From 3602ef87e28a2803531c6f09fff966137eebfd21 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Fri, 10 May 2019 14:22:46 -0600 Subject: [PATCH 0001/1176] generate simple, synthetic data sets of a parametric size --- stdlib/Makefile | 5 + stdlib/docTable.as | 11 + .../examples/produce-exchange/serverActor.as | 35 ++++ .../examples/produce-exchange/serverLang.as | 2 + .../examples/produce-exchange/serverModel.as | 194 +++++++++++++++++- .../examples/produce-exchange/serverTypes.as | 17 ++ .../test/loadWorkloadAndQuery.as | 167 +++++++++++++++ 7 files changed, 428 insertions(+), 3 deletions(-) create mode 100644 stdlib/examples/produce-exchange/test/loadWorkloadAndQuery.as diff --git a/stdlib/Makefile b/stdlib/Makefile index 8ef2e2e7122..421c40620dc 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -19,6 +19,7 @@ TESTS=\ SetDb \ SetDbTest \ ProduceExchange \ + loadWorkloadAndQuery \ producerRemInventory \ retailerReserveMany \ evalBulk \ @@ -160,6 +161,10 @@ $(OUTDIR)/ProduceExchange.out: $(PRODUCE_EXCHANGE_SRC) \ examples/produce-exchange/test/simpleSetupAndQuery.as | $(OUTDIR) $(ASC) -r examples/produce-exchange/serverActor.as examples/produce-exchange/test/simpleSetupAndQuery.as > $@ +$(OUTDIR)/loadWorkloadAndQuery.out: $(PRODUCE_EXCHANGE_SRC) \ + examples/produce-exchange/test/loadWorkloadAndQuery.as | $(OUTDIR) + $(ASC) -r examples/produce-exchange/serverActor.as examples/produce-exchange/test/loadWorkloadAndQuery.as > $@ + $(OUTDIR)/retailerReserveMany.out: $(PRODUCE_EXCHANGE_SRC) \ examples/produce-exchange/test/retailerReserveMany.as | $(OUTDIR) $(ASC) -r examples/produce-exchange/serverActor.as examples/produce-exchange/test/retailerReserveMany.as > $@ diff --git a/stdlib/docTable.as b/stdlib/docTable.as index 407d25aae7b..c66d6a7da41 100644 --- a/stdlib/docTable.as +++ b/stdlib/docTable.as @@ -120,6 +120,17 @@ class DocTable( Table.empty() }; + /** + `reset` + -------- + + Reset the document table back to its initial counter, and empty state. + */ + reset() { + idNext := idFirst; + table := null; + }; + /** `getTable` --------- diff --git a/stdlib/examples/produce-exchange/serverActor.as b/stdlib/examples/produce-exchange/serverActor.as index 4c8b416feca..28a462ed6cf 100644 --- a/stdlib/examples/produce-exchange/serverActor.as +++ b/stdlib/examples/produce-exchange/serverActor.as @@ -11,6 +11,9 @@ let L = (import "serverLang.as"); let Model = (import "serverModel.as"); let Result = (import "../../result.as"); +let List = (import "../../list.as"); +type List = List.List; + type Result = Result.Result; actor server { @@ -1027,6 +1030,38 @@ been processed }; + /** + `loadWorkload` + ---------------- + clear existing server state, and replace with a synthetic workload, based on the given parameters. + */ + + loadWorkload(params:T.WorkloadParams) : async () { + func db(s:Text) = {print "Server::loadWorkload: "; print s; print "\n"}; + + /**- generate add requests for these params: */ + db "generate requests for workload..."; + let addreqs : List = getModel().genAddReqs( + params.day_count, + params.max_route_duration, + params.producer_count, + params.transporter_count, + params.retailer_count, + params.region_count + ); + + /**- reset to initial state before adding this new workload: */ + let reqs : List = + ?(#reset, List.map(addreqs, func (r:L.AddReq):L.Req = #add r)); + + /**- evaluate each request: */ + db "evaluate requests for workload..."; + let resps = getModel().evalReqList(reqs); + + /**- assert that everything worked; a sanity check. */ + // to do + }; + /////////////////////////////////////////////////////////////////////////// // @Omit: diff --git a/stdlib/examples/produce-exchange/serverLang.as b/stdlib/examples/produce-exchange/serverLang.as index a254eb992d7..ee2b0338b7d 100644 --- a/stdlib/examples/produce-exchange/serverLang.as +++ b/stdlib/examples/produce-exchange/serverLang.as @@ -21,6 +21,7 @@ let T = import "serverTypes.as"; - [bulk request](#bulkreq) */ type Req = { + #reset : () ; #add : AddReq ; #update : UpdateReq ; #rem : T.EntId ; @@ -39,6 +40,7 @@ type Req = { - [bulk response](#bulkresp) */ type Resp = { + #reset; #add : T.EntId; #update : (); #rem : (); diff --git a/stdlib/examples/produce-exchange/serverModel.as b/stdlib/examples/produce-exchange/serverModel.as index 75a6308f3d9..679e82a2f05 100644 --- a/stdlib/examples/produce-exchange/serverModel.as +++ b/stdlib/examples/produce-exchange/serverModel.as @@ -28,6 +28,9 @@ let T = (import "serverTypes.as"); let L = (import "serverLang.as"); let M = (import "serverModelTypes.as"); +let List = (import "../../list.as"); +type List = List.List; + let Hash = (import "../../hash.as").BitVec; type Hash = Hash.t; @@ -68,6 +71,7 @@ class Model() { */ + /** `evalReq` ---------- @@ -90,7 +94,36 @@ class Model() { */ evalReq(req:L.Req) : Result { + if false {print "Model::evalReq: "; print (debug_show req); print "\n"; }; switch req { + case (#reset) { + /**- 1. reset each entity table: */ + userTable.reset(); + truckTypeTable.reset(); + regionTable.reset(); + produceTable.reset(); + producerTable.reset(); + inventoryTable.reset(); + transporterTable.reset(); + retailerTable.reset(); + routeTable.reset(); + reservedInventoryTable.reset(); + reservedRouteTable.reset(); + + /**- 2. clear secondary indices: */ + usersByUserName := null; + routesByDstSrcRegions := null; + inventoryByRegion := null; + reservationsByProduceByRegion := null; + + /**- 3. reset counters: */ + joinCount := 0; + retailerQueryCount := 0; + retailerQueryCost := 0; + retailerJoinCount := 0; + + #ok(#reset) + }; case (#add (#truckType info)) Result.fromSomeMap( truckTypeTable.addInfoGetId( func (id_:T.TruckTypeId) : T.TruckTypeInfo = @@ -169,6 +202,22 @@ class Model() { #idErr null ); + case (#add (#retailer info)) Result.fromSomeMap( + retailerTable.addInfoGetId( + func(id_:T.RetailerId):T.RetailerInfo { + shared { + id=id_; + public_key=info.public_key; + short_name=info.short_name; + description=info.description; + region=info.region; + } + } + ), + func (id:T.RetailerId):L.Resp = #add(#retailer(id)), + #idErr null + ); + case (#add (#route info)) Result.mapOk( transporterAddRoute( null, @@ -213,12 +262,19 @@ class Model() { #idErr null ); - case (#add _) P.unreachable(); + //case (#add _) P.unreachable(); case _ P.nyi(); } }; + /** + `evalReqList` + ---------- + */ + evalReqList(reqs:List) : List = + List.map(reqs, evalReq); + /** `evalBulk` ---------- @@ -264,6 +320,138 @@ class Model() { ) }; + /** + `genAddReqs` + ------------- + generate a list of add requests, based on a set of parameters, + and a simple, deterministic strategy, with predictable combinatoric properties. + + Used for seeding unit tests with predictable properties, + and for profiling performance properties of the produce exchange, + e.g., average response time for a retailer query. + */ + genAddReqs( + day_count:Nat, + max_route_duration:Nat, + producer_count:Nat, + transporter_count:Nat, + retailer_count:Nat, + region_count:Nat + ) : List { + assert(region_count > 0); + func min(x:Nat, y:Nat) : Nat = if (x < y) { x } else { y }; + /**- `reqs` accumulates the add requests that we form below: */ + var reqs : List = null; + /**- add truck types; for now, just 2. */ + for (i in range(0, 1)) { + reqs := ?( + #truckType ( + shared { + id=i; short_name=""; description=""; + capacity=i * 50; + isFridge=true; isFreezer=true + } + ), reqs); + }; + /**- add regions */ + for (i in range(0, region_count - 1)) { + reqs := ?(#region (shared { + id=i; short_name=""; description="" + }), reqs); + }; + /**- add produce types, one per region. */ + for (i in range(0, region_count - 1)) { + reqs := ?(#produce (shared { + id=i; short_name=""; description=""; grade=1; + }), reqs); + }; + /**- add producers */ + for (i in range(0, producer_count - 1)) { + reqs := ?(#producer (shared { + id=i; public_key=""; short_name=""; description=""; + region=(i % region_count); + inventory=[]; reserved=[]; + }), reqs); + }; + /**- add transporters */ + for (i in range(0, producer_count - 1)) { + reqs := ?(#transporter (shared { + id=i; public_key=""; short_name=""; description=""; + routes=[]; reserved=[]; + }), reqs); + }; + /**- add retailers */ + for (i in range(0, retailer_count - 1)) { + reqs := ?(#retailer (shared { + id=i; public_key=""; short_name=""; description=""; + region=(i % region_count); + }), reqs); + }; + /**- add routes and inventory, across time and space: */ + for (start_day in range(0, day_count-1)) { + + let max_end_day = + min( start_day + max_route_duration, + day_count - 1 ); + + for (end_day in range(start_day, max_end_day)) { + + /**- consider all pairs of start and end region: */ + for (start_reg in range(0, region_count - 1)) { + for (end_reg in range(0, region_count - 1)) { + + /**- for each producer we choose, + add inventory that will be ready on "start_day", but not beforehand. + It will remain ready until the end of the day count. */ + + for (p in range(0, producer_count)) { + /**- choose this producer iff they are located in the start region: */ + if ((p % region_count) == start_reg) { + reqs := ?(#inventory + (shared { + id=666; + producer = p; + produce = start_reg; + start_date = start_day; + end_date = day_count-1; + quantity = 33; + weight = 66; + ppu = 22; + comments = ""; + }), reqs); + } + }; + + /**- for each transporter we choose, + add a route that will start and end on the current values + of `start_day`, `end_day`, `start_reg`, `end_reg`, respectively: */ + + for (t in range(0, transporter_count - 1)) { + /**- choose this transporter iff their id matches the id of the region, modulo the number of regions: */ + if ((t % region_count) == start_reg) { + reqs := ?(#route + (shared { + id=666; + transporter = t; + start_region = start_reg; + end_region = end_reg; + // there are two truck types; just choose one based on the "produce type", which is based on the region: + truck_type = (start_reg % 2); + start_date = start_day; + end_date = end_day; + // cost is inversely proportional to route duration: slower is cheaper. + // this example cost formula is "linear in duration, with a fixed base cost": + cost = 100 + ((end_day - start_day) * 20); + }), reqs); + } + }; + }; + }; + }; + }; + /**- use "chronological order" for adds above: */ + List.rev(reqs) + }; /** Access control @@ -1562,12 +1750,12 @@ than the MVP goals, however. } }; /** - window start: check that the route begins after the inventory window begins */ - if (item.start_date > route.start_date) { + if (not (item.start_date <= route.start_date)) { debugOff "nope: item start after route start\n"; return false }; /** - window end: check that the route ends before the inventory window ends */ - if (route.end_date > item.end_date) { + if (not (route.end_date <= item.end_date)) { debugOff "nope: route ends after item ends\n"; return false }; diff --git a/stdlib/examples/produce-exchange/serverTypes.as b/stdlib/examples/produce-exchange/serverTypes.as index 6006ffa97d9..42bf659a557 100644 --- a/stdlib/examples/produce-exchange/serverTypes.as +++ b/stdlib/examples/produce-exchange/serverTypes.as @@ -382,3 +382,20 @@ the 2019.03.12 ActorScript Team meeting. */ type QueryAllResults = [QueryAllResult]; + + +/** + Synthetic workloads + ======================= + + The server can generate synthetic workloads given a small set of parameters. + */ + +type WorkloadParams = shared { + day_count:Nat; + max_route_duration:Nat; + producer_count:Nat; + transporter_count:Nat; + retailer_count:Nat; + region_count:Nat; +}; diff --git a/stdlib/examples/produce-exchange/test/loadWorkloadAndQuery.as b/stdlib/examples/produce-exchange/test/loadWorkloadAndQuery.as new file mode 100644 index 00000000000..300a2bb1333 --- /dev/null +++ b/stdlib/examples/produce-exchange/test/loadWorkloadAndQuery.as @@ -0,0 +1,167 @@ +let T = (import "../serverTypes.as"); +//let A = (import "../serverActor.as"); +let Result = (import "../../../result.as"); +let Option = (import "../../../option.as"); + +func scaledParams(region_count_:Nat, factor:Nat) : T.WorkloadParams = shared { + region_count = region_count_:Nat; + day_count = 3:Nat; + max_route_duration = 1:Nat; + producer_count = region_count * factor:Nat; + transporter_count = region_count * factor:Nat; + retailer_count = region_count * factor:Nat; +}; + +///////////////////////////////////////////////////////////////////////////////////// + +actor class Test() = this { + go() { + ignore(async + { + // Vary the choice of region count and scaling factor here: + let params = { + scaledParams(2, 2); // (40, 40 ), loads in 0.7s in my AS intepreter + //scaledParams(5, 5); // (625 , 625 ), loads in 8.8s in my AS interpreter + //scaledParams(8, 10); // (3_200, 3_200), loads in 1:07min in my AS interpreter + //scaledParams(10, 10); // (5_000, 5_000), loads in 2:13min in my AS interpreter + }; + + ///////////////////////////////////////////////////////////////////////////////////// + let s = server; + + print "\nExchange setup: Begin...\n====================================\n"; + await s.loadWorkload(params); + + if false { + print "\nRetailer queries\n====================================\n"; + // do a query for each retailer: + for (r in range(0, params.retailer_count)) { + await retailerQueryAll("", r) + }; + }; + + print "\nQuery counts\n----------------\n"; + let counts = await s.getCounts(); + + printEntityCount("Retailer join", counts.retailer_join_count); + printEntityCount("Retailer query", counts.retailer_query_count); + printLabeledCost("Retailer query", counts.retailer_query_cost); + + print "\nDump all\n====================================\n"; + print (debug_show (await s.getCounts())); + if false { + await debugDumpAll() + } + }) + }; +}; + + +//func retailerQueryAll(server:A.Server, pk:Text, r:?T.UserId) : async () { +func retailerQueryAll(pk:Text, retailerId:T.RetailerId) : async () { + + print "\nRetailer "; + printInt retailerId; + print " sends `retailerQueryAll`\n"; + print "------------------------------------\n"; + + print "\n## Query begin:\n"; + let res = Result.assertUnwrapAny( + await server.retailerQueryAll(pk, retailerId, null, null) + ); + print "\n## Query end."; + + print "\n## Query results ("; + printInt (res.len()); + print ")\n"; + for (info in res.vals()) { + print "- "; + print (debug_show info); + print "\n"; + } +}; + +//func debugDumpAll(server:A.Server) : async () { +func debugDumpAll() : async () { + + print "\nTruck type info\n----------------\n"; + for ( info in ((await server.allTruckTypeInfo()).vals()) ) { + print "- "; + print (debug_show info); + print "\n"; + }; + + print "\nRegion info\n----------------\n"; + for ( info in ((await server.allRegionInfo()).vals()) ) { + print "- "; + print (debug_show info); + print "\n"; + }; + + print "\nProduce info\n----------------\n"; + for ( info in ((await server.allProduceInfo()).vals()) ) { + print "- "; + print (debug_show info); + print "\n"; + }; + + print "\nProducer info\n----------------\n"; + for ( info in ((await server.allProducerInfo()).vals()) ) { + print "- "; + print (debug_show info); + print "\n"; + }; + + print "\nTransporter info\n----------------\n"; + for ( info in ((await server.allTransporterInfo()).vals()) ) { + print "- "; + print (debug_show info); + print "\n"; + }; + + print "\nRetailer info\n----------------\n"; + for ( info in ((await server.allRetailerInfo()).vals()) ) { + print "- "; + print (debug_show info); + print "\n"; + }; + + { print "\nInventory info\n----------------\n"; + let items = await server.allInventoryInfo(); + print "total count of "; + printInt (items.len()); + print ":\n"; + for ( info in items.vals() ) { + print "- "; + print (debug_show info); + print "\n"; + }; + }; + + { print "\nRoute info\n----------------\n"; + let routes = await server.allRouteInfo(); + print "total count of "; + printInt (routes.len()); + print ":\n"; + for ( info in (routes.vals()) ) { + print "- "; + print (debug_show info); + print "\n"; + }; + }; +}; + +func printEntityCount(entname:Text, count:Nat) { + print ("- " # entname # " count: "); + printInt count; + print "\n"; +}; + +func printLabeledCost(lab:Text, cost:Nat) { + print ("- " # lab # " cost: "); + printInt cost; + print "\n"; +}; + +let test = Test(); +test.go() From d4e82c363da5d5b75a923ce7c22f430dbd1db7f5 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Fri, 10 May 2019 14:59:29 -0600 Subject: [PATCH 0002/1176] minor: clarifying comment --- stdlib/examples/produce-exchange/test/loadWorkloadAndQuery.as | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stdlib/examples/produce-exchange/test/loadWorkloadAndQuery.as b/stdlib/examples/produce-exchange/test/loadWorkloadAndQuery.as index 300a2bb1333..06466cff50c 100644 --- a/stdlib/examples/produce-exchange/test/loadWorkloadAndQuery.as +++ b/stdlib/examples/produce-exchange/test/loadWorkloadAndQuery.as @@ -18,7 +18,8 @@ actor class Test() = this { go() { ignore(async { - // Vary the choice of region count and scaling factor here: + // Vary the choice of region count and scaling factor here; + // Each choice leads to a different count of (InventoryCount, RouteCount), and load time: let params = { scaledParams(2, 2); // (40, 40 ), loads in 0.7s in my AS intepreter //scaledParams(5, 5); // (625 , 625 ), loads in 8.8s in my AS interpreter From 2987784be4d7fdc6374aa59b7670232d3b8e5489 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Tue, 14 May 2019 08:28:38 -0400 Subject: [PATCH 0003/1176] profiling support collects CSV files with source region counters --- src/flags.ml | 3 + src/interpret.ml | 5 + src/interpret.mli | 2 + src/interpret_ir.ml | 6 +- src/interpret_ir.mli | 2 + src/main.ml | 3 + src/pipeline.ml | 9 +- src/source.ml | 58 +++++++ src/source.mli | 7 + stdlib/Makefile | 25 ++- .../examples/produce-exchange/serverActor.as | 2 +- .../test/loadWorkloadAndQuery.as | 162 ++---------------- stdlib/hash.as | 8 +- stdlib/trie.as | 1 + 14 files changed, 134 insertions(+), 159 deletions(-) diff --git a/src/flags.ml b/src/flags.ml index 8e7f21fea90..95e6272d4a6 100644 --- a/src/flags.ml +++ b/src/flags.ml @@ -10,3 +10,6 @@ let interpret_ir = ref false let source_map = ref false let prelude = ref true let link = ref true +let profile = ref false +let profile_file = ref "profiling-counters.csv" +let profile_line_prefix = ref "" diff --git a/src/interpret.ml b/src/interpret.ml index 4bafb9875b9..b768c7b43a3 100644 --- a/src/interpret.ml +++ b/src/interpret.ml @@ -75,6 +75,7 @@ let string_of_arg = function let last_env = ref (env_of_scope empty_scope) let last_region = ref Source.no_region +let region_counters : Counters.t = Counters.zeros () let print_exn exn = Printf.printf "%!"; @@ -246,6 +247,7 @@ let rec interpret_exp env exp (k : V.value V.cont) = and interpret_exp_mut env exp (k : V.value V.cont) = last_region := exp.at; last_env := env; + Counters.bump region_counters exp.at ; match exp.it with | PrimE s -> k (V.Func (V.call_conv_of_typ exp.note.note_typ, Prelude.prim s)) @@ -737,3 +739,6 @@ let interpret_library scope (filename, p) : scope = in library_scope filename v scope + +let dump_profile () = + Counters.dump region_counters diff --git a/src/interpret.mli b/src/interpret.mli index 6f18c5d3859..c1b97597e76 100644 --- a/src/interpret.mli +++ b/src/interpret.mli @@ -13,3 +13,5 @@ exception Trap of Source.region * string val interpret_prog : scope -> Syntax.prog -> (V.value * scope) option val interpret_library : scope -> Syntax.library -> scope + +val dump_profile : unit -> unit diff --git a/src/interpret_ir.ml b/src/interpret_ir.ml index 85f2d7b860a..b53a002f74a 100644 --- a/src/interpret_ir.ml +++ b/src/interpret_ir.ml @@ -4,7 +4,6 @@ open Source module V = Value module T = Type - (* Context *) type val_env = V.def V.Env.t @@ -62,6 +61,7 @@ let string_of_arg = function let last_env = ref (env_of_scope empty_scope) let last_region = ref Source.no_region +let region_counters : Counters.t = Counters.zeros () let print_exn exn = Printf.printf "%!"; @@ -263,6 +263,7 @@ let rec interpret_exp env exp (k : V.value V.cont) = and interpret_exp_mut env exp (k : V.value V.cont) = last_region := exp.at; last_env := env; + Counters.bump region_counters exp.at ; match exp.it with | PrimE s -> let at = exp.at in @@ -661,3 +662,6 @@ let interpret_prog scope ((ds, exp), _flavor) : scope = !ve with exn -> print_exn exn; !ve + +let dump_profile () = + Counters.dump region_counters diff --git a/src/interpret_ir.mli b/src/interpret_ir.mli index 4dea591faaa..04034507076 100644 --- a/src/interpret_ir.mli +++ b/src/interpret_ir.mli @@ -9,3 +9,5 @@ val adjoin_scope : scope -> scope -> scope exception Trap of Source.region * string val interpret_prog : scope -> Ir.prog -> scope + +val dump_profile : unit -> unit diff --git a/src/main.ml b/src/main.ml index d586f6b8afd..ca459dfd660 100644 --- a/src/main.ml +++ b/src/main.ml @@ -41,6 +41,9 @@ let argspec = Arg.align "--map", Arg.Set Flags.source_map, " output source map"; "-t", Arg.Set Flags.trace, " activate tracing"; + "--profile", Arg.Set Flags.profile, " activate profiling counters in interpreters "; + "--profile-file", Arg.Set_string Flags.profile_file, " set profiling output file "; + "--profile-line-prefix", Arg.Set_string Flags.profile_line_prefix, " prefix each profile line with the given string "; "-iR", Arg.Set Flags.interpret_ir, " interpret the lowered code"; "-no-await", Arg.Clear Flags.await_lowering, " no await-lowering (with -iR)"; "-no-async", Arg.Clear Flags.async_lowering, " no async-lowering (with -iR)"; diff --git a/src/pipeline.ml b/src/pipeline.ml index 762e29ac59b..cf7ceb5d8c2 100644 --- a/src/pipeline.ml +++ b/src/pipeline.ml @@ -235,7 +235,8 @@ let load_decl parse_one senv : load_decl_result = let interpret_prog denv prog : (Value.value * Interpret.scope) option = phase "Interpreting" prog.Source.note; - Interpret.interpret_prog denv prog + let result = Interpret.interpret_prog denv prog in + result let rec interpret_libraries denv libraries : Interpret.scope = match libraries with @@ -316,8 +317,9 @@ let check_string s name : check_result = (* Running *) let run_files files : unit Diag.result = - Diag.ignore (interpret_files initial_env files) - + let result = Diag.ignore (interpret_files initial_env files) in + Interpret.dump_profile () ; + result (* Interactively *) @@ -499,6 +501,7 @@ let interpret_ir_prog inp_env libraries progs = let dscope = Interpret_ir.interpret_prog denv0 prelude_ir in let denv1 = Interpret_ir.adjoin_scope denv0 dscope in let _ = Interpret_ir.interpret_prog denv1 prog_ir in + let _ = Interpret_ir.dump_profile () in () let interpret_ir_files files = diff --git a/src/source.ml b/src/source.ml index bc54030ea07..b77bb2eb3cd 100644 --- a/src/source.ml +++ b/src/source.ml @@ -22,3 +22,61 @@ let string_of_region r = if r.left.file = "" then "(unknown location)" else r.left.file ^ ":" ^ string_of_pos r.left ^ (if r.right = r.left then "" else "-" ^ string_of_pos r.right) + + +(** Counters for regions, for super-simple profiling support. *) +module Counters = struct + type t = (region, int) Hashtbl.t + + let dump_count = ref 0 + + let zeros () = + Hashtbl.create 100 + + let bump c reg = + if !Flags.profile then + match Hashtbl.find_opt c reg with + Some n -> Hashtbl.replace c reg (n + 1) + | None -> Hashtbl.replace c reg 1 + + (* lexicographic on (left.file, left.line, left.column, right.line, right.column) *) + let region_order rega regb = + if rega.left.file = regb.left.file then + if rega.left.line = regb.left.line then + if rega.left.column = regb.left.column then + if rega.right.line = regb.right.line then + compare rega.right.column regb.right.column + else + compare rega.right.line regb.right.line + else + compare rega.left.column regb.left.column + else + compare rega.left.line regb.left.line + else + compare rega.left.file regb.left.file + + let dump c = + if !Flags.profile then + let dump_count = begin + let d = !dump_count in + dump_count := d + 1; + d + end + in + let counts = Hashtbl.fold (fun region count counts -> (region, count) :: counts) c [] in + let counts = List.sort (fun (rega, x) (regb, y) -> + let diff = x - y in + if diff <> 0 then -diff else + region_order rega regb + ) counts + in + let file = open_out (!Flags.profile_file) in + List.iter (fun (region, region_count) -> + assert (dump_count = 0); + Printf.fprintf file "%s\"%s\", %d\n" + (!Flags.profile_line_prefix) + (string_of_region region) + region_count + ) counts; + close_out file +end diff --git a/src/source.mli b/src/source.mli index df5e731afe6..ace4dd31eb9 100644 --- a/src/source.mli +++ b/src/source.mli @@ -12,3 +12,10 @@ val string_of_region : region -> string val span : region -> region -> region val (@@) : 'a -> region -> 'a phrase + +module Counters : sig + type t + val zeros : unit -> t + val bump : t -> region -> unit + val dump : t -> unit +end diff --git a/stdlib/Makefile b/stdlib/Makefile index 421c40620dc..3bebb31de60 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -19,14 +19,15 @@ TESTS=\ SetDb \ SetDbTest \ ProduceExchange \ - loadWorkloadAndQuery \ producerRemInventory \ retailerReserveMany \ evalBulk \ WASM=\ - ProduceExchange + ProduceExchange\ + loadWorkloadAndQueryBig\ + OUTFILES=$(addsuffix .out, $(TESTS)) $(addsuffix .wasm, $(WASM)) @@ -161,9 +162,25 @@ $(OUTDIR)/ProduceExchange.out: $(PRODUCE_EXCHANGE_SRC) \ examples/produce-exchange/test/simpleSetupAndQuery.as | $(OUTDIR) $(ASC) -r examples/produce-exchange/serverActor.as examples/produce-exchange/test/simpleSetupAndQuery.as > $@ -$(OUTDIR)/loadWorkloadAndQuery.out: $(PRODUCE_EXCHANGE_SRC) \ +PROFILE_SRC=\ + examples/produce-exchange/serverActor.as \ + examples/produce-exchange/test/loadWorkloadAndQuery.Common.as + +$(OUTDIR)/loadWorkloadAndQuery.profile.4-5-5.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_SRC) | $(OUTDIR) + $(ASC) -r --profile examples/produce-exchange/test/params-5-5.as $(PROFILE_SRC) --profile-file $@ --profile-line-prefix "4, 5, 5, " + +$(OUTDIR)/loadWorkloadAndQuery.profile.4-5-10.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_SRC) | $(OUTDIR) + $(ASC) -r --profile examples/produce-exchange/test/params-5-10.as $(PROFILE_SRC) --profile-file $@ --profile-line-prefix "4, 5, 10, " + +$(OUTDIR)/loadWorkloadAndQuery.profile.4-5-20.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_SRC) | $(OUTDIR) + $(ASC) -r --profile examples/produce-exchange/test/params-5-20.as $(PROFILE_SRC) --profile-file $@ --profile-line-prefix "4, 5, 20, " + +$(OUTDIR)/loadWorkloadAndQuery.profile.4-5-50.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_SRC) | $(OUTDIR) + $(ASC) -r --profile examples/produce-exchange/test/params-5-50.as $(PROFILE_SRC) --profile-file $@ --profile-line-prefix "4, 5, 50, " + +$(OUTDIR)/loadWorkloadAndQueryBig.wasm: $(PRODUCE_EXCHANGE_SRC) \ examples/produce-exchange/test/loadWorkloadAndQuery.as | $(OUTDIR) - $(ASC) -r examples/produce-exchange/serverActor.as examples/produce-exchange/test/loadWorkloadAndQuery.as > $@ + $(ASC) examples/produce-exchange/serverActor.as examples/produce-exchange/test/loadWorkloadAndQueryBig.as -c --dfinity -o $@ $(OUTDIR)/retailerReserveMany.out: $(PRODUCE_EXCHANGE_SRC) \ examples/produce-exchange/test/retailerReserveMany.as | $(OUTDIR) diff --git a/stdlib/examples/produce-exchange/serverActor.as b/stdlib/examples/produce-exchange/serverActor.as index 28a462ed6cf..ea4d4775851 100644 --- a/stdlib/examples/produce-exchange/serverActor.as +++ b/stdlib/examples/produce-exchange/serverActor.as @@ -1037,7 +1037,7 @@ been processed */ loadWorkload(params:T.WorkloadParams) : async () { - func db(s:Text) = {print "Server::loadWorkload: "; print s; print "\n"}; + func db(s:Text) = if false {print "Server::loadWorkload: "; print s; print "\n"}; /**- generate add requests for these params: */ db "generate requests for workload..."; diff --git a/stdlib/examples/produce-exchange/test/loadWorkloadAndQuery.as b/stdlib/examples/produce-exchange/test/loadWorkloadAndQuery.as index 06466cff50c..388c8f33a5c 100644 --- a/stdlib/examples/produce-exchange/test/loadWorkloadAndQuery.as +++ b/stdlib/examples/produce-exchange/test/loadWorkloadAndQuery.as @@ -1,19 +1,17 @@ -let T = (import "../serverTypes.as"); -//let A = (import "../serverActor.as"); -let Result = (import "../../../result.as"); -let Option = (import "../../../option.as"); - -func scaledParams(region_count_:Nat, factor:Nat) : T.WorkloadParams = shared { - region_count = region_count_:Nat; - day_count = 3:Nat; - max_route_duration = 1:Nat; - producer_count = region_count * factor:Nat; - transporter_count = region_count * factor:Nat; - retailer_count = region_count * factor:Nat; +func scaledParams(region_count_:Nat, factor:Nat) : T.WorkloadParams = { + print "## region_count = "; printInt region_count_; print "\n"; + print "## factor = "; printInt factor; print "\n"; + print "## data format: source-region, evaluation-count:\n"; + shared { + region_count = region_count_:Nat; + day_count = 3:Nat; + max_route_duration = 1:Nat; + producer_count = region_count * factor:Nat; + transporter_count = region_count * factor:Nat; + retailer_count = region_count * factor:Nat; + } }; -///////////////////////////////////////////////////////////////////////////////////// - actor class Test() = this { go() { ignore(async @@ -21,148 +19,18 @@ actor class Test() = this { // Vary the choice of region count and scaling factor here; // Each choice leads to a different count of (InventoryCount, RouteCount), and load time: let params = { - scaledParams(2, 2); // (40, 40 ), loads in 0.7s in my AS intepreter + //scaledParams(2, 2); // (40, 40 ), loads in 0.7s in my AS intepreter //scaledParams(5, 5); // (625 , 625 ), loads in 8.8s in my AS interpreter //scaledParams(8, 10); // (3_200, 3_200), loads in 1:07min in my AS interpreter //scaledParams(10, 10); // (5_000, 5_000), loads in 2:13min in my AS interpreter - }; - ///////////////////////////////////////////////////////////////////////////////////// + scaledParams(5, 2); + }; let s = server; - - print "\nExchange setup: Begin...\n====================================\n"; await s.loadWorkload(params); - - if false { - print "\nRetailer queries\n====================================\n"; - // do a query for each retailer: - for (r in range(0, params.retailer_count)) { - await retailerQueryAll("", r) - }; - }; - - print "\nQuery counts\n----------------\n"; - let counts = await s.getCounts(); - - printEntityCount("Retailer join", counts.retailer_join_count); - printEntityCount("Retailer query", counts.retailer_query_count); - printLabeledCost("Retailer query", counts.retailer_query_cost); - - print "\nDump all\n====================================\n"; - print (debug_show (await s.getCounts())); - if false { - await debugDumpAll() - } }) }; }; - -//func retailerQueryAll(server:A.Server, pk:Text, r:?T.UserId) : async () { -func retailerQueryAll(pk:Text, retailerId:T.RetailerId) : async () { - - print "\nRetailer "; - printInt retailerId; - print " sends `retailerQueryAll`\n"; - print "------------------------------------\n"; - - print "\n## Query begin:\n"; - let res = Result.assertUnwrapAny( - await server.retailerQueryAll(pk, retailerId, null, null) - ); - print "\n## Query end."; - - print "\n## Query results ("; - printInt (res.len()); - print ")\n"; - for (info in res.vals()) { - print "- "; - print (debug_show info); - print "\n"; - } -}; - -//func debugDumpAll(server:A.Server) : async () { -func debugDumpAll() : async () { - - print "\nTruck type info\n----------------\n"; - for ( info in ((await server.allTruckTypeInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; - }; - - print "\nRegion info\n----------------\n"; - for ( info in ((await server.allRegionInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; - }; - - print "\nProduce info\n----------------\n"; - for ( info in ((await server.allProduceInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; - }; - - print "\nProducer info\n----------------\n"; - for ( info in ((await server.allProducerInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; - }; - - print "\nTransporter info\n----------------\n"; - for ( info in ((await server.allTransporterInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; - }; - - print "\nRetailer info\n----------------\n"; - for ( info in ((await server.allRetailerInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; - }; - - { print "\nInventory info\n----------------\n"; - let items = await server.allInventoryInfo(); - print "total count of "; - printInt (items.len()); - print ":\n"; - for ( info in items.vals() ) { - print "- "; - print (debug_show info); - print "\n"; - }; - }; - - { print "\nRoute info\n----------------\n"; - let routes = await server.allRouteInfo(); - print "total count of "; - printInt (routes.len()); - print ":\n"; - for ( info in (routes.vals()) ) { - print "- "; - print (debug_show info); - print "\n"; - }; - }; -}; - -func printEntityCount(entname:Text, count:Nat) { - print ("- " # entname # " count: "); - printInt count; - print "\n"; -}; - -func printLabeledCost(lab:Text, cost:Nat) { - print ("- " # lab # " cost: "); - printInt cost; - print "\n"; -}; - let test = Test(); test.go() diff --git a/stdlib/hash.as b/stdlib/hash.as index d0e37a53bff..4356fb63434 100644 --- a/stdlib/hash.as +++ b/stdlib/hash.as @@ -68,11 +68,13 @@ module BitVec { return x }; - /** Test if two lists of bits are equal. */ + /** Project a given bit from the bit vector. */ func getHashBit(h:BitVec, pos:Nat) : Bool { assert (pos <= length()); - if ((h & (natToWord32(1) << natToWord32(pos))) != natToWord32(0)) { true } - else { false } + if ((h & (natToWord32(1) << natToWord32(pos))) != natToWord32(0)) + { true } + else + { false } }; /** Test if two lists of bits are equal. */ diff --git a/stdlib/trie.as b/stdlib/trie.as index 059b64247d4..45fe8d6e8ab 100644 --- a/stdlib/trie.as +++ b/stdlib/trie.as @@ -70,6 +70,7 @@ let AssocList = import "assocList.as"; type AssocList = AssocList.AssocList; let HASH_BITS = 4; +//let HASH_BITS = 16; type Key = { // hash field: permits fast inequality checks, permits collisions; From 23c03caa6d3e70e7b5b91c036c8fd8a90a811776 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Tue, 14 May 2019 08:28:57 -0400 Subject: [PATCH 0004/1176] profiling support collects CSV files with source region counters --- .../test/loadWorkloadAndQuery.Common.as | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 stdlib/examples/produce-exchange/test/loadWorkloadAndQuery.Common.as diff --git a/stdlib/examples/produce-exchange/test/loadWorkloadAndQuery.Common.as b/stdlib/examples/produce-exchange/test/loadWorkloadAndQuery.Common.as new file mode 100644 index 00000000000..05c28d8cd96 --- /dev/null +++ b/stdlib/examples/produce-exchange/test/loadWorkloadAndQuery.Common.as @@ -0,0 +1,15 @@ +func scaledParams(region_count_:Nat, factor:Nat) : T.WorkloadParams = { + shared { + region_count = region_count_:Nat; + day_count = 3:Nat; + max_route_duration = 1:Nat; + producer_count = region_count * factor:Nat; + transporter_count = region_count * factor:Nat; + retailer_count = region_count * factor:Nat; + } +}; +async { +let _ = server.loadWorkload(scaledParams(region_count, scale_factor)); +let c = (await server.getCounts()); +print (debug_show c); +}; \ No newline at end of file From 9d913dfdc5af69b7d982b9deccb91e8135e813a3 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Tue, 14 May 2019 08:29:13 -0400 Subject: [PATCH 0005/1176] profiling support collects CSV files with source region counters --- .../test/loadWorkloadAndQueryBig.as | 168 ++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 stdlib/examples/produce-exchange/test/loadWorkloadAndQueryBig.as diff --git a/stdlib/examples/produce-exchange/test/loadWorkloadAndQueryBig.as b/stdlib/examples/produce-exchange/test/loadWorkloadAndQueryBig.as new file mode 100644 index 00000000000..852721c2a58 --- /dev/null +++ b/stdlib/examples/produce-exchange/test/loadWorkloadAndQueryBig.as @@ -0,0 +1,168 @@ +//let T = (import "../serverTypes.as"); +//let A = (import "../serverActor.as"); +//let Result = (import "../../../result.as"); +//let Option = (import "../../../option.as"); + +func scaledParams(region_count_:Nat, factor:Nat) : T.WorkloadParams = shared { + region_count = region_count_:Nat; + day_count = 3:Nat; + max_route_duration = 1:Nat; + producer_count = region_count * factor:Nat; + transporter_count = region_count * factor:Nat; + retailer_count = region_count * factor:Nat; +}; + +///////////////////////////////////////////////////////////////////////////////////// + +actor class Test() = this { + go() { + ignore(async + { + // Vary the choice of region count and scaling factor here; + // Each choice leads to a different count of (InventoryCount, RouteCount), and load time: + let params = { + //scaledParams(2, 2); // (40, 40 ), loads in 0.7s in my AS intepreter + //scaledParams(5, 5); // (625 , 625 ), loads in 8.8s in my AS interpreter + scaledParams(8, 10); // (3_200, 3_200), loads in 1:07min in my AS interpreter + //scaledParams(10, 10); // (5_000, 5_000), loads in 2:13min in my AS interpreter + }; + + ///////////////////////////////////////////////////////////////////////////////////// + let s = server; + + print "\nExchange setup: Begin...\n====================================\n"; + await s.loadWorkload(params); + + if false { + print "\nRetailer queries\n====================================\n"; + // do a query for each retailer: + for (r in range(0, params.retailer_count)) { + await retailerQueryAll("", r) + }; + }; + + print "\nQuery counts\n----------------\n"; + let counts = await s.getCounts(); + + printEntityCount("Retailer join", counts.retailer_join_count); + printEntityCount("Retailer query", counts.retailer_query_count); + printLabeledCost("Retailer query", counts.retailer_query_cost); + + print "\nDump all\n====================================\n"; + print (debug_show (await s.getCounts())); + if false { + await debugDumpAll() + } + }) + }; +}; + + +//func retailerQueryAll(server:A.Server, pk:Text, r:?T.UserId) : async () { +func retailerQueryAll(pk:Text, retailerId:T.RetailerId) : async () { + + print "\nRetailer "; + printInt retailerId; + print " sends `retailerQueryAll`\n"; + print "------------------------------------\n"; + + print "\n## Query begin:\n"; + let res = Result.assertUnwrapAny( + await server.retailerQueryAll(pk, retailerId, null, null) + ); + print "\n## Query end."; + + print "\n## Query results ("; + printInt (res.len()); + print ")\n"; + for (info in res.vals()) { + print "- "; + print (debug_show info); + print "\n"; + } +}; + +//func debugDumpAll(server:A.Server) : async () { +func debugDumpAll() : async () { + + print "\nTruck type info\n----------------\n"; + for ( info in ((await server.allTruckTypeInfo()).vals()) ) { + print "- "; + print (debug_show info); + print "\n"; + }; + + print "\nRegion info\n----------------\n"; + for ( info in ((await server.allRegionInfo()).vals()) ) { + print "- "; + print (debug_show info); + print "\n"; + }; + + print "\nProduce info\n----------------\n"; + for ( info in ((await server.allProduceInfo()).vals()) ) { + print "- "; + print (debug_show info); + print "\n"; + }; + + print "\nProducer info\n----------------\n"; + for ( info in ((await server.allProducerInfo()).vals()) ) { + print "- "; + print (debug_show info); + print "\n"; + }; + + print "\nTransporter info\n----------------\n"; + for ( info in ((await server.allTransporterInfo()).vals()) ) { + print "- "; + print (debug_show info); + print "\n"; + }; + + print "\nRetailer info\n----------------\n"; + for ( info in ((await server.allRetailerInfo()).vals()) ) { + print "- "; + print (debug_show info); + print "\n"; + }; + + { print "\nInventory info\n----------------\n"; + let items = await server.allInventoryInfo(); + print "total count of "; + printInt (items.len()); + print ":\n"; + for ( info in items.vals() ) { + print "- "; + print (debug_show info); + print "\n"; + }; + }; + + { print "\nRoute info\n----------------\n"; + let routes = await server.allRouteInfo(); + print "total count of "; + printInt (routes.len()); + print ":\n"; + for ( info in (routes.vals()) ) { + print "- "; + print (debug_show info); + print "\n"; + }; + }; +}; + +func printEntityCount(entname:Text, count:Nat) { + print ("- " # entname # " count: "); + printInt count; + print "\n"; +}; + +func printLabeledCost(lab:Text, cost:Nat) { + print ("- " # lab # " cost: "); + printInt cost; + print "\n"; +}; + +let test = Test(); +test.go() From 8830fb8579ae1fb0948940fa766ed9b61b2a7390 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Tue, 14 May 2019 08:29:24 -0400 Subject: [PATCH 0006/1176] profiling support collects CSV files with source region counters --- stdlib/examples/produce-exchange/test/params-5-10.as | 3 +++ stdlib/examples/produce-exchange/test/params-5-20.as | 3 +++ stdlib/examples/produce-exchange/test/params-5-5.as | 3 +++ stdlib/examples/produce-exchange/test/params-5-50.as | 3 +++ 4 files changed, 12 insertions(+) create mode 100644 stdlib/examples/produce-exchange/test/params-5-10.as create mode 100644 stdlib/examples/produce-exchange/test/params-5-20.as create mode 100644 stdlib/examples/produce-exchange/test/params-5-5.as create mode 100644 stdlib/examples/produce-exchange/test/params-5-50.as diff --git a/stdlib/examples/produce-exchange/test/params-5-10.as b/stdlib/examples/produce-exchange/test/params-5-10.as new file mode 100644 index 00000000000..3860a6cf423 --- /dev/null +++ b/stdlib/examples/produce-exchange/test/params-5-10.as @@ -0,0 +1,3 @@ +let region_count = 5; +let scale_factor = 10; + diff --git a/stdlib/examples/produce-exchange/test/params-5-20.as b/stdlib/examples/produce-exchange/test/params-5-20.as new file mode 100644 index 00000000000..74b1386fdae --- /dev/null +++ b/stdlib/examples/produce-exchange/test/params-5-20.as @@ -0,0 +1,3 @@ +let region_count = 5; +let scale_factor = 20; + diff --git a/stdlib/examples/produce-exchange/test/params-5-5.as b/stdlib/examples/produce-exchange/test/params-5-5.as new file mode 100644 index 00000000000..268b0ed8552 --- /dev/null +++ b/stdlib/examples/produce-exchange/test/params-5-5.as @@ -0,0 +1,3 @@ +let region_count = 5; +let scale_factor = 5; + diff --git a/stdlib/examples/produce-exchange/test/params-5-50.as b/stdlib/examples/produce-exchange/test/params-5-50.as new file mode 100644 index 00000000000..ad74710a24e --- /dev/null +++ b/stdlib/examples/produce-exchange/test/params-5-50.as @@ -0,0 +1,3 @@ +let region_count = 5; +let scale_factor = 50; + From ed49fc10f1decf8885166c4b4314a1b77ef74223 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Wed, 15 May 2019 13:45:55 -0400 Subject: [PATCH 0007/1176] profile csv file includes program-specific counts, given by CLI args --- src/counters.ml | 84 +++++++++++++++++++ src/flags.ml | 2 + src/interpret.ml | 4 +- src/interpret.mli | 2 +- src/interpret_ir.ml | 4 - src/interpret_ir.mli | 1 - src/main.ml | 3 + src/pipeline.ml | 21 ++++- src/source.ml | 58 ------------- src/source.mli | 7 -- stdlib/Makefile | 41 ++++++--- .../examples/produce-exchange/serverActor.as | 3 + .../examples/produce-exchange/serverTypes.as | 1 + .../produce-exchange/test/params-5-1.as | 3 + .../produce-exchange/test/params-5-100.as | 3 + ...kloadAndQuery.Common.as => profileLoad.as} | 5 +- 16 files changed, 151 insertions(+), 91 deletions(-) create mode 100644 src/counters.ml create mode 100644 stdlib/examples/produce-exchange/test/params-5-1.as create mode 100644 stdlib/examples/produce-exchange/test/params-5-100.as rename stdlib/examples/produce-exchange/test/{loadWorkloadAndQuery.Common.as => profileLoad.as} (86%) diff --git a/src/counters.ml b/src/counters.ml new file mode 100644 index 00000000000..db4ff7b94c3 --- /dev/null +++ b/src/counters.ml @@ -0,0 +1,84 @@ +(** + +Counters for regions, for super-simple profiling support. + +Useful for debugging combinatoric algorithms +or other algorithms with known complexity, +such as search, sorting, etc. + +*) + +open Source + +type t = (region, int) Hashtbl.t + +let dump_count = ref 0 + +let zeros () = + Hashtbl.create 100 + +let bump c reg = + if !Flags.profile then + match Hashtbl.find_opt c reg with + Some n -> Hashtbl.replace c reg (n + 1) + | None -> Hashtbl.replace c reg 1 + +(* lexicographic on (left.file, left.line, left.column, right.line, right.column) *) +let region_order rega regb = + if rega.left.file = regb.left.file then + if rega.left.line = regb.left.line then + if rega.left.column = regb.left.column then + if rega.right.line = regb.right.line then + compare rega.right.column regb.right.column + else + compare rega.right.line regb.right.line + else + compare rega.left.column regb.left.column + else + compare rega.left.line regb.left.line + else + compare rega.left.file regb.left.file + +let dump (c:t) (ve: Value.value Value.Env.t) = + if !Flags.profile then + if !Flags.profile_verbose then ( + Printf.printf "{\n" ; + Value.Env.iter (fun fn fv -> + Printf.printf " %s = %s;\n" + fn (Value.string_of_val fv) + ) + ve ; + Printf.printf "}\n" + ) ; + let dump_count = begin + let d = !dump_count in + dump_count := d + 1; + d + end + in + let counts = Hashtbl.fold (fun region count counts -> (region, count) :: counts) c [] in + let counts = List.sort (fun (rega, x) (regb, y) -> + let diff = x - y in + if diff <> 0 then -diff else + region_order rega regb + ) counts + in + let file = open_out (!Flags.profile_file) in + let suffix = + (* the suffix of the line consists of field values for each field in `profile_field_names`: *) + List.fold_right + (fun var line -> + match Value.Env.find_opt var ve with + None -> Printf.sprintf "%s, #err(\"undefined field `%s`\")" line var + | Some v -> Printf.sprintf "%s, %s" line (Value.string_of_val v) + ) !Flags.profile_field_names "" + in + List.iter (fun (region, region_count) -> + assert (dump_count = 0); + Printf.fprintf file "%s\"%s\", %d%s\n" + (!Flags.profile_line_prefix) + (string_of_region region) + region_count + suffix + ) counts; + close_out file diff --git a/src/flags.ml b/src/flags.ml index 95e6272d4a6..a37fb5f5a3e 100644 --- a/src/flags.ml +++ b/src/flags.ml @@ -11,5 +11,7 @@ let source_map = ref false let prelude = ref true let link = ref true let profile = ref false +let profile_verbose = ref false let profile_file = ref "profiling-counters.csv" let profile_line_prefix = ref "" +let profile_field_names : (string list) ref = ref [] diff --git a/src/interpret.ml b/src/interpret.ml index b768c7b43a3..18390d07d47 100644 --- a/src/interpret.ml +++ b/src/interpret.ml @@ -740,5 +740,5 @@ let interpret_library scope (filename, p) : scope = library_scope filename v scope -let dump_profile () = - Counters.dump region_counters +let dump_profile (results: Value.value Value.Env.t) = + Counters.dump region_counters results diff --git a/src/interpret.mli b/src/interpret.mli index c1b97597e76..9c58b254b8b 100644 --- a/src/interpret.mli +++ b/src/interpret.mli @@ -14,4 +14,4 @@ exception Trap of Source.region * string val interpret_prog : scope -> Syntax.prog -> (V.value * scope) option val interpret_library : scope -> Syntax.library -> scope -val dump_profile : unit -> unit +val dump_profile : V.value V.Env.t -> unit diff --git a/src/interpret_ir.ml b/src/interpret_ir.ml index b53a002f74a..5f7972676a5 100644 --- a/src/interpret_ir.ml +++ b/src/interpret_ir.ml @@ -661,7 +661,3 @@ let interpret_prog scope ((ds, exp), _flavor) : scope = Scheduler.run (); !ve with exn -> print_exn exn; !ve - - -let dump_profile () = - Counters.dump region_counters diff --git a/src/interpret_ir.mli b/src/interpret_ir.mli index 04034507076..292d519d831 100644 --- a/src/interpret_ir.mli +++ b/src/interpret_ir.mli @@ -10,4 +10,3 @@ exception Trap of Source.region * string val interpret_prog : scope -> Ir.prog -> scope -val dump_profile : unit -> unit diff --git a/src/main.ml b/src/main.ml index ca459dfd660..4d7bc626033 100644 --- a/src/main.ml +++ b/src/main.ml @@ -44,6 +44,9 @@ let argspec = Arg.align "--profile", Arg.Set Flags.profile, " activate profiling counters in interpreters "; "--profile-file", Arg.Set_string Flags.profile_file, " set profiling output file "; "--profile-line-prefix", Arg.Set_string Flags.profile_line_prefix, " prefix each profile line with the given string "; + "--profile-field", + Arg.String (fun n -> Flags.profile_field_names := n :: !Flags.profile_field_names), + " suffix each profile line with the given string "; "-iR", Arg.Set Flags.interpret_ir, " interpret the lowered code"; "-no-await", Arg.Clear Flags.await_lowering, " no await-lowering (with -iR)"; "-no-async", Arg.Clear Flags.async_lowering, " no async-lowering (with -iR)"; diff --git a/src/pipeline.ml b/src/pipeline.ml index cf7ceb5d8c2..fdf766b3c40 100644 --- a/src/pipeline.ml +++ b/src/pipeline.ml @@ -236,6 +236,19 @@ let load_decl parse_one senv : load_decl_result = let interpret_prog denv prog : (Value.value * Interpret.scope) option = phase "Interpreting" prog.Source.note; let result = Interpret.interpret_prog denv prog in + begin + if !Flags.profile then + try + match result with + Some(Value.Async a,_) -> begin + match Lib.Promise.value_opt a.Value.result with + | Some v -> Interpret.dump_profile (Value.as_obj v) + | None -> () + end + | _ -> () + with + | Invalid_argument _ -> () ; + end ; result let rec interpret_libraries denv libraries : Interpret.scope = @@ -317,9 +330,10 @@ let check_string s name : check_result = (* Running *) let run_files files : unit Diag.result = - let result = Diag.ignore (interpret_files initial_env files) in - Interpret.dump_profile () ; - result + Diag.bind (interpret_files initial_env files) + (fun (_, _) -> + Diag.return () + ) (* Interactively *) @@ -501,7 +515,6 @@ let interpret_ir_prog inp_env libraries progs = let dscope = Interpret_ir.interpret_prog denv0 prelude_ir in let denv1 = Interpret_ir.adjoin_scope denv0 dscope in let _ = Interpret_ir.interpret_prog denv1 prog_ir in - let _ = Interpret_ir.dump_profile () in () let interpret_ir_files files = diff --git a/src/source.ml b/src/source.ml index b77bb2eb3cd..bc54030ea07 100644 --- a/src/source.ml +++ b/src/source.ml @@ -22,61 +22,3 @@ let string_of_region r = if r.left.file = "" then "(unknown location)" else r.left.file ^ ":" ^ string_of_pos r.left ^ (if r.right = r.left then "" else "-" ^ string_of_pos r.right) - - -(** Counters for regions, for super-simple profiling support. *) -module Counters = struct - type t = (region, int) Hashtbl.t - - let dump_count = ref 0 - - let zeros () = - Hashtbl.create 100 - - let bump c reg = - if !Flags.profile then - match Hashtbl.find_opt c reg with - Some n -> Hashtbl.replace c reg (n + 1) - | None -> Hashtbl.replace c reg 1 - - (* lexicographic on (left.file, left.line, left.column, right.line, right.column) *) - let region_order rega regb = - if rega.left.file = regb.left.file then - if rega.left.line = regb.left.line then - if rega.left.column = regb.left.column then - if rega.right.line = regb.right.line then - compare rega.right.column regb.right.column - else - compare rega.right.line regb.right.line - else - compare rega.left.column regb.left.column - else - compare rega.left.line regb.left.line - else - compare rega.left.file regb.left.file - - let dump c = - if !Flags.profile then - let dump_count = begin - let d = !dump_count in - dump_count := d + 1; - d - end - in - let counts = Hashtbl.fold (fun region count counts -> (region, count) :: counts) c [] in - let counts = List.sort (fun (rega, x) (regb, y) -> - let diff = x - y in - if diff <> 0 then -diff else - region_order rega regb - ) counts - in - let file = open_out (!Flags.profile_file) in - List.iter (fun (region, region_count) -> - assert (dump_count = 0); - Printf.fprintf file "%s\"%s\", %d\n" - (!Flags.profile_line_prefix) - (string_of_region region) - region_count - ) counts; - close_out file -end diff --git a/src/source.mli b/src/source.mli index ace4dd31eb9..df5e731afe6 100644 --- a/src/source.mli +++ b/src/source.mli @@ -12,10 +12,3 @@ val string_of_region : region -> string val span : region -> region -> region val (@@) : 'a -> region -> 'a phrase - -module Counters : sig - type t - val zeros : unit -> t - val bump : t -> region -> unit - val dump : t -> unit -end diff --git a/stdlib/Makefile b/stdlib/Makefile index 3bebb31de60..f92c37ba2a3 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -33,7 +33,7 @@ OUTFILES=$(addsuffix .out, $(TESTS)) $(addsuffix .wasm, $(WASM)) OUTPATHS=$(addprefix $(OUTDIR)/, $(OUTFILES)) -.PHONY: default all clean alltests alldoc docMd docHtml +.PHONY: default all clean alltests alldoc docMd docHtml profile default: all @@ -164,19 +164,40 @@ $(OUTDIR)/ProduceExchange.out: $(PRODUCE_EXCHANGE_SRC) \ PROFILE_SRC=\ examples/produce-exchange/serverActor.as \ - examples/produce-exchange/test/loadWorkloadAndQuery.Common.as + examples/produce-exchange/test/profileLoad.as -$(OUTDIR)/loadWorkloadAndQuery.profile.4-5-5.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_SRC) | $(OUTDIR) - $(ASC) -r --profile examples/produce-exchange/test/params-5-5.as $(PROFILE_SRC) --profile-file $@ --profile-line-prefix "4, 5, 5, " +PROFILE_FIELDS=\ + --profile-field "hash_bit_length" \ + --profile-field "producer_count" \ + --profile-field "inventory_count" \ + --profile-field "transporter_count" \ + --profile-field "route_count" \ -$(OUTDIR)/loadWorkloadAndQuery.profile.4-5-10.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_SRC) | $(OUTDIR) - $(ASC) -r --profile examples/produce-exchange/test/params-5-10.as $(PROFILE_SRC) --profile-file $@ --profile-line-prefix "4, 5, 10, " +profile: \ + $(OUTDIR)/profileLoad.04-05-01.csv \ + $(OUTDIR)/profileLoad.04-05-05.csv \ + $(OUTDIR)/profileLoad.04-05-10.csv \ + $(OUTDIR)/profileLoad.04-05-20.csv \ + $(OUTDIR)/profileLoad.04-05-50.csv \ + $(OUTDIR)/profileLoad.04-05-100.csv \ -$(OUTDIR)/loadWorkloadAndQuery.profile.4-5-20.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_SRC) | $(OUTDIR) - $(ASC) -r --profile examples/produce-exchange/test/params-5-20.as $(PROFILE_SRC) --profile-file $@ --profile-line-prefix "4, 5, 20, " +$(OUTDIR)/profileLoad.04-05-01.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_SRC) | $(OUTDIR) + $(ASC) -r --profile examples/produce-exchange/test/params-5-1.as $(PROFILE_SRC) --profile-file $@ $(PROFILE_FIELDS) -$(OUTDIR)/loadWorkloadAndQuery.profile.4-5-50.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_SRC) | $(OUTDIR) - $(ASC) -r --profile examples/produce-exchange/test/params-5-50.as $(PROFILE_SRC) --profile-file $@ --profile-line-prefix "4, 5, 50, " +$(OUTDIR)/profileLoad.04-05-05.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_SRC) | $(OUTDIR) + $(ASC) -r --profile examples/produce-exchange/test/params-5-5.as $(PROFILE_SRC) --profile-file $@ $(PROFILE_FIELDS) + +$(OUTDIR)/profileLoad.04-05-10.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_SRC) | $(OUTDIR) + $(ASC) -r --profile examples/produce-exchange/test/params-5-10.as $(PROFILE_SRC) --profile-file $@ $(PROFILE_FIELDS) + +$(OUTDIR)/profileLoad.04-05-20.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_SRC) | $(OUTDIR) + $(ASC) -r --profile examples/produce-exchange/test/params-5-20.as $(PROFILE_SRC) --profile-file $@ $(PROFILE_FIELDS) + +$(OUTDIR)/profileLoad.04-05-50.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_SRC) | $(OUTDIR) + $(ASC) -r --profile examples/produce-exchange/test/params-5-50.as $(PROFILE_SRC) --profile-file $@ $(PROFILE_FIELDS) + +$(OUTDIR)/profileLoad.04-05-100.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_SRC) | $(OUTDIR) + $(ASC) -r --profile examples/produce-exchange/test/params-5-100.as $(PROFILE_SRC) --profile-file $@ $(PROFILE_FIELDS) $(OUTDIR)/loadWorkloadAndQueryBig.wasm: $(PRODUCE_EXCHANGE_SRC) \ examples/produce-exchange/test/loadWorkloadAndQuery.as | $(OUTDIR) diff --git a/stdlib/examples/produce-exchange/serverActor.as b/stdlib/examples/produce-exchange/serverActor.as index ea4d4775851..193dbbd3d6a 100644 --- a/stdlib/examples/produce-exchange/serverActor.as +++ b/stdlib/examples/produce-exchange/serverActor.as @@ -11,6 +11,8 @@ let L = (import "serverLang.as"); let Model = (import "serverModel.as"); let Result = (import "../../result.as"); +let Trie = (import "../../trie.as"); + let List = (import "../../list.as"); type List = List.List; @@ -909,6 +911,7 @@ actor server { getCounts() : async T.ProduceExchangeCounts { let m = getModel(); shared { + hash_bit_length = Trie.HASH_BITS; truck_type_count = m.truckTypeTable.count(); region_count = m.regionTable.count(); produce_count = m.produceTable.count(); diff --git a/stdlib/examples/produce-exchange/serverTypes.as b/stdlib/examples/produce-exchange/serverTypes.as index 42bf659a557..d790d51bd5d 100644 --- a/stdlib/examples/produce-exchange/serverTypes.as +++ b/stdlib/examples/produce-exchange/serverTypes.as @@ -338,6 +338,7 @@ type ReservationInfo = shared { */ type ProduceExchangeCounts = shared { + hash_bit_length : Nat; truck_type_count : Nat; region_count : Nat; produce_count : Nat; diff --git a/stdlib/examples/produce-exchange/test/params-5-1.as b/stdlib/examples/produce-exchange/test/params-5-1.as new file mode 100644 index 00000000000..4a5eddae81a --- /dev/null +++ b/stdlib/examples/produce-exchange/test/params-5-1.as @@ -0,0 +1,3 @@ +let region_count = 5; +let scale_factor = 1; + diff --git a/stdlib/examples/produce-exchange/test/params-5-100.as b/stdlib/examples/produce-exchange/test/params-5-100.as new file mode 100644 index 00000000000..3b107e555e3 --- /dev/null +++ b/stdlib/examples/produce-exchange/test/params-5-100.as @@ -0,0 +1,3 @@ +let region_count = 5; +let scale_factor = 100; + diff --git a/stdlib/examples/produce-exchange/test/loadWorkloadAndQuery.Common.as b/stdlib/examples/produce-exchange/test/profileLoad.as similarity index 86% rename from stdlib/examples/produce-exchange/test/loadWorkloadAndQuery.Common.as rename to stdlib/examples/produce-exchange/test/profileLoad.as index 05c28d8cd96..42d9e172f03 100644 --- a/stdlib/examples/produce-exchange/test/loadWorkloadAndQuery.Common.as +++ b/stdlib/examples/produce-exchange/test/profileLoad.as @@ -8,8 +8,5 @@ func scaledParams(region_count_:Nat, factor:Nat) : T.WorkloadParams = { retailer_count = region_count * factor:Nat; } }; -async { let _ = server.loadWorkload(scaledParams(region_count, scale_factor)); -let c = (await server.getCounts()); -print (debug_show c); -}; \ No newline at end of file +server.getCounts() From 89a1c02a2eb5c64c62a1f73e8ce4f30da695396e Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Wed, 15 May 2019 14:01:37 -0400 Subject: [PATCH 0008/1176] make profile-small gathers some counts --- src/interpret_ir.ml | 2 + src/interpret_ir.mli | 1 - src/pipeline.ml | 5 +- stdlib/Makefile | 63 +++++++++++++++---- .../produce-exchange/test/profileLoadQuery.as | 13 ++++ 5 files changed, 66 insertions(+), 18 deletions(-) create mode 100644 stdlib/examples/produce-exchange/test/profileLoadQuery.as diff --git a/src/interpret_ir.ml b/src/interpret_ir.ml index 5f7972676a5..a8f0cd2f0d8 100644 --- a/src/interpret_ir.ml +++ b/src/interpret_ir.ml @@ -4,6 +4,7 @@ open Source module V = Value module T = Type + (* Context *) type val_env = V.def V.Env.t @@ -661,3 +662,4 @@ let interpret_prog scope ((ds, exp), _flavor) : scope = Scheduler.run (); !ve with exn -> print_exn exn; !ve + diff --git a/src/interpret_ir.mli b/src/interpret_ir.mli index 292d519d831..4dea591faaa 100644 --- a/src/interpret_ir.mli +++ b/src/interpret_ir.mli @@ -9,4 +9,3 @@ val adjoin_scope : scope -> scope -> scope exception Trap of Source.region * string val interpret_prog : scope -> Ir.prog -> scope - diff --git a/src/pipeline.ml b/src/pipeline.ml index fdf766b3c40..7fe63183f00 100644 --- a/src/pipeline.ml +++ b/src/pipeline.ml @@ -330,10 +330,7 @@ let check_string s name : check_result = (* Running *) let run_files files : unit Diag.result = - Diag.bind (interpret_files initial_env files) - (fun (_, _) -> - Diag.return () - ) + Diag.ignore (interpret_files initial_env files) (* Interactively *) diff --git a/stdlib/Makefile b/stdlib/Makefile index f92c37ba2a3..21d0f2ac838 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -162,10 +162,14 @@ $(OUTDIR)/ProduceExchange.out: $(PRODUCE_EXCHANGE_SRC) \ examples/produce-exchange/test/simpleSetupAndQuery.as | $(OUTDIR) $(ASC) -r examples/produce-exchange/serverActor.as examples/produce-exchange/test/simpleSetupAndQuery.as > $@ -PROFILE_SRC=\ +PROFILE_LOAD_SRC=\ examples/produce-exchange/serverActor.as \ examples/produce-exchange/test/profileLoad.as +PROFILE_LOAD_QUERY_SRC=\ + examples/produce-exchange/serverActor.as \ + examples/produce-exchange/test/profileLoadQuery.as + PROFILE_FIELDS=\ --profile-field "hash_bit_length" \ --profile-field "producer_count" \ @@ -173,6 +177,13 @@ PROFILE_FIELDS=\ --profile-field "transporter_count" \ --profile-field "route_count" \ +profile-small: \ + $(OUTDIR)/profileLoad.04-05-01.csv \ + $(OUTDIR)/profileLoad.04-05-05.csv \ + \ + $(OUTDIR)/profileLoadQuery.04-05-01.csv \ + $(OUTDIR)/profileLoadQuery.04-05-05.csv \ + profile: \ $(OUTDIR)/profileLoad.04-05-01.csv \ $(OUTDIR)/profileLoad.04-05-05.csv \ @@ -180,24 +191,50 @@ profile: \ $(OUTDIR)/profileLoad.04-05-20.csv \ $(OUTDIR)/profileLoad.04-05-50.csv \ $(OUTDIR)/profileLoad.04-05-100.csv \ + \ + $(OUTDIR)/profileLoadQuery.04-05-01.csv \ + $(OUTDIR)/profileLoadQuery.04-05-05.csv \ + $(OUTDIR)/profileLoadQuery.04-05-10.csv \ + $(OUTDIR)/profileLoadQuery.04-05-20.csv \ + $(OUTDIR)/profileLoadQuery.04-05-50.csv \ + $(OUTDIR)/profileLoadQuery.04-05-100.csv \ + +$(OUTDIR)/profileLoad.04-05-01.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_SRC) | $(OUTDIR) + $(ASC) -r --profile examples/produce-exchange/test/params-5-1.as $(PROFILE_LOAD_SRC) --profile-file $@ $(PROFILE_FIELDS) + +$(OUTDIR)/profileLoad.04-05-05.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_SRC) | $(OUTDIR) + $(ASC) -r --profile examples/produce-exchange/test/params-5-5.as $(PROFILE_LOAD_SRC) --profile-file $@ $(PROFILE_FIELDS) + +$(OUTDIR)/profileLoad.04-05-10.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_SRC) | $(OUTDIR) + $(ASC) -r --profile examples/produce-exchange/test/params-5-10.as $(PROFILE_LOAD_SRC) --profile-file $@ $(PROFILE_FIELDS) + +$(OUTDIR)/profileLoad.04-05-20.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_SRC) | $(OUTDIR) + $(ASC) -r --profile examples/produce-exchange/test/params-5-20.as $(PROFILE_LOAD_SRC) --profile-file $@ $(PROFILE_FIELDS) + +$(OUTDIR)/profileLoad.04-05-50.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_SRC) | $(OUTDIR) + $(ASC) -r --profile examples/produce-exchange/test/params-5-50.as $(PROFILE_LOAD_SRC) --profile-file $@ $(PROFILE_FIELDS) + +$(OUTDIR)/profileLoad.04-05-100.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_SRC) | $(OUTDIR) + $(ASC) -r --profile examples/produce-exchange/test/params-5-100.as $(PROFILE_LOAD_SRC) --profile-file $@ $(PROFILE_FIELDS) + -$(OUTDIR)/profileLoad.04-05-01.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_SRC) | $(OUTDIR) - $(ASC) -r --profile examples/produce-exchange/test/params-5-1.as $(PROFILE_SRC) --profile-file $@ $(PROFILE_FIELDS) +$(OUTDIR)/profileLoadQuery.04-05-01.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) + $(ASC) -r --profile examples/produce-exchange/test/params-5-1.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) -$(OUTDIR)/profileLoad.04-05-05.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_SRC) | $(OUTDIR) - $(ASC) -r --profile examples/produce-exchange/test/params-5-5.as $(PROFILE_SRC) --profile-file $@ $(PROFILE_FIELDS) +$(OUTDIR)/profileLoadQuery.04-05-05.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) + $(ASC) -r --profile examples/produce-exchange/test/params-5-5.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) -$(OUTDIR)/profileLoad.04-05-10.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_SRC) | $(OUTDIR) - $(ASC) -r --profile examples/produce-exchange/test/params-5-10.as $(PROFILE_SRC) --profile-file $@ $(PROFILE_FIELDS) +$(OUTDIR)/profileLoadQuery.04-05-10.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) + $(ASC) -r --profile examples/produce-exchange/test/params-5-10.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) -$(OUTDIR)/profileLoad.04-05-20.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_SRC) | $(OUTDIR) - $(ASC) -r --profile examples/produce-exchange/test/params-5-20.as $(PROFILE_SRC) --profile-file $@ $(PROFILE_FIELDS) +$(OUTDIR)/profileLoadQuery.04-05-20.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) + $(ASC) -r --profile examples/produce-exchange/test/params-5-20.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) -$(OUTDIR)/profileLoad.04-05-50.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_SRC) | $(OUTDIR) - $(ASC) -r --profile examples/produce-exchange/test/params-5-50.as $(PROFILE_SRC) --profile-file $@ $(PROFILE_FIELDS) +$(OUTDIR)/profileLoadQuery.04-05-50.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) + $(ASC) -r --profile examples/produce-exchange/test/params-5-50.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) -$(OUTDIR)/profileLoad.04-05-100.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_SRC) | $(OUTDIR) - $(ASC) -r --profile examples/produce-exchange/test/params-5-100.as $(PROFILE_SRC) --profile-file $@ $(PROFILE_FIELDS) +$(OUTDIR)/profileLoadQuery.04-05-100.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) + $(ASC) -r --profile examples/produce-exchange/test/params-5-100.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) $(OUTDIR)/loadWorkloadAndQueryBig.wasm: $(PRODUCE_EXCHANGE_SRC) \ examples/produce-exchange/test/loadWorkloadAndQuery.as | $(OUTDIR) diff --git a/stdlib/examples/produce-exchange/test/profileLoadQuery.as b/stdlib/examples/produce-exchange/test/profileLoadQuery.as new file mode 100644 index 00000000000..f359b59c310 --- /dev/null +++ b/stdlib/examples/produce-exchange/test/profileLoadQuery.as @@ -0,0 +1,13 @@ +func scaledParams(region_count_:Nat, factor:Nat) : T.WorkloadParams = { + shared { + region_count = region_count_:Nat; + day_count = 3:Nat; + max_route_duration = 1:Nat; + producer_count = region_count * factor:Nat; + transporter_count = region_count * factor:Nat; + retailer_count = region_count * factor:Nat; + } +}; +let _ = server.loadWorkload(scaledParams(region_count, scale_factor)); +let _ = server.retailerQueryAll("", 0, null, null); +server.getCounts() From af4ca1b78c9d246c07aeaa4b63625706a55a7bea Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Wed, 15 May 2019 14:44:33 -0400 Subject: [PATCH 0009/1176] csv profile files include retailer query size --- src/counters.ml | 14 ++++++--- stdlib/Makefile | 17 ++++++++-- .../examples/produce-exchange/serverActor.as | 1 + .../examples/produce-exchange/serverModel.as | 31 ++++++++++++------- .../examples/produce-exchange/serverTypes.as | 1 + .../produce-exchange/test/params-5-2.as | 3 ++ 6 files changed, 48 insertions(+), 19 deletions(-) create mode 100644 stdlib/examples/produce-exchange/test/params-5-2.as diff --git a/src/counters.ml b/src/counters.ml index db4ff7b94c3..024d5f34800 100644 --- a/src/counters.ml +++ b/src/counters.ml @@ -64,15 +64,19 @@ let dump (c:t) (ve: Value.value Value.Env.t) = ) counts in let file = open_out (!Flags.profile_file) in - let suffix = + let (suffix, flds) = (* the suffix of the line consists of field values for each field in `profile_field_names`: *) List.fold_right - (fun var line -> + (fun var (line, flds) -> match Value.Env.find_opt var ve with - None -> Printf.sprintf "%s, #err(\"undefined field `%s`\")" line var - | Some v -> Printf.sprintf "%s, %s" line (Value.string_of_val v) - ) !Flags.profile_field_names "" + None -> (Printf.sprintf "%s, #err" line, (var :: flds)) + | Some v -> (Printf.sprintf "%s, %s" line (Value.string_of_val v), var :: flds) + ) !Flags.profile_field_names ("", []) in + Printf.fprintf file "# column: source region\n" ; + Printf.fprintf file "# column: source region count\n" ; + List.iter (fun fld -> Printf.fprintf file "# column: --profile-field: %s\n" fld) + (List.rev flds) ; List.iter (fun (region, region_count) -> assert (dump_count = 0); Printf.fprintf file "%s\"%s\", %d%s\n" diff --git a/stdlib/Makefile b/stdlib/Makefile index 21d0f2ac838..f03cf88d216 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -176,16 +176,20 @@ PROFILE_FIELDS=\ --profile-field "inventory_count" \ --profile-field "transporter_count" \ --profile-field "route_count" \ + --profile-field "retailer_join_count" \ + --profile-field "retailer_query_cost" \ + --profile-field "retailer_query_size_max" \ profile-small: \ $(OUTDIR)/profileLoad.04-05-01.csv \ - $(OUTDIR)/profileLoad.04-05-05.csv \ + $(OUTDIR)/profileLoad.04-05-02.csv \ \ $(OUTDIR)/profileLoadQuery.04-05-01.csv \ - $(OUTDIR)/profileLoadQuery.04-05-05.csv \ + $(OUTDIR)/profileLoadQuery.04-05-02.csv \ profile: \ $(OUTDIR)/profileLoad.04-05-01.csv \ + $(OUTDIR)/profileLoad.04-05-02.csv \ $(OUTDIR)/profileLoad.04-05-05.csv \ $(OUTDIR)/profileLoad.04-05-10.csv \ $(OUTDIR)/profileLoad.04-05-20.csv \ @@ -193,15 +197,21 @@ profile: \ $(OUTDIR)/profileLoad.04-05-100.csv \ \ $(OUTDIR)/profileLoadQuery.04-05-01.csv \ + $(OUTDIR)/profileLoadQuery.04-05-02.csv \ $(OUTDIR)/profileLoadQuery.04-05-05.csv \ $(OUTDIR)/profileLoadQuery.04-05-10.csv \ $(OUTDIR)/profileLoadQuery.04-05-20.csv \ $(OUTDIR)/profileLoadQuery.04-05-50.csv \ $(OUTDIR)/profileLoadQuery.04-05-100.csv \ +## AS wishlist: the following various targets would be easier to relate if we could accept named AS values as CLI params; that feature would also obviate the need for the `param-X-Y.as` files used below: + $(OUTDIR)/profileLoad.04-05-01.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_SRC) | $(OUTDIR) $(ASC) -r --profile examples/produce-exchange/test/params-5-1.as $(PROFILE_LOAD_SRC) --profile-file $@ $(PROFILE_FIELDS) +$(OUTDIR)/profileLoad.04-05-02.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_SRC) | $(OUTDIR) + $(ASC) -r --profile examples/produce-exchange/test/params-5-2.as $(PROFILE_LOAD_SRC) --profile-file $@ $(PROFILE_FIELDS) + $(OUTDIR)/profileLoad.04-05-05.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_SRC) | $(OUTDIR) $(ASC) -r --profile examples/produce-exchange/test/params-5-5.as $(PROFILE_LOAD_SRC) --profile-file $@ $(PROFILE_FIELDS) @@ -221,6 +231,9 @@ $(OUTDIR)/profileLoad.04-05-100.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_SRC) $(OUTDIR)/profileLoadQuery.04-05-01.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) $(ASC) -r --profile examples/produce-exchange/test/params-5-1.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) +$(OUTDIR)/profileLoadQuery.04-05-02.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) + $(ASC) -r --profile examples/produce-exchange/test/params-5-2.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + $(OUTDIR)/profileLoadQuery.04-05-05.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) $(ASC) -r --profile examples/produce-exchange/test/params-5-5.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) diff --git a/stdlib/examples/produce-exchange/serverActor.as b/stdlib/examples/produce-exchange/serverActor.as index 193dbbd3d6a..e3535b609c0 100644 --- a/stdlib/examples/produce-exchange/serverActor.as +++ b/stdlib/examples/produce-exchange/serverActor.as @@ -923,6 +923,7 @@ actor server { route_count = m.routeTable.count(); reserved_route_count = m.reservedRouteTable.count(); + retailer_query_size_max = m.retailerQuerySizeMax; retailer_query_count = m.retailerQueryCount; retailer_query_cost = m.retailerQueryCost; retailer_join_count = m.retailerJoinCount; diff --git a/stdlib/examples/produce-exchange/serverModel.as b/stdlib/examples/produce-exchange/serverModel.as index 679e82a2f05..19e78a2967b 100644 --- a/stdlib/examples/produce-exchange/serverModel.as +++ b/stdlib/examples/produce-exchange/serverModel.as @@ -121,6 +121,7 @@ class Model() { retailerQueryCount := 0; retailerQueryCost := 0; retailerJoinCount := 0; + retailerQuerySizeMax := 0; #ok(#reset) }; @@ -501,6 +502,7 @@ class Model() { private debugOff (t:Text) { }; private debugIntOff (i:Int) { }; + private debugOffInt (i:Int) { }; private idIsEq(x:Nat,y:Nat):Bool { x == y }; @@ -530,6 +532,7 @@ class Model() { */ var joinCount = 0; + var retailerQuerySizeMax = 0; /** @@ -1801,14 +1804,14 @@ than the MVP goals, however. case (null) { return null }; case (?x) { x }}; - debug "- user_name: "; - debug (retailer.short_name); - debug "\n"; + debugOff "- user_name: "; + debugOff (retailer.short_name); + debugOff "\n"; /** - Temp: */ - debug "- retailer is located in region "; - debugInt (retailer.region.id); - debug ", and\n- is accessible via routes from "; + debugOff "- retailer is located in region "; + debugOffInt (retailer.region.id); + debugOff ", and\n- is accessible via routes from "; /** - Find all routes whose the destination region is the retailer's region: */ let retailerRoutes = @@ -1820,8 +1823,8 @@ than the MVP goals, however. case (null) { return ?[] }; case (?x) { x }}; - debugInt(Trie.count(retailerRoutes)); - debug " production regions.\n"; + debugOffInt(Trie.count(retailerRoutes)); + debugOff " production regions.\n"; /** - Join: For each production region, consider all routes and inventory: */ let queryResults : Trie = { @@ -1873,10 +1876,14 @@ than the MVP goals, however. Trie.mergeDisjoint2D( queryResults, idIsEq, idPairIsEq); - debug "- query result count: "; - debugInt(Trie.count<(T.RouteId, T.InventoryId), - (M.RouteDoc, M.InventoryDoc)>(queryResultsMerged)); - debug " (count of feasible route-item pairs).\n"; + debugOff "- query result count: "; + let size = Trie.count<(T.RouteId, T.InventoryId), + (M.RouteDoc, M.InventoryDoc)>(queryResultsMerged); + if ( size > retailerQuerySizeMax ) { + retailerQuerySizeMax := size; + }; + debugOffInt(size); + debugOff " (count of feasible route-item pairs).\n"; /** - Prepare reservation information for client, as an array; see also [`makeReservationInfo`](#makereservationinfo) */ let arr = diff --git a/stdlib/examples/produce-exchange/serverTypes.as b/stdlib/examples/produce-exchange/serverTypes.as index d790d51bd5d..634bb54d447 100644 --- a/stdlib/examples/produce-exchange/serverTypes.as +++ b/stdlib/examples/produce-exchange/serverTypes.as @@ -349,6 +349,7 @@ type ProduceExchangeCounts = shared { route_count : Nat; reserved_route_count : Nat; retailer_count : Nat; + retailer_query_size_max : Nat; retailer_query_count : Nat; retailer_query_cost : Nat; retailer_join_count : Nat; diff --git a/stdlib/examples/produce-exchange/test/params-5-2.as b/stdlib/examples/produce-exchange/test/params-5-2.as new file mode 100644 index 00000000000..d0ba163842d --- /dev/null +++ b/stdlib/examples/produce-exchange/test/params-5-2.as @@ -0,0 +1,3 @@ +let region_count = 5; +let scale_factor = 2; + From 551513f7006f2028ca013773bf9d7e6bcf2e9cb6 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Fri, 3 May 2019 17:13:57 -0700 Subject: [PATCH 0010/1176] [WIP] --- default.nix | 233 +++++++------------- nix/md2mld.nix | 32 +++ nix/ocaml-rpc.nix | 67 ++++++ src/Makefile | 15 ++ src/actorscript.mllib | 44 ++++ src/language_server/language_server_main.ml | 137 ++++++++++++ 6 files changed, 374 insertions(+), 154 deletions(-) create mode 100644 nix/md2mld.nix create mode 100644 nix/ocaml-rpc.nix create mode 100644 src/actorscript.mllib create mode 100644 src/language_server/language_server_main.ml diff --git a/default.nix b/default.nix index fc43aef96d5..3d58507066e 100644 --- a/default.nix +++ b/default.nix @@ -1,11 +1,8 @@ -{ nixpkgs ? (import ./nix/nixpkgs.nix).nixpkgs {}, +{ nixpkgs ? (import ./nix/nixpkgs.nix) {}, test-dvm ? true, dvm ? null, - export-shell ? false, }: -let llvm = import ./nix/llvm.nix { system = nixpkgs.system; }; in - let stdenv = nixpkgs.stdenv; in let sourceByRegex = src: regexes: builtins.path @@ -17,18 +14,20 @@ let sourceByRegex = src: regexes: builtins.path ( type == "directory" && match (relPath + "/") != null || match relPath != null); }; in -let ocaml_wasm = import ./nix/ocaml-wasm.nix { +let ocaml_wasm = (import ./nix/ocaml-wasm.nix) { inherit (nixpkgs) stdenv fetchFromGitHub ocaml; inherit (nixpkgs.ocamlPackages) findlib ocamlbuild; }; in -let ocaml_vlq = import ./nix/ocaml-vlq.nix { +let ocaml_vlq = (import ./nix/ocaml-vlq.nix) { inherit (nixpkgs) stdenv fetchFromGitHub ocaml dune; inherit (nixpkgs.ocamlPackages) findlib; }; in -let ocaml_bisect_ppx = import ./nix/ocaml-bisect_ppx.nix nixpkgs; in -let ocaml_bisect_ppx-ocamlbuild = import ./nix/ocaml-bisect_ppx-ocamlbuild.nix nixpkgs; in +let ocaml_bisect_ppx = (import ./nix/ocaml-bisect_ppx.nix) nixpkgs; in +let ocaml_bisect_ppx-ocamlbuild = (import ./nix/ocaml-bisect_ppx-ocamlbuild.nix) nixpkgs; in + +let ocaml-rpc = import ./nix/ocaml-rpc.nix { pkgs = nixpkgs; }; in # Include dvm let real-dvm = @@ -39,9 +38,9 @@ let real-dvm = let dev = builtins.fetchGit { url = "ssh://git@github.com/dfinity-lab/dev"; ref = "master"; - rev = "aff35b2a015108f7d1d694471ccaf3ffd6f0340c"; + rev = "b6f587c3303b9f2585548e5fcb98f907b0275219"; }; in - (import dev { system = nixpkgs.system; }).dvm + (import dev {}).dvm else null else dvm; in @@ -60,19 +59,30 @@ let commonBuildInputs = [ ]; in let + native_src_files =[ + "src/" + "src/Makefile.*" + "src/.*.ml" + "src/.*.mli" + "src/.*.mly" + "src/.*.mll" + "src/.*.mllib" + "src/.*.mlpack" + "src/_tags" + "test/" + "test/node-test.js" + ]; test_files = [ "test/" "test/.*Makefile.*" "test/quick.mk" - "test/(fail|run|run-dfinity|repl|ld)/" - "test/(fail|run|run-dfinity|repl|ld)/lib/" - "test/(fail|run|run-dfinity|repl|ld)/lib/dir/" - "test/(fail|run|run-dfinity|repl|ld)/.*.as" - "test/(fail|run|run-dfinity|repl|ld)/.*.sh" - "test/(fail|run|run-dfinity|repl|ld)/[^/]*.wat" - "test/(fail|run|run-dfinity|repl|ld)/[^/]*.c" - "test/(fail|run|run-dfinity|repl|ld)/ok/" - "test/(fail|run|run-dfinity|repl|ld)/ok/.*.ok" + "test/(fail|run|run-dfinity|repl)/" + "test/(fail|run|run-dfinity|repl)/lib/" + "test/(fail|run|run-dfinity|repl)/lib/dir/" + "test/(fail|run|run-dfinity|repl)/.*.as" + "test/(fail|run|run-dfinity|repl)/.*.sh" + "test/(fail|run|run-dfinity|repl)/ok/" + "test/(fail|run|run-dfinity|repl)/ok/.*.ok" "test/.*.sh" ]; samples_files = [ @@ -96,89 +106,58 @@ let "stdlib/examples/produce-exchange/README.md" ]; - libtommath = nixpkgs.fetchFromGitHub { - owner = "libtom"; - repo = "libtommath"; - rev = "9e1a75cfdc4de614eaf4f88c52d8faf384e54dd0"; - sha256 = "0qwmzmp3a2rg47pnrsls99jpk5cjj92m75alh1kfhcg104qq6w3d"; - }; - - llvmBuildInputs = [ - llvm.clang_9 - llvm.lld_9 - ]; - - llvmEnv = '' - export CLANG="clang-9" - export WASM_LD=wasm-ld - ''; in rec { - rts = stdenv.mkDerivation { - name = "asc-rts"; - - src = sourceByRegex ./rts [ - "rts.c" - "Makefile" - "includes/" - "includes/.*.h" - ]; - - nativeBuildInputs = [ nixpkgs.makeWrapper ]; - - buildInputs = llvmBuildInputs; - - preBuild = '' - ${llvmEnv} - export TOMMATHSRC=${libtommath} + rpclib_core = ocaml-rpc.rpclib_core; + + language-server = stdenv.mkDerivation { + name = "actorscript-language-server"; + src = sourceByRegex ./. (native_src_files ++ [ + "^src/language_server/$" + "^src/language_server/.*\.ml(i|l|pack|y){0,1}$" + ]); + nativeBuildInputs = native.nativeBuildInputs; + buildInputs = native.buildInputs + ++ ocaml-rpc.ppx_deriving_rpc.buildInputs + ++ [ ocaml-rpc.ppx_deriving_rpc ]; + buildPhase = '' + make -C src BUILD=native aslan ''; - installPhase = '' - mkdir -p $out/rts - cp as-rts.wasm $out/rts + mkdir -p $out/bin + cp src/aslan $out/bin ''; }; - asc-bin = stdenv.mkDerivation { - name = "asc-bin"; + library = native.overrideAttrs (oldAttrs: { + name = "actorscript.mllib"; + buildPhase = '' + make -C src actorscript.cma + ''; + installPhase = '' + mkdir -p $out + cp src/actorscript.cma $out + ''; + }); + + native = stdenv.mkDerivation { + name = "asc"; - src = sourceByRegex ./. [ - "src/" - "src/Makefile.*" - "src/.*.ml" - "src/.*.mli" - "src/.*.mly" - "src/.*.mll" - "src/.*.mlpack" - "src/_tags" - "test/" - "test/node-test.js" - ]; + src = sourceByRegex ./. native_src_files; nativeBuildInputs = [ nixpkgs.makeWrapper ]; buildInputs = commonBuildInputs; buildPhase = '' - make -C src BUILD=native asc as-ld + make -C src BUILD=native asc ''; installPhase = '' mkdir -p $out/bin cp src/asc $out/bin - cp src/as-ld $out/bin - ''; - }; - - native = nixpkgs.symlinkJoin { - name = "asc"; - paths = [ asc-bin rts ]; - buildInputs = [ nixpkgs.makeWrapper ]; - postBuild = '' - wrapProgram $out/bin/asc \ - --set-default ASC_RTS "$out/rts/as-rts.wasm" ''; }; @@ -198,21 +177,18 @@ rec { nixpkgs.perl filecheck ] ++ - (if test-dvm then [ real-dvm ] else []) ++ - llvmBuildInputs; + (if test-dvm then [ real-dvm ] else []); buildPhase = '' - patchShebangs . - ${llvmEnv} - export ASC=asc - export AS_LD=as-ld - asc --version - make -C samples all - '' + - (if test-dvm then '' - make -C test parallel + patchShebangs . + asc --version + make -C samples ASC=asc all + '' + + (if test-dvm + then '' + make -C test ASC=asc parallel '' else '' - make -C test quick + make -C test ASC=asc quick ''); installPhase = '' @@ -220,8 +196,8 @@ rec { ''; }; - asc-bin-coverage = asc-bin.overrideAttrs (oldAttrs: { - name = "asc-bin-coverage"; + native-coverage = native.overrideAttrs (oldAttrs: { + name = "asc-coverage"; buildPhase = "export BISECT_COVERAGE=YES;" + oldAttrs.buildPhase; @@ -231,18 +207,8 @@ rec { ''; }); - native-coverage = nixpkgs.symlinkJoin { - name = "asc-covergage"; - paths = [ asc-bin-coverage rts ]; - buildInputs = [ nixpkgs.makeWrapper ]; - postBuild = '' - wrapProgram $out/bin/asc \ - --set-default ASC_RTS "$out/rts/as-rts.wasm" - ''; - }; - coverage-report = stdenv.mkDerivation { - name = "coverage-report"; + name = "native.coverage"; src = sourceByRegex ./. ( test_files ++ @@ -256,16 +222,12 @@ rec { nixpkgs.perl ocaml_bisect_ppx ] ++ - (if test-dvm then [ real-dvm ] else []) ++ - llvmBuildInputs; + (if test-dvm then [ real-dvm ] else []); buildPhase = '' patchShebangs . - ${llvmEnv} - export ASC=asc - export AS_LD=as-ld ln -vs ${native-coverage}/src src - make -C test coverage + make -C test ASC=asc coverage ''; installPhase = '' @@ -277,14 +239,14 @@ rec { }; - js = asc-bin.overrideAttrs (oldAttrs: { + js = native.overrideAttrs (oldAttrs: { name = "asc.js"; buildInputs = commonBuildInputs ++ [ nixpkgs.ocamlPackages.js_of_ocaml nixpkgs.ocamlPackages.js_of_ocaml-ocamlbuild nixpkgs.ocamlPackages.js_of_ocaml-ppx - nixpkgs.nodejs-10_x + nixpkgs.nodejs ]; buildPhase = '' @@ -293,14 +255,11 @@ rec { installPhase = '' mkdir -p $out - cp -v src/asc.js $out - cp -vr ${rts}/rts $out + cp src/asc.js $out ''; - doInstallCheck = true; - installCheckPhase = '' - NODE_PATH=$out node --experimental-wasm-mut-global --experimental-wasm-mv test/node-test.js + NODE_PATH=$out/ node test/node-test.js ''; }); @@ -402,40 +361,6 @@ rec { all-systems-go = nixpkgs.releaseTools.aggregate { name = "all-systems-go"; - constituents = [ - native - js - native_test - coverage-report - rts - stdlib-reference - produce-exchange - users-guide - ]; + constituents = [ native js native_test coverage-report stdlib-reference produce-exchange users-guide ]; }; - - shell = if export-shell then nixpkgs.mkShell { - - # - # Since building asc, and testing it, are two different derivation in default.nix - # we have to create a fake derivation for shell.nix that commons up the build dependencies - # of the two to provide a build environment that offers both - # - # Would not be necessary if nix-shell would take more than one `-A` flag, see - # https://github.com/NixOS/nix/issues/955 - # - - buildInputs = nixpkgs.lib.lists.unique (builtins.filter (i: i != native) ( - asc-bin.buildInputs ++ - rts.buildInputs ++ - native_test.buildInputs ++ - users-guide.buildInputs ++ - [ nixpkgs.ncurses ] - )); - - shellHook = llvmEnv; - TOMMATHSRC = libtommath; - NIX_FONTCONFIG_FILE = users-guide.NIX_FONTCONFIG_FILE; - } else null; - } diff --git a/nix/md2mld.nix b/nix/md2mld.nix new file mode 100644 index 00000000000..81cb113db27 --- /dev/null +++ b/nix/md2mld.nix @@ -0,0 +1,32 @@ +{ pkgs }: + +let repo = "md2mld"; in +let rev = "0.3.0"; in + +pkgs.stdenv.mkDerivation { + name = "ocaml${pkgs.ocaml.version}-${repo}-${rev}"; + + src = pkgs.fetchFromGitHub { + inherit repo rev; + owner = "mseri"; + sha256 = "0xb8890q6f6rh02ih6vw3wnkybddr2fmzpj7144l1gfix3smx5cv"; + }; + + buildInputs = [ + pkgs.dune + pkgs.ocaml + pkgs.ocamlPackages.findlib + pkgs.ocamlPackages.omd + ]; + + buildPhase = "dune build -p md2mld"; + + inherit (pkgs.dune) installPhase; + + meta = { + homepage = https://github.com/mseri/md2mld; + platforms = pkgs.ocaml.meta.platforms or []; + description = "Little cli tool to convert md files into mld files"; + license = pkgs.stdenv.lib.licenses.isc; + }; +} diff --git a/nix/ocaml-rpc.nix b/nix/ocaml-rpc.nix new file mode 100644 index 00000000000..ae663e12920 --- /dev/null +++ b/nix/ocaml-rpc.nix @@ -0,0 +1,67 @@ +{ pkgs }: + +let repo = "ocaml-rpc"; in +let rev = "4d542cb7b0c42a62196c6043ba556de54c1b7820"; in + +let src = pkgs.fetchFromGitHub { + inherit repo rev; + owner = "mirage"; + sha256 = "1931505xpycng9s18mq1m44naq0v7nxwr95nyws1kldl4fvrymn7"; +}; in + +let mkPackage = ({ name, description, buildInputs }: + pkgs.stdenv.mkDerivation { + name = "ocaml${pkgs.ocaml.version}-${repo}-${rev}-${name}"; + + inherit src; + + buildInputs = buildInputs ++ (with pkgs; [ + dune + ocaml + ocamlPackages.findlib + ]); + + buildPhase = '' + dune build -p ${name} + ''; + + inherit (pkgs.dune) installPhase; + + meta = { + homepage = https://github.com/mirage/ocaml-rpc; + platforms = pkgs.ocaml.meta.platforms or []; + license = pkgs.stdenv.lib.licenses.isc; + inherit description; + }; + } +); in + +let rpclib = mkPackage { + name = "rpclib"; + description = "A library to deal with RPCs in OCaml"; + buildInputs = with pkgs.ocamlPackages; [ + cmdliner + result + rresult + xmlm + yojson + ]; +}; in + +let ppx_deriving_rpc = mkPackage { + name = "ppx_deriving_rpc"; + description = "Ppx deriver for ocaml-rpc, a library to deal with RPCs in OCaml"; + buildInputs = rpclib.buildInputs ++ [ + pkgs.jbuilder + rpclib + ] ++ (with pkgs.ocamlPackages; [ + findlib + rresult + ppx_deriving + ppxlib + ]); +}; in + +{ + inherit rpclib ppx_deriving_rpc; +} diff --git a/src/Makefile b/src/Makefile index 5b798dc2515..ae831c3afbc 100644 --- a/src/Makefile +++ b/src/Makefile @@ -3,6 +3,13 @@ BUILD = byte MAIN = main JS_MAIN = js_main +LIBRARY_NAME = actorscript + +LANGUAGE_SERVER_DIR = language_server +LANGUAGE_SERVER_BIN = aslan +LANGUAGE_SERVER_MAIN = language_server_main +LANGUAGE_SERVER_OPAM_PACKAGES = ppx_deriving_rpc rpclib + ASC = `pwd`/$(NAME) OPAM_PACKAGES = wasm num vlq yojson bisect_ppx-ocamlbuild @@ -43,6 +50,14 @@ $(NAME).js: $(JS_MAIN).byte $(JS_MAIN).byte: $(JS_MAIN).ml sanity $(OCAMLBUILD) $(JS_OPAM_PACKAGES:%=-pkg %) $@ +$(LANGUAGE_SERVER_BIN): $(LANGUAGE_SERVER_MAIN).${BUILD} + mv $< $@ + +$(LANGUAGE_SERVER_MAIN).${BUILD}: sanity + $(OCAMLBUILD) $(LANGUAGE_SERVER_OPAM_PACKAGES:%=-pkg %) $(LANGUAGE_SERVER_DIR)/$@ + +$(LIBRARY_NAME).cma: sanity + $(OCAMLBUILD) $@ sanity: ocamlfind query $(OPAM_PACKAGES) diff --git a/src/actorscript.mllib b/src/actorscript.mllib new file mode 100644 index 00000000000..20df6eea936 --- /dev/null +++ b/src/actorscript.mllib @@ -0,0 +1,44 @@ +Arrange +Arrange_ir +Arrange_type +Async +Await +Check_ir +Compile +Con +Construct +Coverage +CustomModule +CustomSections +Definedness +Desugar +Diag +Dom +Effect +EncodeMap +Env +Flags +FreeVars +InstrList +Interpret +Interpret_ir +Ir +Lexer +Lib +NameRel +Operator +Parser +Pipeline +Prelude +Rename +Resolve_import +Serialization +Show +Source +Static +Syntax +Tailcall +Type +Typing +Value +Wasm_eval diff --git a/src/language_server/language_server_main.ml b/src/language_server/language_server_main.ml new file mode 100644 index 00000000000..b5eb2f6f43e --- /dev/null +++ b/src/language_server/language_server_main.ml @@ -0,0 +1,137 @@ +(* TODO: Move to protocol module *) + +(* type t = { foo: int; } [@@deriving rpcty] *) +(* type t = { foo: int; } [@@deriving rpc] *) + +(* Jsonrpc.to_string (rpc_of_t x) *) + +(* open Rpc + * open Idl *) + +(* type int = Rpc.Types.int *) +(* module Foo = Rpc.Idl *) + +(* +module CalcInterface(R : Idl.RPC) = struct + open R + + let int_p = Idl.Param.mk Rpc.Types.int + + let add = R.declare "add" + ["Add two numbers"] + (int_p @-> int_p @-> returning int_p Idl.DefaultError.err) + + let mul = R.declare "mul" + ["Multiply two numbers"] + (int_p @-> int_p @-> returning int_p Idl.DefaultError.err) + + let implementation = implement + { Idl.Interface.name = "Calc" + ; namespace = Some "Calc" + ; description = ["Calculator supporting addition and multiplication"] + ; version = (1,0,0) + } +end + +module M = Idl.IdM +module MyIdl = Idl.Make(M) + +module CalcClient : + sig + val add : + (Rpc.call -> Rpc.response) -> + int -> int -> (int, Idl.DefaultError.t) result + val mul : + (Rpc.call -> Rpc.response) -> + int -> int -> (int, Idl.DefaultError.t) result + end = CalcInterface(MyIdl.GenClient ()) +*) + +(* +module MyAPI(R : Idl.RPC) = struct + open R + open Idl + + let implementation = implement + { name = "MyAPI" + ; namespace = Some "MyApi" + ; version = (1, 0, 0) + ; description = + [ "This is an example showing how to use the IDL part of the ocaml-rpc " + ; "library. What goes here is a description of the interface we're " + ; "currently describing." + ] + ; + } + + (* We can define some named parameters here. These can be used in different + method declarations. *) + let i1 = Param.mk ~name:"i1" ~description:["Parameter i1"] Rpc.Types.int + let s1 = Param.mk ~name:"s1" ~description:["Parameter s1"] Rpc.Types.string + + (* Parameters don't _have_ to have names and descriptions, in which case they + will inherit from the name and description of the type. *) + let b1 = Param.mk Rpc.Types.bool + + (* For the following methods, we use the default error type for any errors + the methods may throw *) + let e1 = Idl.DefaultError.err + + (* `declare` is defined in the RPC module passed in, and can do several + different things. It is only the following two lines that actually do + anything in this module - the declarations of parameters above are useful + only in allowing the two declarations here to be succinct. *) + let api1 = declare "api1" ["Description 1"] (i1 @-> s1 @-> returning b1 e1) + let api2 = declare "api2" ["Description 2"] (s1 @-> returning i1 e1) + +end + +(* You can swap the rpc engine, by using a different monad here, + note however that if you are using an asynchronous one, like + lwt or async, you should also use their specific IO functions + including the print functions. *) + +(* You can easily put ExnM here and the code would stay unchanged*) +module M = Idl.IdM +module MyIdl = Idl.Make(M) + +(* By passing in different modules to the `MyAPI` functor above, we can + generate Client and Server modules. *) +module Client = MyAPI(MyIdl.GenClient ()) +module Server = MyAPI(MyIdl.GenServer ()) + +let _ = + (* The Client module generated above makes use of the Result.result type, + and hence it is convenient to use the Monadic `bind` and `return` + functions in Result.R *) + let open MyIdl in + + (* The server is used by associating the RPC declarations with their + implementations. The return type is expected to be Result.result, hence the + use of `ok` here. *) + Server.api1 (fun i s -> + Printf.printf "Received '%d' and '%s': returning '%b'\n" i s true; + ErrM.return true + ); + + Server.api2 (fun s -> + Printf.printf "Received '%s': returning '%d'\n%!" s 56; + ErrM.return 56 + ); + + (* The Server module has a 'server' function that can be used to service RPC + requests by passing the funcs value created above. *) + let rpc_fn = server Server.implementation in + + (* ... *) + + let open ErrM in + (* ... *) + return (Result.Ok ()) +*) + +(* TODO: Example2 *) + + +(* let () = + * print_string "Hello, World!\n" *) From ed43254d918132b5976a52b2a5864a331386fa9f Mon Sep 17 00:00:00 2001 From: Paul Young Date: Tue, 7 May 2019 13:03:19 -0700 Subject: [PATCH 0011/1176] [WIP] --- src/Makefile | 6 +- src/language_server/example2_client.ml | 45 +++++ src/language_server/example2_idl.ml | 93 ++++++++++ src/language_server/example2_server.ml | 103 +++++++++++ src/language_server/language_server_main.ml | 178 ++++++-------------- 5 files changed, 299 insertions(+), 126 deletions(-) create mode 100644 src/language_server/example2_client.ml create mode 100644 src/language_server/example2_idl.ml create mode 100644 src/language_server/example2_server.ml diff --git a/src/Makefile b/src/Makefile index ae831c3afbc..da77a5ff4b7 100644 --- a/src/Makefile +++ b/src/Makefile @@ -8,7 +8,7 @@ LIBRARY_NAME = actorscript LANGUAGE_SERVER_DIR = language_server LANGUAGE_SERVER_BIN = aslan LANGUAGE_SERVER_MAIN = language_server_main -LANGUAGE_SERVER_OPAM_PACKAGES = ppx_deriving_rpc rpclib +LANGUAGE_SERVER_OPAM_PACKAGES = ppx_deriving_rpc rpclib rpclib.json rpclib.cmdliner ASC = `pwd`/$(NAME) @@ -18,7 +18,7 @@ JS_OPAM_PACKAGES = js_of_ocaml js_of_ocaml-ppx MENHIR = menhir MENHIR_FLAGS = --infer --dump --explain --strict -OCAML_FLAGS = -cflags '-w +a-4-27-30-42-44-45-58 -warn-error +a' +OCAML_FLAGS = -cflags '' #'-w +a-4-27-30-42-44-45-58 -warn-error +a' OCAMLBUILD = ocamlbuild $(OCAML_FLAGS) \ -use-ocamlfind \ -plugin-tag 'package(bisect_ppx-ocamlbuild)' \ @@ -54,7 +54,7 @@ $(LANGUAGE_SERVER_BIN): $(LANGUAGE_SERVER_MAIN).${BUILD} mv $< $@ $(LANGUAGE_SERVER_MAIN).${BUILD}: sanity - $(OCAMLBUILD) $(LANGUAGE_SERVER_OPAM_PACKAGES:%=-pkg %) $(LANGUAGE_SERVER_DIR)/$@ + $(OCAMLBUILD) -tag thread $(LANGUAGE_SERVER_OPAM_PACKAGES:%=-pkg %) $(LANGUAGE_SERVER_DIR)/$@ $(LIBRARY_NAME).cma: sanity $(OCAMLBUILD) $@ diff --git a/src/language_server/example2_client.ml b/src/language_server/example2_client.ml new file mode 100644 index 00000000000..3a887db80c8 --- /dev/null +++ b/src/language_server/example2_client.ml @@ -0,0 +1,45 @@ +open Example2_idl + +module M = Idl.IdM +module MyIdl = Idl.Make(M) +module Client = API(MyIdl.GenClient ()) +module Cmds = API(Cmdlinergen.Gen ()) + +(* Use a binary 16-byte length to frame RPC messages *) +let binary_rpc path (call: Rpc.call) : Rpc.response = + let sockaddr = Unix.ADDR_UNIX path in + let s = Unix.socket Unix.PF_UNIX Unix.SOCK_STREAM 0 in + Unix.connect s sockaddr; + let ic = Unix.in_channel_of_descr s in + let oc = Unix.out_channel_of_descr s in + let msg_buf = Jsonrpc.string_of_call call in + let len = Printf.sprintf "%016d" (String.length msg_buf) in + output_string oc len; + output_string oc msg_buf; + flush oc; + let len_buf = Bytes.make 16 '\000' in + really_input ic len_buf 0 16; + let len = int_of_string (Bytes.unsafe_to_string len_buf) in + let msg_buf = Bytes.make len '\000' in + really_input ic msg_buf 0 len; + let (response: Rpc.response) = Jsonrpc.response_of_string (Bytes.unsafe_to_string msg_buf) in + response + +let default_cmd = + let doc = "a cli for an API" in + Cmdliner.Term.(ret (const (fun _ -> `Help (`Pager, None)) $ const ())), + Cmdliner.Term.info "cli" ~version:"1.6.1" ~doc + +let server_cmd = + let doc = "Start the server" in + Cmdliner.Term.(const Example2_server.start_server $ const ()), + Cmdliner.Term.info "server" ~doc + +let cli () = + let rpc = binary_rpc Example2_idl.sockpath in + Cmdliner.Term.eval_choice default_cmd ( + server_cmd + :: List.map + (fun t -> let (term, info) = t rpc in (Cmdliner.Term.(term $ const ()), info)) + (Cmds.implementation ()) + ) diff --git a/src/language_server/example2_idl.ml b/src/language_server/example2_idl.ml new file mode 100644 index 00000000000..9946061fcfd --- /dev/null +++ b/src/language_server/example2_idl.ml @@ -0,0 +1,93 @@ +(* https://github.com/mirage/ocaml-rpc/blob/4d542cb7b0c42a62196c6043ba556de54c1b7820/example/example2_idl.ml *) +(* Example2 *) + +(* In this one we're going to use the PPX to generate the structure and + variant values rather than doing it by hand as in example1. We'll also + actually create a client and server process. *) + +open Rpc +open Idl + +let sockpath = "/tmp/rpcsock" + +module Datatypes = struct + module Query = struct + type t = + { name: string + ; vendor: string + ; version: string + ; features: string list + ; instance_id: string + } [@@deriving rpcty] (* TODO: rpc? *) + end + + type errty = + | InternalError of string + | FrobnicationFailed + | OperationInProgress + [@@deriving rpcty] (* TODO: rpc? *) + + exception DatatypeError of errty + + let err = Error. + { def = errty + ; raiser = (function | e -> raise (DatatypeError e)) + ; matcher = function | DatatypeError e -> Some e | _ -> None + } +end + +module API(R : RPC) = struct + open R + + let description = Interface. + { name = "API" + ; namespace = None + ; description = [ "This is another example of the ocaml-rpc IDL." ] + ; version = (1, 0, 0) + } + + let implementation = implement description + + let query_p = Param.mk + ~name: "query" + ~description: ["The result of the query operation"] + Datatypes.Query.t + + let unit_p = Param.mk + Types.unit + + let string_p = Param.mk + Types.string + + let domid_p = Param.mk + ~name: "domid" + ~description: ["The domid on which to operate"] + Types.int64 + + let vm_p = Param.mk + ~name: "vm" + ~description: ["The uuid of the VM"] + Types.string + + let vm_desc = Param.mk + ~name: "description" + ~description: ["The description of the VM"] + Types.string + + let err = Datatypes.err + + let query = declare + "query" + ["Query the details of the server."] + (unit_p @-> returning query_p err) + + let diagnostics = declare + "get_diagnostics" + ["Get diagnostics information from the server."] + (unit_p @-> returning string_p err) + + let test = declare + "test" + ["A test of a bit more of the IDL stuff."] + (domid_p @-> vm_p @-> vm_desc @-> returning query_p err) +end diff --git a/src/language_server/example2_server.ml b/src/language_server/example2_server.ml new file mode 100644 index 00000000000..13078ed602b --- /dev/null +++ b/src/language_server/example2_server.ml @@ -0,0 +1,103 @@ +(* https://github.com/mirage/ocaml-rpc/blob/4d542cb7b0c42a62196c6043ba556de54c1b7820/example/example2_server.ml *) +open Example2_idl + +(* You can swap the rpc engine, by using a different monad here, + note however that if you are using an asynchoronous one, like + lwt or async, you should also use their specific IO functions + including print functions. *) +module M = Idl.IdM (* You can easily but ExnM here and the code would stay unchanged. *) +module MyIdl = Idl.Make(M) +module Server = API(MyIdl.GenServer ()) + +(* Implementations of the methods *) +let query () = + let open Datatypes.Query in + Printf.printf "Received query API call\n%!"; + let result = + { name = "Example2 server" + ; vendor = "This is the example server showing how to use the ocaml-rpc IDL." + ; version = "2.0.0" + ; features = + [ "defaults" + ; "upgradability" + ] + ; instance_id = string_of_int (Random.int 1000) + } in + MyIdl.ErrM.return result + +let diagnostics () = + MyIdl.ErrM.return "This should be the diagnostics of the server." + +let test i s1 s2 = + Printf.printf "%Ld %s %s\n%!" i s1 s2; + query () + +(* Utility and general non-specific server bits and bobs *) +let finally f g = + try + let result = f () in + g (); + result + with e -> + g (); + raise e + +let mkdir_rec dir perm = + let rec p_mkdir dir = + let p_name = Filename.dirname dir in + if p_name <> "/" && p_name <> "." + then p_mkdir p_name; + (try Unix.mkdir dir perm with Unix.Unix_error(Unix.EEXIST, _, _) -> ()) in + p_mkdir dir + +let binary_handler process s = + let ic = Unix.in_channel_of_descr s in + let oc = Unix.out_channel_of_descr s in + (* Read a 16 byte length encoded as a string *) + let len_buf = Bytes.make 16 '\000' in + really_input ic len_buf 0 (Bytes.length len_buf); + let len = int_of_string (Bytes.unsafe_to_string len_buf) in + let msg_buf = Bytes.make len '\000' in + really_input ic msg_buf 0 (Bytes.length msg_buf); + let (>>=) = M.bind in + process msg_buf >>= fun result -> + let len_buf = Printf.sprintf "%016d" (String.length result) in + output_string oc len_buf; + output_string oc result; + flush oc; + M.return () + +let serve_requests rpcfn path = + (try Unix.unlink path with Unix.Unix_error(Unix.ENOENT, _, _) -> ()); + mkdir_rec (Filename.dirname path) 0o0755; + let sock = Unix.socket Unix.PF_UNIX Unix.SOCK_STREAM 0 in + Unix.bind sock (Unix.ADDR_UNIX path); + Unix.listen sock 5; + Printf.fprintf stdout "Listening on %s" path; + while true do + let this_connection, _ = Unix.accept sock in + let (_: Thread.t) = Thread.create + (fun () -> + finally + (* Here I am calling M.run to make sure that I am running the process, + this is not much of a problem with IdM or ExnM, but in general you + should ensure that the computation is started by a runner. *) + (fun () -> binary_handler rpcfn this_connection |> M.run) + (fun () -> Unix.close this_connection) + ) () in + () + done + +let start_server () = + Server.query query; + Server.diagnostics diagnostics; + Server.test test; + + let rpc_fn = MyIdl.server Server.implementation in + + let process x = + let open M in + rpc_fn (Jsonrpc.call_of_string (Bytes.unsafe_to_string x)) + >>= fun response -> Jsonrpc.string_of_response response |> return in + + serve_requests process sockpath diff --git a/src/language_server/language_server_main.ml b/src/language_server/language_server_main.ml index b5eb2f6f43e..719b6e214ac 100644 --- a/src/language_server/language_server_main.ml +++ b/src/language_server/language_server_main.ml @@ -1,137 +1,69 @@ -(* TODO: Move to protocol module *) +(* https://microsoft.github.io/language-server-protocol/specification *) -(* type t = { foo: int; } [@@deriving rpcty] *) -(* type t = { foo: int; } [@@deriving rpc] *) +open Rpc +open Idl -(* Jsonrpc.to_string (rpc_of_t x) *) - -(* open Rpc - * open Idl *) - -(* type int = Rpc.Types.int *) -(* module Foo = Rpc.Idl *) - -(* -module CalcInterface(R : Idl.RPC) = struct - open R - - let int_p = Idl.Param.mk Rpc.Types.int - - let add = R.declare "add" - ["Add two numbers"] - (int_p @-> int_p @-> returning int_p Idl.DefaultError.err) - - let mul = R.declare "mul" - ["Multiply two numbers"] - (int_p @-> int_p @-> returning int_p Idl.DefaultError.err) +module ResponseError(*(D : RPC.t)*) = struct + type t = + { code: int + ; message: string + (* ; data: D option *) (* FIXME *) + } [@@deriving rpcty] +end - let implementation = implement - { Idl.Interface.name = "Calc" - ; namespace = Some "Calc" - ; description = ["Calculator supporting addition and multiplication"] - ; version = (1,0,0) - } +module InitializeParams = struct + type t = + { processId: int option (* FIXME *) + } [@@deriving rpcty] end -module M = Idl.IdM -module MyIdl = Idl.Make(M) +module ServerCapabilities = struct + type t = + { textDocumentSync: int option (* FIXME *) + } [@@deriving rpcty] +end -module CalcClient : - sig - val add : - (Rpc.call -> Rpc.response) -> - int -> int -> (int, Idl.DefaultError.t) result - val mul : - (Rpc.call -> Rpc.response) -> - int -> int -> (int, Idl.DefaultError.t) result - end = CalcInterface(MyIdl.GenClient ()) -*) +module InitializeResult = struct + type t = + { capabilities: ServerCapabilities.t (* FIXME *) + } [@@deriving rpcty] +end -(* -module MyAPI(R : Idl.RPC) = struct +module API(R : RPC) = struct open R - open Idl - - let implementation = implement - { name = "MyAPI" - ; namespace = Some "MyApi" - ; version = (1, 0, 0) - ; description = - [ "This is an example showing how to use the IDL part of the ocaml-rpc " - ; "library. What goes here is a description of the interface we're " - ; "currently describing." - ] - ; - } - - (* We can define some named parameters here. These can be used in different - method declarations. *) - let i1 = Param.mk ~name:"i1" ~description:["Parameter i1"] Rpc.Types.int - let s1 = Param.mk ~name:"s1" ~description:["Parameter s1"] Rpc.Types.string - - (* Parameters don't _have_ to have names and descriptions, in which case they - will inherit from the name and description of the type. *) - let b1 = Param.mk Rpc.Types.bool - - (* For the following methods, we use the default error type for any errors - the methods may throw *) - let e1 = Idl.DefaultError.err - - (* `declare` is defined in the RPC module passed in, and can do several - different things. It is only the following two lines that actually do - anything in this module - the declarations of parameters above are useful - only in allowing the two declarations here to be succinct. *) - let api1 = declare "api1" ["Description 1"] (i1 @-> s1 @-> returning b1 e1) - let api2 = declare "api2" ["Description 2"] (s1 @-> returning i1 e1) + (* FIXME: use ResponseError *) + let error = Idl.DefaultError.err + + (* FIXME *) + let initialize_params = Param.mk + ~name:"initialize_params" + InitializeParams.t + + (* FIXME *) + let server_capabilities = Param.mk + ~name:"server_capabilities" + ServerCapabilities.t + + (* FIXME *) + let initialize_result = Param.mk + ~name:"initialize_result" + InitializeResult.t + + let initialize = declare + "initialize" + [ "The initialize request is sent as the first request from the client to " + ; "the server." + ] + (initialize_params @-> returning initialize_result error) end -(* You can swap the rpc engine, by using a different monad here, - note however that if you are using an asynchronous one, like - lwt or async, you should also use their specific IO functions - including the print functions. *) - -(* You can easily put ExnM here and the code would stay unchanged*) -module M = Idl.IdM -module MyIdl = Idl.Make(M) - -(* By passing in different modules to the `MyAPI` functor above, we can - generate Client and Server modules. *) -module Client = MyAPI(MyIdl.GenClient ()) -module Server = MyAPI(MyIdl.GenServer ()) - -let _ = - (* The Client module generated above makes use of the Result.result type, - and hence it is convenient to use the Monadic `bind` and `return` - functions in Result.R *) - let open MyIdl in - - (* The server is used by associating the RPC declarations with their - implementations. The return type is expected to be Result.result, hence the - use of `ok` here. *) - Server.api1 (fun i s -> - Printf.printf "Received '%d' and '%s': returning '%b'\n" i s true; - ErrM.return true - ); - - Server.api2 (fun s -> - Printf.printf "Received '%s': returning '%d'\n%!" s 56; - ErrM.return 56 - ); - - (* The Server module has a 'server' function that can be used to service RPC - requests by passing the funcs value created above. *) - let rpc_fn = server Server.implementation in - - (* ... *) - - let open ErrM in - (* ... *) - return (Result.Ok ()) -*) +(* let _ = Example2_client.cli () *) -(* TODO: Example2 *) +let () = + print_string "Hello, World!\n"; + (* TODO: basic sanity check *) + (* print_string (Rpc.string_of_call ...) *) + (* print_string (Rpc.string_of_response ...) *) -(* let () = - * print_string "Hello, World!\n" *) From df91cf51b16efad3fa2b841b87f017bab53363be Mon Sep 17 00:00:00 2001 From: Christoph Hegemann Date: Thu, 9 May 2019 23:26:18 +0200 Subject: [PATCH 0012/1176] [WIP] progress --- default.nix | 2 - src/language_server/language_server_main.ml | 96 +++++++++++++++++++-- 2 files changed, 90 insertions(+), 8 deletions(-) diff --git a/default.nix b/default.nix index 3d58507066e..abc785ec113 100644 --- a/default.nix +++ b/default.nix @@ -110,8 +110,6 @@ in rec { - rpclib_core = ocaml-rpc.rpclib_core; - language-server = stdenv.mkDerivation { name = "actorscript-language-server"; src = sourceByRegex ./. (native_src_files ++ [ diff --git a/src/language_server/language_server_main.ml b/src/language_server/language_server_main.ml index 719b6e214ac..cb61149e1f3 100644 --- a/src/language_server/language_server_main.ml +++ b/src/language_server/language_server_main.ml @@ -13,7 +13,7 @@ end module InitializeParams = struct type t = - { processId: int option (* FIXME *) + { processId: int (* FIXME *) } [@@deriving rpcty] end @@ -29,15 +29,29 @@ module InitializeResult = struct } [@@deriving rpcty] end +type show_message_params = + { type_: int [@key "type"] (* FIXME *) + ; message: string + } [@@deriving rpc] + module API(R : RPC) = struct open R + let description = Interface. + { name = "API" + ; namespace = None + ; description = [ "ActorScript LSP" ] + ; version = (1, 0, 0) + } + + let implementation = implement description + (* FIXME: use ResponseError *) let error = Idl.DefaultError.err (* FIXME *) let initialize_params = Param.mk - ~name:"initialize_params" + (* ~name:"initialize_params" *) InitializeParams.t (* FIXME *) @@ -50,20 +64,90 @@ module API(R : RPC) = struct ~name:"initialize_result" InitializeResult.t + (* let show_message_params = Param.mk + * ShowMessageParams.t *) + + let unit_p = Param.mk Types.unit + let initialize = declare "initialize" [ "The initialize request is sent as the first request from the client to " ; "the server." ] (initialize_params @-> returning initialize_result error) + + (* let show_message = declare + * "window/showMessage" + * [ "The show message notification is sent from a " + * ; "server to a client to ask the client to display a particular message in the user interface." + * ] + * (show_message_params @-> returning unit_p error) *) end -(* let _ = Example2_client.cli () *) +module M = Idl.IdM (* You can easily but ExnM here and the code would stay unchanged. *) +module MyIdl = Idl.Make(M) +module Server = API(MyIdl.GenServer ()) +module Client = API(MyIdl.GenClient ()) -let () = - print_string "Hello, World!\n"; +let oc = open_out_gen [Open_append; Open_creat] 0o666 "ls.log" +let log_to_file txt = + Printf.fprintf oc "%s\n" txt; + flush oc + +let respond out = + let cl = "Content-Length: " ^ string_of_int (String.length out) ^ "\r\n\r\n" in + print_string cl; + print_string out; + flush stdout + +let my_start_server handler = + let rec server_loop () = + let clength = read_line () in + log_to_file clength; + let cl = "Content-Length: " in + let cll = String.length cl in + let num = + (int_of_string + (String.trim + (String.sub + clength + cll + (String.length(clength) - cll - 1)))) + 2 in + let buffer = Buffer.create num in + Buffer.add_channel buffer stdin num; + let raw = Buffer.contents buffer in + log_to_file raw; + (* Printf.fprintf oc "%s\n" (String.trim raw); *) + let open M in + handler (Jsonrpc.call_of_string raw) + >>= fun response -> let res = Jsonrpc.string_of_response ~version:V2 response in + log_to_file res; + let mes_res = + (Jsonrpc.string_of_call ~version:V2 + (Rpc.call "window/showMessage" + [ rpc_of_show_message_params { type_ = 2; message = "Handled command"}; ])); in + log_to_file mes_res; + respond res; + respond mes_res; + return res; + server_loop () + in server_loop () + +let initialize InitializeParams.{ processId } = + log_to_file (string_of_int processId); + MyIdl.ErrM.return (InitializeResult.{ capabilities = ServerCapabilities.{ textDocumentSync = None }}) + (* MyIdl.ErrM.return (ShowMessageParams.{ type_ = 2; message = "Hello from aslan"}) *) + +let _ = + Server.initialize initialize; + let rpc_fn = MyIdl.server Server.implementation + in my_start_server rpc_fn; + (* my_start_server (); *) + + +(* let () = + * print_string "Hello, World!\n"; *) (* TODO: basic sanity check *) (* print_string (Rpc.string_of_call ...) *) (* print_string (Rpc.string_of_response ...) *) - From f33109f8b6fe85ec31e429982beb414590c97ffb Mon Sep 17 00:00:00 2001 From: Paul Young Date: Wed, 15 May 2019 12:01:34 -0700 Subject: [PATCH 0013/1176] Add language server derivation --- default.nix | 197 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 148 insertions(+), 49 deletions(-) diff --git a/default.nix b/default.nix index abc785ec113..b23297e0da5 100644 --- a/default.nix +++ b/default.nix @@ -1,8 +1,11 @@ -{ nixpkgs ? (import ./nix/nixpkgs.nix) {}, +{ nixpkgs ? (import ./nix/nixpkgs.nix).nixpkgs {}, test-dvm ? true, dvm ? null, + export-shell ? false, }: +let llvm = import ./nix/llvm.nix { system = nixpkgs.system; }; in + let stdenv = nixpkgs.stdenv; in let sourceByRegex = src: regexes: builtins.path @@ -14,18 +17,18 @@ let sourceByRegex = src: regexes: builtins.path ( type == "directory" && match (relPath + "/") != null || match relPath != null); }; in -let ocaml_wasm = (import ./nix/ocaml-wasm.nix) { +let ocaml_wasm = import ./nix/ocaml-wasm.nix { inherit (nixpkgs) stdenv fetchFromGitHub ocaml; inherit (nixpkgs.ocamlPackages) findlib ocamlbuild; }; in -let ocaml_vlq = (import ./nix/ocaml-vlq.nix) { +let ocaml_vlq = import ./nix/ocaml-vlq.nix { inherit (nixpkgs) stdenv fetchFromGitHub ocaml dune; inherit (nixpkgs.ocamlPackages) findlib; }; in -let ocaml_bisect_ppx = (import ./nix/ocaml-bisect_ppx.nix) nixpkgs; in -let ocaml_bisect_ppx-ocamlbuild = (import ./nix/ocaml-bisect_ppx-ocamlbuild.nix) nixpkgs; in +let ocaml_bisect_ppx = import ./nix/ocaml-bisect_ppx.nix nixpkgs; in +let ocaml_bisect_ppx-ocamlbuild = import ./nix/ocaml-bisect_ppx-ocamlbuild.nix nixpkgs; in let ocaml-rpc = import ./nix/ocaml-rpc.nix { pkgs = nixpkgs; }; in @@ -38,9 +41,9 @@ let real-dvm = let dev = builtins.fetchGit { url = "ssh://git@github.com/dfinity-lab/dev"; ref = "master"; - rev = "b6f587c3303b9f2585548e5fcb98f907b0275219"; + rev = "aff35b2a015108f7d1d694471ccaf3ffd6f0340c"; }; in - (import dev {}).dvm + (import dev { system = nixpkgs.system; }).dvm else null else dvm; in @@ -59,14 +62,13 @@ let commonBuildInputs = [ ]; in let - native_src_files =[ + asc_src_files = [ "src/" "src/Makefile.*" "src/.*.ml" "src/.*.mli" "src/.*.mly" "src/.*.mll" - "src/.*.mllib" "src/.*.mlpack" "src/_tags" "test/" @@ -76,13 +78,15 @@ let "test/" "test/.*Makefile.*" "test/quick.mk" - "test/(fail|run|run-dfinity|repl)/" - "test/(fail|run|run-dfinity|repl)/lib/" - "test/(fail|run|run-dfinity|repl)/lib/dir/" - "test/(fail|run|run-dfinity|repl)/.*.as" - "test/(fail|run|run-dfinity|repl)/.*.sh" - "test/(fail|run|run-dfinity|repl)/ok/" - "test/(fail|run|run-dfinity|repl)/ok/.*.ok" + "test/(fail|run|run-dfinity|repl|ld)/" + "test/(fail|run|run-dfinity|repl|ld)/lib/" + "test/(fail|run|run-dfinity|repl|ld)/lib/dir/" + "test/(fail|run|run-dfinity|repl|ld)/.*.as" + "test/(fail|run|run-dfinity|repl|ld)/.*.sh" + "test/(fail|run|run-dfinity|repl|ld)/[^/]*.wat" + "test/(fail|run|run-dfinity|repl|ld)/[^/]*.c" + "test/(fail|run|run-dfinity|repl|ld)/ok/" + "test/(fail|run|run-dfinity|repl|ld)/ok/.*.ok" "test/.*.sh" ]; samples_files = [ @@ -106,18 +110,34 @@ let "stdlib/examples/produce-exchange/README.md" ]; + libtommath = nixpkgs.fetchFromGitHub { + owner = "libtom"; + repo = "libtommath"; + rev = "9e1a75cfdc4de614eaf4f88c52d8faf384e54dd0"; + sha256 = "0qwmzmp3a2rg47pnrsls99jpk5cjj92m75alh1kfhcg104qq6w3d"; + }; + + llvmBuildInputs = [ + llvm.clang_9 + llvm.lld_9 + ]; + + llvmEnv = '' + export CLANG="clang-9" + export WASM_LD=wasm-ld + ''; in rec { language-server = stdenv.mkDerivation { name = "actorscript-language-server"; - src = sourceByRegex ./. (native_src_files ++ [ + src = sourceByRegex ./. (asc_src_files ++ [ "^src/language_server/$" "^src/language_server/.*\.ml(i|l|pack|y){0,1}$" ]); - nativeBuildInputs = native.nativeBuildInputs; - buildInputs = native.buildInputs + nativeBuildInputs = asc-bin.nativeBuildInputs; + buildInputs = asc-bin.buildInputs ++ ocaml-rpc.ppx_deriving_rpc.buildInputs ++ [ ocaml-rpc.ppx_deriving_rpc ]; buildPhase = '' @@ -129,33 +149,58 @@ rec { ''; }; - library = native.overrideAttrs (oldAttrs: { - name = "actorscript.mllib"; - buildPhase = '' - make -C src actorscript.cma + rts = stdenv.mkDerivation { + name = "asc-rts"; + + src = sourceByRegex ./rts [ + "rts.c" + "Makefile" + "includes/" + "includes/.*.h" + ]; + + nativeBuildInputs = [ nixpkgs.makeWrapper ]; + + buildInputs = llvmBuildInputs; + + preBuild = '' + ${llvmEnv} + export TOMMATHSRC=${libtommath} ''; + installPhase = '' - mkdir -p $out - cp src/actorscript.cma $out + mkdir -p $out/rts + cp as-rts.wasm $out/rts ''; - }); + }; - native = stdenv.mkDerivation { - name = "asc"; + asc-bin = stdenv.mkDerivation { + name = "asc-bin"; - src = sourceByRegex ./. native_src_files; + src = sourceByRegex ./. asc_src_files; nativeBuildInputs = [ nixpkgs.makeWrapper ]; buildInputs = commonBuildInputs; buildPhase = '' - make -C src BUILD=native asc + make -C src BUILD=native asc as-ld ''; installPhase = '' mkdir -p $out/bin cp src/asc $out/bin + cp src/as-ld $out/bin + ''; + }; + + native = nixpkgs.symlinkJoin { + name = "asc"; + paths = [ asc-bin rts ]; + buildInputs = [ nixpkgs.makeWrapper ]; + postBuild = '' + wrapProgram $out/bin/asc \ + --set-default ASC_RTS "$out/rts/as-rts.wasm" ''; }; @@ -175,18 +220,21 @@ rec { nixpkgs.perl filecheck ] ++ - (if test-dvm then [ real-dvm ] else []); + (if test-dvm then [ real-dvm ] else []) ++ + llvmBuildInputs; buildPhase = '' - patchShebangs . - asc --version - make -C samples ASC=asc all - '' + - (if test-dvm - then '' - make -C test ASC=asc parallel + patchShebangs . + ${llvmEnv} + export ASC=asc + export AS_LD=as-ld + asc --version + make -C samples all + '' + + (if test-dvm then '' + make -C test parallel '' else '' - make -C test ASC=asc quick + make -C test quick ''); installPhase = '' @@ -194,8 +242,8 @@ rec { ''; }; - native-coverage = native.overrideAttrs (oldAttrs: { - name = "asc-coverage"; + asc-bin-coverage = asc-bin.overrideAttrs (oldAttrs: { + name = "asc-bin-coverage"; buildPhase = "export BISECT_COVERAGE=YES;" + oldAttrs.buildPhase; @@ -205,8 +253,18 @@ rec { ''; }); + native-coverage = nixpkgs.symlinkJoin { + name = "asc-covergage"; + paths = [ asc-bin-coverage rts ]; + buildInputs = [ nixpkgs.makeWrapper ]; + postBuild = '' + wrapProgram $out/bin/asc \ + --set-default ASC_RTS "$out/rts/as-rts.wasm" + ''; + }; + coverage-report = stdenv.mkDerivation { - name = "native.coverage"; + name = "coverage-report"; src = sourceByRegex ./. ( test_files ++ @@ -220,12 +278,16 @@ rec { nixpkgs.perl ocaml_bisect_ppx ] ++ - (if test-dvm then [ real-dvm ] else []); + (if test-dvm then [ real-dvm ] else []) ++ + llvmBuildInputs; buildPhase = '' patchShebangs . + ${llvmEnv} + export ASC=asc + export AS_LD=as-ld ln -vs ${native-coverage}/src src - make -C test ASC=asc coverage + make -C test coverage ''; installPhase = '' @@ -237,14 +299,14 @@ rec { }; - js = native.overrideAttrs (oldAttrs: { + js = asc-bin.overrideAttrs (oldAttrs: { name = "asc.js"; buildInputs = commonBuildInputs ++ [ nixpkgs.ocamlPackages.js_of_ocaml nixpkgs.ocamlPackages.js_of_ocaml-ocamlbuild nixpkgs.ocamlPackages.js_of_ocaml-ppx - nixpkgs.nodejs + nixpkgs.nodejs-10_x ]; buildPhase = '' @@ -253,11 +315,14 @@ rec { installPhase = '' mkdir -p $out - cp src/asc.js $out + cp -v src/asc.js $out + cp -vr ${rts}/rts $out ''; + doInstallCheck = true; + installCheckPhase = '' - NODE_PATH=$out/ node test/node-test.js + NODE_PATH=$out node --experimental-wasm-mut-global --experimental-wasm-mv test/node-test.js ''; }); @@ -359,6 +424,40 @@ rec { all-systems-go = nixpkgs.releaseTools.aggregate { name = "all-systems-go"; - constituents = [ native js native_test coverage-report stdlib-reference produce-exchange users-guide ]; + constituents = [ + native + js + native_test + coverage-report + rts + stdlib-reference + produce-exchange + users-guide + ]; }; + + shell = if export-shell then nixpkgs.mkShell { + + # + # Since building asc, and testing it, are two different derivation in default.nix + # we have to create a fake derivation for shell.nix that commons up the build dependencies + # of the two to provide a build environment that offers both + # + # Would not be necessary if nix-shell would take more than one `-A` flag, see + # https://github.com/NixOS/nix/issues/955 + # + + buildInputs = nixpkgs.lib.lists.unique (builtins.filter (i: i != native) ( + asc-bin.buildInputs ++ + rts.buildInputs ++ + native_test.buildInputs ++ + users-guide.buildInputs ++ + [ nixpkgs.ncurses ] + )); + + shellHook = llvmEnv; + TOMMATHSRC = libtommath; + NIX_FONTCONFIG_FILE = users-guide.NIX_FONTCONFIG_FILE; + } else null; + } From a426335541c889280472e27338773af4e92485f9 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Wed, 15 May 2019 16:24:26 -0400 Subject: [PATCH 0014/1176] correct CLI string --- src/main.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.ml b/src/main.ml index 4d7bc626033..3c6dd1ff36a 100644 --- a/src/main.ml +++ b/src/main.ml @@ -46,7 +46,7 @@ let argspec = Arg.align "--profile-line-prefix", Arg.Set_string Flags.profile_line_prefix, " prefix each profile line with the given string "; "--profile-field", Arg.String (fun n -> Flags.profile_field_names := n :: !Flags.profile_field_names), - " suffix each profile line with the given string "; + " profile file includes the given field from the program result "; "-iR", Arg.Set Flags.interpret_ir, " interpret the lowered code"; "-no-await", Arg.Clear Flags.await_lowering, " no await-lowering (with -iR)"; "-no-async", Arg.Clear Flags.async_lowering, " no async-lowering (with -iR)"; From 255e44f538f4f84b755b794e29a3edc2680da295 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Wed, 15 May 2019 15:14:35 -0700 Subject: [PATCH 0015/1176] Add .merlin file --- src/language_server/.merlin | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 src/language_server/.merlin diff --git a/src/language_server/.merlin b/src/language_server/.merlin new file mode 100644 index 00000000000..de8ead383d8 --- /dev/null +++ b/src/language_server/.merlin @@ -0,0 +1,2 @@ +B ../_build +PKG wasm num vlq yojson bisect_ppx-ocamlbuild ppx_deriving_rpc rpclib rpclib.json rpclib.cmdliner From e6f0f695f4e98686f9108bc14117d919e39d76be Mon Sep 17 00:00:00 2001 From: Paul Young Date: Wed, 15 May 2019 15:15:02 -0700 Subject: [PATCH 0016/1176] Add language-server to nix shell for direnv --- default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/default.nix b/default.nix index b23297e0da5..4ce99ec04bf 100644 --- a/default.nix +++ b/default.nix @@ -458,6 +458,7 @@ rec { shellHook = llvmEnv; TOMMATHSRC = libtommath; NIX_FONTCONFIG_FILE = users-guide.NIX_FONTCONFIG_FILE; + language-server = language-server; } else null; } From e022951dc2cfb5b785667b63e02c63275a3e33ce Mon Sep 17 00:00:00 2001 From: Paul Young Date: Wed, 15 May 2019 15:15:46 -0700 Subject: [PATCH 0017/1176] Attempt to showMessage after receiving initialized --- src/language_server/language_server_main.ml | 22 +++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/language_server/language_server_main.ml b/src/language_server/language_server_main.ml index cb61149e1f3..1557fd37a7f 100644 --- a/src/language_server/language_server_main.ml +++ b/src/language_server/language_server_main.ml @@ -64,6 +64,8 @@ module API(R : RPC) = struct ~name:"initialize_result" InitializeResult.t + (* let initialized_params = Param.mk *) + (* let show_message_params = Param.mk * ShowMessageParams.t *) @@ -119,17 +121,21 @@ let my_start_server handler = log_to_file raw; (* Printf.fprintf oc "%s\n" (String.trim raw); *) let open M in - handler (Jsonrpc.call_of_string raw) + let call = Jsonrpc.call_of_string raw in + if call.name = "initialized" + then + let mes_res = + (Jsonrpc.string_of_call ~version:V2 + (Rpc.call "window/showMessage" + [ rpc_of_show_message_params { type_ = 2; message = "Handled command"}; ])); in + log_to_file mes_res; + respond mes_res; + server_loop () + else + handler call >>= fun response -> let res = Jsonrpc.string_of_response ~version:V2 response in log_to_file res; - let mes_res = - (Jsonrpc.string_of_call ~version:V2 - (Rpc.call "window/showMessage" - [ rpc_of_show_message_params { type_ = 2; message = "Handled command"}; ])); in - log_to_file mes_res; respond res; - respond mes_res; - return res; server_loop () in server_loop () From d5b7eb1df7ce2699eac08441184f38b6baa93094 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Wed, 15 May 2019 15:17:16 -0700 Subject: [PATCH 0018/1176] Remove attempt at building a library from Makefile --- src/Makefile | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Makefile b/src/Makefile index da77a5ff4b7..59b44da8185 100644 --- a/src/Makefile +++ b/src/Makefile @@ -3,8 +3,6 @@ BUILD = byte MAIN = main JS_MAIN = js_main -LIBRARY_NAME = actorscript - LANGUAGE_SERVER_DIR = language_server LANGUAGE_SERVER_BIN = aslan LANGUAGE_SERVER_MAIN = language_server_main @@ -56,9 +54,6 @@ $(LANGUAGE_SERVER_BIN): $(LANGUAGE_SERVER_MAIN).${BUILD} $(LANGUAGE_SERVER_MAIN).${BUILD}: sanity $(OCAMLBUILD) -tag thread $(LANGUAGE_SERVER_OPAM_PACKAGES:%=-pkg %) $(LANGUAGE_SERVER_DIR)/$@ -$(LIBRARY_NAME).cma: sanity - $(OCAMLBUILD) $@ - sanity: ocamlfind query $(OPAM_PACKAGES) From a7d9e39ef2d75052a522e91b3a8ad43fd5add2c3 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Wed, 15 May 2019 16:08:44 -0700 Subject: [PATCH 0019/1176] Move language server to asc --- default.nix | 50 +++------ src/Makefile | 16 +-- ...guage_server_main.ml => languageServer.ml} | 2 +- src/language_server/.merlin | 2 - src/language_server/example2_client.ml | 45 -------- src/language_server/example2_idl.ml | 93 ---------------- src/language_server/example2_server.ml | 103 ------------------ src/main.ml | 2 + 8 files changed, 23 insertions(+), 290 deletions(-) rename src/{language_server/language_server_main.ml => languageServer.ml} (99%) delete mode 100644 src/language_server/.merlin delete mode 100644 src/language_server/example2_client.ml delete mode 100644 src/language_server/example2_idl.ml delete mode 100644 src/language_server/example2_server.ml diff --git a/default.nix b/default.nix index 4ce99ec04bf..a296eaf5388 100644 --- a/default.nix +++ b/default.nix @@ -62,18 +62,6 @@ let commonBuildInputs = [ ]; in let - asc_src_files = [ - "src/" - "src/Makefile.*" - "src/.*.ml" - "src/.*.mli" - "src/.*.mly" - "src/.*.mll" - "src/.*.mlpack" - "src/_tags" - "test/" - "test/node-test.js" - ]; test_files = [ "test/" "test/.*Makefile.*" @@ -130,25 +118,6 @@ in rec { - language-server = stdenv.mkDerivation { - name = "actorscript-language-server"; - src = sourceByRegex ./. (asc_src_files ++ [ - "^src/language_server/$" - "^src/language_server/.*\.ml(i|l|pack|y){0,1}$" - ]); - nativeBuildInputs = asc-bin.nativeBuildInputs; - buildInputs = asc-bin.buildInputs - ++ ocaml-rpc.ppx_deriving_rpc.buildInputs - ++ [ ocaml-rpc.ppx_deriving_rpc ]; - buildPhase = '' - make -C src BUILD=native aslan - ''; - installPhase = '' - mkdir -p $out/bin - cp src/aslan $out/bin - ''; - }; - rts = stdenv.mkDerivation { name = "asc-rts"; @@ -177,11 +146,25 @@ rec { asc-bin = stdenv.mkDerivation { name = "asc-bin"; - src = sourceByRegex ./. asc_src_files; + src = sourceByRegex ./. [ + "src/" + "src/Makefile.*" + "src/.*.ml" + "src/.*.mli" + "src/.*.mly" + "src/.*.mll" + "src/.*.mlpack" + "src/_tags" + "^src/language_server/$" + "test/" + "test/node-test.js" + ]; nativeBuildInputs = [ nixpkgs.makeWrapper ]; - buildInputs = commonBuildInputs; + buildInputs = commonBuildInputs + ++ ocaml-rpc.ppx_deriving_rpc.buildInputs + ++ [ ocaml-rpc.ppx_deriving_rpc ]; buildPhase = '' make -C src BUILD=native asc as-ld @@ -458,7 +441,6 @@ rec { shellHook = llvmEnv; TOMMATHSRC = libtommath; NIX_FONTCONFIG_FILE = users-guide.NIX_FONTCONFIG_FILE; - language-server = language-server; } else null; } diff --git a/src/Makefile b/src/Makefile index 59b44da8185..ad7a913176f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -3,15 +3,11 @@ BUILD = byte MAIN = main JS_MAIN = js_main -LANGUAGE_SERVER_DIR = language_server -LANGUAGE_SERVER_BIN = aslan -LANGUAGE_SERVER_MAIN = language_server_main -LANGUAGE_SERVER_OPAM_PACKAGES = ppx_deriving_rpc rpclib rpclib.json rpclib.cmdliner - ASC = `pwd`/$(NAME) OPAM_PACKAGES = wasm num vlq yojson bisect_ppx-ocamlbuild JS_OPAM_PACKAGES = js_of_ocaml js_of_ocaml-ppx +LANGUAGE_SERVER_OPAM_PACKAGES = ppx_deriving_rpc rpclib rpclib.json rpclib.cmdliner MENHIR = menhir MENHIR_FLAGS = --infer --dump --explain --strict @@ -24,7 +20,9 @@ OCAMLBUILD = ocamlbuild $(OCAML_FLAGS) \ -I src \ -I lib \ $(OPAM_PACKAGES:%=-pkg %) \ - -tags debug + -tags debug \ + -tag thread \ + $(LANGUAGE_SERVER_OPAM_PACKAGES:%=-pkg %) .PHONY: all parallel quick clean test test-parallel test-quick @@ -48,12 +46,6 @@ $(NAME).js: $(JS_MAIN).byte $(JS_MAIN).byte: $(JS_MAIN).ml sanity $(OCAMLBUILD) $(JS_OPAM_PACKAGES:%=-pkg %) $@ -$(LANGUAGE_SERVER_BIN): $(LANGUAGE_SERVER_MAIN).${BUILD} - mv $< $@ - -$(LANGUAGE_SERVER_MAIN).${BUILD}: sanity - $(OCAMLBUILD) -tag thread $(LANGUAGE_SERVER_OPAM_PACKAGES:%=-pkg %) $(LANGUAGE_SERVER_DIR)/$@ - sanity: ocamlfind query $(OPAM_PACKAGES) diff --git a/src/language_server/language_server_main.ml b/src/languageServer.ml similarity index 99% rename from src/language_server/language_server_main.ml rename to src/languageServer.ml index 1557fd37a7f..619f390a9eb 100644 --- a/src/language_server/language_server_main.ml +++ b/src/languageServer.ml @@ -144,7 +144,7 @@ let initialize InitializeParams.{ processId } = MyIdl.ErrM.return (InitializeResult.{ capabilities = ServerCapabilities.{ textDocumentSync = None }}) (* MyIdl.ErrM.return (ShowMessageParams.{ type_ = 2; message = "Hello from aslan"}) *) -let _ = +let start () = Server.initialize initialize; let rpc_fn = MyIdl.server Server.implementation in my_start_server rpc_fn; diff --git a/src/language_server/.merlin b/src/language_server/.merlin deleted file mode 100644 index de8ead383d8..00000000000 --- a/src/language_server/.merlin +++ /dev/null @@ -1,2 +0,0 @@ -B ../_build -PKG wasm num vlq yojson bisect_ppx-ocamlbuild ppx_deriving_rpc rpclib rpclib.json rpclib.cmdliner diff --git a/src/language_server/example2_client.ml b/src/language_server/example2_client.ml deleted file mode 100644 index 3a887db80c8..00000000000 --- a/src/language_server/example2_client.ml +++ /dev/null @@ -1,45 +0,0 @@ -open Example2_idl - -module M = Idl.IdM -module MyIdl = Idl.Make(M) -module Client = API(MyIdl.GenClient ()) -module Cmds = API(Cmdlinergen.Gen ()) - -(* Use a binary 16-byte length to frame RPC messages *) -let binary_rpc path (call: Rpc.call) : Rpc.response = - let sockaddr = Unix.ADDR_UNIX path in - let s = Unix.socket Unix.PF_UNIX Unix.SOCK_STREAM 0 in - Unix.connect s sockaddr; - let ic = Unix.in_channel_of_descr s in - let oc = Unix.out_channel_of_descr s in - let msg_buf = Jsonrpc.string_of_call call in - let len = Printf.sprintf "%016d" (String.length msg_buf) in - output_string oc len; - output_string oc msg_buf; - flush oc; - let len_buf = Bytes.make 16 '\000' in - really_input ic len_buf 0 16; - let len = int_of_string (Bytes.unsafe_to_string len_buf) in - let msg_buf = Bytes.make len '\000' in - really_input ic msg_buf 0 len; - let (response: Rpc.response) = Jsonrpc.response_of_string (Bytes.unsafe_to_string msg_buf) in - response - -let default_cmd = - let doc = "a cli for an API" in - Cmdliner.Term.(ret (const (fun _ -> `Help (`Pager, None)) $ const ())), - Cmdliner.Term.info "cli" ~version:"1.6.1" ~doc - -let server_cmd = - let doc = "Start the server" in - Cmdliner.Term.(const Example2_server.start_server $ const ()), - Cmdliner.Term.info "server" ~doc - -let cli () = - let rpc = binary_rpc Example2_idl.sockpath in - Cmdliner.Term.eval_choice default_cmd ( - server_cmd - :: List.map - (fun t -> let (term, info) = t rpc in (Cmdliner.Term.(term $ const ()), info)) - (Cmds.implementation ()) - ) diff --git a/src/language_server/example2_idl.ml b/src/language_server/example2_idl.ml deleted file mode 100644 index 9946061fcfd..00000000000 --- a/src/language_server/example2_idl.ml +++ /dev/null @@ -1,93 +0,0 @@ -(* https://github.com/mirage/ocaml-rpc/blob/4d542cb7b0c42a62196c6043ba556de54c1b7820/example/example2_idl.ml *) -(* Example2 *) - -(* In this one we're going to use the PPX to generate the structure and - variant values rather than doing it by hand as in example1. We'll also - actually create a client and server process. *) - -open Rpc -open Idl - -let sockpath = "/tmp/rpcsock" - -module Datatypes = struct - module Query = struct - type t = - { name: string - ; vendor: string - ; version: string - ; features: string list - ; instance_id: string - } [@@deriving rpcty] (* TODO: rpc? *) - end - - type errty = - | InternalError of string - | FrobnicationFailed - | OperationInProgress - [@@deriving rpcty] (* TODO: rpc? *) - - exception DatatypeError of errty - - let err = Error. - { def = errty - ; raiser = (function | e -> raise (DatatypeError e)) - ; matcher = function | DatatypeError e -> Some e | _ -> None - } -end - -module API(R : RPC) = struct - open R - - let description = Interface. - { name = "API" - ; namespace = None - ; description = [ "This is another example of the ocaml-rpc IDL." ] - ; version = (1, 0, 0) - } - - let implementation = implement description - - let query_p = Param.mk - ~name: "query" - ~description: ["The result of the query operation"] - Datatypes.Query.t - - let unit_p = Param.mk - Types.unit - - let string_p = Param.mk - Types.string - - let domid_p = Param.mk - ~name: "domid" - ~description: ["The domid on which to operate"] - Types.int64 - - let vm_p = Param.mk - ~name: "vm" - ~description: ["The uuid of the VM"] - Types.string - - let vm_desc = Param.mk - ~name: "description" - ~description: ["The description of the VM"] - Types.string - - let err = Datatypes.err - - let query = declare - "query" - ["Query the details of the server."] - (unit_p @-> returning query_p err) - - let diagnostics = declare - "get_diagnostics" - ["Get diagnostics information from the server."] - (unit_p @-> returning string_p err) - - let test = declare - "test" - ["A test of a bit more of the IDL stuff."] - (domid_p @-> vm_p @-> vm_desc @-> returning query_p err) -end diff --git a/src/language_server/example2_server.ml b/src/language_server/example2_server.ml deleted file mode 100644 index 13078ed602b..00000000000 --- a/src/language_server/example2_server.ml +++ /dev/null @@ -1,103 +0,0 @@ -(* https://github.com/mirage/ocaml-rpc/blob/4d542cb7b0c42a62196c6043ba556de54c1b7820/example/example2_server.ml *) -open Example2_idl - -(* You can swap the rpc engine, by using a different monad here, - note however that if you are using an asynchoronous one, like - lwt or async, you should also use their specific IO functions - including print functions. *) -module M = Idl.IdM (* You can easily but ExnM here and the code would stay unchanged. *) -module MyIdl = Idl.Make(M) -module Server = API(MyIdl.GenServer ()) - -(* Implementations of the methods *) -let query () = - let open Datatypes.Query in - Printf.printf "Received query API call\n%!"; - let result = - { name = "Example2 server" - ; vendor = "This is the example server showing how to use the ocaml-rpc IDL." - ; version = "2.0.0" - ; features = - [ "defaults" - ; "upgradability" - ] - ; instance_id = string_of_int (Random.int 1000) - } in - MyIdl.ErrM.return result - -let diagnostics () = - MyIdl.ErrM.return "This should be the diagnostics of the server." - -let test i s1 s2 = - Printf.printf "%Ld %s %s\n%!" i s1 s2; - query () - -(* Utility and general non-specific server bits and bobs *) -let finally f g = - try - let result = f () in - g (); - result - with e -> - g (); - raise e - -let mkdir_rec dir perm = - let rec p_mkdir dir = - let p_name = Filename.dirname dir in - if p_name <> "/" && p_name <> "." - then p_mkdir p_name; - (try Unix.mkdir dir perm with Unix.Unix_error(Unix.EEXIST, _, _) -> ()) in - p_mkdir dir - -let binary_handler process s = - let ic = Unix.in_channel_of_descr s in - let oc = Unix.out_channel_of_descr s in - (* Read a 16 byte length encoded as a string *) - let len_buf = Bytes.make 16 '\000' in - really_input ic len_buf 0 (Bytes.length len_buf); - let len = int_of_string (Bytes.unsafe_to_string len_buf) in - let msg_buf = Bytes.make len '\000' in - really_input ic msg_buf 0 (Bytes.length msg_buf); - let (>>=) = M.bind in - process msg_buf >>= fun result -> - let len_buf = Printf.sprintf "%016d" (String.length result) in - output_string oc len_buf; - output_string oc result; - flush oc; - M.return () - -let serve_requests rpcfn path = - (try Unix.unlink path with Unix.Unix_error(Unix.ENOENT, _, _) -> ()); - mkdir_rec (Filename.dirname path) 0o0755; - let sock = Unix.socket Unix.PF_UNIX Unix.SOCK_STREAM 0 in - Unix.bind sock (Unix.ADDR_UNIX path); - Unix.listen sock 5; - Printf.fprintf stdout "Listening on %s" path; - while true do - let this_connection, _ = Unix.accept sock in - let (_: Thread.t) = Thread.create - (fun () -> - finally - (* Here I am calling M.run to make sure that I am running the process, - this is not much of a problem with IdM or ExnM, but in general you - should ensure that the computation is started by a runner. *) - (fun () -> binary_handler rpcfn this_connection |> M.run) - (fun () -> Unix.close this_connection) - ) () in - () - done - -let start_server () = - Server.query query; - Server.diagnostics diagnostics; - Server.test test; - - let rpc_fn = MyIdl.server Server.implementation in - - let process x = - let open M in - rpc_fn (Jsonrpc.call_of_string (Bytes.unsafe_to_string x)) - >>= fun response -> Jsonrpc.string_of_response response |> return in - - serve_requests process sockpath diff --git a/src/main.ml b/src/main.ml index c3efb011e54..81b8399ea5e 100644 --- a/src/main.ml +++ b/src/main.ml @@ -51,6 +51,8 @@ let argspec = Arg.align "-dt", Arg.Set Flags.dump_tc, " dump type-checked AST"; "-dl", Arg.Set Flags.dump_lowering, " dump intermediate representation "; "--disable-prelude", Arg.Clear Flags.prelude, " disable prelude"; + + "-ide", Arg.Unit (fun () -> LanguageServer.start (); ()), " start the language server" ] From 51f221cc4f97c626d51ba6687db8aa4c4db92b57 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Wed, 15 May 2019 17:45:32 -0700 Subject: [PATCH 0020/1176] Remove ocaml-rpc, use YoJson (manually) --- default.nix | 6 +- nix/md2mld.nix | 32 -------- nix/ocaml-rpc.nix | 67 --------------- src/Makefile | 3 - src/languageServer.ml | 186 +++++++++++++----------------------------- 5 files changed, 58 insertions(+), 236 deletions(-) delete mode 100644 nix/md2mld.nix delete mode 100644 nix/ocaml-rpc.nix diff --git a/default.nix b/default.nix index a296eaf5388..028c57db033 100644 --- a/default.nix +++ b/default.nix @@ -30,8 +30,6 @@ let ocaml_vlq = import ./nix/ocaml-vlq.nix { let ocaml_bisect_ppx = import ./nix/ocaml-bisect_ppx.nix nixpkgs; in let ocaml_bisect_ppx-ocamlbuild = import ./nix/ocaml-bisect_ppx-ocamlbuild.nix nixpkgs; in -let ocaml-rpc = import ./nix/ocaml-rpc.nix { pkgs = nixpkgs; }; in - # Include dvm let real-dvm = if dvm == null @@ -162,9 +160,7 @@ rec { nativeBuildInputs = [ nixpkgs.makeWrapper ]; - buildInputs = commonBuildInputs - ++ ocaml-rpc.ppx_deriving_rpc.buildInputs - ++ [ ocaml-rpc.ppx_deriving_rpc ]; + buildInputs = commonBuildInputs; buildPhase = '' make -C src BUILD=native asc as-ld diff --git a/nix/md2mld.nix b/nix/md2mld.nix deleted file mode 100644 index 81cb113db27..00000000000 --- a/nix/md2mld.nix +++ /dev/null @@ -1,32 +0,0 @@ -{ pkgs }: - -let repo = "md2mld"; in -let rev = "0.3.0"; in - -pkgs.stdenv.mkDerivation { - name = "ocaml${pkgs.ocaml.version}-${repo}-${rev}"; - - src = pkgs.fetchFromGitHub { - inherit repo rev; - owner = "mseri"; - sha256 = "0xb8890q6f6rh02ih6vw3wnkybddr2fmzpj7144l1gfix3smx5cv"; - }; - - buildInputs = [ - pkgs.dune - pkgs.ocaml - pkgs.ocamlPackages.findlib - pkgs.ocamlPackages.omd - ]; - - buildPhase = "dune build -p md2mld"; - - inherit (pkgs.dune) installPhase; - - meta = { - homepage = https://github.com/mseri/md2mld; - platforms = pkgs.ocaml.meta.platforms or []; - description = "Little cli tool to convert md files into mld files"; - license = pkgs.stdenv.lib.licenses.isc; - }; -} diff --git a/nix/ocaml-rpc.nix b/nix/ocaml-rpc.nix deleted file mode 100644 index ae663e12920..00000000000 --- a/nix/ocaml-rpc.nix +++ /dev/null @@ -1,67 +0,0 @@ -{ pkgs }: - -let repo = "ocaml-rpc"; in -let rev = "4d542cb7b0c42a62196c6043ba556de54c1b7820"; in - -let src = pkgs.fetchFromGitHub { - inherit repo rev; - owner = "mirage"; - sha256 = "1931505xpycng9s18mq1m44naq0v7nxwr95nyws1kldl4fvrymn7"; -}; in - -let mkPackage = ({ name, description, buildInputs }: - pkgs.stdenv.mkDerivation { - name = "ocaml${pkgs.ocaml.version}-${repo}-${rev}-${name}"; - - inherit src; - - buildInputs = buildInputs ++ (with pkgs; [ - dune - ocaml - ocamlPackages.findlib - ]); - - buildPhase = '' - dune build -p ${name} - ''; - - inherit (pkgs.dune) installPhase; - - meta = { - homepage = https://github.com/mirage/ocaml-rpc; - platforms = pkgs.ocaml.meta.platforms or []; - license = pkgs.stdenv.lib.licenses.isc; - inherit description; - }; - } -); in - -let rpclib = mkPackage { - name = "rpclib"; - description = "A library to deal with RPCs in OCaml"; - buildInputs = with pkgs.ocamlPackages; [ - cmdliner - result - rresult - xmlm - yojson - ]; -}; in - -let ppx_deriving_rpc = mkPackage { - name = "ppx_deriving_rpc"; - description = "Ppx deriver for ocaml-rpc, a library to deal with RPCs in OCaml"; - buildInputs = rpclib.buildInputs ++ [ - pkgs.jbuilder - rpclib - ] ++ (with pkgs.ocamlPackages; [ - findlib - rresult - ppx_deriving - ppxlib - ]); -}; in - -{ - inherit rpclib ppx_deriving_rpc; -} diff --git a/src/Makefile b/src/Makefile index ad7a913176f..c3469f6c046 100644 --- a/src/Makefile +++ b/src/Makefile @@ -7,7 +7,6 @@ ASC = `pwd`/$(NAME) OPAM_PACKAGES = wasm num vlq yojson bisect_ppx-ocamlbuild JS_OPAM_PACKAGES = js_of_ocaml js_of_ocaml-ppx -LANGUAGE_SERVER_OPAM_PACKAGES = ppx_deriving_rpc rpclib rpclib.json rpclib.cmdliner MENHIR = menhir MENHIR_FLAGS = --infer --dump --explain --strict @@ -21,8 +20,6 @@ OCAMLBUILD = ocamlbuild $(OCAML_FLAGS) \ -I lib \ $(OPAM_PACKAGES:%=-pkg %) \ -tags debug \ - -tag thread \ - $(LANGUAGE_SERVER_OPAM_PACKAGES:%=-pkg %) .PHONY: all parallel quick clean test test-parallel test-quick diff --git a/src/languageServer.ml b/src/languageServer.ml index 619f390a9eb..e64b63a0274 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -1,96 +1,5 @@ (* https://microsoft.github.io/language-server-protocol/specification *) -open Rpc -open Idl - -module ResponseError(*(D : RPC.t)*) = struct - type t = - { code: int - ; message: string - (* ; data: D option *) (* FIXME *) - } [@@deriving rpcty] -end - -module InitializeParams = struct - type t = - { processId: int (* FIXME *) - } [@@deriving rpcty] -end - -module ServerCapabilities = struct - type t = - { textDocumentSync: int option (* FIXME *) - } [@@deriving rpcty] -end - -module InitializeResult = struct - type t = - { capabilities: ServerCapabilities.t (* FIXME *) - } [@@deriving rpcty] -end - -type show_message_params = - { type_: int [@key "type"] (* FIXME *) - ; message: string - } [@@deriving rpc] - -module API(R : RPC) = struct - open R - - let description = Interface. - { name = "API" - ; namespace = None - ; description = [ "ActorScript LSP" ] - ; version = (1, 0, 0) - } - - let implementation = implement description - - (* FIXME: use ResponseError *) - let error = Idl.DefaultError.err - - (* FIXME *) - let initialize_params = Param.mk - (* ~name:"initialize_params" *) - InitializeParams.t - - (* FIXME *) - let server_capabilities = Param.mk - ~name:"server_capabilities" - ServerCapabilities.t - - (* FIXME *) - let initialize_result = Param.mk - ~name:"initialize_result" - InitializeResult.t - - (* let initialized_params = Param.mk *) - - (* let show_message_params = Param.mk - * ShowMessageParams.t *) - - let unit_p = Param.mk Types.unit - - let initialize = declare - "initialize" - [ "The initialize request is sent as the first request from the client to " - ; "the server." - ] - (initialize_params @-> returning initialize_result error) - - (* let show_message = declare - * "window/showMessage" - * [ "The show message notification is sent from a " - * ; "server to a client to ask the client to display a particular message in the user interface." - * ] - * (show_message_params @-> returning unit_p error) *) -end - -module M = Idl.IdM (* You can easily but ExnM here and the code would stay unchanged. *) -module MyIdl = Idl.Make(M) -module Server = API(MyIdl.GenServer ()) -module Client = API(MyIdl.GenClient ()) - let oc = open_out_gen [Open_append; Open_creat] 0o666 "ls.log" let log_to_file txt = Printf.fprintf oc "%s\n" txt; @@ -100,11 +9,15 @@ let respond out = let cl = "Content-Length: " ^ string_of_int (String.length out) ^ "\r\n\r\n" in print_string cl; print_string out; - flush stdout + flush stdout; + log_to_file "Response:"; + log_to_file cl; + log_to_file out -let my_start_server handler = - let rec server_loop () = +let start () = + let rec loop () = let clength = read_line () in + log_to_file "Request:"; log_to_file clength; let cl = "Content-Length: " in let cll = String.length cl in @@ -119,41 +32,56 @@ let my_start_server handler = Buffer.add_channel buffer stdin num; let raw = Buffer.contents buffer in log_to_file raw; - (* Printf.fprintf oc "%s\n" (String.trim raw); *) - let open M in - let call = Jsonrpc.call_of_string raw in - if call.name = "initialized" - then - let mes_res = - (Jsonrpc.string_of_call ~version:V2 - (Rpc.call "window/showMessage" - [ rpc_of_show_message_params { type_ = 2; message = "Handled command"}; ])); in - log_to_file mes_res; - respond mes_res; - server_loop () - else - handler call - >>= fun response -> let res = Jsonrpc.string_of_response ~version:V2 response in - log_to_file res; - respond res; - server_loop () - in server_loop () - -let initialize InitializeParams.{ processId } = - log_to_file (string_of_int processId); - MyIdl.ErrM.return (InitializeResult.{ capabilities = ServerCapabilities.{ textDocumentSync = None }}) - (* MyIdl.ErrM.return (ShowMessageParams.{ type_ = 2; message = "Hello from aslan"}) *) - -let start () = - Server.initialize initialize; - let rpc_fn = MyIdl.server Server.implementation - in my_start_server rpc_fn; - (* my_start_server (); *) + let json = Yojson.Basic.from_string raw in + let open Yojson.Basic.Util in + let jsonrpc = json |> member "jsonrpc" |> to_string in + let id = json |> member "id" |> to_int_option in + let method_ = json |> member "method" |> to_string in + let params = json |> member "params" in + + let string_of_int_option = + function + | None -> "None" + | Some id -> string_of_int id in + + log_to_file (jsonrpc ^ ", " ^ string_of_int_option id ^ ", " ^ method_); + + if method_ = "initialize" + then begin + log_to_file "Handle initialize"; + let capabilities = `Assoc + [ ("textDocumentSync", `Null) + ] in + let result = `Assoc + [ ("capabilities", capabilities) + ] in + let response = `Assoc + [ ("jsonrpc", `String "2.0") + ; ("id", json |> member "id") + ; ("result", result) + ; ("error", `Null) + ] in + respond (Yojson.Basic.pretty_to_string response); + end + + else if method_ = "initialized" + then begin + log_to_file "Handle initialized"; + let params = `Assoc + [ ("type", `Int 3) + ; ("message", `String "Language server initialized") + ] in + let notification = `Assoc + [ ("jsonrpc", `String "2.0") + ; ("method", `String "window/showMessage") + ; ("params", params) + ] in + respond (Yojson.Basic.pretty_to_string notification); + end -(* let () = - * print_string "Hello, World!\n"; *) + else + loop (); - (* TODO: basic sanity check *) - (* print_string (Rpc.string_of_call ...) *) - (* print_string (Rpc.string_of_response ...) *) + loop () + in loop () From 74175b1bb537a6343a67bf31b070740188e123e8 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Wed, 15 May 2019 17:50:02 -0700 Subject: [PATCH 0021/1176] Remove old directory from src files list --- default.nix | 1 - 1 file changed, 1 deletion(-) diff --git a/default.nix b/default.nix index 028c57db033..39244821a3f 100644 --- a/default.nix +++ b/default.nix @@ -153,7 +153,6 @@ rec { "src/.*.mll" "src/.*.mlpack" "src/_tags" - "^src/language_server/$" "test/" "test/node-test.js" ]; From 5f8fb7bedd7ee9ccc83c81985ad2be1e6983ae60 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Wed, 15 May 2019 17:50:41 -0700 Subject: [PATCH 0022/1176] Remove trailing slash --- src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index c3469f6c046..7ffbb1ae655 100644 --- a/src/Makefile +++ b/src/Makefile @@ -19,7 +19,7 @@ OCAMLBUILD = ocamlbuild $(OCAML_FLAGS) \ -I src \ -I lib \ $(OPAM_PACKAGES:%=-pkg %) \ - -tags debug \ + -tags debug .PHONY: all parallel quick clean test test-parallel test-quick From d443c8e10759f1fd82d861324bfc156e2d7dcb4d Mon Sep 17 00:00:00 2001 From: Paul Young Date: Wed, 15 May 2019 17:51:31 -0700 Subject: [PATCH 0023/1176] Remove attempt at building a library --- src/actorscript.mllib | 44 ------------------------------------------- 1 file changed, 44 deletions(-) delete mode 100644 src/actorscript.mllib diff --git a/src/actorscript.mllib b/src/actorscript.mllib deleted file mode 100644 index 20df6eea936..00000000000 --- a/src/actorscript.mllib +++ /dev/null @@ -1,44 +0,0 @@ -Arrange -Arrange_ir -Arrange_type -Async -Await -Check_ir -Compile -Con -Construct -Coverage -CustomModule -CustomSections -Definedness -Desugar -Diag -Dom -Effect -EncodeMap -Env -Flags -FreeVars -InstrList -Interpret -Interpret_ir -Ir -Lexer -Lib -NameRel -Operator -Parser -Pipeline -Prelude -Rename -Resolve_import -Serialization -Show -Source -Static -Syntax -Tailcall -Type -Typing -Value -Wasm_eval From 79c1bbf54166ce6d20e11c673638b565ed3c34c1 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Wed, 15 May 2019 17:51:47 -0700 Subject: [PATCH 0024/1176] Restore OCaml flags --- src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 7ffbb1ae655..cd4ef789b3a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -11,7 +11,7 @@ JS_OPAM_PACKAGES = js_of_ocaml js_of_ocaml-ppx MENHIR = menhir MENHIR_FLAGS = --infer --dump --explain --strict -OCAML_FLAGS = -cflags '' #'-w +a-4-27-30-42-44-45-58 -warn-error +a' +OCAML_FLAGS = -cflags '-w +a-4-27-30-42-44-45-58 -warn-error +a' OCAMLBUILD = ocamlbuild $(OCAML_FLAGS) \ -use-ocamlfind \ -plugin-tag 'package(bisect_ppx-ocamlbuild)' \ From f88778c02fe03b6ebf458fc8ad0aa35946ff7d13 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Wed, 15 May 2019 17:52:05 -0700 Subject: [PATCH 0025/1176] Comment out unused binding to address warning --- src/languageServer.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/languageServer.ml b/src/languageServer.ml index e64b63a0274..7f121bfc916 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -38,7 +38,7 @@ let start () = let jsonrpc = json |> member "jsonrpc" |> to_string in let id = json |> member "id" |> to_int_option in let method_ = json |> member "method" |> to_string in - let params = json |> member "params" in + (* let params = json |> member "params" in *) let string_of_int_option = function From 5bbc2298569d664286741047a901d9918b0280a0 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Wed, 15 May 2019 17:53:21 -0700 Subject: [PATCH 0026/1176] Revert whitespace changes --- default.nix | 2 +- src/Makefile | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/default.nix b/default.nix index 39244821a3f..fc43aef96d5 100644 --- a/default.nix +++ b/default.nix @@ -155,7 +155,7 @@ rec { "src/_tags" "test/" "test/node-test.js" - ]; + ]; nativeBuildInputs = [ nixpkgs.makeWrapper ]; diff --git a/src/Makefile b/src/Makefile index cd4ef789b3a..5b798dc2515 100644 --- a/src/Makefile +++ b/src/Makefile @@ -43,6 +43,7 @@ $(NAME).js: $(JS_MAIN).byte $(JS_MAIN).byte: $(JS_MAIN).ml sanity $(OCAMLBUILD) $(JS_OPAM_PACKAGES:%=-pkg %) $@ + sanity: ocamlfind query $(OPAM_PACKAGES) From cb80d7e813ec73dff5bc85f1912347cebbd65316 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 16 May 2019 12:18:00 -0400 Subject: [PATCH 0027/1176] Makefile profiles Wasm PX at various scales; collects microsec measurements in CSV files --- stdlib/Makefile | 163 ++++++++++++++++-- .../examples/produce-exchange/profileActor.as | 25 +++ .../examples/produce-exchange/serverActor.as | 67 +++---- .../examples/produce-exchange/serverModel.as | 31 ++++ .../produce-exchange/test/params-5-3.as | 3 + .../produce-exchange/test/params-5-4.as | 3 + stdlib/time.c | 24 +++ 7 files changed, 270 insertions(+), 46 deletions(-) create mode 100644 stdlib/examples/produce-exchange/profileActor.as create mode 100644 stdlib/examples/produce-exchange/test/params-5-3.as create mode 100644 stdlib/examples/produce-exchange/test/params-5-4.as create mode 100644 stdlib/time.c diff --git a/stdlib/Makefile b/stdlib/Makefile index f03cf88d216..1ee91c6f1b1 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -1,4 +1,5 @@ ASC=../src/asc +DVM=dvm OUTDIR=_out DOCDIR=doc MDofAS=./markdown-of-actorscript.py @@ -198,6 +199,8 @@ profile: \ \ $(OUTDIR)/profileLoadQuery.04-05-01.csv \ $(OUTDIR)/profileLoadQuery.04-05-02.csv \ + $(OUTDIR)/profileLoadQuery.04-05-03.csv \ + $(OUTDIR)/profileLoadQuery.04-05-04.csv \ $(OUTDIR)/profileLoadQuery.04-05-05.csv \ $(OUTDIR)/profileLoadQuery.04-05-10.csv \ $(OUTDIR)/profileLoadQuery.04-05-20.csv \ @@ -207,49 +210,55 @@ profile: \ ## AS wishlist: the following various targets would be easier to relate if we could accept named AS values as CLI params; that feature would also obviate the need for the `param-X-Y.as` files used below: $(OUTDIR)/profileLoad.04-05-01.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_SRC) | $(OUTDIR) - $(ASC) -r --profile examples/produce-exchange/test/params-5-1.as $(PROFILE_LOAD_SRC) --profile-file $@ $(PROFILE_FIELDS) + time $(ASC) -r --profile examples/produce-exchange/test/params-5-1.as $(PROFILE_LOAD_SRC) --profile-file $@ $(PROFILE_FIELDS) $(OUTDIR)/profileLoad.04-05-02.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_SRC) | $(OUTDIR) - $(ASC) -r --profile examples/produce-exchange/test/params-5-2.as $(PROFILE_LOAD_SRC) --profile-file $@ $(PROFILE_FIELDS) + time $(ASC) -r --profile examples/produce-exchange/test/params-5-2.as $(PROFILE_LOAD_SRC) --profile-file $@ $(PROFILE_FIELDS) $(OUTDIR)/profileLoad.04-05-05.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_SRC) | $(OUTDIR) - $(ASC) -r --profile examples/produce-exchange/test/params-5-5.as $(PROFILE_LOAD_SRC) --profile-file $@ $(PROFILE_FIELDS) + time $(ASC) -r --profile examples/produce-exchange/test/params-5-5.as $(PROFILE_LOAD_SRC) --profile-file $@ $(PROFILE_FIELDS) $(OUTDIR)/profileLoad.04-05-10.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_SRC) | $(OUTDIR) - $(ASC) -r --profile examples/produce-exchange/test/params-5-10.as $(PROFILE_LOAD_SRC) --profile-file $@ $(PROFILE_FIELDS) + time $(ASC) -r --profile examples/produce-exchange/test/params-5-10.as $(PROFILE_LOAD_SRC) --profile-file $@ $(PROFILE_FIELDS) $(OUTDIR)/profileLoad.04-05-20.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_SRC) | $(OUTDIR) - $(ASC) -r --profile examples/produce-exchange/test/params-5-20.as $(PROFILE_LOAD_SRC) --profile-file $@ $(PROFILE_FIELDS) + time $(ASC) -r --profile examples/produce-exchange/test/params-5-20.as $(PROFILE_LOAD_SRC) --profile-file $@ $(PROFILE_FIELDS) $(OUTDIR)/profileLoad.04-05-50.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_SRC) | $(OUTDIR) - $(ASC) -r --profile examples/produce-exchange/test/params-5-50.as $(PROFILE_LOAD_SRC) --profile-file $@ $(PROFILE_FIELDS) + time $(ASC) -r --profile examples/produce-exchange/test/params-5-50.as $(PROFILE_LOAD_SRC) --profile-file $@ $(PROFILE_FIELDS) $(OUTDIR)/profileLoad.04-05-100.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_SRC) | $(OUTDIR) - $(ASC) -r --profile examples/produce-exchange/test/params-5-100.as $(PROFILE_LOAD_SRC) --profile-file $@ $(PROFILE_FIELDS) + time $(ASC) -r --profile examples/produce-exchange/test/params-5-100.as $(PROFILE_LOAD_SRC) --profile-file $@ $(PROFILE_FIELDS) $(OUTDIR)/profileLoadQuery.04-05-01.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) - $(ASC) -r --profile examples/produce-exchange/test/params-5-1.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + time $(ASC) -r --profile examples/produce-exchange/test/params-5-1.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) $(OUTDIR)/profileLoadQuery.04-05-02.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) - $(ASC) -r --profile examples/produce-exchange/test/params-5-2.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + time $(ASC) -r --profile examples/produce-exchange/test/params-5-2.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + +$(OUTDIR)/profileLoadQuery.04-05-03.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) + time $(ASC) -r --profile examples/produce-exchange/test/params-5-3.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + +$(OUTDIR)/profileLoadQuery.04-05-04.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) + time $(ASC) -r --profile examples/produce-exchange/test/params-5-4.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) $(OUTDIR)/profileLoadQuery.04-05-05.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) - $(ASC) -r --profile examples/produce-exchange/test/params-5-5.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + time $(ASC) -r --profile examples/produce-exchange/test/params-5-5.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) $(OUTDIR)/profileLoadQuery.04-05-10.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) - $(ASC) -r --profile examples/produce-exchange/test/params-5-10.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + time $(ASC) -r --profile examples/produce-exchange/test/params-5-10.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) $(OUTDIR)/profileLoadQuery.04-05-20.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) - $(ASC) -r --profile examples/produce-exchange/test/params-5-20.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + time $(ASC) -r --profile examples/produce-exchange/test/params-5-20.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) $(OUTDIR)/profileLoadQuery.04-05-50.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) - $(ASC) -r --profile examples/produce-exchange/test/params-5-50.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + time $(ASC) -r --profile examples/produce-exchange/test/params-5-50.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) $(OUTDIR)/profileLoadQuery.04-05-100.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) - $(ASC) -r --profile examples/produce-exchange/test/params-5-100.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + time $(ASC) -r --profile examples/produce-exchange/test/params-5-100.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) -$(OUTDIR)/loadWorkloadAndQueryBig.wasm: $(PRODUCE_EXCHANGE_SRC) \ +$(OUTDI R)/loadWorkloadAndQueryBig.wasm: $(PRODUCE_EXCHANGE_SRC) \ examples/produce-exchange/test/loadWorkloadAndQuery.as | $(OUTDIR) $(ASC) examples/produce-exchange/serverActor.as examples/produce-exchange/test/loadWorkloadAndQueryBig.as -c --dfinity -o $@ @@ -268,6 +277,130 @@ $(OUTDIR)/evalBulk.out: $(PRODUCE_EXCHANGE_SRC) \ $(OUTDIR)/ProduceExchange.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) $(ASC) -c --dfinity -o $@ examples/produce-exchange/serverActor.as + +profile-wasm:\ + $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm.csv \ + \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_2.wasm \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_2.wasm.csv \ + \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_3.wasm \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_3.wasm.csv \ + \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_4.wasm \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_4.wasm.csv \ + \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm.csv \ + \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_10.wasm \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_10.wasm.csv \ + \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_20.wasm \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_20.wasm.csv \ + \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_50.wasm \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_50.wasm.csv \ + \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_100.wasm \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_100.wasm.csv \ + + +$(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) + $(ASC) -c --dfinity -o $@ examples/produce-exchange/test/params-5-1.as examples/produce-exchange/profileActor.as + +$(OUTDIR)/ProduceExchangeLoadQuery_5_2.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) + $(ASC) -c --dfinity -o $@ examples/produce-exchange/test/params-5-2.as examples/produce-exchange/profileActor.as + +$(OUTDIR)/ProduceExchangeLoadQuery_5_3.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) + $(ASC) -c --dfinity -o $@ examples/produce-exchange/test/params-5-3.as examples/produce-exchange/profileActor.as + +$(OUTDIR)/ProduceExchangeLoadQuery_5_4.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) + $(ASC) -c --dfinity -o $@ examples/produce-exchange/test/params-5-4.as examples/produce-exchange/profileActor.as + +$(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) + $(ASC) -c --dfinity -o $@ examples/produce-exchange/test/params-5-5.as examples/produce-exchange/profileActor.as + +$(OUTDIR)/ProduceExchangeLoadQuery_5_10.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) + $(ASC) -c --dfinity -o $@ examples/produce-exchange/test/params-5-10.as examples/produce-exchange/profileActor.as + +$(OUTDIR)/ProduceExchangeLoadQuery_5_20.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) + $(ASC) -c --dfinity -o $@ examples/produce-exchange/test/params-5-20.as examples/produce-exchange/profileActor.as + +$(OUTDIR)/ProduceExchangeLoadQuery_5_50.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) + $(ASC) -c --dfinity -o $@ examples/produce-exchange/test/params-5-50.as examples/produce-exchange/profileActor.as + +$(OUTDIR)/ProduceExchangeLoadQuery_5_100.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) + $(ASC) -c --dfinity -o $@ examples/produce-exchange/test/params-5-100.as examples/produce-exchange/profileActor.as + + +$(OUTDIR)/time: + gcc time.c -o $@ + +$(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm $(OUTDIR)/time + rm -rf ./.dvm + $(DVM) reset + $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm + $(OUTDIR)/time "$(DVM) run 1 start -t" "5, 1, " > $@ + cat $@ + +$(OUTDIR)/ProduceExchangeLoadQuery_5_2.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_2.wasm $(OUTDIR)/time + rm -rf ./.dvm + $(DVM) reset + $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_2.wasm + $(OUTDIR)/time "$(DVM) run 1 start -t" "5, 2, " > $@ + cat $@ + +$(OUTDIR)/ProduceExchangeLoadQuery_5_3.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_3.wasm $(OUTDIR)/time + rm -rf ./.dvm + $(DVM) reset + $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_3.wasm + $(OUTDIR)/time "$(DVM) run 1 start -t" "5, 3, " > $@ + cat $@ + +$(OUTDIR)/ProduceExchangeLoadQuery_5_4.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_4.wasm $(OUTDIR)/time + rm -rf ./.dvm + $(DVM) reset + $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_4.wasm + $(OUTDIR)/time "$(DVM) run 1 start -t" "5, 4, " > $@ + cat $@ + +$(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm $(OUTDIR)/time + rm -rf ./.dvm + $(DVM) reset + $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm + $(OUTDIR)/time "$(DVM) run 1 start -t" "5, 5, " > $@ + cat $@ + +$(OUTDIR)/ProduceExchangeLoadQuery_5_10.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_10.wasm $(OUTDIR)/time + rm -rf ./.dvm + $(DVM) reset + $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_10.wasm + $(OUTDIR)/time "$(DVM) run 1 start -t" "5, 10, " > $@ + cat $@ + +$(OUTDIR)/ProduceExchangeLoadQuery_5_20.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_20.wasm $(OUTDIR)/time + rm -rf ./.dvm + $(DVM) reset + $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_20.wasm + $(OUTDIR)/time "$(DVM) run 1 start -t" "5, 20, " > $@ + cat $@ + +$(OUTDIR)/ProduceExchangeLoadQuery_5_50.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_50.wasm $(OUTDIR)/time + rm -rf ./.dvm + $(DVM) reset + $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_50.wasm + $(OUTDIR)/time "$(DVM) run 1 start -t" "5, 50, " > $@ + cat $@ + +$(OUTDIR)/ProduceExchangeLoadQuery_5_100.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_100.wasm $(OUTDIR)/time + rm -rf ./.dvm + $(DVM) reset + $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_100.wasm + $(OUTDIR)/time "$(DVM) run 1 start -t" "5, 100, " > $@ + cat $@ + $(DOCDIR)/%.md: %.as $(MDofAS) | $(DOCDIR) @echo "" > $@ @echo "" >> $@ diff --git a/stdlib/examples/produce-exchange/profileActor.as b/stdlib/examples/produce-exchange/profileActor.as new file mode 100644 index 00000000000..2f9548acb54 --- /dev/null +++ b/stdlib/examples/produce-exchange/profileActor.as @@ -0,0 +1,25 @@ +let T = (import "serverTypes.as"); +let Model = (import "serverModel.as"); + +actor server { + // morally: loadQuery (region_count:Nat, scale_factor:Nat) { + // + // except, we assume that region_count and scale_factor are already defined in the enclosing env + // + private var dummy = { + func scaledParams(region_count_:Nat, factor:Nat) : T.WorkloadParams = { + shared { + region_count = region_count_:Nat; + day_count = 3:Nat; + max_route_duration = 1:Nat; + producer_count = region_count * factor:Nat; + transporter_count = region_count * factor:Nat; + retailer_count = region_count * factor:Nat; + } + }; + let m = Model.Model(); + let _ = m.loadWorkload(scaledParams(region_count, scale_factor)); + let _ = m.retailerQueryAll(0, null, null); + () + }; +} diff --git a/stdlib/examples/produce-exchange/serverActor.as b/stdlib/examples/produce-exchange/serverActor.as index e3535b609c0..916c944311a 100644 --- a/stdlib/examples/produce-exchange/serverActor.as +++ b/stdlib/examples/produce-exchange/serverActor.as @@ -1034,55 +1034,60 @@ been processed }; + loadWorkload(params:T.WorkloadParams) : () { + func db(s:Text) = if false {print "Model::loadWorkload: "; print s; print "\n"}; + getModel().loadWorkload(params) + }; + /** - `loadWorkload` - ---------------- - clear existing server state, and replace with a synthetic workload, based on the given parameters. + Standard workloads + ========================= */ - loadWorkload(params:T.WorkloadParams) : async () { - func db(s:Text) = if false {print "Server::loadWorkload: "; print s; print "\n"}; - - /**- generate add requests for these params: */ - db "generate requests for workload..."; - let addreqs : List = getModel().genAddReqs( - params.day_count, - params.max_route_duration, - params.producer_count, - params.transporter_count, - params.retailer_count, - params.region_count - ); - - /**- reset to initial state before adding this new workload: */ - let reqs : List = - ?(#reset, List.map(addreqs, func (r:L.AddReq):L.Req = #add r)); - - /**- evaluate each request: */ - db "evaluate requests for workload..."; - let resps = getModel().evalReqList(reqs); - - /**- assert that everything worked; a sanity check. */ - // to do + devTestLoadQuery (region_count:Nat, scale_factor:Nat) { + func scaledParams(region_count_:Nat, factor:Nat) : T.WorkloadParams = { + shared { + region_count = region_count_:Nat; + day_count = 3:Nat; + max_route_duration = 1:Nat; + producer_count = region_count * factor:Nat; + transporter_count = region_count * factor:Nat; + retailer_count = region_count * factor:Nat; + } + }; + let m = Model.Model(); + let _ = m.loadWorkload(scaledParams(5, 2)); + let _ = m.retailerQueryAll(0, null, null); }; /////////////////////////////////////////////////////////////////////////// - // @Omit: // See `serverModel.as` for the Model class's implementation // Matthew-Says: // There are two initialization options for the model field: - // 1. Call Model() directly; using this option now. + // 1. Call Model() directly // 2. Call Model() later, when we try to access the model field. + // + // Option 1 is simpler, but option 2 permits a "static" class or actor definition, + // which is needed in some contexts. - private var model : ?Model.Model = null; + //private var model : ?Model.Model = null; + + + private var model : ?Model.Model = { + // TEMP: + devTestLoadQuery(5, 2); + // + ?(Model.Model()); + }; private getModel() : Model.Model { switch model { case (null) { let m = Model.Model(); - model := ?m; m + model := ?m; + m }; case (?m) m; } diff --git a/stdlib/examples/produce-exchange/serverModel.as b/stdlib/examples/produce-exchange/serverModel.as index 19e78a2967b..1590768dacf 100644 --- a/stdlib/examples/produce-exchange/serverModel.as +++ b/stdlib/examples/produce-exchange/serverModel.as @@ -70,6 +70,37 @@ class Model() { Evaluation semantics for the PX server language */ + /** + `loadWorkload` + ---------------- + clear existing server state, and replace with a synthetic workload, based on the given parameters. + */ + + loadWorkload(params:T.WorkloadParams) : () { + func db(s:Text) = if false {print "Model::loadWorkload: "; print s; print "\n"}; + + /**- generate add requests for these params: */ + db "generate requests for workload..."; + let addreqs : List = genAddReqs( + params.day_count, + params.max_route_duration, + params.producer_count, + params.transporter_count, + params.retailer_count, + params.region_count + ); + + /**- reset to initial state before adding this new workload: */ + let reqs : List = + ?(#reset, List.map(addreqs, func (r:L.AddReq):L.Req = #add r)); + + /**- evaluate each request: */ + db "evaluate requests for workload..."; + let resps = evalReqList(reqs); + + /**- assert that everything worked; a sanity check. */ + // to do + }; /** diff --git a/stdlib/examples/produce-exchange/test/params-5-3.as b/stdlib/examples/produce-exchange/test/params-5-3.as new file mode 100644 index 00000000000..3923444a00c --- /dev/null +++ b/stdlib/examples/produce-exchange/test/params-5-3.as @@ -0,0 +1,3 @@ +let region_count = 5; +let scale_factor = 3; + diff --git a/stdlib/examples/produce-exchange/test/params-5-4.as b/stdlib/examples/produce-exchange/test/params-5-4.as new file mode 100644 index 00000000000..26953628e29 --- /dev/null +++ b/stdlib/examples/produce-exchange/test/params-5-4.as @@ -0,0 +1,3 @@ +let region_count = 5; +let scale_factor = 4; + diff --git a/stdlib/time.c b/stdlib/time.c new file mode 100644 index 00000000000..ab2df00e475 --- /dev/null +++ b/stdlib/time.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include + +int main(int argc, char** args) { + struct timeval tv_0; + struct timeval tv_1; + gettimeofday(&tv_0,0); + system(args[1]); + gettimeofday(&tv_1,0); + printf("%s%d\n", + // + // second argument is the line prefix for the output... + // + args[2], + // + // ...and line ends with time, in micro seconds. + // + (int) ((tv_1.tv_sec - tv_0.tv_sec) * 1000000) + + + (int) (tv_1.tv_usec - tv_0.tv_usec) + ); +} From 09042ec220ef24959da24f4fd985b78b7a03d73b Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 16 May 2019 13:38:40 -0400 Subject: [PATCH 0028/1176] Makefile times Wasm via dvm and counts interpeter via --profile for a set of common workloads --- stdlib/Makefile | 184 ++++++++++-------- .../examples/produce-exchange/serverActor.as | 7 +- .../produce-exchange/test/params-5-6.as | 3 + .../produce-exchange/test/params-5-7.as | 3 + .../produce-exchange/test/params-5-8.as | 3 + .../produce-exchange/test/params-5-9.as | 3 + 6 files changed, 116 insertions(+), 87 deletions(-) create mode 100644 stdlib/examples/produce-exchange/test/params-5-6.as create mode 100644 stdlib/examples/produce-exchange/test/params-5-7.as create mode 100644 stdlib/examples/produce-exchange/test/params-5-8.as create mode 100644 stdlib/examples/produce-exchange/test/params-5-9.as diff --git a/stdlib/Makefile b/stdlib/Makefile index 1ee91c6f1b1..9f3218db528 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -163,6 +163,27 @@ $(OUTDIR)/ProduceExchange.out: $(PRODUCE_EXCHANGE_SRC) \ examples/produce-exchange/test/simpleSetupAndQuery.as | $(OUTDIR) $(ASC) -r examples/produce-exchange/serverActor.as examples/produce-exchange/test/simpleSetupAndQuery.as > $@ +$(OUTDIR)/retailerReserveMany.out: $(PRODUCE_EXCHANGE_SRC) \ + examples/produce-exchange/test/retailerReserveMany.as | $(OUTDIR) + $(ASC) -r examples/produce-exchange/serverActor.as examples/produce-exchange/test/retailerReserveMany.as > $@ + +$(OUTDIR)/producerRemInventory.out: $(PRODUCE_EXCHANGE_SRC) \ + examples/produce-exchange/test/producerRemInventory.as | $(OUTDIR) + $(ASC) -r examples/produce-exchange/serverActor.as examples/produce-exchange/test/producerRemInventory.as > $@ + +$(OUTDIR)/evalBulk.out: $(PRODUCE_EXCHANGE_SRC) \ + examples/produce-exchange/test/evalBulk.as | $(OUTDIR) + $(ASC) -r examples/produce-exchange/serverActor.as examples/produce-exchange/test/evalBulk.as > $@ + +$(OUTDIR)/ProduceExchange.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) + $(ASC) -c --dfinity -o $@ examples/produce-exchange/serverActor.as + +#########################################################################################################33 + +## +## Profiling targets +## + PROFILE_LOAD_SRC=\ examples/produce-exchange/serverActor.as \ examples/produce-exchange/test/profileLoad.as @@ -181,102 +202,51 @@ PROFILE_FIELDS=\ --profile-field "retailer_query_cost" \ --profile-field "retailer_query_size_max" \ -profile-small: \ - $(OUTDIR)/profileLoad.04-05-01.csv \ - $(OUTDIR)/profileLoad.04-05-02.csv \ - \ - $(OUTDIR)/profileLoadQuery.04-05-01.csv \ - $(OUTDIR)/profileLoadQuery.04-05-02.csv \ - -profile: \ - $(OUTDIR)/profileLoad.04-05-01.csv \ - $(OUTDIR)/profileLoad.04-05-02.csv \ - $(OUTDIR)/profileLoad.04-05-05.csv \ - $(OUTDIR)/profileLoad.04-05-10.csv \ - $(OUTDIR)/profileLoad.04-05-20.csv \ - $(OUTDIR)/profileLoad.04-05-50.csv \ - $(OUTDIR)/profileLoad.04-05-100.csv \ - \ +profile-interp-small: \ $(OUTDIR)/profileLoadQuery.04-05-01.csv \ $(OUTDIR)/profileLoadQuery.04-05-02.csv \ $(OUTDIR)/profileLoadQuery.04-05-03.csv \ - $(OUTDIR)/profileLoadQuery.04-05-04.csv \ - $(OUTDIR)/profileLoadQuery.04-05-05.csv \ - $(OUTDIR)/profileLoadQuery.04-05-10.csv \ - $(OUTDIR)/profileLoadQuery.04-05-20.csv \ - $(OUTDIR)/profileLoadQuery.04-05-50.csv \ - $(OUTDIR)/profileLoadQuery.04-05-100.csv \ - -## AS wishlist: the following various targets would be easier to relate if we could accept named AS values as CLI params; that feature would also obviate the need for the `param-X-Y.as` files used below: - -$(OUTDIR)/profileLoad.04-05-01.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_SRC) | $(OUTDIR) - time $(ASC) -r --profile examples/produce-exchange/test/params-5-1.as $(PROFILE_LOAD_SRC) --profile-file $@ $(PROFILE_FIELDS) - -$(OUTDIR)/profileLoad.04-05-02.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_SRC) | $(OUTDIR) - time $(ASC) -r --profile examples/produce-exchange/test/params-5-2.as $(PROFILE_LOAD_SRC) --profile-file $@ $(PROFILE_FIELDS) - -$(OUTDIR)/profileLoad.04-05-05.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_SRC) | $(OUTDIR) - time $(ASC) -r --profile examples/produce-exchange/test/params-5-5.as $(PROFILE_LOAD_SRC) --profile-file $@ $(PROFILE_FIELDS) -$(OUTDIR)/profileLoad.04-05-10.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_SRC) | $(OUTDIR) - time $(ASC) -r --profile examples/produce-exchange/test/params-5-10.as $(PROFILE_LOAD_SRC) --profile-file $@ $(PROFILE_FIELDS) - -$(OUTDIR)/profileLoad.04-05-20.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_SRC) | $(OUTDIR) - time $(ASC) -r --profile examples/produce-exchange/test/params-5-20.as $(PROFILE_LOAD_SRC) --profile-file $@ $(PROFILE_FIELDS) - -$(OUTDIR)/profileLoad.04-05-50.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_SRC) | $(OUTDIR) - time $(ASC) -r --profile examples/produce-exchange/test/params-5-50.as $(PROFILE_LOAD_SRC) --profile-file $@ $(PROFILE_FIELDS) - -$(OUTDIR)/profileLoad.04-05-100.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_SRC) | $(OUTDIR) - time $(ASC) -r --profile examples/produce-exchange/test/params-5-100.as $(PROFILE_LOAD_SRC) --profile-file $@ $(PROFILE_FIELDS) +profile-interp: \ + $(OUTDIR)/profileLoadQuery.05-01.csv \ + $(OUTDIR)/profileLoadQuery.05-02.csv \ + $(OUTDIR)/profileLoadQuery.05-03.csv \ + $(OUTDIR)/profileLoadQuery.05-04.csv \ + $(OUTDIR)/profileLoadQuery.05-05.csv \ + $(OUTDIR)/profileLoadQuery.05-10.csv \ + $(OUTDIR)/profileLoadQuery.05-20.csv \ + $(OUTDIR)/profileLoadQuery.05-50.csv \ + $(OUTDIR)/profileLoadQuery.05-100.csv \ +## AS wishlist: the following various targets would be easier to relate if we could accept named AS values as CLI params; that feature would also obviate the need for the `param-X-Y.as` files used below: -$(OUTDIR)/profileLoadQuery.04-05-01.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) +$(OUTDIR)/profileLoadQuery.05-01.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) time $(ASC) -r --profile examples/produce-exchange/test/params-5-1.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) -$(OUTDIR)/profileLoadQuery.04-05-02.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) +$(OUTDIR)/profileLoadQuery.05-02.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) time $(ASC) -r --profile examples/produce-exchange/test/params-5-2.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) -$(OUTDIR)/profileLoadQuery.04-05-03.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) +$(OUTDIR)/profileLoadQuery.05-03.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) time $(ASC) -r --profile examples/produce-exchange/test/params-5-3.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) -$(OUTDIR)/profileLoadQuery.04-05-04.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) +$(OUTDIR)/profileLoadQuery.05-04.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) time $(ASC) -r --profile examples/produce-exchange/test/params-5-4.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) -$(OUTDIR)/profileLoadQuery.04-05-05.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) +$(OUTDIR)/profileLoadQuery.05-05.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) time $(ASC) -r --profile examples/produce-exchange/test/params-5-5.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) -$(OUTDIR)/profileLoadQuery.04-05-10.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) +$(OUTDIR)/profileLoadQuery.05-10.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) time $(ASC) -r --profile examples/produce-exchange/test/params-5-10.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) -$(OUTDIR)/profileLoadQuery.04-05-20.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) +$(OUTDIR)/profileLoadQuery.05-20.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) time $(ASC) -r --profile examples/produce-exchange/test/params-5-20.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) -$(OUTDIR)/profileLoadQuery.04-05-50.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) +$(OUTDIR)/profileLoadQuery.05-50.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) time $(ASC) -r --profile examples/produce-exchange/test/params-5-50.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) -$(OUTDIR)/profileLoadQuery.04-05-100.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) +$(OUTDIR)/profileLoadQuery.05-100.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) time $(ASC) -r --profile examples/produce-exchange/test/params-5-100.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) -$(OUTDI R)/loadWorkloadAndQueryBig.wasm: $(PRODUCE_EXCHANGE_SRC) \ - examples/produce-exchange/test/loadWorkloadAndQuery.as | $(OUTDIR) - $(ASC) examples/produce-exchange/serverActor.as examples/produce-exchange/test/loadWorkloadAndQueryBig.as -c --dfinity -o $@ - -$(OUTDIR)/retailerReserveMany.out: $(PRODUCE_EXCHANGE_SRC) \ - examples/produce-exchange/test/retailerReserveMany.as | $(OUTDIR) - $(ASC) -r examples/produce-exchange/serverActor.as examples/produce-exchange/test/retailerReserveMany.as > $@ - -$(OUTDIR)/producerRemInventory.out: $(PRODUCE_EXCHANGE_SRC) \ - examples/produce-exchange/test/producerRemInventory.as | $(OUTDIR) - $(ASC) -r examples/produce-exchange/serverActor.as examples/produce-exchange/test/producerRemInventory.as > $@ - -$(OUTDIR)/evalBulk.out: $(PRODUCE_EXCHANGE_SRC) \ - examples/produce-exchange/test/evalBulk.as | $(OUTDIR) - $(ASC) -r examples/produce-exchange/serverActor.as examples/produce-exchange/test/evalBulk.as > $@ - -$(OUTDIR)/ProduceExchange.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c --dfinity -o $@ examples/produce-exchange/serverActor.as - profile-wasm:\ $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm \ @@ -294,6 +264,18 @@ profile-wasm:\ $(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm \ $(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm.csv \ \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_6.wasm \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_6.wasm.csv \ + \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_7.wasm \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_7.wasm.csv \ + \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_8.wasm \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_8.wasm.csv \ + \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_9.wasm \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_9.wasm.csv \ + \ $(OUTDIR)/ProduceExchangeLoadQuery_5_10.wasm \ $(OUTDIR)/ProduceExchangeLoadQuery_5_10.wasm.csv \ \ @@ -322,6 +304,18 @@ $(OUTDIR)/ProduceExchangeLoadQuery_5_4.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) $(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) $(ASC) -c --dfinity -o $@ examples/produce-exchange/test/params-5-5.as examples/produce-exchange/profileActor.as +$(OUTDIR)/ProduceExchangeLoadQuery_5_6.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) + $(ASC) -c --dfinity -o $@ examples/produce-exchange/test/params-5-6.as examples/produce-exchange/profileActor.as + +$(OUTDIR)/ProduceExchangeLoadQuery_5_7.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) + $(ASC) -c --dfinity -o $@ examples/produce-exchange/test/params-5-7.as examples/produce-exchange/profileActor.as + +$(OUTDIR)/ProduceExchangeLoadQuery_5_8.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) + $(ASC) -c --dfinity -o $@ examples/produce-exchange/test/params-5-8.as examples/produce-exchange/profileActor.as + +$(OUTDIR)/ProduceExchangeLoadQuery_5_9.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) + $(ASC) -c --dfinity -o $@ examples/produce-exchange/test/params-5-9.as examples/produce-exchange/profileActor.as + $(OUTDIR)/ProduceExchangeLoadQuery_5_10.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) $(ASC) -c --dfinity -o $@ examples/produce-exchange/test/params-5-10.as examples/produce-exchange/profileActor.as @@ -342,63 +336,91 @@ $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQu rm -rf ./.dvm $(DVM) reset $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm - $(OUTDIR)/time "$(DVM) run 1 start -t" "5, 1, " > $@ + $(OUTDIR)/time "$(DVM) run 1 start " "5, 1, " > $@ cat $@ $(OUTDIR)/ProduceExchangeLoadQuery_5_2.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_2.wasm $(OUTDIR)/time rm -rf ./.dvm $(DVM) reset $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_2.wasm - $(OUTDIR)/time "$(DVM) run 1 start -t" "5, 2, " > $@ + $(OUTDIR)/time "$(DVM) run 1 start " "5, 2, " > $@ cat $@ $(OUTDIR)/ProduceExchangeLoadQuery_5_3.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_3.wasm $(OUTDIR)/time rm -rf ./.dvm $(DVM) reset $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_3.wasm - $(OUTDIR)/time "$(DVM) run 1 start -t" "5, 3, " > $@ + $(OUTDIR)/time "$(DVM) run 1 start " "5, 3, " > $@ cat $@ $(OUTDIR)/ProduceExchangeLoadQuery_5_4.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_4.wasm $(OUTDIR)/time rm -rf ./.dvm $(DVM) reset $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_4.wasm - $(OUTDIR)/time "$(DVM) run 1 start -t" "5, 4, " > $@ + $(OUTDIR)/time "$(DVM) run 1 start " "5, 4, " > $@ cat $@ $(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm $(OUTDIR)/time rm -rf ./.dvm $(DVM) reset $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm - $(OUTDIR)/time "$(DVM) run 1 start -t" "5, 5, " > $@ + $(OUTDIR)/time "$(DVM) run 1 start " "5, 5, " > $@ + cat $@ + +$(OUTDIR)/ProduceExchangeLoadQuery_5_6.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_6.wasm $(OUTDIR)/time + rm -rf ./.dvm + $(DVM) reset + $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_6.wasm + $(OUTDIR)/time "$(DVM) run 1 start " "5, 6, " > $@ + cat $@ + +$(OUTDIR)/ProduceExchangeLoadQuery_5_7.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_7.wasm $(OUTDIR)/time + rm -rf ./.dvm + $(DVM) reset + $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_7.wasm + $(OUTDIR)/time "$(DVM) run 1 start " "5, 7, " > $@ + cat $@ + +$(OUTDIR)/ProduceExchangeLoadQuery_5_8.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_8.wasm $(OUTDIR)/time + rm -rf ./.dvm + $(DVM) reset + $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_8.wasm + $(OUTDIR)/time "$(DVM) run 1 start " "5, 8, " > $@ + cat $@ + +$(OUTDIR)/ProduceExchangeLoadQuery_5_9.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_9.wasm $(OUTDIR)/time + rm -rf ./.dvm + $(DVM) reset + $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm + $(OUTDIR)/time "$(DVM) run 1 start " "5, 9, " > $@ cat $@ $(OUTDIR)/ProduceExchangeLoadQuery_5_10.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_10.wasm $(OUTDIR)/time rm -rf ./.dvm $(DVM) reset $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_10.wasm - $(OUTDIR)/time "$(DVM) run 1 start -t" "5, 10, " > $@ + $(OUTDIR)/time "$(DVM) run 1 start " "5, 10, " > $@ cat $@ $(OUTDIR)/ProduceExchangeLoadQuery_5_20.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_20.wasm $(OUTDIR)/time rm -rf ./.dvm $(DVM) reset $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_20.wasm - $(OUTDIR)/time "$(DVM) run 1 start -t" "5, 20, " > $@ + $(OUTDIR)/time "$(DVM) run 1 start " "5, 20, " > $@ cat $@ $(OUTDIR)/ProduceExchangeLoadQuery_5_50.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_50.wasm $(OUTDIR)/time rm -rf ./.dvm $(DVM) reset $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_50.wasm - $(OUTDIR)/time "$(DVM) run 1 start -t" "5, 50, " > $@ + $(OUTDIR)/time "$(DVM) run 1 start " "5, 50, " > $@ cat $@ $(OUTDIR)/ProduceExchangeLoadQuery_5_100.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_100.wasm $(OUTDIR)/time rm -rf ./.dvm $(DVM) reset $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_100.wasm - $(OUTDIR)/time "$(DVM) run 1 start -t" "5, 100, " > $@ + $(OUTDIR)/time "$(DVM) run 1 start " "5, 100, " > $@ cat $@ $(DOCDIR)/%.md: %.as $(MDofAS) | $(DOCDIR) diff --git a/stdlib/examples/produce-exchange/serverActor.as b/stdlib/examples/produce-exchange/serverActor.as index 916c944311a..3eaa89984fe 100644 --- a/stdlib/examples/produce-exchange/serverActor.as +++ b/stdlib/examples/produce-exchange/serverActor.as @@ -1075,12 +1075,7 @@ been processed //private var model : ?Model.Model = null; - private var model : ?Model.Model = { - // TEMP: - devTestLoadQuery(5, 2); - // - ?(Model.Model()); - }; + private var model : ?Model.Model = ?(Model.Model()); private getModel() : Model.Model { switch model { diff --git a/stdlib/examples/produce-exchange/test/params-5-6.as b/stdlib/examples/produce-exchange/test/params-5-6.as new file mode 100644 index 00000000000..931e109ee76 --- /dev/null +++ b/stdlib/examples/produce-exchange/test/params-5-6.as @@ -0,0 +1,3 @@ +let region_count = 5; +let scale_factor = 6; + diff --git a/stdlib/examples/produce-exchange/test/params-5-7.as b/stdlib/examples/produce-exchange/test/params-5-7.as new file mode 100644 index 00000000000..d4d1ac5b846 --- /dev/null +++ b/stdlib/examples/produce-exchange/test/params-5-7.as @@ -0,0 +1,3 @@ +let region_count = 5; +let scale_factor = 7; + diff --git a/stdlib/examples/produce-exchange/test/params-5-8.as b/stdlib/examples/produce-exchange/test/params-5-8.as new file mode 100644 index 00000000000..ef16d5899a8 --- /dev/null +++ b/stdlib/examples/produce-exchange/test/params-5-8.as @@ -0,0 +1,3 @@ +let region_count = 5; +let scale_factor = 8; + diff --git a/stdlib/examples/produce-exchange/test/params-5-9.as b/stdlib/examples/produce-exchange/test/params-5-9.as new file mode 100644 index 00000000000..3e72b6fd9cd --- /dev/null +++ b/stdlib/examples/produce-exchange/test/params-5-9.as @@ -0,0 +1,3 @@ +let region_count = 5; +let scale_factor = 9; + From e269c6b1d8441df7bfc05ee8620b0788af181db2 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 16 May 2019 14:07:38 -0400 Subject: [PATCH 0029/1176] clean up huge Makefile; improve timing util to report msec, not usec --- stdlib/Makefile | 243 ++++++++++++++++++++++++++++++------------------ stdlib/time.c | 29 ++++-- 2 files changed, 176 insertions(+), 96 deletions(-) diff --git a/stdlib/Makefile b/stdlib/Makefile index 9f3218db528..6f5c5141052 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -6,6 +6,38 @@ MDofAS=./markdown-of-actorscript.py MDofMD=./markdown-of-markdown.py PANDOC=pandoc +WASM=\ + ProduceExchange\ + loadWorkloadAndQueryBig\ + +OUTFILES=$(addsuffix .out, $(TESTS)) $(addsuffix .wasm, $(WASM)) + +OUTPATHS=$(addprefix $(OUTDIR)/, $(OUTFILES)) + +.PHONY: default all clean alltests alldoc docMd docHtml profile-wasm profile-wasm-success profile-interp profile-interp-small + +default: all + +docmsg: + @echo Begin building documentation in \`$(DOCDIR)\`... + @echo $(HRULE) + +alltests: $(OUTDIR) $(OUTPATHS) + +all: alltests alldoc profile-wasm-success profile-interp-small + +clean: + rm -rf $(OUTDIR) $(DOCDIR) + +$(OUTDIR): + @mkdir $@ + +#########################################################################################################33 + +## +## Unit tests +## + # Add new module targets here: TESTS=\ Option \ @@ -24,27 +56,77 @@ TESTS=\ retailerReserveMany \ evalBulk \ +$(OUTDIR)/Hash.out: hash.as | $(OUTDIR) + $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ -WASM=\ - ProduceExchange\ - loadWorkloadAndQueryBig\ +$(OUTDIR)/Option.out: option.as | $(OUTDIR) + $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ +$(OUTDIR)/Result.out: result.as | $(OUTDIR) + $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ -OUTFILES=$(addsuffix .out, $(TESTS)) $(addsuffix .wasm, $(WASM)) +$(OUTDIR)/List.out: list.as | $(OUTDIR) + $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ -OUTPATHS=$(addprefix $(OUTDIR)/, $(OUTFILES)) +$(OUTDIR)/ListTest.out: listTest.as | $(OUTDIR) + $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ -.PHONY: default all clean alltests alldoc docMd docHtml profile +$(OUTDIR)/AssocList.out: assocList.as | $(OUTDIR) + $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ -default: all +$(OUTDIR)/Trie.out: trie.as | $(OUTDIR) + $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ -docmsg: - @echo Begin building documentation in \`$(DOCDIR)\`... - @echo $(HRULE) +$(OUTDIR)/DocTable.out: docTable.as | $(OUTDIR) + $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ -alltests: $(OUTDIR) $(OUTPATHS) +$(OUTDIR)/Set.out: set.as | $(OUTDIR) + $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ + +$(OUTDIR)/SetDb.out: setDb.as | $(OUTDIR) + $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ + +$(OUTDIR)/SetDbTest.out: setDbTest.as | $(OUTDIR) + $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ + +#########################################################################################################33 + +## +## PX Unit tests +## + +PRODUCE_EXCHANGE_SRC=\ + prelude.as option.as hash.as list.as assocList.as trie.as docTable.as result.as \ + examples/produce-exchange/serverTypes.as \ + examples/produce-exchange/serverLang.as \ + examples/produce-exchange/serverModelTypes.as \ + examples/produce-exchange/serverModel.as \ + examples/produce-exchange/serverActor.as \ + +$(OUTDIR)/ProduceExchange.out: $(PRODUCE_EXCHANGE_SRC) \ + examples/produce-exchange/test/simpleSetupAndQuery.as | $(OUTDIR) + $(ASC) -r examples/produce-exchange/serverActor.as examples/produce-exchange/test/simpleSetupAndQuery.as > $@ + +$(OUTDIR)/retailerReserveMany.out: $(PRODUCE_EXCHANGE_SRC) \ + examples/produce-exchange/test/retailerReserveMany.as | $(OUTDIR) + $(ASC) -r examples/produce-exchange/serverActor.as examples/produce-exchange/test/retailerReserveMany.as > $@ + +$(OUTDIR)/producerRemInventory.out: $(PRODUCE_EXCHANGE_SRC) \ + examples/produce-exchange/test/producerRemInventory.as | $(OUTDIR) + $(ASC) -r examples/produce-exchange/serverActor.as examples/produce-exchange/test/producerRemInventory.as > $@ + +$(OUTDIR)/evalBulk.out: $(PRODUCE_EXCHANGE_SRC) \ + examples/produce-exchange/test/evalBulk.as | $(OUTDIR) + $(ASC) -r examples/produce-exchange/serverActor.as examples/produce-exchange/test/evalBulk.as > $@ -all: alltests alldoc +$(OUTDIR)/ProduceExchange.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) + $(ASC) -c --dfinity -o $@ examples/produce-exchange/serverActor.as + +#########################################################################################################33 + +## +## Documentation +## alldoc: docMd docHtml @@ -96,12 +178,6 @@ docHtml: \ $(DOCDIR)/ \ $(DOCDIR)/examples/produce-exchange/ -clean: - rm -rf $(OUTDIR) $(DOCDIR) - -$(OUTDIR): - @mkdir $@ - $(DOCDIR): mkdir $@ @@ -118,72 +194,24 @@ $(DOCDIR)/examples/produce-exchange/README.md: examples/produce-exchange/README. @echo "" >> $@ $(MDofMD) $< >> $@ -$(OUTDIR)/Hash.out: hash.as | $(OUTDIR) - $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/Option.out: option.as | $(OUTDIR) - $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/Result.out: result.as | $(OUTDIR) - $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/List.out: list.as | $(OUTDIR) - $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/ListTest.out: listTest.as | $(OUTDIR) - $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/AssocList.out: assocList.as | $(OUTDIR) - $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/Trie.out: trie.as | $(OUTDIR) - $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/DocTable.out: docTable.as | $(OUTDIR) - $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/Set.out: set.as | $(OUTDIR) - $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/SetDb.out: setDb.as | $(OUTDIR) - $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/SetDbTest.out: setDbTest.as | $(OUTDIR) - $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ - -PRODUCE_EXCHANGE_SRC=\ - prelude.as option.as hash.as list.as assocList.as trie.as docTable.as result.as \ - examples/produce-exchange/serverTypes.as \ - examples/produce-exchange/serverLang.as \ - examples/produce-exchange/serverModelTypes.as \ - examples/produce-exchange/serverModel.as \ - examples/produce-exchange/serverActor.as \ - -$(OUTDIR)/ProduceExchange.out: $(PRODUCE_EXCHANGE_SRC) \ - examples/produce-exchange/test/simpleSetupAndQuery.as | $(OUTDIR) - $(ASC) -r examples/produce-exchange/serverActor.as examples/produce-exchange/test/simpleSetupAndQuery.as > $@ - -$(OUTDIR)/retailerReserveMany.out: $(PRODUCE_EXCHANGE_SRC) \ - examples/produce-exchange/test/retailerReserveMany.as | $(OUTDIR) - $(ASC) -r examples/produce-exchange/serverActor.as examples/produce-exchange/test/retailerReserveMany.as > $@ - -$(OUTDIR)/producerRemInventory.out: $(PRODUCE_EXCHANGE_SRC) \ - examples/produce-exchange/test/producerRemInventory.as | $(OUTDIR) - $(ASC) -r examples/produce-exchange/serverActor.as examples/produce-exchange/test/producerRemInventory.as > $@ - -$(OUTDIR)/evalBulk.out: $(PRODUCE_EXCHANGE_SRC) \ - examples/produce-exchange/test/evalBulk.as | $(OUTDIR) - $(ASC) -r examples/produce-exchange/serverActor.as examples/produce-exchange/test/evalBulk.as > $@ +$(DOCDIR)/%.md: %.as $(MDofAS) | $(DOCDIR) + @echo "" > $@ + @echo "" >> $@ + @echo "" >> $@ + $(MDofAS) $< >> $@ -$(OUTDIR)/ProduceExchange.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c --dfinity -o $@ examples/produce-exchange/serverActor.as +$(DOCDIR)/%.html: $(DOCDIR)/%.md + $(PANDOC) -f gfm $^ > $@ #########################################################################################################33 ## -## Profiling targets +## Profiling ## +# to do: Fix my Makefile targets below to make the file shorter; +# There is lot of redundancy, but I don't know how to hack the Makefile to overcome it without also making it too complex. + PROFILE_LOAD_SRC=\ examples/produce-exchange/serverActor.as \ examples/produce-exchange/test/profileLoad.as @@ -213,12 +241,17 @@ profile-interp: \ $(OUTDIR)/profileLoadQuery.05-03.csv \ $(OUTDIR)/profileLoadQuery.05-04.csv \ $(OUTDIR)/profileLoadQuery.05-05.csv \ + $(OUTDIR)/profileLoadQuery.05-06.csv \ + $(OUTDIR)/profileLoadQuery.05-07.csv \ + $(OUTDIR)/profileLoadQuery.05-08.csv \ + $(OUTDIR)/profileLoadQuery.05-09.csv \ $(OUTDIR)/profileLoadQuery.05-10.csv \ $(OUTDIR)/profileLoadQuery.05-20.csv \ $(OUTDIR)/profileLoadQuery.05-50.csv \ $(OUTDIR)/profileLoadQuery.05-100.csv \ -## AS wishlist: the following various targets would be easier to relate if we could accept named AS values as CLI params; that feature would also obviate the need for the `param-X-Y.as` files used below: +## AS wishlist: the following various targets each take a params file that defines two variables used in the common test file. +## it would be better if we could accept named AS values as CLI params; that feature would obviate the need for the `param-X-Y.as` files used below: $(OUTDIR)/profileLoadQuery.05-01.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) time $(ASC) -r --profile examples/produce-exchange/test/params-5-1.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) @@ -235,6 +268,18 @@ $(OUTDIR)/profileLoadQuery.05-04.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUE $(OUTDIR)/profileLoadQuery.05-05.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) time $(ASC) -r --profile examples/produce-exchange/test/params-5-5.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) +$(OUTDIR)/profileLoadQuery.05-06.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) + time $(ASC) -r --profile examples/produce-exchange/test/params-5-6.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + +$(OUTDIR)/profileLoadQuery.05-07.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) + time $(ASC) -r --profile examples/produce-exchange/test/params-5-7.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + +$(OUTDIR)/profileLoadQuery.05-08.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) + time $(ASC) -r --profile examples/produce-exchange/test/params-5-8.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + +$(OUTDIR)/profileLoadQuery.05-09.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) + time $(ASC) -r --profile examples/produce-exchange/test/params-5-9.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + $(OUTDIR)/profileLoadQuery.05-10.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) time $(ASC) -r --profile examples/produce-exchange/test/params-5-10.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) @@ -247,7 +292,38 @@ $(OUTDIR)/profileLoadQuery.05-50.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUE $(OUTDIR)/profileLoadQuery.05-100.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) time $(ASC) -r --profile examples/produce-exchange/test/params-5-100.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) +# wasm binaries and time measurements for various-sized PX workloads +# +# these sizes all run without memory limitation issues; bigger sizes complain about growing memory +profile-wasm-success:\ + $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm.csv \ + \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_2.wasm \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_2.wasm.csv \ + \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_3.wasm \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_3.wasm.csv \ + \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_4.wasm \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_4.wasm.csv \ + \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm.csv \ + \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_6.wasm \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_6.wasm.csv \ + \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_7.wasm \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_7.wasm.csv \ + \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_8.wasm \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_8.wasm.csv \ + \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_9.wasm \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_9.wasm.csv \ +# wasm binaries and time measurements for various-sized PX workloads profile-wasm:\ $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm \ $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm.csv \ @@ -329,7 +405,7 @@ $(OUTDIR)/ProduceExchangeLoadQuery_5_100.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDI $(ASC) -c --dfinity -o $@ examples/produce-exchange/test/params-5-100.as examples/produce-exchange/profileActor.as -$(OUTDIR)/time: +$(OUTDIR)/time: time.c gcc time.c -o $@ $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm $(OUTDIR)/time @@ -422,12 +498,3 @@ $(OUTDIR)/ProduceExchangeLoadQuery_5_100.wasm.csv: $(OUTDIR)/ProduceExchangeLoad $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_100.wasm $(OUTDIR)/time "$(DVM) run 1 start " "5, 100, " > $@ cat $@ - -$(DOCDIR)/%.md: %.as $(MDofAS) | $(DOCDIR) - @echo "" > $@ - @echo "" >> $@ - @echo "" >> $@ - $(MDofAS) $< >> $@ - -$(DOCDIR)/%.html: $(DOCDIR)/%.md - $(PANDOC) -f gfm $^ > $@ diff --git a/stdlib/time.c b/stdlib/time.c index ab2df00e475..5bb84ddb647 100644 --- a/stdlib/time.c +++ b/stdlib/time.c @@ -1,24 +1,37 @@ -#include -#include -#include +#include +#include +#include #include int main(int argc, char** args) { struct timeval tv_0; struct timeval tv_1; + + if (argc < 2) { + fprintf(stderr, "usage: %s \n", args[0]); + return -1; + } + gettimeofday(&tv_0,0); + // + // first argument is the command to run and time: + // system(args[1]); gettimeofday(&tv_1,0); - printf("%s%d\n", + printf("%s%.3f\n", // // second argument is the line prefix for the output... // args[2], // - // ...and line ends with time, in micro seconds. + // ...and the output line ends with the measured time, in milliseconds. // - (int) ((tv_1.tv_sec - tv_0.tv_sec) * 1000000) - + - (int) (tv_1.tv_usec - tv_0.tv_usec) + ((float) + ( + (int) ((tv_1.tv_sec - tv_0.tv_sec) * 1000000) + + + (int) (tv_1.tv_usec - tv_0.tv_usec) ) + ) + / 1000.0f ); } From 56081d4177ee641511b6e55be6a2e4eac84c71e1 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Thu, 16 May 2019 11:36:11 -0700 Subject: [PATCH 0030/1176] Add LSP module --- src/LSP.ml | 40 ++++++++++++++++++++++++++++++++++++++++ src/LSP.mli | 11 +++++++++++ src/languageServer.ml | 28 +++++++--------------------- 3 files changed, 58 insertions(+), 21 deletions(-) create mode 100644 src/LSP.ml create mode 100644 src/LSP.mli diff --git a/src/LSP.ml b/src/LSP.ml new file mode 100644 index 00000000000..71200070455 --- /dev/null +++ b/src/LSP.ml @@ -0,0 +1,40 @@ +open Yojson.Basic.Util + +let jsonrpc_version = "2.0" +let jsonrpc_field = ("jsonrpc", `String jsonrpc_version) + +let from_int_option = + function + | None -> `Null + | Some i -> `Int i + +type received_message = + { id : int option + ; method_ : string + ; params : Yojson.Basic.t + } + +(* Parse and LSP request message or notification *) +let parse json = + (* if json |> member "jsonrpc" |> to_string = jsonrpc_version + * then Some *) + { id = json |> member "id" |> to_int_option (* notifications omit id *) + ; method_ = json |> member "method" |> to_string + ; params = json |> member "params" + } + (* else None *) + +(* Construct an LSP response message *) +let response id result error = `Assoc + [ jsonrpc_field + ; ("id", from_int_option id) + ; ("result", result) + ; ("error", error) + ] + +(* Construct an LSP notification message *) +let notification method_ params = `Assoc + [ jsonrpc_field + ; ("method", `String method_) + ; ("params", `Assoc params) + ] diff --git a/src/LSP.mli b/src/LSP.mli new file mode 100644 index 00000000000..3c948bffbe2 --- /dev/null +++ b/src/LSP.mli @@ -0,0 +1,11 @@ +type received_message = + { id : int option + ; method_ : string + ; params : Yojson.Basic.t + } + +val parse : Yojson.Basic.t -> received_message (* option *) + +val response : int option -> Yojson.Basic.t -> Yojson.Basic.t -> Yojson.Basic.t + +val notification : string -> (string * Yojson.Basic.t) list -> Yojson.Basic.t diff --git a/src/languageServer.ml b/src/languageServer.ml index 7f121bfc916..b7973b4c6c6 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -34,20 +34,16 @@ let start () = log_to_file raw; let json = Yojson.Basic.from_string raw in - let open Yojson.Basic.Util in - let jsonrpc = json |> member "jsonrpc" |> to_string in - let id = json |> member "id" |> to_int_option in - let method_ = json |> member "method" |> to_string in - (* let params = json |> member "params" in *) + let received = LSP.parse json in let string_of_int_option = function | None -> "None" - | Some id -> string_of_int id in + | Some i -> string_of_int i in - log_to_file (jsonrpc ^ ", " ^ string_of_int_option id ^ ", " ^ method_); + log_to_file (string_of_int_option received.LSP.id ^ ", " ^ received.LSP.method_); - if method_ = "initialize" + if received.LSP.method_ = "initialize" then begin log_to_file "Handle initialize"; let capabilities = `Assoc @@ -56,27 +52,17 @@ let start () = let result = `Assoc [ ("capabilities", capabilities) ] in - let response = `Assoc - [ ("jsonrpc", `String "2.0") - ; ("id", json |> member "id") - ; ("result", result) - ; ("error", `Null) - ] in + let response = LSP.response received.LSP.id result `Null in respond (Yojson.Basic.pretty_to_string response); end - else if method_ = "initialized" + else if received.LSP.method_ = "initialized" then begin log_to_file "Handle initialized"; - let params = `Assoc + let notification = LSP.notification "window/showMessage" [ ("type", `Int 3) ; ("message", `String "Language server initialized") ] in - let notification = `Assoc - [ ("jsonrpc", `String "2.0") - ; ("method", `String "window/showMessage") - ; ("params", params) - ] in respond (Yojson.Basic.pretty_to_string notification); end From 3b3eec567e7461fc121e91cbe7f2969e7848d289 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Thu, 16 May 2019 14:49:34 -0700 Subject: [PATCH 0031/1176] [WIP] Use ATD --- default.nix | 5 ++++ nix/ocamlbuild-atdgen.nix | 33 ++++++++++++++++++++++++ src/Makefile | 3 ++- src/languageServer.ml | 6 +++++ src/lsp2.atd | 53 +++++++++++++++++++++++++++++++++++++++ src/myocamlbuild.ml | 4 ++- 6 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 nix/ocamlbuild-atdgen.nix create mode 100644 src/lsp2.atd diff --git a/default.nix b/default.nix index fc43aef96d5..a494c7c355c 100644 --- a/default.nix +++ b/default.nix @@ -30,6 +30,8 @@ let ocaml_vlq = import ./nix/ocaml-vlq.nix { let ocaml_bisect_ppx = import ./nix/ocaml-bisect_ppx.nix nixpkgs; in let ocaml_bisect_ppx-ocamlbuild = import ./nix/ocaml-bisect_ppx-ocamlbuild.nix nixpkgs; in +let ocamlbuild-atdgen = import ./nix/ocamlbuild-atdgen.nix nixpkgs; in + # Include dvm let real-dvm = if dvm == null @@ -47,6 +49,7 @@ let real-dvm = let commonBuildInputs = [ nixpkgs.ocaml + nixpkgs.ocamlPackages.atdgen nixpkgs.ocamlPackages.menhir nixpkgs.ocamlPackages.findlib nixpkgs.ocamlPackages.ocamlbuild @@ -57,6 +60,7 @@ let commonBuildInputs = [ nixpkgs.ocamlPackages.yojson ocaml_bisect_ppx ocaml_bisect_ppx-ocamlbuild + ocamlbuild-atdgen ]; in let @@ -147,6 +151,7 @@ rec { src = sourceByRegex ./. [ "src/" "src/Makefile.*" + "src/.*.atd" "src/.*.ml" "src/.*.mli" "src/.*.mly" diff --git a/nix/ocamlbuild-atdgen.nix b/nix/ocamlbuild-atdgen.nix new file mode 100644 index 00000000000..cfb0f7cd8d9 --- /dev/null +++ b/nix/ocamlbuild-atdgen.nix @@ -0,0 +1,33 @@ +pkgs: + +let repo = "ocamlbuild-atdgen"; in +let rev = "v0.1.0"; in + +pkgs.stdenv.mkDerivation { + name = "ocaml${pkgs.ocaml.version}-${repo}-${rev}"; + + src = pkgs.fetchFromGitHub { + inherit repo rev; + owner = "rgrinberg"; + sha256 = "0wxgvgb8j6ajdzqwzxldvnwfblgbkhgycwmrkmrq8dcjim0mg8ah"; + }; + + buildInputs = with pkgs; [ + ocaml + ocamlPackages.findlib + ocamlPackages.ocamlbuild + ]; + + createFindlibDestdir = true; + + installPhase = '' + make install + ''; + + meta = { + homepage = https://github.com/rgrinberg/ocamlbuild-atdgen; + platforms = pkgs.ocaml.meta.platforms or []; + description = "ocamlbuild plugin for atdgen"; + license = pkgs.stdenv.lib.licenses.isc; + }; +} diff --git a/src/Makefile b/src/Makefile index 5b798dc2515..bca0fe8415e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -5,7 +5,7 @@ JS_MAIN = js_main ASC = `pwd`/$(NAME) -OPAM_PACKAGES = wasm num vlq yojson bisect_ppx-ocamlbuild +OPAM_PACKAGES = wasm num vlq yojson bisect_ppx-ocamlbuild atdgen JS_OPAM_PACKAGES = js_of_ocaml js_of_ocaml-ppx MENHIR = menhir @@ -15,6 +15,7 @@ OCAML_FLAGS = -cflags '-w +a-4-27-30-42-44-45-58 -warn-error +a' OCAMLBUILD = ocamlbuild $(OCAML_FLAGS) \ -use-ocamlfind \ -plugin-tag 'package(bisect_ppx-ocamlbuild)' \ + -plugin-tag 'package(ocamlbuild_atdgen)' \ -use-menhir -menhir "$(MENHIR) $(MENHIR_FLAGS)" \ -I src \ -I lib \ diff --git a/src/languageServer.ml b/src/languageServer.ml index b7973b4c6c6..20db5517c43 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -34,6 +34,12 @@ let start () = log_to_file raw; let json = Yojson.Basic.from_string raw in + + let json2 = Lsp2_j.message_of_string raw in + (* let open Yojson.Basic.Util in + * log_to_file (json2 |> member "jsonrpc" |> to_string); *) + log_to_file (json2.Lsp2_t.message_jsonrpc); + let received = LSP.parse json in let string_of_int_option = diff --git a/src/lsp2.atd b/src/lsp2.atd new file mode 100644 index 00000000000..52fedc0b13a --- /dev/null +++ b/src/lsp2.atd @@ -0,0 +1,53 @@ +type message = + { jsonrpc : string + } + + +(* +type 'a request_message = + { inherit message + ; id : int + ; method : string + ; params : 'a + } + +*) + +(* +type ('a, 'b) response_message = + { inherit message + ; id : int + ; ?result : 'a option + (* ; ?error : (b' response_error) option *) + ; ?error : 'b option + } + +type 'a response_error = + { code : error_code + ; message : string + ; ?data : 'a option + } + +type error_code = + (* Defined by JSON RPC *) + [ ParseError + | InvalidRequest + | MethodNotFound + | InvalidParams + | InternalError + | ServerErrorStart + | ServerErrorEnd + | ServerNotInitialized + | UnknownErrorCode + + (* Defined by the protocol *) + | RequestCancelled + | ContentModified + ] + +type 'a notification_message = + { jsonrpc : string + ; method : string + ; ?params : 'a option + } +*) \ No newline at end of file diff --git a/src/myocamlbuild.ml b/src/myocamlbuild.ml index 3d5ad4ee44c..fdfc99f3b10 100644 --- a/src/myocamlbuild.ml +++ b/src/myocamlbuild.ml @@ -1,2 +1,4 @@ open Ocamlbuild_plugin -let () = dispatch Bisect_ppx_plugin.dispatch +let () = + dispatch Bisect_ppx_plugin.dispatch; + dispatch Ocamlbuild_atdgen.dispatcher From 28a889970c9d44903d9d18bbece6c7bb0aa8b04a Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 16 May 2019 17:54:39 -0400 Subject: [PATCH 0032/1176] collect counts of PX workload sizes without actually loading or running it --- stdlib/Makefile | 17 +++++- .../examples/produce-exchange/serverModel.as | 61 +++++++++++++++++++ .../test/profileFastCounts.as | 33 ++++++++++ 3 files changed, 108 insertions(+), 3 deletions(-) create mode 100644 stdlib/examples/produce-exchange/test/profileFastCounts.as diff --git a/stdlib/Makefile b/stdlib/Makefile index 6f5c5141052..0d83013852c 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -230,10 +230,21 @@ PROFILE_FIELDS=\ --profile-field "retailer_query_cost" \ --profile-field "retailer_query_size_max" \ +## +## To see the sizes of the workloads below, run `make profile-fast-counts`: +## + +profile-fast-counts: \ + $(OUTDIR)/profileFastCounts.csv + +$(OUTDIR)/profileFastCounts.csv: examples/produce-exchange/test/profileFastCounts.as + $(ASC) -r examples/produce-exchange/test/profileFastCounts.as > $@ + + profile-interp-small: \ - $(OUTDIR)/profileLoadQuery.04-05-01.csv \ - $(OUTDIR)/profileLoadQuery.04-05-02.csv \ - $(OUTDIR)/profileLoadQuery.04-05-03.csv \ + $(OUTDIR)/profileLoadQuery.05-01.csv \ + $(OUTDIR)/profileLoadQuery.05-02.csv \ + $(OUTDIR)/profileLoadQuery.05-03.csv \ profile-interp: \ $(OUTDIR)/profileLoadQuery.05-01.csv \ diff --git a/stdlib/examples/produce-exchange/serverModel.as b/stdlib/examples/produce-exchange/serverModel.as index 1590768dacf..94b667d82c5 100644 --- a/stdlib/examples/produce-exchange/serverModel.as +++ b/stdlib/examples/produce-exchange/serverModel.as @@ -352,6 +352,67 @@ class Model() { ) }; + /** + `countAddReqs` + ------------- + xxx + */ + countAddReqs( + day_count:Nat, + max_route_duration:Nat, + producer_count:Nat, + transporter_count:Nat, + retailer_count:Nat, + region_count:Nat + ) : (Nat, Nat) { + var inventoryCount : Nat = 0; + var routeCount : Nat = 0; + + assert(region_count > 0); + func min(x:Nat, y:Nat) : Nat = if (x < y) { x } else { y }; + + /**- add routes and inventory, across time and space: */ + for (start_day in range(0, day_count-1)) { + + let max_end_day = + min( start_day + max_route_duration, + day_count - 1 ); + + for (end_day in range(start_day, max_end_day)) { + + /**- consider all pairs of start and end region: */ + for (start_reg in range(0, region_count - 1)) { + for (end_reg in range(0, region_count - 1)) { + + /**- for each producer we choose, + add inventory that will be ready on "start_day", but not beforehand. + It will remain ready until the end of the day count. */ + + for (p in range(0, producer_count - 1)) { + /**- choose this producer iff they are located in the start region: */ + if ((p % region_count) == start_reg) { + inventoryCount := inventoryCount + 1; + }; + }; + + /**- for each transporter we choose, + add a route that will start and end on the current values + of `start_day`, `end_day`, `start_reg`, `end_reg`, respectively: */ + + for (t in range(0, transporter_count - 1)) { + /**- choose this transporter iff their id matches the id of the region, modulo the number of regions: */ + if ((t % region_count) == start_reg) { + routeCount := routeCount + 1; + } + } + }; + }; + }; + }; + + return (inventoryCount, routeCount) + }; + /** `genAddReqs` ------------- diff --git a/stdlib/examples/produce-exchange/test/profileFastCounts.as b/stdlib/examples/produce-exchange/test/profileFastCounts.as new file mode 100644 index 00000000000..c45d79ce2e9 --- /dev/null +++ b/stdlib/examples/produce-exchange/test/profileFastCounts.as @@ -0,0 +1,33 @@ +// print a table of numbers (somewhat) quickly. +// we correlate these numbers with times that we +// measure elsewhere, where these numbers are not available. + +let T = (import "../serverTypes.as"); +let Model = (import "../serverModel.as"); + +let m = Model.Model(); + +let scales = [1,2,3,4,5,6,7,8,9,10, + 20,50,100]; + +print "# column: region count\n"; +print "# column: workload scale\n"; +print "# column: inventory count\n"; +print "# column: route count\n"; + +for (scale in scales.vals()) { + let (ic, rc) = m.countAddReqs(3, 1, + 5 * scale, + 5 * scale, + 5 * scale, + 5); + + printInt 5; + print ", "; + printInt scale; + print ", "; + printInt ic; + print ", "; + printInt rc; + print "\n"; +}; From e8e79bd32511ae306ec2d2b54e383d0a5d845bd9 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Thu, 16 May 2019 17:47:13 -0700 Subject: [PATCH 0033/1176] [WIP] Debug variant decoding --- src/languageServer.ml | 9 +++--- src/lsp2.atd | 73 +++++++++++++++++++++++++++++++++---------- src/lsp2.ml | 7 +++++ 3 files changed, 69 insertions(+), 20 deletions(-) create mode 100644 src/lsp2.ml diff --git a/src/languageServer.ml b/src/languageServer.ml index 20db5517c43..eaa1daa3853 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -35,10 +35,11 @@ let start () = let json = Yojson.Basic.from_string raw in - let json2 = Lsp2_j.message_of_string raw in - (* let open Yojson.Basic.Util in - * log_to_file (json2 |> member "jsonrpc" |> to_string); *) - log_to_file (json2.Lsp2_t.message_jsonrpc); + let json2 = Lsp2_j.incoming_message_of_string raw in + let jsonrpc = json2.Lsp2_t.incoming_message_jsonrpc in + (* let method_ = Lsp2_j.string_of_incoming_message_method json2.Lsp2_t.incoming_message_method in *) + (* log_to_file ("jsonrpc: " ^ jsonrpc ^ ", method: " ^ method_); *) + log_to_file ("jsonrpc: " ^ jsonrpc); let received = LSP.parse json in diff --git a/src/lsp2.atd b/src/lsp2.atd index 52fedc0b13a..ec6070af38c 100644 --- a/src/lsp2.atd +++ b/src/lsp2.atd @@ -1,31 +1,78 @@ +(* Abstract message *) + type message = { jsonrpc : string } -(* -type 'a request_message = + +(* Incoming messages *) + +(* Incoming messages may be either request or notification messages. The latter + omits the `id` field. *) + +type incoming_message = { inherit message - ; id : int - ; method : string - ; params : 'a + ; ?id : int nullable + ; method : incoming_message_method + } + + +type incoming_message_method = + [ Initialize of initialize_params + | Initialized + ] + + +(* Outgoing messages *) + +(* Outgoing messages may be either response or notification messages. The latter + omits the `id` field. *) + +type outgoing_message_method = + [ WindowShowMessage + ] + + +(* "initialize" request message *) + +type initialize_params = + { ?processId : int nullable + ; ?rootPath : string nullable + (*; rootUri : document_uri nullable*) + (*; ?initializationOptions : any*) + (*; capabilities : client_capabilities*) + (*; ?trace : trace nullable*) + (*; ?workspaceFolders : (workspace_folder list) nullable*) + } + +(* +type client_capabilities = + { ?workspace : workspace_client_capabilities + ; ?textDocument : text_document_client_capabilities + ; ?experimental : any } - *) +type trace = + [ Off + | Messages + | Verbose + ] + + (* type ('a, 'b) response_message = { inherit message ; id : int - ; ?result : 'a option - (* ; ?error : (b' response_error) option *) - ; ?error : 'b option + ; ?result : 'a nullable + ; ?error : 'b } type 'a response_error = { code : error_code ; message : string - ; ?data : 'a option + ; ?data : 'a } type error_code = @@ -44,10 +91,4 @@ type error_code = | RequestCancelled | ContentModified ] - -type 'a notification_message = - { jsonrpc : string - ; method : string - ; ?params : 'a option - } *) \ No newline at end of file diff --git a/src/lsp2.ml b/src/lsp2.ml new file mode 100644 index 00000000000..7f11e9da42b --- /dev/null +++ b/src/lsp2.ml @@ -0,0 +1,7 @@ +module Message_adapter = Atdgen_runtime.Json_adapter.Type_and_value_fields.Make( + struct + let type_field_name = "method" + let value_field_name = "params" + let known_tags = None + end +) From 007c1e175f02fed8c2db84c8b069eb1a41a42e81 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Thu, 16 May 2019 18:07:57 -0700 Subject: [PATCH 0034/1176] [WIP] Add comment about ATD issue --- src/lsp2.atd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lsp2.atd b/src/lsp2.atd index ec6070af38c..a50764d26aa 100644 --- a/src/lsp2.atd +++ b/src/lsp2.atd @@ -19,7 +19,7 @@ type incoming_message = type incoming_message_method = - [ Initialize of initialize_params + [ Initialize (*of initialize_params*) (* <-- uncomment to trigger decoding issue *) | Initialized ] From f9705a8ae31ed468b44abdb45601e0a259b80c29 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Thu, 16 May 2019 18:10:36 -0700 Subject: [PATCH 0035/1176] Move link to LSP spec --- src/languageServer.ml | 2 -- src/lsp2.atd | 3 +++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/languageServer.ml b/src/languageServer.ml index eaa1daa3853..ee838b71890 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -1,5 +1,3 @@ -(* https://microsoft.github.io/language-server-protocol/specification *) - let oc = open_out_gen [Open_append; Open_creat] 0o666 "ls.log" let log_to_file txt = Printf.fprintf oc "%s\n" txt; diff --git a/src/lsp2.atd b/src/lsp2.atd index a50764d26aa..19faae1b9c0 100644 --- a/src/lsp2.atd +++ b/src/lsp2.atd @@ -1,3 +1,6 @@ +(* https://microsoft.github.io/language-server-protocol/specification *) + + (* Abstract message *) type message = From 925cf54481e48e9e3995566050132b809b036435 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Fri, 17 May 2019 10:26:30 -0400 Subject: [PATCH 0036/1176] csv output contains source labels, for human-readable region names, indep of line numbers --- src/counters.ml | 77 +++++++++++++++++++++++++++++++++++---------- src/interpret.ml | 7 +++-- src/interpret_ir.ml | 4 +-- stdlib/assocList.as | 5 ++- stdlib/hash.as | 16 +++++++--- stdlib/trie.as | 20 +++++++++--- 6 files changed, 99 insertions(+), 30 deletions(-) diff --git a/src/counters.ml b/src/counters.ml index 024d5f34800..25156fbbc94 100644 --- a/src/counters.ml +++ b/src/counters.ml @@ -10,18 +10,29 @@ such as search, sorting, etc. open Source -type t = (region, int) Hashtbl.t +type t = { + label : ((region * string), int) Hashtbl.t ; + region : (region, int) Hashtbl.t ; + } let dump_count = ref 0 -let zeros () = - Hashtbl.create 100 +let zeros () = { + label = Hashtbl.create 100 ; + region = Hashtbl.create 100 ; + } -let bump c reg = +let bump_region c reg = if !Flags.profile then - match Hashtbl.find_opt c reg with - Some n -> Hashtbl.replace c reg (n + 1) - | None -> Hashtbl.replace c reg 1 + match Hashtbl.find_opt c.region reg with + Some n -> Hashtbl.replace c.region reg (n + 1) + | None -> Hashtbl.replace c.region reg 1 + +let bump_label c reg lab = + if !Flags.profile then + match Hashtbl.find_opt c.label (reg, lab) with + Some n -> Hashtbl.replace c.label (reg, lab) (n + 1) + | None -> Hashtbl.replace c.label (reg, lab) 1 (* lexicographic on (left.file, left.line, left.column, right.line, right.column) *) let region_order rega regb = @@ -39,6 +50,9 @@ let region_order rega regb = else compare rega.left.file regb.left.file +let label_order laba labb = + compare laba labb + let dump (c:t) (ve: Value.value Value.Env.t) = if !Flags.profile then if !Flags.profile_verbose then ( @@ -56,12 +70,39 @@ let dump (c:t) (ve: Value.value Value.Env.t) = d end in - let counts = Hashtbl.fold (fun region count counts -> (region, count) :: counts) c [] in - let counts = List.sort (fun (rega, x) (regb, y) -> - let diff = x - y in - if diff <> 0 then -diff else - region_order rega regb - ) counts + (* Include all labeled regions in the final table: *) + let labeled_counts = + Hashtbl.fold ( + fun (reg, label) count counts -> + ((reg, Some label), count) :: counts) + c.label [] + in + (* Include all other regions in the final table: *) + let all_region_counts = + Hashtbl.fold ( + fun reg count counts -> + ((reg, None), count) :: counts) + c.region labeled_counts + in + let sorted_counts = + List.sort ( + (* Final ordering: + - counts; bigger first; this is the main ordering constraint. + - labels; labeled expressions before unlabeled + - regions; earlier/outer regions before later/enclosed ones + *) + fun + ((rega, laba), x) + ((regb, labb), y) + -> + let diff = x - y in + if diff <> 0 then -diff else + match (laba, labb) with + (Some _, None) -> -1 + | (None, Some _) -> 1 + | (Some _, Some _) -> label_order laba labb + | (None, None) -> region_order rega regb + ) all_region_counts in let file = open_out (!Flags.profile_file) in let (suffix, flds) = @@ -77,12 +118,16 @@ let dump (c:t) (ve: Value.value Value.Env.t) = Printf.fprintf file "# column: source region count\n" ; List.iter (fun fld -> Printf.fprintf file "# column: --profile-field: %s\n" fld) (List.rev flds) ; - List.iter (fun (region, region_count) -> + List.iter (fun ((region, labop), region_count) -> assert (dump_count = 0); - Printf.fprintf file "%s\"%s\", %d%s\n" + Printf.fprintf file "%s\"%s\", %s, %d%s\n" (!Flags.profile_line_prefix) (string_of_region region) + (match labop with + None -> "null" + | Some x -> Printf.sprintf "?\"%s\"" x + ) region_count suffix - ) counts; + ) sorted_counts; close_out file diff --git a/src/interpret.ml b/src/interpret.ml index 18390d07d47..bdbf3a5582e 100644 --- a/src/interpret.ml +++ b/src/interpret.ml @@ -75,7 +75,7 @@ let string_of_arg = function let last_env = ref (env_of_scope empty_scope) let last_region = ref Source.no_region -let region_counters : Counters.t = Counters.zeros () +let profile_counters : Counters.t = Counters.zeros () let print_exn exn = Printf.printf "%!"; @@ -247,7 +247,7 @@ let rec interpret_exp env exp (k : V.value V.cont) = and interpret_exp_mut env exp (k : V.value V.cont) = last_region := exp.at; last_env := env; - Counters.bump region_counters exp.at ; + Counters.bump_region profile_counters exp.at ; match exp.it with | PrimE s -> k (V.Func (V.call_conv_of_typ exp.note.note_typ, Prelude.prim s)) @@ -406,6 +406,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = ) | LabelE (id, _typ, exp1) -> let env' = {env with labs = V.Env.add id.it k env.labs} in + Counters.bump_label profile_counters id.at id.it ; interpret_exp env' exp1 k | BreakE (id, exp1) -> interpret_exp env exp1 (find id.it env.labs) @@ -741,4 +742,4 @@ let interpret_library scope (filename, p) : scope = let dump_profile (results: Value.value Value.Env.t) = - Counters.dump region_counters results + Counters.dump profile_counters results diff --git a/src/interpret_ir.ml b/src/interpret_ir.ml index a8f0cd2f0d8..57d353b7d65 100644 --- a/src/interpret_ir.ml +++ b/src/interpret_ir.ml @@ -62,7 +62,7 @@ let string_of_arg = function let last_env = ref (env_of_scope empty_scope) let last_region = ref Source.no_region -let region_counters : Counters.t = Counters.zeros () +let profile_counters : Counters.t = Counters.zeros () let print_exn exn = Printf.printf "%!"; @@ -264,7 +264,7 @@ let rec interpret_exp env exp (k : V.value V.cont) = and interpret_exp_mut env exp (k : V.value V.cont) = last_region := exp.at; last_env := env; - Counters.bump region_counters exp.at ; + Counters.bump_region profile_counters exp.at ; match exp.it with | PrimE s -> let at = exp.at in diff --git a/stdlib/assocList.as b/stdlib/assocList.as index b43de184c2d..8d28e0116f6 100644 --- a/stdlib/assocList.as +++ b/stdlib/assocList.as @@ -25,16 +25,19 @@ type AssocList = List.List<(K,V)>; : ?V { func rec(al:AssocList) : ?V { + label profile_assocList_find_rec : (?V) switch (al) { - case (null) null; + case (null) { label profile_assocList_find_end_fail : (?V) null }; case (?((hd_k, hd_v), tl)) { if (k_eq(k, hd_k)) { + label profile_assocList_find_end_success : (?V) ?hd_v } else { rec(tl) } }; }}; + label profile_assocList_find_begin : (?V) rec(al) }; diff --git a/stdlib/hash.as b/stdlib/hash.as index 4356fb63434..a0e8c163407 100644 --- a/stdlib/hash.as +++ b/stdlib/hash.as @@ -48,7 +48,9 @@ module BitVec { type t = BitVec; - func length() : Nat = 31; + func length() : Nat = + label profile_hash_length : Nat + 31; func hashOfInt(i:Int) : BitVec { hashInt(i) @@ -69,16 +71,22 @@ module BitVec { }; /** Project a given bit from the bit vector. */ - func getHashBit(h:BitVec, pos:Nat) : Bool { + func getHashBit(h:BitVec, pos:Nat) : Bool = + label profile_getHashBit : Bool { assert (pos <= length()); if ((h & (natToWord32(1) << natToWord32(pos))) != natToWord32(0)) - { true } + { label profile_getHashBit_true : Bool + true + } else - { false } + { label profile_getHashBit_false : Bool + false + } }; /** Test if two lists of bits are equal. */ func hashEq(ha:BitVec, hb:BitVec) : Bool { + label profile_hashEq : Bool ha == hb }; diff --git a/stdlib/trie.as b/stdlib/trie.as index 45fe8d6e8ab..ae12a267388 100644 --- a/stdlib/trie.as +++ b/stdlib/trie.as @@ -384,10 +384,12 @@ type Trie3D = Trie >; func find(t : Trie, k:Key, k_eq:(K,K) -> Bool) : ?V { let key_eq = keyEq(k_eq); // For `bitpos` in 0..HASH_BITS, walk the given trie and locate the given value `x`, if it exists. - func rec(t : Trie, bitpos:Nat) : ?V { + func rec(t : Trie, bitpos:Nat) : ?V { label profile_trie_find_rec : (?V) if ( bitpos < HASH_BITS ) { + label profile_trie_find_bitpos_lt_hash_bits : (?V) switch t { case null { + label profile_trie_find_end_null : (?V) // the trie may be "sparse" along paths leading to no keys, and may end early. null }; @@ -399,16 +401,19 @@ type Trie3D = Trie >; }; } } else { + label profile_trie_find_bitpos_gte_hash_bits : (?V) // No more walking; we should be at a leaf now, by construction invariants. switch t { case null { null }; case (?l) { + label profile_trie_find_end_assocList_find : (?V) // Permit hash collisions by walking a list/array of KV pairs in each leaf: AssocList.find,V>(l.keyvals, k, key_eq) }; } } }; + label profile_trie_find_begin : (?V) rec(t, 0) }; @@ -911,21 +916,26 @@ type Trie3D = Trie >; To do: make this more efficient, using a single array allocation. */ - func toArray(t:Trie,f:(K,V)->[W]):[W]{ + func toArray(t:Trie,f:(K,V)->[W]):[W] = + label profile_trie_toArray_begin : [W] { func arrayAppend(x:[W],y:[W]):[W] { + label profile_trie_toArray_arrayAppend : [W] Array_tabulate ( x.len() + y.len(), func (i:Nat) : W { + label profile_trie_toArray_arrayAppend_projelm : W if (i >= x.len()) { y[i - x.len()] } else { x[i] } } ) }; - foldUp + let result = foldUp (t, arrayAppend, func(k:K, v:V):[W]{f(k,v)}, - []) + []); + label profile_trie_toArray_end : [W] + result }; /** @@ -1074,6 +1084,7 @@ type Trie3D = Trie >; // Equality function for two `Key`s, in terms of equaltiy of `K`'s. func keyEq(keq:(K,K) -> Bool) : ((Key,Key) -> Bool) = { func (key1:Key, key2:Key) : Bool = + label profile_trie_keyEq : Bool (Hash.hashEq(key1.hash, key2.hash) and keq(key1.key, key2.key)) }; @@ -1094,6 +1105,7 @@ type Trie3D = Trie >; // XXX: until AST-42: func assertIsNull(x : ?X) { + label profile_trie_assertIsNull switch x { case null { assert(true) }; case (?_) { assert(false) }; From fbdc860f566410a4a6fcfe1f16c66496e30e88e5 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Fri, 17 May 2019 11:38:04 -0400 Subject: [PATCH 0037/1176] label the source of 'real work' in the PX model logic, to contrast with collections work --- .../examples/produce-exchange/serverModel.as | 29 +++++++++++++++++-- stdlib/trie.as | 3 +- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/stdlib/examples/produce-exchange/serverModel.as b/stdlib/examples/produce-exchange/serverModel.as index 94b667d82c5..ad91c1cccb4 100644 --- a/stdlib/examples/produce-exchange/serverModel.as +++ b/stdlib/examples/produce-exchange/serverModel.as @@ -1824,6 +1824,8 @@ than the MVP goals, however. queryProduce:?T.ProduceId, queryDate:?T.Date) : Bool + = + label profile_isFeasibleReservation_begin : Bool { switch queryProduce { @@ -1831,6 +1833,7 @@ than the MVP goals, however. case (?qp) { if (item.produce.id != qp) { debugOff "nope: wrong produce kind\n"; + label profile_isFeasibleReservation_false_wrong_product_kind return false }; }; @@ -1840,6 +1843,7 @@ than the MVP goals, however. case (?qd) { if (route.end_date > qd ) { debugOff "nope: route arrives too late\n"; + label profile_isFeasibleReservation_false_arrives_too_late return false } } @@ -1847,19 +1851,23 @@ than the MVP goals, however. /** - window start: check that the route begins after the inventory window begins */ if (not (item.start_date <= route.start_date)) { debugOff "nope: item start after route start\n"; + label profile_isFeasibleReservation_false_item_start_ater_route_start return false }; /** - window end: check that the route ends before the inventory window ends */ if (not (route.end_date <= item.end_date)) { debugOff "nope: route ends after item ends\n"; + label profile_isFeasibleReservation_false_item_route_ends_after_item_ends return false }; /** - check that truck can carry the given produce */ if (not isCompatibleTruckType(route.truck_type, item.produce)) { debugOff "nope: truck is not compatible\n"; + label profile_isFeasibleReservation_false_truck_is_not_compatible return false }; /** - all checks pass: */ + label profile_isFeasibleReservation_true : Bool true }; @@ -1886,7 +1894,8 @@ than the MVP goals, however. id:T.RetailerId, queryProduce:?T.ProduceId, queryDate:?T.Date - ) : ?T.QueryAllResults + ) : ?T.QueryAllResults = + label profile_retailerQueryAll_begin : (?T.QueryAllResults) { retailerQueryCount += 1; @@ -1930,6 +1939,8 @@ than the MVP goals, however. idIsEq, func (routes:M.RouteMap, inventory:M.ByProducerInventoryMap) : RouteInventoryMap + = + label profile_retailerQueryAll_product_region : RouteInventoryMap { /** - Within this production region, consider every route-item pairing: */ @@ -1948,14 +1959,28 @@ than the MVP goals, however. item :M.InventoryDoc) : ?(Key<(T.RouteId, T.InventoryId)>, (M.RouteDoc, M.InventoryDoc)) + = + label profile_retailerQueryAll_candidate_check : + ( ?(Key<(T.RouteId, T.InventoryId)>, + (M.RouteDoc, M.InventoryDoc)) ) { retailerQueryCost += 1; /** - Consider the constraints of the retailer-route-item combination: */ if (isFeasibleReservation(retailer, item, route, queryProduce, queryDate)) { + label profile_retailerQueryAll_candidate_check_true : + ( ?(Key<(T.RouteId, T.InventoryId)>, + (M.RouteDoc, M.InventoryDoc)) ) + ?( keyOfIdPair(route_id, item_id), (route, item) ) - } else { null } + } else { + label profile_retailerQueryAll_candidate_check_false : + ( ?(Key<(T.RouteId, T.InventoryId)>, + (M.RouteDoc, M.InventoryDoc)) ) + + null + } }, idPairIsEq ); diff --git a/stdlib/trie.as b/stdlib/trie.as index ae12a267388..1d121e55b80 100644 --- a/stdlib/trie.as +++ b/stdlib/trie.as @@ -922,8 +922,7 @@ type Trie3D = Trie >; label profile_trie_toArray_arrayAppend : [W] Array_tabulate ( x.len() + y.len(), - func (i:Nat) : W { - label profile_trie_toArray_arrayAppend_projelm : W + func (i:Nat) : W = label profile_trie_toArray_arrayAppend_projelm : W { if (i >= x.len()) { y[i - x.len()] } else { x[i] } } From 693eac5e36e848dc66897b0a001bdb8aba3a29c4 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Fri, 17 May 2019 11:22:40 -0700 Subject: [PATCH 0038/1176] [WIP] Use ATD --- src/lsp2.atd | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/src/lsp2.atd b/src/lsp2.atd index 19faae1b9c0..fe8dc1b88bb 100644 --- a/src/lsp2.atd +++ b/src/lsp2.atd @@ -17,14 +17,16 @@ type message = type incoming_message = { inherit message ; ?id : int nullable - ; method : incoming_message_method + ; params : incoming_message_params } + -type incoming_message_method = - [ Initialize (*of initialize_params*) (* <-- uncomment to trigger decoding issue *) - | Initialized - ] +(* All tags must also provide params, even if they are an `empty_record` *) +type incoming_message_params = + [ Initialize of initialize_params + | Initialized of initialized_params + ] (* Outgoing messages *) @@ -37,7 +39,7 @@ type outgoing_message_method = ] -(* "initialize" request message *) +(* "initialize" request *) type initialize_params = { ?processId : int nullable @@ -64,6 +66,21 @@ type trace = ] +(* "initialized" notification *) + +type initialized_params = empty_record + + +(* Helpers *) + +(* Empty records aren't valid in OCaml but some notifications send them in the + params field. Work around that by defining a record with a field that is + never expected to be provided. *) +type empty_record = + { ?omitted : int nullable + } + + (* type ('a, 'b) response_message = { inherit message From 734cb8fdc73ebf32862f4c130d0dd2eb227c1b57 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Fri, 17 May 2019 11:38:36 -0700 Subject: [PATCH 0039/1176] [WIP] Use ATD --- src/languageServer.ml | 56 +++++++++++++------------------------------ 1 file changed, 17 insertions(+), 39 deletions(-) diff --git a/src/languageServer.ml b/src/languageServer.ml index ee838b71890..f1a59e8ee3f 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -31,48 +31,26 @@ let start () = let raw = Buffer.contents buffer in log_to_file raw; - let json = Yojson.Basic.from_string raw in + let json = Lsp2_j.incoming_message_of_string raw in - let json2 = Lsp2_j.incoming_message_of_string raw in - let jsonrpc = json2.Lsp2_t.incoming_message_jsonrpc in - (* let method_ = Lsp2_j.string_of_incoming_message_method json2.Lsp2_t.incoming_message_method in *) - (* log_to_file ("jsonrpc: " ^ jsonrpc ^ ", method: " ^ method_); *) - log_to_file ("jsonrpc: " ^ jsonrpc); - - let received = LSP.parse json in - - let string_of_int_option = - function - | None -> "None" - | Some i -> string_of_int i in - - log_to_file (string_of_int_option received.LSP.id ^ ", " ^ received.LSP.method_); - - if received.LSP.method_ = "initialize" - then begin + match json.Lsp2_t.incoming_message_params with + | `Initialize params -> log_to_file "Handle initialize"; - let capabilities = `Assoc - [ ("textDocumentSync", `Null) - ] in - let result = `Assoc - [ ("capabilities", capabilities) - ] in - let response = LSP.response received.LSP.id result `Null in - respond (Yojson.Basic.pretty_to_string response); - end - - else if received.LSP.method_ = "initialized" - then begin + (* let capabilities = `Assoc + * [ ("textDocumentSync", `Null) + * ] in + * let result = `Assoc + * [ ("capabilities", capabilities) + * ] in + * let response = LSP.response received.LSP.id result `Null in + * respond (Yojson.Basic.pretty_to_string response); *) + | `Initialized _ -> log_to_file "Handle initialized"; - let notification = LSP.notification "window/showMessage" - [ ("type", `Int 3) - ; ("message", `String "Language server initialized") - ] in - respond (Yojson.Basic.pretty_to_string notification); - end - - else - loop (); + (* let notification = LSP.notification "window/showMessage" + * [ ("type", `Int 3) + * ; ("message", `String "Language server initialized") + * ] in + * respond (Yojson.Basic.pretty_to_string notification); *) loop () in loop () From 3142deaa88f6804c06f4b6948eebd41010a14ea6 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Fri, 17 May 2019 12:28:44 -0700 Subject: [PATCH 0040/1176] [WIP] Use ATD --- src/languageServer.ml | 2 + src/lsp2.atd | 96 +++++++++++++++++++++++++------------------ src/lsp2.ml | 8 ++++ src/lsp2.mli | 4 ++ 4 files changed, 69 insertions(+), 41 deletions(-) create mode 100644 src/lsp2.mli diff --git a/src/languageServer.ml b/src/languageServer.ml index f1a59e8ee3f..0d060092f13 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -44,6 +44,8 @@ let start () = * ] in * let response = LSP.response received.LSP.id result `Null in * respond (Yojson.Basic.pretty_to_string response); *) + (* let response = + * log_to_file (Lsp2_j.string_of_response_result response) *) | `Initialized _ -> log_to_file "Handle initialized"; (* let notification = LSP.notification "window/showMessage" diff --git a/src/lsp2.atd b/src/lsp2.atd index fe8dc1b88bb..7ccc68fdd35 100644 --- a/src/lsp2.atd +++ b/src/lsp2.atd @@ -9,10 +9,23 @@ type message = -(* Incoming messages *) +(* Notification message *) -(* Incoming messages may be either request or notification messages. The latter - omits the `id` field. *) +type notification_message = + { inherit message; + } + + + +(* + Incoming messages + + Incoming messages may be either request or notification messages. + + Notification messages are a subtype of response messages (notification + messages omit the `id` field) so both are represented by the + `incoming_message` type to allow them to be decoded in a single pass. +*) type incoming_message = { inherit message @@ -29,12 +42,30 @@ type incoming_message_params = ] -(* Outgoing messages *) +(* + Outgoing messages + + Outgoing messages may be either response or notification messages. +*) + +(* Response message *) + +type response_message = + { inherit message + ; id : int + ; ?result : response_result nullable + (*; ?error : response_error nullable*) + } + + +type response_result = + [ InitializeResult of initialize_result + ] + -(* Outgoing messages may be either response or notification messages. The latter - omits the `id` field. *) +(* Outgoing notifications *) -type outgoing_message_method = +type outgoing_notification_method = [ WindowShowMessage ] @@ -66,6 +97,22 @@ type trace = ] +(* "initialize" response *) + +type initialize_result = + { capabilities : server_capabilities + } + +(* FIXME: incomplete *) +type server_capabilities = + (*{ ?textDocumentSync : text_document_sync_options*) + { ?hoverProvider : bool nullable + } + +(* TODO: see LSP spec for InitializeError *) +(*type initialize_error = *) + + (* "initialized" notification *) type initialized_params = empty_record @@ -74,41 +121,8 @@ type initialized_params = empty_record (* Helpers *) (* Empty records aren't valid in OCaml but some notifications send them in the - params field. Work around that by defining a record with a field that is + `params` field. Work around that by defining a record with a field that is never expected to be provided. *) type empty_record = { ?omitted : int nullable } - - -(* -type ('a, 'b) response_message = - { inherit message - ; id : int - ; ?result : 'a nullable - ; ?error : 'b - } - -type 'a response_error = - { code : error_code - ; message : string - ; ?data : 'a - } - -type error_code = - (* Defined by JSON RPC *) - [ ParseError - | InvalidRequest - | MethodNotFound - | InvalidParams - | InternalError - | ServerErrorStart - | ServerErrorEnd - | ServerNotInitialized - | UnknownErrorCode - - (* Defined by the protocol *) - | RequestCancelled - | ContentModified - ] -*) \ No newline at end of file diff --git a/src/lsp2.ml b/src/lsp2.ml index 7f11e9da42b..178d0d66cda 100644 --- a/src/lsp2.ml +++ b/src/lsp2.ml @@ -5,3 +5,11 @@ module Message_adapter = Atdgen_runtime.Json_adapter.Type_and_value_fields.Make( let known_tags = None end ) + +let response_result id result = Lsp2_t. + { response_message_jsonrpc = "2.0" + ; response_message_id = id + ; response_message_result = Some result + } + +(* let response_error id error = *) diff --git a/src/lsp2.mli b/src/lsp2.mli new file mode 100644 index 00000000000..8cd8916a281 --- /dev/null +++ b/src/lsp2.mli @@ -0,0 +1,4 @@ +module Message_adapter : Atdgen_runtime.Json_adapter.S + +val response_result : int -> Lsp2_t.response_result -> Lsp2_t.response_message +(* val response_error : int -> Lsp2_t.response_error -> Lsp2_t.response_message *) From 434b96f1e68cb93c873e171a313efe9f7de89fa2 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Fri, 17 May 2019 12:52:12 -0700 Subject: [PATCH 0041/1176] Respond to "initialize" request via ATD --- src/languageServer.ml | 29 ++++++++++++++--------------- src/lsp2.atd | 5 +++-- src/lsp2.ml | 10 +++++++++- src/lsp2.mli | 3 ++- 4 files changed, 28 insertions(+), 19 deletions(-) diff --git a/src/languageServer.ml b/src/languageServer.ml index 0d060092f13..fba0107a2c1 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -31,28 +31,27 @@ let start () = let raw = Buffer.contents buffer in log_to_file raw; - let json = Lsp2_j.incoming_message_of_string raw in + let message = Lsp2_j.incoming_message_of_string raw in + let message_id = message.Lsp2_t.incoming_message_id in - match json.Lsp2_t.incoming_message_params with - | `Initialize params -> + match (message_id, message.Lsp2_t.incoming_message_params) with + | (Some id, `Initialize params) -> log_to_file "Handle initialize"; - (* let capabilities = `Assoc - * [ ("textDocumentSync", `Null) - * ] in - * let result = `Assoc - * [ ("capabilities", capabilities) - * ] in - * let response = LSP.response received.LSP.id result `Null in - * respond (Yojson.Basic.pretty_to_string response); *) - (* let response = - * log_to_file (Lsp2_j.string_of_response_result response) *) - | `Initialized _ -> + let result = `Initialize (Lsp2_t. + { capabilities = + { hoverProvider = Some false + } + }) in + let response = Lsp2.response_result id result in + respond (Lsp2_j.string_of_response_message response) + | (_, `Initialized _) -> log_to_file "Handle initialized"; (* let notification = LSP.notification "window/showMessage" * [ ("type", `Int 3) * ; ("message", `String "Language server initialized") * ] in * respond (Yojson.Basic.pretty_to_string notification); *) + | _ -> + loop () - loop () in loop () diff --git a/src/lsp2.atd b/src/lsp2.atd index 7ccc68fdd35..35b27e85b21 100644 --- a/src/lsp2.atd +++ b/src/lsp2.atd @@ -32,7 +32,7 @@ type incoming_message = ; ?id : int nullable ; params : incoming_message_params } - + (* All tags must also provide params, even if they are an `empty_record` *) @@ -56,10 +56,11 @@ type response_message = ; ?result : response_result nullable (*; ?error : response_error nullable*) } + type response_result = - [ InitializeResult of initialize_result + [ Initialize of initialize_result ] diff --git a/src/lsp2.ml b/src/lsp2.ml index 178d0d66cda..5dd372d4872 100644 --- a/src/lsp2.ml +++ b/src/lsp2.ml @@ -1,4 +1,4 @@ -module Message_adapter = Atdgen_runtime.Json_adapter.Type_and_value_fields.Make( +module Incoming_message_adapter = Atdgen_runtime.Json_adapter.Type_and_value_fields.Make( struct let type_field_name = "method" let value_field_name = "params" @@ -6,6 +6,14 @@ module Message_adapter = Atdgen_runtime.Json_adapter.Type_and_value_fields.Make( end ) +module Response_result_adapter = Atdgen_runtime.Json_adapter.Type_and_value_fields.Make( + struct + let type_field_name = "response_for" (* Ideally we would omit this *) + let value_field_name = "result" + let known_tags = None + end +) + let response_result id result = Lsp2_t. { response_message_jsonrpc = "2.0" ; response_message_id = id diff --git a/src/lsp2.mli b/src/lsp2.mli index 8cd8916a281..7484350c4f1 100644 --- a/src/lsp2.mli +++ b/src/lsp2.mli @@ -1,4 +1,5 @@ -module Message_adapter : Atdgen_runtime.Json_adapter.S +module Incoming_message_adapter : Atdgen_runtime.Json_adapter.S +module Response_result_adapter : Atdgen_runtime.Json_adapter.S val response_result : int -> Lsp2_t.response_result -> Lsp2_t.response_message (* val response_error : int -> Lsp2_t.response_error -> Lsp2_t.response_message *) From ed8da1fcbe52a1369cfaa3873f0b6159f9f28ef4 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Fri, 17 May 2019 14:56:54 -0700 Subject: [PATCH 0042/1176] Send show message notification with ATD --- src/languageServer.ml | 20 ++++++++++++-------- src/lsp2.atd | 20 +++++++++++++++----- src/lsp2.ml | 13 ++++++++++--- src/lsp2.mli | 6 ++++-- src/main.ml | 2 +- 5 files changed, 42 insertions(+), 19 deletions(-) diff --git a/src/languageServer.ml b/src/languageServer.ml index fba0107a2c1..2b6fdb42776 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -34,7 +34,7 @@ let start () = let message = Lsp2_j.incoming_message_of_string raw in let message_id = message.Lsp2_t.incoming_message_id in - match (message_id, message.Lsp2_t.incoming_message_params) with + (match (message_id, message.Lsp2_t.incoming_message_params) with | (Some id, `Initialize params) -> log_to_file "Handle initialize"; let result = `Initialize (Lsp2_t. @@ -43,15 +43,19 @@ let start () = } }) in let response = Lsp2.response_result id result in - respond (Lsp2_j.string_of_response_message response) + respond (Lsp2_j.string_of_response_message response); | (_, `Initialized _) -> log_to_file "Handle initialized"; - (* let notification = LSP.notification "window/showMessage" - * [ ("type", `Int 3) - * ; ("message", `String "Language server initialized") - * ] in - * respond (Yojson.Basic.pretty_to_string notification); *) + let params = `ShowMessage (Lsp2_t. + { type_ = 3 + ; message = "Language server initialized" + }) in + let notification = Lsp2.notification params in + respond (Lsp2_j.string_of_notification_message notification); | _ -> - loop () + (* TODO: log useful info here *) + log_to_file "Unhandled message"; + ); + loop () in loop () diff --git a/src/lsp2.atd b/src/lsp2.atd index 35b27e85b21..df1fb6f7a61 100644 --- a/src/lsp2.atd +++ b/src/lsp2.atd @@ -12,8 +12,10 @@ type message = (* Notification message *) type notification_message = - { inherit message; + { inherit message + ; params : notification_message_params } + @@ -32,7 +34,7 @@ type incoming_message = ; ?id : int nullable ; params : incoming_message_params } - + (* All tags must also provide params, even if they are an `empty_record` *) @@ -56,7 +58,7 @@ type response_message = ; ?result : response_result nullable (*; ?error : response_error nullable*) } - + type response_result = @@ -66,8 +68,8 @@ type response_result = (* Outgoing notifications *) -type outgoing_notification_method = - [ WindowShowMessage +type notification_message_params = + [ ShowMessage of show_message_params ] @@ -119,6 +121,14 @@ type server_capabilities = type initialized_params = empty_record +(* "window/showMessage" notification *) + +type show_message_params = + { type_ : int + ; message : string + } + + (* Helpers *) (* Empty records aren't valid in OCaml but some notifications send them in the diff --git a/src/lsp2.ml b/src/lsp2.ml index 5dd372d4872..a3731a201fc 100644 --- a/src/lsp2.ml +++ b/src/lsp2.ml @@ -1,4 +1,4 @@ -module Incoming_message_adapter = Atdgen_runtime.Json_adapter.Type_and_value_fields.Make( +module Message_adapter = Atdgen_runtime.Json_adapter.Type_and_value_fields.Make( struct let type_field_name = "method" let value_field_name = "params" @@ -6,7 +6,7 @@ module Incoming_message_adapter = Atdgen_runtime.Json_adapter.Type_and_value_fie end ) -module Response_result_adapter = Atdgen_runtime.Json_adapter.Type_and_value_fields.Make( +module Response_message_adapter = Atdgen_runtime.Json_adapter.Type_and_value_fields.Make( struct let type_field_name = "response_for" (* Ideally we would omit this *) let value_field_name = "result" @@ -14,8 +14,15 @@ module Response_result_adapter = Atdgen_runtime.Json_adapter.Type_and_value_fiel end ) +let jsonrpc_version = "2.0" + +let notification params = Lsp2_t. + { notification_message_jsonrpc = jsonrpc_version + ; notification_message_params = params + } + let response_result id result = Lsp2_t. - { response_message_jsonrpc = "2.0" + { response_message_jsonrpc = jsonrpc_version ; response_message_id = id ; response_message_result = Some result } diff --git a/src/lsp2.mli b/src/lsp2.mli index 7484350c4f1..57a57ae06b5 100644 --- a/src/lsp2.mli +++ b/src/lsp2.mli @@ -1,5 +1,7 @@ -module Incoming_message_adapter : Atdgen_runtime.Json_adapter.S -module Response_result_adapter : Atdgen_runtime.Json_adapter.S +module Message_adapter : Atdgen_runtime.Json_adapter.S +module Response_message_adapter : Atdgen_runtime.Json_adapter.S + +val notification : Lsp2_t.notification_message_params -> Lsp2_t.notification_message val response_result : int -> Lsp2_t.response_result -> Lsp2_t.response_message (* val response_error : int -> Lsp2_t.response_error -> Lsp2_t.response_message *) diff --git a/src/main.ml b/src/main.ml index 81b8399ea5e..513aa5fd473 100644 --- a/src/main.ml +++ b/src/main.ml @@ -52,7 +52,7 @@ let argspec = Arg.align "-dl", Arg.Set Flags.dump_lowering, " dump intermediate representation "; "--disable-prelude", Arg.Clear Flags.prelude, " disable prelude"; - "-ide", Arg.Unit (fun () -> LanguageServer.start (); ()), " start the language server" + "-ide", Arg.Unit (fun () -> ignore (LanguageServer.start ()); ()), " start the language server" ] From 75aa8a458b456646808e5720ede0537335d10ca6 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Fri, 17 May 2019 14:58:15 -0700 Subject: [PATCH 0043/1176] Rename respond to send --- src/languageServer.ml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/languageServer.ml b/src/languageServer.ml index 2b6fdb42776..3a5f0f2ed71 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -3,7 +3,7 @@ let log_to_file txt = Printf.fprintf oc "%s\n" txt; flush oc -let respond out = +let send out = let cl = "Content-Length: " ^ string_of_int (String.length out) ^ "\r\n\r\n" in print_string cl; print_string out; @@ -43,7 +43,7 @@ let start () = } }) in let response = Lsp2.response_result id result in - respond (Lsp2_j.string_of_response_message response); + send (Lsp2_j.string_of_response_message response); | (_, `Initialized _) -> log_to_file "Handle initialized"; let params = `ShowMessage (Lsp2_t. @@ -51,7 +51,7 @@ let start () = ; message = "Language server initialized" }) in let notification = Lsp2.notification params in - respond (Lsp2_j.string_of_notification_message notification); + send (Lsp2_j.string_of_notification_message notification); | _ -> (* TODO: log useful info here *) log_to_file "Unhandled message"; From cd5ada63982b5385c2dc75a68dee2cc480fce0c4 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Fri, 17 May 2019 14:59:17 -0700 Subject: [PATCH 0044/1176] Remove old LSP module --- src/LSP.ml | 40 ---------------------------------------- src/LSP.mli | 11 ----------- 2 files changed, 51 deletions(-) delete mode 100644 src/LSP.ml delete mode 100644 src/LSP.mli diff --git a/src/LSP.ml b/src/LSP.ml deleted file mode 100644 index 71200070455..00000000000 --- a/src/LSP.ml +++ /dev/null @@ -1,40 +0,0 @@ -open Yojson.Basic.Util - -let jsonrpc_version = "2.0" -let jsonrpc_field = ("jsonrpc", `String jsonrpc_version) - -let from_int_option = - function - | None -> `Null - | Some i -> `Int i - -type received_message = - { id : int option - ; method_ : string - ; params : Yojson.Basic.t - } - -(* Parse and LSP request message or notification *) -let parse json = - (* if json |> member "jsonrpc" |> to_string = jsonrpc_version - * then Some *) - { id = json |> member "id" |> to_int_option (* notifications omit id *) - ; method_ = json |> member "method" |> to_string - ; params = json |> member "params" - } - (* else None *) - -(* Construct an LSP response message *) -let response id result error = `Assoc - [ jsonrpc_field - ; ("id", from_int_option id) - ; ("result", result) - ; ("error", error) - ] - -(* Construct an LSP notification message *) -let notification method_ params = `Assoc - [ jsonrpc_field - ; ("method", `String method_) - ; ("params", `Assoc params) - ] diff --git a/src/LSP.mli b/src/LSP.mli deleted file mode 100644 index 3c948bffbe2..00000000000 --- a/src/LSP.mli +++ /dev/null @@ -1,11 +0,0 @@ -type received_message = - { id : int option - ; method_ : string - ; params : Yojson.Basic.t - } - -val parse : Yojson.Basic.t -> received_message (* option *) - -val response : int option -> Yojson.Basic.t -> Yojson.Basic.t -> Yojson.Basic.t - -val notification : string -> (string * Yojson.Basic.t) list -> Yojson.Basic.t From adf59081d471bcceb7288d3b32597ed6d4403810 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Fri, 17 May 2019 15:02:04 -0700 Subject: [PATCH 0045/1176] Rename ATD lsp module --- src/languageServer.ml | 18 +++++++++--------- src/{lsp2.atd => lsp.atd} | 6 +++--- src/{lsp2.ml => lsp.ml} | 4 ++-- src/lsp.mli | 7 +++++++ src/lsp2.mli | 7 ------- 5 files changed, 21 insertions(+), 21 deletions(-) rename src/{lsp2.atd => lsp.atd} (95%) rename src/{lsp2.ml => lsp.ml} (90%) create mode 100644 src/lsp.mli delete mode 100644 src/lsp2.mli diff --git a/src/languageServer.ml b/src/languageServer.ml index 3a5f0f2ed71..7289db2697c 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -31,27 +31,27 @@ let start () = let raw = Buffer.contents buffer in log_to_file raw; - let message = Lsp2_j.incoming_message_of_string raw in - let message_id = message.Lsp2_t.incoming_message_id in + let message = Lsp_j.incoming_message_of_string raw in + let message_id = message.Lsp_t.incoming_message_id in - (match (message_id, message.Lsp2_t.incoming_message_params) with + (match (message_id, message.Lsp_t.incoming_message_params) with | (Some id, `Initialize params) -> log_to_file "Handle initialize"; - let result = `Initialize (Lsp2_t. + let result = `Initialize (Lsp_t. { capabilities = { hoverProvider = Some false } }) in - let response = Lsp2.response_result id result in - send (Lsp2_j.string_of_response_message response); + let response = Lsp.response_result id result in + send (Lsp_j.string_of_response_message response); | (_, `Initialized _) -> log_to_file "Handle initialized"; - let params = `ShowMessage (Lsp2_t. + let params = `ShowMessage (Lsp_t. { type_ = 3 ; message = "Language server initialized" }) in - let notification = Lsp2.notification params in - send (Lsp2_j.string_of_notification_message notification); + let notification = Lsp.notification params in + send (Lsp_j.string_of_notification_message notification); | _ -> (* TODO: log useful info here *) log_to_file "Unhandled message"; diff --git a/src/lsp2.atd b/src/lsp.atd similarity index 95% rename from src/lsp2.atd rename to src/lsp.atd index df1fb6f7a61..c2a81e7d29d 100644 --- a/src/lsp2.atd +++ b/src/lsp.atd @@ -15,7 +15,7 @@ type notification_message = { inherit message ; params : notification_message_params } - + @@ -34,7 +34,7 @@ type incoming_message = ; ?id : int nullable ; params : incoming_message_params } - + (* All tags must also provide params, even if they are an `empty_record` *) @@ -58,7 +58,7 @@ type response_message = ; ?result : response_result nullable (*; ?error : response_error nullable*) } - + type response_result = diff --git a/src/lsp2.ml b/src/lsp.ml similarity index 90% rename from src/lsp2.ml rename to src/lsp.ml index a3731a201fc..956fbb4db3b 100644 --- a/src/lsp2.ml +++ b/src/lsp.ml @@ -16,12 +16,12 @@ module Response_message_adapter = Atdgen_runtime.Json_adapter.Type_and_value_fie let jsonrpc_version = "2.0" -let notification params = Lsp2_t. +let notification params = Lsp_t. { notification_message_jsonrpc = jsonrpc_version ; notification_message_params = params } -let response_result id result = Lsp2_t. +let response_result id result = Lsp_t. { response_message_jsonrpc = jsonrpc_version ; response_message_id = id ; response_message_result = Some result diff --git a/src/lsp.mli b/src/lsp.mli new file mode 100644 index 00000000000..433a273175a --- /dev/null +++ b/src/lsp.mli @@ -0,0 +1,7 @@ +module Message_adapter : Atdgen_runtime.Json_adapter.S +module Response_message_adapter : Atdgen_runtime.Json_adapter.S + +val notification : Lsp_t.notification_message_params -> Lsp_t.notification_message + +val response_result : int -> Lsp_t.response_result -> Lsp_t.response_message +(* val response_error : int -> Lsp_t.response_error -> Lsp_t.response_message *) diff --git a/src/lsp2.mli b/src/lsp2.mli deleted file mode 100644 index 57a57ae06b5..00000000000 --- a/src/lsp2.mli +++ /dev/null @@ -1,7 +0,0 @@ -module Message_adapter : Atdgen_runtime.Json_adapter.S -module Response_message_adapter : Atdgen_runtime.Json_adapter.S - -val notification : Lsp2_t.notification_message_params -> Lsp2_t.notification_message - -val response_result : int -> Lsp2_t.response_result -> Lsp2_t.response_message -(* val response_error : int -> Lsp2_t.response_error -> Lsp2_t.response_message *) From 47cee6f30b6bb49cced6d028a9759444f790a45c Mon Sep 17 00:00:00 2001 From: Paul Young Date: Fri, 17 May 2019 15:10:06 -0700 Subject: [PATCH 0046/1176] Be explicit about notification IDs --- src/languageServer.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/languageServer.ml b/src/languageServer.ml index 7289db2697c..932dff53f73 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -44,7 +44,7 @@ let start () = }) in let response = Lsp.response_result id result in send (Lsp_j.string_of_response_message response); - | (_, `Initialized _) -> + | (None, `Initialized _) -> log_to_file "Handle initialized"; let params = `ShowMessage (Lsp_t. { type_ = 3 From 906ece70c453024fbb0b4c645fdbf04b4f8fa1b8 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Fri, 17 May 2019 15:11:24 -0700 Subject: [PATCH 0047/1176] Log raw JSON for unhandled messages --- src/languageServer.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/languageServer.ml b/src/languageServer.ml index 932dff53f73..aa0188e06fe 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -53,8 +53,8 @@ let start () = let notification = Lsp.notification params in send (Lsp_j.string_of_notification_message notification); | _ -> - (* TODO: log useful info here *) - log_to_file "Unhandled message"; + log_to_file "Unhandled message:"; + log_to_file raw; ); loop () From 71d2e0c30295e4006b8269d77f57263b8268c667 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Fri, 17 May 2019 15:13:06 -0700 Subject: [PATCH 0048/1176] Organize message handlers --- src/languageServer.ml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/languageServer.ml b/src/languageServer.ml index aa0188e06fe..a3317b39b55 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -35,6 +35,9 @@ let start () = let message_id = message.Lsp_t.incoming_message_id in (match (message_id, message.Lsp_t.incoming_message_params) with + + (* Request messages *) + | (Some id, `Initialize params) -> log_to_file "Handle initialize"; let result = `Initialize (Lsp_t. @@ -44,6 +47,10 @@ let start () = }) in let response = Lsp.response_result id result in send (Lsp_j.string_of_response_message response); + + + (* Notification messages *) + | (None, `Initialized _) -> log_to_file "Handle initialized"; let params = `ShowMessage (Lsp_t. @@ -52,6 +59,9 @@ let start () = }) in let notification = Lsp.notification params in send (Lsp_j.string_of_notification_message notification); + + + (* Unhandled messages *) | _ -> log_to_file "Unhandled message:"; log_to_file raw; From 0f1647f3c1440acfac13e8a7d29569842c0b5fd8 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Fri, 17 May 2019 15:13:38 -0700 Subject: [PATCH 0049/1176] Remove redundant logging --- src/languageServer.ml | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/languageServer.ml b/src/languageServer.ml index a3317b39b55..dad0e3bb2b6 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -39,7 +39,6 @@ let start () = (* Request messages *) | (Some id, `Initialize params) -> - log_to_file "Handle initialize"; let result = `Initialize (Lsp_t. { capabilities = { hoverProvider = Some false @@ -52,7 +51,6 @@ let start () = (* Notification messages *) | (None, `Initialized _) -> - log_to_file "Handle initialized"; let params = `ShowMessage (Lsp_t. { type_ = 3 ; message = "Language server initialized" From 8b2c7a2aac277a6f5b992ef04fa16346a5e4cd14 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Fri, 17 May 2019 16:10:15 -0700 Subject: [PATCH 0050/1176] Rename ambiguous response functions --- src/languageServer.ml | 2 +- src/lsp.ml | 4 ++-- src/lsp.mli | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/languageServer.ml b/src/languageServer.ml index dad0e3bb2b6..c4e8029a514 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -44,7 +44,7 @@ let start () = { hoverProvider = Some false } }) in - let response = Lsp.response_result id result in + let response = Lsp.response_result_message id result in send (Lsp_j.string_of_response_message response); diff --git a/src/lsp.ml b/src/lsp.ml index 956fbb4db3b..45341a15597 100644 --- a/src/lsp.ml +++ b/src/lsp.ml @@ -21,10 +21,10 @@ let notification params = Lsp_t. ; notification_message_params = params } -let response_result id result = Lsp_t. +let response_result_message id result = Lsp_t. { response_message_jsonrpc = jsonrpc_version ; response_message_id = id ; response_message_result = Some result } -(* let response_error id error = *) +(* let response_error_message id error = *) diff --git a/src/lsp.mli b/src/lsp.mli index 433a273175a..7b382c55d3c 100644 --- a/src/lsp.mli +++ b/src/lsp.mli @@ -3,5 +3,5 @@ module Response_message_adapter : Atdgen_runtime.Json_adapter.S val notification : Lsp_t.notification_message_params -> Lsp_t.notification_message -val response_result : int -> Lsp_t.response_result -> Lsp_t.response_message -(* val response_error : int -> Lsp_t.response_error -> Lsp_t.response_message *) +val response_result_message : int -> Lsp_t.response_result -> Lsp_t.response_message +(* val response_error_message : int -> Lsp_t.response_error -> Lsp_t.response_message *) From 6568cc2fd42347b217a8e7104f1fe0b30146b84d Mon Sep 17 00:00:00 2001 From: Paul Young Date: Fri, 17 May 2019 16:11:34 -0700 Subject: [PATCH 0051/1176] Fix spacing --- src/languageServer.ml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/languageServer.ml b/src/languageServer.ml index c4e8029a514..b0a883cd616 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -60,6 +60,7 @@ let start () = (* Unhandled messages *) + | _ -> log_to_file "Unhandled message:"; log_to_file raw; From 6446cdb30cabea0cdc132d890bb2303035191e0b Mon Sep 17 00:00:00 2001 From: Paul Young Date: Fri, 17 May 2019 16:24:33 -0700 Subject: [PATCH 0052/1176] Sanity check that trace variant works as expected --- src/languageServer.ml | 8 ++++++++ src/lsp.atd | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/languageServer.ml b/src/languageServer.ml index b0a883cd616..43fe827cdf1 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -39,6 +39,14 @@ let start () = (* Request messages *) | (Some id, `Initialize params) -> + (match params.Lsp_t.trace with + | Some trace -> (match trace with + | `Off -> log_to_file "trace: Off" + | `Messages -> log_to_file "trace: Messages" + | `Verbose -> log_to_file "trace: Verbose" + ); + | None -> log_to_file "trace: null" + ); let result = `Initialize (Lsp_t. { capabilities = { hoverProvider = Some false diff --git a/src/lsp.atd b/src/lsp.atd index c2a81e7d29d..d8411feaeaa 100644 --- a/src/lsp.atd +++ b/src/lsp.atd @@ -81,7 +81,7 @@ type initialize_params = (*; rootUri : document_uri nullable*) (*; ?initializationOptions : any*) (*; capabilities : client_capabilities*) - (*; ?trace : trace nullable*) + ; ?trace : trace nullable (*; ?workspaceFolders : (workspace_folder list) nullable*) } From 267d3c26bff4e3fb1fc8603263d933752cd18ba0 Mon Sep 17 00:00:00 2001 From: Christoph Hegemann Date: Tue, 21 May 2019 16:27:25 +0200 Subject: [PATCH 0053/1176] add labels to log messages --- src/languageServer.ml | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/src/languageServer.ml b/src/languageServer.ml index 43fe827cdf1..5c275e7f075 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -1,6 +1,6 @@ let oc = open_out_gen [Open_append; Open_creat] 0o666 "ls.log" -let log_to_file txt = - Printf.fprintf oc "%s\n" txt; +let log_to_file lbl txt = + Printf.fprintf oc "[%s] %s\n" lbl txt; flush oc let send out = @@ -8,15 +8,13 @@ let send out = print_string cl; print_string out; flush stdout; - log_to_file "Response:"; - log_to_file cl; - log_to_file out + log_to_file "response_length" cl; + log_to_file "response" out let start () = let rec loop () = let clength = read_line () in - log_to_file "Request:"; - log_to_file clength; + log_to_file "content-length" clength; let cl = "Content-Length: " in let cll = String.length cl in let num = @@ -28,8 +26,8 @@ let start () = (String.length(clength) - cll - 1)))) + 2 in let buffer = Buffer.create num in Buffer.add_channel buffer stdin num; - let raw = Buffer.contents buffer in - log_to_file raw; + let raw = String.trim (Buffer.contents buffer) in + log_to_file "raw" raw; let message = Lsp_j.incoming_message_of_string raw in let message_id = message.Lsp_t.incoming_message_id in @@ -41,21 +39,31 @@ let start () = | (Some id, `Initialize params) -> (match params.Lsp_t.trace with | Some trace -> (match trace with - | `Off -> log_to_file "trace: Off" - | `Messages -> log_to_file "trace: Messages" - | `Verbose -> log_to_file "trace: Verbose" + | `Off -> log_to_file "trace" "Off" + | `Messages -> log_to_file "trace" "Messages" + | `Verbose -> log_to_file "trace" "Verbose" ); - | None -> log_to_file "trace: null" + | None -> log_to_file "trace" "null" ); let result = `Initialize (Lsp_t. { capabilities = - { hoverProvider = Some false + { textDocumentSync = 1 + ; hoverProvider = Some true } }) in let response = Lsp.response_result_message id result in + log_to_file "response" (Lsp_j.string_of_response_message response); send (Lsp_j.string_of_response_message response); - +(* +TODO(Christoph): Can't figure out how this works yet + | (Some id, `TextDocumentHover params) -> + let result = `TextDocumentHoverResponse (Lsp_t. { + contents = "Hovered over: " + }) in + let response = Lsp.response_result_message id result in + send (Lsp_j.string_of_response_message response); + *) (* Notification messages *) | (None, `Initialized _) -> @@ -66,12 +74,10 @@ let start () = let notification = Lsp.notification params in send (Lsp_j.string_of_notification_message notification); - (* Unhandled messages *) | _ -> - log_to_file "Unhandled message:"; - log_to_file raw; + log_to_file "unhandled message" raw; ); loop () From d7054c700805a69f7fbbc0acef353f4ef21c6937 Mon Sep 17 00:00:00 2001 From: Christoph Hegemann Date: Tue, 21 May 2019 16:27:45 +0200 Subject: [PATCH 0054/1176] adds type definitions for various text/* requests --- src/lsp.atd | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/src/lsp.atd b/src/lsp.atd index d8411feaeaa..9315681c682 100644 --- a/src/lsp.atd +++ b/src/lsp.atd @@ -41,9 +41,13 @@ type incoming_message = type incoming_message_params = [ Initialize of initialize_params | Initialized of initialized_params + | TextDocumentDidOpen of text_document_did_open_params + | TextDocumentDidClose of text_document_did_close_params + | TextDocumentDidChange of text_document_did_change_params + | TextDocumentDidSave of text_document_did_save_params + | TextDocumentHover of text_document_position_params ] - (* Outgoing messages @@ -63,8 +67,13 @@ type response_message = type response_result = [ Initialize of initialize_result + | TextDocumentHoverResponse of hover_result ] +type hover_result = + { contents : string + } + (* Outgoing notifications *) @@ -85,6 +94,53 @@ type initialize_params = (*; ?workspaceFolders : (workspace_folder list) nullable*) } +type text_document_did_open_params = + { textDocument : text_document_item + } + +type text_document_did_change_params = + { textDocument : versioned_text_document_identifier + } + +type text_document_did_close_params = + { textDocument : text_document_identifier + } + +type text_document_did_save_params = + { textDocument : text_document_identifier + } + +type text_document_position_params = + { textDocument : text_document_identifier + ; position : position + } + +(* See https://microsoft.github.io/language-server-protocol/specification#position + + We'll have to do some work to make sure we can split text + efficiently regardless of what line endings are being used +*) +type position = + { line : int + ; character : int + } + +type text_document_item = + { uri: string + ; text: string + ; languageId: string + ; version: int + } + +type text_document_identifier = + { uri: string + } + +type versioned_text_document_identifier = + { inherit text_document_identifier + ; ?version: int option + } + (* type client_capabilities = { ?workspace : workspace_client_capabilities @@ -108,8 +164,8 @@ type initialize_result = (* FIXME: incomplete *) type server_capabilities = - (*{ ?textDocumentSync : text_document_sync_options*) - { ?hoverProvider : bool nullable + { textDocumentSync : int + ; ?hoverProvider : bool nullable } (* TODO: see LSP spec for InitializeError *) From 79d5bdcc795328b00b211cf685390d0b2ffbe082 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Tue, 21 May 2019 13:56:27 -0700 Subject: [PATCH 0055/1176] Rename ShowMessage to WindowShowMessage --- src/languageServer.ml | 2 +- src/lsp.atd | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/languageServer.ml b/src/languageServer.ml index 5c275e7f075..c76a9d082a1 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -67,7 +67,7 @@ TODO(Christoph): Can't figure out how this works yet (* Notification messages *) | (None, `Initialized _) -> - let params = `ShowMessage (Lsp_t. + let params = `WindowShowMessage (Lsp_t. { type_ = 3 ; message = "Language server initialized" }) in diff --git a/src/lsp.atd b/src/lsp.atd index 9315681c682..2ca7dc0bb43 100644 --- a/src/lsp.atd +++ b/src/lsp.atd @@ -78,7 +78,7 @@ type hover_result = (* Outgoing notifications *) type notification_message_params = - [ ShowMessage of show_message_params + [ WindowShowMessage of window_show_message_params ] @@ -179,7 +179,7 @@ type initialized_params = empty_record (* "window/showMessage" notification *) -type show_message_params = +type window_show_message_params = { type_ : int ; message : string } From 63a40be0d4224efc7b1a18797688d9a1d9ca0b86 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Tue, 21 May 2019 17:27:59 -0700 Subject: [PATCH 0056/1176] [WIP] textDocument/hover result --- src/languageServer.ml | 18 ++++++++++-------- src/lsp.atd | 3 ++- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/languageServer.ml b/src/languageServer.ml index c76a9d082a1..eaf3f9bc743 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -55,15 +55,17 @@ let start () = log_to_file "response" (Lsp_j.string_of_response_message response); send (Lsp_j.string_of_response_message response); -(* -TODO(Christoph): Can't figure out how this works yet | (Some id, `TextDocumentHover params) -> - let result = `TextDocumentHoverResponse (Lsp_t. { - contents = "Hovered over: " - }) in - let response = Lsp.response_result_message id result in - send (Lsp_j.string_of_response_message response); - *) + let position = params.Lsp_t.text_document_position_params_position in + let textDocument = params.Lsp_t.text_document_position_params_textDocument in + let result = `TextDocumentHoverResponse (Lsp_t. { + hover_result_contents = "hovered over: " ^ textDocument.uri + ^ " " ^ string_of_int position.line + ^ ", " ^ string_of_int position.character + }) in + let response = Lsp.response_result_message id result in + send (Lsp_j.string_of_response_message response); + (* Notification messages *) | (None, `Initialized _) -> diff --git a/src/lsp.atd b/src/lsp.atd index 2ca7dc0bb43..198ee2ee2f3 100644 --- a/src/lsp.atd +++ b/src/lsp.atd @@ -73,6 +73,7 @@ type response_result = type hover_result = { contents : string } + (* Outgoing notifications *) @@ -113,7 +114,7 @@ type text_document_did_save_params = type text_document_position_params = { textDocument : text_document_identifier ; position : position - } + } (* See https://microsoft.github.io/language-server-protocol/specification#position From 99a305b668efa003cdcbb6a89319fa76c09304c5 Mon Sep 17 00:00:00 2001 From: Christoph Hegemann Date: Wed, 22 May 2019 17:09:54 +0200 Subject: [PATCH 0057/1176] runs compilation on a single file after it has been saved Doesn't actually send proper diagnostics to the editor yet --- default.nix | 1 + src/.merlin | 2 +- src/Makefile | 2 +- src/languageServer.ml | 38 ++++++++++++++++++++++++++++++++------ src/lsp.atd | 2 +- 5 files changed, 36 insertions(+), 9 deletions(-) diff --git a/default.nix b/default.nix index 8ae1c252e44..0cb4ccfcc44 100644 --- a/default.nix +++ b/default.nix @@ -50,6 +50,7 @@ let real-dvm = let commonBuildInputs = [ nixpkgs.ocaml nixpkgs.ocamlPackages.atdgen + nixpkgs.ocamlPackages.base nixpkgs.ocamlPackages.menhir nixpkgs.ocamlPackages.findlib nixpkgs.ocamlPackages.ocamlbuild diff --git a/src/.merlin b/src/.merlin index ec0c288f348..7a314f2e115 100644 --- a/src/.merlin +++ b/src/.merlin @@ -1,3 +1,3 @@ B _build -PKG wasm num vlq yojson +PKG wasm num vlq yojson base FLG -w +a-4-27-30-42-44-45 diff --git a/src/Makefile b/src/Makefile index bca0fe8415e..92f04528da0 100644 --- a/src/Makefile +++ b/src/Makefile @@ -5,7 +5,7 @@ JS_MAIN = js_main ASC = `pwd`/$(NAME) -OPAM_PACKAGES = wasm num vlq yojson bisect_ppx-ocamlbuild atdgen +OPAM_PACKAGES = wasm num vlq yojson bisect_ppx-ocamlbuild atdgen base JS_OPAM_PACKAGES = js_of_ocaml js_of_ocaml-ppx MENHIR = menhir diff --git a/src/languageServer.ml b/src/languageServer.ml index eaf3f9bc743..615ac2cf1bd 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -11,6 +11,15 @@ let send out = log_to_file "response_length" cl; log_to_file "response" out +let show_message msg = + let params = `WindowShowMessage (Lsp_t. + { type_ = 3 + ; message = msg + }) in + let notification = Lsp.notification params in + send (Lsp_j.string_of_notification_message notification) +;; + let start () = let rec loop () = let clength = read_line () in @@ -66,15 +75,32 @@ let start () = let response = Lsp.response_result_message id result in send (Lsp_j.string_of_response_message response); + | (_, `TextDocumentDidSave params) -> + let textDocumentIdent = params.Lsp_t.text_document_did_save_params_textDocument in + (match Base.String.chop_prefix ~prefix:"file://" textDocumentIdent.Lsp_t.uri with + | Some file_name -> begin + let result = Pipeline.compile_files + Pipeline.DfinityMode + false + [file_name] in + show_message ("Compiling file: " ^ file_name); + (match result with + | Ok _ -> show_message "Compilation successful" + | Error diag -> + show_message + ("Compilation failed with" ^ + String.concat + " " + (List.map Diag.string_of_message diag))) + end + | None -> + log_to_file + "error" + ("Failed to strip filename from: " ^ textDocumentIdent.Lsp_t.uri)); (* Notification messages *) | (None, `Initialized _) -> - let params = `WindowShowMessage (Lsp_t. - { type_ = 3 - ; message = "Language server initialized" - }) in - let notification = Lsp.notification params in - send (Lsp_j.string_of_notification_message notification); + show_message "Language server initialized" (* Unhandled messages *) diff --git a/src/lsp.atd b/src/lsp.atd index 198ee2ee2f3..aa4c71d811f 100644 --- a/src/lsp.atd +++ b/src/lsp.atd @@ -109,7 +109,7 @@ type text_document_did_close_params = type text_document_did_save_params = { textDocument : text_document_identifier - } + } type text_document_position_params = { textDocument : text_document_identifier From 7076464a3461608fcefbe3d72932df31272ad4a4 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Wed, 22 May 2019 13:45:49 -0700 Subject: [PATCH 0058/1176] Add space --- src/languageServer.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/languageServer.ml b/src/languageServer.ml index 615ac2cf1bd..617f54a786c 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -88,7 +88,7 @@ let start () = | Ok _ -> show_message "Compilation successful" | Error diag -> show_message - ("Compilation failed with" ^ + ("Compilation failed with " ^ String.concat " " (List.map Diag.string_of_message diag))) From 311ae3632f0f27cf5f5fbe68e6356900f3d85355 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Wed, 22 May 2019 13:47:35 -0700 Subject: [PATCH 0059/1176] Remove semicolons --- src/languageServer.ml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/languageServer.ml b/src/languageServer.ml index 617f54a786c..79ae663f2ba 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -18,7 +18,6 @@ let show_message msg = }) in let notification = Lsp.notification params in send (Lsp_j.string_of_notification_message notification) -;; let start () = let rec loop () = From 674b5931b10ab47226ea48c4a9cecfb778697877 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Wed, 22 May 2019 14:08:52 -0700 Subject: [PATCH 0060/1176] Fix nullable type --- src/lsp.atd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lsp.atd b/src/lsp.atd index aa4c71d811f..15ee99f0367 100644 --- a/src/lsp.atd +++ b/src/lsp.atd @@ -139,7 +139,7 @@ type text_document_identifier = type versioned_text_document_identifier = { inherit text_document_identifier - ; ?version: int option + ; ?version: int nullable } (* From b1bd0dca7bd1d9ef0c3c697bc6a2b5a78cdf10c6 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Wed, 22 May 2019 16:27:20 -0700 Subject: [PATCH 0061/1176] Add OCaml field prefixes to prevent name conflicts --- src/languageServer.ml | 23 ++++++++++++----------- src/lsp.atd | 14 ++++++++++++-- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/languageServer.ml b/src/languageServer.ml index 79ae663f2ba..f3d0394b918 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -13,8 +13,8 @@ let send out = let show_message msg = let params = `WindowShowMessage (Lsp_t. - { type_ = 3 - ; message = msg + { window_show_message_params_type_ = 3 + ; window_show_message_params_message = msg }) in let notification = Lsp.notification params in send (Lsp_j.string_of_notification_message notification) @@ -45,7 +45,7 @@ let start () = (* Request messages *) | (Some id, `Initialize params) -> - (match params.Lsp_t.trace with + (match params.Lsp_t.initialize_params_trace with | Some trace -> (match trace with | `Off -> log_to_file "trace" "Off" | `Messages -> log_to_file "trace" "Messages" @@ -54,9 +54,9 @@ let start () = | None -> log_to_file "trace" "null" ); let result = `Initialize (Lsp_t. - { capabilities = - { textDocumentSync = 1 - ; hoverProvider = Some true + { initialize_result_capabilities = + { server_capabilities_textDocumentSync = 1 + ; server_capabilities_hoverProvider = Some true } }) in let response = Lsp.response_result_message id result in @@ -67,16 +67,17 @@ let start () = let position = params.Lsp_t.text_document_position_params_position in let textDocument = params.Lsp_t.text_document_position_params_textDocument in let result = `TextDocumentHoverResponse (Lsp_t. { - hover_result_contents = "hovered over: " ^ textDocument.uri - ^ " " ^ string_of_int position.line - ^ ", " ^ string_of_int position.character + hover_result_contents = "hovered over: " ^ textDocument.text_document_identifier_uri + ^ " " ^ string_of_int position.position_line + ^ ", " ^ string_of_int position.position_character }) in let response = Lsp.response_result_message id result in send (Lsp_j.string_of_response_message response); | (_, `TextDocumentDidSave params) -> let textDocumentIdent = params.Lsp_t.text_document_did_save_params_textDocument in - (match Base.String.chop_prefix ~prefix:"file://" textDocumentIdent.Lsp_t.uri with + let uri = textDocumentIdent.Lsp_t.text_document_identifier_uri in + (match Base.String.chop_prefix ~prefix:"file://" uri with | Some file_name -> begin let result = Pipeline.compile_files Pipeline.DfinityMode @@ -95,7 +96,7 @@ let start () = | None -> log_to_file "error" - ("Failed to strip filename from: " ^ textDocumentIdent.Lsp_t.uri)); + ("Failed to strip filename from: " ^ uri)); (* Notification messages *) | (None, `Initialized _) -> diff --git a/src/lsp.atd b/src/lsp.atd index 15ee99f0367..9708f9dc061 100644 --- a/src/lsp.atd +++ b/src/lsp.atd @@ -94,27 +94,33 @@ type initialize_params = ; ?trace : trace nullable (*; ?workspaceFolders : (workspace_folder list) nullable*) } + type text_document_did_open_params = { textDocument : text_document_item } + type text_document_did_change_params = { textDocument : versioned_text_document_identifier } + type text_document_did_close_params = { textDocument : text_document_identifier } + type text_document_did_save_params = { textDocument : text_document_identifier - } + } + type text_document_position_params = { textDocument : text_document_identifier ; position : position - } + } + (* See https://microsoft.github.io/language-server-protocol/specification#position @@ -125,6 +131,7 @@ type position = { line : int ; character : int } + type text_document_item = { uri: string @@ -132,15 +139,18 @@ type text_document_item = ; languageId: string ; version: int } + type text_document_identifier = { uri: string } + type versioned_text_document_identifier = { inherit text_document_identifier ; ?version: int nullable } + (* type client_capabilities = From 45d08a903d434beaeadf21bcbaf2fdd05daa081e Mon Sep 17 00:00:00 2001 From: Paul Young Date: Wed, 22 May 2019 16:39:42 -0700 Subject: [PATCH 0062/1176] [WIP] publishDiagnostics --- src/languageServer.ml | 1 + src/lsp.atd | 47 +++++++++++++++++++++++++++++++++++++------ 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/languageServer.ml b/src/languageServer.ml index f3d0394b918..8b576a53901 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -87,6 +87,7 @@ let start () = (match result with | Ok _ -> show_message "Compilation successful" | Error diag -> + (* TODO: publish diagnostics, if capable *) show_message ("Compilation failed with " ^ String.concat diff --git a/src/lsp.atd b/src/lsp.atd index 9708f9dc061..1648d6fe78a 100644 --- a/src/lsp.atd +++ b/src/lsp.atd @@ -90,7 +90,7 @@ type initialize_params = ; ?rootPath : string nullable (*; rootUri : document_uri nullable*) (*; ?initializationOptions : any*) - (*; capabilities : client_capabilities*) + ; capabilities : client_capabilities ; ?trace : trace nullable (*; ?workspaceFolders : (workspace_folder list) nullable*) } @@ -152,13 +152,44 @@ type versioned_text_document_identifier = } -(* type client_capabilities = - { ?workspace : workspace_client_capabilities - ; ?textDocument : text_document_client_capabilities - ; ?experimental : any - } + (* { ?workspace : workspace_client_capabilities *) + { ?textDocument : text_document_client_capabilities nullable + (* ; ?experimental : any *) + } + + +type text_document_client_capabilities = + (* { ?synchronization : TODO *) + (* ; ?completion : TODO *) + (* ; ?hover : TODO *) + (* ; ?signatureHelp : TODO *) + (* ; ?references : TODO *) + (* ; ?documentHighlight : TODO *) + (* ; ?documentSymbol : TODO *) + (* ; ?formatting : TODO *) + (* ; ?rangeFormatting : TODO *) + (* ; ?onTypeFormatting : TODO *) + (* ; ?declaration : TODO *) + (* ; ?definition : TODO *) + (* ; ?typeDefinition : TODO *) + (* ; ?implementation : TODO *) + (* ; ?codeAction : TODO *) + (* ; ?codeLens : TODO *) + (* ; ?documentLink : TODO *) + (* ; ?colorProvider : TODO *) + (* ; ?rename : TODO *) + { ?publishDiagnostics : publish_diagnostics_field_type nullable + (* { ?publishDiagnostics : bool nullable *) + (* ; ?foldingRange : TODO *) + } + + +(* Defining this inline in `text_document_client_capabilities` resulted in + a syntax error in the generated `lsp_t.mli` file. *) +type publish_diagnostics_field_type = { ?relatedInformation : bool nullable } + type trace = [ Off @@ -172,12 +203,14 @@ type trace = type initialize_result = { capabilities : server_capabilities } + (* FIXME: incomplete *) type server_capabilities = { textDocumentSync : int ; ?hoverProvider : bool nullable } + (* TODO: see LSP spec for InitializeError *) (*type initialize_error = *) @@ -194,6 +227,7 @@ type window_show_message_params = { type_ : int ; message : string } + (* Helpers *) @@ -204,3 +238,4 @@ type window_show_message_params = type empty_record = { ?omitted : int nullable } + From c6e52b467eee1269306fae19b7fd50d030412dc3 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Wed, 22 May 2019 16:40:09 -0700 Subject: [PATCH 0063/1176] Fix spacing --- src/languageServer.ml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/languageServer.ml b/src/languageServer.ml index 8b576a53901..5b57c794cca 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -98,6 +98,7 @@ let start () = log_to_file "error" ("Failed to strip filename from: " ^ uri)); + (* Notification messages *) | (None, `Initialized _) -> From c2fdd4bf28951af8875e6e792dce26468744a8da Mon Sep 17 00:00:00 2001 From: Paul Young Date: Wed, 22 May 2019 16:48:56 -0700 Subject: [PATCH 0064/1176] Add type synonym for DocumentUri --- src/lsp.atd | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/lsp.atd b/src/lsp.atd index 1648d6fe78a..dd40278b3a6 100644 --- a/src/lsp.atd +++ b/src/lsp.atd @@ -83,6 +83,9 @@ type notification_message_params = ] +type document_uri = string + + (* "initialize" request *) type initialize_params = @@ -134,7 +137,7 @@ type position = type text_document_item = - { uri: string + { uri: document_uri ; text: string ; languageId: string ; version: int @@ -142,7 +145,7 @@ type text_document_item = type text_document_identifier = - { uri: string + { uri: document_uri } From c7699b7734614147e39299c3fdbac59dcf0cd945 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Wed, 22 May 2019 17:03:00 -0700 Subject: [PATCH 0065/1176] [WIP] publishDiagnostics --- src/lsp.atd | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/lsp.atd b/src/lsp.atd index dd40278b3a6..6ab28059da1 100644 --- a/src/lsp.atd +++ b/src/lsp.atd @@ -136,6 +136,18 @@ type position = } +type range = + { start : position + ; end_ : position + } + + +type location = + { uri : document_uri + ; range : range + } + + type text_document_item = { uri: document_uri ; text: string @@ -224,6 +236,38 @@ type server_capabilities = type initialized_params = empty_record +(* "publishDiagnostics" notification *) + +type publish_diagnostics_params = + { uri : document_uri + ; diagnostics : diagnostic list + } + + +type diagnostic = + { range : range + ; ?severity : int nullable (* diagnostic_severity *) + ; ?code : int nullable + ; ?source : string nullable + ; message : string + ; ?relatedInformation : (diagnostic_related_information list) nullable + } + + +(* TODO: figure out how to map these to 1, 2, 3, 4 *) +type diagnostic_severity = + [ Error + | Warning + | Information + | Hint + ] + +type diagnostic_related_information = + { location : location + ; message : string + } + + (* "window/showMessage" notification *) type window_show_message_params = From dd920a3d1d5f2ef4f92b63a6d16e086737b52a13 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Wed, 22 May 2019 17:15:48 -0700 Subject: [PATCH 0066/1176] Remove sanity check for initialize params --- src/languageServer.ml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/languageServer.ml b/src/languageServer.ml index 5b57c794cca..cde97c921b8 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -45,14 +45,6 @@ let start () = (* Request messages *) | (Some id, `Initialize params) -> - (match params.Lsp_t.initialize_params_trace with - | Some trace -> (match trace with - | `Off -> log_to_file "trace" "Off" - | `Messages -> log_to_file "trace" "Messages" - | `Verbose -> log_to_file "trace" "Verbose" - ); - | None -> log_to_file "trace" "null" - ); let result = `Initialize (Lsp_t. { initialize_result_capabilities = { server_capabilities_textDocumentSync = 1 From 5f6aa09d5fd803057f1af4b6006c3c8b0ede9e11 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Wed, 22 May 2019 18:01:37 -0700 Subject: [PATCH 0067/1176] Distinguish between responses and notifications --- src/languageServer.ml | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/languageServer.ml b/src/languageServer.ml index cde97c921b8..5d84bcbf6f7 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -3,13 +3,16 @@ let log_to_file lbl txt = Printf.fprintf oc "[%s] %s\n" lbl txt; flush oc -let send out = +let send label out = let cl = "Content-Length: " ^ string_of_int (String.length out) ^ "\r\n\r\n" in print_string cl; print_string out; flush stdout; - log_to_file "response_length" cl; - log_to_file "response" out + log_to_file (label ^ "_length") cl; + log_to_file label out + +let send_response = send "response" +let send_notification = send "notification" let show_message msg = let params = `WindowShowMessage (Lsp_t. @@ -17,7 +20,7 @@ let show_message msg = ; window_show_message_params_message = msg }) in let notification = Lsp.notification params in - send (Lsp_j.string_of_notification_message notification) + send_notification (Lsp_j.string_of_notification_message notification) let start () = let rec loop () = @@ -53,7 +56,7 @@ let start () = }) in let response = Lsp.response_result_message id result in log_to_file "response" (Lsp_j.string_of_response_message response); - send (Lsp_j.string_of_response_message response); + send_response (Lsp_j.string_of_response_message response); | (Some id, `TextDocumentHover params) -> let position = params.Lsp_t.text_document_position_params_position in @@ -64,7 +67,7 @@ let start () = ^ ", " ^ string_of_int position.position_character }) in let response = Lsp.response_result_message id result in - send (Lsp_j.string_of_response_message response); + send_response (Lsp_j.string_of_response_message response); | (_, `TextDocumentDidSave params) -> let textDocumentIdent = params.Lsp_t.text_document_did_save_params_textDocument in From 27a575bfdbb1794f4affb4fbdb94130659e1acca Mon Sep 17 00:00:00 2001 From: Paul Young Date: Wed, 22 May 2019 18:02:03 -0700 Subject: [PATCH 0068/1176] Remove duplicate logging --- src/languageServer.ml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/languageServer.ml b/src/languageServer.ml index 5d84bcbf6f7..f10476d5e05 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -55,7 +55,6 @@ let start () = } }) in let response = Lsp.response_result_message id result in - log_to_file "response" (Lsp_j.string_of_response_message response); send_response (Lsp_j.string_of_response_message response); | (Some id, `TextDocumentHover params) -> From 70a0b48048f0ccdb2cd840eb7c44236438da9a70 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Wed, 22 May 2019 18:03:53 -0700 Subject: [PATCH 0069/1176] Wrap up publish diagnostics --- src/languageServer.ml | 47 ++++++++++++++++++++++++++++++++++++++++--- src/lsp.atd | 3 ++- 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/src/languageServer.ml b/src/languageServer.ml index f10476d5e05..9f747befe07 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -22,7 +22,37 @@ let show_message msg = let notification = Lsp.notification params in send_notification (Lsp_j.string_of_notification_message notification) +let position_of_pos pos = Lsp_t. + (* The LSP spec requires zero-based positions *) + { position_line = if pos.Source.line > 0 then pos.Source.line - 1 else 0 + ; position_character = pos.Source.column + } + +let range_of_region at = Lsp_t. + { range_start = position_of_pos at.Source.left + ; range_end_ = position_of_pos at.Source.right + } + +let diagnostics_of_message msg = Lsp_t. + { diagnostic_range = range_of_region msg.Diag.at + ; diagnostic_severity = Some (match msg.Diag.sev with Diag.Error -> 1 | Diag.Warning -> 2) + ; diagnostic_code = None + ; diagnostic_source = Some "actorscript" + ; diagnostic_message = msg.Diag.text + ; diagnostic_relatedInformation = None + } + +let publish_diagnostics uri diags = + let params = `PublishDiagnostics (Lsp_t. + { publish_diagnostics_params_uri = uri + ; publish_diagnostics_params_diagnostics = diags + }) in + let notification = Lsp.notification params in + send_notification (Lsp_j.string_of_notification_message notification) + let start () = + let client_capabilities = ref None in + let rec loop () = let clength = read_line () in log_to_file "content-length" clength; @@ -48,6 +78,7 @@ let start () = (* Request messages *) | (Some id, `Initialize params) -> + client_capabilities := Some params.Lsp_t.initialize_params_capabilities; let result = `Initialize (Lsp_t. { initialize_result_capabilities = { server_capabilities_textDocumentSync = 1 @@ -78,15 +109,25 @@ let start () = false [file_name] in show_message ("Compiling file: " ^ file_name); + (* TODO: let msgs = match result with | Error msgs -> msgs | Ok (_, msgs) -> in *) (match result with | Ok _ -> show_message "Compilation successful" - | Error diag -> - (* TODO: publish diagnostics, if capable *) + | Error msgs -> + (match !client_capabilities with + | Some capabilities -> + (* TODO: determine if the client accepts diagnostics with related info *) + (* let textDocument = capabilities.client_capabilities_textDocument in + * let send_related_information = textDocument.publish_diagnostics.relatedInformation in *) + let diags = List.map diagnostics_of_message msgs in + publish_diagnostics uri diags; + | None -> ()); + + (* TODO: remove *) show_message ("Compilation failed with " ^ String.concat " " - (List.map Diag.string_of_message diag))) + (List.map Diag.string_of_message msgs))) end | None -> log_to_file diff --git a/src/lsp.atd b/src/lsp.atd index 6ab28059da1..5ed881b7990 100644 --- a/src/lsp.atd +++ b/src/lsp.atd @@ -79,7 +79,8 @@ type hover_result = (* Outgoing notifications *) type notification_message_params = - [ WindowShowMessage of window_show_message_params + [ PublishDiagnostics of publish_diagnostics_params + | WindowShowMessage of window_show_message_params ] From a42fd18fe52a605e2af5553b4d6764309d1cc811 Mon Sep 17 00:00:00 2001 From: Christoph Hegemann Date: Thu, 23 May 2019 10:23:07 +0200 Subject: [PATCH 0070/1176] adds for_maybe --- src/languageServer.ml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/languageServer.ml b/src/languageServer.ml index 9f747befe07..acbf839b0b4 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -42,6 +42,11 @@ let diagnostics_of_message msg = Lsp_t. ; diagnostic_relatedInformation = None } +let for_option (m: 'a option) (f: 'a -> unit): unit = + match m with + | Some x -> f x + | None -> () + let publish_diagnostics uri diags = let params = `PublishDiagnostics (Lsp_t. { publish_diagnostics_params_uri = uri @@ -113,14 +118,13 @@ let start () = (match result with | Ok _ -> show_message "Compilation successful" | Error msgs -> - (match !client_capabilities with - | Some capabilities -> + (for_option !client_capabilities (fun capabilities -> (* TODO: determine if the client accepts diagnostics with related info *) (* let textDocument = capabilities.client_capabilities_textDocument in * let send_related_information = textDocument.publish_diagnostics.relatedInformation in *) let diags = List.map diagnostics_of_message msgs in publish_diagnostics uri diags; - | None -> ()); + )); (* TODO: remove *) show_message From 1bd24650e0419b6aea53dba3a9d5bdf435592369 Mon Sep 17 00:00:00 2001 From: Christoph Hegemann Date: Thu, 23 May 2019 10:23:15 +0200 Subject: [PATCH 0071/1176] adds explicit type signatures to all top-level functions --- src/languageServer.ml | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/languageServer.ml b/src/languageServer.ml index acbf839b0b4..8c240d9cded 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -1,9 +1,9 @@ -let oc = open_out_gen [Open_append; Open_creat] 0o666 "ls.log" -let log_to_file lbl txt = +let oc: out_channel = open_out_gen [Open_append; Open_creat] 0o666 "ls.log" +let log_to_file (lbl: string) (txt: string): unit = Printf.fprintf oc "[%s] %s\n" lbl txt; flush oc -let send label out = +let send (label: string) (out: string): unit = let cl = "Content-Length: " ^ string_of_int (String.length out) ^ "\r\n\r\n" in print_string cl; print_string out; @@ -11,29 +11,31 @@ let send label out = log_to_file (label ^ "_length") cl; log_to_file label out -let send_response = send "response" -let send_notification = send "notification" +let send_response: string -> unit = send "response" +let send_notification: string -> unit = send "notification" -let show_message msg = - let params = `WindowShowMessage (Lsp_t. - { window_show_message_params_type_ = 3 - ; window_show_message_params_message = msg - }) in +let show_message (msg: string): unit = + let params = + `WindowShowMessage + (Lsp_t. + { window_show_message_params_type_ = 3 + ; window_show_message_params_message = msg + }) in let notification = Lsp.notification params in send_notification (Lsp_j.string_of_notification_message notification) -let position_of_pos pos = Lsp_t. +let position_of_pos (pos: Source.pos): Lsp_t.position = Lsp_t. (* The LSP spec requires zero-based positions *) { position_line = if pos.Source.line > 0 then pos.Source.line - 1 else 0 ; position_character = pos.Source.column } -let range_of_region at = Lsp_t. +let range_of_region (at: Source.region): Lsp_t.range = Lsp_t. { range_start = position_of_pos at.Source.left ; range_end_ = position_of_pos at.Source.right } -let diagnostics_of_message msg = Lsp_t. +let diagnostics_of_message (msg: Diag.message): Lsp_t.diagnostic = Lsp_t. { diagnostic_range = range_of_region msg.Diag.at ; diagnostic_severity = Some (match msg.Diag.sev with Diag.Error -> 1 | Diag.Warning -> 2) ; diagnostic_code = None @@ -47,7 +49,7 @@ let for_option (m: 'a option) (f: 'a -> unit): unit = | Some x -> f x | None -> () -let publish_diagnostics uri diags = +let publish_diagnostics (uri: Lsp_t.document_uri) (diags: Lsp_t.diagnostic list): unit = let params = `PublishDiagnostics (Lsp_t. { publish_diagnostics_params_uri = uri ; publish_diagnostics_params_diagnostics = diags From 43fd670ba1d2c6d54fdef3abb59862401ef30b8a Mon Sep 17 00:00:00 2001 From: Christoph Hegemann Date: Thu, 23 May 2019 10:31:45 +0200 Subject: [PATCH 0072/1176] generalize for_option --- src/languageServer.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/languageServer.ml b/src/languageServer.ml index 8c240d9cded..1ddce2bc4e5 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -44,9 +44,9 @@ let diagnostics_of_message (msg: Diag.message): Lsp_t.diagnostic = Lsp_t. ; diagnostic_relatedInformation = None } -let for_option (m: 'a option) (f: 'a -> unit): unit = +let for_option (m: 'a option) (f: 'a -> 'b): unit = match m with - | Some x -> f x + | Some x -> f x; () | None -> () let publish_diagnostics (uri: Lsp_t.document_uri) (diags: Lsp_t.diagnostic list): unit = From 6cab763a9d25d702cc0ee5a12c7e50794655aeaa Mon Sep 17 00:00:00 2001 From: Christoph Hegemann Date: Thu, 23 May 2019 13:19:40 +0200 Subject: [PATCH 0073/1176] use Base.Option.iter --- src/languageServer.ml | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/languageServer.ml b/src/languageServer.ml index 1ddce2bc4e5..3f2bea0171b 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -44,11 +44,6 @@ let diagnostics_of_message (msg: Diag.message): Lsp_t.diagnostic = Lsp_t. ; diagnostic_relatedInformation = None } -let for_option (m: 'a option) (f: 'a -> 'b): unit = - match m with - | Some x -> f x; () - | None -> () - let publish_diagnostics (uri: Lsp_t.document_uri) (diags: Lsp_t.diagnostic list): unit = let params = `PublishDiagnostics (Lsp_t. { publish_diagnostics_params_uri = uri @@ -120,15 +115,13 @@ let start () = (match result with | Ok _ -> show_message "Compilation successful" | Error msgs -> - (for_option !client_capabilities (fun capabilities -> + (Base.Option.iter !client_capabilities ~f:(fun capabilities -> (* TODO: determine if the client accepts diagnostics with related info *) (* let textDocument = capabilities.client_capabilities_textDocument in * let send_related_information = textDocument.publish_diagnostics.relatedInformation in *) let diags = List.map diagnostics_of_message msgs in publish_diagnostics uri diags; )); - - (* TODO: remove *) show_message ("Compilation failed with " ^ String.concat From d84d51db1cfd58735cb50f7542d56d9a6c2d48ba Mon Sep 17 00:00:00 2001 From: Christoph Hegemann Date: Thu, 23 May 2019 14:17:24 +0200 Subject: [PATCH 0074/1176] fix method name for publishDiagnostics --- src/lsp.atd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lsp.atd b/src/lsp.atd index 5ed881b7990..32d54a1683c 100644 --- a/src/lsp.atd +++ b/src/lsp.atd @@ -79,7 +79,7 @@ type hover_result = (* Outgoing notifications *) type notification_message_params = - [ PublishDiagnostics of publish_diagnostics_params + [ PublishDiagnostics of publish_diagnostics_params | WindowShowMessage of window_show_message_params ] From 36586aba9fa1ee2d772abd20c44f4a7a928ce4a0 Mon Sep 17 00:00:00 2001 From: Christoph Hegemann Date: Thu, 23 May 2019 14:17:36 +0200 Subject: [PATCH 0075/1176] clear existing diagnostics on successful compilation --- src/languageServer.ml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/languageServer.ml b/src/languageServer.ml index 3f2bea0171b..ccae4bb9b44 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -113,15 +113,18 @@ let start () = show_message ("Compiling file: " ^ file_name); (* TODO: let msgs = match result with | Error msgs -> msgs | Ok (_, msgs) -> in *) (match result with - | Ok _ -> show_message "Compilation successful" + | Ok _ -> + (* It's our responsibility to clear any existing diagnostics *) + publish_diagnostics uri []; + show_message "Compilation successful" | Error msgs -> (Base.Option.iter !client_capabilities ~f:(fun capabilities -> (* TODO: determine if the client accepts diagnostics with related info *) (* let textDocument = capabilities.client_capabilities_textDocument in * let send_related_information = textDocument.publish_diagnostics.relatedInformation in *) - let diags = List.map diagnostics_of_message msgs in - publish_diagnostics uri diags; - )); + let diags = List.map diagnostics_of_message msgs in + publish_diagnostics uri diags; + )); show_message ("Compilation failed with " ^ String.concat From d74ed4fbc98329a84abaf0767c086421520abe44 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 23 May 2019 13:40:13 -0700 Subject: [PATCH 0076/1176] new trie design; use variants for datatype --- stdlib/list.as | 16 + stdlib/trie2.as | 1237 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1253 insertions(+) create mode 100644 stdlib/trie2.as diff --git a/stdlib/list.as b/stdlib/list.as index 2bd5aaadfc2..0a688f3adb9 100644 --- a/stdlib/list.as +++ b/stdlib/list.as @@ -167,6 +167,22 @@ type List = ?(T, List); rec(l) }; + /** + `split` + ---------- + split the list elements; non-tail recursive + */ + func split(l : List, f:T -> Bool) : (List, List) = { + func rec(l : List) : (List, List) { + switch l { + case null { (null, null) }; + case (?(h,t)) { let (l,r) = rec(t) ; + if (f(h)){ (?(h,l), r) } else { (l, ?(h,r)) } }; + } + }; + rec(l) + }; + /** `mapFilter` -------------- diff --git a/stdlib/trie2.as b/stdlib/trie2.as new file mode 100644 index 00000000000..35bd9693d0d --- /dev/null +++ b/stdlib/trie2.as @@ -0,0 +1,1237 @@ +/** + +Hash tries +====================== + +Functional maps (and sets) whose representation is "canonical", and +history independent. + +Background +------------------ + +See this POPL 1989 paper (Section 6): + + - ["Incremental computation via function caching", Pugh & Teitelbaum](https://dl.acm.org/citation.cfm?id=75305). + - [Public copy here](http://matthewhammer.org/courses/csci7000-s17/readings/Pugh89.pdf). + +By contrast, other usual functional representations of maps (AVL +Trees, Red-Black Trees) do not enjoy history independence, and are +each more complex to implement (e.g., each requires "rebalancing"; +these trees never do). + +*/ + +/** +Representation +===================== + +Below, we define the types used in the representation: + + - **`Key`**, parameterized by a hashable type `K` + + +See the full details in the definitions below: + +*/ + +let P = (import "prelude.as"); + +let Hash = (import "hash.as").BitVec; +type Hash = Hash.t; + +let List = import "list.as"; +type List = List.List; + +let AssocList = import "assocList.as"; +type AssocList = AssocList.AssocList; + +type Key = { + // hash field: permits fast inequality checks, permits collisions; + // (eventually: permits incremental growth of deeper trie paths) + hash: Hash; + // key field: for conservative equality checks, after equal hashes. + key: K; +}; + +// Equality function for two `Key`s, in terms of equaltiy of `K`'s. +func keyEq(keq:(K,K) -> Bool) : ((Key,Key) -> Bool) = { + func (key1:Key, key2:Key) : Bool = + label profile_trie_keyEq : Bool + (Hash.hashEq(key1.hash, key2.hash) and keq(key1.key, key2.key)) +}; + +type Trie = { + #empty ; + #leaf : AssocList,V> ; + #branch : (Trie, Trie) ; +}; + +/** + Two-dimensional trie + --------------------- + A 2D trie is just a trie that maps dimension-1 keys to another + layer of tries, each keyed on the dimension-2 keys. +*/ +type Trie2D = Trie >; + +/** + Three-dimensional trie + --------------------- + A 3D trie is just a trie that maps dimension-1 keys to another + layer of 2D tries, each keyed on the dimension-2 and dimension-3 keys. +*/ +type Trie3D = Trie >; + +/** + Module interface + =================== + */ + + /** + `empty` + -------- + An empty trie. + */ + func empty() : Trie = #empty; + + /** + `copy` + --------- + Purely-functional representation permits _O(1)_-time copy, via persistent sharing. + */ + func copy(t : Trie) : Trie = t; + + /** + `replace` + --------- + replace the given key's value option with the given one, returning the previous one + */ + func replace(t : Trie, k:Key, k_eq:(K,K)->Bool, v:?V) : (Trie, ?V) { + let key_eq = keyEq(k_eq); + func rec(t : Trie, bitpos:Nat) : (Trie, ?V) { + switch t { + case (#empty) { + let (kvs, _) = AssocList.replace,V>(null, k, key_eq, v); + ((#leaf(kvs)), null) + }; + case (#branch b) { + let bit = Hash.getHashBit(k.hash, bitpos); + // rebuild either the left or right path with the inserted (k,v) pair + if (not bit) { + let (l, v_) = rec(b.0, bitpos+1); + (#branch(l, b.1), v_) + } + else { + let (r, v_) = rec(b.1, bitpos+1); + (#branch(b.0, r), v_) + } + }; + case (#leaf al) { + let (kvs2, old_val) = + AssocList.replace,V>(al, k, key_eq, v); + (#leaf(kvs2), old_val) + }; + } + }; + rec(t, 0) + }; + + /** + `find` + --------- + find the given key's value in the trie, or return null if nonexistent + */ + func find(t : Trie, k:Key, k_eq:(K,K) -> Bool) : ?V { + let key_eq = keyEq(k_eq); + func rec(t : Trie, bitpos:Nat) : ?V = label profile_trie_find_rec : (?V) { + switch t { + case (#empty) { + label profile_trie_find_end_null : (?V) + null + }; + case (#leaf as) { + label profile_trie_find_end_assocList_find : (?V) + AssocList.find,V>(as, k, key_eq) + }; + case (#branch(l,r)) { + let bit = Hash.getHashBit(k.hash, bitpos); + if (not bit) { + label profile_trie_find_branch_left : (?V) + rec(l, bitpos+1) + } + else { + label profile_trie_find_branch_right : (?V) + rec(r, bitpos+1) + } + }; + } + }; + label profile_trie_find_begin : (?V) + rec(t, 0) + }; + + + func splitAssocList(al:AssocList,V>, bitpos:Nat) + : (AssocList,V>, AssocList,V>) + { + List.split<(Key,V)>( + al, + func ((k : Key, v : V)) : Bool{ + Hash.getHashBit(k.hash, bitpos) + } + ) + }; + + /** + `merge` + --------- + merge tries, preferring the right trie where there are collisions + in common keys. note: the `disj` operation generalizes this `merge` + operation in various ways, and does not (in general) loose + information; this operation is a simpler, special case. + + See also: + + - [`disj`](#disj) + - [`join`](#join) + - [`prod`](#prod) + + */ + func merge(tl:Trie, tr:Trie, k_eq:(K,K)->Bool): Trie { + let key_eq = keyEq(k_eq); + func rec(bitpos:Nat, tl:Trie, tr:Trie) : Trie { + switch (tl, tr) { + case (#empty, _) { return tr }; + case (_, #empty) { return tl }; + case (#leaf as, #leaf bs) { + #leaf( + AssocList.disj,V,V,V>( + as, bs, + key_eq, + func (x:?V, y:?V):V = { + switch (x, y) { + case (null, null) { P.unreachable() }; + case (null, ?v) v; + case (?v, _) v; + }} + ) + ) + }; + case (#leaf al, _) { + let (l,r) = splitAssocList(al, bitpos); + rec(bitpos, #branch(#leaf l, #leaf r), tr) + }; + case (_, #leaf al) { + let (l,r) = splitAssocList(al, bitpos); + rec(bitpos, tl, #branch(#leaf l, #leaf r)) + }; + case (#branch (ll, lr), #branch(rl, rr)) { + #branch(rec(bitpos + 1, ll, rl), + rec(bitpos + 1, lr, rr)) + }; + } + }; + rec(0, tl, tr) + }; + +/* + /** + `mergeDisjoint` + ---------------- + like `merge`, it merges tries, but unlike `merge`, it signals a + dynamic error if there are collisions in common keys between the + left and right inputs. + */ + func mergeDisjoint(tl:Trie, tr:Trie, k_eq:(K,K)->Bool): Trie { + let key_eq = keyEq(k_eq); + func rec(tl:Trie, tr:Trie) : Trie { + switch (tl, tr) { + case (null, _) { return tr }; + case (_, null) { return tl }; + case (?nl,?nr) { + switch (isBin(tl), + isBin(tr)) { + case (true, true) { + let t0 = rec(nl.left, nr.left); + let t1 = rec(nl.right, nr.right); + makeBin(t0, t1) + }; + case (false, true) { + assert(false); + // XXX impossible, until we lift uniform depth assumption + tr + }; + case (true, false) { + assert(false); + // XXX impossible, until we lift uniform depth assumption + tr + }; + case (false, false) { + /// handle hash collisions by using the association list: + makeLeaf( + AssocList.disj,V,V,V>( + nl.keyvals, nr.keyvals, + key_eq, + func (x:?V, y:?V):V = { + switch (x, y) { + case (null, null) { + /* IMPOSSIBLE case. */ + assert false; func x():V=x(); x() + }; + case (?_, ?_) { + /* INVALID case: left and right defined for the same key */ + assert false; func x():V=x(); x() + }; + case (null, ?v) v; + case (?v, null) v; + }} + )) + }; + } + }; + } + }; + rec(tl, tr) + }; +*/ + + + + + +/* + /** + `diff` + ------ + The key-value pairs of the final trie consists of those pairs of + the left trie whose keys are not present in the right trie; the + values of the right trie are irrelevant. + */ + func diff(tl:Trie, tr:Trie, k_eq:(K,K)->Bool) : Trie { + let key_eq = keyEq(k_eq); + func rec(tl:Trie, tr:Trie) : Trie { + switch (tl, tr) { + case (null, _) { return makeEmpty() }; + case (_, null) { return tl }; + case (?nl,?nr) { + switch (isBin(tl), + isBin(tr)) { + case (true, true) { + let t0 = rec(nl.left, nr.left); + let t1 = rec(nl.right, nr.right); + makeBin(t0, t1) + }; + case (false, true) { + assert false; + // XXX impossible, until we lift uniform depth assumption + tl + }; + case (true, false) { + assert false; + // XXX impossible, until we lift uniform depth assumption + tl + }; + case (false, false) { + assert(isLeaf(tl)); + assert(isLeaf(tr)); + makeLeaf( + AssocList.diff,V,W>(nl.keyvals, nr.keyvals, key_eq) + ) + }; + } + }; + }}; + rec(tl, tr) + }; +*/ + +/* + /** + `disj` + -------- + + This operation generalizes the notion of "set union" to finite maps. + + Produces a "disjunctive image" of the two tries, where the values of + matching keys are combined with the given binary operator. + + For unmatched key-value pairs, the operator is still applied to + create the value in the image. To accomodate these various + situations, the operator accepts optional values, but is never + applied to (null, null). + + Implements the database idea of an ["outer join"](https://stackoverflow.com/questions/38549/what-is-the-difference-between-inner-join-and-outer-join). + + See also: + + - [`join`](#join) + - [`merge`](#merge) + - [`prod`](#prod) + + */ + func disj(tl:Trie, tr:Trie, + k_eq:(K,K)->Bool, vbin:(?V,?W)->X) + : Trie + { + let key_eq = keyEq(k_eq); + func recL(t:Trie) : Trie { + switch t { + case (null) null; + case (? n) { + switch (matchLeaf(t)) { + case (?_) { makeLeaf(AssocList.disj,V,W,X>(n.keyvals, null, key_eq, vbin)) }; + case _ { makeBin(recL(n.left), recL(n.right)) } + } + }; + }}; + func recR(t:Trie) : Trie { + switch t { + case (null) null; + case (? n) { + switch (matchLeaf(t)) { + case (?_) { makeLeaf(AssocList.disj,V,W,X>(null, n.keyvals, key_eq, vbin)) }; + case _ { makeBin(recR(n.left), recR(n.right)) } + } + }; + }}; + func rec(tl:Trie, tr:Trie) : Trie { + switch (tl, tr) { + // empty-empty terminates early, all other cases do not. + case (null, null) { makeEmpty() }; + case (null, _ ) { recR(tr) }; + case (_, null) { recL(tl) }; + case (? nl, ? nr) { + switch (isBin(tl), + isBin(tr)) { + case (true, true) { + let t0 = rec(nl.left, nr.left); + let t1 = rec(nl.right, nr.right); + makeBin(t0, t1) + }; + case (false, true) { + assert false; + // XXX impossible, until we lift uniform depth assumption + makeEmpty() + }; + case (true, false) { + assert false; + // XXX impossible, until we lift uniform depth assumption + makeEmpty() + }; + case (false, false) { + assert(isLeaf(tl)); + assert(isLeaf(tr)); + makeLeaf( + AssocList.disj,V,W,X>(nl.keyvals, nr.keyvals, key_eq, vbin) + ) + }; + } + }; + }}; + rec(tl, tr) + }; +*/ + +/* + /** + `join` + --------- + This operation generalizes the notion of "set intersection" to + finite maps. Produces a "conjuctive image" of the two tries, where + the values of matching keys are combined with the given binary + operator, and unmatched key-value pairs are not present in the output. + + Implements the database idea of an ["inner join"](https://stackoverflow.com/questions/38549/what-is-the-difference-between-inner-join-and-outer-join). + + See also: + + - [`disj`](#disj) + - [`merge`](#merge) + - [`prod`](#prod) + + */ + func join(tl:Trie, tr:Trie, + k_eq:(K,K)->Bool, vbin:(V,W)->X) + : Trie + { + let key_eq = keyEq(k_eq); + func rec(tl:Trie, tr:Trie) : Trie { + switch (tl, tr) { + case (null, null) { return makeEmpty() }; + case (null, ? nr) { return makeEmpty() }; + case (? nl, null) { return makeEmpty() }; + case (? nl, ? nr) { + switch (isBin(tl), + isBin(tr)) { + case (true, true) { + let t0 = rec(nl.left, nr.left); + let t1 = rec(nl.right, nr.right); + makeBin(t0, t1) + }; + case (false, true) { + assert false; + // XXX impossible, until we lift uniform depth assumption + makeEmpty() + }; + case (true, false) { + assert false; + // XXX impossible, until we lift uniform depth assumption + makeEmpty() + }; + case (false, false) { + assert(isLeaf(tl)); + assert(isLeaf(tr)); + makeLeaf( + AssocList.join,V,W,X>(nl.keyvals, nr.keyvals, key_eq, vbin) + ) + }; + } + } + }}; + rec(tl, tr) + }; +*/ + +/* + /** + + `prod` + --------- + + Conditional _catesian product_, where the given + operation `op` _conditionally_ creates output elements in the + resulting trie. + + The keyed structure of the input tries are not relevant for this + operation: all pairs are considered, regardless of keys matching or + not. Moreover, the resulting trie may use keys that are unrelated to + these input keys. + + See also: + + - [`disj`](#disj) + - [`join`](#join) + - [`merge`](#merge) + + */ + func prod( + tl :Trie, + tr :Trie, + op :(K1,V1,K2,V2) -> ?(Key,V3), + k3_eq :(K3,K3) -> Bool + ) + : Trie + { + /**- binary case: merge disjoint results: */ + func merge (a:Trie, b:Trie) : Trie = + mergeDisjoint(a, b, k3_eq); + + /**- `foldUp` "squared"; something like "`foldUp^2((tl, tr), merge, (insert null >( + tl, merge, + func (k1:K1, v1:V1) : Trie { + foldUp>( + tr, merge, + func (k2:K2, v2:V2) : Trie { + switch (op(k1, v1, k2, v2)) { + case null null; + case (?(k3, v3)) { (insert(null, k3, k3_eq, v3)).0 }; + } + }, + null + ) + }, + null + ) + }; +*/ + +/* + /** + `foldUp` + ------------ + This operation gives a recursor for the internal structure of + tries. Many common operations are instantiations of this function, + either as clients, or as hand-specialized versions (e.g., see map, + mapFilter, exists and forAll below). + */ + func foldUp(t:Trie, bin:(X,X)->X, leaf:(K,V)->X, empty:X) : X { + func rec(t:Trie) : X { + switch t { + case (null) { empty }; + case (?n) { + switch (matchLeaf(t)) { + case (?kvs) { + AssocList.fold,V,X>( + kvs, empty, + func (k:Key, v:V, x:X):X = + bin(leaf(k.key,v),x) + ) + }; + case null { bin(rec(n.left), rec(n.right)) }; + } + }; + }}; + rec(t) + }; + + /** + `fold` + --------- + Fold over the key-value pairs of the trie, using an accumulator. + The key-value pairs have no reliable or meaningful ordering. + */ + func fold(t:Trie, f:(K,V,X)->X, x:X) : X { + func rec(t:Trie, x:X) : X { + switch t { + case (null) x; + case (?n) { + switch (matchLeaf(t)) { + case (?kvs) { + AssocList.fold,V,X>( + kvs, x, + func (k:Key, v:V, x:X):X = f(k.key,v,x) + ) + }; + case null { rec(n.left,rec(n.right,x)) }; + } + }; + }}; + rec(t, x) + }; + + /** + `exists` + -------- + Test whether a given key-value pair is present, or not. + */ + func exists(t:Trie, f:(K,V)->Bool) : Bool { + func rec(t:Trie) : Bool { + switch t { + case (null) { false }; + case (?n) { + switch (matchLeaf(t)) { + case (?kvs) { + List.exists<(Key,V)>( + kvs, func ((k:Key,v:V)):Bool=f(k.key,v) + ) + }; + case null { rec(n.left) or rec(n.right) }; + } + }; + }}; + rec(t) + }; + + + /** + `forAll` + --------- + Test whether all key-value pairs have a given property. + */ + func forAll(t:Trie, f:(K,V)->Bool) : Bool { + func rec(t:Trie) : Bool { + switch t { + case (null) { true }; + case (?n) { + switch (matchLeaf(t)) { + case (?kvs) { + List.all<(Key,V)>( + kvs, func ((k:Key,v:V)):Bool=f(k.key,v) + ) + }; + case null { rec(n.left) and rec(n.right) }; + } + }; + }}; + rec(t) + }; + + /** + `count` + -------- + Count the number of entries in the trie. + */ + func count(t:Trie):Nat{ + foldUp + (t, + func(n:Nat,m:Nat):Nat{n+m}, + func(_:K,_:V):Nat{1}, + 0) + }; + + /** + `toArray` + -------- + Gather the collection of key-value pairs into an array. + + To do: make this more efficient, using a single array allocation. + */ + func toArray(t:Trie,f:(K,V)->[W]):[W] = + label profile_trie_toArray_begin : [W] { + func arrayAppend(x:[W],y:[W]):[W] { + label profile_trie_toArray_arrayAppend : [W] + Array_tabulate ( + x.len() + y.len(), + func (i:Nat) : W = label profile_trie_toArray_arrayAppend_projelm : W { + if (i >= x.len()) { y[i - x.len()] } + else { x[i] } + } + ) + }; + let result = foldUp + (t, + arrayAppend, + func(k:K, v:V):[W]{f(k,v)}, + []); + label profile_trie_toArray_end : [W] + result + }; + + /** + `isEmpty` + ----------- + specialized foldUp operation. + Test for "deep emptiness": subtrees that have branching structure, + but no leaves. These can result from naive filtering operations; + filter uses this function to avoid creating such subtrees. + */ + func isEmpty(t:Trie) : Bool { + func rec(t:Trie) : Bool { + switch t { + case (null) { true }; + case (?n) { + switch (matchLeaf(t)) { + case (?kvs) { List.isNil<(Key,V)>(kvs) }; + case null { rec(n.left) and rec(n.right) }; + } + }; + } + }; + rec(t) + }; + + /** + `filter` + ----------- + filter the key-value pairs by a given predicate. + */ + func filter(t:Trie, f:(K,V)->Bool) : Trie { + func rec(t:Trie) : Trie { + switch t { + case (null) { null }; + case (?n) { + switch (matchLeaf(t)) { + case (?kvs) { + makeLeaf( + List.filter<(Key,V)>(kvs, func ((k:Key,v:V)):Bool = f(k.key,v)) + ) + }; + case null { + let l = rec(n.left); + let r = rec(n.right); + switch (isEmpty(l), + isEmpty(r)) { + case (true, true) null; + case (false, true) r; + case (true, false) l; + case (false, false) makeBin(l, r); + } + }; + } + }; + } + }; + rec(t) + }; + + /** + `mapFilter` + ----------- + map and filter the key-value pairs by a given partial mapping function. + */ + func mapFilter(t:Trie, f:(K,V)->?W) : Trie { + func rec(t:Trie) : Trie { + switch t { + case (null) { null }; + case (?n) { + switch (matchLeaf(t)) { + case (?kvs) { + makeLeaf( + List.mapFilter<(Key,V),(Key,W)> + (kvs, + // retain key and hash, but update key's value using f: + func ((k:Key,v:V)):?(Key,W) = { + switch (f(k.key,v)) { + case (null) null; + case (?w) (?(new {key=k.key; hash=k.hash}, w)); + }} + )) + }; + case null { + let l = rec(n.left); + let r = rec(n.right); + switch (isEmpty(l), + isEmpty(r)) { + case (true, true) null; + case (false, true) r; + case (true, false) l; + case (false, false) makeBin(l, r); + } + }; + } + }; + } + }; + rec(t) + }; + + /** + `equalStructure` + ------------------ + + Test for equality, but naively, based on structure. + Does not attempt to remove "junk" in the tree; + For instance, a "smarter" approach would equate + `#bin{left=#empty;right=#empty}` + with + `#empty`. + We do not observe that equality here. + */ + func equalStructure( + tl:Trie, + tr:Trie, + keq:(K,K)->Bool, + veq:(V,V)->Bool + ) : Bool { + func rec(tl:Trie, tr:Trie) : Bool { + switch (tl, tr) { + case (null, null) { true }; + case (_, null) { false }; + case (null, _) { false }; + case (?nl, ?nr) { + switch (matchLeaf(tl), + matchLeaf(tr)) { + case (null, null) { + rec(nl.left, nr.left) + and rec(nl.right, nr.right) + }; + case (null, _) { false }; + case (_, null) { false }; + case (?kvs1, ?kvs2) { + List.isEq<(Key,V)> + (kvs1, kvs2, + func ((k1:Key, v1:V), (k2:Key, v2:V)) : Bool = + keq(k1.key, k2.key) and veq(v1,v2) + ) + }; + } + }; + }}; + rec(tl, tr) + }; + + + + + + + /** + + ------------------------------------------------------------------------------------------------- + + `replaceThen` + ------------ + replace the given key's value in the trie, + and only if successful, do the success continuation, + otherwise, return the failure value + */ + func replaceThen(t : Trie, k:Key, k_eq:(K,K)->Bool, v2:V, + success: (Trie, V) -> X, + fail: () -> X) + : X + { + let (t2, ov) = replace(t, k, k_eq, ?v2); + switch ov { + case (null) { /* no prior value; failure to remove */ fail() }; + case (?v1) { success(t2, v1) }; + } + }; + + /** + `insert` + ------------ + insert the given key's value in the trie; return the new trie, and the previous value associated with the key, if any + */ + func insert(t : Trie, k:Key, k_eq:(K,K)->Bool, v:V) : (Trie, ?V) { + replace(t, k, k_eq, ?v) + }; + + /** + `insertFresh` + ---------------- + insert the given key's value in the trie; return the new trie; assert that no prior value is associated with the key + */ + func insertFresh(t : Trie, k:Key, k_eq:(K,K)->Bool, v:V) : Trie { + let (t2, none) = replace(t, k, k_eq, ?v); + switch none { + case (null) (); + case (?_) assert false; + }; + t2 + }; + + /** + `insert2D` + --------------- + insert the given key's value in the 2D trie; return the new 2D trie. + */ + func insert2D(t : Trie2D, + k1:Key, k1_eq:(K1,K1)->Bool, + k2:Key, k2_eq:(K2,K2)->Bool, + v:V) + : Trie2D + { + let inner = find>(t, k1, k1_eq); + let (updated_inner, _) = switch inner { + case (null) { insert(null, k2, k2_eq, v) }; + case (?inner) { insert(inner, k2, k2_eq, v) }; + }; + let (updated_outer, _) = { insert>(t, k1, k1_eq, updated_inner) }; + updated_outer; + }; + + /** + `insert3D` + --------------- + insert the given key's value in the trie; return the new trie; + */ + func insert3D + (t : Trie3D, + k1:Key, k1_eq:(K1,K1)->Bool, + k2:Key, k2_eq:(K2,K2)->Bool, + k3:Key, k3_eq:(K3,K3)->Bool, + v:V + ) + : Trie3D + { + let inner1 = find>(t, k1, k1_eq); + let (updated_inner1, _) = switch inner1 { + case (null) { + insert>( + null, k2, k2_eq, + (insert(null, k3, k3_eq, v)).0 + ) + }; + case (?inner1) { + let inner2 = find>(inner1, k2, k2_eq); + let (updated_inner2, _) = switch inner2 { + case (null) { insert(null, k3, k3_eq, v) }; + case (?inner2) { insert(inner2, k3, k3_eq, v) }; + }; + insert>( inner1, k2, k2_eq, updated_inner2 ) + }; + }; + let (updated_outer, _) = { insert>(t, k1, k1_eq, updated_inner1) }; + updated_outer; + }; + + /** + `remove` + ------------- + remove the given key's value in the trie; return the new trie + */ + func remove(t : Trie, k:Key, k_eq:(K,K)->Bool) : (Trie, ?V) { + replace(t, k, k_eq, null) + }; + + /** + `removeThen` + ------------ + remove the given key's value in the trie, + and only if successful, do the success continuation, + otherwise, return the failure value + */ + func removeThen(t : Trie, k:Key, k_eq:(K,K)->Bool, + success: (Trie, V) -> X, + fail: () -> X) + : X + { + let (t2, ov) = replace(t, k, k_eq, null); + switch ov { + case (null) { /* no prior value; failure to remove */ fail() }; + case (?v) { success(t2, v) }; + } + }; + + + /** + `remove2D` + -------------- + remove the given key-key pair's value in the 2D trie; return the + new trie, and the prior value, if any. + */ + func remove2D(t : Trie2D, + k1:Key, k1_eq:(K1,K1)->Bool, + k2:Key, k2_eq:(K2,K2)->Bool) + : (Trie2D, ?V) + { + switch (find>(t, k1, k1_eq)) { + case (null) { + (t, null) + }; + case (?inner) { + let (updated_inner, ov) = remove(inner, k2, k2_eq); + let (updated_outer, _) = { + insert>(t, k1, k1_eq, updated_inner) + }; + (updated_outer, ov) + }; + } + }; + + /** + `remove3D` + --------------- + remove the given key-key pair's value in the 3D trie; return the + new trie, and the prior value, if any. + */ + func remove3D + (t : Trie3D, + k1:Key, k1_eq:(K1,K1)->Bool, + k2:Key, k2_eq:(K2,K2)->Bool, + k3:Key, k3_eq:(K3,K3)->Bool, + ) + : (Trie3D, ?V) + { + switch (find>(t, k1, k1_eq)) { + case (null) { + (t, null) + }; + case (?inner) { + let (updated_inner, ov) = remove2D(inner, k2, k2_eq, k3, k3_eq); + let (updated_outer, _) = { + insert>(t, k1, k1_eq, updated_inner) + }; + (updated_outer, ov) + }; + } + }; + + + + /** + `mergeDisjoint2D` + -------------- + + Like [`mergeDisjoint`](#mergedisjoint), except instead of merging a + pair, it merges the collection of dimension-2 sub-trees of a 2D + trie. + + */ + func mergeDisjoint2D(t : Trie2D, k1_eq:(K1,K1)->Bool, k2_eq:(K2,K2)->Bool) + : Trie + { + foldUp, Trie> + ( t, + func (t1:Trie, t2:Trie):Trie { mergeDisjoint(t1, t2, k2_eq) }, + func (_:K1, t:Trie): Trie { t }, + null ) + }; + + // Equality function for two `Key`s, in terms of equaltiy of `K`'s. + func keyEq(keq:(K,K) -> Bool) : ((Key,Key) -> Bool) = { + func (key1:Key, key2:Key) : Bool = + label profile_trie_keyEq : Bool + (Hash.hashEq(key1.hash, key2.hash) and keq(key1.key, key2.key)) + }; + + /** + Helpers for missing variants + ============================== + Until ActorScript has variant types, we need various helper functions here. They are uninteresting. + */ + // @Omit: + + // XXX: until AST-42: + func isNull(x : ?X) : Bool { + switch x { + case null { true }; + case (?_) { false }; + }; + }; + + // XXX: until AST-42: + func assertIsNull(x : ?X) { + label profile_trie_assertIsNull + switch x { + case null { assert(true) }; + case (?_) { assert(false) }; + }; + }; + + // XXX: until AST-42: + func makeEmpty() : Trie + = null; + + // XXX: until AST-42: + func assertIsEmpty(t : Trie) { + switch t { + case null { assert(true) }; + case (?_) { assert(false) }; + }; + }; + + // XXX: until AST-42: + func makeBin(l:Trie, r:Trie) : Trie { + ?(new {left=l; right=r; keyvals=null; }) + }; + + // XXX: until AST-42: + func isBin(t:Trie) : Bool { + switch t { + case null { false }; + case (?t_) { + switch (t_.keyvals) { + case null { true }; + case _ { false }; + }; + }; + } + }; + + // XXX: until AST-42: + func makeLeaf(kvs:AssocList,V>) : Trie { + ?(new {left=null; right=null; keyvals=kvs }) + }; + + // XXX: until AST-42: + func matchLeaf(t:Trie) : ?AssocList,V> { + switch t { + case null { null }; + case (?t_) { + switch (t_.keyvals) { + case (?keyvals) ?(?(keyvals)); + case (_) null; + } + }; + } + }; + + // XXX: until AST-42: + func isLeaf(t:Trie) : Bool { + switch t { + case null { false }; + case (?t_) { + switch (t_.keyvals) { + case null { false }; + case _ { true }; + } + }; + } + }; + // XXX: until AST-42: + func assertIsBin(t : Trie) { + switch t { + case null { assert(false) }; + case (?n) { + assertIsNull<((Key,V),AssocList,V>)>(n.keyvals); + }; + } + }; + + // XXX: until AST-42: + func getLeafKey(t : Node) : Key { + assertIsNull>(t.left); + assertIsNull>(t.right); + switch (t.keyvals) { + case (?((k,v),_)) { k }; + case (null) { /* ERROR */ getLeafKey(t) }; + } + }; + + // XXX: this helper is an ugly hack; we need real sum types to avoid it, I think: + func getLeafVal(t : Node) : V { + assertIsNull>(t.left); + assertIsNull>(t.right); + switch (t.keyvals) { + case (?((k,v),_)) { v }; + case null { /* ERROR */ getLeafVal(t) }; + } + }; + + + /** + More helpers + ============================== + */ + + + /** + `buildNewPath` + --------------- + helper function for constructing new paths of uniform length + */ + + func buildNewPath(bitpos:Nat, k:Key, ov:?V) : Trie { + func rec(bitpos:Nat) : Trie { + if ( bitpos < HASH_BITS ) { + // create new bin node for this bit of the hash + let path = rec(bitpos+1); + let bit = Hash.getHashBit(k.hash, bitpos); + if (not bit) { + ?(new {left=path; right=null; keyvals=null}) + } + else { + ?(new {left=null; right=path; keyvals=null}) + } + } else { + // create new leaf for (k,v) pair, if the value is non-null: + switch ov { + case null { ?(new {left=null; right=null; keyvals=null }) }; + case (?v) { ?(new {left=null; right=null; keyvals=?((k,v),null) }) }; + } + } + }; + rec(bitpos) + }; + +//}; + + +/** + +Future work +============= + +Tests +--------- +more regression tests for everything documented in the [module interface](#module-interface). + + +Variant types +------------------------ +See [AST-42]() (sum types); we want this type definition instead: + + ``` + // Use a sum type (AST-42) + type Trie = { #leaf : LeafNode; #bin : BinNode; #empty }; + type BinNode = { left:Trie; right:Trie }; + type LeafNode = { key:K; val:V }; + ``` + +Adaptive path lengths +---------------------- + +Currently we assume a uniform path length. This can be inefficient, +and requires careful tuning. In the future, we could adapt the path +length of each subtree to its cardinality; this wouild avoid +needlessly long paths, or paths that are too short for their subtree's +size. + +Iterator objects +------------------- +for use in 'for ... in ...' patterns + +*/ +*/ From 37a024ef0ea1a8b9387e10bc4ed76e87fe6b4b4a Mon Sep 17 00:00:00 2001 From: Paul Young Date: Thu, 23 May 2019 14:36:25 -0700 Subject: [PATCH 0077/1176] Update case --- src/languageServer.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/languageServer.ml b/src/languageServer.ml index ccae4bb9b44..932decce29d 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -39,7 +39,7 @@ let diagnostics_of_message (msg: Diag.message): Lsp_t.diagnostic = Lsp_t. { diagnostic_range = range_of_region msg.Diag.at ; diagnostic_severity = Some (match msg.Diag.sev with Diag.Error -> 1 | Diag.Warning -> 2) ; diagnostic_code = None - ; diagnostic_source = Some "actorscript" + ; diagnostic_source = Some "ActorScript" ; diagnostic_message = msg.Diag.text ; diagnostic_relatedInformation = None } From 16e73e62e5381e789e60fd9ad1b829ffa8e4a1b0 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 23 May 2019 14:53:27 -0700 Subject: [PATCH 0078/1176] new trie design; use variants for datatype --- stdlib/trie2.as | 87 +++++++++++++++++++++---------------------------- 1 file changed, 38 insertions(+), 49 deletions(-) diff --git a/stdlib/trie2.as b/stdlib/trie2.as index 35bd9693d0d..5adf2d89689 100644 --- a/stdlib/trie2.as +++ b/stdlib/trie2.as @@ -234,7 +234,6 @@ type Trie3D = Trie >; rec(0, tl, tr) }; -/* /** `mergeDisjoint` ---------------- @@ -244,58 +243,48 @@ type Trie3D = Trie >; */ func mergeDisjoint(tl:Trie, tr:Trie, k_eq:(K,K)->Bool): Trie { let key_eq = keyEq(k_eq); - func rec(tl:Trie, tr:Trie) : Trie { + func rec(bitpos:Nat, tl:Trie, tr:Trie) : Trie { switch (tl, tr) { - case (null, _) { return tr }; - case (_, null) { return tl }; - case (?nl,?nr) { - switch (isBin(tl), - isBin(tr)) { - case (true, true) { - let t0 = rec(nl.left, nr.left); - let t1 = rec(nl.right, nr.right); - makeBin(t0, t1) - }; - case (false, true) { - assert(false); - // XXX impossible, until we lift uniform depth assumption - tr - }; - case (true, false) { - assert(false); - // XXX impossible, until we lift uniform depth assumption - tr - }; - case (false, false) { - /// handle hash collisions by using the association list: - makeLeaf( - AssocList.disj,V,V,V>( - nl.keyvals, nr.keyvals, - key_eq, - func (x:?V, y:?V):V = { - switch (x, y) { - case (null, null) { - /* IMPOSSIBLE case. */ - assert false; func x():V=x(); x() - }; - case (?_, ?_) { - /* INVALID case: left and right defined for the same key */ - assert false; func x():V=x(); x() - }; - case (null, ?v) v; - case (?v, null) v; - }} - )) - }; - } - }; + case (#empty, _) { return tr }; + case (_, #empty) { return tl }; + case (#leaf as, #leaf bs) { + #leaf( + AssocList.disj,V,V,V>( + as, bs, + key_eq, + func (x:?V, y:?V):V = { + switch (x, y) { + case (null, null) { + /* IMPOSSIBLE case. */ + P.unreachable() + }; + case (?_, ?_) { + /* INVALID case: left and right defined for the same key */ + assert false; + P.unreachable() + }; + case (null, ?v) v; + case (?v, null) v; + }} + ) + ) + }; + case (#leaf al, _) { + let (l,r) = splitAssocList(al, bitpos); + rec(bitpos, #branch(#leaf l, #leaf r), tr) + }; + case (_, #leaf al) { + let (l,r) = splitAssocList(al, bitpos); + rec(bitpos, tl, #branch(#leaf l, #leaf r)) + }; + case (#branch (ll, lr), #branch(rl, rr)) { + #branch(rec(bitpos + 1, ll, rl), + rec(bitpos + 1, lr, rr)) + }; } }; - rec(tl, tr) + rec(0, tl, tr) }; -*/ - - From 66370fe88113d3fd3a49f89aa289d749c1c8bb0e Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 23 May 2019 15:30:55 -0700 Subject: [PATCH 0079/1176] tries: diff --- stdlib/trie2.as | 67 +++++++++++++++++++++---------------------------- 1 file changed, 29 insertions(+), 38 deletions(-) diff --git a/stdlib/trie2.as b/stdlib/trie2.as index 5adf2d89689..13c5b12292f 100644 --- a/stdlib/trie2.as +++ b/stdlib/trie2.as @@ -286,53 +286,44 @@ type Trie3D = Trie >; rec(0, tl, tr) }; - - -/* - /** + /** `diff` ------ The key-value pairs of the final trie consists of those pairs of the left trie whose keys are not present in the right trie; the values of the right trie are irrelevant. */ - func diff(tl:Trie, tr:Trie, k_eq:(K,K)->Bool) : Trie { + func diff(tl:Trie, tr:Trie, k_eq:(K,K)->Bool): Trie { let key_eq = keyEq(k_eq); - func rec(tl:Trie, tr:Trie) : Trie { + func rec(bitpos:Nat, tl:Trie, tr:Trie) : Trie { switch (tl, tr) { - case (null, _) { return makeEmpty() }; - case (_, null) { return tl }; - case (?nl,?nr) { - switch (isBin(tl), - isBin(tr)) { - case (true, true) { - let t0 = rec(nl.left, nr.left); - let t1 = rec(nl.right, nr.right); - makeBin(t0, t1) - }; - case (false, true) { - assert false; - // XXX impossible, until we lift uniform depth assumption - tl - }; - case (true, false) { - assert false; - // XXX impossible, until we lift uniform depth assumption - tl - }; - case (false, false) { - assert(isLeaf(tl)); - assert(isLeaf(tr)); - makeLeaf( - AssocList.diff,V,W>(nl.keyvals, nr.keyvals, key_eq) - ) - }; - } - }; - }}; - rec(tl, tr) + case (#empty, _) { return #empty }; + case (_, #empty) { return tl }; + case (#leaf as, #leaf bs) { + #leaf( + AssocList.diff,V,W>( + as, bs, + key_eq, + ) + ) + }; + case (#leaf al, _) { + let (l,r) = splitAssocList(al, bitpos); + rec(bitpos, #branch(#leaf l, #leaf r), tr) + }; + case (_, #leaf al) { + let (l,r) = splitAssocList(al, bitpos); + rec(bitpos, tl, #branch(#leaf l, #leaf r)) + }; + case (#branch (ll, lr), #branch(rl, rr)) { + #branch(rec(bitpos + 1, ll, rl), + rec(bitpos + 1, lr, rr)) + }; + } + }; + rec(0, tl, tr) }; -*/ + /* /** From 4db984266336a5ad473429b862ddf73e529dcb05 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 23 May 2019 15:40:42 -0700 Subject: [PATCH 0080/1176] tries: disj --- stdlib/trie2.as | 92 ++++++++++++++++++++++--------------------------- 1 file changed, 41 insertions(+), 51 deletions(-) diff --git a/stdlib/trie2.as b/stdlib/trie2.as index 13c5b12292f..0caaf52940b 100644 --- a/stdlib/trie2.as +++ b/stdlib/trie2.as @@ -325,7 +325,6 @@ type Trie3D = Trie >; }; -/* /** `disj` -------- @@ -349,68 +348,59 @@ type Trie3D = Trie >; - [`prod`](#prod) */ - func disj(tl:Trie, tr:Trie, - k_eq:(K,K)->Bool, vbin:(?V,?W)->X) + func disj( + tl : Trie, + tr : Trie, + k_eq : (K,K)->Bool, + vbin : (?V,?W)->X + ) : Trie { let key_eq = keyEq(k_eq); func recL(t:Trie) : Trie { switch t { - case (null) null; - case (? n) { - switch (matchLeaf(t)) { - case (?_) { makeLeaf(AssocList.disj,V,W,X>(n.keyvals, null, key_eq, vbin)) }; - case _ { makeBin(recL(n.left), recL(n.right)) } - } + case (#empty) #empty; + case (#leaf as) { + #leaf(AssocList.disj,V,W,X>(as, null, key_eq, vbin)) }; - }}; + case (#branch(l,r)) { #branch(recL(l),recL(r)) }; + } + }; func recR(t:Trie) : Trie { switch t { - case (null) null; - case (? n) { - switch (matchLeaf(t)) { - case (?_) { makeLeaf(AssocList.disj,V,W,X>(null, n.keyvals, key_eq, vbin)) }; - case _ { makeBin(recR(n.left), recR(n.right)) } - } + case (#empty) #empty; + case (#leaf as) { + #leaf(AssocList.disj,V,W,X>(null, as, key_eq, vbin)) }; - }}; - func rec(tl:Trie, tr:Trie) : Trie { + case (#branch(l,r)) { #branch(recR(l),recR(r)) }; + } + }; + func rec(bitpos:Nat, tl:Trie, tr:Trie) : Trie { switch (tl, tr) { - // empty-empty terminates early, all other cases do not. - case (null, null) { makeEmpty() }; - case (null, _ ) { recR(tr) }; - case (_, null) { recL(tl) }; - case (? nl, ? nr) { - switch (isBin(tl), - isBin(tr)) { - case (true, true) { - let t0 = rec(nl.left, nr.left); - let t1 = rec(nl.right, nr.right); - makeBin(t0, t1) - }; - case (false, true) { - assert false; - // XXX impossible, until we lift uniform depth assumption - makeEmpty() - }; - case (true, false) { - assert false; - // XXX impossible, until we lift uniform depth assumption - makeEmpty() - }; - case (false, false) { - assert(isLeaf(tl)); - assert(isLeaf(tr)); - makeLeaf( - AssocList.disj,V,W,X>(nl.keyvals, nr.keyvals, key_eq, vbin) - ) - }; - } + case (#empty, #empty) { #empty }; + case (#empty, _ ) { recR(tr) }; + case (_, #empty) { recL(tl) }; + case (#leaf as, #leaf bs) { + #leaf(AssocList.disj,V,W,X>(as, bs, key_eq, vbin)) }; - }}; - rec(tl, tr) + case (#leaf al, _) { + let (l,r) = splitAssocList(al, bitpos); + rec(bitpos, #branch(#leaf l, #leaf r), tr) + }; + case (_, #leaf al) { + let (l,r) = splitAssocList(al, bitpos); + rec(bitpos, tl, #branch(#leaf l, #leaf r)) + }; + case (#branch (ll, lr), #branch(rl, rr)) { + #branch(rec(bitpos + 1, ll, rl), + rec(bitpos + 1, lr, rr)) + }; + } + }; + rec(0, tl, tr) }; -*/ + + /* /** From fcdd7815aca6196491b92e835ffd0825f72797cb Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 23 May 2019 16:06:53 -0700 Subject: [PATCH 0081/1176] tries: implement old interface with variants-based ADT def --- stdlib/trie2.as | 522 ++++++++++++++---------------------------------- 1 file changed, 145 insertions(+), 377 deletions(-) diff --git a/stdlib/trie2.as b/stdlib/trie2.as index 0caaf52940b..69fea722397 100644 --- a/stdlib/trie2.as +++ b/stdlib/trie2.as @@ -136,6 +136,15 @@ type Trie3D = Trie >; rec(t, 0) }; + /** + `insert` + ------------ + insert the given key's value in the trie; return the new trie, and the previous value associated with the key, if any + */ + func insert(t : Trie, k:Key, k_eq:(K,K)->Bool, v:V) : (Trie, ?V) { + replace(t, k, k_eq, ?v) + }; + /** `find` --------- @@ -399,10 +408,8 @@ type Trie3D = Trie >; }; rec(0, tl, tr) }; - - + -/* /** `join` --------- @@ -425,46 +432,58 @@ type Trie3D = Trie >; : Trie { let key_eq = keyEq(k_eq); - func rec(tl:Trie, tr:Trie) : Trie { + func rec(bitpos:Nat, tl:Trie, tr:Trie) : Trie { switch (tl, tr) { - case (null, null) { return makeEmpty() }; - case (null, ? nr) { return makeEmpty() }; - case (? nl, null) { return makeEmpty() }; - case (? nl, ? nr) { - switch (isBin(tl), - isBin(tr)) { - case (true, true) { - let t0 = rec(nl.left, nr.left); - let t1 = rec(nl.right, nr.right); - makeBin(t0, t1) - }; - case (false, true) { - assert false; - // XXX impossible, until we lift uniform depth assumption - makeEmpty() - }; - case (true, false) { - assert false; - // XXX impossible, until we lift uniform depth assumption - makeEmpty() - }; - case (false, false) { - assert(isLeaf(tl)); - assert(isLeaf(tr)); - makeLeaf( - AssocList.join,V,W,X>(nl.keyvals, nr.keyvals, key_eq, vbin) - ) - }; - } - } - }}; - rec(tl, tr) + case (#empty, _) { #empty }; + case (_, #empty) { #empty }; + case (#leaf as, #leaf bs) { + #leaf(AssocList.join,V,W,X>(as, bs, key_eq, vbin)) + }; + case (#leaf al, _) { + let (l,r) = splitAssocList(al, bitpos); + rec(bitpos, #branch(#leaf l, #leaf r), tr) + }; + case (_, #leaf al) { + let (l,r) = splitAssocList(al, bitpos); + rec(bitpos, tl, #branch(#leaf l, #leaf r)) + }; + case (#branch (ll, lr), #branch(rl, rr)) { + #branch(rec(bitpos + 1, ll, rl), + rec(bitpos + 1, lr, rr)) + }; + } + }; + rec(0, tl, tr) }; -*/ -/* + /** + `foldUp` + ------------ + This operation gives a recursor for the internal structure of + tries. Many common operations are instantiations of this function, + either as clients, or as hand-specialized versions (e.g., see map, + mapFilter, exists and forAll below). + */ + func foldUp(t:Trie, bin:(X,X)->X, leaf:(K,V)->X, empty:X) : X { + func rec(t:Trie) : X { + switch t { + case (#empty) { empty }; + case (#leaf al) { + AssocList.fold,V,X>( + al, empty, + func (k:Key, v:V, x:X):X = + bin(leaf(k.key,v),x) + ) + }; + case (#branch(l,r)) { bin(rec(l), rec(r)) }; + } + }; + rec(t) + }; + + /** `prod` --------- @@ -504,46 +523,16 @@ type Trie3D = Trie >; tr, merge, func (k2:K2, v2:V2) : Trie { switch (op(k1, v1, k2, v2)) { - case null null; - case (?(k3, v3)) { (insert(null, k3, k3_eq, v3)).0 }; + case null #empty; + case (?(k3, v3)) { (insert(#empty, k3, k3_eq, v3)).0 }; } }, - null + #empty ) }, - null + #empty ) }; -*/ - -/* - /** - `foldUp` - ------------ - This operation gives a recursor for the internal structure of - tries. Many common operations are instantiations of this function, - either as clients, or as hand-specialized versions (e.g., see map, - mapFilter, exists and forAll below). - */ - func foldUp(t:Trie, bin:(X,X)->X, leaf:(K,V)->X, empty:X) : X { - func rec(t:Trie) : X { - switch t { - case (null) { empty }; - case (?n) { - switch (matchLeaf(t)) { - case (?kvs) { - AssocList.fold,V,X>( - kvs, empty, - func (k:Key, v:V, x:X):X = - bin(leaf(k.key,v),x) - ) - }; - case null { bin(rec(n.left), rec(n.right)) }; - } - }; - }}; - rec(t) - }; /** `fold` @@ -554,22 +543,20 @@ type Trie3D = Trie >; func fold(t:Trie, f:(K,V,X)->X, x:X) : X { func rec(t:Trie, x:X) : X { switch t { - case (null) x; - case (?n) { - switch (matchLeaf(t)) { - case (?kvs) { - AssocList.fold,V,X>( - kvs, x, - func (k:Key, v:V, x:X):X = f(k.key,v,x) - ) - }; - case null { rec(n.left,rec(n.right,x)) }; - } + case (#empty) x; + case (#leaf al) { + AssocList.fold,V,X>( + al, x, + func (k:Key, v:V, x:X):X = f(k.key,v,x) + ) }; - }}; + case (#branch(l,r)) { rec(l,rec(r,x)) }; + }; + }; rec(t, x) }; + /** `exists` -------- @@ -578,22 +565,18 @@ type Trie3D = Trie >; func exists(t:Trie, f:(K,V)->Bool) : Bool { func rec(t:Trie) : Bool { switch t { - case (null) { false }; - case (?n) { - switch (matchLeaf(t)) { - case (?kvs) { - List.exists<(Key,V)>( - kvs, func ((k:Key,v:V)):Bool=f(k.key,v) - ) - }; - case null { rec(n.left) or rec(n.right) }; - } + case (#empty) { false }; + case (#leaf al) { + List.exists<(Key,V)>( + al, func ((k:Key,v:V)):Bool=f(k.key,v) + ) }; - }}; + case (#branch(l,r)) { rec(l) or rec(r) }; + }; + }; rec(t) }; - /** `forAll` --------- @@ -602,18 +585,15 @@ type Trie3D = Trie >; func forAll(t:Trie, f:(K,V)->Bool) : Bool { func rec(t:Trie) : Bool { switch t { - case (null) { true }; - case (?n) { - switch (matchLeaf(t)) { - case (?kvs) { - List.all<(Key,V)>( - kvs, func ((k:Key,v:V)):Bool=f(k.key,v) - ) - }; - case null { rec(n.left) and rec(n.right) }; - } + case (#empty) { true }; + case (#leaf al) { + List.all<(Key,V)>( + al, func ((k:Key,v:V)):Bool=f(k.key,v) + ) }; - }}; + case (#branch(l,r)) { rec(l) and rec(r) }; + }; + }; rec(t) }; @@ -669,18 +649,15 @@ type Trie3D = Trie >; func isEmpty(t:Trie) : Bool { func rec(t:Trie) : Bool { switch t { - case (null) { true }; - case (?n) { - switch (matchLeaf(t)) { - case (?kvs) { List.isNil<(Key,V)>(kvs) }; - case null { rec(n.left) and rec(n.right) }; - } - }; - } + case (#empty) { true }; + case (#leaf al) { List.isNil<(Key,V)>(al) }; + case (#branch(l,r)) { rec(l) and rec(r) }; + }; }; rec(t) }; + /** `filter` ----------- @@ -689,27 +666,21 @@ type Trie3D = Trie >; func filter(t:Trie, f:(K,V)->Bool) : Trie { func rec(t:Trie) : Trie { switch t { - case (null) { null }; - case (?n) { - switch (matchLeaf(t)) { - case (?kvs) { - makeLeaf( - List.filter<(Key,V)>(kvs, func ((k:Key,v:V)):Bool = f(k.key,v)) - ) - }; - case null { - let l = rec(n.left); - let r = rec(n.right); - switch (isEmpty(l), - isEmpty(r)) { - case (true, true) null; - case (false, true) r; - case (true, false) l; - case (false, false) makeBin(l, r); - } - }; - } - }; + case (#empty) { #empty }; + case (#leaf al) { + #leaf(List.filter<(Key,V)>(al, func ((k:Key,v:V)):Bool = f(k.key,v))) + }; + case (#branch(l,r)) { + let fl = rec(l); + let fr = rec(r); + switch (isEmpty(fl), + isEmpty(fr)) { + case (true, true) #empty; + case (false, true) fr; + case (true, false) fl; + case (false, false) #branch(fl, fr); + }; + } } }; rec(t) @@ -718,39 +689,35 @@ type Trie3D = Trie >; /** `mapFilter` ----------- - map and filter the key-value pairs by a given partial mapping function. + map and filter the key-value pairs by a given predicate. */ func mapFilter(t:Trie, f:(K,V)->?W) : Trie { func rec(t:Trie) : Trie { switch t { - case (null) { null }; - case (?n) { - switch (matchLeaf(t)) { - case (?kvs) { - makeLeaf( - List.mapFilter<(Key,V),(Key,W)> - (kvs, + case (#empty) { #empty }; + case (#leaf al) { + #leaf(List.mapFilter<(Key,V),(Key,W)>( + al, // retain key and hash, but update key's value using f: func ((k:Key,v:V)):?(Key,W) = { switch (f(k.key,v)) { case (null) null; case (?w) (?(new {key=k.key; hash=k.hash}, w)); }} - )) - }; - case null { - let l = rec(n.left); - let r = rec(n.right); - switch (isEmpty(l), - isEmpty(r)) { - case (true, true) null; - case (false, true) r; - case (true, false) l; - case (false, false) makeBin(l, r); - } - }; - } - }; + ) + ) + }; + case (#branch(l,r)) { + let fl = rec(l); + let fr = rec(r); + switch (isEmpty(fl), + isEmpty(fr)) { + case (true, true) #empty; + case (false, true) fr; + case (true, false) fl; + case (false, false) #branch(fl, fr); + }; + } } }; rec(t) @@ -776,40 +743,24 @@ type Trie3D = Trie >; ) : Bool { func rec(tl:Trie, tr:Trie) : Bool { switch (tl, tr) { - case (null, null) { true }; - case (_, null) { false }; - case (null, _) { false }; - case (?nl, ?nr) { - switch (matchLeaf(tl), - matchLeaf(tr)) { - case (null, null) { - rec(nl.left, nr.left) - and rec(nl.right, nr.right) - }; - case (null, _) { false }; - case (_, null) { false }; - case (?kvs1, ?kvs2) { - List.isEq<(Key,V)> - (kvs1, kvs2, - func ((k1:Key, v1:V), (k2:Key, v2:V)) : Bool = - keq(k1.key, k2.key) and veq(v1,v2) - ) - }; - } + case (#empty, #empty) { true }; + case (#leaf as, #leaf bs) { + List.isEq<(Key,V)> + (as, bs, + func ((k1:Key, v1:V), (k2:Key, v2:V)) : Bool = + keq(k1.key, k2.key) and veq(v1,v2) + ) + }; + case (#branch(ll,lr),#branch(rl,rr)) { + rec(ll,rl) and rec(lr,rr) }; - }}; - rec(tl, tr) + case _ { false }; + } + }; + rec(tl,tr) }; - - - - - /** - - ------------------------------------------------------------------------------------------------- - `replaceThen` ------------ replace the given key's value in the trie, @@ -828,15 +779,6 @@ type Trie3D = Trie >; } }; - /** - `insert` - ------------ - insert the given key's value in the trie; return the new trie, and the previous value associated with the key, if any - */ - func insert(t : Trie, k:Key, k_eq:(K,K)->Bool, v:V) : (Trie, ?V) { - replace(t, k, k_eq, ?v) - }; - /** `insertFresh` ---------------- @@ -864,7 +806,7 @@ type Trie3D = Trie >; { let inner = find>(t, k1, k1_eq); let (updated_inner, _) = switch inner { - case (null) { insert(null, k2, k2_eq, v) }; + case (null) { insert(#empty, k2, k2_eq, v) }; case (?inner) { insert(inner, k2, k2_eq, v) }; }; let (updated_outer, _) = { insert>(t, k1, k1_eq, updated_inner) }; @@ -889,14 +831,14 @@ type Trie3D = Trie >; let (updated_inner1, _) = switch inner1 { case (null) { insert>( - null, k2, k2_eq, - (insert(null, k3, k3_eq, v)).0 + #empty, k2, k2_eq, + (insert(#empty, k3, k3_eq, v)).0 ) }; case (?inner1) { let inner2 = find>(inner1, k2, k2_eq); let (updated_inner2, _) = switch inner2 { - case (null) { insert(null, k3, k3_eq, v) }; + case (null) { insert(#empty, k3, k3_eq, v) }; case (?inner2) { insert(inner2, k3, k3_eq, v) }; }; insert>( inner1, k2, k2_eq, updated_inner2 ) @@ -1006,167 +948,10 @@ type Trie3D = Trie >; ( t, func (t1:Trie, t2:Trie):Trie { mergeDisjoint(t1, t2, k2_eq) }, func (_:K1, t:Trie): Trie { t }, - null ) - }; - - // Equality function for two `Key`s, in terms of equaltiy of `K`'s. - func keyEq(keq:(K,K) -> Bool) : ((Key,Key) -> Bool) = { - func (key1:Key, key2:Key) : Bool = - label profile_trie_keyEq : Bool - (Hash.hashEq(key1.hash, key2.hash) and keq(key1.key, key2.key)) - }; - - /** - Helpers for missing variants - ============================== - Until ActorScript has variant types, we need various helper functions here. They are uninteresting. - */ - // @Omit: - - // XXX: until AST-42: - func isNull(x : ?X) : Bool { - switch x { - case null { true }; - case (?_) { false }; - }; - }; - - // XXX: until AST-42: - func assertIsNull(x : ?X) { - label profile_trie_assertIsNull - switch x { - case null { assert(true) }; - case (?_) { assert(false) }; - }; - }; - - // XXX: until AST-42: - func makeEmpty() : Trie - = null; - - // XXX: until AST-42: - func assertIsEmpty(t : Trie) { - switch t { - case null { assert(true) }; - case (?_) { assert(false) }; - }; + #empty ) }; - // XXX: until AST-42: - func makeBin(l:Trie, r:Trie) : Trie { - ?(new {left=l; right=r; keyvals=null; }) - }; - // XXX: until AST-42: - func isBin(t:Trie) : Bool { - switch t { - case null { false }; - case (?t_) { - switch (t_.keyvals) { - case null { true }; - case _ { false }; - }; - }; - } - }; - - // XXX: until AST-42: - func makeLeaf(kvs:AssocList,V>) : Trie { - ?(new {left=null; right=null; keyvals=kvs }) - }; - - // XXX: until AST-42: - func matchLeaf(t:Trie) : ?AssocList,V> { - switch t { - case null { null }; - case (?t_) { - switch (t_.keyvals) { - case (?keyvals) ?(?(keyvals)); - case (_) null; - } - }; - } - }; - - // XXX: until AST-42: - func isLeaf(t:Trie) : Bool { - switch t { - case null { false }; - case (?t_) { - switch (t_.keyvals) { - case null { false }; - case _ { true }; - } - }; - } - }; - // XXX: until AST-42: - func assertIsBin(t : Trie) { - switch t { - case null { assert(false) }; - case (?n) { - assertIsNull<((Key,V),AssocList,V>)>(n.keyvals); - }; - } - }; - - // XXX: until AST-42: - func getLeafKey(t : Node) : Key { - assertIsNull>(t.left); - assertIsNull>(t.right); - switch (t.keyvals) { - case (?((k,v),_)) { k }; - case (null) { /* ERROR */ getLeafKey(t) }; - } - }; - - // XXX: this helper is an ugly hack; we need real sum types to avoid it, I think: - func getLeafVal(t : Node) : V { - assertIsNull>(t.left); - assertIsNull>(t.right); - switch (t.keyvals) { - case (?((k,v),_)) { v }; - case null { /* ERROR */ getLeafVal(t) }; - } - }; - - - /** - More helpers - ============================== - */ - - - /** - `buildNewPath` - --------------- - helper function for constructing new paths of uniform length - */ - - func buildNewPath(bitpos:Nat, k:Key, ov:?V) : Trie { - func rec(bitpos:Nat) : Trie { - if ( bitpos < HASH_BITS ) { - // create new bin node for this bit of the hash - let path = rec(bitpos+1); - let bit = Hash.getHashBit(k.hash, bitpos); - if (not bit) { - ?(new {left=path; right=null; keyvals=null}) - } - else { - ?(new {left=null; right=path; keyvals=null}) - } - } else { - // create new leaf for (k,v) pair, if the value is non-null: - switch ov { - case null { ?(new {left=null; right=null; keyvals=null }) }; - case (?v) { ?(new {left=null; right=null; keyvals=?((k,v),null) }) }; - } - } - }; - rec(bitpos) - }; - -//}; /** @@ -1174,22 +959,6 @@ type Trie3D = Trie >; Future work ============= -Tests ---------- -more regression tests for everything documented in the [module interface](#module-interface). - - -Variant types ------------------------- -See [AST-42]() (sum types); we want this type definition instead: - - ``` - // Use a sum type (AST-42) - type Trie = { #leaf : LeafNode; #bin : BinNode; #empty }; - type BinNode = { left:Trie; right:Trie }; - type LeafNode = { key:K; val:V }; - ``` - Adaptive path lengths ---------------------- @@ -1204,4 +973,3 @@ Iterator objects for use in 'for ... in ...' patterns */ -*/ From 58817a427e2353cf4f036811baa98cbb6aa056b6 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Thu, 23 May 2019 16:32:34 -0700 Subject: [PATCH 0082/1176] Use a variant for diag severity, add lsp subdir --- default.nix | 8 +------- src/_tags | 1 + src/languageServer.ml | 28 ++++++++++++++++++++++++---- src/lsp.atd | 14 ++++---------- src/lsp.mli | 7 ------- src/{lsp.ml => lsp/atdAdapters.ml} | 15 --------------- src/lsp/atdAdapters.mli | 2 ++ src/lsp/diagnosticSeverity.ml | 22 ++++++++++++++++++++++ src/lsp/diagnosticSeverity.mli | 9 +++++++++ 9 files changed, 63 insertions(+), 43 deletions(-) delete mode 100644 src/lsp.mli rename src/{lsp.ml => lsp/atdAdapters.ml} (53%) create mode 100644 src/lsp/atdAdapters.mli create mode 100644 src/lsp/diagnosticSeverity.ml create mode 100644 src/lsp/diagnosticSeverity.mli diff --git a/default.nix b/default.nix index 313a7c5ea21..bd0fdcb6860 100644 --- a/default.nix +++ b/default.nix @@ -150,14 +150,8 @@ rec { name = "asc-bin"; src = sourceByRegex ./. [ - "src/" + "src\/(lsp)?(.*\.(atd|ml|mli|mll|mlpack|mly))?$" "src/Makefile.*" - "src/.*.atd" - "src/.*.ml" - "src/.*.mli" - "src/.*.mly" - "src/.*.mll" - "src/.*.mlpack" "src/_tags" "test/" "test/node-test.js" diff --git a/src/_tags b/src/_tags index b8a23322447..854df40a381 100644 --- a/src/_tags +++ b/src/_tags @@ -1 +1,2 @@ <**/*>: coverage +: for-pack(Lsp) diff --git a/src/languageServer.ml b/src/languageServer.ml index 932decce29d..df057dd603f 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -1,3 +1,23 @@ +(* Ideally the following functions would be in the `Lsp` module, but doing so + creates a circular dependency with the `Lsp_t` module generated by ATD. +*) + +let jsonrpc_version : string = "2.0" + +let notification (params : Lsp_t.notification_message_params) : Lsp_t.notification_message = Lsp_t. + { notification_message_jsonrpc = jsonrpc_version + ; notification_message_params = params + } + +let response_result_message (id : int) (result : Lsp_t.response_result) : Lsp_t.response_message = Lsp_t. + { response_message_jsonrpc = jsonrpc_version + ; response_message_id = id + ; response_message_result = Some result + } + +(* let response_error_message (id : int) (error : Lsp_t.response_error) : Lsp_t.response_message = *) + + let oc: out_channel = open_out_gen [Open_append; Open_creat] 0o666 "ls.log" let log_to_file (lbl: string) (txt: string): unit = Printf.fprintf oc "[%s] %s\n" lbl txt; @@ -21,7 +41,7 @@ let show_message (msg: string): unit = { window_show_message_params_type_ = 3 ; window_show_message_params_message = msg }) in - let notification = Lsp.notification params in + let notification = notification params in send_notification (Lsp_j.string_of_notification_message notification) let position_of_pos (pos: Source.pos): Lsp_t.position = Lsp_t. @@ -49,7 +69,7 @@ let publish_diagnostics (uri: Lsp_t.document_uri) (diags: Lsp_t.diagnostic list) { publish_diagnostics_params_uri = uri ; publish_diagnostics_params_diagnostics = diags }) in - let notification = Lsp.notification params in + let notification = notification params in send_notification (Lsp_j.string_of_notification_message notification) let start () = @@ -87,7 +107,7 @@ let start () = ; server_capabilities_hoverProvider = Some true } }) in - let response = Lsp.response_result_message id result in + let response = response_result_message id result in send_response (Lsp_j.string_of_response_message response); | (Some id, `TextDocumentHover params) -> @@ -98,7 +118,7 @@ let start () = ^ " " ^ string_of_int position.position_line ^ ", " ^ string_of_int position.position_character }) in - let response = Lsp.response_result_message id result in + let response = response_result_message id result in send_response (Lsp_j.string_of_response_message response); | (_, `TextDocumentDidSave params) -> diff --git a/src/lsp.atd b/src/lsp.atd index 32d54a1683c..fdedc4648a5 100644 --- a/src/lsp.atd +++ b/src/lsp.atd @@ -15,7 +15,7 @@ type notification_message = { inherit message ; params : notification_message_params } - + @@ -34,7 +34,7 @@ type incoming_message = ; ?id : int nullable ; params : incoming_message_params } - + (* All tags must also provide params, even if they are an `empty_record` *) @@ -62,7 +62,7 @@ type response_message = ; ?result : response_result nullable (*; ?error : response_error nullable*) } - + type response_result = @@ -255,13 +255,7 @@ type diagnostic = } -(* TODO: figure out how to map these to 1, 2, 3, 4 *) -type diagnostic_severity = - [ Error - | Warning - | Information - | Hint - ] +type diagnostic_severity = int wrap type diagnostic_related_information = { location : location diff --git a/src/lsp.mli b/src/lsp.mli deleted file mode 100644 index 7b382c55d3c..00000000000 --- a/src/lsp.mli +++ /dev/null @@ -1,7 +0,0 @@ -module Message_adapter : Atdgen_runtime.Json_adapter.S -module Response_message_adapter : Atdgen_runtime.Json_adapter.S - -val notification : Lsp_t.notification_message_params -> Lsp_t.notification_message - -val response_result_message : int -> Lsp_t.response_result -> Lsp_t.response_message -(* val response_error_message : int -> Lsp_t.response_error -> Lsp_t.response_message *) diff --git a/src/lsp.ml b/src/lsp/atdAdapters.ml similarity index 53% rename from src/lsp.ml rename to src/lsp/atdAdapters.ml index 45341a15597..a0882a23e54 100644 --- a/src/lsp.ml +++ b/src/lsp/atdAdapters.ml @@ -13,18 +13,3 @@ module Response_message_adapter = Atdgen_runtime.Json_adapter.Type_and_value_fie let known_tags = None end ) - -let jsonrpc_version = "2.0" - -let notification params = Lsp_t. - { notification_message_jsonrpc = jsonrpc_version - ; notification_message_params = params - } - -let response_result_message id result = Lsp_t. - { response_message_jsonrpc = jsonrpc_version - ; response_message_id = id - ; response_message_result = Some result - } - -(* let response_error_message id error = *) diff --git a/src/lsp/atdAdapters.mli b/src/lsp/atdAdapters.mli new file mode 100644 index 00000000000..bd828b6ce31 --- /dev/null +++ b/src/lsp/atdAdapters.mli @@ -0,0 +1,2 @@ +module Message_adapter : Atdgen_runtime.Json_adapter.S +module Response_message_adapter : Atdgen_runtime.Json_adapter.S diff --git a/src/lsp/diagnosticSeverity.ml b/src/lsp/diagnosticSeverity.ml new file mode 100644 index 00000000000..78bb084c03c --- /dev/null +++ b/src/lsp/diagnosticSeverity.ml @@ -0,0 +1,22 @@ +type t + = Error + | Warning + | Information + | Hint + | Unknown + +let wrap : int -> t = +function +| 1 -> Error +| 2 -> Warning +| 3 -> Information +| 4 -> Hint +| _ -> Unknown + +let unwrap : t -> int = +function +| Unknown -> 0 +| Error -> 1 +| Warning -> 2 +| Information -> 3 +| Hint -> 4 diff --git a/src/lsp/diagnosticSeverity.mli b/src/lsp/diagnosticSeverity.mli new file mode 100644 index 00000000000..d08a2c3ae04 --- /dev/null +++ b/src/lsp/diagnosticSeverity.mli @@ -0,0 +1,9 @@ +type t + = Error + | Warning + | Information + | Hint + | Unknown + +val wrap : int -> t +val unwrap : t -> int From b79e7f9084df94c15c4f92440ce21d2e8f2b36f5 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Thu, 23 May 2019 16:42:54 -0700 Subject: [PATCH 0083/1176] Stop ignoring .mlpack files in the src directory --- src/.gitignore | 1 - src/lsp.mlpack | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 src/lsp.mlpack diff --git a/src/.gitignore b/src/.gitignore index d82f8742dc3..ca234c5272a 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -4,7 +4,6 @@ *.byte *.opt *.unopt -*.mlpack as asc asc.js diff --git a/src/lsp.mlpack b/src/lsp.mlpack new file mode 100644 index 00000000000..a32fb7646f6 --- /dev/null +++ b/src/lsp.mlpack @@ -0,0 +1,2 @@ +AtdAdapters +DiagnosticSeverity From 9aa58ad03d74f52b6c6b6b7e23ac693caf5483d1 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Fri, 24 May 2019 10:43:23 -0700 Subject: [PATCH 0084/1176] Actually use DiagnosticSeverity variant --- src/languageServer.ml | 7 ++++++- src/lsp.atd | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/languageServer.ml b/src/languageServer.ml index df057dd603f..89570c85cbb 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -55,9 +55,14 @@ let range_of_region (at: Source.region): Lsp_t.range = Lsp_t. ; range_end_ = position_of_pos at.Source.right } +let severity_of_sev : Diag.severity -> Lsp.DiagnosticSeverity.t = + function + | Diag.Error -> Lsp.DiagnosticSeverity.Error + | Diag.Warning -> Lsp.DiagnosticSeverity.Warning + let diagnostics_of_message (msg: Diag.message): Lsp_t.diagnostic = Lsp_t. { diagnostic_range = range_of_region msg.Diag.at - ; diagnostic_severity = Some (match msg.Diag.sev with Diag.Error -> 1 | Diag.Warning -> 2) + ; diagnostic_severity = Some (severity_of_sev msg.Diag.sev) ; diagnostic_code = None ; diagnostic_source = Some "ActorScript" ; diagnostic_message = msg.Diag.text diff --git a/src/lsp.atd b/src/lsp.atd index fdedc4648a5..e740632ece3 100644 --- a/src/lsp.atd +++ b/src/lsp.atd @@ -247,7 +247,7 @@ type publish_diagnostics_params = type diagnostic = { range : range - ; ?severity : int nullable (* diagnostic_severity *) + ; ?severity : diagnostic_severity nullable ; ?code : int nullable ; ?source : string nullable ; message : string From a3c8f04039a700d7d0510c0b90aa1362ebd225a4 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Fri, 24 May 2019 11:56:43 -0700 Subject: [PATCH 0085/1176] Update TODO --- src/languageServer.ml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/languageServer.ml b/src/languageServer.ml index 89570c85cbb..e2dd81e6e31 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -136,6 +136,10 @@ let start () = false [file_name] in show_message ("Compiling file: " ^ file_name); + (* TODO: it appears that warning messages should also be included in + the OK case, since warnings are not reported if there are no + errors. + *) (* TODO: let msgs = match result with | Error msgs -> msgs | Ok (_, msgs) -> in *) (match result with | Ok _ -> From 26d69be502aac6e14a43d561ec4d1be0bdad67ca Mon Sep 17 00:00:00 2001 From: Paul Young Date: Fri, 24 May 2019 12:03:55 -0700 Subject: [PATCH 0086/1176] Use a variant for message type --- src/languageServer.ml | 13 +++++++------ src/lsp.atd | 4 +++- src/lsp.mlpack | 1 + src/lsp/messageType.ml | 22 ++++++++++++++++++++++ src/lsp/messageType.mli | 9 +++++++++ 5 files changed, 42 insertions(+), 7 deletions(-) create mode 100644 src/lsp/messageType.ml create mode 100644 src/lsp/messageType.mli diff --git a/src/languageServer.ml b/src/languageServer.ml index e2dd81e6e31..39543374fd6 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -34,11 +34,12 @@ let send (label: string) (out: string): unit = let send_response: string -> unit = send "response" let send_notification: string -> unit = send "notification" -let show_message (msg: string): unit = +(* TODO: pass type, use a variant *) +let show_message (typ : Lsp.MessageType.t) (msg: string): unit = let params = `WindowShowMessage (Lsp_t. - { window_show_message_params_type_ = 3 + { window_show_message_params_type_ = typ ; window_show_message_params_message = msg }) in let notification = notification params in @@ -135,7 +136,7 @@ let start () = Pipeline.DfinityMode false [file_name] in - show_message ("Compiling file: " ^ file_name); + show_message Lsp.MessageType.Info ("Compiling file: " ^ file_name); (* TODO: it appears that warning messages should also be included in the OK case, since warnings are not reported if there are no errors. @@ -145,7 +146,7 @@ let start () = | Ok _ -> (* It's our responsibility to clear any existing diagnostics *) publish_diagnostics uri []; - show_message "Compilation successful" + show_message Lsp.MessageType.Info "Compilation successful" | Error msgs -> (Base.Option.iter !client_capabilities ~f:(fun capabilities -> (* TODO: determine if the client accepts diagnostics with related info *) @@ -154,7 +155,7 @@ let start () = let diags = List.map diagnostics_of_message msgs in publish_diagnostics uri diags; )); - show_message + show_message Lsp.MessageType.Error ("Compilation failed with " ^ String.concat " " @@ -168,7 +169,7 @@ let start () = (* Notification messages *) | (None, `Initialized _) -> - show_message "Language server initialized" + show_message Lsp.MessageType.Info "Language server initialized" (* Unhandled messages *) diff --git a/src/lsp.atd b/src/lsp.atd index e740632ece3..a479c132706 100644 --- a/src/lsp.atd +++ b/src/lsp.atd @@ -266,11 +266,13 @@ type diagnostic_related_information = (* "window/showMessage" notification *) type window_show_message_params = - { type_ : int + { type_ : message_type ; message : string } +type message_type = int wrap + (* Helpers *) diff --git a/src/lsp.mlpack b/src/lsp.mlpack index a32fb7646f6..de44a4d2755 100644 --- a/src/lsp.mlpack +++ b/src/lsp.mlpack @@ -1,2 +1,3 @@ AtdAdapters DiagnosticSeverity +MessageType diff --git a/src/lsp/messageType.ml b/src/lsp/messageType.ml new file mode 100644 index 00000000000..6221305660a --- /dev/null +++ b/src/lsp/messageType.ml @@ -0,0 +1,22 @@ +type t + = Error + | Warning + | Info + | Log + | Unknown + +let wrap : int -> t = +function +| 1 -> Error +| 2 -> Warning +| 3 -> Info +| 4 -> Log +| _ -> Unknown + +let unwrap : t -> int = +function +| Unknown -> 0 +| Error -> 1 +| Warning -> 2 +| Info -> 3 +| Log -> 4 diff --git a/src/lsp/messageType.mli b/src/lsp/messageType.mli new file mode 100644 index 00000000000..508cbaffbeb --- /dev/null +++ b/src/lsp/messageType.mli @@ -0,0 +1,9 @@ +type t + = Error + | Warning + | Info + | Log + | Unknown + +val wrap : int -> t +val unwrap : t -> int From 85deef747d9eee71e97e75687f716f194c69780a Mon Sep 17 00:00:00 2001 From: Paul Young Date: Fri, 24 May 2019 12:39:05 -0700 Subject: [PATCH 0087/1176] Report warnings when compilation succeeds --- src/lib.ml | 7 +++++++ src/lib.mli | 5 +++++ src/main.ml | 4 ++-- src/pipeline.ml | 10 ++++++---- src/pipeline.mli | 2 +- 5 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/lib.ml b/src/lib.ml index 52a5d21aa52..c980c9a65ab 100644 --- a/src/lib.ml +++ b/src/lib.ml @@ -254,3 +254,10 @@ struct let value_opt p = !p let value p = match !p with Some x -> x | None -> raise Promise end + +module Result = +struct + let map f = function + | Ok x -> Ok (f x) + | Error x -> Error x +end diff --git a/src/lib.mli b/src/lib.mli index b414e51e797..e81ff8be584 100644 --- a/src/lib.mli +++ b/src/lib.mli @@ -100,3 +100,8 @@ sig val breakup : string -> int -> string list val find_from_opt : (char -> bool) -> string -> int -> int option end + +module Result : +sig + val map : ('a -> 'c) -> ('a, 'b) result -> ('c, 'b) result +end diff --git a/src/main.ml b/src/main.ml index 513aa5fd473..5c9d88f3c84 100644 --- a/src/main.ml +++ b/src/main.ml @@ -92,8 +92,8 @@ let process_files files : unit = | [n] -> out_file := Filename.remove_extension (Filename.basename n) ^ ".wasm" | ns -> eprintf "asc: no output file specified"; exit 1 end; - let module_ = exit_on_failure - Pipeline.(compile_files !compile_mode !(Flags.link) files) in + let result = Pipeline.(compile_files !compile_mode !(Flags.link) files) in + let module_ = exit_on_failure (Lib.Result.map (fun (module_, _) -> module_) result) in let oc = open_out !out_file in let (source_map, wasm) = CustomModuleEncode.encode module_ in output_string oc wasm; close_out oc; diff --git a/src/pipeline.ml b/src/pipeline.ml index 762e29ac59b..471fe1fc99e 100644 --- a/src/pipeline.ml +++ b/src/pipeline.ml @@ -448,7 +448,7 @@ let load_as_rts () = CustomModuleDecode.decode "rts.wasm" wasm type compile_mode = Compile.mode = WasmMode | DfinityMode -type compile_result = (CustomModule.extended_module, Diag.messages) result +type compile_result = ((CustomModule.extended_module * Diag.messages), Diag.messages) result let name_progs progs = if progs = [] @@ -471,21 +471,23 @@ let compile_prog mode do_link lib_env libraries progs : compile_result = phase "Compiling" name; let rts = if do_link then Some (load_as_rts ()) else None in let module_ = Compile.compile mode name rts prelude_ir [prog_ir] in - Ok module_ + Ok (module_, []) let compile_files mode do_link files : compile_result = match load_progs (parse_files files) initial_stat_env with | Error msgs -> Error msgs | Ok ((libraries, progs, senv), msgs) -> Diag.print_messages msgs; - compile_prog mode do_link senv.Typing.lib_env libraries progs + let result = compile_prog mode do_link senv.Typing.lib_env libraries progs in + Lib.Result.map (fun (module_, _) -> (module_, msgs)) result let compile_string mode s name : compile_result = match load_decl (parse_string s name) initial_stat_env with | Error msgs -> Error msgs | Ok ((libraries, prog, senv, _t, _sscope), msgs) -> Diag.print_messages msgs; - compile_prog mode false senv.Typing.lib_env libraries [prog] + let result = compile_prog mode false senv.Typing.lib_env libraries [prog] in + Lib.Result.map (fun (module_, _) -> (module_, msgs)) result (* Interpretation (IR) *) diff --git a/src/pipeline.mli b/src/pipeline.mli index 0890923f09a..4928ead8e64 100644 --- a/src/pipeline.mli +++ b/src/pipeline.mli @@ -6,6 +6,6 @@ val interpret_ir_files : string list -> unit Diag.result val run_files_and_stdin : string list -> unit Diag.result type compile_mode = WasmMode | DfinityMode -type compile_result = (CustomModule.extended_module, Diag.messages) result +type compile_result = ((CustomModule.extended_module * Diag.messages), Diag.messages) result val compile_string : compile_mode -> string -> string -> compile_result val compile_files : compile_mode -> bool -> string list -> compile_result From f49c8ddc73f434865d5ce6cc768b223976527254 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Fri, 24 May 2019 12:39:31 -0700 Subject: [PATCH 0088/1176] Account for warnings when compilation succeeds --- src/languageServer.ml | 33 ++++++++++----------------------- 1 file changed, 10 insertions(+), 23 deletions(-) diff --git a/src/languageServer.ml b/src/languageServer.ml index 39543374fd6..be2c41aacf1 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -137,29 +137,16 @@ let start () = false [file_name] in show_message Lsp.MessageType.Info ("Compiling file: " ^ file_name); - (* TODO: it appears that warning messages should also be included in - the OK case, since warnings are not reported if there are no - errors. - *) - (* TODO: let msgs = match result with | Error msgs -> msgs | Ok (_, msgs) -> in *) - (match result with - | Ok _ -> - (* It's our responsibility to clear any existing diagnostics *) - publish_diagnostics uri []; - show_message Lsp.MessageType.Info "Compilation successful" - | Error msgs -> - (Base.Option.iter !client_capabilities ~f:(fun capabilities -> - (* TODO: determine if the client accepts diagnostics with related info *) - (* let textDocument = capabilities.client_capabilities_textDocument in - * let send_related_information = textDocument.publish_diagnostics.relatedInformation in *) - let diags = List.map diagnostics_of_message msgs in - publish_diagnostics uri diags; - )); - show_message Lsp.MessageType.Error - ("Compilation failed with " ^ - String.concat - " " - (List.map Diag.string_of_message msgs))) + let msgs = match result with + | Error msgs' -> msgs' + | Ok (_, msgs') -> msgs' in + Base.Option.iter !client_capabilities ~f:(fun capabilities -> + (* TODO: determine if the client accepts diagnostics with related info *) + (* let textDocument = capabilities.client_capabilities_textDocument in + * let send_related_information = textDocument.publish_diagnostics.relatedInformation in *) + let diags = List.map diagnostics_of_message msgs in + publish_diagnostics uri diags; + ); end | None -> log_to_file From 23fc0871c66412b16dfc7368246d48331987516e Mon Sep 17 00:00:00 2001 From: Paul Young Date: Fri, 24 May 2019 14:05:39 -0700 Subject: [PATCH 0089/1176] Fix js_main --- src/js_main.ml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/js_main.ml b/src/js_main.ml index f7c0351302b..80ba661f175 100644 --- a/src/js_main.ml +++ b/src/js_main.ml @@ -23,6 +23,8 @@ let diagnostics_of_error (msg : Diag.message) = val message = Js.string msg.text end) +let diagnostics_of_errors (msgs : Diag.message list) = + Array.of_list (List.map diagnostics_of_error msgs) let js_check source = let msgs = match @@ -30,7 +32,7 @@ let js_check source = | Error msgs -> msgs | Ok (_, msgs) -> msgs in object%js - val diagnostics = Js.array (Array.of_list (List.map diagnostics_of_error msgs)) + val diagnostics = Js.array (diagnostics_of_errors msgs) val code = Js.null end @@ -42,17 +44,16 @@ let js_compile_with mode_string source_map source convert = | _ -> Pipeline.WasmMode in match Pipeline.compile_string mode (Js.to_string source) "js-input" with - | Ok module_ -> + | Ok (module_, msgs) -> let (code, map) = convert module_ in object%js - val diagnostics = Js.array [||] + val diagnostics = Js.array (diagnostics_of_errors msgs) val code = Js.some code val map = Js.some map end - | Error es -> + | Error msgs -> object%js - val diagnostics = - Js.array (Array.of_list (List.map diagnostics_of_error es)) + val diagnostics = Js.array (Array.of_list (List.map diagnostics_of_error msgs)) val code = Js.null val map = Js.null end From 9864e93b8cde441d3ade2c615d1b77a1a09dedaa Mon Sep 17 00:00:00 2001 From: Paul Young Date: Fri, 24 May 2019 14:35:32 -0700 Subject: [PATCH 0090/1176] Rename function --- src/js_main.ml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/js_main.ml b/src/js_main.ml index 80ba661f175..2b837f2f911 100644 --- a/src/js_main.ml +++ b/src/js_main.ml @@ -15,7 +15,7 @@ let range_of_region at = val _end = position_of_pos at.right end -let diagnostics_of_error (msg : Diag.message) = +let diagnostics_of_msg (msg : Diag.message) = Diag.(object%js val source = Js.string "actorscript" val severity = match msg.sev with Diag.Error -> 1 | Diag.Warning -> 2 @@ -23,8 +23,8 @@ let diagnostics_of_error (msg : Diag.message) = val message = Js.string msg.text end) -let diagnostics_of_errors (msgs : Diag.message list) = - Array.of_list (List.map diagnostics_of_error msgs) +let diagnostics_of_msgs (msgs : Diag.message list) = + Array.of_list (List.map diagnostics_of_msg msgs) let js_check source = let msgs = match @@ -32,7 +32,7 @@ let js_check source = | Error msgs -> msgs | Ok (_, msgs) -> msgs in object%js - val diagnostics = Js.array (diagnostics_of_errors msgs) + val diagnostics = Js.array (diagnostics_of_msgs msgs) val code = Js.null end @@ -47,13 +47,13 @@ let js_compile_with mode_string source_map source convert = | Ok (module_, msgs) -> let (code, map) = convert module_ in object%js - val diagnostics = Js.array (diagnostics_of_errors msgs) + val diagnostics = Js.array (diagnostics_of_msgs msgs) val code = Js.some code val map = Js.some map end | Error msgs -> object%js - val diagnostics = Js.array (Array.of_list (List.map diagnostics_of_error msgs)) + val diagnostics = Js.array (Array.of_list (List.map diagnostics_of_msg msgs)) val code = Js.null val map = Js.null end From 0cd61bfacf55c03903b06744d9de1944920fc6da Mon Sep 17 00:00:00 2001 From: Paul Young Date: Fri, 24 May 2019 14:47:03 -0700 Subject: [PATCH 0091/1176] Use Diag.result --- src/pipeline.ml | 2 +- src/pipeline.mli | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pipeline.ml b/src/pipeline.ml index 471fe1fc99e..a3fba7cc1a1 100644 --- a/src/pipeline.ml +++ b/src/pipeline.ml @@ -448,7 +448,7 @@ let load_as_rts () = CustomModuleDecode.decode "rts.wasm" wasm type compile_mode = Compile.mode = WasmMode | DfinityMode -type compile_result = ((CustomModule.extended_module * Diag.messages), Diag.messages) result +type compile_result = CustomModule.extended_module Diag.result let name_progs progs = if progs = [] diff --git a/src/pipeline.mli b/src/pipeline.mli index 4928ead8e64..10feeebadb3 100644 --- a/src/pipeline.mli +++ b/src/pipeline.mli @@ -6,6 +6,6 @@ val interpret_ir_files : string list -> unit Diag.result val run_files_and_stdin : string list -> unit Diag.result type compile_mode = WasmMode | DfinityMode -type compile_result = ((CustomModule.extended_module * Diag.messages), Diag.messages) result +type compile_result = CustomModule.extended_module Diag.result val compile_string : compile_mode -> string -> string -> compile_result val compile_files : compile_mode -> bool -> string list -> compile_result From 4f5757cff6fedcd218c95b7430bb80daebfb3bda Mon Sep 17 00:00:00 2001 From: Paul Young Date: Fri, 24 May 2019 15:02:19 -0700 Subject: [PATCH 0092/1176] Consider cwd in file prefix --- src/languageServer.ml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/languageServer.ml b/src/languageServer.ml index be2c41aacf1..422cdc242e5 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -130,7 +130,8 @@ let start () = | (_, `TextDocumentDidSave params) -> let textDocumentIdent = params.Lsp_t.text_document_did_save_params_textDocument in let uri = textDocumentIdent.Lsp_t.text_document_identifier_uri in - (match Base.String.chop_prefix ~prefix:"file://" uri with + let prefix = "file://" ^ Sys.getcwd () ^ "/" in + (match Base.String.chop_prefix ~prefix:prefix uri with | Some file_name -> begin let result = Pipeline.compile_files Pipeline.DfinityMode From 31221de3215df4c00085d90eaded18abb24e2af0 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Fri, 24 May 2019 15:23:08 -0700 Subject: [PATCH 0093/1176] Retrieve cwd once --- src/languageServer.ml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/languageServer.ml b/src/languageServer.ml index 422cdc242e5..82cb31c2f0f 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -78,6 +78,8 @@ let publish_diagnostics (uri: Lsp_t.document_uri) (diags: Lsp_t.diagnostic list) let notification = notification params in send_notification (Lsp_j.string_of_notification_message notification) +let file_uri_prefix = "file://" ^ Sys.getcwd () ^ "/" + let start () = let client_capabilities = ref None in @@ -130,8 +132,7 @@ let start () = | (_, `TextDocumentDidSave params) -> let textDocumentIdent = params.Lsp_t.text_document_did_save_params_textDocument in let uri = textDocumentIdent.Lsp_t.text_document_identifier_uri in - let prefix = "file://" ^ Sys.getcwd () ^ "/" in - (match Base.String.chop_prefix ~prefix:prefix uri with + (match Base.String.chop_prefix ~prefix:file_uri_prefix uri with | Some file_name -> begin let result = Pipeline.compile_files Pipeline.DfinityMode From 51e08a2bdb412a8b6e299817f02cb6d4d82f9561 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Fri, 24 May 2019 16:04:12 -0700 Subject: [PATCH 0094/1176] Use Diag.return --- src/pipeline.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pipeline.ml b/src/pipeline.ml index a3fba7cc1a1..0b670e5dc69 100644 --- a/src/pipeline.ml +++ b/src/pipeline.ml @@ -471,7 +471,7 @@ let compile_prog mode do_link lib_env libraries progs : compile_result = phase "Compiling" name; let rts = if do_link then Some (load_as_rts ()) else None in let module_ = Compile.compile mode name rts prelude_ir [prog_ir] in - Ok (module_, []) + Diag.return module_ let compile_files mode do_link files : compile_result = match load_progs (parse_files files) initial_stat_env with From 3ae1a304535ae279f370d1f6e3535b8412ca98c4 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Fri, 24 May 2019 19:41:09 -0700 Subject: [PATCH 0095/1176] Handle Unknown severity and message types properly --- src/lsp/diagnosticSeverity.ml | 6 +++--- src/lsp/diagnosticSeverity.mli | 2 +- src/lsp/messageType.ml | 6 +++--- src/lsp/messageType.mli | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/lsp/diagnosticSeverity.ml b/src/lsp/diagnosticSeverity.ml index 78bb084c03c..3dbf0b586d9 100644 --- a/src/lsp/diagnosticSeverity.ml +++ b/src/lsp/diagnosticSeverity.ml @@ -3,7 +3,7 @@ type t | Warning | Information | Hint - | Unknown + | Unknown of int let wrap : int -> t = function @@ -11,12 +11,12 @@ function | 2 -> Warning | 3 -> Information | 4 -> Hint -| _ -> Unknown +| x -> Unknown x let unwrap : t -> int = function -| Unknown -> 0 | Error -> 1 | Warning -> 2 | Information -> 3 | Hint -> 4 +| Unknown x -> x diff --git a/src/lsp/diagnosticSeverity.mli b/src/lsp/diagnosticSeverity.mli index d08a2c3ae04..4391815666d 100644 --- a/src/lsp/diagnosticSeverity.mli +++ b/src/lsp/diagnosticSeverity.mli @@ -3,7 +3,7 @@ type t | Warning | Information | Hint - | Unknown + | Unknown of int val wrap : int -> t val unwrap : t -> int diff --git a/src/lsp/messageType.ml b/src/lsp/messageType.ml index 6221305660a..fbec3d7d8aa 100644 --- a/src/lsp/messageType.ml +++ b/src/lsp/messageType.ml @@ -3,7 +3,7 @@ type t | Warning | Info | Log - | Unknown + | Unknown of int let wrap : int -> t = function @@ -11,12 +11,12 @@ function | 2 -> Warning | 3 -> Info | 4 -> Log -| _ -> Unknown +| x -> Unknown x let unwrap : t -> int = function -| Unknown -> 0 | Error -> 1 | Warning -> 2 | Info -> 3 | Log -> 4 +| Unknown x -> x diff --git a/src/lsp/messageType.mli b/src/lsp/messageType.mli index 508cbaffbeb..f148ee3b07e 100644 --- a/src/lsp/messageType.mli +++ b/src/lsp/messageType.mli @@ -3,7 +3,7 @@ type t | Warning | Info | Log - | Unknown + | Unknown of int val wrap : int -> t val unwrap : t -> int From 871e90192f5ea7278332f98624ffe31fa28ad7b7 Mon Sep 17 00:00:00 2001 From: Christoph Hegemann Date: Mon, 27 May 2019 14:19:38 +0200 Subject: [PATCH 0096/1176] use check_files to find type errors The output of the compile_files command on stderr caused vscode to kill the running lsp-server process --- src/languageServer.ml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/languageServer.ml b/src/languageServer.ml index 82cb31c2f0f..2c5643df192 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -134,10 +134,7 @@ let start () = let uri = textDocumentIdent.Lsp_t.text_document_identifier_uri in (match Base.String.chop_prefix ~prefix:file_uri_prefix uri with | Some file_name -> begin - let result = Pipeline.compile_files - Pipeline.DfinityMode - false - [file_name] in + let result = Pipeline.check_files [file_name] in show_message Lsp.MessageType.Info ("Compiling file: " ^ file_name); let msgs = match result with | Error msgs' -> msgs' From e1ecc9295994f70416c4fe391f350b047ebc8b82 Mon Sep 17 00:00:00 2001 From: Christoph Hegemann Date: Mon, 27 May 2019 14:20:13 +0200 Subject: [PATCH 0097/1176] don't output delimiters for the protocol into our log file --- src/languageServer.ml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/languageServer.ml b/src/languageServer.ml index 2c5643df192..92be71446c9 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -24,8 +24,9 @@ let log_to_file (lbl: string) (txt: string): unit = flush oc let send (label: string) (out: string): unit = - let cl = "Content-Length: " ^ string_of_int (String.length out) ^ "\r\n\r\n" in + let cl = "Content-Length: " ^ string_of_int (String.length out) in print_string cl; + print_string "\r\n\r\n"; print_string out; flush stdout; log_to_file (label ^ "_length") cl; From 5d22c237e35b3b825ea42c0673885873971f8aac Mon Sep 17 00:00:00 2001 From: Paul Young Date: Tue, 28 May 2019 11:12:28 -0700 Subject: [PATCH 0098/1176] Remove Result map (bad auto merge resolution) --- src/lib.ml | 7 ------- src/lib.mli | 5 ----- 2 files changed, 12 deletions(-) diff --git a/src/lib.ml b/src/lib.ml index 50562af5d15..6f4b86fb765 100644 --- a/src/lib.ml +++ b/src/lib.ml @@ -258,10 +258,3 @@ struct let value_opt p = !p let value p = match !p with Some x -> x | None -> raise Promise end - -module Result = -struct - let map f = function - | Ok x -> Ok (f x) - | Error x -> Error x -end diff --git a/src/lib.mli b/src/lib.mli index 62b5c569fd9..4c70be475cb 100644 --- a/src/lib.mli +++ b/src/lib.mli @@ -101,8 +101,3 @@ sig val breakup : string -> int -> string list val find_from_opt : (char -> bool) -> string -> int -> int option end - -module Result : -sig - val map : ('a -> 'c) -> ('a, 'b) result -> ('c, 'b) result -end From 49ff3aaa3335c77c9e45f0477c0a677234db63e1 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 28 May 2019 11:07:18 +0200 Subject: [PATCH 0099/1176] Backend: Allow `actor class foo() { .. }` as last expression this is in anticipation of #400. It extends the prevoius hack in the backend, and does not include the necessary changes to the front end for proper error handling. But it finally allows the produce exchange to use `import` for everything, no longer relying on the concatenation of source files (relevant for #447). --- src/compile.ml | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/compile.ml b/src/compile.ml index 3276177a079..e5095d7d8d6 100644 --- a/src/compile.ml +++ b/src/compile.ml @@ -5182,14 +5182,22 @@ and find_prelude_names env = and compile_start_func mod_env (progs : Ir.prog list) : E.func_with_names = - let find_last_actor (ds1,e) = match ds1, e.it with - | _, ActorE (i, ds2, fs, _) -> Some (i, ds1 @ ds2, fs) - | [], _ -> None + let find_last_expr ds e = + if ds = [] then [], e.it else + match Lib.List.split_last ds, e.it with + | (ds1', {it = LetD ({it = VarP i1; _}, e'); _}), TupE [] -> + ds1', e'.it + | (ds1', {it = LetD ({it = VarP i1; _}, e'); _}), VarE i2 when i1 = i2 -> + ds1', e'.it + | _ -> ds, e.it in + + let find_last_actor (ds,e) = match find_last_expr ds e with + | ds1, ActorE (i, ds2, fs, _) -> + Some (i, ds1 @ ds2, fs) + | ds1, FuncE (_name, _cc, [], [], _, {it = ActorE (i, ds2, fs, _);_}) -> + Some (i, ds1 @ ds2, fs) | _, _ -> - match Lib.List.split_last ds1, e.it with - | (ds1', {it = LetD ({it = VarP i1; _}, {it = ActorE (i2, ds2, fs, _); _}); _}) - , VarE i3 when i1 = i2 && i2 = i3 -> Some (i2, ds1' @ ds2, fs) - | _ -> None + None in Func.of_body mod_env [] [] (fun env -> From 2c4f4be03eb5099e1e96b7473fd93d5e9663a15f Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 28 May 2019 11:12:41 +0200 Subject: [PATCH 0100/1176] Use `import` in the produce exchange MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit now that we can use `actor class Foo () {..}` for actor files. Also wraps the standard libraries in `module {…}`, following the hint that `asc` spits out (probably introduced by @crusso). --- stdlib/Makefile | 8 ++-- stdlib/assocList.as | 5 ++- stdlib/docTable.as | 3 +- .../examples/produce-exchange/serverActor.as | 3 +- .../examples/produce-exchange/serverLang.as | 2 + .../examples/produce-exchange/serverModel.as | 3 +- .../produce-exchange/serverModelTypes.as | 2 + .../examples/produce-exchange/serverTypes.as | 2 + .../produce-exchange/test/evalBulk.as | 23 +++++------ .../test/producerRemInventory.as | 22 +++++------ .../test/retailerReserveMany.as | 39 +++++++++---------- .../test/simpleSetupAndQuery.as | 24 +++++------- stdlib/hash.as | 2 + stdlib/list.as | 2 + stdlib/option.as | 3 ++ stdlib/prelude.as | 2 + stdlib/result.as | 4 +- stdlib/trie.as | 2 + 18 files changed, 82 insertions(+), 69 deletions(-) diff --git a/stdlib/Makefile b/stdlib/Makefile index a16f3527649..fe7f8eac1f3 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -158,19 +158,19 @@ PRODUCE_EXCHANGE_SRC=\ $(OUTDIR)/ProduceExchange.out: $(PRODUCE_EXCHANGE_SRC) \ examples/produce-exchange/test/simpleSetupAndQuery.as | $(OUTDIR) - $(ASC) -r examples/produce-exchange/serverActor.as examples/produce-exchange/test/simpleSetupAndQuery.as > $@ + $(ASC) -r examples/produce-exchange/test/simpleSetupAndQuery.as > $@ $(OUTDIR)/retailerReserveMany.out: $(PRODUCE_EXCHANGE_SRC) \ examples/produce-exchange/test/retailerReserveMany.as | $(OUTDIR) - $(ASC) -r examples/produce-exchange/serverActor.as examples/produce-exchange/test/retailerReserveMany.as > $@ + $(ASC) -r examples/produce-exchange/test/retailerReserveMany.as > $@ $(OUTDIR)/producerRemInventory.out: $(PRODUCE_EXCHANGE_SRC) \ examples/produce-exchange/test/producerRemInventory.as | $(OUTDIR) - $(ASC) -r examples/produce-exchange/serverActor.as examples/produce-exchange/test/producerRemInventory.as > $@ + $(ASC) -r examples/produce-exchange/test/producerRemInventory.as > $@ $(OUTDIR)/evalBulk.out: $(PRODUCE_EXCHANGE_SRC) \ examples/produce-exchange/test/evalBulk.as | $(OUTDIR) - $(ASC) -r examples/produce-exchange/serverActor.as examples/produce-exchange/test/evalBulk.as > $@ + $(ASC) -r examples/produce-exchange/test/evalBulk.as > $@ $(OUTDIR)/ProduceExchange.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) $(ASC) -c -o $@ examples/produce-exchange/serverActor.as diff --git a/stdlib/assocList.as b/stdlib/assocList.as index b43de184c2d..702ae734771 100644 --- a/stdlib/assocList.as +++ b/stdlib/assocList.as @@ -1,3 +1,4 @@ +module { /** Association Lists @@ -9,7 +10,7 @@ Implements the same interface as `Trie`, but as a linked-list of key-value pairs */ -let List = import "list.as"; +private let List = import "list.as"; // polymorphic association linked lists between keys and values type AssocList = List.List<(K,V)>; @@ -194,3 +195,5 @@ type AssocList = List.List<(K,V)>; }; rec(al) }; + +} diff --git a/stdlib/docTable.as b/stdlib/docTable.as index 407d25aae7b..9750ac76e03 100644 --- a/stdlib/docTable.as +++ b/stdlib/docTable.as @@ -1,4 +1,4 @@ - +module { /** Document Table @@ -356,3 +356,4 @@ class DocTable( /** The end */ } +} diff --git a/stdlib/examples/produce-exchange/serverActor.as b/stdlib/examples/produce-exchange/serverActor.as index 2b590e35c06..6b2c09e93db 100644 --- a/stdlib/examples/produce-exchange/serverActor.as +++ b/stdlib/examples/produce-exchange/serverActor.as @@ -13,7 +13,7 @@ import Result = "../../result.as"; type Result = Result.Result; -actor server { +actor class Server () { /** Server Actor @@ -51,6 +51,7 @@ actor server { - `Transporter`. */ + /** `-User` diff --git a/stdlib/examples/produce-exchange/serverLang.as b/stdlib/examples/produce-exchange/serverLang.as index d0714954a0b..9c1c1270bc0 100644 --- a/stdlib/examples/produce-exchange/serverLang.as +++ b/stdlib/examples/produce-exchange/serverLang.as @@ -1,3 +1,4 @@ +module { /** Server language @@ -145,3 +146,4 @@ type UpdateReq = { #inventory : T.InventoryInfo ; #route : T.RouteInfo ; } ; +} diff --git a/stdlib/examples/produce-exchange/serverModel.as b/stdlib/examples/produce-exchange/serverModel.as index b5410558caa..827fec7f42b 100644 --- a/stdlib/examples/produce-exchange/serverModel.as +++ b/stdlib/examples/produce-exchange/serverModel.as @@ -1,4 +1,4 @@ - +module { /** [Background]($DOCURL/examples/produce-exchange#Produce-Exchange-Standards-Specification) @@ -1974,3 +1974,4 @@ than the MVP goals, however. }; }; +} diff --git a/stdlib/examples/produce-exchange/serverModelTypes.as b/stdlib/examples/produce-exchange/serverModelTypes.as index cd08b42d6d5..f71024c79de 100644 --- a/stdlib/examples/produce-exchange/serverModelTypes.as +++ b/stdlib/examples/produce-exchange/serverModelTypes.as @@ -1,3 +1,4 @@ +module { /** [Background]($DOCURL/examples/produce-exchange#Produce-Exchange-Standards-Specification) @@ -337,3 +338,4 @@ type ReservedRouteDoc = { type ReservedRouteTable = DocTable; type ReservedRouteMap = Map; +} diff --git a/stdlib/examples/produce-exchange/serverTypes.as b/stdlib/examples/produce-exchange/serverTypes.as index 917fe1d6473..e643a126f59 100644 --- a/stdlib/examples/produce-exchange/serverTypes.as +++ b/stdlib/examples/produce-exchange/serverTypes.as @@ -1,3 +1,4 @@ +module { /** [Background]($DOCURL/examples/produce-exchange#Produce-Exchange-Standards-Specification) @@ -382,3 +383,4 @@ the 2019.03.12 ActorScript Team meeting. */ type QueryAllResults = [QueryAllResult]; +} diff --git a/stdlib/examples/produce-exchange/test/evalBulk.as b/stdlib/examples/produce-exchange/test/evalBulk.as index 23ad96f0719..1bfd42e3035 100644 --- a/stdlib/examples/produce-exchange/test/evalBulk.as +++ b/stdlib/examples/produce-exchange/test/evalBulk.as @@ -1,5 +1,5 @@ let T = (import "../serverTypes.as"); -//let A = (import "../serverActor.as"); +let A = (import "../serverActor.as"); let Result = (import "../../../result.as"); let Option = (import "../../../option.as"); @@ -19,8 +19,7 @@ actor class Test() = this { go() { ignore(async { - //let s = A.Server(); - let s = server; + let s = A.Server(); print "\nExchange setup: Begin...\n====================================\n"; @@ -120,18 +119,18 @@ actor class Test() = this { let uidd = #ok 3; let uide = #ok 4; - await debugDumpAll(); + await debugDumpAll(s); ////////////////////////////////////////////////////////////////// print "\nRetailer queries\n====================================\n"; // do some queries - await retailerQueryAll(pka, ? Result.assertUnwrapAny(uida)); - await retailerQueryAll(pkb, ? Result.assertUnwrapAny(uidb)); - await retailerQueryAll(pkc, ? Result.assertUnwrapAny(uidc)); - await retailerQueryAll(pkd, ? Result.assertUnwrapAny(uidd)); - await retailerQueryAll(pke, ? Result.assertUnwrapAny(uide)); + await retailerQueryAll(s, pka, ? Result.assertUnwrapAny(uida)); + await retailerQueryAll(s, pkb, ? Result.assertUnwrapAny(uidb)); + await retailerQueryAll(s, pkc, ? Result.assertUnwrapAny(uidc)); + await retailerQueryAll(s, pkd, ? Result.assertUnwrapAny(uidd)); + await retailerQueryAll(s, pke, ? Result.assertUnwrapAny(uide)); print "\nQuery counts\n----------------\n"; let counts = await s.getCounts(); @@ -145,8 +144,7 @@ actor class Test() = this { }; -//func retailerQueryAll(server:A.Server, pk:Text, r:?T.UserId) : async () { -func retailerQueryAll(pk:Text, r:?T.UserId) : async () { +func retailerQueryAll(server:A.Server, pk:Text, r:?T.UserId) : async () { print "\nRetailer "; let retailerId: T.UserId = Option.unwrap(r); @@ -170,8 +168,7 @@ func retailerQueryAll(pk:Text, r:?T.UserId) : async () { } }; -//func debugDumpAll(server:A.Server) : async () { -func debugDumpAll() : async () { +func debugDumpAll(server:A.Server) : async () { print "\nTruck type info\n----------------\n"; for ( info in ((await server.allTruckTypeInfo()).vals()) ) { diff --git a/stdlib/examples/produce-exchange/test/producerRemInventory.as b/stdlib/examples/produce-exchange/test/producerRemInventory.as index 43e71ce3b44..77a18304a66 100644 --- a/stdlib/examples/produce-exchange/test/producerRemInventory.as +++ b/stdlib/examples/produce-exchange/test/producerRemInventory.as @@ -1,5 +1,5 @@ let T = (import "../serverTypes.as"); -//let A = (import "../serverActor.as"); +let A = (import "../serverActor.as"); let Result = (import "../../../result.as"); let Option = (import "../../../option.as"); @@ -19,8 +19,7 @@ actor class Test() = this { go() { ignore(async { - //let s = A.Server(); - let s = server; + let s = A.Server(); print "\nExchange setup: Begin...\n====================================\n"; @@ -122,8 +121,8 @@ actor class Test() = this { ////////////////////// - await debugDumpInventory(pka, 0); - await debugDumpAll(); + await debugDumpInventory(s, pka, 0); + await debugDumpAll(s); print "\n First time: Producer remove query\n====================================\n"; @@ -132,8 +131,8 @@ actor class Test() = this { print (debug_show rem0); print "\n"; - await debugDumpInventory(pka, 0); - await debugDumpAll(); + await debugDumpInventory(s, pka, 0); + await debugDumpAll(s); print "\n Second time: Producer remove query\n====================================\n"; @@ -142,13 +141,13 @@ actor class Test() = this { print (debug_show rem0b); print "\n"; - await debugDumpInventory(pka, 0); - await debugDumpAll(); + await debugDumpInventory(s, pka, 0); + await debugDumpAll(s); }) }; }; -func debugDumpInventory(pk:T.PublicKey, p:T.ProducerId) : async () { +func debugDumpInventory(server:A.Server, pk:T.PublicKey, p:T.ProducerId) : async () { print "\nProducer "; printInt p; print "'s inventory:\n--------------------------------\n"; @@ -162,8 +161,7 @@ func debugDumpInventory(pk:T.PublicKey, p:T.ProducerId) : async () { } }; -//func debugDumpAll(server:A.Server) : async () { -func debugDumpAll() : async () { +func debugDumpAll(server:A.Server) : async () { print "\nTruck type info\n----------------\n"; for ( info in ((await server.allTruckTypeInfo()).vals()) ) { diff --git a/stdlib/examples/produce-exchange/test/retailerReserveMany.as b/stdlib/examples/produce-exchange/test/retailerReserveMany.as index d608d366a6f..b4a4a664971 100644 --- a/stdlib/examples/produce-exchange/test/retailerReserveMany.as +++ b/stdlib/examples/produce-exchange/test/retailerReserveMany.as @@ -1,5 +1,5 @@ let T = (import "../serverTypes.as"); -//let A = (import "../serverActor.as"); +let A = (import "../serverActor.as"); let Result = (import "../../../result.as"); let Option = (import "../../../option.as"); @@ -19,8 +19,7 @@ actor class Test() = this { go() { ignore(async { - //let s = A.Server(); - let s = server; + let s = A.Server(); print "\nExchange setup: Begin...\n====================================\n"; @@ -100,20 +99,20 @@ actor class Test() = this { print "\nExchange setup: Done.\n====================================\n"; - let inventoryCount1 = await debugDumpInventory(pka, 0); - let routeCount1 = await debugDumpRoutes(pka, 0); - await debugDumpAll(); + let inventoryCount1 = await debugDumpInventory(s, pka, 0); + let routeCount1 = await debugDumpRoutes(s, pka, 0); + await debugDumpAll(s); ////////////////////////////////////////////////////////////////// print "\nRetailer queries\n====================================\n"; // do some queries - await retailerQueryAll(pka, ? Result.assertUnwrapAny(uida)); - await retailerQueryAll(pkb, ? Result.assertUnwrapAny(uidb)); - await retailerQueryAll(pkc, ? Result.assertUnwrapAny(uidc)); - await retailerQueryAll(pkd, ? Result.assertUnwrapAny(uidd)); - await retailerQueryAll(pke, ? Result.assertUnwrapAny(uide)); + await retailerQueryAll(s, pka, ? Result.assertUnwrapAny(uida)); + await retailerQueryAll(s, pkb, ? Result.assertUnwrapAny(uidb)); + await retailerQueryAll(s, pkc, ? Result.assertUnwrapAny(uidc)); + await retailerQueryAll(s, pkd, ? Result.assertUnwrapAny(uidd)); + await retailerQueryAll(s, pke, ? Result.assertUnwrapAny(uide)); print "\nQuery counts\n----------------\n"; let counts = await s.getCounts(); @@ -134,7 +133,7 @@ actor class Test() = this { (0, 1)]); - let urrm = Result.assertUnwrapAny<[Result<(T.ReservedInventoryId, T.ReservedRouteId), T.ServerErr>]>(rrm); + let urrm = Result.assertUnwrapAny<[Result.Result<(T.ReservedInventoryId, T.ReservedRouteId), T.ServerErr>]>(rrm); print "\nRetailer reservations: results:\n---------------------------------\n"; @@ -173,17 +172,17 @@ actor class Test() = this { print "\nExchange interactions: Done.\n====================================\n"; - let inventoryCount2 = await debugDumpInventory(pka, 0); - let routeCount2 = await debugDumpRoutes(pka, 0); + let inventoryCount2 = await debugDumpInventory(s, pka, 0); + let routeCount2 = await debugDumpRoutes(s, pka, 0); assert (inventoryCount2 == 0); assert (routeCount2 == 1); - await debugDumpAll(); + await debugDumpAll(s); }) }; }; -func debugDumpInventory(pk:T.PublicKey, p:T.ProducerId) : async Nat { +func debugDumpInventory(server:A.Server, pk:T.PublicKey, p:T.ProducerId) : async Nat { print "\nProducer "; printInt p; print "'s inventory:\n--------------------------------\n"; @@ -199,7 +198,7 @@ func debugDumpInventory(pk:T.PublicKey, p:T.ProducerId) : async Nat { items.len() }; -func debugDumpRoutes(pk:T.PublicKey, t:T.TransporterId) : async Nat { +func debugDumpRoutes(server:A.Server, pk:T.PublicKey, t:T.TransporterId) : async Nat { print "\nTransporter "; printInt t; print "'s routes:\n--------------------------------\n"; @@ -215,8 +214,7 @@ func debugDumpRoutes(pk:T.PublicKey, t:T.TransporterId) : async Nat { items.len() }; -//func retailerQueryAll(server:A.Server, pk:Text, r:?T.UserId) : async () { -func retailerQueryAll(pk:Text, r:?T.UserId) : async () { +func retailerQueryAll(server:A.Server, pk:Text, r:?T.UserId) : async () { print "\nRetailer "; let retailerId: T.UserId = Option.unwrap(r); @@ -240,8 +238,7 @@ func retailerQueryAll(pk:Text, r:?T.UserId) : async () { } }; -//func debugDumpAll(server:A.Server) : async () { -func debugDumpAll() : async () { +func debugDumpAll(server:A.Server) : async () { print "\nTruck type info\n----------------\n"; for ( info in ((await server.allTruckTypeInfo()).vals()) ) { diff --git a/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.as b/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.as index 8b561e0be13..473b3e4a4c8 100644 --- a/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.as +++ b/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.as @@ -1,5 +1,5 @@ let T = (import "../serverTypes.as"); -//let A = (import "../serverActor.as"); +let A = (import "../serverActor.as"); let Result = (import "../../../result.as"); let Option = (import "../../../option.as"); @@ -19,8 +19,7 @@ actor class Test() = this { go() { ignore(async { - //let s = A.Server(); - let s = server; + let s = A.Server(); print "\nExchange setup: Begin...\n====================================\n"; @@ -292,19 +291,18 @@ actor class Test() = this { print "\nExchange setup: Done.\n====================================\n"; - //await debugDumpAll(s); - await debugDumpAll(); + await debugDumpAll(s); ////////////////////////////////////////////////////////////////// print "\nRetailer queries\n====================================\n"; // do some queries - await retailerQueryAll(pka, ? Result.assertUnwrapAny(uida)); - await retailerQueryAll(pkb, ? Result.assertUnwrapAny(uidb)); - await retailerQueryAll(pkc, ? Result.assertUnwrapAny(uidc)); - await retailerQueryAll(pkd, ? Result.assertUnwrapAny(uidd)); - await retailerQueryAll(pke, ? Result.assertUnwrapAny(uide)); + await retailerQueryAll(s, pka, ? Result.assertUnwrapAny(uida)); + await retailerQueryAll(s, pkb, ? Result.assertUnwrapAny(uidb)); + await retailerQueryAll(s, pkc, ? Result.assertUnwrapAny(uidc)); + await retailerQueryAll(s, pkd, ? Result.assertUnwrapAny(uidd)); + await retailerQueryAll(s, pke, ? Result.assertUnwrapAny(uide)); print "\nQuery counts\n----------------\n"; let counts = await s.getCounts(); @@ -337,8 +335,7 @@ actor class Test() = this { }; -//func retailerQueryAll(server:A.Server, pk:Text, r:?T.UserId) : async () { -func retailerQueryAll(pk:Text, r:?T.UserId) : async () { +func retailerQueryAll(server:A.Server, pk:Text, r:?T.UserId) : async () { print "\nRetailer "; let retailerId: T.UserId = Option.unwrap(r); @@ -362,8 +359,7 @@ func retailerQueryAll(pk:Text, r:?T.UserId) : async () { } }; -//func debugDumpAll(server:A.Server) : async () { -func debugDumpAll() : async () { +func debugDumpAll(server:A.Server) : async () { print "\nTruck type info\n----------------\n"; for ( info in ((await server.allTruckTypeInfo()).vals()) ) { diff --git a/stdlib/hash.as b/stdlib/hash.as index d0e37a53bff..4fd641aa5fb 100644 --- a/stdlib/hash.as +++ b/stdlib/hash.as @@ -1,3 +1,4 @@ +module { /** Hash values @@ -193,3 +194,4 @@ module BitList { type Hash = BitVec; let Hash = BitVec; +} diff --git a/stdlib/list.as b/stdlib/list.as index 2bd5aaadfc2..9c17aa74308 100644 --- a/stdlib/list.as +++ b/stdlib/list.as @@ -1,3 +1,4 @@ +module { /** # List @@ -437,3 +438,4 @@ To do: - more regression tests for everything that is below */ +} diff --git a/stdlib/option.as b/stdlib/option.as index 9dbbbb8f935..2f326c01413 100644 --- a/stdlib/option.as +++ b/stdlib/option.as @@ -1,3 +1,4 @@ +module { /** Functions for Option types. @@ -151,3 +152,5 @@ func printOpInt(x : ?Int) = case null { print "null" }; case (?x_) { print "?"; printInt x_ }; }; + +} diff --git a/stdlib/prelude.as b/stdlib/prelude.as index 260cd5b6d25..0d66aed63e1 100644 --- a/stdlib/prelude.as +++ b/stdlib/prelude.as @@ -1,3 +1,4 @@ +module { /** Stdlib prelude @@ -39,3 +40,4 @@ func xxx() : None = */ func unreachable() : None = { assert false ; loop { } }; +} diff --git a/stdlib/result.as b/stdlib/result.as index d383ffbdf9d..aa7cda25653 100644 --- a/stdlib/result.as +++ b/stdlib/result.as @@ -1,4 +1,5 @@ -let P = (import "prelude.as"); +module { +private let P = (import "prelude.as"); /** @@ -164,3 +165,4 @@ func joinArrayIfOk(x:[Result]) : Result<[R],E> { /**- all of the results are Ok; tabulate them. */ #ok(Array_tabulate(x.len(), func (i:Nat):R { assertUnwrap(x[i]) })) }; +} diff --git a/stdlib/trie.as b/stdlib/trie.as index 059b64247d4..a17de7fb599 100644 --- a/stdlib/trie.as +++ b/stdlib/trie.as @@ -1,3 +1,4 @@ +module { /** Hash tries @@ -1263,3 +1264,4 @@ Iterator objects for use in 'for ... in ...' patterns */ +} From 5cd5adf04d93295754e1a2e4e3edb1bae50e56e1 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 28 May 2019 11:22:42 +0200 Subject: [PATCH 0101/1176] `import`'ify samples/app --- samples/app/Makefile | 4 ++-- samples/app/client.as | 6 ++++-- samples/app/main.as | 11 +++++++---- samples/app/server.as | 9 ++++++--- 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/samples/app/Makefile b/samples/app/Makefile index bbabfa700b7..a4302b8b957 100644 --- a/samples/app/Makefile +++ b/samples/app/Makefile @@ -12,10 +12,10 @@ LIB=list.as types.as server.as client.as SAMPLES:= test all: - $(ASC) -r -t -v $(LIB) main.as >main.txt 2>&1 + $(ASC) -r -t -v main.as >main.txt 2>&1 dvm: - $(ASC) -o $(OUT) $(LIB) main.as + $(ASC) -o $(OUT) main.as $(DVM) $(OUT) clean: diff --git a/samples/app/client.as b/samples/app/client.as index c5643c5fc26..0a4d34de41d 100644 --- a/samples/app/client.as +++ b/samples/app/client.as @@ -1,9 +1,11 @@ +import S "server.as"; + actor class Client() = this { // TODO: these should be constructor params once we can compile them private var name : Text = ""; - private var server : ?Server = null; + private var server : ?S.Server = null; - go(n : Text, s : Server) { + go(n : Text, s : S.Server) { name := n; server := ?s; ignore(async { diff --git a/samples/app/main.as b/samples/app/main.as index d23e4ee6fb2..6632f551174 100644 --- a/samples/app/main.as +++ b/samples/app/main.as @@ -1,7 +1,10 @@ -let server = Server(); -let bob = Client(); -let alice = Client(); -let charlie = Client(); +import Server "server.as"; +import Client "client.as"; + +let server = Server.Server(); +let bob = Client.Client(); +let alice = Client.Client(); +let charlie = Client.Client(); bob.go("bob", server); alice.go("alice", server); charlie.go("charlie", server); diff --git a/samples/app/server.as b/samples/app/server.as index e3457ac31fc..076fcc8d116 100644 --- a/samples/app/server.as +++ b/samples/app/server.as @@ -1,3 +1,6 @@ +import L "list.as"; +import T "types.as"; + type ClientData = { id : Nat; client : shared Text -> (); @@ -6,7 +9,7 @@ type ClientData = { actor class Server() = { private var nextId : Nat = 0; - private var clients : List = null; + private var clients : L.List = null; private broadcast(id : Nat, message : Text) { var next = clients; @@ -21,7 +24,7 @@ actor class Server() = { }; }; - subscribe(aclient : shared Text -> ()) : async Subscription { + subscribe(aclient : shared Text -> ()) : async T.Subscription { let c = new {id = nextId; client = aclient; var revoked = false}; nextId += 1; let cs = new {head = c; var tail = clients}; @@ -35,7 +38,7 @@ actor class Server() = { }; private unsubscribe(id : Nat) { - var prev : List = null; + var prev : L.List = null; var next = clients; loop { switch next { From 83cf3d6854885f2ebece926b899cae1c15c3fd9d Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Wed, 29 May 2019 17:52:03 +0200 Subject: [PATCH 0102/1176] AST-63 arithmetic shift right operator (#450) * implements signed (arithmetic) shift right operator `+>>` * `+>>` operates on word types by inserting the sign (topmost) bit as many times as demanded. * made `>>` a _logical shift right_ in the interpreter (it used to be signed shift) * adds tests --- spec/fig-syntax.tex | 2 +- src/arrange.ml | 3 ++- src/compile.ml | 21 ++++++++------------- src/lexer.mll | 10 ++++++---- src/operator.ml | 3 ++- src/parser.mly | 14 ++++++++------ src/prelude.ml | 14 -------------- src/syntax.ml | 3 ++- test/run/ok/words.run-ir.ok | 4 ++++ test/run/ok/words.run-low.ok | 4 ++++ test/run/ok/words.run.ok | 4 ++++ test/run/words.as | 16 ++++++++++------ 12 files changed, 51 insertions(+), 47 deletions(-) diff --git a/spec/fig-syntax.tex b/spec/fig-syntax.tex index aa473f37572..c24fb66be6d 100644 --- a/spec/fig-syntax.tex +++ b/spec/fig-syntax.tex @@ -94,7 +94,7 @@ \subsection*{Expressions} %[1ex] \text{(binary operators)} & \x{binop} &:=& \K{+} ~|~ \K\textendash ~|~ \K{*} ~|~ \K{/} ~|~ \K{\%} \\&&|& - \K{\&} ~|~ \;\K\textbar\; ~|~ \K{\^{}} ~|~ \Klt\Klt ~|~ \Kgt\Kgt ~|~ \Kgt\Kgt\Kgt ~|~ \Klt\Klt\Kgt ~|~ \Klt\Kgt\Kgt \\ + \K{\&} ~|~ \;\K\textbar\; ~|~ \K{\^{}} ~|~ \Klt\Klt ~|~ \Kgt\Kgt ~|~ \K{+}\Kgt\Kgt ~|~ \Klt\Klt\Kgt ~|~ \Klt\Kgt\Kgt \\ [1ex] \text{(relational operators)} & \x{relop} &:=& \K= ~|~ \K{!=} ~|~ \Klt ~|~ \Kgt ~|~ {\Klt}{\K=} ~|~ {\Kgt}{\K=} \\ diff --git a/src/arrange.ml b/src/arrange.ml index e1b1da37abd..afe8a307eda 100644 --- a/src/arrange.ml +++ b/src/arrange.ml @@ -97,7 +97,8 @@ and binop bo = match bo with | OrOp -> Atom "OrOp" | XorOp -> Atom "XorOp" | ShLOp -> Atom "ShiftLOp" - | ShROp -> Atom "ShiftROp" + | UShROp -> Atom "UnsignedShiftROp" + | SShROp -> Atom "SignedShiftROp" | RotLOp -> Atom "RotLOp" | RotROp -> Atom "RotROp" | CatOp -> Atom "CatOp" diff --git a/src/compile.ml b/src/compile.ml index e5095d7d8d6..57c4d92e84f 100644 --- a/src/compile.ml +++ b/src/compile.ml @@ -1339,12 +1339,6 @@ module UnboxedSmallWord = struct G.i (Unary (Wasm.Values.I32 I32Op.Ctz)) ^^ msb_adjust ty - (* Kernel for arithmetic (signed) shift, according to the word invariant. *) - let shrs_kernel ty = - lsb_adjust ty ^^ - G.i (Binary (Wasm.Values.I32 I32Op.ShrS)) ^^ - sanitize_word_result ty - (* Kernel for testing a bit position, according to the word invariant. *) let btst_kernel env ty = let (set_b, get_b) = new_local env "b" @@ -1448,7 +1442,7 @@ sig (* literals *) val compile_lit : E.t -> Big_int.big_int -> G.t - (* arithmetics *) + (* arithmetic *) val compile_abs : E.t -> G.t val compile_neg : E.t -> G.t val compile_add : E.t -> G.t @@ -4436,11 +4430,16 @@ let rec compile_binop env t op = | Type.(Prim (Word8|Word16|Word32 as ty)), ShLOp -> UnboxedSmallWord.( lsb_adjust ty ^^ clamp_shift_amount ty ^^ G.i (Binary (Wasm.Values.I32 I32Op.Shl))) - | Type.(Prim Word64), ShROp -> G.i (Binary (Wasm.Values.I64 I64Op.ShrU)) - | Type.(Prim (Word8|Word16|Word32 as ty)), ShROp -> UnboxedSmallWord.( + | Type.(Prim Word64), UShROp -> G.i (Binary (Wasm.Values.I64 I64Op.ShrU)) + | Type.(Prim (Word8|Word16|Word32 as ty)), UShROp -> UnboxedSmallWord.( lsb_adjust ty ^^ clamp_shift_amount ty ^^ G.i (Binary (Wasm.Values.I32 I32Op.ShrU)) ^^ sanitize_word_result ty) + | Type.(Prim Word64), SShROp -> G.i (Binary (Wasm.Values.I64 I64Op.ShrS)) + | Type.(Prim (Word8|Word16|Word32 as ty)), SShROp -> UnboxedSmallWord.( + lsb_adjust ty ^^ clamp_shift_amount ty ^^ + G.i (Binary (Wasm.Values.I32 I32Op.ShrS)) ^^ + sanitize_word_result ty) | Type.(Prim Word64), RotLOp -> G.i (Binary (Wasm.Values.I64 I64Op.Rotl)) | Type.Prim Type. Word32, RotLOp -> G.i (Binary (Wasm.Values.I32 I32Op.Rotl)) | Type.Prim Type.(Word8 | Word16 as ty), RotLOp -> UnboxedSmallWord.( @@ -4701,10 +4700,6 @@ and compile_exp (env : E.t) ae exp = in match p with | "Array.init" -> compile_kernel_as SR.Vanilla (Arr.init env) | "Array.tabulate" -> compile_kernel_as SR.Vanilla (Arr.tabulate env) - | "shrs8" -> compile_kernel_as SR.Vanilla (UnboxedSmallWord.shrs_kernel Type.Word8) - | "shrs16" -> compile_kernel_as SR.Vanilla (UnboxedSmallWord.shrs_kernel Type.Word16) - | "shrs" -> compile_kernel_as SR.UnboxedWord32 (G.i (Binary (Wasm.Values.I32 I32Op.ShrS))) - | "shrs64" -> compile_kernel_as SR.UnboxedWord64 (G.i (Binary (Wasm.Values.I64 I64Op.ShrS))) | "btst8" -> compile_kernel_as SR.Vanilla (UnboxedSmallWord.btst_kernel env Type.Word8) | "btst16" -> compile_kernel_as SR.Vanilla (UnboxedSmallWord.btst_kernel env Type.Word16) | "btst" -> compile_kernel_as SR.UnboxedWord32 (UnboxedSmallWord.btst_kernel env Type.Word32) diff --git a/src/lexer.mll b/src/lexer.mll index d51fca62a7b..84d0c105115 100644 --- a/src/lexer.mll +++ b/src/lexer.mll @@ -139,7 +139,8 @@ rule token mode = parse | "|" { OROP } | "^" { XOROP } | "<<" { SHLOP } - | space">>" { SHROP } (*TBR*) + | space">>" { USHROP } (*TBR*) + | "+>>" { SSHROP } | "<<>" { ROTLOP } | "<>>" { ROTROP } | "#" { CATOP } @@ -160,9 +161,10 @@ rule token mode = parse | "|=" { ORASSIGN } | "^=" { XORASSIGN } | "<<=" { SHLASSIGN } - | ">>=" { SHRASSIGN } - | "<<>=" { ROTLASSIGN } - | "<>>=" { ROTRASSIGN } + | ">>=" { USHRASSIGN } + | "+>>=" { SSHRASSIGN } + | "<<>=" { ROTLASSIGN } + | "<>>=" { ROTRASSIGN } | "#=" { CATASSIGN } | space">"space { GTOP } (*TBR*) diff --git a/src/operator.ml b/src/operator.ml index 1bdc2c27e4d..b937a2346bc 100644 --- a/src/operator.ml +++ b/src/operator.ml @@ -66,7 +66,8 @@ let binop t op = | OrOp -> word_binop Word8.or_ Word16.or_ Word32.or_ Word64.or_ p | XorOp -> word_binop Word8.xor Word16.xor Word32.xor Word64.xor p | ShLOp -> word_binop Word8.shl Word16.shl Word32.shl Word64.shl p - | ShROp -> word_binop Word8.shr_s Word16.shr_s Word32.shr_s Word64.shr_s p + | UShROp -> word_binop Word8.shr_u Word16.shr_u Word32.shr_u Word64.shr_u p + | SShROp -> word_binop Word8.shr_s Word16.shr_s Word32.shr_s Word64.shr_s p | RotLOp -> word_binop Word8.rotl Word16.rotl Word32.rotl Word64.rotl p | RotROp -> word_binop Word8.rotr Word16.rotr Word32.rotr Word64.rotr p | CatOp -> text_binop (^) p diff --git a/src/parser.mly b/src/parser.mly index a10ebe93aff..1d75d4d4bfc 100644 --- a/src/parser.mly +++ b/src/parser.mly @@ -102,12 +102,12 @@ let share_expfield (ef : exp_field) = %token DEBUG_SHOW %token ASSERT %token ADDOP SUBOP MULOP DIVOP MODOP POWOP -%token ANDOP OROP XOROP SHLOP SHROP ROTLOP ROTROP +%token ANDOP OROP XOROP SHLOP USHROP SSHROP ROTLOP ROTROP %token EQOP NEQOP LEOP LTOP GTOP GEOP %token CATOP %token EQ LT GT %token PLUSASSIGN MINUSASSIGN MULASSIGN DIVASSIGN MODASSIGN POWASSIGN CATASSIGN -%token ANDASSIGN ORASSIGN XORASSIGN SHLASSIGN SHRASSIGN ROTLASSIGN ROTRASSIGN +%token ANDASSIGN ORASSIGN XORASSIGN SHLASSIGN USHRASSIGN SSHRASSIGN ROTLASSIGN ROTRASSIGN %token NULL %token DOT_NUM %token NAT @@ -123,7 +123,7 @@ let share_expfield (ef : exp_field) = %nonassoc IF_NO_ELSE LOOP_NO_WHILE %nonassoc ELSE WHILE -%right ASSIGN PLUSASSIGN MINUSASSIGN MULASSIGN DIVASSIGN MODASSIGN POWASSIGN CATASSIGN ANDASSIGN ORASSIGN XORASSIGN SHLASSIGN SHRASSIGN ROTLASSIGN ROTRASSIGN +%right ASSIGN PLUSASSIGN MINUSASSIGN MULASSIGN DIVASSIGN MODASSIGN POWASSIGN CATASSIGN ANDASSIGN ORASSIGN XORASSIGN SHLASSIGN USHRASSIGN SSHRASSIGN ROTLASSIGN ROTRASSIGN %left COLON %left OR %left AND @@ -133,7 +133,7 @@ let share_expfield (ef : exp_field) = %left OROP %left ANDOP %left XOROP -%nonassoc SHLOP SHROP ROTLOP ROTROP +%nonassoc SHLOP USHROP SSHROP ROTLOP ROTROP %left POWOP %type exp exp_nullary @@ -313,7 +313,8 @@ lit : | OROP { OrOp } | XOROP { XorOp } | SHLOP { ShLOp } - | SHROP { ShROp } + | USHROP { UShROp } + | SSHROP { SShROp } | ROTLOP { RotLOp } | ROTROP { RotROp } | CATOP { CatOp } @@ -342,7 +343,8 @@ lit : | ORASSIGN { OrOp } | XORASSIGN { XorOp } | SHLASSIGN { ShLOp } - | SHRASSIGN { ShROp } + | USHRASSIGN { UShROp } + | SSHRASSIGN { SShROp } | ROTLASSIGN { RotLOp } | ROTRASSIGN { RotROp } | CATASSIGN { CatOp } diff --git a/src/prelude.ml b/src/prelude.ml index edd323c96a5..66c84fbbfa4 100644 --- a/src/prelude.ml +++ b/src/prelude.ml @@ -80,25 +80,21 @@ func word32ToChar(w : Word32) : Char = (prim "Word32->Char" : Word32 -> Char) w; func decodeUTF8(s : Text) : (Word32, Char) = (prim "decodeUTF8" : Text -> (Word32, Char)) s; // Exotic bitwise operations -func shrsWord8(w : Word8, amount : Word8) : Word8 = (prim "shrs8" : (Word8, Word8) -> Word8) (w, amount); func popcntWord8(w : Word8) : Word8 = (prim "popcnt8" : Word8 -> Word8) w; func clzWord8(w : Word8) : Word8 = (prim "clz8" : Word8 -> Word8) w; func ctzWord8(w : Word8) : Word8 = (prim "ctz8" : Word8 -> Word8) w; func btstWord8(w : Word8, amount : Word8) : Bool = (prim "btst8" : (Word8, Word8) -> Word8) (w, amount) != (0 : Word8); -func shrsWord16(w : Word16, amount : Word16) : Word16 = (prim "shrs16" : (Word16, Word16) -> Word16) (w, amount); func popcntWord16(w : Word16) : Word16 = (prim "popcnt16" : Word16 -> Word16) w; func clzWord16(w : Word16) : Word16 = (prim "clz16" : Word16 -> Word16) w; func ctzWord16(w : Word16) : Word16 = (prim "ctz16" : Word16 -> Word16) w; func btstWord16(w : Word16, amount : Word16) : Bool = (prim "btst16" : (Word16, Word16) -> Word16) (w, amount) != (0 : Word16); -func shrsWord32(w : Word32, amount : Word32) : Word32 = (prim "shrs" : (Word32, Word32) -> Word32) (w, amount); func popcntWord32(w : Word32) : Word32 = (prim "popcnt" : Word32 -> Word32) w; func clzWord32(w : Word32) : Word32 = (prim "clz" : Word32 -> Word32) w; func ctzWord32(w : Word32) : Word32 = (prim "ctz" : Word32 -> Word32) w; func btstWord32(w : Word32, amount : Word32) : Bool = (prim "btst" : (Word32, Word32) -> Word32) (w, amount) != (0 : Word32); -func shrsWord64(w : Word64, amount : Word64) : Word64 = (prim "shrs64" : (Word64, Word64) -> Word64) (w, amount); func popcntWord64(w : Word64) : Word64 = (prim "popcnt64" : Word64 -> Word64) w; func clzWord64(w : Word64) : Word64 = (prim "clz64" : Word64 -> Word64) w; func ctzWord64(w : Word64) : Word64 = (prim "ctz64" : Word64 -> Word64) w; @@ -303,16 +299,6 @@ let prim = function let i = Conv.of_signed_Word32 (as_word32 v) in k (Char i) - | "shrs8" | "shrs16" | "shrs" | "shrs64" -> - fun v k -> - let w, a = as_pair v - in k (match w with - | Word8 y -> Word8 (Word8 .shr_s y (as_word8 a)) - | Word16 y -> Word16 (Word16.shr_s y (as_word16 a)) - | Word32 y -> Word32 (Word32.shr_s y (as_word32 a)) - | Word64 y -> Word64 (Word64.shr_s y (as_word64 a)) - | _ -> failwith "shrs") - | "popcnt8" | "popcnt16" | "popcnt" | "popcnt64" -> fun v k -> k (match v with diff --git a/src/syntax.ml b/src/syntax.ml index 2901a68acec..bebe28968ea 100644 --- a/src/syntax.ml +++ b/src/syntax.ml @@ -86,7 +86,8 @@ type binop = | OrOp | XorOp | ShLOp - | ShROp + | UShROp + | SShROp | RotLOp | RotROp | CatOp (* concatenation *) diff --git a/test/run/ok/words.run-ir.ok b/test/run/ok/words.run-ir.ok index a3f996d1a6f..2f95577638e 100644 --- a/test/run/ok/words.run-ir.ok +++ b/test/run/ok/words.run-ir.ok @@ -12,6 +12,7 @@ 8908458 8908458 584576 584576 35 35 +826339054743125951 826339054743125951 -2 -2 -326582449863721025 -326582449863721025 1140833920 1140833920 @@ -36,6 +37,7 @@ set 8908458 8908458 584576 584576 35 35 +192397053 192397053 4294967294 -2 4218928893 -76038403 1140833920 1140833920 @@ -60,6 +62,7 @@ set 51297 -14239 60288 -5248 35 35 +8190 8190 65534 -2 56172 -9364 28083 28083 @@ -83,6 +86,7 @@ set 97 97 128 -128 0 0 +30 30 254 -2 17 17 68 68 diff --git a/test/run/ok/words.run-low.ok b/test/run/ok/words.run-low.ok index a3f996d1a6f..2f95577638e 100644 --- a/test/run/ok/words.run-low.ok +++ b/test/run/ok/words.run-low.ok @@ -12,6 +12,7 @@ 8908458 8908458 584576 584576 35 35 +826339054743125951 826339054743125951 -2 -2 -326582449863721025 -326582449863721025 1140833920 1140833920 @@ -36,6 +37,7 @@ set 8908458 8908458 584576 584576 35 35 +192397053 192397053 4294967294 -2 4218928893 -76038403 1140833920 1140833920 @@ -60,6 +62,7 @@ set 51297 -14239 60288 -5248 35 35 +8190 8190 65534 -2 56172 -9364 28083 28083 @@ -83,6 +86,7 @@ set 97 97 128 -128 0 0 +30 30 254 -2 17 17 68 68 diff --git a/test/run/ok/words.run.ok b/test/run/ok/words.run.ok index a3f996d1a6f..2f95577638e 100644 --- a/test/run/ok/words.run.ok +++ b/test/run/ok/words.run.ok @@ -12,6 +12,7 @@ 8908458 8908458 584576 584576 35 35 +826339054743125951 826339054743125951 -2 -2 -326582449863721025 -326582449863721025 1140833920 1140833920 @@ -36,6 +37,7 @@ set 8908458 8908458 584576 584576 35 35 +192397053 192397053 4294967294 -2 4218928893 -76038403 1140833920 1140833920 @@ -60,6 +62,7 @@ set 51297 -14239 60288 -5248 35 35 +8190 8190 65534 -2 56172 -9364 28083 28083 @@ -83,6 +86,7 @@ set 97 97 128 -128 0 0 +30 30 254 -2 17 17 68 68 diff --git a/test/run/words.as b/test/run/words.as index 7f77b256236..d2b9be2ec41 100644 --- a/test/run/words.as +++ b/test/run/words.as @@ -49,8 +49,9 @@ func checkpointJuliett() {}; printW64ln(a ^ c); printW64ln(a << b); printW64ln(a >> b); - printW64ln(shrsWord64(d, 3)); - printW64ln(shrsWord64(-5225319197819536385, 4)); // 0b1011011101111011111011111101111111011111111011111111101111111111L == -5225319197819536385L --> -326582449863721025L + printW64ln(-5225319197819536385 >> 4); // 0b1011011101111011111011111101111111011111111011111111101111111111L == -5225319197819536385L --> 826339054743125951L + printW64ln(d +>> 3); + printW64ln(-5225319197819536385 +>> 4); // 0b1011011101111011111011111101111111011111111011111111101111111111L == -5225319197819536385L --> -326582449863721025L printW64ln(c <<> b); printW64ln(c <>> b); printW64ln(popcntWord64 d); // -15 = 0xfffffffffffffff1 = 0b1111_..._1111_1111_0001 (population = 61) @@ -104,8 +105,9 @@ func checkpointJuliett() {}; printW32ln(a ^ c); printW32ln(a << b); printW32ln(a >> b); - printW32ln(shrsWord32(d, 3)); - printW32ln(shrsWord32(-1216614433, 4)); // 0b10110111011110111110111111011111l == -1216614433l --> -76038403 + printW32ln(-1216614433 >> 4); // 0b10110111011110111110111111011111l == -1216614433l --> 192397053l + printW32ln(d +>> 3); + printW32ln(-1216614433 +>> 4); // 0b10110111011110111110111111011111l == -1216614433l --> -76038403 printW32ln(c <<> b); printW32ln(c <>> b); printW32ln(popcntWord32 d); // -15 = 0xfffffff1 = 0b1111_1111_1111_1111_1111_1111_1111_0001 (population = 29) @@ -171,7 +173,8 @@ func checkpointJuliett() {}; // CHECK-NEXT: i32.and // CHECK-NEXT: call $printW16ln printW16ln(a >> b); - printW16ln(shrsWord16(d, 3 : Word16)); // -15 = 0xfff1 = 0b1111_1111_1111_0001 (shifted = 0b1111_1111_1111_1110 = -2) + printW16ln(d >> 3); // -15 = 0xfff1 = 0b1111_1111_1111_0001 (shifted = 0b0001_1111_1111_1110 = 8190) + printW16ln(d +>> 3); // -15 = 0xfff1 = 0b1111_1111_1111_0001 (shifted = 0b1111_1111_1111_1110 = -2) // CHECK: call $checkpointFoxtrot checkpointFoxtrot(); @@ -248,7 +251,8 @@ func checkpointJuliett() {}; // CHECK-NEXT: i32.and // CHECK-NEXT: call $printW8ln printW8ln(a >> b); - printW8ln(shrsWord8(d, 3 : Word8)); // -15 = 0xf1 = 0b1111_0001 (shifted = 0b1111_1110 = -2) + printW8ln(d >> 3); // -15 = 0xf1 = 0b1111_0001 (shifted = 0b0001_1110 = 30) + printW8ln(d +>> 3); // -15 = 0xf1 = 0b1111_0001 (shifted = 0b1111_1110 = -2) // CHECK: call $checkpointJuliett checkpointJuliett(); From 016fa9b50008b2ee91b1969dabbccf59c3f1581c Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 29 May 2019 11:38:32 +0200 Subject: [PATCH 0103/1176] Build idlc via nix --- default.nix | 60 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 19 deletions(-) diff --git a/default.nix b/default.nix index e3b748ea7c3..f1257bdee5f 100644 --- a/default.nix +++ b/default.nix @@ -51,6 +51,7 @@ let commonBuildInputs = [ nixpkgs.ocamlPackages.findlib nixpkgs.ocamlPackages.ocamlbuild nixpkgs.ocamlPackages.num + nixpkgs.ocamlPackages.stdint ocaml_wasm ocaml_vlq nixpkgs.ocamlPackages.zarith @@ -144,31 +145,26 @@ rec { asc-bin = stdenv.mkDerivation { name = "asc-bin"; - src = sourceByRegex ./. [ - "src/" - "src/Makefile.*" - "src/.*.ml" - "src/.*.mli" - "src/.*.mly" - "src/.*.mll" - "src/.*.mlpack" - "src/_tags" - "test/" - "test/node-test.js" + src = sourceByRegex ./src [ + "Makefile.*" + ".*.ml" + ".*.mli" + ".*.mly" + ".*.mll" + ".*.mlpack" + "_tags" ]; - nativeBuildInputs = [ nixpkgs.makeWrapper ]; - buildInputs = commonBuildInputs; buildPhase = '' - make -C src BUILD=native asc as-ld + make BUILD=native asc as-ld ''; installPhase = '' mkdir -p $out/bin - cp src/asc $out/bin - cp src/as-ld $out/bin + cp asc $out/bin + cp as-ld $out/bin ''; }; @@ -288,23 +284,48 @@ rec { ]; buildPhase = '' - make -C src asc.js + make asc.js ''; installPhase = '' mkdir -p $out - cp -v src/asc.js $out + cp -v asc.js $out cp -vr ${rts}/rts $out ''; doInstallCheck = true; installCheckPhase = '' - NODE_PATH=$out node --experimental-wasm-mut-global --experimental-wasm-mv test/node-test.js + NODE_PATH=$out node --experimental-wasm-mut-global --experimental-wasm-mv ${./test/node-test.js} ''; }); + idlc = stdenv.mkDerivation { + name = "idlc"; + + src = sourceByRegex ./idl [ + "Makefile.*" + ".*.ml" + ".*.mli" + ".*.mly" + ".*.mll" + ".*.mlpack" + "_tags" + ]; + + buildInputs = commonBuildInputs; + + buildPhase = '' + make BUILD=native idlc + ''; + + installPhase = '' + mkdir -p $out/bin + cp idlc $out/bin + ''; + }; + wasm = ocaml_wasm; dvm = real-dvm; filecheck = nixpkgs.linkFarm "FileCheck" @@ -405,6 +426,7 @@ rec { constituents = [ native js + idlc native_test coverage-report rts From 7b19e31bab86790717d700f50750e6051dee8715 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 29 May 2019 12:14:24 +0200 Subject: [PATCH 0104/1176] Move idl test files to `test/idl` just run `make` therein to find out if the `idlc` has changed semantics. Also includes some clean-up on `default.nix`. --- README.md | 2 +- default.nix | 49 ++++++++++++++++++++----------------- test/Makefile | 6 +++-- test/compare-wat.sh | 4 +-- test/idl/Makefile | 12 +++++++++ test/idl/ok/px.idlc.ok | 16 ++++++++++++ test/idl/ok/test.idlc.ok | 40 ++++++++++++++++++++++++++++++ {idl => test/idl}/px.didl | 0 {idl => test/idl}/test.didl | 0 test/run.sh | 13 ++++++++-- 10 files changed, 113 insertions(+), 29 deletions(-) create mode 100644 test/idl/Makefile create mode 100644 test/idl/ok/px.idlc.ok create mode 100644 test/idl/ok/test.idlc.ok rename {idl => test/idl}/px.didl (100%) rename {idl => test/idl}/test.didl (100%) diff --git a/README.md b/README.md index 82c5faec1c8..e5477c84fa8 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ A simple language for writing Dfinity actors. To install the `asc` binary into your nix environment, use ``` -$ nix-env -i -f . -A native +$ nix-env -i -f . -A asc ``` ## Development using Nix diff --git a/default.nix b/default.nix index f1257bdee5f..ee1204e05bf 100644 --- a/default.nix +++ b/default.nix @@ -65,15 +65,16 @@ let "test/" "test/.*Makefile.*" "test/quick.mk" - "test/(fail|run|run-dfinity|repl|ld)/" - "test/(fail|run|run-dfinity|repl|ld)/lib/" - "test/(fail|run|run-dfinity|repl|ld)/lib/dir/" - "test/(fail|run|run-dfinity|repl|ld)/.*.as" - "test/(fail|run|run-dfinity|repl|ld)/.*.sh" - "test/(fail|run|run-dfinity|repl|ld)/[^/]*.wat" - "test/(fail|run|run-dfinity|repl|ld)/[^/]*.c" - "test/(fail|run|run-dfinity|repl|ld)/ok/" - "test/(fail|run|run-dfinity|repl|ld)/ok/.*.ok" + "test/(fail|run|run-dfinity|repl|ld|idl)/" + "test/(fail|run|run-dfinity|repl|ld|idl)/lib/" + "test/(fail|run|run-dfinity|repl|ld|idl)/lib/dir/" + "test/(fail|run|run-dfinity|repl|ld|idl)/.*.as" + "test/(fail|run|run-dfinity|repl|ld|idl)/.*.sh" + "test/(fail|run|run-dfinity|repl|ld|idl)/.*.didl" + "test/(fail|run|run-dfinity|repl|ld|idl)/[^/]*.wat" + "test/(fail|run|run-dfinity|repl|ld|idl)/[^/]*.c" + "test/(fail|run|run-dfinity|repl|ld|idl)/ok/" + "test/(fail|run|run-dfinity|repl|ld|idl)/ok/.*.ok" "test/.*.sh" ]; samples_files = [ @@ -168,7 +169,7 @@ rec { ''; }; - native = nixpkgs.symlinkJoin { + asc = nixpkgs.symlinkJoin { name = "asc"; paths = [ asc-bin rts ]; buildInputs = [ nixpkgs.makeWrapper ]; @@ -178,8 +179,8 @@ rec { ''; }; - native_test = stdenv.mkDerivation { - name = "native.test"; + tests = stdenv.mkDerivation { + name = "tests"; src = sourceByRegex ./. ( test_files ++ @@ -187,7 +188,8 @@ rec { ); buildInputs = - [ native + [ asc + idlc ocaml_wasm nixpkgs.wabt nixpkgs.bash @@ -202,6 +204,7 @@ rec { ${llvmEnv} export ASC=asc export AS_LD=as-ld + export IDLC=idlc asc --version make -C samples all '' + @@ -223,11 +226,12 @@ rec { oldAttrs.buildPhase; installPhase = oldAttrs.installPhase + '' - mv src/ $out/src + # The coverage report needs access to sources, including _build/parser.ml + cp -r . $out/src ''; }); - native-coverage = nixpkgs.symlinkJoin { + asc-coverage = nixpkgs.symlinkJoin { name = "asc-covergage"; paths = [ asc-bin-coverage rts ]; buildInputs = [ nixpkgs.makeWrapper ]; @@ -246,7 +250,7 @@ rec { ); buildInputs = - [ native-coverage + [ asc-coverage nixpkgs.wabt nixpkgs.bash nixpkgs.perl @@ -260,7 +264,7 @@ rec { ${llvmEnv} export ASC=asc export AS_LD=as-ld - ln -vs ${native-coverage}/src src + ln -vs ${asc-coverage}/src src make -C test coverage ''; @@ -405,7 +409,7 @@ rec { ); buildInputs = [ - native + asc ]; doCheck = true; @@ -424,10 +428,10 @@ rec { all-systems-go = nixpkgs.releaseTools.aggregate { name = "all-systems-go"; constituents = [ - native + asc js idlc - native_test + tests coverage-report rts stdlib-reference @@ -447,10 +451,11 @@ rec { # https://github.com/NixOS/nix/issues/955 # - buildInputs = nixpkgs.lib.lists.unique (builtins.filter (i: i != native) ( + buildInputs = nixpkgs.lib.lists.unique (builtins.filter (i: i != asc && i != idlc) ( asc-bin.buildInputs ++ rts.buildInputs ++ - native_test.buildInputs ++ + idlc.buildInputs ++ + tests.buildInputs ++ users-guide.buildInputs ++ [ nixpkgs.ncurses nixpkgs.ocamlPackages.merlin ] )); diff --git a/test/Makefile b/test/Makefile index 00e071270a6..b269a546ef2 100644 --- a/test/Makefile +++ b/test/Makefile @@ -4,6 +4,7 @@ all: $(MAKE) -C run-dfinity $(MAKE) -C repl $(MAKE) -C ld + $(MAKE) -C idl MAKE_PAR := $(MAKE) --no-print-directory --load-average -j $(shell getconf _NPROCESSORS_ONLN) --keep-going @@ -12,6 +13,7 @@ quick: $(MAKE_PAR) -C run quick $(MAKE_PAR) -C repl quick $(MAKE_PAR) -C ld quick + $(MAKE_PAR) -C idl quick parallel: quick $(MAKE_PAR) -C run-dfinity quick @@ -29,14 +31,13 @@ coverage: bisect-ppx-report -I ../src/_build/ -html coverage/ _coverage/bisect*.out rm -rf _coverage - - accept: $(MAKE) -C fail accept $(MAKE) -C run accept $(MAKE) -C run-dfinity accept $(MAKE) -C repl accept $(MAKE) -C ld accept + $(MAKE) -C idl accept clean: $(MAKE) -C fail clean @@ -44,5 +45,6 @@ clean: $(MAKE) -C run-dfinity clean $(MAKE) -C repl clean $(MAKE) -C ld clean + $(MAKE) -C idl clean .PHONY: coverage diff --git a/test/compare-wat.sh b/test/compare-wat.sh index 27e7c8b8a5d..70965888d0c 100755 --- a/test/compare-wat.sh +++ b/test/compare-wat.sh @@ -28,7 +28,7 @@ function build_ref_to { if [ -z "$1" ] then echo "Building $2 asc from working copy.." - chronic nix-build -E '((import ./..) {}).native' \ + chronic nix-build -E '((import ./..) {}).asc' \ --option binary-caches '' \ -o $2-asc/ else @@ -42,7 +42,7 @@ function build_ref_to { let nixpkg = import (../nix/nixpkgs.nix).nixpkgs {}; in let checkout = (builtins.fetchGit {url = path; ref = ref; rev = rev; name = "old-asc";}).outPath; in builtins.trace checkout ( - ((import checkout) {}).native)' \ + ((import checkout) {}).asc)' \ --option binary-caches '' \ -o $2-asc/ fi diff --git a/test/idl/Makefile b/test/idl/Makefile new file mode 100644 index 00000000000..9c06507358f --- /dev/null +++ b/test/idl/Makefile @@ -0,0 +1,12 @@ +RUNFLAGS = + +all: + ../run.sh $(RUNFLAGS) *.didl + +accept: + ../run.sh $(RUNFLAGS) -a *.didl + +clean: + rm -rf _out + +include ../*.mk diff --git a/test/idl/ok/px.idlc.ok b/test/idl/ok/px.idlc.ok new file mode 100644 index 00000000000..bbc8019ccf4 --- /dev/null +++ b/test/idl/ok/px.idlc.ok @@ -0,0 +1,16 @@ +const RegionId = IDL.nat +const UserId = IDL.nat +const TruckTypeId = IDL.nat +const ProducerId = IDL.nat +const UserInfo = + IDL.Obj({'id': UserId, 'public_key': IDL.text, 'user_name': IDL.text, + 'description': IDL.text, 'region': RegionId, + 'produceId': IDL.Opt(ProducerId)}) +const EntId = + IDL.Obj({'user': UserId, 'truckType': TruckTypeId, 'region': RegionId}) +const OpEntId = IDL.Opt(EntId) +const IdErr = IDL.Obj({'idErr': OpEntId}) +const Inventory = IDL.Obj({'produce_id': IDL.nat, 'quantity': IDL.nat}) +const ProduceExchange = new IDL.ActorInterface({ + getInventory: + IDL.message(IDL.Obj({'producer_id': IDL.nat}), IDL.Obj({'0': Inventory}))}) diff --git a/test/idl/ok/test.idlc.ok b/test/idl/ok/test.idlc.ok new file mode 100644 index 00000000000..0bbd4a5bfaa --- /dev/null +++ b/test/idl/ok/test.idlc.ok @@ -0,0 +1,40 @@ +const my_type = IDL.nat +const B = my_type +const C = E +const E = IDL.Opt(C) +const node = IDL.Obj({'head': IDL.nat, 'tail': list}) +const list = IDL.Opt(node) +const enum = + IDL.Variant({'red': IDL.null, 'blue': IDL.null, 'green': IDL.null}) +const message = IDL.Obj({'name': IDL.text, '25': C, '26': IDL.reserved}) +const test = + IDL.Obj({'0': IDL.nat, '1': IDL.nat, '2': IDL.nat, '99': IDL.nat, + '100': IDL.nat, 'named_field': IDL.nat, '108546619': IDL.nat, + '108546620': IDL.nat, '108546621': IDL.nat}) +const nest_record = + IDL.Obj({'0': IDL.nat, '1': IDL.nat, '2': IDL.nat, + '3': IDL.Obj({'0': IDL.nat, '1': IDL.nat, '2': IDL.nat}), '4': IDL.nat, + '5': IDL.nat, '6': IDL.nat}) +const tree = + IDL.Variant({'leaf': IDL.int, + 'branch': IDL.Obj({'left': tree, 'val': IDL.int, 'right': tree})}) +const s = IDL.ActorInterface({f: t}) +const t = IDL.message(IDL.Obj({'server': s}), IDL.Obj({})) +const broker = + IDL.ActorInterface({ + find: + IDL.message(IDL.Obj({'name': IDL.text}), + IDL.Obj({ + '0': + IDL.ActorInterface({up: IDL.message(IDL.Obj({}), IDL.Obj({})), + current: IDL.message(IDL.Obj({}), IDL.Obj({'0': IDL.nat}))}) + })) + }) +const stream = + IDL.Opt( + IDL.Obj({'head': IDL.nat, + 'next': IDL.message(IDL.Obj({}), IDL.Obj({'0': stream}))})) + +const user = new IDL.ActorInterface({ + addUser: IDL.message(IDL.Obj({'0': IDL.nat}), IDL.Obj({'0': my_type})), + userName: IDL.message(IDL.Obj({'0': IDL.nat}), IDL.Obj({'0': stream}))}) diff --git a/idl/px.didl b/test/idl/px.didl similarity index 100% rename from idl/px.didl rename to test/idl/px.didl diff --git a/idl/test.didl b/test/idl/test.didl similarity index 100% rename from idl/test.didl rename to test/idl/test.didl diff --git a/test/run.sh b/test/run.sh index 9157165b64e..54057dccd3b 100755 --- a/test/run.sh +++ b/test/run.sh @@ -21,6 +21,7 @@ DFINITY=no EXTRA_ASC_FLAGS= ASC=${ASC:-$(realpath $(dirname $0)/../src/asc)} AS_LD=${AS_LD:-$(realpath $(dirname $0)/../src/as-ld)} +IDLC=${IDLC:-$(realpath $(dirname $0)/../idl/idlc)} export AS_LD WASM=${WASM:-wasm} DVM_WRAPPER=$(realpath $(dirname $0)/dvm.sh) @@ -80,8 +81,10 @@ do then base=$(basename $file .sh) elif [ ${file: -4} == ".wat" ] then base=$(basename $file .wat) + elif [ ${file: -5} == ".didl" ] + then base=$(basename $file .didl) else - echo "Unknown file extension in $file, expected .as, .sh or .wat"; exit 1 + echo "Unknown file extension in $file, expected .as, .sh, .wat or .didl"; exit 1 failures=yes continue fi @@ -191,7 +194,8 @@ do $ECHO -n " [out]" ./$(basename $file) > $out/$base.stdout 2> $out/$base.stderr diff_files="$diff_files $base.stdout $base.stderr" - else + elif [ ${file: -4} == ".wat" ] + then # The file is a .wat file, so we are expected to test linking $ECHO -n " [as-ld]" rm -f $out/$base.{base,lib,linked}.{wasm,wat,o} @@ -206,6 +210,11 @@ do diff_files="$diff_files $base.linked.wat $base.linked.wat.stderr" fi + else + # The file is a .didl file, so we are expected to test the idl + $ECHO -n " [idlc]" + $IDLC $base.didl > $out/$base.idlc 2>&1 + diff_files="$diff_files $base.idlc" fi $ECHO "" From e38d24cdcac3d0e05012254f1794a8e732d9785c Mon Sep 17 00:00:00 2001 From: Paul Young Date: Wed, 29 May 2019 11:33:48 -0700 Subject: [PATCH 0105/1176] Remove TODO --- src/languageServer.ml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/languageServer.ml b/src/languageServer.ml index 92be71446c9..4131e111e10 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -35,7 +35,6 @@ let send (label: string) (out: string): unit = let send_response: string -> unit = send "response" let send_notification: string -> unit = send "notification" -(* TODO: pass type, use a variant *) let show_message (typ : Lsp.MessageType.t) (msg: string): unit = let params = `WindowShowMessage From cbcdd7a0b69020bbd20b017daf75eac5c8334aeb Mon Sep 17 00:00:00 2001 From: Paul Young Date: Wed, 29 May 2019 12:00:29 -0700 Subject: [PATCH 0106/1176] Prevent writing log file for other commands --- src/languageServer.ml | 71 ++++++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 32 deletions(-) diff --git a/src/languageServer.ml b/src/languageServer.ml index 4131e111e10..55e91984d13 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -17,33 +17,41 @@ let response_result_message (id : int) (result : Lsp_t.response_result) : Lsp_t. (* let response_error_message (id : int) (error : Lsp_t.response_error) : Lsp_t.response_message = *) - -let oc: out_channel = open_out_gen [Open_append; Open_creat] 0o666 "ls.log" -let log_to_file (lbl: string) (txt: string): unit = +module Channel = struct + let log_to_file (oc : out_channel) (lbl : string) (txt : string) : unit = Printf.fprintf oc "[%s] %s\n" lbl txt; flush oc -let send (label: string) (out: string): unit = - let cl = "Content-Length: " ^ string_of_int (String.length out) in - print_string cl; - print_string "\r\n\r\n"; - print_string out; - flush stdout; - log_to_file (label ^ "_length") cl; - log_to_file label out - -let send_response: string -> unit = send "response" -let send_notification: string -> unit = send "notification" - -let show_message (typ : Lsp.MessageType.t) (msg: string): unit = - let params = - `WindowShowMessage - (Lsp_t. - { window_show_message_params_type_ = typ - ; window_show_message_params_message = msg - }) in - let notification = notification params in - send_notification (Lsp_j.string_of_notification_message notification) + let send (oc : out_channel) (label : string) (out : string) : unit = + let cl = "Content-Length: " ^ string_of_int (String.length out) in + print_string cl; + print_string "\r\n\r\n"; + print_string out; + flush stdout; + log_to_file oc (label ^ "_length") cl; + log_to_file oc label out + + let send_response (oc : out_channel) : string -> unit = send oc "response" + let send_notification (oc : out_channel) : string -> unit = send oc "notification" + + let show_message (oc : out_channel) (typ : Lsp.MessageType.t) (msg: string): unit = + let params = + `WindowShowMessage + (Lsp_t. + { window_show_message_params_type_ = typ + ; window_show_message_params_message = msg + }) in + let notification = notification params in + send_notification oc (Lsp_j.string_of_notification_message notification) + + let publish_diagnostics (oc : out_channel) (uri: Lsp_t.document_uri) (diags: Lsp_t.diagnostic list): unit = + let params = `PublishDiagnostics (Lsp_t. + { publish_diagnostics_params_uri = uri + ; publish_diagnostics_params_diagnostics = diags + }) in + let notification = notification params in + send_notification oc (Lsp_j.string_of_notification_message notification) +end let position_of_pos (pos: Source.pos): Lsp_t.position = Lsp_t. (* The LSP spec requires zero-based positions *) @@ -70,17 +78,16 @@ let diagnostics_of_message (msg: Diag.message): Lsp_t.diagnostic = Lsp_t. ; diagnostic_relatedInformation = None } -let publish_diagnostics (uri: Lsp_t.document_uri) (diags: Lsp_t.diagnostic list): unit = - let params = `PublishDiagnostics (Lsp_t. - { publish_diagnostics_params_uri = uri - ; publish_diagnostics_params_diagnostics = diags - }) in - let notification = notification params in - send_notification (Lsp_j.string_of_notification_message notification) - let file_uri_prefix = "file://" ^ Sys.getcwd () ^ "/" let start () = + let oc: out_channel = open_out_gen [Open_append; Open_creat] 0o666 "ls.log"; in + + let log_to_file = Channel.log_to_file oc in + let publish_diagnostics = Channel.publish_diagnostics oc in + let send_response = Channel.send_response oc in + let show_message = Channel.show_message oc in + let client_capabilities = ref None in let rec loop () = From 9816407de4c10389fa7fe28bd6b6dc6308d53ec4 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 30 May 2019 23:30:57 +0200 Subject: [PATCH 0107/1176] Typing: Do not report inconsistent types if env.pre (#454) fixes #442. --- src/typing.ml | 13 +++++++------ test/fail/ok/type-inference.tc.ok | 30 ----------------------------- test/run/issue442.as | 2 ++ test/run/ok/issue442.run-ir.ok | 6 ++++++ test/run/ok/issue442.run-low.ok | 6 ++++++ test/run/ok/issue442.run.ok | 6 ++++++ test/run/ok/issue442.tc.ok | 6 ++++++ test/run/ok/issue442.wasm.stderr.ok | 6 ++++++ 8 files changed, 39 insertions(+), 36 deletions(-) create mode 100644 test/run/issue442.as create mode 100644 test/run/ok/issue442.run-ir.ok create mode 100644 test/run/ok/issue442.run-low.ok create mode 100644 test/run/ok/issue442.run.ok create mode 100644 test/run/ok/issue442.tc.ok create mode 100644 test/run/ok/issue442.wasm.stderr.ok diff --git a/src/typing.ml b/src/typing.ml index 99f0f97d77d..e43c8bf8ba6 100644 --- a/src/typing.ml +++ b/src/typing.ml @@ -554,7 +554,7 @@ and infer_exp'' env exp : T.typ = | ArrayE (mut, exps) -> let ts = List.map (infer_exp env) exps in let t1 = List.fold_left T.lub T.Non ts in - if t1 = T.Any && List.for_all (fun t -> T.promote t <> T.Any) ts then + if not env.pre && t1 = T.Any && List.for_all (fun t -> T.promote t <> T.Any) ts then warn env exp.at "this array has type %s because elements have inconsistent types" (T.string_of_typ (T.Array t1)); @@ -670,7 +670,7 @@ and infer_exp'' env exp : T.typ = let t2 = infer_exp env exp2 in let t3 = infer_exp env exp3 in let t = T.lub t2 t3 in - if t = T.Any && T.promote t2 <> T.Any && T.promote t3 <> T.Any then + if not env.pre && t = T.Any && T.promote t2 <> T.Any && T.promote t3 <> T.Any then warn env exp.at "this if has type %s because branches have inconsistent types,\ntrue produces\n %s\nfalse produces\n %s" (T.string_of_typ t) @@ -834,9 +834,10 @@ and check_exp' env t exp : T.typ = | SwitchE (exp1, cases), _ -> let t1 = infer_exp_promote env exp1 in check_cases env t1 t cases; - if not (Coverage.check_cases cases t1) then - warn env exp.at - "the cases in this switch do not cover all possible values"; + if not env.pre then + if not (Coverage.check_cases cases t1) then + warn env exp.at + "the cases in this switch do not cover all possible values"; t | _ -> let t' = infer_exp env exp in @@ -857,7 +858,7 @@ and infer_case env t_pat t {it = {pat; exp}; at; _} = let ve = check_pat env t_pat pat in let t' = recover_with T.Non (infer_exp (adjoin_vals env ve)) exp in let t'' = T.lub t t' in - if t'' = T.Any && T.promote t <> T.Any && T.promote t' <> T.Any then + if not env.pre && t'' = T.Any && T.promote t <> T.Any && T.promote t' <> T.Any then warn env at "the switch has type %s because branches have inconsistent types,\nthis case produces type\n %s\nthe previous produce type\n %s" (T.string_of_typ t'') (T.string_of_typ_expand t) diff --git a/test/fail/ok/type-inference.tc.ok b/test/fail/ok/type-inference.tc.ok index d415b3da3e8..26ad31a9324 100644 --- a/test/fail/ok/type-inference.tc.ok +++ b/test/fail/ok/type-inference.tc.ok @@ -24,36 +24,6 @@ this case produces type the previous produce type Nat type-inference.as:18.43-18.56: warning, the switch has type Any because branches have inconsistent types, -this case produces type - Int -the previous produce type - Text -type-inference.as:10.9-10.28: warning, this if has type Any because branches have inconsistent types, -true produces - Bool -false produces - Nat -type-inference.as:11.9-11.27: warning, this if has type Any because branches have inconsistent types, -true produces - Nat -false produces - Float -type-inference.as:12.9-12.33: warning, this if has type Any because branches have inconsistent types, -true produces - () -false produces - {} -type-inference.as:13.9-13.53: warning, this if has type Any because branches have inconsistent types, -true produces - {x : Nat} -false produces - {x : var Nat} -type-inference.as:17.33-17.41: warning, the switch has type Any because branches have inconsistent types, -this case produces type - Bool -the previous produce type - Nat -type-inference.as:18.43-18.56: warning, the switch has type Any because branches have inconsistent types, this case produces type Int the previous produce type diff --git a/test/run/issue442.as b/test/run/issue442.as new file mode 100644 index 00000000000..decc4e2230e --- /dev/null +++ b/test/run/issue442.as @@ -0,0 +1,2 @@ +let foo = [1, true, ""]; +let bar = if true 1 else "2"; diff --git a/test/run/ok/issue442.run-ir.ok b/test/run/ok/issue442.run-ir.ok new file mode 100644 index 00000000000..136d5ad0c79 --- /dev/null +++ b/test/run/ok/issue442.run-ir.ok @@ -0,0 +1,6 @@ +issue442.as:1.11-1.24: warning, this array has type [Any] because elements have inconsistent types +issue442.as:2.11-2.29: warning, this if has type Any because branches have inconsistent types, +true produces + Nat +false produces + Text diff --git a/test/run/ok/issue442.run-low.ok b/test/run/ok/issue442.run-low.ok new file mode 100644 index 00000000000..136d5ad0c79 --- /dev/null +++ b/test/run/ok/issue442.run-low.ok @@ -0,0 +1,6 @@ +issue442.as:1.11-1.24: warning, this array has type [Any] because elements have inconsistent types +issue442.as:2.11-2.29: warning, this if has type Any because branches have inconsistent types, +true produces + Nat +false produces + Text diff --git a/test/run/ok/issue442.run.ok b/test/run/ok/issue442.run.ok new file mode 100644 index 00000000000..136d5ad0c79 --- /dev/null +++ b/test/run/ok/issue442.run.ok @@ -0,0 +1,6 @@ +issue442.as:1.11-1.24: warning, this array has type [Any] because elements have inconsistent types +issue442.as:2.11-2.29: warning, this if has type Any because branches have inconsistent types, +true produces + Nat +false produces + Text diff --git a/test/run/ok/issue442.tc.ok b/test/run/ok/issue442.tc.ok new file mode 100644 index 00000000000..136d5ad0c79 --- /dev/null +++ b/test/run/ok/issue442.tc.ok @@ -0,0 +1,6 @@ +issue442.as:1.11-1.24: warning, this array has type [Any] because elements have inconsistent types +issue442.as:2.11-2.29: warning, this if has type Any because branches have inconsistent types, +true produces + Nat +false produces + Text diff --git a/test/run/ok/issue442.wasm.stderr.ok b/test/run/ok/issue442.wasm.stderr.ok new file mode 100644 index 00000000000..136d5ad0c79 --- /dev/null +++ b/test/run/ok/issue442.wasm.stderr.ok @@ -0,0 +1,6 @@ +issue442.as:1.11-1.24: warning, this array has type [Any] because elements have inconsistent types +issue442.as:2.11-2.29: warning, this if has type Any because branches have inconsistent types, +true produces + Nat +false produces + Text From 68131883b281bb3806587eb3f5d970bc57921f5c Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 30 May 2019 16:41:50 -0600 Subject: [PATCH 0108/1176] efficient toArray, via indexed-projection, via cached counts --- stdlib/trie2.as | 497 +++++++++++++++++++++++++++++++----------------- 1 file changed, 323 insertions(+), 174 deletions(-) diff --git a/stdlib/trie2.as b/stdlib/trie2.as index 69fea722397..3cdb265fb1e 100644 --- a/stdlib/trie2.as +++ b/stdlib/trie2.as @@ -1,3 +1,4 @@ +module{ /** Hash tries @@ -30,12 +31,26 @@ Below, we define the types used in the representation: - **`Key`**, parameterized by a hashable type `K` + + ### Cached counts + + At each branch and leaf, we use a stored count to support a +memory-efficient `toArray` function, which itself relies on +per-element projection via `nth`; in turn, `nth` directly uses the +O(1)-time function `count` for achieving an acceptable level of +algorithmic efficiently. Notably, leaves are generally lists of +key-value pairs, and we do not store a count for each Cons cell in the +list. + + See the full details in the definitions below: */ let P = (import "prelude.as"); +let Option = import "option.as"; + let Hash = (import "hash.as").BitVec; type Hash = Hash.t; @@ -60,10 +75,21 @@ func keyEq(keq:(K,K) -> Bool) : ((Key,Key) -> Bool) = { (Hash.hashEq(key1.hash, key2.hash) and keq(key1.key, key2.key)) }; +type Leaf = { + count : Nat ; + keyvals : AssocList,V> ; +}; + +type Branch = { + count : Nat ; + left : Trie ; + right : Trie ; +}; + type Trie = { #empty ; - #leaf : AssocList,V> ; - #branch : (Trie, Trie) ; + #leaf : Leaf ; + #branch : Branch ; }; /** @@ -94,6 +120,71 @@ type Trie3D = Trie >; */ func empty() : Trie = #empty; + /** + `count` + -------- + Get the number of key-value pairs in the trie, in constant time. + + ### Implementation notes + + `nth` directly uses this function `count` for achieving an + acceptable level of algorithmic efficiently. + + */ + func count(t: Trie) : Nat { + switch t { + case (#empty) 0; + case (#leaf l) l.count; + case (#branch b) b.count; + } + }; + + + /** + `branch` + -------- + Construct a branch node, computing the count stored there. + */ + func branch(l:Trie, r:Trie) : Trie { + // note: need to rename the `count` function, because otherwise AS + // is confused by what looks like a recursive definition below for + // the field `count`. + func c(t:Trie) : Nat = count(t); + #branch( + new{ + count=c(l) + c(r); + left=l; + right=r + } + ) + }; + + /** + `leaf` + -------- + Construct a leaf node, computing the count stored there. + */ + func leaf(al:AssocList,V>) : Trie { + #leaf( + new{ + count=List.len<(Key,V)>(al); + keyvals=al + }) + }; + + // /** + // `count` + // -------- + // Count the number of entries in the trie. + // */ + // func count(t:Trie):Nat{ + // foldUp + // (t, + // func(n:Nat,m:Nat):Nat{n+m}, + // func(_:K,_:V):Nat{1}, + // 0) + // }; + /** `copy` --------- @@ -112,24 +203,24 @@ type Trie3D = Trie >; switch t { case (#empty) { let (kvs, _) = AssocList.replace,V>(null, k, key_eq, v); - ((#leaf(kvs)), null) + ((leaf(kvs)), null) }; case (#branch b) { let bit = Hash.getHashBit(k.hash, bitpos); // rebuild either the left or right path with the inserted (k,v) pair if (not bit) { - let (l, v_) = rec(b.0, bitpos+1); - (#branch(l, b.1), v_) + let (l, v_) = rec(b.left, bitpos+1); + (branch(l, b.right), v_) } else { - let (r, v_) = rec(b.1, bitpos+1); - (#branch(b.0, r), v_) + let (r, v_) = rec(b.right, bitpos+1); + (branch(b.left, r), v_) } }; - case (#leaf al) { + case (#leaf l) { let (kvs2, old_val) = - AssocList.replace,V>(al, k, key_eq, v); - (#leaf(kvs2), old_val) + AssocList.replace,V>(l.keyvals, k, key_eq, v); + (leaf(kvs2), old_val) }; } }; @@ -145,7 +236,7 @@ type Trie3D = Trie >; replace(t, k, k_eq, ?v) }; - /** +/** `find` --------- find the given key's value in the trie, or return null if nonexistent @@ -154,24 +245,24 @@ type Trie3D = Trie >; let key_eq = keyEq(k_eq); func rec(t : Trie, bitpos:Nat) : ?V = label profile_trie_find_rec : (?V) { switch t { - case (#empty) { + case (#empty) { label profile_trie_find_end_null : (?V) - null + null }; - case (#leaf as) { + case (#leaf l) { label profile_trie_find_end_assocList_find : (?V) - AssocList.find,V>(as, k, key_eq) + AssocList.find,V>(l.keyvals, k, key_eq) }; - case (#branch(l,r)) { + case (#branch b) { let bit = Hash.getHashBit(k.hash, bitpos); - if (not bit) { - label profile_trie_find_branch_left : (?V) - rec(l, bitpos+1) + if (not bit) { + label profile_trie_find_branch_left : (?V) + rec(b.left, bitpos+1) } - else { + else { label profile_trie_find_branch_right : (?V) - rec(r, bitpos+1) - } + rec(b.right, bitpos+1) + } }; } }; @@ -180,17 +271,19 @@ type Trie3D = Trie >; }; - func splitAssocList(al:AssocList,V>, bitpos:Nat) - : (AssocList,V>, AssocList,V>) + + + func splitAssocList(al:AssocList,V>, bitpos:Nat) + : (AssocList,V>, AssocList,V>) { List.split<(Key,V)>( - al, - func ((k : Key, v : V)) : Bool{ + al, + func ((k : Key, v : V)) : Bool{ Hash.getHashBit(k.hash, bitpos) } - ) + ) }; - + /** `merge` --------- @@ -208,14 +301,16 @@ type Trie3D = Trie >; */ func merge(tl:Trie, tr:Trie, k_eq:(K,K)->Bool): Trie { let key_eq = keyEq(k_eq); + func br(l:Trie, r:Trie) : Trie = branch(l,r); + func lf(kvs:AssocList,V>) : Trie = leaf(kvs); func rec(bitpos:Nat, tl:Trie, tr:Trie) : Trie { switch (tl, tr) { case (#empty, _) { return tr }; case (_, #empty) { return tl }; - case (#leaf as, #leaf bs) { - #leaf( + case (#leaf l1, #leaf l2) { + lf( AssocList.disj,V,V,V>( - as, bs, + l1.keyvals, l2.keyvals, key_eq, func (x:?V, y:?V):V = { switch (x, y) { @@ -226,17 +321,17 @@ type Trie3D = Trie >; ) ) }; - case (#leaf al, _) { - let (l,r) = splitAssocList(al, bitpos); - rec(bitpos, #branch(#leaf l, #leaf r), tr) + case (#leaf l, _) { + let (ll, lr) = splitAssocList(l.keyvals, bitpos); + rec(bitpos, br(lf ll, lf lr), tr) }; - case (_, #leaf al) { - let (l,r) = splitAssocList(al, bitpos); - rec(bitpos, tl, #branch(#leaf l, #leaf r)) + case (_, #leaf l) { + let (ll, lr) = splitAssocList(l.keyvals, bitpos); + rec(bitpos, tl, br(lf ll, lf lr)) }; - case (#branch (ll, lr), #branch(rl, rr)) { - #branch(rec(bitpos + 1, ll, rl), - rec(bitpos + 1, lr, rr)) + case (#branch b1, #branch b2) { + br(rec(bitpos + 1, b1.left, b2.left), + rec(bitpos + 1, b1.right, b2.right)) }; } }; @@ -252,20 +347,22 @@ type Trie3D = Trie >; */ func mergeDisjoint(tl:Trie, tr:Trie, k_eq:(K,K)->Bool): Trie { let key_eq = keyEq(k_eq); + func br(l:Trie, r:Trie) : Trie = branch(l,r); + func lf(kvs:AssocList,V>) : Trie = leaf(kvs); func rec(bitpos:Nat, tl:Trie, tr:Trie) : Trie { switch (tl, tr) { case (#empty, _) { return tr }; case (_, #empty) { return tl }; - case (#leaf as, #leaf bs) { - #leaf( + case (#leaf l1, #leaf l2) { + lf( AssocList.disj,V,V,V>( - as, bs, + l1.keyvals, l2.keyvals, key_eq, func (x:?V, y:?V):V = { switch (x, y) { case (null, null) { /* IMPOSSIBLE case. */ - P.unreachable() + P.unreachable() }; case (?_, ?_) { /* INVALID case: left and right defined for the same key */ @@ -278,18 +375,19 @@ type Trie3D = Trie >; ) ) }; - case (#leaf al, _) { - let (l,r) = splitAssocList(al, bitpos); - rec(bitpos, #branch(#leaf l, #leaf r), tr) + case (#leaf l, _) { + let (ll, lr) = splitAssocList(l.keyvals, bitpos); + rec(bitpos, br(lf ll, lf lr), tr) }; - case (_, #leaf al) { - let (l,r) = splitAssocList(al, bitpos); - rec(bitpos, tl, #branch(#leaf l, #leaf r)) + case (_, #leaf l) { + let (ll, lr) = splitAssocList(l.keyvals, bitpos); + rec(bitpos, tl, br(lf ll, lf lr)) }; - case (#branch (ll, lr), #branch(rl, rr)) { - #branch(rec(bitpos + 1, ll, rl), - rec(bitpos + 1, lr, rr)) + case (#branch b1, #branch b2) { + br(rec(bitpos + 1, b1.left, b2.left), + rec(bitpos + 1, b1.right, b2.right)) }; + } }; rec(0, tl, tr) @@ -304,36 +402,42 @@ type Trie3D = Trie >; */ func diff(tl:Trie, tr:Trie, k_eq:(K,K)->Bool): Trie { let key_eq = keyEq(k_eq); + + func br1(l:Trie, r:Trie) : Trie = branch(l,r); + func lf1(kvs:AssocList,V>) : Trie = leaf(kvs); + + func br2(l:Trie, r:Trie) : Trie = branch(l,r); + func lf2(kvs:AssocList,W>) : Trie = leaf(kvs); + func rec(bitpos:Nat, tl:Trie, tr:Trie) : Trie { switch (tl, tr) { case (#empty, _) { return #empty }; case (_, #empty) { return tl }; - case (#leaf as, #leaf bs) { - #leaf( + case (#leaf l1, #leaf l2) { + lf1( AssocList.diff,V,W>( - as, bs, + l1.keyvals, l2.keyvals, key_eq, ) ) }; - case (#leaf al, _) { - let (l,r) = splitAssocList(al, bitpos); - rec(bitpos, #branch(#leaf l, #leaf r), tr) + case (#leaf l, _) { + let (ll, lr) = splitAssocList(l.keyvals, bitpos); + rec(bitpos, br1(lf1 ll, lf1 lr), tr) }; - case (_, #leaf al) { - let (l,r) = splitAssocList(al, bitpos); - rec(bitpos, tl, #branch(#leaf l, #leaf r)) + case (_, #leaf l) { + let (ll, lr) = splitAssocList(l.keyvals, bitpos); + rec(bitpos, tl, br2(lf2 ll, lf2 lr)) }; - case (#branch (ll, lr), #branch(rl, rr)) { - #branch(rec(bitpos + 1, ll, rl), - rec(bitpos + 1, lr, rr)) + case (#branch b1, #branch b2) { + br1(rec(bitpos + 1, b1.left, b2.left), + rec(bitpos + 1, b1.right, b2.right)) }; } }; rec(0, tl, tr) }; - /** `disj` -------- @@ -358,57 +462,72 @@ type Trie3D = Trie >; */ func disj( - tl : Trie, + tl : Trie, tr : Trie, - k_eq : (K,K)->Bool, + k_eq : (K,K)->Bool, vbin : (?V,?W)->X ) : Trie { let key_eq = keyEq(k_eq); + + func br1(l:Trie, r:Trie) : Trie = branch(l,r); + func lf1(kvs:AssocList,V>) : Trie = leaf(kvs); + + func br2(l:Trie, r:Trie) : Trie = branch(l,r); + func lf2(kvs:AssocList,W>) : Trie = leaf(kvs); + + func br3(l:Trie, r:Trie) : Trie = branch(l,r); + func lf3(kvs:AssocList,X>) : Trie = leaf(kvs); + + /** empty right case; build from left only: */ func recL(t:Trie) : Trie { switch t { case (#empty) #empty; - case (#leaf as) { - #leaf(AssocList.disj,V,W,X>(as, null, key_eq, vbin)) + case (#leaf l) { + lf3(AssocList.disj,V,W,X>(l.keyvals, null, key_eq, vbin)) }; - case (#branch(l,r)) { #branch(recL(l),recL(r)) }; + case (#branch(b)) { br3(recL(b.left),recL(b.right)) }; } }; + /** empty left case; build from right only: */ func recR(t:Trie) : Trie { switch t { case (#empty) #empty; - case (#leaf as) { - #leaf(AssocList.disj,V,W,X>(null, as, key_eq, vbin)) + case (#leaf l) { + lf3(AssocList.disj,V,W,X>(null, l.keyvals, key_eq, vbin)) }; - case (#branch(l,r)) { #branch(recR(l),recR(r)) }; + case (#branch(b)) { br3(recR(b.left),recR(b.right)) }; } }; + + /** main recursion */ func rec(bitpos:Nat, tl:Trie, tr:Trie) : Trie { switch (tl, tr) { case (#empty, #empty) { #empty }; case (#empty, _ ) { recR(tr) }; case (_, #empty) { recL(tl) }; - case (#leaf as, #leaf bs) { - #leaf(AssocList.disj,V,W,X>(as, bs, key_eq, vbin)) + case (#leaf l1, #leaf l2) { + lf3(AssocList.disj,V,W,X>(l1.keyvals, l2.keyvals, key_eq, vbin)) }; - case (#leaf al, _) { - let (l,r) = splitAssocList(al, bitpos); - rec(bitpos, #branch(#leaf l, #leaf r), tr) + case (#leaf l, _) { + let (ll, lr) = splitAssocList(l.keyvals, bitpos); + rec(bitpos, br1(lf1 ll, lf1 lr), tr) }; - case (_, #leaf al) { - let (l,r) = splitAssocList(al, bitpos); - rec(bitpos, tl, #branch(#leaf l, #leaf r)) + case (_, #leaf l) { + let (ll, lr) = splitAssocList(l.keyvals, bitpos); + rec(bitpos, tl, br2(lf2 ll, lf2 lr)) }; - case (#branch (ll, lr), #branch(rl, rr)) { - #branch(rec(bitpos + 1, ll, rl), - rec(bitpos + 1, lr, rr)) + case (#branch b1, #branch b2) { + br3(rec(bitpos + 1, b1.left, b2.left), + rec(bitpos + 1, b1.right, b2.right)) }; + } }; + rec(0, tl, tr) }; - /** `join` @@ -432,31 +551,41 @@ type Trie3D = Trie >; : Trie { let key_eq = keyEq(k_eq); + + func br1(l:Trie, r:Trie) : Trie = branch(l,r); + func lf1(kvs:AssocList,V>) : Trie = leaf(kvs); + + func br2(l:Trie, r:Trie) : Trie = branch(l,r); + func lf2(kvs:AssocList,W>) : Trie = leaf(kvs); + + func br3(l:Trie, r:Trie) : Trie = branch(l,r); + func lf3(kvs:AssocList,X>) : Trie = leaf(kvs); + func rec(bitpos:Nat, tl:Trie, tr:Trie) : Trie { switch (tl, tr) { case (#empty, _) { #empty }; case (_, #empty) { #empty }; - case (#leaf as, #leaf bs) { - #leaf(AssocList.join,V,W,X>(as, bs, key_eq, vbin)) + case (#leaf l1, #leaf l2) { + lf3(AssocList.join,V,W,X>(l1.keyvals, l2.keyvals, key_eq, vbin)) }; - case (#leaf al, _) { - let (l,r) = splitAssocList(al, bitpos); - rec(bitpos, #branch(#leaf l, #leaf r), tr) + case (#leaf l, _) { + let (ll, lr) = splitAssocList(l.keyvals, bitpos); + rec(bitpos, br1(lf1 ll, lf1 lr), tr) }; - case (_, #leaf al) { - let (l,r) = splitAssocList(al, bitpos); - rec(bitpos, tl, #branch(#leaf l, #leaf r)) + case (_, #leaf l) { + let (ll, lr) = splitAssocList(l.keyvals, bitpos); + rec(bitpos, tl, br2(lf2 ll, lf2 lr)) }; - case (#branch (ll, lr), #branch(rl, rr)) { - #branch(rec(bitpos + 1, ll, rl), - rec(bitpos + 1, lr, rr)) + case (#branch b1, #branch b2) { + br3(rec(bitpos + 1, b1.left, b2.left), + rec(bitpos + 1, b1.right, b2.right)) }; + } }; rec(0, tl, tr) }; - /** `foldUp` ------------ @@ -469,14 +598,14 @@ type Trie3D = Trie >; func rec(t:Trie) : X { switch t { case (#empty) { empty }; - case (#leaf al) { + case (#leaf l) { AssocList.fold,V,X>( - al, empty, + l.keyvals, empty, func (k:Key, v:V, x:X):X = bin(leaf(k.key,v),x) ) }; - case (#branch(l,r)) { bin(rec(l), rec(r)) }; + case (#branch(b)) { bin(rec(b.left), rec(b.right)) }; } }; rec(t) @@ -534,6 +663,7 @@ type Trie3D = Trie >; ) }; + /** `fold` --------- @@ -544,13 +674,13 @@ type Trie3D = Trie >; func rec(t:Trie, x:X) : X { switch t { case (#empty) x; - case (#leaf al) { + case (#leaf l) { AssocList.fold,V,X>( - al, x, + l.keyvals, x, func (k:Key, v:V, x:X):X = f(k.key,v,x) ) }; - case (#branch(l,r)) { rec(l,rec(r,x)) }; + case (#branch(b)) { rec(b.left,rec(b.right,x)) }; }; }; rec(t, x) @@ -566,12 +696,12 @@ type Trie3D = Trie >; func rec(t:Trie) : Bool { switch t { case (#empty) { false }; - case (#leaf al) { + case (#leaf l) { List.exists<(Key,V)>( - al, func ((k:Key,v:V)):Bool=f(k.key,v) + l.keyvals, func ((k:Key,v:V)):Bool=f(k.key,v) ) }; - case (#branch(l,r)) { rec(l) or rec(r) }; + case (#branch(b)) { rec(b.left) or rec(b.right) }; }; }; rec(t) @@ -586,56 +716,80 @@ type Trie3D = Trie >; func rec(t:Trie) : Bool { switch t { case (#empty) { true }; - case (#leaf al) { + case (#leaf l) { List.all<(Key,V)>( - al, func ((k:Key,v:V)):Bool=f(k.key,v) + l.keyvals, func ((k:Key,v:V)):Bool=f(k.key,v) ) }; - case (#branch(l,r)) { rec(l) and rec(r) }; + case (#branch(b)) { rec(b.left) and rec(b.right) }; }; }; rec(t) }; /** - `count` + `nth` -------- - Count the number of entries in the trie. + Project the nth key-value pair from the trie. + + Note: This position is not meaningful; it's only here so that we + can inject tries into arrays given the Array_tabulate interface for + doing so. */ - func count(t:Trie):Nat{ - foldUp - (t, - func(n:Nat,m:Nat):Nat{n+m}, - func(_:K,_:V):Nat{1}, - 0) + func nth(t:Trie, i:Nat) : ?(Key, V) { + func rec(t:Trie, i:Nat) : ?(Key, V) { + switch t { + case (#empty) null; + case (#leaf l) List.nth<(Key,V)>(l.keyvals, i); + case (#branch b) { + let count_left = count(b.left); + if (i < count_left) { rec(b.left, i) } + else { rec(b.right, i - count_left) } + } + } + }; + assert (i < count(t)); + rec(t, i) }; /** `toArray` -------- - Gather the collection of key-value pairs into an array. + Gather the collection of key-value pairs into an array of a (possibly-distinct) type. + + ### Implementation notes: + + we use this function repeatedly in the Produce Exchange example + application, often on very large tries. + + Performance Profiling shows that it is important that this be + memory efficient, and reasonably time efficient, at large scales. + + To do so, we use a single array allocation: The returned array. To do so, we + sacrifice some efficiency in reading the input trie, and use function `nth` to + project each element with an independent trie traversal. + + This approach is somewhat forced on us by the type signature of + Array_tabulate, and the desire to only allocate one array; that requirement rules + out iterative mutation of an optionally-null array, since an imperative + approach which would give us the wrong return type. + + Since we want to statically rule out null output elements, and since the AS type system + cannot do that for an imperative approach unless we assume more about + the type W (e.g., the existence of "default values"), we settle for using `nth`. - To do: make this more efficient, using a single array allocation. */ - func toArray(t:Trie,f:(K,V)->[W]):[W] = + func toArray(t:Trie,f:(K,V)->W):[W] = label profile_trie_toArray_begin : [W] { - func arrayAppend(x:[W],y:[W]):[W] { - label profile_trie_toArray_arrayAppend : [W] - Array_tabulate ( - x.len() + y.len(), - func (i:Nat) : W = label profile_trie_toArray_arrayAppend_projelm : W { - if (i >= x.len()) { y[i - x.len()] } - else { x[i] } - } - ) - }; - let result = foldUp - (t, - arrayAppend, - func(k:K, v:V):[W]{f(k,v)}, - []); + let a = Array_tabulate ( + count(t), + func (i:Nat) : W = label profile_trie_toArray_nth : W { + let (k,v) = Option.unwrap<(Key,V)>(nth(t, i)); + f(k.key, v) + } + ); label profile_trie_toArray_end : [W] - result + a }; /** @@ -646,17 +800,8 @@ type Trie3D = Trie >; but no leaves. These can result from naive filtering operations; filter uses this function to avoid creating such subtrees. */ - func isEmpty(t:Trie) : Bool { - func rec(t:Trie) : Bool { - switch t { - case (#empty) { true }; - case (#leaf al) { List.isNil<(Key,V)>(al) }; - case (#branch(l,r)) { rec(l) and rec(r) }; - }; - }; - rec(t) - }; - + func isEmpty(t:Trie) : Bool = + count(t) == 0; /** `filter` @@ -667,18 +812,22 @@ type Trie3D = Trie >; func rec(t:Trie) : Trie { switch t { case (#empty) { #empty }; - case (#leaf al) { - #leaf(List.filter<(Key,V)>(al, func ((k:Key,v:V)):Bool = f(k.key,v))) + case (#leaf l) { + leaf( + List.filter<(Key,V)>( + l.keyvals, + func ((k:Key,v:V)):Bool = f(k.key,v)) + ) }; - case (#branch(l,r)) { - let fl = rec(l); - let fr = rec(r); + case (#branch(b)) { + let fl = rec(b.left); + let fr = rec(b.right); switch (isEmpty(fl), isEmpty(fr)) { case (true, true) #empty; case (false, true) fr; case (true, false) fl; - case (false, false) #branch(fl, fr); + case (false, false) branch(fl, fr); }; } } @@ -695,27 +844,28 @@ type Trie3D = Trie >; func rec(t:Trie) : Trie { switch t { case (#empty) { #empty }; - case (#leaf al) { - #leaf(List.mapFilter<(Key,V),(Key,W)>( - al, - // retain key and hash, but update key's value using f: - func ((k:Key,v:V)):?(Key,W) = { - switch (f(k.key,v)) { - case (null) null; - case (?w) (?(new {key=k.key; hash=k.hash}, w)); - }} - ) + case (#leaf l) { + leaf( + List.mapFilter<(Key,V),(Key,W)>( + l.keyvals, + // retain key and hash, but update key's value using f: + func ((k:Key,v:V)):?(Key,W) = { + switch (f(k.key,v)) { + case (null) null; + case (?w) (?(new {key=k.key; hash=k.hash}, w)); + }} + ) ) }; - case (#branch(l,r)) { - let fl = rec(l); - let fr = rec(r); + case (#branch(b)) { + let fl = rec(b.left); + let fr = rec(b.right); switch (isEmpty(fl), isEmpty(fr)) { case (true, true) #empty; case (false, true) fr; case (true, false) fl; - case (false, false) #branch(fl, fr); + case (false, false) branch(fl, fr); }; } } @@ -744,15 +894,15 @@ type Trie3D = Trie >; func rec(tl:Trie, tr:Trie) : Bool { switch (tl, tr) { case (#empty, #empty) { true }; - case (#leaf as, #leaf bs) { + case (#leaf l1, #leaf l2) { List.isEq<(Key,V)> - (as, bs, + (l1.keyvals, l2.keyvals, func ((k1:Key, v1:V), (k2:Key, v2:V)) : Bool = keq(k1.key, k2.key) and veq(v1,v2) ) }; - case (#branch(ll,lr),#branch(rl,rr)) { - rec(ll,rl) and rec(lr,rr) + case (#branch(b1),#branch(b2)) { + rec(b1.left, b2.left) and rec(b2.right, b2.right) }; case _ { false }; } @@ -952,8 +1102,6 @@ type Trie3D = Trie >; }; - - /** Future work @@ -973,3 +1121,4 @@ Iterator objects for use in 'for ... in ...' patterns */ +} From 5016e64d0448d510e2240f0c1d4c7e4bfe5c474b Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 30 May 2019 17:32:40 -0600 Subject: [PATCH 0109/1176] adaptive tries: automatic branching to impose a maximum leaf count --- stdlib/trie2.as | 99 +++++++++++++++++++++++++++++-------------------- 1 file changed, 58 insertions(+), 41 deletions(-) diff --git a/stdlib/trie2.as b/stdlib/trie2.as index 3cdb265fb1e..5d7ba4c91db 100644 --- a/stdlib/trie2.as +++ b/stdlib/trie2.as @@ -47,6 +47,8 @@ See the full details in the definitions below: */ +let MAX_LEAF_COUNT = 32; + let P = (import "prelude.as"); let Option = import "option.as"; @@ -163,13 +165,27 @@ type Trie3D = Trie >; `leaf` -------- Construct a leaf node, computing the count stored there. + + This helper function automatically enforces the MAX_LEAF_COUNT + by constructing branches as necessary; to do so, it also needs the bitpos + of the leaf. + */ - func leaf(al:AssocList,V>) : Trie { - #leaf( - new{ - count=List.len<(Key,V)>(al); - keyvals=al - }) + func leaf(kvs:AssocList,V>, bitpos:Nat) : Trie { + func rec(kvs:AssocList,V>, bitpos:Nat) : Trie { + let len = List.len<(Key,V)>(kvs); + if ( len < MAX_LEAF_COUNT ) { + #leaf( + new{ + count=len; + keyvals=kvs + }) + } else { + let (l, r) = splitAssocList(kvs, bitpos); + branch(rec(l, bitpos + 1), rec(r, bitpos + 1)) + } + }; + rec(kvs, bitpos) }; // /** @@ -203,7 +219,7 @@ type Trie3D = Trie >; switch t { case (#empty) { let (kvs, _) = AssocList.replace,V>(null, k, key_eq, v); - ((leaf(kvs)), null) + (leaf(kvs, bitpos), null) }; case (#branch b) { let bit = Hash.getHashBit(k.hash, bitpos); @@ -220,7 +236,7 @@ type Trie3D = Trie >; case (#leaf l) { let (kvs2, old_val) = AssocList.replace,V>(l.keyvals, k, key_eq, v); - (leaf(kvs2), old_val) + (leaf(kvs2, bitpos), old_val) }; } }; @@ -302,8 +318,8 @@ type Trie3D = Trie >; func merge(tl:Trie, tr:Trie, k_eq:(K,K)->Bool): Trie { let key_eq = keyEq(k_eq); func br(l:Trie, r:Trie) : Trie = branch(l,r); - func lf(kvs:AssocList,V>) : Trie = leaf(kvs); func rec(bitpos:Nat, tl:Trie, tr:Trie) : Trie { + func lf(kvs:AssocList,V>) : Trie = leaf(kvs, bitpos); switch (tl, tr) { case (#empty, _) { return tr }; case (_, #empty) { return tl }; @@ -348,8 +364,8 @@ type Trie3D = Trie >; func mergeDisjoint(tl:Trie, tr:Trie, k_eq:(K,K)->Bool): Trie { let key_eq = keyEq(k_eq); func br(l:Trie, r:Trie) : Trie = branch(l,r); - func lf(kvs:AssocList,V>) : Trie = leaf(kvs); func rec(bitpos:Nat, tl:Trie, tr:Trie) : Trie { + func lf(kvs:AssocList,V>) : Trie = leaf(kvs, bitpos); switch (tl, tr) { case (#empty, _) { return tr }; case (_, #empty) { return tl }; @@ -404,12 +420,12 @@ type Trie3D = Trie >; let key_eq = keyEq(k_eq); func br1(l:Trie, r:Trie) : Trie = branch(l,r); - func lf1(kvs:AssocList,V>) : Trie = leaf(kvs); - func br2(l:Trie, r:Trie) : Trie = branch(l,r); - func lf2(kvs:AssocList,W>) : Trie = leaf(kvs); func rec(bitpos:Nat, tl:Trie, tr:Trie) : Trie { + func lf1(kvs:AssocList,V>) : Trie = leaf(kvs, bitpos); + func lf2(kvs:AssocList,W>) : Trie = leaf(kvs, bitpos); + switch (tl, tr) { case (#empty, _) { return #empty }; case (_, #empty) { return tl }; @@ -472,43 +488,42 @@ type Trie3D = Trie >; let key_eq = keyEq(k_eq); func br1(l:Trie, r:Trie) : Trie = branch(l,r); - func lf1(kvs:AssocList,V>) : Trie = leaf(kvs); - func br2(l:Trie, r:Trie) : Trie = branch(l,r); - func lf2(kvs:AssocList,W>) : Trie = leaf(kvs); func br3(l:Trie, r:Trie) : Trie = branch(l,r); - func lf3(kvs:AssocList,X>) : Trie = leaf(kvs); + func lf3(kvs:AssocList,X>, bitpos:Nat) : Trie = leaf(kvs, bitpos); /** empty right case; build from left only: */ - func recL(t:Trie) : Trie { + func recL(t:Trie, bitpos:Nat) : Trie { switch t { case (#empty) #empty; case (#leaf l) { - lf3(AssocList.disj,V,W,X>(l.keyvals, null, key_eq, vbin)) + lf3(AssocList.disj,V,W,X>(l.keyvals, null, key_eq, vbin), bitpos) }; - case (#branch(b)) { br3(recL(b.left),recL(b.right)) }; + case (#branch(b)) { br3(recL(b.left,bitpos+1),recL(b.right,bitpos+1)) }; } }; /** empty left case; build from right only: */ - func recR(t:Trie) : Trie { + func recR(t:Trie, bitpos:Nat) : Trie { switch t { case (#empty) #empty; case (#leaf l) { - lf3(AssocList.disj,V,W,X>(null, l.keyvals, key_eq, vbin)) + lf3(AssocList.disj,V,W,X>(null, l.keyvals, key_eq, vbin), bitpos) }; - case (#branch(b)) { br3(recR(b.left),recR(b.right)) }; + case (#branch(b)) { br3(recR(b.left,bitpos+1),recR(b.right,bitpos+1)) }; } }; /** main recursion */ func rec(bitpos:Nat, tl:Trie, tr:Trie) : Trie { + func lf1(kvs:AssocList,V>) : Trie = leaf(kvs, bitpos); + func lf2(kvs:AssocList,W>) : Trie = leaf(kvs, bitpos); switch (tl, tr) { case (#empty, #empty) { #empty }; - case (#empty, _ ) { recR(tr) }; - case (_, #empty) { recL(tl) }; + case (#empty, _ ) { recR(tr, bitpos) }; + case (_, #empty) { recL(tl, bitpos) }; case (#leaf l1, #leaf l2) { - lf3(AssocList.disj,V,W,X>(l1.keyvals, l2.keyvals, key_eq, vbin)) + lf3(AssocList.disj,V,W,X>(l1.keyvals, l2.keyvals, key_eq, vbin), bitpos) }; case (#leaf l, _) { let (ll, lr) = splitAssocList(l.keyvals, bitpos); @@ -553,15 +568,14 @@ type Trie3D = Trie >; let key_eq = keyEq(k_eq); func br1(l:Trie, r:Trie) : Trie = branch(l,r); - func lf1(kvs:AssocList,V>) : Trie = leaf(kvs); - func br2(l:Trie, r:Trie) : Trie = branch(l,r); - func lf2(kvs:AssocList,W>) : Trie = leaf(kvs); - func br3(l:Trie, r:Trie) : Trie = branch(l,r); - func lf3(kvs:AssocList,X>) : Trie = leaf(kvs); func rec(bitpos:Nat, tl:Trie, tr:Trie) : Trie { + func lf1(kvs:AssocList,V>) : Trie = leaf(kvs, bitpos); + func lf2(kvs:AssocList,W>) : Trie = leaf(kvs, bitpos); + func lf3(kvs:AssocList,X>) : Trie = leaf(kvs, bitpos); + switch (tl, tr) { case (#empty, _) { #empty }; case (_, #empty) { #empty }; @@ -809,19 +823,21 @@ type Trie3D = Trie >; filter the key-value pairs by a given predicate. */ func filter(t:Trie, f:(K,V)->Bool) : Trie { - func rec(t:Trie) : Trie { + func rec(t:Trie, bitpos:Nat) : Trie { switch t { case (#empty) { #empty }; case (#leaf l) { leaf( List.filter<(Key,V)>( l.keyvals, - func ((k:Key,v:V)):Bool = f(k.key,v)) + func ((k:Key,v:V)):Bool = f(k.key,v) + ), + bitpos ) }; case (#branch(b)) { - let fl = rec(b.left); - let fr = rec(b.right); + let fl = rec(b.left, bitpos+1); + let fr = rec(b.right, bitpos+1); switch (isEmpty(fl), isEmpty(fr)) { case (true, true) #empty; @@ -832,7 +848,7 @@ type Trie3D = Trie >; } } }; - rec(t) + rec(t, 0) }; /** @@ -841,7 +857,7 @@ type Trie3D = Trie >; map and filter the key-value pairs by a given predicate. */ func mapFilter(t:Trie, f:(K,V)->?W) : Trie { - func rec(t:Trie) : Trie { + func rec(t:Trie, bitpos:Nat) : Trie { switch t { case (#empty) { #empty }; case (#leaf l) { @@ -854,12 +870,13 @@ type Trie3D = Trie >; case (null) null; case (?w) (?(new {key=k.key; hash=k.hash}, w)); }} - ) + ), + bitpos ) }; case (#branch(b)) { - let fl = rec(b.left); - let fr = rec(b.right); + let fl = rec(b.left, bitpos + 1); + let fr = rec(b.right, bitpos + 1); switch (isEmpty(fl), isEmpty(fr)) { case (true, true) #empty; @@ -870,7 +887,7 @@ type Trie3D = Trie >; } } }; - rec(t) + rec(t, 0) }; /** From 5b47e1d08d1f11b1331e73741e250ad2363d6b95 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 30 May 2019 17:43:11 -0600 Subject: [PATCH 0110/1176] tries: clean up doc --- stdlib/trie2.as | 46 ++++++++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/stdlib/trie2.as b/stdlib/trie2.as index 5d7ba4c91db..896b798ac01 100644 --- a/stdlib/trie2.as +++ b/stdlib/trie2.as @@ -26,15 +26,36 @@ these trees never do). Representation ===================== -Below, we define the types used in the representation: +A hash trie is a binary trie, where each (internal) branch node +represents having distinguished its key-value pairs on a single bit of +the keys. + +By following paths in the trie, we determine an increasingly smaller +and smaller subset of the keys. + +Each leaf node consists of an association list of key-value pairs. + +We say that a leaf is valid if it contains no more than MAX_LEAF_COUNT +key-value pairs. + +Each non-empty trie node stores a count; we discuss that more below. - - **`Key`**, parameterized by a hashable type `K` +### Adaptive depth +For small mappings, this "trie" structure just consists of a single +leaf, which contains up to MAX_LEAF_COUNT key-value pairs. +By construction, the algorithms below enforce the invariant that no +leaf ever contains more than MAX_LEAF_COUNT key-value pairs: the +function `leaf` accepts a list, but subdivides it with branches until +it can actually construct valid leaves. Once distinguished, subsets +of keys tend to remain distinguished by the presence of these branches. - ### Cached counts +To do: Collapse branches whose count is less than MAX_LEAF_COUNT. - At each branch and leaf, we use a stored count to support a +### Cached counts + +At each branch and leaf, we use a stored count to support a memory-efficient `toArray` function, which itself relies on per-element projection via `nth`; in turn, `nth` directly uses the O(1)-time function `count` for achieving an acceptable level of @@ -43,7 +64,9 @@ key-value pairs, and we do not store a count for each Cons cell in the list. -See the full details in the definitions below: +### Details + +Below, we define the types used in the representation: */ @@ -188,19 +211,6 @@ type Trie3D = Trie >; rec(kvs, bitpos) }; - // /** - // `count` - // -------- - // Count the number of entries in the trie. - // */ - // func count(t:Trie):Nat{ - // foldUp - // (t, - // func(n:Nat,m:Nat):Nat{n+m}, - // func(_:K,_:V):Nat{1}, - // 0) - // }; - /** `copy` --------- From 629663ccff4faa8f81bb3b56c84f1ed56c89d7a8 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 30 May 2019 17:51:39 -0600 Subject: [PATCH 0111/1176] tries: clean up doc --- stdlib/trie2.as | 9 --------- 1 file changed, 9 deletions(-) diff --git a/stdlib/trie2.as b/stdlib/trie2.as index 896b798ac01..dc98d03e643 100644 --- a/stdlib/trie2.as +++ b/stdlib/trie2.as @@ -1134,15 +1134,6 @@ type Trie3D = Trie >; Future work ============= -Adaptive path lengths ----------------------- - -Currently we assume a uniform path length. This can be inefficient, -and requires careful tuning. In the future, we could adapt the path -length of each subtree to its cardinality; this wouild avoid -needlessly long paths, or paths that are too short for their subtree's -size. - Iterator objects ------------------- for use in 'for ... in ...' patterns From 532917ff5c3469f4538805f41c6d9b6682090103 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Fri, 31 May 2019 05:53:19 -0600 Subject: [PATCH 0112/1176] tries: impose invariant: never create useless branches --- stdlib/trie2.as | 52 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/stdlib/trie2.as b/stdlib/trie2.as index dc98d03e643..776188e8666 100644 --- a/stdlib/trie2.as +++ b/stdlib/trie2.as @@ -85,32 +85,38 @@ type List = List.List; let AssocList = import "assocList.as"; type AssocList = AssocList.AssocList; +/** A `Key` for the trie has an associated hash value */ type Key = { - // hash field: permits fast inequality checks, permits collisions; - // (eventually: permits incremental growth of deeper trie paths) + /** `hash` permits fast inequality checks, and permits collisions */ hash: Hash; - // key field: for conservative equality checks, after equal hashes. + /** `key` permits percise equality checks, but only used after equal hashes. */ key: K; }; -// Equality function for two `Key`s, in terms of equaltiy of `K`'s. +/** Equality function for two `Key`s, in terms of equaltiy of `K`'s. */ func keyEq(keq:(K,K) -> Bool) : ((Key,Key) -> Bool) = { func (key1:Key, key2:Key) : Bool = label profile_trie_keyEq : Bool (Hash.hashEq(key1.hash, key2.hash) and keq(key1.key, key2.key)) }; +/** leaf nodes of trie consist of key-value pairs as a list. */ type Leaf = { count : Nat ; keyvals : AssocList,V> ; }; +/** branch nodes of the trie discriminate on a bit position of the keys' hashes. + we never store this bitpos; rather, + we enforce a style where this position is always known from context. +*/ type Branch = { count : Nat ; left : Trie ; right : Trie ; }; +/** binary hash tries: either empty, a leaf node, or a branch node */ type Trie = { #empty ; #leaf : Leaf ; @@ -143,7 +149,8 @@ type Trie3D = Trie >; -------- An empty trie. */ - func empty() : Trie = #empty; + func empty() : Trie = + #empty; /** `count` @@ -169,19 +176,36 @@ type Trie3D = Trie >; `branch` -------- Construct a branch node, computing the count stored there. + + ### edge case: 0 or 1 elements: + + if the left and right in sum have fewer than 2 key-value pairs, + then a leaf or empty node suffices, so do not make a branch. + + otherwise, we make a branch normally, regardless of the sizes: + our rationale is that the l-vs-r keys have already been distinguished, + so let's memorialize that work with a branch, regardless of how small. */ func branch(l:Trie, r:Trie) : Trie { - // note: need to rename the `count` function, because otherwise AS - // is confused by what looks like a recursive definition below for - // the field `count`. func c(t:Trie) : Nat = count(t); - #branch( - new{ - count=c(l) + c(r); - left=l; - right=r + let sum = c(l) + c(r); + /** handle edge case: */ + if ( sum < 2 ) { + switch (nth(l,0), nth(r,0)) { + case (null, null) { #empty }; + case (?kv, null) { leaf(?(kv,null),0) }; + case (null, ?kv ) { leaf(?(kv,null),0) }; + case (?kv1, ?kv2) { P.unreachable() }; } - ) + } else { + #branch( + new{ + count=sum; + left=l; + right=r + } + ) + } }; /** From 0b1f2cecc80f6a124e1dc5707280bbfaaa88f368 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Fri, 31 May 2019 05:54:38 -0600 Subject: [PATCH 0113/1176] remove stale note in doc --- stdlib/trie2.as | 2 -- 1 file changed, 2 deletions(-) diff --git a/stdlib/trie2.as b/stdlib/trie2.as index 776188e8666..d6ad038bc08 100644 --- a/stdlib/trie2.as +++ b/stdlib/trie2.as @@ -51,8 +51,6 @@ function `leaf` accepts a list, but subdivides it with branches until it can actually construct valid leaves. Once distinguished, subsets of keys tend to remain distinguished by the presence of these branches. -To do: Collapse branches whose count is less than MAX_LEAF_COUNT. - ### Cached counts At each branch and leaf, we use a stored count to support a From 741e6181a516c6b3db4f5f38bba19662629ea5f3 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 31 May 2019 14:20:15 +0200 Subject: [PATCH 0114/1176] Backend: Properly allocate scratch memory (#457) previously, we were using the memory past the heap pointer as scratch space, but that only works if no furher allocation needs to happen during serialization. This is fragile, so lets do proper allocation here. --- src/compile.ml | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/compile.ml b/src/compile.ml index 57c4d92e84f..5c731512978 100644 --- a/src/compile.ml +++ b/src/compile.ml @@ -2130,6 +2130,13 @@ module Text = struct end ^^ get_utf8 + (* We also use Text heap objects for byte arrays + (really should rename Text to Bytes) *) + let dyn_alloc_scratch env = + compile_add_const (Int32.mul Heap.word_size header_size) ^^ + Heap.dyn_alloc_bytes env ^^ + payload_ptr_unskewed + end (* Text *) module Arr = struct @@ -2699,9 +2706,8 @@ module Serialization = struct The general serialization strategy is as follows: * We traverse the data to calculate the size needed for the data buffer and the reference buffer. - * We remember the current heap pointer, and use the space after as scratch space. - * The scratch space is separated into two regions: - One for references, and one for raw data. + * We allocate memory for the data buffer and the reference buffer + (this memory area is not referenced, so will be dead with the next GC) * We traverse the data, in a type-driven way, and copy it to the scratch space. We thread through pointers to the current free space of the two scratch spaces. This is type driven, and we use the `share_code` machinery and names that @@ -2709,7 +2715,6 @@ module Serialization = struct * We externalize all that new data space into a databuf, and add this reference to the reference space. * We externalize the reference space into a elembuf - * We reset the heap pointer and table pointer, to garbage collect the scratch space. TODO: Cycles are not detected. @@ -3149,20 +3154,14 @@ module Serialization = struct let (set_data_start, get_data_start) = new_local env "data_start" in let (set_refs_start, get_refs_start) = new_local env "refs_start" in - Heap.get_heap_ptr ^^ - set_data_start ^^ - - Heap.get_heap_ptr ^^ get_data_size ^^ - G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ - set_refs_start ^^ + Text.dyn_alloc_scratch env ^^ + set_data_start ^^ - (* Allocate space, if needed *) - get_refs_start ^^ get_refs_size ^^ - compile_divU_const Heap.word_size ^^ - G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ - Heap.grow_memory env ^^ + compile_mul_const Heap.word_size ^^ + Text.dyn_alloc_scratch env ^^ + set_refs_start ^^ (* Serialize x into the buffer *) get_x ^^ From d1456785472c34cc94a5040f6004b201f6d8aacc Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 3 Jun 2019 10:25:37 +0200 Subject: [PATCH 0115/1176] Failing test case related to large Word64 literals (#459) * Failing test case related to large Word64 literals and their conversions in the interpreter. * fix overflowed Big_int to int conversion * fix Word64->Nat and Int->Word64 by always modulo-wrapping and then using `int64_of_big_int_opt` * fix testcases * word64ToNat won't produce negatives any more * extend roundtrip tests and accept ok files * fix more representability problems this way all conversions to word types should avoid the `Big_int` range that is not representable as an OCaml `int` * there are also tests for problematic ranges --- src/prelude.ml | 54 +++++++++---- test/run/conversions.as | 149 +++++++++++++++++++++++++++++++++++ test/run/ok/words.run-ir.ok | 10 +-- test/run/ok/words.run-low.ok | 10 +-- test/run/ok/words.run.ok | 10 +-- 5 files changed, 204 insertions(+), 29 deletions(-) diff --git a/src/prelude.ml b/src/prelude.ml index 66c84fbbfa4..09a4138b421 100644 --- a/src/prelude.ml +++ b/src/prelude.ml @@ -237,7 +237,37 @@ open Value module Conv = struct open Nativeint + open Big_int let of_signed_Word32 w = to_int (logand 0xFFFFFFFFn (of_int32 w)) + + let two = big_int_of_int 2 + let twoRaised62 = power_big_int_positive_int two 62 + let twoRaised63 = power_big_int_positive_int two 63 + let word_twoRaised63 = Word64.(pow 2L 63L) + let twoRaised64 = power_big_int_positive_int two 64 + + let word64_of_nat_big_int i = + assert (sign_big_int i > -1); + let wrapped = mod_big_int i twoRaised64 in + match int64_of_big_int_opt wrapped with + | Some n -> n + | _ -> Word64.add (int64_of_big_int (sub_big_int wrapped twoRaised63)) word_twoRaised63 + + let word64_of_big_int i = + let wrapped = mod_big_int i twoRaised64 in + match int64_of_big_int_opt wrapped with + | Some n -> n + | _ -> Word64.sub (int64_of_big_int (sub_big_int wrapped twoRaised63)) word_twoRaised63 + + let big_int_of_unsigned_word64 w = + let i = big_int_of_int64 w in + if sign_big_int i > -1 then i + else add_big_int i twoRaised64 + + let wrapped_int_of_big_int i = + match int_of_big_int_opt i with + | Some n -> n + | _ -> int_of_big_int (mod_big_int i twoRaised62) end (* Conv *) @@ -245,30 +275,26 @@ let prim = function | "abs" -> fun v k -> k (Int (Nat.abs (as_int v))) | "Nat->Word8" -> fun v k -> - let i = Big_int.int_of_big_int (as_int v) + let i = Conv.wrapped_int_of_big_int (as_int v) in k (Word8 (Word8.of_int_u i)) | "Int->Word8" -> fun v k -> - let i = Big_int.int_of_big_int (as_int v) + let i = Conv.wrapped_int_of_big_int (as_int v) in k (Word8 (Word8.of_int_s i)) | "Nat->Word16" -> fun v k -> - let i = Big_int.int_of_big_int (as_int v) + let i = Conv.wrapped_int_of_big_int (as_int v) in k (Word16 (Word16.of_int_u i)) | "Int->Word16" -> fun v k -> - let i = Big_int.int_of_big_int (as_int v) + let i = Conv.wrapped_int_of_big_int (as_int v) in k (Word16 (Word16.of_int_s i)) | "Nat->Word32" -> fun v k -> - let i = Big_int.int_of_big_int (as_int v) + let i = Conv.wrapped_int_of_big_int (as_int v) in k (Word32 (Word32.of_int_u i)) | "Int->Word32" -> fun v k -> - let i = Big_int.int_of_big_int (as_int v) + let i = Conv.wrapped_int_of_big_int (as_int v) in k (Word32 (Word32.of_int_s i)) - | "Nat->Word64" -> fun v k -> - let i = Big_int.int_of_big_int (as_int v) - in k (Word64 (Word64.of_int_u i)) - | "Int->Word64" -> fun v k -> - let i = Big_int.int_of_big_int (as_int v) - in k (Word64 (Word64.of_int_s i)) + | "Nat->Word64" -> fun v k -> k (Word64 (Conv.word64_of_nat_big_int (as_int v))) + | "Int->Word64" -> fun v k -> k (Word64 (Conv.word64_of_big_int (as_int v))) | "Word8->Nat" -> fun v k -> let i = Int32.to_int (Int32.shift_right_logical (Word8.to_bits (as_word8 v)) 24) @@ -288,8 +314,8 @@ let prim = function | "Word32->Int" -> fun v k -> k (Int (Big_int.big_int_of_int32 (as_word32 v))) | "Word64->Nat" -> fun v k -> - let i = Int64.to_int (as_word64 v) (* ! *) - in k (Int (Big_int.big_int_of_int i)) + let i = Conv.big_int_of_unsigned_word64 (as_word64 v) + in k (Int i) | "Word64->Int" -> fun v k -> k (Int (Big_int.big_int_of_int64 (as_word64 v))) | "Char->Word32" -> fun v k -> diff --git a/test/run/conversions.as b/test/run/conversions.as index 472dd48517c..d1a53c2045d 100644 --- a/test/run/conversions.as +++ b/test/run/conversions.as @@ -33,6 +33,8 @@ assert(word32ToNat 4294967295 == 4294967295); // 2**32 - 1 roundtrip 10000000; roundtrip 100000000; roundtrip 1000000000; + roundtrip 0x7FFFFFFF; + roundtrip 0xFFFFFFFF; }; { @@ -47,6 +49,8 @@ assert(word32ToNat 4294967295 == 4294967295); // 2**32 - 1 roundtrip 10000000; roundtrip 100000000; roundtrip 1000000000; + roundtrip 0x7FFFFFFF; + roundtrip 0xFFFFFFFF; }; @@ -99,6 +103,7 @@ println(word32ToInt 4294967295); // == (-1) // 2**32 - 1 roundtrip 10000000; roundtrip 100000000; roundtrip 1000000000; + roundtrip 0x7FFFFFFF; roundtrip (-10); roundtrip (-100); @@ -109,6 +114,7 @@ println(word32ToInt 4294967295); // == (-1) // 2**32 - 1 roundtrip (-10000000); roundtrip (-100000000); roundtrip (-1000000000); + roundtrip (-2147483648); }; { @@ -123,6 +129,8 @@ println(word32ToInt 4294967295); // == (-1) // 2**32 - 1 roundtrip 10000000; roundtrip 100000000; roundtrip 1000000000; + roundtrip 0x7FFFFFFF; + roundtrip 0xFFFFFFFF; /*!*/ roundtrip (-10); @@ -165,3 +173,144 @@ assert(charToWord32 '\u{10ffff}' == (0x10FFFF : Word32)); assert(charToText 'П' == "П"); func snd((a : Word32, b : Char)) : Char = b; assert(snd (decodeUTF8 "П") =='П'); + +// Nat <--> Word64 + +assert(natToWord64 0x0000000000000000 == (0x0000000000000000 : Word64)); +assert(natToWord64 0x0000000000000001 == (0x0000000000000001 : Word64)); +assert(natToWord64 0x7FFFFFFFFFFFFFFF == (0x7FFFFFFFFFFFFFFF : Word64)); +assert(natToWord64 0x8000000000000000 == (0x8000000000000000 : Word64)); +assert(natToWord64 0x8000000000000001 == (0x8000000000000001 : Word64)); +assert(natToWord64 0xFFFFFFFFFFFFFFFF == (0xFFFFFFFFFFFFFFFF : Word64)); + +assert(word64ToNat 0x0000000000000000 == (0x0000000000000000 : Nat)); +assert(word64ToNat 0x0000000000000001 == (0x0000000000000001 : Nat)); +assert(word64ToNat 0x7FFFFFFFFFFFFFFF == (0x7FFFFFFFFFFFFFFF : Nat)); +assert(word64ToNat 0x8000000000000000 == (0x8000000000000000 : Nat)); +assert(word64ToNat 0x8000000000000001 == (0x8000000000000001 : Nat)); +assert(word64ToNat 0xFFFFFFFFFFFFFFFF == (0xFFFFFFFFFFFFFFFF : Nat)); + +// Int <--> Word64 + +assert(intToWord64 0x0000000000000000 == (0x0000000000000000 : Word64)); +assert(intToWord64 0x0000000000000001 == (0x0000000000000001 : Word64)); +assert(intToWord64 0x7FFFFFFFFFFFFFFF == (0x7FFFFFFFFFFFFFFF : Word64)); +assert(intToWord64 (-0x8000000000000000) == (0x8000000000000000 : Word64)); +assert(intToWord64 (-0x7FFFFFFFFFFFFFFF) == (0x8000000000000001 : Word64)); +assert(intToWord64 (-0x7FFFFFFFFFFFFFFE) == (0x8000000000000002 : Word64)); +assert(intToWord64 (-0x0000000000000001) == (0xFFFFFFFFFFFFFFFF : Word64)); + +assert(word64ToInt (0x0000000000000000 : Word64) == 0x0000000000000000); +assert(word64ToInt (0x0000000000000001 : Word64) == 0x0000000000000001); +assert(word64ToInt (0x7FFFFFFFFFFFFFFF : Word64) == 0x7FFFFFFFFFFFFFFF); +assert(word64ToInt (0x8000000000000000 : Word64) == -0x8000000000000000); +assert(word64ToInt (0x8000000000000001 : Word64) == -0x7FFFFFFFFFFFFFFF); +assert(word64ToInt (0x8000000000000002 : Word64) == -0x7FFFFFFFFFFFFFFE); +assert(word64ToInt (0xFFFFFFFFFFFFFFFF : Word64) == -0x0000000000000001); + +// Below conversions mainly test the interpreter's bignum arithmetics + +// Int <--> Word8 + +assert(intToWord8 (2 ** 62) == (0 : Word8)); +assert(intToWord8 (2 ** 62 + 1) == (1 : Word8)); +assert(intToWord8 (2 ** 62 - 1) == (255 : Word8)); +assert(intToWord8 (- 2 ** 62) == (0 : Word8)); +assert(intToWord8 (- 2 ** 62 + 1) == (1 : Word8)); +assert(intToWord8 (- 2 ** 62 - 1) == (255 : Word8)); + +assert(intToWord8 (2 ** 63) == (0 : Word8)); +assert(intToWord8 (2 ** 63 + 1) == (1 : Word8)); +assert(intToWord8 (2 ** 63 - 1) == (255 : Word8)); +assert(intToWord8 (- 2 ** 63) == (0 : Word8)); +assert(intToWord8 (- 2 ** 63 + 1) == (1 : Word8)); +assert(intToWord8 (- 2 ** 63 - 1) == (255 : Word8)); + +assert(intToWord8 (2 ** 64) == (0 : Word8)); +assert(intToWord8 (2 ** 64 + 1) == (1 : Word8)); +assert(intToWord8 (2 ** 64 - 1) == (255 : Word8)); +assert(intToWord8 (- 2 ** 64) == (0 : Word8)); +assert(intToWord8 (- 2 ** 64 + 1) == (1 : Word8)); +assert(intToWord8 (- 2 ** 64 - 1) == (255 : Word8)); + + +// Nat <--> Word8 + +assert(natToWord8 (2 ** 64) == (0 : Word8)); +assert(natToWord8 (2 ** 64 + 1) == (1 : Word8)); +assert(natToWord8 (2 ** 64 - 1) == (255 : Word8)); + +// Int <--> Word16 + +assert(intToWord16 (2 ** 62) == (0 : Word16)); +assert(intToWord16 (2 ** 62 + 1) == (1 : Word16)); +assert(intToWord16 (2 ** 62 - 1) == (65535 : Word16)); +assert(intToWord16 (- 2 ** 62) == (0 : Word16)); +assert(intToWord16 (- 2 ** 62 + 1) == (1 : Word16)); +assert(intToWord16 (- 2 ** 62 - 1) == (65535 : Word16)); + +assert(intToWord16 (2 ** 63) == (0 : Word16)); +assert(intToWord16 (2 ** 63 + 1) == (1 : Word16)); +assert(intToWord16 (2 ** 63 - 1) == (65535 : Word16)); +assert(intToWord16 (- 2 ** 63) == (0 : Word16)); +assert(intToWord16 (- 2 ** 63 + 1) == (1 : Word16)); +assert(intToWord16 (- 2 ** 63 - 1) == (65535 : Word16)); + +assert(intToWord16 (2 ** 64) == (0 : Word16)); +assert(intToWord16 (2 ** 64 + 1) == (1 : Word16)); +assert(intToWord16 (2 ** 64 - 1) == (65535 : Word16)); +assert(intToWord16 (- 2 ** 64) == (0 : Word16)); +assert(intToWord16 (- 2 ** 64 + 1) == (1 : Word16)); +assert(intToWord16 (- 2 ** 64 - 1) == (65535 : Word16)); + +// Nat <--> Word16 + +assert(natToWord16 (2 ** 62) == (0 : Word16)); +assert(natToWord16 (2 ** 62 + 1) == (1 : Word16)); +assert(natToWord16 (2 ** 62 - 1) == (65535 : Word16)); + +assert(natToWord16 (2 ** 63) == (0 : Word16)); +assert(natToWord16 (2 ** 63 + 1) == (1 : Word16)); +assert(natToWord16 (2 ** 63 - 1) == (65535 : Word16)); + +assert(natToWord16 (2 ** 64) == (0 : Word16)); +assert(natToWord16 (2 ** 64 + 1) == (1 : Word16)); +assert(natToWord16 (2 ** 64 - 1) == (65535 : Word16)); + +// Int <--> Word32 + +assert(intToWord32 (2 ** 62) == (0 : Word32)); +assert(intToWord32 (2 ** 62 + 1) == (1 : Word32)); +assert(intToWord32 (2 ** 62 - 1) == (4294967295 : Word32)); +assert(intToWord32 (- 2 ** 62) == (0 : Word32)); +assert(intToWord32 (- 2 ** 62 + 1) == (1 : Word32)); +assert(intToWord32 (- 2 ** 62 - 1) == (4294967295 : Word32)); + +assert(intToWord32 (2 ** 63) == (0 : Word32)); +assert(intToWord32 (2 ** 63 + 1) == (1 : Word32)); +assert(intToWord32 (2 ** 63 - 1) == (4294967295 : Word32)); +assert(intToWord32 (- 2 ** 63) == (0 : Word32)); +assert(intToWord32 (- 2 ** 63 + 1) == (1 : Word32)); +assert(intToWord32 (- 2 ** 63 - 1) == (4294967295 : Word32)); + +assert(intToWord32 (2 ** 64) == (0 : Word32)); +assert(intToWord32 (2 ** 64 + 1) == (1 : Word32)); +assert(intToWord32 (2 ** 64 - 1) == (4294967295 : Word32)); +assert(intToWord32 (- 2 ** 64) == (0 : Word32)); +assert(intToWord32 (- 2 ** 64 + 1) == (1 : Word32)); +assert(intToWord32 (- 2 ** 64 - 1) == (4294967295 : Word32)); + +// Nat <--> Word32 + +assert(natToWord32 (2 ** 62) == (0 : Word32)); +assert(natToWord32 (2 ** 62 + 1) == (1 : Word32)); +assert(natToWord32 (2 ** 62 - 1) == (4294967295 : Word32)); + +assert(natToWord32 (2 ** 63) == (0 : Word32)); +assert(natToWord32 (2 ** 63 + 1) == (1 : Word32)); +assert(natToWord32 (2 ** 63 - 1) == (4294967295 : Word32)); + +assert(natToWord32 (2 ** 64) == (0 : Word32)); +assert(natToWord32 (2 ** 64 + 1) == (1 : Word32)); +assert(natToWord32 (2 ** 64 - 1) == (4294967295 : Word32)); + diff --git a/test/run/ok/words.run-ir.ok b/test/run/ok/words.run-ir.ok index 2f95577638e..bead286abe0 100644 --- a/test/run/ok/words.run-ir.ok +++ b/test/run/ok/words.run-ir.ok @@ -1,6 +1,6 @@ 8912765 8912765 --8912765 -8912765 --8912766 -8912766 +18446744073700638851 -8912765 +18446744073700638850 -8912766 8917332 8917332 8908198 8908198 31969 31969 @@ -13,10 +13,10 @@ 584576 584576 35 35 826339054743125951 826339054743125951 --2 -2 --326582449863721025 -326582449863721025 +18446744073709551614 -2 +18120161623845830591 -326582449863721025 1140833920 1140833920 --432345564227497986 -432345564227497986 +18014398509482053630 -432345564227497986 61 61 49 49 5 5 diff --git a/test/run/ok/words.run-low.ok b/test/run/ok/words.run-low.ok index 2f95577638e..bead286abe0 100644 --- a/test/run/ok/words.run-low.ok +++ b/test/run/ok/words.run-low.ok @@ -1,6 +1,6 @@ 8912765 8912765 --8912765 -8912765 --8912766 -8912766 +18446744073700638851 -8912765 +18446744073700638850 -8912766 8917332 8917332 8908198 8908198 31969 31969 @@ -13,10 +13,10 @@ 584576 584576 35 35 826339054743125951 826339054743125951 --2 -2 --326582449863721025 -326582449863721025 +18446744073709551614 -2 +18120161623845830591 -326582449863721025 1140833920 1140833920 --432345564227497986 -432345564227497986 +18014398509482053630 -432345564227497986 61 61 49 49 5 5 diff --git a/test/run/ok/words.run.ok b/test/run/ok/words.run.ok index 2f95577638e..bead286abe0 100644 --- a/test/run/ok/words.run.ok +++ b/test/run/ok/words.run.ok @@ -1,6 +1,6 @@ 8912765 8912765 --8912765 -8912765 --8912766 -8912766 +18446744073700638851 -8912765 +18446744073700638850 -8912766 8917332 8917332 8908198 8908198 31969 31969 @@ -13,10 +13,10 @@ 584576 584576 35 35 826339054743125951 826339054743125951 --2 -2 --326582449863721025 -326582449863721025 +18446744073709551614 -2 +18120161623845830591 -326582449863721025 1140833920 1140833920 --432345564227497986 -432345564227497986 +18014398509482053630 -432345564227497986 61 61 49 49 5 5 From b4a03bac556b9409340e870a746870836506aee6 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Mon, 3 Jun 2019 11:12:50 +0100 Subject: [PATCH 0116/1176] Add support for declaring oneway functions (#380) * specify oneway functions --- design/IDL.md | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/design/IDL.md b/design/IDL.md index f0d6080b8b3..16a7f66f0bf 100644 --- a/design/IDL.md +++ b/design/IDL.md @@ -4,7 +4,7 @@ To document, discover, and interact with actors on the platform, we need an inte #### Goals: -* Language-independent description of actor interfaces and the data they +* Language-independent description of actor interfaces and the data they exchange (names, parameter and result formats of actor methods) * Simple and canonical constructs (C-like; algebraically: sums, products, exponentials) * Extensible, backwards-compatible @@ -65,7 +65,7 @@ This is a summary of the grammar proposed: ::= { ;* } ::= : ( | ) ::= ( ,* ) -> ( ,* ) * - ::= pure + ::= oneway | pure ::= ::= | | | @@ -159,16 +159,18 @@ service { addUser : (name : text, age : nat8) -> (id : nat64); userName : (id : nat64) -> (text) pure; userAge : (id : nat64) -> (nat8) pure; + deleteUser : (id : nat64) -> () oneway; } ``` ### Functions -*Functions* are endpoints for communication. A function invocation is a bidirectional communication, with *parameters* and *results*, a.k.a. request and response. +*Functions* are endpoints for communication. A typical function invocation is a bidirectional communication, with *parameters* and *results*, a.k.a. request and response. A `oneway` function invocation is a uni-directional communication with zero or more parameters but no results, intended for fire-and-forget scenarios. **Note:** The IDL is in fact agnostic to the question whether communication via functions is synchronous (like RPCs) or asynchronous (like messaging with callbacks as response continuations). However, it assumes that all invocations have the same semantics, i.e., there is no need to distinguish between both. +**Note:** In a synchronous interpretation of functions, invocation of a oneway function would return immediately, without waiting for completion of the service-side invocation of the function. In an asynchronous interpretation of functions, the invocation of a `oneway` function does not accept a callback (to invoke on completion). #### Structure @@ -176,11 +178,12 @@ A function type describes the list of parameters and results and their respectiv ``` ::= ( ,* ) -> ( ,* ) * - ::= pure + ::= oneway | pure ``` The parameter and result lists are essentially treated as records, see below. That is, they are named, not positional. The list of parameters must be shorter than 2^32 values and no name/id may occur twice in it. The same restrictions apply to the result list. +The result list of a `oneway` function must be empty. #### Example ``` @@ -593,10 +596,13 @@ For a specialised function, any parameter type can be generalised and any result ``` record { ;* } <: record { ;* } record { ;* } <: record { ;* } +{ a | a in * } = { a | a in * } ------------------------------------------------------------------------------------------------ -func ( ,* ) -> ( ,* ) <: func ( ,* ) -> ( ,* ) +func ( ,* ) -> ( ,* ) * <: func ( ,* ) -> ( ,* ) * ``` +Viewed as sets, the annotations on the functions must be equal. + #### Actors For an actor, a method can be specialised (by specialising its function type), or a method added. Essentially, they are treated exactly like records of functions. From 6d21837afcdfb5a18d340bd79a3f58ca95a2dc2a Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Mon, 3 Jun 2019 13:39:41 +0200 Subject: [PATCH 0117/1176] Update syntax --- design/Syntax.md | 15 ++++++++++----- src/lexer.mll | 3 +-- src/parser.mly | 11 +++++------ 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/design/Syntax.md b/design/Syntax.md index e0b42430b46..03eca90ad34 100644 --- a/design/Syntax.md +++ b/design/Syntax.md @@ -8,6 +8,8 @@ Productions marked * probably deferred to later versions. ::= type expressions ? constructor (shared|actor)? { ;* } object + { ;* } variant + { # } empty variant [ var? ] array ? option shared ? -> function @@ -15,14 +17,16 @@ Productions marked * probably deferred to later versions. ( (( :)? ),* ) tuple Any top None bottom -* | union -* # atom ::= object type fields : immutable var : mutable ? : function (short-hand) + ::= variant type fields + # : tag + # unit tag (short-hand) + ::= type arguments < ,* > @@ -51,6 +55,7 @@ Productions marked * probably deferred to later versions. . tuple projection ? option injection . object projection + # ? variant injection := assignment = unary update = binary update @@ -77,7 +82,6 @@ Productions marked * probably deferred to later versions. declaration (scopes to block) * throw raise exception * try (catch )+ ( )? try -* # atom ::= object expression fields private? dec field @@ -91,15 +95,16 @@ Productions marked * probably deferred to later versions. variable ? literal ( ,* ) tuple or brackets + { ;* } object pattern + # ? variant pattern ? option : type annotation or disjunctive pattern * and conjunctive pattern -* { ;* } object pattern * async asynchronous ::= object pattern fields -* = field + = field ``` ## Declarations diff --git a/src/lexer.mll b/src/lexer.mll index 84d0c105115..ccf9e8463a6 100644 --- a/src/lexer.mll +++ b/src/lexer.mll @@ -143,7 +143,7 @@ rule token mode = parse | "+>>" { SSHROP } | "<<>" { ROTLOP } | "<>>" { ROTROP } - | "#" { CATOP } + | "#" { HASH } | "==" { EQOP } | "!=" { NEQOP } @@ -221,7 +221,6 @@ rule token mode = parse | "prim" as s { if mode = Privileged then PRIM else ID s } | id as s { ID s } - | "#" (id as s) { TAG s } | privileged_id as s { if mode = Privileged then ID s else error lexbuf "privileged identifier" } | "//"utf8_no_nl*eof { EOF } diff --git a/src/parser.mly b/src/parser.mly index 1d75d4d4bfc..3094a953f1f 100644 --- a/src/parser.mly +++ b/src/parser.mly @@ -104,7 +104,7 @@ let share_expfield (ef : exp_field) = %token ADDOP SUBOP MULOP DIVOP MODOP POWOP %token ANDOP OROP XOROP SHLOP USHROP SSHROP ROTLOP ROTROP %token EQOP NEQOP LEOP LTOP GTOP GEOP -%token CATOP +%token HASH %token EQ LT GT %token PLUSASSIGN MINUSASSIGN MULASSIGN DIVASSIGN MODASSIGN POWASSIGN CATASSIGN %token ANDASSIGN ORASSIGN XORASSIGN SHLASSIGN USHRASSIGN SSHRASSIGN ROTLASSIGN ROTRASSIGN @@ -115,7 +115,6 @@ let share_expfield (ef : exp_field) = %token CHAR %token BOOL %token ID -%token TAG %token TEXT %token PRIM %token UNDERSCORE @@ -128,7 +127,7 @@ let share_expfield (ef : exp_field) = %left OR %left AND %nonassoc EQOP NEQOP LEOP LTOP GTOP GEOP -%left ADDOP SUBOP CATOP +%left ADDOP SUBOP HASH %left MULOP DIVOP MODOP %left OROP %left ANDOP @@ -160,7 +159,7 @@ seplist(X, SEP) : | id=ID { id @@ at $sloc } %inline tag : - | id=TAG { id @@ at $sloc } + | HASH id=ID { id @@ at $sloc } %inline typ_id : | id=ID { id @= at $sloc } @@ -211,7 +210,7 @@ typ_obj : { tfs } typ_variant : - | LCURLY CATOP RCURLY + | LCURLY HASH RCURLY { [] } | LCURLY tf=typ_tag RCURLY { [tf] } @@ -317,7 +316,7 @@ lit : | SSHROP { SShROp } | ROTLOP { RotLOp } | ROTROP { RotROp } - | CATOP { CatOp } + | HASH { CatOp } %inline relop : | EQOP { EqOp } From 80763afa502b8f8b5a814989ae170812675daa96 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 3 Jun 2019 15:33:08 +0200 Subject: [PATCH 0118/1176] Specify the IDL hash function (#464) In particular, specify that we hash the `utf8` encoding. --- design/IDL.md | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/design/IDL.md b/design/IDL.md index 16a7f66f0bf..8e6b0ef004d 100644 --- a/design/IDL.md +++ b/design/IDL.md @@ -305,26 +305,28 @@ The id is described as a simple unsigned integer that has to fit the 64 bit valu ``` An id value must be smaller than 2^32 and no id may occur twice in the same record type. - - ##### Shorthand: Symbolic Field Ids -An id can also be given as a *name*, which is a shorthand for a numeric id that is the hash of that name wrt a specified hash function, e.g. SHA-256 mod 64. +An id can also be given as a *name*, which is a shorthand for a numeric id that is the hash of that name: ``` ::= ... | : := : ``` -This expansion implies that a hash collision between field names within a single record is disallowed. However, the chosen hash function makes such a collision highly unlikely in practice. -**Note:** For example, the following hash function [Jacques Garrigue, "Programming with Polymorphic Variants", ML 1998], -``` -hash(id) = ( Sum_(i=0..|id|) id[i] * 223^(|id|-1) ) mod 2^64 +The hash function is specified as ``` -guarantees that no hash collision occurs for regular identifiers of length up to 8, and that the overall likelihood of a collision for a variant with n cases is lower than +hash(id) = ( Sum_(i=0..k) id[i] * 223^(k-i) ) mod 2^32 where k = |id|-1 ``` -p(n) = Sum_(i=1..n-1) i/2^64 -``` -That is, the likelihood p(100) of a collision for a variant with 100 cases is less than 2.74 * 10^(-16). + +This expansion implies that a hash collision between field names within a single record is disallowed. + +This hash function has the the following useful properties: + + * Collisions are sufficiently rare. It has [no collisions for names up to length 4](https://caml.inria.fr/pub/papers/garrigue-polymorphic_variants-ml98.pdf). + + * It is rather simple to implement, compared to, say, a cryptographic hash function (we do not need resistence against collision attacks). + +The hash function does not have the property that every numeric value can be turned into a human-readable preimage. Host languages that cannot support numeric field names will have to come up with a suitable encoding textual encoding of numeric field names, as well as of field names that are not valid in the host langauge. ##### Shorthand: Tuple Fields From 3fd7993f41e382394ad3f3782337bb13b45b8c27 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Mon, 3 Jun 2019 11:18:22 -0600 Subject: [PATCH 0119/1176] test new trie representation; fix bugs; now functions on large PX workloads --- stdlib/Makefile | 45 ++--- stdlib/docTable.as | 11 +- .../examples/produce-exchange/serverActor.as | 4 +- .../examples/produce-exchange/serverModel.as | 65 +++++--- .../produce-exchange/serverModelTypes.as | 2 +- .../produce-exchange/test/profileLoadQuery.as | 1 + stdlib/list.as | 30 +++- stdlib/set.as | 2 +- stdlib/trie2.as | 154 ++++++++++++------ 9 files changed, 198 insertions(+), 116 deletions(-) diff --git a/stdlib/Makefile b/stdlib/Makefile index 8e3c184db2d..73e72372f3c 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -103,25 +103,6 @@ PRODUCE_EXCHANGE_SRC=\ examples/produce-exchange/serverModel.as \ examples/produce-exchange/serverActor.as \ -$(OUTDIR)/ProduceExchange.out: $(PRODUCE_EXCHANGE_SRC) \ - examples/produce-exchange/test/simpleSetupAndQuery.as | $(OUTDIR) - $(ASC) -r examples/produce-exchange/serverActor.as examples/produce-exchange/test/simpleSetupAndQuery.as > $@ - -$(OUTDIR)/retailerReserveMany.out: $(PRODUCE_EXCHANGE_SRC) \ - examples/produce-exchange/test/retailerReserveMany.as | $(OUTDIR) - $(ASC) -r examples/produce-exchange/serverActor.as examples/produce-exchange/test/retailerReserveMany.as > $@ - -$(OUTDIR)/producerRemInventory.out: $(PRODUCE_EXCHANGE_SRC) \ - examples/produce-exchange/test/producerRemInventory.as | $(OUTDIR) - $(ASC) -r examples/produce-exchange/serverActor.as examples/produce-exchange/test/producerRemInventory.as > $@ - -$(OUTDIR)/evalBulk.out: $(PRODUCE_EXCHANGE_SRC) \ - examples/produce-exchange/test/evalBulk.as | $(OUTDIR) - $(ASC) -r examples/produce-exchange/serverActor.as examples/produce-exchange/test/evalBulk.as > $@ - -$(OUTDIR)/ProduceExchange.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c --dfinity -o $@ examples/produce-exchange/serverActor.as - #########################################################################################################33 ## @@ -404,43 +385,43 @@ profile-wasm:\ $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c --dfinity -o $@ examples/produce-exchange/test/params-5-1.as examples/produce-exchange/profileActor.as + $(ASC) -c -o $@ examples/produce-exchange/test/params-5-1.as examples/produce-exchange/profileActor.as $(OUTDIR)/ProduceExchangeLoadQuery_5_2.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c --dfinity -o $@ examples/produce-exchange/test/params-5-2.as examples/produce-exchange/profileActor.as + $(ASC) -c -o $@ examples/produce-exchange/test/params-5-2.as examples/produce-exchange/profileActor.as $(OUTDIR)/ProduceExchangeLoadQuery_5_3.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c --dfinity -o $@ examples/produce-exchange/test/params-5-3.as examples/produce-exchange/profileActor.as + $(ASC) -c -o $@ examples/produce-exchange/test/params-5-3.as examples/produce-exchange/profileActor.as $(OUTDIR)/ProduceExchangeLoadQuery_5_4.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c --dfinity -o $@ examples/produce-exchange/test/params-5-4.as examples/produce-exchange/profileActor.as + $(ASC) -c -o $@ examples/produce-exchange/test/params-5-4.as examples/produce-exchange/profileActor.as $(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c --dfinity -o $@ examples/produce-exchange/test/params-5-5.as examples/produce-exchange/profileActor.as + $(ASC) -c -o $@ examples/produce-exchange/test/params-5-5.as examples/produce-exchange/profileActor.as $(OUTDIR)/ProduceExchangeLoadQuery_5_6.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c --dfinity -o $@ examples/produce-exchange/test/params-5-6.as examples/produce-exchange/profileActor.as + $(ASC) -c -o $@ examples/produce-exchange/test/params-5-6.as examples/produce-exchange/profileActor.as $(OUTDIR)/ProduceExchangeLoadQuery_5_7.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c --dfinity -o $@ examples/produce-exchange/test/params-5-7.as examples/produce-exchange/profileActor.as + $(ASC) -c -o $@ examples/produce-exchange/test/params-5-7.as examples/produce-exchange/profileActor.as $(OUTDIR)/ProduceExchangeLoadQuery_5_8.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c --dfinity -o $@ examples/produce-exchange/test/params-5-8.as examples/produce-exchange/profileActor.as + $(ASC) -c -o $@ examples/produce-exchange/test/params-5-8.as examples/produce-exchange/profileActor.as $(OUTDIR)/ProduceExchangeLoadQuery_5_9.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c --dfinity -o $@ examples/produce-exchange/test/params-5-9.as examples/produce-exchange/profileActor.as + $(ASC) -c -o $@ examples/produce-exchange/test/params-5-9.as examples/produce-exchange/profileActor.as $(OUTDIR)/ProduceExchangeLoadQuery_5_10.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c --dfinity -o $@ examples/produce-exchange/test/params-5-10.as examples/produce-exchange/profileActor.as + $(ASC) -c -o $@ examples/produce-exchange/test/params-5-10.as examples/produce-exchange/profileActor.as $(OUTDIR)/ProduceExchangeLoadQuery_5_20.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c --dfinity -o $@ examples/produce-exchange/test/params-5-20.as examples/produce-exchange/profileActor.as + $(ASC) -c -o $@ examples/produce-exchange/test/params-5-20.as examples/produce-exchange/profileActor.as $(OUTDIR)/ProduceExchangeLoadQuery_5_50.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c --dfinity -o $@ examples/produce-exchange/test/params-5-50.as examples/produce-exchange/profileActor.as + $(ASC) -c -o $@ examples/produce-exchange/test/params-5-50.as examples/produce-exchange/profileActor.as $(OUTDIR)/ProduceExchangeLoadQuery_5_100.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c --dfinity -o $@ examples/produce-exchange/test/params-5-100.as examples/produce-exchange/profileActor.as + $(ASC) -c -o $@ examples/produce-exchange/test/params-5-100.as examples/produce-exchange/profileActor.as $(OUTDIR)/time: time.c diff --git a/stdlib/docTable.as b/stdlib/docTable.as index 9bbd7d1bbbf..bf7e0cb9a64 100644 --- a/stdlib/docTable.as +++ b/stdlib/docTable.as @@ -46,7 +46,8 @@ type information. let Hash = import "hash.as"; type Hash = Hash.Hash; -let Trie = import "trie.as"; +//let Trie = import "trie.as"; +let Trie = import "trie2.as"; type Trie = Trie.Trie; type Key = Trie.Key; @@ -128,7 +129,7 @@ class DocTable( */ reset() { idNext := idFirst; - table := null; + table := Table.empty(); }; /** @@ -319,7 +320,7 @@ class DocTable( allDoc() : [Doc] { Table.toArray - (table, func (id:Id, doc:Doc):[Doc] = [doc] ) + (table, func (id:Id, doc:Doc):Doc = doc ) }; /** @@ -331,7 +332,7 @@ class DocTable( allInfo() : [Info] { Table.toArray - (table, func (id:Id, doc:Doc):[Info] = [infoOfDoc(doc)] ) + (table, func (id:Id, doc:Doc):Info = infoOfDoc(doc) ) }; @@ -356,7 +357,7 @@ class DocTable( private var idNext:Id = idFirst; - private var table : Table = null; + private var table : Table = Table.empty(); /** Helpers diff --git a/stdlib/examples/produce-exchange/serverActor.as b/stdlib/examples/produce-exchange/serverActor.as index eb184608ad8..cb9824bd8c2 100644 --- a/stdlib/examples/produce-exchange/serverActor.as +++ b/stdlib/examples/produce-exchange/serverActor.as @@ -11,7 +11,7 @@ import L = "serverLang.as"; import Model = "serverModel.as"; import Result = "../../result.as"; -let Trie = (import "../../trie.as"); +let Trie = (import "../../trie2.as"); let List = (import "../../list.as"); type List = List.List; @@ -922,7 +922,7 @@ actor class Server () { getCounts() : async T.ProduceExchangeCounts { let m = getModel(); shared { - hash_bit_length = Trie.HASH_BITS; + hash_bit_length = 0; truck_type_count = m.truckTypeTable.count(); region_count = m.regionTable.count(); produce_count = m.produceTable.count(); diff --git a/stdlib/examples/produce-exchange/serverModel.as b/stdlib/examples/produce-exchange/serverModel.as index a073cd8a63c..2f56304552f 100644 --- a/stdlib/examples/produce-exchange/serverModel.as +++ b/stdlib/examples/produce-exchange/serverModel.as @@ -35,7 +35,7 @@ let Hash = (import "../../hash.as").BitVec; type Hash = Hash.t; import Option = "../../option.as"; -import Trie = "../../trie.as"; +import Trie = "../../trie2.as"; type Trie = Trie.Trie; type Key = Trie.Key; @@ -142,10 +142,20 @@ class Model() { reservedRouteTable.reset(); /**- 2. clear secondary indices: */ - usersByUserName := null; - routesByDstSrcRegions := null; - inventoryByRegion := null; - reservationsByProduceByRegion := null; + usersByUserName + := Map.empty(); + + routesByDstSrcRegions + := Map.empty(); + + inventoryByRegion + := Map.empty(); + + reservationsByProduceByRegion + := Map.empty>>(); /**- 3. reset counters: */ joinCount := 0; @@ -923,7 +933,7 @@ secondary maps. short_name=info.short_name; description=info.description; region=regionDoc; - reserved=null; + reserved=Map.empty(); } ) ); @@ -1074,7 +1084,7 @@ secondary maps. */ private var usersByUserName - : M.UserNameMap = null; + : M.UserNameMap = Map.empty(); /** @@ -1101,7 +1111,8 @@ secondary maps. */ - private var routesByDstSrcRegions : M.ByRegionPairRouteMap = null; + private var routesByDstSrcRegions : M.ByRegionPairRouteMap + = Map.empty(); /** Inventory by region @@ -1114,7 +1125,8 @@ secondary maps. */ - private var inventoryByRegion : M.ByRegionInventoryMap = null; + private var inventoryByRegion : M.ByRegionInventoryMap + = Map.empty(); /** @@ -1144,8 +1156,11 @@ than the MVP goals, however. */ private var reservationsByProduceByRegion - : M.ByProduceByRegionInventoryReservationMap = null; - + : M.ByProduceByRegionInventoryReservationMap + = Map.empty>>(); /** @@ -1324,8 +1339,8 @@ than the MVP goals, however. ?Map.toArray( doc.inventory, - func (_:T.InventoryId,doc:M.InventoryDoc):[T.InventoryInfo] = - [inventoryTable.getInfoOfDoc()(doc)] + func (_:T.InventoryId,doc:M.InventoryDoc):T.InventoryInfo = + inventoryTable.getInfoOfDoc()(doc) ) }; @@ -1540,9 +1555,9 @@ than the MVP goals, however. doc.reserved, func (_:T.ReservedInventoryId, doc:M.ReservedInventoryDoc): - [T.ReservedInventoryInfo] + T.ReservedInventoryInfo = - [reservedInventoryTable.getInfoOfDoc()(doc)] + reservedInventoryTable.getInfoOfDoc()(doc) ) }; @@ -1756,9 +1771,9 @@ than the MVP goals, however. doc.routes, func (_:T.RouteId, doc:M.RouteDoc): - [T.RouteInfo] + T.RouteInfo = - [routeTable.getInfoOfDoc()(doc)] + routeTable.getInfoOfDoc()(doc) ) }; @@ -1779,9 +1794,9 @@ than the MVP goals, however. doc.reserved, func (_:T.ReservedRouteId, doc:M.ReservedRouteDoc): - [T.ReservedRouteInfo] + T.ReservedRouteInfo = - [reservedRouteTable.getInfoOfDoc()(doc)] + reservedRouteTable.getInfoOfDoc()(doc) ) }; @@ -2035,8 +2050,8 @@ than the MVP goals, however. T.ReservationInfo>( queryResultsMerged, func (_:(T.RouteId,T.InventoryId), (r:M.RouteDoc, i:M.InventoryDoc)) - : [ T.ReservationInfo ] { - [ makeReservationInfo(i, r) ] + : T.ReservationInfo { + makeReservationInfo(i, r) }); ?arr @@ -2064,11 +2079,11 @@ than the MVP goals, however. ((idoc:M.ReservedInventoryDoc), (rdoc:M.ReservedRouteDoc))) : - [(T.ReservedInventoryInfo, - T.ReservedRouteInfo)] + ((T.ReservedInventoryInfo, + T.ReservedRouteInfo)) = - [(reservedInventoryTable.getInfoOfDoc()(idoc), - reservedRouteTable.getInfoOfDoc()(rdoc))] + ( (reservedInventoryTable.getInfoOfDoc()(idoc), + reservedRouteTable.getInfoOfDoc()(rdoc)) ) ) }; diff --git a/stdlib/examples/produce-exchange/serverModelTypes.as b/stdlib/examples/produce-exchange/serverModelTypes.as index f71024c79de..56ce4a7ca35 100644 --- a/stdlib/examples/produce-exchange/serverModelTypes.as +++ b/stdlib/examples/produce-exchange/serverModelTypes.as @@ -35,7 +35,7 @@ Representation import T = "serverTypes.as"; -import Trie = "../../trie.as"; +import Trie = "../../trie2.as"; type Trie = Trie.Trie; type Map = Trie; diff --git a/stdlib/examples/produce-exchange/test/profileLoadQuery.as b/stdlib/examples/produce-exchange/test/profileLoadQuery.as index f359b59c310..eb15d400c01 100644 --- a/stdlib/examples/produce-exchange/test/profileLoadQuery.as +++ b/stdlib/examples/produce-exchange/test/profileLoadQuery.as @@ -8,6 +8,7 @@ func scaledParams(region_count_:Nat, factor:Nat) : T.WorkloadParams = { retailer_count = region_count * factor:Nat; } }; +let server = Server(); let _ = server.loadWorkload(scaledParams(region_count, scale_factor)); let _ = server.retailerQueryAll("", 0, null, null); server.getCounts() diff --git a/stdlib/list.as b/stdlib/list.as index d25ce4cf8bf..17b95517726 100644 --- a/stdlib/list.as +++ b/stdlib/list.as @@ -93,6 +93,30 @@ type List = ?(T, List); rec(l,0) }; + /** + `lenIsLessThan` + -------- + test length against a maximum value; tail recursive + */ + func lenIsEqLessThan(l : List, i : Nat) : Bool = + label profile_list_lenIsEqLessThan_begin : Bool { + func rec(l : List, i : Nat) : Bool = label profile_list_lenIsEqLessThan_rec : Bool { + switch l { + case null label profile_list_lenIsEqLessThan_end_true : Bool true; + case (?(_, t)) { + if ( i == 0 ) { + label profile_list_lenIsEqLessThan_end_false : Bool + false + } + else { + rec(t, i - 1) + } + }; + } + }; + rec(l, i) + }; + /** `nth` --------- @@ -174,13 +198,15 @@ type List = ?(T, List); split the list elements; non-tail recursive */ func split(l : List, f:T -> Bool) : (List, List) = { - func rec(l : List) : (List, List) { + func rec(l : List) : (List, List) = + label profile_list_split_rec : (List, List) { switch l { case null { (null, null) }; case (?(h,t)) { let (l,r) = rec(t) ; if (f(h)){ (?(h,l), r) } else { (l, ?(h,r)) } }; } }; + label profile_list_split_begin : (List, List) rec(l) }; @@ -343,7 +369,7 @@ type List = ?(T, List); func rec(l:List) : Bool { switch l { case null { true }; - case (?(h,t)) { if (f(h)) { false } else { rec(t) } }; + case (?(h,t)) { if (not f(h)) { false } else { rec(t) } }; } }; rec(l) diff --git a/stdlib/set.as b/stdlib/set.as index a0d4a72254b..7d13eba0508 100644 --- a/stdlib/set.as +++ b/stdlib/set.as @@ -18,7 +18,7 @@ */ -let Trie = import "trie.as"; +let Trie = import "trie2.as"; let Hash = import "hash.as"; type Hash = Hash.Hash; diff --git a/stdlib/trie2.as b/stdlib/trie2.as index d6ad038bc08..b7b333a01f6 100644 --- a/stdlib/trie2.as +++ b/stdlib/trie2.as @@ -48,7 +48,7 @@ leaf, which contains up to MAX_LEAF_COUNT key-value pairs. By construction, the algorithms below enforce the invariant that no leaf ever contains more than MAX_LEAF_COUNT key-value pairs: the function `leaf` accepts a list, but subdivides it with branches until -it can actually construct valid leaves. Once distinguished, subsets +it can actually construct valid leaves. Ongce distinguished, subsets of keys tend to remain distinguished by the presence of these branches. ### Cached counts @@ -68,7 +68,9 @@ Below, we define the types used in the representation: */ -let MAX_LEAF_COUNT = 32; +//let MAX_LEAF_COUNT = 32; +let MAX_LEAF_COUNT = 16; // <-- beats both 32 and 8, for me. +//let MAX_LEAF_COUNT = 8; let P = (import "prelude.as"); @@ -121,6 +123,60 @@ type Trie = { #branch : Branch ; }; +func isValid (t:Trie, enforceNormal:Bool) : Bool { + func rec(t:Trie, bitpos:?Hash, bits:Hash, mask:Hash) : Bool { + switch t { + case (#empty) { + switch bitpos { + case null true; + case (?_) not enforceNormal; + } + }; + case (#leaf l) { + let len = List.len<(Key,V)>(l.keyvals); + ((len <= MAX_LEAF_COUNT) or (not enforceNormal)) + and + len == l.count + and + ( List.all<(Key,V)>( + l.keyvals, + func ((k:Key,v:V)):Bool{ + //{ print "testing hash..."; true } + //and + ((k.hash & mask) == bits) + or + { print "\nmalformed hash!:\n"; + printInt (word32ToNat(k.hash)); + print "\n (key hash) != (path bits): \n"; + printInt (word32ToNat(bits)); + print "\nmask : "; printInt (word32ToNat(mask)); + print "\n"; + false } + } + ) or + { print "one or more hashes are malformed"; false } + ) + }; + case (#branch b) { + let bitpos1 = switch bitpos { + case null (natToWord32(0)); + case (?bp) (natToWord32(word32ToNat(bp) + 1)) + }; + let mask1 = mask | (natToWord32(1) << bitpos1); + let bits1 = bits | (natToWord32(1) << bitpos1); + let sum = count(b.left) + count(b.right); + (b.count == sum or { print "malformed count"; false }) + and + rec(b.left, ?bitpos1, bits, mask1) + and + rec(b.right, ?bitpos1, bits1, mask1) + }; + } + }; + rec(t, null, 0, 0) +}; + + /** Two-dimensional trie --------------------- @@ -169,41 +225,20 @@ type Trie3D = Trie >; } }; - /** `branch` -------- Construct a branch node, computing the count stored there. - - ### edge case: 0 or 1 elements: - - if the left and right in sum have fewer than 2 key-value pairs, - then a leaf or empty node suffices, so do not make a branch. - - otherwise, we make a branch normally, regardless of the sizes: - our rationale is that the l-vs-r keys have already been distinguished, - so let's memorialize that work with a branch, regardless of how small. */ func branch(l:Trie, r:Trie) : Trie { - func c(t:Trie) : Nat = count(t); - let sum = c(l) + c(r); - /** handle edge case: */ - if ( sum < 2 ) { - switch (nth(l,0), nth(r,0)) { - case (null, null) { #empty }; - case (?kv, null) { leaf(?(kv,null),0) }; - case (null, ?kv ) { leaf(?(kv,null),0) }; - case (?kv1, ?kv2) { P.unreachable() }; + let sum = count(l) + count(r); + #branch( + new{ + count=sum; + left=l; + right=r } - } else { - #branch( - new{ - count=sum; - left=l; - right=r - } - ) - } + ); }; /** @@ -216,16 +251,29 @@ type Trie3D = Trie >; of the leaf. */ - func leaf(kvs:AssocList,V>, bitpos:Nat) : Trie { + func leaf(kvs:AssocList,V>, bitpos:Nat) : Trie = + fromList(kvs, bitpos); + + + func fromList(kvs:AssocList,V>, bitpos:Nat) : Trie = + label profile_trie_fromList_begin : (Trie) { func rec(kvs:AssocList,V>, bitpos:Nat) : Trie { - let len = List.len<(Key,V)>(kvs); - if ( len < MAX_LEAF_COUNT ) { - #leaf( - new{ - count=len; - keyvals=kvs - }) - } else { + if ( List.isNil<(Key,V)>(kvs) ) + label profile_trie_fromList_end_empty : (Trie) { + #empty + } + else if ( List.lenIsEqLessThan<(Key,V)>(kvs, MAX_LEAF_COUNT - 1) ) + label profile_trie_fromList_end_validleaf : (Trie) { + let len = List.len<(Key,V)>(kvs); + #leaf(new{count=len;keyvals=kvs}) + } + else if ( bitpos >= 31 ) + label profile_trie_fromList_end_bitposIs31 : (Trie) { + let len = List.len<(Key,V)>(kvs); + #leaf(new{count=len;keyvals=kvs}) + } + else /* too many keys for a leaf, so introduce a branch */ + label profile_trie_fromList_branch : (Trie) { let (l, r) = splitAssocList(kvs, bitpos); branch(rec(l, bitpos + 1), rec(r, bitpos + 1)) } @@ -233,6 +281,7 @@ type Trie3D = Trie >; rec(kvs, bitpos) }; + /** `copy` --------- @@ -245,8 +294,10 @@ type Trie3D = Trie >; --------- replace the given key's value option with the given one, returning the previous one */ - func replace(t : Trie, k:Key, k_eq:(K,K)->Bool, v:?V) : (Trie, ?V) { + func replace(t : Trie, k:Key, k_eq:(K,K)->Bool, v:?V) : (Trie, ?V) = + label profile_trie_replace : (Trie, ?V) { let key_eq = keyEq(k_eq); + func rec(t : Trie, bitpos:Nat) : (Trie, ?V) { switch t { case (#empty) { @@ -272,7 +323,9 @@ type Trie3D = Trie >; }; } }; - rec(t, 0) + let (to, vo) = rec(t, 0); + //assert(isValid(to, false)); + (to, vo) }; /** @@ -280,7 +333,8 @@ type Trie3D = Trie >; ------------ insert the given key's value in the trie; return the new trie, and the previous value associated with the key, if any */ - func insert(t : Trie, k:Key, k_eq:(K,K)->Bool, v:V) : (Trie, ?V) { + func insert(t : Trie, k:Key, k_eq:(K,K)->Bool, v:V) : (Trie, ?V) = + label profile_trie_insert : (Trie, ?V) { replace(t, k, k_eq, ?v) }; @@ -326,8 +380,8 @@ type Trie3D = Trie >; { List.split<(Key,V)>( al, - func ((k : Key, v : V)) : Bool{ - Hash.getHashBit(k.hash, bitpos) + func ((k : Key, v : V)) : Bool { + not Hash.getHashBit(k.hash, bitpos) } ) }; @@ -432,8 +486,10 @@ type Trie3D = Trie >; rec(bitpos, tl, br(lf ll, lf lr)) }; case (#branch b1, #branch b2) { - br(rec(bitpos + 1, b1.left, b2.left), - rec(bitpos + 1, b1.right, b2.right)) + branch( + rec(bitpos + 1, b1.left, b2.left), + rec(bitpos + 1, b1.right, b2.right) + ) }; } @@ -785,7 +841,7 @@ type Trie3D = Trie >; func nth(t:Trie, i:Nat) : ?(Key, V) { func rec(t:Trie, i:Nat) : ?(Key, V) { switch t { - case (#empty) null; + case (#empty) P.unreachable(); case (#leaf l) List.nth<(Key,V)>(l.keyvals, i); case (#branch b) { let count_left = count(b.left); @@ -794,7 +850,9 @@ type Trie3D = Trie >; } } }; - assert (i < count(t)); + if (i >= count(t)) { + return null + }; rec(t, i) }; From 15e2d0584ad22c464869ae6c679c122542d0917b Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Mon, 3 Jun 2019 11:49:32 -0600 Subject: [PATCH 0120/1176] stdlib doc nit --- stdlib/trie2.as | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/trie2.as b/stdlib/trie2.as index b7b333a01f6..a0008b87d08 100644 --- a/stdlib/trie2.as +++ b/stdlib/trie2.as @@ -869,8 +869,8 @@ type Trie3D = Trie >; Performance Profiling shows that it is important that this be memory efficient, and reasonably time efficient, at large scales. - To do so, we use a single array allocation: The returned array. To do so, we - sacrifice some efficiency in reading the input trie, and use function `nth` to + To do so, we use a single array allocation (for the returned array) and we + sacrifice some efficiency in reading the input trie, and instead use function `nth` to project each element with an independent trie traversal. This approach is somewhat forced on us by the type signature of From 22ba9d26ff7db5411464e7c7d4fbe220419e70d1 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Tue, 4 Jun 2019 14:13:07 +0200 Subject: [PATCH 0121/1176] Fix Word8/16 division miscompilation (#470) * failing tests for issue #422 * msb_adjust word div result fixes #422 --- src/compile.ml | 3 ++- test/run/numeric-ops.as | 14 ++++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/compile.ml b/src/compile.ml index 5c731512978..79f7f522b9f 100644 --- a/src/compile.ml +++ b/src/compile.ml @@ -4387,7 +4387,8 @@ let rec compile_binop env t op = | Type.Prim Type.(Word8 | Word16 | Word32), SubOp -> G.i (Binary (Wasm.Values.I32 I32Op.Sub)) | Type.(Prim (Word8|Word16|Word32 as ty)), MulOp -> UnboxedSmallWord.lsb_adjust ty ^^ G.i (Binary (Wasm.Values.I32 I32Op.Mul)) - | Type.Prim Type.(Word8 | Word16 | Word32), DivOp -> G.i (Binary (Wasm.Values.I32 I32Op.DivU)) + | Type.(Prim (Word8|Word16|Word32 as ty)), DivOp -> G.i (Binary (Wasm.Values.I32 I32Op.DivU)) ^^ + UnboxedSmallWord.msb_adjust ty | Type.Prim Type.(Word8 | Word16 | Word32), ModOp -> G.i (Binary (Wasm.Values.I32 I32Op.RemU)) | Type.(Prim (Word8|Word16|Word32 as ty)), PowOp -> let rec pow () = Func.share_code2 env (UnboxedSmallWord.name_of_type ty "pow") diff --git a/test/run/numeric-ops.as b/test/run/numeric-ops.as index fb0a238a743..923a82c0c1b 100644 --- a/test/run/numeric-ops.as +++ b/test/run/numeric-ops.as @@ -133,7 +133,10 @@ func testWord8(a : Word8, b : Word8) : [Word8] { [pos1, pos2, neg1, neg2, sum1, sum2, diff1, diff2, prod1, prod2, rat1, rat2, mod1, mod2, pow1, pow2] }; -verify([3, 253, 8, 254, 15, 0, 3, 243], testWord8(3, 5), func (a : Word8, b : Word8) : Bool = a == b); +func word8Compare(a : Word8, b : Word8) : Bool = a == b; +verify([3, 253, 8, 254, 15, 0, 3, 243], testWord8(3, 5), word8Compare); + +verify([25, 231, 30, 20, 125, 5, 0, 249], testWord8(25, 5), word8Compare); func testWord16(a : Word16, b : Word16) : [Word16] { let pos1 = + a; @@ -155,7 +158,9 @@ func testWord16(a : Word16, b : Word16) : [Word16] { [pos1, pos2, neg1, neg2, sum1, sum2, diff1, diff2, prod1, prod2, rat1, rat2, mod1, mod2, pow1, pow2] }; -verify([3, 65533, 8, 65534, 15, 0, 3, 243], testWord16(3, 5), func (a : Word16, b : Word16) : Bool = a == b); +func word16Compare(a : Word16, b : Word16) : Bool = a == b; +verify([3, 65533, 8, 65534, 15, 0, 3, 243], testWord16(3, 5), word16Compare); +verify([25, 65511, 30, 20, 125, 5, 0, 761], testWord16(25, 5), word16Compare); func testWord32(a : Word32, b : Word32) : [Word32] { let pos1 = + a; @@ -177,8 +182,9 @@ func testWord32(a : Word32, b : Word32) : [Word32] { [pos1, pos2, neg1, neg2, sum1, sum2, diff1, diff2, prod1, prod2, rat1, rat2, mod1, mod2, pow1, pow2] }; -verify([3, 4_294_967_293, 8, 4_294_967_294, 15, 0, 3, 243], testWord32(3, 5), - func (a : Word32, b : Word32) : Bool = a == b); +func word32Compare(a : Word32, b : Word32) : Bool = a == b; +verify([3, 4_294_967_293, 8, 4_294_967_294, 15, 0, 3, 243], testWord32(3, 5), word32Compare); +verify([25, 4_294_967_271, 30, 20, 125, 5, 0, 9765625], testWord32(25, 5), word32Compare); func testWord64(a : Word64, b : Word64) : [Word64] { let pos1 = + a; From 0360cdc2c36e4ce13fce0b877bae2eee73f75bc7 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 4 Jun 2019 17:13:29 +0200 Subject: [PATCH 0122/1176] Add `` to grammar overview (#467) must have been lost in some commit or so. --- design/IDL.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/design/IDL.md b/design/IDL.md index 8e6b0ef004d..76ce46fea2e 100644 --- a/design/IDL.md +++ b/design/IDL.md @@ -66,7 +66,7 @@ This is a summary of the grammar proposed: ::= : ( | ) ::= ( ,* ) -> ( ,* ) * ::= oneway | pure - ::= + ::= : ::= | | | ::= @@ -105,9 +105,6 @@ In addition to this basic grammar, a few syntactic shorthands are supported that ::= ... | blob := vec nat8 - ::= ... - | : := - ::= ... | : := : | := N : where N is either 0 or previous + 1 (only in records) From 9b780b3fb50c3123438a75a0863b8bc12c65fac8 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Tue, 4 Jun 2019 21:56:59 -0700 Subject: [PATCH 0123/1176] add tests for idl compiler --- idl/.merlin | 4 +++ idl/Makefile | 6 ++++- idl/compile_js.ml | 26 +++++++++--------- idl/main.ml | 12 ++++----- idl/pipeline.ml | 8 +++--- idl/pipeline.mli | 6 ++--- idl/typing_idl.ml | 2 ++ test/idl/actor.didl | 5 ++++ test/idl/collision_fields.didl | 6 +++++ test/idl/cyclic.didl | 13 +++++++++ test/idl/fields.didl | 13 +++++++++ test/idl/ok/actor.js.ok | 3 +++ test/idl/ok/actor.tc.ok | 3 +++ test/idl/ok/collision_fields.tc.ok | 3 +++ test/idl/ok/cyclic.tc.ok | 3 +++ test/idl/ok/fields.js.ok | 14 ++++++++++ test/idl/ok/fields.tc.ok | 6 +++++ test/idl/ok/oneway.tc.ok | 3 +++ test/idl/ok/{px.idlc.ok => px.js.ok} | 2 +- test/idl/ok/px.tc.ok | 11 ++++++++ test/idl/ok/recursion.js.ok | 15 +++++++++++ test/idl/ok/recursion.tc.ok | 10 +++++++ test/idl/ok/test.idlc.ok | 40 ---------------------------- test/idl/ok/test.js.ok | 21 +++++++++++++++ test/idl/ok/test.tc.ok | 6 +++++ test/idl/ok/unbound_actor.tc.ok | 3 +++ test/idl/ok/undefine.tc.ok | 3 +++ test/idl/ok/unicode.js.ok | 11 ++++++++ test/idl/ok/unicode.tc.ok | 4 +++ test/idl/ok/variant.tc.ok | 3 +++ test/idl/oneway.didl | 3 +++ test/idl/px.didl | 6 ----- test/idl/recursion.didl | 13 +++++++++ test/idl/test.didl | 35 +++++------------------- test/idl/unbound_actor.didl | 4 +++ test/idl/undefine.didl | 4 +++ test/idl/unicode.didl | 14 ++++++++++ test/idl/variant.didl | 3 +++ test/run.sh | 17 +++++++++--- 39 files changed, 257 insertions(+), 107 deletions(-) create mode 100644 idl/.merlin create mode 100644 test/idl/actor.didl create mode 100644 test/idl/collision_fields.didl create mode 100644 test/idl/cyclic.didl create mode 100644 test/idl/fields.didl create mode 100644 test/idl/ok/actor.js.ok create mode 100644 test/idl/ok/actor.tc.ok create mode 100644 test/idl/ok/collision_fields.tc.ok create mode 100644 test/idl/ok/cyclic.tc.ok create mode 100644 test/idl/ok/fields.js.ok create mode 100644 test/idl/ok/fields.tc.ok create mode 100644 test/idl/ok/oneway.tc.ok rename test/idl/ok/{px.idlc.ok => px.js.ok} (97%) create mode 100644 test/idl/ok/px.tc.ok create mode 100644 test/idl/ok/recursion.js.ok create mode 100644 test/idl/ok/recursion.tc.ok delete mode 100644 test/idl/ok/test.idlc.ok create mode 100644 test/idl/ok/test.js.ok create mode 100644 test/idl/ok/test.tc.ok create mode 100644 test/idl/ok/unbound_actor.tc.ok create mode 100644 test/idl/ok/undefine.tc.ok create mode 100644 test/idl/ok/unicode.js.ok create mode 100644 test/idl/ok/unicode.tc.ok create mode 100644 test/idl/ok/variant.tc.ok create mode 100644 test/idl/oneway.didl create mode 100644 test/idl/recursion.didl create mode 100644 test/idl/unbound_actor.didl create mode 100644 test/idl/undefine.didl create mode 100644 test/idl/unicode.didl create mode 100644 test/idl/variant.didl diff --git a/idl/.merlin b/idl/.merlin new file mode 100644 index 00000000000..7e0e2689936 --- /dev/null +++ b/idl/.merlin @@ -0,0 +1,4 @@ +B _build +PKG stdint wasm num vlq yojson +FLG -w +a-4-27-30-42-44-45 + diff --git a/idl/Makefile b/idl/Makefile index d76a2b19048..a64af0c5b24 100644 --- a/idl/Makefile +++ b/idl/Makefile @@ -2,7 +2,7 @@ NAME = idlc BUILD = byte MAIN = main -IDL = `pwd`/$(NAME) +IDLC = `pwd`/$(NAME) OPAM_PACKAGES = wasm stdint num vlq yojson @@ -29,4 +29,8 @@ sanity: clean: rm -f *~ .*~ $(OCAMLBUILD) -clean + $(MAKE) -C ../test/idl clean + +test: $(NAME) + $(MAKE) -C ../test/idl IDLC=$(IDLC) all diff --git a/idl/compile_js.ml b/idl/compile_js.ml index 6b20ba70c63..a3ca3c542e7 100644 --- a/idl/compile_js.ml +++ b/idl/compile_js.ml @@ -54,7 +54,7 @@ and pp_field ppf env tf = and pp_meth ppf env meth = pp_open_box ppf 1; - id ppf meth.it.var; + field_name ppf meth.it.var; kwd ppf ":"; pp_typ ppf env meth.it.meth; pp_close_box ppf () @@ -74,19 +74,19 @@ let pp_dec ppf env dec = let pp_actor ppf env actor_opt = pp_open_hovbox ppf 1; - kwd ppf "const"; (match actor_opt with - None -> () - | Some actor -> - (match actor.it with - | ActorD (x, {it=ServT tp; _}) -> - id ppf x; space ppf (); kwd ppf "="; kwd ppf "new"; - str ppf "IDL.ActorInterface({"; - concat ppf pp_meth env "," tp; - str ppf "})" - | ActorD (x, {it=VarT var; _}) -> id ppf x; space ppf (); kwd ppf "="; id ppf var - | ActorD (x, _) -> () - ) + None -> () + | Some actor -> + kwd ppf "const"; + (match actor.it with + | ActorD (x, {it=ServT tp; _}) -> + id ppf x; space ppf (); kwd ppf "="; kwd ppf "new"; + str ppf "IDL.ActorInterface({"; + concat ppf pp_meth env "," tp; + str ppf "})" + | ActorD (x, {it=VarT var; _}) -> id ppf x; space ppf (); kwd ppf "="; id ppf var + | ActorD (x, _) -> () + ) ); pp_close_box ppf () diff --git a/idl/main.ml b/idl/main.ml index e77989bfda2..408d2384017 100644 --- a/idl/main.ml +++ b/idl/main.ml @@ -8,7 +8,7 @@ let usage = "Usage: " ^ name ^ " [option] [file ...]" (* Argument handling *) -type mode = Default | Check | Compile +type mode = Default | Check | Js let mode = ref Default let args = ref [] @@ -24,7 +24,7 @@ let out_file = ref "" let argspec = Arg.align [ - "-c", Arg.Unit (set_mode Compile), " compile programs to WebAssembly"; + "--js", Arg.Unit (set_mode Js), " output Javascript binding"; "--check", Arg.Unit (set_mode Check), " type-check only"; "-v", Arg.Set Flags.verbose, " verbose output"; "-dp", Arg.Set Flags.dump_parse, " dump parse"; @@ -54,10 +54,10 @@ let process_files files : unit = Flags.verbose := true; let (_, msgs) = exit_on_failure (Pipeline.(check_file (List.hd files))) in Diag.print_messages msgs - | Compile -> + | Js -> let out = exit_on_failure (Pipeline.(compile_js_file (List.hd files))) in - Buffer.contents out |> print_endline - + Buffer.contents out |> print_endline + let print_exn exn = Printf.printf "%!"; Printf.eprintf "Internal error, %s\n" (Printexc.to_string exn); @@ -72,7 +72,7 @@ let () = Printexc.record_backtrace true; try Arg.parse argspec add_arg usage; - if !mode = Default then mode := Compile; + if !mode = Default then mode := Js; process_files !args with exn -> print_exn exn diff --git a/idl/pipeline.ml b/idl/pipeline.ml index bac319f63ed..0bd19dda98b 100644 --- a/idl/pipeline.ml +++ b/idl/pipeline.ml @@ -79,15 +79,15 @@ let check_with parse check senv name : check_result = let check_file' senv name = check_with parse_file Typing.check_prog senv name let check_file name = check_file' initial_stat_env name -(* Compilation *) +(* JS Compilation *) -type compile_result = (Buffer.t, Diag.messages) result +type compile_js_result = (Buffer.t, Diag.messages) result -let compile_js_file name : compile_result = +let compile_js_file name : compile_js_result = match check_file name with | Error msgs -> Error msgs | Ok ((prog, scope), msgs) -> Diag.print_messages msgs; - phase "Compiling" name; + phase "JS Compiling" name; let buf = Compile_js.compile scope prog in Ok buf diff --git a/idl/pipeline.mli b/idl/pipeline.mli index ab8414b9072..1855f29954e 100644 --- a/idl/pipeline.mli +++ b/idl/pipeline.mli @@ -10,7 +10,5 @@ val parse_file : string -> parse_result type check_result = (Syntax_idl.prog * Typing_idl.scope) Diag.result val check_file : string -> check_result -type compile_result = (Buffer.t, Diag.messages) result -val compile_js_file : string -> compile_result - - +type compile_js_result = (Buffer.t, Diag.messages) result +val compile_js_file : string -> compile_js_result diff --git a/idl/typing_idl.ml b/idl/typing_idl.ml index 31c83cfcc81..1d36a3d32ff 100644 --- a/idl/typing_idl.ml +++ b/idl/typing_idl.ml @@ -103,6 +103,8 @@ let rec check_typ env t = | FuncT (ms, t1, t2) -> let t1' = check_fields env t1 in let t2' = check_fields env t2 in + if List.exists (fun m -> m.it == Oneway) ms && List.length t2 > 0 then + error env t.at "oneway function has non-unit return type"; FuncT (ms, t1', t2') @@ t.at | OptT t -> OptT (check_typ env t) @@ t.at | VecT t -> VecT (check_typ env t) @@ t.at diff --git a/test/idl/actor.didl b/test/idl/actor.didl new file mode 100644 index 00000000000..61f656a3a3a --- /dev/null +++ b/test/idl/actor.didl @@ -0,0 +1,5 @@ +type f = func (nat) -> (nat) pure; +service A { + f : (nat) -> (); + g : f; +} diff --git a/test/idl/collision_fields.didl b/test/idl/collision_fields.didl new file mode 100644 index 00000000000..a98cf39e44a --- /dev/null +++ b/test/idl/collision_fields.didl @@ -0,0 +1,6 @@ +type D = record { + reserved; nat; nat; nat; + 2:nat; + nat; +}; + diff --git a/test/idl/cyclic.didl b/test/idl/cyclic.didl new file mode 100644 index 00000000000..6f5478e5d50 --- /dev/null +++ b/test/idl/cyclic.didl @@ -0,0 +1,13 @@ +type A = opt B; +type B = opt C; +type C = A; + +type X = Y; +type Y = Z; +type Z = A; + +type D = E; +type E = F; +type F = G; +type G = D; + diff --git a/test/idl/fields.didl b/test/idl/fields.didl new file mode 100644 index 00000000000..cf6f72f46ef --- /dev/null +++ b/test/idl/fields.didl @@ -0,0 +1,13 @@ +type A = record {nat;nat;nat;}; +type B = record {blob; 35:blob;nat;nat;named_files:reserved;nat;nat}; +type C = variant {red;4;3;2;1;reserved;10;green;blue;A;B;C}; + +type nest_record = record { + nat;nat;nat; + record { + nat;nat;nat; + }; + nat;nat;nat; + A;B;C;nat; +}; + diff --git a/test/idl/ok/actor.js.ok b/test/idl/ok/actor.js.ok new file mode 100644 index 00000000000..84f943ea017 --- /dev/null +++ b/test/idl/ok/actor.js.ok @@ -0,0 +1,3 @@ +const f = IDL.message(IDL.Obj({'0': IDL.nat}), IDL.Obj({'0': IDL.nat})) +const A = new IDL.ActorInterface({ + 'f': IDL.message(IDL.Obj({'0': IDL.nat}), IDL.Obj({})), 'g': f}) diff --git a/test/idl/ok/actor.tc.ok b/test/idl/ok/actor.tc.ok new file mode 100644 index 00000000000..505e326f3f4 --- /dev/null +++ b/test/idl/ok/actor.tc.ok @@ -0,0 +1,3 @@ +-- Parsing actor.didl: +-- Checking actor.didl: +var f : (0 : nat) -> (0 : nat) pure diff --git a/test/idl/ok/collision_fields.tc.ok b/test/idl/ok/collision_fields.tc.ok new file mode 100644 index 00000000000..b6108787dd8 --- /dev/null +++ b/test/idl/ok/collision_fields.tc.ok @@ -0,0 +1,3 @@ +-- Parsing collision_fields.didl: +-- Checking collision_fields.didl: +collision_fields.didl:3.2-3.3: type error, field name 2 hash collision with field 2 diff --git a/test/idl/ok/cyclic.tc.ok b/test/idl/ok/cyclic.tc.ok new file mode 100644 index 00000000000..08c562794f5 --- /dev/null +++ b/test/idl/ok/cyclic.tc.ok @@ -0,0 +1,3 @@ +-- Parsing cyclic.didl: +-- Checking cyclic.didl: +cyclic.didl:9.10-9.11: type error, D has a cyclic type definition diff --git a/test/idl/ok/fields.js.ok b/test/idl/ok/fields.js.ok new file mode 100644 index 00000000000..09c1c2da177 --- /dev/null +++ b/test/idl/ok/fields.js.ok @@ -0,0 +1,14 @@ +const A = IDL.Obj({'0': IDL.nat, '1': IDL.nat, '2': IDL.nat}) +const B = + IDL.Obj({'0': IDL.Arr(IDL.nat8), '35': IDL.Arr(IDL.nat8), '36': IDL.nat, + '37': IDL.nat, 'named_files': IDL.reserved, '653352244': IDL.nat, + '653352245': IDL.nat}) +const C = + IDL.Variant({'red': IDL.null, '4': IDL.null, '3': IDL.null, '2': IDL.null, + '1': IDL.null, 'reserved': IDL.null, '10': IDL.null, 'green': IDL.null, + 'blue': IDL.null, 'A': IDL.null, 'B': IDL.null, 'C': IDL.null}) +const nest_record = + IDL.Obj({'0': IDL.nat, '1': IDL.nat, '2': IDL.nat, + '3': IDL.Obj({'0': IDL.nat, '1': IDL.nat, '2': IDL.nat}), '4': IDL.nat, + '5': IDL.nat, '6': IDL.nat, '7': A, '8': B, '9': C, '10': IDL.nat}) + diff --git a/test/idl/ok/fields.tc.ok b/test/idl/ok/fields.tc.ok new file mode 100644 index 00000000000..881ec9d4eed --- /dev/null +++ b/test/idl/ok/fields.tc.ok @@ -0,0 +1,6 @@ +-- Parsing fields.didl: +-- Checking fields.didl: +var A : {0 : nat; 1 : nat; 2 : nat} +var B : {0 : vec nat8; 35 : vec nat8; 36 : nat; 37 : nat; named_files : reserved; 653352244 : nat; 653352245 : nat} +var C : variant {1 : null; 2 : null; 3 : null; 4 : null; 10 : null; C : null; red : null; A : null; B : null; reserved : null; green : null; blue : null} +var nest_record : {0 : nat; 1 : nat; 2 : nat; 3 : {0 : nat; 1 : nat; 2 : nat}; 4 : nat; 5 : nat; 6 : nat; 7 : var A; 8 : var B; 9 : var C; 10 : nat} diff --git a/test/idl/ok/oneway.tc.ok b/test/idl/ok/oneway.tc.ok new file mode 100644 index 00000000000..d34873d9000 --- /dev/null +++ b/test/idl/ok/oneway.tc.ok @@ -0,0 +1,3 @@ +-- Parsing oneway.didl: +-- Checking oneway.didl: +oneway.didl:2.15-2.41: type error, oneway function has non-unit return type diff --git a/test/idl/ok/px.idlc.ok b/test/idl/ok/px.js.ok similarity index 97% rename from test/idl/ok/px.idlc.ok rename to test/idl/ok/px.js.ok index bbc8019ccf4..765c7e2e47f 100644 --- a/test/idl/ok/px.idlc.ok +++ b/test/idl/ok/px.js.ok @@ -12,5 +12,5 @@ const OpEntId = IDL.Opt(EntId) const IdErr = IDL.Obj({'idErr': OpEntId}) const Inventory = IDL.Obj({'produce_id': IDL.nat, 'quantity': IDL.nat}) const ProduceExchange = new IDL.ActorInterface({ - getInventory: + 'getInventory': IDL.message(IDL.Obj({'producer_id': IDL.nat}), IDL.Obj({'0': Inventory}))}) diff --git a/test/idl/ok/px.tc.ok b/test/idl/ok/px.tc.ok new file mode 100644 index 00000000000..e58929a4c5b --- /dev/null +++ b/test/idl/ok/px.tc.ok @@ -0,0 +1,11 @@ +-- Parsing px.didl: +-- Checking px.didl: +var EntId : {truckType : var TruckTypeId; user : var UserId; region : var RegionId} +var IdErr : {idErr : var OpEntId} +var Inventory : {quantity : nat; produce_id : nat} +var OpEntId : opt var EntId +var ProducerId : nat +var RegionId : nat +var TruckTypeId : nat +var UserId : nat +var UserInfo : {description : text; user_name : text; produceId : opt var ProducerId; id : var UserId; public_key : text; region : var RegionId} diff --git a/test/idl/ok/recursion.js.ok b/test/idl/ok/recursion.js.ok new file mode 100644 index 00000000000..0e181196071 --- /dev/null +++ b/test/idl/ok/recursion.js.ok @@ -0,0 +1,15 @@ +const A = B +const B = IDL.Opt(A) +const node = IDL.Obj({'head': IDL.nat, 'tail': list}) +const list = IDL.Opt(node) +const tree = + IDL.Variant({'leaf': IDL.int, + 'branch': IDL.Obj({'left': tree, 'val': IDL.int, 'right': tree})}) +const s = IDL.ActorInterface({'f': t}) +const t = IDL.message(IDL.Obj({'server': s}), IDL.Obj({})) +const stream = + IDL.Opt( + IDL.Obj({'head': IDL.nat, + 'next': IDL.message(IDL.Obj({}), IDL.Obj({'0': stream}))})) + +const A = s diff --git a/test/idl/ok/recursion.tc.ok b/test/idl/ok/recursion.tc.ok new file mode 100644 index 00000000000..1f556243b6b --- /dev/null +++ b/test/idl/ok/recursion.tc.ok @@ -0,0 +1,10 @@ +-- Parsing recursion.didl: +-- Checking recursion.didl: +var A : var B +var B : opt var A +var list : opt var node +var node : {head : nat; tail : var list} +var s : service {f : var t} +var stream : opt {head : nat; next : () -> (0 : var stream) pure} +var t : (server : var s) -> () +var tree : variant {branch : {right : var tree; val : int; left : var tree}; leaf : int} diff --git a/test/idl/ok/test.idlc.ok b/test/idl/ok/test.idlc.ok deleted file mode 100644 index 0bbd4a5bfaa..00000000000 --- a/test/idl/ok/test.idlc.ok +++ /dev/null @@ -1,40 +0,0 @@ -const my_type = IDL.nat -const B = my_type -const C = E -const E = IDL.Opt(C) -const node = IDL.Obj({'head': IDL.nat, 'tail': list}) -const list = IDL.Opt(node) -const enum = - IDL.Variant({'red': IDL.null, 'blue': IDL.null, 'green': IDL.null}) -const message = IDL.Obj({'name': IDL.text, '25': C, '26': IDL.reserved}) -const test = - IDL.Obj({'0': IDL.nat, '1': IDL.nat, '2': IDL.nat, '99': IDL.nat, - '100': IDL.nat, 'named_field': IDL.nat, '108546619': IDL.nat, - '108546620': IDL.nat, '108546621': IDL.nat}) -const nest_record = - IDL.Obj({'0': IDL.nat, '1': IDL.nat, '2': IDL.nat, - '3': IDL.Obj({'0': IDL.nat, '1': IDL.nat, '2': IDL.nat}), '4': IDL.nat, - '5': IDL.nat, '6': IDL.nat}) -const tree = - IDL.Variant({'leaf': IDL.int, - 'branch': IDL.Obj({'left': tree, 'val': IDL.int, 'right': tree})}) -const s = IDL.ActorInterface({f: t}) -const t = IDL.message(IDL.Obj({'server': s}), IDL.Obj({})) -const broker = - IDL.ActorInterface({ - find: - IDL.message(IDL.Obj({'name': IDL.text}), - IDL.Obj({ - '0': - IDL.ActorInterface({up: IDL.message(IDL.Obj({}), IDL.Obj({})), - current: IDL.message(IDL.Obj({}), IDL.Obj({'0': IDL.nat}))}) - })) - }) -const stream = - IDL.Opt( - IDL.Obj({'head': IDL.nat, - 'next': IDL.message(IDL.Obj({}), IDL.Obj({'0': stream}))})) - -const user = new IDL.ActorInterface({ - addUser: IDL.message(IDL.Obj({'0': IDL.nat}), IDL.Obj({'0': my_type})), - userName: IDL.message(IDL.Obj({'0': IDL.nat}), IDL.Obj({'0': stream}))}) diff --git a/test/idl/ok/test.js.ok b/test/idl/ok/test.js.ok new file mode 100644 index 00000000000..369fd11f46a --- /dev/null +++ b/test/idl/ok/test.js.ok @@ -0,0 +1,21 @@ +const my_type = IDL.nat +const B = my_type +const message = IDL.Obj({'name': IDL.text, '25': B, '26': IDL.reserved}) +const broker = + IDL.ActorInterface({ + 'find': + IDL.message(IDL.Obj({'name': IDL.text}), + IDL.Obj({ + '0': + IDL.ActorInterface({'up': IDL.message(IDL.Obj({}), IDL.Obj({})), + 'current': IDL.message(IDL.Obj({}), IDL.Obj({'0': IDL.nat}))}) + })) + }) +const server = new IDL.ActorInterface({ + 'addUser': + IDL.message(IDL.Obj({'name': IDL.text, 'age': IDL.nat8}), + IDL.Obj({'id': IDL.nat64})), + 'userName': + IDL.message(IDL.Obj({'id': IDL.nat64}), IDL.Obj({'0': IDL.text})), + 'userAge': IDL.message(IDL.Obj({'id': IDL.nat64}), IDL.Obj({'0': IDL.nat8})), + 'deleteUser': IDL.message(IDL.Obj({'id': IDL.nat64}), IDL.Obj({}))}) diff --git a/test/idl/ok/test.tc.ok b/test/idl/ok/test.tc.ok new file mode 100644 index 00000000000..f83723819fc --- /dev/null +++ b/test/idl/ok/test.tc.ok @@ -0,0 +1,6 @@ +-- Parsing test.didl: +-- Checking test.didl: +var B : var my_type +var broker : service {find : (name : text) -> (0 : service {up : () -> () ; current : () -> (0 : nat) }) } +var message : {25 : var B; 26 : reserved; name : text} +var my_type : nat diff --git a/test/idl/ok/unbound_actor.tc.ok b/test/idl/ok/unbound_actor.tc.ok new file mode 100644 index 00000000000..baf267520a7 --- /dev/null +++ b/test/idl/ok/unbound_actor.tc.ok @@ -0,0 +1,3 @@ +-- Parsing unbound_actor.didl: +-- Checking unbound_actor.didl: +unbound_actor.didl:3.7-3.8: type error, unbound type identifier f diff --git a/test/idl/ok/undefine.tc.ok b/test/idl/ok/undefine.tc.ok new file mode 100644 index 00000000000..aa4812092b8 --- /dev/null +++ b/test/idl/ok/undefine.tc.ok @@ -0,0 +1,3 @@ +-- Parsing undefine.didl: +-- Checking undefine.didl: +undefine.didl:4.14-4.15: type error, unbound type identifier a diff --git a/test/idl/ok/unicode.js.ok b/test/idl/ok/unicode.js.ok new file mode 100644 index 00000000000..7dc29bc6ef9 --- /dev/null +++ b/test/idl/ok/unicode.js.ok @@ -0,0 +1,11 @@ +const A = + IDL.Obj({'字段名': IDL.nat, '字 段 名2': IDL.nat, '📦🍦': IDL.nat + }) +const B = + IDL.Variant({'': IDL.null, '空的': IDL.null, ' 空的 ': IDL.null, + '1⃣️2⃣️3⃣️': IDL.null}) +const C = new IDL.ActorInterface({ + '函数名': IDL.message(IDL.Obj({'0': A}), IDL.Obj({'0': B})), + '': IDL.message(IDL.Obj({'0': IDL.nat}), IDL.Obj({'0': IDL.nat})), + '👀': IDL.message(IDL.Obj({'0': IDL.nat}), IDL.Obj({'0': IDL.nat})), + '✈️ 🚗 ⛱️ ': IDL.message(IDL.Obj({}), IDL.Obj({}))}) diff --git a/test/idl/ok/unicode.tc.ok b/test/idl/ok/unicode.tc.ok new file mode 100644 index 00000000000..702c0319351 --- /dev/null +++ b/test/idl/ok/unicode.tc.ok @@ -0,0 +1,4 @@ +-- Parsing unicode.didl: +-- Checking unicode.didl: +var A : {字 段 名2 : nat; 字段名 : nat; 📦🍦 : nat} +var B : variant { : null; 空的 : null; 1⃣️2⃣️3⃣️ : null; 空的 : null} diff --git a/test/idl/ok/variant.tc.ok b/test/idl/ok/variant.tc.ok new file mode 100644 index 00000000000..99f5b8dc3ad --- /dev/null +++ b/test/idl/ok/variant.tc.ok @@ -0,0 +1,3 @@ +-- Parsing variant.didl: +-- Checking variant.didl: +variant.didl:2.23-2.26: type error, field name nat hash collision with field nat diff --git a/test/idl/oneway.didl b/test/idl/oneway.didl new file mode 100644 index 00000000000..32666deec39 --- /dev/null +++ b/test/idl/oneway.didl @@ -0,0 +1,3 @@ +type g = func (nat) -> () oneway pure; +type f = func (nat) -> (nat) pure oneway; + diff --git a/test/idl/px.didl b/test/idl/px.didl index 9ffdfd6c186..030d1c44bf1 100644 --- a/test/idl/px.didl +++ b/test/idl/px.didl @@ -29,9 +29,3 @@ service ProduceExchange { getInventory: (producer_id: nat) -> (Inventory) pure; } -/* -service server { - registrarAddUser : (user_name: text, description: text, region: RegionId, isDeveloper: bool) -> (UserId, IdErr); - allUserInfo: () -> (UserInfo); -} -*/ diff --git a/test/idl/recursion.didl b/test/idl/recursion.didl new file mode 100644 index 00000000000..6a573e21033 --- /dev/null +++ b/test/idl/recursion.didl @@ -0,0 +1,13 @@ +type A = B; +type B = opt A; +type node = record {head:nat; tail:list}; +type list = opt node; +type tree = variant { + leaf : int; + branch : record { left : tree; val : int; right : tree }; +}; +type s = service { f : t }; +type t = func (server : s) -> (); +type stream = opt record {head:nat; next:func ()-> (stream) pure}; + +service A : s diff --git a/test/idl/test.didl b/test/idl/test.didl index a93bac2f025..473957316eb 100644 --- a/test/idl/test.didl +++ b/test/idl/test.didl @@ -1,43 +1,20 @@ type my_type = nat; type B = my_type; -type C = E; -type E = opt C; -type node = record {head:nat; tail:list}; -type list = opt node; -//type X = Y; -//type Y = X; -type enum = variant {red; blue; green;}; type message = record { name : text; - 25 : C; + 25 : B; reserved; }; -type test = record {nat;nat;nat;99:nat;nat;named_field:nat;nat;nat;nat;}; -type nest_record = record { - nat;nat;nat; - record { - nat;nat;nat; - }; - nat;nat;nat; -}; -type tree = variant { - leaf : int; - branch : record { left : tree; val : int; right : tree }; -}; -type s = service { f : t }; -type t = func (server : s) -> (); type broker = service { find : (name : text) -> (service {up:() -> (); current:() -> (nat)}); }; -type stream = opt record {head:nat; next:func ()-> (stream) pure}; -//service use2 : test - -service user { - addUser : (nat) -> (my_type) oneway pure ; - userName : (nat) -> (stream) pure; +service server { + addUser : (name : text, age : nat8) -> (id : nat64); + userName : (id : nat64) -> (text) pure; + userAge : (id : nat64) -> (nat8) pure; + deleteUser : (id : nat64) -> () oneway; } - diff --git a/test/idl/unbound_actor.didl b/test/idl/unbound_actor.didl new file mode 100644 index 00000000000..56436c210b9 --- /dev/null +++ b/test/idl/unbound_actor.didl @@ -0,0 +1,4 @@ +service A { + f : (nat) -> (); + g : f; +} diff --git a/test/idl/undefine.didl b/test/idl/undefine.didl new file mode 100644 index 00000000000..beb911dbdda --- /dev/null +++ b/test/idl/undefine.didl @@ -0,0 +1,4 @@ +type A = vec B; +type B = C; +type C = opt D; +type D = vec a; diff --git a/test/idl/unicode.didl b/test/idl/unicode.didl new file mode 100644 index 00000000000..ebf9fe334c5 --- /dev/null +++ b/test/idl/unicode.didl @@ -0,0 +1,14 @@ +type A = record { + "字段名":nat; + "字 段 名2":nat; + "📦🍦":nat; +}; +type B = variant { ""; "空的"; " 空的 "; "1⃣️2⃣️3⃣️"; }; + +service C { + "函数名": (A) -> (B); + "": (nat) -> (nat); + "👀": (nat) -> (nat) pure; + "✈️ 🚗 ⛱️ ": () -> () oneway; +} + diff --git a/test/idl/variant.didl b/test/idl/variant.didl new file mode 100644 index 00000000000..0bae1c957fd --- /dev/null +++ b/test/idl/variant.didl @@ -0,0 +1,3 @@ +type A = record {nat;nat;nat;}; +type B = variant {nat;nat;nat;}; + diff --git a/test/run.sh b/test/run.sh index 54057dccd3b..b4856073f65 100755 --- a/test/run.sh +++ b/test/run.sh @@ -212,9 +212,20 @@ do else # The file is a .didl file, so we are expected to test the idl - $ECHO -n " [idlc]" - $IDLC $base.didl > $out/$base.idlc 2>&1 - diff_files="$diff_files $base.idlc" + # Typecheck + $ECHO -n " [tc]" + $IDLC --check $base.didl > $out/$base.tc 2>&1 + tc_succeeded=$? + normalize $out/$base.tc + diff_files="$diff_files $base.tc" + + if [ "$tc_succeeded" -eq 0 ]; + then + $ECHO -n " [js]" + $IDLC --js $base.didl > $out/$base.js 2>&1 + diff_files="$diff_files $base.js" + fi + fi $ECHO "" From 7d305d48785cf5077f804dc5951a3cf813d158c8 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 5 Jun 2019 14:20:09 +0100 Subject: [PATCH 0124/1176] fix function result type translation to respect result arity --- src/desugar.ml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/desugar.ml b/src/desugar.ml index d74c8c0b38f..353bca61907 100644 --- a/src/desugar.ml +++ b/src/desugar.ml @@ -70,7 +70,8 @@ and exp' at note = function | S.FuncE (name, s, tbs, p, ty, e) -> let cc = Value.call_conv_of_typ note.S.note_typ in let args, wrap = to_args cc p in - I.FuncE (name, cc, typ_binds tbs, args, Type.as_seq ty.note, wrap (exp e)) + let tys = if cc.Value.n_res = 1 then [ty.note] else Type.as_seq ty.note in + I.FuncE (name, cc, typ_binds tbs, args, tys, wrap (exp e)) | S.CallE (e1, inst, e2) -> let t = e1.Source.note.S.note_typ in if Type.is_non t From 69045fc7c1ec170d2afe07f450c7054e454719f1 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 5 Jun 2019 14:43:58 +0100 Subject: [PATCH 0125/1176] add test --- test/run-dfinity/arity_bug.as | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 test/run-dfinity/arity_bug.as diff --git a/test/run-dfinity/arity_bug.as b/test/run-dfinity/arity_bug.as new file mode 100644 index 00000000000..6388dfd752f --- /dev/null +++ b/test/run-dfinity/arity_bug.as @@ -0,0 +1,2 @@ +func f((i:Int,b:Bool)):((Int,Bool)) { return (i,b);}; +let g : ((Int,Bool)) -> ((Int,Bool)) = f; \ No newline at end of file From 467e35f8c618b2878cc7966e03ce6bf464a9ae19 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 5 Jun 2019 14:20:09 +0100 Subject: [PATCH 0126/1176] fix function result type translation to respect result arity --- src/desugar.ml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/desugar.ml b/src/desugar.ml index d74c8c0b38f..353bca61907 100644 --- a/src/desugar.ml +++ b/src/desugar.ml @@ -70,7 +70,8 @@ and exp' at note = function | S.FuncE (name, s, tbs, p, ty, e) -> let cc = Value.call_conv_of_typ note.S.note_typ in let args, wrap = to_args cc p in - I.FuncE (name, cc, typ_binds tbs, args, Type.as_seq ty.note, wrap (exp e)) + let tys = if cc.Value.n_res = 1 then [ty.note] else Type.as_seq ty.note in + I.FuncE (name, cc, typ_binds tbs, args, tys, wrap (exp e)) | S.CallE (e1, inst, e2) -> let t = e1.Source.note.S.note_typ in if Type.is_non t From 750c56d63be60000579083eaa4258668fd652c48 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 5 Jun 2019 16:42:31 +0100 Subject: [PATCH 0127/1176] spacing --- test/run-dfinity/arity_bug.as | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/run-dfinity/arity_bug.as b/test/run-dfinity/arity_bug.as index 6388dfd752f..c0aec58c4db 100644 --- a/test/run-dfinity/arity_bug.as +++ b/test/run-dfinity/arity_bug.as @@ -1,2 +1,2 @@ func f((i:Int,b:Bool)):((Int,Bool)) { return (i,b);}; -let g : ((Int,Bool)) -> ((Int,Bool)) = f; \ No newline at end of file +let g : ((Int,Bool)) -> ((Int,Bool)) = f; From 9cb2c237f148bc241b02e4e4c8c1d048ed032031 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 5 Jun 2019 18:55:55 +0200 Subject: [PATCH 0128/1176] IR: Use Type.lab instead of Name (#451) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In contrast to the source, the IR has a clear separation of what are variables (can be renamed) and what are record labels (must not be renamed). E.g. thanks to @crusso’s `NewObjE`. And because the label in, say, `DotE`, directly refers to the label in a type, it makes sense to use `Type.lab` instead of `Ir.name` here. This allows the backend to move the `open Ir` much further down, making the structure of that file more obvious. Currently, `Type.lab` is an alias for `string`, and it might be desirable to make that a new type (as `Ir.name` was before), but that can happen separately. --- src/arrange_ir.ml | 11 ++++------- src/check_ir.ml | 8 ++++---- src/compile.ml | 44 +++++++++++++++++++++----------------------- src/construct.ml | 4 ++-- src/construct.mli | 6 +++--- src/desugar.ml | 6 +++--- src/interpret_ir.ml | 13 +++++-------- src/ir.ml | 11 ++++------- src/show.ml | 2 +- 9 files changed, 47 insertions(+), 58 deletions(-) diff --git a/src/arrange_ir.ml b/src/arrange_ir.ml index 45da4e6b9c8..313a5814876 100644 --- a/src/arrange_ir.ml +++ b/src/arrange_ir.ml @@ -17,8 +17,8 @@ let rec exp e = match e.it with | ShowE (t, e) -> "ShowE" $$ [typ t; exp e] | TupE es -> "TupE" $$ List.map exp es | ProjE (e, i) -> "ProjE" $$ [exp e; Atom (string_of_int i)] - | DotE (e, n) -> "DotE" $$ [exp e; Atom (name n)] - | ActorDotE (e, n) -> "ActorDotE" $$ [exp e; Atom (name n)] + | DotE (e, n) -> "DotE" $$ [exp e; Atom n] + | ActorDotE (e, n) -> "ActorDotE" $$ [exp e; Atom n] | AssignE (e1, e2) -> "AssignE" $$ [exp e1; exp e2] | ArrayE (m, t, es) -> "ArrayE" $$ [Arrange.mut m; typ t] @ List.map exp es | IdxE (e1, e2) -> "IdxE" $$ [exp e1; exp e2] @@ -43,7 +43,7 @@ let rec exp e = match e.it with | ActorE (i, ds, fs, t) -> "ActorE" $$ [id i] @ List.map dec ds @ fields fs @ [typ t] | NewObjE (s, fs, t) -> "NewObjE" $$ (Arrange.obj_sort' s :: fields fs @ [typ t]) -and fields fs = List.fold_left (fun flds (f : field) -> (name f.it.name $$ [ id f.it.var ]):: flds) [] fs +and fields fs = List.fold_left (fun flds (f : field) -> (f.it.name $$ [ id f.it.var ]):: flds) [] fs and args = function | [] -> [] @@ -61,13 +61,10 @@ and pat p = match p.it with | TagP (i, p) -> "TagP" $$ [ id i; pat p ] | AltP (p1,p2) -> "AltP" $$ [ pat p1; pat p2 ] -and pat_field pf = name pf.it.name $$ [pat pf.it.pat] +and pat_field pf = pf.it.name $$ [pat pf.it.pat] and case c = "case" $$ [pat c.it.pat; exp c.it.exp] -and name n = match n.it with - | Name l -> l - and call_conv cc = Atom (Value.string_of_call_conv cc) and dec d = match d.it with diff --git a/src/check_ir.ml b/src/check_ir.ml index 21b13510cf1..b1f409c6b30 100644 --- a/src/check_ir.ml +++ b/src/check_ir.ml @@ -337,8 +337,8 @@ let rec check_exp env (exp:Ir.exp) : unit = error env exp.at "tuple projection %n is out of bounds for type\n %s" n (T.string_of_typ_expand t1) in tn <: t - | ActorDotE(exp1,{it = Name n;_}) - | DotE (exp1, {it = Name n;_}) -> + | ActorDotE(exp1, n) + | DotE (exp1, n) -> begin check_exp env exp1; let t1 = typ exp1 in @@ -639,7 +639,7 @@ and check_pats at env pats ve : val_env = and check_pat_fields env t = List.iter (check_pat_field env t) and check_pat_field env t (pf : pat_field) = - let Name lab = pf.it.name.it in + let lab = pf.it.name in let tf = T.{lab; typ=pf.it.pat.note} in let s, tfs = T.as_obj_sub lab t in let (<:) = check_sub env pf.it.pat.at in @@ -658,7 +658,7 @@ and type_exp_fields env s fs : T.field list = List.sort T.compare_field tfs and type_exp_field env s f : T.field = - let {name = {it = Name name; _}; var} = f.it in + let {name; var} = f.it in let t = try T.Env.find var.it env.vals with | Not_found -> error env f.at "field typing for %s not found" name in diff --git a/src/compile.ml b/src/compile.ml index 79f7f522b9f..1ff783e410e 100644 --- a/src/compile.ml +++ b/src/compile.ml @@ -14,7 +14,6 @@ this keeps documentation close to the code (a lesson learned from Simon PJ). open Wasm.Ast open Wasm.Types open Source -open Ir (* Re-shadow Source.(@@), to get Pervasives.(@@) *) let (@@) = Pervasives.(@@) @@ -33,8 +32,6 @@ let ptr_unskew = 1l (* Helper functions to produce annotated terms (Wasm.AST) *) let nr x = { Wasm.Source.it = x; Wasm.Source.at = Wasm.Source.no_region } -(* Dito, for the Source AST *) -let nr_ x = { it = x; at = no_region; note = () } let todo fn se x = Printf.eprintf "%s: %s" fn (Wasm.Sexpr.to_string 80 se); x @@ -138,7 +135,7 @@ module E = struct (* Global fields *) (* Static *) mode : mode; - prelude : prog; (* The prelude. Re-used when compiling actors *) + prelude : Ir.prog; (* The prelude. Re-used when compiling actors *) rts : CustomModule.extended_module option; (* The rts. Re-used when compiling actors *) trap_with : t -> string -> G.t; (* Trap with message; in the env for dependency injection *) @@ -1733,7 +1730,7 @@ module Object = struct let size_field = Int32.add Tagged.header_size 0l (* We use the same hashing function as Ocaml would *) - let hash_field_name ({it = Name s; _}) = + let hash_field_name s = Int32.of_int (Hashtbl.hash s) module FieldEnv = Env.Make(String) @@ -1747,7 +1744,7 @@ module Object = struct then we need to allocate separate boxes for the non-public ones: List.filter (fun (_, vis, f) -> vis.it = Public) |> *) - List.map (fun ({it = Name s;_} as n,_) -> (hash_field_name n, s)) |> + List.map (fun (n,_) -> (hash_field_name n, n)) |> List.sort compare |> List.mapi (fun i (_h,n) -> (n,Int32.of_int i)) |> List.fold_left (fun m (n,i) -> FieldEnv.add n i m) FieldEnv.empty in @@ -1768,10 +1765,10 @@ module Object = struct compile_unboxed_const sz ^^ Heap.store_field size_field ^^ - let hash_position env {it = Name n; _} = + let hash_position env n = let i = FieldEnv.find n name_pos_map in Int32.add header_size (Int32.mul 2l i) in - let field_position env {it = Name n; _} = + let field_position env n = let i = FieldEnv.find n name_pos_map in Int32.add header_size (Int32.add (Int32.mul 2l i) 1l) in @@ -1833,7 +1830,7 @@ module Object = struct else idx_hash_raw env (* Determines whether the field is mutable (and thus needs an indirection) *) - let is_mut_field env obj_type ({it = Name s; _}) = + let is_mut_field env obj_type s = let _, fields = Type.as_obj_sub "" obj_type in Type.is_mut (Lib.Option.value (Type.lookup_val_field s fields)) @@ -1917,7 +1914,7 @@ module Iterators = struct set_ni ^^ Object.lit_raw env - [ nr_ (Name "next"), fun _ -> get_ni ] + [ "next", fun _ -> get_ni ] ) ) in @@ -2822,8 +2819,7 @@ module Serialization = struct (* Disregarding all subtyping, and assuming sorted fields, we can just treat this like a tuple *) G.concat_mapi (fun i f -> - let n = { it = Name f.Type.lab; at = no_region; note = () } in - get_x ^^ Object.load_idx env t n ^^ + get_x ^^ Object.load_idx env t f.Type.lab ^^ size env f.typ ) fs | Array t -> @@ -2948,8 +2944,7 @@ module Serialization = struct (* Disregarding all subtyping, and assuming sorted fields, we can just treat this like a tuple *) G.concat_mapi (fun i f -> - let n = { it = Name f.Type.lab; at = no_region; note = () } in - get_x ^^ Object.load_idx env t n ^^ + get_x ^^ Object.load_idx env t f.Type.lab ^^ write env f.typ ) fs | Array t -> @@ -3073,8 +3068,7 @@ module Serialization = struct (* Disregarding all subtyping, and assuming sorted fields, we can just treat this like a tuple *) Object.lit_raw env (List.map (fun f -> - let n = { it = Name f.Type.lab; at = no_region; note = () } in - n, fun () -> read env f.typ + f.Type.lab, fun () -> read env f.typ ) fs) | Array t -> let (set_len, get_len) = new_local env "len" in @@ -4136,6 +4130,11 @@ module PatCode = struct end (* PatCode *) open PatCode + +(* All the code above is independent of the IR *) +open Ir + + module AllocHow = struct (* When compiling a (recursive) block, we need to do a dependency analysis, to @@ -4501,10 +4500,10 @@ let compile_relop env t op = we currently have for arrays and text. It goes through branch_typed_with, which does a dynamic check of the heap object type *) -let compile_load_field env typ ({it=(Name n); _} as name) = +let compile_load_field env typ name = let branches = ( Tagged.Object, Object.load_idx env typ name ) :: - match n with + match name with | "len" -> [ Tagged.Array, Arr.partial_len env ; Tagged.Text, Text.partial_len env ] @@ -4557,10 +4556,10 @@ and compile_exp (env : E.t) ae exp = SR.Vanilla, compile_exp_vanilla env ae e ^^ compile_load_field env e.note.note_typ name - | ActorDotE (e, ({it = Name n;_} as name)) -> + | ActorDotE (e, name) -> SR.UnboxedReference, compile_exp_as env ae SR.UnboxedReference e ^^ - actor_fake_object_idx env {name with it = n} + actor_fake_object_idx env name (* We only allow prims of certain shapes, as they occur in the prelude *) | CallE (_, ({ it = PrimE p; _} as pe), typ_args, e) -> begin @@ -5214,7 +5213,6 @@ and compile_start_func mod_env (progs : Ir.prog list) : E.func_with_names = ) and export_actor_field env ae (f : Ir.field) = - let Name name = f.it.name.it in let sr, code = Var.get_val env ae f.it.var.it in (* A public actor field is guaranteed to be compiled as a StaticMessage *) let fi = match sr with @@ -5229,7 +5227,7 @@ and export_actor_field env ae (f : Ir.field) = ) ts ); E.add_export env (nr { - name = Wasm.Utf8.decode name; + name = Wasm.Utf8.decode f.it.name; edesc = nr (FuncExport (nr fi)) }) @@ -5290,7 +5288,7 @@ and main_actor env ae1 this ds fs = decls_code and actor_fake_object_idx env name = - Dfinity.compile_databuf_of_bytes env (name.it) ^^ + Dfinity.compile_databuf_of_bytes env name ^^ Dfinity.system_call env "actor_export" and conclude_module env module_name start_fi_o = diff --git a/src/construct.ml b/src/construct.ml index 894a63ec3d8..10dfc87aea7 100644 --- a/src/construct.ml +++ b/src/construct.ml @@ -15,9 +15,9 @@ let constM = S.Const @@ no_region (* Field names *) -let nameN s = Name s @@ no_region +let nameN s = s -let nextN = nameN "next" +let nextN = "next" (* Identifiers *) diff --git a/src/construct.mli b/src/construct.mli index 2ab8c1be489..019c4db1220 100644 --- a/src/construct.mli +++ b/src/construct.mli @@ -18,8 +18,8 @@ val constM : mut (* Field names *) -val nameN : string -> name -val nextN : name +val nameN : string -> Type.lab +val nextN : Type.lab (* Identifiers *) @@ -55,7 +55,7 @@ val boolE : bool -> exp val callE : exp -> typ list -> exp -> exp val ifE : exp -> exp -> exp -> typ -> exp -val dotE : exp -> name -> typ -> exp +val dotE : exp -> Type.lab -> typ -> exp val switch_optE : exp -> exp -> pat -> exp -> typ -> exp val switch_variantE : exp -> (id * pat * exp) list -> typ -> exp val tupE : exp list -> exp diff --git a/src/desugar.ml b/src/desugar.ml index 353bca61907..02265f0fc6e 100644 --- a/src/desugar.ml +++ b/src/desugar.ml @@ -57,7 +57,7 @@ and exp' at note = function obj at s None es note.S.note_typ | S.TagE (c, e) -> I.TagE (c, exp e) | S.DotE (e, x) -> - let n = {x with it = I.Name x.it} in + let n = x.it in begin match T.as_obj_sub x.it e.note.S.note_typ with | Type.Actor, _ -> I.ActorDotE (exp e, n) | _ -> I.DotE (exp e, n) @@ -109,7 +109,7 @@ and obj at s self_id es obj_typ = | Type.Actor -> build_actor at self_id es obj_typ and build_field {Type.lab; Type.typ} = - { it = { I.name = I.Name lab @@ no_region + { it = { I.name = lab ; I.var = lab @@ no_region } ; at = no_region @@ -252,7 +252,7 @@ and pat' = function and pat_fields pfs = List.map pat_field pfs -and pat_field pf = phrase (fun S.{id; pat=p} -> I.{name=phrase (fun s -> Name s) id; pat=pat p}) pf +and pat_field pf = phrase (fun S.{id; pat=p} -> I.{name=id.it; pat=pat p}) pf and to_arg p : (Ir.arg * (Ir.exp -> Ir.exp)) = match p.it with diff --git a/src/interpret_ir.ml b/src/interpret_ir.ml index 0c636ce46b6..a572ebe5fd1 100644 --- a/src/interpret_ir.ml +++ b/src/interpret_ir.ml @@ -304,8 +304,8 @@ and interpret_exp_mut env exp (k : V.value V.cont) = interpret_exp env exp1 (fun v1 -> k (V.Variant (i.it, v1))) | ProjE (exp1, n) -> interpret_exp env exp1 (fun v1 -> k (List.nth (V.as_tup v1) n)) - | DotE (exp1, {it = Name n; _}) - | ActorDotE (exp1, {it = Name n; _}) -> + | DotE (exp1, n) + | ActorDotE (exp1, n) -> interpret_exp env exp1 (fun v1 -> let fs = V.as_obj v1 in k (try find n fs with _ -> assert false) @@ -424,8 +424,7 @@ and interpret_fields env fs = let ve = List.fold_left (fun ve (f : field) -> - let Name name = f.it.name.it in - V.Env.disjoint_add name (Lib.Promise.value (find f.it.var.it env.vals)) ve + V.Env.disjoint_add f.it.name (Lib.Promise.value (find f.it.var.it env.vals)) ve ) V.Env.empty fs in V.Obj ve @@ -513,8 +512,7 @@ and define_pats env pats vs = and define_field_pats env pfs vs = let define_field (pf : pat_field) = - let Name key = pf.it.name.it in - define_pat env pf.it.pat (V.Env.find key vs) in + define_pat env pf.it.pat (V.Env.find pf.it.name vs) in List.iter define_field pfs @@ -582,8 +580,7 @@ and match_pat_fields pfs vs ve : val_env option = | [] -> Some ve | pf::pfs' -> begin - let Name key = pf.it.name.it in - match match_pat pf.it.pat (V.Env.find key vs) with + match match_pat pf.it.pat (V.Env.find pf.it.name vs) with | Some ve' -> match_pat_fields pfs' vs (V.Env.adjoin ve ve') | None -> None end diff --git a/src/ir.ml b/src/ir.ml index 7735c3abd6a..82dc6449d0d 100644 --- a/src/ir.ml +++ b/src/ir.ml @@ -14,9 +14,6 @@ type relop = Syntax.relop type mut = Syntax.mut type vis = Syntax.vis -type name = name' Source.phrase -and name' = Name of string - type pat = (pat', Type.typ) Source.annotated_phrase and pat' = | WildP (* wildcard *) @@ -29,7 +26,7 @@ and pat' = | AltP of pat * pat (* disjunctive *) and pat_field = pat_field' Source.phrase -and pat_field' = {name : name; pat : pat} +and pat_field' = {name : Type.lab; pat : pat} (* Like id, but with a type attached *) type arg = (string, Type.typ) Source.annotated_phrase @@ -49,8 +46,8 @@ and exp' = | ProjE of exp * int (* tuple projection *) | OptE of exp (* option injection *) | TagE of id * exp (* variant injection *) - | DotE of exp * name (* object projection *) - | ActorDotE of exp * name (* actor field access *) + | DotE of exp * Type.lab (* object projection *) + | ActorDotE of exp * Type.lab (* actor field access *) | AssignE of exp * exp (* assignment *) | ArrayE of mut * Type.typ * exp list (* array *) | IdxE of exp * exp (* array indexing *) @@ -74,7 +71,7 @@ and exp' = | NewObjE of Type.obj_sort * field list * Type.typ (* make an object *) and field = (field', Type.typ) Source.annotated_phrase -and field' = {name : name; var : id} (* the var is by reference, not by value *) +and field' = {name : Type.lab; var : id} (* the var is by reference, not by value *) and case = case' Source.phrase and case' = {pat : pat; exp : exp} diff --git a/src/show.ml b/src/show.ml index 787d8b26e80..197bcee3001 100644 --- a/src/show.ml +++ b/src/show.ml @@ -329,7 +329,7 @@ let show_for : T.typ -> Ir.dec * T.typ list = fun t -> catE (textE (f.Type.lab ^ " = ")) (invoke_generated_show t' - { it = DotE (argE t, Ir.Name f.Type.lab @@ no_region ) + { it = DotE (argE t, f.Type.lab) ; at = no_region ; note = { note_typ = t'; note_eff = T.Triv } } From 29cb9ce98d9737bde625e79404def4e9e8a1de68 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Wed, 5 Jun 2019 11:06:30 -0700 Subject: [PATCH 0129/1176] remove verbose type checking results from tests; change .didl to .did --- idl/compile_js.ml | 26 ++++++++++++++++--- idl/main.ml | 1 - test/idl/Makefile | 4 +-- test/idl/{actor.didl => actor.did} | 0 ...ision_fields.didl => collision_fields.did} | 0 test/idl/{cyclic.didl => cyclic.did} | 0 test/idl/{fields.didl => fields.did} | 0 test/idl/integer.did | 5 ++++ test/idl/{unbound_actor.didl => meths.did} | 0 test/idl/ok/actor.js.ok | 4 +-- test/idl/ok/actor.tc.ok | 3 --- test/idl/ok/collision_fields.tc.ok | 4 +-- test/idl/ok/cyclic.tc.ok | 4 +-- test/idl/ok/fields.js.ok | 20 +++++++------- test/idl/ok/fields.tc.ok | 6 ----- test/idl/ok/integer.js.ok | 4 +++ test/idl/ok/meths.tc.ok | 1 + test/idl/ok/oneway.tc.ok | 4 +-- test/idl/ok/px.js.ok | 16 ++++++------ test/idl/ok/px.tc.ok | 11 -------- test/idl/ok/recursion.js.ok | 8 +++--- test/idl/ok/recursion.tc.ok | 10 ------- test/idl/ok/test.js.ok | 19 +++++++------- test/idl/ok/test.tc.ok | 6 ----- test/idl/ok/unbound_actor.tc.ok | 3 --- test/idl/ok/undefine.tc.ok | 4 +-- test/idl/ok/unicode.js.ok | 10 +++---- test/idl/ok/unicode.tc.ok | 4 --- test/idl/ok/variant.tc.ok | 4 +-- test/idl/{oneway.didl => oneway.did} | 0 test/idl/{px.didl => px.did} | 0 test/idl/{recursion.didl => recursion.did} | 0 test/idl/{test.didl => test.did} | 0 test/idl/{undefine.didl => undefine.did} | 0 test/idl/{unicode.didl => unicode.did} | 0 test/idl/{variant.didl => variant.did} | 0 test/run.sh | 12 ++++----- 37 files changed, 83 insertions(+), 110 deletions(-) rename test/idl/{actor.didl => actor.did} (100%) rename test/idl/{collision_fields.didl => collision_fields.did} (100%) rename test/idl/{cyclic.didl => cyclic.did} (100%) rename test/idl/{fields.didl => fields.did} (100%) create mode 100644 test/idl/integer.did rename test/idl/{unbound_actor.didl => meths.did} (100%) delete mode 100644 test/idl/ok/actor.tc.ok delete mode 100644 test/idl/ok/fields.tc.ok create mode 100644 test/idl/ok/integer.js.ok create mode 100644 test/idl/ok/meths.tc.ok delete mode 100644 test/idl/ok/px.tc.ok delete mode 100644 test/idl/ok/recursion.tc.ok delete mode 100644 test/idl/ok/test.tc.ok delete mode 100644 test/idl/ok/unbound_actor.tc.ok delete mode 100644 test/idl/ok/unicode.tc.ok rename test/idl/{oneway.didl => oneway.did} (100%) rename test/idl/{px.didl => px.did} (100%) rename test/idl/{recursion.didl => recursion.did} (100%) rename test/idl/{test.didl => test.did} (100%) rename test/idl/{undefine.didl => undefine.did} (100%) rename test/idl/{unicode.didl => unicode.did} (100%) rename test/idl/{variant.didl => variant.did} (100%) diff --git a/idl/compile_js.ml b/idl/compile_js.ml index a3ca3c542e7..b72ed209fd7 100644 --- a/idl/compile_js.ml +++ b/idl/compile_js.ml @@ -8,7 +8,26 @@ let id ppf s = str ppf s.it; pp_print_cut ppf () let space = pp_print_space let kwd ppf s = str ppf s; space ppf () let field_name ppf s = str ppf "'"; str ppf s.it; str ppf "'"; pp_print_cut ppf () - + +let pp_prim p = + match p with + | Nat -> "Nat" + | Nat8 -> "Nat" + | Nat16 -> "Nat" + | Nat32 -> "Nat" + | Nat64 -> "Nat" + | Int -> "Int" + | Int8 -> "Int" + | Int16 -> "Int" + | Int32 -> "Int" + | Int64 -> "Int" + | Float32 -> "Float" + | Float64 -> "Float" + | Bool -> "Bool" + | Text -> "Text" + | Null -> "Unit" + | Reserved -> "None" + let rec concat ppf f env sep list = match list with | [] -> () @@ -18,8 +37,8 @@ let rec concat ppf f env sep list = let rec pp_typ ppf env t = pp_open_box ppf 1; (match t.it with - | VarT s -> id ppf s (*pp_print_string ppf s.it; str ppf "()"*) - | PrimT p -> str ppf ("IDL."^(Arrange_idl.string_of_prim p)) + | VarT s -> id ppf s + | PrimT p -> str ppf ("IDL."^(pp_prim p)) | RecordT ts -> pp_fields ppf env ts | VecT t -> str ppf "IDL.Arr("; pp_typ ppf env t; str ppf ")"; | OptT t -> str ppf "IDL.Opt("; pp_typ ppf env t; str ppf ")"; @@ -66,7 +85,6 @@ let pp_dec ppf env dec = | TypD (x, t) -> kwd ppf x.it; kwd ppf "="; - (*kwd ppf "()"; kwd ppf "=>";*) pp_typ ppf env t ); pp_close_box ppf (); diff --git a/idl/main.ml b/idl/main.ml index 408d2384017..5dae631a9a3 100644 --- a/idl/main.ml +++ b/idl/main.ml @@ -51,7 +51,6 @@ let process_files files : unit = | Default -> assert false | Check -> - Flags.verbose := true; let (_, msgs) = exit_on_failure (Pipeline.(check_file (List.hd files))) in Diag.print_messages msgs | Js -> diff --git a/test/idl/Makefile b/test/idl/Makefile index 9c06507358f..c0452d6aca1 100644 --- a/test/idl/Makefile +++ b/test/idl/Makefile @@ -1,10 +1,10 @@ RUNFLAGS = all: - ../run.sh $(RUNFLAGS) *.didl + ../run.sh $(RUNFLAGS) *.did accept: - ../run.sh $(RUNFLAGS) -a *.didl + ../run.sh $(RUNFLAGS) -a *.did clean: rm -rf _out diff --git a/test/idl/actor.didl b/test/idl/actor.did similarity index 100% rename from test/idl/actor.didl rename to test/idl/actor.did diff --git a/test/idl/collision_fields.didl b/test/idl/collision_fields.did similarity index 100% rename from test/idl/collision_fields.didl rename to test/idl/collision_fields.did diff --git a/test/idl/cyclic.didl b/test/idl/cyclic.did similarity index 100% rename from test/idl/cyclic.didl rename to test/idl/cyclic.did diff --git a/test/idl/fields.didl b/test/idl/fields.did similarity index 100% rename from test/idl/fields.didl rename to test/idl/fields.did diff --git a/test/idl/integer.did b/test/idl/integer.did new file mode 100644 index 00000000000..1fcbdfbe502 --- /dev/null +++ b/test/idl/integer.did @@ -0,0 +1,5 @@ +service num { + f : (nat8) -> (int16); + g : (nat64) -> (int64); + h : (int8) -> (nat); +} diff --git a/test/idl/unbound_actor.didl b/test/idl/meths.did similarity index 100% rename from test/idl/unbound_actor.didl rename to test/idl/meths.did diff --git a/test/idl/ok/actor.js.ok b/test/idl/ok/actor.js.ok index 84f943ea017..8234f80a0b8 100644 --- a/test/idl/ok/actor.js.ok +++ b/test/idl/ok/actor.js.ok @@ -1,3 +1,3 @@ -const f = IDL.message(IDL.Obj({'0': IDL.nat}), IDL.Obj({'0': IDL.nat})) +const f = IDL.message(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': IDL.Nat})) const A = new IDL.ActorInterface({ - 'f': IDL.message(IDL.Obj({'0': IDL.nat}), IDL.Obj({})), 'g': f}) + 'f': IDL.message(IDL.Obj({'0': IDL.Nat}), IDL.Obj({})), 'g': f}) diff --git a/test/idl/ok/actor.tc.ok b/test/idl/ok/actor.tc.ok deleted file mode 100644 index 505e326f3f4..00000000000 --- a/test/idl/ok/actor.tc.ok +++ /dev/null @@ -1,3 +0,0 @@ --- Parsing actor.didl: --- Checking actor.didl: -var f : (0 : nat) -> (0 : nat) pure diff --git a/test/idl/ok/collision_fields.tc.ok b/test/idl/ok/collision_fields.tc.ok index b6108787dd8..9d12b957398 100644 --- a/test/idl/ok/collision_fields.tc.ok +++ b/test/idl/ok/collision_fields.tc.ok @@ -1,3 +1 @@ --- Parsing collision_fields.didl: --- Checking collision_fields.didl: -collision_fields.didl:3.2-3.3: type error, field name 2 hash collision with field 2 +collision_fields.did:3.2-3.3: type error, field name 2 hash collision with field 2 diff --git a/test/idl/ok/cyclic.tc.ok b/test/idl/ok/cyclic.tc.ok index 08c562794f5..37467c8cfb3 100644 --- a/test/idl/ok/cyclic.tc.ok +++ b/test/idl/ok/cyclic.tc.ok @@ -1,3 +1 @@ --- Parsing cyclic.didl: --- Checking cyclic.didl: -cyclic.didl:9.10-9.11: type error, D has a cyclic type definition +cyclic.did:9.10-9.11: type error, D has a cyclic type definition diff --git a/test/idl/ok/fields.js.ok b/test/idl/ok/fields.js.ok index 09c1c2da177..6ce735ba91a 100644 --- a/test/idl/ok/fields.js.ok +++ b/test/idl/ok/fields.js.ok @@ -1,14 +1,14 @@ -const A = IDL.Obj({'0': IDL.nat, '1': IDL.nat, '2': IDL.nat}) +const A = IDL.Obj({'0': IDL.Nat, '1': IDL.Nat, '2': IDL.Nat}) const B = - IDL.Obj({'0': IDL.Arr(IDL.nat8), '35': IDL.Arr(IDL.nat8), '36': IDL.nat, - '37': IDL.nat, 'named_files': IDL.reserved, '653352244': IDL.nat, - '653352245': IDL.nat}) + IDL.Obj({'0': IDL.Arr(IDL.Nat), '35': IDL.Arr(IDL.Nat), '36': IDL.Nat, + '37': IDL.Nat, 'named_files': IDL.None, '653352244': IDL.Nat, + '653352245': IDL.Nat}) const C = - IDL.Variant({'red': IDL.null, '4': IDL.null, '3': IDL.null, '2': IDL.null, - '1': IDL.null, 'reserved': IDL.null, '10': IDL.null, 'green': IDL.null, - 'blue': IDL.null, 'A': IDL.null, 'B': IDL.null, 'C': IDL.null}) + IDL.Variant({'red': IDL.Unit, '4': IDL.Unit, '3': IDL.Unit, '2': IDL.Unit, + '1': IDL.Unit, 'reserved': IDL.Unit, '10': IDL.Unit, 'green': IDL.Unit, + 'blue': IDL.Unit, 'A': IDL.Unit, 'B': IDL.Unit, 'C': IDL.Unit}) const nest_record = - IDL.Obj({'0': IDL.nat, '1': IDL.nat, '2': IDL.nat, - '3': IDL.Obj({'0': IDL.nat, '1': IDL.nat, '2': IDL.nat}), '4': IDL.nat, - '5': IDL.nat, '6': IDL.nat, '7': A, '8': B, '9': C, '10': IDL.nat}) + IDL.Obj({'0': IDL.Nat, '1': IDL.Nat, '2': IDL.Nat, + '3': IDL.Obj({'0': IDL.Nat, '1': IDL.Nat, '2': IDL.Nat}), '4': IDL.Nat, + '5': IDL.Nat, '6': IDL.Nat, '7': A, '8': B, '9': C, '10': IDL.Nat}) diff --git a/test/idl/ok/fields.tc.ok b/test/idl/ok/fields.tc.ok deleted file mode 100644 index 881ec9d4eed..00000000000 --- a/test/idl/ok/fields.tc.ok +++ /dev/null @@ -1,6 +0,0 @@ --- Parsing fields.didl: --- Checking fields.didl: -var A : {0 : nat; 1 : nat; 2 : nat} -var B : {0 : vec nat8; 35 : vec nat8; 36 : nat; 37 : nat; named_files : reserved; 653352244 : nat; 653352245 : nat} -var C : variant {1 : null; 2 : null; 3 : null; 4 : null; 10 : null; C : null; red : null; A : null; B : null; reserved : null; green : null; blue : null} -var nest_record : {0 : nat; 1 : nat; 2 : nat; 3 : {0 : nat; 1 : nat; 2 : nat}; 4 : nat; 5 : nat; 6 : nat; 7 : var A; 8 : var B; 9 : var C; 10 : nat} diff --git a/test/idl/ok/integer.js.ok b/test/idl/ok/integer.js.ok new file mode 100644 index 00000000000..d531ed509da --- /dev/null +++ b/test/idl/ok/integer.js.ok @@ -0,0 +1,4 @@ +const num = new IDL.ActorInterface({ + 'f': IDL.message(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': IDL.Int})), + 'g': IDL.message(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': IDL.Int})), + 'h': IDL.message(IDL.Obj({'0': IDL.Int}), IDL.Obj({'0': IDL.Nat}))}) diff --git a/test/idl/ok/meths.tc.ok b/test/idl/ok/meths.tc.ok new file mode 100644 index 00000000000..564a9f619f7 --- /dev/null +++ b/test/idl/ok/meths.tc.ok @@ -0,0 +1 @@ +meths.did:3.7-3.8: type error, unbound type identifier f diff --git a/test/idl/ok/oneway.tc.ok b/test/idl/ok/oneway.tc.ok index d34873d9000..848eb80046e 100644 --- a/test/idl/ok/oneway.tc.ok +++ b/test/idl/ok/oneway.tc.ok @@ -1,3 +1 @@ --- Parsing oneway.didl: --- Checking oneway.didl: -oneway.didl:2.15-2.41: type error, oneway function has non-unit return type +oneway.did:2.15-2.41: type error, oneway function has non-unit return type diff --git a/test/idl/ok/px.js.ok b/test/idl/ok/px.js.ok index 765c7e2e47f..cbc6c8fc9e1 100644 --- a/test/idl/ok/px.js.ok +++ b/test/idl/ok/px.js.ok @@ -1,16 +1,16 @@ -const RegionId = IDL.nat -const UserId = IDL.nat -const TruckTypeId = IDL.nat -const ProducerId = IDL.nat +const RegionId = IDL.Nat +const UserId = IDL.Nat +const TruckTypeId = IDL.Nat +const ProducerId = IDL.Nat const UserInfo = - IDL.Obj({'id': UserId, 'public_key': IDL.text, 'user_name': IDL.text, - 'description': IDL.text, 'region': RegionId, + IDL.Obj({'id': UserId, 'public_key': IDL.Text, 'user_name': IDL.Text, + 'description': IDL.Text, 'region': RegionId, 'produceId': IDL.Opt(ProducerId)}) const EntId = IDL.Obj({'user': UserId, 'truckType': TruckTypeId, 'region': RegionId}) const OpEntId = IDL.Opt(EntId) const IdErr = IDL.Obj({'idErr': OpEntId}) -const Inventory = IDL.Obj({'produce_id': IDL.nat, 'quantity': IDL.nat}) +const Inventory = IDL.Obj({'produce_id': IDL.Nat, 'quantity': IDL.Nat}) const ProduceExchange = new IDL.ActorInterface({ 'getInventory': - IDL.message(IDL.Obj({'producer_id': IDL.nat}), IDL.Obj({'0': Inventory}))}) + IDL.message(IDL.Obj({'producer_id': IDL.Nat}), IDL.Obj({'0': Inventory}))}) diff --git a/test/idl/ok/px.tc.ok b/test/idl/ok/px.tc.ok deleted file mode 100644 index e58929a4c5b..00000000000 --- a/test/idl/ok/px.tc.ok +++ /dev/null @@ -1,11 +0,0 @@ --- Parsing px.didl: --- Checking px.didl: -var EntId : {truckType : var TruckTypeId; user : var UserId; region : var RegionId} -var IdErr : {idErr : var OpEntId} -var Inventory : {quantity : nat; produce_id : nat} -var OpEntId : opt var EntId -var ProducerId : nat -var RegionId : nat -var TruckTypeId : nat -var UserId : nat -var UserInfo : {description : text; user_name : text; produceId : opt var ProducerId; id : var UserId; public_key : text; region : var RegionId} diff --git a/test/idl/ok/recursion.js.ok b/test/idl/ok/recursion.js.ok index 0e181196071..cb454e0ff6e 100644 --- a/test/idl/ok/recursion.js.ok +++ b/test/idl/ok/recursion.js.ok @@ -1,15 +1,15 @@ const A = B const B = IDL.Opt(A) -const node = IDL.Obj({'head': IDL.nat, 'tail': list}) +const node = IDL.Obj({'head': IDL.Nat, 'tail': list}) const list = IDL.Opt(node) const tree = - IDL.Variant({'leaf': IDL.int, - 'branch': IDL.Obj({'left': tree, 'val': IDL.int, 'right': tree})}) + IDL.Variant({'leaf': IDL.Int, + 'branch': IDL.Obj({'left': tree, 'val': IDL.Int, 'right': tree})}) const s = IDL.ActorInterface({'f': t}) const t = IDL.message(IDL.Obj({'server': s}), IDL.Obj({})) const stream = IDL.Opt( - IDL.Obj({'head': IDL.nat, + IDL.Obj({'head': IDL.Nat, 'next': IDL.message(IDL.Obj({}), IDL.Obj({'0': stream}))})) const A = s diff --git a/test/idl/ok/recursion.tc.ok b/test/idl/ok/recursion.tc.ok deleted file mode 100644 index 1f556243b6b..00000000000 --- a/test/idl/ok/recursion.tc.ok +++ /dev/null @@ -1,10 +0,0 @@ --- Parsing recursion.didl: --- Checking recursion.didl: -var A : var B -var B : opt var A -var list : opt var node -var node : {head : nat; tail : var list} -var s : service {f : var t} -var stream : opt {head : nat; next : () -> (0 : var stream) pure} -var t : (server : var s) -> () -var tree : variant {branch : {right : var tree; val : int; left : var tree}; leaf : int} diff --git a/test/idl/ok/test.js.ok b/test/idl/ok/test.js.ok index 369fd11f46a..93ece59addb 100644 --- a/test/idl/ok/test.js.ok +++ b/test/idl/ok/test.js.ok @@ -1,21 +1,20 @@ -const my_type = IDL.nat +const my_type = IDL.Nat const B = my_type -const message = IDL.Obj({'name': IDL.text, '25': B, '26': IDL.reserved}) +const message = IDL.Obj({'name': IDL.Text, '25': B, '26': IDL.None}) const broker = IDL.ActorInterface({ 'find': - IDL.message(IDL.Obj({'name': IDL.text}), + IDL.message(IDL.Obj({'name': IDL.Text}), IDL.Obj({ '0': IDL.ActorInterface({'up': IDL.message(IDL.Obj({}), IDL.Obj({})), - 'current': IDL.message(IDL.Obj({}), IDL.Obj({'0': IDL.nat}))}) + 'current': IDL.message(IDL.Obj({}), IDL.Obj({'0': IDL.Nat}))}) })) }) const server = new IDL.ActorInterface({ 'addUser': - IDL.message(IDL.Obj({'name': IDL.text, 'age': IDL.nat8}), - IDL.Obj({'id': IDL.nat64})), - 'userName': - IDL.message(IDL.Obj({'id': IDL.nat64}), IDL.Obj({'0': IDL.text})), - 'userAge': IDL.message(IDL.Obj({'id': IDL.nat64}), IDL.Obj({'0': IDL.nat8})), - 'deleteUser': IDL.message(IDL.Obj({'id': IDL.nat64}), IDL.Obj({}))}) + IDL.message(IDL.Obj({'name': IDL.Text, 'age': IDL.Nat}), + IDL.Obj({'id': IDL.Nat})), + 'userName': IDL.message(IDL.Obj({'id': IDL.Nat}), IDL.Obj({'0': IDL.Text})), + 'userAge': IDL.message(IDL.Obj({'id': IDL.Nat}), IDL.Obj({'0': IDL.Nat})), + 'deleteUser': IDL.message(IDL.Obj({'id': IDL.Nat}), IDL.Obj({}))}) diff --git a/test/idl/ok/test.tc.ok b/test/idl/ok/test.tc.ok deleted file mode 100644 index f83723819fc..00000000000 --- a/test/idl/ok/test.tc.ok +++ /dev/null @@ -1,6 +0,0 @@ --- Parsing test.didl: --- Checking test.didl: -var B : var my_type -var broker : service {find : (name : text) -> (0 : service {up : () -> () ; current : () -> (0 : nat) }) } -var message : {25 : var B; 26 : reserved; name : text} -var my_type : nat diff --git a/test/idl/ok/unbound_actor.tc.ok b/test/idl/ok/unbound_actor.tc.ok deleted file mode 100644 index baf267520a7..00000000000 --- a/test/idl/ok/unbound_actor.tc.ok +++ /dev/null @@ -1,3 +0,0 @@ --- Parsing unbound_actor.didl: --- Checking unbound_actor.didl: -unbound_actor.didl:3.7-3.8: type error, unbound type identifier f diff --git a/test/idl/ok/undefine.tc.ok b/test/idl/ok/undefine.tc.ok index aa4812092b8..31d2fd84aea 100644 --- a/test/idl/ok/undefine.tc.ok +++ b/test/idl/ok/undefine.tc.ok @@ -1,3 +1 @@ --- Parsing undefine.didl: --- Checking undefine.didl: -undefine.didl:4.14-4.15: type error, unbound type identifier a +undefine.did:4.14-4.15: type error, unbound type identifier a diff --git a/test/idl/ok/unicode.js.ok b/test/idl/ok/unicode.js.ok index 7dc29bc6ef9..9469eae3f3f 100644 --- a/test/idl/ok/unicode.js.ok +++ b/test/idl/ok/unicode.js.ok @@ -1,11 +1,11 @@ const A = - IDL.Obj({'字段名': IDL.nat, '字 段 名2': IDL.nat, '📦🍦': IDL.nat + IDL.Obj({'字段名': IDL.Nat, '字 段 名2': IDL.Nat, '📦🍦': IDL.Nat }) const B = - IDL.Variant({'': IDL.null, '空的': IDL.null, ' 空的 ': IDL.null, - '1⃣️2⃣️3⃣️': IDL.null}) + IDL.Variant({'': IDL.Unit, '空的': IDL.Unit, ' 空的 ': IDL.Unit, + '1⃣️2⃣️3⃣️': IDL.Unit}) const C = new IDL.ActorInterface({ '函数名': IDL.message(IDL.Obj({'0': A}), IDL.Obj({'0': B})), - '': IDL.message(IDL.Obj({'0': IDL.nat}), IDL.Obj({'0': IDL.nat})), - '👀': IDL.message(IDL.Obj({'0': IDL.nat}), IDL.Obj({'0': IDL.nat})), + '': IDL.message(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': IDL.Nat})), + '👀': IDL.message(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': IDL.Nat})), '✈️ 🚗 ⛱️ ': IDL.message(IDL.Obj({}), IDL.Obj({}))}) diff --git a/test/idl/ok/unicode.tc.ok b/test/idl/ok/unicode.tc.ok deleted file mode 100644 index 702c0319351..00000000000 --- a/test/idl/ok/unicode.tc.ok +++ /dev/null @@ -1,4 +0,0 @@ --- Parsing unicode.didl: --- Checking unicode.didl: -var A : {字 段 名2 : nat; 字段名 : nat; 📦🍦 : nat} -var B : variant { : null; 空的 : null; 1⃣️2⃣️3⃣️ : null; 空的 : null} diff --git a/test/idl/ok/variant.tc.ok b/test/idl/ok/variant.tc.ok index 99f5b8dc3ad..0ff3ec8e21f 100644 --- a/test/idl/ok/variant.tc.ok +++ b/test/idl/ok/variant.tc.ok @@ -1,3 +1 @@ --- Parsing variant.didl: --- Checking variant.didl: -variant.didl:2.23-2.26: type error, field name nat hash collision with field nat +variant.did:2.23-2.26: type error, field name nat hash collision with field nat diff --git a/test/idl/oneway.didl b/test/idl/oneway.did similarity index 100% rename from test/idl/oneway.didl rename to test/idl/oneway.did diff --git a/test/idl/px.didl b/test/idl/px.did similarity index 100% rename from test/idl/px.didl rename to test/idl/px.did diff --git a/test/idl/recursion.didl b/test/idl/recursion.did similarity index 100% rename from test/idl/recursion.didl rename to test/idl/recursion.did diff --git a/test/idl/test.didl b/test/idl/test.did similarity index 100% rename from test/idl/test.didl rename to test/idl/test.did diff --git a/test/idl/undefine.didl b/test/idl/undefine.did similarity index 100% rename from test/idl/undefine.didl rename to test/idl/undefine.did diff --git a/test/idl/unicode.didl b/test/idl/unicode.did similarity index 100% rename from test/idl/unicode.didl rename to test/idl/unicode.did diff --git a/test/idl/variant.didl b/test/idl/variant.did similarity index 100% rename from test/idl/variant.didl rename to test/idl/variant.did diff --git a/test/run.sh b/test/run.sh index b4856073f65..0d112c0bda4 100755 --- a/test/run.sh +++ b/test/run.sh @@ -81,10 +81,10 @@ do then base=$(basename $file .sh) elif [ ${file: -4} == ".wat" ] then base=$(basename $file .wat) - elif [ ${file: -5} == ".didl" ] - then base=$(basename $file .didl) + elif [ ${file: -4} == ".did" ] + then base=$(basename $file .did) else - echo "Unknown file extension in $file, expected .as, .sh, .wat or .didl"; exit 1 + echo "Unknown file extension in $file, expected .as, .sh, .wat or .did"; exit 1 failures=yes continue fi @@ -211,10 +211,10 @@ do fi else - # The file is a .didl file, so we are expected to test the idl + # The file is a .did file, so we are expected to test the idl # Typecheck $ECHO -n " [tc]" - $IDLC --check $base.didl > $out/$base.tc 2>&1 + $IDLC --check $base.did > $out/$base.tc 2>&1 tc_succeeded=$? normalize $out/$base.tc diff_files="$diff_files $base.tc" @@ -222,7 +222,7 @@ do if [ "$tc_succeeded" -eq 0 ]; then $ECHO -n " [js]" - $IDLC --js $base.didl > $out/$base.js 2>&1 + $IDLC --js $base.did > $out/$base.js 2>&1 diff_files="$diff_files $base.js" fi From def24cf7f12a5228e1b582d960370a7c772d961c Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Wed, 5 Jun 2019 14:54:10 -0700 Subject: [PATCH 0130/1176] more tests; change idlc to didc --- idl/.gitignore | 2 +- idl/Makefile | 6 +++--- idl/compile_js.ml | 1 + test/idl/actor.did | 9 +++++++-- test/idl/cyclic.did | 2 +- test/idl/dup.did | 4 ++++ test/idl/func.did | 11 +++++++++++ test/idl/ok/actor.js.ok | 10 +++++++--- test/idl/ok/dup.tc.ok | 1 + test/idl/ok/func.tc.ok | 2 ++ test/idl/ok/recursion.js.ok | 2 +- test/idl/ok/test.js.ok | 4 ++-- test/run.sh | 6 +++--- 13 files changed, 44 insertions(+), 16 deletions(-) create mode 100644 test/idl/dup.did create mode 100644 test/idl/func.did create mode 100644 test/idl/ok/dup.tc.ok create mode 100644 test/idl/ok/func.tc.ok diff --git a/idl/.gitignore b/idl/.gitignore index 4d6f3866971..4e46efe60a5 100644 --- a/idl/.gitignore +++ b/idl/.gitignore @@ -5,4 +5,4 @@ *.opt *.unopt *.mlpack -idlc +didc diff --git a/idl/Makefile b/idl/Makefile index a64af0c5b24..b945f6daee4 100644 --- a/idl/Makefile +++ b/idl/Makefile @@ -1,8 +1,8 @@ -NAME = idlc +NAME = didc BUILD = byte MAIN = main -IDLC = `pwd`/$(NAME) +DIDC = `pwd`/$(NAME) OPAM_PACKAGES = wasm stdint num vlq yojson @@ -32,5 +32,5 @@ clean: $(MAKE) -C ../test/idl clean test: $(NAME) - $(MAKE) -C ../test/idl IDLC=$(IDLC) all + $(MAKE) -C ../test/idl DIDC=$(DIDC) all diff --git a/idl/compile_js.ml b/idl/compile_js.ml index b72ed209fd7..a4ff3de6916 100644 --- a/idl/compile_js.ml +++ b/idl/compile_js.ml @@ -51,6 +51,7 @@ let rec pp_typ ppf env t = str ppf ")"; | ServT ts -> pp_open_hovbox ppf 1; + kwd ppf "new"; str ppf "IDL.ActorInterface({"; concat ppf pp_meth env "," ts; str ppf "})"; diff --git a/test/idl/actor.did b/test/idl/actor.did index 61f656a3a3a..1923f5646f3 100644 --- a/test/idl/actor.did +++ b/test/idl/actor.did @@ -1,5 +1,10 @@ -type f = func (nat) -> (nat) pure; -service A { +type f = func (int8) -> (int8); +type g = f; +type h = func (f) -> (f); +type o = opt o; +service g { f : (nat) -> (); g : f; + h : g; + o : (o) -> (o); } diff --git a/test/idl/cyclic.did b/test/idl/cyclic.did index 6f5478e5d50..a81205caf8d 100644 --- a/test/idl/cyclic.did +++ b/test/idl/cyclic.did @@ -1,6 +1,6 @@ type A = opt B; -type B = opt C; type C = A; +type B = opt C; type X = Y; type Y = Z; diff --git a/test/idl/dup.did b/test/idl/dup.did new file mode 100644 index 00000000000..8fa397d8121 --- /dev/null +++ b/test/idl/dup.did @@ -0,0 +1,4 @@ +type A = B; +type B = opt A; +type A = opt B; + diff --git a/test/idl/func.did b/test/idl/func.did new file mode 100644 index 00000000000..eddea8f17b6 --- /dev/null +++ b/test/idl/func.did @@ -0,0 +1,11 @@ +type f = func (int8) -> (int8); +type g = f; +type h = func (f) -> (f); +type o = opt f; +service g { + f : f; + g : g; + h : h; + o : (o) -> (o); + p : o; +} diff --git a/test/idl/ok/actor.js.ok b/test/idl/ok/actor.js.ok index 8234f80a0b8..313e553af12 100644 --- a/test/idl/ok/actor.js.ok +++ b/test/idl/ok/actor.js.ok @@ -1,3 +1,7 @@ -const f = IDL.message(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': IDL.Nat})) -const A = new IDL.ActorInterface({ - 'f': IDL.message(IDL.Obj({'0': IDL.Nat}), IDL.Obj({})), 'g': f}) +const f = IDL.message(IDL.Obj({'0': IDL.Int}), IDL.Obj({'0': IDL.Int})) +const g = f +const h = IDL.message(IDL.Obj({'0': f}), IDL.Obj({'0': f})) +const o = IDL.Opt(o) +const g = new IDL.ActorInterface({ + 'f': IDL.message(IDL.Obj({'0': IDL.Nat}), IDL.Obj({})), 'g': f, 'h': g, + 'o': IDL.message(IDL.Obj({'0': o}), IDL.Obj({'0': o}))}) diff --git a/test/idl/ok/dup.tc.ok b/test/idl/ok/dup.tc.ok new file mode 100644 index 00000000000..b30994f91a8 --- /dev/null +++ b/test/idl/ok/dup.tc.ok @@ -0,0 +1 @@ +dup.did:3.6-3.7: type error, duplicate binding for A in type definitions diff --git a/test/idl/ok/func.tc.ok b/test/idl/ok/func.tc.ok new file mode 100644 index 00000000000..aba71bbb729 --- /dev/null +++ b/test/idl/ok/func.tc.ok @@ -0,0 +1,2 @@ +func.did:10.3-10.8: type error, p is a non-function type + var o diff --git a/test/idl/ok/recursion.js.ok b/test/idl/ok/recursion.js.ok index cb454e0ff6e..8caaff51b9e 100644 --- a/test/idl/ok/recursion.js.ok +++ b/test/idl/ok/recursion.js.ok @@ -5,7 +5,7 @@ const list = IDL.Opt(node) const tree = IDL.Variant({'leaf': IDL.Int, 'branch': IDL.Obj({'left': tree, 'val': IDL.Int, 'right': tree})}) -const s = IDL.ActorInterface({'f': t}) +const s = new IDL.ActorInterface({'f': t}) const t = IDL.message(IDL.Obj({'server': s}), IDL.Obj({})) const stream = IDL.Opt( diff --git a/test/idl/ok/test.js.ok b/test/idl/ok/test.js.ok index 93ece59addb..05f1f7a7faf 100644 --- a/test/idl/ok/test.js.ok +++ b/test/idl/ok/test.js.ok @@ -2,12 +2,12 @@ const my_type = IDL.Nat const B = my_type const message = IDL.Obj({'name': IDL.Text, '25': B, '26': IDL.None}) const broker = - IDL.ActorInterface({ + new IDL.ActorInterface({ 'find': IDL.message(IDL.Obj({'name': IDL.Text}), IDL.Obj({ '0': - IDL.ActorInterface({'up': IDL.message(IDL.Obj({}), IDL.Obj({})), + new IDL.ActorInterface({'up': IDL.message(IDL.Obj({}), IDL.Obj({})), 'current': IDL.message(IDL.Obj({}), IDL.Obj({'0': IDL.Nat}))}) })) }) diff --git a/test/run.sh b/test/run.sh index 0d112c0bda4..6a3a6b028fa 100755 --- a/test/run.sh +++ b/test/run.sh @@ -21,7 +21,7 @@ DFINITY=no EXTRA_ASC_FLAGS= ASC=${ASC:-$(realpath $(dirname $0)/../src/asc)} AS_LD=${AS_LD:-$(realpath $(dirname $0)/../src/as-ld)} -IDLC=${IDLC:-$(realpath $(dirname $0)/../idl/idlc)} +DIDC=${IDLC:-$(realpath $(dirname $0)/../idl/didc)} export AS_LD WASM=${WASM:-wasm} DVM_WRAPPER=$(realpath $(dirname $0)/dvm.sh) @@ -214,7 +214,7 @@ do # The file is a .did file, so we are expected to test the idl # Typecheck $ECHO -n " [tc]" - $IDLC --check $base.did > $out/$base.tc 2>&1 + $DIDC --check $base.did > $out/$base.tc 2>&1 tc_succeeded=$? normalize $out/$base.tc diff_files="$diff_files $base.tc" @@ -222,7 +222,7 @@ do if [ "$tc_succeeded" -eq 0 ]; then $ECHO -n " [js]" - $IDLC --js $base.did > $out/$base.js 2>&1 + $DIDC --js $base.did > $out/$base.js 2>&1 diff_files="$diff_files $base.js" fi From ec2d879de1ed5fbd701780fdbb32f6a1265d8405 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Wed, 5 Jun 2019 15:01:08 -0700 Subject: [PATCH 0131/1176] fix nix --- default.nix | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/default.nix b/default.nix index ee1204e05bf..e8a662724da 100644 --- a/default.nix +++ b/default.nix @@ -70,7 +70,7 @@ let "test/(fail|run|run-dfinity|repl|ld|idl)/lib/dir/" "test/(fail|run|run-dfinity|repl|ld|idl)/.*.as" "test/(fail|run|run-dfinity|repl|ld|idl)/.*.sh" - "test/(fail|run|run-dfinity|repl|ld|idl)/.*.didl" + "test/(fail|run|run-dfinity|repl|ld|idl)/.*.did" "test/(fail|run|run-dfinity|repl|ld|idl)/[^/]*.wat" "test/(fail|run|run-dfinity|repl|ld|idl)/[^/]*.c" "test/(fail|run|run-dfinity|repl|ld|idl)/ok/" @@ -189,7 +189,7 @@ rec { buildInputs = [ asc - idlc + didc ocaml_wasm nixpkgs.wabt nixpkgs.bash @@ -204,7 +204,7 @@ rec { ${llvmEnv} export ASC=asc export AS_LD=as-ld - export IDLC=idlc + export DIDC=didc asc --version make -C samples all '' + @@ -305,8 +305,8 @@ rec { }); - idlc = stdenv.mkDerivation { - name = "idlc"; + didc = stdenv.mkDerivation { + name = "didc"; src = sourceByRegex ./idl [ "Makefile.*" @@ -321,12 +321,12 @@ rec { buildInputs = commonBuildInputs; buildPhase = '' - make BUILD=native idlc + make BUILD=native didc ''; installPhase = '' mkdir -p $out/bin - cp idlc $out/bin + cp didc $out/bin ''; }; @@ -430,7 +430,7 @@ rec { constituents = [ asc js - idlc + didc tests coverage-report rts @@ -451,10 +451,10 @@ rec { # https://github.com/NixOS/nix/issues/955 # - buildInputs = nixpkgs.lib.lists.unique (builtins.filter (i: i != asc && i != idlc) ( + buildInputs = nixpkgs.lib.lists.unique (builtins.filter (i: i != asc && i != didc) ( asc-bin.buildInputs ++ rts.buildInputs ++ - idlc.buildInputs ++ + didc.buildInputs ++ tests.buildInputs ++ users-guide.buildInputs ++ [ nixpkgs.ncurses nixpkgs.ocamlPackages.merlin ] From 3862e8c3b841ae719af5b7ad969ac296cca37718 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Wed, 5 Jun 2019 22:29:50 -0600 Subject: [PATCH 0132/1176] temp fix: 'hashing' a pair ints uses both, and is 'injective-ish' --- stdlib/hash.as | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/stdlib/hash.as b/stdlib/hash.as index 96673cc2d40..da640d5e608 100644 --- a/stdlib/hash.as +++ b/stdlib/hash.as @@ -57,10 +57,9 @@ module BitVec { hashInt(i) }; - func hashOfIntAcc(h:BitVec, i:Int) : BitVec { - //hashIntAcc(h, i) - // xxx use the value h - hashInt(i) + func hashOfIntAcc(h1:BitVec, i:Int) : BitVec { + let h2 = hashInt(i); + h2 ^ (h1 << 10) ^ (h2 << 20); }; func hashOfText(t:Text) : BitVec { From fc8bab1d4f9519179788036d2be09ab6eaf858ef Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 6 Jun 2019 10:43:20 +0200 Subject: [PATCH 0133/1176] Flush after printing banner (fixes #475) (#477) --- src/main.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.ml b/src/main.ml index 9d4ade178c7..479b3709fc7 100644 --- a/src/main.ml +++ b/src/main.ml @@ -34,7 +34,7 @@ let argspec = Arg.align "-o", Arg.Set_string out_file, " output file"; "--version", - Arg.Unit (fun () -> printf "%s\n" banner; exit 0), " show version"; + Arg.Unit (fun () -> printf "%s\n%!" banner; exit 0), " show version"; "--map", Arg.Set Flags.source_map, " output source map"; "-t", Arg.Set Flags.trace, " activate tracing"; @@ -70,7 +70,7 @@ let process_files files : unit = then exit_on_none (Pipeline.interpret_ir_files files) else exit_on_none (Pipeline.run_files files) | Interact -> - printf "%s\n" banner; + printf "%s\n%!" banner; exit_on_none (Pipeline.run_files_and_stdin files) | Check -> Diag.run (Pipeline.check_files files) From 71521a7d36447e82f33418105b76b786a554087e Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 6 Jun 2019 13:53:19 +0200 Subject: [PATCH 0134/1176] IDL: nat <: int (#479) cherry-picked from #438 --- design/IDL.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/design/IDL.md b/design/IDL.md index 76ce46fea2e..f392c7567a3 100644 --- a/design/IDL.md +++ b/design/IDL.md @@ -517,13 +517,21 @@ Future extensions: defaults, including for variants? #### Primitive Types -A primitive type cannot be changed in an upgrade. +Most primitive types cannot be changed in an upgrade. ``` ------------------------ <: ``` +An exception are integers, which can be specialised to natural numbers: + +``` + +----------- +nat <: int +``` + An additional rule applies to `unavailable`, which makes it a top type, i.e., a supertype of every type. ``` From 3dc895a88e83172a05102e8e2fe9f2d84d4cc47a Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 6 Jun 2019 13:55:53 +0200 Subject: [PATCH 0135/1176] s/unavailable/reserved (#478) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit this PR cherry-picks a change from @rossberg’s `idl-sub` branch (i.e. #438) that is not actually related to polarities. --- design/IDL.md | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/design/IDL.md b/design/IDL.md index f392c7567a3..f53c9e91a5f 100644 --- a/design/IDL.md +++ b/design/IDL.md @@ -76,7 +76,7 @@ This is a summary of the grammar proposed: | bool | text | null - | unavailable + | reserved ::= | opt @@ -250,11 +250,11 @@ The type `null` has exactly one value (the *null* value) and therefor carries no ::= ... | null | ... ``` -#### Unavailable +#### Reserved -The type `unavailable` is a type with unknown content that ought to be ignored. Its purpose is to occupy field ids in records in order to prevent backwards/forwards compatibility problems, see the description of record types below. +The type `reserved` is a type with unknown content that ought to be ignored. Its purpose is to occupy field ids in records in order to prevent backwards/forwards compatibility problems, see the description of record types below. ``` - ::= ... | unavailable + ::= ... | reserved ``` **Note:** This type has a similar role as *reserved fields* in proto buffers. @@ -345,7 +345,7 @@ record { num : nat; city : text; zip : nat; - state : unavailable; // removed since no longer needed + state : reserved; // removed since no longer needed } record { nat; nat } @@ -353,6 +353,7 @@ record { 0 : nat; 1 : nat } ``` The latter two records are equivalent. + #### Variants A *variant* is a tagged union of different possible data types. The tag is given by a numeric id that uniquely determines the variant case. Each case is described as a field. The order in which fields are specified is immaterial. @@ -634,12 +635,12 @@ type TruckTypeId = nat; type Weight = float32; type TruckTypeInfo = record { - id : TruckTypeId; - short_name : Text; - description : Text; - capacity : opt Weight; - isFridge : opt bool; - isFreezer : opt bool; + id : TruckTypeId; + short_name : Text; + description : Text; + capacity : opt Weight; + isFridge : opt bool; + isFreezer : opt bool; }; service Server : { @@ -651,9 +652,9 @@ service Server : { Note: * `TruckTypeId` and `nat` are used interchangeably. -With this IDL file, the server actor code will be: +With this IDL file, the server code in ActorScript could be: ``` -actor server = { +actor Server { registrarAddTruckType(truck_info : TruckTypeInfo) : async ?TruckTypeId { getModel().truckTypeTable.AddInfoGetId( func (id_ : TruckTypeId) : TruckTypeInfo = shared { @@ -721,7 +722,7 @@ T(nat) = sleb128(-5 - log2(N/8)) T(int) = sleb128(-9 - log2(N/8)) T(float) = sleb128(-13 - log2(N/32)) T(text) = sleb128(-15) -T(unavailable) = sleb128(-16) +T(reserved) = sleb128(-16) T : -> i8* T(opt ) = sleb128(-17) I() @@ -786,7 +787,7 @@ M(z : float) = f(z) M(b : bool) = i8(if b then 1 else 0) M(t : text) = leb128(|utf8(t)|) i8*(utf8(t)) M(_ : null) = . -M(_ : unavailable) = . +M(_ : reserved) = . M : -> -> i8* M(null : opt ) = i8(0) From 94fdd5ec1d798080de673b10a9b0586d1e0d18f6 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 6 Jun 2019 16:07:53 +0200 Subject: [PATCH 0136/1176] Add a bottom type to IDL (#476) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add a bottom type to IDL the need for a bottom type follows from: 1. We have `None` in ActorScript. 2. We want to use it in the IDL (@matthewhammer uses a generic `Result` type, and if there cannot be an error, puts `None` in `t2`). So `None ∈ dom e`. 3. `None <: t` for all `t` in ActorScript 4. `∀ t1 t2 : dom(e), t1 <: t2 ⟹ e(t1) <: e(t2)` as per #465 This PR proposes adding a bottom type (called `absent`, but other names like `bottom` are fine too). But there are alternatives: * The ADL-AS spec currently has `e(None) = variant {}`. This has the right semantics as an empty set of values, but lacks the right subtyping relation in the IDL subtyping. We could fix the latter, i.e. add an ad-hoc rule `variant {} <: t` and would not have to extend the grammer of the IDL spec. I actually like that. * We define `e` to normalize types with `None` first, with rewrite rules like ``` (None, t) = None shared { n:None, … } = None variant { n:None, … } = variant { … } ? None = null [None] = () None -> t = unavailable t -> None = None // fishy, the function could just be not returning, // but still do something useful ``` with such rules I assume we can completely remove `None` from the actor signature (unless the whole actor becomes `None`). But this might be surprising to the user and cause problems if we add parametric type definitions at some point, such as ``` type Result = { #ok : t1; #fail : t2 } ``` * s/absent/empty --- design/IDL.md | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/design/IDL.md b/design/IDL.md index f53c9e91a5f..8b876f01337 100644 --- a/design/IDL.md +++ b/design/IDL.md @@ -77,6 +77,7 @@ This is a summary of the grammar proposed: | text | null | reserved + | empty ::= | opt @@ -258,6 +259,12 @@ The type `reserved` is a type with unknown content that ought to be ignored. Its ``` **Note:** This type has a similar role as *reserved fields* in proto buffers. +#### Empty + +The type `empty` is the type of values that are not present. Its purpose is to mark variants that are not actually there, or -- as argument types of function reference -- indicate that they will not be called. +``` + ::= ... | empty +``` ### Constructed Data @@ -533,11 +540,15 @@ An exception are integers, which can be specialised to natural numbers: nat <: int ``` -An additional rule applies to `unavailable`, which makes it a top type, i.e., a supertype of every type. +Additional rules apply to `empty` and `reserved`, which makes these a bottom resp. top type: ``` ------------------------- - <: unavailable + <: reserved + + +-------------------- +empty <: ``` #### Options and Vectors @@ -723,12 +734,13 @@ T(int) = sleb128(-9 - log2(N/8)) T(float) = sleb128(-13 - log2(N/32)) T(text) = sleb128(-15) T(reserved) = sleb128(-16) +T(empty) = sleb128(-17) T : -> i8* -T(opt ) = sleb128(-17) I() -T(vec ) = sleb128(-18) I() -T(record {^N}) = sleb128(-19) T*(^N) -T(variant {^N}) = sleb128(-20) T*(^N) +T(opt ) = sleb128(-18) I() +T(vec ) = sleb128(-19) I() +T(record {^N}) = sleb128(-20) T*(^N) +T(variant {^N}) = sleb128(-21) T*(^N) T : -> i8* T(:) = leb128() I() @@ -788,6 +800,7 @@ M(b : bool) = i8(if b then 1 else 0) M(t : text) = leb128(|utf8(t)|) i8*(utf8(t)) M(_ : null) = . M(_ : reserved) = . +// NB: M(_ : empty) will never be called M : -> -> i8* M(null : opt ) = i8(0) From 9f5121deb874696fa2c53fee38547f9182e4155e Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 6 Jun 2019 12:29:01 -0600 Subject: [PATCH 0137/1176] use a 'real' hash function; profiling shows that tries are finally balanced; faster trie merge --- stdlib/Makefile | 5 +++-- stdlib/assocList.as | 40 +++++++++++++++++++++++++++++++++------ stdlib/hash.as | 46 +++++++++++++++++++++++++++++++++++++-------- stdlib/list.as | 4 ++-- stdlib/trie2.as | 16 ++++------------ 5 files changed, 81 insertions(+), 30 deletions(-) diff --git a/stdlib/Makefile b/stdlib/Makefile index 73e72372f3c..4b0f1f13b6d 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -314,7 +314,7 @@ $(OUTDIR)/profileLoadQuery.05-100.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QU # wasm binaries and time measurements for various-sized PX workloads # # these sizes all run without memory limitation issues; bigger sizes complain about growing memory -profile-wasm-success:\ +profile-wasm-success: profile-fast-counts $(OUTDIR) \ $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm \ $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm.csv \ \ @@ -343,7 +343,8 @@ profile-wasm-success:\ $(OUTDIR)/ProduceExchangeLoadQuery_5_9.wasm.csv \ # wasm binaries and time measurements for various-sized PX workloads -profile-wasm:\ +profile-wasm: profile-fast-counts $(OUTDIR) \ + \ $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm \ $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm.csv \ \ diff --git a/stdlib/assocList.as b/stdlib/assocList.as index 93682d344b4..c0d2c33bbc6 100644 --- a/stdlib/assocList.as +++ b/stdlib/assocList.as @@ -1,11 +1,11 @@ module { /** -Association Lists +Association Lists ================== - + Association Lists, a la functional programming, in ActorScript. - + Implements the same interface as `Trie`, but as a linked-list of key-value pairs. */ @@ -105,18 +105,46 @@ type AssocList = List.List<(K,V)>; rec(al1) }; + /** + `mapAppend` + -------- + */ + func mapAppend(al1:AssocList, + al2:AssocList, + vbin:(?V,?W)->X) + : AssocList + { + func rec(al1:AssocList, + al2:AssocList) : AssocList { + switch (al1, al2) { + case (null, null) null; + case (?((k,v),al1_), _ ) ?((k, vbin(?v, null)), rec(al1_, al2 )); + case (null, ?((k,v),al2_)) ?((k, vbin(null, ?v)), rec(null, al2_)); + } + }; + rec(al1, al2) + }; + + func disjDisjoint(al1:AssocList, + al2:AssocList, + vbin:(?V,?W)->X) + : AssocList + { + mapAppend(al1, al2, vbin) + }; + /** `disj` -------- This operation generalizes the notion of "set union" to finite maps. Produces a "disjunctive image" of the two lists, where the values of matching keys are combined with the given binary operator. - + For unmatched key-value pairs, the operator is still applied to create the value in the image. To accomodate these various situations, the operator accepts optional values, but is never applied to (null, null). - + */ func disj(al1:AssocList, al2:AssocList, @@ -158,7 +186,7 @@ type AssocList = List.List<(K,V)>; finite maps. Produces a "conjuctive image" of the two lists, where the values of matching keys are combined with the given binary operator, and unmatched key-value pairs are not present in the output. - + */ func join(al1 : AssocList, al2:AssocList, diff --git a/stdlib/hash.as b/stdlib/hash.as index da640d5e608..8be2b2e4568 100644 --- a/stdlib/hash.as +++ b/stdlib/hash.as @@ -49,20 +49,51 @@ module BitVec { type t = BitVec; + // Jenkin's one at a time: + // https://en.wikipedia.org/wiki/Jenkins_hash_function#one_at_a_time + // + // The input type should actually be [Word8]. + // Note: Be sure to explode each Word8 of a Word32 into its own Word32, and to shift into lower 8 bits. + func hashWord8s(key:[BitVec]) : BitVec = label profile_hash_hashWord8s : BitVec { + var hash = natToWord32(0); + for (wordOfKey in key.vals()) { label profile_hash_hashWord8s_forLoop : () + hash := hash + wordOfKey; + hash := hash + hash << 10; + hash := hash ^ (hash >> 6); + }; + hash := hash + hash << 3; + hash := hash ^ (hash >> 11); + hash := hash + hash << 15; + return hash; + }; + func length() : Nat = label profile_hash_length : Nat 31; - func hashOfInt(i:Int) : BitVec { - hashInt(i) + func hashOfInt(i:Int) : BitVec = label profile_hash_hashOfInt : BitVec { + //hashInt(i) + let j = intToWord32(i); + hashWord8s( + [j & (255 << 0), + j & (255 << 8), + j & (255 << 16), + j & (255 << 24) + ]); }; - func hashOfIntAcc(h1:BitVec, i:Int) : BitVec { - let h2 = hashInt(i); - h2 ^ (h1 << 10) ^ (h2 << 20); + func hashOfIntAcc(h1:BitVec, i:Int) : BitVec = label profile_hash_hashOfIntAcc : BitVec { + let j = intToWord32(i); + hashWord8s( + [h1, + j & (255 << 0), + j & (255 << 8), + j & (255 << 16), + j & (255 << 24) + ]); }; - func hashOfText(t:Text) : BitVec { + func hashOfText(t:Text) : BitVec = label profile_hash_hashOfText : BitVec { var x = 0 : Word32; for (c in t.chars()) { x := x ^ charToWord32(c); @@ -71,8 +102,7 @@ module BitVec { }; /** Project a given bit from the bit vector. */ - func getHashBit(h:BitVec, pos:Nat) : Bool = - label profile_getHashBit : Bool { + func getHashBit(h:BitVec, pos:Nat) : Bool = label profile_getHashBit : Bool { assert (pos <= length()); if ((h & (natToWord32(1) << natToWord32(pos))) != natToWord32(0)) { label profile_getHashBit_true : Bool diff --git a/stdlib/list.as b/stdlib/list.as index 17b95517726..917f29ff073 100644 --- a/stdlib/list.as +++ b/stdlib/list.as @@ -83,8 +83,8 @@ type List = ?(T, List); -------- length; tail recursive */ - func len(l : List) : Nat = { - func rec(l : List, n : Nat) : Nat { + func len(l : List) : Nat = label profile_list_len : Nat { + func rec(l : List, n : Nat) : Nat = label profile_list_len_rec : Nat { switch l { case null { n }; case (?(_,t)) { rec(t,n+1) }; diff --git a/stdlib/trie2.as b/stdlib/trie2.as index a0008b87d08..304df119e17 100644 --- a/stdlib/trie2.as +++ b/stdlib/trie2.as @@ -457,23 +457,15 @@ type Trie3D = Trie >; case (_, #empty) { return tl }; case (#leaf l1, #leaf l2) { lf( - AssocList.disj,V,V,V>( + AssocList.disjDisjoint,V,V,V>( l1.keyvals, l2.keyvals, - key_eq, func (x:?V, y:?V):V = { switch (x, y) { - case (null, null) { - /* IMPOSSIBLE case. */ - P.unreachable() - }; - case (?_, ?_) { - /* INVALID case: left and right defined for the same key */ - assert false; - P.unreachable() - }; case (null, ?v) v; case (?v, null) v; - }} + case (_, _) P.unreachable(); + } + } ) ) }; From c3a23f28d6cae102c3554a8e9ed6e235ea62e01a Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Thu, 6 Jun 2019 12:03:44 -0700 Subject: [PATCH 0138/1176] address comments --- idl/compile_js.ml | 16 ++++++++-------- idl/main.ml | 2 +- test/idl/cyclic.did | 5 ----- test/idl/fields.did | 14 +++++++------- test/idl/invalid_cyclic.did | 5 +++++ test/idl/ok/actor.js.ok | 2 +- test/idl/ok/cyclic.js.ok | 7 +++++++ test/idl/ok/cyclic.tc.ok | 1 - test/idl/ok/fields.js.ok | 2 +- test/idl/ok/integer.js.ok | 6 +++--- test/idl/ok/invalid_cyclic.tc.ok | 1 + test/idl/ok/test.js.ok | 11 ++++++----- 12 files changed, 40 insertions(+), 32 deletions(-) create mode 100644 test/idl/invalid_cyclic.did create mode 100644 test/idl/ok/cyclic.js.ok delete mode 100644 test/idl/ok/cyclic.tc.ok create mode 100644 test/idl/ok/invalid_cyclic.tc.ok diff --git a/idl/compile_js.ml b/idl/compile_js.ml index a4ff3de6916..cd1d90a4198 100644 --- a/idl/compile_js.ml +++ b/idl/compile_js.ml @@ -12,15 +12,15 @@ let field_name ppf s = str ppf "'"; str ppf s.it; str ppf "'"; pp_print_cut ppf let pp_prim p = match p with | Nat -> "Nat" - | Nat8 -> "Nat" - | Nat16 -> "Nat" - | Nat32 -> "Nat" - | Nat64 -> "Nat" + | Nat8 -> "Nat8" + | Nat16 -> "Nat16" + | Nat32 -> "Nat32" + | Nat64 -> "Nat64" | Int -> "Int" - | Int8 -> "Int" - | Int16 -> "Int" - | Int32 -> "Int" - | Int64 -> "Int" + | Int8 -> "Int8" + | Int16 -> "Int16" + | Int32 -> "Int32" + | Int64 -> "Int64" | Float32 -> "Float" | Float64 -> "Float" | Bool -> "Bool" diff --git a/idl/main.ml b/idl/main.ml index 5dae631a9a3..c3e59a4e348 100644 --- a/idl/main.ml +++ b/idl/main.ml @@ -71,7 +71,7 @@ let () = Printexc.record_backtrace true; try Arg.parse argspec add_arg usage; - if !mode = Default then mode := Js; + if !mode = Default then mode := Check; process_files !args with exn -> print_exn exn diff --git a/test/idl/cyclic.did b/test/idl/cyclic.did index a81205caf8d..f33db13bc14 100644 --- a/test/idl/cyclic.did +++ b/test/idl/cyclic.did @@ -6,8 +6,3 @@ type X = Y; type Y = Z; type Z = A; -type D = E; -type E = F; -type F = G; -type G = D; - diff --git a/test/idl/fields.did b/test/idl/fields.did index cf6f72f46ef..a381d4ff50a 100644 --- a/test/idl/fields.did +++ b/test/idl/fields.did @@ -1,13 +1,13 @@ -type A = record {nat;nat;nat;}; -type B = record {blob; 35:blob;nat;nat;named_files:reserved;nat;nat}; -type C = variant {red;4;3;2;1;reserved;10;green;blue;A;B;C}; +type A = record { nat; nat; nat; }; +type B = record { blob; 35:blob; nat; nat; named_files:reserved; nat; nat }; +type C = variant { red; 4; 3; 2; 1; reserved; 10; green; blue; A; B; C }; type nest_record = record { - nat;nat;nat; + nat; nat; nat; record { - nat;nat;nat; + nat; nat; nat; }; - nat;nat;nat; - A;B;C;nat; + nat; nat; nat; + A; B; C; nat; }; diff --git a/test/idl/invalid_cyclic.did b/test/idl/invalid_cyclic.did new file mode 100644 index 00000000000..77ec24b70d6 --- /dev/null +++ b/test/idl/invalid_cyclic.did @@ -0,0 +1,5 @@ +type D = E; +type E = F; +type F = G; +type G = D; + diff --git a/test/idl/ok/actor.js.ok b/test/idl/ok/actor.js.ok index 313e553af12..512aae673cf 100644 --- a/test/idl/ok/actor.js.ok +++ b/test/idl/ok/actor.js.ok @@ -1,4 +1,4 @@ -const f = IDL.message(IDL.Obj({'0': IDL.Int}), IDL.Obj({'0': IDL.Int})) +const f = IDL.message(IDL.Obj({'0': IDL.Int8}), IDL.Obj({'0': IDL.Int8})) const g = f const h = IDL.message(IDL.Obj({'0': f}), IDL.Obj({'0': f})) const o = IDL.Opt(o) diff --git a/test/idl/ok/cyclic.js.ok b/test/idl/ok/cyclic.js.ok new file mode 100644 index 00000000000..746a7a557c8 --- /dev/null +++ b/test/idl/ok/cyclic.js.ok @@ -0,0 +1,7 @@ +const A = IDL.Opt(B) +const C = A +const B = IDL.Opt(C) +const X = Y +const Y = Z +const Z = A + diff --git a/test/idl/ok/cyclic.tc.ok b/test/idl/ok/cyclic.tc.ok deleted file mode 100644 index 37467c8cfb3..00000000000 --- a/test/idl/ok/cyclic.tc.ok +++ /dev/null @@ -1 +0,0 @@ -cyclic.did:9.10-9.11: type error, D has a cyclic type definition diff --git a/test/idl/ok/fields.js.ok b/test/idl/ok/fields.js.ok index 6ce735ba91a..1457a7325a2 100644 --- a/test/idl/ok/fields.js.ok +++ b/test/idl/ok/fields.js.ok @@ -1,6 +1,6 @@ const A = IDL.Obj({'0': IDL.Nat, '1': IDL.Nat, '2': IDL.Nat}) const B = - IDL.Obj({'0': IDL.Arr(IDL.Nat), '35': IDL.Arr(IDL.Nat), '36': IDL.Nat, + IDL.Obj({'0': IDL.Arr(IDL.Nat8), '35': IDL.Arr(IDL.Nat8), '36': IDL.Nat, '37': IDL.Nat, 'named_files': IDL.None, '653352244': IDL.Nat, '653352245': IDL.Nat}) const C = diff --git a/test/idl/ok/integer.js.ok b/test/idl/ok/integer.js.ok index d531ed509da..e9c26dee5e3 100644 --- a/test/idl/ok/integer.js.ok +++ b/test/idl/ok/integer.js.ok @@ -1,4 +1,4 @@ const num = new IDL.ActorInterface({ - 'f': IDL.message(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': IDL.Int})), - 'g': IDL.message(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': IDL.Int})), - 'h': IDL.message(IDL.Obj({'0': IDL.Int}), IDL.Obj({'0': IDL.Nat}))}) + 'f': IDL.message(IDL.Obj({'0': IDL.Nat8}), IDL.Obj({'0': IDL.Int16})), + 'g': IDL.message(IDL.Obj({'0': IDL.Nat64}), IDL.Obj({'0': IDL.Int64})), + 'h': IDL.message(IDL.Obj({'0': IDL.Int8}), IDL.Obj({'0': IDL.Nat}))}) diff --git a/test/idl/ok/invalid_cyclic.tc.ok b/test/idl/ok/invalid_cyclic.tc.ok new file mode 100644 index 00000000000..77d2187068d --- /dev/null +++ b/test/idl/ok/invalid_cyclic.tc.ok @@ -0,0 +1 @@ +invalid_cyclic.did:1.10-1.11: type error, D has a cyclic type definition diff --git a/test/idl/ok/test.js.ok b/test/idl/ok/test.js.ok index 05f1f7a7faf..39867203392 100644 --- a/test/idl/ok/test.js.ok +++ b/test/idl/ok/test.js.ok @@ -13,8 +13,9 @@ const broker = }) const server = new IDL.ActorInterface({ 'addUser': - IDL.message(IDL.Obj({'name': IDL.Text, 'age': IDL.Nat}), - IDL.Obj({'id': IDL.Nat})), - 'userName': IDL.message(IDL.Obj({'id': IDL.Nat}), IDL.Obj({'0': IDL.Text})), - 'userAge': IDL.message(IDL.Obj({'id': IDL.Nat}), IDL.Obj({'0': IDL.Nat})), - 'deleteUser': IDL.message(IDL.Obj({'id': IDL.Nat}), IDL.Obj({}))}) + IDL.message(IDL.Obj({'name': IDL.Text, 'age': IDL.Nat8}), + IDL.Obj({'id': IDL.Nat64})), + 'userName': + IDL.message(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({'0': IDL.Text})), + 'userAge': IDL.message(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({'0': IDL.Nat8})), + 'deleteUser': IDL.message(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({}))}) From 3e917e5a6d68f54b5225787939bce2aa18987d38 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Thu, 6 Jun 2019 21:02:10 +0100 Subject: [PATCH 0139/1176] [AST-77][AST-89] Fix correct check_ir.check_pat (#480) * correct check_ir.check_pat subtyping checks; fix bug in source interpretation of variants; add test * cleanup * made patterns total to avoid ok files * make ir-litpat-subtype.as warning free * make test warning free * new line * formatting --- src/check_ir.ml | 11 +++-- src/interpret.ml | 6 ++- test/run/ir-litpat-subtype.as | 5 +++ test/run/ir-pat-subtype.as | 85 +++++++++++++++++++++++++++++++++++ 4 files changed, 102 insertions(+), 5 deletions(-) create mode 100644 test/run/ir-litpat-subtype.as create mode 100644 test/run/ir-pat-subtype.as diff --git a/src/check_ir.ml b/src/check_ir.ml index b1f409c6b30..313e549ff71 100644 --- a/src/check_ir.ml +++ b/src/check_ir.ml @@ -598,9 +598,12 @@ and check_pat env pat : val_env = match pat.it with | WildP -> T.Env.empty | VarP id -> T.Env.singleton id.it pat.note + | LitP Syntax.NullLit -> + T.Prim T.Null <: t; + T.Env.empty | LitP lit -> let t1 = T.Prim (type_lit env lit pat.at) in - t1 <: t; + t <: t1; T.Env.empty | TupP pats -> let ve = check_pats pat.at env pats T.Env.empty in @@ -613,7 +616,7 @@ and check_pat env pat : val_env = ve | OptP pat1 -> let ve = check_pat env pat1 in - T.Opt pat1.note <: t; + t <: T.Opt pat1.note; ve | TagP (i, pat1) -> let ve = check_pat env pat1 in @@ -622,8 +625,8 @@ and check_pat env pat : val_env = | AltP (pat1, pat2) -> let ve1 = check_pat env pat1 in let ve2 = check_pat env pat2 in - pat1.note <: t; - pat2.note <: t; + t <: pat1.note; + t <: pat2.note; check env pat.at (T.Env.is_empty ve1 && T.Env.is_empty ve2) "variables are not allowed in pattern alternatives"; T.Env.empty diff --git a/src/interpret.ml b/src/interpret.ml index 3474ef8e3c8..11b21e9ac14 100644 --- a/src/interpret.ml +++ b/src/interpret.ml @@ -500,7 +500,11 @@ and define_pat env pat v = trap pat.at "value %s does not match pattern" (V.string_of_val v) | _ -> assert false ) - | TagP (_, pat1) + | TagP (i, pat1) -> + let lab, v1 = V.as_variant v in + if lab = i.it + then define_pat env pat1 v1 + else trap pat.at "value %s does not match pattern" (V.string_of_val v) | AnnotP (pat1, _) | ParP pat1 -> define_pat env pat1 v diff --git a/test/run/ir-litpat-subtype.as b/test/run/ir-litpat-subtype.as new file mode 100644 index 00000000000..1c914d13553 --- /dev/null +++ b/test/run/ir-litpat-subtype.as @@ -0,0 +1,5 @@ +func bar (a : Nat) = switch a { + case (25 : Int) (); // OK: pattern of supertype accepted + case _ (); +} + diff --git a/test/run/ir-pat-subtype.as b/test/run/ir-pat-subtype.as new file mode 100644 index 00000000000..17680076560 --- /dev/null +++ b/test/run/ir-pat-subtype.as @@ -0,0 +1,85 @@ +type L = {a:{}}; +type U = {}; + +let l = new {a = new {}}; + +func f(l:L):U = switch l { + case (u:U) u; +}; + +let {} = f(l); + +// tuples +func t1(tl : (L, L) ) : (U, U) = switch tl { + case (tu : (U, U)) tu; +}; + +let ({}, {}) = t1((l,l)); + +func t2(tl : (L, L)) : (U, U) = switch tl { + case (u1 : U, u2 : U) (u1,u2); +}; + +let ({}, {}) = t2((l, l)); + + +// options + +func o1(ol : ? L) : ? U = switch ol { + case (null : ? U) null; + case (ou: ? U) ou; +}; + +let (? {} or _) = o1(? l); + +func o2(tl : ? L) : ? U = switch tl { + case (null : ? U) null; + case (? u) (? u); +}; + +let (? {} or _) = o2(? l); + +// records + +func r1(rl : object { a : L }) : object { a : U } = switch rl { + case (ru : { a : U }) ru; +}; + +let { a = {} } : object { a : U } = r1(object { a = l }); + +func r2(rl : object { a : L }) : object { a : U } = switch rl { + case ({a=u:U}) object {a=u}; +}; + +let { a = {} } : object { a : U } = r2(object { a = l }); + +func r3(rl : object { a : L }) : object {} = switch rl { + case {} object {}; +}; + +let {}:object{} = r3(object{a=l}); + + +// variants + +func v1(vl : { #a : L }) : {#a:U} = switch vl { + case (vu : { #a : U }) vu; +}; + +let (#a {} or _)= v1(#a l); + +func v2(vl : { #a : L }) : { #a : U } = switch vl { + case (#a u) #a u; + case _ vl; +}; + +let (#a {} or _) = v2(#a l); + +// alternative patterns + +func a(l : object { a : Int }):U = switch l { + case (({ a = 1 }:object { a : Int }) or ( _ : U) ) l; +}; + +let {} = a(object {a = 2}); + From c24102a21a8ab23fd2bb432df4314df37ae3f2fe Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Thu, 6 Jun 2019 22:07:52 +0200 Subject: [PATCH 0140/1176] IDL elaboration and some other tweaks (#438) --- design/IDL.md | 215 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 188 insertions(+), 27 deletions(-) diff --git a/design/IDL.md b/design/IDL.md index 8b876f01337..7244eedaf93 100644 --- a/design/IDL.md +++ b/design/IDL.md @@ -309,6 +309,7 @@ The id is described as a simple unsigned integer that has to fit the 64 bit valu ``` An id value must be smaller than 2^32 and no id may occur twice in the same record type. + ##### Shorthand: Symbolic Field Ids An id can also be given as a *name*, which is a shorthand for a numeric id that is the hash of that name: @@ -317,6 +318,8 @@ An id can also be given as a *name*, which is a shorthand for a numeric id that | : := : ``` +The purpose of identifying fields by unique (numeric or textual) ids is to support safe upgrading of the record type returned by an IDL function: a new version of an IDL can safely *add* fields to an out record as long as their id has not been used before. See the discussion on upgrading below for more details. + The hash function is specified as ``` hash(id) = ( Sum_(i=0..k) id[i] * 223^(k-i) ) mod 2^32 where k = |id|-1 @@ -332,6 +335,7 @@ This hash function has the the following useful properties: The hash function does not have the property that every numeric value can be turned into a human-readable preimage. Host languages that cannot support numeric field names will have to come up with a suitable encoding textual encoding of numeric field names, as well as of field names that are not valid in the host langauge. + ##### Shorthand: Tuple Fields Field ids can also be omitted entirely, which is just a shorthand for picking either 0 (for the first field) or N+1 when the previous field has id N. @@ -340,10 +344,6 @@ Field ids can also be omitted entirely, which is just a shorthand for picking ei | := N : ``` -##### Upgrading - -The purpose of identifying fields by unique (numeric or textual) ids is to support safe upgrading of the record type returned by an IDL function: a new version of an IDL can safely *add* fields to a record as long as their id has not been used before. See below for more details. - ##### Examples ``` record { @@ -352,7 +352,6 @@ record { num : nat; city : text; zip : nat; - state : reserved; // removed since no longer needed } record { nat; nat } @@ -509,13 +508,15 @@ For upgrading data structures passed between service and client, it is important That is, outbound message results can only be replaced with a subtype (more fields) in an upgrade, while inbound message parameters can only be replaced with a supertype (fewer fields). This corresponds to the notions of co-variance and contra-variance in type systems. -Subtyping replies recursively to the types of the fields themselves. Moreover, the directions get *inverted* for inbound function and actor references, in compliance with standard rules. +Subtyping applies recursively to the types of the fields themselves. Moreover, the directions get *inverted* for inbound function and actor references, in compliance with standard rules. + +**TODO: unsound, fix** To make these constraints as flexible as possible, two special rules apply: -* An absent record field is considered equivalent to a present field with value `null`. Moreover, a record field of type `null` is a subtype of a field with type `opt `. That way, + * An absent record field is considered equivalent to a present field with value `null`. Moreover, a record field of type `null` is a subtype of a field with type `opt `. That way, That way, a field of option (or null) type can always be added to a record type, no matter whether in co- or contra-variant position. If an optional field is added to an inbound record, and he client did not provide it, the service will read it as if its value was null. - - in an outbound record, a field of option (or null) type can also be removed in an upgrade, in which case the client will read it as if its value was null; + - in an outbound record, a field of option (or null) type can also be removed in an upgrade, in which case the client will read it as if its value was null; - in an inbound record, a field of option (or null) type can also be added, in which case the service will read it as if its value was null. Future extensions: defaults, including for variants? @@ -563,11 +564,25 @@ opt <: opt --------------------------------- vec <: vec ``` -More flexible rules apply to option types used as record field types, see below. +Furthermore, an option type can be specialised to either `null` or to its constituent type: +``` +not (null <: ) +------------------------ +null <: opt + +not (null <: ) + <: +----------------------------- + <: opt +``` +The premise means that the rule does not apply when the constituent type is itself `null` or an option. That restriction is necessary so that there is no ambiguity. For example, there would be two ways to interpret `null` when going from `opt nat` to `opt opt nat`, either as `null` or as `?null`. + +Q: The negated nature of this premise isn't really compatible with parametric polymorphism. Is that a problem? We could always introduce a supertype of all non-nullable types and rephrase it with that. + #### Records -In a specialised record type, the type of a record field can be specialised, or a field can be added. +In a specialised record type, the type of a record field can be specialised, or a field can be added. ``` --------------------------------------- @@ -581,19 +596,52 @@ record { : ; ;* } <: record { : ; = null \/ = opt record { ;* } <: record { ;* } ------------------------------------------------------------------------------ -record { ;* } <: record { : ; ;* } +------------------------------------------------------------------- +record { ;* } <: record { : null; ;* } - <> null /\ <> opt - <: record { ;* } <: record { ;* } --------------------------------------------------------------------------------------------------- -record { : ; ;* } <: record { : opt ; ;* } +----------------------------------------------------------------------------- +record { ;* } <: record { : opt ; ;* } +``` +TODO: What we want to achieve: Taken together, these rules ensure that adding an optional field creates both a co- and a contra-variant subtype. Consequently, it is always possible to add an optional field. In particular, that allows extending round-tripping record types as well. For example, +``` +type T = {}; +actor { f : T -> T }; +``` +can safely be upgraded to +``` +type T' = {x : opt text}; +actor { f : T' -> T' }; +``` +for all first-order uses of `T`, because both of the following hold: +``` +upgrade T' <: T +upgrade T <: T' +``` +And hence: +``` +upgrade (T' -> T') <: (T -> T) +``` +for some version of a type `upgrade T`. +Moreover, this extends to the higher-order case, where e.g. a function of the above type is expected as a parameter: ``` +actor { g : (h : T -> T) -> ()} +``` +Upgrading `T` as above contra-variantly requires +``` +upgrade (T -> T) <: (T' -> T') +``` +which also holds. + +Note: Subtyping still needs to be transitive . We must not allow: +``` +record {x : opt text} <: record {} <: record {x : opt nat} +``` +**TODO: Sanity continues from here.** + #### Variants @@ -615,27 +663,140 @@ For a specialised function, any parameter type can be generalised and any result ``` record { ;* } <: record { ;* } record { ;* } <: record { ;* } -{ a | a in * } = { a | a in * } ------------------------------------------------------------------------------------------------- -func ( ,* ) -> ( ,* ) * <: func ( ,* ) -> ( ,* ) * +----------------------------------------------------------------------------------------------------------------------- +func ( ,* ) -> ( ,* ) * <: func ( ,* ) -> ( ,* ) * ``` Viewed as sets, the annotations on the functions must be equal. #### Actors -For an actor, a method can be specialised (by specialising its function type), or a method added. Essentially, they are treated exactly like records of functions. +For an actor, a method can be specialised (by specialising its function type), or a method added. Essentially, they are treated like records of functions. ``` ------------------------------------- -actor { ;* } <: actor { } +---------------------------------------- +service { ;* } <: service { } <: -actor { ;* } <: actor { ;* } --------------------------------------------------------------------------------------------- -actor { : ; ;* } <: actor { : ; ;* } +service { ;* } <: service { ;* } +------------------------------------------------------------------------------------------------ +service { : ; ;* } <: service { : ; ;* } +``` + +### Elaboration + +To define the actual coercion function, we extend the subtyping relation to a ternary *elaboration* relation `T <: T' ~> f`, where `f` is a suitable coercion function of type `T -> T'`. + + +#### Primitive Types + +``` + +-------------------------------- + <: ~> \x.x + + +------------------ +Nat <: Int ~> \x.x + + +------------------------------ + <: reserved ~> \x.x + + +------------------------------ +empty <: ~> \_.unreachable ``` +#### Options and Vectors + +``` + <: ~> f +--------------------------------------------------- +opt <: opt ~> \x.map_opt f x + + <: ~> f +--------------------------------------------------- +vec <: vec ~> \x.map_vec f x + +not (null <: ) +--------------------------------- +null <: opt ~> \x.null + +not (null <: ) + <: ~> f +------------------------------------------ + <: opt ~> \x.?(f x) +``` + + +#### Records + +``` + +------------------------------------------------ +record { ;* } <: record { } ~> \x.{} + + <: ~> f1 +record { ;* } <: record { ;* } ~> f2 +---------------------------------------------------------------------------------------------- +record { : ; ;* } <: record { : ; ;* } + ~> \x.{f2 x with = f1 x.} +``` + +TODO: Fix +``` +record { ;* } <: record { ;* } ~> f +------------------------------------------------------------------- +record { ;* } <: record { : null; ;* } + ~> \x.{f x; = null} + +record { ;* } <: record { ;* } ~> f +----------------------------------------------------------------------------- +record { ;* } <: record { : opt ; ;* } + ~> \x.{f x; = null} +``` + + +#### Variants + +``` + +------------------------------------------------- +variant { } <: variant { ;* } ~> \x.x + + <: ~> f1 +variant { ;* } <: variant { ;* } ~> f2 +------------------------------------------------------------------------------------------------ +variant { : ; ;* } <: variant { : ; ;* } + ~> \x.case x of y => (f1 y) | _ => f2 x +``` + +#### Functions + +``` +record { ;* } <: record { ;* } ~> f1 +record { ;* } <: record { ;* } ~> f2 +---------------------------------------------------------------------------------------------------------------------- +func ( ,* ) -> ( ,* ) * <: func ( ,* ) -> ( ,* ) * + ~> \x.\y.f2 (x (f1 y)) +``` + +#### Actors + +``` + +------------------------------------------------- +service { ;* } <: service { } ~> \x.{} + + <: ~> f1 +service { ;* } <: service { ;* } ~> f2 +------------------------------------------------------------------------------------------------ +service { : ; ;* } <: service { : ; ;* } + ~> \x.{f1 x; = f2 x.} +``` + + ## Example Development Flow We take the produce exchange app as an example to illustrate how a developer would use IDL in their development flow. From 5cc62f95792e2e1cfbede2470f7f116de3b25d46 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Thu, 6 Jun 2019 13:43:47 -0700 Subject: [PATCH 0141/1176] add test for collision between symbolic and numeric field names --- test/idl/collision_fields2.did | 7 +++++++ test/idl/ok/collision_fields2.tc.ok | 1 + 2 files changed, 8 insertions(+) create mode 100644 test/idl/collision_fields2.did create mode 100644 test/idl/ok/collision_fields2.tc.ok diff --git a/test/idl/collision_fields2.did b/test/idl/collision_fields2.did new file mode 100644 index 00000000000..f03bd2dcaa1 --- /dev/null +++ b/test/idl/collision_fields2.did @@ -0,0 +1,7 @@ +type A = record { + "字段名":nat; + 994301184:nat; + "字 段 名2":nat; + "📦🍦":nat; +}; + diff --git a/test/idl/ok/collision_fields2.tc.ok b/test/idl/ok/collision_fields2.tc.ok new file mode 100644 index 00000000000..7ff3a96b5e5 --- /dev/null +++ b/test/idl/ok/collision_fields2.tc.ok @@ -0,0 +1 @@ +collision_fields2.did:5.2-5.12: type error, field name 📦🍦 hash collision with field 994301184 From dede37d9cbbfe2cb69931819848c751038f9b2b1 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 6 Jun 2019 16:35:45 -0600 Subject: [PATCH 0142/1176] trie performance: avoid recomputing lengths of kv lists --- stdlib/Makefile | 2 +- stdlib/assocList.as | 6 +-- stdlib/list.as | 24 ++++++++++ stdlib/trie2.as | 112 ++++++++++++++++++++++++++++++++++---------- 4 files changed, 114 insertions(+), 30 deletions(-) diff --git a/stdlib/Makefile b/stdlib/Makefile index 4b0f1f13b6d..78e3d5267b7 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -343,7 +343,7 @@ profile-wasm-success: profile-fast-counts $(OUTDIR) \ $(OUTDIR)/ProduceExchangeLoadQuery_5_9.wasm.csv \ # wasm binaries and time measurements for various-sized PX workloads -profile-wasm: profile-fast-counts $(OUTDIR) \ +profile-wasm: $(OUTDIR) profile-fast-counts \ \ $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm \ $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm.csv \ diff --git a/stdlib/assocList.as b/stdlib/assocList.as index c0d2c33bbc6..bda8d9452e4 100644 --- a/stdlib/assocList.as +++ b/stdlib/assocList.as @@ -112,10 +112,10 @@ type AssocList = List.List<(K,V)>; func mapAppend(al1:AssocList, al2:AssocList, vbin:(?V,?W)->X) - : AssocList + : AssocList = label profile_assocList_mapAppend : AssocList { func rec(al1:AssocList, - al2:AssocList) : AssocList { + al2:AssocList) : AssocList = label profile_assocList_mapAppend_rec : AssocList { switch (al1, al2) { case (null, null) null; case (?((k,v),al1_), _ ) ?((k, vbin(?v, null)), rec(al1_, al2 )); @@ -128,7 +128,7 @@ type AssocList = List.List<(K,V)>; func disjDisjoint(al1:AssocList, al2:AssocList, vbin:(?V,?W)->X) - : AssocList + : AssocList = label profile_assocList_disjDisjoint : AssocList { mapAppend(al1, al2, vbin) }; diff --git a/stdlib/list.as b/stdlib/list.as index 917f29ff073..03c376a1032 100644 --- a/stdlib/list.as +++ b/stdlib/list.as @@ -117,6 +117,30 @@ type List = ?(T, List); rec(l, i) }; + /** + `lenClamp` + -------- + get the length, unless greater than a maximum value, in which return null; tail recursive + */ + func lenClamp(l : List, i0 : Nat) : ?Nat = + label profile_list_lenClamp : (?Nat) { + func rec(l : List, i : Nat) : ?Nat = label profile_list_lenClamp_rec : (?Nat) { + switch l { + case null { label profile_list_lenClamp_end_some : (?Nat) ?(i0 - i) }; + case (?(_, t)) { + if ( i == 0 ) { + label profile_list_lenClamp_end_null : (?Nat) + null + } + else { + rec(t, i - 1) + } + }; + } + }; + rec(l, i0) + }; + /** `nth` --------- diff --git a/stdlib/trie2.as b/stdlib/trie2.as index 304df119e17..f2481744f88 100644 --- a/stdlib/trie2.as +++ b/stdlib/trie2.as @@ -68,9 +68,10 @@ Below, we define the types used in the representation: */ +//let MAX_LEAF_COUNT = 4; // worse than 8, slightly +let MAX_LEAF_COUNT = 8; // <-- beats both 4 and 16 for me, now +//let MAX_LEAF_COUNT = 16; //let MAX_LEAF_COUNT = 32; -let MAX_LEAF_COUNT = 16; // <-- beats both 32 and 8, for me. -//let MAX_LEAF_COUNT = 8; let P = (import "prelude.as"); @@ -217,7 +218,7 @@ type Trie3D = Trie >; acceptable level of algorithmic efficiently. */ - func count(t: Trie) : Nat { + func count(t: Trie) : Nat = label profile_trie_count : Nat { switch t { case (#empty) 0; case (#leaf l) l.count; @@ -230,7 +231,7 @@ type Trie3D = Trie >; -------- Construct a branch node, computing the count stored there. */ - func branch(l:Trie, r:Trie) : Trie { + func branch(l:Trie, r:Trie) : Trie = label profile_trie_branch : Trie { let sum = count(l) + count(r); #branch( new{ @@ -251,9 +252,9 @@ type Trie3D = Trie >; of the leaf. */ - func leaf(kvs:AssocList,V>, bitpos:Nat) : Trie = - fromList(kvs, bitpos); - + func leaf(kvs:AssocList,V>, bitpos:Nat) : Trie = label trie_leaf : Trie { + fromSizedList(null, kvs, bitpos) + }; func fromList(kvs:AssocList,V>, bitpos:Nat) : Trie = label profile_trie_fromList_begin : (Trie) { @@ -282,6 +283,42 @@ type Trie3D = Trie >; }; + func fromSizedList(kvc:?Nat, kvs:AssocList,V>, bitpos:Nat) : Trie = + label profile_trie_fromList_begin : (Trie) { + func rec(kvc:?Nat, kvs:AssocList,V>, bitpos:Nat) : Trie { + switch kvc { + case null { + switch (List.lenClamp<(Key,V)>(kvs, MAX_LEAF_COUNT)) { + case null () /* fall through to branch case. */; + case (?len) { + return #leaf(new{count=len; keyvals=kvs}) + }; + } + }; + case (?c) { + if ( c == 0 ) { + return #empty + } else if ( c <= MAX_LEAF_COUNT ) { + return #leaf(new{count=c; keyvals=kvs}) + } else { + /* fall through to branch case */ + } + }; + }; + let (ls, l, rs, r) = splitSizedList(kvs, bitpos); + if ( ls == 0 and rs == 0 ) { + #empty + } else if (rs == 0 and ls <= MAX_LEAF_COUNT) { + #leaf(new{count=ls; keyvals=l}) + } else if (ls == 0 and rs <= MAX_LEAF_COUNT) { + #leaf(new{count=rs; keyvals=r}) + } else { + branch(rec(?ls, l, bitpos + 1), rec(?rs, r, bitpos + 1)) + } + }; + rec(kvc, kvs, bitpos) + }; + /** `copy` --------- @@ -298,13 +335,14 @@ type Trie3D = Trie >; label profile_trie_replace : (Trie, ?V) { let key_eq = keyEq(k_eq); - func rec(t : Trie, bitpos:Nat) : (Trie, ?V) { + func rec(t : Trie, bitpos:Nat) : (Trie, ?V) = + label profile_trie_replace_rec : (Trie, ?V) { switch t { - case (#empty) { + case (#empty) label profile_trie_replace_rec_empty : (Trie, ?V) { let (kvs, _) = AssocList.replace,V>(null, k, key_eq, v); (leaf(kvs, bitpos), null) }; - case (#branch b) { + case (#branch b) label profile_trie_replace_rec_branch : (Trie, ?V) { let bit = Hash.getHashBit(k.hash, bitpos); // rebuild either the left or right path with the inserted (k,v) pair if (not bit) { @@ -316,7 +354,7 @@ type Trie3D = Trie >; (branch(b.left, r), v_) } }; - case (#leaf l) { + case (#leaf l) label profile_trie_replace_rec_leaf : (Trie, ?V) { let (kvs2, old_val) = AssocList.replace,V>(l.keyvals, k, key_eq, v); (leaf(kvs2, bitpos), old_val) @@ -343,7 +381,7 @@ type Trie3D = Trie >; --------- find the given key's value in the trie, or return null if nonexistent */ - func find(t : Trie, k:Key, k_eq:(K,K) -> Bool) : ?V { + func find(t : Trie, k:Key, k_eq:(K,K) -> Bool) : ?V = label profile_trie_find : (?V) { let key_eq = keyEq(k_eq); func rec(t : Trie, bitpos:Nat) : ?V = label profile_trie_find_rec : (?V) { switch t { @@ -368,7 +406,6 @@ type Trie3D = Trie >; }; } }; - label profile_trie_find_begin : (?V) rec(t, 0) }; @@ -376,7 +413,8 @@ type Trie3D = Trie >; func splitAssocList(al:AssocList,V>, bitpos:Nat) - : (AssocList,V>, AssocList,V>) + : (AssocList,V>, AssocList,V>) = + label profile_trie_splitAssocList : (AssocList,V>, AssocList,V>) { List.split<(Key,V)>( al, @@ -386,6 +424,27 @@ type Trie3D = Trie >; ) }; + func splitSizedList(l:AssocList,V>, bitpos:Nat) + : (Nat, AssocList,V>, Nat, AssocList,V>) = + label profile_trie_splitSizedList : (Nat, AssocList,V>, Nat, AssocList,V>) + { + func rec(l : AssocList,V>) : (Nat, AssocList,V>, Nat, AssocList,V>) = + label profile_trie_sized_split_rec : (Nat, AssocList,V>, Nat, AssocList,V>) { + switch l { + case null { (0, null, 0, null) }; + case (?((k,v),t)) { + let (cl, l, cr, r) = rec(t) ; + if (not Hash.getHashBit(k.hash, bitpos)){ + (cl + 1, ?((k,v),l), cr, r) + } else { + (cl, l, cr + 1, ?((k,v),r)) + } + }; + } + }; + rec(l) + }; + /** `merge` --------- @@ -401,7 +460,7 @@ type Trie3D = Trie >; - [`prod`](#prod) */ - func merge(tl:Trie, tr:Trie, k_eq:(K,K)->Bool): Trie { + func merge(tl:Trie, tr:Trie, k_eq:(K,K)->Bool) : Trie = label profile_trie_merge : Trie { let key_eq = keyEq(k_eq); func br(l:Trie, r:Trie) : Trie = branch(l,r); func rec(bitpos:Nat, tl:Trie, tr:Trie) : Trie { @@ -447,15 +506,16 @@ type Trie3D = Trie >; dynamic error if there are collisions in common keys between the left and right inputs. */ - func mergeDisjoint(tl:Trie, tr:Trie, k_eq:(K,K)->Bool): Trie { + func mergeDisjoint(tl:Trie, tr:Trie, k_eq:(K,K)->Bool): Trie = + label profile_trie_mergeDisjoint : Trie { let key_eq = keyEq(k_eq); func br(l:Trie, r:Trie) : Trie = branch(l,r); - func rec(bitpos:Nat, tl:Trie, tr:Trie) : Trie { + func rec(bitpos:Nat, tl:Trie, tr:Trie) : Trie = label profile_trie_mergeDisjoint_rec : Trie { func lf(kvs:AssocList,V>) : Trie = leaf(kvs, bitpos); switch (tl, tr) { - case (#empty, _) { return tr }; - case (_, #empty) { return tl }; - case (#leaf l1, #leaf l2) { + case (#empty, _) label profile_trie_mergeDisjoint_rec_emptyL : Trie { return tr }; + case (_, #empty) label profile_trie_mergeDisjoint_rec_emptyR : Trie { return tl }; + case (#leaf l1, #leaf l2) label profile_trie_mergeDisjoint_rec_leafPair : Trie { lf( AssocList.disjDisjoint,V,V,V>( l1.keyvals, l2.keyvals, @@ -469,15 +529,15 @@ type Trie3D = Trie >; ) ) }; - case (#leaf l, _) { + case (#leaf l, _) label profile_trie_mergeDisjoint_rec_splitLeafL : Trie { let (ll, lr) = splitAssocList(l.keyvals, bitpos); rec(bitpos, br(lf ll, lf lr), tr) }; - case (_, #leaf l) { + case (_, #leaf l) label profile_trie_mergeDisjoint_rec_splitLeafR : Trie { let (ll, lr) = splitAssocList(l.keyvals, bitpos); rec(bitpos, tl, br(lf ll, lf lr)) }; - case (#branch b1, #branch b2) { + case (#branch b1, #branch b2) label profile_trie_mergeDisjoint_rec_branchPair : Trie { branch( rec(bitpos + 1, b1.left, b2.left), rec(bitpos + 1, b1.right, b2.right) @@ -643,7 +703,7 @@ type Trie3D = Trie >; */ func join(tl:Trie, tr:Trie, k_eq:(K,K)->Bool, vbin:(V,W)->X) - : Trie + : Trie = label profile_trie_join : Trie { let key_eq = keyEq(k_eq); @@ -651,7 +711,7 @@ type Trie3D = Trie >; func br2(l:Trie, r:Trie) : Trie = branch(l,r); func br3(l:Trie, r:Trie) : Trie = branch(l,r); - func rec(bitpos:Nat, tl:Trie, tr:Trie) : Trie { + func rec(bitpos:Nat, tl:Trie, tr:Trie) : Trie = label profile_trie_join_rec : Trie { func lf1(kvs:AssocList,V>) : Trie = leaf(kvs, bitpos); func lf2(kvs:AssocList,W>) : Trie = leaf(kvs, bitpos); func lf3(kvs:AssocList,X>) : Trie = leaf(kvs, bitpos); @@ -830,7 +890,7 @@ type Trie3D = Trie >; can inject tries into arrays given the Array_tabulate interface for doing so. */ - func nth(t:Trie, i:Nat) : ?(Key, V) { + func nth(t:Trie, i:Nat) : ?(Key, V) = label profile_trie_nth : (?(Key, V)) { func rec(t:Trie, i:Nat) : ?(Key, V) { switch t { case (#empty) P.unreachable(); From 4b4678205078e40668fca984aa5ebe04f19b0cf7 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 7 Jun 2019 11:47:52 +0200 Subject: [PATCH 0143/1176] Switch build system from `ocamlbuild` to `dune` (#481) * Switch build system from `ocamlbuild` to `dune` * There is still a `Makefile` to offer convenient targets, like ``` make make all make asc make didc ``` * The `make test` target its gone, to keep subdirectory hygiene. The `Makefile` in `src/` is now only concerned with files in `src/`. I recommend ``` make -C src && make -C test ``` for a one-stop command, or adding this command to a top-level `Makefile` if desired. * All ml files are in subdirectories of `src/`. See the file Structure.md for more details. This PR does _not_ yet split the files into more subdirectories than necessary. There is a `lib/` library, to show what is possible, and the executables are in their own directory, which is necessary, but otherwise all files are in `aslib` and `idllib`. I will split `aslib` into more sane components in a seperate PR. * We lose the coverage report that noone has looked at. Once https://github.com/ocaml/dune/issues/57 looks more promising we can add it back. * Warnings are no longer fatal when using `make` (you still see them); building with `nix-build` (and hence CI) will fail if warnings remain. I think this gives a nicer development experience. * Moved build (hardly changes) instructions to `Building.md`, so that `Readme.md` starts again with Goals, and describes the language. --- Building.md | 85 +++++++ README.md | 104 --------- default.nix | 106 ++------- idl/Makefile | 36 --- idl/myocamlbuild.ml | 14 -- src/.gitignore | 19 +- src/.merlin | 3 - src/Makefile | 88 +++----- src/Structure.md | 37 ++++ src/_tags | 1 - src/{ => aslib}/arrange.ml | 0 src/{ => aslib}/arrange_ir.ml | 0 src/{ => aslib}/arrange_type.ml | 0 src/{ => aslib}/async.ml | 0 src/{ => aslib}/async.mli | 0 src/{ => aslib}/await.ml | 0 src/{ => aslib}/await.mli | 0 src/{ => aslib}/check_ir.ml | 0 src/{ => aslib}/check_ir.mli | 0 src/{ => aslib}/compile.ml | 0 src/{ => aslib}/compile.mli | 0 src/{ => aslib}/con.ml | 0 src/{ => aslib}/con.mli | 0 src/{ => aslib}/construct.ml | 0 src/{ => aslib}/construct.mli | 0 src/{ => aslib}/coverage.ml | 0 src/{ => aslib}/coverage.mli | 0 src/{ => aslib}/customModule.ml | 0 src/{ => aslib}/customModuleDecode.ml | 0 src/{ => aslib}/customModuleDecode.mli | 0 src/{ => aslib}/customModuleEncode.ml | 0 src/{ => aslib}/customModuleEncode.mli | 0 src/{ => aslib}/definedness.ml | 0 src/{ => aslib}/definedness.mli | 0 src/{ => aslib}/desugar.ml | 0 src/{ => aslib}/desugar.mli | 0 src/{ => aslib}/diag.ml | 0 src/{ => aslib}/diag.mli | 0 {idl => src/aslib}/dom.ml | 0 src/aslib/dune | 10 + src/{ => aslib}/effect.ml | 0 src/{ => aslib}/effect.mli | 0 src/{ => aslib}/env.ml | 0 src/{ => aslib}/flags.ml | 0 src/{ => aslib}/freevars.ml | 0 src/{ => aslib}/instrList.ml | 0 src/{ => aslib}/interpret.ml | 0 src/{ => aslib}/interpret.mli | 0 src/{ => aslib}/interpret_ir.ml | 0 src/{ => aslib}/interpret_ir.mli | 0 src/{ => aslib}/ir.ml | 0 src/{ => aslib}/lexer.mli | 0 src/{ => aslib}/lexer.mll | 0 src/{ => aslib}/linkModule.ml | 0 src/{ => aslib}/linkModule.mli | 0 src/{ => aslib}/nameRel.ml | 0 src/{ => aslib}/operator.ml | 0 src/{ => aslib}/operator.mli | 0 src/{ => aslib}/parser.mly | 0 src/{ => aslib}/pipeline.ml | 0 src/{ => aslib}/pipeline.mli | 0 src/{ => aslib}/prelude.ml | 0 src/{ => aslib}/prelude.mli | 0 src/{ => aslib}/rename.ml | 0 src/{ => aslib}/resolve_import.ml | 0 src/{ => aslib}/resolve_import.mli | 0 src/{ => aslib}/serialization.ml | 0 src/{ => aslib}/serialization.mli | 0 src/{ => aslib}/show.ml | 0 src/{ => aslib}/show.mli | 0 {idl => src/aslib}/source.ml | 0 {idl => src/aslib}/source.mli | 0 src/{ => aslib}/static.ml | 0 src/{ => aslib}/static.mli | 0 src/{ => aslib}/syntax.ml | 0 src/{ => aslib}/tailcall.ml | 0 src/{ => aslib}/tailcall.mli | 0 src/{ => aslib}/type.ml | 4 +- src/{ => aslib}/type.mli | 0 src/{ => aslib}/typing.ml | 0 src/{ => aslib}/typing.mli | 0 src/{ => aslib}/value.ml | 0 src/{ => aslib}/value.mli | 0 src/dune | 5 + src/dune-project | 2 + src/{js_main.ml => exes/as_js.ml} | 1 + src/{ld_main.ml => exes/as_ld.ml} | 1 + src/{main.ml => exes/asc.ml} | 2 + idl/main.mli => src/exes/asc.mli | 0 idl/main.ml => src/exes/didc.ml | 7 +- src/{main.mli => exes/didc.mli} | 0 src/exes/dune | 23 ++ {idl => src/idllib}/arrange_idl.ml | 0 {idl => src/idllib}/compile_js.ml | 0 {idl => src/idllib}/diag.ml | 0 {idl => src/idllib}/diag.mli | 0 src/{ => idllib}/dom.ml | 0 src/idllib/dune | 10 + {idl => src/idllib}/env_idl.ml | 0 {idl => src/idllib}/flags.ml | 0 {idl => src/idllib}/lexer.mli | 0 {idl => src/idllib}/lexer.mll | 2 +- {idl => src/idllib}/parser.mly | 2 +- {idl => src/idllib}/pipeline.ml | 0 {idl => src/idllib}/pipeline.mli | 0 src/{ => idllib}/source.ml | 0 src/{ => idllib}/source.mli | 0 {idl => src/idllib}/syntax_idl.ml | 0 {idl => src/idllib}/typing_idl.ml | 8 +- {idl => src/idllib}/typing_idl.mli | 0 src/lib/dune | 4 + src/{ => lib}/lib.ml | 0 src/{ => lib}/lib.mli | 0 src/myocamlbuild.ml | 2 - src/wasm_eval.ml | 293 ------------------------- src/wasm_eval.mli | 7 - test/run.sh | 5 +- 117 files changed, 256 insertions(+), 625 deletions(-) create mode 100644 Building.md delete mode 100644 idl/Makefile delete mode 100644 idl/myocamlbuild.ml delete mode 100644 src/.merlin create mode 100644 src/Structure.md delete mode 100644 src/_tags rename src/{ => aslib}/arrange.ml (100%) rename src/{ => aslib}/arrange_ir.ml (100%) rename src/{ => aslib}/arrange_type.ml (100%) rename src/{ => aslib}/async.ml (100%) rename src/{ => aslib}/async.mli (100%) rename src/{ => aslib}/await.ml (100%) rename src/{ => aslib}/await.mli (100%) rename src/{ => aslib}/check_ir.ml (100%) rename src/{ => aslib}/check_ir.mli (100%) rename src/{ => aslib}/compile.ml (100%) rename src/{ => aslib}/compile.mli (100%) rename src/{ => aslib}/con.ml (100%) rename src/{ => aslib}/con.mli (100%) rename src/{ => aslib}/construct.ml (100%) rename src/{ => aslib}/construct.mli (100%) rename src/{ => aslib}/coverage.ml (100%) rename src/{ => aslib}/coverage.mli (100%) rename src/{ => aslib}/customModule.ml (100%) rename src/{ => aslib}/customModuleDecode.ml (100%) rename src/{ => aslib}/customModuleDecode.mli (100%) rename src/{ => aslib}/customModuleEncode.ml (100%) rename src/{ => aslib}/customModuleEncode.mli (100%) rename src/{ => aslib}/definedness.ml (100%) rename src/{ => aslib}/definedness.mli (100%) rename src/{ => aslib}/desugar.ml (100%) rename src/{ => aslib}/desugar.mli (100%) rename src/{ => aslib}/diag.ml (100%) rename src/{ => aslib}/diag.mli (100%) rename {idl => src/aslib}/dom.ml (100%) create mode 100644 src/aslib/dune rename src/{ => aslib}/effect.ml (100%) rename src/{ => aslib}/effect.mli (100%) rename src/{ => aslib}/env.ml (100%) rename src/{ => aslib}/flags.ml (100%) rename src/{ => aslib}/freevars.ml (100%) rename src/{ => aslib}/instrList.ml (100%) rename src/{ => aslib}/interpret.ml (100%) rename src/{ => aslib}/interpret.mli (100%) rename src/{ => aslib}/interpret_ir.ml (100%) rename src/{ => aslib}/interpret_ir.mli (100%) rename src/{ => aslib}/ir.ml (100%) rename src/{ => aslib}/lexer.mli (100%) rename src/{ => aslib}/lexer.mll (100%) rename src/{ => aslib}/linkModule.ml (100%) rename src/{ => aslib}/linkModule.mli (100%) rename src/{ => aslib}/nameRel.ml (100%) rename src/{ => aslib}/operator.ml (100%) rename src/{ => aslib}/operator.mli (100%) rename src/{ => aslib}/parser.mly (100%) rename src/{ => aslib}/pipeline.ml (100%) rename src/{ => aslib}/pipeline.mli (100%) rename src/{ => aslib}/prelude.ml (100%) rename src/{ => aslib}/prelude.mli (100%) rename src/{ => aslib}/rename.ml (100%) rename src/{ => aslib}/resolve_import.ml (100%) rename src/{ => aslib}/resolve_import.mli (100%) rename src/{ => aslib}/serialization.ml (100%) rename src/{ => aslib}/serialization.mli (100%) rename src/{ => aslib}/show.ml (100%) rename src/{ => aslib}/show.mli (100%) rename {idl => src/aslib}/source.ml (100%) rename {idl => src/aslib}/source.mli (100%) rename src/{ => aslib}/static.ml (100%) rename src/{ => aslib}/static.mli (100%) rename src/{ => aslib}/syntax.ml (100%) rename src/{ => aslib}/tailcall.ml (100%) rename src/{ => aslib}/tailcall.mli (100%) rename src/{ => aslib}/type.ml (99%) rename src/{ => aslib}/type.mli (100%) rename src/{ => aslib}/typing.ml (100%) rename src/{ => aslib}/typing.mli (100%) rename src/{ => aslib}/value.ml (100%) rename src/{ => aslib}/value.mli (100%) create mode 100644 src/dune create mode 100644 src/dune-project rename src/{js_main.ml => exes/as_js.ml} (99%) rename src/{ld_main.ml => exes/as_ld.ml} (99%) rename src/{main.ml => exes/asc.ml} (99%) rename idl/main.mli => src/exes/asc.mli (100%) rename idl/main.ml => src/exes/didc.ml (95%) rename src/{main.mli => exes/didc.mli} (100%) create mode 100644 src/exes/dune rename {idl => src/idllib}/arrange_idl.ml (100%) rename {idl => src/idllib}/compile_js.ml (100%) rename {idl => src/idllib}/diag.ml (100%) rename {idl => src/idllib}/diag.mli (100%) rename src/{ => idllib}/dom.ml (100%) create mode 100644 src/idllib/dune rename {idl => src/idllib}/env_idl.ml (100%) rename {idl => src/idllib}/flags.ml (100%) rename {idl => src/idllib}/lexer.mli (100%) rename {idl => src/idllib}/lexer.mll (99%) rename {idl => src/idllib}/parser.mly (98%) rename {idl => src/idllib}/pipeline.ml (100%) rename {idl => src/idllib}/pipeline.mli (100%) rename src/{ => idllib}/source.ml (100%) rename src/{ => idllib}/source.mli (100%) rename {idl => src/idllib}/syntax_idl.ml (100%) rename {idl => src/idllib}/typing_idl.ml (98%) rename {idl => src/idllib}/typing_idl.mli (100%) create mode 100644 src/lib/dune rename src/{ => lib}/lib.ml (100%) rename src/{ => lib}/lib.mli (100%) delete mode 100644 src/myocamlbuild.ml delete mode 100644 src/wasm_eval.ml delete mode 100644 src/wasm_eval.mli diff --git a/Building.md b/Building.md new file mode 100644 index 00000000000..fd405451de5 --- /dev/null +++ b/Building.md @@ -0,0 +1,85 @@ +## Installation using Nix + +To install the `asc` binary into your nix environment, use + +``` +$ nix-env -i -f . -A asc +``` + +## Development using Nix + +This is the command that should always pass on master is the following, which builds everything: +``` +$ nix-build +``` + +To enter a shell with the necessary dependencies, you can use +``` +$ nix-shell +``` +within this shell you can run + * `make asc` in `src/` to build the `asc` binary, + * `make` in `rts/` to build the ActorScript runtime + * `make` in `test/` to run the test suite. + +This invokes `dune` under the hood, which will, as a side effect, also create +`.merlin` files for Merlin integration. + +## Development without Nix + +You can get a development environment that is independent of nix (although +installing all required tools without nix is out of scope). + + * Use your system’s package manager to install `ocaml` and + [`opam`](https://opam.ocaml.org/doc/Install.html) + * Install the packages: + ``` + opam install num vlq yojson menhir + ``` + * Install the `wasm` Ocaml package. We use a newer version than is on opam, and a + fork that supports the multi-value extension. See `nix/ocaml-wasm.nix` for + the precise repository and version. You can use `nix` to fetch the correct + source for you, and run the manual installation inside: + ``` + cd $(nix-build -Q -A wasm.src)/interpreter + make install + ``` + * Install various command line tools used by, in particuar, the test suite: + ``` + nix-env -i -f . -A wasm + nix-env -i -f . -A filecheck + nix-env -i -f . -A wabt + nix-env -i -f . -A dvm + ``` + * Building the ActorScript runtime without nix is tricky. But you can run + ``` + nix-shell --run 'make -C rts' + ``` + to get `rts/as-rts.wasm`. + + +## Create a coverage report + +The coverage report support got dropped when switching to `dune`. Please monitor +https://github.com/ocaml/dune/issues/57 to see when a coverage report is viable again. + +## Profile the compiler + +1. Build with profiling (TODO: How to do with dune) + ``` + make -C src clean + make BUILD=p.native -C src asc + ``` +2. Run `asc` as normal, e.g. + ``` + ./src/asc -c foo.as -o foo.wasm + ``` + this should dump a `gmon.out` file in the current directory. +3. Create the report, e.g. using + ``` + gprof --graph src/asc + ``` + (Note that you have to _run_ this in the directory with `gmon.out`, but + _pass_ it the path to the binary.) + + diff --git a/README.md b/README.md index e5477c84fa8..3c548cba4a2 100644 --- a/README.md +++ b/README.md @@ -2,110 +2,6 @@ A simple language for writing Dfinity actors. - -## Installation using Nix - -To install the `asc` binary into your nix environment, use - -``` -$ nix-env -i -f . -A asc -``` - -## Development using Nix - -This is the command that should always pass on master is the following, which builds everything: -``` -$ nix-build -``` - -To enter a shell with the necessary dependencies, you can use -``` -$ nix-shell -``` -within this shell you can run - * `make asc` in `src/` to build the `asc` binary, - * `make` in `rts/` to build the ActorScript runtime - * `make` in `test/` to run the test suite. - -### Merlin - -> For Merlin to be able to give you the type of identifiers or to offer completion from other file of your projects, it needs to know where to find the cmi files of the other modules of your project. - -To do this, run `make -C src asc` within a nix shell. - -## Development without Nix - -You can get a development environment that is independent of nix (although -installing all required tools without nix is out of scope). - - * Use your system’s package manager to install `ocaml` and - [`opam`](https://opam.ocaml.org/doc/Install.html) - * Install the packages listed as `OPAM_PACKAGES` in `src/Makefile`: - ``` - opam install num vlq yojson bisect_ppx bisect_ppx-ocamlbuild menhir - ``` - * Install the `wasm` Ocaml package. We use a newer version than is on opam, and a - fork that supports the multi-value extension. See `nix/ocaml-wasm.nix` for - the precise repository and version. You can use `nix` to fetch the correct - source for you, and run the manual installation inside: - ``` - cd $(nix-build -Q -A wasm.src)/interpreter - make install - ``` - * Install various command line tools used by, in particuar, the test suite: - ``` - nix-env -i -f . -A wasm - nix-env -i -f . -A filecheck - nix-env -i -f . -A wabt - nix-env -i -f . -A dvm - ``` - * Building the ActorScript runtime without nix is tricky. But you can run - ``` - nix-shell --run 'make -C rts' - ``` - to get `rts/as-rts.wasm`. - - -## Create a coverage report - -Three ways of obtaining the coverage report: - - * Run - ``` - BISECT_COVERAGE=YES make -C src asc - make -C test coverage - ``` - and open `test/coverage/index.html` in the browser. - - * Alternatively, you can run - ``` - nix-build -A coverage-report - ``` - and open the path printed on the last line of that command. - * On the VPN, simply go to - - for the report for the latest version on `master`. - -## Profile the compiler - -1. Build with profiling - ``` - make -C src clean - make BUILD=p.native -C src asc - ``` -2. Run `asc` as normal, e.g. - ``` - ./src/asc -c foo.as -o foo.wasm - ``` - this should dump a `gmon.out` file in the current directory. -3. Create the report, e.g. using - ``` - gprof --graph src/asc - ``` - (Note that you have to _run_ this in the directory with `gmon.out`, but - _pass_ it the path to the binary.) - - ## Introduction ### Motivation and Goals diff --git a/default.nix b/default.nix index e8a662724da..73c29a0edeb 100644 --- a/default.nix +++ b/default.nix @@ -47,9 +47,9 @@ let real-dvm = let commonBuildInputs = [ nixpkgs.ocaml - nixpkgs.ocamlPackages.menhir + nixpkgs.dune nixpkgs.ocamlPackages.findlib - nixpkgs.ocamlPackages.ocamlbuild + nixpkgs.ocamlPackages.menhir nixpkgs.ocamlPackages.num nixpkgs.ocamlPackages.stdint ocaml_wasm @@ -58,6 +58,8 @@ let commonBuildInputs = [ nixpkgs.ocamlPackages.yojson ocaml_bisect_ppx ocaml_bisect_ppx-ocamlbuild + nixpkgs.ocamlPackages.ocaml-migrate-parsetree + nixpkgs.ocamlPackages.ppx_tools_versioned ]; in let @@ -147,25 +149,25 @@ rec { name = "asc-bin"; src = sourceByRegex ./src [ - "Makefile.*" + "Makefile" + "dune-project" + "dune" + "[a-z].*/" ".*.ml" - ".*.mli" ".*.mly" ".*.mll" - ".*.mlpack" - "_tags" + ".*/dune" ]; buildInputs = commonBuildInputs; buildPhase = '' - make BUILD=native asc as-ld + make DUNE_OPTS="--display=short --profile release" asc as-ld ''; installPhase = '' mkdir -p $out/bin - cp asc $out/bin - cp as-ld $out/bin + cp --verbose --dereference asc as-ld $out/bin ''; }; @@ -219,64 +221,6 @@ rec { ''; }; - asc-bin-coverage = asc-bin.overrideAttrs (oldAttrs: { - name = "asc-bin-coverage"; - buildPhase = - "export BISECT_COVERAGE=YES;" + - oldAttrs.buildPhase; - installPhase = - oldAttrs.installPhase + '' - # The coverage report needs access to sources, including _build/parser.ml - cp -r . $out/src - ''; - }); - - asc-coverage = nixpkgs.symlinkJoin { - name = "asc-covergage"; - paths = [ asc-bin-coverage rts ]; - buildInputs = [ nixpkgs.makeWrapper ]; - postBuild = '' - wrapProgram $out/bin/asc \ - --set-default ASC_RTS "$out/rts/as-rts.wasm" - ''; - }; - - coverage-report = stdenv.mkDerivation { - name = "coverage-report"; - - src = sourceByRegex ./. ( - test_files ++ - samples_files - ); - - buildInputs = - [ asc-coverage - nixpkgs.wabt - nixpkgs.bash - nixpkgs.perl - ocaml_bisect_ppx - ] ++ - (if test-dvm then [ real-dvm ] else []) ++ - llvmBuildInputs; - - buildPhase = '' - patchShebangs . - ${llvmEnv} - export ASC=asc - export AS_LD=as-ld - ln -vs ${asc-coverage}/src src - make -C test coverage - ''; - - installPhase = '' - mkdir -p $out - mv test/coverage/ $out/ - mkdir -p $out/nix-support - echo "report coverage $out/coverage index.html" >> $out/nix-support/hydra-build-products - ''; - }; - - js = asc-bin.overrideAttrs (oldAttrs: { name = "asc.js"; @@ -308,25 +252,26 @@ rec { didc = stdenv.mkDerivation { name = "didc"; - src = sourceByRegex ./idl [ - "Makefile.*" + src = sourceByRegex ./src [ + "Makefile" + "dune-project" + "dune" + "[a-z].*/" ".*.ml" - ".*.mli" ".*.mly" ".*.mll" - ".*.mlpack" - "_tags" + ".*/dune" ]; buildInputs = commonBuildInputs; buildPhase = '' - make BUILD=native didc + make DUNE_OPTS="--display=short --profile release" didc ''; installPhase = '' mkdir -p $out/bin - cp didc $out/bin + cp --verbose --dereference didc $out/bin ''; }; @@ -432,7 +377,6 @@ rec { js didc tests - coverage-report rts stdlib-reference produce-exchange @@ -441,18 +385,16 @@ rec { }; shell = if export-shell then nixpkgs.mkShell { - - # - # Since building asc, and testing it, are two different derivation in default.nix - # we have to create a fake derivation for shell.nix that commons up the build dependencies - # of the two to provide a build environment that offers both # - # Would not be necessary if nix-shell would take more than one `-A` flag, see - # https://github.com/NixOS/nix/issues/955 + # Since building asc, and testing it, are two different derivations in we + # have to create a fake derivation for `nix-shell` that commons up the + # build dependencies of the two to provide a build environment that offers + # both. # buildInputs = nixpkgs.lib.lists.unique (builtins.filter (i: i != asc && i != didc) ( asc-bin.buildInputs ++ + js.buildInputs ++ rts.buildInputs ++ didc.buildInputs ++ tests.buildInputs ++ diff --git a/idl/Makefile b/idl/Makefile deleted file mode 100644 index b945f6daee4..00000000000 --- a/idl/Makefile +++ /dev/null @@ -1,36 +0,0 @@ -NAME = didc -BUILD = byte -MAIN = main - -DIDC = `pwd`/$(NAME) - -OPAM_PACKAGES = wasm stdint num vlq yojson - -MENHIR = menhir -MENHIR_FLAGS = --infer --dump --explain - -OCAML_FLAGS = -cflags '-w +a-4-27-30-42-44-45-58 -warn-error +a' -OCAML_FLAGS = -cflags '-w' -OCAMLBUILD = ocamlbuild $(OCAML_FLAGS) \ - -use-ocamlfind \ - -use-menhir -menhir "$(MENHIR) $(MENHIR_FLAGS)" \ - $(OPAM_PACKAGES:%=-pkg %) \ - -tags debug - -$(NAME): $(MAIN).$(BUILD) - mv $< $@ - -$(MAIN).$(BUILD): sanity - $(OCAMLBUILD) $@ - -sanity: - ocamlfind query $(OPAM_PACKAGES) - -clean: - rm -f *~ .*~ - $(OCAMLBUILD) -clean - $(MAKE) -C ../test/idl clean - -test: $(NAME) - $(MAKE) -C ../test/idl DIDC=$(DIDC) all - diff --git a/idl/myocamlbuild.ml b/idl/myocamlbuild.ml deleted file mode 100644 index 8b3cccefcf3..00000000000 --- a/idl/myocamlbuild.ml +++ /dev/null @@ -1,14 +0,0 @@ -open Ocamlbuild_plugin - -let ocamlfind_query pkg = - let cmd = Printf.sprintf "ocamlfind query %s" (Filename.quote pkg) in - Ocamlbuild_pack.My_unix.run_and_open cmd (fun ic -> - Printf.printf "Getting ocaml directory from command %s\n" cmd; - input_line ic - ) - -let () = dispatch begin function - | After_rules -> () - (* ocaml_lib ~extern:true ~dir:(ocamlfind_query "js_of_ocaml-compiler") "js_of_ocaml_compiler";*) - | _ -> () - end diff --git a/src/.gitignore b/src/.gitignore index d82f8742dc3..f29f5bb05c3 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -1,11 +1,8 @@ -*.cmo -*.cmx -*.native -*.byte -*.opt -*.unopt -*.mlpack -as -asc -asc.js -as-ld +# generated by Makefile +/asc +/as-ld +/asc.js +/didc + +# generated by dune +.merlin diff --git a/src/.merlin b/src/.merlin deleted file mode 100644 index ec0c288f348..00000000000 --- a/src/.merlin +++ /dev/null @@ -1,3 +0,0 @@ -B _build -PKG wasm num vlq yojson -FLG -w +a-4-27-30-42-44-45 diff --git a/src/Makefile b/src/Makefile index 5b798dc2515..93ae13c4d3b 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,67 +1,43 @@ -NAME = asc -BUILD = byte -MAIN = main -JS_MAIN = js_main +# This Makefile is not really a +# dependency tracking makefile, it just +# calls `dune` -ASC = `pwd`/$(NAME) +AS_LD_TARGET = _build/default/exes/as_ld.exe +ASC_TARGET = _build/default/exes/asc.exe +DIDC_TARGET = _build/default/exes/didc.exe +ASC_JS_TARGET = _build/default/exes/as_js.bc.js -OPAM_PACKAGES = wasm num vlq yojson bisect_ppx-ocamlbuild -JS_OPAM_PACKAGES = js_of_ocaml js_of_ocaml-ppx +DUNE_OPTS ?= -MENHIR = menhir -MENHIR_FLAGS = --infer --dump --explain --strict +ALL_TARGETS = $(AS_LD_TARGET) $(ASC_TARGET) $(ASC_JS_TARGET) $(DIDC_TARGET) -OCAML_FLAGS = -cflags '-w +a-4-27-30-42-44-45-58 -warn-error +a' -OCAMLBUILD = ocamlbuild $(OCAML_FLAGS) \ - -use-ocamlfind \ - -plugin-tag 'package(bisect_ppx-ocamlbuild)' \ - -use-menhir -menhir "$(MENHIR) $(MENHIR_FLAGS)" \ - -I src \ - -I lib \ - $(OPAM_PACKAGES:%=-pkg %) \ - -tags debug +.PHONY: all clean asc as-ld asc.js didc -.PHONY: all parallel quick clean test test-parallel test-quick +# This targets is spelled out so that `make` +# only invokes `dune` once, much faster +all: + dune build $(DUNE_OPTS) $(ALL_TARGETS) + @ln -fs $(ASC_TARGET) asc + @ln -fs $(AS_LD_TARGET) as-ld + @ln -fs $(ASC_JS_TARGET) asc.js + @ln -fs $(DIDC_TARGET) didc -all: $(NAME) as-ld test +asc: + dune build $(DUNE_OPTS) $(ASC_TARGET) + @ln -fs $(ASC_TARGET) asc -parallel: $(NAME) test-parallel -quick: $(NAME) test-quick +as-ld: + dune build $(DUNE_OPTS) $(AS_LD_TARGET) + @ln -fs $(AS_LD_TARGET) as-ld -$(NAME): $(MAIN).$(BUILD) - mv $< $@ +asc.js: + dune build $(DUNE_OPTS) $(ASC_JS_TARGET) + @ln -fs $(ASC_JS_TARGET) asc.js -as-ld: ld_main.$(BUILD) - mv $< $@ - -$(NAME).js: $(JS_MAIN).byte - js_of_ocaml +nat.js $< -o $@ - -%.$(BUILD): sanity - $(OCAMLBUILD) $@ - -$(JS_MAIN).byte: $(JS_MAIN).ml sanity - $(OCAMLBUILD) $(JS_OPAM_PACKAGES:%=-pkg %) $@ - - -sanity: - ocamlfind query $(OPAM_PACKAGES) +didc: + dune build $(DUNE_OPTS) $(DIDC_TARGET) + @ln -fs $(DIDC_TARGET) didc clean: - rm -f *~ .*~ - $(OCAMLBUILD) -clean - $(MAKE) -C ../test clean - -test: $(NAME) - $(MAKE) -C ../stdlib ASC=$(ASC) all - $(MAKE) -C ../test ASC=$(ASC) all - $(MAKE) -C ../samples ASC=$(ASC) all - -accept: $(NAME) - $(MAKE) -C ../test ASC=$(ASC) accept - -test-parallel: $(NAME) - $(MAKE) -C ../test ASC=$(ASC) parallel - -test-quick: $(NAME) - $(MAKE) -C ../test ASC=$(ASC) quick + rm -f asc as-ld asc.js didc + dune clean diff --git a/src/Structure.md b/src/Structure.md new file mode 100644 index 00000000000..12a11d0e3da --- /dev/null +++ b/src/Structure.md @@ -0,0 +1,37 @@ +Project file structure +====================== + +Since we switched to `dune`, we are organizing the Ocaml source in libraries +and executables. + +Every library is a subdirectory of `src/`, contains a `dune` file that +indicates its name and other library dependencies. All `.ml` files in that +directory are part of the library. + +Within a library `lib`, modules are accessed using `Foo`; outside via +`Lib.Foo`. Unless there is `lib/libml`, then this is the entry point. + +Executables +--------- + +All exectuables are in the directory `exe/`, and should be kept rather small; +essentially only the command line parsing should be there, so that +actual functionality is easily shared. + + +Libraries +--------- + +We split the files into the following subdirectories + + * `lib/` + + Stuff that could be in the Ocaml standard library. + + * `aslib/` + + Kitchen-sink of `asc` and `as-ld` related files. Will be split soon. + + * `idllib/` + + Kitchen-sink of `didc` related files. Will likely be split soon. diff --git a/src/_tags b/src/_tags deleted file mode 100644 index b8a23322447..00000000000 --- a/src/_tags +++ /dev/null @@ -1 +0,0 @@ -<**/*>: coverage diff --git a/src/arrange.ml b/src/aslib/arrange.ml similarity index 100% rename from src/arrange.ml rename to src/aslib/arrange.ml diff --git a/src/arrange_ir.ml b/src/aslib/arrange_ir.ml similarity index 100% rename from src/arrange_ir.ml rename to src/aslib/arrange_ir.ml diff --git a/src/arrange_type.ml b/src/aslib/arrange_type.ml similarity index 100% rename from src/arrange_type.ml rename to src/aslib/arrange_type.ml diff --git a/src/async.ml b/src/aslib/async.ml similarity index 100% rename from src/async.ml rename to src/aslib/async.ml diff --git a/src/async.mli b/src/aslib/async.mli similarity index 100% rename from src/async.mli rename to src/aslib/async.mli diff --git a/src/await.ml b/src/aslib/await.ml similarity index 100% rename from src/await.ml rename to src/aslib/await.ml diff --git a/src/await.mli b/src/aslib/await.mli similarity index 100% rename from src/await.mli rename to src/aslib/await.mli diff --git a/src/check_ir.ml b/src/aslib/check_ir.ml similarity index 100% rename from src/check_ir.ml rename to src/aslib/check_ir.ml diff --git a/src/check_ir.mli b/src/aslib/check_ir.mli similarity index 100% rename from src/check_ir.mli rename to src/aslib/check_ir.mli diff --git a/src/compile.ml b/src/aslib/compile.ml similarity index 100% rename from src/compile.ml rename to src/aslib/compile.ml diff --git a/src/compile.mli b/src/aslib/compile.mli similarity index 100% rename from src/compile.mli rename to src/aslib/compile.mli diff --git a/src/con.ml b/src/aslib/con.ml similarity index 100% rename from src/con.ml rename to src/aslib/con.ml diff --git a/src/con.mli b/src/aslib/con.mli similarity index 100% rename from src/con.mli rename to src/aslib/con.mli diff --git a/src/construct.ml b/src/aslib/construct.ml similarity index 100% rename from src/construct.ml rename to src/aslib/construct.ml diff --git a/src/construct.mli b/src/aslib/construct.mli similarity index 100% rename from src/construct.mli rename to src/aslib/construct.mli diff --git a/src/coverage.ml b/src/aslib/coverage.ml similarity index 100% rename from src/coverage.ml rename to src/aslib/coverage.ml diff --git a/src/coverage.mli b/src/aslib/coverage.mli similarity index 100% rename from src/coverage.mli rename to src/aslib/coverage.mli diff --git a/src/customModule.ml b/src/aslib/customModule.ml similarity index 100% rename from src/customModule.ml rename to src/aslib/customModule.ml diff --git a/src/customModuleDecode.ml b/src/aslib/customModuleDecode.ml similarity index 100% rename from src/customModuleDecode.ml rename to src/aslib/customModuleDecode.ml diff --git a/src/customModuleDecode.mli b/src/aslib/customModuleDecode.mli similarity index 100% rename from src/customModuleDecode.mli rename to src/aslib/customModuleDecode.mli diff --git a/src/customModuleEncode.ml b/src/aslib/customModuleEncode.ml similarity index 100% rename from src/customModuleEncode.ml rename to src/aslib/customModuleEncode.ml diff --git a/src/customModuleEncode.mli b/src/aslib/customModuleEncode.mli similarity index 100% rename from src/customModuleEncode.mli rename to src/aslib/customModuleEncode.mli diff --git a/src/definedness.ml b/src/aslib/definedness.ml similarity index 100% rename from src/definedness.ml rename to src/aslib/definedness.ml diff --git a/src/definedness.mli b/src/aslib/definedness.mli similarity index 100% rename from src/definedness.mli rename to src/aslib/definedness.mli diff --git a/src/desugar.ml b/src/aslib/desugar.ml similarity index 100% rename from src/desugar.ml rename to src/aslib/desugar.ml diff --git a/src/desugar.mli b/src/aslib/desugar.mli similarity index 100% rename from src/desugar.mli rename to src/aslib/desugar.mli diff --git a/src/diag.ml b/src/aslib/diag.ml similarity index 100% rename from src/diag.ml rename to src/aslib/diag.ml diff --git a/src/diag.mli b/src/aslib/diag.mli similarity index 100% rename from src/diag.mli rename to src/aslib/diag.mli diff --git a/idl/dom.ml b/src/aslib/dom.ml similarity index 100% rename from idl/dom.ml rename to src/aslib/dom.ml diff --git a/src/aslib/dune b/src/aslib/dune new file mode 100644 index 00000000000..ee1f37f92fa --- /dev/null +++ b/src/aslib/dune @@ -0,0 +1,10 @@ +(library + (name aslib) + (libraries wasm num vlq yojson lib) +) + +(menhir + (modules parser) + (infer false) +) +(ocamllex lexer) diff --git a/src/effect.ml b/src/aslib/effect.ml similarity index 100% rename from src/effect.ml rename to src/aslib/effect.ml diff --git a/src/effect.mli b/src/aslib/effect.mli similarity index 100% rename from src/effect.mli rename to src/aslib/effect.mli diff --git a/src/env.ml b/src/aslib/env.ml similarity index 100% rename from src/env.ml rename to src/aslib/env.ml diff --git a/src/flags.ml b/src/aslib/flags.ml similarity index 100% rename from src/flags.ml rename to src/aslib/flags.ml diff --git a/src/freevars.ml b/src/aslib/freevars.ml similarity index 100% rename from src/freevars.ml rename to src/aslib/freevars.ml diff --git a/src/instrList.ml b/src/aslib/instrList.ml similarity index 100% rename from src/instrList.ml rename to src/aslib/instrList.ml diff --git a/src/interpret.ml b/src/aslib/interpret.ml similarity index 100% rename from src/interpret.ml rename to src/aslib/interpret.ml diff --git a/src/interpret.mli b/src/aslib/interpret.mli similarity index 100% rename from src/interpret.mli rename to src/aslib/interpret.mli diff --git a/src/interpret_ir.ml b/src/aslib/interpret_ir.ml similarity index 100% rename from src/interpret_ir.ml rename to src/aslib/interpret_ir.ml diff --git a/src/interpret_ir.mli b/src/aslib/interpret_ir.mli similarity index 100% rename from src/interpret_ir.mli rename to src/aslib/interpret_ir.mli diff --git a/src/ir.ml b/src/aslib/ir.ml similarity index 100% rename from src/ir.ml rename to src/aslib/ir.ml diff --git a/src/lexer.mli b/src/aslib/lexer.mli similarity index 100% rename from src/lexer.mli rename to src/aslib/lexer.mli diff --git a/src/lexer.mll b/src/aslib/lexer.mll similarity index 100% rename from src/lexer.mll rename to src/aslib/lexer.mll diff --git a/src/linkModule.ml b/src/aslib/linkModule.ml similarity index 100% rename from src/linkModule.ml rename to src/aslib/linkModule.ml diff --git a/src/linkModule.mli b/src/aslib/linkModule.mli similarity index 100% rename from src/linkModule.mli rename to src/aslib/linkModule.mli diff --git a/src/nameRel.ml b/src/aslib/nameRel.ml similarity index 100% rename from src/nameRel.ml rename to src/aslib/nameRel.ml diff --git a/src/operator.ml b/src/aslib/operator.ml similarity index 100% rename from src/operator.ml rename to src/aslib/operator.ml diff --git a/src/operator.mli b/src/aslib/operator.mli similarity index 100% rename from src/operator.mli rename to src/aslib/operator.mli diff --git a/src/parser.mly b/src/aslib/parser.mly similarity index 100% rename from src/parser.mly rename to src/aslib/parser.mly diff --git a/src/pipeline.ml b/src/aslib/pipeline.ml similarity index 100% rename from src/pipeline.ml rename to src/aslib/pipeline.ml diff --git a/src/pipeline.mli b/src/aslib/pipeline.mli similarity index 100% rename from src/pipeline.mli rename to src/aslib/pipeline.mli diff --git a/src/prelude.ml b/src/aslib/prelude.ml similarity index 100% rename from src/prelude.ml rename to src/aslib/prelude.ml diff --git a/src/prelude.mli b/src/aslib/prelude.mli similarity index 100% rename from src/prelude.mli rename to src/aslib/prelude.mli diff --git a/src/rename.ml b/src/aslib/rename.ml similarity index 100% rename from src/rename.ml rename to src/aslib/rename.ml diff --git a/src/resolve_import.ml b/src/aslib/resolve_import.ml similarity index 100% rename from src/resolve_import.ml rename to src/aslib/resolve_import.ml diff --git a/src/resolve_import.mli b/src/aslib/resolve_import.mli similarity index 100% rename from src/resolve_import.mli rename to src/aslib/resolve_import.mli diff --git a/src/serialization.ml b/src/aslib/serialization.ml similarity index 100% rename from src/serialization.ml rename to src/aslib/serialization.ml diff --git a/src/serialization.mli b/src/aslib/serialization.mli similarity index 100% rename from src/serialization.mli rename to src/aslib/serialization.mli diff --git a/src/show.ml b/src/aslib/show.ml similarity index 100% rename from src/show.ml rename to src/aslib/show.ml diff --git a/src/show.mli b/src/aslib/show.mli similarity index 100% rename from src/show.mli rename to src/aslib/show.mli diff --git a/idl/source.ml b/src/aslib/source.ml similarity index 100% rename from idl/source.ml rename to src/aslib/source.ml diff --git a/idl/source.mli b/src/aslib/source.mli similarity index 100% rename from idl/source.mli rename to src/aslib/source.mli diff --git a/src/static.ml b/src/aslib/static.ml similarity index 100% rename from src/static.ml rename to src/aslib/static.ml diff --git a/src/static.mli b/src/aslib/static.mli similarity index 100% rename from src/static.mli rename to src/aslib/static.mli diff --git a/src/syntax.ml b/src/aslib/syntax.ml similarity index 100% rename from src/syntax.ml rename to src/aslib/syntax.ml diff --git a/src/tailcall.ml b/src/aslib/tailcall.ml similarity index 100% rename from src/tailcall.ml rename to src/aslib/tailcall.ml diff --git a/src/tailcall.mli b/src/aslib/tailcall.mli similarity index 100% rename from src/tailcall.mli rename to src/aslib/tailcall.mli diff --git a/src/type.ml b/src/aslib/type.ml similarity index 99% rename from src/type.ml rename to src/aslib/type.ml index d669c3a5a66..7a880ae8498 100644 --- a/src/type.ml +++ b/src/aslib/type.ml @@ -921,8 +921,8 @@ and string_of_kind k = let op, sbs, st = strings_of_kind k in sprintf "%s %s%s" op sbs st -let string_of_con = string_of_con' [] -let string_of_typ = string_of_typ' [] +let string_of_con : con -> string = string_of_con' [] +let string_of_typ : typ -> string = string_of_typ' [] let rec string_of_typ_expand t = let s = string_of_typ t in diff --git a/src/type.mli b/src/aslib/type.mli similarity index 100% rename from src/type.mli rename to src/aslib/type.mli diff --git a/src/typing.ml b/src/aslib/typing.ml similarity index 100% rename from src/typing.ml rename to src/aslib/typing.ml diff --git a/src/typing.mli b/src/aslib/typing.mli similarity index 100% rename from src/typing.mli rename to src/aslib/typing.mli diff --git a/src/value.ml b/src/aslib/value.ml similarity index 100% rename from src/value.ml rename to src/aslib/value.ml diff --git a/src/value.mli b/src/aslib/value.mli similarity index 100% rename from src/value.mli rename to src/aslib/value.mli diff --git a/src/dune b/src/dune new file mode 100644 index 00000000000..fa38da7d854 --- /dev/null +++ b/src/dune @@ -0,0 +1,5 @@ +(env + (dev (flags "-w" "+a-4-27-30-42-44-45-58")) + (release (flags "-w" "+a-4-27-30-42-44-45-58" "-warn-error" "+a")) +) + diff --git a/src/dune-project b/src/dune-project new file mode 100644 index 00000000000..13109bb9be7 --- /dev/null +++ b/src/dune-project @@ -0,0 +1,2 @@ +(lang dune 1.6) +(using menhir 2.0) diff --git a/src/js_main.ml b/src/exes/as_js.ml similarity index 99% rename from src/js_main.ml rename to src/exes/as_js.ml index 3428f87c613..c159585aab4 100644 --- a/src/js_main.ml +++ b/src/exes/as_js.ml @@ -1,3 +1,4 @@ +open Aslib open Source module Js = Js_of_ocaml.Js diff --git a/src/ld_main.ml b/src/exes/as_ld.ml similarity index 99% rename from src/ld_main.ml rename to src/exes/as_ld.ml index d1d70637e4e..fa46843640b 100644 --- a/src/ld_main.ml +++ b/src/exes/as_ld.ml @@ -1,3 +1,4 @@ +open Aslib open Printf let name = "as-ld" diff --git a/src/main.ml b/src/exes/asc.ml similarity index 99% rename from src/main.ml rename to src/exes/asc.ml index 479b3709fc7..39662d328be 100644 --- a/src/main.ml +++ b/src/exes/asc.ml @@ -1,3 +1,5 @@ +open Aslib + open Printf let name = "asc" diff --git a/idl/main.mli b/src/exes/asc.mli similarity index 100% rename from idl/main.mli rename to src/exes/asc.mli diff --git a/idl/main.ml b/src/exes/didc.ml similarity index 95% rename from idl/main.ml rename to src/exes/didc.ml index c3e59a4e348..75de9694f55 100644 --- a/idl/main.ml +++ b/src/exes/didc.ml @@ -1,6 +1,7 @@ +open Idllib open Printf -let name = "idlc" +let name = "didc" let version = "0.1" let banner = "Interface Description Language (IDL) " ^ version ^ " interpreter" let usage = "Usage: " ^ name ^ " [option] [file ...]" @@ -36,10 +37,6 @@ let argspec = Arg.align (* Main *) -let exit_on_none = function - | Some x -> x - | None -> exit 1 - let exit_on_failure = function | Ok x -> x | Error errs -> diff --git a/src/main.mli b/src/exes/didc.mli similarity index 100% rename from src/main.mli rename to src/exes/didc.mli diff --git a/src/exes/dune b/src/exes/dune new file mode 100644 index 00000000000..402750dce17 --- /dev/null +++ b/src/exes/dune @@ -0,0 +1,23 @@ +(executable + (name asc) + (modules asc) + (libraries aslib) +) +(executable + (name as_ld) + (modules as_ld) + (libraries aslib) +) +(executable + (name didc) + (modules didc) + (libraries idllib) +) +(executable + (name as_js) + (modules as_js) + (libraries aslib) + (preprocess (pps js_of_ocaml-ppx)) + (js_of_ocaml (flags :standard "+nat.js") ) +) + diff --git a/idl/arrange_idl.ml b/src/idllib/arrange_idl.ml similarity index 100% rename from idl/arrange_idl.ml rename to src/idllib/arrange_idl.ml diff --git a/idl/compile_js.ml b/src/idllib/compile_js.ml similarity index 100% rename from idl/compile_js.ml rename to src/idllib/compile_js.ml diff --git a/idl/diag.ml b/src/idllib/diag.ml similarity index 100% rename from idl/diag.ml rename to src/idllib/diag.ml diff --git a/idl/diag.mli b/src/idllib/diag.mli similarity index 100% rename from idl/diag.mli rename to src/idllib/diag.mli diff --git a/src/dom.ml b/src/idllib/dom.ml similarity index 100% rename from src/dom.ml rename to src/idllib/dom.ml diff --git a/src/idllib/dune b/src/idllib/dune new file mode 100644 index 00000000000..88a321df719 --- /dev/null +++ b/src/idllib/dune @@ -0,0 +1,10 @@ +(library + (name idllib) + (libraries wasm stdint) +) + +(menhir + (modules parser) + (infer false) +) +(ocamllex lexer) diff --git a/idl/env_idl.ml b/src/idllib/env_idl.ml similarity index 100% rename from idl/env_idl.ml rename to src/idllib/env_idl.ml diff --git a/idl/flags.ml b/src/idllib/flags.ml similarity index 100% rename from idl/flags.ml rename to src/idllib/flags.ml diff --git a/idl/lexer.mli b/src/idllib/lexer.mli similarity index 100% rename from idl/lexer.mli rename to src/idllib/lexer.mli diff --git a/idl/lexer.mll b/src/idllib/lexer.mll similarity index 99% rename from idl/lexer.mll rename to src/idllib/lexer.mll index a4289f371e5..b1d4eb8fa92 100644 --- a/idl/lexer.mll +++ b/src/idllib/lexer.mll @@ -49,7 +49,7 @@ let codepoint lexbuf s i = int_of_string ("0x" ^ String.make 1 h ^ String.make 1 s.[!i]) in incr i; u -let char lexbuf s = +let _char lexbuf s = codepoint lexbuf s (ref 1) let text lexbuf s = diff --git a/idl/parser.mly b/src/idllib/parser.mly similarity index 98% rename from idl/parser.mly rename to src/idllib/parser.mly index 661f73ee11b..d9558bd06ab 100644 --- a/idl/parser.mly +++ b/src/idllib/parser.mly @@ -20,7 +20,7 @@ let positions_to_region position1 position2 = let at (startpos, endpos) = positions_to_region startpos endpos -let anon sort at = "anon-" ^ sort ^ "-" ^ string_of_pos at.left +let _anon sort at = "anon-" ^ sort ^ "-" ^ string_of_pos at.left let prim_typs = ["nat", Nat; "nat8", Nat8; "nat16", Nat16; "nat32", Nat32; "nat64", Nat64; "int", Int; "int8", Int8; "int16", Int16; "int32", Int32; "int64", Int64; diff --git a/idl/pipeline.ml b/src/idllib/pipeline.ml similarity index 100% rename from idl/pipeline.ml rename to src/idllib/pipeline.ml diff --git a/idl/pipeline.mli b/src/idllib/pipeline.mli similarity index 100% rename from idl/pipeline.mli rename to src/idllib/pipeline.mli diff --git a/src/source.ml b/src/idllib/source.ml similarity index 100% rename from src/source.ml rename to src/idllib/source.ml diff --git a/src/source.mli b/src/idllib/source.mli similarity index 100% rename from src/source.mli rename to src/idllib/source.mli diff --git a/idl/syntax_idl.ml b/src/idllib/syntax_idl.ml similarity index 100% rename from idl/syntax_idl.ml rename to src/idllib/syntax_idl.ml diff --git a/idl/typing_idl.ml b/src/idllib/typing_idl.ml similarity index 98% rename from idl/typing_idl.ml rename to src/idllib/typing_idl.ml index 1d36a3d32ff..5fb05a5bdf7 100644 --- a/idl/typing_idl.ml +++ b/src/idllib/typing_idl.ml @@ -13,8 +13,8 @@ exception Recover let recover_with (x : 'a) (f : 'b -> 'a) (y : 'b) = try f y with Recover -> x let recover_opt f y = recover_with None (fun y -> Some (f y)) y -let recover f y = recover_with () f y - +let _recover f y = recover_with () f y + (* Scopes *) type typ_env = typ Env.t @@ -42,11 +42,11 @@ let env_of_scope msgs scope = let type_error at text : Diag.message = Diag.{sev = Diag.Error; at; cat = "type"; text} let type_warning at text : Diag.message = Diag.{sev = Diag.Warning; at; cat = "type"; text} -let local_error env at fmt = +let _local_error env at fmt = Printf.ksprintf (fun s -> Diag.add_msg env.msgs (type_error at s)) fmt let error env at fmt = Printf.ksprintf (fun s -> Diag.add_msg env.msgs (type_error at s); raise Recover) fmt -let warn env at fmt = +let _warn env at fmt = Printf.ksprintf (fun s -> Diag.add_msg env.msgs (type_warning at s)) fmt (* Context extension *) diff --git a/idl/typing_idl.mli b/src/idllib/typing_idl.mli similarity index 100% rename from idl/typing_idl.mli rename to src/idllib/typing_idl.mli diff --git a/src/lib/dune b/src/lib/dune new file mode 100644 index 00000000000..cd4322f9112 --- /dev/null +++ b/src/lib/dune @@ -0,0 +1,4 @@ +(library + (name lib) + (preprocess (pps bisect_ppx -conditional)) +) diff --git a/src/lib.ml b/src/lib/lib.ml similarity index 100% rename from src/lib.ml rename to src/lib/lib.ml diff --git a/src/lib.mli b/src/lib/lib.mli similarity index 100% rename from src/lib.mli rename to src/lib/lib.mli diff --git a/src/myocamlbuild.ml b/src/myocamlbuild.ml deleted file mode 100644 index 3d5ad4ee44c..00000000000 --- a/src/myocamlbuild.ml +++ /dev/null @@ -1,2 +0,0 @@ -open Ocamlbuild_plugin -let () = dispatch Bisect_ppx_plugin.dispatch diff --git a/src/wasm_eval.ml b/src/wasm_eval.ml deleted file mode 100644 index 7631db7cdce..00000000000 --- a/src/wasm_eval.ml +++ /dev/null @@ -1,293 +0,0 @@ -open Wasm -open Values -open Types -open Instance -open Ast -open Source - - -(* Errors *) - -exception Trap of Source.region * string -exception Crash of Source.region * string - -let trap at fmt = Printf.ksprintf (fun s -> raise (Trap (at, s))) fmt -let crash at fmt = Printf.ksprintf (fun s -> raise (Crash (at, s))) fmt - -let memory_error at = function - | Memory.Bounds -> "out of bounds memory access" - | Memory.SizeOverflow -> "memory size overflow" - | Memory.SizeLimit -> "memory size limit reached" - | Memory.Type -> crash at "type mismatch at memory access" - | exn -> raise exn - -let numeric_error at = function - | Numeric_error.IntegerOverflow -> "integer overflow" - | Numeric_error.IntegerDivideByZero -> "integer divide by zero" - | Numeric_error.InvalidConversionToInteger -> "invalid conversion to integer" - | Eval_numeric.TypeError (i, v, t) -> - crash at "type error, expected %s as operand %d, got %s" - (Types.string_of_value_type t) i - (Types.string_of_value_type (type_of v)) - | exn -> raise exn - - -(* Configurations *) - -type 'a stack = 'a list (* reversed *) -type label = {branch : 'a. value stack -> Source.region -> 'a} - -type frame = -{ - inst : module_inst; - locals : value ref list; -} - -type config = -{ - frame : frame; - labels : label list; - return : label; - steps : int ref; -} - -let return = {branch = fun _ _ -> crash no_region "misplaced return"} - -let frame inst locals = {inst; locals} -let config inst = {frame = frame inst []; steps = ref 0; labels = []; return} - -let lookup category list x = - try Lib.List32.nth list x.it with Failure _ -> - crash x.at "undefined %s %ld" category x.it - -let type_ (inst : module_inst) x = lookup "type" inst.types x -let func (inst : module_inst) x = lookup "function" inst.funcs x -let table (inst : module_inst) x = lookup "table" inst.tables x -let memory (inst : module_inst) x = lookup "memory" inst.memories x -let global (inst : module_inst) x = lookup "global" inst.globals x -let local (frame : frame) x = lookup "local" frame.locals x -let label (c : config) x = lookup "label" c.labels x - -let elem inst x i at = - match Table.load (table inst x) i with - | Table.Uninitialized -> - trap at "uninitialized element %s" (Int32.to_string i) - | f -> f - | exception Table.Bounds -> - trap at "undefined element %s" (Int32.to_string i) - -let func_elem inst x i at = - match elem inst x i at with - | FuncElem f -> f - | _ -> crash at "type mismatch for element %s" (Int32.to_string i) - -let take n (vs : 'a stack) at = - try Lib.List.take n vs with Failure _ -> crash at "stack underflow" - -let drop n (vs : 'a stack) at = - try Lib.List.drop n vs with Failure _ -> crash at "stack underflow" - - -(* Evaluation *) - -(* - * Conventions: - * e : instr - * v : value - * es : instr list - * vs : value stack - * c : config - *) - -module Label () = -struct - exception Branch of value list - let label ts = - {branch = fun vs at -> raise (Branch (take (List.length ts) vs at))} -end - -let rec eval_instr (c : config) (vs : value stack) (e : instr) : value stack = - incr c.steps; - match e.it, vs with - | Unreachable, vs -> - trap e.at "unreachable executed, current operand stack: %s" - (string_of_values (List.rev vs)) - - | Nop, vs -> - vs - - | Block (ts, es), vs -> - let module L = Label () in - (try - eval_instrs {c with labels = L.label ts :: c.labels} [] es @ vs - with L.Branch vs' -> - vs' @ vs - ) - - | Loop (_ts, es), vs -> - let module L = Label () in - (try - eval_instrs {c with labels = L.label [] :: c.labels} [] es @ vs - with L.Branch vs' -> - eval_instr c (vs' @ vs) e - ) - - | If (ts, es1, es2), I32 i :: vs' -> - let module L = Label () in - (try - if i <> 0l - then eval_instrs {c with labels = L.label ts :: c.labels} [] es1 @ vs' - else eval_instrs {c with labels = L.label ts :: c.labels} [] es2 @ vs' - with L.Branch vs'' -> - vs'' @ vs' - ) - - | Br x, vs -> - (label c x).branch vs e.at - - | BrIf x, I32 i :: vs' -> - if i <> 0l - then (label c x).branch vs' e.at - else vs' - - | BrTable (xs, x), I32 i :: vs' -> - if I32.lt_u i (Lib.List32.length xs) - then (label c (Lib.List32.nth xs i)).branch vs' e.at - else (label c x).branch vs' e.at - - | Return, vs -> - c.return.branch vs e.at - - | Call x, vs -> - eval_func c vs (func c.frame.inst x) - - | CallIndirect x, I32 i :: vs -> - let func = func_elem c.frame.inst (0l @@ e.at) i e.at in - if type_ c.frame.inst x <> Func.type_of func then - trap e.at "indirect call type mismatch" - else - eval_func c vs func - - | Drop, v :: vs' -> - vs' - - | Select, I32 i :: v2 :: v1 :: vs' -> - (if i <> 0l then v1 else v2) :: vs' - - | GetLocal x, vs -> - !(local c.frame x) :: vs - - | SetLocal x, v :: vs' -> - local c.frame x := v; - vs' - - | TeeLocal x, v :: vs' -> - local c.frame x := v; - v :: vs' - - | GetGlobal x, vs -> - Global.load (global c.frame.inst x) :: vs - - | SetGlobal x, v :: vs' -> - (try Global.store (global c.frame.inst x) v; vs' - with Global.NotMutable -> crash e.at "write to immutable global" - | Global.Type -> crash e.at "type mismatch at global write") - - | Load {offset; ty; sz; _}, I32 i :: vs' -> - let mem = memory c.frame.inst (0l @@ e.at) in - let addr = I64_convert.extend_u_i32 i in - (try - let v = - match sz with - | None -> Memory.load_value mem addr offset ty - | Some (sz, ext) -> Memory.load_packed sz ext mem addr offset ty - in v :: vs' - with exn -> trap e.at "%s" (memory_error e.at exn)) - - | Store {offset; sz; _}, v :: I32 i :: vs' -> - let mem = memory c.frame.inst (0l @@ e.at) in - let addr = I64_convert.extend_u_i32 i in - (try - (match sz with - | None -> Memory.store_value mem addr offset v - | Some sz -> Memory.store_packed sz mem addr offset v - ); - vs' - with exn -> trap e.at "%s" (memory_error e.at exn)) - - | CurrentMemory, vs -> - let mem = memory c.frame.inst (0l @@ e.at) in - I32 (Memory.size mem) :: vs - - | GrowMemory, I32 delta :: vs' -> - let mem = memory c.frame.inst (0l @@ e.at) in - let old_size = Memory.size mem in - let result = - try Memory.grow mem delta; old_size - with Memory.SizeOverflow | Memory.SizeLimit | Memory.OutOfMemory -> -1l - in I32 result :: vs' - - | Const v, vs -> - v.it :: vs - - | Test testop, v :: vs' -> - (try value_of_bool (Eval_numeric.eval_testop testop v) :: vs' - with exn -> trap e.at "%s" (numeric_error e.at exn)) - - | Compare relop, v2 :: v1 :: vs' -> - (try value_of_bool (Eval_numeric.eval_relop relop v1 v2) :: vs' - with exn -> trap e.at "%s" (numeric_error e.at exn)) - - | Unary unop, v :: vs' -> - (try Eval_numeric.eval_unop unop v :: vs' - with exn -> trap e.at "%s" (numeric_error e.at exn)) - - | Binary binop, v2 :: v1 :: vs' -> - (try Eval_numeric.eval_binop binop v1 v2 :: vs' - with exn -> trap e.at "%s" (numeric_error e.at exn)) - - | Convert cvtop, v :: vs' -> - (try Eval_numeric.eval_cvtop cvtop v :: vs' - with exn -> trap e.at "%s" (numeric_error e.at exn)) - - | _ -> - crash e.at "missing or ill-typed operand on stack (%s : %s)" - (string_of_values (List.rev vs)) - (string_of_value_types (List.map type_of (List.rev vs))) - -and eval_instrs (c : config) (vs : value stack) (es : instr list) : value stack = - match es with - | [] -> vs - | e::es' -> - let vs' = eval_instr c vs e in - eval_instrs c vs' es' - -and eval_func (c : config) (vs : value stack) func : value stack = - let FuncType (ins, out) = Func.type_of func in - let n = List.length ins in - match func with - | Func.AstFunc (t, inst', f) -> - let args, vs' = take n vs f.at, drop n vs f.at in - let locals' = List.rev args @ List.map default_value f.it.locals in - let frame' = {inst = !inst'; locals = List.map ref locals'} in - let module L = Label () in - let l = L.label out in - let c' = {c with frame = frame'; labels = [l]; return = l} in - (try - eval_instrs c' args f.it.body @ vs' - with L.Branch vs'' -> - vs'' @ vs' - ) - - | Func.HostFunc (t, f) -> - let args, vs' = take n vs no_region, drop n vs no_region in - List.rev (f (List.rev args)) @ vs' - - -let invoke (func : func_inst) (vs : value list) : value list * int = - let FuncType (ins, out) = Func.type_of func in - assert (List.length vs = List.length ins); - let c = config empty_module_inst in - let vs' = eval_func c vs func in - assert (List.length vs' = List.length out); - List.rev vs', !(c.steps) diff --git a/src/wasm_eval.mli b/src/wasm_eval.mli deleted file mode 100644 index fee754a9564..00000000000 --- a/src/wasm_eval.mli +++ /dev/null @@ -1,7 +0,0 @@ -open Wasm.Values -open Wasm.Instance - -exception Trap of Wasm.Source.region * string -exception Crash of Wasm.Source.region * string - -val invoke : func_inst -> value list -> value list * int (* raises Trap *) diff --git a/test/run.sh b/test/run.sh index 6a3a6b028fa..fffd629ec90 100755 --- a/test/run.sh +++ b/test/run.sh @@ -21,7 +21,7 @@ DFINITY=no EXTRA_ASC_FLAGS= ASC=${ASC:-$(realpath $(dirname $0)/../src/asc)} AS_LD=${AS_LD:-$(realpath $(dirname $0)/../src/as-ld)} -DIDC=${IDLC:-$(realpath $(dirname $0)/../idl/didc)} +DIDC=${DIDC:-$(realpath $(dirname $0)/../src/didc)} export AS_LD WASM=${WASM:-wasm} DVM_WRAPPER=$(realpath $(dirname $0)/dvm.sh) @@ -216,7 +216,7 @@ do $ECHO -n " [tc]" $DIDC --check $base.did > $out/$base.tc 2>&1 tc_succeeded=$? - normalize $out/$base.tc + normalize $out/$base.tc diff_files="$diff_files $base.tc" if [ "$tc_succeeded" -eq 0 ]; @@ -225,7 +225,6 @@ do $DIDC --js $base.did > $out/$base.js 2>&1 diff_files="$diff_files $base.js" fi - fi $ECHO "" From 12e1a6f52c3aaa6fdb2674ff47166e98348906da Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 7 Jun 2019 12:35:13 +0200 Subject: [PATCH 0144/1176] Remove dependency Check_ir -> Flags by passing in verbosity as a boolean. In preparation of #483. --- src/aslib/check_ir.ml | 4 ++-- src/aslib/check_ir.mli | 2 +- src/aslib/pipeline.ml | 6 ++++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/aslib/check_ir.ml b/src/aslib/check_ir.ml index 313e549ff71..95773794f07 100644 --- a/src/aslib/check_ir.ml +++ b/src/aslib/check_ir.ml @@ -752,7 +752,7 @@ and gather_typ env ce typ = (* Programs *) -let check_prog scope phase (((ds, exp), flavor) as prog) : unit = +let check_prog verbose scope phase (((ds, exp), flavor) as prog) : unit = let env = env_of_scope scope flavor in try let scope = gather_block_decs env ds in @@ -761,7 +761,7 @@ let check_prog scope phase (((ds, exp), flavor) as prog) : unit = check_exp env' exp; with CheckFailed s -> let bt = Printexc.get_backtrace () in - if !Flags.verbose + if verbose then begin Printf.eprintf "Ill-typed intermediate code after %s:\n" phase; Printf.eprintf "%s" (Wasm.Sexpr.to_string 80 (Arrange_ir.prog prog)); diff --git a/src/aslib/check_ir.mli b/src/aslib/check_ir.mli index edb6264fa51..f5d7044aa40 100644 --- a/src/aslib/check_ir.mli +++ b/src/aslib/check_ir.mli @@ -1 +1 @@ -val check_prog : Typing.scope -> string -> Ir.prog -> unit +val check_prog : bool -> Typing.scope -> string -> Ir.prog -> unit diff --git a/src/aslib/pipeline.ml b/src/aslib/pipeline.ml index 362db40361a..6e7d4fd0ab7 100644 --- a/src/aslib/pipeline.ml +++ b/src/aslib/pipeline.ml @@ -394,7 +394,8 @@ let transform transform_name trans env prog name = phase transform_name name; let prog_ir' : Ir.prog = trans env prog in dump_ir Flags.dump_lowering prog_ir'; - if !Flags.check_ir then Check_ir.check_prog env transform_name prog_ir'; + if !Flags.check_ir + then Check_ir.check_prog !Flags.verbose env transform_name prog_ir'; prog_ir' let transform_if transform_name trans flag env prog name = @@ -405,7 +406,8 @@ let desugar env lib_env libraries progs name = phase "Desugaring" name; let prog_ir' : Ir.prog = Desugar.transform_graph lib_env libraries progs in dump_ir Flags.dump_lowering prog_ir'; - if !Flags.check_ir then Check_ir.check_prog env "Desugaring" prog_ir'; + if !Flags.check_ir + then Check_ir.check_prog !Flags.verbose env "Desugaring" prog_ir'; prog_ir' let await_lowering = From 107b3735a653efda3d0e42c61ea176c0360993eb Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Fri, 7 Jun 2019 13:22:00 -0600 Subject: [PATCH 0145/1176] trie optimizations for PX workload; measured --- src/counters.ml | 15 +- .../examples/produce-exchange/serverModel.as | 40 ++-- stdlib/trie2.as | 176 +++++++++++++++++- 3 files changed, 210 insertions(+), 21 deletions(-) diff --git a/src/counters.ml b/src/counters.ml index 25156fbbc94..459073e5ebc 100644 --- a/src/counters.ml +++ b/src/counters.ml @@ -86,7 +86,7 @@ let dump (c:t) (ve: Value.value Value.Env.t) = in let sorted_counts = List.sort ( - (* Final ordering: + (* Final ordering: - counts; bigger first; this is the main ordering constraint. - labels; labeled expressions before unlabeled - regions; earlier/outer regions before later/enclosed ones @@ -118,12 +118,23 @@ let dump (c:t) (ve: Value.value Value.Env.t) = Printf.fprintf file "# column: source region count\n" ; List.iter (fun fld -> Printf.fprintf file "# column: --profile-field: %s\n" fld) (List.rev flds) ; + let lab_total = ref 0 in + let unlab_total = ref 0 in + List.iter (fun ((region, labop), region_count) -> + assert (dump_count = 0); + (match labop with + None -> unlab_total := !unlab_total + region_count + | Some x -> lab_total := !lab_total + region_count + ); + ) sorted_counts; + Printf.fprintf file "# count total (unlabeled): %d\n" !unlab_total ; + Printf.fprintf file "# ... labeled: %d\n" !lab_total ; List.iter (fun ((region, labop), region_count) -> assert (dump_count = 0); Printf.fprintf file "%s\"%s\", %s, %d%s\n" (!Flags.profile_line_prefix) (string_of_region region) - (match labop with + (match labop with None -> "null" | Some x -> Printf.sprintf "?\"%s\"" x ) diff --git a/stdlib/examples/produce-exchange/serverModel.as b/stdlib/examples/produce-exchange/serverModel.as index 2f56304552f..86348d550ae 100644 --- a/stdlib/examples/produce-exchange/serverModel.as +++ b/stdlib/examples/produce-exchange/serverModel.as @@ -38,6 +38,7 @@ import Option = "../../option.as"; import Trie = "../../trie2.as"; type Trie = Trie.Trie; +type TrieBuild = Trie.Build.TrieBuild; type Key = Trie.Key; type Table = Trie.Trie; @@ -54,6 +55,7 @@ import Result = "../../result.as"; type Result = Result.Result; type RouteInventoryMap = Trie<(T.RouteId, T.InventoryId), (M.RouteDoc, M.InventoryDoc)>; +type QueryResult = TrieBuild<(T.RouteId, T.InventoryId), (M.RouteDoc, M.InventoryDoc)>; type RoleId = { #user : T.UserId; @@ -1969,26 +1971,27 @@ than the MVP goals, however. debugOff " production regions.\n"; /** - Join: For each production region, consider all routes and inventory: */ - let queryResults : Trie = { + let queryResults : Trie = { retailerJoinCount += 1; Trie.join( + QueryResult>( retailerRoutes, inventoryByRegion, idIsEq, func (routes:M.RouteMap, - inventory:M.ByProducerInventoryMap) : RouteInventoryMap + inventory:M.ByProducerInventoryMap) : QueryResult = - label profile_retailerQueryAll_product_region : RouteInventoryMap + label profile_retailerQueryAll_product_region : QueryResult { /** - Within this production region, consider every route-item pairing: */ - let product = Trie.prod( + let product = Trie.Build.prodBuild + ( routes, /** - (To perform this Cartesian product, use a 1D inventory map:) */ Trie.mergeDisjoint2D( @@ -2030,13 +2033,15 @@ than the MVP goals, however. )}; /** - The results are still organized by producer region; merge all such regions: */ - let queryResultsMerged : RouteInventoryMap = - Trie.mergeDisjoint2D( - queryResults, idIsEq, idPairIsEq); + let queryResult : QueryResult = + Trie.Build.projectInnerBuild + + (queryResults); debugOff "- query result count: "; - let size = Trie.count<(T.RouteId, T.InventoryId), - (M.RouteDoc, M.InventoryDoc)>(queryResultsMerged); + let size = Trie.Build.buildCount + <(T.RouteId, T.InventoryId), + (M.RouteDoc, M.InventoryDoc)>(queryResult); if ( size > retailerQuerySizeMax ) { retailerQuerySizeMax := size; }; @@ -2045,10 +2050,11 @@ than the MVP goals, however. /** - Prepare reservation information for client, as an array; see also [`makeReservationInfo`](#makereservationinfo) */ let arr = - Trie.toArray<(T.RouteId, T.InventoryId), - (M.RouteDoc, M.InventoryDoc), - T.ReservationInfo>( - queryResultsMerged, + Trie.Build.buildToArray + <(T.RouteId, T.InventoryId), + (M.RouteDoc, M.InventoryDoc), + T.ReservationInfo>( + queryResult, func (_:(T.RouteId,T.InventoryId), (r:M.RouteDoc, i:M.InventoryDoc)) : T.ReservationInfo { makeReservationInfo(i, r) diff --git a/stdlib/trie2.as b/stdlib/trie2.as index f2481744f88..a283be289c9 100644 --- a/stdlib/trie2.as +++ b/stdlib/trie2.as @@ -798,7 +798,7 @@ type Trie3D = Trie >; func merge (a:Trie, b:Trie) : Trie = mergeDisjoint(a, b, k3_eq); - /**- `foldUp` "squared"; something like "`foldUp^2((tl, tr), merge, (insert null >( tl, merge, func (k1:K1, v1:V1) : Trie { @@ -818,6 +818,177 @@ type Trie3D = Trie >; }; + /** + Build: An ADT for "Trie Builds" + ======================================== + + This module provides optimized variants of normal tries, for + (much!) more efficient PX retailer queries. + + The central insight is that for (unmaterialized) query results, we + do not need to actually build any resulting trie of the resulting + data, but rather, just need a collection of what would be in that + trie. Since query results can be large (quadratic in the DB size!), + avoiding the construction of this trie provides a considerable savings. + + To get this savings, we use an ADT for the operations that _would_ build this trie, + if evaluated. This structure specializes a rope: a balanced tree representing a + sequence. It is only as balanced as the tries from which we generate + these build ASTs. They have no intrinsic balance properties of their + own. + + */ + module Build { + + /** Commands for building tries. + + For PL academics: Imagine commands for the IMP imperative language, + but where global memory consists of a single (anonymous) global trie */ + type TrieBuild = { + #skip ; + #insert : (Key, V) ; + #seq : { + count : Nat ; + left : TrieBuild ; + right : TrieBuild ; + } ; + }; + + func buildCount(tb:TrieBuild) : Nat = + label profile_trie_buildCount : Nat { + switch tb { + case (#skip) 0; + case (#insert(_, _)) 1; + case (#seq(seq)) seq.count; + } + }; + + func buildSeq(l:TrieBuild, r:TrieBuild) : TrieBuild = + label profile_trie_buildSeq : TrieBuild { + let sum = buildCount(l) + buildCount(r); + #seq(new { count = sum; left = l; right = r }) + }; + + /** + `prodBuild` + --------------- + + Like `prod`, except do not actually do the insert calls, just + record them, as a (binary tree) data structure, isomorphic to the + recursion of this function (which is balanced, in expectation). + + See also: + + - [`prod`](#prod) + + */ + func prodBuild( + tl :Trie, + tr :Trie, + op :(K1,V1,K2,V2) -> ?(Key,V3), + k3_eq :(K3,K3) -> Bool + ) + : TrieBuild + { + func outer_bin (a:TrieBuild, + b:TrieBuild) + : TrieBuild = + label profile_trie_prodBuild_outer_seqOfBranch : TrieBuild { + buildSeq(a, b) + }; + + func inner_bin (a:TrieBuild, + b:TrieBuild) + : TrieBuild = + label profile_trie_prodBuild_inner_seqOfBranch : TrieBuild { + buildSeq(a, b) + }; + + /**- "`foldUp` squared" (imagine two nested loops): */ + foldUp>( + tl, outer_bin, + func (k1:K1, v1:V1) : TrieBuild { + foldUp>( + tr, inner_bin, + func (k2:K2, v2:V2) : TrieBuild { + switch (op(k1, v1, k2, v2)) { + case null #skip; + case (?(k3, v3)) { #insert(k3, v3) }; + } + }, + #skip + ) + }, + #skip + ) + }; + + /** + `buildNth` + -------- + Project the nth key-value pair from the trie build. + + This position is meaningful only when the build contains multiple uses of one or more keys, otherwise it is not. + */ + func buildNth(tb:TrieBuild, i:Nat) : ?(Key, V) = label profile_triebuild_nth : (?(Key, V)) { + func rec(tb:TrieBuild, i:Nat) : ?(Key, V) = label profile_triebuild_nth_rec : (?(Key, V)) { + switch tb { + case (#skip) P.unreachable(); + case (#insert (k,v)) label profile_trie_buildNth_rec_end : (?(Key, V)) { + assert(i == 0); + ?(k,v) + }; + case (#seq s) label profile_trie_buildNth_rec_seq : (?(Key, V)) { + let count_left = buildCount(s.left); + if (i < count_left) { rec(s.left, i) } + else { rec(s.right, i - count_left) } + }; + } + }; + if (i >= buildCount(tb)) { + return null + }; + rec(tb, i) + }; + + /** + `projectInnerBuild` + -------------- + + Like [`mergeDisjoint`](#mergedisjoint), except that it avoids the + work of actually merging any tries; rather, just record the work for + latter (if ever). + */ + func projectInnerBuild(t : Trie>) + : TrieBuild + { + foldUp, TrieBuild> + ( t, + func (t1:TrieBuild, t2:TrieBuild):TrieBuild { buildSeq(t1, t2) }, + func (_:K1, t:TrieBuild): TrieBuild { t }, + #skip ) + }; + + /** + `buildToArray` + -------- + Gather the collection of key-value pairs into an array of a (possibly-distinct) type. + */ + func buildToArray(tb:TrieBuild,f:(K,V)->W):[W] = + label profile_triebuild_toArray_begin : [W] { + let a = Array_tabulate ( + buildCount(tb), + func (i:Nat) : W = label profile_triebuild_toArray_nth : W { + let (k,v) = Option.unwrap<(Key,V)>(buildNth(tb, i)); + f(k.key, v) + } + ); + label profile_triebuild_toArray_end : [W] + a + }; + + }; + /** `fold` --------- @@ -891,7 +1062,7 @@ type Trie3D = Trie >; doing so. */ func nth(t:Trie, i:Nat) : ?(Key, V) = label profile_trie_nth : (?(Key, V)) { - func rec(t:Trie, i:Nat) : ?(Key, V) { + func rec(t:Trie, i:Nat) : ?(Key, V) = label profile_trie_nth_rec : (?(Key, V)) { switch t { case (#empty) P.unreachable(); case (#leaf l) List.nth<(Key,V)>(l.keyvals, i); @@ -908,6 +1079,7 @@ type Trie3D = Trie >; rec(t, i) }; + /** `toArray` -------- From 46e7ce98418f58c2c3d01b72d9461232ee5dd7cc Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Fri, 7 Jun 2019 15:10:30 -0600 Subject: [PATCH 0146/1176] trie: a faster tree-to-array procedure --- .../examples/produce-exchange/serverModel.as | 2 +- stdlib/trie2.as | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/stdlib/examples/produce-exchange/serverModel.as b/stdlib/examples/produce-exchange/serverModel.as index 86348d550ae..18d87efedd9 100644 --- a/stdlib/examples/produce-exchange/serverModel.as +++ b/stdlib/examples/produce-exchange/serverModel.as @@ -2050,7 +2050,7 @@ than the MVP goals, however. /** - Prepare reservation information for client, as an array; see also [`makeReservationInfo`](#makereservationinfo) */ let arr = - Trie.Build.buildToArray + Trie.Build.buildToArray2 <(T.RouteId, T.InventoryId), (M.RouteDoc, M.InventoryDoc), T.ReservationInfo>( diff --git a/stdlib/trie2.as b/stdlib/trie2.as index a283be289c9..887a348e156 100644 --- a/stdlib/trie2.as +++ b/stdlib/trie2.as @@ -987,6 +987,28 @@ type Trie3D = Trie >; a }; + /** + `buildToArray2` + -------- + Gather the collection of key-value pairs into an array of a (possibly-distinct) type. + + (Same semantics as `buildToArray`, but faster in practice.) + */ + func buildToArray2(tb:TrieBuild,f:(K,V)->W):[W] { + let c = buildCount(tb); + let a = Array_init(c, null); + var i = 0; + func rec(tb:TrieBuild) { + switch tb { + case (#skip) (); + case (#insert(k,v)) { a[i] := ?f(k.key,v); i := i + 1 }; + case (#seq(s)) { rec(s.left); rec(s.right) }; + } + }; + rec(tb); + Array_tabulate(c, func(i:Nat) : W = Option.unwrap(a[i])) + }; + }; /** From 85610ab4953b43f919bb826bf18cec065b274fb1 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Fri, 7 Jun 2019 15:35:03 -0600 Subject: [PATCH 0147/1176] tickled compiler bug: coverage check: assertion failed --- stdlib/examples/produce-exchange/serverModel.as | 8 ++------ stdlib/trie2.as | 8 ++++---- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/stdlib/examples/produce-exchange/serverModel.as b/stdlib/examples/produce-exchange/serverModel.as index 18d87efedd9..67084cc5235 100644 --- a/stdlib/examples/produce-exchange/serverModel.as +++ b/stdlib/examples/produce-exchange/serverModel.as @@ -2012,12 +2012,8 @@ than the MVP goals, however. /** - Consider the constraints of the retailer-route-item combination: */ if (isFeasibleReservation(retailer, item, route, queryProduce, queryDate)) { label profile_retailerQueryAll_candidate_check_true : - ( ?(Key<(T.RouteId, T.InventoryId)>, - (M.RouteDoc, M.InventoryDoc)) ) - - ?( keyOfIdPair(route_id, item_id), - (route, item) - ) + ( ?((T.RouteId, T.InventoryId), (M.RouteDoc, M.InventoryDoc)) ) + ?( (route_id, item_id), (route, item) ) } else { label profile_retailerQueryAll_candidate_check_false : ( ?(Key<(T.RouteId, T.InventoryId)>, diff --git a/stdlib/trie2.as b/stdlib/trie2.as index 887a348e156..31d7094311d 100644 --- a/stdlib/trie2.as +++ b/stdlib/trie2.as @@ -846,7 +846,7 @@ type Trie3D = Trie >; but where global memory consists of a single (anonymous) global trie */ type TrieBuild = { #skip ; - #insert : (Key, V) ; + #insert : (K, ?Hash, V) ; #seq : { count : Nat ; left : TrieBuild ; @@ -858,7 +858,7 @@ type Trie3D = Trie >; label profile_trie_buildCount : Nat { switch tb { case (#skip) 0; - case (#insert(_, _)) 1; + case (#insert(_, _, _)) 1; case (#seq(seq)) seq.count; } }; @@ -885,7 +885,7 @@ type Trie3D = Trie >; func prodBuild( tl :Trie, tr :Trie, - op :(K1,V1,K2,V2) -> ?(Key,V3), + op :(K1,V1,K2,V2) -> ?(K3,V3), k3_eq :(K3,K3) -> Bool ) : TrieBuild @@ -913,7 +913,7 @@ type Trie3D = Trie >; func (k2:K2, v2:V2) : TrieBuild { switch (op(k1, v1, k2, v2)) { case null #skip; - case (?(k3, v3)) { #insert(k3, v3) }; + case (?(k3, v3)) { #insert(k3, null, v3) }; } }, #skip From 09adef31c95be45f9435b32da3e0c1451cfeae77 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Fri, 7 Jun 2019 14:40:49 -0700 Subject: [PATCH 0148/1176] Fix spacing --- src/languageServer.ml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/languageServer.ml b/src/languageServer.ml index 55e91984d13..0cff8fdbb53 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -44,7 +44,7 @@ module Channel = struct let notification = notification params in send_notification oc (Lsp_j.string_of_notification_message notification) - let publish_diagnostics (oc : out_channel) (uri: Lsp_t.document_uri) (diags: Lsp_t.diagnostic list): unit = + let publish_diagnostics (oc : out_channel) (uri : Lsp_t.document_uri) (diags : Lsp_t.diagnostic list): unit = let params = `PublishDiagnostics (Lsp_t. { publish_diagnostics_params_uri = uri ; publish_diagnostics_params_diagnostics = diags @@ -53,13 +53,13 @@ module Channel = struct send_notification oc (Lsp_j.string_of_notification_message notification) end -let position_of_pos (pos: Source.pos): Lsp_t.position = Lsp_t. +let position_of_pos (pos : Source.pos) : Lsp_t.position = Lsp_t. (* The LSP spec requires zero-based positions *) { position_line = if pos.Source.line > 0 then pos.Source.line - 1 else 0 ; position_character = pos.Source.column } -let range_of_region (at: Source.region): Lsp_t.range = Lsp_t. +let range_of_region (at : Source.region) : Lsp_t.range = Lsp_t. { range_start = position_of_pos at.Source.left ; range_end_ = position_of_pos at.Source.right } @@ -69,7 +69,7 @@ let severity_of_sev : Diag.severity -> Lsp.DiagnosticSeverity.t = | Diag.Error -> Lsp.DiagnosticSeverity.Error | Diag.Warning -> Lsp.DiagnosticSeverity.Warning -let diagnostics_of_message (msg: Diag.message): Lsp_t.diagnostic = Lsp_t. +let diagnostics_of_message (msg : Diag.message) : Lsp_t.diagnostic = Lsp_t. { diagnostic_range = range_of_region msg.Diag.at ; diagnostic_severity = Some (severity_of_sev msg.Diag.sev) ; diagnostic_code = None From f8519d7522a6cdf4011bbd4483739642ef8d3f54 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Fri, 7 Jun 2019 15:57:46 -0600 Subject: [PATCH 0149/1176] PX/stdlib optimization: avoid hashing query result keys --- stdlib/examples/produce-exchange/serverModel.as | 6 +++--- stdlib/trie2.as | 16 ++++++++-------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/stdlib/examples/produce-exchange/serverModel.as b/stdlib/examples/produce-exchange/serverModel.as index 67084cc5235..60251292b19 100644 --- a/stdlib/examples/produce-exchange/serverModel.as +++ b/stdlib/examples/produce-exchange/serverModel.as @@ -2001,11 +2001,11 @@ than the MVP goals, however. route :M.RouteDoc, item_id :T.InventoryId, item :M.InventoryDoc) : - ?(Key<(T.RouteId, T.InventoryId)>, + ?((T.RouteId, T.InventoryId), (M.RouteDoc, M.InventoryDoc)) = label profile_retailerQueryAll_candidate_check : - ( ?(Key<(T.RouteId, T.InventoryId)>, + ( ?((T.RouteId, T.InventoryId), (M.RouteDoc, M.InventoryDoc)) ) { retailerQueryCost += 1; @@ -2016,7 +2016,7 @@ than the MVP goals, however. ?( (route_id, item_id), (route, item) ) } else { label profile_retailerQueryAll_candidate_check_false : - ( ?(Key<(T.RouteId, T.InventoryId)>, + ( ?((T.RouteId, T.InventoryId), (M.RouteDoc, M.InventoryDoc)) ) null diff --git a/stdlib/trie2.as b/stdlib/trie2.as index 31d7094311d..ac560a61dd1 100644 --- a/stdlib/trie2.as +++ b/stdlib/trie2.as @@ -930,15 +930,15 @@ type Trie3D = Trie >; This position is meaningful only when the build contains multiple uses of one or more keys, otherwise it is not. */ - func buildNth(tb:TrieBuild, i:Nat) : ?(Key, V) = label profile_triebuild_nth : (?(Key, V)) { - func rec(tb:TrieBuild, i:Nat) : ?(Key, V) = label profile_triebuild_nth_rec : (?(Key, V)) { + func buildNth(tb:TrieBuild, i:Nat) : ?(K, ?Hash, V) = label profile_triebuild_nth : (?(K, ?Hash, V)) { + func rec(tb:TrieBuild, i:Nat) : ?(K, ?Hash, V) = label profile_triebuild_nth_rec : (?(K, ?Hash, V)) { switch tb { case (#skip) P.unreachable(); - case (#insert (k,v)) label profile_trie_buildNth_rec_end : (?(Key, V)) { + case (#insert (k,h,v)) label profile_trie_buildNth_rec_end : (?(K, ?Hash, V)) { assert(i == 0); - ?(k,v) + ?(k,h,v) }; - case (#seq s) label profile_trie_buildNth_rec_seq : (?(Key, V)) { + case (#seq s) label profile_trie_buildNth_rec_seq : (?(K, ?Hash, V)) { let count_left = buildCount(s.left); if (i < count_left) { rec(s.left, i) } else { rec(s.right, i - count_left) } @@ -979,8 +979,8 @@ type Trie3D = Trie >; let a = Array_tabulate ( buildCount(tb), func (i:Nat) : W = label profile_triebuild_toArray_nth : W { - let (k,v) = Option.unwrap<(Key,V)>(buildNth(tb, i)); - f(k.key, v) + let (k,_,v) = Option.unwrap<(K,?Hash,V)>(buildNth(tb, i)); + f(k, v) } ); label profile_triebuild_toArray_end : [W] @@ -1001,7 +1001,7 @@ type Trie3D = Trie >; func rec(tb:TrieBuild) { switch tb { case (#skip) (); - case (#insert(k,v)) { a[i] := ?f(k.key,v); i := i + 1 }; + case (#insert(k,_,v)) { a[i] := ?f(k,v); i := i + 1 }; case (#seq(s)) { rec(s.left); rec(s.right) }; } }; From eda40a92a5625b3e9152c47c3bf1c6335f5e5ec3 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Fri, 7 Jun 2019 15:26:26 -0700 Subject: [PATCH 0150/1176] Formatting --- src/languageServer.ml | 53 +++-- src/lsp.atd | 373 +++++++++++++++++----------------- src/lsp/diagnosticSeverity.ml | 26 ++- src/lsp/messageType.ml | 26 ++- 4 files changed, 237 insertions(+), 241 deletions(-) diff --git a/src/languageServer.ml b/src/languageServer.ml index 0cff8fdbb53..75aedd8808c 100644 --- a/src/languageServer.ml +++ b/src/languageServer.ml @@ -5,14 +5,14 @@ let jsonrpc_version : string = "2.0" let notification (params : Lsp_t.notification_message_params) : Lsp_t.notification_message = Lsp_t. - { notification_message_jsonrpc = jsonrpc_version - ; notification_message_params = params + { notification_message_jsonrpc = jsonrpc_version; + notification_message_params = params; } let response_result_message (id : int) (result : Lsp_t.response_result) : Lsp_t.response_message = Lsp_t. - { response_message_jsonrpc = jsonrpc_version - ; response_message_id = id - ; response_message_result = Some result + { response_message_jsonrpc = jsonrpc_version; + response_message_id = id; + response_message_result = Some result; } (* let response_error_message (id : int) (error : Lsp_t.response_error) : Lsp_t.response_message = *) @@ -38,16 +38,16 @@ module Channel = struct let params = `WindowShowMessage (Lsp_t. - { window_show_message_params_type_ = typ - ; window_show_message_params_message = msg + { window_show_message_params_type_ = typ; + window_show_message_params_message = msg; }) in let notification = notification params in send_notification oc (Lsp_j.string_of_notification_message notification) let publish_diagnostics (oc : out_channel) (uri : Lsp_t.document_uri) (diags : Lsp_t.diagnostic list): unit = let params = `PublishDiagnostics (Lsp_t. - { publish_diagnostics_params_uri = uri - ; publish_diagnostics_params_diagnostics = diags + { publish_diagnostics_params_uri = uri; + publish_diagnostics_params_diagnostics = diags; }) in let notification = notification params in send_notification oc (Lsp_j.string_of_notification_message notification) @@ -55,27 +55,26 @@ end let position_of_pos (pos : Source.pos) : Lsp_t.position = Lsp_t. (* The LSP spec requires zero-based positions *) - { position_line = if pos.Source.line > 0 then pos.Source.line - 1 else 0 - ; position_character = pos.Source.column + { position_line = if pos.Source.line > 0 then pos.Source.line - 1 else 0; + position_character = pos.Source.column; } let range_of_region (at : Source.region) : Lsp_t.range = Lsp_t. - { range_start = position_of_pos at.Source.left - ; range_end_ = position_of_pos at.Source.right + { range_start = position_of_pos at.Source.left; + range_end_ = position_of_pos at.Source.right; } -let severity_of_sev : Diag.severity -> Lsp.DiagnosticSeverity.t = - function +let severity_of_sev : Diag.severity -> Lsp.DiagnosticSeverity.t = function | Diag.Error -> Lsp.DiagnosticSeverity.Error | Diag.Warning -> Lsp.DiagnosticSeverity.Warning let diagnostics_of_message (msg : Diag.message) : Lsp_t.diagnostic = Lsp_t. - { diagnostic_range = range_of_region msg.Diag.at - ; diagnostic_severity = Some (severity_of_sev msg.Diag.sev) - ; diagnostic_code = None - ; diagnostic_source = Some "ActorScript" - ; diagnostic_message = msg.Diag.text - ; diagnostic_relatedInformation = None + { diagnostic_range = range_of_region msg.Diag.at; + diagnostic_severity = Some (severity_of_sev msg.Diag.sev); + diagnostic_code = None; + diagnostic_source = Some "ActorScript"; + diagnostic_message = msg.Diag.text; + diagnostic_relatedInformation = None; } let file_uri_prefix = "file://" ^ Sys.getcwd () ^ "/" @@ -116,12 +115,12 @@ let start () = | (Some id, `Initialize params) -> client_capabilities := Some params.Lsp_t.initialize_params_capabilities; - let result = `Initialize (Lsp_t. - { initialize_result_capabilities = - { server_capabilities_textDocumentSync = 1 - ; server_capabilities_hoverProvider = Some true - } - }) in + let result = `Initialize (Lsp_t.{ + initialize_result_capabilities = { + server_capabilities_textDocumentSync = 1; + server_capabilities_hoverProvider = Some true; + } + }) in let response = response_result_message id result in send_response (Lsp_j.string_of_response_message response); diff --git a/src/lsp.atd b/src/lsp.atd index a479c132706..cb6f8f41c3c 100644 --- a/src/lsp.atd +++ b/src/lsp.atd @@ -3,20 +3,20 @@ (* Abstract message *) -type message = - { jsonrpc : string - } - +type message = { + jsonrpc : string; +} + (* Notification message *) -type notification_message = - { inherit message - ; params : notification_message_params - } - - +type notification_message = { + inherit message; + params : notification_message_params; +} + + (* @@ -29,24 +29,24 @@ type notification_message = `incoming_message` type to allow them to be decoded in a single pass. *) -type incoming_message = - { inherit message - ; ?id : int nullable - ; params : incoming_message_params - } - - +type incoming_message = { + inherit message; + ?id : int nullable; + params : incoming_message_params; +} + + (* All tags must also provide params, even if they are an `empty_record` *) -type incoming_message_params = - [ Initialize of initialize_params +type incoming_message_params = [ + Initialize of initialize_params | Initialized of initialized_params | TextDocumentDidOpen of text_document_did_open_params | TextDocumentDidClose of text_document_did_close_params | TextDocumentDidChange of text_document_did_change_params | TextDocumentDidSave of text_document_did_save_params | TextDocumentHover of text_document_position_params - ] +] (* Outgoing messages @@ -56,32 +56,32 @@ type incoming_message_params = (* Response message *) -type response_message = - { inherit message - ; id : int - ; ?result : response_result nullable - (*; ?error : response_error nullable*) - } - - - -type response_result = - [ Initialize of initialize_result +type response_message = { + inherit message; + id : int; + ?result : response_result nullable; + (* ?error : response_error nullable; *) +} + + + +type response_result = [ + Initialize of initialize_result | TextDocumentHoverResponse of hover_result - ] +] -type hover_result = - { contents : string - } - +type hover_result = { + contents : string; +} + (* Outgoing notifications *) -type notification_message_params = - [ PublishDiagnostics of publish_diagnostics_params +type notification_message_params = [ + PublishDiagnostics of publish_diagnostics_params | WindowShowMessage of window_show_message_params - ] +] type document_uri = string @@ -89,144 +89,145 @@ type document_uri = string (* "initialize" request *) -type initialize_params = - { ?processId : int nullable - ; ?rootPath : string nullable - (*; rootUri : document_uri nullable*) - (*; ?initializationOptions : any*) - ; capabilities : client_capabilities - ; ?trace : trace nullable - (*; ?workspaceFolders : (workspace_folder list) nullable*) - } - - -type text_document_did_open_params = - { textDocument : text_document_item - } - - -type text_document_did_change_params = - { textDocument : versioned_text_document_identifier - } - - -type text_document_did_close_params = - { textDocument : text_document_identifier - } - - -type text_document_did_save_params = - { textDocument : text_document_identifier - } - - -type text_document_position_params = - { textDocument : text_document_identifier - ; position : position - } - +type initialize_params = { + ?processId : int nullable; + ?rootPath : string nullable; + (* rootUri : document_uri nullable; *) + (* ?initializationOptions : any; *) + capabilities : client_capabilities; + ?trace : trace nullable; + (* ?workspaceFolders : (workspace_folder list) nullable; *) +} + + +type text_document_did_open_params = { + textDocument : text_document_item; +} + + +type text_document_did_change_params = { + textDocument : versioned_text_document_identifier; +} + + +type text_document_did_close_params = { + textDocument : text_document_identifier; +} + + +type text_document_did_save_params = { + textDocument : text_document_identifier; +} + + +type text_document_position_params = { + textDocument : text_document_identifier; + position : position; +} + (* See https://microsoft.github.io/language-server-protocol/specification#position We'll have to do some work to make sure we can split text efficiently regardless of what line endings are being used *) -type position = - { line : int - ; character : int - } - - -type range = - { start : position - ; end_ : position - } - - -type location = - { uri : document_uri - ; range : range - } - - -type text_document_item = - { uri: document_uri - ; text: string - ; languageId: string - ; version: int - } - - -type text_document_identifier = - { uri: document_uri - } - - -type versioned_text_document_identifier = - { inherit text_document_identifier - ; ?version: int nullable - } - - -type client_capabilities = - (* { ?workspace : workspace_client_capabilities *) - { ?textDocument : text_document_client_capabilities nullable - (* ; ?experimental : any *) - } - - -type text_document_client_capabilities = - (* { ?synchronization : TODO *) - (* ; ?completion : TODO *) - (* ; ?hover : TODO *) - (* ; ?signatureHelp : TODO *) - (* ; ?references : TODO *) - (* ; ?documentHighlight : TODO *) - (* ; ?documentSymbol : TODO *) - (* ; ?formatting : TODO *) - (* ; ?rangeFormatting : TODO *) - (* ; ?onTypeFormatting : TODO *) - (* ; ?declaration : TODO *) - (* ; ?definition : TODO *) - (* ; ?typeDefinition : TODO *) - (* ; ?implementation : TODO *) - (* ; ?codeAction : TODO *) - (* ; ?codeLens : TODO *) - (* ; ?documentLink : TODO *) - (* ; ?colorProvider : TODO *) - (* ; ?rename : TODO *) - { ?publishDiagnostics : publish_diagnostics_field_type nullable - (* { ?publishDiagnostics : bool nullable *) - (* ; ?foldingRange : TODO *) - } - +type position = { + line : int; + character : int; +} + + +type range = { + start : position; + end_ : position; +} + + +type location = { + uri : document_uri; + range : range; +} + + +type text_document_item = { + uri: document_uri; + text: string; + languageId: string; + version: int; +} + + +type text_document_identifier = { + uri: document_uri; +} + + +type versioned_text_document_identifier = { + inherit text_document_identifier; + ?version: int nullable; +} + + +type client_capabilities = { + (* ?workspace : workspace_client_capabilities; *) + ?textDocument : text_document_client_capabilities nullable; + (* ?experimental : any; *) +} + + +type text_document_client_capabilities = { + (* ?synchronization : TODO; *) + (* ?completion : TODO; *) + (* ?hover : TODO; *) + (* ?signatureHelp : TODO; *) + (* ?references : TODO; *) + (* ?documentHighlight : TODO; *) + (* ?documentSymbol : TODO; *) + (* ?formatting : TODO; *) + (* ?rangeFormatting : TODO; *) + (* ?onTypeFormatting : TODO; *) + (* ?declaration : TODO; *) + (* ?definition : TODO; *) + (* ?typeDefinition : TODO; *) + (* ?implementation : TODO; *) + (* ?codeAction : TODO; *) + (* ?codeLens : TODO; *) + (* ?documentLink : TODO; *) + (* ?colorProvider : TODO; *) + (* ?rename : TODO; *) + ?publishDiagnostics : publish_diagnostics_field_type nullable; + (* ?foldingRange : TODO; *) +} + (* Defining this inline in `text_document_client_capabilities` resulted in a syntax error in the generated `lsp_t.mli` file. *) -type publish_diagnostics_field_type = { ?relatedInformation : bool nullable } +type publish_diagnostics_field_type = { + ?relatedInformation : bool nullable; +} -type trace = - [ Off +type trace = [ + Off | Messages | Verbose - ] +] (* "initialize" response *) -type initialize_result = - { capabilities : server_capabilities - } - +type initialize_result = { + capabilities : server_capabilities; +} + (* FIXME: incomplete *) -type server_capabilities = - { textDocumentSync : int - ; ?hoverProvider : bool nullable - } - +type server_capabilities = { + textDocumentSync : int; + ?hoverProvider : bool nullable; +} + (* TODO: see LSP spec for InitializeError *) (*type initialize_error = *) @@ -239,37 +240,37 @@ type initialized_params = empty_record (* "publishDiagnostics" notification *) -type publish_diagnostics_params = - { uri : document_uri - ; diagnostics : diagnostic list - } - - -type diagnostic = - { range : range - ; ?severity : diagnostic_severity nullable - ; ?code : int nullable - ; ?source : string nullable - ; message : string - ; ?relatedInformation : (diagnostic_related_information list) nullable - } - +type publish_diagnostics_params = { + uri : document_uri; + diagnostics : diagnostic list; +} + + +type diagnostic = { + range : range; + ?severity : diagnostic_severity nullable; + ?code : int nullable; + ?source : string nullable; + message : string; + ?relatedInformation : (diagnostic_related_information list) nullable; +} + type diagnostic_severity = int wrap -type diagnostic_related_information = - { location : location - ; message : string - } - +type diagnostic_related_information = { + location : location; + message : string; +} + (* "window/showMessage" notification *) -type window_show_message_params = - { type_ : message_type - ; message : string - } - +type window_show_message_params = { + type_ : message_type; + message : string; +} + type message_type = int wrap @@ -279,7 +280,7 @@ type message_type = int wrap (* Empty records aren't valid in OCaml but some notifications send them in the `params` field. Work around that by defining a record with a field that is never expected to be provided. *) -type empty_record = - { ?omitted : int nullable - } - +type empty_record = { + ?omitted : int nullable +} + diff --git a/src/lsp/diagnosticSeverity.ml b/src/lsp/diagnosticSeverity.ml index 3dbf0b586d9..6435c8a7d0c 100644 --- a/src/lsp/diagnosticSeverity.ml +++ b/src/lsp/diagnosticSeverity.ml @@ -5,18 +5,16 @@ type t | Hint | Unknown of int -let wrap : int -> t = -function -| 1 -> Error -| 2 -> Warning -| 3 -> Information -| 4 -> Hint -| x -> Unknown x +let wrap : int -> t = function + | 1 -> Error + | 2 -> Warning + | 3 -> Information + | 4 -> Hint + | x -> Unknown x -let unwrap : t -> int = -function -| Error -> 1 -| Warning -> 2 -| Information -> 3 -| Hint -> 4 -| Unknown x -> x +let unwrap : t -> int = function + | Error -> 1 + | Warning -> 2 + | Information -> 3 + | Hint -> 4 + | Unknown x -> x diff --git a/src/lsp/messageType.ml b/src/lsp/messageType.ml index fbec3d7d8aa..0b8f1216e0f 100644 --- a/src/lsp/messageType.ml +++ b/src/lsp/messageType.ml @@ -5,18 +5,16 @@ type t | Log | Unknown of int -let wrap : int -> t = -function -| 1 -> Error -| 2 -> Warning -| 3 -> Info -| 4 -> Log -| x -> Unknown x +let wrap : int -> t = function + | 1 -> Error + | 2 -> Warning + | 3 -> Info + | 4 -> Log + | x -> Unknown x -let unwrap : t -> int = -function -| Error -> 1 -| Warning -> 2 -| Info -> 3 -| Log -> 4 -| Unknown x -> x +let unwrap : t -> int = function + | Error -> 1 + | Warning -> 2 + | Info -> 3 + | Log -> 4 + | Unknown x -> x From cf140bf1837aaecdaa6c0ab297a5eb36a58e0fb2 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Fri, 7 Jun 2019 17:35:31 -0700 Subject: [PATCH 0151/1176] Port to dune --- default.nix | 5 ++--- src/Structure.md | 9 +++++++++ src/exes/dune | 2 +- src/languageServer/dune | 4 ++++ src/{ => languageServer}/languageServer.ml | 8 +++++++- src/lsp.mlpack | 3 --- src/lsp/dune | 16 ++++++++++++++++ src/{ => lsp}/lsp.atd | 10 +++++----- 8 files changed, 44 insertions(+), 13 deletions(-) create mode 100644 src/languageServer/dune rename src/{ => languageServer}/languageServer.ml (97%) delete mode 100644 src/lsp.mlpack create mode 100644 src/lsp/dune rename src/{ => lsp}/lsp.atd (95%) diff --git a/default.nix b/default.nix index 958dc3c6a74..247d5db2784 100644 --- a/default.nix +++ b/default.nix @@ -30,8 +30,6 @@ let ocaml_vlq = import ./nix/ocaml-vlq.nix { let ocaml_bisect_ppx = import ./nix/ocaml-bisect_ppx.nix nixpkgs; in let ocaml_bisect_ppx-ocamlbuild = import ./nix/ocaml-bisect_ppx-ocamlbuild.nix nixpkgs; in -let ocamlbuild-atdgen = import ./nix/ocamlbuild-atdgen.nix nixpkgs; in - # Include dvm let real-dvm = if dvm == null @@ -49,9 +47,9 @@ let real-dvm = let commonBuildInputs = [ nixpkgs.ocaml + nixpkgs.dune nixpkgs.ocamlPackages.atdgen nixpkgs.ocamlPackages.base - nixpkgs.ocamlPackages.dune nixpkgs.ocamlPackages.findlib nixpkgs.ocamlPackages.menhir nixpkgs.ocamlPackages.num @@ -157,6 +155,7 @@ rec { "dune-project" "dune" "[a-z].*/" + ".*.atd" ".*.ml" ".*.mly" ".*.mll" diff --git a/src/Structure.md b/src/Structure.md index 12a11d0e3da..bcb5e6874c0 100644 --- a/src/Structure.md +++ b/src/Structure.md @@ -35,3 +35,12 @@ We split the files into the following subdirectories * `idllib/` Kitchen-sink of `didc` related files. Will likely be split soon. + + * `lsp/` + + Language Server Protocol JSON mapping. + + * `languageServer/` + + The language server functionality itself. + diff --git a/src/exes/dune b/src/exes/dune index 402750dce17..255f52a870e 100644 --- a/src/exes/dune +++ b/src/exes/dune @@ -1,7 +1,7 @@ (executable (name asc) (modules asc) - (libraries aslib) + (libraries aslib languageServer) ) (executable (name as_ld) diff --git a/src/languageServer/dune b/src/languageServer/dune new file mode 100644 index 00000000000..563d5b72663 --- /dev/null +++ b/src/languageServer/dune @@ -0,0 +1,4 @@ +(library + (name languageServer) + (libraries aslib base lsp) +) diff --git a/src/languageServer.ml b/src/languageServer/languageServer.ml similarity index 97% rename from src/languageServer.ml rename to src/languageServer/languageServer.ml index 75aedd8808c..bae62920f44 100644 --- a/src/languageServer.ml +++ b/src/languageServer/languageServer.ml @@ -1,6 +1,12 @@ +module Diag = Aslib.Diag +module Lsp_j = Lsp.Lsp_j +module Lsp_t = Lsp.Lsp_t +module Pipeline = Aslib.Pipeline +module Source = Aslib.Source + (* Ideally the following functions would be in the `Lsp` module, but doing so creates a circular dependency with the `Lsp_t` module generated by ATD. -*) + *) let jsonrpc_version : string = "2.0" diff --git a/src/lsp.mlpack b/src/lsp.mlpack deleted file mode 100644 index de44a4d2755..00000000000 --- a/src/lsp.mlpack +++ /dev/null @@ -1,3 +0,0 @@ -AtdAdapters -DiagnosticSeverity -MessageType diff --git a/src/lsp/dune b/src/lsp/dune new file mode 100644 index 00000000000..360b0f1f095 --- /dev/null +++ b/src/lsp/dune @@ -0,0 +1,16 @@ +(library + (name lsp) + (libraries atdgen) +) + +(rule + (targets lsp_j.ml lsp_j.mli) + (deps lsp.atd) + (action (run atdgen -j -j-std %{deps})) +) + +(rule + (targets lsp_t.ml lsp_t.mli) + (deps lsp.atd) + (action (run atdgen -t %{deps})) +) diff --git a/src/lsp.atd b/src/lsp/lsp.atd similarity index 95% rename from src/lsp.atd rename to src/lsp/lsp.atd index cb6f8f41c3c..f9e558a045b 100644 --- a/src/lsp.atd +++ b/src/lsp/lsp.atd @@ -15,7 +15,7 @@ type notification_message = { inherit message; params : notification_message_params; } - + @@ -34,7 +34,7 @@ type incoming_message = { ?id : int nullable; params : incoming_message_params; } - + (* All tags must also provide params, even if they are an `empty_record` *) @@ -62,7 +62,7 @@ type response_message = { ?result : response_result nullable; (* ?error : response_error nullable; *) } - + type response_result = [ @@ -256,7 +256,7 @@ type diagnostic = { } -type diagnostic_severity = int wrap +type diagnostic_severity = int wrap type diagnostic_related_information = { location : location; @@ -272,7 +272,7 @@ type window_show_message_params = { } -type message_type = int wrap +type message_type = int wrap (* Helpers *) From 4bc1d7d16d0a97628d77149530353a28d86a5b40 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Mon, 10 Jun 2019 10:42:09 -0700 Subject: [PATCH 0152/1176] Remove ocamlbuild-atdgen --- nix/ocamlbuild-atdgen.nix | 33 --------------------------------- 1 file changed, 33 deletions(-) delete mode 100644 nix/ocamlbuild-atdgen.nix diff --git a/nix/ocamlbuild-atdgen.nix b/nix/ocamlbuild-atdgen.nix deleted file mode 100644 index cfb0f7cd8d9..00000000000 --- a/nix/ocamlbuild-atdgen.nix +++ /dev/null @@ -1,33 +0,0 @@ -pkgs: - -let repo = "ocamlbuild-atdgen"; in -let rev = "v0.1.0"; in - -pkgs.stdenv.mkDerivation { - name = "ocaml${pkgs.ocaml.version}-${repo}-${rev}"; - - src = pkgs.fetchFromGitHub { - inherit repo rev; - owner = "rgrinberg"; - sha256 = "0wxgvgb8j6ajdzqwzxldvnwfblgbkhgycwmrkmrq8dcjim0mg8ah"; - }; - - buildInputs = with pkgs; [ - ocaml - ocamlPackages.findlib - ocamlPackages.ocamlbuild - ]; - - createFindlibDestdir = true; - - installPhase = '' - make install - ''; - - meta = { - homepage = https://github.com/rgrinberg/ocamlbuild-atdgen; - platforms = pkgs.ocaml.meta.platforms or []; - description = "ocamlbuild plugin for atdgen"; - license = pkgs.stdenv.lib.licenses.isc; - }; -} From e9eb4399136d54b070232759d4e51b7ecd096df9 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 11 Jun 2019 09:31:10 +0200 Subject: [PATCH 0153/1176] Use the IDL value format (`M`) as the temporary wire format (#458) * Serialize `Int` using sleb128 * Use leb128 encoding in the temporary wire format * Use a reference array, not a reference table * Sort object fields and variant constructors based on the IDL hash * Update TmpWriteFormat documentation accordingly Also: * Clean up data-parameters.as a bit I use this test a lot, and there was too much repetition for the word types. Also add tests with negative numbers, and very large numbers. --- design/TmpWireFormat.md | 38 +-- rts/Makefile | 2 +- rts/rts.c | 112 +++++++ src/aslib/compile.ml | 274 +++++++++++------- src/aslib/idlHash.ml | 8 + src/aslib/idlHash.mli | 1 + src/aslib/prelude.ml | 4 + test/run-dfinity/data-params.as | 164 ++--------- test/run-dfinity/ok/data-params.dvm-run.ok | 39 +-- test/run-dfinity/ok/data-params.run-ir.ok | 43 +-- test/run-dfinity/ok/data-params.run-low.ok | 43 +-- test/run-dfinity/ok/data-params.run.ok | 43 +-- test/run-dfinity/ok/data-params.tc.ok | 4 +- .../run-dfinity/ok/data-params.wasm.stderr.ok | 4 +- 14 files changed, 367 insertions(+), 412 deletions(-) create mode 100644 src/aslib/idlHash.ml create mode 100644 src/aslib/idlHash.mli diff --git a/design/TmpWireFormat.md b/design/TmpWireFormat.md index 2ae4e9e028c..253ceb7242b 100644 --- a/design/TmpWireFormat.md +++ b/design/TmpWireFormat.md @@ -40,30 +40,34 @@ General argument format (without references) Arguments with a type that does not mention any reference types (no actors, no shared functions), are represented as a `databuf`. This `databuf` is generated -by an in-order traversal of the data type. All numbers are fixed-width and in -little endian format. +by an in-order traversal of the data type. All numbers are in little endian +format. - * A `Nat`, `Int` or `Word64` is represented by 8 bytes. + * A `Nat` is represented by its shortest [LEB128 encoding] + * An `Int` is represented by its shortest [SLEB128 encoding] + * A `Word64` is represented by 8 bytes. * A `Word32` is represented by 4 bytes. * A `Word16` is represented by 2 bytes. * A `Word8` is represented by 1 byte. * A `Bool` is represented by 1 byte that is `0` for `false` and `1` for `true`. - * A `Text` is represented by 4 bytes indicating the length of the following - payload, followed by the payload as a utf8-encoded string (no trailing `\0`). - * An `Array` is represented by 4 bytes indicating the number of entries, - followed by the concatenation of the representation of these entries. + * A `Text` is represented by a LEB128-encoded number indicating the length of + the following payload, followed by the payload as a utf8-encoded string (no + trailing `\0`). + * An `Array` is represented by a LEB128-encoded number indicating the number + of entries, followed by the concatenation of the representation of these + entries. * A `Tuple` is represented by the concatenation of the representation of its entries. (No need for a length field, as it can be statically determined.) * An `Object` is represented by the concatenation of the representation of its - fields, sorted by field name. (The field names are not serialized, as they - are statically known.) + fields, sorted by IDL hash of the field name. + (The field names are not serialized, as they are statically known.) * An `Option` is represented by a single byte `0` if it is `null`, or otherwise by a single byte `1` followed by the representation of the value * An empty tuple, the type `Null` and the type `Shared` are represented by zero bytes. - * A `Variant` with `n` constructors sorted by constructor name is represented - by a single 32-bit word indicating the constructor as a number `0..n-1`, followed - by the payload of the constructor. (Yes, obviously no subtyping here.) + * A `Variant` with `n` constructors sorted by IDL hash of the constructor name + is represented by a LEB128-encoded number the constructor as a number + `0..n-1`, followed by the payload of the constructor. *Example:* The ActorScript value ``` @@ -74,6 +78,8 @@ is represented as 00 01 04 00 00 00 00 00 00 00 01 21 ``` +[LEB128 encoding](https://en.wikipedia.org/wiki/LEB128) + General argument format (with references) ----------------------------------------- @@ -86,11 +92,9 @@ are represented as an `elembuf`: The above format is thus extended with the following case: - * A reference (`actor`, `shared func`) is represented as a 32-bit number (4 - bytes). Thus number is an index into the surrounding `elembuf`. + * A reference (`actor`, `shared func`) is represented as zero bytes in the data + buffer, and writing the reference into the next position in `elembuf`. - NB: The index is never never `0`, as the first entry in the `elembuf` is the - `databuf` with the actual data. *Example:* The ActorScript value ``` @@ -98,5 +102,5 @@ The above format is thus extended with the following case: ``` is represented as ``` -elembuf [databuf [00 01 01 00 00 00], console] +elembuf [databuf [00 01], console] ``` diff --git a/rts/Makefile b/rts/Makefile index f54942cc82a..706419c32aa 100644 --- a/rts/Makefile +++ b/rts/Makefile @@ -6,7 +6,7 @@ TOMMATHFILES=\ mp_div mp_init_copy mp_get_int mp_get_long mp_set_long_long mp_get_long_long mp_neg mp_abs mp_2expt mp_expt_d_ex mp_set mp_sqr \ s_mp_add mp_cmp_mag s_mp_sub mp_grow mp_clamp \ mp_init_size mp_exch mp_clear mp_copy mp_count_bits mp_mul_2d mp_rshd mp_mul_d mp_div_2d mp_mod_2d \ - s_mp_balance_mul s_mp_toom_mul s_mp_toom_sqr s_mp_karatsuba_sqr s_mp_sqr_fast s_mp_sqr s_mp_karatsuba_mul s_mp_mul_digs_fast s_mp_mul_digs mp_init_multi mp_clear_multi mp_mul_2 mp_div_2 mp_div_3 mp_lshd + s_mp_balance_mul s_mp_toom_mul s_mp_toom_sqr s_mp_karatsuba_sqr s_mp_sqr_fast s_mp_sqr s_mp_karatsuba_mul s_mp_mul_digs_fast s_mp_mul_digs mp_init_multi mp_clear_multi mp_mul_2 mp_div_2 mp_div_3 mp_lshd mp_incr mp_decr mp_add_d mp_sub_d TOMMATH_O=$(patsubst %,_build/tommath_%.o,$(TOMMATHFILES)) diff --git a/rts/rts.c b/rts/rts.c index d5d563073c0..3156b1c1c2e 100644 --- a/rts/rts.c +++ b/rts/rts.c @@ -349,3 +349,115 @@ export as_ptr bigint_lsh(as_ptr a, int b) { export int bigint_count_bits(as_ptr a) { return mp_count_bits(BIGINT_PAYLOAD(a)); } + +/* LEB128 Encoding-decoding */ +export int bigint_leb128_size(as_ptr n) { + if (mp_iszero(BIGINT_PAYLOAD(n))) return 1; + int x = bigint_count_bits(n); + return ((x + 6) / 7); // divide by 7, round up +} + +void leb128_encode_go(mp_int *tmp, unsigned char *buf) { + // now the number should be positive + if (mp_isneg(tmp)) bigint_trap(); + while (true) { + buf[0] = (char)(mp_get_int(tmp)); // get low bits + CHECK(mp_div_2d(tmp, 7, tmp, NULL)); + if (mp_iszero(tmp)) { + // we are done. high bit should be cleared anyways + return; + } else { + // more bytes to come, set high bit and continue + buf[0] |= 1<<7; + buf++; + } + } +} + +export void bigint_leb128_encode(as_ptr n, unsigned char *buf) { + mp_int tmp; + CHECK(mp_init_copy(&tmp, BIGINT_PAYLOAD(n))); + leb128_encode_go(&tmp, buf); +} + + +int leb128_encoding_size(unsigned char *buf) { + // zoom to the end + int i = 0; + while (buf[i] & (1<<7)) i++; + return i+1; +} + +as_ptr leb128_decode_go(unsigned char *buf, int bytes) { + // do not accept overlong encodings + if (buf[bytes-1] == 1<<7) bigint_trap(); + + as_ptr r = bigint_alloc(); + CHECK(mp_init(BIGINT_PAYLOAD(r))); + int i = bytes-1; + while (true) { + CHECK(mp_add_d(BIGINT_PAYLOAD(r), buf[i] & ((1<<7)-1), BIGINT_PAYLOAD(r))); + if (i > 0) { + CHECK(mp_mul_2d(BIGINT_PAYLOAD(r), 7, BIGINT_PAYLOAD(r))); + i--; + } else { + break; + } + } + return r; +} + +export as_ptr bigint_leb128_decode(unsigned char *buf) { + int bytes = leb128_encoding_size(buf); + return leb128_decode_go(buf, bytes); +} + +/* SLEB128 Encoding-decoding */ +export int bigint_2complement_bits(as_ptr n) { + if (mp_isneg(BIGINT_PAYLOAD(n))) { + mp_int tmp; + CHECK(mp_init_copy(&tmp, BIGINT_PAYLOAD(n))); + CHECK(mp_incr(&tmp)); + return 1 + mp_count_bits(&tmp); + } else { + return 1 + mp_count_bits(BIGINT_PAYLOAD(n)); + } +} + +export int bigint_sleb128_size(as_ptr n) { + int x = bigint_2complement_bits(n); + return ((x + 6) / 7); // divide by 7, round up +} + +export void bigint_sleb128_encode(as_ptr n, unsigned char *buf) { + mp_int tmp; + CHECK(mp_init_copy(&tmp, BIGINT_PAYLOAD(n))); + + if (mp_isneg(&tmp)) { + // turn negative numbers into the two's complement of the right size + int bytes = bigint_sleb128_size(n); + mp_int big; + CHECK(mp_init(&big)); + CHECK(mp_2expt(&big, 7*bytes)); + CHECK(mp_add(&tmp, &big, &tmp)); + } + + leb128_encode_go(&tmp, buf); +} + +export as_ptr bigint_sleb128_decode(unsigned char *buf) { + int bytes = leb128_encoding_size(buf); + + as_ptr r = leb128_decode_go(buf, bytes); + + // Now adjust sign if necessary + if (buf[bytes-1] & (1<<6)) { + // negative number + mp_int big; + CHECK(mp_init(&big)); + CHECK(mp_2expt(&big, 7*bytes)); + CHECK(mp_sub(BIGINT_PAYLOAD(r), &big, BIGINT_PAYLOAD(r))); + } + + return r; +} diff --git a/src/aslib/compile.ml b/src/aslib/compile.ml index 1ff783e410e..623703a96c9 100644 --- a/src/aslib/compile.ml +++ b/src/aslib/compile.ml @@ -524,7 +524,7 @@ module RTS = struct E.add_func_import env "rts" "bigint_to_word64_signed_trap" [I32Type] [I64Type]; E.add_func_import env "rts" "bigint_eq" [I32Type; I32Type] [I32Type]; E.add_func_import env "rts" "bigint_isneg" [I32Type] [I32Type]; - E.add_func_import env "rts" "bigint_count_bits" [I32Type] [I32Type]; + E.add_func_import env "rts" "bigint_2complement_bits" [I32Type] [I32Type]; E.add_func_import env "rts" "bigint_lt" [I32Type; I32Type] [I32Type]; E.add_func_import env "rts" "bigint_gt" [I32Type; I32Type] [I32Type]; E.add_func_import env "rts" "bigint_le" [I32Type; I32Type] [I32Type]; @@ -537,7 +537,13 @@ module RTS = struct E.add_func_import env "rts" "bigint_pow" [I32Type; I32Type] [I32Type]; E.add_func_import env "rts" "bigint_neg" [I32Type] [I32Type]; E.add_func_import env "rts" "bigint_lsh" [I32Type; I32Type] [I32Type]; - E.add_func_import env "rts" "bigint_abs" [I32Type] [I32Type] + E.add_func_import env "rts" "bigint_abs" [I32Type] [I32Type]; + E.add_func_import env "rts" "bigint_leb128_size" [I32Type] [I32Type]; + E.add_func_import env "rts" "bigint_leb128_encode" [I32Type; I32Type] []; + E.add_func_import env "rts" "bigint_leb128_decode" [I32Type] [I32Type]; + E.add_func_import env "rts" "bigint_sleb128_size" [I32Type] [I32Type]; + E.add_func_import env "rts" "bigint_sleb128_encode" [I32Type; I32Type] []; + E.add_func_import env "rts" "bigint_sleb128_decode" [I32Type] [I32Type] let system_exports env = E.add_export env (nr { @@ -1189,7 +1195,8 @@ module BoxedWord = struct (* from/to SR.UnboxedWord64 *) let to_word64 env = G.nop - let from_word64 env = G.nop + let from_word64 env = G.nop (* TODO trap if negative *) + let from_signed_word64 env = G.nop let to_word32 env = G.i (Convert (Wasm.Values.I32 I32Op.WrapI64)) let from_word32 env = G.i (Convert (Wasm.Values.I64 I64Op.ExtendUI32)) let from_signed_word32 env = G.i (Convert (Wasm.Values.I64 I64Op.ExtendSI32)) @@ -1414,27 +1421,31 @@ sig val from_word64 : E.t -> G.t (* signed word to SR.Vanilla *) + val from_signed_word64 : E.t -> G.t val from_signed_word32 : E.t -> G.t (* buffers *) (* given a numeric object on stack (vanilla), push the number (i32) of bytes necessary to externalize the numeric object *) - val compile_data_size : E.t -> G.t + val compile_data_size_signed : E.t -> G.t + val compile_data_size_unsigned : E.t -> G.t (* given on stack - numeric object (vanilla, TOS) - data buffer store the binary representation of the numeric object into the data buffer, and push the number (i32) of bytes stored onto the stack *) - val compile_store_to_data_buf : E.t -> G.t + val compile_store_to_data_buf_signed : E.t -> G.t + val compile_store_to_data_buf_unsigned : E.t -> G.t (* given a data buffer on stack, consume bytes from it, deserializing to a numeric object and leave two words on stack: - number of consumed bytes (i32, TOS) - numeric object (vanilla) *) - val compile_load_from_data_buf : E.t -> G.t + val compile_load_from_data_buf_signed : E.t -> G.t + val compile_load_from_data_buf_unsigned : E.t -> G.t (* literals *) val compile_lit : E.t -> Big_int.big_int -> G.t @@ -1520,17 +1531,20 @@ module BigNum64 : BigNumType = struct let compile_lit env n = compile_const_64 (Big_int.int64_of_big_int n) ^^ box env - let compile_data_size env = G.i Drop ^^ compile_unboxed_const 8l (* 64 bit for now *) + let compile_data_size_signed env = G.i Drop ^^ compile_unboxed_const 8l (* 64 bit for now *) + let compile_data_size_unsigned = compile_data_size_signed - let compile_store_to_data_buf env = + let compile_store_to_data_buf_unsigned env = unbox env ^^ G.i (Store {ty = I64Type; align = 0; offset = 0l; sz = None}) ^^ compile_unboxed_const 8l (* 64 bit for now *) + let compile_store_to_data_buf_signed = compile_store_to_data_buf_unsigned - let compile_load_from_data_buf env = + let compile_load_from_data_buf_signed env = G.i (Load {ty = I64Type; align = 2; offset = 0l; sz = None}) ^^ box env ^^ compile_unboxed_const 8l (* 64 bit for now *) + let compile_load_from_data_buf_unsigned = compile_load_from_data_buf_signed let compile_abs env = let (set_i, get_i) = new_local env "abs_param" in @@ -1596,18 +1610,36 @@ module BigNumLibtommmath : BigNumType = struct let from_word32 env = E.call_import env "rts" "bigint_of_word32" let from_word64 env = E.call_import env "rts" "bigint_of_word64" let from_signed_word32 env = E.call_import env "rts" "bigint_of_word32_signed" - let _from_signed_word64 env = E.call_import env "rts" "bigint_of_word64_signed" + let from_signed_word64 env = E.call_import env "rts" "bigint_of_word64_signed" - (* TODO: Actually change binary encoding *) - let compile_data_size env = G.i Drop ^^ compile_unboxed_const 8l - let compile_store_to_data_buf env = - _truncate_to_word64 env ^^ - G.i (Store {ty = I64Type; align = 0; offset = 0l; sz = None}) ^^ - compile_unboxed_const 8l (* 64 bit for now *) - let compile_load_from_data_buf env = - G.i (Load {ty = I64Type; align = 2; offset = 0l; sz = None}) ^^ - from_word64 env ^^ - compile_unboxed_const 8l (* 64 bit for now *) + let compile_data_size_unsigned env = E.call_import env "rts" "bigint_leb128_size" + let compile_data_size_signed env = E.call_import env "rts" "bigint_sleb128_size" + + let compile_store_to_data_buf_unsigned env = + let (set_buf, get_buf) = new_local env "buf" in + let (set_n, get_n) = new_local env "n" in + set_n ^^ set_buf ^^ + get_n ^^ get_buf ^^ E.call_import env "rts" "bigint_leb128_encode" ^^ + get_n ^^ E.call_import env "rts" "bigint_leb128_size" + let compile_store_to_data_buf_signed env = + let (set_buf, get_buf) = new_local env "buf" in + let (set_n, get_n) = new_local env "n" in + set_n ^^ set_buf ^^ + get_n ^^ get_buf ^^ E.call_import env "rts" "bigint_sleb128_encode" ^^ + get_n ^^ E.call_import env "rts" "bigint_sleb128_size" + + let compile_load_from_data_buf_unsigned env = + E.call_import env "rts" "bigint_leb128_decode" ^^ + let (set_n, get_n) = new_local env "n" in + set_n ^^ + get_n ^^ + get_n ^^ E.call_import env "rts" "bigint_leb128_size" + let compile_load_from_data_buf_signed env = + E.call_import env "rts" "bigint_sleb128_decode" ^^ + let (set_n, get_n) = new_local env "n" in + set_n ^^ + get_n ^^ + get_n ^^ E.call_import env "rts" "bigint_sleb128_size" let compile_lit env n = let limb_size = 31 in @@ -1665,7 +1697,7 @@ module BigNumLibtommmath : BigNumType = struct G.i (Call (nr (E.built_in env fn))) let _fits_signed_bits env bits = - G.i (Call (nr (E.built_in env ("rts_bigint_count_bits")))) ^^ + G.i (Call (nr (E.built_in env ("rts_bigint_2complement_bits")))) ^^ compile_unboxed_const (Int32.of_int (bits - 1)) ^^ G.i (Compare (Wasm.Values.I32 I32Op.LeU)) let _fits_unsigned_bits env bits = @@ -2736,7 +2768,16 @@ module Serialization = struct *) let typ_id : Type.typ -> string = Type.string_of_typ + let unsigned_compare i1 i2 = + (* int32 is signed, but we want unsigned comparision *) + if i1 < 0l && i2 >= 0l then 1 + else if i1 >= 0l && i2 < 0l then -1 + else compare i1 i2 + let sort_by_hash fs = + List.sort + (fun (h1,_) (h2,_) -> unsigned_compare h1 h2) + (List.map (fun f -> (IdlHash.idl_hash f.Type.lab, f)) fs) (* Checks whether the serialization of a given type could contain references *) module TS = Set.Make (struct type t = Type.typ let compare = compare end) @@ -2773,6 +2814,15 @@ module Serialization = struct end in go t + (* TODO (leb128 for i32): + All leb128 currently goes through bignum. This is of course + absurdly expensive and round-about, but I want _one_ implementation + first that I can test, until we properly exercise this code (i.e. there + is also the JS-side of things and we know it is bug-free). + Writing a Wasm-native implementation of this will then be done separately. + *) + + (* Returns data (in bytes) and reference buffer size (in entries) needed *) let rec buffer_size env t = let open Type in @@ -2796,6 +2846,11 @@ module Serialization = struct get_ref_size ^^ compile_add_const i ^^ set_ref_size in + (* See TODO (leb128 for i32) *) + let size_word env code = + inc_data_size (code ^^ BigNum.from_word32 env ^^ BigNum.compile_data_size_unsigned env) + in + let size env t = buffer_size env t ^^ get_ref_size ^^ G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ set_ref_size ^^ @@ -2804,7 +2859,8 @@ module Serialization = struct (* Now the actual type-dependent code *) begin match t with - | Prim (Nat|Int) -> inc_data_size (get_x ^^ BigNum.compile_data_size env) + | Prim Nat -> inc_data_size (get_x ^^ BigNum.compile_data_size_unsigned env) + | Prim Int -> inc_data_size (get_x ^^ BigNum.compile_data_size_signed env) | Prim Word64 -> inc_data_size (compile_unboxed_const 8l) (* 64 bit *) | Prim Word8 -> inc_data_size (compile_unboxed_const 1l) | Prim Word16 -> inc_data_size (compile_unboxed_const 2l) @@ -2816,45 +2872,37 @@ module Serialization = struct size env t ) ts | Obj (Object Sharable, fs) -> - (* Disregarding all subtyping, and assuming sorted fields, we can just - treat this like a tuple *) - G.concat_mapi (fun i f -> + G.concat_map (fun (_h, f) -> get_x ^^ Object.load_idx env t f.Type.lab ^^ size env f.typ - ) fs + ) (sort_by_hash fs) | Array t -> - inc_data_size (compile_unboxed_const Heap.word_size) ^^ (* 32 bit length field *) - get_x ^^ - Heap.load_field Arr.len_field ^^ + size_word env (get_x ^^ Heap.load_field Arr.len_field) ^^ + get_x ^^ Heap.load_field Arr.len_field ^^ from_0_to_n env (fun get_i -> get_x ^^ get_i ^^ Arr.idx env ^^ load_ptr ^^ size env t ) | Prim Text -> - inc_data_size ( - compile_unboxed_const Heap.word_size ^^ (* 32 bit length field *) - get_x ^^ Heap.load_field Text.len_field ^^ - G.i (Binary (Wasm.Values.I32 I32Op.Add)) - ) + size_word env (get_x ^^ Heap.load_field Text.len_field) ^^ + inc_data_size (get_x ^^ Heap.load_field Text.len_field) | (Prim Null | Shared) -> G.nop | Opt t -> inc_data_size (compile_unboxed_const 1l) ^^ (* one byte tag *) - get_x ^^ - Opt.is_some env ^^ + get_x ^^ Opt.is_some env ^^ G.if_ (ValBlockType None) (get_x ^^ Opt.project ^^ size env t) G.nop | Variant vs -> - inc_data_size (compile_unboxed_const 4l) ^^ (* one word tag *) - List.fold_right (fun {lab = l; typ = t} continue -> + List.fold_right (fun (i, {lab = l; typ = t}) continue -> get_x ^^ Variant.test_is env l ^^ G.if_ (ValBlockType None) - ( get_x ^^ Variant.project ^^ size env t) - continue + ( size_word env (compile_unboxed_const (Int32.of_int i)) ^^ + get_x ^^ Variant.project ^^ size env t + ) continue ) - vs + ( List.mapi (fun i (_h, f) -> (i,f)) (sort_by_hash vs) ) ( E.trap_with env "buffer_size: unexpected variant" ) | (Func _ | Obj (Actor, _)) -> - inc_data_size (compile_unboxed_const Heap.word_size) ^^ inc_ref_size 1l | Non -> E.trap_with env "buffer_size called on value of type None" @@ -2869,22 +2917,24 @@ module Serialization = struct let open Type in let t = normalize t in let name = "@serialize_go<" ^ typ_id t ^ ">" in - Func.share_code4 env name (("x", I32Type), ("data_buffer", I32Type), ("ref_base", I32Type), ("ref_count" , I32Type)) [I32Type; I32Type] - (fun env get_x get_data_buf get_ref_base get_ref_count -> + Func.share_code3 env name (("x", I32Type), ("data_buffer", I32Type), ("ref_buffer", I32Type)) [I32Type; I32Type] + (fun env get_x get_data_buf get_ref_buf -> let set_data_buf = G.i (LocalSet (nr 1l)) in - let set_ref_count = G.i (LocalSet (nr 3l)) in + let set_ref_buf = G.i (LocalSet (nr 2l)) in (* Some combinators for writing values *) let advance_data_buf = get_data_buf ^^ G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ set_data_buf in - let allocate_ref = - get_ref_count ^^ - get_ref_count ^^ compile_add_const 1l ^^ set_ref_count in + let advance_ref_buf = + get_ref_buf ^^ compile_add_const Heap.word_size ^^ set_ref_buf in let write_word code = - get_data_buf ^^ code ^^ store_unskewed_ptr ^^ - compile_unboxed_const Heap.word_size ^^ advance_data_buf + (* See TODO (leb128 for i32) *) + get_data_buf ^^ + code ^^ BigNum.from_word32 env ^^ + BigNum.compile_store_to_data_buf_unsigned env ^^ + advance_data_buf in let write_byte code = @@ -2895,20 +2945,24 @@ module Serialization = struct let write env t = get_data_buf ^^ - get_ref_base ^^ - get_ref_count ^^ + get_ref_buf ^^ serialize_go env t ^^ - set_ref_count ^^ + set_ref_buf ^^ set_data_buf in (* Now the actual serialization *) begin match t with - | Prim (Nat | Int) -> + | Prim Nat -> get_data_buf ^^ get_x ^^ - BigNum.compile_store_to_data_buf env ^^ + BigNum.compile_store_to_data_buf_unsigned env ^^ + advance_data_buf + | Prim Int -> + get_data_buf ^^ + get_x ^^ + BigNum.compile_store_to_data_buf_signed env ^^ advance_data_buf | Prim Word64 -> get_data_buf ^^ @@ -2941,12 +2995,10 @@ module Serialization = struct write env t ) ts | Obj (Object Sharable, fs) -> - (* Disregarding all subtyping, and assuming sorted fields, we can just - treat this like a tuple *) - G.concat_mapi (fun i f -> + G.concat_map (fun (_h,f) -> get_x ^^ Object.load_idx env t f.Type.lab ^^ write env f.typ - ) fs + ) (sort_by_hash fs) | Array t -> write_word (get_x ^^ Heap.load_field Arr.len_field) ^^ get_x ^^ Heap.load_field Arr.len_field ^^ @@ -2970,48 +3022,45 @@ module Serialization = struct get_x ^^ Variant.project ^^ write env t) continue ) - ( List.mapi (fun i f -> (i,f)) vs ) + ( List.mapi (fun i (_h, f) -> (i,f)) (sort_by_hash vs) ) ( E.trap_with env "serialize_go: unexpected variant" ) | Prim Text -> let (set_len, get_len) = new_local env "len" in - get_x ^^ Heap.load_field Text.len_field ^^ - compile_add_const Heap.word_size ^^ - set_len ^^ + get_x ^^ Heap.load_field Text.len_field ^^ set_len ^^ + + write_word get_len ^^ get_data_buf ^^ - get_x ^^ compile_add_const (Int32.mul Tagged.header_size Heap.word_size) ^^ - compile_add_const ptr_unskew ^^ + get_x ^^ Text.payload_ptr_unskewed ^^ get_len ^^ Heap.memcpy env ^^ get_len ^^ advance_data_buf | (Func _ | Obj (Actor, _)) -> - get_ref_base ^^ - get_ref_count ^^ compile_mul_const Heap.word_size ^^ - G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ + get_ref_buf ^^ get_x ^^ Dfinity.unbox_reference env ^^ store_unskewed_ptr ^^ - write_word allocate_ref + advance_ref_buf | Non -> E.trap_with env "serializing value of type None" | _ -> todo "serialize" (Arrange_ir.typ t) G.nop end ^^ get_data_buf ^^ - get_ref_count + get_ref_buf ) let rec deserialize_go env t = let open Type in let t = normalize t in let name = "@deserialize_go<" ^ typ_id t ^ ">" in - Func.share_code2 env name (("data_buffer", I32Type), ("ref_base", I32Type)) [I32Type; I32Type] - (fun env get_data_buf get_ref_base -> + Func.share_code2 env name (("data_buffer", I32Type), ("ref_buffer", I32Type)) [I32Type; I32Type; I32Type] + (fun env get_data_buf get_ref_buf -> let set_data_buf = G.i (LocalSet (nr 0l)) in + let set_ref_buf = G.i (LocalSet (nr 1l)) in (* Some combinators for reading values *) let advance_data_buf = - get_data_buf ^^ - G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ - set_data_buf - in + get_data_buf ^^ G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ set_data_buf in + let advance_ref_buf = + get_ref_buf ^^ compile_add_const Heap.word_size ^^ set_ref_buf in let read_byte = get_data_buf ^^ @@ -3020,22 +3069,30 @@ module Serialization = struct in let read_word = - get_data_buf ^^ load_unskewed_ptr ^^ - compile_unboxed_const Heap.word_size ^^ advance_data_buf + (* See TODO (leb128 for i32) *) + get_data_buf ^^ + BigNum.compile_load_from_data_buf_unsigned env ^^ + advance_data_buf ^^ + BigNum.to_word32 env in let read env t = get_data_buf ^^ - get_ref_base ^^ + get_ref_buf ^^ deserialize_go env t ^^ + set_ref_buf ^^ set_data_buf in (* Now the actual deserialization *) begin match t with - | Prim (Nat | Int) -> + | Prim Nat -> get_data_buf ^^ - BigNum.compile_load_from_data_buf env ^^ + BigNum.compile_load_from_data_buf_unsigned env ^^ + advance_data_buf + | Prim Int -> + get_data_buf ^^ + BigNum.compile_load_from_data_buf_signed env ^^ advance_data_buf | Prim Word64 -> get_data_buf ^^ @@ -3065,11 +3122,9 @@ module Serialization = struct G.concat_map (fun t -> read env t) ts ^^ Tuple.from_stack env (List.length ts) | Obj (Object Sharable, fs) -> - (* Disregarding all subtyping, and assuming sorted fields, we can just - treat this like a tuple *) - Object.lit_raw env (List.map (fun f -> + Object.lit_raw env (List.map (fun (_h,f) -> f.Type.lab, fun () -> read env f.typ - ) fs) + ) (sort_by_hash fs)) | Array t -> let (set_len, get_len) = new_local env "len" in let (set_x, get_x) = new_local env "x" in @@ -3098,7 +3153,7 @@ module Serialization = struct ( Variant.inject env l (read env t) ) continue ) - ( List.mapi (fun i f -> (i,f)) vs ) + ( List.mapi (fun i (_h, f) -> (i,f)) (sort_by_hash vs) ) ( E.trap_with env "deserialize_go: unexpected variant tag" ) | Prim Text -> let (set_len, get_len) = new_local env "len" in @@ -3116,16 +3171,16 @@ module Serialization = struct get_x | (Func _ | Obj (Actor, _)) -> - get_ref_base ^^ - read_word ^^ compile_mul_const Heap.word_size ^^ - G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ + get_ref_buf ^^ load_unskewed_ptr ^^ - Dfinity.box_reference env + Dfinity.box_reference env ^^ + advance_ref_buf | Non -> E.trap_with env "deserializing value of type None" | _ -> todo_trap env "deserialize" (Arrange_ir.typ t) end ^^ - get_data_buf + get_data_buf ^^ + get_ref_buf ) let serialize env t = @@ -3142,30 +3197,25 @@ module Serialization = struct (* Get object sizes *) get_x ^^ buffer_size env t ^^ + compile_add_const 1l ^^ (* Leave space for databuf *) + compile_mul_const Heap.word_size ^^ set_refs_size ^^ set_data_size ^^ let (set_data_start, get_data_start) = new_local env "data_start" in let (set_refs_start, get_refs_start) = new_local env "refs_start" in - get_data_size ^^ - Text.dyn_alloc_scratch env ^^ - set_data_start ^^ - - get_refs_size ^^ - compile_mul_const Heap.word_size ^^ - Text.dyn_alloc_scratch env ^^ - set_refs_start ^^ + get_data_size ^^ Text.dyn_alloc_scratch env ^^ set_data_start ^^ + get_refs_size ^^ Text.dyn_alloc_scratch env ^^ set_refs_start ^^ (* Serialize x into the buffer *) get_x ^^ get_data_start ^^ - get_refs_start ^^ - compile_unboxed_const 1l ^^ (* Leave space for databuf *) + get_refs_start ^^ compile_add_const Heap.word_size ^^ (* Leave space for databuf *) serialize_go env t ^^ (* Sanity check: Did we fill exactly the buffer *) - get_refs_size ^^ compile_add_const 1l ^^ + get_refs_start ^^ get_refs_size ^^ G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ G.i (Compare (Wasm.Values.I32 I32Op.Eq)) ^^ E.else_trap_with env "reference buffer not filled " ^^ @@ -3184,7 +3234,8 @@ module Serialization = struct then (* Sanity check: Really no references *) get_refs_size ^^ - G.i (Test (Wasm.Values.I32 I32Op.Eqz)) ^^ + compile_unboxed_const Heap.word_size ^^ + G.i (Compare (Wasm.Values.I32 I32Op.Eq)) ^^ E.else_trap_with env "has_no_references wrong" ^^ (* If there are no references, just return the databuf *) get_refs_start ^^ @@ -3192,7 +3243,7 @@ module Serialization = struct else (* Finally, create elembuf *) get_refs_start ^^ - get_refs_size ^^ compile_add_const 1l ^^ + get_refs_size ^^ compile_divU_const Heap.word_size ^^ Dfinity.system_call env "elem_externalize" ) @@ -3284,8 +3335,9 @@ module Serialization = struct (* Go! *) get_data_start ^^ - get_refs_start ^^ + get_refs_start ^^ compile_add_const Heap.word_size ^^ deserialize_go env t ^^ + G.i Drop ^^ G.i Drop ) @@ -4587,6 +4639,10 @@ and compile_exp (env : E.t) ae exp = compile_exp_as env ae SR.unit e ^^ E.call_import env "rts" "version" + | "idlHash" -> + SR.Vanilla, + E.trap_with env "idlHash only implemented in interpreter " + | "Nat->Word8" | "Int->Word8" -> SR.Vanilla, @@ -4643,12 +4699,16 @@ and compile_exp (env : E.t) ae exp = compile_exp_as env ae SR.UnboxedWord32 e ^^ Prim.prim_word32toInt env - | "Word64->Nat" - | "Word64->Int" -> + | "Word64->Nat" -> SR.Vanilla, compile_exp_as env ae SR.UnboxedWord64 e ^^ BigNum.from_word64 env + | "Word64->Int" -> + SR.Vanilla, + compile_exp_as env ae SR.UnboxedWord64 e ^^ + BigNum.from_signed_word64 env + | "Word32->Char" -> SR.Vanilla, compile_exp_as env ae SR.UnboxedWord32 e ^^ diff --git a/src/aslib/idlHash.ml b/src/aslib/idlHash.ml new file mode 100644 index 00000000000..4d03804b8c4 --- /dev/null +++ b/src/aslib/idlHash.ml @@ -0,0 +1,8 @@ +(* IDL field hashes *) +let idl_hash : string -> int32 = fun s -> + let open Int32 in + List.fold_left + (fun s c -> add (mul s 223l) (of_int (Char.code c))) + 0l + (* TODO: also unescape the string, once #465 is approved *) + (Lib.String.explode s) diff --git a/src/aslib/idlHash.mli b/src/aslib/idlHash.mli new file mode 100644 index 00000000000..06bb62ab1c1 --- /dev/null +++ b/src/aslib/idlHash.mli @@ -0,0 +1 @@ +val idl_hash : string -> int32 diff --git a/src/aslib/prelude.ml b/src/aslib/prelude.ml index 09a4138b421..5e4d71d466d 100644 --- a/src/aslib/prelude.ml +++ b/src/aslib/prelude.ml @@ -31,6 +31,9 @@ class revrange(x : Nat, y : Nat) { next() : ?Nat { if (i <= y) null else {i -= 1; ?i} }; }; +// for testing +func idlHash(x : Text) : Word32 { (prim "idlHash" : Text -> Word32) x }; + func charToText(c : Char) : Text = (prim "Char->Text" : Char -> Text) c; func printInt(x : Int) { print (@text_of_Int x) }; @@ -368,6 +371,7 @@ let prim = function in k (Text str) | "print" -> fun v k -> Printf.printf "%s%!" (as_text v); k unit | "rts_version" -> fun v k -> as_unit v; k (Text "0.1") + | "idlHash" -> fun v k -> let s = as_text v in k (Word32 (IdlHash.idl_hash s)) | "decodeUTF8" -> fun v k -> let s = as_text v in let open Int32 in diff --git a/test/run-dfinity/data-params.as b/test/run-dfinity/data-params.as index 9a5e9dcac88..68207c6323d 100644 --- a/test/run-dfinity/data-params.as +++ b/test/run-dfinity/data-params.as @@ -1,5 +1,10 @@ let a = actor { - private var c = 0; + private var c : Int = 0; + inci(n : Int) : () { + c += n; + printInt(c); + print("\n"); + }; incn(n : Nat) : () { c += n; printInt(c); @@ -56,6 +61,13 @@ let a = actor { printInt(c); print("\n"); }; + incwords(w16 : Word16, w32 : Word32, w64 : Word64) : () { + c += word16ToInt(w16); + c += word32ToInt(w32); + c += word64ToInt(w64); + printInt(c); + print("\n"); + }; }; @@ -78,146 +90,10 @@ a.printCounter(); a.printLabeled("Foo1: "); a.printLabeledOpt(?"Foo2: "); a.incn(10000000000000); - - -let w32 = actor { - private var c : Word32 = 0; - incn(n : Word32) : () { - c += n; - printInt(word32ToInt(c)); - print("\n"); - }; - incnn(n1 : Word32, n2 : Word32) : () { - c += n1 + n2; - printInt(word32ToInt(c)); - print("\n"); - }; - incnested(n1 : Word32, (n2 : Word32, n3 : Word32)) : () { - c += n1 + n2 + n3; - printInt(word32ToInt(c)); - print("\n"); - }; - incarray(a : [Word32]) : () { - for (i in a.vals()) { c += i }; - printInt(word32ToInt(c)); - print("\n"); - }; - incopt(a : ?Word32) : () { - switch a { - case null { c += 1000000 }; - case (?a) { c += a }; - }; - printInt(word32ToInt(c)); - print("\n"); - }; - increcord(a : shared { x : Word32; y : Word32 }) : () { - c += a.x; - c += a.y; - printInt(word32ToInt(c)); - print("\n"); - }; - printCounter() { - printInt(word32ToInt(c)); - print("\n"); - }; - printLabeled(l:Text) { - print l; - printInt(word32ToInt(c)); - print("\n"); - }; - printLabeledOpt(?l:?Text) { - print l; - printInt(word32ToInt(c)); - print("\n"); - }; -}; - - -w32.incn(1); -w32.incn(2); -w32.incn(3); -w32.incn(4); -w32.incn(1000); -w32.incnn(5,6); -w32.incnn(2000,3000); -w32.incnested(7,(8,9)); -w32.incarray([10,11,12,13]); -w32.incopt(null); -w32.incopt(?14); -w32.increcord(shared {x = 15 : Word32; y = 16 : Word32}); -w32.increcord(shared {x = 17 : Word32; y = 18 : Word32; z = 19 : Word32}); -w32.printCounter(); -w32.printLabeled("Foo1: "); -w32.printLabeledOpt(?"Foo2: "); - - - -let w16 = actor { - private var c : Word16 = 0; - incn(n : Word16) : () { - c += n; - printInt(word16ToInt(c)); - print("\n"); - }; - incnn(n1 : Word16, n2 : Word16) : () { - c += n1 + n2; - printInt(word16ToInt(c)); - print("\n"); - }; - incnested(n1 : Word16, (n2 : Word16, n3 : Word16)) : () { - c += n1 + n2 + n3; - printInt(word16ToInt(c)); - print("\n"); - }; - incarray(a : [Word16]) : () { - for (i in a.vals()) { c += i }; - printInt(word16ToInt(c)); - print("\n"); - }; - incopt(a : ?Word16) : () { - switch a { - case null { c += 10000 }; - case (?a) { c += a }; - }; - printInt(word16ToInt(c)); - print("\n"); - }; - increcord(a : shared { x : Word16; y : Word16 }) : () { - c += a.x; - c += a.y; - printInt(word16ToInt(c)); - print("\n"); - }; - printCounter() { - printInt(word16ToInt(c)); - print("\n"); - }; - printLabeled(l:Text) { - print l; - printInt(word16ToInt(c)); - print("\n"); - }; - printLabeledOpt(?l:?Text) { - print l; - printInt(word16ToInt(c)); - print("\n"); - }; -}; - - -w16.incn(1); -w16.incn(2); -w16.incn(3); -w16.incn(4); -w16.incn(1000); -w16.incnn(5,6); -w16.incnn(2000,3000); -w16.incnested(7,(8,9)); -w16.incarray([10,11,12,13]); -w16.incopt(null); -w16.incopt(?14); -w16.increcord(shared {x = 15 : Word16; y = 16 : Word16}); -w16.increcord(shared {x = 17 : Word16; y = 18 : Word16; z = 19 : Word16}); -w16.printCounter(); -w16.printLabeled("Foo1: "); -w16.printLabeledOpt(?"Foo2: "); +a.inci(10000000000000); +a.inci(-20000000000000); +a.incwords(1,2,3); +a.incwords(-1,-2,-3); +a.incn(2**100); +a.inci(2**100); +a.inci(-(2**101)); diff --git a/test/run-dfinity/ok/data-params.dvm-run.ok b/test/run-dfinity/ok/data-params.dvm-run.ok index c1ac61e2e3c..b59714f09cc 100644 --- a/test/run-dfinity/ok/data-params.dvm-run.ok +++ b/test/run-dfinity/ok/data-params.dvm-run.ok @@ -17,35 +17,10 @@ Foo1: 1006211 Foo2: 1006211 10000001006211 -1 -3 -6 -10 -1010 -1021 -6021 -6045 -6091 -1006091 -1006105 -1006136 -1006171 -1006171 -Foo1: 1006171 -Foo2: 1006171 -1 -3 -6 -10 -1010 -1021 -6021 -6045 -6091 -16091 -16105 -16136 -16171 -16171 -Foo1: 16171 -Foo2: 16171 +20000001006211 +1006211 +1006217 +1006211 +1267650600228229401496704211587 +2535301200456458802993407416963 +1006211 diff --git a/test/run-dfinity/ok/data-params.run-ir.ok b/test/run-dfinity/ok/data-params.run-ir.ok index 41ea77762f8..e4cd9453940 100644 --- a/test/run-dfinity/ok/data-params.run-ir.ok +++ b/test/run-dfinity/ok/data-params.run-ir.ok @@ -1,6 +1,4 @@ -data-params.as:54.18-54.28: warning, this pattern does not cover all possible values -data-params.as:128.18-128.28: warning, this pattern does not cover all possible values -data-params.as:200.18-200.28: warning, this pattern does not cover all possible values +data-params.as:59.18-59.28: warning, this pattern does not cover all possible values 1 3 6 @@ -20,35 +18,10 @@ data-params.as:200.18-200.28: warning, this pattern does not cover all possible Foo1: 1006211 Foo2: 1006211 10000001006211 -1 -3 -6 -10 -1010 -1021 -6021 -6045 -6091 -1006091 -1006105 -1006136 -1006171 -1006171 -Foo1: 1006171 -Foo2: 1006171 -1 -3 -6 -10 -1010 -1021 -6021 -6045 -6091 -16091 -16105 -16136 -16171 -16171 -Foo1: 16171 -Foo2: 16171 +20000001006211 +1006211 +1006217 +1006211 +1267650600228229401496704211587 +2535301200456458802993407416963 +1006211 diff --git a/test/run-dfinity/ok/data-params.run-low.ok b/test/run-dfinity/ok/data-params.run-low.ok index 41ea77762f8..e4cd9453940 100644 --- a/test/run-dfinity/ok/data-params.run-low.ok +++ b/test/run-dfinity/ok/data-params.run-low.ok @@ -1,6 +1,4 @@ -data-params.as:54.18-54.28: warning, this pattern does not cover all possible values -data-params.as:128.18-128.28: warning, this pattern does not cover all possible values -data-params.as:200.18-200.28: warning, this pattern does not cover all possible values +data-params.as:59.18-59.28: warning, this pattern does not cover all possible values 1 3 6 @@ -20,35 +18,10 @@ data-params.as:200.18-200.28: warning, this pattern does not cover all possible Foo1: 1006211 Foo2: 1006211 10000001006211 -1 -3 -6 -10 -1010 -1021 -6021 -6045 -6091 -1006091 -1006105 -1006136 -1006171 -1006171 -Foo1: 1006171 -Foo2: 1006171 -1 -3 -6 -10 -1010 -1021 -6021 -6045 -6091 -16091 -16105 -16136 -16171 -16171 -Foo1: 16171 -Foo2: 16171 +20000001006211 +1006211 +1006217 +1006211 +1267650600228229401496704211587 +2535301200456458802993407416963 +1006211 diff --git a/test/run-dfinity/ok/data-params.run.ok b/test/run-dfinity/ok/data-params.run.ok index 41ea77762f8..e4cd9453940 100644 --- a/test/run-dfinity/ok/data-params.run.ok +++ b/test/run-dfinity/ok/data-params.run.ok @@ -1,6 +1,4 @@ -data-params.as:54.18-54.28: warning, this pattern does not cover all possible values -data-params.as:128.18-128.28: warning, this pattern does not cover all possible values -data-params.as:200.18-200.28: warning, this pattern does not cover all possible values +data-params.as:59.18-59.28: warning, this pattern does not cover all possible values 1 3 6 @@ -20,35 +18,10 @@ data-params.as:200.18-200.28: warning, this pattern does not cover all possible Foo1: 1006211 Foo2: 1006211 10000001006211 -1 -3 -6 -10 -1010 -1021 -6021 -6045 -6091 -1006091 -1006105 -1006136 -1006171 -1006171 -Foo1: 1006171 -Foo2: 1006171 -1 -3 -6 -10 -1010 -1021 -6021 -6045 -6091 -16091 -16105 -16136 -16171 -16171 -Foo1: 16171 -Foo2: 16171 +20000001006211 +1006211 +1006217 +1006211 +1267650600228229401496704211587 +2535301200456458802993407416963 +1006211 diff --git a/test/run-dfinity/ok/data-params.tc.ok b/test/run-dfinity/ok/data-params.tc.ok index ab5f795ada3..757997e11c7 100644 --- a/test/run-dfinity/ok/data-params.tc.ok +++ b/test/run-dfinity/ok/data-params.tc.ok @@ -1,3 +1 @@ -data-params.as:54.18-54.28: warning, this pattern does not cover all possible values -data-params.as:128.18-128.28: warning, this pattern does not cover all possible values -data-params.as:200.18-200.28: warning, this pattern does not cover all possible values +data-params.as:59.18-59.28: warning, this pattern does not cover all possible values diff --git a/test/run-dfinity/ok/data-params.wasm.stderr.ok b/test/run-dfinity/ok/data-params.wasm.stderr.ok index ab5f795ada3..757997e11c7 100644 --- a/test/run-dfinity/ok/data-params.wasm.stderr.ok +++ b/test/run-dfinity/ok/data-params.wasm.stderr.ok @@ -1,3 +1 @@ -data-params.as:54.18-54.28: warning, this pattern does not cover all possible values -data-params.as:128.18-128.28: warning, this pattern does not cover all possible values -data-params.as:200.18-200.28: warning, this pattern does not cover all possible values +data-params.as:59.18-59.28: warning, this pattern does not cover all possible values From 0bf5b875166a9c6bb0c041ed656342d1af9f11c6 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 11 Jun 2019 11:25:31 +0200 Subject: [PATCH 0154/1176] Remove dependency Interpreter -> Flags (#484) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Remove dependency Interpreter -> Flags in preparation for organizing the files in `src/` more cleanly. * Also pass through print_depths explicitly Clearly this doesn’t scale to more settings, and maybe we want some kind of `interpreter_flags` type. But for now this is good enough, and removes the `Value -> Flags` dependency. * Bundle interpreter flags into a record --- Building.md | 4 +- src/aslib/interpret.ml | 111 +++++++++++++++++--------------- src/aslib/interpret.mli | 9 ++- src/aslib/interpret_ir.ml | 126 ++++++++++++++++++++----------------- src/aslib/interpret_ir.mli | 7 ++- src/aslib/ir.ml | 8 +++ src/aslib/pipeline.ml | 24 ++++--- src/aslib/show.ml | 2 +- src/aslib/value.ml | 19 +++--- src/aslib/value.mli | 4 +- 10 files changed, 178 insertions(+), 136 deletions(-) diff --git a/Building.md b/Building.md index fd405451de5..644dc62ee14 100644 --- a/Building.md +++ b/Building.md @@ -18,7 +18,9 @@ To enter a shell with the necessary dependencies, you can use $ nix-shell ``` within this shell you can run - * `make asc` in `src/` to build the `asc` binary, + * `make` in `src/` to build all binaries, + * `make asc` in `src/` to build just the `asc` binary, + * `make DUNE_OPTS=--watch asc` to keep rebuilding as source files are changing * `make` in `rts/` to build the ActorScript runtime * `make` in `test/` to run the test suite. diff --git a/src/aslib/interpret.ml b/src/aslib/interpret.ml index 11b21e9ac14..f6554b1e80d 100644 --- a/src/aslib/interpret.ml +++ b/src/aslib/interpret.ml @@ -12,13 +12,19 @@ type lib_env = V.value V.Env.t type lab_env = V.value V.cont V.Env.t type ret_env = V.value V.cont option +type flags = { + trace : bool; + print_depth : int +} + type scope = { val_env: V.def V.Env.t; lib_env: V.value V.Env.t; } type env = - { vals : val_env; + { flags : flags; + vals : val_env; labs : lab_env; libs : lib_env; rets : ret_env; @@ -37,8 +43,9 @@ let empty_scope = { val_env = V.Env.empty; lib_env = V.Env.empty } let library_scope f v scope : scope = { scope with lib_env = V.Env.add f v scope.lib_env } -let env_of_scope scope = - { vals = scope.val_env; +let env_of_scope flags scope = + { flags; + vals = scope.val_env; libs = scope.lib_env; labs = V.Env.empty; rets = None; @@ -66,23 +73,25 @@ let trace fmt = Printf.printf "%s%s\n%!" (String.make (2 * !trace_depth) ' ') s ) fmt -let string_of_arg = function - | V.Tup _ as v -> V.string_of_val v - | v -> "(" ^ V.string_of_val v ^ ")" +let string_of_val env = V.string_of_val env.flags.print_depth +let string_of_def flags = V.string_of_def flags.print_depth +let string_of_arg env = function + | V.Tup _ as v -> string_of_val env v + | v -> "(" ^ string_of_val env v ^ ")" (* Debugging aids *) -let last_env = ref (env_of_scope empty_scope) +let last_env = ref (env_of_scope {trace = false; print_depth = 2} empty_scope) let last_region = ref Source.no_region -let print_exn exn = +let print_exn flags exn = Printf.printf "%!"; let at = Source.string_of_region !last_region in Printf.eprintf "%s: internal error, %s\n" at (Printexc.to_string exn); Printf.eprintf "\nLast environment:\n"; - Value.Env.iter (fun x d -> Printf.eprintf "%s = %s\n" x (Value.string_of_def d)) - (!last_env.vals); + Value.Env.iter (fun x d -> Printf.eprintf "%s = %s\n" x (string_of_def flags d)) + !last_env.vals; Printf.eprintf "\n"; Printexc.print_backtrace stderr; Printf.eprintf "%!" @@ -123,59 +132,59 @@ let fulfill async v = Scheduler.queue (fun () -> set_async async v) -let async at (f: (V.value V.cont) -> unit) (k : V.value V.cont) = +let async env at (f: (V.value V.cont) -> unit) (k : V.value V.cont) = let async = make_async () in (* let k' = fun v1 -> set_async async v1 in *) let k' = fun v1 -> fulfill async v1 in - if !Flags.trace then trace "-> async %s" (string_of_region at); + if env.flags.trace then trace "-> async %s" (string_of_region at); Scheduler.queue (fun () -> - if !Flags.trace then trace "<- async %s" (string_of_region at); + if env.flags.trace then trace "<- async %s" (string_of_region at); incr trace_depth; f (fun v -> - if !Flags.trace then trace "<= %s" (V.string_of_val v); + if env.flags.trace then trace "<= %s" (string_of_val env v); decr trace_depth; k' v) ); k (V.Async async) -let await at async k = - if !Flags.trace then trace "=> await %s" (string_of_region at); +let await env at async k = + if env.flags.trace then trace "=> await %s" (string_of_region at); decr trace_depth; get_async async (fun v -> Scheduler.queue (fun () -> - if !Flags.trace then - trace "<- await %s%s" (string_of_region at) (string_of_arg v); + if env.flags.trace then + trace "<- await %s%s" (string_of_region at) (string_of_arg env v); incr trace_depth; k v ) ) -let actor_msg id f v (k : V.value V.cont) = - if !Flags.trace then trace "-> message %s%s" id (string_of_arg v); +let actor_msg env id f v (k : V.value V.cont) = + if env.flags.trace then trace "-> message %s%s" id (string_of_arg env v); Scheduler.queue (fun () -> - if !Flags.trace then trace "<- message %s%s" id (string_of_arg v); + if env.flags.trace then trace "<- message %s%s" id (string_of_arg env v); incr trace_depth; f v k ) -let make_unit_message id v = +let make_unit_message env id v = let call_conv, f = V.as_func v in match call_conv with | {V.sort = T.Sharable; V.n_res = 0; _} -> Value.message_func call_conv.V.n_args (fun v k -> - actor_msg id f v (fun _ -> ()); + actor_msg env id f v (fun _ -> ()); k V.unit ) | _ -> (* assert false *) failwith ("unexpected call_conv " ^ (V.string_of_call_conv call_conv)) -let make_async_message id v = +let make_async_message env id v = let call_conv, f = V.as_func v in match call_conv with | {V.sort = T.Sharable; V.control = T.Promises; V.n_res = 1; _} -> Value.async_func call_conv.V.n_args (fun v k -> let async = make_async () in - actor_msg id f v (fun v_async -> + actor_msg env id f v (fun v_async -> get_async (V.as_async v_async) (fun v_r -> set_async async v_r) ); k (V.Async async) @@ -184,10 +193,10 @@ let make_async_message id v = failwith ("unexpected call_conv " ^ (V.string_of_call_conv call_conv)) -let make_message name t v : V.value = +let make_message env name t v : V.value = match t with - | T.Func (_, _, _, _, []) -> make_unit_message name v - | T.Func (_, _, _, _, [T.Async _]) -> make_async_message name v + | T.Func (_, _, _, _, []) -> make_unit_message env name v + | T.Func (_, _, _, _, [T.Async _]) -> make_async_message env name v | _ -> (* assert false *) failwith (Printf.sprintf "actorfield: %s %s" name (T.string_of_typ t)) @@ -223,14 +232,14 @@ let check_call_conv exp call_conv = (V.string_of_call_conv call_conv) ) -let check_call_conv_arg exp v call_conv = +let check_call_conv_arg env exp v call_conv = if call_conv.V.n_args <> 1 then let es = try V.as_tup v with Invalid_argument _ -> failwith (Printf.sprintf "call %s: calling convention %s cannot handle non-tuple value %s" (Wasm.Sexpr.to_string 80 (Arrange.exp exp)) (V.string_of_call_conv call_conv) - (V.string_of_val v) + (string_of_val env v) ) in if List.length es <> call_conv.V.n_args then @@ -238,7 +247,7 @@ let check_call_conv_arg exp v call_conv = "call %s: calling convention %s got tuple of wrong length %s" (Wasm.Sexpr.to_string 80 (Arrange.exp exp)) (V.string_of_call_conv call_conv) - (V.string_of_val v) + (string_of_val env v) ) @@ -321,7 +330,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = let v = V.Func (V.call_conv_of_typ exp.note.note_typ, f) in let v' = match _sort.it with - | T.Sharable -> make_message name exp.note.note_typ v + | T.Sharable -> make_message env name exp.note.note_typ v | T.Local -> v in k v' | CallE (exp1, typs, exp2) -> @@ -329,7 +338,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = interpret_exp env exp2 (fun v2 -> let call_conv, f = V.as_func v1 in check_call_conv exp1 call_conv; - check_call_conv_arg exp v2 call_conv; + check_call_conv_arg env exp v2 call_conv; f v2 k (* try @@ -394,7 +403,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = | V.Opt v1 -> (match match_pat pat v1 with | None -> - trap pat.at "value %s does not match pattern" (V.string_of_val v') + trap pat.at "value %s does not match pattern" (string_of_val env v') | Some ve -> interpret_exp (adjoin_vals env ve) exp2 k_continue ) @@ -411,7 +420,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = | RetE exp1 -> interpret_exp env exp1 (Lib.Option.value env.rets) | AsyncE exp1 -> - async + async env exp.at (fun k' -> let env' = {env with labs = V.Env.empty; rets = Some k'; async = true} @@ -420,7 +429,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = | AwaitE exp1 -> interpret_exp env exp1 - (fun v1 -> await exp.at (V.as_async v1) k) + (fun v1 -> await env exp.at (V.as_async v1) k) | AssertE exp1 -> interpret_exp env exp1 (fun v -> if V.as_bool v @@ -442,7 +451,7 @@ and interpret_exps env exps vs (k : V.value list V.cont) = and interpret_cases env cases at v (k : V.value V.cont) = match cases with | [] -> - trap at "switch value %s does not match any case" (V.string_of_val v) + trap at "switch value %s does not match any case" (string_of_val env v) | {it = {pat; exp}; at; _}::cases' -> match match_pat pat v with | Some ve -> interpret_exp (adjoin_vals env ve) exp k @@ -484,11 +493,12 @@ and define_id env id v = Lib.Promise.fulfill (find id.it env.vals) v and define_pat env pat v = + let err () = trap pat.at "value %s does not match pattern" (string_of_val env v) in match pat.it with | WildP -> () | LitP _ | SignP _ | AltP _ -> if match_pat pat v = None - then trap pat.at "value %s does not match pattern" (V.string_of_val v) + then err () else () | VarP id -> define_id env id v | TupP pats -> define_pats env pats (V.as_tup v) @@ -496,15 +506,14 @@ and define_pat env pat v = | OptP pat1 -> (match v with | V.Opt v1 -> define_pat env pat1 v1 - | V.Null -> - trap pat.at "value %s does not match pattern" (V.string_of_val v) + | V.Null -> err () | _ -> assert false ) | TagP (i, pat1) -> let lab, v1 = V.as_variant v in if lab = i.it then define_pat env pat1 v1 - else trap pat.at "value %s does not match pattern" (V.string_of_val v) + else err () | AnnotP (pat1, _) | ParP pat1 -> define_pat env pat1 v @@ -673,20 +682,20 @@ and interpret_decs env decs (k : V.value V.cont) = and interpret_func env name pat f v (k : V.value V.cont) = - if !Flags.trace then trace "%s%s" name (string_of_arg v); + if env.flags.trace then trace "%s%s" name (string_of_arg env v); match match_pat pat v with | None -> - trap pat.at "argument value %s does not match parameter list" - (V.string_of_val v) + trap pat.at "argument value %s does not match parameter list" (string_of_val env v) | Some ve -> incr trace_depth; let k' = fun v' -> - if !Flags.trace then trace "<= %s" (V.string_of_val v'); + if env.flags.trace then trace "<= %s" (string_of_val env v'); decr trace_depth; k v' in let env' = - { vals = V.Env.adjoin env.vals ve; + { env with + vals = V.Env.adjoin env.vals ve; libs = env.libs; labs = V.Env.empty; rets = Some k'; @@ -697,9 +706,9 @@ and interpret_func env name pat f v (k : V.value V.cont) = (* Programs *) -let interpret_prog scope p : (V.value * scope) option = +let interpret_prog flags scope p : (V.value * scope) option = try - let env = env_of_scope scope in + let env = env_of_scope flags scope in trace_depth := 0; let vo = ref None in let ve = ref V.Env.empty in @@ -713,12 +722,12 @@ let interpret_prog scope p : (V.value * scope) option = | None -> None with exn -> (* For debugging, should never happen. *) - print_exn exn; + print_exn flags exn; None -let interpret_library scope (filename, p) : scope = - let env = env_of_scope scope in +let interpret_library flags scope (filename, p) : scope = + let env = env_of_scope flags scope in trace_depth := 0; let vo = ref None in let ve = ref V.Env.empty in diff --git a/src/aslib/interpret.mli b/src/aslib/interpret.mli index 6f18c5d3859..ab969ccac00 100644 --- a/src/aslib/interpret.mli +++ b/src/aslib/interpret.mli @@ -1,6 +1,11 @@ module V = Value module T = Type +type flags = { + trace : bool; + print_depth : int +} + type scope = { val_env: V.def V.Env.t; lib_env: V.value V.Env.t; @@ -11,5 +16,5 @@ val adjoin_scope : scope -> scope -> scope exception Trap of Source.region * string -val interpret_prog : scope -> Syntax.prog -> (V.value * scope) option -val interpret_library : scope -> Syntax.library -> scope +val interpret_prog : flags -> scope -> Syntax.prog -> (V.value * scope) option +val interpret_library : flags -> scope -> Syntax.library -> scope diff --git a/src/aslib/interpret_ir.ml b/src/aslib/interpret_ir.ml index a572ebe5fd1..6731a168950 100644 --- a/src/aslib/interpret_ir.ml +++ b/src/aslib/interpret_ir.ml @@ -13,8 +13,15 @@ type ret_env = V.value V.cont option type scope = val_env +type flags = { + trace : bool; + print_depth : int +} + type env = - { vals : val_env; + { flags : flags; + flavor : Ir.flavor; + vals : val_env; labs : lab_env; rets : ret_env; async : bool @@ -25,8 +32,10 @@ let adjoin_vals c ve = {c with vals = adjoin_scope c.vals ve} let empty_scope = V.Env.empty -let env_of_scope ve = - { vals = ve; +let env_of_scope flags flavor ve = + { flags; + flavor; + vals = ve; labs = V.Env.empty; rets = None; async = false; @@ -53,23 +62,26 @@ let trace fmt = Printf.printf "%s%s\n%!" (String.make (2 * !trace_depth) ' ') s ) fmt -let string_of_arg = function - | V.Tup _ as v -> V.string_of_val v - | v -> "(" ^ V.string_of_val v ^ ")" +let string_of_val env = V.string_of_val env.flags.print_depth +let string_of_def flags = V.string_of_def flags.print_depth +let string_of_arg env = function + | V.Tup _ as v -> string_of_val env v + | v -> "(" ^ string_of_val env v ^ ")" (* Debugging aids *) -let last_env = ref (env_of_scope empty_scope) +let last_env = ref (env_of_scope { trace = false; print_depth = 2} Ir.full_flavor empty_scope) let last_region = ref Source.no_region -let print_exn exn = +let print_exn flags exn = Printf.printf "%!"; let at = Source.string_of_region !last_region in Printf.eprintf "%s: internal error, %s\n" at (Printexc.to_string exn); Printf.eprintf "\nLast environment:\n"; - Value.Env.iter (fun x d -> Printf.eprintf "%s = %s\n" x (Value.string_of_def d)) - (!last_env.vals); + Value.Env.iter + (fun x d -> Printf.eprintf "%s = %s\n" x (string_of_def flags d)) + !last_env.vals; Printf.eprintf "\n"; Printexc.print_backtrace stderr; Printf.eprintf "%!" @@ -110,62 +122,62 @@ let fulfill async v = Scheduler.queue (fun () -> set_async async v) -let async at (f: (V.value V.cont) -> unit) (k : V.value V.cont) = +let async env at (f: (V.value V.cont) -> unit) (k : V.value V.cont) = let async = make_async () in (* let k' = fun v1 -> set_async async v1 in *) let k' = fun v1 -> fulfill async v1 in - if !Flags.trace then trace "-> async %s" (string_of_region at); + if env.flags.trace then trace "-> async %s" (string_of_region at); Scheduler.queue (fun () -> - if !Flags.trace then trace "<- async %s" (string_of_region at); + if env.flags.trace then trace "<- async %s" (string_of_region at); incr trace_depth; f (fun v -> - if !Flags.trace then trace "<= %s" (V.string_of_val v); + if env.flags.trace then trace "<= %s" (string_of_val env v); decr trace_depth; k' v) ); k (V.Async async) -let await at async k = - if !Flags.trace then trace "=> await %s" (string_of_region at); +let await env at async k = + if env.flags.trace then trace "=> await %s" (string_of_region at); decr trace_depth; get_async async (fun v -> Scheduler.queue (fun () -> - if !Flags.trace then - trace "<- await %s%s" (string_of_region at) (string_of_arg v); + if env.flags.trace then + trace "<- await %s%s" (string_of_region at) (string_of_arg env v); incr trace_depth; k v ) ) (*; Scheduler.yield () *) -let actor_msg id f v (k : V.value V.cont) = - if !Flags.trace then trace "-> message %s%s" id (string_of_arg v); +let actor_msg env id f v (k : V.value V.cont) = + if env.flags.trace then trace "-> message %s%s" id (string_of_arg env v); Scheduler.queue (fun () -> - if !Flags.trace then trace "<- message %s%s" id (string_of_arg v); + if env.flags.trace then trace "<- message %s%s" id (string_of_arg env v); incr trace_depth; f v k ) -let make_unit_message id v = +let make_unit_message env id v = let call_conv, f = V.as_func v in match call_conv with | {V.sort = T.Sharable; V.n_res = 0; _} -> Value.message_func call_conv.V.n_args (fun v k -> - actor_msg id f v (fun _ -> ()); + actor_msg env id f v (fun _ -> ()); k V.unit ) | _ -> failwith ("unexpected call_conv " ^ (V.string_of_call_conv call_conv)) (* assert (false) *) -let make_async_message id v = - assert (not !Flags.async_lowering); +let make_async_message env id v = + assert env.flavor.has_async_typ; let call_conv, f = V.as_func v in match call_conv with | {V.sort = T.Sharable; V.control = T.Promises; V.n_res = 1; _} -> Value.async_func call_conv.V.n_args (fun v k -> let async = make_async () in - actor_msg id f v (fun v_async -> + actor_msg env id f v (fun v_async -> get_async (V.as_async v_async) (fun v_r -> set_async async v_r) ); k (V.Async async) @@ -175,25 +187,22 @@ let make_async_message id v = (* assert (false) *) -let make_message x cc v : V.value = +let make_message env x cc v : V.value = match cc.V.control with - | T.Returns -> - make_unit_message x v - | T.Promises -> - assert (not !Flags.async_lowering); - make_async_message x v + | T.Returns -> make_unit_message env x v + | T.Promises -> make_async_message env x v -let extended_prim s typ at = +let extended_prim env s typ at = match s with | "@async" -> - assert (!Flags.await_lowering && not !Flags.async_lowering); + assert (not env.flavor.has_await && env.flavor.has_async_typ); (fun v k -> let (_, f) = V.as_func v in match typ with | T.Func(_, _, _, [T.Func(_, _, _, [f_dom], _)], _) -> let call_conv = Value.call_conv_of_typ f_dom in - async at + async env at (fun k' -> let k' = Value.Func (call_conv, fun v _ -> k' v) in f k' V.as_unit @@ -201,12 +210,12 @@ let extended_prim s typ at = | _ -> assert false ) | "@await" -> - assert(!Flags.await_lowering && not !Flags.async_lowering); + assert (not env.flavor.has_await && env.flavor.has_async_typ); fun v k -> (match V.as_tup v with | [async; w] -> let (_, f) = V.as_func w in - await at (V.as_async async) (fun v -> f v k) + await env at (V.as_async async) (fun v -> f v k) | _ -> assert false ) | _ -> Prelude.prim s @@ -242,19 +251,19 @@ let check_call_conv exp call_conv = (V.string_of_call_conv exp_call_conv) (V.string_of_call_conv call_conv)) -let check_call_conv_arg exp v call_conv = +let check_call_conv_arg env exp v call_conv = if call_conv.V.n_args <> 1 then let es = try V.as_tup v with Invalid_argument _ -> failwith (Printf.sprintf "call %s: calling convention %s cannot handle non-tuple value %s" (Wasm.Sexpr.to_string 80 (Arrange_ir.exp exp)) (V.string_of_call_conv call_conv) - (V.string_of_val v)) in + (string_of_val env v)) in if List.length es <> call_conv.V.n_args then failwith (Printf.sprintf "call %s: calling convention %s got tuple of wrong length %s" (Wasm.Sexpr.to_string 80 (Arrange_ir.exp exp)) (V.string_of_call_conv call_conv) - (V.string_of_val v)) + (string_of_val env v)) let rec interpret_exp env exp (k : V.value V.cont) = @@ -268,7 +277,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = let at = exp.at in let t = exp.note.Syntax.note_typ in let cc = V.call_conv_of_typ t in - k (V.Func (cc, extended_prim s t at)) + k (V.Func (cc, extended_prim env s t at)) | VarE id -> (match Lib.Promise.value_opt (find id.it env.vals) with | Some v -> k v @@ -336,7 +345,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = interpret_exp env exp2 (fun v2 -> let call_conv, f = V.as_func v1 in check_call_conv exp1 call_conv; - check_call_conv_arg exp v2 call_conv; + check_call_conv_arg env exp v2 call_conv; f v2 k (* @@ -369,8 +378,8 @@ and interpret_exp_mut env exp (k : V.value V.cont) = | RetE exp1 -> interpret_exp env exp1 (Lib.Option.value env.rets) | AsyncE exp1 -> - assert(not(!Flags.await_lowering)); - async + assert env.flavor.has_await; + async env exp.at (fun k' -> let env' = {env with labs = V.Env.empty; rets = Some k'; async = true} @@ -378,9 +387,9 @@ and interpret_exp_mut env exp (k : V.value V.cont) = k | AwaitE exp1 -> - assert(not(!Flags.await_lowering)); + assert env.flavor.has_await; interpret_exp env exp1 - (fun v1 -> await exp.at (V.as_async v1) k) + (fun v1 -> await env exp.at (V.as_async v1) k) | AssertE exp1 -> interpret_exp env exp1 (fun v -> if V.as_bool v @@ -406,7 +415,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = let v = V.Func (cc, f) in let v = match cc.Value.sort with - | T.Sharable -> make_message x cc v + | T.Sharable -> make_message env x cc v | _-> v in k v @@ -440,7 +449,7 @@ and interpret_exps env exps vs (k : V.value list V.cont) = and interpret_cases env cases at v (k : V.value V.cont) = match cases with | [] -> - trap at "switch value %s does not match any case" (V.string_of_val v) + trap at "switch value %s does not match any case" (string_of_val env v) | {it = {pat; exp}; at; _}::cases' -> match match_pat pat v with | Some ve -> interpret_exp (adjoin_vals env ve) exp k @@ -485,11 +494,12 @@ and define_id env id v = Lib.Promise.fulfill (find id.it env.vals) v and define_pat env pat v = + let err () = trap pat.at "value %s does not match pattern" (string_of_val env v) in match pat.it with | WildP -> () | LitP _ | AltP _ -> if match_pat pat v = None - then trap pat.at "value %s does not match pattern" (V.string_of_val v) + then err () else () | VarP id -> define_id env id v | TupP pats -> define_pats env pats (V.as_tup v) @@ -497,15 +507,14 @@ and define_pat env pat v = | OptP pat1 -> (match v with | V.Opt v1 -> define_pat env pat1 v1 - | V.Null -> - trap pat.at "value %s does not match pattern" (V.string_of_val v) + | V.Null -> err () | _ -> assert false ) | TagP (i, pat1) -> let lab, v1 = V.as_variant v in if lab = i.it then define_pat env pat1 v1 - else trap pat.at "value %s does not match pattern" (V.string_of_val v) + else err () and define_pats env pats vs = List.iter2 (define_pat env) pats vs @@ -627,16 +636,17 @@ and interpret_decs env decs (k : unit V.cont) = | d::ds -> interpret_dec env d (fun () -> interpret_decs env ds k) and interpret_func env at x args f v (k : V.value V.cont) = - if !Flags.trace then trace "%s%s" x (string_of_arg v); + if env.flags.trace then trace "%s%s" x (string_of_arg env v); let ve = match_args at args v in incr trace_depth; let k' = fun v' -> - if !Flags.trace then trace "<= %s" (V.string_of_val v'); + if env.flags.trace then trace "<= %s" (string_of_val env v'); decr trace_depth; k v' in let env' = - { vals = V.Env.adjoin env.vals ve; + { env with + vals = V.Env.adjoin env.vals ve; labs = V.Env.empty; rets = Some k'; async = false @@ -646,8 +656,8 @@ and interpret_func env at x args f v (k : V.value V.cont) = (* Programs *) -let interpret_prog scope ((ds, exp), _flavor) : scope = - let env = env_of_scope scope in +let interpret_prog flags scope ((ds, exp), flavor) : scope = + let env = env_of_scope flags flavor scope in trace_depth := 0; let ve = ref V.Env.empty in try @@ -656,5 +666,5 @@ let interpret_prog scope ((ds, exp), _flavor) : scope = ); Scheduler.run (); !ve - with exn -> print_exn exn; !ve + with exn -> print_exn flags exn; !ve diff --git a/src/aslib/interpret_ir.mli b/src/aslib/interpret_ir.mli index 4dea591faaa..67f3bd79fb2 100644 --- a/src/aslib/interpret_ir.mli +++ b/src/aslib/interpret_ir.mli @@ -1,6 +1,11 @@ module V = Value module T = Type +type flags = { + trace : bool; + print_depth : int +} + type scope = V.def V.Env.t val empty_scope : scope @@ -8,4 +13,4 @@ val adjoin_scope : scope -> scope -> scope exception Trap of Source.region * string -val interpret_prog : scope -> Ir.prog -> scope +val interpret_prog : flags -> scope -> Ir.prog -> scope diff --git a/src/aslib/ir.ml b/src/aslib/ir.ml index 82dc6449d0d..89bb65d1800 100644 --- a/src/aslib/ir.ml +++ b/src/aslib/ir.ml @@ -103,6 +103,14 @@ type flavor = { serialized : bool; (* Shared function arguments are serialized *) } +let full_flavor : flavor = { + has_await = true; + has_async_typ = true; + has_show = true; + serialized = false; +} + + (* Program *) diff --git a/src/aslib/pipeline.ml b/src/aslib/pipeline.ml index 6e7d4fd0ab7..f2665b4244d 100644 --- a/src/aslib/pipeline.ml +++ b/src/aslib/pipeline.ml @@ -32,7 +32,7 @@ let print_dyn_ve scope = let t' = Type.as_immut t in printf "%s %s : %s = %s\n" (if t == t' then "let" else "var") x - (Type.string_of_typ t') (Value.string_of_def d) + (Type.string_of_typ t') (Value.string_of_def !Flags.print_depth d) ) let print_scope senv scope dve = @@ -40,7 +40,7 @@ let print_scope senv scope dve = print_dyn_ve senv dve let print_val _senv v t = - printf "%s : %s\n" (Value.string_of_val v) (Type.string_of_typ t) + printf "%s : %s\n" (Value.string_of_val !Flags.print_depth v) (Type.string_of_typ t) (* Dumping *) @@ -234,16 +234,20 @@ let load_decl parse_one senv : load_decl_result = (* Interpretation (Source) *) let interpret_prog denv prog : (Value.value * Interpret.scope) option = + let open Interpret in phase "Interpreting" prog.Source.note; - Interpret.interpret_prog denv prog + let flags = { trace = !Flags.trace; print_depth = !Flags.print_depth } in + interpret_prog flags denv prog let rec interpret_libraries denv libraries : Interpret.scope = + let open Interpret in match libraries with | [] -> denv | (f, p)::libs -> phase "Interpreting" p.Source.note; - let dscope = Interpret.interpret_library denv (f, p) in - let denv' = Interpret.adjoin_scope denv dscope in + let flags = { trace = !Flags.trace; print_depth = !Flags.print_depth } in + let dscope = interpret_library flags denv (f, p) in + let denv' = adjoin_scope denv dscope in interpret_libraries denv' libs let rec interpret_progs denv progs : Interpret.scope option = @@ -491,10 +495,12 @@ let interpret_ir_prog inp_env libraries progs = let name = name_progs progs in let prog_ir = lower_prog initial_stat_env inp_env libraries progs name in phase "Interpreting" name; - let denv0 = Interpret_ir.empty_scope in - let dscope = Interpret_ir.interpret_prog denv0 prelude_ir in - let denv1 = Interpret_ir.adjoin_scope denv0 dscope in - let _ = Interpret_ir.interpret_prog denv1 prog_ir in + let open Interpret_ir in + let flags = { trace = !Flags.trace; print_depth = !Flags.print_depth } in + let denv0 = empty_scope in + let dscope = interpret_prog flags denv0 prelude_ir in + let denv1 = adjoin_scope denv0 dscope in + let _ = interpret_prog flags denv1 prog_ir in () let interpret_ir_files files = diff --git a/src/aslib/show.ml b/src/aslib/show.ml index 197bcee3001..466842d2d28 100644 --- a/src/aslib/show.ml +++ b/src/aslib/show.ml @@ -419,7 +419,7 @@ let rec show_val t v = | _ -> assert false end | _ -> - Printf.eprintf "show_val: %s : %s\n" (Value.string_of_val v) (T.string_of_typ t); + Printf.eprintf "show_val: %s : %s\n" (Value.string_of_val 2 v) (T.string_of_typ t); assert false and show_field fs ft = diff --git a/src/aslib/value.ml b/src/aslib/value.ml index 15652b775fb..2307a55c4c3 100644 --- a/src/aslib/value.ml +++ b/src/aslib/value.ml @@ -384,21 +384,21 @@ let rec string_of_val_nullary d = function | Text t -> string_of_string '\"' (Wasm.Utf8.decode t) '\"' | Tup vs -> sprintf "(%s%s)" - (String.concat ", " (List.map (string_of_val' d) vs)) + (String.concat ", " (List.map (string_of_val d) vs)) (if List.length vs = 1 then "," else "") | Opt v -> sprintf "?%s" (string_of_val_nullary d v) | Obj ve -> if d = 0 then "{...}" else sprintf "{%s}" (String.concat "; " (List.map (fun (x, v) -> - sprintf "%s = %s" x (string_of_val' (d - 1) v)) (Env.bindings ve))) + sprintf "%s = %s" x (string_of_val (d - 1) v)) (Env.bindings ve))) | Array a -> sprintf "[%s]" (String.concat ", " - (List.map (string_of_val' d) (Array.to_list a))) + (List.map (string_of_val d) (Array.to_list a))) | Func (_, _) -> "func" - | v -> "(" ^ string_of_val' d v ^ ")" + | v -> "(" ^ string_of_val d v ^ ")" -and string_of_val' d = function +and string_of_val d = function | Async {result; waiters = []} -> sprintf "async %s" (string_of_def_nullary d result) | Async {result; waiters} -> @@ -407,7 +407,7 @@ and string_of_val' d = function | Variant (l, Tup []) -> sprintf "#%s" l | Variant (l, v) when v <> unit -> sprintf "#%s %s" l (string_of_val_nullary d v) - | Mut r -> sprintf "%s" (string_of_val' d !r) + | Mut r -> sprintf "%s" (string_of_val d !r) | v -> string_of_val_nullary d v and string_of_def_nullary d def = @@ -415,14 +415,11 @@ and string_of_def_nullary d def = | Some v -> string_of_val_nullary d v | None -> "_" -and string_of_def' d def = +and string_of_def d def = match Lib.Promise.value_opt def with - | Some v -> string_of_val' d v + | Some v -> string_of_val d v | None -> "_" -let string_of_val v = string_of_val' !Flags.print_depth v -let string_of_def d = string_of_def' !Flags.print_depth d - let string_of_call_conv {sort;control;n_args;n_res} = sprintf "(%s %i %s %i)" (T.string_of_sharing sort) diff --git a/src/aslib/value.mli b/src/aslib/value.mli index ce3259a3491..08f3be96ca1 100644 --- a/src/aslib/value.mli +++ b/src/aslib/value.mli @@ -143,6 +143,6 @@ val compare : value -> value -> int (* Pretty Printing *) -val string_of_val : value -> string -val string_of_def : def -> string +val string_of_val : int -> value -> string +val string_of_def : int -> def -> string val string_of_call_conv : call_conv -> string From 359cea81af010943c92b181a851b0363e41bfd60 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Tue, 11 Jun 2019 14:13:33 +0200 Subject: [PATCH 0155/1176] Simple peephole optimisations (#490) * peephole: optimise `if` after pushed constant * peephole: eliminate empty blocks --- src/aslib/instrList.ml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/aslib/instrList.ml b/src/aslib/instrList.ml index 5c1aa536c20..dc4c11ed557 100644 --- a/src/aslib/instrList.ml +++ b/src/aslib/instrList.ml @@ -29,6 +29,13 @@ let optimize : instr list -> instr list = fun is -> (* Code after Return, Br or Unreachable is dead *) | _, ({ it = Return | Br _ | Unreachable; _ } as i) :: _ -> List.rev (i::l) + (* `If` blocks after pushed constants are simplifiable *) + | { it = Const {it = Wasm.Values.I32 0l; _}; _} :: l', ({it = If (res,_,else_); _} as i) :: r' -> + go l' ({i with it = Block (res, else_)} :: r') + | { it = Const {it = Wasm.Values.I32 _; _}; _} :: l', ({it = If (res,then_,_); _} as i) :: r' -> + go l' ({i with it = Block (res, then_)} :: r') + (* Empty block is redundant *) + | l', ({ it = Block (_, []); _ }) :: r' -> go l' r' (* Look further *) | _, i::r' -> go (i::l) r' (* Done looking *) From e6fc9d696fbc2a21bc4f4cfcef9303b365f1ae03 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Wed, 12 Jun 2019 13:30:49 +0200 Subject: [PATCH 0156/1176] fix func import oversight --- src/aslib/compile.ml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/aslib/compile.ml b/src/aslib/compile.ml index 623703a96c9..707500b8680 100644 --- a/src/aslib/compile.ml +++ b/src/aslib/compile.ml @@ -524,6 +524,7 @@ module RTS = struct E.add_func_import env "rts" "bigint_to_word64_signed_trap" [I32Type] [I64Type]; E.add_func_import env "rts" "bigint_eq" [I32Type; I32Type] [I32Type]; E.add_func_import env "rts" "bigint_isneg" [I32Type] [I32Type]; + E.add_func_import env "rts" "bigint_count_bits" [I32Type] [I32Type]; E.add_func_import env "rts" "bigint_2complement_bits" [I32Type] [I32Type]; E.add_func_import env "rts" "bigint_lt" [I32Type; I32Type] [I32Type]; E.add_func_import env "rts" "bigint_gt" [I32Type; I32Type] [I32Type]; From 0e5f71daa2dbc588ab74625c12a3c37620a6ae50 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 13 Jun 2019 12:26:24 +0200 Subject: [PATCH 0157/1176] Source reorganization (first big step) (#483) It turned out to be pretty tedious, and at some point I took some shortcuts, so there are now edges in the dependency graph that we do not actually one. For example, some definitions from `Syntax` permeate the `Ir` world as well. Instead of fixing everything in one go, I propose we merge this, and then take further cleanup steps. Some clean-up steps that I did take: * split `effect.ml` in the Source and the Ir part. * Move data types for operations in to `operation.ml`, as they are shared between Syntax and Ir. There needs to be done more in that direction. * Move `Arrange.prim` to `Arrange_type.prim`. * Splitting the `prelude.ml` into the text of the prelude, and the interpreter semantics of the primitive functions. The decision whether we `open Libname` or not was not taking with too much considerations yet, and can be refined further. Also which libraries should export their set of modules unwrapped (bad practice according to the dune documentation). The `flags` library is also a stop-gap measure, as is the `prelude` library. --- src/Structure.md | 96 ++++++- src/{aslib => as_frontend}/arrange.ml | 8 +- src/{aslib => as_frontend}/coverage.ml | 4 +- src/{aslib => as_frontend}/coverage.mli | 2 + src/{aslib => as_frontend}/definedness.ml | 0 src/{aslib => as_frontend}/definedness.mli | 0 src/{aslib => as_frontend}/dune | 5 +- src/as_frontend/effect.ml | 106 ++++++++ src/{aslib => as_frontend}/effect.mli | 10 +- src/{aslib => as_frontend}/lexer.mli | 0 src/{aslib => as_frontend}/lexer.mll | 0 src/{aslib => as_frontend}/parser.mly | 5 +- src/{aslib => as_frontend}/static.ml | 0 src/{aslib => as_frontend}/static.mli | 0 src/{aslib => as_frontend}/syntax.ml | 37 +-- src/{aslib => as_frontend}/typing.ml | 5 +- src/{aslib => as_frontend}/typing.mli | 2 +- src/{aslib => as_ir}/arrange_ir.ml | 5 +- src/{aslib => as_ir}/check_ir.ml | 8 +- src/{aslib => as_ir}/check_ir.mli | 1 + src/{aslib => as_ir}/construct.ml | 23 +- src/{aslib => as_ir}/construct.mli | 2 + src/as_ir/dune | 4 + src/{aslib => as_ir}/freevars.ml | 0 src/{aslib => as_ir}/ir.ml | 10 +- src/as_ir/ir_effect.ml | 102 ++++++++ src/as_ir/ir_effect.mli | 17 ++ src/as_ld | 1 + src/{aslib => as_types}/arrange_type.ml | 0 src/{aslib => as_types}/con.ml | 0 src/{aslib => as_types}/con.mli | 0 src/as_types/dune | 4 + src/{aslib => as_types}/type.ml | 0 src/{aslib => as_types}/type.mli | 0 src/as_values/dune | 4 + src/{aslib => as_values}/idlHash.ml | 0 src/{aslib => as_values}/idlHash.mli | 0 src/{aslib => as_values}/operator.ml | 36 ++- src/as_values/operator.mli | 43 ++++ src/{aslib/prelude.ml => as_values/prim.ml} | 236 ------------------ src/{aslib/prelude.mli => as_values/prim.mli} | 1 - src/as_values/show.ml | 66 +++++ src/as_values/show.mli | 4 + src/{aslib => as_values}/value.ml | 8 +- src/{aslib => as_values}/value.mli | 2 + src/aslib/compile.mli | 3 - src/aslib/effect.ml | 198 --------------- src/aslib/operator.mli | 10 - src/{aslib => codegen}/compile.ml | 70 +++--- src/codegen/compile.mli | 5 + src/codegen/dune | 4 + src/{aslib => codegen}/instrList.ml | 0 src/exes/as_js.ml | 2 +- src/exes/as_ld.ml | 3 +- src/exes/asc.ml | 2 +- src/exes/dune | 6 +- src/flags/dune | 4 + src/{aslib => flags}/flags.ml | 0 src/interpreter/dune | 4 + src/{aslib => interpreter}/interpret.ml | 8 +- src/{aslib => interpreter}/interpret.mli | 5 +- src/ir_interpreter/dune | 4 + src/{aslib => ir_interpreter}/interpret_ir.ml | 7 +- .../interpret_ir.mli | 4 + src/{aslib => ir_passes}/async.ml | 6 +- src/{aslib => ir_passes}/async.mli | 2 + src/{aslib => ir_passes}/await.ml | 5 +- src/{aslib => ir_passes}/await.mli | 2 +- src/ir_passes/dune | 4 + src/{aslib => ir_passes}/rename.ml | 3 +- src/{aslib => ir_passes}/serialization.ml | 4 + src/{aslib => ir_passes}/serialization.mli | 2 + src/{aslib => ir_passes}/show.ml | 5 +- src/{aslib => ir_passes}/show.mli | 4 + src/{aslib => ir_passes}/tailcall.ml | 8 +- src/{aslib => ir_passes}/tailcall.mli | 2 + src/{aslib => lang_utils}/diag.ml | 0 src/{aslib => lang_utils}/diag.mli | 0 src/{aslib => lang_utils}/dom.ml | 0 src/lang_utils/dune | 5 + src/{aslib => lang_utils}/env.ml | 0 src/{aslib => lang_utils}/nameRel.ml | 0 src/{aslib => lang_utils}/source.ml | 0 src/{aslib => lang_utils}/source.mli | 0 src/lib/dune | 1 + src/linking/dune | 4 + src/{aslib => linking}/linkModule.ml | 2 +- src/{aslib => linking}/linkModule.mli | 2 +- src/{aslib => lowering}/desugar.ml | 33 +-- src/{aslib => lowering}/desugar.mli | 3 + src/lowering/dune | 4 + src/pipeline/dune | 18 ++ src/{aslib => pipeline}/pipeline.ml | 33 +-- src/{aslib => pipeline}/pipeline.mli | 2 +- src/{aslib => pipeline}/resolve_import.ml | 2 + src/{aslib => pipeline}/resolve_import.mli | 2 + src/prelude/dune | 4 + src/prelude/prelude.ml | 235 +++++++++++++++++ src/prelude/prelude.mli | 1 + src/{aslib => wasm-exts}/customModule.ml | 0 .../customModuleDecode.ml | 0 .../customModuleDecode.mli | 0 .../customModuleEncode.ml | 0 .../customModuleEncode.mli | 0 src/wasm-exts/dune | 4 + 105 files changed, 977 insertions(+), 621 deletions(-) rename src/{aslib => as_frontend}/arrange.ml (98%) rename src/{aslib => as_frontend}/coverage.ml (99%) rename src/{aslib => as_frontend}/coverage.mli (87%) rename src/{aslib => as_frontend}/definedness.ml (100%) rename src/{aslib => as_frontend}/definedness.mli (100%) rename src/{aslib => as_frontend}/dune (51%) create mode 100644 src/as_frontend/effect.ml rename src/{aslib => as_frontend}/effect.mli (68%) rename src/{aslib => as_frontend}/lexer.mli (100%) rename src/{aslib => as_frontend}/lexer.mll (100%) rename src/{aslib => as_frontend}/parser.mly (99%) rename src/{aslib => as_frontend}/static.ml (100%) rename src/{aslib => as_frontend}/static.mli (100%) rename src/{aslib => as_frontend}/syntax.ml (86%) rename src/{aslib => as_frontend}/typing.ml (99%) rename src/{aslib => as_frontend}/typing.mli (96%) rename src/{aslib => as_ir}/arrange_ir.ml (98%) rename src/{aslib => as_ir}/check_ir.ml (99%) rename src/{aslib => as_ir}/check_ir.mli (79%) rename src/{aslib => as_ir}/construct.ml (96%) rename src/{aslib => as_ir}/construct.mli (99%) create mode 100644 src/as_ir/dune rename src/{aslib => as_ir}/freevars.ml (100%) rename src/{aslib => as_ir}/ir.ml (97%) create mode 100644 src/as_ir/ir_effect.ml create mode 100644 src/as_ir/ir_effect.mli create mode 120000 src/as_ld rename src/{aslib => as_types}/arrange_type.ml (100%) rename src/{aslib => as_types}/con.ml (100%) rename src/{aslib => as_types}/con.mli (100%) create mode 100644 src/as_types/dune rename src/{aslib => as_types}/type.ml (100%) rename src/{aslib => as_types}/type.mli (100%) create mode 100644 src/as_values/dune rename src/{aslib => as_values}/idlHash.ml (100%) rename src/{aslib => as_values}/idlHash.mli (100%) rename src/{aslib => as_values}/operator.ml (82%) create mode 100644 src/as_values/operator.mli rename src/{aslib/prelude.ml => as_values/prim.ml} (51%) rename src/{aslib/prelude.mli => as_values/prim.mli} (60%) create mode 100644 src/as_values/show.ml create mode 100644 src/as_values/show.mli rename src/{aslib => as_values}/value.ml (99%) rename src/{aslib => as_values}/value.mli (99%) delete mode 100644 src/aslib/compile.mli delete mode 100644 src/aslib/effect.ml delete mode 100644 src/aslib/operator.mli rename src/{aslib => codegen}/compile.ml (99%) create mode 100644 src/codegen/compile.mli create mode 100644 src/codegen/dune rename src/{aslib => codegen}/instrList.ml (100%) create mode 100644 src/flags/dune rename src/{aslib => flags}/flags.ml (100%) create mode 100644 src/interpreter/dune rename src/{aslib => interpreter}/interpret.ml (99%) rename src/{aslib => interpreter}/interpret.mli (84%) create mode 100644 src/ir_interpreter/dune rename src/{aslib => ir_interpreter}/interpret_ir.ml (99%) rename src/{aslib => ir_interpreter}/interpret_ir.mli (87%) rename src/{aslib => ir_passes}/async.ml (99%) rename src/{aslib => ir_passes}/async.mli (77%) rename src/{aslib => ir_passes}/await.ml (99%) rename src/{aslib => ir_passes}/await.mli (90%) create mode 100644 src/ir_passes/dune rename src/{aslib => ir_passes}/rename.ml (99%) rename src/{aslib => ir_passes}/serialization.ml (99%) rename src/{aslib => ir_passes}/serialization.mli (64%) rename src/{aslib => ir_passes}/show.ml (99%) rename src/{aslib => ir_passes}/show.mli (75%) rename src/{aslib => ir_passes}/tailcall.ml (99%) rename src/{aslib => ir_passes}/tailcall.mli (91%) rename src/{aslib => lang_utils}/diag.ml (100%) rename src/{aslib => lang_utils}/diag.mli (100%) rename src/{aslib => lang_utils}/dom.ml (100%) create mode 100644 src/lang_utils/dune rename src/{aslib => lang_utils}/env.ml (100%) rename src/{aslib => lang_utils}/nameRel.ml (100%) rename src/{aslib => lang_utils}/source.ml (100%) rename src/{aslib => lang_utils}/source.mli (100%) create mode 100644 src/linking/dune rename src/{aslib => linking}/linkModule.ml (99%) rename src/{aslib => linking}/linkModule.mli (51%) rename src/{aslib => lowering}/desugar.ml (93%) rename src/{aslib => lowering}/desugar.mli (81%) create mode 100644 src/lowering/dune create mode 100644 src/pipeline/dune rename src/{aslib => pipeline}/pipeline.ml (93%) rename src/{aslib => pipeline}/pipeline.mli (86%) rename src/{aslib => pipeline}/resolve_import.ml (99%) rename src/{aslib => pipeline}/resolve_import.mli (84%) create mode 100644 src/prelude/dune create mode 100644 src/prelude/prelude.ml create mode 100644 src/prelude/prelude.mli rename src/{aslib => wasm-exts}/customModule.ml (100%) rename src/{aslib => wasm-exts}/customModuleDecode.ml (100%) rename src/{aslib => wasm-exts}/customModuleDecode.mli (100%) rename src/{aslib => wasm-exts}/customModuleEncode.ml (100%) rename src/{aslib => wasm-exts}/customModuleEncode.mli (100%) create mode 100644 src/wasm-exts/dune diff --git a/src/Structure.md b/src/Structure.md index 12a11d0e3da..352549adca2 100644 --- a/src/Structure.md +++ b/src/Structure.md @@ -11,27 +11,101 @@ directory are part of the library. Within a library `lib`, modules are accessed using `Foo`; outside via `Lib.Foo`. Unless there is `lib/libml`, then this is the entry point. -Executables + +Libraries --------- +We split the files into the following subdirectories, topologically sorted. One +goal of the structure is to make it clear which parts operate on AS Source, AS +IR or Wasm, respectively. + +In parenthesis: which end-product is using these file, and which libraries this +is should depend on, omitting transitive dependencies. See the `*/dune` files +for the real deal; some shortcuts had to be taken. + + * `lib/` (all) + + Stuff that could be in the Ocaml standard library. + + * `lang-utils/` (asc, didc; using `lib/`) + + General PL-related utility-functions, useful for AS Source, AS IR, the IDL + AST: Environments, diagnostic error messages, source locations. + + * `as-types/` (asc; using `lang-utils/`) + + The ActorScript type definition, as used by both Source and IR. Includes + pretty-printer. Also includes the value definitions. + + * `as-values/` (asc; using `lang-utils/`) + + Value definitions, as used for literals, interpreter. Also includes + operations on values and primitive operations. + + * `as-frontend/` (asc; using `lang-utils/`) + + The ActorScript Source AST, including parser and type inference. + + * `as-ir/` (asc; using `lang-utils/`) + + The ActorScript IR AST, including type checker and pretty-printer. + + * `lowering/` (asc; using `as-frontent/` and `as-ir/`) + + The IR to Source pass. + + * `ir-passes/` (asc; using `as-ir/`) + + The various IR to IR passes. + + * `wasm-exts/` (asc, as-ld; using `lib/`) + + Extensions to the wasm library: Support for additional custom sections, + including serialization and de-serialization. + + * `linking/` (asc, as-ld; using `wasm-exts/`) + + Wasm linking code + + * `codegen/` (asc; using `as-ir/`, `linking/`) + + The backend, including the instruction list generator. + + * `interpreter/` (asc; using `as-frontend/`) + + Source interpreter. + + * `ir-interpreter/` (asc; using `as-ir/`) + + IR interpreter. + + * `pipeline/` (asc; using `as-frontend/`, `lowering/`, `ir-passes/`, `codegen/`, `interpreter/`, `interpreter-ir/`) + + The pipeline, prelude text and flags + + * `idllib/` + + Kitchen-sink of `didc` related files. Yet to be split up. + +Executables +----------- + All exectuables are in the directory `exe/`, and should be kept rather small; essentially only the command line parsing should be there, so that actual functionality is easily shared. + * `asc` (using `pipeline/`) -Libraries ---------- + The ActorScript compiler -We split the files into the following subdirectories + * `as.js` (using `pipeline/`) - * `lib/` + The ActorScript compiler, as a JS library - Stuff that could be in the Ocaml standard library. + * `as-ld` (using `linking/`) - * `aslib/` + The stand-alone Wasm linker - Kitchen-sink of `asc` and `as-ld` related files. Will be split soon. - - * `idllib/` + * `didc` (using `idl/`) - Kitchen-sink of `didc` related files. Will likely be split soon. + The IDL compiler diff --git a/src/aslib/arrange.ml b/src/as_frontend/arrange.ml similarity index 98% rename from src/aslib/arrange.ml rename to src/as_frontend/arrange.ml index afe8a307eda..ffe3818ad0d 100644 --- a/src/aslib/arrange.ml +++ b/src/as_frontend/arrange.ml @@ -1,3 +1,7 @@ +open As_types +open As_values +open As_values.Operator + open Source open Syntax open Wasm.Sexpr @@ -80,7 +84,7 @@ and lit (l:lit) = match l with | FloatLit f -> "FloatLit" $$ [ Atom (Value.Float.to_string f) ] | CharLit c -> "CharLit" $$ [ Atom (string_of_int c) ] | TextLit t -> "TextLit" $$ [ Atom t ] - | PreLit (s,p) -> "PreLit" $$ [ Atom s; prim p ] + | PreLit (s,p) -> "PreLit" $$ [ Atom s; Arrange_type.prim p ] and unop uo = match uo with | PosOp -> Atom "PosOp" @@ -116,8 +120,6 @@ and case c = "case" $$ [pat c.it.pat; exp c.it.exp] and pat_field pf = pf.it.id.it $$ [pat pf.it.pat] -and prim p = Atom (Type.string_of_prim p) - and sharing sh = match sh with | Type.Local -> "Local" | Type.Sharable -> "Sharable" diff --git a/src/aslib/coverage.ml b/src/as_frontend/coverage.ml similarity index 99% rename from src/aslib/coverage.ml rename to src/as_frontend/coverage.ml index 823b5e698ec..0f444651892 100644 --- a/src/aslib/coverage.ml +++ b/src/as_frontend/coverage.ml @@ -1,7 +1,9 @@ open Syntax open Source +open As_types +open As_values -module V = Value +module V = As_values.Value module ValSet = Set.Make(struct type t = V.value let compare = V.compare end) module TagSet = Set.Make(struct type t = string let compare = compare end) diff --git a/src/aslib/coverage.mli b/src/as_frontend/coverage.mli similarity index 87% rename from src/aslib/coverage.mli rename to src/as_frontend/coverage.mli index b0833624403..fe1c584c27d 100644 --- a/src/aslib/coverage.mli +++ b/src/as_frontend/coverage.mli @@ -1,2 +1,4 @@ +open As_types + val check_pat : Syntax.pat -> Type.typ -> bool val check_cases : Syntax.case list -> Type.typ -> bool diff --git a/src/aslib/definedness.ml b/src/as_frontend/definedness.ml similarity index 100% rename from src/aslib/definedness.ml rename to src/as_frontend/definedness.ml diff --git a/src/aslib/definedness.mli b/src/as_frontend/definedness.mli similarity index 100% rename from src/aslib/definedness.mli rename to src/as_frontend/definedness.mli diff --git a/src/aslib/dune b/src/as_frontend/dune similarity index 51% rename from src/aslib/dune rename to src/as_frontend/dune index ee1f37f92fa..fabe922c733 100644 --- a/src/aslib/dune +++ b/src/as_frontend/dune @@ -1,8 +1,7 @@ (library - (name aslib) - (libraries wasm num vlq yojson lib) + (name as_frontend) + (libraries lib lang_utils as_types as_values) ) - (menhir (modules parser) (infer false) diff --git a/src/as_frontend/effect.ml b/src/as_frontend/effect.ml new file mode 100644 index 00000000000..75e1cefff35 --- /dev/null +++ b/src/as_frontend/effect.ml @@ -0,0 +1,106 @@ +open Syntax +open Source +module T = As_types.Type + +(* a simple effect analysis to annote expressions as Triv(ial) (await-free) or Await (containing unprotected awaits) *) + +(* in future we could merge this with the type-checker + but I prefer to keep it mostly separate for now *) + +let max_eff e1 e2 = + match e1,e2 with + | T.Triv,T.Triv -> T.Triv + | _ , T.Await -> T.Await + | T.Await,_ -> T.Await + +let typ phrase = phrase.note.note_typ + +let eff phrase = phrase.note.note_eff + +let is_triv phrase = + eff phrase = T.Triv + +let effect_exp (exp:Syntax.exp) : T.eff = eff exp + +(* infer the effect of an expression, assuming all sub-expressions are correctly effect-annotated es*) +let rec infer_effect_exp (exp:Syntax.exp) : T.eff = + match exp.it with + | PrimE _ + | VarE _ + | LitE _ + | ImportE _ + | FuncE _ -> + T.Triv + | UnE (_, _, exp1) + | ShowE (_, exp1) + | ProjE (exp1, _) + | OptE exp1 + | TagE (_, exp1) + | DotE (exp1, _) + | NotE exp1 + | AssertE exp1 + | LabelE (_, _, exp1) + | BreakE (_, exp1) + | RetE exp1 + | AnnotE (exp1, _) + | LoopE (exp1, None) -> + effect_exp exp1 + | BinE (_, exp1, _, exp2) + | IdxE (exp1, exp2) + | RelE (_, exp1, _, exp2) + | AssignE (exp1, exp2) + | CallE (exp1, _, exp2) + | AndE (exp1, exp2) + | OrE (exp1, exp2) + | WhileE (exp1, exp2) + | LoopE (exp1, Some exp2) + | ForE (_, exp1, exp2) -> + let t1 = effect_exp exp1 in + let t2 = effect_exp exp2 in + max_eff t1 t2 + | TupE exps + | ArrayE (_, exps) -> + let es = List.map effect_exp exps in + List.fold_left max_eff T.Triv es + | BlockE decs -> + let es = List.map effect_dec decs in + List.fold_left max_eff T.Triv es + | ObjE (_, efs) -> + effect_field_exps efs + | IfE (exp1, exp2, exp3) -> + let e1 = effect_exp exp1 in + let e2 = effect_exp exp2 in + let e3 = effect_exp exp3 in + max_eff e1 (max_eff e2 e3) + | SwitchE (exp1, cases) -> + let e1 = effect_exp exp1 in + let e2 = effect_cases cases in + max_eff e1 e2 + | AsyncE exp1 -> + T.Triv + | AwaitE exp1 -> + T.Await + +and effect_cases cases = + match cases with + | [] -> + T.Triv + | {it = {pat; exp}; _}::cases' -> + let e = effect_exp exp in + max_eff e (effect_cases cases') + +and effect_field_exps efs = + List.fold_left (fun e (fld:exp_field) -> max_eff e (effect_dec fld.it.dec)) T.Triv efs + +and effect_dec dec = + dec.note.note_eff + +and infer_effect_dec dec = + match dec.it with + | ExpD e + | LetD (_,e) + | VarD (_, e) -> + effect_exp e + | TypD _ + | ClassD _ -> + T.Triv diff --git a/src/aslib/effect.mli b/src/as_frontend/effect.mli similarity index 68% rename from src/aslib/effect.mli rename to src/as_frontend/effect.mli index 5585f452ba8..e6093a419ed 100644 --- a/src/aslib/effect.mli +++ b/src/as_frontend/effect.mli @@ -1,6 +1,6 @@ open Source open Syntax -open Type +open As_types.Type val max_eff : eff -> eff -> eff @@ -15,11 +15,3 @@ val typ : ('a, typ_note) annotated_phrase -> typ val eff : ('a, typ_note) annotated_phrase -> eff val is_triv : ('a, typ_note) annotated_phrase -> bool - -(* (incremental) effect inference on IR *) - -module Ir : sig - val effect_exp: Ir.exp -> eff - val infer_effect_exp : Ir.exp -> eff - val infer_effect_dec : Ir.dec -> eff -end diff --git a/src/aslib/lexer.mli b/src/as_frontend/lexer.mli similarity index 100% rename from src/aslib/lexer.mli rename to src/as_frontend/lexer.mli diff --git a/src/aslib/lexer.mll b/src/as_frontend/lexer.mll similarity index 100% rename from src/aslib/lexer.mll rename to src/as_frontend/lexer.mll diff --git a/src/aslib/parser.mly b/src/as_frontend/parser.mly similarity index 99% rename from src/aslib/parser.mly rename to src/as_frontend/parser.mly index 3094a953f1f..960f8bc30d8 100644 --- a/src/aslib/parser.mly +++ b/src/as_frontend/parser.mly @@ -1,5 +1,6 @@ %{ - +open As_types +open As_values.Operator open Syntax open Source @@ -112,7 +113,7 @@ let share_expfield (ef : exp_field) = %token DOT_NUM %token NAT %token FLOAT -%token CHAR +%token CHAR %token BOOL %token ID %token TEXT diff --git a/src/aslib/static.ml b/src/as_frontend/static.ml similarity index 100% rename from src/aslib/static.ml rename to src/as_frontend/static.ml diff --git a/src/aslib/static.mli b/src/as_frontend/static.mli similarity index 100% rename from src/aslib/static.mli rename to src/as_frontend/static.mli diff --git a/src/aslib/syntax.ml b/src/as_frontend/syntax.ml similarity index 86% rename from src/aslib/syntax.ml rename to src/as_frontend/syntax.ml index bebe28968ea..4ee0ae7efd3 100644 --- a/src/aslib/syntax.ml +++ b/src/as_frontend/syntax.ml @@ -1,3 +1,7 @@ +open As_types +open As_values +open As_values.Operator + (* Notes *) type typ_note = {note_typ : Type.typ; note_eff : Type.eff} @@ -68,39 +72,6 @@ type lit = | PreLit of string * Type.prim -(* Operators *) - -type unop = - | PosOp (* +x *) - | NegOp (* -x *) - | NotOp (* bitwise negation *) - -type binop = - | AddOp (* x+y *) - | SubOp (* x-y *) - | MulOp (* x*y *) - | DivOp (* x/y *) - | ModOp (* x%y *) - | PowOp (* x^y *) - | AndOp (* bitwise operators... *) - | OrOp - | XorOp - | ShLOp - | UShROp - | SShROp - | RotLOp - | RotROp - | CatOp (* concatenation *) - -type relop = - | EqOp (* x=y *) - | NeqOp (* x!=y *) - | LtOp (* xy *) - | LeOp (* x<=y *) - | GeOp (* x>=y *) - - (* Patterns *) type pat = (pat', Type.typ) Source.annotated_phrase diff --git a/src/aslib/typing.ml b/src/as_frontend/typing.ml similarity index 99% rename from src/aslib/typing.ml rename to src/as_frontend/typing.ml index e43c8bf8ba6..191aa5bd4eb 100644 --- a/src/aslib/typing.ml +++ b/src/as_frontend/typing.ml @@ -1,12 +1,11 @@ open Syntax open Source +open As_types +open As_values module T = Type module A = Effect - - - (* Error recovery *) exception Recover diff --git a/src/aslib/typing.mli b/src/as_frontend/typing.mli similarity index 96% rename from src/aslib/typing.mli rename to src/as_frontend/typing.mli index 247cd62dad4..d98a0deb1c9 100644 --- a/src/aslib/typing.mli +++ b/src/as_frontend/typing.mli @@ -1,4 +1,4 @@ -open Type +open As_types.Type type val_env = typ Env.t type lib_env = typ Env.t diff --git a/src/aslib/arrange_ir.ml b/src/as_ir/arrange_ir.ml similarity index 98% rename from src/aslib/arrange_ir.ml rename to src/as_ir/arrange_ir.ml index 313a5814876..053f118700b 100644 --- a/src/aslib/arrange_ir.ml +++ b/src/as_ir/arrange_ir.ml @@ -1,5 +1,8 @@ +open As_frontend +open As_types +open As_values open Source -open Arrange_type (* currently not used *) +open Arrange_type open Ir open Wasm.Sexpr diff --git a/src/aslib/check_ir.ml b/src/as_ir/check_ir.ml similarity index 99% rename from src/aslib/check_ir.ml rename to src/as_ir/check_ir.ml index 95773794f07..4e6b4e800f5 100644 --- a/src/aslib/check_ir.ml +++ b/src/as_ir/check_ir.ml @@ -1,6 +1,10 @@ +open As_types +open As_frontend +open As_values + open Source module T = Type -module E = Effect +module E = Ir_effect (* TODO: remove DecE from syntax, replace by BlockE [dec] *) (* TODO: check constraint matching supports recursive bounds *) @@ -279,7 +283,7 @@ let rec check_exp env (exp:Ir.exp) : unit = let t = E.typ exp in check_typ env t; (* check effect annotation *) - check (E.Ir.infer_effect_exp exp <= E.eff exp) + check (E.infer_effect_exp exp <= E.eff exp) "inferred effect not a subtype of expected effect"; (* check typing *) match exp.it with diff --git a/src/aslib/check_ir.mli b/src/as_ir/check_ir.mli similarity index 79% rename from src/aslib/check_ir.mli rename to src/as_ir/check_ir.mli index f5d7044aa40..c8a9a7506d4 100644 --- a/src/aslib/check_ir.mli +++ b/src/as_ir/check_ir.mli @@ -1 +1,2 @@ +open As_frontend val check_prog : bool -> Typing.scope -> string -> Ir.prog -> unit diff --git a/src/aslib/construct.ml b/src/as_ir/construct.ml similarity index 96% rename from src/aslib/construct.ml rename to src/as_ir/construct.ml index 10dfc87aea7..56b3c61124a 100644 --- a/src/aslib/construct.ml +++ b/src/as_ir/construct.ml @@ -1,10 +1,13 @@ +open As_frontend +open As_values + (* WIP translation of syntaxops to use IR in place of Source *) open Source open Ir -open Effect +open Ir_effect module S = Syntax -module T = Type +module T = As_types.Type type var = exp @@ -220,7 +223,7 @@ let switch_variantE exp1 cases typ1 = let tupE exps = let effs = List.map eff exps in - let eff = List.fold_left max_eff Type.Triv effs in + let eff = List.fold_left max_eff T.Triv effs in { it = TupE exps; at = no_region; note = { S.note_typ = T.Tup (List.map typ exps); @@ -231,14 +234,14 @@ let breakE l exp = { it = BreakE (l, exp); at = no_region; note = { S.note_eff = eff exp; - S.note_typ = Type.Non } + S.note_typ = T.Non } } let retE exp = { it = RetE exp; at = no_region; note = { S.note_eff = eff exp; - S.note_typ = Type.Non } + S.note_typ = T.Non } } let immuteE e = @@ -253,7 +256,7 @@ let assignE exp1 exp2 = { it = AssignE (exp1, exp2); at = no_region; note = { S.note_eff = Effect.max_eff (eff exp1) (eff exp2); - S.note_typ = Type.unit } + S.note_typ = T.unit } } let labelE l typ exp = @@ -434,7 +437,7 @@ let ( -*- ) exp1 exp2 = | typ1 -> failwith (Printf.sprintf "Impossible: \n func: %s \n : %s arg: \n %s" (Wasm.Sexpr.to_string 80 (Arrange_ir.exp exp1)) - (Type.string_of_typ typ1) + (T.string_of_typ typ1) (Wasm.Sexpr.to_string 80 (Arrange_ir.exp exp2))) @@ -497,15 +500,15 @@ let forE pat exp1 exp2 = } *) let lab = fresh_id "done" () in let ty1 = exp1.note.S.note_typ in - let _, tfs = Type.as_obj_sub "next" ty1 in + let _, tfs = T.as_obj_sub "next" ty1 in let tnxt = Lib.Option.value (T.lookup_val_field "next" tfs) in let nxt = fresh_var "nxt" tnxt in letE nxt (dotE exp1 (nameN "next") tnxt) ( - labelE lab Type.unit ( + labelE lab T.unit ( loopE ( switch_optE (callE nxt [] (tupE [])) (breakE lab (tupE [])) - pat exp2 Type.unit + pat exp2 T.unit ) ) ) diff --git a/src/aslib/construct.mli b/src/as_ir/construct.mli similarity index 99% rename from src/aslib/construct.mli rename to src/as_ir/construct.mli index 019c4db1220..28f36f9c691 100644 --- a/src/aslib/construct.mli +++ b/src/as_ir/construct.mli @@ -1,3 +1,5 @@ +open As_types + open Ir open Type diff --git a/src/as_ir/dune b/src/as_ir/dune new file mode 100644 index 00000000000..462598f3b1b --- /dev/null +++ b/src/as_ir/dune @@ -0,0 +1,4 @@ +(library + (name as_ir) + (libraries lib as_types as_values as_frontend) +) diff --git a/src/aslib/freevars.ml b/src/as_ir/freevars.ml similarity index 100% rename from src/aslib/freevars.ml rename to src/as_ir/freevars.ml diff --git a/src/aslib/ir.ml b/src/as_ir/ir.ml similarity index 97% rename from src/aslib/ir.ml rename to src/as_ir/ir.ml index 89bb65d1800..c829d044c23 100644 --- a/src/aslib/ir.ml +++ b/src/as_ir/ir.ml @@ -1,3 +1,7 @@ +open As_types +open As_values +open As_frontend (* TODO *) + (* Patterns *) type type_note = Syntax.typ_note = {note_typ : Type.typ; note_eff : Type.eff} @@ -8,9 +12,9 @@ type typ_bind = typ_bind' Source.phrase type id = Syntax.id type lit = Syntax.lit -type unop = Syntax.unop -type binop = Syntax.binop -type relop = Syntax.relop +type unop = Operator.unop +type binop = Operator.binop +type relop = Operator.relop type mut = Syntax.mut type vis = Syntax.vis diff --git a/src/as_ir/ir_effect.ml b/src/as_ir/ir_effect.ml new file mode 100644 index 00000000000..43289ba8101 --- /dev/null +++ b/src/as_ir/ir_effect.ml @@ -0,0 +1,102 @@ +open Ir +open Source +module T = As_types.Type + +(* a simple effect analysis to annote expressions as Triv(ial) (await-free) or Await (containing unprotected awaits) *) + +(* in future we could merge this with the type-checker + but I prefer to keep it mostly separate for now *) + +let max_eff e1 e2 = + match e1,e2 with + | T.Triv,T.Triv -> T.Triv + | _ , T.Await -> T.Await + | T.Await,_ -> T.Await + +let typ phrase = phrase.note.note_typ + +let eff phrase = phrase.note.note_eff + +let is_triv phrase = + eff phrase = T.Triv + +let effect_exp (exp: exp) : T.eff = eff exp + +(* infer the effect of an expression, assuming all sub-expressions are correctly effect-annotated es*) +let rec infer_effect_exp (exp: exp) : T.eff = + match exp.it with + | PrimE _ + | VarE _ + | LitE _ -> + T.Triv + | UnE (_, _, exp1) + | ShowE (_, exp1) + | ProjE (exp1, _) + | OptE exp1 + | TagE (_, exp1) + | DotE (exp1, _) + | ActorDotE (exp1, _) + | AssertE exp1 + | LabelE (_, _, exp1) + | BreakE (_, exp1) + | RetE exp1 + | LoopE exp1 -> + effect_exp exp1 + | BinE (_, exp1, _, exp2) + | IdxE (exp1, exp2) + | RelE (_, exp1, _, exp2) + | AssignE (exp1, exp2) + | CallE (_, exp1, _, exp2) -> + let t1 = effect_exp exp1 in + let t2 = effect_exp exp2 in + max_eff t1 t2 + | TupE exps + | ArrayE (_, _, exps) -> + let es = List.map effect_exp exps in + List.fold_left max_eff T.Triv es + | BlockE (ds, exp) -> + let es = List.map effect_dec ds in + List.fold_left max_eff (effect_exp exp) es + | IfE (exp1, exp2, exp3) -> + let e1 = effect_exp exp1 in + let e2 = effect_exp exp2 in + let e3 = effect_exp exp3 in + max_eff e1 (max_eff e2 e3) + | SwitchE (exp1, cases) -> + let e1 = effect_exp exp1 in + let e2 = effect_cases cases in + max_eff e1 e2 + | AsyncE exp1 -> + T.Triv + | AwaitE exp1 -> + T.Await + | DeclareE (_, _, exp1) -> + effect_exp exp1 + | DefineE (_, _, exp1) -> + effect_exp exp1 + | FuncE _ -> + T.Triv + | ActorE _ -> + T.Triv + | NewObjE _ -> + T.Triv + +and effect_cases cases = + match cases with + | [] -> + T.Triv + | {it = {pat; exp}; _}::cases' -> + let e = effect_exp exp in + max_eff e (effect_cases cases') + +and effect_dec dec = match dec.it with + | TypD _ -> T.Triv + | LetD (_,e) | VarD (_,e) -> effect_exp e + +and infer_effect_dec (dec:Ir.dec) = + match dec.it with + | LetD (_,e) + | VarD (_, e) -> + effect_exp e + | TypD _ -> + T.Triv diff --git a/src/as_ir/ir_effect.mli b/src/as_ir/ir_effect.mli new file mode 100644 index 00000000000..4a55e902ddf --- /dev/null +++ b/src/as_ir/ir_effect.mli @@ -0,0 +1,17 @@ +open As_frontend +open Syntax +open Source +open As_types.Type + +val max_eff : eff -> eff -> eff + +(* (incremental) effect inference on IR *) + +val typ : ('a, typ_note) annotated_phrase -> typ +val eff : ('a, typ_note) annotated_phrase -> eff + +val is_triv : ('a, typ_note) annotated_phrase -> bool + +val effect_exp: Ir.exp -> eff +val infer_effect_exp : Ir.exp -> eff +val infer_effect_dec : Ir.dec -> eff diff --git a/src/as_ld b/src/as_ld new file mode 120000 index 00000000000..8ed244c2d96 --- /dev/null +++ b/src/as_ld @@ -0,0 +1 @@ +_build/default/exes/as_ld.exe \ No newline at end of file diff --git a/src/aslib/arrange_type.ml b/src/as_types/arrange_type.ml similarity index 100% rename from src/aslib/arrange_type.ml rename to src/as_types/arrange_type.ml diff --git a/src/aslib/con.ml b/src/as_types/con.ml similarity index 100% rename from src/aslib/con.ml rename to src/as_types/con.ml diff --git a/src/aslib/con.mli b/src/as_types/con.mli similarity index 100% rename from src/aslib/con.mli rename to src/as_types/con.mli diff --git a/src/as_types/dune b/src/as_types/dune new file mode 100644 index 00000000000..1dab68e6563 --- /dev/null +++ b/src/as_types/dune @@ -0,0 +1,4 @@ +(library + (name as_types) + (libraries wasm lib lang_utils) +) diff --git a/src/aslib/type.ml b/src/as_types/type.ml similarity index 100% rename from src/aslib/type.ml rename to src/as_types/type.ml diff --git a/src/aslib/type.mli b/src/as_types/type.mli similarity index 100% rename from src/aslib/type.mli rename to src/as_types/type.mli diff --git a/src/as_values/dune b/src/as_values/dune new file mode 100644 index 00000000000..efdce94254e --- /dev/null +++ b/src/as_values/dune @@ -0,0 +1,4 @@ +(library + (name as_values) + (libraries num wasm lib lang_utils as_types) +) diff --git a/src/aslib/idlHash.ml b/src/as_values/idlHash.ml similarity index 100% rename from src/aslib/idlHash.ml rename to src/as_values/idlHash.ml diff --git a/src/aslib/idlHash.mli b/src/as_values/idlHash.mli similarity index 100% rename from src/aslib/idlHash.mli rename to src/as_values/idlHash.mli diff --git a/src/aslib/operator.ml b/src/as_values/operator.ml similarity index 82% rename from src/aslib/operator.ml rename to src/as_values/operator.ml index b937a2346bc..1e183741407 100644 --- a/src/aslib/operator.ml +++ b/src/as_values/operator.ml @@ -1,8 +1,38 @@ -open Syntax open Value -module T = Type - +module T = As_types.Type + +(* Operators *) + +type unop = + | PosOp (* +x *) + | NegOp (* -x *) + | NotOp (* bitwise negation *) + +type binop = + | AddOp (* x+y *) + | SubOp (* x-y *) + | MulOp (* x*y *) + | DivOp (* x/y *) + | ModOp (* x%y *) + | PowOp (* x^y *) + | AndOp (* bitwise operators... *) + | OrOp + | XorOp + | ShLOp + | UShROp + | SShROp + | RotLOp + | RotROp + | CatOp (* concatenation *) + +type relop = + | EqOp (* x=y *) + | NeqOp (* x!=y *) + | LtOp (* xy *) + | LeOp (* x<=y *) + | GeOp (* x>=y *) let impossible _ = raise (Invalid_argument "impossible") diff --git a/src/as_values/operator.mli b/src/as_values/operator.mli new file mode 100644 index 00000000000..4c1150c4dd0 --- /dev/null +++ b/src/as_values/operator.mli @@ -0,0 +1,43 @@ +open As_types.Type +open Value + +(* Operators *) + +type unop = + | PosOp (* +x *) + | NegOp (* -x *) + | NotOp (* bitwise negation *) + +type binop = + | AddOp (* x+y *) + | SubOp (* x-y *) + | MulOp (* x*y *) + | DivOp (* x/y *) + | ModOp (* x%y *) + | PowOp (* x^y *) + | AndOp (* bitwise operators... *) + | OrOp + | XorOp + | ShLOp + | UShROp + | SShROp + | RotLOp + | RotROp + | CatOp (* concatenation *) + +type relop = + | EqOp (* x=y *) + | NeqOp (* x!=y *) + | LtOp (* xy *) + | LeOp (* x<=y *) + | GeOp (* x>=y *) + + +val unop : typ -> unop -> (value -> value) (* raise Invalid_argument *) +val binop : typ -> binop -> (value -> value -> value) (* raise Invalid_argument *) +val relop : typ -> relop -> (value -> value -> value) (* raise Invalid_argument *) + +val has_unop : typ -> unop -> bool +val has_binop : typ -> binop -> bool +val has_relop : typ -> relop -> bool diff --git a/src/aslib/prelude.ml b/src/as_values/prim.ml similarity index 51% rename from src/aslib/prelude.ml rename to src/as_values/prim.ml index 5e4d71d466d..20575609b20 100644 --- a/src/aslib/prelude.ml +++ b/src/as_values/prim.ml @@ -1,239 +1,3 @@ -let prelude = -{| -type Any = prim "Any"; -type None = prim "None"; -type Shared = prim "Shared"; -type Null = prim "Null"; -type Bool = prim "Bool"; -type Nat = prim "Nat"; -type Int = prim "Int"; -type Word8 = prim "Word8"; -type Word16 = prim "Word16"; -type Word32 = prim "Word32"; -type Word64 = prim "Word64"; -type Float = prim "Float"; -type Char = prim "Char"; -type Text = prim "Text"; - -type Iter = {next : () -> ?T_}; - -func abs(x : Int) : Nat { (prim "abs" : Int -> Nat) x }; - -func ignore(_ : Any) {}; - -class range(x : Nat, y : Nat) { - private var i = x; - next() : ?Nat { if (i > y) null else {let j = i; i += 1; ?j} }; -}; - -class revrange(x : Nat, y : Nat) { - private var i = x + 1; - next() : ?Nat { if (i <= y) null else {i -= 1; ?i} }; -}; - -// for testing -func idlHash(x : Text) : Word32 { (prim "idlHash" : Text -> Word32) x }; - -func charToText(c : Char) : Text = (prim "Char->Text" : Char -> Text) c; - -func printInt(x : Int) { print (@text_of_Int x) }; -func printChar(x : Char) { print (charToText x) }; -func print(x : Text) { (prim "print" : Text -> ()) x }; -func rts_version() : Text { (prim "rts_version" : () -> Text) () }; - -// Hashing -func hashInt(x : Int) : Word32 { - var n = x; - var hash : Word32 = 0; - if (n < 0) { - hash := ^hash; - n := abs n; - }; - let base = 2**32; - while (n > 0) { - hash ^= intToWord32(n % base); - n /= base; - }; - return hash; -}; - -// Conversions -func natToWord8(n : Nat) : Word8 = (prim "Nat->Word8" : Nat -> Word8) n; -func word8ToNat(n : Word8) : Nat = (prim "Word8->Nat" : Word8 -> Nat) n; -func intToWord8(n : Int) : Word8 = (prim "Int->Word8" : Int -> Word8) n; -func word8ToInt(n : Word8) : Int = (prim "Word8->Int" : Word8 -> Int) n; - -func natToWord16(n : Nat) : Word16 = (prim "Nat->Word16" : Nat -> Word16) n; -func word16ToNat(n : Word16) : Nat = (prim "Word16->Nat" : Word16 -> Nat) n; -func intToWord16(n : Int) : Word16 = (prim "Int->Word16" : Int -> Word16) n; -func word16ToInt(n : Word16) : Int = (prim "Word16->Int" : Word16 -> Int) n; - -func natToWord32(n : Nat) : Word32 = (prim "Nat->Word32" : Nat -> Word32) n; -func word32ToNat(n : Word32) : Nat = (prim "Word32->Nat" : Word32 -> Nat) n; -func intToWord32(n : Int) : Word32 = (prim "Int->Word32" : Int -> Word32) n; -func word32ToInt(n : Word32) : Int = (prim "Word32->Int" : Word32 -> Int) n; - -func natToWord64(n : Nat) : Word64 = (prim "Nat->Word64" : Nat -> Word64) n; -func word64ToNat(n : Word64) : Nat = (prim "Word64->Nat" : Word64 -> Nat) n; -func intToWord64(n : Int) : Word64 = (prim "Int->Word64" : Int -> Word64) n; -func word64ToInt(n : Word64) : Int = (prim "Word64->Int" : Word64 -> Int) n; - -func charToWord32(c : Char) : Word32 = (prim "Char->Word32" : Char -> Word32) c; -func word32ToChar(w : Word32) : Char = (prim "Word32->Char" : Word32 -> Char) w; -func decodeUTF8(s : Text) : (Word32, Char) = (prim "decodeUTF8" : Text -> (Word32, Char)) s; - -// Exotic bitwise operations -func popcntWord8(w : Word8) : Word8 = (prim "popcnt8" : Word8 -> Word8) w; -func clzWord8(w : Word8) : Word8 = (prim "clz8" : Word8 -> Word8) w; -func ctzWord8(w : Word8) : Word8 = (prim "ctz8" : Word8 -> Word8) w; -func btstWord8(w : Word8, amount : Word8) : Bool = (prim "btst8" : (Word8, Word8) -> Word8) (w, amount) != (0 : Word8); - -func popcntWord16(w : Word16) : Word16 = (prim "popcnt16" : Word16 -> Word16) w; -func clzWord16(w : Word16) : Word16 = (prim "clz16" : Word16 -> Word16) w; -func ctzWord16(w : Word16) : Word16 = (prim "ctz16" : Word16 -> Word16) w; -func btstWord16(w : Word16, amount : Word16) : Bool = (prim "btst16" : (Word16, Word16) -> Word16) (w, amount) != (0 : Word16); - -func popcntWord32(w : Word32) : Word32 = (prim "popcnt" : Word32 -> Word32) w; -func clzWord32(w : Word32) : Word32 = (prim "clz" : Word32 -> Word32) w; -func ctzWord32(w : Word32) : Word32 = (prim "ctz" : Word32 -> Word32) w; -func btstWord32(w : Word32, amount : Word32) : Bool = (prim "btst" : (Word32, Word32) -> Word32) (w, amount) != (0 : Word32); - -func popcntWord64(w : Word64) : Word64 = (prim "popcnt64" : Word64 -> Word64) w; -func clzWord64(w : Word64) : Word64 = (prim "clz64" : Word64 -> Word64) w; -func ctzWord64(w : Word64) : Word64 = (prim "ctz64" : Word64 -> Word64) w; -func btstWord64(w : Word64, amount : Word64) : Bool = (prim "btst64" : (Word64, Word64) -> Word64) (w, amount) != (0 : Word64); - -// Internal helper functions for the show translation - -// The @ in the name ensures that this cannot be shadowed by user code, so -// compiler passes can rely on them being in scope -// The text_of functions do not need to be exposed; the user can just use -// the show above. - -func @text_of_Nat(x : Nat) : Text { - var text = ""; - var n = x; - let base = 10; - let digits = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]; - - assert(n >= 0); - - if (n == 0) { - return "0"; - }; - - while (n > 0) { - let rem = n % base; - text := digits[rem] # text; - n := n / base; - }; - return text; -}; - -func @text_of_Int(x : Int) : Text { - if (x == 0) { - return "0"; - }; - if (x < 0) { - "-" # @text_of_Nat(abs x) - } else { - @text_of_Nat(abs x) - } -}; - -func @text_of_Bool(b : Bool) : Text { - if (b) "true" else "false" -}; - -func @text_of_Text(t : Text) : Text { - // TODO: Escape properly - "\"" # t # "\""; -}; - -func @text_of_option(f : T -> Text, x : ?T) : Text { - switch (x) { - case (?y) {"?(" # f y # ")"}; - case null {"null"}; - } -}; - -func @text_of_variant(l : Text, f : T -> Text, x : T) : Text { - let fx = f x; - if (fx == "()") "(#" # l # ")" - else "(#" # l # " " # fx # ")" -}; - -func @text_of_array(f : T -> Text, xs : [T]) : Text { - var text = ""; - for (x in xs.vals()) { - if (text == "") { - text := text # "["; - } else { - text := text # ", "; - }; - text := text # f x; - }; - text := text # "]"; - return text; -}; - -func @text_of_array_mut(f : T -> Text, xs : [var T]) : Text { - var text = ""; - for (x in xs.vals()) { - if (text == "") { - text := text # "[var "; - } else { - text := text # ", "; - }; - text := text # f x; - }; - text := text # "]"; - return text; -}; - -// Array utilities - -// This would be nicer as a objects, but lets do them as functions -// until the compiler has a concept of “static objects” -func Array_init(len : Nat, x : T) : [var T] { - (prim "Array.init" : (Nat, T) -> [var T])(len, x) -}; - -func Array_tabulate(len : Nat, gen : Nat -> T) : [T] { - (prim "Array.tabulate" : (Nat, Nat -> T) -> [T])(len, gen) -}; - -type Cont = T -> () ; -type Async = Cont -> (); - -func @new_async():(Async, Cont) { - let empty = func k (t:T) = (); - var result : ?T = null; - var ks : T -> () = empty; - func fulfill(t:T):() { - switch(result) { - case null { - result := ?t; - let ks_ = ks; - ks := empty; - ks_(t); - }; - case (?t) (assert(false)); - }; - }; - func enqueue(k:Cont):() { - switch(result) { - case null { - let ks_ = ks; - ks := (func (t:T) {ks_(t);k(t);}); - }; - case (?t) (k(t)); - }; - }; - (enqueue,fulfill) -}; -|} - (* Primitives *) open Value diff --git a/src/aslib/prelude.mli b/src/as_values/prim.mli similarity index 60% rename from src/aslib/prelude.mli rename to src/as_values/prim.mli index 963d419f648..ae9fff98e92 100644 --- a/src/aslib/prelude.mli +++ b/src/as_values/prim.mli @@ -1,2 +1 @@ -val prelude : string val prim : string -> Value.func diff --git a/src/as_values/show.ml b/src/as_values/show.ml new file mode 100644 index 00000000000..d89c67ffb15 --- /dev/null +++ b/src/as_values/show.ml @@ -0,0 +1,66 @@ +module T = As_types.Type + +(* Entry point for type checking: *) + +let rec can_show t = + let t = T.normalize t in + match t with + | T.Prim T.Bool + | T.Prim T.Nat + | T.Prim T.Int + | T.Prim T.Text + | T.Prim T.Null -> true + | T.Tup ts' -> List.for_all can_show ts' + | T.Opt t' -> can_show t' + | T.Array t' -> can_show (T.as_immut t') + | T.Obj (T.Object _, fs) -> + List.for_all (fun f -> can_show (T.as_immut f.T.typ)) fs + | T.Variant cts -> + List.for_all (fun f -> can_show f.T.typ) cts + | _ -> false + +(* Entry point for the interpreter (reference implementation) *) + +let rec show_val t v = + let t = T.normalize t in + match t, v with + | T.Prim T.Bool, Value.Bool b -> if b then "true" else "false" + | T.Prim T.Nat, Value.Int i -> Value.Int.to_string i + | T.Prim T.Int, Value.Int i -> Value.Int.to_string i + | T.Prim T.Text, Value.Text s -> "\"" ^ s ^ "\"" + | T.Prim T.Null, Value.Null -> "null" + | T.Opt _, Value.Null -> "null" + | T.Opt t', Value.Opt v -> "?(" ^ show_val t' v ^ ")" + | T.Tup ts', Value.Tup vs -> + Printf.sprintf "(%s%s)" + (String.concat ", " (List.map2 show_val ts' vs)) + (if List.length vs = 1 then "," else "") + | T.Array (T.Mut t'), Value.Array a -> + Printf.sprintf "[var %s]" + (String.concat ", " (List.map (fun v -> show_val t' !(Value.as_mut v)) (Array.to_list a))) + | T.Array t', Value.Array a -> + Printf.sprintf "[%s]" + (String.concat ", " (List.map (show_val t') (Array.to_list a))) + | T.Obj (_, fts), Value.Obj fs -> + Printf.sprintf "{%s}" (String.concat "; " (List.map (show_field fs) fts)) + | T.Variant fs, Value.Variant (l, v) -> + begin match List.find_opt (fun {T.lab = l'; _} -> l = l') fs with + | Some {T.typ = T.Tup []; _} -> Printf.sprintf "(#%s)" l + | Some {T.typ = t'; _} -> Printf.sprintf "(#%s %s)" l (show_val t' v) + | _ -> assert false + end + | _ -> + Printf.eprintf "show_val: %s : %s\n" (Value.string_of_val 2 v) (T.string_of_typ t); + assert false + +and show_field fs ft = + let v = Value.Env.find ft.T.lab fs in + let m, t', v' = + match ft.T.typ with + | T.Mut t' -> "var ", t', !(Value.as_mut v) + | t' -> "", t', v + in + (* With types: + Printf.sprintf "%s%s : %s = %s" m ft.T.name (T.string_of_typ t') (show_val t' v') + *) + Printf.sprintf "%s = %s" ft.T.lab (show_val t' v') diff --git a/src/as_values/show.mli b/src/as_values/show.mli new file mode 100644 index 00000000000..289cfc6269d --- /dev/null +++ b/src/as_values/show.mli @@ -0,0 +1,4 @@ +open As_types +val can_show : Type.typ -> bool +val show_val : Type.typ -> Value.value -> string + diff --git a/src/aslib/value.ml b/src/as_values/value.ml similarity index 99% rename from src/aslib/value.ml rename to src/as_values/value.ml index 2307a55c4c3..0abab03142c 100644 --- a/src/aslib/value.ml +++ b/src/as_values/value.ml @@ -1,5 +1,5 @@ open Printf -module T = Type +module T = As_types.Type (* Environments *) @@ -194,15 +194,15 @@ end type unicode = int type call_conv = { - sort: Type.sharing; - control : Type.control; + sort: T.sharing; + control : T.control; n_args : int; n_res : int; } let call_conv_of_typ typ = match typ with - | Type.Func(sort, control, tbds, dom, res) -> + | T.Func(sort, control, tbds, dom, res) -> { sort; control; n_args = List.length dom; n_res = List.length res } | _ -> raise (Invalid_argument ("call_conv_of_typ " ^ T.string_of_typ typ)) diff --git a/src/aslib/value.mli b/src/as_values/value.mli similarity index 99% rename from src/aslib/value.mli rename to src/as_values/value.mli index 08f3be96ca1..8fa1f0b8e5a 100644 --- a/src/aslib/value.mli +++ b/src/as_values/value.mli @@ -1,3 +1,5 @@ +open As_types + (* Numeric Representations *) module type WordType = diff --git a/src/aslib/compile.mli b/src/aslib/compile.mli deleted file mode 100644 index 35dcd8b81c8..00000000000 --- a/src/aslib/compile.mli +++ /dev/null @@ -1,3 +0,0 @@ -type mode = WasmMode | DfinityMode - -val compile : mode -> string -> CustomModule.extended_module option -> Ir.prog -> Ir.prog list -> CustomModule.extended_module diff --git a/src/aslib/effect.ml b/src/aslib/effect.ml deleted file mode 100644 index d3d04e35e67..00000000000 --- a/src/aslib/effect.ml +++ /dev/null @@ -1,198 +0,0 @@ -open Syntax -open Source -module T = Type - -(* a simple effect analysis to annote expressions as Triv(ial) (await-free) or Await (containing unprotected awaits) *) - -(* in future we could merge this with the type-checker - but I prefer to keep it mostly separate for now *) - -let max_eff e1 e2 = - match e1,e2 with - | T.Triv,T.Triv -> T.Triv - | _ , T.Await -> T.Await - | T.Await,_ -> T.Await - -let typ phrase = phrase.note.note_typ - -let eff phrase = phrase.note.note_eff - -let is_triv phrase = - eff phrase = T.Triv - -let effect_exp (exp:Syntax.exp) : T.eff = eff exp - -(* infer the effect of an expression, assuming all sub-expressions are correctly effect-annotated es*) -let rec infer_effect_exp (exp:Syntax.exp) : T.eff = - match exp.it with - | PrimE _ - | VarE _ - | LitE _ - | ImportE _ - | FuncE _ -> - T.Triv - | UnE (_, _, exp1) - | ShowE (_, exp1) - | ProjE (exp1, _) - | OptE exp1 - | TagE (_, exp1) - | DotE (exp1, _) - | NotE exp1 - | AssertE exp1 - | LabelE (_, _, exp1) - | BreakE (_, exp1) - | RetE exp1 - | AnnotE (exp1, _) - | LoopE (exp1, None) -> - effect_exp exp1 - | BinE (_, exp1, _, exp2) - | IdxE (exp1, exp2) - | RelE (_, exp1, _, exp2) - | AssignE (exp1, exp2) - | CallE (exp1, _, exp2) - | AndE (exp1, exp2) - | OrE (exp1, exp2) - | WhileE (exp1, exp2) - | LoopE (exp1, Some exp2) - | ForE (_, exp1, exp2) -> - let t1 = effect_exp exp1 in - let t2 = effect_exp exp2 in - max_eff t1 t2 - | TupE exps - | ArrayE (_, exps) -> - let es = List.map effect_exp exps in - List.fold_left max_eff Type.Triv es - | BlockE decs -> - let es = List.map effect_dec decs in - List.fold_left max_eff Type.Triv es - | ObjE (_, efs) -> - effect_field_exps efs - | IfE (exp1, exp2, exp3) -> - let e1 = effect_exp exp1 in - let e2 = effect_exp exp2 in - let e3 = effect_exp exp3 in - max_eff e1 (max_eff e2 e3) - | SwitchE (exp1, cases) -> - let e1 = effect_exp exp1 in - let e2 = effect_cases cases in - max_eff e1 e2 - | AsyncE exp1 -> - T.Triv - | AwaitE exp1 -> - T.Await - -and effect_cases cases = - match cases with - | [] -> - T.Triv - | {it = {pat; exp}; _}::cases' -> - let e = effect_exp exp in - max_eff e (effect_cases cases') - -and effect_field_exps efs = - List.fold_left (fun e (fld:exp_field) -> max_eff e (effect_dec fld.it.dec)) T.Triv efs - -and effect_dec dec = - dec.note.note_eff - -and infer_effect_dec dec = - match dec.it with - | ExpD e - | LetD (_,e) - | VarD (_, e) -> - effect_exp e - | TypD _ - | ClassD _ -> - T.Triv - -(* effect inference on Ir *) - -(* TODO: remove effect inference on Source once await.ml ported to work on IR - since effect inference is purely syntactic, we could roll this into desugaring -*) - -module Ir = - struct - open Ir - - let effect_exp (exp: exp) : T.eff = eff exp - - (* infer the effect of an expression, assuming all sub-expressions are correctly effect-annotated es*) - let rec infer_effect_exp (exp: exp) : T.eff = - match exp.it with - | PrimE _ - | VarE _ - | LitE _ -> - T.Triv - | UnE (_, _, exp1) - | ShowE (_, exp1) - | ProjE (exp1, _) - | OptE exp1 - | TagE (_, exp1) - | DotE (exp1, _) - | ActorDotE (exp1, _) - | AssertE exp1 - | LabelE (_, _, exp1) - | BreakE (_, exp1) - | RetE exp1 - | LoopE exp1 -> - effect_exp exp1 - | BinE (_, exp1, _, exp2) - | IdxE (exp1, exp2) - | RelE (_, exp1, _, exp2) - | AssignE (exp1, exp2) - | CallE (_, exp1, _, exp2) -> - let t1 = effect_exp exp1 in - let t2 = effect_exp exp2 in - max_eff t1 t2 - | TupE exps - | ArrayE (_, _, exps) -> - let es = List.map effect_exp exps in - List.fold_left max_eff Type.Triv es - | BlockE (ds, exp) -> - let es = List.map effect_dec ds in - List.fold_left max_eff (effect_exp exp) es - | IfE (exp1, exp2, exp3) -> - let e1 = effect_exp exp1 in - let e2 = effect_exp exp2 in - let e3 = effect_exp exp3 in - max_eff e1 (max_eff e2 e3) - | SwitchE (exp1, cases) -> - let e1 = effect_exp exp1 in - let e2 = effect_cases cases in - max_eff e1 e2 - | AsyncE exp1 -> - T.Triv - | AwaitE exp1 -> - T.Await - | DeclareE (_, _, exp1) -> - effect_exp exp1 - | DefineE (_, _, exp1) -> - effect_exp exp1 - | FuncE _ -> - T.Triv - | ActorE _ -> - T.Triv - | NewObjE _ -> - T.Triv - - and effect_cases cases = - match cases with - | [] -> - T.Triv - | {it = {pat; exp}; _}::cases' -> - let e = effect_exp exp in - max_eff e (effect_cases cases') - - and effect_dec dec = match dec.it with - | TypD _ -> T.Triv - | LetD (_,e) | VarD (_,e) -> effect_exp e - - and infer_effect_dec (dec:Ir.dec) = - match dec.it with - | LetD (_,e) - | VarD (_, e) -> - effect_exp e - | TypD _ -> - T.Triv -end diff --git a/src/aslib/operator.mli b/src/aslib/operator.mli deleted file mode 100644 index 63b11934153..00000000000 --- a/src/aslib/operator.mli +++ /dev/null @@ -1,10 +0,0 @@ -open Type -open Value - -val unop : typ -> Syntax.unop -> (value -> value) (* raise Invalid_argument *) -val binop : typ -> Syntax.binop -> (value -> value -> value) (* raise Invalid_argument *) -val relop : typ -> Syntax.relop -> (value -> value -> value) (* raise Invalid_argument *) - -val has_unop : typ -> Syntax.unop -> bool -val has_binop : typ -> Syntax.binop -> bool -val has_relop : typ -> Syntax.relop -> bool diff --git a/src/aslib/compile.ml b/src/codegen/compile.ml similarity index 99% rename from src/aslib/compile.ml rename to src/codegen/compile.ml index 707500b8680..32d01af612c 100644 --- a/src/aslib/compile.ml +++ b/src/codegen/compile.ml @@ -10,6 +10,9 @@ grouping. Every module has a high-level prose comment explaining the concept; this keeps documentation close to the code (a lesson learned from Simon PJ). *) +open As_ir +open As_values +open As_types open Wasm.Ast open Wasm.Types @@ -136,7 +139,7 @@ module E = struct (* Static *) mode : mode; prelude : Ir.prog; (* The prelude. Re-used when compiling actors *) - rts : CustomModule.extended_module option; (* The rts. Re-used when compiling actors *) + rts : Wasm_exts.CustomModule.extended_module option; (* The rts. Re-used when compiling actors *) trap_with : t -> string -> G.t; (* Trap with message; in the env for dependency injection *) @@ -147,7 +150,7 @@ module E = struct func_imports : import list ref; other_imports : import list ref; exports : export list ref; - dfinity_types : (int32 * CustomModule.type_ list) list ref; (* Dfinity types of exports *) + dfinity_types : (int32 * Wasm_exts.CustomModule.type_ list) list ref; (* Dfinity types of exports *) funcs : (func * string * local_names) Lib.Promise.t list ref; built_in_funcs : lazy_built_in NameEnv.t ref; static_strings : int32 StringEnv.t ref; @@ -996,7 +999,7 @@ module Tagged = struct (* Needs to be conservative, i.e. return `true` if unsure *) (* This function can also be used as assertions in a lint mode, e.g. in compile_exp *) let can_have_tag ty tag = - let open Type in + let open As_types.Type in match (tag : tag) with | Array -> begin match normalize ty with @@ -1081,7 +1084,7 @@ module Variant = struct let tag_field = Tagged.header_size let payload_field = Int32.add Tagged.header_size 1l - let hash_variant_label : Type.lab -> int32 = fun l -> + let hash_variant_label : As_types.Type.lab -> int32 = fun l -> Int32.of_int (Hashtbl.hash l) let inject env l e = @@ -1297,7 +1300,7 @@ module UnboxedSmallWord = struct let mask_of_type ty = Int32.lognot (padding_of_type ty) - let name_of_type ty seed = match Arrange.prim ty with + let name_of_type ty seed = match Arrange_type.prim ty with | Wasm.Sexpr.Atom s -> seed ^ "<" ^ s ^ ">" | wtf -> todo "name_of_type" wtf seed @@ -3343,8 +3346,8 @@ module Serialization = struct ) let dfinity_type t = - let open Type in - let open CustomModule in + let open As_types.Type in + let open Wasm_exts.CustomModule in match normalize t with | Prim Text -> DataBuf | Obj (Actor, _) -> ActorRef @@ -4014,7 +4017,7 @@ module FuncDec = struct let declare_dfinity_type env has_closure fi args = E.add_dfinity_type env (fi, - (if has_closure then [ CustomModule.I32 ] else []) @ + (if has_closure then [ Wasm_exts.CustomModule.I32 ] else []) @ List.map ( fun a -> Serialization.dfinity_type (Type.as_serialized a.note) ) args @@ -4358,7 +4361,7 @@ end (* AllocHow *) (* The actual compiler code that looks at the AST *) let compile_lit env lit = - try Syntax.(match lit with + try As_frontend.Syntax.(match lit with (* Booleans are directly in Vanilla representation *) | BoolLit false -> SR.bool, Bool.lit false | BoolLit true -> SR.bool, Bool.lit true @@ -4372,10 +4375,10 @@ let compile_lit env lit = | CharLit c -> SR.Vanilla, compile_unboxed_const Int32.(shift_left (of_int c) 8) | NullLit -> SR.Vanilla, Opt.null | TextLit t -> SR.Vanilla, Text.lit env t - | _ -> todo_trap_SR env "compile_lit" (Arrange.lit lit) + | _ -> todo_trap_SR env "compile_lit" (As_frontend.Arrange.lit lit) ) with Failure _ -> - Printf.eprintf "compile_lit: Overflow in literal %s\n" (Syntax.string_of_lit lit); + Printf.eprintf "compile_lit: Overflow in literal %s\n" (As_frontend.Syntax.string_of_lit lit); SR.Unreachable, E.trap_with env "static literal overflow" let compile_lit_as env sr_out lit = @@ -4383,7 +4386,7 @@ let compile_lit_as env sr_out lit = code ^^ StackRep.adjust env sr_in sr_out let compile_unop env t op = - let open Syntax in + let open Operator in match op, t with | NegOp, Type.(Prim Int) -> SR.Vanilla, @@ -4412,7 +4415,7 @@ let compile_unop env t op = | _ -> (* NB: Must not use todo_trap_SR here, as the SR.t here is also passed to `compile_exp_as`, which does not take SR.Unreachable. *) - todo "compile_unop" (Arrange.unop op) (SR.Vanilla, E.trap_with env "TODO: compile_unop") + todo "compile_unop" (As_frontend.Arrange.unop op) (SR.Vanilla, E.trap_with env "TODO: compile_unop") (* This returns a single StackRep, to be used for both arguments and the result. One could imagine operators that require or produce different StackReps, @@ -4420,7 +4423,7 @@ let compile_unop env t op = *) let rec compile_binop env t op = StackRep.of_type t, - Syntax.(match t, op with + Operator.(match t, op with | Type.(Prim (Nat | Int)), AddOp -> BigNum.compile_add env | Type.(Prim Word64), AddOp -> G.i (Binary (Wasm.Values.I64 I64Op.Add)) | Type.(Prim Nat), SubOp -> BigNum.compile_unsigned_sub env @@ -4511,7 +4514,7 @@ let rec compile_binop env t op = sanitize_word_result ty)) | Type.Prim Type.Text, CatOp -> Text.concat env - | _ -> todo_trap env "compile_binop" (Arrange.binop op) + | _ -> todo_trap env "compile_binop" (As_frontend.Arrange.binop op) ) let compile_eq env t = match t with @@ -4520,9 +4523,9 @@ let compile_eq env t = match t with | Type.(Prim (Nat | Int)) -> BigNum.compile_eq env | Type.(Prim Word64) -> G.i (Compare (Wasm.Values.I64 I64Op.Eq)) | Type.(Prim (Word8 | Word16 | Word32 | Char)) -> G.i (Compare (Wasm.Values.I32 I32Op.Eq)) - | _ -> todo_trap env "compile_eq" (Arrange.relop Syntax.EqOp) + | _ -> todo_trap env "compile_eq" (As_frontend.Arrange.relop Operator.EqOp) -let get_relops = Syntax.(function +let get_relops = Operator.(function | GeOp -> Ge, I64Op.GeU, I32Op.GeU, I32Op.GeS | GtOp -> Gt, I64Op.GtU, I32Op.GtU, I32Op.GtS | LeOp -> Le, I64Op.LeU, I32Op.LeU, I32Op.LeS @@ -4536,18 +4539,18 @@ let compile_comparison env t op = | Nat | Int -> BigNum.compile_relop env bigintop | Word64 -> G.i (Compare (Wasm.Values.I64 u64op)) | Word8 | Word16 | Word32 | Char -> G.i (Compare (Wasm.Values.I32 u32op)) - | _ -> todo_trap env "compile_comparison" (Arrange.prim t) + | _ -> todo_trap env "compile_comparison" (Arrange_type.prim t) let compile_relop env t op = StackRep.of_type t, - let open Syntax in + let open Operator in match t, op with | _, EqOp -> compile_eq env t | _, NeqOp -> compile_eq env t ^^ G.if_ (StackRep.to_block_type env SR.bool) (Bool.lit false) (Bool.lit true) | Type.Prim Type.(Nat | Int | Word8 | Word16 | Word32 | Word64 | Char as t1), op1 -> compile_comparison env t1 op1 - | _ -> todo_trap env "compile_relop" (Arrange.relop op) + | _ -> todo_trap env "compile_relop" (As_frontend.Arrange.relop op) (* compile_load_field implements the various “virtual fields”, which we currently have for arrays and text. @@ -4787,7 +4790,7 @@ and compile_exp (env : E.t) ae exp = SR.unit, compile_exp_as env ae SR.bool e1 ^^ G.if_ (ValBlockType None) G.nop (G.i Unreachable) - | UnE (_, Syntax.PosOp, e1) -> compile_exp env ae e1 + | UnE (_, Operator.PosOp, e1) -> compile_exp env ae e1 | UnE (t, op, e1) -> let sr, code = compile_unop env t op in sr, @@ -4999,22 +5002,23 @@ enabled mutual recursion. and compile_lit_pat env l = + let open As_frontend.Syntax in match l with - | Syntax.NullLit -> + | NullLit -> compile_lit_as env SR.Vanilla l ^^ G.i (Compare (Wasm.Values.I32 I32Op.Eq)) - | Syntax.BoolLit true -> + | BoolLit true -> G.nop - | Syntax.BoolLit false -> + | BoolLit false -> Bool.lit false ^^ G.i (Compare (Wasm.Values.I32 I32Op.Eq)) - | Syntax.(NatLit _ | IntLit _) -> + | (NatLit _ | IntLit _) -> compile_lit_as env SR.Vanilla l ^^ BigNum.compile_eq env - | Syntax.(TextLit t) -> + | (TextLit t) -> Text.lit env t ^^ Text.compare env - | _ -> todo_trap env "compile_lit_pat" (Arrange.lit l) + | _ -> todo_trap env "compile_lit_pat" (As_frontend.Arrange.lit l) and fill_pat env ae pat : patternCode = PatCode.with_region pat.at @@ @@ -5327,7 +5331,7 @@ and actor_lit outer_env this ds fs at = OrthogonalPersistence.register mod_env start_fi; let m = conclude_module mod_env this.it None in - let (_map, wasm_binary) = CustomModuleEncode.encode m in + let (_map, wasm_binary) = Wasm_exts.CustomModuleEncode.encode m in wasm_binary in Dfinity.compile_databuf_of_bytes outer_env wasm_binary ^^ @@ -5441,7 +5445,7 @@ and conclude_module env module_name start_fi_o = } in let emodule = - let open CustomModule in + let open Wasm_exts.CustomModule in { module_; dylink = None; name = { @@ -5453,16 +5457,16 @@ and conclude_module env module_name start_fi_o = }; types = E.get_dfinity_types env; persist = - [ (OrthogonalPersistence.mem_global, CustomModule.DataBuf) - ; (OrthogonalPersistence.elem_global, CustomModule.ElemBuf) + [ (OrthogonalPersistence.mem_global, Wasm_exts.CustomModule.DataBuf) + ; (OrthogonalPersistence.elem_global, Wasm_exts.CustomModule.ElemBuf) ]; } in match E.get_rts env with | None -> emodule - | Some rts -> LinkModule.link emodule "rts" rts + | Some rts -> Linking.LinkModule.link emodule "rts" rts -let compile mode module_name rts (prelude : Ir.prog) (progs : Ir.prog list) : CustomModule.extended_module = +let compile mode module_name rts (prelude : Ir.prog) (progs : Ir.prog list) : Wasm_exts.CustomModule.extended_module = let env = E.mk_global mode rts prelude Dfinity.trap_with ClosureTable.table_end in if E.mode env = DfinityMode then Dfinity.system_imports env; diff --git a/src/codegen/compile.mli b/src/codegen/compile.mli new file mode 100644 index 00000000000..685e374a2dd --- /dev/null +++ b/src/codegen/compile.mli @@ -0,0 +1,5 @@ +type mode = WasmMode | DfinityMode + +open As_ir + +val compile : mode -> string -> Wasm_exts.CustomModule.extended_module option -> Ir.prog -> Ir.prog list -> Wasm_exts.CustomModule.extended_module diff --git a/src/codegen/dune b/src/codegen/dune new file mode 100644 index 00000000000..a9c1f70654b --- /dev/null +++ b/src/codegen/dune @@ -0,0 +1,4 @@ +(library + (name codegen) + (libraries wasm lib lang_utils wasm_exts as_ir linking) +) diff --git a/src/aslib/instrList.ml b/src/codegen/instrList.ml similarity index 100% rename from src/aslib/instrList.ml rename to src/codegen/instrList.ml diff --git a/src/exes/as_js.ml b/src/exes/as_js.ml index c159585aab4..91f76233338 100644 --- a/src/exes/as_js.ml +++ b/src/exes/as_js.ml @@ -1,4 +1,4 @@ -open Aslib +open Wasm_exts open Source module Js = Js_of_ocaml.Js diff --git a/src/exes/as_ld.ml b/src/exes/as_ld.ml index fa46843640b..16d7a317e6b 100644 --- a/src/exes/as_ld.ml +++ b/src/exes/as_ld.ml @@ -1,4 +1,5 @@ -open Aslib +open Linking +open Wasm_exts open Printf let name = "as-ld" diff --git a/src/exes/asc.ml b/src/exes/asc.ml index 39662d328be..39a080e27a9 100644 --- a/src/exes/asc.ml +++ b/src/exes/asc.ml @@ -1,4 +1,4 @@ -open Aslib +open Wasm_exts open Printf diff --git a/src/exes/dune b/src/exes/dune index 402750dce17..e77d7f902d0 100644 --- a/src/exes/dune +++ b/src/exes/dune @@ -1,12 +1,12 @@ (executable (name asc) (modules asc) - (libraries aslib) + (libraries pipeline) ) (executable (name as_ld) (modules as_ld) - (libraries aslib) + (libraries wasm_exts linking) ) (executable (name didc) @@ -16,7 +16,7 @@ (executable (name as_js) (modules as_js) - (libraries aslib) + (libraries pipeline) (preprocess (pps js_of_ocaml-ppx)) (js_of_ocaml (flags :standard "+nat.js") ) ) diff --git a/src/flags/dune b/src/flags/dune new file mode 100644 index 00000000000..1c367919f3d --- /dev/null +++ b/src/flags/dune @@ -0,0 +1,4 @@ +(library + (name flags) + (wrapped false) +) diff --git a/src/aslib/flags.ml b/src/flags/flags.ml similarity index 100% rename from src/aslib/flags.ml rename to src/flags/flags.ml diff --git a/src/interpreter/dune b/src/interpreter/dune new file mode 100644 index 00000000000..b6f36f606a6 --- /dev/null +++ b/src/interpreter/dune @@ -0,0 +1,4 @@ +(library + (name interpreter) + (libraries lib as_types as_values as_frontend) +) diff --git a/src/aslib/interpret.ml b/src/interpreter/interpret.ml similarity index 99% rename from src/aslib/interpret.ml rename to src/interpreter/interpret.ml index f6554b1e80d..ad8342bf1d7 100644 --- a/src/aslib/interpret.ml +++ b/src/interpreter/interpret.ml @@ -1,8 +1,10 @@ +open As_values +open As_frontend open Syntax open Source -module V = Value -module T = Type +module V = As_values.Value +module T = As_types.Type (* Context *) @@ -259,7 +261,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = last_env := env; match exp.it with | PrimE s -> - k (V.Func (V.call_conv_of_typ exp.note.note_typ, Prelude.prim s)) + k (V.Func (V.call_conv_of_typ exp.note.note_typ, Prim.prim s)) | VarE id -> begin match Lib.Promise.value_opt (find id.it env.vals) with | Some v -> k v diff --git a/src/aslib/interpret.mli b/src/interpreter/interpret.mli similarity index 84% rename from src/aslib/interpret.mli rename to src/interpreter/interpret.mli index ab969ccac00..152a10f3737 100644 --- a/src/aslib/interpret.mli +++ b/src/interpreter/interpret.mli @@ -1,5 +1,6 @@ -module V = Value -module T = Type +open As_frontend +module V = As_values.Value +module T = As_types.Type type flags = { trace : bool; diff --git a/src/ir_interpreter/dune b/src/ir_interpreter/dune new file mode 100644 index 00000000000..53f391afe41 --- /dev/null +++ b/src/ir_interpreter/dune @@ -0,0 +1,4 @@ +(library + (name ir_interpreter) + (libraries lib as_types as_values as_ir) +) diff --git a/src/aslib/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml similarity index 99% rename from src/aslib/interpret_ir.ml rename to src/ir_interpreter/interpret_ir.ml index 6731a168950..42f87f79f2d 100644 --- a/src/aslib/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -1,5 +1,10 @@ +open As_types +open As_values +open As_ir + open Ir open Source +open As_frontend module V = Value module T = Type @@ -218,7 +223,7 @@ let extended_prim env s typ at = await env at (V.as_async async) (fun v -> f v k) | _ -> assert false ) - | _ -> Prelude.prim s + | _ -> Prim.prim s (* Literals *) diff --git a/src/aslib/interpret_ir.mli b/src/ir_interpreter/interpret_ir.mli similarity index 87% rename from src/aslib/interpret_ir.mli rename to src/ir_interpreter/interpret_ir.mli index 67f3bd79fb2..94bf126ac19 100644 --- a/src/aslib/interpret_ir.mli +++ b/src/ir_interpreter/interpret_ir.mli @@ -1,3 +1,7 @@ +open As_types +open As_values +open As_ir + module V = Value module T = Type diff --git a/src/aslib/async.ml b/src/ir_passes/async.ml similarity index 99% rename from src/aslib/async.ml rename to src/ir_passes/async.ml index 6a3a2d17751..9fb895680f2 100644 --- a/src/aslib/async.ml +++ b/src/ir_passes/async.ml @@ -1,8 +1,12 @@ +open As_types +open As_ir +open As_values +open As_frontend module E = Env open Source module Ir = Ir open Ir -open Effect +open Ir_effect module T = Type open T open Construct diff --git a/src/aslib/async.mli b/src/ir_passes/async.mli similarity index 77% rename from src/aslib/async.mli rename to src/ir_passes/async.mli index 07b57dae373..6d411227d28 100644 --- a/src/aslib/async.mli +++ b/src/ir_passes/async.mli @@ -1,3 +1,5 @@ (* lower uses of async type appropriately *) +open As_frontend +open As_ir val transform : Typing.scope -> Ir.prog -> Ir.prog diff --git a/src/aslib/await.ml b/src/ir_passes/await.ml similarity index 99% rename from src/aslib/await.ml rename to src/ir_passes/await.ml index a97e382875b..ecdbe84fbef 100644 --- a/src/aslib/await.ml +++ b/src/ir_passes/await.ml @@ -1,8 +1,9 @@ +open As_ir open Source open Ir -open Effect +open Ir_effect module R = Rename -module T = Type +module T = As_types.Type open Construct (* continuations, syntactic and meta-level *) diff --git a/src/aslib/await.mli b/src/ir_passes/await.mli similarity index 90% rename from src/aslib/await.mli rename to src/ir_passes/await.mli index 8283ee38724..af98a42c581 100644 --- a/src/aslib/await.mli +++ b/src/ir_passes/await.mli @@ -1,3 +1,3 @@ (* lower uses of async and await to continuation passing style *) - +open As_ir val transform : Ir.prog -> Ir.prog diff --git a/src/ir_passes/dune b/src/ir_passes/dune new file mode 100644 index 00000000000..0a249ed5227 --- /dev/null +++ b/src/ir_passes/dune @@ -0,0 +1,4 @@ +(library + (name ir_passes) + (libraries lib as_ir) +) diff --git a/src/aslib/rename.ml b/src/ir_passes/rename.ml similarity index 99% rename from src/aslib/rename.ml rename to src/ir_passes/rename.ml index 540416f2701..6fa8e84c910 100644 --- a/src/aslib/rename.ml +++ b/src/ir_passes/rename.ml @@ -1,5 +1,6 @@ +open As_ir open Source -module S = Syntax +module S = As_frontend.Syntax open Ir module Renaming = Map.Make(String) diff --git a/src/aslib/serialization.ml b/src/ir_passes/serialization.ml similarity index 99% rename from src/aslib/serialization.ml rename to src/ir_passes/serialization.ml index ba391a7710f..89d2c1819b6 100644 --- a/src/aslib/serialization.ml +++ b/src/ir_passes/serialization.ml @@ -1,3 +1,7 @@ +open As_frontend +open As_ir +open As_types +open As_values open Source open Ir module T = Type diff --git a/src/aslib/serialization.mli b/src/ir_passes/serialization.mli similarity index 64% rename from src/aslib/serialization.mli rename to src/ir_passes/serialization.mli index 60e9a77c4ec..61dab1d0464 100644 --- a/src/aslib/serialization.mli +++ b/src/ir_passes/serialization.mli @@ -1 +1,3 @@ +open As_frontend +open As_ir val transform : Typing.scope -> Ir.prog -> Ir.prog diff --git a/src/aslib/show.ml b/src/ir_passes/show.ml similarity index 99% rename from src/aslib/show.ml rename to src/ir_passes/show.ml index 466842d2d28..b7ddd2ee3fc 100644 --- a/src/aslib/show.ml +++ b/src/ir_passes/show.ml @@ -1,3 +1,6 @@ +open As_ir +open As_types +open As_values (* Translates away calls to `show`. *) open Source open Ir @@ -250,7 +253,7 @@ let list_build : 'a -> 'a -> 'a -> 'a list -> 'a list = fun pre sep post xs -> in [ pre ] @ go xs let catE : Ir.exp -> Ir.exp -> Ir.exp = fun e1 e2 -> - { it = BinE (T.Prim T.Text, e1, Syntax.CatOp, e2) + { it = BinE (T.Prim T.Text, e1, Operator.CatOp, e2) ; at = no_region ; note = { note_typ = T.Prim T.Text; note_eff = T.Triv } } diff --git a/src/aslib/show.mli b/src/ir_passes/show.mli similarity index 75% rename from src/aslib/show.mli rename to src/ir_passes/show.mli index 6f740910ece..ab759d510dc 100644 --- a/src/aslib/show.mli +++ b/src/ir_passes/show.mli @@ -1,3 +1,7 @@ +open As_ir +open As_types +open As_values + val can_show : Type.typ -> bool val show_val : Type.typ -> Value.value -> string diff --git a/src/aslib/tailcall.ml b/src/ir_passes/tailcall.ml similarity index 99% rename from src/aslib/tailcall.ml rename to src/ir_passes/tailcall.ml index a1f0a9e903f..2d524f4c572 100644 --- a/src/aslib/tailcall.ml +++ b/src/ir_passes/tailcall.ml @@ -1,9 +1,13 @@ +open As_ir +open As_types +open As_values + open Source open Ir -open Effect +open Ir_effect open Type open Construct -module S = Syntax +module S = As_frontend.Syntax (* Optimize (self) tail calls to jumps, avoiding stack overflow in a single linear pass *) diff --git a/src/aslib/tailcall.mli b/src/ir_passes/tailcall.mli similarity index 91% rename from src/aslib/tailcall.mli rename to src/ir_passes/tailcall.mli index c506c33629d..452c14782d6 100644 --- a/src/aslib/tailcall.mli +++ b/src/ir_passes/tailcall.mli @@ -1,4 +1,6 @@ (* Optimize (self) tail calls to jumps, avoiding stack overflow, in a single linear pass *) +open As_ir + val transform: Ir.prog -> Ir.prog diff --git a/src/aslib/diag.ml b/src/lang_utils/diag.ml similarity index 100% rename from src/aslib/diag.ml rename to src/lang_utils/diag.ml diff --git a/src/aslib/diag.mli b/src/lang_utils/diag.mli similarity index 100% rename from src/aslib/diag.mli rename to src/lang_utils/diag.mli diff --git a/src/aslib/dom.ml b/src/lang_utils/dom.ml similarity index 100% rename from src/aslib/dom.ml rename to src/lang_utils/dom.ml diff --git a/src/lang_utils/dune b/src/lang_utils/dune new file mode 100644 index 00000000000..00d153bb761 --- /dev/null +++ b/src/lang_utils/dune @@ -0,0 +1,5 @@ +(library + (name lang_utils) + (libraries lib) + (wrapped false) +) diff --git a/src/aslib/env.ml b/src/lang_utils/env.ml similarity index 100% rename from src/aslib/env.ml rename to src/lang_utils/env.ml diff --git a/src/aslib/nameRel.ml b/src/lang_utils/nameRel.ml similarity index 100% rename from src/aslib/nameRel.ml rename to src/lang_utils/nameRel.ml diff --git a/src/aslib/source.ml b/src/lang_utils/source.ml similarity index 100% rename from src/aslib/source.ml rename to src/lang_utils/source.ml diff --git a/src/aslib/source.mli b/src/lang_utils/source.mli similarity index 100% rename from src/aslib/source.mli rename to src/lang_utils/source.mli diff --git a/src/lib/dune b/src/lib/dune index cd4322f9112..87151ffe9b6 100644 --- a/src/lib/dune +++ b/src/lib/dune @@ -1,4 +1,5 @@ (library (name lib) + (libraries bigarray) (preprocess (pps bisect_ppx -conditional)) ) diff --git a/src/linking/dune b/src/linking/dune new file mode 100644 index 00000000000..3f652418e3a --- /dev/null +++ b/src/linking/dune @@ -0,0 +1,4 @@ +(library + (name linking) + (libraries lib wasm_exts) +) diff --git a/src/aslib/linkModule.ml b/src/linking/linkModule.ml similarity index 99% rename from src/aslib/linkModule.ml rename to src/linking/linkModule.ml index 4903572519c..74e1a5babe4 100644 --- a/src/aslib/linkModule.ml +++ b/src/linking/linkModule.ml @@ -5,7 +5,7 @@ plus the dylink section. open Wasm.Ast open Wasm.Source -open CustomModule +open Wasm_exts.CustomModule (* This module is a first stab that should be functionally working, but will go diff --git a/src/aslib/linkModule.mli b/src/linking/linkModule.mli similarity index 51% rename from src/aslib/linkModule.mli rename to src/linking/linkModule.mli index 1fd2ff40a28..407aa2d59c5 100644 --- a/src/aslib/linkModule.mli +++ b/src/linking/linkModule.mli @@ -5,4 +5,4 @@ *) exception LinkError of string -val link : CustomModule.extended_module -> string -> CustomModule.extended_module -> CustomModule.extended_module +val link : Wasm_exts.CustomModule.extended_module -> string -> Wasm_exts.CustomModule.extended_module -> Wasm_exts.CustomModule.extended_module diff --git a/src/aslib/desugar.ml b/src/lowering/desugar.ml similarity index 93% rename from src/aslib/desugar.ml rename to src/lowering/desugar.ml index 02265f0fc6e..774014f0a06 100644 --- a/src/aslib/desugar.ml +++ b/src/lowering/desugar.ml @@ -1,7 +1,12 @@ +open As_ir +open As_frontend +open As_values + open Source +open Operator module S = Syntax module I = Ir -module T = Type +module T = As_types.Type open Construct (* @@ -59,22 +64,22 @@ and exp' at note = function | S.DotE (e, x) -> let n = x.it in begin match T.as_obj_sub x.it e.note.S.note_typ with - | Type.Actor, _ -> I.ActorDotE (exp e, n) + | T.Actor, _ -> I.ActorDotE (exp e, n) | _ -> I.DotE (exp e, n) end | S.AssignE (e1, e2) -> I.AssignE (exp e1, exp e2) | S.ArrayE (m, es) -> - let t = Type.as_array note.S.note_typ in - I.ArrayE (m, Type.as_immut t, exps es) + let t = T.as_array note.S.note_typ in + I.ArrayE (m, T.as_immut t, exps es) | S.IdxE (e1, e2) -> I.IdxE (exp e1, exp e2) | S.FuncE (name, s, tbs, p, ty, e) -> let cc = Value.call_conv_of_typ note.S.note_typ in let args, wrap = to_args cc p in - let tys = if cc.Value.n_res = 1 then [ty.note] else Type.as_seq ty.note in + let tys = if cc.Value.n_res = 1 then [ty.note] else T.as_seq ty.note in I.FuncE (name, cc, typ_binds tbs, args, tys, wrap (exp e)) | S.CallE (e1, inst, e2) -> let t = e1.Source.note.S.note_typ in - if Type.is_non t + if T.is_non t then unreachableE.it else let cc = Value.call_conv_of_typ t in @@ -82,7 +87,7 @@ and exp' at note = function I.CallE (cc, exp e1, inst, exp e2) | S.BlockE [] -> I.TupE [] | S.BlockE [{it = S.ExpD e; _}] -> (exp e).it - | S.BlockE ds -> I.BlockE (block (Type.is_unit note.S.note_typ) ds) + | S.BlockE ds -> I.BlockE (block (T.is_unit note.S.note_typ) ds) | S.NotE e -> I.IfE (exp e, falseE, trueE) | S.AndE (e1, e2) -> I.IfE (exp e1, exp e2, falseE) | S.OrE (e1, e2) -> I.IfE (exp e1, trueE, exp e2) @@ -105,10 +110,10 @@ and exp' at note = function and obj at s self_id es obj_typ = match s.it with - | Type.Object _ | T.Module -> build_obj at s self_id es obj_typ - | Type.Actor -> build_actor at self_id es obj_typ + | T.Object _ | T.Module -> build_obj at s self_id es obj_typ + | T.Actor -> build_actor at self_id es obj_typ -and build_field {Type.lab; Type.typ} = +and build_field {T.lab; T.typ} = { it = { I.name = lab ; I.var = lab @@ no_region } @@ -118,9 +123,9 @@ and build_field {Type.lab; Type.typ} = and build_fields obj_typ = match obj_typ with - | Type.Obj (_, fields) -> + | T.Obj (_, fields) -> (* TBR: do we need to sort val_fields?*) - let val_fields = List.filter (fun {Type.lab;Type.typ} -> not (Type.is_typ typ)) fields in + let val_fields = List.filter (fun {T.lab;T.typ} -> not (T.is_typ typ)) fields in List.map build_field val_fields | _ -> assert false @@ -320,7 +325,7 @@ and prog (p : Syntax.prog) : Ir.prog = let declare_import imp_env (f, (prog:Syntax.prog)) = let open Source in - let t = Type.Env.find f imp_env in + let t = T.Env.find f imp_env in let typ_note = { Syntax.empty_typ_note with Syntax.note_typ = t } in match prog.it with | [{it = Syntax.ExpD e;_}] -> @@ -354,7 +359,7 @@ let declare_import imp_env (f, (prog:Syntax.prog)) = ; note = t } , { it = Syntax.ObjE - (Type.Module @@ no_region, + (T.Module @@ no_region, List.map (fun d -> { Syntax.dec=d; vis=Syntax.Public @@ no_region } diff --git a/src/aslib/desugar.mli b/src/lowering/desugar.mli similarity index 81% rename from src/aslib/desugar.mli rename to src/lowering/desugar.mli index ad0f020a6aa..b81ebdc6b39 100644 --- a/src/aslib/desugar.mli +++ b/src/lowering/desugar.mli @@ -1,2 +1,5 @@ +open As_frontend +open As_ir + val transform : Syntax.prog -> Ir.prog val transform_graph : Typing.lib_env -> Syntax.libraries -> Syntax.prog list -> Ir.prog diff --git a/src/lowering/dune b/src/lowering/dune new file mode 100644 index 00000000000..f15ddb41097 --- /dev/null +++ b/src/lowering/dune @@ -0,0 +1,4 @@ +(library + (name lowering) + (libraries lib as_frontend as_ir) +) diff --git a/src/pipeline/dune b/src/pipeline/dune new file mode 100644 index 00000000000..f2fe1882335 --- /dev/null +++ b/src/pipeline/dune @@ -0,0 +1,18 @@ +(library + (name pipeline) + (libraries + lib + lang_utils + as_types + as_values + as_frontend + as_ir + wasm_exts + interpreter + ir_interpreter + lowering + ir_passes + codegen + flags + ) +) diff --git a/src/aslib/pipeline.ml b/src/pipeline/pipeline.ml similarity index 93% rename from src/aslib/pipeline.ml rename to src/pipeline/pipeline.ml index f2665b4244d..f49b68ad64c 100644 --- a/src/aslib/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -1,3 +1,8 @@ +open As_frontend +open As_types +open As_values +open As_ir +open Interpreter open Printf type stat_env = Typing.scope @@ -408,26 +413,26 @@ let transform_if transform_name trans flag env prog name = let desugar env lib_env libraries progs name = phase "Desugaring" name; - let prog_ir' : Ir.prog = Desugar.transform_graph lib_env libraries progs in + let prog_ir' : Ir.prog = Lowering.Desugar.transform_graph lib_env libraries progs in dump_ir Flags.dump_lowering prog_ir'; if !Flags.check_ir then Check_ir.check_prog !Flags.verbose env "Desugaring" prog_ir'; prog_ir' let await_lowering = - transform_if "Await Lowering" (fun _ -> Await.transform) + transform_if "Await Lowering" (fun _ -> Ir_passes.Await.transform) let async_lowering = - transform_if "Async Lowering" Async.transform + transform_if "Async Lowering" Ir_passes.Async.transform let serialization = - transform_if "Synthesizing serialization code" Serialization.transform + transform_if "Synthesizing serialization code" Ir_passes.Serialization.transform let tailcall_optimization = - transform_if "Tailcall optimization" (fun _ -> Tailcall.transform) + transform_if "Tailcall optimization" (fun _ -> Ir_passes.Tailcall.transform) let show_translation = - transform_if "Translate show" Show.transform + transform_if "Translate show" Ir_passes.Show.transform (* Compilation *) @@ -451,10 +456,10 @@ let load_as_rts () = | Some filename -> filename | None -> Filename.(concat (dirname Sys.argv.(0)) "../rts/as-rts.wasm") in let wasm = load_file wasm_filename in - CustomModuleDecode.decode "rts.wasm" wasm + Wasm_exts.CustomModuleDecode.decode "rts.wasm" wasm -type compile_mode = Compile.mode = WasmMode | DfinityMode -type compile_result = CustomModule.extended_module Diag.result +type compile_mode = Codegen.Compile.mode = WasmMode | DfinityMode +type compile_result = Wasm_exts.CustomModule.extended_module Diag.result let name_progs progs = if progs = [] @@ -470,13 +475,13 @@ let lower_prog senv lib_env libraries progs name = let prog_ir = show_translation true initial_stat_env prog_ir name in prog_ir -let compile_prog mode do_link lib_env libraries progs : CustomModule.extended_module = - let prelude_ir = Desugar.transform prelude in +let compile_prog mode do_link lib_env libraries progs : Wasm_exts.CustomModule.extended_module = + let prelude_ir = Lowering.Desugar.transform prelude in let name = name_progs progs in let prog_ir = lower_prog initial_stat_env lib_env libraries progs name in phase "Compiling" name; let rts = if do_link then Some (load_as_rts ()) else None in - Compile.compile mode name rts prelude_ir [prog_ir] + Codegen.Compile.compile mode name rts prelude_ir [prog_ir] let compile_files mode do_link files : compile_result = Diag.bind (load_progs (parse_files files) initial_stat_env) @@ -491,11 +496,11 @@ let compile_string mode s name : compile_result = (* Interpretation (IR) *) let interpret_ir_prog inp_env libraries progs = - let prelude_ir = Desugar.transform prelude in + let prelude_ir = Lowering.Desugar.transform prelude in let name = name_progs progs in let prog_ir = lower_prog initial_stat_env inp_env libraries progs name in phase "Interpreting" name; - let open Interpret_ir in + let open Ir_interpreter.Interpret_ir in let flags = { trace = !Flags.trace; print_depth = !Flags.print_depth } in let denv0 = empty_scope in let dscope = interpret_prog flags denv0 prelude_ir in diff --git a/src/aslib/pipeline.mli b/src/pipeline/pipeline.mli similarity index 86% rename from src/aslib/pipeline.mli rename to src/pipeline/pipeline.mli index 7cc541f065b..0873226661a 100644 --- a/src/aslib/pipeline.mli +++ b/src/pipeline/pipeline.mli @@ -6,6 +6,6 @@ val interpret_ir_files : string list -> unit option val run_files_and_stdin : string list -> unit option type compile_mode = WasmMode | DfinityMode -type compile_result = CustomModule.extended_module Diag.result +type compile_result = Wasm_exts.CustomModule.extended_module Diag.result val compile_string : compile_mode -> string -> string -> compile_result val compile_files : compile_mode -> bool -> string list -> compile_result diff --git a/src/aslib/resolve_import.ml b/src/pipeline/resolve_import.ml similarity index 99% rename from src/aslib/resolve_import.ml rename to src/pipeline/resolve_import.ml index f969715c525..7c28668fb4f 100644 --- a/src/aslib/resolve_import.ml +++ b/src/pipeline/resolve_import.ml @@ -1,3 +1,5 @@ +open As_frontend + (* This module traverses the syntax tree. For each `import` statement, it looks at the given relative path and tries to resolve it to a full path (where diff --git a/src/aslib/resolve_import.mli b/src/pipeline/resolve_import.mli similarity index 84% rename from src/aslib/resolve_import.mli rename to src/pipeline/resolve_import.mli index cc72fefc85e..55f685fe253 100644 --- a/src/aslib/resolve_import.mli +++ b/src/pipeline/resolve_import.mli @@ -1,3 +1,5 @@ +open As_frontend + module S : Set.S with type elt = String.t val resolve : Syntax.prog -> string -> S.t Diag.result diff --git a/src/prelude/dune b/src/prelude/dune new file mode 100644 index 00000000000..17f4f664b0e --- /dev/null +++ b/src/prelude/dune @@ -0,0 +1,4 @@ +(library + (name prelude) + (wrapped false) +) diff --git a/src/prelude/prelude.ml b/src/prelude/prelude.ml new file mode 100644 index 00000000000..17f4fb91013 --- /dev/null +++ b/src/prelude/prelude.ml @@ -0,0 +1,235 @@ +let prelude = +{| +type Any = prim "Any"; +type None = prim "None"; +type Shared = prim "Shared"; +type Null = prim "Null"; +type Bool = prim "Bool"; +type Nat = prim "Nat"; +type Int = prim "Int"; +type Word8 = prim "Word8"; +type Word16 = prim "Word16"; +type Word32 = prim "Word32"; +type Word64 = prim "Word64"; +type Float = prim "Float"; +type Char = prim "Char"; +type Text = prim "Text"; + +type Iter = {next : () -> ?T_}; + +func abs(x : Int) : Nat { (prim "abs" : Int -> Nat) x }; + +func ignore(_ : Any) {}; + +class range(x : Nat, y : Nat) { + private var i = x; + next() : ?Nat { if (i > y) null else {let j = i; i += 1; ?j} }; +}; + +class revrange(x : Nat, y : Nat) { + private var i = x + 1; + next() : ?Nat { if (i <= y) null else {i -= 1; ?i} }; +}; + +// for testing +func idlHash(x : Text) : Word32 { (prim "idlHash" : Text -> Word32) x }; + +func charToText(c : Char) : Text = (prim "Char->Text" : Char -> Text) c; + +func printInt(x : Int) { print (@text_of_Int x) }; +func printChar(x : Char) { print (charToText x) }; +func print(x : Text) { (prim "print" : Text -> ()) x }; +func rts_version() : Text { (prim "rts_version" : () -> Text) () }; + +// Hashing +func hashInt(x : Int) : Word32 { + var n = x; + var hash : Word32 = 0; + if (n < 0) { + hash := ^hash; + n := abs n; + }; + let base = 2**32; + while (n > 0) { + hash ^= intToWord32(n % base); + n /= base; + }; + return hash; +}; + +// Conversions +func natToWord8(n : Nat) : Word8 = (prim "Nat->Word8" : Nat -> Word8) n; +func word8ToNat(n : Word8) : Nat = (prim "Word8->Nat" : Word8 -> Nat) n; +func intToWord8(n : Int) : Word8 = (prim "Int->Word8" : Int -> Word8) n; +func word8ToInt(n : Word8) : Int = (prim "Word8->Int" : Word8 -> Int) n; + +func natToWord16(n : Nat) : Word16 = (prim "Nat->Word16" : Nat -> Word16) n; +func word16ToNat(n : Word16) : Nat = (prim "Word16->Nat" : Word16 -> Nat) n; +func intToWord16(n : Int) : Word16 = (prim "Int->Word16" : Int -> Word16) n; +func word16ToInt(n : Word16) : Int = (prim "Word16->Int" : Word16 -> Int) n; + +func natToWord32(n : Nat) : Word32 = (prim "Nat->Word32" : Nat -> Word32) n; +func word32ToNat(n : Word32) : Nat = (prim "Word32->Nat" : Word32 -> Nat) n; +func intToWord32(n : Int) : Word32 = (prim "Int->Word32" : Int -> Word32) n; +func word32ToInt(n : Word32) : Int = (prim "Word32->Int" : Word32 -> Int) n; + +func natToWord64(n : Nat) : Word64 = (prim "Nat->Word64" : Nat -> Word64) n; +func word64ToNat(n : Word64) : Nat = (prim "Word64->Nat" : Word64 -> Nat) n; +func intToWord64(n : Int) : Word64 = (prim "Int->Word64" : Int -> Word64) n; +func word64ToInt(n : Word64) : Int = (prim "Word64->Int" : Word64 -> Int) n; + +func charToWord32(c : Char) : Word32 = (prim "Char->Word32" : Char -> Word32) c; +func word32ToChar(w : Word32) : Char = (prim "Word32->Char" : Word32 -> Char) w; +func decodeUTF8(s : Text) : (Word32, Char) = (prim "decodeUTF8" : Text -> (Word32, Char)) s; + +// Exotic bitwise operations +func popcntWord8(w : Word8) : Word8 = (prim "popcnt8" : Word8 -> Word8) w; +func clzWord8(w : Word8) : Word8 = (prim "clz8" : Word8 -> Word8) w; +func ctzWord8(w : Word8) : Word8 = (prim "ctz8" : Word8 -> Word8) w; +func btstWord8(w : Word8, amount : Word8) : Bool = (prim "btst8" : (Word8, Word8) -> Word8) (w, amount) != (0 : Word8); + +func popcntWord16(w : Word16) : Word16 = (prim "popcnt16" : Word16 -> Word16) w; +func clzWord16(w : Word16) : Word16 = (prim "clz16" : Word16 -> Word16) w; +func ctzWord16(w : Word16) : Word16 = (prim "ctz16" : Word16 -> Word16) w; +func btstWord16(w : Word16, amount : Word16) : Bool = (prim "btst16" : (Word16, Word16) -> Word16) (w, amount) != (0 : Word16); + +func popcntWord32(w : Word32) : Word32 = (prim "popcnt" : Word32 -> Word32) w; +func clzWord32(w : Word32) : Word32 = (prim "clz" : Word32 -> Word32) w; +func ctzWord32(w : Word32) : Word32 = (prim "ctz" : Word32 -> Word32) w; +func btstWord32(w : Word32, amount : Word32) : Bool = (prim "btst" : (Word32, Word32) -> Word32) (w, amount) != (0 : Word32); + +func popcntWord64(w : Word64) : Word64 = (prim "popcnt64" : Word64 -> Word64) w; +func clzWord64(w : Word64) : Word64 = (prim "clz64" : Word64 -> Word64) w; +func ctzWord64(w : Word64) : Word64 = (prim "ctz64" : Word64 -> Word64) w; +func btstWord64(w : Word64, amount : Word64) : Bool = (prim "btst64" : (Word64, Word64) -> Word64) (w, amount) != (0 : Word64); + +// Internal helper functions for the show translation + +// The @ in the name ensures that this cannot be shadowed by user code, so +// compiler passes can rely on them being in scope +// The text_of functions do not need to be exposed; the user can just use +// the show above. + +func @text_of_Nat(x : Nat) : Text { + var text = ""; + var n = x; + let base = 10; + let digits = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]; + + assert(n >= 0); + + if (n == 0) { + return "0"; + }; + + while (n > 0) { + let rem = n % base; + text := digits[rem] # text; + n := n / base; + }; + return text; +}; + +func @text_of_Int(x : Int) : Text { + if (x == 0) { + return "0"; + }; + if (x < 0) { + "-" # @text_of_Nat(abs x) + } else { + @text_of_Nat(abs x) + } +}; + +func @text_of_Bool(b : Bool) : Text { + if (b) "true" else "false" +}; + +func @text_of_Text(t : Text) : Text { + // TODO: Escape properly + "\"" # t # "\""; +}; + +func @text_of_option(f : T -> Text, x : ?T) : Text { + switch (x) { + case (?y) {"?(" # f y # ")"}; + case null {"null"}; + } +}; + +func @text_of_variant(l : Text, f : T -> Text, x : T) : Text { + let fx = f x; + if (fx == "()") "(#" # l # ")" + else "(#" # l # " " # fx # ")" +}; + +func @text_of_array(f : T -> Text, xs : [T]) : Text { + var text = ""; + for (x in xs.vals()) { + if (text == "") { + text := text # "["; + } else { + text := text # ", "; + }; + text := text # f x; + }; + text := text # "]"; + return text; +}; + +func @text_of_array_mut(f : T -> Text, xs : [var T]) : Text { + var text = ""; + for (x in xs.vals()) { + if (text == "") { + text := text # "[var "; + } else { + text := text # ", "; + }; + text := text # f x; + }; + text := text # "]"; + return text; +}; + +// Array utilities + +// This would be nicer as a objects, but lets do them as functions +// until the compiler has a concept of “static objects” +func Array_init(len : Nat, x : T) : [var T] { + (prim "Array.init" : (Nat, T) -> [var T])(len, x) +}; + +func Array_tabulate(len : Nat, gen : Nat -> T) : [T] { + (prim "Array.tabulate" : (Nat, Nat -> T) -> [T])(len, gen) +}; + +type Cont = T -> () ; +type Async = Cont -> (); + +func @new_async():(Async, Cont) { + let empty = func k (t:T) = (); + var result : ?T = null; + var ks : T -> () = empty; + func fulfill(t:T):() { + switch(result) { + case null { + result := ?t; + let ks_ = ks; + ks := empty; + ks_(t); + }; + case (?t) (assert(false)); + }; + }; + func enqueue(k:Cont):() { + switch(result) { + case null { + let ks_ = ks; + ks := (func (t:T) {ks_(t);k(t);}); + }; + case (?t) (k(t)); + }; + }; + (enqueue,fulfill) +}; +|} diff --git a/src/prelude/prelude.mli b/src/prelude/prelude.mli new file mode 100644 index 00000000000..e9b8a0b9f64 --- /dev/null +++ b/src/prelude/prelude.mli @@ -0,0 +1 @@ +val prelude : string diff --git a/src/aslib/customModule.ml b/src/wasm-exts/customModule.ml similarity index 100% rename from src/aslib/customModule.ml rename to src/wasm-exts/customModule.ml diff --git a/src/aslib/customModuleDecode.ml b/src/wasm-exts/customModuleDecode.ml similarity index 100% rename from src/aslib/customModuleDecode.ml rename to src/wasm-exts/customModuleDecode.ml diff --git a/src/aslib/customModuleDecode.mli b/src/wasm-exts/customModuleDecode.mli similarity index 100% rename from src/aslib/customModuleDecode.mli rename to src/wasm-exts/customModuleDecode.mli diff --git a/src/aslib/customModuleEncode.ml b/src/wasm-exts/customModuleEncode.ml similarity index 100% rename from src/aslib/customModuleEncode.ml rename to src/wasm-exts/customModuleEncode.ml diff --git a/src/aslib/customModuleEncode.mli b/src/wasm-exts/customModuleEncode.mli similarity index 100% rename from src/aslib/customModuleEncode.mli rename to src/wasm-exts/customModuleEncode.mli diff --git a/src/wasm-exts/dune b/src/wasm-exts/dune new file mode 100644 index 00000000000..d739a086164 --- /dev/null +++ b/src/wasm-exts/dune @@ -0,0 +1,4 @@ +(library + (name wasm_exts) + (libraries wasm vlq yojson lib flags prelude) +) From 1afd2e747fa03470bc18eb216f6a04c14170904d Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 13 Jun 2019 12:59:33 +0200 Subject: [PATCH 0158/1176] Move call_conv into its own module (#486) There are many modules that were using `Value` only to get functions related to the calling convention, which really is more closely related to the type of functions (it is a project of the function type, after all). Moving stuff into its own module disentangled the module dependency graph a bit. Might help with #843, in particular seperateing `Value` from `Type`, as suggested by Claudio in https://github.com/dfinity-lab/actorscript/pull/483#discussion_r291564774 --- src/as_ir/arrange_ir.ml | 3 +-- src/as_ir/check_ir.ml | 12 ++++----- src/as_ir/construct.ml | 16 ++++++------ src/as_ir/ir.ml | 4 +-- src/as_types/call_conv.ml | 27 ++++++++++++++++++++ src/as_types/call_conv.mli | 17 +++++++++++++ src/as_types/type.ml | 8 +++--- src/as_types/type.mli | 2 -- src/as_values/value.ml | 36 ++++----------------------- src/as_values/value.mli | 19 +++----------- src/codegen/compile.ml | 32 ++++++++++++------------ src/interpreter/interpret.ml | 37 +++++++++++++++------------ src/ir_interpreter/interpret_ir.ml | 40 +++++++++++++++++------------- src/ir_passes/async.ml | 5 ++-- src/ir_passes/serialization.ml | 9 +++---- src/ir_passes/show.ml | 14 +++++------ src/ir_passes/tailcall.ml | 3 +-- src/lowering/desugar.ml | 13 +++++----- 18 files changed, 153 insertions(+), 144 deletions(-) create mode 100644 src/as_types/call_conv.ml create mode 100644 src/as_types/call_conv.mli diff --git a/src/as_ir/arrange_ir.ml b/src/as_ir/arrange_ir.ml index 053f118700b..9a87348ec13 100644 --- a/src/as_ir/arrange_ir.ml +++ b/src/as_ir/arrange_ir.ml @@ -1,6 +1,5 @@ open As_frontend open As_types -open As_values open Source open Arrange_type open Ir @@ -68,7 +67,7 @@ and pat_field pf = pf.it.name $$ [pat pf.it.pat] and case c = "case" $$ [pat c.it.pat; exp c.it.exp] -and call_conv cc = Atom (Value.string_of_call_conv cc) +and call_conv cc = Atom (Call_conv.string_of_call_conv cc) and dec d = match d.it with | LetD (p, e) -> "LetD" $$ [pat p; exp e] diff --git a/src/as_ir/check_ir.ml b/src/as_ir/check_ir.ml index 4e6b4e800f5..0de0c3ba676 100644 --- a/src/as_ir/check_ir.ml +++ b/src/as_ir/check_ir.ml @@ -393,7 +393,7 @@ let rec check_exp env (exp:Ir.exp) : unit = (* TODO: check call_conv (assuming there's something to check) *) let t1 = T.promote (typ exp1) in let _, tbs, t2, t3 = - try T.as_func_sub call_conv.Value.sort (List.length insts) t1 with + try T.as_func_sub call_conv.Call_conv.sort (List.length insts) t1 with | Invalid_argument _ -> error env exp1.at "expected function type, but expression produces type\n %s" (T.string_of_typ_expand t1) @@ -402,7 +402,7 @@ let rec check_exp env (exp:Ir.exp) : unit = check_exp env exp2; let t_arg = T.open_ insts t2 in let t_ret = T.open_ insts t3 in - if (call_conv.Value.sort = T.Sharable) then begin + if (call_conv.Call_conv.sort = T.Sharable) then begin check_concrete env exp.at t_arg; check_concrete env exp.at t_ret; end; @@ -510,19 +510,19 @@ let rec check_exp env (exp:Ir.exp) : unit = let env' = adjoin_cons env ce in let ve = check_args env' args in List.iter (check_typ env') ret_tys; - check ((cc.Value.sort = T.Sharable && Type.is_async (T.seq ret_tys)) + check ((cc.Call_conv.sort = T.Sharable && Type.is_async (T.seq ret_tys)) ==> isAsyncE exp) "shared function with async type has non-async body"; - if (cc.Value.sort = T.Sharable) then List.iter (check_concrete env exp.at) ret_tys; + if (cc.Call_conv.sort = T.Sharable) then List.iter (check_concrete env exp.at) ret_tys; let env'' = {env' with labs = T.Env.empty; rets = Some (T.seq ret_tys); async = false} in check_exp (adjoin_vals env'' ve) exp; check_sub env' exp.at (typ exp) (T.seq ret_tys); (* Now construct the function type and compare with the annotation *) let ts1 = List.map (fun a -> a.note) args in - if (cc.Value.sort = T.Sharable) then List.iter (check_concrete env exp.at) ts1; + if (cc.Call_conv.sort = T.Sharable) then List.iter (check_concrete env exp.at) ts1; let fun_ty = T.Func - ( cc.Value.sort, cc.Value.control + ( cc.Call_conv.sort, cc.Call_conv.control , tbs, List.map (T.close cs) ts1, List.map (T.close cs) ret_tys ) in fun_ty <: t diff --git a/src/as_ir/construct.ml b/src/as_ir/construct.ml index 56b3c61124a..bcd30fcaf2d 100644 --- a/src/as_ir/construct.ml +++ b/src/as_ir/construct.ml @@ -1,5 +1,5 @@ open As_frontend -open As_values +open As_types (* WIP translation of syntaxops to use IR in place of Source *) open Source @@ -156,8 +156,8 @@ let boolE b = let callE exp1 ts exp2 = let fun_ty = typ exp1 in - let cc = Value.call_conv_of_typ fun_ty in - let _, _, _, ret_ty = T.as_func_sub cc.Value.sort (List.length ts) fun_ty in + let cc = Call_conv.call_conv_of_typ fun_ty in + let _, _, _, ret_ty = T.as_func_sub cc.Call_conv.sort (List.length ts) fun_ty in { it = CallE (cc, exp1, ts, exp2); at = no_region; note = { S.note_typ = T.open_ ts ret_ty; @@ -325,9 +325,9 @@ let funcE name t x exp = let arg_tys, retty = match t with | T.Func(_, _, _, ts1, ts2) -> ts1, ts2 | _ -> assert false in - let cc = Value.call_conv_of_typ t in + let cc = Call_conv.call_conv_of_typ t in let args, exp' = - if cc.Value.n_args = 1; + if cc.Call_conv.n_args = 1; then [ arg_of_exp x ], exp else @@ -352,8 +352,8 @@ let nary_funcE name t xs exp = let retty = match t with | T.Func(_, _, _, _, ts2) -> ts2 | _ -> assert false in - let cc = Value.call_conv_of_typ t in - assert (cc.Value.n_args = List.length xs); + let cc = Call_conv.call_conv_of_typ t in + assert (cc.Call_conv.n_args = List.length xs); ({it = FuncE ( name, cc, @@ -428,7 +428,7 @@ let (-@>*) xs exp = let ( -*- ) exp1 exp2 = match typ exp1 with | T.Func (_, _, [], ts1, ts2) -> - let cc = Value.call_conv_of_typ (typ exp1) in + let cc = Call_conv.call_conv_of_typ (typ exp1) in { it = CallE (cc, exp1, [], exp2); at = no_region; note = {S.note_typ = T.seq ts2; diff --git a/src/as_ir/ir.ml b/src/as_ir/ir.ml index c829d044c23..0b5ca5a9e1c 100644 --- a/src/as_ir/ir.ml +++ b/src/as_ir/ir.ml @@ -56,7 +56,7 @@ and exp' = | ArrayE of mut * Type.typ * exp list (* array *) | IdxE of exp * exp (* array indexing *) | CallE of (* function call *) - Value.call_conv * exp * Type.typ list * exp + Call_conv.t * exp * Type.typ list * exp | BlockE of (dec list * exp) (* block *) | IfE of exp * exp * exp (* conditional *) | SwitchE of exp * case list (* switch *) @@ -70,7 +70,7 @@ and exp' = | DeclareE of id * Type.typ * exp (* local promise *) | DefineE of id * mut * exp (* promise fulfillment *) | FuncE of (* function *) - string * Value.call_conv * typ_bind list * arg list * Type.typ list * exp + string * Call_conv.t * typ_bind list * arg list * Type.typ list * exp | ActorE of id * dec list * field list * Type.typ (* actor *) | NewObjE of Type.obj_sort * field list * Type.typ (* make an object *) diff --git a/src/as_types/call_conv.ml b/src/as_types/call_conv.ml new file mode 100644 index 00000000000..8b479185886 --- /dev/null +++ b/src/as_types/call_conv.ml @@ -0,0 +1,27 @@ +open Type + +type call_conv = { + sort: sharing; + control : control; + n_args : int; + n_res : int; +} +type t = call_conv + +let local_cc n m = { sort = Local; control = Returns; n_args = n; n_res = m} +let message_cc n = { sort = Sharable; control = Returns; n_args = n; n_res = 0} +let async_cc n = { sort = Sharable; control = Promises; n_args = n; n_res = 1} + +let call_conv_of_typ typ = + match typ with + | Func(sort, control, tbds, dom, res) -> + { sort; control; n_args = List.length dom; n_res = List.length res } + | _ -> raise (Invalid_argument ("call_conv_of_typ " ^ string_of_typ typ)) + +let string_of_call_conv {sort;control;n_args;n_res} = + Printf.sprintf "(%s %i %s %i)" + (string_of_sharing sort) + n_args + (match control with Returns -> "->" | Promises -> "@>") + n_res + diff --git a/src/as_types/call_conv.mli b/src/as_types/call_conv.mli new file mode 100644 index 00000000000..5cef573ce01 --- /dev/null +++ b/src/as_types/call_conv.mli @@ -0,0 +1,17 @@ +(* Calling convention *) + +type call_conv = { + sort: Type.sharing; + control : Type.control; + n_args : int; + n_res : int; +} +type t = call_conv + +val local_cc : int -> int -> call_conv +val message_cc : int -> call_conv +val async_cc : int -> call_conv + +val call_conv_of_typ : Type.typ -> call_conv + +val string_of_call_conv : call_conv -> string diff --git a/src/as_types/type.ml b/src/as_types/type.ml index 7a880ae8498..662031c2787 100644 --- a/src/as_types/type.ml +++ b/src/as_types/type.ml @@ -773,6 +773,9 @@ and glb_tags fs1 fs2 = match fs1, fs2 with | +1 -> glb_tags fs1 fs2' | _ -> {f1 with typ = glb f1.typ f2.typ}::glb_tags fs1' fs2' +(* Environments *) + +module Env = Env.Make(String) (* Pretty printing *) @@ -936,8 +939,3 @@ let rec string_of_typ_expand t = | t' -> s ^ " = " ^ string_of_typ_expand t' ) | _ -> s - - -(* Environments *) - -module Env = Env.Make(String) diff --git a/src/as_types/type.mli b/src/as_types/type.mli index e32bd6b3646..3835d0eed5d 100644 --- a/src/as_types/type.mli +++ b/src/as_types/type.mli @@ -168,7 +168,6 @@ val open_binds : bind list -> typ list module Env : Env.S with type key = string - (* Pretty printing *) val string_of_con : con -> string @@ -177,5 +176,4 @@ val string_of_sharing: sharing -> string val string_of_typ : typ -> string val string_of_kind : kind -> string val strings_of_kind : kind -> string * string * string - val string_of_typ_expand : typ -> string diff --git a/src/as_values/value.ml b/src/as_values/value.ml index 0abab03142c..2fb46c563ee 100644 --- a/src/as_values/value.ml +++ b/src/as_values/value.ml @@ -1,5 +1,5 @@ +open As_types open Printf -module T = As_types.Type (* Environments *) @@ -193,19 +193,6 @@ end type unicode = int -type call_conv = { - sort: T.sharing; - control : T.control; - n_args : int; - n_res : int; -} - -let call_conv_of_typ typ = - match typ with - | T.Func(sort, control, tbds, dom, res) -> - { sort; control; n_args = List.length dom; n_res = List.length res } - | _ -> raise (Invalid_argument ("call_conv_of_typ " ^ T.string_of_typ typ)) - type func = (value -> value cont -> unit) and value = @@ -224,7 +211,7 @@ and value = | Variant of string * value | Array of value array | Obj of value Env.t - | Func of call_conv * func + | Func of Call_conv.t * func | Async of async | Mut of value ref | Serialized of value @@ -236,13 +223,9 @@ and 'a cont = 'a -> unit (* Smart constructors *) -let local_cc n m = { sort = T.Local; control = T.Returns; n_args = n; n_res = m} -let message_cc n = { sort = T.Sharable; control = T.Returns; n_args = n; n_res = 0} -let async_cc n = { sort = T.Sharable; control = T.Promises; n_args = n; n_res = 1} - -let local_func n m f = Func (local_cc n m, f) -let message_func n f = Func (message_cc n, f) -let async_func n f = Func (async_cc n, f) +let local_func n m f = Func (Call_conv.local_cc n m, f) +let message_func n f = Func (Call_conv.message_cc n, f) +let async_func n f = Func (Call_conv.async_cc n, f) (* Projections *) @@ -419,12 +402,3 @@ and string_of_def d def = match Lib.Promise.value_opt def with | Some v -> string_of_val d v | None -> "_" - -let string_of_call_conv {sort;control;n_args;n_res} = - sprintf "(%s %i %s %i)" - (T.string_of_sharing sort) - n_args - (match control with - | T.Returns -> "->" - | T.Promises -> "@>") - n_res diff --git a/src/as_values/value.mli b/src/as_values/value.mli index 8fa1f0b8e5a..2ad651c9084 100644 --- a/src/as_values/value.mli +++ b/src/as_values/value.mli @@ -61,15 +61,6 @@ module Env : Env.S with type key = string type unicode = int -type call_conv = { - sort: Type.sharing; - control : Type.control; - n_args : int; - n_res : int; -} - -val call_conv_of_typ : Type.typ -> call_conv - type func = value -> value cont -> unit and value = | Null @@ -87,7 +78,7 @@ and value = | Variant of string * value | Array of value array | Obj of value Env.t - | Func of call_conv * func + | Func of Call_conv.t * func | Async of async | Mut of value ref | Serialized of value @@ -104,10 +95,6 @@ val unit : value (* Smart constructors *) -val local_cc : int -> int -> call_conv -val message_cc : int -> call_conv -val async_cc : int -> call_conv - val local_func : int -> int -> func -> value val message_func : int -> func -> value val async_func : int -> func -> value @@ -131,7 +118,7 @@ val as_pair : value -> value * value val as_opt : value -> value val as_obj : value -> value Env.t val as_variant : value -> string * value -val as_func : value -> call_conv * func +val as_func : value -> Call_conv.t * func val as_async : value -> async val as_mut : value -> value ref val as_serialized : value -> value @@ -147,4 +134,4 @@ val compare : value -> value -> int val string_of_val : int -> value -> string val string_of_def : int -> def -> string -val string_of_call_conv : call_conv -> string + diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 32d01af612c..25f36f8662a 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -1125,8 +1125,8 @@ module Closure = struct An extra first argument for the closure! *) let ty env cc = E.func_type env (FuncType ( - I32Type :: Lib.List.make cc.Value.n_args I32Type, - Lib.List.make cc.Value.n_res I32Type)) + I32Type :: Lib.List.make cc.Call_conv.n_args I32Type, + Lib.List.make cc.Call_conv.n_res I32Type)) (* Expect on the stack * the function closure @@ -2335,7 +2335,7 @@ module Arr = struct (* The closure again *) get_f ^^ (* Call *) - Closure.call_closure env (Value.local_cc 1 1) ^^ + Closure.call_closure env (Call_conv.local_cc 1 1) ^^ store_ptr ) ^^ get_r @@ -3897,7 +3897,7 @@ module FuncDec = struct (* The type of messages *) let message_ty env cc = - E.func_type env (FuncType (Lib.List.make cc.Value.n_args I32Type,[])) + E.func_type env (FuncType (Lib.List.make cc.Call_conv.n_args I32Type,[])) (* Expects all arguments on the stack, in serialized form. *) let call_funcref env cc get_ref = @@ -3937,7 +3937,7 @@ module FuncDec = struct the function will find in the closure. *) let compile_local_function outer_env outer_ae cc restore_env args mk_body at = let arg_names = List.map (fun a -> a.it, I32Type) args in - let retty = Lib.List.make cc.Value.n_res I32Type in + let retty = Lib.List.make cc.Call_conv.n_res I32Type in let ae0 = ASEnv.mk_fun_ae outer_ae in Func.of_body outer_env (["clos", I32Type] @ arg_names) retty (fun env -> G.with_region at ( let get_closure = G.i (LocalGet (nr 0l)) in @@ -3963,7 +3963,7 @@ module FuncDec = struct *) let compile_message outer_env outer_ae cc restore_env args mk_body at = let arg_names = List.map (fun a -> a.it, I32Type) args in - assert (cc.Value.n_res = 0); + assert (cc.Call_conv.n_res = 0); let ae0 = ASEnv.mk_fun_ae outer_ae in Func.of_body outer_env (["clos", I32Type] @ arg_names) [] (fun env -> G.with_region at ( (* Restore memory *) @@ -3994,7 +3994,7 @@ module FuncDec = struct let compile_static_message outer_env outer_ae cc args mk_body at : E.func_with_names = let arg_names = List.map (fun a -> a.it, I32Type) args in - assert (cc.Value.n_res = 0); + assert (cc.Call_conv.n_res = 0); let ae0 = ASEnv.mk_fun_ae outer_ae in (* Messages take no closure, return nothing *) Func.of_body outer_env arg_names [] (fun env -> @@ -4026,7 +4026,7 @@ module FuncDec = struct (* Compile a closed function declaration (captures no local variables) *) let closed pre_env cc name args mk_body at = let (fi, fill) = E.reserve_fun pre_env name in - if cc.Value.sort = Type.Sharable + if cc.Call_conv.sort = Type.Sharable then begin declare_dfinity_type pre_env false fi args; ( SR.StaticMessage fi, fun env ae -> @@ -4040,7 +4040,7 @@ module FuncDec = struct (* Compile a closure declaration (captures local variables) *) let closure env ae cc name captured args mk_body at = - let is_local = cc.Value.sort <> Type.Sharable in + let is_local = cc.Call_conv.sort <> Type.Sharable in let (set_clos, get_clos) = new_local env (name ^ "_clos") in @@ -4866,27 +4866,27 @@ and compile_exp (env : E.t) ae exp = | ArrayE (m, t, es) -> SR.Vanilla, Arr.lit env (List.map (compile_exp_vanilla env ae) es) | CallE (cc, e1, _, e2) -> - StackRep.of_arity (cc.Value.n_res), + StackRep.of_arity cc.Call_conv.n_res, let fun_sr, code1 = compile_exp env ae e1 in - begin match fun_sr, cc.Value.sort with + begin match fun_sr, cc.Call_conv.sort with | SR.StaticThing (SR.StaticFun fi), _ -> code1 ^^ compile_unboxed_zero ^^ (* A dummy closure *) - compile_exp_as env ae (StackRep.of_arity cc.Value.n_args) e2 ^^ (* the args *) + compile_exp_as env ae (StackRep.of_arity cc.Call_conv.n_args) e2 ^^ (* the args *) G.i (Call (nr fi)) | _, Type.Local -> let (set_clos, get_clos) = new_local env "clos" in code1 ^^ StackRep.adjust env fun_sr SR.Vanilla ^^ set_clos ^^ get_clos ^^ - compile_exp_as env ae (StackRep.of_arity cc.Value.n_args) e2 ^^ + compile_exp_as env ae (StackRep.of_arity cc.Call_conv.n_args) e2 ^^ get_clos ^^ Closure.call_closure env cc | _, Type.Sharable -> let (set_funcref, get_funcref) = new_local env "funcref" in code1 ^^ StackRep.adjust env fun_sr SR.UnboxedReference ^^ set_funcref ^^ - compile_exp_as env ae (StackRep.refs_of_arity cc.Value.n_args) e2 ^^ + compile_exp_as env ae (StackRep.refs_of_arity cc.Call_conv.n_args) e2 ^^ FuncDec.call_funcref env cc get_funcref end | SwitchE (e, cs) -> @@ -4919,7 +4919,7 @@ and compile_exp (env : E.t) ae exp = Var.set_val env ae name.it | FuncE (x, cc, typ_binds, args, _rt, e) -> let captured = Freevars.captured exp in - let mk_body env1 ae1 = compile_exp_as env1 ae1 (StackRep.of_arity cc.Value.n_res) e in + let mk_body env1 ae1 = compile_exp_as env1 ae1 (StackRep.of_arity cc.Call_conv.n_res) e in FuncDec.lit env ae typ_binds x cc captured args mk_body exp.at | ActorE (i, ds, fs, _) -> SR.UnboxedReference, @@ -5213,7 +5213,7 @@ and compile_static_exp env pre_ae how exp = match exp.it with List.for_all (fun v -> ASEnv.NameEnv.mem v ae.ASEnv.vars) (Freevars.M.keys (Freevars.exp e)) end; - compile_exp_as env ae (StackRep.of_arity cc.Value.n_res) e in + compile_exp_as env ae (StackRep.of_arity cc.Call_conv.n_res) e in FuncDec.closed env cc name args mk_body exp.at | _ -> assert false diff --git a/src/interpreter/interpret.ml b/src/interpreter/interpret.ml index ad8342bf1d7..6bcca1ef848 100644 --- a/src/interpreter/interpret.ml +++ b/src/interpreter/interpret.ml @@ -5,6 +5,7 @@ open Source module V = As_values.Value module T = As_types.Type +module CC = As_types.Call_conv (* Context *) @@ -170,21 +171,23 @@ let actor_msg env id f v (k : V.value V.cont) = ) let make_unit_message env id v = + let open CC in let call_conv, f = V.as_func v in match call_conv with - | {V.sort = T.Sharable; V.n_res = 0; _} -> - Value.message_func call_conv.V.n_args (fun v k -> + | {sort = T.Sharable; n_res = 0; _} -> + Value.message_func call_conv.n_args (fun v k -> actor_msg env id f v (fun _ -> ()); k V.unit ) | _ -> (* assert false *) - failwith ("unexpected call_conv " ^ (V.string_of_call_conv call_conv)) + failwith ("unexpected call_conv " ^ (string_of_call_conv call_conv)) let make_async_message env id v = + let open CC in let call_conv, f = V.as_func v in match call_conv with - | {V.sort = T.Sharable; V.control = T.Promises; V.n_res = 1; _} -> - Value.async_func call_conv.V.n_args (fun v k -> + | {sort = T.Sharable; control = T.Promises; n_res = 1; _} -> + Value.async_func call_conv.n_args (fun v k -> let async = make_async () in actor_msg env id f v (fun v_async -> get_async (V.as_async v_async) (fun v_r -> set_async async v_r) @@ -192,7 +195,7 @@ let make_async_message env id v = k (V.Async async) ) | _ -> (* assert false *) - failwith ("unexpected call_conv " ^ (V.string_of_call_conv call_conv)) + failwith ("unexpected call_conv " ^ (string_of_call_conv call_conv)) let make_message env name t v : V.value = @@ -224,31 +227,33 @@ let interpret_lit env lit : V.value = (* Expressions *) let check_call_conv exp call_conv = - let exp_call_conv = V.call_conv_of_typ exp.note.note_typ in + let open CC in + let exp_call_conv = call_conv_of_typ exp.note.note_typ in if not (exp_call_conv = call_conv) then failwith (Printf.sprintf "call_conv mismatch: function %s of type %s expecting %s, found %s" (Wasm.Sexpr.to_string 80 (Arrange.exp exp)) (T.string_of_typ exp.note.note_typ) - (V.string_of_call_conv exp_call_conv) - (V.string_of_call_conv call_conv) + (string_of_call_conv exp_call_conv) + (string_of_call_conv call_conv) ) let check_call_conv_arg env exp v call_conv = - if call_conv.V.n_args <> 1 then + let open CC in + if call_conv.n_args <> 1 then let es = try V.as_tup v with Invalid_argument _ -> failwith (Printf.sprintf "call %s: calling convention %s cannot handle non-tuple value %s" (Wasm.Sexpr.to_string 80 (Arrange.exp exp)) - (V.string_of_call_conv call_conv) + (string_of_call_conv call_conv) (string_of_val env v) ) in - if List.length es <> call_conv.V.n_args then + if List.length es <> call_conv.n_args then failwith (Printf.sprintf "call %s: calling convention %s got tuple of wrong length %s" (Wasm.Sexpr.to_string 80 (Arrange.exp exp)) - (V.string_of_call_conv call_conv) + (string_of_call_conv call_conv) (string_of_val env v) ) @@ -261,7 +266,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = last_env := env; match exp.it with | PrimE s -> - k (V.Func (V.call_conv_of_typ exp.note.note_typ, Prim.prim s)) + k (V.Func (CC.call_conv_of_typ exp.note.note_typ, Prim.prim s)) | VarE id -> begin match Lib.Promise.value_opt (find id.it env.vals) with | Some v -> k v @@ -329,7 +334,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = ) | FuncE (name, _sort, _typbinds, pat, _typ, exp2) -> let f = interpret_func env name pat (fun env' -> interpret_exp env' exp2) in - let v = V.Func (V.call_conv_of_typ exp.note.note_typ, f) in + let v = V.Func (CC.call_conv_of_typ exp.note.note_typ, f) in let v' = match _sort.it with | T.Sharable -> make_message env name exp.note.note_typ v @@ -671,7 +676,7 @@ and interpret_dec env dec (k : V.value V.cont) = k' v' ) ) in - let v = V.Func (V.call_conv_of_typ dec.note.note_typ, f) in + let v = V.Func (CC.call_conv_of_typ dec.note.note_typ, f) in define_id env {id with note = ()} v; k v diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index 42f87f79f2d..1293b76a879 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -8,6 +8,7 @@ open As_frontend module V = Value module T = Type +module CC = As_types.Call_conv (* Context *) @@ -164,23 +165,25 @@ let actor_msg env id f v (k : V.value V.cont) = ) let make_unit_message env id v = + let open CC in let call_conv, f = V.as_func v in match call_conv with - | {V.sort = T.Sharable; V.n_res = 0; _} -> - Value.message_func call_conv.V.n_args (fun v k -> + | {sort = T.Sharable; n_res = 0; _} -> + Value.message_func call_conv.n_args (fun v k -> actor_msg env id f v (fun _ -> ()); k V.unit ) | _ -> - failwith ("unexpected call_conv " ^ (V.string_of_call_conv call_conv)) + failwith ("unexpected call_conv " ^ string_of_call_conv call_conv) (* assert (false) *) let make_async_message env id v = assert env.flavor.has_async_typ; + let open CC in let call_conv, f = V.as_func v in match call_conv with - | {V.sort = T.Sharable; V.control = T.Promises; V.n_res = 1; _} -> - Value.async_func call_conv.V.n_args (fun v k -> + | {sort = T.Sharable; control = T.Promises; n_res = 1; _} -> + Value.async_func call_conv.n_args (fun v k -> let async = make_async () in actor_msg env id f v (fun v_async -> get_async (V.as_async v_async) (fun v_r -> set_async async v_r) @@ -188,12 +191,12 @@ let make_async_message env id v = k (V.Async async) ) | _ -> - failwith ("unexpected call_conv " ^ (V.string_of_call_conv call_conv)) + failwith ("unexpected call_conv " ^ string_of_call_conv call_conv) (* assert (false) *) let make_message env x cc v : V.value = - match cc.V.control with + match cc.CC.control with | T.Returns -> make_unit_message env x v | T.Promises -> make_async_message env x v @@ -206,7 +209,7 @@ let extended_prim env s typ at = let (_, f) = V.as_func v in match typ with | T.Func(_, _, _, [T.Func(_, _, _, [f_dom], _)], _) -> - let call_conv = Value.call_conv_of_typ f_dom in + let call_conv = CC.call_conv_of_typ f_dom in async env at (fun k' -> let k' = Value.Func (call_conv, fun v _ -> k' v) in @@ -248,26 +251,28 @@ let interpret_lit env lit : V.value = (* Expressions *) let check_call_conv exp call_conv = - let exp_call_conv = V.call_conv_of_typ exp.note.Syntax.note_typ in + let open Call_conv in + let exp_call_conv = call_conv_of_typ exp.note.Syntax.note_typ in if not (exp_call_conv = call_conv) then failwith (Printf.sprintf "call_conv mismatch: function %s of type %s expecting %s, found %s" (Wasm.Sexpr.to_string 80 (Arrange_ir.exp exp)) (T.string_of_typ exp.note.Syntax.note_typ) - (V.string_of_call_conv exp_call_conv) - (V.string_of_call_conv call_conv)) + (string_of_call_conv exp_call_conv) + (string_of_call_conv call_conv)) let check_call_conv_arg env exp v call_conv = - if call_conv.V.n_args <> 1 then + let open CC in + if call_conv.n_args <> 1 then let es = try V.as_tup v with Invalid_argument _ -> failwith (Printf.sprintf "call %s: calling convention %s cannot handle non-tuple value %s" (Wasm.Sexpr.to_string 80 (Arrange_ir.exp exp)) - (V.string_of_call_conv call_conv) + (string_of_call_conv call_conv) (string_of_val env v)) in - if List.length es <> call_conv.V.n_args then + if List.length es <> call_conv.n_args then failwith (Printf.sprintf "call %s: calling convention %s got tuple of wrong length %s" (Wasm.Sexpr.to_string 80 (Arrange_ir.exp exp)) - (V.string_of_call_conv call_conv) + (string_of_call_conv call_conv) (string_of_val env v)) @@ -275,13 +280,14 @@ let rec interpret_exp env exp (k : V.value V.cont) = interpret_exp_mut env exp (function V.Mut r -> k !r | v -> k v) and interpret_exp_mut env exp (k : V.value V.cont) = + let open Call_conv in last_region := exp.at; last_env := env; match exp.it with | PrimE s -> let at = exp.at in let t = exp.note.Syntax.note_typ in - let cc = V.call_conv_of_typ t in + let cc = call_conv_of_typ t in k (V.Func (cc, extended_prim env s t at)) | VarE id -> (match Lib.Promise.value_opt (find id.it env.vals) with @@ -419,7 +425,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = (fun env' -> interpret_exp env' e) in let v = V.Func (cc, f) in let v = - match cc.Value.sort with + match cc.sort with | T.Sharable -> make_message env x cc v | _-> v in diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index 9fb895680f2..5e2b05528a0 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -1,6 +1,5 @@ open As_types open As_ir -open As_values open As_frontend module E = Env open Source @@ -318,7 +317,7 @@ module Transform() = struct | DefineE (id, mut ,exp1) -> DefineE (id, mut, t_exp exp1) | FuncE (x, cc, typbinds, args, typT, exp) -> - let s = cc.Value.sort in + let s = cc.Call_conv.sort in begin match s with | T.Local -> @@ -329,7 +328,7 @@ module Transform() = struct | T.Tup [] -> FuncE (x, cc, t_typ_binds typbinds, t_args args, List.map t_typ typT, t_exp exp) | T.Async res_typ -> - let cc' = Value.message_cc (cc.Value.n_args + 1) in + let cc' = Call_conv.message_cc (cc.Call_conv.n_args + 1) in let res_typ = t_typ res_typ in let reply_typ = replyT nary res_typ in let k = fresh_var "k" reply_typ in diff --git a/src/ir_passes/serialization.ml b/src/ir_passes/serialization.ml index 89d2c1819b6..684ea9db802 100644 --- a/src/ir_passes/serialization.ml +++ b/src/ir_passes/serialization.ml @@ -1,7 +1,6 @@ open As_frontend open As_ir open As_types -open As_values open Source open Ir module T = Type @@ -131,20 +130,20 @@ module Transform() = struct let exp' = exp.it in match exp' with | CallE (cc, exp1, typs, exp2) -> - begin match cc.Value.sort with + begin match cc.Call_conv.sort with | T.Local -> CallE(cc, t_exp exp1, List.map t_typ typs, t_exp exp2) | T.Sharable -> (* We should take the type to serialize at from the function, not the argument, as the latter could be a subtype *) let fun_ty = exp1.note.note_typ in - let _, _, t_arg, t_ret = T.as_func_sub cc.Value.sort (List.length typs) fun_ty in + let _, _, t_arg, t_ret = T.as_func_sub cc.Call_conv.sort (List.length typs) fun_ty in assert (T.is_unit t_ret); - let exp2' = map_tuple cc.Value.n_args serialize (t_exp exp2) (t_typ (T.open_ typs t_arg)) in + let exp2' = map_tuple cc.Call_conv.n_args serialize (t_exp exp2) (t_typ (T.open_ typs t_arg)) in CallE (cc, t_exp exp1, [], exp2') end | FuncE (x, cc, typbinds, args, ret_tys, exp) -> - begin match cc.Value.sort with + begin match cc.Call_conv.sort with | T.Local -> FuncE (x, cc, t_typ_binds typbinds, t_args args, List.map t_typ ret_tys, t_exp exp) | T.Sharable -> diff --git a/src/ir_passes/show.ml b/src/ir_passes/show.ml index b7ddd2ee3fc..b8c37d42760 100644 --- a/src/ir_passes/show.ml +++ b/src/ir_passes/show.ml @@ -71,7 +71,7 @@ and t_exp' env = function let t' = T.normalize ot in add_type env t'; let f = idE (show_name_for t' @@ no_region) (show_fun_typ_for t') in - CallE(Value.local_cc 1 1, f, [], t_exp env exp1) + CallE (Call_conv.local_cc 1 1, f, [], t_exp env exp1) | UnE (ot, op, exp1) -> UnE (ot, op, t_exp env exp1) | BinE (ot, exp1, op, exp2) -> @@ -162,12 +162,12 @@ let text_exp : Ir.exp' -> Ir.exp = fun e -> } let invoke_generated_show : T.typ -> Ir.exp -> Ir.exp = fun t e -> - text_exp (CallE (Value.local_cc 1 1, show_var_for t, [], e)) + text_exp (CallE (Call_conv.local_cc 1 1, show_var_for t, [], e)) let invoke_prelude_show : string -> T.typ -> Ir.exp -> Ir.exp = fun n t e -> let fun_typ = T.Func (T.Local, T.Returns, [], [t], [T.Prim T.Text]) in text_exp (CallE - ( Value.local_cc 1 1 + ( Call_conv.local_cc 1 1 , { it = VarE (n @@ no_region) ; at = no_region ; note = { note_typ = fun_typ; note_eff = T.Triv } @@ -181,7 +181,7 @@ let invoke_text_of_option : T.typ -> Ir.exp -> Ir.exp -> Ir.exp = fun t f e -> let fun_typ = T.Func (T.Local, T.Returns, [{T.var="T";T.bound=T.Any}], [show_fun_typ_for (T.Var ("T",0)); T.Opt (T.Var ("T",0))], [T.Prim T.Text]) in text_exp (CallE - ( Value.local_cc 2 1 + ( Call_conv.local_cc 2 1 , { it = VarE ("@text_of_option" @@ no_region) ; at = no_region ; note = { note_typ = fun_typ; note_eff = T.Triv } @@ -198,7 +198,7 @@ let invoke_text_of_variant : T.typ -> Ir.exp -> T.lab -> Ir.exp -> Ir.exp = fun let fun_typ = T.Func (T.Local, T.Returns, [{T.var="T";T.bound=T.Any}], [T.Prim T.Text; show_fun_typ_for (T.Var ("T",0)); T.Var ("T",0)], [T.Prim T.Text]) in text_exp (CallE - ( Value.local_cc 3 1 + ( Call_conv.local_cc 3 1 , { it = VarE ("@text_of_variant" @@ no_region) ; at = no_region ; note = { note_typ = fun_typ; note_eff = T.Triv } @@ -215,7 +215,7 @@ let invoke_text_of_array : T.typ -> Ir.exp -> Ir.exp -> Ir.exp = fun t f e -> let fun_typ = T.Func (T.Local, T.Returns, [{T.var="T";T.bound=T.Any}], [show_fun_typ_for (T.Var ("T",0)); T.Array (T.Var ("T",0))], [T.Prim T.Text]) in text_exp (CallE - ( Value.local_cc 2 1 + ( Call_conv.local_cc 2 1 , { it = VarE ("@text_of_array" @@ no_region) ; at = no_region ; note = { note_typ = fun_typ; note_eff = T.Triv } @@ -232,7 +232,7 @@ let invoke_text_of_array_mut : T.typ -> Ir.exp -> Ir.exp -> Ir.exp = fun t f e - let fun_typ = T.Func (T.Local, T.Returns, [{T.var="T";T.bound=T.Any}], [show_fun_typ_for (T.Var ("T",0)); T.Array (T.Mut (T.Var ("T",0)))], [T.Prim T.Text]) in text_exp (CallE - ( Value.local_cc 2 1 + ( Call_conv.local_cc 2 1 , { it = VarE ("@text_of_array_mut" @@ no_region) ; at = no_region ; note = { note_typ = fun_typ; note_eff = T.Triv } diff --git a/src/ir_passes/tailcall.ml b/src/ir_passes/tailcall.ml index 2d524f4c572..9c0b097cbf4 100644 --- a/src/ir_passes/tailcall.ml +++ b/src/ir_passes/tailcall.ml @@ -1,6 +1,5 @@ open As_ir open As_types -open As_values open Source open Ir @@ -191,7 +190,7 @@ and dec' env d = (* A local let bound function, this is what we are looking for *) (* TODO: Do we need to detect more? A tuple of functions? *) | LetD (({it = VarP id;_} as id_pat), - ({it = FuncE (x, ({ Value.sort = Local; _} as cc), tbs, as_, typT, exp0);_} as funexp)) -> + ({it = FuncE (x, ({ Call_conv.sort = Local; _} as cc), tbs, as_, typT, exp0);_} as funexp)) -> let env = bind env id None in begin fun env1 -> let temps = fresh_vars "temp" (List.map (fun a -> Mut a.note) as_) in diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 774014f0a06..fceec643934 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -1,5 +1,6 @@ open As_ir open As_frontend +open As_types open As_values open Source @@ -73,16 +74,16 @@ and exp' at note = function I.ArrayE (m, T.as_immut t, exps es) | S.IdxE (e1, e2) -> I.IdxE (exp e1, exp e2) | S.FuncE (name, s, tbs, p, ty, e) -> - let cc = Value.call_conv_of_typ note.S.note_typ in + let cc = Call_conv.call_conv_of_typ note.S.note_typ in let args, wrap = to_args cc p in - let tys = if cc.Value.n_res = 1 then [ty.note] else T.as_seq ty.note in + let tys = if cc.Call_conv.n_res = 1 then [ty.note] else T.as_seq ty.note in I.FuncE (name, cc, typ_binds tbs, args, tys, wrap (exp e)) | S.CallE (e1, inst, e2) -> let t = e1.Source.note.S.note_typ in if T.is_non t then unreachableE.it else - let cc = Value.call_conv_of_typ t in + let cc = Call_conv.call_conv_of_typ t in let inst = List.map (fun t -> t.Source.note) inst in I.CallE (cc, exp e1, inst, exp e2) | S.BlockE [] -> I.TupE [] @@ -204,7 +205,7 @@ and dec' at n d = match d with I.TypD c | S.ClassD (id, tbs, s, p, self_id, es) -> let id' = {id with note = ()} in - let cc = Value.call_conv_of_typ n.S.note_typ in + let cc = Call_conv.call_conv_of_typ n.S.note_typ in let inst = List.map (fun tb -> match tb.note with @@ -276,7 +277,7 @@ and to_arg p : (Ir.arg * (Ir.exp -> Ir.exp)) = and to_args cc p : (Ir.arg list * (Ir.exp -> Ir.exp)) = - let n = cc.Value.n_args in + let n = cc.Call_conv.n_args in let tys = if n = 1 then [p.note] else T.as_seq p.note in let args, wrap = @@ -303,7 +304,7 @@ and to_args cc p : (Ir.arg list * (Ir.exp -> Ir.exp)) = in let wrap_under_async e = - if cc.Value.sort = T.Sharable && cc.Value.control = T.Promises + if cc.Call_conv.sort = T.Sharable && cc.Call_conv.control = T.Promises then match e.it with | Ir.AsyncE e' -> { e with it = Ir.AsyncE (wrap e') } | _ -> assert false From 8339d6fea37fed78aa321ce95bbba0ce5ed0841f Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 13 Jun 2019 13:39:17 +0200 Subject: [PATCH 0159/1176] Move scopes into their own module in `as_types/` (#494) this removes many dependencies on `as_frontend/typing.ml` from modules that should be indepdnent from the frontend, such as IR passes. --- src/as_frontend/typing.ml | 44 ++------------------------------- src/as_frontend/typing.mli | 19 +------------- src/as_ir/check_ir.ml | 4 +-- src/as_ir/check_ir.mli | 3 +-- src/as_types/scope.ml | 40 ++++++++++++++++++++++++++++++ src/as_types/scope.mli | 22 +++++++++++++++++ src/ir_passes/async.ml | 3 +-- src/ir_passes/async.mli | 3 +-- src/ir_passes/serialization.ml | 3 +-- src/ir_passes/serialization.mli | 3 +-- src/lowering/desugar.mli | 2 +- src/pipeline/pipeline.ml | 42 +++++++++++++++---------------- 12 files changed, 94 insertions(+), 94 deletions(-) create mode 100644 src/as_types/scope.ml create mode 100644 src/as_types/scope.mli diff --git a/src/as_frontend/typing.ml b/src/as_frontend/typing.ml index 191aa5bd4eb..e7f397d8ed6 100644 --- a/src/as_frontend/typing.ml +++ b/src/as_frontend/typing.ml @@ -3,6 +3,7 @@ open Source open As_types open As_values +open Scope module T = Type module A = Effect @@ -14,48 +15,7 @@ let recover_with (x : 'a) (f : 'b -> 'a) (y : 'b) = try f y with Recover -> x let recover_opt f y = recover_with None (fun y -> Some (f y)) y let recover f y = recover_with () f y - -(* Scopes *) - -type val_env = T.typ T.Env.t -type lib_env = T.typ T.Env.t -type typ_env = T.con T.Env.t -type con_env = T.ConSet.t - -type obj_env = scope T.Env.t (* internal object scopes *) - -and scope = - { val_env : val_env; - lib_env : lib_env; - typ_env : typ_env; - con_env : con_env; - obj_env : obj_env; - } - -let empty_scope : scope = - { val_env = T.Env.empty; - lib_env = T.Env.empty; - typ_env = T.Env.empty; - con_env = T.ConSet.empty; - obj_env = T.Env.empty; - } - -let adjoin_scope scope1 scope2 = - { val_env = T.Env.adjoin scope1.val_env scope2.val_env; - lib_env = T.Env.adjoin scope1.lib_env scope2.lib_env; - typ_env = T.Env.adjoin scope1.typ_env scope2.typ_env; - con_env = T.ConSet.union scope1.con_env scope2.con_env; - obj_env = T.Env.adjoin scope1.obj_env scope2.obj_env; - } - - -let adjoin_val_env scope ve = {scope with val_env = T.Env.adjoin scope.val_env ve} - -let library_scope f t = - { empty_scope with lib_env = T.Env.add f t empty_scope.lib_env } - - -(* Contexts (internal) *) +(* Contexts *) type lab_env = T.typ T.Env.t type ret_env = T.typ option diff --git a/src/as_frontend/typing.mli b/src/as_frontend/typing.mli index d98a0deb1c9..b600f0f6a43 100644 --- a/src/as_frontend/typing.mli +++ b/src/as_frontend/typing.mli @@ -1,22 +1,5 @@ open As_types.Type - -type val_env = typ Env.t -type lib_env = typ Env.t -type typ_env = con Env.t -type con_env = ConSet.t - -type obj_env = scope Env.t (* internal object scopes *) - -and scope = - { val_env : val_env; - lib_env : lib_env; - typ_env : typ_env; - con_env : con_env; - obj_env : obj_env; - } - -val empty_scope : scope -val adjoin_scope : scope -> scope -> scope +open As_types.Scope val infer_prog : scope -> Syntax.prog -> (typ * scope) Diag.result val check_library : scope -> Syntax.library -> scope Diag.result diff --git a/src/as_ir/check_ir.ml b/src/as_ir/check_ir.ml index 0de0c3ba676..0d10ca0c91e 100644 --- a/src/as_ir/check_ir.ml +++ b/src/as_ir/check_ir.ml @@ -57,8 +57,8 @@ type env = let env_of_scope scope flavor : env = { flavor; - vals = scope.Typing.val_env; - cons = scope.Typing.con_env; + vals = scope.Scope.val_env; + cons = scope.Scope.con_env; labs = T.Env.empty; rets = None; async = false; diff --git a/src/as_ir/check_ir.mli b/src/as_ir/check_ir.mli index c8a9a7506d4..da01840917f 100644 --- a/src/as_ir/check_ir.mli +++ b/src/as_ir/check_ir.mli @@ -1,2 +1 @@ -open As_frontend -val check_prog : bool -> Typing.scope -> string -> Ir.prog -> unit +val check_prog : bool -> As_types.Scope.scope -> string -> Ir.prog -> unit diff --git a/src/as_types/scope.ml b/src/as_types/scope.ml new file mode 100644 index 00000000000..2fcdfa4ad2d --- /dev/null +++ b/src/as_types/scope.ml @@ -0,0 +1,40 @@ +module T = Type + +(* Scopes *) + +type val_env = T.typ T.Env.t +type lib_env = T.typ T.Env.t +type typ_env = T.con T.Env.t +type con_env = T.ConSet.t + +type obj_env = scope T.Env.t (* internal object scopes *) + +and scope = + { val_env : val_env; + lib_env : lib_env; + typ_env : typ_env; + con_env : con_env; + obj_env : obj_env; + } + +let empty_scope : scope = + { val_env = T.Env.empty; + lib_env = T.Env.empty; + typ_env = T.Env.empty; + con_env = T.ConSet.empty; + obj_env = T.Env.empty; + } + +let adjoin_scope scope1 scope2 = + { val_env = T.Env.adjoin scope1.val_env scope2.val_env; + lib_env = T.Env.adjoin scope1.lib_env scope2.lib_env; + typ_env = T.Env.adjoin scope1.typ_env scope2.typ_env; + con_env = T.ConSet.union scope1.con_env scope2.con_env; + obj_env = T.Env.adjoin scope1.obj_env scope2.obj_env; + } + + +let adjoin_val_env scope ve = {scope with val_env = T.Env.adjoin scope.val_env ve} + +let library_scope f t = + { empty_scope with lib_env = T.Env.add f t empty_scope.lib_env } diff --git a/src/as_types/scope.mli b/src/as_types/scope.mli new file mode 100644 index 00000000000..11825897969 --- /dev/null +++ b/src/as_types/scope.mli @@ -0,0 +1,22 @@ +open Type + +type val_env = typ Env.t +type lib_env = typ Env.t +type typ_env = con Env.t +type con_env = ConSet.t + +type obj_env = scope Env.t (* internal object scopes *) + +and scope = + { val_env : val_env; + lib_env : lib_env; + typ_env : typ_env; + con_env : con_env; + obj_env : obj_env; + } + +val empty_scope : scope +val adjoin_scope : scope -> scope -> scope + +val adjoin_val_env : scope -> val_env -> scope +val library_scope : string -> typ -> scope diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index 5e2b05528a0..6c30055e455 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -1,6 +1,5 @@ open As_types open As_ir -open As_frontend module E = Env open Source module Ir = Ir @@ -414,5 +413,5 @@ let transform env prog = Eventually, pipeline will allow us to pass the con_renaming to downstream program fragments, then we would simply start with an empty con_renaming and the prelude. *) - Type.ConSet.iter (fun c -> T.con_renaming := T.ConRenaming.add c c (!T.con_renaming)) env.Typing.con_env; + Type.ConSet.iter (fun c -> T.con_renaming := T.ConRenaming.add c c (!T.con_renaming)) env.Scope.con_env; T.t_prog prog diff --git a/src/ir_passes/async.mli b/src/ir_passes/async.mli index 6d411227d28..af974b3217b 100644 --- a/src/ir_passes/async.mli +++ b/src/ir_passes/async.mli @@ -1,5 +1,4 @@ (* lower uses of async type appropriately *) -open As_frontend open As_ir -val transform : Typing.scope -> Ir.prog -> Ir.prog +val transform : As_types.Scope.scope -> Ir.prog -> Ir.prog diff --git a/src/ir_passes/serialization.ml b/src/ir_passes/serialization.ml index 684ea9db802..2daacd994ec 100644 --- a/src/ir_passes/serialization.ml +++ b/src/ir_passes/serialization.ml @@ -1,4 +1,3 @@ -open As_frontend open As_ir open As_types open Source @@ -276,5 +275,5 @@ let transform env prog = Eventually, pipeline will allow us to pass the con_renaming to downstream program fragments, then we would simply start with an empty con_renaming and the prelude. *) - Type.ConSet.iter (fun c -> T.con_renaming := T.ConRenaming.add c c (!T.con_renaming)) env.Typing.con_env; + Type.ConSet.iter (fun c -> T.con_renaming := T.ConRenaming.add c c (!T.con_renaming)) env.Scope.con_env; T.t_prog prog diff --git a/src/ir_passes/serialization.mli b/src/ir_passes/serialization.mli index 61dab1d0464..efab3b5b661 100644 --- a/src/ir_passes/serialization.mli +++ b/src/ir_passes/serialization.mli @@ -1,3 +1,2 @@ -open As_frontend open As_ir -val transform : Typing.scope -> Ir.prog -> Ir.prog +val transform : As_types.Scope.scope -> Ir.prog -> Ir.prog diff --git a/src/lowering/desugar.mli b/src/lowering/desugar.mli index b81ebdc6b39..6a5962c4fda 100644 --- a/src/lowering/desugar.mli +++ b/src/lowering/desugar.mli @@ -2,4 +2,4 @@ open As_frontend open As_ir val transform : Syntax.prog -> Ir.prog -val transform_graph : Typing.lib_env -> Syntax.libraries -> Syntax.prog list -> Ir.prog +val transform_graph : As_types.Scope.lib_env -> Syntax.libraries -> Syntax.prog list -> Ir.prog diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index f49b68ad64c..181e9927022 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -5,7 +5,7 @@ open As_ir open Interpreter open Printf -type stat_env = Typing.scope +type stat_env = Scope.scope type dyn_env = Interpret.scope type env = stat_env * dyn_env @@ -33,7 +33,7 @@ let print_stat_ve = let print_dyn_ve scope = Value.Env.iter (fun x d -> - let t = Type.Env.find x scope.Typing.val_env in + let t = Type.Env.find x scope.Scope.val_env in let t' = Type.as_immut t in printf "%s %s : %s = %s\n" (if t == t' then "let" else "var") x @@ -41,7 +41,7 @@ let print_dyn_ve scope = ) let print_scope senv scope dve = - print_ce scope.Typing.con_env; + print_ce scope.Scope.con_env; print_dyn_ve senv dve let print_val _senv v t = @@ -116,29 +116,29 @@ let resolve_progs = (* Typechecking *) let infer_prog senv prog - : (Type.typ * Typing.scope) Diag.result = + : (Type.typ * Scope.scope) Diag.result = phase "Checking" prog.Source.note; let r = Typing.infer_prog senv prog in if !Flags.trace && !Flags.verbose then begin match r with | Ok ((_, scope), _) -> - print_ce scope.Typing.con_env; - print_stat_ve scope.Typing.val_env; + print_ce scope.Scope.con_env; + print_stat_ve scope.Scope.val_env; dump_prog Flags.dump_tc prog; | Error _ -> () end; r -let rec typecheck_progs senv progs : Typing.scope Diag.result = +let rec typecheck_progs senv progs : Scope.scope Diag.result = match progs with | [] -> Diag.return senv | p::ps -> Diag.bind (infer_prog senv p) (fun (_t, sscope) -> - let senv' = Typing.adjoin_scope senv sscope in + let senv' = Scope.adjoin_scope senv sscope in typecheck_progs senv' ps ) -let typecheck_library senv filename prog : Typing.scope Diag.result = +let typecheck_library senv filename prog : Scope.scope Diag.result = phase "Checking" prog.Source.note; Typing.check_library senv (filename, prog) @@ -163,12 +163,12 @@ and the newly added scopes, so these are returned separately. *) type load_result = - (Syntax.libraries * Syntax.prog list * Typing.scope) Diag.result + (Syntax.libraries * Syntax.prog list * Scope.scope) Diag.result type load_decl_result = - (Syntax.libraries * Syntax.prog * Typing.scope * Type.typ * Typing.scope) Diag.result + (Syntax.libraries * Syntax.prog * Scope.scope * Type.typ * Scope.scope) Diag.result -let chase_imports senv0 imports : (Syntax.libraries * Typing.scope) Diag.result = +let chase_imports senv0 imports : (Syntax.libraries * Scope.scope) Diag.result = (* This function loads and type-checkes the files given in `imports`, including any further dependencies. @@ -188,7 +188,7 @@ let chase_imports senv0 imports : (Syntax.libraries * Typing.scope) Diag.result let libraries = ref [] in let rec go f = - if Type.Env.mem f !senv.Typing.lib_env then + if Type.Env.mem f !senv.Scope.lib_env then Diag.return () else if mem f !pending then Error [{ @@ -204,7 +204,7 @@ let chase_imports senv0 imports : (Syntax.libraries * Typing.scope) Diag.result Diag.bind (typecheck_library !senv f prog) (fun sscope -> Diag.bind (defindeness_prog prog) (fun () -> libraries := (f, prog) :: !libraries; (* NB: Conceptually an append *) - senv := Typing.adjoin_scope !senv sscope; + senv := Scope.adjoin_scope !senv sscope; pending := remove f !pending; Diag.return () )))))) @@ -231,7 +231,7 @@ let load_decl parse_one senv : load_decl_result = Diag.bind (resolve_prog parsed) (fun (prog, libraries) -> Diag.bind (chase_imports senv libraries) (fun (libraries, senv') -> Diag.bind (infer_prog senv' prog) (fun (t, sscope) -> - let senv'' = Typing.adjoin_scope senv' sscope in + let senv'' = Scope.adjoin_scope senv' sscope in Diag.return (libraries, prog, senv'', t, sscope) )))) @@ -265,7 +265,7 @@ let rec interpret_progs denv progs : Interpret.scope option = interpret_progs denv' ps | None -> None -let interpret_files (senv0, denv0) files : (Typing.scope * Interpret.scope) option = +let interpret_files (senv0, denv0) files : (Scope.scope * Interpret.scope) option = Lib.Option.bind (Diag.flush_messages (load_progs (parse_files files) senv0)) (fun (libraries, progs, senv1) -> @@ -291,11 +291,11 @@ let typecheck_prelude () : Syntax.prog * stat_env = match parse_with Lexer.Privileged lexer parse prelude_name with | Error e -> prelude_error "parsing" [e] | Ok prog -> - let senv0 = Typing.empty_scope in + let senv0 = Scope.empty_scope in match infer_prog senv0 prog with | Error es -> prelude_error "checking" es | Ok ((_t, sscope), msgs) -> - let senv1 = Typing.adjoin_scope senv0 sscope in + let senv1 = Scope.adjoin_scope senv0 sscope in prog, senv1 let prelude, initial_stat_env = typecheck_prelude () @@ -486,12 +486,12 @@ let compile_prog mode do_link lib_env libraries progs : Wasm_exts.CustomModule.e let compile_files mode do_link files : compile_result = Diag.bind (load_progs (parse_files files) initial_stat_env) (fun (libraries, progs, senv) -> - Diag.return (compile_prog mode do_link senv.Typing.lib_env libraries progs)) + Diag.return (compile_prog mode do_link senv.Scope.lib_env libraries progs)) let compile_string mode s name : compile_result = Diag.bind (load_decl (parse_string s name) initial_stat_env) (fun (libraries, prog, senv, _t, _sscope) -> - Diag.return (compile_prog mode false senv.Typing.lib_env libraries [prog])) + Diag.return (compile_prog mode false senv.Scope.lib_env libraries [prog])) (* Interpretation (IR) *) @@ -510,5 +510,5 @@ let interpret_ir_prog inp_env libraries progs = let interpret_ir_files files = Lib.Option.map - (fun (libraries, progs, senv) -> interpret_ir_prog senv.Typing.lib_env libraries progs) + (fun (libraries, progs, senv) -> interpret_ir_prog senv.Scope.lib_env libraries progs) (Diag.flush_messages (load_progs (parse_files files) initial_stat_env)) From 362e4a01e26e13ec778cd8c28de689f954810751 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 13 Jun 2019 14:49:52 +0200 Subject: [PATCH 0160/1176] Do not group numbers in `debug_show` (#489) * Do not prettify output of debug_show extracted from #458 * Use to_string / to_pretty_string * Add IDL Hash unit tests * Use `to_pretty_string` also for Word sizes --- src/as_frontend/arrange.ml | 14 +++++++------- src/as_frontend/syntax.ml | 12 ++++++------ src/as_values/value.ml | 23 ++++++++++++++--------- src/as_values/value.mli | 3 +++ test/run-dfinity/ok/show.dvm-run.ok | 6 ++++++ test/run-dfinity/ok/show.run-ir.ok | 6 ++++++ test/run-dfinity/ok/show.run-low.ok | 6 ++++++ test/run-dfinity/ok/show.run.ok | 6 ++++++ test/run-dfinity/show.as | 6 ++++++ test/run/idlHash.as | 15 +++++++++++++++ test/run/ok/idlHash.run-ir.ok | 15 +++++++++++++++ test/run/ok/idlHash.run-low.ok | 15 +++++++++++++++ test/run/ok/idlHash.run.ok | 15 +++++++++++++++ test/run/ok/idlHash.wasm-run.ok | 1 + 14 files changed, 121 insertions(+), 22 deletions(-) create mode 100644 test/run/idlHash.as create mode 100644 test/run/ok/idlHash.run-ir.ok create mode 100644 test/run/ok/idlHash.run-low.ok create mode 100644 test/run/ok/idlHash.run.ok create mode 100644 test/run/ok/idlHash.wasm-run.ok diff --git a/src/as_frontend/arrange.ml b/src/as_frontend/arrange.ml index ffe3818ad0d..bafa423cb5c 100644 --- a/src/as_frontend/arrange.ml +++ b/src/as_frontend/arrange.ml @@ -75,13 +75,13 @@ and lit (l:lit) = match l with | NullLit -> Atom "NullLit" | BoolLit true -> "BoolLit" $$ [ Atom "true" ] | BoolLit false -> "BoolLit" $$ [ Atom "false" ] - | NatLit n -> "NatLit" $$ [ Atom (Value.Nat.to_string n) ] - | IntLit i -> "IntLit" $$ [ Atom (Value.Int.to_string i) ] - | Word8Lit w -> "Word8Lit" $$ [ Atom (Value.Word8.to_string_u w) ] - | Word16Lit w -> "Word16Lit" $$ [ Atom (Value.Word16.to_string_u w) ] - | Word32Lit w -> "Word32Lit" $$ [ Atom (Value.Word32.to_string_u w) ] - | Word64Lit w -> "Word64Lit" $$ [ Atom (Value.Word64.to_string_u w) ] - | FloatLit f -> "FloatLit" $$ [ Atom (Value.Float.to_string f) ] + | NatLit n -> "NatLit" $$ [ Atom (Value.Nat.to_pretty_string n) ] + | IntLit i -> "IntLit" $$ [ Atom (Value.Int.to_pretty_string i) ] + | Word8Lit w -> "Word8Lit" $$ [ Atom (Value.Word8.to_pretty_string w) ] + | Word16Lit w -> "Word16Lit" $$ [ Atom (Value.Word16.to_pretty_string w) ] + | Word32Lit w -> "Word32Lit" $$ [ Atom (Value.Word32.to_pretty_string w) ] + | Word64Lit w -> "Word64Lit" $$ [ Atom (Value.Word64.to_pretty_string w) ] + | FloatLit f -> "FloatLit" $$ [ Atom (Value.Float.to_pretty_string f) ] | CharLit c -> "CharLit" $$ [ Atom (string_of_int c) ] | TextLit t -> "TextLit" $$ [ Atom t ] | PreLit (s,p) -> "PreLit" $$ [ Atom s; Arrange_type.prim p ] diff --git a/src/as_frontend/syntax.ml b/src/as_frontend/syntax.ml index 4ee0ae7efd3..b87fdf77d6f 100644 --- a/src/as_frontend/syntax.ml +++ b/src/as_frontend/syntax.ml @@ -195,14 +195,14 @@ let string_of_lit = function | BoolLit false -> "false" | BoolLit true -> "true" | IntLit n - | NatLit n -> Value.Int.to_string n - | Word8Lit n -> Value.Word8.to_string n - | Word16Lit n -> Value.Word16.to_string n - | Word32Lit n -> Value.Word32.to_string n - | Word64Lit n -> Value.Word64.to_string n + | NatLit n -> Value.Int.to_pretty_string n + | Word8Lit n -> Value.Word8.to_pretty_string n + | Word16Lit n -> Value.Word16.to_pretty_string n + | Word32Lit n -> Value.Word32.to_pretty_string n + | Word64Lit n -> Value.Word64.to_pretty_string n | CharLit c -> string_of_int c | NullLit -> "null" | TextLit t -> t - | FloatLit f -> Value.Float.to_string f + | FloatLit f -> Value.Float.to_pretty_string f | PreLit _ -> assert false diff --git a/src/as_values/value.ml b/src/as_values/value.ml index 2fb46c563ee..53e284db16b 100644 --- a/src/as_values/value.ml +++ b/src/as_values/value.ml @@ -75,6 +75,7 @@ sig val not : t -> t val pow : t -> t -> t val to_string : t -> string + val to_pretty_string : t -> string end module MakeWord(WasmInt : Wasm.Int.S) = @@ -90,7 +91,8 @@ struct pow (mul x x) (shr_u y one) else mul x (pow x (sub y one)) - let to_string w = group_num (WasmInt.to_string_u w) + let to_string w = WasmInt.to_string_u w + let to_pretty_string w = group_num (WasmInt.to_string_u w) end module Int32Rep = struct include Int32 let bitwidth = 32 end @@ -106,13 +108,14 @@ module type FloatType = sig include Wasm.Float.S val pow : t -> t -> t + val to_pretty_string : t -> string end module MakeFloat(WasmFloat : Wasm.Float.S) = struct include WasmFloat let pow x y = of_float (to_float x ** to_float y) - let to_string w = group_num (WasmFloat.to_string w) + let to_pretty_string w = group_num (WasmFloat.to_string w) end module Float = MakeFloat(Wasm.F64) @@ -141,6 +144,7 @@ sig val of_int : int -> t val of_string : string -> t val to_string : t -> string + val to_pretty_string : t -> string end module Int : NumType with type t = Big_int.big_int = @@ -168,7 +172,8 @@ struct let compare = compare_big_int let to_int = int_of_big_int let of_int = big_int_of_int - let to_string i = group_num (string_of_big_int i) + let to_string i = string_of_big_int i + let to_pretty_string i = group_num (string_of_big_int i) let of_string s = big_int_of_string (String.concat "" (String.split_on_char '_' s)) @@ -357,12 +362,12 @@ let string_of_string lsep s rsep = let rec string_of_val_nullary d = function | Null -> "null" | Bool b -> if b then "true" else "false" - | Int i -> Int.to_string i - | Word8 w -> Word8.to_string w - | Word16 w -> Word16.to_string w - | Word32 w -> Word32.to_string w - | Word64 w -> Word64.to_string w - | Float f -> Float.to_string f + | Int i -> Int.to_pretty_string i + | Word8 w -> Word8.to_pretty_string w + | Word16 w -> Word16.to_pretty_string w + | Word32 w -> Word32.to_pretty_string w + | Word64 w -> Word64.to_pretty_string w + | Float f -> Float.to_pretty_string f | Char c -> string_of_string '\'' [c] '\'' | Text t -> string_of_string '\"' (Wasm.Utf8.decode t) '\"' | Tup vs -> diff --git a/src/as_values/value.mli b/src/as_values/value.mli index 2ad651c9084..b9fa22c7162 100644 --- a/src/as_values/value.mli +++ b/src/as_values/value.mli @@ -9,6 +9,7 @@ sig val not : t -> t val pow : t -> t -> t val to_string : t -> string + val to_pretty_string : t -> string end module type NumType = @@ -34,12 +35,14 @@ sig val of_int : int -> t val of_string : string -> t val to_string : t -> string + val to_pretty_string : t -> string end module type FloatType = sig include Wasm.Float.S val pow : t -> t -> t + val to_pretty_string : t -> string end module Word8 : WordType with type bits = int32 diff --git a/test/run-dfinity/ok/show.dvm-run.ok b/test/run-dfinity/ok/show.dvm-run.ok index e61431fbc4c..d48b386b82f 100644 --- a/test/run-dfinity/ok/show.dvm-run.ok +++ b/test/run-dfinity/ok/show.dvm-run.ok @@ -1,9 +1,15 @@ true false +-42000000000000 +-42000000 +-42000 -42 0 0 42 +42000 +42000000 +420000000000000 (42, -42, ()) ("Foobar", null, null, ?(23)) [1, 2, 3] diff --git a/test/run-dfinity/ok/show.run-ir.ok b/test/run-dfinity/ok/show.run-ir.ok index e61431fbc4c..d48b386b82f 100644 --- a/test/run-dfinity/ok/show.run-ir.ok +++ b/test/run-dfinity/ok/show.run-ir.ok @@ -1,9 +1,15 @@ true false +-42000000000000 +-42000000 +-42000 -42 0 0 42 +42000 +42000000 +420000000000000 (42, -42, ()) ("Foobar", null, null, ?(23)) [1, 2, 3] diff --git a/test/run-dfinity/ok/show.run-low.ok b/test/run-dfinity/ok/show.run-low.ok index e61431fbc4c..d48b386b82f 100644 --- a/test/run-dfinity/ok/show.run-low.ok +++ b/test/run-dfinity/ok/show.run-low.ok @@ -1,9 +1,15 @@ true false +-42000000000000 +-42000000 +-42000 -42 0 0 42 +42000 +42000000 +420000000000000 (42, -42, ()) ("Foobar", null, null, ?(23)) [1, 2, 3] diff --git a/test/run-dfinity/ok/show.run.ok b/test/run-dfinity/ok/show.run.ok index e61431fbc4c..d48b386b82f 100644 --- a/test/run-dfinity/ok/show.run.ok +++ b/test/run-dfinity/ok/show.run.ok @@ -1,9 +1,15 @@ true false +-42000000000000 +-42000000 +-42000 -42 0 0 42 +42000 +42000000 +420000000000000 (42, -42, ()) ("Foobar", null, null, ?(23)) [1, 2, 3] diff --git a/test/run-dfinity/show.as b/test/run-dfinity/show.as index c58fcfac382..779b9aa0d5e 100644 --- a/test/run-dfinity/show.as +++ b/test/run-dfinity/show.as @@ -1,10 +1,16 @@ func printLn(x : Text) { print(x # "\n"); }; printLn(debug_show (true)); printLn(debug_show (false)); +printLn(debug_show (-42000000000000)); +printLn(debug_show (-42000000)); +printLn(debug_show (-42000)); printLn(debug_show (-42)); printLn(debug_show (-0)); printLn(debug_show (0)); printLn(debug_show (42)); +printLn(debug_show (42000)); +printLn(debug_show (42000000)); +printLn(debug_show (420000000000000)); printLn(debug_show (42,-42,())); printLn(debug_show ("Foobar", null, null, ?23)); printLn(debug_show ([1,2,3])); diff --git a/test/run/idlHash.as b/test/run/idlHash.as new file mode 100644 index 00000000000..a118bac6e08 --- /dev/null +++ b/test/run/idlHash.as @@ -0,0 +1,15 @@ +func testHash(s : Text, h : Word32) { + print("Hash for " # s # ":\n"); + print("Expected: " # debug_show (word32ToNat(h)) # "\n"); + print("Actual: " # debug_show (word32ToNat(idlHash s)) # "\n"); +}; + +// The lines below can be copied verbatim out of the corresponding JS unit test +// in dev/experimental/js-dfinity-client/tests/unit-tests/idl.js + +testHash("", 0); +testHash("id", 23515); +testHash("description", 1595738364); +testHash("short_name", 3261810734); +testHash("Hi ☃", 1419229646); + diff --git a/test/run/ok/idlHash.run-ir.ok b/test/run/ok/idlHash.run-ir.ok new file mode 100644 index 00000000000..eb89fe0b5af --- /dev/null +++ b/test/run/ok/idlHash.run-ir.ok @@ -0,0 +1,15 @@ +Hash for : +Expected: 0 +Actual: 0 +Hash for id: +Expected: 23515 +Actual: 23515 +Hash for description: +Expected: 1595738364 +Actual: 1595738364 +Hash for short_name: +Expected: 3261810734 +Actual: 3261810734 +Hash for Hi ☃: +Expected: 1419229646 +Actual: 1419229646 diff --git a/test/run/ok/idlHash.run-low.ok b/test/run/ok/idlHash.run-low.ok new file mode 100644 index 00000000000..eb89fe0b5af --- /dev/null +++ b/test/run/ok/idlHash.run-low.ok @@ -0,0 +1,15 @@ +Hash for : +Expected: 0 +Actual: 0 +Hash for id: +Expected: 23515 +Actual: 23515 +Hash for description: +Expected: 1595738364 +Actual: 1595738364 +Hash for short_name: +Expected: 3261810734 +Actual: 3261810734 +Hash for Hi ☃: +Expected: 1419229646 +Actual: 1419229646 diff --git a/test/run/ok/idlHash.run.ok b/test/run/ok/idlHash.run.ok new file mode 100644 index 00000000000..eb89fe0b5af --- /dev/null +++ b/test/run/ok/idlHash.run.ok @@ -0,0 +1,15 @@ +Hash for : +Expected: 0 +Actual: 0 +Hash for id: +Expected: 23515 +Actual: 23515 +Hash for description: +Expected: 1595738364 +Actual: 1595738364 +Hash for short_name: +Expected: 3261810734 +Actual: 3261810734 +Hash for Hi ☃: +Expected: 1419229646 +Actual: 1419229646 diff --git a/test/run/ok/idlHash.wasm-run.ok b/test/run/ok/idlHash.wasm-run.ok new file mode 100644 index 00000000000..4ba414f67c5 --- /dev/null +++ b/test/run/ok/idlHash.wasm-run.ok @@ -0,0 +1 @@ +_out/idlHash.wasm:0x___: runtime trap: unreachable executed From e723578c8305b07a005ff3e2823e76f0d0bb12c7 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 13 Jun 2019 14:55:27 +0200 Subject: [PATCH 0161/1176] Use the Scope module qualified and drop _scope (#495) as suggested by Andreas in https://github.com/dfinity-lab/actorscript/pull/494#pullrequestreview-249289316 --- src/as_frontend/typing.ml | 134 +++++++++++++++++++------------------- src/as_types/scope.ml | 9 +-- src/as_types/scope.mli | 7 +- src/pipeline/pipeline.ml | 12 ++-- 4 files changed, 83 insertions(+), 79 deletions(-) diff --git a/src/as_frontend/typing.ml b/src/as_frontend/typing.ml index e7f397d8ed6..14a7066dafc 100644 --- a/src/as_frontend/typing.ml +++ b/src/as_frontend/typing.ml @@ -3,7 +3,6 @@ open Source open As_types open As_values -open Scope module T = Type module A = Effect @@ -21,11 +20,11 @@ type lab_env = T.typ T.Env.t type ret_env = T.typ option type env = - { vals : val_env; - libs : lib_env; - typs : typ_env; - cons : con_env; - objs : obj_env; + { vals : Scope.val_env; + libs : Scope.lib_env; + typs : Scope.typ_env; + cons : Scope.con_env; + objs : Scope.obj_env; labs : lab_env; rets : ret_env; async : bool; @@ -34,10 +33,10 @@ type env = } let env_of_scope msgs scope = - { vals = scope.val_env; - libs = scope.lib_env; - typs = scope.typ_env; - cons = scope.con_env; + { vals = scope.Scope.val_env; + libs = scope.Scope.lib_env; + typs = scope.Scope.typ_env; + cons = scope.Scope.con_env; objs = T.Env.empty; labs = T.Env.empty; rets = None; @@ -77,11 +76,11 @@ let add_typs env xs cs = let adjoin env scope = { env with - vals = T.Env.adjoin env.vals scope.val_env; - libs = T.Env.adjoin env.libs scope.lib_env; - typs = T.Env.adjoin env.typs scope.typ_env; - cons = T.ConSet.union env.cons scope.con_env; - objs = T.Env.adjoin env.objs scope.obj_env; + vals = T.Env.adjoin env.vals scope.Scope.val_env; + libs = T.Env.adjoin env.libs scope.Scope.lib_env; + typs = T.Env.adjoin env.typs scope.Scope.typ_env; + cons = T.ConSet.union env.cons scope.Scope.con_env; + objs = T.Env.adjoin env.objs scope.Scope.obj_env; } let adjoin_vals env ve = {env with vals = T.Env.adjoin env.vals ve} @@ -256,7 +255,7 @@ and check_typ_tag env typ_tag = let t = check_typ env typ in T.{lab = tag.it; typ = t} -and check_typ_binds env typ_binds : T.con list * T.typ list * typ_env * con_env = +and check_typ_binds env typ_binds : T.con list * T.typ list * Scope.typ_env * Scope.con_env = let xs = List.map (fun typ_bind -> typ_bind.it.var.it) typ_binds in let cs = List.map (fun n -> Con.fresh n (T.Abs ([], T.Pre))) xs in let te = List.fold_left2 (fun te typ_bind c -> @@ -603,7 +602,7 @@ and infer_exp'' env exp : T.typ = t_ret | BlockE decs -> let t, scope = infer_block env decs exp.at in - (try T.avoid scope.con_env t with T.Unavoidable c -> + (try T.avoid scope.Scope.con_env t with T.Unavoidable c -> error env exp.at "local class type %s is contained in inferred block type\n %s" (Con.to_string c) @@ -834,21 +833,21 @@ and check_case env t_pat t {it = {pat; exp}; _} = (* Patterns *) -and infer_pat_exhaustive env pat : T.typ * val_env = +and infer_pat_exhaustive env pat : T.typ * Scope.val_env = let t, ve = infer_pat env pat in if not env.pre then if not (Coverage.check_pat pat t) then warn env pat.at "this pattern does not cover all possible values"; t, ve -and infer_pat env pat : T.typ * val_env = +and infer_pat env pat : T.typ * Scope.val_env = assert (pat.note = T.Pre); let t, ve = infer_pat' env pat in if not env.pre then pat.note <- T.normalize t; t, ve -and infer_pat' env pat : T.typ * val_env = +and infer_pat' env pat : T.typ * Scope.val_env = match pat.it with | WildP -> error env pat.at "cannot infer type of wildcard" @@ -889,7 +888,7 @@ and infer_pat' env pat : T.typ * val_env = | ParP pat1 -> infer_pat env pat1 -and infer_pats at env pats ts ve : T.typ list * val_env = +and infer_pats at env pats ts ve : T.typ list * Scope.val_env = match pats with | [] -> List.rev ts, ve | pat::pats' -> @@ -897,7 +896,7 @@ and infer_pats at env pats ts ve : T.typ list * val_env = let ve' = disjoint_union env at "duplicate binding for %s in pattern" ve ve1 in infer_pats at env pats' (t::ts) ve' -and infer_pat_fields at env pfs ts ve : (T.obj_sort * T.field list) * val_env = +and infer_pat_fields at env pfs ts ve : (T.obj_sort * T.field list) * Scope.val_env = match pfs with | [] -> (T.(Object Local), List.rev ts), ve | pf::pfs' -> @@ -905,14 +904,14 @@ and infer_pat_fields at env pfs ts ve : (T.obj_sort * T.field list) * val_env = let ve' = disjoint_union env at "duplicate binding for %s in pattern" ve ve1 in infer_pat_fields at env pfs' (T.{ lab = pf.it.id.it; typ }::ts) ve' -and check_pat_exhaustive env t pat : val_env = +and check_pat_exhaustive env t pat : Scope.val_env = let ve = check_pat env t pat in if not env.pre then if not (Coverage.check_pat pat t) then warn env pat.at "this pattern does not cover all possible values"; ve -and check_pat env t pat : val_env = +and check_pat env t pat : Scope.val_env = assert (pat.note = T.Pre); if t = T.Pre then snd (infer_pat env pat) else let t' = T.normalize t in @@ -920,7 +919,7 @@ and check_pat env t pat : val_env = if not env.pre then pat.note <- t'; ve -and check_pat' env t pat : val_env = +and check_pat' env t pat : Scope.val_env = assert (t <> T.Pre); match pat.it with | WildP -> @@ -988,7 +987,7 @@ and check_pat' env t pat : val_env = (T.string_of_typ_expand t); ve -and check_pats env ts pats ve at : val_env = +and check_pats env ts pats ve at : Scope.val_env = match pats, ts with | [], [] -> ve | pat::pats', t::ts' -> @@ -1002,7 +1001,7 @@ and check_pats env ts pats ve at : val_env = error env at "tuple pattern has %i more components than expected type" (List.length ts) -and check_pat_fields env tfs pfs ve at : val_env = +and check_pat_fields env tfs pfs ve at : Scope.val_env = let repeated l = function | [] -> None | (pf : pat_field)::_ -> if l = pf.it.id.it then Some pf.at else None @@ -1092,18 +1091,18 @@ and object_of_scope env sort fields scope at = (fun id con flds -> if T.Env.mem id pub_typ then { T.lab = id; T.typ = T.Typ con }::flds - else flds) scope.typ_env [] + else flds) scope.Scope.typ_env [] in let fields = T.Env.fold (fun id typ flds -> if T.Env.mem id pub_val then { T.lab = id; T.typ = typ }::flds - else flds) scope.val_env typ_fields + else flds) scope.Scope.val_env typ_fields in let t = T.Obj (sort, List.sort T.compare_field fields) in let accessible_cons = gather_typ T.ConSet.empty t in - let inaccessible_cons = T.ConSet.diff scope.con_env accessible_cons in + let inaccessible_cons = T.ConSet.diff scope.Scope.con_env accessible_cons in try T.avoid_cons inaccessible_cons accessible_cons; T.avoid inaccessible_cons t @@ -1146,12 +1145,12 @@ and infer_obj env s fields at : T.typ = (* Blocks and Declarations *) -and infer_block env decs at : T.typ * scope = +and infer_block env decs at : T.typ * Scope.scope = let scope = infer_block_decs env decs in let t = infer_block_exps (adjoin env scope) decs in t, scope -and infer_block_decs env decs : scope = +and infer_block_decs env decs : Scope.t = let scope = gather_block_decs env decs in let env' = adjoin {env with pre = true} scope in let scope_ce = infer_block_typdecs env' decs in @@ -1203,7 +1202,7 @@ and infer_dec env dec : T.typ = t -and check_block env t decs at : scope = +and check_block env t decs at : Scope.t = let scope = infer_block_decs env decs in check_block_exps (adjoin env scope) t decs at; scope @@ -1278,10 +1277,10 @@ and infer_val_path env exp : T.typ option = * object identifiers and their fields (if known) (recursively) * other value identifiers at type T.Pre *) -and gather_block_decs env decs : scope = - List.fold_left (gather_dec env) empty_scope decs +and gather_block_decs env decs : Scope.t = + List.fold_left (gather_dec env) Scope.empty decs -and gather_dec env scope dec : scope = +and gather_dec env scope dec : Scope.t = match dec.it with | ExpD _ -> scope (* TODO: generalize beyond let = *) @@ -1290,6 +1289,7 @@ and gather_dec env scope dec : scope = {it = ObjE ({it = sort; _}, fields); at; _} ) -> let decs = List.map (fun ef -> ef.it.dec) fields in + let open Scope in if T.Env.mem id.it scope.val_env then error env dec.at "duplicate definition for value %s in block" id.it; let scope' = gather_block_decs env decs in @@ -1300,9 +1300,10 @@ and gather_dec env scope dec : scope = lib_env = scope.lib_env; con_env = scope.con_env; obj_env = obj_env } - | LetD (pat, _) -> adjoin_val_env scope (gather_pat env scope.val_env pat) - | VarD (id, _) -> adjoin_val_env scope (gather_id env scope.val_env id) + | LetD (pat, _) -> Scope.adjoin_val_env scope (gather_pat env scope.Scope.val_env pat) + | VarD (id, _) -> Scope.adjoin_val_env scope (gather_id env scope.Scope.val_env id) | TypD (id, binds, _) | ClassD (id, binds, _, _, _, _) -> + let open Scope in if T.Env.mem id.it scope.typ_env then error env dec.at "duplicate definition for type %s in block" id.it; let pre_tbs = List.map (fun bind -> {T.var = bind.it.var.it; bound = T.Pre}) binds in @@ -1322,7 +1323,7 @@ and gather_dec env scope dec : scope = obj_env = scope.obj_env; } -and gather_pat env ve pat : val_env = +and gather_pat env ve pat : Scope.val_env = match pat.it with | WildP | LitP _ | SignP _ -> ve | VarP id -> gather_id env ve id @@ -1331,24 +1332,24 @@ and gather_pat env ve pat : val_env = | TagP (_, pat1) | AltP (pat1, _) | OptP pat1 | AnnotP (pat1, _) | ParP pat1 -> gather_pat env ve pat1 -and gather_pat_field env ve pf : val_env = +and gather_pat_field env ve pf : Scope.val_env = gather_pat env ve pf.it.pat -and gather_id env ve id : val_env = +and gather_id env ve id : Scope.val_env = if T.Env.find_opt id.it ve <> None then error env id.at "duplicate definition for %s in block" id.it; T.Env.add id.it T.Pre ve (* Pass 2 and 3: infer type definitions *) -and infer_block_typdecs env decs : scope = +and infer_block_typdecs env decs : Scope.t = let _env', scope = List.fold_left (fun (env, scope) dec -> let scope' = infer_dec_typdecs env dec in - adjoin env scope', adjoin_scope scope scope' - ) (env, empty_scope) decs + adjoin env scope', Scope.adjoin scope scope' + ) (env, Scope.empty) decs in scope -and infer_dec_typdecs env dec : scope = +and infer_dec_typdecs env dec : Scope.t = match dec.it with (* TODO: generalize beyond let = *) | LetD ( @@ -1359,7 +1360,7 @@ and infer_dec_typdecs env dec : scope = let scope = T.Env.find id.it env.objs in let env' = adjoin env scope in let obj_scope = infer_block_typdecs env' decs in - { empty_scope with + Scope.{ empty with con_env = obj_scope.con_env; val_env = T.Env.singleton id.it (object_of_scope env sort fields obj_scope at); obj_env = T.Env.singleton id.it obj_scope @@ -1367,14 +1368,15 @@ and infer_dec_typdecs env dec : scope = (* TODO: generalize beyond let = *) | LetD ({it = VarP id; _}, exp) -> (match infer_val_path env exp with - | None -> empty_scope + | None -> Scope.empty | Some t -> + let open Scope in match T.promote t with - | T.Obj (_, _) as t' -> { empty_scope with val_env = T.Env.singleton id.it t' } - | _ -> { empty_scope with val_env = T.Env.singleton id.it T.Pre } + | T.Obj (_, _) as t' -> { Scope.empty with val_env = T.Env.singleton id.it t' } + | _ -> { Scope.empty with val_env = T.Env.singleton id.it T.Pre } ) | LetD _ | ExpD _ | VarD _ -> - empty_scope + Scope.empty | TypD (con_id, binds, typ) -> let c = T.Env.find con_id.it env.typs in let cs, ts, te, ce = check_typ_binds {env with pre = true} binds in @@ -1398,7 +1400,7 @@ and infer_dec_typdecs env dec : scope = (T.string_of_kind k) (String.concat ", " (T.ConSet.fold (fun c cs -> T.string_of_con c::cs) free_params [])) end; - { empty_scope with + Scope.{ empty with typ_env = T.Env.singleton con_id.it c; con_env = infer_id_typdecs con_id c k; } @@ -1412,12 +1414,12 @@ and infer_dec_typdecs env dec : scope = let t = infer_obj env'' sort.it fields dec.at in let tbs = List.map2 (fun c t -> {T.var = Con.name c; bound = T.close cs t}) cs ts in let k = T.Def (tbs, T.close cs t) in - { empty_scope with + Scope.{ empty with typ_env = T.Env.singleton id.it c; con_env = infer_id_typdecs id c k; } -and infer_id_typdecs id c k : con_env = +and infer_id_typdecs id c k : Scope.con_env = assert (match k with T.Abs (_, T.Pre) -> false | _ -> true); (match Con.kind c with | T.Abs (_, T.Pre) -> T.set_kind c k; id.note <- Some c @@ -1426,18 +1428,18 @@ and infer_id_typdecs id c k : con_env = T.ConSet.singleton c (* Pass 4: infer value types *) -and infer_block_valdecs env decs scope : scope = +and infer_block_valdecs env decs scope : Scope.t = let _, scope' = List.fold_left (fun (env, scope) dec -> let scope' = infer_dec_valdecs env dec in - adjoin env scope', adjoin_scope scope scope' + adjoin env scope', Scope.adjoin scope scope' ) (env, scope) decs in scope' -and infer_dec_valdecs env dec : scope = +and infer_dec_valdecs env dec : Scope.t = match dec.it with | ExpD _ -> - empty_scope + Scope.empty (* TODO: generalize beyond let = *) | LetD ( {it = VarP id; _} as pat, @@ -1448,23 +1450,23 @@ and infer_dec_valdecs env dec : scope = let obj_scope' = infer_block_valdecs (adjoin {env with pre = true} obj_scope) - decs empty_scope + decs Scope.empty in let obj_typ = object_of_scope env sort fields obj_scope' at in let _ve = check_pat env obj_typ pat in - { empty_scope with + Scope.{ Scope.empty with val_env = T.Env.singleton id.it obj_typ } | LetD (pat, exp) -> let t = infer_exp {env with pre = true} exp in let ve' = check_pat_exhaustive env t pat in - { empty_scope with val_env = ve' } + Scope.{ Scope.empty with val_env = ve' } | VarD (id, exp) -> let t = infer_exp {env with pre = true} exp in - { empty_scope with val_env = T.Env.singleton id.it (T.Mut t) } + Scope.{ Scope.empty with val_env = T.Env.singleton id.it (T.Mut t) } | TypD (con_id, binds, typ) -> let c = match con_id.note with | Some c -> c | _ -> assert false in - { empty_scope with + Scope.{ Scope.empty with typ_env = T.Env.singleton con_id.it c; con_env = T.ConSet.singleton c ; } @@ -1477,7 +1479,7 @@ and infer_dec_valdecs env dec : scope = let t2 = T.Con (c, List.map (fun c -> T.Con (c, [])) cs) in let tbs = List.map2 (fun c t -> {T.var = Con.name c; bound = T.close cs t}) cs ts in let t = T.Func (T.Local, T.Returns, tbs, List.map (T.close cs) ts1, [T.close cs t2]) in - { empty_scope with + Scope.{ Scope.empty with val_env = T.Env.singleton id.it t; typ_env = T.Env.singleton id.it c; con_env = T.ConSet.singleton c; @@ -1485,7 +1487,7 @@ and infer_dec_valdecs env dec : scope = (* Programs *) -let infer_prog scope prog : (T.typ * scope) Diag.result = +let infer_prog scope prog : (T.typ * Scope.t) Diag.result = Diag.with_message_store (fun msgs -> recover_opt @@ -1506,14 +1508,14 @@ let infer_library env prog at = | ds -> object_of_scope env T.Module (List.map (fun d -> { vis = Public @@ no_region ; dec = d } @@ no_region) ds) scope at -let check_library scope (filename, prog) : scope Diag.result = +let check_library scope (filename, prog) : Scope.t Diag.result = Diag.with_message_store (fun msgs -> recover_opt (fun prog -> let env = env_of_scope msgs scope in let typ = infer_library env prog.it prog.at in - library_scope filename typ + Scope.library filename typ ) prog ) diff --git a/src/as_types/scope.ml b/src/as_types/scope.ml index 2fcdfa4ad2d..e0de17da283 100644 --- a/src/as_types/scope.ml +++ b/src/as_types/scope.ml @@ -16,8 +16,9 @@ and scope = con_env : con_env; obj_env : obj_env; } +and t = scope -let empty_scope : scope = +let empty : scope = { val_env = T.Env.empty; lib_env = T.Env.empty; typ_env = T.Env.empty; @@ -25,7 +26,7 @@ let empty_scope : scope = obj_env = T.Env.empty; } -let adjoin_scope scope1 scope2 = +let adjoin scope1 scope2 = { val_env = T.Env.adjoin scope1.val_env scope2.val_env; lib_env = T.Env.adjoin scope1.lib_env scope2.lib_env; typ_env = T.Env.adjoin scope1.typ_env scope2.typ_env; @@ -36,5 +37,5 @@ let adjoin_scope scope1 scope2 = let adjoin_val_env scope ve = {scope with val_env = T.Env.adjoin scope.val_env ve} -let library_scope f t = - { empty_scope with lib_env = T.Env.add f t empty_scope.lib_env } +let library f t = + { empty with lib_env = T.Env.add f t empty.lib_env } diff --git a/src/as_types/scope.mli b/src/as_types/scope.mli index 11825897969..dad521e2342 100644 --- a/src/as_types/scope.mli +++ b/src/as_types/scope.mli @@ -14,9 +14,10 @@ and scope = con_env : con_env; obj_env : obj_env; } +and t = scope -val empty_scope : scope -val adjoin_scope : scope -> scope -> scope +val empty : scope +val adjoin : scope -> scope -> scope val adjoin_val_env : scope -> val_env -> scope -val library_scope : string -> typ -> scope +val library : string -> typ -> scope diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index 181e9927022..023a004349e 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -5,7 +5,7 @@ open As_ir open Interpreter open Printf -type stat_env = Scope.scope +type stat_env = Scope.t type dyn_env = Interpret.scope type env = stat_env * dyn_env @@ -134,7 +134,7 @@ let rec typecheck_progs senv progs : Scope.scope Diag.result = | [] -> Diag.return senv | p::ps -> Diag.bind (infer_prog senv p) (fun (_t, sscope) -> - let senv' = Scope.adjoin_scope senv sscope in + let senv' = Scope.adjoin senv sscope in typecheck_progs senv' ps ) @@ -204,7 +204,7 @@ let chase_imports senv0 imports : (Syntax.libraries * Scope.scope) Diag.result = Diag.bind (typecheck_library !senv f prog) (fun sscope -> Diag.bind (defindeness_prog prog) (fun () -> libraries := (f, prog) :: !libraries; (* NB: Conceptually an append *) - senv := Scope.adjoin_scope !senv sscope; + senv := Scope.adjoin !senv sscope; pending := remove f !pending; Diag.return () )))))) @@ -231,7 +231,7 @@ let load_decl parse_one senv : load_decl_result = Diag.bind (resolve_prog parsed) (fun (prog, libraries) -> Diag.bind (chase_imports senv libraries) (fun (libraries, senv') -> Diag.bind (infer_prog senv' prog) (fun (t, sscope) -> - let senv'' = Scope.adjoin_scope senv' sscope in + let senv'' = Scope.adjoin senv' sscope in Diag.return (libraries, prog, senv'', t, sscope) )))) @@ -291,11 +291,11 @@ let typecheck_prelude () : Syntax.prog * stat_env = match parse_with Lexer.Privileged lexer parse prelude_name with | Error e -> prelude_error "parsing" [e] | Ok prog -> - let senv0 = Scope.empty_scope in + let senv0 = Scope.empty in match infer_prog senv0 prog with | Error es -> prelude_error "checking" es | Ok ((_t, sscope), msgs) -> - let senv1 = Scope.adjoin_scope senv0 sscope in + let senv1 = Scope.adjoin senv0 sscope in prog, senv1 let prelude, initial_stat_env = typecheck_prelude () From 5cbdfa881a778223c17dec82c970a42c80c82923 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 13 Jun 2019 16:44:50 +0200 Subject: [PATCH 0162/1176] Unused modules in ir_passes/* (#493) --- src/ir_passes/rename.ml | 1 - src/ir_passes/tailcall.ml | 5 ++--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/ir_passes/rename.ml b/src/ir_passes/rename.ml index 6fa8e84c910..bcece9140a8 100644 --- a/src/ir_passes/rename.ml +++ b/src/ir_passes/rename.ml @@ -1,6 +1,5 @@ open As_ir open Source -module S = As_frontend.Syntax open Ir module Renaming = Map.Make(String) diff --git a/src/ir_passes/tailcall.ml b/src/ir_passes/tailcall.ml index 9c0b097cbf4..4a4a025a4ed 100644 --- a/src/ir_passes/tailcall.ml +++ b/src/ir_passes/tailcall.ml @@ -6,7 +6,6 @@ open Ir open Ir_effect open Type open Construct -module S = As_frontend.Syntax (* Optimize (self) tail calls to jumps, avoiding stack overflow in a single linear pass *) @@ -44,10 +43,10 @@ TODO: optimize for multiple arguments using multiple temps (not a tuple). *) -type func_info = { func: S.id; +type func_info = { func: id; typ_binds: typ_bind list; temps: var list; - label: S.id; + label: id; tail_called: bool ref; } From 6db9087955fd8ffec323f19e00b2a1eec423a265 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 13 Jun 2019 17:22:30 +0200 Subject: [PATCH 0163/1176] Mergify tweaks (#496) as applied in `dev` by Nikola in https://github.com/dfinity-lab/dev/pull/1072 --- .mergify.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.mergify.yml b/.mergify.yml index b958a7c7cd2..6160fbe6815 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -2,6 +2,7 @@ pull_request_rules: - name: Automatic merge conditions: - "#approved-reviews-by>=1" + - "#changes-requested-reviews-by=0" - status-success=hydra:dfinity-ci-build:actorscript:all-systems-go - base=master - label=automerge @@ -13,6 +14,7 @@ pull_request_rules: - name: Automatic merge (squash) conditions: - "#approved-reviews-by>=1" + - "#changes-requested-reviews-by=0" - status-success=hydra:dfinity-ci-build:actorscript:all-systems-go - base=master - label=automerge-squash @@ -24,6 +26,7 @@ pull_request_rules: - name: Automatic merge (rebase) conditions: - "#approved-reviews-by>=1" + - "#changes-requested-reviews-by=0" - status-success=hydra:dfinity-ci-build:actorscript:all-systems-go - base=master - label=automerge-rebase From 39b98d8bdc567329c9b27e9f54573cda982838f3 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 13 Jun 2019 17:49:57 +0200 Subject: [PATCH 0164/1176] Remove code copied to `ir_values/show.ml` but left in `ir_passes` (#500) --- src/ir_passes/show.ml | 65 ------------------------------------------ src/ir_passes/show.mli | 6 ---- 2 files changed, 71 deletions(-) diff --git a/src/ir_passes/show.ml b/src/ir_passes/show.ml index b8c37d42760..5e14d61d058 100644 --- a/src/ir_passes/show.ml +++ b/src/ir_passes/show.ml @@ -372,71 +372,6 @@ let show_decls : T.typ M.t -> Ir.dec list = fun roots -> decl :: go (deps @ todo) in go (List.map snd (M.bindings roots)) -(* Entry point for type checking: *) - -let rec can_show t = - let t = T.normalize t in - match t with - | T.Prim T.Bool - | T.Prim T.Nat - | T.Prim T.Int - | T.Prim T.Text - | T.Prim T.Null -> true - | T.Tup ts' -> List.for_all can_show ts' - | T.Opt t' -> can_show t' - | T.Array t' -> can_show (T.as_immut t') - | T.Obj (T.Object _, fs) -> - List.for_all (fun f -> can_show (T.as_immut f.T.typ)) fs - | T.Variant cts -> - List.for_all (fun f -> can_show f.T.typ) cts - | _ -> false - -(* Entry point for the interpreter (reference implementation) *) - -let rec show_val t v = - let t = T.normalize t in - match t, v with - | T.Prim T.Bool, Value.Bool b -> if b then "true" else "false" - | T.Prim T.Nat, Value.Int i -> Value.Int.to_string i - | T.Prim T.Int, Value.Int i -> Value.Int.to_string i - | T.Prim T.Text, Value.Text s -> "\"" ^ s ^ "\"" - | T.Prim T.Null, Value.Null -> "null" - | T.Opt _, Value.Null -> "null" - | T.Opt t', Value.Opt v -> "?(" ^ show_val t' v ^ ")" - | T.Tup ts', Value.Tup vs -> - Printf.sprintf "(%s%s)" - (String.concat ", " (List.map2 show_val ts' vs)) - (if List.length vs = 1 then "," else "") - | T.Array (T.Mut t'), Value.Array a -> - Printf.sprintf "[var %s]" - (String.concat ", " (List.map (fun v -> show_val t' !(Value.as_mut v)) (Array.to_list a))) - | T.Array t', Value.Array a -> - Printf.sprintf "[%s]" - (String.concat ", " (List.map (show_val t') (Array.to_list a))) - | T.Obj (_, fts), Value.Obj fs -> - Printf.sprintf "{%s}" (String.concat "; " (List.map (show_field fs) fts)) - | T.Variant fs, Value.Variant (l, v) -> - begin match List.find_opt (fun {T.lab = l'; _} -> l = l') fs with - | Some {T.typ = T.Tup []; _} -> Printf.sprintf "(#%s)" l - | Some {T.typ = t'; _} -> Printf.sprintf "(#%s %s)" l (show_val t' v) - | _ -> assert false - end - | _ -> - Printf.eprintf "show_val: %s : %s\n" (Value.string_of_val 2 v) (T.string_of_typ t); - assert false - -and show_field fs ft = - let v = Value.Env.find ft.T.lab fs in - let m, t', v' = - match ft.T.typ with - | T.Mut t' -> "var ", t', !(Value.as_mut v) - | t' -> "", t', v - in - (* With types: - Printf.sprintf "%s%s : %s = %s" m ft.T.name (T.string_of_typ t') (show_val t' v') - *) - Printf.sprintf "%s = %s" ft.T.lab (show_val t' v') - (* Entry point for the program transformation *) let transform scope prog = diff --git a/src/ir_passes/show.mli b/src/ir_passes/show.mli index ab759d510dc..01f7f067f94 100644 --- a/src/ir_passes/show.mli +++ b/src/ir_passes/show.mli @@ -1,9 +1,3 @@ open As_ir -open As_types -open As_values - -val can_show : Type.typ -> bool - -val show_val : Type.typ -> Value.value -> string val transform : 'a -> Ir.prog -> Ir.prog From ff025b73de7deb6848ca73178db2ff8823ea06a5 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 13 Jun 2019 17:21:39 +0200 Subject: [PATCH 0165/1176] Give the Ir its own `id` and `lit` and also remove the not useful `phrase` wrapper from `id`, simplifying the code noticably. --- src/as_ir/arrange_ir.ml | 26 +++++++++++--- src/as_ir/check_ir.ml | 48 ++++++++++++------------- src/as_ir/construct.ml | 26 +++++++------- src/as_ir/freevars.ml | 12 +++---- src/as_ir/ir.ml | 35 +++++++++++++++++-- src/as_types/arrange_type.ml | 3 -- src/codegen/compile.ml | 56 ++++++++++++++---------------- src/ir_interpreter/interpret_ir.ml | 25 ++++++------- src/ir_passes/async.ml | 2 +- src/ir_passes/await.ml | 12 +++---- src/ir_passes/rename.ml | 16 ++++----- src/ir_passes/show.ml | 18 +++++----- src/ir_passes/tailcall.ml | 8 +++-- src/lowering/desugar.ml | 48 ++++++++++++++++--------- 14 files changed, 192 insertions(+), 143 deletions(-) diff --git a/src/as_ir/arrange_ir.ml b/src/as_ir/arrange_ir.ml index 9a87348ec13..b253f6c394d 100644 --- a/src/as_ir/arrange_ir.ml +++ b/src/as_ir/arrange_ir.ml @@ -1,18 +1,20 @@ open As_frontend open As_types +open As_values open Source -open Arrange_type open Ir open Wasm.Sexpr -(* for concision, we shadow the imported definition of [Arrange_type.typ] and pretty print types instead *) +let ($$) head inner = Node (head, inner) + +let id i = Atom i let typ t = Atom (Type.string_of_typ t) let kind k = Atom (Type.string_of_kind k) let rec exp e = match e.it with | VarE i -> "VarE" $$ [id i] - | LitE l -> "LitE" $$ [Arrange.lit l] + | LitE l -> "LitE" $$ [lit l] | UnE (t, uo, e) -> "UnE" $$ [typ t; Arrange.unop uo; exp e] | BinE (t, e1, bo, e2)-> "BinE" $$ [typ t; exp e1; Arrange.binop bo; exp e2] | RelE (t, e1, ro, e2)-> "RelE" $$ [typ t; exp e1; Arrange.relop ro; exp e2] @@ -58,11 +60,25 @@ and pat p = match p.it with | VarP i -> "VarP" $$ [ id i ] | TupP ps -> "TupP" $$ List.map pat ps | ObjP pfs -> "ObjP" $$ List.map pat_field pfs - | LitP l -> "LitP" $$ [ Arrange.lit l ] + | LitP l -> "LitP" $$ [ lit l ] | OptP p -> "OptP" $$ [ pat p ] | TagP (i, p) -> "TagP" $$ [ id i; pat p ] | AltP (p1,p2) -> "AltP" $$ [ pat p1; pat p2 ] +and lit (l:lit) = match l with + | NullLit -> Atom "NullLit" + | BoolLit true -> "BoolLit" $$ [ Atom "true" ] + | BoolLit false -> "BoolLit" $$ [ Atom "false" ] + | NatLit n -> "NatLit" $$ [ Atom (Value.Nat.to_string n) ] + | IntLit i -> "IntLit" $$ [ Atom (Value.Int.to_string i) ] + | Word8Lit w -> "Word8Lit" $$ [ Atom (Value.Word8.to_string_u w) ] + | Word16Lit w -> "Word16Lit" $$ [ Atom (Value.Word16.to_string_u w) ] + | Word32Lit w -> "Word32Lit" $$ [ Atom (Value.Word32.to_string_u w) ] + | Word64Lit w -> "Word64Lit" $$ [ Atom (Value.Word64.to_string_u w) ] + | FloatLit f -> "FloatLit" $$ [ Atom (Value.Float.to_string f) ] + | CharLit c -> "CharLit" $$ [ Atom (string_of_int c) ] + | TextLit t -> "TextLit" $$ [ Atom t ] + and pat_field pf = pf.it.name $$ [pat pf.it.pat] and case c = "case" $$ [pat c.it.pat; exp c.it.exp] @@ -72,7 +88,7 @@ and call_conv cc = Atom (Call_conv.string_of_call_conv cc) and dec d = match d.it with | LetD (p, e) -> "LetD" $$ [pat p; exp e] | VarD (i, e) -> "VarD" $$ [id i; exp e] - | TypD c -> "TypD" $$ [con c; kind (Con.kind c)] + | TypD c -> "TypD" $$ [Arrange_type.con c; kind (Con.kind c)] and typ_bind (tb : typ_bind) = Con.to_string tb.it.con $$ [typ tb.it.bound] diff --git a/src/as_ir/check_ir.ml b/src/as_ir/check_ir.ml index 0d10ca0c91e..465d7ce53d7 100644 --- a/src/as_ir/check_ir.ml +++ b/src/as_ir/check_ir.ml @@ -244,8 +244,9 @@ and check_inst_bounds env tbs typs at = (* Literals *) +open Ir + let type_lit env lit at : T.prim = - let open Syntax in match lit with | NullLit -> T.Null | BoolLit _ -> T.Bool @@ -258,10 +259,7 @@ let type_lit env lit at : T.prim = | FloatLit _ -> T.Float | CharLit _ -> T.Char | TextLit _ -> T.Text - | PreLit (s, p) -> - error env at "unresolved literal %s of type\n %s" s (T.string_of_prim p) -open Ir (* Expressions *) @@ -289,8 +287,8 @@ let rec check_exp env (exp:Ir.exp) : unit = match exp.it with | PrimE _ -> () | VarE id -> - let t0 = try T.Env.find id.it env.vals with - | Not_found -> error env id.at "unbound variable %s" id.it + let t0 = try T.Env.find id env.vals with + | Not_found -> error env exp.at "unbound variable %s" id in t0 <~ t | LitE lit -> @@ -328,7 +326,7 @@ let rec check_exp env (exp:Ir.exp) : unit = T.Opt (typ exp1) <: t | TagE (i, exp1) -> check_exp env exp1; - T.Variant [{T.lab = i.it; typ = typ exp1}] <: t + T.Variant [{T.lab = i; typ = typ exp1}] <: t | ProjE (exp1, n) -> check_exp env exp1; let t1 = T.promote (immute_typ exp1) in @@ -436,14 +434,14 @@ let rec check_exp env (exp:Ir.exp) : unit = | LabelE (id, t0, exp1) -> assert (t0 <> T.Pre); check_typ env t0; - check_exp (add_lab env id.it t0) exp1; + check_exp (add_lab env id t0) exp1; typ exp1 <: t0; t0 <: t | BreakE (id, exp1) -> begin - match T.Env.find_opt id.it env.labs with + match T.Env.find_opt id env.labs with | None -> - error env id.at "unbound label %s" id.it + error env exp.at "unbound label %s" id | Some t1 -> check_exp env exp1; typ exp1 <: t1; @@ -485,14 +483,14 @@ let rec check_exp env (exp:Ir.exp) : unit = T.unit <: t | DeclareE (id, t0, exp1) -> check_typ env t0; - let env' = adjoin_vals env (T.Env.singleton id.it t0) in + let env' = adjoin_vals env (T.Env.singleton id t0) in check_exp env' exp1; (typ exp1) <: t | DefineE (id, mut, exp1) -> check_exp env exp1; begin - match T.Env.find_opt id.it env.vals with - | None -> error env id.at "unbound variable %s" id.it + match T.Env.find_opt id env.vals with + | None -> error env exp.at "unbound variable %s" id | Some t0 -> match mut.it with | Syntax.Const -> @@ -528,7 +526,7 @@ let rec check_exp env (exp:Ir.exp) : unit = fun_ty <: t | ActorE (id, ds, fs, t0) -> let env' = { env with async = false } in - let ve0 = T.Env.singleton id.it t0 in + let ve0 = T.Env.singleton id t0 in let scope0 = { empty_scope with val_env = ve0 } in let scope1 = List.fold_left (gather_dec env') scope0 ds in let env'' = adjoin env' scope1 in @@ -576,9 +574,9 @@ and gather_pat env ve0 pat : val_env = | LitP _ -> ve | VarP id -> - check env id.at (not (T.Env.mem id.it ve0)) - "duplicate binding for %s in block" id.it; - T.Env.add id.it pat.note ve (*TBR*) + check env pat.at (not (T.Env.mem id ve0)) + "duplicate binding for %s in block" id; + T.Env.add id pat.note ve (*TBR*) | TupP pats -> List.fold_left go ve pats | ObjP pfs -> @@ -601,8 +599,8 @@ and check_pat env pat : val_env = let t = pat.note in match pat.it with | WildP -> T.Env.empty - | VarP id -> T.Env.singleton id.it pat.note - | LitP Syntax.NullLit -> + | VarP id -> T.Env.singleton id pat.note + | LitP NullLit -> T.Prim T.Null <: t; T.Env.empty | LitP lit -> @@ -624,7 +622,7 @@ and check_pat env pat : val_env = ve | TagP (i, pat1) -> let ve = check_pat env pat1 in - T.Variant [{T.lab = i.it; typ = pat1.note}] <: t; + T.Variant [{T.lab = i; typ = pat1.note}] <: t; ve | AltP (pat1, pat2) -> let ve1 = check_pat env pat1 in @@ -666,7 +664,7 @@ and type_exp_fields env s fs : T.field list = and type_exp_field env s f : T.field = let {name; var} = f.it in - let t = try T.Env.find var.it env.vals with + let t = try T.Env.find var env.vals with | Not_found -> error env f.at "field typing for %s not found" name in assert (t <> T.Pre); @@ -701,8 +699,8 @@ and check_dec env dec = check_exp env exp; typ exp <: pat.note | VarD (id, exp) -> - let t0 = try T.Env.find id.it env.vals with - | Not_found -> error env id.at "unbound variable %s" id.it + let t0 = try T.Env.find id env.vals with + | Not_found -> error env dec.at "unbound variable %s" id in check (T.is_mut t0) "variable in VarD is not immutable"; check_exp env exp; @@ -733,9 +731,9 @@ and gather_dec env scope dec : scope = { val_env = ve; con_env = ce'} | VarD (id, exp) -> check env dec.at - (not (T.Env.mem id.it scope.val_env)) + (not (T.Env.mem id scope.val_env)) "duplicate variable definition in block"; - let ve = T.Env.add id.it (T.Mut (typ exp)) scope.val_env in + let ve = T.Env.add id (T.Mut (typ exp)) scope.val_env in { scope with val_env = ve} | TypD c -> check env dec.at diff --git a/src/as_ir/construct.ml b/src/as_ir/construct.ml index bcd30fcaf2d..66395630512 100644 --- a/src/as_ir/construct.ml +++ b/src/as_ir/construct.ml @@ -38,28 +38,28 @@ let id_of_exp x = let arg_of_exp x = match x.it with - | VarE i -> { i with note = x.note.note_typ } + | VarE i -> { it = i; at = x.at; note = x.note.note_typ } | _ -> failwith "Impossible: arg_of_exp" -let exp_of_arg a = idE {a with note = () } a.note +let exp_of_arg a = + idE a.it a.note (* Fresh id generation *) module Stamps = Map.Make(String) let id_stamps = ref Stamps.empty -let fresh name_base () = +let fresh name_base () : string = let n = Lib.Option.get (Stamps.find_opt name_base !id_stamps) 0 in id_stamps := Stamps.add name_base (n + 1) !id_stamps; Printf.sprintf "$%s/%i" name_base n -let fresh_id name_base () = - let name = fresh name_base () in - name @@ no_region +let fresh_id name_base () : id = + fresh name_base () -let fresh_var name_base typ = +let fresh_var name_base typ : exp = let name = fresh name_base () in - idE (name @@ no_region) typ + idE name typ let fresh_vars name_base ts = List.mapi (fun i t -> fresh_var (Printf.sprintf "%s%i" name_base i) t) ts @@ -133,7 +133,7 @@ let blockE decs exp = } let textE s = - { it = LitE (S.TextLit s); + { it = LitE (TextLit s); at = no_region; note = { S.note_typ = T.Prim T.Text; S.note_eff = T.Triv } @@ -148,7 +148,7 @@ let unitE = } let boolE b = - { it = LitE (S.BoolLit b); + { it = LitE (BoolLit b); at = no_region; note = { S.note_typ = T.bool; S.note_eff = T.Triv} @@ -183,7 +183,7 @@ let switch_optE exp1 exp2 pat exp3 typ1 = { it = SwitchE (exp1, - [{ it = {pat = {it = LitP S.NullLit; + [{ it = {pat = {it = LitP NullLit; at = no_region; note = typ exp1}; exp = exp2}; @@ -370,14 +370,14 @@ let nary_funcE name t xs exp = let funcD f x exp = match f.it, x.it with | VarE _, VarE _ -> - letD f (funcE (id_of_exp f).it (typ f) x exp) + letD f (funcE (id_of_exp f) (typ f) x exp) | _ -> failwith "Impossible: funcD" (* Mono-morphic, n-ary function declaration *) let nary_funcD f xs exp = match f.it with | VarE _ -> - letD f (nary_funcE (id_of_exp f).it (typ f) xs exp) + letD f (nary_funcE (id_of_exp f) (typ f) xs exp) | _ -> failwith "Impossible: funcD" diff --git a/src/as_ir/freevars.ml b/src/as_ir/freevars.ml index 2c744fcba5d..fd44e06b080 100644 --- a/src/as_ir/freevars.ml +++ b/src/as_ir/freevars.ml @@ -57,7 +57,7 @@ let close (f,d) = diff f d (* One traversal for each syntactic category, named by that category *) let rec exp e : f = match e.it with - | VarE i -> M.singleton i.it {captured = false} + | VarE i -> M.singleton i {captured = false} | LitE l -> M.empty | PrimE _ -> M.empty | UnE (_, uo, e) -> exp e @@ -84,10 +84,10 @@ let rec exp e : f = match e.it with | AssertE e -> exp e | OptE e -> exp e | TagE (_, e) -> exp e - | DeclareE (i, t, e) -> exp e // i.it + | DeclareE (i, t, e) -> exp e // i | DefineE (i, m, e) -> id i ++ exp e | FuncE (x, cc, tp, as_, t, e) -> under_lambda (exp e /// args as_) - | ActorE (i, ds, fs, _) -> close (decs ds +++ fields fs) // i.it + | ActorE (i, ds, fs, _) -> close (decs ds +++ fields fs) // i | NewObjE (_, fs, _) -> fields fs and fields fs = unions (fun f -> id f.it.var) fs @@ -100,7 +100,7 @@ and args as_ : fd = union_binders arg as_ and pat p : fd = match p.it with | WildP -> (M.empty, S.empty) - | VarP i -> (M.empty, S.singleton i.it) + | VarP i -> (M.empty, S.singleton i) | TupP ps -> pats ps | ObjP pfs -> pats (pats_of_obj_pat pfs) | LitP l -> (M.empty, S.empty) @@ -114,11 +114,11 @@ and case (c : case) = exp c.it.exp /// pat c.it.pat and cases cs : f = unions case cs -and id i = M.singleton i.it {captured = false} +and id i = M.singleton i {captured = false} and dec d = match d.it with | LetD (p, e) -> pat p +++ exp e - | VarD (i, e) -> (M.empty, S.singleton i.it) +++ exp e + | VarD (i, e) -> (M.empty, S.singleton i) +++ exp e | TypD c -> (M.empty, S.empty) (* The variables captured by a function. May include the function itself! *) diff --git a/src/as_ir/ir.ml b/src/as_ir/ir.ml index 0b5ca5a9e1c..f2e1dcf6ee5 100644 --- a/src/as_ir/ir.ml +++ b/src/as_ir/ir.ml @@ -2,6 +2,23 @@ open As_types open As_values open As_frontend (* TODO *) +type id = string + +(* Literals *) + +type lit = + | NullLit + | BoolLit of bool + | NatLit of Value.Nat.t + | IntLit of Value.Int.t + | Word8Lit of Value.Word8.t + | Word16Lit of Value.Word16.t + | Word32Lit of Value.Word32.t + | Word64Lit of Value.Word64.t + | FloatLit of Value.Float.t + | CharLit of Value.unicode + | TextLit of string + (* Patterns *) type type_note = Syntax.typ_note = {note_typ : Type.typ; note_eff : Type.eff} @@ -10,13 +27,10 @@ type 'a phrase = ('a, Syntax.typ_note) Source.annotated_phrase type typ_bind' = {con : Type.con; bound : Type.typ} type typ_bind = typ_bind' Source.phrase -type id = Syntax.id -type lit = Syntax.lit type unop = Operator.unop type binop = Operator.binop type relop = Operator.relop type mut = Syntax.mut -type vis = Syntax.vis type pat = (pat', Type.typ) Source.annotated_phrase and pat' = @@ -89,6 +103,21 @@ and dec' = | VarD of id * exp (* mutable *) | TypD of Type.con (* type *) +(* Literals *) + +let string_of_lit = function + | BoolLit false -> "false" + | BoolLit true -> "true" + | IntLit n + | NatLit n -> Value.Int.to_pretty_string n + | Word8Lit n -> Value.Word8.to_pretty_string n + | Word16Lit n -> Value.Word16.to_pretty_string n + | Word32Lit n -> Value.Word32.to_pretty_string n + | Word64Lit n -> Value.Word64.to_pretty_string n + | CharLit c -> string_of_int c + | NullLit -> "null" + | TextLit t -> t + | FloatLit f -> Value.Float.to_pretty_string f (* Flavor *) diff --git a/src/as_types/arrange_type.ml b/src/as_types/arrange_type.ml index 28ff1225941..a3bc3f92358 100644 --- a/src/as_types/arrange_type.ml +++ b/src/as_types/arrange_type.ml @@ -1,11 +1,8 @@ -open Source open Type open Wasm.Sexpr let ($$) head inner = Node (head, inner) -let id i = Atom i.it - let sharing sh = match sh with | Type.Local -> "Local" | Type.Sharable -> "Sharable" diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 25f36f8662a..ba8cdef1f24 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -3794,12 +3794,12 @@ module ASEnv = struct NameEnv.fold (fun k _ -> Freevars.S.add k) ae.vars Freevars.S.empty let add_label (ae : t) name (d : G.depth) = - { ae with labels = NameEnv.add name.it d ae.labels } + { ae with labels = NameEnv.add name d ae.labels } let get_label_depth (ae : t) name : G.depth = - match NameEnv.find_opt name.it ae.labels with + match NameEnv.find_opt name ae.labels with | Some d -> d - | None -> Printf.eprintf "Could not find %s\n" name.it; raise Not_found + | None -> Printf.eprintf "Could not find %s\n" name; raise Not_found end (* ASEnv *) @@ -4361,7 +4361,7 @@ end (* AllocHow *) (* The actual compiler code that looks at the AST *) let compile_lit env lit = - try As_frontend.Syntax.(match lit with + try match lit with (* Booleans are directly in Vanilla representation *) | BoolLit false -> SR.bool, Bool.lit false | BoolLit true -> SR.bool, Bool.lit true @@ -4375,10 +4375,9 @@ let compile_lit env lit = | CharLit c -> SR.Vanilla, compile_unboxed_const Int32.(shift_left (of_int c) 8) | NullLit -> SR.Vanilla, Opt.null | TextLit t -> SR.Vanilla, Text.lit env t - | _ -> todo_trap_SR env "compile_lit" (As_frontend.Arrange.lit lit) - ) + | _ -> todo_trap_SR env "compile_lit" (Arrange_ir.lit lit) with Failure _ -> - Printf.eprintf "compile_lit: Overflow in literal %s\n" (As_frontend.Syntax.string_of_lit lit); + Printf.eprintf "compile_lit: Overflow in literal %s\n" (string_of_lit lit); SR.Unreachable, E.trap_with env "static literal overflow" let compile_lit_as env sr_out lit = @@ -4584,7 +4583,7 @@ let rec compile_lexp (env : E.t) ae exp = match exp.it with | VarE var -> G.nop, - Var.set_val env ae var.it + Var.set_val env ae var | IdxE (e1,e2) -> compile_exp_vanilla env ae e1 ^^ (* offset to array *) compile_exp_vanilla env ae e2 ^^ (* idx *) @@ -4777,7 +4776,7 @@ and compile_exp (env : E.t) ae exp = end end | VarE var -> - Var.get_val env ae var.it + Var.get_val env ae var | AssignE (e1,e2) -> SR.unit, let (prepare_code, store_code) = compile_lexp env ae e1 in @@ -4855,7 +4854,7 @@ and compile_exp (env : E.t) ae exp = Opt.inject env (compile_exp_vanilla env ae e) | TagE (l, e) -> SR.Vanilla, - Variant.inject env l.it (compile_exp_vanilla env ae e) + Variant.inject env l (compile_exp_vanilla env ae e) | TupE es -> SR.UnboxedTuple (List.length es), G.concat_map (compile_exp_vanilla env ae) es @@ -4907,7 +4906,7 @@ and compile_exp (env : E.t) ae exp = code1 ^^ set_i ^^ orTrap env code2 ^^ get_j (* Async-wait lowering support features *) | DeclareE (name, _, e) -> - let (ae1, i) = ASEnv.add_local_with_offset env ae name.it 1l in + let (ae1, i) = ASEnv.add_local_with_offset env ae name 1l in let sr, code = compile_exp env ae1 e in sr, Tagged.obj env Tagged.MutBox [ compile_unboxed_zero ] ^^ @@ -4916,7 +4915,7 @@ and compile_exp (env : E.t) ae exp = | DefineE (name, _, e) -> SR.unit, compile_exp_vanilla env ae e ^^ - Var.set_val env ae name.it + Var.set_val env ae name | FuncE (x, cc, typ_binds, args, _rt, e) -> let captured = Freevars.captured exp in let mk_body env1 ae1 = compile_exp_as env1 ae1 (StackRep.of_arity cc.Call_conv.n_res) e in @@ -4933,8 +4932,8 @@ and compile_exp (env : E.t) ae exp = let fs' = fs |> List.map (fun (f : Ir.field) -> (f.it.name, fun () -> if Object.is_mut_field env exp.note.note_typ f.it.name - then Var.get_val_ptr env ae f.it.var.it - else Var.get_val_vanilla env ae f.it.var.it)) in + then Var.get_val_ptr env ae f.it.var + else Var.get_val_vanilla env ae f.it.var)) in Object.lit_raw env fs' | _ -> SR.unit, todo_trap env "compile_exp" (Arrange_ir.exp exp) @@ -5002,7 +5001,6 @@ enabled mutual recursion. and compile_lit_pat env l = - let open As_frontend.Syntax in match l with | NullLit -> compile_lit_as env SR.Vanilla l ^^ @@ -5018,7 +5016,7 @@ and compile_lit_pat env l = | (TextLit t) -> Text.lit env t ^^ Text.compare env - | _ -> todo_trap env "compile_lit_pat" (As_frontend.Arrange.lit l) + | _ -> todo_trap env "compile_lit_pat" (Arrange_ir.lit l) and fill_pat env ae pat : patternCode = PatCode.with_region pat.at @@ @@ -5042,7 +5040,7 @@ and fill_pat env ae pat : patternCode = CanFail (fun fail_code -> set_x ^^ get_x ^^ - Variant.test_is env l.it ^^ + Variant.test_is env l ^^ G.if_ (ValBlockType None) ( get_x ^^ Variant.project ^^ @@ -5055,7 +5053,7 @@ and fill_pat env ae pat : patternCode = compile_lit_pat env l ^^ G.if_ (ValBlockType None) G.nop fail_code) | VarP name -> - CannotFail (Var.set_val env ae name.it) + CannotFail (Var.set_val env ae name) | TupP ps -> let (set_i, get_i) = new_local env "tup_scrut" in let rec go i = function @@ -5150,9 +5148,9 @@ and compile_dec env pre_ae how dec : ASEnv.t * G.t * (ASEnv.t -> G.t) = | TypD _ -> (pre_ae, G.nop, fun _ -> G.nop) (* A special case for static expressions *) - | LetD ({it = VarP v; _}, e) when not (AllocHow.M.mem v.it how) -> + | LetD ({it = VarP v; _}, e) when not (AllocHow.M.mem v how) -> let (static_thing, fill) = compile_static_exp env pre_ae how e in - let pre_ae1 = ASEnv.add_local_deferred pre_ae v.it + let pre_ae1 = ASEnv.add_local_deferred pre_ae v (SR.StaticThing static_thing) (fun _ -> G.nop) false in ( pre_ae1, G.nop, fun ae -> fill env ae; G.nop) | LetD (p, e) -> @@ -5162,14 +5160,14 @@ and compile_dec env pre_ae how dec : ASEnv.t * G.t * (ASEnv.t -> G.t) = fill_code ) | VarD (name, e) -> - assert (AllocHow.M.find_opt name.it how = Some AllocHow.LocalMut || - AllocHow.M.find_opt name.it how = Some AllocHow.StoreHeap || - AllocHow.M.find_opt name.it how = Some AllocHow.StoreStatic); - let (pre_ae1, alloc_code) = AllocHow.add_local env pre_ae how name.it in + assert (AllocHow.M.find_opt name how = Some AllocHow.LocalMut || + AllocHow.M.find_opt name how = Some AllocHow.StoreHeap || + AllocHow.M.find_opt name how = Some AllocHow.StoreStatic); + let (pre_ae1, alloc_code) = AllocHow.add_local env pre_ae how name in ( pre_ae1, alloc_code, fun ae -> compile_exp_vanilla env ae e ^^ - Var.set_val env ae name.it + Var.set_val env ae name ) and compile_decs env ae lvl decs captured_in_body : ASEnv.t * G.t = @@ -5278,7 +5276,7 @@ and compile_start_func mod_env (progs : Ir.prog list) : E.func_with_names = ) and export_actor_field env ae (f : Ir.field) = - let sr, code = Var.get_val env ae f.it.var.it in + let sr, code = Var.get_val env ae f.it.var in (* A public actor field is guaranteed to be compiled as a StaticMessage *) let fi = match sr with | SR.StaticThing (SR.StaticMessage fi) -> fi @@ -5317,7 +5315,7 @@ and actor_lit outer_env this ds fs at = let (ae1, prelude_code) = compile_prelude env ae0 in (* Add this pointer *) - let ae2 = ASEnv.add_local_deferred ae1 this.it SR.Vanilla Dfinity.get_self_reference false in + let ae2 = ASEnv.add_local_deferred ae1 this SR.Vanilla Dfinity.get_self_reference false in (* Compile the declarations *) let (ae3, decls_code) = compile_decs env ae2 AllocHow.TopLvl ds Freevars.S.empty in @@ -5330,7 +5328,7 @@ and actor_lit outer_env this ds fs at = OrthogonalPersistence.register mod_env start_fi; - let m = conclude_module mod_env this.it None in + let m = conclude_module mod_env this None in let (_map, wasm_binary) = Wasm_exts.CustomModuleEncode.encode m in wasm_binary in @@ -5342,7 +5340,7 @@ and actor_lit outer_env this ds fs at = (* Main actor: Just return the initialization code, and export functions as needed *) and main_actor env ae1 this ds fs = (* Add this pointer *) - let ae2 = ASEnv.add_local_deferred ae1 this.it SR.Vanilla Dfinity.get_self_reference false in + let ae2 = ASEnv.add_local_deferred ae1 this SR.Vanilla Dfinity.get_self_reference false in (* Compile the declarations *) let (ae3, decls_code) = compile_decs env ae2 AllocHow.TopLvl ds Freevars.S.empty in diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index 1293b76a879..6018cba659c 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -232,7 +232,6 @@ let extended_prim env s typ at = (* Literals *) let interpret_lit env lit : V.value = - let open Syntax in match lit with | NullLit -> V.Null | BoolLit b -> V.Bool b @@ -245,8 +244,6 @@ let interpret_lit env lit : V.value = | FloatLit f -> V.Float f | CharLit c -> V.Char c | TextLit s -> V.Text s - | PreLit _ -> assert false - (* Expressions *) @@ -290,7 +287,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = let cc = call_conv_of_typ t in k (V.Func (cc, extended_prim env s t at)) | VarE id -> - (match Lib.Promise.value_opt (find id.it env.vals) with + (match Lib.Promise.value_opt (find id env.vals) with | Some v -> k v | None -> trap exp.at "accessing identifier before its definition" ) @@ -321,7 +318,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = | OptE exp1 -> interpret_exp env exp1 (fun v1 -> k (V.Opt v1)) | TagE (i, exp1) -> - interpret_exp env exp1 (fun v1 -> k (V.Variant (i.it, v1))) + interpret_exp env exp1 (fun v1 -> k (V.Variant (i, v1))) | ProjE (exp1, n) -> interpret_exp env exp1 (fun v1 -> k (List.nth (V.as_tup v1) n)) | DotE (exp1, n) @@ -382,10 +379,10 @@ and interpret_exp_mut env exp (k : V.value V.cont) = | LoopE exp1 -> interpret_exp env exp1 (fun v -> V.as_unit v; interpret_exp env exp k) | LabelE (id, _typ, exp1) -> - let env' = {env with labs = V.Env.add id.it k env.labs} in + let env' = {env with labs = V.Env.add id k env.labs} in interpret_exp env' exp1 k | BreakE (id, exp1) -> - interpret_exp env exp1 (find id.it env.labs) + interpret_exp env exp1 (find id env.labs) | RetE exp1 -> interpret_exp env exp1 (Lib.Option.value env.rets) | AsyncE exp1 -> @@ -444,7 +441,7 @@ and interpret_fields env fs = let ve = List.fold_left (fun ve (f : field) -> - V.Env.disjoint_add f.it.name (Lib.Promise.value (find f.it.var.it env.vals)) ve + V.Env.disjoint_add f.it.name (Lib.Promise.value (find f.it.var env.vals)) ve ) V.Env.empty fs in V.Obj ve @@ -481,7 +478,7 @@ and match_args at args v : val_env = (* Patterns *) and declare_id id = - V.Env.singleton id.it (Lib.Promise.make ()) + V.Env.singleton id (Lib.Promise.make ()) and declare_pat pat : val_env = match pat.it with @@ -502,7 +499,7 @@ and declare_pats pats ve : val_env = and define_id env id v = - Lib.Promise.fulfill (find id.it env.vals) v + Lib.Promise.fulfill (find id env.vals) v and define_pat env pat v = let err () = trap pat.at "value %s does not match pattern" (string_of_val env v) in @@ -523,7 +520,7 @@ and define_pat env pat v = ) | TagP (i, pat1) -> let lab, v1 = V.as_variant v in - if lab = i.it + if lab = i then define_pat env pat1 v1 else err () @@ -537,7 +534,6 @@ and define_field_pats env pfs vs = and match_lit lit v : bool = - let open Syntax in match lit, v with | NullLit, V.Null -> true | BoolLit b, V.Bool b' -> b = b' @@ -550,11 +546,10 @@ and match_lit lit v : bool = | FloatLit z, V.Float z' -> z = z' | CharLit c, V.Char c' -> c = c' | TextLit u, V.Text u' -> u = u' - | PreLit _, _ -> assert false | _ -> false and match_id id v : val_env = - V.Env.singleton id.it (Lib.Promise.make_fulfilled v) + V.Env.singleton id (Lib.Promise.make_fulfilled v) and match_pat pat v : val_env option = match pat.it with @@ -576,7 +571,7 @@ and match_pat pat v : val_env option = ) | TagP (i, pat1) -> let tag, v1 = V.as_variant v in - if i.it = tag + if i = tag then match_pat pat1 v1 else None | AltP (pat1, pat2) -> diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index 6c30055e455..957f9873fe0 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -62,7 +62,7 @@ module Transform() = struct ) let new_asyncE = - idE ("@new_async"@@no_region) new_asyncT + idE "@new_async" new_asyncT let new_async t1 = let call_new_async = callE new_asyncE [t1] (tupE []) in diff --git a/src/ir_passes/await.ml b/src/ir_passes/await.ml index ecdbe84fbef..21f3d22b05e 100644 --- a/src/ir_passes/await.ml +++ b/src/ir_passes/await.ml @@ -104,11 +104,11 @@ and t_exp' context exp' = | LoopE exp1 -> LoopE (t_exp context exp1) | LabelE (id, _typ, exp1) -> - let context' = LabelEnv.add id.it Label context in + let context' = LabelEnv.add id Label context in LabelE (id, _typ, t_exp context' exp1) | BreakE (id, exp1) -> begin - match LabelEnv.find_opt id.it context with + match LabelEnv.find_opt id context with | Some (Cont k) -> RetE (k -@- (t_exp context exp1)) | Some Label -> BreakE (id, t_exp context exp1) | None -> assert false @@ -297,11 +297,11 @@ and c_exp' context exp k = | LabelE (id, _typ, exp1) -> letcont k (fun k -> - let context' = LabelEnv.add id.it (Cont (ContVar k)) context in + let context' = LabelEnv.add id (Cont (ContVar k)) context in c_exp context' exp1 (ContVar k)) (* TODO optimize me, if possible *) | BreakE (id, exp1) -> begin - match LabelEnv.find_opt id.it context with + match LabelEnv.find_opt id context with | Some (Cont k') -> c_exp context exp1 k' | Some Label -> assert false @@ -431,7 +431,7 @@ and rename_pat' pat = | LitP _ -> (PatEnv.empty, pat.it) | VarP id -> let v = fresh_var "v" pat.note in - (PatEnv.singleton id.it v, + (PatEnv.singleton id v, VarP (id_of_exp v)) | TupP pats -> let (patenv,pats') = rename_pats pats in @@ -465,7 +465,7 @@ and define_pat patenv pat : dec list = | LitP _ -> [] | VarP id -> - [ expD (define_idE id constM (PatEnv.find id.it patenv)) ] + [ expD (define_idE id constM (PatEnv.find id patenv)) ] | TupP pats -> define_pats patenv pats | ObjP pfs -> define_pats patenv (pats_of_obj_pat pfs) | OptP pat1 diff --git a/src/ir_passes/rename.ml b/src/ir_passes/rename.ml index bcece9140a8..3d32496042b 100644 --- a/src/ir_passes/rename.ml +++ b/src/ir_passes/rename.ml @@ -10,21 +10,21 @@ module Stamps = Map.Make(String) let stamps = ref Stamps.empty let fresh_id id = - let n = Lib.Option.get (Stamps.find_opt id.it !stamps) 0 in - stamps := Stamps.add id.it (n + 1) !stamps; - Printf.sprintf "%s/%i" id.it n + let n = Lib.Option.get (Stamps.find_opt id !stamps) 0 in + stamps := Stamps.add id (n + 1) !stamps; + Printf.sprintf "%s/%i" id n let id rho i = - try {i with it = Renaming.find i.it rho} + try Renaming.find i rho with Not_found -> i let id_bind rho i = let i' = fresh_id i in - ({i with it = i'}, Renaming.add i.it i' rho) + (i', Renaming.add i i' rho) -let arg_bind rho i = - let i' = fresh_id i in - ({i with it = i'}, Renaming.add i.it i' rho) +let arg_bind rho a = + let i' = fresh_id a.it in + ({a with it = i'}, Renaming.add a.it i' rho) let rec exp rho e = {e with it = exp' rho e.it} diff --git a/src/ir_passes/show.ml b/src/ir_passes/show.ml index 5e14d61d058..671508859ef 100644 --- a/src/ir_passes/show.ml +++ b/src/ir_passes/show.ml @@ -54,7 +54,7 @@ let show_fun_typ_for t = T.Func (T.Local, T.Returns, [], [t], [T.Prim T.Text]) let show_var_for t : Construct.var = - idE (show_name_for t @@ no_region) (show_fun_typ_for t) + idE (show_name_for t) (show_fun_typ_for t) (* The AST traversal *) @@ -70,7 +70,7 @@ and t_exp' env = function | ShowE (ot, exp1) -> let t' = T.normalize ot in add_type env t'; - let f = idE (show_name_for t' @@ no_region) (show_fun_typ_for t') in + let f = idE (show_name_for t') (show_fun_typ_for t') in CallE (Call_conv.local_cc 1 1, f, [], t_exp env exp1) | UnE (ot, op, exp1) -> UnE (ot, op, t_exp env exp1) @@ -150,7 +150,7 @@ and t_prog env (prog, flavor) = (t_block env prog, flavor) (* Many of these are simply the entry points for helper functions defined in the prelude. *) -let argE t = idE ("x" @@ no_region) t +let argE t = idE "x" t let define_show : T.typ -> Ir.exp -> Ir.dec = fun t e -> Construct.funcD (show_var_for t) (argE t) e @@ -168,7 +168,7 @@ let invoke_prelude_show : string -> T.typ -> Ir.exp -> Ir.exp = fun n t e -> let fun_typ = T.Func (T.Local, T.Returns, [], [t], [T.Prim T.Text]) in text_exp (CallE ( Call_conv.local_cc 1 1 - , { it = VarE (n @@ no_region) + , { it = VarE n ; at = no_region ; note = { note_typ = fun_typ; note_eff = T.Triv } } @@ -182,7 +182,7 @@ let invoke_text_of_option : T.typ -> Ir.exp -> Ir.exp -> Ir.exp = fun t f e -> T.Func (T.Local, T.Returns, [{T.var="T";T.bound=T.Any}], [show_fun_typ_for (T.Var ("T",0)); T.Opt (T.Var ("T",0))], [T.Prim T.Text]) in text_exp (CallE ( Call_conv.local_cc 2 1 - , { it = VarE ("@text_of_option" @@ no_region) + , { it = VarE "@text_of_option" ; at = no_region ; note = { note_typ = fun_typ; note_eff = T.Triv } } @@ -199,7 +199,7 @@ let invoke_text_of_variant : T.typ -> Ir.exp -> T.lab -> Ir.exp -> Ir.exp = fun T.Func (T.Local, T.Returns, [{T.var="T";T.bound=T.Any}], [T.Prim T.Text; show_fun_typ_for (T.Var ("T",0)); T.Var ("T",0)], [T.Prim T.Text]) in text_exp (CallE ( Call_conv.local_cc 3 1 - , { it = VarE ("@text_of_variant" @@ no_region) + , { it = VarE "@text_of_variant" ; at = no_region ; note = { note_typ = fun_typ; note_eff = T.Triv } } @@ -216,7 +216,7 @@ let invoke_text_of_array : T.typ -> Ir.exp -> Ir.exp -> Ir.exp = fun t f e -> T.Func (T.Local, T.Returns, [{T.var="T";T.bound=T.Any}], [show_fun_typ_for (T.Var ("T",0)); T.Array (T.Var ("T",0))], [T.Prim T.Text]) in text_exp (CallE ( Call_conv.local_cc 2 1 - , { it = VarE ("@text_of_array" @@ no_region) + , { it = VarE "@text_of_array" ; at = no_region ; note = { note_typ = fun_typ; note_eff = T.Triv } } @@ -233,7 +233,7 @@ let invoke_text_of_array_mut : T.typ -> Ir.exp -> Ir.exp -> Ir.exp = fun t f e - T.Func (T.Local, T.Returns, [{T.var="T";T.bound=T.Any}], [show_fun_typ_for (T.Var ("T",0)); T.Array (T.Mut (T.Var ("T",0)))], [T.Prim T.Text]) in text_exp (CallE ( Call_conv.local_cc 2 1 - , { it = VarE ("@text_of_array_mut" @@ no_region) + , { it = VarE "@text_of_array_mut" ; at = no_region ; note = { note_typ = fun_typ; note_eff = T.Triv } } @@ -348,7 +348,7 @@ let show_for : T.typ -> Ir.dec * T.typ list = fun t -> (argE t) (List.map (fun {T.lab = l; typ = t'} -> let t' = T.normalize t' in - l @@ no_region, + l, (varP (argE t')), (* Shadowing, but that's fine *) (invoke_text_of_variant t' (show_var_for t') l (argE t')) ) fs) diff --git a/src/ir_passes/tailcall.ml b/src/ir_passes/tailcall.ml index 4a4a025a4ed..440018b47eb 100644 --- a/src/ir_passes/tailcall.ml +++ b/src/ir_passes/tailcall.ml @@ -61,10 +61,12 @@ let bind env i (info:func_info option) : env = { env with info = info; } | None -> match env.info with - | Some { func; _} when i.it = func.it -> + | Some { func; _} when i = func -> { env with info = None } (* remove shadowed func info *) | _ -> env (* preserve existing, non-shadowed info *) +let bind_arg env a info = bind env a.it info + let are_generic_insts (tbs : typ_bind list) insts = List.for_all2 (fun (tb : typ_bind) inst -> @@ -109,7 +111,7 @@ and exp' env e : exp' = match e.it with match e1.it, env with | VarE f1, { tail_pos = true; info = Some { func; typ_binds; temps; label; tail_called } } - when f1.it = func.it && are_generic_insts typ_binds insts -> + when f1 = func && are_generic_insts typ_binds insts -> tail_called := true; (blockE (assignEs temps (exp env e2)) (breakE label (tupE []))).it @@ -143,7 +145,7 @@ and exp' env e : exp' = match e.it with and exps env es = List.map (exp env) es and args env as_ = - List.fold_left (fun env a -> bind env a None) env as_ + List.fold_left (fun env a -> bind_arg env a None) env as_ and pat env p = let env = pat' env p.it in diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index fceec643934..5d53b8361b5 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -46,8 +46,8 @@ and exp e = and exp' at note = function | S.PrimE p -> I.PrimE p - | S.VarE i -> I.VarE i - | S.LitE l -> I.LitE !l + | S.VarE i -> I.VarE i.it + | S.LitE l -> I.LitE (lit !l) | S.UnE (ot, o, e) -> I.UnE (!ot, o, exp e) | S.BinE (ot, e1, o, e2) -> @@ -61,7 +61,7 @@ and exp' at note = function | S.OptE e -> I.OptE (exp e) | S.ObjE (s, es) -> obj at s None es note.S.note_typ - | S.TagE (c, e) -> I.TagE (c, exp e) + | S.TagE (c, e) -> I.TagE (c.it, exp e) | S.DotE (e, x) -> let n = x.it in begin match T.as_obj_sub x.it e.note.S.note_typ with @@ -98,8 +98,8 @@ and exp' at note = function | S.LoopE (e1, None) -> I.LoopE (exp e1) | S.LoopE (e1, Some e2) -> (loopWhileE (exp e1) (exp e2)).it | S.ForE (p, e1, e2) -> (forE (pat p) (exp e1) (exp e2)).it - | S.LabelE (l, t, e) -> I.LabelE (l, t.Source.note, exp e) - | S.BreakE (l, e) -> I.BreakE (l, exp e) + | S.LabelE (l, t, e) -> I.LabelE (l.it, t.Source.note, exp e) + | S.BreakE (l, e) -> I.BreakE (l.it, exp e) | S.RetE e -> I.RetE (exp e) | S.AsyncE e -> I.AsyncE (exp e) | S.AwaitE e -> I.AwaitE (exp e) @@ -107,7 +107,7 @@ and exp' at note = function | S.AnnotE (e, _) -> assert false | S.ImportE (f, fp) -> if !fp = "" then assert false; (* unresolved import *) - I.VarE (id_of_full_path !fp) + I.VarE (id_of_full_path !fp).it and obj at s self_id es obj_typ = match s.it with @@ -116,7 +116,7 @@ and obj at s self_id es obj_typ = and build_field {T.lab; T.typ} = { it = { I.name = lab - ; I.var = lab @@ no_region + ; I.var = lab } ; at = no_region ; note = typ @@ -134,8 +134,8 @@ and build_actor at self_id es obj_typ = let fs = build_fields obj_typ in let ds = decs (List.map (fun ef -> ef.it.S.dec) es) in let name = match self_id with - | Some n -> n - | None -> ("anon-actor-" ^ string_of_pos at.left) @@ at in + | Some n -> n.it + | None -> "anon-actor-" ^ string_of_pos at.left in I.ActorE (name, ds, fs, obj_typ) and build_obj at s self_id es obj_typ = @@ -144,7 +144,7 @@ and build_obj at s self_id es obj_typ = let ret_ds, ret_o = match self_id with | None -> [], obj_e - | Some id -> let self = idE id obj_typ in [ letD self obj_e ], self + | Some id -> let self = idE id.it obj_typ in [ letD self obj_e ], self in I.BlockE (decs (List.map (fun ef -> ef.it.S.dec) es) @ ret_ds, ret_o) and typ_binds tbs = List.map typ_bind tbs @@ -166,7 +166,7 @@ and block force_unit ds = | _, S.ExpD e -> (extra @ List.map dec prefix, exp e) | false, S.LetD ({it = S.VarP x; _}, e) -> - (extra @ List.map dec ds, idE x e.note.S.note_typ) + (extra @ List.map dec ds, idE x.it e.note.S.note_typ) | false, S.LetD (p', e') -> let x = fresh_var "x" (e'.note.S.note_typ) in (extra @ List.map dec prefix @ [letD x (exp e'); letP (pat p') x], x) @@ -199,7 +199,7 @@ and dec' at n d = match d with I.LetD (p', {e' with it = I.ActorE (i, ds, fs, t)}) | _ -> I.LetD (p', e') end - | S.VarD (i, e) -> I.VarD (i, exp e) + | S.VarD (i, e) -> I.VarD (i.it, exp e) | S.TypD (id, typ_bind, t) -> let c = Lib.Option.value id.note in I.TypD c @@ -220,7 +220,7 @@ and dec' at n d = match d with T.promote (T.open_ inst rng) | _ -> assert false in - let varPat = {it = I.VarP id'; at = at; note = fun_typ } in + let varPat = {it = I.VarP id'.it; at = at; note = fun_typ } in let args, wrap = to_args cc p in let fn = { it = I.FuncE (id.it, cc, typ_binds tbs, args, [obj_typ], wrap @@ -243,19 +243,33 @@ and pats ps = List.map pat ps and pat p = phrase pat' p and pat' = function - | S.VarP v -> I.VarP v + | S.VarP v -> I.VarP v.it | S.WildP -> I.WildP - | S.LitP l -> I.LitP !l - | S.SignP (o, l) -> I.LitP (apply_sign o !l) + | S.LitP l -> I.LitP (lit !l) + | S.SignP (o, l) -> I.LitP (lit (apply_sign o (!l))) | S.TupP ps -> I.TupP (pats ps) | S.ObjP pfs -> I.ObjP (pat_fields pfs) | S.OptP p -> I.OptP (pat p) - | S.TagP (i, p) -> I.TagP (i, pat p) + | S.TagP (i, p) -> I.TagP (i.it, pat p) | S.AltP (p1, p2) -> I.AltP (pat p1, pat p2) | S.AnnotP (p, _) | S.ParP p -> pat' p.it +and lit l = match l with + | S.NullLit -> I.NullLit + | S.BoolLit x -> I.BoolLit x + | S.NatLit x -> I.NatLit x + | S.IntLit x -> I.IntLit x + | S.Word8Lit x -> I.Word8Lit x + | S.Word16Lit x -> I.Word16Lit x + | S.Word32Lit x -> I.Word32Lit x + | S.Word64Lit x -> I.Word64Lit x + | S.FloatLit x -> I.FloatLit x + | S.CharLit x -> I.CharLit x + | S.TextLit x -> I.TextLit x + | S.PreLit _ -> assert false + and pat_fields pfs = List.map pat_field pfs and pat_field pf = phrase (fun S.{id; pat=p} -> I.{name=id.it; pat=pat p}) pf From b051be593dd536148c967cc3583f01b2c581245f Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 13 Jun 2019 15:42:13 +0200 Subject: [PATCH 0166/1176] Ir/Frontent distangling: Define Ir.mut MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit so that we don’t have to use Syntax.mut --- src/as_ir/arrange_ir.ml | 8 ++++++-- src/as_ir/check_ir.ml | 9 ++++----- src/as_ir/construct.ml | 5 ----- src/as_ir/construct.mli | 5 ----- src/as_ir/ir.ml | 3 ++- src/ir_interpreter/interpret_ir.ml | 12 ++++++------ src/ir_passes/await.ml | 6 +++--- src/lowering/desugar.ml | 6 +++++- 8 files changed, 26 insertions(+), 28 deletions(-) diff --git a/src/as_ir/arrange_ir.ml b/src/as_ir/arrange_ir.ml index b253f6c394d..b9dac18cb50 100644 --- a/src/as_ir/arrange_ir.ml +++ b/src/as_ir/arrange_ir.ml @@ -24,7 +24,7 @@ let rec exp e = match e.it with | DotE (e, n) -> "DotE" $$ [exp e; Atom n] | ActorDotE (e, n) -> "ActorDotE" $$ [exp e; Atom n] | AssignE (e1, e2) -> "AssignE" $$ [exp e1; exp e2] - | ArrayE (m, t, es) -> "ArrayE" $$ [Arrange.mut m; typ t] @ List.map exp es + | ArrayE (m, t, es) -> "ArrayE" $$ [mut m; typ t] @ List.map exp es | IdxE (e1, e2) -> "IdxE" $$ [exp e1; exp e2] | CallE (cc, e1, ts, e2) -> "CallE" $$ [call_conv cc; exp e1] @ List.map typ ts @ [exp e2] | BlockE (ds, e1) -> "BlockE" $$ List.map dec ds @ [exp e1] @@ -41,7 +41,7 @@ let rec exp e = match e.it with | TagE (i, e) -> "TagE" $$ [id i; exp e] | PrimE p -> "PrimE" $$ [Atom p] | DeclareE (i, t, e1) -> "DeclareE" $$ [id i; exp e1] - | DefineE (i, m, e1) -> "DefineE" $$ [id i; Arrange.mut m; exp e1] + | DefineE (i, m, e1) -> "DefineE" $$ [id i; mut m; exp e1] | FuncE (x, cc, tp, as_, ts, e) -> "FuncE" $$ [Atom x; call_conv cc] @ List.map typ_bind tp @ args as_@ [ typ (Type.seq ts); exp e] | ActorE (i, ds, fs, t) -> "ActorE" $$ [id i] @ List.map dec ds @ fields fs @ [typ t] @@ -55,6 +55,10 @@ and args = function and arg a = Atom a.it +and mut = function + | Const -> Atom "Const" + | Var -> Atom "Var" + and pat p = match p.it with | WildP -> Atom "WildP" | VarP i -> "VarP" $$ [ id i ] diff --git a/src/as_ir/check_ir.ml b/src/as_ir/check_ir.ml index 465d7ce53d7..c9d1eefc39d 100644 --- a/src/as_ir/check_ir.ml +++ b/src/as_ir/check_ir.ml @@ -1,5 +1,4 @@ open As_types -open As_frontend open As_values open Source @@ -372,7 +371,7 @@ let rec check_exp env (exp:Ir.exp) : unit = | ArrayE (mut, t0, exps) -> List.iter (check_exp env) exps; List.iter (fun e -> typ e <: t0) exps; - let t1 = T.Array (match mut.it with Syntax.Const -> t0 | Syntax.Var -> T.Mut t0) in + let t1 = T.Array (match mut with Const -> t0 | Var -> T.Mut t0) in t1 <: t | IdxE (exp1, exp2) -> check_exp env exp1; @@ -492,10 +491,10 @@ let rec check_exp env (exp:Ir.exp) : unit = match T.Env.find_opt id env.vals with | None -> error env exp.at "unbound variable %s" id | Some t0 -> - match mut.it with - | Syntax.Const -> + match mut with + | Const -> typ exp1 <: t0 - | Syntax.Var -> + | Var -> let t0 = try T.as_mut t0 with | Invalid_argument _ -> error env exp.at "expected mutable %s" (T.string_of_typ t0) diff --git a/src/as_ir/construct.ml b/src/as_ir/construct.ml index 66395630512..72694289b95 100644 --- a/src/as_ir/construct.ml +++ b/src/as_ir/construct.ml @@ -11,11 +11,6 @@ module T = As_types.Type type var = exp -(* Mutabilities *) - -let varM = S.Var @@ no_region -let constM = S.Const @@ no_region - (* Field names *) let nameN s = s diff --git a/src/as_ir/construct.mli b/src/as_ir/construct.mli index 28f36f9c691..ff788c746da 100644 --- a/src/as_ir/construct.mli +++ b/src/as_ir/construct.mli @@ -13,11 +13,6 @@ open Type type var = exp -(* Mutabilities *) - -val varM : mut -val constM : mut - (* Field names *) val nameN : string -> Type.lab diff --git a/src/as_ir/ir.ml b/src/as_ir/ir.ml index f2e1dcf6ee5..7b62def7eb6 100644 --- a/src/as_ir/ir.ml +++ b/src/as_ir/ir.ml @@ -30,7 +30,8 @@ type typ_bind = typ_bind' Source.phrase type unop = Operator.unop type binop = Operator.binop type relop = Operator.relop -type mut = Syntax.mut + +type mut = Const | Var type pat = (pat', Type.typ) Source.annotated_phrase and pat' = diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index 6018cba659c..e72e63e5ed9 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -336,9 +336,9 @@ and interpret_exp_mut env exp (k : V.value V.cont) = | ArrayE (mut, _, exps) -> interpret_exps env exps [] (fun vs -> let vs' = - match mut.it with - | Syntax.Var -> List.map (fun v -> V.Mut (ref v)) vs - | Syntax.Const -> vs + match mut with + | Var -> List.map (fun v -> V.Mut (ref v)) vs + | Const -> vs in k (V.Array (Array.of_list vs')) ) | IdxE (exp1, exp2) -> @@ -410,9 +410,9 @@ and interpret_exp_mut env exp (k : V.value V.cont) = | DefineE (id, mut, exp1) -> interpret_exp env exp1 (fun v -> let v' = - match mut.it with - | Syntax.Const -> v - | Syntax.Var -> V.Mut (ref v) + match mut with + | Const -> v + | Var -> V.Mut (ref v) in define_id env id v'; k V.unit diff --git a/src/ir_passes/await.ml b/src/ir_passes/await.ml index 21f3d22b05e..62b2a6a8987 100644 --- a/src/ir_passes/await.ml +++ b/src/ir_passes/await.ml @@ -371,11 +371,11 @@ and c_dec context dec (k:kont) = begin match eff exp with | T.Triv -> - k -@- define_idE id varM (t_exp context exp) + k -@- define_idE id Var (t_exp context exp) | T.Await -> c_exp context exp (meta (typ exp) - (fun v -> k -@- define_idE id varM v)) + (fun v -> k -@- define_idE id Var v)) end @@ -465,7 +465,7 @@ and define_pat patenv pat : dec list = | LitP _ -> [] | VarP id -> - [ expD (define_idE id constM (PatEnv.find id patenv)) ] + [ expD (define_idE id Const (PatEnv.find id patenv)) ] | TupP pats -> define_pats patenv pats | ObjP pfs -> define_pats patenv (pats_of_obj_pat pfs) | OptP pat1 diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 5d53b8361b5..b8e268e888f 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -71,7 +71,7 @@ and exp' at note = function | S.AssignE (e1, e2) -> I.AssignE (exp e1, exp e2) | S.ArrayE (m, es) -> let t = T.as_array note.S.note_typ in - I.ArrayE (m, T.as_immut t, exps es) + I.ArrayE (mut m, T.as_immut t, exps es) | S.IdxE (e1, e2) -> I.IdxE (exp e1, exp e2) | S.FuncE (name, s, tbs, p, ty, e) -> let cc = Call_conv.call_conv_of_typ note.S.note_typ in @@ -109,6 +109,10 @@ and exp' at note = function if !fp = "" then assert false; (* unresolved import *) I.VarE (id_of_full_path !fp).it +and mut m = match m.it with + | S.Const -> Ir.Const + | S.Var -> Ir.Var + and obj at s self_id es obj_typ = match s.it with | T.Object _ | T.Module -> build_obj at s self_id es obj_typ From 687e6034d9f5146aba8b0c6e9786eb7e5d5ff769 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 13 Jun 2019 17:39:26 +0200 Subject: [PATCH 0167/1176] IR is now independent of the Frontend --- src/as_frontend/arrange.ml | 58 ++-------------- src/as_ir/arrange_ir.ml | 9 ++- src/as_ir/construct.ml | 108 +++++++++++++++-------------- src/as_ir/dune | 2 +- src/as_ir/ir.ml | 5 +- src/as_ir/ir_effect.mli | 3 +- src/as_types/arrange_type.ml | 14 ++-- src/as_values/arrange_ops.ml | 32 +++++++++ src/codegen/compile.ml | 8 +-- src/ir_interpreter/interpret_ir.ml | 7 +- src/lowering/desugar.ml | 26 ++++--- 11 files changed, 133 insertions(+), 139 deletions(-) create mode 100644 src/as_values/arrange_ops.ml diff --git a/src/as_frontend/arrange.ml b/src/as_frontend/arrange.ml index bafa423cb5c..5c28fbe5d37 100644 --- a/src/as_frontend/arrange.ml +++ b/src/as_frontend/arrange.ml @@ -1,6 +1,5 @@ open As_types open As_values -open As_values.Operator open Source open Syntax @@ -14,9 +13,9 @@ and tag i = Atom ("#" ^ i.it) let rec exp e = match e.it with | VarE x -> "VarE" $$ [id x] | LitE l -> "LitE" $$ [lit !l] - | UnE (ot, uo, e) -> "UnE" $$ [operator_type !ot; unop uo; exp e] - | BinE (ot, e1, bo, e2) -> "BinE" $$ [operator_type !ot; exp e1; binop bo; exp e2] - | RelE (ot, e1, ro, e2) -> "RelE" $$ [operator_type !ot; exp e1; relop ro; exp e2] + | UnE (ot, uo, e) -> "UnE" $$ [operator_type !ot; Arrange_ops.unop uo; exp e] + | BinE (ot, e1, bo, e2) -> "BinE" $$ [operator_type !ot; exp e1; Arrange_ops.binop bo; exp e2] + | RelE (ot, e1, ro, e2) -> "RelE" $$ [operator_type !ot; exp e1; Arrange_ops.relop ro; exp e2] | ShowE (ot, e) -> "ShowE" $$ [operator_type !ot; exp e] | TupE es -> "TupE" $$ List.map exp es | ProjE (e, i) -> "ProjE" $$ [exp e; Atom (string_of_int i)] @@ -28,7 +27,7 @@ let rec exp e = match e.it with | FuncE (x, s, tp, p, t, e') -> "FuncE" $$ [ Atom (Type.string_of_typ e.note.note_typ); - Atom (sharing s.it); + Atom (Arrange_type.sharing s.it); Atom x] @ List.map typ_bind tp @ [ pat p; @@ -65,7 +64,7 @@ and pat p = match p.it with | ObjP ps -> "ObjP" $$ List.map pat_field ps | AnnotP (p, t) -> "AnnotP" $$ [pat p; typ t] | LitP l -> "LitP" $$ [lit !l] - | SignP (uo, l) -> "SignP" $$ [unop uo ; lit !l] + | SignP (uo, l) -> "SignP" $$ [Arrange_ops.unop uo ; lit !l] | OptP p -> "OptP" $$ [pat p] | TagP (i, p) -> "TagP" $$ [tag i; pat p] | AltP (p1,p2) -> "AltP" $$ [pat p1; pat p2] @@ -86,54 +85,11 @@ and lit (l:lit) = match l with | TextLit t -> "TextLit" $$ [ Atom t ] | PreLit (s,p) -> "PreLit" $$ [ Atom s; Arrange_type.prim p ] -and unop uo = match uo with - | PosOp -> Atom "PosOp" - | NegOp -> Atom "NegOp" - | NotOp -> Atom "NotOp" - -and binop bo = match bo with - | AddOp -> Atom "AddOp" - | SubOp -> Atom "SubOp" - | MulOp -> Atom "MulOp" - | DivOp -> Atom "DivOp" - | ModOp -> Atom "ModOp" - | AndOp -> Atom "AndOp" - | OrOp -> Atom "OrOp" - | XorOp -> Atom "XorOp" - | ShLOp -> Atom "ShiftLOp" - | UShROp -> Atom "UnsignedShiftROp" - | SShROp -> Atom "SignedShiftROp" - | RotLOp -> Atom "RotLOp" - | RotROp -> Atom "RotROp" - | CatOp -> Atom "CatOp" - | PowOp -> Atom "PowOp" - -and relop ro = match ro with - | EqOp -> Atom "EqOp" - | NeqOp -> Atom "NeqOp" - | LtOp -> Atom "LtOp" - | GtOp -> Atom "GtOp" - | LeOp -> Atom "LeOp" - | GeOp -> Atom "GeOp" - and case c = "case" $$ [pat c.it.pat; exp c.it.exp] and pat_field pf = pf.it.id.it $$ [pat pf.it.pat] -and sharing sh = match sh with - | Type.Local -> "Local" - | Type.Sharable -> "Sharable" - -and control c = match c with - | Type.Returns -> "Returns" - | Type.Promises -> "Promises" - -and obj_sort' s = match s with - | Type.Object sh -> Atom ("Object " ^ sharing sh) - | Type.Actor -> Atom "Actor" - | Type.Module -> Atom "Module" - -and obj_sort s = obj_sort' s.it +and obj_sort s = Arrange_type.obj_sort s.it and mut m = match m.it with | Const -> Atom "Const" @@ -169,7 +125,7 @@ and typ t = match t.it with | OptT t -> "OptT" $$ [typ t] | VariantT cts -> "VariantT" $$ List.map typ_tag cts | TupT ts -> "TupT" $$ List.map typ ts - | FuncT (s, tbs, at, rt) -> "FuncT" $$ [Atom (sharing s.it)] @ List.map typ_bind tbs @ [ typ at; typ rt] + | FuncT (s, tbs, at, rt) -> "FuncT" $$ [Atom (Arrange_type.sharing s.it)] @ List.map typ_bind tbs @ [ typ at; typ rt] | AsyncT t -> "AsyncT" $$ [typ t] | ParT t -> "ParT" $$ [typ t] diff --git a/src/as_ir/arrange_ir.ml b/src/as_ir/arrange_ir.ml index b9dac18cb50..474ad81fe37 100644 --- a/src/as_ir/arrange_ir.ml +++ b/src/as_ir/arrange_ir.ml @@ -1,4 +1,3 @@ -open As_frontend open As_types open As_values open Source @@ -15,9 +14,9 @@ let kind k = Atom (Type.string_of_kind k) let rec exp e = match e.it with | VarE i -> "VarE" $$ [id i] | LitE l -> "LitE" $$ [lit l] - | UnE (t, uo, e) -> "UnE" $$ [typ t; Arrange.unop uo; exp e] - | BinE (t, e1, bo, e2)-> "BinE" $$ [typ t; exp e1; Arrange.binop bo; exp e2] - | RelE (t, e1, ro, e2)-> "RelE" $$ [typ t; exp e1; Arrange.relop ro; exp e2] + | UnE (t, uo, e) -> "UnE" $$ [typ t; Arrange_ops.unop uo; exp e] + | BinE (t, e1, bo, e2)-> "BinE" $$ [typ t; exp e1; Arrange_ops.binop bo; exp e2] + | RelE (t, e1, ro, e2)-> "RelE" $$ [typ t; exp e1; Arrange_ops.relop ro; exp e2] | ShowE (t, e) -> "ShowE" $$ [typ t; exp e] | TupE es -> "TupE" $$ List.map exp es | ProjE (e, i) -> "ProjE" $$ [exp e; Atom (string_of_int i)] @@ -45,7 +44,7 @@ let rec exp e = match e.it with | FuncE (x, cc, tp, as_, ts, e) -> "FuncE" $$ [Atom x; call_conv cc] @ List.map typ_bind tp @ args as_@ [ typ (Type.seq ts); exp e] | ActorE (i, ds, fs, t) -> "ActorE" $$ [id i] @ List.map dec ds @ fields fs @ [typ t] - | NewObjE (s, fs, t) -> "NewObjE" $$ (Arrange.obj_sort' s :: fields fs @ [typ t]) + | NewObjE (s, fs, t) -> "NewObjE" $$ (Arrange_type.obj_sort s :: fields fs @ [typ t]) and fields fs = List.fold_left (fun flds (f : field) -> (f.it.name $$ [ id f.it.var ]):: flds) [] fs diff --git a/src/as_ir/construct.ml b/src/as_ir/construct.ml index 72694289b95..d2a00812f82 100644 --- a/src/as_ir/construct.ml +++ b/src/as_ir/construct.ml @@ -1,4 +1,3 @@ -open As_frontend open As_types (* WIP translation of syntaxops to use IR in place of Source *) @@ -6,7 +5,6 @@ open Source open Ir open Ir_effect -module S = Syntax module T = As_types.Type type var = exp @@ -22,8 +20,7 @@ let nextN = "next" let idE id typ = { it = VarE id; at = no_region; - note = { S.note_typ = typ; - S.note_eff = T.Triv } + note = { note_typ = typ; note_eff = T.Triv } } let id_of_exp x = @@ -65,7 +62,7 @@ let fresh_vars name_base ts = let varP x = { it = VarP (id_of_exp x); at = x.at; - note = x.note.S.note_typ + note = x.note.note_typ } let tupP pats = @@ -88,8 +85,7 @@ let as_seqP p = let primE name typ = { it = PrimE name; at = no_region; - note = { S.note_typ = typ; - S.note_eff = T.Triv } + note = { note_typ = typ; note_eff = T.Triv } } (* tuples *) @@ -98,8 +94,7 @@ let projE e n = match typ e with | T.Tup ts -> { it = ProjE (e, n); - note = { S.note_typ = List.nth ts n; - S.note_eff = eff e }; + note = { note_typ = List.nth ts n; note_eff = eff e }; at = no_region; } | _ -> failwith "projE" @@ -123,30 +118,26 @@ let blockE decs exp = let e = List.fold_left max_eff (eff exp) es in { it = BlockE (decs', exp); at = no_region; - note = {S.note_typ = typ; - S.note_eff = e } + note = {note_typ = typ; note_eff = e } } let textE s = { it = LitE (TextLit s); at = no_region; - note = { S.note_typ = T.Prim T.Text; - S.note_eff = T.Triv } + note = { note_typ = T.Prim T.Text; note_eff = T.Triv } } let unitE = { it = TupE []; at = no_region; - note = { S.note_typ = T.Tup []; - S.note_eff = T.Triv } + note = { note_typ = T.Tup []; note_eff = T.Triv } } let boolE b = { it = LitE (BoolLit b); at = no_region; - note = { S.note_typ = T.bool; - S.note_eff = T.Triv} + note = { note_typ = T.bool; note_eff = T.Triv} } let callE exp1 ts exp2 = @@ -155,23 +146,28 @@ let callE exp1 ts exp2 = let _, _, _, ret_ty = T.as_func_sub cc.Call_conv.sort (List.length ts) fun_ty in { it = CallE (cc, exp1, ts, exp2); at = no_region; - note = { S.note_typ = T.open_ ts ret_ty; - S.note_eff = max_eff (eff exp1) (eff exp2) } + note = { + note_typ = T.open_ ts ret_ty; + note_eff = max_eff (eff exp1) (eff exp2) + } } let ifE exp1 exp2 exp3 typ = { it = IfE (exp1, exp2, exp3); at = no_region; - note = { S.note_typ = typ; - S.note_eff = max_eff (eff exp1) (max_eff (eff exp2) (eff exp3)) - } + note = { + note_typ = typ; + note_eff = max_eff (eff exp1) (max_eff (eff exp2) (eff exp3)) + } } let dotE exp name typ = { it = DotE (exp, name); at = no_region; - note = { S.note_typ = typ; - S.note_eff = eff exp } + note = { + note_typ = typ; + note_eff = eff exp + } } let switch_optE exp1 exp2 pat exp3 typ1 = @@ -192,9 +188,10 @@ let switch_optE exp1 exp2 pat exp3 typ1 = note = () }] ); at = no_region; - note = { S.note_typ = typ1; - S.note_eff = max_eff (eff exp1) (max_eff (eff exp2) (eff exp3)) - } + note = { + note_typ = typ1; + note_eff = max_eff (eff exp1) (max_eff (eff exp2) (eff exp3)) + } } let switch_variantE exp1 cases typ1 = @@ -211,9 +208,10 @@ let switch_variantE exp1 cases typ1 = cases ); at = no_region; - note = { S.note_typ = typ1; - S.note_eff = List.fold_left max_eff (eff exp1) (List.map (fun (l,p,e) -> eff e) cases) - } + note = { + note_typ = typ1; + note_eff = List.fold_left max_eff (eff exp1) (List.map (fun (l,p,e) -> eff e) cases) + } } let tupE exps = @@ -221,28 +219,32 @@ let tupE exps = let eff = List.fold_left max_eff T.Triv effs in { it = TupE exps; at = no_region; - note = { S.note_typ = T.Tup (List.map typ exps); - S.note_eff = eff } + note = { + note_typ = T.Tup (List.map typ exps); + note_eff = eff + } } let breakE l exp = { it = BreakE (l, exp); at = no_region; - note = { S.note_eff = eff exp; - S.note_typ = T.Non } + note = { + note_eff = eff exp; + note_typ = T.Non + } } let retE exp = { it = RetE exp; at = no_region; - note = { S.note_eff = eff exp; - S.note_typ = T.Non } + note = { note_eff = eff exp; + note_typ = T.Non } } let immuteE e = { e with - note = { S.note_eff = eff e; - S.note_typ = T.as_immut (typ e) } + note = { note_eff = eff e; + note_typ = T.as_immut (typ e) } } @@ -250,23 +252,23 @@ let assignE exp1 exp2 = assert (T.is_mut (typ exp1)); { it = AssignE (exp1, exp2); at = no_region; - note = { S.note_eff = Effect.max_eff (eff exp1) (eff exp2); - S.note_typ = T.unit } + note = { note_eff = Ir_effect.max_eff (eff exp1) (eff exp2); + note_typ = T.unit } } let labelE l typ exp = { it = LabelE (l, typ, exp); at = no_region; - note = { S.note_eff = eff exp; - S.note_typ = typ } + note = { note_eff = eff exp; + note_typ = typ } } (* Used to desugar for loops, while loops and loop-while loops. *) let loopE exp = { it = LoopE exp; at = no_region; - note = { S.note_eff = eff exp ; - S.note_typ = T.Non } + note = { note_eff = eff exp ; + note_typ = T.Non } } let declare_idE x typ exp1 = @@ -278,15 +280,15 @@ let declare_idE x typ exp1 = let define_idE x mut exp1 = { it = DefineE (x, mut, exp1); at = no_region; - note = { S.note_typ = T.unit; - S.note_eff = T.Triv} + note = { note_typ = T.unit; + note_eff = T.Triv} } let newObjE sort ids typ = { it = NewObjE (sort, ids, typ); at = no_region; - note = { S.note_typ = typ; - S.note_eff = T.Triv } + note = { note_typ = typ; + note_eff = T.Triv } } @@ -340,7 +342,7 @@ let funcE name t x exp = exp' ); at = no_region; - note = { S.note_eff = T.Triv; S.note_typ = t } + note = { note_eff = T.Triv; note_typ = t } }) let nary_funcE name t xs exp = @@ -358,7 +360,7 @@ let nary_funcE name t xs exp = exp ); at = no_region; - note = { S.note_eff = T.Triv; S.note_typ = t } + note = { note_eff = T.Triv; note_typ = t } }) (* Mono-morphic function declaration, sharing inferred from f's type *) @@ -426,8 +428,8 @@ let ( -*- ) exp1 exp2 = let cc = Call_conv.call_conv_of_typ (typ exp1) in { it = CallE (cc, exp1, [], exp2); at = no_region; - note = {S.note_typ = T.seq ts2; - S.note_eff = max_eff (eff exp1) (eff exp2)} + note = {note_typ = T.seq ts2; + note_eff = max_eff (eff exp1) (eff exp2)} } | typ1 -> failwith (Printf.sprintf "Impossible: \n func: %s \n : %s arg: \n %s" @@ -494,7 +496,7 @@ let forE pat exp1 exp2 = } } *) let lab = fresh_id "done" () in - let ty1 = exp1.note.S.note_typ in + let ty1 = exp1.note.note_typ in let _, tfs = T.as_obj_sub "next" ty1 in let tnxt = Lib.Option.value (T.lookup_val_field "next" tfs) in let nxt = fresh_var "nxt" tnxt in diff --git a/src/as_ir/dune b/src/as_ir/dune index 462598f3b1b..e08e318a43d 100644 --- a/src/as_ir/dune +++ b/src/as_ir/dune @@ -1,4 +1,4 @@ (library (name as_ir) - (libraries lib as_types as_values as_frontend) + (libraries lib as_types as_values) ) diff --git a/src/as_ir/ir.ml b/src/as_ir/ir.ml index 7b62def7eb6..e04d743b318 100644 --- a/src/as_ir/ir.ml +++ b/src/as_ir/ir.ml @@ -1,6 +1,5 @@ open As_types open As_values -open As_frontend (* TODO *) type id = string @@ -20,9 +19,9 @@ type lit = | TextLit of string (* Patterns *) -type type_note = Syntax.typ_note = {note_typ : Type.typ; note_eff : Type.eff} +type typ_note = {note_typ : Type.typ; note_eff : Type.eff} -type 'a phrase = ('a, Syntax.typ_note) Source.annotated_phrase +type 'a phrase = ('a, typ_note) Source.annotated_phrase type typ_bind' = {con : Type.con; bound : Type.typ} type typ_bind = typ_bind' Source.phrase diff --git a/src/as_ir/ir_effect.mli b/src/as_ir/ir_effect.mli index 4a55e902ddf..e6a52ba911c 100644 --- a/src/as_ir/ir_effect.mli +++ b/src/as_ir/ir_effect.mli @@ -1,6 +1,5 @@ -open As_frontend -open Syntax open Source +open Ir open As_types.Type val max_eff : eff -> eff -> eff diff --git a/src/as_types/arrange_type.ml b/src/as_types/arrange_type.ml index a3bc3f92358..1a9ea33babb 100644 --- a/src/as_types/arrange_type.ml +++ b/src/as_types/arrange_type.ml @@ -4,17 +4,17 @@ open Wasm.Sexpr let ($$) head inner = Node (head, inner) let sharing sh = match sh with - | Type.Local -> "Local" - | Type.Sharable -> "Sharable" + | Local -> "Local" + | Sharable -> "Sharable" let control c = match c with - | Type.Returns -> "Returns" - | Type.Promises -> "Promises" + | Returns -> "Returns" + | Promises -> "Promises" let obj_sort s = match s with - | Type.Object sh -> Atom ("Object " ^ sharing sh) - | Type.Actor -> Atom "Actor" - | Type.Module -> Atom "Module" + | Object sh -> Atom ("Object " ^ sharing sh) + | Actor -> Atom "Actor" + | Module -> Atom "Module" let prim p = match p with | Null -> Atom "Null" diff --git a/src/as_values/arrange_ops.ml b/src/as_values/arrange_ops.ml new file mode 100644 index 00000000000..b41992c3d81 --- /dev/null +++ b/src/as_values/arrange_ops.ml @@ -0,0 +1,32 @@ +open Wasm.Sexpr +open Operator + +let unop uo = match uo with + | PosOp -> Atom "PosOp" + | NegOp -> Atom "NegOp" + | NotOp -> Atom "NotOp" + +let binop bo = match bo with + | AddOp -> Atom "AddOp" + | SubOp -> Atom "SubOp" + | MulOp -> Atom "MulOp" + | DivOp -> Atom "DivOp" + | ModOp -> Atom "ModOp" + | AndOp -> Atom "AndOp" + | OrOp -> Atom "OrOp" + | XorOp -> Atom "XorOp" + | ShLOp -> Atom "ShiftLOp" + | UShROp -> Atom "UnsignedShiftROp" + | SShROp -> Atom "SignedShiftROp" + | RotLOp -> Atom "RotLOp" + | RotROp -> Atom "RotROp" + | CatOp -> Atom "CatOp" + | PowOp -> Atom "PowOp" + +let relop ro = match ro with + | EqOp -> Atom "EqOp" + | NeqOp -> Atom "NeqOp" + | LtOp -> Atom "LtOp" + | GtOp -> Atom "GtOp" + | LeOp -> Atom "LeOp" + | GeOp -> Atom "GeOp" diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index ba8cdef1f24..5ced4158f36 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -4414,7 +4414,7 @@ let compile_unop env t op = | _ -> (* NB: Must not use todo_trap_SR here, as the SR.t here is also passed to `compile_exp_as`, which does not take SR.Unreachable. *) - todo "compile_unop" (As_frontend.Arrange.unop op) (SR.Vanilla, E.trap_with env "TODO: compile_unop") + todo "compile_unop" (Arrange_ops.unop op) (SR.Vanilla, E.trap_with env "TODO: compile_unop") (* This returns a single StackRep, to be used for both arguments and the result. One could imagine operators that require or produce different StackReps, @@ -4513,7 +4513,7 @@ let rec compile_binop env t op = sanitize_word_result ty)) | Type.Prim Type.Text, CatOp -> Text.concat env - | _ -> todo_trap env "compile_binop" (As_frontend.Arrange.binop op) + | _ -> todo_trap env "compile_binop" (Arrange_ops.binop op) ) let compile_eq env t = match t with @@ -4522,7 +4522,7 @@ let compile_eq env t = match t with | Type.(Prim (Nat | Int)) -> BigNum.compile_eq env | Type.(Prim Word64) -> G.i (Compare (Wasm.Values.I64 I64Op.Eq)) | Type.(Prim (Word8 | Word16 | Word32 | Char)) -> G.i (Compare (Wasm.Values.I32 I32Op.Eq)) - | _ -> todo_trap env "compile_eq" (As_frontend.Arrange.relop Operator.EqOp) + | _ -> todo_trap env "compile_eq" (Arrange_ops.relop Operator.EqOp) let get_relops = Operator.(function | GeOp -> Ge, I64Op.GeU, I32Op.GeU, I32Op.GeS @@ -4549,7 +4549,7 @@ let compile_relop env t op = G.if_ (StackRep.to_block_type env SR.bool) (Bool.lit false) (Bool.lit true) | Type.Prim Type.(Nat | Int | Word8 | Word16 | Word32 | Word64 | Char as t1), op1 -> compile_comparison env t1 op1 - | _ -> todo_trap env "compile_relop" (As_frontend.Arrange.relop op) + | _ -> todo_trap env "compile_relop" (Arrange_ops.relop op) (* compile_load_field implements the various “virtual fields”, which we currently have for arrays and text. diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index e72e63e5ed9..04c4a43f456 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -4,7 +4,6 @@ open As_ir open Ir open Source -open As_frontend module V = Value module T = Type @@ -249,11 +248,11 @@ let interpret_lit env lit : V.value = let check_call_conv exp call_conv = let open Call_conv in - let exp_call_conv = call_conv_of_typ exp.note.Syntax.note_typ in + let exp_call_conv = call_conv_of_typ exp.note.note_typ in if not (exp_call_conv = call_conv) then failwith (Printf.sprintf "call_conv mismatch: function %s of type %s expecting %s, found %s" (Wasm.Sexpr.to_string 80 (Arrange_ir.exp exp)) - (T.string_of_typ exp.note.Syntax.note_typ) + (T.string_of_typ exp.note.note_typ) (string_of_call_conv exp_call_conv) (string_of_call_conv call_conv)) @@ -283,7 +282,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = match exp.it with | PrimE s -> let at = exp.at in - let t = exp.note.Syntax.note_typ in + let t = exp.note.note_typ in let cc = call_conv_of_typ t in k (V.Func (cc, extended_prim env s t at)) | VarE id -> diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index b8e268e888f..bc416ccb6b1 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -32,9 +32,17 @@ let apply_sign op l = Syntax.(match op, l with | _, _ -> raise (Invalid_argument "Invalid signed pattern") ) -let phrase f x = { x with it = f x.it } +let phrase f x = { x with it = f x.it } -let phrase' f x = { x with it = f x.at x.note x.it } +let typ_note : S.typ_note -> I.typ_note = + fun {S.note_typ;S.note_eff} -> {I.note_typ;I.note_eff} + +let phrase' f x = + { x with it = f x.at x.note x.it } + +let typed_phrase' f x = + let n' = typ_note x.note in + { x with it = f x.at n' x.it; note = n' } let rec exps es = List.map exp es @@ -42,7 +50,7 @@ and exp e = (* We short-cut AnnotE here, so that we get the position of the inner expression *) match e.it with | S.AnnotE (e,_) -> exp e - | _ -> phrase' exp' e + | _ -> typed_phrase' exp' e and exp' at note = function | S.PrimE p -> I.PrimE p @@ -60,7 +68,7 @@ and exp' at note = function | S.ProjE (e, i) -> I.ProjE (exp e, i) | S.OptE e -> I.OptE (exp e) | S.ObjE (s, es) -> - obj at s None es note.S.note_typ + obj at s None es note.I.note_typ | S.TagE (c, e) -> I.TagE (c.it, exp e) | S.DotE (e, x) -> let n = x.it in @@ -70,11 +78,11 @@ and exp' at note = function end | S.AssignE (e1, e2) -> I.AssignE (exp e1, exp e2) | S.ArrayE (m, es) -> - let t = T.as_array note.S.note_typ in + let t = T.as_array note.I.note_typ in I.ArrayE (mut m, T.as_immut t, exps es) | S.IdxE (e1, e2) -> I.IdxE (exp e1, exp e2) | S.FuncE (name, s, tbs, p, ty, e) -> - let cc = Call_conv.call_conv_of_typ note.S.note_typ in + let cc = Call_conv.call_conv_of_typ note.I.note_typ in let args, wrap = to_args cc p in let tys = if cc.Call_conv.n_res = 1 then [ty.note] else T.as_seq ty.note in I.FuncE (name, cc, typ_binds tbs, args, tys, wrap (exp e)) @@ -88,7 +96,7 @@ and exp' at note = function I.CallE (cc, exp e1, inst, exp e2) | S.BlockE [] -> I.TupE [] | S.BlockE [{it = S.ExpD e; _}] -> (exp e).it - | S.BlockE ds -> I.BlockE (block (T.is_unit note.S.note_typ) ds) + | S.BlockE ds -> I.BlockE (block (T.is_unit note.I.note_typ) ds) | S.NotE e -> I.IfE (exp e, falseE, trueE) | S.AndE (e1, e2) -> I.IfE (exp e1, exp e2, falseE) | S.OrE (e1, e2) -> I.IfE (exp e1, trueE, exp e2) @@ -230,9 +238,9 @@ and dec' at n d = match d with it = I.FuncE (id.it, cc, typ_binds tbs, args, [obj_typ], wrap { it = obj at s (Some self_id) es obj_typ; at = at; - note = { S.note_typ = obj_typ; S.note_eff = T.Triv } }); + note = { I.note_typ = obj_typ; I.note_eff = T.Triv } }); at = at; - note = { S.note_typ = fun_typ; S.note_eff = T.Triv } + note = { I.note_typ = fun_typ; I.note_eff = T.Triv } } in I.LetD (varPat, fn) From e36089dadd31e74c6803bb80eb7b20f693d3f4e5 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 13 Jun 2019 17:50:47 +0200 Subject: [PATCH 0168/1176] Also group numbers in Arrange_ir overlooked due to copying code before merging #489. --- src/as_ir/arrange_ir.ml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/as_ir/arrange_ir.ml b/src/as_ir/arrange_ir.ml index 474ad81fe37..e338a6e6b1f 100644 --- a/src/as_ir/arrange_ir.ml +++ b/src/as_ir/arrange_ir.ml @@ -72,13 +72,13 @@ and lit (l:lit) = match l with | NullLit -> Atom "NullLit" | BoolLit true -> "BoolLit" $$ [ Atom "true" ] | BoolLit false -> "BoolLit" $$ [ Atom "false" ] - | NatLit n -> "NatLit" $$ [ Atom (Value.Nat.to_string n) ] - | IntLit i -> "IntLit" $$ [ Atom (Value.Int.to_string i) ] - | Word8Lit w -> "Word8Lit" $$ [ Atom (Value.Word8.to_string_u w) ] - | Word16Lit w -> "Word16Lit" $$ [ Atom (Value.Word16.to_string_u w) ] - | Word32Lit w -> "Word32Lit" $$ [ Atom (Value.Word32.to_string_u w) ] - | Word64Lit w -> "Word64Lit" $$ [ Atom (Value.Word64.to_string_u w) ] - | FloatLit f -> "FloatLit" $$ [ Atom (Value.Float.to_string f) ] + | NatLit n -> "NatLit" $$ [ Atom (Value.Nat.to_pretty_string n) ] + | IntLit i -> "IntLit" $$ [ Atom (Value.Int.to_pretty_string i) ] + | Word8Lit w -> "Word8Lit" $$ [ Atom (Value.Word8.to_pretty_string w) ] + | Word16Lit w -> "Word16Lit" $$ [ Atom (Value.Word16.to_pretty_string w) ] + | Word32Lit w -> "Word32Lit" $$ [ Atom (Value.Word32.to_pretty_string w) ] + | Word64Lit w -> "Word64Lit" $$ [ Atom (Value.Word64.to_pretty_string w) ] + | FloatLit f -> "FloatLit" $$ [ Atom (Value.Float.to_pretty_string f) ] | CharLit c -> "CharLit" $$ [ Atom (string_of_int c) ] | TextLit t -> "TextLit" $$ [ Atom t ] From 1026592532d8466d4fe02b3d809f50f87fe4e4d9 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 13 Jun 2019 20:15:14 +0200 Subject: [PATCH 0169/1176] nix: Avoid regex whitelists (#488) and instead just use the output of `git ls-files`. This encourages better subdirectory discipline, so now we have seperate derivations for `samples` and `tests`. Also, moves `guide.md` to `guide/` This is the same approach as implemented for `dev` in https://github.com/dfinity-lab/dev/pull/1041 --- default.nix | 159 ++++++++++--------------------------- guide/Makefile | 4 +- {design => guide}/guide.md | 0 nix/gitSource.nix | 94 ++++++++++++++++++++++ 4 files changed, 139 insertions(+), 118 deletions(-) rename {design => guide}/guide.md (100%) create mode 100644 nix/gitSource.nix diff --git a/default.nix b/default.nix index 73c29a0edeb..c1b86775b12 100644 --- a/default.nix +++ b/default.nix @@ -8,14 +8,7 @@ let llvm = import ./nix/llvm.nix { system = nixpkgs.system; }; in let stdenv = nixpkgs.stdenv; in -let sourceByRegex = src: regexes: builtins.path - { name = "actorscript"; - path = src; - filter = path: type: - let relPath = nixpkgs.lib.removePrefix (toString src + "/") (toString path); in - let match = builtins.match (nixpkgs.lib.strings.concatStringsSep "|" regexes); in - ( type == "directory" && match (relPath + "/") != null || match relPath != null); - }; in +let subpath = p: import ./nix/gitSource.nix p; in let ocaml_wasm = import ./nix/ocaml-wasm.nix { inherit (nixpkgs) stdenv fetchFromGitHub ocaml; @@ -63,43 +56,6 @@ let commonBuildInputs = [ ]; in let - test_files = [ - "test/" - "test/.*Makefile.*" - "test/quick.mk" - "test/(fail|run|run-dfinity|repl|ld|idl)/" - "test/(fail|run|run-dfinity|repl|ld|idl)/lib/" - "test/(fail|run|run-dfinity|repl|ld|idl)/lib/dir/" - "test/(fail|run|run-dfinity|repl|ld|idl)/.*.as" - "test/(fail|run|run-dfinity|repl|ld|idl)/.*.sh" - "test/(fail|run|run-dfinity|repl|ld|idl)/.*.did" - "test/(fail|run|run-dfinity|repl|ld|idl)/[^/]*.wat" - "test/(fail|run|run-dfinity|repl|ld|idl)/[^/]*.c" - "test/(fail|run|run-dfinity|repl|ld|idl)/ok/" - "test/(fail|run|run-dfinity|repl|ld|idl)/ok/.*.ok" - "test/.*.sh" - ]; - samples_files = [ - "samples/" - "samples/.*" - ]; - stdlib_files = [ - "stdlib/" - "stdlib/.*Makefile.*" - "stdlib/.*.as" - "stdlib/examples/" - "stdlib/examples/.*.as" - "stdlib/examples/produce-exchange/" - "stdlib/examples/produce-exchange/.*.as" - "stdlib/examples/produce-exchange/test/" - "stdlib/examples/produce-exchange/test/.*.as" - ]; - stdlib_doc_files = [ - "stdlib/.*\.py" - "stdlib/README.md" - "stdlib/examples/produce-exchange/README.md" - ]; - libtommath = nixpkgs.fetchFromGitHub { owner = "libtom"; repo = "libtommath"; @@ -123,13 +79,7 @@ rec { rts = stdenv.mkDerivation { name = "asc-rts"; - src = sourceByRegex ./rts [ - "rts.c" - "Makefile" - "includes/" - "includes/.*.h" - ]; - + src = subpath ./rts; nativeBuildInputs = [ nixpkgs.makeWrapper ]; buildInputs = llvmBuildInputs; @@ -148,16 +98,7 @@ rec { asc-bin = stdenv.mkDerivation { name = "asc-bin"; - src = sourceByRegex ./src [ - "Makefile" - "dune-project" - "dune" - "[a-z].*/" - ".*.ml" - ".*.mly" - ".*.mll" - ".*/dune" - ]; + src = subpath ./src; buildInputs = commonBuildInputs; @@ -183,12 +124,7 @@ rec { tests = stdenv.mkDerivation { name = "tests"; - - src = sourceByRegex ./. ( - test_files ++ - samples_files - ); - + src = subpath ./test; buildInputs = [ asc didc @@ -208,16 +144,40 @@ rec { export AS_LD=as-ld export DIDC=didc asc --version - make -C samples all '' + (if test-dvm then '' - make -C test parallel + make parallel '' else '' - make -C test quick + make quick ''); installPhase = '' - mkdir -p $out + touch $out + ''; + }; + + samples = stdenv.mkDerivation { + name = "samples"; + src = subpath ./samples; + buildInputs = + [ asc + didc + ocaml_wasm + nixpkgs.wabt + nixpkgs.bash + nixpkgs.perl + filecheck + ] ++ + (if test-dvm then [ real-dvm ] else []) ++ + llvmBuildInputs; + + buildPhase = '' + patchShebangs . + export ASC=asc + make all + ''; + installPhase = '' + touch $out ''; }; @@ -251,24 +211,11 @@ rec { didc = stdenv.mkDerivation { name = "didc"; - - src = sourceByRegex ./src [ - "Makefile" - "dune-project" - "dune" - "[a-z].*/" - ".*.ml" - ".*.mly" - ".*.mll" - ".*/dune" - ]; - + src = subpath ./src; buildInputs = commonBuildInputs; - buildPhase = '' make DUNE_OPTS="--display=short --profile release" didc ''; - installPhase = '' mkdir -p $out/bin cp --verbose --dereference didc $out/bin @@ -284,17 +231,7 @@ rec { users-guide = stdenv.mkDerivation { name = "users-guide"; - - src = sourceByRegex ./. [ - "design/" - "design/guide.md" - "guide/" - "guide/Makefile" - "guide/.*css" - "guide/.*md" - "guide/.*png" - ]; - + src = subpath ./guide; buildInputs = with nixpkgs; let tex = texlive.combine { @@ -308,13 +245,13 @@ rec { buildPhase = '' patchShebangs . - make -C guide + make ''; installPhase = '' mkdir -p $out - mv guide $out/ - rm $out/guide/Makefile + mv * $out/ + rm $out/Makefile mkdir -p $out/nix-support echo "report guide $out/guide index.html" >> $out/nix-support/hydra-build-products ''; @@ -323,50 +260,39 @@ rec { stdlib-reference = stdenv.mkDerivation { name = "stdlib-reference"; - - src = sourceByRegex ./. ( - stdlib_files ++ - stdlib_doc_files - ) + "/stdlib"; - + src = subpath ./stdlib; buildInputs = with nixpkgs; [ pandoc bash python ]; - buildPhase = '' patchShebangs . make alldoc ''; - installPhase = '' mkdir -p $out mv doc $out/ mkdir -p $out/nix-support echo "report docs $out/doc README.html" >> $out/nix-support/hydra-build-products ''; - forceShare = ["man"]; }; produce-exchange = stdenv.mkDerivation { name = "produce-exchange"; - src = sourceByRegex ./. ( - stdlib_files - ); - + src = subpath ./stdlib; buildInputs = [ asc ]; doCheck = true; buildPhase = '' - make -C stdlib ASC=asc OUTDIR=_out _out/ProduceExchange.wasm + make ASC=asc OUTDIR=_out _out/ProduceExchange.wasm ''; checkPhase = '' - make -C stdlib ASC=asc OUTDIR=_out _out/ProduceExchange.out + make ASC=asc OUTDIR=_out _out/ProduceExchange.out ''; installPhase = '' mkdir -p $out - cp stdlib/_out/ProduceExchange.wasm $out + cp _out/ProduceExchange.wasm $out ''; }; @@ -377,6 +303,7 @@ rec { js didc tests + samples rts stdlib-reference produce-exchange diff --git a/guide/Makefile b/guide/Makefile index 0461ed62ea1..b3e4391f316 100644 --- a/guide/Makefile +++ b/guide/Makefile @@ -2,7 +2,7 @@ all: index.html actorscript-guide.pdf as-slides.html SHELL=bash -index.html: ../design/guide.md pandoc.css inline-code.css +index.html: guide.md pandoc.css inline-code.css pandoc \ --toc \ --toc-depth 2 \ @@ -36,7 +36,7 @@ TEX_OPTIONS=\ --include-in-header=<(echo '\newunicodechar{█}{\textrm{\textfallback{█}}}') \ --include-in-header=<(echo '\newunicodechar{ツ}{\textrm{\textfallback{ツ}}}') \ -actorscript-guide.pdf: ../design/guide.md +actorscript-guide.pdf: guide.md if [ -n "$$NIX_FONTCONFIG_FILE" ]; then export FONTCONFIG_FILE="$$NIX_FONTCONFIG_FILE"; fi; \ pandoc \ --toc \ diff --git a/design/guide.md b/guide/guide.md similarity index 100% rename from design/guide.md rename to guide/guide.md diff --git a/nix/gitSource.nix b/nix/gitSource.nix new file mode 100644 index 00000000000..1af7959cec8 --- /dev/null +++ b/nix/gitSource.nix @@ -0,0 +1,94 @@ +# The function call +# +# gitSource ./toplevel subpath +# +# creates a Nix store path of ./toplevel/subpath that includes only those files +# tracked by git. More precisely: mentioned in the git index (i.e. git add is enough +# to get them to be included, you do not have to commit). +# +# This is a whitelist-based alternative to manually listing files or using +# nix-gitignore. + +# Internally, it works by calling git ls-files at evaluation time. To +# avoid copying all of `.git` to the git store, it only copies the least amount +# of files necessary for `git ls-files` to work; this is a bit fragile, but +# very fast. + +with builtins; + +# We read the git index once, before getting the subdir parameter, so that it +# is shared among multiple invocations of gitSource: + +let + filter_from_list = root: files: + let + all_paren_dirs = p: + if p == "." || p == "/" + then [] + else [ p ] ++ all_paren_dirs (dirOf p); + + whitelist_set = listToAttrs ( + concatMap (p: + let full_path = toString (root + "/${p}"); in + map (p': { name = p'; value = true; }) (all_paren_dirs full_path) + ) files + ); + in + p: t: hasAttr (toString p) whitelist_set; + + has_prefix = prefix: s: + prefix == builtins.substring 0 (builtins.stringLength prefix) s; + remove_prefix = prefix: s: + builtins.substring + (builtins.stringLength prefix) + (builtins.stringLength s - builtins.stringLength prefix) + s; + + lines = s: filter (x : x != [] && x != "") (split "\n" s); +in + +if builtins.pathExists ../.git +then + let + nixpkgs = (import ./nixpkgs.nix).nixpkgs {}; + + git_dir = + if builtins.pathExists ../.git/index + then ../.git + else # likely a git worktree, so follow the indirection + let + git_content = lines (readFile ./../.git); + first_line = head git_content; + prefix = "gitdir: "; + ok = length git_content == 1 && has_prefix prefix first_line; + in + if ok + then /. + remove_prefix prefix first_line + else abort "gitSource.nix: Cannot parse ${toString ./../.git}"; + + whitelist_file = + nixpkgs.runCommand "git-ls-files" {envVariable = true;} '' + cp -v ${git_dir + "/index"} index + echo "ref: refs/heads/master" > HEAD + mkdir objects refs + ${nixpkgs.git}/bin/git --git-dir . ls-files > $out + ''; + + whitelist = lines (readFile (whitelist_file.out)); + + filter = filter_from_list ../. whitelist; + in + subdir: path { + name = baseNameOf (toString subdir); + path = if isString subdir then (../. + "/${subdir}") else subdir; + filter = filter; + } + +else + trace "gitSource.nix: ${toString ../.} does not seem to be a git repository,\nassuming it is a clean checkout." ( + subdir: path { + name = baseNameOf (toString subdir); + path = if isString subdir then (../. + "/${subdir}") else subdir; + } + ) + From 1aac39c21dc604e4dd5f30d373b5a91386f00f8f Mon Sep 17 00:00:00 2001 From: Paul Young Date: Fri, 14 Jun 2019 13:50:31 +0100 Subject: [PATCH 0170/1176] Respond to further module reorganization --- src/languageServer/dune | 2 +- src/languageServer/languageServer.ml | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/languageServer/dune b/src/languageServer/dune index 563d5b72663..99300e95f16 100644 --- a/src/languageServer/dune +++ b/src/languageServer/dune @@ -1,4 +1,4 @@ (library (name languageServer) - (libraries aslib base lsp) + (libraries base lang_utils lsp pipeline) ) diff --git a/src/languageServer/languageServer.ml b/src/languageServer/languageServer.ml index bae62920f44..cb658bcf82c 100644 --- a/src/languageServer/languageServer.ml +++ b/src/languageServer/languageServer.ml @@ -1,8 +1,5 @@ -module Diag = Aslib.Diag module Lsp_j = Lsp.Lsp_j module Lsp_t = Lsp.Lsp_t -module Pipeline = Aslib.Pipeline -module Source = Aslib.Source (* Ideally the following functions would be in the `Lsp` module, but doing so creates a circular dependency with the `Lsp_t` module generated by ATD. From 952f01f4b94d49f9e389715ead47f8f4666b3353 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Fri, 14 Jun 2019 14:34:28 +0100 Subject: [PATCH 0171/1176] Move language server to as-ide executable --- default.nix | 17 +++++++++++++++++ src/Makefile | 12 +++++++++--- src/Structure.md | 4 ++++ src/exes/as_ide.ml | 2 ++ src/exes/asc.ml | 2 -- src/exes/dune | 7 ++++++- 6 files changed, 38 insertions(+), 6 deletions(-) create mode 100644 src/exes/as_ide.ml diff --git a/default.nix b/default.nix index 2a5008c4953..1fb4495e7ff 100644 --- a/default.nix +++ b/default.nix @@ -158,6 +158,23 @@ rec { ''; }; + as-ide = stdenv.mkDerivation { + name = "as-ide"; + + src = subpath ./src; + + buildInputs = commonBuildInputs; + + buildPhase = '' + make DUNE_OPTS="--display=short --profile release" as-ide + ''; + + installPhase = '' + mkdir -p $out/bin + cp --verbose --dereference as-ide $out/bin + ''; + }; + samples = stdenv.mkDerivation { name = "samples"; src = subpath ./samples; diff --git a/src/Makefile b/src/Makefile index 93ae13c4d3b..844c9d6219d 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2,6 +2,7 @@ # dependency tracking makefile, it just # calls `dune` +AS_IDE_TARGET = _build/default/exes/as_ide.exe AS_LD_TARGET = _build/default/exes/as_ld.exe ASC_TARGET = _build/default/exes/asc.exe DIDC_TARGET = _build/default/exes/didc.exe @@ -9,15 +10,16 @@ ASC_JS_TARGET = _build/default/exes/as_js.bc.js DUNE_OPTS ?= -ALL_TARGETS = $(AS_LD_TARGET) $(ASC_TARGET) $(ASC_JS_TARGET) $(DIDC_TARGET) +ALL_TARGETS = $(AS_IDE_TARGET) $(AS_LD_TARGET) $(ASC_TARGET) $(ASC_JS_TARGET) $(DIDC_TARGET) -.PHONY: all clean asc as-ld asc.js didc +.PHONY: all clean asc as-ide as-ld asc.js didc # This targets is spelled out so that `make` # only invokes `dune` once, much faster all: dune build $(DUNE_OPTS) $(ALL_TARGETS) @ln -fs $(ASC_TARGET) asc + @ln -fs $(AS_IDE_TARGET) as-ide @ln -fs $(AS_LD_TARGET) as-ld @ln -fs $(ASC_JS_TARGET) asc.js @ln -fs $(DIDC_TARGET) didc @@ -26,6 +28,10 @@ asc: dune build $(DUNE_OPTS) $(ASC_TARGET) @ln -fs $(ASC_TARGET) asc +as-ide: + dune build $(DUNE_OPTS) $(AS_IDE_TARGET) + @ln -fs $(AS_IDE_TARGET) as-ide + as-ld: dune build $(DUNE_OPTS) $(AS_LD_TARGET) @ln -fs $(AS_LD_TARGET) as-ld @@ -39,5 +45,5 @@ didc: @ln -fs $(DIDC_TARGET) didc clean: - rm -f asc as-ld asc.js didc + rm -f asc as-ide as-ld asc.js didc dune clean diff --git a/src/Structure.md b/src/Structure.md index eb340e62b63..3d09b344314 100644 --- a/src/Structure.md +++ b/src/Structure.md @@ -106,6 +106,10 @@ actual functionality is easily shared. The ActorScript compiler + * `as-ide` (using `languageServer/`) + + The ActorScript language server + * `as.js` (using `pipeline/`) The ActorScript compiler, as a JS library diff --git a/src/exes/as_ide.ml b/src/exes/as_ide.ml new file mode 100644 index 00000000000..6919193ee44 --- /dev/null +++ b/src/exes/as_ide.ml @@ -0,0 +1,2 @@ +let () = + LanguageServer.start () diff --git a/src/exes/asc.ml b/src/exes/asc.ml index f128e4316d8..39a080e27a9 100644 --- a/src/exes/asc.ml +++ b/src/exes/asc.ml @@ -54,8 +54,6 @@ let argspec = Arg.align "-dl", Arg.Set Flags.dump_lowering, " dump intermediate representation "; "-no-check-ir", Arg.Clear Flags.check_ir, " do not check intermediate code"; "--disable-prelude", Arg.Clear Flags.prelude, " disable prelude"; - - "-ide", Arg.Unit (fun () -> ignore (LanguageServer.start ()); ()), " start the language server" ] diff --git a/src/exes/dune b/src/exes/dune index 5b7a315d8e3..060a1f91373 100644 --- a/src/exes/dune +++ b/src/exes/dune @@ -1,7 +1,12 @@ (executable (name asc) (modules asc) - (libraries languageServer pipeline) + (libraries pipeline) +) +(executable + (name as_ide) + (modules as_ide) + (libraries languageServer) ) (executable (name as_ld) From 181e42a61de81560fdd69d24938ba74b01b3eb88 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Fri, 14 Jun 2019 20:48:26 +0200 Subject: [PATCH 0172/1176] lsb_adjust correct bits when externalising Word8 --- src/codegen/compile.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 5ced4158f36..b5a18c0b506 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -2985,7 +2985,7 @@ module Serialization = struct compile_unboxed_const 2l ^^ advance_data_buf | Prim Word8 -> get_data_buf ^^ - get_x ^^ UnboxedSmallWord.lsb_adjust Word16 ^^ + get_x ^^ UnboxedSmallWord.lsb_adjust Word8 ^^ G.i (Store {ty = I32Type; align = 0; offset = 0l; sz = Some Wasm.Memory.Pack8}) ^^ compile_unboxed_const 1l ^^ advance_data_buf | Prim Bool -> From 00c7514ff8e0322480016076c42ee6d81cce4ed4 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity <48968912+chenyan-dfinity@users.noreply.github.com> Date: Fri, 14 Jun 2019 12:53:28 -0700 Subject: [PATCH 0173/1176] clean up idl compiler to use lang-utils (#503) --- src/idllib/arrange_idl.ml | 2 +- src/idllib/compile_js.ml | 4 +- src/idllib/diag.ml | 69 ------------------------- src/idllib/diag.mli | 49 ------------------ src/idllib/dom.ml | 19 ------- src/idllib/dune | 2 +- src/idllib/env_idl.ml | 36 ------------- src/idllib/parser.mly | 4 +- src/idllib/pipeline.ml | 5 +- src/idllib/pipeline.mli | 6 +-- src/idllib/source.ml | 24 --------- src/idllib/source.mli | 14 ----- src/idllib/{syntax_idl.ml => syntax.ml} | 0 src/idllib/{typing_idl.ml => typing.ml} | 6 +-- src/idllib/typing.mli | 10 ++++ src/idllib/typing_idl.mli | 10 ---- 16 files changed, 24 insertions(+), 236 deletions(-) delete mode 100644 src/idllib/diag.ml delete mode 100644 src/idllib/diag.mli delete mode 100644 src/idllib/dom.ml delete mode 100644 src/idllib/env_idl.ml delete mode 100644 src/idllib/source.ml delete mode 100644 src/idllib/source.mli rename src/idllib/{syntax_idl.ml => syntax.ml} (100%) rename src/idllib/{typing_idl.ml => typing.ml} (97%) create mode 100644 src/idllib/typing.mli delete mode 100644 src/idllib/typing_idl.mli diff --git a/src/idllib/arrange_idl.ml b/src/idllib/arrange_idl.ml index d66fcb4b4e8..22a028a5821 100644 --- a/src/idllib/arrange_idl.ml +++ b/src/idllib/arrange_idl.ml @@ -1,5 +1,5 @@ open Source -open Syntax_idl +open Syntax open Wasm.Sexpr let string_of_prim p = diff --git a/src/idllib/compile_js.ml b/src/idllib/compile_js.ml index cd1d90a4198..15db365ed43 100644 --- a/src/idllib/compile_js.ml +++ b/src/idllib/compile_js.ml @@ -1,6 +1,6 @@ open Format -open Syntax_idl +open Syntax open Source let str ppf s = pp_print_string ppf s; pp_print_cut ppf () @@ -115,7 +115,7 @@ let pp_prog ppf env prog = pp_actor ppf env prog.it.actor; pp_close_box ppf () -let compile (scope : Typing_idl.scope) (prog : Syntax_idl.prog) = +let compile (scope : Typing.scope) (prog : Syntax.prog) = let buf = Buffer.create 100 in let ppf = formatter_of_buffer buf in pp_prog ppf scope prog; diff --git a/src/idllib/diag.ml b/src/idllib/diag.ml deleted file mode 100644 index 274d6fbf4ad..00000000000 --- a/src/idllib/diag.ml +++ /dev/null @@ -1,69 +0,0 @@ -type severity = Warning | Error -type message = { - sev : severity; - at : Source.region; - cat : string; - text : string -} -type messages = message list - -type 'a result = ('a * messages, messages) Pervasives.result - -let return x = Ok (x, []) - -let map_result f = function - | Pervasives.Error msgs -> Pervasives.Error msgs - | Ok (x, msgs) -> Ok (f x, msgs) - -let ignore = function - | Pervasives.Error msgs -> Pervasives.Error msgs - | Ok (_, msgs) -> Ok ((), msgs) - -let bind x f = match x with - | Pervasives.Error msgs -> Pervasives.Error msgs - | Ok (y, msgs1) -> match f y with - | Ok (z, msgs2) -> Ok (z, msgs1 @ msgs2) - | Pervasives.Error msgs2 -> Error (msgs1 @ msgs2) - -let rec traverse : ('a -> 'b result) -> 'a list -> 'b list result = fun f -> function - | [] -> return [] - | x :: xs -> bind (f x) (fun y -> map_result (fun ys -> y :: ys) (traverse f xs)) - -let rec traverse_ : ('a -> unit result) -> 'a list -> unit result = fun f -> function - | [] -> return () - | x :: xs -> bind (f x) (fun () -> traverse_ f xs) - -type msg_store = messages ref -let add_msg s m = s := m :: !s -let add_msgs s ms = s := List.rev ms @ !s -let get_msgs s = List.rev !s - -let has_errors : messages -> bool = - List.fold_left (fun b msg -> b || msg.sev == Error) false - -let fatal_error at text = { sev = Error; at; cat = "fatal"; text } - -let string_of_message msg = - let label = match msg.sev with - | Error -> Printf.sprintf "%s error" msg.cat - | Warning -> "warning" in - Printf.sprintf "%s: %s, %s\n" (Source.string_of_region msg.at) label msg.text - -let print_message msg = - Printf.eprintf "%s%!" (string_of_message msg) - -let print_messages = List.iter print_message - -let with_message_store f = - let s = ref [] in - let r = f s in - let msgs = get_msgs s in - match r with - | Some x when not (has_errors msgs) -> Ok (x, msgs) - | _ -> Error msgs - - -let flush_messages : 'a result -> 'a result = function - | Pervasives.Error msgs -> print_messages msgs; Pervasives.Error [] - | Ok (x, msgs) -> print_messages msgs; Ok (x, []) - diff --git a/src/idllib/diag.mli b/src/idllib/diag.mli deleted file mode 100644 index 7c0f01ba776..00000000000 --- a/src/idllib/diag.mli +++ /dev/null @@ -1,49 +0,0 @@ -(* A common data type for diagnostic messages *) - -type severity = Warning | Error - -type message = { - sev : severity; - at : Source.region; - cat : string; - text : string -} - -type messages = message list - -val fatal_error : Source.region -> string -> message - -val string_of_message : message -> string -val print_message : message -> unit -val print_messages : messages -> unit - -(* -An extension of the built-in result type that also reports diagnostic messages. -Both success and failure can come with messages) -*) - -type 'a result = ('a * messages, messages) Pervasives.result - -val return : 'a -> 'a result -val bind : 'a result -> ('a -> 'b result) -> 'b result -val map_result : ('a -> 'b) -> 'a result -> 'b result -val ignore : 'a result -> unit result -val traverse: ('a -> 'b result) -> 'a list -> 'b list result -val traverse_: ('a -> unit result) -> 'a list -> unit result -val flush_messages : 'a result -> 'a result - -(* -An impure, but more more convenient interface. - -The 'result' type above is a monad, and would be sufficient to model, e.g., the -type checker. But since monadic style is cumbersome, the following definitions -provide an impure way of tracking messages. - -The function with_message_store returns Error if its argument returns None or -the reported messages contain an error. -*) - -type msg_store -val add_msg : msg_store -> message -> unit -val add_msgs : msg_store -> messages -> unit -val with_message_store : (msg_store -> 'a option) -> 'a result diff --git a/src/idllib/dom.ml b/src/idllib/dom.ml deleted file mode 100644 index 9bab5cd5611..00000000000 --- a/src/idllib/dom.ml +++ /dev/null @@ -1,19 +0,0 @@ -module type S = -sig - include Set.S - - exception Clash of elt - - val disjoint_add : elt -> t -> t (* raises Clash *) - val disjoint_union : t -> t -> t (* raises Clash *) -end - -module Make(X : Set.OrderedType) : S with type elt = X.t = -struct - include Set.Make(X) - - exception Clash of elt - - let disjoint_add e set = if mem e set then raise (Clash e) else add e set - let disjoint_union set1 set2 = fold (fun e s -> disjoint_add e s) set2 set1 -end diff --git a/src/idllib/dune b/src/idllib/dune index 88a321df719..4f9ec41278a 100644 --- a/src/idllib/dune +++ b/src/idllib/dune @@ -1,6 +1,6 @@ (library (name idllib) - (libraries wasm stdint) + (libraries wasm stdint lang_utils) ) (menhir diff --git a/src/idllib/env_idl.ml b/src/idllib/env_idl.ml deleted file mode 100644 index 95806081ba4..00000000000 --- a/src/idllib/env_idl.ml +++ /dev/null @@ -1,36 +0,0 @@ -module type S = -sig - include Map.S - - module Dom : Dom.S with type elt = key - - exception Clash of key - - val dom : 'a t -> Dom.t - val keys : 'a t -> key list - val from_list : (key * 'a) list -> 'a t - val from_list2 : key list -> 'a list -> 'a t - val adjoin : 'a t -> 'a t -> 'a t - val disjoint_add : key -> 'a -> 'a t -> 'a t (* raises Clash *) - val disjoint_union : 'a t -> 'a t -> 'a t (* raises Clash *) - val disjoint_unions : 'a t list -> 'a t (* raises Clash *) -end - -module Make(X : Map.OrderedType) : S with type key = X.t = -struct - include Map.Make(X) - - module Dom = Dom.Make(X) - - exception Clash of key - - let dom env = List.fold_left (fun s (x, _) -> Dom.add x s) Dom.empty (bindings env) - let keys env = List.map fst (bindings env) - let from_list kxs = List.fold_left (fun env (k, x) -> add k x env) empty kxs - let from_list2 ks xs = List.fold_left2 (fun env k x -> add k x env) empty ks xs - let adjoin env1 env2 = union (fun _ x1 x2 -> Some x2) env1 env2 - let disjoint_union env1 env2 = union (fun k _ _ -> raise (Clash k)) env1 env2 - let disjoint_unions envs = List.fold_left disjoint_union empty envs - let disjoint_add k x env = disjoint_union env (singleton k x) - -end diff --git a/src/idllib/parser.mly b/src/idllib/parser.mly index d9558bd06ab..1b15eae9eb7 100644 --- a/src/idllib/parser.mly +++ b/src/idllib/parser.mly @@ -1,6 +1,6 @@ %{ -open Syntax_idl +open Syntax open Source (* Position handling *) @@ -55,7 +55,7 @@ let record_fields fs = %token ID %token TEXT -%start parse_prog +%start parse_prog %% diff --git a/src/idllib/pipeline.ml b/src/idllib/pipeline.ml index 0bd19dda98b..03988e8a1ee 100644 --- a/src/idllib/pipeline.ml +++ b/src/idllib/pipeline.ml @@ -1,5 +1,4 @@ open Printf -module Typing = Typing_idl type stat_env = Typing.scope type env = stat_env @@ -26,7 +25,7 @@ let dump_prog flag prog = (* Parsing *) -type parse_result = Syntax_idl.prog Diag.result +type parse_result = Syntax.prog Diag.result let parse_with lexer parser name = try @@ -58,7 +57,7 @@ let initial_env = initial_stat_env (* Checking *) -type check_result = (Syntax_idl.prog * Typing.scope) Diag.result +type check_result = (Syntax.prog * Typing.scope) Diag.result let check_prog check senv name prog : Typing.scope Diag.result = diff --git a/src/idllib/pipeline.mli b/src/idllib/pipeline.mli index 1855f29954e..8f8f2a506e0 100644 --- a/src/idllib/pipeline.mli +++ b/src/idllib/pipeline.mli @@ -1,13 +1,13 @@ -type stat_env = Typing_idl.scope +type stat_env = Typing.scope type env = stat_env val initial_stat_env : stat_env val initial_env : env -type parse_result = Syntax_idl.prog Diag.result +type parse_result = Syntax.prog Diag.result val parse_file : string -> parse_result -type check_result = (Syntax_idl.prog * Typing_idl.scope) Diag.result +type check_result = (Syntax.prog * Typing.scope) Diag.result val check_file : string -> check_result type compile_js_result = (Buffer.t, Diag.messages) result diff --git a/src/idllib/source.ml b/src/idllib/source.ml deleted file mode 100644 index bc54030ea07..00000000000 --- a/src/idllib/source.ml +++ /dev/null @@ -1,24 +0,0 @@ -type pos = {file : string; line : int; column : int} -type region = {left : pos; right : pos} -type ('a, 'b) annotated_phrase = {at : region; it : 'a; mutable note: 'b} -type 'a phrase = ('a, unit) annotated_phrase - -let (@@) it at = {it; at; note = ()} - -(* Positions and regions *) - -let no_pos = {file = ""; line = 0; column = 0} -let no_region = {left = no_pos; right = no_pos} - -let span r1 r2 = {left = r1.left; right = r2.right} - -let string_of_pos pos = - if pos.line = -1 then - Printf.sprintf "0x%x" pos.column - else - string_of_int pos.line ^ "." ^ string_of_int (pos.column + 1) - -let string_of_region r = - if r.left.file = "" then "(unknown location)" else - r.left.file ^ ":" ^ string_of_pos r.left ^ - (if r.right = r.left then "" else "-" ^ string_of_pos r.right) diff --git a/src/idllib/source.mli b/src/idllib/source.mli deleted file mode 100644 index df5e731afe6..00000000000 --- a/src/idllib/source.mli +++ /dev/null @@ -1,14 +0,0 @@ -type pos = {file : string; line : int; column : int} -type region = {left : pos; right : pos} -type ('a, 'b) annotated_phrase = {at : region; it : 'a; mutable note: 'b} -type 'a phrase = ('a, unit) annotated_phrase - -val no_pos : pos -val no_region : region - -val string_of_pos : pos -> string -val string_of_region : region -> string - -val span : region -> region -> region - -val (@@) : 'a -> region -> 'a phrase diff --git a/src/idllib/syntax_idl.ml b/src/idllib/syntax.ml similarity index 100% rename from src/idllib/syntax_idl.ml rename to src/idllib/syntax.ml diff --git a/src/idllib/typing_idl.ml b/src/idllib/typing.ml similarity index 97% rename from src/idllib/typing_idl.ml rename to src/idllib/typing.ml index 5fb05a5bdf7..ce3eeedaffb 100644 --- a/src/idllib/typing_idl.ml +++ b/src/idllib/typing.ml @@ -1,10 +1,10 @@ -open Syntax_idl +open Syntax open Source open Arrange_idl (* Environments *) -module FieldEnv = Env_idl.Make(struct type t = Stdint.uint64 let compare = Stdint.Uint64.compare end) -module Env = Env_idl.Make(String) +module FieldEnv = Env.Make(struct type t = Stdint.uint64 let compare = Stdint.Uint64.compare end) +module Env = Env.Make(String) module TS = Set.Make(String) (* Error recovery *) diff --git a/src/idllib/typing.mli b/src/idllib/typing.mli new file mode 100644 index 00000000000..d72f09f07a7 --- /dev/null +++ b/src/idllib/typing.mli @@ -0,0 +1,10 @@ +module Env : Env.S with type key = string + +type typ_env = Syntax.typ Env.t + +type scope = typ_env + +val empty_scope : scope + +val check_prog : scope -> Syntax.prog -> scope Diag.result + diff --git a/src/idllib/typing_idl.mli b/src/idllib/typing_idl.mli deleted file mode 100644 index 9114e59e4cf..00000000000 --- a/src/idllib/typing_idl.mli +++ /dev/null @@ -1,10 +0,0 @@ -module Env : Env_idl.S with type key = string - -type typ_env = Syntax_idl.typ Env.t - -type scope = typ_env - -val empty_scope : scope - -val check_prog : scope -> Syntax_idl.prog -> scope Diag.result - From bbfc416475f5f0181b7ba81098a90bf679675198 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Fri, 14 Jun 2019 14:14:16 -0700 Subject: [PATCH 0174/1176] switch idl compiler to use idl_hash --- src/as_values/dune | 2 +- src/as_values/prim.ml | 2 +- src/codegen/compile.ml | 2 +- src/idllib/arrange_idl.ml | 2 +- src/{as_values => idllib}/idlHash.ml | 0 src/{as_values => idllib}/idlHash.mli | 0 src/idllib/parser.mly | 12 ++++++------ src/idllib/syntax.ml | 2 +- src/idllib/typing.ml | 2 +- test/idl/collision_fields2.did | 2 +- test/idl/ok/collision_fields2.tc.ok | 2 +- test/idl/ok/fields.js.ok | 4 ++-- 12 files changed, 16 insertions(+), 16 deletions(-) rename src/{as_values => idllib}/idlHash.ml (100%) rename src/{as_values => idllib}/idlHash.mli (100%) diff --git a/src/as_values/dune b/src/as_values/dune index efdce94254e..341f197eb55 100644 --- a/src/as_values/dune +++ b/src/as_values/dune @@ -1,4 +1,4 @@ (library (name as_values) - (libraries num wasm lib lang_utils as_types) + (libraries num wasm lib lang_utils as_types idllib) ) diff --git a/src/as_values/prim.ml b/src/as_values/prim.ml index 20575609b20..f81dfdd7c81 100644 --- a/src/as_values/prim.ml +++ b/src/as_values/prim.ml @@ -135,7 +135,7 @@ let prim = function in k (Text str) | "print" -> fun v k -> Printf.printf "%s%!" (as_text v); k unit | "rts_version" -> fun v k -> as_unit v; k (Text "0.1") - | "idlHash" -> fun v k -> let s = as_text v in k (Word32 (IdlHash.idl_hash s)) + | "idlHash" -> fun v k -> let s = as_text v in k (Word32 (Idllib.IdlHash.idl_hash s)) | "decodeUTF8" -> fun v k -> let s = as_text v in let open Int32 in diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 5ced4158f36..6a4d8206a05 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -2781,7 +2781,7 @@ module Serialization = struct let sort_by_hash fs = List.sort (fun (h1,_) (h2,_) -> unsigned_compare h1 h2) - (List.map (fun f -> (IdlHash.idl_hash f.Type.lab, f)) fs) + (List.map (fun f -> (Idllib.IdlHash.idl_hash f.Type.lab, f)) fs) (* Checks whether the serialization of a given type could contain references *) module TS = Set.Make (struct type t = Type.typ let compare = compare end) diff --git a/src/idllib/arrange_idl.ml b/src/idllib/arrange_idl.ml index 22a028a5821..3e320b2d65a 100644 --- a/src/idllib/arrange_idl.ml +++ b/src/idllib/arrange_idl.ml @@ -32,7 +32,7 @@ and id i = Atom i.it and tag i = Atom ("#" ^ i.it) let field_tag (tf : typ_field) - = tf.it.name.it ^ "(" ^ Stdint.Uint64.to_string tf.it.id ^ ")" + = tf.it.name.it ^ "(" ^ Int32.to_string tf.it.id ^ ")" let rec typ_field (tf : typ_field) = field_tag tf $$ [typ tf.it.typ] diff --git a/src/as_values/idlHash.ml b/src/idllib/idlHash.ml similarity index 100% rename from src/as_values/idlHash.ml rename to src/idllib/idlHash.ml diff --git a/src/as_values/idlHash.mli b/src/idllib/idlHash.mli similarity index 100% rename from src/as_values/idlHash.mli rename to src/idllib/idlHash.mli diff --git a/src/idllib/parser.mly b/src/idllib/parser.mly index 1b15eae9eb7..762c108fe59 100644 --- a/src/idllib/parser.mly +++ b/src/idllib/parser.mly @@ -31,7 +31,7 @@ let is_prim_typs t = List.assoc_opt t prim_typs let func_modes = ["oneway", Oneway; "pure", Pure] let get_func_mode m = List.assoc m func_modes -let hash name = Stdint.Uint64.of_int (Hashtbl.hash name) +let hash = IdlHash.idl_hash let record_fields fs = let rec go start fs = @@ -39,9 +39,9 @@ let record_fields fs = | [] -> [] | hd :: tl -> let field = hd start in - let next = Stdint.Uint64.succ field.it.id in + let next = Int32.succ field.it.id in field :: (go next tl) - in go Stdint.Uint64.zero fs + in go 0l fs %} %token EOF @@ -89,21 +89,21 @@ ref_typ : field_typ : | n=NAT COLON t=data_typ - { { id = Stdint.Uint64.of_string n; name = n @@ at $loc(n); typ = t } @@ at $sloc } + { { id = Int32.of_string n; name = n @@ at $loc(n); typ = t } @@ at $sloc } | name=name COLON t=data_typ { { id = hash name.it; name = name; typ = t } @@ at $sloc } record_typ : | f=field_typ { fun _ -> f } | t=data_typ - { fun x -> { id = x; name = Stdint.Uint64.to_string x @@ no_region; typ = t } @@ at $sloc } + { fun x -> { id = x; name = Int32.to_string x @@ no_region; typ = t } @@ at $sloc } variant_typ : | f=field_typ { f } | name=name { { id = hash name.it; name = name; typ = PrimT Null @@ no_region } @@ at $sloc } | n=NAT - { { id = Stdint.Uint64.of_string n; name = n @@ at $loc(n); typ = PrimT Null @@ no_region } @@ at $sloc } + { { id = Int32.of_string n; name = n @@ at $loc(n); typ = PrimT Null @@ no_region } @@ at $sloc } record_typs : | LCURLY fs=seplist(record_typ, SEMICOLON) RCURLY diff --git a/src/idllib/syntax.ml b/src/idllib/syntax.ml index 56ff920b732..324136353d3 100644 --- a/src/idllib/syntax.ml +++ b/src/idllib/syntax.ml @@ -39,7 +39,7 @@ and typ' = | PreT (* pre-type *) and typ_field = typ_field' Source.phrase -and typ_field' = { id : Stdint.uint64; name : id; typ : typ } +and typ_field' = { id : int32; name : id; typ : typ } and typ_meth = typ_meth' Source.phrase and typ_meth' = {var : id; meth : typ} diff --git a/src/idllib/typing.ml b/src/idllib/typing.ml index ce3eeedaffb..ec4c745fb9f 100644 --- a/src/idllib/typing.ml +++ b/src/idllib/typing.ml @@ -3,7 +3,7 @@ open Source open Arrange_idl (* Environments *) -module FieldEnv = Env.Make(struct type t = Stdint.uint64 let compare = Stdint.Uint64.compare end) +module FieldEnv = Env.Make(Int32) module Env = Env.Make(String) module TS = Set.Make(String) diff --git a/test/idl/collision_fields2.did b/test/idl/collision_fields2.did index f03bd2dcaa1..1e1dd9d1282 100644 --- a/test/idl/collision_fields2.did +++ b/test/idl/collision_fields2.did @@ -1,6 +1,6 @@ type A = record { "字段名":nat; - 994301184:nat; + 1832283146:nat; "字 段 名2":nat; "📦🍦":nat; }; diff --git a/test/idl/ok/collision_fields2.tc.ok b/test/idl/ok/collision_fields2.tc.ok index 7ff3a96b5e5..3e67f074ece 100644 --- a/test/idl/ok/collision_fields2.tc.ok +++ b/test/idl/ok/collision_fields2.tc.ok @@ -1 +1 @@ -collision_fields2.did:5.2-5.12: type error, field name 📦🍦 hash collision with field 994301184 +collision_fields2.did:5.2-5.12: type error, field name 📦🍦 hash collision with field 1832283146 diff --git a/test/idl/ok/fields.js.ok b/test/idl/ok/fields.js.ok index 1457a7325a2..3c40de2b530 100644 --- a/test/idl/ok/fields.js.ok +++ b/test/idl/ok/fields.js.ok @@ -1,8 +1,8 @@ const A = IDL.Obj({'0': IDL.Nat, '1': IDL.Nat, '2': IDL.Nat}) const B = IDL.Obj({'0': IDL.Arr(IDL.Nat8), '35': IDL.Arr(IDL.Nat8), '36': IDL.Nat, - '37': IDL.Nat, 'named_files': IDL.None, '653352244': IDL.Nat, - '653352245': IDL.Nat}) + '37': IDL.Nat, 'named_files': IDL.None, '-665008590': IDL.Nat, + '-665008589': IDL.Nat}) const C = IDL.Variant({'red': IDL.Unit, '4': IDL.Unit, '3': IDL.Unit, '2': IDL.Unit, '1': IDL.Unit, 'reserved': IDL.Unit, '10': IDL.Unit, 'green': IDL.Unit, From 3e9e6d60ea6d47ef508bdc16c0cb85884035cd9b Mon Sep 17 00:00:00 2001 From: Paul Young Date: Mon, 17 Jun 2019 16:03:47 +0100 Subject: [PATCH 0175/1176] Remove extra space character --- src/languageServer/languageServer.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/languageServer/languageServer.ml b/src/languageServer/languageServer.ml index cb658bcf82c..54a68083660 100644 --- a/src/languageServer/languageServer.ml +++ b/src/languageServer/languageServer.ml @@ -2,7 +2,7 @@ module Lsp_j = Lsp.Lsp_j module Lsp_t = Lsp.Lsp_t (* Ideally the following functions would be in the `Lsp` module, but doing so - creates a circular dependency with the `Lsp_t` module generated by ATD. + creates a circular dependency with the `Lsp_t` module generated by ATD. *) let jsonrpc_version : string = "2.0" From b810171b43e14cc2c7f81ff4a034bf5cb6244865 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Mon, 17 Jun 2019 10:43:03 -0700 Subject: [PATCH 0176/1176] remove stdint dependency from idllib --- src/idllib/dune | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/idllib/dune b/src/idllib/dune index 4f9ec41278a..2f5499a2b6b 100644 --- a/src/idllib/dune +++ b/src/idllib/dune @@ -1,6 +1,6 @@ (library (name idllib) - (libraries wasm stdint lang_utils) + (libraries wasm lang_utils) ) (menhir From 042777ddebf858fdc10643e58bba9ec7c301a3d4 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Mon, 17 Jun 2019 16:19:53 -0600 Subject: [PATCH 0177/1176] toArray profiling label --- stdlib/trie2.as | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/trie2.as b/stdlib/trie2.as index ac560a61dd1..b7a7f0b1dc9 100644 --- a/stdlib/trie2.as +++ b/stdlib/trie2.as @@ -998,7 +998,7 @@ type Trie3D = Trie >; let c = buildCount(tb); let a = Array_init(c, null); var i = 0; - func rec(tb:TrieBuild) { + func rec(tb:TrieBuild) = label profile_triebuild_toArray2_rec { switch tb { case (#skip) (); case (#insert(k,_,v)) { a[i] := ?f(k,v); i := i + 1 }; From 1e1757ae3b2c6817549ef82d2de6ddb635a0bc93 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Tue, 18 Jun 2019 14:42:12 +0200 Subject: [PATCH 0178/1176] AST-89 Range restricted Nat* and Int* (#487) * add finite-bitwidth integral primitive types * pattern matching {Word,Int,Nat}x{8,16,32,64} * tests Caveats: - no binary operations yet - `-128 : Nat8` not expressible (needs conversion) --- emacs/actorscript-mode.el | 8 + src/as_frontend/arrange.ml | 8 + src/as_frontend/coverage.ml | 8 + src/as_frontend/syntax.ml | 16 + src/as_frontend/typing.ml | 41 ++- src/as_ir/arrange_ir.ml | 8 + src/as_ir/check_ir.ml | 8 + src/as_ir/ir.ml | 16 + src/as_types/arrange_type.ml | 8 + src/as_types/type.ml | 30 +- src/as_types/type.mli | 8 + src/as_values/operator.ml | 52 ++- src/as_values/prim.ml | 110 +++++- src/as_values/show.ml | 43 ++- src/as_values/value.ml | 75 ++++ src/as_values/value.mli | 26 ++ src/codegen/compile.ml | 337 +++++++++++++----- src/interpreter/interpret.ml | 32 +- src/ir_interpreter/interpret_ir.ml | 39 +- src/ir_passes/show.ml | 36 ++ src/lowering/desugar.ml | 12 + src/prelude/prelude.ml | 59 +++ test/fail/ok/outrange-int64lower.run-ir.ok | 1 + test/fail/ok/outrange-int64lower.run-low.ok | 1 + test/fail/ok/outrange-int64lower.run.ok | 1 + test/fail/ok/outrange-int64lower.wasm-run.ok | 1 + test/fail/ok/outrange-int64negation.run-ir.ok | 1 + .../fail/ok/outrange-int64negation.run-low.ok | 1 + test/fail/ok/outrange-int64negation.run.ok | 1 + .../ok/outrange-int64negation.wasm-run.ok | 1 + test/fail/ok/outrange-int64upper.run-ir.ok | 1 + test/fail/ok/outrange-int64upper.run-low.ok | 1 + test/fail/ok/outrange-int64upper.run.ok | 1 + test/fail/ok/outrange-int64upper.wasm-run.ok | 1 + test/fail/ok/outrange-int8lower.run-ir.ok | 1 + test/fail/ok/outrange-int8lower.run-low.ok | 1 + test/fail/ok/outrange-int8lower.run.ok | 1 + test/fail/ok/outrange-int8lower.wasm-run.ok | 1 + test/fail/ok/outrange-int8upper.run-ir.ok | 1 + test/fail/ok/outrange-int8upper.run-low.ok | 1 + test/fail/ok/outrange-int8upper.run.ok | 1 + test/fail/ok/outrange-int8upper.wasm-run.ok | 1 + test/fail/ok/outrange-nat64.run-ir.ok | 1 + test/fail/ok/outrange-nat64.run-low.ok | 1 + test/fail/ok/outrange-nat64.run.ok | 1 + test/fail/ok/outrange-nat64.wasm-run.ok | 1 + test/fail/ok/outrange-nat8.run-ir.ok | 1 + test/fail/ok/outrange-nat8.run-low.ok | 1 + test/fail/ok/outrange-nat8.run.ok | 1 + test/fail/ok/outrange-nat8.wasm-run.ok | 1 + test/fail/outrange-int64lower.as | 1 + test/fail/outrange-int64negation.as | 1 + test/fail/outrange-int64upper.as | 1 + test/fail/outrange-int8lower.as | 1 + test/fail/outrange-int8upper.as | 1 + test/fail/outrange-nat64.as | 1 + test/fail/outrange-nat8.as | 1 + test/repl/ok/outrange-int-nat.stdout.ok | 34 ++ test/repl/outrange-int-nat.sh | 47 +++ test/run-dfinity/data-params.as | 25 +- test/run-dfinity/ok/data-params.dvm-run.ok | 10 +- test/run-dfinity/ok/data-params.run-ir.ok | 10 +- test/run-dfinity/ok/data-params.run-low.ok | 10 +- test/run-dfinity/ok/data-params.run.ok | 10 +- test/run-dfinity/ok/show.dvm-run.ok | 5 +- test/run-dfinity/ok/show.run-ir.ok | 5 +- test/run-dfinity/ok/show.run-low.ok | 5 +- test/run-dfinity/ok/show.run.ok | 5 +- test/run-dfinity/show.as | 5 +- test/run/conversions.as | 143 ++++---- test/run/numeric-ops.as | 48 +++ test/run/ranged-nums.as | 47 +++ test/run/words.as | 14 + 73 files changed, 1183 insertions(+), 255 deletions(-) create mode 100644 test/fail/ok/outrange-int64lower.run-ir.ok create mode 100644 test/fail/ok/outrange-int64lower.run-low.ok create mode 100644 test/fail/ok/outrange-int64lower.run.ok create mode 100644 test/fail/ok/outrange-int64lower.wasm-run.ok create mode 100644 test/fail/ok/outrange-int64negation.run-ir.ok create mode 100644 test/fail/ok/outrange-int64negation.run-low.ok create mode 100644 test/fail/ok/outrange-int64negation.run.ok create mode 100644 test/fail/ok/outrange-int64negation.wasm-run.ok create mode 100644 test/fail/ok/outrange-int64upper.run-ir.ok create mode 100644 test/fail/ok/outrange-int64upper.run-low.ok create mode 100644 test/fail/ok/outrange-int64upper.run.ok create mode 100644 test/fail/ok/outrange-int64upper.wasm-run.ok create mode 100644 test/fail/ok/outrange-int8lower.run-ir.ok create mode 100644 test/fail/ok/outrange-int8lower.run-low.ok create mode 100644 test/fail/ok/outrange-int8lower.run.ok create mode 100644 test/fail/ok/outrange-int8lower.wasm-run.ok create mode 100644 test/fail/ok/outrange-int8upper.run-ir.ok create mode 100644 test/fail/ok/outrange-int8upper.run-low.ok create mode 100644 test/fail/ok/outrange-int8upper.run.ok create mode 100644 test/fail/ok/outrange-int8upper.wasm-run.ok create mode 100644 test/fail/ok/outrange-nat64.run-ir.ok create mode 100644 test/fail/ok/outrange-nat64.run-low.ok create mode 100644 test/fail/ok/outrange-nat64.run.ok create mode 100644 test/fail/ok/outrange-nat64.wasm-run.ok create mode 100644 test/fail/ok/outrange-nat8.run-ir.ok create mode 100644 test/fail/ok/outrange-nat8.run-low.ok create mode 100644 test/fail/ok/outrange-nat8.run.ok create mode 100644 test/fail/ok/outrange-nat8.wasm-run.ok create mode 100644 test/fail/outrange-int64lower.as create mode 100644 test/fail/outrange-int64negation.as create mode 100644 test/fail/outrange-int64upper.as create mode 100644 test/fail/outrange-int8lower.as create mode 100644 test/fail/outrange-int8upper.as create mode 100644 test/fail/outrange-nat64.as create mode 100644 test/fail/outrange-nat8.as create mode 100644 test/repl/ok/outrange-int-nat.stdout.ok create mode 100755 test/repl/outrange-int-nat.sh create mode 100644 test/run/ranged-nums.as diff --git a/emacs/actorscript-mode.el b/emacs/actorscript-mode.el index 39ded3f1ab3..3e87ae6ffa3 100644 --- a/emacs/actorscript-mode.el +++ b/emacs/actorscript-mode.el @@ -13,6 +13,14 @@ "Bool" "Nat" "Int" + "Int8" + "Int16" + "Int32" + "Int64" + "Nat8" + "Nat16" + "Nat32" + "Nat64" "Word8" "Word16" "Word32" diff --git a/src/as_frontend/arrange.ml b/src/as_frontend/arrange.ml index 5c28fbe5d37..98d2e2cdca6 100644 --- a/src/as_frontend/arrange.ml +++ b/src/as_frontend/arrange.ml @@ -75,7 +75,15 @@ and lit (l:lit) = match l with | BoolLit true -> "BoolLit" $$ [ Atom "true" ] | BoolLit false -> "BoolLit" $$ [ Atom "false" ] | NatLit n -> "NatLit" $$ [ Atom (Value.Nat.to_pretty_string n) ] + | Nat8Lit n -> "Nat8Lit" $$ [ Atom (Value.Nat8.to_pretty_string n) ] + | Nat16Lit n -> "Nat16Lit" $$ [ Atom (Value.Nat16.to_pretty_string n) ] + | Nat32Lit n -> "Nat32Lit" $$ [ Atom (Value.Nat32.to_pretty_string n) ] + | Nat64Lit n -> "Nat64Lit" $$ [ Atom (Value.Nat64.to_pretty_string n) ] | IntLit i -> "IntLit" $$ [ Atom (Value.Int.to_pretty_string i) ] + | Int8Lit i -> "Int8Lit" $$ [ Atom (Value.Int_8.to_pretty_string i) ] + | Int16Lit i -> "Int16Lit" $$ [ Atom (Value.Int_16.to_pretty_string i) ] + | Int32Lit i -> "Int32Lit" $$ [ Atom (Value.Int_32.to_pretty_string i) ] + | Int64Lit i -> "Int64Lit" $$ [ Atom (Value.Int_64.to_pretty_string i) ] | Word8Lit w -> "Word8Lit" $$ [ Atom (Value.Word8.to_pretty_string w) ] | Word16Lit w -> "Word16Lit" $$ [ Atom (Value.Word16.to_pretty_string w) ] | Word32Lit w -> "Word32Lit" $$ [ Atom (Value.Word32.to_pretty_string w) ] diff --git a/src/as_frontend/coverage.ml b/src/as_frontend/coverage.ml index 0f444651892..d5b4efd5aeb 100644 --- a/src/as_frontend/coverage.ml +++ b/src/as_frontend/coverage.ml @@ -48,7 +48,15 @@ let value_of_lit = function | NullLit -> V.Null | BoolLit b -> V.Bool b | NatLit n -> V.Int n + | Nat8Lit w -> V.Nat8 w + | Nat16Lit w -> V.Nat16 w + | Nat32Lit w -> V.Nat32 w + | Nat64Lit w -> V.Nat64 w | IntLit i -> V.Int i + | Int8Lit w -> V.Int8 w + | Int16Lit w -> V.Int16 w + | Int32Lit w -> V.Int32 w + | Int64Lit w -> V.Int64 w | Word8Lit w -> V.Word8 w | Word16Lit w -> V.Word16 w | Word32Lit w -> V.Word32 w diff --git a/src/as_frontend/syntax.ml b/src/as_frontend/syntax.ml index b87fdf77d6f..8567860b45b 100644 --- a/src/as_frontend/syntax.ml +++ b/src/as_frontend/syntax.ml @@ -61,7 +61,15 @@ type lit = | NullLit | BoolLit of bool | NatLit of Value.Nat.t + | Nat8Lit of Value.Nat8.t + | Nat16Lit of Value.Nat16.t + | Nat32Lit of Value.Nat32.t + | Nat64Lit of Value.Nat64.t | IntLit of Value.Int.t + | Int8Lit of Value.Int_8.t + | Int16Lit of Value.Int_16.t + | Int32Lit of Value.Int_32.t + | Int64Lit of Value.Int_64.t | Word8Lit of Value.Word8.t | Word16Lit of Value.Word16.t | Word32Lit of Value.Word32.t @@ -196,6 +204,14 @@ let string_of_lit = function | BoolLit true -> "true" | IntLit n | NatLit n -> Value.Int.to_pretty_string n + | Int8Lit n -> Value.Int_8.to_pretty_string n + | Int16Lit n -> Value.Int_16.to_pretty_string n + | Int32Lit n -> Value.Int_32.to_pretty_string n + | Int64Lit n -> Value.Int_64.to_pretty_string n + | Nat8Lit n -> Value.Nat8.to_pretty_string n + | Nat16Lit n -> Value.Nat16.to_pretty_string n + | Nat32Lit n -> Value.Nat32.to_pretty_string n + | Nat64Lit n -> Value.Nat64.to_pretty_string n | Word8Lit n -> Value.Word8.to_pretty_string n | Word16Lit n -> Value.Word16.to_pretty_string n | Word32Lit n -> Value.Word32.to_pretty_string n diff --git a/src/as_frontend/typing.ml b/src/as_frontend/typing.ml index 14a7066dafc..b83219f4368 100644 --- a/src/as_frontend/typing.ml +++ b/src/as_frontend/typing.ml @@ -302,7 +302,15 @@ let check_lit_val env t of_string at s = (T.string_of_typ (T.Prim t)) let check_nat env = check_lit_val env T.Nat Value.Nat.of_string +let check_nat8 env = check_lit_val env T.Nat8 Value.Nat8.of_string +let check_nat16 env = check_lit_val env T.Nat16 Value.Nat16.of_string +let check_nat32 env = check_lit_val env T.Nat32 Value.Nat32.of_string +let check_nat64 env = check_lit_val env T.Nat64 Value.Nat64.of_string let check_int env = check_lit_val env T.Int Value.Int.of_string +let check_int8 env = check_lit_val env T.Int8 Value.Int_8.of_string +let check_int16 env = check_lit_val env T.Int16 Value.Int_16.of_string +let check_int32 env = check_lit_val env T.Int32 Value.Int_32.of_string +let check_int64 env = check_lit_val env T.Int64 Value.Int_64.of_string let check_word8 env = check_lit_val env T.Word8 Value.Word8.of_string_u let check_word16 env = check_lit_val env T.Word16 Value.Word16.of_string_u let check_word32 env = check_lit_val env T.Word32 Value.Word32.of_string_u @@ -315,7 +323,15 @@ let infer_lit env lit at : T.prim = | NullLit -> T.Null | BoolLit _ -> T.Bool | NatLit _ -> T.Nat + | Nat8Lit _ -> T.Nat8 + | Nat16Lit _ -> T.Nat16 + | Nat32Lit _ -> T.Nat32 + | Nat64Lit _ -> T.Nat64 | IntLit _ -> T.Int + | Int8Lit _ -> T.Int8 + | Int16Lit _ -> T.Int16 + | Int32Lit _ -> T.Int32 + | Int64Lit _ -> T.Int64 | Word8Lit _ -> T.Word8 | Word16Lit _ -> T.Word16 | Word32Lit _ -> T.Word32 @@ -340,8 +356,24 @@ let check_lit env t lit at = | T.Opt _, NullLit -> () | T.Prim T.Nat, PreLit (s, T.Nat) -> lit := NatLit (check_nat env at s) + | T.Prim T.Nat8, PreLit (s, T.Nat) -> + lit := Nat8Lit (check_nat8 env at s) + | T.Prim T.Nat16, PreLit (s, T.Nat) -> + lit := Nat16Lit (check_nat16 env at s) + | T.Prim T.Nat32, PreLit (s, T.Nat) -> + lit := Nat32Lit (check_nat32 env at s) + | T.Prim T.Nat64, PreLit (s, T.Nat) -> + lit := Nat64Lit (check_nat64 env at s) | T.Prim T.Int, PreLit (s, (T.Nat | T.Int)) -> lit := IntLit (check_int env at s) + | T.Prim T.Int8, PreLit (s, (T.Nat | T.Int)) -> + lit := Int8Lit (check_int8 env at s) + | T.Prim T.Int16, PreLit (s, (T.Nat | T.Int)) -> + lit := Int16Lit (check_int16 env at s) + | T.Prim T.Int32, PreLit (s, (T.Nat | T.Int)) -> + lit := Int32Lit (check_int32 env at s) + | T.Prim T.Int64, PreLit (s, (T.Nat | T.Int)) -> + lit := Int64Lit (check_int64 env at s) | T.Prim T.Word8, PreLit (s, (T.Nat | T.Int)) -> lit := Word8Lit (check_word8 env at s) | T.Prim T.Word16, PreLit (s, (T.Nat | T.Int)) -> @@ -394,6 +426,11 @@ and infer_exp' f env exp : T.typ = end; t' +and special_unop_typing = let open T in + function + | Prim Nat -> Prim Int + | t -> t + and infer_exp'' env exp : T.typ = match exp.it with | PrimE _ -> @@ -411,7 +448,7 @@ and infer_exp'' env exp : T.typ = | UnE (ot, op, exp1) -> let t1 = infer_exp_promote env exp1 in (* Special case for subtyping *) - let t = if t1 = T.Prim T.Nat then T.Prim T.Int else t1 in + let t = special_unop_typing t1 in if not env.pre then begin assert (!ot = Type.Pre); if not (Operator.has_unop t op) then @@ -858,7 +895,7 @@ and infer_pat' env pat : T.typ * Scope.val_env = | SignP (op, lit) -> let t1 = T.Prim (infer_lit env lit pat.at) in (* Special case for subtyping *) - let t = if t1 = T.Prim T.Nat then T.Prim T.Int else t1 in + let t = special_unop_typing t1 in if not (Operator.has_unop t op) then local_error env pat.at "operator is not defined for operand type\n %s" (T.string_of_typ_expand t); diff --git a/src/as_ir/arrange_ir.ml b/src/as_ir/arrange_ir.ml index e338a6e6b1f..49e9b52a743 100644 --- a/src/as_ir/arrange_ir.ml +++ b/src/as_ir/arrange_ir.ml @@ -73,7 +73,15 @@ and lit (l:lit) = match l with | BoolLit true -> "BoolLit" $$ [ Atom "true" ] | BoolLit false -> "BoolLit" $$ [ Atom "false" ] | NatLit n -> "NatLit" $$ [ Atom (Value.Nat.to_pretty_string n) ] + | Nat8Lit w -> "Nat8Lit" $$ [ Atom (Value.Nat8.to_pretty_string w) ] + | Nat16Lit w -> "Nat16Lit" $$ [ Atom (Value.Nat16.to_pretty_string w) ] + | Nat32Lit w -> "Nat32Lit" $$ [ Atom (Value.Nat32.to_pretty_string w) ] + | Nat64Lit w -> "Nat64Lit" $$ [ Atom (Value.Nat64.to_pretty_string w) ] | IntLit i -> "IntLit" $$ [ Atom (Value.Int.to_pretty_string i) ] + | Int8Lit w -> "Int8Lit" $$ [ Atom (Value.Int_8.to_pretty_string w) ] + | Int16Lit w -> "Int16Lit" $$ [ Atom (Value.Int_16.to_pretty_string w) ] + | Int32Lit w -> "Int32Lit" $$ [ Atom (Value.Int_32.to_pretty_string w) ] + | Int64Lit w -> "Int64Lit" $$ [ Atom (Value.Int_64.to_pretty_string w) ] | Word8Lit w -> "Word8Lit" $$ [ Atom (Value.Word8.to_pretty_string w) ] | Word16Lit w -> "Word16Lit" $$ [ Atom (Value.Word16.to_pretty_string w) ] | Word32Lit w -> "Word32Lit" $$ [ Atom (Value.Word32.to_pretty_string w) ] diff --git a/src/as_ir/check_ir.ml b/src/as_ir/check_ir.ml index c9d1eefc39d..a213349bc6a 100644 --- a/src/as_ir/check_ir.ml +++ b/src/as_ir/check_ir.ml @@ -250,7 +250,15 @@ let type_lit env lit at : T.prim = | NullLit -> T.Null | BoolLit _ -> T.Bool | NatLit _ -> T.Nat + | Nat8Lit _ -> T.Nat8 + | Nat16Lit _ -> T.Nat16 + | Nat32Lit _ -> T.Nat32 + | Nat64Lit _ -> T.Nat64 | IntLit _ -> T.Int + | Int8Lit _ -> T.Int8 + | Int16Lit _ -> T.Int16 + | Int32Lit _ -> T.Int32 + | Int64Lit _ -> T.Int64 | Word8Lit _ -> T.Word8 | Word16Lit _ -> T.Word16 | Word32Lit _ -> T.Word32 diff --git a/src/as_ir/ir.ml b/src/as_ir/ir.ml index e04d743b318..05131e9e193 100644 --- a/src/as_ir/ir.ml +++ b/src/as_ir/ir.ml @@ -9,7 +9,15 @@ type lit = | NullLit | BoolLit of bool | NatLit of Value.Nat.t + | Nat8Lit of Value.Nat8.t + | Nat16Lit of Value.Nat16.t + | Nat32Lit of Value.Nat32.t + | Nat64Lit of Value.Nat64.t | IntLit of Value.Int.t + | Int8Lit of Value.Int_8.t + | Int16Lit of Value.Int_16.t + | Int32Lit of Value.Int_32.t + | Int64Lit of Value.Int_64.t | Word8Lit of Value.Word8.t | Word16Lit of Value.Word16.t | Word32Lit of Value.Word32.t @@ -110,6 +118,14 @@ let string_of_lit = function | BoolLit true -> "true" | IntLit n | NatLit n -> Value.Int.to_pretty_string n + | Int8Lit n -> Value.Int_8.to_pretty_string n + | Int16Lit n -> Value.Int_16.to_pretty_string n + | Int32Lit n -> Value.Int_32.to_pretty_string n + | Int64Lit n -> Value.Int_64.to_pretty_string n + | Nat8Lit n -> Value.Nat8.to_pretty_string n + | Nat16Lit n -> Value.Nat16.to_pretty_string n + | Nat32Lit n -> Value.Nat32.to_pretty_string n + | Nat64Lit n -> Value.Nat64.to_pretty_string n | Word8Lit n -> Value.Word8.to_pretty_string n | Word16Lit n -> Value.Word16.to_pretty_string n | Word32Lit n -> Value.Word32.to_pretty_string n diff --git a/src/as_types/arrange_type.ml b/src/as_types/arrange_type.ml index 1a9ea33babb..51c180ce303 100644 --- a/src/as_types/arrange_type.ml +++ b/src/as_types/arrange_type.ml @@ -20,7 +20,15 @@ let prim p = match p with | Null -> Atom "Null" | Bool -> Atom "Bool" | Nat -> Atom "Nat" + | Nat8 -> Atom "Nat8" + | Nat16 -> Atom "Nat16" + | Nat32 -> Atom "Nat32" + | Nat64 -> Atom "Nat64" | Int -> Atom "Int" + | Int8 -> Atom "Int8" + | Int16 -> Atom "Int16" + | Int32 -> Atom "Int32" + | Int64 -> Atom "Int64" | Word8 -> Atom "Word8" | Word16 -> Atom "Word16" | Word32 -> Atom "Word32" diff --git a/src/as_types/type.ml b/src/as_types/type.ml index 662031c2787..8ca00731cb7 100644 --- a/src/as_types/type.ml +++ b/src/as_types/type.ml @@ -12,7 +12,15 @@ type prim = | Null | Bool | Nat + | Nat8 + | Nat16 + | Nat32 + | Nat64 | Int + | Int8 + | Int16 + | Int32 + | Int64 | Word8 | Word16 | Word32 @@ -72,7 +80,15 @@ let prim = function | "Null" -> Null | "Bool" -> Bool | "Nat" -> Nat + | "Nat8" -> Nat8 + | "Nat16" -> Nat16 + | "Nat32" -> Nat32 + | "Nat64" -> Nat64 | "Int" -> Int + | "Int8" -> Int8 + | "Int16" -> Int16 + | "Int32" -> Int32 + | "Int64" -> Int64 | "Word8" -> Word8 | "Word16" -> Word16 | "Word32" -> Word32 @@ -399,9 +415,9 @@ let rec span = function | Prim Null -> Some 1 | Prim Bool -> Some 2 | Prim (Nat | Int | Float | Text) -> None - | Prim Word8 -> Some 0x100 - | Prim Word16 -> Some 0x10000 - | Prim (Word32 | Word64 | Char) -> None (* for all practical purpuses *) + | Prim (Nat8 | Int8 | Word8) -> Some 0x100 + | Prim (Nat16 | Int16 | Word16) -> Some 0x10000 + | Prim (Nat32 | Int32 | Word32 | Nat64 | Int64 | Word64 | Char) -> None (* for all practical purposes *) | Obj _ | Tup _ | Async _ -> Some 1 | Variant fs -> Some (List.length fs) | Array _ | Func _ | Shared | Any -> None @@ -785,7 +801,15 @@ let string_of_prim = function | Null -> "Null" | Bool -> "Bool" | Nat -> "Nat" + | Nat8 -> "Nat8" + | Nat16 -> "Nat16" + | Nat32 -> "Nat32" + | Nat64 -> "Nat64" | Int -> "Int" + | Int8 -> "Int8" + | Int16 -> "Int16" + | Int32 -> "Int32" + | Int64 -> "Int64" | Float -> "Float" | Word8 -> "Word8" | Word16 -> "Word16" diff --git a/src/as_types/type.mli b/src/as_types/type.mli index 3835d0eed5d..4316a8b11ce 100644 --- a/src/as_types/type.mli +++ b/src/as_types/type.mli @@ -12,7 +12,15 @@ type prim = | Null | Bool | Nat + | Nat8 + | Nat16 + | Nat32 + | Nat64 | Int + | Int8 + | Int16 + | Int32 + | Int64 | Word8 | Word16 | Word32 diff --git a/src/as_values/operator.ml b/src/as_values/operator.ml index 1e183741407..57d2a324ab7 100644 --- a/src/as_values/operator.ml +++ b/src/as_values/operator.ml @@ -39,25 +39,35 @@ let impossible _ = raise (Invalid_argument "impossible") (* Unary operators *) -let word_unop fword8 fword16 fword32 fword64 = function +let word_unop (fword8, fword16, fword32, fword64) = function | T.Word8 -> fun v -> Word8 (fword8 (as_word8 v)) | T.Word16 -> fun v -> Word16 (fword16 (as_word16 v)) | T.Word32 -> fun v -> Word32 (fword32 (as_word32 v)) | T.Word64 -> fun v -> Word64 (fword64 (as_word64 v)) | _ -> raise (Invalid_argument "unop") -let num_unop fint fword8 fword16 fword32 fword64 ffloat = function +let num_unop fint (fint8, fint16, fint32, fint64) wordops ffloat = function | T.Int -> fun v -> Int (fint (as_int v)) + | T.Int8 -> fun v -> Int8 (fint8 (as_int8 v)) + | T.Int16 -> fun v -> Int16 (fint16 (as_int16 v)) + | T.Int32 -> fun v -> Int32 (fint32 (as_int32 v)) + | T.Int64 -> fun v -> Int64 (fint64 (as_int64 v)) | T.Float -> fun v -> Float (ffloat (as_float v)) - | t -> word_unop fword8 fword16 fword32 fword64 t + | t -> word_unop wordops t let unop t op = match t with | T.Prim p -> (match op with - | PosOp -> let id v = v in num_unop id id id id id id p - | NegOp -> num_unop Int.neg Word8.neg Word16.neg Word32.neg Word64.neg Float.neg p - | NotOp -> word_unop Word8.not Word16.not Word32.not Word64.not p + | PosOp -> let id v = v in num_unop id (id, id, id, id) (id, id, id, id) id p + | NegOp -> + num_unop + Int.neg + (Int_8.neg, Int_16.neg, Int_32.neg, Int_64.neg) + (Word8.neg, Word16.neg, Word32.neg, Word64.neg) + Float.neg + p + | NotOp -> word_unop (Word8.not, Word16.not, Word32.not, Word64.not) p ) | T.Non -> impossible | _ -> raise (Invalid_argument "unop") @@ -108,39 +118,43 @@ let binop t op = (* Relational operators *) -let word_relop fword8 fword16 fword32 fword64 = function +let word_relop (fword8, fword16, fword32, fword64) = function | T.Word8 -> fun v1 v2 -> Bool (fword8 (as_word8 v1) (as_word8 v2)) | T.Word16 -> fun v1 v2 -> Bool (fword16 (as_word16 v1) (as_word16 v2)) | T.Word32 -> fun v1 v2 -> Bool (fword32 (as_word32 v1) (as_word32 v2)) | T.Word64 -> fun v1 v2 -> Bool (fword64 (as_word64 v1) (as_word64 v2)) | _ -> raise (Invalid_argument "relop") -let num_relop fnat fint fword8 fword16 fword32 fword64 ffloat = function +let num_relop fnat fint (fint8, fint16, fint32, fint64) fwords ffloat = function | T.Nat -> fun v1 v2 -> Bool (fnat (as_int v1) (as_int v2)) | T.Int -> fun v1 v2 -> Bool (fint (as_int v1) (as_int v2)) + | T.Int8 -> fun v1 v2 -> Bool (fint8 (as_int8 v1) (as_int8 v2)) + | T.Int16 -> fun v1 v2 -> Bool (fint16 (as_int16 v1) (as_int16 v2)) + | T.Int32 -> fun v1 v2 -> Bool (fint32 (as_int32 v1) (as_int32 v2)) + | T.Int64 -> fun v1 v2 -> Bool (fint64 (as_int64 v1) (as_int64 v2)) | T.Float -> fun v1 v2 -> Bool (ffloat (as_float v1) (as_float v2)) - | t -> word_relop fword8 fword16 fword32 fword64 t + | t -> word_relop fwords t -let ord_relop fnat fint fword8 fword16 fword32 fword64 ffloat fchar ftext = function +let ord_relop fnat fint fints fwords ffloat fchar ftext = function | T.Char -> fun v1 v2 -> Bool (fchar (as_char v1) (as_char v2)) | T.Text -> fun v1 v2 -> Bool (ftext (as_text v1) (as_text v2)) - | t -> num_relop fnat fint fword8 fword16 fword32 fword64 ffloat t + | t -> num_relop fnat fint fints fwords ffloat t -let eq_relop fnat fint fword8 fword16 fword32 fword64 ffloat fchar ftext fnull fbool = function +let eq_relop fnat fint fints fwords ffloat fchar ftext fnull fbool = function | T.Null -> fun v1 v2 -> Bool (fnull (as_null v1) (as_null v2)) | T.Bool -> fun v1 v2 -> Bool (fbool (as_bool v1) (as_bool v2)) - | t -> ord_relop fnat fint fword8 fword16 fword32 fword64 ffloat fchar ftext t + | t -> ord_relop fnat fint fints fwords ffloat fchar ftext t let relop t op = match t with | T.Prim p -> (match op with - | EqOp -> eq_relop Nat.eq Int.eq Word8.eq Word16.eq Word32.eq Word64.eq Float.eq (=) (=) (=) (=) p - | NeqOp -> eq_relop Nat.ne Int.ne Word8.ne Word16.ne Word32.ne Word64.ne Float.ne (<>) (<>) (<>) (<>) p - | LtOp -> ord_relop Nat.lt Int.lt Word8.lt_u Word16.lt_u Word32.lt_u Word64.lt_u Float.lt (<) (<) p - | GtOp -> ord_relop Nat.gt Int.gt Word8.gt_u Word16.gt_u Word32.gt_u Word64.gt_u Float.gt (>) (>) p - | LeOp -> ord_relop Nat.le Int.le Word8.le_u Word16.le_u Word32.le_u Word64.le_u Float.le (<=) (<=) p - | GeOp -> ord_relop Nat.ge Int.ge Word8.ge_u Word16.ge_u Word32.ge_u Word64.ge_u Float.ge (>=) (>=) p + | EqOp -> eq_relop Nat.eq Int.eq (Int_8.eq, Int_16.eq, Int_32.eq, Int_64.eq) (Word8.eq, Word16.eq, Word32.eq, Word64.eq) Float.eq (=) (=) (=) (=) p + | NeqOp -> eq_relop Nat.ne Int.ne (Int_8.ne, Int_16.ne, Int_32.ne, Int_64.ne) (Word8.ne, Word16.ne, Word32.ne, Word64.ne) Float.ne (<>) (<>) (<>) (<>) p + | LtOp -> ord_relop Nat.lt Int.lt (Int_8.lt, Int_16.lt, Int_32.lt, Int_64.lt) (Word8.lt_u, Word16.lt_u, Word32.lt_u, Word64.lt_u) Float.lt (<) (<) p + | GtOp -> ord_relop Nat.gt Int.gt (Int_8.gt, Int_16.gt, Int_32.gt, Int_64.gt) (Word8.gt_u, Word16.gt_u, Word32.gt_u, Word64.gt_u) Float.gt (>) (>) p + | LeOp -> ord_relop Nat.le Int.le (Int_8.le, Int_16.le, Int_32.le, Int_64.le) (Word8.le_u, Word16.le_u, Word32.le_u, Word64.le_u) Float.le (<=) (<=) p + | GeOp -> ord_relop Nat.ge Int.ge (Int_8.ge, Int_16.ge, Int_32.ge, Int_64.ge) (Word8.ge_u, Word16.ge_u, Word32.ge_u, Word64.ge_u) Float.ge (>=) (>=) p ) | T.Non -> impossible | _ -> raise (Invalid_argument "relop") diff --git a/src/as_values/prim.ml b/src/as_values/prim.ml index f81dfdd7c81..7bae41b5f1b 100644 --- a/src/as_values/prim.ml +++ b/src/as_values/prim.ml @@ -7,11 +7,10 @@ module Conv = struct open Big_int let of_signed_Word32 w = to_int (logand 0xFFFFFFFFn (of_int32 w)) - let two = big_int_of_int 2 - let twoRaised62 = power_big_int_positive_int two 62 - let twoRaised63 = power_big_int_positive_int two 63 + let twoRaised62 = power_int_positive_int 2 62 + let twoRaised63 = power_int_positive_int 2 63 let word_twoRaised63 = Word64.(pow 2L 63L) - let twoRaised64 = power_big_int_positive_int two 64 + let twoRaised64 = power_int_positive_int 2 64 let word64_of_nat_big_int i = assert (sign_big_int i > -1); @@ -35,55 +34,158 @@ module Conv = struct match int_of_big_int_opt i with | Some n -> n | _ -> int_of_big_int (mod_big_int i twoRaised62) + + (* for q in {0, -1} return i + q * offs *) + let to_signed i q offs = if Big_int.sign_big_int q = 0 then i else i - offs + let to_signed_big_int i q offs = Big_int.(if sign_big_int q = 0 then i else sub_big_int i offs) end (* Conv *) +let range_violation () = raise (Invalid_argument "numeric overflow") let prim = function | "abs" -> fun v k -> k (Int (Nat.abs (as_int v))) + | "Nat8->Word8" -> fun v k -> + let i = Nat8.to_int (as_nat8 v) + in k (Word8 (Word8.of_int_u i)) | "Nat->Word8" -> fun v k -> let i = Conv.wrapped_int_of_big_int (as_int v) in k (Word8 (Word8.of_int_u i)) + | "Nat->Nat8" -> fun v k -> + let q, r = Big_int.quomod_big_int (as_int v) (Big_int.power_int_positive_int 2 8) in + let i = Big_int.int_of_big_int r + in Big_int.(if eq_big_int q zero_big_int then k (Nat8 (Nat8.of_int i)) else range_violation ()) + | "Int8->Word8" -> fun v k -> + let i = Int_8.to_int (as_int8 v) + in k (Word8 (Word8.of_int_s i)) | "Int->Word8" -> fun v k -> let i = Conv.wrapped_int_of_big_int (as_int v) in k (Word8 (Word8.of_int_s i)) + | "Int->Int8" -> fun v k -> + let q, r = Big_int.quomod_big_int (as_int v) (Big_int.power_int_positive_int 2 7) in + let i = Big_int.int_of_big_int r in + Big_int. + (if eq_big_int q zero_big_int || eq_big_int q (pred_big_int zero_big_int) + then k (Int8(Int_8.of_int (Conv.to_signed i q 0x80))) else range_violation ()) + | "Nat16->Word16" -> fun v k -> + let i = Nat16.to_int (as_nat16 v) + in k (Word16 (Word16.of_int_u i)) | "Nat->Word16" -> fun v k -> let i = Conv.wrapped_int_of_big_int (as_int v) in k (Word16 (Word16.of_int_u i)) + | "Nat->Nat16" -> fun v k -> + let q, r = Big_int.quomod_big_int (as_int v) (Big_int.power_int_positive_int 2 16) in + let i = Big_int.int_of_big_int r + in Big_int.(if eq_big_int q zero_big_int then k (Nat16 (Nat16.of_int i)) else range_violation ()) + | "Int16->Word16" -> fun v k -> + let i = Int_16.to_int (as_int16 v) + in k (Word16 (Word16.of_int_s i)) | "Int->Word16" -> fun v k -> let i = Conv.wrapped_int_of_big_int (as_int v) in k (Word16 (Word16.of_int_s i)) + | "Int->Int16" -> fun v k -> + let q, r = Big_int.quomod_big_int (as_int v) (Big_int.power_int_positive_int 2 15) in + let i = Big_int.int_of_big_int r in + Big_int. + (if eq_big_int q zero_big_int || eq_big_int q (pred_big_int zero_big_int) + then k (Int16(Int_16.of_int (Conv.to_signed i q 0x8000))) else range_violation ()) + | "Nat32->Word32" -> fun v k -> + let i = Nat32.to_int (as_nat32 v) + in k (Word32 (Word32.of_int_u i)) | "Nat->Word32" -> fun v k -> let i = Conv.wrapped_int_of_big_int (as_int v) in k (Word32 (Word32.of_int_u i)) + | "Nat->Nat32" -> fun v k -> + let q, r = Big_int.quomod_big_int (as_int v) (Big_int.power_int_positive_int 2 32) in + let i = Big_int.int_of_big_int r + in Big_int.(if eq_big_int q zero_big_int then k (Nat32 (Nat32.of_int i)) else range_violation ()) + | "Int32->Word32" -> fun v k -> + let i = Int_32.to_int (as_int32 v) + in k (Word32 (Word32.of_int_s i)) | "Int->Word32" -> fun v k -> let i = Conv.wrapped_int_of_big_int (as_int v) in k (Word32 (Word32.of_int_s i)) + | "Int->Int32" -> fun v k -> + let q, r = Big_int.quomod_big_int (as_int v) (Big_int.power_int_positive_int 2 31) in + let i = Big_int.int_of_big_int r in + Big_int. + (if eq_big_int q zero_big_int || eq_big_int q (pred_big_int zero_big_int) + then k (Int32 (Int_32.of_int (Conv.to_signed i q 0x80000000))) else range_violation ()) + | "Nat64->Word64" -> fun v k -> + let q, r = Big_int.quomod_big_int (Nat64.to_big_int (as_nat64 v)) Conv.twoRaised63 in + let i = Conv.(to_signed_big_int r q twoRaised63) in + k (Word64 (Big_int.int64_of_big_int i)) | "Nat->Word64" -> fun v k -> k (Word64 (Conv.word64_of_nat_big_int (as_int v))) + | "Nat->Nat64" -> fun v k -> + let q, r = Big_int.quomod_big_int (as_int v) Conv.twoRaised64 in + Big_int. + (if eq_big_int q zero_big_int + then k (Nat64 (Nat64.of_big_int r)) + else range_violation ()) + | "Int64->Word64" -> fun v k -> k (Word64 (Big_int.int64_of_big_int (Int_64.to_big_int (as_int64 v)))) | "Int->Word64" -> fun v k -> k (Word64 (Conv.word64_of_big_int (as_int v))) + | "Int->Int64" -> fun v k -> + let q, r = Big_int.quomod_big_int (as_int v) Conv.twoRaised63 in + Big_int. + (if eq_big_int q zero_big_int || eq_big_int q (pred_big_int zero_big_int) + then k (Int64 (Int_64.of_big_int Conv.(to_signed_big_int r q twoRaised63))) + else range_violation ()) | "Word8->Nat" -> fun v k -> let i = Int32.to_int (Int32.shift_right_logical (Word8.to_bits (as_word8 v)) 24) in k (Int (Big_int.big_int_of_int i)) + | "Word8->Nat8" -> fun v k -> + let i = Int32.to_int (Int32.shift_right_logical (Word8.to_bits (as_word8 v)) 24) + in k (Nat8 (Nat8.of_int i)) + | "Int8->Int" -> fun v k -> k (Int (Int.of_int (Int_8.to_int (as_int8 v)))) + | "Nat8->Nat" -> fun v k -> k (Int (Nat.of_int (Nat8.to_int (as_nat8 v)))) | "Word8->Int" -> fun v k -> let i = Int32.to_int (Int32.shift_right (Word8.to_bits (as_word8 v)) 24) in k (Int (Big_int.big_int_of_int i)) + | "Word8->Int8" -> fun v k -> + let i = Int32.to_int (Int32.shift_right (Word8.to_bits (as_word8 v)) 24) + in k (Int8 (Int_8.of_int i)) | "Word16->Nat" -> fun v k -> let i = Int32.to_int (Int32.shift_right_logical (Word16.to_bits (as_word16 v)) 16) in k (Int (Big_int.big_int_of_int i)) + | "Word16->Nat16" -> fun v k -> + let i = Int32.to_int (Int32.shift_right_logical (Word16.to_bits (as_word16 v)) 16) + in k (Nat16 (Nat16.of_int i)) + | "Int16->Int" -> fun v k -> k (Int (Int.of_int (Int_16.to_int (as_int16 v)))) + | "Nat16->Nat" -> fun v k -> k (Int (Nat.of_int (Nat16.to_int (as_nat16 v)))) | "Word16->Int" -> fun v k -> let i = Int32.to_int (Int32.shift_right (Word16.to_bits (as_word16 v)) 16) in k (Int (Big_int.big_int_of_int i)) + | "Word16->Int16" -> fun v k -> + let i = Int32.to_int (Int32.shift_right (Word16.to_bits (as_word16 v)) 16) + in k (Int16 (Int_16.of_int i)) + | "Int32->Int" -> fun v k -> k (Int (Int.of_int (Int_32.to_int (as_int32 v)))) + | "Nat32->Nat" -> fun v k -> k (Int (Nat.of_int (Nat32.to_int (as_nat32 v)))) | "Word32->Nat" -> fun v k -> let i = Conv.of_signed_Word32 (as_word32 v) in k (Int (Big_int.big_int_of_int i)) | "Word32->Int" -> fun v k -> k (Int (Big_int.big_int_of_int32 (as_word32 v))) + | "Word32->Int32" -> fun v k -> + let i = Big_int.(int_of_big_int (big_int_of_int32 (as_word32 v))) in + k (Int32 (Int_32.of_int i)) + | "Word32->Nat32" -> fun v k -> + let i = Big_int.(int_of_big_int (big_int_of_int32 (as_word32 v))) in + let i' = if i < 0 then i + 0x100000000 else i in + k (Nat32 (Nat32.of_int i')) + | "Int64->Int" -> fun v k -> k (Int (Int_64.to_big_int (as_int64 v))) + | "Nat64->Nat" -> fun v k -> k (Int (Nat64.to_big_int (as_nat64 v))) | "Word64->Nat" -> fun v k -> let i = Conv.big_int_of_unsigned_word64 (as_word64 v) in k (Int i) + | "Word64->Nat64" -> fun v k -> + let i = Conv.big_int_of_unsigned_word64 (as_word64 v) + in k (Nat64 (Nat64.of_big_int i)) | "Word64->Int" -> fun v k -> k (Int (Big_int.big_int_of_int64 (as_word64 v))) + | "Word64->Int64" -> fun v k -> + let i = Big_int.big_int_of_int64 (as_word64 v) + in k (Int64 (Int_64.of_big_int i)) | "Char->Word32" -> fun v k -> let i = as_char v diff --git a/src/as_values/show.ml b/src/as_values/show.ml index d89c67ffb15..22335a92613 100644 --- a/src/as_values/show.ml +++ b/src/as_values/show.ml @@ -3,20 +3,20 @@ module T = As_types.Type (* Entry point for type checking: *) let rec can_show t = - let t = T.normalize t in - match t with - | T.Prim T.Bool - | T.Prim T.Nat - | T.Prim T.Int - | T.Prim T.Text - | T.Prim T.Null -> true - | T.Tup ts' -> List.for_all can_show ts' - | T.Opt t' -> can_show t' - | T.Array t' -> can_show (T.as_immut t') - | T.Obj (T.Object _, fs) -> - List.for_all (fun f -> can_show (T.as_immut f.T.typ)) fs - | T.Variant cts -> - List.for_all (fun f -> can_show f.T.typ) cts + let open T in + match normalize t with + | Prim (Bool|Nat|Int|Text|Null) -> true + | Prim (Nat8|Int8|Word8) + | Prim (Nat16|Int16|Word16) + | Prim (Nat32|Int32|Word32) + | Prim (Nat64|Int64|Word64) -> true + | Tup ts' -> List.for_all can_show ts' + | Opt t' -> can_show t' + | Array t' -> can_show (as_immut t') + | Obj (Object _, fs) -> + List.for_all (fun f -> can_show (as_immut f.typ)) fs + | Variant cts -> + List.for_all (fun f -> can_show f.typ) cts | _ -> false (* Entry point for the interpreter (reference implementation) *) @@ -25,8 +25,19 @@ let rec show_val t v = let t = T.normalize t in match t, v with | T.Prim T.Bool, Value.Bool b -> if b then "true" else "false" - | T.Prim T.Nat, Value.Int i -> Value.Int.to_string i - | T.Prim T.Int, Value.Int i -> Value.Int.to_string i + | T.(Prim (Nat|Int)), Value.Int i -> Value.Int.to_string i + | T.(Prim Nat8), Value.Nat8 i -> Value.Nat8.to_string i + | T.(Prim Nat16), Value.Nat16 i -> Value.Nat16.to_string i + | T.(Prim Nat32), Value.Nat32 i -> Value.Nat32.to_string i + | T.(Prim Nat64), Value.Nat64 i -> Value.Nat64.to_string i + | T.(Prim Int8), Value.Int8 i -> Value.Int_8.to_string i + | T.(Prim Int16), Value.Int16 i -> Value.Int_16.to_string i + | T.(Prim Int32), Value.Int32 i -> Value.Int_32.to_string i + | T.(Prim Int64), Value.Int64 i -> Value.Int_64.to_string i + | T.(Prim Word8), Value.Word8 i -> Value.Word8.to_string i + | T.(Prim Word16), Value.Word16 i -> Value.Word16.to_string i + | T.(Prim Word32), Value.Word32 i -> Value.Word32.to_string i + | T.(Prim Word64), Value.Word64 i -> Value.Word64.to_string i | T.Prim T.Text, Value.Text s -> "\"" ^ s ^ "\"" | T.Prim T.Null, Value.Null -> "null" | T.Opt _, Value.Null -> "null" diff --git a/src/as_values/value.ml b/src/as_values/value.ml index 53e284db16b..73a3144cba1 100644 --- a/src/as_values/value.ml +++ b/src/as_values/value.ml @@ -142,6 +142,8 @@ sig val compare : t -> t -> int val to_int : t -> int val of_int : int -> t + val to_big_int : t -> Big_int.big_int + val of_big_int : Big_int.big_int -> t val of_string : string -> t val to_string : t -> string val to_pretty_string : t -> string @@ -172,6 +174,8 @@ struct let compare = compare_big_int let to_int = int_of_big_int let of_int = big_int_of_int + let of_big_int i = i + let to_big_int i = i let to_string i = string_of_big_int i let to_pretty_string i = group_num (string_of_big_int i) let of_string s = @@ -193,6 +197,45 @@ struct if ge z zero then z else raise (Invalid_argument "Nat.sub") end +module RangeLimited(Rep : NumType)(Range : sig val is_range : Rep.t -> bool end) : NumType = +struct + let check i = + if Range.is_range i then i + else raise (Invalid_argument "value out of bounds") + + include Rep + let neg a = let res = Rep.neg a in check res + let abs a = let res = Rep.abs a in check res + let add a b = let res = Rep.add a b in check res + let mul a b = let res = Rep.mul a b in check res + let div a b = let res = Rep.div a b in check res + let pow a b = let res = Rep.pow a b in check res + let of_int i = let res = Rep.of_int i in check res + let of_big_int i = let res = Rep.of_big_int i in check res + let of_string s = let res = Rep.of_string s in check res +end + +module NatRange(Limit : sig val upper : Big_int.big_int end) = +struct + open Big_int + let is_range n = ge_big_int n zero_big_int && lt_big_int n Limit.upper +end + +module Nat8 = RangeLimited(Nat)(NatRange(struct let upper = Big_int.big_int_of_int 0x100 end)) +module Nat16 = RangeLimited(Nat)(NatRange(struct let upper = Big_int.big_int_of_int 0x10000 end)) +module Nat32 = RangeLimited(Nat)(NatRange(struct let upper = Big_int.big_int_of_int 0x100000000 end)) +module Nat64 = RangeLimited(Nat)(NatRange(struct let upper = Big_int.power_int_positive_int 2 64 end)) + +module IntRange(Limit : sig val upper : Big_int.big_int end) = +struct + open Big_int + let is_range n = ge_big_int n (minus_big_int Limit.upper) && lt_big_int n Limit.upper +end + +module Int_8 = RangeLimited(Int)(IntRange(struct let upper = Big_int.big_int_of_int 0x80 end)) +module Int_16 = RangeLimited(Int)(IntRange(struct let upper = Big_int.big_int_of_int 0x8000 end)) +module Int_32 = RangeLimited(Int)(IntRange(struct let upper = Big_int.big_int_of_int 0x80000000 end)) +module Int_64 = RangeLimited(Int)(IntRange(struct let upper = Big_int.power_int_positive_int 2 63 end)) (* Types *) @@ -204,6 +247,14 @@ and value = | Null | Bool of bool | Int of Int.t + | Int8 of Int_8.t + | Int16 of Int_16.t + | Int32 of Int_32.t + | Int64 of Int_64.t + | Nat8 of Nat8.t + | Nat16 of Nat16.t + | Nat32 of Nat32.t + | Nat64 of Nat64.t | Word8 of Word8.t | Word16 of Word16.t | Word32 of Word32.t @@ -240,6 +291,14 @@ let invalid s = raise (Invalid_argument ("Value." ^ s)) let as_null = function Null -> () | _ -> invalid "as_null" let as_bool = function Bool b -> b | _ -> invalid "as_bool" let as_int = function Int n -> n | _ -> invalid "as_int" +let as_int8 = function Int8 w -> w | _ -> invalid "as_int8" +let as_int16 = function Int16 w -> w | _ -> invalid "as_int16" +let as_int32 = function Int32 w -> w | _ -> invalid "as_int32" +let as_int64 = function Int64 w -> w | _ -> invalid "as_int64" +let as_nat8 = function Nat8 w -> w | _ -> invalid "as_nat8" +let as_nat16 = function Nat16 w -> w | _ -> invalid "as_nat16" +let as_nat32 = function Nat32 w -> w | _ -> invalid "as_nat32" +let as_nat64 = function Nat64 w -> w | _ -> invalid "as_nat64" let as_word8 = function Word8 w -> w | _ -> invalid "as_word8" let as_word16 = function Word16 w -> w | _ -> invalid "as_word16" let as_word32 = function Word32 w -> w | _ -> invalid "as_word32" @@ -325,6 +384,14 @@ let rec compare x1 x2 = if x1 == x2 then 0 else match x1, x2 with | Int n1, Int n2 -> Int.compare n1 n2 + | Int8 n1, Int8 n2 -> Int_8.compare n1 n2 + | Int16 n1, Int16 n2 -> Int_16.compare n1 n2 + | Int32 n1, Int32 n2 -> Int_32.compare n1 n2 + | Int64 n1, Int64 n2 -> Int_64.compare n1 n2 + | Nat8 n1, Nat8 n2 -> Nat8.compare n1 n2 + | Nat16 n1, Nat16 n2 -> Nat16.compare n1 n2 + | Nat32 n1, Nat32 n2 -> Nat32.compare n1 n2 + | Nat64 n1, Nat64 n2 -> Nat64.compare n1 n2 | Opt v1, Opt v2 -> compare v1 v2 | Tup vs1, Tup vs2 -> Lib.List.compare compare vs1 vs2 | Array a1, Array a2 -> Lib.Array.compare compare a1 a2 @@ -363,6 +430,14 @@ let rec string_of_val_nullary d = function | Null -> "null" | Bool b -> if b then "true" else "false" | Int i -> Int.to_pretty_string i + | Int8 w -> Int_8.to_pretty_string w + | Int16 w -> Int_16.to_pretty_string w + | Int32 w -> Int_32.to_pretty_string w + | Int64 w -> Int_64.to_pretty_string w + | Nat8 w -> Nat8.to_pretty_string w + | Nat16 w -> Nat16.to_pretty_string w + | Nat32 w -> Nat32.to_pretty_string w + | Nat64 w -> Nat64.to_pretty_string w | Word8 w -> Word8.to_pretty_string w | Word16 w -> Word16.to_pretty_string w | Word32 w -> Word32.to_pretty_string w diff --git a/src/as_values/value.mli b/src/as_values/value.mli index b9fa22c7162..8ca39331c91 100644 --- a/src/as_values/value.mli +++ b/src/as_values/value.mli @@ -33,6 +33,8 @@ sig val compare : t -> t -> int val to_int : t -> int val of_int : int -> t + val to_big_int : t -> Big_int.big_int + val of_big_int : Big_int.big_int -> t val of_string : string -> t val to_string : t -> string val to_pretty_string : t -> string @@ -53,6 +55,14 @@ module Float : FloatType with type bits = int64 and type t = Wasm.F64.t module Nat : NumType with type t = Big_int.big_int module Int : NumType with type t = Big_int.big_int +module Int_8 : NumType +module Int_16 : NumType +module Int_32 : NumType +module Int_64 : NumType +module Nat8 : NumType +module Nat16 : NumType +module Nat32 : NumType +module Nat64 : NumType (* Environment *) @@ -69,6 +79,14 @@ and value = | Null | Bool of bool | Int of Int.t + | Int8 of Int_8.t + | Int16 of Int_16.t + | Int32 of Int_32.t + | Int64 of Int_64.t + | Nat8 of Nat8.t + | Nat16 of Nat16.t + | Nat32 of Nat32.t + | Nat64 of Nat64.t | Word8 of Word8.t | Word16 of Word16.t | Word32 of Word32.t @@ -107,6 +125,14 @@ val async_func : int -> func -> value val as_null : value -> unit val as_bool : value -> bool val as_int : value -> Int.t +val as_int8 : value -> Int_8.t +val as_int16 : value -> Int_16.t +val as_int32 : value -> Int_32.t +val as_int64 : value -> Int_64.t +val as_nat8 : value -> Nat8.t +val as_nat16 : value -> Nat16.t +val as_nat32 : value -> Nat32.t +val as_nat64 : value -> Nat64.t val as_word8 : value -> Word8.t val as_word16 : value -> Word16.t val as_word32 : value -> Word32.t diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 5855744ea67..9e7d637822e 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -1148,23 +1148,18 @@ module Closure = struct end (* Closure *) -module BoxedWord = struct - (* We store large nats and ints in immutable boxed 64bit heap objects. +module BoxedWord64 = struct + (* We store large word64s, nat64s and int64s in immutable boxed 64bit heap objects. Small values (just <2^5 for now, so that both code paths are well-tested) are stored unboxed, tagged, see BitTagged. - The heap layout of a BoxedWord is: + The heap layout of a BoxedWord64 is: ┌─────┬─────┬─────┐ │ tag │ i64 │ └─────┴─────┴─────┘ - Note, that due to the equivalence of in-memory and on-stack - representations, the 64-bit word type is also represented in this - way. As we get proper bigints, the memory representations should - be disambiguated and stack representations adapted. (Renaming - those will point out where the backend needs adjustments.) *) let payload_field = Tagged.header_size @@ -1200,7 +1195,7 @@ module BoxedWord = struct (* from/to SR.UnboxedWord64 *) let to_word64 env = G.nop let from_word64 env = G.nop (* TODO trap if negative *) - let from_signed_word64 env = G.nop + let _from_signed_word64 env = G.nop let to_word32 env = G.i (Convert (Wasm.Values.I32 I32Op.WrapI64)) let from_word32 env = G.i (Convert (Wasm.Values.I64 I64Op.ExtendUI32)) let from_signed_word32 env = G.i (Convert (Wasm.Values.I64 I64Op.ExtendSI32)) @@ -1233,7 +1228,7 @@ module BoxedWord = struct G.i (Binary (Wasm.Values.I64 I64Op.Mul))))) in pow () -end (* BoxedWord *) +end (* BoxedWord64 *) module BoxedSmallWord = struct @@ -1284,10 +1279,12 @@ module UnboxedSmallWord = struct there are certain differences that are type based. This module provides helpers to abstract over those. *) - let shift_of_type = function - | Type.Word8 -> 24l - | Type.Word16 -> 16l - | _ -> 0l + let bits_of_type = function + | Type.(Int8|Nat8|Word8) -> 8 + | Type.(Int16|Nat16|Word16) -> 16 + | _ -> 32 + + let shift_of_type ty = Int32.of_int (32 - bits_of_type ty) let bitwidth_mask_of_type = function | Type.Word8 -> 0b111l @@ -1315,12 +1312,13 @@ module UnboxedSmallWord = struct (* Makes sure that the word payload (e.g. shift/rotate amount) is in the LSB bits of the word. *) let lsb_adjust = function - | Type.Word32 -> G.nop - | ty -> compile_shrU_const (shift_of_type ty) + | Type.(Int32|Nat32|Word32) -> G.nop + | Type.(Int8|Nat8|Word8|Int16|Nat16|Word16) as ty -> compile_shrU_const (shift_of_type ty) + | _ -> assert false (* Makes sure that the word payload (e.g. operation result) is in the MSB bits of the word. *) let msb_adjust = function - | Type.Word32 -> G.nop + | Type.(Int32|Nat32|Word32) -> G.nop | ty -> shift_leftWordNtoI32 (shift_of_type ty) (* Makes sure that the word representation invariant is restored. *) @@ -1406,6 +1404,9 @@ module UnboxedSmallWord = struct set_res ^^ compile_unboxed_const 4l))) + let lit env ty v = + compile_unboxed_const Int32.(shift_left (of_int v) (to_int (shift_of_type ty))) + end (* UnboxedSmallWord *) type comparator = Lt | Le | Ge | Gt @@ -1418,15 +1419,15 @@ sig (* word from SR.Vanilla, lossy, raw bits *) val truncate_to_word32 : E.t -> G.t - val _truncate_to_word64 : E.t -> G.t + val truncate_to_word64 : E.t -> G.t (* unsigned word to SR.Vanilla *) val from_word32 : E.t -> G.t val from_word64 : E.t -> G.t (* signed word to SR.Vanilla *) - val from_signed_word64 : E.t -> G.t val from_signed_word32 : E.t -> G.t + val from_signed_word64 : E.t -> G.t (* buffers *) (* given a numeric object on stack (vanilla), @@ -1476,24 +1477,24 @@ sig (* given a numeric object on the stack as skewed pointer, check whether it can be faithfully stored in N bits, including a leading sign bit leaves boolean result on the stack - N must be 2..63 + N must be 2..64 *) - val _fits_signed_bits : E.t -> int -> G.t + val fits_signed_bits : E.t -> int -> G.t (* given a numeric object on the stack as skewed pointer, check whether it can be faithfully stored in N unsigned bits leaves boolean result on the stack N must be 1..64 *) - val _fits_unsigned_bits : E.t -> int -> G.t + val fits_unsigned_bits : E.t -> int -> G.t end [@@@warning "-60"] (* Do not warn about unused module *) module BigNum64 : BigNumType = struct - include BoxedWord + include BoxedWord64 (* examine the skewed pointer and determine if the unsigned number it points to fits into N bits *) - let _fits_unsigned_bits env = function + let fits_unsigned_bits env = function | 64 -> G.i Drop ^^ compile_unboxed_one | n when n > 64 || n < 1 -> assert false | n -> @@ -1504,8 +1505,9 @@ module BigNum64 : BigNumType = struct (* examine the skewed pointer and determine if the signed number it points to fits into N bits *) - let _fits_signed_bits env = function - | n when n > 63 || n < 2 -> assert false + let fits_signed_bits env = function + | n when n > 64 || n < 2 -> assert false + | 64 -> Bool.lit true | n -> let set_num, get_num = new_local64 env "num" in unbox env ^^ set_num ^^ get_num ^^ get_num ^^ @@ -1519,19 +1521,20 @@ module BigNum64 : BigNumType = struct let to_word32 env = let (set_num, get_num) = new_local env "num" in set_num ^^ get_num ^^ - _fits_unsigned_bits env 32 ^^ - E.else_trap_with env "Losing precision" ^^ + fits_unsigned_bits env 32 ^^ + E.else_trap_with env "losing precision" ^^ get_num ^^ unbox env ^^ - BoxedWord.to_word32 env + BoxedWord64.to_word32 env - let from_word32 env = BoxedWord.from_word32 env ^^ box env - let from_signed_word32 env = BoxedWord.from_signed_word32 env ^^ box env - let to_word64 env = unbox env ^^ BoxedWord.to_word64 env - let from_word64 env = BoxedWord.from_word64 env ^^ box env + let from_word32 env = BoxedWord64.from_word32 env ^^ box env + let from_signed_word32 env = BoxedWord64.from_signed_word32 env ^^ box env + let from_signed_word64 env = G.i Unreachable (* FIXME *) + let to_word64 env = unbox env ^^ BoxedWord64.to_word64 env + let from_word64 env = BoxedWord64.from_word64 env ^^ box env - let truncate_to_word32 env = unbox env ^^ BoxedWord.to_word32 env - let _truncate_to_word64 env = unbox env ^^ BoxedWord.to_word64 env + let truncate_to_word32 env = unbox env ^^ BoxedWord64.to_word32 env + let truncate_to_word64 env = unbox env ^^ BoxedWord64.to_word64 env let compile_lit env n = compile_const_64 (Big_int.int64_of_big_int n) ^^ box env @@ -1577,11 +1580,11 @@ module BigNum64 : BigNumType = struct let compile_signed_mod = with_both_unboxed (G.i (Binary (Wasm.Values.I64 I64Op.RemS))) let compile_unsigned_div = with_both_unboxed (G.i (Binary (Wasm.Values.I64 I64Op.DivU))) let compile_unsigned_rem = with_both_unboxed (G.i (Binary (Wasm.Values.I64 I64Op.RemU))) - let compile_unsigned_sub env = with_both_unboxed (BoxedWord.compile_unsigned_sub env) env - let compile_unsigned_pow env = with_both_unboxed (BoxedWord.compile_unsigned_pow env) env + let compile_unsigned_sub env = with_both_unboxed (BoxedWord64.compile_unsigned_sub env) env + let compile_unsigned_pow env = with_both_unboxed (BoxedWord64.compile_unsigned_pow env) env let compile_neg env = - Func.share_code1 env "negInt" ("n", I32Type) [I32Type] (fun env get_n -> + Func.share_code1 env "neg" ("n", I32Type) [I32Type] (fun env get_n -> compile_lit env (Big_int.big_int_of_int 0) ^^ get_n ^^ compile_signed_sub env @@ -1609,7 +1612,7 @@ module BigNumLibtommmath : BigNumType = struct let to_word64 env = E.call_import env "rts" "bigint_to_word64_trap" let truncate_to_word32 env = E.call_import env "rts" "bigint_to_word32_wrap" - let _truncate_to_word64 env = E.call_import env "rts" "bigint_to_word64_wrap" + let truncate_to_word64 env = E.call_import env "rts" "bigint_to_word64_wrap" let from_word32 env = E.call_import env "rts" "bigint_of_word32" let from_word64 env = E.call_import env "rts" "bigint_of_word64" @@ -1700,11 +1703,11 @@ module BigNumLibtommmath : BigNumType = struct | Gt -> "rts_bigint_gt" in G.i (Call (nr (E.built_in env fn))) - let _fits_signed_bits env bits = + let fits_signed_bits env bits = G.i (Call (nr (E.built_in env ("rts_bigint_2complement_bits")))) ^^ - compile_unboxed_const (Int32.of_int (bits - 1)) ^^ + compile_unboxed_const (Int32.of_int bits) ^^ G.i (Compare (Wasm.Values.I32 I32Op.LeU)) - let _fits_unsigned_bits env bits = + let fits_unsigned_bits env bits = G.i (Call (nr (E.built_in env ("rts_bigint_count_bits")))) ^^ compile_unboxed_const (Int32.of_int bits) ^^ G.i (Compare (Wasm.Values.I32 I32Op.LeU)) @@ -2865,10 +2868,10 @@ module Serialization = struct begin match t with | Prim Nat -> inc_data_size (get_x ^^ BigNum.compile_data_size_unsigned env) | Prim Int -> inc_data_size (get_x ^^ BigNum.compile_data_size_signed env) - | Prim Word64 -> inc_data_size (compile_unboxed_const 8l) (* 64 bit *) - | Prim Word8 -> inc_data_size (compile_unboxed_const 1l) - | Prim Word16 -> inc_data_size (compile_unboxed_const 2l) - | Prim Word32 -> inc_data_size (compile_unboxed_const 4l) + | Prim (Int8|Nat8|Word8) -> inc_data_size (compile_unboxed_const 1l) + | Prim (Int16|Nat16|Word16) -> inc_data_size (compile_unboxed_const 2l) + | Prim (Int32|Nat32|Word32) -> inc_data_size (compile_unboxed_const 4l) + | Prim (Int64|Nat64|Word64) -> inc_data_size (compile_unboxed_const 8l) | Prim Bool -> inc_data_size (compile_unboxed_const 1l) | Tup ts -> G.concat_mapi (fun i t -> @@ -2968,22 +2971,22 @@ module Serialization = struct get_x ^^ BigNum.compile_store_to_data_buf_signed env ^^ advance_data_buf - | Prim Word64 -> + | Prim (Int64|Nat64|Word64) -> get_data_buf ^^ - get_x ^^ BoxedWord.unbox env ^^ + get_x ^^ BoxedWord64.unbox env ^^ G.i (Store {ty = I64Type; align = 0; offset = 0l; sz = None}) ^^ compile_unboxed_const 8l ^^ advance_data_buf - | Prim Word32 -> + | Prim (Int32|Nat32|Word32) -> get_data_buf ^^ get_x ^^ BoxedSmallWord.unbox env ^^ G.i (Store {ty = I32Type; align = 0; offset = 0l; sz = None}) ^^ compile_unboxed_const 4l ^^ advance_data_buf - | Prim Word16 -> + | Prim (Int16|Nat16|Word16) -> get_data_buf ^^ get_x ^^ UnboxedSmallWord.lsb_adjust Word16 ^^ G.i (Store {ty = I32Type; align = 0; offset = 0l; sz = Some Wasm.Memory.Pack16}) ^^ compile_unboxed_const 2l ^^ advance_data_buf - | Prim Word8 -> + | Prim (Int8|Nat8|Word8) -> get_data_buf ^^ get_x ^^ UnboxedSmallWord.lsb_adjust Word8 ^^ G.i (Store {ty = I32Type; align = 0; offset = 0l; sz = Some Wasm.Memory.Pack8}) ^^ @@ -3098,22 +3101,22 @@ module Serialization = struct get_data_buf ^^ BigNum.compile_load_from_data_buf_signed env ^^ advance_data_buf - | Prim Word64 -> + | Prim (Int64|Nat64|Word64) -> get_data_buf ^^ G.i (Load {ty = I64Type; align = 2; offset = 0l; sz = None}) ^^ - BoxedWord.box env ^^ + BoxedWord64.box env ^^ compile_unboxed_const 8l ^^ advance_data_buf (* 64 bit *) - | Prim Word32 -> + | Prim (Int32|Nat32|Word32) -> get_data_buf ^^ G.i (Load {ty = I32Type; align = 0; offset = 0l; sz = None}) ^^ BoxedSmallWord.box env ^^ compile_unboxed_const 4l ^^ advance_data_buf - | Prim Word16 -> + | Prim (Int16|Nat16|Word16) -> get_data_buf ^^ G.i (Load {ty = I32Type; align = 0; offset = 0l; sz = Some (Wasm.Memory.Pack16, Wasm.Memory.ZX)}) ^^ UnboxedSmallWord.msb_adjust Word16 ^^ compile_unboxed_const 2l ^^ advance_data_buf - | Prim Word8 -> + | Prim (Int8|Nat8|Word8) -> get_data_buf ^^ G.i (Load {ty = I32Type; align = 0; offset = 0l; sz = Some (Wasm.Memory.Pack8, Wasm.Memory.ZX)}) ^^ UnboxedSmallWord.msb_adjust Word8 ^^ @@ -3594,14 +3597,15 @@ module StackRep = struct if n = 1 then UnboxedReference else UnboxedRefTuple n (* The stack rel of a primitive type, i.e. what the binary operators expect *) - let of_type : Type.typ -> t = function - | Type.Prim Type.Bool -> bool - | Type.Prim Type.Nat - | Type.Prim Type.Int -> Vanilla - | Type.Prim Type.Word64 -> UnboxedWord64 - | Type.Prim Type.Word32 -> UnboxedWord32 - | Type.Prim Type.(Word8 | Word16 | Char) -> Vanilla - | Type.Prim Type.Text -> Vanilla + let of_type t = + let open Type in + match normalize t with + | Prim Bool -> SR.bool + | Prim (Nat | Int) -> Vanilla + | Prim (Nat64 | Int64 | Word64) -> UnboxedWord64 + | Prim (Nat32 | Int32 | Word32) -> UnboxedWord32 + | Prim (Nat8 | Nat16 | Int8 | Int16 | Word8 | Word16 | Char) -> Vanilla + | Prim Text -> Vanilla | p -> todo "of_type" (Arrange_ir.typ p) Vanilla let to_block_type env = function @@ -3716,8 +3720,8 @@ module StackRep = struct adjust env sr (UnboxedTuple n) ^^ unbox_reference_n env n - | UnboxedWord64, Vanilla -> BoxedWord.box env - | Vanilla, UnboxedWord64 -> BoxedWord.unbox env + | UnboxedWord64, Vanilla -> BoxedWord64.box env + | Vanilla, UnboxedWord64 -> BoxedWord64.unbox env | UnboxedWord32, Vanilla -> BoxedSmallWord.box env | Vanilla, UnboxedWord32 -> BoxedSmallWord.unbox env @@ -4360,18 +4364,31 @@ end (* AllocHow *) (* The actual compiler code that looks at the AST *) +let nat64_to_int64 n = + let open Big_int in + let twoRaised63 = power_int_positive_int 2 63 in + let q, r = quomod_big_int (Value.Nat64.to_big_int n) twoRaised63 in + if sign_big_int q = 0 then r else sub_big_int r twoRaised63 + let compile_lit env lit = try match lit with (* Booleans are directly in Vanilla representation *) | BoolLit false -> SR.bool, Bool.lit false | BoolLit true -> SR.bool, Bool.lit true - (* This maps int to int32, instead of a proper arbitrary precision library *) | IntLit n | NatLit n -> SR.Vanilla, BigNum.compile_lit env n | Word8Lit n -> SR.Vanilla, compile_unboxed_const (Value.Word8.to_bits n) | Word16Lit n -> SR.Vanilla, compile_unboxed_const (Value.Word16.to_bits n) | Word32Lit n -> SR.UnboxedWord32, compile_unboxed_const n | Word64Lit n -> SR.UnboxedWord64, compile_const_64 n + | Int8Lit n -> SR.Vanilla, UnboxedSmallWord.lit env Type.Int8 (Value.Int_8.to_int n) + | Nat8Lit n -> SR.Vanilla, UnboxedSmallWord.lit env Type.Nat8 (Value.Nat8.to_int n) + | Int16Lit n -> SR.Vanilla, UnboxedSmallWord.lit env Type.Int16 (Value.Int_16.to_int n) + | Nat16Lit n -> SR.Vanilla, UnboxedSmallWord.lit env Type.Nat16 (Value.Nat16.to_int n) + | Int32Lit n -> SR.UnboxedWord32, compile_unboxed_const (Int32.of_int (Value.Int_32.to_int n)) + | Nat32Lit n -> SR.UnboxedWord32, compile_unboxed_const (Int32.of_int (Value.Nat32.to_int n)) + | Int64Lit n -> SR.UnboxedWord64, compile_const_64 (Big_int.int64_of_big_int (Value.Int_64.to_big_int n)) + | Nat64Lit n -> SR.UnboxedWord64, compile_const_64 (Big_int.int64_of_big_int (nat64_to_int64 n)) | CharLit c -> SR.Vanilla, compile_unboxed_const Int32.(shift_left (of_int c) 8) | NullLit -> SR.Vanilla, Opt.null | TextLit t -> SR.Vanilla, Text.lit env t @@ -4384,6 +4401,10 @@ let compile_lit_as env sr_out lit = let sr_in, code = compile_lit env lit in code ^^ StackRep.adjust env sr_in sr_out +let prim_of_typ ty = match Type.normalize ty with + | Type.Prim ty -> ty + | _ -> assert false + let compile_unop env t op = let open Operator in match op, t with @@ -4397,13 +4418,34 @@ let compile_unop env t op = get_n ^^ G.i (Binary (Wasm.Values.I64 I64Op.Sub)) ) - | NegOp, Type.Prim Type.(Word8 | Word16 | Word32) -> + | NegOp, Type.(Prim Int64) -> + SR.UnboxedWord64, + Func.share_code1 env "neg_trap" ("n", I64Type) [I64Type] (fun env get_n -> + get_n ^^ + compile_const_64 0x8000000000000000L ^^ + G.i (Compare (Wasm.Values.I64 I64Op.Eq)) ^^ + E.then_trap_with env "arithmetic overflow" ^^ + compile_const_64 0L ^^ + get_n ^^ + G.i (Binary (Wasm.Values.I64 I64Op.Sub)) + ) + | NegOp, Type.(Prim (Word8 | Word16 | Word32)) -> StackRep.of_type t, Func.share_code1 env "neg32" ("n", I32Type) [I32Type] (fun env get_n -> compile_unboxed_zero ^^ get_n ^^ G.i (Binary (Wasm.Values.I32 I32Op.Sub)) ) + | NegOp, Type.(Prim (Int8 | Int16 | Int32)) -> + StackRep.of_type t, + Func.share_code1 env "neg32_trap" ("n", I32Type) [I32Type] (fun env get_n -> + get_n ^^ + compile_eq_const 0x80000000l ^^ + E.then_trap_with env "arithmetic overflow" ^^ + compile_unboxed_zero ^^ + get_n ^^ + G.i (Binary (Wasm.Values.I32 I32Op.Sub)) + ) | NotOp, Type.(Prim Word64) -> SR.UnboxedWord64, compile_const_64 (-1L) ^^ @@ -4472,7 +4514,7 @@ let rec compile_binop env t op = get_exp ^^ BigNum.compile_is_negative env ^^ E.then_trap_with env "negative power" ^^ get_n ^^ get_exp ^^ pow - | Type.(Prim Word64), PowOp -> BoxedWord.compile_unsigned_pow env + | Type.(Prim Word64), PowOp -> BoxedWord64.compile_unsigned_pow env | Type.(Prim Nat), PowOp -> BigNum.compile_unsigned_pow env | Type.(Prim Word64), AndOp -> G.i (Binary (Wasm.Values.I64 I64Op.And)) | Type.Prim Type.(Word8 | Word16 | Word32), AndOp -> G.i (Binary (Wasm.Values.I32 I32Op.And)) @@ -4516,28 +4558,31 @@ let rec compile_binop env t op = | _ -> todo_trap env "compile_binop" (Arrange_ops.binop op) ) -let compile_eq env t = match t with - | Type.Prim Type.Text -> Text.compare env - | Type.Prim Type.Bool -> G.i (Compare (Wasm.Values.I32 I32Op.Eq)) +let compile_eq env = function + | Type.(Prim Text) -> Text.compare env + | Type.(Prim Bool) -> G.i (Compare (Wasm.Values.I32 I32Op.Eq)) | Type.(Prim (Nat | Int)) -> BigNum.compile_eq env - | Type.(Prim Word64) -> G.i (Compare (Wasm.Values.I64 I64Op.Eq)) - | Type.(Prim (Word8 | Word16 | Word32 | Char)) -> G.i (Compare (Wasm.Values.I32 I32Op.Eq)) + | Type.(Prim (Int64 | Nat64 | Word64)) -> G.i (Compare (Wasm.Values.I64 I64Op.Eq)) + | Type.(Prim (Int8 | Nat8 | Word8 | Int16 | Nat16 | Word16 | Int32 | Nat32 | Word32 | Char)) -> + G.i (Compare (Wasm.Values.I32 I32Op.Eq)) | _ -> todo_trap env "compile_eq" (Arrange_ops.relop Operator.EqOp) let get_relops = Operator.(function - | GeOp -> Ge, I64Op.GeU, I32Op.GeU, I32Op.GeS - | GtOp -> Gt, I64Op.GtU, I32Op.GtU, I32Op.GtS - | LeOp -> Le, I64Op.LeU, I32Op.LeU, I32Op.LeS - | LtOp -> Lt, I64Op.LtU, I32Op.LtU, I32Op.LtS + | GeOp -> Ge, I64Op.GeU, I64Op.GeS, I32Op.GeU, I32Op.GeS + | GtOp -> Gt, I64Op.GtU, I64Op.GtS, I32Op.GtU, I32Op.GtS + | LeOp -> Le, I64Op.LeU, I64Op.LeS, I32Op.LeU, I32Op.LeS + | LtOp -> Lt, I64Op.LtU, I64Op.LtS, I32Op.LtU, I32Op.LtS | _ -> failwith "uncovered relop") let compile_comparison env t op = - let bigintop, u64op, u32op, s32op = get_relops op in + let bigintop, u64op, s64op, u32op, s32op = get_relops op in let open Type in match t with | Nat | Int -> BigNum.compile_relop env bigintop - | Word64 -> G.i (Compare (Wasm.Values.I64 u64op)) - | Word8 | Word16 | Word32 | Char -> G.i (Compare (Wasm.Values.I32 u32op)) + | Nat64 | Word64 -> G.i (Compare (Wasm.Values.I64 u64op)) + | Nat8 | Word8 | Nat16 | Word16 | Nat32 | Word32 | Char -> G.i (Compare (Wasm.Values.I32 u32op)) + | Int64 -> G.i (Compare (Wasm.Values.I64 s64op)) + | Int8 | Int16 | Int32 -> G.i (Compare (Wasm.Values.I32 s32op)) | _ -> todo_trap env "compile_comparison" (Arrange_type.prim t) let compile_relop env t op = @@ -4546,9 +4591,9 @@ let compile_relop env t op = match t, op with | _, EqOp -> compile_eq env t | _, NeqOp -> compile_eq env t ^^ - G.if_ (StackRep.to_block_type env SR.bool) (Bool.lit false) (Bool.lit true) - | Type.Prim Type.(Nat | Int | Word8 | Word16 | Word32 | Word64 | Char as t1), op1 -> - compile_comparison env t1 op1 + G.i (Test (Wasm.Values.I32 I32Op.Eqz)) + | Type.(Prim (Nat | Nat8 | Nat16 | Nat32 | Nat64 | Int | Int8 | Int16 | Int32 | Int64 | Word8 | Word16 | Word32 | Word64 | Char as t1)), op1 -> + compile_comparison env t1 op1 | _ -> todo_trap env "compile_relop" (Arrange_ops.relop op) (* compile_load_field implements the various “virtual fields”, which @@ -4670,43 +4715,120 @@ and compile_exp (env : E.t) ae exp = compile_exp_vanilla env ae e ^^ BigNum.to_word64 env + | "Nat64->Word64" + | "Int64->Word64" + | "Word64->Nat64" + | "Word64->Int64" + | "Nat32->Word32" + | "Int32->Word32" + | "Word32->Nat32" + | "Word32->Int32" + | "Nat16->Word16" + | "Int16->Word16" + | "Word16->Nat16" + | "Word16->Int16" + | "Nat8->Word8" + | "Int8->Word8" + | "Word8->Nat8" + | "Word8->Int8" -> + SR.Vanilla, + compile_exp_vanilla env ae e ^^ + G.nop + + | "Int->Int64" -> + SR.UnboxedWord64, + compile_exp_vanilla env ae e ^^ + Func.share_code1 env "Int->Int64" ("n", I32Type) [I64Type] (fun env get_n -> + get_n ^^ + BigNum.fits_signed_bits env 64 ^^ + E.else_trap_with env "losing precision" ^^ + get_n ^^ + BigNum.truncate_to_word64 env) + + | "Int->Int32" + | "Int->Int16" + | "Int->Int8" -> + let ty = exp.note.note_typ in + StackRep.of_type ty, + let pty = prim_of_typ ty in + compile_exp_vanilla env ae e ^^ + Func.share_code1 env (UnboxedSmallWord.name_of_type pty "Int->") ("n", I32Type) [I32Type] (fun env get_n -> + get_n ^^ + BigNum.fits_signed_bits env (UnboxedSmallWord.bits_of_type pty) ^^ + E.else_trap_with env "losing precision" ^^ + get_n ^^ + BigNum.truncate_to_word32 env ^^ + UnboxedSmallWord.msb_adjust pty) + + | "Nat->Nat64" -> + SR.UnboxedWord64, + compile_exp_vanilla env ae e ^^ + Func.share_code1 env "Nat->Nat64" ("n", I32Type) [I64Type] (fun env get_n -> + get_n ^^ + BigNum.fits_unsigned_bits env 64 ^^ + E.else_trap_with env "losing precision" ^^ + get_n ^^ + BigNum.truncate_to_word64 env) + + | "Nat->Nat32" + | "Nat->Nat16" + | "Nat->Nat8" -> + let ty = exp.note.note_typ in + StackRep.of_type ty, + let pty = prim_of_typ ty in + compile_exp_vanilla env ae e ^^ + Func.share_code1 env (UnboxedSmallWord.name_of_type pty "Nat->") ("n", I32Type) [I32Type] (fun env get_n -> + get_n ^^ + BigNum.fits_unsigned_bits env (UnboxedSmallWord.bits_of_type pty) ^^ + E.else_trap_with env "losing precision" ^^ + get_n ^^ + BigNum.truncate_to_word32 env ^^ + UnboxedSmallWord.msb_adjust pty) + | "Char->Word32" -> SR.UnboxedWord32, compile_exp_vanilla env ae e ^^ UnboxedSmallWord.unbox_codepoint + | "Nat8->Nat" | "Word8->Nat" -> SR.Vanilla, compile_exp_vanilla env ae e ^^ Prim.prim_shiftWordNtoUnsigned env (UnboxedSmallWord.shift_of_type Type.Word8) + | "Int8->Int" | "Word8->Int" -> SR.Vanilla, compile_exp_vanilla env ae e ^^ Prim.prim_shiftWordNtoSigned env (UnboxedSmallWord.shift_of_type Type.Word8) + | "Nat16->Nat" | "Word16->Nat" -> SR.Vanilla, compile_exp_vanilla env ae e ^^ Prim.prim_shiftWordNtoUnsigned env (UnboxedSmallWord.shift_of_type Type.Word16) + | "Int16->Int" | "Word16->Int" -> SR.Vanilla, compile_exp_vanilla env ae e ^^ Prim.prim_shiftWordNtoSigned env (UnboxedSmallWord.shift_of_type Type.Word16) + | "Nat32->Nat" | "Word32->Nat" -> SR.Vanilla, compile_exp_as env ae SR.UnboxedWord32 e ^^ Prim.prim_word32toNat env + | "Int32->Int" | "Word32->Int" -> SR.Vanilla, compile_exp_as env ae SR.UnboxedWord32 e ^^ Prim.prim_word32toInt env + | "Nat64->Nat" | "Word64->Nat" -> SR.Vanilla, compile_exp_as env ae SR.UnboxedWord64 e ^^ BigNum.from_word64 env - + | "Int64->Int" | "Word64->Int" -> SR.Vanilla, compile_exp_as env ae SR.UnboxedWord64 e ^^ @@ -5008,11 +5130,52 @@ and compile_lit_pat env l = | BoolLit true -> G.nop | BoolLit false -> - Bool.lit false ^^ - G.i (Compare (Wasm.Values.I32 I32Op.Eq)) + G.i (Test (Wasm.Values.I32 I32Op.Eqz)) | (NatLit _ | IntLit _) -> compile_lit_as env SR.Vanilla l ^^ BigNum.compile_eq env + | Nat8Lit _ -> + snd (compile_lit env l) ^^ + compile_eq env Type.(Prim Nat8) + | Nat16Lit _ -> + snd (compile_lit env l) ^^ + compile_eq env Type.(Prim Nat16) + | Nat32Lit _ -> + BoxedSmallWord.unbox env ^^ + snd (compile_lit env l) ^^ + compile_eq env Type.(Prim Nat32) + | Nat64Lit _ -> + BoxedWord64.unbox env ^^ + snd (compile_lit env l) ^^ + compile_eq env Type.(Prim Nat64) + | Int8Lit _ -> + snd (compile_lit env l) ^^ + compile_eq env Type.(Prim Int8) + | Int16Lit _ -> + snd (compile_lit env l) ^^ + compile_eq env Type.(Prim Int16) + | Int32Lit _ -> + BoxedSmallWord.unbox env ^^ + snd (compile_lit env l) ^^ + compile_eq env Type.(Prim Int32) + | Int64Lit _ -> + BoxedWord64.unbox env ^^ + snd (compile_lit env l) ^^ + compile_eq env Type.(Prim Int64) + | Word8Lit _ -> + snd (compile_lit env l) ^^ + compile_eq env Type.(Prim Word8) + | Word16Lit _ -> + snd (compile_lit env l) ^^ + compile_eq env Type.(Prim Word16) + | Word32Lit _ -> + BoxedSmallWord.unbox env ^^ + snd (compile_lit env l) ^^ + compile_eq env Type.(Prim Word32) + | Word64Lit _ -> + BoxedWord64.unbox env ^^ + snd (compile_lit env l) ^^ + compile_eq env Type.(Prim Word64) | (TextLit t) -> Text.lit env t ^^ Text.compare env diff --git a/src/interpreter/interpret.ml b/src/interpreter/interpret.ml index 6bcca1ef848..1131e0b1905 100644 --- a/src/interpreter/interpret.ml +++ b/src/interpreter/interpret.ml @@ -213,7 +213,15 @@ let interpret_lit env lit : V.value = | NullLit -> V.Null | BoolLit b -> V.Bool b | NatLit n -> V.Int n + | Nat8Lit n -> V.Nat8 n + | Nat16Lit n -> V.Nat16 n + | Nat32Lit n -> V.Nat32 n + | Nat64Lit n -> V.Nat64 n | IntLit i -> V.Int i + | Int8Lit i -> V.Int8 i + | Int16Lit i -> V.Int16 i + | Int32Lit i -> V.Int32 i + | Int64Lit i -> V.Int64 i | Word8Lit w -> V.Word8 w | Word16Lit w -> V.Word16 w | Word32Lit w -> V.Word32 w @@ -277,7 +285,9 @@ and interpret_exp_mut env exp (k : V.value V.cont) = | LitE lit -> k (interpret_lit env lit) | UnE (ot, op, exp1) -> - interpret_exp env exp1 (fun v1 -> k (Operator.unop !ot op v1)) + interpret_exp env exp1 + (fun v1 -> + k (try Operator.unop !ot op v1 with Invalid_argument s -> trap exp.at "%s" s)) | BinE (ot, exp1, op, exp2) -> interpret_exp env exp1 (fun v1 -> interpret_exp env exp2 (fun v2 -> @@ -346,13 +356,8 @@ and interpret_exp_mut env exp (k : V.value V.cont) = let call_conv, f = V.as_func v1 in check_call_conv exp1 call_conv; check_call_conv_arg env exp v2 call_conv; + last_region := exp.at; (* in case the following throws *) f v2 k -(* - try - let _, f = V.as_func v1 in f v2 k - with Invalid_argument s -> - trap exp.at "%s" s -*) ) ) | BlockE decs -> @@ -539,7 +544,15 @@ and match_lit lit v : bool = | NullLit, V.Null -> true | BoolLit b, V.Bool b' -> b = b' | NatLit n, V.Int n' -> V.Int.eq n n' + | Nat8Lit n, V.Nat8 n' -> V.Nat8.eq n n' + | Nat16Lit n, V.Nat16 n' -> V.Nat16.eq n n' + | Nat32Lit n, V.Nat32 n' -> V.Nat32.eq n n' + | Nat64Lit n, V.Nat64 n' -> V.Nat64.eq n n' | IntLit i, V.Int i' -> V.Int.eq i i' + | Int8Lit i, V.Int8 i' -> V.Int_8.eq i i' + | Int16Lit i, V.Int16 i' -> V.Int_16.eq i i' + | Int32Lit i, V.Int32 i' -> V.Int_32.eq i i' + | Int64Lit i, V.Int64 i' -> V.Int_64.eq i i' | Word8Lit w, V.Word8 w' -> w = w' | Word16Lit w, V.Word16 w' -> w = w' | Word32Lit w, V.Word32 w' -> w = w' @@ -720,7 +733,8 @@ let interpret_prog flags scope p : (V.value * scope) option = let vo = ref None in let ve = ref V.Env.empty in Scheduler.queue (fun () -> - interpret_block env p.it (Some ve) (fun v -> vo := Some v) + try interpret_block env p.it (Some ve) (fun v -> vo := Some v) + with Invalid_argument s -> trap !last_region "%s" s ); Scheduler.run (); let scope = { val_env = !ve; lib_env = scope.lib_env } in @@ -745,7 +759,7 @@ let interpret_library flags scope (filename, p) : scope = let v = match p.it with | [ { it = ExpD _ ; _ } ] -> Lib.Option.value !vo - (* HACK: to be remove once we restrict libraries to expressions *) + (* HACK: to be removed once we restrict libraries to expressions *) | ds -> V.Obj (V.Env.map Lib.Promise.value (!ve)) in diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index 04c4a43f456..796e3a25c96 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -235,7 +235,15 @@ let interpret_lit env lit : V.value = | NullLit -> V.Null | BoolLit b -> V.Bool b | NatLit n -> V.Int n + | Nat8Lit n -> V.Nat8 n + | Nat16Lit n -> V.Nat16 n + | Nat32Lit n -> V.Nat32 n + | Nat64Lit n -> V.Nat64 n | IntLit i -> V.Int i + | Int8Lit i -> V.Int8 i + | Int16Lit i -> V.Int16 i + | Int32Lit i -> V.Int32 i + | Int64Lit i -> V.Int64 i | Word8Lit w -> V.Word8 w | Word16Lit w -> V.Word16 w | Word32Lit w -> V.Word32 w @@ -293,7 +301,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = | LitE lit -> k (interpret_lit env lit) | UnE (ot, op, exp1) -> - interpret_exp env exp1 (fun v1 -> k (Operator.unop ot op v1)) + interpret_exp env exp1 (fun v1 -> k (try Operator.unop ot op v1 with Invalid_argument s -> trap exp.at "%s" s)) | ShowE (ot, exp1) -> interpret_exp env exp1 (fun v -> if Show.can_show ot @@ -349,18 +357,12 @@ and interpret_exp_mut env exp (k : V.value V.cont) = ) | CallE (_cc, exp1, typs, exp2) -> interpret_exp env exp1 (fun v1 -> - interpret_exp env exp2 (fun v2 -> - let call_conv, f = V.as_func v1 in - check_call_conv exp1 call_conv; - check_call_conv_arg env exp v2 call_conv; - f v2 k - -(* - try - let _, f = V.as_func v1 in f v2 k - with Invalid_argument s -> - trap exp.at "%s" s -*) + interpret_exp env exp2 (fun v2 -> + let call_conv, f = V.as_func v1 in + check_call_conv exp1 call_conv; + check_call_conv_arg env exp v2 call_conv; + last_region := exp.at; (* in case the following throws *) + f v2 k ) ) | BlockE (decs, exp1) -> @@ -537,7 +539,15 @@ and match_lit lit v : bool = | NullLit, V.Null -> true | BoolLit b, V.Bool b' -> b = b' | NatLit n, V.Int n' -> V.Int.eq n n' + | Nat8Lit n, V.Nat8 n' -> V.Nat8.eq n n' + | Nat16Lit n, V.Nat16 n' -> V.Nat16.eq n n' + | Nat32Lit n, V.Nat32 n' -> V.Nat32.eq n n' + | Nat64Lit n, V.Nat64 n' -> V.Nat64.eq n n' | IntLit i, V.Int i' -> V.Int.eq i i' + | Int8Lit i, V.Int8 i' -> V.Int_8.eq i i' + | Int16Lit i, V.Int16 i' -> V.Int_16.eq i i' + | Int32Lit i, V.Int32 i' -> V.Int_32.eq i i' + | Int64Lit i, V.Int64 i' -> V.Int_64.eq i i' | Word8Lit w, V.Word8 w' -> w = w' | Word16Lit w, V.Word16 w' -> w = w' | Word32Lit w, V.Word32 w' -> w = w' @@ -667,7 +677,8 @@ let interpret_prog flags scope ((ds, exp), flavor) : scope = let ve = ref V.Env.empty in try Scheduler.queue (fun () -> - interpret_block env (Some ve) ds exp (fun v -> ()) + try interpret_block env (Some ve) ds exp (fun v -> ()) + with Invalid_argument s -> trap !last_region "%s" s ); Scheduler.run (); !ve diff --git a/src/ir_passes/show.ml b/src/ir_passes/show.ml index 671508859ef..05beea657ca 100644 --- a/src/ir_passes/show.ml +++ b/src/ir_passes/show.ml @@ -277,6 +277,42 @@ let show_for : T.typ -> Ir.dec * T.typ list = fun t -> | T.Prim T.Int -> define_show t (invoke_prelude_show "@text_of_Int" t (argE t)), [] + | T.(Prim Nat8) -> + define_show t (invoke_prelude_show "@text_of_Nat8" t (argE t)), + [] + | T.(Prim Nat16) -> + define_show t (invoke_prelude_show "@text_of_Nat16" t (argE t)), + [] + | T.(Prim Nat32) -> + define_show t (invoke_prelude_show "@text_of_Nat32" t (argE t)), + [] + | T.(Prim Nat64) -> + define_show t (invoke_prelude_show "@text_of_Nat64" t (argE t)), + [] + | T.(Prim Int8) -> + define_show t (invoke_prelude_show "@text_of_Int8" t (argE t)), + [] + | T.(Prim Int16) -> + define_show t (invoke_prelude_show "@text_of_Int16" t (argE t)), + [] + | T.(Prim Int32) -> + define_show t (invoke_prelude_show "@text_of_Int32" t (argE t)), + [] + | T.(Prim Int64) -> + define_show t (invoke_prelude_show "@text_of_Int64" t (argE t)), + [] + | T.(Prim Word8) -> + define_show t (invoke_prelude_show "@text_of_Word8" t (argE t)), + [] + | T.(Prim Word16) -> + define_show t (invoke_prelude_show "@text_of_Word16" t (argE t)), + [] + | T.(Prim Word32) -> + define_show t (invoke_prelude_show "@text_of_Word32" t (argE t)), + [] + | T.(Prim Word64) -> + define_show t (invoke_prelude_show "@text_of_Word64" t (argE t)), + [] | T.Prim T.Text -> define_show t (invoke_prelude_show "@text_of_Text" t (argE t)), [] diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index bc416ccb6b1..cca1cf48e60 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -29,6 +29,10 @@ let apply_sign op l = Syntax.(match op, l with | PosOp, l -> l | NegOp, NatLit n -> NatLit (Value.Nat.sub Value.Nat.zero n) | NegOp, IntLit n -> IntLit (Value.Int.sub Value.Int.zero n) + | NegOp, Int8Lit n -> Int8Lit (Value.Int_8.sub Value.Int_8.zero n) + | NegOp, Int16Lit n -> Int16Lit (Value.Int_16.sub Value.Int_16.zero n) + | NegOp, Int32Lit n -> Int32Lit (Value.Int_32.sub Value.Int_32.zero n) + | NegOp, Int64Lit n -> Int64Lit (Value.Int_64.sub Value.Int_64.zero n) | _, _ -> raise (Invalid_argument "Invalid signed pattern") ) @@ -272,7 +276,15 @@ and lit l = match l with | S.NullLit -> I.NullLit | S.BoolLit x -> I.BoolLit x | S.NatLit x -> I.NatLit x + | S.Nat8Lit x -> I.Nat8Lit x + | S.Nat16Lit x -> I.Nat16Lit x + | S.Nat32Lit x -> I.Nat32Lit x + | S.Nat64Lit x -> I.Nat64Lit x | S.IntLit x -> I.IntLit x + | S.Int8Lit x -> I.Int8Lit x + | S.Int16Lit x -> I.Int16Lit x + | S.Int32Lit x -> I.Int32Lit x + | S.Int64Lit x -> I.Int64Lit x | S.Word8Lit x -> I.Word8Lit x | S.Word16Lit x -> I.Word16Lit x | S.Word32Lit x -> I.Word32Lit x diff --git a/src/prelude/prelude.ml b/src/prelude/prelude.ml index 17f4fb91013..cea163e645b 100644 --- a/src/prelude/prelude.ml +++ b/src/prelude/prelude.ml @@ -6,7 +6,15 @@ type Shared = prim "Shared"; type Null = prim "Null"; type Bool = prim "Bool"; type Nat = prim "Nat"; +type Nat8 = prim "Nat8"; +type Nat16 = prim "Nat16"; +type Nat32 = prim "Nat32"; +type Nat64 = prim "Nat64"; type Int = prim "Int"; +type Int8 = prim "Int8"; +type Int16 = prim "Int16"; +type Int32 = prim "Int32"; +type Int64 = prim "Int64"; type Word8 = prim "Word8"; type Word16 = prim "Word16"; type Word32 = prim "Word32"; @@ -58,6 +66,43 @@ func hashInt(x : Int) : Word32 { }; // Conversions + + +func int64ToInt(n : Int64) : Int = (prim "Int64->Int" : Int64 -> Int) n; +func intToInt64(n : Int) : Int64 = (prim "Int->Int64" : Int -> Int64) n; +func int64ToWord64(n : Int64) : Word64 = (prim "Int64->Word64" : Int64 -> Word64) n; +func word64ToInt64(n : Word64) : Int64 = (prim "Word64->Int64" : Word64 -> Int64) n; +func int32ToInt(n : Int32) : Int = (prim "Int32->Int" : Int32 -> Int) n; +func intToInt32(n : Int) : Int32 = (prim "Int->Int32" : Int -> Int32) n; +func int32ToWord32(n : Int32) : Word32 = (prim "Int32->Word32" : Int32 -> Word32) n; +func word32ToInt32(n : Word32) : Int32 = (prim "Word32->Int32" : Word32 -> Int32) n; +func int16ToInt(n : Int16) : Int = (prim "Int16->Int" : Int16 -> Int) n; +func intToInt16(n : Int) : Int16 = (prim "Int->Int16" : Int -> Int16) n; +func int16ToWord16(n : Int16) : Word16 = (prim "Int16->Word16" : Int16 -> Word16) n; +func word16ToInt16(n : Word16) : Int16 = (prim "Word16->Int16" : Word16 -> Int16) n; +func int8ToInt(n : Int8) : Int = (prim "Int8->Int" : Int8 -> Int) n; +func intToInt8(n : Int) : Int8 = (prim "Int->Int8" : Int -> Int8) n; +func int8ToWord8(n : Int8) : Word8 = (prim "Int8->Word8" : Int8 -> Word8) n; +func word8ToInt8(n : Word8) : Int8 = (prim "Word8->Int8" : Word8 -> Int8) n; + +func nat64ToNat(n : Nat64) : Nat = (prim "Nat64->Nat" : Nat64 -> Nat) n; +func natToNat64(n : Nat) : Nat64 = (prim "Nat->Nat64" : Nat -> Nat64) n; +func nat64ToWord64(n : Nat64) : Word64 = (prim "Nat64->Word64" : Nat64 -> Word64) n; +func word64ToNat64(n : Word64) : Nat64 = (prim "Word64->Nat64" : Word64 -> Nat64) n; +func nat32ToNat(n : Nat32) : Nat = (prim "Nat32->Nat" : Nat32 -> Nat) n; +func natToNat32(n : Nat) : Nat32 = (prim "Nat->Nat32" : Nat -> Nat32) n; +func nat32ToWord32(n : Nat32) : Word32 = (prim "Nat32->Word32" : Nat32 -> Word32) n; +func word32ToNat32(n : Word32) : Nat32 = (prim "Word32->Nat32" : Word32 -> Nat32) n; +func nat16ToNat(n : Nat16) : Nat = (prim "Nat16->Nat" : Nat16 -> Nat) n; +func natToNat16(n : Nat) : Nat16 = (prim "Nat->Nat16" : Nat -> Nat16) n; +func nat16ToWord16(n : Nat16) : Word16 = (prim "Nat16->Word16" : Nat16 -> Word16) n; +func word16ToNat16(n : Word16) : Nat16 = (prim "Word16->Nat16" : Word16 -> Nat16) n; +func nat8ToNat(n : Nat8) : Nat = (prim "Nat8->Nat" : Nat8 -> Nat) n; +func natToNat8(n : Nat) : Nat8 = (prim "Nat->Nat8" : Nat -> Nat8) n; +func nat8ToWord8(n : Nat8) : Word8 = (prim "Nat8->Word8" : Nat8 -> Word8) n; +func word8ToNat8(n : Word8) : Nat8 = (prim "Word8->Nat8" : Word8 -> Nat8) n; + + func natToWord8(n : Nat) : Word8 = (prim "Nat->Word8" : Nat -> Word8) n; func word8ToNat(n : Word8) : Nat = (prim "Word8->Nat" : Word8 -> Nat) n; func intToWord8(n : Int) : Word8 = (prim "Int->Word8" : Int -> Word8) n; @@ -141,6 +186,20 @@ func @text_of_Int(x : Int) : Text { } }; +func @text_of_Nat8(x : Nat8) : Text = @text_of_Nat (nat8ToNat x); +func @text_of_Nat16(x : Nat16) : Text = @text_of_Nat (nat16ToNat x); +func @text_of_Nat32(x : Nat32) : Text = @text_of_Nat (nat32ToNat x); +func @text_of_Nat64(x : Nat64) : Text = @text_of_Nat (nat64ToNat x); +func @text_of_Int8(x : Int8) : Text = @text_of_Int (int8ToInt x); +func @text_of_Int16(x : Int16) : Text = @text_of_Int (int16ToInt x); +func @text_of_Int32(x : Int32) : Text = @text_of_Int (int32ToInt x); +func @text_of_Int64(x : Int64) : Text = @text_of_Int (int64ToInt x); +func @text_of_Word8(x : Word8) : Text = @text_of_Nat (word8ToNat x); +func @text_of_Word16(x : Word16) : Text = @text_of_Nat (word16ToNat x); +func @text_of_Word32(x : Word32) : Text = @text_of_Nat (word32ToNat x); +func @text_of_Word64(x : Word64) : Text = @text_of_Nat (word64ToNat x); + + func @text_of_Bool(b : Bool) : Text { if (b) "true" else "false" }; diff --git a/test/fail/ok/outrange-int64lower.run-ir.ok b/test/fail/ok/outrange-int64lower.run-ir.ok new file mode 100644 index 00000000000..d3ac87f6451 --- /dev/null +++ b/test/fail/ok/outrange-int64lower.run-ir.ok @@ -0,0 +1 @@ +prelude:71.36-71.72: execution error, numeric overflow diff --git a/test/fail/ok/outrange-int64lower.run-low.ok b/test/fail/ok/outrange-int64lower.run-low.ok new file mode 100644 index 00000000000..d3ac87f6451 --- /dev/null +++ b/test/fail/ok/outrange-int64lower.run-low.ok @@ -0,0 +1 @@ +prelude:71.36-71.72: execution error, numeric overflow diff --git a/test/fail/ok/outrange-int64lower.run.ok b/test/fail/ok/outrange-int64lower.run.ok new file mode 100644 index 00000000000..d3ac87f6451 --- /dev/null +++ b/test/fail/ok/outrange-int64lower.run.ok @@ -0,0 +1 @@ +prelude:71.36-71.72: execution error, numeric overflow diff --git a/test/fail/ok/outrange-int64lower.wasm-run.ok b/test/fail/ok/outrange-int64lower.wasm-run.ok new file mode 100644 index 00000000000..a87edfdf573 --- /dev/null +++ b/test/fail/ok/outrange-int64lower.wasm-run.ok @@ -0,0 +1 @@ +_out/outrange-int64lower.wasm:0x___: runtime trap: unreachable executed diff --git a/test/fail/ok/outrange-int64negation.run-ir.ok b/test/fail/ok/outrange-int64negation.run-ir.ok new file mode 100644 index 00000000000..01c2fd0b1c4 --- /dev/null +++ b/test/fail/ok/outrange-int64negation.run-ir.ok @@ -0,0 +1 @@ +outrange-int64negation.as:1.9-1.33: execution error, value out of bounds diff --git a/test/fail/ok/outrange-int64negation.run-low.ok b/test/fail/ok/outrange-int64negation.run-low.ok new file mode 100644 index 00000000000..01c2fd0b1c4 --- /dev/null +++ b/test/fail/ok/outrange-int64negation.run-low.ok @@ -0,0 +1 @@ +outrange-int64negation.as:1.9-1.33: execution error, value out of bounds diff --git a/test/fail/ok/outrange-int64negation.run.ok b/test/fail/ok/outrange-int64negation.run.ok new file mode 100644 index 00000000000..01c2fd0b1c4 --- /dev/null +++ b/test/fail/ok/outrange-int64negation.run.ok @@ -0,0 +1 @@ +outrange-int64negation.as:1.9-1.33: execution error, value out of bounds diff --git a/test/fail/ok/outrange-int64negation.wasm-run.ok b/test/fail/ok/outrange-int64negation.wasm-run.ok new file mode 100644 index 00000000000..4db5b575d1b --- /dev/null +++ b/test/fail/ok/outrange-int64negation.wasm-run.ok @@ -0,0 +1 @@ +_out/outrange-int64negation.wasm:0x___: runtime trap: unreachable executed diff --git a/test/fail/ok/outrange-int64upper.run-ir.ok b/test/fail/ok/outrange-int64upper.run-ir.ok new file mode 100644 index 00000000000..d3ac87f6451 --- /dev/null +++ b/test/fail/ok/outrange-int64upper.run-ir.ok @@ -0,0 +1 @@ +prelude:71.36-71.72: execution error, numeric overflow diff --git a/test/fail/ok/outrange-int64upper.run-low.ok b/test/fail/ok/outrange-int64upper.run-low.ok new file mode 100644 index 00000000000..d3ac87f6451 --- /dev/null +++ b/test/fail/ok/outrange-int64upper.run-low.ok @@ -0,0 +1 @@ +prelude:71.36-71.72: execution error, numeric overflow diff --git a/test/fail/ok/outrange-int64upper.run.ok b/test/fail/ok/outrange-int64upper.run.ok new file mode 100644 index 00000000000..d3ac87f6451 --- /dev/null +++ b/test/fail/ok/outrange-int64upper.run.ok @@ -0,0 +1 @@ +prelude:71.36-71.72: execution error, numeric overflow diff --git a/test/fail/ok/outrange-int64upper.wasm-run.ok b/test/fail/ok/outrange-int64upper.wasm-run.ok new file mode 100644 index 00000000000..6ec234a4e85 --- /dev/null +++ b/test/fail/ok/outrange-int64upper.wasm-run.ok @@ -0,0 +1 @@ +_out/outrange-int64upper.wasm:0x___: runtime trap: unreachable executed diff --git a/test/fail/ok/outrange-int8lower.run-ir.ok b/test/fail/ok/outrange-int8lower.run-ir.ok new file mode 100644 index 00000000000..e0fee3eba79 --- /dev/null +++ b/test/fail/ok/outrange-int8lower.run-ir.ok @@ -0,0 +1 @@ +prelude:83.34-83.68: execution error, numeric overflow diff --git a/test/fail/ok/outrange-int8lower.run-low.ok b/test/fail/ok/outrange-int8lower.run-low.ok new file mode 100644 index 00000000000..e0fee3eba79 --- /dev/null +++ b/test/fail/ok/outrange-int8lower.run-low.ok @@ -0,0 +1 @@ +prelude:83.34-83.68: execution error, numeric overflow diff --git a/test/fail/ok/outrange-int8lower.run.ok b/test/fail/ok/outrange-int8lower.run.ok new file mode 100644 index 00000000000..e0fee3eba79 --- /dev/null +++ b/test/fail/ok/outrange-int8lower.run.ok @@ -0,0 +1 @@ +prelude:83.34-83.68: execution error, numeric overflow diff --git a/test/fail/ok/outrange-int8lower.wasm-run.ok b/test/fail/ok/outrange-int8lower.wasm-run.ok new file mode 100644 index 00000000000..054470b6319 --- /dev/null +++ b/test/fail/ok/outrange-int8lower.wasm-run.ok @@ -0,0 +1 @@ +_out/outrange-int8lower.wasm:0x___: runtime trap: unreachable executed diff --git a/test/fail/ok/outrange-int8upper.run-ir.ok b/test/fail/ok/outrange-int8upper.run-ir.ok new file mode 100644 index 00000000000..e0fee3eba79 --- /dev/null +++ b/test/fail/ok/outrange-int8upper.run-ir.ok @@ -0,0 +1 @@ +prelude:83.34-83.68: execution error, numeric overflow diff --git a/test/fail/ok/outrange-int8upper.run-low.ok b/test/fail/ok/outrange-int8upper.run-low.ok new file mode 100644 index 00000000000..e0fee3eba79 --- /dev/null +++ b/test/fail/ok/outrange-int8upper.run-low.ok @@ -0,0 +1 @@ +prelude:83.34-83.68: execution error, numeric overflow diff --git a/test/fail/ok/outrange-int8upper.run.ok b/test/fail/ok/outrange-int8upper.run.ok new file mode 100644 index 00000000000..e0fee3eba79 --- /dev/null +++ b/test/fail/ok/outrange-int8upper.run.ok @@ -0,0 +1 @@ +prelude:83.34-83.68: execution error, numeric overflow diff --git a/test/fail/ok/outrange-int8upper.wasm-run.ok b/test/fail/ok/outrange-int8upper.wasm-run.ok new file mode 100644 index 00000000000..2d769f0989f --- /dev/null +++ b/test/fail/ok/outrange-int8upper.wasm-run.ok @@ -0,0 +1 @@ +_out/outrange-int8upper.wasm:0x___: runtime trap: unreachable executed diff --git a/test/fail/ok/outrange-nat64.run-ir.ok b/test/fail/ok/outrange-nat64.run-ir.ok new file mode 100644 index 00000000000..72676577d7c --- /dev/null +++ b/test/fail/ok/outrange-nat64.run-ir.ok @@ -0,0 +1 @@ +prelude:88.36-88.72: execution error, numeric overflow diff --git a/test/fail/ok/outrange-nat64.run-low.ok b/test/fail/ok/outrange-nat64.run-low.ok new file mode 100644 index 00000000000..72676577d7c --- /dev/null +++ b/test/fail/ok/outrange-nat64.run-low.ok @@ -0,0 +1 @@ +prelude:88.36-88.72: execution error, numeric overflow diff --git a/test/fail/ok/outrange-nat64.run.ok b/test/fail/ok/outrange-nat64.run.ok new file mode 100644 index 00000000000..72676577d7c --- /dev/null +++ b/test/fail/ok/outrange-nat64.run.ok @@ -0,0 +1 @@ +prelude:88.36-88.72: execution error, numeric overflow diff --git a/test/fail/ok/outrange-nat64.wasm-run.ok b/test/fail/ok/outrange-nat64.wasm-run.ok new file mode 100644 index 00000000000..c2173dffda9 --- /dev/null +++ b/test/fail/ok/outrange-nat64.wasm-run.ok @@ -0,0 +1 @@ +_out/outrange-nat64.wasm:0x___: runtime trap: unreachable executed diff --git a/test/fail/ok/outrange-nat8.run-ir.ok b/test/fail/ok/outrange-nat8.run-ir.ok new file mode 100644 index 00000000000..1767cb22299 --- /dev/null +++ b/test/fail/ok/outrange-nat8.run-ir.ok @@ -0,0 +1 @@ +prelude:100.34-100.68: execution error, numeric overflow diff --git a/test/fail/ok/outrange-nat8.run-low.ok b/test/fail/ok/outrange-nat8.run-low.ok new file mode 100644 index 00000000000..1767cb22299 --- /dev/null +++ b/test/fail/ok/outrange-nat8.run-low.ok @@ -0,0 +1 @@ +prelude:100.34-100.68: execution error, numeric overflow diff --git a/test/fail/ok/outrange-nat8.run.ok b/test/fail/ok/outrange-nat8.run.ok new file mode 100644 index 00000000000..1767cb22299 --- /dev/null +++ b/test/fail/ok/outrange-nat8.run.ok @@ -0,0 +1 @@ +prelude:100.34-100.68: execution error, numeric overflow diff --git a/test/fail/ok/outrange-nat8.wasm-run.ok b/test/fail/ok/outrange-nat8.wasm-run.ok new file mode 100644 index 00000000000..e64bc25b4c7 --- /dev/null +++ b/test/fail/ok/outrange-nat8.wasm-run.ok @@ -0,0 +1 @@ +_out/outrange-nat8.wasm:0x___: runtime trap: unreachable executed diff --git a/test/fail/outrange-int64lower.as b/test/fail/outrange-int64lower.as new file mode 100644 index 00000000000..a9a6a6625e8 --- /dev/null +++ b/test/fail/outrange-int64lower.as @@ -0,0 +1 @@ +let _ = intToInt64 (- 2 ** 63 - 1); diff --git a/test/fail/outrange-int64negation.as b/test/fail/outrange-int64negation.as new file mode 100644 index 00000000000..bfa832e02f9 --- /dev/null +++ b/test/fail/outrange-int64negation.as @@ -0,0 +1 @@ +let _ = - intToInt64 (- 2 ** 63); // this should trap diff --git a/test/fail/outrange-int64upper.as b/test/fail/outrange-int64upper.as new file mode 100644 index 00000000000..1c87d142031 --- /dev/null +++ b/test/fail/outrange-int64upper.as @@ -0,0 +1 @@ +let _ = intToInt64 (2 ** 63); diff --git a/test/fail/outrange-int8lower.as b/test/fail/outrange-int8lower.as new file mode 100644 index 00000000000..9cd498631cb --- /dev/null +++ b/test/fail/outrange-int8lower.as @@ -0,0 +1 @@ +let _ = intToInt8 (-129); diff --git a/test/fail/outrange-int8upper.as b/test/fail/outrange-int8upper.as new file mode 100644 index 00000000000..95fc54f289a --- /dev/null +++ b/test/fail/outrange-int8upper.as @@ -0,0 +1 @@ +let _ = intToInt8 128; diff --git a/test/fail/outrange-nat64.as b/test/fail/outrange-nat64.as new file mode 100644 index 00000000000..5fc78dd9b38 --- /dev/null +++ b/test/fail/outrange-nat64.as @@ -0,0 +1 @@ +let _ = natToNat64 (2 ** 64); diff --git a/test/fail/outrange-nat8.as b/test/fail/outrange-nat8.as new file mode 100644 index 00000000000..cfce83df95f --- /dev/null +++ b/test/fail/outrange-nat8.as @@ -0,0 +1 @@ +let _ = natToNat8 256 diff --git a/test/repl/ok/outrange-int-nat.stdout.ok b/test/repl/ok/outrange-int-nat.stdout.ok new file mode 100644 index 00000000000..daa7c921fa1 --- /dev/null +++ b/test/repl/ok/outrange-int-nat.stdout.ok @@ -0,0 +1,34 @@ +ActorScript 0.1 interpreter +> 127 : Int8 +> prelude:83.34-83.68: execution error, numeric overflow +> -128 : Int8 +> prelude:83.34-83.68: execution error, numeric overflow +> 32_767 : Int16 +> prelude:79.36-79.72: execution error, numeric overflow +> -32_768 : Int16 +> prelude:79.36-79.72: execution error, numeric overflow +> 2_147_483_647 : Int32 +> prelude:75.36-75.72: execution error, numeric overflow +> -2_147_483_648 : Int32 +> prelude:75.36-75.72: execution error, numeric overflow +> 9_223_372_036_854_775_807 : Int64 +> prelude:71.36-71.72: execution error, numeric overflow +> -9_223_372_036_854_775_808 : Int64 +> prelude:71.36-71.72: execution error, numeric overflow +> 255 : Nat8 +> prelude:100.34-100.68: execution error, numeric overflow +> 65_535 : Nat16 +> prelude:96.36-96.72: execution error, numeric overflow +> 4_294_967_295 : Nat32 +> prelude:92.36-92.72: execution error, numeric overflow +> 18_446_744_073_709_551_615 : Nat64 +> prelude:88.36-88.72: execution error, numeric overflow +> -127 : Int8 +> -127 : Int8 +> -32_767 : Int16 +> -32_767 : Int16 +> -2_147_483_647 : Int32 +> -2_147_483_647 : Int32 +> -9_223_372_036_854_775_807 : Int64 +> -9_223_372_036_854_775_807 : Int64 +> diff --git a/test/repl/outrange-int-nat.sh b/test/repl/outrange-int-nat.sh new file mode 100755 index 00000000000..8554b134278 --- /dev/null +++ b/test/repl/outrange-int-nat.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash +# Tests that the repl Int* and Nat* types properly trap +${ASC:-$(dirname "$BASH_SOURCE")/../../src/asc} -i <<__END__ +intToInt8 0x7F; +intToInt8 0x80; +intToInt8 (-0x80); +intToInt8 (-0x81); + +intToInt16 0x7FFF; +intToInt16 0x8000; +intToInt16 (-0x8000); +intToInt16 (-0x8001); + +intToInt32 0x7FFFFFFF; +intToInt32 0x80000000; +intToInt32 (-0x80000000); +intToInt32 (-0x80000001); + +intToInt64 0x7FFFFFFFFFFFFFFF; +intToInt64 0x8000000000000000; +intToInt64 (-0x8000000000000000); +intToInt64 (-0x8000000000000001); + + +natToNat8 0xFF; +natToNat8 0x100; + +natToNat16 0xFFFF; +natToNat16 0x10000; + +natToNat32 0xFFFFFFFF; +natToNat32 0x100000000; + +natToNat64 0xFFFFFFFFFFFFFFFF; +natToNat64 0x10000000000000000; + + +-127 : Int8; +-0x7F : Int8; +-32767 : Int16; +-0x7FFF : Int16; +-2147483647 : Int32; +-0x7FFFFFFF : Int32; +-9223372036854775807 : Int64; +-0x7FFFFFFFFFFFFFFF : Int64; + +__END__ diff --git a/test/run-dfinity/data-params.as b/test/run-dfinity/data-params.as index 68207c6323d..b2c1eadbcfd 100644 --- a/test/run-dfinity/data-params.as +++ b/test/run-dfinity/data-params.as @@ -61,13 +61,30 @@ let a = actor { printInt(c); print("\n"); }; - incwords(w16 : Word16, w32 : Word32, w64 : Word64) : () { + incwords(w8 : Word8, w16 : Word16, w32 : Word32, w64 : Word64) : () { + c += word8ToInt(w8); c += word16ToInt(w16); c += word32ToInt(w32); c += word64ToInt(w64); printInt(c); print("\n"); }; + incnats(n8 : Nat8, n16 : Nat16, n32 : Nat32, n64 : Nat64) : () { + c += nat8ToNat(n8); + c += nat16ToNat(n16); + c += nat32ToNat(n32); + c += nat64ToNat(n64); + printInt(c); + print("\n"); + }; + incints(i8 : Int8, i16 : Int16, i32 : Int32, i64 : Int64) : () { + c += int8ToInt(i8); + c += int16ToInt(i16); + c += int32ToInt(i32); + c += int64ToInt(i64); + printInt(c); + print("\n"); + }; }; @@ -92,8 +109,10 @@ a.printLabeledOpt(?"Foo2: "); a.incn(10000000000000); a.inci(10000000000000); a.inci(-20000000000000); -a.incwords(1,2,3); -a.incwords(-1,-2,-3); +a.incwords(1,2,3,4); +a.incwords(-1,-2,-3,-4); +a.incnats(1,2,3,4); +a.incints(1,2,3,4);//(-1,-2,-3,-4); a.incn(2**100); a.inci(2**100); a.inci(-(2**101)); diff --git a/test/run-dfinity/ok/data-params.dvm-run.ok b/test/run-dfinity/ok/data-params.dvm-run.ok index b59714f09cc..f32875d2100 100644 --- a/test/run-dfinity/ok/data-params.dvm-run.ok +++ b/test/run-dfinity/ok/data-params.dvm-run.ok @@ -19,8 +19,10 @@ Foo2: 1006211 10000001006211 20000001006211 1006211 -1006217 -1006211 -1267650600228229401496704211587 -2535301200456458802993407416963 +1006221 1006211 +1006221 +1006231 +1267650600228229401496704211607 +2535301200456458802993407416983 +1006231 diff --git a/test/run-dfinity/ok/data-params.run-ir.ok b/test/run-dfinity/ok/data-params.run-ir.ok index e4cd9453940..19fd485396a 100644 --- a/test/run-dfinity/ok/data-params.run-ir.ok +++ b/test/run-dfinity/ok/data-params.run-ir.ok @@ -20,8 +20,10 @@ Foo2: 1006211 10000001006211 20000001006211 1006211 -1006217 -1006211 -1267650600228229401496704211587 -2535301200456458802993407416963 +1006221 1006211 +1006221 +1006231 +1267650600228229401496704211607 +2535301200456458802993407416983 +1006231 diff --git a/test/run-dfinity/ok/data-params.run-low.ok b/test/run-dfinity/ok/data-params.run-low.ok index e4cd9453940..19fd485396a 100644 --- a/test/run-dfinity/ok/data-params.run-low.ok +++ b/test/run-dfinity/ok/data-params.run-low.ok @@ -20,8 +20,10 @@ Foo2: 1006211 10000001006211 20000001006211 1006211 -1006217 -1006211 -1267650600228229401496704211587 -2535301200456458802993407416963 +1006221 1006211 +1006221 +1006231 +1267650600228229401496704211607 +2535301200456458802993407416983 +1006231 diff --git a/test/run-dfinity/ok/data-params.run.ok b/test/run-dfinity/ok/data-params.run.ok index e4cd9453940..19fd485396a 100644 --- a/test/run-dfinity/ok/data-params.run.ok +++ b/test/run-dfinity/ok/data-params.run.ok @@ -20,8 +20,10 @@ Foo2: 1006211 10000001006211 20000001006211 1006211 -1006217 -1006211 -1267650600228229401496704211587 -2535301200456458802993407416963 +1006221 1006211 +1006221 +1006231 +1267650600228229401496704211607 +2535301200456458802993407416983 +1006231 diff --git a/test/run-dfinity/ok/show.dvm-run.ok b/test/run-dfinity/ok/show.dvm-run.ok index d48b386b82f..819767efd2e 100644 --- a/test/run-dfinity/ok/show.dvm-run.ok +++ b/test/run-dfinity/ok/show.dvm-run.ok @@ -15,7 +15,10 @@ false [1, 2, 3] [var 1, 2, 3] {bar = true; foo = 42} -{bar = true; foo = 42} (#foo) (#bar 42) (#foo 42) +42 +42 +42 +-42 diff --git a/test/run-dfinity/ok/show.run-ir.ok b/test/run-dfinity/ok/show.run-ir.ok index d48b386b82f..819767efd2e 100644 --- a/test/run-dfinity/ok/show.run-ir.ok +++ b/test/run-dfinity/ok/show.run-ir.ok @@ -15,7 +15,10 @@ false [1, 2, 3] [var 1, 2, 3] {bar = true; foo = 42} -{bar = true; foo = 42} (#foo) (#bar 42) (#foo 42) +42 +42 +42 +-42 diff --git a/test/run-dfinity/ok/show.run-low.ok b/test/run-dfinity/ok/show.run-low.ok index d48b386b82f..819767efd2e 100644 --- a/test/run-dfinity/ok/show.run-low.ok +++ b/test/run-dfinity/ok/show.run-low.ok @@ -15,7 +15,10 @@ false [1, 2, 3] [var 1, 2, 3] {bar = true; foo = 42} -{bar = true; foo = 42} (#foo) (#bar 42) (#foo 42) +42 +42 +42 +-42 diff --git a/test/run-dfinity/ok/show.run.ok b/test/run-dfinity/ok/show.run.ok index d48b386b82f..819767efd2e 100644 --- a/test/run-dfinity/ok/show.run.ok +++ b/test/run-dfinity/ok/show.run.ok @@ -15,7 +15,10 @@ false [1, 2, 3] [var 1, 2, 3] {bar = true; foo = 42} -{bar = true; foo = 42} (#foo) (#bar 42) (#foo 42) +42 +42 +42 +-42 diff --git a/test/run-dfinity/show.as b/test/run-dfinity/show.as index 779b9aa0d5e..8f9ca5619a7 100644 --- a/test/run-dfinity/show.as +++ b/test/run-dfinity/show.as @@ -17,7 +17,10 @@ printLn(debug_show ([1,2,3])); printLn(debug_show ([var 1,2,3])); class Foo() { let foo : Int = 42; var bar : Bool = true ; private hidden = [1,2] }; printLn(debug_show (Foo())); -printLn(debug_show (Foo())); printLn(debug_show (#foo ())); printLn(debug_show (#bar 42)); printLn(debug_show ((#foo 42): {#foo : Int; #bar : Text})); +printLn(debug_show (42 : Word16)); +printLn(debug_show (42 : Nat8)); +printLn(debug_show (42 : Int32)); +printLn(debug_show (intToInt64 (-42))); diff --git a/test/run/conversions.as b/test/run/conversions.as index d1a53c2045d..17f3297accb 100644 --- a/test/run/conversions.as +++ b/test/run/conversions.as @@ -21,36 +21,70 @@ assert(word32ToNat 42 == 42); assert(word32ToNat 2147483647 == 2147483647); // 2**31 - 1 assert(word32ToNat 4294967295 == 4294967295); // 2**32 - 1 +func forall (f : T -> (), l : [T]) = for (e in l.vals()) { f e }; + { func roundtrip(n : Nat) = assert (word32ToNat (natToWord32 n) == n); - roundtrip 0; - roundtrip 10; - roundtrip 100; - roundtrip 1000; - roundtrip 10000; - roundtrip 100000; - roundtrip 1000000; - roundtrip 10000000; - roundtrip 100000000; - roundtrip 1000000000; - roundtrip 0x7FFFFFFF; - roundtrip 0xFFFFFFFF; + forall(roundtrip, [0, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 0x7FFFFFFF, 0xFFFFFFFF]); }; { func roundtrip(w : Word32) = assert (natToWord32 (word32ToNat w) == w); - roundtrip 0; - roundtrip 10; - roundtrip 100; - roundtrip 1000; - roundtrip 10000; - roundtrip 100000; - roundtrip 1000000; - roundtrip 10000000; - roundtrip 100000000; - roundtrip 1000000000; - roundtrip 0x7FFFFFFF; - roundtrip 0xFFFFFFFF; + forall(roundtrip, [0, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 0x7FFFFFFF, 0xFFFFFFFF]); + + + + func roundtripNat64(w : Word64) = assert (nat64ToWord64 (word64ToNat64 w) == w); + forall(roundtripNat64, [0, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 0x7FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFFFFFFFFFF]); + + func roundtripInt64(w : Word64) = assert (int64ToWord64 (word64ToInt64 w) == w); + forall(roundtripInt64, [0, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 0x7FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFFFFFFFFFF]); + + func roundtrip64i(w : Int) = assert (int64ToInt (intToInt64 w) == w); + forall(roundtrip64i, [0, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 0x7FFFFFFF, 0x7FFFFFFFFFFFFFFF]); + forall(roundtrip64i, [-10, -100, -1000, -10000, -100000, -1000000, -10000000, -100000000, -1000000000, -2147483648, -9223372036854775808]); + func roundtrip64n(w : Nat) = assert (nat64ToNat (natToNat64 w) == w); + forall(roundtrip64n, [0, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 0x7FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFFFFFFFFFF]); + + + + func roundtripNat32(w : Word32) = assert (nat32ToWord32 (word32ToNat32 w) == w); + forall(roundtripNat32, [0, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 0x7FFFFFFF, 0xFFFFFFFF]); + + func roundtripInt32(w : Word32) = assert (int32ToWord32 (word32ToInt32 w) == w); + forall(roundtripInt32, [0, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 0x7FFFFFFF, 0xFFFFFFFF]); + + func roundtrip32i(w : Int) = assert (int32ToInt (intToInt32 w) == w); + forall(roundtrip32i, [0, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 0x7FFFFFFF]); + forall(roundtrip32i, [-10, -100, -1000, -10000, -100000, -1000000, -10000000, -100000000, -1000000000, -2147483648]); + func roundtrip32n(w : Nat) = assert (nat32ToNat (natToNat32 w) == w); + forall(roundtrip32n, [0, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 0x7FFFFFFF, 0xFFFFFFFF]); + + + func roundtripNat16(w : Word16) = assert (nat16ToWord16 (word16ToNat16 w) == w); + forall(roundtripNat16, [0, 10, 100, 1000, 10000, 0xFFFF]); + + func roundtripInt16(w : Word16) = assert (int16ToWord16 (word16ToInt16 w) == w); + forall(roundtripInt16, [0, 10, 100, 1000, 10000, 0xFFFF]); + + func roundtrip16i(w : Int) = assert (int16ToInt (intToInt16 w) == w); + forall(roundtrip16i, [0, 10, 100, 1000, 10000, 0x7FFF]); + forall(roundtrip16i, [-10, -100, -1000, -10000, -32768]); + func roundtrip16n(w : Nat) = assert (nat16ToNat (natToNat16 w) == w); + forall(roundtrip16n, [0, 10, 100, 1000, 10000, 0xFFFF]); + + + func roundtripNat8(w : Word8) = assert (nat8ToWord8 (word8ToNat8 w) == w); + forall(roundtripNat8, [0, 10, 100, 0xFF]); + + func roundtripInt8(w : Word8) = assert (int8ToWord8 (word8ToInt8 w) == w); + forall(roundtripInt8, [0, 10, 100, 0xFF]); + + func roundtrip8i(w : Int) = assert (int8ToInt (intToInt8 w) == w); + forall(roundtrip8i, [0, 10, 100, 0x7F]); + forall(roundtrip8i, [-10, -100, -128]); + func roundtrip8n(w : Nat) = assert (nat8ToNat (natToNat8 w) == w); + forall(roundtrip8n, [0, 10, 100, 0xFF]); }; @@ -93,55 +127,17 @@ println(word32ToInt 4294967295); // == (-1) // 2**32 - 1 { func roundtrip(i : Int) = assert (word32ToInt (intToWord32 i) == i); - roundtrip 0; - roundtrip 10; - roundtrip 100; - roundtrip 1000; - roundtrip 10000; - roundtrip 100000; - roundtrip 1000000; - roundtrip 10000000; - roundtrip 100000000; - roundtrip 1000000000; - roundtrip 0x7FFFFFFF; - - roundtrip (-10); - roundtrip (-100); - roundtrip (-1000); - roundtrip (-10000); - roundtrip (-100000); - roundtrip (-1000000); - roundtrip (-10000000); - roundtrip (-100000000); - roundtrip (-1000000000); - roundtrip (-2147483648); + forall(roundtrip, [0, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 0x7FFFFFFF]); + + forall(roundtrip, [-10, -100, -1000, -10000, -100000, -1000000, -10000000, -100000000, -1000000000, -2147483648]); }; { func roundtrip(w : Word32) = assert (intToWord32 (word32ToInt w) == w); - roundtrip 0; - roundtrip 10; - roundtrip 100; - roundtrip 1000; - roundtrip 10000; - roundtrip 100000; - roundtrip 1000000; - roundtrip 10000000; - roundtrip 100000000; - roundtrip 1000000000; - roundtrip 0x7FFFFFFF; - roundtrip 0xFFFFFFFF; - - /*!*/ - roundtrip (-10); - roundtrip (-100); - roundtrip (-1000); - roundtrip (-10000); - roundtrip (-100000); - roundtrip (-1000000); - roundtrip (-10000000); - roundtrip (-100000000); - roundtrip (-1000000000); + forall(roundtrip, [0, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 0x7FFFFFFF, 0xFFFFFFFF]); + + /* non-canonical range for Word32 */ + forall(roundtrip, [-10, -100, -1000, -10000, -100000, -1000000, -10000000, -100000000, -1000000000]); }; @@ -157,14 +153,7 @@ assert(charToWord32 '\u{10ffff}' == (0x10FFFF : Word32)); { func roundtrip(w : Word32) = assert (charToWord32 (word32ToChar w) == w); - roundtrip 0; - roundtrip 10; - roundtrip 100; - roundtrip 1000; - roundtrip 10000; - roundtrip 100000; - roundtrip 1000000; - roundtrip 0x10FFFF; // largest code point + forall(roundtrip, [0, 10, 100, 1000, 10000, 100000, 1000000, 0x10FFFF]); // largest code point }; diff --git a/test/run/numeric-ops.as b/test/run/numeric-ops.as index 923a82c0c1b..67cfa38a61f 100644 --- a/test/run/numeric-ops.as +++ b/test/run/numeric-ops.as @@ -208,3 +208,51 @@ func testWord64(a : Word64, b : Word64) : [Word64] { verify([3, 18_446_744_073_709_551_613, 8, 18_446_744_073_709_551_614, 15, 0, 3, 243], testWord64(3, 5), func (a : Word64, b : Word64) : Bool = a == b); + + +func testInt64(a : Int64, b : Int64) : [Int64] { + let pos1 = + a; + let pos2 = (+ a) : Int64; + let neg1 = - a; + let neg2 = (- a) : Int64; + /*let sum1 = a + b; + let sum2 = (a + b) : Int64; + let diff1 = a - b; + let diff2 = (a - b) : Int64; + let prod1 = a * b; + let prod2 = (a * b) : Int64; + let rat1 = a / b; + let rat2 = (a / b) : Int64; + let mod1 = a % b; + let mod2 = (a % b) : Int64; + let pow1 = a ** b; + let pow2 = (a ** b) : Int64;*/ + [pos1, pos2, neg1, neg2, /*sum1, sum2, diff1, diff2, prod1, prod2, rat1, rat2, mod1, mod2, pow1, pow2*/] +}; + +verify([3, -3/*, 8, 18_446_744_073_709_551_614, 15, 0, 3, 243*/], testInt64(3, 5), + func (a : Int64, b : Int64) : Bool = a == b); + + +func testInt8(a : Int8, b : Int8) : [Int8] { + let pos1 = + a; + let pos2 = (+ a) : Int8; + let neg1 = - a; + let neg2 = (- a) : Int8; + /*let sum1 = a + b; + let sum2 = (a + b) : Int8; + let diff1 = a - b; + let diff2 = (a - b) : Int8; + let prod1 = a * b; + let prod2 = (a * b) : Int8; + let rat1 = a / b; + let rat2 = (a / b) : Int8; + let mod1 = a % b; + let mod2 = (a % b) : Int8; + let pow1 = a ** b; + let pow2 = (a ** b) : Int8;*/ + [pos1, pos2, neg1, neg2, /*sum1, sum2, diff1, diff2, prod1, prod2, rat1, rat2, mod1, mod2, pow1, pow2*/] +}; + +verify([3, -3/*, 8, -2, 15, 0, 3, 243*/], testInt8(3, 5), + func (a : Int8, b : Int8) : Bool = a == b); diff --git a/test/run/ranged-nums.as b/test/run/ranged-nums.as new file mode 100644 index 00000000000..5c8e270db51 --- /dev/null +++ b/test/run/ranged-nums.as @@ -0,0 +1,47 @@ +let _ = 255 : Nat8; +let _ = 65535 : Nat16; +let _ = 4_294_967_295 : Nat32; +let _ = 18_446_744_073_709_551_615 : Nat64; + + +let _ = 127 : Int8; +let _ = 32767 : Int16; +let _ = 2_147_483_647 : Int32; +let _ = 9_223_372_036_854_775_807 : Int64; + + +// TODO(gabor) below limits are off-by one, as explained +// in the open issue in #487. +let _ = -127 : Int8; +let _ = -32767 : Int16; +let _ = -2_147_483_647 : Int32; +let _ = -9_223_372_036_854_775_807 : Int64; + +// test patterns + +func n8 (n : Nat8) = assert (switch n { case 0 false; case 1 false; case 42 true; case _ false }); +func n16 (n : Nat16) = assert (switch n { case 0 false; case 1 false; case 65000 true; case _ false }); +func n32 (n : Nat32) = assert (switch n { case 0 false; case 1 false; case 4_294_967_295 true; case _ false }); +func n64 (n : Nat64) = assert (switch n { case 0 false; case 1 false; case 42 true; case _ false }); + + +n8 42; +n16 65000; +n32 4_294_967_295; +n64 42; + + +func i8 (n : Int8) = assert (switch n { case 0 false; case (-42) true; case 1 false; case 42 true; case _ false }); +func i16 (n : Int16) = assert (switch n { case 0 false; case (-32000) true; case 1 false; case 32000 true; case _ false }); +func i32 (n : Int32) = assert (switch n { case 0 false; case (-20000000) true; case 1 false; case 1_294_967_295 true; case _ false }); +func i64 (n : Int64) = assert (switch n { case 0 false; case (-420000000000) true; case 1 false; case 42 true; case _ false }); + + +i8 42; +i8 (-42); +i16 32000; +i16 (-32000); +i32 1_294_967_295; +i32 (-20000000); +i64 (-420000000000); +i64 42; diff --git a/test/run/words.as b/test/run/words.as index d2b9be2ec41..eb9f0444769 100644 --- a/test/run/words.as +++ b/test/run/words.as @@ -276,3 +276,17 @@ func checkpointJuliett() {}; assert (3 : Word8 ** (4 : Word8) == (81 : Word8)); assert (3 : Word8 ** (5 : Word8) == (243 : Word8)); }; + + +// check whether patterns work + +func w8 (n : Word8) = assert (switch n { case 0 false; case 1 false; case 42 true; case _ false }); +func w16 (n : Word16) = assert (switch n { case 0 false; case 1 false; case 65000 true; case _ false }); +func w32 (n : Word32) = assert (switch n { case 0 false; case 1 false; case 4_294_967_295 true; case _ false }); +func w64 (n : Word64) = assert (switch n { case 0 false; case 1 false; case 42 true; case _ false }); + + +w8 42; +w16 65000; +w32 4_294_967_295; +w64 42; From 3724d9d349343870c5c8d17d2b97044d4afc9a2b Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Tue, 18 Jun 2019 14:46:14 -0700 Subject: [PATCH 0179/1176] add import for idl --- src/exes/didc.ml | 19 +++---- src/idllib/arrange_idl.ml | 4 +- src/idllib/compile_js.ml | 1 + src/idllib/lexer.mll | 1 + src/idllib/parser.mly | 9 ++-- src/idllib/pipeline.ml | 99 +++++++++++++++++++++++------------ src/idllib/pipeline.mli | 15 +----- src/idllib/resolve_import.ml | 44 ++++++++++++++++ src/idllib/resolve_import.mli | 3 ++ src/idllib/syntax.ml | 8 ++- src/idllib/typing.ml | 23 ++++---- 11 files changed, 151 insertions(+), 75 deletions(-) create mode 100644 src/idllib/resolve_import.ml create mode 100644 src/idllib/resolve_import.mli diff --git a/src/exes/didc.ml b/src/exes/didc.ml index 75de9694f55..38085ce60f8 100644 --- a/src/exes/didc.ml +++ b/src/exes/didc.ml @@ -17,7 +17,7 @@ let add_arg source = args := !args @ [source] let set_mode m () = if !mode <> Default then begin - eprintf "asc: multiple execution modes specified"; exit 1 + eprintf "didc: multiple execution modes specified"; exit 1 end; mode := m @@ -37,21 +37,14 @@ let argspec = Arg.align (* Main *) -let exit_on_failure = function - | Ok x -> x - | Error errs -> - Diag.print_messages errs; - exit 1 - -let process_files files : unit = +let process_file file : unit = match !mode with | Default -> assert false | Check -> - let (_, msgs) = exit_on_failure (Pipeline.(check_file (List.hd files))) in - Diag.print_messages msgs + ignore (Diag.run (Pipeline.check_file file)) | Js -> - let out = exit_on_failure (Pipeline.(compile_js_file (List.hd files))) in + let out = Diag.run Pipeline.(compile_js_file file) in Buffer.contents out |> print_endline let print_exn exn = @@ -69,6 +62,8 @@ let () = try Arg.parse argspec add_arg usage; if !mode = Default then mode := Check; - process_files !args + match !args with + | [file] -> process_file file + | _ -> eprintf "didc can only take one .did file\n"; exit 1 with exn -> print_exn exn diff --git a/src/idllib/arrange_idl.ml b/src/idllib/arrange_idl.ml index 3e320b2d65a..27b7bf300c3 100644 --- a/src/idllib/arrange_idl.ml +++ b/src/idllib/arrange_idl.ml @@ -55,7 +55,9 @@ and typ t = match t.it with and dec d = match d.it with | TypD (x, t) -> - "TypD" $$ [id x] @ [typ t] + "TypD" $$ [id x] @ [typ t] + | ImportD (f, fp) -> + "ImportD" $$ [Atom (if !fp = "" then f else !fp)] and actor a = match a with | None -> Atom "NoActor" diff --git a/src/idllib/compile_js.ml b/src/idllib/compile_js.ml index 15db365ed43..49482b83fbb 100644 --- a/src/idllib/compile_js.ml +++ b/src/idllib/compile_js.ml @@ -87,6 +87,7 @@ let pp_dec ppf env dec = kwd ppf x.it; kwd ppf "="; pp_typ ppf env t + | ImportD _ -> () ); pp_close_box ppf (); pp_print_cut ppf () diff --git a/src/idllib/lexer.mll b/src/idllib/lexer.mll index b1d4eb8fa92..cccb54a8cdd 100644 --- a/src/idllib/lexer.mll +++ b/src/idllib/lexer.mll @@ -121,6 +121,7 @@ rule token = parse | '"'character*'\\'_ { error_nest (Lexing.lexeme_end_p lexbuf) lexbuf "illegal escape" } + | "import" { IMPORT } | "service" { SERVICE } | "func" { FUNC } | "type" { TYPE } diff --git a/src/idllib/parser.mly b/src/idllib/parser.mly index 762c108fe59..5732cd4c740 100644 --- a/src/idllib/parser.mly +++ b/src/idllib/parser.mly @@ -48,14 +48,14 @@ let record_fields fs = %token LPAR RPAR LCURLY RCURLY %token ARROW -%token FUNC TYPE SERVICE +%token FUNC TYPE SERVICE IMPORT %token SEMICOLON COMMA COLON EQ %token OPT VEC RECORD VARIANT BLOB %token NAT %token ID %token TEXT -%start parse_prog +%start Syntax.prog> parse_prog %% @@ -155,6 +155,8 @@ actor_typ : def : | TYPE x=id EQ t=data_typ { TypD(x, t) @@ at $sloc } + | IMPORT file=TEXT + { ImportD (file, ref "") @@ at $sloc } actor : | (* empty *) { None } @@ -166,6 +168,7 @@ actor : (* Programs *) parse_prog : - | ds=seplist(def, SEMICOLON) actor=actor EOF { {decs=ds; actor=actor} @@ at $sloc } + | ds=seplist(def, SEMICOLON) actor=actor EOF + { fun filename -> { it = {decs=ds; actor=actor}; at = at $sloc; note = filename} } %% diff --git a/src/idllib/pipeline.ml b/src/idllib/pipeline.ml index 03988e8a1ee..96270526da1 100644 --- a/src/idllib/pipeline.ml +++ b/src/idllib/pipeline.ml @@ -1,9 +1,5 @@ open Printf -type stat_env = Typing.scope -type env = stat_env - - (* Diagnostics *) let phase heading name = @@ -25,14 +21,16 @@ let dump_prog flag prog = (* Parsing *) -type parse_result = Syntax.prog Diag.result +type rel_path = string + +type parse_result = (Syntax.prog * rel_path) Diag.result let parse_with lexer parser name = try phase "Parsing" name; lexer.Lexing.lex_curr_p <- {lexer.Lexing.lex_curr_p with Lexing.pos_fname = name}; - let prog = parser Lexer.token lexer in + let prog = parser Lexer.token lexer name in dump_prog !Flags.dump_parse prog; Ok prog with @@ -45,48 +43,83 @@ let parse_file filename : parse_result = let ic = open_in filename in let lexer = Lexing.from_channel ic in let parser = Parser.parse_prog in - let result = parse_with lexer parser filename in + let name = Filename.basename filename in + let result = parse_with lexer parser name in close_in ic; match result with - | Ok prog -> Diag.return prog + | Ok prog -> Diag.return (prog, filename) | Error e -> Error [e] +(* import file name resolution *) -let initial_stat_env = Typing.empty_scope -let initial_env = initial_stat_env - -(* Checking *) +type resolve_result = (Syntax.prog * Resolve_import.S.t) Diag.result -type check_result = (Syntax.prog * Typing.scope) Diag.result +let resolve_prog (prog, base) : resolve_result = + Diag.map (fun libraries -> (prog, libraries)) (Resolve_import.resolve prog base) -let check_prog check senv name prog +(* Type checking *) + +let check_prog senv prog : Typing.scope Diag.result = - phase "Checking" name; - let r = check senv prog in + phase "Checking" prog.Source.note; + let r = Typing.check_prog senv prog in (match r with | Ok (scope, _) -> if !Flags.verbose then print_stat_ve scope; | Error _ -> ()); r -let check_with parse check senv name : check_result = - Diag.bind (parse name) (fun prog -> - Diag.bind (check_prog check senv name prog) (fun senv' -> - Diag.return (prog, senv') - )) +(* Imported file loading *) + +type load_result = (Syntax.prog * Typing.scope) Diag.result + +let chase_imports senv0 imports : (Syntax.libraries * Typing.scope) Diag.result = + let open Resolve_import.S in + let pending = ref empty in + let senv = ref senv0 in + let libraries = ref [] in + let rec go f = + if Typing.Env.mem f !senv then + Diag.return () + else if mem f !pending then + Error [{ + Diag.sev = Diag.Error; at = Source.no_region; cat = "import"; + text = sprintf "file %s must not depend on itself" f + }] + else begin + pending := add f !pending; + Diag.bind (parse_file f) (fun (prog, base) -> + Diag.bind (Resolve_import.resolve prog base) (fun more_imports -> + Diag.bind (go_set more_imports) (fun () -> + Diag.bind (check_prog !senv prog) (fun scope -> + libraries := (f, prog) :: !libraries; + senv := Typing.Env.adjoin !senv scope; + pending := remove f !pending; + Diag.return () + )))) + end + and go_set todo = Diag.traverse_ go (elements todo) + in Diag.map (fun () -> (List.rev !libraries, !senv)) (go_set imports) + +let load_prog parse senv : load_result = + Diag.bind parse (fun parsed -> + Diag.bind (resolve_prog parsed) (fun (prog, libraries) -> + Diag.bind (chase_imports senv libraries) (fun (libraries, senv') -> + Diag.bind (check_prog senv' prog) (fun senv'' -> + Diag.return (prog, senv'') + )))) + +(* Only type checking *) -let check_file' senv name = check_with parse_file Typing.check_prog senv name -let check_file name = check_file' initial_stat_env name +let initial_stat_env = Typing.empty_scope +let check_file file : load_result = load_prog (parse_file file) initial_stat_env + (* JS Compilation *) -type compile_js_result = (Buffer.t, Diag.messages) result - -let compile_js_file name : compile_js_result = - match check_file name with - | Error msgs -> Error msgs - | Ok ((prog, scope), msgs) -> - Diag.print_messages msgs; - phase "JS Compiling" name; - let buf = Compile_js.compile scope prog in - Ok buf +type compile_result = Buffer.t Diag.result + +let compile_js_file file : compile_result = + Diag.bind (load_prog (parse_file file) initial_stat_env) + (fun (prog, senv) -> + Diag.return (Compile_js.compile senv prog)) diff --git a/src/idllib/pipeline.mli b/src/idllib/pipeline.mli index 8f8f2a506e0..76c62bd46b1 100644 --- a/src/idllib/pipeline.mli +++ b/src/idllib/pipeline.mli @@ -1,14 +1,3 @@ -type stat_env = Typing.scope -type env = stat_env +val check_file : string -> (Syntax.prog * Typing.scope) Diag.result -val initial_stat_env : stat_env -val initial_env : env - -type parse_result = Syntax.prog Diag.result -val parse_file : string -> parse_result - -type check_result = (Syntax.prog * Typing.scope) Diag.result -val check_file : string -> check_result - -type compile_js_result = (Buffer.t, Diag.messages) result -val compile_js_file : string -> compile_js_result +val compile_js_file : string -> Buffer.t Diag.result diff --git a/src/idllib/resolve_import.ml b/src/idllib/resolve_import.ml new file mode 100644 index 00000000000..44d31197e25 --- /dev/null +++ b/src/idllib/resolve_import.ml @@ -0,0 +1,44 @@ +type filepath = string + +module S = Set.Make(String) + +type env = { + msgs : Diag.msg_store; + base : filepath; + imported : S.t ref; +} + +open Syntax +open Source + +let rec decs env = List.iter (dec env) +and dec env d = match d.it with + | TypD _ -> () + | ImportD (f, fp) -> + let f = if Filename.is_relative f + then Filename.concat env.base f + else f in + if Sys.file_exists f && not (Sys.is_directory f) + then begin + fp := f; + env.imported := S.add f !(env.imported) + end else + let open Diag in + add_msg env.msgs { + sev = Error; + at = d.at; + cat = "import"; + text = Printf.sprintf "File \"%s\" does not exist" f + } + +let prog env p = decs env p.it.decs + +let resolve : Syntax.prog -> filepath -> S.t Diag.result = fun p base -> + Diag.with_message_store (fun msgs -> + let base = if Sys.is_directory base then base else Filename.dirname base in + let env = { msgs; base; imported = ref S.empty } in + prog env p; + Some !(env.imported) + ) + + diff --git a/src/idllib/resolve_import.mli b/src/idllib/resolve_import.mli new file mode 100644 index 00000000000..bd3e4fd1b29 --- /dev/null +++ b/src/idllib/resolve_import.mli @@ -0,0 +1,3 @@ +module S : Set.S with type elt = String.t + +val resolve : Syntax.prog -> string -> S.t Diag.result diff --git a/src/idllib/syntax.ml b/src/idllib/syntax.ml index 324136353d3..5d207263dd3 100644 --- a/src/idllib/syntax.ml +++ b/src/idllib/syntax.ml @@ -49,6 +49,7 @@ and typ_meth' = {var : id; meth : typ} and dec = dec' Source.phrase and dec' = | TypD of id * typ (* type *) + | ImportD of string * string ref (* import *) and actor = actor' Source.phrase and actor' = @@ -56,5 +57,10 @@ and actor' = (* Program *) -type prog = prog' Source.phrase +type prog = (prog', string) Source.annotated_phrase and prog' = { decs : dec list; actor : actor option } + +(* Libraries *) + +type library = string * prog +type libraries = library list diff --git a/src/idllib/typing.ml b/src/idllib/typing.ml index ec4c745fb9f..23c9d08e68d 100644 --- a/src/idllib/typing.ml +++ b/src/idllib/typing.ml @@ -159,14 +159,15 @@ and check_def env dec = | TypD (id, t) -> let t' = check_typ env t in Env.singleton id.it t' + | ImportD _ -> Env.empty and check_defs env decs = - let _, te = - List.fold_left (fun (env, te) dec -> + let env' = + List.fold_left (fun env dec -> let te' = check_def env dec in - adjoin env te', Env.adjoin te te' - ) (env, Env.empty) decs - in te + adjoin env te' + ) env decs + in env'.typs and check_decs env decs = let pre_env = adjoin env (gather_decs env decs) in @@ -175,15 +176,13 @@ and check_decs env decs = check_cycle env; check_defs {env with pre = false} decs -and gather_id dec = - match dec.it with - | TypD (id, _) -> id - and gather_decs env decs = List.fold_left (fun te dec -> - let id = gather_id dec in - let te' = Env.singleton id.it (PreT @@ id.at) in - disjoint_union env id.at "duplicate binding for %s in type definitions" te te' + match dec.it with + | TypD (id, _) -> + let te' = Env.singleton id.it (PreT @@ id.at) in + disjoint_union env id.at "duplicate binding for %s in type definitions" te te' + | ImportD _ -> te ) env.typs decs (* Actor *) From 36afd02b8d2433d663610c0103240de7d7b02f5c Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Tue, 18 Jun 2019 15:16:35 -0700 Subject: [PATCH 0180/1176] add tests --- src/idllib/compile_js.ml | 21 ++++++++++----------- test/idl/cycle_import1.did | 2 ++ test/idl/cycle_import2.did | 2 ++ test/idl/dup_import.did | 2 ++ test/idl/ok/cycle_import1.tc.ok | 1 + test/idl/ok/cycle_import2.tc.ok | 1 + test/idl/ok/dup_import.tc.ok | 1 + 7 files changed, 19 insertions(+), 11 deletions(-) create mode 100644 test/idl/cycle_import1.did create mode 100644 test/idl/cycle_import2.did create mode 100644 test/idl/dup_import.did create mode 100644 test/idl/ok/cycle_import1.tc.ok create mode 100644 test/idl/ok/cycle_import2.tc.ok create mode 100644 test/idl/ok/dup_import.tc.ok diff --git a/src/idllib/compile_js.ml b/src/idllib/compile_js.ml index 49482b83fbb..4507cf2784a 100644 --- a/src/idllib/compile_js.ml +++ b/src/idllib/compile_js.ml @@ -80,17 +80,16 @@ and pp_meth ppf env meth = pp_close_box ppf () let pp_dec ppf env dec = - pp_open_hovbox ppf 1; - kwd ppf "const"; - (match dec.it with - | TypD (x, t) -> - kwd ppf x.it; - kwd ppf "="; - pp_typ ppf env t - | ImportD _ -> () - ); - pp_close_box ppf (); - pp_print_cut ppf () + match dec.it with + | TypD (x, t) -> + pp_open_hovbox ppf 1; + kwd ppf "const"; + kwd ppf x.it; + kwd ppf "="; + pp_typ ppf env t; + pp_close_box ppf (); + pp_print_cut ppf () + | ImportD _ -> () let pp_actor ppf env actor_opt = pp_open_hovbox ppf 1; diff --git a/test/idl/cycle_import1.did b/test/idl/cycle_import1.did new file mode 100644 index 00000000000..6255e191124 --- /dev/null +++ b/test/idl/cycle_import1.did @@ -0,0 +1,2 @@ +import "cycle_import2.did"; +type A = nat; diff --git a/test/idl/cycle_import2.did b/test/idl/cycle_import2.did new file mode 100644 index 00000000000..817a22694f2 --- /dev/null +++ b/test/idl/cycle_import2.did @@ -0,0 +1,2 @@ +import "cycle_import1.did"; +type b = nat; diff --git a/test/idl/dup_import.did b/test/idl/dup_import.did new file mode 100644 index 00000000000..a4d5196aaae --- /dev/null +++ b/test/idl/dup_import.did @@ -0,0 +1,2 @@ +import "px.did"; +type UserId = blob; diff --git a/test/idl/ok/cycle_import1.tc.ok b/test/idl/ok/cycle_import1.tc.ok new file mode 100644 index 00000000000..12bb840e7ac --- /dev/null +++ b/test/idl/ok/cycle_import1.tc.ok @@ -0,0 +1 @@ +(unknown location): import error, file ./cycle_import2.did must not depend on itself diff --git a/test/idl/ok/cycle_import2.tc.ok b/test/idl/ok/cycle_import2.tc.ok new file mode 100644 index 00000000000..26bb0dac600 --- /dev/null +++ b/test/idl/ok/cycle_import2.tc.ok @@ -0,0 +1 @@ +(unknown location): import error, file ./cycle_import1.did must not depend on itself diff --git a/test/idl/ok/dup_import.tc.ok b/test/idl/ok/dup_import.tc.ok new file mode 100644 index 00000000000..2c721bedbbf --- /dev/null +++ b/test/idl/ok/dup_import.tc.ok @@ -0,0 +1 @@ +dup_import.did:2.6-2.12: type error, duplicate binding for UserId in type definitions From 3a30e9a9f058fee0d58eb8b7bee5b3987bee4abf Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Tue, 18 Jun 2019 15:30:27 -0700 Subject: [PATCH 0181/1176] remove libraries from idl syntax --- src/idllib/pipeline.ml | 6 +++--- src/idllib/syntax.ml | 4 ---- test/idl/missing_import.did | 3 +++ test/idl/ok/missing_import.tc.ok | 1 + 4 files changed, 7 insertions(+), 7 deletions(-) create mode 100644 test/idl/missing_import.did create mode 100644 test/idl/ok/missing_import.tc.ok diff --git a/src/idllib/pipeline.ml b/src/idllib/pipeline.ml index 96270526da1..0f37fc7ec2e 100644 --- a/src/idllib/pipeline.ml +++ b/src/idllib/pipeline.ml @@ -73,7 +73,7 @@ let check_prog senv prog type load_result = (Syntax.prog * Typing.scope) Diag.result -let chase_imports senv0 imports : (Syntax.libraries * Typing.scope) Diag.result = +let chase_imports senv0 imports : Typing.scope Diag.result = let open Resolve_import.S in let pending = ref empty in let senv = ref senv0 in @@ -99,12 +99,12 @@ let chase_imports senv0 imports : (Syntax.libraries * Typing.scope) Diag.result )))) end and go_set todo = Diag.traverse_ go (elements todo) - in Diag.map (fun () -> (List.rev !libraries, !senv)) (go_set imports) + in Diag.map (fun () -> !senv) (go_set imports) let load_prog parse senv : load_result = Diag.bind parse (fun parsed -> Diag.bind (resolve_prog parsed) (fun (prog, libraries) -> - Diag.bind (chase_imports senv libraries) (fun (libraries, senv') -> + Diag.bind (chase_imports senv libraries) (fun senv' -> Diag.bind (check_prog senv' prog) (fun senv'' -> Diag.return (prog, senv'') )))) diff --git a/src/idllib/syntax.ml b/src/idllib/syntax.ml index 5d207263dd3..ed462e465e4 100644 --- a/src/idllib/syntax.ml +++ b/src/idllib/syntax.ml @@ -60,7 +60,3 @@ and actor' = type prog = (prog', string) Source.annotated_phrase and prog' = { decs : dec list; actor : actor option } -(* Libraries *) - -type library = string * prog -type libraries = library list diff --git a/test/idl/missing_import.did b/test/idl/missing_import.did new file mode 100644 index 00000000000..35df983c5a4 --- /dev/null +++ b/test/idl/missing_import.did @@ -0,0 +1,3 @@ +import "ok"; +import "../Makefile"; + diff --git a/test/idl/ok/missing_import.tc.ok b/test/idl/ok/missing_import.tc.ok new file mode 100644 index 00000000000..30f369fe40f --- /dev/null +++ b/test/idl/ok/missing_import.tc.ok @@ -0,0 +1 @@ +missing_import.did:1.1-1.12: import error, File "./ok" does not exist From 778dd8483f3f59fe450c5fa903889b4c5388643c Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Tue, 18 Jun 2019 15:58:04 -0700 Subject: [PATCH 0182/1176] codegen from env for type definitions --- src/idllib/compile_js.ml | 26 +++++++++++++------------- src/idllib/pipeline.ml | 1 + test/idl/import.did | 7 +++++++ test/idl/ok/cyclic.js.ok | 2 +- test/idl/ok/fields.js.ok | 12 ++++++------ test/idl/ok/import.js.ok | 32 ++++++++++++++++++++++++++++++++ test/idl/ok/px.js.ok | 18 +++++++++--------- test/idl/ok/recursion.js.ok | 11 ++++++----- test/idl/ok/test.js.ok | 4 ++-- test/idl/ok/unicode.js.ok | 6 +++--- 10 files changed, 80 insertions(+), 39 deletions(-) create mode 100644 test/idl/import.did create mode 100644 test/idl/ok/import.js.ok diff --git a/src/idllib/compile_js.ml b/src/idllib/compile_js.ml index 4507cf2784a..8baec054016 100644 --- a/src/idllib/compile_js.ml +++ b/src/idllib/compile_js.ml @@ -78,19 +78,16 @@ and pp_meth ppf env meth = kwd ppf ":"; pp_typ ppf env meth.it.meth; pp_close_box ppf () - -let pp_dec ppf env dec = - match dec.it with - | TypD (x, t) -> - pp_open_hovbox ppf 1; - kwd ppf "const"; - kwd ppf x.it; - kwd ppf "="; - pp_typ ppf env t; - pp_close_box ppf (); - pp_print_cut ppf () - | ImportD _ -> () +let pp_dec ppf env x t = + pp_open_hovbox ppf 1; + kwd ppf "const"; + kwd ppf x; + kwd ppf "="; + pp_typ ppf env t; + pp_close_box ppf (); + pp_print_cut ppf () + let pp_actor ppf env actor_opt = pp_open_hovbox ppf 1; (match actor_opt with @@ -111,7 +108,10 @@ let pp_actor ppf env actor_opt = let pp_prog ppf env prog = pp_open_vbox ppf 0; - List.iter (pp_dec ppf env) prog.it.decs; + (* TODO: This is just a quick fix. + * The right way is to trace the used definitions from the actor + * and sort them in topoloical order. *) + Typing.Env.iter (pp_dec ppf env) env; pp_actor ppf env prog.it.actor; pp_close_box ppf () diff --git a/src/idllib/pipeline.ml b/src/idllib/pipeline.ml index 0f37fc7ec2e..75df9b50d45 100644 --- a/src/idllib/pipeline.ml +++ b/src/idllib/pipeline.ml @@ -122,4 +122,5 @@ type compile_result = Buffer.t Diag.result let compile_js_file file : compile_result = Diag.bind (load_prog (parse_file file) initial_stat_env) (fun (prog, senv) -> + phase "JS Compiling" file; Diag.return (Compile_js.compile senv prog)) diff --git a/test/idl/import.did b/test/idl/import.did new file mode 100644 index 00000000000..0d886d0532b --- /dev/null +++ b/test/idl/import.did @@ -0,0 +1,7 @@ +import "px.did"; +import "recursion.did"; + +service S { + f: (tree) -> (list, IdErr); + getInventory: (producer_id: nat) -> (Inventory) pure; +} diff --git a/test/idl/ok/cyclic.js.ok b/test/idl/ok/cyclic.js.ok index 746a7a557c8..669df6dbcf0 100644 --- a/test/idl/ok/cyclic.js.ok +++ b/test/idl/ok/cyclic.js.ok @@ -1,6 +1,6 @@ const A = IDL.Opt(B) -const C = A const B = IDL.Opt(C) +const C = A const X = Y const Y = Z const Z = A diff --git a/test/idl/ok/fields.js.ok b/test/idl/ok/fields.js.ok index 3c40de2b530..eb4bf7e6acc 100644 --- a/test/idl/ok/fields.js.ok +++ b/test/idl/ok/fields.js.ok @@ -1,12 +1,12 @@ const A = IDL.Obj({'0': IDL.Nat, '1': IDL.Nat, '2': IDL.Nat}) const B = - IDL.Obj({'0': IDL.Arr(IDL.Nat8), '35': IDL.Arr(IDL.Nat8), '36': IDL.Nat, - '37': IDL.Nat, 'named_files': IDL.None, '-665008590': IDL.Nat, - '-665008589': IDL.Nat}) + IDL.Obj({'named_files': IDL.None, '-665008590': IDL.Nat, + '-665008589': IDL.Nat, '0': IDL.Arr(IDL.Nat8), '35': IDL.Arr(IDL.Nat8), + '36': IDL.Nat, '37': IDL.Nat}) const C = - IDL.Variant({'red': IDL.Unit, '4': IDL.Unit, '3': IDL.Unit, '2': IDL.Unit, - '1': IDL.Unit, 'reserved': IDL.Unit, '10': IDL.Unit, 'green': IDL.Unit, - 'blue': IDL.Unit, 'A': IDL.Unit, 'B': IDL.Unit, 'C': IDL.Unit}) + IDL.Variant({'green': IDL.Unit, '1': IDL.Unit, '2': IDL.Unit, '3': IDL.Unit, + '4': IDL.Unit, '10': IDL.Unit, 'A': IDL.Unit, 'B': IDL.Unit, 'C': IDL.Unit, + 'red': IDL.Unit, 'blue': IDL.Unit, 'reserved': IDL.Unit}) const nest_record = IDL.Obj({'0': IDL.Nat, '1': IDL.Nat, '2': IDL.Nat, '3': IDL.Obj({'0': IDL.Nat, '1': IDL.Nat, '2': IDL.Nat}), '4': IDL.Nat, diff --git a/test/idl/ok/import.js.ok b/test/idl/ok/import.js.ok new file mode 100644 index 00000000000..8787e42fadb --- /dev/null +++ b/test/idl/ok/import.js.ok @@ -0,0 +1,32 @@ +const A = B +const B = IDL.Opt(A) +const EntId = + IDL.Obj({'region': RegionId, 'user': UserId, 'truckType': TruckTypeId}) +const IdErr = IDL.Obj({'idErr': OpEntId}) +const Inventory = IDL.Obj({'quantity': IDL.Nat, 'produce_id': IDL.Nat}) +const OpEntId = IDL.Opt(EntId) +const ProducerId = IDL.Nat +const RegionId = IDL.Nat +const TruckTypeId = IDL.Nat +const UserId = IDL.Nat +const UserInfo = + IDL.Obj({'id': UserId, 'region': RegionId, 'user_name': IDL.Text, + 'public_key': IDL.Text, 'description': IDL.Text, + 'produceId': IDL.Opt(ProducerId)}) +const list = IDL.Opt(node) +const node = IDL.Obj({'head': IDL.Nat, 'tail': list}) +const s = new IDL.ActorInterface({'f': t}) +const stream = + IDL.Opt( + IDL.Obj({'head': IDL.Nat, + 'next': IDL.message(IDL.Obj({}), IDL.Obj({'0': stream}))})) + +const t = IDL.message(IDL.Obj({'server': s}), IDL.Obj({})) +const tree = + IDL.Variant({ + 'branch': IDL.Obj({'right': tree, 'val': IDL.Int, 'left': tree}), + 'leaf': IDL.Int}) +const S = new IDL.ActorInterface({ + 'f': IDL.message(IDL.Obj({'0': tree}), IDL.Obj({'0': list, '1': IdErr})), + 'getInventory': + IDL.message(IDL.Obj({'producer_id': IDL.Nat}), IDL.Obj({'0': Inventory}))}) diff --git a/test/idl/ok/px.js.ok b/test/idl/ok/px.js.ok index cbc6c8fc9e1..b210f5824c3 100644 --- a/test/idl/ok/px.js.ok +++ b/test/idl/ok/px.js.ok @@ -1,16 +1,16 @@ +const EntId = + IDL.Obj({'region': RegionId, 'user': UserId, 'truckType': TruckTypeId}) +const IdErr = IDL.Obj({'idErr': OpEntId}) +const Inventory = IDL.Obj({'quantity': IDL.Nat, 'produce_id': IDL.Nat}) +const OpEntId = IDL.Opt(EntId) +const ProducerId = IDL.Nat const RegionId = IDL.Nat -const UserId = IDL.Nat const TruckTypeId = IDL.Nat -const ProducerId = IDL.Nat +const UserId = IDL.Nat const UserInfo = - IDL.Obj({'id': UserId, 'public_key': IDL.Text, 'user_name': IDL.Text, - 'description': IDL.Text, 'region': RegionId, + IDL.Obj({'id': UserId, 'region': RegionId, 'user_name': IDL.Text, + 'public_key': IDL.Text, 'description': IDL.Text, 'produceId': IDL.Opt(ProducerId)}) -const EntId = - IDL.Obj({'user': UserId, 'truckType': TruckTypeId, 'region': RegionId}) -const OpEntId = IDL.Opt(EntId) -const IdErr = IDL.Obj({'idErr': OpEntId}) -const Inventory = IDL.Obj({'produce_id': IDL.Nat, 'quantity': IDL.Nat}) const ProduceExchange = new IDL.ActorInterface({ 'getInventory': IDL.message(IDL.Obj({'producer_id': IDL.Nat}), IDL.Obj({'0': Inventory}))}) diff --git a/test/idl/ok/recursion.js.ok b/test/idl/ok/recursion.js.ok index 8caaff51b9e..c73d80a6a9e 100644 --- a/test/idl/ok/recursion.js.ok +++ b/test/idl/ok/recursion.js.ok @@ -1,15 +1,16 @@ const A = B const B = IDL.Opt(A) -const node = IDL.Obj({'head': IDL.Nat, 'tail': list}) const list = IDL.Opt(node) -const tree = - IDL.Variant({'leaf': IDL.Int, - 'branch': IDL.Obj({'left': tree, 'val': IDL.Int, 'right': tree})}) +const node = IDL.Obj({'head': IDL.Nat, 'tail': list}) const s = new IDL.ActorInterface({'f': t}) -const t = IDL.message(IDL.Obj({'server': s}), IDL.Obj({})) const stream = IDL.Opt( IDL.Obj({'head': IDL.Nat, 'next': IDL.message(IDL.Obj({}), IDL.Obj({'0': stream}))})) +const t = IDL.message(IDL.Obj({'server': s}), IDL.Obj({})) +const tree = + IDL.Variant({ + 'branch': IDL.Obj({'right': tree, 'val': IDL.Int, 'left': tree}), + 'leaf': IDL.Int}) const A = s diff --git a/test/idl/ok/test.js.ok b/test/idl/ok/test.js.ok index 39867203392..31376351dc4 100644 --- a/test/idl/ok/test.js.ok +++ b/test/idl/ok/test.js.ok @@ -1,6 +1,4 @@ -const my_type = IDL.Nat const B = my_type -const message = IDL.Obj({'name': IDL.Text, '25': B, '26': IDL.None}) const broker = new IDL.ActorInterface({ 'find': @@ -11,6 +9,8 @@ const broker = 'current': IDL.message(IDL.Obj({}), IDL.Obj({'0': IDL.Nat}))}) })) }) +const message = IDL.Obj({'25': B, '26': IDL.None, 'name': IDL.Text}) +const my_type = IDL.Nat const server = new IDL.ActorInterface({ 'addUser': IDL.message(IDL.Obj({'name': IDL.Text, 'age': IDL.Nat8}), diff --git a/test/idl/ok/unicode.js.ok b/test/idl/ok/unicode.js.ok index 9469eae3f3f..7dc7da27b4f 100644 --- a/test/idl/ok/unicode.js.ok +++ b/test/idl/ok/unicode.js.ok @@ -1,9 +1,9 @@ const A = - IDL.Obj({'字段名': IDL.Nat, '字 段 名2': IDL.Nat, '📦🍦': IDL.Nat + IDL.Obj({'字 段 名2': IDL.Nat, '📦🍦': IDL.Nat, '字段名': IDL.Nat }) const B = - IDL.Variant({'': IDL.Unit, '空的': IDL.Unit, ' 空的 ': IDL.Unit, - '1⃣️2⃣️3⃣️': IDL.Unit}) + IDL.Variant({'1⃣️2⃣️3⃣️': IDL.Unit, '': IDL.Unit, + '空的': IDL.Unit, ' 空的 ': IDL.Unit}) const C = new IDL.ActorInterface({ '函数名': IDL.message(IDL.Obj({'0': A}), IDL.Obj({'0': B})), '': IDL.message(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': IDL.Nat})), From 7dc951a9a299c3c5a6660af134e0b2553695d147 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 19 Jun 2019 13:24:56 +0200 Subject: [PATCH 0183/1176] Remove the --disable-prelude flags (#508) it somehow affected the source map generation, but I see no problem in simply always including the prelude in the source map. --- src/exes/asc.ml | 1 - src/flags/flags.ml | 1 - src/wasm-exts/customModuleEncode.ml | 6 ++---- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/exes/asc.ml b/src/exes/asc.ml index 39a080e27a9..8f5d30cbfa6 100644 --- a/src/exes/asc.ml +++ b/src/exes/asc.ml @@ -53,7 +53,6 @@ let argspec = Arg.align "-dt", Arg.Set Flags.dump_tc, " dump type-checked AST"; "-dl", Arg.Set Flags.dump_lowering, " dump intermediate representation "; "-no-check-ir", Arg.Clear Flags.check_ir, " do not check intermediate code"; - "--disable-prelude", Arg.Clear Flags.prelude, " disable prelude"; ] diff --git a/src/flags/flags.ml b/src/flags/flags.ml index 912fb7eab48..c517c1d4c23 100644 --- a/src/flags/flags.ml +++ b/src/flags/flags.ml @@ -8,6 +8,5 @@ let dump_tc = ref false let dump_lowering = ref false let interpret_ir = ref false let source_map = ref false -let prelude = ref true let link = ref true let check_ir = ref true diff --git a/src/wasm-exts/customModuleEncode.ml b/src/wasm-exts/customModuleEncode.ml index b28b0b01615..b3e99a24b70 100644 --- a/src/wasm-exts/customModuleEncode.ml +++ b/src/wasm-exts/customModuleEncode.ml @@ -66,10 +66,8 @@ let encode (em : extended_module) = | h :: t -> if x = h then 0 else 1 + (add_source x t) in - if !Flags.prelude then begin - sources := !sources @ [ "prelude" ]; - sourcesContent := !sourcesContent @ [ Prelude.prelude ] - end; + sources := !sources @ [ "prelude" ]; + sourcesContent := !sourcesContent @ [ Prelude.prelude ]; let add_to_map file il ic ol oc = let il = il - 1 in From c821320b0040413e2bf44b2ea76b594b8f96f806 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 19 Jun 2019 13:27:39 +0200 Subject: [PATCH 0184/1176] Remove debugging flags from gitSource.nix (#509) --- nix/gitSource.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/gitSource.nix b/nix/gitSource.nix index 1af7959cec8..7d3af5e5e3d 100644 --- a/nix/gitSource.nix +++ b/nix/gitSource.nix @@ -68,7 +68,7 @@ then whitelist_file = nixpkgs.runCommand "git-ls-files" {envVariable = true;} '' - cp -v ${git_dir + "/index"} index + cp ${git_dir + "/index"} index echo "ref: refs/heads/master" > HEAD mkdir objects refs ${nixpkgs.git}/bin/git --git-dir . ls-files > $out From bc6eb5fa7d2934d21e345ed9fd41b0e5fb6aef20 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 19 Jun 2019 13:57:55 +0200 Subject: [PATCH 0185/1176] Do not read Flags.source_map in customModuleEncode.ml (#510) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit one could tell that this code was written by a Haskell programmer: The Source map is generated in any case; the flag was only controlling whether to stringify it or to return `""`. So let’s just always generate the source map for now; the main function decided whether to actually write this out to file or not. At some point we can make sure that `customModuleEncode` doesn’t even create the source map if we don’t want it, but that’s an optimization for later. Together with #508 this means we can remove the `flags` library! --- src/exes/as_js.ml | 9 ++++----- src/wasm-exts/customModuleEncode.ml | 2 +- test/node-test.js | 10 ++++------ 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/exes/as_js.ml b/src/exes/as_js.ml index 91f76233338..3c23d072c70 100644 --- a/src/exes/as_js.ml +++ b/src/exes/as_js.ml @@ -37,8 +37,7 @@ let js_check source = val code = Js.null end -let js_compile_with mode_string source_map source convert = - Flags.source_map := source_map; +let js_compile_with mode_string source convert = let mode = match Js.to_string mode_string with | "dfinity" -> Pipeline.DfinityMode @@ -59,13 +58,13 @@ let js_compile_with mode_string source_map source convert = val map = Js.null end -let js_compile_wasm mode source_map s = - js_compile_with mode source_map s +let js_compile_wasm mode s = + js_compile_with mode s (fun m -> let (map, wasm) = CustomModuleEncode.encode m in Js.bytestring wasm, Js.string map) let () = Js.export "ActorScript" (object%js method check s = js_check s - method compileWasm mode source_map s = js_compile_wasm mode source_map s + method compileWasm mode s = js_compile_wasm mode s end); diff --git a/src/wasm-exts/customModuleEncode.ml b/src/wasm-exts/customModuleEncode.ml index b3e99a24b70..b779001c3a3 100644 --- a/src/wasm-exts/customModuleEncode.ml +++ b/src/wasm-exts/customModuleEncode.ml @@ -641,4 +641,4 @@ let encode (em : extended_module) = ("mappings", `String (String.sub mappings 0 n) ) ] in - ((if !Flags.source_map then Yojson.Basic.to_string json else ""), to_string s) + (Yojson.Basic.to_string json, to_string s) diff --git a/test/node-test.js b/test/node-test.js index 10669d7cda6..55296cfbddc 100644 --- a/test/node-test.js +++ b/test/node-test.js @@ -6,8 +6,8 @@ const assert = require('assert').strict; const m = require('asc.js'); // Compile the empty module in plain and dfinity mode -const empty_wasm_plain = m.ActorScript.compileWasm('wasm', false, ''); -const empty_wasm_dfinity = m.ActorScript.compileWasm('dfinity', false, ''); +const empty_wasm_plain = m.ActorScript.compileWasm('wasm', ''); +const empty_wasm_dfinity = m.ActorScript.compileWasm('dfinity', ''); // For the plain module... // Check that the code looks like a WebAssembly binary @@ -33,7 +33,7 @@ WebAssembly.compile(Buffer.from(empty_wasm_dfinity.code, 'ascii')); assert.notEqual(empty_wasm_plain.code, empty_wasm_dfinity.code); // Check if error messages are correctly returned -const bad_result = m.ActorScript.compileWasm('dfinity', false, '1+'); +const bad_result = m.ActorScript.compileWasm('dfinity', '1+'); // Uncomment to see what to paste below // console.log(JSON.stringify(bad_result, null, 2)); assert.deepStrictEqual(bad_result, { @@ -86,7 +86,7 @@ assert.deepStrictEqual(m.ActorScript.check('1+'), { }); // Create a source map, and check some of its structure -const with_map = m.ActorScript.compileWasm('dfinity', true, ''); +const with_map = m.ActorScript.compileWasm('dfinity', ''); assert.equal(typeof(with_map.map), 'string') let map assert.doesNotThrow(() => map = JSON.parse(with_map.map), SyntaxError) @@ -94,5 +94,3 @@ assert.ok(Array.isArray(map.sources)) assert.ok(Array.isArray(map.sourcesContent)) assert.equal(typeof(map.mappings), 'string') assert.equal(typeof(map.version), 'number') - -assert.equal(empty_wasm_dfinity.map, '') From 96ebc88b262017dafb1db099e50ea1108b510031 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 19 Jun 2019 14:02:12 +0200 Subject: [PATCH 0186/1176] Move flags.ml into pipeline the fact that I have to give a signature of `Flags` in `pipeline.mli` is a consequence of having a `Pipeline` module in the `pipeline` library. But it is not actually a bad thing. --- src/exes/asc.ml | 30 +++++++++++++++--------------- src/flags/dune | 4 ---- src/pipeline/dune | 1 - src/{flags => pipeline}/flags.ml | 0 src/pipeline/pipeline.ml | 1 + src/pipeline/pipeline.mli | 16 ++++++++++++++++ src/wasm-exts/dune | 2 +- 7 files changed, 33 insertions(+), 21 deletions(-) delete mode 100644 src/flags/dune rename src/{flags => pipeline}/flags.ml (100%) diff --git a/src/exes/asc.ml b/src/exes/asc.ml index 8f5d30cbfa6..4749d63fe67 100644 --- a/src/exes/asc.ml +++ b/src/exes/asc.ml @@ -31,28 +31,28 @@ let argspec = Arg.align "-r", Arg.Unit (set_mode Run), " interpret programs"; "-i", Arg.Unit (set_mode Interact), " run interactive REPL (implies -r)"; "--check", Arg.Unit (set_mode Check), " type-check only"; - "-v", Arg.Set Flags.verbose, " verbose output"; - "-p", Arg.Set_int Flags.print_depth, " set print depth"; + "-v", Arg.Set Pipeline.Flags.verbose, " verbose output"; + "-p", Arg.Set_int Pipeline.Flags.print_depth, " set print depth"; "-o", Arg.Set_string out_file, " output file"; "--version", Arg.Unit (fun () -> printf "%s\n%!" banner; exit 0), " show version"; - "--map", Arg.Set Flags.source_map, " output source map"; + "--map", Arg.Set Pipeline.Flags.source_map, " output source map"; - "-t", Arg.Set Flags.trace, " activate tracing"; - "-iR", Arg.Set Flags.interpret_ir, " interpret the lowered code"; - "-no-await", Arg.Clear Flags.await_lowering, " no await-lowering (with -iR)"; - "-no-async", Arg.Clear Flags.async_lowering, " no async-lowering (with -iR)"; + "-t", Arg.Set Pipeline.Flags.trace, " activate tracing"; + "-iR", Arg.Set Pipeline.Flags.interpret_ir, " interpret the lowered code"; + "-no-await", Arg.Clear Pipeline.Flags.await_lowering, " no await-lowering (with -iR)"; + "-no-async", Arg.Clear Pipeline.Flags.async_lowering, " no async-lowering (with -iR)"; - "-no-link", Arg.Clear Flags.link, " do not statically link-in runtime"; + "-no-link", Arg.Clear Pipeline.Flags.link, " do not statically link-in runtime"; "-no-dfinity-api", Arg.Unit (fun () -> compile_mode := Pipeline.WasmMode), " do not import the DFINITY system API"; - "-dp", Arg.Set Flags.dump_parse, " dump parse"; - "-dt", Arg.Set Flags.dump_tc, " dump type-checked AST"; - "-dl", Arg.Set Flags.dump_lowering, " dump intermediate representation "; - "-no-check-ir", Arg.Clear Flags.check_ir, " do not check intermediate code"; + "-dp", Arg.Set Pipeline.Flags.dump_parse, " dump parse"; + "-dt", Arg.Set Pipeline.Flags.dump_tc, " dump type-checked AST"; + "-dl", Arg.Set Pipeline.Flags.dump_lowering, " dump intermediate representation "; + "-no-check-ir", Arg.Clear Pipeline.Flags.check_ir, " do not check intermediate code"; ] @@ -67,7 +67,7 @@ let process_files files : unit = | Default -> assert false | Run -> - if !Flags.interpret_ir + if !Pipeline.Flags.interpret_ir then exit_on_none (Pipeline.interpret_ir_files files) else exit_on_none (Pipeline.run_files files) | Interact -> @@ -81,12 +81,12 @@ let process_files files : unit = | [n] -> out_file := Filename.remove_extension (Filename.basename n) ^ ".wasm" | ns -> eprintf "asc: no output file specified"; exit 1 end; - let module_ = Diag.run Pipeline.(compile_files !compile_mode !(Flags.link) files) in + let module_ = Diag.run Pipeline.(compile_files !compile_mode !(Pipeline.Flags.link) files) in let oc = open_out !out_file in let (source_map, wasm) = CustomModuleEncode.encode module_ in output_string oc wasm; close_out oc; - if !Flags.source_map then begin + if !Pipeline.Flags.source_map then begin let source_map_file = !out_file ^ ".map" in let oc_ = open_out source_map_file in output_string oc_ source_map; close_out oc_ diff --git a/src/flags/dune b/src/flags/dune deleted file mode 100644 index 1c367919f3d..00000000000 --- a/src/flags/dune +++ /dev/null @@ -1,4 +0,0 @@ -(library - (name flags) - (wrapped false) -) diff --git a/src/pipeline/dune b/src/pipeline/dune index f2fe1882335..303e23e55e6 100644 --- a/src/pipeline/dune +++ b/src/pipeline/dune @@ -13,6 +13,5 @@ lowering ir_passes codegen - flags ) ) diff --git a/src/flags/flags.ml b/src/pipeline/flags.ml similarity index 100% rename from src/flags/flags.ml rename to src/pipeline/flags.ml diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index 023a004349e..ce68af08e17 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -9,6 +9,7 @@ type stat_env = Scope.t type dyn_env = Interpret.scope type env = stat_env * dyn_env +module Flags = Flags (* Diagnostics *) diff --git a/src/pipeline/pipeline.mli b/src/pipeline/pipeline.mli index 0873226661a..126cb210eec 100644 --- a/src/pipeline/pipeline.mli +++ b/src/pipeline/pipeline.mli @@ -1,3 +1,19 @@ +module Flags : +sig + val trace : bool ref + val verbose : bool ref + val print_depth : int ref + val await_lowering : bool ref + val async_lowering : bool ref + val dump_parse : bool ref + val dump_tc : bool ref + val dump_lowering : bool ref + val interpret_ir : bool ref + val source_map : bool ref + val link : bool ref + val check_ir : bool ref +end + val check_files : string list -> unit Diag.result val check_string : string -> string -> unit Diag.result diff --git a/src/wasm-exts/dune b/src/wasm-exts/dune index d739a086164..b0fe696ad59 100644 --- a/src/wasm-exts/dune +++ b/src/wasm-exts/dune @@ -1,4 +1,4 @@ (library (name wasm_exts) - (libraries wasm vlq yojson lib flags prelude) + (libraries wasm vlq yojson lib prelude) ) From e005f89c49ab5086e39e11953be056247332e9bf Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 19 Jun 2019 14:06:04 +0200 Subject: [PATCH 0187/1176] Move flags local to asc.ml to there --- src/exes/asc.ml | 15 +++++++++------ src/pipeline/flags.ml | 3 --- src/pipeline/pipeline.mli | 3 --- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/exes/asc.ml b/src/exes/asc.ml index 4749d63fe67..14c52c4a5bb 100644 --- a/src/exes/asc.ml +++ b/src/exes/asc.ml @@ -24,6 +24,9 @@ let set_mode m () = let compile_mode = ref Pipeline.DfinityMode let out_file = ref "" +let link = ref true +let interpret_ir = ref false +let gen_source_map = ref false let argspec = Arg.align [ @@ -37,14 +40,14 @@ let argspec = Arg.align "--version", Arg.Unit (fun () -> printf "%s\n%!" banner; exit 0), " show version"; - "--map", Arg.Set Pipeline.Flags.source_map, " output source map"; + "--map", Arg.Set gen_source_map, " output source map"; "-t", Arg.Set Pipeline.Flags.trace, " activate tracing"; - "-iR", Arg.Set Pipeline.Flags.interpret_ir, " interpret the lowered code"; + "-iR", Arg.Set interpret_ir, " interpret the lowered code"; "-no-await", Arg.Clear Pipeline.Flags.await_lowering, " no await-lowering (with -iR)"; "-no-async", Arg.Clear Pipeline.Flags.async_lowering, " no async-lowering (with -iR)"; - "-no-link", Arg.Clear Pipeline.Flags.link, " do not statically link-in runtime"; + "-no-link", Arg.Clear link, " do not statically link-in runtime"; "-no-dfinity-api", Arg.Unit (fun () -> compile_mode := Pipeline.WasmMode), " do not import the DFINITY system API"; @@ -67,7 +70,7 @@ let process_files files : unit = | Default -> assert false | Run -> - if !Pipeline.Flags.interpret_ir + if !interpret_ir then exit_on_none (Pipeline.interpret_ir_files files) else exit_on_none (Pipeline.run_files files) | Interact -> @@ -81,12 +84,12 @@ let process_files files : unit = | [n] -> out_file := Filename.remove_extension (Filename.basename n) ^ ".wasm" | ns -> eprintf "asc: no output file specified"; exit 1 end; - let module_ = Diag.run Pipeline.(compile_files !compile_mode !(Pipeline.Flags.link) files) in + let module_ = Diag.run Pipeline.(compile_files !compile_mode !link files) in let oc = open_out !out_file in let (source_map, wasm) = CustomModuleEncode.encode module_ in output_string oc wasm; close_out oc; - if !Pipeline.Flags.source_map then begin + if !gen_source_map then begin let source_map_file = !out_file ^ ".map" in let oc_ = open_out source_map_file in output_string oc_ source_map; close_out oc_ diff --git a/src/pipeline/flags.ml b/src/pipeline/flags.ml index c517c1d4c23..ba7363c7e77 100644 --- a/src/pipeline/flags.ml +++ b/src/pipeline/flags.ml @@ -6,7 +6,4 @@ let async_lowering = ref true let dump_parse = ref false let dump_tc = ref false let dump_lowering = ref false -let interpret_ir = ref false -let source_map = ref false -let link = ref true let check_ir = ref true diff --git a/src/pipeline/pipeline.mli b/src/pipeline/pipeline.mli index 126cb210eec..bad1d96b066 100644 --- a/src/pipeline/pipeline.mli +++ b/src/pipeline/pipeline.mli @@ -8,9 +8,6 @@ sig val dump_parse : bool ref val dump_tc : bool ref val dump_lowering : bool ref - val interpret_ir : bool ref - val source_map : bool ref - val link : bool ref val check_ir : bool ref end From 5276be9143bf99d253e8f76c9d962c2e1ca48a35 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 19 Jun 2019 14:07:24 +0200 Subject: [PATCH 0188/1176] Actually inline `flags.ml` in `pipeline.ml` --- src/pipeline/flags.ml | 9 --------- src/pipeline/pipeline.ml | 13 ++++++++++++- 2 files changed, 12 insertions(+), 10 deletions(-) delete mode 100644 src/pipeline/flags.ml diff --git a/src/pipeline/flags.ml b/src/pipeline/flags.ml deleted file mode 100644 index ba7363c7e77..00000000000 --- a/src/pipeline/flags.ml +++ /dev/null @@ -1,9 +0,0 @@ -let trace = ref false -let verbose = ref false -let print_depth = ref 2 -let await_lowering = ref true -let async_lowering = ref true -let dump_parse = ref false -let dump_tc = ref false -let dump_lowering = ref false -let check_ir = ref true diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index ce68af08e17..f00eed9ade8 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -9,7 +9,18 @@ type stat_env = Scope.t type dyn_env = Interpret.scope type env = stat_env * dyn_env -module Flags = Flags +module Flags = struct + let trace = ref false + let verbose = ref false + let print_depth = ref 2 + let await_lowering = ref true + let async_lowering = ref true + let dump_parse = ref false + let dump_tc = ref false + let dump_lowering = ref false + let check_ir = ref true +end (* Flags *) + (* Diagnostics *) From f558d1ed8158fc39b45711a99e82ef0a1d8fb7ac Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Wed, 19 Jun 2019 07:04:03 -0600 Subject: [PATCH 0189/1176] implement Joachim's suggestion --- src/exes/asc.ml | 14 ++++++++++++++ src/exes/dune | 2 +- src/profiler/dune | 3 ++- src/profiler/flags.ml | 5 +++++ 4 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 src/profiler/flags.ml diff --git a/src/exes/asc.ml b/src/exes/asc.ml index b08b302ef1f..5718f9b4b16 100644 --- a/src/exes/asc.ml +++ b/src/exes/asc.ml @@ -99,6 +99,19 @@ let process_files files : unit = output_string oc_ source_map; close_out oc_ end +(* Copy relevant flags into the profiler library's (global) settings. + This indirection affords the profiler library an independence from the (hacky) Flags library. + See also, this discussion: + https://github.com/dfinity-lab/actorscript/pull/405#issuecomment-503326551 +*) +let process_profiler_flags () = + Profiler.Flags.profile := !Flags.profile ; + Profiler.Flags.profile_verbose := !Flags.profile_verbose ; + Profiler.Flags.profile_file := !Flags.profile_file ; + Profiler.Flags.profile_line_prefix := !Flags.profile_line_prefix ; + Profiler.Flags.profile_field_names := !Flags.profile_field_names ; + () + let () = (* Sys.catch_break true; - enable to get stacktrace on interrupt @@ -107,4 +120,5 @@ let () = Printexc.record_backtrace true; Arg.parse argspec add_arg usage; if !mode = Default then mode := (if !args = [] then Interact else Compile); + process_profiler_flags () ; process_files !args diff --git a/src/exes/dune b/src/exes/dune index 060a1f91373..70fcc5c89ab 100644 --- a/src/exes/dune +++ b/src/exes/dune @@ -1,7 +1,7 @@ (executable (name asc) (modules asc) - (libraries pipeline) + (libraries profiler pipeline) ) (executable (name as_ide) diff --git a/src/profiler/dune b/src/profiler/dune index da7826edaf1..c54fe9ae70d 100644 --- a/src/profiler/dune +++ b/src/profiler/dune @@ -1,4 +1,5 @@ (library (name profiler) - (libraries lib lang_utils flags as_values) + (modules flags counters) + (libraries lang_utils as_values) ) diff --git a/src/profiler/flags.ml b/src/profiler/flags.ml new file mode 100644 index 00000000000..4fcb39fdf59 --- /dev/null +++ b/src/profiler/flags.ml @@ -0,0 +1,5 @@ +let profile = ref false +let profile_verbose = ref false +let profile_file = ref "profiling-counters.csv" +let profile_line_prefix = ref "" +let profile_field_names : (string list) ref = ref [] From 1e54367d617db4f33ddc471684ce4b134cc7617b Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Wed, 19 Jun 2019 07:06:48 -0600 Subject: [PATCH 0190/1176] minor paren nit --- src/flags/flags.ml | 2 +- src/profiler/flags.ml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/flags/flags.ml b/src/flags/flags.ml index 3d0487f8339..ed1704893de 100644 --- a/src/flags/flags.ml +++ b/src/flags/flags.ml @@ -15,4 +15,4 @@ let profile = ref false let profile_verbose = ref false let profile_file = ref "profiling-counters.csv" let profile_line_prefix = ref "" -let profile_field_names : (string list) ref = ref [] +let profile_field_names : string list ref = ref [] diff --git a/src/profiler/flags.ml b/src/profiler/flags.ml index 4fcb39fdf59..b36bc547a2d 100644 --- a/src/profiler/flags.ml +++ b/src/profiler/flags.ml @@ -2,4 +2,4 @@ let profile = ref false let profile_verbose = ref false let profile_file = ref "profiling-counters.csv" let profile_line_prefix = ref "" -let profile_field_names : (string list) ref = ref [] +let profile_field_names : string list ref = ref [] From 8e5e78995a62dff71add68a4b028612c02fe5b0a Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Wed, 19 Jun 2019 07:59:01 -0600 Subject: [PATCH 0191/1176] consolodate all profiler state and logic into profiler library --- src/exes/asc.ml | 10 +++++----- src/interpreter/interpret.ml | 9 ++------- src/interpreter/interpret.mli | 2 -- src/ir_interpreter/interpret_ir.ml | 4 +--- src/pipeline/pipeline.ml | 14 +------------- src/profiler/counters.ml | 14 +++++++------- src/profiler/dune | 4 +++- 7 files changed, 19 insertions(+), 38 deletions(-) diff --git a/src/exes/asc.ml b/src/exes/asc.ml index 5718f9b4b16..1ac276b31f5 100644 --- a/src/exes/asc.ml +++ b/src/exes/asc.ml @@ -105,11 +105,11 @@ let process_files files : unit = https://github.com/dfinity-lab/actorscript/pull/405#issuecomment-503326551 *) let process_profiler_flags () = - Profiler.Flags.profile := !Flags.profile ; - Profiler.Flags.profile_verbose := !Flags.profile_verbose ; - Profiler.Flags.profile_file := !Flags.profile_file ; - Profiler.Flags.profile_line_prefix := !Flags.profile_line_prefix ; - Profiler.Flags.profile_field_names := !Flags.profile_field_names ; + ProfilerFlags.profile := !Flags.profile ; + ProfilerFlags.profile_verbose := !Flags.profile_verbose ; + ProfilerFlags.profile_file := !Flags.profile_file ; + ProfilerFlags.profile_line_prefix := !Flags.profile_line_prefix ; + ProfilerFlags.profile_field_names := !Flags.profile_field_names ; () let () = diff --git a/src/interpreter/interpret.ml b/src/interpreter/interpret.ml index b278c052b2a..376ee16e755 100644 --- a/src/interpreter/interpret.ml +++ b/src/interpreter/interpret.ml @@ -6,7 +6,6 @@ open Source module V = As_values.Value module T = As_types.Type module CC = As_types.Call_conv -module Counters = Profiler.Counters (* Context *) @@ -87,7 +86,6 @@ let string_of_arg env = function let last_env = ref (env_of_scope {trace = false; print_depth = 2} empty_scope) let last_region = ref Source.no_region -let profile_counters : Counters.t = Counters.zeros () let print_exn flags exn = Printf.printf "%!"; @@ -265,7 +263,7 @@ let rec interpret_exp env exp (k : V.value V.cont) = and interpret_exp_mut env exp (k : V.value V.cont) = last_region := exp.at; last_env := env; - Counters.bump_region profile_counters exp.at ; + Profiler.bump_region exp.at ; match exp.it with | PrimE s -> k (V.Func (CC.call_conv_of_typ exp.note.note_typ, Prim.prim s)) @@ -423,7 +421,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = ) | LabelE (id, _typ, exp1) -> let env' = {env with labs = V.Env.add id.it k env.labs} in - Counters.bump_label profile_counters id.at id.it ; + Profiler.bump_label id.at id.it ; interpret_exp env' exp1 k | BreakE (id, exp1) -> interpret_exp env exp1 (find id.it env.labs) @@ -754,6 +752,3 @@ let interpret_library flags scope (filename, p) : scope = in library_scope filename v scope - -let dump_profile (results: Value.value Value.Env.t) = - Counters.dump profile_counters results diff --git a/src/interpreter/interpret.mli b/src/interpreter/interpret.mli index d9a4d5778ce..152a10f3737 100644 --- a/src/interpreter/interpret.mli +++ b/src/interpreter/interpret.mli @@ -19,5 +19,3 @@ exception Trap of Source.region * string val interpret_prog : flags -> scope -> Syntax.prog -> (V.value * scope) option val interpret_library : flags -> scope -> Syntax.library -> scope - -val dump_profile : V.value V.Env.t -> unit diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index fa9ce8592fc..6d0b519a26f 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -8,7 +8,6 @@ open Source module V = Value module T = Type module CC = As_types.Call_conv -module Counters = Profiler.Counters (* Context *) @@ -78,7 +77,6 @@ let string_of_arg env = function let last_env = ref (env_of_scope { trace = false; print_depth = 2} Ir.full_flavor empty_scope) let last_region = ref Source.no_region -let profile_counters : Counters.t = Counters.zeros () let print_exn flags exn = Printf.printf "%!"; @@ -280,7 +278,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = let open Call_conv in last_region := exp.at; last_env := env; - Counters.bump_region profile_counters exp.at ; + Profiler.bump_region exp.at ; match exp.it with | PrimE s -> let at = exp.at in diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index 3d1cd18a651..f3a63f8a416 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -243,19 +243,7 @@ let interpret_prog denv prog : (Value.value * Interpret.scope) option = phase "Interpreting" prog.Source.note; let flags = { trace = !Flags.trace; print_depth = !Flags.print_depth } in let result = Interpret.interpret_prog flags denv prog in - begin - if !Flags.profile then - try - match result with - Some(Value.Async a,_) -> begin - match Lib.Promise.value_opt a.Value.result with - | Some v -> Interpret.dump_profile (Value.as_obj v) - | None -> () - end - | _ -> () - with - | Invalid_argument _ -> () ; - end ; + Profiler.process_prog_result result ; result let rec interpret_libraries denv libraries : Interpret.scope = diff --git a/src/profiler/counters.ml b/src/profiler/counters.ml index fc56110de80..acb6964a041 100644 --- a/src/profiler/counters.ml +++ b/src/profiler/counters.ml @@ -24,13 +24,13 @@ let zeros () = { } let bump_region c reg = - if !Flags.profile then + if !ProfilerFlags.profile then match Hashtbl.find_opt c.region reg with Some n -> Hashtbl.replace c.region reg (n + 1) | None -> Hashtbl.replace c.region reg 1 let bump_label c reg lab = - if !Flags.profile then + if !ProfilerFlags.profile then match Hashtbl.find_opt c.label (reg, lab) with Some n -> Hashtbl.replace c.label (reg, lab) (n + 1) | None -> Hashtbl.replace c.label (reg, lab) 1 @@ -55,8 +55,8 @@ let label_order laba labb = compare laba labb let dump (c:t) (ve: Value.value Value.Env.t) = - if !Flags.profile then - if !Flags.profile_verbose then ( + if !ProfilerFlags.profile then + if !ProfilerFlags.profile_verbose then ( Printf.printf "{\n" ; Value.Env.iter (fun fn fv -> Printf.printf " %s = %s;\n" @@ -105,7 +105,7 @@ let dump (c:t) (ve: Value.value Value.Env.t) = | (None, None) -> region_order rega regb ) all_region_counts in - let file = open_out (!Flags.profile_file) in + let file = open_out (!ProfilerFlags.profile_file) in let (suffix, flds) = (* the suffix of the line consists of field values for each field in `profile_field_names`: *) List.fold_right @@ -113,7 +113,7 @@ let dump (c:t) (ve: Value.value Value.Env.t) = match Value.Env.find_opt var ve with None -> (Printf.sprintf "%s, #err" line, (var :: flds)) | Some v -> (Printf.sprintf "%s, %s" line (Value.string_of_val 0 v), var :: flds) - ) !Flags.profile_field_names ("", []) + ) !ProfilerFlags.profile_field_names ("", []) in Printf.fprintf file "# column: source region\n" ; Printf.fprintf file "# column: source region count\n" ; @@ -133,7 +133,7 @@ let dump (c:t) (ve: Value.value Value.Env.t) = List.iter (fun ((region, labop), region_count) -> assert (dump_count = 0); Printf.fprintf file "%s\"%s\", %s, %d%s\n" - (!Flags.profile_line_prefix) + (!ProfilerFlags.profile_line_prefix) (string_of_region region) (match labop with None -> "null" diff --git a/src/profiler/dune b/src/profiler/dune index c54fe9ae70d..4e3cbb18e29 100644 --- a/src/profiler/dune +++ b/src/profiler/dune @@ -1,5 +1,7 @@ (library (name profiler) - (modules flags counters) + (wrapped false) + (modules profilerFlags counters profiler) + (private_modules counters) (libraries lang_utils as_values) ) From db1b807167b3f03d7418f0198309768e7da00e7c Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Wed, 19 Jun 2019 08:00:33 -0600 Subject: [PATCH 0192/1176] consolodate all profiler state and logic into profiler library --- src/profiler/{flags.ml => profilerFlags.ml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/profiler/{flags.ml => profilerFlags.ml} (100%) diff --git a/src/profiler/flags.ml b/src/profiler/profilerFlags.ml similarity index 100% rename from src/profiler/flags.ml rename to src/profiler/profilerFlags.ml From 2e2abcea4b5298ba2647af71b824961eca8d7389 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Wed, 19 Jun 2019 08:02:57 -0600 Subject: [PATCH 0193/1176] consolodate all profiler state and logic into profiler library --- src/profiler/profiler.ml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/profiler/profiler.ml diff --git a/src/profiler/profiler.ml b/src/profiler/profiler.ml new file mode 100644 index 00000000000..5a26fccd973 --- /dev/null +++ b/src/profiler/profiler.ml @@ -0,0 +1,22 @@ +open As_values + +let counters : Counters.t = Counters.zeros () + +let bump_region reg = + Counters.bump_region counters reg + +let bump_label lab reg = + Counters.bump_label counters lab reg + +let process_prog_result result = + if !ProfilerFlags.profile then + try + match result with + Some(Value.Async a,_) -> begin + match Lib.Promise.value_opt a.Value.result with + | Some v -> Counters.dump counters (Value.as_obj v) + | None -> () + end + | _ -> () + with + | Invalid_argument _ -> () ; From e08e579b7de09494d22db78b960a01966f317f82 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Wed, 19 Jun 2019 17:42:15 +0200 Subject: [PATCH 0194/1176] Extend lub/glb to more types (#340) * implement lub/glb for all relevant types * add tests Caveats: #515 lists the open problems that need to be tackled incrementally --- src/as_frontend/typing.ml | 9 +- src/as_ir/check_ir.ml | 4 +- src/as_types/type.ml | 203 ++++++++++++++++++++------- test/fail/ok/type-inference.tc.ok | 29 ++-- test/fail/type-inference.as | 6 + test/repl/ok/type-lub-repl.stderr.ok | 24 ++++ test/repl/ok/type-lub-repl.stdout.ok | 43 ++++++ test/repl/type-lub-repl.sh | 62 ++++++++ test/run/ok/issue442.run-ir.ok | 4 +- test/run/ok/issue442.run-low.ok | 4 +- test/run/ok/issue442.run.ok | 4 +- test/run/ok/issue442.tc.ok | 4 +- test/run/ok/issue442.wasm.stderr.ok | 4 +- test/run/ok/type-lub.wasm-run.ok | 1 + test/run/type-lub.as | 152 ++++++++++++++++++++ 15 files changed, 480 insertions(+), 73 deletions(-) create mode 100644 test/repl/ok/type-lub-repl.stderr.ok create mode 100644 test/repl/ok/type-lub-repl.stdout.ok create mode 100755 test/repl/type-lub-repl.sh create mode 100644 test/run/ok/type-lub.wasm-run.ok create mode 100644 test/run/type-lub.as diff --git a/src/as_frontend/typing.ml b/src/as_frontend/typing.ml index b83219f4368..68127440271 100644 --- a/src/as_frontend/typing.ml +++ b/src/as_frontend/typing.ml @@ -549,7 +549,7 @@ and infer_exp'' env exp : T.typ = | ArrayE (mut, exps) -> let ts = List.map (infer_exp env) exps in let t1 = List.fold_left T.lub T.Non ts in - if not env.pre && t1 = T.Any && List.for_all (fun t -> T.promote t <> T.Any) ts then + if not env.pre && is_inconsistent t1 ts then warn env exp.at "this array has type %s because elements have inconsistent types" (T.string_of_typ (T.Array t1)); @@ -665,7 +665,7 @@ and infer_exp'' env exp : T.typ = let t2 = infer_exp env exp2 in let t3 = infer_exp env exp3 in let t = T.lub t2 t3 in - if not env.pre && t = T.Any && T.promote t2 <> T.Any && T.promote t3 <> T.Any then + if not env.pre && is_inconsistent t [t2; t3] then warn env exp.at "this if has type %s because branches have inconsistent types,\ntrue produces\n %s\nfalse produces\n %s" (T.string_of_typ t) @@ -853,7 +853,7 @@ and infer_case env t_pat t {it = {pat; exp}; at; _} = let ve = check_pat env t_pat pat in let t' = recover_with T.Non (infer_exp (adjoin_vals env ve)) exp in let t'' = T.lub t t' in - if not env.pre && t'' = T.Any && T.promote t <> T.Any && T.promote t' <> T.Any then + if not env.pre && is_inconsistent t'' [t; t'] then warn env at "the switch has type %s because branches have inconsistent types,\nthis case produces type\n %s\nthe previous produce type\n %s" (T.string_of_typ t'') (T.string_of_typ_expand t) @@ -867,6 +867,9 @@ and check_case env t_pat t {it = {pat; exp}; _} = let ve = check_pat env t_pat pat in recover (check_exp (adjoin_vals env ve) t) exp +and is_inconsistent lub ts = + lub = T.Any && List.for_all (fun t -> T.promote t <> lub) ts + || lub = T.Shared && List.for_all (fun t -> T.promote t <> lub) ts (* Patterns *) diff --git a/src/as_ir/check_ir.ml b/src/as_ir/check_ir.ml index a213349bc6a..88858ba1820 100644 --- a/src/as_ir/check_ir.ml +++ b/src/as_ir/check_ir.ml @@ -128,7 +128,9 @@ let rec check_typ env typ : unit = | T.Var (s, i) -> error env no_region "free type variable %s, index %i" s i | T.Con (c, typs) -> - check env no_region (T.ConSet.mem c env.cons) "free type constructor %s" (Con.name c); + (*check env no_region (T.ConSet.mem c env.cons) "free type constructor %s" (Con.name c); + TODO(gabor): re-add above check when it is understood how to deal with mu-types + originating from lub/glb *) (match Con.kind c with | T.Def (tbs, t) | T.Abs (tbs, t) -> check_typ_bounds env tbs typs no_region ) diff --git a/src/as_types/type.ml b/src/as_types/type.ml index 8ca00731cb7..42864b3a472 100644 --- a/src/as_types/type.ml +++ b/src/as_types/type.ml @@ -288,10 +288,9 @@ let open_binds tbs = let cs = List.map (fun {var; _} -> Con.fresh var (Abs ([], Pre))) tbs in let ts = List.map (fun c -> Con (c, [])) cs in let ks = List.map (fun {bound; _} -> Abs ([], open_ ts bound)) tbs in - List.iter2 (fun c k -> set_kind c k) cs ks; + List.iter2 set_kind cs ks; ts - (* Normalization and Classification *) let reduce tbs t ts = @@ -556,6 +555,12 @@ let is_concrete t = end in go t + +module M = Map.Make (struct type t = typ * typ let compare = compare end) +(* Forward declare + TODO: haul string_of_typ before the lub/glb business, if possible *) +let str = ref (fun _ -> failwith "") + (* Equivalence & Subtyping *) module S = Set.Make (struct type t = typ * typ let compare = compare end) @@ -731,63 +736,164 @@ and eq_kind k1 k2 : bool = (* Least upper bound and greatest lower bound *) -let rec lub t1 t2 = +let rec lub' lubs glbs t1 t2 = if t1 == t2 then t1 else - (* TBR: this is just a quick hack *) - match normalize t1, normalize t2 with - | _, Pre - | Pre, _ -> Pre - | _, Any - | Any, _ -> Any - | _, Non -> t1 - | Non, _ -> t2 - | Prim Nat, Prim Int - | Prim Int, Prim Nat -> Prim Int - | Opt t1', Opt t2' -> Opt (lub t1' t2') - | Variant t1', Variant t2' -> Variant (lub_tags t1' t2') - | Prim Null, Opt t' - | Opt t', Prim Null -> Opt t' - | Array t1', (Obj _ as t2) -> lub (array_obj t1') t2 - | (Obj _ as t1), Array t2' -> lub t1 (array_obj t2') - | t1', t2' when eq t1' t2' -> t1 - | _ -> Any - -and lub_tags fs1 fs2 = match fs1, fs2 with + match M.find_opt (t1, t2) !lubs with + | Some t -> t + | _ -> + match t1, t2 with + | _, Pre + | Pre, _ -> assert false + | _, Any + | Any, _ -> Any + | _, Non -> t1 + | Non, _ -> t2 + | Shared, _ when sub t2 Shared -> Shared + | _, Shared when sub t1 Shared -> Shared + | Prim Nat, (Prim Int as t) + | (Prim Int as t), Prim Nat -> t + | Opt t1', Opt t2' -> + Opt (lub' lubs glbs t1' t2') + | Prim Null, Opt t' -> t2 + | Opt t', Prim Null -> t1 + | Variant t1', Variant t2' -> + Variant (lub_tags lubs glbs t1' t2') + | Array t1', Obj _ -> lub' lubs glbs (array_obj t1') t2 + | Obj _, Array t2' -> lub' lubs glbs t1 (array_obj t2') + | Prim Text, Obj _ -> lub' lubs glbs text_obj t2 + | Obj _, Prim Text -> lub' lubs glbs t1 text_obj + | Prim Text, Array t2' -> lub' lubs glbs text_obj (array_obj t2') + | Array t1', Prim Text -> lub' lubs glbs (array_obj t1') text_obj + | Array t1', Array t2' -> + Array (lub' lubs glbs t1' t2') + | Tup ts1, Tup ts2 when List.(length ts1 = length ts2) -> + Tup (List.map2 (lub' lubs glbs) ts1 ts2) + | Obj (s1, tf1), Obj (s2, tf2) when s1 = s2 -> + Obj (s1, lub_fields lubs glbs tf1 tf2) + | Func (s1, c1, bs1, args1, res1), Func (s2, c2, bs2, args2, res2) + when s1 = s2 && c1 = c2 && List.(length bs1 = length bs2) && + List.(length args1 = length args2 && length res1 = length res2) -> + combine_func_parts s1 c1 bs1 args1 res1 bs2 args2 res2 lubs glbs glb' lub' + | Async t1', Async t2' -> + Async (lub' lubs glbs t1' t2') + | Con _, _ + | _, Con _ -> + combine_con_parts t1 t2 "lub" lubs (lub' lubs glbs) + | _ when eq t1 t2 -> t1 + | _ when sub t1 Shared && sub t2 Shared -> Shared + | _ -> Any + +and lub_fields lubs glbs fs1 fs2 = match fs1, fs2 with + | _, [] -> [] + | [], _ -> [] + | f1::fs1', f2::fs2' -> + match compare_field f1 f2 with + | -1 -> lub_fields lubs glbs fs1' fs2 + | +1 -> lub_fields lubs glbs fs1 fs2' + | _ -> {f1 with typ = lub' lubs glbs f1.typ f2.typ}::lub_fields lubs glbs fs1' fs2' + +and lub_tags lubs glbs fs1 fs2 = match fs1, fs2 with | fs1, [] -> fs1 | [], fs2 -> fs2 | f1::fs1', f2::fs2' -> match compare_field f1 f2 with - | -1 -> f1 :: lub_tags fs1' fs2 - | +1 -> f2 :: lub_tags fs1 fs2' - | _ -> {f1 with typ = lub f1.typ f2.typ} :: lub_tags fs1' fs2' + | -1 -> f1 :: lub_tags lubs glbs fs1' fs2 + | +1 -> f2 :: lub_tags lubs glbs fs1 fs2' + | _ -> {f1 with typ = lub' lubs glbs f1.typ f2.typ} :: lub_tags lubs glbs fs1' fs2' -let rec glb t1 t2 = +and glb' lubs glbs t1 t2 = if t1 == t2 then t1 else - (* TBR: this is just a quick hack *) - match normalize t1, normalize t2 with - | _, Pre - | Pre, _ -> Pre - | _, Any -> t1 - | Any, _ -> t2 - | _, Non -> Non - | Non, _ -> Non - | Prim Nat, Prim Int - | Prim Int, Prim Nat -> Prim Nat - | Opt t1', Opt t2' -> Opt (glb t1' t2') - | Variant t1', Variant t2' -> Variant (glb_tags t1' t2') - | Prim Null, Opt _ - | Opt _, Prim Null -> Prim Null - | t1', t2' when eq t1' t2' -> t1 - | _ -> Non - -and glb_tags fs1 fs2 = match fs1, fs2 with + match M.find_opt (t1, t2) !glbs with + | Some t -> t + | _ -> + match t1, t2 with + | _, Pre + | Pre, _ -> assert false + | _, Any -> t1 + | Any, _ -> t2 + | _, Non + | Non, _ -> Non + | Shared, _ when sub t2 Shared -> t2 + | _, Shared when sub t1 Shared -> t1 + | (Prim Nat as t), Prim Int + | Prim Int, (Prim Nat as t) -> t + | Opt t1', Opt t2' -> + Opt (glb' lubs glbs t1' t2') + | Variant t1', Variant t2' -> + Variant (glb_tags lubs glbs t1' t2') + | Prim Null, Opt _ + | Opt _, Prim Null -> Prim Null + | Array t1', Obj _ when sub (array_obj t1') t2 -> t1 (* TODO(gabor): payload should be glb'd *) + | Obj _, Array t2' when sub (array_obj t2') t1 -> t2 (* TODO(gabor): payload should be glb'd *) + | Prim Text, Obj _ when sub text_obj t2 -> t1 + | Obj _, Prim Text when sub text_obj t1 -> t2 + | Tup ts1, Tup ts2 when List.(length ts1 = length ts2) -> + Tup (List.map2 (glb' lubs glbs) ts1 ts2) + | Array t1', Array t2' -> + Array (glb' lubs glbs t1' t2') + | Obj (s1, tf1), Obj (s2, tf2) when s1 = s2 -> + Obj (s1, glb_fields lubs glbs tf1 tf2) + | Func (s1, c1, bs1, args1, res1), Func (s2, c2, bs2, args2, res2) + when s1 = s2 && c1 = c2 && List.(length bs1 = length bs2) && + List.(length args1 = length args2 && length res1 = length res2) -> + combine_func_parts s1 c1 bs1 args1 res1 bs2 args2 res2 lubs glbs lub' glb' + | Async t1', Async t2' -> + Async (glb' lubs glbs t1' t2') + | Con _, _ + | _, Con _ -> + combine_con_parts t1 t2 "glb" glbs (glb' lubs glbs) + | _ when eq t1 t2 -> t1 + | _ -> Non + +and glb_fields lubs glbs fs1 fs2 = match fs1, fs2 with + | fs1, [] -> fs1 + | [], fs2 -> fs2 + | f1::fs1', f2::fs2' -> + match compare_field f1 f2 with + | +1 -> f2::glb_fields lubs glbs fs1 fs2' + | -1 -> f1::glb_fields lubs glbs fs1' fs2 + | _ -> {f1 with typ = glb' lubs glbs f1.typ f2.typ}::glb_fields lubs glbs fs1' fs2' + +and glb_tags lubs glbs fs1 fs2 = match fs1, fs2 with | fs1, [] -> [] | [], fs2 -> [] | f1::fs1', f2::fs2' -> match compare_field f1 f2 with - | -1 -> glb_tags fs1' fs2 - | +1 -> glb_tags fs1 fs2' - | _ -> {f1 with typ = glb f1.typ f2.typ}::glb_tags fs1' fs2' + | -1 -> glb_tags lubs glbs fs1' fs2 + | +1 -> glb_tags lubs glbs fs1 fs2' + | _ -> {f1 with typ = glb' lubs glbs f1.typ f2.typ}::glb_tags lubs glbs fs1' fs2' + +and combine_func_parts s c bs1 args1 res1 bs2 args2 res2 lubs glbs contra co = + let open List in + let ts1 = open_binds bs1 in + let op = map (open_ ts1) in + let get_con = function | Con (c, []) -> c | _ -> assert false in + let cs = map get_con ts1 in + let cl = map (close cs) in + let combine_binds = + map2 (fun b1 b2 -> {b1 with bound = contra lubs glbs b1.bound b2.bound}) in + Func + (s, c, combine_binds bs1 bs2, + cl (map2 (contra lubs glbs) (op args1) (op args2)), + cl (map2 (co lubs glbs) (op res1) (op res2))) + +and combine_con_parts t1 t2 naming re how = + let s1, s2 = !str t1, !str t2 in + if s1 = s2 then t1 else + let c = Con.fresh (Printf.sprintf "@%s(%s, %s)" naming s1 s2) (Abs ([], Pre)) in + let t = Con (c, []) in + re := M.add (t2, t1) t (M.add (t1, t2) t !re); + let inner = how (normalize t1) (normalize t2) in + set_kind c (Def ([], inner)); + (* check for short-circuiting opportunities *) + if eq inner t1 + then (re := M.add (t2, t1) t1 (M.add (t1, t2) t1 !re); t1) + else if eq inner t2 + then (re := M.add (t2, t1) t2 (M.add (t1, t2) t2 !re); t2) + else inner + +let lub t1 t2 = lub' (ref M.empty) (ref M.empty) t1 t2 +let glb t1 t2 = glb' (ref M.empty) (ref M.empty) t1 t2 (* Environments *) @@ -950,6 +1056,7 @@ and string_of_kind k = let string_of_con : con -> string = string_of_con' [] let string_of_typ : typ -> string = string_of_typ' [] +let _ = str := string_of_typ let rec string_of_typ_expand t = let s = string_of_typ t in diff --git a/test/fail/ok/type-inference.tc.ok b/test/fail/ok/type-inference.tc.ok index 26ad31a9324..6fcd921c9f0 100644 --- a/test/fail/ok/type-inference.tc.ok +++ b/test/fail/ok/type-inference.tc.ok @@ -1,32 +1,39 @@ -type-inference.as:10.9-10.28: warning, this if has type Any because branches have inconsistent types, +type-inference.as:10.9-10.28: warning, this if has type Shared because branches have inconsistent types, true produces Bool false produces Nat -type-inference.as:11.9-11.27: warning, this if has type Any because branches have inconsistent types, +type-inference.as:11.9-11.34: warning, this if has type Any because branches have inconsistent types, +true produces + Bool +false produces + [var Nat] +type-inference.as:12.9-12.27: warning, this if has type Shared because branches have inconsistent types, true produces Nat false produces Float -type-inference.as:12.9-12.33: warning, this if has type Any because branches have inconsistent types, +type-inference.as:13.9-13.33: warning, this if has type Any because branches have inconsistent types, true produces () false produces {} -type-inference.as:13.9-13.53: warning, this if has type Any because branches have inconsistent types, -true produces - {x : Nat} -false produces - {x : var Nat} -type-inference.as:17.33-17.41: warning, the switch has type Any because branches have inconsistent types, +type-inference.as:18.33-18.41: warning, the switch has type Shared because branches have inconsistent types, this case produces type Bool the previous produce type Nat -type-inference.as:18.43-18.56: warning, the switch has type Any because branches have inconsistent types, +type-inference.as:19.33-19.47: warning, the switch has type Any because branches have inconsistent types, +this case produces type + Bool +the previous produce type + [var Nat] +type-inference.as:20.43-20.56: warning, the switch has type Shared because branches have inconsistent types, this case produces type Int the previous produce type Text -type-inference.as:78.13-78.16: type error, expected iterable type, but expression has type +type-inference.as:25.9-25.18: warning, this array has type [Shared] because elements have inconsistent types +type-inference.as:26.9-26.24: warning, this array has type [Any] because elements have inconsistent types +type-inference.as:84.13-84.16: type error, expected iterable type, but expression has type Non diff --git a/test/fail/type-inference.as b/test/fail/type-inference.as index f67c294c61e..1e34c3643be 100644 --- a/test/fail/type-inference.as +++ b/test/fail/type-inference.as @@ -8,6 +8,7 @@ let y = f(func x = x + 1); // Branch warnings. let _ = if true true else 5; +let _ = if true true else [var 5]; let _ = if true 5 else 5.1; let _ = if true {} else (new {}); let _ = if true (new {x = 5}) else (new {var x = 5}); @@ -15,9 +16,14 @@ let _ = if true 1 else (-1); // ok let _ = if true true else (5 : Any); // ok let _ = switch 0 { case 0 true; case _ 5 }; +let _ = switch 0 { case 0 true; case _ [var 5] }; let _ = switch 0 { case 0 2; case 2 (-5); case 3 "text"; case _ () }; let _ = switch 0 { case 0 true; case _ (() : Any); }; // ok +// Array warnings. + +let _ = [true, 5]; +let _ = [true, [var 5]]; // Local types (not) escaping. diff --git a/test/repl/ok/type-lub-repl.stderr.ok b/test/repl/ok/type-lub-repl.stderr.ok new file mode 100644 index 00000000000..a32a914044d --- /dev/null +++ b/test/repl/ok/type-lub-repl.stderr.ok @@ -0,0 +1,24 @@ +stdin:34.18-34.26: type error, expression of type + {get : Nat -> Int; keys : () -> {next : () -> ?Nat}; len : () -> Nat; vals : () -> {next : () -> ?Int}} +cannot produce expected type + [Int] +stdin:34.1-34.27: type error, expression of type + Nat +cannot produce expected type + () +stdin:35.18-35.26: type error, expression of type + {get : Nat -> Int; keys : () -> {next : () -> ?Nat}; len : () -> Nat; vals : () -> {next : () -> ?Int}} +cannot produce expected type + [Int] +stdin:35.1-35.27: type error, expression of type + Nat +cannot produce expected type + () +stdin:42.19-42.26: type error, literal of type + Text +does not have expected type + Non +stdin:43.19-43.44: type error, expression of type + [Char] +cannot produce expected type + Non diff --git a/test/repl/ok/type-lub-repl.stdout.ok b/test/repl/ok/type-lub-repl.stdout.ok new file mode 100644 index 00000000000..a2e43e5479c --- /dev/null +++ b/test/repl/ok/type-lub-repl.stdout.ok @@ -0,0 +1,43 @@ +ActorScript 0.1 interpreter +> [null, ?42, ?-25] : [(?Int)] +> [null, null] : [Null] +> [{a = 42}, {b = 42}] : [{}] +> [{a = 42}, {a = 1; b = 42}, {a = -25}] : [{a : Int}] +> [{len = func}, [1, 2, 3]] : [{len : () -> Nat}] +> [{len = func}, "hello"] : [{len : () -> Nat}] +> [[1, 2, 3], "hello"] : [{len : () -> Nat}] +> [{len = func}, [1, 2, 3], "hello"] : [{len : () -> Nat}] +> [(12, -1), (-42, 25)] : [(Int, Int)] +> [-1, 25] : [Int] +> [[-42], [25]] : [[Int]] +> [func, func] : [(Non -> Int)] +> [func, func] : [([Nat] -> Int)] +> 3 : Int +> -42 : Int +> [func, func] : [([Nat] -> Int)] +> 3 : Int +> -42 : Int +> [func, func] : [([Nat] -> Int)] +> 3 : Int +> -42 : Int +> [func, func] : [(([A], B) -> A)] +> [func, func] : [(([A], B) -> A)] +> 1 : Nat +> 11 : Nat +> [func, func] : [([Int] -> Nat)] +> 13 : Nat +> 3 : Nat +> let combined : {get : Nat -> Int; keys : () -> {next : () -> ?Nat}; len : () -> Nat; vals : () -> {next : () -> ?Int}} = {get = func; keys = func; len = func; vals = func} +> > 5 : Nat +> 5 : Nat +> [func, func] : [(Non -> Nat)] +> > > [func, func] : [({#bar} -> ())] +> > > [[42], [25], [77]] : [[Any]] +> [42, 77, [1, 2, 3]] : [Shared] +> [77, [1, 2, 3], 42] : [Shared] +> [func, func] : [(Int -> Int)] +> 25 : Int +> 42 : Int +> func : (C, D) -> [C] +> [async ?4, async ?-42] : [(async (?Int))] +> diff --git a/test/repl/type-lub-repl.sh b/test/repl/type-lub-repl.sh new file mode 100755 index 00000000000..cc4e31ca21d --- /dev/null +++ b/test/repl/type-lub-repl.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env bash +# Tests that correct lub types are inferred when values appear in arrays +${ASC:-$(dirname "$BASH_SOURCE")/../../src/asc} -i ../run/type-lub.as <<__END__ +opts; +nulls; +incompatible_objs; +objs; +obj_arrs; +obj_texts; +arr_texts; +obj_arr_texts; +tups; +tup1s; +arrs; +incompatible_funcs; +funcs; +funcs[0]([1, 2, 3]); +funcs[1]([1, 2, 3]); +poly_funcs; +poly_funcs[0]([1, 2, 3]); +poly_funcs[1]([1, 2, 3]); +poly_funcs2; +poly_funcs2[0]([1, 2, 3]); +poly_funcs2[1]([1, 2, 3]); +poly_funcs3; +poly_funcs4; +poly_funcs4[0]([1, 2, 3], 42); +poly_funcs4[1]([11, 22, 33], 25); +obj_arr_funcs; +obj_arr_funcs[0]([1, 2, 3]); +obj_arr_funcs[1]([1, 2, 3]); +let combined = new { len () : Nat = 42 + ; get (i : Nat) : Int = i + ; keys () : {next () : ?Nat} = new { next () : ?Nat = null } + ; vals () : {next () : ?Int} = new { next () : ?Int = null } + }; +obj_arr_funcs[0](combined); // error: no object below array +obj_arr_funcs[1](combined); // error + +obj_text_funcs; +obj_text_funcs[0]("hello"); +obj_text_funcs[1]("hello"); + +arr_text_funcs; +arr_text_funcs[0]("hello"); +arr_text_funcs[1](['h', 'e', 'l', 'l', 'o']); + +variant_funcs; +variant_funcs[0](#bar); +variant_funcs[1](#bar); + +mut_arrs; + +shareds; +shared2s; +shared_funcs; +shared_funcs[0](25); +shared_funcs[1](25); + +c0; +c1s; +__END__ diff --git a/test/run/ok/issue442.run-ir.ok b/test/run/ok/issue442.run-ir.ok index 136d5ad0c79..486c222891b 100644 --- a/test/run/ok/issue442.run-ir.ok +++ b/test/run/ok/issue442.run-ir.ok @@ -1,5 +1,5 @@ -issue442.as:1.11-1.24: warning, this array has type [Any] because elements have inconsistent types -issue442.as:2.11-2.29: warning, this if has type Any because branches have inconsistent types, +issue442.as:1.11-1.24: warning, this array has type [Shared] because elements have inconsistent types +issue442.as:2.11-2.29: warning, this if has type Shared because branches have inconsistent types, true produces Nat false produces diff --git a/test/run/ok/issue442.run-low.ok b/test/run/ok/issue442.run-low.ok index 136d5ad0c79..486c222891b 100644 --- a/test/run/ok/issue442.run-low.ok +++ b/test/run/ok/issue442.run-low.ok @@ -1,5 +1,5 @@ -issue442.as:1.11-1.24: warning, this array has type [Any] because elements have inconsistent types -issue442.as:2.11-2.29: warning, this if has type Any because branches have inconsistent types, +issue442.as:1.11-1.24: warning, this array has type [Shared] because elements have inconsistent types +issue442.as:2.11-2.29: warning, this if has type Shared because branches have inconsistent types, true produces Nat false produces diff --git a/test/run/ok/issue442.run.ok b/test/run/ok/issue442.run.ok index 136d5ad0c79..486c222891b 100644 --- a/test/run/ok/issue442.run.ok +++ b/test/run/ok/issue442.run.ok @@ -1,5 +1,5 @@ -issue442.as:1.11-1.24: warning, this array has type [Any] because elements have inconsistent types -issue442.as:2.11-2.29: warning, this if has type Any because branches have inconsistent types, +issue442.as:1.11-1.24: warning, this array has type [Shared] because elements have inconsistent types +issue442.as:2.11-2.29: warning, this if has type Shared because branches have inconsistent types, true produces Nat false produces diff --git a/test/run/ok/issue442.tc.ok b/test/run/ok/issue442.tc.ok index 136d5ad0c79..486c222891b 100644 --- a/test/run/ok/issue442.tc.ok +++ b/test/run/ok/issue442.tc.ok @@ -1,5 +1,5 @@ -issue442.as:1.11-1.24: warning, this array has type [Any] because elements have inconsistent types -issue442.as:2.11-2.29: warning, this if has type Any because branches have inconsistent types, +issue442.as:1.11-1.24: warning, this array has type [Shared] because elements have inconsistent types +issue442.as:2.11-2.29: warning, this if has type Shared because branches have inconsistent types, true produces Nat false produces diff --git a/test/run/ok/issue442.wasm.stderr.ok b/test/run/ok/issue442.wasm.stderr.ok index 136d5ad0c79..486c222891b 100644 --- a/test/run/ok/issue442.wasm.stderr.ok +++ b/test/run/ok/issue442.wasm.stderr.ok @@ -1,5 +1,5 @@ -issue442.as:1.11-1.24: warning, this array has type [Any] because elements have inconsistent types -issue442.as:2.11-2.29: warning, this if has type Any because branches have inconsistent types, +issue442.as:1.11-1.24: warning, this array has type [Shared] because elements have inconsistent types +issue442.as:2.11-2.29: warning, this if has type Shared because branches have inconsistent types, true produces Nat false produces diff --git a/test/run/ok/type-lub.wasm-run.ok b/test/run/ok/type-lub.wasm-run.ok new file mode 100644 index 00000000000..ded9968ad6a --- /dev/null +++ b/test/run/ok/type-lub.wasm-run.ok @@ -0,0 +1 @@ +_out/type-lub.wasm:0x___: runtime trap: unreachable executed diff --git a/test/run/type-lub.as b/test/run/type-lub.as new file mode 100644 index 00000000000..783929db3d2 --- /dev/null +++ b/test/run/type-lub.as @@ -0,0 +1,152 @@ +let opts = [null, ?42, ?-25]; +let nulls = [null, null]; + +let incompatible_objs = [new {a = 42}, new {b = 42}]; +let objs = [new {a = 42}, new {b = 42; a = 1}, new {a = -25}]; +let obj_arrs = [new {len() : Nat = 42}, [1, 2, 3]]; +let obj_texts = [new {len() : Nat = 42}, "hello"]; +let arr_texts = [[1, 2, 3], "hello"]; +let obj_arr_texts = [new {len() : Nat = 42}, [1, 2, 3], "hello"]; + +let tups = [(12, -1), (-42, 25)]; +let tup1s = [(-1,), 25]; + +let arrs = [[-42], [25]]; + +let incompatible_funcs = [ func (a : [Int]) : Nat = a.len() + , func (a : ()) : Int = -42 + ]; + +let poly_funcs = [ func (a : [Int]) : Nat = a.len() + , func (a : [Nat]) : Int = -42 + ]; + +let poly_funcs2 = [ func (a : [Int]) : Nat = a.len() + , func (a : [Nat]) : Int = -42 + ]; + +let poly_funcs3 = [ func (as : [A], b : B) : A = as[0] + , func (bs : [B], a : A) : B = bs[0] + ]; + +let poly_funcs4 = [ func (as : [A], b : B) : A = as[0] + , func (bs : [B], a : A) : B = bs[0] + ]; + +let funcs = [ func (a : [Int]) : Nat = a.len() + , func (a : [Nat]) : Int = -42 + ]; + +let obj_arr_funcs = [ func (a : [Int]) : Nat { printInt (a[0]); a.len() } + , func (a : {len : () -> Nat}) : Nat = a.len() + ]; + +let obj_text_funcs = [ func (a : Text) : Nat = a.len() + , func (a : {len : () -> Nat}) : Nat = a.len() + ]; + +let arr_text_funcs = [ func (a : Text) : Nat = a.len() + , func (a : [Char]) : Nat { printChar (a[0]); a.len() } + ]; + +let variant_funcs = [ func (a : {#foo; #bar}) { switch a { case (#foo) (); case (#bar) () } } + , func (a : {#baz; #bar}) { switch a { case (#baz) (); case (#bar) () } } + ]; + +// TODO(gabor), mutable arrays +let mut_arrs = [[var 42], [var 25], [77]]; // boring + +// TODO(gabor), mutable fields, see fail/type-inference.as:13 + +let sh : Shared = 42; +let shareds = [sh, 77, [1, 2, 3]]; +let shared2s = [77, [1, 2, 3], sh]; + +let shared_funcs = [ func (a : Int) : Int = a + , func (a : Shared) : Nat = 42 + ]; + +type C = async(?Int); +type D = async(?Nat); + +func c0(c : C, d : D) : [C] { ignore([c, d]); [c, d] }; +let c1s = [async ?4, async ?-42]; + + +// recursive objects + +// { need global types due to https://dfinity.atlassian.net/browse/AST-34 +type A = {x : A}; +type B = {x : B}; + +func f(v : {x : {x : B}; b : B}, x : A, y : B, z : {x : B; a : A}) : [A] { ignore([v, x, y, z]); [v, x, y, z] }; +// }; + +// { +type A1 = {x : B1}; +type B1 = {x : A1}; + +func f1(x : A1, y : B1) : [A1] { ignore([x, y]); [x, y] }; +// }; + +type O = ?O; +type P = ?P; + +type Q = ?R; +type R = ?S; +type S = ?Q; + +func g(o : O, p : P, q : Q, r : R) : [O] { ignore([o, p, q, r]); [o, p, q, r] }; + +// example from https://dfinity.atlassian.net/browse/AST-83 + +type Foo = ?(Foo); +ignore (if true (null : Foo) else (null : Foo)); + + +type U = { #a : U; #b : Int }; +type V = { #a : V; #b : Nat }; + +func v0(u : U, v : V, w : { #a : { #a : V; #b : Nat }; #b : Nat }) : [U] { ignore([u, v, w]); [u, v, w] }; + + +type G = (Nat, ?G); +type H = (Int, ?H); + +func g0(g : G, h : H) : [H] { ignore([g, h]); [g, h] }; + + +type K = [K]; +type L = [L]; + +func k0(k : K, l : L) : [L] { ignore([k, l]); [k, l] }; + + +type K1 = [?(Nat, K1)]; +type L1 = [?(Int, L1)]; + +func k1(k : K1, l : L1) : [L1] { ignore([k, l]); [k, l] }; + + +/* +type M = [var ?M]; +type N = [?N]; + +func m0(m : M, n : N) : [M] { ignore([m, n]); [m, n] }; +*/ + +type E = Int -> E; +type F = Nat -> F; + +func f0(e : E, f : F) : [F] { ignore([e, f]); [e, f] }; + +type E1 = E1 -> E1; +type F1 = F1 -> F1; + +func f12(e : E1, f : F1) : [F1] { ignore([e, f]); [e, f] }; + +type E2 = F2 -> E2; +type F2 = E2 -> F2; + +func f2(e : E2, f : F2) : [F2] { ignore([e, f]); [e, f] }; + From 066643df562fb9b1e4d354e5203314956d595f5d Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Thu, 20 Jun 2019 17:07:50 +0200 Subject: [PATCH 0195/1176] Reinstate IR Con check (#516) * reinstate IR Con check * Add TODO as requested by @crusso --- src/as_ir/check_ir.ml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/as_ir/check_ir.ml b/src/as_ir/check_ir.ml index 88858ba1820..0ba7c1bb643 100644 --- a/src/as_ir/check_ir.ml +++ b/src/as_ir/check_ir.ml @@ -128,12 +128,13 @@ let rec check_typ env typ : unit = | T.Var (s, i) -> error env no_region "free type variable %s, index %i" s i | T.Con (c, typs) -> - (*check env no_region (T.ConSet.mem c env.cons) "free type constructor %s" (Con.name c); - TODO(gabor): re-add above check when it is understood how to deal with mu-types - originating from lub/glb *) - (match Con.kind c with | T.Def (tbs, t) | T.Abs (tbs, t) -> - check_typ_bounds env tbs typs no_region - ) + begin match Con.kind c with + | T.Def (tbs, _) -> check_typ_bounds env tbs typs no_region (* TODO(Claudio): + check bodies of anonymous T.Defs since they won't get checked elsewhere *) + | T.Abs (tbs, _) -> + check env no_region (T.ConSet.mem c env.cons) "free type constructor %s" (Con.name c); + check_typ_bounds env tbs typs no_region + end | T.Any -> () | T.Non -> () | T.Shared -> () @@ -144,7 +145,7 @@ let rec check_typ env typ : unit = List.iter (check_typ env) typs | T.Func (sort, control, binds, ts1, ts2) -> let cs, ce = check_typ_binds env binds in - let env' = adjoin_cons env ce in + let env' = adjoin_cons env ce in let ts = List.map (fun c -> T.Con (c, [])) cs in let ts1 = List.map (T.open_ ts) ts1 in let ts2 = List.map (T.open_ ts) ts2 in From 5973093e6992ad7f819e738f9e9a55c76a581df3 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 21 Jun 2019 09:42:08 +0200 Subject: [PATCH 0196/1176] Describe separate the compilation schemes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit this doesn’t really change the meaning of the document, but describes the intermediate step a with a bit more detail. This can be seen as a compromise that I can live with being merged into `master`. --- design/Units.md | 45 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/design/Units.md b/design/Units.md index 092da6408ed..9e7111593d0 100644 --- a/design/Units.md +++ b/design/Units.md @@ -52,6 +52,8 @@ The syntax of a unit -- and therefore an AS source file -- is a sequence of *imp Imports are no longer allowed anywhere else. +The `` of the `import` statement is an URL. The precise interpretation is implementation dependant (see below in section Compilation). It at least support local paths relative to the source file. URLs do _not_ include a file ending, such as `.as`, `.dll` or `.wasm`, to allow for different compilation schemes. + Each import binds the identifiers in its *import pattern*. If the pattern is a plain `` then the contents of the imported unit is reified as a module object bound to that id. If the pattern is a *destructuring* import pattern then the respective public fields of the unit are bound to the respective label identifiers. As a crucial restriction, a unit that has at least one public field must be *static*, see below. @@ -92,34 +94,55 @@ The defined actor can still bind and refer to a self variable for the resulting Similarly, the actor short-hand can be recursive. (That is, `actor class C() = this {...this...}` and `actor this {...this...}` are allowed, but `actor class C() = {...C...}` is not. If needs be, this restriction may be lifted later.) +## Compilation schemes + +The source language semantics can be implemented in various ways of increasing sophistication. + +### Source imports + +There are no build artifacts. + +Imports are resolved to ActorScript source files by appending `.as` to the impot path, and read before or during type-checking of the importing file. + +This compilation scheme is suitable for the interpreter, and for early versions of the compiler. + + +### Incremental compilation + +This compilation scheme expresses units as dynamically linkable Wasm modules (according to the [dynamic linking spec](https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md). -## Compilation +Imports are resolved to Wasm modules by appending `.wasm` to the impot path. -The compilation scheme uses the natural mechanisms in Wasm to express units as modules. +The exported module is mapped to Wasm exports (functions and globals) in an implementation-defined way that may vary between compiler versions. + +A custom section `as-type` in the Wasm module is used by the compiler to include the type of the unit. + +A custom section `as-interface` in the Wasm module may be used by the compiler to include any other information needed by the code generator, such as specialized calling conventions. + + +## Natural and separate compilation + +This extension to the former scheme explicitly uses _natural mechanisms_ in Wasm to express units as modules. That enables the best possible integration and interoperation with the wider Wasm eco system and existing tools. (However, it does not automatically enable functional interoperability with other languages, since AS types typically have a representation that cannot directly be interpreted externally. For this, additional interop support would be needed, which is beyond the scope of this proposal.) -Consequently, all units are compiled to Wasm modules. -Their public fields become Wasm exports. +Consequently, every public field of a unit becomes a a Wasm exports. These are either Wasm functions, for public fields of function type, or Wasm globals, for all others. -Compiling arbitrary closures into exported Wasm functions may require eta-expanding the closure and storing its environment into an internal global. -A Wasm module compiled from AS contains a Dfinity-relevant custom section as well as an AS-specific custom section describing the AS type of the module or actor. +No `as-interface` custom section may be present; the interface must be determined by the type alone. This allows true separate compliation. + +It also implies that compiling arbitrary closures into exported Wasm functions may require eta-expanding the closure and storing its environment into an internal global. -Imports expect the import URL to resolve to a Wasm module compiled from AS and link its exports accordingly. An import that is not destructured via a module pattern is reified into a module object at the import site. Programs and libraries are compiled exactly the same. That is, both create dynlib sections. Actors are different. -Their exported functions are wrapped into methods de/serialising their arguments and results according to the IDL epcification. +Their exported functions are wrapped into methods de/serialising their arguments and results according to the IDL sepcification. Furthermore, they are complemented with system exports for initialising the actor (given the actor class'es arguments) and for in/externalising the actor's state for upgrades (details TBD). -(For release 0.5, we do not yet intend to support separate compilation, and imports will resolve to source files compiled in a whole program manner instead.) - - ### Compiler We need two compilation modes, one for programs/libraries, the other for actors. We could differentiate based on file extensions, but that would get in the way of dual-using an actor source file as a library. From 7606b049df409c907e0c200145a88b06c8213b15 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 21 Jun 2019 15:22:02 +0200 Subject: [PATCH 0197/1176] Typos --- design/Units.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/design/Units.md b/design/Units.md index 9e7111593d0..3c33bbed5c7 100644 --- a/design/Units.md +++ b/design/Units.md @@ -52,7 +52,7 @@ The syntax of a unit -- and therefore an AS source file -- is a sequence of *imp Imports are no longer allowed anywhere else. -The `` of the `import` statement is an URL. The precise interpretation is implementation dependant (see below in section Compilation). It at least support local paths relative to the source file. URLs do _not_ include a file ending, such as `.as`, `.dll` or `.wasm`, to allow for different compilation schemes. +The `` of the `import` statement is an URL. The precise interpretation is implementation dependant (see below in section Compilation). It at least supports local paths relative to the source file. URLs do _not_ include a file ending, such as `.as`, `.dll` or `.wasm`, to allow for different compilation schemes. Each import binds the identifiers in its *import pattern*. If the pattern is a plain `` then the contents of the imported unit is reified as a module object bound to that id. If the pattern is a *destructuring* import pattern then the respective public fields of the unit are bound to the respective label identifiers. @@ -140,7 +140,7 @@ Programs and libraries are compiled exactly the same. That is, both create dynlib sections. Actors are different. -Their exported functions are wrapped into methods de/serialising their arguments and results according to the IDL sepcification. +Their exported functions are wrapped into methods de/serialising their arguments and results according to the IDL specification. Furthermore, they are complemented with system exports for initialising the actor (given the actor class'es arguments) and for in/externalising the actor's state for upgrades (details TBD). ### Compiler From 190d212bffc5464e988f977581b62d667065c7c3 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 21 Jun 2019 17:08:38 +0200 Subject: [PATCH 0198/1176] Correct section depth --- design/Units.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/design/Units.md b/design/Units.md index 3c33bbed5c7..7961377d4b5 100644 --- a/design/Units.md +++ b/design/Units.md @@ -120,7 +120,7 @@ A custom section `as-type` in the Wasm module is used by the compiler to include A custom section `as-interface` in the Wasm module may be used by the compiler to include any other information needed by the code generator, such as specialized calling conventions. -## Natural and separate compilation +### Natural and separate compilation This extension to the former scheme explicitly uses _natural mechanisms_ in Wasm to express units as modules. That enables the best possible integration and interoperation with the wider Wasm eco system and existing tools. From 124f9a17ebca5bc3be2cb937413fe564d64c315e Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Fri, 21 Jun 2019 10:02:29 -0600 Subject: [PATCH 0199/1176] clean and organize stdlib dir for SDK-264; fix Makefile bug that skipped tests --- default.nix | 17 ++ stdlib/Makefile | 191 +++++++----------- stdlib/nonCriticalPath/stream.as | 109 ---------- stdlib/nonCriticalPath/thunk.as | 31 --- stdlib/setDb.as | 116 ----------- stdlib/setDbTest.as | 185 ----------------- stdlib/{ => tools}/markdown-of-actorscript.py | 0 stdlib/{ => tools}/markdown-of-markdown.py | 0 stdlib/{time.c => tools/stopwatch.c} | 2 +- 9 files changed, 89 insertions(+), 562 deletions(-) delete mode 100644 stdlib/nonCriticalPath/stream.as delete mode 100644 stdlib/nonCriticalPath/thunk.as delete mode 100644 stdlib/setDb.as delete mode 100644 stdlib/setDbTest.as rename stdlib/{ => tools}/markdown-of-actorscript.py (100%) rename stdlib/{ => tools}/markdown-of-markdown.py (100%) rename stdlib/{time.c => tools/stopwatch.c} (90%) diff --git a/default.nix b/default.nix index 1fb4495e7ff..a24c631c840 100644 --- a/default.nix +++ b/default.nix @@ -277,6 +277,23 @@ rec { }; + stdlib = stdenv.mkDerivation { + name = "stdlib"; + src = subpath ./stdlib; + buildInputs = with nixpkgs; + [ bash ]; + buildPhase = '' + patchShebangs . + ''; + installPhase = '' + mkdir -p $out + cp -r $src $out/ + mkdir -p $out/nix-support + echo "report stdlib $out/stdlib" >> $out/nix-support/hydra-build-products + ''; + forceShare = ["man"]; + }; + stdlib-reference = stdenv.mkDerivation { name = "stdlib-reference"; src = subpath ./stdlib; diff --git a/stdlib/Makefile b/stdlib/Makefile index 78e3d5267b7..07f58835290 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -2,19 +2,35 @@ ASC=../src/asc DVM=dvm OUTDIR=_out DOCDIR=doc -MDofAS=./markdown-of-actorscript.py -MDofMD=./markdown-of-markdown.py +STOPWATCH_C=./tools/stopwatch.c +MDofAS=./tools/markdown-of-actorscript.py +MDofMD=./tools/markdown-of-markdown.py PANDOC=pandoc +STOPWATCH=$(OUTDIR)/stopwatch -WASM=\ - ProduceExchange\ - loadWorkloadAndQueryBig\ +WASM=ProduceExchange + +TESTS=\ + Option \ + Result \ + Hash \ + List \ + ListTest \ + AssocList \ + Trie \ + Trie2 \ + Set \ + DocTable \ + ProduceExchange \ + producerRemInventory \ + retailerReserveMany \ + evalBulk \ OUTFILES=$(addsuffix .out, $(TESTS)) $(addsuffix .wasm, $(WASM)) OUTPATHS=$(addprefix $(OUTDIR)/, $(OUTFILES)) -.PHONY: default all clean alltests alldoc docMd docHtml profile-wasm profile-wasm-success profile-interp profile-interp-small +.PHONY: default all clean alltests alldoc docMd docHtml profile-wasm profile-interp default: all @@ -24,7 +40,7 @@ docmsg: alltests: $(OUTDIR) $(OUTPATHS) -all: alltests alldoc profile-wasm-success profile-interp-small +all: alldoc alltests profile-wasm profile-interp clean: rm -rf $(OUTDIR) $(DOCDIR) @@ -32,30 +48,6 @@ clean: $(OUTDIR): @mkdir $@ -#########################################################################################################33 - -## -## Unit tests -## - -# Add new module targets here: -TESTS=\ - Option \ - Result \ - Hash \ - List \ - ListTest \ - AssocList \ - Trie \ - DocTable \ - Set \ - SetDb \ - SetDbTest \ - ProduceExchange \ - producerRemInventory \ - retailerReserveMany \ - evalBulk \ - $(OUTDIR)/Hash.out: hash.as | $(OUTDIR) $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ @@ -77,17 +69,15 @@ $(OUTDIR)/AssocList.out: assocList.as | $(OUTDIR) $(OUTDIR)/Trie.out: trie.as | $(OUTDIR) $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ -$(OUTDIR)/DocTable.out: docTable.as | $(OUTDIR) +$(OUTDIR)/Trie2.out:trie2.as | $(OUTDIR) $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ $(OUTDIR)/Set.out: set.as | $(OUTDIR) $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ -$(OUTDIR)/SetDb.out: setDb.as | $(OUTDIR) +$(OUTDIR)/DocTable.out: docTable.as | $(OUTDIR) $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ -$(OUTDIR)/SetDbTest.out: setDbTest.as | $(OUTDIR) - $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ #########################################################################################################33 @@ -96,7 +86,7 @@ $(OUTDIR)/SetDbTest.out: setDbTest.as | $(OUTDIR) ## PRODUCE_EXCHANGE_SRC=\ - prelude.as option.as hash.as list.as assocList.as trie.as docTable.as result.as \ + prelude.as option.as hash.as list.as assocList.as trie.as trie2.as docTable.as result.as \ examples/produce-exchange/serverTypes.as \ examples/produce-exchange/serverLang.as \ examples/produce-exchange/serverModelTypes.as \ @@ -121,10 +111,9 @@ docMd: \ $(DOCDIR)/list.md \ $(DOCDIR)/assocList.md \ $(DOCDIR)/trie.md \ - $(DOCDIR)/docTable.md \ + $(DOCDIR)/trie2.md \ $(DOCDIR)/set.md \ - $(DOCDIR)/setDb.md \ - $(DOCDIR)/setDbTest.md \ + $(DOCDIR)/docTable.md \ $(DOCDIR)/examples/produce-exchange/README.md \ $(DOCDIR)/examples/produce-exchange/serverTypes.md \ $(DOCDIR)/examples/produce-exchange/serverLang.md \ @@ -145,10 +134,9 @@ docHtml: \ $(DOCDIR)/list.html \ $(DOCDIR)/assocList.html \ $(DOCDIR)/trie.html \ + $(DOCDIR)/trie2.html \ $(DOCDIR)/docTable.html \ $(DOCDIR)/set.html \ - $(DOCDIR)/setDb.html \ - $(DOCDIR)/setDbTest.html \ $(DOCDIR)/examples/produce-exchange/README.html \ $(DOCDIR)/examples/produce-exchange/serverTypes.html \ $(DOCDIR)/examples/produce-exchange/serverLang.html \ @@ -176,7 +164,7 @@ $(DOCDIR)/examples/produce-exchange/README.md: examples/produce-exchange/README. $(MDofMD) $< >> $@ PRODUCE_EXCHANGE_SRC=\ - prelude.as option.as hash.as list.as assocList.as trie.as docTable.as result.as \ + prelude.as option.as hash.as list.as assocList.as trie2.as docTable.as result.as \ examples/produce-exchange/serverTypes.as \ examples/produce-exchange/serverLang.as \ examples/produce-exchange/serverModelTypes.as \ @@ -248,12 +236,6 @@ profile-fast-counts: \ $(OUTDIR)/profileFastCounts.csv: examples/produce-exchange/test/profileFastCounts.as $(ASC) -r examples/produce-exchange/test/profileFastCounts.as > $@ - -profile-interp-small: \ - $(OUTDIR)/profileLoadQuery.05-01.csv \ - $(OUTDIR)/profileLoadQuery.05-02.csv \ - $(OUTDIR)/profileLoadQuery.05-03.csv \ - profile-interp: \ $(OUTDIR)/profileLoadQuery.05-01.csv \ $(OUTDIR)/profileLoadQuery.05-02.csv \ @@ -311,37 +293,6 @@ $(OUTDIR)/profileLoadQuery.05-50.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUE $(OUTDIR)/profileLoadQuery.05-100.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) time $(ASC) -r --profile examples/produce-exchange/test/params-5-100.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) -# wasm binaries and time measurements for various-sized PX workloads -# -# these sizes all run without memory limitation issues; bigger sizes complain about growing memory -profile-wasm-success: profile-fast-counts $(OUTDIR) \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm.csv \ - \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_2.wasm \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_2.wasm.csv \ - \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_3.wasm \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_3.wasm.csv \ - \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_4.wasm \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_4.wasm.csv \ - \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm.csv \ - \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_6.wasm \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_6.wasm.csv \ - \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_7.wasm \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_7.wasm.csv \ - \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_8.wasm \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_8.wasm.csv \ - \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_9.wasm \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_9.wasm.csv \ - # wasm binaries and time measurements for various-sized PX workloads profile-wasm: $(OUTDIR) profile-fast-counts \ \ @@ -386,135 +337,135 @@ profile-wasm: $(OUTDIR) profile-fast-counts \ $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c -o $@ examples/produce-exchange/test/params-5-1.as examples/produce-exchange/profileActor.as + $(ASC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-1.as examples/produce-exchange/profileActor.as $(OUTDIR)/ProduceExchangeLoadQuery_5_2.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c -o $@ examples/produce-exchange/test/params-5-2.as examples/produce-exchange/profileActor.as + $(ASC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-2.as examples/produce-exchange/profileActor.as $(OUTDIR)/ProduceExchangeLoadQuery_5_3.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c -o $@ examples/produce-exchange/test/params-5-3.as examples/produce-exchange/profileActor.as + $(ASC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-3.as examples/produce-exchange/profileActor.as $(OUTDIR)/ProduceExchangeLoadQuery_5_4.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c -o $@ examples/produce-exchange/test/params-5-4.as examples/produce-exchange/profileActor.as + $(ASC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-4.as examples/produce-exchange/profileActor.as $(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c -o $@ examples/produce-exchange/test/params-5-5.as examples/produce-exchange/profileActor.as + $(ASC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-5.as examples/produce-exchange/profileActor.as $(OUTDIR)/ProduceExchangeLoadQuery_5_6.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c -o $@ examples/produce-exchange/test/params-5-6.as examples/produce-exchange/profileActor.as + $(ASC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-6.as examples/produce-exchange/profileActor.as $(OUTDIR)/ProduceExchangeLoadQuery_5_7.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c -o $@ examples/produce-exchange/test/params-5-7.as examples/produce-exchange/profileActor.as + $(ASC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-7.as examples/produce-exchange/profileActor.as $(OUTDIR)/ProduceExchangeLoadQuery_5_8.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c -o $@ examples/produce-exchange/test/params-5-8.as examples/produce-exchange/profileActor.as + $(ASC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-8.as examples/produce-exchange/profileActor.as $(OUTDIR)/ProduceExchangeLoadQuery_5_9.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c -o $@ examples/produce-exchange/test/params-5-9.as examples/produce-exchange/profileActor.as + $(ASC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-9.as examples/produce-exchange/profileActor.as $(OUTDIR)/ProduceExchangeLoadQuery_5_10.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c -o $@ examples/produce-exchange/test/params-5-10.as examples/produce-exchange/profileActor.as + $(ASC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-10.as examples/produce-exchange/profileActor.as $(OUTDIR)/ProduceExchangeLoadQuery_5_20.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c -o $@ examples/produce-exchange/test/params-5-20.as examples/produce-exchange/profileActor.as + $(ASC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-20.as examples/produce-exchange/profileActor.as $(OUTDIR)/ProduceExchangeLoadQuery_5_50.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c -o $@ examples/produce-exchange/test/params-5-50.as examples/produce-exchange/profileActor.as + $(ASC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-50.as examples/produce-exchange/profileActor.as $(OUTDIR)/ProduceExchangeLoadQuery_5_100.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c -o $@ examples/produce-exchange/test/params-5-100.as examples/produce-exchange/profileActor.as + $(ASC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-100.as examples/produce-exchange/profileActor.as -$(OUTDIR)/time: time.c - gcc time.c -o $@ +$(STOPWATCH): $(STOPWATCH_C) + gcc $< -o $@ -$(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm $(OUTDIR)/time +$(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm $(STOPWATCH) rm -rf ./.dvm $(DVM) reset $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm - $(OUTDIR)/time "$(DVM) run 1 start " "5, 1, " > $@ + $(STOPWATCH) "$(DVM) run 1 start " "5, 1, " > $@ cat $@ -$(OUTDIR)/ProduceExchangeLoadQuery_5_2.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_2.wasm $(OUTDIR)/time +$(OUTDIR)/ProduceExchangeLoadQuery_5_2.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_2.wasm $(STOPWATCH) rm -rf ./.dvm $(DVM) reset $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_2.wasm - $(OUTDIR)/time "$(DVM) run 1 start " "5, 2, " > $@ + $(STOPWATCH) "$(DVM) run 1 start " "5, 2, " > $@ cat $@ -$(OUTDIR)/ProduceExchangeLoadQuery_5_3.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_3.wasm $(OUTDIR)/time +$(OUTDIR)/ProduceExchangeLoadQuery_5_3.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_3.wasm $(STOPWATCH) rm -rf ./.dvm $(DVM) reset $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_3.wasm - $(OUTDIR)/time "$(DVM) run 1 start " "5, 3, " > $@ + $(STOPWATCH) "$(DVM) run 1 start " "5, 3, " > $@ cat $@ -$(OUTDIR)/ProduceExchangeLoadQuery_5_4.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_4.wasm $(OUTDIR)/time +$(OUTDIR)/ProduceExchangeLoadQuery_5_4.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_4.wasm $(STOPWATCH) rm -rf ./.dvm $(DVM) reset $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_4.wasm - $(OUTDIR)/time "$(DVM) run 1 start " "5, 4, " > $@ + $(STOPWATCH) "$(DVM) run 1 start " "5, 4, " > $@ cat $@ -$(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm $(OUTDIR)/time +$(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm $(STOPWATCH) rm -rf ./.dvm $(DVM) reset $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm - $(OUTDIR)/time "$(DVM) run 1 start " "5, 5, " > $@ + $(STOPWATCH) "$(DVM) run 1 start " "5, 5, " > $@ cat $@ -$(OUTDIR)/ProduceExchangeLoadQuery_5_6.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_6.wasm $(OUTDIR)/time +$(OUTDIR)/ProduceExchangeLoadQuery_5_6.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_6.wasm $(STOPWATCH) rm -rf ./.dvm $(DVM) reset $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_6.wasm - $(OUTDIR)/time "$(DVM) run 1 start " "5, 6, " > $@ + $(STOPWATCH) "$(DVM) run 1 start " "5, 6, " > $@ cat $@ -$(OUTDIR)/ProduceExchangeLoadQuery_5_7.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_7.wasm $(OUTDIR)/time +$(OUTDIR)/ProduceExchangeLoadQuery_5_7.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_7.wasm $(STOPWATCH) rm -rf ./.dvm $(DVM) reset $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_7.wasm - $(OUTDIR)/time "$(DVM) run 1 start " "5, 7, " > $@ + $(STOPWATCH) "$(DVM) run 1 start " "5, 7, " > $@ cat $@ -$(OUTDIR)/ProduceExchangeLoadQuery_5_8.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_8.wasm $(OUTDIR)/time +$(OUTDIR)/ProduceExchangeLoadQuery_5_8.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_8.wasm $(STOPWATCH) rm -rf ./.dvm $(DVM) reset $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_8.wasm - $(OUTDIR)/time "$(DVM) run 1 start " "5, 8, " > $@ + $(STOPWATCH) "$(DVM) run 1 start " "5, 8, " > $@ cat $@ -$(OUTDIR)/ProduceExchangeLoadQuery_5_9.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_9.wasm $(OUTDIR)/time +$(OUTDIR)/ProduceExchangeLoadQuery_5_9.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_9.wasm $(STOPWATCH) rm -rf ./.dvm $(DVM) reset $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm - $(OUTDIR)/time "$(DVM) run 1 start " "5, 9, " > $@ + $(STOPWATCH) "$(DVM) run 1 start " "5, 9, " > $@ cat $@ -$(OUTDIR)/ProduceExchangeLoadQuery_5_10.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_10.wasm $(OUTDIR)/time +$(OUTDIR)/ProduceExchangeLoadQuery_5_10.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_10.wasm $(STOPWATCH) rm -rf ./.dvm $(DVM) reset $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_10.wasm - $(OUTDIR)/time "$(DVM) run 1 start " "5, 10, " > $@ + $(STOPWATCH) "$(DVM) run 1 start " "5, 10, " > $@ cat $@ -$(OUTDIR)/ProduceExchangeLoadQuery_5_20.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_20.wasm $(OUTDIR)/time +$(OUTDIR)/ProduceExchangeLoadQuery_5_20.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_20.wasm $(STOPWATCH) rm -rf ./.dvm $(DVM) reset $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_20.wasm - $(OUTDIR)/time "$(DVM) run 1 start " "5, 20, " > $@ + $(STOPWATCH) "$(DVM) run 1 start " "5, 20, " > $@ cat $@ -$(OUTDIR)/ProduceExchangeLoadQuery_5_50.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_50.wasm $(OUTDIR)/time +$(OUTDIR)/ProduceExchangeLoadQuery_5_50.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_50.wasm $(STOPWATCH) rm -rf ./.dvm $(DVM) reset $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_50.wasm - $(OUTDIR)/time "$(DVM) run 1 start " "5, 50, " > $@ + $(STOPWATCH) "$(DVM) run 1 start " "5, 50, " > $@ cat $@ -$(OUTDIR)/ProduceExchangeLoadQuery_5_100.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_100.wasm $(OUTDIR)/time +$(OUTDIR)/ProduceExchangeLoadQuery_5_100.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_100.wasm $(STOPWATCH) rm -rf ./.dvm $(DVM) reset $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_100.wasm - $(OUTDIR)/time "$(DVM) run 1 start " "5, 100, " > $@ + $(STOPWATCH) "$(DVM) run 1 start " "5, 100, " > $@ cat $@ diff --git a/stdlib/nonCriticalPath/stream.as b/stdlib/nonCriticalPath/stream.as deleted file mode 100644 index 9945016de04..00000000000 --- a/stdlib/nonCriticalPath/stream.as +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Streams, a la functional programming, in ActorScript. - * - * Streams are lazy lists that may or may not end. - * If non-empty, a stream contains a value "today", - * and a thunk for the value "tomorrow", if any. - * - */ - -// Done: -// -// - standard stream definition (well, two versions) -// - standard higher-order combinators: map, mapfilter, merge - -// TODO-Matthew: Write: -// -// - (more) stream combinators: take, drop, sort, etc... -// - iterator objects, for use in 'for ... in ...' patterns -// - streams+pairs: zip, split, etc -// - regression tests for everything that is below - -// TODO-Matthew: File issues: -// -// - unhelpful error message around variable shadowing (search for XXX below) -// - -// Thunks are not primitive in AS, -// ..but we can encode them as objects with a force method: -type Thk = {force:() -> T}; - -// A "Stream Head" ("Sh") is the head of the stream, which _always_ -// contains a value "today"; Its "tail" is a thunk that produces the -// next stream head ("tomorrow"), or `null`. -type Sh = (T, ?Thk>); - -// "Optional Stream Head" (Osh) is the optional head of the stream. -// This type is related to Sh, but is not equivalent. -type Osh = ?(T, Thk>); - -// type Stream = -// ??? Sh or Osh -// Q: Which is more more "conventional?" -// - -// stream map; trivially tail recursive. lazy. -func map(l : Osh, f:T -> S) : Osh = { - func rec(l : Osh) : Osh { - switch l { - case null { null }; - case (?(h,t)) { - let s = new{force():Osh{ rec(t.force()) }}; - ?(f(h),s) - }; - } - }; - rec(l) -}; - -// stream merge (aka "collate"); trivially tail recursive. lazy. -func merge(s1 : Osh, s2 : Osh, f:(T,T) -> Bool) : Osh = { - func rec(s1 : Osh, s2 : Osh) : Osh { - switch (s1, s2) { - case (null, _) { s2 }; - case (_, null) { s1 }; - case (?(h1,t1), ?(h2,t2)) { - if (f(h1,h2)) { - // case: h1 is "today", h2 is "later"... - let s = new{force():Osh{ rec(t1.force(), s2) }}; - ?(h1,s) - } else { - // case: h2 is "today", h2 is "later"... - let s = new{force():Osh{ rec(s1, t2.force()) }}; - ?(h2,s) - } - } - } - }; - rec(s1, s2) -}; - -// stream map-and-filter; tail recursive. -// acts eagerly when the predicate fails, -// and lazily when it succeeds. -func mapfilter(l : Osh, f:T -> ?S) : Osh = { - func rec(s : Osh) : Osh { - switch s { - case null { null }; - case (?(h,t)) { - switch (f(h)) { - case null { rec(t.force()) }; - case (?h_){ - // XXX -- When we shadow `t` we get a strange/wrong type error: - // - // type error, expression of type - // Osh = ?(S/3, Thk>) - // cannot produce expected type - // ?(T/28, Thk>) - // - // let t = new{force():Osh{ rec(t.force()) }}; - // ?(h_,t) - let s = new{force():Osh{ rec(t.force()) }}; - ?(h_,s) - }; - } - }; - } - }; - rec(l) -} diff --git a/stdlib/nonCriticalPath/thunk.as b/stdlib/nonCriticalPath/thunk.as deleted file mode 100644 index c13612b7b01..00000000000 --- a/stdlib/nonCriticalPath/thunk.as +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Thunks, a la functional programming, in ActorScript. - */ - -// Thunks are not primitive in AS, -// ..but we can encode them as objects with a force method: -type Thk = {force:() -> T}; - -// lift a value into a "value-producing thunk" -func lift(a:T) : Thk = - new { force() : T { a } }; - -// apply a function to a thunk's value -func app(f:T->S, x:Thk) : Thk { - new { force() : S { f(x.force()) } } -}; - -// pair two thunks' values -func pair(x:Thk, y:Thk) : Thk<(T,S)> { - new { force() : ((T,S)) { (x.force(), y.force()) } } -}; - -// project first from a pair-valued thunk -func fst(x:Thk<(T,S)>) : Thk { - new { force() : T { x.force().0 } } -}; - -// project second from a pair-valued thunk -func snd(x:Thk<(T,S)>) : Thk { - new { force() : S { x.force().1 } } -}; diff --git a/stdlib/setDb.as b/stdlib/setDb.as deleted file mode 100644 index 85d2d62cd4c..00000000000 --- a/stdlib/setDb.as +++ /dev/null @@ -1,116 +0,0 @@ -/** - - Debugging wrapper around `Set` module - ======================================== - - */ - -let Set = import "set.as"; -let Hash = import "hash.as"; -let Trie = import "trie.as"; -let List = import "list.as"; - -type Set = Set.Set; -type BitList = Hash.BitList; -type Hash = Hash.BitVec; -type Key = Trie.Key; - - func setDbPrint(s:Set) { - func rec(s:Set, ind:Nat, bits:BitList) { - func indPrint(i:Nat) { - if (i == 0) { } else { print "| "; indPrint(i-1) } - }; - switch s { - case null { - //indPrint(ind); - //bitsPrintRev(bits); - //print "(null)\n"; - }; - case (?n) { - switch (n.keyvals) { - case null { - //indPrint(ind); - //bitsPrintRev(bits); - //print "bin \n"; - rec(n.right, ind+1, ?(true, bits)); - rec(n.left, ind+1, ?(false,bits)); - //bitsPrintRev(bits); - //print ")\n" - }; - case (?keyvals) { - //indPrint(ind); - print "(leaf ["; - List.iter<(Key,())>( - ?keyvals, - func ((k:Key, ())) : () = { - print("hash("); - printInt(k.key); - print(")="); - Hash.BitVec.hashPrintRev(k.hash); - print("; "); - () - } - ); - print "])\n"; - }; - } - }; - } - }; - rec(s, 0, null); - }; - - //////////////////////////////////////////////////////////////////////////////// - - func natEq(n:Nat,m:Nat):Bool{ n == m}; - - func insert(s:Set, x:Nat, xh:Hash):Set = { - print " setInsert("; - printInt x; - print ")"; - let r = Set.insert(s,x,xh,natEq); - print ";\n"; - setDbPrint(r); - r - }; - - func mem(s:Set, sname:Text, x:Nat, xh:Hash):Bool = { - print " setMem("; - print sname; - print ", "; - printInt x; - print ")"; - let b = Set.mem(s,x,xh,natEq); - if b { print " = true" } else { print " = false" }; - print ";\n"; - b - }; - - func union(s1:Set, s1name:Text, s2:Set, s2name:Text):Set = { - print " setUnion("; - print s1name; - print ", "; - print s2name; - print ")"; - // also: test that merge agrees with disj: - let r1 = Set.union(s1, s2, natEq); - let r2 = Trie.disj(s1, s2, natEq, func (_:?(),_:?()):(())=()); - assert(Trie.equalStructure(r1, r2, natEq, Set.unitEq)); - print ";\n"; - setDbPrint(r1); - print "=========\n"; - setDbPrint(r2); - r1 - }; - - func intersect(s1:Set, s1name:Text, s2:Set, s2name:Text):Set = { - print " setIntersect("; - print s1name; - print ", "; - print s2name; - print ")"; - let r = Set.intersect(s1, s2, natEq); - print ";\n"; - setDbPrint(r); - r - }; diff --git a/stdlib/setDbTest.as b/stdlib/setDbTest.as deleted file mode 100644 index 8f8d985c55a..00000000000 --- a/stdlib/setDbTest.as +++ /dev/null @@ -1,185 +0,0 @@ -/** - - Tests with debugging wrapper around `Set` module - =============================================== - - */ - -let Hash = (import "hash.as").BitVec; - -let Set = (import "set.as"); -type Set = Set.Set; - -let SetDb = (import "setDb.as"); - - let hash_0 = Hash.hashOfInt(0); - let hash_1 = Hash.hashOfInt(1); - let hash_2 = Hash.hashOfInt(2); - let hash_3 = Hash.hashOfInt(3); - let hash_4 = Hash.hashOfInt(4); - let hash_5 = Hash.hashOfInt(5); - let hash_6 = Hash.hashOfInt(6); - let hash_7 = Hash.hashOfInt(7); - let hash_8 = Hash.hashOfInt(8); - let hash_9 = Hash.hashOfInt(9); - - - print "inserting...\n"; - // Insert numbers [0..8] into the set, using their bits as their hashes: - let s0 : Set = Set.empty(); - assert(Set.card(s0) == 0); - - let s1 : Set = SetDb.insert(s0, 0, hash_0); - assert(Set.card(s1) == 1); - - let s2 : Set = SetDb.insert(s1, 1, hash_1); - assert(Set.card(s2) == 2); - - let s3 : Set = SetDb.insert(s2, 2, hash_2); - assert(Set.card(s3) == 3); - - let s4 : Set = SetDb.insert(s3, 3, hash_3); - assert(Set.card(s4) == 4); - - let s5 : Set = SetDb.insert(s4, 4, hash_4); - assert(Set.card(s5) == 5); - - let s6 : Set = SetDb.insert(s5, 5, hash_5); - assert(Set.card(s6) == 6); - - let s7 : Set = SetDb.insert(s6, 6, hash_6); - assert(Set.card(s7) == 7); - - let s8 : Set = SetDb.insert(s7, 7, hash_7); - assert(Set.card(s8) == 8); - - let s9 : Set = SetDb.insert(s8, 8, hash_8); - assert(Set.card(s9) == 9); - print "done.\n"; - - print "unioning...\n"; - let s1s2 : Set = SetDb.union(s1, "s1", s2, "s2"); - let s2s1 : Set = SetDb.union(s2, "s2", s1, "s1"); - let s3s2 : Set = SetDb.union(s3, "s3", s2, "s2"); - let s4s2 : Set = SetDb.union(s4, "s4", s2, "s2"); - let s1s5 : Set = SetDb.union(s1, "s1", s5, "s5"); - let s0s2 : Set = SetDb.union(s0, "s0", s2, "s2"); - print "done.\n"; - - print "intersecting...\n"; - let s3is6 : Set = SetDb.intersect(s3, "s3", s6, "s6"); - let s2is1 : Set = SetDb.intersect(s2, "s2", s1, "s1"); - print "done.\n"; - - - print "testing membership...\n"; - - // Element 0: Test memberships of each set defined above for element 0 - assert( not( SetDb.mem(s0, "s0", 0, hash_0 ) )); - assert( SetDb.mem(s1, "s1", 0, hash_0 ) ); - assert( SetDb.mem(s2, "s2", 0, hash_0 ) ); - assert( SetDb.mem(s3, "s3", 0, hash_0 ) ); - assert( SetDb.mem(s4, "s4", 0, hash_0 ) ); - assert( SetDb.mem(s5, "s5", 0, hash_0 ) ); - assert( SetDb.mem(s6, "s6", 0, hash_0 ) ); - assert( SetDb.mem(s7, "s7", 0, hash_0 ) ); - assert( SetDb.mem(s8, "s8", 0, hash_0 ) ); - assert( SetDb.mem(s9, "s9", 0, hash_0 ) ); - - // Element 1: Test memberships of each set defined above for element 1 - assert( not(SetDb.mem(s0, "s0", 1, hash_1 )) ); - assert( not(SetDb.mem(s1, "s1", 1, hash_1 )) ); - assert( SetDb.mem(s2, "s2", 1, hash_1 ) ); - assert( SetDb.mem(s3, "s3", 1, hash_1 ) ); - assert( SetDb.mem(s4, "s4", 1, hash_1 ) ); - assert( SetDb.mem(s5, "s5", 1, hash_1 ) ); - assert( SetDb.mem(s6, "s6", 1, hash_1 ) ); - assert( SetDb.mem(s7, "s7", 1, hash_1 ) ); - assert( SetDb.mem(s8, "s8", 1, hash_1 ) ); - assert( SetDb.mem(s9, "s9", 1, hash_1 ) ); - - // Element 2: Test memberships of each set defined above for element 2 - assert( not(SetDb.mem(s0, "s0", 2, hash_2 )) ); - assert( not(SetDb.mem(s1, "s1", 2, hash_2 )) ); - assert( not(SetDb.mem(s2, "s2", 2, hash_2 )) ); - assert( SetDb.mem(s3, "s3", 2, hash_2 ) ); - assert( SetDb.mem(s4, "s4", 2, hash_2 ) ); - assert( SetDb.mem(s5, "s5", 2, hash_2 ) ); - assert( SetDb.mem(s6, "s6", 2, hash_2 ) ); - assert( SetDb.mem(s7, "s7", 2, hash_2 ) ); - assert( SetDb.mem(s8, "s8", 2, hash_2 ) ); - assert( SetDb.mem(s9, "s9", 2, hash_2 ) ); - - // Element 3: Test memberships of each set defined above for element 3 - assert( not(SetDb.mem(s0, "s0", 3, hash_3 )) ); - assert( not(SetDb.mem(s1, "s1", 3, hash_3 )) ); - assert( not(SetDb.mem(s2, "s2", 3, hash_3 )) ); - assert( not(SetDb.mem(s3, "s3", 3, hash_3 )) ); - assert( SetDb.mem(s4, "s4", 3, hash_3 ) ); - assert( SetDb.mem(s5, "s5", 3, hash_3 ) ); - assert( SetDb.mem(s6, "s6", 3, hash_3 ) ); - assert( SetDb.mem(s7, "s7", 3, hash_3 ) ); - assert( SetDb.mem(s8, "s8", 3, hash_3 ) ); - assert( SetDb.mem(s9, "s9", 3, hash_3 ) ); - - // Element 4: Test memberships of each set defined above for element 4 - assert( not(SetDb.mem(s0, "s0", 4, hash_4 )) ); - assert( not(SetDb.mem(s1, "s1", 4, hash_4 )) ); - assert( not(SetDb.mem(s2, "s2", 4, hash_4 )) ); - assert( not(SetDb.mem(s3, "s3", 4, hash_4 )) ); - assert( not(SetDb.mem(s4, "s4", 4, hash_4 )) ); - assert( SetDb.mem(s5, "s5", 4, hash_4 ) ); - assert( SetDb.mem(s6, "s6", 4, hash_4 ) ); - assert( SetDb.mem(s7, "s7", 4, hash_4 ) ); - assert( SetDb.mem(s8, "s8", 4, hash_4 ) ); - assert( SetDb.mem(s9, "s9", 4, hash_4 ) ); - - // Element 5: Test memberships of each set defined above for element 5 - assert( not(SetDb.mem(s0, "s0", 5, hash_5 )) ); - assert( not(SetDb.mem(s1, "s1", 5, hash_5 )) ); - assert( not(SetDb.mem(s2, "s2", 5, hash_5 )) ); - assert( not(SetDb.mem(s3, "s3", 5, hash_5 )) ); - assert( not(SetDb.mem(s4, "s4", 5, hash_5 )) ); - assert( not(SetDb.mem(s5, "s5", 5, hash_5 )) ); - assert( SetDb.mem(s6, "s6", 5, hash_5 ) ); - assert( SetDb.mem(s7, "s7", 5, hash_5 ) ); - assert( SetDb.mem(s8, "s8", 5, hash_5 ) ); - assert( SetDb.mem(s9, "s9", 5, hash_5 ) ); - - // Element 6: Test memberships of each set defined above for element 6 - assert( not(SetDb.mem(s0, "s0", 6, hash_6 )) ); - assert( not(SetDb.mem(s1, "s1", 6, hash_6 )) ); - assert( not(SetDb.mem(s2, "s2", 6, hash_6 )) ); - assert( not(SetDb.mem(s3, "s3", 6, hash_6 )) ); - assert( not(SetDb.mem(s4, "s4", 6, hash_6 )) ); - assert( not(SetDb.mem(s5, "s5", 6, hash_6 )) ); - assert( not(SetDb.mem(s6, "s6", 6, hash_6 )) ); - assert( SetDb.mem(s7, "s7", 6, hash_6 ) ); - assert( SetDb.mem(s8, "s8", 6, hash_6 ) ); - assert( SetDb.mem(s9, "s9", 6, hash_6 ) ); - - // Element 7: Test memberships of each set defined above for element 7 - assert( not(SetDb.mem(s0, "s0", 7, hash_7 )) ); - assert( not(SetDb.mem(s1, "s1", 7, hash_7 )) ); - assert( not(SetDb.mem(s2, "s2", 7, hash_7 )) ); - assert( not(SetDb.mem(s3, "s3", 7, hash_7 )) ); - assert( not(SetDb.mem(s4, "s4", 7, hash_7 )) ); - assert( not(SetDb.mem(s5, "s5", 7, hash_7 )) ); - assert( not(SetDb.mem(s6, "s6", 7, hash_7 )) ); - assert( not(SetDb.mem(s7, "s7", 7, hash_7 )) ); - assert( SetDb.mem(s8, "s8", 7, hash_7 ) ); - assert( SetDb.mem(s9, "s9", 7, hash_7 ) ); - - // Element 8: Test memberships of each set defined above for element 8 - assert( not(SetDb.mem(s0, "s0", 8, hash_8 )) ); - assert( not(SetDb.mem(s1, "s1", 8, hash_8 )) ); - assert( not(SetDb.mem(s2, "s2", 8, hash_8 )) ); - assert( not(SetDb.mem(s3, "s3", 8, hash_8 )) ); - assert( not(SetDb.mem(s4, "s4", 8, hash_8 )) ); - assert( not(SetDb.mem(s6, "s6", 8, hash_8 )) ); - assert( not(SetDb.mem(s6, "s6", 8, hash_8 )) ); - assert( not(SetDb.mem(s7, "s7", 8, hash_8 )) ); - assert( not(SetDb.mem(s8, "s8", 8, hash_8 )) ); - assert( SetDb.mem(s9, "s9", 8, hash_8 ) ); - - print "done.\n"; diff --git a/stdlib/markdown-of-actorscript.py b/stdlib/tools/markdown-of-actorscript.py similarity index 100% rename from stdlib/markdown-of-actorscript.py rename to stdlib/tools/markdown-of-actorscript.py diff --git a/stdlib/markdown-of-markdown.py b/stdlib/tools/markdown-of-markdown.py similarity index 100% rename from stdlib/markdown-of-markdown.py rename to stdlib/tools/markdown-of-markdown.py diff --git a/stdlib/time.c b/stdlib/tools/stopwatch.c similarity index 90% rename from stdlib/time.c rename to stdlib/tools/stopwatch.c index 5bb84ddb647..07631c16a74 100644 --- a/stdlib/time.c +++ b/stdlib/tools/stopwatch.c @@ -14,7 +14,7 @@ int main(int argc, char** args) { gettimeofday(&tv_0,0); // - // first argument is the command to run and time: + // first argument is the shell command to run and whose running time we measure: // system(args[1]); gettimeofday(&tv_1,0); From 583dade3712f20b4b2528f4a9d24af57a6825715 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Fri, 21 Jun 2019 10:11:28 -0600 Subject: [PATCH 0200/1176] didnt produce build product; fix typo in nix file; try again --- default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/default.nix b/default.nix index a24c631c840..7b0e188fcf0 100644 --- a/default.nix +++ b/default.nix @@ -287,7 +287,7 @@ rec { ''; installPhase = '' mkdir -p $out - cp -r $src $out/ + cp -r $src $out/stdlib mkdir -p $out/nix-support echo "report stdlib $out/stdlib" >> $out/nix-support/hydra-build-products ''; From 0d7439f98e0c2768ae9a1cb7f418df6f1f0559a7 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Fri, 21 Jun 2019 10:23:55 -0600 Subject: [PATCH 0201/1176] build products cant be directories? using tar instead --- default.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/default.nix b/default.nix index 7b0e188fcf0..847cb10c7fd 100644 --- a/default.nix +++ b/default.nix @@ -287,9 +287,9 @@ rec { ''; installPhase = '' mkdir -p $out - cp -r $src $out/stdlib + tar -rf $out/stdlib.tar $src mkdir -p $out/nix-support - echo "report stdlib $out/stdlib" >> $out/nix-support/hydra-build-products + echo "report stdlib $out/stdlib.tar" >> $out/nix-support/hydra-build-products ''; forceShare = ["man"]; }; From 587cc6cb0673c3e15e321b7f066a48da1c30d85f Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Fri, 21 Jun 2019 13:25:55 -0700 Subject: [PATCH 0202/1176] proper scoping for imports --- src/idllib/pipeline.ml | 93 ++++++++++++++++++----------------- src/idllib/resolve_import.ml | 12 ++--- src/idllib/resolve_import.mli | 4 +- src/lang_utils/diag.ml | 4 ++ src/lang_utils/diag.mli | 1 + test/idl/import.did | 6 ++- test/idl/import1.did | 7 +++ test/idl/import2.did | 4 ++ test/idl/import3.did | 2 + test/idl/import4.did | 4 ++ test/idl/import5.did | 1 + test/idl/missing_import.did | 2 +- test/idl/ok/import.js.ok | 23 +++------ test/idl/ok/import1.js.ok | 17 +++++++ test/idl/ok/import2.tc.ok | 1 + test/idl/ok/import3.js.ok | 16 ++++++ test/idl/ok/import4.tc.ok | 1 + test/idl/ok/import5.tc.ok | 1 + 18 files changed, 126 insertions(+), 73 deletions(-) create mode 100644 test/idl/import1.did create mode 100644 test/idl/import2.did create mode 100644 test/idl/import3.did create mode 100644 test/idl/import4.did create mode 100644 test/idl/import5.did create mode 100644 test/idl/ok/import1.js.ok create mode 100644 test/idl/ok/import2.tc.ok create mode 100644 test/idl/ok/import3.js.ok create mode 100644 test/idl/ok/import4.tc.ok create mode 100644 test/idl/ok/import5.tc.ok diff --git a/src/idllib/pipeline.ml b/src/idllib/pipeline.ml index 75df9b50d45..6bdc9194e3f 100644 --- a/src/idllib/pipeline.ml +++ b/src/idllib/pipeline.ml @@ -6,7 +6,7 @@ let phase heading name = if !Flags.verbose then printf "-- %s %s:\n%!" heading name let error at cat text = - Error { Diag.sev = Diag.Error; at; cat; text } + Error [{ Diag.sev = Diag.Error; at; cat; text }] let print_stat_ve = Typing.Env.iter (fun x t -> @@ -48,14 +48,7 @@ let parse_file filename : parse_result = close_in ic; match result with | Ok prog -> Diag.return (prog, filename) - | Error e -> Error [e] - -(* import file name resolution *) - -type resolve_result = (Syntax.prog * Resolve_import.S.t) Diag.result - -let resolve_prog (prog, base) : resolve_result = - Diag.map (fun libraries -> (prog, libraries)) (Resolve_import.resolve prog base) + | Error e -> Error e (* Type checking *) @@ -73,54 +66,62 @@ let check_prog senv prog type load_result = (Syntax.prog * Typing.scope) Diag.result -let chase_imports senv0 imports : Typing.scope Diag.result = - let open Resolve_import.S in - let pending = ref empty in - let senv = ref senv0 in - let libraries = ref [] in - let rec go f = - if Typing.Env.mem f !senv then +let initial_stat_env = Typing.empty_scope + +module LibEnv = Env.Make(String) + +let merge_env imports init_env lib_env = + let disjoint_union env1 env2 : Typing.typ_env Diag.result = + try Diag.return (Typing.Env.union (fun k v1 v2 -> + if v1 = v2 then Some v1 else raise (Typing.Env.Clash k) + ) env1 env2) + with Typing.Env.Clash k -> + error Source.no_region "import" (sprintf "conflict type definition for %s" k) in + let env_list = List.map (fun import -> LibEnv.find import lib_env) imports in + Diag.fold disjoint_union init_env env_list + +let chase_imports senv imports = + let module S = Resolve_import.Set in + let pending = ref S.empty in + let lib_env = ref LibEnv.empty in + let rec go file = + if S.mem file !pending then + error Source.no_region "import" (sprintf "file %s must not depend on itself" file) + else if LibEnv.mem file !lib_env then Diag.return () - else if mem f !pending then - Error [{ - Diag.sev = Diag.Error; at = Source.no_region; cat = "import"; - text = sprintf "file %s must not depend on itself" f - }] else begin - pending := add f !pending; - Diag.bind (parse_file f) (fun (prog, base) -> - Diag.bind (Resolve_import.resolve prog base) (fun more_imports -> - Diag.bind (go_set more_imports) (fun () -> - Diag.bind (check_prog !senv prog) (fun scope -> - libraries := (f, prog) :: !libraries; - senv := Typing.Env.adjoin !senv scope; - pending := remove f !pending; - Diag.return () - )))) + pending := S.add file !pending; + Diag.bind (parse_file file) (fun (prog, base) -> + Diag.bind (Resolve_import.resolve prog base) (fun imports -> + Diag.bind (go_set imports) (fun () -> + Diag.bind (merge_env imports senv !lib_env) (fun base_env -> + Diag.bind (check_prog base_env prog) (fun scope -> + lib_env := LibEnv.add file scope !lib_env; + pending := S.remove file !pending; + Diag.return () + ))))) end - and go_set todo = Diag.traverse_ go (elements todo) - in Diag.map (fun () -> !senv) (go_set imports) - -let load_prog parse senv : load_result = - Diag.bind parse (fun parsed -> - Diag.bind (resolve_prog parsed) (fun (prog, libraries) -> - Diag.bind (chase_imports senv libraries) (fun senv' -> - Diag.bind (check_prog senv' prog) (fun senv'' -> - Diag.return (prog, senv'') - )))) - + and go_set todo = Diag.traverse_ go todo + in Diag.map (fun () -> !lib_env) (go_set imports) + +let load_prog parse senv = + Diag.bind parse (fun (prog, base) -> + Diag.bind (Resolve_import.resolve prog base) (fun imports -> + Diag.bind (chase_imports senv imports) (fun lib_env -> + Diag.bind (merge_env imports senv lib_env) (fun base_env -> + Diag.bind (check_prog base_env prog) (fun scope -> + Diag.return (prog, scope)))))) + (* Only type checking *) -let initial_stat_env = Typing.empty_scope - -let check_file file : load_result = load_prog (parse_file file) initial_stat_env +let check_file file : load_result = load_prog (parse_file file) initial_stat_env (* JS Compilation *) type compile_result = Buffer.t Diag.result let compile_js_file file : compile_result = - Diag.bind (load_prog (parse_file file) initial_stat_env) + Diag.bind (check_file file) (fun (prog, senv) -> phase "JS Compiling" file; Diag.return (Compile_js.compile senv prog)) diff --git a/src/idllib/resolve_import.ml b/src/idllib/resolve_import.ml index 44d31197e25..f7c77b9690f 100644 --- a/src/idllib/resolve_import.ml +++ b/src/idllib/resolve_import.ml @@ -1,11 +1,11 @@ type filepath = string -module S = Set.Make(String) +module Set = Set.Make(String) type env = { msgs : Diag.msg_store; base : filepath; - imported : S.t ref; + imported : Set.t ref; } open Syntax @@ -21,7 +21,7 @@ and dec env d = match d.it with if Sys.file_exists f && not (Sys.is_directory f) then begin fp := f; - env.imported := S.add f !(env.imported) + env.imported := Set.add f !(env.imported) end else let open Diag in add_msg env.msgs { @@ -33,12 +33,12 @@ and dec env d = match d.it with let prog env p = decs env p.it.decs -let resolve : Syntax.prog -> filepath -> S.t Diag.result = fun p base -> +let resolve : Syntax.prog -> filepath -> filepath list Diag.result = fun p base -> Diag.with_message_store (fun msgs -> let base = if Sys.is_directory base then base else Filename.dirname base in - let env = { msgs; base; imported = ref S.empty } in + let env = { msgs; base; imported = ref Set.empty } in prog env p; - Some !(env.imported) + Some (Set.elements !(env.imported)) ) diff --git a/src/idllib/resolve_import.mli b/src/idllib/resolve_import.mli index bd3e4fd1b29..c3136391536 100644 --- a/src/idllib/resolve_import.mli +++ b/src/idllib/resolve_import.mli @@ -1,3 +1,3 @@ -module S : Set.S with type elt = String.t +module Set : Set.S with type elt = String.t -val resolve : Syntax.prog -> string -> S.t Diag.result +val resolve : Syntax.prog -> string -> string list Diag.result diff --git a/src/lang_utils/diag.ml b/src/lang_utils/diag.ml index b3bf0e825c9..d4dd3cd1f4c 100644 --- a/src/lang_utils/diag.ml +++ b/src/lang_utils/diag.ml @@ -29,6 +29,10 @@ let rec traverse_ : ('a -> unit result) -> 'a list -> unit result = fun f -> fun | [] -> return () | x :: xs -> bind (f x) (fun () -> traverse_ f xs) +let rec fold : ('a -> 'b -> 'a result) -> 'a -> 'b list -> 'a result = fun f acc -> function + | [] -> return acc + | x :: xs -> bind (f acc x) (fun y -> fold f y xs) + type msg_store = messages ref let add_msg s m = s := m :: !s let add_msgs s ms = s := List.rev ms @ !s diff --git a/src/lang_utils/diag.mli b/src/lang_utils/diag.mli index 4455a9f4981..b76c34f1495 100644 --- a/src/lang_utils/diag.mli +++ b/src/lang_utils/diag.mli @@ -29,6 +29,7 @@ val bind : 'a result -> ('a -> 'b result) -> 'b result val map : ('a -> 'b) -> 'a result -> 'b result val traverse: ('a -> 'b result) -> 'a list -> 'b list result val traverse_: ('a -> unit result) -> 'a list -> unit result +val fold: ('a -> 'b -> 'a result) -> 'a -> 'b list -> 'a result val flush_messages : 'a result -> 'a option val run : 'a result -> 'a (* Prints messages, and exits upon failure *) diff --git a/test/idl/import.did b/test/idl/import.did index 0d886d0532b..4a4d1a67ee9 100644 --- a/test/idl/import.did +++ b/test/idl/import.did @@ -1,7 +1,9 @@ +type list = vec nat; + import "px.did"; -import "recursion.did"; +import "import1.did"; service S { - f: (tree) -> (list, IdErr); + f: (t, t1, t2) -> (list, IdErr); getInventory: (producer_id: nat) -> (Inventory) pure; } diff --git a/test/idl/import1.did b/test/idl/import1.did new file mode 100644 index 00000000000..ddca85c742b --- /dev/null +++ b/test/idl/import1.did @@ -0,0 +1,7 @@ +type t = blob; + +import "px.did"; + +type t1 = t; +type t2 = UserId; + diff --git a/test/idl/import2.did b/test/idl/import2.did new file mode 100644 index 00000000000..6f611598081 --- /dev/null +++ b/test/idl/import2.did @@ -0,0 +1,4 @@ +import "import1.did"; +import "recursion.did"; +import "px.did"; + diff --git a/test/idl/import3.did b/test/idl/import3.did new file mode 100644 index 00000000000..239331b0f20 --- /dev/null +++ b/test/idl/import3.did @@ -0,0 +1,2 @@ +import "recursion.did"; +service S : s diff --git a/test/idl/import4.did b/test/idl/import4.did new file mode 100644 index 00000000000..0b42b4e21cf --- /dev/null +++ b/test/idl/import4.did @@ -0,0 +1,4 @@ +type A = nat; +import "import1.did"; +import "import5.did"; +type B = nat; diff --git a/test/idl/import5.did b/test/idl/import5.did new file mode 100644 index 00000000000..81437f2f269 --- /dev/null +++ b/test/idl/import5.did @@ -0,0 +1 @@ +type C = vec B; diff --git a/test/idl/missing_import.did b/test/idl/missing_import.did index 35df983c5a4..3db79dbfb7b 100644 --- a/test/idl/missing_import.did +++ b/test/idl/missing_import.did @@ -1,3 +1,3 @@ import "ok"; -import "../Makefile"; +// import "../Makefile"; diff --git a/test/idl/ok/import.js.ok b/test/idl/ok/import.js.ok index 8787e42fadb..6490c97ee5a 100644 --- a/test/idl/ok/import.js.ok +++ b/test/idl/ok/import.js.ok @@ -1,5 +1,3 @@ -const A = B -const B = IDL.Opt(A) const EntId = IDL.Obj({'region': RegionId, 'user': UserId, 'truckType': TruckTypeId}) const IdErr = IDL.Obj({'idErr': OpEntId}) @@ -13,20 +11,13 @@ const UserInfo = IDL.Obj({'id': UserId, 'region': RegionId, 'user_name': IDL.Text, 'public_key': IDL.Text, 'description': IDL.Text, 'produceId': IDL.Opt(ProducerId)}) -const list = IDL.Opt(node) -const node = IDL.Obj({'head': IDL.Nat, 'tail': list}) -const s = new IDL.ActorInterface({'f': t}) -const stream = - IDL.Opt( - IDL.Obj({'head': IDL.Nat, - 'next': IDL.message(IDL.Obj({}), IDL.Obj({'0': stream}))})) - -const t = IDL.message(IDL.Obj({'server': s}), IDL.Obj({})) -const tree = - IDL.Variant({ - 'branch': IDL.Obj({'right': tree, 'val': IDL.Int, 'left': tree}), - 'leaf': IDL.Int}) +const list = IDL.Arr(IDL.Nat) +const t = IDL.Arr(IDL.Nat8) +const t1 = t +const t2 = UserId const S = new IDL.ActorInterface({ - 'f': IDL.message(IDL.Obj({'0': tree}), IDL.Obj({'0': list, '1': IdErr})), + 'f': + IDL.message(IDL.Obj({'0': t, '1': t1, '2': t2}), + IDL.Obj({'0': list, '1': IdErr})), 'getInventory': IDL.message(IDL.Obj({'producer_id': IDL.Nat}), IDL.Obj({'0': Inventory}))}) diff --git a/test/idl/ok/import1.js.ok b/test/idl/ok/import1.js.ok new file mode 100644 index 00000000000..de653ee8255 --- /dev/null +++ b/test/idl/ok/import1.js.ok @@ -0,0 +1,17 @@ +const EntId = + IDL.Obj({'region': RegionId, 'user': UserId, 'truckType': TruckTypeId}) +const IdErr = IDL.Obj({'idErr': OpEntId}) +const Inventory = IDL.Obj({'quantity': IDL.Nat, 'produce_id': IDL.Nat}) +const OpEntId = IDL.Opt(EntId) +const ProducerId = IDL.Nat +const RegionId = IDL.Nat +const TruckTypeId = IDL.Nat +const UserId = IDL.Nat +const UserInfo = + IDL.Obj({'id': UserId, 'region': RegionId, 'user_name': IDL.Text, + 'public_key': IDL.Text, 'description': IDL.Text, + 'produceId': IDL.Opt(ProducerId)}) +const t = IDL.Arr(IDL.Nat8) +const t1 = t +const t2 = UserId + diff --git a/test/idl/ok/import2.tc.ok b/test/idl/ok/import2.tc.ok new file mode 100644 index 00000000000..b8e87f3fb02 --- /dev/null +++ b/test/idl/ok/import2.tc.ok @@ -0,0 +1 @@ +(unknown location): import error, conflict type definition for t diff --git a/test/idl/ok/import3.js.ok b/test/idl/ok/import3.js.ok new file mode 100644 index 00000000000..50b4ea16d96 --- /dev/null +++ b/test/idl/ok/import3.js.ok @@ -0,0 +1,16 @@ +const A = B +const B = IDL.Opt(A) +const list = IDL.Opt(node) +const node = IDL.Obj({'head': IDL.Nat, 'tail': list}) +const s = new IDL.ActorInterface({'f': t}) +const stream = + IDL.Opt( + IDL.Obj({'head': IDL.Nat, + 'next': IDL.message(IDL.Obj({}), IDL.Obj({'0': stream}))})) + +const t = IDL.message(IDL.Obj({'server': s}), IDL.Obj({})) +const tree = + IDL.Variant({ + 'branch': IDL.Obj({'right': tree, 'val': IDL.Int, 'left': tree}), + 'leaf': IDL.Int}) +const S = s diff --git a/test/idl/ok/import4.tc.ok b/test/idl/ok/import4.tc.ok new file mode 100644 index 00000000000..3545ecebac9 --- /dev/null +++ b/test/idl/ok/import4.tc.ok @@ -0,0 +1 @@ +import5.did:1.14-1.15: type error, unbound type identifier B diff --git a/test/idl/ok/import5.tc.ok b/test/idl/ok/import5.tc.ok new file mode 100644 index 00000000000..3545ecebac9 --- /dev/null +++ b/test/idl/ok/import5.tc.ok @@ -0,0 +1 @@ +import5.did:1.14-1.15: type error, unbound type identifier B From c1d836d29fd57088eaa6993b048f927bda6fb489 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Mon, 24 Jun 2019 08:41:09 -0600 Subject: [PATCH 0203/1176] package stdlib doc as tar file for download by sdk's dfx tool --- default.nix | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/default.nix b/default.nix index 847cb10c7fd..9f386f0890d 100644 --- a/default.nix +++ b/default.nix @@ -276,7 +276,6 @@ rec { ''; }; - stdlib = stdenv.mkDerivation { name = "stdlib"; src = subpath ./stdlib; @@ -294,8 +293,8 @@ rec { forceShare = ["man"]; }; - stdlib-reference = stdenv.mkDerivation { - name = "stdlib-reference"; + stdlib-doc-live = stdenv.mkDerivation { + name = "stdlib-doc-live"; src = subpath ./stdlib; buildInputs = with nixpkgs; [ pandoc bash python ]; @@ -312,6 +311,24 @@ rec { forceShare = ["man"]; }; + stdlib-doc = stdenv.mkDerivation { + name = "stdlib-doc"; + src = subpath ./stdlib; + buildInputs = with nixpkgs; + [ pandoc bash python ]; + buildPhase = '' + patchShebangs . + make alldoc + ''; + installPhase = '' + mkdir -p $out + tar -rf $out/stdlib-doc.tar doc + mkdir -p $out/nix-support + echo "report stdlib $out/stdlib.tar" >> $out/nix-support/hydra-build-products + ''; + forceShare = ["man"]; + }; + produce-exchange = stdenv.mkDerivation { name = "produce-exchange"; src = subpath ./stdlib; @@ -341,7 +358,9 @@ rec { tests samples rts - stdlib-reference + stdlib + stdlib-doc + stdlib-doc-live produce-exchange users-guide ]; From 02418008af408f84cf13e9991fa85c73375e17f5 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Mon, 24 Jun 2019 12:39:32 -0700 Subject: [PATCH 0204/1176] remove file check in resolve_import, and diamond import tests --- src/idllib/pipeline.ml | 10 ++++++++-- src/idllib/resolve_import.ml | 14 ++------------ test/idl/diamond.did | 6 ++++++ test/idl/diamond2.did | 3 +++ test/idl/diamond3.did | 2 ++ test/idl/diamond4.did | 1 + test/idl/ok/diamond.js.ok | 6 ++++++ test/idl/ok/diamond2.js.ok | 3 +++ test/idl/ok/diamond3.js.ok | 3 +++ test/idl/ok/diamond4.js.ok | 2 ++ test/idl/ok/missing_import.tc.ok | 2 +- 11 files changed, 37 insertions(+), 15 deletions(-) create mode 100644 test/idl/diamond.did create mode 100644 test/idl/diamond2.did create mode 100644 test/idl/diamond3.did create mode 100644 test/idl/diamond4.did create mode 100644 test/idl/ok/diamond.js.ok create mode 100644 test/idl/ok/diamond2.js.ok create mode 100644 test/idl/ok/diamond3.js.ok create mode 100644 test/idl/ok/diamond4.js.ok diff --git a/src/idllib/pipeline.ml b/src/idllib/pipeline.ml index 6bdc9194e3f..ddc0c02747e 100644 --- a/src/idllib/pipeline.ml +++ b/src/idllib/pipeline.ml @@ -50,6 +50,11 @@ let parse_file filename : parse_result = | Ok prog -> Diag.return (prog, filename) | Error e -> Error e +let parse_file filename : parse_result = + try parse_file filename + with Sys_error s -> + error Source.no_region "file" (sprintf "cannot open \"%s\"" filename) + (* Type checking *) let check_prog senv prog @@ -66,13 +71,12 @@ let check_prog senv prog type load_result = (Syntax.prog * Typing.scope) Diag.result -let initial_stat_env = Typing.empty_scope - module LibEnv = Env.Make(String) let merge_env imports init_env lib_env = let disjoint_union env1 env2 : Typing.typ_env Diag.result = try Diag.return (Typing.Env.union (fun k v1 v2 -> + (* TODO Add proper type equivalence check for env *) if v1 = v2 then Some v1 else raise (Typing.Env.Clash k) ) env1 env2) with Typing.Env.Clash k -> @@ -114,6 +118,8 @@ let load_prog parse senv = (* Only type checking *) +let initial_stat_env = Typing.empty_scope + let check_file file : load_result = load_prog (parse_file file) initial_stat_env (* JS Compilation *) diff --git a/src/idllib/resolve_import.ml b/src/idllib/resolve_import.ml index f7c77b9690f..5325a099183 100644 --- a/src/idllib/resolve_import.ml +++ b/src/idllib/resolve_import.ml @@ -18,18 +18,8 @@ and dec env d = match d.it with let f = if Filename.is_relative f then Filename.concat env.base f else f in - if Sys.file_exists f && not (Sys.is_directory f) - then begin - fp := f; - env.imported := Set.add f !(env.imported) - end else - let open Diag in - add_msg env.msgs { - sev = Error; - at = d.at; - cat = "import"; - text = Printf.sprintf "File \"%s\" does not exist" f - } + fp := f; + env.imported := Set.add f !(env.imported) let prog env p = decs env p.it.decs diff --git a/test/idl/diamond.did b/test/idl/diamond.did new file mode 100644 index 00000000000..85dd9572d3b --- /dev/null +++ b/test/idl/diamond.did @@ -0,0 +1,6 @@ +type t1 = record { t2; t3; t }; +import "diamond2.did"; +import "diamond3.did"; +service S { + f : (t, t2, t3) -> (t1); +} diff --git a/test/idl/diamond2.did b/test/idl/diamond2.did new file mode 100644 index 00000000000..3e013db3a4f --- /dev/null +++ b/test/idl/diamond2.did @@ -0,0 +1,3 @@ +import "diamond4.did"; +type t2 = vec t; + diff --git a/test/idl/diamond3.did b/test/idl/diamond3.did new file mode 100644 index 00000000000..e86ab6e5f72 --- /dev/null +++ b/test/idl/diamond3.did @@ -0,0 +1,2 @@ +import "diamond4.did"; +type t3 = opt t; diff --git a/test/idl/diamond4.did b/test/idl/diamond4.did new file mode 100644 index 00000000000..fabad72761b --- /dev/null +++ b/test/idl/diamond4.did @@ -0,0 +1 @@ +type t = nat; diff --git a/test/idl/ok/diamond.js.ok b/test/idl/ok/diamond.js.ok new file mode 100644 index 00000000000..aa579ab3683 --- /dev/null +++ b/test/idl/ok/diamond.js.ok @@ -0,0 +1,6 @@ +const t = IDL.Nat +const t1 = IDL.Obj({'0': t2, '1': t3, '2': t}) +const t2 = IDL.Arr(t) +const t3 = IDL.Opt(t) +const S = new IDL.ActorInterface({ + 'f': IDL.message(IDL.Obj({'0': t, '1': t2, '2': t3}), IDL.Obj({'0': t1}))}) diff --git a/test/idl/ok/diamond2.js.ok b/test/idl/ok/diamond2.js.ok new file mode 100644 index 00000000000..8d97648bdbe --- /dev/null +++ b/test/idl/ok/diamond2.js.ok @@ -0,0 +1,3 @@ +const t = IDL.Nat +const t2 = IDL.Arr(t) + diff --git a/test/idl/ok/diamond3.js.ok b/test/idl/ok/diamond3.js.ok new file mode 100644 index 00000000000..030c50f337a --- /dev/null +++ b/test/idl/ok/diamond3.js.ok @@ -0,0 +1,3 @@ +const t = IDL.Nat +const t3 = IDL.Opt(t) + diff --git a/test/idl/ok/diamond4.js.ok b/test/idl/ok/diamond4.js.ok new file mode 100644 index 00000000000..681129d2a07 --- /dev/null +++ b/test/idl/ok/diamond4.js.ok @@ -0,0 +1,2 @@ +const t = IDL.Nat + diff --git a/test/idl/ok/missing_import.tc.ok b/test/idl/ok/missing_import.tc.ok index 30f369fe40f..e6c0aaf58d4 100644 --- a/test/idl/ok/missing_import.tc.ok +++ b/test/idl/ok/missing_import.tc.ok @@ -1 +1 @@ -missing_import.did:1.1-1.12: import error, File "./ok" does not exist +(unknown location): file error, cannot open "./ok" From a8fe41d708395169cad317939c6db76097c8a0d5 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 25 Jun 2019 16:31:16 +0200 Subject: [PATCH 0205/1176] IDL: Fix type numbers (-22 was used twice) (#524) --- design/IDL.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/design/IDL.md b/design/IDL.md index 7244eedaf93..6573f036b5e 100644 --- a/design/IDL.md +++ b/design/IDL.md @@ -908,9 +908,9 @@ T(:) = leb128() I() T : -> i8* T(func (*) -> (*) *) = - sleb128(-21) T*(*) T*(*) T*(*) + sleb128(-22) T*(*) T*(*) T*(*) T(service {*}) = - sleb128(-22) T*(*) + sleb128(-23) T*(*) T : -> i8* T(:) = leb128(|utf8()|) i8*(utf8()) I() From 46f8e07c237ee3402a8cb9832ac1efed6e03547c Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Tue, 25 Jun 2019 10:07:36 -0700 Subject: [PATCH 0206/1176] add todo for imports --- src/idllib/parser.mly | 1 + 1 file changed, 1 insertion(+) diff --git a/src/idllib/parser.mly b/src/idllib/parser.mly index 5732cd4c740..a1ba1b23e64 100644 --- a/src/idllib/parser.mly +++ b/src/idllib/parser.mly @@ -155,6 +155,7 @@ actor_typ : def : | TYPE x=id EQ t=data_typ { TypD(x, t) @@ at $sloc } + (* TODO enforce all imports to go first in the type definitions *) | IMPORT file=TEXT { ImportD (file, ref "") @@ at $sloc } From 75bc40b7f5daa9560efbb229d687613b8d83862d Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 26 Jun 2019 12:38:08 +0200 Subject: [PATCH 0207/1176] Update design/Units.md Co-Authored-By: Andreas Rossberg --- design/Units.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/design/Units.md b/design/Units.md index 7961377d4b5..36b895bcfad 100644 --- a/design/Units.md +++ b/design/Units.md @@ -52,7 +52,7 @@ The syntax of a unit -- and therefore an AS source file -- is a sequence of *imp Imports are no longer allowed anywhere else. -The `` of the `import` statement is an URL. The precise interpretation is implementation dependant (see below in section Compilation). It at least supports local paths relative to the source file. URLs do _not_ include a file ending, such as `.as`, `.dll` or `.wasm`, to allow for different compilation schemes. +The `` of the `import` statement is a URL. The precise interpretation is implementation dependant (see below in section Compilation). It at least supports local paths relative to the source file. URLs do _not_ include a file ending, such as `.as`, `.dll` or `.wasm`, to allow for different compilation schemes. Each import binds the identifiers in its *import pattern*. If the pattern is a plain `` then the contents of the imported unit is reified as a module object bound to that id. If the pattern is a *destructuring* import pattern then the respective public fields of the unit are bound to the respective label identifiers. From 000ba907ebfa615a256fa1a319943979f782b86e Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 26 Jun 2019 12:43:02 +0200 Subject: [PATCH 0208/1176] Better wording --- design/Units.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/design/Units.md b/design/Units.md index 7961377d4b5..0549f30c8af 100644 --- a/design/Units.md +++ b/design/Units.md @@ -130,7 +130,7 @@ Consequently, every public field of a unit becomes a a Wasm exports. These are either Wasm functions, for public fields of function type, or Wasm globals, for all others. -No `as-interface` custom section may be present; the interface must be determined by the type alone. This allows true separate compliation. +The `as-interface` custom section must not be present; the interface must be determined by the type alone. This allows true separate compliation. It also implies that compiling arbitrary closures into exported Wasm functions may require eta-expanding the closure and storing its environment into an internal global. From 150804442fb3fa55cc4fc46d5a801fe25e766848 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 26 Jun 2019 12:43:49 +0200 Subject: [PATCH 0209/1176] Update design/Units.md Co-Authored-By: Andreas Rossberg --- design/Units.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/design/Units.md b/design/Units.md index 731a0b5d01a..f69a7b03476 100644 --- a/design/Units.md +++ b/design/Units.md @@ -111,7 +111,7 @@ This compilation scheme is suitable for the interpreter, and for early versions This compilation scheme expresses units as dynamically linkable Wasm modules (according to the [dynamic linking spec](https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md). -Imports are resolved to Wasm modules by appending `.wasm` to the impot path. +Imports are resolved to Wasm modules by appending `.wasm` to the import path. The exported module is mapped to Wasm exports (functions and globals) in an implementation-defined way that may vary between compiler versions. From 2806b5e87bec1fd5ba85c1f9ec92f1f549c071cc Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 26 Jun 2019 12:47:52 +0200 Subject: [PATCH 0210/1176] Update design/Units.md Co-Authored-By: Andreas Rossberg --- design/Units.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/design/Units.md b/design/Units.md index f69a7b03476..b3503f9be80 100644 --- a/design/Units.md +++ b/design/Units.md @@ -126,7 +126,7 @@ This extension to the former scheme explicitly uses _natural mechanisms_ in Wasm That enables the best possible integration and interoperation with the wider Wasm eco system and existing tools. (However, it does not automatically enable functional interoperability with other languages, since AS types typically have a representation that cannot directly be interpreted externally. For this, additional interop support would be needed, which is beyond the scope of this proposal.) -Consequently, every public field of a unit becomes a a Wasm exports. +Consequently, every public field of a unit becomes a Wasm exports. These are either Wasm functions, for public fields of function type, or Wasm globals, for all others. From 3ebe7c522a2aa69aefc752b6aff4e51c7da375d2 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 26 Jun 2019 12:49:18 +0200 Subject: [PATCH 0211/1176] Typo --- design/Units.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/design/Units.md b/design/Units.md index b3503f9be80..e542d59304f 100644 --- a/design/Units.md +++ b/design/Units.md @@ -130,7 +130,7 @@ Consequently, every public field of a unit becomes a Wasm exports. These are either Wasm functions, for public fields of function type, or Wasm globals, for all others. -The `as-interface` custom section must not be present; the interface must be determined by the type alone. This allows true separate compliation. +The `as-interface` custom section must not be present; the interface must be determined by the type alone. This allows true separate compilation. It also implies that compiling arbitrary closures into exported Wasm functions may require eta-expanding the closure and storing its environment into an internal global. From c8cc86bfd016b97da2d9da22c4410102be3a3ac0 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Wed, 26 Jun 2019 12:56:51 +0200 Subject: [PATCH 0212/1176] Fix issue #522 (#526) * fix invalid modulus * fix div and rem for good * simplify * test modulus in interpreter and compiler --- src/as_values/value.ml | 9 +++++++-- test/run/modulus.as | 13 +++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 test/run/modulus.as diff --git a/src/as_values/value.ml b/src/as_values/value.ml index 73a3144cba1..2559e19b662 100644 --- a/src/as_values/value.ml +++ b/src/as_values/value.ml @@ -161,10 +161,15 @@ struct let mul = mult_big_int let div a b = let q, m = quomod_big_int a b in - if sign_big_int q < 0 && sign_big_int m > 0 then succ_big_int q else q + if sign_big_int m * sign_big_int a >= 0 then q + else if sign_big_int q = 1 then pred_big_int q else succ_big_int q let rem a b = let q, m = quomod_big_int a b in - if sign_big_int q < 0 && sign_big_int m > 0 then sub_big_int m b else m + let sign_m = sign_big_int m in + if sign_m * sign_big_int a >= 0 then m + else + let abs_b = abs_big_int b in + if sign_m = 1 then sub_big_int m abs_b else add_big_int m abs_b let eq = eq_big_int let ne x y = not (eq x y) let lt = lt_big_int diff --git a/test/run/modulus.as b/test/run/modulus.as new file mode 100644 index 00000000000..f5f5349c2ee --- /dev/null +++ b/test/run/modulus.as @@ -0,0 +1,13 @@ +{ let a = 13; let b = 5; assert (2 == a / b); assert (3 == a % b) }; +{ let a = -13; let b = 5; assert (-2 == a / b); assert (-3 == a % b) }; +{ let a = -13 ;let b = -5; assert (2 == a / b); assert (-3 == a % b) }; +{ let a = 13; let b = -5; assert (-2 == a / b); assert (3 == a % b) }; + + +{ let a = 5; let b = 5; assert (1 == a / b); assert (0 == a % b) }; +{ let a = -5; let b = 5; assert (-1 == a / b); assert (0 == a % b) }; +{ let a = -5 ;let b = -5; assert (1 == a / b); assert (0 == a % b); }; +{ let a = 5; let b = -5; assert (-1 == a / b); assert (0 == a % b) }; + +{ let a = 0; let b = 5; assert (0 == a / b); assert (0 == a % b) }; +{ let a = 0 ;let b = -5; assert (0 == a / b); assert (0 == a % b) }; From 291d97c7949969fc00b6183e9f467e6d289aa9c1 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Wed, 26 Jun 2019 13:12:14 +0200 Subject: [PATCH 0213/1176] [idl] Simplify function subtyping to positional args (#514) --- design/IDL.md | 55 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 13 deletions(-) diff --git a/design/IDL.md b/design/IDL.md index 6573f036b5e..c029715aeb1 100644 --- a/design/IDL.md +++ b/design/IDL.md @@ -64,8 +64,9 @@ This is a summary of the grammar proposed: ::= { ;* } ::= : ( | ) - ::= ( ,* ) -> ( ,* ) * + ::= ( ,* ) -> ( ,* ) * ::= oneway | pure + ::= ::= : ::= | | | @@ -103,6 +104,9 @@ A `` is a *Unicode scalar value* (i.e., a codepoint that is not a surrogat In addition to this basic grammar, a few syntactic shorthands are supported that can be reduced to the basic forms: ``` + ::= ... + | : := + ::= ... | blob := vec nat8 @@ -139,6 +143,8 @@ A service's signature is described by an *actor type*, which defines the list of ::= { ;* } ::= : ( | ) ``` +We identify `` lists in an actor type up to reordering. + #### Names @@ -175,18 +181,34 @@ service { A function type describes the list of parameters and results and their respective types. It can optionally be annotated to be *pure*, which indicates that it does not modify any state and can potentially be executed more efficiently (e.g., on cached state). (Other annotations may be added in the future.) ``` - ::= ( ,* ) -> ( ,* ) * + ::= ( ,* ) -> ( ,* ) * ::= oneway | pure + ::= ``` +We identify `` lists in a function type up to reordering. -The parameter and result lists are essentially treated as records, see below. That is, they are named, not positional. -The list of parameters must be shorter than 2^32 values and no name/id may occur twice in it. The same restrictions apply to the result list. +The list of parameters must be shorter than 2^32 values; +the same restriction apply to the result list. The result list of a `oneway` function must be empty. + +##### Shorthand: Named Parameters and Results + +As a "shorthand", the types of parameters and results in a function type may be prefixed by a name: +``` + ::= : := +``` +The chosen names only serve documentation purposes and have no semantic significance. +However, duplicate names are not allowed. + + #### Example ``` +(text, text, nat16) -> (text, nat64) +(name : text, address : text, nat16) -> (text, id : nat64) (name : text, address : text, nr : nat16) -> (nick : text, id : nat64) ``` +All three types are equivalent. ### Data @@ -244,6 +266,7 @@ Text strings are represented by the type `text` and consist of a sequence of Uni ``` **Note:** The `text` type is distinguished from `vec nat8` (a UTF-8 string) or `vec nat32` (a sequence of code points) in order to allow bindings to map it to a suitable string type, and enable the binary format to select an efficient internal representation independently. + #### Null The type `null` has exactly one value (the *null* value) and therefor carries no information. It can e.g. be used as a placeholder for optional fields that ought to be added to a record in future upgrades, or for *variant cases* that do not need any value, see below. @@ -259,6 +282,7 @@ The type `reserved` is a type with unknown content that ought to be ignored. Its ``` **Note:** This type has a similar role as *reserved fields* in proto buffers. + #### Empty The type `empty` is the type of values that are not present. Its purpose is to mark variants that are not actually there, or -- as argument types of function reference -- indicate that they will not be called. @@ -301,6 +325,7 @@ A *record* is a *heterogeneous* sequence of values of different data types. Each ::= ... | record { ;* } | ... ::= : ``` +We identify `` lists in a record type up to reordering. The id is described as a simple unsigned integer that has to fit the 64 bit value range. It can be given in either decimal or hexadecimal notation: @@ -367,6 +392,8 @@ A *variant* is a tagged union of different possible data types. The tag is given ``` ::= ... | variant { ;* } | ... ``` +We identify `` lists in a variant type up to reordering. + A field id must be smaller than 2^32 and no id may occur twice in the same variant type. @@ -659,16 +686,18 @@ variant { : ; ;* } <: variant { : ; #### Functions -For a specialised function, any parameter type can be generalised and any result type specialised. Moreover, arguments can be dropped while results can be added. That is, the rules mirror those of records. +For a specialised function, any parameter type can be generalised and any result type specialised. Moreover, arguments can be dropped while results can be added. That is, the rules mirror those of tuple-like records, i.e., they are ordered and can only be extended at the end. ``` -record { ;* } <: record { ;* } -record { ;* } <: record { ;* } ------------------------------------------------------------------------------------------------------------------------ -func ( ,* ) -> ( ,* ) * <: func ( ,* ) -> ( ,* ) * +record { (N1' : );* } <: record { (N1 : );* } +record { (N2 : );* } <: record { N2' : );* } +------------------------------------------------------------------------------------------------------------------- +func ( ,* ) -> ( ,* ) * <: func ( ,* ) -> ( ,* ) * ``` +where `NI*` is the `` sequence `1`..`|*|`, respectively. Viewed as sets, the annotations on the functions must be equal. + #### Actors For an actor, a method can be specialised (by specialising its function type), or a method added. Essentially, they are treated like records of functions. @@ -775,10 +804,10 @@ variant { : ; ;* } <: variant { : ; #### Functions ``` -record { ;* } <: record { ;* } ~> f1 -record { ;* } <: record { ;* } ~> f2 ----------------------------------------------------------------------------------------------------------------------- -func ( ,* ) -> ( ,* ) * <: func ( ,* ) -> ( ,* ) * +record { N1':;* } <: record { N1:;* } ~> f1 +record { N2:;* } <: record { N2':;* } ~> f2 +------------------------------------------------------------------------------------------------------------------ +func ( ,* ) -> ( ,* ) * <: func ( ,* ) -> ( ,* ) * ~> \x.\y.f2 (x (f1 y)) ``` From e7a4da62029b972a3ead60210508fa3d86826a02 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Wed, 26 Jun 2019 16:14:31 +0200 Subject: [PATCH 0214/1176] Forgotten commit (#527) --- design/IDL.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/design/IDL.md b/design/IDL.md index c029715aeb1..486210cd031 100644 --- a/design/IDL.md +++ b/design/IDL.md @@ -1054,15 +1054,15 @@ These measures allow the serialisation format to be extended with new types in t We assume that the argument values are sorted by increasing id. ``` -A(kv* : *) = ( B(kv* : *), R(kv* : *) ) +A(kv* : *) = ( B(kv* : *), R(kv* : *) ) -B(kv* : *) = +B(kv* : *) = i8('D') i8('I') i8('D') i8('L') magic number T*(*) type definition table - T*(*) type of argument list - M(kv* : *) values of argument list + I*(*) type of argument list + M(kv* : *) values of argument list ``` -The `` vector contains an arbitrary sequence of type definitions (see above), to be referenced in the serialisation of the `` vector. +The vector `T*(*)` contains an arbitrary sequence of type definitions (see above), to be referenced in the serialisation of the other `` vector. The same representation is used for function results. From 2a8f0fa94502703a6d86eda6dc2022170ee4c6f4 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Thu, 27 Jun 2019 14:18:47 +0200 Subject: [PATCH 0215/1176] [lang] Replace array/text subtyping with overloaded dot (#529) --- src/Makefile | 8 ++++ src/as_frontend/typing.ml | 52 +++++++++++++--------- src/as_ir/check_ir.ml | 6 ++- src/as_types/type.ml | 64 ++++++++++++---------------- src/as_types/type.mli | 6 +++ src/codegen/compile.ml | 7 ++- src/lowering/desugar.ml | 8 +++- test/fail/objpat-duplicate.as | 14 +++--- test/fail/ok/objpat-duplicate.tc.ok | 4 +- test/repl/ok/type-lub-repl.stderr.ok | 24 ----------- test/repl/ok/type-lub-repl.stdout.ok | 13 +----- test/repl/type-lub-repl.sh | 22 ---------- test/run/array.as | 5 --- test/run/objpat-iter.as | 24 ----------- test/run/type-lub.as | 16 ------- 15 files changed, 98 insertions(+), 175 deletions(-) delete mode 100644 test/run/objpat-iter.as diff --git a/src/Makefile b/src/Makefile index 844c9d6219d..4518737a2c5 100644 --- a/src/Makefile +++ b/src/Makefile @@ -47,3 +47,11 @@ didc: clean: rm -f asc as-ide as-ld asc.js didc dune clean + +test: $(NAME) + make -C ../test ASC=$(ASC) all + make -C ../stdlib ASC=$(ASC) all + make -C ../samples ASC=$(ASC) all + +test-quick: $(NAME) + make -C ../test ASC=$(ASC) quick diff --git a/src/as_frontend/typing.ml b/src/as_frontend/typing.ml index 68127440271..18538e832f8 100644 --- a/src/as_frontend/typing.ml +++ b/src/as_frontend/typing.ml @@ -6,6 +6,7 @@ open As_values module T = Type module A = Effect + (* Error recovery *) exception Recover @@ -14,6 +15,7 @@ let recover_with (x : 'a) (f : 'b -> 'a) (y : 'b) = try f y with Recover -> x let recover_opt f y = recover_with None (fun y -> Some (f y)) y let recover f y = recover_with () f y + (* Contexts *) type lab_env = T.typ T.Env.t @@ -45,6 +47,7 @@ let env_of_scope msgs scope = msgs; } + (* Error bookkeeping *) let type_error at text : Diag.message = @@ -111,6 +114,7 @@ let infer_mut mut : T.typ -> T.typ = | Const -> fun t -> t | Var -> fun t -> T.Mut t + (* Paths *) let rec check_obj_path env path : T.obj_sort * (T.field list) = @@ -521,20 +525,22 @@ and infer_exp'' env exp : T.typ = infer_obj env' sort.it fields exp.at | DotE (exp1, id) -> let t1 = infer_exp_promote env exp1 in - (try - let s, tfs = T.as_obj_sub id.it t1 in - match T.lookup_val_field id.it tfs with - | Some T.Pre -> - error env exp.at "cannot infer type of forward field reference %s" - id.it - | Some t -> t - | None -> - error env exp1.at "field %s does not exist in type\n %s" - id.it (T.string_of_typ_expand t1) - with Invalid_argument _ -> - error env exp1.at - "expected object type, but expression produces type\n %s" - (T.string_of_typ_expand t1) + let _s, tfs = + try T.as_obj_sub id.it t1 with Invalid_argument _ -> + try T.array_obj (T.as_array_sub t1) with Invalid_argument _ -> + try T.text_obj (T.as_prim_sub T.Text t1) with Invalid_argument _ -> + error env exp1.at + "expected object type, but expression produces type\n %s" + (T.string_of_typ_expand t1) + in + (match T.lookup_val_field id.it tfs with + | Some T.Pre -> + error env exp.at "cannot infer type of forward field reference %s" + id.it + | Some t -> t + | None -> + error env exp1.at "field %s does not exist in type\n %s" + id.it (T.string_of_typ_expand t1) ) | AssignE (exp1, exp2) -> if not env.pre then begin @@ -1051,21 +1057,25 @@ and check_pat_fields env tfs pfs ve at : Scope.val_env = | pf::pfs', T.{ lab; typ }::tfs' -> (match compare pf.it.id.it lab with | 0 -> - if T.is_mut typ then error env pf.at "cannot pattern match mutable field %s" lab; + if T.is_mut typ then + error env pf.at "cannot pattern match mutable field %s" lab; let ve1 = check_pat env typ pf.it.pat in - let ve' = disjoint_union env at "duplicate binding for %s in pattern" ve ve1 in - begin match repeated lab pfs' with + let ve' = + disjoint_union env at "duplicate binding for %s in pattern" ve ve1 in + (match repeated lab pfs' with | None -> check_pat_fields env tfs' pfs' ve' at - | Some at -> error env at "cannot pattern match repeated field %s" lab - end + | Some at -> error env at "duplicate field %s in object pattern" lab + ) | c when c > 0 -> check_pat_fields env tfs' pfs ve at | _ -> - error env pf.at "object pattern field %s is not contained in expected type" pf.it.id.it + error env pf.at + "object pattern field %s is not contained in expected type" pf.it.id.it ) | [], _ -> ve | pf::_, [] -> - error env pf.at "object pattern field %s is not contained in expected type" pf.it.id.it + error env pf.at + "object pattern field %s is not contained in expected type" pf.it.id.it and compare_pat_field {it={id = l1; pat; _};_} {it={id = l2; pat; _};_} = compare l1.it l2.it diff --git a/src/as_ir/check_ir.ml b/src/as_ir/check_ir.ml index 0ba7c1bb643..a9598d0e465 100644 --- a/src/as_ir/check_ir.ml +++ b/src/as_ir/check_ir.ml @@ -355,8 +355,10 @@ let rec check_exp env (exp:Ir.exp) : unit = check_exp env exp1; let t1 = typ exp1 in let sort, tfs = - try T.as_obj_sub n t1 with - | Invalid_argument _ -> + (* TODO: separate array and text accessors *) + try T.as_obj_sub n t1 with Invalid_argument _ -> + try T.array_obj (T.as_array_sub t1) with Invalid_argument _ -> + try T.text_obj (T.as_prim_sub T.Text t1) with Invalid_argument _ -> error env exp1.at "expected object type, but expression produces type\n %s" (T.string_of_typ_expand t1) in diff --git a/src/as_types/type.ml b/src/as_types/type.ml index 42864b3a472..b66fb4addba 100644 --- a/src/as_types/type.ml +++ b/src/as_types/type.ml @@ -108,6 +108,11 @@ let compare_field f1 f2 = | {lab = l1; typ = _}, {lab = l2; typ = Typ _ } -> 1 | {lab = l1; typ = _}, {lab = l2; typ = _ } -> compare l1 l2 + +(* Coercions *) + +(* TODO: Move to typing once we have separated accessors in IR. *) + let iter_obj t = Obj (Object Local, [{lab = "next"; typ = Func (Local, Returns, [], [], [Opt t])}]) @@ -121,16 +126,14 @@ let array_obj t = ] in let mut t = immut t @ [ {lab = "set"; typ = Func (Local, Returns, [], [Prim Nat; t], [])} ] in - match t with - | Mut t' -> Obj (Object Local, List.sort compare_field (mut t')) - | t -> Obj (Object Local, List.sort compare_field (immut t)) + Object Local, + List.sort compare_field (match t with Mut t' -> mut t' | t -> immut t) -let text_obj = - let immut = - [ {lab = "chars"; typ = Func (Local, Returns, [], [], [iter_obj (Prim Char)])}; - {lab = "len"; typ = Func (Local, Returns, [], [], [Prim Nat])}; - ] in - Obj (Object Local, List.sort compare_field immut) +let text_obj () = + Object Local, + [ {lab = "chars"; typ = Func (Local, Returns, [], [], [iter_obj (Prim Char)])}; + {lab = "len"; typ = Func (Local, Returns, [], [], [Prim Nat])}; + ] (* Shifting *) @@ -353,10 +356,8 @@ let as_prim_sub p t = match promote t with | Prim p' when p = p' -> () | Non -> () | _ -> invalid "as_prim_sub" -let rec as_obj_sub lab t = match promote t with +let as_obj_sub lab t = match promote t with | Obj (s, tfs) -> s, tfs - | Array t -> as_obj_sub lab (array_obj t) - | Prim Text -> as_obj_sub lab text_obj | Non -> Object Sharable, [{lab; typ = Non}] | _ -> invalid "as_obj_sub" let as_array_sub t = match promote t with @@ -615,8 +616,6 @@ let rec rel_typ rel eq t1 t2 = p1 = Nat && p2 = Int | Prim p1, Shared when rel != eq -> true - | Prim Text, Obj _ when rel != eq -> - rel_typ rel eq text_obj t2 | Obj (s1, tfs1), Obj (s2, tfs2) -> s1 = s2 && rel_fields rel eq tfs1 tfs2 @@ -624,8 +623,6 @@ let rec rel_typ rel eq t1 t2 = s <> Object Local | Array t1', Array t2' -> rel_typ rel eq t1' t2' - | Array t1', Obj _ when rel != eq -> - rel_typ rel eq (array_obj t1') t2 | Array t, Shared when rel != eq -> rel_typ rel eq t Shared | Opt t1', Opt t2' -> @@ -728,12 +725,13 @@ and eq_kind k1 k2 : bool = match k1, k2 with | Def (tbs1, t1), Def (tbs2, t2) | Abs (tbs1, t1), Abs (tbs2, t2) -> - begin match rel_binds eq eq tbs1 tbs2 with - | Some ts -> eq_typ eq eq (open_ ts t1) (open_ ts t2) + (match rel_binds eq eq tbs1 tbs2 with + | Some ts -> eq_typ eq eq (open_ ts t1) (open_ ts t2) | None -> false - end + ) | _ -> false + (* Least upper bound and greatest lower bound *) let rec lub' lubs glbs t1 t2 = @@ -758,26 +756,21 @@ let rec lub' lubs glbs t1 t2 = | Opt t', Prim Null -> t1 | Variant t1', Variant t2' -> Variant (lub_tags lubs glbs t1' t2') - | Array t1', Obj _ -> lub' lubs glbs (array_obj t1') t2 - | Obj _, Array t2' -> lub' lubs glbs t1 (array_obj t2') - | Prim Text, Obj _ -> lub' lubs glbs text_obj t2 - | Obj _, Prim Text -> lub' lubs glbs t1 text_obj - | Prim Text, Array t2' -> lub' lubs glbs text_obj (array_obj t2') - | Array t1', Prim Text -> lub' lubs glbs (array_obj t1') text_obj | Array t1', Array t2' -> Array (lub' lubs glbs t1' t2') | Tup ts1, Tup ts2 when List.(length ts1 = length ts2) -> Tup (List.map2 (lub' lubs glbs) ts1 ts2) | Obj (s1, tf1), Obj (s2, tf2) when s1 = s2 -> Obj (s1, lub_fields lubs glbs tf1 tf2) - | Func (s1, c1, bs1, args1, res1), Func (s2, c2, bs2, args2, res2) - when s1 = s2 && c1 = c2 && List.(length bs1 = length bs2) && - List.(length args1 = length args2 && length res1 = length res2) -> + | Func (s1, c1, bs1, args1, res1), Func (s2, c2, bs2, args2, res2) when + s1 = s2 && c1 = c2 && List.(length bs1 = length bs2) && + List.(length args1 = length args2 && length res1 = length res2) -> combine_func_parts s1 c1 bs1 args1 res1 bs2 args2 res2 lubs glbs glb' lub' | Async t1', Async t2' -> Async (lub' lubs glbs t1' t2') | Con _, _ | _, Con _ -> + (* TODO(rossberg): fix handling of bounds *) combine_con_parts t1 t2 "lub" lubs (lub' lubs glbs) | _ when eq t1 t2 -> t1 | _ when sub t1 Shared && sub t2 Shared -> Shared @@ -823,24 +816,21 @@ and glb' lubs glbs t1 t2 = Variant (glb_tags lubs glbs t1' t2') | Prim Null, Opt _ | Opt _, Prim Null -> Prim Null - | Array t1', Obj _ when sub (array_obj t1') t2 -> t1 (* TODO(gabor): payload should be glb'd *) - | Obj _, Array t2' when sub (array_obj t2') t1 -> t2 (* TODO(gabor): payload should be glb'd *) - | Prim Text, Obj _ when sub text_obj t2 -> t1 - | Obj _, Prim Text when sub text_obj t1 -> t2 | Tup ts1, Tup ts2 when List.(length ts1 = length ts2) -> Tup (List.map2 (glb' lubs glbs) ts1 ts2) | Array t1', Array t2' -> Array (glb' lubs glbs t1' t2') | Obj (s1, tf1), Obj (s2, tf2) when s1 = s2 -> Obj (s1, glb_fields lubs glbs tf1 tf2) - | Func (s1, c1, bs1, args1, res1), Func (s2, c2, bs2, args2, res2) - when s1 = s2 && c1 = c2 && List.(length bs1 = length bs2) && - List.(length args1 = length args2 && length res1 = length res2) -> + | Func (s1, c1, bs1, args1, res1), Func (s2, c2, bs2, args2, res2) when + s1 = s2 && c1 = c2 && List.(length bs1 = length bs2) && + List.(length args1 = length args2 && length res1 = length res2) -> combine_func_parts s1 c1 bs1 args1 res1 bs2 args2 res2 lubs glbs lub' glb' | Async t1', Async t2' -> Async (glb' lubs glbs t1' t2') | Con _, _ | _, Con _ -> + (* TODO(rossberg): fix handling of bounds *) combine_con_parts t1 t2 "glb" glbs (glb' lubs glbs) | _ when eq t1 t2 -> t1 | _ -> Non @@ -850,8 +840,8 @@ and glb_fields lubs glbs fs1 fs2 = match fs1, fs2 with | [], fs2 -> fs2 | f1::fs1', f2::fs2' -> match compare_field f1 f2 with - | +1 -> f2::glb_fields lubs glbs fs1 fs2' | -1 -> f1::glb_fields lubs glbs fs1' fs2 + | +1 -> f2::glb_fields lubs glbs fs1 fs2' | _ -> {f1 with typ = glb' lubs glbs f1.typ f2.typ}::glb_fields lubs glbs fs1' fs2' and glb_tags lubs glbs fs1 fs2 = match fs1, fs2 with @@ -895,10 +885,12 @@ and combine_con_parts t1 t2 naming re how = let lub t1 t2 = lub' (ref M.empty) (ref M.empty) t1 t2 let glb t1 t2 = glb' (ref M.empty) (ref M.empty) t1 t2 + (* Environments *) module Env = Env.Make(String) + (* Pretty printing *) open Printf diff --git a/src/as_types/type.mli b/src/as_types/type.mli index 4316a8b11ce..9850712b039 100644 --- a/src/as_types/type.mli +++ b/src/as_types/type.mli @@ -126,6 +126,12 @@ val lookup_typ_field : string -> field list -> con option val compare_field : field -> field -> int +(* Corercions *) + +val array_obj : typ -> obj_sort * field list +val text_obj : unit -> obj_sort * field list + + (* Constructors *) val set_kind : con -> kind -> unit diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 9e7d637822e..e96d3aa61a3 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -1870,8 +1870,11 @@ module Object = struct (* Determines whether the field is mutable (and thus needs an indirection) *) let is_mut_field env obj_type s = - let _, fields = Type.as_obj_sub "" obj_type in - Type.is_mut (Lib.Option.value (Type.lookup_val_field s fields)) + (* TODO: remove try once array and text accessors are separated *) + try + let _, fields = Type.as_obj_sub "" obj_type in + Type.is_mut (Lib.Option.value (Type.lookup_val_field s fields)) + with Invalid_argument _ -> false let idx env obj_type name = compile_unboxed_const (hash_field_name name) ^^ diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index cca1cf48e60..f73cee929ce 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -76,7 +76,13 @@ and exp' at note = function | S.TagE (c, e) -> I.TagE (c.it, exp e) | S.DotE (e, x) -> let n = x.it in - begin match T.as_obj_sub x.it e.note.S.note_typ with + begin match + (* TODO: separate array and text accessors *) + try T.as_obj_sub x.it e.note.S.note_typ with Invalid_argument _ -> + try T.array_obj (T.as_array_sub e.note.S.note_typ) with Invalid_argument _ -> + try T.text_obj (T.as_prim_sub T.Text e.note.S.note_typ) with Invalid_argument _ -> + assert false + with | T.Actor, _ -> I.ActorDotE (exp e, n) | _ -> I.DotE (exp e, n) end diff --git a/test/fail/objpat-duplicate.as b/test/fail/objpat-duplicate.as index db6f6a53a20..2310218182e 100644 --- a/test/fail/objpat-duplicate.as +++ b/test/fail/objpat-duplicate.as @@ -1,11 +1,9 @@ -switch "duplicate field names" { - case { len = l; chars; len } { - for (x in chars()) { printInt (l()); } - } +object o {a = 1; b = 2}; + +switch o { + case {a = x; b; a} {} }; -switch "duplicate bindings" { - case { len; chars = len } { - printInt (len()) - } +switch o { + case {a; b = a} {} }; diff --git a/test/fail/ok/objpat-duplicate.tc.ok b/test/fail/ok/objpat-duplicate.tc.ok index fe1968cfa74..1a6f85ce453 100644 --- a/test/fail/ok/objpat-duplicate.tc.ok +++ b/test/fail/ok/objpat-duplicate.tc.ok @@ -1,2 +1,2 @@ -objpat-duplicate.as:2.26-2.29: type error, cannot pattern match repeated field len -objpat-duplicate.as:8.8-8.28: type error, duplicate binding for len in pattern +objpat-duplicate.as:4.19-4.20: type error, duplicate field a in object pattern +objpat-duplicate.as:8.8-8.18: type error, duplicate binding for a in pattern diff --git a/test/repl/ok/type-lub-repl.stderr.ok b/test/repl/ok/type-lub-repl.stderr.ok index a32a914044d..e69de29bb2d 100644 --- a/test/repl/ok/type-lub-repl.stderr.ok +++ b/test/repl/ok/type-lub-repl.stderr.ok @@ -1,24 +0,0 @@ -stdin:34.18-34.26: type error, expression of type - {get : Nat -> Int; keys : () -> {next : () -> ?Nat}; len : () -> Nat; vals : () -> {next : () -> ?Int}} -cannot produce expected type - [Int] -stdin:34.1-34.27: type error, expression of type - Nat -cannot produce expected type - () -stdin:35.18-35.26: type error, expression of type - {get : Nat -> Int; keys : () -> {next : () -> ?Nat}; len : () -> Nat; vals : () -> {next : () -> ?Int}} -cannot produce expected type - [Int] -stdin:35.1-35.27: type error, expression of type - Nat -cannot produce expected type - () -stdin:42.19-42.26: type error, literal of type - Text -does not have expected type - Non -stdin:43.19-43.44: type error, expression of type - [Char] -cannot produce expected type - Non diff --git a/test/repl/ok/type-lub-repl.stdout.ok b/test/repl/ok/type-lub-repl.stdout.ok index a2e43e5479c..7c6140771e6 100644 --- a/test/repl/ok/type-lub-repl.stdout.ok +++ b/test/repl/ok/type-lub-repl.stdout.ok @@ -3,10 +3,6 @@ ActorScript 0.1 interpreter > [null, null] : [Null] > [{a = 42}, {b = 42}] : [{}] > [{a = 42}, {a = 1; b = 42}, {a = -25}] : [{a : Int}] -> [{len = func}, [1, 2, 3]] : [{len : () -> Nat}] -> [{len = func}, "hello"] : [{len : () -> Nat}] -> [[1, 2, 3], "hello"] : [{len : () -> Nat}] -> [{len = func}, [1, 2, 3], "hello"] : [{len : () -> Nat}] > [(12, -1), (-42, 25)] : [(Int, Int)] > [-1, 25] : [Int] > [[-42], [25]] : [[Int]] @@ -24,14 +20,7 @@ ActorScript 0.1 interpreter > [func, func] : [(([A], B) -> A)] > 1 : Nat > 11 : Nat -> [func, func] : [([Int] -> Nat)] -> 13 : Nat -> 3 : Nat -> let combined : {get : Nat -> Int; keys : () -> {next : () -> ?Nat}; len : () -> Nat; vals : () -> {next : () -> ?Int}} = {get = func; keys = func; len = func; vals = func} -> > 5 : Nat -> 5 : Nat -> [func, func] : [(Non -> Nat)] -> > > [func, func] : [({#bar} -> ())] +> [func, func] : [({#bar} -> ())] > > > [[42], [25], [77]] : [[Any]] > [42, 77, [1, 2, 3]] : [Shared] > [77, [1, 2, 3], 42] : [Shared] diff --git a/test/repl/type-lub-repl.sh b/test/repl/type-lub-repl.sh index cc4e31ca21d..63bae92abd3 100755 --- a/test/repl/type-lub-repl.sh +++ b/test/repl/type-lub-repl.sh @@ -5,10 +5,6 @@ opts; nulls; incompatible_objs; objs; -obj_arrs; -obj_texts; -arr_texts; -obj_arr_texts; tups; tup1s; arrs; @@ -26,24 +22,6 @@ poly_funcs3; poly_funcs4; poly_funcs4[0]([1, 2, 3], 42); poly_funcs4[1]([11, 22, 33], 25); -obj_arr_funcs; -obj_arr_funcs[0]([1, 2, 3]); -obj_arr_funcs[1]([1, 2, 3]); -let combined = new { len () : Nat = 42 - ; get (i : Nat) : Int = i - ; keys () : {next () : ?Nat} = new { next () : ?Nat = null } - ; vals () : {next () : ?Int} = new { next () : ?Int = null } - }; -obj_arr_funcs[0](combined); // error: no object below array -obj_arr_funcs[1](combined); // error - -obj_text_funcs; -obj_text_funcs[0]("hello"); -obj_text_funcs[1]("hello"); - -arr_text_funcs; -arr_text_funcs[0]("hello"); -arr_text_funcs[1](['h', 'e', 'l', 'l', 'o']); variant_funcs; variant_funcs[0](#bar); diff --git a/test/run/array.as b/test/run/array.as index ed1c65f0309..2d56b822fa2 100644 --- a/test/run/array.as +++ b/test/run/array.as @@ -30,11 +30,6 @@ assert(b[1] == 6); b.set(2, 7); assert(b[2] == 7); -let oa : {get : Nat -> Nat} = a; -let ob : {set : (Nat, Nat) -> ()} = b; -assert(oa.get(2) == 42); -ob.set(2, 22); - func opt_eq(x : ?Nat, y : Nat) : Bool { switch x { case null { false }; case (?i) { i == y } } diff --git a/test/run/objpat-iter.as b/test/run/objpat-iter.as deleted file mode 100644 index dcfa056416c..00000000000 --- a/test/run/objpat-iter.as +++ /dev/null @@ -1,24 +0,0 @@ -var y = 0; -switch ([1,2]) { - case ({ vals = iter }) { - for (x in iter()) { y := x; } - } -}; - -assert (y == 2); - -switch ([1,2]) { - case { vals; len } { - for (x in vals()) { y += x + len(); } - } -}; - -assert (y == 9); - -switch "Hi" { - case { chars; len } { - for (x in chars()) { y += 1 + len(); } - } -}; - -assert (y == 15); diff --git a/test/run/type-lub.as b/test/run/type-lub.as index 783929db3d2..7e9c6697b24 100644 --- a/test/run/type-lub.as +++ b/test/run/type-lub.as @@ -3,10 +3,6 @@ let nulls = [null, null]; let incompatible_objs = [new {a = 42}, new {b = 42}]; let objs = [new {a = 42}, new {b = 42; a = 1}, new {a = -25}]; -let obj_arrs = [new {len() : Nat = 42}, [1, 2, 3]]; -let obj_texts = [new {len() : Nat = 42}, "hello"]; -let arr_texts = [[1, 2, 3], "hello"]; -let obj_arr_texts = [new {len() : Nat = 42}, [1, 2, 3], "hello"]; let tups = [(12, -1), (-42, 25)]; let tup1s = [(-1,), 25]; @@ -37,18 +33,6 @@ let funcs = [ func (a : [Int]) : Nat = a.len() , func (a : [Nat]) : Int = -42 ]; -let obj_arr_funcs = [ func (a : [Int]) : Nat { printInt (a[0]); a.len() } - , func (a : {len : () -> Nat}) : Nat = a.len() - ]; - -let obj_text_funcs = [ func (a : Text) : Nat = a.len() - , func (a : {len : () -> Nat}) : Nat = a.len() - ]; - -let arr_text_funcs = [ func (a : Text) : Nat = a.len() - , func (a : [Char]) : Nat { printChar (a[0]); a.len() } - ]; - let variant_funcs = [ func (a : {#foo; #bar}) { switch a { case (#foo) (); case (#bar) () } } , func (a : {#baz; #bar}) { switch a { case (#baz) (); case (#bar) () } } ]; From ec713f1ea971b8970b72576ff47f075e5f71d4fb Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 27 Jun 2019 14:32:26 +0200 Subject: [PATCH 0216/1176] Add testcase for #551 (#512) --- test/run/issue551.as | 6 ++++++ test/run/ok/issue551.diff-ir.ok | 5 +++++ test/run/ok/issue551.diff-low.ok | 5 +++++ test/run/ok/issue551.run-ir.ok | 2 ++ test/run/ok/issue551.run-low.ok | 2 ++ test/run/ok/issue551.wasm.stderr.ok | 2 ++ 6 files changed, 22 insertions(+) create mode 100644 test/run/issue551.as create mode 100644 test/run/ok/issue551.diff-ir.ok create mode 100644 test/run/ok/issue551.diff-low.ok create mode 100644 test/run/ok/issue551.run-ir.ok create mode 100644 test/run/ok/issue551.run-low.ok create mode 100644 test/run/ok/issue551.wasm.stderr.ok diff --git a/test/run/issue551.as b/test/run/issue551.as new file mode 100644 index 00000000000..42c51c3002c --- /dev/null +++ b/test/run/issue551.as @@ -0,0 +1,6 @@ +{ + type A = ?B; + type B = Int; + let x : A = ?5; + ignore(debug_show x) +}; diff --git a/test/run/ok/issue551.diff-ir.ok b/test/run/ok/issue551.diff-ir.ok new file mode 100644 index 00000000000..60b19919a53 --- /dev/null +++ b/test/run/ok/issue551.diff-ir.ok @@ -0,0 +1,5 @@ +--- issue551.run ++++ issue551.run-ir +@@ -0,0 +1,2 @@ ++Ill-typed intermediate code after Translate show (use -v to see dumped IR): ++(unknown location): IR type error, free type constructor B diff --git a/test/run/ok/issue551.diff-low.ok b/test/run/ok/issue551.diff-low.ok new file mode 100644 index 00000000000..c413d986827 --- /dev/null +++ b/test/run/ok/issue551.diff-low.ok @@ -0,0 +1,5 @@ +--- issue551.run ++++ issue551.run-low +@@ -0,0 +1,2 @@ ++Ill-typed intermediate code after Translate show (use -v to see dumped IR): ++(unknown location): IR type error, free type constructor B diff --git a/test/run/ok/issue551.run-ir.ok b/test/run/ok/issue551.run-ir.ok new file mode 100644 index 00000000000..ff73e2b2806 --- /dev/null +++ b/test/run/ok/issue551.run-ir.ok @@ -0,0 +1,2 @@ +Ill-typed intermediate code after Translate show (use -v to see dumped IR): +(unknown location): IR type error, free type constructor B diff --git a/test/run/ok/issue551.run-low.ok b/test/run/ok/issue551.run-low.ok new file mode 100644 index 00000000000..ff73e2b2806 --- /dev/null +++ b/test/run/ok/issue551.run-low.ok @@ -0,0 +1,2 @@ +Ill-typed intermediate code after Translate show (use -v to see dumped IR): +(unknown location): IR type error, free type constructor B diff --git a/test/run/ok/issue551.wasm.stderr.ok b/test/run/ok/issue551.wasm.stderr.ok new file mode 100644 index 00000000000..ff73e2b2806 --- /dev/null +++ b/test/run/ok/issue551.wasm.stderr.ok @@ -0,0 +1,2 @@ +Ill-typed intermediate code after Translate show (use -v to see dumped IR): +(unknown location): IR type error, free type constructor B From 668083d34adc8fbfcdc11331ddfed0e6338cd938 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Thu, 27 Jun 2019 16:39:40 +0200 Subject: [PATCH 0217/1176] AST-89 trapping binops for range-limited numerical types (#521) * add Nat* relops (and test) in interpreter/backend * interpret all Int*/Nat* binops * uncovered a bug/omission in the interpreter for subtraction Int*/Nat* * backend implementations for `+`, `-`, `*`, `/`, `%`. Caveat: `pow` only implemented for `Nat64`/`Int64`. --- src/as_values/operator.ml | 68 +++--- src/as_values/value.ml | 1 + src/codegen/compile.ml | 222 ++++++++++++++++-- test/Makefile | 5 + test/fail/ok/outrange-int64lower.wasm-run.ok | 1 - test/fail/ok/outrange-int64negation.run-ir.ok | 1 - .../fail/ok/outrange-int64negation.run-low.ok | 1 - test/fail/ok/outrange-int64negation.run.ok | 1 - .../ok/outrange-int64negation.wasm-run.ok | 1 - test/fail/ok/outrange-int64upper.wasm-run.ok | 1 - test/fail/ok/outrange-int8lower.wasm-run.ok | 1 - test/fail/ok/outrange-int8upper.wasm-run.ok | 1 - test/run/numeric-ops.as | 201 +++++++++++++++- test/trap/Makefile | 31 +++ test/trap/addInt16-lower.as | 1 + test/trap/addInt16-upper.as | 1 + test/trap/addInt32-lower.as | 1 + test/trap/addInt32-upper.as | 1 + test/trap/addInt64-lower.as | 1 + test/trap/addInt64-upper.as | 1 + test/trap/addInt8-lower.as | 1 + test/trap/addInt8-upper.as | 1 + test/trap/addNat16.as | 1 + test/trap/addNat32.as | 1 + test/trap/addNat64.as | 1 + test/trap/addNat8.as | 1 + test/trap/divInt16.as | 1 + test/trap/divInt32.as | 1 + test/trap/divInt64.as | 1 + test/trap/divInt8.as | 1 + test/trap/mulInt16-lower.as | 1 + test/trap/mulInt16-upper.as | 1 + test/trap/mulInt32-lower.as | 1 + test/trap/mulInt32-upper.as | 1 + test/trap/mulInt64-lower.as | 1 + test/trap/mulInt64-upper.as | 1 + test/trap/mulInt8-lower.as | 1 + test/trap/mulInt8-upper.as | 1 + test/trap/mulNat16.as | 1 + test/trap/mulNat32.as | 1 + test/trap/mulNat64.as | 1 + test/trap/mulNat8.as | 1 + test/trap/ok/addInt16-lower.run-ir.ok | 1 + test/trap/ok/addInt16-lower.run-low.ok | 1 + test/trap/ok/addInt16-lower.run.ok | 1 + test/trap/ok/addInt16-lower.wasm-run.ok | 1 + test/trap/ok/addInt16-upper.run-ir.ok | 1 + test/trap/ok/addInt16-upper.run-low.ok | 1 + test/trap/ok/addInt16-upper.run.ok | 1 + test/trap/ok/addInt16-upper.wasm-run.ok | 1 + test/trap/ok/addInt32-lower.run-ir.ok | 1 + test/trap/ok/addInt32-lower.run-low.ok | 1 + test/trap/ok/addInt32-lower.run.ok | 1 + test/trap/ok/addInt32-lower.wasm-run.ok | 1 + test/trap/ok/addInt32-upper.run-ir.ok | 1 + test/trap/ok/addInt32-upper.run-low.ok | 1 + test/trap/ok/addInt32-upper.run.ok | 1 + test/trap/ok/addInt32-upper.wasm-run.ok | 1 + test/trap/ok/addInt64-lower.run-ir.ok | 1 + test/trap/ok/addInt64-lower.run-low.ok | 1 + test/trap/ok/addInt64-lower.run.ok | 1 + test/trap/ok/addInt64-lower.wasm-run.ok | 1 + test/trap/ok/addInt64-upper.run-ir.ok | 1 + test/trap/ok/addInt64-upper.run-low.ok | 1 + test/trap/ok/addInt64-upper.run.ok | 1 + test/trap/ok/addInt64-upper.wasm-run.ok | 1 + test/trap/ok/addInt8-lower.run-ir.ok | 1 + test/trap/ok/addInt8-lower.run-low.ok | 1 + test/trap/ok/addInt8-lower.run.ok | 1 + test/trap/ok/addInt8-lower.wasm-run.ok | 1 + test/trap/ok/addInt8-upper.run-ir.ok | 1 + test/trap/ok/addInt8-upper.run-low.ok | 1 + test/trap/ok/addInt8-upper.run.ok | 1 + test/trap/ok/addInt8-upper.wasm-run.ok | 1 + test/trap/ok/addNat16.run-ir.ok | 1 + test/trap/ok/addNat16.run-low.ok | 1 + test/trap/ok/addNat16.run.ok | 1 + test/trap/ok/addNat16.wasm-run.ok | 1 + test/trap/ok/addNat32.run-ir.ok | 1 + test/trap/ok/addNat32.run-low.ok | 1 + test/trap/ok/addNat32.run.ok | 1 + test/trap/ok/addNat32.wasm-run.ok | 1 + test/trap/ok/addNat64.run-ir.ok | 1 + test/trap/ok/addNat64.run-low.ok | 1 + test/trap/ok/addNat64.run.ok | 1 + test/trap/ok/addNat64.wasm-run.ok | 1 + test/trap/ok/addNat8.run-ir.ok | 1 + test/trap/ok/addNat8.run-low.ok | 1 + test/trap/ok/addNat8.run.ok | 1 + test/trap/ok/addNat8.wasm-run.ok | 1 + test/trap/ok/divInt16.run-ir.ok | 1 + test/trap/ok/divInt16.run-low.ok | 1 + test/trap/ok/divInt16.run.ok | 1 + test/trap/ok/divInt16.wasm-run.ok | 1 + test/trap/ok/divInt32.run-ir.ok | 1 + test/trap/ok/divInt32.run-low.ok | 1 + test/trap/ok/divInt32.run.ok | 1 + test/trap/ok/divInt32.wasm-run.ok | 1 + test/trap/ok/divInt64.run-ir.ok | 1 + test/trap/ok/divInt64.run-low.ok | 1 + test/trap/ok/divInt64.run.ok | 1 + test/trap/ok/divInt64.wasm-run.ok | 1 + test/trap/ok/divInt8.run-ir.ok | 1 + test/trap/ok/divInt8.run-low.ok | 1 + test/trap/ok/divInt8.run.ok | 1 + test/trap/ok/divInt8.wasm-run.ok | 1 + test/trap/ok/mulInt16-lower.run-ir.ok | 1 + test/trap/ok/mulInt16-lower.run-low.ok | 1 + test/trap/ok/mulInt16-lower.run.ok | 1 + test/trap/ok/mulInt16-lower.wasm-run.ok | 1 + test/trap/ok/mulInt16-upper.run-ir.ok | 1 + test/trap/ok/mulInt16-upper.run-low.ok | 1 + test/trap/ok/mulInt16-upper.run.ok | 1 + test/trap/ok/mulInt16-upper.wasm-run.ok | 1 + test/trap/ok/mulInt32-lower.run-ir.ok | 1 + test/trap/ok/mulInt32-lower.run-low.ok | 1 + test/trap/ok/mulInt32-lower.run.ok | 1 + test/trap/ok/mulInt32-lower.wasm-run.ok | 1 + test/trap/ok/mulInt32-upper.run-ir.ok | 1 + test/trap/ok/mulInt32-upper.run-low.ok | 1 + test/trap/ok/mulInt32-upper.run.ok | 1 + test/trap/ok/mulInt32-upper.wasm-run.ok | 1 + test/trap/ok/mulInt64-lower.run-ir.ok | 1 + test/trap/ok/mulInt64-lower.run-low.ok | 1 + test/trap/ok/mulInt64-lower.run.ok | 1 + test/trap/ok/mulInt64-lower.wasm-run.ok | 1 + test/trap/ok/mulInt64-upper.run-ir.ok | 1 + test/trap/ok/mulInt64-upper.run-low.ok | 1 + test/trap/ok/mulInt64-upper.run.ok | 1 + test/trap/ok/mulInt64-upper.wasm-run.ok | 1 + test/trap/ok/mulInt8-lower.run-ir.ok | 1 + test/trap/ok/mulInt8-lower.run-low.ok | 1 + test/trap/ok/mulInt8-lower.run.ok | 1 + test/trap/ok/mulInt8-lower.wasm-run.ok | 1 + test/trap/ok/mulInt8-upper.run-ir.ok | 1 + test/trap/ok/mulInt8-upper.run-low.ok | 1 + test/trap/ok/mulInt8-upper.run.ok | 1 + test/trap/ok/mulInt8-upper.wasm-run.ok | 1 + test/trap/ok/mulNat16.run-ir.ok | 1 + test/trap/ok/mulNat16.run-low.ok | 1 + test/trap/ok/mulNat16.run.ok | 1 + test/trap/ok/mulNat16.wasm-run.ok | 1 + test/trap/ok/mulNat32.run-ir.ok | 1 + test/trap/ok/mulNat32.run-low.ok | 1 + test/trap/ok/mulNat32.run.ok | 1 + test/trap/ok/mulNat32.wasm-run.ok | 1 + test/trap/ok/mulNat64.run-ir.ok | 1 + test/trap/ok/mulNat64.run-low.ok | 1 + test/trap/ok/mulNat64.run.ok | 1 + test/trap/ok/mulNat64.wasm-run.ok | 1 + test/trap/ok/mulNat8.run-ir.ok | 1 + test/trap/ok/mulNat8.run-low.ok | 1 + test/trap/ok/mulNat8.run.ok | 1 + test/trap/ok/mulNat8.wasm-run.ok | 1 + test/trap/ok/outrange-int16-lower.run-ir.ok | 1 + test/trap/ok/outrange-int16-lower.run-low.ok | 1 + test/trap/ok/outrange-int16-lower.run.ok | 1 + test/trap/ok/outrange-int16-lower.wasm-run.ok | 1 + .../trap/ok/outrange-int16-negation.run-ir.ok | 1 + .../ok/outrange-int16-negation.run-low.ok | 1 + test/trap/ok/outrange-int16-negation.run.ok | 1 + .../ok/outrange-int16-negation.wasm-run.ok | 1 + test/trap/ok/outrange-int16-upper.run-ir.ok | 1 + test/trap/ok/outrange-int16-upper.run-low.ok | 1 + test/trap/ok/outrange-int16-upper.run.ok | 1 + test/trap/ok/outrange-int16-upper.wasm-run.ok | 1 + test/trap/ok/outrange-int32-lower.run-ir.ok | 1 + test/trap/ok/outrange-int32-lower.run-low.ok | 1 + test/trap/ok/outrange-int32-lower.run.ok | 1 + test/trap/ok/outrange-int32-lower.wasm-run.ok | 1 + .../trap/ok/outrange-int32-negation.run-ir.ok | 1 + .../ok/outrange-int32-negation.run-low.ok | 1 + test/trap/ok/outrange-int32-negation.run.ok | 1 + .../ok/outrange-int32-negation.wasm-run.ok | 1 + test/trap/ok/outrange-int32-upper.run-ir.ok | 1 + test/trap/ok/outrange-int32-upper.run-low.ok | 1 + test/trap/ok/outrange-int32-upper.run.ok | 1 + test/trap/ok/outrange-int32-upper.wasm-run.ok | 1 + .../ok/outrange-int64-lower.run-ir.ok} | 0 .../ok/outrange-int64-lower.run-low.ok} | 0 .../ok/outrange-int64-lower.run.ok} | 0 test/trap/ok/outrange-int64-lower.wasm-run.ok | 1 + .../trap/ok/outrange-int64-negation.run-ir.ok | 1 + .../ok/outrange-int64-negation.run-low.ok | 1 + test/trap/ok/outrange-int64-negation.run.ok | 1 + .../ok/outrange-int64-negation.wasm-run.ok | 1 + .../ok/outrange-int64-upper.run-ir.ok} | 0 .../ok/outrange-int64-upper.run-low.ok} | 0 .../ok/outrange-int64-upper.run.ok} | 0 test/trap/ok/outrange-int64-upper.wasm-run.ok | 1 + .../ok/outrange-int8-lower.run-ir.ok} | 0 .../ok/outrange-int8-lower.run-low.ok} | 0 .../ok/outrange-int8-lower.run.ok} | 0 test/trap/ok/outrange-int8-lower.wasm-run.ok | 1 + test/trap/ok/outrange-int8-negation.run-ir.ok | 1 + .../trap/ok/outrange-int8-negation.run-low.ok | 1 + test/trap/ok/outrange-int8-negation.run.ok | 1 + .../ok/outrange-int8-negation.wasm-run.ok | 1 + .../ok/outrange-int8-upper.run-ir.ok} | 0 .../ok/outrange-int8-upper.run-low.ok} | 0 .../ok/outrange-int8-upper.run.ok} | 0 test/trap/ok/outrange-int8-upper.wasm-run.ok | 1 + test/trap/ok/outrange-nat16.run-ir.ok | 1 + test/trap/ok/outrange-nat16.run-low.ok | 1 + test/trap/ok/outrange-nat16.run.ok | 1 + test/trap/ok/outrange-nat16.wasm-run.ok | 1 + test/trap/ok/outrange-nat32.run-ir.ok | 1 + test/trap/ok/outrange-nat32.run-low.ok | 1 + test/trap/ok/outrange-nat32.run.ok | 1 + test/trap/ok/outrange-nat32.wasm-run.ok | 1 + .../ok/outrange-nat64.run-ir.ok | 0 .../ok/outrange-nat64.run-low.ok | 0 test/{fail => trap}/ok/outrange-nat64.run.ok | 0 .../ok/outrange-nat64.wasm-run.ok | 0 .../{fail => trap}/ok/outrange-nat8.run-ir.ok | 0 .../ok/outrange-nat8.run-low.ok | 0 test/{fail => trap}/ok/outrange-nat8.run.ok | 0 .../ok/outrange-nat8.wasm-run.ok | 0 test/trap/ok/subInt16-lower.run-ir.ok | 1 + test/trap/ok/subInt16-lower.run-low.ok | 1 + test/trap/ok/subInt16-lower.run.ok | 1 + test/trap/ok/subInt16-lower.wasm-run.ok | 1 + test/trap/ok/subInt16-upper.run-ir.ok | 1 + test/trap/ok/subInt16-upper.run-low.ok | 1 + test/trap/ok/subInt16-upper.run.ok | 1 + test/trap/ok/subInt16-upper.wasm-run.ok | 1 + test/trap/ok/subInt32-lower.run-ir.ok | 1 + test/trap/ok/subInt32-lower.run-low.ok | 1 + test/trap/ok/subInt32-lower.run.ok | 1 + test/trap/ok/subInt32-lower.wasm-run.ok | 1 + test/trap/ok/subInt32-upper.run-ir.ok | 1 + test/trap/ok/subInt32-upper.run-low.ok | 1 + test/trap/ok/subInt32-upper.run.ok | 1 + test/trap/ok/subInt32-upper.wasm-run.ok | 1 + test/trap/ok/subInt64-lower.run-ir.ok | 1 + test/trap/ok/subInt64-lower.run-low.ok | 1 + test/trap/ok/subInt64-lower.run.ok | 1 + test/trap/ok/subInt64-lower.wasm-run.ok | 1 + test/trap/ok/subInt64-upper.run-ir.ok | 1 + test/trap/ok/subInt64-upper.run-low.ok | 1 + test/trap/ok/subInt64-upper.run.ok | 1 + test/trap/ok/subInt64-upper.wasm-run.ok | 1 + test/trap/ok/subInt8-lower.run-ir.ok | 1 + test/trap/ok/subInt8-lower.run-low.ok | 1 + test/trap/ok/subInt8-lower.run.ok | 1 + test/trap/ok/subInt8-lower.wasm-run.ok | 1 + test/trap/ok/subInt8-upper.run-ir.ok | 1 + test/trap/ok/subInt8-upper.run-low.ok | 1 + test/trap/ok/subInt8-upper.run.ok | 1 + test/trap/ok/subInt8-upper.wasm-run.ok | 1 + test/trap/ok/subNat16.run-ir.ok | 1 + test/trap/ok/subNat16.run-low.ok | 1 + test/trap/ok/subNat16.run.ok | 1 + test/trap/ok/subNat16.wasm-run.ok | 1 + test/trap/ok/subNat32.run-ir.ok | 1 + test/trap/ok/subNat32.run-low.ok | 1 + test/trap/ok/subNat32.run.ok | 1 + test/trap/ok/subNat32.wasm-run.ok | 1 + test/trap/ok/subNat64.run-ir.ok | 1 + test/trap/ok/subNat64.run-low.ok | 1 + test/trap/ok/subNat64.run.ok | 1 + test/trap/ok/subNat64.wasm-run.ok | 1 + test/trap/ok/subNat8.run-ir.ok | 1 + test/trap/ok/subNat8.run-low.ok | 1 + test/trap/ok/subNat8.run.ok | 1 + test/trap/ok/subNat8.wasm-run.ok | 1 + test/trap/outrange-int16-lower.as | 1 + test/trap/outrange-int16-negation.as | 1 + test/trap/outrange-int16-upper.as | 1 + test/trap/outrange-int32-lower.as | 1 + test/trap/outrange-int32-negation.as | 1 + test/trap/outrange-int32-upper.as | 1 + .../outrange-int64-lower.as} | 0 .../outrange-int64-negation.as} | 0 .../outrange-int64-upper.as} | 0 .../outrange-int8-lower.as} | 0 test/trap/outrange-int8-negation.as | 1 + .../outrange-int8-upper.as} | 0 test/trap/outrange-nat16.as | 1 + test/trap/outrange-nat32.as | 1 + test/{fail => trap}/outrange-nat64.as | 0 test/{fail => trap}/outrange-nat8.as | 0 test/trap/subInt16-lower.as | 1 + test/trap/subInt16-upper.as | 1 + test/trap/subInt32-lower.as | 1 + test/trap/subInt32-upper.as | 1 + test/trap/subInt64-lower.as | 1 + test/trap/subInt64-upper.as | 1 + test/trap/subInt8-lower.as | 1 + test/trap/subInt8-upper.as | 1 + test/trap/subNat16.as | 1 + test/trap/subNat32.as | 1 + test/trap/subNat64.as | 1 + test/trap/subNat8.as | 1 + 294 files changed, 723 insertions(+), 66 deletions(-) delete mode 100644 test/fail/ok/outrange-int64lower.wasm-run.ok delete mode 100644 test/fail/ok/outrange-int64negation.run-ir.ok delete mode 100644 test/fail/ok/outrange-int64negation.run-low.ok delete mode 100644 test/fail/ok/outrange-int64negation.run.ok delete mode 100644 test/fail/ok/outrange-int64negation.wasm-run.ok delete mode 100644 test/fail/ok/outrange-int64upper.wasm-run.ok delete mode 100644 test/fail/ok/outrange-int8lower.wasm-run.ok delete mode 100644 test/fail/ok/outrange-int8upper.wasm-run.ok create mode 100644 test/trap/Makefile create mode 100644 test/trap/addInt16-lower.as create mode 100644 test/trap/addInt16-upper.as create mode 100644 test/trap/addInt32-lower.as create mode 100644 test/trap/addInt32-upper.as create mode 100644 test/trap/addInt64-lower.as create mode 100644 test/trap/addInt64-upper.as create mode 100644 test/trap/addInt8-lower.as create mode 100644 test/trap/addInt8-upper.as create mode 100644 test/trap/addNat16.as create mode 100644 test/trap/addNat32.as create mode 100644 test/trap/addNat64.as create mode 100644 test/trap/addNat8.as create mode 100644 test/trap/divInt16.as create mode 100644 test/trap/divInt32.as create mode 100644 test/trap/divInt64.as create mode 100644 test/trap/divInt8.as create mode 100644 test/trap/mulInt16-lower.as create mode 100644 test/trap/mulInt16-upper.as create mode 100644 test/trap/mulInt32-lower.as create mode 100644 test/trap/mulInt32-upper.as create mode 100644 test/trap/mulInt64-lower.as create mode 100644 test/trap/mulInt64-upper.as create mode 100644 test/trap/mulInt8-lower.as create mode 100644 test/trap/mulInt8-upper.as create mode 100644 test/trap/mulNat16.as create mode 100644 test/trap/mulNat32.as create mode 100644 test/trap/mulNat64.as create mode 100644 test/trap/mulNat8.as create mode 100644 test/trap/ok/addInt16-lower.run-ir.ok create mode 100644 test/trap/ok/addInt16-lower.run-low.ok create mode 100644 test/trap/ok/addInt16-lower.run.ok create mode 100644 test/trap/ok/addInt16-lower.wasm-run.ok create mode 100644 test/trap/ok/addInt16-upper.run-ir.ok create mode 100644 test/trap/ok/addInt16-upper.run-low.ok create mode 100644 test/trap/ok/addInt16-upper.run.ok create mode 100644 test/trap/ok/addInt16-upper.wasm-run.ok create mode 100644 test/trap/ok/addInt32-lower.run-ir.ok create mode 100644 test/trap/ok/addInt32-lower.run-low.ok create mode 100644 test/trap/ok/addInt32-lower.run.ok create mode 100644 test/trap/ok/addInt32-lower.wasm-run.ok create mode 100644 test/trap/ok/addInt32-upper.run-ir.ok create mode 100644 test/trap/ok/addInt32-upper.run-low.ok create mode 100644 test/trap/ok/addInt32-upper.run.ok create mode 100644 test/trap/ok/addInt32-upper.wasm-run.ok create mode 100644 test/trap/ok/addInt64-lower.run-ir.ok create mode 100644 test/trap/ok/addInt64-lower.run-low.ok create mode 100644 test/trap/ok/addInt64-lower.run.ok create mode 100644 test/trap/ok/addInt64-lower.wasm-run.ok create mode 100644 test/trap/ok/addInt64-upper.run-ir.ok create mode 100644 test/trap/ok/addInt64-upper.run-low.ok create mode 100644 test/trap/ok/addInt64-upper.run.ok create mode 100644 test/trap/ok/addInt64-upper.wasm-run.ok create mode 100644 test/trap/ok/addInt8-lower.run-ir.ok create mode 100644 test/trap/ok/addInt8-lower.run-low.ok create mode 100644 test/trap/ok/addInt8-lower.run.ok create mode 100644 test/trap/ok/addInt8-lower.wasm-run.ok create mode 100644 test/trap/ok/addInt8-upper.run-ir.ok create mode 100644 test/trap/ok/addInt8-upper.run-low.ok create mode 100644 test/trap/ok/addInt8-upper.run.ok create mode 100644 test/trap/ok/addInt8-upper.wasm-run.ok create mode 100644 test/trap/ok/addNat16.run-ir.ok create mode 100644 test/trap/ok/addNat16.run-low.ok create mode 100644 test/trap/ok/addNat16.run.ok create mode 100644 test/trap/ok/addNat16.wasm-run.ok create mode 100644 test/trap/ok/addNat32.run-ir.ok create mode 100644 test/trap/ok/addNat32.run-low.ok create mode 100644 test/trap/ok/addNat32.run.ok create mode 100644 test/trap/ok/addNat32.wasm-run.ok create mode 100644 test/trap/ok/addNat64.run-ir.ok create mode 100644 test/trap/ok/addNat64.run-low.ok create mode 100644 test/trap/ok/addNat64.run.ok create mode 100644 test/trap/ok/addNat64.wasm-run.ok create mode 100644 test/trap/ok/addNat8.run-ir.ok create mode 100644 test/trap/ok/addNat8.run-low.ok create mode 100644 test/trap/ok/addNat8.run.ok create mode 100644 test/trap/ok/addNat8.wasm-run.ok create mode 100644 test/trap/ok/divInt16.run-ir.ok create mode 100644 test/trap/ok/divInt16.run-low.ok create mode 100644 test/trap/ok/divInt16.run.ok create mode 100644 test/trap/ok/divInt16.wasm-run.ok create mode 100644 test/trap/ok/divInt32.run-ir.ok create mode 100644 test/trap/ok/divInt32.run-low.ok create mode 100644 test/trap/ok/divInt32.run.ok create mode 100644 test/trap/ok/divInt32.wasm-run.ok create mode 100644 test/trap/ok/divInt64.run-ir.ok create mode 100644 test/trap/ok/divInt64.run-low.ok create mode 100644 test/trap/ok/divInt64.run.ok create mode 100644 test/trap/ok/divInt64.wasm-run.ok create mode 100644 test/trap/ok/divInt8.run-ir.ok create mode 100644 test/trap/ok/divInt8.run-low.ok create mode 100644 test/trap/ok/divInt8.run.ok create mode 100644 test/trap/ok/divInt8.wasm-run.ok create mode 100644 test/trap/ok/mulInt16-lower.run-ir.ok create mode 100644 test/trap/ok/mulInt16-lower.run-low.ok create mode 100644 test/trap/ok/mulInt16-lower.run.ok create mode 100644 test/trap/ok/mulInt16-lower.wasm-run.ok create mode 100644 test/trap/ok/mulInt16-upper.run-ir.ok create mode 100644 test/trap/ok/mulInt16-upper.run-low.ok create mode 100644 test/trap/ok/mulInt16-upper.run.ok create mode 100644 test/trap/ok/mulInt16-upper.wasm-run.ok create mode 100644 test/trap/ok/mulInt32-lower.run-ir.ok create mode 100644 test/trap/ok/mulInt32-lower.run-low.ok create mode 100644 test/trap/ok/mulInt32-lower.run.ok create mode 100644 test/trap/ok/mulInt32-lower.wasm-run.ok create mode 100644 test/trap/ok/mulInt32-upper.run-ir.ok create mode 100644 test/trap/ok/mulInt32-upper.run-low.ok create mode 100644 test/trap/ok/mulInt32-upper.run.ok create mode 100644 test/trap/ok/mulInt32-upper.wasm-run.ok create mode 100644 test/trap/ok/mulInt64-lower.run-ir.ok create mode 100644 test/trap/ok/mulInt64-lower.run-low.ok create mode 100644 test/trap/ok/mulInt64-lower.run.ok create mode 100644 test/trap/ok/mulInt64-lower.wasm-run.ok create mode 100644 test/trap/ok/mulInt64-upper.run-ir.ok create mode 100644 test/trap/ok/mulInt64-upper.run-low.ok create mode 100644 test/trap/ok/mulInt64-upper.run.ok create mode 100644 test/trap/ok/mulInt64-upper.wasm-run.ok create mode 100644 test/trap/ok/mulInt8-lower.run-ir.ok create mode 100644 test/trap/ok/mulInt8-lower.run-low.ok create mode 100644 test/trap/ok/mulInt8-lower.run.ok create mode 100644 test/trap/ok/mulInt8-lower.wasm-run.ok create mode 100644 test/trap/ok/mulInt8-upper.run-ir.ok create mode 100644 test/trap/ok/mulInt8-upper.run-low.ok create mode 100644 test/trap/ok/mulInt8-upper.run.ok create mode 100644 test/trap/ok/mulInt8-upper.wasm-run.ok create mode 100644 test/trap/ok/mulNat16.run-ir.ok create mode 100644 test/trap/ok/mulNat16.run-low.ok create mode 100644 test/trap/ok/mulNat16.run.ok create mode 100644 test/trap/ok/mulNat16.wasm-run.ok create mode 100644 test/trap/ok/mulNat32.run-ir.ok create mode 100644 test/trap/ok/mulNat32.run-low.ok create mode 100644 test/trap/ok/mulNat32.run.ok create mode 100644 test/trap/ok/mulNat32.wasm-run.ok create mode 100644 test/trap/ok/mulNat64.run-ir.ok create mode 100644 test/trap/ok/mulNat64.run-low.ok create mode 100644 test/trap/ok/mulNat64.run.ok create mode 100644 test/trap/ok/mulNat64.wasm-run.ok create mode 100644 test/trap/ok/mulNat8.run-ir.ok create mode 100644 test/trap/ok/mulNat8.run-low.ok create mode 100644 test/trap/ok/mulNat8.run.ok create mode 100644 test/trap/ok/mulNat8.wasm-run.ok create mode 100644 test/trap/ok/outrange-int16-lower.run-ir.ok create mode 100644 test/trap/ok/outrange-int16-lower.run-low.ok create mode 100644 test/trap/ok/outrange-int16-lower.run.ok create mode 100644 test/trap/ok/outrange-int16-lower.wasm-run.ok create mode 100644 test/trap/ok/outrange-int16-negation.run-ir.ok create mode 100644 test/trap/ok/outrange-int16-negation.run-low.ok create mode 100644 test/trap/ok/outrange-int16-negation.run.ok create mode 100644 test/trap/ok/outrange-int16-negation.wasm-run.ok create mode 100644 test/trap/ok/outrange-int16-upper.run-ir.ok create mode 100644 test/trap/ok/outrange-int16-upper.run-low.ok create mode 100644 test/trap/ok/outrange-int16-upper.run.ok create mode 100644 test/trap/ok/outrange-int16-upper.wasm-run.ok create mode 100644 test/trap/ok/outrange-int32-lower.run-ir.ok create mode 100644 test/trap/ok/outrange-int32-lower.run-low.ok create mode 100644 test/trap/ok/outrange-int32-lower.run.ok create mode 100644 test/trap/ok/outrange-int32-lower.wasm-run.ok create mode 100644 test/trap/ok/outrange-int32-negation.run-ir.ok create mode 100644 test/trap/ok/outrange-int32-negation.run-low.ok create mode 100644 test/trap/ok/outrange-int32-negation.run.ok create mode 100644 test/trap/ok/outrange-int32-negation.wasm-run.ok create mode 100644 test/trap/ok/outrange-int32-upper.run-ir.ok create mode 100644 test/trap/ok/outrange-int32-upper.run-low.ok create mode 100644 test/trap/ok/outrange-int32-upper.run.ok create mode 100644 test/trap/ok/outrange-int32-upper.wasm-run.ok rename test/{fail/ok/outrange-int64lower.run-ir.ok => trap/ok/outrange-int64-lower.run-ir.ok} (100%) rename test/{fail/ok/outrange-int64lower.run-low.ok => trap/ok/outrange-int64-lower.run-low.ok} (100%) rename test/{fail/ok/outrange-int64lower.run.ok => trap/ok/outrange-int64-lower.run.ok} (100%) create mode 100644 test/trap/ok/outrange-int64-lower.wasm-run.ok create mode 100644 test/trap/ok/outrange-int64-negation.run-ir.ok create mode 100644 test/trap/ok/outrange-int64-negation.run-low.ok create mode 100644 test/trap/ok/outrange-int64-negation.run.ok create mode 100644 test/trap/ok/outrange-int64-negation.wasm-run.ok rename test/{fail/ok/outrange-int64upper.run-ir.ok => trap/ok/outrange-int64-upper.run-ir.ok} (100%) rename test/{fail/ok/outrange-int64upper.run-low.ok => trap/ok/outrange-int64-upper.run-low.ok} (100%) rename test/{fail/ok/outrange-int64upper.run.ok => trap/ok/outrange-int64-upper.run.ok} (100%) create mode 100644 test/trap/ok/outrange-int64-upper.wasm-run.ok rename test/{fail/ok/outrange-int8lower.run-ir.ok => trap/ok/outrange-int8-lower.run-ir.ok} (100%) rename test/{fail/ok/outrange-int8lower.run-low.ok => trap/ok/outrange-int8-lower.run-low.ok} (100%) rename test/{fail/ok/outrange-int8lower.run.ok => trap/ok/outrange-int8-lower.run.ok} (100%) create mode 100644 test/trap/ok/outrange-int8-lower.wasm-run.ok create mode 100644 test/trap/ok/outrange-int8-negation.run-ir.ok create mode 100644 test/trap/ok/outrange-int8-negation.run-low.ok create mode 100644 test/trap/ok/outrange-int8-negation.run.ok create mode 100644 test/trap/ok/outrange-int8-negation.wasm-run.ok rename test/{fail/ok/outrange-int8upper.run-ir.ok => trap/ok/outrange-int8-upper.run-ir.ok} (100%) rename test/{fail/ok/outrange-int8upper.run-low.ok => trap/ok/outrange-int8-upper.run-low.ok} (100%) rename test/{fail/ok/outrange-int8upper.run.ok => trap/ok/outrange-int8-upper.run.ok} (100%) create mode 100644 test/trap/ok/outrange-int8-upper.wasm-run.ok create mode 100644 test/trap/ok/outrange-nat16.run-ir.ok create mode 100644 test/trap/ok/outrange-nat16.run-low.ok create mode 100644 test/trap/ok/outrange-nat16.run.ok create mode 100644 test/trap/ok/outrange-nat16.wasm-run.ok create mode 100644 test/trap/ok/outrange-nat32.run-ir.ok create mode 100644 test/trap/ok/outrange-nat32.run-low.ok create mode 100644 test/trap/ok/outrange-nat32.run.ok create mode 100644 test/trap/ok/outrange-nat32.wasm-run.ok rename test/{fail => trap}/ok/outrange-nat64.run-ir.ok (100%) rename test/{fail => trap}/ok/outrange-nat64.run-low.ok (100%) rename test/{fail => trap}/ok/outrange-nat64.run.ok (100%) rename test/{fail => trap}/ok/outrange-nat64.wasm-run.ok (100%) rename test/{fail => trap}/ok/outrange-nat8.run-ir.ok (100%) rename test/{fail => trap}/ok/outrange-nat8.run-low.ok (100%) rename test/{fail => trap}/ok/outrange-nat8.run.ok (100%) rename test/{fail => trap}/ok/outrange-nat8.wasm-run.ok (100%) create mode 100644 test/trap/ok/subInt16-lower.run-ir.ok create mode 100644 test/trap/ok/subInt16-lower.run-low.ok create mode 100644 test/trap/ok/subInt16-lower.run.ok create mode 100644 test/trap/ok/subInt16-lower.wasm-run.ok create mode 100644 test/trap/ok/subInt16-upper.run-ir.ok create mode 100644 test/trap/ok/subInt16-upper.run-low.ok create mode 100644 test/trap/ok/subInt16-upper.run.ok create mode 100644 test/trap/ok/subInt16-upper.wasm-run.ok create mode 100644 test/trap/ok/subInt32-lower.run-ir.ok create mode 100644 test/trap/ok/subInt32-lower.run-low.ok create mode 100644 test/trap/ok/subInt32-lower.run.ok create mode 100644 test/trap/ok/subInt32-lower.wasm-run.ok create mode 100644 test/trap/ok/subInt32-upper.run-ir.ok create mode 100644 test/trap/ok/subInt32-upper.run-low.ok create mode 100644 test/trap/ok/subInt32-upper.run.ok create mode 100644 test/trap/ok/subInt32-upper.wasm-run.ok create mode 100644 test/trap/ok/subInt64-lower.run-ir.ok create mode 100644 test/trap/ok/subInt64-lower.run-low.ok create mode 100644 test/trap/ok/subInt64-lower.run.ok create mode 100644 test/trap/ok/subInt64-lower.wasm-run.ok create mode 100644 test/trap/ok/subInt64-upper.run-ir.ok create mode 100644 test/trap/ok/subInt64-upper.run-low.ok create mode 100644 test/trap/ok/subInt64-upper.run.ok create mode 100644 test/trap/ok/subInt64-upper.wasm-run.ok create mode 100644 test/trap/ok/subInt8-lower.run-ir.ok create mode 100644 test/trap/ok/subInt8-lower.run-low.ok create mode 100644 test/trap/ok/subInt8-lower.run.ok create mode 100644 test/trap/ok/subInt8-lower.wasm-run.ok create mode 100644 test/trap/ok/subInt8-upper.run-ir.ok create mode 100644 test/trap/ok/subInt8-upper.run-low.ok create mode 100644 test/trap/ok/subInt8-upper.run.ok create mode 100644 test/trap/ok/subInt8-upper.wasm-run.ok create mode 100644 test/trap/ok/subNat16.run-ir.ok create mode 100644 test/trap/ok/subNat16.run-low.ok create mode 100644 test/trap/ok/subNat16.run.ok create mode 100644 test/trap/ok/subNat16.wasm-run.ok create mode 100644 test/trap/ok/subNat32.run-ir.ok create mode 100644 test/trap/ok/subNat32.run-low.ok create mode 100644 test/trap/ok/subNat32.run.ok create mode 100644 test/trap/ok/subNat32.wasm-run.ok create mode 100644 test/trap/ok/subNat64.run-ir.ok create mode 100644 test/trap/ok/subNat64.run-low.ok create mode 100644 test/trap/ok/subNat64.run.ok create mode 100644 test/trap/ok/subNat64.wasm-run.ok create mode 100644 test/trap/ok/subNat8.run-ir.ok create mode 100644 test/trap/ok/subNat8.run-low.ok create mode 100644 test/trap/ok/subNat8.run.ok create mode 100644 test/trap/ok/subNat8.wasm-run.ok create mode 100644 test/trap/outrange-int16-lower.as create mode 100644 test/trap/outrange-int16-negation.as create mode 100644 test/trap/outrange-int16-upper.as create mode 100644 test/trap/outrange-int32-lower.as create mode 100644 test/trap/outrange-int32-negation.as create mode 100644 test/trap/outrange-int32-upper.as rename test/{fail/outrange-int64lower.as => trap/outrange-int64-lower.as} (100%) rename test/{fail/outrange-int64negation.as => trap/outrange-int64-negation.as} (100%) rename test/{fail/outrange-int64upper.as => trap/outrange-int64-upper.as} (100%) rename test/{fail/outrange-int8lower.as => trap/outrange-int8-lower.as} (100%) create mode 100644 test/trap/outrange-int8-negation.as rename test/{fail/outrange-int8upper.as => trap/outrange-int8-upper.as} (100%) create mode 100644 test/trap/outrange-nat16.as create mode 100644 test/trap/outrange-nat32.as rename test/{fail => trap}/outrange-nat64.as (100%) rename test/{fail => trap}/outrange-nat8.as (100%) create mode 100644 test/trap/subInt16-lower.as create mode 100644 test/trap/subInt16-upper.as create mode 100644 test/trap/subInt32-lower.as create mode 100644 test/trap/subInt32-upper.as create mode 100644 test/trap/subInt64-lower.as create mode 100644 test/trap/subInt64-upper.as create mode 100644 test/trap/subInt8-lower.as create mode 100644 test/trap/subInt8-upper.as create mode 100644 test/trap/subNat16.as create mode 100644 test/trap/subNat32.as create mode 100644 test/trap/subNat64.as create mode 100644 test/trap/subNat8.as diff --git a/src/as_values/operator.ml b/src/as_values/operator.ml index 57d2a324ab7..0aebd49aaa5 100644 --- a/src/as_values/operator.ml +++ b/src/as_values/operator.ml @@ -79,37 +79,45 @@ let text_binop ftext = function | T.Text -> fun v1 v2 -> Text (ftext (as_text v1) (as_text v2)) | _ -> raise (Invalid_argument "binop") -let word_binop fword8 fword16 fword32 fword64 = function +let word_binop (fword8, fword16, fword32, fword64) = function | T.Word8 -> fun v1 v2 -> Word8 (fword8 (as_word8 v1) (as_word8 v2)) | T.Word16 -> fun v1 v2 -> Word16 (fword16 (as_word16 v1) (as_word16 v2)) | T.Word32 -> fun v1 v2 -> Word32 (fword32 (as_word32 v1) (as_word32 v2)) | T.Word64 -> fun v1 v2 -> Word64 (fword64 (as_word64 v1) (as_word64 v2)) | _ -> raise (Invalid_argument "binop") -let num_binop fnat fint fword8 fword16 fword32 fword64 ffloat = function +let num_binop fnat (fnat8, fnat16, fnat32, fnat64) fint (fint8, fint16, fint32, fint64) fwords ffloat = function | T.Nat -> fun v1 v2 -> Int (fnat (as_int v1) (as_int v2)) + | T.Nat8 -> fun v1 v2 -> Nat8 (fnat8 (as_nat8 v1) (as_nat8 v2)) + | T.Nat16 -> fun v1 v2 -> Nat16 (fnat16 (as_nat16 v1) (as_nat16 v2)) + | T.Nat32 -> fun v1 v2 -> Nat32 (fnat32 (as_nat32 v1) (as_nat32 v2)) + | T.Nat64 -> fun v1 v2 -> Nat64 (fnat64 (as_nat64 v1) (as_nat64 v2)) | T.Int -> fun v1 v2 -> Int (fint (as_int v1) (as_int v2)) + | T.Int8 -> fun v1 v2 -> Int8 (fint8 (as_int8 v1) (as_int8 v2)) + | T.Int16 -> fun v1 v2 -> Int16 (fint16 (as_int16 v1) (as_int16 v2)) + | T.Int32 -> fun v1 v2 -> Int32 (fint32 (as_int32 v1) (as_int32 v2)) + | T.Int64 -> fun v1 v2 -> Int64 (fint64 (as_int64 v1) (as_int64 v2)) | T.Float -> fun v1 v2 -> Float (ffloat (as_float v1) (as_float v2)) - | t -> word_binop fword8 fword16 fword32 fword64 t + | t -> word_binop fwords t let binop t op = match t with | T.Prim p -> (match op with - | AddOp -> num_binop Nat.add Int.add Word8.add Word16.add Word32.add Word64.add Float.add p - | SubOp -> num_binop Nat.sub Int.sub Word8.sub Word16.sub Word32.sub Word64.sub Float.sub p - | MulOp -> num_binop Nat.mul Int.mul Word8.mul Word16.mul Word32.mul Word64.mul Float.mul p - | DivOp -> num_binop Nat.div Int.div Word8.div_u Word16.div_u Word32.div_u Word64.div_u Float.div p - | ModOp -> num_binop Nat.rem Int.rem Word8.rem_u Word16.rem_u Word32.rem_u Word64.rem_u Float.div p (* TBR *) - | PowOp -> num_binop Nat.pow Int.pow Word8.pow Word16.pow Word32.pow Word64.pow Float.pow p (* TBR *) - | AndOp -> word_binop Word8.and_ Word16.and_ Word32.and_ Word64.and_ p - | OrOp -> word_binop Word8.or_ Word16.or_ Word32.or_ Word64.or_ p - | XorOp -> word_binop Word8.xor Word16.xor Word32.xor Word64.xor p - | ShLOp -> word_binop Word8.shl Word16.shl Word32.shl Word64.shl p - | UShROp -> word_binop Word8.shr_u Word16.shr_u Word32.shr_u Word64.shr_u p - | SShROp -> word_binop Word8.shr_s Word16.shr_s Word32.shr_s Word64.shr_s p - | RotLOp -> word_binop Word8.rotl Word16.rotl Word32.rotl Word64.rotl p - | RotROp -> word_binop Word8.rotr Word16.rotr Word32.rotr Word64.rotr p + | AddOp -> num_binop Nat.add (Nat8.add, Nat16.add, Nat32.add, Nat64.add) Int.add (Int_8.add, Int_16.add, Int_32.add, Int_64.add) (Word8.add, Word16.add, Word32.add, Word64.add) Float.add p + | SubOp -> num_binop Nat.sub (Nat8.sub, Nat16.sub, Nat32.sub, Nat64.sub) Int.sub (Int_8.sub, Int_16.sub, Int_32.sub, Int_64.sub) (Word8.sub, Word16.sub, Word32.sub, Word64.sub) Float.sub p + | MulOp -> num_binop Nat.mul (Nat8.mul, Nat16.mul, Nat32.mul, Nat64.mul) Int.mul (Int_8.mul, Int_16.mul, Int_32.mul, Int_64.mul) (Word8.mul, Word16.mul, Word32.mul, Word64.mul) Float.mul p + | DivOp -> num_binop Nat.div (Nat8.div, Nat16.div, Nat32.div, Nat64.div) Int.div (Int_8.div, Int_16.div, Int_32.div, Int_64.div) (Word8.div_u, Word16.div_u, Word32.div_u, Word64.div_u) Float.div p + | ModOp -> num_binop Nat.rem (Nat8.rem, Nat16.rem, Nat32.rem, Nat64.rem) Int.rem (Int_8.rem, Int_16.rem, Int_32.rem, Int_64.rem) (Word8.rem_u, Word16.rem_u, Word32.rem_u, Word64.rem_u) Float.div p (* TBR *) + | PowOp -> num_binop Nat.pow (Nat8.pow, Nat16.pow, Nat32.pow, Nat64.pow) Int.pow (Int_8.pow, Int_16.pow, Int_32.pow, Int_64.pow) (Word8.pow, Word16.pow, Word32.pow, Word64.pow) Float.pow p (* TBR *) + | AndOp -> word_binop (Word8.and_, Word16.and_, Word32.and_, Word64.and_) p + | OrOp -> word_binop (Word8.or_, Word16.or_, Word32.or_, Word64.or_) p + | XorOp -> word_binop (Word8.xor, Word16.xor, Word32.xor, Word64.xor) p + | ShLOp -> word_binop (Word8.shl, Word16.shl, Word32.shl, Word64.shl) p + | UShROp -> word_binop (Word8.shr_u, Word16.shr_u, Word32.shr_u, Word64.shr_u) p + | SShROp -> word_binop (Word8.shr_s, Word16.shr_s, Word32.shr_s, Word64.shr_s) p + | RotLOp -> word_binop (Word8.rotl, Word16.rotl, Word32.rotl, Word64.rotl) p + | RotROp -> word_binop (Word8.rotr, Word16.rotr, Word32.rotr, Word64.rotr) p | CatOp -> text_binop (^) p ) | T.Non -> impossible @@ -125,8 +133,12 @@ let word_relop (fword8, fword16, fword32, fword64) = function | T.Word64 -> fun v1 v2 -> Bool (fword64 (as_word64 v1) (as_word64 v2)) | _ -> raise (Invalid_argument "relop") -let num_relop fnat fint (fint8, fint16, fint32, fint64) fwords ffloat = function +let num_relop fnat (fnat8, fnat16, fnat32, fnat64) fint (fint8, fint16, fint32, fint64) fwords ffloat = function | T.Nat -> fun v1 v2 -> Bool (fnat (as_int v1) (as_int v2)) + | T.Nat8 -> fun v1 v2 -> Bool (fnat8 (as_nat8 v1) (as_nat8 v2)) + | T.Nat16 -> fun v1 v2 -> Bool (fnat16 (as_nat16 v1) (as_nat16 v2)) + | T.Nat32 -> fun v1 v2 -> Bool (fnat32 (as_nat32 v1) (as_nat32 v2)) + | T.Nat64 -> fun v1 v2 -> Bool (fnat64 (as_nat64 v1) (as_nat64 v2)) | T.Int -> fun v1 v2 -> Bool (fint (as_int v1) (as_int v2)) | T.Int8 -> fun v1 v2 -> Bool (fint8 (as_int8 v1) (as_int8 v2)) | T.Int16 -> fun v1 v2 -> Bool (fint16 (as_int16 v1) (as_int16 v2)) @@ -135,26 +147,26 @@ let num_relop fnat fint (fint8, fint16, fint32, fint64) fwords ffloat = function | T.Float -> fun v1 v2 -> Bool (ffloat (as_float v1) (as_float v2)) | t -> word_relop fwords t -let ord_relop fnat fint fints fwords ffloat fchar ftext = function +let ord_relop fnat fnats fint fints fwords ffloat fchar ftext = function | T.Char -> fun v1 v2 -> Bool (fchar (as_char v1) (as_char v2)) | T.Text -> fun v1 v2 -> Bool (ftext (as_text v1) (as_text v2)) - | t -> num_relop fnat fint fints fwords ffloat t + | t -> num_relop fnat fnats fint fints fwords ffloat t -let eq_relop fnat fint fints fwords ffloat fchar ftext fnull fbool = function +let eq_relop fnat fnats fint fints fwords ffloat fchar ftext fnull fbool = function | T.Null -> fun v1 v2 -> Bool (fnull (as_null v1) (as_null v2)) | T.Bool -> fun v1 v2 -> Bool (fbool (as_bool v1) (as_bool v2)) - | t -> ord_relop fnat fint fints fwords ffloat fchar ftext t + | t -> ord_relop fnat fnats fint fints fwords ffloat fchar ftext t let relop t op = match t with | T.Prim p -> (match op with - | EqOp -> eq_relop Nat.eq Int.eq (Int_8.eq, Int_16.eq, Int_32.eq, Int_64.eq) (Word8.eq, Word16.eq, Word32.eq, Word64.eq) Float.eq (=) (=) (=) (=) p - | NeqOp -> eq_relop Nat.ne Int.ne (Int_8.ne, Int_16.ne, Int_32.ne, Int_64.ne) (Word8.ne, Word16.ne, Word32.ne, Word64.ne) Float.ne (<>) (<>) (<>) (<>) p - | LtOp -> ord_relop Nat.lt Int.lt (Int_8.lt, Int_16.lt, Int_32.lt, Int_64.lt) (Word8.lt_u, Word16.lt_u, Word32.lt_u, Word64.lt_u) Float.lt (<) (<) p - | GtOp -> ord_relop Nat.gt Int.gt (Int_8.gt, Int_16.gt, Int_32.gt, Int_64.gt) (Word8.gt_u, Word16.gt_u, Word32.gt_u, Word64.gt_u) Float.gt (>) (>) p - | LeOp -> ord_relop Nat.le Int.le (Int_8.le, Int_16.le, Int_32.le, Int_64.le) (Word8.le_u, Word16.le_u, Word32.le_u, Word64.le_u) Float.le (<=) (<=) p - | GeOp -> ord_relop Nat.ge Int.ge (Int_8.ge, Int_16.ge, Int_32.ge, Int_64.ge) (Word8.ge_u, Word16.ge_u, Word32.ge_u, Word64.ge_u) Float.ge (>=) (>=) p + | EqOp -> eq_relop Nat.eq (Nat8.eq, Nat16.eq, Nat32.eq, Nat64.eq) Int.eq (Int_8.eq, Int_16.eq, Int_32.eq, Int_64.eq) (Word8.eq, Word16.eq, Word32.eq, Word64.eq) Float.eq (=) (=) (=) (=) p + | NeqOp -> eq_relop Nat.ne (Nat8.ne, Nat16.ne, Nat32.ne, Nat64.ne) Int.ne (Int_8.ne, Int_16.ne, Int_32.ne, Int_64.ne) (Word8.ne, Word16.ne, Word32.ne, Word64.ne) Float.ne (<>) (<>) (<>) (<>) p + | LtOp -> ord_relop Nat.lt (Nat8.lt, Nat16.lt, Nat32.lt, Nat64.lt) Int.lt (Int_8.lt, Int_16.lt, Int_32.lt, Int_64.lt) (Word8.lt_u, Word16.lt_u, Word32.lt_u, Word64.lt_u) Float.lt (<) (<) p + | GtOp -> ord_relop Nat.gt (Nat8.gt, Nat16.gt, Nat32.gt, Nat64.gt) Int.gt (Int_8.gt, Int_16.gt, Int_32.gt, Int_64.gt) (Word8.gt_u, Word16.gt_u, Word32.gt_u, Word64.gt_u) Float.gt (>) (>) p + | LeOp -> ord_relop Nat.le (Nat8.le, Nat16.le, Nat32.le, Nat64.le) Int.le (Int_8.le, Int_16.le, Int_32.le, Int_64.le) (Word8.le_u, Word16.le_u, Word32.le_u, Word64.le_u) Float.le (<=) (<=) p + | GeOp -> ord_relop Nat.ge (Nat8.ge, Nat16.ge, Nat32.ge, Nat64.ge) Int.ge (Int_8.ge, Int_16.ge, Int_32.ge, Int_64.ge) (Word8.ge_u, Word16.ge_u, Word32.ge_u, Word64.ge_u) Float.ge (>=) (>=) p ) | T.Non -> impossible | _ -> raise (Invalid_argument "relop") diff --git a/src/as_values/value.ml b/src/as_values/value.ml index 2559e19b662..47217cf6458 100644 --- a/src/as_values/value.ml +++ b/src/as_values/value.ml @@ -212,6 +212,7 @@ struct let neg a = let res = Rep.neg a in check res let abs a = let res = Rep.abs a in check res let add a b = let res = Rep.add a b in check res + let sub a b = let res = Rep.sub a b in check res let mul a b = let res = Rep.mul a b in check res let div a b = let res = Rep.div a b in check res let pow a b = let res = Rep.pow a b in check res diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index e96d3aa61a3..ad466cec5e4 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -370,6 +370,8 @@ let compile_mul_const = compile_op_const I32Op.Mul let compile_divU_const = compile_op_const I32Op.DivU let compile_shrU_const = function | 0l -> G.nop | n -> compile_op_const I32Op.ShrU n +let compile_shrS_const = function + | 0l -> G.nop | n -> compile_op_const I32Op.ShrS n let compile_shl_const = function | 0l -> G.nop | n -> compile_op_const I32Op.Shl n let compile_bitand_const = compile_op_const I32Op.And @@ -1313,7 +1315,8 @@ module UnboxedSmallWord = struct (* Makes sure that the word payload (e.g. shift/rotate amount) is in the LSB bits of the word. *) let lsb_adjust = function | Type.(Int32|Nat32|Word32) -> G.nop - | Type.(Int8|Nat8|Word8|Int16|Nat16|Word16) as ty -> compile_shrU_const (shift_of_type ty) + | Type.(Nat8|Word8|Nat16|Word16) as ty -> compile_shrU_const (shift_of_type ty) + | Type.(Int8|Int16) as ty -> compile_shrS_const (shift_of_type ty) | _ -> assert false (* Makes sure that the word payload (e.g. operation result) is in the MSB bits of the word. *) @@ -1718,8 +1721,6 @@ module BigNum = BigNumLibtommmath (* Primitive functions *) module Prim = struct - open Wasm.Values - (* The Word8 and Word16 bits sit in the MSBs of the i32, in this manner we can perform almost all operations, with the exception of - Mul (needs shr of one operand) @@ -1736,8 +1737,7 @@ module Prim = struct prim_word32toNat env let prim_word32toInt env = BigNum.from_signed_word32 env let prim_shiftWordNtoSigned env b = - compile_unboxed_const b ^^ - G.i (Binary (I32 I32Op.ShrS)) ^^ + compile_shrS_const b ^^ prim_word32toInt env let prim_intToWord32 env = BigNum.truncate_to_word32 env let prim_shiftToWordN env b = @@ -4408,6 +4408,10 @@ let prim_of_typ ty = match Type.normalize ty with | Type.Prim ty -> ty | _ -> assert false +(* helper, traps with message *) +let then_arithmetic_overflow env = + E.then_trap_with env "arithmetic overflow" + let compile_unop env t op = let open Operator in match op, t with @@ -4427,7 +4431,7 @@ let compile_unop env t op = get_n ^^ compile_const_64 0x8000000000000000L ^^ G.i (Compare (Wasm.Values.I64 I64Op.Eq)) ^^ - E.then_trap_with env "arithmetic overflow" ^^ + then_arithmetic_overflow env ^^ compile_const_64 0L ^^ get_n ^^ G.i (Binary (Wasm.Values.I64 I64Op.Sub)) @@ -4444,7 +4448,7 @@ let compile_unop env t op = Func.share_code1 env "neg32_trap" ("n", I32Type) [I32Type] (fun env get_n -> get_n ^^ compile_eq_const 0x80000000l ^^ - E.then_trap_with env "arithmetic overflow" ^^ + then_arithmetic_overflow env ^^ compile_unboxed_zero ^^ get_n ^^ G.i (Binary (Wasm.Values.I32 I32Op.Sub)) @@ -4461,6 +4465,115 @@ let compile_unop env t op = `compile_exp_as`, which does not take SR.Unreachable. *) todo "compile_unop" (Arrange_ops.unop op) (SR.Vanilla, E.trap_with env "TODO: compile_unop") +(* Compiling Int/Nat64 ops by conversion to/from BigNum. This is currently + consing a lot, but compact bignums will get back efficiency as soon as + they are merged. *) + +(* helper, traps with message *) +let else_arithmetic_overflow env = + E.else_trap_with env "arithmetic overflow" + +let compile_Int64_kernel env name op = + Func.share_code2 env (UnboxedSmallWord.name_of_type Type.Int64 name) + (("a", I64Type), ("b", I64Type)) [I64Type] + BigNum.(fun env get_a get_b -> + let (set_res, get_res) = new_local env "res" in + get_a ^^ from_signed_word64 env ^^ + get_b ^^ from_signed_word64 env ^^ + op env ^^ + set_res ^^ get_res ^^ + fits_signed_bits env 64 ^^ + else_arithmetic_overflow env ^^ + get_res ^^ BigNum.truncate_to_word64 env) + +let compile_Nat64_kernel env name op = + Func.share_code2 env (UnboxedSmallWord.name_of_type Type.Nat64 name) + (("a", I64Type), ("b", I64Type)) [I64Type] + BigNum.(fun env get_a get_b -> + let (set_res, get_res) = new_local env "res" in + get_a ^^ from_word64 env ^^ + get_b ^^ from_word64 env ^^ + op env ^^ + set_res ^^ get_res ^^ + fits_unsigned_bits env 64 ^^ + else_arithmetic_overflow env ^^ + get_res ^^ BigNum.truncate_to_word64 env) + +(* Compiling Int/Nat32 ops by conversion to/from i64. *) + +(* helper, expects i64 on stack *) +let enforce_32_unsigned_bits env = + compile_const_64 0xFFFFFFFF00000000L ^^ + G.i (Binary (Wasm.Values.I64 I64Op.And)) ^^ + G.i (Test (Wasm.Values.I64 I64Op.Eqz)) ^^ + else_arithmetic_overflow env + +(* helper, expects two identical i64s on stack *) +let enforce_32_signed_bits env = + compile_const_64 1L ^^ G.i (Binary (Wasm.Values.I64 I64Op.Shl)) ^^ + G.i (Binary (Wasm.Values.I64 I64Op.Xor)) ^^ + enforce_32_unsigned_bits env + +let compile_Int32_kernel env name op = + Func.share_code2 env (UnboxedSmallWord.name_of_type Type.Int32 name) + (("a", I32Type), ("b", I32Type)) [I32Type] + (fun env get_a get_b -> + let (set_res, get_res) = new_local64 env "res" in + get_a ^^ G.i (Convert (Wasm.Values.I64 I64Op.ExtendSI32)) ^^ + get_b ^^ G.i (Convert (Wasm.Values.I64 I64Op.ExtendSI32)) ^^ + G.i (Binary (Wasm.Values.I64 op)) ^^ + set_res ^^ get_res ^^ get_res ^^ + enforce_32_signed_bits env ^^ + get_res ^^ G.i (Convert (Wasm.Values.I32 I32Op.WrapI64))) + +let compile_Nat32_kernel env name op = + Func.share_code2 env (UnboxedSmallWord.name_of_type Type.Nat32 name) + (("a", I32Type), ("b", I32Type)) [I32Type] + (fun env get_a get_b -> + let (set_res, get_res) = new_local64 env "res" in + get_a ^^ G.i (Convert (Wasm.Values.I64 I64Op.ExtendUI32)) ^^ + get_b ^^ G.i (Convert (Wasm.Values.I64 I64Op.ExtendUI32)) ^^ + G.i (Binary (Wasm.Values.I64 op)) ^^ + set_res ^^ get_res ^^ + enforce_32_unsigned_bits env ^^ + get_res ^^ G.i (Convert (Wasm.Values.I32 I32Op.WrapI64))) + +(* Customisable kernels for 8/16bit arithmetic via 32 bits. *) + +(* helper, expects i32 on stack *) +let enforce_16_unsigned_bits env = + compile_bitand_const 0xFFFF0000l ^^ + then_arithmetic_overflow env + +(* helper, expects two identical i32s on stack *) +let enforce_16_signed_bits env = + compile_shl_const 1l ^^ G.i (Binary (Wasm.Values.I32 I32Op.Xor)) ^^ + enforce_16_unsigned_bits env + +let compile_smallInt_kernel env ty name op = + Func.share_code2 env (UnboxedSmallWord.name_of_type ty name) + (("a", I32Type), ("b", I32Type)) [I32Type] + (fun env get_a get_b -> + let (set_res, get_res) = new_local env "res" in + get_a ^^ compile_shrS_const 16l ^^ + get_b ^^ compile_shrS_const 16l ^^ + G.i (Binary (Wasm.Values.I32 op)) ^^ + set_res ^^ get_res ^^ get_res ^^ + enforce_16_signed_bits env ^^ + get_res ^^ compile_shl_const 16l) + +let compile_smallNat_kernel env ty name op = + Func.share_code2 env (UnboxedSmallWord.name_of_type ty name) + (("a", I32Type), ("b", I32Type)) [I32Type] + (fun env get_a get_b -> + let (set_res, get_res) = new_local env "res" in + get_a ^^ compile_shrU_const 16l ^^ + get_b ^^ compile_shrU_const 16l ^^ + G.i (Binary (Wasm.Values.I32 op)) ^^ + set_res ^^ get_res ^^ + enforce_16_unsigned_bits env ^^ + get_res ^^ compile_shl_const 16l) + (* This returns a single StackRep, to be used for both arguments and the result. One could imagine operators that require or produce different StackReps, but none of these do, so a single value is fine. @@ -4470,25 +4583,88 @@ let rec compile_binop env t op = Operator.(match t, op with | Type.(Prim (Nat | Int)), AddOp -> BigNum.compile_add env | Type.(Prim Word64), AddOp -> G.i (Binary (Wasm.Values.I64 I64Op.Add)) + | Type.(Prim Int64), AddOp -> compile_Int64_kernel env "add" BigNum.compile_add + | Type.(Prim Nat64), AddOp -> compile_Nat64_kernel env "add" BigNum.compile_add | Type.(Prim Nat), SubOp -> BigNum.compile_unsigned_sub env | Type.(Prim Int), SubOp -> BigNum.compile_signed_sub env | Type.(Prim (Nat | Int)), MulOp -> BigNum.compile_mul env | Type.(Prim Word64), MulOp -> G.i (Binary (Wasm.Values.I64 I64Op.Mul)) - | Type.(Prim Word64), DivOp -> G.i (Binary (Wasm.Values.I64 I64Op.DivU)) - | Type.(Prim Word64), ModOp -> G.i (Binary (Wasm.Values.I64 I64Op.RemU)) + | Type.(Prim Int64), MulOp -> compile_Int64_kernel env "mul" BigNum.compile_mul + | Type.(Prim Nat64), MulOp -> compile_Nat64_kernel env "mul" BigNum.compile_mul + | Type.(Prim (Nat64|Word64)), DivOp -> G.i (Binary (Wasm.Values.I64 I64Op.DivU)) + | Type.(Prim (Nat64|Word64)), ModOp -> G.i (Binary (Wasm.Values.I64 I64Op.RemU)) + | Type.(Prim Int64), DivOp -> G.i (Binary (Wasm.Values.I64 I64Op.DivS)) + | Type.(Prim Int64), ModOp -> G.i (Binary (Wasm.Values.I64 I64Op.RemS)) | Type.(Prim Nat), DivOp -> BigNum.compile_unsigned_div env | Type.(Prim Nat), ModOp -> BigNum.compile_unsigned_rem env | Type.(Prim Word64), SubOp -> G.i (Binary (Wasm.Values.I64 I64Op.Sub)) + | Type.(Prim Int64), SubOp -> compile_Int64_kernel env "sub" BigNum.compile_signed_sub + | Type.(Prim Nat64), SubOp -> compile_Nat64_kernel env "sub" BigNum.compile_unsigned_sub | Type.(Prim Int), DivOp -> BigNum.compile_signed_div env | Type.(Prim Int), ModOp -> BigNum.compile_signed_mod env | Type.Prim Type.(Word8 | Word16 | Word32), AddOp -> G.i (Binary (Wasm.Values.I32 I32Op.Add)) + | Type.(Prim Int32), AddOp -> compile_Int32_kernel env "add" I64Op.Add + | Type.Prim Type.(Int8 | Int16 as ty), AddOp -> compile_smallInt_kernel env ty "add" I32Op.Add + | Type.(Prim Nat32), AddOp -> compile_Nat32_kernel env "add" I64Op.Add + | Type.Prim Type.(Nat8 | Nat16 as ty), AddOp -> compile_smallNat_kernel env ty "add" I32Op.Add | Type.Prim Type.(Word8 | Word16 | Word32), SubOp -> G.i (Binary (Wasm.Values.I32 I32Op.Sub)) + | Type.(Prim Int32), SubOp -> compile_Int32_kernel env "sub" I64Op.Sub + | Type.(Prim (Int8|Int16 as ty)), SubOp -> compile_smallInt_kernel env ty "sub" I32Op.Sub + | Type.(Prim Nat32), SubOp -> compile_Nat32_kernel env "sub" I64Op.Sub + | Type.(Prim (Nat8|Nat16 as ty)), SubOp -> compile_smallNat_kernel env ty "sub" I32Op.Sub | Type.(Prim (Word8|Word16|Word32 as ty)), MulOp -> UnboxedSmallWord.lsb_adjust ty ^^ G.i (Binary (Wasm.Values.I32 I32Op.Mul)) - | Type.(Prim (Word8|Word16|Word32 as ty)), DivOp -> G.i (Binary (Wasm.Values.I32 I32Op.DivU)) ^^ - UnboxedSmallWord.msb_adjust ty - | Type.Prim Type.(Word8 | Word16 | Word32), ModOp -> G.i (Binary (Wasm.Values.I32 I32Op.RemU)) + | Type.(Prim Int32), MulOp -> compile_Int32_kernel env "mul" I64Op.Mul + | Type.(Prim Int16), MulOp -> compile_smallInt_kernel env Type.Int16 "mul" I32Op.Mul + | Type.(Prim Int8), MulOp -> + Func.share_code2 env (UnboxedSmallWord.name_of_type Type.Int8 "mul") + (("a", I32Type), ("b", I32Type)) [I32Type] + (fun env get_a get_b -> + let (set_res, get_res) = new_local env "res" in + get_a ^^ compile_shrS_const 24l ^^ + get_b ^^ compile_shrS_const 24l ^^ + G.i (Binary (Wasm.Values.I32 I32Op.Mul)) ^^ + set_res ^^ get_res ^^ get_res ^^ compile_shl_const 1l ^^ G.i (Binary (Wasm.Values.I32 I32Op.Xor)) ^^ + compile_bitand_const 0xFFFFFF00l ^^ + then_arithmetic_overflow env ^^ + get_res ^^ compile_shl_const 24l) + | Type.(Prim Nat32), MulOp -> compile_Nat32_kernel env "mul" I64Op.Mul + | Type.(Prim Nat16), MulOp -> compile_smallNat_kernel env Type.Nat16 "mul" I32Op.Mul + | Type.(Prim Nat8), MulOp -> + Func.share_code2 env (UnboxedSmallWord.name_of_type Type.Nat8 "mul") + (("a", I32Type), ("b", I32Type)) [I32Type] + (fun env get_a get_b -> + let (set_res, get_res) = new_local env "res" in + get_a ^^ compile_shrU_const 24l ^^ + get_b ^^ compile_shrU_const 24l ^^ + G.i (Binary (Wasm.Values.I32 I32Op.Mul)) ^^ + set_res ^^ get_res ^^ compile_bitand_const 0xFFFFFF00l ^^ + then_arithmetic_overflow env ^^ + get_res ^^ compile_shl_const 24l) + + | Type.(Prim (Nat8|Nat16|Nat32|Word8|Word16|Word32 as ty)), DivOp -> + G.i (Binary (Wasm.Values.I32 I32Op.DivU)) ^^ + UnboxedSmallWord.msb_adjust ty + | Type.(Prim (Nat8|Nat16|Nat32|Word8|Word16|Word32)), ModOp -> G.i (Binary (Wasm.Values.I32 I32Op.RemU)) + | Type.(Prim Int32), DivOp -> G.i (Binary (Wasm.Values.I32 I32Op.DivS)) + | Type.(Prim (Int8|Int16 as ty)), DivOp -> + Func.share_code2 env (UnboxedSmallWord.name_of_type ty "div") + (("a", I32Type), ("b", I32Type)) [I32Type] + (fun env get_a get_b -> + let (set_res, get_res) = new_local env "res" in + get_a ^^ get_b ^^ G.i (Binary (Wasm.Values.I32 I32Op.DivS)) ^^ + UnboxedSmallWord.msb_adjust ty ^^ set_res ^^ + get_a ^^ compile_eq_const 0x80000000l ^^ + G.if_ (StackRep.to_block_type env SR.UnboxedWord32) + begin + get_b ^^ UnboxedSmallWord.lsb_adjust ty ^^ compile_eq_const (-1l) ^^ + G.if_ (StackRep.to_block_type env SR.UnboxedWord32) + (G.i Unreachable) + get_res + end + get_res) + | Type.(Prim (Int8|Int16|Int32)), ModOp -> G.i (Binary (Wasm.Values.I32 I32Op.RemS)) | Type.(Prim (Word8|Word16|Word32 as ty)), PowOp -> let rec pow () = Func.share_code2 env (UnboxedSmallWord.name_of_type ty "pow") (("n", I32Type), ("exp", I32Type)) [I32Type] @@ -4510,14 +4686,22 @@ let rec compile_binop env t op = mul))) in pow () | Type.(Prim Int), PowOp -> - let pow = BigNum.compile_unsigned_pow env in - let (set_n, get_n) = new_local env "n" in - let (set_exp, get_exp) = new_local env "exp" in - set_exp ^^ set_n ^^ - get_exp ^^ BigNum.compile_is_negative env ^^ - E.then_trap_with env "negative power" ^^ - get_n ^^ get_exp ^^ pow + let pow = BigNum.compile_unsigned_pow env in + let (set_n, get_n) = new_local env "n" in + let (set_exp, get_exp) = new_local env "exp" in + set_exp ^^ set_n ^^ + get_exp ^^ BigNum.compile_is_negative env ^^ + E.then_trap_with env "negative power" ^^ + get_n ^^ get_exp ^^ pow | Type.(Prim Word64), PowOp -> BoxedWord64.compile_unsigned_pow env + | Type.(Prim Int64), PowOp -> + let (set_exp, get_exp) = new_local64 env "exp" in + set_exp ^^ get_exp ^^ + compile_const_64 0L ^^ + G.i (Compare (Wasm.Values.I64 I64Op.LtS)) ^^ + E.then_trap_with env "negative power" ^^ + get_exp ^^ compile_Int64_kernel env "pow" BigNum.compile_unsigned_pow + | Type.(Prim Nat64), PowOp -> compile_Nat64_kernel env "pow" BigNum.compile_unsigned_pow | Type.(Prim Nat), PowOp -> BigNum.compile_unsigned_pow env | Type.(Prim Word64), AndOp -> G.i (Binary (Wasm.Values.I64 I64Op.And)) | Type.Prim Type.(Word8 | Word16 | Word32), AndOp -> G.i (Binary (Wasm.Values.I32 I32Op.And)) diff --git a/test/Makefile b/test/Makefile index b269a546ef2..a349d1fd5c0 100644 --- a/test/Makefile +++ b/test/Makefile @@ -5,6 +5,7 @@ all: $(MAKE) -C repl $(MAKE) -C ld $(MAKE) -C idl + $(MAKE) -C trap MAKE_PAR := $(MAKE) --no-print-directory --load-average -j $(shell getconf _NPROCESSORS_ONLN) --keep-going @@ -17,6 +18,7 @@ quick: parallel: quick $(MAKE_PAR) -C run-dfinity quick + $(MAKE_PAR) -C trap quick coverage: rm -rf _coverage @@ -38,6 +40,8 @@ accept: $(MAKE) -C repl accept $(MAKE) -C ld accept $(MAKE) -C idl accept + $(MAKE) -C trap accept + $(MAKE) -C trap check clean: $(MAKE) -C fail clean @@ -46,5 +50,6 @@ clean: $(MAKE) -C repl clean $(MAKE) -C ld clean $(MAKE) -C idl clean + $(MAKE) -C trap clean .PHONY: coverage diff --git a/test/fail/ok/outrange-int64lower.wasm-run.ok b/test/fail/ok/outrange-int64lower.wasm-run.ok deleted file mode 100644 index a87edfdf573..00000000000 --- a/test/fail/ok/outrange-int64lower.wasm-run.ok +++ /dev/null @@ -1 +0,0 @@ -_out/outrange-int64lower.wasm:0x___: runtime trap: unreachable executed diff --git a/test/fail/ok/outrange-int64negation.run-ir.ok b/test/fail/ok/outrange-int64negation.run-ir.ok deleted file mode 100644 index 01c2fd0b1c4..00000000000 --- a/test/fail/ok/outrange-int64negation.run-ir.ok +++ /dev/null @@ -1 +0,0 @@ -outrange-int64negation.as:1.9-1.33: execution error, value out of bounds diff --git a/test/fail/ok/outrange-int64negation.run-low.ok b/test/fail/ok/outrange-int64negation.run-low.ok deleted file mode 100644 index 01c2fd0b1c4..00000000000 --- a/test/fail/ok/outrange-int64negation.run-low.ok +++ /dev/null @@ -1 +0,0 @@ -outrange-int64negation.as:1.9-1.33: execution error, value out of bounds diff --git a/test/fail/ok/outrange-int64negation.run.ok b/test/fail/ok/outrange-int64negation.run.ok deleted file mode 100644 index 01c2fd0b1c4..00000000000 --- a/test/fail/ok/outrange-int64negation.run.ok +++ /dev/null @@ -1 +0,0 @@ -outrange-int64negation.as:1.9-1.33: execution error, value out of bounds diff --git a/test/fail/ok/outrange-int64negation.wasm-run.ok b/test/fail/ok/outrange-int64negation.wasm-run.ok deleted file mode 100644 index 4db5b575d1b..00000000000 --- a/test/fail/ok/outrange-int64negation.wasm-run.ok +++ /dev/null @@ -1 +0,0 @@ -_out/outrange-int64negation.wasm:0x___: runtime trap: unreachable executed diff --git a/test/fail/ok/outrange-int64upper.wasm-run.ok b/test/fail/ok/outrange-int64upper.wasm-run.ok deleted file mode 100644 index 6ec234a4e85..00000000000 --- a/test/fail/ok/outrange-int64upper.wasm-run.ok +++ /dev/null @@ -1 +0,0 @@ -_out/outrange-int64upper.wasm:0x___: runtime trap: unreachable executed diff --git a/test/fail/ok/outrange-int8lower.wasm-run.ok b/test/fail/ok/outrange-int8lower.wasm-run.ok deleted file mode 100644 index 054470b6319..00000000000 --- a/test/fail/ok/outrange-int8lower.wasm-run.ok +++ /dev/null @@ -1 +0,0 @@ -_out/outrange-int8lower.wasm:0x___: runtime trap: unreachable executed diff --git a/test/fail/ok/outrange-int8upper.wasm-run.ok b/test/fail/ok/outrange-int8upper.wasm-run.ok deleted file mode 100644 index 2d769f0989f..00000000000 --- a/test/fail/ok/outrange-int8upper.wasm-run.ok +++ /dev/null @@ -1 +0,0 @@ -_out/outrange-int8upper.wasm:0x___: runtime trap: unreachable executed diff --git a/test/run/numeric-ops.as b/test/run/numeric-ops.as index 67cfa38a61f..c45a72839cd 100644 --- a/test/run/numeric-ops.as +++ b/test/run/numeric-ops.as @@ -215,7 +215,7 @@ func testInt64(a : Int64, b : Int64) : [Int64] { let pos2 = (+ a) : Int64; let neg1 = - a; let neg2 = (- a) : Int64; - /*let sum1 = a + b; + let sum1 = a + b; let sum2 = (a + b) : Int64; let diff1 = a - b; let diff2 = (a - b) : Int64; @@ -225,13 +225,86 @@ func testInt64(a : Int64, b : Int64) : [Int64] { let rat2 = (a / b) : Int64; let mod1 = a % b; let mod2 = (a % b) : Int64; - let pow1 = a ** b; - let pow2 = (a ** b) : Int64;*/ - [pos1, pos2, neg1, neg2, /*sum1, sum2, diff1, diff2, prod1, prod2, rat1, rat2, mod1, mod2, pow1, pow2*/] + if (b >= (0 : Int64)) + { + let pow1 = a ** b; + let pow2 = (a ** b) : Int64; + [pos1, pos2, neg1, neg2, sum1, sum2, diff1, diff2, prod1, prod2, rat1, rat2, mod1, mod2, pow1, pow2] + } + else + { + [pos1, pos2, neg1, neg2, sum1, sum2, diff1, diff2, prod1, prod2, rat1, rat2, mod1, mod2] + } +}; + +func int64Compare(a : Int64, b : Int64) : Bool = a == b; + +verify([3, -3, 8, -2, 15, 0, 3, 243], testInt64(3, 5), + int64Compare); +verify([13, -13, 18, 8, 65, 2, 3, 371293], testInt64(13, 5), + int64Compare); +verify([-13, 13, -18, -8, 65, 2, -3], testInt64(-13, -5), + int64Compare); + + +func testInt32(a : Int32, b : Int32) : [Int32] { + let pos1 = + a; + let pos2 = (+ a) : Int32; + let neg1 = - a; + let neg2 = (- a) : Int32; + let sum1 = a + b; + let sum2 = (a + b) : Int32; + let diff1 = a - b; + let diff2 = (a - b) : Int32; + let prod1 = a * b; + let prod2 = (a * b) : Int32; + let rat1 = a / b; + let rat2 = (a / b) : Int32; + let mod1 = a % b; + let mod2 = (a % b) : Int32; + /*let pow1 = a ** b; + let pow2 = (a ** b) : Int32;*/ + [pos1, pos2, neg1, neg2, sum1, sum2, diff1, diff2, prod1, prod2, rat1, rat2, mod1, mod2/*, pow1, pow2*/] +}; + +func int32Compare(a : Int32, b : Int32) : Bool = a == b; + +verify([3, -3, 8, -2, 15, 0, 3/*, 243*/], testInt32(3, 5), + int32Compare); +verify([13, -13, 18, 8, 65, 2, 3/*, 243*/], testInt32(13, 5), + int32Compare); +verify([-13, 13, -18, -8, 65, 2, -3/*, 243*/], testInt32(-13, -5), + int32Compare); + + +func testInt16(a : Int16, b : Int16) : [Int16] { + let pos1 = + a; + let pos2 = (+ a) : Int16; + let neg1 = - a; + let neg2 = (- a) : Int16; + let sum1 = a + b; + let sum2 = (a + b) : Int16; + let diff1 = a - b; + let diff2 = (a - b) : Int16; + let prod1 = a * b; + let prod2 = (a * b) : Int16; + let rat1 = a / b; + let rat2 = (a / b) : Int16; + let mod1 = a % b; + let mod2 = (a % b) : Int16; + /*let pow1 = a ** b; + let pow2 = (a ** b) : Int16;*/ + [pos1, pos2, neg1, neg2, sum1, sum2, diff1, diff2, prod1, prod2, rat1, rat2, mod1, mod2/*, pow1, pow2*/] }; -verify([3, -3/*, 8, 18_446_744_073_709_551_614, 15, 0, 3, 243*/], testInt64(3, 5), - func (a : Int64, b : Int64) : Bool = a == b); +func int16Compare(a : Int16, b : Int16) : Bool = a == b; + +verify([3, -3, 8, -2, 15, 0, 3/*, 243*/], testInt16(3, 5), + int16Compare); +verify([13, -13, 18, 8, 65, 2, 3/*, 243*/], testInt16(13, 5), + int16Compare); +verify([-13, 13, -18, -8, 65, 2, -3/*, 243*/], testInt16(-13, -5), + int16Compare); func testInt8(a : Int8, b : Int8) : [Int8] { @@ -239,7 +312,7 @@ func testInt8(a : Int8, b : Int8) : [Int8] { let pos2 = (+ a) : Int8; let neg1 = - a; let neg2 = (- a) : Int8; - /*let sum1 = a + b; + let sum1 = a + b; let sum2 = (a + b) : Int8; let diff1 = a - b; let diff2 = (a - b) : Int8; @@ -249,10 +322,116 @@ func testInt8(a : Int8, b : Int8) : [Int8] { let rat2 = (a / b) : Int8; let mod1 = a % b; let mod2 = (a % b) : Int8; - let pow1 = a ** b; + /*let pow1 = a ** b; let pow2 = (a ** b) : Int8;*/ - [pos1, pos2, neg1, neg2, /*sum1, sum2, diff1, diff2, prod1, prod2, rat1, rat2, mod1, mod2, pow1, pow2*/] + [pos1, pos2, neg1, neg2, sum1, sum2, diff1, diff2, prod1, prod2, rat1, rat2, mod1, mod2, /*pow1, pow2*/] +}; + +func int8Compare(a : Int8, b : Int8) : Bool = a == b; + +verify([3, -3, 8, -2, 15, 0, 3/*, 243*/], testInt8(3, 5), + int8Compare); +verify([13, -13, 18, 8, 65, 2, 3/*, 243*/], testInt8(13, 5), + int8Compare); +verify([3, -3, -2, 8, -15, 0, 3/*, 243*/], testInt8(3, -5), + int8Compare); +verify([13, -13, 8, 18, -65, -2, 3/*, 243*/], testInt8(13, -5), + int8Compare); +verify([-13, 13, -18, -8, 65, 2, -3/*, 243*/], testInt8(-13, -5), + int8Compare); + + +func testNat64(a : Nat64, b : Nat64) : [Nat64] { + let sum1 = a + b; + let sum2 = (a + b) : Nat64; + let diff1 = a - b; + let diff2 = (a - b) : Nat64; + let prod1 = a * b; + let prod2 = (a * b) : Nat64; + let rat1 = a / b; + let rat2 = (a / b) : Nat64; + let mod1 = a % b; + let mod2 = (a % b) : Nat64; + let pow1 = a ** b; + let pow2 = (a ** b) : Nat64; + [sum1, sum2, diff1, diff2, prod1, prod2, rat1, rat2, mod1, mod2, pow1, pow2] +}; + +func nat64Compare(a : Nat64, b : Nat64) : Bool = a == b; + +verify([8, 2, 15, 1, 2, 125], testNat64(5, 3), + nat64Compare); +verify([18, 8, 65, 2, 3, 371293], testNat64(13, 5), + nat64Compare); + + +func testNat32(a : Nat32, b : Nat32) : [Nat32] { + let sum1 = a + b; + let sum2 = (a + b) : Nat32; + let diff1 = a - b; + let diff2 = (a - b) : Nat32; + let prod1 = a * b; + let prod2 = (a * b) : Nat32; + let rat1 = a / b; + let rat2 = (a / b) : Nat32; + let mod1 = a % b; + let mod2 = (a % b) : Nat32; + /*let pow1 = a ** b; + let pow2 = (a ** b) : Nat32;*/ + [sum1, sum2, diff1, diff2, prod1, prod2, rat1, rat2, mod1, mod2/*, pow1, pow2*/] +}; + +func nat32Compare(a : Nat32, b : Nat32) : Bool = a == b; + +verify([8, 2, 15, 1, 2/*, 243*/], testNat32(5, 3), + nat32Compare); +verify([18, 12, 45, 5, 0/*, 243*/], testNat32(15, 3), + nat32Compare); + + +func testNat16(a : Nat16, b : Nat16) : [Nat16] { + let sum1 = a + b; + let sum2 = (a + b) : Nat16; + let diff1 = a - b; + let diff2 = (a - b) : Nat16; + let prod1 = a * b; + let prod2 = (a * b) : Nat16; + let rat1 = a / b; + let rat2 = (a / b) : Nat16; + let mod1 = a % b; + let mod2 = (a % b) : Nat16; + /*let pow1 = a ** b; + let pow2 = (a ** b) : Nat16;*/ + [sum1, sum2, diff1, diff2, prod1, prod2, rat1, rat2, mod1, mod2/*, pow1, pow2*/] +}; + +func nat16Compare(a : Nat16, b : Nat16) : Bool = a == b; + +verify([8, 2, 15, 1, 2/*, 243*/], testNat16(5, 3), + nat16Compare); +verify([18, 12, 45, 5, 0/*, 243*/], testNat16(15, 3), + nat16Compare); + + +func testNat8(a : Nat8, b : Nat8) : [Nat8] { + let sum1 = a + b; + let sum2 = (a + b) : Nat8; + let diff1 = a - b; + let diff2 = (a - b) : Nat8; + let prod1 = a * b; + let prod2 = (a * b) : Nat8; + let rat1 = a / b; + let rat2 = (a / b) : Nat8; + let mod1 = a % b; + let mod2 = (a % b) : Nat8; + /*let pow1 = a ** b; + let pow2 = (a ** b) : Nat8;*/ + [sum1, sum2, diff1, diff2, prod1, prod2, rat1, rat2, mod1, mod2/*, pow1, pow2*/] }; -verify([3, -3/*, 8, -2, 15, 0, 3, 243*/], testInt8(3, 5), - func (a : Int8, b : Int8) : Bool = a == b); +func nat8Compare(a : Nat8, b : Nat8) : Bool = a == b; + +verify([8, 2, 15, 1, 2/*, 243*/], testNat8(5, 3), + nat8Compare); +verify([18, 12, 45, 5, 0/*, 243*/], testNat8(15, 3), + nat8Compare); diff --git a/test/trap/Makefile b/test/trap/Makefile new file mode 100644 index 00000000000..6caa4f56e49 --- /dev/null +++ b/test/trap/Makefile @@ -0,0 +1,31 @@ +RUNFLAGS = + +all: + ../run.sh $(RUNFLAGS) *.as + +accept: + ../run.sh $(RUNFLAGS) -a *.as + +clean: + rm -rf _out + +include ../*.mk + +.PHONY: check _out/%.checked +check: $(patsubst %.as,_out/%.checked,$(wildcard *.as)) + +## for each %.as test there should be 4 ok/%.*.ok files with defined contents +_out/%.checked: %.as + @ (cat $(patsubst %.as,ok/%.run*.ok,$^) \ + | grep -e "execution error, arithmetic overflow" \ + -e "execution error, numeric overflow" \ + -e "execution error, value out of bounds" \ + | wc -l | grep 3 > /dev/null) \ + || (cat $(patsubst %.as,ok/%.run*.ok,$^); ls $(patsubst %.as,ok/%.run*.ok,$^); false) + @ (cat $(patsubst %.as,ok/%.wasm-run.ok,$^) \ + | grep -e "runtime trap: unreachable" \ + -e "runtime trap: integer overflow" \ + | wc -l | grep 1 > /dev/null) \ + || (cat $(patsubst %.as,ok/%.wasm-run.ok,$^); ls $(patsubst %.as,ok/%.wasm-run.ok,$^); false) + @ (ls $(patsubst %.as,ok/%.*.ok,$^) | wc -l | grep 4 > /dev/null) \ + || (ls $(patsubst %.as,ok/%.*.ok,$^); false) diff --git a/test/trap/addInt16-lower.as b/test/trap/addInt16-lower.as new file mode 100644 index 00000000000..ff12393bb07 --- /dev/null +++ b/test/trap/addInt16-lower.as @@ -0,0 +1 @@ +let _ = (-32767 : Int16) + (-2 : Int16) diff --git a/test/trap/addInt16-upper.as b/test/trap/addInt16-upper.as new file mode 100644 index 00000000000..608a20aaf41 --- /dev/null +++ b/test/trap/addInt16-upper.as @@ -0,0 +1 @@ +let _ = (32767 : Int16) + (1 : Int16) diff --git a/test/trap/addInt32-lower.as b/test/trap/addInt32-lower.as new file mode 100644 index 00000000000..c03e4c85bc9 --- /dev/null +++ b/test/trap/addInt32-lower.as @@ -0,0 +1 @@ +let _ = (-2_147_483_647 : Int32) + (-2 : Int32) diff --git a/test/trap/addInt32-upper.as b/test/trap/addInt32-upper.as new file mode 100644 index 00000000000..70da084ce33 --- /dev/null +++ b/test/trap/addInt32-upper.as @@ -0,0 +1 @@ +let _ = (2_147_483_647 : Int32) + (1 : Int32) diff --git a/test/trap/addInt64-lower.as b/test/trap/addInt64-lower.as new file mode 100644 index 00000000000..26070558d22 --- /dev/null +++ b/test/trap/addInt64-lower.as @@ -0,0 +1 @@ +let _ = (-9_223_372_036_854_775_807 : Int64) + (-2 : Int64) diff --git a/test/trap/addInt64-upper.as b/test/trap/addInt64-upper.as new file mode 100644 index 00000000000..5e0d6dceb40 --- /dev/null +++ b/test/trap/addInt64-upper.as @@ -0,0 +1 @@ +let _ = (9_223_372_036_854_775_807 : Int64) + (1 : Int64) diff --git a/test/trap/addInt8-lower.as b/test/trap/addInt8-lower.as new file mode 100644 index 00000000000..2bb342e1cb6 --- /dev/null +++ b/test/trap/addInt8-lower.as @@ -0,0 +1 @@ +let _ = (-127 : Int8) + (-2 : Int8) diff --git a/test/trap/addInt8-upper.as b/test/trap/addInt8-upper.as new file mode 100644 index 00000000000..a8072ae355d --- /dev/null +++ b/test/trap/addInt8-upper.as @@ -0,0 +1 @@ +let _ = (127 : Int8) + (1 : Int8) diff --git a/test/trap/addNat16.as b/test/trap/addNat16.as new file mode 100644 index 00000000000..65c418cddc7 --- /dev/null +++ b/test/trap/addNat16.as @@ -0,0 +1 @@ +let _ = (32767 : Nat16) + (32768 : Nat16) + (1 : Nat16) diff --git a/test/trap/addNat32.as b/test/trap/addNat32.as new file mode 100644 index 00000000000..e50d9744bcf --- /dev/null +++ b/test/trap/addNat32.as @@ -0,0 +1 @@ +let _ = (2_147_483_647 : Nat32) + (2_147_483_648 : Nat32) + (1 : Nat32) diff --git a/test/trap/addNat64.as b/test/trap/addNat64.as new file mode 100644 index 00000000000..bd2eb3a1e64 --- /dev/null +++ b/test/trap/addNat64.as @@ -0,0 +1 @@ +let _ = (9_223_372_036_854_775_807 : Nat64) + (9_223_372_036_854_775_808 : Nat64) + (1 : Nat64) diff --git a/test/trap/addNat8.as b/test/trap/addNat8.as new file mode 100644 index 00000000000..5bfe1a677a6 --- /dev/null +++ b/test/trap/addNat8.as @@ -0,0 +1 @@ +let _ = (127 : Nat8) + (128 : Nat8) + (1 : Nat8) diff --git a/test/trap/divInt16.as b/test/trap/divInt16.as new file mode 100644 index 00000000000..e94d269c0b6 --- /dev/null +++ b/test/trap/divInt16.as @@ -0,0 +1 @@ +let _ = intToInt16 (-32768) / (-1 : Int16) diff --git a/test/trap/divInt32.as b/test/trap/divInt32.as new file mode 100644 index 00000000000..5fbace59270 --- /dev/null +++ b/test/trap/divInt32.as @@ -0,0 +1 @@ +let _ = intToInt32 (-0x80000000) / (-1 : Int32) diff --git a/test/trap/divInt64.as b/test/trap/divInt64.as new file mode 100644 index 00000000000..603c31ff26b --- /dev/null +++ b/test/trap/divInt64.as @@ -0,0 +1 @@ +let _ = intToInt64 (-0x8000000000000000) / (-1 : Int64) diff --git a/test/trap/divInt8.as b/test/trap/divInt8.as new file mode 100644 index 00000000000..4202c0c43df --- /dev/null +++ b/test/trap/divInt8.as @@ -0,0 +1 @@ +let _ = intToInt8 (-128) / (-1 : Int8) diff --git a/test/trap/mulInt16-lower.as b/test/trap/mulInt16-lower.as new file mode 100644 index 00000000000..a62bb73727a --- /dev/null +++ b/test/trap/mulInt16-lower.as @@ -0,0 +1 @@ +let _ = (-10923 : Int16) * (3 : Int16) diff --git a/test/trap/mulInt16-upper.as b/test/trap/mulInt16-upper.as new file mode 100644 index 00000000000..ea09b1bc8da --- /dev/null +++ b/test/trap/mulInt16-upper.as @@ -0,0 +1 @@ +let _ = (256 : Int16) * (128 : Int16) diff --git a/test/trap/mulInt32-lower.as b/test/trap/mulInt32-lower.as new file mode 100644 index 00000000000..8aeb9cd967a --- /dev/null +++ b/test/trap/mulInt32-lower.as @@ -0,0 +1 @@ +let _ = (-715827883 : Int32) * (3 : Int32) diff --git a/test/trap/mulInt32-upper.as b/test/trap/mulInt32-upper.as new file mode 100644 index 00000000000..d1684a4b754 --- /dev/null +++ b/test/trap/mulInt32-upper.as @@ -0,0 +1 @@ +let _ = (65536 : Int32) * (32768 : Int32) diff --git a/test/trap/mulInt64-lower.as b/test/trap/mulInt64-lower.as new file mode 100644 index 00000000000..60351f20d32 --- /dev/null +++ b/test/trap/mulInt64-lower.as @@ -0,0 +1 @@ +let _ = (-1_024_819_115_206_086_201 : Int64) * (9 : Int64) diff --git a/test/trap/mulInt64-upper.as b/test/trap/mulInt64-upper.as new file mode 100644 index 00000000000..27367dc7b0d --- /dev/null +++ b/test/trap/mulInt64-upper.as @@ -0,0 +1 @@ +let _ = (4_294_967_296 : Int64) * (2_147_483_648 : Int64) diff --git a/test/trap/mulInt8-lower.as b/test/trap/mulInt8-lower.as new file mode 100644 index 00000000000..b198ab8c90b --- /dev/null +++ b/test/trap/mulInt8-lower.as @@ -0,0 +1 @@ +let _ = (-43 : Int8) * (3 : Int8) diff --git a/test/trap/mulInt8-upper.as b/test/trap/mulInt8-upper.as new file mode 100644 index 00000000000..3036bcc9a5d --- /dev/null +++ b/test/trap/mulInt8-upper.as @@ -0,0 +1 @@ +let _ = (16 : Int8) * (8 : Int8) diff --git a/test/trap/mulNat16.as b/test/trap/mulNat16.as new file mode 100644 index 00000000000..2f82ecbab27 --- /dev/null +++ b/test/trap/mulNat16.as @@ -0,0 +1 @@ +let _ = (256 : Nat16) * (256 : Nat16) diff --git a/test/trap/mulNat32.as b/test/trap/mulNat32.as new file mode 100644 index 00000000000..4862c61bae7 --- /dev/null +++ b/test/trap/mulNat32.as @@ -0,0 +1 @@ +let _ = (65536 : Nat32) * (65536 : Nat32) diff --git a/test/trap/mulNat64.as b/test/trap/mulNat64.as new file mode 100644 index 00000000000..0e32e55e4a4 --- /dev/null +++ b/test/trap/mulNat64.as @@ -0,0 +1 @@ +let _ = (4_294_967_296 : Nat64) * (4_294_967_296 : Nat64) diff --git a/test/trap/mulNat8.as b/test/trap/mulNat8.as new file mode 100644 index 00000000000..7244e98e2e7 --- /dev/null +++ b/test/trap/mulNat8.as @@ -0,0 +1 @@ +let _ = (16 : Nat8) * (16 : Nat8) diff --git a/test/trap/ok/addInt16-lower.run-ir.ok b/test/trap/ok/addInt16-lower.run-ir.ok new file mode 100644 index 00000000000..d62a0f9e2ac --- /dev/null +++ b/test/trap/ok/addInt16-lower.run-ir.ok @@ -0,0 +1 @@ +addInt16-lower.as:1.9-1.40: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt16-lower.run-low.ok b/test/trap/ok/addInt16-lower.run-low.ok new file mode 100644 index 00000000000..d62a0f9e2ac --- /dev/null +++ b/test/trap/ok/addInt16-lower.run-low.ok @@ -0,0 +1 @@ +addInt16-lower.as:1.9-1.40: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt16-lower.run.ok b/test/trap/ok/addInt16-lower.run.ok new file mode 100644 index 00000000000..d62a0f9e2ac --- /dev/null +++ b/test/trap/ok/addInt16-lower.run.ok @@ -0,0 +1 @@ +addInt16-lower.as:1.9-1.40: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt16-lower.wasm-run.ok b/test/trap/ok/addInt16-lower.wasm-run.ok new file mode 100644 index 00000000000..a53f2af670e --- /dev/null +++ b/test/trap/ok/addInt16-lower.wasm-run.ok @@ -0,0 +1 @@ +_out/addInt16-lower.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/addInt16-upper.run-ir.ok b/test/trap/ok/addInt16-upper.run-ir.ok new file mode 100644 index 00000000000..d79caaf1e0e --- /dev/null +++ b/test/trap/ok/addInt16-upper.run-ir.ok @@ -0,0 +1 @@ +addInt16-upper.as:1.9-1.38: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt16-upper.run-low.ok b/test/trap/ok/addInt16-upper.run-low.ok new file mode 100644 index 00000000000..d79caaf1e0e --- /dev/null +++ b/test/trap/ok/addInt16-upper.run-low.ok @@ -0,0 +1 @@ +addInt16-upper.as:1.9-1.38: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt16-upper.run.ok b/test/trap/ok/addInt16-upper.run.ok new file mode 100644 index 00000000000..d79caaf1e0e --- /dev/null +++ b/test/trap/ok/addInt16-upper.run.ok @@ -0,0 +1 @@ +addInt16-upper.as:1.9-1.38: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt16-upper.wasm-run.ok b/test/trap/ok/addInt16-upper.wasm-run.ok new file mode 100644 index 00000000000..79ac5c6da61 --- /dev/null +++ b/test/trap/ok/addInt16-upper.wasm-run.ok @@ -0,0 +1 @@ +_out/addInt16-upper.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/addInt32-lower.run-ir.ok b/test/trap/ok/addInt32-lower.run-ir.ok new file mode 100644 index 00000000000..cf0ff2993d8 --- /dev/null +++ b/test/trap/ok/addInt32-lower.run-ir.ok @@ -0,0 +1 @@ +addInt32-lower.as:1.9-1.48: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt32-lower.run-low.ok b/test/trap/ok/addInt32-lower.run-low.ok new file mode 100644 index 00000000000..cf0ff2993d8 --- /dev/null +++ b/test/trap/ok/addInt32-lower.run-low.ok @@ -0,0 +1 @@ +addInt32-lower.as:1.9-1.48: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt32-lower.run.ok b/test/trap/ok/addInt32-lower.run.ok new file mode 100644 index 00000000000..cf0ff2993d8 --- /dev/null +++ b/test/trap/ok/addInt32-lower.run.ok @@ -0,0 +1 @@ +addInt32-lower.as:1.9-1.48: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt32-lower.wasm-run.ok b/test/trap/ok/addInt32-lower.wasm-run.ok new file mode 100644 index 00000000000..7301a614e60 --- /dev/null +++ b/test/trap/ok/addInt32-lower.wasm-run.ok @@ -0,0 +1 @@ +_out/addInt32-lower.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/addInt32-upper.run-ir.ok b/test/trap/ok/addInt32-upper.run-ir.ok new file mode 100644 index 00000000000..acd452bb58a --- /dev/null +++ b/test/trap/ok/addInt32-upper.run-ir.ok @@ -0,0 +1 @@ +addInt32-upper.as:1.9-1.46: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt32-upper.run-low.ok b/test/trap/ok/addInt32-upper.run-low.ok new file mode 100644 index 00000000000..acd452bb58a --- /dev/null +++ b/test/trap/ok/addInt32-upper.run-low.ok @@ -0,0 +1 @@ +addInt32-upper.as:1.9-1.46: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt32-upper.run.ok b/test/trap/ok/addInt32-upper.run.ok new file mode 100644 index 00000000000..acd452bb58a --- /dev/null +++ b/test/trap/ok/addInt32-upper.run.ok @@ -0,0 +1 @@ +addInt32-upper.as:1.9-1.46: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt32-upper.wasm-run.ok b/test/trap/ok/addInt32-upper.wasm-run.ok new file mode 100644 index 00000000000..e7274c12aea --- /dev/null +++ b/test/trap/ok/addInt32-upper.wasm-run.ok @@ -0,0 +1 @@ +_out/addInt32-upper.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/addInt64-lower.run-ir.ok b/test/trap/ok/addInt64-lower.run-ir.ok new file mode 100644 index 00000000000..928eca69453 --- /dev/null +++ b/test/trap/ok/addInt64-lower.run-ir.ok @@ -0,0 +1 @@ +addInt64-lower.as:1.9-1.60: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt64-lower.run-low.ok b/test/trap/ok/addInt64-lower.run-low.ok new file mode 100644 index 00000000000..928eca69453 --- /dev/null +++ b/test/trap/ok/addInt64-lower.run-low.ok @@ -0,0 +1 @@ +addInt64-lower.as:1.9-1.60: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt64-lower.run.ok b/test/trap/ok/addInt64-lower.run.ok new file mode 100644 index 00000000000..928eca69453 --- /dev/null +++ b/test/trap/ok/addInt64-lower.run.ok @@ -0,0 +1 @@ +addInt64-lower.as:1.9-1.60: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt64-lower.wasm-run.ok b/test/trap/ok/addInt64-lower.wasm-run.ok new file mode 100644 index 00000000000..da9469b2efd --- /dev/null +++ b/test/trap/ok/addInt64-lower.wasm-run.ok @@ -0,0 +1 @@ +_out/addInt64-lower.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/addInt64-upper.run-ir.ok b/test/trap/ok/addInt64-upper.run-ir.ok new file mode 100644 index 00000000000..0de67ff7676 --- /dev/null +++ b/test/trap/ok/addInt64-upper.run-ir.ok @@ -0,0 +1 @@ +addInt64-upper.as:1.9-1.58: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt64-upper.run-low.ok b/test/trap/ok/addInt64-upper.run-low.ok new file mode 100644 index 00000000000..0de67ff7676 --- /dev/null +++ b/test/trap/ok/addInt64-upper.run-low.ok @@ -0,0 +1 @@ +addInt64-upper.as:1.9-1.58: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt64-upper.run.ok b/test/trap/ok/addInt64-upper.run.ok new file mode 100644 index 00000000000..0de67ff7676 --- /dev/null +++ b/test/trap/ok/addInt64-upper.run.ok @@ -0,0 +1 @@ +addInt64-upper.as:1.9-1.58: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt64-upper.wasm-run.ok b/test/trap/ok/addInt64-upper.wasm-run.ok new file mode 100644 index 00000000000..7d7fd9d5525 --- /dev/null +++ b/test/trap/ok/addInt64-upper.wasm-run.ok @@ -0,0 +1 @@ +_out/addInt64-upper.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/addInt8-lower.run-ir.ok b/test/trap/ok/addInt8-lower.run-ir.ok new file mode 100644 index 00000000000..9fe0fcb4891 --- /dev/null +++ b/test/trap/ok/addInt8-lower.run-ir.ok @@ -0,0 +1 @@ +addInt8-lower.as:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt8-lower.run-low.ok b/test/trap/ok/addInt8-lower.run-low.ok new file mode 100644 index 00000000000..9fe0fcb4891 --- /dev/null +++ b/test/trap/ok/addInt8-lower.run-low.ok @@ -0,0 +1 @@ +addInt8-lower.as:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt8-lower.run.ok b/test/trap/ok/addInt8-lower.run.ok new file mode 100644 index 00000000000..9fe0fcb4891 --- /dev/null +++ b/test/trap/ok/addInt8-lower.run.ok @@ -0,0 +1 @@ +addInt8-lower.as:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt8-lower.wasm-run.ok b/test/trap/ok/addInt8-lower.wasm-run.ok new file mode 100644 index 00000000000..8a3153abe4d --- /dev/null +++ b/test/trap/ok/addInt8-lower.wasm-run.ok @@ -0,0 +1 @@ +_out/addInt8-lower.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/addInt8-upper.run-ir.ok b/test/trap/ok/addInt8-upper.run-ir.ok new file mode 100644 index 00000000000..e9473ec9d23 --- /dev/null +++ b/test/trap/ok/addInt8-upper.run-ir.ok @@ -0,0 +1 @@ +addInt8-upper.as:1.9-1.34: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt8-upper.run-low.ok b/test/trap/ok/addInt8-upper.run-low.ok new file mode 100644 index 00000000000..e9473ec9d23 --- /dev/null +++ b/test/trap/ok/addInt8-upper.run-low.ok @@ -0,0 +1 @@ +addInt8-upper.as:1.9-1.34: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt8-upper.run.ok b/test/trap/ok/addInt8-upper.run.ok new file mode 100644 index 00000000000..e9473ec9d23 --- /dev/null +++ b/test/trap/ok/addInt8-upper.run.ok @@ -0,0 +1 @@ +addInt8-upper.as:1.9-1.34: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt8-upper.wasm-run.ok b/test/trap/ok/addInt8-upper.wasm-run.ok new file mode 100644 index 00000000000..885fc9bb190 --- /dev/null +++ b/test/trap/ok/addInt8-upper.wasm-run.ok @@ -0,0 +1 @@ +_out/addInt8-upper.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/addNat16.run-ir.ok b/test/trap/ok/addNat16.run-ir.ok new file mode 100644 index 00000000000..df835aa414d --- /dev/null +++ b/test/trap/ok/addNat16.run-ir.ok @@ -0,0 +1 @@ +addNat16.as:1.9-1.56: execution error, arithmetic overflow diff --git a/test/trap/ok/addNat16.run-low.ok b/test/trap/ok/addNat16.run-low.ok new file mode 100644 index 00000000000..df835aa414d --- /dev/null +++ b/test/trap/ok/addNat16.run-low.ok @@ -0,0 +1 @@ +addNat16.as:1.9-1.56: execution error, arithmetic overflow diff --git a/test/trap/ok/addNat16.run.ok b/test/trap/ok/addNat16.run.ok new file mode 100644 index 00000000000..df835aa414d --- /dev/null +++ b/test/trap/ok/addNat16.run.ok @@ -0,0 +1 @@ +addNat16.as:1.9-1.56: execution error, arithmetic overflow diff --git a/test/trap/ok/addNat16.wasm-run.ok b/test/trap/ok/addNat16.wasm-run.ok new file mode 100644 index 00000000000..211d569d615 --- /dev/null +++ b/test/trap/ok/addNat16.wasm-run.ok @@ -0,0 +1 @@ +_out/addNat16.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/addNat32.run-ir.ok b/test/trap/ok/addNat32.run-ir.ok new file mode 100644 index 00000000000..44c1c0e581f --- /dev/null +++ b/test/trap/ok/addNat32.run-ir.ok @@ -0,0 +1 @@ +addNat32.as:1.9-1.72: execution error, arithmetic overflow diff --git a/test/trap/ok/addNat32.run-low.ok b/test/trap/ok/addNat32.run-low.ok new file mode 100644 index 00000000000..44c1c0e581f --- /dev/null +++ b/test/trap/ok/addNat32.run-low.ok @@ -0,0 +1 @@ +addNat32.as:1.9-1.72: execution error, arithmetic overflow diff --git a/test/trap/ok/addNat32.run.ok b/test/trap/ok/addNat32.run.ok new file mode 100644 index 00000000000..44c1c0e581f --- /dev/null +++ b/test/trap/ok/addNat32.run.ok @@ -0,0 +1 @@ +addNat32.as:1.9-1.72: execution error, arithmetic overflow diff --git a/test/trap/ok/addNat32.wasm-run.ok b/test/trap/ok/addNat32.wasm-run.ok new file mode 100644 index 00000000000..a8bbc4d6459 --- /dev/null +++ b/test/trap/ok/addNat32.wasm-run.ok @@ -0,0 +1 @@ +_out/addNat32.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/addNat64.run-ir.ok b/test/trap/ok/addNat64.run-ir.ok new file mode 100644 index 00000000000..9ba553ba038 --- /dev/null +++ b/test/trap/ok/addNat64.run-ir.ok @@ -0,0 +1 @@ +addNat64.as:1.9-1.96: execution error, arithmetic overflow diff --git a/test/trap/ok/addNat64.run-low.ok b/test/trap/ok/addNat64.run-low.ok new file mode 100644 index 00000000000..9ba553ba038 --- /dev/null +++ b/test/trap/ok/addNat64.run-low.ok @@ -0,0 +1 @@ +addNat64.as:1.9-1.96: execution error, arithmetic overflow diff --git a/test/trap/ok/addNat64.run.ok b/test/trap/ok/addNat64.run.ok new file mode 100644 index 00000000000..9ba553ba038 --- /dev/null +++ b/test/trap/ok/addNat64.run.ok @@ -0,0 +1 @@ +addNat64.as:1.9-1.96: execution error, arithmetic overflow diff --git a/test/trap/ok/addNat64.wasm-run.ok b/test/trap/ok/addNat64.wasm-run.ok new file mode 100644 index 00000000000..83259226b95 --- /dev/null +++ b/test/trap/ok/addNat64.wasm-run.ok @@ -0,0 +1 @@ +_out/addNat64.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/addNat8.run-ir.ok b/test/trap/ok/addNat8.run-ir.ok new file mode 100644 index 00000000000..c11ce155102 --- /dev/null +++ b/test/trap/ok/addNat8.run-ir.ok @@ -0,0 +1 @@ +addNat8.as:1.9-1.49: execution error, arithmetic overflow diff --git a/test/trap/ok/addNat8.run-low.ok b/test/trap/ok/addNat8.run-low.ok new file mode 100644 index 00000000000..c11ce155102 --- /dev/null +++ b/test/trap/ok/addNat8.run-low.ok @@ -0,0 +1 @@ +addNat8.as:1.9-1.49: execution error, arithmetic overflow diff --git a/test/trap/ok/addNat8.run.ok b/test/trap/ok/addNat8.run.ok new file mode 100644 index 00000000000..c11ce155102 --- /dev/null +++ b/test/trap/ok/addNat8.run.ok @@ -0,0 +1 @@ +addNat8.as:1.9-1.49: execution error, arithmetic overflow diff --git a/test/trap/ok/addNat8.wasm-run.ok b/test/trap/ok/addNat8.wasm-run.ok new file mode 100644 index 00000000000..6c45c588c69 --- /dev/null +++ b/test/trap/ok/addNat8.wasm-run.ok @@ -0,0 +1 @@ +_out/addNat8.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/divInt16.run-ir.ok b/test/trap/ok/divInt16.run-ir.ok new file mode 100644 index 00000000000..0fa6f654fec --- /dev/null +++ b/test/trap/ok/divInt16.run-ir.ok @@ -0,0 +1 @@ +divInt16.as:1.9-1.43: execution error, arithmetic overflow diff --git a/test/trap/ok/divInt16.run-low.ok b/test/trap/ok/divInt16.run-low.ok new file mode 100644 index 00000000000..0fa6f654fec --- /dev/null +++ b/test/trap/ok/divInt16.run-low.ok @@ -0,0 +1 @@ +divInt16.as:1.9-1.43: execution error, arithmetic overflow diff --git a/test/trap/ok/divInt16.run.ok b/test/trap/ok/divInt16.run.ok new file mode 100644 index 00000000000..0fa6f654fec --- /dev/null +++ b/test/trap/ok/divInt16.run.ok @@ -0,0 +1 @@ +divInt16.as:1.9-1.43: execution error, arithmetic overflow diff --git a/test/trap/ok/divInt16.wasm-run.ok b/test/trap/ok/divInt16.wasm-run.ok new file mode 100644 index 00000000000..5c10a0140c7 --- /dev/null +++ b/test/trap/ok/divInt16.wasm-run.ok @@ -0,0 +1 @@ +_out/divInt16.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/divInt32.run-ir.ok b/test/trap/ok/divInt32.run-ir.ok new file mode 100644 index 00000000000..63925b7f704 --- /dev/null +++ b/test/trap/ok/divInt32.run-ir.ok @@ -0,0 +1 @@ +divInt32.as:1.9-1.48: execution error, arithmetic overflow diff --git a/test/trap/ok/divInt32.run-low.ok b/test/trap/ok/divInt32.run-low.ok new file mode 100644 index 00000000000..63925b7f704 --- /dev/null +++ b/test/trap/ok/divInt32.run-low.ok @@ -0,0 +1 @@ +divInt32.as:1.9-1.48: execution error, arithmetic overflow diff --git a/test/trap/ok/divInt32.run.ok b/test/trap/ok/divInt32.run.ok new file mode 100644 index 00000000000..63925b7f704 --- /dev/null +++ b/test/trap/ok/divInt32.run.ok @@ -0,0 +1 @@ +divInt32.as:1.9-1.48: execution error, arithmetic overflow diff --git a/test/trap/ok/divInt32.wasm-run.ok b/test/trap/ok/divInt32.wasm-run.ok new file mode 100644 index 00000000000..c590a95e715 --- /dev/null +++ b/test/trap/ok/divInt32.wasm-run.ok @@ -0,0 +1 @@ +_out/divInt32.wasm:0x___: runtime trap: integer overflow diff --git a/test/trap/ok/divInt64.run-ir.ok b/test/trap/ok/divInt64.run-ir.ok new file mode 100644 index 00000000000..6fea9ac0cd6 --- /dev/null +++ b/test/trap/ok/divInt64.run-ir.ok @@ -0,0 +1 @@ +divInt64.as:1.9-1.56: execution error, arithmetic overflow diff --git a/test/trap/ok/divInt64.run-low.ok b/test/trap/ok/divInt64.run-low.ok new file mode 100644 index 00000000000..6fea9ac0cd6 --- /dev/null +++ b/test/trap/ok/divInt64.run-low.ok @@ -0,0 +1 @@ +divInt64.as:1.9-1.56: execution error, arithmetic overflow diff --git a/test/trap/ok/divInt64.run.ok b/test/trap/ok/divInt64.run.ok new file mode 100644 index 00000000000..6fea9ac0cd6 --- /dev/null +++ b/test/trap/ok/divInt64.run.ok @@ -0,0 +1 @@ +divInt64.as:1.9-1.56: execution error, arithmetic overflow diff --git a/test/trap/ok/divInt64.wasm-run.ok b/test/trap/ok/divInt64.wasm-run.ok new file mode 100644 index 00000000000..a83505797dc --- /dev/null +++ b/test/trap/ok/divInt64.wasm-run.ok @@ -0,0 +1 @@ +_out/divInt64.wasm:0x___: runtime trap: integer overflow diff --git a/test/trap/ok/divInt8.run-ir.ok b/test/trap/ok/divInt8.run-ir.ok new file mode 100644 index 00000000000..463f3dfb55a --- /dev/null +++ b/test/trap/ok/divInt8.run-ir.ok @@ -0,0 +1 @@ +divInt8.as:1.9-1.39: execution error, arithmetic overflow diff --git a/test/trap/ok/divInt8.run-low.ok b/test/trap/ok/divInt8.run-low.ok new file mode 100644 index 00000000000..463f3dfb55a --- /dev/null +++ b/test/trap/ok/divInt8.run-low.ok @@ -0,0 +1 @@ +divInt8.as:1.9-1.39: execution error, arithmetic overflow diff --git a/test/trap/ok/divInt8.run.ok b/test/trap/ok/divInt8.run.ok new file mode 100644 index 00000000000..463f3dfb55a --- /dev/null +++ b/test/trap/ok/divInt8.run.ok @@ -0,0 +1 @@ +divInt8.as:1.9-1.39: execution error, arithmetic overflow diff --git a/test/trap/ok/divInt8.wasm-run.ok b/test/trap/ok/divInt8.wasm-run.ok new file mode 100644 index 00000000000..cc30751f738 --- /dev/null +++ b/test/trap/ok/divInt8.wasm-run.ok @@ -0,0 +1 @@ +_out/divInt8.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/mulInt16-lower.run-ir.ok b/test/trap/ok/mulInt16-lower.run-ir.ok new file mode 100644 index 00000000000..8bd0a01b943 --- /dev/null +++ b/test/trap/ok/mulInt16-lower.run-ir.ok @@ -0,0 +1 @@ +mulInt16-lower.as:1.9-1.39: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt16-lower.run-low.ok b/test/trap/ok/mulInt16-lower.run-low.ok new file mode 100644 index 00000000000..8bd0a01b943 --- /dev/null +++ b/test/trap/ok/mulInt16-lower.run-low.ok @@ -0,0 +1 @@ +mulInt16-lower.as:1.9-1.39: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt16-lower.run.ok b/test/trap/ok/mulInt16-lower.run.ok new file mode 100644 index 00000000000..8bd0a01b943 --- /dev/null +++ b/test/trap/ok/mulInt16-lower.run.ok @@ -0,0 +1 @@ +mulInt16-lower.as:1.9-1.39: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt16-lower.wasm-run.ok b/test/trap/ok/mulInt16-lower.wasm-run.ok new file mode 100644 index 00000000000..8d58f77d6bf --- /dev/null +++ b/test/trap/ok/mulInt16-lower.wasm-run.ok @@ -0,0 +1 @@ +_out/mulInt16-lower.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/mulInt16-upper.run-ir.ok b/test/trap/ok/mulInt16-upper.run-ir.ok new file mode 100644 index 00000000000..f508a0f4f21 --- /dev/null +++ b/test/trap/ok/mulInt16-upper.run-ir.ok @@ -0,0 +1 @@ +mulInt16-upper.as:1.9-1.38: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt16-upper.run-low.ok b/test/trap/ok/mulInt16-upper.run-low.ok new file mode 100644 index 00000000000..f508a0f4f21 --- /dev/null +++ b/test/trap/ok/mulInt16-upper.run-low.ok @@ -0,0 +1 @@ +mulInt16-upper.as:1.9-1.38: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt16-upper.run.ok b/test/trap/ok/mulInt16-upper.run.ok new file mode 100644 index 00000000000..f508a0f4f21 --- /dev/null +++ b/test/trap/ok/mulInt16-upper.run.ok @@ -0,0 +1 @@ +mulInt16-upper.as:1.9-1.38: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt16-upper.wasm-run.ok b/test/trap/ok/mulInt16-upper.wasm-run.ok new file mode 100644 index 00000000000..eec850eeb1d --- /dev/null +++ b/test/trap/ok/mulInt16-upper.wasm-run.ok @@ -0,0 +1 @@ +_out/mulInt16-upper.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/mulInt32-lower.run-ir.ok b/test/trap/ok/mulInt32-lower.run-ir.ok new file mode 100644 index 00000000000..7c36e38f828 --- /dev/null +++ b/test/trap/ok/mulInt32-lower.run-ir.ok @@ -0,0 +1 @@ +mulInt32-lower.as:1.9-1.43: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt32-lower.run-low.ok b/test/trap/ok/mulInt32-lower.run-low.ok new file mode 100644 index 00000000000..7c36e38f828 --- /dev/null +++ b/test/trap/ok/mulInt32-lower.run-low.ok @@ -0,0 +1 @@ +mulInt32-lower.as:1.9-1.43: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt32-lower.run.ok b/test/trap/ok/mulInt32-lower.run.ok new file mode 100644 index 00000000000..7c36e38f828 --- /dev/null +++ b/test/trap/ok/mulInt32-lower.run.ok @@ -0,0 +1 @@ +mulInt32-lower.as:1.9-1.43: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt32-lower.wasm-run.ok b/test/trap/ok/mulInt32-lower.wasm-run.ok new file mode 100644 index 00000000000..67a3d477bdd --- /dev/null +++ b/test/trap/ok/mulInt32-lower.wasm-run.ok @@ -0,0 +1 @@ +_out/mulInt32-lower.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/mulInt32-upper.run-ir.ok b/test/trap/ok/mulInt32-upper.run-ir.ok new file mode 100644 index 00000000000..e2b4edd024f --- /dev/null +++ b/test/trap/ok/mulInt32-upper.run-ir.ok @@ -0,0 +1 @@ +mulInt32-upper.as:1.9-1.42: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt32-upper.run-low.ok b/test/trap/ok/mulInt32-upper.run-low.ok new file mode 100644 index 00000000000..e2b4edd024f --- /dev/null +++ b/test/trap/ok/mulInt32-upper.run-low.ok @@ -0,0 +1 @@ +mulInt32-upper.as:1.9-1.42: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt32-upper.run.ok b/test/trap/ok/mulInt32-upper.run.ok new file mode 100644 index 00000000000..e2b4edd024f --- /dev/null +++ b/test/trap/ok/mulInt32-upper.run.ok @@ -0,0 +1 @@ +mulInt32-upper.as:1.9-1.42: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt32-upper.wasm-run.ok b/test/trap/ok/mulInt32-upper.wasm-run.ok new file mode 100644 index 00000000000..c11c7fda881 --- /dev/null +++ b/test/trap/ok/mulInt32-upper.wasm-run.ok @@ -0,0 +1 @@ +_out/mulInt32-upper.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/mulInt64-lower.run-ir.ok b/test/trap/ok/mulInt64-lower.run-ir.ok new file mode 100644 index 00000000000..0411d2c52dc --- /dev/null +++ b/test/trap/ok/mulInt64-lower.run-ir.ok @@ -0,0 +1 @@ +mulInt64-lower.as:1.9-1.59: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt64-lower.run-low.ok b/test/trap/ok/mulInt64-lower.run-low.ok new file mode 100644 index 00000000000..0411d2c52dc --- /dev/null +++ b/test/trap/ok/mulInt64-lower.run-low.ok @@ -0,0 +1 @@ +mulInt64-lower.as:1.9-1.59: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt64-lower.run.ok b/test/trap/ok/mulInt64-lower.run.ok new file mode 100644 index 00000000000..0411d2c52dc --- /dev/null +++ b/test/trap/ok/mulInt64-lower.run.ok @@ -0,0 +1 @@ +mulInt64-lower.as:1.9-1.59: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt64-lower.wasm-run.ok b/test/trap/ok/mulInt64-lower.wasm-run.ok new file mode 100644 index 00000000000..57661b67d09 --- /dev/null +++ b/test/trap/ok/mulInt64-lower.wasm-run.ok @@ -0,0 +1 @@ +_out/mulInt64-lower.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/mulInt64-upper.run-ir.ok b/test/trap/ok/mulInt64-upper.run-ir.ok new file mode 100644 index 00000000000..a6fce3b9824 --- /dev/null +++ b/test/trap/ok/mulInt64-upper.run-ir.ok @@ -0,0 +1 @@ +mulInt64-upper.as:1.9-1.58: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt64-upper.run-low.ok b/test/trap/ok/mulInt64-upper.run-low.ok new file mode 100644 index 00000000000..a6fce3b9824 --- /dev/null +++ b/test/trap/ok/mulInt64-upper.run-low.ok @@ -0,0 +1 @@ +mulInt64-upper.as:1.9-1.58: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt64-upper.run.ok b/test/trap/ok/mulInt64-upper.run.ok new file mode 100644 index 00000000000..a6fce3b9824 --- /dev/null +++ b/test/trap/ok/mulInt64-upper.run.ok @@ -0,0 +1 @@ +mulInt64-upper.as:1.9-1.58: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt64-upper.wasm-run.ok b/test/trap/ok/mulInt64-upper.wasm-run.ok new file mode 100644 index 00000000000..2dad24b7f71 --- /dev/null +++ b/test/trap/ok/mulInt64-upper.wasm-run.ok @@ -0,0 +1 @@ +_out/mulInt64-upper.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/mulInt8-lower.run-ir.ok b/test/trap/ok/mulInt8-lower.run-ir.ok new file mode 100644 index 00000000000..b0ea4be6c13 --- /dev/null +++ b/test/trap/ok/mulInt8-lower.run-ir.ok @@ -0,0 +1 @@ +mulInt8-lower.as:1.9-1.34: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt8-lower.run-low.ok b/test/trap/ok/mulInt8-lower.run-low.ok new file mode 100644 index 00000000000..b0ea4be6c13 --- /dev/null +++ b/test/trap/ok/mulInt8-lower.run-low.ok @@ -0,0 +1 @@ +mulInt8-lower.as:1.9-1.34: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt8-lower.run.ok b/test/trap/ok/mulInt8-lower.run.ok new file mode 100644 index 00000000000..b0ea4be6c13 --- /dev/null +++ b/test/trap/ok/mulInt8-lower.run.ok @@ -0,0 +1 @@ +mulInt8-lower.as:1.9-1.34: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt8-lower.wasm-run.ok b/test/trap/ok/mulInt8-lower.wasm-run.ok new file mode 100644 index 00000000000..ee3b90af24b --- /dev/null +++ b/test/trap/ok/mulInt8-lower.wasm-run.ok @@ -0,0 +1 @@ +_out/mulInt8-lower.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/mulInt8-upper.run-ir.ok b/test/trap/ok/mulInt8-upper.run-ir.ok new file mode 100644 index 00000000000..d08ca12303c --- /dev/null +++ b/test/trap/ok/mulInt8-upper.run-ir.ok @@ -0,0 +1 @@ +mulInt8-upper.as:1.9-1.33: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt8-upper.run-low.ok b/test/trap/ok/mulInt8-upper.run-low.ok new file mode 100644 index 00000000000..d08ca12303c --- /dev/null +++ b/test/trap/ok/mulInt8-upper.run-low.ok @@ -0,0 +1 @@ +mulInt8-upper.as:1.9-1.33: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt8-upper.run.ok b/test/trap/ok/mulInt8-upper.run.ok new file mode 100644 index 00000000000..d08ca12303c --- /dev/null +++ b/test/trap/ok/mulInt8-upper.run.ok @@ -0,0 +1 @@ +mulInt8-upper.as:1.9-1.33: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt8-upper.wasm-run.ok b/test/trap/ok/mulInt8-upper.wasm-run.ok new file mode 100644 index 00000000000..30c1be3a4eb --- /dev/null +++ b/test/trap/ok/mulInt8-upper.wasm-run.ok @@ -0,0 +1 @@ +_out/mulInt8-upper.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/mulNat16.run-ir.ok b/test/trap/ok/mulNat16.run-ir.ok new file mode 100644 index 00000000000..2761ae3d89d --- /dev/null +++ b/test/trap/ok/mulNat16.run-ir.ok @@ -0,0 +1 @@ +mulNat16.as:1.9-1.38: execution error, arithmetic overflow diff --git a/test/trap/ok/mulNat16.run-low.ok b/test/trap/ok/mulNat16.run-low.ok new file mode 100644 index 00000000000..2761ae3d89d --- /dev/null +++ b/test/trap/ok/mulNat16.run-low.ok @@ -0,0 +1 @@ +mulNat16.as:1.9-1.38: execution error, arithmetic overflow diff --git a/test/trap/ok/mulNat16.run.ok b/test/trap/ok/mulNat16.run.ok new file mode 100644 index 00000000000..2761ae3d89d --- /dev/null +++ b/test/trap/ok/mulNat16.run.ok @@ -0,0 +1 @@ +mulNat16.as:1.9-1.38: execution error, arithmetic overflow diff --git a/test/trap/ok/mulNat16.wasm-run.ok b/test/trap/ok/mulNat16.wasm-run.ok new file mode 100644 index 00000000000..9b4c3b7176e --- /dev/null +++ b/test/trap/ok/mulNat16.wasm-run.ok @@ -0,0 +1 @@ +_out/mulNat16.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/mulNat32.run-ir.ok b/test/trap/ok/mulNat32.run-ir.ok new file mode 100644 index 00000000000..37e7a009b19 --- /dev/null +++ b/test/trap/ok/mulNat32.run-ir.ok @@ -0,0 +1 @@ +mulNat32.as:1.9-1.42: execution error, arithmetic overflow diff --git a/test/trap/ok/mulNat32.run-low.ok b/test/trap/ok/mulNat32.run-low.ok new file mode 100644 index 00000000000..37e7a009b19 --- /dev/null +++ b/test/trap/ok/mulNat32.run-low.ok @@ -0,0 +1 @@ +mulNat32.as:1.9-1.42: execution error, arithmetic overflow diff --git a/test/trap/ok/mulNat32.run.ok b/test/trap/ok/mulNat32.run.ok new file mode 100644 index 00000000000..37e7a009b19 --- /dev/null +++ b/test/trap/ok/mulNat32.run.ok @@ -0,0 +1 @@ +mulNat32.as:1.9-1.42: execution error, arithmetic overflow diff --git a/test/trap/ok/mulNat32.wasm-run.ok b/test/trap/ok/mulNat32.wasm-run.ok new file mode 100644 index 00000000000..717a6e28d74 --- /dev/null +++ b/test/trap/ok/mulNat32.wasm-run.ok @@ -0,0 +1 @@ +_out/mulNat32.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/mulNat64.run-ir.ok b/test/trap/ok/mulNat64.run-ir.ok new file mode 100644 index 00000000000..816128a21e8 --- /dev/null +++ b/test/trap/ok/mulNat64.run-ir.ok @@ -0,0 +1 @@ +mulNat64.as:1.9-1.58: execution error, arithmetic overflow diff --git a/test/trap/ok/mulNat64.run-low.ok b/test/trap/ok/mulNat64.run-low.ok new file mode 100644 index 00000000000..816128a21e8 --- /dev/null +++ b/test/trap/ok/mulNat64.run-low.ok @@ -0,0 +1 @@ +mulNat64.as:1.9-1.58: execution error, arithmetic overflow diff --git a/test/trap/ok/mulNat64.run.ok b/test/trap/ok/mulNat64.run.ok new file mode 100644 index 00000000000..816128a21e8 --- /dev/null +++ b/test/trap/ok/mulNat64.run.ok @@ -0,0 +1 @@ +mulNat64.as:1.9-1.58: execution error, arithmetic overflow diff --git a/test/trap/ok/mulNat64.wasm-run.ok b/test/trap/ok/mulNat64.wasm-run.ok new file mode 100644 index 00000000000..bb34cc33252 --- /dev/null +++ b/test/trap/ok/mulNat64.wasm-run.ok @@ -0,0 +1 @@ +_out/mulNat64.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/mulNat8.run-ir.ok b/test/trap/ok/mulNat8.run-ir.ok new file mode 100644 index 00000000000..5873fd751db --- /dev/null +++ b/test/trap/ok/mulNat8.run-ir.ok @@ -0,0 +1 @@ +mulNat8.as:1.9-1.34: execution error, arithmetic overflow diff --git a/test/trap/ok/mulNat8.run-low.ok b/test/trap/ok/mulNat8.run-low.ok new file mode 100644 index 00000000000..5873fd751db --- /dev/null +++ b/test/trap/ok/mulNat8.run-low.ok @@ -0,0 +1 @@ +mulNat8.as:1.9-1.34: execution error, arithmetic overflow diff --git a/test/trap/ok/mulNat8.run.ok b/test/trap/ok/mulNat8.run.ok new file mode 100644 index 00000000000..5873fd751db --- /dev/null +++ b/test/trap/ok/mulNat8.run.ok @@ -0,0 +1 @@ +mulNat8.as:1.9-1.34: execution error, arithmetic overflow diff --git a/test/trap/ok/mulNat8.wasm-run.ok b/test/trap/ok/mulNat8.wasm-run.ok new file mode 100644 index 00000000000..2b9666200cd --- /dev/null +++ b/test/trap/ok/mulNat8.wasm-run.ok @@ -0,0 +1 @@ +_out/mulNat8.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/outrange-int16-lower.run-ir.ok b/test/trap/ok/outrange-int16-lower.run-ir.ok new file mode 100644 index 00000000000..54a37fcb824 --- /dev/null +++ b/test/trap/ok/outrange-int16-lower.run-ir.ok @@ -0,0 +1 @@ +prelude:79.36-79.72: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int16-lower.run-low.ok b/test/trap/ok/outrange-int16-lower.run-low.ok new file mode 100644 index 00000000000..54a37fcb824 --- /dev/null +++ b/test/trap/ok/outrange-int16-lower.run-low.ok @@ -0,0 +1 @@ +prelude:79.36-79.72: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int16-lower.run.ok b/test/trap/ok/outrange-int16-lower.run.ok new file mode 100644 index 00000000000..54a37fcb824 --- /dev/null +++ b/test/trap/ok/outrange-int16-lower.run.ok @@ -0,0 +1 @@ +prelude:79.36-79.72: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int16-lower.wasm-run.ok b/test/trap/ok/outrange-int16-lower.wasm-run.ok new file mode 100644 index 00000000000..9fd79b192f9 --- /dev/null +++ b/test/trap/ok/outrange-int16-lower.wasm-run.ok @@ -0,0 +1 @@ +_out/outrange-int16-lower.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/outrange-int16-negation.run-ir.ok b/test/trap/ok/outrange-int16-negation.run-ir.ok new file mode 100644 index 00000000000..ddbdfed7780 --- /dev/null +++ b/test/trap/ok/outrange-int16-negation.run-ir.ok @@ -0,0 +1 @@ +outrange-int16-negation.as:1.9-1.33: execution error, value out of bounds diff --git a/test/trap/ok/outrange-int16-negation.run-low.ok b/test/trap/ok/outrange-int16-negation.run-low.ok new file mode 100644 index 00000000000..ddbdfed7780 --- /dev/null +++ b/test/trap/ok/outrange-int16-negation.run-low.ok @@ -0,0 +1 @@ +outrange-int16-negation.as:1.9-1.33: execution error, value out of bounds diff --git a/test/trap/ok/outrange-int16-negation.run.ok b/test/trap/ok/outrange-int16-negation.run.ok new file mode 100644 index 00000000000..ddbdfed7780 --- /dev/null +++ b/test/trap/ok/outrange-int16-negation.run.ok @@ -0,0 +1 @@ +outrange-int16-negation.as:1.9-1.33: execution error, value out of bounds diff --git a/test/trap/ok/outrange-int16-negation.wasm-run.ok b/test/trap/ok/outrange-int16-negation.wasm-run.ok new file mode 100644 index 00000000000..b292eceb663 --- /dev/null +++ b/test/trap/ok/outrange-int16-negation.wasm-run.ok @@ -0,0 +1 @@ +_out/outrange-int16-negation.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/outrange-int16-upper.run-ir.ok b/test/trap/ok/outrange-int16-upper.run-ir.ok new file mode 100644 index 00000000000..54a37fcb824 --- /dev/null +++ b/test/trap/ok/outrange-int16-upper.run-ir.ok @@ -0,0 +1 @@ +prelude:79.36-79.72: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int16-upper.run-low.ok b/test/trap/ok/outrange-int16-upper.run-low.ok new file mode 100644 index 00000000000..54a37fcb824 --- /dev/null +++ b/test/trap/ok/outrange-int16-upper.run-low.ok @@ -0,0 +1 @@ +prelude:79.36-79.72: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int16-upper.run.ok b/test/trap/ok/outrange-int16-upper.run.ok new file mode 100644 index 00000000000..54a37fcb824 --- /dev/null +++ b/test/trap/ok/outrange-int16-upper.run.ok @@ -0,0 +1 @@ +prelude:79.36-79.72: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int16-upper.wasm-run.ok b/test/trap/ok/outrange-int16-upper.wasm-run.ok new file mode 100644 index 00000000000..03b9e36d669 --- /dev/null +++ b/test/trap/ok/outrange-int16-upper.wasm-run.ok @@ -0,0 +1 @@ +_out/outrange-int16-upper.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/outrange-int32-lower.run-ir.ok b/test/trap/ok/outrange-int32-lower.run-ir.ok new file mode 100644 index 00000000000..a1f443605b3 --- /dev/null +++ b/test/trap/ok/outrange-int32-lower.run-ir.ok @@ -0,0 +1 @@ +prelude:75.36-75.72: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int32-lower.run-low.ok b/test/trap/ok/outrange-int32-lower.run-low.ok new file mode 100644 index 00000000000..a1f443605b3 --- /dev/null +++ b/test/trap/ok/outrange-int32-lower.run-low.ok @@ -0,0 +1 @@ +prelude:75.36-75.72: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int32-lower.run.ok b/test/trap/ok/outrange-int32-lower.run.ok new file mode 100644 index 00000000000..a1f443605b3 --- /dev/null +++ b/test/trap/ok/outrange-int32-lower.run.ok @@ -0,0 +1 @@ +prelude:75.36-75.72: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int32-lower.wasm-run.ok b/test/trap/ok/outrange-int32-lower.wasm-run.ok new file mode 100644 index 00000000000..a630c1ce2a7 --- /dev/null +++ b/test/trap/ok/outrange-int32-lower.wasm-run.ok @@ -0,0 +1 @@ +_out/outrange-int32-lower.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/outrange-int32-negation.run-ir.ok b/test/trap/ok/outrange-int32-negation.run-ir.ok new file mode 100644 index 00000000000..0f7f8d168ac --- /dev/null +++ b/test/trap/ok/outrange-int32-negation.run-ir.ok @@ -0,0 +1 @@ +outrange-int32-negation.as:1.9-1.33: execution error, value out of bounds diff --git a/test/trap/ok/outrange-int32-negation.run-low.ok b/test/trap/ok/outrange-int32-negation.run-low.ok new file mode 100644 index 00000000000..0f7f8d168ac --- /dev/null +++ b/test/trap/ok/outrange-int32-negation.run-low.ok @@ -0,0 +1 @@ +outrange-int32-negation.as:1.9-1.33: execution error, value out of bounds diff --git a/test/trap/ok/outrange-int32-negation.run.ok b/test/trap/ok/outrange-int32-negation.run.ok new file mode 100644 index 00000000000..0f7f8d168ac --- /dev/null +++ b/test/trap/ok/outrange-int32-negation.run.ok @@ -0,0 +1 @@ +outrange-int32-negation.as:1.9-1.33: execution error, value out of bounds diff --git a/test/trap/ok/outrange-int32-negation.wasm-run.ok b/test/trap/ok/outrange-int32-negation.wasm-run.ok new file mode 100644 index 00000000000..82b07835bd3 --- /dev/null +++ b/test/trap/ok/outrange-int32-negation.wasm-run.ok @@ -0,0 +1 @@ +_out/outrange-int32-negation.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/outrange-int32-upper.run-ir.ok b/test/trap/ok/outrange-int32-upper.run-ir.ok new file mode 100644 index 00000000000..a1f443605b3 --- /dev/null +++ b/test/trap/ok/outrange-int32-upper.run-ir.ok @@ -0,0 +1 @@ +prelude:75.36-75.72: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int32-upper.run-low.ok b/test/trap/ok/outrange-int32-upper.run-low.ok new file mode 100644 index 00000000000..a1f443605b3 --- /dev/null +++ b/test/trap/ok/outrange-int32-upper.run-low.ok @@ -0,0 +1 @@ +prelude:75.36-75.72: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int32-upper.run.ok b/test/trap/ok/outrange-int32-upper.run.ok new file mode 100644 index 00000000000..a1f443605b3 --- /dev/null +++ b/test/trap/ok/outrange-int32-upper.run.ok @@ -0,0 +1 @@ +prelude:75.36-75.72: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int32-upper.wasm-run.ok b/test/trap/ok/outrange-int32-upper.wasm-run.ok new file mode 100644 index 00000000000..ffc335345f7 --- /dev/null +++ b/test/trap/ok/outrange-int32-upper.wasm-run.ok @@ -0,0 +1 @@ +_out/outrange-int32-upper.wasm:0x___: runtime trap: unreachable executed diff --git a/test/fail/ok/outrange-int64lower.run-ir.ok b/test/trap/ok/outrange-int64-lower.run-ir.ok similarity index 100% rename from test/fail/ok/outrange-int64lower.run-ir.ok rename to test/trap/ok/outrange-int64-lower.run-ir.ok diff --git a/test/fail/ok/outrange-int64lower.run-low.ok b/test/trap/ok/outrange-int64-lower.run-low.ok similarity index 100% rename from test/fail/ok/outrange-int64lower.run-low.ok rename to test/trap/ok/outrange-int64-lower.run-low.ok diff --git a/test/fail/ok/outrange-int64lower.run.ok b/test/trap/ok/outrange-int64-lower.run.ok similarity index 100% rename from test/fail/ok/outrange-int64lower.run.ok rename to test/trap/ok/outrange-int64-lower.run.ok diff --git a/test/trap/ok/outrange-int64-lower.wasm-run.ok b/test/trap/ok/outrange-int64-lower.wasm-run.ok new file mode 100644 index 00000000000..a485fbae838 --- /dev/null +++ b/test/trap/ok/outrange-int64-lower.wasm-run.ok @@ -0,0 +1 @@ +_out/outrange-int64-lower.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/outrange-int64-negation.run-ir.ok b/test/trap/ok/outrange-int64-negation.run-ir.ok new file mode 100644 index 00000000000..a02a1a02263 --- /dev/null +++ b/test/trap/ok/outrange-int64-negation.run-ir.ok @@ -0,0 +1 @@ +outrange-int64-negation.as:1.9-1.33: execution error, value out of bounds diff --git a/test/trap/ok/outrange-int64-negation.run-low.ok b/test/trap/ok/outrange-int64-negation.run-low.ok new file mode 100644 index 00000000000..a02a1a02263 --- /dev/null +++ b/test/trap/ok/outrange-int64-negation.run-low.ok @@ -0,0 +1 @@ +outrange-int64-negation.as:1.9-1.33: execution error, value out of bounds diff --git a/test/trap/ok/outrange-int64-negation.run.ok b/test/trap/ok/outrange-int64-negation.run.ok new file mode 100644 index 00000000000..a02a1a02263 --- /dev/null +++ b/test/trap/ok/outrange-int64-negation.run.ok @@ -0,0 +1 @@ +outrange-int64-negation.as:1.9-1.33: execution error, value out of bounds diff --git a/test/trap/ok/outrange-int64-negation.wasm-run.ok b/test/trap/ok/outrange-int64-negation.wasm-run.ok new file mode 100644 index 00000000000..1238f5ad4ec --- /dev/null +++ b/test/trap/ok/outrange-int64-negation.wasm-run.ok @@ -0,0 +1 @@ +_out/outrange-int64-negation.wasm:0x___: runtime trap: unreachable executed diff --git a/test/fail/ok/outrange-int64upper.run-ir.ok b/test/trap/ok/outrange-int64-upper.run-ir.ok similarity index 100% rename from test/fail/ok/outrange-int64upper.run-ir.ok rename to test/trap/ok/outrange-int64-upper.run-ir.ok diff --git a/test/fail/ok/outrange-int64upper.run-low.ok b/test/trap/ok/outrange-int64-upper.run-low.ok similarity index 100% rename from test/fail/ok/outrange-int64upper.run-low.ok rename to test/trap/ok/outrange-int64-upper.run-low.ok diff --git a/test/fail/ok/outrange-int64upper.run.ok b/test/trap/ok/outrange-int64-upper.run.ok similarity index 100% rename from test/fail/ok/outrange-int64upper.run.ok rename to test/trap/ok/outrange-int64-upper.run.ok diff --git a/test/trap/ok/outrange-int64-upper.wasm-run.ok b/test/trap/ok/outrange-int64-upper.wasm-run.ok new file mode 100644 index 00000000000..0dc740b1173 --- /dev/null +++ b/test/trap/ok/outrange-int64-upper.wasm-run.ok @@ -0,0 +1 @@ +_out/outrange-int64-upper.wasm:0x___: runtime trap: unreachable executed diff --git a/test/fail/ok/outrange-int8lower.run-ir.ok b/test/trap/ok/outrange-int8-lower.run-ir.ok similarity index 100% rename from test/fail/ok/outrange-int8lower.run-ir.ok rename to test/trap/ok/outrange-int8-lower.run-ir.ok diff --git a/test/fail/ok/outrange-int8lower.run-low.ok b/test/trap/ok/outrange-int8-lower.run-low.ok similarity index 100% rename from test/fail/ok/outrange-int8lower.run-low.ok rename to test/trap/ok/outrange-int8-lower.run-low.ok diff --git a/test/fail/ok/outrange-int8lower.run.ok b/test/trap/ok/outrange-int8-lower.run.ok similarity index 100% rename from test/fail/ok/outrange-int8lower.run.ok rename to test/trap/ok/outrange-int8-lower.run.ok diff --git a/test/trap/ok/outrange-int8-lower.wasm-run.ok b/test/trap/ok/outrange-int8-lower.wasm-run.ok new file mode 100644 index 00000000000..a6754b244ca --- /dev/null +++ b/test/trap/ok/outrange-int8-lower.wasm-run.ok @@ -0,0 +1 @@ +_out/outrange-int8-lower.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/outrange-int8-negation.run-ir.ok b/test/trap/ok/outrange-int8-negation.run-ir.ok new file mode 100644 index 00000000000..ad485b61ad4 --- /dev/null +++ b/test/trap/ok/outrange-int8-negation.run-ir.ok @@ -0,0 +1 @@ +outrange-int8-negation.as:1.9-1.31: execution error, value out of bounds diff --git a/test/trap/ok/outrange-int8-negation.run-low.ok b/test/trap/ok/outrange-int8-negation.run-low.ok new file mode 100644 index 00000000000..ad485b61ad4 --- /dev/null +++ b/test/trap/ok/outrange-int8-negation.run-low.ok @@ -0,0 +1 @@ +outrange-int8-negation.as:1.9-1.31: execution error, value out of bounds diff --git a/test/trap/ok/outrange-int8-negation.run.ok b/test/trap/ok/outrange-int8-negation.run.ok new file mode 100644 index 00000000000..ad485b61ad4 --- /dev/null +++ b/test/trap/ok/outrange-int8-negation.run.ok @@ -0,0 +1 @@ +outrange-int8-negation.as:1.9-1.31: execution error, value out of bounds diff --git a/test/trap/ok/outrange-int8-negation.wasm-run.ok b/test/trap/ok/outrange-int8-negation.wasm-run.ok new file mode 100644 index 00000000000..d0518678619 --- /dev/null +++ b/test/trap/ok/outrange-int8-negation.wasm-run.ok @@ -0,0 +1 @@ +_out/outrange-int8-negation.wasm:0x___: runtime trap: unreachable executed diff --git a/test/fail/ok/outrange-int8upper.run-ir.ok b/test/trap/ok/outrange-int8-upper.run-ir.ok similarity index 100% rename from test/fail/ok/outrange-int8upper.run-ir.ok rename to test/trap/ok/outrange-int8-upper.run-ir.ok diff --git a/test/fail/ok/outrange-int8upper.run-low.ok b/test/trap/ok/outrange-int8-upper.run-low.ok similarity index 100% rename from test/fail/ok/outrange-int8upper.run-low.ok rename to test/trap/ok/outrange-int8-upper.run-low.ok diff --git a/test/fail/ok/outrange-int8upper.run.ok b/test/trap/ok/outrange-int8-upper.run.ok similarity index 100% rename from test/fail/ok/outrange-int8upper.run.ok rename to test/trap/ok/outrange-int8-upper.run.ok diff --git a/test/trap/ok/outrange-int8-upper.wasm-run.ok b/test/trap/ok/outrange-int8-upper.wasm-run.ok new file mode 100644 index 00000000000..3366993f2a4 --- /dev/null +++ b/test/trap/ok/outrange-int8-upper.wasm-run.ok @@ -0,0 +1 @@ +_out/outrange-int8-upper.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/outrange-nat16.run-ir.ok b/test/trap/ok/outrange-nat16.run-ir.ok new file mode 100644 index 00000000000..db44073a1d2 --- /dev/null +++ b/test/trap/ok/outrange-nat16.run-ir.ok @@ -0,0 +1 @@ +prelude:96.36-96.72: execution error, numeric overflow diff --git a/test/trap/ok/outrange-nat16.run-low.ok b/test/trap/ok/outrange-nat16.run-low.ok new file mode 100644 index 00000000000..db44073a1d2 --- /dev/null +++ b/test/trap/ok/outrange-nat16.run-low.ok @@ -0,0 +1 @@ +prelude:96.36-96.72: execution error, numeric overflow diff --git a/test/trap/ok/outrange-nat16.run.ok b/test/trap/ok/outrange-nat16.run.ok new file mode 100644 index 00000000000..db44073a1d2 --- /dev/null +++ b/test/trap/ok/outrange-nat16.run.ok @@ -0,0 +1 @@ +prelude:96.36-96.72: execution error, numeric overflow diff --git a/test/trap/ok/outrange-nat16.wasm-run.ok b/test/trap/ok/outrange-nat16.wasm-run.ok new file mode 100644 index 00000000000..3e31c22ece7 --- /dev/null +++ b/test/trap/ok/outrange-nat16.wasm-run.ok @@ -0,0 +1 @@ +_out/outrange-nat16.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/outrange-nat32.run-ir.ok b/test/trap/ok/outrange-nat32.run-ir.ok new file mode 100644 index 00000000000..2e6e9e985ca --- /dev/null +++ b/test/trap/ok/outrange-nat32.run-ir.ok @@ -0,0 +1 @@ +prelude:92.36-92.72: execution error, numeric overflow diff --git a/test/trap/ok/outrange-nat32.run-low.ok b/test/trap/ok/outrange-nat32.run-low.ok new file mode 100644 index 00000000000..2e6e9e985ca --- /dev/null +++ b/test/trap/ok/outrange-nat32.run-low.ok @@ -0,0 +1 @@ +prelude:92.36-92.72: execution error, numeric overflow diff --git a/test/trap/ok/outrange-nat32.run.ok b/test/trap/ok/outrange-nat32.run.ok new file mode 100644 index 00000000000..2e6e9e985ca --- /dev/null +++ b/test/trap/ok/outrange-nat32.run.ok @@ -0,0 +1 @@ +prelude:92.36-92.72: execution error, numeric overflow diff --git a/test/trap/ok/outrange-nat32.wasm-run.ok b/test/trap/ok/outrange-nat32.wasm-run.ok new file mode 100644 index 00000000000..e3d912613a5 --- /dev/null +++ b/test/trap/ok/outrange-nat32.wasm-run.ok @@ -0,0 +1 @@ +_out/outrange-nat32.wasm:0x___: runtime trap: unreachable executed diff --git a/test/fail/ok/outrange-nat64.run-ir.ok b/test/trap/ok/outrange-nat64.run-ir.ok similarity index 100% rename from test/fail/ok/outrange-nat64.run-ir.ok rename to test/trap/ok/outrange-nat64.run-ir.ok diff --git a/test/fail/ok/outrange-nat64.run-low.ok b/test/trap/ok/outrange-nat64.run-low.ok similarity index 100% rename from test/fail/ok/outrange-nat64.run-low.ok rename to test/trap/ok/outrange-nat64.run-low.ok diff --git a/test/fail/ok/outrange-nat64.run.ok b/test/trap/ok/outrange-nat64.run.ok similarity index 100% rename from test/fail/ok/outrange-nat64.run.ok rename to test/trap/ok/outrange-nat64.run.ok diff --git a/test/fail/ok/outrange-nat64.wasm-run.ok b/test/trap/ok/outrange-nat64.wasm-run.ok similarity index 100% rename from test/fail/ok/outrange-nat64.wasm-run.ok rename to test/trap/ok/outrange-nat64.wasm-run.ok diff --git a/test/fail/ok/outrange-nat8.run-ir.ok b/test/trap/ok/outrange-nat8.run-ir.ok similarity index 100% rename from test/fail/ok/outrange-nat8.run-ir.ok rename to test/trap/ok/outrange-nat8.run-ir.ok diff --git a/test/fail/ok/outrange-nat8.run-low.ok b/test/trap/ok/outrange-nat8.run-low.ok similarity index 100% rename from test/fail/ok/outrange-nat8.run-low.ok rename to test/trap/ok/outrange-nat8.run-low.ok diff --git a/test/fail/ok/outrange-nat8.run.ok b/test/trap/ok/outrange-nat8.run.ok similarity index 100% rename from test/fail/ok/outrange-nat8.run.ok rename to test/trap/ok/outrange-nat8.run.ok diff --git a/test/fail/ok/outrange-nat8.wasm-run.ok b/test/trap/ok/outrange-nat8.wasm-run.ok similarity index 100% rename from test/fail/ok/outrange-nat8.wasm-run.ok rename to test/trap/ok/outrange-nat8.wasm-run.ok diff --git a/test/trap/ok/subInt16-lower.run-ir.ok b/test/trap/ok/subInt16-lower.run-ir.ok new file mode 100644 index 00000000000..22d529184b6 --- /dev/null +++ b/test/trap/ok/subInt16-lower.run-ir.ok @@ -0,0 +1 @@ +subInt16-lower.as:1.9-1.39: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt16-lower.run-low.ok b/test/trap/ok/subInt16-lower.run-low.ok new file mode 100644 index 00000000000..22d529184b6 --- /dev/null +++ b/test/trap/ok/subInt16-lower.run-low.ok @@ -0,0 +1 @@ +subInt16-lower.as:1.9-1.39: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt16-lower.run.ok b/test/trap/ok/subInt16-lower.run.ok new file mode 100644 index 00000000000..22d529184b6 --- /dev/null +++ b/test/trap/ok/subInt16-lower.run.ok @@ -0,0 +1 @@ +subInt16-lower.as:1.9-1.39: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt16-lower.wasm-run.ok b/test/trap/ok/subInt16-lower.wasm-run.ok new file mode 100644 index 00000000000..a1b0d29f73e --- /dev/null +++ b/test/trap/ok/subInt16-lower.wasm-run.ok @@ -0,0 +1 @@ +_out/subInt16-lower.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/subInt16-upper.run-ir.ok b/test/trap/ok/subInt16-upper.run-ir.ok new file mode 100644 index 00000000000..c440d4eaa3b --- /dev/null +++ b/test/trap/ok/subInt16-upper.run-ir.ok @@ -0,0 +1 @@ +subInt16-upper.as:1.9-1.39: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt16-upper.run-low.ok b/test/trap/ok/subInt16-upper.run-low.ok new file mode 100644 index 00000000000..c440d4eaa3b --- /dev/null +++ b/test/trap/ok/subInt16-upper.run-low.ok @@ -0,0 +1 @@ +subInt16-upper.as:1.9-1.39: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt16-upper.run.ok b/test/trap/ok/subInt16-upper.run.ok new file mode 100644 index 00000000000..c440d4eaa3b --- /dev/null +++ b/test/trap/ok/subInt16-upper.run.ok @@ -0,0 +1 @@ +subInt16-upper.as:1.9-1.39: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt16-upper.wasm-run.ok b/test/trap/ok/subInt16-upper.wasm-run.ok new file mode 100644 index 00000000000..2382e27d4e8 --- /dev/null +++ b/test/trap/ok/subInt16-upper.wasm-run.ok @@ -0,0 +1 @@ +_out/subInt16-upper.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/subInt32-lower.run-ir.ok b/test/trap/ok/subInt32-lower.run-ir.ok new file mode 100644 index 00000000000..11e292f395f --- /dev/null +++ b/test/trap/ok/subInt32-lower.run-ir.ok @@ -0,0 +1 @@ +subInt32-lower.as:1.9-1.47: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt32-lower.run-low.ok b/test/trap/ok/subInt32-lower.run-low.ok new file mode 100644 index 00000000000..11e292f395f --- /dev/null +++ b/test/trap/ok/subInt32-lower.run-low.ok @@ -0,0 +1 @@ +subInt32-lower.as:1.9-1.47: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt32-lower.run.ok b/test/trap/ok/subInt32-lower.run.ok new file mode 100644 index 00000000000..11e292f395f --- /dev/null +++ b/test/trap/ok/subInt32-lower.run.ok @@ -0,0 +1 @@ +subInt32-lower.as:1.9-1.47: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt32-lower.wasm-run.ok b/test/trap/ok/subInt32-lower.wasm-run.ok new file mode 100644 index 00000000000..c7aaeeb70fa --- /dev/null +++ b/test/trap/ok/subInt32-lower.wasm-run.ok @@ -0,0 +1 @@ +_out/subInt32-lower.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/subInt32-upper.run-ir.ok b/test/trap/ok/subInt32-upper.run-ir.ok new file mode 100644 index 00000000000..b1db8940b4c --- /dev/null +++ b/test/trap/ok/subInt32-upper.run-ir.ok @@ -0,0 +1 @@ +subInt32-upper.as:1.9-1.47: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt32-upper.run-low.ok b/test/trap/ok/subInt32-upper.run-low.ok new file mode 100644 index 00000000000..b1db8940b4c --- /dev/null +++ b/test/trap/ok/subInt32-upper.run-low.ok @@ -0,0 +1 @@ +subInt32-upper.as:1.9-1.47: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt32-upper.run.ok b/test/trap/ok/subInt32-upper.run.ok new file mode 100644 index 00000000000..b1db8940b4c --- /dev/null +++ b/test/trap/ok/subInt32-upper.run.ok @@ -0,0 +1 @@ +subInt32-upper.as:1.9-1.47: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt32-upper.wasm-run.ok b/test/trap/ok/subInt32-upper.wasm-run.ok new file mode 100644 index 00000000000..7ef9e891064 --- /dev/null +++ b/test/trap/ok/subInt32-upper.wasm-run.ok @@ -0,0 +1 @@ +_out/subInt32-upper.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/subInt64-lower.run-ir.ok b/test/trap/ok/subInt64-lower.run-ir.ok new file mode 100644 index 00000000000..f3f2790aaf7 --- /dev/null +++ b/test/trap/ok/subInt64-lower.run-ir.ok @@ -0,0 +1 @@ +subInt64-lower.as:1.9-1.59: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt64-lower.run-low.ok b/test/trap/ok/subInt64-lower.run-low.ok new file mode 100644 index 00000000000..f3f2790aaf7 --- /dev/null +++ b/test/trap/ok/subInt64-lower.run-low.ok @@ -0,0 +1 @@ +subInt64-lower.as:1.9-1.59: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt64-lower.run.ok b/test/trap/ok/subInt64-lower.run.ok new file mode 100644 index 00000000000..f3f2790aaf7 --- /dev/null +++ b/test/trap/ok/subInt64-lower.run.ok @@ -0,0 +1 @@ +subInt64-lower.as:1.9-1.59: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt64-lower.wasm-run.ok b/test/trap/ok/subInt64-lower.wasm-run.ok new file mode 100644 index 00000000000..e5e991412ee --- /dev/null +++ b/test/trap/ok/subInt64-lower.wasm-run.ok @@ -0,0 +1 @@ +_out/subInt64-lower.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/subInt64-upper.run-ir.ok b/test/trap/ok/subInt64-upper.run-ir.ok new file mode 100644 index 00000000000..5f3501be12a --- /dev/null +++ b/test/trap/ok/subInt64-upper.run-ir.ok @@ -0,0 +1 @@ +subInt64-upper.as:1.9-1.59: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt64-upper.run-low.ok b/test/trap/ok/subInt64-upper.run-low.ok new file mode 100644 index 00000000000..5f3501be12a --- /dev/null +++ b/test/trap/ok/subInt64-upper.run-low.ok @@ -0,0 +1 @@ +subInt64-upper.as:1.9-1.59: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt64-upper.run.ok b/test/trap/ok/subInt64-upper.run.ok new file mode 100644 index 00000000000..5f3501be12a --- /dev/null +++ b/test/trap/ok/subInt64-upper.run.ok @@ -0,0 +1 @@ +subInt64-upper.as:1.9-1.59: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt64-upper.wasm-run.ok b/test/trap/ok/subInt64-upper.wasm-run.ok new file mode 100644 index 00000000000..0c8ea0c1929 --- /dev/null +++ b/test/trap/ok/subInt64-upper.wasm-run.ok @@ -0,0 +1 @@ +_out/subInt64-upper.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/subInt8-lower.run-ir.ok b/test/trap/ok/subInt8-lower.run-ir.ok new file mode 100644 index 00000000000..ead4dc243a5 --- /dev/null +++ b/test/trap/ok/subInt8-lower.run-ir.ok @@ -0,0 +1 @@ +subInt8-lower.as:1.9-1.35: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt8-lower.run-low.ok b/test/trap/ok/subInt8-lower.run-low.ok new file mode 100644 index 00000000000..ead4dc243a5 --- /dev/null +++ b/test/trap/ok/subInt8-lower.run-low.ok @@ -0,0 +1 @@ +subInt8-lower.as:1.9-1.35: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt8-lower.run.ok b/test/trap/ok/subInt8-lower.run.ok new file mode 100644 index 00000000000..ead4dc243a5 --- /dev/null +++ b/test/trap/ok/subInt8-lower.run.ok @@ -0,0 +1 @@ +subInt8-lower.as:1.9-1.35: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt8-lower.wasm-run.ok b/test/trap/ok/subInt8-lower.wasm-run.ok new file mode 100644 index 00000000000..9ca860506a2 --- /dev/null +++ b/test/trap/ok/subInt8-lower.wasm-run.ok @@ -0,0 +1 @@ +_out/subInt8-lower.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/subInt8-upper.run-ir.ok b/test/trap/ok/subInt8-upper.run-ir.ok new file mode 100644 index 00000000000..9ae20177fb6 --- /dev/null +++ b/test/trap/ok/subInt8-upper.run-ir.ok @@ -0,0 +1 @@ +subInt8-upper.as:1.9-1.35: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt8-upper.run-low.ok b/test/trap/ok/subInt8-upper.run-low.ok new file mode 100644 index 00000000000..9ae20177fb6 --- /dev/null +++ b/test/trap/ok/subInt8-upper.run-low.ok @@ -0,0 +1 @@ +subInt8-upper.as:1.9-1.35: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt8-upper.run.ok b/test/trap/ok/subInt8-upper.run.ok new file mode 100644 index 00000000000..9ae20177fb6 --- /dev/null +++ b/test/trap/ok/subInt8-upper.run.ok @@ -0,0 +1 @@ +subInt8-upper.as:1.9-1.35: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt8-upper.wasm-run.ok b/test/trap/ok/subInt8-upper.wasm-run.ok new file mode 100644 index 00000000000..52d843336fb --- /dev/null +++ b/test/trap/ok/subInt8-upper.wasm-run.ok @@ -0,0 +1 @@ +_out/subInt8-upper.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/subNat16.run-ir.ok b/test/trap/ok/subNat16.run-ir.ok new file mode 100644 index 00000000000..3667438a5e7 --- /dev/null +++ b/test/trap/ok/subNat16.run-ir.ok @@ -0,0 +1 @@ +subNat16.as:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/subNat16.run-low.ok b/test/trap/ok/subNat16.run-low.ok new file mode 100644 index 00000000000..3667438a5e7 --- /dev/null +++ b/test/trap/ok/subNat16.run-low.ok @@ -0,0 +1 @@ +subNat16.as:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/subNat16.run.ok b/test/trap/ok/subNat16.run.ok new file mode 100644 index 00000000000..3667438a5e7 --- /dev/null +++ b/test/trap/ok/subNat16.run.ok @@ -0,0 +1 @@ +subNat16.as:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/subNat16.wasm-run.ok b/test/trap/ok/subNat16.wasm-run.ok new file mode 100644 index 00000000000..f7323ad6059 --- /dev/null +++ b/test/trap/ok/subNat16.wasm-run.ok @@ -0,0 +1 @@ +_out/subNat16.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/subNat32.run-ir.ok b/test/trap/ok/subNat32.run-ir.ok new file mode 100644 index 00000000000..398ff3eef50 --- /dev/null +++ b/test/trap/ok/subNat32.run-ir.ok @@ -0,0 +1 @@ +subNat32.as:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/subNat32.run-low.ok b/test/trap/ok/subNat32.run-low.ok new file mode 100644 index 00000000000..398ff3eef50 --- /dev/null +++ b/test/trap/ok/subNat32.run-low.ok @@ -0,0 +1 @@ +subNat32.as:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/subNat32.run.ok b/test/trap/ok/subNat32.run.ok new file mode 100644 index 00000000000..398ff3eef50 --- /dev/null +++ b/test/trap/ok/subNat32.run.ok @@ -0,0 +1 @@ +subNat32.as:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/subNat32.wasm-run.ok b/test/trap/ok/subNat32.wasm-run.ok new file mode 100644 index 00000000000..508878f6747 --- /dev/null +++ b/test/trap/ok/subNat32.wasm-run.ok @@ -0,0 +1 @@ +_out/subNat32.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/subNat64.run-ir.ok b/test/trap/ok/subNat64.run-ir.ok new file mode 100644 index 00000000000..c06ed2bd1f9 --- /dev/null +++ b/test/trap/ok/subNat64.run-ir.ok @@ -0,0 +1 @@ +subNat64.as:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/subNat64.run-low.ok b/test/trap/ok/subNat64.run-low.ok new file mode 100644 index 00000000000..c06ed2bd1f9 --- /dev/null +++ b/test/trap/ok/subNat64.run-low.ok @@ -0,0 +1 @@ +subNat64.as:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/subNat64.run.ok b/test/trap/ok/subNat64.run.ok new file mode 100644 index 00000000000..c06ed2bd1f9 --- /dev/null +++ b/test/trap/ok/subNat64.run.ok @@ -0,0 +1 @@ +subNat64.as:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/subNat64.wasm-run.ok b/test/trap/ok/subNat64.wasm-run.ok new file mode 100644 index 00000000000..8cede90807f --- /dev/null +++ b/test/trap/ok/subNat64.wasm-run.ok @@ -0,0 +1 @@ +_out/subNat64.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/subNat8.run-ir.ok b/test/trap/ok/subNat8.run-ir.ok new file mode 100644 index 00000000000..d0dfd63bcad --- /dev/null +++ b/test/trap/ok/subNat8.run-ir.ok @@ -0,0 +1 @@ +subNat8.as:1.9-1.34: execution error, arithmetic overflow diff --git a/test/trap/ok/subNat8.run-low.ok b/test/trap/ok/subNat8.run-low.ok new file mode 100644 index 00000000000..d0dfd63bcad --- /dev/null +++ b/test/trap/ok/subNat8.run-low.ok @@ -0,0 +1 @@ +subNat8.as:1.9-1.34: execution error, arithmetic overflow diff --git a/test/trap/ok/subNat8.run.ok b/test/trap/ok/subNat8.run.ok new file mode 100644 index 00000000000..d0dfd63bcad --- /dev/null +++ b/test/trap/ok/subNat8.run.ok @@ -0,0 +1 @@ +subNat8.as:1.9-1.34: execution error, arithmetic overflow diff --git a/test/trap/ok/subNat8.wasm-run.ok b/test/trap/ok/subNat8.wasm-run.ok new file mode 100644 index 00000000000..7fd00f66dcb --- /dev/null +++ b/test/trap/ok/subNat8.wasm-run.ok @@ -0,0 +1 @@ +_out/subNat8.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/outrange-int16-lower.as b/test/trap/outrange-int16-lower.as new file mode 100644 index 00000000000..51f97e6b3fc --- /dev/null +++ b/test/trap/outrange-int16-lower.as @@ -0,0 +1 @@ +let _ = intToInt16 (-32769) diff --git a/test/trap/outrange-int16-negation.as b/test/trap/outrange-int16-negation.as new file mode 100644 index 00000000000..b144fc7c120 --- /dev/null +++ b/test/trap/outrange-int16-negation.as @@ -0,0 +1 @@ +let _ = - intToInt16 (- 2 ** 15); // this should trap diff --git a/test/trap/outrange-int16-upper.as b/test/trap/outrange-int16-upper.as new file mode 100644 index 00000000000..568450cced3 --- /dev/null +++ b/test/trap/outrange-int16-upper.as @@ -0,0 +1 @@ +let _ = intToInt16 (2 ** 15); diff --git a/test/trap/outrange-int32-lower.as b/test/trap/outrange-int32-lower.as new file mode 100644 index 00000000000..2c319773417 --- /dev/null +++ b/test/trap/outrange-int32-lower.as @@ -0,0 +1 @@ +let _ = intToInt32 (-2147483649) diff --git a/test/trap/outrange-int32-negation.as b/test/trap/outrange-int32-negation.as new file mode 100644 index 00000000000..d7c164e2764 --- /dev/null +++ b/test/trap/outrange-int32-negation.as @@ -0,0 +1 @@ +let _ = - intToInt32 (- 2 ** 31); // this should trap diff --git a/test/trap/outrange-int32-upper.as b/test/trap/outrange-int32-upper.as new file mode 100644 index 00000000000..a7091425e94 --- /dev/null +++ b/test/trap/outrange-int32-upper.as @@ -0,0 +1 @@ +let _ = intToInt32 (2 ** 31); diff --git a/test/fail/outrange-int64lower.as b/test/trap/outrange-int64-lower.as similarity index 100% rename from test/fail/outrange-int64lower.as rename to test/trap/outrange-int64-lower.as diff --git a/test/fail/outrange-int64negation.as b/test/trap/outrange-int64-negation.as similarity index 100% rename from test/fail/outrange-int64negation.as rename to test/trap/outrange-int64-negation.as diff --git a/test/fail/outrange-int64upper.as b/test/trap/outrange-int64-upper.as similarity index 100% rename from test/fail/outrange-int64upper.as rename to test/trap/outrange-int64-upper.as diff --git a/test/fail/outrange-int8lower.as b/test/trap/outrange-int8-lower.as similarity index 100% rename from test/fail/outrange-int8lower.as rename to test/trap/outrange-int8-lower.as diff --git a/test/trap/outrange-int8-negation.as b/test/trap/outrange-int8-negation.as new file mode 100644 index 00000000000..bbfebafb79d --- /dev/null +++ b/test/trap/outrange-int8-negation.as @@ -0,0 +1 @@ +let _ = - intToInt8 (- 2 ** 7); // this should trap diff --git a/test/fail/outrange-int8upper.as b/test/trap/outrange-int8-upper.as similarity index 100% rename from test/fail/outrange-int8upper.as rename to test/trap/outrange-int8-upper.as diff --git a/test/trap/outrange-nat16.as b/test/trap/outrange-nat16.as new file mode 100644 index 00000000000..2c16854aa64 --- /dev/null +++ b/test/trap/outrange-nat16.as @@ -0,0 +1 @@ +let _ = natToNat16 (2 ** 16); diff --git a/test/trap/outrange-nat32.as b/test/trap/outrange-nat32.as new file mode 100644 index 00000000000..bbd1c242388 --- /dev/null +++ b/test/trap/outrange-nat32.as @@ -0,0 +1 @@ +let _ = natToNat32 (2 ** 32); diff --git a/test/fail/outrange-nat64.as b/test/trap/outrange-nat64.as similarity index 100% rename from test/fail/outrange-nat64.as rename to test/trap/outrange-nat64.as diff --git a/test/fail/outrange-nat8.as b/test/trap/outrange-nat8.as similarity index 100% rename from test/fail/outrange-nat8.as rename to test/trap/outrange-nat8.as diff --git a/test/trap/subInt16-lower.as b/test/trap/subInt16-lower.as new file mode 100644 index 00000000000..c5baae2cd94 --- /dev/null +++ b/test/trap/subInt16-lower.as @@ -0,0 +1 @@ +let _ = (-32767 : Int16) - (2 : Int16) diff --git a/test/trap/subInt16-upper.as b/test/trap/subInt16-upper.as new file mode 100644 index 00000000000..5a562a2cfcc --- /dev/null +++ b/test/trap/subInt16-upper.as @@ -0,0 +1 @@ +let _ = (32767 : Int16) - (-1 : Int16) diff --git a/test/trap/subInt32-lower.as b/test/trap/subInt32-lower.as new file mode 100644 index 00000000000..dedff750eb4 --- /dev/null +++ b/test/trap/subInt32-lower.as @@ -0,0 +1 @@ +let _ = (-2_147_483_647 : Int32) - (2 : Int32) diff --git a/test/trap/subInt32-upper.as b/test/trap/subInt32-upper.as new file mode 100644 index 00000000000..98a37647bd1 --- /dev/null +++ b/test/trap/subInt32-upper.as @@ -0,0 +1 @@ +let _ = (2_147_483_647 : Int32) - (-1 : Int32) diff --git a/test/trap/subInt64-lower.as b/test/trap/subInt64-lower.as new file mode 100644 index 00000000000..684bf24aa49 --- /dev/null +++ b/test/trap/subInt64-lower.as @@ -0,0 +1 @@ +let _ = (-9_223_372_036_854_775_807 : Int64) - (2 : Int64) diff --git a/test/trap/subInt64-upper.as b/test/trap/subInt64-upper.as new file mode 100644 index 00000000000..437399dba54 --- /dev/null +++ b/test/trap/subInt64-upper.as @@ -0,0 +1 @@ +let _ = (9_223_372_036_854_775_807 : Int64) - (-1 : Int64) diff --git a/test/trap/subInt8-lower.as b/test/trap/subInt8-lower.as new file mode 100644 index 00000000000..fd9108d0da1 --- /dev/null +++ b/test/trap/subInt8-lower.as @@ -0,0 +1 @@ +let _ = (-127 : Int8) - (2 : Int8) diff --git a/test/trap/subInt8-upper.as b/test/trap/subInt8-upper.as new file mode 100644 index 00000000000..46748c84f3e --- /dev/null +++ b/test/trap/subInt8-upper.as @@ -0,0 +1 @@ +let _ = (127 : Int8) - (-1 : Int8) diff --git a/test/trap/subNat16.as b/test/trap/subNat16.as new file mode 100644 index 00000000000..5bd0f3f3353 --- /dev/null +++ b/test/trap/subNat16.as @@ -0,0 +1 @@ +let _ = (42 : Nat16) - (43 : Nat16) diff --git a/test/trap/subNat32.as b/test/trap/subNat32.as new file mode 100644 index 00000000000..646fa1c4ff3 --- /dev/null +++ b/test/trap/subNat32.as @@ -0,0 +1 @@ +let _ = (42 : Nat32) - (43 : Nat32) diff --git a/test/trap/subNat64.as b/test/trap/subNat64.as new file mode 100644 index 00000000000..bee4cff4395 --- /dev/null +++ b/test/trap/subNat64.as @@ -0,0 +1 @@ +let _ = (42 : Nat64) - (43 : Nat64) diff --git a/test/trap/subNat8.as b/test/trap/subNat8.as new file mode 100644 index 00000000000..b386f2bbe20 --- /dev/null +++ b/test/trap/subNat8.as @@ -0,0 +1 @@ +let _ = (42 : Nat8) - (43 : Nat8) From 167aab073ae93d81634b12f77aabf510d6fdad33 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Thu, 27 Jun 2019 16:40:01 +0100 Subject: [PATCH 0218/1176] update test output for issue551.as --- test/run/ok/issue551.diff-ir.ok | 5 ----- test/run/ok/issue551.diff-low.ok | 5 ----- test/run/ok/issue551.run-ir.ok | 2 -- test/run/ok/issue551.run-low.ok | 2 -- test/run/ok/issue551.wasm.stderr.ok | 2 -- 5 files changed, 16 deletions(-) delete mode 100644 test/run/ok/issue551.diff-ir.ok delete mode 100644 test/run/ok/issue551.diff-low.ok delete mode 100644 test/run/ok/issue551.run-ir.ok delete mode 100644 test/run/ok/issue551.run-low.ok delete mode 100644 test/run/ok/issue551.wasm.stderr.ok diff --git a/test/run/ok/issue551.diff-ir.ok b/test/run/ok/issue551.diff-ir.ok deleted file mode 100644 index 60b19919a53..00000000000 --- a/test/run/ok/issue551.diff-ir.ok +++ /dev/null @@ -1,5 +0,0 @@ ---- issue551.run -+++ issue551.run-ir -@@ -0,0 +1,2 @@ -+Ill-typed intermediate code after Translate show (use -v to see dumped IR): -+(unknown location): IR type error, free type constructor B diff --git a/test/run/ok/issue551.diff-low.ok b/test/run/ok/issue551.diff-low.ok deleted file mode 100644 index c413d986827..00000000000 --- a/test/run/ok/issue551.diff-low.ok +++ /dev/null @@ -1,5 +0,0 @@ ---- issue551.run -+++ issue551.run-low -@@ -0,0 +1,2 @@ -+Ill-typed intermediate code after Translate show (use -v to see dumped IR): -+(unknown location): IR type error, free type constructor B diff --git a/test/run/ok/issue551.run-ir.ok b/test/run/ok/issue551.run-ir.ok deleted file mode 100644 index ff73e2b2806..00000000000 --- a/test/run/ok/issue551.run-ir.ok +++ /dev/null @@ -1,2 +0,0 @@ -Ill-typed intermediate code after Translate show (use -v to see dumped IR): -(unknown location): IR type error, free type constructor B diff --git a/test/run/ok/issue551.run-low.ok b/test/run/ok/issue551.run-low.ok deleted file mode 100644 index ff73e2b2806..00000000000 --- a/test/run/ok/issue551.run-low.ok +++ /dev/null @@ -1,2 +0,0 @@ -Ill-typed intermediate code after Translate show (use -v to see dumped IR): -(unknown location): IR type error, free type constructor B diff --git a/test/run/ok/issue551.wasm.stderr.ok b/test/run/ok/issue551.wasm.stderr.ok deleted file mode 100644 index ff73e2b2806..00000000000 --- a/test/run/ok/issue551.wasm.stderr.ok +++ /dev/null @@ -1,2 +0,0 @@ -Ill-typed intermediate code after Translate show (use -v to see dumped IR): -(unknown location): IR type error, free type constructor B From 5080e67ca0874e78e9d59522062910fba763476e Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Fri, 28 Jun 2019 13:52:24 -0700 Subject: [PATCH 0219/1176] refactor idlHash to use uint32 type --- idl/.gitignore | 8 -------- idl/.merlin | 4 ---- src/codegen/compile.ml | 8 +------- src/idllib/arrange_idl.ml | 2 +- src/idllib/dune | 2 +- src/idllib/idlHash.ml | 8 ++++---- src/idllib/idlHash.mli | 2 +- src/idllib/parser.mly | 13 ++++++++----- src/idllib/syntax.ml | 2 +- src/idllib/typing.ml | 5 ++--- src/lib/lib.ml | 19 +++++++++++++++++++ src/lib/lib.mli | 16 ++++++++++++++++ test/idl/ok/fields.js.ok | 13 +++++++------ test/idl/ok/import.js.ok | 2 +- test/idl/ok/import1.js.ok | 2 +- test/idl/ok/import3.js.ok | 2 +- test/idl/ok/px.js.ok | 2 +- test/idl/ok/recursion.js.ok | 2 +- test/idl/ok/unicode.js.ok | 6 +++--- 19 files changed, 69 insertions(+), 49 deletions(-) delete mode 100644 idl/.gitignore delete mode 100644 idl/.merlin diff --git a/idl/.gitignore b/idl/.gitignore deleted file mode 100644 index 4e46efe60a5..00000000000 --- a/idl/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -*.cmo -*.cmx -*.native -*.byte -*.opt -*.unopt -*.mlpack -didc diff --git a/idl/.merlin b/idl/.merlin deleted file mode 100644 index 7e0e2689936..00000000000 --- a/idl/.merlin +++ /dev/null @@ -1,4 +0,0 @@ -B _build -PKG stdint wasm num vlq yojson -FLG -w +a-4-27-30-42-44-45 - diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index ad466cec5e4..22a11901e43 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -2778,15 +2778,9 @@ module Serialization = struct *) let typ_id : Type.typ -> string = Type.string_of_typ - let unsigned_compare i1 i2 = - (* int32 is signed, but we want unsigned comparision *) - if i1 < 0l && i2 >= 0l then 1 - else if i1 >= 0l && i2 < 0l then -1 - else compare i1 i2 - let sort_by_hash fs = List.sort - (fun (h1,_) (h2,_) -> unsigned_compare h1 h2) + (fun (h1,_) (h2,_) -> Lib.Uint32.compare h1 h2) (List.map (fun f -> (Idllib.IdlHash.idl_hash f.Type.lab, f)) fs) (* Checks whether the serialization of a given type could contain references *) diff --git a/src/idllib/arrange_idl.ml b/src/idllib/arrange_idl.ml index 27b7bf300c3..39cb25eef1c 100644 --- a/src/idllib/arrange_idl.ml +++ b/src/idllib/arrange_idl.ml @@ -32,7 +32,7 @@ and id i = Atom i.it and tag i = Atom ("#" ^ i.it) let field_tag (tf : typ_field) - = tf.it.name.it ^ "(" ^ Int32.to_string tf.it.id ^ ")" + = tf.it.name.it ^ "(" ^ Lib.Uint32.to_string tf.it.id ^ ")" let rec typ_field (tf : typ_field) = field_tag tf $$ [typ tf.it.typ] diff --git a/src/idllib/dune b/src/idllib/dune index 2f5499a2b6b..29b1abcce11 100644 --- a/src/idllib/dune +++ b/src/idllib/dune @@ -1,6 +1,6 @@ (library (name idllib) - (libraries wasm lang_utils) + (libraries lib wasm lang_utils) ) (menhir diff --git a/src/idllib/idlHash.ml b/src/idllib/idlHash.ml index 4d03804b8c4..f80993440f2 100644 --- a/src/idllib/idlHash.ml +++ b/src/idllib/idlHash.ml @@ -1,8 +1,8 @@ (* IDL field hashes *) -let idl_hash : string -> int32 = fun s -> - let open Int32 in +let idl_hash : string -> Lib.Uint32.t = fun s -> + let open Lib.Uint32 in List.fold_left - (fun s c -> add (mul s 223l) (of_int (Char.code c))) - 0l + (fun s c -> add (mul s (of_int 223)) (of_int (Char.code c))) + zero (* TODO: also unescape the string, once #465 is approved *) (Lib.String.explode s) diff --git a/src/idllib/idlHash.mli b/src/idllib/idlHash.mli index 06bb62ab1c1..fded26512ee 100644 --- a/src/idllib/idlHash.mli +++ b/src/idllib/idlHash.mli @@ -1 +1 @@ -val idl_hash : string -> int32 +val idl_hash : string -> Lib.Uint32.t diff --git a/src/idllib/parser.mly b/src/idllib/parser.mly index a1ba1b23e64..4080faaee7d 100644 --- a/src/idllib/parser.mly +++ b/src/idllib/parser.mly @@ -3,6 +3,8 @@ open Syntax open Source +module Uint32 = Lib.Uint32 + (* Position handling *) let position_to_pos position = @@ -34,14 +36,15 @@ let get_func_mode m = List.assoc m func_modes let hash = IdlHash.idl_hash let record_fields fs = + let open Uint32 in let rec go start fs = match fs with | [] -> [] | hd :: tl -> let field = hd start in - let next = Int32.succ field.it.id in + let next = succ field.it.id in field :: (go next tl) - in go 0l fs + in go zero fs %} %token EOF @@ -89,21 +92,21 @@ ref_typ : field_typ : | n=NAT COLON t=data_typ - { { id = Int32.of_string n; name = n @@ at $loc(n); typ = t } @@ at $sloc } + { { id = Uint32.of_string n; name = n @@ at $loc(n); typ = t } @@ at $sloc } | name=name COLON t=data_typ { { id = hash name.it; name = name; typ = t } @@ at $sloc } record_typ : | f=field_typ { fun _ -> f } | t=data_typ - { fun x -> { id = x; name = Int32.to_string x @@ no_region; typ = t } @@ at $sloc } + { fun x -> { id = x; name = Uint32.to_string x @@ no_region; typ = t } @@ at $sloc } variant_typ : | f=field_typ { f } | name=name { { id = hash name.it; name = name; typ = PrimT Null @@ no_region } @@ at $sloc } | n=NAT - { { id = Int32.of_string n; name = n @@ at $loc(n); typ = PrimT Null @@ no_region } @@ at $sloc } + { { id = Uint32.of_string n; name = n @@ at $loc(n); typ = PrimT Null @@ no_region } @@ at $sloc } record_typs : | LCURLY fs=seplist(record_typ, SEMICOLON) RCURLY diff --git a/src/idllib/syntax.ml b/src/idllib/syntax.ml index ed462e465e4..f43dd2e89c1 100644 --- a/src/idllib/syntax.ml +++ b/src/idllib/syntax.ml @@ -39,7 +39,7 @@ and typ' = | PreT (* pre-type *) and typ_field = typ_field' Source.phrase -and typ_field' = { id : int32; name : id; typ : typ } +and typ_field' = { id : Lib.Uint32.t; name : id; typ : typ } and typ_meth = typ_meth' Source.phrase and typ_meth' = {var : id; meth : typ} diff --git a/src/idllib/typing.ml b/src/idllib/typing.ml index 23c9d08e68d..2c531e2eed4 100644 --- a/src/idllib/typing.ml +++ b/src/idllib/typing.ml @@ -3,7 +3,7 @@ open Source open Arrange_idl (* Environments *) -module FieldEnv = Env.Make(Int32) +module FieldEnv = Env.Make(Lib.Uint32) module Env = Env.Make(String) module TS = Set.Make(String) @@ -61,8 +61,7 @@ let disjoint_union env at fmt env1 env2 = with Env.Clash k -> error env at fmt k (* Types *) - -let compare_field (f1: typ_field) (f2: typ_field) = compare f1.it.id f2.it.id +let compare_field (f1: typ_field) (f2: typ_field) = Lib.Uint32.compare f1.it.id f2.it.id let compare_meth (m1: typ_meth) (m2: typ_meth) = compare m1.it.var m2.it.var let find_type env id = match Env.find_opt id.it env.typs with diff --git a/src/lib/lib.ml b/src/lib/lib.ml index 6f4b86fb765..e212dd52e7d 100644 --- a/src/lib/lib.ml +++ b/src/lib/lib.ml @@ -21,6 +21,25 @@ struct n <> 0 && n land (n - 1) = 0 end +module Uint32 = +struct + type t = int32 + let of_string = Int32.of_string + let to_string n = Printf.sprintf "%lu" n + let add = Int32.add + let sub = Int32.sub + let mul = Int32.mul + let succ = Int32.succ + let zero = Int32.zero + let one = Int32.one + let of_int = Int32.of_int + let to_int = Int32.to_int + let compare i1 i2 = + if i1 < 0l && i2 >= 0l then 1 + else if i1 >= 0l && i2 < 0l then -1 + else Int32.compare i1 i2 +end + module String = struct let implode cs = diff --git a/src/lib/lib.mli b/src/lib/lib.mli index 4c70be475cb..ea13ec6acca 100644 --- a/src/lib/lib.mli +++ b/src/lib/lib.mli @@ -93,6 +93,22 @@ sig val is_power_of_two : int -> bool end +module Uint32 : +sig + type t = int32 + val to_string : t -> string + val of_string : string -> t + val of_int : int -> t + val to_int : t -> int + val add : t -> t -> t + val sub : t -> t -> t + val mul : t -> t -> t + val succ : t -> t + val zero : t + val one : t + val compare : t -> t -> int +end + module String : sig val implode : char list -> string diff --git a/test/idl/ok/fields.js.ok b/test/idl/ok/fields.js.ok index eb4bf7e6acc..1e0d4259a6c 100644 --- a/test/idl/ok/fields.js.ok +++ b/test/idl/ok/fields.js.ok @@ -1,12 +1,13 @@ const A = IDL.Obj({'0': IDL.Nat, '1': IDL.Nat, '2': IDL.Nat}) const B = - IDL.Obj({'named_files': IDL.None, '-665008590': IDL.Nat, - '-665008589': IDL.Nat, '0': IDL.Arr(IDL.Nat8), '35': IDL.Arr(IDL.Nat8), - '36': IDL.Nat, '37': IDL.Nat}) + IDL.Obj({'0': IDL.Arr(IDL.Nat8), '35': IDL.Arr(IDL.Nat8), '36': IDL.Nat, + '37': IDL.Nat, 'named_files': IDL.None, '3629958706': IDL.Nat, + '3629958707': IDL.Nat}) const C = - IDL.Variant({'green': IDL.Unit, '1': IDL.Unit, '2': IDL.Unit, '3': IDL.Unit, - '4': IDL.Unit, '10': IDL.Unit, 'A': IDL.Unit, 'B': IDL.Unit, 'C': IDL.Unit, - 'red': IDL.Unit, 'blue': IDL.Unit, 'reserved': IDL.Unit}) + IDL.Variant({'1': IDL.Unit, '2': IDL.Unit, '3': IDL.Unit, '4': IDL.Unit, + '10': IDL.Unit, 'A': IDL.Unit, 'B': IDL.Unit, 'C': IDL.Unit, + 'red': IDL.Unit, 'blue': IDL.Unit, 'reserved': IDL.Unit, 'green': IDL.Unit + }) const nest_record = IDL.Obj({'0': IDL.Nat, '1': IDL.Nat, '2': IDL.Nat, '3': IDL.Obj({'0': IDL.Nat, '1': IDL.Nat, '2': IDL.Nat}), '4': IDL.Nat, diff --git a/test/idl/ok/import.js.ok b/test/idl/ok/import.js.ok index 6490c97ee5a..cdf39162bb1 100644 --- a/test/idl/ok/import.js.ok +++ b/test/idl/ok/import.js.ok @@ -1,7 +1,7 @@ const EntId = IDL.Obj({'region': RegionId, 'user': UserId, 'truckType': TruckTypeId}) const IdErr = IDL.Obj({'idErr': OpEntId}) -const Inventory = IDL.Obj({'quantity': IDL.Nat, 'produce_id': IDL.Nat}) +const Inventory = IDL.Obj({'produce_id': IDL.Nat, 'quantity': IDL.Nat}) const OpEntId = IDL.Opt(EntId) const ProducerId = IDL.Nat const RegionId = IDL.Nat diff --git a/test/idl/ok/import1.js.ok b/test/idl/ok/import1.js.ok index de653ee8255..d55f0f16617 100644 --- a/test/idl/ok/import1.js.ok +++ b/test/idl/ok/import1.js.ok @@ -1,7 +1,7 @@ const EntId = IDL.Obj({'region': RegionId, 'user': UserId, 'truckType': TruckTypeId}) const IdErr = IDL.Obj({'idErr': OpEntId}) -const Inventory = IDL.Obj({'quantity': IDL.Nat, 'produce_id': IDL.Nat}) +const Inventory = IDL.Obj({'produce_id': IDL.Nat, 'quantity': IDL.Nat}) const OpEntId = IDL.Opt(EntId) const ProducerId = IDL.Nat const RegionId = IDL.Nat diff --git a/test/idl/ok/import3.js.ok b/test/idl/ok/import3.js.ok index 50b4ea16d96..a111f9b3033 100644 --- a/test/idl/ok/import3.js.ok +++ b/test/idl/ok/import3.js.ok @@ -11,6 +11,6 @@ const stream = const t = IDL.message(IDL.Obj({'server': s}), IDL.Obj({})) const tree = IDL.Variant({ - 'branch': IDL.Obj({'right': tree, 'val': IDL.Int, 'left': tree}), + 'branch': IDL.Obj({'val': IDL.Int, 'left': tree, 'right': tree}), 'leaf': IDL.Int}) const S = s diff --git a/test/idl/ok/px.js.ok b/test/idl/ok/px.js.ok index b210f5824c3..4970f19a8b4 100644 --- a/test/idl/ok/px.js.ok +++ b/test/idl/ok/px.js.ok @@ -1,7 +1,7 @@ const EntId = IDL.Obj({'region': RegionId, 'user': UserId, 'truckType': TruckTypeId}) const IdErr = IDL.Obj({'idErr': OpEntId}) -const Inventory = IDL.Obj({'quantity': IDL.Nat, 'produce_id': IDL.Nat}) +const Inventory = IDL.Obj({'produce_id': IDL.Nat, 'quantity': IDL.Nat}) const OpEntId = IDL.Opt(EntId) const ProducerId = IDL.Nat const RegionId = IDL.Nat diff --git a/test/idl/ok/recursion.js.ok b/test/idl/ok/recursion.js.ok index c73d80a6a9e..caab4905e37 100644 --- a/test/idl/ok/recursion.js.ok +++ b/test/idl/ok/recursion.js.ok @@ -11,6 +11,6 @@ const stream = const t = IDL.message(IDL.Obj({'server': s}), IDL.Obj({})) const tree = IDL.Variant({ - 'branch': IDL.Obj({'right': tree, 'val': IDL.Int, 'left': tree}), + 'branch': IDL.Obj({'val': IDL.Int, 'left': tree, 'right': tree}), 'leaf': IDL.Int}) const A = s diff --git a/test/idl/ok/unicode.js.ok b/test/idl/ok/unicode.js.ok index 7dc7da27b4f..6660ac1ac96 100644 --- a/test/idl/ok/unicode.js.ok +++ b/test/idl/ok/unicode.js.ok @@ -1,9 +1,9 @@ const A = - IDL.Obj({'字 段 名2': IDL.Nat, '📦🍦': IDL.Nat, '字段名': IDL.Nat + IDL.Obj({'📦🍦': IDL.Nat, '字段名': IDL.Nat, '字 段 名2': IDL.Nat }) const B = - IDL.Variant({'1⃣️2⃣️3⃣️': IDL.Unit, '': IDL.Unit, - '空的': IDL.Unit, ' 空的 ': IDL.Unit}) + IDL.Variant({'': IDL.Unit, '空的': IDL.Unit, ' 空的 ': IDL.Unit, + '1⃣️2⃣️3⃣️': IDL.Unit}) const C = new IDL.ActorInterface({ '函数名': IDL.message(IDL.Obj({'0': A}), IDL.Obj({'0': B})), '': IDL.message(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': IDL.Nat})), From 141c9a1a7317bd2167dcd8f2f82ca68ad427fd0d Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Fri, 28 Jun 2019 14:06:39 -0700 Subject: [PATCH 0220/1176] add to_int32 --- src/as_values/prim.ml | 2 +- src/lib/lib.ml | 2 ++ src/lib/lib.mli | 4 +++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/as_values/prim.ml b/src/as_values/prim.ml index 7bae41b5f1b..8c2c47222dd 100644 --- a/src/as_values/prim.ml +++ b/src/as_values/prim.ml @@ -237,7 +237,7 @@ let prim = function in k (Text str) | "print" -> fun v k -> Printf.printf "%s%!" (as_text v); k unit | "rts_version" -> fun v k -> as_unit v; k (Text "0.1") - | "idlHash" -> fun v k -> let s = as_text v in k (Word32 (Idllib.IdlHash.idl_hash s)) + | "idlHash" -> fun v k -> let s = as_text v in k (Word32 (Lib.Uint32.to_int32 (Idllib.IdlHash.idl_hash s))) | "decodeUTF8" -> fun v k -> let s = as_text v in let open Int32 in diff --git a/src/lib/lib.ml b/src/lib/lib.ml index e212dd52e7d..ca10f517c0d 100644 --- a/src/lib/lib.ml +++ b/src/lib/lib.ml @@ -34,6 +34,8 @@ struct let one = Int32.one let of_int = Int32.of_int let to_int = Int32.to_int + let of_int32 x = x + let to_int32 x = x let compare i1 i2 = if i1 < 0l && i2 >= 0l then 1 else if i1 >= 0l && i2 < 0l then -1 diff --git a/src/lib/lib.mli b/src/lib/lib.mli index ea13ec6acca..599af8767b8 100644 --- a/src/lib/lib.mli +++ b/src/lib/lib.mli @@ -95,11 +95,13 @@ end module Uint32 : sig - type t = int32 + type t val to_string : t -> string val of_string : string -> t val of_int : int -> t val to_int : t -> int + val of_int32 : int32 -> t + val to_int32 : t -> int32 val add : t -> t -> t val sub : t -> t -> t val mul : t -> t -> t From 9152bac769b766bd7f0dc78a101ec45e8be55136 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Sat, 29 Jun 2019 00:02:06 +0200 Subject: [PATCH 0221/1176] Redundant shift elimination (#533) * review feedback: try to reuse compile_smallNat/Int_kernel * shift-shift optimisation * eliminate null shifts --- src/codegen/compile.ml | 51 +++++++++++++------------------------- src/codegen/instrList.ml | 29 +++++++++++++++++++--- test/trap/mulInt8-upper.as | 5 ++++ test/trap/mulNat8.as | 5 ++++ 4 files changed, 52 insertions(+), 38 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index ad466cec5e4..3b3e940031b 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -368,12 +368,9 @@ let compile_add_const = compile_op_const I32Op.Add let compile_sub_const = compile_op_const I32Op.Sub let compile_mul_const = compile_op_const I32Op.Mul let compile_divU_const = compile_op_const I32Op.DivU -let compile_shrU_const = function - | 0l -> G.nop | n -> compile_op_const I32Op.ShrU n -let compile_shrS_const = function - | 0l -> G.nop | n -> compile_op_const I32Op.ShrS n -let compile_shl_const = function - | 0l -> G.nop | n -> compile_op_const I32Op.Shl n +let compile_shrU_const = compile_op_const I32Op.ShrU +let compile_shrS_const = compile_op_const I32Op.ShrS +let compile_shl_const = compile_op_const I32Op.Shl let compile_bitand_const = compile_op_const I32Op.And let compile_bitor_const = function | 0l -> G.nop | n -> compile_op_const I32Op.Or n @@ -4550,30 +4547,36 @@ let enforce_16_signed_bits env = compile_shl_const 1l ^^ G.i (Binary (Wasm.Values.I32 I32Op.Xor)) ^^ enforce_16_unsigned_bits env -let compile_smallInt_kernel env ty name op = +let compile_smallInt_kernel' env ty name op = Func.share_code2 env (UnboxedSmallWord.name_of_type ty name) (("a", I32Type), ("b", I32Type)) [I32Type] (fun env get_a get_b -> let (set_res, get_res) = new_local env "res" in get_a ^^ compile_shrS_const 16l ^^ get_b ^^ compile_shrS_const 16l ^^ - G.i (Binary (Wasm.Values.I32 op)) ^^ + op ^^ set_res ^^ get_res ^^ get_res ^^ enforce_16_signed_bits env ^^ get_res ^^ compile_shl_const 16l) -let compile_smallNat_kernel env ty name op = +let compile_smallInt_kernel env ty name op = + compile_smallInt_kernel' env ty name (G.i (Binary (Wasm.Values.I32 op))) + +let compile_smallNat_kernel' env ty name op = Func.share_code2 env (UnboxedSmallWord.name_of_type ty name) (("a", I32Type), ("b", I32Type)) [I32Type] (fun env get_a get_b -> let (set_res, get_res) = new_local env "res" in get_a ^^ compile_shrU_const 16l ^^ get_b ^^ compile_shrU_const 16l ^^ - G.i (Binary (Wasm.Values.I32 op)) ^^ + op ^^ set_res ^^ get_res ^^ enforce_16_unsigned_bits env ^^ get_res ^^ compile_shl_const 16l) +let compile_smallNat_kernel env ty name op = + compile_smallNat_kernel' env ty name (G.i (Binary (Wasm.Values.I32 op))) + (* This returns a single StackRep, to be used for both arguments and the result. One could imagine operators that require or produce different StackReps, but none of these do, so a single value is fine. @@ -4617,32 +4620,12 @@ let rec compile_binop env t op = G.i (Binary (Wasm.Values.I32 I32Op.Mul)) | Type.(Prim Int32), MulOp -> compile_Int32_kernel env "mul" I64Op.Mul | Type.(Prim Int16), MulOp -> compile_smallInt_kernel env Type.Int16 "mul" I32Op.Mul - | Type.(Prim Int8), MulOp -> - Func.share_code2 env (UnboxedSmallWord.name_of_type Type.Int8 "mul") - (("a", I32Type), ("b", I32Type)) [I32Type] - (fun env get_a get_b -> - let (set_res, get_res) = new_local env "res" in - get_a ^^ compile_shrS_const 24l ^^ - get_b ^^ compile_shrS_const 24l ^^ - G.i (Binary (Wasm.Values.I32 I32Op.Mul)) ^^ - set_res ^^ get_res ^^ get_res ^^ compile_shl_const 1l ^^ G.i (Binary (Wasm.Values.I32 I32Op.Xor)) ^^ - compile_bitand_const 0xFFFFFF00l ^^ - then_arithmetic_overflow env ^^ - get_res ^^ compile_shl_const 24l) + | Type.(Prim Int8), MulOp -> compile_smallInt_kernel' env Type.Int8 "mul" + (compile_shrS_const 8l ^^ G.i (Binary (Wasm.Values.I32 I32Op.Mul))) | Type.(Prim Nat32), MulOp -> compile_Nat32_kernel env "mul" I64Op.Mul | Type.(Prim Nat16), MulOp -> compile_smallNat_kernel env Type.Nat16 "mul" I32Op.Mul - | Type.(Prim Nat8), MulOp -> - Func.share_code2 env (UnboxedSmallWord.name_of_type Type.Nat8 "mul") - (("a", I32Type), ("b", I32Type)) [I32Type] - (fun env get_a get_b -> - let (set_res, get_res) = new_local env "res" in - get_a ^^ compile_shrU_const 24l ^^ - get_b ^^ compile_shrU_const 24l ^^ - G.i (Binary (Wasm.Values.I32 I32Op.Mul)) ^^ - set_res ^^ get_res ^^ compile_bitand_const 0xFFFFFF00l ^^ - then_arithmetic_overflow env ^^ - get_res ^^ compile_shl_const 24l) - + | Type.(Prim Nat8), MulOp -> compile_smallNat_kernel' env Type.Nat8 "mul" + (compile_shrU_const 8l ^^ G.i (Binary (Wasm.Values.I32 I32Op.Mul))) | Type.(Prim (Nat8|Nat16|Nat32|Word8|Word16|Word32 as ty)), DivOp -> G.i (Binary (Wasm.Values.I32 I32Op.DivU)) ^^ UnboxedSmallWord.msb_adjust ty diff --git a/src/codegen/instrList.ml b/src/codegen/instrList.ml index dc4c11ed557..ec67ac9a8e2 100644 --- a/src/codegen/instrList.ml +++ b/src/codegen/instrList.ml @@ -9,14 +9,27 @@ features are open Wasm.Ast open Wasm.Source +open Wasm.Values + +let combine_shifts const op = function + | I32 opl, ({it = I32 l'; _} as cl), I32 opr, I32 r' when opl = opr -> + let l, r = Int32.(to_int l', to_int r') in + if (l >= 0 && l < 32 && r >= 0 && r < 32 && l + r < 32) then + Some [{const with it = Const {cl with it = I32 (Int32.add l' r')}}; {op with it = Binary (I32 opl)}] + else None + | _ -> None + +module Option = struct + let is_some = function None -> false | _ -> true + let get = function None -> assert false | Some x -> x +end (* Some simple peephole optimizations, to make the output code look less stupid *) (* This uses a zipper.*) let optimize : instr list -> instr list = fun is -> let rec go l r = match l, r with (* Loading and dropping is pointless *) - | { it = Const _; _} :: l', { it = Drop; _ } :: r' -> go l' r' - | { it = LocalGet _; _} :: l', { it = Drop; _ } :: r' -> go l' r' + | { it = Const _ | LocalGet _; _} :: l', { it = Drop; _ } :: r' -> go l' r' (* The following is not semantics preserving for general Wasm (due to out-of-memory) but should be fine for the code that we create *) | { it = Load _; _} :: l', { it = Drop; _ } :: _ -> go l' r @@ -30,12 +43,20 @@ let optimize : instr list -> instr list = fun is -> | _, ({ it = Return | Br _ | Unreachable; _ } as i) :: _ -> List.rev (i::l) (* `If` blocks after pushed constants are simplifiable *) - | { it = Const {it = Wasm.Values.I32 0l; _}; _} :: l', ({it = If (res,_,else_); _} as i) :: r' -> + | { it = Const {it = I32 0l; _}; _} :: l', ({it = If (res,_,else_); _} as i) :: r' -> go l' ({i with it = Block (res, else_)} :: r') - | { it = Const {it = Wasm.Values.I32 _; _}; _} :: l', ({it = If (res,then_,_); _} as i) :: r' -> + | { it = Const {it = I32 _; _}; _} :: l', ({it = If (res,then_,_); _} as i) :: r' -> go l' ({i with it = Block (res, then_)} :: r') (* Empty block is redundant *) | l', ({ it = Block (_, []); _ }) :: r' -> go l' r' + (* Constant shifts can be combined *) + | {it = Binary (I32 I32Op.(Shl|ShrS|ShrU) as opl); _} :: {it = Const cl; _} :: l', + ({it = Const cr; _} as const) :: ({it = Binary opr; _} as op) :: r' + when Option.is_some (combine_shifts const op (opl, cl, opr, cr.it)) -> + go l' (Option.get (combine_shifts const op (opl, cl, opr, cr.it)) @ r') + (* Null shifts can be eliminated *) + | l', {it = Const {it = I32 0l; _}; _} :: {it = Binary (I32 I32Op.(Shl|ShrS|ShrU)); _} :: r' -> + go l' r' (* Look further *) | _, i::r' -> go (i::l) r' (* Done looking *) diff --git a/test/trap/mulInt8-upper.as b/test/trap/mulInt8-upper.as index 3036bcc9a5d..e9173faf73e 100644 --- a/test/trap/mulInt8-upper.as +++ b/test/trap/mulInt8-upper.as @@ -1 +1,6 @@ let _ = (16 : Int8) * (8 : Int8) +// There should be only one shift per operand +// CHECK: mul +// CHECK: i32.shr_s +// CHECK: i32.const 24 +// CHECK-NEXT: i32.shr_s diff --git a/test/trap/mulNat8.as b/test/trap/mulNat8.as index 7244e98e2e7..a257eca610d 100644 --- a/test/trap/mulNat8.as +++ b/test/trap/mulNat8.as @@ -1 +1,6 @@ let _ = (16 : Nat8) * (16 : Nat8) +// There should be only one shift per operand +// CHECK: mul +// CHECK: i32.shr_u +// CHECK: i32.const 24 +// CHECK-NEXT: i32.shr_u From e4fbbacb7d7322b12b06e27b63f28c0aaef316c0 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Sat, 29 Jun 2019 00:25:46 +0200 Subject: [PATCH 0222/1176] Test normalize: Remove location details from messages about the prelude (#534) Less churn in diffs --- test/repl/ok/outrange-int-nat.stdout.ok | 24 ++++++++++---------- test/repl/ok/type-lub-repl.stderr.ok | 0 test/run.sh | 3 +++ test/trap/ok/outrange-int16-lower.run-ir.ok | 2 +- test/trap/ok/outrange-int16-lower.run-low.ok | 2 +- test/trap/ok/outrange-int16-lower.run.ok | 2 +- test/trap/ok/outrange-int16-upper.run-ir.ok | 2 +- test/trap/ok/outrange-int16-upper.run-low.ok | 2 +- test/trap/ok/outrange-int16-upper.run.ok | 2 +- test/trap/ok/outrange-int32-lower.run-ir.ok | 2 +- test/trap/ok/outrange-int32-lower.run-low.ok | 2 +- test/trap/ok/outrange-int32-lower.run.ok | 2 +- test/trap/ok/outrange-int32-upper.run-ir.ok | 2 +- test/trap/ok/outrange-int32-upper.run-low.ok | 2 +- test/trap/ok/outrange-int32-upper.run.ok | 2 +- test/trap/ok/outrange-int64-lower.run-ir.ok | 2 +- test/trap/ok/outrange-int64-lower.run-low.ok | 2 +- test/trap/ok/outrange-int64-lower.run.ok | 2 +- test/trap/ok/outrange-int64-upper.run-ir.ok | 2 +- test/trap/ok/outrange-int64-upper.run-low.ok | 2 +- test/trap/ok/outrange-int64-upper.run.ok | 2 +- test/trap/ok/outrange-int8-lower.run-ir.ok | 2 +- test/trap/ok/outrange-int8-lower.run-low.ok | 2 +- test/trap/ok/outrange-int8-lower.run.ok | 2 +- test/trap/ok/outrange-int8-upper.run-ir.ok | 2 +- test/trap/ok/outrange-int8-upper.run-low.ok | 2 +- test/trap/ok/outrange-int8-upper.run.ok | 2 +- test/trap/ok/outrange-nat16.run-ir.ok | 2 +- test/trap/ok/outrange-nat16.run-low.ok | 2 +- test/trap/ok/outrange-nat16.run.ok | 2 +- test/trap/ok/outrange-nat32.run-ir.ok | 2 +- test/trap/ok/outrange-nat32.run-low.ok | 2 +- test/trap/ok/outrange-nat32.run.ok | 2 +- test/trap/ok/outrange-nat64.run-ir.ok | 2 +- test/trap/ok/outrange-nat64.run-low.ok | 2 +- test/trap/ok/outrange-nat64.run.ok | 2 +- test/trap/ok/outrange-nat8.run-ir.ok | 2 +- test/trap/ok/outrange-nat8.run-low.ok | 2 +- test/trap/ok/outrange-nat8.run.ok | 2 +- 39 files changed, 51 insertions(+), 48 deletions(-) delete mode 100644 test/repl/ok/type-lub-repl.stderr.ok diff --git a/test/repl/ok/outrange-int-nat.stdout.ok b/test/repl/ok/outrange-int-nat.stdout.ok index daa7c921fa1..141ae75ff42 100644 --- a/test/repl/ok/outrange-int-nat.stdout.ok +++ b/test/repl/ok/outrange-int-nat.stdout.ok @@ -1,28 +1,28 @@ ActorScript 0.1 interpreter > 127 : Int8 -> prelude:83.34-83.68: execution error, numeric overflow +> prelude:___: execution error, numeric overflow > -128 : Int8 -> prelude:83.34-83.68: execution error, numeric overflow +> prelude:___: execution error, numeric overflow > 32_767 : Int16 -> prelude:79.36-79.72: execution error, numeric overflow +> prelude:___: execution error, numeric overflow > -32_768 : Int16 -> prelude:79.36-79.72: execution error, numeric overflow +> prelude:___: execution error, numeric overflow > 2_147_483_647 : Int32 -> prelude:75.36-75.72: execution error, numeric overflow +> prelude:___: execution error, numeric overflow > -2_147_483_648 : Int32 -> prelude:75.36-75.72: execution error, numeric overflow +> prelude:___: execution error, numeric overflow > 9_223_372_036_854_775_807 : Int64 -> prelude:71.36-71.72: execution error, numeric overflow +> prelude:___: execution error, numeric overflow > -9_223_372_036_854_775_808 : Int64 -> prelude:71.36-71.72: execution error, numeric overflow +> prelude:___: execution error, numeric overflow > 255 : Nat8 -> prelude:100.34-100.68: execution error, numeric overflow +> prelude:___: execution error, numeric overflow > 65_535 : Nat16 -> prelude:96.36-96.72: execution error, numeric overflow +> prelude:___: execution error, numeric overflow > 4_294_967_295 : Nat32 -> prelude:92.36-92.72: execution error, numeric overflow +> prelude:___: execution error, numeric overflow > 18_446_744_073_709_551_615 : Nat64 -> prelude:88.36-88.72: execution error, numeric overflow +> prelude:___: execution error, numeric overflow > -127 : Int8 > -127 : Int8 > -32_767 : Int16 diff --git a/test/repl/ok/type-lub-repl.stderr.ok b/test/repl/ok/type-lub-repl.stderr.ok deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/test/run.sh b/test/run.sh index fffd629ec90..627ccef2afe 100755 --- a/test/run.sh +++ b/test/run.sh @@ -58,6 +58,7 @@ function normalize () { sed 's/\x1b\[[0-9;]*[a-zA-Z]//g' | sed 's/^.*[IW], hypervisor:/hypervisor:/g' | sed 's/wasm:0x[a-f0-9]*:/wasm:0x___:/g' | + sed 's/prelude:[^:]*:/prelude:___:/g' | sed 's/^.*run-dfinity\/\.\.\/dvm.sh: line/dvm.sh: line/g' | sed 's/ *[0-9]* Illegal instruction.*dvm/ Illegal instruction dvm/g' | sed 's/ calling func\$[0-9]*/ calling func$NNN/g' | @@ -193,6 +194,8 @@ do # The file is a shell script, just run it $ECHO -n " [out]" ./$(basename $file) > $out/$base.stdout 2> $out/$base.stderr + normalize $out/$base.stdout + normalize $out/$base.stderr diff_files="$diff_files $base.stdout $base.stderr" elif [ ${file: -4} == ".wat" ] then diff --git a/test/trap/ok/outrange-int16-lower.run-ir.ok b/test/trap/ok/outrange-int16-lower.run-ir.ok index 54a37fcb824..0356664e3e0 100644 --- a/test/trap/ok/outrange-int16-lower.run-ir.ok +++ b/test/trap/ok/outrange-int16-lower.run-ir.ok @@ -1 +1 @@ -prelude:79.36-79.72: execution error, numeric overflow +prelude:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int16-lower.run-low.ok b/test/trap/ok/outrange-int16-lower.run-low.ok index 54a37fcb824..0356664e3e0 100644 --- a/test/trap/ok/outrange-int16-lower.run-low.ok +++ b/test/trap/ok/outrange-int16-lower.run-low.ok @@ -1 +1 @@ -prelude:79.36-79.72: execution error, numeric overflow +prelude:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int16-lower.run.ok b/test/trap/ok/outrange-int16-lower.run.ok index 54a37fcb824..0356664e3e0 100644 --- a/test/trap/ok/outrange-int16-lower.run.ok +++ b/test/trap/ok/outrange-int16-lower.run.ok @@ -1 +1 @@ -prelude:79.36-79.72: execution error, numeric overflow +prelude:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int16-upper.run-ir.ok b/test/trap/ok/outrange-int16-upper.run-ir.ok index 54a37fcb824..0356664e3e0 100644 --- a/test/trap/ok/outrange-int16-upper.run-ir.ok +++ b/test/trap/ok/outrange-int16-upper.run-ir.ok @@ -1 +1 @@ -prelude:79.36-79.72: execution error, numeric overflow +prelude:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int16-upper.run-low.ok b/test/trap/ok/outrange-int16-upper.run-low.ok index 54a37fcb824..0356664e3e0 100644 --- a/test/trap/ok/outrange-int16-upper.run-low.ok +++ b/test/trap/ok/outrange-int16-upper.run-low.ok @@ -1 +1 @@ -prelude:79.36-79.72: execution error, numeric overflow +prelude:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int16-upper.run.ok b/test/trap/ok/outrange-int16-upper.run.ok index 54a37fcb824..0356664e3e0 100644 --- a/test/trap/ok/outrange-int16-upper.run.ok +++ b/test/trap/ok/outrange-int16-upper.run.ok @@ -1 +1 @@ -prelude:79.36-79.72: execution error, numeric overflow +prelude:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int32-lower.run-ir.ok b/test/trap/ok/outrange-int32-lower.run-ir.ok index a1f443605b3..0356664e3e0 100644 --- a/test/trap/ok/outrange-int32-lower.run-ir.ok +++ b/test/trap/ok/outrange-int32-lower.run-ir.ok @@ -1 +1 @@ -prelude:75.36-75.72: execution error, numeric overflow +prelude:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int32-lower.run-low.ok b/test/trap/ok/outrange-int32-lower.run-low.ok index a1f443605b3..0356664e3e0 100644 --- a/test/trap/ok/outrange-int32-lower.run-low.ok +++ b/test/trap/ok/outrange-int32-lower.run-low.ok @@ -1 +1 @@ -prelude:75.36-75.72: execution error, numeric overflow +prelude:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int32-lower.run.ok b/test/trap/ok/outrange-int32-lower.run.ok index a1f443605b3..0356664e3e0 100644 --- a/test/trap/ok/outrange-int32-lower.run.ok +++ b/test/trap/ok/outrange-int32-lower.run.ok @@ -1 +1 @@ -prelude:75.36-75.72: execution error, numeric overflow +prelude:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int32-upper.run-ir.ok b/test/trap/ok/outrange-int32-upper.run-ir.ok index a1f443605b3..0356664e3e0 100644 --- a/test/trap/ok/outrange-int32-upper.run-ir.ok +++ b/test/trap/ok/outrange-int32-upper.run-ir.ok @@ -1 +1 @@ -prelude:75.36-75.72: execution error, numeric overflow +prelude:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int32-upper.run-low.ok b/test/trap/ok/outrange-int32-upper.run-low.ok index a1f443605b3..0356664e3e0 100644 --- a/test/trap/ok/outrange-int32-upper.run-low.ok +++ b/test/trap/ok/outrange-int32-upper.run-low.ok @@ -1 +1 @@ -prelude:75.36-75.72: execution error, numeric overflow +prelude:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int32-upper.run.ok b/test/trap/ok/outrange-int32-upper.run.ok index a1f443605b3..0356664e3e0 100644 --- a/test/trap/ok/outrange-int32-upper.run.ok +++ b/test/trap/ok/outrange-int32-upper.run.ok @@ -1 +1 @@ -prelude:75.36-75.72: execution error, numeric overflow +prelude:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int64-lower.run-ir.ok b/test/trap/ok/outrange-int64-lower.run-ir.ok index d3ac87f6451..0356664e3e0 100644 --- a/test/trap/ok/outrange-int64-lower.run-ir.ok +++ b/test/trap/ok/outrange-int64-lower.run-ir.ok @@ -1 +1 @@ -prelude:71.36-71.72: execution error, numeric overflow +prelude:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int64-lower.run-low.ok b/test/trap/ok/outrange-int64-lower.run-low.ok index d3ac87f6451..0356664e3e0 100644 --- a/test/trap/ok/outrange-int64-lower.run-low.ok +++ b/test/trap/ok/outrange-int64-lower.run-low.ok @@ -1 +1 @@ -prelude:71.36-71.72: execution error, numeric overflow +prelude:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int64-lower.run.ok b/test/trap/ok/outrange-int64-lower.run.ok index d3ac87f6451..0356664e3e0 100644 --- a/test/trap/ok/outrange-int64-lower.run.ok +++ b/test/trap/ok/outrange-int64-lower.run.ok @@ -1 +1 @@ -prelude:71.36-71.72: execution error, numeric overflow +prelude:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int64-upper.run-ir.ok b/test/trap/ok/outrange-int64-upper.run-ir.ok index d3ac87f6451..0356664e3e0 100644 --- a/test/trap/ok/outrange-int64-upper.run-ir.ok +++ b/test/trap/ok/outrange-int64-upper.run-ir.ok @@ -1 +1 @@ -prelude:71.36-71.72: execution error, numeric overflow +prelude:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int64-upper.run-low.ok b/test/trap/ok/outrange-int64-upper.run-low.ok index d3ac87f6451..0356664e3e0 100644 --- a/test/trap/ok/outrange-int64-upper.run-low.ok +++ b/test/trap/ok/outrange-int64-upper.run-low.ok @@ -1 +1 @@ -prelude:71.36-71.72: execution error, numeric overflow +prelude:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int64-upper.run.ok b/test/trap/ok/outrange-int64-upper.run.ok index d3ac87f6451..0356664e3e0 100644 --- a/test/trap/ok/outrange-int64-upper.run.ok +++ b/test/trap/ok/outrange-int64-upper.run.ok @@ -1 +1 @@ -prelude:71.36-71.72: execution error, numeric overflow +prelude:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int8-lower.run-ir.ok b/test/trap/ok/outrange-int8-lower.run-ir.ok index e0fee3eba79..0356664e3e0 100644 --- a/test/trap/ok/outrange-int8-lower.run-ir.ok +++ b/test/trap/ok/outrange-int8-lower.run-ir.ok @@ -1 +1 @@ -prelude:83.34-83.68: execution error, numeric overflow +prelude:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int8-lower.run-low.ok b/test/trap/ok/outrange-int8-lower.run-low.ok index e0fee3eba79..0356664e3e0 100644 --- a/test/trap/ok/outrange-int8-lower.run-low.ok +++ b/test/trap/ok/outrange-int8-lower.run-low.ok @@ -1 +1 @@ -prelude:83.34-83.68: execution error, numeric overflow +prelude:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int8-lower.run.ok b/test/trap/ok/outrange-int8-lower.run.ok index e0fee3eba79..0356664e3e0 100644 --- a/test/trap/ok/outrange-int8-lower.run.ok +++ b/test/trap/ok/outrange-int8-lower.run.ok @@ -1 +1 @@ -prelude:83.34-83.68: execution error, numeric overflow +prelude:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int8-upper.run-ir.ok b/test/trap/ok/outrange-int8-upper.run-ir.ok index e0fee3eba79..0356664e3e0 100644 --- a/test/trap/ok/outrange-int8-upper.run-ir.ok +++ b/test/trap/ok/outrange-int8-upper.run-ir.ok @@ -1 +1 @@ -prelude:83.34-83.68: execution error, numeric overflow +prelude:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int8-upper.run-low.ok b/test/trap/ok/outrange-int8-upper.run-low.ok index e0fee3eba79..0356664e3e0 100644 --- a/test/trap/ok/outrange-int8-upper.run-low.ok +++ b/test/trap/ok/outrange-int8-upper.run-low.ok @@ -1 +1 @@ -prelude:83.34-83.68: execution error, numeric overflow +prelude:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int8-upper.run.ok b/test/trap/ok/outrange-int8-upper.run.ok index e0fee3eba79..0356664e3e0 100644 --- a/test/trap/ok/outrange-int8-upper.run.ok +++ b/test/trap/ok/outrange-int8-upper.run.ok @@ -1 +1 @@ -prelude:83.34-83.68: execution error, numeric overflow +prelude:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-nat16.run-ir.ok b/test/trap/ok/outrange-nat16.run-ir.ok index db44073a1d2..0356664e3e0 100644 --- a/test/trap/ok/outrange-nat16.run-ir.ok +++ b/test/trap/ok/outrange-nat16.run-ir.ok @@ -1 +1 @@ -prelude:96.36-96.72: execution error, numeric overflow +prelude:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-nat16.run-low.ok b/test/trap/ok/outrange-nat16.run-low.ok index db44073a1d2..0356664e3e0 100644 --- a/test/trap/ok/outrange-nat16.run-low.ok +++ b/test/trap/ok/outrange-nat16.run-low.ok @@ -1 +1 @@ -prelude:96.36-96.72: execution error, numeric overflow +prelude:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-nat16.run.ok b/test/trap/ok/outrange-nat16.run.ok index db44073a1d2..0356664e3e0 100644 --- a/test/trap/ok/outrange-nat16.run.ok +++ b/test/trap/ok/outrange-nat16.run.ok @@ -1 +1 @@ -prelude:96.36-96.72: execution error, numeric overflow +prelude:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-nat32.run-ir.ok b/test/trap/ok/outrange-nat32.run-ir.ok index 2e6e9e985ca..0356664e3e0 100644 --- a/test/trap/ok/outrange-nat32.run-ir.ok +++ b/test/trap/ok/outrange-nat32.run-ir.ok @@ -1 +1 @@ -prelude:92.36-92.72: execution error, numeric overflow +prelude:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-nat32.run-low.ok b/test/trap/ok/outrange-nat32.run-low.ok index 2e6e9e985ca..0356664e3e0 100644 --- a/test/trap/ok/outrange-nat32.run-low.ok +++ b/test/trap/ok/outrange-nat32.run-low.ok @@ -1 +1 @@ -prelude:92.36-92.72: execution error, numeric overflow +prelude:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-nat32.run.ok b/test/trap/ok/outrange-nat32.run.ok index 2e6e9e985ca..0356664e3e0 100644 --- a/test/trap/ok/outrange-nat32.run.ok +++ b/test/trap/ok/outrange-nat32.run.ok @@ -1 +1 @@ -prelude:92.36-92.72: execution error, numeric overflow +prelude:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-nat64.run-ir.ok b/test/trap/ok/outrange-nat64.run-ir.ok index 72676577d7c..0356664e3e0 100644 --- a/test/trap/ok/outrange-nat64.run-ir.ok +++ b/test/trap/ok/outrange-nat64.run-ir.ok @@ -1 +1 @@ -prelude:88.36-88.72: execution error, numeric overflow +prelude:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-nat64.run-low.ok b/test/trap/ok/outrange-nat64.run-low.ok index 72676577d7c..0356664e3e0 100644 --- a/test/trap/ok/outrange-nat64.run-low.ok +++ b/test/trap/ok/outrange-nat64.run-low.ok @@ -1 +1 @@ -prelude:88.36-88.72: execution error, numeric overflow +prelude:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-nat64.run.ok b/test/trap/ok/outrange-nat64.run.ok index 72676577d7c..0356664e3e0 100644 --- a/test/trap/ok/outrange-nat64.run.ok +++ b/test/trap/ok/outrange-nat64.run.ok @@ -1 +1 @@ -prelude:88.36-88.72: execution error, numeric overflow +prelude:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-nat8.run-ir.ok b/test/trap/ok/outrange-nat8.run-ir.ok index 1767cb22299..0356664e3e0 100644 --- a/test/trap/ok/outrange-nat8.run-ir.ok +++ b/test/trap/ok/outrange-nat8.run-ir.ok @@ -1 +1 @@ -prelude:100.34-100.68: execution error, numeric overflow +prelude:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-nat8.run-low.ok b/test/trap/ok/outrange-nat8.run-low.ok index 1767cb22299..0356664e3e0 100644 --- a/test/trap/ok/outrange-nat8.run-low.ok +++ b/test/trap/ok/outrange-nat8.run-low.ok @@ -1 +1 @@ -prelude:100.34-100.68: execution error, numeric overflow +prelude:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-nat8.run.ok b/test/trap/ok/outrange-nat8.run.ok index 1767cb22299..0356664e3e0 100644 --- a/test/trap/ok/outrange-nat8.run.ok +++ b/test/trap/ok/outrange-nat8.run.ok @@ -1 +1 @@ -prelude:100.34-100.68: execution error, numeric overflow +prelude:___: execution error, numeric overflow From 304fd28f847dd549f934b02325efbcfd9cc63c32 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Mon, 1 Jul 2019 11:17:55 -0600 Subject: [PATCH 0223/1176] attempt to fix nix/hydra build product for stdlib-doc --- default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/default.nix b/default.nix index 9f386f0890d..7790a626708 100644 --- a/default.nix +++ b/default.nix @@ -324,7 +324,7 @@ rec { mkdir -p $out tar -rf $out/stdlib-doc.tar doc mkdir -p $out/nix-support - echo "report stdlib $out/stdlib.tar" >> $out/nix-support/hydra-build-products + echo "report stdlib-doc $out/stdlib-doc.tar" >> $out/nix-support/hydra-build-products ''; forceShare = ["man"]; }; From 620783afd4a6b23136f7a04205e71551b9891314 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 1 Jul 2019 22:34:23 +0200 Subject: [PATCH 0224/1176] IDL Messages: Prepend and skip magic bytes and type description (#525) Goes together with https://github.com/dfinity-lab/dev/pull/1095. Also fixes type numbers in IDl spec (-22 was used twice). --- rts/rts.c | 89 ++++++++++++++++++++ src/codegen/compile.ml | 181 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 268 insertions(+), 2 deletions(-) diff --git a/rts/rts.c b/rts/rts.c index 3156b1c1c2e..3408b08fdca 100644 --- a/rts/rts.c +++ b/rts/rts.c @@ -84,6 +84,95 @@ as_ptr (*version_getter)() = &get_version; export as_ptr version() { return (*version_getter)(); } +/* IDL code */ +from_rts __attribute__ ((noreturn)) void idl_trap(); + +// Initially, we just want to be able to zoom past the type description +// TODO: Defensive programming +// (not going past the size of the message, trapping if leb128 does not fit in int) + +int read_leb128(char **ptr) { + int r = 0; + int s = 0; + char b; + do { + b = *(*ptr)++; + r += (b & (char)0x7f) << s; + s += 7; + } while (b & (char)0x80); + return r; +} +int read_sleb128(char **ptr) { + int r = 0; + int s = 0; + char b; + do { + b = *(*ptr)++; + r += (b & (char)0x7f) << s; + s += 7; + } while (b & (char)0x80); + // sign extend + if (b & (char)0x40) { + r |= (~0 << s); + } + return r; +} + +export char *skip_idl_header(char *ptr) { + // Magic bytes + if (*ptr++ != 'D') idl_trap(); + if (*ptr++ != 'I') idl_trap(); + if (*ptr++ != 'D') idl_trap(); + if (*ptr++ != 'L') idl_trap(); + // Size of type list + for (int count = read_leb128(&ptr); count > 0; count --) { + int ty = read_sleb128(&ptr); + if (ty >= -17) { + idl_trap(); // illegal + } else if (ty == -18) { // opt + read_sleb128(&ptr); + } + else if (ty == -19) { // vec + read_sleb128(&ptr); + } else if (ty == -20) { // record + for (int n = read_leb128(&ptr); n > 0; n--) { + read_leb128(&ptr); + read_sleb128(&ptr); + } + } else if (ty == -21) { // variant + for (int n = read_leb128(&ptr); n > 0; n--) { + read_leb128(&ptr); + read_sleb128(&ptr); + } + } else if (ty == -22) { // func + // arg types + for (int n = read_leb128(&ptr); n > 0; n--) { + read_sleb128(&ptr); + } + // ret types + for (int n = read_leb128(&ptr); n > 0; n--) { + read_sleb128(&ptr); + } + // annotations + for (int n = read_leb128(&ptr); n > 0; n--) { + ptr++; + } + } else if (ty == -23) { // service + for (int n = read_leb128(&ptr); n > 0; n--) { + // name + ptr += read_leb128(&ptr); + // type + read_sleb128(&ptr); + } + } else { + // no support for future types yet + idl_trap(); + } + } + read_sleb128(&ptr); // index + return ptr; +} + /* Memory management for libtommath */ /* diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index b4bc8c70852..6f61ff33566 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -514,6 +514,7 @@ module RTS = struct let system_imports env = E.add_func_import env "rts" "as_memcpy" [I32Type; I32Type; I32Type] []; E.add_func_import env "rts" "version" [] [I32Type]; + E.add_func_import env "rts" "skip_idl_header" [I32Type] [I32Type]; E.add_func_import env "rts" "bigint_of_word32" [I32Type] [I32Type]; E.add_func_import env "rts" "bigint_of_word32_signed" [I32Type] [I32Type]; E.add_func_import env "rts" "bigint_to_word32_wrap" [I32Type] [I32Type]; @@ -561,6 +562,15 @@ module RTS = struct E.add_export env (nr { name = Wasm.Utf8.decode "bigint_trap"; edesc = nr (FuncExport (nr bigint_trap_fi)) + }); + let idl_trap_fi = E.add_fun env "idl_trap" ( + Func.of_body env [] [] (fun env -> + E.trap_with env "idl function error" + ) + ) in + E.add_export env (nr { + name = Wasm.Utf8.decode "idl_trap"; + edesc = nr (FuncExport (nr idl_trap_fi)) }) end (* RTS *) @@ -2823,6 +2833,160 @@ module Serialization = struct Writing a Wasm-native implementation of this will then be done separately. *) + (* The IDL serialization prefaces the data with a type description. + We can statically create the type description in Ocaml code, + store it in the program, and just copy it to the beginning of the message. + + At some point this can be factored into a function from AS type to IDL type, + and a function like this for IDL types. But due to recursion handling + it is easier to start like this. + *) + + module TM = Map.Make (struct type t = Type.typ let compare = compare end) + + let type_desc t : string = + let open Type in + + let to_idl_prim = function + | Prim Null -> Some 1 + | Prim Bool -> Some 2 + | Prim Nat -> Some 3 + | Prim Int -> Some 4 + | Prim (Nat8|Word8) -> Some 5 + | Prim (Nat16|Word16) -> Some 6 + | Prim (Nat32|Word32) -> Some 7 + | Prim (Nat64|Word64) -> Some 8 + | Prim Int8 -> Some 9 + | Prim Int16 -> Some 10 + | Prim Int32 -> Some 11 + | Prim Int64 -> Some 12 + | Prim Float -> Some 14 + | Prim Text -> Some 15 + | Shared -> Some 16 + | Non -> Some 17 + | _ -> None + in + + (* Type traversal *) + (* We do a first traversal to find out the indices of types *) + let (typs, idx) = + let typs = ref [] in + let idx = ref TM.empty in + let rec go t = + let t = normalize t in + let t = match t with Serialized t -> t | _ -> t in + let t = normalize t in + if to_idl_prim t <> None then () else + if TM.mem t !idx then () else begin + idx := TM.add t (List.length !typs) !idx; + typs := !typs @ [ t ]; + match t with + | Tup ts -> List.iter go ts + | Obj ((Object Sharable | Actor), fs) -> + List.iter (fun f -> go f.typ) fs + | Array t -> go t + | Opt t -> go t + | Variant vs -> List.iter (fun f -> go f.typ) vs + | Func (s, c, tbs, ts1, ts2) -> + List.iter go ts1; List.iter go ts2 + | _ -> + Printf.eprintf "type_desc: unexpected type %s\n" (string_of_typ t); + assert false + end + in + go t; + (!typs, !idx) + in + + (* buffer utilities *) + let buf = Buffer.create 16 in + + let add_u8 i = + Buffer.add_char buf (Char.chr (i land 0xff)) in + + let rec add_leb128_32 (i : int32) = + let open Int32 in + let b = logand i 0x7fl in + if 0l <= i && i < 128l + then add_u8 (to_int b) + else begin + add_u8 (to_int (logor b 0x80l)); + add_leb128_32 (shift_right_logical i 7) + end in + + let add_leb128 i = + assert (i >= 0); + add_leb128_32 (Int32.of_int i) in + + let rec add_sleb128 i = + let b = i land 0x7f in + if -64 <= i && i < 64 + then add_u8 b + else begin + add_u8 (b lor 0x80); + add_sleb128 (i asr 7) + end in + + (* Actual binary data *) + + let add_idx t = + let t = normalize t in + let t = match t with Serialized t -> t | _ -> t in + let t = normalize t in + match to_idl_prim t with + | Some i -> add_sleb128 (-i) + | None -> add_sleb128 (TM.find (normalize t) idx) in + + let add_typ t = + match t with + | Prim _ | Shared | Non -> assert false + | Tup ts -> + add_sleb128 (-20); + add_leb128 (List.length ts); + List.iteri (fun i t -> + add_leb128 i; + add_idx t; + ) ts + | Obj (Object Sharable, fs) -> + add_sleb128 (-20); + add_leb128 (List.length fs); + List.iter (fun (h, f) -> + add_leb128_32 h; + add_idx f.typ + ) (sort_by_hash fs) + | Obj (Actor, fs) -> + add_sleb128 (-23); + add_leb128 (List.length fs); + List.iter (fun f -> + add_leb128 (String.length f.lab); + Buffer.add_string buf f.lab; + add_idx f.typ + ) fs + | Array t -> + add_sleb128 (-19); add_idx t + | Opt t -> + add_sleb128 (-18); add_idx t + | Variant vs -> + add_sleb128 (-21); + add_leb128 (List.length vs); + List.iter (fun (h, f) -> + add_leb128_32 h; + add_idx f.typ + ) (sort_by_hash vs) + | Func (s, c, tbs, ts1, ts2) -> + add_sleb128 (-22); + add_leb128 (List.length ts1); + List.iter add_idx ts1; + add_leb128 (List.length ts2); + List.iter add_idx ts2; + add_leb128 0 (* no annotations *) + | _ -> assert false in + + Buffer.add_string buf "DIDL"; + add_leb128 (List.length typs); + List.iter add_typ typs; + add_idx (normalize t); + Buffer.contents buf (* Returns data (in bytes) and reference buffer size (in entries) needed *) let rec buffer_size env t = @@ -3188,19 +3352,26 @@ module Serialization = struct let name = "@serialize<" ^ typ_id t ^ ">" in Func.share_code1 env name ("x", I32Type) [I32Type] (fun env get_x -> match Type.normalize t with + (* Special-cased formats for scaffolding *) | Type.Prim Type.Text -> get_x ^^ Dfinity.compile_databuf_of_text env | Type.Obj (Type.Actor, _) | Type.Func (Type.Sharable, _, _, _, _) -> get_x ^^ Dfinity.unbox_reference env + (* normal format *) | _ -> let (set_data_size, get_data_size) = new_local env "data_size" in let (set_refs_size, get_refs_size) = new_local env "refs_size" in + let tydesc = type_desc t in + let tydesc_len = Int32.of_int (String.length tydesc) in + (* Get object sizes *) get_x ^^ buffer_size env t ^^ compile_add_const 1l ^^ (* Leave space for databuf *) compile_mul_const Heap.word_size ^^ set_refs_size ^^ + + compile_add_const tydesc_len ^^ set_data_size ^^ let (set_data_start, get_data_start) = new_local env "data_start" in @@ -3209,9 +3380,15 @@ module Serialization = struct get_data_size ^^ Text.dyn_alloc_scratch env ^^ set_data_start ^^ get_refs_size ^^ Text.dyn_alloc_scratch env ^^ set_refs_start ^^ + (* Write ty desc *) + get_data_start ^^ + Text.lit env tydesc ^^ Text.payload_ptr_unskewed ^^ + compile_unboxed_const tydesc_len ^^ + Heap.memcpy env ^^ + (* Serialize x into the buffer *) get_x ^^ - get_data_start ^^ + get_data_start ^^ compile_add_const tydesc_len ^^ get_refs_start ^^ compile_add_const Heap.word_size ^^ (* Leave space for databuf *) serialize_go env t ^^ @@ -3335,7 +3512,7 @@ module Serialization = struct Dfinity.system_call env "data_internalize" ^^ (* Go! *) - get_data_start ^^ + get_data_start ^^ E.call_import env "rts" "skip_idl_header" ^^ get_refs_start ^^ compile_add_const Heap.word_size ^^ deserialize_go env t ^^ G.i Drop ^^ From be983cc2053c6b38b74bb128eb361a55c23f5527 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity <48968912+chenyan-dfinity@users.noreply.github.com> Date: Tue, 2 Jul 2019 00:20:36 -0700 Subject: [PATCH 0225/1176] fix build error due to uint32 (#540) --- src/codegen/compile.ml | 12 ++++++------ src/lib/lib.ml | 3 +++ src/lib/lib.mli | 3 +++ 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 6f61ff33566..d616d063fda 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -2904,19 +2904,19 @@ module Serialization = struct let add_u8 i = Buffer.add_char buf (Char.chr (i land 0xff)) in - let rec add_leb128_32 (i : int32) = - let open Int32 in - let b = logand i 0x7fl in - if 0l <= i && i < 128l + let rec add_leb128_32 (i : Lib.Uint32.t) = + let open Lib.Uint32 in + let b = logand i (of_int32 0x7fl) in + if of_int32 0l <= i && i < of_int32 128l then add_u8 (to_int b) else begin - add_u8 (to_int (logor b 0x80l)); + add_u8 (to_int (logor b (of_int32 0x80l))); add_leb128_32 (shift_right_logical i 7) end in let add_leb128 i = assert (i >= 0); - add_leb128_32 (Int32.of_int i) in + add_leb128_32 (Lib.Uint32.of_int i) in let rec add_sleb128 i = let b = i land 0x7f in diff --git a/src/lib/lib.ml b/src/lib/lib.ml index ca10f517c0d..c93303bc09b 100644 --- a/src/lib/lib.ml +++ b/src/lib/lib.ml @@ -34,6 +34,9 @@ struct let one = Int32.one let of_int = Int32.of_int let to_int = Int32.to_int + let logand = Int32.logand + let logor = Int32.logor + let shift_right_logical = Int32.shift_right_logical let of_int32 x = x let to_int32 x = x let compare i1 i2 = diff --git a/src/lib/lib.mli b/src/lib/lib.mli index 599af8767b8..c29d3ea03bc 100644 --- a/src/lib/lib.mli +++ b/src/lib/lib.mli @@ -109,6 +109,9 @@ sig val zero : t val one : t val compare : t -> t -> int + val logand : t -> t -> t + val logor : t -> t -> t + val shift_right_logical : t -> int -> t end module String : From 9d8c12810c6367beb96998357d5d600ad4ad540c Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 3 Jul 2019 10:29:12 +0200 Subject: [PATCH 0226/1176] Remove virtual object fields from IR and compiler (#531) This adds definitions for the overloaded dot operations to the prelude so that we can desugar to them in `desugar.ml`. Moves T.array_obj and T.text_obj to typing. Removes lots of code from the backend. --- src/as_frontend/typing.ml | 26 ++++- src/as_ir/check_ir.ml | 3 - src/as_types/type.ml | 24 +---- src/as_types/type.mli | 9 +- src/as_values/prim.ml | 13 +++ src/codegen/compile.ml | 167 +++++++++---------------------- src/lowering/desugar.ml | 51 ++++++++-- src/prelude/prelude.ml | 43 ++++++++ test/fail/ok/abstract-msgs.tc.ok | 14 +-- 9 files changed, 181 insertions(+), 169 deletions(-) diff --git a/src/as_frontend/typing.ml b/src/as_frontend/typing.ml index 18538e832f8..decdca7ad15 100644 --- a/src/as_frontend/typing.ml +++ b/src/as_frontend/typing.ml @@ -395,6 +395,28 @@ let check_lit env t lit at = "literal of type\n %s\ndoes not have expected type\n %s" (T.string_of_typ t') (T.string_of_typ_expand t) +(* Coercions *) + +let array_obj t = + let open T in + let immut t = + [ {lab = "get"; typ = Func (Local, Returns, [], [Prim Nat], [t])}; + {lab = "len"; typ = Func (Local, Returns, [], [], [Prim Nat])}; + {lab = "keys"; typ = Func (Local, Returns, [], [], [iter_obj (Prim Nat)])}; + {lab = "vals"; typ = Func (Local, Returns, [], [], [iter_obj t])}; + ] in + let mut t = immut t @ + [ {lab = "set"; typ = Func (Local, Returns, [], [Prim Nat; t], [])} ] in + Object Local, + List.sort compare_field (match t with Mut t' -> mut t' | t -> immut t) + +let text_obj () = + let open T in + Object Local, + [ {lab = "chars"; typ = Func (Local, Returns, [], [], [iter_obj (Prim Char)])}; + {lab = "len"; typ = Func (Local, Returns, [], [], [Prim Nat])}; + ] + (* Expressions *) @@ -527,8 +549,8 @@ and infer_exp'' env exp : T.typ = let t1 = infer_exp_promote env exp1 in let _s, tfs = try T.as_obj_sub id.it t1 with Invalid_argument _ -> - try T.array_obj (T.as_array_sub t1) with Invalid_argument _ -> - try T.text_obj (T.as_prim_sub T.Text t1) with Invalid_argument _ -> + try array_obj (T.as_array_sub t1) with Invalid_argument _ -> + try text_obj (T.as_prim_sub T.Text t1) with Invalid_argument _ -> error env exp1.at "expected object type, but expression produces type\n %s" (T.string_of_typ_expand t1) diff --git a/src/as_ir/check_ir.ml b/src/as_ir/check_ir.ml index a9598d0e465..3c1c367809b 100644 --- a/src/as_ir/check_ir.ml +++ b/src/as_ir/check_ir.ml @@ -355,10 +355,7 @@ let rec check_exp env (exp:Ir.exp) : unit = check_exp env exp1; let t1 = typ exp1 in let sort, tfs = - (* TODO: separate array and text accessors *) try T.as_obj_sub n t1 with Invalid_argument _ -> - try T.array_obj (T.as_array_sub t1) with Invalid_argument _ -> - try T.text_obj (T.as_prim_sub T.Text t1) with Invalid_argument _ -> error env exp1.at "expected object type, but expression produces type\n %s" (T.string_of_typ_expand t1) in diff --git a/src/as_types/type.ml b/src/as_types/type.ml index b66fb4addba..9eb3704a5f1 100644 --- a/src/as_types/type.ml +++ b/src/as_types/type.ml @@ -75,6 +75,8 @@ let unit = Tup [] let bool = Prim Bool let nat = Prim Nat let int = Prim Int +let text = Prim Text +let char = Prim Char let prim = function | "Null" -> Null @@ -108,34 +110,12 @@ let compare_field f1 f2 = | {lab = l1; typ = _}, {lab = l2; typ = Typ _ } -> 1 | {lab = l1; typ = _}, {lab = l2; typ = _ } -> compare l1 l2 - (* Coercions *) -(* TODO: Move to typing once we have separated accessors in IR. *) - let iter_obj t = Obj (Object Local, [{lab = "next"; typ = Func (Local, Returns, [], [], [Opt t])}]) -let array_obj t = - let immut t = - [ {lab = "get"; typ = Func (Local, Returns, [], [Prim Nat], [t])}; - {lab = "len"; typ = Func (Local, Returns, [], [], [Prim Nat])}; - {lab = "keys"; typ = Func (Local, Returns, [], [], [iter_obj (Prim Nat)])}; - {lab = "vals"; typ = Func (Local, Returns, [], [], [iter_obj t])}; - ] in - let mut t = immut t @ - [ {lab = "set"; typ = Func (Local, Returns, [], [Prim Nat; t], [])} ] in - Object Local, - List.sort compare_field (match t with Mut t' -> mut t' | t -> immut t) - -let text_obj () = - Object Local, - [ {lab = "chars"; typ = Func (Local, Returns, [], [], [iter_obj (Prim Char)])}; - {lab = "len"; typ = Func (Local, Returns, [], [], [Prim Nat])}; - ] - - (* Shifting *) let rec shift i n t = diff --git a/src/as_types/type.mli b/src/as_types/type.mli index 9850712b039..d99db995cb4 100644 --- a/src/as_types/type.mli +++ b/src/as_types/type.mli @@ -64,6 +64,9 @@ val unit : typ val bool : typ val nat : typ val int : typ +val text : typ +val char : typ +val iter_obj : typ -> typ val prim : string -> prim @@ -126,12 +129,6 @@ val lookup_typ_field : string -> field list -> con option val compare_field : field -> field -> int -(* Corercions *) - -val array_obj : typ -> obj_sort * field list -val text_obj : unit -> obj_sort * field list - - (* Constructors *) val set_kind : con -> kind -> unit diff --git a/src/as_values/prim.ml b/src/as_values/prim.ml index 8c2c47222dd..92e0bcba75f 100644 --- a/src/as_values/prim.ml +++ b/src/as_values/prim.ml @@ -255,6 +255,19 @@ let prim = function k (Tup [Word32 (of_int (length nobbles)); Char (to_int code)]) | "@serialize" -> fun v k -> k (Serialized v) | "@deserialize" -> fun v k -> k (as_serialized v) + + | "array_len" -> fun v k -> + k (Int (Int.of_int (Array.length (Value.as_array v)))) + | "text_len" -> fun v k -> + k (Int (Nat.of_int (List.length (Wasm.Utf8.decode (Value.as_text v))))) + | "text_chars" -> fun v k -> + let i = ref 0 in + let s = Wasm.Utf8.decode (Value.as_text v) in + let next = local_func 0 1 @@ fun v k' -> + if !i = List.length s then k' Null else + let v = Opt (Char (List.nth s !i)) in incr i; k' v + in k (Obj (Env.singleton "next" next)) + | "Array.init" -> fun v k -> (match Value.as_tup v with | [len; x] -> diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index d616d063fda..44e61b62798 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -1034,7 +1034,7 @@ module Tagged = struct | _ -> true (* like branch_with but with type information to statically skip some branches *) - let branch_typed_with env ty retty branches = + let _branch_typed_with env ty retty branches = branch_with env retty (List.filter (fun (tag,c) -> can_have_tag ty tag) branches) let obj env tag element_instructions : G.t = @@ -1910,7 +1910,7 @@ module Iterators = struct get_x: The thing to put in the closure, and pass to mk_next Return code that takes the object (array or text) on the stack and puts a - closure onto the stack. + the iterator onto the stack. *) let create outer_env name mk_stop mk_next = Func.share_code1 outer_env name ("x", I32Type) [I32Type] (fun env get_x -> @@ -1952,23 +1952,14 @@ module Iterators = struct ) ) in - let iter_funid = E.add_fun env (name ^ "_iter") ( - Func.of_body env ["clos", I32Type] [I32Type] (fun env -> - (* closure for the function *) - let (set_ni, get_ni) = new_local env "next" in - Closure.fixed_closure env next_funid - [ Tagged.obj env Tagged.MutBox [ compile_unboxed_zero ] - ; Closure.get ^^ Closure.load_data 0l - ] ^^ - set_ni ^^ - - Object.lit_raw env - [ "next", fun _ -> get_ni ] - ) - ) in + let (set_ni, get_ni) = new_local env "next" in + Closure.fixed_closure env next_funid + [ Tagged.obj env Tagged.MutBox [ compile_unboxed_zero ] + ; get_x + ] ^^ + set_ni ^^ - (* Now build the closure *) - Closure.fixed_closure env iter_funid [ get_x ] + Object.lit_raw env [ "next", fun _ -> get_ni ] ) end (* Iterators *) @@ -2089,8 +2080,8 @@ module Text = struct get_res ^^ UnboxedSmallWord.box_codepoint ) - let text_chars env = - Iterators.create env "text_chars" + let text_chars_direct env = + Iterators.create env "text_chars_direct" (fun env get_x -> get_x ^^ Heap.load_field len_field) (fun env get_i get_x -> let (set_char, get_char) = new_local env "char" in @@ -2100,29 +2091,25 @@ module Text = struct get_char ^^ UnboxedSmallWord.box_codepoint ) - let partial_len env = - Func.share_code1 env "text_len_partial" ("x", I32Type) [I32Type] (fun env get_x -> - let funid = E.add_fun env "text_len" (Func.of_body env ["clos", I32Type] [I32Type] (fun env -> - let get_text_object = Closure.get ^^ Closure.load_data 0l in - let (set_max, get_max) = new_local env "max" in - let (set_n, get_n) = new_local env "n" in - let (set_len, get_len) = new_local env "len" in - compile_unboxed_zero ^^ set_n ^^ - compile_unboxed_zero ^^ set_len ^^ - get_text_object ^^ Heap.load_field len_field ^^ set_max ^^ - compile_while - (get_n ^^ get_max ^^ G.i (Compare (Wasm.Values.I32 I32Op.LtU))) - begin - get_text_object ^^ payload_ptr_unskewed ^^ get_n ^^ - G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ - UnboxedSmallWord.len_UTF8_head env (G.i Drop) ^^ - get_n ^^ G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ set_n ^^ - get_len ^^ compile_add_const 1l ^^ set_len - end ^^ - get_len ^^ - BigNum.from_word32 env - )) in - Closure.fixed_closure env funid [ get_x ] + let len env = + Func.share_code1 env "text_len" ("x", I32Type) [I32Type] (fun env get_x -> + let (set_max, get_max) = new_local env "max" in + let (set_n, get_n) = new_local env "n" in + let (set_len, get_len) = new_local env "len" in + compile_unboxed_zero ^^ set_n ^^ + compile_unboxed_zero ^^ set_len ^^ + get_x ^^ Heap.load_field len_field ^^ set_max ^^ + compile_while + (get_n ^^ get_max ^^ G.i (Compare (Wasm.Values.I32 I32Op.LtU))) + begin + get_x ^^ payload_ptr_unskewed ^^ get_n ^^ + G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ + UnboxedSmallWord.len_UTF8_head env (G.i Drop) ^^ + get_n ^^ G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ set_n ^^ + get_len ^^ compile_add_const 1l ^^ set_len + end ^^ + get_len ^^ + BigNum.from_word32 env ) let prim_showChar env = @@ -2217,64 +2204,12 @@ module Arr = struct G.i (Binary (Wasm.Values.I32 I32Op.Add)) ) - let partial_get env = - Func.share_code1 env "array_get_partial" ("x", I32Type) [I32Type] (fun env get_x -> - let funid = E.add_fun env "array_get" (Func.of_body env ["clos", I32Type; "idx", I32Type] [I32Type] (fun env1 -> - let get_idx = G.i (LocalGet (nr 1l)) in - Closure.get ^^ Closure.load_data 0l ^^ - get_idx ^^ BigNum.to_word32 env1 ^^ - idx env1 ^^ - load_ptr - )) in - Closure.fixed_closure env funid [ get_x ] - ) - - let partial_set env = - Func.share_code1 env "array_set_partial" ("x", I32Type) [I32Type] (fun env get_x -> - let funid = E.add_fun env "array_set" (Func.of_body env ["clos", I32Type; "idx", I32Type; "val", I32Type] [] (fun env1 -> - let get_idx = G.i (LocalGet (nr 1l)) in - let get_val = G.i (LocalGet (nr 2l)) in - Closure.get ^^ Closure.load_data 0l ^^ - get_idx ^^ BigNum.to_word32 env1 ^^ - idx env1 ^^ - get_val ^^ - store_ptr - )) in - Closure.fixed_closure env funid [ get_x ] - ) - - let partial_len env = - Func.share_code1 env "array_len_partial" ("x", I32Type) [I32Type] (fun env get_x -> - let funid = E.add_fun env "array_len" (Func.of_body env ["clos", I32Type] [I32Type] (fun env1 -> - Closure.get ^^ Closure.load_data 0l ^^ - Heap.load_field len_field ^^ - BigNum.from_word32 env1 - )) in - Closure.fixed_closure env funid [ get_x ] - ) - (* Compile an array literal. *) let lit env element_instructions = Tagged.obj env Tagged.Array ([ compile_unboxed_const (Wasm.I32.of_int_u (List.length element_instructions)) ] @ element_instructions) - let keys_iter env = - Iterators.create env "array_keys" - (fun env get_x -> get_x ^^ Heap.load_field len_field) - (fun env get_i get_x -> - compile_unboxed_const 1l ^^ (* advance by one *) - get_i ^^ BigNum.from_word32 env (* return the boxed index *) - ) - - let vals_iter env = - Iterators.create env "array_vals" - (fun env get_x -> get_x ^^ Heap.load_field len_field) - (fun env get_i get_x -> - compile_unboxed_const 1l ^^ (* advance by one *) - get_x ^^ get_i ^^ idx env ^^ load_ptr (* return the element *) - ) - (* Does not initialize the fields! *) let alloc env = let (set_len, get_len) = new_local env "len" in @@ -4937,30 +4872,8 @@ let compile_relop env t op = compile_comparison env t1 op1 | _ -> todo_trap env "compile_relop" (Arrange_ops.relop op) -(* compile_load_field implements the various “virtual fields”, which - we currently have for arrays and text. - It goes through branch_typed_with, which does a dynamic check of the - heap object type *) let compile_load_field env typ name = - let branches = - ( Tagged.Object, Object.load_idx env typ name ) :: - match name with - | "len" -> - [ Tagged.Array, Arr.partial_len env - ; Tagged.Text, Text.partial_len env ] - | "get" -> - [ Tagged.Array, Arr.partial_get env ] - | "set" -> - [ Tagged.Array, Arr.partial_set env ] - | "keys" -> - [ Tagged.Array, Arr.keys_iter env ] - | "vals" -> - [ Tagged.Array, Arr.vals_iter env ] - | "chars" -> - [ Tagged.Text, Text.text_chars env ] - | _ -> [] - in - Tagged.branch_typed_with env typ (ValBlockType (Some I32Type)) branches + Object.load_idx env typ name (* compile_lexp is used for expressions on the left of an assignment operator, produces some code (with side effect), and some pure code *) @@ -4996,7 +4909,7 @@ and compile_exp (env : E.t) ae exp = | DotE (e, name) -> SR.Vanilla, compile_exp_vanilla env ae e ^^ - compile_load_field env e.note.note_typ name + Object.load_idx env e.note.note_typ name | ActorDotE (e, name) -> SR.UnboxedReference, compile_exp_as env ae SR.UnboxedReference e ^^ @@ -5006,6 +4919,22 @@ and compile_exp (env : E.t) ae exp = begin (* First check for all unary prims. *) match p with + | "array_len" -> + SR.Vanilla, + compile_exp_vanilla env ae e ^^ + Heap.load_field Arr.len_field ^^ + BigNum.from_word32 env + + | "text_len" -> + SR.Vanilla, + compile_exp_vanilla env ae e ^^ + Text.len env + + | "text_chars" -> + SR.Vanilla, + compile_exp_vanilla env ae e ^^ + Text.text_chars_direct env + | "@serialize" -> SR.UnboxedReference, let t = match typ_args with [t] -> t | _ -> assert false in diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index f73cee929ce..68c58352d72 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -74,17 +74,14 @@ and exp' at note = function | S.ObjE (s, es) -> obj at s None es note.I.note_typ | S.TagE (c, e) -> I.TagE (c.it, exp e) + | S.DotE (e, x) when T.is_array e.note.S.note_typ -> + (array_dotE e.note.S.note_typ x.it (exp e)).it + | S.DotE (e, x) when T.is_prim T.Text e.note.S.note_typ -> + (text_dotE x.it (exp e)).it | S.DotE (e, x) -> - let n = x.it in - begin match - (* TODO: separate array and text accessors *) - try T.as_obj_sub x.it e.note.S.note_typ with Invalid_argument _ -> - try T.array_obj (T.as_array_sub e.note.S.note_typ) with Invalid_argument _ -> - try T.text_obj (T.as_prim_sub T.Text e.note.S.note_typ) with Invalid_argument _ -> - assert false - with - | T.Actor, _ -> I.ActorDotE (exp e, n) - | _ -> I.DotE (exp e, n) + begin match T.as_obj_sub x.it e.note.S.note_typ with + | T.Actor, _ -> I.ActorDotE (exp e, x.it) + | _ -> I.DotE (exp e, x.it) end | S.AssignE (e1, e2) -> I.AssignE (exp e1, exp e2) | S.ArrayE (m, es) -> @@ -181,6 +178,40 @@ and typ_bind tb = ; note = () } +and array_dotE array_ty proj e = + let fun_ty bs t1 t2 = T.Func (T.Local, T.Returns, bs, t1, t2) in + let varA = T.Var ("A", 0) in + let element_ty = T.as_immut (T.as_array array_ty) in + let call name t1 t2 = + let poly_array_ty = + if T.is_mut (T.as_array array_ty) + then T.Array (T.Mut varA) + else T.Array varA in + let ty_param = {T.var = "A"; T.bound = T.Any} in + let f = idE name (fun_ty [ty_param] [poly_array_ty] [fun_ty [] t1 t2]) in + callE f [element_ty] e in + match T.is_mut (T.as_array array_ty), proj with + | true, "len" -> call "@mut_array_len" [] [T.nat] + | false, "len" -> call "@immut_array_len" [] [T.nat] + | true, "get" -> call "@mut_array_get" [T.nat] [varA] + | false, "get" -> call "@immut_array_get" [T.nat] [varA] + | true, "set" -> call "@mut_array_set" [T.nat; varA] [] + | true, "keys" -> call "@mut_array_keys" [] [T.iter_obj T.nat] + | false, "keys" -> call "@immut_array_keys" [] [T.iter_obj T.nat] + | true, "vals" -> call "@mut_array_vals" [] [T.iter_obj varA] + | false, "vals" -> call "@immut_array_vals" [] [T.iter_obj varA] + | _, _ -> assert false + +and text_dotE proj e = + let fun_ty t1 t2 = T.Func (T.Local, T.Returns, [], t1, t2) in + let call name t1 t2 = + let f = idE name (fun_ty [T.text] [fun_ty t1 t2]) in + callE f [] e in + match proj with + | "len" -> call "@text_len" [] [T.nat] + | "chars" -> call "@text_chars" [] [T.iter_obj T.char] + | _ -> assert false + and block force_unit ds = let extra = extra_typDs ds in let prefix, last = Lib.List.split_last ds in diff --git a/src/prelude/prelude.ml b/src/prelude/prelude.ml index cea163e645b..950081d384f 100644 --- a/src/prelude/prelude.ml +++ b/src/prelude/prelude.ml @@ -39,6 +39,49 @@ class revrange(x : Nat, y : Nat) { next() : ?Nat { if (i <= y) null else {i -= 1; ?i} }; }; +// Implementations for overloaded dot operations +// Note that these return functions! +// (Some optimizations in the backend might be feasible.) + +func @immut_array_get(xs : [A]) : (Nat -> A) = + (func (n : Nat) : A = xs[n]); +func @mut_array_get(xs : [var A]) : (Nat -> A) = + (func (n : Nat) : A = xs[n]); +func @immut_array_len(xs : [A]) : (() -> Nat) = + (func () : Nat = (prim "array_len" : ([A]) -> Nat) xs); +func @mut_array_len(xs : [var A]) : (() -> Nat) = + (func () : Nat = (prim "array_len" : ([var A]) -> Nat) xs); +func @mut_array_set(xs : [var A]) : ((Nat, A) -> ()) = + (func (n : Nat, x : A) = (xs[n] := x)); +func @immut_array_keys(xs : [A]) : (() -> Iter) = + (func () : Iter = new { + private var i = 0; + private l = xs.len(); + next() : ?Nat { if (i >= l) null else {let j = i; i += 1; ?j} }; + }); +func @mut_array_keys(xs : [var A]) : (() -> Iter) = + (func () : Iter = new { + private var i = 0; + private l = xs.len(); + next() : ?Nat { if (i >= l) null else {let j = i; i += 1; ?j} }; + }); +func @immut_array_vals(xs : [A]) : (() -> Iter) = + (func () : Iter = new { + private var i = 0; + private l = xs.len(); + next() : ?A { if (i >= l) null else {let j = i; i += 1; ?xs[j]} }; + }); +func @mut_array_vals(xs : [var A]) : (() -> Iter) = + (func () : Iter = new { + private var i = 0; + private l = xs.len(); + next() : ?A { if (i >= l) null else {let j = i; i += 1; ?xs[j]} }; + }); +func @text_len(xs : Text) : (() -> Nat) = + (func () : Nat = (prim "text_len" : Text -> Nat) xs); +func @text_chars(xs : Text) : (() -> Iter) = + (func () : Iter = (prim "text_chars" : Text -> Iter) xs); + // for testing func idlHash(x : Text) : Word32 { (prim "idlHash" : Text -> Word32) x }; diff --git a/test/fail/ok/abstract-msgs.tc.ok b/test/fail/ok/abstract-msgs.tc.ok index f1619b120dd..8b869759f92 100644 --- a/test/fail/ok/abstract-msgs.tc.ok +++ b/test/fail/ok/abstract-msgs.tc.ok @@ -1,14 +1,14 @@ abstract-msgs.as:2.31-2.40: type error, shared function parameter contains abstract type - A/1 + A/19 abstract-msgs.as:3.36-3.38: type error, shared function has non-async result type - ?A/3 + ?A/21 abstract-msgs.as:5.20-5.29: type error, shared function parameter contains abstract type - A/5 + A/23 abstract-msgs.as:6.25-6.33: type error, shared function result contains abstract type - ?A/5 + ?A/23 abstract-msgs.as:10.58-10.59: type error, shared function argument contains abstract type - A/7 + A/25 abstract-msgs.as:11.82-11.84: type error, shared function call result contains abstract type - async A/9 + async A/27 abstract-msgs.as:29.44-29.53: type error, shared function parameter contains abstract type - X/1 = shared A/19 -> () + X/1 = shared A/37 -> () From 9e3578fdae90e27c58e226f6b2d53628197bbe97 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 3 Jul 2019 10:54:19 +0200 Subject: [PATCH 0227/1176] Do dispatch on overloaded dot in interpreter removes `obj_of_array` from `Value`, which is good! I am a bit worried about having to look at the source note when for other cases of overloading (operators, show) there is a `typ ref` field in the constructor that gets filled in by the type checker. Should this happen here as well? (Maybe filling only an enum type that indicates object, actor, text or array might suffice.) --- src/as_values/value.ml | 54 +-------------------------- src/interpreter/interpret.ml | 72 ++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 53 deletions(-) diff --git a/src/as_values/value.ml b/src/as_values/value.ml index 47217cf6458..d826d3b6df3 100644 --- a/src/as_values/value.ml +++ b/src/as_values/value.ml @@ -319,59 +319,7 @@ let as_tup = function Tup vs -> vs | _ -> invalid "as_tup" let as_unit = function Tup [] -> () | _ -> invalid "as_unit" let as_pair = function Tup [v1; v2] -> v1, v2 | _ -> invalid "as_pair" let as_serialized = function Serialized v -> v | _ -> invalid "as_serialized" - -let obj_of_array a = - let get = local_func 1 1 @@ fun v k -> - let n = as_int v in - if Nat.lt n (Nat.of_int (Array.length a)) then - k (a.(Nat.to_int n)) - else - raise (Invalid_argument "array index out of bounds") in - - let set = local_func 2 0 @@ fun v k -> - let v1, v2 = as_pair v in - let n = as_int v1 in - if Nat.lt n (Nat.of_int (Array.length a)) then - k (a.(Nat.to_int n) <- v2; Tup []) - else - raise (Invalid_argument "array index out of bounds") in - - let len = local_func 0 1 @@ fun v k -> - as_unit v; k (Int (Nat.of_int (Array.length a))) in - - let keys = local_func 0 1 @@ fun v k -> - as_unit v; - let i = ref 0 in - let next = local_func 0 1 @@ fun v k' -> - if !i = Array.length a then k' Null else - let v = Opt (Int (Nat.of_int !i)) in incr i; k' v - in k (Obj (Env.singleton "next" next)) in - - let vals = local_func 0 1 @@ fun v k -> - as_unit v; - let i = ref 0 in - let next = local_func 0 1 @@ fun v k' -> - if !i = Array.length a then k' Null else - let v = Opt (a.(!i)) in incr i; k' v - in k (Obj (Env.singleton "next" next)) in - - Env.from_list ["get", get; "set", set; "len", len; "keys", keys; "vals", vals] - -let obj_of_text t = - let chars = local_func 0 1 @@ fun v k -> - as_unit v; - let i = ref 0 in - let s = Wasm.Utf8.decode t in - let next = local_func 0 1 @@ fun v k' -> - if !i = List.length s then k' Null else - let v = Opt (Char (List.nth s !i)) in incr i; k' v - in k (Obj (Env.singleton "next" next)) in - let len = local_func 0 1 @@ fun v k -> - as_unit v; k (Int (Nat.of_int (List.length (Wasm.Utf8.decode t)))) in - - Env.from_list ["chars", chars; "len", len] - -let as_obj = function Obj ve -> ve | Array a -> obj_of_array a | Text t -> obj_of_text t | _ -> invalid "as_obj" +let as_obj = function Obj ve -> ve | _ -> invalid "as_obj" let as_func = function Func (cc, f) -> cc, f | _ -> invalid "as_func" let as_async = function Async a -> a | _ -> invalid "as_async" let as_mut = function Mut r -> r | _ -> invalid "as_mut" diff --git a/src/interpreter/interpret.ml b/src/interpreter/interpret.ml index 47ac5c4c15e..3fb3fcf3dd6 100644 --- a/src/interpreter/interpret.ml +++ b/src/interpreter/interpret.ml @@ -230,6 +230,64 @@ let interpret_lit env lit : V.value = | TextLit s -> V.Text s | PreLit _ -> assert false +(* Overloaded dot implementations *) + +let array_get a = V.(local_func 1 1 (fun v k -> + let n = as_int v in + if Nat.lt n (Nat.of_int (Array.length a)) + then k (a.(Nat.to_int n)) + else raise (Invalid_argument "array index out of bounds") +)) + +let array_set a = V.(local_func 2 0 (fun v k -> + let v1, v2 = as_pair v in + let n = as_int v1 in + if Nat.lt n (Nat.of_int (Array.length a)) + then k (a.(Nat.to_int n) <- v2; Tup []) + else raise (Invalid_argument "array index out of bounds") +)) + +let array_len a = V.(local_func 0 1 (fun v k -> + as_unit v; k (Int (Nat.of_int (Array.length a))) +)) + +let array_keys a = V.(local_func 0 1 (fun v k -> + as_unit v; + let i = ref 0 in + let next = local_func 0 1 (fun v k' -> + if !i = Array.length a + then k' Null + else let v = Opt (Int (Nat.of_int !i)) in incr i; k' v + ) in + k (Obj (Env.singleton "next" next)) +)) + +let array_vals a = V.(local_func 0 1 (fun v k -> + as_unit v; + let i = ref 0 in + let next = local_func 0 1 (fun v k' -> + if !i = Array.length a + then k' Null + else let v = Opt (a.(!i)) in incr i; k' v + ) in + k (Obj (Env.singleton "next" next)) +)) + +let text_chars t = V.(local_func 0 1 (fun v k -> + as_unit v; + let i = ref 0 in + let s = Wasm.Utf8.decode t in + let next = local_func 0 1 (fun v k' -> + if !i = List.length s + then k' Null + else let v = Opt (Char (List.nth s !i)) in incr i; k' v + ) in + k (Obj (Env.singleton "next" next)) +)) + +let text_len t = V.(local_func 0 1 (fun v k -> + as_unit v; k (Int (Nat.of_int (List.length (Wasm.Utf8.decode t)))) +)) (* Expressions *) @@ -316,6 +374,20 @@ and interpret_exp_mut env exp (k : V.value V.cont) = interpret_obj env sort fields k | TagE (i, exp1) -> interpret_exp env exp1 (fun v1 -> k (V.Variant (i.it, v1))) + | DotE (exp1, x) when T.is_array exp1.note.note_typ && x.it = "len"-> + interpret_exp env exp1 (fun v -> k (array_len (V.as_array v))) + | DotE (exp1, x) when T.is_array exp1.note.note_typ && x.it = "get"-> + interpret_exp env exp1 (fun v -> k (array_get (V.as_array v))) + | DotE (exp1, x) when T.is_array exp1.note.note_typ && x.it = "set"-> + interpret_exp env exp1 (fun v -> k (array_set (V.as_array v))) + | DotE (exp1, x) when T.is_array exp1.note.note_typ && x.it = "keys"-> + interpret_exp env exp1 (fun v -> k (array_keys (V.as_array v))) + | DotE (exp1, x) when T.is_array exp1.note.note_typ && x.it = "vals"-> + interpret_exp env exp1 (fun v -> k (array_vals (V.as_array v))) + | DotE (exp1, x) when T.is_prim T.Text exp1.note.note_typ && x.it = "len"-> + interpret_exp env exp1 (fun v -> k (text_len (V.as_text v))) + | DotE (exp1, x) when T.is_prim T.Text exp1.note.note_typ && x.it = "chars"-> + interpret_exp env exp1 (fun v -> k (text_chars (V.as_text v))) | DotE (exp1, id) -> interpret_exp env exp1 (fun v1 -> let fs = V.as_obj v1 in From f0c5164f57b802c73bc129063cf369e97aac3a70 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 3 Jul 2019 11:44:29 +0200 Subject: [PATCH 0228/1176] Code prettification --- src/interpreter/interpret.ml | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/interpreter/interpret.ml b/src/interpreter/interpret.ml index 3fb3fcf3dd6..128e50553d9 100644 --- a/src/interpreter/interpret.ml +++ b/src/interpreter/interpret.ml @@ -374,18 +374,21 @@ and interpret_exp_mut env exp (k : V.value V.cont) = interpret_obj env sort fields k | TagE (i, exp1) -> interpret_exp env exp1 (fun v1 -> k (V.Variant (i.it, v1))) - | DotE (exp1, x) when T.is_array exp1.note.note_typ && x.it = "len"-> - interpret_exp env exp1 (fun v -> k (array_len (V.as_array v))) - | DotE (exp1, x) when T.is_array exp1.note.note_typ && x.it = "get"-> - interpret_exp env exp1 (fun v -> k (array_get (V.as_array v))) - | DotE (exp1, x) when T.is_array exp1.note.note_typ && x.it = "set"-> - interpret_exp env exp1 (fun v -> k (array_set (V.as_array v))) - | DotE (exp1, x) when T.is_array exp1.note.note_typ && x.it = "keys"-> - interpret_exp env exp1 (fun v -> k (array_keys (V.as_array v))) - | DotE (exp1, x) when T.is_array exp1.note.note_typ && x.it = "vals"-> - interpret_exp env exp1 (fun v -> k (array_vals (V.as_array v))) - | DotE (exp1, x) when T.is_prim T.Text exp1.note.note_typ && x.it = "len"-> - interpret_exp env exp1 (fun v -> k (text_len (V.as_text v))) + | DotE (exp1, x) when T.is_array exp1.note.note_typ -> + let f = match x.it with + | "len" -> array_len + | "get" -> array_get + | "set" -> array_set + | "keys" -> array_keys + | "vals" -> array_vals + | _ -> assert false in + interpret_exp env exp1 (fun v -> k (f (V.as_array v))) + | DotE (exp1, x) when T.is_prim T.Text exp1.note.note_typ -> + let f = match x.it with + | "len" -> text_len + | "chars" -> text_chars + | _ -> assert false in + interpret_exp env exp1 (fun v -> k (f (V.as_text v))) | DotE (exp1, x) when T.is_prim T.Text exp1.note.note_typ && x.it = "chars"-> interpret_exp env exp1 (fun v -> k (text_chars (V.as_text v))) | DotE (exp1, id) -> From bec7fc90552e64f821edce97a157111e60a833c3 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Wed, 3 Jul 2019 14:56:56 +0200 Subject: [PATCH 0229/1176] Analysis mode for function expressions (#544) * Checking mode for functions * Checking mode for result type --- src/as_frontend/arrange.ml | 2 +- src/as_frontend/parser.mly | 9 +++-- src/as_frontend/syntax.ml | 6 +--- src/as_frontend/typing.ml | 52 ++++++++++++++------------- src/lowering/desugar.ml | 5 +-- test/fail/ok/type-inference.tc.ok | 20 +++++------ test/fail/type-inference.as | 58 +++++++++++++++++++++++++++---- 7 files changed, 97 insertions(+), 55 deletions(-) diff --git a/src/as_frontend/arrange.ml b/src/as_frontend/arrange.ml index 98d2e2cdca6..475c7fdd0c2 100644 --- a/src/as_frontend/arrange.ml +++ b/src/as_frontend/arrange.ml @@ -31,7 +31,7 @@ let rec exp e = match e.it with Atom x] @ List.map typ_bind tp @ [ pat p; - typ t; + (match t with None -> Atom "_" | Some t -> typ t); exp e' ] | CallE (e1, ts, e2) -> "CallE" $$ [exp e1] @ List.map typ ts @ [exp e2] diff --git a/src/as_frontend/parser.mly b/src/as_frontend/parser.mly index 960f8bc30d8..1f9729ca32a 100644 --- a/src/as_frontend/parser.mly +++ b/src/as_frontend/parser.mly @@ -605,16 +605,15 @@ dec : { ExpD e @? at $sloc } func_exp : - | tps=typ_params_opt p=pat_argument rt=return_typ? fb=func_body - { let t = Lib.Option.get rt (TupT([]) @! no_region) in - (* This is a hack to support local func declarations that return a computed async. + | tps=typ_params_opt p=pat_argument t=return_typ? fb=func_body + { (* This is a hack to support local func declarations that return a computed async. These should be defined using RHS syntax EQ e to avoid the implicit AsyncE introduction around bodies declared as blocks *) let e = match fb with | (false, e) -> e (* body declared as EQ e *) | (true, e) -> (* body declared as immediate block *) - match t.it with - | AsyncT _ -> AsyncE(e) @? e.at + match t with + | Some {it = AsyncT _; _} -> AsyncE(e) @? e.at | _ -> e in fun s x -> FuncE(x, s, tps, p, t, e) @? at $sloc } diff --git a/src/as_frontend/syntax.ml b/src/as_frontend/syntax.ml index 8567860b45b..b2fa117df62 100644 --- a/src/as_frontend/syntax.ml +++ b/src/as_frontend/syntax.ml @@ -40,10 +40,6 @@ and typ' = | FuncT of sharing * typ_bind list * typ * typ (* function *) | AsyncT of typ (* future *) | ParT of typ (* parentheses, used to control function arity only *) -(* - | UnionT of type * typ (* union *) - | AtomT of string (* atom *) -*) and typ_field = typ_field' Source.phrase and typ_field' = {id : id; typ : typ; mut : mut} @@ -128,7 +124,7 @@ and exp' = | AssignE of exp * exp (* assignment *) | ArrayE of mut * exp list (* array *) | IdxE of exp * exp (* array indexing *) - | FuncE of string * sharing * typ_bind list * pat * typ * exp (* function *) + | FuncE of string * sharing * typ_bind list * pat * typ option * exp (* function *) | CallE of exp * typ list * exp (* function call *) | BlockE of dec list (* block (with type after avoidance)*) | NotE of exp (* negation *) diff --git a/src/as_frontend/typing.ml b/src/as_frontend/typing.ml index decdca7ad15..2616eb11714 100644 --- a/src/as_frontend/typing.ml +++ b/src/as_frontend/typing.ml @@ -593,7 +593,12 @@ and infer_exp'' env exp : T.typ = "expected array type, but expression produces type\n %s" (T.string_of_typ_expand t1) ) - | FuncE (_, sort, typ_binds, pat, typ, exp) -> + | FuncE (_, sort, typ_binds, pat, typ_opt, exp) -> + let typ = + match typ_opt with + | Some typ -> typ + | None -> {it = TupT []; at = no_region; note = T.Pre} + in let cs, ts, te, ce = check_typ_binds env typ_binds in let env' = adjoin_typs env te ce in let t1, ve = infer_pat_exhaustive env' pat in @@ -630,7 +635,7 @@ and infer_exp'' env exp : T.typ = (T.string_of_typ_expand t2) end end; - let ts1 = match pat.it with TupP ps -> T.as_seq t1 | _ -> [t1] in + let ts1 = match pat.it with TupP _ -> T.as_seq t1 | _ -> [t1] in let ts2 = match typ.it with TupT _ -> T.as_seq t2 | _ -> [t2] in let c = match sort.it, typ.it with @@ -862,6 +867,26 @@ and check_exp' env t exp : T.typ = warn env exp.at "the cases in this switch do not cover all possible values"; t + | FuncE (_, s', [], pat, typ_opt, exp), T.Func (s, _, [], ts1, ts2) -> + let ve = check_pat_exhaustive env (T.seq ts1) pat in + let t2 = + match typ_opt with + | None -> T.seq ts2 + | Some typ -> check_typ env typ + in + if s'.it <> s then + error env exp.at + "%sshared function does not match expected %sshared function type" + (if s'.it = T.Local then "non-" else "") + (if s = T.Local then "non-" else ""); + if not (T.sub t2 (T.seq ts2)) then + error env exp.at + "function return type\n %s\ndoes not match expected return type\n %s" + (T.string_of_typ_expand t2) (T.string_of_typ_expand (T.seq ts2)); + let env' = + {env with labs = T.Env.empty; rets = Some t2; async = false} in + check_exp (adjoin_vals env' ve) t2 exp; + t | _ -> let t' = infer_exp env exp in if not (T.sub t' t) then @@ -1296,29 +1321,6 @@ and check_dec env t dec = | ExpD exp -> check_exp env t exp; dec.note <- exp.note -(* TBR: push in external type annotation; - 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 - ignore (infer_dec env dec) - else - (match T.nonopt env.cons t with - | T.Func ([], t1, t2)-> - let ve = check_pat env t1 pat in - let t2' = check_typ env typ in - (* TBR: infer return type *) - if not (T.eq env.cons t2 t2') then - error dec.at "expected return type %s but found %s" - (T.string_of_typ t2) (T.string_of_typ t2'); - let env' = - {env with labs = T.Env.empty; rets = Some t2; async = false} in - check_exp (adjoin_vals env' ve) t2 exp - | _ -> - error exp.at "function expression cannot produce expected type %s" - (T.string_of_typ t) - ) -*) | _ -> let t' = infer_dec env dec in if not (T.eq t T.unit || T.sub t' t) then diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 68c58352d72..8d1fb562b9b 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -88,10 +88,11 @@ and exp' at note = function let t = T.as_array note.I.note_typ in I.ArrayE (mut m, T.as_immut t, exps es) | S.IdxE (e1, e2) -> I.IdxE (exp e1, exp e2) - | S.FuncE (name, s, tbs, p, ty, e) -> + | S.FuncE (name, s, tbs, p, ty_opt, e) -> let cc = Call_conv.call_conv_of_typ note.I.note_typ in let args, wrap = to_args cc p in - let tys = if cc.Call_conv.n_res = 1 then [ty.note] else T.as_seq ty.note in + let ty = match ty_opt with Some ty -> ty.note | None -> T.Tup [] in + let tys = if cc.Call_conv.n_res = 1 then [ty] else T.as_seq ty in I.FuncE (name, cc, typ_binds tbs, args, tys, wrap (exp e)) | S.CallE (e1, inst, e2) -> let t = e1.Source.note.S.note_typ in diff --git a/test/fail/ok/type-inference.tc.ok b/test/fail/ok/type-inference.tc.ok index 6fcd921c9f0..68f382f616d 100644 --- a/test/fail/ok/type-inference.tc.ok +++ b/test/fail/ok/type-inference.tc.ok @@ -1,39 +1,39 @@ -type-inference.as:10.9-10.28: warning, this if has type Shared because branches have inconsistent types, +type-inference.as:3.9-3.28: warning, this if has type Shared because branches have inconsistent types, true produces Bool false produces Nat -type-inference.as:11.9-11.34: warning, this if has type Any because branches have inconsistent types, +type-inference.as:4.9-4.34: warning, this if has type Any because branches have inconsistent types, true produces Bool false produces [var Nat] -type-inference.as:12.9-12.27: warning, this if has type Shared because branches have inconsistent types, +type-inference.as:5.9-5.27: warning, this if has type Shared because branches have inconsistent types, true produces Nat false produces Float -type-inference.as:13.9-13.33: warning, this if has type Any because branches have inconsistent types, +type-inference.as:6.9-6.33: warning, this if has type Any because branches have inconsistent types, true produces () false produces {} -type-inference.as:18.33-18.41: warning, the switch has type Shared because branches have inconsistent types, +type-inference.as:11.33-11.41: warning, the switch has type Shared because branches have inconsistent types, this case produces type Bool the previous produce type Nat -type-inference.as:19.33-19.47: warning, the switch has type Any because branches have inconsistent types, +type-inference.as:12.33-12.47: warning, the switch has type Any because branches have inconsistent types, this case produces type Bool the previous produce type [var Nat] -type-inference.as:20.43-20.56: warning, the switch has type Shared because branches have inconsistent types, +type-inference.as:13.43-13.56: warning, the switch has type Shared because branches have inconsistent types, this case produces type Int the previous produce type Text -type-inference.as:25.9-25.18: warning, this array has type [Shared] because elements have inconsistent types -type-inference.as:26.9-26.24: warning, this array has type [Any] because elements have inconsistent types -type-inference.as:84.13-84.16: type error, expected iterable type, but expression has type +type-inference.as:19.9-19.18: warning, this array has type [Shared] because elements have inconsistent types +type-inference.as:20.9-20.24: warning, this array has type [Any] because elements have inconsistent types +type-inference.as:81.13-81.16: type error, expected iterable type, but expression has type Non diff --git a/test/fail/type-inference.as b/test/fail/type-inference.as index 1e34c3643be..2ec976e4075 100644 --- a/test/fail/type-inference.as +++ b/test/fail/type-inference.as @@ -1,10 +1,3 @@ -func f(g : Int -> Int) : Int = g 5; -/* TBR -let x = f(func x = x); -let y = f(func x = x + 1); -*/ - - // Branch warnings. let _ = if true true else 5; @@ -20,11 +13,13 @@ let _ = switch 0 { case 0 true; case _ [var 5] }; let _ = switch 0 { case 0 2; case 2 (-5); case 3 "text"; case _ () }; let _ = switch 0 { case 0 true; case _ (() : Any); }; // ok + // Array warnings. let _ = [true, 5]; let _ = [true, [var 5]]; + // Local types (not) escaping. let x = @@ -70,7 +65,9 @@ func top(top : Top) { }; }; + // Bottom Type + { type Bot = None; func bot(bot : Bot) { @@ -97,3 +94,50 @@ func bot(bot : Bot) { o; }; }; + + +// Function types. + +func f(h : Int -> Int) : Int = h 5; +func g(h : (Int, Int) -> Int) : Int = h(5, 6); +func k(h : {#A; #B : Int} -> Int) : Int = h(#B 9); + +let _ = f(func x = x); +let _ = f(func x = x + 1); +let _ = f(func x = abs(x + 1)); +let _ = f(func x = -1); +let _ = g(func p = abs(p.0)); +let _ = g(func(x, y) = x + y); +let _ = g(func(x, y) = abs x); +let _ = k(func(#A or #B _) = 0); + +let _ = f(func x : Int = x); +let _ = f(func x : Int = x + 1); +let _ = f(func x : Nat = abs(x + 1)); +let _ = f(func x : Int = 0); +let _ = g(func p : Nat = abs(p.0)); +let _ = g(func(x, y) : Int = x + y); +let _ = g(func(x, _) : Nat = abs x); +let _ = k(func(#A or #B _) : Nat = 0); + +let _ = f(func(x : Int) : Int = x); +let _ = f(func(x : Int) : Int = x + 1); +let _ = f(func(x : Int) : Nat = abs(x + 1)); +let _ = f(func(x : Any) : Int = 0); +let _ = g(func(p : (Int, Any)) : Nat = abs(p.0)); +let _ = g(func(x : Int, y : Int) : Int = x + y); +let _ = g(func(x : Int, _ : Any) : Nat = abs x); +let _ = g(func((x, _) : (Int, Any)) : Nat = abs x); +let _ = k(func(#A or #B (_ : Any)) : Nat = 0); +let _ = k(func((#A or #B _) : {#A; #B : Any}) : Nat = 0); + +let _ = f(func<>(x : Int) : Int = x); +let _ = f(func<>(x : Int) : Int = x + 1); +let _ = f(func<>(x : Int) : Nat = abs(x + 1)); +let _ = f(func<>(x : Any) : Int = 0); +let _ = g(func<>(p : (Int, Any)) : Nat = abs(p.0)); +let _ = g(func<>(x : Int, y : Int) : Int = x + y); +let _ = g(func<>(x : Int, y : Any) : Nat = abs x); +let _ = g(func<>((x, _) : (Int, Any)) : Nat = abs x); +let _ = k(func<>(#A or #B (_ : Any)) : Nat = 0); +let _ = k(func<>((#A or #B _) : {#A; #B : Any}) : Nat = 0); From da2f57b875866361d2d664d98e124b13ea0621f1 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Wed, 3 Jul 2019 16:22:10 +0200 Subject: [PATCH 0230/1176] Overload on value --- src/interpreter/interpret.ml | 180 ++++++++++++++++++---------------- src/interpreter/interpret.mli | 16 +-- 2 files changed, 105 insertions(+), 91 deletions(-) diff --git a/src/interpreter/interpret.ml b/src/interpreter/interpret.ml index 128e50553d9..549844cf8e7 100644 --- a/src/interpreter/interpret.ml +++ b/src/interpreter/interpret.ml @@ -14,15 +14,15 @@ type lib_env = V.value V.Env.t type lab_env = V.value V.cont V.Env.t type ret_env = V.value V.cont option -type flags = { - trace : bool; - print_depth : int -} +type flags = + { trace : bool; + print_depth : int + } -type scope = { - val_env: V.def V.Env.t; - lib_env: V.value V.Env.t; -} +type scope = + { val_env: V.def V.Env.t; + lib_env: V.value V.Env.t; + } type env = { flags : flags; @@ -230,64 +230,78 @@ let interpret_lit env lit : V.value = | TextLit s -> V.Text s | PreLit _ -> assert false + (* Overloaded dot implementations *) -let array_get a = V.(local_func 1 1 (fun v k -> - let n = as_int v in - if Nat.lt n (Nat.of_int (Array.length a)) - then k (a.(Nat.to_int n)) - else raise (Invalid_argument "array index out of bounds") -)) - -let array_set a = V.(local_func 2 0 (fun v k -> - let v1, v2 = as_pair v in - let n = as_int v1 in - if Nat.lt n (Nat.of_int (Array.length a)) - then k (a.(Nat.to_int n) <- v2; Tup []) - else raise (Invalid_argument "array index out of bounds") -)) - -let array_len a = V.(local_func 0 1 (fun v k -> - as_unit v; k (Int (Nat.of_int (Array.length a))) -)) - -let array_keys a = V.(local_func 0 1 (fun v k -> - as_unit v; - let i = ref 0 in - let next = local_func 0 1 (fun v k' -> - if !i = Array.length a - then k' Null - else let v = Opt (Int (Nat.of_int !i)) in incr i; k' v - ) in - k (Obj (Env.singleton "next" next)) -)) - -let array_vals a = V.(local_func 0 1 (fun v k -> - as_unit v; - let i = ref 0 in - let next = local_func 0 1 (fun v k' -> - if !i = Array.length a - then k' Null - else let v = Opt (a.(!i)) in incr i; k' v - ) in - k (Obj (Env.singleton "next" next)) -)) - -let text_chars t = V.(local_func 0 1 (fun v k -> - as_unit v; - let i = ref 0 in - let s = Wasm.Utf8.decode t in - let next = local_func 0 1 (fun v k' -> - if !i = List.length s - then k' Null - else let v = Opt (Char (List.nth s !i)) in incr i; k' v - ) in - k (Obj (Env.singleton "next" next)) -)) - -let text_len t = V.(local_func 0 1 (fun v k -> - as_unit v; k (Int (Nat.of_int (List.length (Wasm.Utf8.decode t)))) -)) +let array_get a at = + V.local_func 1 1 (fun v k -> + let n = V.as_int v in + if V.Nat.lt n (V.Nat.of_int (Array.length a)) + then k (a.(V.Nat.to_int n)) + else trap at "array index out of bounds" + ) + +let array_set a at = + V.local_func 2 0 (fun v k -> + let v1, v2 = V.as_pair v in + let n = V.as_int v1 in + if V.Nat.lt n (V.Nat.of_int (Array.length a)) + then k (a.(V.Nat.to_int n) <- v2; V.Tup []) + else trap at "array index out of bounds" + ) + +let array_len a at = + V.local_func 0 1 (fun v k -> + V.as_unit v; + k (V.Int (V.Nat.of_int (Array.length a))) + ) + +let array_keys a at = + V.local_func 0 1 (fun v k -> + V.as_unit v; + let i = ref 0 in + let next = + V.local_func 0 1 (fun v k' -> + if !i = Array.length a + then k' V.Null + else let v = V.Opt (V.Int (V.Nat.of_int !i)) in incr i; k' v + ) + in k (V.Obj (V.Env.singleton "next" next)) + ) + +let array_vals a at = + V.local_func 0 1 (fun v k -> + V.as_unit v; + let i = ref 0 in + let next = + V.local_func 0 1 (fun v k' -> + if !i = Array.length a + then k' V.Null + else let v = V.Opt a.(!i) in incr i; k' v + ) + in k (V.Obj (V.Env.singleton "next" next)) + ) + +let text_chars t at = + V.local_func 0 1 (fun v k -> + V.as_unit v; + let i = ref 0 in + let s = Wasm.Utf8.decode t in + let next = + V.local_func 0 1 (fun v k' -> + if !i = List.length s + then k' V.Null + else let v = V.Opt (V.Char (List.nth s !i)) in incr i; k' v + ) + in k (V.Obj (V.Env.singleton "next" next)) + ) + +let text_len t at = + V.local_func 0 1 (fun v k -> + V.as_unit v; + k (V.Int (V.Nat.of_int (List.length (Wasm.Utf8.decode t)))) + ) + (* Expressions *) @@ -374,27 +388,27 @@ and interpret_exp_mut env exp (k : V.value V.cont) = interpret_obj env sort fields k | TagE (i, exp1) -> interpret_exp env exp1 (fun v1 -> k (V.Variant (i.it, v1))) - | DotE (exp1, x) when T.is_array exp1.note.note_typ -> - let f = match x.it with - | "len" -> array_len - | "get" -> array_get - | "set" -> array_set - | "keys" -> array_keys - | "vals" -> array_vals - | _ -> assert false in - interpret_exp env exp1 (fun v -> k (f (V.as_array v))) - | DotE (exp1, x) when T.is_prim T.Text exp1.note.note_typ -> - let f = match x.it with - | "len" -> text_len - | "chars" -> text_chars - | _ -> assert false in - interpret_exp env exp1 (fun v -> k (f (V.as_text v))) - | DotE (exp1, x) when T.is_prim T.Text exp1.note.note_typ && x.it = "chars"-> - interpret_exp env exp1 (fun v -> k (text_chars (V.as_text v))) | DotE (exp1, id) -> interpret_exp env exp1 (fun v1 -> - let fs = V.as_obj v1 in - k (try find id.it fs with _ -> assert false) + match v1 with + | V.Obj fs -> + k (find id.it fs) + | V.Array vs -> + let f = match id.it with + | "len" -> array_len + | "get" -> array_get + | "set" -> array_set + | "keys" -> array_keys + | "vals" -> array_vals + | _ -> assert false + in k (f vs exp.at) + | V.Text s -> + let f = match id.it with + | "len" -> text_len + | "chars" -> text_chars + | _ -> assert false + in k (f s exp.at) + | _ -> assert false ) | AssignE (exp1, exp2) -> interpret_exp_mut env exp1 (fun v1 -> diff --git a/src/interpreter/interpret.mli b/src/interpreter/interpret.mli index 152a10f3737..b53864de020 100644 --- a/src/interpreter/interpret.mli +++ b/src/interpreter/interpret.mli @@ -2,15 +2,15 @@ open As_frontend module V = As_values.Value module T = As_types.Type -type flags = { - trace : bool; - print_depth : int -} +type flags = + { trace : bool; + print_depth : int + } -type scope = { - val_env: V.def V.Env.t; - lib_env: V.value V.Env.t; -} +type scope = + { val_env: V.def V.Env.t; + lib_env: V.value V.Env.t; + } val empty_scope : scope val adjoin_scope : scope -> scope -> scope From 14e8a58ea31cb582067db5c95cb5ba66d1711fd4 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Wed, 3 Jul 2019 11:04:15 -0600 Subject: [PATCH 0231/1176] force CI to try again --- stdlib/dummy | 1 + 1 file changed, 1 insertion(+) create mode 100644 stdlib/dummy diff --git a/stdlib/dummy b/stdlib/dummy new file mode 100644 index 00000000000..8f4bef751a6 --- /dev/null +++ b/stdlib/dummy @@ -0,0 +1 @@ +Wed Jul 3 11:03:58 MDT 2019 From 3445b2f7442032db6d58ad266fbb628ce2499afb Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Thu, 4 Jul 2019 09:49:49 +0200 Subject: [PATCH 0232/1176] AST-89 trapping pow for Int/Nat8/16/32 (#542) * use power magnitude estimation to decide whether we can carry out the operations in a machine word * fall back to next wider datatype when necessary * tests --- src/codegen/compile.ml | 147 +++++- test/run-dfinity/log-slow.as | 151 ++++++ test/run/numeric-ops.as | 65 ++- test/run/small-pow.lhs | 516 +++++++++++++++++++++ test/trap/ok/powInt32-lower.run-ir.ok | 1 + test/trap/ok/powInt32-lower.run-low.ok | 1 + test/trap/ok/powInt32-lower.run.ok | 1 + test/trap/ok/powInt32-lower.wasm-run.ok | 1 + test/trap/ok/powInt32-upper.run-ir.ok | 1 + test/trap/ok/powInt32-upper.run-low.ok | 1 + test/trap/ok/powInt32-upper.run.ok | 1 + test/trap/ok/powInt32-upper.wasm-run.ok | 1 + test/trap/ok/powInt8-lower.run-ir.ok | 1 + test/trap/ok/powInt8-lower.run-low.ok | 1 + test/trap/ok/powInt8-lower.run.ok | 1 + test/trap/ok/powInt8-lower.wasm-run.ok | 1 + test/trap/ok/powInt8-raise-neg.run-ir.ok | 1 + test/trap/ok/powInt8-raise-neg.run-low.ok | 1 + test/trap/ok/powInt8-raise-neg.run.ok | 1 + test/trap/ok/powInt8-raise-neg.wasm-run.ok | 1 + test/trap/ok/powInt8-upper.run-ir.ok | 1 + test/trap/ok/powInt8-upper.run-low.ok | 1 + test/trap/ok/powInt8-upper.run.ok | 1 + test/trap/ok/powInt8-upper.wasm-run.ok | 1 + test/trap/ok/powNat16.run-ir.ok | 1 + test/trap/ok/powNat16.run-low.ok | 1 + test/trap/ok/powNat16.run.ok | 1 + test/trap/ok/powNat16.wasm-run.ok | 1 + test/trap/ok/powNat32.run-ir.ok | 1 + test/trap/ok/powNat32.run-low.ok | 1 + test/trap/ok/powNat32.run.ok | 1 + test/trap/ok/powNat32.wasm-run.ok | 1 + test/trap/ok/powNat8.run-ir.ok | 1 + test/trap/ok/powNat8.run-low.ok | 1 + test/trap/ok/powNat8.run.ok | 1 + test/trap/ok/powNat8.wasm-run.ok | 1 + test/trap/powInt32-lower.as | 1 + test/trap/powInt32-upper.as | 1 + test/trap/powInt8-lower.as | 1 + test/trap/powInt8-raise-neg.as | 1 + test/trap/powInt8-upper.as | 1 + test/trap/powNat16.as | 1 + test/trap/powNat32.as | 1 + test/trap/powNat8.as | 1 + 44 files changed, 890 insertions(+), 29 deletions(-) create mode 100644 test/run-dfinity/log-slow.as create mode 100644 test/run/small-pow.lhs create mode 100644 test/trap/ok/powInt32-lower.run-ir.ok create mode 100644 test/trap/ok/powInt32-lower.run-low.ok create mode 100644 test/trap/ok/powInt32-lower.run.ok create mode 100644 test/trap/ok/powInt32-lower.wasm-run.ok create mode 100644 test/trap/ok/powInt32-upper.run-ir.ok create mode 100644 test/trap/ok/powInt32-upper.run-low.ok create mode 100644 test/trap/ok/powInt32-upper.run.ok create mode 100644 test/trap/ok/powInt32-upper.wasm-run.ok create mode 100644 test/trap/ok/powInt8-lower.run-ir.ok create mode 100644 test/trap/ok/powInt8-lower.run-low.ok create mode 100644 test/trap/ok/powInt8-lower.run.ok create mode 100644 test/trap/ok/powInt8-lower.wasm-run.ok create mode 100644 test/trap/ok/powInt8-raise-neg.run-ir.ok create mode 100644 test/trap/ok/powInt8-raise-neg.run-low.ok create mode 100644 test/trap/ok/powInt8-raise-neg.run.ok create mode 100644 test/trap/ok/powInt8-raise-neg.wasm-run.ok create mode 100644 test/trap/ok/powInt8-upper.run-ir.ok create mode 100644 test/trap/ok/powInt8-upper.run-low.ok create mode 100644 test/trap/ok/powInt8-upper.run.ok create mode 100644 test/trap/ok/powInt8-upper.wasm-run.ok create mode 100644 test/trap/ok/powNat16.run-ir.ok create mode 100644 test/trap/ok/powNat16.run-low.ok create mode 100644 test/trap/ok/powNat16.run.ok create mode 100644 test/trap/ok/powNat16.wasm-run.ok create mode 100644 test/trap/ok/powNat32.run-ir.ok create mode 100644 test/trap/ok/powNat32.run-low.ok create mode 100644 test/trap/ok/powNat32.run.ok create mode 100644 test/trap/ok/powNat32.wasm-run.ok create mode 100644 test/trap/ok/powNat8.run-ir.ok create mode 100644 test/trap/ok/powNat8.run-low.ok create mode 100644 test/trap/ok/powNat8.run.ok create mode 100644 test/trap/ok/powNat8.wasm-run.ok create mode 100644 test/trap/powInt32-lower.as create mode 100644 test/trap/powInt32-upper.as create mode 100644 test/trap/powInt8-lower.as create mode 100644 test/trap/powInt8-raise-neg.as create mode 100644 test/trap/powInt8-upper.as create mode 100644 test/trap/powNat16.as create mode 100644 test/trap/powNat32.as create mode 100644 test/trap/powNat8.as diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 44e61b62798..9e6c341a9b7 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -4568,6 +4568,20 @@ let compile_unop env t op = `compile_exp_as`, which does not take SR.Unreachable. *) todo "compile_unop" (Arrange_ops.unop op) (SR.Vanilla, E.trap_with env "TODO: compile_unop") +(* Logarithmic helpers for deciding whether we can carry out operations in constant bitwidth *) + +(* helper, measures the dynamics of the signed i32, returns (32 - effective bits) + expects two identical i32 copies on stack *) +let signed_dynamics = + compile_shl_const 1l ^^ + G.i (Binary (Wasm.Values.I32 I32Op.Xor)) ^^ + G.i (Unary (Wasm.Values.I32 I32Op.Clz)) + +(* helper, measures the dynamics of the unsigned i32, returns (32 - effective bits) + expects i32 on stack *) +let unsigned_dynamics = + G.i (Unary (Wasm.Values.I32 I32Op.Clz)) + (* Compiling Int/Nat64 ops by conversion to/from BigNum. This is currently consing a lot, but compact bignums will get back efficiency as soon as they are merged. *) @@ -4644,14 +4658,18 @@ let compile_Nat32_kernel env name op = (* Customisable kernels for 8/16bit arithmetic via 32 bits. *) (* helper, expects i32 on stack *) -let enforce_16_unsigned_bits env = - compile_bitand_const 0xFFFF0000l ^^ +let enforce_unsigned_bits env n = + compile_bitand_const Int32.(shift_left minus_one n) ^^ then_arithmetic_overflow env +let enforce_16_unsigned_bits env = enforce_unsigned_bits env 16 + (* helper, expects two identical i32s on stack *) -let enforce_16_signed_bits env = +let enforce_signed_bits env n = compile_shl_const 1l ^^ G.i (Binary (Wasm.Values.I32 I32Op.Xor)) ^^ - enforce_16_unsigned_bits env + enforce_unsigned_bits env n + +let enforce_16_signed_bits env = enforce_signed_bits env 16 let compile_smallInt_kernel' env ty name op = Func.share_code2 env (UnboxedSmallWord.name_of_type ty name) @@ -4774,6 +4792,127 @@ let rec compile_binop env t op = square_recurse_with_shifted (UnboxedSmallWord.sanitize_word_result ty) ^^ mul))) in pow () + | Type.(Prim ((Nat8|Nat16) as ty)), PowOp -> + Func.share_code2 env (UnboxedSmallWord.name_of_type ty "pow") + (("n", I32Type), ("exp", I32Type)) [I32Type] + (fun env get_n get_exp -> + let (set_res, get_res) = new_local env "res" in + let bits = UnboxedSmallWord.bits_of_type ty in + get_exp ^^ + G.if_ (ValBlockType (Some I32Type)) + begin + get_n ^^ compile_shrU_const Int32.(sub 33l (of_int bits)) ^^ + G.if_ (ValBlockType (Some I32Type)) + begin + get_n ^^ unsigned_dynamics ^^ compile_sub_const (Int32.of_int bits) ^^ + get_exp ^^ UnboxedSmallWord.lsb_adjust ty ^^ G.i (Binary (Wasm.Values.I32 I32Op.Mul)) ^^ + compile_unboxed_const (-30l) ^^ + G.i (Compare (Wasm.Values.I32 I32Op.LtS)) ^^ then_arithmetic_overflow env ^^ + get_n ^^ UnboxedSmallWord.lsb_adjust ty ^^ + get_exp ^^ UnboxedSmallWord.lsb_adjust ty ^^ + snd (compile_binop env Type.(Prim Word32) PowOp) ^^ + set_res ^^ get_res ^^ enforce_unsigned_bits env bits ^^ + get_res ^^ UnboxedSmallWord.msb_adjust ty + end + get_n (* n@{0,1} ** (1+exp) == n *) + end + (compile_unboxed_const + Int32.(shift_left one (to_int (UnboxedSmallWord.shift_of_type ty))))) (* x ** 0 == 1 *) + | Type.(Prim Nat32), PowOp -> + Func.share_code2 env (UnboxedSmallWord.name_of_type Type.Nat32 "pow") + (("n", I32Type), ("exp", I32Type)) [I32Type] + (fun env get_n get_exp -> + let (set_res, get_res) = new_local64 env "res" in + get_exp ^^ + G.if_ (ValBlockType (Some I32Type)) + begin + get_n ^^ compile_shrU_const 1l ^^ + G.if_ (ValBlockType (Some I32Type)) + begin + get_exp ^^ compile_unboxed_const 32l ^^ + G.i (Compare (Wasm.Values.I32 I32Op.GeU)) ^^ then_arithmetic_overflow env ^^ + get_n ^^ unsigned_dynamics ^^ compile_sub_const 32l ^^ + get_exp ^^ UnboxedSmallWord.lsb_adjust Type.Nat32 ^^ G.i (Binary (Wasm.Values.I32 I32Op.Mul)) ^^ + compile_unboxed_const (-62l) ^^ + G.i (Compare (Wasm.Values.I32 I32Op.LtS)) ^^ then_arithmetic_overflow env ^^ + get_n ^^ G.i (Convert (Wasm.Values.I64 I64Op.ExtendUI32)) ^^ + get_exp ^^ G.i (Convert (Wasm.Values.I64 I64Op.ExtendUI32)) ^^ + snd (compile_binop env Type.(Prim Word64) PowOp) ^^ + set_res ^^ get_res ^^ enforce_32_unsigned_bits env ^^ + get_res ^^ G.i (Convert (Wasm.Values.I32 I32Op.WrapI64)) + end + get_n (* n@{0,1} ** (1+exp) == n *) + end + compile_unboxed_one) (* x ** 0 == 1 *) + | Type.(Prim ((Int8|Int16) as ty)), PowOp -> + Func.share_code2 env (UnboxedSmallWord.name_of_type ty "pow") + (("n", I32Type), ("exp", I32Type)) [I32Type] + (fun env get_n get_exp -> + let (set_res, get_res) = new_local env "res" in + let bits = UnboxedSmallWord.bits_of_type ty in + get_exp ^^ compile_unboxed_zero ^^ + G.i (Compare (Wasm.Values.I32 I32Op.LtS)) ^^ E.then_trap_with env "negative power" ^^ + get_exp ^^ + G.if_ (ValBlockType (Some I32Type)) + begin + get_n ^^ compile_shrS_const Int32.(sub 33l (of_int bits)) ^^ + G.if_ (ValBlockType (Some I32Type)) + begin + get_n ^^ get_n ^^ signed_dynamics ^^ compile_sub_const (Int32.of_int (bits - 1)) ^^ + get_exp ^^ UnboxedSmallWord.lsb_adjust ty ^^ G.i (Binary (Wasm.Values.I32 I32Op.Mul)) ^^ + compile_unboxed_const (-30l) ^^ + G.i (Compare (Wasm.Values.I32 I32Op.LtS)) ^^ then_arithmetic_overflow env ^^ + get_n ^^ UnboxedSmallWord.lsb_adjust ty ^^ + get_exp ^^ UnboxedSmallWord.lsb_adjust ty ^^ + snd (compile_binop env Type.(Prim Word32) PowOp) ^^ + set_res ^^ get_res ^^ get_res ^^ enforce_signed_bits env bits ^^ + get_res ^^ UnboxedSmallWord.msb_adjust ty + end + get_n (* n@{0,1} ** (1+exp) == n *) + end + (compile_unboxed_const + Int32.(shift_left one (to_int (UnboxedSmallWord.shift_of_type ty))))) (* x ** 0 == 1 *) + | Type.(Prim Int32), PowOp -> + Func.share_code2 env (UnboxedSmallWord.name_of_type Type.Int32 "pow") + (("n", I32Type), ("exp", I32Type)) [I32Type] + (fun env get_n get_exp -> + let (set_res, get_res) = new_local64 env "res" in + get_exp ^^ compile_unboxed_zero ^^ + G.i (Compare (Wasm.Values.I32 I32Op.LtS)) ^^ E.then_trap_with env "negative power" ^^ + get_exp ^^ + G.if_ (ValBlockType (Some I32Type)) + begin + get_n ^^ compile_unboxed_one ^^ G.i (Compare (Wasm.Values.I32 I32Op.LeS)) ^^ + get_n ^^ compile_unboxed_const (-1l) ^^ G.i (Compare (Wasm.Values.I32 I32Op.GeS)) ^^ + G.i (Binary (Wasm.Values.I32 I32Op.And)) ^^ + G.if_ (ValBlockType (Some I32Type)) + begin + get_n ^^ compile_unboxed_zero ^^ G.i (Compare (Wasm.Values.I32 I32Op.LtS)) ^^ + G.if_ (ValBlockType (Some I32Type)) + begin + (* -1 ** (1+exp) == if even (1+exp) then 1 else -1 *) + get_exp ^^ compile_unboxed_one ^^ G.i (Binary (Wasm.Values.I32 I32Op.And)) ^^ + G.if_ (ValBlockType (Some I32Type)) + get_n + compile_unboxed_one + end + get_n (* n@{0,1} ** (1+exp) == n *) + end + begin + get_exp ^^ compile_unboxed_const 32l ^^ + G.i (Compare (Wasm.Values.I32 I32Op.GeU)) ^^ then_arithmetic_overflow env ^^ + get_n ^^ get_n ^^ signed_dynamics ^^ compile_sub_const 31l ^^ + get_exp ^^ UnboxedSmallWord.lsb_adjust Type.Int32 ^^ G.i (Binary (Wasm.Values.I32 I32Op.Mul)) ^^ + compile_unboxed_const (-62l) ^^ + G.i (Compare (Wasm.Values.I32 I32Op.LtS)) ^^ then_arithmetic_overflow env ^^ + get_n ^^ G.i (Convert (Wasm.Values.I64 I64Op.ExtendSI32)) ^^ + get_exp ^^ G.i (Convert (Wasm.Values.I64 I64Op.ExtendSI32)) ^^ + snd (compile_binop env Type.(Prim Word64) PowOp) ^^ + set_res ^^ get_res ^^ get_res ^^ enforce_32_signed_bits env ^^ + get_res ^^ G.i (Convert (Wasm.Values.I32 I32Op.WrapI64)) + end + end + compile_unboxed_one) (* x ** 0 == 1 *) | Type.(Prim Int), PowOp -> let pow = BigNum.compile_unsigned_pow env in let (set_n, get_n) = new_local env "n" in diff --git a/test/run-dfinity/log-slow.as b/test/run-dfinity/log-slow.as new file mode 100644 index 00000000000..3ec81b4e5ed --- /dev/null +++ b/test/run-dfinity/log-slow.as @@ -0,0 +1,151 @@ +// These are rather lon-running tests, not advisable for wasm-run! + +// Nat* + +for (n in range(0, 255)) { + for (exp in range(0, 255)) { + if (n <= 1 or exp <= 1 or (n <= 16 and exp <= 9)) { + let res = n ** exp; + if (res <= 255) { assert (natToNat8 n ** natToNat8 exp == natToNat8 res) } + } + } +}; + +assert (natToNat8 2 ** natToNat8 7 == natToNat8 128); // highest exponent + +for (n in range(0, 255)) { + for (exp in range(0, 255)) { + if (n <= 1 or exp <= 1 or (n <= 16 and exp <= 9)) { // see #537 + let res = n ** exp; + if (res <= 255) { assert (natToNat8 n ** natToNat8 exp == natToNat8 res) } + } + } +}; + + +assert (natToNat16 2 ** natToNat16 15 == natToNat16 32768); // highest exponent + +for (n in range(0, 255)) { + for (exp in range(0, 255)) { + if (n <= 1 or exp <= 106) { // see #537 + let res = n ** exp; + if (res <= 65535) { assert (natToNat16 n ** natToNat16 exp == natToNat16 res) } + } + } +}; + + +assert (natToNat32 2 ** natToNat32 31 == natToNat32 2_147_483_648); // highest exponent + +for (n in range(0, 255)) { + for (exp in range(0, 255)) { + if (n <= 1 or exp <= 106) { // see #537 + let res = n ** exp; + if (res <= 65535) { assert (natToNat32 n ** natToNat32 exp == natToNat32 res) } + } + } +}; + + +// Int* + +assert (intToInt8 2 ** intToInt8 6 == intToInt8 64); // highest exponent + +for (n in range(0, 127)) { + for (exp in range(0, 127)) { + if (n <= 1 or exp <= 1 or (n <= 16 and exp <= 9)) { + let res = n ** exp; + if (res <= 127) { assert (intToInt8 n ** intToInt8 exp == intToInt8 res) } + } + } +}; + + +assert (intToInt8 (-2) ** intToInt8 7 == intToInt8 (-128)); // highest exponent + +{ +var n = -128; +while (n < -1) { + for (exp in range(0, 127)) { + if (n == -1 or exp <= 1 or (n >= -17 and exp <= 9)) { + let res = n ** exp; + if (res >= -128 and res <= 127) { + assert (intToInt8 n ** intToInt8 exp == intToInt8 res) + } + } + }; + n += 1 +} +}; + + + +assert (intToInt16 2 ** intToInt16 14 == intToInt16 16384); // highest exponent + +for (n in range(0, 127)) { + for (exp in range(0, 127)) { + if (n <= 1 or exp <= 1 or exp <= 14) { + let res = n ** exp; + if (res <= 32767) { assert (intToInt16 n ** intToInt16 exp == intToInt16 res) } + } + } +}; + + +assert (intToInt16 (-2) ** intToInt16 15 == intToInt16 (-32768)); // highest exponent + +{ +var n = -128; +while (n < -1) { + for (exp in range(0, 127)) { + if (n == -1 or exp <= 1 or exp <= 15) { + let res = n ** exp; + if (res >= -32768 and res <= 32767) { + assert (intToInt16 n ** intToInt16 exp == intToInt16 res) + } + } + }; + n += 1 +} +}; + +assert (intToInt32 3 ** intToInt32 19 == intToInt32 1_162_261_467); +assert (intToInt32 2 ** intToInt32 30 == intToInt32 1_073_741_824); // highest exponent +assert (intToInt32 (-2) ** intToInt32 31 == intToInt32 (-2_147_483_648)); // highest exponent +assert (intToInt32 (-3) ** intToInt32 19 == intToInt32 (-1_162_261_467)); + +assert (intToInt32 1 ** intToInt32 19 == intToInt32 1); +assert (intToInt32 1 ** intToInt32 100 == intToInt32 1); +assert (intToInt32 1 ** intToInt32 101 == intToInt32 1); + +assert (intToInt32 0 ** intToInt32 19 == intToInt32 0); +assert (intToInt32 0 ** intToInt32 100 == intToInt32 0); +assert (intToInt32 0 ** intToInt32 101 == intToInt32 0); + +assert (intToInt32 (-1) ** intToInt32 19 == intToInt32 (-1)); +assert (intToInt32 (-1) ** intToInt32 100 == intToInt32 1); +assert (intToInt32 (-1) ** intToInt32 101 == intToInt32 (-1)); + +for (n in range(0, 127)) { + for (exp in range(0, 127)) { + if (n <= 1 or exp <= 1 or exp <= 30) { + let res = n ** exp; + if (res <= 2_147_483_647) { assert (intToInt32 n ** intToInt32 exp == intToInt32 res) } + } + } +}; + +{ +var n = -128; +while (n < -1) { + for (exp in range(0, 127)) { + if (n == -1 or exp <= 1 or exp <= 31) { + let res = n ** exp; + if (res >= -2_147_483_648 and res <= 2_147_483_647) { + assert (intToInt32 n ** intToInt32 exp == intToInt32 res) + } + } + }; + n += 1 +} +}; diff --git a/test/run/numeric-ops.as b/test/run/numeric-ops.as index c45a72839cd..719d36b673e 100644 --- a/test/run/numeric-ops.as +++ b/test/run/numeric-ops.as @@ -262,18 +262,25 @@ func testInt32(a : Int32, b : Int32) : [Int32] { let rat2 = (a / b) : Int32; let mod1 = a % b; let mod2 = (a % b) : Int32; - /*let pow1 = a ** b; - let pow2 = (a ** b) : Int32;*/ - [pos1, pos2, neg1, neg2, sum1, sum2, diff1, diff2, prod1, prod2, rat1, rat2, mod1, mod2/*, pow1, pow2*/] + if (b >= (0 : Int32)) + { + let pow1 = a ** b; + let pow2 = (a ** b) : Int32; + [pos1, pos2, neg1, neg2, sum1, sum2, diff1, diff2, prod1, prod2, rat1, rat2, mod1, mod2, pow1, pow2] + } + else + { + [pos1, pos2, neg1, neg2, sum1, sum2, diff1, diff2, prod1, prod2, rat1, rat2, mod1, mod2] + } }; func int32Compare(a : Int32, b : Int32) : Bool = a == b; -verify([3, -3, 8, -2, 15, 0, 3/*, 243*/], testInt32(3, 5), +verify([3, -3, 8, -2, 15, 0, 3, 243], testInt32(3, 5), int32Compare); -verify([13, -13, 18, 8, 65, 2, 3/*, 243*/], testInt32(13, 5), +verify([13, -13, 18, 8, 65, 2, 3, 371293], testInt32(13, 5), int32Compare); -verify([-13, 13, -18, -8, 65, 2, -3/*, 243*/], testInt32(-13, -5), +verify([-13, 13, -18, -8, 65, 2, -3], testInt32(-13, -5), int32Compare); @@ -292,18 +299,20 @@ func testInt16(a : Int16, b : Int16) : [Int16] { let rat2 = (a / b) : Int16; let mod1 = a % b; let mod2 = (a % b) : Int16; - /*let pow1 = a ** b; - let pow2 = (a ** b) : Int16;*/ - [pos1, pos2, neg1, neg2, sum1, sum2, diff1, diff2, prod1, prod2, rat1, rat2, mod1, mod2/*, pow1, pow2*/] + if (b >= (0 : Int16) and a < (10 : Int16)) { + let pow1 = a ** b; + let pow2 = (a ** b) : Int16; + [pos1, pos2, neg1, neg2, sum1, sum2, diff1, diff2, prod1, prod2, rat1, rat2, mod1, mod2, pow1, pow2] + } else { [pos1, pos2, neg1, neg2, sum1, sum2, diff1, diff2, prod1, prod2, rat1, rat2, mod1, mod2] } }; func int16Compare(a : Int16, b : Int16) : Bool = a == b; -verify([3, -3, 8, -2, 15, 0, 3/*, 243*/], testInt16(3, 5), +verify([3, -3, 8, -2, 15, 0, 3, 243], testInt16(3, 5), int16Compare); -verify([13, -13, 18, 8, 65, 2, 3/*, 243*/], testInt16(13, 5), +verify([13, -13, 18, 8, 65, 2, 3], testInt16(13, 5), int16Compare); -verify([-13, 13, -18, -8, 65, 2, -3/*, 243*/], testInt16(-13, -5), +verify([-13, 13, -18, -8, 65, 2, -3], testInt16(-13, -5), int16Compare); @@ -322,22 +331,26 @@ func testInt8(a : Int8, b : Int8) : [Int8] { let rat2 = (a / b) : Int8; let mod1 = a % b; let mod2 = (a % b) : Int8; - /*let pow1 = a ** b; - let pow2 = (a ** b) : Int8;*/ - [pos1, pos2, neg1, neg2, sum1, sum2, diff1, diff2, prod1, prod2, rat1, rat2, mod1, mod2, /*pow1, pow2*/] + if (b >= (0 : Int8) and b < (5 : Int8)) { + let pow1 = a ** b; + let pow2 = (a ** b) : Int8; + [pos1, pos2, neg1, neg2, sum1, sum2, diff1, diff2, prod1, prod2, rat1, rat2, mod1, mod2, pow1, pow2] + } else { [pos1, pos2, neg1, neg2, sum1, sum2, diff1, diff2, prod1, prod2, rat1, rat2, mod1, mod2] } }; func int8Compare(a : Int8, b : Int8) : Bool = a == b; -verify([3, -3, 8, -2, 15, 0, 3/*, 243*/], testInt8(3, 5), +verify([3, -3, 7, -1, 12, 0, 3, 81], testInt8(3, 4), int8Compare); -verify([13, -13, 18, 8, 65, 2, 3/*, 243*/], testInt8(13, 5), +verify([3, -3, 8, -2, 15, 0, 3], testInt8(3, 5), int8Compare); -verify([3, -3, -2, 8, -15, 0, 3/*, 243*/], testInt8(3, -5), +verify([13, -13, 18, 8, 65, 2, 3], testInt8(13, 5), int8Compare); -verify([13, -13, 8, 18, -65, -2, 3/*, 243*/], testInt8(13, -5), +verify([3, -3, -2, 8, -15, 0, 3], testInt8(3, -5), int8Compare); -verify([-13, 13, -18, -8, 65, 2, -3/*, 243*/], testInt8(-13, -5), +verify([13, -13, 8, 18, -65, -2, 3], testInt8(13, -5), + int8Compare); +verify([-13, 13, -18, -8, 65, 2, -3], testInt8(-13, -5), int8Compare); @@ -424,14 +437,16 @@ func testNat8(a : Nat8, b : Nat8) : [Nat8] { let rat2 = (a / b) : Nat8; let mod1 = a % b; let mod2 = (a % b) : Nat8; - /*let pow1 = a ** b; - let pow2 = (a ** b) : Nat8;*/ - [sum1, sum2, diff1, diff2, prod1, prod2, rat1, rat2, mod1, mod2/*, pow1, pow2*/] + if (b >= (0 : Nat8) and a < (10 : Nat8)) { + let pow1 = a ** b; + let pow2 = (a ** b) : Nat8; + [sum1, sum2, diff1, diff2, prod1, prod2, rat1, rat2, mod1, mod2, pow1, pow2] + } else { [sum1, sum2, diff1, diff2, prod1, prod2, rat1, rat2, mod1, mod2] } }; func nat8Compare(a : Nat8, b : Nat8) : Bool = a == b; -verify([8, 2, 15, 1, 2/*, 243*/], testNat8(5, 3), +verify([8, 2, 15, 1, 2, 125], testNat8(5, 3), nat8Compare); -verify([18, 12, 45, 5, 0/*, 243*/], testNat8(15, 3), +verify([18, 12, 45, 5, 0], testNat8(15, 3), nat8Compare); diff --git a/test/run/small-pow.lhs b/test/run/small-pow.lhs new file mode 100644 index 00000000000..8d0af321938 --- /dev/null +++ b/test/run/small-pow.lhs @@ -0,0 +1,516 @@ +/* +This can be read as literate Haskell (temporarily `ln ../test/run/small-pow.as ../test/run/small-pow.lhs`) + +> import Data.Bits +> import Data.Word +> +> effbits :: FiniteBits a => a -> Int +> effbits a = finiteBitSize a - countLeadingZeros (a `xor` (a `shiftL` 1)) +> +> extremal :: FiniteBits a => Int -> [a] +> extremal 0 = [zeroBits] +> extremal 1 = [complement zeroBits] +> extremal n = [complement zeroBits `shiftL` pred n, let max = complement zeroBits `shiftR` (finiteBitSize max - pred n) in max] +> +> asBigNum :: (Integral a, FiniteBits a) => a -> Integer +> asBigNum a | a `testBit` 63 = - fromIntegral (complement a) - 1 +> asBigNum a = fromIntegral a +> +> showBig = show . asBigNum +> +> main = sequence_ [ putStrLn ("assert (" ++ showBig n ++ " ** " ++ show e ++ " == " ++ show n' ++ ");") +> | b <- [0 .. 31], e <- [0 .. 31], b * e <= 65, n <- extremal b :: [Word64] +> , let n' = asBigNum n ^ fromIntegral e ] + +*/ + +assert (0 ** 0 == 1); +assert (0 ** 1 == 0); +assert (0 ** 2 == 0); +assert (0 ** 3 == 0); +assert (0 ** 4 == 0); +assert (0 ** 5 == 0); +assert (0 ** 6 == 0); +assert (0 ** 7 == 0); +assert (0 ** 8 == 0); +assert (0 ** 9 == 0); +assert (0 ** 10 == 0); +assert (0 ** 11 == 0); +assert (0 ** 12 == 0); +assert (0 ** 13 == 0); +assert (0 ** 14 == 0); +assert (0 ** 15 == 0); +assert (0 ** 16 == 0); +assert (0 ** 17 == 0); +assert (0 ** 18 == 0); +assert (0 ** 19 == 0); +assert (0 ** 20 == 0); +assert (0 ** 21 == 0); +assert (0 ** 22 == 0); +assert (0 ** 23 == 0); +assert (0 ** 24 == 0); +assert (0 ** 25 == 0); +assert (0 ** 26 == 0); +assert (0 ** 27 == 0); +assert (0 ** 28 == 0); +assert (0 ** 29 == 0); +assert (0 ** 30 == 0); +assert (0 ** 31 == 0); +assert (-1 ** 0 == 1); +assert (-1 ** 1 == -1); +assert (-1 ** 2 == 1); +assert (-1 ** 3 == -1); +assert (-1 ** 4 == 1); +assert (-1 ** 5 == -1); +assert (-1 ** 6 == 1); +assert (-1 ** 7 == -1); +assert (-1 ** 8 == 1); +assert (-1 ** 9 == -1); +assert (-1 ** 10 == 1); +assert (-1 ** 11 == -1); +assert (-1 ** 12 == 1); +assert (-1 ** 13 == -1); +assert (-1 ** 14 == 1); +assert (-1 ** 15 == -1); +assert (-1 ** 16 == 1); +assert (-1 ** 17 == -1); +assert (-1 ** 18 == 1); +assert (-1 ** 19 == -1); +assert (-1 ** 20 == 1); +assert (-1 ** 21 == -1); +assert (-1 ** 22 == 1); +assert (-1 ** 23 == -1); +assert (-1 ** 24 == 1); +assert (-1 ** 25 == -1); +assert (-1 ** 26 == 1); +assert (-1 ** 27 == -1); +assert (-1 ** 28 == 1); +assert (-1 ** 29 == -1); +assert (-1 ** 30 == 1); +assert (-1 ** 31 == -1); +assert (-2 ** 0 == 1); +assert (1 ** 0 == 1); +assert (-2 ** 1 == -2); +assert (1 ** 1 == 1); +assert (-2 ** 2 == 4); +assert (1 ** 2 == 1); +assert (-2 ** 3 == -8); +assert (1 ** 3 == 1); +assert (-2 ** 4 == 16); +assert (1 ** 4 == 1); +assert (-2 ** 5 == -32); +assert (1 ** 5 == 1); +assert (-2 ** 6 == 64); +assert (1 ** 6 == 1); +assert (-2 ** 7 == -128); +assert (1 ** 7 == 1); +assert (-2 ** 8 == 256); +assert (1 ** 8 == 1); +assert (-2 ** 9 == -512); +assert (1 ** 9 == 1); +assert (-2 ** 10 == 1024); +assert (1 ** 10 == 1); +assert (-2 ** 11 == -2048); +assert (1 ** 11 == 1); +assert (-2 ** 12 == 4096); +assert (1 ** 12 == 1); +assert (-2 ** 13 == -8192); +assert (1 ** 13 == 1); +assert (-2 ** 14 == 16384); +assert (1 ** 14 == 1); +assert (-2 ** 15 == -32768); +assert (1 ** 15 == 1); +assert (-2 ** 16 == 65536); +assert (1 ** 16 == 1); +assert (-2 ** 17 == -131072); +assert (1 ** 17 == 1); +assert (-2 ** 18 == 262144); +assert (1 ** 18 == 1); +assert (-2 ** 19 == -524288); +assert (1 ** 19 == 1); +assert (-2 ** 20 == 1048576); +assert (1 ** 20 == 1); +assert (-2 ** 21 == -2097152); +assert (1 ** 21 == 1); +assert (-2 ** 22 == 4194304); +assert (1 ** 22 == 1); +assert (-2 ** 23 == -8388608); +assert (1 ** 23 == 1); +assert (-2 ** 24 == 16777216); +assert (1 ** 24 == 1); +assert (-2 ** 25 == -33554432); +assert (1 ** 25 == 1); +assert (-2 ** 26 == 67108864); +assert (1 ** 26 == 1); +assert (-2 ** 27 == -134217728); +assert (1 ** 27 == 1); +assert (-2 ** 28 == 268435456); +assert (1 ** 28 == 1); +assert (-2 ** 29 == -536870912); +assert (1 ** 29 == 1); +assert (-2 ** 30 == 1073741824); +assert (1 ** 30 == 1); +assert (-2 ** 31 == -2147483648); +assert (1 ** 31 == 1); +assert (-4 ** 0 == 1); +assert (3 ** 0 == 1); +assert (-4 ** 1 == -4); +assert (3 ** 1 == 3); +assert (-4 ** 2 == 16); +assert (3 ** 2 == 9); +assert (-4 ** 3 == -64); +assert (3 ** 3 == 27); +assert (-4 ** 4 == 256); +assert (3 ** 4 == 81); +assert (-4 ** 5 == -1024); +assert (3 ** 5 == 243); +assert (-4 ** 6 == 4096); +assert (3 ** 6 == 729); +assert (-4 ** 7 == -16384); +assert (3 ** 7 == 2187); +assert (-4 ** 8 == 65536); +assert (3 ** 8 == 6561); +assert (-4 ** 9 == -262144); +assert (3 ** 9 == 19683); +assert (-4 ** 10 == 1048576); +assert (3 ** 10 == 59049); +assert (-4 ** 11 == -4194304); +assert (3 ** 11 == 177147); +assert (-4 ** 12 == 16777216); +assert (3 ** 12 == 531441); +assert (-4 ** 13 == -67108864); +assert (3 ** 13 == 1594323); +assert (-4 ** 14 == 268435456); +assert (3 ** 14 == 4782969); +assert (-4 ** 15 == -1073741824); +assert (3 ** 15 == 14348907); +assert (-4 ** 16 == 4294967296); +assert (3 ** 16 == 43046721); +assert (-4 ** 17 == -17179869184); +assert (3 ** 17 == 129140163); +assert (-4 ** 18 == 68719476736); +assert (3 ** 18 == 387420489); +assert (-4 ** 19 == -274877906944); +assert (3 ** 19 == 1162261467); +assert (-4 ** 20 == 1099511627776); +assert (3 ** 20 == 3486784401); +assert (-4 ** 21 == -4398046511104); +assert (3 ** 21 == 10460353203); +assert (-8 ** 0 == 1); +assert (7 ** 0 == 1); +assert (-8 ** 1 == -8); +assert (7 ** 1 == 7); +assert (-8 ** 2 == 64); +assert (7 ** 2 == 49); +assert (-8 ** 3 == -512); +assert (7 ** 3 == 343); +assert (-8 ** 4 == 4096); +assert (7 ** 4 == 2401); +assert (-8 ** 5 == -32768); +assert (7 ** 5 == 16807); +assert (-8 ** 6 == 262144); +assert (7 ** 6 == 117649); +assert (-8 ** 7 == -2097152); +assert (7 ** 7 == 823543); +assert (-8 ** 8 == 16777216); +assert (7 ** 8 == 5764801); +assert (-8 ** 9 == -134217728); +assert (7 ** 9 == 40353607); +assert (-8 ** 10 == 1073741824); +assert (7 ** 10 == 282475249); +assert (-8 ** 11 == -8589934592); +assert (7 ** 11 == 1977326743); +assert (-8 ** 12 == 68719476736); +assert (7 ** 12 == 13841287201); +assert (-8 ** 13 == -549755813888); +assert (7 ** 13 == 96889010407); +assert (-8 ** 14 == 4398046511104); +assert (7 ** 14 == 678223072849); +assert (-8 ** 15 == -35184372088832); +assert (7 ** 15 == 4747561509943); +assert (-8 ** 16 == 281474976710656); +assert (7 ** 16 == 33232930569601); +assert (-16 ** 0 == 1); +assert (15 ** 0 == 1); +assert (-16 ** 1 == -16); +assert (15 ** 1 == 15); +assert (-16 ** 2 == 256); +assert (15 ** 2 == 225); +assert (-16 ** 3 == -4096); +assert (15 ** 3 == 3375); +assert (-16 ** 4 == 65536); +assert (15 ** 4 == 50625); +assert (-16 ** 5 == -1048576); +assert (15 ** 5 == 759375); +assert (-16 ** 6 == 16777216); +assert (15 ** 6 == 11390625); +assert (-16 ** 7 == -268435456); +assert (15 ** 7 == 170859375); +assert (-16 ** 8 == 4294967296); +assert (15 ** 8 == 2562890625); +assert (-16 ** 9 == -68719476736); +assert (15 ** 9 == 38443359375); +assert (-16 ** 10 == 1099511627776); +assert (15 ** 10 == 576650390625); +assert (-16 ** 11 == -17592186044416); +assert (15 ** 11 == 8649755859375); +assert (-16 ** 12 == 281474976710656); +assert (15 ** 12 == 129746337890625); +assert (-16 ** 13 == -4503599627370496); +assert (15 ** 13 == 1946195068359375); +assert (-32 ** 0 == 1); +assert (31 ** 0 == 1); +assert (-32 ** 1 == -32); +assert (31 ** 1 == 31); +assert (-32 ** 2 == 1024); +assert (31 ** 2 == 961); +assert (-32 ** 3 == -32768); +assert (31 ** 3 == 29791); +assert (-32 ** 4 == 1048576); +assert (31 ** 4 == 923521); +assert (-32 ** 5 == -33554432); +assert (31 ** 5 == 28629151); +assert (-32 ** 6 == 1073741824); +assert (31 ** 6 == 887503681); +assert (-32 ** 7 == -34359738368); +assert (31 ** 7 == 27512614111); +assert (-32 ** 8 == 1099511627776); +assert (31 ** 8 == 852891037441); +assert (-32 ** 9 == -35184372088832); +assert (31 ** 9 == 26439622160671); +assert (-32 ** 10 == 1125899906842624); +assert (31 ** 10 == 819628286980801); +assert (-64 ** 0 == 1); +assert (63 ** 0 == 1); +assert (-64 ** 1 == -64); +assert (63 ** 1 == 63); +assert (-64 ** 2 == 4096); +assert (63 ** 2 == 3969); +assert (-64 ** 3 == -262144); +assert (63 ** 3 == 250047); +assert (-64 ** 4 == 16777216); +assert (63 ** 4 == 15752961); +assert (-64 ** 5 == -1073741824); +assert (63 ** 5 == 992436543); +assert (-64 ** 6 == 68719476736); +assert (63 ** 6 == 62523502209); +assert (-64 ** 7 == -4398046511104); +assert (63 ** 7 == 3938980639167); +assert (-64 ** 8 == 281474976710656); +assert (63 ** 8 == 248155780267521); +assert (-64 ** 9 == -18014398509481984); +assert (63 ** 9 == 15633814156853823); +assert (-128 ** 0 == 1); +assert (127 ** 0 == 1); +assert (-128 ** 1 == -128); +assert (127 ** 1 == 127); +assert (-128 ** 2 == 16384); +assert (127 ** 2 == 16129); +assert (-128 ** 3 == -2097152); +assert (127 ** 3 == 2048383); +assert (-128 ** 4 == 268435456); +assert (127 ** 4 == 260144641); +assert (-128 ** 5 == -34359738368); +assert (127 ** 5 == 33038369407); +assert (-128 ** 6 == 4398046511104); +assert (127 ** 6 == 4195872914689); +assert (-128 ** 7 == -562949953421312); +assert (127 ** 7 == 532875860165503); +assert (-128 ** 8 == 72057594037927936); +assert (127 ** 8 == 67675234241018881); +assert (-256 ** 0 == 1); +assert (255 ** 0 == 1); +assert (-256 ** 1 == -256); +assert (255 ** 1 == 255); +assert (-256 ** 2 == 65536); +assert (255 ** 2 == 65025); +assert (-256 ** 3 == -16777216); +assert (255 ** 3 == 16581375); +assert (-256 ** 4 == 4294967296); +assert (255 ** 4 == 4228250625); +assert (-256 ** 5 == -1099511627776); +assert (255 ** 5 == 1078203909375); +assert (-256 ** 6 == 281474976710656); +assert (255 ** 6 == 274941996890625); +assert (-256 ** 7 == -72057594037927936); +assert (255 ** 7 == 70110209207109375); +assert (-512 ** 0 == 1); +assert (511 ** 0 == 1); +assert (-512 ** 1 == -512); +assert (511 ** 1 == 511); +assert (-512 ** 2 == 262144); +assert (511 ** 2 == 261121); +assert (-512 ** 3 == -134217728); +assert (511 ** 3 == 133432831); +assert (-512 ** 4 == 68719476736); +assert (511 ** 4 == 68184176641); +assert (-512 ** 5 == -35184372088832); +assert (511 ** 5 == 34842114263551); +assert (-512 ** 6 == 18014398509481984); +assert (511 ** 6 == 17804320388674561); +assert (-1024 ** 0 == 1); +assert (1023 ** 0 == 1); +assert (-1024 ** 1 == -1024); +assert (1023 ** 1 == 1023); +assert (-1024 ** 2 == 1048576); +assert (1023 ** 2 == 1046529); +assert (-1024 ** 3 == -1073741824); +assert (1023 ** 3 == 1070599167); +assert (-1024 ** 4 == 1099511627776); +assert (1023 ** 4 == 1095222947841); +assert (-1024 ** 5 == -1125899906842624); +assert (1023 ** 5 == 1120413075641343); +assert (-2048 ** 0 == 1); +assert (2047 ** 0 == 1); +assert (-2048 ** 1 == -2048); +assert (2047 ** 1 == 2047); +assert (-2048 ** 2 == 4194304); +assert (2047 ** 2 == 4190209); +assert (-2048 ** 3 == -8589934592); +assert (2047 ** 3 == 8577357823); +assert (-2048 ** 4 == 17592186044416); +assert (2047 ** 4 == 17557851463681); +assert (-2048 ** 5 == -36028797018963968); +assert (2047 ** 5 == 35940921946155007); +assert (-4096 ** 0 == 1); +assert (4095 ** 0 == 1); +assert (-4096 ** 1 == -4096); +assert (4095 ** 1 == 4095); +assert (-4096 ** 2 == 16777216); +assert (4095 ** 2 == 16769025); +assert (-4096 ** 3 == -68719476736); +assert (4095 ** 3 == 68669157375); +assert (-4096 ** 4 == 281474976710656); +assert (4095 ** 4 == 281200199450625); +assert (-4096 ** 5 == -1152921504606846976); +assert (4095 ** 5 == 1151514816750309375); +assert (-8192 ** 0 == 1); +assert (8191 ** 0 == 1); +assert (-8192 ** 1 == -8192); +assert (8191 ** 1 == 8191); +assert (-8192 ** 2 == 67108864); +assert (8191 ** 2 == 67092481); +assert (-8192 ** 3 == -549755813888); +assert (8191 ** 3 == 549554511871); +assert (-8192 ** 4 == 4503599627370496); +assert (8191 ** 4 == 4501401006735361); +assert (-16384 ** 0 == 1); +assert (16383 ** 0 == 1); +assert (-16384 ** 1 == -16384); +assert (16383 ** 1 == 16383); +assert (-16384 ** 2 == 268435456); +assert (16383 ** 2 == 268402689); +assert (-16384 ** 3 == -4398046511104); +assert (16383 ** 3 == 4397241253887); +assert (-16384 ** 4 == 72057594037927936); +assert (16383 ** 4 == 72040003462430721); +assert (-32768 ** 0 == 1); +assert (32767 ** 0 == 1); +assert (-32768 ** 1 == -32768); +assert (32767 ** 1 == 32767); +assert (-32768 ** 2 == 1073741824); +assert (32767 ** 2 == 1073676289); +assert (-32768 ** 3 == -35184372088832); +assert (32767 ** 3 == 35181150961663); +assert (-32768 ** 4 == 1152921504606846976); +assert (32767 ** 4 == 1152780773560811521); +assert (-65536 ** 0 == 1); +assert (65535 ** 0 == 1); +assert (-65536 ** 1 == -65536); +assert (65535 ** 1 == 65535); +assert (-65536 ** 2 == 4294967296); +assert (65535 ** 2 == 4294836225); +assert (-65536 ** 3 == -281474976710656); +assert (65535 ** 3 == 281462092005375); +assert (-131072 ** 0 == 1); +assert (131071 ** 0 == 1); +assert (-131072 ** 1 == -131072); +assert (131071 ** 1 == 131071); +assert (-131072 ** 2 == 17179869184); +assert (131071 ** 2 == 17179607041); +assert (-131072 ** 3 == -2251799813685248); +assert (131071 ** 3 == 2251748274470911); +assert (-262144 ** 0 == 1); +assert (262143 ** 0 == 1); +assert (-262144 ** 1 == -262144); +assert (262143 ** 1 == 262143); +assert (-262144 ** 2 == 68719476736); +assert (262143 ** 2 == 68718952449); +assert (-262144 ** 3 == -18014398509481984); +assert (262143 ** 3 == 18014192351838207); +assert (-524288 ** 0 == 1); +assert (524287 ** 0 == 1); +assert (-524288 ** 1 == -524288); +assert (524287 ** 1 == 524287); +assert (-524288 ** 2 == 274877906944); +assert (524287 ** 2 == 274876858369); +assert (-524288 ** 3 == -144115188075855872); +assert (524287 ** 3 == 144114363443707903); +assert (-1048576 ** 0 == 1); +assert (1048575 ** 0 == 1); +assert (-1048576 ** 1 == -1048576); +assert (1048575 ** 1 == 1048575); +assert (-1048576 ** 2 == 1099511627776); +assert (1048575 ** 2 == 1099509530625); +assert (-1048576 ** 3 == -1152921504606846976); +assert (1048575 ** 3 == 1152918206075109375); +assert (-2097152 ** 0 == 1); +assert (2097151 ** 0 == 1); +assert (-2097152 ** 1 == -2097152); +assert (2097151 ** 1 == 2097151); +assert (-2097152 ** 2 == 4398046511104); +assert (2097151 ** 2 == 4398042316801); +assert (-4194304 ** 0 == 1); +assert (4194303 ** 0 == 1); +assert (-4194304 ** 1 == -4194304); +assert (4194303 ** 1 == 4194303); +assert (-4194304 ** 2 == 17592186044416); +assert (4194303 ** 2 == 17592177655809); +assert (-8388608 ** 0 == 1); +assert (8388607 ** 0 == 1); +assert (-8388608 ** 1 == -8388608); +assert (8388607 ** 1 == 8388607); +assert (-8388608 ** 2 == 70368744177664); +assert (8388607 ** 2 == 70368727400449); +assert (-16777216 ** 0 == 1); +assert (16777215 ** 0 == 1); +assert (-16777216 ** 1 == -16777216); +assert (16777215 ** 1 == 16777215); +assert (-16777216 ** 2 == 281474976710656); +assert (16777215 ** 2 == 281474943156225); +assert (-33554432 ** 0 == 1); +assert (33554431 ** 0 == 1); +assert (-33554432 ** 1 == -33554432); +assert (33554431 ** 1 == 33554431); +assert (-33554432 ** 2 == 1125899906842624); +assert (33554431 ** 2 == 1125899839733761); +assert (-67108864 ** 0 == 1); +assert (67108863 ** 0 == 1); +assert (-67108864 ** 1 == -67108864); +assert (67108863 ** 1 == 67108863); +assert (-67108864 ** 2 == 4503599627370496); +assert (67108863 ** 2 == 4503599493152769); +assert (-134217728 ** 0 == 1); +assert (134217727 ** 0 == 1); +assert (-134217728 ** 1 == -134217728); +assert (134217727 ** 1 == 134217727); +assert (-134217728 ** 2 == 18014398509481984); +assert (134217727 ** 2 == 18014398241046529); +assert (-268435456 ** 0 == 1); +assert (268435455 ** 0 == 1); +assert (-268435456 ** 1 == -268435456); +assert (268435455 ** 1 == 268435455); +assert (-268435456 ** 2 == 72057594037927936); +assert (268435455 ** 2 == 72057593501057025); +assert (-536870912 ** 0 == 1); +assert (536870911 ** 0 == 1); +assert (-536870912 ** 1 == -536870912); +assert (536870911 ** 1 == 536870911); +assert (-536870912 ** 2 == 288230376151711744); +assert (536870911 ** 2 == 288230375077969921); +assert (-1073741824 ** 0 == 1); +assert (1073741823 ** 0 == 1); +assert (-1073741824 ** 1 == -1073741824); +assert (1073741823 ** 1 == 1073741823); +assert (-1073741824 ** 2 == 1152921504606846976); +assert (1073741823 ** 2 == 1152921502459363329); diff --git a/test/trap/ok/powInt32-lower.run-ir.ok b/test/trap/ok/powInt32-lower.run-ir.ok new file mode 100644 index 00000000000..768b933644b --- /dev/null +++ b/test/trap/ok/powInt32-lower.run-ir.ok @@ -0,0 +1 @@ +powInt32-lower.as:1.9-1.39: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt32-lower.run-low.ok b/test/trap/ok/powInt32-lower.run-low.ok new file mode 100644 index 00000000000..768b933644b --- /dev/null +++ b/test/trap/ok/powInt32-lower.run-low.ok @@ -0,0 +1 @@ +powInt32-lower.as:1.9-1.39: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt32-lower.run.ok b/test/trap/ok/powInt32-lower.run.ok new file mode 100644 index 00000000000..768b933644b --- /dev/null +++ b/test/trap/ok/powInt32-lower.run.ok @@ -0,0 +1 @@ +powInt32-lower.as:1.9-1.39: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt32-lower.wasm-run.ok b/test/trap/ok/powInt32-lower.wasm-run.ok new file mode 100644 index 00000000000..1686c95bc0c --- /dev/null +++ b/test/trap/ok/powInt32-lower.wasm-run.ok @@ -0,0 +1 @@ +_out/powInt32-lower.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/powInt32-upper.run-ir.ok b/test/trap/ok/powInt32-upper.run-ir.ok new file mode 100644 index 00000000000..0c18eae037c --- /dev/null +++ b/test/trap/ok/powInt32-upper.run-ir.ok @@ -0,0 +1 @@ +powInt32-upper.as:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt32-upper.run-low.ok b/test/trap/ok/powInt32-upper.run-low.ok new file mode 100644 index 00000000000..0c18eae037c --- /dev/null +++ b/test/trap/ok/powInt32-upper.run-low.ok @@ -0,0 +1 @@ +powInt32-upper.as:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt32-upper.run.ok b/test/trap/ok/powInt32-upper.run.ok new file mode 100644 index 00000000000..0c18eae037c --- /dev/null +++ b/test/trap/ok/powInt32-upper.run.ok @@ -0,0 +1 @@ +powInt32-upper.as:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt32-upper.wasm-run.ok b/test/trap/ok/powInt32-upper.wasm-run.ok new file mode 100644 index 00000000000..6f29285d1d2 --- /dev/null +++ b/test/trap/ok/powInt32-upper.wasm-run.ok @@ -0,0 +1 @@ +_out/powInt32-upper.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/powInt8-lower.run-ir.ok b/test/trap/ok/powInt8-lower.run-ir.ok new file mode 100644 index 00000000000..aaca6f96edc --- /dev/null +++ b/test/trap/ok/powInt8-lower.run-ir.ok @@ -0,0 +1 @@ +powInt8-lower.as:1.9-1.34: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt8-lower.run-low.ok b/test/trap/ok/powInt8-lower.run-low.ok new file mode 100644 index 00000000000..aaca6f96edc --- /dev/null +++ b/test/trap/ok/powInt8-lower.run-low.ok @@ -0,0 +1 @@ +powInt8-lower.as:1.9-1.34: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt8-lower.run.ok b/test/trap/ok/powInt8-lower.run.ok new file mode 100644 index 00000000000..aaca6f96edc --- /dev/null +++ b/test/trap/ok/powInt8-lower.run.ok @@ -0,0 +1 @@ +powInt8-lower.as:1.9-1.34: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt8-lower.wasm-run.ok b/test/trap/ok/powInt8-lower.wasm-run.ok new file mode 100644 index 00000000000..7385b83b26c --- /dev/null +++ b/test/trap/ok/powInt8-lower.wasm-run.ok @@ -0,0 +1 @@ +_out/powInt8-lower.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/powInt8-raise-neg.run-ir.ok b/test/trap/ok/powInt8-raise-neg.run-ir.ok new file mode 100644 index 00000000000..37e5942034d --- /dev/null +++ b/test/trap/ok/powInt8-raise-neg.run-ir.ok @@ -0,0 +1 @@ +powInt8-raise-neg.as:1.9-1.35: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt8-raise-neg.run-low.ok b/test/trap/ok/powInt8-raise-neg.run-low.ok new file mode 100644 index 00000000000..37e5942034d --- /dev/null +++ b/test/trap/ok/powInt8-raise-neg.run-low.ok @@ -0,0 +1 @@ +powInt8-raise-neg.as:1.9-1.35: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt8-raise-neg.run.ok b/test/trap/ok/powInt8-raise-neg.run.ok new file mode 100644 index 00000000000..37e5942034d --- /dev/null +++ b/test/trap/ok/powInt8-raise-neg.run.ok @@ -0,0 +1 @@ +powInt8-raise-neg.as:1.9-1.35: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt8-raise-neg.wasm-run.ok b/test/trap/ok/powInt8-raise-neg.wasm-run.ok new file mode 100644 index 00000000000..e6cd6aa2c71 --- /dev/null +++ b/test/trap/ok/powInt8-raise-neg.wasm-run.ok @@ -0,0 +1 @@ +_out/powInt8-raise-neg.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/powInt8-upper.run-ir.ok b/test/trap/ok/powInt8-upper.run-ir.ok new file mode 100644 index 00000000000..f6fcd37f57f --- /dev/null +++ b/test/trap/ok/powInt8-upper.run-ir.ok @@ -0,0 +1 @@ +powInt8-upper.as:1.9-1.34: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt8-upper.run-low.ok b/test/trap/ok/powInt8-upper.run-low.ok new file mode 100644 index 00000000000..f6fcd37f57f --- /dev/null +++ b/test/trap/ok/powInt8-upper.run-low.ok @@ -0,0 +1 @@ +powInt8-upper.as:1.9-1.34: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt8-upper.run.ok b/test/trap/ok/powInt8-upper.run.ok new file mode 100644 index 00000000000..f6fcd37f57f --- /dev/null +++ b/test/trap/ok/powInt8-upper.run.ok @@ -0,0 +1 @@ +powInt8-upper.as:1.9-1.34: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt8-upper.wasm-run.ok b/test/trap/ok/powInt8-upper.wasm-run.ok new file mode 100644 index 00000000000..a765c82a85c --- /dev/null +++ b/test/trap/ok/powInt8-upper.wasm-run.ok @@ -0,0 +1 @@ +_out/powInt8-upper.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/powNat16.run-ir.ok b/test/trap/ok/powNat16.run-ir.ok new file mode 100644 index 00000000000..e94d06ffe4f --- /dev/null +++ b/test/trap/ok/powNat16.run-ir.ok @@ -0,0 +1 @@ +powNat16.as:1.9-1.35: execution error, arithmetic overflow diff --git a/test/trap/ok/powNat16.run-low.ok b/test/trap/ok/powNat16.run-low.ok new file mode 100644 index 00000000000..e94d06ffe4f --- /dev/null +++ b/test/trap/ok/powNat16.run-low.ok @@ -0,0 +1 @@ +powNat16.as:1.9-1.35: execution error, arithmetic overflow diff --git a/test/trap/ok/powNat16.run.ok b/test/trap/ok/powNat16.run.ok new file mode 100644 index 00000000000..e94d06ffe4f --- /dev/null +++ b/test/trap/ok/powNat16.run.ok @@ -0,0 +1 @@ +powNat16.as:1.9-1.35: execution error, arithmetic overflow diff --git a/test/trap/ok/powNat16.wasm-run.ok b/test/trap/ok/powNat16.wasm-run.ok new file mode 100644 index 00000000000..a1b622733f6 --- /dev/null +++ b/test/trap/ok/powNat16.wasm-run.ok @@ -0,0 +1 @@ +_out/powNat16.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/powNat32.run-ir.ok b/test/trap/ok/powNat32.run-ir.ok new file mode 100644 index 00000000000..723841a34e6 --- /dev/null +++ b/test/trap/ok/powNat32.run-ir.ok @@ -0,0 +1 @@ +powNat32.as:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/powNat32.run-low.ok b/test/trap/ok/powNat32.run-low.ok new file mode 100644 index 00000000000..723841a34e6 --- /dev/null +++ b/test/trap/ok/powNat32.run-low.ok @@ -0,0 +1 @@ +powNat32.as:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/powNat32.run.ok b/test/trap/ok/powNat32.run.ok new file mode 100644 index 00000000000..723841a34e6 --- /dev/null +++ b/test/trap/ok/powNat32.run.ok @@ -0,0 +1 @@ +powNat32.as:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/powNat32.wasm-run.ok b/test/trap/ok/powNat32.wasm-run.ok new file mode 100644 index 00000000000..b23b3b070ed --- /dev/null +++ b/test/trap/ok/powNat32.wasm-run.ok @@ -0,0 +1 @@ +_out/powNat32.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/powNat8.run-ir.ok b/test/trap/ok/powNat8.run-ir.ok new file mode 100644 index 00000000000..a1d4ca72c2e --- /dev/null +++ b/test/trap/ok/powNat8.run-ir.ok @@ -0,0 +1 @@ +powNat8.as:1.9-1.33: execution error, arithmetic overflow diff --git a/test/trap/ok/powNat8.run-low.ok b/test/trap/ok/powNat8.run-low.ok new file mode 100644 index 00000000000..a1d4ca72c2e --- /dev/null +++ b/test/trap/ok/powNat8.run-low.ok @@ -0,0 +1 @@ +powNat8.as:1.9-1.33: execution error, arithmetic overflow diff --git a/test/trap/ok/powNat8.run.ok b/test/trap/ok/powNat8.run.ok new file mode 100644 index 00000000000..a1d4ca72c2e --- /dev/null +++ b/test/trap/ok/powNat8.run.ok @@ -0,0 +1 @@ +powNat8.as:1.9-1.33: execution error, arithmetic overflow diff --git a/test/trap/ok/powNat8.wasm-run.ok b/test/trap/ok/powNat8.wasm-run.ok new file mode 100644 index 00000000000..8343057bb39 --- /dev/null +++ b/test/trap/ok/powNat8.wasm-run.ok @@ -0,0 +1 @@ +_out/powNat8.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/powInt32-lower.as b/test/trap/powInt32-lower.as new file mode 100644 index 00000000000..211e7ef7ecc --- /dev/null +++ b/test/trap/powInt32-lower.as @@ -0,0 +1 @@ +let _ = (-1291 : Int32) ** (3 : Int32) diff --git a/test/trap/powInt32-upper.as b/test/trap/powInt32-upper.as new file mode 100644 index 00000000000..270d3f40919 --- /dev/null +++ b/test/trap/powInt32-upper.as @@ -0,0 +1 @@ +let _ = (3 : Int32) ** (20 : Int32) diff --git a/test/trap/powInt8-lower.as b/test/trap/powInt8-lower.as new file mode 100644 index 00000000000..f3aabb95b9b --- /dev/null +++ b/test/trap/powInt8-lower.as @@ -0,0 +1 @@ +let _ = (-3 : Int8) ** (5 : Int8) diff --git a/test/trap/powInt8-raise-neg.as b/test/trap/powInt8-raise-neg.as new file mode 100644 index 00000000000..7a8e41bea6b --- /dev/null +++ b/test/trap/powInt8-raise-neg.as @@ -0,0 +1 @@ +let _ = (12 : Int8) ** (-2 : Int8) diff --git a/test/trap/powInt8-upper.as b/test/trap/powInt8-upper.as new file mode 100644 index 00000000000..8ee1c2a0bb8 --- /dev/null +++ b/test/trap/powInt8-upper.as @@ -0,0 +1 @@ +let _ = (12 : Int8) ** (2 : Int8) diff --git a/test/trap/powNat16.as b/test/trap/powNat16.as new file mode 100644 index 00000000000..6a0fe91040c --- /dev/null +++ b/test/trap/powNat16.as @@ -0,0 +1 @@ +let _ = (5 : Nat16) ** (7 : Nat16) diff --git a/test/trap/powNat32.as b/test/trap/powNat32.as new file mode 100644 index 00000000000..b3dcbaf9dd0 --- /dev/null +++ b/test/trap/powNat32.as @@ -0,0 +1 @@ +let _ = (3 : Nat32) ** (21 : Nat32) diff --git a/test/trap/powNat8.as b/test/trap/powNat8.as new file mode 100644 index 00000000000..1f2d0eed175 --- /dev/null +++ b/test/trap/powNat8.as @@ -0,0 +1 @@ +let _ = (3 : Nat8) ** (6 : Nat8) From 6f477046f26c831973b27f7101870b11a1d5d31e Mon Sep 17 00:00:00 2001 From: Christoph Hegemann Date: Thu, 4 Jul 2019 21:04:26 +0200 Subject: [PATCH 0233/1176] [SDK-234] Building a declaration index to enable auto-completion (#530) * listing all as files inside a lib/ dir * Extract definitions for single-module export libraries * bind imports to names, to allow multiple * only return the library_env from load_libraries * use chase_imports instead of a hack * don't expose unused things * adds to string for `vis` * adds pure for Option to lib * reads lib information of the collected lib scope also defines an index type that we'll collect identifier information into * adds basic bindings to the completion request * adds types and handler for autocompletions so far just the types, no actual logic * skeleton for computing actual completions * implements a simple virtual file system * sync editor file changes to the vfs * extract uri->file_path function * call the completions using the LSP parameters and the vfs * write a simple completion prefix parser * handle on_close document notification in the vfs * adds a unit-tests target to the build Uses ppx_inline to have the unit tests next to the library * handle off-by-one line number mismatch with the LSP * disable warning about discarding optional parameters * adds another dummy import for demo purposes * adds ppx_inline_test to commonBuildInputs * gracefully handle completion for non-existent files * annotate TODO with Christoph's name so he can find it * stops looking for prefixes once we've advanced past the cursor * version tracking for files is not really pressing * displays types alongside completions * don't crash on cancelRequest, but ignore it * no urgency on adding more completion parameters * removes debugging leftovers * complete imported module identifiers if no prefix is found * Apply suggestions from code review Co-Authored-By: Claudio Russo * deletes dead code * apply styling suggestions from review * Apply suggestions from code review Co-Authored-By: Claudio Russo * renames Option.pure to Option.some --- default.nix | 20 ++++ src/Makefile | 5 +- src/as_frontend/syntax.ml | 1 - src/languageServer/completion.ml | 147 ++++++++++++++++++++++++++ src/languageServer/completion_test.ml | 70 ++++++++++++ src/languageServer/dune | 3 + src/languageServer/languageServer.ml | 82 ++++++++++---- src/languageServer/vfs.ml | 48 +++++++++ src/languageServer/vfs.mli | 22 ++++ src/lib/lib.ml | 2 + src/lib/lib.mli | 1 + src/lsp/lsp.atd | 32 +++++- src/pipeline/pipeline.mli | 5 + 13 files changed, 413 insertions(+), 25 deletions(-) create mode 100644 src/languageServer/completion.ml create mode 100644 src/languageServer/completion_test.ml create mode 100644 src/languageServer/vfs.ml create mode 100644 src/languageServer/vfs.mli diff --git a/default.nix b/default.nix index 7790a626708..27debab37f2 100644 --- a/default.nix +++ b/default.nix @@ -51,6 +51,8 @@ let commonBuildInputs = [ ocaml_vlq nixpkgs.ocamlPackages.zarith nixpkgs.ocamlPackages.yojson + nixpkgs.ocamlPackages.ppxlib + nixpkgs.ocamlPackages.ppx_inline_test ocaml_bisect_ppx ocaml_bisect_ppx-ocamlbuild nixpkgs.ocamlPackages.ocaml-migrate-parsetree @@ -158,6 +160,22 @@ rec { ''; }; + unit-tests = stdenv.mkDerivation { + name = "unit-tests"; + + src = subpath ./src; + + buildInputs = commonBuildInputs; + + buildPhase = '' + make DUNE_OPTS="--display=short" unit-tests + ''; + + installPhase = '' + touch $out + ''; + }; + as-ide = stdenv.mkDerivation { name = "as-ide"; @@ -353,9 +371,11 @@ rec { name = "all-systems-go"; constituents = [ asc + as-ide js didc tests + unit-tests samples rts stdlib diff --git a/src/Makefile b/src/Makefile index 4518737a2c5..e70652258ed 100644 --- a/src/Makefile +++ b/src/Makefile @@ -12,7 +12,7 @@ DUNE_OPTS ?= ALL_TARGETS = $(AS_IDE_TARGET) $(AS_LD_TARGET) $(ASC_TARGET) $(ASC_JS_TARGET) $(DIDC_TARGET) -.PHONY: all clean asc as-ide as-ld asc.js didc +.PHONY: all clean asc as-ide as-ld asc.js didc unit-tests # This targets is spelled out so that `make` # only invokes `dune` once, much faster @@ -44,6 +44,9 @@ didc: dune build $(DUNE_OPTS) $(DIDC_TARGET) @ln -fs $(DIDC_TARGET) didc +unit-tests: + dune runtest $(DUNE_OPTS) + clean: rm -f asc as-ide as-ld asc.js didc dune clean diff --git a/src/as_frontend/syntax.ml b/src/as_frontend/syntax.ml index b2fa117df62..360d4f6b424 100644 --- a/src/as_frontend/syntax.ml +++ b/src/as_frontend/syntax.ml @@ -217,4 +217,3 @@ let string_of_lit = function | TextLit t -> t | FloatLit f -> Value.Float.to_pretty_string f | PreLit _ -> assert false - diff --git a/src/languageServer/completion.ml b/src/languageServer/completion.ml new file mode 100644 index 00000000000..4b9977c63c6 --- /dev/null +++ b/src/languageServer/completion.ml @@ -0,0 +1,147 @@ +open As_types +open As_frontend +module Lsp_t = Lsp.Lsp_t + +type ide_decl = + | ValueDecl of string * Type.typ + | TypeDecl of string * Type.typ + +module Index = Map.Make(String) +type completion_index = (ide_decl list) Index.t + +let string_of_list f xs = + List.map f xs + |> String.concat "; " + |> fun x -> "[ " ^ x ^ " ]" + +let item_of_ide_decl = function + | ValueDecl (lbl, ty) -> + (lbl, Some(Type.string_of_typ ty)) + | TypeDecl (lbl, ty) -> + (lbl, Some(Type.string_of_typ ty)) + +let string_of_ide_decl = function + | ValueDecl (lbl, ty) -> + "ValueDecl(" ^ String.escaped lbl ^ ", " ^ Type.string_of_typ ty ^ ")" + | TypeDecl (lbl, ty) -> + "TypeDecl(" ^ String.escaped lbl ^ ", " ^ Type.string_of_typ ty ^ ")" + +let lib_files () : string list = + let lib_dir = "lib" in + Sys.readdir lib_dir + |> Array.to_list + |> List.filter (fun file -> String.equal (Filename.extension file) ".as") + |> List.map (fun file -> Filename.concat lib_dir file) + +let read_single_module_lib (ty: Type.typ): ide_decl list option = + match ty with + | Type.Obj (Type.Module, fields) -> + fields + |> List.map (fun Type.{ lab = lab; typ = typ } -> ValueDecl (lab, typ)) + |> Lib.Option.some + | _ -> None + +let make_index (): completion_index = + let (libraries, scope) = + Diag.run + (Pipeline.chase_imports + Scope.empty + (Pipeline__.Resolve_import.S.of_list (lib_files ()))) in + Type.Env.fold + (fun path ty acc -> + Index.add + path + (ty |> read_single_module_lib |> Base.Option.value ~default:[]) + acc) + scope.Scope.lib_env + Index.empty + +let string_of_index index = + Index.bindings index + |> string_of_list + (fun (path, decls) -> + path + ^ " =>\n " + ^ string_of_list string_of_ide_decl decls + ^ "\n") + +(* Given the source of a module, figure out under what names what + modules have been imported. Normalizes the imported modules + filepaths relative to the project root *) +let find_imported_modules file = + [ ("List", "lib/ListLib.as") + ; ("ListFns", "lib/ListFuncs.as") + ] + +(* Given a source file and a cursor position in that file, figure out + the prefix relevant to searching completions. For example, given: + + List.| (where | is the cursor) return `List.` *) +let find_completion_prefix logger file line column = + (* The LSP sends 0 based line numbers *) + let line = line + 1 in + let lexbuf = Lexing.from_string file in + let next () = Lexer.token Lexer.Normal lexbuf in + let pos_past_cursor pos = + pos.Source.line > line + || (pos.Source.line = line && pos.Source.column >= column) in + let rec loop = function + | _ when (pos_past_cursor (Lexer.region lexbuf).Source.right) -> None + | Parser.ID ident -> + (match next () with + | Parser.DOT -> + (match next () with + | Parser.EOF -> Some ident + | tkn -> + let next_token_start = (Lexer.region lexbuf).Source.left in + let _ = + logger + "completion_prefix" + (Printf.sprintf + "%d:%d::%s\n" + next_token_start.Source.line + next_token_start.Source.column + ident) in + if pos_past_cursor next_token_start + then Some ident + else loop tkn) + | tkn -> loop tkn) + | Parser.EOF -> None + | _ -> loop (next ()) in + loop (next ()) + +(* TODO(Christoph): Don't recompute the index whenever completions are + requested *) +let completions (* index *) logger file line column = + let index = make_index () in + let imported = find_imported_modules file in + match find_completion_prefix logger file line column with + | None -> + imported + |> List.map (fun (alias, _) -> alias, None) + | Some prefix -> + let module_path = + imported + |> List.find_opt (fun (mn, _) -> String.equal mn prefix) in + let index_keys = + Index.bindings index + |> List.map fst + |> string_of_list Base.Fn.id in + match module_path with + | Some mp -> + (match Index.find_opt (snd mp) index with + | Some decls -> + List.map item_of_ide_decl decls + | None -> + [ (("ERROR: Couldn't find module in index: " ^ index_keys), None) ]) + | None -> + [ (("ERROR: Couldn't find module for prefix: " ^ prefix), None) ] + +let completion_handler logger file position = + let line = position.Lsp_t.position_line in + let column = position.Lsp_t.position_character in + let completion_item (lbl, detail) = + Lsp_t.{ completion_item_label = lbl + ; completion_item_detail = detail } in + `CompletionResponse + (List.map completion_item (completions logger file line column)) diff --git a/src/languageServer/completion_test.ml b/src/languageServer/completion_test.ml new file mode 100644 index 00000000000..09a9750956a --- /dev/null +++ b/src/languageServer/completion_test.ml @@ -0,0 +1,70 @@ +let extract_cursor input = + let cursor_pos = ref (0, 0) in + Base.String.split_lines input + |> List.mapi + (fun line_num line -> + match String.index_opt line '|' with + | Some column_num -> + cursor_pos := (line_num, column_num); + line + |> String.split_on_char '|' + |> String.concat "" + | None -> line + ) + |> String.concat "\n" + |> fun f -> (f, !cursor_pos) + +let dummy_logger _ _ = () + +let prefix_test_case file expected = + let (file, (line, column)) = extract_cursor file in + let prefix = + Completion.find_completion_prefix dummy_logger file line column in + Base.Option.equal String.equal prefix expected + + +let%test "it finds a simple prefix" = + prefix_test_case "List.|" (Some "List") + +let%test "it doesn't find non-qualified idents" = + prefix_test_case "List.filter we|" None + +let%test "it picks the qualified closest to the cursor" = + prefix_test_case "Stack.some List.|" (Some "List") + +let%test "it handles immediately following single character tokens" = + prefix_test_case "List.|<" (Some "List") + +let%test "TODO(Christoph): it doesn't handle qualifier + partial identifierf" = + prefix_test_case "Stack.so|" (None) + +let%test "it handles multiline files" = + prefix_test_case +{|Stak. +List.| +|} (Some "List") + +let%test "it handles a full module" = + prefix_test_case +{|module { + private import List = "./ListLib.as"; + + func singleton(x: T): List.List = + List.cons(x, Test.|()); + + func doubleton(x: T): List.List = + List.cons(x, List.cons(x, List.nil())); + }|} (Some "Test") + +let%test "it doesn't fall through to the next valid prefix" = + prefix_test_case +{|module { +private import List = "lib/ListLib.as"; // private, so we don't re-export List +private import ListFns = "lib/ListFuncs.as"; // private, so we don't re-export List +type Stack = List.List; +func push(x : Int, s : Stack) : Stack = List.cons(x, s); +func empty():Stack = List.nil(); +func singleton(x : Int) : Stack = + List.we| + ListFns.singleton(x); +}|} None diff --git a/src/languageServer/dune b/src/languageServer/dune index 99300e95f16..8f82a820892 100644 --- a/src/languageServer/dune +++ b/src/languageServer/dune @@ -1,4 +1,7 @@ (library (name languageServer) (libraries base lang_utils lsp pipeline) + (inline_tests) + (preprocess (pps ppx_inline_test)) + (flags (:standard -w -48)) ) diff --git a/src/languageServer/languageServer.ml b/src/languageServer/languageServer.ml index 54a68083660..71f7c29de3c 100644 --- a/src/languageServer/languageServer.ml +++ b/src/languageServer/languageServer.ml @@ -16,6 +16,14 @@ let response_result_message (id : int) (result : Lsp_t.response_result) : Lsp_t. { response_message_jsonrpc = jsonrpc_version; response_message_id = id; response_message_result = Some result; + response_message_error = None; + } + +let response_error_message (id : int) (error : Lsp_t.response_error) : Lsp_t.response_message = Lsp_t. + { response_message_jsonrpc = jsonrpc_version; + response_message_id = id; + response_message_result = None; + response_message_error = Some error; } (* let response_error_message (id : int) (error : Lsp_t.response_error) : Lsp_t.response_message = *) @@ -81,6 +89,12 @@ let diagnostics_of_message (msg : Diag.message) : Lsp_t.diagnostic = Lsp_t. } let file_uri_prefix = "file://" ^ Sys.getcwd () ^ "/" +let file_from_uri logger uri = + match Base.String.chop_prefix ~prefix:file_uri_prefix uri with + | Some file -> file + | None -> + let _ = logger "error" ("Failed to strip filename from: " ^ uri) in + uri let start () = let oc: out_channel = open_out_gen [Open_append; Open_creat] 0o666 "ls.log"; in @@ -92,6 +106,8 @@ let start () = let client_capabilities = ref None in + let vfs = ref Vfs.empty in + let rec loop () = let clength = read_line () in log_to_file "content-length" clength; @@ -117,11 +133,16 @@ let start () = (* Request messages *) | (Some id, `Initialize params) -> - client_capabilities := Some params.Lsp_t.initialize_params_capabilities; + client_capabilities := Some params.Lsp_t.initialize_params_capabilities; + let completion_options = + Lsp_t.{ completion_options_resolveProvider = Some false; + completion_options_triggerCharacters = Some ["."] + } in let result = `Initialize (Lsp_t.{ initialize_result_capabilities = { server_capabilities_textDocumentSync = 1; server_capabilities_hoverProvider = Some true; + server_capabilities_completionProvider = Some completion_options; } }) in let response = response_result_message id result in @@ -137,37 +158,54 @@ let start () = }) in let response = response_result_message id result in send_response (Lsp_j.string_of_response_message response); - + | (_, `TextDocumentDidOpen params) -> + vfs := Vfs.open_file params !vfs + | (_, `TextDocumentDidChange params) -> + vfs := Vfs.update_file params !vfs + | (_, `TextDocumentDidClose params) -> + vfs := Vfs.close_file params !vfs | (_, `TextDocumentDidSave params) -> let textDocumentIdent = params.Lsp_t.text_document_did_save_params_textDocument in let uri = textDocumentIdent.Lsp_t.text_document_identifier_uri in - (match Base.String.chop_prefix ~prefix:file_uri_prefix uri with - | Some file_name -> begin - let result = Pipeline.check_files [file_name] in - show_message Lsp.MessageType.Info ("Compiling file: " ^ file_name); - let msgs = match result with - | Error msgs' -> msgs' - | Ok (_, msgs') -> msgs' in - Base.Option.iter !client_capabilities ~f:(fun capabilities -> - (* TODO: determine if the client accepts diagnostics with related info *) - (* let textDocument = capabilities.client_capabilities_textDocument in - * let send_related_information = textDocument.publish_diagnostics.relatedInformation in *) - let diags = List.map diagnostics_of_message msgs in - publish_diagnostics uri diags; - ); - end - | None -> - log_to_file - "error" - ("Failed to strip filename from: " ^ uri)); + let file_name = file_from_uri log_to_file uri in + let result = Pipeline.check_files [file_name] in + show_message Lsp.MessageType.Info ("Compiling file: " ^ file_name); + let msgs = match result with + | Error msgs' -> msgs' + | Ok (_, msgs') -> msgs' in + Base.Option.iter !client_capabilities ~f:(fun _ -> + (* TODO: determine if the client accepts diagnostics with related info *) + (* let textDocument = capabilities.client_capabilities_textDocument in + * let send_related_information = textDocument.publish_diagnostics.relatedInformation in *) + let diags = List.map diagnostics_of_message msgs in + publish_diagnostics uri diags; + ); (* Notification messages *) | (None, `Initialized _) -> show_message Lsp.MessageType.Info "Language server initialized" + | (Some id, `CompletionRequest params) -> + let uri = + params + .Lsp_t.text_document_position_params_textDocument + .Lsp_t.text_document_identifier_uri in + let position = + params.Lsp_t.text_document_position_params_position in + let response = match Vfs.read_file uri !vfs with + | None -> + response_error_message + id + Lsp_t.{ code = 1 + ; message = "Tried to find completions for a file that hadn't been opened yet"} + | Some file_content -> + Completion.completion_handler log_to_file file_content position + |> response_result_message id in + response + |> Lsp_j.string_of_response_message + |> send_response (* Unhandled messages *) - | _ -> log_to_file "unhandled message" raw; ); diff --git a/src/languageServer/vfs.ml b/src/languageServer/vfs.ml new file mode 100644 index 00000000000..e95dd3953a6 --- /dev/null +++ b/src/languageServer/vfs.ml @@ -0,0 +1,48 @@ +module Lsp_t = Lsp.Lsp_t + +module VfsStore = Map.Make(String) + +type virtual_file = string + +type t = virtual_file VfsStore.t + +type uri = string + +let empty = VfsStore.empty + +let open_file did_open_params vfs = + let text_document_item = + did_open_params + .Lsp_t + .text_document_did_open_params_textDocument in + let uri = + text_document_item.Lsp_t.text_document_item_uri in + let _ = + text_document_item.Lsp_t.text_document_item_version in + let text = + text_document_item.Lsp_t.text_document_item_text in + VfsStore.add uri text vfs + +let read_file uri vfs = + VfsStore.find_opt uri vfs + +let update_file did_change_params = + let change_event = + did_change_params.Lsp_t.text_document_did_change_params_contentChanges + |> (* TODO(Christoph): This needs to change once we allow + incremental file updates*) + Base.Fn.flip List.nth 0 + in + let new_content = change_event.Lsp_t.text_document_content_change_event_text in + let uri = + did_change_params + .Lsp_t.text_document_did_change_params_textDocument + .Lsp_t.versioned_text_document_identifier_uri in + VfsStore.add uri new_content + +let close_file did_close_params = + let uri = + did_close_params + .Lsp_t.text_document_did_close_params_textDocument + .Lsp_t.text_document_identifier_uri in + VfsStore.remove uri diff --git a/src/languageServer/vfs.mli b/src/languageServer/vfs.mli new file mode 100644 index 00000000000..ffe8f3a6e31 --- /dev/null +++ b/src/languageServer/vfs.mli @@ -0,0 +1,22 @@ +module Lsp_t = Lsp.Lsp_t + +type t + +type uri = string +(* NOTE(Christoph): Track file version *) +type virtual_file = string + +(** Creates a new virtual file system *) +val empty: t + +(** Reads a file from the OS's file system and adds it to the vfs *) +val open_file: Lsp_t.text_document_did_open_params -> t -> t + +(** Reads a file from the vfs *) +val read_file: uri -> t -> virtual_file option + +(** Updates the contents of a file in the vfs *) +val update_file: Lsp_t.text_document_did_change_params -> t -> t + +(** Removes a file from the vfs *) +val close_file: Lsp_t.text_document_did_close_params -> t -> t diff --git a/src/lib/lib.ml b/src/lib/lib.ml index c93303bc09b..6e32589b811 100644 --- a/src/lib/lib.ml +++ b/src/lib/lib.ml @@ -264,6 +264,8 @@ struct | Some x -> f x | None -> () + let some x = Some x + let bind x f = match x with | Some x -> f x | None -> None diff --git a/src/lib/lib.mli b/src/lib/lib.mli index c29d3ea03bc..ed0c1bd169f 100644 --- a/src/lib/lib.mli +++ b/src/lib/lib.mli @@ -71,6 +71,7 @@ sig val get : 'a option -> 'a -> 'a val value : 'a option -> 'a val map : ('a -> 'b) -> 'a option -> 'b option + val some : 'a -> 'a option val app : ('a -> unit) -> 'a option -> unit val bind : 'a option -> ('a -> 'b option) -> 'b option end diff --git a/src/lsp/lsp.atd b/src/lsp/lsp.atd index f9e558a045b..e3fd3f4d9ab 100644 --- a/src/lsp/lsp.atd +++ b/src/lsp/lsp.atd @@ -46,6 +46,9 @@ type incoming_message_params = [ | TextDocumentDidChange of text_document_did_change_params | TextDocumentDidSave of text_document_did_save_params | TextDocumentHover of text_document_position_params + (* NOTE(Christoph) There are more parameters than just text_document_position on the completion request *) + | CompletionRequest of text_document_position_params + | CancelRequest of unit ] (* @@ -60,7 +63,7 @@ type response_message = { inherit message; id : int; ?result : response_result nullable; - (* ?error : response_error nullable; *) + ?error : response_error nullable; } @@ -68,13 +71,25 @@ type response_message = { type response_result = [ Initialize of initialize_result | TextDocumentHoverResponse of hover_result + | CompletionResponse of completion_item list ] +type response_error = { + code : int; + message : string; + (* ?data : json; *) +} + type hover_result = { contents : string; } +type completion_item = { + label : string; + ?detail: string nullable; +} + (* Outgoing notifications *) @@ -107,9 +122,17 @@ type text_document_did_open_params = { type text_document_did_change_params = { textDocument : versioned_text_document_identifier; + contentChanges : text_document_content_change_event list } +type text_document_content_change_event = { + ?range: range nullable; + ?rangeLength: int nullable; + text: string; +} + + type text_document_did_close_params = { textDocument : text_document_identifier; } @@ -222,10 +245,17 @@ type initialize_result = { } +type completion_options = { + ?resolveProvider : bool nullable; + ?triggerCharacters : string list nullable; +} + + (* FIXME: incomplete *) type server_capabilities = { textDocumentSync : int; ?hoverProvider : bool nullable; + ?completionProvider : completion_options nullable; } diff --git a/src/pipeline/pipeline.mli b/src/pipeline/pipeline.mli index cf14e260989..a35a2fd69b1 100644 --- a/src/pipeline/pipeline.mli +++ b/src/pipeline/pipeline.mli @@ -19,6 +19,11 @@ end val check_files : string list -> unit Diag.result val check_string : string -> string -> unit Diag.result +val chase_imports + : As_types.Scope.scope + -> Resolve_import.S.t + -> (As_frontend.Syntax.libraries * As_types.Scope.scope) Diag.result + val run_files : string list -> unit option val interpret_ir_files : string list -> unit option val run_files_and_stdin : string list -> unit option From 08264604341dc76e634843d3dd873c0e5a951f52 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Fri, 5 Jul 2019 17:48:48 +0200 Subject: [PATCH 0234/1176] Fix type and coverage checking for patterns (#538) --- src/as_frontend/coverage.ml | 93 ++++---- src/as_frontend/typing.ml | 247 ++++++++++++--------- src/as_ir/check_ir.ml | 24 +- src/as_ir/construct.ml | 2 +- src/as_types/call_conv.ml | 2 + src/as_types/type.ml | 163 +++++++++++--- src/as_types/type.mli | 9 +- src/as_values/operator.ml | 20 +- src/as_values/operator.mli | 16 +- src/codegen/compile.ml | 12 +- src/interpreter/interpret.ml | 8 +- src/ir_interpreter/interpret_ir.ml | 6 +- src/lowering/desugar.ml | 12 +- test/fail/ok/actor-match.tc.ok | 3 +- test/fail/ok/objpat-infer.tc.ok | 3 +- test/fail/ok/pat-inconsistent.tc.ok | 114 ++++++++++ test/fail/ok/pat-subtyping-fail.tc.ok | 92 ++++++++ test/fail/pat-inconsistent.as | 37 +++ test/fail/pat-subtyping-fail.as | 119 ++++++++++ test/repl/ok/stateful.stderr.ok | 3 +- test/repl/ok/type-lub-repl.stdout.ok | 2 +- test/run-dfinity/shared-object.as | 6 +- test/run/coverage.as | 64 ++++-- test/run/ir-pat-subtype.as | 5 +- test/run/ok/coverage.run-ir.ok | 21 +- test/run/ok/coverage.run-low.ok | 21 +- test/run/ok/coverage.run.ok | 21 +- test/run/ok/coverage.tc.ok | 21 +- test/run/ok/coverage.wasm.stderr.ok | 21 +- test/run/ok/pat-subtyping.run-ir.ok | 33 +++ test/run/ok/pat-subtyping.run-low.ok | 33 +++ test/run/ok/pat-subtyping.run.ok | 33 +++ test/run/ok/pat-subtyping.tc.ok | 33 +++ test/run/ok/pat-subtyping.wasm.stderr.ok | 33 +++ test/run/ok/switch.run-ir.ok | 3 +- test/run/ok/switch.run-low.ok | 3 +- test/run/ok/switch.run.ok | 3 +- test/run/ok/switch.tc.ok | 3 +- test/run/ok/switch.wasm.stderr.ok | 3 +- test/run/ok/type-inference.run-ir.ok | 37 +++ test/run/ok/type-inference.run-low.ok | 37 +++ test/run/ok/type-inference.run.ok | 37 +++ test/{fail => run}/ok/type-inference.tc.ok | 2 - test/run/ok/type-inference.wasm.stderr.ok | 38 ++++ test/run/pat-subtyping.as | 207 +++++++++++++++++ test/run/switch.as | 2 +- test/{fail => run}/type-inference.as | 11 +- 47 files changed, 1435 insertions(+), 283 deletions(-) create mode 100644 test/fail/ok/pat-inconsistent.tc.ok create mode 100644 test/fail/ok/pat-subtyping-fail.tc.ok create mode 100644 test/fail/pat-inconsistent.as create mode 100644 test/fail/pat-subtyping-fail.as create mode 100644 test/run/ok/pat-subtyping.run-ir.ok create mode 100644 test/run/ok/pat-subtyping.run-low.ok create mode 100644 test/run/ok/pat-subtyping.run.ok create mode 100644 test/run/ok/pat-subtyping.tc.ok create mode 100644 test/run/ok/pat-subtyping.wasm.stderr.ok create mode 100644 test/run/ok/type-inference.run-ir.ok create mode 100644 test/run/ok/type-inference.run-low.ok create mode 100644 test/run/ok/type-inference.run.ok rename test/{fail => run}/ok/type-inference.tc.ok (93%) create mode 100644 test/run/ok/type-inference.wasm.stderr.ok create mode 100644 test/run/pat-subtyping.as rename test/{fail => run}/type-inference.as (96%) diff --git a/src/as_frontend/coverage.ml b/src/as_frontend/coverage.ml index d5b4efd5aeb..75aee409245 100644 --- a/src/as_frontend/coverage.ml +++ b/src/as_frontend/coverage.ml @@ -7,6 +7,7 @@ module V = As_values.Value module ValSet = Set.Make(struct type t = V.value let compare = V.compare end) module TagSet = Set.Make(struct type t = string let compare = compare end) +module LabMap = Map.Make(struct type t = string let compare = compare end) module AtSet = Set.Make(struct type t = Source.region let compare = compare end) type desc = @@ -14,7 +15,7 @@ type desc = | Val of V.value | NotVal of ValSet.t | Tup of desc list - | Obj of desc list + | Obj of desc LabMap.t | Opt of desc | Tag of desc * string | NotTag of TagSet.t @@ -23,7 +24,7 @@ type ctxt = | InOpt of ctxt | InTag of ctxt * string | InTup of ctxt * desc list * desc list * pat list * Type.typ list - | InObj of ctxt * desc list * desc list * pat_field list * Type.field list + | InObj of ctxt * desc LabMap.t * string * pat_field list * Type.field list | InAlt1 of ctxt * Source.region * pat * Type.typ | InAlt2 of ctxt * Source.region | InCase of Source.region * case list * Type.typ @@ -67,6 +68,8 @@ let value_of_lit = function | PreLit _ -> assert false +let (&&&) = (&&) (* No short-cutting *) + let skip_pat pat sets = sets.alts <- AtSet.add pat.at sets.alts; true @@ -75,11 +78,14 @@ let rec match_pat ctxt desc pat t sets = Type.span t = Some 0 && skip_pat pat sets || match pat.it with | WildP | VarP _ -> - succeed ctxt desc sets + if Type.inhabited t then + succeed ctxt desc sets + else + skip_pat pat sets | LitP lit -> match_lit ctxt desc (value_of_lit !lit) t sets | SignP (op, lit) -> - let f = Operator.unop pat.note op in + let f = Operator.unop op (Operator.type_unop op pat.note) in match_lit ctxt desc (f (value_of_lit !lit)) t sets | TupP pats -> let ts = Type.as_tup (Type.promote t) in @@ -89,20 +95,16 @@ let rec match_pat ctxt desc pat t sets = | Any -> List.map (fun _ -> Any) pats | _ -> assert false in match_tup ctxt [] descs pats ts sets - | ObjP pfs -> - let t' = Type.promote t in - let sensible (pf : pat_field) = - List.exists (fun {Type.lab; _} -> pf.it.id.it = lab) (snd (Type.as_obj_sub pf.it.id.it t')) in - let pfs' = List.filter sensible pfs in - let tf_of_pf (pf : pat_field) = - List.find (fun {Type.lab; _} -> pf.it.id.it = lab) (snd (Type.as_obj_sub pf.it.id.it t')) in - let tfs' = List.map tf_of_pf pfs' in - let descs = + | ObjP pat_fields -> + let _, tfs = Type.as_obj (Type.promote t) in + let ldescs = match desc with - | Obj descs -> descs - | Any -> List.map (fun _ -> Any) pfs' + | Obj ldescs -> ldescs + | Any -> + LabMap.(List.fold_left + (fun m (tf : Type.field) -> add tf.Type.lab Any m) empty tfs) | _ -> assert false - in match_obj ctxt [] descs pfs' tfs' sets + in match_obj ctxt ldescs pat_fields tfs sets | OptP pat1 -> let t' = Type.as_opt (Type.promote t) in (match desc with @@ -113,7 +115,7 @@ let rec match_pat ctxt desc pat t sets = | Opt desc' -> match_pat (InOpt ctxt) desc' pat1 t' sets | Any -> - fail ctxt (Val Value.Null) sets && + fail ctxt (Val Value.Null) sets &&& match_pat (InOpt ctxt) Any pat1 t' sets | _ -> assert false ) @@ -127,15 +129,19 @@ let rec match_pat ctxt desc pat t sets = else if Type.span t = Some (TagSet.cardinal ls + 1) then match_pat (InTag (ctxt, id.it)) Any pat1 t' sets else - fail ctxt (NotTag (TagSet.add id.it ls)) sets && + fail ctxt (NotTag (TagSet.add id.it ls)) sets &&& match_pat (InTag (ctxt, id.it)) Any pat1 t' sets | Tag (desc', l) -> - if id.it <> l - then fail ctxt desc sets - else match_pat (InTag (ctxt, l)) desc' pat1 t' sets + if id.it = l then + match_pat (InTag (ctxt, l)) desc' pat1 t' sets + else + fail ctxt desc sets | Any -> - fail ctxt (NotTag (TagSet.singleton id.it)) sets && - match_pat (InTag (ctxt, id.it)) Any pat1 t' sets + if Type.span t = Some 1 then + match_pat (InTag (ctxt, id.it)) Any pat1 t' sets + else + fail ctxt (NotTag (TagSet.singleton id.it)) sets &&& + match_pat (InTag (ctxt, id.it)) Any pat1 t' sets | _ -> assert false ) | AltP (pat1, pat2) -> @@ -153,19 +159,21 @@ and match_lit ctxt desc v t sets = if Type.span t = Some 1 then succeed ctxt desc_succ sets else - succeed ctxt desc_succ sets && - fail ctxt (desc_fail ValSet.empty) sets + fail ctxt (desc_fail ValSet.empty) sets &&& + succeed ctxt desc_succ sets | Val v' -> - if Value.equal v v' - then succeed ctxt desc sets - else fail ctxt desc sets + if Value.equal v v' then + succeed ctxt desc sets + else + fail ctxt desc sets | NotVal vs -> if ValSet.mem v vs then fail ctxt desc sets else if Type.span t = Some (ValSet.cardinal vs + 1) then succeed ctxt desc_succ sets else - succeed ctxt desc_succ sets && fail ctxt (desc_fail vs) sets + fail ctxt (desc_fail vs) sets &&& + succeed ctxt desc_succ sets | Opt _ -> fail ctxt desc sets | _ -> @@ -180,14 +188,15 @@ and match_tup ctxt descs_r descs pats ts sets = | _ -> assert false -and match_obj ctxt descs_r descs (pfs : pat_field list) tfs sets = - match descs, pfs, tfs with - | [], [], [] -> - succeed ctxt (Obj (List.rev descs_r)) sets - | desc::descs', pf::pfs', Type.{lab; typ}::tfs' -> - match_pat (InObj (ctxt, descs_r, descs', pfs', tfs')) desc pf.it.pat typ sets - | _ -> - assert false +and match_obj ctxt ldescs (pat_fields : pat_field list) tfs sets = + match pat_fields with + | [] -> succeed ctxt (Obj ldescs) sets + | pat_field::pat_fields' -> + let l = pat_field.it.id.it in + let tf = List.find (fun tf -> tf.Type.lab = l) tfs in + let desc = LabMap.find l ldescs in + match_pat (InObj (ctxt, ldescs, l, pat_fields', tfs)) + desc pat_field.it.pat tf.Type.typ sets and succeed ctxt desc sets : bool = match ctxt with @@ -197,8 +206,8 @@ and succeed ctxt desc sets : bool = succeed ctxt' (Tag (desc, l)) sets | InTup (ctxt', descs_r, descs, pats, ts) -> match_tup ctxt' (desc::descs_r) descs pats ts sets - | InObj (ctxt', descs_r, descs, pfs, tfs) -> - match_obj ctxt' (desc::descs_r) descs pfs tfs sets + | InObj (ctxt', ldescs, l, pfs, tfs) -> + match_obj ctxt' (LabMap.add l desc ldescs) pfs tfs sets | InAlt1 (ctxt', at1, _pat2, _t) -> sets.reached_alts <- AtSet.add at1 sets.reached_alts; succeed ctxt' desc sets @@ -225,14 +234,14 @@ and fail ctxt desc sets : bool = fail ctxt' (Tag (desc, l)) sets | InTup (ctxt', descs', descs, pats, _ts) -> fail ctxt' (Tup (List.rev descs' @ [desc] @ descs)) sets - | InObj (ctxt', descs', descs, pats, _ts) -> - fail ctxt' (Obj (List.rev descs' @ [desc] @ descs)) sets + | InObj (ctxt', ldescs, l, pats, _tfs) -> + fail ctxt' (Obj (LabMap.add l desc ldescs)) sets | InAlt1 (ctxt', at1, pat2, t) -> match_pat (InAlt2 (ctxt', pat2.at)) desc pat2 t sets | InAlt2 (ctxt', at2) -> fail ctxt' desc sets | InCase (at, [], t) -> - Type.span t = Some 0 + Type.span t = Some 0 || not (Type.inhabited t) | InCase (at, case::cases, t) -> Type.span t = Some 0 && skip (case::cases) sets || match_pat (InCase (case.at, cases, t)) desc case.it.pat t sets diff --git a/src/as_frontend/typing.ml b/src/as_frontend/typing.ml index 2616eb11714..3f7bd1248ab 100644 --- a/src/as_frontend/typing.ml +++ b/src/as_frontend/typing.ml @@ -357,7 +357,6 @@ let infer_lit env lit at : T.prim = let check_lit env t lit at = match T.normalize t, !lit with - | T.Opt _, NullLit -> () | T.Prim T.Nat, PreLit (s, T.Nat) -> lit := NatLit (check_nat env at s) | T.Prim T.Nat8, PreLit (s, T.Nat) -> @@ -452,11 +451,6 @@ and infer_exp' f env exp : T.typ = end; t' -and special_unop_typing = let open T in - function - | Prim Nat -> Prim Int - | t -> t - and infer_exp'' env exp : T.typ = match exp.it with | PrimE _ -> @@ -473,34 +467,24 @@ and infer_exp'' env exp : T.typ = T.Prim (infer_lit env lit exp.at) | UnE (ot, op, exp1) -> let t1 = infer_exp_promote env exp1 in - (* Special case for subtyping *) - let t = special_unop_typing t1 in + let t = Operator.type_unop op t1 in if not env.pre then begin assert (!ot = Type.Pre); - if not (Operator.has_unop t op) then + if not (Operator.has_unop op t) then error env exp.at "operator is not defined for operand type\n %s" (T.string_of_typ_expand t); ot := t; end; t - | ShowE (ot, exp1) -> - let t = infer_exp_promote env exp1 in - if not env.pre then begin - if not (Show.can_show t) then - error env exp.at "show is not defined for operand type\n %s" - (T.string_of_typ_expand t); - ot := t - end; - T.Prim T.Text | BinE (ot, exp1, op, exp2) -> let t1 = infer_exp_promote env exp1 in let t2 = infer_exp_promote env exp2 in - let t = T.lub t1 t2 in + let t = Operator.type_binop op (T.lub t1 t2) in if not env.pre then begin assert (!ot = Type.Pre); - if not (Operator.has_binop t op) then + if not (Operator.has_binop op t) then error env exp.at - "operator not defined for operand types\n %s and\n %s" + "operator not defined for operand types\n %s\nand\n %s" (T.string_of_typ_expand t1) (T.string_of_typ_expand t2); ot := t @@ -509,17 +493,26 @@ and infer_exp'' env exp : T.typ = | RelE (ot, exp1, op, exp2) -> let t1 = infer_exp_promote env exp1 in let t2 = infer_exp_promote env exp2 in - let t = T.lub t1 t2 in + let t = Operator.type_relop op (T.lub t1 t2) in if not env.pre then begin assert (!ot = Type.Pre); - if not (Operator.has_relop t op) then + if not (Operator.has_relop op t) then error env exp.at - "operator not defined for operand types\n %s and\n %s" + "operator not defined for operand types\n %s\nand\n %s" (T.string_of_typ_expand t1) (T.string_of_typ_expand t2); ot := t; end; T.bool + | ShowE (ot, exp1) -> + let t = infer_exp_promote env exp1 in + if not env.pre then begin + if not (Show.can_show t) then + error env exp.at "show is not defined for operand type\n %s" + (T.string_of_typ_expand t); + ot := t + end; + T.Prim T.Text | TupE exps -> let ts = List.map (infer_exp env) exps in T.Tup ts @@ -548,7 +541,7 @@ and infer_exp'' env exp : T.typ = | DotE (exp1, id) -> let t1 = infer_exp_promote env exp1 in let _s, tfs = - try T.as_obj_sub id.it t1 with Invalid_argument _ -> + try T.as_obj_sub [id.it] t1 with Invalid_argument _ -> try array_obj (T.as_array_sub t1) with Invalid_argument _ -> try text_obj (T.as_prim_sub T.Text t1) with Invalid_argument _ -> error env exp1.at @@ -577,7 +570,7 @@ and infer_exp'' env exp : T.typ = | ArrayE (mut, exps) -> let ts = List.map (infer_exp env) exps in let t1 = List.fold_left T.lub T.Non ts in - if not env.pre && is_inconsistent t1 ts then + if not env.pre && inconsistent t1 ts then warn env exp.at "this array has type %s because elements have inconsistent types" (T.string_of_typ (T.Array t1)); @@ -612,7 +605,7 @@ and infer_exp'' env exp : T.typ = error env pat.at "shared function has non-shared parameter type\n %s" (T.string_of_typ_expand t1); - if not (T.is_concrete t1) then + if not (T.concrete t1) then error env pat.at "shared function parameter contains abstract type\n %s" (T.string_of_typ_expand t1); @@ -623,7 +616,7 @@ and infer_exp'' env exp : T.typ = error env typ.at "shared function has non-shared result type\n %s" (T.string_of_typ_expand t2); - if not (T.is_concrete t2) then + if not (T.concrete t2) then error env typ.at "shared function result contains abstract type\n %s" (T.string_of_typ_expand t2); @@ -659,11 +652,11 @@ and infer_exp'' env exp : T.typ = if not env.pre then begin check_exp env t_arg exp2; if sort = T.Sharable then begin - if not (T.is_concrete t_arg) then + if not (T.concrete t_arg) then error env exp1.at "shared function argument contains abstract type\n %s" (T.string_of_typ_expand t_arg); - if not (T.is_concrete t_ret) then + if not (T.concrete t_ret) then error env exp2.at "shared function call result contains abstract type\n %s" (T.string_of_typ_expand t_ret); @@ -698,7 +691,7 @@ and infer_exp'' env exp : T.typ = let t2 = infer_exp env exp2 in let t3 = infer_exp env exp3 in let t = T.lub t2 t3 in - if not env.pre && is_inconsistent t [t2; t3] then + if not env.pre && inconsistent t [t2; t3] then warn env exp.at "this if has type %s because branches have inconsistent types,\ntrue produces\n %s\nfalse produces\n %s" (T.string_of_typ t) @@ -734,7 +727,7 @@ and infer_exp'' env exp : T.typ = if not env.pre then begin let t1 = infer_exp_promote env exp1 in (try - let _, tfs = T.as_obj_sub "next" t1 in + let _, tfs = T.as_obj_sub ["next"] t1 in let t = Lib.Option.value (T.lookup_val_field "next" tfs) in let t1, t2 = T.as_mono_func_sub t in if not (T.sub T.unit t1) then raise (Invalid_argument ""); @@ -824,11 +817,11 @@ and check_exp' env t exp : T.typ = | LitE lit, _ -> check_lit env t lit exp.at; t - | UnE (ot, op, exp1), _ when Operator.has_unop t op -> + | UnE (ot, op, exp1), _ when Operator.has_unop op t -> ot := t; check_exp env t exp1; t - | BinE (ot, exp1, op, exp2), _ when Operator.has_binop t op -> + | BinE (ot, exp1, op, exp2), _ when Operator.has_binop op t -> ot := t; check_exp env t exp1; check_exp env t exp2; @@ -906,7 +899,7 @@ and infer_case env t_pat t {it = {pat; exp}; at; _} = let ve = check_pat env t_pat pat in let t' = recover_with T.Non (infer_exp (adjoin_vals env ve)) exp in let t'' = T.lub t t' in - if not env.pre && is_inconsistent t'' [t; t'] then + if not env.pre && inconsistent t'' [t; t'] then warn env at "the switch has type %s because branches have inconsistent types,\nthis case produces type\n %s\nthe previous produce type\n %s" (T.string_of_typ t'') (T.string_of_typ_expand t) @@ -920,9 +913,9 @@ and check_case env t_pat t {it = {pat; exp}; _} = let ve = check_pat env t_pat pat in recover (check_exp (adjoin_vals env ve) t) exp -and is_inconsistent lub ts = - lub = T.Any && List.for_all (fun t -> T.promote t <> lub) ts - || lub = T.Shared && List.for_all (fun t -> T.promote t <> lub) ts +and inconsistent t ts = + T.opaque t && not (List.exists T.opaque ts) + (* Patterns *) @@ -950,9 +943,8 @@ and infer_pat' env pat : T.typ * Scope.val_env = T.Prim (infer_lit env lit pat.at), T.Env.empty | SignP (op, lit) -> let t1 = T.Prim (infer_lit env lit pat.at) in - (* Special case for subtyping *) - let t = special_unop_typing t1 in - if not (Operator.has_unop t op) then + let t = Operator.type_unop op t1 in + if not (Operator.has_unop op t) then local_error env pat.at "operator is not defined for operand type\n %s" (T.string_of_typ_expand t); t, T.Env.empty @@ -972,6 +964,11 @@ and infer_pat' env pat : T.typ * Scope.val_env = let t1, ve1 = infer_pat env pat1 in let t2, ve2 = infer_pat env pat2 in let t = T.lub t1 t2 in + if not (T.compatible t1 t2) then + error env pat.at + "pattern branches have incompatible types,\nleft consumes\n %s\nright consumes\n %s" + (T.string_of_typ_expand t1) + (T.string_of_typ_expand t2); if ve1 <> T.Env.empty || ve2 <> T.Env.empty then error env pat.at "variables are not allowed in pattern alternatives"; t, T.Env.empty @@ -1020,111 +1017,145 @@ and check_pat' env t pat : Scope.val_env = | VarP id -> T.Env.singleton id.it t | LitP lit -> - if not env.pre then check_lit env t lit pat.at; + if not env.pre then begin + if T.opaque t then + error env pat.at "literal pattern cannot consume expected type\n %s" + (T.string_of_typ_expand t); + if T.sub t T.Non + then ignore (infer_lit env lit pat.at) + else check_lit env t lit pat.at + end; T.Env.empty | SignP (op, lit) -> if not env.pre then begin - let t' = T.normalize t in - if not (Operator.has_unop t op) then + if not (Operator.has_unop op (T.promote t)) then local_error env pat.at "operator cannot consume expected type\n %s" - (T.string_of_typ_expand t'); - check_lit env t' lit pat.at + (T.string_of_typ_expand t); + if T.sub t T.Non + then ignore (infer_lit env lit pat.at) + else check_lit env t lit pat.at end; T.Env.empty | TupP pats -> - (try - let ts = T.as_tup_sub (List.length pats) t in - check_pats env ts pats T.Env.empty pat.at - with Invalid_argument _ -> + let ts = try T.as_tup_sub (List.length pats) t with Invalid_argument _ -> error env pat.at "tuple pattern cannot consume expected type\n %s" (T.string_of_typ_expand t) - ) + in check_pats env ts pats T.Env.empty pat.at | ObjP pfs -> - (try - let s, tfs = T.as_obj_sub "" t in - if s = T.Actor then error env pat.at "object pattern cannot destructure actors"; - check_pat_fields env tfs (List.stable_sort compare_pat_field pfs) T.Env.empty pat.at - with Invalid_argument _ -> - error env pat.at "object pattern cannot consume expected type\n %s" - (T.string_of_typ_expand t) - ) + let pfs' = List.stable_sort compare_pat_field pfs in + let s, tfs = + try T.as_obj_sub (List.map (fun (pf : pat_field) -> pf.it.id.it) pfs') t + with Invalid_argument _ -> + error env pat.at "object pattern cannot consume expected type\n %s" + (T.string_of_typ_expand t) + in + if not env.pre && s = T.Actor then + local_error env pat.at "object pattern cannot consume actor type\n %s" + (T.string_of_typ_expand t); + check_pat_fields env s tfs pfs' T.Env.empty pat.at | OptP pat1 -> - (try - let t1 = T.as_opt t in - check_pat env t1 pat1 - with Invalid_argument _ -> - error env pat.at "option pattern cannot consume expected type\n %s" - (T.string_of_typ_expand t) - ) + let t1 = try T.as_opt_sub t with Invalid_argument _ -> + error env pat.at "option pattern cannot consume expected type\n %s" + (T.string_of_typ_expand t) + in check_pat env t1 pat1 | TagP (id, pat1) -> - (try - let t1 = Lib.Option.value (T.lookup_val_field id.it (T.as_variant t)) in - check_pat env t1 pat1 - with Invalid_argument _ | Not_found -> - error env pat.at "variant pattern cannot consume expected type\n %s" - (T.string_of_typ_expand t) - ) + let t1 = + try + Lib.Option.value (T.lookup_val_field id.it (T.as_variant_sub id.it t)) + with Invalid_argument _ | Not_found -> + error env pat.at "variant pattern cannot consume expected type\n %s" + (T.string_of_typ_expand t) + in check_pat env t1 pat1 | AltP (pat1, pat2) -> let ve1 = check_pat env t pat1 in let ve2 = check_pat env t pat2 in if ve1 <> T.Env.empty || ve2 <> T.Env.empty then error env pat.at "variables are not allowed in pattern alternatives"; T.Env.empty - | ParP pat1 -> - check_pat env t pat1 - | _ -> - let t', ve = infer_pat env pat in + | AnnotP (pat1, typ) -> + let t' = check_typ env typ in if not (T.sub t t') then - error env pat.at "pattern of type\n %s\ncannot consume expected type\n %s" + error env pat.at + "pattern of type\n %s\ncannot consume expected type\n %s" (T.string_of_typ_expand t') (T.string_of_typ_expand t); - ve + check_pat env t pat1 + | ParP pat1 -> + check_pat env t pat1 + +(* +Consider: + + case (P : A) : B + + +(P : A) :<= B iff +1: B <: A P :<= B +2: A <: B P :<= A +3: B <: A P :<= A +4: A <: B P :<= B + +1 is implemented, allows + + case ({x} : {}) : {x} // type annotations are reversed for patterns + case (1 : Int) : Nat // type annotations are reversed for patterns + case (x : Int) : Nat // type annotations are reversed for patterns + +2 would allow + + case ({x} : {x}) : {} // unsound, x does not exist + +3 would allow + + case (-1 : Int) : Nat // breaks coverage checking + +4 would allow + + case (x : Nat) : Int // x is Int, harmless but misleading + +Alternative: pass in two types? +*) + and check_pats env ts pats ve at : Scope.val_env = - match pats, ts with + match ts, pats with | [], [] -> ve - | pat::pats', t::ts' -> + | t::ts', pat::pats' -> let ve1 = check_pat env t pat in let ve' = disjoint_union env at "duplicate binding for %s in pattern" ve ve1 in check_pats env ts' pats' ve' at - | [], ts -> + | ts, [] -> local_error env at "tuple pattern has %i fewer components than expected type" (List.length ts); ve - | ts, [] -> + | [], ts -> error env at "tuple pattern has %i more components than expected type" (List.length ts) -and check_pat_fields env tfs pfs ve at : Scope.val_env = - let repeated l = function - | [] -> None - | (pf : pat_field)::_ -> if l = pf.it.id.it then Some pf.at else None - in - match pfs, tfs with - | [], [] -> ve - | pf::pfs', T.{ lab; typ }::tfs' -> - (match compare pf.it.id.it lab with - | 0 -> +and check_pat_fields env s tfs pfs ve at : Scope.val_env = + match tfs, pfs with + | _, [] -> ve + | [], pf::_ -> + error env pf.at + "object field %s is not contained in expected type\n %s" + pf.it.id.it (T.string_of_typ (T.Obj (s, tfs))) + | T.{lab; typ = Typ _}::tfs', _ -> (* TODO: remove the namespace hack *) + check_pat_fields env s tfs' pfs ve at + | T.{lab; typ}::tfs', pf::pfs' -> + match compare pf.it.id.it lab with + | -1 -> check_pat_fields env s [] pfs ve at + | +1 -> check_pat_fields env s tfs' pfs ve at + | _ -> if T.is_mut typ then error env pf.at "cannot pattern match mutable field %s" lab; let ve1 = check_pat env typ pf.it.pat in let ve' = disjoint_union env at "duplicate binding for %s in pattern" ve ve1 in - (match repeated lab pfs' with - | None -> check_pat_fields env tfs' pfs' ve' at - | Some at -> error env at "duplicate field %s in object pattern" lab - ) - | c when c > 0 -> - check_pat_fields env tfs' pfs ve at - | _ -> - error env pf.at - "object pattern field %s is not contained in expected type" pf.it.id.it - ) - | [], _ -> ve - | pf::_, [] -> - error env pf.at - "object pattern field %s is not contained in expected type" pf.it.id.it + match pfs' with + | pf'::_ when pf'.it.id.it = lab -> + error env pf'.at "duplicate field %s in object pattern" lab + | _ -> check_pat_fields env s tfs' pfs' ve' at -and compare_pat_field {it={id = l1; pat; _};_} {it={id = l2; pat; _};_} = compare l1.it l2.it +and compare_pat_field pf1 pf2 = compare pf1.it.id.it pf2.it.id.it (* Objects *) diff --git a/src/as_ir/check_ir.ml b/src/as_ir/check_ir.ml index 3c1c367809b..1d01548dbcb 100644 --- a/src/as_ir/check_ir.ml +++ b/src/as_ir/check_ir.ml @@ -118,7 +118,7 @@ let check_shared env at t = "message argument is not sharable:\n %s" (T.string_of_typ_expand t) let check_concrete env at t = - check env at (T.is_concrete t) + check env at (T.concrete t) "message argument is not concrete:\n %s" (T.string_of_typ_expand t) let rec check_typ env typ : unit = @@ -304,12 +304,12 @@ let rec check_exp env (exp:Ir.exp) : unit = | LitE lit -> T.Prim (type_lit env lit exp.at) <: t | UnE (ot, op, exp1) -> - check (Operator.has_unop ot op) "unary operator is not defined for operand type"; + check (Operator.has_unop op ot) "unary operator is not defined for operand type"; check_exp env exp1; typ exp1 <: ot; ot <: t | BinE (ot, exp1, op, exp2) -> - check (Operator.has_binop ot op) "binary operator is not defined for operand type"; + check (Operator.has_binop op ot) "binary operator is not defined for operand type"; check_exp env exp1; check_exp env exp2; typ exp1 <: ot; @@ -322,7 +322,7 @@ let rec check_exp env (exp:Ir.exp) : unit = typ exp1 <: ot; T.Prim T.Text <: t | RelE (ot, exp1, op, exp2) -> - check (Operator.has_relop ot op) "relational operator is not defined for operand type"; + check (Operator.has_relop op ot) "relational operator is not defined for operand type"; check_exp env exp1; check_exp env exp2; typ exp1 <: ot; @@ -355,7 +355,7 @@ let rec check_exp env (exp:Ir.exp) : unit = check_exp env exp1; let t1 = typ exp1 in let sort, tfs = - try T.as_obj_sub n t1 with Invalid_argument _ -> + try T.as_obj_sub [n] t1 with Invalid_argument _ -> error env exp1.at "expected object type, but expression produces type\n %s" (T.string_of_typ_expand t1) in @@ -558,7 +558,7 @@ and check_cases env t_pat t cases = and check_case env t_pat t {it = {pat; exp}; _} = let ve = check_pat env pat in - check_sub env pat.at pat.note t_pat; + check_sub env pat.at t_pat pat.note; check_exp (adjoin_vals env ve) exp; check env pat.at (T.sub (typ exp) t) "bad case" @@ -610,7 +610,7 @@ and check_pat env pat : val_env = | WildP -> T.Env.empty | VarP id -> T.Env.singleton id pat.note | LitP NullLit -> - T.Prim T.Null <: t; + t <: T.Opt T.Any; T.Env.empty | LitP lit -> let t1 = T.Prim (type_lit env lit pat.at) in @@ -629,9 +629,9 @@ and check_pat env pat : val_env = let ve = check_pat env pat1 in t <: T.Opt pat1.note; ve - | TagP (i, pat1) -> + | TagP (l, pat1) -> let ve = check_pat env pat1 in - T.Variant [{T.lab = i; typ = pat1.note}] <: t; + check_pat_tag env t l pat1; ve | AltP (pat1, pat2) -> let ve1 = check_pat env pat1 in @@ -655,12 +655,16 @@ and check_pat_fields env t = List.iter (check_pat_field env t) and check_pat_field env t (pf : pat_field) = let lab = pf.it.name in let tf = T.{lab; typ=pf.it.pat.note} in - let s, tfs = T.as_obj_sub lab t in + let s, tfs = T.as_obj_sub [lab] t in let (<:) = check_sub env pf.it.pat.at in t <: T.Obj (s, [tf]); if T.is_mut (Lib.Option.value (T.lookup_val_field lab tfs)) then error env pf.it.pat.at "cannot match mutable field %s" lab +and check_pat_tag env t l pat = + let (<:) = check_sub env pat.at in + Lib.Option.value (T.lookup_val_field l (T.as_variant_sub l t)) <: pat.note + (* Objects *) and type_obj env s fs : T.typ = diff --git a/src/as_ir/construct.ml b/src/as_ir/construct.ml index d2a00812f82..66b7f6fa3f5 100644 --- a/src/as_ir/construct.ml +++ b/src/as_ir/construct.ml @@ -497,7 +497,7 @@ let forE pat exp1 exp2 = } *) let lab = fresh_id "done" () in let ty1 = exp1.note.note_typ in - let _, tfs = T.as_obj_sub "next" ty1 in + let _, tfs = T.as_obj_sub ["next"] ty1 in let tnxt = Lib.Option.value (T.lookup_val_field "next" tfs) in let nxt = fresh_var "nxt" tnxt in letE nxt (dotE exp1 (nameN "next") tnxt) ( diff --git a/src/as_types/call_conv.ml b/src/as_types/call_conv.ml index 8b479185886..aecb211d1ad 100644 --- a/src/as_types/call_conv.ml +++ b/src/as_types/call_conv.ml @@ -16,6 +16,8 @@ let call_conv_of_typ typ = match typ with | Func(sort, control, tbds, dom, res) -> { sort; control; n_args = List.length dom; n_res = List.length res } + | Non -> + { sort = Type.Local; control = Type.Returns; n_args = 1; n_res = 1 } | _ -> raise (Invalid_argument ("call_conv_of_typ " ^ string_of_typ typ)) let string_of_call_conv {sort;control;n_args;n_res} = diff --git a/src/as_types/type.ml b/src/as_types/type.ml index 9eb3704a5f1..0c13264190e 100644 --- a/src/as_types/type.ml +++ b/src/as_types/type.ml @@ -336,16 +336,21 @@ let as_prim_sub p t = match promote t with | Prim p' when p = p' -> () | Non -> () | _ -> invalid "as_prim_sub" -let as_obj_sub lab t = match promote t with +let as_obj_sub ls t = match promote t with | Obj (s, tfs) -> s, tfs - | Non -> Object Sharable, [{lab; typ = Non}] + | Non -> Object Sharable, List.map (fun l -> {lab = l; typ = Non}) ls | _ -> invalid "as_obj_sub" +let as_variant_sub l t = match promote t with + | Variant tfs -> tfs + | Non -> [{lab = l; typ = Non}] + | _ -> invalid "as_variant_sub" let as_array_sub t = match promote t with | Array t -> t | Non -> Non | _ -> invalid "as_array_sub" let as_opt_sub t = match promote t with | Opt t -> t + | Non -> Non | _ -> invalid "as_opt_sub" let as_tup_sub n t = match promote t with | Tup ts -> ts @@ -466,7 +471,8 @@ let avoid cons t = if cons = ConSet.empty then t else avoid' cons ConSet.empty t -(* Checking for concrete types *) + +(* Collecting type constructors *) let rec cons t cs = match t with @@ -497,29 +503,30 @@ let cons_kind k = | Abs (tbs, t) -> cons t (List.fold_right cons_bind tbs ConSet.empty) + (* Checking for concrete types *) -module TS = Set.Make (struct type t = typ let compare = compare end) +module S = Set.Make (struct type t = typ let compare = compare end) (* This check is a stop-gap measure until we have an IDL strategy that allows polymorphic types, see #250. It is not what we desire for ActorScript. *) -let is_concrete t = - let seen = ref TS.empty in (* break the cycles *) +let concrete t = + let seen = ref S.empty in (* break the cycles *) let rec go t = - TS.mem t !seen || + S.mem t !seen || begin - seen := TS.add t !seen; + seen := S.add t !seen; match t with | Var _ -> assert false - | (Prim _ | Any | Non | Shared | Pre) -> true + | Prim _ | Any | Non | Shared -> true | Con (c, ts) -> - begin match Con.kind c with + (match Con.kind c with | Abs _ -> false | Def (tbs,t) -> go (open_ ts t) (* TBR this may fail to terminate *) - end + ) | Array t -> go t | Tup ts -> List.for_all go ts | Func (s, c, tbs, ts1, ts2) -> @@ -533,25 +540,21 @@ let is_concrete t = | Mut t -> go t | Typ c -> assert false (* TBR *) | Serialized t -> go t + | Pre -> assert false end in go t -module M = Map.Make (struct type t = typ * typ let compare = compare end) -(* Forward declare - TODO: haul string_of_typ before the lub/glb business, if possible *) -let str = ref (fun _ -> failwith "") - (* Equivalence & Subtyping *) -module S = Set.Make (struct type t = typ * typ let compare = compare end) +module SS = Set.Make (struct type t = typ * typ let compare = compare end) let rel_list p rel eq xs1 xs2 = try List.for_all2 (p rel eq) xs1 xs2 with Invalid_argument _ -> false let rec rel_typ rel eq t1 t2 = - t1 == t2 || S.mem (t1, t2) !rel || begin - rel := S.add (t1, t2) !rel; + t1 == t2 || SS.mem (t1, t2) !rel || begin + rel := SS.add (t1, t2) !rel; match t1, t2 with | Pre, _ | _, Pre -> assert false @@ -609,12 +612,12 @@ let rec rel_typ rel eq t1 t2 = rel_typ rel eq t1' t2' | Opt t1', Shared -> rel_typ rel eq t1' Shared + | Prim Null, Opt t2' when rel != eq -> + true | Variant fs1, Variant fs2 -> rel_tags rel eq fs1 fs2 | Variant fs1, Shared -> rel_tags rel eq fs1 (List.map (fun f -> {f with typ = Shared}) fs1) - | Prim Null, Opt t2' when rel != eq -> - true | Tup ts1, Tup ts2 -> rel_list rel_typ rel eq ts1 ts2 | Tup ts1, Shared -> @@ -643,7 +646,7 @@ let rec rel_typ rel eq t1 t2 = | Serialized t1', Serialized t2' -> eq_typ rel eq t1' t2' (* TBR: eq or sub? Does it matter? *) | Typ c1, Typ c2 -> - Con.eq c1 c2 + Con.eq c1 c2 | _, _ -> false end @@ -677,7 +680,7 @@ and rel_tags rel eq tfs1 tfs2 = | 0 -> rel_typ rel eq tf1.typ tf2.typ && rel_tags rel eq tfs1' tfs2' - | 1 when rel != eq -> + | +1 when rel != eq -> rel_tags rel eq tfs1 tfs2' | _ -> false ) @@ -695,13 +698,13 @@ and rel_bind ts rel eq tb1 tb2 = and eq_typ rel eq t1 t2 = rel_typ eq eq t1 t2 and eq t1 t2 : bool = - let eq = ref S.empty in eq_typ eq eq t1 t2 + let eq = ref SS.empty in eq_typ eq eq t1 t2 and sub t1 t2 : bool = - rel_typ (ref S.empty) (ref S.empty) t1 t2 + rel_typ (ref SS.empty) (ref SS.empty) t1 t2 and eq_kind k1 k2 : bool = - let eq = ref S.empty in + let eq = ref SS.empty in match k1, k2 with | Def (tbs1, t1), Def (tbs2, t2) | Abs (tbs1, t1), Abs (tbs2, t2) -> @@ -712,8 +715,112 @@ and eq_kind k1 k2 : bool = | _ -> false +(* Compatibility *) + +let compatible_list p co xs1 xs2 = + try List.for_all2 (p co) xs1 xs2 with Invalid_argument _ -> false + +let rec compatible_typ co t1 t2 = + t1 == t2 || SS.mem (t1, t2) !co || begin + co := SS.add (t1, t2) !co; + match promote t1, promote t2 with + | (Pre | Serialized _), _ | _, (Pre | Serialized _) -> + assert false + | (Any | Shared), (Any | Shared) -> + true + | Non, (Any | Shared) | (Any | Shared), Non -> + false + | Non, _ | _, Non -> + true + | Prim p1, Prim p2 when p1 = p2 -> + true + | Prim (Nat | Int), Prim (Nat | Int) -> + true + | Array t1', Array t2' -> + compatible_typ co t1' t2' + | Tup ts1, Tup ts2 -> + compatible_list compatible_typ co ts1 ts2 + | Obj (s1, tfs1), Obj (s2, tfs2) -> + s1 = s2 && + compatible_fields co tfs1 tfs2 + | Opt t1', Opt t2' -> + compatible_typ co t1' t2' + | Prim Null, Opt _ | Opt _, Prim Null -> + true + | Variant tfs1, Variant tfs2 -> + compatible_tags co tfs1 tfs2 + | Async t1', Async t2' -> + compatible_typ co t1' t2' + | Func _, Func _ -> + true + | Typ _, Typ _ -> + true + | Mut t1', Mut t2' -> + compatible_typ co t1' t2' + | _, _ -> false + end + +and compatible_fields co tfs1 tfs2 = + (* Assume that tfs1 and tfs2 are sorted. *) + match tfs1, tfs2 with + | [], [] -> true + | tf1::tfs1', tf2::tfs2' -> + tf1.lab = tf2.lab && compatible_typ co tf1.typ tf2.typ && + compatible_fields co tfs1' tfs2' + | _, _ -> false + +and compatible_tags co tfs1 tfs2 = + (* Assume that tfs1 and tfs2 are sorted. *) + match tfs1, tfs2 with + | [], _ | _, [] -> true + | tf1::tfs1', tf2::tfs2' -> + match compare_field tf1 tf2 with + | -1 -> compatible_tags co tfs1' tfs2 + | +1 -> compatible_tags co tfs1 tfs2' + | _ -> compatible_typ co tf1.typ tf2.typ && compatible_tags co tfs1' tfs2' + +and compatible t1 t2 : bool = + compatible_typ (ref SS.empty) t1 t2 + + +let opaque t = compatible t Any + + +(* Inhabitance *) + +let rec inhabited_typ co t = + S.mem t !co || begin + co := S.add t !co; + match promote t with + | Pre | Serialized _ -> assert false + | Non -> false + | Any | Shared | Prim _ | Array _ | Opt _ | Async _ | Func _ | Typ _ -> true + | Mut t' -> inhabited_typ co t' + | Tup ts -> List.for_all (inhabited_typ co) ts + | Obj (_, tfs) -> List.for_all (inhabited_field co) tfs + | Variant tfs -> List.exists (inhabited_field co) tfs + | Var _ -> true (* TODO(rossberg): consider bound *) + | Con (c, ts) -> + match Con.kind c with + | Def (tbs, t') -> (* TBR this may fail to terminate *) + inhabited_typ co (open_ ts t') + | Abs (tbs, t') -> + inhabited_typ co t' + end + +and inhabited_field co tf = inhabited_typ co tf.typ + +and inhabited t : bool = inhabited_typ (ref S.empty) t + + (* Least upper bound and greatest lower bound *) +module M = Map.Make (struct type t = typ * typ let compare = compare end) + +(* Forward declare + TODO: haul string_of_typ before the lub/glb business, if possible *) +let str = ref (fun _ -> failwith "") + let rec lub' lubs glbs t1 t2 = if t1 == t2 then t1 else match M.find_opt (t1, t2) !lubs with @@ -910,7 +1017,7 @@ let string_of_sharing = function let rec string_of_typ_nullary vs = function | Pre -> "???" | Any -> "Any" - | Non -> "Non" + | Non -> "None" | Shared -> "Shared" | Prim p -> string_of_prim p | Var (s, i) -> (try string_of_var (List.nth vs i) with _ -> assert false) @@ -1038,7 +1145,7 @@ let rec string_of_typ_expand t = | Abs _ -> s | Def _ -> match normalize t with - | Prim _ | Any | Non -> s + | Prim _ | Any | Non | Shared -> s | t' -> s ^ " = " ^ string_of_typ_expand t' ) | _ -> s diff --git a/src/as_types/type.mli b/src/as_types/type.mli index d99db995cb4..abf9c2a4449 100644 --- a/src/as_types/type.mli +++ b/src/as_types/type.mli @@ -104,7 +104,8 @@ val as_serialized : typ -> typ val as_typ : typ -> con val as_prim_sub : prim -> typ -> unit -val as_obj_sub : string -> typ -> obj_sort * field list +val as_obj_sub : string list -> typ -> obj_sort * field list +val as_variant_sub : string -> typ -> field list val as_array_sub : typ -> typ val as_opt_sub : typ -> typ val as_tup_sub : int -> typ -> typ list @@ -145,8 +146,9 @@ exception Unavoidable of con val avoid : ConSet.t -> typ -> typ (* raise Unavoidable *) val avoid_cons : ConSet.t -> ConSet.t -> unit (* raise Unavoidable *) -val is_concrete : typ -> bool - +val opaque : typ -> bool +val concrete : typ -> bool +val inhabited : typ -> bool val span : typ -> int option @@ -161,6 +163,7 @@ val eq : typ -> typ -> bool val eq_kind : kind -> kind -> bool val sub : typ -> typ -> bool +val compatible : typ -> typ -> bool val lub : typ -> typ -> typ val glb : typ -> typ -> typ diff --git a/src/as_values/operator.ml b/src/as_values/operator.ml index 0aebd49aaa5..a95b3deac78 100644 --- a/src/as_values/operator.ml +++ b/src/as_values/operator.ml @@ -34,7 +34,7 @@ type relop = | LeOp (* x<=y *) | GeOp (* x>=y *) -let impossible _ = raise (Invalid_argument "impossible") +let impossible _ = raise (Invalid_argument "operator called for None") (* Unary operators *) @@ -55,7 +55,7 @@ let num_unop fint (fint8, fint16, fint32, fint64) wordops ffloat = function | T.Float -> fun v -> Float (ffloat (as_float v)) | t -> word_unop wordops t -let unop t op = +let unop op t = match t with | T.Prim p -> (match op with @@ -100,7 +100,7 @@ let num_binop fnat (fnat8, fnat16, fnat32, fnat64) fint (fint8, fint16, fint32, | T.Float -> fun v1 v2 -> Float (ffloat (as_float v1) (as_float v2)) | t -> word_binop fwords t -let binop t op = +let binop op t = match t with | T.Prim p -> (match op with @@ -157,7 +157,7 @@ let eq_relop fnat fnats fint fints fwords ffloat fchar ftext fnull fbool = funct | T.Bool -> fun v1 v2 -> Bool (fbool (as_bool v1) (as_bool v2)) | t -> ord_relop fnat fnats fint fints fwords ffloat fchar ftext t -let relop t op = +let relop op t = match t with | T.Prim p -> (match op with @@ -172,7 +172,11 @@ let relop t op = | _ -> raise (Invalid_argument "relop") -let has f t op = try ignore (f t op); true with Invalid_argument _ -> false -let has_unop t op = has unop t op -let has_binop t op = has binop t op -let has_relop t op = has relop t op +let has f op t = try ignore (f op t); true with Invalid_argument _ -> false +let has_unop op t = has unop op t +let has_binop op t = has binop op t +let has_relop op t = has relop op t + +let type_unop op t = if t = T.Prim T.Nat then T.Prim T.Int else t +let type_binop op t = t +let type_relop op t = t diff --git a/src/as_values/operator.mli b/src/as_values/operator.mli index 4c1150c4dd0..1e94f92bc70 100644 --- a/src/as_values/operator.mli +++ b/src/as_values/operator.mli @@ -34,10 +34,14 @@ type relop = | GeOp (* x>=y *) -val unop : typ -> unop -> (value -> value) (* raise Invalid_argument *) -val binop : typ -> binop -> (value -> value -> value) (* raise Invalid_argument *) -val relop : typ -> relop -> (value -> value -> value) (* raise Invalid_argument *) +val unop : unop -> typ -> (value -> value) (* raise Invalid_argument *) +val binop : binop -> typ -> (value -> value -> value) (* raise Invalid_argument *) +val relop : relop -> typ -> (value -> value -> value) (* raise Invalid_argument *) -val has_unop : typ -> unop -> bool -val has_binop : typ -> binop -> bool -val has_relop : typ -> relop -> bool +val has_unop : unop -> typ -> bool +val has_binop : binop -> typ -> bool +val has_relop : relop -> typ -> bool + +val type_unop : unop -> typ -> typ +val type_binop : binop -> typ -> typ +val type_relop : relop -> typ -> typ diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 9e6c341a9b7..421e56ce2be 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -984,7 +984,7 @@ module Tagged = struct (* like branch_default but the tag is known statically *) let branch env retty = function - | [] -> failwith "branch" + | [] -> G.i Unreachable | [_, code] -> G.i Drop ^^ code | (_, code) :: cases -> branch_default env retty code cases @@ -997,7 +997,7 @@ module Tagged = struct (* like branch_default_with but the tag is known statically *) let branch_with env retty = function - | [] -> failwith "branch_with" + | [] -> G.i Unreachable | [_, code] -> code | (_, code) :: cases -> let (set_o, get_o) = new_local env "o" in @@ -1879,7 +1879,7 @@ module Object = struct let is_mut_field env obj_type s = (* TODO: remove try once array and text accessors are separated *) try - let _, fields = Type.as_obj_sub "" obj_type in + let _, fields = Type.as_obj_sub [s] obj_type in Type.is_mut (Lib.Option.value (Type.lookup_val_field s fields)) with Invalid_argument _ -> false @@ -3712,6 +3712,7 @@ module StackRep = struct | Prim (Nat32 | Int32 | Word32) -> UnboxedWord32 | Prim (Nat8 | Nat16 | Int8 | Int16 | Word8 | Word16 | Char) -> Vanilla | Prim Text -> Vanilla + | Non -> Vanilla | p -> todo "of_type" (Arrange_ir.typ p) Vanilla let to_block_type env = function @@ -4563,6 +4564,8 @@ let compile_unop env t op = | NotOp, Type.Prim Type.(Word8 | Word16 | Word32 as ty) -> StackRep.of_type t, compile_unboxed_const (UnboxedSmallWord.mask_of_type ty) ^^ G.i (Binary (Wasm.Values.I32 I32Op.Xor)) + | _, Type.Non -> + SR.Vanilla, G.i Unreachable | _ -> (* NB: Must not use todo_trap_SR here, as the SR.t here is also passed to `compile_exp_as`, which does not take SR.Unreachable. *) @@ -4970,6 +4973,7 @@ let rec compile_binop env t op = sanitize_word_result ty)) | Type.Prim Type.Text, CatOp -> Text.concat env + | Type.Non, _ -> G.i Unreachable | _ -> todo_trap env "compile_binop" (Arrange_ops.binop op) ) @@ -4980,6 +4984,7 @@ let compile_eq env = function | Type.(Prim (Int64 | Nat64 | Word64)) -> G.i (Compare (Wasm.Values.I64 I64Op.Eq)) | Type.(Prim (Int8 | Nat8 | Word8 | Int16 | Nat16 | Word16 | Int32 | Nat32 | Word32 | Char)) -> G.i (Compare (Wasm.Values.I32 I32Op.Eq)) + | Type.Non -> G.i Unreachable | _ -> todo_trap env "compile_eq" (Arrange_ops.relop Operator.EqOp) let get_relops = Operator.(function @@ -5009,6 +5014,7 @@ let compile_relop env t op = G.i (Test (Wasm.Values.I32 I32Op.Eqz)) | Type.(Prim (Nat | Nat8 | Nat16 | Nat32 | Nat64 | Int | Int8 | Int16 | Int32 | Int64 | Word8 | Word16 | Word32 | Word64 | Char as t1)), op1 -> compile_comparison env t1 op1 + | Type.Non, _ -> G.i Unreachable | _ -> todo_trap env "compile_relop" (Arrange_ops.relop op) let compile_load_field env typ name = diff --git a/src/interpreter/interpret.ml b/src/interpreter/interpret.ml index 549844cf8e7..17e1ab1ca0f 100644 --- a/src/interpreter/interpret.ml +++ b/src/interpreter/interpret.ml @@ -359,11 +359,11 @@ and interpret_exp_mut env exp (k : V.value V.cont) = | UnE (ot, op, exp1) -> interpret_exp env exp1 (fun v1 -> - k (try Operator.unop !ot op v1 with Invalid_argument s -> trap exp.at "%s" s)) + k (try Operator.unop op !ot v1 with Invalid_argument s -> trap exp.at "%s" s)) | BinE (ot, exp1, op, exp2) -> interpret_exp env exp1 (fun v1 -> interpret_exp env exp2 (fun v2 -> - k (try Operator.binop !ot op v1 v2 with _ -> + k (try Operator.binop op !ot v1 v2 with _ -> trap exp.at "arithmetic overflow") ) ) @@ -375,7 +375,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = | RelE (ot, exp1, op, exp2) -> interpret_exp env exp1 (fun v1 -> interpret_exp env exp2 (fun v2 -> - k (Operator.relop !ot op v1 v2) + k (Operator.relop op !ot v1 v2) ) ) | TupE exps -> @@ -663,7 +663,7 @@ and match_pat pat v : val_env option = else None | SignP (op, lit) -> let t = T.as_immut pat.note in - match_pat {pat with it = LitP lit} (Operator.unop t op v) + match_pat {pat with it = LitP lit} (Operator.unop op t v) | TupP pats -> match_pats pats (V.as_tup v) V.Env.empty | ObjP pfs -> diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index 6302d3afdac..f35d85f3b2a 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -301,7 +301,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = | LitE lit -> k (interpret_lit env lit) | UnE (ot, op, exp1) -> - interpret_exp env exp1 (fun v1 -> k (try Operator.unop ot op v1 with Invalid_argument s -> trap exp.at "%s" s)) + interpret_exp env exp1 (fun v1 -> k (try Operator.unop op ot v1 with Invalid_argument s -> trap exp.at "%s" s)) | ShowE (ot, exp1) -> interpret_exp env exp1 (fun v -> if Show.can_show ot @@ -310,14 +310,14 @@ and interpret_exp_mut env exp (k : V.value V.cont) = | BinE (ot, exp1, op, exp2) -> interpret_exp env exp1 (fun v1 -> interpret_exp env exp2 (fun v2 -> - k (try Operator.binop ot op v1 v2 with _ -> + k (try Operator.binop op ot v1 v2 with _ -> trap exp.at "arithmetic overflow") ) ) | RelE (ot, exp1, op, exp2) -> interpret_exp env exp1 (fun v1 -> interpret_exp env exp2 (fun v2 -> - k (Operator.relop ot op v1 v2) + k (Operator.relop op ot v1 v2) ) ) | TupE exps -> diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 8d1fb562b9b..0072520ae13 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -27,8 +27,7 @@ let falseE : Ir.exp = boolE false let apply_sign op l = Syntax.(match op, l with | PosOp, l -> l - | NegOp, NatLit n -> NatLit (Value.Nat.sub Value.Nat.zero n) - | NegOp, IntLit n -> IntLit (Value.Int.sub Value.Int.zero n) + | NegOp, (NatLit n | IntLit n) -> IntLit (Value.Int.sub Value.Int.zero n) | NegOp, Int8Lit n -> Int8Lit (Value.Int_8.sub Value.Int_8.zero n) | NegOp, Int16Lit n -> Int16Lit (Value.Int_16.sub Value.Int_16.zero n) | NegOp, Int32Lit n -> Int32Lit (Value.Int_32.sub Value.Int_32.zero n) @@ -79,7 +78,7 @@ and exp' at note = function | S.DotE (e, x) when T.is_prim T.Text e.note.S.note_typ -> (text_dotE x.it (exp e)).it | S.DotE (e, x) -> - begin match T.as_obj_sub x.it e.note.S.note_typ with + begin match T.as_obj_sub [x.it] e.note.S.note_typ with | T.Actor, _ -> I.ActorDotE (exp e, x.it) | _ -> I.DotE (exp e, x.it) end @@ -91,9 +90,12 @@ and exp' at note = function | S.FuncE (name, s, tbs, p, ty_opt, e) -> let cc = Call_conv.call_conv_of_typ note.I.note_typ in let args, wrap = to_args cc p in - let ty = match ty_opt with Some ty -> ty.note | None -> T.Tup [] in + let _, _, _, ty = T.as_func_sub s.it (List.length tbs) note.I.note_typ in + let tbs' = typ_binds tbs in + let vars = List.map (fun (tb : I.typ_bind) -> T.Con (tb.it.I.con, [])) tbs' in + let ty = T.open_ vars ty in let tys = if cc.Call_conv.n_res = 1 then [ty] else T.as_seq ty in - I.FuncE (name, cc, typ_binds tbs, args, tys, wrap (exp e)) + I.FuncE (name, cc, tbs', args, tys, wrap (exp e)) | S.CallE (e1, inst, e2) -> let t = e1.Source.note.S.note_typ in if T.is_non t diff --git a/test/fail/ok/actor-match.tc.ok b/test/fail/ok/actor-match.tc.ok index dc155ec9176..215e094f045 100644 --- a/test/fail/ok/actor-match.tc.ok +++ b/test/fail/ok/actor-match.tc.ok @@ -1 +1,2 @@ -actor-match.as:7.8-7.14: type error, object pattern cannot destructure actors +actor-match.as:7.8-7.14: type error, object pattern cannot consume actor type + actor {f : shared () -> (); g : shared () -> ()} diff --git a/test/fail/ok/objpat-infer.tc.ok b/test/fail/ok/objpat-infer.tc.ok index bcc67bc49e3..d2a44371dd2 100644 --- a/test/fail/ok/objpat-infer.tc.ok +++ b/test/fail/ok/objpat-infer.tc.ok @@ -1,4 +1,5 @@ -objpat-infer.as:3.36-3.37: type error, object pattern field a is not contained in expected type +objpat-infer.as:3.36-3.37: type error, object field a is not contained in expected type + shared {} objpat-infer.as:15.17-15.21: type error, shared function has non-shared parameter type {} objpat-infer.as:20.14-20.23: type error, expression of type diff --git a/test/fail/ok/pat-inconsistent.tc.ok b/test/fail/ok/pat-inconsistent.tc.ok new file mode 100644 index 00000000000..f0a70077b07 --- /dev/null +++ b/test/fail/ok/pat-inconsistent.tc.ok @@ -0,0 +1,114 @@ +pat-inconsistent.as:6.31-6.44: warning, this pattern is never matched +pat-inconsistent.as:7.34-7.50: warning, this pattern is never matched +pat-inconsistent.as:9.20-9.22: warning, this pattern is never matched +pat-inconsistent.as:10.20-10.24: warning, this pattern is never matched +pat-inconsistent.as:11.20-11.30: warning, this pattern is never matched +pat-inconsistent.as:2.13-2.21: warning, this pattern does not cover all possible values +pat-inconsistent.as:3.13-3.22: warning, this pattern does not cover all possible values +pat-inconsistent.as:5.13-5.29: warning, this pattern does not cover all possible values +pat-inconsistent.as:8.13-8.33: warning, this pattern does not cover all possible values +pat-inconsistent.as:16.16-16.24: type error, pattern branches have incompatible types, +left consumes + Nat +right consumes + Float +pat-inconsistent.as:17.16-17.23: type error, pattern branches have incompatible types, +left consumes + Nat +right consumes + Text +pat-inconsistent.as:18.16-18.26: type error, pattern branches have incompatible types, +left consumes + Bool +right consumes + Text +pat-inconsistent.as:19.16-19.23: type error, pattern branches have incompatible types, +left consumes + Nat +right consumes + () +pat-inconsistent.as:20.16-20.23: type error, pattern branches have incompatible types, +left consumes + Nat +right consumes + {} +pat-inconsistent.as:21.16-21.31: type error, pattern branches have incompatible types, +left consumes + Nat +right consumes + Text +pat-inconsistent.as:22.16-22.46: type error, pattern branches have incompatible types, +left consumes + {a : Int} +right consumes + {b : Nat} +pat-inconsistent.as:23.16-23.40: type error, pattern branches have incompatible types, +left consumes + Int8 +right consumes + Nat8 +pat-inconsistent.as:24.16-24.36: type error, pattern branches have incompatible types, +left consumes + (Text, Nat) +right consumes + (Text, Float) +pat-inconsistent.as:25.16-25.50: type error, pattern branches have incompatible types, +left consumes + (Int16, Text) +right consumes + (Nat16, Text) +pat-inconsistent.as:26.16-26.28: type error, pattern branches have incompatible types, +left consumes + {#A} +right consumes + {#A : Text} +pat-inconsistent.as:27.16-27.31: type error, pattern branches have incompatible types, +left consumes + {#A : Nat} +right consumes + {#A : Text} +pat-inconsistent.as:29.16-29.30: type error, pattern branches have incompatible types, +left consumes + Nat +right consumes + Any +pat-inconsistent.as:30.16-30.35: type error, pattern branches have incompatible types, +left consumes + Shared +right consumes + Float +pat-inconsistent.as:31.16-31.31: type error, pattern branches have incompatible types, +left consumes + () +right consumes + Any +pat-inconsistent.as:32.19-32.32: type error, pattern branches have incompatible types, +left consumes + Text +right consumes + A/18 +pat-inconsistent.as:33.16-33.40: type error, pattern branches have incompatible types, +left consumes + Any +right consumes + [Nat] +pat-inconsistent.as:34.16-34.43: type error, pattern branches have incompatible types, +left consumes + Any +right consumes + () -> () +pat-inconsistent.as:35.16-35.40: type error, pattern branches have incompatible types, +left consumes + (Text, Nat) +right consumes + (Text, Any) +pat-inconsistent.as:36.16-36.33: type error, pattern branches have incompatible types, +left consumes + {#A} +right consumes + {#A : Any} +pat-inconsistent.as:37.16-37.36: type error, pattern branches have incompatible types, +left consumes + {#A : Nat} +right consumes + {#A : Any} diff --git a/test/fail/ok/pat-subtyping-fail.tc.ok b/test/fail/ok/pat-subtyping-fail.tc.ok new file mode 100644 index 00000000000..9779245d9ea --- /dev/null +++ b/test/fail/ok/pat-subtyping-fail.tc.ok @@ -0,0 +1,92 @@ +pat-subtyping-fail.as:4.9-4.11: type error, operator cannot consume expected type + Nat +pat-subtyping-fail.as:8.9-8.11: type error, operator cannot consume expected type + Nat +pat-subtyping-fail.as:13.13-13.15: type error, operator cannot consume expected type + Nat +pat-subtyping-fail.as:17.18-17.20: type error, operator cannot consume expected type + Nat +pat-subtyping-fail.as:22.21-22.23: type error, operator cannot consume expected type + Nat +pat-subtyping-fail.as:26.26-26.28: type error, operator cannot consume expected type + Nat +pat-subtyping-fail.as:31.11-31.13: type error, operator cannot consume expected type + Nat +pat-subtyping-fail.as:35.11-35.13: type error, operator cannot consume expected type + Nat +pat-subtyping-fail.as:39.11-39.13: type error, operator cannot consume expected type + Nat +pat-subtyping-fail.as:44.12-44.14: type error, operator cannot consume expected type + Nat +pat-subtyping-fail.as:48.12-48.14: type error, operator cannot consume expected type + Nat +pat-subtyping-fail.as:52.12-52.14: type error, operator cannot consume expected type + Nat +pat-subtyping-fail.as:57.9-57.16: type error, pattern of type + Nat +cannot consume expected type + Int +pat-subtyping-fail.as:61.9-61.23: type error, pattern of type + (Nat, Nat) +cannot consume expected type + (Int, Int) +pat-subtyping-fail.as:64.9-64.28: type error, pattern of type + (Nat, Nat) +cannot consume expected type + (Int, Int) +pat-subtyping-fail.as:67.9-67.16: type error, pattern of type + Nat +cannot consume expected type + Int +pat-subtyping-fail.as:71.9-71.31: type error, pattern of type + {a : Nat; b : Nat} +cannot consume expected type + {a : Int; b : Int} +pat-subtyping-fail.as:74.9-74.36: type error, pattern of type + {a : Nat; b : Nat} +cannot consume expected type + {a : Int; b : Int} +pat-subtyping-fail.as:77.13-77.20: type error, pattern of type + Nat +cannot consume expected type + Int +pat-subtyping-fail.as:80.9-80.31: type error, pattern of type + {a : Nat; b : Nat} +cannot consume expected type + {a : Nat} +pat-subtyping-fail.as:83.9-83.36: type error, pattern of type + {a : Nat; b : Nat} +cannot consume expected type + {a : Nat} +pat-subtyping-fail.as:86.9-86.31: type error, pattern of type + {a : Nat; b : Nat} +cannot consume expected type + {} +pat-subtyping-fail.as:89.9-89.36: type error, pattern of type + {a : Nat; b : Nat} +cannot consume expected type + {} +pat-subtyping-fail.as:94.9-94.12: type error, option pattern cannot consume expected type + Null +pat-subtyping-fail.as:97.9-97.20: type error, pattern of type + Null +cannot consume expected type + ?Nat +pat-subtyping-fail.as:101.9-101.18: type error, pattern of type + ?Nat +cannot consume expected type + ?Int +pat-subtyping-fail.as:105.11-105.18: type error, pattern of type + Nat +cannot consume expected type + Int +pat-subtyping-fail.as:110.9-110.13: type error, variant pattern cannot consume expected type + {#} +pat-subtyping-fail.as:113.9-113.26: type error, pattern of type + {#A : Nat} +cannot consume expected type + {#A : Nat; #B} +pat-subtyping-fail.as:117.9-117.18: type error, pattern of type + {#B} +cannot consume expected type + {#A : Nat; #B} diff --git a/test/fail/pat-inconsistent.as b/test/fail/pat-inconsistent.as new file mode 100644 index 00000000000..04b5cb06712 --- /dev/null +++ b/test/fail/pat-inconsistent.as @@ -0,0 +1,37 @@ +// Okay joins +let _ = func(1 or 2) {}; +let _ = func(1 or -1) {}; +let _ = func(1 or (_ : Int)) {}; +let _ = func((1 : Int) or 2) {}; +let _ = func({a = _ : Int} or {a = _ : Nat}) {}; +let _ = func((_ : Int -> Int) or (_ : Nat -> Nat)) {}; +let _ = func((-1, 2) or (2, -1)) {}; +let _ = func(#A or #A) {}; +let _ = func(#A or #A()) {}; +let _ = func(#A or #A(_ : ())) {}; +let _ = func(#A(5) or #A(_ : Int)) {}; +let _ = func(#A or #B(_ : Nat)) {}; + +// Bogus joins +{ let _ = func(1 or 1.0) {} }; +{ let _ = func(1 or "") {} }; +{ let _ = func(true or "") {} }; +{ let _ = func(1 or ()) {} }; +{ let _ = func(1 or {}) {} }; +{ let _ = func(1 or (_ : Text)) {} }; +{ let _ = func({a = _ : Int} or {b = _ : Nat}) {} }; +{ let _ = func((_ : Int8) or (_ : Nat8)) {} }; +{ let _ = func(("", 1) or ("", 1.0)) {} }; +{ let _ = func((_ : Int16, "") or (_ : Nat16, "")) {} }; +{ let _ = func(#A or #A("")) {}; }; +{ let _ = func(#A(0) or #A("")) {}; }; + +{ let _ = func(1 or (_ : Any)) {} }; +{ let _ = func((_ : Shared) or 1.4) {} }; +{ let _ = func(() or (_ : Any)) {} }; +{ let _ = func("" or (_ : A)) {} }; +{ let _ = func((_ : Any) or (_ : [Nat])) {} }; +{ let _ = func((_ : Any) or (_ : () -> ())) {} }; +{ let _ = func(("", 1) or ("", _ : Any)) {} }; +{ let _ = func(#A or #A(_ : Any)) {}; }; +{ let _ = func(#A(5) or #A(_ : Any)) {}; }; diff --git a/test/fail/pat-subtyping-fail.as b/test/fail/pat-subtyping-fail.as new file mode 100644 index 00000000000..e0ed59ec39c --- /dev/null +++ b/test/fail/pat-subtyping-fail.as @@ -0,0 +1,119 @@ +func magic() : None = magic(); + +switch (magic () : Nat) { + case (-1) {}; + case _ {}; +}; +switch (magic () : Nat) { + case (-1 : Int) {}; + case _ {}; +}; + +switch (magic () : (Nat, Nat)) { + case ((1, -2) : (Int, Int)) {}; + case _ {}; +}; +switch (magic () : (Nat, Nat)) { + case (1 : Int, -2 : Int) {}; + case _ {}; +}; + +switch (magic () : {a : Nat; b : Nat}) { + case ({a = 1; b = -2} : {a : Int; b : Int}) {}; + case _ {}; +}; +switch (magic () : {a : Nat; b : Nat}) { + case {a = 1 : Int; b = -2 : Int} {}; + case _ {}; +}; + +switch (magic () : ?Nat) { + case (? -1) {}; + case _ {}; +}; +switch (magic () : ?Nat) { + case (? -1 : ?Int) {}; + case _ {}; +}; +switch (magic () : ?Nat) { + case (?(-1 : Int)) {}; + case _ {}; +}; + +switch (magic () : {#A : Nat; #B}) { + case (#A(-1)) {}; + case _ {}; +}; +switch (magic () : {#A : Nat; #B}) { + case (#A(-1 : Int)) {}; + case _ {}; +}; +switch (magic () : {#A : Nat; #B}) { + case (#A(-1) : {#A : Int; #B}) {}; + case _ {}; +}; + +switch (magic () : Int) { + case (n : Nat) {}; +}; + +switch (magic () : (Int, Int)) { + case (p : (Nat, Nat)) {}; +}; +switch (magic () : (Int, Int)) { + case ((x, y) : (Nat, Nat)) {}; +}; +switch (magic () : (Int, Int)) { + case (x : Nat, y : Nat) {}; +}; + +switch (magic () : {a : Int; b : Int}) { + case (r : {a : Nat; b : Nat}) {}; +}; +switch (magic () : {a : Int; b : Int}) { + case ({a; b} : {a : Nat; b : Nat}) {}; +}; +switch (magic () : {a : Int; b : Int}) { + case {a = _ : Nat; b = _ : Nat} {}; +}; +switch (magic () : {a : Nat}) { + case (r : {a : Nat; b : Nat}) {}; +}; +switch (magic () : {a : Nat}) { + case ({a; b} : {a : Nat; b : Nat}) {}; +}; +switch (magic () : {}) { + case (r : {a : Nat; b : Nat}) {}; +}; +switch (magic () : {}) { + case ({a; b} : {a : Nat; b : Nat}) {}; +}; + +switch (magic () : Null) { + case (null) {}; + case (? _) {}; +}; +switch (magic () : ?Nat) { + case (null : Null) {}; + case _ {}; +}; +switch (magic () : ?Int) { + case (?n : ?Nat) {}; + case null {}; +}; +switch (magic () : ?Int) { + case (?(_ : Nat)) {}; + case _ {}; +}; + +switch (magic () : {#}) { + case (#A _ : {#A : Nat; #B}) {}; // redundant +}; +switch (magic () : {#A : Nat; #B}) { + case (#A _ : {#A : Nat}) {}; + case _ {}; +}; +switch (magic () : {#A : Nat; #B}) { + case (#B : {#B}) {}; + case _ {}; +}; diff --git a/test/repl/ok/stateful.stderr.ok b/test/repl/ok/stateful.stderr.ok index 1087bd78526..72a3f26c62e 100644 --- a/test/repl/ok/stateful.stderr.ok +++ b/test/repl/ok/stateful.stderr.ok @@ -1,4 +1,5 @@ stdin:2.9-2.17: syntax error, unclosed text literal stdin:2.9-2.17: type error, operator not defined for operand types - Nat and + Nat +and Bool diff --git a/test/repl/ok/type-lub-repl.stdout.ok b/test/repl/ok/type-lub-repl.stdout.ok index 7c6140771e6..60f200a9828 100644 --- a/test/repl/ok/type-lub-repl.stdout.ok +++ b/test/repl/ok/type-lub-repl.stdout.ok @@ -6,7 +6,7 @@ ActorScript 0.1 interpreter > [(12, -1), (-42, 25)] : [(Int, Int)] > [-1, 25] : [Int] > [[-42], [25]] : [[Int]] -> [func, func] : [(Non -> Int)] +> [func, func] : [(None -> Int)] > [func, func] : [([Nat] -> Int)] > 3 : Int > -42 : Int diff --git a/test/run-dfinity/shared-object.as b/test/run-dfinity/shared-object.as index d65e633483f..10adf637b5a 100644 --- a/test/run-dfinity/shared-object.as +++ b/test/run-dfinity/shared-object.as @@ -4,9 +4,9 @@ let foo : Shob = shared { a = 17; b = shared { c = ?25 } }; // check whether we can pattern match shared objects -shared func baz (sh : Shob) : async Int = async (switch sh { - case { a; b = { c = null } } a; - case { a; b = { c = ?c } } (a + c) +shared func baz(sh : Shob) : async Int = async (switch sh { + case {a; b = {c = null}} a; + case {a; b = {c = ?c}} (a + c) }); async { diff --git a/test/run/coverage.as b/test/run/coverage.as index 3681301d546..f927a1471f7 100644 --- a/test/run/coverage.as +++ b/test/run/coverage.as @@ -34,39 +34,67 @@ func f() { switch (0, 0) { case (_, (6 or _)) {}; case _ {} }; switch (0, 0) { case (0, _) {}; case (_, 0) {} }; switch (0, 0) { case (0, _) {}; case (_, 0) {}; case _ {} }; + switch (object {a = 0; b = 0}) { case {a = _; b = _} {}; case {a = _; b = 6} {} }; + switch (object {a = 0; b = 0}) { case {} {}; case {b = 6} {} }; + switch (object {a = 0; b = 0}) { case {a = _; b = 6 or _} {}; case _ {} }; + switch (object {a = 0; b = 0}) { case {b = 6 or _} {}; case _ {} }; + switch (object {a = 0; b = 0}) { case {a = 0} {}; case {b = 0} {} }; + switch (object {a = 0; b = 0}) { case {a = 0} {}; case {b = 0} {}; case {} {} }; + switch (object {a = true}) { case {a = true} {}; case {a = false} {} }; + switch (#a 6 : {#a : Nat; #b : Nat}) { case (#a _) {}; case (#b _) {} }; + switch (#a 6 : {#a : Nat; #b : Nat}) { case (#a _) {}; case (#b 6) {} }; + switch (#a 6 : {#a : Nat; #b : Nat}) { case (#a _) {}; case (#a 5) {}; case (#b _) {} }; + switch (#a 6 : {#a : Nat; #b : Nat}) { case (#a _) {} }; + switch (#a 6 : {#a : Nat; #b : Nat}) { case (#b _) {} }; + switch (#a 5) { case (#a _) {} }; + + func empty() : None = empty(); + switch (empty()) {}; + switch (empty() : {#}) {}; + switch (empty() : {a : Nat; b : None}) {}; + switch (empty() : {a : Nat; b : {#}}) {}; + switch (empty() : {#a : None}) {}; + switch (empty() : {#a : {#}}) {}; + + switch (empty()) { case _ {} }; + switch (empty() : {#}) { case _ {} }; + switch (empty() : {a : Nat; b : None}) { case _ {} }; + switch (empty() : {a : Nat; b : {#}}) { case _ {} }; + switch (empty() : {#a : None}) { case _ {} }; + switch (empty() : {#a : {#}}) { case _ {} }; }; type Tree = {#leaf : Int; #branch : (Tree, Tree)}; -// leaf is not fully covered and branch is covered twice +// Leaf is not fully covered and branch is covered twice func size(t : Tree) : Nat { switch t { - case (#leaf 3) 1; - case (#branch(t1, t2)) { 1 + size(t1) + size(t2) }; - case (#branch(t1, t2)) { 1 + size(t1) + size(t2) }; + case (#leaf 3) 1; + case (#branch(t1, t2)) { 1 + size(t1) + size(t2) }; + case (#branch(t1, t2)) { 1 + size(t1) + size(t2) }; } }; -// the following is fully covered +// The following is fully covered func size1(t : Tree) : Nat { switch t { - case (#leaf 3) 1; - case (#branch(t1, t2)) { 1 + size1(t1) + size1(t2) }; - case (#leaf _) 1; + case (#leaf 3) 1; + case (#branch(t1, t2)) { 1 + size1(t1) + size1(t2) }; + case (#leaf _) 1; } }; -// example from Sestoft's paper -// ML pattern match compilation and partial evaluation -type Lam = - { #va : Int - ; #lam : (Int, Lam) - ; #app : (Lam, Lam) - ; #le : (Int, Lam, Lam) - }; +// Example from Sestoft's paper +// "ML pattern match compilation and partial evaluation" +type Lam = { + #va : Int; + #lam : (Int, Lam); + #app : (Lam, Lam); + #le : (Int, Lam, Lam); +}; -func test (t : Lam) : Nat = switch (t) { +func test(t : Lam) : Nat = switch (t) { case (#va x) 111; case (#lam(x, #va y)) 222; case (#lam(x, #lam(y, z))) 333; @@ -82,4 +110,4 @@ func test (t : Lam) : Nat = switch (t) { case (#le(_, _, _)) 2300; }; -assert (test (#le(1, #va 0, #app(#va 0, #va 1))) == 999) +assert (test(#le(1, #va 0, #app(#va 0, #va 1))) == 999); diff --git a/test/run/ir-pat-subtype.as b/test/run/ir-pat-subtype.as index 17680076560..0fc6bad58f4 100644 --- a/test/run/ir-pat-subtype.as +++ b/test/run/ir-pat-subtype.as @@ -66,14 +66,13 @@ func v1(vl : { #a : L }) : {#a:U} = switch vl { case (vu : { #a : U }) vu; }; -let (#a {} or _)= v1(#a l); +let (#a {})= v1(#a l); func v2(vl : { #a : L }) : { #a : U } = switch vl { case (#a u) #a u; - case _ vl; }; -let (#a {} or _) = v2(#a l); +let (#a {}) = v2(#a l); // alternative patterns diff --git a/test/run/ok/coverage.run-ir.ok b/test/run/ok/coverage.run-ir.ok index c03ff704735..a273de79859 100644 --- a/test/run/ok/coverage.run-ir.ok +++ b/test/run/ok/coverage.run-ir.ok @@ -13,8 +13,19 @@ coverage.as:31.25-31.34: warning, this case is never reached coverage.as:32.43-32.44: warning, this pattern is never matched coverage.as:33.35-33.49: warning, this case is never reached coverage.as:34.42-34.51: warning, this case is never reached -coverage.as:47.3-47.53: warning, this case is never reached -coverage.as:79.3-79.52: warning, this case is never reached +coverage.as:37.60-37.82: warning, this case is never reached +coverage.as:38.48-38.63: warning, this case is never reached +coverage.as:39.65-39.74: warning, this case is never reached +coverage.as:40.58-40.67: warning, this case is never reached +coverage.as:46.58-46.72: warning, this case is never reached +coverage.as:59.22-59.31: warning, this case is never reached +coverage.as:60.28-60.37: warning, this case is never reached +coverage.as:61.49-61.50: warning, this pattern is never matched +coverage.as:62.48-62.49: warning, this pattern is never matched +coverage.as:63.41-63.42: warning, this pattern is never matched +coverage.as:64.40-64.41: warning, this pattern is never matched +coverage.as:75.5-75.55: warning, this case is never reached +coverage.as:107.3-107.52: warning, this case is never reached coverage.as:4.7-4.8: warning, this pattern does not cover all possible values coverage.as:5.7-5.15: warning, this pattern does not cover all possible values coverage.as:9.7-9.9: warning, this pattern does not cover all possible values @@ -26,4 +37,8 @@ coverage.as:23.3-23.25: warning, the cases in this switch do not cover all possi coverage.as:24.3-24.36: warning, the cases in this switch do not cover all possible values coverage.as:32.3-32.50: warning, the cases in this switch do not cover all possible values coverage.as:35.3-35.51: warning, the cases in this switch do not cover all possible values -coverage.as:44.3-48.4: warning, the cases in this switch do not cover all possible values +coverage.as:41.3-41.70: warning, the cases in this switch do not cover all possible values +coverage.as:45.3-45.74: warning, the cases in this switch do not cover all possible values +coverage.as:47.3-47.58: warning, the cases in this switch do not cover all possible values +coverage.as:48.3-48.58: warning, the cases in this switch do not cover all possible values +coverage.as:72.3-76.4: warning, the cases in this switch do not cover all possible values diff --git a/test/run/ok/coverage.run-low.ok b/test/run/ok/coverage.run-low.ok index c03ff704735..a273de79859 100644 --- a/test/run/ok/coverage.run-low.ok +++ b/test/run/ok/coverage.run-low.ok @@ -13,8 +13,19 @@ coverage.as:31.25-31.34: warning, this case is never reached coverage.as:32.43-32.44: warning, this pattern is never matched coverage.as:33.35-33.49: warning, this case is never reached coverage.as:34.42-34.51: warning, this case is never reached -coverage.as:47.3-47.53: warning, this case is never reached -coverage.as:79.3-79.52: warning, this case is never reached +coverage.as:37.60-37.82: warning, this case is never reached +coverage.as:38.48-38.63: warning, this case is never reached +coverage.as:39.65-39.74: warning, this case is never reached +coverage.as:40.58-40.67: warning, this case is never reached +coverage.as:46.58-46.72: warning, this case is never reached +coverage.as:59.22-59.31: warning, this case is never reached +coverage.as:60.28-60.37: warning, this case is never reached +coverage.as:61.49-61.50: warning, this pattern is never matched +coverage.as:62.48-62.49: warning, this pattern is never matched +coverage.as:63.41-63.42: warning, this pattern is never matched +coverage.as:64.40-64.41: warning, this pattern is never matched +coverage.as:75.5-75.55: warning, this case is never reached +coverage.as:107.3-107.52: warning, this case is never reached coverage.as:4.7-4.8: warning, this pattern does not cover all possible values coverage.as:5.7-5.15: warning, this pattern does not cover all possible values coverage.as:9.7-9.9: warning, this pattern does not cover all possible values @@ -26,4 +37,8 @@ coverage.as:23.3-23.25: warning, the cases in this switch do not cover all possi coverage.as:24.3-24.36: warning, the cases in this switch do not cover all possible values coverage.as:32.3-32.50: warning, the cases in this switch do not cover all possible values coverage.as:35.3-35.51: warning, the cases in this switch do not cover all possible values -coverage.as:44.3-48.4: warning, the cases in this switch do not cover all possible values +coverage.as:41.3-41.70: warning, the cases in this switch do not cover all possible values +coverage.as:45.3-45.74: warning, the cases in this switch do not cover all possible values +coverage.as:47.3-47.58: warning, the cases in this switch do not cover all possible values +coverage.as:48.3-48.58: warning, the cases in this switch do not cover all possible values +coverage.as:72.3-76.4: warning, the cases in this switch do not cover all possible values diff --git a/test/run/ok/coverage.run.ok b/test/run/ok/coverage.run.ok index c03ff704735..a273de79859 100644 --- a/test/run/ok/coverage.run.ok +++ b/test/run/ok/coverage.run.ok @@ -13,8 +13,19 @@ coverage.as:31.25-31.34: warning, this case is never reached coverage.as:32.43-32.44: warning, this pattern is never matched coverage.as:33.35-33.49: warning, this case is never reached coverage.as:34.42-34.51: warning, this case is never reached -coverage.as:47.3-47.53: warning, this case is never reached -coverage.as:79.3-79.52: warning, this case is never reached +coverage.as:37.60-37.82: warning, this case is never reached +coverage.as:38.48-38.63: warning, this case is never reached +coverage.as:39.65-39.74: warning, this case is never reached +coverage.as:40.58-40.67: warning, this case is never reached +coverage.as:46.58-46.72: warning, this case is never reached +coverage.as:59.22-59.31: warning, this case is never reached +coverage.as:60.28-60.37: warning, this case is never reached +coverage.as:61.49-61.50: warning, this pattern is never matched +coverage.as:62.48-62.49: warning, this pattern is never matched +coverage.as:63.41-63.42: warning, this pattern is never matched +coverage.as:64.40-64.41: warning, this pattern is never matched +coverage.as:75.5-75.55: warning, this case is never reached +coverage.as:107.3-107.52: warning, this case is never reached coverage.as:4.7-4.8: warning, this pattern does not cover all possible values coverage.as:5.7-5.15: warning, this pattern does not cover all possible values coverage.as:9.7-9.9: warning, this pattern does not cover all possible values @@ -26,4 +37,8 @@ coverage.as:23.3-23.25: warning, the cases in this switch do not cover all possi coverage.as:24.3-24.36: warning, the cases in this switch do not cover all possible values coverage.as:32.3-32.50: warning, the cases in this switch do not cover all possible values coverage.as:35.3-35.51: warning, the cases in this switch do not cover all possible values -coverage.as:44.3-48.4: warning, the cases in this switch do not cover all possible values +coverage.as:41.3-41.70: warning, the cases in this switch do not cover all possible values +coverage.as:45.3-45.74: warning, the cases in this switch do not cover all possible values +coverage.as:47.3-47.58: warning, the cases in this switch do not cover all possible values +coverage.as:48.3-48.58: warning, the cases in this switch do not cover all possible values +coverage.as:72.3-76.4: warning, the cases in this switch do not cover all possible values diff --git a/test/run/ok/coverage.tc.ok b/test/run/ok/coverage.tc.ok index c03ff704735..a273de79859 100644 --- a/test/run/ok/coverage.tc.ok +++ b/test/run/ok/coverage.tc.ok @@ -13,8 +13,19 @@ coverage.as:31.25-31.34: warning, this case is never reached coverage.as:32.43-32.44: warning, this pattern is never matched coverage.as:33.35-33.49: warning, this case is never reached coverage.as:34.42-34.51: warning, this case is never reached -coverage.as:47.3-47.53: warning, this case is never reached -coverage.as:79.3-79.52: warning, this case is never reached +coverage.as:37.60-37.82: warning, this case is never reached +coverage.as:38.48-38.63: warning, this case is never reached +coverage.as:39.65-39.74: warning, this case is never reached +coverage.as:40.58-40.67: warning, this case is never reached +coverage.as:46.58-46.72: warning, this case is never reached +coverage.as:59.22-59.31: warning, this case is never reached +coverage.as:60.28-60.37: warning, this case is never reached +coverage.as:61.49-61.50: warning, this pattern is never matched +coverage.as:62.48-62.49: warning, this pattern is never matched +coverage.as:63.41-63.42: warning, this pattern is never matched +coverage.as:64.40-64.41: warning, this pattern is never matched +coverage.as:75.5-75.55: warning, this case is never reached +coverage.as:107.3-107.52: warning, this case is never reached coverage.as:4.7-4.8: warning, this pattern does not cover all possible values coverage.as:5.7-5.15: warning, this pattern does not cover all possible values coverage.as:9.7-9.9: warning, this pattern does not cover all possible values @@ -26,4 +37,8 @@ coverage.as:23.3-23.25: warning, the cases in this switch do not cover all possi coverage.as:24.3-24.36: warning, the cases in this switch do not cover all possible values coverage.as:32.3-32.50: warning, the cases in this switch do not cover all possible values coverage.as:35.3-35.51: warning, the cases in this switch do not cover all possible values -coverage.as:44.3-48.4: warning, the cases in this switch do not cover all possible values +coverage.as:41.3-41.70: warning, the cases in this switch do not cover all possible values +coverage.as:45.3-45.74: warning, the cases in this switch do not cover all possible values +coverage.as:47.3-47.58: warning, the cases in this switch do not cover all possible values +coverage.as:48.3-48.58: warning, the cases in this switch do not cover all possible values +coverage.as:72.3-76.4: warning, the cases in this switch do not cover all possible values diff --git a/test/run/ok/coverage.wasm.stderr.ok b/test/run/ok/coverage.wasm.stderr.ok index c03ff704735..a273de79859 100644 --- a/test/run/ok/coverage.wasm.stderr.ok +++ b/test/run/ok/coverage.wasm.stderr.ok @@ -13,8 +13,19 @@ coverage.as:31.25-31.34: warning, this case is never reached coverage.as:32.43-32.44: warning, this pattern is never matched coverage.as:33.35-33.49: warning, this case is never reached coverage.as:34.42-34.51: warning, this case is never reached -coverage.as:47.3-47.53: warning, this case is never reached -coverage.as:79.3-79.52: warning, this case is never reached +coverage.as:37.60-37.82: warning, this case is never reached +coverage.as:38.48-38.63: warning, this case is never reached +coverage.as:39.65-39.74: warning, this case is never reached +coverage.as:40.58-40.67: warning, this case is never reached +coverage.as:46.58-46.72: warning, this case is never reached +coverage.as:59.22-59.31: warning, this case is never reached +coverage.as:60.28-60.37: warning, this case is never reached +coverage.as:61.49-61.50: warning, this pattern is never matched +coverage.as:62.48-62.49: warning, this pattern is never matched +coverage.as:63.41-63.42: warning, this pattern is never matched +coverage.as:64.40-64.41: warning, this pattern is never matched +coverage.as:75.5-75.55: warning, this case is never reached +coverage.as:107.3-107.52: warning, this case is never reached coverage.as:4.7-4.8: warning, this pattern does not cover all possible values coverage.as:5.7-5.15: warning, this pattern does not cover all possible values coverage.as:9.7-9.9: warning, this pattern does not cover all possible values @@ -26,4 +37,8 @@ coverage.as:23.3-23.25: warning, the cases in this switch do not cover all possi coverage.as:24.3-24.36: warning, the cases in this switch do not cover all possible values coverage.as:32.3-32.50: warning, the cases in this switch do not cover all possible values coverage.as:35.3-35.51: warning, the cases in this switch do not cover all possible values -coverage.as:44.3-48.4: warning, the cases in this switch do not cover all possible values +coverage.as:41.3-41.70: warning, the cases in this switch do not cover all possible values +coverage.as:45.3-45.74: warning, the cases in this switch do not cover all possible values +coverage.as:47.3-47.58: warning, the cases in this switch do not cover all possible values +coverage.as:48.3-48.58: warning, the cases in this switch do not cover all possible values +coverage.as:72.3-76.4: warning, the cases in this switch do not cover all possible values diff --git a/test/run/ok/pat-subtyping.run-ir.ok b/test/run/ok/pat-subtyping.run-ir.ok new file mode 100644 index 00000000000..8819fa5dc63 --- /dev/null +++ b/test/run/ok/pat-subtyping.run-ir.ok @@ -0,0 +1,33 @@ +pat-subtyping.as:6.3-6.12: warning, this case is never reached +pat-subtyping.as:7.3-7.15: warning, this case is never reached +pat-subtyping.as:10.3-10.20: warning, this case is never reached +pat-subtyping.as:11.3-11.20: warning, this case is never reached +pat-subtyping.as:18.3-18.28: warning, this case is never reached +pat-subtyping.as:25.3-25.28: warning, this case is never reached +pat-subtyping.as:32.3-32.42: warning, this case is never reached +pat-subtyping.as:38.3-38.47: warning, this case is never reached +pat-subtyping.as:44.3-44.44: warning, this case is never reached +pat-subtyping.as:51.3-51.47: warning, this case is never reached +pat-subtyping.as:58.3-58.44: warning, this case is never reached +pat-subtyping.as:65.3-65.58: warning, this case is never reached +pat-subtyping.as:71.3-71.63: warning, this case is never reached +pat-subtyping.as:77.3-77.60: warning, this case is never reached +pat-subtyping.as:84.3-84.71: warning, this case is never reached +pat-subtyping.as:91.3-91.60: warning, this case is never reached +pat-subtyping.as:97.3-97.49: warning, this case is never reached +pat-subtyping.as:103.3-103.51: warning, this case is never reached +pat-subtyping.as:109.3-109.42: warning, this case is never reached +pat-subtyping.as:115.3-115.36: warning, this case is never reached +pat-subtyping.as:119.3-119.17: warning, this case is never reached +pat-subtyping.as:120.3-120.16: warning, this case is never reached +pat-subtyping.as:130.3-130.33: warning, this case is never reached +pat-subtyping.as:137.3-137.31: warning, this case is never reached +pat-subtyping.as:138.3-138.15: warning, this case is never reached +pat-subtyping.as:145.3-145.30: warning, this case is never reached +pat-subtyping.as:156.3-156.31: warning, this case is never reached +pat-subtyping.as:163.3-163.30: warning, this case is never reached +pat-subtyping.as:171.3-171.34: warning, this case is never reached +pat-subtyping.as:172.3-172.32: warning, this case is never reached +pat-subtyping.as:182.3-182.49: warning, this case is never reached +pat-subtyping.as:185.3-185.31: warning, this case is never reached +pat-subtyping.as:188.3-188.39: warning, this case is never reached diff --git a/test/run/ok/pat-subtyping.run-low.ok b/test/run/ok/pat-subtyping.run-low.ok new file mode 100644 index 00000000000..8819fa5dc63 --- /dev/null +++ b/test/run/ok/pat-subtyping.run-low.ok @@ -0,0 +1,33 @@ +pat-subtyping.as:6.3-6.12: warning, this case is never reached +pat-subtyping.as:7.3-7.15: warning, this case is never reached +pat-subtyping.as:10.3-10.20: warning, this case is never reached +pat-subtyping.as:11.3-11.20: warning, this case is never reached +pat-subtyping.as:18.3-18.28: warning, this case is never reached +pat-subtyping.as:25.3-25.28: warning, this case is never reached +pat-subtyping.as:32.3-32.42: warning, this case is never reached +pat-subtyping.as:38.3-38.47: warning, this case is never reached +pat-subtyping.as:44.3-44.44: warning, this case is never reached +pat-subtyping.as:51.3-51.47: warning, this case is never reached +pat-subtyping.as:58.3-58.44: warning, this case is never reached +pat-subtyping.as:65.3-65.58: warning, this case is never reached +pat-subtyping.as:71.3-71.63: warning, this case is never reached +pat-subtyping.as:77.3-77.60: warning, this case is never reached +pat-subtyping.as:84.3-84.71: warning, this case is never reached +pat-subtyping.as:91.3-91.60: warning, this case is never reached +pat-subtyping.as:97.3-97.49: warning, this case is never reached +pat-subtyping.as:103.3-103.51: warning, this case is never reached +pat-subtyping.as:109.3-109.42: warning, this case is never reached +pat-subtyping.as:115.3-115.36: warning, this case is never reached +pat-subtyping.as:119.3-119.17: warning, this case is never reached +pat-subtyping.as:120.3-120.16: warning, this case is never reached +pat-subtyping.as:130.3-130.33: warning, this case is never reached +pat-subtyping.as:137.3-137.31: warning, this case is never reached +pat-subtyping.as:138.3-138.15: warning, this case is never reached +pat-subtyping.as:145.3-145.30: warning, this case is never reached +pat-subtyping.as:156.3-156.31: warning, this case is never reached +pat-subtyping.as:163.3-163.30: warning, this case is never reached +pat-subtyping.as:171.3-171.34: warning, this case is never reached +pat-subtyping.as:172.3-172.32: warning, this case is never reached +pat-subtyping.as:182.3-182.49: warning, this case is never reached +pat-subtyping.as:185.3-185.31: warning, this case is never reached +pat-subtyping.as:188.3-188.39: warning, this case is never reached diff --git a/test/run/ok/pat-subtyping.run.ok b/test/run/ok/pat-subtyping.run.ok new file mode 100644 index 00000000000..8819fa5dc63 --- /dev/null +++ b/test/run/ok/pat-subtyping.run.ok @@ -0,0 +1,33 @@ +pat-subtyping.as:6.3-6.12: warning, this case is never reached +pat-subtyping.as:7.3-7.15: warning, this case is never reached +pat-subtyping.as:10.3-10.20: warning, this case is never reached +pat-subtyping.as:11.3-11.20: warning, this case is never reached +pat-subtyping.as:18.3-18.28: warning, this case is never reached +pat-subtyping.as:25.3-25.28: warning, this case is never reached +pat-subtyping.as:32.3-32.42: warning, this case is never reached +pat-subtyping.as:38.3-38.47: warning, this case is never reached +pat-subtyping.as:44.3-44.44: warning, this case is never reached +pat-subtyping.as:51.3-51.47: warning, this case is never reached +pat-subtyping.as:58.3-58.44: warning, this case is never reached +pat-subtyping.as:65.3-65.58: warning, this case is never reached +pat-subtyping.as:71.3-71.63: warning, this case is never reached +pat-subtyping.as:77.3-77.60: warning, this case is never reached +pat-subtyping.as:84.3-84.71: warning, this case is never reached +pat-subtyping.as:91.3-91.60: warning, this case is never reached +pat-subtyping.as:97.3-97.49: warning, this case is never reached +pat-subtyping.as:103.3-103.51: warning, this case is never reached +pat-subtyping.as:109.3-109.42: warning, this case is never reached +pat-subtyping.as:115.3-115.36: warning, this case is never reached +pat-subtyping.as:119.3-119.17: warning, this case is never reached +pat-subtyping.as:120.3-120.16: warning, this case is never reached +pat-subtyping.as:130.3-130.33: warning, this case is never reached +pat-subtyping.as:137.3-137.31: warning, this case is never reached +pat-subtyping.as:138.3-138.15: warning, this case is never reached +pat-subtyping.as:145.3-145.30: warning, this case is never reached +pat-subtyping.as:156.3-156.31: warning, this case is never reached +pat-subtyping.as:163.3-163.30: warning, this case is never reached +pat-subtyping.as:171.3-171.34: warning, this case is never reached +pat-subtyping.as:172.3-172.32: warning, this case is never reached +pat-subtyping.as:182.3-182.49: warning, this case is never reached +pat-subtyping.as:185.3-185.31: warning, this case is never reached +pat-subtyping.as:188.3-188.39: warning, this case is never reached diff --git a/test/run/ok/pat-subtyping.tc.ok b/test/run/ok/pat-subtyping.tc.ok new file mode 100644 index 00000000000..8819fa5dc63 --- /dev/null +++ b/test/run/ok/pat-subtyping.tc.ok @@ -0,0 +1,33 @@ +pat-subtyping.as:6.3-6.12: warning, this case is never reached +pat-subtyping.as:7.3-7.15: warning, this case is never reached +pat-subtyping.as:10.3-10.20: warning, this case is never reached +pat-subtyping.as:11.3-11.20: warning, this case is never reached +pat-subtyping.as:18.3-18.28: warning, this case is never reached +pat-subtyping.as:25.3-25.28: warning, this case is never reached +pat-subtyping.as:32.3-32.42: warning, this case is never reached +pat-subtyping.as:38.3-38.47: warning, this case is never reached +pat-subtyping.as:44.3-44.44: warning, this case is never reached +pat-subtyping.as:51.3-51.47: warning, this case is never reached +pat-subtyping.as:58.3-58.44: warning, this case is never reached +pat-subtyping.as:65.3-65.58: warning, this case is never reached +pat-subtyping.as:71.3-71.63: warning, this case is never reached +pat-subtyping.as:77.3-77.60: warning, this case is never reached +pat-subtyping.as:84.3-84.71: warning, this case is never reached +pat-subtyping.as:91.3-91.60: warning, this case is never reached +pat-subtyping.as:97.3-97.49: warning, this case is never reached +pat-subtyping.as:103.3-103.51: warning, this case is never reached +pat-subtyping.as:109.3-109.42: warning, this case is never reached +pat-subtyping.as:115.3-115.36: warning, this case is never reached +pat-subtyping.as:119.3-119.17: warning, this case is never reached +pat-subtyping.as:120.3-120.16: warning, this case is never reached +pat-subtyping.as:130.3-130.33: warning, this case is never reached +pat-subtyping.as:137.3-137.31: warning, this case is never reached +pat-subtyping.as:138.3-138.15: warning, this case is never reached +pat-subtyping.as:145.3-145.30: warning, this case is never reached +pat-subtyping.as:156.3-156.31: warning, this case is never reached +pat-subtyping.as:163.3-163.30: warning, this case is never reached +pat-subtyping.as:171.3-171.34: warning, this case is never reached +pat-subtyping.as:172.3-172.32: warning, this case is never reached +pat-subtyping.as:182.3-182.49: warning, this case is never reached +pat-subtyping.as:185.3-185.31: warning, this case is never reached +pat-subtyping.as:188.3-188.39: warning, this case is never reached diff --git a/test/run/ok/pat-subtyping.wasm.stderr.ok b/test/run/ok/pat-subtyping.wasm.stderr.ok new file mode 100644 index 00000000000..8819fa5dc63 --- /dev/null +++ b/test/run/ok/pat-subtyping.wasm.stderr.ok @@ -0,0 +1,33 @@ +pat-subtyping.as:6.3-6.12: warning, this case is never reached +pat-subtyping.as:7.3-7.15: warning, this case is never reached +pat-subtyping.as:10.3-10.20: warning, this case is never reached +pat-subtyping.as:11.3-11.20: warning, this case is never reached +pat-subtyping.as:18.3-18.28: warning, this case is never reached +pat-subtyping.as:25.3-25.28: warning, this case is never reached +pat-subtyping.as:32.3-32.42: warning, this case is never reached +pat-subtyping.as:38.3-38.47: warning, this case is never reached +pat-subtyping.as:44.3-44.44: warning, this case is never reached +pat-subtyping.as:51.3-51.47: warning, this case is never reached +pat-subtyping.as:58.3-58.44: warning, this case is never reached +pat-subtyping.as:65.3-65.58: warning, this case is never reached +pat-subtyping.as:71.3-71.63: warning, this case is never reached +pat-subtyping.as:77.3-77.60: warning, this case is never reached +pat-subtyping.as:84.3-84.71: warning, this case is never reached +pat-subtyping.as:91.3-91.60: warning, this case is never reached +pat-subtyping.as:97.3-97.49: warning, this case is never reached +pat-subtyping.as:103.3-103.51: warning, this case is never reached +pat-subtyping.as:109.3-109.42: warning, this case is never reached +pat-subtyping.as:115.3-115.36: warning, this case is never reached +pat-subtyping.as:119.3-119.17: warning, this case is never reached +pat-subtyping.as:120.3-120.16: warning, this case is never reached +pat-subtyping.as:130.3-130.33: warning, this case is never reached +pat-subtyping.as:137.3-137.31: warning, this case is never reached +pat-subtyping.as:138.3-138.15: warning, this case is never reached +pat-subtyping.as:145.3-145.30: warning, this case is never reached +pat-subtyping.as:156.3-156.31: warning, this case is never reached +pat-subtyping.as:163.3-163.30: warning, this case is never reached +pat-subtyping.as:171.3-171.34: warning, this case is never reached +pat-subtyping.as:172.3-172.32: warning, this case is never reached +pat-subtyping.as:182.3-182.49: warning, this case is never reached +pat-subtyping.as:185.3-185.31: warning, this case is never reached +pat-subtyping.as:188.3-188.39: warning, this case is never reached diff --git a/test/run/ok/switch.run-ir.ok b/test/run/ok/switch.run-ir.ok index 574eb979021..650be56a521 100644 --- a/test/run/ok/switch.run-ir.ok +++ b/test/run/ok/switch.run-ir.ok @@ -1,6 +1,5 @@ -switch.as:87.33-87.34: warning, this pattern is never matched +switch.as:86.29-86.30: warning, this pattern is never matched switch.as:75.11-77.2: warning, the cases in this switch do not cover all possible values switch.as:81.3-81.14: warning, the cases in this switch do not cover all possible values -switch.as:87.3-87.40: warning, the cases in this switch do not cover all possible values switch.as:92.11-94.2: warning, the cases in this switch do not cover all possible values switch.as:97.11-99.2: warning, the cases in this switch do not cover all possible values diff --git a/test/run/ok/switch.run-low.ok b/test/run/ok/switch.run-low.ok index 574eb979021..650be56a521 100644 --- a/test/run/ok/switch.run-low.ok +++ b/test/run/ok/switch.run-low.ok @@ -1,6 +1,5 @@ -switch.as:87.33-87.34: warning, this pattern is never matched +switch.as:86.29-86.30: warning, this pattern is never matched switch.as:75.11-77.2: warning, the cases in this switch do not cover all possible values switch.as:81.3-81.14: warning, the cases in this switch do not cover all possible values -switch.as:87.3-87.40: warning, the cases in this switch do not cover all possible values switch.as:92.11-94.2: warning, the cases in this switch do not cover all possible values switch.as:97.11-99.2: warning, the cases in this switch do not cover all possible values diff --git a/test/run/ok/switch.run.ok b/test/run/ok/switch.run.ok index 574eb979021..650be56a521 100644 --- a/test/run/ok/switch.run.ok +++ b/test/run/ok/switch.run.ok @@ -1,6 +1,5 @@ -switch.as:87.33-87.34: warning, this pattern is never matched +switch.as:86.29-86.30: warning, this pattern is never matched switch.as:75.11-77.2: warning, the cases in this switch do not cover all possible values switch.as:81.3-81.14: warning, the cases in this switch do not cover all possible values -switch.as:87.3-87.40: warning, the cases in this switch do not cover all possible values switch.as:92.11-94.2: warning, the cases in this switch do not cover all possible values switch.as:97.11-99.2: warning, the cases in this switch do not cover all possible values diff --git a/test/run/ok/switch.tc.ok b/test/run/ok/switch.tc.ok index 574eb979021..650be56a521 100644 --- a/test/run/ok/switch.tc.ok +++ b/test/run/ok/switch.tc.ok @@ -1,6 +1,5 @@ -switch.as:87.33-87.34: warning, this pattern is never matched +switch.as:86.29-86.30: warning, this pattern is never matched switch.as:75.11-77.2: warning, the cases in this switch do not cover all possible values switch.as:81.3-81.14: warning, the cases in this switch do not cover all possible values -switch.as:87.3-87.40: warning, the cases in this switch do not cover all possible values switch.as:92.11-94.2: warning, the cases in this switch do not cover all possible values switch.as:97.11-99.2: warning, the cases in this switch do not cover all possible values diff --git a/test/run/ok/switch.wasm.stderr.ok b/test/run/ok/switch.wasm.stderr.ok index 574eb979021..650be56a521 100644 --- a/test/run/ok/switch.wasm.stderr.ok +++ b/test/run/ok/switch.wasm.stderr.ok @@ -1,6 +1,5 @@ -switch.as:87.33-87.34: warning, this pattern is never matched +switch.as:86.29-86.30: warning, this pattern is never matched switch.as:75.11-77.2: warning, the cases in this switch do not cover all possible values switch.as:81.3-81.14: warning, the cases in this switch do not cover all possible values -switch.as:87.3-87.40: warning, the cases in this switch do not cover all possible values switch.as:92.11-94.2: warning, the cases in this switch do not cover all possible values switch.as:97.11-99.2: warning, the cases in this switch do not cover all possible values diff --git a/test/run/ok/type-inference.run-ir.ok b/test/run/ok/type-inference.run-ir.ok new file mode 100644 index 00000000000..f2ebd9a64d1 --- /dev/null +++ b/test/run/ok/type-inference.run-ir.ok @@ -0,0 +1,37 @@ +type-inference.as:3.9-3.28: warning, this if has type Shared because branches have inconsistent types, +true produces + Bool +false produces + Nat +type-inference.as:4.9-4.34: warning, this if has type Any because branches have inconsistent types, +true produces + Bool +false produces + [var Nat] +type-inference.as:5.9-5.27: warning, this if has type Shared because branches have inconsistent types, +true produces + Nat +false produces + Float +type-inference.as:6.9-6.33: warning, this if has type Any because branches have inconsistent types, +true produces + () +false produces + {} +type-inference.as:11.33-11.41: warning, the switch has type Shared because branches have inconsistent types, +this case produces type + Bool +the previous produce type + Nat +type-inference.as:12.33-12.47: warning, the switch has type Any because branches have inconsistent types, +this case produces type + Bool +the previous produce type + [var Nat] +type-inference.as:13.43-13.56: warning, the switch has type Shared because branches have inconsistent types, +this case produces type + Int +the previous produce type + Text +type-inference.as:19.9-19.18: warning, this array has type [Shared] because elements have inconsistent types +type-inference.as:20.9-20.24: warning, this array has type [Any] because elements have inconsistent types diff --git a/test/run/ok/type-inference.run-low.ok b/test/run/ok/type-inference.run-low.ok new file mode 100644 index 00000000000..f2ebd9a64d1 --- /dev/null +++ b/test/run/ok/type-inference.run-low.ok @@ -0,0 +1,37 @@ +type-inference.as:3.9-3.28: warning, this if has type Shared because branches have inconsistent types, +true produces + Bool +false produces + Nat +type-inference.as:4.9-4.34: warning, this if has type Any because branches have inconsistent types, +true produces + Bool +false produces + [var Nat] +type-inference.as:5.9-5.27: warning, this if has type Shared because branches have inconsistent types, +true produces + Nat +false produces + Float +type-inference.as:6.9-6.33: warning, this if has type Any because branches have inconsistent types, +true produces + () +false produces + {} +type-inference.as:11.33-11.41: warning, the switch has type Shared because branches have inconsistent types, +this case produces type + Bool +the previous produce type + Nat +type-inference.as:12.33-12.47: warning, the switch has type Any because branches have inconsistent types, +this case produces type + Bool +the previous produce type + [var Nat] +type-inference.as:13.43-13.56: warning, the switch has type Shared because branches have inconsistent types, +this case produces type + Int +the previous produce type + Text +type-inference.as:19.9-19.18: warning, this array has type [Shared] because elements have inconsistent types +type-inference.as:20.9-20.24: warning, this array has type [Any] because elements have inconsistent types diff --git a/test/run/ok/type-inference.run.ok b/test/run/ok/type-inference.run.ok new file mode 100644 index 00000000000..f2ebd9a64d1 --- /dev/null +++ b/test/run/ok/type-inference.run.ok @@ -0,0 +1,37 @@ +type-inference.as:3.9-3.28: warning, this if has type Shared because branches have inconsistent types, +true produces + Bool +false produces + Nat +type-inference.as:4.9-4.34: warning, this if has type Any because branches have inconsistent types, +true produces + Bool +false produces + [var Nat] +type-inference.as:5.9-5.27: warning, this if has type Shared because branches have inconsistent types, +true produces + Nat +false produces + Float +type-inference.as:6.9-6.33: warning, this if has type Any because branches have inconsistent types, +true produces + () +false produces + {} +type-inference.as:11.33-11.41: warning, the switch has type Shared because branches have inconsistent types, +this case produces type + Bool +the previous produce type + Nat +type-inference.as:12.33-12.47: warning, the switch has type Any because branches have inconsistent types, +this case produces type + Bool +the previous produce type + [var Nat] +type-inference.as:13.43-13.56: warning, the switch has type Shared because branches have inconsistent types, +this case produces type + Int +the previous produce type + Text +type-inference.as:19.9-19.18: warning, this array has type [Shared] because elements have inconsistent types +type-inference.as:20.9-20.24: warning, this array has type [Any] because elements have inconsistent types diff --git a/test/fail/ok/type-inference.tc.ok b/test/run/ok/type-inference.tc.ok similarity index 93% rename from test/fail/ok/type-inference.tc.ok rename to test/run/ok/type-inference.tc.ok index 68f382f616d..f2ebd9a64d1 100644 --- a/test/fail/ok/type-inference.tc.ok +++ b/test/run/ok/type-inference.tc.ok @@ -35,5 +35,3 @@ the previous produce type Text type-inference.as:19.9-19.18: warning, this array has type [Shared] because elements have inconsistent types type-inference.as:20.9-20.24: warning, this array has type [Any] because elements have inconsistent types -type-inference.as:81.13-81.16: type error, expected iterable type, but expression has type - Non diff --git a/test/run/ok/type-inference.wasm.stderr.ok b/test/run/ok/type-inference.wasm.stderr.ok new file mode 100644 index 00000000000..5e5cb268e62 --- /dev/null +++ b/test/run/ok/type-inference.wasm.stderr.ok @@ -0,0 +1,38 @@ +compile_lit: (FloatLit 5.1) +type-inference.as:3.9-3.28: warning, this if has type Shared because branches have inconsistent types, +true produces + Bool +false produces + Nat +type-inference.as:4.9-4.34: warning, this if has type Any because branches have inconsistent types, +true produces + Bool +false produces + [var Nat] +type-inference.as:5.9-5.27: warning, this if has type Shared because branches have inconsistent types, +true produces + Nat +false produces + Float +type-inference.as:6.9-6.33: warning, this if has type Any because branches have inconsistent types, +true produces + () +false produces + {} +type-inference.as:11.33-11.41: warning, the switch has type Shared because branches have inconsistent types, +this case produces type + Bool +the previous produce type + Nat +type-inference.as:12.33-12.47: warning, the switch has type Any because branches have inconsistent types, +this case produces type + Bool +the previous produce type + [var Nat] +type-inference.as:13.43-13.56: warning, the switch has type Shared because branches have inconsistent types, +this case produces type + Int +the previous produce type + Text +type-inference.as:19.9-19.18: warning, this array has type [Shared] because elements have inconsistent types +type-inference.as:20.9-20.24: warning, this array has type [Any] because elements have inconsistent types diff --git a/test/run/pat-subtyping.as b/test/run/pat-subtyping.as new file mode 100644 index 00000000000..22931ad66a9 --- /dev/null +++ b/test/run/pat-subtyping.as @@ -0,0 +1,207 @@ +func magic() : None = magic(); + +if false { + +switch (magic ()) { + case 1 {}; // redundant + case (-1) {}; // redundant +}; +switch (magic ()) { + case (1 : Nat) {}; // redundant + case (_ : Nat) {}; // redundant +}; + +switch (magic () : Nat) { + case (n : Int) {}; +}; +switch (magic ()) { + case ((n : Int) : Nat) {}; // redundant +}; +switch (magic () : Nat) { + case (1 : Int) {}; + case (_ : Nat) {}; +}; +switch (magic ()) { + case ((1 : Int) : Nat) {}; // redundant +}; + +switch (magic () : (Nat, Nat)) { + case (p : (Int, Int)) {}; +}; +switch (magic ()) { + case ((p : (Int, Int)) : (Nat, Nat)) {}; // redundant +}; +switch (magic () : (Nat, Nat)) { + case ((x, y) : (Int, Int)) {}; +}; +switch (magic ()) { + case (((x, y) : (Int, Int)) : (Nat, Nat)) {}; // redundant +}; +switch (magic () : (Nat, Nat)) { + case (x : Int, y : Int) {}; +}; +switch (magic ()) { + case ((x : Int, y : Int) : (Nat, Nat)) {}; // redundant +}; +switch (magic () : (Nat, Nat)) { + case ((1, 2) : (Int, Int)) {}; + case _ {}; +}; +switch (magic ()) { + case (((1, 2) : (Int, Int)) : (Nat, Nat)) {}; // redundant +}; +switch (magic () : (Nat, Nat)) { + case (1 : Int, 2 : Int) {}; + case _ {}; +}; +switch (magic ()) { + case ((1 : Int, 2 : Int) : (Nat, Nat)) {}; // redundant +}; + +switch (magic () : {a : Nat; b : Nat}) { + case (r : {a : Int; b : Int}) {}; +}; +switch (magic ()) { + case ((r : {a : Int; b : Int}) : {a : Nat; b : Nat}) {}; // redundant +}; +switch (magic () : {a : Nat; b : Nat}) { + case ({a; b} : {a : Int; b : Int}) {}; +}; +switch (magic ()) { + case (({a; b} : {a : Int; b : Int}) : {a : Nat; b : Nat}) {}; // redundant +}; +switch (magic () : {a : Nat; b : Nat}) { + case {a = _ : Int; b = _ : Int} {}; +}; +switch (magic ()) { + case ({a = _ : Int; b = _ : Int} : {a : Nat; b : Nat}) {}; // redundant +}; +switch (magic () : {a : Nat; b : Nat}) { + case ({a = 1; b = 2} : {a : Int; b : Int}) {}; + case _ {}; +}; +switch (magic ()) { + case (({a = 1; b = 2} : {a : Int; b : Int}) : {a : Nat; b : Nat}) {}; // redundant +}; +switch (magic () : {a : Nat; b : Nat}) { + case {a = 1 : Int; b = 2 : Int} {}; + case _ {}; +}; +switch (magic ()) { + case ({a = 1 : Int; b = 2 : Int} : {a : Nat; b : Nat}) {}; // redundant +}; +switch (magic () : {a : Nat; b : Nat}) { + case (r : {a : Nat}) {}; +}; +switch (magic ()) { + case ((r : {a : Nat}) : {a : Nat; b : Nat}) {}; // redundant +}; +switch (magic () : {a : Nat; b : Nat}) { + case ({a} : {a : Nat}) {}; +}; +switch (magic ()) { + case (({a} : {a : Nat}) : {a : Nat; b : Nat}) {}; // redundant +}; +switch (magic () : {a : Nat; b : Nat}) { + case (r : {}) {}; +}; +switch (magic ()) { + case ((r : {}) : {a : Nat; b : Nat}) {}; // redundant +}; +switch (magic () : {a : Nat; b : Nat}) { + case {} {}; +}; +switch (magic ()) { + case ({} : {a : Nat; b : Nat}) {}; // redundant +}; + +switch (magic ()) { + case (null) {}; // redundant + case (? _) {}; // redundant +}; +switch (magic () : Null) { + case (null : ?Nat) {}; +}; +switch (magic () : ?Nat) { + case (null) {}; + case (? _) {}; +}; +switch (magic ()) { + case ((null : ?Nat) : Null) {}; // redundant +}; +switch (magic () : ?Nat) { + case (?n : ?Int) {}; + case null {}; +}; +switch (magic ()) { + case ((?n : ?Int) : ?Nat) {}; // redundant + case null {}; // redundant +}; +switch (magic () : ?Nat) { + case (?(_ : Int)) {}; + case _ {}; +}; +switch (magic ()) { + case (?(_ : Int) : ?Nat) {}; // redundant +}; +switch (magic () : ?Nat) { + case (?1) {}; + case _ {}; +}; +switch (magic () : ?Nat) { + case (?1 : ?Int) {}; + case _ {}; +}; +switch (magic ()) { + case ((?1 : ?Int) : ?Nat) {}; // redundant +}; +switch (magic () : ?Nat) { + case (?(1 : Int)) {}; + case _ {}; +}; +switch (magic ()) { + case (?(1 : Int) : ?Nat) {}; // redundant +}; + +switch (magic () : {#A : Nat; #B}) { + case (#A _) {}; + case (#B) {}; +}; +switch (magic ()) { + case (#A _ : {#A : Nat; #B}) {}; // redundant + case (#B : {#A : Nat; #B}) {}; // redundant +}; +switch (magic () : {#A : Nat; #B}) { + case (#A _ : {#A : Nat; #B}) {}; + case (#B : {#A : Nat; #B}) {}; +}; +switch (magic () : {#A : Nat}) { + case (#A _ : {#A : Nat; #B}) {}; +}; +switch (magic ()) { + case ((#A _ : {#A : Nat; #B}) : {#A : Nat}) {}; // redundant +}; +switch (magic () : {#}) { + case (_ : {#A : Nat; #B}) {}; // redundant +}; +switch (magic ()) { + case ((_ : {#A : Nat; #B}) : {#}) {}; // redundant +}; +switch (magic () : {#A : Nat; #B}) { + case (#A(_ : Int)) {}; + case (#B) {}; +}; +switch (magic () : {#A : Nat; #B}) { + case (#A 1) {}; + case _ {}; +}; +switch (magic () : {#A : Nat; #B}) { + case (#A(1 : Int)) {}; + case _ {}; +}; +switch (magic () : {#A : Nat; #B}) { + case (#A 1 : {#A : Int; #B}) {}; + case _ {}; +}; + +}; diff --git a/test/run/switch.as b/test/run/switch.as index 5f078853712..5442a665a26 100644 --- a/test/run/switch.as +++ b/test/run/switch.as @@ -84,7 +84,7 @@ func f() { switch 0 { case 0 {}; case _ {}; }; switch (return) {}; switch (0, return) { case _ {} }; - switch (0, return) { case (0, _) {} }; + switch (0, return) {}; }; func g(_ : None) {}; diff --git a/test/fail/type-inference.as b/test/run/type-inference.as similarity index 96% rename from test/fail/type-inference.as rename to test/run/type-inference.as index 2ec976e4075..aaf9f8b57cc 100644 --- a/test/fail/type-inference.as +++ b/test/run/type-inference.as @@ -57,12 +57,11 @@ let a = type Top = Any; func top(top : Top) { - switch top { - case 1 (); - case true (); - case null (); - case _ (); - }; + let _ = [1, top]; + let _ = [true, top]; + let _ = [null, top]; + let _ = ["", top]; + let _ = [top, top]; }; From 42ab6cb27a25d7e3dfbdba1ae5d45b1c808126fa Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Fri, 5 Jul 2019 21:09:46 +0200 Subject: [PATCH 0235/1176] Split as_frontend (#548) --- src/Structure.md | 34 +++++++++++-------- src/{as_frontend => as_def}/arrange.ml | 0 src/as_def/dune | 4 +++ src/{as_frontend => as_def}/syntax.ml | 4 ++- src/as_frontend/coverage.ml | 8 +++-- src/as_frontend/coverage.mli | 1 + src/as_frontend/definedness.ml | 2 ++ src/as_frontend/definedness.mli | 2 ++ src/as_frontend/dune | 2 +- src/as_frontend/effect.ml | 6 +++- src/as_frontend/effect.mli | 5 ++- src/as_frontend/parser.mly | 10 ++++-- src/as_frontend/static.ml | 2 ++ src/as_frontend/static.mli | 2 ++ src/as_frontend/typing.ml | 6 ++-- src/as_frontend/typing.mli | 7 ++-- src/as_interpreter/dune | 4 +++ .../interpret.ml | 10 +++--- .../interpret.mli | 9 +++-- src/as_ld | 1 - src/codegen/compile.ml | 2 +- src/codegen/compile.mli | 4 +-- src/codegen/dune | 2 +- src/interpreter/dune | 4 --- src/{as_ir => ir_def}/arrange_ir.ml | 0 src/{as_ir => ir_def}/check_ir.ml | 0 src/{as_ir => ir_def}/check_ir.mli | 0 src/{as_ir => ir_def}/construct.ml | 0 src/{as_ir => ir_def}/construct.mli | 0 src/{as_ir => ir_def}/dune | 2 +- src/{as_ir => ir_def}/freevars.ml | 0 src/{as_ir => ir_def}/ir.ml | 0 src/{as_ir => ir_def}/ir_effect.ml | 0 src/{as_ir => ir_def}/ir_effect.mli | 0 src/ir_interpreter/dune | 2 +- src/ir_interpreter/interpret_ir.ml | 2 +- src/ir_interpreter/interpret_ir.mli | 2 +- src/ir_passes/async.ml | 3 +- src/ir_passes/async.mli | 2 +- src/ir_passes/await.ml | 6 ++-- src/ir_passes/await.mli | 3 +- src/ir_passes/dune | 2 +- src/ir_passes/rename.ml | 3 +- src/ir_passes/serialization.ml | 3 +- src/ir_passes/serialization.mli | 3 +- src/ir_passes/show.ml | 2 +- src/ir_passes/show.mli | 2 +- src/ir_passes/tailcall.ml | 2 +- src/ir_passes/tailcall.mli | 2 +- src/lowering/desugar.ml | 6 ++-- src/lowering/desugar.mli | 7 ++-- src/lowering/dune | 2 +- src/pipeline/dune | 7 ++-- src/pipeline/pipeline.ml | 20 ++++++----- src/pipeline/pipeline.mli | 10 +++--- src/pipeline/resolve_import.ml | 2 +- src/pipeline/resolve_import.mli | 2 +- 57 files changed, 142 insertions(+), 86 deletions(-) rename src/{as_frontend => as_def}/arrange.ml (100%) create mode 100644 src/as_def/dune rename src/{as_frontend => as_def}/syntax.ml (99%) create mode 100644 src/as_interpreter/dune rename src/{interpreter => as_interpreter}/interpret.ml (99%) rename src/{interpreter => as_interpreter}/interpret.mli (83%) delete mode 120000 src/as_ld delete mode 100644 src/interpreter/dune rename src/{as_ir => ir_def}/arrange_ir.ml (100%) rename src/{as_ir => ir_def}/check_ir.ml (100%) rename src/{as_ir => ir_def}/check_ir.mli (100%) rename src/{as_ir => ir_def}/construct.ml (100%) rename src/{as_ir => ir_def}/construct.mli (100%) rename src/{as_ir => ir_def}/dune (75%) rename src/{as_ir => ir_def}/freevars.ml (100%) rename src/{as_ir => ir_def}/ir.ml (100%) rename src/{as_ir => ir_def}/ir_effect.ml (100%) rename src/{as_ir => ir_def}/ir_effect.mli (100%) diff --git a/src/Structure.md b/src/Structure.md index 3d09b344314..7b5a0e59477 100644 --- a/src/Structure.md +++ b/src/Structure.md @@ -27,59 +27,63 @@ for the real deal; some shortcuts had to be taken. Stuff that could be in the Ocaml standard library. - * `lang-utils/` (asc, didc; using `lib/`) + * `lang_utils/` (asc, didc; using `lib/`) General PL-related utility-functions, useful for AS Source, AS IR, the IDL AST: Environments, diagnostic error messages, source locations. - * `as-types/` (asc; using `lang-utils/`) + * `as_def/` (asc; using `lang_utils/`) + + The ActorScript AST and pretty-printer. + + * `as_types/` (asc; using `lang_utils/`) The ActorScript type definition, as used by both Source and IR. Includes - pretty-printer. Also includes the value definitions. + pretty-printer. - * `as-values/` (asc; using `lang-utils/`) + * `as_values/` (asc; using `lang_utils/`) Value definitions, as used for literals, interpreter. Also includes operations on values and primitive operations. - * `as-frontend/` (asc; using `lang-utils/`) + * `as_frontend/` (asc; using `lang_utils/` and `as_def`) - The ActorScript Source AST, including parser and type inference. + The ActorScript parser and type checker. - * `as-ir/` (asc; using `lang-utils/`) + * `ir_def/` (asc; using `lang_utils/`) The ActorScript IR AST, including type checker and pretty-printer. - * `lowering/` (asc; using `as-frontent/` and `as-ir/`) + * `lowering/` (asc; using `as_def/` and `ir_def/`) The IR to Source pass. - * `ir-passes/` (asc; using `as-ir/`) + * `ir_passes/` (asc; using `as_def/`) The various IR to IR passes. - * `wasm-exts/` (asc, as-ld; using `lib/`) + * `wasm_exts/` (asc, as-ld; using `lib/`) Extensions to the wasm library: Support for additional custom sections, including serialization and de-serialization. - * `linking/` (asc, as-ld; using `wasm-exts/`) + * `linking/` (asc, as-ld; using `wasm_exts/`) Wasm linking code - * `codegen/` (asc; using `as-ir/`, `linking/`) + * `codegen/` (asc; using `ir_def/`, `linking/`) The backend, including the instruction list generator. - * `interpreter/` (asc; using `as-frontend/`) + * `interpreter/` (asc; using `as_def/`) Source interpreter. - * `ir-interpreter/` (asc; using `as-ir/`) + * `ir_interpreter/` (asc; using `ir_def/`) IR interpreter. - * `pipeline/` (asc; using `as-frontend/`, `lowering/`, `ir-passes/`, `codegen/`, `interpreter/`, `interpreter-ir/`) + * `pipeline/` (asc; using `as_frontend/`, `lowering/`, `ir_passes/`, `codegen/`, `as_interpreter/`, `ir_interpreter/`) The pipeline, prelude text and flags diff --git a/src/as_frontend/arrange.ml b/src/as_def/arrange.ml similarity index 100% rename from src/as_frontend/arrange.ml rename to src/as_def/arrange.ml diff --git a/src/as_def/dune b/src/as_def/dune new file mode 100644 index 00000000000..f943cacfa60 --- /dev/null +++ b/src/as_def/dune @@ -0,0 +1,4 @@ +(library + (name as_def) + (libraries lib lang_utils as_types as_values) +) diff --git a/src/as_frontend/syntax.ml b/src/as_def/syntax.ml similarity index 99% rename from src/as_frontend/syntax.ml rename to src/as_def/syntax.ml index 360d4f6b424..e51e2d93d27 100644 --- a/src/as_frontend/syntax.ml +++ b/src/as_def/syntax.ml @@ -1,6 +1,8 @@ open As_types open As_values -open As_values.Operator + +open Operator + (* Notes *) diff --git a/src/as_frontend/coverage.ml b/src/as_frontend/coverage.ml index 75aee409245..e9a9f9e2b68 100644 --- a/src/as_frontend/coverage.ml +++ b/src/as_frontend/coverage.ml @@ -1,9 +1,11 @@ -open Syntax -open Source +open As_def open As_types open As_values -module V = As_values.Value +open Syntax +open Source + +module V = Value module ValSet = Set.Make(struct type t = V.value let compare = V.compare end) module TagSet = Set.Make(struct type t = string let compare = compare end) diff --git a/src/as_frontend/coverage.mli b/src/as_frontend/coverage.mli index fe1c584c27d..2eec785b21b 100644 --- a/src/as_frontend/coverage.mli +++ b/src/as_frontend/coverage.mli @@ -1,3 +1,4 @@ +open As_def open As_types val check_pat : Syntax.pat -> Type.typ -> bool diff --git a/src/as_frontend/definedness.ml b/src/as_frontend/definedness.ml index fa0dd39537b..246e13662a5 100644 --- a/src/as_frontend/definedness.ml +++ b/src/as_frontend/definedness.ml @@ -10,6 +10,8 @@ We keep it still separate, because we are doing much more interesting things here in for blocks (function decs). *) +open As_def + open Source open Syntax diff --git a/src/as_frontend/definedness.mli b/src/as_frontend/definedness.mli index a2f983e4002..40925eaf093 100644 --- a/src/as_frontend/definedness.mli +++ b/src/as_frontend/definedness.mli @@ -1 +1,3 @@ +open As_def + val check_prog : Syntax.prog -> unit Diag.result diff --git a/src/as_frontend/dune b/src/as_frontend/dune index fabe922c733..c076b4a19fb 100644 --- a/src/as_frontend/dune +++ b/src/as_frontend/dune @@ -1,6 +1,6 @@ (library (name as_frontend) - (libraries lib lang_utils as_types as_values) + (libraries lib lang_utils as_def as_types as_values) ) (menhir (modules parser) diff --git a/src/as_frontend/effect.ml b/src/as_frontend/effect.ml index 75e1cefff35..4f3ac993d3c 100644 --- a/src/as_frontend/effect.ml +++ b/src/as_frontend/effect.ml @@ -1,6 +1,10 @@ +open As_def +open As_types + open Syntax open Source -module T = As_types.Type + +module T = Type (* a simple effect analysis to annote expressions as Triv(ial) (await-free) or Await (containing unprotected awaits) *) diff --git a/src/as_frontend/effect.mli b/src/as_frontend/effect.mli index e6093a419ed..0469849bba1 100644 --- a/src/as_frontend/effect.mli +++ b/src/as_frontend/effect.mli @@ -1,6 +1,9 @@ +open As_def +open As_types + open Source open Syntax -open As_types.Type +open Type val max_eff : eff -> eff -> eff diff --git a/src/as_frontend/parser.mly b/src/as_frontend/parser.mly index 1f9729ca32a..2eb61d38f2d 100644 --- a/src/as_frontend/parser.mly +++ b/src/as_frontend/parser.mly @@ -1,8 +1,12 @@ %{ +open As_def open As_types -open As_values.Operator +open As_values + open Syntax open Source +open Operator + (* Position handling *) @@ -137,8 +141,8 @@ let share_expfield (ef : exp_field) = %left POWOP %type exp exp_nullary -%start Syntax.prog> parse_prog -%start Syntax.prog> parse_prog_interactive +%start As_def.Syntax.prog> parse_prog +%start As_def.Syntax.prog> parse_prog_interactive %% diff --git a/src/as_frontend/static.ml b/src/as_frontend/static.ml index a16884c227a..d726b826448 100644 --- a/src/as_frontend/static.ml +++ b/src/as_frontend/static.ml @@ -10,6 +10,8 @@ some kind of beta-reduction, and can actually cause loops, but are required to allow re-exporting names in modules. *) +open As_def + open Source open Syntax diff --git a/src/as_frontend/static.mli b/src/as_frontend/static.mli index bcf37440fd8..7b6cc8ac514 100644 --- a/src/as_frontend/static.mli +++ b/src/as_frontend/static.mli @@ -1,3 +1,5 @@ +open As_def + val exp : Diag.msg_store -> Syntax.exp -> unit val fields : Diag.msg_store -> Syntax.exp_field list -> unit val prog : Syntax.prog -> unit Diag.result diff --git a/src/as_frontend/typing.ml b/src/as_frontend/typing.ml index 3f7bd1248ab..ddcefe6710d 100644 --- a/src/as_frontend/typing.ml +++ b/src/as_frontend/typing.ml @@ -1,8 +1,10 @@ -open Syntax -open Source +open As_def open As_types open As_values +open Syntax +open Source + module T = Type module A = Effect diff --git a/src/as_frontend/typing.mli b/src/as_frontend/typing.mli index b600f0f6a43..95afd71bec9 100644 --- a/src/as_frontend/typing.mli +++ b/src/as_frontend/typing.mli @@ -1,5 +1,8 @@ -open As_types.Type -open As_types.Scope +open As_def +open As_types + +open Type +open Scope val infer_prog : scope -> Syntax.prog -> (typ * scope) Diag.result val check_library : scope -> Syntax.library -> scope Diag.result diff --git a/src/as_interpreter/dune b/src/as_interpreter/dune new file mode 100644 index 00000000000..c23e20322d8 --- /dev/null +++ b/src/as_interpreter/dune @@ -0,0 +1,4 @@ +(library + (name as_interpreter) + (libraries lib as_def as_types as_values profiler) +) diff --git a/src/interpreter/interpret.ml b/src/as_interpreter/interpret.ml similarity index 99% rename from src/interpreter/interpret.ml rename to src/as_interpreter/interpret.ml index 17e1ab1ca0f..6bee8d66092 100644 --- a/src/interpreter/interpret.ml +++ b/src/as_interpreter/interpret.ml @@ -1,11 +1,13 @@ +open As_def open As_values -open As_frontend +open As_types + open Syntax open Source -module V = As_values.Value -module T = As_types.Type -module CC = As_types.Call_conv +module V = Value +module T = Type +module CC = Call_conv (* Context *) diff --git a/src/interpreter/interpret.mli b/src/as_interpreter/interpret.mli similarity index 83% rename from src/interpreter/interpret.mli rename to src/as_interpreter/interpret.mli index b53864de020..7bf2f131c2d 100644 --- a/src/interpreter/interpret.mli +++ b/src/as_interpreter/interpret.mli @@ -1,6 +1,9 @@ -open As_frontend -module V = As_values.Value -module T = As_types.Type +open As_def +open As_values +open As_types + +module V = Value +module T = Type type flags = { trace : bool; diff --git a/src/as_ld b/src/as_ld deleted file mode 120000 index 8ed244c2d96..00000000000 --- a/src/as_ld +++ /dev/null @@ -1 +0,0 @@ -_build/default/exes/as_ld.exe \ No newline at end of file diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 421e56ce2be..c011dd42a2c 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -10,7 +10,7 @@ grouping. Every module has a high-level prose comment explaining the concept; this keeps documentation close to the code (a lesson learned from Simon PJ). *) -open As_ir +open Ir_def open As_values open As_types diff --git a/src/codegen/compile.mli b/src/codegen/compile.mli index 685e374a2dd..15f98fa3712 100644 --- a/src/codegen/compile.mli +++ b/src/codegen/compile.mli @@ -1,5 +1,5 @@ -type mode = WasmMode | DfinityMode +open Ir_def -open As_ir +type mode = WasmMode | DfinityMode val compile : mode -> string -> Wasm_exts.CustomModule.extended_module option -> Ir.prog -> Ir.prog list -> Wasm_exts.CustomModule.extended_module diff --git a/src/codegen/dune b/src/codegen/dune index a9c1f70654b..fd155db2fa2 100644 --- a/src/codegen/dune +++ b/src/codegen/dune @@ -1,4 +1,4 @@ (library (name codegen) - (libraries wasm lib lang_utils wasm_exts as_ir linking) + (libraries wasm lib lang_utils wasm_exts ir_def linking) ) diff --git a/src/interpreter/dune b/src/interpreter/dune deleted file mode 100644 index 25600c50de0..00000000000 --- a/src/interpreter/dune +++ /dev/null @@ -1,4 +0,0 @@ -(library - (name interpreter) - (libraries lib as_types as_values as_frontend profiler) -) diff --git a/src/as_ir/arrange_ir.ml b/src/ir_def/arrange_ir.ml similarity index 100% rename from src/as_ir/arrange_ir.ml rename to src/ir_def/arrange_ir.ml diff --git a/src/as_ir/check_ir.ml b/src/ir_def/check_ir.ml similarity index 100% rename from src/as_ir/check_ir.ml rename to src/ir_def/check_ir.ml diff --git a/src/as_ir/check_ir.mli b/src/ir_def/check_ir.mli similarity index 100% rename from src/as_ir/check_ir.mli rename to src/ir_def/check_ir.mli diff --git a/src/as_ir/construct.ml b/src/ir_def/construct.ml similarity index 100% rename from src/as_ir/construct.ml rename to src/ir_def/construct.ml diff --git a/src/as_ir/construct.mli b/src/ir_def/construct.mli similarity index 100% rename from src/as_ir/construct.mli rename to src/ir_def/construct.mli diff --git a/src/as_ir/dune b/src/ir_def/dune similarity index 75% rename from src/as_ir/dune rename to src/ir_def/dune index e08e318a43d..e2314901c80 100644 --- a/src/as_ir/dune +++ b/src/ir_def/dune @@ -1,4 +1,4 @@ (library - (name as_ir) + (name ir_def) (libraries lib as_types as_values) ) diff --git a/src/as_ir/freevars.ml b/src/ir_def/freevars.ml similarity index 100% rename from src/as_ir/freevars.ml rename to src/ir_def/freevars.ml diff --git a/src/as_ir/ir.ml b/src/ir_def/ir.ml similarity index 100% rename from src/as_ir/ir.ml rename to src/ir_def/ir.ml diff --git a/src/as_ir/ir_effect.ml b/src/ir_def/ir_effect.ml similarity index 100% rename from src/as_ir/ir_effect.ml rename to src/ir_def/ir_effect.ml diff --git a/src/as_ir/ir_effect.mli b/src/ir_def/ir_effect.mli similarity index 100% rename from src/as_ir/ir_effect.mli rename to src/ir_def/ir_effect.mli diff --git a/src/ir_interpreter/dune b/src/ir_interpreter/dune index ec88c028790..76f2ee2a74a 100644 --- a/src/ir_interpreter/dune +++ b/src/ir_interpreter/dune @@ -1,4 +1,4 @@ (library (name ir_interpreter) - (libraries lib as_types as_values as_ir profiler) + (libraries lib as_types as_values ir_def profiler) ) diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index f35d85f3b2a..f544fea0efd 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -1,6 +1,6 @@ open As_types open As_values -open As_ir +open Ir_def open Ir open Source diff --git a/src/ir_interpreter/interpret_ir.mli b/src/ir_interpreter/interpret_ir.mli index 94bf126ac19..97c54b6cfb9 100644 --- a/src/ir_interpreter/interpret_ir.mli +++ b/src/ir_interpreter/interpret_ir.mli @@ -1,6 +1,6 @@ open As_types open As_values -open As_ir +open Ir_def module V = Value module T = Type diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index 957f9873fe0..994dc314150 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -1,5 +1,6 @@ open As_types -open As_ir +open Ir_def + module E = Env open Source module Ir = Ir diff --git a/src/ir_passes/async.mli b/src/ir_passes/async.mli index af974b3217b..c0fc1977ef3 100644 --- a/src/ir_passes/async.mli +++ b/src/ir_passes/async.mli @@ -1,4 +1,4 @@ (* lower uses of async type appropriately *) -open As_ir +open Ir_def val transform : As_types.Scope.scope -> Ir.prog -> Ir.prog diff --git a/src/ir_passes/await.ml b/src/ir_passes/await.ml index 62b2a6a8987..33e3eb54f54 100644 --- a/src/ir_passes/await.ml +++ b/src/ir_passes/await.ml @@ -1,9 +1,11 @@ -open As_ir +open Ir_def +open As_types + open Source open Ir open Ir_effect module R = Rename -module T = As_types.Type +module T = Type open Construct (* continuations, syntactic and meta-level *) diff --git a/src/ir_passes/await.mli b/src/ir_passes/await.mli index af98a42c581..adf4580dd39 100644 --- a/src/ir_passes/await.mli +++ b/src/ir_passes/await.mli @@ -1,3 +1,4 @@ (* lower uses of async and await to continuation passing style *) -open As_ir +open Ir_def + val transform : Ir.prog -> Ir.prog diff --git a/src/ir_passes/dune b/src/ir_passes/dune index 0a249ed5227..f21c8932d3f 100644 --- a/src/ir_passes/dune +++ b/src/ir_passes/dune @@ -1,4 +1,4 @@ (library (name ir_passes) - (libraries lib as_ir) + (libraries lib ir_def) ) diff --git a/src/ir_passes/rename.ml b/src/ir_passes/rename.ml index 3d32496042b..ed77b58f224 100644 --- a/src/ir_passes/rename.ml +++ b/src/ir_passes/rename.ml @@ -1,4 +1,5 @@ -open As_ir +open Ir_def + open Source open Ir diff --git a/src/ir_passes/serialization.ml b/src/ir_passes/serialization.ml index 2daacd994ec..80c4bf3681c 100644 --- a/src/ir_passes/serialization.ml +++ b/src/ir_passes/serialization.ml @@ -1,5 +1,6 @@ -open As_ir +open Ir_def open As_types + open Source open Ir module T = Type diff --git a/src/ir_passes/serialization.mli b/src/ir_passes/serialization.mli index efab3b5b661..c25737838df 100644 --- a/src/ir_passes/serialization.mli +++ b/src/ir_passes/serialization.mli @@ -1,2 +1,3 @@ -open As_ir +open Ir_def + val transform : As_types.Scope.scope -> Ir.prog -> Ir.prog diff --git a/src/ir_passes/show.ml b/src/ir_passes/show.ml index 05beea657ca..58b78f52249 100644 --- a/src/ir_passes/show.ml +++ b/src/ir_passes/show.ml @@ -1,4 +1,4 @@ -open As_ir +open Ir_def open As_types open As_values (* Translates away calls to `show`. *) diff --git a/src/ir_passes/show.mli b/src/ir_passes/show.mli index 01f7f067f94..aec760b211b 100644 --- a/src/ir_passes/show.mli +++ b/src/ir_passes/show.mli @@ -1,3 +1,3 @@ -open As_ir +open Ir_def val transform : 'a -> Ir.prog -> Ir.prog diff --git a/src/ir_passes/tailcall.ml b/src/ir_passes/tailcall.ml index 440018b47eb..d775af681b4 100644 --- a/src/ir_passes/tailcall.ml +++ b/src/ir_passes/tailcall.ml @@ -1,4 +1,4 @@ -open As_ir +open Ir_def open As_types open Source diff --git a/src/ir_passes/tailcall.mli b/src/ir_passes/tailcall.mli index 452c14782d6..28b6c3bbb72 100644 --- a/src/ir_passes/tailcall.mli +++ b/src/ir_passes/tailcall.mli @@ -1,6 +1,6 @@ (* Optimize (self) tail calls to jumps, avoiding stack overflow, in a single linear pass *) -open As_ir +open Ir_def val transform: Ir.prog -> Ir.prog diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 0072520ae13..8794c6d45d5 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -1,5 +1,5 @@ -open As_ir -open As_frontend +open Ir_def +open As_def open As_types open As_values @@ -7,7 +7,7 @@ open Source open Operator module S = Syntax module I = Ir -module T = As_types.Type +module T = Type open Construct (* diff --git a/src/lowering/desugar.mli b/src/lowering/desugar.mli index 6a5962c4fda..00110d42f0e 100644 --- a/src/lowering/desugar.mli +++ b/src/lowering/desugar.mli @@ -1,5 +1,6 @@ -open As_frontend -open As_ir +open As_def +open As_types +open Ir_def val transform : Syntax.prog -> Ir.prog -val transform_graph : As_types.Scope.lib_env -> Syntax.libraries -> Syntax.prog list -> Ir.prog +val transform_graph : Scope.lib_env -> Syntax.libraries -> Syntax.prog list -> Ir.prog diff --git a/src/lowering/dune b/src/lowering/dune index f15ddb41097..617ce491e6c 100644 --- a/src/lowering/dune +++ b/src/lowering/dune @@ -1,4 +1,4 @@ (library (name lowering) - (libraries lib as_frontend as_ir) + (libraries lib as_def ir_def) ) diff --git a/src/pipeline/dune b/src/pipeline/dune index 303e23e55e6..31ba8205364 100644 --- a/src/pipeline/dune +++ b/src/pipeline/dune @@ -3,14 +3,15 @@ (libraries lib lang_utils + as_def as_types as_values as_frontend - as_ir + as_interpreter + lowering wasm_exts - interpreter + ir_def ir_interpreter - lowering ir_passes codegen ) diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index a4ca869d834..7313b59fbee 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -1,8 +1,12 @@ +open As_def open As_frontend open As_types open As_values -open As_ir -open Interpreter +open As_interpreter +open Ir_def +open Ir_interpreter +open Ir_passes + open Printf type stat_env = Scope.t @@ -438,19 +442,19 @@ let desugar env lib_env libraries progs name = prog_ir' let await_lowering = - transform_if "Await Lowering" (fun _ -> Ir_passes.Await.transform) + transform_if "Await Lowering" (fun _ -> Await.transform) let async_lowering = - transform_if "Async Lowering" Ir_passes.Async.transform + transform_if "Async Lowering" Async.transform let serialization = - transform_if "Synthesizing serialization code" Ir_passes.Serialization.transform + transform_if "Synthesizing serialization code" Serialization.transform let tailcall_optimization = - transform_if "Tailcall optimization" (fun _ -> Ir_passes.Tailcall.transform) + transform_if "Tailcall optimization" (fun _ -> Tailcall.transform) let show_translation = - transform_if "Translate show" Ir_passes.Show.transform + transform_if "Translate show" Show.transform (* Compilation *) @@ -518,7 +522,7 @@ let interpret_ir_prog inp_env libraries progs = let name = name_progs progs in let prog_ir = lower_prog initial_stat_env inp_env libraries progs name in phase "Interpreting" name; - let open Ir_interpreter.Interpret_ir in + let open Interpret_ir in let flags = { trace = !Flags.trace; print_depth = !Flags.print_depth } in let denv0 = empty_scope in let dscope = interpret_prog flags denv0 prelude_ir in diff --git a/src/pipeline/pipeline.mli b/src/pipeline/pipeline.mli index a35a2fd69b1..8b185d1fe69 100644 --- a/src/pipeline/pipeline.mli +++ b/src/pipeline/pipeline.mli @@ -1,3 +1,6 @@ +open As_def +open As_types + module Flags : sig val trace : bool ref @@ -19,10 +22,8 @@ end val check_files : string list -> unit Diag.result val check_string : string -> string -> unit Diag.result -val chase_imports - : As_types.Scope.scope - -> Resolve_import.S.t - -> (As_frontend.Syntax.libraries * As_types.Scope.scope) Diag.result +val chase_imports : Scope.scope -> Resolve_import.S.t -> + (Syntax.libraries * Scope.scope) Diag.result val run_files : string list -> unit option val interpret_ir_files : string list -> unit option @@ -30,5 +31,6 @@ val run_files_and_stdin : string list -> unit option type compile_mode = WasmMode | DfinityMode type compile_result = Wasm_exts.CustomModule.extended_module Diag.result + val compile_string : compile_mode -> string -> string -> compile_result val compile_files : compile_mode -> bool -> string list -> compile_result diff --git a/src/pipeline/resolve_import.ml b/src/pipeline/resolve_import.ml index 7c28668fb4f..c00b903dc5d 100644 --- a/src/pipeline/resolve_import.ml +++ b/src/pipeline/resolve_import.ml @@ -1,4 +1,4 @@ -open As_frontend +open As_def (* This module traverses the syntax tree. For each `import` statement, it looks diff --git a/src/pipeline/resolve_import.mli b/src/pipeline/resolve_import.mli index 55f685fe253..2d1bc23d43e 100644 --- a/src/pipeline/resolve_import.mli +++ b/src/pipeline/resolve_import.mli @@ -1,4 +1,4 @@ -open As_frontend +open As_def module S : Set.S with type elt = String.t From 6fac3d9808763d49b1fe9ec0cd80930dafaa6f70 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Sat, 6 Jul 2019 09:17:44 +0200 Subject: [PATCH 0236/1176] Move as_js out of exes (#556) to quench a warning from dune --- src/Makefile | 2 +- src/exes/dune | 8 -------- src/{exes => js}/as_js.ml | 0 src/js/dune | 8 ++++++++ 4 files changed, 9 insertions(+), 9 deletions(-) rename src/{exes => js}/as_js.ml (100%) create mode 100644 src/js/dune diff --git a/src/Makefile b/src/Makefile index e70652258ed..5a690143288 100644 --- a/src/Makefile +++ b/src/Makefile @@ -6,7 +6,7 @@ AS_IDE_TARGET = _build/default/exes/as_ide.exe AS_LD_TARGET = _build/default/exes/as_ld.exe ASC_TARGET = _build/default/exes/asc.exe DIDC_TARGET = _build/default/exes/didc.exe -ASC_JS_TARGET = _build/default/exes/as_js.bc.js +ASC_JS_TARGET = _build/default/js/as_js.bc.js DUNE_OPTS ?= diff --git a/src/exes/dune b/src/exes/dune index 70fcc5c89ab..d94e942a9fa 100644 --- a/src/exes/dune +++ b/src/exes/dune @@ -18,11 +18,3 @@ (modules didc) (libraries idllib) ) -(executable - (name as_js) - (modules as_js) - (libraries pipeline) - (preprocess (pps js_of_ocaml-ppx)) - (js_of_ocaml (flags :standard "+nat.js") ) -) - diff --git a/src/exes/as_js.ml b/src/js/as_js.ml similarity index 100% rename from src/exes/as_js.ml rename to src/js/as_js.ml diff --git a/src/js/dune b/src/js/dune new file mode 100644 index 00000000000..d7ee87b5b5d --- /dev/null +++ b/src/js/dune @@ -0,0 +1,8 @@ +(executable + (name as_js) + (modules as_js) + (libraries pipeline) + (preprocess (pps js_of_ocaml-ppx)) + (js_of_ocaml (flags :standard "+nat.js") ) +) + From 7f16357a654b1f047dfb37fd8d3a7e6306c56648 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Sat, 6 Jul 2019 13:35:06 +0200 Subject: [PATCH 0237/1176] Do not define StackRep.of_type Non (#555) * Do not define StackRep.of_type Non as neither `Vanilla` nor `Unreachable` is correct. Instead, allow `compile_binop` to return a different stack rep for the input and the output. A minor clean-up post #538. * Update test output --- src/codegen/compile.ml | 117 ++++++++++++------------- test/run/ok/numeric-ops.wasm.stderr.ok | 10 +++ 2 files changed, 68 insertions(+), 59 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index c011dd42a2c..c4f81db7a73 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -3712,7 +3712,6 @@ module StackRep = struct | Prim (Nat32 | Int32 | Word32) -> UnboxedWord32 | Prim (Nat8 | Nat16 | Int8 | Int16 | Word8 | Word16 | Char) -> Vanilla | Prim Text -> Vanilla - | Non -> Vanilla | p -> todo "of_type" (Arrange_ir.typ p) Vanilla let to_block_type env = function @@ -4516,60 +4515,61 @@ let prim_of_typ ty = match Type.normalize ty with let then_arithmetic_overflow env = E.then_trap_with env "arithmetic overflow" +(* The first returned StackRep is for the arguments (expected), the second for the results (produced) *) let compile_unop env t op = let open Operator in match op, t with + | _, Type.Non -> + SR.Vanilla, SR.Unreachable, G.i Unreachable | NegOp, Type.(Prim Int) -> - SR.Vanilla, - BigNum.compile_neg env + SR.Vanilla, SR.Vanilla, + BigNum.compile_neg env | NegOp, Type.(Prim Word64) -> - SR.UnboxedWord64, - Func.share_code1 env "neg" ("n", I64Type) [I64Type] (fun env get_n -> - compile_const_64 0L ^^ - get_n ^^ - G.i (Binary (Wasm.Values.I64 I64Op.Sub)) - ) + SR.UnboxedWord64, SR.UnboxedWord64, + Func.share_code1 env "neg" ("n", I64Type) [I64Type] (fun env get_n -> + compile_const_64 0L ^^ + get_n ^^ + G.i (Binary (Wasm.Values.I64 I64Op.Sub)) + ) | NegOp, Type.(Prim Int64) -> - SR.UnboxedWord64, - Func.share_code1 env "neg_trap" ("n", I64Type) [I64Type] (fun env get_n -> - get_n ^^ - compile_const_64 0x8000000000000000L ^^ - G.i (Compare (Wasm.Values.I64 I64Op.Eq)) ^^ - then_arithmetic_overflow env ^^ - compile_const_64 0L ^^ - get_n ^^ - G.i (Binary (Wasm.Values.I64 I64Op.Sub)) - ) + SR.UnboxedWord64, SR.UnboxedWord64, + Func.share_code1 env "neg_trap" ("n", I64Type) [I64Type] (fun env get_n -> + get_n ^^ + compile_const_64 0x8000000000000000L ^^ + G.i (Compare (Wasm.Values.I64 I64Op.Eq)) ^^ + then_arithmetic_overflow env ^^ + compile_const_64 0L ^^ + get_n ^^ + G.i (Binary (Wasm.Values.I64 I64Op.Sub)) + ) | NegOp, Type.(Prim (Word8 | Word16 | Word32)) -> - StackRep.of_type t, - Func.share_code1 env "neg32" ("n", I32Type) [I32Type] (fun env get_n -> - compile_unboxed_zero ^^ - get_n ^^ - G.i (Binary (Wasm.Values.I32 I32Op.Sub)) - ) + StackRep.of_type t, StackRep.of_type t, + Func.share_code1 env "neg32" ("n", I32Type) [I32Type] (fun env get_n -> + compile_unboxed_zero ^^ + get_n ^^ + G.i (Binary (Wasm.Values.I32 I32Op.Sub)) + ) | NegOp, Type.(Prim (Int8 | Int16 | Int32)) -> - StackRep.of_type t, - Func.share_code1 env "neg32_trap" ("n", I32Type) [I32Type] (fun env get_n -> - get_n ^^ - compile_eq_const 0x80000000l ^^ - then_arithmetic_overflow env ^^ - compile_unboxed_zero ^^ - get_n ^^ - G.i (Binary (Wasm.Values.I32 I32Op.Sub)) - ) + StackRep.of_type t, StackRep.of_type t, + Func.share_code1 env "neg32_trap" ("n", I32Type) [I32Type] (fun env get_n -> + get_n ^^ + compile_eq_const 0x80000000l ^^ + then_arithmetic_overflow env ^^ + compile_unboxed_zero ^^ + get_n ^^ + G.i (Binary (Wasm.Values.I32 I32Op.Sub)) + ) | NotOp, Type.(Prim Word64) -> - SR.UnboxedWord64, + SR.UnboxedWord64, SR.UnboxedWord64, compile_const_64 (-1L) ^^ G.i (Binary (Wasm.Values.I64 I64Op.Xor)) | NotOp, Type.Prim Type.(Word8 | Word16 | Word32 as ty) -> - StackRep.of_type t, compile_unboxed_const (UnboxedSmallWord.mask_of_type ty) ^^ - G.i (Binary (Wasm.Values.I32 I32Op.Xor)) - | _, Type.Non -> - SR.Vanilla, G.i Unreachable + StackRep.of_type t, StackRep.of_type t, + compile_unboxed_const (UnboxedSmallWord.mask_of_type ty) ^^ + G.i (Binary (Wasm.Values.I32 I32Op.Xor)) | _ -> - (* NB: Must not use todo_trap_SR here, as the SR.t here is also passed to - `compile_exp_as`, which does not take SR.Unreachable. *) - todo "compile_unop" (Arrange_ops.unop op) (SR.Vanilla, E.trap_with env "TODO: compile_unop") + todo "compile_unop" (Arrange_ops.unop op) + (SR.Vanilla, SR.Unreachable, E.trap_with env "TODO: compile_unop") (* Logarithmic helpers for deciding whether we can carry out operations in constant bitwidth *) @@ -4704,11 +4704,10 @@ let compile_smallNat_kernel' env ty name op = let compile_smallNat_kernel env ty name op = compile_smallNat_kernel' env ty name (G.i (Binary (Wasm.Values.I32 op))) -(* This returns a single StackRep, to be used for both arguments and the - result. One could imagine operators that require or produce different StackReps, - but none of these do, so a single value is fine. -*) +(* The first returned StackRep is for the arguments (expected), the second for the results (produced) *) let rec compile_binop env t op = + if t = Type.Non then SR.Vanilla, SR.Unreachable, G.i Unreachable else + StackRep.of_type t, StackRep.of_type t, Operator.(match t, op with | Type.(Prim (Nat | Int)), AddOp -> BigNum.compile_add env @@ -4781,7 +4780,7 @@ let rec compile_binop env t op = Wasm.Values.(fun env get_n get_exp -> let one = compile_unboxed_const (UnboxedSmallWord.const_of_type ty 1l) in let (set_res, get_res) = new_local env "res" in - let mul = snd (compile_binop env t MulOp) in + let _,_,mul = compile_binop env t MulOp in let square_recurse_with_shifted sanitize = get_n ^^ get_exp ^^ compile_shrU_const 1l ^^ sanitize ^^ pow () ^^ set_res ^^ get_res ^^ get_res ^^ mul @@ -4813,7 +4812,7 @@ let rec compile_binop env t op = G.i (Compare (Wasm.Values.I32 I32Op.LtS)) ^^ then_arithmetic_overflow env ^^ get_n ^^ UnboxedSmallWord.lsb_adjust ty ^^ get_exp ^^ UnboxedSmallWord.lsb_adjust ty ^^ - snd (compile_binop env Type.(Prim Word32) PowOp) ^^ + let _,_,pow = compile_binop env Type.(Prim Word32) PowOp in pow ^^ set_res ^^ get_res ^^ enforce_unsigned_bits env bits ^^ get_res ^^ UnboxedSmallWord.msb_adjust ty end @@ -4840,7 +4839,7 @@ let rec compile_binop env t op = G.i (Compare (Wasm.Values.I32 I32Op.LtS)) ^^ then_arithmetic_overflow env ^^ get_n ^^ G.i (Convert (Wasm.Values.I64 I64Op.ExtendUI32)) ^^ get_exp ^^ G.i (Convert (Wasm.Values.I64 I64Op.ExtendUI32)) ^^ - snd (compile_binop env Type.(Prim Word64) PowOp) ^^ + let _,_,pow = compile_binop env Type.(Prim Word64) PowOp in pow ^^ set_res ^^ get_res ^^ enforce_32_unsigned_bits env ^^ get_res ^^ G.i (Convert (Wasm.Values.I32 I32Op.WrapI64)) end @@ -4867,7 +4866,7 @@ let rec compile_binop env t op = G.i (Compare (Wasm.Values.I32 I32Op.LtS)) ^^ then_arithmetic_overflow env ^^ get_n ^^ UnboxedSmallWord.lsb_adjust ty ^^ get_exp ^^ UnboxedSmallWord.lsb_adjust ty ^^ - snd (compile_binop env Type.(Prim Word32) PowOp) ^^ + (let _,_,pow = compile_binop env Type.(Prim Word32) PowOp in pow) ^^ set_res ^^ get_res ^^ get_res ^^ enforce_signed_bits env bits ^^ get_res ^^ UnboxedSmallWord.msb_adjust ty end @@ -4910,7 +4909,7 @@ let rec compile_binop env t op = G.i (Compare (Wasm.Values.I32 I32Op.LtS)) ^^ then_arithmetic_overflow env ^^ get_n ^^ G.i (Convert (Wasm.Values.I64 I64Op.ExtendSI32)) ^^ get_exp ^^ G.i (Convert (Wasm.Values.I64 I64Op.ExtendSI32)) ^^ - snd (compile_binop env Type.(Prim Word64) PowOp) ^^ + (let _,_,pow = compile_binop env Type.(Prim Word64) PowOp in pow) ^^ set_res ^^ get_res ^^ get_res ^^ enforce_32_signed_bits env ^^ get_res ^^ G.i (Convert (Wasm.Values.I32 I32Op.WrapI64)) end @@ -5006,6 +5005,7 @@ let compile_comparison env t op = | _ -> todo_trap env "compile_comparison" (Arrange_type.prim t) let compile_relop env t op = + if t = Type.Non then SR.Vanilla, G.i Unreachable else StackRep.of_type t, let open Operator in match t, op with @@ -5014,7 +5014,6 @@ let compile_relop env t op = G.i (Test (Wasm.Values.I32 I32Op.Eqz)) | Type.(Prim (Nat | Nat8 | Nat16 | Nat32 | Nat64 | Int | Int8 | Int16 | Int32 | Int64 | Word8 | Word16 | Word32 | Word64 | Char as t1)), op1 -> compile_comparison env t1 op1 - | Type.Non, _ -> G.i Unreachable | _ -> todo_trap env "compile_relop" (Arrange_ops.relop op) let compile_load_field env typ name = @@ -5328,15 +5327,15 @@ and compile_exp (env : E.t) ae exp = G.if_ (ValBlockType None) G.nop (G.i Unreachable) | UnE (_, Operator.PosOp, e1) -> compile_exp env ae e1 | UnE (t, op, e1) -> - let sr, code = compile_unop env t op in - sr, - compile_exp_as env ae sr e1 ^^ + let sr_in, sr_out, code = compile_unop env t op in + sr_out, + compile_exp_as env ae sr_in e1 ^^ code | BinE (t, e1, op, e2) -> - let sr, code = compile_binop env t op in - sr, - compile_exp_as env ae sr e1 ^^ - compile_exp_as env ae sr e2 ^^ + let sr_in, sr_out, code = compile_binop env t op in + sr_out, + compile_exp_as env ae sr_in e1 ^^ + compile_exp_as env ae sr_in e2 ^^ code | RelE (t, e1, op, e2) -> let sr, code = compile_relop env t op in diff --git a/test/run/ok/numeric-ops.wasm.stderr.ok b/test/run/ok/numeric-ops.wasm.stderr.ok index 20555433169..542e3add28a 100644 --- a/test/run/ok/numeric-ops.wasm.stderr.ok +++ b/test/run/ok/numeric-ops.wasm.stderr.ok @@ -2,21 +2,31 @@ compile_unop: NegOp compile_unop: NegOp compile_binop: AddOp of_type: Float +of_type: Float compile_binop: AddOp of_type: Float +of_type: Float compile_binop: SubOp of_type: Float +of_type: Float compile_binop: SubOp of_type: Float +of_type: Float compile_binop: MulOp of_type: Float +of_type: Float compile_binop: MulOp of_type: Float +of_type: Float compile_binop: DivOp of_type: Float +of_type: Float compile_binop: DivOp of_type: Float +of_type: Float compile_binop: PowOp of_type: Float +of_type: Float compile_binop: PowOp of_type: Float +of_type: Float From 3b1ab6faa75fbf7be09703c42d382b8cb2cfa789 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 8 Jul 2019 14:05:02 +0200 Subject: [PATCH 0238/1176] Extend .gitignore (#557) --- src/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/src/.gitignore b/src/.gitignore index f29f5bb05c3..93000a9ee37 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -1,6 +1,7 @@ # generated by Makefile /asc /as-ld +/as-id /asc.js /didc From 0de15afe3812f842d2c9f09fbe377cb0296f03c2 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Mon, 8 Jul 2019 19:12:30 +0200 Subject: [PATCH 0239/1176] Note some accomplishments in README (#547) * Some accomplishments (remaining open features updated) --- README.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 3c548cba4a2..e9193f3ceeb 100644 --- a/README.md +++ b/README.md @@ -38,17 +38,13 @@ A simple language for writing Dfinity actors. * Gas-related features? -* Infinite-precision integers - -* Richer destructuring and pattern matching - * Exception handling * Tail calls * Mixin composition for inheritance -* Fancier types (generic bounds, top type?, union types?, co/contra-variance?) +* Fancier types (co/contra-variance annotations?) * Linear types? @@ -64,6 +60,7 @@ A simple language for writing Dfinity actors. * Primitive types: integers, naturals, words, floats, characters, (unicode) text, bool, null - `Int`, `Nat` (trap on overflow) - `Word8`, `Word16`, `Word32`, `Word64` (wrap around) + - `Int8`, `Int16`, `Int32`, `Int64`, `Nat8`, `Nat16`, `Nat32`, `Nat64` (trap on over/underflow) - `Float` - `Char`, `Text` - `Bool`, `Null` From e6e544ce339947dc0f5b0b3f18262c3de95e8629 Mon Sep 17 00:00:00 2001 From: Christoph Hegemann Date: Mon, 8 Jul 2019 22:16:02 +0200 Subject: [PATCH 0240/1176] Normalises file paths for modules (#554) * adds functions that normalise file paths * normalises file paths before inserting them into the library env * file_path is a better name for operations on file paths * normalise both paths before checking if they are relative to another * Applies review suggestions from Andreas - File names can't contain slashes, so a simple String.split is good enough to figure out the components * make relative_to also work for relative paths * adds a test for relative_to on relative paths * adjusts self import test * add tests for path normalisation Checks that every module is only parsed once * address review nit --- src/pipeline/dune | 3 + src/pipeline/file_path.ml | 25 ++++++++ src/pipeline/file_path.mli | 16 +++++ src/pipeline/file_path_test.ml | 88 ++++++++++++++++++++++++++++ src/pipeline/resolve_import.ml | 1 + test/fail/ok/self-import.tc.ok | 2 +- test/repl/lib/nested.as | 2 + test/repl/lib/nested/a.as | 1 + test/repl/lib/nested/b.as | 3 + test/repl/nested-import.sh | 4 ++ test/repl/ok/nested-import.stdout.ok | 5 ++ 11 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 src/pipeline/file_path.ml create mode 100644 src/pipeline/file_path.mli create mode 100644 src/pipeline/file_path_test.ml create mode 100644 test/repl/lib/nested.as create mode 100644 test/repl/lib/nested/a.as create mode 100644 test/repl/lib/nested/b.as create mode 100755 test/repl/nested-import.sh create mode 100644 test/repl/ok/nested-import.stdout.ok diff --git a/src/pipeline/dune b/src/pipeline/dune index 31ba8205364..eab27a21a0b 100644 --- a/src/pipeline/dune +++ b/src/pipeline/dune @@ -2,6 +2,7 @@ (name pipeline) (libraries lib + base lang_utils as_def as_types @@ -15,4 +16,6 @@ ir_passes codegen ) + (inline_tests) + (preprocess (pps ppx_inline_test)) ) diff --git a/src/pipeline/file_path.ml b/src/pipeline/file_path.ml new file mode 100644 index 00000000000..44eaa8ee54a --- /dev/null +++ b/src/pipeline/file_path.ml @@ -0,0 +1,25 @@ +let normalise file_path = + let has_trailing_slash = + Base.Option.is_some (Base.String.chop_suffix ~suffix:"/" file_path) in + let has_leading_slash = not (Filename.is_relative file_path) in + let acc = Stack.create () in + Lib.String.split file_path '/' + |> List.iter + (function + | "" -> () + | "." -> () + | ".." -> + if Stack.is_empty acc + then Stack.push ".." acc + else ignore (Stack.pop acc) + | segment -> Stack.push segment acc); + let result = Stack.fold (fun x y -> y ^ "/" ^ x) "" acc in + let prefix = if has_leading_slash then "/" else "" in + prefix ^ (if has_trailing_slash + then result + else Base.String.chop_suffix_exn ~suffix:"/" result) + +let relative_to base path = + Base.String.chop_prefix + ~prefix:(normalise (base ^ "/")) + (normalise path) diff --git a/src/pipeline/file_path.mli b/src/pipeline/file_path.mli new file mode 100644 index 00000000000..2cf21b0011f --- /dev/null +++ b/src/pipeline/file_path.mli @@ -0,0 +1,16 @@ +(** + * Normalises a file path + *) +val normalise : string -> string + +(** + * Makes one path relative to another path. + * + * Examples: + * + * relative_to "/home/foo" "/home/foo/project" = Some "project" + * relative_to "/home/foo" "/home/foo/project/lib" = Some "project/lib" + * relative_to "/home/foo" "/home/bar/project" = None + * relative_to "foo/bar" "foo/bar/project" = Some "project" + *) +val relative_to : string -> string -> string option diff --git a/src/pipeline/file_path_test.ml b/src/pipeline/file_path_test.ml new file mode 100644 index 00000000000..31aee54bb04 --- /dev/null +++ b/src/pipeline/file_path_test.ml @@ -0,0 +1,88 @@ +let normalise_test_case input expected = + let actual = File_path.normalise input in + if String.equal actual expected + then true + else (Printf.printf "\nExpected: %s\nActual: %s\n" expected actual; false) + +let relative_to_test_case root contained expected = + let actual = File_path.relative_to root contained in + let show = function + | None -> "None" + | Some s -> "Some " ^ s in + if Base.Option.equal Base.String.equal actual expected + then true + else + (Printf.printf + "\nExpected: %s\nActual: %s\n" + (show expected) + (show actual); + false) + +let%test "it removes leading `./` for relative paths" = + normalise_test_case "./lib/foo" "lib/foo" + +let%test "it removes duplicate `//`s" = + normalise_test_case ".//lib/foo" "lib/foo" + +let%test "it preserves trailing slashes" = + normalise_test_case "lib/foo/" "lib/foo/" + +let%test "it drops intermediate references to the `.` directory" = + normalise_test_case "lib/./foo/" "lib/foo/" + +let%test "it applies parent directory traversals" = + normalise_test_case "lib/../foo/" "foo/" + +let%test "it keeps parent directory references at the start of a path" = + normalise_test_case "../foo/lib" "../foo/lib" + +let%test "it does everything at once" = + normalise_test_case "../foo//.././lib" "../lib" + +let%test "it handles absolute paths" = + normalise_test_case "/foo" "/foo" + +let%test "it handles absolute directory paths" = + normalise_test_case "/foo/./lib/" "/foo/lib/" + +let%test "it makes one absolute path relative to another one" = + relative_to_test_case + "/home/project" + "/home/project/src/main.as" + (Some "src/main.as") + +let%test "it's robust in the face of trailing slashes" = + relative_to_test_case + "/home/project/" + "/home/project/src/main.as" + (Some "src/main.as") + +let%test "it makes a file path relative to a path" = + relative_to_test_case + "/home/project" + "/home/project/main.as" + (Some "main.as") + +let%test "it preserves trailing slashes" = + relative_to_test_case + "/home/project/" + "/home/project/src/" + (Some "src/") + +let%test "it handles directory traversals" = + relative_to_test_case + "/home/project" + "/home/project/src/../lib/" + (Some "lib/") + +let%test "it fails to make disjoint paths relative to one another" = + relative_to_test_case + "/home/project" + "/home/main.as" + None + +let%test "it handles relative paths" = + relative_to_test_case + "project/src" + "project/src/Main.as" + (Some "Main.as") diff --git a/src/pipeline/resolve_import.ml b/src/pipeline/resolve_import.ml index c00b903dc5d..b1987fcc461 100644 --- a/src/pipeline/resolve_import.ml +++ b/src/pipeline/resolve_import.ml @@ -39,6 +39,7 @@ let rec if Sys.file_exists f && Sys.is_directory f then Filename.concat f "lib.as" else f in + let f = File_path.normalise f in if Sys.file_exists f then begin fp := f; diff --git a/test/fail/ok/self-import.tc.ok b/test/fail/ok/self-import.tc.ok index 5705c4da733..3ee8ccd9faf 100644 --- a/test/fail/ok/self-import.tc.ok +++ b/test/fail/ok/self-import.tc.ok @@ -1 +1 @@ -(unknown location): import error, file ./self-import.as must not depend on itself +(unknown location): import error, file self-import.as must not depend on itself diff --git a/test/repl/lib/nested.as b/test/repl/lib/nested.as new file mode 100644 index 00000000000..b22aecefea3 --- /dev/null +++ b/test/repl/lib/nested.as @@ -0,0 +1,2 @@ +import A "nested/a.as"; +import "nested/b.as" diff --git a/test/repl/lib/nested/a.as b/test/repl/lib/nested/a.as new file mode 100644 index 00000000000..d81cc0710eb --- /dev/null +++ b/test/repl/lib/nested/a.as @@ -0,0 +1 @@ +42 diff --git a/test/repl/lib/nested/b.as b/test/repl/lib/nested/b.as new file mode 100644 index 00000000000..ac75e1c4228 --- /dev/null +++ b/test/repl/lib/nested/b.as @@ -0,0 +1,3 @@ +module { + import "./a.as"; +} diff --git a/test/repl/nested-import.sh b/test/repl/nested-import.sh new file mode 100755 index 00000000000..2d8a2f5602d --- /dev/null +++ b/test/repl/nested-import.sh @@ -0,0 +1,4 @@ +#!/bin/bash +${ASC:-$(dirname "$BASH_SOURCE")/../../src/asc} -v -i <<__END__ | grep Parsing +import "lib/nested.as"; +__END__ diff --git a/test/repl/ok/nested-import.stdout.ok b/test/repl/ok/nested-import.stdout.ok new file mode 100644 index 00000000000..a5d14862a3a --- /dev/null +++ b/test/repl/ok/nested-import.stdout.ok @@ -0,0 +1,5 @@ +-- Parsing stdin: +> -- Parsing nested.as: +-- Parsing a.as: +-- Parsing b.as: +-- Parsing stdin: From a4e1208392c2d50727a16a72f32ad45560663fb0 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Tue, 9 Jul 2019 08:19:41 -0700 Subject: [PATCH 0241/1176] accept --package options --- src/exes/asc.ml | 10 +++ src/lang_utils/diag.mli | 1 + src/pipeline/pipeline.ml | 6 +- src/pipeline/pipeline.mli | 2 + src/pipeline/resolve_import.ml | 117 +++++++++++++++++++++++++------- src/pipeline/resolve_import.mli | 4 +- 6 files changed, 113 insertions(+), 27 deletions(-) diff --git a/src/exes/asc.ml b/src/exes/asc.ml index 4f79f221b00..a3c2d67f26c 100644 --- a/src/exes/asc.ml +++ b/src/exes/asc.ml @@ -43,6 +43,16 @@ let argspec = Arg.align "--map", Arg.Set gen_source_map, " output source map"; "-t", Arg.Set Pipeline.Flags.trace, " activate tracing"; + "--package", Arg.Tuple [ + Arg.Set_string Pipeline.Flags.package_name_temp ; + Arg.String begin fun package_url -> + (* push (package_name, package_url) onto the list. *) + Pipeline.Flags.package_urls := ( + !Pipeline.Flags.package_name_temp, + package_url + ) :: ! Pipeline.Flags.package_urls + end + ], " Specify a package-name-package-URL pair, separated by a space" ; "--profile", Arg.Set Pipeline.Flags.profile, " activate profiling counters in interpreters "; "--profile-file", Arg.Set_string Pipeline.Flags.profile_file, " set profiling output file "; "--profile-line-prefix", Arg.Set_string Pipeline.Flags.profile_line_prefix, " prefix each profile line with the given string "; diff --git a/src/lang_utils/diag.mli b/src/lang_utils/diag.mli index b76c34f1495..357bdebd2d4 100644 --- a/src/lang_utils/diag.mli +++ b/src/lang_utils/diag.mli @@ -48,5 +48,6 @@ the reported messages contain an error. type msg_store val add_msg : msg_store -> message -> unit val add_msgs : msg_store -> messages -> unit +val get_msgs : msg_store -> messages val with_message_store : (msg_store -> 'a option) -> 'a result diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index 7313b59fbee..da6cd13f939 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -23,6 +23,8 @@ module Flags = struct let dump_tc = ref false let dump_lowering = ref false let check_ir = ref true + let package_urls : (string * string) list ref = ref [] + let package_name_temp : string ref = ref "DEADBEEF" let profile = ref false let profile_verbose = ref false let profile_file = ref "profiling-counters.csv" @@ -128,7 +130,7 @@ type resolve_result = (Syntax.prog * Resolve_import.S.t) Diag.result let resolve_prog (prog, base) : resolve_result = Diag.map (fun libraries -> (prog, libraries)) - (Resolve_import.resolve prog base) + (Resolve_import.resolve !Flags.package_urls prog base) let resolve_progs = Diag.traverse resolve_prog @@ -220,7 +222,7 @@ let chase_imports senv0 imports : (Syntax.libraries * Scope.scope) Diag.result = pending := add f !pending; Diag.bind (parse_file f) (fun (prog, base) -> Diag.bind (Static.prog prog) (fun () -> - Diag.bind (Resolve_import.resolve prog base) (fun more_imports -> + Diag.bind (Resolve_import.resolve !Flags.package_urls prog base) (fun more_imports -> Diag.bind (go_set more_imports) (fun () -> Diag.bind (typecheck_library !senv f prog) (fun sscope -> Diag.bind (defindeness_prog prog) (fun () -> diff --git a/src/pipeline/pipeline.mli b/src/pipeline/pipeline.mli index 8b185d1fe69..1bbbb5442e0 100644 --- a/src/pipeline/pipeline.mli +++ b/src/pipeline/pipeline.mli @@ -12,6 +12,8 @@ sig val dump_tc : bool ref val dump_lowering : bool ref val check_ir : bool ref + val package_name_temp : string ref + val package_urls : (string * string) list ref val profile : bool ref val profile_verbose : bool ref val profile_file : string ref diff --git a/src/pipeline/resolve_import.ml b/src/pipeline/resolve_import.ml index c00b903dc5d..9c169bb7592 100644 --- a/src/pipeline/resolve_import.ml +++ b/src/pipeline/resolve_import.ml @@ -10,7 +10,15 @@ in the second, mutable field of the ImportE statement. It returns a list of all imported file names. -At some point, SEARCH_PATH functionality would be added here. + +SEARCH_PATH functionality +-------------------------- +- Uses `--package` CLI option +- See Jira Ticket: https://dfinity.atlassian.net/browse/SDK-269 +- See also: `Pipeline.Flags.package_urls`, of type `(string * string) list ref`; + - Each key-value pair gives a package-name, package-URL pairing + - the URL can be interpreted as a filesystem path, for now. + *) (* written as a functor so we can allocate some temporary shared state without making it global *) @@ -18,39 +26,74 @@ At some point, SEARCH_PATH functionality would be added here. type filepath = string module S = Set.Make(String) +module M = Map.Make(String) + +(* type packages maps package names to package URLs (filenames): + e.g., packages("std") = "/Users/home/username/.dfinity-sdk/src/as-stdlib" +*) +type package_map = string M.t type env = { msgs : Diag.msg_store; base : filepath; + packages : package_map; imported : S.t ref; } open Syntax open Source -let rec - exp env (e : exp) = match e.it with - | ImportE (f, fp) -> - let f = - if Filename.is_relative f - then Filename.concat env.base f - else f in - let f = - if Sys.file_exists f && Sys.is_directory f - then Filename.concat f "lib.as" - else f in - if Sys.file_exists f - then begin + +let resolve_import_string env region (f: string) (fp: string ref) = + let f = + if Filename.is_relative f + then Filename.concat env.base f + else f in + let f = + if Sys.file_exists f && Sys.is_directory f + then Filename.concat f "lib.as" + else f in + if Sys.file_exists f + then begin fp := f; env.imported := S.add f !(env.imported) end else - let open Diag in - add_msg env.msgs { + let open Diag in + add_msg env.msgs { sev = Error; - at = e.at; + at = region; cat = "import"; text = Printf.sprintf "File \"%s\" does not exist" f } + +(* compare to the `resolve_import_string`'s filesystem semantics; + the two resolution semantics agree for now, + but other API details and usage are distinct. + *) +let resolve_package_url (msgs:Diag.msg_store) (base:filepath) (pname:string) (f: string) : string option = + let f = + if Filename.is_relative f + then Filename.concat base f + else f in + let f = + if Sys.file_exists f && Sys.is_directory f + then Filename.concat f "lib.as" + else f in + if Sys.file_exists f then + Some f + else + let open Diag in + add_msg msgs { + sev = Error; + at = no_region; + cat = "package"; + text = Printf.sprintf "File \"%s\" (for package `%s`) does not exist" f pname + }; + None + +let rec + exp env (e : exp) = match e.it with + | ImportE (f, fp) -> resolve_import_string env e.at f fp (* The rest is just a boring syntax traversal *) | (PrimE _ | VarE _ | LitE _) -> () | UnE (_, _, exp1) @@ -109,10 +152,36 @@ and dec env d = match d.it with let prog env p = decs env p.it -let resolve : Syntax.prog -> filepath -> S.t Diag.result = fun p base -> - Diag.with_message_store (fun msgs -> - let base = if Sys.is_directory base then base else Filename.dirname base in - let env = { msgs; base; imported = ref S.empty } in - prog env p; - Some !(env.imported) - ) +type package_urls = (string * string) list + +let resolve_packages : package_urls -> filepath -> package_map Diag.result = fun purls base -> + Diag.fold (fun package_map (package_name, package_url) -> + if M.mem package_name package_map then + Diag.with_message_store (fun msgs -> + let open Diag in + Diag.add_msg msgs { + sev = Error; + at = no_region; + cat = "--package"; + text = Printf.sprintf "Package name \"%s\" already defined" package_name; + }; + None + ) + else + Diag.with_message_store (fun msgs -> + match resolve_package_url msgs base package_name package_url with + | None -> None + | Some resolved_url -> Some (M.add package_name resolved_url package_map) + ) + ) + M.empty purls + +let resolve : package_urls -> Syntax.prog -> filepath -> S.t Diag.result = fun purls p base -> + Diag.bind (resolve_packages purls base) (fun (packages:package_map) -> + Diag.with_message_store (fun msgs -> + let base = if Sys.is_directory base then base else Filename.dirname base in + let env = { msgs; base; imported = ref S.empty; packages } in + prog env p; + Some !(env.imported) + ) + ) diff --git a/src/pipeline/resolve_import.mli b/src/pipeline/resolve_import.mli index 2d1bc23d43e..8f97a5bd5b2 100644 --- a/src/pipeline/resolve_import.mli +++ b/src/pipeline/resolve_import.mli @@ -2,5 +2,7 @@ open As_def module S : Set.S with type elt = String.t -val resolve : Syntax.prog -> string -> S.t Diag.result +type package_urls = (string * string) list + +val resolve : package_urls -> Syntax.prog -> string -> S.t Diag.result From 9889834e33c0c362d852ca12f297c55b26a096e4 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Tue, 9 Jul 2019 08:56:19 -0700 Subject: [PATCH 0242/1176] consult package env to resolve import strings --- src/pipeline/resolve_import.ml | 35 +++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/src/pipeline/resolve_import.ml b/src/pipeline/resolve_import.ml index 9c169bb7592..a6ac989b15e 100644 --- a/src/pipeline/resolve_import.ml +++ b/src/pipeline/resolve_import.ml @@ -43,8 +43,41 @@ type env = { open Syntax open Source +let get_package_name_and_path (f: string) : (string * string) option = + (* loop recursively until we get to a 'self-loop', indicated by dirname '.' ; + in each iteration, we use function pair (dirname, basename) + to decompose the filename. + *) + let rec loop (f: string) (path_accum:string) : (string * string) option = + let (dir, base) = (Filename.dirname f, Filename.basename f) in + match dir with + | "." -> Some (f, path_accum) + | _ -> begin + assert ((Filename.concat dir base) = f) ; + loop dir (Filename.concat base path_accum) + end + in + loop f "" + +(* using env, resolve import strings of the form "package-name/mod1/mod2/item" + into the triple ("package-name", "package-url", "mod1/mod2/item") when the package name is defined. + Does not validate the package url or path. + *) +let resolve_package env (f: string) : (string * string * string) option = + match get_package_name_and_path f with + | None -> None + | Some (name, path) -> + if M.mem name env.packages then + Some (name, M.find name env.packages, path) + else + None let resolve_import_string env region (f: string) (fp: string ref) = + let f = + match resolve_package env f with + | None -> f + | Some (_, url, path) -> Filename.concat url path + in let f = if Filename.is_relative f then Filename.concat env.base f @@ -67,7 +100,7 @@ let resolve_import_string env region (f: string) (fp: string ref) = } (* compare to the `resolve_import_string`'s filesystem semantics; - the two resolution semantics agree for now, + the two import-string to filesystem-path resolution semantics agree for now, but other API details and usage are distinct. *) let resolve_package_url (msgs:Diag.msg_store) (base:filepath) (pname:string) (f: string) : string option = From 0073467edaf08e0d48ca47676f66b392cc48df40 Mon Sep 17 00:00:00 2001 From: Christoph Hegemann Date: Tue, 9 Jul 2019 18:51:54 +0200 Subject: [PATCH 0243/1176] [SDK-268] Parses imports contained in a module (#558) * adds a parser that extracts imports from a module header * parses module header before suggesting imports * use import syntax in stdlib * adds the prelude to the env before chasing imports for completions --- src/.gitignore | 1 + src/languageServer/completion.ml | 62 +++++++++++++------ src/languageServer/completion_test.ml | 87 +++++++++++++++++++++++++++ src/languageServer/languageServer.ml | 14 ++++- src/pipeline/pipeline.mli | 1 + stdlib/assocList.as | 2 +- stdlib/docTable.as | 6 +- stdlib/listTest.as | 2 +- stdlib/option.as | 2 +- stdlib/result.as | 2 +- stdlib/set.as | 9 +-- stdlib/trie.as | 7 ++- stdlib/trie2.as | 11 ++-- 13 files changed, 168 insertions(+), 38 deletions(-) diff --git a/src/.gitignore b/src/.gitignore index 93000a9ee37..b852156ba6a 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -2,6 +2,7 @@ /asc /as-ld /as-id +/as-ide /asc.js /didc diff --git a/src/languageServer/completion.ml b/src/languageServer/completion.ml index 4b9977c63c6..e39e3c3281c 100644 --- a/src/languageServer/completion.ml +++ b/src/languageServer/completion.ml @@ -45,7 +45,7 @@ let make_index (): completion_index = let (libraries, scope) = Diag.run (Pipeline.chase_imports - Scope.empty + Pipeline.initial_stat_env (Pipeline__.Resolve_import.S.of_list (lib_files ()))) in Type.Env.fold (fun path ty acc -> @@ -65,13 +65,43 @@ let string_of_index index = ^ string_of_list string_of_ide_decl decls ^ "\n") +let import_relative_to_project_root root module_path dependency = + match Pipeline__.File_path.relative_to root module_path with + | None -> None + | Some root_to_module -> + root_to_module + |> Filename.dirname + |> Base.Fn.flip Filename.concat dependency + |> Pipeline__.File_path.normalise + |> Lib.Option.some + (* Given the source of a module, figure out under what names what modules have been imported. Normalizes the imported modules filepaths relative to the project root *) -let find_imported_modules file = - [ ("List", "lib/ListLib.as") - ; ("ListFns", "lib/ListFuncs.as") - ] +let parse_module_header project_root current_file_path file = + let lexbuf = Lexing.from_string file in + let next () = Lexer.token Lexer.Normal lexbuf in + let res = ref [] in + let rec loop = function + | Parser.IMPORT -> + (match next () with + | Parser.ID alias -> + (match next () with + | Parser.TEXT path -> + let path = + import_relative_to_project_root + project_root + current_file_path + path in + (match path with + | Some path -> res := (alias, path) :: !res + | None -> ()); + loop (next ()) + | tkn -> loop tkn) + | tkn -> loop tkn) + | Parser.EOF -> List.rev !res + | tkn -> loop (next ()) in + loop (next ()) (* Given a source file and a cursor position in that file, figure out the prefix relevant to searching completions. For example, given: @@ -94,14 +124,6 @@ let find_completion_prefix logger file line column = | Parser.EOF -> Some ident | tkn -> let next_token_start = (Lexer.region lexbuf).Source.left in - let _ = - logger - "completion_prefix" - (Printf.sprintf - "%d:%d::%s\n" - next_token_start.Source.line - next_token_start.Source.column - ident) in if pos_past_cursor next_token_start then Some ident else loop tkn) @@ -112,10 +134,10 @@ let find_completion_prefix logger file line column = (* TODO(Christoph): Don't recompute the index whenever completions are requested *) -let completions (* index *) logger file line column = +let completions (* index *) logger project_root file_path file_contents line column = let index = make_index () in - let imported = find_imported_modules file in - match find_completion_prefix logger file line column with + let imported = parse_module_header project_root file_path file_contents in + match find_completion_prefix logger file_contents line column with | None -> imported |> List.map (fun (alias, _) -> alias, None) @@ -137,11 +159,15 @@ let completions (* index *) logger file line column = | None -> [ (("ERROR: Couldn't find module for prefix: " ^ prefix), None) ] -let completion_handler logger file position = +let completion_handler logger project_root file_path file_contents position = let line = position.Lsp_t.position_line in let column = position.Lsp_t.position_character in let completion_item (lbl, detail) = Lsp_t.{ completion_item_label = lbl ; completion_item_detail = detail } in `CompletionResponse - (List.map completion_item (completions logger file line column)) + (List.map completion_item + (completions logger project_root file_path file_contents line column)) + +let test_completion () = + Printf.printf "%s\n" (string_of_index (make_index ())) diff --git a/src/languageServer/completion_test.ml b/src/languageServer/completion_test.ml index 09a9750956a..aee2ac0b4c8 100644 --- a/src/languageServer/completion_test.ml +++ b/src/languageServer/completion_test.ml @@ -22,6 +22,39 @@ let prefix_test_case file expected = Completion.find_completion_prefix dummy_logger file line column in Base.Option.equal String.equal prefix expected +let import_relative_test_case root module_path import expected = + let actual = + Completion.import_relative_to_project_root root module_path import in + let show = function + | None -> "None" + | Some s -> "Some " ^ s in + if Base.Option.equal Base.String.equal actual expected + then true + else + (Printf.printf + "\nExpected: %s\nActual: %s\n" + (show expected) + (show actual); + false) + +let parse_module_header_test_case project_root current_file file expected = + let actual = + Completion.parse_module_header + project_root + current_file file in + let display_result (alias, path) = Printf.sprintf "%s => \"%s\"" alias path in + let result = Base.List.equal + actual + expected + ~equal:(fun (x, y) (x', y') -> + String.equal x x' && String.equal y y' ) in + if not result then + Printf.printf + "\nExpected: %s\nActual: %s" + (Completion.string_of_list display_result expected) + (Completion.string_of_list display_result actual) else (); + result + let%test "it finds a simple prefix" = prefix_test_case "List.|" (Some "List") @@ -68,3 +101,57 @@ func singleton(x : Int) : Stack = List.we| ListFns.singleton(x); }|} None + +let%test "it makes an import relative to the project root" = + import_relative_test_case + "/home/project" + "/home/project/src/main.as" + "lib/List.as" + (Some "src/lib/List.as") + +let%test "it preserves trailing slashes for directory imports" = + import_relative_test_case + "/home/project" + "/home/project/src/main.as" + "lib/List/" + (Some "src/lib/List/") + +let%test "it can handle parent directory relationships" = + import_relative_test_case + "/home/project" + "/home/project/src/main.as" + "../lib/List.as" + (Some "lib/List.as") + +let%test "it parses a simple module header" = + parse_module_header_test_case + "/project" + "/project/src/Main.as" + "import P \"lib/prelude.as\"" + ["P", "src/lib/prelude.as"] + +let%test "it parses a simple module header" = + parse_module_header_test_case + "/project" + "/project/Main.as" + {| +module { + +private import List "lib/ListLib.as"; +private import ListFuncs "lib/ListFuncs.as"; + +type Stack = List.List; + +func push(x: Int, s: Stack): Stack = + List.cons(x, s); + +func empty(): Stack = + List.nil(); + +func singleton(x: Int): Stack = + ListFuncs.doubleton(x, x); +} +|} + [ ("List", "lib/ListLib.as") + ; ("ListFuncs", "lib/ListFuncs.as") + ] diff --git a/src/languageServer/languageServer.ml b/src/languageServer/languageServer.ml index 71f7c29de3c..ea8df94b204 100644 --- a/src/languageServer/languageServer.ml +++ b/src/languageServer/languageServer.ml @@ -95,6 +95,12 @@ let file_from_uri logger uri = | None -> let _ = logger "error" ("Failed to strip filename from: " ^ uri) in uri +let abs_file_from_uri logger uri = + match Base.String.chop_prefix ~prefix:"file://" uri with + | Some file -> file + | None -> + let _ = logger "error" ("Failed to strip filename from: " ^ uri) in + uri let start () = let oc: out_channel = open_out_gen [Open_append; Open_creat] 0o666 "ls.log"; in @@ -105,6 +111,7 @@ let start () = let show_message = Channel.show_message oc in let client_capabilities = ref None in + let project_root = Sys.getcwd () in let vfs = ref Vfs.empty in @@ -200,7 +207,12 @@ let start () = Lsp_t.{ code = 1 ; message = "Tried to find completions for a file that hadn't been opened yet"} | Some file_content -> - Completion.completion_handler log_to_file file_content position + Completion.completion_handler + log_to_file + project_root + (abs_file_from_uri log_to_file uri) + file_content + position |> response_result_message id in response |> Lsp_j.string_of_response_message diff --git a/src/pipeline/pipeline.mli b/src/pipeline/pipeline.mli index 8b185d1fe69..df7055561ca 100644 --- a/src/pipeline/pipeline.mli +++ b/src/pipeline/pipeline.mli @@ -22,6 +22,7 @@ end val check_files : string list -> unit Diag.result val check_string : string -> string -> unit Diag.result +val initial_stat_env : Scope.scope val chase_imports : Scope.scope -> Resolve_import.S.t -> (Syntax.libraries * Scope.scope) Diag.result diff --git a/stdlib/assocList.as b/stdlib/assocList.as index bda8d9452e4..ae08a796153 100644 --- a/stdlib/assocList.as +++ b/stdlib/assocList.as @@ -10,7 +10,7 @@ Implements the same interface as `Trie`, but as a linked-list of key-value pairs */ -private let List = import "list.as"; +private import List "list.as"; // polymorphic association linked lists between keys and values type AssocList = List.List<(K,V)>; diff --git a/stdlib/docTable.as b/stdlib/docTable.as index bf7e0cb9a64..0203895268e 100644 --- a/stdlib/docTable.as +++ b/stdlib/docTable.as @@ -43,11 +43,11 @@ type information. */ -let Hash = import "hash.as"; +private import Hash "hash.as"; type Hash = Hash.Hash; -//let Trie = import "trie.as"; -let Trie = import "trie2.as"; +//import Trie "trie.as"; +private import Trie "trie2.as"; type Trie = Trie.Trie; type Key = Trie.Key; diff --git a/stdlib/listTest.as b/stdlib/listTest.as index 99b25b3bfe4..21a9439898b 100644 --- a/stdlib/listTest.as +++ b/stdlib/listTest.as @@ -1,5 +1,5 @@ type X = Nat; -let List = import "list.as"; +import List "list.as"; func opnatEq(a : ?Nat, b : ?Nat) : Bool { switch (a, b) { diff --git a/stdlib/option.as b/stdlib/option.as index 2f326c01413..4d0398e06bd 100644 --- a/stdlib/option.as +++ b/stdlib/option.as @@ -5,7 +5,7 @@ Functions for Option types. */ -let P = (import "prelude.as"); +private import P "prelude.as"; type t = ?A; diff --git a/stdlib/result.as b/stdlib/result.as index aa7cda25653..251eed233b1 100644 --- a/stdlib/result.as +++ b/stdlib/result.as @@ -1,5 +1,5 @@ module { -private let P = (import "prelude.as"); +private import P "prelude.as"; /** diff --git a/stdlib/set.as b/stdlib/set.as index 7d13eba0508..d9aaca6b273 100644 --- a/stdlib/set.as +++ b/stdlib/set.as @@ -1,5 +1,5 @@ /** - + Sets ======== @@ -17,9 +17,9 @@ in the future, we might avoid this via https://dfinity.atlassian.net/browse/AST-32 */ - -let Trie = import "trie2.as"; -let Hash = import "hash.as"; +module { +private import Trie "trie2.as"; +private import Hash "hash.as"; type Hash = Hash.Hash; type Set = Trie.Trie; @@ -75,3 +75,4 @@ type Set = Trie.Trie; }; func unitEq (_:(),_:()):Bool{ true }; +} diff --git a/stdlib/trie.as b/stdlib/trie.as index afbd9d22c7a..8deba6e2249 100644 --- a/stdlib/trie.as +++ b/stdlib/trie.as @@ -61,13 +61,14 @@ See the full details in the definitions below: */ -let Hash = (import "hash.as").BitVec; +private import H "hash.as"; +let Hash = H.BitVec; type Hash = Hash.t; -let List = import "list.as"; +private import List "list.as"; type List = List.List; -let AssocList = import "assocList.as"; +private import AssocList "assocList.as"; type AssocList = AssocList.AssocList; let HASH_BITS = 4; diff --git a/stdlib/trie2.as b/stdlib/trie2.as index b7a7f0b1dc9..ac5355f9211 100644 --- a/stdlib/trie2.as +++ b/stdlib/trie2.as @@ -73,17 +73,18 @@ let MAX_LEAF_COUNT = 8; // <-- beats both 4 and 16 for me, now //let MAX_LEAF_COUNT = 16; //let MAX_LEAF_COUNT = 32; -let P = (import "prelude.as"); +private import P "prelude.as"; -let Option = import "option.as"; +private import Option "option.as"; -let Hash = (import "hash.as").BitVec; +private import H "hash.as"; +let Hash = H.BitVec; type Hash = Hash.t; -let List = import "list.as"; +private import List "list.as"; type List = List.List; -let AssocList = import "assocList.as"; +private import AssocList "assocList.as"; type AssocList = AssocList.AssocList; /** A `Key` for the trie has an associated hash value */ From fc05bf1255d5c3f8137ab3d9a06fd3b70c8cc441 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Tue, 9 Jul 2019 19:36:52 +0200 Subject: [PATCH 0244/1176] Generate coverage counter-examples (#553) --- src/as_frontend/coverage.ml | 203 +++++++++++++----- src/as_frontend/coverage.mli | 4 +- src/as_frontend/typing.ml | 71 +++--- src/as_types/type.ml | 9 +- src/as_types/type.mli | 4 +- src/codegen/compile.ml | 2 +- src/ir_def/check_ir.ml | 9 +- src/ir_def/construct.ml | 2 +- test/fail/ok/pat-inconsistent.tc.ok | 22 +- test/repl/ok/file-and-repl.stderr.ok | 5 +- test/run-dfinity/ok/data-params.run-ir.ok | 5 +- test/run-dfinity/ok/data-params.run-low.ok | 5 +- test/run-dfinity/ok/data-params.run.ok | 5 +- test/run-dfinity/ok/data-params.tc.ok | 5 +- .../run-dfinity/ok/data-params.wasm.stderr.ok | 5 +- .../ok/flatten-awaitables.run-ir.ok | 144 ++++++++++--- .../ok/flatten-awaitables.run-low.ok | 144 ++++++++++--- test/run-dfinity/ok/flatten-awaitables.run.ok | 144 ++++++++++--- test/run-dfinity/ok/flatten-awaitables.tc.ok | 144 ++++++++++--- .../ok/flatten-awaitables.wasm.stderr.ok | 144 ++++++++++--- test/run/coverage.as | 2 + test/run/ok/coverage.run-ir.ok | 105 ++++++--- test/run/ok/coverage.run-low.ok | 105 ++++++--- test/run/ok/coverage.run.ok | 105 ++++++--- test/run/ok/coverage.tc.ok | 105 ++++++--- test/run/ok/coverage.wasm.stderr.ok | 105 ++++++--- test/run/ok/objects1.run-ir.ok | 10 +- test/run/ok/objects1.run-low.ok | 10 +- test/run/ok/objects1.run.ok | 10 +- test/run/ok/objects1.tc.ok | 10 +- test/run/ok/objects1.wasm.stderr.ok | 10 +- test/run/ok/switch.run-ir.ok | 20 +- test/run/ok/switch.run-low.ok | 20 +- test/run/ok/switch.run.ok | 20 +- test/run/ok/switch.tc.ok | 20 +- test/run/ok/switch.wasm.stderr.ok | 20 +- 36 files changed, 1383 insertions(+), 370 deletions(-) diff --git a/src/as_frontend/coverage.ml b/src/as_frontend/coverage.ml index e9a9f9e2b68..f7d90734a2d 100644 --- a/src/as_frontend/coverage.ml +++ b/src/as_frontend/coverage.ml @@ -5,6 +5,7 @@ open As_values open Syntax open Source +module T = Type module V = Value module ValSet = Set.Make(struct type t = V.value let compare = V.compare end) @@ -25,17 +26,18 @@ type desc = type ctxt = | InOpt of ctxt | InTag of ctxt * string - | InTup of ctxt * desc list * desc list * pat list * Type.typ list - | InObj of ctxt * desc LabMap.t * string * pat_field list * Type.field list - | InAlt1 of ctxt * Source.region * pat * Type.typ + | InTup of ctxt * desc list * desc list * pat list * T.typ list + | InObj of ctxt * desc LabMap.t * string * pat_field list * T.field list + | InAlt1 of ctxt * Source.region * pat * T.typ | InAlt2 of ctxt * Source.region - | InCase of Source.region * case list * Type.typ + | InCase of Source.region * case list * T.typ type sets = { mutable cases : AtSet.t; mutable alts : AtSet.t; mutable reached_cases : AtSet.t; mutable reached_alts : AtSet.t; + mutable missing : desc list; } @@ -44,9 +46,124 @@ let make_sets () = alts = AtSet.empty; reached_cases = AtSet.empty; reached_alts = AtSet.empty; + missing = []; } +(* Generating counter examples *) + +let max_expand = 2 + +let pick_nat (type t) (module Num : V.NumType with type t = t) to_val vs = + let x = ref Num.zero in + while ValSet.mem (to_val !x) vs do + x := Num.add (Num.of_int 1) !x + done; + Val (to_val !x) + +let pick_int (type t) (module Num : V.NumType with type t = t) to_val vs = + let x = ref Num.zero in + while ValSet.mem (to_val !x) vs do + x := Num.neg !x; + if Num.ge !x Num.zero then x := Num.add (Num.of_int 1) !x + done; + Val (to_val !x) + +let pick_word (type t) (module Word : V.WordType with type t = t) to_val vs = + let x = ref Word.zero in + while ValSet.mem (to_val !x) vs do + x := Word.add (Word.of_int_u 1) !x + done; + Val (to_val !x) + +let pick_char vs = + let x = ref 0 in + while ValSet.mem (V.Char !x) vs do + x := !x + 1 + done; + Val (V.Char !x) + +let pick_val vs = function + | T.Null -> assert false + | T.Bool -> Val (V.Bool (ValSet.mem (V.Bool false) vs)) + | T.Nat -> pick_nat (module V.Nat) (fun x -> V.Int x) vs + | T.Nat8 -> pick_nat (module V.Nat8) (fun x -> V.Nat8 x) vs + | T.Nat16 -> pick_nat (module V.Nat16) (fun x -> V.Nat16 x) vs + | T.Nat32 -> pick_nat (module V.Nat32) (fun x -> V.Nat32 x) vs + | T.Nat64 -> pick_nat (module V.Nat64) (fun x -> V.Nat64 x) vs + | T.Int -> pick_int (module V.Int) (fun x -> V.Int x) vs + | T.Int8 -> pick_int (module V.Int_8) (fun x -> V.Int8 x) vs + | T.Int16 -> pick_int (module V.Int_16) (fun x -> V.Int16 x) vs + | T.Int32 -> pick_int (module V.Int_32) (fun x -> V.Int32 x) vs + | T.Int64 -> pick_int (module V.Int_64) (fun x -> V.Int64 x) vs + | T.Word8 -> pick_word (module V.Word8) (fun x -> V.Word8 x) vs + | T.Word16 -> pick_word (module V.Word16) (fun x -> V.Word16 x) vs + | T.Word32 -> pick_word (module V.Word32) (fun x -> V.Word32 x) vs + | T.Word64 -> pick_word (module V.Word64) (fun x -> V.Word64 x) vs + | T.Char -> pick_char vs + | T.Text + | T.Float -> Any + +let rec expand_notval t n vs : desc list = + let missing = Lib.Option.get (T.span t) max_int - ValSet.cardinal vs in + if missing = 0 then [] else + if n = max_expand && missing > 1 then [Any] else + match t with + | T.Prim t' -> + (match pick_val vs t' with + | Val v -> Val v :: expand_notval t (n + 1) (ValSet.add v vs) + | _ -> [Any] + ) + | T.Opt _ -> [Opt Any] + | _ -> [Any] + + +let rec pick_tag ls = function + | [] -> assert false + | tf::tfs when TagSet.mem tf.T.lab ls -> pick_tag ls tfs + | tf::_ -> tf.T.lab + +let rec expand_nottag tfs n ls : desc list = + let missing = List.length tfs - TagSet.cardinal ls in + if missing = 0 then [] else + if n = max_expand && missing > 1 then [Any] else + let l = pick_tag ls tfs in + Tag (Any, l) :: expand_nottag tfs (n + 1) (TagSet.add l ls) + + +let rec string_of_desc t = function + | Any -> "_" + | Val v -> V.string_of_val 100 v + | NotVal vs -> string_of_descs t (expand_notval (T.promote t) 0 vs) + | Tup descs -> + let ts = T.as_tup_sub (List.length descs) t in + "(" ^ String.concat ", " (List.map2 string_of_desc ts descs) ^ ")" + | Obj ldescs -> + let fields = LabMap.bindings ldescs in + let _, tfs = T.as_obj_sub (List.map fst fields) t in + "{" ^ String.concat "; " (List.map (string_of_ldesc tfs) fields) ^ ")" + | Opt desc -> + let t' = T.as_opt_sub t in + "?(" ^ string_of_desc t' desc ^ ")" + | Tag (desc, l) -> + let t' = T.lookup_val_field l (T.as_variant_sub l t) in + if T.sub t' T.unit + then "#" ^ l + else "#" ^ l ^ "(" ^ string_of_desc t' desc ^ ")" + | NotTag ls -> + let tfs = T.as_variant (T.promote t) in + string_of_descs t (expand_nottag tfs 0 ls) + +and string_of_ldesc tfs (l, desc) = + l ^ " = " ^ string_of_desc (T.lookup_val_field l tfs) desc + +and string_of_descs t descs = + assert (descs <> []); + String.concat " or " (List.map (string_of_desc t) descs) + + +(* Abstract interpretation *) + let value_of_lit = function | NullLit -> V.Null | BoolLit b -> V.Bool b @@ -77,10 +194,10 @@ let skip_pat pat sets = true let rec match_pat ctxt desc pat t sets = - Type.span t = Some 0 && skip_pat pat sets || + T.span t = Some 0 && skip_pat pat sets || match pat.it with | WildP | VarP _ -> - if Type.inhabited t then + if T.inhabited t then succeed ctxt desc sets else skip_pat pat sets @@ -90,7 +207,7 @@ let rec match_pat ctxt desc pat t sets = let f = Operator.unop op (Operator.type_unop op pat.note) in match_lit ctxt desc (f (value_of_lit !lit)) t sets | TupP pats -> - let ts = Type.as_tup (Type.promote t) in + let ts = T.as_tup (T.promote t) in let descs = match desc with | Tup descs -> descs @@ -98,52 +215,47 @@ let rec match_pat ctxt desc pat t sets = | _ -> assert false in match_tup ctxt [] descs pats ts sets | ObjP pat_fields -> - let _, tfs = Type.as_obj (Type.promote t) in + let _, tfs = T.as_obj (T.promote t) in let ldescs = match desc with | Obj ldescs -> ldescs | Any -> LabMap.(List.fold_left - (fun m (tf : Type.field) -> add tf.Type.lab Any m) empty tfs) + (fun m (tf : T.field) -> add tf.T.lab Any m) empty tfs) | _ -> assert false in match_obj ctxt ldescs pat_fields tfs sets | OptP pat1 -> - let t' = Type.as_opt (Type.promote t) in + let t' = T.as_opt (T.promote t) in (match desc with - | Val Value.Null -> - fail ctxt desc sets - | NotVal vs when ValSet.mem Value.Null vs -> - match_pat (InOpt ctxt) Any pat1 t' sets | Opt desc' -> match_pat (InOpt ctxt) desc' pat1 t' sets + | Val V.Null -> + fail ctxt desc sets + | NotVal vs when ValSet.mem V.Null vs -> + match_pat (InOpt ctxt) Any pat1 t' sets | Any -> - fail ctxt (Val Value.Null) sets &&& + fail ctxt (Val V.Null) sets &&& match_pat (InOpt ctxt) Any pat1 t' sets | _ -> assert false ) | TagP (id, pat1) -> - let t' = Lib.Option.value - (Type.lookup_val_field id.it (Type.as_variant (Type.promote t))) in + let t' = T.lookup_val_field id.it (T.as_variant (T.promote t)) in (match desc with - | NotTag ls -> - if TagSet.mem id.it ls then - fail ctxt desc sets - else if Type.span t = Some (TagSet.cardinal ls + 1) then - match_pat (InTag (ctxt, id.it)) Any pat1 t' sets - else - fail ctxt (NotTag (TagSet.add id.it ls)) sets &&& - match_pat (InTag (ctxt, id.it)) Any pat1 t' sets | Tag (desc', l) -> if id.it = l then match_pat (InTag (ctxt, l)) desc' pat1 t' sets else fail ctxt desc sets - | Any -> - if Type.span t = Some 1 then + | NotTag ls -> + if TagSet.mem id.it ls then + fail ctxt desc sets + else if T.span t = Some (TagSet.cardinal ls + 1) then match_pat (InTag (ctxt, id.it)) Any pat1 t' sets else - fail ctxt (NotTag (TagSet.singleton id.it)) sets &&& + fail ctxt (NotTag (TagSet.add id.it ls)) sets &&& match_pat (InTag (ctxt, id.it)) Any pat1 t' sets + | Any -> + match_pat ctxt (NotTag TagSet.empty) pat t sets | _ -> assert false ) | AltP (pat1, pat2) -> @@ -154,30 +266,24 @@ let rec match_pat ctxt desc pat t sets = match_pat ctxt desc pat1 t sets and match_lit ctxt desc v t sets = - let desc_succ = Val v in - let desc_fail vs = NotVal (ValSet.add v vs) in match desc with - | Any -> - if Type.span t = Some 1 then - succeed ctxt desc_succ sets - else - fail ctxt (desc_fail ValSet.empty) sets &&& - succeed ctxt desc_succ sets | Val v' -> - if Value.equal v v' then + if V.equal v v' then succeed ctxt desc sets else fail ctxt desc sets | NotVal vs -> if ValSet.mem v vs then fail ctxt desc sets - else if Type.span t = Some (ValSet.cardinal vs + 1) then - succeed ctxt desc_succ sets + else if T.span t = Some (ValSet.cardinal vs + 1) then + succeed ctxt (Val v) sets else - fail ctxt (desc_fail vs) sets &&& - succeed ctxt desc_succ sets + fail ctxt (NotVal (ValSet.add v vs)) sets &&& + succeed ctxt (Val v) sets | Opt _ -> fail ctxt desc sets + | Any -> + match_lit ctxt (NotVal ValSet.empty) v t sets | _ -> assert false @@ -195,10 +301,10 @@ and match_obj ctxt ldescs (pat_fields : pat_field list) tfs sets = | [] -> succeed ctxt (Obj ldescs) sets | pat_field::pat_fields' -> let l = pat_field.it.id.it in - let tf = List.find (fun tf -> tf.Type.lab = l) tfs in + let tf = List.find (fun tf -> tf.T.lab = l) tfs in let desc = LabMap.find l ldescs in match_pat (InObj (ctxt, ldescs, l, pat_fields', tfs)) - desc pat_field.it.pat tf.Type.typ sets + desc pat_field.it.pat tf.T.typ sets and succeed ctxt desc sets : bool = match ctxt with @@ -243,9 +349,10 @@ and fail ctxt desc sets : bool = | InAlt2 (ctxt', at2) -> fail ctxt' desc sets | InCase (at, [], t) -> - Type.span t = Some 0 || not (Type.inhabited t) + T.span t = Some 0 || not (T.inhabited t) || + (sets.missing <- desc::sets.missing; false) | InCase (at, case::cases, t) -> - Type.span t = Some 0 && skip (case::cases) sets || + T.span t = Some 0 && skip (case::cases) sets || match_pat (InCase (case.at, cases, t)) desc case.it.pat t sets let warn at fmt = @@ -256,15 +363,15 @@ let warn at fmt = let check_cases cases t = let sets = make_sets () in - let exhaustive = fail (InCase (Source.no_region, cases, t)) Any sets in + let _exhaustive = fail (InCase (Source.no_region, cases, t)) Any sets in let unreached_cases = AtSet.diff sets.cases sets.reached_cases in let unreached_alts = AtSet.diff sets.alts sets.reached_alts in AtSet.iter (fun at -> warn at "this case is never reached") unreached_cases; AtSet.iter (fun at -> warn at "this pattern is never matched") unreached_alts; - exhaustive + List.map (string_of_desc t) (List.rev sets.missing) let (@?) it at = {it; at; note = empty_typ_note} -let check_pat pat t : bool = +let check_pat pat t = check_cases [{pat; exp = TupE [] @? Source.no_region} @@ Source.no_region] t diff --git a/src/as_frontend/coverage.mli b/src/as_frontend/coverage.mli index 2eec785b21b..ebe4ddb3056 100644 --- a/src/as_frontend/coverage.mli +++ b/src/as_frontend/coverage.mli @@ -1,5 +1,5 @@ open As_def open As_types -val check_pat : Syntax.pat -> Type.typ -> bool -val check_cases : Syntax.case list -> Type.typ -> bool +val check_pat : Syntax.pat -> Type.typ -> string list +val check_cases : Syntax.case list -> Type.typ -> string list diff --git a/src/as_frontend/typing.ml b/src/as_frontend/typing.ml index ddcefe6710d..e58d91559e7 100644 --- a/src/as_frontend/typing.ml +++ b/src/as_frontend/typing.ml @@ -141,10 +141,10 @@ and check_obj_path' env path : T.typ = | DotH (path', id) -> let s, fs = check_obj_path env path' in match T.lookup_val_field id.it fs with - | Some T.Pre -> + | T.Pre -> error env id.at "cannot infer type of forward field reference %s" id.it - | Some t -> t - | None -> + | t -> t + | exception Invalid_argument _ -> error env id.at "field %s does not exist in type\n %s" id.it (T.string_of_typ_expand (T.Obj (s, fs))) @@ -162,9 +162,7 @@ and check_typ_path' env path : T.con = ) | DotH (path', id) -> let s, fs = check_obj_path env path' in - match T.lookup_typ_field id.it fs with - | Some t -> t - | None -> + try T.lookup_typ_field id.it fs with Invalid_argument _ -> error env id.at "type field %s does not exist in type\n %s" id.it (T.string_of_typ_expand (T.Obj (s, fs))) @@ -551,11 +549,11 @@ and infer_exp'' env exp : T.typ = (T.string_of_typ_expand t1) in (match T.lookup_val_field id.it tfs with - | Some T.Pre -> + | T.Pre -> error env exp.at "cannot infer type of forward field reference %s" id.it - | Some t -> t - | None -> + | t -> t + | exception Invalid_argument _ -> error env exp1.at "field %s does not exist in type\n %s" id.it (T.string_of_typ_expand t1) ) @@ -703,10 +701,15 @@ and infer_exp'' env exp : T.typ = | SwitchE (exp1, cases) -> let t1 = infer_exp_promote env exp1 in let t = infer_cases env t1 T.Non cases in - if not env.pre then - if not (Coverage.check_cases cases t1) then + if not env.pre then begin + match Coverage.check_cases cases t1 with + | [] -> () + | ss -> warn env exp.at - "the cases in this switch do not cover all possible values"; + "the cases in this switch over type\n %s\ndo not cover value\n %s" + (Type.string_of_typ_expand t1) + (String.concat " or\n " ss) + end; t | WhileE (exp1, exp2) -> if not env.pre then begin @@ -730,7 +733,7 @@ and infer_exp'' env exp : T.typ = let t1 = infer_exp_promote env exp1 in (try let _, tfs = T.as_obj_sub ["next"] t1 in - let t = Lib.Option.value (T.lookup_val_field "next" tfs) in + let t = T.lookup_val_field "next" tfs in let t1, t2 = T.as_mono_func_sub t in if not (T.sub T.unit t1) then raise (Invalid_argument ""); let t2' = T.as_opt_sub t2 in @@ -857,10 +860,15 @@ and check_exp' env t exp : T.typ = | SwitchE (exp1, cases), _ -> let t1 = infer_exp_promote env exp1 in check_cases env t1 t cases; - if not env.pre then - if not (Coverage.check_cases cases t1) then + if not env.pre then begin + match Coverage.check_cases cases t1 with + | [] -> () + | ss -> warn env exp.at - "the cases in this switch do not cover all possible values"; + "the cases in this switch over type\n %s\ndo not cover value\n %s" + (Type.string_of_typ_expand t1) + (String.concat " or\n " ss) + end; t | FuncE (_, s', [], pat, typ_opt, exp), T.Func (s, _, [], ts1, ts2) -> let ve = check_pat_exhaustive env (T.seq ts1) pat in @@ -923,9 +931,15 @@ and inconsistent t ts = and infer_pat_exhaustive env pat : T.typ * Scope.val_env = let t, ve = infer_pat env pat in - if not env.pre then - if not (Coverage.check_pat pat t) then - warn env pat.at "this pattern does not cover all possible values"; + if not env.pre then begin + match Coverage.check_pat pat t with + | [] -> () + | ss -> + warn env pat.at + "this pattern consuming type\n %s\ndoes not cover value\n %s" + (Type.string_of_typ_expand t) + (String.concat " or\n " ss) + end; t, ve and infer_pat env pat : T.typ * Scope.val_env = @@ -998,9 +1012,15 @@ and infer_pat_fields at env pfs ts ve : (T.obj_sort * T.field list) * Scope.val_ and check_pat_exhaustive env t pat : Scope.val_env = let ve = check_pat env t pat in - if not env.pre then - if not (Coverage.check_pat pat t) then - warn env pat.at "this pattern does not cover all possible values"; + if not env.pre then begin + match Coverage.check_pat pat t with + | [] -> () + | ss -> + warn env pat.at + "this pattern consuming type\n %s\ndoes not cover value\n %s" + (Type.string_of_typ_expand t) + (String.concat " or\n " ss) + end; ve and check_pat env t pat : Scope.val_env = @@ -1062,8 +1082,7 @@ and check_pat' env t pat : Scope.val_env = in check_pat env t1 pat1 | TagP (id, pat1) -> let t1 = - try - Lib.Option.value (T.lookup_val_field id.it (T.as_variant_sub id.it t)) + try T.lookup_val_field id.it (T.as_variant_sub id.it t) with Invalid_argument _ | Not_found -> error env pat.at "variant pattern cannot consume expected type\n %s" (T.string_of_typ_expand t) @@ -1373,7 +1392,9 @@ and infer_val_path env exp : T.typ option = | None -> None | Some t -> match T.promote t with - | T.Obj ( _, flds) -> T.lookup_val_field id.it flds + | T.Obj ( _, flds) -> + (try Some (T.lookup_val_field id.it flds) + with Invalid_argument _ -> None) | _ -> None ) | _ -> None diff --git a/src/as_types/type.ml b/src/as_types/type.ml index 0c13264190e..1c61d5e255a 100644 --- a/src/as_types/type.ml +++ b/src/as_types/type.ml @@ -381,15 +381,14 @@ let as_async_sub t = match promote t with let lookup_val_field l tfs = let is_lab = function {typ = Typ _; _} -> false | {lab; _} -> lab = l in match List.find_opt is_lab tfs with - | Some tf -> Some tf.typ - | None -> None + | Some tf -> tf.typ + | None -> invalid "lookup_val_field" let lookup_typ_field l tfs = let is_lab = function {typ = Typ _; lab} -> lab = l | _ -> false in match List.find_opt is_lab tfs with - | Some {typ = Typ c; _} -> Some c - | Some _ -> assert false - | None -> None + | Some {typ = Typ c; _} -> c + | _ -> invalid "lookup_typ_field" (* Span *) diff --git a/src/as_types/type.mli b/src/as_types/type.mli index abf9c2a4449..4282da843ca 100644 --- a/src/as_types/type.mli +++ b/src/as_types/type.mli @@ -124,8 +124,8 @@ val as_seq : typ -> typ list (* Fields *) -val lookup_val_field : string -> field list -> typ option -val lookup_typ_field : string -> field list -> con option +val lookup_val_field : string -> field list -> typ +val lookup_typ_field : string -> field list -> con val compare_field : field -> field -> int diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index c4f81db7a73..f686c48966b 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -1880,7 +1880,7 @@ module Object = struct (* TODO: remove try once array and text accessors are separated *) try let _, fields = Type.as_obj_sub [s] obj_type in - Type.is_mut (Lib.Option.value (Type.lookup_val_field s fields)) + Type.is_mut (Type.lookup_val_field s fields) with Invalid_argument _ -> false let idx env obj_type name = diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 1d01548dbcb..72229ebe0c9 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -363,10 +363,7 @@ let rec check_exp env (exp:Ir.exp) : unit = | ActorDotE _ -> sort = T.Actor | DotE _ -> sort <> T.Actor | _ -> false) "sort mismatch"; - match T.lookup_val_field n tfs with - | Some tn -> - tn <~ t - | None -> + try T.lookup_val_field n tfs <~ t with Invalid_argument _ -> error env exp1.at "field name %s does not exist in type\n %s" n (T.string_of_typ_expand t1) end @@ -658,12 +655,12 @@ and check_pat_field env t (pf : pat_field) = let s, tfs = T.as_obj_sub [lab] t in let (<:) = check_sub env pf.it.pat.at in t <: T.Obj (s, [tf]); - if T.is_mut (Lib.Option.value (T.lookup_val_field lab tfs)) then + if T.is_mut (T.lookup_val_field lab tfs) then error env pf.it.pat.at "cannot match mutable field %s" lab and check_pat_tag env t l pat = let (<:) = check_sub env pat.at in - Lib.Option.value (T.lookup_val_field l (T.as_variant_sub l t)) <: pat.note + T.lookup_val_field l (T.as_variant_sub l t) <: pat.note (* Objects *) diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index 66b7f6fa3f5..1f78c0c7f2f 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -498,7 +498,7 @@ let forE pat exp1 exp2 = let lab = fresh_id "done" () in let ty1 = exp1.note.note_typ in let _, tfs = T.as_obj_sub ["next"] ty1 in - let tnxt = Lib.Option.value (T.lookup_val_field "next" tfs) in + let tnxt = T.lookup_val_field "next" tfs in let nxt = fresh_var "nxt" tnxt in letE nxt (dotE exp1 (nameN "next") tnxt) ( labelE lab T.unit ( diff --git a/test/fail/ok/pat-inconsistent.tc.ok b/test/fail/ok/pat-inconsistent.tc.ok index f0a70077b07..4742eea9d3a 100644 --- a/test/fail/ok/pat-inconsistent.tc.ok +++ b/test/fail/ok/pat-inconsistent.tc.ok @@ -3,10 +3,24 @@ pat-inconsistent.as:7.34-7.50: warning, this pattern is never matched pat-inconsistent.as:9.20-9.22: warning, this pattern is never matched pat-inconsistent.as:10.20-10.24: warning, this pattern is never matched pat-inconsistent.as:11.20-11.30: warning, this pattern is never matched -pat-inconsistent.as:2.13-2.21: warning, this pattern does not cover all possible values -pat-inconsistent.as:3.13-3.22: warning, this pattern does not cover all possible values -pat-inconsistent.as:5.13-5.29: warning, this pattern does not cover all possible values -pat-inconsistent.as:8.13-8.33: warning, this pattern does not cover all possible values +pat-inconsistent.as:2.13-2.21: warning, this pattern consuming type + Nat +does not cover value + 0 or 3 or _ +pat-inconsistent.as:3.13-3.22: warning, this pattern consuming type + Int +does not cover value + 0 or 2 or _ +pat-inconsistent.as:5.13-5.29: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +pat-inconsistent.as:8.13-8.33: warning, this pattern consuming type + (Int, Int) +does not cover value + (-1, 0 or 1 or _) or + (2, 0 or 1 or _) or + (0 or 1 or _, _) pat-inconsistent.as:16.16-16.24: type error, pattern branches have incompatible types, left consumes Nat diff --git a/test/repl/ok/file-and-repl.stderr.ok b/test/repl/ok/file-and-repl.stderr.ok index bd26b9ea5cd..7e572ed4d4d 100644 --- a/test/repl/ok/file-and-repl.stderr.ok +++ b/test/repl/ok/file-and-repl.stderr.ok @@ -1 +1,4 @@ -63:1.12-1.40: warning, the cases in this switch do not cover all possible values +63:1.12-1.40: warning, the cases in this switch over type + Bool +do not cover value + false diff --git a/test/run-dfinity/ok/data-params.run-ir.ok b/test/run-dfinity/ok/data-params.run-ir.ok index 19fd485396a..508800c183f 100644 --- a/test/run-dfinity/ok/data-params.run-ir.ok +++ b/test/run-dfinity/ok/data-params.run-ir.ok @@ -1,4 +1,7 @@ -data-params.as:59.18-59.28: warning, this pattern does not cover all possible values +data-params.as:59.18-59.28: warning, this pattern consuming type + ?Text +does not cover value + null 1 3 6 diff --git a/test/run-dfinity/ok/data-params.run-low.ok b/test/run-dfinity/ok/data-params.run-low.ok index 19fd485396a..508800c183f 100644 --- a/test/run-dfinity/ok/data-params.run-low.ok +++ b/test/run-dfinity/ok/data-params.run-low.ok @@ -1,4 +1,7 @@ -data-params.as:59.18-59.28: warning, this pattern does not cover all possible values +data-params.as:59.18-59.28: warning, this pattern consuming type + ?Text +does not cover value + null 1 3 6 diff --git a/test/run-dfinity/ok/data-params.run.ok b/test/run-dfinity/ok/data-params.run.ok index 19fd485396a..508800c183f 100644 --- a/test/run-dfinity/ok/data-params.run.ok +++ b/test/run-dfinity/ok/data-params.run.ok @@ -1,4 +1,7 @@ -data-params.as:59.18-59.28: warning, this pattern does not cover all possible values +data-params.as:59.18-59.28: warning, this pattern consuming type + ?Text +does not cover value + null 1 3 6 diff --git a/test/run-dfinity/ok/data-params.tc.ok b/test/run-dfinity/ok/data-params.tc.ok index 757997e11c7..a988892530f 100644 --- a/test/run-dfinity/ok/data-params.tc.ok +++ b/test/run-dfinity/ok/data-params.tc.ok @@ -1 +1,4 @@ -data-params.as:59.18-59.28: warning, this pattern does not cover all possible values +data-params.as:59.18-59.28: warning, this pattern consuming type + ?Text +does not cover value + null diff --git a/test/run-dfinity/ok/data-params.wasm.stderr.ok b/test/run-dfinity/ok/data-params.wasm.stderr.ok index 757997e11c7..a988892530f 100644 --- a/test/run-dfinity/ok/data-params.wasm.stderr.ok +++ b/test/run-dfinity/ok/data-params.wasm.stderr.ok @@ -1 +1,4 @@ -data-params.as:59.18-59.28: warning, this pattern does not cover all possible values +data-params.as:59.18-59.28: warning, this pattern consuming type + ?Text +does not cover value + null diff --git a/test/run-dfinity/ok/flatten-awaitables.run-ir.ok b/test/run-dfinity/ok/flatten-awaitables.run-ir.ok index 421cb9c1b5e..e5bc31fb875 100644 --- a/test/run-dfinity/ok/flatten-awaitables.run-ir.ok +++ b/test/run-dfinity/ok/flatten-awaitables.run-ir.ok @@ -1,27 +1,123 @@ -flatten-awaitables.as:43.9-43.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:45.9-45.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:47.9-47.25: warning, this pattern does not cover all possible values -flatten-awaitables.as:52.9-52.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:54.9-54.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:56.9-56.25: warning, this pattern does not cover all possible values -flatten-awaitables.as:66.9-66.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:68.9-68.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:70.9-70.25: warning, this pattern does not cover all possible values -flatten-awaitables.as:75.9-75.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:77.9-77.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:79.9-79.25: warning, this pattern does not cover all possible values -flatten-awaitables.as:85.9-85.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:87.9-87.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:89.9-89.25: warning, this pattern does not cover all possible values -flatten-awaitables.as:94.9-94.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:96.9-96.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:98.9-98.25: warning, this pattern does not cover all possible values -flatten-awaitables.as:103.9-103.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:105.9-105.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:107.9-107.25: warning, this pattern does not cover all possible values -flatten-awaitables.as:112.9-112.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:114.9-114.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:116.9-116.25: warning, this pattern does not cover all possible values +flatten-awaitables.as:43.9-43.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:45.9-45.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:47.9-47.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:52.9-52.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:54.9-54.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:56.9-56.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:66.9-66.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:68.9-68.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:70.9-70.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:75.9-75.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:77.9-77.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:79.9-79.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:85.9-85.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:87.9-87.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:89.9-89.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:94.9-94.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:96.9-96.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:98.9-98.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:103.9-103.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:105.9-105.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:107.9-107.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:112.9-112.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:114.9-114.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:116.9-116.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) first-order ,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, diff --git a/test/run-dfinity/ok/flatten-awaitables.run-low.ok b/test/run-dfinity/ok/flatten-awaitables.run-low.ok index 421cb9c1b5e..e5bc31fb875 100644 --- a/test/run-dfinity/ok/flatten-awaitables.run-low.ok +++ b/test/run-dfinity/ok/flatten-awaitables.run-low.ok @@ -1,27 +1,123 @@ -flatten-awaitables.as:43.9-43.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:45.9-45.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:47.9-47.25: warning, this pattern does not cover all possible values -flatten-awaitables.as:52.9-52.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:54.9-54.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:56.9-56.25: warning, this pattern does not cover all possible values -flatten-awaitables.as:66.9-66.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:68.9-68.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:70.9-70.25: warning, this pattern does not cover all possible values -flatten-awaitables.as:75.9-75.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:77.9-77.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:79.9-79.25: warning, this pattern does not cover all possible values -flatten-awaitables.as:85.9-85.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:87.9-87.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:89.9-89.25: warning, this pattern does not cover all possible values -flatten-awaitables.as:94.9-94.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:96.9-96.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:98.9-98.25: warning, this pattern does not cover all possible values -flatten-awaitables.as:103.9-103.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:105.9-105.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:107.9-107.25: warning, this pattern does not cover all possible values -flatten-awaitables.as:112.9-112.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:114.9-114.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:116.9-116.25: warning, this pattern does not cover all possible values +flatten-awaitables.as:43.9-43.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:45.9-45.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:47.9-47.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:52.9-52.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:54.9-54.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:56.9-56.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:66.9-66.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:68.9-68.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:70.9-70.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:75.9-75.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:77.9-77.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:79.9-79.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:85.9-85.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:87.9-87.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:89.9-89.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:94.9-94.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:96.9-96.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:98.9-98.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:103.9-103.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:105.9-105.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:107.9-107.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:112.9-112.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:114.9-114.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:116.9-116.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) first-order ,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, diff --git a/test/run-dfinity/ok/flatten-awaitables.run.ok b/test/run-dfinity/ok/flatten-awaitables.run.ok index 421cb9c1b5e..e5bc31fb875 100644 --- a/test/run-dfinity/ok/flatten-awaitables.run.ok +++ b/test/run-dfinity/ok/flatten-awaitables.run.ok @@ -1,27 +1,123 @@ -flatten-awaitables.as:43.9-43.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:45.9-45.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:47.9-47.25: warning, this pattern does not cover all possible values -flatten-awaitables.as:52.9-52.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:54.9-54.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:56.9-56.25: warning, this pattern does not cover all possible values -flatten-awaitables.as:66.9-66.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:68.9-68.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:70.9-70.25: warning, this pattern does not cover all possible values -flatten-awaitables.as:75.9-75.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:77.9-77.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:79.9-79.25: warning, this pattern does not cover all possible values -flatten-awaitables.as:85.9-85.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:87.9-87.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:89.9-89.25: warning, this pattern does not cover all possible values -flatten-awaitables.as:94.9-94.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:96.9-96.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:98.9-98.25: warning, this pattern does not cover all possible values -flatten-awaitables.as:103.9-103.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:105.9-105.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:107.9-107.25: warning, this pattern does not cover all possible values -flatten-awaitables.as:112.9-112.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:114.9-114.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:116.9-116.25: warning, this pattern does not cover all possible values +flatten-awaitables.as:43.9-43.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:45.9-45.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:47.9-47.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:52.9-52.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:54.9-54.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:56.9-56.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:66.9-66.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:68.9-68.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:70.9-70.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:75.9-75.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:77.9-77.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:79.9-79.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:85.9-85.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:87.9-87.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:89.9-89.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:94.9-94.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:96.9-96.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:98.9-98.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:103.9-103.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:105.9-105.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:107.9-107.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:112.9-112.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:114.9-114.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:116.9-116.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) first-order ,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, diff --git a/test/run-dfinity/ok/flatten-awaitables.tc.ok b/test/run-dfinity/ok/flatten-awaitables.tc.ok index 245da16d2fd..132c1167a2f 100644 --- a/test/run-dfinity/ok/flatten-awaitables.tc.ok +++ b/test/run-dfinity/ok/flatten-awaitables.tc.ok @@ -1,24 +1,120 @@ -flatten-awaitables.as:43.9-43.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:45.9-45.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:47.9-47.25: warning, this pattern does not cover all possible values -flatten-awaitables.as:52.9-52.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:54.9-54.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:56.9-56.25: warning, this pattern does not cover all possible values -flatten-awaitables.as:66.9-66.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:68.9-68.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:70.9-70.25: warning, this pattern does not cover all possible values -flatten-awaitables.as:75.9-75.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:77.9-77.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:79.9-79.25: warning, this pattern does not cover all possible values -flatten-awaitables.as:85.9-85.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:87.9-87.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:89.9-89.25: warning, this pattern does not cover all possible values -flatten-awaitables.as:94.9-94.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:96.9-96.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:98.9-98.25: warning, this pattern does not cover all possible values -flatten-awaitables.as:103.9-103.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:105.9-105.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:107.9-107.25: warning, this pattern does not cover all possible values -flatten-awaitables.as:112.9-112.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:114.9-114.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:116.9-116.25: warning, this pattern does not cover all possible values +flatten-awaitables.as:43.9-43.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:45.9-45.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:47.9-47.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:52.9-52.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:54.9-54.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:56.9-56.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:66.9-66.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:68.9-68.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:70.9-70.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:75.9-75.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:77.9-77.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:79.9-79.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:85.9-85.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:87.9-87.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:89.9-89.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:94.9-94.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:96.9-96.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:98.9-98.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:103.9-103.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:105.9-105.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:107.9-107.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:112.9-112.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:114.9-114.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:116.9-116.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) diff --git a/test/run-dfinity/ok/flatten-awaitables.wasm.stderr.ok b/test/run-dfinity/ok/flatten-awaitables.wasm.stderr.ok index 245da16d2fd..132c1167a2f 100644 --- a/test/run-dfinity/ok/flatten-awaitables.wasm.stderr.ok +++ b/test/run-dfinity/ok/flatten-awaitables.wasm.stderr.ok @@ -1,24 +1,120 @@ -flatten-awaitables.as:43.9-43.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:45.9-45.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:47.9-47.25: warning, this pattern does not cover all possible values -flatten-awaitables.as:52.9-52.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:54.9-54.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:56.9-56.25: warning, this pattern does not cover all possible values -flatten-awaitables.as:66.9-66.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:68.9-68.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:70.9-70.25: warning, this pattern does not cover all possible values -flatten-awaitables.as:75.9-75.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:77.9-77.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:79.9-79.25: warning, this pattern does not cover all possible values -flatten-awaitables.as:85.9-85.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:87.9-87.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:89.9-89.25: warning, this pattern does not cover all possible values -flatten-awaitables.as:94.9-94.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:96.9-96.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:98.9-98.25: warning, this pattern does not cover all possible values -flatten-awaitables.as:103.9-103.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:105.9-105.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:107.9-107.25: warning, this pattern does not cover all possible values -flatten-awaitables.as:112.9-112.10: warning, this pattern does not cover all possible values -flatten-awaitables.as:114.9-114.17: warning, this pattern does not cover all possible values -flatten-awaitables.as:116.9-116.25: warning, this pattern does not cover all possible values +flatten-awaitables.as:43.9-43.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:45.9-45.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:47.9-47.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:52.9-52.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:54.9-54.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:56.9-56.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:66.9-66.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:68.9-68.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:70.9-70.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:75.9-75.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:77.9-77.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:79.9-79.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:85.9-85.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:87.9-87.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:89.9-89.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:94.9-94.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:96.9-96.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:98.9-98.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:103.9-103.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:105.9-105.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:107.9-107.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:112.9-112.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:114.9-114.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:116.9-116.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) diff --git a/test/run/coverage.as b/test/run/coverage.as index f927a1471f7..8f5f5404b2d 100644 --- a/test/run/coverage.as +++ b/test/run/coverage.as @@ -46,6 +46,8 @@ func f() { switch (#a 6 : {#a : Nat; #b : Nat}) { case (#a _) {}; case (#a 5) {}; case (#b _) {} }; switch (#a 6 : {#a : Nat; #b : Nat}) { case (#a _) {} }; switch (#a 6 : {#a : Nat; #b : Nat}) { case (#b _) {} }; + switch (#a 6 : {#a : Nat; #b : Nat; #c}) { case (#b _) {} }; + switch (#a 6 : {#a : Nat; #b : Nat}) {}; switch (#a 5) { case (#a _) {} }; func empty() : None = empty(); diff --git a/test/run/ok/coverage.run-ir.ok b/test/run/ok/coverage.run-ir.ok index a273de79859..39ee1621c2d 100644 --- a/test/run/ok/coverage.run-ir.ok +++ b/test/run/ok/coverage.run-ir.ok @@ -18,27 +18,84 @@ coverage.as:38.48-38.63: warning, this case is never reached coverage.as:39.65-39.74: warning, this case is never reached coverage.as:40.58-40.67: warning, this case is never reached coverage.as:46.58-46.72: warning, this case is never reached -coverage.as:59.22-59.31: warning, this case is never reached -coverage.as:60.28-60.37: warning, this case is never reached -coverage.as:61.49-61.50: warning, this pattern is never matched -coverage.as:62.48-62.49: warning, this pattern is never matched -coverage.as:63.41-63.42: warning, this pattern is never matched -coverage.as:64.40-64.41: warning, this pattern is never matched -coverage.as:75.5-75.55: warning, this case is never reached -coverage.as:107.3-107.52: warning, this case is never reached -coverage.as:4.7-4.8: warning, this pattern does not cover all possible values -coverage.as:5.7-5.15: warning, this pattern does not cover all possible values -coverage.as:9.7-9.9: warning, this pattern does not cover all possible values -coverage.as:10.7-10.9: warning, this pattern does not cover all possible values -coverage.as:11.7-11.9: warning, this pattern does not cover all possible values -coverage.as:15.10-15.13: warning, this pattern does not cover all possible values -coverage.as:16.10-16.18: warning, this pattern does not cover all possible values -coverage.as:23.3-23.25: warning, the cases in this switch do not cover all possible values -coverage.as:24.3-24.36: warning, the cases in this switch do not cover all possible values -coverage.as:32.3-32.50: warning, the cases in this switch do not cover all possible values -coverage.as:35.3-35.51: warning, the cases in this switch do not cover all possible values -coverage.as:41.3-41.70: warning, the cases in this switch do not cover all possible values -coverage.as:45.3-45.74: warning, the cases in this switch do not cover all possible values -coverage.as:47.3-47.58: warning, the cases in this switch do not cover all possible values -coverage.as:48.3-48.58: warning, the cases in this switch do not cover all possible values -coverage.as:72.3-76.4: warning, the cases in this switch do not cover all possible values +coverage.as:61.22-61.31: warning, this case is never reached +coverage.as:62.28-62.37: warning, this case is never reached +coverage.as:63.49-63.50: warning, this pattern is never matched +coverage.as:64.48-64.49: warning, this pattern is never matched +coverage.as:65.41-65.42: warning, this pattern is never matched +coverage.as:66.40-66.41: warning, this pattern is never matched +coverage.as:77.5-77.55: warning, this case is never reached +coverage.as:109.3-109.52: warning, this case is never reached +coverage.as:4.7-4.8: warning, this pattern consuming type + Nat +does not cover value + 0 or 1 or _ +coverage.as:5.7-5.15: warning, this pattern consuming type + Nat +does not cover value + 0 or 1 or _ +coverage.as:9.7-9.9: warning, this pattern consuming type + ?Nat +does not cover value + null +coverage.as:10.7-10.9: warning, this pattern consuming type + ?Nat +does not cover value + null +coverage.as:11.7-11.9: warning, this pattern consuming type + ?Nat +does not cover value + ?(0 or 1 or _) or + null +coverage.as:15.10-15.13: warning, this pattern consuming type + Nat +does not cover value + 0 or 1 or _ +coverage.as:16.10-16.18: warning, this pattern consuming type + Nat +does not cover value + 0 or 1 or _ +coverage.as:23.3-23.25: warning, the cases in this switch over type + Nat +do not cover value + 0 or 1 or _ +coverage.as:24.3-24.36: warning, the cases in this switch over type + Nat +do not cover value + 0 or 1 or _ +coverage.as:32.3-32.50: warning, the cases in this switch over type + Nat +do not cover value + 0 or 1 or _ +coverage.as:35.3-35.51: warning, the cases in this switch over type + (Nat, Nat) +do not cover value + (1 or 2 or _, 1 or 2 or _) +coverage.as:41.3-41.70: warning, the cases in this switch over type + {a : Nat; b : Nat} +do not cover value + {a = 1 or 2 or _; b = 1 or 2 or _) +coverage.as:45.3-45.74: warning, the cases in this switch over type + {#a : Nat; #b : Nat} +do not cover value + #b(0 or 1 or _) +coverage.as:47.3-47.58: warning, the cases in this switch over type + {#a : Nat; #b : Nat} +do not cover value + #b(_) +coverage.as:48.3-48.58: warning, the cases in this switch over type + {#a : Nat; #b : Nat} +do not cover value + #a(_) +coverage.as:49.3-49.62: warning, the cases in this switch over type + {#a : Nat; #b : Nat; #c} +do not cover value + #a(_) or #c +coverage.as:50.3-50.42: warning, the cases in this switch over type + {#a : Nat; #b : Nat} +do not cover value + _ +coverage.as:74.3-78.4: warning, the cases in this switch over type + {#branch : (Tree, Tree); #leaf : Int} +do not cover value + #leaf(0 or 1 or _) diff --git a/test/run/ok/coverage.run-low.ok b/test/run/ok/coverage.run-low.ok index a273de79859..39ee1621c2d 100644 --- a/test/run/ok/coverage.run-low.ok +++ b/test/run/ok/coverage.run-low.ok @@ -18,27 +18,84 @@ coverage.as:38.48-38.63: warning, this case is never reached coverage.as:39.65-39.74: warning, this case is never reached coverage.as:40.58-40.67: warning, this case is never reached coverage.as:46.58-46.72: warning, this case is never reached -coverage.as:59.22-59.31: warning, this case is never reached -coverage.as:60.28-60.37: warning, this case is never reached -coverage.as:61.49-61.50: warning, this pattern is never matched -coverage.as:62.48-62.49: warning, this pattern is never matched -coverage.as:63.41-63.42: warning, this pattern is never matched -coverage.as:64.40-64.41: warning, this pattern is never matched -coverage.as:75.5-75.55: warning, this case is never reached -coverage.as:107.3-107.52: warning, this case is never reached -coverage.as:4.7-4.8: warning, this pattern does not cover all possible values -coverage.as:5.7-5.15: warning, this pattern does not cover all possible values -coverage.as:9.7-9.9: warning, this pattern does not cover all possible values -coverage.as:10.7-10.9: warning, this pattern does not cover all possible values -coverage.as:11.7-11.9: warning, this pattern does not cover all possible values -coverage.as:15.10-15.13: warning, this pattern does not cover all possible values -coverage.as:16.10-16.18: warning, this pattern does not cover all possible values -coverage.as:23.3-23.25: warning, the cases in this switch do not cover all possible values -coverage.as:24.3-24.36: warning, the cases in this switch do not cover all possible values -coverage.as:32.3-32.50: warning, the cases in this switch do not cover all possible values -coverage.as:35.3-35.51: warning, the cases in this switch do not cover all possible values -coverage.as:41.3-41.70: warning, the cases in this switch do not cover all possible values -coverage.as:45.3-45.74: warning, the cases in this switch do not cover all possible values -coverage.as:47.3-47.58: warning, the cases in this switch do not cover all possible values -coverage.as:48.3-48.58: warning, the cases in this switch do not cover all possible values -coverage.as:72.3-76.4: warning, the cases in this switch do not cover all possible values +coverage.as:61.22-61.31: warning, this case is never reached +coverage.as:62.28-62.37: warning, this case is never reached +coverage.as:63.49-63.50: warning, this pattern is never matched +coverage.as:64.48-64.49: warning, this pattern is never matched +coverage.as:65.41-65.42: warning, this pattern is never matched +coverage.as:66.40-66.41: warning, this pattern is never matched +coverage.as:77.5-77.55: warning, this case is never reached +coverage.as:109.3-109.52: warning, this case is never reached +coverage.as:4.7-4.8: warning, this pattern consuming type + Nat +does not cover value + 0 or 1 or _ +coverage.as:5.7-5.15: warning, this pattern consuming type + Nat +does not cover value + 0 or 1 or _ +coverage.as:9.7-9.9: warning, this pattern consuming type + ?Nat +does not cover value + null +coverage.as:10.7-10.9: warning, this pattern consuming type + ?Nat +does not cover value + null +coverage.as:11.7-11.9: warning, this pattern consuming type + ?Nat +does not cover value + ?(0 or 1 or _) or + null +coverage.as:15.10-15.13: warning, this pattern consuming type + Nat +does not cover value + 0 or 1 or _ +coverage.as:16.10-16.18: warning, this pattern consuming type + Nat +does not cover value + 0 or 1 or _ +coverage.as:23.3-23.25: warning, the cases in this switch over type + Nat +do not cover value + 0 or 1 or _ +coverage.as:24.3-24.36: warning, the cases in this switch over type + Nat +do not cover value + 0 or 1 or _ +coverage.as:32.3-32.50: warning, the cases in this switch over type + Nat +do not cover value + 0 or 1 or _ +coverage.as:35.3-35.51: warning, the cases in this switch over type + (Nat, Nat) +do not cover value + (1 or 2 or _, 1 or 2 or _) +coverage.as:41.3-41.70: warning, the cases in this switch over type + {a : Nat; b : Nat} +do not cover value + {a = 1 or 2 or _; b = 1 or 2 or _) +coverage.as:45.3-45.74: warning, the cases in this switch over type + {#a : Nat; #b : Nat} +do not cover value + #b(0 or 1 or _) +coverage.as:47.3-47.58: warning, the cases in this switch over type + {#a : Nat; #b : Nat} +do not cover value + #b(_) +coverage.as:48.3-48.58: warning, the cases in this switch over type + {#a : Nat; #b : Nat} +do not cover value + #a(_) +coverage.as:49.3-49.62: warning, the cases in this switch over type + {#a : Nat; #b : Nat; #c} +do not cover value + #a(_) or #c +coverage.as:50.3-50.42: warning, the cases in this switch over type + {#a : Nat; #b : Nat} +do not cover value + _ +coverage.as:74.3-78.4: warning, the cases in this switch over type + {#branch : (Tree, Tree); #leaf : Int} +do not cover value + #leaf(0 or 1 or _) diff --git a/test/run/ok/coverage.run.ok b/test/run/ok/coverage.run.ok index a273de79859..39ee1621c2d 100644 --- a/test/run/ok/coverage.run.ok +++ b/test/run/ok/coverage.run.ok @@ -18,27 +18,84 @@ coverage.as:38.48-38.63: warning, this case is never reached coverage.as:39.65-39.74: warning, this case is never reached coverage.as:40.58-40.67: warning, this case is never reached coverage.as:46.58-46.72: warning, this case is never reached -coverage.as:59.22-59.31: warning, this case is never reached -coverage.as:60.28-60.37: warning, this case is never reached -coverage.as:61.49-61.50: warning, this pattern is never matched -coverage.as:62.48-62.49: warning, this pattern is never matched -coverage.as:63.41-63.42: warning, this pattern is never matched -coverage.as:64.40-64.41: warning, this pattern is never matched -coverage.as:75.5-75.55: warning, this case is never reached -coverage.as:107.3-107.52: warning, this case is never reached -coverage.as:4.7-4.8: warning, this pattern does not cover all possible values -coverage.as:5.7-5.15: warning, this pattern does not cover all possible values -coverage.as:9.7-9.9: warning, this pattern does not cover all possible values -coverage.as:10.7-10.9: warning, this pattern does not cover all possible values -coverage.as:11.7-11.9: warning, this pattern does not cover all possible values -coverage.as:15.10-15.13: warning, this pattern does not cover all possible values -coverage.as:16.10-16.18: warning, this pattern does not cover all possible values -coverage.as:23.3-23.25: warning, the cases in this switch do not cover all possible values -coverage.as:24.3-24.36: warning, the cases in this switch do not cover all possible values -coverage.as:32.3-32.50: warning, the cases in this switch do not cover all possible values -coverage.as:35.3-35.51: warning, the cases in this switch do not cover all possible values -coverage.as:41.3-41.70: warning, the cases in this switch do not cover all possible values -coverage.as:45.3-45.74: warning, the cases in this switch do not cover all possible values -coverage.as:47.3-47.58: warning, the cases in this switch do not cover all possible values -coverage.as:48.3-48.58: warning, the cases in this switch do not cover all possible values -coverage.as:72.3-76.4: warning, the cases in this switch do not cover all possible values +coverage.as:61.22-61.31: warning, this case is never reached +coverage.as:62.28-62.37: warning, this case is never reached +coverage.as:63.49-63.50: warning, this pattern is never matched +coverage.as:64.48-64.49: warning, this pattern is never matched +coverage.as:65.41-65.42: warning, this pattern is never matched +coverage.as:66.40-66.41: warning, this pattern is never matched +coverage.as:77.5-77.55: warning, this case is never reached +coverage.as:109.3-109.52: warning, this case is never reached +coverage.as:4.7-4.8: warning, this pattern consuming type + Nat +does not cover value + 0 or 1 or _ +coverage.as:5.7-5.15: warning, this pattern consuming type + Nat +does not cover value + 0 or 1 or _ +coverage.as:9.7-9.9: warning, this pattern consuming type + ?Nat +does not cover value + null +coverage.as:10.7-10.9: warning, this pattern consuming type + ?Nat +does not cover value + null +coverage.as:11.7-11.9: warning, this pattern consuming type + ?Nat +does not cover value + ?(0 or 1 or _) or + null +coverage.as:15.10-15.13: warning, this pattern consuming type + Nat +does not cover value + 0 or 1 or _ +coverage.as:16.10-16.18: warning, this pattern consuming type + Nat +does not cover value + 0 or 1 or _ +coverage.as:23.3-23.25: warning, the cases in this switch over type + Nat +do not cover value + 0 or 1 or _ +coverage.as:24.3-24.36: warning, the cases in this switch over type + Nat +do not cover value + 0 or 1 or _ +coverage.as:32.3-32.50: warning, the cases in this switch over type + Nat +do not cover value + 0 or 1 or _ +coverage.as:35.3-35.51: warning, the cases in this switch over type + (Nat, Nat) +do not cover value + (1 or 2 or _, 1 or 2 or _) +coverage.as:41.3-41.70: warning, the cases in this switch over type + {a : Nat; b : Nat} +do not cover value + {a = 1 or 2 or _; b = 1 or 2 or _) +coverage.as:45.3-45.74: warning, the cases in this switch over type + {#a : Nat; #b : Nat} +do not cover value + #b(0 or 1 or _) +coverage.as:47.3-47.58: warning, the cases in this switch over type + {#a : Nat; #b : Nat} +do not cover value + #b(_) +coverage.as:48.3-48.58: warning, the cases in this switch over type + {#a : Nat; #b : Nat} +do not cover value + #a(_) +coverage.as:49.3-49.62: warning, the cases in this switch over type + {#a : Nat; #b : Nat; #c} +do not cover value + #a(_) or #c +coverage.as:50.3-50.42: warning, the cases in this switch over type + {#a : Nat; #b : Nat} +do not cover value + _ +coverage.as:74.3-78.4: warning, the cases in this switch over type + {#branch : (Tree, Tree); #leaf : Int} +do not cover value + #leaf(0 or 1 or _) diff --git a/test/run/ok/coverage.tc.ok b/test/run/ok/coverage.tc.ok index a273de79859..39ee1621c2d 100644 --- a/test/run/ok/coverage.tc.ok +++ b/test/run/ok/coverage.tc.ok @@ -18,27 +18,84 @@ coverage.as:38.48-38.63: warning, this case is never reached coverage.as:39.65-39.74: warning, this case is never reached coverage.as:40.58-40.67: warning, this case is never reached coverage.as:46.58-46.72: warning, this case is never reached -coverage.as:59.22-59.31: warning, this case is never reached -coverage.as:60.28-60.37: warning, this case is never reached -coverage.as:61.49-61.50: warning, this pattern is never matched -coverage.as:62.48-62.49: warning, this pattern is never matched -coverage.as:63.41-63.42: warning, this pattern is never matched -coverage.as:64.40-64.41: warning, this pattern is never matched -coverage.as:75.5-75.55: warning, this case is never reached -coverage.as:107.3-107.52: warning, this case is never reached -coverage.as:4.7-4.8: warning, this pattern does not cover all possible values -coverage.as:5.7-5.15: warning, this pattern does not cover all possible values -coverage.as:9.7-9.9: warning, this pattern does not cover all possible values -coverage.as:10.7-10.9: warning, this pattern does not cover all possible values -coverage.as:11.7-11.9: warning, this pattern does not cover all possible values -coverage.as:15.10-15.13: warning, this pattern does not cover all possible values -coverage.as:16.10-16.18: warning, this pattern does not cover all possible values -coverage.as:23.3-23.25: warning, the cases in this switch do not cover all possible values -coverage.as:24.3-24.36: warning, the cases in this switch do not cover all possible values -coverage.as:32.3-32.50: warning, the cases in this switch do not cover all possible values -coverage.as:35.3-35.51: warning, the cases in this switch do not cover all possible values -coverage.as:41.3-41.70: warning, the cases in this switch do not cover all possible values -coverage.as:45.3-45.74: warning, the cases in this switch do not cover all possible values -coverage.as:47.3-47.58: warning, the cases in this switch do not cover all possible values -coverage.as:48.3-48.58: warning, the cases in this switch do not cover all possible values -coverage.as:72.3-76.4: warning, the cases in this switch do not cover all possible values +coverage.as:61.22-61.31: warning, this case is never reached +coverage.as:62.28-62.37: warning, this case is never reached +coverage.as:63.49-63.50: warning, this pattern is never matched +coverage.as:64.48-64.49: warning, this pattern is never matched +coverage.as:65.41-65.42: warning, this pattern is never matched +coverage.as:66.40-66.41: warning, this pattern is never matched +coverage.as:77.5-77.55: warning, this case is never reached +coverage.as:109.3-109.52: warning, this case is never reached +coverage.as:4.7-4.8: warning, this pattern consuming type + Nat +does not cover value + 0 or 1 or _ +coverage.as:5.7-5.15: warning, this pattern consuming type + Nat +does not cover value + 0 or 1 or _ +coverage.as:9.7-9.9: warning, this pattern consuming type + ?Nat +does not cover value + null +coverage.as:10.7-10.9: warning, this pattern consuming type + ?Nat +does not cover value + null +coverage.as:11.7-11.9: warning, this pattern consuming type + ?Nat +does not cover value + ?(0 or 1 or _) or + null +coverage.as:15.10-15.13: warning, this pattern consuming type + Nat +does not cover value + 0 or 1 or _ +coverage.as:16.10-16.18: warning, this pattern consuming type + Nat +does not cover value + 0 or 1 or _ +coverage.as:23.3-23.25: warning, the cases in this switch over type + Nat +do not cover value + 0 or 1 or _ +coverage.as:24.3-24.36: warning, the cases in this switch over type + Nat +do not cover value + 0 or 1 or _ +coverage.as:32.3-32.50: warning, the cases in this switch over type + Nat +do not cover value + 0 or 1 or _ +coverage.as:35.3-35.51: warning, the cases in this switch over type + (Nat, Nat) +do not cover value + (1 or 2 or _, 1 or 2 or _) +coverage.as:41.3-41.70: warning, the cases in this switch over type + {a : Nat; b : Nat} +do not cover value + {a = 1 or 2 or _; b = 1 or 2 or _) +coverage.as:45.3-45.74: warning, the cases in this switch over type + {#a : Nat; #b : Nat} +do not cover value + #b(0 or 1 or _) +coverage.as:47.3-47.58: warning, the cases in this switch over type + {#a : Nat; #b : Nat} +do not cover value + #b(_) +coverage.as:48.3-48.58: warning, the cases in this switch over type + {#a : Nat; #b : Nat} +do not cover value + #a(_) +coverage.as:49.3-49.62: warning, the cases in this switch over type + {#a : Nat; #b : Nat; #c} +do not cover value + #a(_) or #c +coverage.as:50.3-50.42: warning, the cases in this switch over type + {#a : Nat; #b : Nat} +do not cover value + _ +coverage.as:74.3-78.4: warning, the cases in this switch over type + {#branch : (Tree, Tree); #leaf : Int} +do not cover value + #leaf(0 or 1 or _) diff --git a/test/run/ok/coverage.wasm.stderr.ok b/test/run/ok/coverage.wasm.stderr.ok index a273de79859..39ee1621c2d 100644 --- a/test/run/ok/coverage.wasm.stderr.ok +++ b/test/run/ok/coverage.wasm.stderr.ok @@ -18,27 +18,84 @@ coverage.as:38.48-38.63: warning, this case is never reached coverage.as:39.65-39.74: warning, this case is never reached coverage.as:40.58-40.67: warning, this case is never reached coverage.as:46.58-46.72: warning, this case is never reached -coverage.as:59.22-59.31: warning, this case is never reached -coverage.as:60.28-60.37: warning, this case is never reached -coverage.as:61.49-61.50: warning, this pattern is never matched -coverage.as:62.48-62.49: warning, this pattern is never matched -coverage.as:63.41-63.42: warning, this pattern is never matched -coverage.as:64.40-64.41: warning, this pattern is never matched -coverage.as:75.5-75.55: warning, this case is never reached -coverage.as:107.3-107.52: warning, this case is never reached -coverage.as:4.7-4.8: warning, this pattern does not cover all possible values -coverage.as:5.7-5.15: warning, this pattern does not cover all possible values -coverage.as:9.7-9.9: warning, this pattern does not cover all possible values -coverage.as:10.7-10.9: warning, this pattern does not cover all possible values -coverage.as:11.7-11.9: warning, this pattern does not cover all possible values -coverage.as:15.10-15.13: warning, this pattern does not cover all possible values -coverage.as:16.10-16.18: warning, this pattern does not cover all possible values -coverage.as:23.3-23.25: warning, the cases in this switch do not cover all possible values -coverage.as:24.3-24.36: warning, the cases in this switch do not cover all possible values -coverage.as:32.3-32.50: warning, the cases in this switch do not cover all possible values -coverage.as:35.3-35.51: warning, the cases in this switch do not cover all possible values -coverage.as:41.3-41.70: warning, the cases in this switch do not cover all possible values -coverage.as:45.3-45.74: warning, the cases in this switch do not cover all possible values -coverage.as:47.3-47.58: warning, the cases in this switch do not cover all possible values -coverage.as:48.3-48.58: warning, the cases in this switch do not cover all possible values -coverage.as:72.3-76.4: warning, the cases in this switch do not cover all possible values +coverage.as:61.22-61.31: warning, this case is never reached +coverage.as:62.28-62.37: warning, this case is never reached +coverage.as:63.49-63.50: warning, this pattern is never matched +coverage.as:64.48-64.49: warning, this pattern is never matched +coverage.as:65.41-65.42: warning, this pattern is never matched +coverage.as:66.40-66.41: warning, this pattern is never matched +coverage.as:77.5-77.55: warning, this case is never reached +coverage.as:109.3-109.52: warning, this case is never reached +coverage.as:4.7-4.8: warning, this pattern consuming type + Nat +does not cover value + 0 or 1 or _ +coverage.as:5.7-5.15: warning, this pattern consuming type + Nat +does not cover value + 0 or 1 or _ +coverage.as:9.7-9.9: warning, this pattern consuming type + ?Nat +does not cover value + null +coverage.as:10.7-10.9: warning, this pattern consuming type + ?Nat +does not cover value + null +coverage.as:11.7-11.9: warning, this pattern consuming type + ?Nat +does not cover value + ?(0 or 1 or _) or + null +coverage.as:15.10-15.13: warning, this pattern consuming type + Nat +does not cover value + 0 or 1 or _ +coverage.as:16.10-16.18: warning, this pattern consuming type + Nat +does not cover value + 0 or 1 or _ +coverage.as:23.3-23.25: warning, the cases in this switch over type + Nat +do not cover value + 0 or 1 or _ +coverage.as:24.3-24.36: warning, the cases in this switch over type + Nat +do not cover value + 0 or 1 or _ +coverage.as:32.3-32.50: warning, the cases in this switch over type + Nat +do not cover value + 0 or 1 or _ +coverage.as:35.3-35.51: warning, the cases in this switch over type + (Nat, Nat) +do not cover value + (1 or 2 or _, 1 or 2 or _) +coverage.as:41.3-41.70: warning, the cases in this switch over type + {a : Nat; b : Nat} +do not cover value + {a = 1 or 2 or _; b = 1 or 2 or _) +coverage.as:45.3-45.74: warning, the cases in this switch over type + {#a : Nat; #b : Nat} +do not cover value + #b(0 or 1 or _) +coverage.as:47.3-47.58: warning, the cases in this switch over type + {#a : Nat; #b : Nat} +do not cover value + #b(_) +coverage.as:48.3-48.58: warning, the cases in this switch over type + {#a : Nat; #b : Nat} +do not cover value + #a(_) +coverage.as:49.3-49.62: warning, the cases in this switch over type + {#a : Nat; #b : Nat; #c} +do not cover value + #a(_) or #c +coverage.as:50.3-50.42: warning, the cases in this switch over type + {#a : Nat; #b : Nat} +do not cover value + _ +coverage.as:74.3-78.4: warning, the cases in this switch over type + {#branch : (Tree, Tree); #leaf : Int} +do not cover value + #leaf(0 or 1 or _) diff --git a/test/run/ok/objects1.run-ir.ok b/test/run/ok/objects1.run-ir.ok index 73662fc5762..91dcd890805 100644 --- a/test/run/ok/objects1.run-ir.ok +++ b/test/run/ok/objects1.run-ir.ok @@ -1,4 +1,10 @@ objects1.as:22.3-22.26: warning, this case is never reached objects1.as:23.3-23.14: warning, this case is never reached -objects1.as:32.23-35.2: warning, the cases in this switch do not cover all possible values -objects1.as:43.21-45.2: warning, the cases in this switch do not cover all possible values +objects1.as:32.23-35.2: warning, the cases in this switch over type + {a : Int; b : Nat} +do not cover value + {a = 0 or 1 or _; b = 0 or 1 or _) +objects1.as:43.21-45.2: warning, the cases in this switch over type + (Nat, Int, {c : Char; d : Text}) +do not cover value + (_, 0 or 1 or _, _) diff --git a/test/run/ok/objects1.run-low.ok b/test/run/ok/objects1.run-low.ok index 73662fc5762..91dcd890805 100644 --- a/test/run/ok/objects1.run-low.ok +++ b/test/run/ok/objects1.run-low.ok @@ -1,4 +1,10 @@ objects1.as:22.3-22.26: warning, this case is never reached objects1.as:23.3-23.14: warning, this case is never reached -objects1.as:32.23-35.2: warning, the cases in this switch do not cover all possible values -objects1.as:43.21-45.2: warning, the cases in this switch do not cover all possible values +objects1.as:32.23-35.2: warning, the cases in this switch over type + {a : Int; b : Nat} +do not cover value + {a = 0 or 1 or _; b = 0 or 1 or _) +objects1.as:43.21-45.2: warning, the cases in this switch over type + (Nat, Int, {c : Char; d : Text}) +do not cover value + (_, 0 or 1 or _, _) diff --git a/test/run/ok/objects1.run.ok b/test/run/ok/objects1.run.ok index 73662fc5762..91dcd890805 100644 --- a/test/run/ok/objects1.run.ok +++ b/test/run/ok/objects1.run.ok @@ -1,4 +1,10 @@ objects1.as:22.3-22.26: warning, this case is never reached objects1.as:23.3-23.14: warning, this case is never reached -objects1.as:32.23-35.2: warning, the cases in this switch do not cover all possible values -objects1.as:43.21-45.2: warning, the cases in this switch do not cover all possible values +objects1.as:32.23-35.2: warning, the cases in this switch over type + {a : Int; b : Nat} +do not cover value + {a = 0 or 1 or _; b = 0 or 1 or _) +objects1.as:43.21-45.2: warning, the cases in this switch over type + (Nat, Int, {c : Char; d : Text}) +do not cover value + (_, 0 or 1 or _, _) diff --git a/test/run/ok/objects1.tc.ok b/test/run/ok/objects1.tc.ok index 73662fc5762..91dcd890805 100644 --- a/test/run/ok/objects1.tc.ok +++ b/test/run/ok/objects1.tc.ok @@ -1,4 +1,10 @@ objects1.as:22.3-22.26: warning, this case is never reached objects1.as:23.3-23.14: warning, this case is never reached -objects1.as:32.23-35.2: warning, the cases in this switch do not cover all possible values -objects1.as:43.21-45.2: warning, the cases in this switch do not cover all possible values +objects1.as:32.23-35.2: warning, the cases in this switch over type + {a : Int; b : Nat} +do not cover value + {a = 0 or 1 or _; b = 0 or 1 or _) +objects1.as:43.21-45.2: warning, the cases in this switch over type + (Nat, Int, {c : Char; d : Text}) +do not cover value + (_, 0 or 1 or _, _) diff --git a/test/run/ok/objects1.wasm.stderr.ok b/test/run/ok/objects1.wasm.stderr.ok index 73662fc5762..91dcd890805 100644 --- a/test/run/ok/objects1.wasm.stderr.ok +++ b/test/run/ok/objects1.wasm.stderr.ok @@ -1,4 +1,10 @@ objects1.as:22.3-22.26: warning, this case is never reached objects1.as:23.3-23.14: warning, this case is never reached -objects1.as:32.23-35.2: warning, the cases in this switch do not cover all possible values -objects1.as:43.21-45.2: warning, the cases in this switch do not cover all possible values +objects1.as:32.23-35.2: warning, the cases in this switch over type + {a : Int; b : Nat} +do not cover value + {a = 0 or 1 or _; b = 0 or 1 or _) +objects1.as:43.21-45.2: warning, the cases in this switch over type + (Nat, Int, {c : Char; d : Text}) +do not cover value + (_, 0 or 1 or _, _) diff --git a/test/run/ok/switch.run-ir.ok b/test/run/ok/switch.run-ir.ok index 650be56a521..0a7d23907a0 100644 --- a/test/run/ok/switch.run-ir.ok +++ b/test/run/ok/switch.run-ir.ok @@ -1,5 +1,17 @@ switch.as:86.29-86.30: warning, this pattern is never matched -switch.as:75.11-77.2: warning, the cases in this switch do not cover all possible values -switch.as:81.3-81.14: warning, the cases in this switch do not cover all possible values -switch.as:92.11-94.2: warning, the cases in this switch do not cover all possible values -switch.as:97.11-99.2: warning, the cases in this switch do not cover all possible values +switch.as:75.11-77.2: warning, the cases in this switch over type + ?Int +do not cover value + ?(_) +switch.as:81.3-81.14: warning, the cases in this switch over type + Nat +do not cover value + _ +switch.as:92.11-94.2: warning, the cases in this switch over type + ?Nat +do not cover value + null +switch.as:97.11-99.2: warning, the cases in this switch over type + ?Nat +do not cover value + ?(_) diff --git a/test/run/ok/switch.run-low.ok b/test/run/ok/switch.run-low.ok index 650be56a521..0a7d23907a0 100644 --- a/test/run/ok/switch.run-low.ok +++ b/test/run/ok/switch.run-low.ok @@ -1,5 +1,17 @@ switch.as:86.29-86.30: warning, this pattern is never matched -switch.as:75.11-77.2: warning, the cases in this switch do not cover all possible values -switch.as:81.3-81.14: warning, the cases in this switch do not cover all possible values -switch.as:92.11-94.2: warning, the cases in this switch do not cover all possible values -switch.as:97.11-99.2: warning, the cases in this switch do not cover all possible values +switch.as:75.11-77.2: warning, the cases in this switch over type + ?Int +do not cover value + ?(_) +switch.as:81.3-81.14: warning, the cases in this switch over type + Nat +do not cover value + _ +switch.as:92.11-94.2: warning, the cases in this switch over type + ?Nat +do not cover value + null +switch.as:97.11-99.2: warning, the cases in this switch over type + ?Nat +do not cover value + ?(_) diff --git a/test/run/ok/switch.run.ok b/test/run/ok/switch.run.ok index 650be56a521..0a7d23907a0 100644 --- a/test/run/ok/switch.run.ok +++ b/test/run/ok/switch.run.ok @@ -1,5 +1,17 @@ switch.as:86.29-86.30: warning, this pattern is never matched -switch.as:75.11-77.2: warning, the cases in this switch do not cover all possible values -switch.as:81.3-81.14: warning, the cases in this switch do not cover all possible values -switch.as:92.11-94.2: warning, the cases in this switch do not cover all possible values -switch.as:97.11-99.2: warning, the cases in this switch do not cover all possible values +switch.as:75.11-77.2: warning, the cases in this switch over type + ?Int +do not cover value + ?(_) +switch.as:81.3-81.14: warning, the cases in this switch over type + Nat +do not cover value + _ +switch.as:92.11-94.2: warning, the cases in this switch over type + ?Nat +do not cover value + null +switch.as:97.11-99.2: warning, the cases in this switch over type + ?Nat +do not cover value + ?(_) diff --git a/test/run/ok/switch.tc.ok b/test/run/ok/switch.tc.ok index 650be56a521..0a7d23907a0 100644 --- a/test/run/ok/switch.tc.ok +++ b/test/run/ok/switch.tc.ok @@ -1,5 +1,17 @@ switch.as:86.29-86.30: warning, this pattern is never matched -switch.as:75.11-77.2: warning, the cases in this switch do not cover all possible values -switch.as:81.3-81.14: warning, the cases in this switch do not cover all possible values -switch.as:92.11-94.2: warning, the cases in this switch do not cover all possible values -switch.as:97.11-99.2: warning, the cases in this switch do not cover all possible values +switch.as:75.11-77.2: warning, the cases in this switch over type + ?Int +do not cover value + ?(_) +switch.as:81.3-81.14: warning, the cases in this switch over type + Nat +do not cover value + _ +switch.as:92.11-94.2: warning, the cases in this switch over type + ?Nat +do not cover value + null +switch.as:97.11-99.2: warning, the cases in this switch over type + ?Nat +do not cover value + ?(_) diff --git a/test/run/ok/switch.wasm.stderr.ok b/test/run/ok/switch.wasm.stderr.ok index 650be56a521..0a7d23907a0 100644 --- a/test/run/ok/switch.wasm.stderr.ok +++ b/test/run/ok/switch.wasm.stderr.ok @@ -1,5 +1,17 @@ switch.as:86.29-86.30: warning, this pattern is never matched -switch.as:75.11-77.2: warning, the cases in this switch do not cover all possible values -switch.as:81.3-81.14: warning, the cases in this switch do not cover all possible values -switch.as:92.11-94.2: warning, the cases in this switch do not cover all possible values -switch.as:97.11-99.2: warning, the cases in this switch do not cover all possible values +switch.as:75.11-77.2: warning, the cases in this switch over type + ?Int +do not cover value + ?(_) +switch.as:81.3-81.14: warning, the cases in this switch over type + Nat +do not cover value + _ +switch.as:92.11-94.2: warning, the cases in this switch over type + ?Nat +do not cover value + null +switch.as:97.11-99.2: warning, the cases in this switch over type + ?Nat +do not cover value + ?(_) From 14ebd102198a6e5b626b46f27204c550f98a51ed Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Wed, 10 Jul 2019 07:37:25 -0700 Subject: [PATCH 0245/1176] review comments from Joachim; fix URL semantics --- src/lang_utils/diag.mli | 1 - src/pipeline/resolve_import.ml | 44 ++++++++++++++++++---------------- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/src/lang_utils/diag.mli b/src/lang_utils/diag.mli index 357bdebd2d4..b76c34f1495 100644 --- a/src/lang_utils/diag.mli +++ b/src/lang_utils/diag.mli @@ -48,6 +48,5 @@ the reported messages contain an error. type msg_store val add_msg : msg_store -> message -> unit val add_msgs : msg_store -> messages -> unit -val get_msgs : msg_store -> messages val with_message_store : (msg_store -> 'a option) -> 'a result diff --git a/src/pipeline/resolve_import.ml b/src/pipeline/resolve_import.ml index a6ac989b15e..1d911c884ae 100644 --- a/src/pipeline/resolve_import.ml +++ b/src/pipeline/resolve_import.ml @@ -10,15 +10,6 @@ in the second, mutable field of the ImportE statement. It returns a list of all imported file names. - -SEARCH_PATH functionality --------------------------- -- Uses `--package` CLI option -- See Jira Ticket: https://dfinity.atlassian.net/browse/SDK-269 -- See also: `Pipeline.Flags.package_urls`, of type `(string * string) list ref`; - - Each key-value pair gives a package-name, package-URL pairing - - the URL can be interpreted as a filesystem path, for now. - *) (* written as a functor so we can allocate some temporary shared state without making it global *) @@ -28,8 +19,12 @@ type filepath = string module S = Set.Make(String) module M = Map.Make(String) -(* type packages maps package names to package URLs (filenames): - e.g., packages("std") = "/Users/home/username/.dfinity-sdk/src/as-stdlib" +(* a map of type package_map will map each package name to a(n optional) package URL, + which for now is just a filesystem path: + + e.g., + packages("std") = "/Users/home/username/.dfinity-sdk/src/as-stdlib/0.1.0/" + packages("foo") = "/Users/home/username/fooPackage/1.2.3/src" *) type package_map = string M.t @@ -43,12 +38,14 @@ type env = { open Syntax open Source -let get_package_name_and_path (f: string) : (string * string) option = - (* loop recursively until we get to a 'self-loop', indicated by dirname '.' ; - in each iteration, we use function pair (dirname, basename) - to decompose the filename. - *) +(* match `f` against the URL pattern 'as:package-name/path', + optionally returning the package-name and path components as a pair of strings. *) +let match_package_name (f: string) : (string * string) option = let rec loop (f: string) (path_accum:string) : (string * string) option = + (* loop recursively until we get to a 'self-loop', indicated by dirname '.' ; + in each iteration, we use function pair (dirname, basename) + to decompose the filename. + *) let (dir, base) = (Filename.dirname f, Filename.basename f) in match dir with | "." -> Some (f, path_accum) @@ -57,14 +54,21 @@ let get_package_name_and_path (f: string) : (string * string) option = loop dir (Filename.concat base path_accum) end in - loop f "" + let (prefix, suffix) = ( + String.sub f 0 3, + String.sub f 3 ((String.length f) - 3) + ) + in + match prefix with + | "as:" -> loop suffix "" + | _ -> None -(* using env, resolve import strings of the form "package-name/mod1/mod2/item" +(* using env, resolve import strings of the form "as:package-name/mod1/mod2/item" into the triple ("package-name", "package-url", "mod1/mod2/item") when the package name is defined. Does not validate the package url or path. *) let resolve_package env (f: string) : (string * string * string) option = - match get_package_name_and_path f with + match match_package_name f with | None -> None | Some (name, path) -> if M.mem name env.packages then @@ -99,7 +103,7 @@ let resolve_import_string env region (f: string) (fp: string ref) = text = Printf.sprintf "File \"%s\" does not exist" f } -(* compare to the `resolve_import_string`'s filesystem semantics; +(* compare to the filesystem semantics of function `resolve_import_string`: the two import-string to filesystem-path resolution semantics agree for now, but other API details and usage are distinct. *) From 555ed57ff39969de73699f17fc0573599c608209 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Wed, 10 Jul 2019 07:50:11 -0700 Subject: [PATCH 0246/1176] bug fix: avoid exceptions from String.sub --- src/pipeline/resolve_import.ml | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/pipeline/resolve_import.ml b/src/pipeline/resolve_import.ml index 1d911c884ae..7edbc5e8062 100644 --- a/src/pipeline/resolve_import.ml +++ b/src/pipeline/resolve_import.ml @@ -54,14 +54,15 @@ let match_package_name (f: string) : (string * string) option = loop dir (Filename.concat base path_accum) end in - let (prefix, suffix) = ( - String.sub f 0 3, - String.sub f 3 ((String.length f) - 3) - ) - in - match prefix with - | "as:" -> loop suffix "" - | _ -> None + if String.length f < 3 then None else + let (prefix, suffix) = ( + String.sub f 0 3, + String.sub f 3 ((String.length f) - 3) + ) + in + match prefix with + | "as:" -> loop suffix "" + | _ -> None (* using env, resolve import strings of the form "as:package-name/mod1/mod2/item" into the triple ("package-name", "package-url", "mod1/mod2/item") when the package name is defined. From 7b21ef872dc8f71a5a16c24a1408c688e8d397d4 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Wed, 10 Jul 2019 07:59:18 -0700 Subject: [PATCH 0247/1176] hide CLI state, as per Joachim's code review --- src/exes/asc.ml | 9 +++++---- src/pipeline/pipeline.ml | 1 - src/pipeline/pipeline.mli | 1 - 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/exes/asc.ml b/src/exes/asc.ml index a3c2d67f26c..914c7e0a12f 100644 --- a/src/exes/asc.ml +++ b/src/exes/asc.ml @@ -43,16 +43,17 @@ let argspec = Arg.align "--map", Arg.Set gen_source_map, " output source map"; "-t", Arg.Set Pipeline.Flags.trace, " activate tracing"; - "--package", Arg.Tuple [ - Arg.Set_string Pipeline.Flags.package_name_temp ; + "--package", (let package_name_ref = ref "DEADBEEF" in + Arg.Tuple [ + Arg.Set_string package_name_ref ; Arg.String begin fun package_url -> (* push (package_name, package_url) onto the list. *) Pipeline.Flags.package_urls := ( - !Pipeline.Flags.package_name_temp, + !package_name_ref, package_url ) :: ! Pipeline.Flags.package_urls end - ], " Specify a package-name-package-URL pair, separated by a space" ; + ]), " Specify a package-name-package-URL pair, separated by a space" ; "--profile", Arg.Set Pipeline.Flags.profile, " activate profiling counters in interpreters "; "--profile-file", Arg.Set_string Pipeline.Flags.profile_file, " set profiling output file "; "--profile-line-prefix", Arg.Set_string Pipeline.Flags.profile_line_prefix, " prefix each profile line with the given string "; diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index da6cd13f939..c49daac6186 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -24,7 +24,6 @@ module Flags = struct let dump_lowering = ref false let check_ir = ref true let package_urls : (string * string) list ref = ref [] - let package_name_temp : string ref = ref "DEADBEEF" let profile = ref false let profile_verbose = ref false let profile_file = ref "profiling-counters.csv" diff --git a/src/pipeline/pipeline.mli b/src/pipeline/pipeline.mli index 1bbbb5442e0..c76c3ef4e77 100644 --- a/src/pipeline/pipeline.mli +++ b/src/pipeline/pipeline.mli @@ -12,7 +12,6 @@ sig val dump_tc : bool ref val dump_lowering : bool ref val check_ir : bool ref - val package_name_temp : string ref val package_urls : (string * string) list ref val profile : bool ref val profile_verbose : bool ref From 06e4defcdfed063f0d88cac5f3dc6b7045961214 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Wed, 10 Jul 2019 14:51:37 -0700 Subject: [PATCH 0248/1176] URL format uses 'as://', not just 'as: --- src/pipeline/resolve_import.ml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/pipeline/resolve_import.ml b/src/pipeline/resolve_import.ml index 200a6fd553e..52ae3b29406 100644 --- a/src/pipeline/resolve_import.ml +++ b/src/pipeline/resolve_import.ml @@ -38,7 +38,7 @@ type env = { open Syntax open Source -(* match `f` against the URL pattern 'as:package-name/path', +(* match `f` against the URL pattern 'as://package-name/path', optionally returning the package-name and path components as a pair of strings. *) let match_package_name (f: string) : (string * string) option = let rec loop (f: string) (path_accum:string) : (string * string) option = @@ -54,15 +54,15 @@ let match_package_name (f: string) : (string * string) option = loop dir (Filename.concat base path_accum) end in - if String.length f < 3 then None else + if String.length f < 5 then None else let (prefix, suffix) = ( - String.sub f 0 3, - String.sub f 3 ((String.length f) - 3) + String.sub f 0 5, + String.sub f 5 ((String.length f) - 5) ) in match prefix with - | "as:" -> loop suffix "" - | _ -> None + | "as://" -> loop suffix "" + | _ -> None (* using env, resolve import strings of the form "as:package-name/mod1/mod2/item" into the triple ("package-name", "package-url", "mod1/mod2/item") when the package name is defined. From 1b7f76fb35756be0e750a31dc31572221484d473 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Wed, 10 Jul 2019 15:30:12 -0700 Subject: [PATCH 0249/1176] Add recursion point for IDL JS binding --- src/exes/didc.ml | 2 +- src/idllib/compile_js.ml | 149 ++++++++++++++++++++++++++---------- test/idl/actor.did | 2 +- test/idl/cyclic.did | 3 + test/idl/fields.did | 3 + test/idl/import1.did | 4 +- test/idl/ok/actor.js.ok | 7 +- test/idl/ok/cyclic.js.ok | 14 ++-- test/idl/ok/diamond.js.ok | 2 +- test/idl/ok/diamond2.js.ok | 2 - test/idl/ok/diamond3.js.ok | 2 - test/idl/ok/diamond4.js.ok | 1 - test/idl/ok/fields.js.ok | 5 +- test/idl/ok/import.js.ok | 21 ++--- test/idl/ok/import1.js.ok | 17 +--- test/idl/ok/import3.js.ok | 21 ++--- test/idl/ok/px.js.ok | 19 ++--- test/idl/ok/recursion.js.ok | 21 ++--- test/idl/ok/test.js.ok | 7 +- test/idl/px.did | 2 +- test/idl/recursion.did | 2 +- test/idl/test.did | 1 + 22 files changed, 186 insertions(+), 121 deletions(-) diff --git a/src/exes/didc.ml b/src/exes/didc.ml index 38085ce60f8..0a6cef4c42b 100644 --- a/src/exes/didc.ml +++ b/src/exes/didc.ml @@ -61,7 +61,7 @@ let () = Printexc.record_backtrace true; try Arg.parse argspec add_arg usage; - if !mode = Default then mode := Check; + if !mode = Default then mode := Js; match !args with | [file] -> process_file file | _ -> eprintf "didc can only take one .did file\n"; exit 1 diff --git a/src/idllib/compile_js.ml b/src/idllib/compile_js.ml index 8baec054016..0ff4b268c03 100644 --- a/src/idllib/compile_js.ml +++ b/src/idllib/compile_js.ml @@ -3,6 +3,63 @@ open Format open Syntax open Source +module Env = Typing.Env +module TS = Set.Make(String) + +(* Gather type definitions from actor and sort the definitions in topological order *) +let chase_env env actor = + let new_env = ref [] in + let seen = ref TS.empty in + let rec chase t = + match t.it with + | PrimT _ -> () + | VarT id -> + if not (TS.mem id.it !seen) then begin + seen := TS.add id.it !seen; + let t = Env.find id.it env in + chase t; + new_env := (id.it, t) :: !new_env; + end + | ServT ms -> List.iter (fun m -> chase m.it.meth) ms + | OptT t -> chase t + | VecT t -> chase t + | RecordT fs -> chase_fields fs + | VariantT fs -> chase_fields fs + | FuncT (ms, fs1, fs2) -> chase_fields fs1; chase_fields fs2 + | PreT -> assert false + and chase_fields fs = + List.iter (fun (f : typ_field) -> chase f.it.typ) fs + in + match actor.it with + | ActorD (_, t) -> + chase t; + List.rev (!new_env) + +(* Given a topologically sorted type definition list, infer which types are recursive *) +let infer_rec env_list = + let seen = ref TS.empty in + let recs = ref TS.empty in + let rec go t = + match t.it with + | PrimT _ -> () + | VarT id -> + if not (TS.mem id.it !seen) then begin + seen := TS.add id.it !seen; + recs := TS.add id.it !recs + end + | ServT ms -> List.iter (fun m -> go m.it.meth) ms + | OptT t -> go t + | VecT t -> go t + | RecordT fs -> go_fields fs + | VariantT fs -> go_fields fs + | FuncT (_, fs1, fs2) -> go_fields fs1; go_fields fs2 + | preT -> assert false + and go_fields fs = + List.iter (fun (f:typ_field) -> go f.it.typ) fs + in + List.iter (fun (x,t) -> go t; seen := TS.add x !seen) env_list; + !recs + let str ppf s = pp_print_string ppf s; pp_print_cut ppf () let id ppf s = str ppf s.it; pp_print_cut ppf () let space = pp_print_space @@ -28,92 +85,100 @@ let pp_prim p = | Null -> "Unit" | Reserved -> "None" -let rec concat ppf f env sep list = +let rec concat ppf f sep list = match list with | [] -> () - | e::[] -> f ppf env e; pp_print_cut ppf () - | e::tail -> f ppf env e; str ppf sep; space ppf (); concat ppf f env sep tail + | e::[] -> f ppf e; pp_print_cut ppf () + | e::tail -> f ppf e; str ppf sep; space ppf (); concat ppf f sep tail -let rec pp_typ ppf env t = +let rec pp_typ ppf t = pp_open_box ppf 1; (match t.it with | VarT s -> id ppf s | PrimT p -> str ppf ("IDL."^(pp_prim p)) - | RecordT ts -> pp_fields ppf env ts - | VecT t -> str ppf "IDL.Arr("; pp_typ ppf env t; str ppf ")"; - | OptT t -> str ppf "IDL.Opt("; pp_typ ppf env t; str ppf ")"; - | VariantT ts -> str ppf "IDL.Variant({"; concat ppf pp_field env "," ts; str ppf "})"; + | RecordT ts -> pp_fields ppf ts + | VecT t -> str ppf "IDL.Arr("; pp_typ ppf t; str ppf ")"; + | OptT t -> str ppf "IDL.Opt("; pp_typ ppf t; str ppf ")"; + | VariantT ts -> str ppf "IDL.Variant({"; concat ppf pp_field "," ts; str ppf "})"; | FuncT (ms, t1, t2) -> str ppf "IDL.message("; - pp_fields ppf env t1; + pp_fields ppf t1; kwd ppf ","; - pp_fields ppf env t2; + pp_fields ppf t2; str ppf ")"; | ServT ts -> pp_open_hovbox ppf 1; kwd ppf "new"; str ppf "IDL.ActorInterface({"; - concat ppf pp_meth env "," ts; + concat ppf pp_meth "," ts; str ppf "})"; pp_close_box ppf (); - | PreT -> () + | PreT -> assert false ); pp_close_box ppf () -and pp_fields ppf env fs = +and pp_fields ppf fs = pp_open_box ppf 1; str ppf "IDL.Obj({"; - concat ppf pp_field env "," fs; + concat ppf pp_field "," fs; str ppf "})"; pp_close_box ppf () -and pp_field ppf env tf = +and pp_field ppf tf = pp_open_box ppf 1; - field_name ppf tf.it.name; kwd ppf ":"; pp_typ ppf env tf.it.typ; + field_name ppf tf.it.name; kwd ppf ":"; pp_typ ppf tf.it.typ; pp_close_box ppf () -and pp_meth ppf env meth = +and pp_meth ppf meth = pp_open_box ppf 1; field_name ppf meth.it.var; kwd ppf ":"; - pp_typ ppf env meth.it.meth; + pp_typ ppf meth.it.meth; pp_close_box ppf () -let pp_dec ppf env x t = +let pp_dec ppf (x,t) = pp_open_hovbox ppf 1; kwd ppf "const"; kwd ppf x; kwd ppf "="; - pp_typ ppf env t; + pp_typ ppf t; pp_close_box ppf (); pp_print_cut ppf () - -let pp_actor ppf env actor_opt = + +let pp_rec ppf x = pp_open_hovbox ppf 1; - (match actor_opt with - None -> () - | Some actor -> - kwd ppf "const"; - (match actor.it with - | ActorD (x, {it=ServT tp; _}) -> - id ppf x; space ppf (); kwd ppf "="; kwd ppf "new"; - str ppf "IDL.ActorInterface({"; - concat ppf pp_meth env "," tp; - str ppf "})" - | ActorD (x, {it=VarT var; _}) -> id ppf x; space ppf (); kwd ppf "="; id ppf var - | ActorD (x, _) -> () - ) + kwd ppf "const"; + kwd ppf x; + kwd ppf "="; + str ppf "IDL.Rec()"; + pp_close_box ppf (); + pp_print_cut ppf () + +let pp_actor ppf actor = + pp_open_hovbox ppf 1; + kwd ppf "const"; + (match actor.it with + | ActorD (x, {it=ServT tp; _}) -> + id ppf x; space ppf (); kwd ppf "="; kwd ppf "new"; + str ppf "IDL.ActorInterface({"; + concat ppf pp_meth "," tp; + str ppf "})" + | ActorD (x, {it=VarT var; _}) -> id ppf x; space ppf (); kwd ppf "="; id ppf var + | ActorD (x, _) -> assert false ); pp_close_box ppf () let pp_prog ppf env prog = - pp_open_vbox ppf 0; - (* TODO: This is just a quick fix. - * The right way is to trace the used definitions from the actor - * and sort them in topoloical order. *) - Typing.Env.iter (pp_dec ppf env) env; - pp_actor ppf env prog.it.actor; - pp_close_box ppf () + match prog.it.actor with + | None -> () + | Some actor -> + let env_list = chase_env env actor in + let recs = infer_rec env_list in + pp_open_vbox ppf 0; + TS.iter (pp_rec ppf) recs; + List.iter (pp_dec ppf) env_list; + pp_actor ppf actor; + pp_close_box ppf () let compile (scope : Typing.scope) (prog : Syntax.prog) = let buf = Buffer.create 100 in diff --git a/test/idl/actor.did b/test/idl/actor.did index 1923f5646f3..19fde259828 100644 --- a/test/idl/actor.did +++ b/test/idl/actor.did @@ -3,7 +3,7 @@ type g = f; type h = func (f) -> (f); type o = opt o; service g { - f : (nat) -> (); + f : (nat) -> (h); g : f; h : g; o : (o) -> (o); diff --git a/test/idl/cyclic.did b/test/idl/cyclic.did index f33db13bc14..729a9f4234c 100644 --- a/test/idl/cyclic.did +++ b/test/idl/cyclic.did @@ -6,3 +6,6 @@ type X = Y; type Y = Z; type Z = A; +service S { + f : (A,B,C,X,Y,Z) -> (); +} diff --git a/test/idl/fields.did b/test/idl/fields.did index a381d4ff50a..7c4aa3c0f6e 100644 --- a/test/idl/fields.did +++ b/test/idl/fields.did @@ -11,3 +11,6 @@ type nest_record = record { A; B; C; nat; }; +service S { + f : (A,B,C,nest_record) -> (); +} diff --git a/test/idl/import1.did b/test/idl/import1.did index ddca85c742b..525ad927aa8 100644 --- a/test/idl/import1.did +++ b/test/idl/import1.did @@ -4,4 +4,6 @@ import "px.did"; type t1 = t; type t2 = UserId; - +service S { + f : (t,t1,t2) -> (); +} diff --git a/test/idl/ok/actor.js.ok b/test/idl/ok/actor.js.ok index 512aae673cf..9c3f9459833 100644 --- a/test/idl/ok/actor.js.ok +++ b/test/idl/ok/actor.js.ok @@ -1,7 +1,8 @@ +const o = IDL.Rec() const f = IDL.message(IDL.Obj({'0': IDL.Int8}), IDL.Obj({'0': IDL.Int8})) -const g = f const h = IDL.message(IDL.Obj({'0': f}), IDL.Obj({'0': f})) +const g = f const o = IDL.Opt(o) const g = new IDL.ActorInterface({ - 'f': IDL.message(IDL.Obj({'0': IDL.Nat}), IDL.Obj({})), 'g': f, 'h': g, - 'o': IDL.message(IDL.Obj({'0': o}), IDL.Obj({'0': o}))}) + 'f': IDL.message(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': h})), 'g': f, + 'h': g, 'o': IDL.message(IDL.Obj({'0': o}), IDL.Obj({'0': o}))}) diff --git a/test/idl/ok/cyclic.js.ok b/test/idl/ok/cyclic.js.ok index 669df6dbcf0..d5a4673a1ec 100644 --- a/test/idl/ok/cyclic.js.ok +++ b/test/idl/ok/cyclic.js.ok @@ -1,7 +1,11 @@ -const A = IDL.Opt(B) -const B = IDL.Opt(C) +const A = IDL.Rec() const C = A -const X = Y -const Y = Z +const B = IDL.Opt(C) +const A = IDL.Opt(B) const Z = A - +const Y = Z +const X = Y +const S = new IDL.ActorInterface({ + 'f': + IDL.message(IDL.Obj({'0': A, '1': B, '2': C, '3': X, '4': Y, '5': Z}), + IDL.Obj({}))}) diff --git a/test/idl/ok/diamond.js.ok b/test/idl/ok/diamond.js.ok index aa579ab3683..55be9ac8fa3 100644 --- a/test/idl/ok/diamond.js.ok +++ b/test/idl/ok/diamond.js.ok @@ -1,6 +1,6 @@ const t = IDL.Nat -const t1 = IDL.Obj({'0': t2, '1': t3, '2': t}) const t2 = IDL.Arr(t) const t3 = IDL.Opt(t) +const t1 = IDL.Obj({'0': t2, '1': t3, '2': t}) const S = new IDL.ActorInterface({ 'f': IDL.message(IDL.Obj({'0': t, '1': t2, '2': t3}), IDL.Obj({'0': t1}))}) diff --git a/test/idl/ok/diamond2.js.ok b/test/idl/ok/diamond2.js.ok index 8d97648bdbe..8b137891791 100644 --- a/test/idl/ok/diamond2.js.ok +++ b/test/idl/ok/diamond2.js.ok @@ -1,3 +1 @@ -const t = IDL.Nat -const t2 = IDL.Arr(t) diff --git a/test/idl/ok/diamond3.js.ok b/test/idl/ok/diamond3.js.ok index 030c50f337a..8b137891791 100644 --- a/test/idl/ok/diamond3.js.ok +++ b/test/idl/ok/diamond3.js.ok @@ -1,3 +1 @@ -const t = IDL.Nat -const t3 = IDL.Opt(t) diff --git a/test/idl/ok/diamond4.js.ok b/test/idl/ok/diamond4.js.ok index 681129d2a07..8b137891791 100644 --- a/test/idl/ok/diamond4.js.ok +++ b/test/idl/ok/diamond4.js.ok @@ -1,2 +1 @@ -const t = IDL.Nat diff --git a/test/idl/ok/fields.js.ok b/test/idl/ok/fields.js.ok index 1e0d4259a6c..eef5930f0d4 100644 --- a/test/idl/ok/fields.js.ok +++ b/test/idl/ok/fields.js.ok @@ -12,4 +12,7 @@ const nest_record = IDL.Obj({'0': IDL.Nat, '1': IDL.Nat, '2': IDL.Nat, '3': IDL.Obj({'0': IDL.Nat, '1': IDL.Nat, '2': IDL.Nat}), '4': IDL.Nat, '5': IDL.Nat, '6': IDL.Nat, '7': A, '8': B, '9': C, '10': IDL.Nat}) - +const S = new IDL.ActorInterface({ + 'f': + IDL.message(IDL.Obj({'0': A, '1': B, '2': C, '3': nest_record}), + IDL.Obj({}))}) diff --git a/test/idl/ok/import.js.ok b/test/idl/ok/import.js.ok index cdf39162bb1..a2d8865d911 100644 --- a/test/idl/ok/import.js.ok +++ b/test/idl/ok/import.js.ok @@ -1,20 +1,15 @@ +const t = IDL.Arr(IDL.Nat8) +const t1 = t +const UserId = IDL.Nat +const t2 = UserId +const list = IDL.Arr(IDL.Nat) +const RegionId = IDL.Nat +const TruckTypeId = IDL.Nat const EntId = IDL.Obj({'region': RegionId, 'user': UserId, 'truckType': TruckTypeId}) +const OpEntId = IDL.Opt(EntId) const IdErr = IDL.Obj({'idErr': OpEntId}) const Inventory = IDL.Obj({'produce_id': IDL.Nat, 'quantity': IDL.Nat}) -const OpEntId = IDL.Opt(EntId) -const ProducerId = IDL.Nat -const RegionId = IDL.Nat -const TruckTypeId = IDL.Nat -const UserId = IDL.Nat -const UserInfo = - IDL.Obj({'id': UserId, 'region': RegionId, 'user_name': IDL.Text, - 'public_key': IDL.Text, 'description': IDL.Text, - 'produceId': IDL.Opt(ProducerId)}) -const list = IDL.Arr(IDL.Nat) -const t = IDL.Arr(IDL.Nat8) -const t1 = t -const t2 = UserId const S = new IDL.ActorInterface({ 'f': IDL.message(IDL.Obj({'0': t, '1': t1, '2': t2}), diff --git a/test/idl/ok/import1.js.ok b/test/idl/ok/import1.js.ok index d55f0f16617..25ed302284f 100644 --- a/test/idl/ok/import1.js.ok +++ b/test/idl/ok/import1.js.ok @@ -1,17 +1,6 @@ -const EntId = - IDL.Obj({'region': RegionId, 'user': UserId, 'truckType': TruckTypeId}) -const IdErr = IDL.Obj({'idErr': OpEntId}) -const Inventory = IDL.Obj({'produce_id': IDL.Nat, 'quantity': IDL.Nat}) -const OpEntId = IDL.Opt(EntId) -const ProducerId = IDL.Nat -const RegionId = IDL.Nat -const TruckTypeId = IDL.Nat -const UserId = IDL.Nat -const UserInfo = - IDL.Obj({'id': UserId, 'region': RegionId, 'user_name': IDL.Text, - 'public_key': IDL.Text, 'description': IDL.Text, - 'produceId': IDL.Opt(ProducerId)}) const t = IDL.Arr(IDL.Nat8) const t1 = t +const UserId = IDL.Nat const t2 = UserId - +const S = new IDL.ActorInterface({ + 'f': IDL.message(IDL.Obj({'0': t, '1': t1, '2': t2}), IDL.Obj({}))}) diff --git a/test/idl/ok/import3.js.ok b/test/idl/ok/import3.js.ok index a111f9b3033..6a3245c21f2 100644 --- a/test/idl/ok/import3.js.ok +++ b/test/idl/ok/import3.js.ok @@ -1,16 +1,17 @@ -const A = B -const B = IDL.Opt(A) -const list = IDL.Opt(node) -const node = IDL.Obj({'head': IDL.Nat, 'tail': list}) -const s = new IDL.ActorInterface({'f': t}) -const stream = - IDL.Opt( - IDL.Obj({'head': IDL.Nat, - 'next': IDL.message(IDL.Obj({}), IDL.Obj({'0': stream}))})) - +const B = IDL.Rec() +const list = IDL.Rec() +const s = IDL.Rec() +const tree = IDL.Rec() const t = IDL.message(IDL.Obj({'server': s}), IDL.Obj({})) +const node = IDL.Obj({'head': IDL.Nat, 'tail': list}) +const list = IDL.Opt(node) const tree = IDL.Variant({ 'branch': IDL.Obj({'val': IDL.Int, 'left': tree, 'right': tree}), 'leaf': IDL.Int}) +const A = B +const B = IDL.Opt(A) +const s = + new IDL.ActorInterface({'f': t, + 'g': IDL.message(IDL.Obj({'0': list}), IDL.Obj({'1': tree, '0': B}))}) const S = s diff --git a/test/idl/ok/px.js.ok b/test/idl/ok/px.js.ok index 4970f19a8b4..95bc9c30625 100644 --- a/test/idl/ok/px.js.ok +++ b/test/idl/ok/px.js.ok @@ -1,16 +1,17 @@ -const EntId = - IDL.Obj({'region': RegionId, 'user': UserId, 'truckType': TruckTypeId}) -const IdErr = IDL.Obj({'idErr': OpEntId}) -const Inventory = IDL.Obj({'produce_id': IDL.Nat, 'quantity': IDL.Nat}) -const OpEntId = IDL.Opt(EntId) -const ProducerId = IDL.Nat -const RegionId = IDL.Nat -const TruckTypeId = IDL.Nat const UserId = IDL.Nat +const RegionId = IDL.Nat +const ProducerId = IDL.Nat const UserInfo = IDL.Obj({'id': UserId, 'region': RegionId, 'user_name': IDL.Text, 'public_key': IDL.Text, 'description': IDL.Text, 'produceId': IDL.Opt(ProducerId)}) +const Inventory = IDL.Obj({'produce_id': IDL.Nat, 'quantity': IDL.Nat}) +const TruckTypeId = IDL.Nat +const EntId = + IDL.Obj({'region': RegionId, 'user': UserId, 'truckType': TruckTypeId}) +const OpEntId = IDL.Opt(EntId) +const IdErr = IDL.Obj({'idErr': OpEntId}) const ProduceExchange = new IDL.ActorInterface({ 'getInventory': - IDL.message(IDL.Obj({'producer_id': IDL.Nat}), IDL.Obj({'0': Inventory}))}) + IDL.message(IDL.Obj({'producer_id': IDL.Nat, '3667444713': UserInfo}), + IDL.Obj({'0': Inventory, '1': IdErr}))}) diff --git a/test/idl/ok/recursion.js.ok b/test/idl/ok/recursion.js.ok index caab4905e37..7578c4d6a9f 100644 --- a/test/idl/ok/recursion.js.ok +++ b/test/idl/ok/recursion.js.ok @@ -1,16 +1,17 @@ -const A = B -const B = IDL.Opt(A) -const list = IDL.Opt(node) -const node = IDL.Obj({'head': IDL.Nat, 'tail': list}) -const s = new IDL.ActorInterface({'f': t}) -const stream = - IDL.Opt( - IDL.Obj({'head': IDL.Nat, - 'next': IDL.message(IDL.Obj({}), IDL.Obj({'0': stream}))})) - +const B = IDL.Rec() +const list = IDL.Rec() +const s = IDL.Rec() +const tree = IDL.Rec() const t = IDL.message(IDL.Obj({'server': s}), IDL.Obj({})) +const node = IDL.Obj({'head': IDL.Nat, 'tail': list}) +const list = IDL.Opt(node) const tree = IDL.Variant({ 'branch': IDL.Obj({'val': IDL.Int, 'left': tree, 'right': tree}), 'leaf': IDL.Int}) +const A = B +const B = IDL.Opt(A) +const s = + new IDL.ActorInterface({'f': t, + 'g': IDL.message(IDL.Obj({'0': list}), IDL.Obj({'1': tree, '0': B}))}) const A = s diff --git a/test/idl/ok/test.js.ok b/test/idl/ok/test.js.ok index 31376351dc4..8e2a1f185cf 100644 --- a/test/idl/ok/test.js.ok +++ b/test/idl/ok/test.js.ok @@ -1,4 +1,6 @@ +const my_type = IDL.Nat const B = my_type +const message = IDL.Obj({'25': B, '26': IDL.None, 'name': IDL.Text}) const broker = new IDL.ActorInterface({ 'find': @@ -9,8 +11,6 @@ const broker = 'current': IDL.message(IDL.Obj({}), IDL.Obj({'0': IDL.Nat}))}) })) }) -const message = IDL.Obj({'25': B, '26': IDL.None, 'name': IDL.Text}) -const my_type = IDL.Nat const server = new IDL.ActorInterface({ 'addUser': IDL.message(IDL.Obj({'name': IDL.Text, 'age': IDL.Nat8}), @@ -18,4 +18,5 @@ const server = new IDL.ActorInterface({ 'userName': IDL.message(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({'0': IDL.Text})), 'userAge': IDL.message(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({'0': IDL.Nat8})), - 'deleteUser': IDL.message(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({}))}) + 'deleteUser': IDL.message(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({})), + 'f': IDL.message(IDL.Obj({'0': message}), IDL.Obj({'0': broker}))}) diff --git a/test/idl/px.did b/test/idl/px.did index 030d1c44bf1..3f9db345cf8 100644 --- a/test/idl/px.did +++ b/test/idl/px.did @@ -26,6 +26,6 @@ type Inventory = record { } service ProduceExchange { - getInventory: (producer_id: nat) -> (Inventory) pure; + getInventory: (producer_id: nat, UserInfo) -> (Inventory, IdErr) pure; } diff --git a/test/idl/recursion.did b/test/idl/recursion.did index 6a573e21033..3f9a17dd09a 100644 --- a/test/idl/recursion.did +++ b/test/idl/recursion.did @@ -6,7 +6,7 @@ type tree = variant { leaf : int; branch : record { left : tree; val : int; right : tree }; }; -type s = service { f : t }; +type s = service { f : t; g : (list) -> (B,tree); }; type t = func (server : s) -> (); type stream = opt record {head:nat; next:func ()-> (stream) pure}; diff --git a/test/idl/test.did b/test/idl/test.did index 473957316eb..42e9fbdd293 100644 --- a/test/idl/test.did +++ b/test/idl/test.did @@ -16,5 +16,6 @@ service server { userName : (id : nat64) -> (text) pure; userAge : (id : nat64) -> (nat8) pure; deleteUser : (id : nat64) -> () oneway; + f : (message) -> (broker); } From 0429d6008f39934f94a50810281db8df32348ca0 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Wed, 10 Jul 2019 15:52:38 -0700 Subject: [PATCH 0250/1176] use fill for recursion point --- src/idllib/compile_js.ml | 32 +++++++++++++++++++++++++------- test/idl/ok/actor.js.ok | 2 +- test/idl/ok/cyclic.js.ok | 2 +- test/idl/ok/import3.js.ok | 20 ++++++++++++++------ test/idl/ok/recursion.js.ok | 20 ++++++++++++++------ test/idl/recursion.did | 2 +- 6 files changed, 56 insertions(+), 22 deletions(-) diff --git a/src/idllib/compile_js.ml b/src/idllib/compile_js.ml index 0ff4b268c03..669489f9779 100644 --- a/src/idllib/compile_js.ml +++ b/src/idllib/compile_js.ml @@ -6,6 +6,12 @@ open Source module Env = Typing.Env module TS = Set.Make(String) +type typ_info = { + var : string; + typ : typ; + is_rec : bool; + } + (* Gather type definitions from actor and sort the definitions in topological order *) let chase_env env actor = let new_env = ref [] in @@ -18,7 +24,7 @@ let chase_env env actor = seen := TS.add id.it !seen; let t = Env.find id.it env in chase t; - new_env := (id.it, t) :: !new_env; + new_env := {var = id.it; typ = t; is_rec = false} :: !new_env; end | ServT ms -> List.iter (fun m -> chase m.it.meth) ms | OptT t -> chase t @@ -57,7 +63,7 @@ let infer_rec env_list = and go_fields fs = List.iter (fun (f:typ_field) -> go f.it.typ) fs in - List.iter (fun (x,t) -> go t; seen := TS.add x !seen) env_list; + List.iter (fun {var;typ;_} -> go typ; seen := TS.add var !seen) env_list; !recs let str ppf s = pp_print_string ppf s; pp_print_cut ppf () @@ -136,12 +142,20 @@ and pp_meth ppf meth = pp_typ ppf meth.it.meth; pp_close_box ppf () -let pp_dec ppf (x,t) = +let pp_dec ppf {var;typ;is_rec} = pp_open_hovbox ppf 1; - kwd ppf "const"; - kwd ppf x; - kwd ppf "="; - pp_typ ppf t; + if is_rec then begin + str ppf var; + str ppf ".fill("; + pp_typ ppf typ; + str ppf ")"; + end + else begin + kwd ppf "const"; + kwd ppf var; + kwd ppf "="; + pp_typ ppf typ; + end; pp_close_box ppf (); pp_print_cut ppf () @@ -174,6 +188,10 @@ let pp_prog ppf env prog = | Some actor -> let env_list = chase_env env actor in let recs = infer_rec env_list in + let env_list = + List.map (fun (e:typ_info) -> + if TS.mem e.var recs then {e with is_rec = true} else e) + env_list in pp_open_vbox ppf 0; TS.iter (pp_rec ppf) recs; List.iter (pp_dec ppf) env_list; diff --git a/test/idl/ok/actor.js.ok b/test/idl/ok/actor.js.ok index 9c3f9459833..1e768735ea6 100644 --- a/test/idl/ok/actor.js.ok +++ b/test/idl/ok/actor.js.ok @@ -2,7 +2,7 @@ const o = IDL.Rec() const f = IDL.message(IDL.Obj({'0': IDL.Int8}), IDL.Obj({'0': IDL.Int8})) const h = IDL.message(IDL.Obj({'0': f}), IDL.Obj({'0': f})) const g = f -const o = IDL.Opt(o) +o.fill(IDL.Opt(o)) const g = new IDL.ActorInterface({ 'f': IDL.message(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': h})), 'g': f, 'h': g, 'o': IDL.message(IDL.Obj({'0': o}), IDL.Obj({'0': o}))}) diff --git a/test/idl/ok/cyclic.js.ok b/test/idl/ok/cyclic.js.ok index d5a4673a1ec..2926b862188 100644 --- a/test/idl/ok/cyclic.js.ok +++ b/test/idl/ok/cyclic.js.ok @@ -1,7 +1,7 @@ const A = IDL.Rec() const C = A const B = IDL.Opt(C) -const A = IDL.Opt(B) +A.fill(IDL.Opt(B)) const Z = A const Y = Z const X = Y diff --git a/test/idl/ok/import3.js.ok b/test/idl/ok/import3.js.ok index 6a3245c21f2..b88df20df65 100644 --- a/test/idl/ok/import3.js.ok +++ b/test/idl/ok/import3.js.ok @@ -1,17 +1,25 @@ const B = IDL.Rec() const list = IDL.Rec() const s = IDL.Rec() +const stream = IDL.Rec() const tree = IDL.Rec() const t = IDL.message(IDL.Obj({'server': s}), IDL.Obj({})) const node = IDL.Obj({'head': IDL.Nat, 'tail': list}) -const list = IDL.Opt(node) -const tree = +list.fill(IDL.Opt(node)) +stream.fill( + IDL.Opt( + IDL.Obj({'head': IDL.Nat, + 'next': IDL.message(IDL.Obj({}), IDL.Obj({'0': stream}))})) + ) +tree.fill( IDL.Variant({ 'branch': IDL.Obj({'val': IDL.Int, 'left': tree, 'right': tree}), - 'leaf': IDL.Int}) + 'leaf': IDL.Int})) const A = B -const B = IDL.Opt(A) -const s = +B.fill(IDL.Opt(A)) +s.fill( new IDL.ActorInterface({'f': t, - 'g': IDL.message(IDL.Obj({'0': list}), IDL.Obj({'1': tree, '0': B}))}) + 'g': + IDL.message(IDL.Obj({'0': list}), + IDL.Obj({'2': stream, '1': tree, '0': B}))})) const S = s diff --git a/test/idl/ok/recursion.js.ok b/test/idl/ok/recursion.js.ok index 7578c4d6a9f..e89ecb02db0 100644 --- a/test/idl/ok/recursion.js.ok +++ b/test/idl/ok/recursion.js.ok @@ -1,17 +1,25 @@ const B = IDL.Rec() const list = IDL.Rec() const s = IDL.Rec() +const stream = IDL.Rec() const tree = IDL.Rec() const t = IDL.message(IDL.Obj({'server': s}), IDL.Obj({})) const node = IDL.Obj({'head': IDL.Nat, 'tail': list}) -const list = IDL.Opt(node) -const tree = +list.fill(IDL.Opt(node)) +stream.fill( + IDL.Opt( + IDL.Obj({'head': IDL.Nat, + 'next': IDL.message(IDL.Obj({}), IDL.Obj({'0': stream}))})) + ) +tree.fill( IDL.Variant({ 'branch': IDL.Obj({'val': IDL.Int, 'left': tree, 'right': tree}), - 'leaf': IDL.Int}) + 'leaf': IDL.Int})) const A = B -const B = IDL.Opt(A) -const s = +B.fill(IDL.Opt(A)) +s.fill( new IDL.ActorInterface({'f': t, - 'g': IDL.message(IDL.Obj({'0': list}), IDL.Obj({'1': tree, '0': B}))}) + 'g': + IDL.message(IDL.Obj({'0': list}), + IDL.Obj({'2': stream, '1': tree, '0': B}))})) const A = s diff --git a/test/idl/recursion.did b/test/idl/recursion.did index 3f9a17dd09a..5efc5f72137 100644 --- a/test/idl/recursion.did +++ b/test/idl/recursion.did @@ -6,7 +6,7 @@ type tree = variant { leaf : int; branch : record { left : tree; val : int; right : tree }; }; -type s = service { f : t; g : (list) -> (B,tree); }; +type s = service { f : t; g : (list) -> (B,tree,stream); }; type t = func (server : s) -> (); type stream = opt record {head:nat; next:func ()-> (stream) pure}; From 0266bb5f1797ae9d861aaacdeb5a7871246a3a2c Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 11 Jul 2019 11:38:45 -0700 Subject: [PATCH 0251/1176] fix FS resolution for package URLs; adjust URL syntax back to 'as:' --- src/pipeline/resolve_import.ml | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/pipeline/resolve_import.ml b/src/pipeline/resolve_import.ml index 52ae3b29406..640e839866c 100644 --- a/src/pipeline/resolve_import.ml +++ b/src/pipeline/resolve_import.ml @@ -54,15 +54,15 @@ let match_package_name (f: string) : (string * string) option = loop dir (Filename.concat base path_accum) end in - if String.length f < 5 then None else + if String.length f < 3 then None else let (prefix, suffix) = ( - String.sub f 0 5, - String.sub f 5 ((String.length f) - 5) + String.sub f 0 3, + String.sub f 3 ((String.length f) - 3) ) in match prefix with - | "as://" -> loop suffix "" - | _ -> None + | "as:" -> loop suffix "" + | _ -> None (* using env, resolve import strings of the form "as:package-name/mod1/mod2/item" into the triple ("package-name", "package-url", "mod1/mod2/item") when the package name is defined. @@ -106,18 +106,13 @@ let resolve_import_string env region (f: string) (fp: string ref) = } (* compare to the filesystem semantics of function `resolve_import_string`: - the two import-string to filesystem-path resolution semantics agree for now, - but other API details and usage are distinct. + the import-string to filesystem-path resolution semantics are related, but distinct. *) let resolve_package_url (msgs:Diag.msg_store) (base:filepath) (pname:string) (f: string) : string option = let f = if Filename.is_relative f then Filename.concat base f else f in - let f = - if Sys.file_exists f && Sys.is_directory f - then Filename.concat f "lib.as" - else f in let f = File_path.normalise f in if Sys.file_exists f then Some f From 2588d62d1311140e56f308b1a74348fff8167638 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 11 Jul 2019 14:45:16 -0700 Subject: [PATCH 0252/1176] bug fix; can import 'as:std/list' via --package std ... --- src/pipeline/resolve_import.ml | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/src/pipeline/resolve_import.ml b/src/pipeline/resolve_import.ml index 640e839866c..5524ff5037d 100644 --- a/src/pipeline/resolve_import.ml +++ b/src/pipeline/resolve_import.ml @@ -39,20 +39,31 @@ open Syntax open Source (* match `f` against the URL pattern 'as://package-name/path', - optionally returning the package-name and path components as a pair of strings. *) + optionally returning the package-name and path components as a pair of strings. + + e.g., + match_package_name "as:std/list" = Some("std", "list") + match_package_name "as:std/foo/bar" = Some("std", "foo/bar") + match_package_name "as:foo/bar" = Some("foo", "bar") + + match_package_name "as:" = None + match_package_name "as:std" = None + match_package_name "std/foo" = None + match_package_name "std/foo/bar" = None + +*) let match_package_name (f: string) : (string * string) option = let rec loop (f: string) (path_accum:string) : (string * string) option = - (* loop recursively until we get to a 'self-loop', indicated by dirname '.' ; - in each iteration, we use function pair (dirname, basename) - to decompose the filename. - *) let (dir, base) = (Filename.dirname f, Filename.basename f) in match dir with - | "." -> Some (f, path_accum) - | _ -> begin - assert ((Filename.concat dir base) = f) ; - loop dir (Filename.concat base path_accum) - end + | "." -> if path_accum = "" then None else Some (f, path_accum) + | _ -> + let path_accum = + match path_accum with + | "" -> base + | _ -> Filename.concat base path_accum + in + loop dir path_accum in if String.length f < 3 then None else let (prefix, suffix) = ( @@ -81,7 +92,7 @@ let resolve_import_string env region (f: string) (fp: string ref) = let f = match resolve_package env f with | None -> f - | Some (_, url, path) -> Filename.concat url path + | Some (_pname, url, path) -> Filename.concat url path in let f = if Filename.is_relative f From 18f07aad9e892d7413e37cbbcb3357ebe19cbe72 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Fri, 12 Jul 2019 20:47:30 +0200 Subject: [PATCH 0253/1176] send negative Int* (#564) --- test/run-dfinity/data-params.as | 3 ++- test/run-dfinity/ok/data-params.dvm-run.ok | 7 ++++--- test/run-dfinity/ok/data-params.run-ir.ok | 7 ++++--- test/run-dfinity/ok/data-params.run-low.ok | 7 ++++--- test/run-dfinity/ok/data-params.run.ok | 7 ++++--- 5 files changed, 18 insertions(+), 13 deletions(-) diff --git a/test/run-dfinity/data-params.as b/test/run-dfinity/data-params.as index b2c1eadbcfd..42c52076183 100644 --- a/test/run-dfinity/data-params.as +++ b/test/run-dfinity/data-params.as @@ -112,7 +112,8 @@ a.inci(-20000000000000); a.incwords(1,2,3,4); a.incwords(-1,-2,-3,-4); a.incnats(1,2,3,4); -a.incints(1,2,3,4);//(-1,-2,-3,-4); +a.incints(1,2,3,4); +a.incints(-1,-2,-3,-4); a.incn(2**100); a.inci(2**100); a.inci(-(2**101)); diff --git a/test/run-dfinity/ok/data-params.dvm-run.ok b/test/run-dfinity/ok/data-params.dvm-run.ok index f32875d2100..ad92e1130d0 100644 --- a/test/run-dfinity/ok/data-params.dvm-run.ok +++ b/test/run-dfinity/ok/data-params.dvm-run.ok @@ -23,6 +23,7 @@ Foo2: 1006211 1006211 1006221 1006231 -1267650600228229401496704211607 -2535301200456458802993407416983 -1006231 +1006221 +1267650600228229401496704211597 +2535301200456458802993407416973 +1006221 diff --git a/test/run-dfinity/ok/data-params.run-ir.ok b/test/run-dfinity/ok/data-params.run-ir.ok index 508800c183f..d30b0888488 100644 --- a/test/run-dfinity/ok/data-params.run-ir.ok +++ b/test/run-dfinity/ok/data-params.run-ir.ok @@ -27,6 +27,7 @@ Foo2: 1006211 1006211 1006221 1006231 -1267650600228229401496704211607 -2535301200456458802993407416983 -1006231 +1006221 +1267650600228229401496704211597 +2535301200456458802993407416973 +1006221 diff --git a/test/run-dfinity/ok/data-params.run-low.ok b/test/run-dfinity/ok/data-params.run-low.ok index 508800c183f..d30b0888488 100644 --- a/test/run-dfinity/ok/data-params.run-low.ok +++ b/test/run-dfinity/ok/data-params.run-low.ok @@ -27,6 +27,7 @@ Foo2: 1006211 1006211 1006221 1006231 -1267650600228229401496704211607 -2535301200456458802993407416983 -1006231 +1006221 +1267650600228229401496704211597 +2535301200456458802993407416973 +1006221 diff --git a/test/run-dfinity/ok/data-params.run.ok b/test/run-dfinity/ok/data-params.run.ok index 508800c183f..d30b0888488 100644 --- a/test/run-dfinity/ok/data-params.run.ok +++ b/test/run-dfinity/ok/data-params.run.ok @@ -27,6 +27,7 @@ Foo2: 1006211 1006211 1006221 1006231 -1267650600228229401496704211607 -2535301200456458802993407416983 -1006231 +1006221 +1267650600228229401496704211597 +2535301200456458802993407416973 +1006221 From a720064d30a565439e785bb6c03222f98b1ee805 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Fri, 12 Jul 2019 14:39:14 -0700 Subject: [PATCH 0254/1176] typo --- src/idllib/compile_js.ml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/idllib/compile_js.ml b/src/idllib/compile_js.ml index 669489f9779..67d47cb082d 100644 --- a/src/idllib/compile_js.ml +++ b/src/idllib/compile_js.ml @@ -107,7 +107,7 @@ let rec pp_typ ppf t = | OptT t -> str ppf "IDL.Opt("; pp_typ ppf t; str ppf ")"; | VariantT ts -> str ppf "IDL.Variant({"; concat ppf pp_field "," ts; str ppf "})"; | FuncT (ms, t1, t2) -> - str ppf "IDL.message("; + str ppf "IDL.Message("; pp_fields ppf t1; kwd ppf ","; pp_fields ppf t2; @@ -182,6 +182,11 @@ let pp_actor ppf actor = ); pp_close_box ppf () +let pp_header ppf () = + pp_open_vbox ppf 0; + str ppf "const IDL = require('./IDL')"; + pp_close_box ppf () + let pp_prog ppf env prog = match prog.it.actor with | None -> () @@ -192,6 +197,7 @@ let pp_prog ppf env prog = List.map (fun (e:typ_info) -> if TS.mem e.var recs then {e with is_rec = true} else e) env_list in + pp_header ppf (); pp_open_vbox ppf 0; TS.iter (pp_rec ppf) recs; List.iter (pp_dec ppf) env_list; From cae0987078e6fb7c0b0f404bdb35276d525377cc Mon Sep 17 00:00:00 2001 From: Christoph Hegemann Date: Mon, 15 Jul 2019 10:10:21 +0200 Subject: [PATCH 0255/1176] Adds various functions to lib.ml in an attempt to get rid of base (#562) * adds various functions to lib/ in an attempt to get rid of base Still need to worry about the string prefix and suffix handling * address review * use exception handling to speed up list equality * trigger ci-build * adds prefix/suffix functions for strings gets rid of the remaining base usages * use functions from `lib` rather than reimplementing them * simpler implementation for is_some --- default.nix | 1 - src/as_interpreter/interpret.ml | 2 +- src/codegen/instrList.ml | 9 ++----- src/ir_interpreter/interpret_ir.ml | 2 +- src/languageServer/completion.ml | 8 +++--- src/languageServer/completion_test.ml | 26 +++++++++--------- src/languageServer/dune | 2 +- src/languageServer/languageServer.ml | 6 ++--- src/languageServer/vfs.ml | 2 +- src/lib/lib.ml | 38 +++++++++++++++++++++++++-- src/lib/lib.mli | 9 ++++++- src/pipeline/dune | 1 - src/pipeline/file_path.ml | 8 +++--- src/pipeline/file_path_test.ml | 23 ++++++++-------- src/wasm-exts/customModuleEncode.ml | 2 +- 15 files changed, 87 insertions(+), 52 deletions(-) diff --git a/default.nix b/default.nix index 27debab37f2..f47012d706b 100644 --- a/default.nix +++ b/default.nix @@ -42,7 +42,6 @@ let commonBuildInputs = [ nixpkgs.ocaml nixpkgs.dune nixpkgs.ocamlPackages.atdgen - nixpkgs.ocamlPackages.base nixpkgs.ocamlPackages.findlib nixpkgs.ocamlPackages.menhir nixpkgs.ocamlPackages.num diff --git a/src/as_interpreter/interpret.ml b/src/as_interpreter/interpret.ml index 6bee8d66092..21027eefd09 100644 --- a/src/as_interpreter/interpret.ml +++ b/src/as_interpreter/interpret.ml @@ -737,7 +737,7 @@ and interpret_exp_fields env s fields ve (k : V.value V.cont) = and interpret_block env decs ro (k : V.value V.cont) = let ve = declare_decs decs V.Env.empty in - Lib.Option.app (fun r -> r := ve) ro; + Lib.Option.iter (fun r -> r := ve) ro; interpret_decs (adjoin_vals env ve) decs k diff --git a/src/codegen/instrList.ml b/src/codegen/instrList.ml index ec67ac9a8e2..1de783e74a8 100644 --- a/src/codegen/instrList.ml +++ b/src/codegen/instrList.ml @@ -19,11 +19,6 @@ let combine_shifts const op = function else None | _ -> None -module Option = struct - let is_some = function None -> false | _ -> true - let get = function None -> assert false | Some x -> x -end - (* Some simple peephole optimizations, to make the output code look less stupid *) (* This uses a zipper.*) let optimize : instr list -> instr list = fun is -> @@ -52,8 +47,8 @@ let optimize : instr list -> instr list = fun is -> (* Constant shifts can be combined *) | {it = Binary (I32 I32Op.(Shl|ShrS|ShrU) as opl); _} :: {it = Const cl; _} :: l', ({it = Const cr; _} as const) :: ({it = Binary opr; _} as op) :: r' - when Option.is_some (combine_shifts const op (opl, cl, opr, cr.it)) -> - go l' (Option.get (combine_shifts const op (opl, cl, opr, cr.it)) @ r') + when Lib.Option.is_some (combine_shifts const op (opl, cl, opr, cr.it)) -> + go l' (Lib.Option.value (combine_shifts const op (opl, cl, opr, cr.it)) @ r') (* Null shifts can be eliminated *) | l', {it = Const {it = I32 0l; _}; _} :: {it = Binary (I32 I32Op.(Shl|ShrS|ShrU)); _} :: r' -> go l' r' diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index f544fea0efd..9c735b3832f 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -613,7 +613,7 @@ and match_pat_fields pfs vs ve : val_env option = and interpret_block env ro decs exp k = let ve = declare_decs decs V.Env.empty in - Lib.Option.app (fun r -> r := ve) ro; + Lib.Option.iter (fun r -> r := ve) ro; let env' = adjoin_vals env ve in interpret_decs env' decs (fun _ -> interpret_exp env' exp k) diff --git a/src/languageServer/completion.ml b/src/languageServer/completion.ml index e39e3c3281c..82da606c281 100644 --- a/src/languageServer/completion.ml +++ b/src/languageServer/completion.ml @@ -51,7 +51,9 @@ let make_index (): completion_index = (fun path ty acc -> Index.add path - (ty |> read_single_module_lib |> Base.Option.value ~default:[]) + (ty + |> read_single_module_lib + |> Lib.Fun.flip Lib.Option.get []) acc) scope.Scope.lib_env Index.empty @@ -71,7 +73,7 @@ let import_relative_to_project_root root module_path dependency = | Some root_to_module -> root_to_module |> Filename.dirname - |> Base.Fn.flip Filename.concat dependency + |> Lib.Fun.flip Filename.concat dependency |> Pipeline__.File_path.normalise |> Lib.Option.some @@ -148,7 +150,7 @@ let completions (* index *) logger project_root file_path file_contents line col let index_keys = Index.bindings index |> List.map fst - |> string_of_list Base.Fn.id in + |> string_of_list Lib.Fun.id in match module_path with | Some mp -> (match Index.find_opt (snd mp) index with diff --git a/src/languageServer/completion_test.ml b/src/languageServer/completion_test.ml index aee2ac0b4c8..8b404956abe 100644 --- a/src/languageServer/completion_test.ml +++ b/src/languageServer/completion_test.ml @@ -1,6 +1,6 @@ let extract_cursor input = let cursor_pos = ref (0, 0) in - Base.String.split_lines input + String.split_on_char '\n' input |> List.mapi (fun line_num line -> match String.index_opt line '|' with @@ -20,7 +20,7 @@ let prefix_test_case file expected = let (file, (line, column)) = extract_cursor file in let prefix = Completion.find_completion_prefix dummy_logger file line column in - Base.Option.equal String.equal prefix expected + Lib.Option.equal String.equal prefix expected let import_relative_test_case root module_path import expected = let actual = @@ -28,14 +28,12 @@ let import_relative_test_case root module_path import expected = let show = function | None -> "None" | Some s -> "Some " ^ s in - if Base.Option.equal Base.String.equal actual expected - then true - else - (Printf.printf - "\nExpected: %s\nActual: %s\n" - (show expected) - (show actual); - false) + Lib.Option.equal String.equal actual expected || + (Printf.printf + "\nExpected: %s\nActual: %s\n" + (show expected) + (show actual); + false) let parse_module_header_test_case project_root current_file file expected = let actual = @@ -43,11 +41,11 @@ let parse_module_header_test_case project_root current_file file expected = project_root current_file file in let display_result (alias, path) = Printf.sprintf "%s => \"%s\"" alias path in - let result = Base.List.equal + let result = Lib.List.equal + (fun (x, y) (x', y') -> + String.equal x x' && String.equal y y') actual - expected - ~equal:(fun (x, y) (x', y') -> - String.equal x x' && String.equal y y' ) in + expected in if not result then Printf.printf "\nExpected: %s\nActual: %s" diff --git a/src/languageServer/dune b/src/languageServer/dune index 8f82a820892..b9a31912258 100644 --- a/src/languageServer/dune +++ b/src/languageServer/dune @@ -1,6 +1,6 @@ (library (name languageServer) - (libraries base lang_utils lsp pipeline) + (libraries lib lang_utils lsp pipeline) (inline_tests) (preprocess (pps ppx_inline_test)) (flags (:standard -w -48)) diff --git a/src/languageServer/languageServer.ml b/src/languageServer/languageServer.ml index ea8df94b204..fa70c695ad2 100644 --- a/src/languageServer/languageServer.ml +++ b/src/languageServer/languageServer.ml @@ -90,13 +90,13 @@ let diagnostics_of_message (msg : Diag.message) : Lsp_t.diagnostic = Lsp_t. let file_uri_prefix = "file://" ^ Sys.getcwd () ^ "/" let file_from_uri logger uri = - match Base.String.chop_prefix ~prefix:file_uri_prefix uri with + match Lib.String.chop_prefix file_uri_prefix uri with | Some file -> file | None -> let _ = logger "error" ("Failed to strip filename from: " ^ uri) in uri let abs_file_from_uri logger uri = - match Base.String.chop_prefix ~prefix:"file://" uri with + match Lib.String.chop_prefix "file://" uri with | Some file -> file | None -> let _ = logger "error" ("Failed to strip filename from: " ^ uri) in @@ -180,7 +180,7 @@ let start () = let msgs = match result with | Error msgs' -> msgs' | Ok (_, msgs') -> msgs' in - Base.Option.iter !client_capabilities ~f:(fun _ -> + Lib.Fun.flip Lib.Option.iter !client_capabilities (fun _ -> (* TODO: determine if the client accepts diagnostics with related info *) (* let textDocument = capabilities.client_capabilities_textDocument in * let send_related_information = textDocument.publish_diagnostics.relatedInformation in *) diff --git a/src/languageServer/vfs.ml b/src/languageServer/vfs.ml index e95dd3953a6..f98b9caf3fd 100644 --- a/src/languageServer/vfs.ml +++ b/src/languageServer/vfs.ml @@ -31,7 +31,7 @@ let update_file did_change_params = did_change_params.Lsp_t.text_document_did_change_params_contentChanges |> (* TODO(Christoph): This needs to change once we allow incremental file updates*) - Base.Fn.flip List.nth 0 + Lib.Fun.flip List.nth 0 in let new_content = change_event.Lsp_t.text_document_content_change_event_text in let uri = diff --git a/src/lib/lib.ml b/src/lib/lib.ml index 6e32589b811..b4ac557caa3 100644 --- a/src/lib/lib.ml +++ b/src/lib/lib.ml @@ -1,6 +1,7 @@ module Fun = struct let id x = x + let flip f x y = f y x let curry f x y = f (x, y) let uncurry f (x, y) = f x y @@ -44,7 +45,7 @@ struct else if i1 >= 0l && i2 < 0l then -1 else Int32.compare i1 i2 end - + module String = struct let implode cs = @@ -78,10 +79,33 @@ struct Some i else find_from_opt f s (i + 1) + + let chop_prefix prefix s = + let prefix_len = String.length prefix in + let s_len = String.length s in + if s_len < prefix_len then + None + else if String.sub s 0 prefix_len = prefix then + Some (String.sub s prefix_len (s_len - prefix_len)) + else + None + + let chop_suffix suffix s = + let suffix_len = String.length suffix in + let s_len = String.length s in + if s_len < suffix_len then + None + else if String.sub s (s_len - suffix_len) suffix_len = suffix then + Some (String.sub s 0 (s_len - suffix_len)) + else + None end module List = struct + let equal p xs ys = + try List.for_all2 p xs ys with _ -> false + let rec make n x = make' n x [] and make' n x xs = if n = 0 then xs else make' (n - 1) x (x::xs) @@ -247,6 +271,12 @@ end module Option = struct + let equal p x y = + match x, y with + | Some x', Some y' -> p x' y' + | None, None -> true + | _, _ -> false + let get o x = match o with | Some y -> y @@ -260,7 +290,7 @@ struct | Some x -> Some (f x) | None -> None - let app f = function + let iter f = function | Some x -> f x | None -> () @@ -269,6 +299,10 @@ struct let bind x f = match x with | Some x -> f x | None -> None + + let is_some x = x <> None + + let is_none x = x = None end module Promise = diff --git a/src/lib/lib.mli b/src/lib/lib.mli index ed0c1bd169f..f8adfc33fdf 100644 --- a/src/lib/lib.mli +++ b/src/lib/lib.mli @@ -3,6 +3,7 @@ module Fun : sig val id : 'a -> 'a + val flip : ('a -> 'b -> 'c) -> 'b -> 'a -> 'c val curry : ('a * 'b -> 'c) -> ('a -> 'b -> 'c) val uncurry : ('a -> 'b -> 'c) -> ('a * 'b -> 'c) @@ -12,6 +13,7 @@ end module List : sig + val equal : ('a -> 'a -> bool) -> 'a list -> 'a list -> bool val make : int -> 'a -> 'a list val table : int -> (int -> 'a) -> 'a list val take : int -> 'a list -> 'a list (* raises Failure *) @@ -68,12 +70,15 @@ end module Option : sig + val equal : ('a -> 'a -> bool) -> 'a option -> 'a option -> bool val get : 'a option -> 'a -> 'a val value : 'a option -> 'a val map : ('a -> 'b) -> 'a option -> 'b option val some : 'a -> 'a option - val app : ('a -> unit) -> 'a option -> unit + val iter : ('a -> unit) -> 'a option -> unit val bind : 'a option -> ('a -> 'b option) -> 'b option + val is_some : 'a option -> bool + val is_none : 'a option -> bool end module Promise : @@ -122,4 +127,6 @@ sig val split : string -> char -> string list val breakup : string -> int -> string list val find_from_opt : (char -> bool) -> string -> int -> int option + val chop_prefix : string -> string -> string option + val chop_suffix : string -> string -> string option end diff --git a/src/pipeline/dune b/src/pipeline/dune index eab27a21a0b..68bd990da2f 100644 --- a/src/pipeline/dune +++ b/src/pipeline/dune @@ -2,7 +2,6 @@ (name pipeline) (libraries lib - base lang_utils as_def as_types diff --git a/src/pipeline/file_path.ml b/src/pipeline/file_path.ml index 44eaa8ee54a..b77585c12fe 100644 --- a/src/pipeline/file_path.ml +++ b/src/pipeline/file_path.ml @@ -1,6 +1,6 @@ let normalise file_path = let has_trailing_slash = - Base.Option.is_some (Base.String.chop_suffix ~suffix:"/" file_path) in + Lib.Option.is_some (Lib.String.chop_suffix "/" file_path) in let has_leading_slash = not (Filename.is_relative file_path) in let acc = Stack.create () in Lib.String.split file_path '/' @@ -17,9 +17,9 @@ let normalise file_path = let prefix = if has_leading_slash then "/" else "" in prefix ^ (if has_trailing_slash then result - else Base.String.chop_suffix_exn ~suffix:"/" result) + else Lib.Option.value (Lib.String.chop_suffix "/" result)) let relative_to base path = - Base.String.chop_prefix - ~prefix:(normalise (base ^ "/")) + Lib.String.chop_prefix + (normalise (base ^ "/")) (normalise path) diff --git a/src/pipeline/file_path_test.ml b/src/pipeline/file_path_test.ml index 31aee54bb04..da2294f7e6e 100644 --- a/src/pipeline/file_path_test.ml +++ b/src/pipeline/file_path_test.ml @@ -1,22 +1,23 @@ let normalise_test_case input expected = let actual = File_path.normalise input in - if String.equal actual expected - then true - else (Printf.printf "\nExpected: %s\nActual: %s\n" expected actual; false) + String.equal actual expected || + (Printf.printf + "\nExpected: %s\nActual: %s\n" + expected + actual; + false) let relative_to_test_case root contained expected = let actual = File_path.relative_to root contained in let show = function | None -> "None" | Some s -> "Some " ^ s in - if Base.Option.equal Base.String.equal actual expected - then true - else - (Printf.printf - "\nExpected: %s\nActual: %s\n" - (show expected) - (show actual); - false) + Lib.Option.equal String.equal actual expected || + (Printf.printf + "\nExpected: %s\nActual: %s\n" + (show expected) + (show actual); + false) let%test "it removes leading `./` for relative paths" = normalise_test_case "./lib/foo" "lib/foo" diff --git a/src/wasm-exts/customModuleEncode.ml b/src/wasm-exts/customModuleEncode.ml index b779001c3a3..ecb2182d199 100644 --- a/src/wasm-exts/customModuleEncode.ml +++ b/src/wasm-exts/customModuleEncode.ml @@ -122,7 +122,7 @@ let encode (em : extended_module) = let string bs = len (String.length bs); put_string s bs let name n = string (Wasm.Utf8.encode n) let list f xs = List.iter f xs - let opt f xo = Lib.Option.app f xo + let opt f xo = Lib.Option.iter f xo let vec f xs = len (List.length xs); list f xs let veci f xs = len (List.length xs); List.iteri f xs From 7a014f5724c558ea22a41225b9305141483328cb Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Mon, 15 Jul 2019 11:59:27 +0200 Subject: [PATCH 0256/1176] Kill Shared type (#560) --- design/Syntax.md | 2 +- guide/as-slides.md | 15 +- guide/chat.as | 4 +- guide/guide.md | 80 +++++------ samples/app/server.as | 2 +- samples/app/types.as | 4 +- src/as_def/arrange.ml | 13 +- src/as_def/syntax.ml | 6 +- src/as_frontend/parser.mly | 37 ++--- src/as_frontend/typing.ml | 82 +++++------ src/as_interpreter/interpret.ml | 6 +- src/as_types/arrange_type.ml | 13 +- src/as_types/call_conv.ml | 12 +- src/as_types/call_conv.mli | 2 +- src/as_types/type.ml | 129 ++++++++---------- src/as_types/type.mli | 15 +- src/as_values/show.ml | 2 +- src/codegen/compile.ml | 43 +++--- src/ir_def/check_ir.ml | 32 +++-- src/ir_def/construct.ml | 2 +- src/ir_interpreter/interpret_ir.ml | 6 +- src/ir_passes/async.ml | 17 ++- src/ir_passes/serialization.ml | 13 +- src/ir_passes/show.ml | 2 +- src/lowering/desugar.ml | 4 +- src/prelude/prelude.ml | 26 ++-- .../examples/produce-exchange/profileActor.as | 2 +- .../examples/produce-exchange/serverActor.as | 16 +-- .../examples/produce-exchange/serverLang.as | 4 +- .../examples/produce-exchange/serverModel.as | 70 +++++----- .../examples/produce-exchange/serverTypes.as | 30 ++-- test/fail/abstract-msgs.as | 36 ++--- test/fail/argument-subtyping.as | 9 +- test/fail/asyncret1.as | 2 +- test/fail/objpat-infer.as | 12 +- test/fail/ok/abstract-msgs.tc.ok | 24 ++-- test/fail/ok/argument-subtyping.tc.ok | 8 +- test/fail/ok/asyncret1.tc.ok | 2 +- test/fail/ok/asyncret3.tc.ok | 2 +- test/fail/ok/issue103.tc.ok | 4 +- test/fail/ok/objpat-infer.tc.ok | 20 +-- test/fail/ok/pat-inconsistent.tc.ok | 4 +- .../fail/ok/use-before-define5.wasm.stderr.ok | 2 +- test/fail/pat-inconsistent.as | 2 +- test/repl/ok/type-lub-repl.stdout.ok | 6 +- test/run-dfinity/chatpp.as | 4 +- test/run-dfinity/data-params.as | 6 +- .../ok/counter-class.wasm.stderr.ok | 20 +-- test/run-dfinity/shared-object.as | 4 +- test/run-dfinity/transpose.as | 4 +- test/run/ok/issue442.run-ir.ok | 4 +- test/run/ok/issue442.run-low.ok | 4 +- test/run/ok/issue442.run.ok | 4 +- test/run/ok/issue442.tc.ok | 4 +- test/run/ok/issue442.wasm.stderr.ok | 4 +- test/run/ok/type-inference.run-ir.ok | 10 +- test/run/ok/type-inference.run-low.ok | 10 +- test/run/ok/type-inference.run.ok | 10 +- test/run/ok/type-inference.tc.ok | 10 +- test/run/ok/type-inference.wasm.stderr.ok | 10 +- test/run/type-definition.as | 4 +- test/run/type-lub.as | 4 +- 62 files changed, 439 insertions(+), 501 deletions(-) diff --git a/design/Syntax.md b/design/Syntax.md index 03eca90ad34..59a34a55ca7 100644 --- a/design/Syntax.md +++ b/design/Syntax.md @@ -113,7 +113,7 @@ Productions marked * probably deferred to later versions. expression let = immutable var (: )? = mutable - (new|object|actor|shared) ? =? { ;* } object + (new|object|actor) ? =? { ;* } object shared? func ? ? (: )? =? function type ? = type actor? class ? (: )? =? class diff --git a/guide/as-slides.md b/guide/as-slides.md index 136439d86ee..15172c23bac 100644 --- a/guide/as-slides.md +++ b/guide/as-slides.md @@ -108,9 +108,9 @@ structural record types, JS-like, fields can be mutable * `{var x : Int; color : Color}` -* `shared {x : Int; color: Color}` +* `{x : Int; color: Color}` -shared (think serializable) objects have immutable fields of sharable types. +objects with immutable fields of sharable types are sharable. ### Actor types @@ -188,7 +188,7 @@ AS distinguishes sharable types: - all primitive types are sharable (scalars + text) - any `shared` function type is sharable - - any `shared` object type is sharable + - an object type is sharable if it's fields are sharable and immutable - any `actor` type is sharable - `[T]` and `?T` are sharable if `T` is sharable. - `(T1,...,Tn)` is sharable if `T1`,..., `Tn` all sharable. @@ -197,8 +197,7 @@ AS distinguishes sharable types: ### ... Sharability - * `shared` functions must have sharable arguments and return `()` or async `T`, where `T` sharable -* `shared` object must have sharable fields +* `shared` functions must have sharable arguments and return `()` or async `T`, where `T` sharable * actor fields must re `shared` functions (actors \& shared functions serialized by *reference*, other types serialzed by *value*) @@ -224,12 +223,12 @@ AS distinguishes sharable types: * Unary & binary, arithmetic & logical operators - `- x`, `not b`, `a + b`, `a & b` ... -### (Shared) Objects +### (Sharable) Objects -* `shared` (think serializable) objects have immutable fields of sharable type: +* sharable (think serializable) objects have immutable fields of sharable type: ``` - shared { x = 0; color = Colors.Red } + { x = 0; color = Colors.Red } ``` * full `object`s can be mutable, stateful diff --git a/guide/chat.as b/guide/chat.as index 17bbaa09a81..f92c49e8bd8 100644 --- a/guide/chat.as +++ b/guide/chat.as @@ -5,7 +5,7 @@ type Post = shared Text -> (); actor Server = { private var clients : List = null; - private shared broadcast(message : Text) { + private shared func broadcast(message : Text) { var next = clients; loop { switch next { @@ -18,7 +18,7 @@ actor Server = { }; }; - subscribe(client : Client) : async Post { + func subscribe(client : Client) : async Post { let cs = new {head = client; var tail = clients}; clients := ?cs; return broadcast; diff --git a/guide/guide.md b/guide/guide.md index a2f32e923c9..19d39f2272b 100644 --- a/guide/guide.md +++ b/guide/guide.md @@ -328,7 +328,7 @@ Type expressions are used to specify the types of arguments, constraints (a.k.a ``` ::= type expressions ? constructor - (shared|actor)? { ;* } object + actor? { ;* } object [ var? ] array Null null type ? option @@ -436,18 +436,17 @@ representation is applied. ## Object types -`(shared|actor)? { ;* }` specifies an object type by listing its zero or more named *type fields*. +`actor? { ;* }` specifies an object type by listing its zero or more named *type fields*. Within an object type, the names of fields must be distinct. Object types that differ only in the ordering of the fields are equivalent. -The optional qualifier `shared` constrains the object's field to have *sharable* type. - -Messages (see below) always requires arguments of *sharable* (think *serializable*) type. - The optional qualifier `actor` constrains the object's fields to be *shared* functions (i.e. messages). +## Variant types + +TODO ## Array types @@ -496,10 +495,6 @@ No value has type `None`. As an empty type, `None` can be used to specify the impossible return value of an infinite loop or unconditional trap. -## Shared type - -Type `Shared` is the super-type of all types that can be transmitted between actors (i.e. sent or received) as the arguments or return values of `shared` functions. - ## Parenthesised type @@ -569,16 +564,15 @@ type parameter. ## Well-formed types -A type `T` is well-formed only if (recursively) its constituent types are well-formed,and: +A type `T` is well-formed only if (recursively) its constituent types are well-formed, and: -* if `T` is `async U` then `U <: Shared`, and -* if `T` is `shared < ... > V -> W` then `...` is empty, `U <: Shared` and - `W == ()` or `W == async W`, and +* if `T` is `async U` then `U` is shared, and +* if `T` is `shared < ... > V -> W` then `...` is empty, `U` is shared and + `W == ()` or `W == async W'`, and * if `T` is `C` where: * a declaration `type C = ...` is in scope, and * `Ti <: Ui[ T0/X0, ..., Tn/Xn ]`, for each `0 <= i <= n`. * if `T` is `actor { ... }` then all fields in `...` are immutable and have `shared` function type. -* if `T` is `shared { ... }` then all fields in `...` are immutable and have a type that subtypes `Shared`. ## Subtyping @@ -631,16 +625,18 @@ Two types `T`, `U` are related by subtyping, written `T <: U`, whenever, one of * For some type `V`, `T <: V` and `V <: U` (*transitivity*). -* `U` is type `Shared` and `T` is equivalent to: - * a `shared` function type, or - * a `shared` object type, or - * a `actor` object type, or - * a scalar primitive type, or - * the type `Text`, or - * an immutable array type `[V]` with `V <: Shared`, or - * the type `Null`, or - * an option type `? V` with `V <: Shared`, or - * a tuple type `(T0, ..., Tn)` where, for each `0 <= i <= n`, `Ti <: Shared`. +## Sharability + +A type `T` is *shared* if it is +* `Any` or `None`, or +* a primitive type, or +* an option type `? V` where `V` is shared, or +* a tuple type `(T0, ..., Tn)` where all `Ti` are shared, or +* an immutable array type `[V]` where `V` is shared, or +* an object type where all fields are immutable and have shared type, or +* a variant type where all tags have shared type, or +* a `shared` function type. + # Literals @@ -980,7 +976,7 @@ Otherwise, `r2` is false and the result is `()`. The for expression `for ( in ) ` has type `()` provided: -* `` has type `(object|shared) { Next : () -> ?T; }`; +* `` has type `{ next : () -> ?T; }`; * pattern `` has type `U`; and, * expression `` has type `()` (in the environment extended with ``'s bindings). @@ -990,19 +986,18 @@ The `for`-expression is syntactic sugar for for ( in ) := { let x = ; - label l - loop { - switch (x.Next()) { + label l loop { + switch (x.next()) { case (? ) ; case (null) break l; - }; - }; - }; + } + } + } ``` where `x` is fresh identifier. -In particular, the `for` loops will trap if evaluation of `` traps; as soon as some value of `x.Next()` traps or the value of `x.Next()` does not match pattern ``. +In particular, the `for` loops will trap if evaluation of `` traps; as soon as some value of `x.next()` traps or the value of `x.next()` does not match pattern ``. _TBR: do we want this semantics? We could, instead, skip values that don't match ``?_ @@ -1066,7 +1061,7 @@ TBR async traps? The async expression `async ` has type `async T` provided: * `` has type `T`; -* `T <: Shared`. +* `T` is shared. Any control-flow label in scope for `async ` is not in scope for `` (that `` may declare its own, local, labels. @@ -1082,8 +1077,8 @@ Evaluation of `async ` queues a message to evaluate `` in the nearest The `await` expression `await ` has type `T` provided: * `` has type `async T`, -* `T <: Shared`. -* the `await` is explicitly enclosed by an `async`-expression or its nearest enclosing function is `shared`. +* `T` is shared, +* the `await` is explicitly enclosed by an `async`-expression. `await ` evaluates `` to a result `r`. If `r` is `trap`, evaluation returns `trap`. Otherwise `r1` is a promise. If the promise is complete with value `v`, then `await ` evaluates to value `v`. If the `promise` is incomplete, that is, its evaluation is still pending, `await ` suspends evaluation of the neared enclosing `async` or `shared`-function, adding the suspension to the wait-queue of the `promise`. Execution of the suspension is resumed once the promise is completed (if ever). @@ -1193,7 +1188,7 @@ matching ``, if it succeeds, or the result of matching ``, if the fi expression let = immutable var (: )? = mutable - (new|object|actor|shared) ? =? { ;* } object + (new|object|actor) ? =? { ;* } object shared? func ? ? (: )? =? function type ? = type obj_sort? class ? =? { ;* }` class @@ -1257,9 +1252,9 @@ In scope of the declaration `type C < X0<:T0>, ..., Xn <: Tn > = U`, any well- ## Object Declaration -Declaration `(new|object|actor|shared) ? =? { ;* }` declares an object with optional identifier `` and zero or more fields `;*`. +Declaration `(new|object|actor) ? =? { ;* }` declares an object with optional identifier `` and zero or more fields `;*`. -The qualifier `new|object|actor|shared` specifies the *sort* of the object's type (`new` is equivalent to `object`). The sort imposes restrictions on the types of the non-private object fields and the sharability of the object itself. +The qualifier `new|object|actor` specifies the *sort* of the object's type (`new` is equivalent to `object`). The sort imposes restrictions on the types of the non-private object fields. Let `T = sort { [var0] id0 : T0, ... , [varn] idn : T0 }` denote the type of the object. Let `;*` be the sequence of declarations in `;*`. @@ -1276,11 +1271,8 @@ Note that requirement 1. imposes further constraints on the fields type of `T`. In particular: * if the sort is `actor` then all non-private fields must be non-`var` (immutable) `shared` functions (the public interface of an actor can only provide asynchronous messaging via shared functions). -* if the sort is `shared` then all non-private field must be non-`var` (immutable) and of a type that is sharable (`T(idi) <: Shared`). Shared objects can be sent - as arguments to `shared` functions or returned as the result of a `shared` - function (wrapped in a promise). -Evaluation of `(new|object|actor|shared) ? =? { ;* }` proceeds by +Evaluation of `(new|object|actor) ? =? { ;* }` proceeds by evaluating the declarations in `;*`. If the evaluation of `;*` traps, so does the object declaration. Otherwise, `;*` produces a set of bindings for identifiers in `Id`. let `v0`, ..., `vn` be the values or locations bound to identifiers ``, ..., ``. @@ -1322,7 +1314,7 @@ where: * `;*` is the set of non-`private` field types inferred from ``. * `?` is the optional `this` parameter of the object instance. -_TBR can we delete `new'?_ +_TBR can we delete `new`?_ ## Expression Fields diff --git a/samples/app/server.as b/samples/app/server.as index 076fcc8d116..558bdeeb406 100644 --- a/samples/app/server.as +++ b/samples/app/server.as @@ -29,7 +29,7 @@ actor class Server() = { nextId += 1; let cs = new {head = c; var tail = clients}; clients := ?cs; - return (shared { + return (new { post = shared func(message : Text) { if (not c.revoked) broadcast(c.id, message); }; diff --git a/samples/app/types.as b/samples/app/types.as index 489dc008197..343eaa34205 100644 --- a/samples/app/types.as +++ b/samples/app/types.as @@ -1,6 +1,4 @@ -type Subscription = shared { +type Subscription = { post : shared Text -> (); // revokable by Server cancel : shared () -> (); }; - - diff --git a/src/as_def/arrange.ml b/src/as_def/arrange.ml index 475c7fdd0c2..48d28c9e7e1 100644 --- a/src/as_def/arrange.ml +++ b/src/as_def/arrange.ml @@ -27,7 +27,7 @@ let rec exp e = match e.it with | FuncE (x, s, tp, p, t, e') -> "FuncE" $$ [ Atom (Type.string_of_typ e.note.note_typ); - Atom (Arrange_type.sharing s.it); + func_sort s; Atom x] @ List.map typ_bind tp @ [ pat p; @@ -97,7 +97,14 @@ and case c = "case" $$ [pat c.it.pat; exp c.it.exp] and pat_field pf = pf.it.id.it $$ [pat pf.it.pat] -and obj_sort s = Arrange_type.obj_sort s.it +and obj_sort s = match s.it with + | Type.Object -> Atom "Object" + | Type.Actor -> Atom "Actor" + | Type.Module -> Atom "Module" + +and func_sort s = match s.it with + | Type.Local -> Atom "Local" + | Type.Shared -> Atom "Shared" and mut m = match m.it with | Const -> Atom "Const" @@ -133,7 +140,7 @@ and typ t = match t.it with | OptT t -> "OptT" $$ [typ t] | VariantT cts -> "VariantT" $$ List.map typ_tag cts | TupT ts -> "TupT" $$ List.map typ ts - | FuncT (s, tbs, at, rt) -> "FuncT" $$ [Atom (Arrange_type.sharing s.it)] @ List.map typ_bind tbs @ [ typ at; typ rt] + | FuncT (s, tbs, at, rt) -> "FuncT" $$ [func_sort s] @ List.map typ_bind tbs @ [ typ at; typ rt] | AsyncT t -> "AsyncT" $$ [typ t] | ParT t -> "ParT" $$ [typ t] diff --git a/src/as_def/syntax.ml b/src/as_def/syntax.ml index e51e2d93d27..3a055d9c4e1 100644 --- a/src/as_def/syntax.ml +++ b/src/as_def/syntax.ml @@ -19,8 +19,8 @@ type typ_id = (string, Type.con option) Source.annotated_phrase (* Types *) -type sharing = Type.sharing Source.phrase type obj_sort = Type.obj_sort Source.phrase +type func_sort = Type.func_sort Source.phrase type mut = mut' Source.phrase and mut' = Const | Var @@ -39,7 +39,7 @@ and typ' = | OptT of typ (* option *) | VariantT of typ_tag list (* variant *) | TupT of typ list (* tuple *) - | FuncT of sharing * typ_bind list * typ * typ (* function *) + | FuncT of func_sort * typ_bind list * typ * typ (* function *) | AsyncT of typ (* future *) | ParT of typ (* parentheses, used to control function arity only *) @@ -126,7 +126,7 @@ and exp' = | AssignE of exp * exp (* assignment *) | ArrayE of mut * exp list (* array *) | IdxE of exp * exp (* array indexing *) - | FuncE of string * sharing * typ_bind list * pat * typ option * exp (* function *) + | FuncE of string * func_sort * typ_bind list * pat * typ option * exp (* function *) | CallE of exp * typ list * exp (* function call *) | BlockE of dec list (* block (with type after avoidance)*) | NotE of exp (* negation *) diff --git a/src/as_frontend/parser.mly b/src/as_frontend/parser.mly index 2eb61d38f2d..260c9d8c514 100644 --- a/src/as_frontend/parser.mly +++ b/src/as_frontend/parser.mly @@ -66,10 +66,8 @@ let let_or_exp named x e' at = let share_typ t = match t.it with - | ObjT ({it = Type.Object Type.Local; _} as s, tfs) -> - { t with it = ObjT ({s with it = Type.Object Type.Sharable}, tfs)} | FuncT ({it = Type.Local; _} as s, tbs, t1, t2) -> - { t with it = FuncT ({s with it = Type.Sharable}, tbs, t1, t2)} + { t with it = FuncT ({s with it = Type.Shared}, tbs, t1, t2)} | _ -> t let share_typfield (tf : typ_field) = @@ -78,7 +76,7 @@ let share_typfield (tf : typ_field) = let share_exp e = match e.it with | FuncE (x, ({it = Type.Local; _} as s), tbs, p, t, e) -> - FuncE (x, {s with it = Type.Sharable}, tbs, p, t, e) @? e.at + FuncE (x, {s with it = Type.Shared}, tbs, p, t, e) @? e.at | _ -> e let share_dec d = @@ -182,23 +180,18 @@ seplist(X, SEP) : | VAR { Var @@ at $sloc } %inline obj_sort : - | NEW { Type.Object Type.Local @@ at $sloc } - | OBJECT { Type.Object Type.Local @@ at $sloc } - | SHARED { Type.Object Type.Sharable @@ at $sloc } + | NEW { Type.Object @@ at $sloc } + | OBJECT { Type.Object @@ at $sloc } | ACTOR { Type.Actor @@ at $sloc } | MODULE { Type.Module @@ at $sloc } %inline obj_sort_opt : - | (* empty *) { Type.Object Type.Local @@ no_region } + | (* empty *) { Type.Object @@ no_region } | s=obj_sort { s } -%inline shared_opt : - | (* empty *) { Type.Local @@ no_region } - | SHARED { Type.Sharable @@ at $sloc } - %inline func_sort_opt : | (* empty *) { Type.Local @@ no_region } - | SHARED { Type.Sharable @@ at $sloc } + | SHARED { Type.Shared @@ at $sloc } (* paths *) @@ -230,7 +223,7 @@ typ_nullary : | LBRACKET m=var_opt t=typ RBRACKET { ArrayT(m, t) @! at $sloc } | tfs=typ_obj - { ObjT(Type.Object Type.Local @@ at $sloc, tfs) @! at $sloc } + { ObjT(Type.Object @@ at $sloc, tfs) @! at $sloc } | tfs=typ_variant { VariantT tfs @! at $sloc } @@ -249,9 +242,7 @@ typ_pre : { AsyncT(t) @! at $sloc } | s=obj_sort tfs=typ_obj { let tfs' = - if s.it = Type.Object Type.Local || s.it = Type.Module - then tfs - else List.map share_typfield tfs + if s.it = Type.Actor then List.map share_typfield tfs else tfs in ObjT(s, tfs') @! at $sloc } typ : @@ -495,7 +486,7 @@ exp_field : | v=private_opt x=id EQ e=exp { let d = LetD(VarP(x) @! x.at, e) @? at $sloc in {dec = d; vis = v} @@ at $sloc } - | v=private_opt s=shared_opt x=id fe=func_exp + | v=private_opt s=func_sort_opt x=id fe=func_exp { let d = LetD(VarP(x) @! x.at, fe s x.it) @? at $sloc in {dec = d; vis = v} @@ at $sloc } (* TODO(andreas): allow any dec *) @@ -582,19 +573,15 @@ dec_nonvar : | s=obj_sort xf=id_opt EQ? efs=obj_body { let named, x = xf "object" $sloc in let efs' = - if s.it = Type.Object Type.Local || s.it = Type.Module - then efs - else List.map share_expfield efs + if s.it = Type.Actor then List.map share_expfield efs else efs in let_or_exp named x (ObjE(s, efs')) (at $sloc) } - | s=shared_opt FUNC xf=id_opt fe=func_exp + | s=func_sort_opt FUNC xf=id_opt fe=func_exp { let named, x = xf "func" $sloc in let_or_exp named x (fe s x.it).it (at $sloc) } | s=obj_sort_opt CLASS xf=typ_id_opt tps=typ_params_opt p=pat_argument xefs=class_body { let x, efs = xefs in let efs' = - if s.it = Type.Object Type.Local || s.it = Type.Module - then efs - else List.map share_expfield efs + if s.it = Type.Actor then List.map share_expfield efs else efs in ClassD(xf "class" $sloc, tps, s, p, x, efs') @? at $sloc } | IMPORT xf=id_opt EQ? f=TEXT { let named, x = xf "import" $sloc in diff --git a/src/as_frontend/typing.ml b/src/as_frontend/typing.ml index e58d91559e7..b893cff7216 100644 --- a/src/as_frontend/typing.ml +++ b/src/as_frontend/typing.ml @@ -126,7 +126,7 @@ let rec check_obj_path env path : T.obj_sort * (T.field list) = (s, fs) | t -> error env path.at - "expected actor, object or module type, but path expression produces type\n %s" + "expected module, object, or actor type, but path expression produces type\n %s" (T.string_of_typ_expand t) and check_obj_path' env path : T.typ = @@ -180,7 +180,6 @@ and check_typ' env typ : T.typ = T.Con (c, ts) | PrimT "Any" -> T.Any | PrimT "None" -> T.Non - | PrimT "Shared" -> T.Shared | PrimT s -> (try T.Prim (T.prim s) with Invalid_argument _ -> error env typ.at "unknown primitive type" @@ -198,20 +197,15 @@ and check_typ' env typ : T.typ = let ts1 = List.map (check_typ env') typs1 in let ts2 = List.map (check_typ env') typs2 in let c = match typs2 with [{it = AsyncT _; _}] -> T.Promises | _ -> T.Returns in - if sort.it = T.Sharable then + if sort.it = T.Shared then if not env.pre then begin let t1 = T.seq ts1 in - if not (T.sub t1 T.Shared) then + if not (T.shared t1) then error env typ1.at "shared function has non-shared parameter type\n %s" (T.string_of_typ_expand t1); match ts2 with - | [] -> () - | [T.Async t2] -> - if not (T.sub t2 T.Shared) then - error env typ2.at - "shared function has non-shared result type\n %s" - (T.string_of_typ_expand t2); + | [] | [T.Async _] -> () | _ -> error env typ2.at "shared function has non-async result type\n %s" @@ -228,8 +222,8 @@ and check_typ' env typ : T.typ = T.Variant (List.sort T.compare_field fs) | AsyncT typ -> let t = check_typ env typ in - if not env.pre && not (T.sub t T.Shared) then - error env typ.at "async type has non-shared parameter type\n %s" + if not env.pre && not (T.shared t) then + error env typ.at "async has non-shared content type\n %s" (T.string_of_typ_expand t); T.Async t | ObjT (sort, fields) -> @@ -243,13 +237,12 @@ and check_typ' env typ : T.typ = and check_typ_field env s typ_field : T.field = let {id; mut; typ} = typ_field.it in let t = infer_mut mut (check_typ env typ) in - if not env.pre then begin - if s = T.Actor && not (T.is_func (T.promote t)) then + if not env.pre && s = T.Actor then begin + if not (T.is_func (T.promote t)) then error env typ.at "actor field %s has non-function type\n %s" id.it (T.string_of_typ_expand t); - if s <> T.Object T.Local && not (T.sub t T.Shared) then - error env typ.at - "shared object or actor field %s has non-shared type\n %s" + if not (T.shared t) then + error env typ.at "actor field %s has non-shared type\n %s" id.it (T.string_of_typ_expand t) end; T.{lab = id.it; typ = t} @@ -406,12 +399,12 @@ let array_obj t = ] in let mut t = immut t @ [ {lab = "set"; typ = Func (Local, Returns, [], [Prim Nat; t], [])} ] in - Object Local, + Object, List.sort compare_field (match t with Mut t' -> mut t' | t -> immut t) let text_obj () = let open T in - Object Local, + Object, [ {lab = "chars"; typ = Func (Local, Returns, [], [], [iter_obj (Prim Char)])}; {lab = "len"; typ = Func (Local, Returns, [], [], [Prim Nat])}; ] @@ -600,29 +593,17 @@ and infer_exp'' env exp : T.typ = let env'' = {env' with labs = T.Env.empty; rets = Some t2; async = false} in check_exp (adjoin_vals env'' ve) t2 exp; - if sort.it = T.Sharable then begin - if not (T.sub t1 T.Shared) then + if sort.it = T.Shared then begin + if not (T.shared t1) then error env pat.at "shared function has non-shared parameter type\n %s" (T.string_of_typ_expand t1); - if not (T.concrete t1) then - error env pat.at - "shared function parameter contains abstract type\n %s" - (T.string_of_typ_expand t1); match t2 with | T.Tup [] -> () - | T.Async t2 -> - if not (T.sub t2 T.Shared) then - error env typ.at - "shared function has non-shared result type\n %s" - (T.string_of_typ_expand t2); - if not (T.concrete t2) then - error env typ.at - "shared function result contains abstract type\n %s" - (T.string_of_typ_expand t2); + | T.Async _ -> if not (isAsyncE exp) then error env exp.at - "shared function with async type has non-async body" + "shared function with async result type has non-async body" | _ -> error env typ.at "shared function has non-async result type\n %s" (T.string_of_typ_expand t2) @@ -632,7 +613,7 @@ and infer_exp'' env exp : T.typ = let ts2 = match typ.it with TupT _ -> T.as_seq t2 | _ -> [t2] in let c = match sort.it, typ.it with - | T.Sharable, (AsyncT _) -> T.Promises (* TBR: do we want this for T.Local too? *) + | T.Shared, (AsyncT _) -> T.Promises (* TBR: do we want this for T.Local too? *) | _ -> T.Returns in let tbs = List.map2 (fun c t -> {T.var = Con.name c; bound = T.close cs t}) cs ts in @@ -651,7 +632,7 @@ and infer_exp'' env exp : T.typ = let t_ret = T.open_ ts t_ret in if not env.pre then begin check_exp env t_arg exp2; - if sort = T.Sharable then begin + if sort = T.Shared then begin if not (T.concrete t_arg) then error env exp1.at "shared function argument contains abstract type\n %s" @@ -777,8 +758,8 @@ and infer_exp'' env exp : T.typ = let env' = {env with labs = T.Env.empty; rets = Some T.Pre; async = true} in let t = infer_exp env' exp1 in - if not (T.sub t T.Shared) then - error env exp1.at "async type has non-shared parameter type\n %s" + if not (T.shared t) then + error env exp1.at "async type has non-shared content type\n %s" (T.string_of_typ_expand t); T.Async t | AwaitE exp1 -> @@ -1004,7 +985,7 @@ and infer_pats at env pats ts ve : T.typ list * Scope.val_env = and infer_pat_fields at env pfs ts ve : (T.obj_sort * T.field list) * Scope.val_env = match pfs with - | [] -> (T.(Object Local), List.rev ts), ve + | [] -> (T.Object, List.rev ts), ve | pf::pfs' -> let typ, ve1 = infer_pat env pf.it.pat in let ve' = disjoint_union env at "duplicate binding for %s in pattern" ve ve1 in @@ -1275,19 +1256,20 @@ and infer_obj env s fields at : T.typ = let t = object_of_scope env s fields scope at in let (_, tfs) = T.as_obj t in if not env.pre then begin - if s = T.Object T.Sharable || s = T.Actor then + if s = T.Actor then List.iter (fun T.{lab; typ} -> - if (not (T.is_typ typ)) && not (T.sub typ T.Shared) then - let _, pub_val = pub_fields fields in - error env (T.Env.find lab pub_val) - "public shared object or actor field %s has non-shared type\n %s" - lab (T.string_of_typ_expand typ) - ) tfs; + if not (T.is_typ typ) && not (T.shared typ) then + let _, pub_val = pub_fields fields in + error env (T.Env.find lab pub_val) + "public actor field %s has non-shared type\n %s" + lab (T.string_of_typ_expand typ) + ) tfs; if s = T.Actor then List.iter (fun ef -> - if ef.it.vis.it = Syntax.Public && not (is_actor_method ef.it.dec) && not (is_typ_dec ef.it.dec) then - local_error env ef.it.dec.at "public actor field needs to be a manifest function" - ) fields; + if ef.it.vis.it = Syntax.Public && not (is_actor_method ef.it.dec) && not (is_typ_dec ef.it.dec) then + local_error env ef.it.dec.at + "public actor field needs to be a manifest function" + ) fields; if s = T.Module then Static.fields env.msgs fields end; t diff --git a/src/as_interpreter/interpret.ml b/src/as_interpreter/interpret.ml index 21027eefd09..dcbdcd7cc73 100644 --- a/src/as_interpreter/interpret.ml +++ b/src/as_interpreter/interpret.ml @@ -175,7 +175,7 @@ let make_unit_message env id v = let open CC in let call_conv, f = V.as_func v in match call_conv with - | {sort = T.Sharable; n_res = 0; _} -> + | {sort = T.Shared; n_res = 0; _} -> Value.message_func call_conv.n_args (fun v k -> actor_msg env id f v (fun _ -> ()); k V.unit @@ -187,7 +187,7 @@ let make_async_message env id v = let open CC in let call_conv, f = V.as_func v in match call_conv with - | {sort = T.Sharable; control = T.Promises; n_res = 1; _} -> + | {sort = T.Shared; control = T.Promises; n_res = 1; _} -> Value.async_func call_conv.n_args (fun v k -> let async = make_async () in actor_msg env id f v (fun v_async -> @@ -438,7 +438,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = let v = V.Func (CC.call_conv_of_typ exp.note.note_typ, f) in let v' = match _sort.it with - | T.Sharable -> make_message env name exp.note.note_typ v + | T.Shared -> make_message env name exp.note.note_typ v | T.Local -> v in k v' | CallE (exp1, typs, exp2) -> diff --git a/src/as_types/arrange_type.ml b/src/as_types/arrange_type.ml index 51c180ce303..1b5208d459e 100644 --- a/src/as_types/arrange_type.ml +++ b/src/as_types/arrange_type.ml @@ -3,19 +3,19 @@ open Wasm.Sexpr let ($$) head inner = Node (head, inner) -let sharing sh = match sh with - | Local -> "Local" - | Sharable -> "Sharable" - let control c = match c with | Returns -> "Returns" | Promises -> "Promises" let obj_sort s = match s with - | Object sh -> Atom ("Object " ^ sharing sh) + | Object -> Atom "Object" | Actor -> Atom "Actor" | Module -> Atom "Module" +let func_sort s = match s with + | Local -> "Local" + | Shared -> "Shared" + let prim p = match p with | Null -> Atom "Null" | Bool -> Atom "Bool" @@ -48,11 +48,10 @@ let rec typ (t:Type.typ) = match t with | Opt t -> "Opt" $$ [typ t] | Variant tfs -> "Variant" $$ List.map typ_field tfs | Tup ts -> "Tup" $$ List.map typ ts - | Func (s, c, tbs, at, rt) -> "Func" $$ [Atom (sharing s); Atom (control c)] @ List.map typ_bind tbs @ [ "" $$ (List.map typ at); "" $$ (List.map typ rt)] + | Func (s, c, tbs, at, rt) -> "Func" $$ [Atom (func_sort s); Atom (control c)] @ List.map typ_bind tbs @ [ "" $$ (List.map typ at); "" $$ (List.map typ rt)] | Async t -> "Async" $$ [typ t] | Mut t -> "Mut" $$ [typ t] | Serialized t -> "Serialized" $$ [typ t] - | Shared -> Atom "Shared" | Any -> Atom "Any" | Non -> Atom "Non" | Pre -> Atom "Pre" diff --git a/src/as_types/call_conv.ml b/src/as_types/call_conv.ml index aecb211d1ad..6c1acb006e0 100644 --- a/src/as_types/call_conv.ml +++ b/src/as_types/call_conv.ml @@ -1,7 +1,7 @@ open Type type call_conv = { - sort: sharing; + sort: func_sort; control : control; n_args : int; n_res : int; @@ -9,20 +9,20 @@ type call_conv = { type t = call_conv let local_cc n m = { sort = Local; control = Returns; n_args = n; n_res = m} -let message_cc n = { sort = Sharable; control = Returns; n_args = n; n_res = 0} -let async_cc n = { sort = Sharable; control = Promises; n_args = n; n_res = 1} +let message_cc n = { sort = Shared; control = Returns; n_args = n; n_res = 0} +let async_cc n = { sort = Shared; control = Promises; n_args = n; n_res = 1} let call_conv_of_typ typ = match typ with | Func(sort, control, tbds, dom, res) -> { sort; control; n_args = List.length dom; n_res = List.length res } | Non -> - { sort = Type.Local; control = Type.Returns; n_args = 1; n_res = 1 } + { sort = Local; control = Returns; n_args = 1; n_res = 1 } | _ -> raise (Invalid_argument ("call_conv_of_typ " ^ string_of_typ typ)) let string_of_call_conv {sort;control;n_args;n_res} = - Printf.sprintf "(%s %i %s %i)" - (string_of_sharing sort) + Printf.sprintf "(%s%i %s %i)" + (string_of_func_sort sort) n_args (match control with Returns -> "->" | Promises -> "@>") n_res diff --git a/src/as_types/call_conv.mli b/src/as_types/call_conv.mli index 5cef573ce01..b1930824765 100644 --- a/src/as_types/call_conv.mli +++ b/src/as_types/call_conv.mli @@ -1,7 +1,7 @@ (* Calling convention *) type call_conv = { - sort: Type.sharing; + sort: Type.func_sort; control : Type.control; n_args : int; n_res : int; diff --git a/src/as_types/type.ml b/src/as_types/type.ml index 1c61d5e255a..d65439098ac 100644 --- a/src/as_types/type.ml +++ b/src/as_types/type.ml @@ -4,8 +4,8 @@ type lab = string type var = string type control = Returns | Promises (* Returns a computed value or immediate promise *) -type sharing = Local | Sharable -type obj_sort = Object of sharing | Actor | Module +type obj_sort = Object | Actor | Module +type func_sort = Local | Shared type eff = Triv | Await type prim = @@ -39,10 +39,9 @@ and typ = | Array of typ (* array *) | Opt of typ (* option *) | Tup of typ list (* tuple *) - | Func of sharing * control * bind list * typ list * typ list (* function *) + | Func of func_sort * control * bind list * typ list * typ list (* function *) | Async of typ (* future *) | Mut of typ (* mutable type *) - | Shared (* sharable *) | Serialized of typ (* a serialized value *) | Any (* top *) | Non (* bottom *) @@ -113,7 +112,7 @@ let compare_field f1 f2 = (* Coercions *) let iter_obj t = - Obj (Object Local, + Obj (Object, [{lab = "next"; typ = Func (Local, Returns, [], [], [Opt t])}]) (* Shifting *) @@ -133,7 +132,6 @@ let rec shift i n t = | Obj (s, fs) -> Obj (s, List.map (shift_field n i) fs) | Variant fs -> Variant (List.map (shift_field n i) fs) | Mut t -> Mut (shift i n t) - | Shared -> Shared | Serialized t -> Serialized (shift i n t) | Any -> Any | Non -> Non @@ -181,7 +179,6 @@ let rec subst sigma t = | Obj (s, fs) -> Obj (s, List.map (subst_field sigma) fs) | Variant fs -> Variant (List.map (subst_field sigma) fs) | Mut t -> Mut (subst sigma t) - | Shared -> Shared | Serialized t -> Serialized (subst sigma t) | Any -> Any | Non -> Non @@ -238,7 +235,6 @@ let rec open' i ts t = | Obj (s, fs) -> Obj (s, List.map (open_field i ts) fs) | Variant fs -> Variant (List.map (open_field i ts) fs) | Mut t -> Mut (open' i ts t) - | Shared -> Shared | Serialized t -> Serialized (open' i ts t) | Any -> Any | Non -> Non @@ -338,7 +334,7 @@ let as_prim_sub p t = match promote t with | _ -> invalid "as_prim_sub" let as_obj_sub ls t = match promote t with | Obj (s, tfs) -> s, tfs - | Non -> Object Sharable, List.map (fun l -> {lab = l; typ = Non}) ls + | Non -> Object, List.map (fun l -> {lab = l; typ = Non}) ls | _ -> invalid "as_obj_sub" let as_variant_sub l t = match promote t with | Variant tfs -> tfs @@ -404,7 +400,7 @@ let rec span = function | Prim (Nat32 | Int32 | Word32 | Nat64 | Int64 | Word64 | Char) -> None (* for all practical purposes *) | Obj _ | Tup _ | Async _ -> Some 1 | Variant fs -> Some (List.length fs) - | Array _ | Func _ | Shared | Any -> None + | Array _ | Func _ | Any -> None | Opt _ -> Some 2 | Mut t -> span t | Serialized t -> None @@ -417,7 +413,7 @@ let rec span = function exception Unavoidable of con let rec avoid' cons seen = function - | (Prim _ | Var _ | Any | Non | Shared | Pre) as t -> t + | (Prim _ | Var _ | Any | Non | Pre) as t -> t | Con (c, ts) -> if ConSet.mem c seen then raise (Unavoidable c) else if ConSet.mem c cons @@ -476,7 +472,7 @@ let avoid cons t = let rec cons t cs = match t with | Var _ -> cs - | (Prim _ | Any | Non | Shared | Pre) -> cs + | (Prim _ | Any | Non | Pre) -> cs | Con (c, ts) -> List.fold_right cons ts (ConSet.add c cs) | (Opt t | Async t | Mut t | Serialized t | Array t) -> @@ -513,33 +509,51 @@ allows polymorphic types, see #250. It is not what we desire for ActorScript. *) let concrete t = - let seen = ref S.empty in (* break the cycles *) + let seen = ref S.empty in let rec go t = S.mem t !seen || begin seen := S.add t !seen; match t with - | Var _ -> assert false - | Prim _ | Any | Non | Shared -> true + | Var _ | Pre -> assert false + | Prim _ | Any | Non -> true | Con (c, ts) -> (match Con.kind c with | Abs _ -> false - | Def (tbs,t) -> go (open_ ts t) (* TBR this may fail to terminate *) + | Def (_, t) -> go (open_ ts t) (* TBR this may fail to terminate *) ) - | Array t -> go t + | Array t | Opt t | Async t | Mut t | Serialized t -> go t | Tup ts -> List.for_all go ts + | Obj (_, fs) | Variant fs -> List.for_all (fun f -> go f.typ) fs | Func (s, c, tbs, ts1, ts2) -> let ts = open_binds tbs in List.for_all go (List.map (open_ ts) ts1) && List.for_all go (List.map (open_ ts) ts2) - | Opt t -> go t - | Async t -> go t - | Obj (s, fs) -> List.for_all (fun f -> go f.typ) fs - | Variant fs -> List.for_all (fun f -> go f.typ) fs - | Mut t -> go t | Typ c -> assert false (* TBR *) - | Serialized t -> go t - | Pre -> assert false + end + in go t + + +let shared t = + let seen = ref S.empty in + let rec go t = + S.mem t !seen || + begin + seen := S.add t !seen; + match t with + | Var _ | Pre -> assert false + | Any | Non | Prim _ | Typ _ -> true + | Async _ | Mut _ -> false + | Con (c, ts) -> + (match Con.kind c with + | Abs _ -> false + | Def (_, t) -> go (open_ ts t) (* TBR this may fail to terminate *) + ) + | Array t | Opt t | Serialized t -> go t + | Tup ts -> List.for_all go ts + | Obj (s, fs) -> s = Actor || List.for_all (fun f -> go f.typ) fs + | Variant fs -> List.for_all (fun f -> go f.typ) fs + | Func (s, c, tbs, ts1, ts2) -> s = Shared end in go t @@ -596,54 +610,33 @@ let rec rel_typ rel eq t1 t2 = true | Prim p1, Prim p2 when rel != eq -> p1 = Nat && p2 = Int - | Prim p1, Shared when rel != eq -> - true | Obj (s1, tfs1), Obj (s2, tfs2) -> s1 = s2 && rel_fields rel eq tfs1 tfs2 - | Obj (s, _), Shared when rel != eq -> - s <> Object Local | Array t1', Array t2' -> rel_typ rel eq t1' t2' - | Array t, Shared when rel != eq -> - rel_typ rel eq t Shared | Opt t1', Opt t2' -> rel_typ rel eq t1' t2' - | Opt t1', Shared -> - rel_typ rel eq t1' Shared | Prim Null, Opt t2' when rel != eq -> true | Variant fs1, Variant fs2 -> rel_tags rel eq fs1 fs2 - | Variant fs1, Shared -> - rel_tags rel eq fs1 (List.map (fun f -> {f with typ = Shared}) fs1) | Tup ts1, Tup ts2 -> rel_list rel_typ rel eq ts1 ts2 - | Tup ts1, Shared -> - rel_list rel_typ rel eq ts1 (List.map (fun _ -> Shared) ts1) | Func (s1, c1, tbs1, t11, t12), Func (s2, c2, tbs2, t21, t22) -> c1 = c2 && s1 = s2 && - (* subtyping on shared functions needs to imply subtyping of the serialized - arguments, i.e. the IDL. Until we have a real IDL, we are conservative - here and assume no subtyping in the IDL. This makes shared functions invariant. *) - let rel_param = - if s1 = Sharable then eq_typ else rel_typ in (match rel_binds rel eq tbs1 tbs2 with | Some ts -> - rel_list rel_param rel eq (List.map (open_ ts) t21) (List.map (open_ ts) t11) && - rel_list rel_param rel eq (List.map (open_ ts) t12) (List.map (open_ ts) t22) + rel_list rel_typ rel eq (List.map (open_ ts) t21) (List.map (open_ ts) t11) && + rel_list rel_typ rel eq (List.map (open_ ts) t12) (List.map (open_ ts) t22) | None -> false ) - | Func (Sharable, _, _, _, _), Shared when rel != eq -> - true - | Shared, Shared -> - true | Async t1', Async t2' -> rel_typ rel eq t1' t2' | Mut t1', Mut t2' -> eq_typ rel eq t1' t2' | Serialized t1', Serialized t2' -> - eq_typ rel eq t1' t2' (* TBR: eq or sub? Does it matter? *) + rel_typ rel eq t1' t2' | Typ c1, Typ c2 -> Con.eq c1 c2 | _, _ -> false @@ -725,9 +718,9 @@ let rec compatible_typ co t1 t2 = match promote t1, promote t2 with | (Pre | Serialized _), _ | _, (Pre | Serialized _) -> assert false - | (Any | Shared), (Any | Shared) -> + | Any, Any -> true - | Non, (Any | Shared) | (Any | Shared), Non -> + | Any, _ | _, Any -> false | Non, _ | _, Non -> true @@ -756,7 +749,8 @@ let rec compatible_typ co t1 t2 = true | Mut t1', Mut t2' -> compatible_typ co t1' t2' - | _, _ -> false + | _, _ -> + false end and compatible_fields co tfs1 tfs2 = @@ -793,7 +787,7 @@ let rec inhabited_typ co t = match promote t with | Pre | Serialized _ -> assert false | Non -> false - | Any | Shared | Prim _ | Array _ | Opt _ | Async _ | Func _ | Typ _ -> true + | Any | Prim _ | Array _ | Opt _ | Async _ | Func _ | Typ _ -> true | Mut t' -> inhabited_typ co t' | Tup ts -> List.for_all (inhabited_typ co) ts | Obj (_, tfs) -> List.for_all (inhabited_field co) tfs @@ -832,8 +826,6 @@ let rec lub' lubs glbs t1 t2 = | Any, _ -> Any | _, Non -> t1 | Non, _ -> t2 - | Shared, _ when sub t2 Shared -> Shared - | _, Shared when sub t1 Shared -> Shared | Prim Nat, (Prim Int as t) | (Prim Int as t), Prim Nat -> t | Opt t1', Opt t2' -> @@ -859,7 +851,6 @@ let rec lub' lubs glbs t1 t2 = (* TODO(rossberg): fix handling of bounds *) combine_con_parts t1 t2 "lub" lubs (lub' lubs glbs) | _ when eq t1 t2 -> t1 - | _ when sub t1 Shared && sub t2 Shared -> Shared | _ -> Any and lub_fields lubs glbs fs1 fs2 = match fs1, fs2 with @@ -892,8 +883,6 @@ and glb' lubs glbs t1 t2 = | Any, _ -> t2 | _, Non | Non, _ -> Non - | Shared, _ when sub t2 Shared -> t2 - | _, Shared when sub t1 Shared -> t1 | (Prim Nat as t), Prim Int | Prim Int, (Prim Nat as t) -> t | Opt t1', Opt t2' -> @@ -1009,15 +998,19 @@ let string_of_con' vs c = let s = Con.to_string c in if List.mem (s, 0) vs then s ^ "/0" else s (* TBR *) -let string_of_sharing = function +let string_of_obj_sort = function + | Object -> "" + | Module -> "module " + | Actor -> "actor " + +let string_of_func_sort = function | Local -> "" - | Sharable -> "shared " + | Shared -> "shared " let rec string_of_typ_nullary vs = function | Pre -> "???" | Any -> "Any" | Non -> "None" - | Shared -> "Shared" | Prim p -> string_of_prim p | Var (s, i) -> (try string_of_var (List.nth vs i) with _ -> assert false) | Con (c, []) -> string_of_con' vs c @@ -1032,7 +1025,7 @@ let rec string_of_typ_nullary vs = function sprintf "[var %s]" (string_of_typ_nullary vs t) | Array t -> sprintf "[%s]" (string_of_typ_nullary vs t) - | Obj (Object Local, fs) -> + | Obj (Object, fs) -> sprintf "{%s}" (String.concat "; " (List.map (string_of_field vs) fs)) | Variant [] -> "{#}" | Variant fs -> @@ -1063,24 +1056,20 @@ and string_of_cod c vs ts = and string_of_typ' vs t = match t with | Func (s, c, [], ts1, ts2) -> - sprintf "%s%s -> %s" (string_of_sharing s) + sprintf "%s%s -> %s" (string_of_func_sort s) (string_of_dom vs ts1) (string_of_cod c vs ts2) | Func (s, c, tbs, ts1, ts2) -> let vs' = vars_of_binds vs tbs in sprintf "%s%s%s -> %s" - (string_of_sharing s) (string_of_binds (vs' @ vs) vs' tbs) + (string_of_func_sort s) (string_of_binds (vs' @ vs) vs' tbs) (string_of_dom (vs' @ vs) ts1) (string_of_cod c (vs' @ vs) ts2) | Opt t -> sprintf "?%s" (string_of_typ_nullary vs t) | Async t -> sprintf "async %s" (string_of_typ_nullary vs t) - | Obj (Object Sharable, fs) -> - sprintf "shared %s" (string_of_typ_nullary vs (Obj (Object Local, fs))) - | Obj (Actor, fs) -> - sprintf "actor %s" (string_of_typ_nullary vs (Obj (Object Local, fs))) - | Obj (Module, fs) -> - sprintf "module %s" (string_of_typ_nullary vs (Obj (Object Local, fs))) + | Obj (s, fs) -> + sprintf "%s%s" (string_of_obj_sort s) (string_of_typ_nullary vs (Obj (Object, fs))) | Typ c -> sprintf "= (%s,%s)" (Con.to_string c) (string_of_kind (Con.kind c)) | Mut t -> @@ -1144,7 +1133,7 @@ let rec string_of_typ_expand t = | Abs _ -> s | Def _ -> match normalize t with - | Prim _ | Any | Non | Shared -> s + | Prim _ | Any | Non -> s | t' -> s ^ " = " ^ string_of_typ_expand t' ) | _ -> s diff --git a/src/as_types/type.mli b/src/as_types/type.mli index 4282da843ca..ae42e8f9cff 100644 --- a/src/as_types/type.mli +++ b/src/as_types/type.mli @@ -4,8 +4,8 @@ type lab = string type var = string type control = Returns | Promises (* returns a computed value or immediate promise *) -type sharing = Local | Sharable -type obj_sort = Object of sharing | Actor | Module +type obj_sort = Object | Actor | Module +type func_sort = Local | Shared type eff = Triv | Await type prim = @@ -39,10 +39,9 @@ and typ = | Array of typ (* array *) | Opt of typ (* option *) | Tup of typ list (* tuple *) - | Func of sharing * control * bind list * typ list * typ list (* function *) + | Func of func_sort * control * bind list * typ list * typ list (* function *) | Async of typ (* future *) | Mut of typ (* mutable type *) - | Shared (* sharable *) | Serialized of typ (* a serialized value *) | Any (* top *) | Non (* bottom *) @@ -96,7 +95,7 @@ val as_opt : typ -> typ val as_tup : typ -> typ list val as_unit : typ -> unit val as_pair : typ -> typ * typ -val as_func : typ -> sharing * control * bind list * typ list * typ list +val as_func : typ -> func_sort * control * bind list * typ list * typ list val as_async : typ -> typ val as_mut : typ -> typ val as_immut : typ -> typ @@ -111,7 +110,7 @@ val as_opt_sub : typ -> typ val as_tup_sub : int -> typ -> typ list val as_unit_sub : typ -> unit val as_pair_sub : typ -> typ * typ -val as_func_sub : sharing -> int -> typ -> sharing * bind list * typ * typ +val as_func_sub : func_sort -> int -> typ -> func_sort * bind list * typ * typ val as_mono_func_sub : typ -> typ * typ val as_async_sub : typ -> typ @@ -148,6 +147,7 @@ val avoid_cons : ConSet.t -> ConSet.t -> unit (* raise Unavoidable *) val opaque : typ -> bool val concrete : typ -> bool +val shared : typ -> bool val inhabited : typ -> bool val span : typ -> int option @@ -184,9 +184,10 @@ module Env : Env.S with type key = string (* Pretty printing *) +val string_of_obj_sort : obj_sort -> string +val string_of_func_sort : func_sort -> string val string_of_con : con -> string val string_of_prim : prim -> string -val string_of_sharing: sharing -> string val string_of_typ : typ -> string val string_of_kind : kind -> string val strings_of_kind : kind -> string * string * string diff --git a/src/as_values/show.ml b/src/as_values/show.ml index 22335a92613..095437daf0d 100644 --- a/src/as_values/show.ml +++ b/src/as_values/show.ml @@ -13,7 +13,7 @@ let rec can_show t = | Tup ts' -> List.for_all can_show ts' | Opt t' -> can_show t' | Array t' -> can_show (as_immut t') - | Obj (Object _, fs) -> + | Obj (Object, fs) -> List.for_all (fun f -> can_show (as_immut f.typ)) fs | Variant cts -> List.for_all (fun f -> can_show f.typ) cts diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index f686c48966b..4a4e02cd10c 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -1012,21 +1012,21 @@ module Tagged = struct match (tag : tag) with | Array -> begin match normalize ty with - | (Con _ | Shared | Any) -> true + | (Con _ | Any) -> true | (Array _ | Tup _ | Obj _) -> true | (Prim _ | Opt _ | Variant _ | Func _ | Serialized _ | Non) -> false | (Pre | Async _ | Mut _ | Var _ | Typ _) -> assert false end | Text -> begin match normalize ty with - | (Con _ | Shared | Any) -> true + | (Con _ | Any) -> true | (Prim Text | Obj _) -> true | (Prim _ | Array _ | Tup _ | Opt _ | Variant _ | Func _ | Serialized _ | Non) -> false | (Pre | Async _ | Mut _ | Var _ | Typ _) -> assert false end | Object -> begin match normalize ty with - | (Con _ | Shared | Any) -> true + | (Con _ | Any) -> true | (Obj _) -> true | (Prim _ | Array _ | Tup _ | Opt _ | Variant _ | Func _ | Serialized _ | Non) -> false | (Pre | Async _ | Mut _ | Var _ | Typ _) -> assert false @@ -2736,7 +2736,7 @@ module Serialization = struct seen := TS.add t !seen; match t with | Var _ -> assert false - | (Prim _ | Any | Non | Shared | Pre) -> true + | (Prim _ | Any | Non | Pre) -> true | Con (c, ts) -> begin match Con.kind c with | Abs _ -> assert false @@ -2744,7 +2744,7 @@ module Serialization = struct end | Array t -> go t | Tup ts -> List.for_all go ts - | Func (Sharable, c, tbs, ts1, ts2) -> false + | Func (Shared, c, tbs, ts1, ts2) -> false | Func (s, c, tbs, ts1, ts2) -> let ts = open_binds tbs in List.for_all go (List.map (open_ ts) ts1) && @@ -2797,7 +2797,6 @@ module Serialization = struct | Prim Int64 -> Some 12 | Prim Float -> Some 14 | Prim Text -> Some 15 - | Shared -> Some 16 | Non -> Some 17 | _ -> None in @@ -2817,7 +2816,7 @@ module Serialization = struct typs := !typs @ [ t ]; match t with | Tup ts -> List.iter go ts - | Obj ((Object Sharable | Actor), fs) -> + | Obj (_, fs) -> List.iter (fun f -> go f.typ) fs | Array t -> go t | Opt t -> go t @@ -2874,7 +2873,7 @@ module Serialization = struct let add_typ t = match t with - | Prim _ | Shared | Non -> assert false + | Prim _ | Non -> assert false | Tup ts -> add_sleb128 (-20); add_leb128 (List.length ts); @@ -2882,7 +2881,7 @@ module Serialization = struct add_leb128 i; add_idx t; ) ts - | Obj (Object Sharable, fs) -> + | Obj (Object, fs) -> add_sleb128 (-20); add_leb128 (List.length fs); List.iter (fun (h, f) -> @@ -2971,7 +2970,7 @@ module Serialization = struct get_x ^^ Tuple.load_n (Int32.of_int i) ^^ size env t ) ts - | Obj (Object Sharable, fs) -> + | Obj (Object, fs) -> G.concat_map (fun (_h, f) -> get_x ^^ Object.load_idx env t f.Type.lab ^^ size env f.typ @@ -2986,7 +2985,7 @@ module Serialization = struct | Prim Text -> size_word env (get_x ^^ Heap.load_field Text.len_field) ^^ inc_data_size (get_x ^^ Heap.load_field Text.len_field) - | (Prim Null | Shared) -> G.nop + | Prim Null -> G.nop | Opt t -> inc_data_size (compile_unboxed_const 1l) ^^ (* one byte tag *) get_x ^^ Opt.is_some env ^^ @@ -3094,7 +3093,7 @@ module Serialization = struct get_x ^^ Tuple.load_n (Int32.of_int i) ^^ write env t ) ts - | Obj (Object Sharable, fs) -> + | Obj (Object, fs) -> G.concat_map (fun (_h,f) -> get_x ^^ Object.load_idx env t f.Type.lab ^^ write env f.typ @@ -3106,7 +3105,7 @@ module Serialization = struct get_x ^^ get_i ^^ Arr.idx env ^^ load_ptr ^^ write env t ) - | (Prim Null | Shared) -> G.nop + | Prim Null -> G.nop | Opt t -> get_x ^^ Opt.is_some env ^^ @@ -3221,7 +3220,7 @@ module Serialization = struct | Tup ts -> G.concat_map (fun t -> read env t) ts ^^ Tuple.from_stack env (List.length ts) - | Obj (Object Sharable, fs) -> + | Obj (Object, fs) -> Object.lit_raw env (List.map (fun (_h,f) -> f.Type.lab, fun () -> read env f.typ ) (sort_by_hash fs)) @@ -3236,7 +3235,7 @@ module Serialization = struct read env t ^^ store_ptr ) ^^ get_x - | (Prim Null | Shared) -> Opt.null + | Prim Null -> Opt.null | Opt t -> read_byte ^^ compile_eq_const 0l ^^ @@ -3290,7 +3289,7 @@ module Serialization = struct (* Special-cased formats for scaffolding *) | Type.Prim Type.Text -> get_x ^^ Dfinity.compile_databuf_of_text env | Type.Obj (Type.Actor, _) - | Type.Func (Type.Sharable, _, _, _, _) -> get_x ^^ Dfinity.unbox_reference env + | Type.Func (Type.Shared, _, _, _, _) -> get_x ^^ Dfinity.unbox_reference env (* normal format *) | _ -> let (set_data_size, get_data_size) = new_local env "data_size" in @@ -3387,7 +3386,7 @@ module Serialization = struct match Type.normalize t with | Type.Prim Type.Text -> deserialize_text env get_elembuf | Type.Obj (Type.Actor, _) - | Type.Func (Type.Sharable, _, _, _, _) -> get_elembuf ^^ Dfinity.box_reference env + | Type.Func (Type.Shared, _, _, _, _) -> get_elembuf ^^ Dfinity.box_reference env | _ -> let (set_data_size, get_data_size) = new_local env "data_size" in let (set_refs_size, get_refs_size) = new_local env "refs_size" in @@ -3460,7 +3459,7 @@ module Serialization = struct match normalize t with | Prim Text -> DataBuf | Obj (Actor, _) -> ActorRef - | Func (Sharable, _, _, _, _) -> FuncRef + | Func (Shared, _, _, _, _) -> FuncRef | t' when has_no_references t' -> DataBuf | _ -> ElemBuf @@ -4136,7 +4135,7 @@ module FuncDec = struct (* Compile a closed function declaration (captures no local variables) *) let closed pre_env cc name args mk_body at = let (fi, fill) = E.reserve_fun pre_env name in - if cc.Call_conv.sort = Type.Sharable + if cc.Call_conv.sort = Type.Shared then begin declare_dfinity_type pre_env false fi args; ( SR.StaticMessage fi, fun env ae -> @@ -4150,7 +4149,7 @@ module FuncDec = struct (* Compile a closure declaration (captures local variables) *) let closure env ae cc name captured args mk_body at = - let is_local = cc.Call_conv.sort <> Type.Sharable in + let is_local = cc.Call_conv.sort <> Type.Shared in let (set_clos, get_clos) = new_local env (name ^ "_clos") in @@ -5417,7 +5416,7 @@ and compile_exp (env : E.t) ae exp = compile_exp_as env ae (StackRep.of_arity cc.Call_conv.n_args) e2 ^^ get_clos ^^ Closure.call_closure env cc - | _, Type.Sharable -> + | _, Type.Shared -> let (set_funcref, get_funcref) = new_local env "funcref" in code1 ^^ StackRep.adjust env fun_sr SR.UnboxedReference ^^ set_funcref ^^ @@ -5463,7 +5462,7 @@ and compile_exp (env : E.t) ae exp = if Freevars.M.is_empty (Freevars.diff captured prelude_names) then actor_lit env i ds fs exp.at else todo_trap env "non-closed actor" (Arrange_ir.exp exp) - | NewObjE ((Type.Object _ (*sharing*) | Type.Module), fs, _) -> + | NewObjE ((Type.Object | Type.Module), fs, _) -> SR.Vanilla, let fs' = fs |> List.map (fun (f : Ir.field) -> (f.it.name, fun () -> diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 72229ebe0c9..ea47c5c6777 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -114,7 +114,7 @@ let check_shared env at t = if env.flavor.Ir.serialized then check env at (T.is_serialized t) "message argument is not serialized:\n %s" (T.string_of_typ_expand t) - else check env at (T.sub t T.Shared) + else check env at (T.shared t) "message argument is not sharable:\n %s" (T.string_of_typ_expand t) let check_concrete env at t = @@ -137,7 +137,6 @@ let rec check_typ env typ : unit = end | T.Any -> () | T.Non -> () - | T.Shared -> () | T.Prim _ -> () | T.Array typ -> check_typ env typ @@ -159,12 +158,13 @@ let rec check_typ env typ : unit = error env no_region "promising function with non-async result type \n %s" (T.string_of_typ_expand t2) end; - if sort = T.Sharable then begin + if sort = T.Shared then begin List.iter (fun t -> check_shared env no_region t) ts1; match ts2 with | [] -> () | [T.Async t2] -> - check_sub env' no_region t2 T.Shared; + check env' no_region (T.shared t2) + "message result is not sharable:\n %s" (T.string_of_typ_expand t2) | _ -> error env no_region "shared function has non-async result type\n %s" (T.string_of_typ_expand (T.seq ts2)) end @@ -189,7 +189,11 @@ let rec check_typ env typ : unit = check env no_region env.flavor.Ir.serialized "Serialized in non-serialized flavor"; check_typ env typ; - check_sub env no_region typ T.Shared + (* TODO: we cannot currently express abstract shared types, + so @serialize is a hack *) + (*check env no_region (T.shared typ) + * "serialized type is not sharable:\n %s" (T.string_of_typ_expand typ) + *) | T.Typ c -> check env no_region (T.ConSet.mem c env.cons) "free type constructor %s" (Con.name c); @@ -214,8 +218,8 @@ and check_typ_field env s typ_field : unit = (s <> Some T.Actor || T.is_func (T.promote typ)) "actor field has non-function type"; check env no_region - ((s <> Some T.Actor && s <> Some (T.Object T.Sharable)) || T.sub typ T.Shared) - "shared object or actor field has non-shared type" + (s <> Some T.Actor || T.shared typ) + "actor field has non-shared type" end and check_typ_binds env typ_binds : T.con list * con_env = @@ -406,7 +410,7 @@ let rec check_exp env (exp:Ir.exp) : unit = check_exp env exp2; let t_arg = T.open_ insts t2 in let t_ret = T.open_ insts t3 in - if (call_conv.Call_conv.sort = T.Sharable) then begin + if (call_conv.Call_conv.sort = T.Shared) then begin check_concrete env exp.at t_arg; check_concrete env exp.at t_ret; end; @@ -470,7 +474,7 @@ let rec check_exp env (exp:Ir.exp) : unit = let env' = {env with labs = T.Env.empty; rets = Some t1; async = true} in check_exp env' exp1; - t1 <: T.Shared; + t1 <: T.Any; T.Async t1 <: t | AwaitE exp1 -> check env.flavor.has_await "await in non-await flavor"; @@ -514,17 +518,17 @@ let rec check_exp env (exp:Ir.exp) : unit = let env' = adjoin_cons env ce in let ve = check_args env' args in List.iter (check_typ env') ret_tys; - check ((cc.Call_conv.sort = T.Sharable && Type.is_async (T.seq ret_tys)) + check ((cc.Call_conv.sort = T.Shared && Type.is_async (T.seq ret_tys)) ==> isAsyncE exp) "shared function with async type has non-async body"; - if (cc.Call_conv.sort = T.Sharable) then List.iter (check_concrete env exp.at) ret_tys; + if (cc.Call_conv.sort = T.Shared) then List.iter (check_concrete env exp.at) ret_tys; let env'' = {env' with labs = T.Env.empty; rets = Some (T.seq ret_tys); async = false} in check_exp (adjoin_vals env'' ve) exp; check_sub env' exp.at (typ exp) (T.seq ret_tys); (* Now construct the function type and compare with the annotation *) let ts1 = List.map (fun a -> a.note) args in - if (cc.Call_conv.sort = T.Sharable) then List.iter (check_concrete env exp.at) ts1; + if (cc.Call_conv.sort = T.Shared) then List.iter (check_concrete env exp.at) ts1; let fun_ty = T.Func ( cc.Call_conv.sort, cc.Call_conv.control , tbs, List.map (T.close cs) ts1, List.map (T.close cs) ret_tys @@ -682,8 +686,8 @@ and type_exp_field env s f : T.field = if not (T.is_typ t) then begin check env f.at ((s = T.Actor) ==> T.is_func t) "public actor field is not a function"; - check env f.at ((s <> T.Object T.Local && s <> T.Module) ==> T.sub t T.Shared) - "public shared object or actor field has non-shared type"; + check env f.at ((s = T.Actor) ==> T.shared t) + "public actor field has non-shared type"; end; T.{lab = name; typ = t} diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index 1f78c0c7f2f..f2867a2bb76 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -416,7 +416,7 @@ let (-->*) xs exp = (* n-ary shared lambda *) let (-@>*) xs exp = - let fun_ty = T.Func (T.Sharable, T.Returns, [], List.map typ xs, T.as_seq (typ exp)) in + let fun_ty = T.Func (T.Shared, T.Returns, [], List.map typ xs, T.as_seq (typ exp)) in nary_funcE "$lambda" fun_ty xs exp diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index 9c735b3832f..230d4715aa8 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -166,7 +166,7 @@ let make_unit_message env id v = let open CC in let call_conv, f = V.as_func v in match call_conv with - | {sort = T.Sharable; n_res = 0; _} -> + | {sort = T.Shared; n_res = 0; _} -> Value.message_func call_conv.n_args (fun v k -> actor_msg env id f v (fun _ -> ()); k V.unit @@ -180,7 +180,7 @@ let make_async_message env id v = let open CC in let call_conv, f = V.as_func v in match call_conv with - | {sort = T.Sharable; control = T.Promises; n_res = 1; _} -> + | {sort = T.Shared; control = T.Promises; n_res = 1; _} -> Value.async_func call_conv.n_args (fun v k -> let async = make_async () in actor_msg env id f v (fun v_async -> @@ -424,7 +424,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = let v = V.Func (cc, f) in let v = match cc.sort with - | T.Sharable -> make_message env x cc v + | T.Shared -> make_message env x cc v | _-> v in k v diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index 994dc314150..d0072e39ef3 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -44,7 +44,7 @@ module Transform() = struct let nary typ = T.as_seq typ - let replyT as_seq typ = T.Func(T.Sharable, T.Returns, [], as_seq typ, []) + let replyT as_seq typ = T.Func(T.Shared, T.Returns, [], as_seq typ, []) let fulfillT as_seq typ = T.Func(T.Local, T.Returns, [], as_seq typ, []) @@ -57,7 +57,7 @@ module Transform() = struct T.Func ( T.Local, T.Returns, - [ { var = "T"; bound = T.Shared } ], + [ { var = "T"; bound = T.Any } ], [], new_async_ret unary (T.Var ("T", 0)) ) @@ -111,7 +111,7 @@ module Transform() = struct let isAwaitableFunc exp = match typ exp with - | T.Func (T.Sharable,T.Promises,_,_,[T.Async _]) -> true + | T.Func (T.Shared,T.Promises,_,_,[T.Async _]) -> true | _ -> false let extendTup ts t2 = ts @ [t2] @@ -145,7 +145,7 @@ module Transform() = struct | Func (s, c, tbs, t1, t2) -> begin match s with - | T.Sharable -> + | T.Shared -> begin match t2 with | [] -> @@ -157,7 +157,7 @@ module Transform() = struct extendTup (List.map t_typ t1) (replyT nary (t_typ t2)), []) | _ -> assert false end - | _ -> + | T.Local -> Func (s, c, List.map t_bind tbs, List.map t_typ t1, List.map t_typ t2) end | Opt t -> Opt (t_typ t) @@ -165,7 +165,6 @@ module Transform() = struct | Async t -> t_async nary (t_typ t) | Obj (s, fs) -> Obj (s, List.map t_field fs) | Mut t -> Mut (t_typ t) - | Shared -> Shared | Serialized t -> Serialized (t_typ t) | Any -> Any | Non -> Non @@ -257,7 +256,7 @@ module Transform() = struct | t -> assert false in let k = fresh_var "k" contT in let v1 = fresh_var "v" t1 in - let post = fresh_var "post" (T.Func(T.Sharable,T.Returns,[],[],[])) in + let post = fresh_var "post" (T.Func(T.Shared,T.Returns,[],[],[])) in let u = fresh_var "u" T.unit in let ((nary_async,nary_reply),def) = new_nary_async_reply t1 in (blockE [letP (tupP [varP nary_async; varP nary_reply]) def; @@ -269,7 +268,7 @@ module Transform() = struct | CallE (cc,exp1, typs, exp2) when isAwaitableFunc exp1 -> let ts1,t2 = match typ exp1 with - | T.Func (T.Sharable,T.Promises,tbs,ts1,[T.Async t2]) -> + | T.Func (T.Shared,T.Promises,tbs,ts1,[T.Async t2]) -> List.map t_typ ts1, t_typ t2 | _ -> assert(false) in @@ -322,7 +321,7 @@ module Transform() = struct match s with | T.Local -> FuncE (x, cc, t_typ_binds typbinds, t_args args, List.map t_typ typT, t_exp exp) - | T.Sharable -> + | T.Shared -> begin match typ exp with | T.Tup [] -> diff --git a/src/ir_passes/serialization.ml b/src/ir_passes/serialization.ml index 80c4bf3681c..52811aa5b2d 100644 --- a/src/ir_passes/serialization.ml +++ b/src/ir_passes/serialization.ml @@ -35,12 +35,12 @@ module Transform() = struct let open Type in let var : var = "A" in primE "@deserialize" - (Func (Local, Returns, [{var; bound = Shared}], [Serialized (Var (var, 0))], [(Var (var, 0))])) + (Func (Local, Returns, [{var; bound = Any}], [Serialized (Var (var, 0))], [(Var (var, 0))])) let serialize_prim = let open Type in let var : var = "A" in primE "@serialize" - (Func (Local, Returns, [{var; bound = Shared}], [Var (var, 0)], [Serialized (Var (var, 0))])) + (Func (Local, Returns, [{var; bound = Any}], [Var (var, 0)], [Serialized (Var (var, 0))])) let deserialize e = let t = T.as_serialized e.note.note_typ in @@ -71,7 +71,6 @@ module Transform() = struct let rec t_typ (t:T.typ) = match t with | T.Prim _ - | T.Shared | T.Any | T.Non | T.Pre @@ -81,10 +80,10 @@ module Transform() = struct T.Con (t_con c, List.map t_typ ts) | T.Array t -> T.Array (t_typ t) | T.Tup ts -> T.Tup (List.map t_typ ts) - | T.Func (T.Sharable, c, tbs, t1, t2) -> + | T.Func (T.Shared, c, tbs, t1, t2) -> assert (c = T.Returns); assert (t2 = []); (* A returning sharable function has no return values *) - T.Func (T.Sharable, T.Returns, tbs, List.map (fun t -> T.Serialized (t_typ t)) t1, []) + T.Func (T.Shared, T.Returns, tbs, List.map (fun t -> T.Serialized (t_typ t)) t1, []) | T.Func (T.Local, c, tbs, t1, t2) -> T.Func (T.Local, c, List.map t_bind tbs, List.map t_typ t1, List.map t_typ t2) | T.Opt t -> T.Opt (t_typ t) @@ -133,7 +132,7 @@ module Transform() = struct begin match cc.Call_conv.sort with | T.Local -> CallE(cc, t_exp exp1, List.map t_typ typs, t_exp exp2) - | T.Sharable -> + | T.Shared -> (* We should take the type to serialize at from the function, not the argument, as the latter could be a subtype *) let fun_ty = exp1.note.note_typ in @@ -146,7 +145,7 @@ module Transform() = struct begin match cc.Call_conv.sort with | T.Local -> FuncE (x, cc, t_typ_binds typbinds, t_args args, List.map t_typ ret_tys, t_exp exp) - | T.Sharable -> + | T.Shared -> assert (ret_tys = []); let args' = t_args args in let raw_args = List.map serialized_arg args' in diff --git a/src/ir_passes/show.ml b/src/ir_passes/show.ml index 58b78f52249..6ce4b8efb53 100644 --- a/src/ir_passes/show.ml +++ b/src/ir_passes/show.ml @@ -359,7 +359,7 @@ let show_for : T.typ -> Ir.dec * T.typ list = fun t -> define_show t (invoke_text_of_array t' (show_var_for t') (argE t)), [t'] end - | T.Obj (T.Object _, fs) -> + | T.Obj (T.Object, fs) -> define_show t ( cat_list (list_build (textE "{") (textE "; ") (textE "}") diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 8794c6d45d5..9c9be101aa9 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -133,7 +133,7 @@ and mut m = match m.it with and obj at s self_id es obj_typ = match s.it with - | T.Object _ | T.Module -> build_obj at s self_id es obj_typ + | T.Object | T.Module -> build_obj at s self_id es obj_typ | T.Actor -> build_actor at self_id es obj_typ and build_field {T.lab; T.typ} = @@ -382,7 +382,7 @@ and to_args cc p : (Ir.arg list * (Ir.exp -> Ir.exp)) = in let wrap_under_async e = - if cc.Call_conv.sort = T.Sharable && cc.Call_conv.control = T.Promises + if cc.Call_conv.sort = T.Shared && cc.Call_conv.control = T.Promises then match e.it with | Ir.AsyncE e' -> { e with it = Ir.AsyncE (wrap e') } | _ -> assert false diff --git a/src/prelude/prelude.ml b/src/prelude/prelude.ml index 950081d384f..b3d95b99e86 100644 --- a/src/prelude/prelude.ml +++ b/src/prelude/prelude.ml @@ -2,7 +2,6 @@ let prelude = {| type Any = prim "Any"; type None = prim "None"; -type Shared = prim "Shared"; type Null = prim "Null"; type Bool = prim "Bool"; type Nat = prim "Nat"; @@ -305,15 +304,16 @@ func Array_tabulate(len : Nat, gen : Nat -> T) : [T] { (prim "Array.tabulate" : (Nat, Nat -> T) -> [T])(len, gen) }; -type Cont = T -> () ; -type Async = Cont -> (); +type Cont = T -> () ; +type Async = Cont -> (); -func @new_async():(Async, Cont) { - let empty = func k (t:T) = (); +func @new_async() : (Async, Cont) { + let empty = func(t : T) {}; var result : ?T = null; var ks : T -> () = empty; - func fulfill(t:T):() { - switch(result) { + + func fulfill(t : T) { + switch result { case null { result := ?t; let ks_ = ks; @@ -321,17 +321,19 @@ func @new_async():(Async, Cont) { ks_(t); }; case (?t) (assert(false)); - }; }; - func enqueue(k:Cont):() { - switch(result) { + }; + + func enqueue(k : Cont) { + switch result { case null { let ks_ = ks; - ks := (func (t:T) {ks_(t);k(t);}); + ks := (func(t : T) { ks_(t); k(t) }); }; case (?t) (k(t)); }; }; - (enqueue,fulfill) + + (enqueue, fulfill) }; |} diff --git a/stdlib/examples/produce-exchange/profileActor.as b/stdlib/examples/produce-exchange/profileActor.as index 2f9548acb54..9168332e0a0 100644 --- a/stdlib/examples/produce-exchange/profileActor.as +++ b/stdlib/examples/produce-exchange/profileActor.as @@ -8,7 +8,7 @@ actor server { // private var dummy = { func scaledParams(region_count_:Nat, factor:Nat) : T.WorkloadParams = { - shared { + new { region_count = region_count_:Nat; day_count = 3:Nat; max_route_duration = 1:Nat; diff --git a/stdlib/examples/produce-exchange/serverActor.as b/stdlib/examples/produce-exchange/serverActor.as index cb9824bd8c2..64dc812e0b4 100644 --- a/stdlib/examples/produce-exchange/serverActor.as +++ b/stdlib/examples/produce-exchange/serverActor.as @@ -159,7 +159,7 @@ actor class Server () { // but two other sources exist for each type: the type of `insert` is known, and hence, this record has a known type, // and, the type of each of these `variables` is known, as well. - shared { + new { id=id_ :T.TruckTypeId; short_name=short_name_:Text; description=description_:Text; @@ -229,7 +229,7 @@ actor class Server () { Result.fromSome( getModel().regionTable.addInfoGetId( func (id_:T.RegionId) : T.RegionInfo = - shared { + new { id = id_:T.RegionId; short_name=short_name_:Text; description=description_:Text @@ -306,7 +306,7 @@ actor class Server () { Result.fromSome( getModel().produceTable.addInfoGetId( func (id_:T.ProduceId) : T.ProduceInfo = - shared { + new { id = id_:T.ProduceId; short_name=short_name_:Text; description=description_:Text; @@ -378,7 +378,7 @@ actor class Server () { Result.fromOption( getModel().producerTable.addInfoGetId( func(id_:T.ProducerId):T.ProducerInfo { - shared { + new { id=id_:T.ProducerId; public_key=producer_public_key; short_name=short_name_:Text; @@ -455,7 +455,7 @@ actor class Server () { Result.fromOption( getModel().retailerTable.addInfoGetId( func(id_:T.RetailerId):T.RetailerInfo { - shared { + new { id=id_:T.RetailerId; public_key=retailer_public_key; short_name=short_name_:Text; @@ -526,7 +526,7 @@ actor class Server () { Result.fromOption( getModel().transporterTable.addInfoGetId( func(id_:T.TransporterId):T.TransporterInfo { - shared { + new { id=id_:T.TransporterId; public_key=transporter_public_key; short_name=short_name_:Text; @@ -921,7 +921,7 @@ actor class Server () { getCounts() : async T.ProduceExchangeCounts { let m = getModel(); - shared { + new { hash_bit_length = 0; truck_type_count = m.truckTypeTable.count(); region_count = m.regionTable.count(); @@ -1057,7 +1057,7 @@ been processed devTestLoadQuery (region_count:Nat, scale_factor:Nat) { func scaledParams(region_count_:Nat, factor:Nat) : T.WorkloadParams = { - shared { + new { region_count = region_count_:Nat; day_count = 3:Nat; max_route_duration = 1:Nat; diff --git a/stdlib/examples/produce-exchange/serverLang.as b/stdlib/examples/produce-exchange/serverLang.as index 936a6bef19f..d6b8be18af7 100644 --- a/stdlib/examples/produce-exchange/serverLang.as +++ b/stdlib/examples/produce-exchange/serverLang.as @@ -84,7 +84,7 @@ type BulkResp = { } ; -type UserAddReq = shared { +type UserAddReq = new { user_name: Text; public_key: Text; description: Text; @@ -100,7 +100,7 @@ type UserAddReq = shared { ---------------- Note: The `RouteInfo` type contains too much information about truck types to use here in place of this type. */ -type RouteAddReq = shared { +type RouteAddReq = new { id : T.RouteId; transporter : T.TransporterId; truck_type : T.TruckTypeId; diff --git a/stdlib/examples/produce-exchange/serverModel.as b/stdlib/examples/produce-exchange/serverModel.as index 60251292b19..072768b53ad 100644 --- a/stdlib/examples/produce-exchange/serverModel.as +++ b/stdlib/examples/produce-exchange/serverModel.as @@ -171,7 +171,7 @@ class Model() { case (#add (#truckType info)) Result.fromSomeMap( truckTypeTable.addInfoGetId( func (id_:T.TruckTypeId) : T.TruckTypeInfo = - shared { + new { id=id_; short_name=info.short_name; description=info.description; @@ -187,7 +187,7 @@ class Model() { case (#add (#region info)) Result.fromSomeMap( regionTable.addInfoGetId( func (id_:T.RegionId) : T.RegionInfo = - shared { + new { id = id_; short_name=info.short_name; description=info.description @@ -200,7 +200,7 @@ class Model() { case (#add (#produce info)) Result.fromSomeMap( produceTable.addInfoGetId( func (id_:T.ProduceId) : T.ProduceInfo = - shared { + new { id = id_; short_name=info.short_name; description=info.description; @@ -214,7 +214,7 @@ class Model() { case (#add (#producer info)) Result.fromSomeMap( producerTable.addInfoGetId( func(id_:T.ProducerId):T.ProducerInfo { - shared { + new { id=id_; public_key=info.public_key; short_name=info.short_name; @@ -232,7 +232,7 @@ class Model() { case (#add (#transporter info)) Result.fromSomeMap( transporterTable.addInfoGetId( func(id_:T.TransporterId):T.TransporterInfo { - shared { + new { id=id_; public_key=info.public_key; short_name=info.short_name; @@ -249,7 +249,7 @@ class Model() { case (#add (#retailer info)) Result.fromSomeMap( retailerTable.addInfoGetId( func(id_:T.RetailerId):T.RetailerInfo { - shared { + new { id=id_; public_key=info.public_key; short_name=info.short_name; @@ -451,7 +451,7 @@ class Model() { for (i in range(0, 1)) { reqs := ?( #truckType ( - shared { + new { id=i; short_name=""; description=""; capacity=i * 50; isFridge=true; isFreezer=true @@ -460,19 +460,19 @@ class Model() { }; /**- add regions */ for (i in range(0, region_count - 1)) { - reqs := ?(#region (shared { + reqs := ?(#region (new { id=i; short_name=""; description="" }), reqs); }; /**- add produce types, one per region. */ for (i in range(0, region_count - 1)) { - reqs := ?(#produce (shared { + reqs := ?(#produce (new { id=i; short_name=""; description=""; grade=1; }), reqs); }; /**- add producers */ for (i in range(0, producer_count - 1)) { - reqs := ?(#producer (shared { + reqs := ?(#producer (new { id=i; public_key=""; short_name=""; description=""; region=(i % region_count); inventory=[]; reserved=[]; @@ -480,14 +480,14 @@ class Model() { }; /**- add transporters */ for (i in range(0, producer_count - 1)) { - reqs := ?(#transporter (shared { + reqs := ?(#transporter (new { id=i; public_key=""; short_name=""; description=""; routes=[]; reserved=[]; }), reqs); }; /**- add retailers */ for (i in range(0, retailer_count - 1)) { - reqs := ?(#retailer (shared { + reqs := ?(#retailer (new { id=i; public_key=""; short_name=""; description=""; region=(i % region_count); }), reqs); @@ -513,7 +513,7 @@ class Model() { /**- choose this producer iff they are located in the start region: */ if ((p % region_count) == start_reg) { reqs := ?(#inventory - (shared { + (new { id=666; producer = p; produce = start_reg; @@ -535,7 +535,7 @@ class Model() { /**- choose this transporter iff their id matches the id of the region, modulo the number of regions: */ if ((t % region_count) == start_reg) { reqs := ?(#route - (shared { + (new { id=666; transporter = t; start_region = start_reg; @@ -692,7 +692,7 @@ secondary maps. func(x:T.UserId):T.UserId{x+1}, func(x:T.UserId,y:T.UserId):Bool{x==y}, idHash, - func(doc:M.UserDoc):T.UserInfo = shared { + func(doc:M.UserDoc):T.UserInfo = new { id=doc.id; user_name=doc.user_name; public_key=doc.public_key; @@ -728,7 +728,7 @@ secondary maps. func(x:T.TruckTypeId):T.TruckTypeId{x+1}, func(x:T.TruckTypeId,y:T.TruckTypeId):Bool{x==y}, idHash, - func(doc:M.TruckTypeDoc):T.TruckTypeInfo = shared { + func(doc:M.TruckTypeDoc):T.TruckTypeInfo = new { id=doc.id; short_name=doc.short_name; description=doc.description; @@ -757,7 +757,7 @@ secondary maps. func(x:T.RegionId):T.RegionId{x+1}, func(x:T.RegionId,y:T.RegionId):Bool{x==y}, idHash, - func(doc:M.RegionDoc):T.RegionInfo = shared { + func(doc:M.RegionDoc):T.RegionInfo = new { id=doc.id; short_name=doc.short_name; description=doc.description; @@ -780,7 +780,7 @@ secondary maps. func(x:T.ProduceId):T.ProduceId{x+1}, func(x:T.ProduceId,y:T.ProduceId):Bool{x==y}, idHash, - func(doc:M.ProduceDoc):T.ProduceInfo = shared { + func(doc:M.ProduceDoc):T.ProduceInfo = new { id=doc.id; short_name=doc.short_name; description=doc.description; @@ -805,7 +805,7 @@ secondary maps. func(x:T.ProducerId):T.ProducerId{x+1}, func(x:T.ProducerId,y:T.ProducerId):Bool{x==y}, idHash, - func(doc:M.ProducerDoc):T.ProducerInfo = shared { + func(doc:M.ProducerDoc):T.ProducerInfo = new { id=doc.id; public_key=doc.public_key; short_name=doc.short_name; @@ -841,7 +841,7 @@ secondary maps. func(x:T.InventoryId):T.InventoryId{x+1}, func(x:T.InventoryId,y:T.InventoryId):Bool{x==y}, idHash, - func(doc:M.InventoryDoc):T.InventoryInfo = shared { + func(doc:M.InventoryDoc):T.InventoryInfo = new { id=doc.id; produce=doc.produce.id; producer=doc.producer; @@ -887,7 +887,7 @@ secondary maps. func(x:T.TransporterId):T.TransporterId{x+1}, func(x:T.TransporterId,y:T.TransporterId):Bool{x==y}, idHash, - func(doc:M.TransporterDoc):T.TransporterInfo = shared { + func(doc:M.TransporterDoc):T.TransporterInfo = new { id=doc.id; public_key=doc.public_key; short_name=doc.short_name; @@ -917,7 +917,7 @@ secondary maps. func(x:T.RetailerId):T.RetailerId{x+1}, func(x:T.RetailerId,y:T.RetailerId):Bool{x==y}, idHash, - func(doc:M.RetailerDoc):T.RetailerInfo = shared { + func(doc:M.RetailerDoc):T.RetailerInfo = new { id=doc.id; public_key=doc.public_key; short_name=doc.short_name; @@ -955,7 +955,7 @@ secondary maps. func(x:T.RouteId):T.RouteId{x+1}, func(x:T.RouteId,y:T.RouteId):Bool{x==y}, idHash, - func(doc:M.RouteDoc):T.RouteInfo = shared { + func(doc:M.RouteDoc):T.RouteInfo = new { id=doc.id; transporter=doc.transporter; truck_type=(truckTypeTable.getInfoOfDoc())(doc.truck_type); @@ -999,10 +999,10 @@ secondary maps. func(x:T.ReservedInventoryId):T.ReservedInventoryId{x+1}, func(x:T.ReservedInventoryId,y:T.ReservedInventoryId):Bool{x==y}, idHash, - func(doc:M.ReservedInventoryDoc):T.ReservedInventoryInfo = shared { + func(doc:M.ReservedInventoryDoc):T.ReservedInventoryInfo = new { id=doc.id; retailer=doc.retailer; - item=shared { + item=new { id=doc.item.id; produce=doc.item.produce.id; producer=doc.item.producer; @@ -1042,13 +1042,13 @@ secondary maps. func(x:T.ReservedRouteId):T.ReservedRouteId{x+1}, func(x:T.ReservedRouteId,y:T.ReservedRouteId):Bool{x==y}, idHash, - func(doc:M.ReservedRouteDoc):T.ReservedRouteInfo = shared { + func(doc:M.ReservedRouteDoc):T.ReservedRouteInfo = new { id=doc.id; retailer=doc.retailer; - route=shared { + route=new { id=doc.route.id; transporter=doc.route.transporter; - truck_type=shared { + truck_type=new { id=doc.route.truck_type.id; short_name=doc.route.truck_type.short_name; description=doc.route.truck_type.description; @@ -1237,7 +1237,7 @@ than the MVP goals, however. /**- Create a producer role for the user: */ let prId = if isProducer { producerTable.addInfoGetId( func(id_:T.ProducerId):T.ProducerInfo { - shared { + new { id=id_:T.ProducerId; public_key=public_key_; short_name=user_name_; @@ -1251,7 +1251,7 @@ than the MVP goals, however. /**- Create a transporter role for the user: */ let trId = if isTransporter { transporterTable.addInfoGetId( func(id_:T.TransporterId):T.TransporterInfo { - shared { + new { id=id_:T.TransporterId; public_key=public_key_; short_name=user_name_; @@ -1264,7 +1264,7 @@ than the MVP goals, however. /**- Create a retailer role for the user: */ let rrId = if isRetailer { retailerTable.addInfoGetId( func(id_:T.RetailerId):T.RetailerInfo { - shared { + new { id=id_; public_key=public_key_; short_name=user_name_; @@ -1276,7 +1276,7 @@ than the MVP goals, however. /**- Record the user information: */ let id = userTable.addInfoGetId( func (id_: T.UserId) : T.UserInfo = - shared { + new { id = id_; user_name = user_name_; public_key = public_key_; @@ -1378,7 +1378,7 @@ than the MVP goals, however. let (_, item) = { switch (inventoryTable.addInfoAs(iid_, func(iid:T.InventoryId):T.InventoryInfo{ - shared { + new { id = iid :T.InventoryId; produce = produce_id:T.ProduceId; producer = id_ :T.ProducerId; @@ -1600,7 +1600,7 @@ than the MVP goals, however. /**- Create the route item document: */ let route : M.RouteDoc = { switch (routeTable.addInfoAs(rid_, func(routeId:T.RouteId):T.RouteInfo{ - shared { + new { id= routeId; transporter=transporterId; truck_type=truck_type_; @@ -1816,7 +1816,7 @@ than the MVP goals, however. based on the given inventory and route documents. */ makeReservationInfo(item:M.InventoryDoc, route:M.RouteDoc) : T.ReservationInfo { - shared { + new { produce =item.produce.id :T.ProduceId; producer =item.producer :T.ProducerId; quant =item.quantity :T.Quantity; diff --git a/stdlib/examples/produce-exchange/serverTypes.as b/stdlib/examples/produce-exchange/serverTypes.as index 4d5f52c2d39..79cb5fd7759 100644 --- a/stdlib/examples/produce-exchange/serverTypes.as +++ b/stdlib/examples/produce-exchange/serverTypes.as @@ -136,7 +136,7 @@ Public info associated with Ids ------------- */ -type UserInfo = shared { +type UserInfo = new { id: UserId; public_key: Text; user_name: Text; @@ -153,7 +153,7 @@ type UserInfo = shared { `TruckTypeInfo` ----------------- */ -type TruckTypeInfo = shared { +type TruckTypeInfo = new { id : TruckTypeId; short_name : Text; description : Text; @@ -167,7 +167,7 @@ type TruckTypeInfo = shared { `RegionInfo` ----------------- */ -type RegionInfo = shared { +type RegionInfo = new { id : RegionId; short_name : Text; description : Text; @@ -178,7 +178,7 @@ type RegionInfo = shared { ----------------- */ -type ProduceInfo = shared { +type ProduceInfo = new { id : ProduceId; short_name : Text; description : Text; @@ -190,7 +190,7 @@ type ProduceInfo = shared { ----------------- */ -type ProducerInfo = shared { +type ProducerInfo = new { id : ProducerId; public_key: Text; short_name : Text; @@ -205,7 +205,7 @@ type ProducerInfo = shared { ----------------- */ -type InventoryInfo = shared { +type InventoryInfo = new { id : InventoryId; produce : ProduceId; producer : ProducerId; @@ -222,7 +222,7 @@ type InventoryInfo = shared { ----------------------------- */ -type ReservedInventoryInfo = shared { +type ReservedInventoryInfo = new { id : ReservedInventoryId; retailer : RetailerId; item : InventoryInfo; @@ -234,7 +234,7 @@ type ReservedInventoryInfo = shared { */ // for now, this is the same as a ReservationInfo -type ProduceMarketInfo = shared { +type ProduceMarketInfo = new { produce: ProduceId; producer: ProducerId; quant: Quantity; @@ -255,7 +255,7 @@ type ProduceMarketInfo = shared { ----------------- */ -type RetailerInfo = shared { +type RetailerInfo = new { id : RetailerId; public_key: Text; short_name : Text; @@ -268,7 +268,7 @@ type RetailerInfo = shared { ----------------- */ -type TransporterInfo = shared { +type TransporterInfo = new { id : TransporterId; public_key: Text; // no region; the transporters are the supply of routes, not "end @@ -284,7 +284,7 @@ type TransporterInfo = shared { ----------------- */ -type RouteInfo = shared { +type RouteInfo = new { id : RouteId; transporter : TransporterId; truck_type : TruckTypeInfo; @@ -300,7 +300,7 @@ type RouteInfo = shared { ----------------- */ -type ReservedRouteInfo = shared { +type ReservedRouteInfo = new { id : ReservedRouteId; retailer : RetailerId; route : RouteInfo; @@ -311,7 +311,7 @@ type ReservedRouteInfo = shared { ----------------- */ -type ReservationInfo = shared { +type ReservationInfo = new { produce: ProduceId; producer: ProducerId; quant: Quantity; @@ -338,7 +338,7 @@ type ReservationInfo = shared { Developer-level, counter-based information about the exchange, including counts of each kind of entity. */ -type ProduceExchangeCounts = shared { +type ProduceExchangeCounts = new { hash_bit_length : Nat; truck_type_count : Nat; region_count : Nat; @@ -394,7 +394,7 @@ type QueryAllResults = [QueryAllResult]; The server can generate synthetic workloads given a small set of parameters. */ -type WorkloadParams = shared { +type WorkloadParams = new { day_count:Nat; max_route_duration:Nat; producer_count:Nat; diff --git a/test/fail/abstract-msgs.as b/test/fail/abstract-msgs.as index 10d5e595e45..c3dbe6889f7 100644 --- a/test/fail/abstract-msgs.as +++ b/test/fail/abstract-msgs.as @@ -1,35 +1,23 @@ // In function definitions, parameters with abstract types are not fine -{ shared func foo( x : A ) : () = (); }; -{ shared func foo() : ?A = null; }; -{ func foo() : () = { +{ shared func foo( x : A ) : () = (); }; +{ shared func foo() : ?A = null; }; +{ func foo() : () = { { shared func bar( x : A ) : () = (); }; { shared func bar() : async ?A { null } }; }}; // In function calls, parameters with abstract types are not fine -{ func foo( f : shared A -> (), x : A ) = (f x); }; -{ func foo( f : shared () -> async A ) : async A = async { await (f ())}; }; +{ func foo( f : shared A -> (), x : A ) = (f x); }; +{ func foo( f : shared () -> async A ) : async A = async { await (f ())}; }; // Just in types, away from definitinos and calls, parameters with abstract types are fine -{ let x : ?(shared A -> ()) = null; }; -{ let x : ?(shared () -> async A) = null; }; -{ let x : ?((shared A -> ()) -> ()) = null; }; -{ let x : ?((shared () -> async A) -> ()) = null; }; +{ let x : ?(shared A -> ()) = null; }; +{ let x : ?(shared () -> async A) = null; }; +{ let x : ?((shared A -> ()) -> ()) = null; }; +{ let x : ?((shared () -> async A) -> ()) = null; }; -// This is mostly because type aliases can have message arguments with type -// variables, as long as they are instantiated with concrete types. So this -// whould be fine: -{ type X = shared B -> (); - shared func foo ( f: X ) = (); -}; - -// But this not -{ type X = shared B -> (); - func foo() { shared func foo(f: X) = (); () } -}; - -// Also, phantom parameters are fine -{ type X = shared () -> (); - func foo() { shared func foo(f: X) = (); () } +// Phantom parameters are fine +{ type X = shared () -> (); + func foo() { shared func bar(f : X) = (); () } }; diff --git a/test/fail/argument-subtyping.as b/test/fail/argument-subtyping.as index 3eac941731e..65147672da6 100644 --- a/test/fail/argument-subtyping.as +++ b/test/fail/argument-subtyping.as @@ -1,9 +1,12 @@ // Normal function allow subtyping { func foo(h : Int -> ()) : (Nat -> ()) = h }; -// Shared functions are invariant for now +// Shared functions do, too { func foo(h : shared Int -> ()) : (shared Nat -> ()) = h }; // The same with abstract types -{ func foo(h : (shared {}) -> ()) : ((shared{x:Nat}) -> ()) = h }; -{ func foo(h : shared (shared {}) -> ()) : (shared (shared {x:Nat}) -> ()) = h }; +{ func foo(h : {} -> ()) : ({x : Nat} -> ()) = h }; +{ func foo(h : shared {} -> ()) : (shared {x : Nat} -> ()) = h }; + +// But not incomaptible types +{ func foo(h : shared Nat -> ()) : (shared Text -> ()) = h }; diff --git a/test/fail/asyncret1.as b/test/fail/asyncret1.as index 2c5059b6dda..7d20d7883aa 100644 --- a/test/fail/asyncret1.as +++ b/test/fail/asyncret1.as @@ -1 +1 @@ -func call3(f : shared () -> C) : C { f (); }; +func call3(f : shared () -> C) : C { f (); }; diff --git a/test/fail/objpat-infer.as b/test/fail/objpat-infer.as index e5ff3c8a710..0669afe2e17 100644 --- a/test/fail/objpat-infer.as +++ b/test/fail/objpat-infer.as @@ -1,10 +1,10 @@ // checks -ignore (switch (shared {}) { case {a} 42 }); +ignore (switch (object {}) { case {a} 42 }); // checks -for ({} in [shared {}].vals()) { print "hey" }; +for ({} in [object {}].vals()) { print "hey" }; // infers @@ -12,12 +12,12 @@ func foo ({}) : Int = 42; // infers -shared func baz ({}) : Int = 42; +shared func baz (a : actor {}) : async Int { 42 }; // call it ignore (foo (new {})); -ignore (foo (shared {})); +ignore (foo (object {})); ignore (foo (actor {})); let a = actor { bar ({}) : async Nat = async 25 }; @@ -25,9 +25,9 @@ ignore (foo a); ignore (baz (new {})); -ignore (baz (shared {})); +ignore (baz (object {})); ignore (baz (actor {})); ignore (a.bar (new {})); -ignore (a.bar (shared {})); +ignore (a.bar (object {})); ignore (a.bar (actor {})); diff --git a/test/fail/ok/abstract-msgs.tc.ok b/test/fail/ok/abstract-msgs.tc.ok index 8b869759f92..5358c1e7327 100644 --- a/test/fail/ok/abstract-msgs.tc.ok +++ b/test/fail/ok/abstract-msgs.tc.ok @@ -1,14 +1,20 @@ -abstract-msgs.as:2.31-2.40: type error, shared function parameter contains abstract type +abstract-msgs.as:2.28-2.37: type error, shared function has non-shared parameter type A/19 -abstract-msgs.as:3.36-3.38: type error, shared function has non-async result type +abstract-msgs.as:3.33-3.35: type error, shared function has non-async result type ?A/21 -abstract-msgs.as:5.20-5.29: type error, shared function parameter contains abstract type +abstract-msgs.as:5.20-5.29: type error, shared function has non-shared parameter type A/23 -abstract-msgs.as:6.25-6.33: type error, shared function result contains abstract type +abstract-msgs.as:6.31-6.33: type error, async has non-shared content type ?A/23 -abstract-msgs.as:10.58-10.59: type error, shared function argument contains abstract type +abstract-msgs.as:10.34-10.35: type error, shared function has non-shared parameter type A/25 -abstract-msgs.as:11.82-11.84: type error, shared function call result contains abstract type - async A/27 -abstract-msgs.as:29.44-29.53: type error, shared function parameter contains abstract type - X/1 = shared A/37 -> () +abstract-msgs.as:11.46-11.47: type error, async has non-shared content type + A/27 +abstract-msgs.as:14.30-14.31: type error, shared function has non-shared parameter type + A/29 +abstract-msgs.as:15.42-15.43: type error, async has non-shared content type + A/31 +abstract-msgs.as:16.31-16.32: type error, shared function has non-shared parameter type + A/33 +abstract-msgs.as:17.43-17.44: type error, async has non-shared content type + A/35 diff --git a/test/fail/ok/argument-subtyping.tc.ok b/test/fail/ok/argument-subtyping.tc.ok index 81609c59caa..2f9ad83d739 100644 --- a/test/fail/ok/argument-subtyping.tc.ok +++ b/test/fail/ok/argument-subtyping.tc.ok @@ -1,8 +1,4 @@ -argument-subtyping.as:5.57-5.58: type error, expression of type - shared Int -> () -cannot produce expected type +argument-subtyping.as:12.58-12.59: type error, expression of type shared Nat -> () -argument-subtyping.as:9.94-9.95: type error, expression of type - shared (shared {}) -> () cannot produce expected type - shared (shared {x : Nat}) -> () + shared Text -> () diff --git a/test/fail/ok/asyncret1.tc.ok b/test/fail/ok/asyncret1.tc.ok index 80b0257d1cf..ca6952b3eaa 100644 --- a/test/fail/ok/asyncret1.tc.ok +++ b/test/fail/ok/asyncret1.tc.ok @@ -1,2 +1,2 @@ -asyncret1.as:1.42-1.43: type error, shared function has non-async result type +asyncret1.as:1.39-1.40: type error, shared function has non-async result type C/1 diff --git a/test/fail/ok/asyncret3.tc.ok b/test/fail/ok/asyncret3.tc.ok index 9bd82d6175d..d42f77fb1b0 100644 --- a/test/fail/ok/asyncret3.tc.ok +++ b/test/fail/ok/asyncret3.tc.ok @@ -1 +1 @@ -asyncret3.as:1.61-1.64: type error, shared function with async type has non-async body +asyncret3.as:1.61-1.64: type error, shared function with async result type has non-async body diff --git a/test/fail/ok/issue103.tc.ok b/test/fail/ok/issue103.tc.ok index d0f8ed19484..cb4947dde21 100644 --- a/test/fail/ok/issue103.tc.ok +++ b/test/fail/ok/issue103.tc.ok @@ -2,7 +2,7 @@ issue103.as:3.29-3.40: type error, shared function has non-shared parameter type () -> Nat issue103.as:10.29-10.46: type error, shared function has non-shared parameter type {foo : () -> Nat} -issue103.as:17.29-17.40: type error, async type has non-shared parameter type +issue103.as:17.29-17.40: type error, async has non-shared content type () -> Nat -issue103.as:24.29-24.48: type error, async type has non-shared parameter type +issue103.as:24.29-24.48: type error, async has non-shared content type {foo : () -> Nat} diff --git a/test/fail/ok/objpat-infer.tc.ok b/test/fail/ok/objpat-infer.tc.ok index d2a44371dd2..2d3042e069b 100644 --- a/test/fail/ok/objpat-infer.tc.ok +++ b/test/fail/ok/objpat-infer.tc.ok @@ -1,33 +1,21 @@ objpat-infer.as:3.36-3.37: type error, object field a is not contained in expected type - shared {} -objpat-infer.as:15.17-15.21: type error, shared function has non-shared parameter type - {} -objpat-infer.as:20.14-20.23: type error, expression of type - shared {} -cannot produce expected type {} objpat-infer.as:21.14-21.22: type error, expression of type actor {} cannot produce expected type {} -objpat-infer.as:23.21-23.25: type error, shared function has non-shared parameter type - {} objpat-infer.as:24.13-24.14: type error, expression of type actor {bar : shared {} -> async Nat} cannot produce expected type {} -objpat-infer.as:28.14-28.23: type error, expression of type - shared {} -cannot produce expected type +objpat-infer.as:27.14-27.20: type error, expression of type {} -objpat-infer.as:29.14-29.22: type error, expression of type - actor {} cannot produce expected type + actor {} +objpat-infer.as:28.14-28.23: type error, expression of type {} -objpat-infer.as:32.16-32.25: type error, expression of type - shared {} cannot produce expected type - {} + actor {} objpat-infer.as:33.16-33.24: type error, expression of type actor {} cannot produce expected type diff --git a/test/fail/ok/pat-inconsistent.tc.ok b/test/fail/ok/pat-inconsistent.tc.ok index 4742eea9d3a..3a02fd6bf1e 100644 --- a/test/fail/ok/pat-inconsistent.tc.ok +++ b/test/fail/ok/pat-inconsistent.tc.ok @@ -86,9 +86,9 @@ left consumes Nat right consumes Any -pat-inconsistent.as:30.16-30.35: type error, pattern branches have incompatible types, +pat-inconsistent.as:30.16-30.32: type error, pattern branches have incompatible types, left consumes - Shared + Any right consumes Float pat-inconsistent.as:31.16-31.31: type error, pattern branches have incompatible types, diff --git a/test/fail/ok/use-before-define5.wasm.stderr.ok b/test/fail/ok/use-before-define5.wasm.stderr.ok index 3bdcd030757..ae7d5dd979a 100644 --- a/test/fail/ok/use-before-define5.wasm.stderr.ok +++ b/test/fail/ok/use-before-define5.wasm.stderr.ok @@ -4,7 +4,7 @@ non-closed actor: (ActorE (VarP foo) (FuncE foo - (shared 0 -> 0) + (shared 0 -> 0) () (AssertE (RelE Nat (VarE x) EqOp (LitE (NatLit 1)))) ) diff --git a/test/fail/pat-inconsistent.as b/test/fail/pat-inconsistent.as index 04b5cb06712..b24ff39b4e9 100644 --- a/test/fail/pat-inconsistent.as +++ b/test/fail/pat-inconsistent.as @@ -27,7 +27,7 @@ let _ = func(#A or #B(_ : Nat)) {}; { let _ = func(#A(0) or #A("")) {}; }; { let _ = func(1 or (_ : Any)) {} }; -{ let _ = func((_ : Shared) or 1.4) {} }; +{ let _ = func((_ : Any) or 1.4) {} }; { let _ = func(() or (_ : Any)) {} }; { let _ = func("" or (_ : A)) {} }; { let _ = func((_ : Any) or (_ : [Nat])) {} }; diff --git a/test/repl/ok/type-lub-repl.stdout.ok b/test/repl/ok/type-lub-repl.stdout.ok index 60f200a9828..414f1561517 100644 --- a/test/repl/ok/type-lub-repl.stdout.ok +++ b/test/repl/ok/type-lub-repl.stdout.ok @@ -22,9 +22,9 @@ ActorScript 0.1 interpreter > 11 : Nat > [func, func] : [({#bar} -> ())] > > > [[42], [25], [77]] : [[Any]] -> [42, 77, [1, 2, 3]] : [Shared] -> [77, [1, 2, 3], 42] : [Shared] -> [func, func] : [(Int -> Int)] +> [42, 77, [1, 2, 3]] : [Any] +> [77, [1, 2, 3], 42] : [Any] +> [func, func] : [(Nat -> Int)] > 25 : Int > 42 : Int > func : (C, D) -> [C] diff --git a/test/run-dfinity/chatpp.as b/test/run-dfinity/chatpp.as index 570618a5260..f107bd3468d 100644 --- a/test/run-dfinity/chatpp.as +++ b/test/run-dfinity/chatpp.as @@ -1,6 +1,6 @@ type List = ?{head : T; var tail : List}; -type Subscription = shared { +type Subscription = { post : shared Text -> (); // revokable by Server cancel : shared () -> (); }; @@ -33,7 +33,7 @@ actor class Server() = { nextId += 1; let cs = new {head = c; var tail = clients}; clients := ?cs; - return (shared { + return (new { post = shared func(message : Text) { if (not c.revoked) broadcast(c.id, message); }; diff --git a/test/run-dfinity/data-params.as b/test/run-dfinity/data-params.as index 42c52076183..be0da0b8757 100644 --- a/test/run-dfinity/data-params.as +++ b/test/run-dfinity/data-params.as @@ -33,7 +33,7 @@ let a = actor { printInt(c); print("\n"); }; - increcord(a : shared { x : Nat; y : Nat }) : () { + increcord(a : { x : Nat; y : Nat }) : () { c += a.x; c += a.y; printInt(c); @@ -99,8 +99,8 @@ a.incnested(7,(8,9)); a.incarray([10,11,12,13]); a.incopt(null); a.incopt(?14); -a.increcord(shared {x = 15; y = 16}); -a.increcord(shared {x = 17; y = 18; z = 19}); +a.increcord(new {x = 15; y = 16}); +a.increcord(new {x = 17; y = 18; z = 19}); a.incVariant(#foo 20); a.incVariant(#bar 20); a.printCounter(); diff --git a/test/run-dfinity/ok/counter-class.wasm.stderr.ok b/test/run-dfinity/ok/counter-class.wasm.stderr.ok index 80644982323..2677c7e0195 100644 --- a/test/run-dfinity/ok/counter-class.wasm.stderr.ok +++ b/test/run-dfinity/ok/counter-class.wasm.stderr.ok @@ -5,10 +5,10 @@ non-closed actor: (ActorE (VarP dec) (FuncE dec - (shared 0 -> 0) + (shared 0 -> 0) () (BlockE - (LetD WildP (CallE ( 1 -> 0) (VarE showCounter) (VarE j))) + (LetD WildP (CallE (1 -> 0) (VarE showCounter) (VarE j))) (AssignE (VarE j) (BinE Int (VarE j) SubOp (LitE (IntLit 1)))) ) ) @@ -17,7 +17,7 @@ non-closed actor: (ActorE (VarP read) (FuncE read - (shared 1 -> 0) + (shared 1 -> 0) (params $k/0/raw) () (BlockE @@ -25,7 +25,7 @@ non-closed actor: (ActorE (TupP (VarP $k/0)) (TupE (CallE - ( 1 -> 1) + (1 -> 1) (PrimE @deserialize) shared (serialized Int) -> () (VarE $k/0/raw) @@ -33,23 +33,23 @@ non-closed actor: (ActorE ) ) (CallE - ( 1 -> 0) + (1 -> 0) (FuncE $lambda - ( 1 -> 0) + (1 -> 0) (params $cont/0) () - (CallE ( 1 -> 0) (VarE $cont/0) (VarE j)) + (CallE (1 -> 0) (VarE $cont/0) (VarE j)) ) (FuncE $lambda - ( 1 -> 0) + (1 -> 0) (params $y/0) () (CallE - (shared 1 -> 0) + (shared 1 -> 0) (VarE $k/0) - (CallE ( 1 -> 1) (PrimE @serialize) Int (VarE $y/0)) + (CallE (1 -> 1) (PrimE @serialize) Int (VarE $y/0)) ) ) ) diff --git a/test/run-dfinity/shared-object.as b/test/run-dfinity/shared-object.as index 10adf637b5a..1ae89ea1b23 100644 --- a/test/run-dfinity/shared-object.as +++ b/test/run-dfinity/shared-object.as @@ -1,6 +1,6 @@ -type Shob = shared { a : Int; b : { c : ?Nat } }; +type Shob = { a : Int; b : { c : ?Nat } }; -let foo : Shob = shared { a = 17; b = shared { c = ?25 } }; +let foo : Shob = new { a = 17; b = new { c = ?25 } }; // check whether we can pattern match shared objects diff --git a/test/run-dfinity/transpose.as b/test/run-dfinity/transpose.as index dbd34243c8a..024739e4e73 100644 --- a/test/run-dfinity/transpose.as +++ b/test/run-dfinity/transpose.as @@ -1,6 +1,6 @@ actor foo { - transpose (data : [(Int,Text)]) : async (shared {ints: [Int]; txts: [Text]}) { - return (shared { + transpose (data : [(Int,Text)]) : async {ints: [Int]; txts: [Text]} { + return (new { ints = Array_tabulate(data.len(), func (i:Nat) : Int = (data[i].0)); txts = Array_tabulate(data.len(), func (i:Nat) : Text = (data[i].1)) }) diff --git a/test/run/ok/issue442.run-ir.ok b/test/run/ok/issue442.run-ir.ok index 486c222891b..136d5ad0c79 100644 --- a/test/run/ok/issue442.run-ir.ok +++ b/test/run/ok/issue442.run-ir.ok @@ -1,5 +1,5 @@ -issue442.as:1.11-1.24: warning, this array has type [Shared] because elements have inconsistent types -issue442.as:2.11-2.29: warning, this if has type Shared because branches have inconsistent types, +issue442.as:1.11-1.24: warning, this array has type [Any] because elements have inconsistent types +issue442.as:2.11-2.29: warning, this if has type Any because branches have inconsistent types, true produces Nat false produces diff --git a/test/run/ok/issue442.run-low.ok b/test/run/ok/issue442.run-low.ok index 486c222891b..136d5ad0c79 100644 --- a/test/run/ok/issue442.run-low.ok +++ b/test/run/ok/issue442.run-low.ok @@ -1,5 +1,5 @@ -issue442.as:1.11-1.24: warning, this array has type [Shared] because elements have inconsistent types -issue442.as:2.11-2.29: warning, this if has type Shared because branches have inconsistent types, +issue442.as:1.11-1.24: warning, this array has type [Any] because elements have inconsistent types +issue442.as:2.11-2.29: warning, this if has type Any because branches have inconsistent types, true produces Nat false produces diff --git a/test/run/ok/issue442.run.ok b/test/run/ok/issue442.run.ok index 486c222891b..136d5ad0c79 100644 --- a/test/run/ok/issue442.run.ok +++ b/test/run/ok/issue442.run.ok @@ -1,5 +1,5 @@ -issue442.as:1.11-1.24: warning, this array has type [Shared] because elements have inconsistent types -issue442.as:2.11-2.29: warning, this if has type Shared because branches have inconsistent types, +issue442.as:1.11-1.24: warning, this array has type [Any] because elements have inconsistent types +issue442.as:2.11-2.29: warning, this if has type Any because branches have inconsistent types, true produces Nat false produces diff --git a/test/run/ok/issue442.tc.ok b/test/run/ok/issue442.tc.ok index 486c222891b..136d5ad0c79 100644 --- a/test/run/ok/issue442.tc.ok +++ b/test/run/ok/issue442.tc.ok @@ -1,5 +1,5 @@ -issue442.as:1.11-1.24: warning, this array has type [Shared] because elements have inconsistent types -issue442.as:2.11-2.29: warning, this if has type Shared because branches have inconsistent types, +issue442.as:1.11-1.24: warning, this array has type [Any] because elements have inconsistent types +issue442.as:2.11-2.29: warning, this if has type Any because branches have inconsistent types, true produces Nat false produces diff --git a/test/run/ok/issue442.wasm.stderr.ok b/test/run/ok/issue442.wasm.stderr.ok index 486c222891b..136d5ad0c79 100644 --- a/test/run/ok/issue442.wasm.stderr.ok +++ b/test/run/ok/issue442.wasm.stderr.ok @@ -1,5 +1,5 @@ -issue442.as:1.11-1.24: warning, this array has type [Shared] because elements have inconsistent types -issue442.as:2.11-2.29: warning, this if has type Shared because branches have inconsistent types, +issue442.as:1.11-1.24: warning, this array has type [Any] because elements have inconsistent types +issue442.as:2.11-2.29: warning, this if has type Any because branches have inconsistent types, true produces Nat false produces diff --git a/test/run/ok/type-inference.run-ir.ok b/test/run/ok/type-inference.run-ir.ok index f2ebd9a64d1..2de3eceb85b 100644 --- a/test/run/ok/type-inference.run-ir.ok +++ b/test/run/ok/type-inference.run-ir.ok @@ -1,4 +1,4 @@ -type-inference.as:3.9-3.28: warning, this if has type Shared because branches have inconsistent types, +type-inference.as:3.9-3.28: warning, this if has type Any because branches have inconsistent types, true produces Bool false produces @@ -8,7 +8,7 @@ true produces Bool false produces [var Nat] -type-inference.as:5.9-5.27: warning, this if has type Shared because branches have inconsistent types, +type-inference.as:5.9-5.27: warning, this if has type Any because branches have inconsistent types, true produces Nat false produces @@ -18,7 +18,7 @@ true produces () false produces {} -type-inference.as:11.33-11.41: warning, the switch has type Shared because branches have inconsistent types, +type-inference.as:11.33-11.41: warning, the switch has type Any because branches have inconsistent types, this case produces type Bool the previous produce type @@ -28,10 +28,10 @@ this case produces type Bool the previous produce type [var Nat] -type-inference.as:13.43-13.56: warning, the switch has type Shared because branches have inconsistent types, +type-inference.as:13.43-13.56: warning, the switch has type Any because branches have inconsistent types, this case produces type Int the previous produce type Text -type-inference.as:19.9-19.18: warning, this array has type [Shared] because elements have inconsistent types +type-inference.as:19.9-19.18: warning, this array has type [Any] because elements have inconsistent types type-inference.as:20.9-20.24: warning, this array has type [Any] because elements have inconsistent types diff --git a/test/run/ok/type-inference.run-low.ok b/test/run/ok/type-inference.run-low.ok index f2ebd9a64d1..2de3eceb85b 100644 --- a/test/run/ok/type-inference.run-low.ok +++ b/test/run/ok/type-inference.run-low.ok @@ -1,4 +1,4 @@ -type-inference.as:3.9-3.28: warning, this if has type Shared because branches have inconsistent types, +type-inference.as:3.9-3.28: warning, this if has type Any because branches have inconsistent types, true produces Bool false produces @@ -8,7 +8,7 @@ true produces Bool false produces [var Nat] -type-inference.as:5.9-5.27: warning, this if has type Shared because branches have inconsistent types, +type-inference.as:5.9-5.27: warning, this if has type Any because branches have inconsistent types, true produces Nat false produces @@ -18,7 +18,7 @@ true produces () false produces {} -type-inference.as:11.33-11.41: warning, the switch has type Shared because branches have inconsistent types, +type-inference.as:11.33-11.41: warning, the switch has type Any because branches have inconsistent types, this case produces type Bool the previous produce type @@ -28,10 +28,10 @@ this case produces type Bool the previous produce type [var Nat] -type-inference.as:13.43-13.56: warning, the switch has type Shared because branches have inconsistent types, +type-inference.as:13.43-13.56: warning, the switch has type Any because branches have inconsistent types, this case produces type Int the previous produce type Text -type-inference.as:19.9-19.18: warning, this array has type [Shared] because elements have inconsistent types +type-inference.as:19.9-19.18: warning, this array has type [Any] because elements have inconsistent types type-inference.as:20.9-20.24: warning, this array has type [Any] because elements have inconsistent types diff --git a/test/run/ok/type-inference.run.ok b/test/run/ok/type-inference.run.ok index f2ebd9a64d1..2de3eceb85b 100644 --- a/test/run/ok/type-inference.run.ok +++ b/test/run/ok/type-inference.run.ok @@ -1,4 +1,4 @@ -type-inference.as:3.9-3.28: warning, this if has type Shared because branches have inconsistent types, +type-inference.as:3.9-3.28: warning, this if has type Any because branches have inconsistent types, true produces Bool false produces @@ -8,7 +8,7 @@ true produces Bool false produces [var Nat] -type-inference.as:5.9-5.27: warning, this if has type Shared because branches have inconsistent types, +type-inference.as:5.9-5.27: warning, this if has type Any because branches have inconsistent types, true produces Nat false produces @@ -18,7 +18,7 @@ true produces () false produces {} -type-inference.as:11.33-11.41: warning, the switch has type Shared because branches have inconsistent types, +type-inference.as:11.33-11.41: warning, the switch has type Any because branches have inconsistent types, this case produces type Bool the previous produce type @@ -28,10 +28,10 @@ this case produces type Bool the previous produce type [var Nat] -type-inference.as:13.43-13.56: warning, the switch has type Shared because branches have inconsistent types, +type-inference.as:13.43-13.56: warning, the switch has type Any because branches have inconsistent types, this case produces type Int the previous produce type Text -type-inference.as:19.9-19.18: warning, this array has type [Shared] because elements have inconsistent types +type-inference.as:19.9-19.18: warning, this array has type [Any] because elements have inconsistent types type-inference.as:20.9-20.24: warning, this array has type [Any] because elements have inconsistent types diff --git a/test/run/ok/type-inference.tc.ok b/test/run/ok/type-inference.tc.ok index f2ebd9a64d1..2de3eceb85b 100644 --- a/test/run/ok/type-inference.tc.ok +++ b/test/run/ok/type-inference.tc.ok @@ -1,4 +1,4 @@ -type-inference.as:3.9-3.28: warning, this if has type Shared because branches have inconsistent types, +type-inference.as:3.9-3.28: warning, this if has type Any because branches have inconsistent types, true produces Bool false produces @@ -8,7 +8,7 @@ true produces Bool false produces [var Nat] -type-inference.as:5.9-5.27: warning, this if has type Shared because branches have inconsistent types, +type-inference.as:5.9-5.27: warning, this if has type Any because branches have inconsistent types, true produces Nat false produces @@ -18,7 +18,7 @@ true produces () false produces {} -type-inference.as:11.33-11.41: warning, the switch has type Shared because branches have inconsistent types, +type-inference.as:11.33-11.41: warning, the switch has type Any because branches have inconsistent types, this case produces type Bool the previous produce type @@ -28,10 +28,10 @@ this case produces type Bool the previous produce type [var Nat] -type-inference.as:13.43-13.56: warning, the switch has type Shared because branches have inconsistent types, +type-inference.as:13.43-13.56: warning, the switch has type Any because branches have inconsistent types, this case produces type Int the previous produce type Text -type-inference.as:19.9-19.18: warning, this array has type [Shared] because elements have inconsistent types +type-inference.as:19.9-19.18: warning, this array has type [Any] because elements have inconsistent types type-inference.as:20.9-20.24: warning, this array has type [Any] because elements have inconsistent types diff --git a/test/run/ok/type-inference.wasm.stderr.ok b/test/run/ok/type-inference.wasm.stderr.ok index 5e5cb268e62..73cc0a6f37b 100644 --- a/test/run/ok/type-inference.wasm.stderr.ok +++ b/test/run/ok/type-inference.wasm.stderr.ok @@ -1,5 +1,5 @@ compile_lit: (FloatLit 5.1) -type-inference.as:3.9-3.28: warning, this if has type Shared because branches have inconsistent types, +type-inference.as:3.9-3.28: warning, this if has type Any because branches have inconsistent types, true produces Bool false produces @@ -9,7 +9,7 @@ true produces Bool false produces [var Nat] -type-inference.as:5.9-5.27: warning, this if has type Shared because branches have inconsistent types, +type-inference.as:5.9-5.27: warning, this if has type Any because branches have inconsistent types, true produces Nat false produces @@ -19,7 +19,7 @@ true produces () false produces {} -type-inference.as:11.33-11.41: warning, the switch has type Shared because branches have inconsistent types, +type-inference.as:11.33-11.41: warning, the switch has type Any because branches have inconsistent types, this case produces type Bool the previous produce type @@ -29,10 +29,10 @@ this case produces type Bool the previous produce type [var Nat] -type-inference.as:13.43-13.56: warning, the switch has type Shared because branches have inconsistent types, +type-inference.as:13.43-13.56: warning, the switch has type Any because branches have inconsistent types, this case produces type Int the previous produce type Text -type-inference.as:19.9-19.18: warning, this array has type [Shared] because elements have inconsistent types +type-inference.as:19.9-19.18: warning, this array has type [Any] because elements have inconsistent types type-inference.as:20.9-20.24: warning, this array has type [Any] because elements have inconsistent types diff --git a/test/run/type-definition.as b/test/run/type-definition.as index 51399d9f04f..3ae60c90970 100644 --- a/test/run/type-definition.as +++ b/test/run/type-definition.as @@ -19,5 +19,5 @@ class E(x : U) {r = x.f}; //class F(x : FF) {r = x.a}; //type FF = {a : Int}; -type AA = shared {b : BB}; -type BB = shared {a : ?AA}; +type AA = {b : BB}; +type BB = {a : ?AA}; diff --git a/test/run/type-lub.as b/test/run/type-lub.as index 7e9c6697b24..e52f1d98fcb 100644 --- a/test/run/type-lub.as +++ b/test/run/type-lub.as @@ -42,12 +42,12 @@ let mut_arrs = [[var 42], [var 25], [77]]; // boring // TODO(gabor), mutable fields, see fail/type-inference.as:13 -let sh : Shared = 42; +let sh : Any = 42; let shareds = [sh, 77, [1, 2, 3]]; let shared2s = [77, [1, 2, 3], sh]; let shared_funcs = [ func (a : Int) : Int = a - , func (a : Shared) : Nat = 42 + , func (a : Nat) : Nat = 42 ]; type C = async(?Int); From 01dd5c19ca5156ffeaefdfe3b67e57052903e409 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 15 Jul 2019 13:18:12 +0200 Subject: [PATCH 0257/1176] Add `Any` back to `to_idl_prim`, to replace `Shared` (#567) slipped through the cracks in #560 --- src/codegen/compile.ml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 4a4e02cd10c..443a0f1be6a 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -2797,6 +2797,7 @@ module Serialization = struct | Prim Int64 -> Some 12 | Prim Float -> Some 14 | Prim Text -> Some 15 + | Any -> Some 16 | Non -> Some 17 | _ -> None in From af0000b7070ae379b283a69f118aa3be12d9d835 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Mon, 15 Jul 2019 16:27:01 +0200 Subject: [PATCH 0258/1176] AST-89 Magnitude estimation for Nat/Int64 operations (#549) * bitsize estimation for Nat/Int64 operations * add more tests --- src/codegen/compile.ml | 235 +++++++++++++++---- test/run-dfinity/log-slow.as | 62 +++++ test/trap/ok/powInt32-raise-neg.run-ir.ok | 1 + test/trap/ok/powInt32-raise-neg.run-low.ok | 1 + test/trap/ok/powInt32-raise-neg.run.ok | 1 + test/trap/ok/powInt32-raise-neg.wasm-run.ok | 1 + test/trap/ok/powInt64-lower-fast.run-ir.ok | 1 + test/trap/ok/powInt64-lower-fast.run-low.ok | 1 + test/trap/ok/powInt64-lower-fast.run.ok | 1 + test/trap/ok/powInt64-lower-fast.wasm-run.ok | 1 + test/trap/ok/powInt64-lower-slow.run-ir.ok | 1 + test/trap/ok/powInt64-lower-slow.run-low.ok | 1 + test/trap/ok/powInt64-lower-slow.run.ok | 1 + test/trap/ok/powInt64-lower-slow.wasm-run.ok | 1 + test/trap/ok/powInt64-raise-neg.run-ir.ok | 1 + test/trap/ok/powInt64-raise-neg.run-low.ok | 1 + test/trap/ok/powInt64-raise-neg.run.ok | 1 + test/trap/ok/powInt64-raise-neg.wasm-run.ok | 1 + test/trap/ok/powInt64-upper-fast.run-ir.ok | 1 + test/trap/ok/powInt64-upper-fast.run-low.ok | 1 + test/trap/ok/powInt64-upper-fast.run.ok | 1 + test/trap/ok/powInt64-upper-fast.wasm-run.ok | 1 + test/trap/ok/powInt64-upper-slow.run-ir.ok | 1 + test/trap/ok/powInt64-upper-slow.run-low.ok | 1 + test/trap/ok/powInt64-upper-slow.run.ok | 1 + test/trap/ok/powInt64-upper-slow.wasm-run.ok | 1 + test/trap/ok/powNat64.run-ir.ok | 1 + test/trap/ok/powNat64.run-low.ok | 1 + test/trap/ok/powNat64.run.ok | 1 + test/trap/ok/powNat64.wasm-run.ok | 1 + test/trap/ok/subNat64-slow.run-ir.ok | 1 + test/trap/ok/subNat64-slow.run-low.ok | 1 + test/trap/ok/subNat64-slow.run.ok | 1 + test/trap/ok/subNat64-slow.wasm-run.ok | 1 + test/trap/powInt32-raise-neg.as | 1 + test/trap/powInt64-lower-fast.as | 1 + test/trap/powInt64-lower-slow.as | 1 + test/trap/powInt64-raise-neg.as | 1 + test/trap/powInt64-upper-fast.as | 1 + test/trap/powInt64-upper-slow.as | 1 + test/trap/powNat64.as | 1 + test/trap/subNat64-slow.as | 1 + 42 files changed, 291 insertions(+), 46 deletions(-) create mode 100644 test/trap/ok/powInt32-raise-neg.run-ir.ok create mode 100644 test/trap/ok/powInt32-raise-neg.run-low.ok create mode 100644 test/trap/ok/powInt32-raise-neg.run.ok create mode 100644 test/trap/ok/powInt32-raise-neg.wasm-run.ok create mode 100644 test/trap/ok/powInt64-lower-fast.run-ir.ok create mode 100644 test/trap/ok/powInt64-lower-fast.run-low.ok create mode 100644 test/trap/ok/powInt64-lower-fast.run.ok create mode 100644 test/trap/ok/powInt64-lower-fast.wasm-run.ok create mode 100644 test/trap/ok/powInt64-lower-slow.run-ir.ok create mode 100644 test/trap/ok/powInt64-lower-slow.run-low.ok create mode 100644 test/trap/ok/powInt64-lower-slow.run.ok create mode 100644 test/trap/ok/powInt64-lower-slow.wasm-run.ok create mode 100644 test/trap/ok/powInt64-raise-neg.run-ir.ok create mode 100644 test/trap/ok/powInt64-raise-neg.run-low.ok create mode 100644 test/trap/ok/powInt64-raise-neg.run.ok create mode 100644 test/trap/ok/powInt64-raise-neg.wasm-run.ok create mode 100644 test/trap/ok/powInt64-upper-fast.run-ir.ok create mode 100644 test/trap/ok/powInt64-upper-fast.run-low.ok create mode 100644 test/trap/ok/powInt64-upper-fast.run.ok create mode 100644 test/trap/ok/powInt64-upper-fast.wasm-run.ok create mode 100644 test/trap/ok/powInt64-upper-slow.run-ir.ok create mode 100644 test/trap/ok/powInt64-upper-slow.run-low.ok create mode 100644 test/trap/ok/powInt64-upper-slow.run.ok create mode 100644 test/trap/ok/powInt64-upper-slow.wasm-run.ok create mode 100644 test/trap/ok/powNat64.run-ir.ok create mode 100644 test/trap/ok/powNat64.run-low.ok create mode 100644 test/trap/ok/powNat64.run.ok create mode 100644 test/trap/ok/powNat64.wasm-run.ok create mode 100644 test/trap/ok/subNat64-slow.run-ir.ok create mode 100644 test/trap/ok/subNat64-slow.run-low.ok create mode 100644 test/trap/ok/subNat64-slow.run.ok create mode 100644 test/trap/ok/subNat64-slow.wasm-run.ok create mode 100644 test/trap/powInt32-raise-neg.as create mode 100644 test/trap/powInt64-lower-fast.as create mode 100644 test/trap/powInt64-lower-slow.as create mode 100644 test/trap/powInt64-raise-neg.as create mode 100644 test/trap/powInt64-upper-fast.as create mode 100644 test/trap/powInt64-upper-slow.as create mode 100644 test/trap/powNat64.as create mode 100644 test/trap/subNat64-slow.as diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 443a0f1be6a..427873b5a26 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -378,6 +378,23 @@ let compile_eq_const i = compile_unboxed_const i ^^ G.i (Compare (Wasm.Values.I32 I32Op.Eq)) +let compile_op64_const op i = + compile_const_64 i ^^ + G.i (Binary (Wasm.Values.I64 op)) +let _compile_add64_const = compile_op64_const I64Op.Add +let compile_sub64_const = compile_op64_const I64Op.Sub +let _compile_mul64_const = compile_op64_const I64Op.Mul +let _compile_divU64_const = compile_op64_const I64Op.DivU +let compile_shrU64_const = compile_op64_const I64Op.ShrU +let compile_shrS64_const = compile_op64_const I64Op.ShrS +let compile_shl64_const = compile_op64_const I64Op.Shl +let compile_bitand64_const = compile_op64_const I64Op.And +let _compile_bitor64_const = function + | 0L -> G.nop | n -> compile_op64_const I64Op.Or n +let compile_eq64_const i = + compile_const_64 i ^^ + G.i (Compare (Wasm.Values.I64 I64Op.Eq)) + (* more random utilities *) let bytes_of_int32 (i : int32) : string = @@ -1509,8 +1526,7 @@ module BigNum64 : BigNumType = struct | n when n > 64 || n < 1 -> assert false | n -> unbox env ^^ - compile_const_64 Int64.(shift_left minus_one n) ^^ - G.i (Binary (Wasm.Values.I64 I64Op.And)) ^^ + compile_bitand64_const Int64.(shift_left minus_one n) ^^ G.i (Test (Wasm.Values.I64 I64Op.Eqz)) (* examine the skewed pointer and determine if the signed number @@ -1521,11 +1537,9 @@ module BigNum64 : BigNumType = struct | n -> let set_num, get_num = new_local64 env "num" in unbox env ^^ set_num ^^ get_num ^^ get_num ^^ - compile_const_64 1L ^^ - G.i (Binary (Wasm.Values.I64 I64Op.Shl)) ^^ + compile_shl64_const 1L ^^ G.i (Binary (Wasm.Values.I64 I64Op.Xor)) ^^ - compile_const_64 Int64.(shift_left minus_one n) ^^ - G.i (Binary (Wasm.Values.I64 I64Op.And)) ^^ + compile_bitand64_const Int64.(shift_left minus_one n) ^^ G.i (Test (Wasm.Values.I64 I64Op.Eqz)) let to_word32 env = @@ -4532,16 +4546,15 @@ let compile_unop env t op = G.i (Binary (Wasm.Values.I64 I64Op.Sub)) ) | NegOp, Type.(Prim Int64) -> - SR.UnboxedWord64, SR.UnboxedWord64, - Func.share_code1 env "neg_trap" ("n", I64Type) [I64Type] (fun env get_n -> - get_n ^^ - compile_const_64 0x8000000000000000L ^^ - G.i (Compare (Wasm.Values.I64 I64Op.Eq)) ^^ - then_arithmetic_overflow env ^^ - compile_const_64 0L ^^ - get_n ^^ - G.i (Binary (Wasm.Values.I64 I64Op.Sub)) - ) + SR.UnboxedWord64, SR.UnboxedWord64, + Func.share_code1 env "neg_trap" ("n", I64Type) [I64Type] (fun env get_n -> + get_n ^^ + compile_eq64_const 0x8000000000000000L ^^ + then_arithmetic_overflow env ^^ + compile_const_64 0L ^^ + get_n ^^ + G.i (Binary (Wasm.Values.I64 I64Op.Sub)) + ) | NegOp, Type.(Prim (Word8 | Word16 | Word32)) -> StackRep.of_type t, StackRep.of_type t, Func.share_code1 env "neg32" ("n", I32Type) [I32Type] (fun env get_n -> @@ -4593,44 +4606,151 @@ let unsigned_dynamics = let else_arithmetic_overflow env = E.else_trap_with env "arithmetic overflow" -let compile_Int64_kernel env name op = +(* helpers to decide if Int64 arithmetic can be carried out on the fast path *) +let additiveInt64_shortcut fast env get_a get_b slow = + get_a ^^ get_a ^^ compile_shl64_const 1L ^^ G.i (Binary (Wasm.Values.I64 I64Op.Xor)) ^^ compile_shrU64_const 63L ^^ + get_b ^^ get_b ^^ compile_shl64_const 1L ^^ G.i (Binary (Wasm.Values.I64 I64Op.Xor)) ^^ compile_shrU64_const 63L ^^ + G.i (Binary (Wasm.Values.I64 I64Op.Or)) ^^ + G.i (Test (Wasm.Values.I64 I64Op.Eqz)) ^^ + G.if_ (ValBlockType (Some I64Type)) + (get_a ^^ get_b ^^ fast) + slow + +let mulInt64_shortcut fast env get_a get_b slow = + get_a ^^ get_a ^^ compile_shl64_const 1L ^^ G.i (Binary (Wasm.Values.I64 I64Op.Xor)) ^^ G.i (Unary (Wasm.Values.I64 I64Op.Clz)) ^^ + get_b ^^ get_b ^^ compile_shl64_const 1L ^^ G.i (Binary (Wasm.Values.I64 I64Op.Xor)) ^^ G.i (Unary (Wasm.Values.I64 I64Op.Clz)) ^^ + G.i (Binary (Wasm.Values.I64 I64Op.Add)) ^^ + compile_const_64 65L ^^ G.i (Compare (Wasm.Values.I64 I64Op.GeU)) ^^ + G.if_ (ValBlockType (Some I64Type)) + (get_a ^^ get_b ^^ fast) + slow + +let powInt64_shortcut fast env get_a get_b slow = + get_b ^^ G.i (Test (Wasm.Values.I64 I64Op.Eqz)) ^^ + G.if_ (ValBlockType (Some I64Type)) + (compile_const_64 1L) (* ^0 *) + begin (* ^(1+n) *) + get_a ^^ compile_const_64 (-1L) ^^ G.i (Compare (Wasm.Values.I64 I64Op.Eq)) ^^ + G.if_ (ValBlockType (Some I64Type)) + begin (* -1 ** (1+exp) == if even (1+exp) then 1 else -1 *) + get_b ^^ compile_const_64 1L ^^ + G.i (Binary (Wasm.Values.I64 I64Op.And)) ^^ G.i (Test (Wasm.Values.I64 I64Op.Eqz)) ^^ + G.if_ (ValBlockType (Some I64Type)) + (compile_const_64 1L) + get_a + end + begin + get_a ^^ compile_shrS64_const 1L ^^ + G.i (Test (Wasm.Values.I64 I64Op.Eqz)) ^^ + G.if_ (ValBlockType (Some I64Type)) + get_a (* {0,1}^(1+n) *) + begin + get_b ^^ compile_const_64 64L ^^ + G.i (Compare (Wasm.Values.I64 I64Op.GeU)) ^^ then_arithmetic_overflow env ^^ + get_a ^^ get_a ^^ compile_shl64_const 1L ^^ G.i (Binary (Wasm.Values.I64 I64Op.Xor)) ^^ + G.i (Unary (Wasm.Values.I64 I64Op.Clz)) ^^ compile_sub64_const 63L ^^ + get_b ^^ G.i (Binary (Wasm.Values.I64 I64Op.Mul)) ^^ + compile_const_64 (-63L) ^^ G.i (Compare (Wasm.Values.I64 I64Op.GeS)) ^^ + G.if_ (ValBlockType (Some I64Type)) + (get_a ^^ get_b ^^ fast) + slow + end + end + end + + +(* kernel for Int64 arithmetic, invokes estimator for fast path *) +let compile_Int64_kernel env name op shortcut = Func.share_code2 env (UnboxedSmallWord.name_of_type Type.Int64 name) (("a", I64Type), ("b", I64Type)) [I64Type] BigNum.(fun env get_a get_b -> - let (set_res, get_res) = new_local env "res" in - get_a ^^ from_signed_word64 env ^^ - get_b ^^ from_signed_word64 env ^^ - op env ^^ - set_res ^^ get_res ^^ - fits_signed_bits env 64 ^^ - else_arithmetic_overflow env ^^ - get_res ^^ BigNum.truncate_to_word64 env) - -let compile_Nat64_kernel env name op = + shortcut + env + get_a + get_b + begin + let (set_res, get_res) = new_local env "res" in + get_a ^^ from_signed_word64 env ^^ + get_b ^^ from_signed_word64 env ^^ + op env ^^ + set_res ^^ get_res ^^ + fits_signed_bits env 64 ^^ + else_arithmetic_overflow env ^^ + get_res ^^ truncate_to_word64 env + end) + + +(* helpers to decide if Nat64 arithmetic can be carried out on the fast path *) +let additiveNat64_shortcut fast env get_a get_b slow = + get_a ^^ compile_shrU64_const 62L ^^ + get_b ^^ compile_shrU64_const 62L ^^ + G.i (Binary (Wasm.Values.I64 I64Op.Or)) ^^ + G.i (Test (Wasm.Values.I64 I64Op.Eqz)) ^^ + G.if_ (ValBlockType (Some I64Type)) + (get_a ^^ get_b ^^ fast) + slow + +let mulNat64_shortcut fast env get_a get_b slow = + get_a ^^ G.i (Unary (Wasm.Values.I64 I64Op.Clz)) ^^ + get_b ^^ G.i (Unary (Wasm.Values.I64 I64Op.Clz)) ^^ + G.i (Binary (Wasm.Values.I64 I64Op.Add)) ^^ + compile_const_64 64L ^^ G.i (Compare (Wasm.Values.I64 I64Op.GeU)) ^^ + G.if_ (ValBlockType (Some I64Type)) + (get_a ^^ get_b ^^ fast) + slow + +let powNat64_shortcut fast env get_a get_b slow = + get_b ^^ G.i (Test (Wasm.Values.I64 I64Op.Eqz)) ^^ + G.if_ (ValBlockType (Some I64Type)) + (compile_const_64 1L) (* ^0 *) + begin (* ^(1+n) *) + get_a ^^ compile_shrU64_const 1L ^^ + G.i (Test (Wasm.Values.I64 I64Op.Eqz)) ^^ + G.if_ (ValBlockType (Some I64Type)) + get_a (* {0,1}^(1+n) *) + begin + get_b ^^ compile_const_64 64L ^^ G.i (Compare (Wasm.Values.I64 I64Op.GeU)) ^^ then_arithmetic_overflow env ^^ + get_a ^^ G.i (Unary (Wasm.Values.I64 I64Op.Clz)) ^^ compile_sub64_const 64L ^^ + get_b ^^ G.i (Binary (Wasm.Values.I64 I64Op.Mul)) ^^ compile_const_64 (-64L) ^^ G.i (Compare (Wasm.Values.I64 I64Op.GeS)) ^^ + G.if_ (ValBlockType (Some I64Type)) + (get_a ^^ get_b ^^ fast) + slow + end + end + + +(* kernel for Nat64 arithmetic, invokes estimator for fast path *) +let compile_Nat64_kernel env name op shortcut = Func.share_code2 env (UnboxedSmallWord.name_of_type Type.Nat64 name) (("a", I64Type), ("b", I64Type)) [I64Type] BigNum.(fun env get_a get_b -> - let (set_res, get_res) = new_local env "res" in - get_a ^^ from_word64 env ^^ - get_b ^^ from_word64 env ^^ - op env ^^ - set_res ^^ get_res ^^ - fits_unsigned_bits env 64 ^^ - else_arithmetic_overflow env ^^ - get_res ^^ BigNum.truncate_to_word64 env) + shortcut + env + get_a + get_b + begin + let (set_res, get_res) = new_local env "res" in + get_a ^^ from_word64 env ^^ + get_b ^^ from_word64 env ^^ + op env ^^ + set_res ^^ get_res ^^ + fits_unsigned_bits env 64 ^^ + else_arithmetic_overflow env ^^ + get_res ^^ truncate_to_word64 env + end) + (* Compiling Int/Nat32 ops by conversion to/from i64. *) (* helper, expects i64 on stack *) let enforce_32_unsigned_bits env = - compile_const_64 0xFFFFFFFF00000000L ^^ - G.i (Binary (Wasm.Values.I64 I64Op.And)) ^^ + compile_bitand64_const 0xFFFFFFFF00000000L ^^ G.i (Test (Wasm.Values.I64 I64Op.Eqz)) ^^ else_arithmetic_overflow env (* helper, expects two identical i64s on stack *) let enforce_32_signed_bits env = - compile_const_64 1L ^^ G.i (Binary (Wasm.Values.I64 I64Op.Shl)) ^^ + compile_shl64_const 1L ^^ G.i (Binary (Wasm.Values.I64 I64Op.Xor)) ^^ enforce_32_unsigned_bits env @@ -4712,14 +4832,22 @@ let rec compile_binop env t op = Operator.(match t, op with | Type.(Prim (Nat | Int)), AddOp -> BigNum.compile_add env | Type.(Prim Word64), AddOp -> G.i (Binary (Wasm.Values.I64 I64Op.Add)) - | Type.(Prim Int64), AddOp -> compile_Int64_kernel env "add" BigNum.compile_add - | Type.(Prim Nat64), AddOp -> compile_Nat64_kernel env "add" BigNum.compile_add + | Type.(Prim Int64), AddOp -> + compile_Int64_kernel env "add" BigNum.compile_add + (additiveInt64_shortcut (G.i (Binary (Wasm.Values.I64 I64Op.Add)))) + | Type.(Prim Nat64), AddOp -> + compile_Nat64_kernel env "add" BigNum.compile_add + (additiveNat64_shortcut (G.i (Binary (Wasm.Values.I64 I64Op.Add)))) | Type.(Prim Nat), SubOp -> BigNum.compile_unsigned_sub env | Type.(Prim Int), SubOp -> BigNum.compile_signed_sub env | Type.(Prim (Nat | Int)), MulOp -> BigNum.compile_mul env | Type.(Prim Word64), MulOp -> G.i (Binary (Wasm.Values.I64 I64Op.Mul)) - | Type.(Prim Int64), MulOp -> compile_Int64_kernel env "mul" BigNum.compile_mul - | Type.(Prim Nat64), MulOp -> compile_Nat64_kernel env "mul" BigNum.compile_mul + | Type.(Prim Int64), MulOp -> + compile_Int64_kernel env "mul" BigNum.compile_mul + (mulInt64_shortcut (G.i (Binary (Wasm.Values.I64 I64Op.Mul)))) + | Type.(Prim Nat64), MulOp -> + compile_Nat64_kernel env "mul" BigNum.compile_mul + (mulNat64_shortcut (G.i (Binary (Wasm.Values.I64 I64Op.Mul)))) | Type.(Prim (Nat64|Word64)), DivOp -> G.i (Binary (Wasm.Values.I64 I64Op.DivU)) | Type.(Prim (Nat64|Word64)), ModOp -> G.i (Binary (Wasm.Values.I64 I64Op.RemU)) | Type.(Prim Int64), DivOp -> G.i (Binary (Wasm.Values.I64 I64Op.DivS)) @@ -4727,8 +4855,17 @@ let rec compile_binop env t op = | Type.(Prim Nat), DivOp -> BigNum.compile_unsigned_div env | Type.(Prim Nat), ModOp -> BigNum.compile_unsigned_rem env | Type.(Prim Word64), SubOp -> G.i (Binary (Wasm.Values.I64 I64Op.Sub)) - | Type.(Prim Int64), SubOp -> compile_Int64_kernel env "sub" BigNum.compile_signed_sub - | Type.(Prim Nat64), SubOp -> compile_Nat64_kernel env "sub" BigNum.compile_unsigned_sub + | Type.(Prim Int64), SubOp -> + compile_Int64_kernel env "sub" BigNum.compile_signed_sub + (additiveInt64_shortcut (G.i (Binary (Wasm.Values.I64 I64Op.Sub)))) + | Type.(Prim Nat64), SubOp -> + compile_Nat64_kernel env "sub" BigNum.compile_unsigned_sub + (fun env get_a get_b -> + additiveNat64_shortcut + (G.i (Compare (Wasm.Values.I64 I64Op.GeU)) ^^ + else_arithmetic_overflow env ^^ + get_a ^^ get_b ^^ G.i (Binary (Wasm.Values.I64 I64Op.Sub))) + env get_a get_b) | Type.(Prim Int), DivOp -> BigNum.compile_signed_div env | Type.(Prim Int), ModOp -> BigNum.compile_signed_mod env @@ -4930,8 +5067,14 @@ let rec compile_binop env t op = compile_const_64 0L ^^ G.i (Compare (Wasm.Values.I64 I64Op.LtS)) ^^ E.then_trap_with env "negative power" ^^ - get_exp ^^ compile_Int64_kernel env "pow" BigNum.compile_unsigned_pow - | Type.(Prim Nat64), PowOp -> compile_Nat64_kernel env "pow" BigNum.compile_unsigned_pow + get_exp ^^ + compile_Int64_kernel + env "pow" BigNum.compile_unsigned_pow + (powInt64_shortcut (let _,_,pow = compile_binop env Type.(Prim Word64) PowOp in pow)) + | Type.(Prim Nat64), PowOp -> + compile_Nat64_kernel env "pow" + BigNum.compile_unsigned_pow + (powNat64_shortcut (let _,_,pow = compile_binop env Type.(Prim Word64) PowOp in pow)) | Type.(Prim Nat), PowOp -> BigNum.compile_unsigned_pow env | Type.(Prim Word64), AndOp -> G.i (Binary (Wasm.Values.I64 I64Op.And)) | Type.Prim Type.(Word8 | Word16 | Word32), AndOp -> G.i (Binary (Wasm.Values.I32 I32Op.And)) diff --git a/test/run-dfinity/log-slow.as b/test/run-dfinity/log-slow.as index 3ec81b4e5ed..7358e9fe804 100644 --- a/test/run-dfinity/log-slow.as +++ b/test/run-dfinity/log-slow.as @@ -47,6 +47,22 @@ for (n in range(0, 255)) { }; +assert (natToNat64 2 ** natToNat64 63 == natToNat64 9223372036854775808); // highest exponent +assert (natToNat64 2642245 ** natToNat64 3 == natToNat64 18_446_724_184_312_856_125); + +for (n in range(0, 255)) { + for (exp in range(0, 255)) { + if (n <= 1 or exp <= 106) { // see #537 + let res = n ** exp; + if (res <= 18446744073709551615) + { + assert (natToNat64 n ** natToNat64 exp == natToNat64 res) + } + } + } +}; + + // Int* assert (intToInt8 2 ** intToInt8 6 == intToInt8 64); // highest exponent @@ -149,3 +165,49 @@ while (n < -1) { n += 1 } }; + + +assert (intToInt64 3 ** intToInt64 31 == intToInt64 617_673_396_283_947); // still on fast path + +assert (intToInt64 3 ** intToInt64 39 == intToInt64 4_052_555_153_018_976_267); +assert (intToInt64 2 ** intToInt64 62 == intToInt64 4_611_686_018_427_387_904); // highest exponent +assert (intToInt64 (-2) ** intToInt64 63 == intToInt64 (-9_223_372_036_854_775_808)); // highest exponent +assert (intToInt64 (-3) ** intToInt64 39 == intToInt64 (-4_052_555_153_018_976_267)); + +assert (intToInt64 (-3) ** intToInt64 31 == intToInt64 (-617_673_396_283_947)); // still on fast path + +assert (intToInt64 1 ** intToInt64 39 == intToInt64 1); +assert (intToInt64 1 ** intToInt64 100 == intToInt64 1); +assert (intToInt64 1 ** intToInt64 101 == intToInt64 1); + +assert (intToInt64 0 ** intToInt64 39 == intToInt64 0); +assert (intToInt64 0 ** intToInt64 100 == intToInt64 0); +assert (intToInt64 0 ** intToInt64 101 == intToInt64 0); + +assert (intToInt64 (-1) ** intToInt64 39 == intToInt64 (-1)); +assert (intToInt64 (-1) ** intToInt64 100 == intToInt64 1); +assert (intToInt64 (-1) ** intToInt64 101 == intToInt64 (-1)); + +for (n in range(0, 127)) { + for (exp in range(0, 127)) { + if (n <= 1 or exp <= 1 or exp <= 63) { + let res = n ** exp; + if (res <= 9_223_372_036_854_775_807) { assert (intToInt64 n ** intToInt64 exp == intToInt64 res) } + } + } +}; + +{ +var n = -128; +while (n < -1) { + for (exp in range(0, 127)) { + if (n == -1 or exp <= 1 or exp <= 63) { + let res = n ** exp; + if (res >= -9_223_372_036_854_775_808 and res <= 9_223_372_036_854_775_807) { + assert (intToInt64 n ** intToInt64 exp == intToInt64 res) + } + } + }; + n += 1 +} +}; diff --git a/test/trap/ok/powInt32-raise-neg.run-ir.ok b/test/trap/ok/powInt32-raise-neg.run-ir.ok new file mode 100644 index 00000000000..6660e86c6ff --- /dev/null +++ b/test/trap/ok/powInt32-raise-neg.run-ir.ok @@ -0,0 +1 @@ +powInt32-raise-neg.as:1.9-1.37: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt32-raise-neg.run-low.ok b/test/trap/ok/powInt32-raise-neg.run-low.ok new file mode 100644 index 00000000000..6660e86c6ff --- /dev/null +++ b/test/trap/ok/powInt32-raise-neg.run-low.ok @@ -0,0 +1 @@ +powInt32-raise-neg.as:1.9-1.37: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt32-raise-neg.run.ok b/test/trap/ok/powInt32-raise-neg.run.ok new file mode 100644 index 00000000000..6660e86c6ff --- /dev/null +++ b/test/trap/ok/powInt32-raise-neg.run.ok @@ -0,0 +1 @@ +powInt32-raise-neg.as:1.9-1.37: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt32-raise-neg.wasm-run.ok b/test/trap/ok/powInt32-raise-neg.wasm-run.ok new file mode 100644 index 00000000000..81aa3d12b63 --- /dev/null +++ b/test/trap/ok/powInt32-raise-neg.wasm-run.ok @@ -0,0 +1 @@ +_out/powInt32-raise-neg.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/powInt64-lower-fast.run-ir.ok b/test/trap/ok/powInt64-lower-fast.run-ir.ok new file mode 100644 index 00000000000..66a5a93a328 --- /dev/null +++ b/test/trap/ok/powInt64-lower-fast.run-ir.ok @@ -0,0 +1 @@ +powInt64-lower-fast.as:1.9-1.37: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt64-lower-fast.run-low.ok b/test/trap/ok/powInt64-lower-fast.run-low.ok new file mode 100644 index 00000000000..66a5a93a328 --- /dev/null +++ b/test/trap/ok/powInt64-lower-fast.run-low.ok @@ -0,0 +1 @@ +powInt64-lower-fast.as:1.9-1.37: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt64-lower-fast.run.ok b/test/trap/ok/powInt64-lower-fast.run.ok new file mode 100644 index 00000000000..66a5a93a328 --- /dev/null +++ b/test/trap/ok/powInt64-lower-fast.run.ok @@ -0,0 +1 @@ +powInt64-lower-fast.as:1.9-1.37: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt64-lower-fast.wasm-run.ok b/test/trap/ok/powInt64-lower-fast.wasm-run.ok new file mode 100644 index 00000000000..76a7f113984 --- /dev/null +++ b/test/trap/ok/powInt64-lower-fast.wasm-run.ok @@ -0,0 +1 @@ +_out/powInt64-lower-fast.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/powInt64-lower-slow.run-ir.ok b/test/trap/ok/powInt64-lower-slow.run-ir.ok new file mode 100644 index 00000000000..0fd2e8c791f --- /dev/null +++ b/test/trap/ok/powInt64-lower-slow.run-ir.ok @@ -0,0 +1 @@ +powInt64-lower-slow.as:1.9-1.37: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt64-lower-slow.run-low.ok b/test/trap/ok/powInt64-lower-slow.run-low.ok new file mode 100644 index 00000000000..0fd2e8c791f --- /dev/null +++ b/test/trap/ok/powInt64-lower-slow.run-low.ok @@ -0,0 +1 @@ +powInt64-lower-slow.as:1.9-1.37: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt64-lower-slow.run.ok b/test/trap/ok/powInt64-lower-slow.run.ok new file mode 100644 index 00000000000..0fd2e8c791f --- /dev/null +++ b/test/trap/ok/powInt64-lower-slow.run.ok @@ -0,0 +1 @@ +powInt64-lower-slow.as:1.9-1.37: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt64-lower-slow.wasm-run.ok b/test/trap/ok/powInt64-lower-slow.wasm-run.ok new file mode 100644 index 00000000000..5a7fce1bb95 --- /dev/null +++ b/test/trap/ok/powInt64-lower-slow.wasm-run.ok @@ -0,0 +1 @@ +_out/powInt64-lower-slow.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/powInt64-raise-neg.run-ir.ok b/test/trap/ok/powInt64-raise-neg.run-ir.ok new file mode 100644 index 00000000000..529eba25595 --- /dev/null +++ b/test/trap/ok/powInt64-raise-neg.run-ir.ok @@ -0,0 +1 @@ +powInt64-raise-neg.as:1.9-1.37: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt64-raise-neg.run-low.ok b/test/trap/ok/powInt64-raise-neg.run-low.ok new file mode 100644 index 00000000000..529eba25595 --- /dev/null +++ b/test/trap/ok/powInt64-raise-neg.run-low.ok @@ -0,0 +1 @@ +powInt64-raise-neg.as:1.9-1.37: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt64-raise-neg.run.ok b/test/trap/ok/powInt64-raise-neg.run.ok new file mode 100644 index 00000000000..529eba25595 --- /dev/null +++ b/test/trap/ok/powInt64-raise-neg.run.ok @@ -0,0 +1 @@ +powInt64-raise-neg.as:1.9-1.37: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt64-raise-neg.wasm-run.ok b/test/trap/ok/powInt64-raise-neg.wasm-run.ok new file mode 100644 index 00000000000..c9999dacc32 --- /dev/null +++ b/test/trap/ok/powInt64-raise-neg.wasm-run.ok @@ -0,0 +1 @@ +_out/powInt64-raise-neg.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/powInt64-upper-fast.run-ir.ok b/test/trap/ok/powInt64-upper-fast.run-ir.ok new file mode 100644 index 00000000000..31662af7ca5 --- /dev/null +++ b/test/trap/ok/powInt64-upper-fast.run-ir.ok @@ -0,0 +1 @@ +powInt64-upper-fast.as:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt64-upper-fast.run-low.ok b/test/trap/ok/powInt64-upper-fast.run-low.ok new file mode 100644 index 00000000000..31662af7ca5 --- /dev/null +++ b/test/trap/ok/powInt64-upper-fast.run-low.ok @@ -0,0 +1 @@ +powInt64-upper-fast.as:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt64-upper-fast.run.ok b/test/trap/ok/powInt64-upper-fast.run.ok new file mode 100644 index 00000000000..31662af7ca5 --- /dev/null +++ b/test/trap/ok/powInt64-upper-fast.run.ok @@ -0,0 +1 @@ +powInt64-upper-fast.as:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt64-upper-fast.wasm-run.ok b/test/trap/ok/powInt64-upper-fast.wasm-run.ok new file mode 100644 index 00000000000..98fa7675e78 --- /dev/null +++ b/test/trap/ok/powInt64-upper-fast.wasm-run.ok @@ -0,0 +1 @@ +_out/powInt64-upper-fast.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/powInt64-upper-slow.run-ir.ok b/test/trap/ok/powInt64-upper-slow.run-ir.ok new file mode 100644 index 00000000000..c3f19d51285 --- /dev/null +++ b/test/trap/ok/powInt64-upper-slow.run-ir.ok @@ -0,0 +1 @@ +powInt64-upper-slow.as:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt64-upper-slow.run-low.ok b/test/trap/ok/powInt64-upper-slow.run-low.ok new file mode 100644 index 00000000000..c3f19d51285 --- /dev/null +++ b/test/trap/ok/powInt64-upper-slow.run-low.ok @@ -0,0 +1 @@ +powInt64-upper-slow.as:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt64-upper-slow.run.ok b/test/trap/ok/powInt64-upper-slow.run.ok new file mode 100644 index 00000000000..c3f19d51285 --- /dev/null +++ b/test/trap/ok/powInt64-upper-slow.run.ok @@ -0,0 +1 @@ +powInt64-upper-slow.as:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt64-upper-slow.wasm-run.ok b/test/trap/ok/powInt64-upper-slow.wasm-run.ok new file mode 100644 index 00000000000..01093b45a72 --- /dev/null +++ b/test/trap/ok/powInt64-upper-slow.wasm-run.ok @@ -0,0 +1 @@ +_out/powInt64-upper-slow.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/powNat64.run-ir.ok b/test/trap/ok/powNat64.run-ir.ok new file mode 100644 index 00000000000..befe74d8029 --- /dev/null +++ b/test/trap/ok/powNat64.run-ir.ok @@ -0,0 +1 @@ +powNat64.as:1.9-1.41: execution error, arithmetic overflow diff --git a/test/trap/ok/powNat64.run-low.ok b/test/trap/ok/powNat64.run-low.ok new file mode 100644 index 00000000000..befe74d8029 --- /dev/null +++ b/test/trap/ok/powNat64.run-low.ok @@ -0,0 +1 @@ +powNat64.as:1.9-1.41: execution error, arithmetic overflow diff --git a/test/trap/ok/powNat64.run.ok b/test/trap/ok/powNat64.run.ok new file mode 100644 index 00000000000..befe74d8029 --- /dev/null +++ b/test/trap/ok/powNat64.run.ok @@ -0,0 +1 @@ +powNat64.as:1.9-1.41: execution error, arithmetic overflow diff --git a/test/trap/ok/powNat64.wasm-run.ok b/test/trap/ok/powNat64.wasm-run.ok new file mode 100644 index 00000000000..569b2f79dd0 --- /dev/null +++ b/test/trap/ok/powNat64.wasm-run.ok @@ -0,0 +1 @@ +_out/powNat64.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/ok/subNat64-slow.run-ir.ok b/test/trap/ok/subNat64-slow.run-ir.ok new file mode 100644 index 00000000000..b2fa6c6e4cd --- /dev/null +++ b/test/trap/ok/subNat64-slow.run-ir.ok @@ -0,0 +1 @@ +subNat64-slow.as:1.9-1.84: execution error, arithmetic overflow diff --git a/test/trap/ok/subNat64-slow.run-low.ok b/test/trap/ok/subNat64-slow.run-low.ok new file mode 100644 index 00000000000..b2fa6c6e4cd --- /dev/null +++ b/test/trap/ok/subNat64-slow.run-low.ok @@ -0,0 +1 @@ +subNat64-slow.as:1.9-1.84: execution error, arithmetic overflow diff --git a/test/trap/ok/subNat64-slow.run.ok b/test/trap/ok/subNat64-slow.run.ok new file mode 100644 index 00000000000..b2fa6c6e4cd --- /dev/null +++ b/test/trap/ok/subNat64-slow.run.ok @@ -0,0 +1 @@ +subNat64-slow.as:1.9-1.84: execution error, arithmetic overflow diff --git a/test/trap/ok/subNat64-slow.wasm-run.ok b/test/trap/ok/subNat64-slow.wasm-run.ok new file mode 100644 index 00000000000..b7e53fd8ac8 --- /dev/null +++ b/test/trap/ok/subNat64-slow.wasm-run.ok @@ -0,0 +1 @@ +_out/subNat64-slow.wasm:0x___: runtime trap: unreachable executed diff --git a/test/trap/powInt32-raise-neg.as b/test/trap/powInt32-raise-neg.as new file mode 100644 index 00000000000..101e2078da2 --- /dev/null +++ b/test/trap/powInt32-raise-neg.as @@ -0,0 +1 @@ +let _ = (12 : Int32) ** (-2 : Int32) diff --git a/test/trap/powInt64-lower-fast.as b/test/trap/powInt64-lower-fast.as new file mode 100644 index 00000000000..215a59fa426 --- /dev/null +++ b/test/trap/powInt64-lower-fast.as @@ -0,0 +1 @@ +let _ = (-3 : Int64) ** (65 : Int64) diff --git a/test/trap/powInt64-lower-slow.as b/test/trap/powInt64-lower-slow.as new file mode 100644 index 00000000000..aec922e6579 --- /dev/null +++ b/test/trap/powInt64-lower-slow.as @@ -0,0 +1 @@ +let _ = (-3 : Int64) ** (41 : Int64) diff --git a/test/trap/powInt64-raise-neg.as b/test/trap/powInt64-raise-neg.as new file mode 100644 index 00000000000..e82b33288e9 --- /dev/null +++ b/test/trap/powInt64-raise-neg.as @@ -0,0 +1 @@ +let _ = (12 : Int64) ** (-2 : Int64) diff --git a/test/trap/powInt64-upper-fast.as b/test/trap/powInt64-upper-fast.as new file mode 100644 index 00000000000..b54498e17ec --- /dev/null +++ b/test/trap/powInt64-upper-fast.as @@ -0,0 +1 @@ +let _ = (2 : Int64) ** (64 : Int64) diff --git a/test/trap/powInt64-upper-slow.as b/test/trap/powInt64-upper-slow.as new file mode 100644 index 00000000000..ed90fc48445 --- /dev/null +++ b/test/trap/powInt64-upper-slow.as @@ -0,0 +1 @@ +let _ = (3 : Int64) ** (40 : Int64) diff --git a/test/trap/powNat64.as b/test/trap/powNat64.as new file mode 100644 index 00000000000..4852e6534c6 --- /dev/null +++ b/test/trap/powNat64.as @@ -0,0 +1 @@ +let _ = (2642246 : Nat64) ** (3 : Nat64) diff --git a/test/trap/subNat64-slow.as b/test/trap/subNat64-slow.as new file mode 100644 index 00000000000..2505c95dd6e --- /dev/null +++ b/test/trap/subNat64-slow.as @@ -0,0 +1 @@ +let _ = (18_446_744_073_709_551_614 : Nat64) - (18_446_744_073_709_551_615 : Nat64) From fdc4d982f79f1767be3f5fe3b1e9e2fa116ed37d Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Tue, 16 Jul 2019 00:00:40 +0200 Subject: [PATCH 0259/1176] Refactor wrapping codegen for Word8/16/32 mul and pow (#571) * factor out Word<64 `mul` and `pow` * remove `rec` marker from `compile_binop` * move `compile_word_mul`, `compile_word_power` to `UnboxedSmallWord` --- src/codegen/compile.ml | 67 +++++++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 30 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 427873b5a26..66ceea44434 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -1434,6 +1434,33 @@ module UnboxedSmallWord = struct let lit env ty v = compile_unboxed_const Int32.(shift_left (of_int v) (to_int (shift_of_type ty))) + (* Wrapping implementation for multiplication and exponentiation. *) + + let compile_word_mul env ty = + lsb_adjust ty ^^ + G.i (Binary (Wasm.Values.I32 I32Op.Mul)) + + let compile_word_power env ty = + let rec pow () = Func.share_code2 env (name_of_type ty "pow") + (("n", I32Type), ("exp", I32Type)) [I32Type] + Wasm.Values.(fun env get_n get_exp -> + let one = compile_unboxed_const (const_of_type ty 1l) in + let (set_res, get_res) = new_local env "res" in + let mul = compile_word_mul env ty in + let square_recurse_with_shifted sanitize = + get_n ^^ get_exp ^^ compile_shrU_const 1l ^^ sanitize ^^ + pow () ^^ set_res ^^ get_res ^^ get_res ^^ mul + in get_exp ^^ G.i (Test (I32 I32Op.Eqz)) ^^ + G.if_ (ValBlockType (Some I32Type)) + one + (get_exp ^^ one ^^ G.i (Binary (I32 I32Op.And)) ^^ G.i (Test (I32 I32Op.Eqz)) ^^ + G.if_ (ValBlockType (Some I32Type)) + (square_recurse_with_shifted G.nop) + (get_n ^^ + square_recurse_with_shifted (sanitize_word_result ty) ^^ + mul))) + in pow () + end (* UnboxedSmallWord *) type comparator = Lt | Le | Ge | Gt @@ -4825,7 +4852,7 @@ let compile_smallNat_kernel env ty name op = compile_smallNat_kernel' env ty name (G.i (Binary (Wasm.Values.I32 op))) (* The first returned StackRep is for the arguments (expected), the second for the results (produced) *) -let rec compile_binop env t op = +let compile_binop env t op = if t = Type.Non then SR.Vanilla, SR.Unreachable, G.i Unreachable else StackRep.of_type t, StackRep.of_type t, @@ -4879,8 +4906,7 @@ let rec compile_binop env t op = | Type.(Prim (Int8|Int16 as ty)), SubOp -> compile_smallInt_kernel env ty "sub" I32Op.Sub | Type.(Prim Nat32), SubOp -> compile_Nat32_kernel env "sub" I64Op.Sub | Type.(Prim (Nat8|Nat16 as ty)), SubOp -> compile_smallNat_kernel env ty "sub" I32Op.Sub - | Type.(Prim (Word8|Word16|Word32 as ty)), MulOp -> UnboxedSmallWord.lsb_adjust ty ^^ - G.i (Binary (Wasm.Values.I32 I32Op.Mul)) + | Type.(Prim (Word8|Word16|Word32 as ty)), MulOp -> UnboxedSmallWord.compile_word_mul env ty | Type.(Prim Int32), MulOp -> compile_Int32_kernel env "mul" I64Op.Mul | Type.(Prim Int16), MulOp -> compile_smallInt_kernel env Type.Int16 "mul" I32Op.Mul | Type.(Prim Int8), MulOp -> compile_smallInt_kernel' env Type.Int8 "mul" @@ -4911,26 +4937,7 @@ let rec compile_binop env t op = end get_res) | Type.(Prim (Int8|Int16|Int32)), ModOp -> G.i (Binary (Wasm.Values.I32 I32Op.RemS)) - | Type.(Prim (Word8|Word16|Word32 as ty)), PowOp -> - let rec pow () = Func.share_code2 env (UnboxedSmallWord.name_of_type ty "pow") - (("n", I32Type), ("exp", I32Type)) [I32Type] - Wasm.Values.(fun env get_n get_exp -> - let one = compile_unboxed_const (UnboxedSmallWord.const_of_type ty 1l) in - let (set_res, get_res) = new_local env "res" in - let _,_,mul = compile_binop env t MulOp in - let square_recurse_with_shifted sanitize = - get_n ^^ get_exp ^^ compile_shrU_const 1l ^^ sanitize ^^ - pow () ^^ set_res ^^ get_res ^^ get_res ^^ mul - in get_exp ^^ G.i (Test (I32 I32Op.Eqz)) ^^ - G.if_ (StackRep.to_block_type env SR.UnboxedWord32) - one - (get_exp ^^ one ^^ G.i (Binary (I32 I32Op.And)) ^^ G.i (Test (I32 I32Op.Eqz)) ^^ - G.if_ (StackRep.to_block_type env SR.UnboxedWord32) - (square_recurse_with_shifted G.nop) - (get_n ^^ - square_recurse_with_shifted (UnboxedSmallWord.sanitize_word_result ty) ^^ - mul))) - in pow () + | Type.(Prim (Word8|Word16|Word32 as ty)), PowOp -> UnboxedSmallWord.compile_word_power env ty | Type.(Prim ((Nat8|Nat16) as ty)), PowOp -> Func.share_code2 env (UnboxedSmallWord.name_of_type ty "pow") (("n", I32Type), ("exp", I32Type)) [I32Type] @@ -4949,8 +4956,8 @@ let rec compile_binop env t op = G.i (Compare (Wasm.Values.I32 I32Op.LtS)) ^^ then_arithmetic_overflow env ^^ get_n ^^ UnboxedSmallWord.lsb_adjust ty ^^ get_exp ^^ UnboxedSmallWord.lsb_adjust ty ^^ - let _,_,pow = compile_binop env Type.(Prim Word32) PowOp in pow ^^ - set_res ^^ get_res ^^ enforce_unsigned_bits env bits ^^ + UnboxedSmallWord.compile_word_power env Type.Word32 ^^ set_res ^^ + get_res ^^ enforce_unsigned_bits env bits ^^ get_res ^^ UnboxedSmallWord.msb_adjust ty end get_n (* n@{0,1} ** (1+exp) == n *) @@ -4976,7 +4983,7 @@ let rec compile_binop env t op = G.i (Compare (Wasm.Values.I32 I32Op.LtS)) ^^ then_arithmetic_overflow env ^^ get_n ^^ G.i (Convert (Wasm.Values.I64 I64Op.ExtendUI32)) ^^ get_exp ^^ G.i (Convert (Wasm.Values.I64 I64Op.ExtendUI32)) ^^ - let _,_,pow = compile_binop env Type.(Prim Word64) PowOp in pow ^^ + BoxedWord64.compile_unsigned_pow env ^^ set_res ^^ get_res ^^ enforce_32_unsigned_bits env ^^ get_res ^^ G.i (Convert (Wasm.Values.I32 I32Op.WrapI64)) end @@ -5003,7 +5010,7 @@ let rec compile_binop env t op = G.i (Compare (Wasm.Values.I32 I32Op.LtS)) ^^ then_arithmetic_overflow env ^^ get_n ^^ UnboxedSmallWord.lsb_adjust ty ^^ get_exp ^^ UnboxedSmallWord.lsb_adjust ty ^^ - (let _,_,pow = compile_binop env Type.(Prim Word32) PowOp in pow) ^^ + UnboxedSmallWord.compile_word_power env Type.Word32 ^^ set_res ^^ get_res ^^ get_res ^^ enforce_signed_bits env bits ^^ get_res ^^ UnboxedSmallWord.msb_adjust ty end @@ -5046,7 +5053,7 @@ let rec compile_binop env t op = G.i (Compare (Wasm.Values.I32 I32Op.LtS)) ^^ then_arithmetic_overflow env ^^ get_n ^^ G.i (Convert (Wasm.Values.I64 I64Op.ExtendSI32)) ^^ get_exp ^^ G.i (Convert (Wasm.Values.I64 I64Op.ExtendSI32)) ^^ - (let _,_,pow = compile_binop env Type.(Prim Word64) PowOp in pow) ^^ + BoxedWord64.compile_unsigned_pow env ^^ set_res ^^ get_res ^^ get_res ^^ enforce_32_signed_bits env ^^ get_res ^^ G.i (Convert (Wasm.Values.I32 I32Op.WrapI64)) end @@ -5070,11 +5077,11 @@ let rec compile_binop env t op = get_exp ^^ compile_Int64_kernel env "pow" BigNum.compile_unsigned_pow - (powInt64_shortcut (let _,_,pow = compile_binop env Type.(Prim Word64) PowOp in pow)) + (powInt64_shortcut (BoxedWord64.compile_unsigned_pow env)) | Type.(Prim Nat64), PowOp -> compile_Nat64_kernel env "pow" BigNum.compile_unsigned_pow - (powNat64_shortcut (let _,_,pow = compile_binop env Type.(Prim Word64) PowOp in pow)) + (powNat64_shortcut (BoxedWord64.compile_unsigned_pow env)) | Type.(Prim Nat), PowOp -> BigNum.compile_unsigned_pow env | Type.(Prim Word64), AndOp -> G.i (Binary (Wasm.Values.I64 I64Op.And)) | Type.Prim Type.(Word8 | Word16 | Word32), AndOp -> G.i (Binary (Wasm.Values.I32 I32Op.And)) From 356c4f1cc04a121d0e8aa23e89ba5c2ebaeaec6f Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Mon, 15 Jul 2019 15:17:59 -0700 Subject: [PATCH 0260/1176] Node test for IDL JS binding --- default.nix | 16 +++++++++++++++- src/idllib/compile_js.ml | 19 +++++++++++-------- test/idl/ok/actor.js.ok | 11 ++++++----- test/idl/ok/cyclic.js.ok | 5 +++-- test/idl/ok/diamond.js.ok | 5 +++-- test/idl/ok/fields.js.ok | 5 +++-- test/idl/ok/import.js.ok | 7 ++++--- test/idl/ok/import1.js.ok | 5 +++-- test/idl/ok/import3.js.ok | 9 +++++---- test/idl/ok/integer.js.ok | 9 +++++---- test/idl/ok/px.js.ok | 5 +++-- test/idl/ok/recursion.js.ok | 9 +++++---- test/idl/ok/test.js.ok | 19 ++++++++++--------- test/idl/ok/unicode.js.ok | 11 ++++++----- test/run.sh | 10 ++++++++++ 15 files changed, 92 insertions(+), 53 deletions(-) diff --git a/default.nix b/default.nix index f47012d706b..3436bb7bd70 100644 --- a/default.nix +++ b/default.nix @@ -7,6 +7,7 @@ let llvm = import ./nix/llvm.nix { system = nixpkgs.system; }; in let stdenv = nixpkgs.stdenv; in +let lib = stdenv.lib; in let subpath = p: import ./nix/gitSource.nix p; in @@ -38,10 +39,20 @@ let real-dvm = else null else dvm; in +# Include js-client +let js-client = + let dev = builtins.fetchGit { + url = "ssh://git@github.com/dfinity-lab/dev"; + ref = "master"; + rev = "a556b011d957d3174b6c4017d76dd510791d8922"; + }; in + (import dev { system = nixpkgs.system; }).js-dfinity-client; in + let commonBuildInputs = [ nixpkgs.ocaml nixpkgs.dune nixpkgs.ocamlPackages.atdgen + nixpkgs.ocamlPackages.base nixpkgs.ocamlPackages.findlib nixpkgs.ocamlPackages.menhir nixpkgs.ocamlPackages.num @@ -136,6 +147,7 @@ rec { nixpkgs.bash nixpkgs.perl filecheck + js-client ] ++ (if test-dvm then [ real-dvm ] else []) ++ llvmBuildInputs; @@ -146,6 +158,7 @@ rec { export ASC=asc export AS_LD=as-ld export DIDC=didc + export JSCLIENT=${js-client} asc --version '' + (if test-dvm then '' @@ -248,7 +261,7 @@ rec { didc = stdenv.mkDerivation { name = "didc"; src = subpath ./src; - buildInputs = commonBuildInputs; + buildInputs = [ commonBuildInputs ]; buildPhase = '' make DUNE_OPTS="--display=short --profile release" didc ''; @@ -405,6 +418,7 @@ rec { shellHook = llvmEnv; TOMMATHSRC = libtommath; + JSCLIENT = js-client; NIX_FONTCONFIG_FILE = users-guide.NIX_FONTCONFIG_FILE; } else null; diff --git a/src/idllib/compile_js.ml b/src/idllib/compile_js.ml index 67d47cb082d..576018e6a59 100644 --- a/src/idllib/compile_js.ml +++ b/src/idllib/compile_js.ml @@ -172,19 +172,22 @@ let pp_actor ppf actor = pp_open_hovbox ppf 1; kwd ppf "const"; (match actor.it with - | ActorD (x, {it=ServT tp; _}) -> - id ppf x; space ppf (); kwd ppf "="; kwd ppf "new"; - str ppf "IDL.ActorInterface({"; - concat ppf pp_meth "," tp; - str ppf "})" - | ActorD (x, {it=VarT var; _}) -> id ppf x; space ppf (); kwd ppf "="; id ppf var - | ActorD (x, _) -> assert false + | ActorD (x, {it=t; _}) -> + let x = ("actor_" ^ x.it) @@ x.at in + match t with + | ServT tp -> + id ppf x; space ppf (); kwd ppf "="; kwd ppf "new"; + str ppf "IDL.ActorInterface({"; + concat ppf pp_meth "," tp; + str ppf "})" + | VarT var -> id ppf x; space ppf (); kwd ppf "="; id ppf var + | _ -> assert false ); pp_close_box ppf () let pp_header ppf () = pp_open_vbox ppf 0; - str ppf "const IDL = require('./IDL')"; + str ppf "const IDL = require('IDL')"; pp_close_box ppf () let pp_prog ppf env prog = diff --git a/test/idl/ok/actor.js.ok b/test/idl/ok/actor.js.ok index 1e768735ea6..2225b3b1fd9 100644 --- a/test/idl/ok/actor.js.ok +++ b/test/idl/ok/actor.js.ok @@ -1,8 +1,9 @@ +const IDL = require('IDL') const o = IDL.Rec() -const f = IDL.message(IDL.Obj({'0': IDL.Int8}), IDL.Obj({'0': IDL.Int8})) -const h = IDL.message(IDL.Obj({'0': f}), IDL.Obj({'0': f})) +const f = IDL.Message(IDL.Obj({'0': IDL.Int8}), IDL.Obj({'0': IDL.Int8})) +const h = IDL.Message(IDL.Obj({'0': f}), IDL.Obj({'0': f})) const g = f o.fill(IDL.Opt(o)) -const g = new IDL.ActorInterface({ - 'f': IDL.message(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': h})), 'g': f, - 'h': g, 'o': IDL.message(IDL.Obj({'0': o}), IDL.Obj({'0': o}))}) +const actor_g = new IDL.ActorInterface({ + 'f': IDL.Message(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': h})), 'g': f, + 'h': g, 'o': IDL.Message(IDL.Obj({'0': o}), IDL.Obj({'0': o}))}) diff --git a/test/idl/ok/cyclic.js.ok b/test/idl/ok/cyclic.js.ok index 2926b862188..f04f438c3ba 100644 --- a/test/idl/ok/cyclic.js.ok +++ b/test/idl/ok/cyclic.js.ok @@ -1,3 +1,4 @@ +const IDL = require('IDL') const A = IDL.Rec() const C = A const B = IDL.Opt(C) @@ -5,7 +6,7 @@ A.fill(IDL.Opt(B)) const Z = A const Y = Z const X = Y -const S = new IDL.ActorInterface({ +const actor_S = new IDL.ActorInterface({ 'f': - IDL.message(IDL.Obj({'0': A, '1': B, '2': C, '3': X, '4': Y, '5': Z}), + IDL.Message(IDL.Obj({'0': A, '1': B, '2': C, '3': X, '4': Y, '5': Z}), IDL.Obj({}))}) diff --git a/test/idl/ok/diamond.js.ok b/test/idl/ok/diamond.js.ok index 55be9ac8fa3..360efbdc716 100644 --- a/test/idl/ok/diamond.js.ok +++ b/test/idl/ok/diamond.js.ok @@ -1,6 +1,7 @@ +const IDL = require('IDL') const t = IDL.Nat const t2 = IDL.Arr(t) const t3 = IDL.Opt(t) const t1 = IDL.Obj({'0': t2, '1': t3, '2': t}) -const S = new IDL.ActorInterface({ - 'f': IDL.message(IDL.Obj({'0': t, '1': t2, '2': t3}), IDL.Obj({'0': t1}))}) +const actor_S = new IDL.ActorInterface({ + 'f': IDL.Message(IDL.Obj({'0': t, '1': t2, '2': t3}), IDL.Obj({'0': t1}))}) diff --git a/test/idl/ok/fields.js.ok b/test/idl/ok/fields.js.ok index eef5930f0d4..4e2493fcfad 100644 --- a/test/idl/ok/fields.js.ok +++ b/test/idl/ok/fields.js.ok @@ -1,3 +1,4 @@ +const IDL = require('IDL') const A = IDL.Obj({'0': IDL.Nat, '1': IDL.Nat, '2': IDL.Nat}) const B = IDL.Obj({'0': IDL.Arr(IDL.Nat8), '35': IDL.Arr(IDL.Nat8), '36': IDL.Nat, @@ -12,7 +13,7 @@ const nest_record = IDL.Obj({'0': IDL.Nat, '1': IDL.Nat, '2': IDL.Nat, '3': IDL.Obj({'0': IDL.Nat, '1': IDL.Nat, '2': IDL.Nat}), '4': IDL.Nat, '5': IDL.Nat, '6': IDL.Nat, '7': A, '8': B, '9': C, '10': IDL.Nat}) -const S = new IDL.ActorInterface({ +const actor_S = new IDL.ActorInterface({ 'f': - IDL.message(IDL.Obj({'0': A, '1': B, '2': C, '3': nest_record}), + IDL.Message(IDL.Obj({'0': A, '1': B, '2': C, '3': nest_record}), IDL.Obj({}))}) diff --git a/test/idl/ok/import.js.ok b/test/idl/ok/import.js.ok index a2d8865d911..fa9377df38d 100644 --- a/test/idl/ok/import.js.ok +++ b/test/idl/ok/import.js.ok @@ -1,3 +1,4 @@ +const IDL = require('IDL') const t = IDL.Arr(IDL.Nat8) const t1 = t const UserId = IDL.Nat @@ -10,9 +11,9 @@ const EntId = const OpEntId = IDL.Opt(EntId) const IdErr = IDL.Obj({'idErr': OpEntId}) const Inventory = IDL.Obj({'produce_id': IDL.Nat, 'quantity': IDL.Nat}) -const S = new IDL.ActorInterface({ +const actor_S = new IDL.ActorInterface({ 'f': - IDL.message(IDL.Obj({'0': t, '1': t1, '2': t2}), + IDL.Message(IDL.Obj({'0': t, '1': t1, '2': t2}), IDL.Obj({'0': list, '1': IdErr})), 'getInventory': - IDL.message(IDL.Obj({'producer_id': IDL.Nat}), IDL.Obj({'0': Inventory}))}) + IDL.Message(IDL.Obj({'producer_id': IDL.Nat}), IDL.Obj({'0': Inventory}))}) diff --git a/test/idl/ok/import1.js.ok b/test/idl/ok/import1.js.ok index 25ed302284f..23a298b9391 100644 --- a/test/idl/ok/import1.js.ok +++ b/test/idl/ok/import1.js.ok @@ -1,6 +1,7 @@ +const IDL = require('IDL') const t = IDL.Arr(IDL.Nat8) const t1 = t const UserId = IDL.Nat const t2 = UserId -const S = new IDL.ActorInterface({ - 'f': IDL.message(IDL.Obj({'0': t, '1': t1, '2': t2}), IDL.Obj({}))}) +const actor_S = new IDL.ActorInterface({ + 'f': IDL.Message(IDL.Obj({'0': t, '1': t1, '2': t2}), IDL.Obj({}))}) diff --git a/test/idl/ok/import3.js.ok b/test/idl/ok/import3.js.ok index b88df20df65..517f9849fb4 100644 --- a/test/idl/ok/import3.js.ok +++ b/test/idl/ok/import3.js.ok @@ -1,15 +1,16 @@ +const IDL = require('IDL') const B = IDL.Rec() const list = IDL.Rec() const s = IDL.Rec() const stream = IDL.Rec() const tree = IDL.Rec() -const t = IDL.message(IDL.Obj({'server': s}), IDL.Obj({})) +const t = IDL.Message(IDL.Obj({'server': s}), IDL.Obj({})) const node = IDL.Obj({'head': IDL.Nat, 'tail': list}) list.fill(IDL.Opt(node)) stream.fill( IDL.Opt( IDL.Obj({'head': IDL.Nat, - 'next': IDL.message(IDL.Obj({}), IDL.Obj({'0': stream}))})) + 'next': IDL.Message(IDL.Obj({}), IDL.Obj({'0': stream}))})) ) tree.fill( IDL.Variant({ @@ -20,6 +21,6 @@ B.fill(IDL.Opt(A)) s.fill( new IDL.ActorInterface({'f': t, 'g': - IDL.message(IDL.Obj({'0': list}), + IDL.Message(IDL.Obj({'0': list}), IDL.Obj({'2': stream, '1': tree, '0': B}))})) -const S = s +const actor_S = s diff --git a/test/idl/ok/integer.js.ok b/test/idl/ok/integer.js.ok index e9c26dee5e3..436f404354e 100644 --- a/test/idl/ok/integer.js.ok +++ b/test/idl/ok/integer.js.ok @@ -1,4 +1,5 @@ -const num = new IDL.ActorInterface({ - 'f': IDL.message(IDL.Obj({'0': IDL.Nat8}), IDL.Obj({'0': IDL.Int16})), - 'g': IDL.message(IDL.Obj({'0': IDL.Nat64}), IDL.Obj({'0': IDL.Int64})), - 'h': IDL.message(IDL.Obj({'0': IDL.Int8}), IDL.Obj({'0': IDL.Nat}))}) +const IDL = require('IDL') +const actor_num = new IDL.ActorInterface({ + 'f': IDL.Message(IDL.Obj({'0': IDL.Nat8}), IDL.Obj({'0': IDL.Int16})), + 'g': IDL.Message(IDL.Obj({'0': IDL.Nat64}), IDL.Obj({'0': IDL.Int64})), + 'h': IDL.Message(IDL.Obj({'0': IDL.Int8}), IDL.Obj({'0': IDL.Nat}))}) diff --git a/test/idl/ok/px.js.ok b/test/idl/ok/px.js.ok index 95bc9c30625..06ea8d3f87f 100644 --- a/test/idl/ok/px.js.ok +++ b/test/idl/ok/px.js.ok @@ -1,3 +1,4 @@ +const IDL = require('IDL') const UserId = IDL.Nat const RegionId = IDL.Nat const ProducerId = IDL.Nat @@ -11,7 +12,7 @@ const EntId = IDL.Obj({'region': RegionId, 'user': UserId, 'truckType': TruckTypeId}) const OpEntId = IDL.Opt(EntId) const IdErr = IDL.Obj({'idErr': OpEntId}) -const ProduceExchange = new IDL.ActorInterface({ +const actor_ProduceExchange = new IDL.ActorInterface({ 'getInventory': - IDL.message(IDL.Obj({'producer_id': IDL.Nat, '3667444713': UserInfo}), + IDL.Message(IDL.Obj({'producer_id': IDL.Nat, '3667444713': UserInfo}), IDL.Obj({'0': Inventory, '1': IdErr}))}) diff --git a/test/idl/ok/recursion.js.ok b/test/idl/ok/recursion.js.ok index e89ecb02db0..1b71a15819f 100644 --- a/test/idl/ok/recursion.js.ok +++ b/test/idl/ok/recursion.js.ok @@ -1,15 +1,16 @@ +const IDL = require('IDL') const B = IDL.Rec() const list = IDL.Rec() const s = IDL.Rec() const stream = IDL.Rec() const tree = IDL.Rec() -const t = IDL.message(IDL.Obj({'server': s}), IDL.Obj({})) +const t = IDL.Message(IDL.Obj({'server': s}), IDL.Obj({})) const node = IDL.Obj({'head': IDL.Nat, 'tail': list}) list.fill(IDL.Opt(node)) stream.fill( IDL.Opt( IDL.Obj({'head': IDL.Nat, - 'next': IDL.message(IDL.Obj({}), IDL.Obj({'0': stream}))})) + 'next': IDL.Message(IDL.Obj({}), IDL.Obj({'0': stream}))})) ) tree.fill( IDL.Variant({ @@ -20,6 +21,6 @@ B.fill(IDL.Opt(A)) s.fill( new IDL.ActorInterface({'f': t, 'g': - IDL.message(IDL.Obj({'0': list}), + IDL.Message(IDL.Obj({'0': list}), IDL.Obj({'2': stream, '1': tree, '0': B}))})) -const A = s +const actor_A = s diff --git a/test/idl/ok/test.js.ok b/test/idl/ok/test.js.ok index 8e2a1f185cf..dc13ef34670 100644 --- a/test/idl/ok/test.js.ok +++ b/test/idl/ok/test.js.ok @@ -1,22 +1,23 @@ +const IDL = require('IDL') const my_type = IDL.Nat const B = my_type const message = IDL.Obj({'25': B, '26': IDL.None, 'name': IDL.Text}) const broker = new IDL.ActorInterface({ 'find': - IDL.message(IDL.Obj({'name': IDL.Text}), + IDL.Message(IDL.Obj({'name': IDL.Text}), IDL.Obj({ '0': - new IDL.ActorInterface({'up': IDL.message(IDL.Obj({}), IDL.Obj({})), - 'current': IDL.message(IDL.Obj({}), IDL.Obj({'0': IDL.Nat}))}) + new IDL.ActorInterface({'up': IDL.Message(IDL.Obj({}), IDL.Obj({})), + 'current': IDL.Message(IDL.Obj({}), IDL.Obj({'0': IDL.Nat}))}) })) }) -const server = new IDL.ActorInterface({ +const actor_server = new IDL.ActorInterface({ 'addUser': - IDL.message(IDL.Obj({'name': IDL.Text, 'age': IDL.Nat8}), + IDL.Message(IDL.Obj({'name': IDL.Text, 'age': IDL.Nat8}), IDL.Obj({'id': IDL.Nat64})), 'userName': - IDL.message(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({'0': IDL.Text})), - 'userAge': IDL.message(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({'0': IDL.Nat8})), - 'deleteUser': IDL.message(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({})), - 'f': IDL.message(IDL.Obj({'0': message}), IDL.Obj({'0': broker}))}) + IDL.Message(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({'0': IDL.Text})), + 'userAge': IDL.Message(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({'0': IDL.Nat8})), + 'deleteUser': IDL.Message(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({})), + 'f': IDL.Message(IDL.Obj({'0': message}), IDL.Obj({'0': broker}))}) diff --git a/test/idl/ok/unicode.js.ok b/test/idl/ok/unicode.js.ok index 6660ac1ac96..47b5d653c9c 100644 --- a/test/idl/ok/unicode.js.ok +++ b/test/idl/ok/unicode.js.ok @@ -1,11 +1,12 @@ +const IDL = require('IDL') const A = IDL.Obj({'📦🍦': IDL.Nat, '字段名': IDL.Nat, '字 段 名2': IDL.Nat }) const B = IDL.Variant({'': IDL.Unit, '空的': IDL.Unit, ' 空的 ': IDL.Unit, '1⃣️2⃣️3⃣️': IDL.Unit}) -const C = new IDL.ActorInterface({ - '函数名': IDL.message(IDL.Obj({'0': A}), IDL.Obj({'0': B})), - '': IDL.message(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': IDL.Nat})), - '👀': IDL.message(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': IDL.Nat})), - '✈️ 🚗 ⛱️ ': IDL.message(IDL.Obj({}), IDL.Obj({}))}) +const actor_C = new IDL.ActorInterface({ + '函数名': IDL.Message(IDL.Obj({'0': A}), IDL.Obj({'0': B})), + '': IDL.Message(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': IDL.Nat})), + '👀': IDL.Message(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': IDL.Nat})), + '✈️ 🚗 ⛱️ ': IDL.Message(IDL.Obj({}), IDL.Obj({}))}) diff --git a/test/run.sh b/test/run.sh index 627ccef2afe..3a98ad4b2dd 100755 --- a/test/run.sh +++ b/test/run.sh @@ -25,6 +25,8 @@ DIDC=${DIDC:-$(realpath $(dirname $0)/../src/didc)} export AS_LD WASM=${WASM:-wasm} DVM_WRAPPER=$(realpath $(dirname $0)/dvm.sh) +JSCLIENT=${JSCLIENT:-$(realpath $(dirname $0)/../../dev/experimental/js-dfinity-client)} +NODE=node ECHO=echo while getopts "ads" o; do @@ -227,6 +229,14 @@ do $ECHO -n " [js]" $DIDC --js $base.did > $out/$base.js 2>&1 diff_files="$diff_files $base.js" + + if [ -e $out/$base.js ] + then + $ECHO -n " [node]" + export NODE_PATH=$NODE_PATH:$JSCLIENT/node_modules:$JSCLIENT/src + $NODE $out/$base.js > $out/$base.err 2>&1 + diff_files="$diff_files $base.err" + fi fi fi $ECHO "" From 445d92449a1ec793f6a344c4f36b03e230bc3ed1 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Mon, 15 Jul 2019 15:22:01 -0700 Subject: [PATCH 0261/1176] manual sync with master --- default.nix | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/default.nix b/default.nix index 3436bb7bd70..d2b33aa9122 100644 --- a/default.nix +++ b/default.nix @@ -52,7 +52,6 @@ let commonBuildInputs = [ nixpkgs.ocaml nixpkgs.dune nixpkgs.ocamlPackages.atdgen - nixpkgs.ocamlPackages.base nixpkgs.ocamlPackages.findlib nixpkgs.ocamlPackages.menhir nixpkgs.ocamlPackages.num @@ -261,7 +260,7 @@ rec { didc = stdenv.mkDerivation { name = "didc"; src = subpath ./src; - buildInputs = [ commonBuildInputs ]; + buildInputs = commonBuildInputs; buildPhase = '' make DUNE_OPTS="--display=short --profile release" didc ''; From 10d9bbd39f0937f19d8fddaa1512c5322c882434 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Mon, 15 Jul 2019 15:34:43 -0700 Subject: [PATCH 0262/1176] add IDL to quick.mk --- test/quick.mk | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/quick.mk b/test/quick.mk index 9163100f733..50ebab5d391 100644 --- a/test/quick.mk +++ b/test/quick.mk @@ -4,6 +4,7 @@ TO-TEST = \ $(patsubst %.as,_out/%.done,$(wildcard *.as)) \ $(patsubst %.sh,_out/%.done,$(wildcard *.sh)) \ $(patsubst %.wat,_out/%.done,$(wildcard *.wat)) \ + $(patsubst %.did,_out/%.done,$(wildcard *.did)) \ .PHONY: quick @@ -20,3 +21,5 @@ _out/%.done: %.sh $(wildcard ../../src/asc) ../run.sh | _out @+ (../run.sh $(RUNFLAGS) $< > $@.tmp && mv $@.tmp $@) || (cat $@.tmp; rm -f $@.tmp; false) _out/%.done: %.wat $(wildcard ../../src/asc) ../run.sh | _out @+ (../run.sh $(RUNFLAGS) $< > $@.tmp && mv $@.tmp $@) || (cat $@.tmp; rm -f $@.tmp; false) +_out/%.done: %.did $(wildcard ../../src/didc) ../run.sh | _out + @+ (../run.sh $(RUNFLAGS) $< > $@.tmp && mv $@.tmp $@) || (cat $@.tmp; rm -f $@.tmp; false) From 11ef6a4a9abddfb93c20a5f9a9afc1fae42e9479 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Mon, 15 Jul 2019 15:49:54 -0700 Subject: [PATCH 0263/1176] try fix nix --- default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/default.nix b/default.nix index d2b33aa9122..00e328a3f27 100644 --- a/default.nix +++ b/default.nix @@ -145,6 +145,7 @@ rec { nixpkgs.wabt nixpkgs.bash nixpkgs.perl + nixpkgs.nodejs-10_x filecheck js-client ] ++ From 6b0a9a1de8e041e81c81a88365a7b4fb50513db9 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Mon, 15 Jul 2019 16:03:54 -0700 Subject: [PATCH 0264/1176] minor fix --- src/idllib/compile_js.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/idllib/compile_js.ml b/src/idllib/compile_js.ml index 576018e6a59..4e774298869 100644 --- a/src/idllib/compile_js.ml +++ b/src/idllib/compile_js.ml @@ -172,9 +172,9 @@ let pp_actor ppf actor = pp_open_hovbox ppf 1; kwd ppf "const"; (match actor.it with - | ActorD (x, {it=t; _}) -> + | ActorD (x, t) -> let x = ("actor_" ^ x.it) @@ x.at in - match t with + match t.it with | ServT tp -> id ppf x; space ppf (); kwd ppf "="; kwd ppf "new"; str ppf "IDL.ActorInterface({"; From 119c307fc4558a75e3d727b50b10d67d02e0c48e Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 16 Jul 2019 10:10:28 +0200 Subject: [PATCH 0265/1176] Minor cleanup in the nix files but does not yet include https://github.com/dfinity-lab/dev/pull/1101, I was hoping to get that into `master` first. --- default.nix | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/default.nix b/default.nix index 00e328a3f27..08aea1044df 100644 --- a/default.nix +++ b/default.nix @@ -24,29 +24,22 @@ let ocaml_vlq = import ./nix/ocaml-vlq.nix { let ocaml_bisect_ppx = import ./nix/ocaml-bisect_ppx.nix nixpkgs; in let ocaml_bisect_ppx-ocamlbuild = import ./nix/ocaml-bisect_ppx-ocamlbuild.nix nixpkgs; in +let dev = import (builtins.fetchGit { + url = "ssh://git@github.com/dfinity-lab/dev"; + ref = "master"; + rev = "65c295edfc4164ca89c129d501a403fa246d3d36"; +}) { system = nixpkgs.system; }; in + # Include dvm let real-dvm = if dvm == null - then - if test-dvm - then - let dev = builtins.fetchGit { - url = "ssh://git@github.com/dfinity-lab/dev"; - ref = "master"; - rev = "65c295edfc4164ca89c129d501a403fa246d3d36"; - }; in - (import dev { system = nixpkgs.system; }).dvm + then if test-dvm + then dev.dvm else null else dvm; in # Include js-client -let js-client = - let dev = builtins.fetchGit { - url = "ssh://git@github.com/dfinity-lab/dev"; - ref = "master"; - rev = "a556b011d957d3174b6c4017d76dd510791d8922"; - }; in - (import dev { system = nixpkgs.system; }).js-dfinity-client; in +let js-client = dev.js-dfinity-client; in let commonBuildInputs = [ nixpkgs.ocaml @@ -145,7 +138,7 @@ rec { nixpkgs.wabt nixpkgs.bash nixpkgs.perl - nixpkgs.nodejs-10_x + nixpkgs.nodejs-10_x filecheck js-client ] ++ From 8afd063dda939c924acde4828e85544c27a6ee04 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 16 Jul 2019 11:15:41 +0200 Subject: [PATCH 0266/1176] Claudio/f bounds (#552) * manually port tests from PR #523 * manually port tests from PR #523 * more realistic use of f-bounded polymorphism * add newline at end * manually merge check_ir.ml from PR #523 to support f-bounds; restore rejection of open type definitions; update test output that has changed; adapt f-bounds.as to work sans open type definitions * add f-bounds-fail negative test * manually port f-bounds-fail.as test from PR #523 to test f-bounds; adapt test to avoid open type definitions * update comments; typos * Apply suggestions from code review Co-Authored-By: Andreas Rossberg * update tests --- src/as_frontend/typing.ml | 65 ++++++---- src/ir_def/check_ir.ml | 86 +++++++------- test/fail/f-bounds-fail.as | 87 ++++++++++++++ test/fail/ok/abstract-msgs.tc.ok | 20 ++-- test/fail/ok/asyncret1.tc.ok | 2 +- test/fail/ok/f-bounds-fail.tc.ok | 176 ++++++++++++++++++++++++++++ test/fail/ok/issue167.tc.ok | 1 - test/fail/ok/modexp5.tc.ok | 2 +- test/fail/ok/pat-inconsistent.tc.ok | 2 +- test/run/f-bounds.as | 87 ++++++++++++++ test/run/ott-typeclasses.as | 69 +++++++++++ test/run/self-bounds.as | 7 ++ 12 files changed, 522 insertions(+), 82 deletions(-) create mode 100644 test/fail/f-bounds-fail.as create mode 100644 test/fail/ok/f-bounds-fail.tc.ok create mode 100644 test/run/f-bounds.as create mode 100644 test/run/ott-typeclasses.as create mode 100644 test/run/self-bounds.as diff --git a/src/as_frontend/typing.ml b/src/as_frontend/typing.ml index b893cff7216..709e55ea22e 100644 --- a/src/as_frontend/typing.ml +++ b/src/as_frontend/typing.ml @@ -175,8 +175,10 @@ and check_typ' env typ : T.typ = match typ.it with | PathT (path, typs) -> let c = check_typ_path env path in + let ts = List.map (check_typ env) typs in let T.Def (tbs, _) | T.Abs (tbs, _) = Con.kind c in - let ts = check_typ_bounds env tbs typs typ.at in + let tbs' = List.map (fun {T.var; T.bound} -> {T.var; bound = T.open_ ts bound}) tbs in + check_typ_bounds env tbs' ts typs typ.at; T.Con (c, ts) | PrimT "Any" -> T.Any | PrimT "None" -> T.Non @@ -253,8 +255,13 @@ and check_typ_tag env typ_tag = T.{lab = tag.it; typ = t} and check_typ_binds env typ_binds : T.con list * T.typ list * Scope.typ_env * Scope.con_env = + (* TODO: rule out cyclic bounds *) let xs = List.map (fun typ_bind -> typ_bind.it.var.it) typ_binds in - let cs = List.map (fun n -> Con.fresh n (T.Abs ([], T.Pre))) xs in + let cs = + List.map2 (fun x tb -> + match tb.note with + | Some c -> c + | None -> Con.fresh x (T.Abs ([], T.Pre))) xs typ_binds in let te = List.fold_left2 (fun te typ_bind c -> let id = typ_bind.it.var in if T.Env.mem id.it te then @@ -264,32 +271,42 @@ and check_typ_binds env typ_binds : T.con list * T.typ list * Scope.typ_env * Sc let pre_env' = add_typs {env with pre = true} xs cs in let ts = List.map (fun typ_bind -> check_typ pre_env' typ_bind.it.bound) typ_binds in let ks = List.map (fun t -> T.Abs ([], t)) ts in - List.iter2 T.set_kind cs ks; + List.iter2 (fun c k -> + match Con.kind c with + | T.Abs (_, T.Pre) -> T.set_kind c k + | k' -> assert (T.eq_kind k k') + ) cs ks; let env' = add_typs env xs cs in let _ = List.map (fun typ_bind -> check_typ env' typ_bind.it.bound) typ_binds in List.iter2 (fun typ_bind c -> typ_bind.note <- Some c) typ_binds cs; cs, ts, te, T.ConSet.of_list cs -and check_typ_bounds env (tbs : T.bind list) typs at : T.typ list = - match tbs, typs with - | tb::tbs', typ::typs' -> - let t = check_typ env typ in - if not env.pre then begin - if not (T.sub t tb.T.bound) then - local_error env typ.at - "type argument\n %s\ndoes not match parameter bound\n %s" - (T.string_of_typ_expand t) - (T.string_of_typ_expand tb.T.bound) - end; - let ts' = check_typ_bounds env tbs' typs' at in - t::ts' - | [], [] -> [] - | [], _ -> local_error env at "too many type arguments"; [] - | _, [] -> error env at "too few type arguments" +and check_typ_bounds env (tbs : T.bind list) (ts : T.typ list) typs at = + let pars = List.length tbs in + let args = List.length ts in + if pars > args then + error env at "too few type arguments"; + if pars < args then + error env at "too many type arguments"; + let rec go tbs' ts' typs' = + match tbs', ts', typs' with + | tb::tbs', t::ts', typ::typs' -> + if not env.pre then + let u = T.open_ ts tb.T.bound in + if not (T.sub t u) then + local_error env typ.at + "type argument\n %s\ndoes not match parameter bound\n %s" + (T.string_of_typ_expand t) + (T.string_of_typ_expand u); + go tbs' ts' typs' + | [], [], [] -> () + | _ -> assert false + in go tbs ts typs and check_inst_bounds env tbs typs at = - let tys = check_typ_bounds env tbs typs at in - tys + let ts = List.map (check_typ env) typs in + check_typ_bounds env tbs ts typs at; + ts (* Literals *) @@ -626,7 +643,7 @@ and infer_exp'' env exp : T.typ = error env exp1.at "expected function type, but expression produces type\n %s" (T.string_of_typ_expand t1) - in + in let ts = check_inst_bounds env tbs insts exp.at in let t_arg = T.open_ ts t_arg in let t_ret = T.open_ ts t_ret in @@ -1492,7 +1509,7 @@ and infer_dec_typdecs env dec : Scope.t = 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 + let tbs = List.map2 (fun c' t -> {T.var = Con.name c'; bound = T.close cs t}) cs ts in let k = T.Def (tbs, T.close cs t) in begin let is_typ_param c = @@ -1522,7 +1539,7 @@ and infer_dec_typdecs env dec : Scope.t = let self_typ = T.Con (c, List.map (fun c -> T.Con (c, [])) cs) in let env'' = add_val (adjoin_vals env' ve) self_id.it self_typ in let t = infer_obj env'' sort.it fields dec.at in - let tbs = List.map2 (fun c t -> {T.var = Con.name c; bound = T.close cs t}) cs ts in + let tbs = List.map2 (fun c' t -> {T.var = Con.name c'; bound = T.close cs t}) cs ts in let k = T.Def (tbs, T.close cs t) in Scope.{ empty with typ_env = T.Env.singleton id.it c; diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index ea47c5c6777..35c745847ae 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -5,20 +5,21 @@ open Source module T = Type module E = Ir_effect -(* TODO: remove DecE from syntax, replace by BlockE [dec] *) -(* TODO: check constraint matching supports recursive bounds *) - (* TODO: make note immutable, perhaps just using type abstraction *) (* TODO: - dereferencing is still implicit in the IR (see immut_typ below) - consider making it explicit as part of desugaring. - *) + dereferencing is still implicit in the IR (see immut_typ below); + consider making it explicit as part of desugaring. +*) (* TODO: enforce second-class nature of T.Mut? in check_typ *) + (* TODO: check escape of free mutables via actors *) -(* helpers *) +(* Helpers *) + let (==>) p q = not p || q + let typ = E.typ let immute_typ p = @@ -128,12 +129,18 @@ let rec check_typ env typ : unit = | T.Var (s, i) -> error env no_region "free type variable %s, index %i" s i | T.Con (c, typs) -> - begin match Con.kind c with - | T.Def (tbs, _) -> check_typ_bounds env tbs typs no_region (* TODO(Claudio): - check bodies of anonymous T.Defs since they won't get checked elsewhere *) - | T.Abs (tbs, _) -> - check env no_region (T.ConSet.mem c env.cons) "free type constructor %s" (Con.name c); - check_typ_bounds env tbs typs no_region + List.iter (check_typ env) typs; + begin + match Con.kind c with + | T.Def (tbs,_) -> + if not (T.ConSet.mem c env.cons) then + (* an anonymous recursive type, check its def but beware recursion + future: use a visited set *) + check_con {env with cons = T.ConSet.add c env.cons} c; + check_typ_bounds env tbs typs no_region + | T.Abs (tbs, _) -> + check env no_region (T.ConSet.mem c env.cons) "free type constructor"; + check_typ_bounds env tbs typs no_region end | T.Any -> () | T.Non -> () @@ -195,20 +202,15 @@ let rec check_typ env typ : unit = * "serialized type is not sharable:\n %s" (T.string_of_typ_expand typ) *) | T.Typ c -> - check env no_region (T.ConSet.mem c env.cons) "free type constructor %s" (Con.name c); - -(* -and check_kind env k = - let (binds,typ) = - match k with - | T.Abs(binds,typ) - | T.Def(binds,typ) -> (binds,typ) - in - let cs,ce = check_typ_binds env binds in - let ts = List.map (fun c -> T.Con(c,[])) cs in + check_con env c + +and check_con env c = + let env = {env with cons = T.ConSet.add c env.cons} in + let T.Abs (binds,typ) | T.Def (binds, typ) = Con.kind c in + let cs, ce = check_typ_binds env binds in + let ts = List.map (fun c -> T.Con (c, [])) cs in let env' = adjoin_cons env ce in - check_typ env' (T.open_ ts typ); -*) + check_typ env' (T.open_ ts typ) and check_typ_field env s typ_field : unit = let T.{lab; typ} = typ_field in @@ -224,7 +226,7 @@ and check_typ_field env s typ_field : unit = and check_typ_binds env typ_binds : T.con list * con_env = let ts = Type.open_binds typ_binds in - let cs = List.map (function T.Con (c, []) -> c | _ -> assert false) ts in + let cs = List.map (function T.Con (c, []) -> c | _ -> assert false) ts in let env' = add_typs env cs in let _ = List.map (fun typ_bind -> @@ -235,17 +237,21 @@ and check_typ_binds env typ_binds : T.con list * con_env = cs, T.ConSet.of_list cs and check_typ_bounds env (tbs : T.bind list) typs at : unit = - match tbs, typs with - | tb::tbs', typ::typs' -> - check_typ env typ; - check env at (T.sub typ tb.T.bound) - "type argument does not match parameter bound"; - check_typ_bounds env tbs' typs' at - | [], [] -> () - | [], _ -> error env at "too many type arguments" - | _, [] -> error env at "too few type arguments" + let pars = List.length tbs in + let args = List.length typs in + if pars < args then + error env at "too many type arguments"; + if pars > args then + error env at "too few type arguments"; + List.iter2 + (fun tb typ -> + check env at (T.sub typ (T.open_ typs tb.T.bound)) + "type argument does not match parameter bound") + tbs typs + and check_inst_bounds env tbs typs at = + List.iter (check_typ env) typs; check_typ_bounds env tbs typs at (* Literals *) @@ -721,15 +727,7 @@ and check_dec env dec = typ exp <: T.as_immut t0 | TypD c -> check (T.ConSet.mem c env.cons) "free type constructor"; - let (binds, typ) = - match Con.kind c with - | T.Abs (binds, typ) - | T.Def (binds, typ) -> (binds, typ) - in - let cs, ce = check_typ_binds env binds in - let ts = List.map (fun c -> T.Con (c, [])) cs in - let env' = adjoin_cons env ce in - check_typ env' (T.open_ ts typ) + check_con env c and check_decs env decs = List.iter (check_dec env) decs; diff --git a/test/fail/f-bounds-fail.as b/test/fail/f-bounds-fail.as new file mode 100644 index 00000000000..5d10485c67b --- /dev/null +++ b/test/fail/f-bounds-fail.as @@ -0,0 +1,87 @@ +type Cast< A <: B, B> = A -> B; + +let f = (func(x:Int):Nat = 0) : Cast; + +func f2a< A <: B, B> ( x : A ) : B = x; + +func f2b< B, A <: B> ( x : A ) : B = x; + +func f3a< A <: B, B /* <: C */ , C> ( x : A ) : C = x; +func f3b< B /* <: C */, A <: B, C> ( x : A ) : C = x; +func f3c< C, B /* <: C */, A <: B> ( x : A ) : C = x; + +type T1< A <: B, B /* <: C */, C> = Cast; +type T2< B /* <: C */, A <: B, C> = Cast; +type T3< C, B /* <: C */, A <: B> = Cast; + +func g< A <: B, B /* <: C */ , C> ( a : A, b : B, c: C, n:Int ) : C { + /* TODO: restore these tests once open type defintions are supported + type U0 = T1; + type U1 = T1; + type U2 = T1; + type U3 = T1; + type U4 = T1; + type U5 = T1; + type U6 = T1; + + type V0 = T2; + type V1 = T2; + type V2 = T2; + type V3 = T2; + type V4 = T2; + type V5 = T2; + type V6 = T2; + + type W0 = T3; + type W1 = T3; + type W2 = T3; + type W3 = T3; + type W4 = T3; + type W5 = T3; + type W6 = T3; + */ + + /* test type formation involving f-bounds */ + let u0 : T1 = (); + let u1 : T1 = (); + let u2 : T1 = (); + let u3 : T1 = (); + let u4 : T1 = (); + let u5 : T1 = (); + let u6 : T1 = (); + + let v0 : T2 = (); + let v1 : T2 = (); + let v2 : T2 = (); + let v3 : T2 = (); + let v4 : T2 = (); + let v5 : T2 = (); + let v6 : T2 = (); + + let w0 : T3 = (); + let w1 : T3 = (); + let w2 : T3 = (); + let w3 : T3 = (); + let w4 : T3 = (); + let w5 : T3 = (); + let w6 : T3 = (); + + switch n { + case 0 { g(a,a,a,n) }; + case 1 { g(a,b,b,n) }; + case 2 { g(a,b,c,n) }; + + case 3 { g(a,a,a,n) }; + case 4 { g(a,b,b,n) }; + case 5 { g(a,b,c,n) }; + case 6 { g(b,b,b,n) }; + case 7 { g(b,b,c,n) }; + + case 8 { g(a,a,a,n) }; + case 9 { g(a,a,b,n) }; + case 10 { g(a,b,c,n) }; + case 11 { g(c,c,c,n) }; + case _ { c }; + } +}; + diff --git a/test/fail/ok/abstract-msgs.tc.ok b/test/fail/ok/abstract-msgs.tc.ok index 5358c1e7327..d62841c511e 100644 --- a/test/fail/ok/abstract-msgs.tc.ok +++ b/test/fail/ok/abstract-msgs.tc.ok @@ -1,20 +1,20 @@ abstract-msgs.as:2.28-2.37: type error, shared function has non-shared parameter type - A/19 + A/9 abstract-msgs.as:3.33-3.35: type error, shared function has non-async result type - ?A/21 + ?A/10 abstract-msgs.as:5.20-5.29: type error, shared function has non-shared parameter type - A/23 + A/11 abstract-msgs.as:6.31-6.33: type error, async has non-shared content type - ?A/23 + ?A/11 abstract-msgs.as:10.34-10.35: type error, shared function has non-shared parameter type - A/25 + A/12 abstract-msgs.as:11.46-11.47: type error, async has non-shared content type - A/27 + A/13 abstract-msgs.as:14.30-14.31: type error, shared function has non-shared parameter type - A/29 + A/14 abstract-msgs.as:15.42-15.43: type error, async has non-shared content type - A/31 + A/15 abstract-msgs.as:16.31-16.32: type error, shared function has non-shared parameter type - A/33 + A/16 abstract-msgs.as:17.43-17.44: type error, async has non-shared content type - A/35 + A/17 diff --git a/test/fail/ok/asyncret1.tc.ok b/test/fail/ok/asyncret1.tc.ok index ca6952b3eaa..2879cd8331c 100644 --- a/test/fail/ok/asyncret1.tc.ok +++ b/test/fail/ok/asyncret1.tc.ok @@ -1,2 +1,2 @@ asyncret1.as:1.39-1.40: type error, shared function has non-async result type - C/1 + C diff --git a/test/fail/ok/f-bounds-fail.tc.ok b/test/fail/ok/f-bounds-fail.tc.ok new file mode 100644 index 00000000000..ff8436a1726 --- /dev/null +++ b/test/fail/ok/f-bounds-fail.tc.ok @@ -0,0 +1,176 @@ +f-bounds-fail.as:13.42-13.43: type error, type argument + A/10 +does not match parameter bound + C +f-bounds-fail.as:14.42-14.43: type error, type argument + A/11 +does not match parameter bound + C/1 +f-bounds-fail.as:15.42-15.43: type error, type argument + A/12 +does not match parameter bound + C/2 +f-bounds-fail.as:3.38-3.41: type error, type argument + Int +does not match parameter bound + Nat +f-bounds-fail.as:9.53-9.54: type error, expression of type + A/19 +cannot produce expected type + C/6 +f-bounds-fail.as:10.52-10.53: type error, expression of type + A/20 +cannot produce expected type + C/7 +f-bounds-fail.as:11.52-11.53: type error, expression of type + A/21 +cannot produce expected type + C/8 +f-bounds-fail.as:45.23-45.25: type error, expression of type + () +cannot produce expected type + A/22 -> A/22 +f-bounds-fail.as:46.23-46.25: type error, expression of type + () +cannot produce expected type + A/22 -> B/13 +f-bounds-fail.as:47.23-47.25: type error, expression of type + () +cannot produce expected type + A/22 -> B/13 +f-bounds-fail.as:48.23-48.25: type error, expression of type + () +cannot produce expected type + B/13 -> B/13 +f-bounds-fail.as:49.23-49.25: type error, expression of type + () +cannot produce expected type + B/13 -> C/9 +f-bounds-fail.as:50.14-50.15: type error, type argument + B/13 +does not match parameter bound + C/9 +f-bounds-fail.as:50.23-50.25: type error, expression of type + () +cannot produce expected type + B/13 -> C/9 +f-bounds-fail.as:51.23-51.25: type error, expression of type + () +cannot produce expected type + C/9 -> C/9 +f-bounds-fail.as:53.23-53.25: type error, expression of type + () +cannot produce expected type + A/22 -> A/22 +f-bounds-fail.as:54.23-54.25: type error, expression of type + () +cannot produce expected type + A/22 -> B/13 +f-bounds-fail.as:55.23-55.25: type error, expression of type + () +cannot produce expected type + A/22 -> B/13 +f-bounds-fail.as:56.23-56.25: type error, expression of type + () +cannot produce expected type + B/13 -> B/13 +f-bounds-fail.as:57.23-57.25: type error, expression of type + () +cannot produce expected type + B/13 -> C/9 +f-bounds-fail.as:58.16-58.17: type error, type argument + B/13 +does not match parameter bound + C/9 +f-bounds-fail.as:58.23-58.25: type error, expression of type + () +cannot produce expected type + B/13 -> C/9 +f-bounds-fail.as:59.23-59.25: type error, expression of type + () +cannot produce expected type + C/9 -> C/9 +f-bounds-fail.as:61.23-61.25: type error, expression of type + () +cannot produce expected type + A/22 -> A/22 +f-bounds-fail.as:62.23-62.25: type error, expression of type + () +cannot produce expected type + A/22 -> B/13 +f-bounds-fail.as:63.23-63.25: type error, expression of type + () +cannot produce expected type + A/22 -> B/13 +f-bounds-fail.as:64.23-64.25: type error, expression of type + () +cannot produce expected type + B/13 -> B/13 +f-bounds-fail.as:65.23-65.25: type error, expression of type + () +cannot produce expected type + B/13 -> C/9 +f-bounds-fail.as:66.18-66.19: type error, type argument + B/13 +does not match parameter bound + C/9 +f-bounds-fail.as:66.23-66.25: type error, expression of type + () +cannot produce expected type + B/13 -> C/9 +f-bounds-fail.as:67.23-67.25: type error, expression of type + () +cannot produce expected type + C/9 -> C/9 +f-bounds-fail.as:70.27-70.28: type error, expression of type + A/22 +cannot produce expected type + C/9 +f-bounds-fail.as:71.27-71.28: type error, expression of type + B/13 +cannot produce expected type + C/9 +f-bounds-fail.as:74.27-74.28: type error, expression of type + A/22 +cannot produce expected type + C/9 +f-bounds-fail.as:75.27-75.28: type error, expression of type + B/13 +cannot produce expected type + C/9 +f-bounds-fail.as:77.27-77.28: type error, expression of type + B/13 +cannot produce expected type + C/9 +f-bounds-fail.as:80.23-80.24: type error, expression of type + A/22 +cannot produce expected type + C/9 +f-bounds-fail.as:80.25-80.26: type error, expression of type + A/22 +cannot produce expected type + C/9 +f-bounds-fail.as:80.27-80.28: type error, expression of type + A/22 +cannot produce expected type + C/9 +f-bounds-fail.as:81.23-81.24: type error, expression of type + A/22 +cannot produce expected type + C/9 +f-bounds-fail.as:81.25-81.26: type error, expression of type + A/22 +cannot produce expected type + C/9 +f-bounds-fail.as:81.27-81.28: type error, expression of type + B/13 +cannot produce expected type + C/9 +f-bounds-fail.as:82.24-82.25: type error, expression of type + A/22 +cannot produce expected type + C/9 +f-bounds-fail.as:82.26-82.27: type error, expression of type + B/13 +cannot produce expected type + C/9 diff --git a/test/fail/ok/issue167.tc.ok b/test/fail/ok/issue167.tc.ok index bee902a2a10..d4f77135651 100644 --- a/test/fail/ok/issue167.tc.ok +++ b/test/fail/ok/issue167.tc.ok @@ -1,2 +1 @@ issue167.as:1.13-1.19: type error, too many type arguments -issue167.as:1.13-1.19: type error, too many type arguments diff --git a/test/fail/ok/modexp5.tc.ok b/test/fail/ok/modexp5.tc.ok index 079888d23b3..35aaf210788 100644 --- a/test/fail/ok/modexp5.tc.ok +++ b/test/fail/ok/modexp5.tc.ok @@ -1 +1 @@ -modexp5.as:6.20-6.30: type error, type definition U = T/24 references type parameter(s) T/24 from an outer scope +modexp5.as:6.20-6.30: type error, type definition U = T/15 references type parameter(s) T/15 from an outer scope diff --git a/test/fail/ok/pat-inconsistent.tc.ok b/test/fail/ok/pat-inconsistent.tc.ok index 3a02fd6bf1e..2f6bdb9c9af 100644 --- a/test/fail/ok/pat-inconsistent.tc.ok +++ b/test/fail/ok/pat-inconsistent.tc.ok @@ -100,7 +100,7 @@ pat-inconsistent.as:32.19-32.32: type error, pattern branches have incompatible left consumes Text right consumes - A/18 + A/9 pat-inconsistent.as:33.16-33.40: type error, pattern branches have incompatible types, left consumes Any diff --git a/test/run/f-bounds.as b/test/run/f-bounds.as new file mode 100644 index 00000000000..321d2bdc3f0 --- /dev/null +++ b/test/run/f-bounds.as @@ -0,0 +1,87 @@ +type Cast< A <: B, B> = A -> B; + +let f = (func(x :Nat):Int = x) : Cast; + +func f2a< A <: B, B> ( x : A ) : B = x; + +func f2b< B, A <: B> ( x : A ) : B = x; + +func f3a< A <: B, B <: C , C> ( x : A ) : C = x; +func f3b< B <: C, A <: B, C> ( x : A ) : C = x; +func f3c< C, B <: C, A <: B> ( x : A ) : C = x; + +type T1< A <: B, B <: C, C> = Any; +type T2< B <: C, A <: B, C> = Any; +type T3< C, B <: C, A <: B> = Any; + +func g< A <: B, B <: C , C> ( a : A, b : B, c: C, n:Int ) : C { + + /* TODO: restore these tests once open type defintions are supported + type U0 = T1; + type U1 = T1; + type U2 = T1; + type U3 = T1; + type U4 = T1; + type U5 = T1; + type U6 = T1; + + type V0 = T2; + type V1 = T2; + type V2 = T2; + type V3 = T2; + type V4 = T2; + type V5 = T2; + type V6 = T2; + + type W0 = T3; + type W1 = T3; + type W2 = T3; + type W3 = T3; + type W4 = T3; + type W5 = T3; + type W6 = T3; + */ + + /* test type formation involving f-bounds */ + let u0 : T1 = (); + let u1 : T1 = (); + let u2 : T1 = (); + let u3 : T1 = (); + let u4 : T1 = (); + let u5 : T1 = (); + let u6 : T1 = (); + + let v0 : T2 = (); + let v1 : T2 = (); + let v2 : T2 = (); + let v3 : T2 = (); + let v4 : T2 = (); + let v5 : T2 = (); + let v6 : T2 = (); + + let w0 : T3 = (); + let w1 : T3 = (); + let w2 : T3 = (); + let w3 : T3 = (); + let w4 : T3 = (); + let w5 : T3 = (); + let w6 : T3 = (); + + switch n { + case 0 { g(a,a,a,n) }; + case 1 { g(a,b,b,n) }; + case 2 { g(a,b,c,n) }; + + case 3 { g(a,a,a,n) }; + case 4 { g(a,b,b,n) }; + case 5 { g(a,b,c,n) }; + case 6 { g(b,b,b,n) }; + case 7 { g(b,b,c,n) }; + + case 8 { g(a,a,a,n) }; + case 9 { g(a,a,b,n) }; + case 10 { g(a,b,c,n) }; + case 11 { g(c,c,c,n) }; + case _ { c }; + } +}; diff --git a/test/run/ott-typeclasses.as b/test/run/ott-typeclasses.as new file mode 100644 index 00000000000..f2009fc26ef --- /dev/null +++ b/test/run/ott-typeclasses.as @@ -0,0 +1,69 @@ +// test realistic f-bound polymorphism using a contrived implementation of type classes +// NB: it's contrived, because we don't need the dictionary *type* parameters + +type Eq = { + eq: (T,T) -> Bool +}; + +func equal, T>(w:W, t1 : T, t2 : T) : Bool = w.eq(t1, t2); + +type Order = { #LT; #EQ; #GT; }; + +type Ord = { + eq : (T,T) -> Bool; + cmp: (T,T) -> Order; +}; + +func compare, T>(w : W, t1 : T, t2 : T) : Order = w.cmp(t1,t2); + +object ordInt { + func eq(t1 : Int, t2:Int) : Bool = t1 == t2; + func cmp(t1 : Int, t2 : Int) : Order = + if (t1 < t2) #LT + else if (t1 > t2) #GT + else #EQ; +}; + +type List = ?(T,List); + +class OrdList, T>(w : W) = this { + func eq(ts1 : List, ts2: List) : Bool = + switch (cmp (ts1, ts2)) { + case (#EQ) true; + case _ false; + }; + + func cmp(ts1 : List, ts2: List) : Order = + switch (ts1, ts2) { + case (null, null) #EQ; + case (null, ? _) #LT; + case (?(t1, ts1), ?(t2, ts2)) { + switch (compare(w, t1, t2)) { + case (#EQ) (compare, List> (this, ts1, ts2)); + case other other; + } + }; + case (? _, null ) #GT; + } +}; + + + +assert(equal,Int>(ordInt, 0, 0)); + +assert(not (equal,Int>(ordInt, -1, 0))); + +type OLI = OrdList,Int>; +let oli = OrdList,Int>(ordInt); + +switch (compare>(oli, null, null)) +{ + case (#EQ) (); + case _ (assert false); +}; + +switch (compare>(oli, ?(1,null), null)) +{ + case (#GT) (); + case _ (assert false); +}; diff --git a/test/run/self-bounds.as b/test/run/self-bounds.as new file mode 100644 index 00000000000..c27ae53c41d --- /dev/null +++ b/test/run/self-bounds.as @@ -0,0 +1,7 @@ +type List> = (A,B); + +type List1> = (A,B); + +type List2> = (A,B); + +type List3,A,C> = (A,B); From 903e1cd8211588f0397d4dc01e817b8d3fb5975a Mon Sep 17 00:00:00 2001 From: Christoph Hegemann Date: Tue, 16 Jul 2019 13:53:32 +0200 Subject: [PATCH 0267/1176] Adds the PA parking service example (#565) * Adds the PA parking service example * retrigger ci --- samples/pa_cars.as | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 samples/pa_cars.as diff --git a/samples/pa_cars.as b/samples/pa_cars.as new file mode 100644 index 00000000000..946089ddfc3 --- /dev/null +++ b/samples/pa_cars.as @@ -0,0 +1,43 @@ +// Stateless Suspendable Workflow +// ============================== + +// Creating an Account for the PA parking service + +// - Client: Insert Car data and holder's name +// - Server: Validate car is registered under the given name +// - Client: Pick a parking spot from a Google Map like interface + time +// - Server: Register the parking spot for the user + +type Car = shared { model : Text; plate : Text }; +type DMV = actor { check : Car -> async CarInfo }; +type CarInfo = shared { + model : Text; + plate : Text; + isValid : Bool; + wasStolen : Bool; + expires : Nat; +}; + +actor class PACars(dmv : DMV) { + func verifyCarInformation(user : User, car : Car) : async ?(shared (Location, TimeSpan) -> async Result) { + let carInfo = await dmv.check(car); + if (carInfo.isValid and not carInfo.wasStolen) { + return ?(shared func (location, time) : async Result { + return reserveSpot(user, carInfo, location, time); + }) + } else { + return null; + } + }; + + private func reserveSpot(user : User, carInfo : CarInfo, location : Location, timeSpan : TimeSpan) : Result { + // Do the actual work of registering the parking spot for the + // given car in the given time span + return null; + }; + + type Location = shared { lat : Float; long : Float }; + type TimeSpan = shared { start : Int; end : Int }; + type Result = ?(shared { reservationId : Text }); + type User = shared { name : Text }; +}; From f4153e9ea1aedb40b9f327b7fd2bdf5210b0c31d Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 16 Jul 2019 16:15:32 +0200 Subject: [PATCH 0268/1176] Bump dev (#574) to depend on the same version that @chenyan-dfinity wants in #573 --- default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/default.nix b/default.nix index f47012d706b..aab99f0ecdc 100644 --- a/default.nix +++ b/default.nix @@ -32,7 +32,7 @@ let real-dvm = let dev = builtins.fetchGit { url = "ssh://git@github.com/dfinity-lab/dev"; ref = "master"; - rev = "65c295edfc4164ca89c129d501a403fa246d3d36"; + rev = "a556b011d957d3174b6c4017d76dd510791d8922"; }; in (import dev { system = nixpkgs.system; }).dvm else null From 716d5842a64718da3c918c8aa7818565da0c849c Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Tue, 16 Jul 2019 18:28:06 +0200 Subject: [PATCH 0269/1176] Invert public/private default (#570) --- design/Syntax.md | 16 +- guide/as-slides.md | 26 +-- guide/chat.as | 8 +- guide/guide.md | 69 ++++---- samples/ListClient.as | 8 +- samples/ListLib.as | 7 +- samples/app/client.as | 8 +- samples/app/list.as | 1 - samples/app/server.as | 18 +- samples/counter.as | 10 +- samples/modules.as | 9 +- samples/quicksort.as | 8 +- src/as_frontend/dune | 1 + src/as_frontend/lexer.mll | 1 + src/as_frontend/parser.mly | 71 ++++---- src/prelude/prelude.ml | 48 +++--- stdlib/assocList.as | 20 +-- stdlib/docTable.as | 63 +++---- .../examples/produce-exchange/profileActor.as | 2 +- .../examples/produce-exchange/serverActor.as | 126 +++++++------- .../examples/produce-exchange/serverLang.as | 20 +-- .../examples/produce-exchange/serverModel.as | 156 +++++++++--------- .../produce-exchange/serverModelTypes.as | 76 ++++----- .../examples/produce-exchange/serverTypes.as | 86 +++++----- .../test/simpleSetupAndQuery.as | 10 +- stdlib/hash.as | 46 +++--- stdlib/list.as | 62 +++---- stdlib/option.as | 32 ++-- stdlib/prelude.as | 6 +- stdlib/result.as | 28 ++-- stdlib/set.as | 28 ++-- stdlib/trie.as | 118 ++++++------- stdlib/trie2.as | 128 +++++++------- test/fail/actor-match.as | 8 +- test/fail/actor-reexport.as | 8 +- test/fail/ast81-clash.as | 2 +- test/fail/await-in-actor.as | 4 +- test/fail/const-var-field.as | 2 +- test/fail/duplicate-field.as | 6 +- test/fail/issue103.as | 4 +- test/fail/modexp1.as | 4 +- test/fail/modexp2.as | 10 +- test/fail/modexp3.as | 10 +- test/fail/modexp4.as | 12 +- test/fail/modules-fwd.as | 8 +- test/fail/modules-shadow.as | 5 +- test/fail/nested-class-rec-fail.as | 10 +- test/fail/object-patterns.as | 8 +- test/fail/objpat-duplicate.as | 2 +- test/fail/objpat-infer.as | 2 +- test/fail/ok/actor-reexport.tc.ok | 6 +- test/fail/ok/await-in-actor.tc.ok | 2 +- test/fail/ok/const-var-field.tc.ok | 2 +- test/fail/ok/duplicate-field.tc.ok | 2 +- test/fail/ok/nested-class-rec-fail.tc.ok | 2 +- test/fail/ok/object-patterns.tc.ok | 4 +- test/fail/ok/use-before-define6.tc.ok | 2 +- test/fail/use-before-define5.as | 2 +- test/fail/use-before-define6.as | 14 +- test/run-dfinity/AST-64.as | 8 +- test/run-dfinity/async-new-obj.as | 102 ++++++------ test/run-dfinity/async-obj-mut.as | 16 +- test/run-dfinity/chat.as | 14 +- test/run-dfinity/chatpp.as | 26 +-- test/run-dfinity/closure-params.as | 6 +- test/run-dfinity/counter-class.as | 6 +- test/run-dfinity/counter.as | 6 +- test/run-dfinity/counter2.as | 6 +- test/run-dfinity/data-params.as | 30 ++-- test/run-dfinity/flatten-awaitables.as | 32 ++-- test/run-dfinity/general-type-components.as | 24 +-- test/run-dfinity/hello-world-async.as | 4 +- test/run-dfinity/hello-world-await.as | 6 +- test/run-dfinity/hello-world-message.as | 2 +- test/run-dfinity/hello-world-message2.as | 2 +- test/run-dfinity/hello-world2.as | 2 +- test/run-dfinity/hello-world3.as | 6 +- test/run-dfinity/indirect-counter.as | 12 +- test/run-dfinity/modexp1.as | 6 +- test/run-dfinity/modexp2.as | 12 +- test/run-dfinity/modexp3.as | 12 +- test/run-dfinity/modexp4.as | 16 +- test/run-dfinity/modules-bwd.as | 6 +- test/run-dfinity/ok/data-params.run-ir.ok | 2 +- test/run-dfinity/ok/data-params.run-low.ok | 2 +- test/run-dfinity/ok/data-params.run.ok | 2 +- test/run-dfinity/ok/data-params.tc.ok | 2 +- .../run-dfinity/ok/data-params.wasm.stderr.ok | 2 +- test/run-dfinity/reference-params.as | 16 +- test/run-dfinity/show.as | 2 +- test/run-dfinity/transpose.as | 6 +- test/run/actors.as | 12 +- test/run/async-calls.as | 28 ++-- test/run/control.as | 18 +- test/run/coverage.as | 14 +- test/run/import-module.as | 2 +- test/run/ir-pat-subtype.as | 43 +++-- test/run/issue150.as | 4 +- test/run/lib/ListM.as | 7 +- test/run/module1.as | 32 ++-- test/run/module2.as | 4 +- test/run/module3.as | 5 +- test/run/mut-field-bound.as | 2 +- test/run/nested-class-rec.as | 6 +- test/run/nested-lexpr.as | 2 +- test/run/objects1.as | 18 +- test/run/objects2.as | 2 +- test/run/objects3.as | 2 +- test/run/objects4.as | 6 +- test/run/objects5.as | 4 +- test/run/ok/coverage.run-ir.ok | 10 +- test/run/ok/coverage.run-low.ok | 10 +- test/run/ok/coverage.run.ok | 10 +- test/run/ok/coverage.tc.ok | 10 +- test/run/ok/coverage.wasm.stderr.ok | 10 +- test/run/quicksort.as | 8 +- test/run/type-definition.as | 4 +- test/run/type-inclusion.as | 10 +- 118 files changed, 1067 insertions(+), 1069 deletions(-) diff --git a/design/Syntax.md b/design/Syntax.md index 59a34a55ca7..f015d8dccc1 100644 --- a/design/Syntax.md +++ b/design/Syntax.md @@ -7,12 +7,12 @@ Productions marked * probably deferred to later versions. ``` ::= type expressions ? constructor - (shared|actor)? { ;* } object + (actor|module|object)? { ;* } actor / module / object (default) { ;* } variant { # } empty variant [ var? ] array ? option - shared ? -> function + shared? ? -> function async future ( (( :)? ),* ) tuple Any top @@ -54,6 +54,7 @@ Productions marked * probably deferred to later versions. ( ,* ) tuple . tuple projection ? option injection + new { ;* } object . object projection # ? variant injection := assignment @@ -84,8 +85,7 @@ Productions marked * probably deferred to later versions. * try (catch )+ ( )? try ::= object expression fields - private? dec field - private? = short-hand + var? = field ``` ## Patterns @@ -113,12 +113,14 @@ Productions marked * probably deferred to later versions. expression let = immutable var (: )? = mutable - (new|object|actor) ? =? { ;* } object + (actor|module|object) ? =? { ;* } object shared? func ? ? (: )? =? function - type ? = type actor? class ? (: )? =? class - module ? =? { * } module + type ? = type import ? =? import + + ::= object declaration fields + (public|private)? dec field ``` ## Programs diff --git a/guide/as-slides.md b/guide/as-slides.md index 15172c23bac..206a4b5a081 100644 --- a/guide/as-slides.md +++ b/guide/as-slides.md @@ -228,7 +228,7 @@ AS distinguishes sharable types: * sharable (think serializable) objects have immutable fields of sharable type: ``` - { x = 0; color = Colors.Red } + new { x = 0; color = Colors.Red } ``` * full `object`s can be mutable, stateful @@ -236,8 +236,8 @@ AS distinguishes sharable types: ``` swift object { private var c = 0; - inc() { c += 1 }; - get() : Int { c } + public func inc() { c += 1 }; + public func get() : Int { c } } ``` @@ -252,8 +252,8 @@ Actors are restricted objects: ``` actor { private var c = 0; - inc() { c += 1 }; - get() : async Int { c } + public func inc() { c += 1 }; + public func get() : async Int { c } } ``` @@ -484,8 +484,8 @@ Classes as functions returning objects: ``` class Counter(init : Int) { private var state : Int = init; - inc() { state += 1; }; - get() : Int { state; }; + public func inc() { state += 1; }; + public func get() : Int { state; }; } ``` @@ -512,9 +512,9 @@ let ? name = d.find(1); ### Actor Declarations ``` -actor Server = { +actor Server { private shared func broadcast():(){...}; - subscribe(c : Client): async Post { + public func subscribe(c : Client): async Post { ... return broadcast; }; @@ -562,7 +562,7 @@ alice.start("Alice", Server); // async send as function call ### Chat Server ``` -actor Server = { +actor Server { private var clients : List = null; private shared broadcast(message : Text) { @@ -576,7 +576,7 @@ actor Server = { }; ``` ``` - subscribe(client : Client) : async Post { + public func subscribe(client : Client) : async Post { let cs = new {head = client; var tail = clients}; clients := ?cs; return broadcast; @@ -597,7 +597,7 @@ type Server = actor { subscribe : Client -> async Post; }; actor class Client() = this { private var name : Text = ""; - start(n : Text , s : Server) { + public func start(n : Text , s : Server) { name := n; let _ = async { let post = await s.subscribe(this); @@ -607,7 +607,7 @@ actor class Client() = this { }; ``` ``` - send(msg : Text) { + public func send(msg : Text) { print(name # " received " # msg # "\n"); }; }; diff --git a/guide/chat.as b/guide/chat.as index f92c49e8bd8..ba672f0b9a3 100644 --- a/guide/chat.as +++ b/guide/chat.as @@ -18,7 +18,7 @@ actor Server = { }; }; - func subscribe(client : Client) : async Post { + public func subscribe(client : Client) : async Post { let cs = new {head = client; var tail = clients}; clients := ?cs; return broadcast; @@ -29,7 +29,8 @@ type Server = actor { subscribe : Client -> async Post; }; actor class Client() = this { private var name : Text = ""; - start(n : Text , s : Server) { + + public func start(n : Text , s : Server) { name := n; let _ = async { let post = await s.subscribe(this); @@ -37,7 +38,8 @@ actor class Client() = this { post("goodbye from " # name); } }; - send(msg : Text) { + + public func send(msg : Text) { print(name # " received " # msg # "\n"); }; }; diff --git a/guide/guide.md b/guide/guide.md index 19d39f2272b..89ea93207c2 100644 --- a/guide/guide.md +++ b/guide/guide.md @@ -135,7 +135,7 @@ The following keywords are reserved and may not be used as identifiers: ```bnf actor and async assert await break case class continue else false for func if in new not null object or label let loop -private return shared switch true type var while +private public return shared switch true type var while ``` ## Identifiers @@ -660,6 +660,7 @@ A type `T` is *shared* if it is ( ,* ) tuple . tuple projection ? option injection + new { ;* } object . object projection := assignment = unary update @@ -687,9 +688,6 @@ A type `T` is *shared* if it is : type annotation dec declaration ( ) parentheses - - ::= function expression - ? (: )? =? function body ``` ## Identifiers @@ -758,6 +756,17 @@ The option expression `? ` has type `? T` provided `` has type `T`. The literal `null` has type `Null`. Since `Null <: ? T` for any `T`, literal `null` also has type `? T` and signifies the "missing" value at type `? T`. +## Objects + +Objects can be written in literal form `new { ;* }`, consisting of a list of expression fields: + +```bnf + ::= var? = +``` +Such an object literal is equivalent to the object declaration `object { ;* }` where the declaration fields are obtained from the expression fields by prefixing each of them with `public let`, or just `public` in case of `var` fields. + +_TBR can we delete `new`?_ + ## Object projection (Member access) The object projection ` . ` has type `var? T` provided `` has object type @@ -1188,16 +1197,15 @@ matching ``, if it succeeds, or the result of matching ``, if the fi expression let = immutable var (: )? = mutable - (new|object|actor) ? =? { ;* } object + (object|module|actor) ? =? { ;* } object shared? func ? ? (: )? =? function type ? = type obj_sort? class ? =? { ;* }` class ``` ```bnf - ::= object expression fields - private? field - private? = short-hand + ::= object declaration fields + (public|private)? field ``` ## Expression Declaration @@ -1252,9 +1260,10 @@ In scope of the declaration `type C < X0<:T0>, ..., Xn <: Tn > = U`, any well- ## Object Declaration -Declaration `(new|object|actor) ? =? { ;* }` declares an object with optional identifier `` and zero or more fields `;*`. +Declaration `(object|module|actor) ? =? { ;* }` declares an object with optional identifier `` and zero or more fields `;*`. +Fields can be declared with `public` or `private` visibility; if the visibility is omitted, it defaults to `private`. -The qualifier `new|object|actor` specifies the *sort* of the object's type (`new` is equivalent to `object`). The sort imposes restrictions on the types of the non-private object fields. +The qualifier `object|module|actor` specifies the *sort* of the object's type. The sort imposes restrictions on the types of the public object fields. Let `T = sort { [var0] id0 : T0, ... , [varn] idn : T0 }` denote the type of the object. Let `;*` be the sequence of declarations in `;*`. @@ -1262,7 +1271,7 @@ The object declaration has type `T` provided that: 1. type `T` is well-formed for sort `sort`, and 2. under the assumption that ` : T`, - * the sequence of declarations `;*` has type `Any` and declares the disjoint sets of private and non-private identifiers, `Id_private` and `Id_public` respectively, + * the sequence of declarations `;*` has type `Any` and declares the disjoint sets of private and public identifiers, `Id_private` and `Id_public` respectively, with types `T(id)` for `id` in `Id == Id_private union Id_public`, and * `{ id0, ..., idn } == Id_public`, and * for all `i in 0 <= i <= n`, `[vari] Ti == T(idi)`. @@ -1270,7 +1279,7 @@ The object declaration has type `T` provided that: Note that requirement 1. imposes further constraints on the fields type of `T`. In particular: -* if the sort is `actor` then all non-private fields must be non-`var` (immutable) `shared` functions (the public interface of an actor can only provide asynchronous messaging via shared functions). +* if the sort is `actor` then all public fields must be non-`var` (immutable) `shared` functions (the public interface of an actor can only provide asynchronous messaging via shared functions). Evaluation of `(new|object|actor) ? =? { ;* }` proceeds by evaluating the declarations in `;*`. If the evaluation of `;*` traps, so does the object declaration. @@ -1302,51 +1311,33 @@ The declaration `obj_sort? class ? =? ? { ? (: )? =? ? { ;* } := +obj_sort? class ? (: )? =? ? { ;* } := type = sort { ;* }; - func ? : = sort ? { ;* } + func ? : = sort ? { ;* } ``` where: * `` is `object` if `obj_sort?` is absent or `new` and `sort == obj_sort` otherwise. * `?` is the sequence of type identifiers bound by `?` (if any), and -* `;*` is the set of non-`private` field types inferred from ``. +* `;*` is the set of public field types inferred from ``. * `?` is the optional `this` parameter of the object instance. -_TBR can we delete `new`?_ -## Expression Fields +## Declaration Fields ```bnf - ::= object expression fields - private? field - private? = short-hand - private? shared? ? short-hand + ::= object expression fields + (public|private)? field ``` -Expression fields declare the fields of actors and objects. +Declaration fields declare the fields of actors and objects. +They are just declarations, prefixed by an optional visibility qualifier `public` or `private`; if omitted, visibility defaults to `private`. -The expression field `private? dec` is just a declaration, prefixed by an optional visibility qualifier 'private?'. - -Any identifier bound by a non-`private` declaration appears in the type of enclosing object and is accessible via the dot notation. +Any identifier bound by a `public` declaration appears in the type of enclosing object and is accessible via the dot notation. An identifier bound by a `private` declaration is excluded form the type of the enclosing object and inaccessible via the dot notation. -The field expression `private? = ` is syntactic sugar for a `let` declaration: - -```bnf -private? = := - private? let = -``` - -The field expression `private? shared? ? ` is syntactic sugar for a `let`-declared function: - -```bnf -private? private? shared? ? := - private? let = shared? -``` - # Sequence of Declarations A sequence of declarations `;*` occurring in a block, a program or the `exp-field;*` sequence of an object declaration has type `T` diff --git a/samples/ListClient.as b/samples/ListClient.as index c4b3a76c67c..f348aadd971 100644 --- a/samples/ListClient.as +++ b/samples/ListClient.as @@ -1,11 +1,11 @@ module { -private import List = "ListLib.as"; // private, so we don't re-export List +import List = "ListLib.as"; // private, so we don't re-export List -type Stack = List.List; +public type Stack = List.List; -func push(x : Int, s : Stack) : Stack = List.cons(x, s); +public func push(x : Int, s : Stack) : Stack = List.cons(x, s); -func empty():Stack = List.nil(); +public func empty() : Stack = List.nil(); } diff --git a/samples/ListLib.as b/samples/ListLib.as index 432fa38a153..5f09b3fea39 100644 --- a/samples/ListLib.as +++ b/samples/ListLib.as @@ -1,5 +1,6 @@ module { - type List = ?(T, List); - func nil() : List = null; - func cons(x : T, l : List) : List = ?(x, l); + public type List = ?(T, List); + + public func nil() : List = null; + public func cons(x : T, l : List) : List = ?(x, l); } diff --git a/samples/app/client.as b/samples/app/client.as index 0a4d34de41d..df1dc53466d 100644 --- a/samples/app/client.as +++ b/samples/app/client.as @@ -2,10 +2,10 @@ import S "server.as"; actor class Client() = this { // TODO: these should be constructor params once we can compile them - private var name : Text = ""; - private var server : ?S.Server = null; + var name : Text = ""; + var server : ?S.Server = null; - go(n : Text, s : S.Server) { + public func go(n : Text, s : S.Server) { name := n; server := ?s; ignore(async { @@ -16,7 +16,7 @@ actor class Client() = this { }) }; - send(msg : Text) { + public func send(msg : Text) { print(name # " received " # msg # "\n"); }; }; diff --git a/samples/app/list.as b/samples/app/list.as index b37e2d13f01..d3723f55bbb 100644 --- a/samples/app/list.as +++ b/samples/app/list.as @@ -1,2 +1 @@ type List = ?{head : T; var tail : List}; - diff --git a/samples/app/server.as b/samples/app/server.as index 558bdeeb406..e1a8322b78f 100644 --- a/samples/app/server.as +++ b/samples/app/server.as @@ -8,10 +8,10 @@ type ClientData = { }; actor class Server() = { - private var nextId : Nat = 0; - private var clients : L.List = null; + var nextId : Nat = 0; + var clients : L.List = null; - private broadcast(id : Nat, message : Text) { + func broadcast(id : Nat, message : Text) { var next = clients; label sends loop { switch next { @@ -24,20 +24,20 @@ actor class Server() = { }; }; - subscribe(aclient : shared Text -> ()) : async T.Subscription { + public func subscribe(aclient : shared Text -> ()) : async T.Subscription { let c = new {id = nextId; client = aclient; var revoked = false}; nextId += 1; let cs = new {head = c; var tail = clients}; clients := ?cs; - return (new { - post = shared func(message : Text) { + return object { + public shared func post(message : Text) { if (not c.revoked) broadcast(c.id, message); }; - cancel = shared func() { unsubscribe(c.id) }; - }); + public shared func cancel() { unsubscribe(c.id) }; + }; }; - private unsubscribe(id : Nat) { + func unsubscribe(id : Nat) { var prev : L.List = null; var next = clients; loop { diff --git a/samples/counter.as b/samples/counter.as index 6dc99b7505b..636588fa7ed 100644 --- a/samples/counter.as +++ b/samples/counter.as @@ -1,16 +1,16 @@ // A simple Counter actor. actor class Counter(i : Int) { - private var c = i; + var c = i; // Decrement counter - dec() { - show("dec", c); - c -= 1; + public func dec() { + show("dec", c); + c -= 1; }; // Read counter, asynchronous - read() : async Int { c }; + public func read() : async Int { c }; }; // Dummy functions to show intermediate value in trace. diff --git a/samples/modules.as b/samples/modules.as index 7ca07c55531..e56b940292e 100644 --- a/samples/modules.as +++ b/samples/modules.as @@ -1,8 +1,9 @@ module Collections = { - module List = { - type List = ?(T, List); - func nil() : List = null; - func cons(x : T, l : List) : List = ?(x, l); + public module List = { + public type List = ?(T, List); + + public func nil() : List = null; + public func cons(x : T, l : List) : List = ?(x, l); }; }; diff --git a/samples/quicksort.as b/samples/quicksort.as index a30245bd90e..ca0adcb9153 100644 --- a/samples/quicksort.as +++ b/samples/quicksort.as @@ -5,7 +5,7 @@ type Array = [var T]; class QS(cmp : (T, T) -> Int) { - quicksort(a : Array, lo : Nat, hi : Nat) { + public func quicksort(a : Array, lo : Nat, hi : Nat) { if (lo < hi) { let p = partition(a, lo, hi); quicksort(a, lo, p); @@ -13,15 +13,15 @@ class QS(cmp : (T, T) -> Int) { } }; - private swap(a : Array, i : Nat, j : Nat) { + func swap(a : Array, i : Nat, j : Nat) { let temp = a[i]; a[i] := a[j]; a[j] := temp; }; - private trace(v : T) {}; + func trace(v : T) {}; - private partition(a : Array, lo : Nat, hi : Nat) : Nat { + func partition(a : Array, lo : Nat, hi : Nat) : Nat { trace>(a); let pivot = a[lo]; var i = lo; diff --git a/src/as_frontend/dune b/src/as_frontend/dune index c076b4a19fb..6d0524128c1 100644 --- a/src/as_frontend/dune +++ b/src/as_frontend/dune @@ -4,6 +4,7 @@ ) (menhir (modules parser) + (flags -v) (infer false) ) (ocamllex lexer) diff --git a/src/as_frontend/lexer.mll b/src/as_frontend/lexer.mll index ccf9e8463a6..50c09787961 100644 --- a/src/as_frontend/lexer.mll +++ b/src/as_frontend/lexer.mll @@ -210,6 +210,7 @@ rule token mode = parse | "let" { LET } | "loop" { LOOP } | "private" { PRIVATE } + | "public" { PUBLIC } | "return" { RETURN } | "shared" { SHARED } | "debug_show" { DEBUG_SHOW } diff --git a/src/as_frontend/parser.mly b/src/as_frontend/parser.mly index 260c9d8c514..e37299dd4aa 100644 --- a/src/as_frontend/parser.mly +++ b/src/as_frontend/parser.mly @@ -98,7 +98,7 @@ let share_expfield (ef : exp_field) = %token AWAIT ASYNC BREAK CASE CONTINUE LABEL %token IF IN ELSE SWITCH LOOP WHILE FOR RETURN %token ARROW ASSIGN -%token FUNC TYPE OBJECT ACTOR CLASS PRIVATE NEW SHARED +%token FUNC TYPE OBJECT ACTOR CLASS PUBLIC PRIVATE SHARED NEW %token SEMICOLON SEMICOLON_EOL COMMA COLON SUB DOT QUEST %token AND OR NOT %token IMPORT MODULE @@ -122,7 +122,7 @@ let share_expfield (ef : exp_field) = %token PRIM %token UNDERSCORE -%nonassoc IF_NO_ELSE LOOP_NO_WHILE +%nonassoc RETURN_NO_ARG IF_NO_ELSE LOOP_NO_WHILE %nonassoc ELSE WHILE %right ASSIGN PLUSASSIGN MINUSASSIGN MULASSIGN DIVASSIGN MODASSIGN POWASSIGN CATASSIGN ANDASSIGN ORASSIGN XORASSIGN SHLASSIGN USHRASSIGN SSHRASSIGN ROTLASSIGN ROTRASSIGN @@ -151,6 +151,10 @@ seplist(X, SEP) : | x=X { [x] } | x=X SEP xs=seplist(X, SEP) { x::xs } +seplist1(X, SEP) : + | x=X { [x] } + | x=X SEP xs=seplist(X, SEP) { x::xs } + (* Basics *) @@ -180,7 +184,6 @@ seplist(X, SEP) : | VAR { Var @@ at $sloc } %inline obj_sort : - | NEW { Type.Object @@ at $sloc } | OBJECT { Type.Object @@ at $sloc } | ACTOR { Type.Actor @@ at $sloc } | MODULE { Type.Module @@ at $sloc } @@ -193,7 +196,8 @@ seplist(X, SEP) : | (* empty *) { Type.Local @@ no_region } | SHARED { Type.Shared @@ at $sloc } -(* paths *) + +(* Paths *) path : | x=id @@ -201,6 +205,7 @@ path : | p=path DOT x=id { DotH (p, x) @! at $sloc } + (* Types *) typ_obj : @@ -210,10 +215,8 @@ typ_obj : typ_variant : | LCURLY HASH RCURLY { [] } - | LCURLY tf=typ_tag RCURLY - { [tf] } - | LCURLY tf=typ_tag semicolon tfs=seplist(typ_tag, semicolon) RCURLY - { tf::tfs } + | LCURLY tfs=seplist1(typ_tag, semicolon) RCURLY + { tfs } typ_nullary : | LPAR ts=seplist(typ_item, COMMA) RPAR @@ -412,22 +415,21 @@ exp_bin : | e=exp_bin COLON t=typ { AnnotE(e, t) @? at $sloc } -exp_pre : +exp_nondec : | e=exp_bin { e } - | RETURN eo=exp_pre? - { let e = Lib.Option.get eo (TupE([]) @? at $sloc) in - RetE(e) @? at $sloc } - | ASYNC e=exp_pre + | NEW LCURLY efs=seplist(exp_field, semicolon) RCURLY + { ObjE(Type.Object @@ at $sloc, efs) @? at $sloc } + | RETURN %prec RETURN_NO_ARG + { RetE(TupE([]) @? at $sloc) @? at $sloc } + | RETURN e=exp + { RetE(e) @? at $sloc } + | ASYNC e=exp { AsyncE(e) @? at $sloc } - | AWAIT e=exp_pre + | AWAIT e=exp { AwaitE(e) @? at $sloc } - | ASSERT e=exp_pre + | ASSERT e=exp { AssertE(e) @? at $sloc } - -exp_nondec : - | e=exp_pre - { e } | LABEL x=id rt=return_typ_nullary? e=exp { let x' = ("continue " ^ x.it) @@ x.at in let t = Lib.Option.get rt (TupT [] @! at $sloc) in @@ -476,25 +478,23 @@ case : | CASE p=pat_nullary e=exp { {pat = p; exp = e} @@ at $sloc } -%inline private_opt : - | (* empty *) { Public @@ no_region } - | PRIVATE { Private @@ at $sloc } - -(* TODO(andreas): separate short forms *) -(* TODO(andreas): invert public/private default *) exp_field : - | v=private_opt x=id EQ e=exp + | x=id EQ e=exp { let d = LetD(VarP(x) @! x.at, e) @? at $sloc in - {dec = d; vis = v} @@ at $sloc } - | v=private_opt s=func_sort_opt x=id fe=func_exp - { let d = LetD(VarP(x) @! x.at, fe s x.it) @? at $sloc in - {dec = d; vis = v} @@ at $sloc } - (* TODO(andreas): allow any dec *) - | v=private_opt d=dec_var - { {dec = d; vis = v} @@ at $sloc } - | v=private_opt d=dec_nonvar + {dec = d; vis = Public @@ x.at} @@ at $sloc } + | VAR x=id EQ e=exp + { let d = VarD(x, e) @? at $sloc in + {dec = d; vis = Public @@ x.at} @@ at $sloc } + +dec_field : + | v=vis d=dec { {dec = d; vis = v} @@ at $sloc } +vis : + | (* empty *) { Private @@ no_region } + | PRIVATE { Private @@ at $sloc } + | PUBLIC { Public @@ at $sloc } + (* Patterns *) @@ -613,8 +613,7 @@ func_body : | e=exp_block { (true, e) } obj_body : - | LCURLY efs=seplist(exp_field, semicolon) RCURLY - { efs } + | LCURLY efs=seplist(dec_field, semicolon) RCURLY { efs } class_body : | EQ xf=id_opt efs=obj_body { snd (xf "object" $sloc), efs } diff --git a/src/prelude/prelude.ml b/src/prelude/prelude.ml index b3d95b99e86..15d535700a0 100644 --- a/src/prelude/prelude.ml +++ b/src/prelude/prelude.ml @@ -29,13 +29,13 @@ func abs(x : Int) : Nat { (prim "abs" : Int -> Nat) x }; func ignore(_ : Any) {}; class range(x : Nat, y : Nat) { - private var i = x; - next() : ?Nat { if (i > y) null else {let j = i; i += 1; ?j} }; + var i = x; + public func next() : ?Nat { if (i > y) null else {let j = i; i += 1; ?j} }; }; class revrange(x : Nat, y : Nat) { - private var i = x + 1; - next() : ?Nat { if (i <= y) null else {i -= 1; ?i} }; + var i = x + 1; + public func next() : ?Nat { if (i <= y) null else {i -= 1; ?i} }; }; // Implementations for overloaded dot operations @@ -53,28 +53,28 @@ func @mut_array_len(xs : [var A]) : (() -> Nat) = func @mut_array_set(xs : [var A]) : ((Nat, A) -> ()) = (func (n : Nat, x : A) = (xs[n] := x)); func @immut_array_keys(xs : [A]) : (() -> Iter) = - (func () : Iter = new { - private var i = 0; - private l = xs.len(); - next() : ?Nat { if (i >= l) null else {let j = i; i += 1; ?j} }; + (func () : Iter = object { + var i = 0; + let l = xs.len(); + public func next() : ?Nat { if (i >= l) null else {let j = i; i += 1; ?j} }; }); func @mut_array_keys(xs : [var A]) : (() -> Iter) = - (func () : Iter = new { - private var i = 0; - private l = xs.len(); - next() : ?Nat { if (i >= l) null else {let j = i; i += 1; ?j} }; + (func () : Iter = object { + var i = 0; + let l = xs.len(); + public func next() : ?Nat { if (i >= l) null else {let j = i; i += 1; ?j} }; }); func @immut_array_vals(xs : [A]) : (() -> Iter) = - (func () : Iter = new { - private var i = 0; - private l = xs.len(); - next() : ?A { if (i >= l) null else {let j = i; i += 1; ?xs[j]} }; + (func () : Iter = object { + var i = 0; + let l = xs.len(); + public func next() : ?A { if (i >= l) null else {let j = i; i += 1; ?xs[j]} }; }); func @mut_array_vals(xs : [var A]) : (() -> Iter) = - (func () : Iter = new { - private var i = 0; - private l = xs.len(); - next() : ?A { if (i >= l) null else {let j = i; i += 1; ?xs[j]} }; + (func () : Iter = object { + var i = 0; + let l = xs.len(); + public func next() : ?A { if (i >= l) null else {let j = i; i += 1; ?xs[j]} }; }); func @text_len(xs : Text) : (() -> Nat) = (func () : Nat = (prim "text_len" : Text -> Nat) xs); @@ -107,8 +107,8 @@ func hashInt(x : Int) : Word32 { return hash; }; -// Conversions +// Conversions func int64ToInt(n : Int64) : Int = (prim "Int64->Int" : Int64 -> Int) n; func intToInt64(n : Int) : Int64 = (prim "Int->Int64" : Int -> Int64) n; @@ -190,6 +190,7 @@ func clzWord64(w : Word64) : Word64 = (prim "clz64" : Word64 -> Word64) w; func ctzWord64(w : Word64) : Word64 = (prim "ctz64" : Word64 -> Word64) w; func btstWord64(w : Word64, amount : Word64) : Bool = (prim "btst64" : (Word64, Word64) -> Word64) (w, amount) != (0 : Word64); + // Internal helper functions for the show translation // The @ in the name ensures that this cannot be shadowed by user code, so @@ -292,6 +293,7 @@ func @text_of_array_mut(f : T -> Text, xs : [var T]) : Text { return text; }; + // Array utilities // This would be nicer as a objects, but lets do them as functions @@ -320,7 +322,7 @@ func @new_async() : (Async, Cont) { ks := empty; ks_(t); }; - case (?t) (assert(false)); + case (?t) { assert false }; }; }; @@ -330,7 +332,7 @@ func @new_async() : (Async, Cont) { let ks_ = ks; ks := (func(t : T) { ks_(t); k(t) }); }; - case (?t) (k(t)); + case (?t) { k(t) }; }; }; diff --git a/stdlib/assocList.as b/stdlib/assocList.as index ae08a796153..ad354fc331f 100644 --- a/stdlib/assocList.as +++ b/stdlib/assocList.as @@ -10,17 +10,17 @@ Implements the same interface as `Trie`, but as a linked-list of key-value pairs */ -private import List "list.as"; +import List "list.as"; // polymorphic association linked lists between keys and values -type AssocList = List.List<(K,V)>; +public type AssocList = List.List<(K,V)>; /** `find` -------- find the value associated with a given key, or null if absent. */ - func find(al : AssocList, + public func find(al : AssocList, k:K, k_eq:(K,K)->Bool) : ?V @@ -48,7 +48,7 @@ type AssocList = List.List<(K,V)>; replace the value associated with a given key, or add it, if missing. returns old value, or null, if no prior value existed. */ - func replace(al : AssocList, + public func replace(al : AssocList, k:K, k_eq:(K,K)->Bool, ov: ?V) @@ -86,7 +86,7 @@ type AssocList = List.List<(K,V)>; the left list whose keys are not present in the right list; the values of the right list are irrelevant. */ - func diff(al1: AssocList, + public func diff(al1: AssocList, al2: AssocList, keq: (K,K)->Bool) : AssocList @@ -109,7 +109,7 @@ type AssocList = List.List<(K,V)>; `mapAppend` -------- */ - func mapAppend(al1:AssocList, + public func mapAppend(al1:AssocList, al2:AssocList, vbin:(?V,?W)->X) : AssocList = label profile_assocList_mapAppend : AssocList @@ -125,7 +125,7 @@ type AssocList = List.List<(K,V)>; rec(al1, al2) }; - func disjDisjoint(al1:AssocList, + public func disjDisjoint(al1:AssocList, al2:AssocList, vbin:(?V,?W)->X) : AssocList = label profile_assocList_disjDisjoint : AssocList @@ -146,7 +146,7 @@ type AssocList = List.List<(K,V)>; applied to (null, null). */ - func disj(al1:AssocList, + public func disj(al1:AssocList, al2:AssocList, keq:(K,K)->Bool, vbin:(?V,?W)->X) @@ -188,7 +188,7 @@ type AssocList = List.List<(K,V)>; operator, and unmatched key-value pairs are not present in the output. */ - func join(al1 : AssocList, + public func join(al1 : AssocList, al2:AssocList, keq:(K,K)->Bool, vbin:(V,W)->X) @@ -213,7 +213,7 @@ type AssocList = List.List<(K,V)>; `fold` --------- */ - func fold(al:AssocList, + public func fold(al:AssocList, nil:X, cons:(K,V,X)->X) : X diff --git a/stdlib/docTable.as b/stdlib/docTable.as index 0203895268e..a4baf4f5795 100644 --- a/stdlib/docTable.as +++ b/stdlib/docTable.as @@ -43,20 +43,21 @@ type information. */ -private import Hash "hash.as"; -type Hash = Hash.Hash; +import Hash "hash.as"; //import Trie "trie.as"; -private import Trie "trie2.as"; -type Trie = Trie.Trie; -type Key = Trie.Key; +import Trie "trie2.as"; + +public type Hash = Hash.Hash; +public type Trie = Trie.Trie; +public type Key = Trie.Key; /** We choose to represent each `Table` as a `Trie`: */ -let Table = Trie; -type Table = Trie; +public let Table = Trie; +public type Table = Trie; /** @@ -95,7 +96,7 @@ below](#public-interface). See the types below for details. */ -class DocTable( +public class DocTable( idFirst:Id, idIncr:Id->Id, idIsEq:(Id,Id)->Bool, @@ -117,7 +118,7 @@ class DocTable( */ - empty() : Table { + public func empty() : Table { Table.empty() }; @@ -127,7 +128,7 @@ class DocTable( Reset the document table back to its initial counter, and empty state. */ - reset() { + public func reset() { idNext := idFirst; table := Table.empty(); }; @@ -140,7 +141,7 @@ class DocTable( */ - getTable() : Table { + public func getTable() : Table { Table.copy(table) }; @@ -152,7 +153,7 @@ class DocTable( */ - addDoc(doc:Id -> Doc) : (Id, Doc) { + public func addDoc(doc:Id -> Doc) : (Id, Doc) { let id = idNext; idNext := idIncr(idNext); let d = doc(id); @@ -169,7 +170,7 @@ class DocTable( */ - updateDoc(id:Id, doc:Doc) : ?Doc { + public func updateDoc(id:Id, doc:Doc) : ?Doc { let (updatedTable, oldDoc) = Table.replace (table, keyOfId(id), idIsEq, ?doc); table := updatedTable; @@ -185,7 +186,7 @@ class DocTable( This variant of `addInfo` permits the caller to choose the id, but still insists that it be fresh (not currently in use). */ - addInfoAs(idChoice:?Id, info:Id -> Info) : ?(Id, Doc) { + public func addInfoAs(idChoice:?Id, info:Id -> Info) : ?(Id, Doc) { switch idChoice { // subcase: No pre-chosen Id, so mint a new fresh one: case null { @@ -223,11 +224,11 @@ class DocTable( See also [`Table.insertFresh`]($DOCURL/trie.md#insertfresh) */ - addInfo(info:Id -> Info) : ?(Id, Doc) { + public func addInfo(info:Id -> Info) : ?(Id, Doc) { addInfoAs(null, info) }; - addInfoGetId(info:Id -> Info) : ?Id { + public func addInfoGetId(info:Id -> Info) : ?Id { switch (addInfo(info)) { case null { null }; case (?(id, doc)) { ?id } @@ -242,7 +243,7 @@ class DocTable( */ - rem(id:Id) : ?Doc { + public func rem(id:Id) : ?Doc { Table.removeThen( table, keyOfId(id), idIsEq, func (t:Table, d:Doc) : ?Doc { @@ -254,7 +255,7 @@ class DocTable( }; - remGetId(id:Id) : ?Id { + public func remGetId(id:Id) : ?Id { Table.removeThen( table, keyOfId(id), idIsEq, func (t:Table, d:Doc) : ?Id { @@ -265,7 +266,7 @@ class DocTable( ) }; - remGetUnit(id:Id) : ?() { + public func remGetUnit(id:Id) : ?() { Table.removeThen( table, keyOfId(id), idIsEq, func (t:Table, d:Doc) : ?() { @@ -284,7 +285,7 @@ class DocTable( */ - getDoc(id:Id) : ?Doc { + public func getDoc(id:Id) : ?Doc { Table.find(table, keyOfId(id), idIsEq) }; @@ -293,7 +294,7 @@ class DocTable( --------- */ - getInfo(id:Id) : ?Info { + public func getInfo(id:Id) : ?Info { switch (getDoc(id)) { case null null; case (?doc) { ?infoOfDoc(doc) }; @@ -307,7 +308,7 @@ class DocTable( See also [`Table.count`]($DOCURL/trie.md#count) */ - count() : Nat { + public func count() : Nat { Table.count(table) }; @@ -318,7 +319,7 @@ class DocTable( See also [`Table.toArray`]($DOCURL/trie.md#toarray) */ - allDoc() : [Doc] { + public func allDoc() : [Doc] { Table.toArray (table, func (id:Id, doc:Doc):Doc = doc ) }; @@ -330,7 +331,7 @@ class DocTable( See also [`Table.toArray`]($DOCURL/trie.md#toarray) */ - allInfo() : [Info] { + public func allInfo() : [Info] { Table.toArray (table, func (id:Id, doc:Doc):Info = infoOfDoc(doc) ) }; @@ -341,13 +342,13 @@ class DocTable( =============== */ - keyOfId(x:Id) : Key = new { key = x ; hash = idHash(x) }; + public func keyOfId(x:Id) : Key = new { key = x ; hash = idHash(x) }; - getIdIsEq() :(Id,Id)->Bool = idIsEq; - getIdHash() : Id->Hash = idHash; + public func getIdIsEq() :(Id,Id)->Bool = idIsEq; + public func getIdHash() : Id->Hash = idHash; - getInfoOfDoc() : Doc->Info = infoOfDoc; - getDocOfInfo() : Info->?Doc = docOfInfo; + public func getInfoOfDoc() : Doc->Info = infoOfDoc; + public func getDocOfInfo() : Info->?Doc = docOfInfo; /** @@ -355,9 +356,9 @@ class DocTable( =============== */ - private var idNext:Id = idFirst; + var idNext:Id = idFirst; - private var table : Table = Table.empty(); + var table : Table = Table.empty(); /** Helpers diff --git a/stdlib/examples/produce-exchange/profileActor.as b/stdlib/examples/produce-exchange/profileActor.as index 9168332e0a0..d791a33c561 100644 --- a/stdlib/examples/produce-exchange/profileActor.as +++ b/stdlib/examples/produce-exchange/profileActor.as @@ -6,7 +6,7 @@ actor server { // // except, we assume that region_count and scale_factor are already defined in the enclosing env // - private var dummy = { + var dummy = { func scaledParams(region_count_:Nat, factor:Nat) : T.WorkloadParams = { new { region_count = region_count_:Nat; diff --git a/stdlib/examples/produce-exchange/serverActor.as b/stdlib/examples/produce-exchange/serverActor.as index 64dc812e0b4..37e84de7af9 100644 --- a/stdlib/examples/produce-exchange/serverActor.as +++ b/stdlib/examples/produce-exchange/serverActor.as @@ -72,7 +72,7 @@ actor class Server () { */ - registrarAddUser( + public func registrarAddUser( public_key: T.PublicKey, user_name: Text, description: Text, @@ -102,7 +102,7 @@ actor class Server () { ------------- Get info for all users. */ - allUserInfo() : async [T.UserInfo] { + public func allUserInfo() : async [T.UserInfo] { getModel().userTable.allInfo() }; @@ -111,7 +111,7 @@ actor class Server () { --------------------------- Get the information associated with a user, based on its id. */ - getUserInfo(id:T.UserId) : async Result { + public func getUserInfo(id:T.UserId) : async Result { Result.fromOption( getModel().userTable.getInfo(id), #idErr null @@ -123,7 +123,7 @@ actor class Server () { --------------------------- Returns true if the user id matches the public key. */ - validateUser(public_key: T.PublicKey, id: T.UserId) : async Bool { + public func validateUser(public_key: T.PublicKey, id: T.UserId) : async Bool { getModel().isValidPublicKey(#user(id), public_key); }; @@ -140,7 +140,7 @@ actor class Server () { */ - registrarAddTruckType( + public func registrarAddTruckType( short_name_: Text, description_: Text, capacity_ : T.Weight, @@ -175,7 +175,7 @@ actor class Server () { --------------------- */ - registrarRemTruckType( + public func registrarRemTruckType( id: T.TruckTypeId ) : async Result<(),T.ServerErr> { Result.fromOption<(),T.IdErr>( @@ -189,7 +189,7 @@ actor class Server () { --------------------- */ - getTruckTypeInfo( + public func getTruckTypeInfo( id: T.TruckTypeId ) : async Result { Result.fromOption( @@ -203,7 +203,7 @@ actor class Server () { --------------------- */ - allTruckTypeInfo() : async [T.TruckTypeInfo] { + public func allTruckTypeInfo() : async [T.TruckTypeInfo] { getModel().truckTypeTable.allInfo() }; @@ -222,7 +222,7 @@ actor class Server () { invalid in any way. */ - registrarAddRegion( + public func registrarAddRegion( short_name_: Text, description_: Text, ) : async Result { @@ -244,7 +244,7 @@ actor class Server () { returns `?()` on success, and `null` on failure. */ - registrarRemRegion( + public func registrarRemRegion( id: T.RegionId ) : async Result<(),T.IdErr> { Result.fromOption<(),T.IdErr>( @@ -261,7 +261,7 @@ actor class Server () { */ - getRegionInfo( + public func getRegionInfo( id: T.RegionId ) : async Result { Result.fromOption( @@ -279,7 +279,7 @@ actor class Server () { */ - allRegionInfo() : async [T.RegionInfo] { + public func allRegionInfo() : async [T.RegionInfo] { getModel().regionTable.allInfo() }; @@ -298,7 +298,7 @@ actor class Server () { adds the produce to the system; fails if the given information is invalid in any way. */ - registrarAddProduce( + public func registrarAddProduce( short_name_: Text, description_: Text, grade_: T.Grade, @@ -322,7 +322,7 @@ actor class Server () { returns `?()` on success, and `null` on failure. */ - registrarRemProduce( + public func registrarRemProduce( id: T.ProduceId ) : async Result<(),T.IdErr> { Result.fromOption<(),T.IdErr>( @@ -337,7 +337,7 @@ actor class Server () { --------------------- */ - getProduceInfo( + public func getProduceInfo( id: T.ProduceId ) : async Result { Result.fromOption( @@ -351,7 +351,7 @@ actor class Server () { --------------------- */ - allProduceInfo() : async [T.ProduceInfo] { + public func allProduceInfo() : async [T.ProduceInfo] { getModel().produceTable.allInfo() }; @@ -369,7 +369,7 @@ actor class Server () { adds the producer to the system; fails if the given region is non-existent. */ - registrarAddProducer( + public func registrarAddProducer( producer_public_key : T.PublicKey, short_name_: Text, description_: Text, @@ -399,7 +399,7 @@ actor class Server () { returns `?()` on success, and `null` on failure. */ - registrarRemProducer( + public func registrarRemProducer( id: T.ProducerId ) : async Result<(),T.IdErr> { Result.fromOption<(),T.IdErr>( @@ -414,7 +414,7 @@ actor class Server () { --------------------- */ - getProducerInfo( + public func getProducerInfo( id: T.ProducerId ) : async Result { Result.fromOption( @@ -428,7 +428,7 @@ actor class Server () { --------------------- */ - allProducerInfo() : async [T.ProducerInfo] { + public func allProducerInfo() : async [T.ProducerInfo] { getModel().producerTable.allInfo() }; @@ -446,7 +446,7 @@ actor class Server () { adds the producer to the system; fails if the given region is non-existent. */ - registrarAddRetailer( + public func registrarAddRetailer( retailer_public_key : T.PublicKey, short_name_: Text, description_: Text, @@ -474,7 +474,7 @@ actor class Server () { returns `?()` on success, and `null` on failure. */ - registrarRemRetailer( + public func registrarRemRetailer( id: T.RetailerId ) : async Result<(),T.IdErr> { Result.fromOption<(),T.IdErr>( @@ -488,7 +488,7 @@ actor class Server () { --------------------- */ - getRetailerInfo( + public func getRetailerInfo( id: T.RetailerId ) : async Result { Result.fromOption( @@ -502,7 +502,7 @@ actor class Server () { --------------------- */ - allRetailerInfo() : async [T.RetailerInfo] { + public func allRetailerInfo() : async [T.RetailerInfo] { getModel().retailerTable.allInfo() }; @@ -518,7 +518,7 @@ actor class Server () { --------------------- */ - registrarAddTransporter( + public func registrarAddTransporter( transporter_public_key: T.PublicKey, short_name_: Text, description_: Text, @@ -545,7 +545,7 @@ actor class Server () { */ - registrarRemTransporter( + public func registrarRemTransporter( id: T.TransporterId ) : async Result<(),T.IdErr> { Result.fromOption<(),T.IdErr>( @@ -559,7 +559,7 @@ actor class Server () { --------------------- */ - getTransporterInfo( + public func getTransporterInfo( id: T.TransporterId ) : async Result { Result.fromOption( @@ -574,7 +574,7 @@ actor class Server () { --------------------- */ - allTransporterInfo() : async [T.TransporterInfo] { + public func allTransporterInfo() : async [T.TransporterInfo] { getModel().transporterTable.allInfo() }; @@ -590,7 +590,7 @@ actor class Server () { See also [Model.producerAddInventory]($DOCURL/stdlib/examples/produce-exchange/serverModel.md#produceraddinventory) */ - producerAddInventory( + public func producerAddInventory( public_key: T.PublicKey, id: T.ProducerId, prod: T.ProduceId, @@ -614,7 +614,7 @@ actor class Server () { ------------------------------------------ */ - producerUpdateInventory( + public func producerUpdateInventory( public_key: T.PublicKey, iid: T.InventoryId, id: T.ProducerId, @@ -638,7 +638,7 @@ actor class Server () { `producerRemInventory` --------------------------- */ - producerRemInventory(public_key: T.PublicKey, id:T.InventoryId) : async Result<(),T.ServerErr> { + public func producerRemInventory(public_key: T.PublicKey, id:T.InventoryId) : async Result<(),T.ServerErr> { if (not getModel().isValidPublicKey(#producer(id), public_key)) { return (#err(#publicKeyErr)) }; @@ -649,7 +649,7 @@ actor class Server () { `producerAllInventoryInfo` --------------------------- */ - producerAllInventoryInfo(public_key: T.PublicKey, id:T.UserId) : async Result<[T.InventoryInfo],T.IdErr> { + public func producerAllInventoryInfo(public_key: T.PublicKey, id:T.UserId) : async Result<[T.InventoryInfo],T.IdErr> { Result.fromOption<[T.InventoryInfo],T.IdErr>( getModel() .producerAllInventoryInfo(id), @@ -661,7 +661,7 @@ actor class Server () { `producerAllReservationInfo` --------------------------- */ - producerReservations(public_key: T.PublicKey, id:T.UserId) : async Result<[T.ReservedInventoryInfo],T.IdErr> { + public func producerReservations(public_key: T.PublicKey, id:T.UserId) : async Result<[T.ReservedInventoryInfo],T.IdErr> { Result.fromOption<[T.ReservedInventoryInfo],T.IdErr>( getModel() .producerAllReservationInfo(id), @@ -682,7 +682,7 @@ actor class Server () { --------------------------- The last sales price for produce within a given geographic area; null region id means "all areas." */ - produceMarketInfo(public_key: T.PublicKey, id:T.ProduceId, reg:?T.RegionId) : async Result<[T.ProduceMarketInfo],T.IdErr> { + public func produceMarketInfo(public_key: T.PublicKey, id:T.ProduceId, reg:?T.RegionId) : async Result<[T.ProduceMarketInfo],T.IdErr> { Result.fromOption<[T.ProduceMarketInfo],T.IdErr>( getModel() .produceMarketInfo(id, reg), @@ -696,7 +696,7 @@ actor class Server () { --------------------------- Get the information for all known inventory. */ - allInventoryInfo() : async [T.InventoryInfo] { + public func allInventoryInfo() : async [T.InventoryInfo] { getModel() .inventoryTable.allInfo() }; @@ -706,7 +706,7 @@ actor class Server () { --------------------------- Get the information associated with inventory, based on its id. */ - getInventoryInfo(id:T.InventoryId) : async Result { + public func getInventoryInfo(id:T.InventoryId) : async Result { Result.fromOption( getModel() .inventoryTable.getInfo(id), @@ -724,7 +724,7 @@ actor class Server () { `transporterAddRoute` --------------------------- */ - transporterAddRoute( + public func transporterAddRoute( public_key: T.PublicKey, id: T.TransporterId, rstart: T.RegionId, @@ -744,7 +744,7 @@ actor class Server () { `transporterUpdateRoute` --------------------------- */ - transporterUpdateRoute( + public func transporterUpdateRoute( public_key: T.PublicKey, route: T.RouteId, id: T.TransporterId, @@ -765,7 +765,7 @@ actor class Server () { `transporterRemRoute` --------------------------- */ - transporterRemRoute(public_key: T.PublicKey, id:T.RouteId) : async Result<(),T.ServerErr> { + public func transporterRemRoute(public_key: T.PublicKey, id:T.RouteId) : async Result<(),T.ServerErr> { if (not getModel().isValidPublicKey(#transporter(id), public_key)) { return (#err(#publicKeyErr)) }; @@ -776,7 +776,7 @@ actor class Server () { `transporterAllRouteInfo` --------------------------- */ - transporterAllRouteInfo(public_key: T.PublicKey, id:T.UserId) : async Result<[T.RouteInfo],T.IdErr> { + public func transporterAllRouteInfo(public_key: T.PublicKey, id:T.UserId) : async Result<[T.RouteInfo],T.IdErr> { Result.fromOption<[T.RouteInfo],T.IdErr>( getModel() .transporterAllRouteInfo(id), @@ -788,7 +788,7 @@ actor class Server () { `transporterAllReservationInfo` --------------------------- */ - transporterAllReservationInfo(public_key: T.PublicKey, id:T.UserId) : async Result<[T.ReservedRouteInfo],T.IdErr> { + public func transporterAllReservationInfo(public_key: T.PublicKey, id:T.UserId) : async Result<[T.ReservedRouteInfo],T.IdErr> { Result.fromOption<[T.ReservedRouteInfo],T.IdErr>( getModel() .transporterAllReservationInfo(id), @@ -801,7 +801,7 @@ actor class Server () { --------------------------- Get the information for all known routes. */ - allRouteInfo() : async [T.RouteInfo] { + public func allRouteInfo() : async [T.RouteInfo] { getModel() .routeTable.allInfo() }; @@ -811,7 +811,7 @@ actor class Server () { --------------------------- Get the information for all reserved routes. */ - allReservedRouteInfo() : async [T.ReservedRouteInfo] { + public func allReservedRouteInfo() : async [T.ReservedRouteInfo] { getModel() .reservedRouteTable.allInfo() }; @@ -824,7 +824,7 @@ actor class Server () { */ - getRouteInfo( + public func getRouteInfo( id: T.RouteId ) : async Result { Result.fromOption( @@ -841,9 +841,11 @@ actor class Server () { --------------------------- */ - retailerQueryAll(public_key: T.PublicKey, id:T.RetailerId, - queryProduce:?T.ProduceId, - queryDate:?T.Date + public func retailerQueryAll( + public_key: T.PublicKey, + id:T.RetailerId, + queryProduce:?T.ProduceId, + queryDate:?T.Date ) : async Result { Result.fromOption( getModel(). @@ -856,7 +858,7 @@ actor class Server () { `retailerReserve` --------------------------- */ - retailerReserve( + public func retailerReserve( public_key: T.PublicKey, id:T.RetailerId, inventory:T.InventoryId, @@ -873,7 +875,7 @@ actor class Server () { `retailerReserveMany` --------------------------- */ - retailerReserveMany( + public func retailerReserveMany( public_key: T.PublicKey, id: T.RetailerId, list: [(T.InventoryId, T.RouteId)] @@ -891,7 +893,7 @@ actor class Server () { --------------------------- */ - retailerReservations(public_key: T.PublicKey, id:T.RetailerId) : + public func retailerReservations(public_key: T.PublicKey, id:T.RetailerId) : async Result<[(T.ReservedInventoryInfo, T.ReservedRouteInfo)],T.ServerErr> { @@ -919,7 +921,7 @@ actor class Server () { ---------- */ - getCounts() : async T.ProduceExchangeCounts { + public func getCounts() : async T.ProduceExchangeCounts { let m = getModel(); new { hash_bit_length = 0; @@ -951,7 +953,7 @@ actor class Server () { been processed */ - devViewGMV() : async ?Nat { + public func devViewGMV() : async ?Nat { P.nyi() }; @@ -965,7 +967,7 @@ been processed */ - devViewQueries() : async ?Nat { + public func devViewQueries() : async ?Nat { ?getModel().retailerQueryCount; }; @@ -980,7 +982,7 @@ been processed */ - devViewReservations() : async Nat { + public func devViewReservations() : async Nat { getModel().reservedInventoryTable.count() }; @@ -996,7 +998,7 @@ been processed */ - devViewProducers() : async [T.ProducerInfo] { + public func devViewProducers() : async [T.ProducerInfo] { getModel().producerTable.allInfo() }; @@ -1013,7 +1015,7 @@ been processed */ - devViewTransporters() : async [T.TransporterInfo] { + public func devViewTransporters() : async [T.TransporterInfo] { getModel().transporterTable.allInfo() }; @@ -1029,7 +1031,7 @@ been processed */ - devViewRetailers() : async [T.RetailerInfo] { + public func devViewRetailers() : async [T.RetailerInfo] { getModel().retailerTable.allInfo() }; @@ -1040,12 +1042,12 @@ been processed evaluate a collection of API calls (a "bulk request"), represented as an AS datatype. */ - evalBulkArray(reqs:[L.BulkReq]) : async [L.BulkResp] { + public func evalBulkArray(reqs:[L.BulkReq]) : async [L.BulkResp] { getModel().evalBulkArray(reqs) }; - loadWorkload(params:T.WorkloadParams) : () { + public func loadWorkload(params:T.WorkloadParams) : () { func db(s:Text) = if false {print "Model::loadWorkload: "; print s; print "\n"}; getModel().loadWorkload(params) }; @@ -1055,7 +1057,7 @@ been processed ========================= */ - devTestLoadQuery (region_count:Nat, scale_factor:Nat) { + public func devTestLoadQuery (region_count:Nat, scale_factor:Nat) { func scaledParams(region_count_:Nat, factor:Nat) : T.WorkloadParams = { new { region_count = region_count_:Nat; @@ -1086,9 +1088,9 @@ been processed //private var model : ?Model.Model = null; - private var model : ?Model.Model = ?(Model.Model()); + var model : ?Model.Model = ?(Model.Model()); - private getModel() : Model.Model { + func getModel() : Model.Model { switch model { case (null) { let m = Model.Model(); diff --git a/stdlib/examples/produce-exchange/serverLang.as b/stdlib/examples/produce-exchange/serverLang.as index d6b8be18af7..77f0e84affc 100644 --- a/stdlib/examples/produce-exchange/serverLang.as +++ b/stdlib/examples/produce-exchange/serverLang.as @@ -11,7 +11,7 @@ module { import Result = "../../result.as"; import T = "serverTypes.as"; -type Result = Result.Result; +public type Result = Result.Result; /** `Req` @@ -22,7 +22,7 @@ type Result = Result.Result; - [resp](#resp) - [bulk request](#bulkreq) */ -type Req = { +public type Req = { #reset : () ; #add : AddReq ; #update : UpdateReq ; @@ -41,7 +41,7 @@ type Req = { - [request](#req) - [bulk response](#bulkresp) */ -type Resp = { +public type Resp = { #reset; #add : T.EntId; #update : (); @@ -53,7 +53,7 @@ type Resp = { -------------------------------------- A `Result` whose OK type is `Resp`. */ -type ResultResp = Result; +public type ResultResp = Result; /** `BulkReq` @@ -64,7 +64,7 @@ type ResultResp = Result; - [bulk response](#bulkresp) - [response](#resp) */ -type BulkReq = { +public type BulkReq = { #add : [ AddReq ] ; #update : [ UpdateReq ] ; #rem : [ T.EntId ] ; @@ -77,14 +77,14 @@ type BulkReq = { See also: [bulk request](#bulkreq). */ -type BulkResp = { +public type BulkResp = { #add : [ Result ] ; #update : [ Result<(), T.IdErr> ] ; #rem : [ Result<(), T.IdErr> ] ; } ; -type UserAddReq = new { +public type UserAddReq = { user_name: Text; public_key: Text; description: Text; @@ -100,7 +100,7 @@ type UserAddReq = new { ---------------- Note: The `RouteInfo` type contains too much information about truck types to use here in place of this type. */ -type RouteAddReq = new { +public type RouteAddReq = { id : T.RouteId; transporter : T.TransporterId; truck_type : T.TruckTypeId; @@ -120,7 +120,7 @@ type RouteAddReq = new { etc.), the identifier is ignored; the request, if successful, will generate a fresh identifier for the new entity. */ -type AddReq = { +public type AddReq = { #user : UserAddReq ; #truckType : T.TruckTypeInfo ; #region : T.RegionInfo ; @@ -137,7 +137,7 @@ type AddReq = { -------------------------------------- a server `Update` request, as an AS datatype */ -type UpdateReq = { +public type UpdateReq = { #user : T.UserInfo ; #truckType : T.TruckTypeInfo ; #region : T.RegionInfo ; diff --git a/stdlib/examples/produce-exchange/serverModel.as b/stdlib/examples/produce-exchange/serverModel.as index 072768b53ad..fa1f10df178 100644 --- a/stdlib/examples/produce-exchange/serverModel.as +++ b/stdlib/examples/produce-exchange/serverModel.as @@ -28,43 +28,43 @@ import T = "serverTypes.as"; import L = "serverLang.as"; import M = "serverModelTypes.as"; -let List = (import "../../list.as"); -type List = List.List; +public let List = (import "../../list.as"); +public type List = List.List; -let Hash = (import "../../hash.as").BitVec; -type Hash = Hash.t; +public let Hash = (import "../../hash.as").BitVec; +public type Hash = Hash.t; import Option = "../../option.as"; import Trie = "../../trie2.as"; -type Trie = Trie.Trie; -type TrieBuild = Trie.Build.TrieBuild; -type Key = Trie.Key; +public type Trie = Trie.Trie; +public type TrieBuild = Trie.Build.TrieBuild; +public type Key = Trie.Key; -type Table = Trie.Trie; -let Table = Trie; +public type Table = Trie.Trie; +public let Table = Trie; -type Map = Trie.Trie; -let Map = Trie; +public type Map = Trie.Trie; +public let Map = Trie; import DT = "../../docTable.as"; -let DocTable = DT.DocTable; -type DocTable = DT.DocTable; +public let DocTable = DT.DocTable; +public type DocTable = DT.DocTable; import Result = "../../result.as"; -type Result = Result.Result; +public type Result = Result.Result; -type RouteInventoryMap = Trie<(T.RouteId, T.InventoryId), (M.RouteDoc, M.InventoryDoc)>; -type QueryResult = TrieBuild<(T.RouteId, T.InventoryId), (M.RouteDoc, M.InventoryDoc)>; +public type RouteInventoryMap = Trie<(T.RouteId, T.InventoryId), (M.RouteDoc, M.InventoryDoc)>; +public type QueryResult = TrieBuild<(T.RouteId, T.InventoryId), (M.RouteDoc, M.InventoryDoc)>; -type RoleId = { +public type RoleId = { #user : T.UserId; #producer : T.ProducerId; #transporter : T.TransporterId; #retailer : T.RetailerId; }; -class Model() { +public class Model() { /** PX server language semantics @@ -78,7 +78,7 @@ class Model() { clear existing server state, and replace with a synthetic workload, based on the given parameters. */ - loadWorkload(params:T.WorkloadParams) : () { + public func loadWorkload(params:T.WorkloadParams) : () { func db(s:Text) = if false {print "Model::loadWorkload: "; print s; print "\n"}; /**- generate add requests for these params: */ @@ -126,7 +126,7 @@ class Model() { - update (`#update`) cases */ - evalReq(req:L.Req) : Result { + public func evalReq(req:L.Req) : Result { if false {print "Model::evalReq: "; print (debug_show req); print "\n"; }; switch req { case (#reset) { @@ -316,7 +316,7 @@ class Model() { `evalReqList` ---------- */ - evalReqList(reqs:List) : List = + public func evalReqList(reqs:List) : List = List.map(reqs, evalReq); /** @@ -325,7 +325,7 @@ class Model() { evaluate groups of similar API calls, grouping their results. Each bulk request consists of an array of similar requests (adds, updates, or removes). */ - evalBulk(req:L.BulkReq) : L.BulkResp { + public func evalBulk(req:L.BulkReq) : L.BulkResp { func eatAdd (x:L.Resp) : T.EntId = switch x { case (#add i) i; case _ P.unreachable() }; switch req { @@ -357,7 +357,7 @@ class Model() { - The request is an array of bulk requests, and - Each bulk request in this array consists of an array of similar requests (adds, updates, or removes). */ - evalBulkArray(reqs:[L.BulkReq]) : [L.BulkResp] { + public func evalBulkArray(reqs:[L.BulkReq]) : [L.BulkResp] { Array_tabulate( reqs.len(), func(i:Nat):L.BulkResp = evalBulk(reqs[i]) @@ -369,7 +369,7 @@ class Model() { ------------- xxx */ - countAddReqs( + public func countAddReqs( day_count:Nat, max_route_duration:Nat, producer_count:Nat, @@ -435,7 +435,7 @@ class Model() { and for profiling performance properties of the produce exchange, e.g., average response time for a retailer query. */ - genAddReqs( + public func genAddReqs( day_count:Nat, max_route_duration:Nat, producer_count:Nat, @@ -567,7 +567,7 @@ class Model() { Match a given public key to that of an identified role, whose public key on record. */ - func isValidPublicKey(id:RoleId, public_key:T.PublicKey) : Bool { + public func isValidPublicKey(id:RoleId, public_key:T.PublicKey) : Bool { switch id { case (#user id) { switch (userTable.getDoc(id)) { @@ -601,32 +601,32 @@ class Model() { ================== */ - private debug (t:Text) { print t }; - private debugInt (i:Int) { printInt i }; + func debug (t:Text) { print t }; + func debugInt (i:Int) { printInt i }; - private debugOff (t:Text) { }; - private debugIntOff (i:Int) { }; - private debugOffInt (i:Int) { }; + func debugOff (t:Text) { }; + func debugIntOff (i:Int) { }; + func debugOffInt (i:Int) { }; - private idIsEq(x:Nat,y:Nat):Bool { x == y }; + func idIsEq(x:Nat,y:Nat):Bool { x == y }; - private textIsEq(x:Text,y:Text):Bool { x == y }; + func textIsEq(x:Text,y:Text):Bool { x == y }; - private idPairIsEq(x:(Nat,Nat),y:(Nat,Nat)):Bool { x.0 == y.0 and x.1 == y.1 }; + func idPairIsEq(x:(Nat,Nat),y:(Nat,Nat)):Bool { x.0 == y.0 and x.1 == y.1 }; - private idHash(x:Nat):Hash { Hash.hashOfInt(x) }; + func idHash(x:Nat):Hash { Hash.hashOfInt(x) }; - private idPairHash(x:(Nat,Nat)):Hash { Hash.hashOfIntAcc(Hash.hashOfInt(x.0), x.1) }; + func idPairHash(x:(Nat,Nat)):Hash { Hash.hashOfIntAcc(Hash.hashOfInt(x.0), x.1) }; - private keyOf(x:Nat):Key { + func keyOf(x:Nat):Key { new { key = x ; hash = idHash(x) } }; - private keyOfIdPair(x:Nat, y:Nat):Key<(Nat,Nat)> { + func keyOfIdPair(x:Nat, y:Nat):Key<(Nat,Nat)> { new { key = (x,y) ; hash = idPairHash(x,y) } }; - private keyOfText(x:Text):Key { + func keyOfText(x:Text):Key { new { key = x ; hash = Hash.hashOfText(x) } }; @@ -635,8 +635,8 @@ class Model() { ================== */ - var joinCount = 0; - var retailerQuerySizeMax = 0; + public var joinCount = 0; + public var retailerQuerySizeMax = 0; /** @@ -686,7 +686,7 @@ secondary maps. ----------------- */ - var userTable : M.UserTable = + public var userTable : M.UserTable = DocTable( 0, func(x:T.UserId):T.UserId{x+1}, @@ -722,7 +722,7 @@ secondary maps. ----------------- */ - var truckTypeTable : M.TruckTypeTable = + public var truckTypeTable : M.TruckTypeTable = DocTable( 0, func(x:T.TruckTypeId):T.TruckTypeId{x+1}, @@ -751,7 +751,7 @@ secondary maps. ----------------- */ - var regionTable : M.RegionTable = + public var regionTable : M.RegionTable = DocTable( 0, func(x:T.RegionId):T.RegionId{x+1}, @@ -774,7 +774,7 @@ secondary maps. ----------------- */ - var produceTable : M.ProduceTable = + public var produceTable : M.ProduceTable = DocTable( 0, func(x:T.ProduceId):T.ProduceId{x+1}, @@ -799,7 +799,7 @@ secondary maps. ----------------- */ - var producerTable : M.ProducerTable = + public var producerTable : M.ProducerTable = DocTable( 0, func(x:T.ProducerId):T.ProducerId{x+1}, @@ -835,7 +835,7 @@ secondary maps. --------------- */ - var inventoryTable : M.InventoryTable = + public var inventoryTable : M.InventoryTable = DocTable( 0, func(x:T.InventoryId):T.InventoryId{x+1}, @@ -881,7 +881,7 @@ secondary maps. ----------------- */ - var transporterTable : M.TransporterTable = + public var transporterTable : M.TransporterTable = DocTable ( 0, func(x:T.TransporterId):T.TransporterId{x+1}, @@ -911,7 +911,7 @@ secondary maps. ----------------- */ - var retailerTable : M.RetailerTable = + public var retailerTable : M.RetailerTable = DocTable( 0, func(x:T.RetailerId):T.RetailerId{x+1}, @@ -940,16 +940,16 @@ secondary maps. ) ); - var retailerQueryCount : Nat = 0; - var retailerQueryCost : Nat = 0; - var retailerJoinCount : Nat = 0; + public var retailerQueryCount : Nat = 0; + public var retailerQueryCost : Nat = 0; + public var retailerJoinCount : Nat = 0; /** `routeTable` ---------------- */ - var routeTable : M.RouteTable = + public var routeTable : M.RouteTable = DocTable ( 0, func(x:T.RouteId):T.RouteId{x+1}, @@ -993,7 +993,7 @@ secondary maps. --------------------------- */ - var reservedInventoryTable : M.ReservedInventoryTable = + public var reservedInventoryTable : M.ReservedInventoryTable = DocTable( 0, func(x:T.ReservedInventoryId):T.ReservedInventoryId{x+1}, @@ -1036,7 +1036,7 @@ secondary maps. ---------------- */ - var reservedRouteTable : M.ReservedRouteTable = + public var reservedRouteTable : M.ReservedRouteTable = DocTable( 0, func(x:T.ReservedRouteId):T.ReservedRouteId{x+1}, @@ -1085,7 +1085,7 @@ secondary maps. ===================================== */ - private var usersByUserName + public var usersByUserName : M.UserNameMap = Map.empty(); /** @@ -1113,7 +1113,7 @@ secondary maps. */ - private var routesByDstSrcRegions : M.ByRegionPairRouteMap + public var routesByDstSrcRegions : M.ByRegionPairRouteMap = Map.empty(); /** @@ -1127,7 +1127,7 @@ secondary maps. */ - private var inventoryByRegion : M.ByRegionInventoryMap + public var inventoryByRegion : M.ByRegionInventoryMap = Map.empty(); /** @@ -1157,7 +1157,7 @@ merely forget the older prices. Doing either of these is more complex than the MVP goals, however. */ - private var reservationsByProduceByRegion + public var reservationsByProduceByRegion : M.ByProduceByRegionInventoryReservationMap = Map.empty>>( // reservationsByProduceByRegion, // produce_id, idIsEq)) { @@ -1333,7 +1333,7 @@ than the MVP goals, however. // `producerAllInventoryInfo` // --------------------------- */ - producerAllInventoryInfo(id:T.UserId) : ?[T.InventoryInfo] { + public func producerAllInventoryInfo(id:T.UserId) : ?[T.InventoryInfo] { let doc = switch (producerTable.getDoc(id)) { case null { return null }; case (?doc) { doc }; @@ -1351,7 +1351,7 @@ than the MVP goals, however. --------------------------- */ - producerAddInventory( + public func producerAddInventory( iid_ : ?T.InventoryId, id_ : T.ProducerId, produce_id : T.ProduceId, @@ -1434,7 +1434,7 @@ than the MVP goals, however. --------------------------- */ - producerUpdateInventory( + public func producerUpdateInventory( iid_ : T.InventoryId, id_ : T.ProducerId, produce_id : T.ProduceId, @@ -1487,7 +1487,7 @@ than the MVP goals, however. Remove the given inventory item from the exchange. */ - producerRemInventory(id:T.InventoryId) : Result<(),T.ServerErr> { + public func producerRemInventory(id:T.InventoryId) : Result<(),T.ServerErr> { /**- validate the `id` */ /// xxx macro for this pattern? @@ -1545,7 +1545,7 @@ than the MVP goals, however. --------------------------- */ - producerAllReservationInfo(id:T.ProducerId) : ?[T.ReservedInventoryInfo] { + public func producerAllReservationInfo(id:T.ProducerId) : ?[T.ReservedInventoryInfo] { let doc = switch (producerTable.getDoc(id)) { case null { return null }; case (?doc) { doc }; @@ -1573,7 +1573,7 @@ than the MVP goals, however. `transporterAddRoute` --------------------------- */ - transporterAddRoute( + public func transporterAddRoute( rid_: ?T.RouteId, id_: T.TransporterId, start_region_id: T.RegionId, @@ -1655,7 +1655,7 @@ than the MVP goals, however. --------------------------- Update the given route with the given field values. */ - transporterUpdateRoute( + public func transporterUpdateRoute( rid_ : T.RouteId, id_ : T.TransporterId, start_region_id : T.RegionId, @@ -1713,7 +1713,7 @@ than the MVP goals, however. --------------------------- Remove the given route from the exchange. */ - transporterRemRoute(id:T.RouteId) : Result<(),T.IdErr> { + public func transporterRemRoute(id:T.RouteId) : Result<(),T.IdErr> { let doc = switch (routeTable.getDoc(id)) { case null { return #err(#idErr null) }; @@ -1761,7 +1761,7 @@ than the MVP goals, however. `transporterAllRouteInfo` --------------------------- */ - transporterAllRouteInfo(id:T.TransporterId) : ?[T.RouteInfo] { + public func transporterAllRouteInfo(id:T.TransporterId) : ?[T.RouteInfo] { let doc = switch (transporterTable.getDoc(id)) { case null { return null }; case (?doc) { doc }; @@ -1784,7 +1784,7 @@ than the MVP goals, however. --------------------------- */ - transporterAllReservationInfo(id:T.TransporterId) : ?[T.ReservedRouteInfo] { + public func transporterAllReservationInfo(id:T.TransporterId) : ?[T.ReservedRouteInfo] { let doc = switch (transporterTable.getDoc(id)) { case null { return null }; case (?doc) { doc }; @@ -1815,7 +1815,7 @@ than the MVP goals, however. Prepare reservation information for a server client based on the given inventory and route documents. */ - makeReservationInfo(item:M.InventoryDoc, route:M.RouteDoc) : T.ReservationInfo { + public func makeReservationInfo(item:M.InventoryDoc, route:M.RouteDoc) : T.ReservationInfo { new { produce =item.produce.id :T.ProduceId; producer =item.producer :T.ProducerId; @@ -1847,7 +1847,7 @@ than the MVP goals, however. Check whether the given truck type can accommodate the given produce type. */ - isCompatibleTruckType(tt:M.TruckTypeDoc, produce:M.ProduceDoc) : Bool { + public func isCompatibleTruckType(tt:M.TruckTypeDoc, produce:M.ProduceDoc) : Bool { // todo true }; @@ -1860,7 +1860,7 @@ than the MVP goals, however. */ - isFeasibleReservation( + public func isFeasibleReservation( retailer:M.RetailerDoc, item:M.InventoryDoc, route:M.RouteDoc, @@ -1933,7 +1933,7 @@ than the MVP goals, however. - [`Trie.prod`]($DOCURL/trie.md#prod): For the catesian product of routes and inventory. - [`Trie.mergeDisjoint2D`]($DOCURL/trie.md#mergeDisjoint2D): To flatten 2D mappings into 1D mappings. */ - retailerQueryAll( + public func retailerQueryAll( id:T.RetailerId, queryProduce:?T.ProduceId, queryDate:?T.Date @@ -2064,7 +2064,7 @@ than the MVP goals, however. --------------------------- */ - retailerAllReservationInfo(id:T.RetailerId) : + public func retailerAllReservationInfo(id:T.RetailerId) : ?[(T.ReservedInventoryInfo, T.ReservedRouteInfo)] { @@ -2101,7 +2101,7 @@ than the MVP goals, however. the created reservation documents, each have a valid id, which this operation returns. */ - retailerReserve( + public func retailerReserve( retailer_id:T.RetailerId, inventory_id:T.InventoryId, route_id:T.RouteId) : Result<(T.ReservedRouteId, T.ReservedInventoryId), T.IdErr> @@ -2279,7 +2279,7 @@ than the MVP goals, however. `retailerReserveMany` --------------------------- */ - retailerReserveMany( + public func retailerReserveMany( id:T.RetailerId, array:[(T.InventoryId,T.RouteId)]) : [Result<(T.ReservedRouteId, T.ReservedInventoryId), T.IdErr>] diff --git a/stdlib/examples/produce-exchange/serverModelTypes.as b/stdlib/examples/produce-exchange/serverModelTypes.as index 56ce4a7ca35..bc1bd858cab 100644 --- a/stdlib/examples/produce-exchange/serverModelTypes.as +++ b/stdlib/examples/produce-exchange/serverModelTypes.as @@ -36,10 +36,10 @@ Representation import T = "serverTypes.as"; import Trie = "../../trie2.as"; -type Trie = Trie.Trie; +public type Trie = Trie.Trie; -type Map = Trie; -let Map = Trie; +public type Map = Trie; +public let Map = Trie; /** @@ -97,8 +97,8 @@ internal sharing: */ -let DocTable = (import "../../docTable.as"); -type DocTable = DocTable.DocTable; +public let DocTable = (import "../../docTable.as"); +public type DocTable = DocTable.DocTable; /** `UserDoc` @@ -106,7 +106,7 @@ type DocTable = DocTable.DocTable; User documents. */ -type UserDoc = { +public type UserDoc = { id: T.UserId; user_name: Text; public_key: Text; @@ -118,10 +118,10 @@ type UserDoc = { isDeveloper: Bool; }; -type UserTable = +public type UserTable = DocTable; -type UserNameMap = +public type UserNameMap = Map; /** @@ -132,7 +132,7 @@ type UserNameMap = - See also [`DocTable`](). */ -type TruckTypeDoc = { +public type TruckTypeDoc = { id : T.TruckTypeId; short_name : Text; description : Text; @@ -142,7 +142,7 @@ type TruckTypeDoc = { isFreezer : Bool; }; -type TruckTypeTable = +public type TruckTypeTable = DocTable; /** @@ -150,13 +150,13 @@ type TruckTypeTable = ========================== */ -type RegionDoc = { +public type RegionDoc = { id : T.RegionId; short_name : Text; description : Text; }; -type RegionTable = +public type RegionTable = DocTable; /** @@ -164,14 +164,14 @@ type RegionTable = ================== */ -type ProduceDoc = { +public type ProduceDoc = { id : T.ProduceId; short_name : Text; description : Text; grade : T.Grade; }; -type ProduceTable = +public type ProduceTable = DocTable; /** @@ -179,7 +179,7 @@ type ProduceTable = ======================= */ -type ProducerDoc = { +public type ProducerDoc = { id : T.ProducerId; public_key: Text; short_name : Text; @@ -189,7 +189,7 @@ type ProducerDoc = { reserved : ReservedInventoryMap; }; -type ProducerTable = +public type ProducerTable = DocTable; /** @@ -197,7 +197,7 @@ type ProducerTable = ======================== */ -type InventoryDoc = { +public type InventoryDoc = { id : T.InventoryId; produce : ProduceDoc; producer : T.ProducerId; @@ -209,27 +209,27 @@ type InventoryDoc = { comments : Text; }; -type InventoryTable = +public type InventoryTable = DocTable; -type InventoryMap = +public type InventoryMap = Map; -type ByProducerInventoryMap = +public type ByProducerInventoryMap = Map>; /** By-region inventory indexing ----------------------------- */ -type ByRegionInventoryMap = Map; +public type ByRegionInventoryMap = Map; /** `ReservedInventory` documents ================================== */ -type ReservedInventoryDoc= { +public type ReservedInventoryDoc= { id : T.ReservedInventoryId; retailer : T.RetailerId; item : InventoryDoc; @@ -240,10 +240,10 @@ type ReservedInventoryDoc= { ----------------------------- */ -type ReservedInventoryTable = +public type ReservedInventoryTable = DocTable; -type ReservedInventoryMap = +public type ReservedInventoryMap = Map; /** @@ -251,7 +251,7 @@ type ReservedInventoryMap = ================== */ -type RetailerDoc = { +public type RetailerDoc = { id : T.RetailerId; public_key: Text; short_name : Text; @@ -260,13 +260,13 @@ type RetailerDoc = { reserved : ReservedInventoryRouteMap; }; -type RetailerTable = +public type RetailerTable = DocTable; -type ReservedInventoryRouteMap = +public type ReservedInventoryRouteMap = Map; -type ByProduceByRegionInventoryReservationMap = +public type ByProduceByRegionInventoryReservationMap = Map>>; /** @@ -274,7 +274,7 @@ type ByProduceByRegionInventoryReservationMap = ================== */ -type TransporterDoc = { +public type TransporterDoc = { id : T.TransporterId; public_key: Text; // no region; the transporters are the supply of routes, not "end @@ -285,7 +285,7 @@ type TransporterDoc = { reserved : ReservedRouteMap; }; -type TransporterTable = +public type TransporterTable = DocTable; /** @@ -293,7 +293,7 @@ type TransporterTable = ================== */ -type RouteDoc = { +public type RouteDoc = { id : T.RouteId; transporter : T.TransporterId; truck_type : TruckTypeDoc; @@ -305,11 +305,11 @@ type RouteDoc = { // ... more? }; -type RouteTable = +public type RouteTable = DocTable; -type RouteMap = +public type RouteMap = Map; /** @@ -318,10 +318,10 @@ type RouteMap = */ // A possibly-sparse 2D table mapping each region-routeid pair to zero or one routes. -type ByRegionRouteMap = Map; +public type ByRegionRouteMap = Map; // A possibly-sparse 3D table mapping each region-region-routeid triple to zero or one routes. -type ByRegionPairRouteMap = Map; +public type ByRegionPairRouteMap = Map; /** @@ -329,13 +329,13 @@ type ByRegionPairRouteMap = Map; ----------------------------- */ -type ReservedRouteDoc = { +public type ReservedRouteDoc = { id : T.ReservedRouteId; retailer : T.RetailerId; route : RouteDoc; }; -type ReservedRouteTable = DocTable; +public type ReservedRouteTable = DocTable; -type ReservedRouteMap = Map; +public type ReservedRouteMap = Map; } diff --git a/stdlib/examples/produce-exchange/serverTypes.as b/stdlib/examples/produce-exchange/serverTypes.as index 79cb5fd7759..8594fc64628 100644 --- a/stdlib/examples/produce-exchange/serverTypes.as +++ b/stdlib/examples/produce-exchange/serverTypes.as @@ -22,23 +22,23 @@ These types standardize representations for many common notions // import Date // xxx Dates, eventually from a standard library: -type Date = Nat; +public type Date = Nat; // xxx standard weight units? -type Weight = Nat; +public type Weight = Nat; // xxx standard price units? -type Price = Nat; +public type Price = Nat; -type Unit = Nat; // xxx replace with a variant type -type Grade = Nat; // xxx replace with a variant type +public type Unit = Nat; // xxx replace with a variant type +public type Grade = Nat; // xxx replace with a variant type -type TruckCapacity = Weight; +public type TruckCapacity = Weight; -type Quantity = Nat; +public type Quantity = Nat; -type PricePerUnit = Price; // needed to calculate prices -type PriceTotal = Price; +public type PricePerUnit = Price; // needed to calculate prices +public type PriceTotal = Price; /** User Names @@ -49,7 +49,7 @@ Each user of the exchange chooses a unique _user name_, represented as `Text`. In response to this choice, the exchange assigns the user a unique Id (see below); it maintains a mapping from this user name to the (internally-chosen) user Id. */ -type UserName = Text; +public type UserName = Text; /** Unique Ids @@ -63,21 +63,21 @@ Internally, each type of Id serves as a "row key" for a table (or two). */ -type UserId = Nat; +public type UserId = Nat; -type PublicKey = Text; +public type PublicKey = Text; -type RegionId = Nat; -type TruckTypeId = Nat; -type ProduceId = Nat; +public type RegionId = Nat; +public type TruckTypeId = Nat; +public type ProduceId = Nat; -type ProducerId = Nat; -type InventoryId = Nat; -type ReservedInventoryId = Nat; -type RetailerId = Nat; -type TransporterId = Nat; -type RouteId = Nat; -type ReservedRouteId = Nat; +public type ProducerId = Nat; +public type InventoryId = Nat; +public type ReservedInventoryId = Nat; +public type RetailerId = Nat; +public type TransporterId = Nat; +public type RouteId = Nat; +public type ReservedRouteId = Nat; /** `EntId` @@ -86,7 +86,7 @@ type ReservedRouteId = Nat; The optional payload of an `#idErr` error message. */ -type EntId = { +public type EntId = { #user : UserId ; #truckType : TruckTypeId ; #region : RegionId ; @@ -104,14 +104,14 @@ type EntId = { */ /** Optional entity ID */ -type OpEntId = ?EntId; +public type OpEntId = ?EntId; /** `IdErr` --------- An ID error consists only of the `#idErr` case, which carries an optional ID. */ -type IdErr = { +public type IdErr = { #idErr: OpEntId; }; @@ -120,7 +120,7 @@ type IdErr = { ------------ A Server error occurs when the client either has access control issues (e.g., `#publicKeyErr`) or provides invalid parameters (e.g., `#idErr`). */ -type ServerErr = { +public type ServerErr = { #idErr: OpEntId; #publicKeyErr; }; @@ -136,7 +136,7 @@ Public info associated with Ids ------------- */ -type UserInfo = new { +public type UserInfo = { id: UserId; public_key: Text; user_name: Text; @@ -153,7 +153,7 @@ type UserInfo = new { `TruckTypeInfo` ----------------- */ -type TruckTypeInfo = new { +public type TruckTypeInfo = { id : TruckTypeId; short_name : Text; description : Text; @@ -167,7 +167,7 @@ type TruckTypeInfo = new { `RegionInfo` ----------------- */ -type RegionInfo = new { +public type RegionInfo = { id : RegionId; short_name : Text; description : Text; @@ -178,7 +178,7 @@ type RegionInfo = new { ----------------- */ -type ProduceInfo = new { +public type ProduceInfo = { id : ProduceId; short_name : Text; description : Text; @@ -190,7 +190,7 @@ type ProduceInfo = new { ----------------- */ -type ProducerInfo = new { +public type ProducerInfo = { id : ProducerId; public_key: Text; short_name : Text; @@ -205,7 +205,7 @@ type ProducerInfo = new { ----------------- */ -type InventoryInfo = new { +public type InventoryInfo = { id : InventoryId; produce : ProduceId; producer : ProducerId; @@ -222,7 +222,7 @@ type InventoryInfo = new { ----------------------------- */ -type ReservedInventoryInfo = new { +public type ReservedInventoryInfo = { id : ReservedInventoryId; retailer : RetailerId; item : InventoryInfo; @@ -234,7 +234,7 @@ type ReservedInventoryInfo = new { */ // for now, this is the same as a ReservationInfo -type ProduceMarketInfo = new { +public type ProduceMarketInfo = { produce: ProduceId; producer: ProducerId; quant: Quantity; @@ -255,7 +255,7 @@ type ProduceMarketInfo = new { ----------------- */ -type RetailerInfo = new { +public type RetailerInfo = { id : RetailerId; public_key: Text; short_name : Text; @@ -268,7 +268,7 @@ type RetailerInfo = new { ----------------- */ -type TransporterInfo = new { +public type TransporterInfo = { id : TransporterId; public_key: Text; // no region; the transporters are the supply of routes, not "end @@ -284,7 +284,7 @@ type TransporterInfo = new { ----------------- */ -type RouteInfo = new { +public type RouteInfo = { id : RouteId; transporter : TransporterId; truck_type : TruckTypeInfo; @@ -300,7 +300,7 @@ type RouteInfo = new { ----------------- */ -type ReservedRouteInfo = new { +public type ReservedRouteInfo = { id : ReservedRouteId; retailer : RetailerId; route : RouteInfo; @@ -311,7 +311,7 @@ type ReservedRouteInfo = new { ----------------- */ -type ReservationInfo = new { +public type ReservationInfo = { produce: ProduceId; producer: ProducerId; quant: Quantity; @@ -338,7 +338,7 @@ type ReservationInfo = new { Developer-level, counter-based information about the exchange, including counts of each kind of entity. */ -type ProduceExchangeCounts = new { +public type ProduceExchangeCounts = { hash_bit_length : Nat; truck_type_count : Nat; region_count : Nat; @@ -372,7 +372,7 @@ type ProduceExchangeCounts = new { */ // xxx same as a reservation structure; represents a possible reservation to make -type QueryAllResult = ReservationInfo; +public type QueryAllResult = ReservationInfo; /** @@ -384,7 +384,7 @@ the 2019.03.12 ActorScript Team meeting. */ -type QueryAllResults = [QueryAllResult]; +public type QueryAllResults = [QueryAllResult]; /** @@ -394,7 +394,7 @@ type QueryAllResults = [QueryAllResult]; The server can generate synthetic workloads given a small set of parameters. */ -type WorkloadParams = new { +public type WorkloadParams = { day_count:Nat; max_route_duration:Nat; producer_count:Nat; diff --git a/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.as b/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.as index 473b3e4a4c8..ab2a1956886 100644 --- a/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.as +++ b/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.as @@ -1,7 +1,7 @@ -let T = (import "../serverTypes.as"); -let A = (import "../serverActor.as"); -let Result = (import "../../../result.as"); -let Option = (import "../../../option.as"); +import T = "../serverTypes.as"; +import A = "../serverActor.as"; +import Result = "../../../result.as"; +import Option = "../../../option.as"; func printEntityCount(entname:Text, count:Nat) { print ("- " # entname # " count: "); @@ -16,7 +16,7 @@ func printLabeledCost(lab:Text, cost:Nat) { }; actor class Test() = this { - go() { + public func go() { ignore(async { let s = A.Server(); diff --git a/stdlib/hash.as b/stdlib/hash.as index 8be2b2e4568..e772bdb9219 100644 --- a/stdlib/hash.as +++ b/stdlib/hash.as @@ -32,10 +32,10 @@ going forward. */ /** A "bit string" as a linked list of bits: */ -type BitList = ?(Bool, BitList); +public type BitList = ?(Bool, BitList); /** A "bit vector" is a bounded-length bit string packed into a single word: */ -type BitVec = Word32; +public type BitVec = Word32; /** @@ -45,16 +45,16 @@ type BitVec = Word32; */ -module BitVec { +public module BitVec { - type t = BitVec; + public type t = BitVec; // Jenkin's one at a time: // https://en.wikipedia.org/wiki/Jenkins_hash_function#one_at_a_time // // The input type should actually be [Word8]. // Note: Be sure to explode each Word8 of a Word32 into its own Word32, and to shift into lower 8 bits. - func hashWord8s(key:[BitVec]) : BitVec = label profile_hash_hashWord8s : BitVec { + public func hashWord8s(key:[BitVec]) : BitVec = label profile_hash_hashWord8s : BitVec { var hash = natToWord32(0); for (wordOfKey in key.vals()) { label profile_hash_hashWord8s_forLoop : () hash := hash + wordOfKey; @@ -67,11 +67,11 @@ module BitVec { return hash; }; - func length() : Nat = + public func length() : Nat = label profile_hash_length : Nat 31; - func hashOfInt(i:Int) : BitVec = label profile_hash_hashOfInt : BitVec { + public func hashOfInt(i:Int) : BitVec = label profile_hash_hashOfInt : BitVec { //hashInt(i) let j = intToWord32(i); hashWord8s( @@ -82,7 +82,7 @@ module BitVec { ]); }; - func hashOfIntAcc(h1:BitVec, i:Int) : BitVec = label profile_hash_hashOfIntAcc : BitVec { + public func hashOfIntAcc(h1:BitVec, i:Int) : BitVec = label profile_hash_hashOfIntAcc : BitVec { let j = intToWord32(i); hashWord8s( [h1, @@ -93,7 +93,7 @@ module BitVec { ]); }; - func hashOfText(t:Text) : BitVec = label profile_hash_hashOfText : BitVec { + public func hashOfText(t:Text) : BitVec = label profile_hash_hashOfText : BitVec { var x = 0 : Word32; for (c in t.chars()) { x := x ^ charToWord32(c); @@ -102,7 +102,7 @@ module BitVec { }; /** Project a given bit from the bit vector. */ - func getHashBit(h:BitVec, pos:Nat) : Bool = label profile_getHashBit : Bool { + public func getHashBit(h:BitVec, pos:Nat) : Bool = label profile_getHashBit : Bool { assert (pos <= length()); if ((h & (natToWord32(1) << natToWord32(pos))) != natToWord32(0)) { label profile_getHashBit_true : Bool @@ -115,12 +115,12 @@ module BitVec { }; /** Test if two lists of bits are equal. */ - func hashEq(ha:BitVec, hb:BitVec) : Bool { + public func hashEq(ha:BitVec, hb:BitVec) : Bool { label profile_hashEq : Bool ha == hb }; - func bitsPrintRev(bits:BitVec) { + public func bitsPrintRev(bits:BitVec) { for (j in range(0, length() - 1)) { if (getHashBit(bits, j)) { print "1" @@ -130,7 +130,7 @@ module BitVec { } }; - func hashPrintRev(bits:BitVec) { + public func hashPrintRev(bits:BitVec) { for (j in range(length() - 1, 0)) { if (getHashBit(bits, j)) { print "1" @@ -140,7 +140,7 @@ module BitVec { } }; - func toList(v:BitVec) : BitList { + public func toList(v:BitVec) : BitList { func rec(pos:Nat) : BitList { if (pos >= length()) { null } else { @@ -163,16 +163,16 @@ module BitVec { TODO: Replace with bitwise operations on Words, for greater efficiency. */ -module BitList { +public module BitList { - type t = BitList; + public type t = BitList; - func hashOfInt(i:Int) : BitList { + public func hashOfInt(i:Int) : BitList { BitVec.toList(BitVec.hashOfInt(i)) }; /** Test if two lists of bits are equal. */ - func getHashBit(h:BitList, pos:Nat) : Bool { + public func getHashBit(h:BitList, pos:Nat) : Bool { switch h { case null { // XXX: Should be an error case; it shouldn't happen in our tests if we set them up right. @@ -186,7 +186,7 @@ module BitList { }; /** Test if two lists of bits are equal. */ - func hashEq(ha:BitList, hb:BitList) : Bool { + public func hashEq(ha:BitList, hb:BitList) : Bool { switch (ha, hb) { case (null, null) true; case (null, _) false; @@ -198,7 +198,7 @@ module BitList { } }; - func bitsPrintRev(bits:BitList) { + public func bitsPrintRev(bits:BitList) { switch bits { case null { print "" }; case (?(bit,bits_)) { @@ -209,7 +209,7 @@ module BitList { } }; - func hashPrintRev(bits:BitList) { + public func hashPrintRev(bits:BitList) { switch bits { case null { print "" }; case (?(bit,bits_)) { @@ -231,6 +231,6 @@ module BitList { the standard library to use: */ -type Hash = BitVec; -let Hash = BitVec; +public type Hash = BitVec; +public let Hash = BitVec; } diff --git a/stdlib/list.as b/stdlib/list.as index 03c376a1032..05bab397f13 100644 --- a/stdlib/list.as +++ b/stdlib/list.as @@ -17,7 +17,7 @@ remainder of the list (the cell's _tail_). */ -type List = ?(T, List); +public type List = ?(T, List); /** Interface @@ -29,7 +29,7 @@ type List = ?(T, List); ------ empty list */ - func nil() : List = + public func nil() : List = null; @@ -38,7 +38,7 @@ type List = ?(T, List); -------- test for empty list */ - func isNil(l : List) : Bool { + public func isNil(l : List) : Bool { switch l { case null { true }; case _ { false }; @@ -50,7 +50,7 @@ type List = ?(T, List); ------------- aka "list cons" */ - func push(x : T, l : List) : List = + public func push(x : T, l : List) : List = ?(x, l); /** @@ -58,7 +58,7 @@ type List = ?(T, List); ---------- last element, optionally; tail recursive */ - func last(l : List) : ?T = { + public func last(l : List) : ?T = { switch l { case null { null }; case (?(x,null)) { ?x }; @@ -71,7 +71,7 @@ type List = ?(T, List); -------- treat the list as a stack; combines the usual operations `head` and (non-failing) `tail` into one operation */ - func pop(l : List) : (?T, List) = { + public func pop(l : List) : (?T, List) = { switch l { case null { (null, null) }; case (?(h, t)) { (?h, t) }; @@ -83,7 +83,7 @@ type List = ?(T, List); -------- length; tail recursive */ - func len(l : List) : Nat = label profile_list_len : Nat { + public func len(l : List) : Nat = label profile_list_len : Nat { func rec(l : List, n : Nat) : Nat = label profile_list_len_rec : Nat { switch l { case null { n }; @@ -98,7 +98,7 @@ type List = ?(T, List); -------- test length against a maximum value; tail recursive */ - func lenIsEqLessThan(l : List, i : Nat) : Bool = + public func lenIsEqLessThan(l : List, i : Nat) : Bool = label profile_list_lenIsEqLessThan_begin : Bool { func rec(l : List, i : Nat) : Bool = label profile_list_lenIsEqLessThan_rec : Bool { switch l { @@ -122,7 +122,7 @@ type List = ?(T, List); -------- get the length, unless greater than a maximum value, in which return null; tail recursive */ - func lenClamp(l : List, i0 : Nat) : ?Nat = + public func lenClamp(l : List, i0 : Nat) : ?Nat = label profile_list_lenClamp : (?Nat) { func rec(l : List, i : Nat) : ?Nat = label profile_list_lenClamp_rec : (?Nat) { switch l { @@ -146,7 +146,7 @@ type List = ?(T, List); --------- array-like list access, but in linear time; tail recursive */ - func nth(l : List, n : Nat) : ?T = { + public func nth(l : List, n : Nat) : ?T = { switch (n, l) { case (_, null) { null }; case (0, (?(h,t))) { ?h }; @@ -159,7 +159,7 @@ type List = ?(T, List); -------- reverse the list; tail recursive */ - func rev(l : List) : List = { + public func rev(l : List) : List = { func rec(l : List, r : List) : List { switch l { case null { r }; @@ -174,7 +174,7 @@ type List = ?(T, List); --------- Called `app` in SML Basis, and `iter` in OCaml; tail recursive */ - func iter(l : List, f:T -> ()) : () = { + public func iter(l : List, f:T -> ()) : () = { func rec(l : List) : () { switch l { case null { () }; @@ -191,7 +191,7 @@ type List = ?(T, List); Note: need mutable Cons tails for tail-recursive map. */ - func map(l : List, f:T -> S) : List = { + public func map(l : List, f:T -> S) : List = { func rec(l : List) : List { switch l { case null { null }; @@ -206,7 +206,7 @@ type List = ?(T, List); ---------- filter the list elements; non-tail recursive */ - func filter(l : List, f:T -> Bool) : List = { + public func filter(l : List, f:T -> Bool) : List = { func rec(l : List) : List { switch l { case null { null }; @@ -221,7 +221,7 @@ type List = ?(T, List); ---------- split the list elements; non-tail recursive */ - func split(l : List, f:T -> Bool) : (List, List) = { + public func split(l : List, f:T -> Bool) : (List, List) = { func rec(l : List) : (List, List) = label profile_list_split_rec : (List, List) { switch l { @@ -239,7 +239,7 @@ type List = ?(T, List); -------------- map and filter the list elements; non-tail recursive */ - func mapFilter(l : List, f:T -> ?S) : List = { + public func mapFilter(l : List, f:T -> ?S) : List = { func rec(l : List) : List { switch l { case null { null }; @@ -259,7 +259,7 @@ type List = ?(T, List); --------- append two lists; non-tail recursive */ - func append(l : List, m : List) : List = { + public func append(l : List, m : List) : List = { func rec(l : List) : List { switch l { case null { m }; @@ -274,7 +274,7 @@ type List = ?(T, List); ----------- concat (aka "list join"); tail recursive, but requires "two passes" */ - func concat(l : List>) : List = { + public func concat(l : List>) : List = { // 1/2: fold from left to right, reverse-appending the sublists... let r = { let f = func(a:List, b:List) : List { revAppend(a,b) }; @@ -289,7 +289,7 @@ type List = ?(T, List); ------------- See SML Basis library; tail recursive */ - func revAppend(l1 : List, l2 : List) : List = { + public func revAppend(l1 : List, l2 : List) : List = { switch l1 { case null { l2 }; case (?(h,t)) { revAppend(t, ?(h,l2)) }; @@ -302,7 +302,7 @@ type List = ?(T, List); "take" `n` elements from the prefix of the given list. If the given list has fewer than `n` elements, we return the full input list. */ - func take(l : List, n:Nat) : List = { + public func take(l : List, n:Nat) : List = { switch (l, n) { case (_, 0) { null }; case (null,_) { null }; @@ -314,7 +314,7 @@ type List = ?(T, List); `drop` ---------- */ - func drop(l : List, n:Nat) : List = { + public func drop(l : List, n:Nat) : List = { switch (l, n) { case (l_, 0) { l_ }; case (null, _) { null }; @@ -327,7 +327,7 @@ type List = ?(T, List); --------------- fold list left-to-right using function `f`; tail recursive */ - func foldLeft(l : List, a:S, f:(T,S) -> S) : S = { + public func foldLeft(l : List, a:S, f:(T,S) -> S) : S = { func rec(l:List, a:S) : S = { switch l { case null { a }; @@ -342,7 +342,7 @@ type List = ?(T, List); ------------ fold the list right-to-left using function `f`; non-tail recursive */ - func foldRight(l : List, a:S, f:(T,S) -> S) : S = { + public func foldRight(l : List, a:S, f:(T,S) -> S) : S = { func rec(l:List) : S = { switch l { case null { a }; @@ -357,7 +357,7 @@ type List = ?(T, List); ----------- test if there exists list element for which given predicate is true */ - func find(l: List, f:T -> Bool) : ?T = { + public func find(l: List, f:T -> Bool) : ?T = { func rec(l:List) : ?T { switch l { case null { null }; @@ -372,7 +372,7 @@ type List = ?(T, List); --------- test if there exists list element for which given predicate is true */ - func exists(l: List, f:T -> Bool) : Bool = { + public func exists(l: List, f:T -> Bool) : Bool = { func rec(l:List) : Bool { switch l { case null { false }; @@ -389,7 +389,7 @@ type List = ?(T, List); ------- test if given predicate is true for all list elements */ - func all(l: List, f:T -> Bool) : Bool = { + public func all(l: List, f:T -> Bool) : Bool = { func rec(l:List) : Bool { switch l { case null { true }; @@ -404,7 +404,7 @@ type List = ?(T, List); --------- Given two ordered lists, merge them into a single ordered list */ - func merge(l1: List, l2: List, lte:(T,T) -> Bool) : List { + public func merge(l1: List, l2: List, lte:(T,T) -> Bool) : List { func rec(l1: List, l2: List) : List { switch (l1, l2) { case (null, _) { l2 }; @@ -429,7 +429,7 @@ type List = ?(T, List); To do: Eventually, follow `collate` design from SML Basis, with real sum types, use 3-valued `order` type here. */ - func lessThanEq(l1: List, l2: List, lte:(T,T) -> Bool) : Bool { + public func lessThanEq(l1: List, l2: List, lte:(T,T) -> Bool) : Bool { func rec(l1: List, l2: List) : Bool { switch (l1, l2) { case (null, _) { true }; @@ -447,7 +447,7 @@ type List = ?(T, List); `isEq(l1, l2)` is equivalent to `lessThanEq(l1,l2) && lessThanEq(l2,l1)`, but the former is more efficient. */ - func isEq(l1: List, l2: List, eq:(T,T) -> Bool) : Bool { + public func isEq(l1: List, l2: List, eq:(T,T) -> Bool) : Bool { func rec(l1: List, l2: List) : Bool { switch (l1, l2) { case (null, null) { true }; @@ -465,7 +465,7 @@ type List = ?(T, List); using a predicate, create two lists from one: the "true" list, and the "false" list. (See SML basis library); non-tail recursive. */ - func partition(l: List, f:T -> Bool) : (List, List) { + public func partition(l: List, f:T -> Bool) : (List, List) { func rec(l: List) : (List, List) { switch l { case null { (null, null) }; @@ -488,7 +488,7 @@ type List = ?(T, List); generate a list based on a length, and a function from list index to list element. (See SML basis library); non-tail recursive. */ - func tabulate(n:Nat, f:Nat -> T) : List { + public func tabulate(n:Nat, f:Nat -> T) : List { func rec(i:Nat) : List { if (i == n) { null } else { ?(f(i), rec(i+1)) } }; diff --git a/stdlib/option.as b/stdlib/option.as index 4d0398e06bd..c992ebac0bf 100644 --- a/stdlib/option.as +++ b/stdlib/option.as @@ -5,9 +5,9 @@ Functions for Option types. */ -private import P "prelude.as"; +import P "prelude.as"; -type t = ?A; +public type t = ?A; /*** @@ -17,13 +17,13 @@ type t = ?A; Returns true if the value is not `null`. */ -func isSomeAny(x: ?Any): Bool = +public func isSomeAny(x: ?Any): Bool = switch x { case null false; case _ true; }; -func isSome(x: t): Bool = isSomeAny(x); +public func isSome(x: t): Bool = isSomeAny(x); /*** @@ -33,9 +33,9 @@ func isSome(x: t): Bool = isSomeAny(x); Returns true if the value is `null`. */ -func isNullAny(x: ?Any): Bool = not isSome(x); +public func isNullAny(x: ?Any): Bool = not isSome(x); -func isNull(x: t): Bool = not isSome(x); +public func isNull(x: t): Bool = not isSome(x); /*** @@ -45,7 +45,7 @@ func isNull(x: t): Bool = not isSome(x); Unwrap an optional value, and fail if it is `null`. */ -func unwrap(x: ?T): T = +public func unwrap(x: ?T): T = switch x { case null { P.unreachable() }; case (?x_) x_; @@ -59,7 +59,7 @@ func unwrap(x: ?T): T = Unwrap an optional value or a default. */ -func unwrapOr(x: ?T, d: T): T = +public func unwrapOr(x: ?T, d: T): T = switch x { case null { d }; case (?x_) x_; @@ -73,7 +73,7 @@ func unwrapOr(x: ?T, d: T): T = Unwrap an optional value. If null, return the default, else, apply the function to the unwrapped value. */ -func option(x: ?A, f: A->B, d: B): B = +public func option(x: ?A, f: A->B, d: B): B = switch x { case null { d }; case (?x_) f(x_); @@ -87,7 +87,7 @@ func option(x: ?A, f: A->B, d: B): B = Apply a function to the wrapped value. */ -func map(x: ?A, f: A->B): ?B = +public func map(x: ?A, f: A->B): ?B = switch x { case null null; case (?x_) ?f(x_); @@ -101,7 +101,7 @@ func map(x: ?A, f: A->B): ?B = Apply a function to the wrapped value. */ -func fmap(x: ?A, f: A->?B): ?B = +public func fmap(x: ?A, f: A->?B): ?B = switch x { case null null; case (?x_) f(x_); @@ -115,13 +115,13 @@ func fmap(x: ?A, f: A->?B): ?B = Assert that the given value is not `null`; ignore this value and return unit. */ -func assertSomeAny(x: ?Any) = +public func assertSomeAny(x: ?Any) = switch x { case null { P.unreachable() }; case _ {}; }; -func assertSome(x: ?A) = assertSomeAny(x); +public func assertSome(x: ?A) = assertSomeAny(x); /*** @@ -131,13 +131,13 @@ func assertSome(x: ?A) = assertSomeAny(x); Assert that the given value is `null`; ignore this value and return unit. */ -func assertNullAny(x: ?Any) = +public func assertNullAny(x: ?Any) = switch x { case null { }; case _ { P.unreachable() }; }; -func assertNull(x: ?A) = assertNullAny(x); +public func assertNull(x: ?A) = assertNullAny(x); /*** @@ -147,7 +147,7 @@ func assertNull(x: ?A) = assertNullAny(x); Print an optional integer. */ -func printOpInt(x : ?Int) = +public func printOpInt(x : ?Int) = switch x { case null { print "null" }; case (?x_) { print "?"; printInt x_ }; diff --git a/stdlib/prelude.as b/stdlib/prelude.as index 0d66aed63e1..2588945387c 100644 --- a/stdlib/prelude.as +++ b/stdlib/prelude.as @@ -22,10 +22,10 @@ trap in all execution contexts. */ -func nyi() : None = +public func nyi() : None = { assert false ; loop { } }; -func xxx() : None = +public func xxx() : None = { assert false ; loop { } }; /*** @@ -39,5 +39,5 @@ func xxx() : None = trap in all execution contexts. */ -func unreachable() : None = { assert false ; loop { } }; +public func unreachable() : None = { assert false ; loop { } }; } diff --git a/stdlib/result.as b/stdlib/result.as index 251eed233b1..101fbb249a7 100644 --- a/stdlib/result.as +++ b/stdlib/result.as @@ -1,5 +1,5 @@ module { -private import P "prelude.as"; +import P "prelude.as"; /** @@ -14,7 +14,7 @@ private import P "prelude.as"; */ -type Result = { +public type Result = { #ok:Ok; #err:Err; }; @@ -26,7 +26,7 @@ type Result = { --------------- assert that we can unwrap the result; should only be used in tests, not in canister implementations. This will trap. */ -func assertUnwrap(r:Result):Ok { +public func assertUnwrap(r:Result):Ok { switch(r) { case (#err e) P.unreachable(); case (#ok r) r; @@ -37,7 +37,7 @@ func assertUnwrap(r:Result):Ok { `assertUnwrapAny` --------------- */ -func assertUnwrapAny(r:Result):Ok { +public func assertUnwrapAny(r:Result):Ok { switch(r) { case (#err e) P.unreachable(); case (#ok r) r; @@ -48,7 +48,7 @@ func assertUnwrapAny(r:Result):Ok { `assertOk` --------------- */ -func assertOk(r:Result) { +public func assertOk(r:Result) { switch(r) { case (#err _) assert false; case (#ok _) (); @@ -59,7 +59,7 @@ func assertOk(r:Result) { `assertErr` --------------- */ -func assertErr(r:Result) { +public func assertErr(r:Result) { switch(r) { case (#err _) (); case (#ok _) assert false; @@ -70,14 +70,14 @@ func assertErr(r:Result) { `assertErrIs` --------------- */ -func assertErrIs(r:Result, f:E->Bool) : Bool = +public func assertErrIs(r:Result, f:E->Bool) : Bool = assertErrAs(r, f); /** `assertErrAs` --------------- */ -func assertErrAs(r:Result, f:E->X) : X { +public func assertErrAs(r:Result, f:E->X) : X { switch(r) { case (#err e) f e; case (#ok _) P.unreachable(); @@ -89,7 +89,7 @@ func assertErrAs(r:Result, f:E->X) : X { ------- bind operation in result monad. */ -func bind( +public func bind( x:Result, y:R1 -> Result) : Result { switch x { @@ -104,7 +104,7 @@ func bind( ------- map the `Ok` type/value, leaving any `Error` type/value unchanged. */ -func mapOk( +public func mapOk( x:Result, y:Ok1 -> Ok2) : Result { switch x { @@ -118,7 +118,7 @@ func mapOk( -------------- create a result from an option, including an error value to handle the `null` case. */ -func fromOption(x:?R, err:E):Result { +public func fromOption(x:?R, err:E):Result { switch x { case (? x) {#ok x}; case null {#err err}; @@ -130,7 +130,7 @@ func fromOption(x:?R, err:E):Result { -------------- map the `Ok` type/value from the optional value, or else use the given error value. */ -func fromSomeMap(x:?R1, f:R1->R2, err:E):Result { +public func fromSomeMap(x:?R1, f:R1->R2, err:E):Result { switch x { case (? x) {#ok (f x)}; case null {#err err}; @@ -142,7 +142,7 @@ func fromSomeMap(x:?R1, f:R1->R2, err:E):Result { --------------- asserts that the option is Some(_) form. */ -func fromSome(o:?Ok):Result { +public func fromSome(o:?Ok):Result { switch(o) { case (?o) (#ok o); case _ P.unreachable(); @@ -154,7 +154,7 @@ func fromSome(o:?Ok):Result { --------------- a result that consists of an array of Ok results from an array of results, or the first error in the result array, if any. */ -func joinArrayIfOk(x:[Result]) : Result<[R],E> { +public func joinArrayIfOk(x:[Result]) : Result<[R],E> { /**- return early with the first Err result, if any */ for (i in x.keys()) { switch (x[i]) { diff --git a/stdlib/set.as b/stdlib/set.as index d9aaca6b273..826d6ab5b0b 100644 --- a/stdlib/set.as +++ b/stdlib/set.as @@ -18,32 +18,32 @@ */ module { -private import Trie "trie2.as"; -private import Hash "hash.as"; +import Trie "trie2.as"; +import Hash "hash.as"; -type Hash = Hash.Hash; -type Set = Trie.Trie; +public type Hash = Hash.Hash; +public type Set = Trie.Trie; - func empty():Set = + public func empty():Set = Trie.empty(); - func insert(s:Set, x:T, xh:Hash, eq:(T,T)->Bool) : Set = { + public func insert(s:Set, x:T, xh:Hash, eq:(T,T)->Bool) : Set = { let (s2, _) = Trie.insert(s, new {key=x; hash=xh}, eq, ()); s2 }; - func remove(s:Set, x:T, xh:Hash, eq:(T,T)->Bool) : Set = { + public func remove(s:Set, x:T, xh:Hash, eq:(T,T)->Bool) : Set = { let (s2, _) = Trie.remove(s, new {key=x; hash=xh}, eq); s2 }; - func eq(s1:Set, s2:Set, eq:(T,T)->Bool):Bool { + public func eq(s1:Set, s2:Set, eq:(T,T)->Bool):Bool { // XXX: Todo: use a smarter check Trie.equalStructure(s1, s2, eq, unitEq) }; - func card(s:Set) : Nat { + public func card(s:Set) : Nat { Trie.foldUp (s, func(n:Nat,m:Nat):Nat{n+m}, @@ -51,28 +51,28 @@ type Set = Trie.Trie; 0) }; - func mem(s:Set, x:T, xh:Hash, eq:(T,T)->Bool):Bool { + public func mem(s:Set, x:T, xh:Hash, eq:(T,T)->Bool):Bool { switch (Trie.find(s, new {key=x; hash=xh}, eq)) { case null { false }; case (?_) { true }; } }; - func union(s1:Set, s2:Set, eq:(T,T)->Bool):Set { + public func union(s1:Set, s2:Set, eq:(T,T)->Bool):Set { let s3 = Trie.merge(s1, s2, eq); s3 }; - func diff(s1:Set, s2:Set, eq:(T,T)->Bool):Set { + public func diff(s1:Set, s2:Set, eq:(T,T)->Bool):Set { let s3 = Trie.diff(s1, s2, eq); s3 }; - func intersect(s1:Set, s2:Set, eq:(T,T)->Bool):Set { + public func intersect(s1:Set, s2:Set, eq:(T,T)->Bool):Set { let noop : ((),())->(()) = func (_:(),_:()):(())=(); let s3 = Trie.join(s1, s2, eq, noop); s3 }; - func unitEq (_:(),_:()):Bool{ true }; + public func unitEq (_:(),_:()):Bool{ true }; } diff --git a/stdlib/trie.as b/stdlib/trie.as index 8deba6e2249..f3293e1ba18 100644 --- a/stdlib/trie.as +++ b/stdlib/trie.as @@ -61,20 +61,20 @@ See the full details in the definitions below: */ -private import H "hash.as"; -let Hash = H.BitVec; -type Hash = Hash.t; +import H "hash.as"; +public let Hash = H.BitVec; +public type Hash = Hash.t; -private import List "list.as"; -type List = List.List; +import List "list.as"; +public type List = List.List; -private import AssocList "assocList.as"; -type AssocList = AssocList.AssocList; +import AssocList "assocList.as"; +public type AssocList = AssocList.AssocList; -let HASH_BITS = 4; +public let HASH_BITS = 4; //let HASH_BITS = 16; -type Key = { +public type Key = { // hash field: permits fast inequality checks, permits collisions; // (eventually: permits incremental growth of deeper trie paths) hash: Hash; @@ -83,24 +83,24 @@ type Key = { }; // Binary branch nodes -type Branch = { +public type Branch = { left:Trie; right:Trie; }; // Leaf nodes are association lists of `Key`s where every key // shares a common hash prefix, its (common) trie path. -type Leaf = { +public type Leaf = { keyvals:AssocList,V>; }; // XXX: See AST-42 -type Node = { +public type Node = { left:Trie; right:Trie; keyvals:AssocList,V>; }; -type Trie = ?Node; +public type Trie = ?Node; /** Association lists @@ -116,7 +116,7 @@ type Trie = ?Node; A 2D trie is just a trie that maps dimension-1 keys to another layer of tries, each keyed on the dimension-2 keys. */ -type Trie2D = Trie >; +public type Trie2D = Trie >; /** Three-dimensional trie @@ -124,7 +124,7 @@ type Trie2D = Trie >; A 3D trie is just a trie that maps dimension-1 keys to another layer of 2D tries, each keyed on the dimension-2 and dimension-3 keys. */ -type Trie3D = Trie >; +public type Trie3D = Trie >; /** Module interface @@ -144,7 +144,7 @@ type Trie3D = Trie >; -------- An empty trie. */ - func empty() : Trie = makeEmpty(); + public func empty() : Trie = makeEmpty(); /** `copy` @@ -153,14 +153,14 @@ type Trie3D = Trie >; */ - func copy(t : Trie) : Trie = t; + public func copy(t : Trie) : Trie = t; /** `replace` --------- replace the given key's value option with the given one, returning the previous one */ - func replace(t : Trie, k:Key, k_eq:(K,K)->Bool, v:?V) : (Trie, ?V) { + public func replace(t : Trie, k:Key, k_eq:(K,K)->Bool, v:?V) : (Trie, ?V) { let key_eq = keyEq(k_eq); // For `bitpos` in 0..HASH_BITS, walk the given trie and locate the given value `x`, if it exists. func rec(t : Trie, bitpos:Nat) : (Trie, ?V) { @@ -205,7 +205,7 @@ type Trie3D = Trie >; and only if successful, do the success continuation, otherwise, return the failure value */ - func replaceThen(t : Trie, k:Key, k_eq:(K,K)->Bool, v2:V, + public func replaceThen(t : Trie, k:Key, k_eq:(K,K)->Bool, v2:V, success: (Trie, V) -> X, fail: () -> X) : X @@ -222,7 +222,7 @@ type Trie3D = Trie >; ------------ insert the given key's value in the trie; return the new trie, and the previous value associated with the key, if any */ - func insert(t : Trie, k:Key, k_eq:(K,K)->Bool, v:V) : (Trie, ?V) { + public func insert(t : Trie, k:Key, k_eq:(K,K)->Bool, v:V) : (Trie, ?V) { replace(t, k, k_eq, ?v) }; @@ -231,7 +231,7 @@ type Trie3D = Trie >; ---------------- insert the given key's value in the trie; return the new trie; assert that no prior value is associated with the key */ - func insertFresh(t : Trie, k:Key, k_eq:(K,K)->Bool, v:V) : Trie { + public func insertFresh(t : Trie, k:Key, k_eq:(K,K)->Bool, v:V) : Trie { let (t2, none) = replace(t, k, k_eq, ?v); switch none { case (null) (); @@ -245,7 +245,7 @@ type Trie3D = Trie >; --------------- insert the given key's value in the 2D trie; return the new 2D trie. */ - func insert2D(t : Trie2D, + public func insert2D(t : Trie2D, k1:Key, k1_eq:(K1,K1)->Bool, k2:Key, k2_eq:(K2,K2)->Bool, v:V) @@ -265,7 +265,7 @@ type Trie3D = Trie >; --------------- insert the given key's value in the trie; return the new trie; */ - func insert3D + public func insert3D (t : Trie3D, k1:Key, k1_eq:(K1,K1)->Bool, k2:Key, k2_eq:(K2,K2)->Bool, @@ -300,7 +300,7 @@ type Trie3D = Trie >; ------------- remove the given key's value in the trie; return the new trie */ - func remove(t : Trie, k:Key, k_eq:(K,K)->Bool) : (Trie, ?V) { + public func remove(t : Trie, k:Key, k_eq:(K,K)->Bool) : (Trie, ?V) { replace(t, k, k_eq, null) }; @@ -311,7 +311,7 @@ type Trie3D = Trie >; and only if successful, do the success continuation, otherwise, return the failure value */ - func removeThen(t : Trie, k:Key, k_eq:(K,K)->Bool, + public func removeThen(t : Trie, k:Key, k_eq:(K,K)->Bool, success: (Trie, V) -> X, fail: () -> X) : X @@ -330,7 +330,7 @@ type Trie3D = Trie >; remove the given key-key pair's value in the 2D trie; return the new trie, and the prior value, if any. */ - func remove2D(t : Trie2D, + public func remove2D(t : Trie2D, k1:Key, k1_eq:(K1,K1)->Bool, k2:Key, k2_eq:(K2,K2)->Bool) : (Trie2D, ?V) @@ -355,7 +355,7 @@ type Trie3D = Trie >; remove the given key-key pair's value in the 3D trie; return the new trie, and the prior value, if any. */ - func remove3D + public func remove3D (t : Trie3D, k1:Key, k1_eq:(K1,K1)->Bool, k2:Key, k2_eq:(K2,K2)->Bool, @@ -383,7 +383,7 @@ type Trie3D = Trie >; --------- find the given key's value in the trie, or return null if nonexistent */ - func find(t : Trie, k:Key, k_eq:(K,K) -> Bool) : ?V { + public func find(t : Trie, k:Key, k_eq:(K,K) -> Bool) : ?V { let key_eq = keyEq(k_eq); // For `bitpos` in 0..HASH_BITS, walk the given trie and locate the given value `x`, if it exists. func rec(t : Trie, bitpos:Nat) : ?V { label profile_trie_find_rec : (?V) @@ -434,7 +434,7 @@ type Trie3D = Trie >; - [`prod`](#prod) */ - func merge(tl:Trie, tr:Trie, k_eq:(K,K)->Bool): Trie { + public func merge(tl:Trie, tr:Trie, k_eq:(K,K)->Bool): Trie { let key_eq = keyEq(k_eq); func rec(tl:Trie, tr:Trie) : Trie { switch (tl, tr) { @@ -486,7 +486,7 @@ type Trie3D = Trie >; dynamic error if there are collisions in common keys between the left and right inputs. */ - func mergeDisjoint(tl:Trie, tr:Trie, k_eq:(K,K)->Bool): Trie { + public func mergeDisjoint(tl:Trie, tr:Trie, k_eq:(K,K)->Bool): Trie { let key_eq = keyEq(k_eq); func rec(tl:Trie, tr:Trie) : Trie { switch (tl, tr) { @@ -548,7 +548,7 @@ type Trie3D = Trie >; trie. */ - func mergeDisjoint2D(t : Trie2D, k1_eq:(K1,K1)->Bool, k2_eq:(K2,K2)->Bool) + public func mergeDisjoint2D(t : Trie2D, k1_eq:(K1,K1)->Bool, k2_eq:(K2,K2)->Bool) : Trie { foldUp, Trie> @@ -565,7 +565,7 @@ type Trie3D = Trie >; the left trie whose keys are not present in the right trie; the values of the right trie are irrelevant. */ - func diff(tl:Trie, tr:Trie, k_eq:(K,K)->Bool) : Trie { + public func diff(tl:Trie, tr:Trie, k_eq:(K,K)->Bool) : Trie { let key_eq = keyEq(k_eq); func rec(tl:Trie, tr:Trie) : Trie { switch (tl, tr) { @@ -625,7 +625,7 @@ type Trie3D = Trie >; - [`prod`](#prod) */ - func disj(tl:Trie, tr:Trie, + public func disj(tl:Trie, tr:Trie, k_eq:(K,K)->Bool, vbin:(?V,?W)->X) : Trie { @@ -704,7 +704,7 @@ type Trie3D = Trie >; - [`prod`](#prod) */ - func join(tl:Trie, tr:Trie, + public func join(tl:Trie, tr:Trie, k_eq:(K,K)->Bool, vbin:(V,W)->X) : Trie { @@ -767,7 +767,7 @@ type Trie3D = Trie >; - [`merge`](#merge) */ - func prod( + public func prod( tl :Trie, tr :Trie, op :(K1,V1,K2,V2) -> ?(Key,V3), @@ -806,7 +806,7 @@ type Trie3D = Trie >; either as clients, or as hand-specialized versions (e.g., see map, mapFilter, exists and forAll below). */ - func foldUp(t:Trie, bin:(X,X)->X, leaf:(K,V)->X, empty:X) : X { + public func foldUp(t:Trie, bin:(X,X)->X, leaf:(K,V)->X, empty:X) : X { func rec(t:Trie) : X { switch t { case (null) { empty }; @@ -832,7 +832,7 @@ type Trie3D = Trie >; Fold over the key-value pairs of the trie, using an accumulator. The key-value pairs have no reliable or meaningful ordering. */ - func fold(t:Trie, f:(K,V,X)->X, x:X) : X { + public func fold(t:Trie, f:(K,V,X)->X, x:X) : X { func rec(t:Trie, x:X) : X { switch t { case (null) x; @@ -856,7 +856,7 @@ type Trie3D = Trie >; -------- Test whether a given key-value pair is present, or not. */ - func exists(t:Trie, f:(K,V)->Bool) : Bool { + public func exists(t:Trie, f:(K,V)->Bool) : Bool { func rec(t:Trie) : Bool { switch t { case (null) { false }; @@ -880,7 +880,7 @@ type Trie3D = Trie >; --------- Test whether all key-value pairs have a given property. */ - func forAll(t:Trie, f:(K,V)->Bool) : Bool { + public func forAll(t:Trie, f:(K,V)->Bool) : Bool { func rec(t:Trie) : Bool { switch t { case (null) { true }; @@ -903,7 +903,7 @@ type Trie3D = Trie >; -------- Count the number of entries in the trie. */ - func count(t:Trie):Nat{ + public func count(t:Trie):Nat{ foldUp (t, func(n:Nat,m:Nat):Nat{n+m}, @@ -918,7 +918,7 @@ type Trie3D = Trie >; To do: make this more efficient, using a single array allocation. */ - func toArray(t:Trie,f:(K,V)->[W]):[W] = + public func toArray(t:Trie,f:(K,V)->[W]):[W] = label profile_trie_toArray_begin : [W] { func arrayAppend(x:[W],y:[W]):[W] { label profile_trie_toArray_arrayAppend : [W] @@ -947,7 +947,7 @@ type Trie3D = Trie >; but no leaves. These can result from naive filtering operations; filter uses this function to avoid creating such subtrees. */ - func isEmpty(t:Trie) : Bool { + public func isEmpty(t:Trie) : Bool { func rec(t:Trie) : Bool { switch t { case (null) { true }; @@ -967,7 +967,7 @@ type Trie3D = Trie >; ----------- filter the key-value pairs by a given predicate. */ - func filter(t:Trie, f:(K,V)->Bool) : Trie { + public func filter(t:Trie, f:(K,V)->Bool) : Trie { func rec(t:Trie) : Trie { switch t { case (null) { null }; @@ -1001,7 +1001,7 @@ type Trie3D = Trie >; ----------- map and filter the key-value pairs by a given partial mapping function. */ - func mapFilter(t:Trie, f:(K,V)->?W) : Trie { + public func mapFilter(t:Trie, f:(K,V)->?W) : Trie { func rec(t:Trie) : Trie { switch t { case (null) { null }; @@ -1049,7 +1049,7 @@ type Trie3D = Trie >; `#empty`. We do not observe that equality here. */ - func equalStructure( + public func equalStructure( tl:Trie, tr:Trie, keq:(K,K)->Bool, @@ -1083,7 +1083,7 @@ type Trie3D = Trie >; }; // Equality function for two `Key`s, in terms of equaltiy of `K`'s. - func keyEq(keq:(K,K) -> Bool) : ((Key,Key) -> Bool) = { + public func keyEq(keq:(K,K) -> Bool) : ((Key,Key) -> Bool) = { func (key1:Key, key2:Key) : Bool = label profile_trie_keyEq : Bool (Hash.hashEq(key1.hash, key2.hash) and keq(key1.key, key2.key)) @@ -1097,7 +1097,7 @@ type Trie3D = Trie >; // @Omit: // XXX: until AST-42: - func isNull(x : ?X) : Bool { + public func isNull(x : ?X) : Bool { switch x { case null { true }; case (?_) { false }; @@ -1105,7 +1105,7 @@ type Trie3D = Trie >; }; // XXX: until AST-42: - func assertIsNull(x : ?X) { + public func assertIsNull(x : ?X) { label profile_trie_assertIsNull switch x { case null { assert(true) }; @@ -1114,11 +1114,11 @@ type Trie3D = Trie >; }; // XXX: until AST-42: - func makeEmpty() : Trie + public func makeEmpty() : Trie = null; // XXX: until AST-42: - func assertIsEmpty(t : Trie) { + public func assertIsEmpty(t : Trie) { switch t { case null { assert(true) }; case (?_) { assert(false) }; @@ -1126,12 +1126,12 @@ type Trie3D = Trie >; }; // XXX: until AST-42: - func makeBin(l:Trie, r:Trie) : Trie { + public func makeBin(l:Trie, r:Trie) : Trie { ?(new {left=l; right=r; keyvals=null; }) }; // XXX: until AST-42: - func isBin(t:Trie) : Bool { + public func isBin(t:Trie) : Bool { switch t { case null { false }; case (?t_) { @@ -1144,12 +1144,12 @@ type Trie3D = Trie >; }; // XXX: until AST-42: - func makeLeaf(kvs:AssocList,V>) : Trie { + public func makeLeaf(kvs:AssocList,V>) : Trie { ?(new {left=null; right=null; keyvals=kvs }) }; // XXX: until AST-42: - func matchLeaf(t:Trie) : ?AssocList,V> { + public func matchLeaf(t:Trie) : ?AssocList,V> { switch t { case null { null }; case (?t_) { @@ -1162,7 +1162,7 @@ type Trie3D = Trie >; }; // XXX: until AST-42: - func isLeaf(t:Trie) : Bool { + public func isLeaf(t:Trie) : Bool { switch t { case null { false }; case (?t_) { @@ -1174,7 +1174,7 @@ type Trie3D = Trie >; } }; // XXX: until AST-42: - func assertIsBin(t : Trie) { + public func assertIsBin(t : Trie) { switch t { case null { assert(false) }; case (?n) { @@ -1184,7 +1184,7 @@ type Trie3D = Trie >; }; // XXX: until AST-42: - func getLeafKey(t : Node) : Key { + public func getLeafKey(t : Node) : Key { assertIsNull>(t.left); assertIsNull>(t.right); switch (t.keyvals) { @@ -1194,7 +1194,7 @@ type Trie3D = Trie >; }; // XXX: this helper is an ugly hack; we need real sum types to avoid it, I think: - func getLeafVal(t : Node) : V { + public func getLeafVal(t : Node) : V { assertIsNull>(t.left); assertIsNull>(t.right); switch (t.keyvals) { @@ -1216,7 +1216,7 @@ type Trie3D = Trie >; helper function for constructing new paths of uniform length */ - func buildNewPath(bitpos:Nat, k:Key, ov:?V) : Trie { + public func buildNewPath(bitpos:Nat, k:Key, ov:?V) : Trie { func rec(bitpos:Nat) : Trie { if ( bitpos < HASH_BITS ) { // create new bin node for this bit of the hash diff --git a/stdlib/trie2.as b/stdlib/trie2.as index ac5355f9211..9b69581daf1 100644 --- a/stdlib/trie2.as +++ b/stdlib/trie2.as @@ -69,26 +69,26 @@ Below, we define the types used in the representation: */ //let MAX_LEAF_COUNT = 4; // worse than 8, slightly -let MAX_LEAF_COUNT = 8; // <-- beats both 4 and 16 for me, now +public let MAX_LEAF_COUNT = 8; // <-- beats both 4 and 16 for me, now //let MAX_LEAF_COUNT = 16; //let MAX_LEAF_COUNT = 32; -private import P "prelude.as"; +import P "prelude.as"; -private import Option "option.as"; +import Option "option.as"; -private import H "hash.as"; -let Hash = H.BitVec; -type Hash = Hash.t; +import H "hash.as"; +public let Hash = H.BitVec; +public type Hash = Hash.t; -private import List "list.as"; -type List = List.List; +import List "list.as"; +public type List = List.List; -private import AssocList "assocList.as"; -type AssocList = AssocList.AssocList; +import AssocList "assocList.as"; +public type AssocList = AssocList.AssocList; /** A `Key` for the trie has an associated hash value */ -type Key = { +public type Key = { /** `hash` permits fast inequality checks, and permits collisions */ hash: Hash; /** `key` permits percise equality checks, but only used after equal hashes. */ @@ -96,14 +96,14 @@ type Key = { }; /** Equality function for two `Key`s, in terms of equaltiy of `K`'s. */ -func keyEq(keq:(K,K) -> Bool) : ((Key,Key) -> Bool) = { +public func keyEq(keq:(K,K) -> Bool) : ((Key,Key) -> Bool) = { func (key1:Key, key2:Key) : Bool = label profile_trie_keyEq : Bool (Hash.hashEq(key1.hash, key2.hash) and keq(key1.key, key2.key)) }; /** leaf nodes of trie consist of key-value pairs as a list. */ -type Leaf = { +public type Leaf = { count : Nat ; keyvals : AssocList,V> ; }; @@ -112,20 +112,20 @@ type Leaf = { we never store this bitpos; rather, we enforce a style where this position is always known from context. */ -type Branch = { +public type Branch = { count : Nat ; left : Trie ; right : Trie ; }; /** binary hash tries: either empty, a leaf node, or a branch node */ -type Trie = { +public type Trie = { #empty ; #leaf : Leaf ; #branch : Branch ; }; -func isValid (t:Trie, enforceNormal:Bool) : Bool { +public func isValid (t:Trie, enforceNormal:Bool) : Bool { func rec(t:Trie, bitpos:?Hash, bits:Hash, mask:Hash) : Bool { switch t { case (#empty) { @@ -185,7 +185,7 @@ func isValid (t:Trie, enforceNormal:Bool) : Bool { A 2D trie is just a trie that maps dimension-1 keys to another layer of tries, each keyed on the dimension-2 keys. */ -type Trie2D = Trie >; +public type Trie2D = Trie >; /** Three-dimensional trie @@ -193,7 +193,7 @@ type Trie2D = Trie >; A 3D trie is just a trie that maps dimension-1 keys to another layer of 2D tries, each keyed on the dimension-2 and dimension-3 keys. */ -type Trie3D = Trie >; +public type Trie3D = Trie >; /** Module interface @@ -205,7 +205,7 @@ type Trie3D = Trie >; -------- An empty trie. */ - func empty() : Trie = +public func empty() : Trie = #empty; /** @@ -219,7 +219,7 @@ type Trie3D = Trie >; acceptable level of algorithmic efficiently. */ - func count(t: Trie) : Nat = label profile_trie_count : Nat { +public func count(t: Trie) : Nat = label profile_trie_count : Nat { switch t { case (#empty) 0; case (#leaf l) l.count; @@ -232,7 +232,7 @@ type Trie3D = Trie >; -------- Construct a branch node, computing the count stored there. */ - func branch(l:Trie, r:Trie) : Trie = label profile_trie_branch : Trie { +public func branch(l:Trie, r:Trie) : Trie = label profile_trie_branch : Trie { let sum = count(l) + count(r); #branch( new{ @@ -253,11 +253,11 @@ type Trie3D = Trie >; of the leaf. */ - func leaf(kvs:AssocList,V>, bitpos:Nat) : Trie = label trie_leaf : Trie { +public func leaf(kvs:AssocList,V>, bitpos:Nat) : Trie = label trie_leaf : Trie { fromSizedList(null, kvs, bitpos) }; - func fromList(kvs:AssocList,V>, bitpos:Nat) : Trie = +public func fromList(kvs:AssocList,V>, bitpos:Nat) : Trie = label profile_trie_fromList_begin : (Trie) { func rec(kvs:AssocList,V>, bitpos:Nat) : Trie { if ( List.isNil<(Key,V)>(kvs) ) @@ -284,7 +284,7 @@ type Trie3D = Trie >; }; - func fromSizedList(kvc:?Nat, kvs:AssocList,V>, bitpos:Nat) : Trie = +public func fromSizedList(kvc:?Nat, kvs:AssocList,V>, bitpos:Nat) : Trie = label profile_trie_fromList_begin : (Trie) { func rec(kvc:?Nat, kvs:AssocList,V>, bitpos:Nat) : Trie { switch kvc { @@ -325,14 +325,14 @@ type Trie3D = Trie >; --------- Purely-functional representation permits _O(1)_-time copy, via persistent sharing. */ - func copy(t : Trie) : Trie = t; +public func copy(t : Trie) : Trie = t; /** `replace` --------- replace the given key's value option with the given one, returning the previous one */ - func replace(t : Trie, k:Key, k_eq:(K,K)->Bool, v:?V) : (Trie, ?V) = +public func replace(t : Trie, k:Key, k_eq:(K,K)->Bool, v:?V) : (Trie, ?V) = label profile_trie_replace : (Trie, ?V) { let key_eq = keyEq(k_eq); @@ -372,7 +372,7 @@ type Trie3D = Trie >; ------------ insert the given key's value in the trie; return the new trie, and the previous value associated with the key, if any */ - func insert(t : Trie, k:Key, k_eq:(K,K)->Bool, v:V) : (Trie, ?V) = +public func insert(t : Trie, k:Key, k_eq:(K,K)->Bool, v:V) : (Trie, ?V) = label profile_trie_insert : (Trie, ?V) { replace(t, k, k_eq, ?v) }; @@ -382,7 +382,7 @@ type Trie3D = Trie >; --------- find the given key's value in the trie, or return null if nonexistent */ - func find(t : Trie, k:Key, k_eq:(K,K) -> Bool) : ?V = label profile_trie_find : (?V) { +public func find(t : Trie, k:Key, k_eq:(K,K) -> Bool) : ?V = label profile_trie_find : (?V) { let key_eq = keyEq(k_eq); func rec(t : Trie, bitpos:Nat) : ?V = label profile_trie_find_rec : (?V) { switch t { @@ -413,7 +413,7 @@ type Trie3D = Trie >; - func splitAssocList(al:AssocList,V>, bitpos:Nat) +public func splitAssocList(al:AssocList,V>, bitpos:Nat) : (AssocList,V>, AssocList,V>) = label profile_trie_splitAssocList : (AssocList,V>, AssocList,V>) { @@ -425,7 +425,7 @@ type Trie3D = Trie >; ) }; - func splitSizedList(l:AssocList,V>, bitpos:Nat) +public func splitSizedList(l:AssocList,V>, bitpos:Nat) : (Nat, AssocList,V>, Nat, AssocList,V>) = label profile_trie_splitSizedList : (Nat, AssocList,V>, Nat, AssocList,V>) { @@ -461,7 +461,7 @@ type Trie3D = Trie >; - [`prod`](#prod) */ - func merge(tl:Trie, tr:Trie, k_eq:(K,K)->Bool) : Trie = label profile_trie_merge : Trie { +public func merge(tl:Trie, tr:Trie, k_eq:(K,K)->Bool) : Trie = label profile_trie_merge : Trie { let key_eq = keyEq(k_eq); func br(l:Trie, r:Trie) : Trie = branch(l,r); func rec(bitpos:Nat, tl:Trie, tr:Trie) : Trie { @@ -507,7 +507,7 @@ type Trie3D = Trie >; dynamic error if there are collisions in common keys between the left and right inputs. */ - func mergeDisjoint(tl:Trie, tr:Trie, k_eq:(K,K)->Bool): Trie = +public func mergeDisjoint(tl:Trie, tr:Trie, k_eq:(K,K)->Bool): Trie = label profile_trie_mergeDisjoint : Trie { let key_eq = keyEq(k_eq); func br(l:Trie, r:Trie) : Trie = branch(l,r); @@ -557,7 +557,7 @@ type Trie3D = Trie >; the left trie whose keys are not present in the right trie; the values of the right trie are irrelevant. */ - func diff(tl:Trie, tr:Trie, k_eq:(K,K)->Bool): Trie { +public func diff(tl:Trie, tr:Trie, k_eq:(K,K)->Bool): Trie { let key_eq = keyEq(k_eq); func br1(l:Trie, r:Trie) : Trie = branch(l,r); @@ -618,7 +618,7 @@ type Trie3D = Trie >; - [`prod`](#prod) */ - func disj( +public func disj( tl : Trie, tr : Trie, k_eq : (K,K)->Bool, @@ -702,7 +702,7 @@ type Trie3D = Trie >; - [`prod`](#prod) */ - func join(tl:Trie, tr:Trie, + public func join(tl:Trie, tr:Trie, k_eq:(K,K)->Bool, vbin:(V,W)->X) : Trie = label profile_trie_join : Trie { @@ -749,7 +749,7 @@ type Trie3D = Trie >; either as clients, or as hand-specialized versions (e.g., see map, mapFilter, exists and forAll below). */ - func foldUp(t:Trie, bin:(X,X)->X, leaf:(K,V)->X, empty:X) : X { + public func foldUp(t:Trie, bin:(X,X)->X, leaf:(K,V)->X, empty:X) : X { func rec(t:Trie) : X { switch t { case (#empty) { empty }; @@ -787,7 +787,7 @@ type Trie3D = Trie >; - [`merge`](#merge) */ - func prod( + public func prod( tl :Trie, tr :Trie, op :(K1,V1,K2,V2) -> ?(Key,V3), @@ -839,13 +839,13 @@ type Trie3D = Trie >; own. */ - module Build { + public module Build { /** Commands for building tries. For PL academics: Imagine commands for the IMP imperative language, but where global memory consists of a single (anonymous) global trie */ - type TrieBuild = { + public type TrieBuild = { #skip ; #insert : (K, ?Hash, V) ; #seq : { @@ -855,7 +855,7 @@ type Trie3D = Trie >; } ; }; - func buildCount(tb:TrieBuild) : Nat = + public func buildCount(tb:TrieBuild) : Nat = label profile_trie_buildCount : Nat { switch tb { case (#skip) 0; @@ -864,7 +864,7 @@ type Trie3D = Trie >; } }; - func buildSeq(l:TrieBuild, r:TrieBuild) : TrieBuild = + public func buildSeq(l:TrieBuild, r:TrieBuild) : TrieBuild = label profile_trie_buildSeq : TrieBuild { let sum = buildCount(l) + buildCount(r); #seq(new { count = sum; left = l; right = r }) @@ -883,7 +883,7 @@ type Trie3D = Trie >; - [`prod`](#prod) */ - func prodBuild( + public func prodBuild( tl :Trie, tr :Trie, op :(K1,V1,K2,V2) -> ?(K3,V3), @@ -931,7 +931,7 @@ type Trie3D = Trie >; This position is meaningful only when the build contains multiple uses of one or more keys, otherwise it is not. */ - func buildNth(tb:TrieBuild, i:Nat) : ?(K, ?Hash, V) = label profile_triebuild_nth : (?(K, ?Hash, V)) { + public func buildNth(tb:TrieBuild, i:Nat) : ?(K, ?Hash, V) = label profile_triebuild_nth : (?(K, ?Hash, V)) { func rec(tb:TrieBuild, i:Nat) : ?(K, ?Hash, V) = label profile_triebuild_nth_rec : (?(K, ?Hash, V)) { switch tb { case (#skip) P.unreachable(); @@ -960,7 +960,7 @@ type Trie3D = Trie >; work of actually merging any tries; rather, just record the work for latter (if ever). */ - func projectInnerBuild(t : Trie>) + public func projectInnerBuild(t : Trie>) : TrieBuild { foldUp, TrieBuild> @@ -975,7 +975,7 @@ type Trie3D = Trie >; -------- Gather the collection of key-value pairs into an array of a (possibly-distinct) type. */ - func buildToArray(tb:TrieBuild,f:(K,V)->W):[W] = + public func buildToArray(tb:TrieBuild,f:(K,V)->W):[W] = label profile_triebuild_toArray_begin : [W] { let a = Array_tabulate ( buildCount(tb), @@ -995,7 +995,7 @@ type Trie3D = Trie >; (Same semantics as `buildToArray`, but faster in practice.) */ - func buildToArray2(tb:TrieBuild,f:(K,V)->W):[W] { + public func buildToArray2(tb:TrieBuild,f:(K,V)->W):[W] { let c = buildCount(tb); let a = Array_init(c, null); var i = 0; @@ -1018,7 +1018,7 @@ type Trie3D = Trie >; Fold over the key-value pairs of the trie, using an accumulator. The key-value pairs have no reliable or meaningful ordering. */ - func fold(t:Trie, f:(K,V,X)->X, x:X) : X { + public func fold(t:Trie, f:(K,V,X)->X, x:X) : X { func rec(t:Trie, x:X) : X { switch t { case (#empty) x; @@ -1040,7 +1040,7 @@ type Trie3D = Trie >; -------- Test whether a given key-value pair is present, or not. */ - func exists(t:Trie, f:(K,V)->Bool) : Bool { + public func exists(t:Trie, f:(K,V)->Bool) : Bool { func rec(t:Trie) : Bool { switch t { case (#empty) { false }; @@ -1060,7 +1060,7 @@ type Trie3D = Trie >; --------- Test whether all key-value pairs have a given property. */ - func forAll(t:Trie, f:(K,V)->Bool) : Bool { + public func forAll(t:Trie, f:(K,V)->Bool) : Bool { func rec(t:Trie) : Bool { switch t { case (#empty) { true }; @@ -1084,7 +1084,7 @@ type Trie3D = Trie >; can inject tries into arrays given the Array_tabulate interface for doing so. */ - func nth(t:Trie, i:Nat) : ?(Key, V) = label profile_trie_nth : (?(Key, V)) { + public func nth(t:Trie, i:Nat) : ?(Key, V) = label profile_trie_nth : (?(Key, V)) { func rec(t:Trie, i:Nat) : ?(Key, V) = label profile_trie_nth_rec : (?(Key, V)) { switch t { case (#empty) P.unreachable(); @@ -1130,7 +1130,7 @@ type Trie3D = Trie >; the type W (e.g., the existence of "default values"), we settle for using `nth`. */ - func toArray(t:Trie,f:(K,V)->W):[W] = + public func toArray(t:Trie,f:(K,V)->W):[W] = label profile_trie_toArray_begin : [W] { let a = Array_tabulate ( count(t), @@ -1151,7 +1151,7 @@ type Trie3D = Trie >; but no leaves. These can result from naive filtering operations; filter uses this function to avoid creating such subtrees. */ - func isEmpty(t:Trie) : Bool = + public func isEmpty(t:Trie) : Bool = count(t) == 0; /** @@ -1159,7 +1159,7 @@ type Trie3D = Trie >; ----------- filter the key-value pairs by a given predicate. */ - func filter(t:Trie, f:(K,V)->Bool) : Trie { + public func filter(t:Trie, f:(K,V)->Bool) : Trie { func rec(t:Trie, bitpos:Nat) : Trie { switch t { case (#empty) { #empty }; @@ -1193,7 +1193,7 @@ type Trie3D = Trie >; ----------- map and filter the key-value pairs by a given predicate. */ - func mapFilter(t:Trie, f:(K,V)->?W) : Trie { + public func mapFilter(t:Trie, f:(K,V)->?W) : Trie { func rec(t:Trie, bitpos:Nat) : Trie { switch t { case (#empty) { #empty }; @@ -1239,7 +1239,7 @@ type Trie3D = Trie >; `#empty`. We do not observe that equality here. */ - func equalStructure( + public func equalStructure( tl:Trie, tr:Trie, keq:(K,K)->Bool, @@ -1271,7 +1271,7 @@ type Trie3D = Trie >; and only if successful, do the success continuation, otherwise, return the failure value */ - func replaceThen(t : Trie, k:Key, k_eq:(K,K)->Bool, v2:V, + public func replaceThen(t : Trie, k:Key, k_eq:(K,K)->Bool, v2:V, success: (Trie, V) -> X, fail: () -> X) : X @@ -1288,7 +1288,7 @@ type Trie3D = Trie >; ---------------- insert the given key's value in the trie; return the new trie; assert that no prior value is associated with the key */ - func insertFresh(t : Trie, k:Key, k_eq:(K,K)->Bool, v:V) : Trie { + public func insertFresh(t : Trie, k:Key, k_eq:(K,K)->Bool, v:V) : Trie { let (t2, none) = replace(t, k, k_eq, ?v); switch none { case (null) (); @@ -1302,7 +1302,7 @@ type Trie3D = Trie >; --------------- insert the given key's value in the 2D trie; return the new 2D trie. */ - func insert2D(t : Trie2D, + public func insert2D(t : Trie2D, k1:Key, k1_eq:(K1,K1)->Bool, k2:Key, k2_eq:(K2,K2)->Bool, v:V) @@ -1322,7 +1322,7 @@ type Trie3D = Trie >; --------------- insert the given key's value in the trie; return the new trie; */ - func insert3D + public func insert3D (t : Trie3D, k1:Key, k1_eq:(K1,K1)->Bool, k2:Key, k2_eq:(K2,K2)->Bool, @@ -1357,7 +1357,7 @@ type Trie3D = Trie >; ------------- remove the given key's value in the trie; return the new trie */ - func remove(t : Trie, k:Key, k_eq:(K,K)->Bool) : (Trie, ?V) { + public func remove(t : Trie, k:Key, k_eq:(K,K)->Bool) : (Trie, ?V) { replace(t, k, k_eq, null) }; @@ -1368,7 +1368,7 @@ type Trie3D = Trie >; and only if successful, do the success continuation, otherwise, return the failure value */ - func removeThen(t : Trie, k:Key, k_eq:(K,K)->Bool, + public func removeThen(t : Trie, k:Key, k_eq:(K,K)->Bool, success: (Trie, V) -> X, fail: () -> X) : X @@ -1387,7 +1387,7 @@ type Trie3D = Trie >; remove the given key-key pair's value in the 2D trie; return the new trie, and the prior value, if any. */ - func remove2D(t : Trie2D, + public func remove2D(t : Trie2D, k1:Key, k1_eq:(K1,K1)->Bool, k2:Key, k2_eq:(K2,K2)->Bool) : (Trie2D, ?V) @@ -1412,7 +1412,7 @@ type Trie3D = Trie >; remove the given key-key pair's value in the 3D trie; return the new trie, and the prior value, if any. */ - func remove3D + public func remove3D (t : Trie3D, k1:Key, k1_eq:(K1,K1)->Bool, k2:Key, k2_eq:(K2,K2)->Bool, @@ -1445,7 +1445,7 @@ type Trie3D = Trie >; trie. */ - func mergeDisjoint2D(t : Trie2D, k1_eq:(K1,K1)->Bool, k2_eq:(K2,K2)->Bool) + public func mergeDisjoint2D(t : Trie2D, k1_eq:(K1,K1)->Bool, k2_eq:(K2,K2)->Bool) : Trie { foldUp, Trie> diff --git a/test/fail/actor-match.as b/test/fail/actor-match.as index c647921fe1e..3a00e3f59e7 100644 --- a/test/fail/actor-match.as +++ b/test/fail/actor-match.as @@ -1,10 +1,10 @@ let a : actor {f : () -> (); g : () -> ()} = actor { - f () {}; - g () {} + public func f() {}; + public func g() {} }; -func foo () = switch a { +func foo() = switch a { case {f; g} { f() } }; -assert ((switch (foo()) { case () 0 }) == 0) \ No newline at end of file +assert ((switch (foo()) { case () 0 }) == 0) diff --git a/test/fail/actor-reexport.as b/test/fail/actor-reexport.as index c928d553b44..27cd31e0176 100644 --- a/test/fail/actor-reexport.as +++ b/test/fail/actor-reexport.as @@ -1,13 +1,13 @@ actor test { - exported() { + public func exported() { print("exported()\n"); }; - let exported_too = exported; + public let exported_too = exported; }; actor test2 { - let exported_three = test.exported_too; - let (exported_four, exported_five) = + public let exported_three = test.exported_too; + public let (exported_four, exported_five) = if (true) (test.exported_too, test.exported_too) else diff --git a/test/fail/ast81-clash.as b/test/fail/ast81-clash.as index fafa57fd7cb..bf6098ad920 100644 --- a/test/fail/ast81-clash.as +++ b/test/fail/ast81-clash.as @@ -1,7 +1,7 @@ func foo() { }; // <-- removing this definition avoids the compiler exception actor class Test() = this { // <-- removing this stuff around the inner block avoids compiler exception - go() { + public func go() { ignore(async { let x = 123; diff --git a/test/fail/await-in-actor.as b/test/fail/await-in-actor.as index 41b3b1c2edc..7163f079ee4 100644 --- a/test/fail/await-in-actor.as +++ b/test/fail/await-in-actor.as @@ -1,7 +1,7 @@ let _ = async { let a = actor { - private x = await { async 1 }; - getX() : async Nat { x }; + let x = await { async 1 }; + public func getX() : async Nat { x }; }; () } diff --git a/test/fail/const-var-field.as b/test/fail/const-var-field.as index f6db662c711..e57ff4b772d 100644 --- a/test/fail/const-var-field.as +++ b/test/fail/const-var-field.as @@ -1 +1 @@ -let o : {x : Nat} = new {var x = 0}; +let o : {x : Nat} = object { public var x = 0 }; diff --git a/test/fail/duplicate-field.as b/test/fail/duplicate-field.as index 1e9dff1b781..66db44941ee 100644 --- a/test/fail/duplicate-field.as +++ b/test/fail/duplicate-field.as @@ -1,5 +1,5 @@ actor class C() { - m() {}; - n() {}; - m() {}; // Illegal! + public func m() {}; + public func n() {}; + public func m() {}; // Illegal! }; diff --git a/test/fail/issue103.as b/test/fail/issue103.as index 2b60aa7d48c..b7485f5f1bb 100644 --- a/test/fail/issue103.as +++ b/test/fail/issue103.as @@ -8,7 +8,7 @@ // An object with function fields is not sharable { func invalid2 (f : shared {foo : () -> Nat} -> ()) { - f (new { foo() : Nat = 1; }) + f (object { public func foo() : Nat = 1; }) }; }; @@ -22,6 +22,6 @@ // Cannot return an object with function fields in an async { func invalid4 () : (async ({foo : () -> Nat})) { - async { new { foo() : Nat = 1; } } + async { object { public func foo() : Nat = 1; } } }; }; diff --git a/test/fail/modexp1.as b/test/fail/modexp1.as index 2afd6b85fea..c716c9ca07d 100644 --- a/test/fail/modexp1.as +++ b/test/fail/modexp1.as @@ -1,7 +1,7 @@ module X = { - func f() { g();}; - private func g() { f();}; + public func f() { g();}; + func g() { f();}; }; let ok = X.f; diff --git a/test/fail/modexp2.as b/test/fail/modexp2.as index 98bdf61044a..230a57b7b0d 100644 --- a/test/fail/modexp2.as +++ b/test/fail/modexp2.as @@ -1,10 +1,10 @@ module X = { - func f() { g();}; - private func g() { f();}; - private let y : Nat = 2; - private type U = Int; - type T = U; + public func f() { g();}; + func g() { f();}; + let y : Nat = 2; + type U = Int; + public type T = U; }; type Ok = X.T; diff --git a/test/fail/modexp3.as b/test/fail/modexp3.as index 7e3fdc0d28e..68c92ba05b4 100644 --- a/test/fail/modexp3.as +++ b/test/fail/modexp3.as @@ -1,7 +1,7 @@ module X = { - func f() { g();}; - private func g() { f();}; - private type U = U -> U; - type T = U; // bad public field because U private and unavoidable - func h():T { h() }; // ditto + public func f() { g();}; + func g() { f();}; + type U = U -> U; + public type T = U; // bad public field because U private and unavoidable + public func h():T { h() }; // ditto }; diff --git a/test/fail/modexp4.as b/test/fail/modexp4.as index d3d40e032e8..84eeea22a88 100644 --- a/test/fail/modexp4.as +++ b/test/fail/modexp4.as @@ -1,12 +1,12 @@ module X = { - func f() { g();}; - private func g() { f();}; - private module Y = { - type U = U -> U; + public func f() { g();}; + func g() { f();}; + module Y = { + public type U = U -> U; }; - type T = Y.U; // bad public field because Y.U private and unavoidable - func h():T { h() }; // ditto + public type T = Y.U; // bad public field because Y.U private and unavoidable + public func h():T { h() }; // ditto }; diff --git a/test/fail/modules-fwd.as b/test/fail/modules-fwd.as index c21da7394b8..dfcbc5976dc 100644 --- a/test/fail/modules-fwd.as +++ b/test/fail/modules-fwd.as @@ -5,10 +5,10 @@ let C = A.B; let u = C.v; module A = { - module B = { - type T = (); - let v = (); + public module B = { + public type T = (); + public let v = (); }; }; -}; \ No newline at end of file +}; diff --git a/test/fail/modules-shadow.as b/test/fail/modules-shadow.as index 9d701405ae1..872caff1ddd 100644 --- a/test/fail/modules-shadow.as +++ b/test/fail/modules-shadow.as @@ -1,7 +1,6 @@ -module X = { type t = Int }; +object X { public type t = Int }; -module Y = { +object Y { let X = 1; type t = X.t }; - diff --git a/test/fail/nested-class-rec-fail.as b/test/fail/nested-class-rec-fail.as index 5dbcfb85677..af9e647f28a 100644 --- a/test/fail/nested-class-rec-fail.as +++ b/test/fail/nested-class-rec-fail.as @@ -1,10 +1,8 @@ -class Foo(f1:Int -> Int, f2:Int -> Int) { }; +class Foo(f1 : Int -> Int, f2 : Int -> Int) {}; -class Bar () { - - private g(n:Int) : Int = n + 1; - - let Bar = Foo(g, g) /*: Foo */; // annotation needed to typecheck constructor call +class Bar() { + func g(n:Int) : Int = n + 1; + let foo = Foo(g, g); }; diff --git a/test/fail/object-patterns.as b/test/fail/object-patterns.as index 90c3496c3e1..2db0aeca32e 100644 --- a/test/fail/object-patterns.as +++ b/test/fail/object-patterns.as @@ -1,16 +1,14 @@ - -// subtyping in patterns +// Subtyping in patterns let q : {a : Int; b : Nat} = new {a = -42; b = 25}; func get_a () : Int = switch (q) { case {a = 25 : Nat} 1; // NOT OK: Nat cannot consume all Ints case {a = 42; b} b; // OK: 42 is Int by subtyping - case - {a = a : Int; - b = 25 : Int} a; // OK: Int can consume all Nats + case {a = a : Int; b = 25 : Int} a; // OK: Int can consume all Nats }; + // the above is analogous to the simpler: func (a : Int) = switch a { diff --git a/test/fail/objpat-duplicate.as b/test/fail/objpat-duplicate.as index 2310218182e..e31294bbd9f 100644 --- a/test/fail/objpat-duplicate.as +++ b/test/fail/objpat-duplicate.as @@ -1,4 +1,4 @@ -object o {a = 1; b = 2}; +let o = new {a = 1; b = 2}; switch o { case {a = x; b; a} {} diff --git a/test/fail/objpat-infer.as b/test/fail/objpat-infer.as index 0669afe2e17..9073e468939 100644 --- a/test/fail/objpat-infer.as +++ b/test/fail/objpat-infer.as @@ -20,7 +20,7 @@ ignore (foo (new {})); ignore (foo (object {})); ignore (foo (actor {})); -let a = actor { bar ({}) : async Nat = async 25 }; +let a = actor { public func bar ({}) : async Nat = async 25 }; ignore (foo a); diff --git a/test/fail/ok/actor-reexport.tc.ok b/test/fail/ok/actor-reexport.tc.ok index 084ef0f2bdb..b677a38239d 100644 --- a/test/fail/ok/actor-reexport.tc.ok +++ b/test/fail/ok/actor-reexport.tc.ok @@ -1,3 +1,3 @@ -actor-reexport.as:5.3-5.30: type error, public actor field needs to be a manifest function -actor-reexport.as:9.3-9.41: type error, public actor field needs to be a manifest function -actor-reexport.as:10.3-14.39: type error, public actor field needs to be a manifest function +actor-reexport.as:5.10-5.37: type error, public actor field needs to be a manifest function +actor-reexport.as:9.10-9.48: type error, public actor field needs to be a manifest function +actor-reexport.as:10.10-14.39: type error, public actor field needs to be a manifest function diff --git a/test/fail/ok/await-in-actor.tc.ok b/test/fail/ok/await-in-actor.tc.ok index fe8cedf4c75..f597d1e26dd 100644 --- a/test/fail/ok/await-in-actor.tc.ok +++ b/test/fail/ok/await-in-actor.tc.ok @@ -1 +1 @@ -await-in-actor.as:3.17-3.34: type error, misplaced await +await-in-actor.as:3.13-3.30: type error, misplaced await diff --git a/test/fail/ok/const-var-field.tc.ok b/test/fail/ok/const-var-field.tc.ok index 150f905dc97..980dbf67a3b 100644 --- a/test/fail/ok/const-var-field.tc.ok +++ b/test/fail/ok/const-var-field.tc.ok @@ -1,4 +1,4 @@ -const-var-field.as:1.21-1.36: type error, expression of type +const-var-field.as:1.21-1.48: type error, expression of type {x : var Nat} cannot produce expected type {x : Nat} diff --git a/test/fail/ok/duplicate-field.tc.ok b/test/fail/ok/duplicate-field.tc.ok index b58039f0247..5c8099b99da 100644 --- a/test/fail/ok/duplicate-field.tc.ok +++ b/test/fail/ok/duplicate-field.tc.ok @@ -1 +1 @@ -duplicate-field.as:4.3-4.4: type error, duplicate definition for m in block +duplicate-field.as:4.15-4.16: type error, duplicate definition for m in block diff --git a/test/fail/ok/nested-class-rec-fail.tc.ok b/test/fail/ok/nested-class-rec-fail.tc.ok index 6e4d5470dd3..1471fa653f8 100644 --- a/test/fail/ok/nested-class-rec-fail.tc.ok +++ b/test/fail/ok/nested-class-rec-fail.tc.ok @@ -1 +1 @@ -nested-class-rec-fail.as:8.13-8.16: type error, cannot infer type of forward variable Foo +nested-class-rec-fail.as:7.13-7.16: type error, cannot infer type of forward variable Foo diff --git a/test/fail/ok/object-patterns.tc.ok b/test/fail/ok/object-patterns.tc.ok index ce5874191ea..9ae9b148c88 100644 --- a/test/fail/ok/object-patterns.tc.ok +++ b/test/fail/ok/object-patterns.tc.ok @@ -1,8 +1,8 @@ -object-patterns.as:7.13-7.21: type error, pattern of type +object-patterns.as:6.13-6.21: type error, pattern of type Nat cannot consume expected type Int -object-patterns.as:19.9-19.16: type error, pattern of type +object-patterns.as:17.9-17.16: type error, pattern of type Nat cannot consume expected type Int diff --git a/test/fail/ok/use-before-define6.tc.ok b/test/fail/ok/use-before-define6.tc.ok index 5dc75f76f19..bba698b0347 100644 --- a/test/fail/ok/use-before-define6.tc.ok +++ b/test/fail/ok/use-before-define6.tc.ok @@ -1 +1 @@ -use-before-define6.as:9.3-9.22: definedness error, cannot use g before g has been defined +use-before-define6.as:6.3-6.20: definedness error, cannot use g before g has been defined diff --git a/test/fail/use-before-define5.as b/test/fail/use-before-define5.as index 7fc81febdca..939bd17211e 100644 --- a/test/fail/use-before-define5.as +++ b/test/fail/use-before-define5.as @@ -1,3 +1,3 @@ // A closing actor needs to eagerly get the values -let a = actor { foo() : () { assert (x == 1) } }; +let a = actor { public func foo() : () { assert (x == 1) } }; let x = 1; diff --git a/test/fail/use-before-define6.as b/test/fail/use-before-define6.as index 998c54af626..7e42ffa50bc 100644 --- a/test/fail/use-before-define6.as +++ b/test/fail/use-before-define6.as @@ -1,15 +1,11 @@ - - class Bar () { - - private class Foo(f1:Int -> Int, f2:Int -> Int) { - private bomb = f1(666) + f2(666); + class Foo(f1 : Int -> Int, f2 : Int -> Int) { + let bomb = f1(666) + f2(666); }; - var Bar = Foo(g, g); - - private g(n:Int) : Int = n + 1; + let _ = Foo(g, g); + func g(n : Int) : Int = n + 1; }; -let _ = Bar(); \ No newline at end of file +let _ = Bar(); diff --git a/test/run-dfinity/AST-64.as b/test/run-dfinity/AST-64.as index 5c1685cf14d..cf83b84b2c7 100644 --- a/test/run-dfinity/AST-64.as +++ b/test/run-dfinity/AST-64.as @@ -6,11 +6,11 @@ let _ = (object this {}) : Any; let _ = (object {}) : Any; -let _ = (actor this { func x(){ this.x(); }; }) : Any; -let _ = (actor { func x(){x();}; }) : Any; +let _ = (actor this { public func x() { this.x() } }) : Any; +let _ = (actor { public func x() { x() } }) : Any; -let _ = (object this { func x(){ this.x(); }; }) : Any; -let _ = (object { func x(){x();}; }) : Any; +let _ = (object this { public func x() { this.x() } }) : Any; +let _ = (object { public func x() { x() } }) : Any; diff --git a/test/run-dfinity/async-new-obj.as b/test/run-dfinity/async-new-obj.as index 43e71a001c6..339009c0a7f 100644 --- a/test/run-dfinity/async-new-obj.as +++ b/test/run-dfinity/async-new-obj.as @@ -1,61 +1,69 @@ -/* test asynchronous construction of an object */ +/* Test asynchronous construction of an object */ + let a = async { - let o = new {private a = "aa" ; - private b = "ab"; - get_a():Text {a;}; - get_b():Text {b;};}; - let (a,b) = (o.get_a(),o.get_b()); - print a; - print b; - print "\n"; + let o = object { + let a = "aa"; + let b = "ab"; + public func get_a() : Text { a }; + public func get_b() : Text { b }; + }; + let (a, b) = (o.get_a(), o.get_b()); + print a; + print b; + print "\n"; }; let b = async { - let o = new {private a = await (async "ba") ; - private b = "bb"; - get_a():Text {a;}; - get_b():Text {b;};}; - let (a,b) = (o.get_a(),o.get_b()); - print a; - print b; - print "\n"; + let o = object { + let a = await (async "ba") ; + let b = "bb"; + public func get_a() : Text { a }; + public func get_b() : Text { b }; + }; + let (a, b) = (o.get_a(), o.get_b()); + print a; + print b; + print "\n"; }; let c = async { - let o = new {private a = await (async "ca") ; - private b = await (async "cb"); - get_a():Text {a;}; - get_b():Text {b;};}; - let (a,b) = (o.get_a(),o.get_b()); - print a; - print b; - print "\n"; + let o = object { + let a = await (async "ca") ; + let b = await (async "cb"); + public func get_a() : Text { a }; + public func get_b() : Text { b }; + }; + let (a, b) = (o.get_a(), o.get_b()); + print a; + print b; + print "\n"; }; let d = async { - let o = new {private a = "da"; - private b = await (async "db"); - get_a(): Text {a;}; - get_b(): Text {b;};}; - let (a,b) = (o.get_a(),o.get_b()); - print a; - print b; - print "\n"; + let o = object { + let a = "da"; + let b = await (async "db"); + public func get_a() : Text { a }; + public func get_b() : Text { b }; + }; + let (a, b) = (o.get_a(), o.get_b()); + print a; + print b; + print "\n"; }; - let e = async { - let o = new this { - private a = "ea"; - private b = await (async "eb"); - get_a() : Text {a;}; - get_b(): Text {b;}; - get_ab():(Text,Text) { - (this.get_a(), this.get_b()); - }; - }; - let (a,b) = o.get_ab(); - print a; - print b; - print "\n"; + let o = object this { + let a = "ea"; + let b = await (async "eb"); + public func get_a() : Text { a }; + public func get_b() : Text { b }; + public func get_ab() : (Text, Text) { + (this.get_a(), this.get_b()); + }; + }; + let (a, b) = o.get_ab(); + print a; + print b; + print "\n"; }; diff --git a/test/run-dfinity/async-obj-mut.as b/test/run-dfinity/async-obj-mut.as index afcf5733f86..2f7f2d18708 100644 --- a/test/run-dfinity/async-obj-mut.as +++ b/test/run-dfinity/async-obj-mut.as @@ -1,13 +1,13 @@ let _ = async { - let o = new { - var x = await { async { 1 } }; - private a = printInt(x); + let o = object { + public var x = await { async { 1 } }; + let a = printInt(x); // private b = (x := await { async (x + 1) }); - private b = (x := x + 1); - private c = printInt(x); - foo() = { x := x + 1 }; - private e = foo(); - private f = printInt(x); + let b = (x := x + 1); + let c = printInt(x); + public func foo() = { x := x + 1 }; + let e = foo(); + let f = printInt(x); }; print("\ndone creating\n"); printInt(o.x); diff --git a/test/run-dfinity/chat.as b/test/run-dfinity/chat.as index fff4508e784..2f565f57724 100644 --- a/test/run-dfinity/chat.as +++ b/test/run-dfinity/chat.as @@ -3,9 +3,9 @@ type List = ?{head : T; var tail : List}; type Post = shared Text -> (); actor class Server() = { - private var clients : List = null; + var clients : List = null; - private shared broadcast(message : Text) { + shared func broadcast(message : Text) { var next = clients; loop { switch next { @@ -18,7 +18,7 @@ actor class Server() = { }; }; - subscribe(client : Client) : async Post { + public func subscribe(client : Client) : async Post { let cs = new {head = client; var tail = clients}; clients := ?cs; return broadcast; @@ -28,10 +28,10 @@ actor class Server() = { actor class Client() = this { // TODO: these should be constructor params once we can compile them - private var name : Text = ""; - private var server : ?Server = null; + var name : Text = ""; + var server : ?Server = null; - go(n : Text, s : Server) { + public func go(n : Text, s : Server) { name := n; server := ?s; ignore(async { @@ -41,7 +41,7 @@ actor class Client() = this { }); }; - send(msg : Text) { + public func send(msg : Text) { print(name # " received " # msg # "\n"); }; }; diff --git a/test/run-dfinity/chatpp.as b/test/run-dfinity/chatpp.as index f107bd3468d..cbedc2115b6 100644 --- a/test/run-dfinity/chatpp.as +++ b/test/run-dfinity/chatpp.as @@ -12,10 +12,10 @@ type ClientData = { }; actor class Server() = { - private var nextId : Nat = 0; - private var clients : List = null; + var nextId : Nat = 0; + var clients : List = null; - private broadcast(id : Nat, message : Text) { + func broadcast(id : Nat, message : Text) { var next = clients; label sends loop { switch next { @@ -28,20 +28,20 @@ actor class Server() = { }; }; - subscribe(aclient : Client) : async Subscription { + public func subscribe(aclient : Client) : async Subscription { let c = new {id = nextId; client = aclient; var revoked = false}; nextId += 1; let cs = new {head = c; var tail = clients}; clients := ?cs; - return (new { - post = shared func(message : Text) { + return object { + public shared func post(message : Text) { if (not c.revoked) broadcast(c.id, message); }; - cancel = shared func() { unsubscribe(c.id) }; - }); + public shared func cancel() { unsubscribe(c.id) }; + }; }; - private unsubscribe(id : Nat) { + func unsubscribe(id : Nat) { var prev : List = null; var next = clients; loop { @@ -66,10 +66,10 @@ actor class Server() = { actor class Client() = this { // TODO: these should be constructor params once we can compile them - private var name : Text = ""; - private var server : ?Server = null; + var name : Text = ""; + var server : ?Server = null; - go(n : Text, s : Server) { + public func go(n : Text, s : Server) { name := n; server := ?s; ignore(async { @@ -80,7 +80,7 @@ actor class Client() = this { }) }; - send(msg : Text) { + public func send(msg : Text) { print(name # " received " # msg # "\n"); }; }; diff --git a/test/run-dfinity/closure-params.as b/test/run-dfinity/closure-params.as index 86630872dae..4f7c66e77f4 100644 --- a/test/run-dfinity/closure-params.as +++ b/test/run-dfinity/closure-params.as @@ -1,11 +1,11 @@ let a = actor { - private var c = 0; - incn(n : Nat) : () { + var c = 0; + public func incn(n : Nat) : () { c += n; printInt(c); print("\n"); }; - readCounter(f : shared Nat -> ()) : () { + public func readCounter(f : shared Nat -> ()) : () { f(c); }; }; diff --git a/test/run-dfinity/counter-class.as b/test/run-dfinity/counter-class.as index 62322bc3f65..711ec097d54 100644 --- a/test/run-dfinity/counter-class.as +++ b/test/run-dfinity/counter-class.as @@ -1,12 +1,12 @@ actor class Counter(i : Int) { - private var j = i; + var j = i; - dec() { + public func dec() { showCounter(j); j -= 1; }; - read() : async Int { j }; + public func read() : async Int { j }; }; func showCounter(c : Int) {}; diff --git a/test/run-dfinity/counter.as b/test/run-dfinity/counter.as index 7669b032fcc..e99d656ef79 100644 --- a/test/run-dfinity/counter.as +++ b/test/run-dfinity/counter.as @@ -1,10 +1,10 @@ let a = actor { - private var c = 1; - inc() { + var c = 1; + public func inc() { c += 1; printInt c; print "\n"; }; - printCounter () { + public func printCounter () { printInt c; print "\n"; } }; diff --git a/test/run-dfinity/counter2.as b/test/run-dfinity/counter2.as index d7a24c60069..303e4122e4c 100644 --- a/test/run-dfinity/counter2.as +++ b/test/run-dfinity/counter2.as @@ -1,10 +1,10 @@ actor { - private var c = 1; - inc() { + var c = 1; + public func inc() { c += 1; printInt c; print "\n"; }; - printCounter () { + public func printCounter () { printInt c; print "\n"; } } diff --git a/test/run-dfinity/data-params.as b/test/run-dfinity/data-params.as index be0da0b8757..c0f0036d724 100644 --- a/test/run-dfinity/data-params.as +++ b/test/run-dfinity/data-params.as @@ -1,31 +1,31 @@ let a = actor { - private var c : Int = 0; - inci(n : Int) : () { + var c : Int = 0; + public func inci(n : Int) : () { c += n; printInt(c); print("\n"); }; - incn(n : Nat) : () { + public func incn(n : Nat) : () { c += n; printInt(c); print("\n"); }; - incnn(n1 : Nat, n2 : Nat) : () { + public func incnn(n1 : Nat, n2 : Nat) : () { c += n1 + n2; printInt(c); print("\n"); }; - incnested(n1 : Nat, (n2 : Nat, n3 : Nat)) : () { + public func incnested(n1 : Nat, (n2 : Nat, n3 : Nat)) : () { c += n1 + n2 + n3; printInt(c); print("\n"); }; - incarray(a : [Nat]) : () { + public func incarray(a : [Nat]) : () { for (i in a.vals()) { c += i }; printInt(c); print("\n"); }; - incopt(a : ?Nat) : () { + public func incopt(a : ?Nat) : () { switch a { case null { c += 1000000 }; case (?a) { c += a }; @@ -33,13 +33,13 @@ let a = actor { printInt(c); print("\n"); }; - increcord(a : { x : Nat; y : Nat }) : () { + public func increcord(a : { x : Nat; y : Nat }) : () { c += a.x; c += a.y; printInt(c); print("\n"); }; - incVariant(v : { #foo : Nat; #bar : Nat }) { + public func incVariant(v : { #foo : Nat; #bar : Nat }) { c += (switch v { case (#foo n) n; case (#bar n) n; @@ -47,21 +47,21 @@ let a = actor { printInt(c); print("\n"); }; - printCounter() { + public func printCounter() { printInt(c); print("\n"); }; - printLabeled(l:Text) { + public func printLabeled(l:Text) { print l; printInt(c); print("\n"); }; - printLabeledOpt(?l:?Text) { + public func printLabeledOpt(?l:?Text) { print l; printInt(c); print("\n"); }; - incwords(w8 : Word8, w16 : Word16, w32 : Word32, w64 : Word64) : () { + public func incwords(w8 : Word8, w16 : Word16, w32 : Word32, w64 : Word64) : () { c += word8ToInt(w8); c += word16ToInt(w16); c += word32ToInt(w32); @@ -69,7 +69,7 @@ let a = actor { printInt(c); print("\n"); }; - incnats(n8 : Nat8, n16 : Nat16, n32 : Nat32, n64 : Nat64) : () { + public func incnats(n8 : Nat8, n16 : Nat16, n32 : Nat32, n64 : Nat64) : () { c += nat8ToNat(n8); c += nat16ToNat(n16); c += nat32ToNat(n32); @@ -77,7 +77,7 @@ let a = actor { printInt(c); print("\n"); }; - incints(i8 : Int8, i16 : Int16, i32 : Int32, i64 : Int64) : () { + public func incints(i8 : Int8, i16 : Int16, i32 : Int32, i64 : Int64) : () { c += int8ToInt(i8); c += int16ToInt(i16); c += int32ToInt(i32); diff --git a/test/run-dfinity/flatten-awaitables.as b/test/run-dfinity/flatten-awaitables.as index a23f034c7e4..72184de029b 100644 --- a/test/run-dfinity/flatten-awaitables.as +++ b/test/run-dfinity/flatten-awaitables.as @@ -1,33 +1,33 @@ // test flattening of awaitable, shared function arguments let a = actor { - m0():async() {}; - m1(x:Int):async Int {return x;}; - m2(x:Int,y:Bool):async(Int,Bool) {return (x,y);}; - m3(x:Int,y:Bool,z:Text):async(Int,Bool,Text) {return (x,y,z);}; + public func m0():async() {}; + public func m1(x:Int):async Int {return x;}; + public func m2(x:Int,y:Bool):async(Int,Bool) {return (x,y);}; + public func m3(x:Int,y:Bool,z:Text):async(Int,Bool,Text) {return (x,y,z);}; - n0(u:()):async() {return u}; - n1(x:Int):async Int {return x;}; - n2(xy:(Int,Bool)):async(Int,Bool) {return xy;}; - n3(xyz:(Int,Bool,Text)):async(Int,Bool,Text) {return xyz;}; + public func n0(u:()):async() {return u}; + public func n1(x:Int):async Int {return x;}; + public func n2(xy:(Int,Bool)):async(Int,Bool) {return xy;}; + public func n3(xyz:(Int,Bool,Text)):async(Int,Bool,Text) {return xyz;}; // higher-order cases - h0 (f0:shared () -> async (),u:()) : async () + public func h0 (f0:shared () -> async (),u:()) : async () { await f0 u;}; - h1 (f1:shared (Int) -> async Int,x:Int) : async Int + public func h1 (f1:shared (Int) -> async Int,x:Int) : async Int { await f1 x;}; - h2 (f2:shared (Int,Bool) -> async (Int,Bool), xy:(Int,Bool)) : async (Int,Bool) + public func h2 (f2:shared (Int,Bool) -> async (Int,Bool), xy:(Int,Bool)) : async (Int,Bool) { await f2 xy; }; - h3 (f3:shared (Int,Bool,Text) -> async (Int,Bool,Text), xyz:(Int,Bool,Text)) : async (Int,Bool,Text) + public func h3 (f3:shared (Int,Bool,Text) -> async (Int,Bool,Text), xyz:(Int,Bool,Text)) : async (Int,Bool,Text) { await f3 xyz; }; - g0 (f0:shared (()) -> async (),u:()) : async () + public func g0 (f0:shared (()) -> async (),u:()) : async () { await f0 u;}; - g1 (f1:shared (Int) -> async Int,x:Int) : async Int + public func g1 (f1:shared (Int) -> async Int,x:Int) : async Int { await f1 x;}; - g2 (f2:shared ((Int,Bool)) -> async (Int,Bool), xy:(Int,Bool)) : async (Int,Bool) + public func g2 (f2:shared ((Int,Bool)) -> async (Int,Bool), xy:(Int,Bool)) : async (Int,Bool) { await f2 xy; }; - g3 (f3:shared ((Int,Bool,Text)) -> async (Int,Bool,Text), xyz:(Int,Bool,Text)) : async (Int,Bool,Text) + public func g3 (f3:shared ((Int,Bool,Text)) -> async (Int,Bool,Text), xyz:(Int,Bool,Text)) : async (Int,Bool,Text) { await f3 xyz; }; }; diff --git a/test/run-dfinity/general-type-components.as b/test/run-dfinity/general-type-components.as index f36b9e8b561..5c88383c539 100644 --- a/test/run-dfinity/general-type-components.as +++ b/test/run-dfinity/general-type-components.as @@ -1,13 +1,13 @@ // test type components in object and actors (not just modules) object X = { - func f() { g();}; - private func g() { f();}; - object Y = { - type U = Int; + public func f() { g();}; + func g() { f();}; + public object Y = { + public type U = Int; }; - type T = Y.U; // ok type field since Y.U private but avoidable - private func h():T { h() }; // ditto + public type T = Y.U; // ok type field since Y.U private but avoidable + func h():T { h() }; // ditto }; type XT = X.T; @@ -15,13 +15,13 @@ type XYU = X.Y.U; actor A = { - func f() { g();}; - private func g() { f();}; - private object Y = { - type U = Int; + public func f() { g();}; + func g() { f();}; + object Y = { + public type U = Int; }; - type T = Y.U; // ok type field since Y.U private but avoidable - private func h():T { h() }; // ditto + public type T = Y.U; // ok type field since Y.U private but avoidable + func h():T { h() }; // ditto }; type AT = A.T; diff --git a/test/run-dfinity/hello-world-async.as b/test/run-dfinity/hello-world-async.as index aec152a6f63..2b7bab40032 100644 --- a/test/run-dfinity/hello-world-async.as +++ b/test/run-dfinity/hello-world-async.as @@ -1,8 +1,8 @@ let a = actor { - world () { + public func world() { print("World!\n"); }; - go () { + public func go() { world(); print("Hello "); }; diff --git a/test/run-dfinity/hello-world-await.as b/test/run-dfinity/hello-world-await.as index 632ed4bb694..d8b73e3bdc2 100644 --- a/test/run-dfinity/hello-world-await.as +++ b/test/run-dfinity/hello-world-await.as @@ -1,11 +1,11 @@ let a = actor { - hello () : async Text { + public func hello() : async Text { "Hello "; }; - world () : async Text { + public func world() : async Text { "World!\n" }; - go () : async () { + public func go() : async () { print((await hello()) # (await world())); }; }; diff --git a/test/run-dfinity/hello-world-message.as b/test/run-dfinity/hello-world-message.as index 5ea1e82608e..73608dd9731 100644 --- a/test/run-dfinity/hello-world-message.as +++ b/test/run-dfinity/hello-world-message.as @@ -1,5 +1,5 @@ actor { - hello () { + public func hello() { print("Hello World!\n"); } } diff --git a/test/run-dfinity/hello-world-message2.as b/test/run-dfinity/hello-world-message2.as index d0016c72edc..b177bac179c 100644 --- a/test/run-dfinity/hello-world-message2.as +++ b/test/run-dfinity/hello-world-message2.as @@ -1,5 +1,5 @@ actor hello_world { - hello () { + public func hello() { print("Hello World!\n"); } } diff --git a/test/run-dfinity/hello-world2.as b/test/run-dfinity/hello-world2.as index 0f142775153..c797af62b2c 100644 --- a/test/run-dfinity/hello-world2.as +++ b/test/run-dfinity/hello-world2.as @@ -1,5 +1,5 @@ let a = actor { - hello () { + public func hello() { print("Hello World!\n"); } }; diff --git a/test/run-dfinity/hello-world3.as b/test/run-dfinity/hello-world3.as index 5fd3d5132ba..5354a951b08 100644 --- a/test/run-dfinity/hello-world3.as +++ b/test/run-dfinity/hello-world3.as @@ -1,12 +1,12 @@ let a = actor { - hello () { + public func hello() { print("Hello "); }; - go () { + public func go() { hello(); world(); }; - world () { + public func world() { print("World!\n"); }; }; diff --git a/test/run-dfinity/indirect-counter.as b/test/run-dfinity/indirect-counter.as index b058ed60089..8537fd94dc1 100644 --- a/test/run-dfinity/indirect-counter.as +++ b/test/run-dfinity/indirect-counter.as @@ -1,16 +1,16 @@ let a = actor { - private aa = actor { - private var c = 1; - inc() { + let aa = actor { + var c = 1; + public func inc() { c += 1; printInt(c) }; - print () { + public func print() { printInt(c) }; }; - inc() { aa.inc() }; - print() { aa.print() }; + public func inc() { aa.inc() }; + public func print() { aa.print() }; }; a.inc(); diff --git a/test/run-dfinity/modexp1.as b/test/run-dfinity/modexp1.as index 34a1ada2246..7dda56e0ec2 100644 --- a/test/run-dfinity/modexp1.as +++ b/test/run-dfinity/modexp1.as @@ -1,7 +1,7 @@ -module X = { - func f() { g();}; - private func g() { f();}; +module X { + public func f() { g() }; + func g() { f() }; }; let ok = X.f; diff --git a/test/run-dfinity/modexp2.as b/test/run-dfinity/modexp2.as index 1aab9fee07e..7f658795b0a 100644 --- a/test/run-dfinity/modexp2.as +++ b/test/run-dfinity/modexp2.as @@ -1,10 +1,10 @@ -module X = { - func f() { g();}; - private func g() { f();}; - private let y : Nat = 2; - private type U = Int; - type T = U; +module X { + public func f() { g() }; + func g() { f() }; + let y : Nat = 2; + type U = Int; + public type T = U; }; type Ok = X.T; diff --git a/test/run-dfinity/modexp3.as b/test/run-dfinity/modexp3.as index 7d6af576e05..9d4fa06a3ed 100644 --- a/test/run-dfinity/modexp3.as +++ b/test/run-dfinity/modexp3.as @@ -1,10 +1,10 @@ -module X = { - func f() { g();}; - private func g() { f();}; - private type U = Int -> Int; - type T = U; // ok export, because U, though private, is avoidable - func h():T { h() }; // ditto +module X { + public func f() { g() }; + func g() { f() }; + type U = Int -> Int; + public type T = U; // ok export, because U, though private, is avoidable + public func h() : T { h() }; // ditto }; type Ok = X.T; diff --git a/test/run-dfinity/modexp4.as b/test/run-dfinity/modexp4.as index 66f76f29271..25593e7e4f9 100644 --- a/test/run-dfinity/modexp4.as +++ b/test/run-dfinity/modexp4.as @@ -1,12 +1,10 @@ -module X = { - func f() { g();}; - private func g() { f();}; - private module Y = { - type U = U -> U; +module X { + public func f() { g() }; + func g() { f() }; + module Y { + public type U = U -> U; }; - private type T = Y.U; // ok private field eventhough Y.U private and unavoidable - private func h():T { h() }; // ditto + type T = Y.U; // ok private field eventhough Y.U private and unavoidable + func h() : T { h() }; // ditto }; - - diff --git a/test/run-dfinity/modules-bwd.as b/test/run-dfinity/modules-bwd.as index 6c481a601d1..8708a8a89fb 100644 --- a/test/run-dfinity/modules-bwd.as +++ b/test/run-dfinity/modules-bwd.as @@ -1,9 +1,9 @@ module X = { module A = { - module B = { - type T = (); - let v = () + public module B = { + public type T = (); + public let v = () }; }; diff --git a/test/run-dfinity/ok/data-params.run-ir.ok b/test/run-dfinity/ok/data-params.run-ir.ok index d30b0888488..82fef50ca40 100644 --- a/test/run-dfinity/ok/data-params.run-ir.ok +++ b/test/run-dfinity/ok/data-params.run-ir.ok @@ -1,4 +1,4 @@ -data-params.as:59.18-59.28: warning, this pattern consuming type +data-params.as:59.30-59.40: warning, this pattern consuming type ?Text does not cover value null diff --git a/test/run-dfinity/ok/data-params.run-low.ok b/test/run-dfinity/ok/data-params.run-low.ok index d30b0888488..82fef50ca40 100644 --- a/test/run-dfinity/ok/data-params.run-low.ok +++ b/test/run-dfinity/ok/data-params.run-low.ok @@ -1,4 +1,4 @@ -data-params.as:59.18-59.28: warning, this pattern consuming type +data-params.as:59.30-59.40: warning, this pattern consuming type ?Text does not cover value null diff --git a/test/run-dfinity/ok/data-params.run.ok b/test/run-dfinity/ok/data-params.run.ok index d30b0888488..82fef50ca40 100644 --- a/test/run-dfinity/ok/data-params.run.ok +++ b/test/run-dfinity/ok/data-params.run.ok @@ -1,4 +1,4 @@ -data-params.as:59.18-59.28: warning, this pattern consuming type +data-params.as:59.30-59.40: warning, this pattern consuming type ?Text does not cover value null diff --git a/test/run-dfinity/ok/data-params.tc.ok b/test/run-dfinity/ok/data-params.tc.ok index a988892530f..fdcd0402292 100644 --- a/test/run-dfinity/ok/data-params.tc.ok +++ b/test/run-dfinity/ok/data-params.tc.ok @@ -1,4 +1,4 @@ -data-params.as:59.18-59.28: warning, this pattern consuming type +data-params.as:59.30-59.40: warning, this pattern consuming type ?Text does not cover value null diff --git a/test/run-dfinity/ok/data-params.wasm.stderr.ok b/test/run-dfinity/ok/data-params.wasm.stderr.ok index a988892530f..fdcd0402292 100644 --- a/test/run-dfinity/ok/data-params.wasm.stderr.ok +++ b/test/run-dfinity/ok/data-params.wasm.stderr.ok @@ -1,4 +1,4 @@ -data-params.as:59.18-59.28: warning, this pattern consuming type +data-params.as:59.30-59.40: warning, this pattern consuming type ?Text does not cover value null diff --git a/test/run-dfinity/reference-params.as b/test/run-dfinity/reference-params.as index ba199699a64..98e51252b68 100644 --- a/test/run-dfinity/reference-params.as +++ b/test/run-dfinity/reference-params.as @@ -1,5 +1,5 @@ let a = actor { - hello() { + public func hello() { print("Hello World!\n"); }; }; @@ -7,7 +7,7 @@ a.hello(); // test passing an actor to an actor let b = actor this { - say_hi(a : actor { hello : () -> () } ) { + public func say_hi(a : actor { hello : () -> () } ) { a.hello(); }; }; @@ -15,7 +15,7 @@ b.say_hi(a); // test passing a funcref to an actor let c = actor { - say_hi(f : shared () -> ()) { + public func say_hi(f : shared () -> ()) { f(); }; }; @@ -23,13 +23,13 @@ c.say_hi(a.hello); // test passing a own funcref to an actor let d = actor { - say_hi(f : shared () -> ()) { + public func say_hi(f : shared () -> ()) { f(); }; - hello() { + public func hello() { print("Hello Universe!\n"); }; - go() { + public func go() { say_hi(hello); } }; @@ -37,10 +37,10 @@ d.go(); // test passing a self to an actor let e = actor this { - hello() { + public func hello() { print("Hello Galaxy!\n"); }; - send_to(f : shared (actor { hello : () -> () }) -> ()) { + public func send_to(f : shared (actor { hello : () -> () }) -> ()) { f(this); } }; diff --git a/test/run-dfinity/show.as b/test/run-dfinity/show.as index 8f9ca5619a7..502d1be8b2a 100644 --- a/test/run-dfinity/show.as +++ b/test/run-dfinity/show.as @@ -15,7 +15,7 @@ printLn(debug_show (42,-42,())); printLn(debug_show ("Foobar", null, null, ?23)); printLn(debug_show ([1,2,3])); printLn(debug_show ([var 1,2,3])); -class Foo() { let foo : Int = 42; var bar : Bool = true ; private hidden = [1,2] }; +class Foo() { public let foo : Int = 42; public var bar : Bool = true ; let hidden = [1,2] }; printLn(debug_show (Foo())); printLn(debug_show (#foo ())); printLn(debug_show (#bar 42)); diff --git a/test/run-dfinity/transpose.as b/test/run-dfinity/transpose.as index 024739e4e73..a974c2da176 100644 --- a/test/run-dfinity/transpose.as +++ b/test/run-dfinity/transpose.as @@ -1,9 +1,9 @@ actor foo { - transpose (data : [(Int,Text)]) : async {ints: [Int]; txts: [Text]} { - return (new { + public func transpose (data : [(Int,Text)]) : async {ints: [Int]; txts: [Text]} { + return new { ints = Array_tabulate(data.len(), func (i:Nat) : Int = (data[i].0)); txts = Array_tabulate(data.len(), func (i:Nat) : Text = (data[i].1)) - }) + } } }; diff --git a/test/run/actors.as b/test/run/actors.as index 609faa0e9a3..3da046ff45c 100644 --- a/test/run/actors.as +++ b/test/run/actors.as @@ -1,20 +1,20 @@ 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) }; + public func tic_msg(n : Int) { if (n > 0) tictac_actor.tac_msg(n - 1) }; + public func tac_msg(n : Int) { if (n > 0) tictac_actor.tic_msg(n - 1) }; }; let _ = tictac_actor.tic_msg(10); func ignore(_ : async ()) = (); object tictac_async { - tic_async(n : Int) : async () { if (n > 0) ignore(tictac_async.tac_async(n - 1)) }; - tac_async(n : Int) : async () { if (n > 0) ignore(tictac_async.tic_async(n - 1)) }; + public func tic_async(n : Int) : async () { if (n > 0) ignore(tictac_async.tac_async(n - 1)) }; + public func tac_async(n : Int) : async () { if (n > 0) ignore(tictac_async.tic_async(n - 1)) }; }; let _ = tictac_async.tic_async(10); 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)) }; + public func tic_msg_async(n : Int) : async () { if (n > 0) ignore(tictac_actor_async.tac_msg_async(n - 1)) }; + public func 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/async-calls.as b/test/run/async-calls.as index 890a3e58746..208cd0964d2 100644 --- a/test/run/async-calls.as +++ b/test/run/async-calls.as @@ -2,46 +2,46 @@ before delivery. */ -let sync_object = new self { - private var x : Bool = false; +let sync_object = object self { + var x : Bool = false; - bump() { assert (x == false); x := true; assert (x == true); }; + public func bump() { assert (x == false); x := true; assert (x == true); }; - test() { assert (x == false); self.bump(); assert (x == true); }; + public func test() { assert (x == false); self.bump(); assert (x == true); }; }; sync_object.test(); let async_actor = actor self { - private var x : Bool = false; + var x : Bool = false; - bump() { assert (x == false); x := true; assert (x == true); }; + public func bump() { assert (x == false); x := true; assert (x == true); }; - test() { assert (x == false); self.bump(); assert (x == false); }; + public func test() { assert (x == false); self.bump(); assert (x == false); }; }; async_actor.test(); let async2_actor = actor self { - private var x : Bool = false; + var x : Bool = false; - bump() { assert (x == false); x := true; assert (x == true); }; + public func bump() { assert (x == false); x := true; assert (x == true); }; - test() { assert (x == false); bump(); assert (x == false); is_true(); }; + public func test() { assert (x == false); bump(); assert (x == false); is_true(); }; - is_true() { assert (x == true); }; + public func is_true() { assert (x == true); }; }; async2_actor.test(); let async_rec_actor = actor self { - private var x : Bool = false; + var x : Bool = false; - test(b : Bool) { + public func test(b : Bool) { if (b) { assert (x == false); x := true; assert (x == true); } else { assert (x == false); test(false); assert (x == false); is_true(); } }; - is_true() { assert (x == true); }; + public func is_true() { assert (x == true); }; }; async_rec_actor.test(true); diff --git a/test/run/control.as b/test/run/control.as index a4eeab3dbc9..887e1289431 100644 --- a/test/run/control.as +++ b/test/run/control.as @@ -1,8 +1,8 @@ actor class Control() { - private condition() : Bool = false; + func condition() : Bool = false; - testBlock() { + public func testBlock() { label l1 { break l1 }; @@ -12,44 +12,44 @@ actor class Control() { let (x, y, z) = label l3 : (Int, Bool, Text) (break l3(2, true, "")); }; - testWhile() { + public func testWhile() { label l while (condition()) { if true break l else continue l; }; }; - testLoop() { + public func testLoop() { label l loop { if true break l else continue l; }; }; - testLoopWhile() { + public func testLoopWhile() { label l loop { if true break l else continue l; } while (condition()); }; - testLoopWhile2() { + public func testLoopWhile2() { loop { } while (false); }; - testLoopWhile3() { + public func testLoopWhile3() { label l { loop { } while (false and true) }; }; - testLoopWhile4() { + public func testLoopWhile4() { label l loop { } while (true and false); }; - testNestedWhile() { + public func testNestedWhile() { label l while (condition()) { if true break l else continue l; diff --git a/test/run/coverage.as b/test/run/coverage.as index 8f5f5404b2d..43e0d748f1f 100644 --- a/test/run/coverage.as +++ b/test/run/coverage.as @@ -34,13 +34,13 @@ func f() { switch (0, 0) { case (_, (6 or _)) {}; case _ {} }; switch (0, 0) { case (0, _) {}; case (_, 0) {} }; switch (0, 0) { case (0, _) {}; case (_, 0) {}; case _ {} }; - switch (object {a = 0; b = 0}) { case {a = _; b = _} {}; case {a = _; b = 6} {} }; - switch (object {a = 0; b = 0}) { case {} {}; case {b = 6} {} }; - switch (object {a = 0; b = 0}) { case {a = _; b = 6 or _} {}; case _ {} }; - switch (object {a = 0; b = 0}) { case {b = 6 or _} {}; case _ {} }; - switch (object {a = 0; b = 0}) { case {a = 0} {}; case {b = 0} {} }; - switch (object {a = 0; b = 0}) { case {a = 0} {}; case {b = 0} {}; case {} {} }; - switch (object {a = true}) { case {a = true} {}; case {a = false} {} }; + switch (new {a = 0; b = 0}) { case {a = _; b = _} {}; case {a = _; b = 6} {} }; + switch (new {a = 0; b = 0}) { case {} {}; case {b = 6} {} }; + switch (new {a = 0; b = 0}) { case {a = _; b = 6 or _} {}; case _ {} }; + switch (new {a = 0; b = 0}) { case {b = 6 or _} {}; case _ {} }; + switch (new {a = 0; b = 0}) { case {a = 0} {}; case {b = 0} {} }; + switch (new {a = 0; b = 0}) { case {a = 0} {}; case {b = 0} {}; case {} {} }; + switch (new {a = true}) { case {a = true} {}; case {a = false} {} }; switch (#a 6 : {#a : Nat; #b : Nat}) { case (#a _) {}; case (#b _) {} }; switch (#a 6 : {#a : Nat; #b : Nat}) { case (#a _) {}; case (#b 6) {} }; switch (#a 6 : {#a : Nat; #b : Nat}) { case (#a _) {}; case (#a 5) {}; case (#b _) {} }; diff --git a/test/run/import-module.as b/test/run/import-module.as index 6a164620a6e..1b26b471a87 100644 --- a/test/run/import-module.as +++ b/test/run/import-module.as @@ -1,3 +1,3 @@ let L = import "lib/ListM.as"; type stack = L.List; -let s = L.cons(1,L.nil()); +let s = L.cons(1, L.nil()); diff --git a/test/run/ir-pat-subtype.as b/test/run/ir-pat-subtype.as index 0fc6bad58f4..7b1fa3eb0b2 100644 --- a/test/run/ir-pat-subtype.as +++ b/test/run/ir-pat-subtype.as @@ -1,23 +1,23 @@ -type L = {a:{}}; +type L = {a : {}}; type U = {}; let l = new {a = new {}}; -func f(l:L):U = switch l { - case (u:U) u; +func f(l : L) : U = switch l { + case (u : U) u; }; let {} = f(l); // tuples -func t1(tl : (L, L) ) : (U, U) = switch tl { +func t1(tl : (L, L)) : (U, U) = switch tl { case (tu : (U, U)) tu; }; -let ({}, {}) = t1((l,l)); +let ({}, {}) = t1((l, l)); func t2(tl : (L, L)) : (U, U) = switch tl { - case (u1 : U, u2 : U) (u1,u2); + case (u1 : U, u2 : U) (u1, u2); }; let ({}, {}) = t2((l, l)); @@ -41,34 +41,34 @@ let (? {} or _) = o2(? l); // records -func r1(rl : object { a : L }) : object { a : U } = switch rl { - case (ru : { a : U }) ru; +func r1(rl : {a : L}) : {a : U} = switch rl { + case (ru : {a : U}) ru; }; -let { a = {} } : object { a : U } = r1(object { a = l }); +let {a = {}} : {a : U} = r1(new {a = l}); -func r2(rl : object { a : L }) : object { a : U } = switch rl { - case ({a=u:U}) object {a=u}; +func r2(rl : {a : L}) : {a : U} = switch rl { + case ({a = u : U}) (new {a = u}); }; -let { a = {} } : object { a : U } = r2(object { a = l }); +let {a = {}} : {a : U} = r2(new {a = l}); -func r3(rl : object { a : L }) : object {} = switch rl { - case {} object {}; +func r3(rl : {a : L}) : {} = switch rl { + case {} (new {}); }; -let {}:object{} = r3(object{a=l}); +let {} : {} = r3(new {a = l}); // variants -func v1(vl : { #a : L }) : {#a:U} = switch vl { - case (vu : { #a : U }) vu; +func v1(vl : {#a : L}) : {#a : U} = switch vl { + case (vu : {#a : U}) vu; }; let (#a {})= v1(#a l); -func v2(vl : { #a : L }) : { #a : U } = switch vl { +func v2(vl : {#a : L}) : {#a : U} = switch vl { case (#a u) #a u; }; @@ -76,9 +76,8 @@ let (#a {}) = v2(#a l); // alternative patterns -func a(l : object { a : Int }):U = switch l { - case (({ a = 1 }:object { a : Int }) or ( _ : U) ) l; +func a(l : {a : Int}):U = switch l { + case (({a = 1} : {a : Int}) or (_ : U) ) l; }; -let {} = a(object {a = 2}); - +let {} = a(new {a = 2}); diff --git a/test/run/issue150.as b/test/run/issue150.as index baf5603978f..12047c10be5 100644 --- a/test/run/issue150.as +++ b/test/run/issue150.as @@ -1,6 +1,6 @@ -func f(x:C)=(); +func f(x : C) = (); class C() = this { - apply():() = f(this); + public func apply() : () = f(this); }; diff --git a/test/run/lib/ListM.as b/test/run/lib/ListM.as index 432fa38a153..5f09b3fea39 100644 --- a/test/run/lib/ListM.as +++ b/test/run/lib/ListM.as @@ -1,5 +1,6 @@ module { - type List = ?(T, List); - func nil() : List = null; - func cons(x : T, l : List) : List = ?(x, l); + public type List = ?(T, List); + + public func nil() : List = null; + public func cons(x : T, l : List) : List = ?(x, l); } diff --git a/test/run/module1.as b/test/run/module1.as index 0472186fbf9..b230c35646a 100644 --- a/test/run/module1.as +++ b/test/run/module1.as @@ -1,7 +1,7 @@ { -module X = -{ type T = Int; - let x:T = 1; +module X = { + public type T = Int; + public let x : T = 1; }; type T = X.T; @@ -12,14 +12,14 @@ let y = X.x + 1; { module X = { - type T = (A,A); - let x:T = (1,2); + public type T = (A,A); + public let x : T = (1, 2); }; type T = X.T; let x = X.x; -let (x1,x2) : T = X.x; +let (x1, x2) : T = X.x; assert (x1 == 1); assert (x2 == 2); @@ -28,32 +28,32 @@ assert (x2 == 2); { module X = { - module X = { - type T = (A,A); - let x:T = (1,2); + public module X = { + public type T = (A, A); + public let x : T = (1, 2); }; }; type T = X.X.T; let x = X.X.x; -let (x1,x2) : T = X.X.x; +let (x1, x2) : T = X.X.x; assert (x1 == 1); assert (x2 == 2); }; { module X = { - module X = { - type T = (A,A); - let x:T = (1,2); + public module X = { + public type T = (A, A); + public let x : T = (1, 2); }; }; module Y = { - type T = X.X.T; + public type T = X.X.T; - let x = X.X.x; - let (x1,x2) : T = X.X.x; + public let x = X.X.x; + public let (x1, x2) : T = X.X.x; }; let _ = assert (Y.x1 == 1); diff --git a/test/run/module2.as b/test/run/module2.as index 1edf73a741c..2b6f217a666 100644 --- a/test/run/module2.as +++ b/test/run/module2.as @@ -1,5 +1,5 @@ // check types and terms have separate namespaces -module X = { type x = Int; let x = 1; }; +module X = { public type x = Int; public let x = 1; }; type x = X.x; let x = X.x; -/* assert (x == 1); */ \ No newline at end of file +/* assert (x == 1); */ diff --git a/test/run/module3.as b/test/run/module3.as index baa59ecaebc..79ccfcc82c4 100644 --- a/test/run/module3.as +++ b/test/run/module3.as @@ -1,11 +1,12 @@ // test equivalence of various type references module List = { - type List = ?(A,List.List); + public type List = ?(A,List.List); + func rev(x : List, acc : List.List) : List { switch (x) { case (null) acc; - case (?(h,t)) rev(t,?(h,acc)); + case (?(h, t)) rev(t, ?(h, acc)); }; }; }; diff --git a/test/run/mut-field-bound.as b/test/run/mut-field-bound.as index 21ddc51f11a..100b94c0b3d 100644 --- a/test/run/mut-field-bound.as +++ b/test/run/mut-field-bound.as @@ -2,5 +2,5 @@ type Obj = {var x : Nat}; func foo(o : O) : Nat { o.x }; -let o : Obj = new {var x : Nat = 1}; +let o : Obj = new {var x = 1 : Nat}; assert(foo<{var x : Nat}>(o) == 1); diff --git a/test/run/nested-class-rec.as b/test/run/nested-class-rec.as index 4ab62442d0c..8a8a9b351d9 100644 --- a/test/run/nested-class-rec.as +++ b/test/run/nested-class-rec.as @@ -2,9 +2,7 @@ class Foo(f1:Int -> Int, f2:Int -> Int) { }; class Bar () { + func g(n:Int) : Int = n + 1; - private g(n:Int) : Int = n + 1; - - let Bar = Foo(g, g) : Foo; // annotation needed to typecheck constructor call - + public let Bar = Foo(g, g) : Foo; // annotation needed to typecheck constructor call }; diff --git a/test/run/nested-lexpr.as b/test/run/nested-lexpr.as index 2a9768bf52f..3d7371a1b4b 100644 --- a/test/run/nested-lexpr.as +++ b/test/run/nested-lexpr.as @@ -3,7 +3,7 @@ assert (a[0][0] == 1); a[0][0] := 2; assert (a[0][0] == 2); -let b : [{var x : Int}] = [new {var x : Int = 1}]; +let b : [{var x : Int}] = [new {var x = 1 : Int}]; assert (b[0].x == 1); b[0].x := 2; assert (b[0].x == 2); diff --git a/test/run/objects1.as b/test/run/objects1.as index faf19f324f9..8ec85aaa2c3 100644 --- a/test/run/objects1.as +++ b/test/run/objects1.as @@ -1,17 +1,17 @@ -let p = new {x = 3; private y = 2; get_y() : Int = y}; +let p = object {public let x = 3; let y = 2; public func get_y() : Int = y}; assert(p.x == 3); assert(p.get_y() == 2); let o : {a : {}; b : Nat} = new {a = new {x = 0}; b = a.x}; let oo = object { - private type T = Int; - let x : T = 3; - let (y, z) = (3, ""); - var v = 0; - func f() : T { g() + x }; - func g() : T { f() + y }; - private class C() {}; + type T = Int; + public let x : T = 3; + public let (y, z) = (3, ""); + public var v = 0; + public func f() : T { g() + x }; + public func g() : T { f() + y }; + class C() {}; }; // pattern matching @@ -38,7 +38,7 @@ assert (get_a () == -42); // subtyping and tuple patterns for comparison -let row : (Nat, Int, {c : Char; d : Text}) = (100, -42, new {c='C'; d="D"}); +let row : (Nat, Int, {c : Char; d : Text}) = (100, -42, new {c = 'C'; d = "D"}); func foo () : Int = switch row { case (a : Int, -42, {c} : {c : Char}) (word32ToNat(charToWord32 c)) // OK diff --git a/test/run/objects2.as b/test/run/objects2.as index db7ed3cee68..6fbfa236f5c 100644 --- a/test/run/objects2.as +++ b/test/run/objects2.as @@ -1,5 +1,5 @@ type O = {self : () -> O; x : Nat}; -let o = new this {self() : O = this; x = 1}; +let o = object this {public func self() : O = this; public let x = 1}; assert(o.x == 1); assert(o.self().x == 1); assert(o.self().self().x == 1); diff --git a/test/run/objects3.as b/test/run/objects3.as index 3c9de95c5d5..975a3e13a03 100644 --- a/test/run/objects3.as +++ b/test/run/objects3.as @@ -1,5 +1,5 @@ type Q = {var this : ?Q; x : Nat}; -let q : Q = new {var this : ?Q = null; x = 4}; +let q : Q = new {var this = null : ?Q; x = 4}; q.this := ?q; func unopt(x : ?T) : T = switch x { case (?y) y; case _ unopt(x) }; assert(unopt(unopt(q.this).this).x == 4); diff --git a/test/run/objects4.as b/test/run/objects4.as index 525387c8891..2f20b46f468 100644 --- a/test/run/objects4.as +++ b/test/run/objects4.as @@ -1,5 +1,5 @@ -let oddeven = new this { - odd(n : Int) : Bool = if (n > 0) this.odd(n - 1) else false; - even(n : Int) : Bool = if (n > 0) this.even(n - 1) else true; +let oddeven = object this { + public func odd(n : Int) : Bool = if (n > 0) this.odd(n - 1) else false; + public func even(n : Int) : Bool = if (n > 0) this.even(n - 1) else true; }; assert (oddeven.even(10)); diff --git a/test/run/objects5.as b/test/run/objects5.as index d5ef10c05be..1e7a576d555 100644 --- a/test/run/objects5.as +++ b/test/run/objects5.as @@ -1,5 +1,5 @@ -let p1 = new {var x = 3; private y = 2; get_y() : Int = y}; -let p2 = new {var x = 3; private y = 2; get_y() : Int = y}; +let p1 = object {public var x = 3; let y = 2; public func get_y() : Int = y}; +let p2 = object {public var x = 3; let y = 2; public func get_y() : Int = y}; assert(p1.x == 3); assert(p1.get_y() == 2); diff --git a/test/run/ok/coverage.run-ir.ok b/test/run/ok/coverage.run-ir.ok index 39ee1621c2d..5c8074a5068 100644 --- a/test/run/ok/coverage.run-ir.ok +++ b/test/run/ok/coverage.run-ir.ok @@ -13,10 +13,10 @@ coverage.as:31.25-31.34: warning, this case is never reached coverage.as:32.43-32.44: warning, this pattern is never matched coverage.as:33.35-33.49: warning, this case is never reached coverage.as:34.42-34.51: warning, this case is never reached -coverage.as:37.60-37.82: warning, this case is never reached -coverage.as:38.48-38.63: warning, this case is never reached -coverage.as:39.65-39.74: warning, this case is never reached -coverage.as:40.58-40.67: warning, this case is never reached +coverage.as:37.57-37.79: warning, this case is never reached +coverage.as:38.45-38.60: warning, this case is never reached +coverage.as:39.62-39.71: warning, this case is never reached +coverage.as:40.55-40.64: warning, this case is never reached coverage.as:46.58-46.72: warning, this case is never reached coverage.as:61.22-61.31: warning, this case is never reached coverage.as:62.28-62.37: warning, this case is never reached @@ -71,7 +71,7 @@ coverage.as:35.3-35.51: warning, the cases in this switch over type (Nat, Nat) do not cover value (1 or 2 or _, 1 or 2 or _) -coverage.as:41.3-41.70: warning, the cases in this switch over type +coverage.as:41.3-41.67: warning, the cases in this switch over type {a : Nat; b : Nat} do not cover value {a = 1 or 2 or _; b = 1 or 2 or _) diff --git a/test/run/ok/coverage.run-low.ok b/test/run/ok/coverage.run-low.ok index 39ee1621c2d..5c8074a5068 100644 --- a/test/run/ok/coverage.run-low.ok +++ b/test/run/ok/coverage.run-low.ok @@ -13,10 +13,10 @@ coverage.as:31.25-31.34: warning, this case is never reached coverage.as:32.43-32.44: warning, this pattern is never matched coverage.as:33.35-33.49: warning, this case is never reached coverage.as:34.42-34.51: warning, this case is never reached -coverage.as:37.60-37.82: warning, this case is never reached -coverage.as:38.48-38.63: warning, this case is never reached -coverage.as:39.65-39.74: warning, this case is never reached -coverage.as:40.58-40.67: warning, this case is never reached +coverage.as:37.57-37.79: warning, this case is never reached +coverage.as:38.45-38.60: warning, this case is never reached +coverage.as:39.62-39.71: warning, this case is never reached +coverage.as:40.55-40.64: warning, this case is never reached coverage.as:46.58-46.72: warning, this case is never reached coverage.as:61.22-61.31: warning, this case is never reached coverage.as:62.28-62.37: warning, this case is never reached @@ -71,7 +71,7 @@ coverage.as:35.3-35.51: warning, the cases in this switch over type (Nat, Nat) do not cover value (1 or 2 or _, 1 or 2 or _) -coverage.as:41.3-41.70: warning, the cases in this switch over type +coverage.as:41.3-41.67: warning, the cases in this switch over type {a : Nat; b : Nat} do not cover value {a = 1 or 2 or _; b = 1 or 2 or _) diff --git a/test/run/ok/coverage.run.ok b/test/run/ok/coverage.run.ok index 39ee1621c2d..5c8074a5068 100644 --- a/test/run/ok/coverage.run.ok +++ b/test/run/ok/coverage.run.ok @@ -13,10 +13,10 @@ coverage.as:31.25-31.34: warning, this case is never reached coverage.as:32.43-32.44: warning, this pattern is never matched coverage.as:33.35-33.49: warning, this case is never reached coverage.as:34.42-34.51: warning, this case is never reached -coverage.as:37.60-37.82: warning, this case is never reached -coverage.as:38.48-38.63: warning, this case is never reached -coverage.as:39.65-39.74: warning, this case is never reached -coverage.as:40.58-40.67: warning, this case is never reached +coverage.as:37.57-37.79: warning, this case is never reached +coverage.as:38.45-38.60: warning, this case is never reached +coverage.as:39.62-39.71: warning, this case is never reached +coverage.as:40.55-40.64: warning, this case is never reached coverage.as:46.58-46.72: warning, this case is never reached coverage.as:61.22-61.31: warning, this case is never reached coverage.as:62.28-62.37: warning, this case is never reached @@ -71,7 +71,7 @@ coverage.as:35.3-35.51: warning, the cases in this switch over type (Nat, Nat) do not cover value (1 or 2 or _, 1 or 2 or _) -coverage.as:41.3-41.70: warning, the cases in this switch over type +coverage.as:41.3-41.67: warning, the cases in this switch over type {a : Nat; b : Nat} do not cover value {a = 1 or 2 or _; b = 1 or 2 or _) diff --git a/test/run/ok/coverage.tc.ok b/test/run/ok/coverage.tc.ok index 39ee1621c2d..5c8074a5068 100644 --- a/test/run/ok/coverage.tc.ok +++ b/test/run/ok/coverage.tc.ok @@ -13,10 +13,10 @@ coverage.as:31.25-31.34: warning, this case is never reached coverage.as:32.43-32.44: warning, this pattern is never matched coverage.as:33.35-33.49: warning, this case is never reached coverage.as:34.42-34.51: warning, this case is never reached -coverage.as:37.60-37.82: warning, this case is never reached -coverage.as:38.48-38.63: warning, this case is never reached -coverage.as:39.65-39.74: warning, this case is never reached -coverage.as:40.58-40.67: warning, this case is never reached +coverage.as:37.57-37.79: warning, this case is never reached +coverage.as:38.45-38.60: warning, this case is never reached +coverage.as:39.62-39.71: warning, this case is never reached +coverage.as:40.55-40.64: warning, this case is never reached coverage.as:46.58-46.72: warning, this case is never reached coverage.as:61.22-61.31: warning, this case is never reached coverage.as:62.28-62.37: warning, this case is never reached @@ -71,7 +71,7 @@ coverage.as:35.3-35.51: warning, the cases in this switch over type (Nat, Nat) do not cover value (1 or 2 or _, 1 or 2 or _) -coverage.as:41.3-41.70: warning, the cases in this switch over type +coverage.as:41.3-41.67: warning, the cases in this switch over type {a : Nat; b : Nat} do not cover value {a = 1 or 2 or _; b = 1 or 2 or _) diff --git a/test/run/ok/coverage.wasm.stderr.ok b/test/run/ok/coverage.wasm.stderr.ok index 39ee1621c2d..5c8074a5068 100644 --- a/test/run/ok/coverage.wasm.stderr.ok +++ b/test/run/ok/coverage.wasm.stderr.ok @@ -13,10 +13,10 @@ coverage.as:31.25-31.34: warning, this case is never reached coverage.as:32.43-32.44: warning, this pattern is never matched coverage.as:33.35-33.49: warning, this case is never reached coverage.as:34.42-34.51: warning, this case is never reached -coverage.as:37.60-37.82: warning, this case is never reached -coverage.as:38.48-38.63: warning, this case is never reached -coverage.as:39.65-39.74: warning, this case is never reached -coverage.as:40.58-40.67: warning, this case is never reached +coverage.as:37.57-37.79: warning, this case is never reached +coverage.as:38.45-38.60: warning, this case is never reached +coverage.as:39.62-39.71: warning, this case is never reached +coverage.as:40.55-40.64: warning, this case is never reached coverage.as:46.58-46.72: warning, this case is never reached coverage.as:61.22-61.31: warning, this case is never reached coverage.as:62.28-62.37: warning, this case is never reached @@ -71,7 +71,7 @@ coverage.as:35.3-35.51: warning, the cases in this switch over type (Nat, Nat) do not cover value (1 or 2 or _, 1 or 2 or _) -coverage.as:41.3-41.70: warning, the cases in this switch over type +coverage.as:41.3-41.67: warning, the cases in this switch over type {a : Nat; b : Nat} do not cover value {a = 1 or 2 or _; b = 1 or 2 or _) diff --git a/test/run/quicksort.as b/test/run/quicksort.as index 96412a19a3d..cd5d77dabf6 100644 --- a/test/run/quicksort.as +++ b/test/run/quicksort.as @@ -1,5 +1,5 @@ class QS(cmp : (T, T) -> Int) { - quicksort(a : [var T], lo : Nat, hi : Nat) { + public func quicksort(a : [var T], lo : Nat, hi : Nat) { if (lo < hi) { let p = partition(a, lo, hi); quicksort(a, lo, p); @@ -7,15 +7,15 @@ class QS(cmp : (T, T) -> Int) { } }; - private swap(a : [var T], i : Nat, j : Nat) { + func swap(a : [var T], i : Nat, j : Nat) { let temp = a[i]; a[i] := a[j]; a[j] := temp; }; - private trace(v : T) {}; + func trace(v : T) {}; - private partition(a : [var T], lo : Nat, hi : Nat) : Nat { + func partition(a : [var T], lo : Nat, hi : Nat) : Nat { trace<[var T]>(a); let pivot = a[lo]; var i = lo; diff --git a/test/run/type-definition.as b/test/run/type-definition.as index 3ae60c90970..e24aefa80d7 100644 --- a/test/run/type-definition.as +++ b/test/run/type-definition.as @@ -10,10 +10,10 @@ type None = (); // shadowing prelude // Test printing of shadowed type constructors class C() {}; type T = {f : X -> C}; -class D(x : T) {r = x.f}; +class D(x : T) {let r = x.f}; type U = {f : X -> Y}; -class E(x : U) {r = x.f}; +class E(x : U) {let r = x.f}; // This is an expected forward reference error //class F(x : FF) {r = x.a}; diff --git a/test/run/type-inclusion.as b/test/run/type-inclusion.as index 14217da15eb..6bdb863287f 100644 --- a/test/run/type-inclusion.as +++ b/test/run/type-inclusion.as @@ -90,14 +90,14 @@ func f(x : A) : B = x; // Classes { -class C() {f(x : X) {}}; +class C() {public func f(x : X) {}}; type A = C; type B = {f : X -> ()}; func f(x : A) : B = x; }; { -class C() {f (x : X) {}}; +class C() {public func f(x : X) {}}; type A = C; type B = {f : X -> ()}; func f(x : A) : B = x; @@ -137,21 +137,21 @@ func f(x : A) : B = x; }; { -class C() { x = 0 }; +class C() { public let x = 0 }; type A = X -> X; type B = X -> X; func f(x : A) : B = x; }; { -class C() {f() : X { f() }}; +class C() {public func f() : X { f() }}; type A = X}> X -> X; type B = > X -> X; func f(x : A) : B = x; }; { -class C() {f() : X { f() }}; +class C() {public func f() : X { f() }}; type A = Nat}> X -> X; type B = > X -> X; func f(x : A) : B = x; From 8fa448ad6451fd786cd7339166b2219a065c14a6 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Tue, 16 Jul 2019 10:58:07 -0700 Subject: [PATCH 0270/1176] fix nix --- default.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/default.nix b/default.nix index 08aea1044df..471e1ee9d2f 100644 --- a/default.nix +++ b/default.nix @@ -7,7 +7,6 @@ let llvm = import ./nix/llvm.nix { system = nixpkgs.system; }; in let stdenv = nixpkgs.stdenv; in -let lib = stdenv.lib; in let subpath = p: import ./nix/gitSource.nix p; in @@ -27,7 +26,7 @@ let ocaml_bisect_ppx-ocamlbuild = import ./nix/ocaml-bisect_ppx-ocamlbuild.nix n let dev = import (builtins.fetchGit { url = "ssh://git@github.com/dfinity-lab/dev"; ref = "master"; - rev = "65c295edfc4164ca89c129d501a403fa246d3d36"; + rev = "fcd387ce757fcc1ee697a19665ada9bc3f453adc"; }) { system = nixpkgs.system; }; in # Include dvm @@ -138,6 +137,7 @@ rec { nixpkgs.wabt nixpkgs.bash nixpkgs.perl + nixpkgs.getconf nixpkgs.nodejs-10_x filecheck js-client From 888baa9a6e4eb7b90ded81295ebda4d6c49cf623 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 16 Jul 2019 19:13:09 +0100 Subject: [PATCH 0271/1176] fix test (#576) --- test/run/ott-typeclasses.as | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/run/ott-typeclasses.as b/test/run/ott-typeclasses.as index f2009fc26ef..66eefe7fe09 100644 --- a/test/run/ott-typeclasses.as +++ b/test/run/ott-typeclasses.as @@ -17,8 +17,8 @@ type Ord = { func compare, T>(w : W, t1 : T, t2 : T) : Order = w.cmp(t1,t2); object ordInt { - func eq(t1 : Int, t2:Int) : Bool = t1 == t2; - func cmp(t1 : Int, t2 : Int) : Order = + public func eq(t1 : Int, t2:Int) : Bool = t1 == t2; + public func cmp(t1 : Int, t2 : Int) : Order = if (t1 < t2) #LT else if (t1 > t2) #GT else #EQ; @@ -27,13 +27,13 @@ object ordInt { type List = ?(T,List); class OrdList, T>(w : W) = this { - func eq(ts1 : List, ts2: List) : Bool = + public func eq(ts1 : List, ts2: List) : Bool = switch (cmp (ts1, ts2)) { case (#EQ) true; case _ false; }; - func cmp(ts1 : List, ts2: List) : Order = + public func cmp(ts1 : List, ts2: List) : Order = switch (ts1, ts2) { case (null, null) #EQ; case (null, ? _) #LT; From e426f6947e2c1525cf9f01014d0b9c2f5626a452 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Tue, 16 Jul 2019 11:26:06 -0700 Subject: [PATCH 0272/1176] sync with master --- test/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/run.sh b/test/run.sh index 3a98ad4b2dd..5dccbbf92a0 100755 --- a/test/run.sh +++ b/test/run.sh @@ -233,7 +233,7 @@ do if [ -e $out/$base.js ] then $ECHO -n " [node]" - export NODE_PATH=$NODE_PATH:$JSCLIENT/node_modules:$JSCLIENT/src + export NODE_PATH=$NODE_PATH:$JSCLIENT:$JSCLIENT/src $NODE $out/$base.js > $out/$base.err 2>&1 diff_files="$diff_files $base.err" fi From 75999993b8bc7c59b3651280da6fc57a4af68db7 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Mon, 15 Jul 2019 15:17:59 -0700 Subject: [PATCH 0273/1176] Node test for IDL JS binding --- default.nix | 16 +++++++++++++++- src/idllib/compile_js.ml | 19 +++++++++++-------- test/idl/ok/actor.js.ok | 11 ++++++----- test/idl/ok/cyclic.js.ok | 5 +++-- test/idl/ok/diamond.js.ok | 5 +++-- test/idl/ok/fields.js.ok | 5 +++-- test/idl/ok/import.js.ok | 7 ++++--- test/idl/ok/import1.js.ok | 5 +++-- test/idl/ok/import3.js.ok | 9 +++++---- test/idl/ok/integer.js.ok | 9 +++++---- test/idl/ok/px.js.ok | 5 +++-- test/idl/ok/recursion.js.ok | 9 +++++---- test/idl/ok/test.js.ok | 19 ++++++++++--------- test/idl/ok/unicode.js.ok | 11 ++++++----- test/run.sh | 10 ++++++++++ 15 files changed, 92 insertions(+), 53 deletions(-) diff --git a/default.nix b/default.nix index f47012d706b..3436bb7bd70 100644 --- a/default.nix +++ b/default.nix @@ -7,6 +7,7 @@ let llvm = import ./nix/llvm.nix { system = nixpkgs.system; }; in let stdenv = nixpkgs.stdenv; in +let lib = stdenv.lib; in let subpath = p: import ./nix/gitSource.nix p; in @@ -38,10 +39,20 @@ let real-dvm = else null else dvm; in +# Include js-client +let js-client = + let dev = builtins.fetchGit { + url = "ssh://git@github.com/dfinity-lab/dev"; + ref = "master"; + rev = "a556b011d957d3174b6c4017d76dd510791d8922"; + }; in + (import dev { system = nixpkgs.system; }).js-dfinity-client; in + let commonBuildInputs = [ nixpkgs.ocaml nixpkgs.dune nixpkgs.ocamlPackages.atdgen + nixpkgs.ocamlPackages.base nixpkgs.ocamlPackages.findlib nixpkgs.ocamlPackages.menhir nixpkgs.ocamlPackages.num @@ -136,6 +147,7 @@ rec { nixpkgs.bash nixpkgs.perl filecheck + js-client ] ++ (if test-dvm then [ real-dvm ] else []) ++ llvmBuildInputs; @@ -146,6 +158,7 @@ rec { export ASC=asc export AS_LD=as-ld export DIDC=didc + export JSCLIENT=${js-client} asc --version '' + (if test-dvm then '' @@ -248,7 +261,7 @@ rec { didc = stdenv.mkDerivation { name = "didc"; src = subpath ./src; - buildInputs = commonBuildInputs; + buildInputs = [ commonBuildInputs ]; buildPhase = '' make DUNE_OPTS="--display=short --profile release" didc ''; @@ -405,6 +418,7 @@ rec { shellHook = llvmEnv; TOMMATHSRC = libtommath; + JSCLIENT = js-client; NIX_FONTCONFIG_FILE = users-guide.NIX_FONTCONFIG_FILE; } else null; diff --git a/src/idllib/compile_js.ml b/src/idllib/compile_js.ml index 67d47cb082d..576018e6a59 100644 --- a/src/idllib/compile_js.ml +++ b/src/idllib/compile_js.ml @@ -172,19 +172,22 @@ let pp_actor ppf actor = pp_open_hovbox ppf 1; kwd ppf "const"; (match actor.it with - | ActorD (x, {it=ServT tp; _}) -> - id ppf x; space ppf (); kwd ppf "="; kwd ppf "new"; - str ppf "IDL.ActorInterface({"; - concat ppf pp_meth "," tp; - str ppf "})" - | ActorD (x, {it=VarT var; _}) -> id ppf x; space ppf (); kwd ppf "="; id ppf var - | ActorD (x, _) -> assert false + | ActorD (x, {it=t; _}) -> + let x = ("actor_" ^ x.it) @@ x.at in + match t with + | ServT tp -> + id ppf x; space ppf (); kwd ppf "="; kwd ppf "new"; + str ppf "IDL.ActorInterface({"; + concat ppf pp_meth "," tp; + str ppf "})" + | VarT var -> id ppf x; space ppf (); kwd ppf "="; id ppf var + | _ -> assert false ); pp_close_box ppf () let pp_header ppf () = pp_open_vbox ppf 0; - str ppf "const IDL = require('./IDL')"; + str ppf "const IDL = require('IDL')"; pp_close_box ppf () let pp_prog ppf env prog = diff --git a/test/idl/ok/actor.js.ok b/test/idl/ok/actor.js.ok index 1e768735ea6..2225b3b1fd9 100644 --- a/test/idl/ok/actor.js.ok +++ b/test/idl/ok/actor.js.ok @@ -1,8 +1,9 @@ +const IDL = require('IDL') const o = IDL.Rec() -const f = IDL.message(IDL.Obj({'0': IDL.Int8}), IDL.Obj({'0': IDL.Int8})) -const h = IDL.message(IDL.Obj({'0': f}), IDL.Obj({'0': f})) +const f = IDL.Message(IDL.Obj({'0': IDL.Int8}), IDL.Obj({'0': IDL.Int8})) +const h = IDL.Message(IDL.Obj({'0': f}), IDL.Obj({'0': f})) const g = f o.fill(IDL.Opt(o)) -const g = new IDL.ActorInterface({ - 'f': IDL.message(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': h})), 'g': f, - 'h': g, 'o': IDL.message(IDL.Obj({'0': o}), IDL.Obj({'0': o}))}) +const actor_g = new IDL.ActorInterface({ + 'f': IDL.Message(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': h})), 'g': f, + 'h': g, 'o': IDL.Message(IDL.Obj({'0': o}), IDL.Obj({'0': o}))}) diff --git a/test/idl/ok/cyclic.js.ok b/test/idl/ok/cyclic.js.ok index 2926b862188..f04f438c3ba 100644 --- a/test/idl/ok/cyclic.js.ok +++ b/test/idl/ok/cyclic.js.ok @@ -1,3 +1,4 @@ +const IDL = require('IDL') const A = IDL.Rec() const C = A const B = IDL.Opt(C) @@ -5,7 +6,7 @@ A.fill(IDL.Opt(B)) const Z = A const Y = Z const X = Y -const S = new IDL.ActorInterface({ +const actor_S = new IDL.ActorInterface({ 'f': - IDL.message(IDL.Obj({'0': A, '1': B, '2': C, '3': X, '4': Y, '5': Z}), + IDL.Message(IDL.Obj({'0': A, '1': B, '2': C, '3': X, '4': Y, '5': Z}), IDL.Obj({}))}) diff --git a/test/idl/ok/diamond.js.ok b/test/idl/ok/diamond.js.ok index 55be9ac8fa3..360efbdc716 100644 --- a/test/idl/ok/diamond.js.ok +++ b/test/idl/ok/diamond.js.ok @@ -1,6 +1,7 @@ +const IDL = require('IDL') const t = IDL.Nat const t2 = IDL.Arr(t) const t3 = IDL.Opt(t) const t1 = IDL.Obj({'0': t2, '1': t3, '2': t}) -const S = new IDL.ActorInterface({ - 'f': IDL.message(IDL.Obj({'0': t, '1': t2, '2': t3}), IDL.Obj({'0': t1}))}) +const actor_S = new IDL.ActorInterface({ + 'f': IDL.Message(IDL.Obj({'0': t, '1': t2, '2': t3}), IDL.Obj({'0': t1}))}) diff --git a/test/idl/ok/fields.js.ok b/test/idl/ok/fields.js.ok index eef5930f0d4..4e2493fcfad 100644 --- a/test/idl/ok/fields.js.ok +++ b/test/idl/ok/fields.js.ok @@ -1,3 +1,4 @@ +const IDL = require('IDL') const A = IDL.Obj({'0': IDL.Nat, '1': IDL.Nat, '2': IDL.Nat}) const B = IDL.Obj({'0': IDL.Arr(IDL.Nat8), '35': IDL.Arr(IDL.Nat8), '36': IDL.Nat, @@ -12,7 +13,7 @@ const nest_record = IDL.Obj({'0': IDL.Nat, '1': IDL.Nat, '2': IDL.Nat, '3': IDL.Obj({'0': IDL.Nat, '1': IDL.Nat, '2': IDL.Nat}), '4': IDL.Nat, '5': IDL.Nat, '6': IDL.Nat, '7': A, '8': B, '9': C, '10': IDL.Nat}) -const S = new IDL.ActorInterface({ +const actor_S = new IDL.ActorInterface({ 'f': - IDL.message(IDL.Obj({'0': A, '1': B, '2': C, '3': nest_record}), + IDL.Message(IDL.Obj({'0': A, '1': B, '2': C, '3': nest_record}), IDL.Obj({}))}) diff --git a/test/idl/ok/import.js.ok b/test/idl/ok/import.js.ok index a2d8865d911..fa9377df38d 100644 --- a/test/idl/ok/import.js.ok +++ b/test/idl/ok/import.js.ok @@ -1,3 +1,4 @@ +const IDL = require('IDL') const t = IDL.Arr(IDL.Nat8) const t1 = t const UserId = IDL.Nat @@ -10,9 +11,9 @@ const EntId = const OpEntId = IDL.Opt(EntId) const IdErr = IDL.Obj({'idErr': OpEntId}) const Inventory = IDL.Obj({'produce_id': IDL.Nat, 'quantity': IDL.Nat}) -const S = new IDL.ActorInterface({ +const actor_S = new IDL.ActorInterface({ 'f': - IDL.message(IDL.Obj({'0': t, '1': t1, '2': t2}), + IDL.Message(IDL.Obj({'0': t, '1': t1, '2': t2}), IDL.Obj({'0': list, '1': IdErr})), 'getInventory': - IDL.message(IDL.Obj({'producer_id': IDL.Nat}), IDL.Obj({'0': Inventory}))}) + IDL.Message(IDL.Obj({'producer_id': IDL.Nat}), IDL.Obj({'0': Inventory}))}) diff --git a/test/idl/ok/import1.js.ok b/test/idl/ok/import1.js.ok index 25ed302284f..23a298b9391 100644 --- a/test/idl/ok/import1.js.ok +++ b/test/idl/ok/import1.js.ok @@ -1,6 +1,7 @@ +const IDL = require('IDL') const t = IDL.Arr(IDL.Nat8) const t1 = t const UserId = IDL.Nat const t2 = UserId -const S = new IDL.ActorInterface({ - 'f': IDL.message(IDL.Obj({'0': t, '1': t1, '2': t2}), IDL.Obj({}))}) +const actor_S = new IDL.ActorInterface({ + 'f': IDL.Message(IDL.Obj({'0': t, '1': t1, '2': t2}), IDL.Obj({}))}) diff --git a/test/idl/ok/import3.js.ok b/test/idl/ok/import3.js.ok index b88df20df65..517f9849fb4 100644 --- a/test/idl/ok/import3.js.ok +++ b/test/idl/ok/import3.js.ok @@ -1,15 +1,16 @@ +const IDL = require('IDL') const B = IDL.Rec() const list = IDL.Rec() const s = IDL.Rec() const stream = IDL.Rec() const tree = IDL.Rec() -const t = IDL.message(IDL.Obj({'server': s}), IDL.Obj({})) +const t = IDL.Message(IDL.Obj({'server': s}), IDL.Obj({})) const node = IDL.Obj({'head': IDL.Nat, 'tail': list}) list.fill(IDL.Opt(node)) stream.fill( IDL.Opt( IDL.Obj({'head': IDL.Nat, - 'next': IDL.message(IDL.Obj({}), IDL.Obj({'0': stream}))})) + 'next': IDL.Message(IDL.Obj({}), IDL.Obj({'0': stream}))})) ) tree.fill( IDL.Variant({ @@ -20,6 +21,6 @@ B.fill(IDL.Opt(A)) s.fill( new IDL.ActorInterface({'f': t, 'g': - IDL.message(IDL.Obj({'0': list}), + IDL.Message(IDL.Obj({'0': list}), IDL.Obj({'2': stream, '1': tree, '0': B}))})) -const S = s +const actor_S = s diff --git a/test/idl/ok/integer.js.ok b/test/idl/ok/integer.js.ok index e9c26dee5e3..436f404354e 100644 --- a/test/idl/ok/integer.js.ok +++ b/test/idl/ok/integer.js.ok @@ -1,4 +1,5 @@ -const num = new IDL.ActorInterface({ - 'f': IDL.message(IDL.Obj({'0': IDL.Nat8}), IDL.Obj({'0': IDL.Int16})), - 'g': IDL.message(IDL.Obj({'0': IDL.Nat64}), IDL.Obj({'0': IDL.Int64})), - 'h': IDL.message(IDL.Obj({'0': IDL.Int8}), IDL.Obj({'0': IDL.Nat}))}) +const IDL = require('IDL') +const actor_num = new IDL.ActorInterface({ + 'f': IDL.Message(IDL.Obj({'0': IDL.Nat8}), IDL.Obj({'0': IDL.Int16})), + 'g': IDL.Message(IDL.Obj({'0': IDL.Nat64}), IDL.Obj({'0': IDL.Int64})), + 'h': IDL.Message(IDL.Obj({'0': IDL.Int8}), IDL.Obj({'0': IDL.Nat}))}) diff --git a/test/idl/ok/px.js.ok b/test/idl/ok/px.js.ok index 95bc9c30625..06ea8d3f87f 100644 --- a/test/idl/ok/px.js.ok +++ b/test/idl/ok/px.js.ok @@ -1,3 +1,4 @@ +const IDL = require('IDL') const UserId = IDL.Nat const RegionId = IDL.Nat const ProducerId = IDL.Nat @@ -11,7 +12,7 @@ const EntId = IDL.Obj({'region': RegionId, 'user': UserId, 'truckType': TruckTypeId}) const OpEntId = IDL.Opt(EntId) const IdErr = IDL.Obj({'idErr': OpEntId}) -const ProduceExchange = new IDL.ActorInterface({ +const actor_ProduceExchange = new IDL.ActorInterface({ 'getInventory': - IDL.message(IDL.Obj({'producer_id': IDL.Nat, '3667444713': UserInfo}), + IDL.Message(IDL.Obj({'producer_id': IDL.Nat, '3667444713': UserInfo}), IDL.Obj({'0': Inventory, '1': IdErr}))}) diff --git a/test/idl/ok/recursion.js.ok b/test/idl/ok/recursion.js.ok index e89ecb02db0..1b71a15819f 100644 --- a/test/idl/ok/recursion.js.ok +++ b/test/idl/ok/recursion.js.ok @@ -1,15 +1,16 @@ +const IDL = require('IDL') const B = IDL.Rec() const list = IDL.Rec() const s = IDL.Rec() const stream = IDL.Rec() const tree = IDL.Rec() -const t = IDL.message(IDL.Obj({'server': s}), IDL.Obj({})) +const t = IDL.Message(IDL.Obj({'server': s}), IDL.Obj({})) const node = IDL.Obj({'head': IDL.Nat, 'tail': list}) list.fill(IDL.Opt(node)) stream.fill( IDL.Opt( IDL.Obj({'head': IDL.Nat, - 'next': IDL.message(IDL.Obj({}), IDL.Obj({'0': stream}))})) + 'next': IDL.Message(IDL.Obj({}), IDL.Obj({'0': stream}))})) ) tree.fill( IDL.Variant({ @@ -20,6 +21,6 @@ B.fill(IDL.Opt(A)) s.fill( new IDL.ActorInterface({'f': t, 'g': - IDL.message(IDL.Obj({'0': list}), + IDL.Message(IDL.Obj({'0': list}), IDL.Obj({'2': stream, '1': tree, '0': B}))})) -const A = s +const actor_A = s diff --git a/test/idl/ok/test.js.ok b/test/idl/ok/test.js.ok index 8e2a1f185cf..dc13ef34670 100644 --- a/test/idl/ok/test.js.ok +++ b/test/idl/ok/test.js.ok @@ -1,22 +1,23 @@ +const IDL = require('IDL') const my_type = IDL.Nat const B = my_type const message = IDL.Obj({'25': B, '26': IDL.None, 'name': IDL.Text}) const broker = new IDL.ActorInterface({ 'find': - IDL.message(IDL.Obj({'name': IDL.Text}), + IDL.Message(IDL.Obj({'name': IDL.Text}), IDL.Obj({ '0': - new IDL.ActorInterface({'up': IDL.message(IDL.Obj({}), IDL.Obj({})), - 'current': IDL.message(IDL.Obj({}), IDL.Obj({'0': IDL.Nat}))}) + new IDL.ActorInterface({'up': IDL.Message(IDL.Obj({}), IDL.Obj({})), + 'current': IDL.Message(IDL.Obj({}), IDL.Obj({'0': IDL.Nat}))}) })) }) -const server = new IDL.ActorInterface({ +const actor_server = new IDL.ActorInterface({ 'addUser': - IDL.message(IDL.Obj({'name': IDL.Text, 'age': IDL.Nat8}), + IDL.Message(IDL.Obj({'name': IDL.Text, 'age': IDL.Nat8}), IDL.Obj({'id': IDL.Nat64})), 'userName': - IDL.message(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({'0': IDL.Text})), - 'userAge': IDL.message(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({'0': IDL.Nat8})), - 'deleteUser': IDL.message(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({})), - 'f': IDL.message(IDL.Obj({'0': message}), IDL.Obj({'0': broker}))}) + IDL.Message(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({'0': IDL.Text})), + 'userAge': IDL.Message(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({'0': IDL.Nat8})), + 'deleteUser': IDL.Message(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({})), + 'f': IDL.Message(IDL.Obj({'0': message}), IDL.Obj({'0': broker}))}) diff --git a/test/idl/ok/unicode.js.ok b/test/idl/ok/unicode.js.ok index 6660ac1ac96..47b5d653c9c 100644 --- a/test/idl/ok/unicode.js.ok +++ b/test/idl/ok/unicode.js.ok @@ -1,11 +1,12 @@ +const IDL = require('IDL') const A = IDL.Obj({'📦🍦': IDL.Nat, '字段名': IDL.Nat, '字 段 名2': IDL.Nat }) const B = IDL.Variant({'': IDL.Unit, '空的': IDL.Unit, ' 空的 ': IDL.Unit, '1⃣️2⃣️3⃣️': IDL.Unit}) -const C = new IDL.ActorInterface({ - '函数名': IDL.message(IDL.Obj({'0': A}), IDL.Obj({'0': B})), - '': IDL.message(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': IDL.Nat})), - '👀': IDL.message(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': IDL.Nat})), - '✈️ 🚗 ⛱️ ': IDL.message(IDL.Obj({}), IDL.Obj({}))}) +const actor_C = new IDL.ActorInterface({ + '函数名': IDL.Message(IDL.Obj({'0': A}), IDL.Obj({'0': B})), + '': IDL.Message(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': IDL.Nat})), + '👀': IDL.Message(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': IDL.Nat})), + '✈️ 🚗 ⛱️ ': IDL.Message(IDL.Obj({}), IDL.Obj({}))}) diff --git a/test/run.sh b/test/run.sh index 627ccef2afe..3a98ad4b2dd 100755 --- a/test/run.sh +++ b/test/run.sh @@ -25,6 +25,8 @@ DIDC=${DIDC:-$(realpath $(dirname $0)/../src/didc)} export AS_LD WASM=${WASM:-wasm} DVM_WRAPPER=$(realpath $(dirname $0)/dvm.sh) +JSCLIENT=${JSCLIENT:-$(realpath $(dirname $0)/../../dev/experimental/js-dfinity-client)} +NODE=node ECHO=echo while getopts "ads" o; do @@ -227,6 +229,14 @@ do $ECHO -n " [js]" $DIDC --js $base.did > $out/$base.js 2>&1 diff_files="$diff_files $base.js" + + if [ -e $out/$base.js ] + then + $ECHO -n " [node]" + export NODE_PATH=$NODE_PATH:$JSCLIENT/node_modules:$JSCLIENT/src + $NODE $out/$base.js > $out/$base.err 2>&1 + diff_files="$diff_files $base.err" + fi fi fi $ECHO "" From 285c2571f79faf0bcba44acdaa64ade81cce6620 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Mon, 15 Jul 2019 15:22:01 -0700 Subject: [PATCH 0274/1176] manual sync with master --- default.nix | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/default.nix b/default.nix index 3436bb7bd70..d2b33aa9122 100644 --- a/default.nix +++ b/default.nix @@ -52,7 +52,6 @@ let commonBuildInputs = [ nixpkgs.ocaml nixpkgs.dune nixpkgs.ocamlPackages.atdgen - nixpkgs.ocamlPackages.base nixpkgs.ocamlPackages.findlib nixpkgs.ocamlPackages.menhir nixpkgs.ocamlPackages.num @@ -261,7 +260,7 @@ rec { didc = stdenv.mkDerivation { name = "didc"; src = subpath ./src; - buildInputs = [ commonBuildInputs ]; + buildInputs = commonBuildInputs; buildPhase = '' make DUNE_OPTS="--display=short --profile release" didc ''; From fd1205e0c85f17fc195447ea0ed527e8d5094c97 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Mon, 15 Jul 2019 15:34:43 -0700 Subject: [PATCH 0275/1176] add IDL to quick.mk --- test/quick.mk | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/quick.mk b/test/quick.mk index 9163100f733..50ebab5d391 100644 --- a/test/quick.mk +++ b/test/quick.mk @@ -4,6 +4,7 @@ TO-TEST = \ $(patsubst %.as,_out/%.done,$(wildcard *.as)) \ $(patsubst %.sh,_out/%.done,$(wildcard *.sh)) \ $(patsubst %.wat,_out/%.done,$(wildcard *.wat)) \ + $(patsubst %.did,_out/%.done,$(wildcard *.did)) \ .PHONY: quick @@ -20,3 +21,5 @@ _out/%.done: %.sh $(wildcard ../../src/asc) ../run.sh | _out @+ (../run.sh $(RUNFLAGS) $< > $@.tmp && mv $@.tmp $@) || (cat $@.tmp; rm -f $@.tmp; false) _out/%.done: %.wat $(wildcard ../../src/asc) ../run.sh | _out @+ (../run.sh $(RUNFLAGS) $< > $@.tmp && mv $@.tmp $@) || (cat $@.tmp; rm -f $@.tmp; false) +_out/%.done: %.did $(wildcard ../../src/didc) ../run.sh | _out + @+ (../run.sh $(RUNFLAGS) $< > $@.tmp && mv $@.tmp $@) || (cat $@.tmp; rm -f $@.tmp; false) From 66c36431bfadb2dc42c348e515929a28fb1155f6 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Mon, 15 Jul 2019 15:49:54 -0700 Subject: [PATCH 0276/1176] try fix nix --- default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/default.nix b/default.nix index d2b33aa9122..00e328a3f27 100644 --- a/default.nix +++ b/default.nix @@ -145,6 +145,7 @@ rec { nixpkgs.wabt nixpkgs.bash nixpkgs.perl + nixpkgs.nodejs-10_x filecheck js-client ] ++ From a9e5eead7d90b5599785c68e932f14bca027df1e Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Mon, 15 Jul 2019 16:03:54 -0700 Subject: [PATCH 0277/1176] minor fix --- src/idllib/compile_js.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/idllib/compile_js.ml b/src/idllib/compile_js.ml index 576018e6a59..4e774298869 100644 --- a/src/idllib/compile_js.ml +++ b/src/idllib/compile_js.ml @@ -172,9 +172,9 @@ let pp_actor ppf actor = pp_open_hovbox ppf 1; kwd ppf "const"; (match actor.it with - | ActorD (x, {it=t; _}) -> + | ActorD (x, t) -> let x = ("actor_" ^ x.it) @@ x.at in - match t with + match t.it with | ServT tp -> id ppf x; space ppf (); kwd ppf "="; kwd ppf "new"; str ppf "IDL.ActorInterface({"; From c39c66b880785f6e322f3c7593b6a5c3f6878e7c Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 16 Jul 2019 10:10:28 +0200 Subject: [PATCH 0278/1176] Minor cleanup in the nix files but does not yet include https://github.com/dfinity-lab/dev/pull/1101, I was hoping to get that into `master` first. --- default.nix | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/default.nix b/default.nix index 00e328a3f27..08aea1044df 100644 --- a/default.nix +++ b/default.nix @@ -24,29 +24,22 @@ let ocaml_vlq = import ./nix/ocaml-vlq.nix { let ocaml_bisect_ppx = import ./nix/ocaml-bisect_ppx.nix nixpkgs; in let ocaml_bisect_ppx-ocamlbuild = import ./nix/ocaml-bisect_ppx-ocamlbuild.nix nixpkgs; in +let dev = import (builtins.fetchGit { + url = "ssh://git@github.com/dfinity-lab/dev"; + ref = "master"; + rev = "65c295edfc4164ca89c129d501a403fa246d3d36"; +}) { system = nixpkgs.system; }; in + # Include dvm let real-dvm = if dvm == null - then - if test-dvm - then - let dev = builtins.fetchGit { - url = "ssh://git@github.com/dfinity-lab/dev"; - ref = "master"; - rev = "65c295edfc4164ca89c129d501a403fa246d3d36"; - }; in - (import dev { system = nixpkgs.system; }).dvm + then if test-dvm + then dev.dvm else null else dvm; in # Include js-client -let js-client = - let dev = builtins.fetchGit { - url = "ssh://git@github.com/dfinity-lab/dev"; - ref = "master"; - rev = "a556b011d957d3174b6c4017d76dd510791d8922"; - }; in - (import dev { system = nixpkgs.system; }).js-dfinity-client; in +let js-client = dev.js-dfinity-client; in let commonBuildInputs = [ nixpkgs.ocaml @@ -145,7 +138,7 @@ rec { nixpkgs.wabt nixpkgs.bash nixpkgs.perl - nixpkgs.nodejs-10_x + nixpkgs.nodejs-10_x filecheck js-client ] ++ From 002fc13164ffffd7a4be8f62e99a461320dcc2de Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Tue, 16 Jul 2019 10:58:07 -0700 Subject: [PATCH 0279/1176] fix nix --- default.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/default.nix b/default.nix index 08aea1044df..471e1ee9d2f 100644 --- a/default.nix +++ b/default.nix @@ -7,7 +7,6 @@ let llvm = import ./nix/llvm.nix { system = nixpkgs.system; }; in let stdenv = nixpkgs.stdenv; in -let lib = stdenv.lib; in let subpath = p: import ./nix/gitSource.nix p; in @@ -27,7 +26,7 @@ let ocaml_bisect_ppx-ocamlbuild = import ./nix/ocaml-bisect_ppx-ocamlbuild.nix n let dev = import (builtins.fetchGit { url = "ssh://git@github.com/dfinity-lab/dev"; ref = "master"; - rev = "65c295edfc4164ca89c129d501a403fa246d3d36"; + rev = "fcd387ce757fcc1ee697a19665ada9bc3f453adc"; }) { system = nixpkgs.system; }; in # Include dvm @@ -138,6 +137,7 @@ rec { nixpkgs.wabt nixpkgs.bash nixpkgs.perl + nixpkgs.getconf nixpkgs.nodejs-10_x filecheck js-client From 653dbc4c283996cb94c39b4c8ef25cb28ed8cef0 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Tue, 16 Jul 2019 00:00:40 +0200 Subject: [PATCH 0280/1176] Refactor wrapping codegen for Word8/16/32 mul and pow (#571) * factor out Word<64 `mul` and `pow` * remove `rec` marker from `compile_binop` * move `compile_word_mul`, `compile_word_power` to `UnboxedSmallWord` --- src/codegen/compile.ml | 67 +++++++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 30 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 427873b5a26..66ceea44434 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -1434,6 +1434,33 @@ module UnboxedSmallWord = struct let lit env ty v = compile_unboxed_const Int32.(shift_left (of_int v) (to_int (shift_of_type ty))) + (* Wrapping implementation for multiplication and exponentiation. *) + + let compile_word_mul env ty = + lsb_adjust ty ^^ + G.i (Binary (Wasm.Values.I32 I32Op.Mul)) + + let compile_word_power env ty = + let rec pow () = Func.share_code2 env (name_of_type ty "pow") + (("n", I32Type), ("exp", I32Type)) [I32Type] + Wasm.Values.(fun env get_n get_exp -> + let one = compile_unboxed_const (const_of_type ty 1l) in + let (set_res, get_res) = new_local env "res" in + let mul = compile_word_mul env ty in + let square_recurse_with_shifted sanitize = + get_n ^^ get_exp ^^ compile_shrU_const 1l ^^ sanitize ^^ + pow () ^^ set_res ^^ get_res ^^ get_res ^^ mul + in get_exp ^^ G.i (Test (I32 I32Op.Eqz)) ^^ + G.if_ (ValBlockType (Some I32Type)) + one + (get_exp ^^ one ^^ G.i (Binary (I32 I32Op.And)) ^^ G.i (Test (I32 I32Op.Eqz)) ^^ + G.if_ (ValBlockType (Some I32Type)) + (square_recurse_with_shifted G.nop) + (get_n ^^ + square_recurse_with_shifted (sanitize_word_result ty) ^^ + mul))) + in pow () + end (* UnboxedSmallWord *) type comparator = Lt | Le | Ge | Gt @@ -4825,7 +4852,7 @@ let compile_smallNat_kernel env ty name op = compile_smallNat_kernel' env ty name (G.i (Binary (Wasm.Values.I32 op))) (* The first returned StackRep is for the arguments (expected), the second for the results (produced) *) -let rec compile_binop env t op = +let compile_binop env t op = if t = Type.Non then SR.Vanilla, SR.Unreachable, G.i Unreachable else StackRep.of_type t, StackRep.of_type t, @@ -4879,8 +4906,7 @@ let rec compile_binop env t op = | Type.(Prim (Int8|Int16 as ty)), SubOp -> compile_smallInt_kernel env ty "sub" I32Op.Sub | Type.(Prim Nat32), SubOp -> compile_Nat32_kernel env "sub" I64Op.Sub | Type.(Prim (Nat8|Nat16 as ty)), SubOp -> compile_smallNat_kernel env ty "sub" I32Op.Sub - | Type.(Prim (Word8|Word16|Word32 as ty)), MulOp -> UnboxedSmallWord.lsb_adjust ty ^^ - G.i (Binary (Wasm.Values.I32 I32Op.Mul)) + | Type.(Prim (Word8|Word16|Word32 as ty)), MulOp -> UnboxedSmallWord.compile_word_mul env ty | Type.(Prim Int32), MulOp -> compile_Int32_kernel env "mul" I64Op.Mul | Type.(Prim Int16), MulOp -> compile_smallInt_kernel env Type.Int16 "mul" I32Op.Mul | Type.(Prim Int8), MulOp -> compile_smallInt_kernel' env Type.Int8 "mul" @@ -4911,26 +4937,7 @@ let rec compile_binop env t op = end get_res) | Type.(Prim (Int8|Int16|Int32)), ModOp -> G.i (Binary (Wasm.Values.I32 I32Op.RemS)) - | Type.(Prim (Word8|Word16|Word32 as ty)), PowOp -> - let rec pow () = Func.share_code2 env (UnboxedSmallWord.name_of_type ty "pow") - (("n", I32Type), ("exp", I32Type)) [I32Type] - Wasm.Values.(fun env get_n get_exp -> - let one = compile_unboxed_const (UnboxedSmallWord.const_of_type ty 1l) in - let (set_res, get_res) = new_local env "res" in - let _,_,mul = compile_binop env t MulOp in - let square_recurse_with_shifted sanitize = - get_n ^^ get_exp ^^ compile_shrU_const 1l ^^ sanitize ^^ - pow () ^^ set_res ^^ get_res ^^ get_res ^^ mul - in get_exp ^^ G.i (Test (I32 I32Op.Eqz)) ^^ - G.if_ (StackRep.to_block_type env SR.UnboxedWord32) - one - (get_exp ^^ one ^^ G.i (Binary (I32 I32Op.And)) ^^ G.i (Test (I32 I32Op.Eqz)) ^^ - G.if_ (StackRep.to_block_type env SR.UnboxedWord32) - (square_recurse_with_shifted G.nop) - (get_n ^^ - square_recurse_with_shifted (UnboxedSmallWord.sanitize_word_result ty) ^^ - mul))) - in pow () + | Type.(Prim (Word8|Word16|Word32 as ty)), PowOp -> UnboxedSmallWord.compile_word_power env ty | Type.(Prim ((Nat8|Nat16) as ty)), PowOp -> Func.share_code2 env (UnboxedSmallWord.name_of_type ty "pow") (("n", I32Type), ("exp", I32Type)) [I32Type] @@ -4949,8 +4956,8 @@ let rec compile_binop env t op = G.i (Compare (Wasm.Values.I32 I32Op.LtS)) ^^ then_arithmetic_overflow env ^^ get_n ^^ UnboxedSmallWord.lsb_adjust ty ^^ get_exp ^^ UnboxedSmallWord.lsb_adjust ty ^^ - let _,_,pow = compile_binop env Type.(Prim Word32) PowOp in pow ^^ - set_res ^^ get_res ^^ enforce_unsigned_bits env bits ^^ + UnboxedSmallWord.compile_word_power env Type.Word32 ^^ set_res ^^ + get_res ^^ enforce_unsigned_bits env bits ^^ get_res ^^ UnboxedSmallWord.msb_adjust ty end get_n (* n@{0,1} ** (1+exp) == n *) @@ -4976,7 +4983,7 @@ let rec compile_binop env t op = G.i (Compare (Wasm.Values.I32 I32Op.LtS)) ^^ then_arithmetic_overflow env ^^ get_n ^^ G.i (Convert (Wasm.Values.I64 I64Op.ExtendUI32)) ^^ get_exp ^^ G.i (Convert (Wasm.Values.I64 I64Op.ExtendUI32)) ^^ - let _,_,pow = compile_binop env Type.(Prim Word64) PowOp in pow ^^ + BoxedWord64.compile_unsigned_pow env ^^ set_res ^^ get_res ^^ enforce_32_unsigned_bits env ^^ get_res ^^ G.i (Convert (Wasm.Values.I32 I32Op.WrapI64)) end @@ -5003,7 +5010,7 @@ let rec compile_binop env t op = G.i (Compare (Wasm.Values.I32 I32Op.LtS)) ^^ then_arithmetic_overflow env ^^ get_n ^^ UnboxedSmallWord.lsb_adjust ty ^^ get_exp ^^ UnboxedSmallWord.lsb_adjust ty ^^ - (let _,_,pow = compile_binop env Type.(Prim Word32) PowOp in pow) ^^ + UnboxedSmallWord.compile_word_power env Type.Word32 ^^ set_res ^^ get_res ^^ get_res ^^ enforce_signed_bits env bits ^^ get_res ^^ UnboxedSmallWord.msb_adjust ty end @@ -5046,7 +5053,7 @@ let rec compile_binop env t op = G.i (Compare (Wasm.Values.I32 I32Op.LtS)) ^^ then_arithmetic_overflow env ^^ get_n ^^ G.i (Convert (Wasm.Values.I64 I64Op.ExtendSI32)) ^^ get_exp ^^ G.i (Convert (Wasm.Values.I64 I64Op.ExtendSI32)) ^^ - (let _,_,pow = compile_binop env Type.(Prim Word64) PowOp in pow) ^^ + BoxedWord64.compile_unsigned_pow env ^^ set_res ^^ get_res ^^ get_res ^^ enforce_32_signed_bits env ^^ get_res ^^ G.i (Convert (Wasm.Values.I32 I32Op.WrapI64)) end @@ -5070,11 +5077,11 @@ let rec compile_binop env t op = get_exp ^^ compile_Int64_kernel env "pow" BigNum.compile_unsigned_pow - (powInt64_shortcut (let _,_,pow = compile_binop env Type.(Prim Word64) PowOp in pow)) + (powInt64_shortcut (BoxedWord64.compile_unsigned_pow env)) | Type.(Prim Nat64), PowOp -> compile_Nat64_kernel env "pow" BigNum.compile_unsigned_pow - (powNat64_shortcut (let _,_,pow = compile_binop env Type.(Prim Word64) PowOp in pow)) + (powNat64_shortcut (BoxedWord64.compile_unsigned_pow env)) | Type.(Prim Nat), PowOp -> BigNum.compile_unsigned_pow env | Type.(Prim Word64), AndOp -> G.i (Binary (Wasm.Values.I64 I64Op.And)) | Type.Prim Type.(Word8 | Word16 | Word32), AndOp -> G.i (Binary (Wasm.Values.I32 I32Op.And)) From d235af83ddf13f551dd761ac083063318c627488 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 16 Jul 2019 11:15:41 +0200 Subject: [PATCH 0281/1176] Claudio/f bounds (#552) * manually port tests from PR #523 * manually port tests from PR #523 * more realistic use of f-bounded polymorphism * add newline at end * manually merge check_ir.ml from PR #523 to support f-bounds; restore rejection of open type definitions; update test output that has changed; adapt f-bounds.as to work sans open type definitions * add f-bounds-fail negative test * manually port f-bounds-fail.as test from PR #523 to test f-bounds; adapt test to avoid open type definitions * update comments; typos * Apply suggestions from code review Co-Authored-By: Andreas Rossberg * update tests --- src/as_frontend/typing.ml | 65 ++++++---- src/ir_def/check_ir.ml | 86 +++++++------- test/fail/f-bounds-fail.as | 87 ++++++++++++++ test/fail/ok/abstract-msgs.tc.ok | 20 ++-- test/fail/ok/asyncret1.tc.ok | 2 +- test/fail/ok/f-bounds-fail.tc.ok | 176 ++++++++++++++++++++++++++++ test/fail/ok/issue167.tc.ok | 1 - test/fail/ok/modexp5.tc.ok | 2 +- test/fail/ok/pat-inconsistent.tc.ok | 2 +- test/run/f-bounds.as | 87 ++++++++++++++ test/run/ott-typeclasses.as | 69 +++++++++++ test/run/self-bounds.as | 7 ++ 12 files changed, 522 insertions(+), 82 deletions(-) create mode 100644 test/fail/f-bounds-fail.as create mode 100644 test/fail/ok/f-bounds-fail.tc.ok create mode 100644 test/run/f-bounds.as create mode 100644 test/run/ott-typeclasses.as create mode 100644 test/run/self-bounds.as diff --git a/src/as_frontend/typing.ml b/src/as_frontend/typing.ml index b893cff7216..709e55ea22e 100644 --- a/src/as_frontend/typing.ml +++ b/src/as_frontend/typing.ml @@ -175,8 +175,10 @@ and check_typ' env typ : T.typ = match typ.it with | PathT (path, typs) -> let c = check_typ_path env path in + let ts = List.map (check_typ env) typs in let T.Def (tbs, _) | T.Abs (tbs, _) = Con.kind c in - let ts = check_typ_bounds env tbs typs typ.at in + let tbs' = List.map (fun {T.var; T.bound} -> {T.var; bound = T.open_ ts bound}) tbs in + check_typ_bounds env tbs' ts typs typ.at; T.Con (c, ts) | PrimT "Any" -> T.Any | PrimT "None" -> T.Non @@ -253,8 +255,13 @@ and check_typ_tag env typ_tag = T.{lab = tag.it; typ = t} and check_typ_binds env typ_binds : T.con list * T.typ list * Scope.typ_env * Scope.con_env = + (* TODO: rule out cyclic bounds *) let xs = List.map (fun typ_bind -> typ_bind.it.var.it) typ_binds in - let cs = List.map (fun n -> Con.fresh n (T.Abs ([], T.Pre))) xs in + let cs = + List.map2 (fun x tb -> + match tb.note with + | Some c -> c + | None -> Con.fresh x (T.Abs ([], T.Pre))) xs typ_binds in let te = List.fold_left2 (fun te typ_bind c -> let id = typ_bind.it.var in if T.Env.mem id.it te then @@ -264,32 +271,42 @@ and check_typ_binds env typ_binds : T.con list * T.typ list * Scope.typ_env * Sc let pre_env' = add_typs {env with pre = true} xs cs in let ts = List.map (fun typ_bind -> check_typ pre_env' typ_bind.it.bound) typ_binds in let ks = List.map (fun t -> T.Abs ([], t)) ts in - List.iter2 T.set_kind cs ks; + List.iter2 (fun c k -> + match Con.kind c with + | T.Abs (_, T.Pre) -> T.set_kind c k + | k' -> assert (T.eq_kind k k') + ) cs ks; let env' = add_typs env xs cs in let _ = List.map (fun typ_bind -> check_typ env' typ_bind.it.bound) typ_binds in List.iter2 (fun typ_bind c -> typ_bind.note <- Some c) typ_binds cs; cs, ts, te, T.ConSet.of_list cs -and check_typ_bounds env (tbs : T.bind list) typs at : T.typ list = - match tbs, typs with - | tb::tbs', typ::typs' -> - let t = check_typ env typ in - if not env.pre then begin - if not (T.sub t tb.T.bound) then - local_error env typ.at - "type argument\n %s\ndoes not match parameter bound\n %s" - (T.string_of_typ_expand t) - (T.string_of_typ_expand tb.T.bound) - end; - let ts' = check_typ_bounds env tbs' typs' at in - t::ts' - | [], [] -> [] - | [], _ -> local_error env at "too many type arguments"; [] - | _, [] -> error env at "too few type arguments" +and check_typ_bounds env (tbs : T.bind list) (ts : T.typ list) typs at = + let pars = List.length tbs in + let args = List.length ts in + if pars > args then + error env at "too few type arguments"; + if pars < args then + error env at "too many type arguments"; + let rec go tbs' ts' typs' = + match tbs', ts', typs' with + | tb::tbs', t::ts', typ::typs' -> + if not env.pre then + let u = T.open_ ts tb.T.bound in + if not (T.sub t u) then + local_error env typ.at + "type argument\n %s\ndoes not match parameter bound\n %s" + (T.string_of_typ_expand t) + (T.string_of_typ_expand u); + go tbs' ts' typs' + | [], [], [] -> () + | _ -> assert false + in go tbs ts typs and check_inst_bounds env tbs typs at = - let tys = check_typ_bounds env tbs typs at in - tys + let ts = List.map (check_typ env) typs in + check_typ_bounds env tbs ts typs at; + ts (* Literals *) @@ -626,7 +643,7 @@ and infer_exp'' env exp : T.typ = error env exp1.at "expected function type, but expression produces type\n %s" (T.string_of_typ_expand t1) - in + in let ts = check_inst_bounds env tbs insts exp.at in let t_arg = T.open_ ts t_arg in let t_ret = T.open_ ts t_ret in @@ -1492,7 +1509,7 @@ and infer_dec_typdecs env dec : Scope.t = 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 + let tbs = List.map2 (fun c' t -> {T.var = Con.name c'; bound = T.close cs t}) cs ts in let k = T.Def (tbs, T.close cs t) in begin let is_typ_param c = @@ -1522,7 +1539,7 @@ and infer_dec_typdecs env dec : Scope.t = let self_typ = T.Con (c, List.map (fun c -> T.Con (c, [])) cs) in let env'' = add_val (adjoin_vals env' ve) self_id.it self_typ in let t = infer_obj env'' sort.it fields dec.at in - let tbs = List.map2 (fun c t -> {T.var = Con.name c; bound = T.close cs t}) cs ts in + let tbs = List.map2 (fun c' t -> {T.var = Con.name c'; bound = T.close cs t}) cs ts in let k = T.Def (tbs, T.close cs t) in Scope.{ empty with typ_env = T.Env.singleton id.it c; diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index ea47c5c6777..35c745847ae 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -5,20 +5,21 @@ open Source module T = Type module E = Ir_effect -(* TODO: remove DecE from syntax, replace by BlockE [dec] *) -(* TODO: check constraint matching supports recursive bounds *) - (* TODO: make note immutable, perhaps just using type abstraction *) (* TODO: - dereferencing is still implicit in the IR (see immut_typ below) - consider making it explicit as part of desugaring. - *) + dereferencing is still implicit in the IR (see immut_typ below); + consider making it explicit as part of desugaring. +*) (* TODO: enforce second-class nature of T.Mut? in check_typ *) + (* TODO: check escape of free mutables via actors *) -(* helpers *) +(* Helpers *) + let (==>) p q = not p || q + let typ = E.typ let immute_typ p = @@ -128,12 +129,18 @@ let rec check_typ env typ : unit = | T.Var (s, i) -> error env no_region "free type variable %s, index %i" s i | T.Con (c, typs) -> - begin match Con.kind c with - | T.Def (tbs, _) -> check_typ_bounds env tbs typs no_region (* TODO(Claudio): - check bodies of anonymous T.Defs since they won't get checked elsewhere *) - | T.Abs (tbs, _) -> - check env no_region (T.ConSet.mem c env.cons) "free type constructor %s" (Con.name c); - check_typ_bounds env tbs typs no_region + List.iter (check_typ env) typs; + begin + match Con.kind c with + | T.Def (tbs,_) -> + if not (T.ConSet.mem c env.cons) then + (* an anonymous recursive type, check its def but beware recursion + future: use a visited set *) + check_con {env with cons = T.ConSet.add c env.cons} c; + check_typ_bounds env tbs typs no_region + | T.Abs (tbs, _) -> + check env no_region (T.ConSet.mem c env.cons) "free type constructor"; + check_typ_bounds env tbs typs no_region end | T.Any -> () | T.Non -> () @@ -195,20 +202,15 @@ let rec check_typ env typ : unit = * "serialized type is not sharable:\n %s" (T.string_of_typ_expand typ) *) | T.Typ c -> - check env no_region (T.ConSet.mem c env.cons) "free type constructor %s" (Con.name c); - -(* -and check_kind env k = - let (binds,typ) = - match k with - | T.Abs(binds,typ) - | T.Def(binds,typ) -> (binds,typ) - in - let cs,ce = check_typ_binds env binds in - let ts = List.map (fun c -> T.Con(c,[])) cs in + check_con env c + +and check_con env c = + let env = {env with cons = T.ConSet.add c env.cons} in + let T.Abs (binds,typ) | T.Def (binds, typ) = Con.kind c in + let cs, ce = check_typ_binds env binds in + let ts = List.map (fun c -> T.Con (c, [])) cs in let env' = adjoin_cons env ce in - check_typ env' (T.open_ ts typ); -*) + check_typ env' (T.open_ ts typ) and check_typ_field env s typ_field : unit = let T.{lab; typ} = typ_field in @@ -224,7 +226,7 @@ and check_typ_field env s typ_field : unit = and check_typ_binds env typ_binds : T.con list * con_env = let ts = Type.open_binds typ_binds in - let cs = List.map (function T.Con (c, []) -> c | _ -> assert false) ts in + let cs = List.map (function T.Con (c, []) -> c | _ -> assert false) ts in let env' = add_typs env cs in let _ = List.map (fun typ_bind -> @@ -235,17 +237,21 @@ and check_typ_binds env typ_binds : T.con list * con_env = cs, T.ConSet.of_list cs and check_typ_bounds env (tbs : T.bind list) typs at : unit = - match tbs, typs with - | tb::tbs', typ::typs' -> - check_typ env typ; - check env at (T.sub typ tb.T.bound) - "type argument does not match parameter bound"; - check_typ_bounds env tbs' typs' at - | [], [] -> () - | [], _ -> error env at "too many type arguments" - | _, [] -> error env at "too few type arguments" + let pars = List.length tbs in + let args = List.length typs in + if pars < args then + error env at "too many type arguments"; + if pars > args then + error env at "too few type arguments"; + List.iter2 + (fun tb typ -> + check env at (T.sub typ (T.open_ typs tb.T.bound)) + "type argument does not match parameter bound") + tbs typs + and check_inst_bounds env tbs typs at = + List.iter (check_typ env) typs; check_typ_bounds env tbs typs at (* Literals *) @@ -721,15 +727,7 @@ and check_dec env dec = typ exp <: T.as_immut t0 | TypD c -> check (T.ConSet.mem c env.cons) "free type constructor"; - let (binds, typ) = - match Con.kind c with - | T.Abs (binds, typ) - | T.Def (binds, typ) -> (binds, typ) - in - let cs, ce = check_typ_binds env binds in - let ts = List.map (fun c -> T.Con (c, [])) cs in - let env' = adjoin_cons env ce in - check_typ env' (T.open_ ts typ) + check_con env c and check_decs env decs = List.iter (check_dec env) decs; diff --git a/test/fail/f-bounds-fail.as b/test/fail/f-bounds-fail.as new file mode 100644 index 00000000000..5d10485c67b --- /dev/null +++ b/test/fail/f-bounds-fail.as @@ -0,0 +1,87 @@ +type Cast< A <: B, B> = A -> B; + +let f = (func(x:Int):Nat = 0) : Cast; + +func f2a< A <: B, B> ( x : A ) : B = x; + +func f2b< B, A <: B> ( x : A ) : B = x; + +func f3a< A <: B, B /* <: C */ , C> ( x : A ) : C = x; +func f3b< B /* <: C */, A <: B, C> ( x : A ) : C = x; +func f3c< C, B /* <: C */, A <: B> ( x : A ) : C = x; + +type T1< A <: B, B /* <: C */, C> = Cast; +type T2< B /* <: C */, A <: B, C> = Cast; +type T3< C, B /* <: C */, A <: B> = Cast; + +func g< A <: B, B /* <: C */ , C> ( a : A, b : B, c: C, n:Int ) : C { + /* TODO: restore these tests once open type defintions are supported + type U0 = T1; + type U1 = T1; + type U2 = T1; + type U3 = T1; + type U4 = T1; + type U5 = T1; + type U6 = T1; + + type V0 = T2; + type V1 = T2; + type V2 = T2; + type V3 = T2; + type V4 = T2; + type V5 = T2; + type V6 = T2; + + type W0 = T3; + type W1 = T3; + type W2 = T3; + type W3 = T3; + type W4 = T3; + type W5 = T3; + type W6 = T3; + */ + + /* test type formation involving f-bounds */ + let u0 : T1 = (); + let u1 : T1 = (); + let u2 : T1 = (); + let u3 : T1 = (); + let u4 : T1 = (); + let u5 : T1 = (); + let u6 : T1 = (); + + let v0 : T2 = (); + let v1 : T2 = (); + let v2 : T2 = (); + let v3 : T2 = (); + let v4 : T2 = (); + let v5 : T2 = (); + let v6 : T2 = (); + + let w0 : T3 = (); + let w1 : T3 = (); + let w2 : T3 = (); + let w3 : T3 = (); + let w4 : T3 = (); + let w5 : T3 = (); + let w6 : T3 = (); + + switch n { + case 0 { g(a,a,a,n) }; + case 1 { g(a,b,b,n) }; + case 2 { g(a,b,c,n) }; + + case 3 { g(a,a,a,n) }; + case 4 { g(a,b,b,n) }; + case 5 { g(a,b,c,n) }; + case 6 { g(b,b,b,n) }; + case 7 { g(b,b,c,n) }; + + case 8 { g(a,a,a,n) }; + case 9 { g(a,a,b,n) }; + case 10 { g(a,b,c,n) }; + case 11 { g(c,c,c,n) }; + case _ { c }; + } +}; + diff --git a/test/fail/ok/abstract-msgs.tc.ok b/test/fail/ok/abstract-msgs.tc.ok index 5358c1e7327..d62841c511e 100644 --- a/test/fail/ok/abstract-msgs.tc.ok +++ b/test/fail/ok/abstract-msgs.tc.ok @@ -1,20 +1,20 @@ abstract-msgs.as:2.28-2.37: type error, shared function has non-shared parameter type - A/19 + A/9 abstract-msgs.as:3.33-3.35: type error, shared function has non-async result type - ?A/21 + ?A/10 abstract-msgs.as:5.20-5.29: type error, shared function has non-shared parameter type - A/23 + A/11 abstract-msgs.as:6.31-6.33: type error, async has non-shared content type - ?A/23 + ?A/11 abstract-msgs.as:10.34-10.35: type error, shared function has non-shared parameter type - A/25 + A/12 abstract-msgs.as:11.46-11.47: type error, async has non-shared content type - A/27 + A/13 abstract-msgs.as:14.30-14.31: type error, shared function has non-shared parameter type - A/29 + A/14 abstract-msgs.as:15.42-15.43: type error, async has non-shared content type - A/31 + A/15 abstract-msgs.as:16.31-16.32: type error, shared function has non-shared parameter type - A/33 + A/16 abstract-msgs.as:17.43-17.44: type error, async has non-shared content type - A/35 + A/17 diff --git a/test/fail/ok/asyncret1.tc.ok b/test/fail/ok/asyncret1.tc.ok index ca6952b3eaa..2879cd8331c 100644 --- a/test/fail/ok/asyncret1.tc.ok +++ b/test/fail/ok/asyncret1.tc.ok @@ -1,2 +1,2 @@ asyncret1.as:1.39-1.40: type error, shared function has non-async result type - C/1 + C diff --git a/test/fail/ok/f-bounds-fail.tc.ok b/test/fail/ok/f-bounds-fail.tc.ok new file mode 100644 index 00000000000..ff8436a1726 --- /dev/null +++ b/test/fail/ok/f-bounds-fail.tc.ok @@ -0,0 +1,176 @@ +f-bounds-fail.as:13.42-13.43: type error, type argument + A/10 +does not match parameter bound + C +f-bounds-fail.as:14.42-14.43: type error, type argument + A/11 +does not match parameter bound + C/1 +f-bounds-fail.as:15.42-15.43: type error, type argument + A/12 +does not match parameter bound + C/2 +f-bounds-fail.as:3.38-3.41: type error, type argument + Int +does not match parameter bound + Nat +f-bounds-fail.as:9.53-9.54: type error, expression of type + A/19 +cannot produce expected type + C/6 +f-bounds-fail.as:10.52-10.53: type error, expression of type + A/20 +cannot produce expected type + C/7 +f-bounds-fail.as:11.52-11.53: type error, expression of type + A/21 +cannot produce expected type + C/8 +f-bounds-fail.as:45.23-45.25: type error, expression of type + () +cannot produce expected type + A/22 -> A/22 +f-bounds-fail.as:46.23-46.25: type error, expression of type + () +cannot produce expected type + A/22 -> B/13 +f-bounds-fail.as:47.23-47.25: type error, expression of type + () +cannot produce expected type + A/22 -> B/13 +f-bounds-fail.as:48.23-48.25: type error, expression of type + () +cannot produce expected type + B/13 -> B/13 +f-bounds-fail.as:49.23-49.25: type error, expression of type + () +cannot produce expected type + B/13 -> C/9 +f-bounds-fail.as:50.14-50.15: type error, type argument + B/13 +does not match parameter bound + C/9 +f-bounds-fail.as:50.23-50.25: type error, expression of type + () +cannot produce expected type + B/13 -> C/9 +f-bounds-fail.as:51.23-51.25: type error, expression of type + () +cannot produce expected type + C/9 -> C/9 +f-bounds-fail.as:53.23-53.25: type error, expression of type + () +cannot produce expected type + A/22 -> A/22 +f-bounds-fail.as:54.23-54.25: type error, expression of type + () +cannot produce expected type + A/22 -> B/13 +f-bounds-fail.as:55.23-55.25: type error, expression of type + () +cannot produce expected type + A/22 -> B/13 +f-bounds-fail.as:56.23-56.25: type error, expression of type + () +cannot produce expected type + B/13 -> B/13 +f-bounds-fail.as:57.23-57.25: type error, expression of type + () +cannot produce expected type + B/13 -> C/9 +f-bounds-fail.as:58.16-58.17: type error, type argument + B/13 +does not match parameter bound + C/9 +f-bounds-fail.as:58.23-58.25: type error, expression of type + () +cannot produce expected type + B/13 -> C/9 +f-bounds-fail.as:59.23-59.25: type error, expression of type + () +cannot produce expected type + C/9 -> C/9 +f-bounds-fail.as:61.23-61.25: type error, expression of type + () +cannot produce expected type + A/22 -> A/22 +f-bounds-fail.as:62.23-62.25: type error, expression of type + () +cannot produce expected type + A/22 -> B/13 +f-bounds-fail.as:63.23-63.25: type error, expression of type + () +cannot produce expected type + A/22 -> B/13 +f-bounds-fail.as:64.23-64.25: type error, expression of type + () +cannot produce expected type + B/13 -> B/13 +f-bounds-fail.as:65.23-65.25: type error, expression of type + () +cannot produce expected type + B/13 -> C/9 +f-bounds-fail.as:66.18-66.19: type error, type argument + B/13 +does not match parameter bound + C/9 +f-bounds-fail.as:66.23-66.25: type error, expression of type + () +cannot produce expected type + B/13 -> C/9 +f-bounds-fail.as:67.23-67.25: type error, expression of type + () +cannot produce expected type + C/9 -> C/9 +f-bounds-fail.as:70.27-70.28: type error, expression of type + A/22 +cannot produce expected type + C/9 +f-bounds-fail.as:71.27-71.28: type error, expression of type + B/13 +cannot produce expected type + C/9 +f-bounds-fail.as:74.27-74.28: type error, expression of type + A/22 +cannot produce expected type + C/9 +f-bounds-fail.as:75.27-75.28: type error, expression of type + B/13 +cannot produce expected type + C/9 +f-bounds-fail.as:77.27-77.28: type error, expression of type + B/13 +cannot produce expected type + C/9 +f-bounds-fail.as:80.23-80.24: type error, expression of type + A/22 +cannot produce expected type + C/9 +f-bounds-fail.as:80.25-80.26: type error, expression of type + A/22 +cannot produce expected type + C/9 +f-bounds-fail.as:80.27-80.28: type error, expression of type + A/22 +cannot produce expected type + C/9 +f-bounds-fail.as:81.23-81.24: type error, expression of type + A/22 +cannot produce expected type + C/9 +f-bounds-fail.as:81.25-81.26: type error, expression of type + A/22 +cannot produce expected type + C/9 +f-bounds-fail.as:81.27-81.28: type error, expression of type + B/13 +cannot produce expected type + C/9 +f-bounds-fail.as:82.24-82.25: type error, expression of type + A/22 +cannot produce expected type + C/9 +f-bounds-fail.as:82.26-82.27: type error, expression of type + B/13 +cannot produce expected type + C/9 diff --git a/test/fail/ok/issue167.tc.ok b/test/fail/ok/issue167.tc.ok index bee902a2a10..d4f77135651 100644 --- a/test/fail/ok/issue167.tc.ok +++ b/test/fail/ok/issue167.tc.ok @@ -1,2 +1 @@ issue167.as:1.13-1.19: type error, too many type arguments -issue167.as:1.13-1.19: type error, too many type arguments diff --git a/test/fail/ok/modexp5.tc.ok b/test/fail/ok/modexp5.tc.ok index 079888d23b3..35aaf210788 100644 --- a/test/fail/ok/modexp5.tc.ok +++ b/test/fail/ok/modexp5.tc.ok @@ -1 +1 @@ -modexp5.as:6.20-6.30: type error, type definition U = T/24 references type parameter(s) T/24 from an outer scope +modexp5.as:6.20-6.30: type error, type definition U = T/15 references type parameter(s) T/15 from an outer scope diff --git a/test/fail/ok/pat-inconsistent.tc.ok b/test/fail/ok/pat-inconsistent.tc.ok index 3a02fd6bf1e..2f6bdb9c9af 100644 --- a/test/fail/ok/pat-inconsistent.tc.ok +++ b/test/fail/ok/pat-inconsistent.tc.ok @@ -100,7 +100,7 @@ pat-inconsistent.as:32.19-32.32: type error, pattern branches have incompatible left consumes Text right consumes - A/18 + A/9 pat-inconsistent.as:33.16-33.40: type error, pattern branches have incompatible types, left consumes Any diff --git a/test/run/f-bounds.as b/test/run/f-bounds.as new file mode 100644 index 00000000000..321d2bdc3f0 --- /dev/null +++ b/test/run/f-bounds.as @@ -0,0 +1,87 @@ +type Cast< A <: B, B> = A -> B; + +let f = (func(x :Nat):Int = x) : Cast; + +func f2a< A <: B, B> ( x : A ) : B = x; + +func f2b< B, A <: B> ( x : A ) : B = x; + +func f3a< A <: B, B <: C , C> ( x : A ) : C = x; +func f3b< B <: C, A <: B, C> ( x : A ) : C = x; +func f3c< C, B <: C, A <: B> ( x : A ) : C = x; + +type T1< A <: B, B <: C, C> = Any; +type T2< B <: C, A <: B, C> = Any; +type T3< C, B <: C, A <: B> = Any; + +func g< A <: B, B <: C , C> ( a : A, b : B, c: C, n:Int ) : C { + + /* TODO: restore these tests once open type defintions are supported + type U0 = T1; + type U1 = T1; + type U2 = T1; + type U3 = T1; + type U4 = T1; + type U5 = T1; + type U6 = T1; + + type V0 = T2; + type V1 = T2; + type V2 = T2; + type V3 = T2; + type V4 = T2; + type V5 = T2; + type V6 = T2; + + type W0 = T3; + type W1 = T3; + type W2 = T3; + type W3 = T3; + type W4 = T3; + type W5 = T3; + type W6 = T3; + */ + + /* test type formation involving f-bounds */ + let u0 : T1 = (); + let u1 : T1 = (); + let u2 : T1 = (); + let u3 : T1 = (); + let u4 : T1 = (); + let u5 : T1 = (); + let u6 : T1 = (); + + let v0 : T2 = (); + let v1 : T2 = (); + let v2 : T2 = (); + let v3 : T2 = (); + let v4 : T2 = (); + let v5 : T2 = (); + let v6 : T2 = (); + + let w0 : T3 = (); + let w1 : T3 = (); + let w2 : T3 = (); + let w3 : T3 = (); + let w4 : T3 = (); + let w5 : T3 = (); + let w6 : T3 = (); + + switch n { + case 0 { g(a,a,a,n) }; + case 1 { g(a,b,b,n) }; + case 2 { g(a,b,c,n) }; + + case 3 { g(a,a,a,n) }; + case 4 { g(a,b,b,n) }; + case 5 { g(a,b,c,n) }; + case 6 { g(b,b,b,n) }; + case 7 { g(b,b,c,n) }; + + case 8 { g(a,a,a,n) }; + case 9 { g(a,a,b,n) }; + case 10 { g(a,b,c,n) }; + case 11 { g(c,c,c,n) }; + case _ { c }; + } +}; diff --git a/test/run/ott-typeclasses.as b/test/run/ott-typeclasses.as new file mode 100644 index 00000000000..f2009fc26ef --- /dev/null +++ b/test/run/ott-typeclasses.as @@ -0,0 +1,69 @@ +// test realistic f-bound polymorphism using a contrived implementation of type classes +// NB: it's contrived, because we don't need the dictionary *type* parameters + +type Eq = { + eq: (T,T) -> Bool +}; + +func equal, T>(w:W, t1 : T, t2 : T) : Bool = w.eq(t1, t2); + +type Order = { #LT; #EQ; #GT; }; + +type Ord = { + eq : (T,T) -> Bool; + cmp: (T,T) -> Order; +}; + +func compare, T>(w : W, t1 : T, t2 : T) : Order = w.cmp(t1,t2); + +object ordInt { + func eq(t1 : Int, t2:Int) : Bool = t1 == t2; + func cmp(t1 : Int, t2 : Int) : Order = + if (t1 < t2) #LT + else if (t1 > t2) #GT + else #EQ; +}; + +type List = ?(T,List); + +class OrdList, T>(w : W) = this { + func eq(ts1 : List, ts2: List) : Bool = + switch (cmp (ts1, ts2)) { + case (#EQ) true; + case _ false; + }; + + func cmp(ts1 : List, ts2: List) : Order = + switch (ts1, ts2) { + case (null, null) #EQ; + case (null, ? _) #LT; + case (?(t1, ts1), ?(t2, ts2)) { + switch (compare(w, t1, t2)) { + case (#EQ) (compare, List> (this, ts1, ts2)); + case other other; + } + }; + case (? _, null ) #GT; + } +}; + + + +assert(equal,Int>(ordInt, 0, 0)); + +assert(not (equal,Int>(ordInt, -1, 0))); + +type OLI = OrdList,Int>; +let oli = OrdList,Int>(ordInt); + +switch (compare>(oli, null, null)) +{ + case (#EQ) (); + case _ (assert false); +}; + +switch (compare>(oli, ?(1,null), null)) +{ + case (#GT) (); + case _ (assert false); +}; diff --git a/test/run/self-bounds.as b/test/run/self-bounds.as new file mode 100644 index 00000000000..c27ae53c41d --- /dev/null +++ b/test/run/self-bounds.as @@ -0,0 +1,7 @@ +type List> = (A,B); + +type List1> = (A,B); + +type List2> = (A,B); + +type List3,A,C> = (A,B); From 2eac465e88079575a826e07d1dad653fe1ed68ef Mon Sep 17 00:00:00 2001 From: Christoph Hegemann Date: Tue, 16 Jul 2019 13:53:32 +0200 Subject: [PATCH 0282/1176] Adds the PA parking service example (#565) * Adds the PA parking service example * retrigger ci --- samples/pa_cars.as | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 samples/pa_cars.as diff --git a/samples/pa_cars.as b/samples/pa_cars.as new file mode 100644 index 00000000000..946089ddfc3 --- /dev/null +++ b/samples/pa_cars.as @@ -0,0 +1,43 @@ +// Stateless Suspendable Workflow +// ============================== + +// Creating an Account for the PA parking service + +// - Client: Insert Car data and holder's name +// - Server: Validate car is registered under the given name +// - Client: Pick a parking spot from a Google Map like interface + time +// - Server: Register the parking spot for the user + +type Car = shared { model : Text; plate : Text }; +type DMV = actor { check : Car -> async CarInfo }; +type CarInfo = shared { + model : Text; + plate : Text; + isValid : Bool; + wasStolen : Bool; + expires : Nat; +}; + +actor class PACars(dmv : DMV) { + func verifyCarInformation(user : User, car : Car) : async ?(shared (Location, TimeSpan) -> async Result) { + let carInfo = await dmv.check(car); + if (carInfo.isValid and not carInfo.wasStolen) { + return ?(shared func (location, time) : async Result { + return reserveSpot(user, carInfo, location, time); + }) + } else { + return null; + } + }; + + private func reserveSpot(user : User, carInfo : CarInfo, location : Location, timeSpan : TimeSpan) : Result { + // Do the actual work of registering the parking spot for the + // given car in the given time span + return null; + }; + + type Location = shared { lat : Float; long : Float }; + type TimeSpan = shared { start : Int; end : Int }; + type Result = ?(shared { reservationId : Text }); + type User = shared { name : Text }; +}; From 698447d02204880e79ff1d8c9f43dbd073b4f6b8 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Tue, 16 Jul 2019 18:28:06 +0200 Subject: [PATCH 0283/1176] Invert public/private default (#570) --- design/Syntax.md | 16 +- guide/as-slides.md | 26 +-- guide/chat.as | 8 +- guide/guide.md | 69 ++++---- samples/ListClient.as | 8 +- samples/ListLib.as | 7 +- samples/app/client.as | 8 +- samples/app/list.as | 1 - samples/app/server.as | 18 +- samples/counter.as | 10 +- samples/modules.as | 9 +- samples/quicksort.as | 8 +- src/as_frontend/dune | 1 + src/as_frontend/lexer.mll | 1 + src/as_frontend/parser.mly | 71 ++++---- src/prelude/prelude.ml | 48 +++--- stdlib/assocList.as | 20 +-- stdlib/docTable.as | 63 +++---- .../examples/produce-exchange/profileActor.as | 2 +- .../examples/produce-exchange/serverActor.as | 126 +++++++------- .../examples/produce-exchange/serverLang.as | 20 +-- .../examples/produce-exchange/serverModel.as | 156 +++++++++--------- .../produce-exchange/serverModelTypes.as | 76 ++++----- .../examples/produce-exchange/serverTypes.as | 86 +++++----- .../test/simpleSetupAndQuery.as | 10 +- stdlib/hash.as | 46 +++--- stdlib/list.as | 62 +++---- stdlib/option.as | 32 ++-- stdlib/prelude.as | 6 +- stdlib/result.as | 28 ++-- stdlib/set.as | 28 ++-- stdlib/trie.as | 118 ++++++------- stdlib/trie2.as | 128 +++++++------- test/fail/actor-match.as | 8 +- test/fail/actor-reexport.as | 8 +- test/fail/ast81-clash.as | 2 +- test/fail/await-in-actor.as | 4 +- test/fail/const-var-field.as | 2 +- test/fail/duplicate-field.as | 6 +- test/fail/issue103.as | 4 +- test/fail/modexp1.as | 4 +- test/fail/modexp2.as | 10 +- test/fail/modexp3.as | 10 +- test/fail/modexp4.as | 12 +- test/fail/modules-fwd.as | 8 +- test/fail/modules-shadow.as | 5 +- test/fail/nested-class-rec-fail.as | 10 +- test/fail/object-patterns.as | 8 +- test/fail/objpat-duplicate.as | 2 +- test/fail/objpat-infer.as | 2 +- test/fail/ok/actor-reexport.tc.ok | 6 +- test/fail/ok/await-in-actor.tc.ok | 2 +- test/fail/ok/const-var-field.tc.ok | 2 +- test/fail/ok/duplicate-field.tc.ok | 2 +- test/fail/ok/nested-class-rec-fail.tc.ok | 2 +- test/fail/ok/object-patterns.tc.ok | 4 +- test/fail/ok/use-before-define6.tc.ok | 2 +- test/fail/use-before-define5.as | 2 +- test/fail/use-before-define6.as | 14 +- test/run-dfinity/AST-64.as | 8 +- test/run-dfinity/async-new-obj.as | 102 ++++++------ test/run-dfinity/async-obj-mut.as | 16 +- test/run-dfinity/chat.as | 14 +- test/run-dfinity/chatpp.as | 26 +-- test/run-dfinity/closure-params.as | 6 +- test/run-dfinity/counter-class.as | 6 +- test/run-dfinity/counter.as | 6 +- test/run-dfinity/counter2.as | 6 +- test/run-dfinity/data-params.as | 30 ++-- test/run-dfinity/flatten-awaitables.as | 32 ++-- test/run-dfinity/general-type-components.as | 24 +-- test/run-dfinity/hello-world-async.as | 4 +- test/run-dfinity/hello-world-await.as | 6 +- test/run-dfinity/hello-world-message.as | 2 +- test/run-dfinity/hello-world-message2.as | 2 +- test/run-dfinity/hello-world2.as | 2 +- test/run-dfinity/hello-world3.as | 6 +- test/run-dfinity/indirect-counter.as | 12 +- test/run-dfinity/modexp1.as | 6 +- test/run-dfinity/modexp2.as | 12 +- test/run-dfinity/modexp3.as | 12 +- test/run-dfinity/modexp4.as | 16 +- test/run-dfinity/modules-bwd.as | 6 +- test/run-dfinity/ok/data-params.run-ir.ok | 2 +- test/run-dfinity/ok/data-params.run-low.ok | 2 +- test/run-dfinity/ok/data-params.run.ok | 2 +- test/run-dfinity/ok/data-params.tc.ok | 2 +- .../run-dfinity/ok/data-params.wasm.stderr.ok | 2 +- test/run-dfinity/reference-params.as | 16 +- test/run-dfinity/show.as | 2 +- test/run-dfinity/transpose.as | 6 +- test/run/actors.as | 12 +- test/run/async-calls.as | 28 ++-- test/run/control.as | 18 +- test/run/coverage.as | 14 +- test/run/import-module.as | 2 +- test/run/ir-pat-subtype.as | 43 +++-- test/run/issue150.as | 4 +- test/run/lib/ListM.as | 7 +- test/run/module1.as | 32 ++-- test/run/module2.as | 4 +- test/run/module3.as | 5 +- test/run/mut-field-bound.as | 2 +- test/run/nested-class-rec.as | 6 +- test/run/nested-lexpr.as | 2 +- test/run/objects1.as | 18 +- test/run/objects2.as | 2 +- test/run/objects3.as | 2 +- test/run/objects4.as | 6 +- test/run/objects5.as | 4 +- test/run/ok/coverage.run-ir.ok | 10 +- test/run/ok/coverage.run-low.ok | 10 +- test/run/ok/coverage.run.ok | 10 +- test/run/ok/coverage.tc.ok | 10 +- test/run/ok/coverage.wasm.stderr.ok | 10 +- test/run/quicksort.as | 8 +- test/run/type-definition.as | 4 +- test/run/type-inclusion.as | 10 +- 118 files changed, 1067 insertions(+), 1069 deletions(-) diff --git a/design/Syntax.md b/design/Syntax.md index 59a34a55ca7..f015d8dccc1 100644 --- a/design/Syntax.md +++ b/design/Syntax.md @@ -7,12 +7,12 @@ Productions marked * probably deferred to later versions. ``` ::= type expressions ? constructor - (shared|actor)? { ;* } object + (actor|module|object)? { ;* } actor / module / object (default) { ;* } variant { # } empty variant [ var? ] array ? option - shared ? -> function + shared? ? -> function async future ( (( :)? ),* ) tuple Any top @@ -54,6 +54,7 @@ Productions marked * probably deferred to later versions. ( ,* ) tuple . tuple projection ? option injection + new { ;* } object . object projection # ? variant injection := assignment @@ -84,8 +85,7 @@ Productions marked * probably deferred to later versions. * try (catch )+ ( )? try ::= object expression fields - private? dec field - private? = short-hand + var? = field ``` ## Patterns @@ -113,12 +113,14 @@ Productions marked * probably deferred to later versions. expression let = immutable var (: )? = mutable - (new|object|actor) ? =? { ;* } object + (actor|module|object) ? =? { ;* } object shared? func ? ? (: )? =? function - type ? = type actor? class ? (: )? =? class - module ? =? { * } module + type ? = type import ? =? import + + ::= object declaration fields + (public|private)? dec field ``` ## Programs diff --git a/guide/as-slides.md b/guide/as-slides.md index 15172c23bac..206a4b5a081 100644 --- a/guide/as-slides.md +++ b/guide/as-slides.md @@ -228,7 +228,7 @@ AS distinguishes sharable types: * sharable (think serializable) objects have immutable fields of sharable type: ``` - { x = 0; color = Colors.Red } + new { x = 0; color = Colors.Red } ``` * full `object`s can be mutable, stateful @@ -236,8 +236,8 @@ AS distinguishes sharable types: ``` swift object { private var c = 0; - inc() { c += 1 }; - get() : Int { c } + public func inc() { c += 1 }; + public func get() : Int { c } } ``` @@ -252,8 +252,8 @@ Actors are restricted objects: ``` actor { private var c = 0; - inc() { c += 1 }; - get() : async Int { c } + public func inc() { c += 1 }; + public func get() : async Int { c } } ``` @@ -484,8 +484,8 @@ Classes as functions returning objects: ``` class Counter(init : Int) { private var state : Int = init; - inc() { state += 1; }; - get() : Int { state; }; + public func inc() { state += 1; }; + public func get() : Int { state; }; } ``` @@ -512,9 +512,9 @@ let ? name = d.find(1); ### Actor Declarations ``` -actor Server = { +actor Server { private shared func broadcast():(){...}; - subscribe(c : Client): async Post { + public func subscribe(c : Client): async Post { ... return broadcast; }; @@ -562,7 +562,7 @@ alice.start("Alice", Server); // async send as function call ### Chat Server ``` -actor Server = { +actor Server { private var clients : List = null; private shared broadcast(message : Text) { @@ -576,7 +576,7 @@ actor Server = { }; ``` ``` - subscribe(client : Client) : async Post { + public func subscribe(client : Client) : async Post { let cs = new {head = client; var tail = clients}; clients := ?cs; return broadcast; @@ -597,7 +597,7 @@ type Server = actor { subscribe : Client -> async Post; }; actor class Client() = this { private var name : Text = ""; - start(n : Text , s : Server) { + public func start(n : Text , s : Server) { name := n; let _ = async { let post = await s.subscribe(this); @@ -607,7 +607,7 @@ actor class Client() = this { }; ``` ``` - send(msg : Text) { + public func send(msg : Text) { print(name # " received " # msg # "\n"); }; }; diff --git a/guide/chat.as b/guide/chat.as index f92c49e8bd8..ba672f0b9a3 100644 --- a/guide/chat.as +++ b/guide/chat.as @@ -18,7 +18,7 @@ actor Server = { }; }; - func subscribe(client : Client) : async Post { + public func subscribe(client : Client) : async Post { let cs = new {head = client; var tail = clients}; clients := ?cs; return broadcast; @@ -29,7 +29,8 @@ type Server = actor { subscribe : Client -> async Post; }; actor class Client() = this { private var name : Text = ""; - start(n : Text , s : Server) { + + public func start(n : Text , s : Server) { name := n; let _ = async { let post = await s.subscribe(this); @@ -37,7 +38,8 @@ actor class Client() = this { post("goodbye from " # name); } }; - send(msg : Text) { + + public func send(msg : Text) { print(name # " received " # msg # "\n"); }; }; diff --git a/guide/guide.md b/guide/guide.md index 19d39f2272b..89ea93207c2 100644 --- a/guide/guide.md +++ b/guide/guide.md @@ -135,7 +135,7 @@ The following keywords are reserved and may not be used as identifiers: ```bnf actor and async assert await break case class continue else false for func if in new not null object or label let loop -private return shared switch true type var while +private public return shared switch true type var while ``` ## Identifiers @@ -660,6 +660,7 @@ A type `T` is *shared* if it is ( ,* ) tuple . tuple projection ? option injection + new { ;* } object . object projection := assignment = unary update @@ -687,9 +688,6 @@ A type `T` is *shared* if it is : type annotation dec declaration ( ) parentheses - - ::= function expression - ? (: )? =? function body ``` ## Identifiers @@ -758,6 +756,17 @@ The option expression `? ` has type `? T` provided `` has type `T`. The literal `null` has type `Null`. Since `Null <: ? T` for any `T`, literal `null` also has type `? T` and signifies the "missing" value at type `? T`. +## Objects + +Objects can be written in literal form `new { ;* }`, consisting of a list of expression fields: + +```bnf + ::= var? = +``` +Such an object literal is equivalent to the object declaration `object { ;* }` where the declaration fields are obtained from the expression fields by prefixing each of them with `public let`, or just `public` in case of `var` fields. + +_TBR can we delete `new`?_ + ## Object projection (Member access) The object projection ` . ` has type `var? T` provided `` has object type @@ -1188,16 +1197,15 @@ matching ``, if it succeeds, or the result of matching ``, if the fi expression let = immutable var (: )? = mutable - (new|object|actor) ? =? { ;* } object + (object|module|actor) ? =? { ;* } object shared? func ? ? (: )? =? function type ? = type obj_sort? class ? =? { ;* }` class ``` ```bnf - ::= object expression fields - private? field - private? = short-hand + ::= object declaration fields + (public|private)? field ``` ## Expression Declaration @@ -1252,9 +1260,10 @@ In scope of the declaration `type C < X0<:T0>, ..., Xn <: Tn > = U`, any well- ## Object Declaration -Declaration `(new|object|actor) ? =? { ;* }` declares an object with optional identifier `` and zero or more fields `;*`. +Declaration `(object|module|actor) ? =? { ;* }` declares an object with optional identifier `` and zero or more fields `;*`. +Fields can be declared with `public` or `private` visibility; if the visibility is omitted, it defaults to `private`. -The qualifier `new|object|actor` specifies the *sort* of the object's type (`new` is equivalent to `object`). The sort imposes restrictions on the types of the non-private object fields. +The qualifier `object|module|actor` specifies the *sort* of the object's type. The sort imposes restrictions on the types of the public object fields. Let `T = sort { [var0] id0 : T0, ... , [varn] idn : T0 }` denote the type of the object. Let `;*` be the sequence of declarations in `;*`. @@ -1262,7 +1271,7 @@ The object declaration has type `T` provided that: 1. type `T` is well-formed for sort `sort`, and 2. under the assumption that ` : T`, - * the sequence of declarations `;*` has type `Any` and declares the disjoint sets of private and non-private identifiers, `Id_private` and `Id_public` respectively, + * the sequence of declarations `;*` has type `Any` and declares the disjoint sets of private and public identifiers, `Id_private` and `Id_public` respectively, with types `T(id)` for `id` in `Id == Id_private union Id_public`, and * `{ id0, ..., idn } == Id_public`, and * for all `i in 0 <= i <= n`, `[vari] Ti == T(idi)`. @@ -1270,7 +1279,7 @@ The object declaration has type `T` provided that: Note that requirement 1. imposes further constraints on the fields type of `T`. In particular: -* if the sort is `actor` then all non-private fields must be non-`var` (immutable) `shared` functions (the public interface of an actor can only provide asynchronous messaging via shared functions). +* if the sort is `actor` then all public fields must be non-`var` (immutable) `shared` functions (the public interface of an actor can only provide asynchronous messaging via shared functions). Evaluation of `(new|object|actor) ? =? { ;* }` proceeds by evaluating the declarations in `;*`. If the evaluation of `;*` traps, so does the object declaration. @@ -1302,51 +1311,33 @@ The declaration `obj_sort? class ? =? ? { ? (: )? =? ? { ;* } := +obj_sort? class ? (: )? =? ? { ;* } := type = sort { ;* }; - func ? : = sort ? { ;* } + func ? : = sort ? { ;* } ``` where: * `` is `object` if `obj_sort?` is absent or `new` and `sort == obj_sort` otherwise. * `?` is the sequence of type identifiers bound by `?` (if any), and -* `;*` is the set of non-`private` field types inferred from ``. +* `;*` is the set of public field types inferred from ``. * `?` is the optional `this` parameter of the object instance. -_TBR can we delete `new`?_ -## Expression Fields +## Declaration Fields ```bnf - ::= object expression fields - private? field - private? = short-hand - private? shared? ? short-hand + ::= object expression fields + (public|private)? field ``` -Expression fields declare the fields of actors and objects. +Declaration fields declare the fields of actors and objects. +They are just declarations, prefixed by an optional visibility qualifier `public` or `private`; if omitted, visibility defaults to `private`. -The expression field `private? dec` is just a declaration, prefixed by an optional visibility qualifier 'private?'. - -Any identifier bound by a non-`private` declaration appears in the type of enclosing object and is accessible via the dot notation. +Any identifier bound by a `public` declaration appears in the type of enclosing object and is accessible via the dot notation. An identifier bound by a `private` declaration is excluded form the type of the enclosing object and inaccessible via the dot notation. -The field expression `private? = ` is syntactic sugar for a `let` declaration: - -```bnf -private? = := - private? let = -``` - -The field expression `private? shared? ? ` is syntactic sugar for a `let`-declared function: - -```bnf -private? private? shared? ? := - private? let = shared? -``` - # Sequence of Declarations A sequence of declarations `;*` occurring in a block, a program or the `exp-field;*` sequence of an object declaration has type `T` diff --git a/samples/ListClient.as b/samples/ListClient.as index c4b3a76c67c..f348aadd971 100644 --- a/samples/ListClient.as +++ b/samples/ListClient.as @@ -1,11 +1,11 @@ module { -private import List = "ListLib.as"; // private, so we don't re-export List +import List = "ListLib.as"; // private, so we don't re-export List -type Stack = List.List; +public type Stack = List.List; -func push(x : Int, s : Stack) : Stack = List.cons(x, s); +public func push(x : Int, s : Stack) : Stack = List.cons(x, s); -func empty():Stack = List.nil(); +public func empty() : Stack = List.nil(); } diff --git a/samples/ListLib.as b/samples/ListLib.as index 432fa38a153..5f09b3fea39 100644 --- a/samples/ListLib.as +++ b/samples/ListLib.as @@ -1,5 +1,6 @@ module { - type List = ?(T, List); - func nil() : List = null; - func cons(x : T, l : List) : List = ?(x, l); + public type List = ?(T, List); + + public func nil() : List = null; + public func cons(x : T, l : List) : List = ?(x, l); } diff --git a/samples/app/client.as b/samples/app/client.as index 0a4d34de41d..df1dc53466d 100644 --- a/samples/app/client.as +++ b/samples/app/client.as @@ -2,10 +2,10 @@ import S "server.as"; actor class Client() = this { // TODO: these should be constructor params once we can compile them - private var name : Text = ""; - private var server : ?S.Server = null; + var name : Text = ""; + var server : ?S.Server = null; - go(n : Text, s : S.Server) { + public func go(n : Text, s : S.Server) { name := n; server := ?s; ignore(async { @@ -16,7 +16,7 @@ actor class Client() = this { }) }; - send(msg : Text) { + public func send(msg : Text) { print(name # " received " # msg # "\n"); }; }; diff --git a/samples/app/list.as b/samples/app/list.as index b37e2d13f01..d3723f55bbb 100644 --- a/samples/app/list.as +++ b/samples/app/list.as @@ -1,2 +1 @@ type List = ?{head : T; var tail : List}; - diff --git a/samples/app/server.as b/samples/app/server.as index 558bdeeb406..e1a8322b78f 100644 --- a/samples/app/server.as +++ b/samples/app/server.as @@ -8,10 +8,10 @@ type ClientData = { }; actor class Server() = { - private var nextId : Nat = 0; - private var clients : L.List = null; + var nextId : Nat = 0; + var clients : L.List = null; - private broadcast(id : Nat, message : Text) { + func broadcast(id : Nat, message : Text) { var next = clients; label sends loop { switch next { @@ -24,20 +24,20 @@ actor class Server() = { }; }; - subscribe(aclient : shared Text -> ()) : async T.Subscription { + public func subscribe(aclient : shared Text -> ()) : async T.Subscription { let c = new {id = nextId; client = aclient; var revoked = false}; nextId += 1; let cs = new {head = c; var tail = clients}; clients := ?cs; - return (new { - post = shared func(message : Text) { + return object { + public shared func post(message : Text) { if (not c.revoked) broadcast(c.id, message); }; - cancel = shared func() { unsubscribe(c.id) }; - }); + public shared func cancel() { unsubscribe(c.id) }; + }; }; - private unsubscribe(id : Nat) { + func unsubscribe(id : Nat) { var prev : L.List = null; var next = clients; loop { diff --git a/samples/counter.as b/samples/counter.as index 6dc99b7505b..636588fa7ed 100644 --- a/samples/counter.as +++ b/samples/counter.as @@ -1,16 +1,16 @@ // A simple Counter actor. actor class Counter(i : Int) { - private var c = i; + var c = i; // Decrement counter - dec() { - show("dec", c); - c -= 1; + public func dec() { + show("dec", c); + c -= 1; }; // Read counter, asynchronous - read() : async Int { c }; + public func read() : async Int { c }; }; // Dummy functions to show intermediate value in trace. diff --git a/samples/modules.as b/samples/modules.as index 7ca07c55531..e56b940292e 100644 --- a/samples/modules.as +++ b/samples/modules.as @@ -1,8 +1,9 @@ module Collections = { - module List = { - type List = ?(T, List); - func nil() : List = null; - func cons(x : T, l : List) : List = ?(x, l); + public module List = { + public type List = ?(T, List); + + public func nil() : List = null; + public func cons(x : T, l : List) : List = ?(x, l); }; }; diff --git a/samples/quicksort.as b/samples/quicksort.as index a30245bd90e..ca0adcb9153 100644 --- a/samples/quicksort.as +++ b/samples/quicksort.as @@ -5,7 +5,7 @@ type Array = [var T]; class QS(cmp : (T, T) -> Int) { - quicksort(a : Array, lo : Nat, hi : Nat) { + public func quicksort(a : Array, lo : Nat, hi : Nat) { if (lo < hi) { let p = partition(a, lo, hi); quicksort(a, lo, p); @@ -13,15 +13,15 @@ class QS(cmp : (T, T) -> Int) { } }; - private swap(a : Array, i : Nat, j : Nat) { + func swap(a : Array, i : Nat, j : Nat) { let temp = a[i]; a[i] := a[j]; a[j] := temp; }; - private trace(v : T) {}; + func trace(v : T) {}; - private partition(a : Array, lo : Nat, hi : Nat) : Nat { + func partition(a : Array, lo : Nat, hi : Nat) : Nat { trace>(a); let pivot = a[lo]; var i = lo; diff --git a/src/as_frontend/dune b/src/as_frontend/dune index c076b4a19fb..6d0524128c1 100644 --- a/src/as_frontend/dune +++ b/src/as_frontend/dune @@ -4,6 +4,7 @@ ) (menhir (modules parser) + (flags -v) (infer false) ) (ocamllex lexer) diff --git a/src/as_frontend/lexer.mll b/src/as_frontend/lexer.mll index ccf9e8463a6..50c09787961 100644 --- a/src/as_frontend/lexer.mll +++ b/src/as_frontend/lexer.mll @@ -210,6 +210,7 @@ rule token mode = parse | "let" { LET } | "loop" { LOOP } | "private" { PRIVATE } + | "public" { PUBLIC } | "return" { RETURN } | "shared" { SHARED } | "debug_show" { DEBUG_SHOW } diff --git a/src/as_frontend/parser.mly b/src/as_frontend/parser.mly index 260c9d8c514..e37299dd4aa 100644 --- a/src/as_frontend/parser.mly +++ b/src/as_frontend/parser.mly @@ -98,7 +98,7 @@ let share_expfield (ef : exp_field) = %token AWAIT ASYNC BREAK CASE CONTINUE LABEL %token IF IN ELSE SWITCH LOOP WHILE FOR RETURN %token ARROW ASSIGN -%token FUNC TYPE OBJECT ACTOR CLASS PRIVATE NEW SHARED +%token FUNC TYPE OBJECT ACTOR CLASS PUBLIC PRIVATE SHARED NEW %token SEMICOLON SEMICOLON_EOL COMMA COLON SUB DOT QUEST %token AND OR NOT %token IMPORT MODULE @@ -122,7 +122,7 @@ let share_expfield (ef : exp_field) = %token PRIM %token UNDERSCORE -%nonassoc IF_NO_ELSE LOOP_NO_WHILE +%nonassoc RETURN_NO_ARG IF_NO_ELSE LOOP_NO_WHILE %nonassoc ELSE WHILE %right ASSIGN PLUSASSIGN MINUSASSIGN MULASSIGN DIVASSIGN MODASSIGN POWASSIGN CATASSIGN ANDASSIGN ORASSIGN XORASSIGN SHLASSIGN USHRASSIGN SSHRASSIGN ROTLASSIGN ROTRASSIGN @@ -151,6 +151,10 @@ seplist(X, SEP) : | x=X { [x] } | x=X SEP xs=seplist(X, SEP) { x::xs } +seplist1(X, SEP) : + | x=X { [x] } + | x=X SEP xs=seplist(X, SEP) { x::xs } + (* Basics *) @@ -180,7 +184,6 @@ seplist(X, SEP) : | VAR { Var @@ at $sloc } %inline obj_sort : - | NEW { Type.Object @@ at $sloc } | OBJECT { Type.Object @@ at $sloc } | ACTOR { Type.Actor @@ at $sloc } | MODULE { Type.Module @@ at $sloc } @@ -193,7 +196,8 @@ seplist(X, SEP) : | (* empty *) { Type.Local @@ no_region } | SHARED { Type.Shared @@ at $sloc } -(* paths *) + +(* Paths *) path : | x=id @@ -201,6 +205,7 @@ path : | p=path DOT x=id { DotH (p, x) @! at $sloc } + (* Types *) typ_obj : @@ -210,10 +215,8 @@ typ_obj : typ_variant : | LCURLY HASH RCURLY { [] } - | LCURLY tf=typ_tag RCURLY - { [tf] } - | LCURLY tf=typ_tag semicolon tfs=seplist(typ_tag, semicolon) RCURLY - { tf::tfs } + | LCURLY tfs=seplist1(typ_tag, semicolon) RCURLY + { tfs } typ_nullary : | LPAR ts=seplist(typ_item, COMMA) RPAR @@ -412,22 +415,21 @@ exp_bin : | e=exp_bin COLON t=typ { AnnotE(e, t) @? at $sloc } -exp_pre : +exp_nondec : | e=exp_bin { e } - | RETURN eo=exp_pre? - { let e = Lib.Option.get eo (TupE([]) @? at $sloc) in - RetE(e) @? at $sloc } - | ASYNC e=exp_pre + | NEW LCURLY efs=seplist(exp_field, semicolon) RCURLY + { ObjE(Type.Object @@ at $sloc, efs) @? at $sloc } + | RETURN %prec RETURN_NO_ARG + { RetE(TupE([]) @? at $sloc) @? at $sloc } + | RETURN e=exp + { RetE(e) @? at $sloc } + | ASYNC e=exp { AsyncE(e) @? at $sloc } - | AWAIT e=exp_pre + | AWAIT e=exp { AwaitE(e) @? at $sloc } - | ASSERT e=exp_pre + | ASSERT e=exp { AssertE(e) @? at $sloc } - -exp_nondec : - | e=exp_pre - { e } | LABEL x=id rt=return_typ_nullary? e=exp { let x' = ("continue " ^ x.it) @@ x.at in let t = Lib.Option.get rt (TupT [] @! at $sloc) in @@ -476,25 +478,23 @@ case : | CASE p=pat_nullary e=exp { {pat = p; exp = e} @@ at $sloc } -%inline private_opt : - | (* empty *) { Public @@ no_region } - | PRIVATE { Private @@ at $sloc } - -(* TODO(andreas): separate short forms *) -(* TODO(andreas): invert public/private default *) exp_field : - | v=private_opt x=id EQ e=exp + | x=id EQ e=exp { let d = LetD(VarP(x) @! x.at, e) @? at $sloc in - {dec = d; vis = v} @@ at $sloc } - | v=private_opt s=func_sort_opt x=id fe=func_exp - { let d = LetD(VarP(x) @! x.at, fe s x.it) @? at $sloc in - {dec = d; vis = v} @@ at $sloc } - (* TODO(andreas): allow any dec *) - | v=private_opt d=dec_var - { {dec = d; vis = v} @@ at $sloc } - | v=private_opt d=dec_nonvar + {dec = d; vis = Public @@ x.at} @@ at $sloc } + | VAR x=id EQ e=exp + { let d = VarD(x, e) @? at $sloc in + {dec = d; vis = Public @@ x.at} @@ at $sloc } + +dec_field : + | v=vis d=dec { {dec = d; vis = v} @@ at $sloc } +vis : + | (* empty *) { Private @@ no_region } + | PRIVATE { Private @@ at $sloc } + | PUBLIC { Public @@ at $sloc } + (* Patterns *) @@ -613,8 +613,7 @@ func_body : | e=exp_block { (true, e) } obj_body : - | LCURLY efs=seplist(exp_field, semicolon) RCURLY - { efs } + | LCURLY efs=seplist(dec_field, semicolon) RCURLY { efs } class_body : | EQ xf=id_opt efs=obj_body { snd (xf "object" $sloc), efs } diff --git a/src/prelude/prelude.ml b/src/prelude/prelude.ml index b3d95b99e86..15d535700a0 100644 --- a/src/prelude/prelude.ml +++ b/src/prelude/prelude.ml @@ -29,13 +29,13 @@ func abs(x : Int) : Nat { (prim "abs" : Int -> Nat) x }; func ignore(_ : Any) {}; class range(x : Nat, y : Nat) { - private var i = x; - next() : ?Nat { if (i > y) null else {let j = i; i += 1; ?j} }; + var i = x; + public func next() : ?Nat { if (i > y) null else {let j = i; i += 1; ?j} }; }; class revrange(x : Nat, y : Nat) { - private var i = x + 1; - next() : ?Nat { if (i <= y) null else {i -= 1; ?i} }; + var i = x + 1; + public func next() : ?Nat { if (i <= y) null else {i -= 1; ?i} }; }; // Implementations for overloaded dot operations @@ -53,28 +53,28 @@ func @mut_array_len(xs : [var A]) : (() -> Nat) = func @mut_array_set(xs : [var A]) : ((Nat, A) -> ()) = (func (n : Nat, x : A) = (xs[n] := x)); func @immut_array_keys(xs : [A]) : (() -> Iter) = - (func () : Iter = new { - private var i = 0; - private l = xs.len(); - next() : ?Nat { if (i >= l) null else {let j = i; i += 1; ?j} }; + (func () : Iter = object { + var i = 0; + let l = xs.len(); + public func next() : ?Nat { if (i >= l) null else {let j = i; i += 1; ?j} }; }); func @mut_array_keys(xs : [var A]) : (() -> Iter) = - (func () : Iter = new { - private var i = 0; - private l = xs.len(); - next() : ?Nat { if (i >= l) null else {let j = i; i += 1; ?j} }; + (func () : Iter = object { + var i = 0; + let l = xs.len(); + public func next() : ?Nat { if (i >= l) null else {let j = i; i += 1; ?j} }; }); func @immut_array_vals(xs : [A]) : (() -> Iter) = - (func () : Iter = new { - private var i = 0; - private l = xs.len(); - next() : ?A { if (i >= l) null else {let j = i; i += 1; ?xs[j]} }; + (func () : Iter = object { + var i = 0; + let l = xs.len(); + public func next() : ?A { if (i >= l) null else {let j = i; i += 1; ?xs[j]} }; }); func @mut_array_vals(xs : [var A]) : (() -> Iter) = - (func () : Iter = new { - private var i = 0; - private l = xs.len(); - next() : ?A { if (i >= l) null else {let j = i; i += 1; ?xs[j]} }; + (func () : Iter = object { + var i = 0; + let l = xs.len(); + public func next() : ?A { if (i >= l) null else {let j = i; i += 1; ?xs[j]} }; }); func @text_len(xs : Text) : (() -> Nat) = (func () : Nat = (prim "text_len" : Text -> Nat) xs); @@ -107,8 +107,8 @@ func hashInt(x : Int) : Word32 { return hash; }; -// Conversions +// Conversions func int64ToInt(n : Int64) : Int = (prim "Int64->Int" : Int64 -> Int) n; func intToInt64(n : Int) : Int64 = (prim "Int->Int64" : Int -> Int64) n; @@ -190,6 +190,7 @@ func clzWord64(w : Word64) : Word64 = (prim "clz64" : Word64 -> Word64) w; func ctzWord64(w : Word64) : Word64 = (prim "ctz64" : Word64 -> Word64) w; func btstWord64(w : Word64, amount : Word64) : Bool = (prim "btst64" : (Word64, Word64) -> Word64) (w, amount) != (0 : Word64); + // Internal helper functions for the show translation // The @ in the name ensures that this cannot be shadowed by user code, so @@ -292,6 +293,7 @@ func @text_of_array_mut(f : T -> Text, xs : [var T]) : Text { return text; }; + // Array utilities // This would be nicer as a objects, but lets do them as functions @@ -320,7 +322,7 @@ func @new_async() : (Async, Cont) { ks := empty; ks_(t); }; - case (?t) (assert(false)); + case (?t) { assert false }; }; }; @@ -330,7 +332,7 @@ func @new_async() : (Async, Cont) { let ks_ = ks; ks := (func(t : T) { ks_(t); k(t) }); }; - case (?t) (k(t)); + case (?t) { k(t) }; }; }; diff --git a/stdlib/assocList.as b/stdlib/assocList.as index ae08a796153..ad354fc331f 100644 --- a/stdlib/assocList.as +++ b/stdlib/assocList.as @@ -10,17 +10,17 @@ Implements the same interface as `Trie`, but as a linked-list of key-value pairs */ -private import List "list.as"; +import List "list.as"; // polymorphic association linked lists between keys and values -type AssocList = List.List<(K,V)>; +public type AssocList = List.List<(K,V)>; /** `find` -------- find the value associated with a given key, or null if absent. */ - func find(al : AssocList, + public func find(al : AssocList, k:K, k_eq:(K,K)->Bool) : ?V @@ -48,7 +48,7 @@ type AssocList = List.List<(K,V)>; replace the value associated with a given key, or add it, if missing. returns old value, or null, if no prior value existed. */ - func replace(al : AssocList, + public func replace(al : AssocList, k:K, k_eq:(K,K)->Bool, ov: ?V) @@ -86,7 +86,7 @@ type AssocList = List.List<(K,V)>; the left list whose keys are not present in the right list; the values of the right list are irrelevant. */ - func diff(al1: AssocList, + public func diff(al1: AssocList, al2: AssocList, keq: (K,K)->Bool) : AssocList @@ -109,7 +109,7 @@ type AssocList = List.List<(K,V)>; `mapAppend` -------- */ - func mapAppend(al1:AssocList, + public func mapAppend(al1:AssocList, al2:AssocList, vbin:(?V,?W)->X) : AssocList = label profile_assocList_mapAppend : AssocList @@ -125,7 +125,7 @@ type AssocList = List.List<(K,V)>; rec(al1, al2) }; - func disjDisjoint(al1:AssocList, + public func disjDisjoint(al1:AssocList, al2:AssocList, vbin:(?V,?W)->X) : AssocList = label profile_assocList_disjDisjoint : AssocList @@ -146,7 +146,7 @@ type AssocList = List.List<(K,V)>; applied to (null, null). */ - func disj(al1:AssocList, + public func disj(al1:AssocList, al2:AssocList, keq:(K,K)->Bool, vbin:(?V,?W)->X) @@ -188,7 +188,7 @@ type AssocList = List.List<(K,V)>; operator, and unmatched key-value pairs are not present in the output. */ - func join(al1 : AssocList, + public func join(al1 : AssocList, al2:AssocList, keq:(K,K)->Bool, vbin:(V,W)->X) @@ -213,7 +213,7 @@ type AssocList = List.List<(K,V)>; `fold` --------- */ - func fold(al:AssocList, + public func fold(al:AssocList, nil:X, cons:(K,V,X)->X) : X diff --git a/stdlib/docTable.as b/stdlib/docTable.as index 0203895268e..a4baf4f5795 100644 --- a/stdlib/docTable.as +++ b/stdlib/docTable.as @@ -43,20 +43,21 @@ type information. */ -private import Hash "hash.as"; -type Hash = Hash.Hash; +import Hash "hash.as"; //import Trie "trie.as"; -private import Trie "trie2.as"; -type Trie = Trie.Trie; -type Key = Trie.Key; +import Trie "trie2.as"; + +public type Hash = Hash.Hash; +public type Trie = Trie.Trie; +public type Key = Trie.Key; /** We choose to represent each `Table` as a `Trie`: */ -let Table = Trie; -type Table = Trie; +public let Table = Trie; +public type Table = Trie; /** @@ -95,7 +96,7 @@ below](#public-interface). See the types below for details. */ -class DocTable( +public class DocTable( idFirst:Id, idIncr:Id->Id, idIsEq:(Id,Id)->Bool, @@ -117,7 +118,7 @@ class DocTable( */ - empty() : Table { + public func empty() : Table { Table.empty() }; @@ -127,7 +128,7 @@ class DocTable( Reset the document table back to its initial counter, and empty state. */ - reset() { + public func reset() { idNext := idFirst; table := Table.empty(); }; @@ -140,7 +141,7 @@ class DocTable( */ - getTable() : Table { + public func getTable() : Table { Table.copy(table) }; @@ -152,7 +153,7 @@ class DocTable( */ - addDoc(doc:Id -> Doc) : (Id, Doc) { + public func addDoc(doc:Id -> Doc) : (Id, Doc) { let id = idNext; idNext := idIncr(idNext); let d = doc(id); @@ -169,7 +170,7 @@ class DocTable( */ - updateDoc(id:Id, doc:Doc) : ?Doc { + public func updateDoc(id:Id, doc:Doc) : ?Doc { let (updatedTable, oldDoc) = Table.replace (table, keyOfId(id), idIsEq, ?doc); table := updatedTable; @@ -185,7 +186,7 @@ class DocTable( This variant of `addInfo` permits the caller to choose the id, but still insists that it be fresh (not currently in use). */ - addInfoAs(idChoice:?Id, info:Id -> Info) : ?(Id, Doc) { + public func addInfoAs(idChoice:?Id, info:Id -> Info) : ?(Id, Doc) { switch idChoice { // subcase: No pre-chosen Id, so mint a new fresh one: case null { @@ -223,11 +224,11 @@ class DocTable( See also [`Table.insertFresh`]($DOCURL/trie.md#insertfresh) */ - addInfo(info:Id -> Info) : ?(Id, Doc) { + public func addInfo(info:Id -> Info) : ?(Id, Doc) { addInfoAs(null, info) }; - addInfoGetId(info:Id -> Info) : ?Id { + public func addInfoGetId(info:Id -> Info) : ?Id { switch (addInfo(info)) { case null { null }; case (?(id, doc)) { ?id } @@ -242,7 +243,7 @@ class DocTable( */ - rem(id:Id) : ?Doc { + public func rem(id:Id) : ?Doc { Table.removeThen( table, keyOfId(id), idIsEq, func (t:Table, d:Doc) : ?Doc { @@ -254,7 +255,7 @@ class DocTable( }; - remGetId(id:Id) : ?Id { + public func remGetId(id:Id) : ?Id { Table.removeThen( table, keyOfId(id), idIsEq, func (t:Table, d:Doc) : ?Id { @@ -265,7 +266,7 @@ class DocTable( ) }; - remGetUnit(id:Id) : ?() { + public func remGetUnit(id:Id) : ?() { Table.removeThen( table, keyOfId(id), idIsEq, func (t:Table, d:Doc) : ?() { @@ -284,7 +285,7 @@ class DocTable( */ - getDoc(id:Id) : ?Doc { + public func getDoc(id:Id) : ?Doc { Table.find(table, keyOfId(id), idIsEq) }; @@ -293,7 +294,7 @@ class DocTable( --------- */ - getInfo(id:Id) : ?Info { + public func getInfo(id:Id) : ?Info { switch (getDoc(id)) { case null null; case (?doc) { ?infoOfDoc(doc) }; @@ -307,7 +308,7 @@ class DocTable( See also [`Table.count`]($DOCURL/trie.md#count) */ - count() : Nat { + public func count() : Nat { Table.count(table) }; @@ -318,7 +319,7 @@ class DocTable( See also [`Table.toArray`]($DOCURL/trie.md#toarray) */ - allDoc() : [Doc] { + public func allDoc() : [Doc] { Table.toArray (table, func (id:Id, doc:Doc):Doc = doc ) }; @@ -330,7 +331,7 @@ class DocTable( See also [`Table.toArray`]($DOCURL/trie.md#toarray) */ - allInfo() : [Info] { + public func allInfo() : [Info] { Table.toArray (table, func (id:Id, doc:Doc):Info = infoOfDoc(doc) ) }; @@ -341,13 +342,13 @@ class DocTable( =============== */ - keyOfId(x:Id) : Key = new { key = x ; hash = idHash(x) }; + public func keyOfId(x:Id) : Key = new { key = x ; hash = idHash(x) }; - getIdIsEq() :(Id,Id)->Bool = idIsEq; - getIdHash() : Id->Hash = idHash; + public func getIdIsEq() :(Id,Id)->Bool = idIsEq; + public func getIdHash() : Id->Hash = idHash; - getInfoOfDoc() : Doc->Info = infoOfDoc; - getDocOfInfo() : Info->?Doc = docOfInfo; + public func getInfoOfDoc() : Doc->Info = infoOfDoc; + public func getDocOfInfo() : Info->?Doc = docOfInfo; /** @@ -355,9 +356,9 @@ class DocTable( =============== */ - private var idNext:Id = idFirst; + var idNext:Id = idFirst; - private var table : Table = Table.empty(); + var table : Table = Table.empty(); /** Helpers diff --git a/stdlib/examples/produce-exchange/profileActor.as b/stdlib/examples/produce-exchange/profileActor.as index 9168332e0a0..d791a33c561 100644 --- a/stdlib/examples/produce-exchange/profileActor.as +++ b/stdlib/examples/produce-exchange/profileActor.as @@ -6,7 +6,7 @@ actor server { // // except, we assume that region_count and scale_factor are already defined in the enclosing env // - private var dummy = { + var dummy = { func scaledParams(region_count_:Nat, factor:Nat) : T.WorkloadParams = { new { region_count = region_count_:Nat; diff --git a/stdlib/examples/produce-exchange/serverActor.as b/stdlib/examples/produce-exchange/serverActor.as index 64dc812e0b4..37e84de7af9 100644 --- a/stdlib/examples/produce-exchange/serverActor.as +++ b/stdlib/examples/produce-exchange/serverActor.as @@ -72,7 +72,7 @@ actor class Server () { */ - registrarAddUser( + public func registrarAddUser( public_key: T.PublicKey, user_name: Text, description: Text, @@ -102,7 +102,7 @@ actor class Server () { ------------- Get info for all users. */ - allUserInfo() : async [T.UserInfo] { + public func allUserInfo() : async [T.UserInfo] { getModel().userTable.allInfo() }; @@ -111,7 +111,7 @@ actor class Server () { --------------------------- Get the information associated with a user, based on its id. */ - getUserInfo(id:T.UserId) : async Result { + public func getUserInfo(id:T.UserId) : async Result { Result.fromOption( getModel().userTable.getInfo(id), #idErr null @@ -123,7 +123,7 @@ actor class Server () { --------------------------- Returns true if the user id matches the public key. */ - validateUser(public_key: T.PublicKey, id: T.UserId) : async Bool { + public func validateUser(public_key: T.PublicKey, id: T.UserId) : async Bool { getModel().isValidPublicKey(#user(id), public_key); }; @@ -140,7 +140,7 @@ actor class Server () { */ - registrarAddTruckType( + public func registrarAddTruckType( short_name_: Text, description_: Text, capacity_ : T.Weight, @@ -175,7 +175,7 @@ actor class Server () { --------------------- */ - registrarRemTruckType( + public func registrarRemTruckType( id: T.TruckTypeId ) : async Result<(),T.ServerErr> { Result.fromOption<(),T.IdErr>( @@ -189,7 +189,7 @@ actor class Server () { --------------------- */ - getTruckTypeInfo( + public func getTruckTypeInfo( id: T.TruckTypeId ) : async Result { Result.fromOption( @@ -203,7 +203,7 @@ actor class Server () { --------------------- */ - allTruckTypeInfo() : async [T.TruckTypeInfo] { + public func allTruckTypeInfo() : async [T.TruckTypeInfo] { getModel().truckTypeTable.allInfo() }; @@ -222,7 +222,7 @@ actor class Server () { invalid in any way. */ - registrarAddRegion( + public func registrarAddRegion( short_name_: Text, description_: Text, ) : async Result { @@ -244,7 +244,7 @@ actor class Server () { returns `?()` on success, and `null` on failure. */ - registrarRemRegion( + public func registrarRemRegion( id: T.RegionId ) : async Result<(),T.IdErr> { Result.fromOption<(),T.IdErr>( @@ -261,7 +261,7 @@ actor class Server () { */ - getRegionInfo( + public func getRegionInfo( id: T.RegionId ) : async Result { Result.fromOption( @@ -279,7 +279,7 @@ actor class Server () { */ - allRegionInfo() : async [T.RegionInfo] { + public func allRegionInfo() : async [T.RegionInfo] { getModel().regionTable.allInfo() }; @@ -298,7 +298,7 @@ actor class Server () { adds the produce to the system; fails if the given information is invalid in any way. */ - registrarAddProduce( + public func registrarAddProduce( short_name_: Text, description_: Text, grade_: T.Grade, @@ -322,7 +322,7 @@ actor class Server () { returns `?()` on success, and `null` on failure. */ - registrarRemProduce( + public func registrarRemProduce( id: T.ProduceId ) : async Result<(),T.IdErr> { Result.fromOption<(),T.IdErr>( @@ -337,7 +337,7 @@ actor class Server () { --------------------- */ - getProduceInfo( + public func getProduceInfo( id: T.ProduceId ) : async Result { Result.fromOption( @@ -351,7 +351,7 @@ actor class Server () { --------------------- */ - allProduceInfo() : async [T.ProduceInfo] { + public func allProduceInfo() : async [T.ProduceInfo] { getModel().produceTable.allInfo() }; @@ -369,7 +369,7 @@ actor class Server () { adds the producer to the system; fails if the given region is non-existent. */ - registrarAddProducer( + public func registrarAddProducer( producer_public_key : T.PublicKey, short_name_: Text, description_: Text, @@ -399,7 +399,7 @@ actor class Server () { returns `?()` on success, and `null` on failure. */ - registrarRemProducer( + public func registrarRemProducer( id: T.ProducerId ) : async Result<(),T.IdErr> { Result.fromOption<(),T.IdErr>( @@ -414,7 +414,7 @@ actor class Server () { --------------------- */ - getProducerInfo( + public func getProducerInfo( id: T.ProducerId ) : async Result { Result.fromOption( @@ -428,7 +428,7 @@ actor class Server () { --------------------- */ - allProducerInfo() : async [T.ProducerInfo] { + public func allProducerInfo() : async [T.ProducerInfo] { getModel().producerTable.allInfo() }; @@ -446,7 +446,7 @@ actor class Server () { adds the producer to the system; fails if the given region is non-existent. */ - registrarAddRetailer( + public func registrarAddRetailer( retailer_public_key : T.PublicKey, short_name_: Text, description_: Text, @@ -474,7 +474,7 @@ actor class Server () { returns `?()` on success, and `null` on failure. */ - registrarRemRetailer( + public func registrarRemRetailer( id: T.RetailerId ) : async Result<(),T.IdErr> { Result.fromOption<(),T.IdErr>( @@ -488,7 +488,7 @@ actor class Server () { --------------------- */ - getRetailerInfo( + public func getRetailerInfo( id: T.RetailerId ) : async Result { Result.fromOption( @@ -502,7 +502,7 @@ actor class Server () { --------------------- */ - allRetailerInfo() : async [T.RetailerInfo] { + public func allRetailerInfo() : async [T.RetailerInfo] { getModel().retailerTable.allInfo() }; @@ -518,7 +518,7 @@ actor class Server () { --------------------- */ - registrarAddTransporter( + public func registrarAddTransporter( transporter_public_key: T.PublicKey, short_name_: Text, description_: Text, @@ -545,7 +545,7 @@ actor class Server () { */ - registrarRemTransporter( + public func registrarRemTransporter( id: T.TransporterId ) : async Result<(),T.IdErr> { Result.fromOption<(),T.IdErr>( @@ -559,7 +559,7 @@ actor class Server () { --------------------- */ - getTransporterInfo( + public func getTransporterInfo( id: T.TransporterId ) : async Result { Result.fromOption( @@ -574,7 +574,7 @@ actor class Server () { --------------------- */ - allTransporterInfo() : async [T.TransporterInfo] { + public func allTransporterInfo() : async [T.TransporterInfo] { getModel().transporterTable.allInfo() }; @@ -590,7 +590,7 @@ actor class Server () { See also [Model.producerAddInventory]($DOCURL/stdlib/examples/produce-exchange/serverModel.md#produceraddinventory) */ - producerAddInventory( + public func producerAddInventory( public_key: T.PublicKey, id: T.ProducerId, prod: T.ProduceId, @@ -614,7 +614,7 @@ actor class Server () { ------------------------------------------ */ - producerUpdateInventory( + public func producerUpdateInventory( public_key: T.PublicKey, iid: T.InventoryId, id: T.ProducerId, @@ -638,7 +638,7 @@ actor class Server () { `producerRemInventory` --------------------------- */ - producerRemInventory(public_key: T.PublicKey, id:T.InventoryId) : async Result<(),T.ServerErr> { + public func producerRemInventory(public_key: T.PublicKey, id:T.InventoryId) : async Result<(),T.ServerErr> { if (not getModel().isValidPublicKey(#producer(id), public_key)) { return (#err(#publicKeyErr)) }; @@ -649,7 +649,7 @@ actor class Server () { `producerAllInventoryInfo` --------------------------- */ - producerAllInventoryInfo(public_key: T.PublicKey, id:T.UserId) : async Result<[T.InventoryInfo],T.IdErr> { + public func producerAllInventoryInfo(public_key: T.PublicKey, id:T.UserId) : async Result<[T.InventoryInfo],T.IdErr> { Result.fromOption<[T.InventoryInfo],T.IdErr>( getModel() .producerAllInventoryInfo(id), @@ -661,7 +661,7 @@ actor class Server () { `producerAllReservationInfo` --------------------------- */ - producerReservations(public_key: T.PublicKey, id:T.UserId) : async Result<[T.ReservedInventoryInfo],T.IdErr> { + public func producerReservations(public_key: T.PublicKey, id:T.UserId) : async Result<[T.ReservedInventoryInfo],T.IdErr> { Result.fromOption<[T.ReservedInventoryInfo],T.IdErr>( getModel() .producerAllReservationInfo(id), @@ -682,7 +682,7 @@ actor class Server () { --------------------------- The last sales price for produce within a given geographic area; null region id means "all areas." */ - produceMarketInfo(public_key: T.PublicKey, id:T.ProduceId, reg:?T.RegionId) : async Result<[T.ProduceMarketInfo],T.IdErr> { + public func produceMarketInfo(public_key: T.PublicKey, id:T.ProduceId, reg:?T.RegionId) : async Result<[T.ProduceMarketInfo],T.IdErr> { Result.fromOption<[T.ProduceMarketInfo],T.IdErr>( getModel() .produceMarketInfo(id, reg), @@ -696,7 +696,7 @@ actor class Server () { --------------------------- Get the information for all known inventory. */ - allInventoryInfo() : async [T.InventoryInfo] { + public func allInventoryInfo() : async [T.InventoryInfo] { getModel() .inventoryTable.allInfo() }; @@ -706,7 +706,7 @@ actor class Server () { --------------------------- Get the information associated with inventory, based on its id. */ - getInventoryInfo(id:T.InventoryId) : async Result { + public func getInventoryInfo(id:T.InventoryId) : async Result { Result.fromOption( getModel() .inventoryTable.getInfo(id), @@ -724,7 +724,7 @@ actor class Server () { `transporterAddRoute` --------------------------- */ - transporterAddRoute( + public func transporterAddRoute( public_key: T.PublicKey, id: T.TransporterId, rstart: T.RegionId, @@ -744,7 +744,7 @@ actor class Server () { `transporterUpdateRoute` --------------------------- */ - transporterUpdateRoute( + public func transporterUpdateRoute( public_key: T.PublicKey, route: T.RouteId, id: T.TransporterId, @@ -765,7 +765,7 @@ actor class Server () { `transporterRemRoute` --------------------------- */ - transporterRemRoute(public_key: T.PublicKey, id:T.RouteId) : async Result<(),T.ServerErr> { + public func transporterRemRoute(public_key: T.PublicKey, id:T.RouteId) : async Result<(),T.ServerErr> { if (not getModel().isValidPublicKey(#transporter(id), public_key)) { return (#err(#publicKeyErr)) }; @@ -776,7 +776,7 @@ actor class Server () { `transporterAllRouteInfo` --------------------------- */ - transporterAllRouteInfo(public_key: T.PublicKey, id:T.UserId) : async Result<[T.RouteInfo],T.IdErr> { + public func transporterAllRouteInfo(public_key: T.PublicKey, id:T.UserId) : async Result<[T.RouteInfo],T.IdErr> { Result.fromOption<[T.RouteInfo],T.IdErr>( getModel() .transporterAllRouteInfo(id), @@ -788,7 +788,7 @@ actor class Server () { `transporterAllReservationInfo` --------------------------- */ - transporterAllReservationInfo(public_key: T.PublicKey, id:T.UserId) : async Result<[T.ReservedRouteInfo],T.IdErr> { + public func transporterAllReservationInfo(public_key: T.PublicKey, id:T.UserId) : async Result<[T.ReservedRouteInfo],T.IdErr> { Result.fromOption<[T.ReservedRouteInfo],T.IdErr>( getModel() .transporterAllReservationInfo(id), @@ -801,7 +801,7 @@ actor class Server () { --------------------------- Get the information for all known routes. */ - allRouteInfo() : async [T.RouteInfo] { + public func allRouteInfo() : async [T.RouteInfo] { getModel() .routeTable.allInfo() }; @@ -811,7 +811,7 @@ actor class Server () { --------------------------- Get the information for all reserved routes. */ - allReservedRouteInfo() : async [T.ReservedRouteInfo] { + public func allReservedRouteInfo() : async [T.ReservedRouteInfo] { getModel() .reservedRouteTable.allInfo() }; @@ -824,7 +824,7 @@ actor class Server () { */ - getRouteInfo( + public func getRouteInfo( id: T.RouteId ) : async Result { Result.fromOption( @@ -841,9 +841,11 @@ actor class Server () { --------------------------- */ - retailerQueryAll(public_key: T.PublicKey, id:T.RetailerId, - queryProduce:?T.ProduceId, - queryDate:?T.Date + public func retailerQueryAll( + public_key: T.PublicKey, + id:T.RetailerId, + queryProduce:?T.ProduceId, + queryDate:?T.Date ) : async Result { Result.fromOption( getModel(). @@ -856,7 +858,7 @@ actor class Server () { `retailerReserve` --------------------------- */ - retailerReserve( + public func retailerReserve( public_key: T.PublicKey, id:T.RetailerId, inventory:T.InventoryId, @@ -873,7 +875,7 @@ actor class Server () { `retailerReserveMany` --------------------------- */ - retailerReserveMany( + public func retailerReserveMany( public_key: T.PublicKey, id: T.RetailerId, list: [(T.InventoryId, T.RouteId)] @@ -891,7 +893,7 @@ actor class Server () { --------------------------- */ - retailerReservations(public_key: T.PublicKey, id:T.RetailerId) : + public func retailerReservations(public_key: T.PublicKey, id:T.RetailerId) : async Result<[(T.ReservedInventoryInfo, T.ReservedRouteInfo)],T.ServerErr> { @@ -919,7 +921,7 @@ actor class Server () { ---------- */ - getCounts() : async T.ProduceExchangeCounts { + public func getCounts() : async T.ProduceExchangeCounts { let m = getModel(); new { hash_bit_length = 0; @@ -951,7 +953,7 @@ actor class Server () { been processed */ - devViewGMV() : async ?Nat { + public func devViewGMV() : async ?Nat { P.nyi() }; @@ -965,7 +967,7 @@ been processed */ - devViewQueries() : async ?Nat { + public func devViewQueries() : async ?Nat { ?getModel().retailerQueryCount; }; @@ -980,7 +982,7 @@ been processed */ - devViewReservations() : async Nat { + public func devViewReservations() : async Nat { getModel().reservedInventoryTable.count() }; @@ -996,7 +998,7 @@ been processed */ - devViewProducers() : async [T.ProducerInfo] { + public func devViewProducers() : async [T.ProducerInfo] { getModel().producerTable.allInfo() }; @@ -1013,7 +1015,7 @@ been processed */ - devViewTransporters() : async [T.TransporterInfo] { + public func devViewTransporters() : async [T.TransporterInfo] { getModel().transporterTable.allInfo() }; @@ -1029,7 +1031,7 @@ been processed */ - devViewRetailers() : async [T.RetailerInfo] { + public func devViewRetailers() : async [T.RetailerInfo] { getModel().retailerTable.allInfo() }; @@ -1040,12 +1042,12 @@ been processed evaluate a collection of API calls (a "bulk request"), represented as an AS datatype. */ - evalBulkArray(reqs:[L.BulkReq]) : async [L.BulkResp] { + public func evalBulkArray(reqs:[L.BulkReq]) : async [L.BulkResp] { getModel().evalBulkArray(reqs) }; - loadWorkload(params:T.WorkloadParams) : () { + public func loadWorkload(params:T.WorkloadParams) : () { func db(s:Text) = if false {print "Model::loadWorkload: "; print s; print "\n"}; getModel().loadWorkload(params) }; @@ -1055,7 +1057,7 @@ been processed ========================= */ - devTestLoadQuery (region_count:Nat, scale_factor:Nat) { + public func devTestLoadQuery (region_count:Nat, scale_factor:Nat) { func scaledParams(region_count_:Nat, factor:Nat) : T.WorkloadParams = { new { region_count = region_count_:Nat; @@ -1086,9 +1088,9 @@ been processed //private var model : ?Model.Model = null; - private var model : ?Model.Model = ?(Model.Model()); + var model : ?Model.Model = ?(Model.Model()); - private getModel() : Model.Model { + func getModel() : Model.Model { switch model { case (null) { let m = Model.Model(); diff --git a/stdlib/examples/produce-exchange/serverLang.as b/stdlib/examples/produce-exchange/serverLang.as index d6b8be18af7..77f0e84affc 100644 --- a/stdlib/examples/produce-exchange/serverLang.as +++ b/stdlib/examples/produce-exchange/serverLang.as @@ -11,7 +11,7 @@ module { import Result = "../../result.as"; import T = "serverTypes.as"; -type Result = Result.Result; +public type Result = Result.Result; /** `Req` @@ -22,7 +22,7 @@ type Result = Result.Result; - [resp](#resp) - [bulk request](#bulkreq) */ -type Req = { +public type Req = { #reset : () ; #add : AddReq ; #update : UpdateReq ; @@ -41,7 +41,7 @@ type Req = { - [request](#req) - [bulk response](#bulkresp) */ -type Resp = { +public type Resp = { #reset; #add : T.EntId; #update : (); @@ -53,7 +53,7 @@ type Resp = { -------------------------------------- A `Result` whose OK type is `Resp`. */ -type ResultResp = Result; +public type ResultResp = Result; /** `BulkReq` @@ -64,7 +64,7 @@ type ResultResp = Result; - [bulk response](#bulkresp) - [response](#resp) */ -type BulkReq = { +public type BulkReq = { #add : [ AddReq ] ; #update : [ UpdateReq ] ; #rem : [ T.EntId ] ; @@ -77,14 +77,14 @@ type BulkReq = { See also: [bulk request](#bulkreq). */ -type BulkResp = { +public type BulkResp = { #add : [ Result ] ; #update : [ Result<(), T.IdErr> ] ; #rem : [ Result<(), T.IdErr> ] ; } ; -type UserAddReq = new { +public type UserAddReq = { user_name: Text; public_key: Text; description: Text; @@ -100,7 +100,7 @@ type UserAddReq = new { ---------------- Note: The `RouteInfo` type contains too much information about truck types to use here in place of this type. */ -type RouteAddReq = new { +public type RouteAddReq = { id : T.RouteId; transporter : T.TransporterId; truck_type : T.TruckTypeId; @@ -120,7 +120,7 @@ type RouteAddReq = new { etc.), the identifier is ignored; the request, if successful, will generate a fresh identifier for the new entity. */ -type AddReq = { +public type AddReq = { #user : UserAddReq ; #truckType : T.TruckTypeInfo ; #region : T.RegionInfo ; @@ -137,7 +137,7 @@ type AddReq = { -------------------------------------- a server `Update` request, as an AS datatype */ -type UpdateReq = { +public type UpdateReq = { #user : T.UserInfo ; #truckType : T.TruckTypeInfo ; #region : T.RegionInfo ; diff --git a/stdlib/examples/produce-exchange/serverModel.as b/stdlib/examples/produce-exchange/serverModel.as index 072768b53ad..fa1f10df178 100644 --- a/stdlib/examples/produce-exchange/serverModel.as +++ b/stdlib/examples/produce-exchange/serverModel.as @@ -28,43 +28,43 @@ import T = "serverTypes.as"; import L = "serverLang.as"; import M = "serverModelTypes.as"; -let List = (import "../../list.as"); -type List = List.List; +public let List = (import "../../list.as"); +public type List = List.List; -let Hash = (import "../../hash.as").BitVec; -type Hash = Hash.t; +public let Hash = (import "../../hash.as").BitVec; +public type Hash = Hash.t; import Option = "../../option.as"; import Trie = "../../trie2.as"; -type Trie = Trie.Trie; -type TrieBuild = Trie.Build.TrieBuild; -type Key = Trie.Key; +public type Trie = Trie.Trie; +public type TrieBuild = Trie.Build.TrieBuild; +public type Key = Trie.Key; -type Table = Trie.Trie; -let Table = Trie; +public type Table = Trie.Trie; +public let Table = Trie; -type Map = Trie.Trie; -let Map = Trie; +public type Map = Trie.Trie; +public let Map = Trie; import DT = "../../docTable.as"; -let DocTable = DT.DocTable; -type DocTable = DT.DocTable; +public let DocTable = DT.DocTable; +public type DocTable = DT.DocTable; import Result = "../../result.as"; -type Result = Result.Result; +public type Result = Result.Result; -type RouteInventoryMap = Trie<(T.RouteId, T.InventoryId), (M.RouteDoc, M.InventoryDoc)>; -type QueryResult = TrieBuild<(T.RouteId, T.InventoryId), (M.RouteDoc, M.InventoryDoc)>; +public type RouteInventoryMap = Trie<(T.RouteId, T.InventoryId), (M.RouteDoc, M.InventoryDoc)>; +public type QueryResult = TrieBuild<(T.RouteId, T.InventoryId), (M.RouteDoc, M.InventoryDoc)>; -type RoleId = { +public type RoleId = { #user : T.UserId; #producer : T.ProducerId; #transporter : T.TransporterId; #retailer : T.RetailerId; }; -class Model() { +public class Model() { /** PX server language semantics @@ -78,7 +78,7 @@ class Model() { clear existing server state, and replace with a synthetic workload, based on the given parameters. */ - loadWorkload(params:T.WorkloadParams) : () { + public func loadWorkload(params:T.WorkloadParams) : () { func db(s:Text) = if false {print "Model::loadWorkload: "; print s; print "\n"}; /**- generate add requests for these params: */ @@ -126,7 +126,7 @@ class Model() { - update (`#update`) cases */ - evalReq(req:L.Req) : Result { + public func evalReq(req:L.Req) : Result { if false {print "Model::evalReq: "; print (debug_show req); print "\n"; }; switch req { case (#reset) { @@ -316,7 +316,7 @@ class Model() { `evalReqList` ---------- */ - evalReqList(reqs:List) : List = + public func evalReqList(reqs:List) : List = List.map(reqs, evalReq); /** @@ -325,7 +325,7 @@ class Model() { evaluate groups of similar API calls, grouping their results. Each bulk request consists of an array of similar requests (adds, updates, or removes). */ - evalBulk(req:L.BulkReq) : L.BulkResp { + public func evalBulk(req:L.BulkReq) : L.BulkResp { func eatAdd (x:L.Resp) : T.EntId = switch x { case (#add i) i; case _ P.unreachable() }; switch req { @@ -357,7 +357,7 @@ class Model() { - The request is an array of bulk requests, and - Each bulk request in this array consists of an array of similar requests (adds, updates, or removes). */ - evalBulkArray(reqs:[L.BulkReq]) : [L.BulkResp] { + public func evalBulkArray(reqs:[L.BulkReq]) : [L.BulkResp] { Array_tabulate( reqs.len(), func(i:Nat):L.BulkResp = evalBulk(reqs[i]) @@ -369,7 +369,7 @@ class Model() { ------------- xxx */ - countAddReqs( + public func countAddReqs( day_count:Nat, max_route_duration:Nat, producer_count:Nat, @@ -435,7 +435,7 @@ class Model() { and for profiling performance properties of the produce exchange, e.g., average response time for a retailer query. */ - genAddReqs( + public func genAddReqs( day_count:Nat, max_route_duration:Nat, producer_count:Nat, @@ -567,7 +567,7 @@ class Model() { Match a given public key to that of an identified role, whose public key on record. */ - func isValidPublicKey(id:RoleId, public_key:T.PublicKey) : Bool { + public func isValidPublicKey(id:RoleId, public_key:T.PublicKey) : Bool { switch id { case (#user id) { switch (userTable.getDoc(id)) { @@ -601,32 +601,32 @@ class Model() { ================== */ - private debug (t:Text) { print t }; - private debugInt (i:Int) { printInt i }; + func debug (t:Text) { print t }; + func debugInt (i:Int) { printInt i }; - private debugOff (t:Text) { }; - private debugIntOff (i:Int) { }; - private debugOffInt (i:Int) { }; + func debugOff (t:Text) { }; + func debugIntOff (i:Int) { }; + func debugOffInt (i:Int) { }; - private idIsEq(x:Nat,y:Nat):Bool { x == y }; + func idIsEq(x:Nat,y:Nat):Bool { x == y }; - private textIsEq(x:Text,y:Text):Bool { x == y }; + func textIsEq(x:Text,y:Text):Bool { x == y }; - private idPairIsEq(x:(Nat,Nat),y:(Nat,Nat)):Bool { x.0 == y.0 and x.1 == y.1 }; + func idPairIsEq(x:(Nat,Nat),y:(Nat,Nat)):Bool { x.0 == y.0 and x.1 == y.1 }; - private idHash(x:Nat):Hash { Hash.hashOfInt(x) }; + func idHash(x:Nat):Hash { Hash.hashOfInt(x) }; - private idPairHash(x:(Nat,Nat)):Hash { Hash.hashOfIntAcc(Hash.hashOfInt(x.0), x.1) }; + func idPairHash(x:(Nat,Nat)):Hash { Hash.hashOfIntAcc(Hash.hashOfInt(x.0), x.1) }; - private keyOf(x:Nat):Key { + func keyOf(x:Nat):Key { new { key = x ; hash = idHash(x) } }; - private keyOfIdPair(x:Nat, y:Nat):Key<(Nat,Nat)> { + func keyOfIdPair(x:Nat, y:Nat):Key<(Nat,Nat)> { new { key = (x,y) ; hash = idPairHash(x,y) } }; - private keyOfText(x:Text):Key { + func keyOfText(x:Text):Key { new { key = x ; hash = Hash.hashOfText(x) } }; @@ -635,8 +635,8 @@ class Model() { ================== */ - var joinCount = 0; - var retailerQuerySizeMax = 0; + public var joinCount = 0; + public var retailerQuerySizeMax = 0; /** @@ -686,7 +686,7 @@ secondary maps. ----------------- */ - var userTable : M.UserTable = + public var userTable : M.UserTable = DocTable( 0, func(x:T.UserId):T.UserId{x+1}, @@ -722,7 +722,7 @@ secondary maps. ----------------- */ - var truckTypeTable : M.TruckTypeTable = + public var truckTypeTable : M.TruckTypeTable = DocTable( 0, func(x:T.TruckTypeId):T.TruckTypeId{x+1}, @@ -751,7 +751,7 @@ secondary maps. ----------------- */ - var regionTable : M.RegionTable = + public var regionTable : M.RegionTable = DocTable( 0, func(x:T.RegionId):T.RegionId{x+1}, @@ -774,7 +774,7 @@ secondary maps. ----------------- */ - var produceTable : M.ProduceTable = + public var produceTable : M.ProduceTable = DocTable( 0, func(x:T.ProduceId):T.ProduceId{x+1}, @@ -799,7 +799,7 @@ secondary maps. ----------------- */ - var producerTable : M.ProducerTable = + public var producerTable : M.ProducerTable = DocTable( 0, func(x:T.ProducerId):T.ProducerId{x+1}, @@ -835,7 +835,7 @@ secondary maps. --------------- */ - var inventoryTable : M.InventoryTable = + public var inventoryTable : M.InventoryTable = DocTable( 0, func(x:T.InventoryId):T.InventoryId{x+1}, @@ -881,7 +881,7 @@ secondary maps. ----------------- */ - var transporterTable : M.TransporterTable = + public var transporterTable : M.TransporterTable = DocTable ( 0, func(x:T.TransporterId):T.TransporterId{x+1}, @@ -911,7 +911,7 @@ secondary maps. ----------------- */ - var retailerTable : M.RetailerTable = + public var retailerTable : M.RetailerTable = DocTable( 0, func(x:T.RetailerId):T.RetailerId{x+1}, @@ -940,16 +940,16 @@ secondary maps. ) ); - var retailerQueryCount : Nat = 0; - var retailerQueryCost : Nat = 0; - var retailerJoinCount : Nat = 0; + public var retailerQueryCount : Nat = 0; + public var retailerQueryCost : Nat = 0; + public var retailerJoinCount : Nat = 0; /** `routeTable` ---------------- */ - var routeTable : M.RouteTable = + public var routeTable : M.RouteTable = DocTable ( 0, func(x:T.RouteId):T.RouteId{x+1}, @@ -993,7 +993,7 @@ secondary maps. --------------------------- */ - var reservedInventoryTable : M.ReservedInventoryTable = + public var reservedInventoryTable : M.ReservedInventoryTable = DocTable( 0, func(x:T.ReservedInventoryId):T.ReservedInventoryId{x+1}, @@ -1036,7 +1036,7 @@ secondary maps. ---------------- */ - var reservedRouteTable : M.ReservedRouteTable = + public var reservedRouteTable : M.ReservedRouteTable = DocTable( 0, func(x:T.ReservedRouteId):T.ReservedRouteId{x+1}, @@ -1085,7 +1085,7 @@ secondary maps. ===================================== */ - private var usersByUserName + public var usersByUserName : M.UserNameMap = Map.empty(); /** @@ -1113,7 +1113,7 @@ secondary maps. */ - private var routesByDstSrcRegions : M.ByRegionPairRouteMap + public var routesByDstSrcRegions : M.ByRegionPairRouteMap = Map.empty(); /** @@ -1127,7 +1127,7 @@ secondary maps. */ - private var inventoryByRegion : M.ByRegionInventoryMap + public var inventoryByRegion : M.ByRegionInventoryMap = Map.empty(); /** @@ -1157,7 +1157,7 @@ merely forget the older prices. Doing either of these is more complex than the MVP goals, however. */ - private var reservationsByProduceByRegion + public var reservationsByProduceByRegion : M.ByProduceByRegionInventoryReservationMap = Map.empty>>( // reservationsByProduceByRegion, // produce_id, idIsEq)) { @@ -1333,7 +1333,7 @@ than the MVP goals, however. // `producerAllInventoryInfo` // --------------------------- */ - producerAllInventoryInfo(id:T.UserId) : ?[T.InventoryInfo] { + public func producerAllInventoryInfo(id:T.UserId) : ?[T.InventoryInfo] { let doc = switch (producerTable.getDoc(id)) { case null { return null }; case (?doc) { doc }; @@ -1351,7 +1351,7 @@ than the MVP goals, however. --------------------------- */ - producerAddInventory( + public func producerAddInventory( iid_ : ?T.InventoryId, id_ : T.ProducerId, produce_id : T.ProduceId, @@ -1434,7 +1434,7 @@ than the MVP goals, however. --------------------------- */ - producerUpdateInventory( + public func producerUpdateInventory( iid_ : T.InventoryId, id_ : T.ProducerId, produce_id : T.ProduceId, @@ -1487,7 +1487,7 @@ than the MVP goals, however. Remove the given inventory item from the exchange. */ - producerRemInventory(id:T.InventoryId) : Result<(),T.ServerErr> { + public func producerRemInventory(id:T.InventoryId) : Result<(),T.ServerErr> { /**- validate the `id` */ /// xxx macro for this pattern? @@ -1545,7 +1545,7 @@ than the MVP goals, however. --------------------------- */ - producerAllReservationInfo(id:T.ProducerId) : ?[T.ReservedInventoryInfo] { + public func producerAllReservationInfo(id:T.ProducerId) : ?[T.ReservedInventoryInfo] { let doc = switch (producerTable.getDoc(id)) { case null { return null }; case (?doc) { doc }; @@ -1573,7 +1573,7 @@ than the MVP goals, however. `transporterAddRoute` --------------------------- */ - transporterAddRoute( + public func transporterAddRoute( rid_: ?T.RouteId, id_: T.TransporterId, start_region_id: T.RegionId, @@ -1655,7 +1655,7 @@ than the MVP goals, however. --------------------------- Update the given route with the given field values. */ - transporterUpdateRoute( + public func transporterUpdateRoute( rid_ : T.RouteId, id_ : T.TransporterId, start_region_id : T.RegionId, @@ -1713,7 +1713,7 @@ than the MVP goals, however. --------------------------- Remove the given route from the exchange. */ - transporterRemRoute(id:T.RouteId) : Result<(),T.IdErr> { + public func transporterRemRoute(id:T.RouteId) : Result<(),T.IdErr> { let doc = switch (routeTable.getDoc(id)) { case null { return #err(#idErr null) }; @@ -1761,7 +1761,7 @@ than the MVP goals, however. `transporterAllRouteInfo` --------------------------- */ - transporterAllRouteInfo(id:T.TransporterId) : ?[T.RouteInfo] { + public func transporterAllRouteInfo(id:T.TransporterId) : ?[T.RouteInfo] { let doc = switch (transporterTable.getDoc(id)) { case null { return null }; case (?doc) { doc }; @@ -1784,7 +1784,7 @@ than the MVP goals, however. --------------------------- */ - transporterAllReservationInfo(id:T.TransporterId) : ?[T.ReservedRouteInfo] { + public func transporterAllReservationInfo(id:T.TransporterId) : ?[T.ReservedRouteInfo] { let doc = switch (transporterTable.getDoc(id)) { case null { return null }; case (?doc) { doc }; @@ -1815,7 +1815,7 @@ than the MVP goals, however. Prepare reservation information for a server client based on the given inventory and route documents. */ - makeReservationInfo(item:M.InventoryDoc, route:M.RouteDoc) : T.ReservationInfo { + public func makeReservationInfo(item:M.InventoryDoc, route:M.RouteDoc) : T.ReservationInfo { new { produce =item.produce.id :T.ProduceId; producer =item.producer :T.ProducerId; @@ -1847,7 +1847,7 @@ than the MVP goals, however. Check whether the given truck type can accommodate the given produce type. */ - isCompatibleTruckType(tt:M.TruckTypeDoc, produce:M.ProduceDoc) : Bool { + public func isCompatibleTruckType(tt:M.TruckTypeDoc, produce:M.ProduceDoc) : Bool { // todo true }; @@ -1860,7 +1860,7 @@ than the MVP goals, however. */ - isFeasibleReservation( + public func isFeasibleReservation( retailer:M.RetailerDoc, item:M.InventoryDoc, route:M.RouteDoc, @@ -1933,7 +1933,7 @@ than the MVP goals, however. - [`Trie.prod`]($DOCURL/trie.md#prod): For the catesian product of routes and inventory. - [`Trie.mergeDisjoint2D`]($DOCURL/trie.md#mergeDisjoint2D): To flatten 2D mappings into 1D mappings. */ - retailerQueryAll( + public func retailerQueryAll( id:T.RetailerId, queryProduce:?T.ProduceId, queryDate:?T.Date @@ -2064,7 +2064,7 @@ than the MVP goals, however. --------------------------- */ - retailerAllReservationInfo(id:T.RetailerId) : + public func retailerAllReservationInfo(id:T.RetailerId) : ?[(T.ReservedInventoryInfo, T.ReservedRouteInfo)] { @@ -2101,7 +2101,7 @@ than the MVP goals, however. the created reservation documents, each have a valid id, which this operation returns. */ - retailerReserve( + public func retailerReserve( retailer_id:T.RetailerId, inventory_id:T.InventoryId, route_id:T.RouteId) : Result<(T.ReservedRouteId, T.ReservedInventoryId), T.IdErr> @@ -2279,7 +2279,7 @@ than the MVP goals, however. `retailerReserveMany` --------------------------- */ - retailerReserveMany( + public func retailerReserveMany( id:T.RetailerId, array:[(T.InventoryId,T.RouteId)]) : [Result<(T.ReservedRouteId, T.ReservedInventoryId), T.IdErr>] diff --git a/stdlib/examples/produce-exchange/serverModelTypes.as b/stdlib/examples/produce-exchange/serverModelTypes.as index 56ce4a7ca35..bc1bd858cab 100644 --- a/stdlib/examples/produce-exchange/serverModelTypes.as +++ b/stdlib/examples/produce-exchange/serverModelTypes.as @@ -36,10 +36,10 @@ Representation import T = "serverTypes.as"; import Trie = "../../trie2.as"; -type Trie = Trie.Trie; +public type Trie = Trie.Trie; -type Map = Trie; -let Map = Trie; +public type Map = Trie; +public let Map = Trie; /** @@ -97,8 +97,8 @@ internal sharing: */ -let DocTable = (import "../../docTable.as"); -type DocTable = DocTable.DocTable; +public let DocTable = (import "../../docTable.as"); +public type DocTable = DocTable.DocTable; /** `UserDoc` @@ -106,7 +106,7 @@ type DocTable = DocTable.DocTable; User documents. */ -type UserDoc = { +public type UserDoc = { id: T.UserId; user_name: Text; public_key: Text; @@ -118,10 +118,10 @@ type UserDoc = { isDeveloper: Bool; }; -type UserTable = +public type UserTable = DocTable; -type UserNameMap = +public type UserNameMap = Map; /** @@ -132,7 +132,7 @@ type UserNameMap = - See also [`DocTable`](). */ -type TruckTypeDoc = { +public type TruckTypeDoc = { id : T.TruckTypeId; short_name : Text; description : Text; @@ -142,7 +142,7 @@ type TruckTypeDoc = { isFreezer : Bool; }; -type TruckTypeTable = +public type TruckTypeTable = DocTable; /** @@ -150,13 +150,13 @@ type TruckTypeTable = ========================== */ -type RegionDoc = { +public type RegionDoc = { id : T.RegionId; short_name : Text; description : Text; }; -type RegionTable = +public type RegionTable = DocTable; /** @@ -164,14 +164,14 @@ type RegionTable = ================== */ -type ProduceDoc = { +public type ProduceDoc = { id : T.ProduceId; short_name : Text; description : Text; grade : T.Grade; }; -type ProduceTable = +public type ProduceTable = DocTable; /** @@ -179,7 +179,7 @@ type ProduceTable = ======================= */ -type ProducerDoc = { +public type ProducerDoc = { id : T.ProducerId; public_key: Text; short_name : Text; @@ -189,7 +189,7 @@ type ProducerDoc = { reserved : ReservedInventoryMap; }; -type ProducerTable = +public type ProducerTable = DocTable; /** @@ -197,7 +197,7 @@ type ProducerTable = ======================== */ -type InventoryDoc = { +public type InventoryDoc = { id : T.InventoryId; produce : ProduceDoc; producer : T.ProducerId; @@ -209,27 +209,27 @@ type InventoryDoc = { comments : Text; }; -type InventoryTable = +public type InventoryTable = DocTable; -type InventoryMap = +public type InventoryMap = Map; -type ByProducerInventoryMap = +public type ByProducerInventoryMap = Map>; /** By-region inventory indexing ----------------------------- */ -type ByRegionInventoryMap = Map; +public type ByRegionInventoryMap = Map; /** `ReservedInventory` documents ================================== */ -type ReservedInventoryDoc= { +public type ReservedInventoryDoc= { id : T.ReservedInventoryId; retailer : T.RetailerId; item : InventoryDoc; @@ -240,10 +240,10 @@ type ReservedInventoryDoc= { ----------------------------- */ -type ReservedInventoryTable = +public type ReservedInventoryTable = DocTable; -type ReservedInventoryMap = +public type ReservedInventoryMap = Map; /** @@ -251,7 +251,7 @@ type ReservedInventoryMap = ================== */ -type RetailerDoc = { +public type RetailerDoc = { id : T.RetailerId; public_key: Text; short_name : Text; @@ -260,13 +260,13 @@ type RetailerDoc = { reserved : ReservedInventoryRouteMap; }; -type RetailerTable = +public type RetailerTable = DocTable; -type ReservedInventoryRouteMap = +public type ReservedInventoryRouteMap = Map; -type ByProduceByRegionInventoryReservationMap = +public type ByProduceByRegionInventoryReservationMap = Map>>; /** @@ -274,7 +274,7 @@ type ByProduceByRegionInventoryReservationMap = ================== */ -type TransporterDoc = { +public type TransporterDoc = { id : T.TransporterId; public_key: Text; // no region; the transporters are the supply of routes, not "end @@ -285,7 +285,7 @@ type TransporterDoc = { reserved : ReservedRouteMap; }; -type TransporterTable = +public type TransporterTable = DocTable; /** @@ -293,7 +293,7 @@ type TransporterTable = ================== */ -type RouteDoc = { +public type RouteDoc = { id : T.RouteId; transporter : T.TransporterId; truck_type : TruckTypeDoc; @@ -305,11 +305,11 @@ type RouteDoc = { // ... more? }; -type RouteTable = +public type RouteTable = DocTable; -type RouteMap = +public type RouteMap = Map; /** @@ -318,10 +318,10 @@ type RouteMap = */ // A possibly-sparse 2D table mapping each region-routeid pair to zero or one routes. -type ByRegionRouteMap = Map; +public type ByRegionRouteMap = Map; // A possibly-sparse 3D table mapping each region-region-routeid triple to zero or one routes. -type ByRegionPairRouteMap = Map; +public type ByRegionPairRouteMap = Map; /** @@ -329,13 +329,13 @@ type ByRegionPairRouteMap = Map; ----------------------------- */ -type ReservedRouteDoc = { +public type ReservedRouteDoc = { id : T.ReservedRouteId; retailer : T.RetailerId; route : RouteDoc; }; -type ReservedRouteTable = DocTable; +public type ReservedRouteTable = DocTable; -type ReservedRouteMap = Map; +public type ReservedRouteMap = Map; } diff --git a/stdlib/examples/produce-exchange/serverTypes.as b/stdlib/examples/produce-exchange/serverTypes.as index 79cb5fd7759..8594fc64628 100644 --- a/stdlib/examples/produce-exchange/serverTypes.as +++ b/stdlib/examples/produce-exchange/serverTypes.as @@ -22,23 +22,23 @@ These types standardize representations for many common notions // import Date // xxx Dates, eventually from a standard library: -type Date = Nat; +public type Date = Nat; // xxx standard weight units? -type Weight = Nat; +public type Weight = Nat; // xxx standard price units? -type Price = Nat; +public type Price = Nat; -type Unit = Nat; // xxx replace with a variant type -type Grade = Nat; // xxx replace with a variant type +public type Unit = Nat; // xxx replace with a variant type +public type Grade = Nat; // xxx replace with a variant type -type TruckCapacity = Weight; +public type TruckCapacity = Weight; -type Quantity = Nat; +public type Quantity = Nat; -type PricePerUnit = Price; // needed to calculate prices -type PriceTotal = Price; +public type PricePerUnit = Price; // needed to calculate prices +public type PriceTotal = Price; /** User Names @@ -49,7 +49,7 @@ Each user of the exchange chooses a unique _user name_, represented as `Text`. In response to this choice, the exchange assigns the user a unique Id (see below); it maintains a mapping from this user name to the (internally-chosen) user Id. */ -type UserName = Text; +public type UserName = Text; /** Unique Ids @@ -63,21 +63,21 @@ Internally, each type of Id serves as a "row key" for a table (or two). */ -type UserId = Nat; +public type UserId = Nat; -type PublicKey = Text; +public type PublicKey = Text; -type RegionId = Nat; -type TruckTypeId = Nat; -type ProduceId = Nat; +public type RegionId = Nat; +public type TruckTypeId = Nat; +public type ProduceId = Nat; -type ProducerId = Nat; -type InventoryId = Nat; -type ReservedInventoryId = Nat; -type RetailerId = Nat; -type TransporterId = Nat; -type RouteId = Nat; -type ReservedRouteId = Nat; +public type ProducerId = Nat; +public type InventoryId = Nat; +public type ReservedInventoryId = Nat; +public type RetailerId = Nat; +public type TransporterId = Nat; +public type RouteId = Nat; +public type ReservedRouteId = Nat; /** `EntId` @@ -86,7 +86,7 @@ type ReservedRouteId = Nat; The optional payload of an `#idErr` error message. */ -type EntId = { +public type EntId = { #user : UserId ; #truckType : TruckTypeId ; #region : RegionId ; @@ -104,14 +104,14 @@ type EntId = { */ /** Optional entity ID */ -type OpEntId = ?EntId; +public type OpEntId = ?EntId; /** `IdErr` --------- An ID error consists only of the `#idErr` case, which carries an optional ID. */ -type IdErr = { +public type IdErr = { #idErr: OpEntId; }; @@ -120,7 +120,7 @@ type IdErr = { ------------ A Server error occurs when the client either has access control issues (e.g., `#publicKeyErr`) or provides invalid parameters (e.g., `#idErr`). */ -type ServerErr = { +public type ServerErr = { #idErr: OpEntId; #publicKeyErr; }; @@ -136,7 +136,7 @@ Public info associated with Ids ------------- */ -type UserInfo = new { +public type UserInfo = { id: UserId; public_key: Text; user_name: Text; @@ -153,7 +153,7 @@ type UserInfo = new { `TruckTypeInfo` ----------------- */ -type TruckTypeInfo = new { +public type TruckTypeInfo = { id : TruckTypeId; short_name : Text; description : Text; @@ -167,7 +167,7 @@ type TruckTypeInfo = new { `RegionInfo` ----------------- */ -type RegionInfo = new { +public type RegionInfo = { id : RegionId; short_name : Text; description : Text; @@ -178,7 +178,7 @@ type RegionInfo = new { ----------------- */ -type ProduceInfo = new { +public type ProduceInfo = { id : ProduceId; short_name : Text; description : Text; @@ -190,7 +190,7 @@ type ProduceInfo = new { ----------------- */ -type ProducerInfo = new { +public type ProducerInfo = { id : ProducerId; public_key: Text; short_name : Text; @@ -205,7 +205,7 @@ type ProducerInfo = new { ----------------- */ -type InventoryInfo = new { +public type InventoryInfo = { id : InventoryId; produce : ProduceId; producer : ProducerId; @@ -222,7 +222,7 @@ type InventoryInfo = new { ----------------------------- */ -type ReservedInventoryInfo = new { +public type ReservedInventoryInfo = { id : ReservedInventoryId; retailer : RetailerId; item : InventoryInfo; @@ -234,7 +234,7 @@ type ReservedInventoryInfo = new { */ // for now, this is the same as a ReservationInfo -type ProduceMarketInfo = new { +public type ProduceMarketInfo = { produce: ProduceId; producer: ProducerId; quant: Quantity; @@ -255,7 +255,7 @@ type ProduceMarketInfo = new { ----------------- */ -type RetailerInfo = new { +public type RetailerInfo = { id : RetailerId; public_key: Text; short_name : Text; @@ -268,7 +268,7 @@ type RetailerInfo = new { ----------------- */ -type TransporterInfo = new { +public type TransporterInfo = { id : TransporterId; public_key: Text; // no region; the transporters are the supply of routes, not "end @@ -284,7 +284,7 @@ type TransporterInfo = new { ----------------- */ -type RouteInfo = new { +public type RouteInfo = { id : RouteId; transporter : TransporterId; truck_type : TruckTypeInfo; @@ -300,7 +300,7 @@ type RouteInfo = new { ----------------- */ -type ReservedRouteInfo = new { +public type ReservedRouteInfo = { id : ReservedRouteId; retailer : RetailerId; route : RouteInfo; @@ -311,7 +311,7 @@ type ReservedRouteInfo = new { ----------------- */ -type ReservationInfo = new { +public type ReservationInfo = { produce: ProduceId; producer: ProducerId; quant: Quantity; @@ -338,7 +338,7 @@ type ReservationInfo = new { Developer-level, counter-based information about the exchange, including counts of each kind of entity. */ -type ProduceExchangeCounts = new { +public type ProduceExchangeCounts = { hash_bit_length : Nat; truck_type_count : Nat; region_count : Nat; @@ -372,7 +372,7 @@ type ProduceExchangeCounts = new { */ // xxx same as a reservation structure; represents a possible reservation to make -type QueryAllResult = ReservationInfo; +public type QueryAllResult = ReservationInfo; /** @@ -384,7 +384,7 @@ the 2019.03.12 ActorScript Team meeting. */ -type QueryAllResults = [QueryAllResult]; +public type QueryAllResults = [QueryAllResult]; /** @@ -394,7 +394,7 @@ type QueryAllResults = [QueryAllResult]; The server can generate synthetic workloads given a small set of parameters. */ -type WorkloadParams = new { +public type WorkloadParams = { day_count:Nat; max_route_duration:Nat; producer_count:Nat; diff --git a/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.as b/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.as index 473b3e4a4c8..ab2a1956886 100644 --- a/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.as +++ b/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.as @@ -1,7 +1,7 @@ -let T = (import "../serverTypes.as"); -let A = (import "../serverActor.as"); -let Result = (import "../../../result.as"); -let Option = (import "../../../option.as"); +import T = "../serverTypes.as"; +import A = "../serverActor.as"; +import Result = "../../../result.as"; +import Option = "../../../option.as"; func printEntityCount(entname:Text, count:Nat) { print ("- " # entname # " count: "); @@ -16,7 +16,7 @@ func printLabeledCost(lab:Text, cost:Nat) { }; actor class Test() = this { - go() { + public func go() { ignore(async { let s = A.Server(); diff --git a/stdlib/hash.as b/stdlib/hash.as index 8be2b2e4568..e772bdb9219 100644 --- a/stdlib/hash.as +++ b/stdlib/hash.as @@ -32,10 +32,10 @@ going forward. */ /** A "bit string" as a linked list of bits: */ -type BitList = ?(Bool, BitList); +public type BitList = ?(Bool, BitList); /** A "bit vector" is a bounded-length bit string packed into a single word: */ -type BitVec = Word32; +public type BitVec = Word32; /** @@ -45,16 +45,16 @@ type BitVec = Word32; */ -module BitVec { +public module BitVec { - type t = BitVec; + public type t = BitVec; // Jenkin's one at a time: // https://en.wikipedia.org/wiki/Jenkins_hash_function#one_at_a_time // // The input type should actually be [Word8]. // Note: Be sure to explode each Word8 of a Word32 into its own Word32, and to shift into lower 8 bits. - func hashWord8s(key:[BitVec]) : BitVec = label profile_hash_hashWord8s : BitVec { + public func hashWord8s(key:[BitVec]) : BitVec = label profile_hash_hashWord8s : BitVec { var hash = natToWord32(0); for (wordOfKey in key.vals()) { label profile_hash_hashWord8s_forLoop : () hash := hash + wordOfKey; @@ -67,11 +67,11 @@ module BitVec { return hash; }; - func length() : Nat = + public func length() : Nat = label profile_hash_length : Nat 31; - func hashOfInt(i:Int) : BitVec = label profile_hash_hashOfInt : BitVec { + public func hashOfInt(i:Int) : BitVec = label profile_hash_hashOfInt : BitVec { //hashInt(i) let j = intToWord32(i); hashWord8s( @@ -82,7 +82,7 @@ module BitVec { ]); }; - func hashOfIntAcc(h1:BitVec, i:Int) : BitVec = label profile_hash_hashOfIntAcc : BitVec { + public func hashOfIntAcc(h1:BitVec, i:Int) : BitVec = label profile_hash_hashOfIntAcc : BitVec { let j = intToWord32(i); hashWord8s( [h1, @@ -93,7 +93,7 @@ module BitVec { ]); }; - func hashOfText(t:Text) : BitVec = label profile_hash_hashOfText : BitVec { + public func hashOfText(t:Text) : BitVec = label profile_hash_hashOfText : BitVec { var x = 0 : Word32; for (c in t.chars()) { x := x ^ charToWord32(c); @@ -102,7 +102,7 @@ module BitVec { }; /** Project a given bit from the bit vector. */ - func getHashBit(h:BitVec, pos:Nat) : Bool = label profile_getHashBit : Bool { + public func getHashBit(h:BitVec, pos:Nat) : Bool = label profile_getHashBit : Bool { assert (pos <= length()); if ((h & (natToWord32(1) << natToWord32(pos))) != natToWord32(0)) { label profile_getHashBit_true : Bool @@ -115,12 +115,12 @@ module BitVec { }; /** Test if two lists of bits are equal. */ - func hashEq(ha:BitVec, hb:BitVec) : Bool { + public func hashEq(ha:BitVec, hb:BitVec) : Bool { label profile_hashEq : Bool ha == hb }; - func bitsPrintRev(bits:BitVec) { + public func bitsPrintRev(bits:BitVec) { for (j in range(0, length() - 1)) { if (getHashBit(bits, j)) { print "1" @@ -130,7 +130,7 @@ module BitVec { } }; - func hashPrintRev(bits:BitVec) { + public func hashPrintRev(bits:BitVec) { for (j in range(length() - 1, 0)) { if (getHashBit(bits, j)) { print "1" @@ -140,7 +140,7 @@ module BitVec { } }; - func toList(v:BitVec) : BitList { + public func toList(v:BitVec) : BitList { func rec(pos:Nat) : BitList { if (pos >= length()) { null } else { @@ -163,16 +163,16 @@ module BitVec { TODO: Replace with bitwise operations on Words, for greater efficiency. */ -module BitList { +public module BitList { - type t = BitList; + public type t = BitList; - func hashOfInt(i:Int) : BitList { + public func hashOfInt(i:Int) : BitList { BitVec.toList(BitVec.hashOfInt(i)) }; /** Test if two lists of bits are equal. */ - func getHashBit(h:BitList, pos:Nat) : Bool { + public func getHashBit(h:BitList, pos:Nat) : Bool { switch h { case null { // XXX: Should be an error case; it shouldn't happen in our tests if we set them up right. @@ -186,7 +186,7 @@ module BitList { }; /** Test if two lists of bits are equal. */ - func hashEq(ha:BitList, hb:BitList) : Bool { + public func hashEq(ha:BitList, hb:BitList) : Bool { switch (ha, hb) { case (null, null) true; case (null, _) false; @@ -198,7 +198,7 @@ module BitList { } }; - func bitsPrintRev(bits:BitList) { + public func bitsPrintRev(bits:BitList) { switch bits { case null { print "" }; case (?(bit,bits_)) { @@ -209,7 +209,7 @@ module BitList { } }; - func hashPrintRev(bits:BitList) { + public func hashPrintRev(bits:BitList) { switch bits { case null { print "" }; case (?(bit,bits_)) { @@ -231,6 +231,6 @@ module BitList { the standard library to use: */ -type Hash = BitVec; -let Hash = BitVec; +public type Hash = BitVec; +public let Hash = BitVec; } diff --git a/stdlib/list.as b/stdlib/list.as index 03c376a1032..05bab397f13 100644 --- a/stdlib/list.as +++ b/stdlib/list.as @@ -17,7 +17,7 @@ remainder of the list (the cell's _tail_). */ -type List = ?(T, List); +public type List = ?(T, List); /** Interface @@ -29,7 +29,7 @@ type List = ?(T, List); ------ empty list */ - func nil() : List = + public func nil() : List = null; @@ -38,7 +38,7 @@ type List = ?(T, List); -------- test for empty list */ - func isNil(l : List) : Bool { + public func isNil(l : List) : Bool { switch l { case null { true }; case _ { false }; @@ -50,7 +50,7 @@ type List = ?(T, List); ------------- aka "list cons" */ - func push(x : T, l : List) : List = + public func push(x : T, l : List) : List = ?(x, l); /** @@ -58,7 +58,7 @@ type List = ?(T, List); ---------- last element, optionally; tail recursive */ - func last(l : List) : ?T = { + public func last(l : List) : ?T = { switch l { case null { null }; case (?(x,null)) { ?x }; @@ -71,7 +71,7 @@ type List = ?(T, List); -------- treat the list as a stack; combines the usual operations `head` and (non-failing) `tail` into one operation */ - func pop(l : List) : (?T, List) = { + public func pop(l : List) : (?T, List) = { switch l { case null { (null, null) }; case (?(h, t)) { (?h, t) }; @@ -83,7 +83,7 @@ type List = ?(T, List); -------- length; tail recursive */ - func len(l : List) : Nat = label profile_list_len : Nat { + public func len(l : List) : Nat = label profile_list_len : Nat { func rec(l : List, n : Nat) : Nat = label profile_list_len_rec : Nat { switch l { case null { n }; @@ -98,7 +98,7 @@ type List = ?(T, List); -------- test length against a maximum value; tail recursive */ - func lenIsEqLessThan(l : List, i : Nat) : Bool = + public func lenIsEqLessThan(l : List, i : Nat) : Bool = label profile_list_lenIsEqLessThan_begin : Bool { func rec(l : List, i : Nat) : Bool = label profile_list_lenIsEqLessThan_rec : Bool { switch l { @@ -122,7 +122,7 @@ type List = ?(T, List); -------- get the length, unless greater than a maximum value, in which return null; tail recursive */ - func lenClamp(l : List, i0 : Nat) : ?Nat = + public func lenClamp(l : List, i0 : Nat) : ?Nat = label profile_list_lenClamp : (?Nat) { func rec(l : List, i : Nat) : ?Nat = label profile_list_lenClamp_rec : (?Nat) { switch l { @@ -146,7 +146,7 @@ type List = ?(T, List); --------- array-like list access, but in linear time; tail recursive */ - func nth(l : List, n : Nat) : ?T = { + public func nth(l : List, n : Nat) : ?T = { switch (n, l) { case (_, null) { null }; case (0, (?(h,t))) { ?h }; @@ -159,7 +159,7 @@ type List = ?(T, List); -------- reverse the list; tail recursive */ - func rev(l : List) : List = { + public func rev(l : List) : List = { func rec(l : List, r : List) : List { switch l { case null { r }; @@ -174,7 +174,7 @@ type List = ?(T, List); --------- Called `app` in SML Basis, and `iter` in OCaml; tail recursive */ - func iter(l : List, f:T -> ()) : () = { + public func iter(l : List, f:T -> ()) : () = { func rec(l : List) : () { switch l { case null { () }; @@ -191,7 +191,7 @@ type List = ?(T, List); Note: need mutable Cons tails for tail-recursive map. */ - func map(l : List, f:T -> S) : List = { + public func map(l : List, f:T -> S) : List = { func rec(l : List) : List { switch l { case null { null }; @@ -206,7 +206,7 @@ type List = ?(T, List); ---------- filter the list elements; non-tail recursive */ - func filter(l : List, f:T -> Bool) : List = { + public func filter(l : List, f:T -> Bool) : List = { func rec(l : List) : List { switch l { case null { null }; @@ -221,7 +221,7 @@ type List = ?(T, List); ---------- split the list elements; non-tail recursive */ - func split(l : List, f:T -> Bool) : (List, List) = { + public func split(l : List, f:T -> Bool) : (List, List) = { func rec(l : List) : (List, List) = label profile_list_split_rec : (List, List) { switch l { @@ -239,7 +239,7 @@ type List = ?(T, List); -------------- map and filter the list elements; non-tail recursive */ - func mapFilter(l : List, f:T -> ?S) : List = { + public func mapFilter(l : List, f:T -> ?S) : List = { func rec(l : List) : List { switch l { case null { null }; @@ -259,7 +259,7 @@ type List = ?(T, List); --------- append two lists; non-tail recursive */ - func append(l : List, m : List) : List = { + public func append(l : List, m : List) : List = { func rec(l : List) : List { switch l { case null { m }; @@ -274,7 +274,7 @@ type List = ?(T, List); ----------- concat (aka "list join"); tail recursive, but requires "two passes" */ - func concat(l : List>) : List = { + public func concat(l : List>) : List = { // 1/2: fold from left to right, reverse-appending the sublists... let r = { let f = func(a:List, b:List) : List { revAppend(a,b) }; @@ -289,7 +289,7 @@ type List = ?(T, List); ------------- See SML Basis library; tail recursive */ - func revAppend(l1 : List, l2 : List) : List = { + public func revAppend(l1 : List, l2 : List) : List = { switch l1 { case null { l2 }; case (?(h,t)) { revAppend(t, ?(h,l2)) }; @@ -302,7 +302,7 @@ type List = ?(T, List); "take" `n` elements from the prefix of the given list. If the given list has fewer than `n` elements, we return the full input list. */ - func take(l : List, n:Nat) : List = { + public func take(l : List, n:Nat) : List = { switch (l, n) { case (_, 0) { null }; case (null,_) { null }; @@ -314,7 +314,7 @@ type List = ?(T, List); `drop` ---------- */ - func drop(l : List, n:Nat) : List = { + public func drop(l : List, n:Nat) : List = { switch (l, n) { case (l_, 0) { l_ }; case (null, _) { null }; @@ -327,7 +327,7 @@ type List = ?(T, List); --------------- fold list left-to-right using function `f`; tail recursive */ - func foldLeft(l : List, a:S, f:(T,S) -> S) : S = { + public func foldLeft(l : List, a:S, f:(T,S) -> S) : S = { func rec(l:List, a:S) : S = { switch l { case null { a }; @@ -342,7 +342,7 @@ type List = ?(T, List); ------------ fold the list right-to-left using function `f`; non-tail recursive */ - func foldRight(l : List, a:S, f:(T,S) -> S) : S = { + public func foldRight(l : List, a:S, f:(T,S) -> S) : S = { func rec(l:List) : S = { switch l { case null { a }; @@ -357,7 +357,7 @@ type List = ?(T, List); ----------- test if there exists list element for which given predicate is true */ - func find(l: List, f:T -> Bool) : ?T = { + public func find(l: List, f:T -> Bool) : ?T = { func rec(l:List) : ?T { switch l { case null { null }; @@ -372,7 +372,7 @@ type List = ?(T, List); --------- test if there exists list element for which given predicate is true */ - func exists(l: List, f:T -> Bool) : Bool = { + public func exists(l: List, f:T -> Bool) : Bool = { func rec(l:List) : Bool { switch l { case null { false }; @@ -389,7 +389,7 @@ type List = ?(T, List); ------- test if given predicate is true for all list elements */ - func all(l: List, f:T -> Bool) : Bool = { + public func all(l: List, f:T -> Bool) : Bool = { func rec(l:List) : Bool { switch l { case null { true }; @@ -404,7 +404,7 @@ type List = ?(T, List); --------- Given two ordered lists, merge them into a single ordered list */ - func merge(l1: List, l2: List, lte:(T,T) -> Bool) : List { + public func merge(l1: List, l2: List, lte:(T,T) -> Bool) : List { func rec(l1: List, l2: List) : List { switch (l1, l2) { case (null, _) { l2 }; @@ -429,7 +429,7 @@ type List = ?(T, List); To do: Eventually, follow `collate` design from SML Basis, with real sum types, use 3-valued `order` type here. */ - func lessThanEq(l1: List, l2: List, lte:(T,T) -> Bool) : Bool { + public func lessThanEq(l1: List, l2: List, lte:(T,T) -> Bool) : Bool { func rec(l1: List, l2: List) : Bool { switch (l1, l2) { case (null, _) { true }; @@ -447,7 +447,7 @@ type List = ?(T, List); `isEq(l1, l2)` is equivalent to `lessThanEq(l1,l2) && lessThanEq(l2,l1)`, but the former is more efficient. */ - func isEq(l1: List, l2: List, eq:(T,T) -> Bool) : Bool { + public func isEq(l1: List, l2: List, eq:(T,T) -> Bool) : Bool { func rec(l1: List, l2: List) : Bool { switch (l1, l2) { case (null, null) { true }; @@ -465,7 +465,7 @@ type List = ?(T, List); using a predicate, create two lists from one: the "true" list, and the "false" list. (See SML basis library); non-tail recursive. */ - func partition(l: List, f:T -> Bool) : (List, List) { + public func partition(l: List, f:T -> Bool) : (List, List) { func rec(l: List) : (List, List) { switch l { case null { (null, null) }; @@ -488,7 +488,7 @@ type List = ?(T, List); generate a list based on a length, and a function from list index to list element. (See SML basis library); non-tail recursive. */ - func tabulate(n:Nat, f:Nat -> T) : List { + public func tabulate(n:Nat, f:Nat -> T) : List { func rec(i:Nat) : List { if (i == n) { null } else { ?(f(i), rec(i+1)) } }; diff --git a/stdlib/option.as b/stdlib/option.as index 4d0398e06bd..c992ebac0bf 100644 --- a/stdlib/option.as +++ b/stdlib/option.as @@ -5,9 +5,9 @@ Functions for Option types. */ -private import P "prelude.as"; +import P "prelude.as"; -type t = ?A; +public type t = ?A; /*** @@ -17,13 +17,13 @@ type t = ?A; Returns true if the value is not `null`. */ -func isSomeAny(x: ?Any): Bool = +public func isSomeAny(x: ?Any): Bool = switch x { case null false; case _ true; }; -func isSome(x: t): Bool = isSomeAny(x); +public func isSome(x: t): Bool = isSomeAny(x); /*** @@ -33,9 +33,9 @@ func isSome(x: t): Bool = isSomeAny(x); Returns true if the value is `null`. */ -func isNullAny(x: ?Any): Bool = not isSome(x); +public func isNullAny(x: ?Any): Bool = not isSome(x); -func isNull(x: t): Bool = not isSome(x); +public func isNull(x: t): Bool = not isSome(x); /*** @@ -45,7 +45,7 @@ func isNull(x: t): Bool = not isSome(x); Unwrap an optional value, and fail if it is `null`. */ -func unwrap(x: ?T): T = +public func unwrap(x: ?T): T = switch x { case null { P.unreachable() }; case (?x_) x_; @@ -59,7 +59,7 @@ func unwrap(x: ?T): T = Unwrap an optional value or a default. */ -func unwrapOr(x: ?T, d: T): T = +public func unwrapOr(x: ?T, d: T): T = switch x { case null { d }; case (?x_) x_; @@ -73,7 +73,7 @@ func unwrapOr(x: ?T, d: T): T = Unwrap an optional value. If null, return the default, else, apply the function to the unwrapped value. */ -func option(x: ?A, f: A->B, d: B): B = +public func option(x: ?A, f: A->B, d: B): B = switch x { case null { d }; case (?x_) f(x_); @@ -87,7 +87,7 @@ func option(x: ?A, f: A->B, d: B): B = Apply a function to the wrapped value. */ -func map(x: ?A, f: A->B): ?B = +public func map(x: ?A, f: A->B): ?B = switch x { case null null; case (?x_) ?f(x_); @@ -101,7 +101,7 @@ func map(x: ?A, f: A->B): ?B = Apply a function to the wrapped value. */ -func fmap(x: ?A, f: A->?B): ?B = +public func fmap(x: ?A, f: A->?B): ?B = switch x { case null null; case (?x_) f(x_); @@ -115,13 +115,13 @@ func fmap(x: ?A, f: A->?B): ?B = Assert that the given value is not `null`; ignore this value and return unit. */ -func assertSomeAny(x: ?Any) = +public func assertSomeAny(x: ?Any) = switch x { case null { P.unreachable() }; case _ {}; }; -func assertSome(x: ?A) = assertSomeAny(x); +public func assertSome(x: ?A) = assertSomeAny(x); /*** @@ -131,13 +131,13 @@ func assertSome(x: ?A) = assertSomeAny(x); Assert that the given value is `null`; ignore this value and return unit. */ -func assertNullAny(x: ?Any) = +public func assertNullAny(x: ?Any) = switch x { case null { }; case _ { P.unreachable() }; }; -func assertNull(x: ?A) = assertNullAny(x); +public func assertNull(x: ?A) = assertNullAny(x); /*** @@ -147,7 +147,7 @@ func assertNull(x: ?A) = assertNullAny(x); Print an optional integer. */ -func printOpInt(x : ?Int) = +public func printOpInt(x : ?Int) = switch x { case null { print "null" }; case (?x_) { print "?"; printInt x_ }; diff --git a/stdlib/prelude.as b/stdlib/prelude.as index 0d66aed63e1..2588945387c 100644 --- a/stdlib/prelude.as +++ b/stdlib/prelude.as @@ -22,10 +22,10 @@ trap in all execution contexts. */ -func nyi() : None = +public func nyi() : None = { assert false ; loop { } }; -func xxx() : None = +public func xxx() : None = { assert false ; loop { } }; /*** @@ -39,5 +39,5 @@ func xxx() : None = trap in all execution contexts. */ -func unreachable() : None = { assert false ; loop { } }; +public func unreachable() : None = { assert false ; loop { } }; } diff --git a/stdlib/result.as b/stdlib/result.as index 251eed233b1..101fbb249a7 100644 --- a/stdlib/result.as +++ b/stdlib/result.as @@ -1,5 +1,5 @@ module { -private import P "prelude.as"; +import P "prelude.as"; /** @@ -14,7 +14,7 @@ private import P "prelude.as"; */ -type Result = { +public type Result = { #ok:Ok; #err:Err; }; @@ -26,7 +26,7 @@ type Result = { --------------- assert that we can unwrap the result; should only be used in tests, not in canister implementations. This will trap. */ -func assertUnwrap(r:Result):Ok { +public func assertUnwrap(r:Result):Ok { switch(r) { case (#err e) P.unreachable(); case (#ok r) r; @@ -37,7 +37,7 @@ func assertUnwrap(r:Result):Ok { `assertUnwrapAny` --------------- */ -func assertUnwrapAny(r:Result):Ok { +public func assertUnwrapAny(r:Result):Ok { switch(r) { case (#err e) P.unreachable(); case (#ok r) r; @@ -48,7 +48,7 @@ func assertUnwrapAny(r:Result):Ok { `assertOk` --------------- */ -func assertOk(r:Result) { +public func assertOk(r:Result) { switch(r) { case (#err _) assert false; case (#ok _) (); @@ -59,7 +59,7 @@ func assertOk(r:Result) { `assertErr` --------------- */ -func assertErr(r:Result) { +public func assertErr(r:Result) { switch(r) { case (#err _) (); case (#ok _) assert false; @@ -70,14 +70,14 @@ func assertErr(r:Result) { `assertErrIs` --------------- */ -func assertErrIs(r:Result, f:E->Bool) : Bool = +public func assertErrIs(r:Result, f:E->Bool) : Bool = assertErrAs(r, f); /** `assertErrAs` --------------- */ -func assertErrAs(r:Result, f:E->X) : X { +public func assertErrAs(r:Result, f:E->X) : X { switch(r) { case (#err e) f e; case (#ok _) P.unreachable(); @@ -89,7 +89,7 @@ func assertErrAs(r:Result, f:E->X) : X { ------- bind operation in result monad. */ -func bind( +public func bind( x:Result, y:R1 -> Result) : Result { switch x { @@ -104,7 +104,7 @@ func bind( ------- map the `Ok` type/value, leaving any `Error` type/value unchanged. */ -func mapOk( +public func mapOk( x:Result, y:Ok1 -> Ok2) : Result { switch x { @@ -118,7 +118,7 @@ func mapOk( -------------- create a result from an option, including an error value to handle the `null` case. */ -func fromOption(x:?R, err:E):Result { +public func fromOption(x:?R, err:E):Result { switch x { case (? x) {#ok x}; case null {#err err}; @@ -130,7 +130,7 @@ func fromOption(x:?R, err:E):Result { -------------- map the `Ok` type/value from the optional value, or else use the given error value. */ -func fromSomeMap(x:?R1, f:R1->R2, err:E):Result { +public func fromSomeMap(x:?R1, f:R1->R2, err:E):Result { switch x { case (? x) {#ok (f x)}; case null {#err err}; @@ -142,7 +142,7 @@ func fromSomeMap(x:?R1, f:R1->R2, err:E):Result { --------------- asserts that the option is Some(_) form. */ -func fromSome(o:?Ok):Result { +public func fromSome(o:?Ok):Result { switch(o) { case (?o) (#ok o); case _ P.unreachable(); @@ -154,7 +154,7 @@ func fromSome(o:?Ok):Result { --------------- a result that consists of an array of Ok results from an array of results, or the first error in the result array, if any. */ -func joinArrayIfOk(x:[Result]) : Result<[R],E> { +public func joinArrayIfOk(x:[Result]) : Result<[R],E> { /**- return early with the first Err result, if any */ for (i in x.keys()) { switch (x[i]) { diff --git a/stdlib/set.as b/stdlib/set.as index d9aaca6b273..826d6ab5b0b 100644 --- a/stdlib/set.as +++ b/stdlib/set.as @@ -18,32 +18,32 @@ */ module { -private import Trie "trie2.as"; -private import Hash "hash.as"; +import Trie "trie2.as"; +import Hash "hash.as"; -type Hash = Hash.Hash; -type Set = Trie.Trie; +public type Hash = Hash.Hash; +public type Set = Trie.Trie; - func empty():Set = + public func empty():Set = Trie.empty(); - func insert(s:Set, x:T, xh:Hash, eq:(T,T)->Bool) : Set = { + public func insert(s:Set, x:T, xh:Hash, eq:(T,T)->Bool) : Set = { let (s2, _) = Trie.insert(s, new {key=x; hash=xh}, eq, ()); s2 }; - func remove(s:Set, x:T, xh:Hash, eq:(T,T)->Bool) : Set = { + public func remove(s:Set, x:T, xh:Hash, eq:(T,T)->Bool) : Set = { let (s2, _) = Trie.remove(s, new {key=x; hash=xh}, eq); s2 }; - func eq(s1:Set, s2:Set, eq:(T,T)->Bool):Bool { + public func eq(s1:Set, s2:Set, eq:(T,T)->Bool):Bool { // XXX: Todo: use a smarter check Trie.equalStructure(s1, s2, eq, unitEq) }; - func card(s:Set) : Nat { + public func card(s:Set) : Nat { Trie.foldUp (s, func(n:Nat,m:Nat):Nat{n+m}, @@ -51,28 +51,28 @@ type Set = Trie.Trie; 0) }; - func mem(s:Set, x:T, xh:Hash, eq:(T,T)->Bool):Bool { + public func mem(s:Set, x:T, xh:Hash, eq:(T,T)->Bool):Bool { switch (Trie.find(s, new {key=x; hash=xh}, eq)) { case null { false }; case (?_) { true }; } }; - func union(s1:Set, s2:Set, eq:(T,T)->Bool):Set { + public func union(s1:Set, s2:Set, eq:(T,T)->Bool):Set { let s3 = Trie.merge(s1, s2, eq); s3 }; - func diff(s1:Set, s2:Set, eq:(T,T)->Bool):Set { + public func diff(s1:Set, s2:Set, eq:(T,T)->Bool):Set { let s3 = Trie.diff(s1, s2, eq); s3 }; - func intersect(s1:Set, s2:Set, eq:(T,T)->Bool):Set { + public func intersect(s1:Set, s2:Set, eq:(T,T)->Bool):Set { let noop : ((),())->(()) = func (_:(),_:()):(())=(); let s3 = Trie.join(s1, s2, eq, noop); s3 }; - func unitEq (_:(),_:()):Bool{ true }; + public func unitEq (_:(),_:()):Bool{ true }; } diff --git a/stdlib/trie.as b/stdlib/trie.as index 8deba6e2249..f3293e1ba18 100644 --- a/stdlib/trie.as +++ b/stdlib/trie.as @@ -61,20 +61,20 @@ See the full details in the definitions below: */ -private import H "hash.as"; -let Hash = H.BitVec; -type Hash = Hash.t; +import H "hash.as"; +public let Hash = H.BitVec; +public type Hash = Hash.t; -private import List "list.as"; -type List = List.List; +import List "list.as"; +public type List = List.List; -private import AssocList "assocList.as"; -type AssocList = AssocList.AssocList; +import AssocList "assocList.as"; +public type AssocList = AssocList.AssocList; -let HASH_BITS = 4; +public let HASH_BITS = 4; //let HASH_BITS = 16; -type Key = { +public type Key = { // hash field: permits fast inequality checks, permits collisions; // (eventually: permits incremental growth of deeper trie paths) hash: Hash; @@ -83,24 +83,24 @@ type Key = { }; // Binary branch nodes -type Branch = { +public type Branch = { left:Trie; right:Trie; }; // Leaf nodes are association lists of `Key`s where every key // shares a common hash prefix, its (common) trie path. -type Leaf = { +public type Leaf = { keyvals:AssocList,V>; }; // XXX: See AST-42 -type Node = { +public type Node = { left:Trie; right:Trie; keyvals:AssocList,V>; }; -type Trie = ?Node; +public type Trie = ?Node; /** Association lists @@ -116,7 +116,7 @@ type Trie = ?Node; A 2D trie is just a trie that maps dimension-1 keys to another layer of tries, each keyed on the dimension-2 keys. */ -type Trie2D = Trie >; +public type Trie2D = Trie >; /** Three-dimensional trie @@ -124,7 +124,7 @@ type Trie2D = Trie >; A 3D trie is just a trie that maps dimension-1 keys to another layer of 2D tries, each keyed on the dimension-2 and dimension-3 keys. */ -type Trie3D = Trie >; +public type Trie3D = Trie >; /** Module interface @@ -144,7 +144,7 @@ type Trie3D = Trie >; -------- An empty trie. */ - func empty() : Trie = makeEmpty(); + public func empty() : Trie = makeEmpty(); /** `copy` @@ -153,14 +153,14 @@ type Trie3D = Trie >; */ - func copy(t : Trie) : Trie = t; + public func copy(t : Trie) : Trie = t; /** `replace` --------- replace the given key's value option with the given one, returning the previous one */ - func replace(t : Trie, k:Key, k_eq:(K,K)->Bool, v:?V) : (Trie, ?V) { + public func replace(t : Trie, k:Key, k_eq:(K,K)->Bool, v:?V) : (Trie, ?V) { let key_eq = keyEq(k_eq); // For `bitpos` in 0..HASH_BITS, walk the given trie and locate the given value `x`, if it exists. func rec(t : Trie, bitpos:Nat) : (Trie, ?V) { @@ -205,7 +205,7 @@ type Trie3D = Trie >; and only if successful, do the success continuation, otherwise, return the failure value */ - func replaceThen(t : Trie, k:Key, k_eq:(K,K)->Bool, v2:V, + public func replaceThen(t : Trie, k:Key, k_eq:(K,K)->Bool, v2:V, success: (Trie, V) -> X, fail: () -> X) : X @@ -222,7 +222,7 @@ type Trie3D = Trie >; ------------ insert the given key's value in the trie; return the new trie, and the previous value associated with the key, if any */ - func insert(t : Trie, k:Key, k_eq:(K,K)->Bool, v:V) : (Trie, ?V) { + public func insert(t : Trie, k:Key, k_eq:(K,K)->Bool, v:V) : (Trie, ?V) { replace(t, k, k_eq, ?v) }; @@ -231,7 +231,7 @@ type Trie3D = Trie >; ---------------- insert the given key's value in the trie; return the new trie; assert that no prior value is associated with the key */ - func insertFresh(t : Trie, k:Key, k_eq:(K,K)->Bool, v:V) : Trie { + public func insertFresh(t : Trie, k:Key, k_eq:(K,K)->Bool, v:V) : Trie { let (t2, none) = replace(t, k, k_eq, ?v); switch none { case (null) (); @@ -245,7 +245,7 @@ type Trie3D = Trie >; --------------- insert the given key's value in the 2D trie; return the new 2D trie. */ - func insert2D(t : Trie2D, + public func insert2D(t : Trie2D, k1:Key, k1_eq:(K1,K1)->Bool, k2:Key, k2_eq:(K2,K2)->Bool, v:V) @@ -265,7 +265,7 @@ type Trie3D = Trie >; --------------- insert the given key's value in the trie; return the new trie; */ - func insert3D + public func insert3D (t : Trie3D, k1:Key, k1_eq:(K1,K1)->Bool, k2:Key, k2_eq:(K2,K2)->Bool, @@ -300,7 +300,7 @@ type Trie3D = Trie >; ------------- remove the given key's value in the trie; return the new trie */ - func remove(t : Trie, k:Key, k_eq:(K,K)->Bool) : (Trie, ?V) { + public func remove(t : Trie, k:Key, k_eq:(K,K)->Bool) : (Trie, ?V) { replace(t, k, k_eq, null) }; @@ -311,7 +311,7 @@ type Trie3D = Trie >; and only if successful, do the success continuation, otherwise, return the failure value */ - func removeThen(t : Trie, k:Key, k_eq:(K,K)->Bool, + public func removeThen(t : Trie, k:Key, k_eq:(K,K)->Bool, success: (Trie, V) -> X, fail: () -> X) : X @@ -330,7 +330,7 @@ type Trie3D = Trie >; remove the given key-key pair's value in the 2D trie; return the new trie, and the prior value, if any. */ - func remove2D(t : Trie2D, + public func remove2D(t : Trie2D, k1:Key, k1_eq:(K1,K1)->Bool, k2:Key, k2_eq:(K2,K2)->Bool) : (Trie2D, ?V) @@ -355,7 +355,7 @@ type Trie3D = Trie >; remove the given key-key pair's value in the 3D trie; return the new trie, and the prior value, if any. */ - func remove3D + public func remove3D (t : Trie3D, k1:Key, k1_eq:(K1,K1)->Bool, k2:Key, k2_eq:(K2,K2)->Bool, @@ -383,7 +383,7 @@ type Trie3D = Trie >; --------- find the given key's value in the trie, or return null if nonexistent */ - func find(t : Trie, k:Key, k_eq:(K,K) -> Bool) : ?V { + public func find(t : Trie, k:Key, k_eq:(K,K) -> Bool) : ?V { let key_eq = keyEq(k_eq); // For `bitpos` in 0..HASH_BITS, walk the given trie and locate the given value `x`, if it exists. func rec(t : Trie, bitpos:Nat) : ?V { label profile_trie_find_rec : (?V) @@ -434,7 +434,7 @@ type Trie3D = Trie >; - [`prod`](#prod) */ - func merge(tl:Trie, tr:Trie, k_eq:(K,K)->Bool): Trie { + public func merge(tl:Trie, tr:Trie, k_eq:(K,K)->Bool): Trie { let key_eq = keyEq(k_eq); func rec(tl:Trie, tr:Trie) : Trie { switch (tl, tr) { @@ -486,7 +486,7 @@ type Trie3D = Trie >; dynamic error if there are collisions in common keys between the left and right inputs. */ - func mergeDisjoint(tl:Trie, tr:Trie, k_eq:(K,K)->Bool): Trie { + public func mergeDisjoint(tl:Trie, tr:Trie, k_eq:(K,K)->Bool): Trie { let key_eq = keyEq(k_eq); func rec(tl:Trie, tr:Trie) : Trie { switch (tl, tr) { @@ -548,7 +548,7 @@ type Trie3D = Trie >; trie. */ - func mergeDisjoint2D(t : Trie2D, k1_eq:(K1,K1)->Bool, k2_eq:(K2,K2)->Bool) + public func mergeDisjoint2D(t : Trie2D, k1_eq:(K1,K1)->Bool, k2_eq:(K2,K2)->Bool) : Trie { foldUp, Trie> @@ -565,7 +565,7 @@ type Trie3D = Trie >; the left trie whose keys are not present in the right trie; the values of the right trie are irrelevant. */ - func diff(tl:Trie, tr:Trie, k_eq:(K,K)->Bool) : Trie { + public func diff(tl:Trie, tr:Trie, k_eq:(K,K)->Bool) : Trie { let key_eq = keyEq(k_eq); func rec(tl:Trie, tr:Trie) : Trie { switch (tl, tr) { @@ -625,7 +625,7 @@ type Trie3D = Trie >; - [`prod`](#prod) */ - func disj(tl:Trie, tr:Trie, + public func disj(tl:Trie, tr:Trie, k_eq:(K,K)->Bool, vbin:(?V,?W)->X) : Trie { @@ -704,7 +704,7 @@ type Trie3D = Trie >; - [`prod`](#prod) */ - func join(tl:Trie, tr:Trie, + public func join(tl:Trie, tr:Trie, k_eq:(K,K)->Bool, vbin:(V,W)->X) : Trie { @@ -767,7 +767,7 @@ type Trie3D = Trie >; - [`merge`](#merge) */ - func prod( + public func prod( tl :Trie, tr :Trie, op :(K1,V1,K2,V2) -> ?(Key,V3), @@ -806,7 +806,7 @@ type Trie3D = Trie >; either as clients, or as hand-specialized versions (e.g., see map, mapFilter, exists and forAll below). */ - func foldUp(t:Trie, bin:(X,X)->X, leaf:(K,V)->X, empty:X) : X { + public func foldUp(t:Trie, bin:(X,X)->X, leaf:(K,V)->X, empty:X) : X { func rec(t:Trie) : X { switch t { case (null) { empty }; @@ -832,7 +832,7 @@ type Trie3D = Trie >; Fold over the key-value pairs of the trie, using an accumulator. The key-value pairs have no reliable or meaningful ordering. */ - func fold(t:Trie, f:(K,V,X)->X, x:X) : X { + public func fold(t:Trie, f:(K,V,X)->X, x:X) : X { func rec(t:Trie, x:X) : X { switch t { case (null) x; @@ -856,7 +856,7 @@ type Trie3D = Trie >; -------- Test whether a given key-value pair is present, or not. */ - func exists(t:Trie, f:(K,V)->Bool) : Bool { + public func exists(t:Trie, f:(K,V)->Bool) : Bool { func rec(t:Trie) : Bool { switch t { case (null) { false }; @@ -880,7 +880,7 @@ type Trie3D = Trie >; --------- Test whether all key-value pairs have a given property. */ - func forAll(t:Trie, f:(K,V)->Bool) : Bool { + public func forAll(t:Trie, f:(K,V)->Bool) : Bool { func rec(t:Trie) : Bool { switch t { case (null) { true }; @@ -903,7 +903,7 @@ type Trie3D = Trie >; -------- Count the number of entries in the trie. */ - func count(t:Trie):Nat{ + public func count(t:Trie):Nat{ foldUp (t, func(n:Nat,m:Nat):Nat{n+m}, @@ -918,7 +918,7 @@ type Trie3D = Trie >; To do: make this more efficient, using a single array allocation. */ - func toArray(t:Trie,f:(K,V)->[W]):[W] = + public func toArray(t:Trie,f:(K,V)->[W]):[W] = label profile_trie_toArray_begin : [W] { func arrayAppend(x:[W],y:[W]):[W] { label profile_trie_toArray_arrayAppend : [W] @@ -947,7 +947,7 @@ type Trie3D = Trie >; but no leaves. These can result from naive filtering operations; filter uses this function to avoid creating such subtrees. */ - func isEmpty(t:Trie) : Bool { + public func isEmpty(t:Trie) : Bool { func rec(t:Trie) : Bool { switch t { case (null) { true }; @@ -967,7 +967,7 @@ type Trie3D = Trie >; ----------- filter the key-value pairs by a given predicate. */ - func filter(t:Trie, f:(K,V)->Bool) : Trie { + public func filter(t:Trie, f:(K,V)->Bool) : Trie { func rec(t:Trie) : Trie { switch t { case (null) { null }; @@ -1001,7 +1001,7 @@ type Trie3D = Trie >; ----------- map and filter the key-value pairs by a given partial mapping function. */ - func mapFilter(t:Trie, f:(K,V)->?W) : Trie { + public func mapFilter(t:Trie, f:(K,V)->?W) : Trie { func rec(t:Trie) : Trie { switch t { case (null) { null }; @@ -1049,7 +1049,7 @@ type Trie3D = Trie >; `#empty`. We do not observe that equality here. */ - func equalStructure( + public func equalStructure( tl:Trie, tr:Trie, keq:(K,K)->Bool, @@ -1083,7 +1083,7 @@ type Trie3D = Trie >; }; // Equality function for two `Key`s, in terms of equaltiy of `K`'s. - func keyEq(keq:(K,K) -> Bool) : ((Key,Key) -> Bool) = { + public func keyEq(keq:(K,K) -> Bool) : ((Key,Key) -> Bool) = { func (key1:Key, key2:Key) : Bool = label profile_trie_keyEq : Bool (Hash.hashEq(key1.hash, key2.hash) and keq(key1.key, key2.key)) @@ -1097,7 +1097,7 @@ type Trie3D = Trie >; // @Omit: // XXX: until AST-42: - func isNull(x : ?X) : Bool { + public func isNull(x : ?X) : Bool { switch x { case null { true }; case (?_) { false }; @@ -1105,7 +1105,7 @@ type Trie3D = Trie >; }; // XXX: until AST-42: - func assertIsNull(x : ?X) { + public func assertIsNull(x : ?X) { label profile_trie_assertIsNull switch x { case null { assert(true) }; @@ -1114,11 +1114,11 @@ type Trie3D = Trie >; }; // XXX: until AST-42: - func makeEmpty() : Trie + public func makeEmpty() : Trie = null; // XXX: until AST-42: - func assertIsEmpty(t : Trie) { + public func assertIsEmpty(t : Trie) { switch t { case null { assert(true) }; case (?_) { assert(false) }; @@ -1126,12 +1126,12 @@ type Trie3D = Trie >; }; // XXX: until AST-42: - func makeBin(l:Trie, r:Trie) : Trie { + public func makeBin(l:Trie, r:Trie) : Trie { ?(new {left=l; right=r; keyvals=null; }) }; // XXX: until AST-42: - func isBin(t:Trie) : Bool { + public func isBin(t:Trie) : Bool { switch t { case null { false }; case (?t_) { @@ -1144,12 +1144,12 @@ type Trie3D = Trie >; }; // XXX: until AST-42: - func makeLeaf(kvs:AssocList,V>) : Trie { + public func makeLeaf(kvs:AssocList,V>) : Trie { ?(new {left=null; right=null; keyvals=kvs }) }; // XXX: until AST-42: - func matchLeaf(t:Trie) : ?AssocList,V> { + public func matchLeaf(t:Trie) : ?AssocList,V> { switch t { case null { null }; case (?t_) { @@ -1162,7 +1162,7 @@ type Trie3D = Trie >; }; // XXX: until AST-42: - func isLeaf(t:Trie) : Bool { + public func isLeaf(t:Trie) : Bool { switch t { case null { false }; case (?t_) { @@ -1174,7 +1174,7 @@ type Trie3D = Trie >; } }; // XXX: until AST-42: - func assertIsBin(t : Trie) { + public func assertIsBin(t : Trie) { switch t { case null { assert(false) }; case (?n) { @@ -1184,7 +1184,7 @@ type Trie3D = Trie >; }; // XXX: until AST-42: - func getLeafKey(t : Node) : Key { + public func getLeafKey(t : Node) : Key { assertIsNull>(t.left); assertIsNull>(t.right); switch (t.keyvals) { @@ -1194,7 +1194,7 @@ type Trie3D = Trie >; }; // XXX: this helper is an ugly hack; we need real sum types to avoid it, I think: - func getLeafVal(t : Node) : V { + public func getLeafVal(t : Node) : V { assertIsNull>(t.left); assertIsNull>(t.right); switch (t.keyvals) { @@ -1216,7 +1216,7 @@ type Trie3D = Trie >; helper function for constructing new paths of uniform length */ - func buildNewPath(bitpos:Nat, k:Key, ov:?V) : Trie { + public func buildNewPath(bitpos:Nat, k:Key, ov:?V) : Trie { func rec(bitpos:Nat) : Trie { if ( bitpos < HASH_BITS ) { // create new bin node for this bit of the hash diff --git a/stdlib/trie2.as b/stdlib/trie2.as index ac5355f9211..9b69581daf1 100644 --- a/stdlib/trie2.as +++ b/stdlib/trie2.as @@ -69,26 +69,26 @@ Below, we define the types used in the representation: */ //let MAX_LEAF_COUNT = 4; // worse than 8, slightly -let MAX_LEAF_COUNT = 8; // <-- beats both 4 and 16 for me, now +public let MAX_LEAF_COUNT = 8; // <-- beats both 4 and 16 for me, now //let MAX_LEAF_COUNT = 16; //let MAX_LEAF_COUNT = 32; -private import P "prelude.as"; +import P "prelude.as"; -private import Option "option.as"; +import Option "option.as"; -private import H "hash.as"; -let Hash = H.BitVec; -type Hash = Hash.t; +import H "hash.as"; +public let Hash = H.BitVec; +public type Hash = Hash.t; -private import List "list.as"; -type List = List.List; +import List "list.as"; +public type List = List.List; -private import AssocList "assocList.as"; -type AssocList = AssocList.AssocList; +import AssocList "assocList.as"; +public type AssocList = AssocList.AssocList; /** A `Key` for the trie has an associated hash value */ -type Key = { +public type Key = { /** `hash` permits fast inequality checks, and permits collisions */ hash: Hash; /** `key` permits percise equality checks, but only used after equal hashes. */ @@ -96,14 +96,14 @@ type Key = { }; /** Equality function for two `Key`s, in terms of equaltiy of `K`'s. */ -func keyEq(keq:(K,K) -> Bool) : ((Key,Key) -> Bool) = { +public func keyEq(keq:(K,K) -> Bool) : ((Key,Key) -> Bool) = { func (key1:Key, key2:Key) : Bool = label profile_trie_keyEq : Bool (Hash.hashEq(key1.hash, key2.hash) and keq(key1.key, key2.key)) }; /** leaf nodes of trie consist of key-value pairs as a list. */ -type Leaf = { +public type Leaf = { count : Nat ; keyvals : AssocList,V> ; }; @@ -112,20 +112,20 @@ type Leaf = { we never store this bitpos; rather, we enforce a style where this position is always known from context. */ -type Branch = { +public type Branch = { count : Nat ; left : Trie ; right : Trie ; }; /** binary hash tries: either empty, a leaf node, or a branch node */ -type Trie = { +public type Trie = { #empty ; #leaf : Leaf ; #branch : Branch ; }; -func isValid (t:Trie, enforceNormal:Bool) : Bool { +public func isValid (t:Trie, enforceNormal:Bool) : Bool { func rec(t:Trie, bitpos:?Hash, bits:Hash, mask:Hash) : Bool { switch t { case (#empty) { @@ -185,7 +185,7 @@ func isValid (t:Trie, enforceNormal:Bool) : Bool { A 2D trie is just a trie that maps dimension-1 keys to another layer of tries, each keyed on the dimension-2 keys. */ -type Trie2D = Trie >; +public type Trie2D = Trie >; /** Three-dimensional trie @@ -193,7 +193,7 @@ type Trie2D = Trie >; A 3D trie is just a trie that maps dimension-1 keys to another layer of 2D tries, each keyed on the dimension-2 and dimension-3 keys. */ -type Trie3D = Trie >; +public type Trie3D = Trie >; /** Module interface @@ -205,7 +205,7 @@ type Trie3D = Trie >; -------- An empty trie. */ - func empty() : Trie = +public func empty() : Trie = #empty; /** @@ -219,7 +219,7 @@ type Trie3D = Trie >; acceptable level of algorithmic efficiently. */ - func count(t: Trie) : Nat = label profile_trie_count : Nat { +public func count(t: Trie) : Nat = label profile_trie_count : Nat { switch t { case (#empty) 0; case (#leaf l) l.count; @@ -232,7 +232,7 @@ type Trie3D = Trie >; -------- Construct a branch node, computing the count stored there. */ - func branch(l:Trie, r:Trie) : Trie = label profile_trie_branch : Trie { +public func branch(l:Trie, r:Trie) : Trie = label profile_trie_branch : Trie { let sum = count(l) + count(r); #branch( new{ @@ -253,11 +253,11 @@ type Trie3D = Trie >; of the leaf. */ - func leaf(kvs:AssocList,V>, bitpos:Nat) : Trie = label trie_leaf : Trie { +public func leaf(kvs:AssocList,V>, bitpos:Nat) : Trie = label trie_leaf : Trie { fromSizedList(null, kvs, bitpos) }; - func fromList(kvs:AssocList,V>, bitpos:Nat) : Trie = +public func fromList(kvs:AssocList,V>, bitpos:Nat) : Trie = label profile_trie_fromList_begin : (Trie) { func rec(kvs:AssocList,V>, bitpos:Nat) : Trie { if ( List.isNil<(Key,V)>(kvs) ) @@ -284,7 +284,7 @@ type Trie3D = Trie >; }; - func fromSizedList(kvc:?Nat, kvs:AssocList,V>, bitpos:Nat) : Trie = +public func fromSizedList(kvc:?Nat, kvs:AssocList,V>, bitpos:Nat) : Trie = label profile_trie_fromList_begin : (Trie) { func rec(kvc:?Nat, kvs:AssocList,V>, bitpos:Nat) : Trie { switch kvc { @@ -325,14 +325,14 @@ type Trie3D = Trie >; --------- Purely-functional representation permits _O(1)_-time copy, via persistent sharing. */ - func copy(t : Trie) : Trie = t; +public func copy(t : Trie) : Trie = t; /** `replace` --------- replace the given key's value option with the given one, returning the previous one */ - func replace(t : Trie, k:Key, k_eq:(K,K)->Bool, v:?V) : (Trie, ?V) = +public func replace(t : Trie, k:Key, k_eq:(K,K)->Bool, v:?V) : (Trie, ?V) = label profile_trie_replace : (Trie, ?V) { let key_eq = keyEq(k_eq); @@ -372,7 +372,7 @@ type Trie3D = Trie >; ------------ insert the given key's value in the trie; return the new trie, and the previous value associated with the key, if any */ - func insert(t : Trie, k:Key, k_eq:(K,K)->Bool, v:V) : (Trie, ?V) = +public func insert(t : Trie, k:Key, k_eq:(K,K)->Bool, v:V) : (Trie, ?V) = label profile_trie_insert : (Trie, ?V) { replace(t, k, k_eq, ?v) }; @@ -382,7 +382,7 @@ type Trie3D = Trie >; --------- find the given key's value in the trie, or return null if nonexistent */ - func find(t : Trie, k:Key, k_eq:(K,K) -> Bool) : ?V = label profile_trie_find : (?V) { +public func find(t : Trie, k:Key, k_eq:(K,K) -> Bool) : ?V = label profile_trie_find : (?V) { let key_eq = keyEq(k_eq); func rec(t : Trie, bitpos:Nat) : ?V = label profile_trie_find_rec : (?V) { switch t { @@ -413,7 +413,7 @@ type Trie3D = Trie >; - func splitAssocList(al:AssocList,V>, bitpos:Nat) +public func splitAssocList(al:AssocList,V>, bitpos:Nat) : (AssocList,V>, AssocList,V>) = label profile_trie_splitAssocList : (AssocList,V>, AssocList,V>) { @@ -425,7 +425,7 @@ type Trie3D = Trie >; ) }; - func splitSizedList(l:AssocList,V>, bitpos:Nat) +public func splitSizedList(l:AssocList,V>, bitpos:Nat) : (Nat, AssocList,V>, Nat, AssocList,V>) = label profile_trie_splitSizedList : (Nat, AssocList,V>, Nat, AssocList,V>) { @@ -461,7 +461,7 @@ type Trie3D = Trie >; - [`prod`](#prod) */ - func merge(tl:Trie, tr:Trie, k_eq:(K,K)->Bool) : Trie = label profile_trie_merge : Trie { +public func merge(tl:Trie, tr:Trie, k_eq:(K,K)->Bool) : Trie = label profile_trie_merge : Trie { let key_eq = keyEq(k_eq); func br(l:Trie, r:Trie) : Trie = branch(l,r); func rec(bitpos:Nat, tl:Trie, tr:Trie) : Trie { @@ -507,7 +507,7 @@ type Trie3D = Trie >; dynamic error if there are collisions in common keys between the left and right inputs. */ - func mergeDisjoint(tl:Trie, tr:Trie, k_eq:(K,K)->Bool): Trie = +public func mergeDisjoint(tl:Trie, tr:Trie, k_eq:(K,K)->Bool): Trie = label profile_trie_mergeDisjoint : Trie { let key_eq = keyEq(k_eq); func br(l:Trie, r:Trie) : Trie = branch(l,r); @@ -557,7 +557,7 @@ type Trie3D = Trie >; the left trie whose keys are not present in the right trie; the values of the right trie are irrelevant. */ - func diff(tl:Trie, tr:Trie, k_eq:(K,K)->Bool): Trie { +public func diff(tl:Trie, tr:Trie, k_eq:(K,K)->Bool): Trie { let key_eq = keyEq(k_eq); func br1(l:Trie, r:Trie) : Trie = branch(l,r); @@ -618,7 +618,7 @@ type Trie3D = Trie >; - [`prod`](#prod) */ - func disj( +public func disj( tl : Trie, tr : Trie, k_eq : (K,K)->Bool, @@ -702,7 +702,7 @@ type Trie3D = Trie >; - [`prod`](#prod) */ - func join(tl:Trie, tr:Trie, + public func join(tl:Trie, tr:Trie, k_eq:(K,K)->Bool, vbin:(V,W)->X) : Trie = label profile_trie_join : Trie { @@ -749,7 +749,7 @@ type Trie3D = Trie >; either as clients, or as hand-specialized versions (e.g., see map, mapFilter, exists and forAll below). */ - func foldUp(t:Trie, bin:(X,X)->X, leaf:(K,V)->X, empty:X) : X { + public func foldUp(t:Trie, bin:(X,X)->X, leaf:(K,V)->X, empty:X) : X { func rec(t:Trie) : X { switch t { case (#empty) { empty }; @@ -787,7 +787,7 @@ type Trie3D = Trie >; - [`merge`](#merge) */ - func prod( + public func prod( tl :Trie, tr :Trie, op :(K1,V1,K2,V2) -> ?(Key,V3), @@ -839,13 +839,13 @@ type Trie3D = Trie >; own. */ - module Build { + public module Build { /** Commands for building tries. For PL academics: Imagine commands for the IMP imperative language, but where global memory consists of a single (anonymous) global trie */ - type TrieBuild = { + public type TrieBuild = { #skip ; #insert : (K, ?Hash, V) ; #seq : { @@ -855,7 +855,7 @@ type Trie3D = Trie >; } ; }; - func buildCount(tb:TrieBuild) : Nat = + public func buildCount(tb:TrieBuild) : Nat = label profile_trie_buildCount : Nat { switch tb { case (#skip) 0; @@ -864,7 +864,7 @@ type Trie3D = Trie >; } }; - func buildSeq(l:TrieBuild, r:TrieBuild) : TrieBuild = + public func buildSeq(l:TrieBuild, r:TrieBuild) : TrieBuild = label profile_trie_buildSeq : TrieBuild { let sum = buildCount(l) + buildCount(r); #seq(new { count = sum; left = l; right = r }) @@ -883,7 +883,7 @@ type Trie3D = Trie >; - [`prod`](#prod) */ - func prodBuild( + public func prodBuild( tl :Trie, tr :Trie, op :(K1,V1,K2,V2) -> ?(K3,V3), @@ -931,7 +931,7 @@ type Trie3D = Trie >; This position is meaningful only when the build contains multiple uses of one or more keys, otherwise it is not. */ - func buildNth(tb:TrieBuild, i:Nat) : ?(K, ?Hash, V) = label profile_triebuild_nth : (?(K, ?Hash, V)) { + public func buildNth(tb:TrieBuild, i:Nat) : ?(K, ?Hash, V) = label profile_triebuild_nth : (?(K, ?Hash, V)) { func rec(tb:TrieBuild, i:Nat) : ?(K, ?Hash, V) = label profile_triebuild_nth_rec : (?(K, ?Hash, V)) { switch tb { case (#skip) P.unreachable(); @@ -960,7 +960,7 @@ type Trie3D = Trie >; work of actually merging any tries; rather, just record the work for latter (if ever). */ - func projectInnerBuild(t : Trie>) + public func projectInnerBuild(t : Trie>) : TrieBuild { foldUp, TrieBuild> @@ -975,7 +975,7 @@ type Trie3D = Trie >; -------- Gather the collection of key-value pairs into an array of a (possibly-distinct) type. */ - func buildToArray(tb:TrieBuild,f:(K,V)->W):[W] = + public func buildToArray(tb:TrieBuild,f:(K,V)->W):[W] = label profile_triebuild_toArray_begin : [W] { let a = Array_tabulate ( buildCount(tb), @@ -995,7 +995,7 @@ type Trie3D = Trie >; (Same semantics as `buildToArray`, but faster in practice.) */ - func buildToArray2(tb:TrieBuild,f:(K,V)->W):[W] { + public func buildToArray2(tb:TrieBuild,f:(K,V)->W):[W] { let c = buildCount(tb); let a = Array_init(c, null); var i = 0; @@ -1018,7 +1018,7 @@ type Trie3D = Trie >; Fold over the key-value pairs of the trie, using an accumulator. The key-value pairs have no reliable or meaningful ordering. */ - func fold(t:Trie, f:(K,V,X)->X, x:X) : X { + public func fold(t:Trie, f:(K,V,X)->X, x:X) : X { func rec(t:Trie, x:X) : X { switch t { case (#empty) x; @@ -1040,7 +1040,7 @@ type Trie3D = Trie >; -------- Test whether a given key-value pair is present, or not. */ - func exists(t:Trie, f:(K,V)->Bool) : Bool { + public func exists(t:Trie, f:(K,V)->Bool) : Bool { func rec(t:Trie) : Bool { switch t { case (#empty) { false }; @@ -1060,7 +1060,7 @@ type Trie3D = Trie >; --------- Test whether all key-value pairs have a given property. */ - func forAll(t:Trie, f:(K,V)->Bool) : Bool { + public func forAll(t:Trie, f:(K,V)->Bool) : Bool { func rec(t:Trie) : Bool { switch t { case (#empty) { true }; @@ -1084,7 +1084,7 @@ type Trie3D = Trie >; can inject tries into arrays given the Array_tabulate interface for doing so. */ - func nth(t:Trie, i:Nat) : ?(Key, V) = label profile_trie_nth : (?(Key, V)) { + public func nth(t:Trie, i:Nat) : ?(Key, V) = label profile_trie_nth : (?(Key, V)) { func rec(t:Trie, i:Nat) : ?(Key, V) = label profile_trie_nth_rec : (?(Key, V)) { switch t { case (#empty) P.unreachable(); @@ -1130,7 +1130,7 @@ type Trie3D = Trie >; the type W (e.g., the existence of "default values"), we settle for using `nth`. */ - func toArray(t:Trie,f:(K,V)->W):[W] = + public func toArray(t:Trie,f:(K,V)->W):[W] = label profile_trie_toArray_begin : [W] { let a = Array_tabulate ( count(t), @@ -1151,7 +1151,7 @@ type Trie3D = Trie >; but no leaves. These can result from naive filtering operations; filter uses this function to avoid creating such subtrees. */ - func isEmpty(t:Trie) : Bool = + public func isEmpty(t:Trie) : Bool = count(t) == 0; /** @@ -1159,7 +1159,7 @@ type Trie3D = Trie >; ----------- filter the key-value pairs by a given predicate. */ - func filter(t:Trie, f:(K,V)->Bool) : Trie { + public func filter(t:Trie, f:(K,V)->Bool) : Trie { func rec(t:Trie, bitpos:Nat) : Trie { switch t { case (#empty) { #empty }; @@ -1193,7 +1193,7 @@ type Trie3D = Trie >; ----------- map and filter the key-value pairs by a given predicate. */ - func mapFilter(t:Trie, f:(K,V)->?W) : Trie { + public func mapFilter(t:Trie, f:(K,V)->?W) : Trie { func rec(t:Trie, bitpos:Nat) : Trie { switch t { case (#empty) { #empty }; @@ -1239,7 +1239,7 @@ type Trie3D = Trie >; `#empty`. We do not observe that equality here. */ - func equalStructure( + public func equalStructure( tl:Trie, tr:Trie, keq:(K,K)->Bool, @@ -1271,7 +1271,7 @@ type Trie3D = Trie >; and only if successful, do the success continuation, otherwise, return the failure value */ - func replaceThen(t : Trie, k:Key, k_eq:(K,K)->Bool, v2:V, + public func replaceThen(t : Trie, k:Key, k_eq:(K,K)->Bool, v2:V, success: (Trie, V) -> X, fail: () -> X) : X @@ -1288,7 +1288,7 @@ type Trie3D = Trie >; ---------------- insert the given key's value in the trie; return the new trie; assert that no prior value is associated with the key */ - func insertFresh(t : Trie, k:Key, k_eq:(K,K)->Bool, v:V) : Trie { + public func insertFresh(t : Trie, k:Key, k_eq:(K,K)->Bool, v:V) : Trie { let (t2, none) = replace(t, k, k_eq, ?v); switch none { case (null) (); @@ -1302,7 +1302,7 @@ type Trie3D = Trie >; --------------- insert the given key's value in the 2D trie; return the new 2D trie. */ - func insert2D(t : Trie2D, + public func insert2D(t : Trie2D, k1:Key, k1_eq:(K1,K1)->Bool, k2:Key, k2_eq:(K2,K2)->Bool, v:V) @@ -1322,7 +1322,7 @@ type Trie3D = Trie >; --------------- insert the given key's value in the trie; return the new trie; */ - func insert3D + public func insert3D (t : Trie3D, k1:Key, k1_eq:(K1,K1)->Bool, k2:Key, k2_eq:(K2,K2)->Bool, @@ -1357,7 +1357,7 @@ type Trie3D = Trie >; ------------- remove the given key's value in the trie; return the new trie */ - func remove(t : Trie, k:Key, k_eq:(K,K)->Bool) : (Trie, ?V) { + public func remove(t : Trie, k:Key, k_eq:(K,K)->Bool) : (Trie, ?V) { replace(t, k, k_eq, null) }; @@ -1368,7 +1368,7 @@ type Trie3D = Trie >; and only if successful, do the success continuation, otherwise, return the failure value */ - func removeThen(t : Trie, k:Key, k_eq:(K,K)->Bool, + public func removeThen(t : Trie, k:Key, k_eq:(K,K)->Bool, success: (Trie, V) -> X, fail: () -> X) : X @@ -1387,7 +1387,7 @@ type Trie3D = Trie >; remove the given key-key pair's value in the 2D trie; return the new trie, and the prior value, if any. */ - func remove2D(t : Trie2D, + public func remove2D(t : Trie2D, k1:Key, k1_eq:(K1,K1)->Bool, k2:Key, k2_eq:(K2,K2)->Bool) : (Trie2D, ?V) @@ -1412,7 +1412,7 @@ type Trie3D = Trie >; remove the given key-key pair's value in the 3D trie; return the new trie, and the prior value, if any. */ - func remove3D + public func remove3D (t : Trie3D, k1:Key, k1_eq:(K1,K1)->Bool, k2:Key, k2_eq:(K2,K2)->Bool, @@ -1445,7 +1445,7 @@ type Trie3D = Trie >; trie. */ - func mergeDisjoint2D(t : Trie2D, k1_eq:(K1,K1)->Bool, k2_eq:(K2,K2)->Bool) + public func mergeDisjoint2D(t : Trie2D, k1_eq:(K1,K1)->Bool, k2_eq:(K2,K2)->Bool) : Trie { foldUp, Trie> diff --git a/test/fail/actor-match.as b/test/fail/actor-match.as index c647921fe1e..3a00e3f59e7 100644 --- a/test/fail/actor-match.as +++ b/test/fail/actor-match.as @@ -1,10 +1,10 @@ let a : actor {f : () -> (); g : () -> ()} = actor { - f () {}; - g () {} + public func f() {}; + public func g() {} }; -func foo () = switch a { +func foo() = switch a { case {f; g} { f() } }; -assert ((switch (foo()) { case () 0 }) == 0) \ No newline at end of file +assert ((switch (foo()) { case () 0 }) == 0) diff --git a/test/fail/actor-reexport.as b/test/fail/actor-reexport.as index c928d553b44..27cd31e0176 100644 --- a/test/fail/actor-reexport.as +++ b/test/fail/actor-reexport.as @@ -1,13 +1,13 @@ actor test { - exported() { + public func exported() { print("exported()\n"); }; - let exported_too = exported; + public let exported_too = exported; }; actor test2 { - let exported_three = test.exported_too; - let (exported_four, exported_five) = + public let exported_three = test.exported_too; + public let (exported_four, exported_five) = if (true) (test.exported_too, test.exported_too) else diff --git a/test/fail/ast81-clash.as b/test/fail/ast81-clash.as index fafa57fd7cb..bf6098ad920 100644 --- a/test/fail/ast81-clash.as +++ b/test/fail/ast81-clash.as @@ -1,7 +1,7 @@ func foo() { }; // <-- removing this definition avoids the compiler exception actor class Test() = this { // <-- removing this stuff around the inner block avoids compiler exception - go() { + public func go() { ignore(async { let x = 123; diff --git a/test/fail/await-in-actor.as b/test/fail/await-in-actor.as index 41b3b1c2edc..7163f079ee4 100644 --- a/test/fail/await-in-actor.as +++ b/test/fail/await-in-actor.as @@ -1,7 +1,7 @@ let _ = async { let a = actor { - private x = await { async 1 }; - getX() : async Nat { x }; + let x = await { async 1 }; + public func getX() : async Nat { x }; }; () } diff --git a/test/fail/const-var-field.as b/test/fail/const-var-field.as index f6db662c711..e57ff4b772d 100644 --- a/test/fail/const-var-field.as +++ b/test/fail/const-var-field.as @@ -1 +1 @@ -let o : {x : Nat} = new {var x = 0}; +let o : {x : Nat} = object { public var x = 0 }; diff --git a/test/fail/duplicate-field.as b/test/fail/duplicate-field.as index 1e9dff1b781..66db44941ee 100644 --- a/test/fail/duplicate-field.as +++ b/test/fail/duplicate-field.as @@ -1,5 +1,5 @@ actor class C() { - m() {}; - n() {}; - m() {}; // Illegal! + public func m() {}; + public func n() {}; + public func m() {}; // Illegal! }; diff --git a/test/fail/issue103.as b/test/fail/issue103.as index 2b60aa7d48c..b7485f5f1bb 100644 --- a/test/fail/issue103.as +++ b/test/fail/issue103.as @@ -8,7 +8,7 @@ // An object with function fields is not sharable { func invalid2 (f : shared {foo : () -> Nat} -> ()) { - f (new { foo() : Nat = 1; }) + f (object { public func foo() : Nat = 1; }) }; }; @@ -22,6 +22,6 @@ // Cannot return an object with function fields in an async { func invalid4 () : (async ({foo : () -> Nat})) { - async { new { foo() : Nat = 1; } } + async { object { public func foo() : Nat = 1; } } }; }; diff --git a/test/fail/modexp1.as b/test/fail/modexp1.as index 2afd6b85fea..c716c9ca07d 100644 --- a/test/fail/modexp1.as +++ b/test/fail/modexp1.as @@ -1,7 +1,7 @@ module X = { - func f() { g();}; - private func g() { f();}; + public func f() { g();}; + func g() { f();}; }; let ok = X.f; diff --git a/test/fail/modexp2.as b/test/fail/modexp2.as index 98bdf61044a..230a57b7b0d 100644 --- a/test/fail/modexp2.as +++ b/test/fail/modexp2.as @@ -1,10 +1,10 @@ module X = { - func f() { g();}; - private func g() { f();}; - private let y : Nat = 2; - private type U = Int; - type T = U; + public func f() { g();}; + func g() { f();}; + let y : Nat = 2; + type U = Int; + public type T = U; }; type Ok = X.T; diff --git a/test/fail/modexp3.as b/test/fail/modexp3.as index 7e3fdc0d28e..68c92ba05b4 100644 --- a/test/fail/modexp3.as +++ b/test/fail/modexp3.as @@ -1,7 +1,7 @@ module X = { - func f() { g();}; - private func g() { f();}; - private type U = U -> U; - type T = U; // bad public field because U private and unavoidable - func h():T { h() }; // ditto + public func f() { g();}; + func g() { f();}; + type U = U -> U; + public type T = U; // bad public field because U private and unavoidable + public func h():T { h() }; // ditto }; diff --git a/test/fail/modexp4.as b/test/fail/modexp4.as index d3d40e032e8..84eeea22a88 100644 --- a/test/fail/modexp4.as +++ b/test/fail/modexp4.as @@ -1,12 +1,12 @@ module X = { - func f() { g();}; - private func g() { f();}; - private module Y = { - type U = U -> U; + public func f() { g();}; + func g() { f();}; + module Y = { + public type U = U -> U; }; - type T = Y.U; // bad public field because Y.U private and unavoidable - func h():T { h() }; // ditto + public type T = Y.U; // bad public field because Y.U private and unavoidable + public func h():T { h() }; // ditto }; diff --git a/test/fail/modules-fwd.as b/test/fail/modules-fwd.as index c21da7394b8..dfcbc5976dc 100644 --- a/test/fail/modules-fwd.as +++ b/test/fail/modules-fwd.as @@ -5,10 +5,10 @@ let C = A.B; let u = C.v; module A = { - module B = { - type T = (); - let v = (); + public module B = { + public type T = (); + public let v = (); }; }; -}; \ No newline at end of file +}; diff --git a/test/fail/modules-shadow.as b/test/fail/modules-shadow.as index 9d701405ae1..872caff1ddd 100644 --- a/test/fail/modules-shadow.as +++ b/test/fail/modules-shadow.as @@ -1,7 +1,6 @@ -module X = { type t = Int }; +object X { public type t = Int }; -module Y = { +object Y { let X = 1; type t = X.t }; - diff --git a/test/fail/nested-class-rec-fail.as b/test/fail/nested-class-rec-fail.as index 5dbcfb85677..af9e647f28a 100644 --- a/test/fail/nested-class-rec-fail.as +++ b/test/fail/nested-class-rec-fail.as @@ -1,10 +1,8 @@ -class Foo(f1:Int -> Int, f2:Int -> Int) { }; +class Foo(f1 : Int -> Int, f2 : Int -> Int) {}; -class Bar () { - - private g(n:Int) : Int = n + 1; - - let Bar = Foo(g, g) /*: Foo */; // annotation needed to typecheck constructor call +class Bar() { + func g(n:Int) : Int = n + 1; + let foo = Foo(g, g); }; diff --git a/test/fail/object-patterns.as b/test/fail/object-patterns.as index 90c3496c3e1..2db0aeca32e 100644 --- a/test/fail/object-patterns.as +++ b/test/fail/object-patterns.as @@ -1,16 +1,14 @@ - -// subtyping in patterns +// Subtyping in patterns let q : {a : Int; b : Nat} = new {a = -42; b = 25}; func get_a () : Int = switch (q) { case {a = 25 : Nat} 1; // NOT OK: Nat cannot consume all Ints case {a = 42; b} b; // OK: 42 is Int by subtyping - case - {a = a : Int; - b = 25 : Int} a; // OK: Int can consume all Nats + case {a = a : Int; b = 25 : Int} a; // OK: Int can consume all Nats }; + // the above is analogous to the simpler: func (a : Int) = switch a { diff --git a/test/fail/objpat-duplicate.as b/test/fail/objpat-duplicate.as index 2310218182e..e31294bbd9f 100644 --- a/test/fail/objpat-duplicate.as +++ b/test/fail/objpat-duplicate.as @@ -1,4 +1,4 @@ -object o {a = 1; b = 2}; +let o = new {a = 1; b = 2}; switch o { case {a = x; b; a} {} diff --git a/test/fail/objpat-infer.as b/test/fail/objpat-infer.as index 0669afe2e17..9073e468939 100644 --- a/test/fail/objpat-infer.as +++ b/test/fail/objpat-infer.as @@ -20,7 +20,7 @@ ignore (foo (new {})); ignore (foo (object {})); ignore (foo (actor {})); -let a = actor { bar ({}) : async Nat = async 25 }; +let a = actor { public func bar ({}) : async Nat = async 25 }; ignore (foo a); diff --git a/test/fail/ok/actor-reexport.tc.ok b/test/fail/ok/actor-reexport.tc.ok index 084ef0f2bdb..b677a38239d 100644 --- a/test/fail/ok/actor-reexport.tc.ok +++ b/test/fail/ok/actor-reexport.tc.ok @@ -1,3 +1,3 @@ -actor-reexport.as:5.3-5.30: type error, public actor field needs to be a manifest function -actor-reexport.as:9.3-9.41: type error, public actor field needs to be a manifest function -actor-reexport.as:10.3-14.39: type error, public actor field needs to be a manifest function +actor-reexport.as:5.10-5.37: type error, public actor field needs to be a manifest function +actor-reexport.as:9.10-9.48: type error, public actor field needs to be a manifest function +actor-reexport.as:10.10-14.39: type error, public actor field needs to be a manifest function diff --git a/test/fail/ok/await-in-actor.tc.ok b/test/fail/ok/await-in-actor.tc.ok index fe8cedf4c75..f597d1e26dd 100644 --- a/test/fail/ok/await-in-actor.tc.ok +++ b/test/fail/ok/await-in-actor.tc.ok @@ -1 +1 @@ -await-in-actor.as:3.17-3.34: type error, misplaced await +await-in-actor.as:3.13-3.30: type error, misplaced await diff --git a/test/fail/ok/const-var-field.tc.ok b/test/fail/ok/const-var-field.tc.ok index 150f905dc97..980dbf67a3b 100644 --- a/test/fail/ok/const-var-field.tc.ok +++ b/test/fail/ok/const-var-field.tc.ok @@ -1,4 +1,4 @@ -const-var-field.as:1.21-1.36: type error, expression of type +const-var-field.as:1.21-1.48: type error, expression of type {x : var Nat} cannot produce expected type {x : Nat} diff --git a/test/fail/ok/duplicate-field.tc.ok b/test/fail/ok/duplicate-field.tc.ok index b58039f0247..5c8099b99da 100644 --- a/test/fail/ok/duplicate-field.tc.ok +++ b/test/fail/ok/duplicate-field.tc.ok @@ -1 +1 @@ -duplicate-field.as:4.3-4.4: type error, duplicate definition for m in block +duplicate-field.as:4.15-4.16: type error, duplicate definition for m in block diff --git a/test/fail/ok/nested-class-rec-fail.tc.ok b/test/fail/ok/nested-class-rec-fail.tc.ok index 6e4d5470dd3..1471fa653f8 100644 --- a/test/fail/ok/nested-class-rec-fail.tc.ok +++ b/test/fail/ok/nested-class-rec-fail.tc.ok @@ -1 +1 @@ -nested-class-rec-fail.as:8.13-8.16: type error, cannot infer type of forward variable Foo +nested-class-rec-fail.as:7.13-7.16: type error, cannot infer type of forward variable Foo diff --git a/test/fail/ok/object-patterns.tc.ok b/test/fail/ok/object-patterns.tc.ok index ce5874191ea..9ae9b148c88 100644 --- a/test/fail/ok/object-patterns.tc.ok +++ b/test/fail/ok/object-patterns.tc.ok @@ -1,8 +1,8 @@ -object-patterns.as:7.13-7.21: type error, pattern of type +object-patterns.as:6.13-6.21: type error, pattern of type Nat cannot consume expected type Int -object-patterns.as:19.9-19.16: type error, pattern of type +object-patterns.as:17.9-17.16: type error, pattern of type Nat cannot consume expected type Int diff --git a/test/fail/ok/use-before-define6.tc.ok b/test/fail/ok/use-before-define6.tc.ok index 5dc75f76f19..bba698b0347 100644 --- a/test/fail/ok/use-before-define6.tc.ok +++ b/test/fail/ok/use-before-define6.tc.ok @@ -1 +1 @@ -use-before-define6.as:9.3-9.22: definedness error, cannot use g before g has been defined +use-before-define6.as:6.3-6.20: definedness error, cannot use g before g has been defined diff --git a/test/fail/use-before-define5.as b/test/fail/use-before-define5.as index 7fc81febdca..939bd17211e 100644 --- a/test/fail/use-before-define5.as +++ b/test/fail/use-before-define5.as @@ -1,3 +1,3 @@ // A closing actor needs to eagerly get the values -let a = actor { foo() : () { assert (x == 1) } }; +let a = actor { public func foo() : () { assert (x == 1) } }; let x = 1; diff --git a/test/fail/use-before-define6.as b/test/fail/use-before-define6.as index 998c54af626..7e42ffa50bc 100644 --- a/test/fail/use-before-define6.as +++ b/test/fail/use-before-define6.as @@ -1,15 +1,11 @@ - - class Bar () { - - private class Foo(f1:Int -> Int, f2:Int -> Int) { - private bomb = f1(666) + f2(666); + class Foo(f1 : Int -> Int, f2 : Int -> Int) { + let bomb = f1(666) + f2(666); }; - var Bar = Foo(g, g); - - private g(n:Int) : Int = n + 1; + let _ = Foo(g, g); + func g(n : Int) : Int = n + 1; }; -let _ = Bar(); \ No newline at end of file +let _ = Bar(); diff --git a/test/run-dfinity/AST-64.as b/test/run-dfinity/AST-64.as index 5c1685cf14d..cf83b84b2c7 100644 --- a/test/run-dfinity/AST-64.as +++ b/test/run-dfinity/AST-64.as @@ -6,11 +6,11 @@ let _ = (object this {}) : Any; let _ = (object {}) : Any; -let _ = (actor this { func x(){ this.x(); }; }) : Any; -let _ = (actor { func x(){x();}; }) : Any; +let _ = (actor this { public func x() { this.x() } }) : Any; +let _ = (actor { public func x() { x() } }) : Any; -let _ = (object this { func x(){ this.x(); }; }) : Any; -let _ = (object { func x(){x();}; }) : Any; +let _ = (object this { public func x() { this.x() } }) : Any; +let _ = (object { public func x() { x() } }) : Any; diff --git a/test/run-dfinity/async-new-obj.as b/test/run-dfinity/async-new-obj.as index 43e71a001c6..339009c0a7f 100644 --- a/test/run-dfinity/async-new-obj.as +++ b/test/run-dfinity/async-new-obj.as @@ -1,61 +1,69 @@ -/* test asynchronous construction of an object */ +/* Test asynchronous construction of an object */ + let a = async { - let o = new {private a = "aa" ; - private b = "ab"; - get_a():Text {a;}; - get_b():Text {b;};}; - let (a,b) = (o.get_a(),o.get_b()); - print a; - print b; - print "\n"; + let o = object { + let a = "aa"; + let b = "ab"; + public func get_a() : Text { a }; + public func get_b() : Text { b }; + }; + let (a, b) = (o.get_a(), o.get_b()); + print a; + print b; + print "\n"; }; let b = async { - let o = new {private a = await (async "ba") ; - private b = "bb"; - get_a():Text {a;}; - get_b():Text {b;};}; - let (a,b) = (o.get_a(),o.get_b()); - print a; - print b; - print "\n"; + let o = object { + let a = await (async "ba") ; + let b = "bb"; + public func get_a() : Text { a }; + public func get_b() : Text { b }; + }; + let (a, b) = (o.get_a(), o.get_b()); + print a; + print b; + print "\n"; }; let c = async { - let o = new {private a = await (async "ca") ; - private b = await (async "cb"); - get_a():Text {a;}; - get_b():Text {b;};}; - let (a,b) = (o.get_a(),o.get_b()); - print a; - print b; - print "\n"; + let o = object { + let a = await (async "ca") ; + let b = await (async "cb"); + public func get_a() : Text { a }; + public func get_b() : Text { b }; + }; + let (a, b) = (o.get_a(), o.get_b()); + print a; + print b; + print "\n"; }; let d = async { - let o = new {private a = "da"; - private b = await (async "db"); - get_a(): Text {a;}; - get_b(): Text {b;};}; - let (a,b) = (o.get_a(),o.get_b()); - print a; - print b; - print "\n"; + let o = object { + let a = "da"; + let b = await (async "db"); + public func get_a() : Text { a }; + public func get_b() : Text { b }; + }; + let (a, b) = (o.get_a(), o.get_b()); + print a; + print b; + print "\n"; }; - let e = async { - let o = new this { - private a = "ea"; - private b = await (async "eb"); - get_a() : Text {a;}; - get_b(): Text {b;}; - get_ab():(Text,Text) { - (this.get_a(), this.get_b()); - }; - }; - let (a,b) = o.get_ab(); - print a; - print b; - print "\n"; + let o = object this { + let a = "ea"; + let b = await (async "eb"); + public func get_a() : Text { a }; + public func get_b() : Text { b }; + public func get_ab() : (Text, Text) { + (this.get_a(), this.get_b()); + }; + }; + let (a, b) = o.get_ab(); + print a; + print b; + print "\n"; }; diff --git a/test/run-dfinity/async-obj-mut.as b/test/run-dfinity/async-obj-mut.as index afcf5733f86..2f7f2d18708 100644 --- a/test/run-dfinity/async-obj-mut.as +++ b/test/run-dfinity/async-obj-mut.as @@ -1,13 +1,13 @@ let _ = async { - let o = new { - var x = await { async { 1 } }; - private a = printInt(x); + let o = object { + public var x = await { async { 1 } }; + let a = printInt(x); // private b = (x := await { async (x + 1) }); - private b = (x := x + 1); - private c = printInt(x); - foo() = { x := x + 1 }; - private e = foo(); - private f = printInt(x); + let b = (x := x + 1); + let c = printInt(x); + public func foo() = { x := x + 1 }; + let e = foo(); + let f = printInt(x); }; print("\ndone creating\n"); printInt(o.x); diff --git a/test/run-dfinity/chat.as b/test/run-dfinity/chat.as index fff4508e784..2f565f57724 100644 --- a/test/run-dfinity/chat.as +++ b/test/run-dfinity/chat.as @@ -3,9 +3,9 @@ type List = ?{head : T; var tail : List}; type Post = shared Text -> (); actor class Server() = { - private var clients : List = null; + var clients : List = null; - private shared broadcast(message : Text) { + shared func broadcast(message : Text) { var next = clients; loop { switch next { @@ -18,7 +18,7 @@ actor class Server() = { }; }; - subscribe(client : Client) : async Post { + public func subscribe(client : Client) : async Post { let cs = new {head = client; var tail = clients}; clients := ?cs; return broadcast; @@ -28,10 +28,10 @@ actor class Server() = { actor class Client() = this { // TODO: these should be constructor params once we can compile them - private var name : Text = ""; - private var server : ?Server = null; + var name : Text = ""; + var server : ?Server = null; - go(n : Text, s : Server) { + public func go(n : Text, s : Server) { name := n; server := ?s; ignore(async { @@ -41,7 +41,7 @@ actor class Client() = this { }); }; - send(msg : Text) { + public func send(msg : Text) { print(name # " received " # msg # "\n"); }; }; diff --git a/test/run-dfinity/chatpp.as b/test/run-dfinity/chatpp.as index f107bd3468d..cbedc2115b6 100644 --- a/test/run-dfinity/chatpp.as +++ b/test/run-dfinity/chatpp.as @@ -12,10 +12,10 @@ type ClientData = { }; actor class Server() = { - private var nextId : Nat = 0; - private var clients : List = null; + var nextId : Nat = 0; + var clients : List = null; - private broadcast(id : Nat, message : Text) { + func broadcast(id : Nat, message : Text) { var next = clients; label sends loop { switch next { @@ -28,20 +28,20 @@ actor class Server() = { }; }; - subscribe(aclient : Client) : async Subscription { + public func subscribe(aclient : Client) : async Subscription { let c = new {id = nextId; client = aclient; var revoked = false}; nextId += 1; let cs = new {head = c; var tail = clients}; clients := ?cs; - return (new { - post = shared func(message : Text) { + return object { + public shared func post(message : Text) { if (not c.revoked) broadcast(c.id, message); }; - cancel = shared func() { unsubscribe(c.id) }; - }); + public shared func cancel() { unsubscribe(c.id) }; + }; }; - private unsubscribe(id : Nat) { + func unsubscribe(id : Nat) { var prev : List = null; var next = clients; loop { @@ -66,10 +66,10 @@ actor class Server() = { actor class Client() = this { // TODO: these should be constructor params once we can compile them - private var name : Text = ""; - private var server : ?Server = null; + var name : Text = ""; + var server : ?Server = null; - go(n : Text, s : Server) { + public func go(n : Text, s : Server) { name := n; server := ?s; ignore(async { @@ -80,7 +80,7 @@ actor class Client() = this { }) }; - send(msg : Text) { + public func send(msg : Text) { print(name # " received " # msg # "\n"); }; }; diff --git a/test/run-dfinity/closure-params.as b/test/run-dfinity/closure-params.as index 86630872dae..4f7c66e77f4 100644 --- a/test/run-dfinity/closure-params.as +++ b/test/run-dfinity/closure-params.as @@ -1,11 +1,11 @@ let a = actor { - private var c = 0; - incn(n : Nat) : () { + var c = 0; + public func incn(n : Nat) : () { c += n; printInt(c); print("\n"); }; - readCounter(f : shared Nat -> ()) : () { + public func readCounter(f : shared Nat -> ()) : () { f(c); }; }; diff --git a/test/run-dfinity/counter-class.as b/test/run-dfinity/counter-class.as index 62322bc3f65..711ec097d54 100644 --- a/test/run-dfinity/counter-class.as +++ b/test/run-dfinity/counter-class.as @@ -1,12 +1,12 @@ actor class Counter(i : Int) { - private var j = i; + var j = i; - dec() { + public func dec() { showCounter(j); j -= 1; }; - read() : async Int { j }; + public func read() : async Int { j }; }; func showCounter(c : Int) {}; diff --git a/test/run-dfinity/counter.as b/test/run-dfinity/counter.as index 7669b032fcc..e99d656ef79 100644 --- a/test/run-dfinity/counter.as +++ b/test/run-dfinity/counter.as @@ -1,10 +1,10 @@ let a = actor { - private var c = 1; - inc() { + var c = 1; + public func inc() { c += 1; printInt c; print "\n"; }; - printCounter () { + public func printCounter () { printInt c; print "\n"; } }; diff --git a/test/run-dfinity/counter2.as b/test/run-dfinity/counter2.as index d7a24c60069..303e4122e4c 100644 --- a/test/run-dfinity/counter2.as +++ b/test/run-dfinity/counter2.as @@ -1,10 +1,10 @@ actor { - private var c = 1; - inc() { + var c = 1; + public func inc() { c += 1; printInt c; print "\n"; }; - printCounter () { + public func printCounter () { printInt c; print "\n"; } } diff --git a/test/run-dfinity/data-params.as b/test/run-dfinity/data-params.as index be0da0b8757..c0f0036d724 100644 --- a/test/run-dfinity/data-params.as +++ b/test/run-dfinity/data-params.as @@ -1,31 +1,31 @@ let a = actor { - private var c : Int = 0; - inci(n : Int) : () { + var c : Int = 0; + public func inci(n : Int) : () { c += n; printInt(c); print("\n"); }; - incn(n : Nat) : () { + public func incn(n : Nat) : () { c += n; printInt(c); print("\n"); }; - incnn(n1 : Nat, n2 : Nat) : () { + public func incnn(n1 : Nat, n2 : Nat) : () { c += n1 + n2; printInt(c); print("\n"); }; - incnested(n1 : Nat, (n2 : Nat, n3 : Nat)) : () { + public func incnested(n1 : Nat, (n2 : Nat, n3 : Nat)) : () { c += n1 + n2 + n3; printInt(c); print("\n"); }; - incarray(a : [Nat]) : () { + public func incarray(a : [Nat]) : () { for (i in a.vals()) { c += i }; printInt(c); print("\n"); }; - incopt(a : ?Nat) : () { + public func incopt(a : ?Nat) : () { switch a { case null { c += 1000000 }; case (?a) { c += a }; @@ -33,13 +33,13 @@ let a = actor { printInt(c); print("\n"); }; - increcord(a : { x : Nat; y : Nat }) : () { + public func increcord(a : { x : Nat; y : Nat }) : () { c += a.x; c += a.y; printInt(c); print("\n"); }; - incVariant(v : { #foo : Nat; #bar : Nat }) { + public func incVariant(v : { #foo : Nat; #bar : Nat }) { c += (switch v { case (#foo n) n; case (#bar n) n; @@ -47,21 +47,21 @@ let a = actor { printInt(c); print("\n"); }; - printCounter() { + public func printCounter() { printInt(c); print("\n"); }; - printLabeled(l:Text) { + public func printLabeled(l:Text) { print l; printInt(c); print("\n"); }; - printLabeledOpt(?l:?Text) { + public func printLabeledOpt(?l:?Text) { print l; printInt(c); print("\n"); }; - incwords(w8 : Word8, w16 : Word16, w32 : Word32, w64 : Word64) : () { + public func incwords(w8 : Word8, w16 : Word16, w32 : Word32, w64 : Word64) : () { c += word8ToInt(w8); c += word16ToInt(w16); c += word32ToInt(w32); @@ -69,7 +69,7 @@ let a = actor { printInt(c); print("\n"); }; - incnats(n8 : Nat8, n16 : Nat16, n32 : Nat32, n64 : Nat64) : () { + public func incnats(n8 : Nat8, n16 : Nat16, n32 : Nat32, n64 : Nat64) : () { c += nat8ToNat(n8); c += nat16ToNat(n16); c += nat32ToNat(n32); @@ -77,7 +77,7 @@ let a = actor { printInt(c); print("\n"); }; - incints(i8 : Int8, i16 : Int16, i32 : Int32, i64 : Int64) : () { + public func incints(i8 : Int8, i16 : Int16, i32 : Int32, i64 : Int64) : () { c += int8ToInt(i8); c += int16ToInt(i16); c += int32ToInt(i32); diff --git a/test/run-dfinity/flatten-awaitables.as b/test/run-dfinity/flatten-awaitables.as index a23f034c7e4..72184de029b 100644 --- a/test/run-dfinity/flatten-awaitables.as +++ b/test/run-dfinity/flatten-awaitables.as @@ -1,33 +1,33 @@ // test flattening of awaitable, shared function arguments let a = actor { - m0():async() {}; - m1(x:Int):async Int {return x;}; - m2(x:Int,y:Bool):async(Int,Bool) {return (x,y);}; - m3(x:Int,y:Bool,z:Text):async(Int,Bool,Text) {return (x,y,z);}; + public func m0():async() {}; + public func m1(x:Int):async Int {return x;}; + public func m2(x:Int,y:Bool):async(Int,Bool) {return (x,y);}; + public func m3(x:Int,y:Bool,z:Text):async(Int,Bool,Text) {return (x,y,z);}; - n0(u:()):async() {return u}; - n1(x:Int):async Int {return x;}; - n2(xy:(Int,Bool)):async(Int,Bool) {return xy;}; - n3(xyz:(Int,Bool,Text)):async(Int,Bool,Text) {return xyz;}; + public func n0(u:()):async() {return u}; + public func n1(x:Int):async Int {return x;}; + public func n2(xy:(Int,Bool)):async(Int,Bool) {return xy;}; + public func n3(xyz:(Int,Bool,Text)):async(Int,Bool,Text) {return xyz;}; // higher-order cases - h0 (f0:shared () -> async (),u:()) : async () + public func h0 (f0:shared () -> async (),u:()) : async () { await f0 u;}; - h1 (f1:shared (Int) -> async Int,x:Int) : async Int + public func h1 (f1:shared (Int) -> async Int,x:Int) : async Int { await f1 x;}; - h2 (f2:shared (Int,Bool) -> async (Int,Bool), xy:(Int,Bool)) : async (Int,Bool) + public func h2 (f2:shared (Int,Bool) -> async (Int,Bool), xy:(Int,Bool)) : async (Int,Bool) { await f2 xy; }; - h3 (f3:shared (Int,Bool,Text) -> async (Int,Bool,Text), xyz:(Int,Bool,Text)) : async (Int,Bool,Text) + public func h3 (f3:shared (Int,Bool,Text) -> async (Int,Bool,Text), xyz:(Int,Bool,Text)) : async (Int,Bool,Text) { await f3 xyz; }; - g0 (f0:shared (()) -> async (),u:()) : async () + public func g0 (f0:shared (()) -> async (),u:()) : async () { await f0 u;}; - g1 (f1:shared (Int) -> async Int,x:Int) : async Int + public func g1 (f1:shared (Int) -> async Int,x:Int) : async Int { await f1 x;}; - g2 (f2:shared ((Int,Bool)) -> async (Int,Bool), xy:(Int,Bool)) : async (Int,Bool) + public func g2 (f2:shared ((Int,Bool)) -> async (Int,Bool), xy:(Int,Bool)) : async (Int,Bool) { await f2 xy; }; - g3 (f3:shared ((Int,Bool,Text)) -> async (Int,Bool,Text), xyz:(Int,Bool,Text)) : async (Int,Bool,Text) + public func g3 (f3:shared ((Int,Bool,Text)) -> async (Int,Bool,Text), xyz:(Int,Bool,Text)) : async (Int,Bool,Text) { await f3 xyz; }; }; diff --git a/test/run-dfinity/general-type-components.as b/test/run-dfinity/general-type-components.as index f36b9e8b561..5c88383c539 100644 --- a/test/run-dfinity/general-type-components.as +++ b/test/run-dfinity/general-type-components.as @@ -1,13 +1,13 @@ // test type components in object and actors (not just modules) object X = { - func f() { g();}; - private func g() { f();}; - object Y = { - type U = Int; + public func f() { g();}; + func g() { f();}; + public object Y = { + public type U = Int; }; - type T = Y.U; // ok type field since Y.U private but avoidable - private func h():T { h() }; // ditto + public type T = Y.U; // ok type field since Y.U private but avoidable + func h():T { h() }; // ditto }; type XT = X.T; @@ -15,13 +15,13 @@ type XYU = X.Y.U; actor A = { - func f() { g();}; - private func g() { f();}; - private object Y = { - type U = Int; + public func f() { g();}; + func g() { f();}; + object Y = { + public type U = Int; }; - type T = Y.U; // ok type field since Y.U private but avoidable - private func h():T { h() }; // ditto + public type T = Y.U; // ok type field since Y.U private but avoidable + func h():T { h() }; // ditto }; type AT = A.T; diff --git a/test/run-dfinity/hello-world-async.as b/test/run-dfinity/hello-world-async.as index aec152a6f63..2b7bab40032 100644 --- a/test/run-dfinity/hello-world-async.as +++ b/test/run-dfinity/hello-world-async.as @@ -1,8 +1,8 @@ let a = actor { - world () { + public func world() { print("World!\n"); }; - go () { + public func go() { world(); print("Hello "); }; diff --git a/test/run-dfinity/hello-world-await.as b/test/run-dfinity/hello-world-await.as index 632ed4bb694..d8b73e3bdc2 100644 --- a/test/run-dfinity/hello-world-await.as +++ b/test/run-dfinity/hello-world-await.as @@ -1,11 +1,11 @@ let a = actor { - hello () : async Text { + public func hello() : async Text { "Hello "; }; - world () : async Text { + public func world() : async Text { "World!\n" }; - go () : async () { + public func go() : async () { print((await hello()) # (await world())); }; }; diff --git a/test/run-dfinity/hello-world-message.as b/test/run-dfinity/hello-world-message.as index 5ea1e82608e..73608dd9731 100644 --- a/test/run-dfinity/hello-world-message.as +++ b/test/run-dfinity/hello-world-message.as @@ -1,5 +1,5 @@ actor { - hello () { + public func hello() { print("Hello World!\n"); } } diff --git a/test/run-dfinity/hello-world-message2.as b/test/run-dfinity/hello-world-message2.as index d0016c72edc..b177bac179c 100644 --- a/test/run-dfinity/hello-world-message2.as +++ b/test/run-dfinity/hello-world-message2.as @@ -1,5 +1,5 @@ actor hello_world { - hello () { + public func hello() { print("Hello World!\n"); } } diff --git a/test/run-dfinity/hello-world2.as b/test/run-dfinity/hello-world2.as index 0f142775153..c797af62b2c 100644 --- a/test/run-dfinity/hello-world2.as +++ b/test/run-dfinity/hello-world2.as @@ -1,5 +1,5 @@ let a = actor { - hello () { + public func hello() { print("Hello World!\n"); } }; diff --git a/test/run-dfinity/hello-world3.as b/test/run-dfinity/hello-world3.as index 5fd3d5132ba..5354a951b08 100644 --- a/test/run-dfinity/hello-world3.as +++ b/test/run-dfinity/hello-world3.as @@ -1,12 +1,12 @@ let a = actor { - hello () { + public func hello() { print("Hello "); }; - go () { + public func go() { hello(); world(); }; - world () { + public func world() { print("World!\n"); }; }; diff --git a/test/run-dfinity/indirect-counter.as b/test/run-dfinity/indirect-counter.as index b058ed60089..8537fd94dc1 100644 --- a/test/run-dfinity/indirect-counter.as +++ b/test/run-dfinity/indirect-counter.as @@ -1,16 +1,16 @@ let a = actor { - private aa = actor { - private var c = 1; - inc() { + let aa = actor { + var c = 1; + public func inc() { c += 1; printInt(c) }; - print () { + public func print() { printInt(c) }; }; - inc() { aa.inc() }; - print() { aa.print() }; + public func inc() { aa.inc() }; + public func print() { aa.print() }; }; a.inc(); diff --git a/test/run-dfinity/modexp1.as b/test/run-dfinity/modexp1.as index 34a1ada2246..7dda56e0ec2 100644 --- a/test/run-dfinity/modexp1.as +++ b/test/run-dfinity/modexp1.as @@ -1,7 +1,7 @@ -module X = { - func f() { g();}; - private func g() { f();}; +module X { + public func f() { g() }; + func g() { f() }; }; let ok = X.f; diff --git a/test/run-dfinity/modexp2.as b/test/run-dfinity/modexp2.as index 1aab9fee07e..7f658795b0a 100644 --- a/test/run-dfinity/modexp2.as +++ b/test/run-dfinity/modexp2.as @@ -1,10 +1,10 @@ -module X = { - func f() { g();}; - private func g() { f();}; - private let y : Nat = 2; - private type U = Int; - type T = U; +module X { + public func f() { g() }; + func g() { f() }; + let y : Nat = 2; + type U = Int; + public type T = U; }; type Ok = X.T; diff --git a/test/run-dfinity/modexp3.as b/test/run-dfinity/modexp3.as index 7d6af576e05..9d4fa06a3ed 100644 --- a/test/run-dfinity/modexp3.as +++ b/test/run-dfinity/modexp3.as @@ -1,10 +1,10 @@ -module X = { - func f() { g();}; - private func g() { f();}; - private type U = Int -> Int; - type T = U; // ok export, because U, though private, is avoidable - func h():T { h() }; // ditto +module X { + public func f() { g() }; + func g() { f() }; + type U = Int -> Int; + public type T = U; // ok export, because U, though private, is avoidable + public func h() : T { h() }; // ditto }; type Ok = X.T; diff --git a/test/run-dfinity/modexp4.as b/test/run-dfinity/modexp4.as index 66f76f29271..25593e7e4f9 100644 --- a/test/run-dfinity/modexp4.as +++ b/test/run-dfinity/modexp4.as @@ -1,12 +1,10 @@ -module X = { - func f() { g();}; - private func g() { f();}; - private module Y = { - type U = U -> U; +module X { + public func f() { g() }; + func g() { f() }; + module Y { + public type U = U -> U; }; - private type T = Y.U; // ok private field eventhough Y.U private and unavoidable - private func h():T { h() }; // ditto + type T = Y.U; // ok private field eventhough Y.U private and unavoidable + func h() : T { h() }; // ditto }; - - diff --git a/test/run-dfinity/modules-bwd.as b/test/run-dfinity/modules-bwd.as index 6c481a601d1..8708a8a89fb 100644 --- a/test/run-dfinity/modules-bwd.as +++ b/test/run-dfinity/modules-bwd.as @@ -1,9 +1,9 @@ module X = { module A = { - module B = { - type T = (); - let v = () + public module B = { + public type T = (); + public let v = () }; }; diff --git a/test/run-dfinity/ok/data-params.run-ir.ok b/test/run-dfinity/ok/data-params.run-ir.ok index d30b0888488..82fef50ca40 100644 --- a/test/run-dfinity/ok/data-params.run-ir.ok +++ b/test/run-dfinity/ok/data-params.run-ir.ok @@ -1,4 +1,4 @@ -data-params.as:59.18-59.28: warning, this pattern consuming type +data-params.as:59.30-59.40: warning, this pattern consuming type ?Text does not cover value null diff --git a/test/run-dfinity/ok/data-params.run-low.ok b/test/run-dfinity/ok/data-params.run-low.ok index d30b0888488..82fef50ca40 100644 --- a/test/run-dfinity/ok/data-params.run-low.ok +++ b/test/run-dfinity/ok/data-params.run-low.ok @@ -1,4 +1,4 @@ -data-params.as:59.18-59.28: warning, this pattern consuming type +data-params.as:59.30-59.40: warning, this pattern consuming type ?Text does not cover value null diff --git a/test/run-dfinity/ok/data-params.run.ok b/test/run-dfinity/ok/data-params.run.ok index d30b0888488..82fef50ca40 100644 --- a/test/run-dfinity/ok/data-params.run.ok +++ b/test/run-dfinity/ok/data-params.run.ok @@ -1,4 +1,4 @@ -data-params.as:59.18-59.28: warning, this pattern consuming type +data-params.as:59.30-59.40: warning, this pattern consuming type ?Text does not cover value null diff --git a/test/run-dfinity/ok/data-params.tc.ok b/test/run-dfinity/ok/data-params.tc.ok index a988892530f..fdcd0402292 100644 --- a/test/run-dfinity/ok/data-params.tc.ok +++ b/test/run-dfinity/ok/data-params.tc.ok @@ -1,4 +1,4 @@ -data-params.as:59.18-59.28: warning, this pattern consuming type +data-params.as:59.30-59.40: warning, this pattern consuming type ?Text does not cover value null diff --git a/test/run-dfinity/ok/data-params.wasm.stderr.ok b/test/run-dfinity/ok/data-params.wasm.stderr.ok index a988892530f..fdcd0402292 100644 --- a/test/run-dfinity/ok/data-params.wasm.stderr.ok +++ b/test/run-dfinity/ok/data-params.wasm.stderr.ok @@ -1,4 +1,4 @@ -data-params.as:59.18-59.28: warning, this pattern consuming type +data-params.as:59.30-59.40: warning, this pattern consuming type ?Text does not cover value null diff --git a/test/run-dfinity/reference-params.as b/test/run-dfinity/reference-params.as index ba199699a64..98e51252b68 100644 --- a/test/run-dfinity/reference-params.as +++ b/test/run-dfinity/reference-params.as @@ -1,5 +1,5 @@ let a = actor { - hello() { + public func hello() { print("Hello World!\n"); }; }; @@ -7,7 +7,7 @@ a.hello(); // test passing an actor to an actor let b = actor this { - say_hi(a : actor { hello : () -> () } ) { + public func say_hi(a : actor { hello : () -> () } ) { a.hello(); }; }; @@ -15,7 +15,7 @@ b.say_hi(a); // test passing a funcref to an actor let c = actor { - say_hi(f : shared () -> ()) { + public func say_hi(f : shared () -> ()) { f(); }; }; @@ -23,13 +23,13 @@ c.say_hi(a.hello); // test passing a own funcref to an actor let d = actor { - say_hi(f : shared () -> ()) { + public func say_hi(f : shared () -> ()) { f(); }; - hello() { + public func hello() { print("Hello Universe!\n"); }; - go() { + public func go() { say_hi(hello); } }; @@ -37,10 +37,10 @@ d.go(); // test passing a self to an actor let e = actor this { - hello() { + public func hello() { print("Hello Galaxy!\n"); }; - send_to(f : shared (actor { hello : () -> () }) -> ()) { + public func send_to(f : shared (actor { hello : () -> () }) -> ()) { f(this); } }; diff --git a/test/run-dfinity/show.as b/test/run-dfinity/show.as index 8f9ca5619a7..502d1be8b2a 100644 --- a/test/run-dfinity/show.as +++ b/test/run-dfinity/show.as @@ -15,7 +15,7 @@ printLn(debug_show (42,-42,())); printLn(debug_show ("Foobar", null, null, ?23)); printLn(debug_show ([1,2,3])); printLn(debug_show ([var 1,2,3])); -class Foo() { let foo : Int = 42; var bar : Bool = true ; private hidden = [1,2] }; +class Foo() { public let foo : Int = 42; public var bar : Bool = true ; let hidden = [1,2] }; printLn(debug_show (Foo())); printLn(debug_show (#foo ())); printLn(debug_show (#bar 42)); diff --git a/test/run-dfinity/transpose.as b/test/run-dfinity/transpose.as index 024739e4e73..a974c2da176 100644 --- a/test/run-dfinity/transpose.as +++ b/test/run-dfinity/transpose.as @@ -1,9 +1,9 @@ actor foo { - transpose (data : [(Int,Text)]) : async {ints: [Int]; txts: [Text]} { - return (new { + public func transpose (data : [(Int,Text)]) : async {ints: [Int]; txts: [Text]} { + return new { ints = Array_tabulate(data.len(), func (i:Nat) : Int = (data[i].0)); txts = Array_tabulate(data.len(), func (i:Nat) : Text = (data[i].1)) - }) + } } }; diff --git a/test/run/actors.as b/test/run/actors.as index 609faa0e9a3..3da046ff45c 100644 --- a/test/run/actors.as +++ b/test/run/actors.as @@ -1,20 +1,20 @@ 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) }; + public func tic_msg(n : Int) { if (n > 0) tictac_actor.tac_msg(n - 1) }; + public func tac_msg(n : Int) { if (n > 0) tictac_actor.tic_msg(n - 1) }; }; let _ = tictac_actor.tic_msg(10); func ignore(_ : async ()) = (); object tictac_async { - tic_async(n : Int) : async () { if (n > 0) ignore(tictac_async.tac_async(n - 1)) }; - tac_async(n : Int) : async () { if (n > 0) ignore(tictac_async.tic_async(n - 1)) }; + public func tic_async(n : Int) : async () { if (n > 0) ignore(tictac_async.tac_async(n - 1)) }; + public func tac_async(n : Int) : async () { if (n > 0) ignore(tictac_async.tic_async(n - 1)) }; }; let _ = tictac_async.tic_async(10); 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)) }; + public func tic_msg_async(n : Int) : async () { if (n > 0) ignore(tictac_actor_async.tac_msg_async(n - 1)) }; + public func 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/async-calls.as b/test/run/async-calls.as index 890a3e58746..208cd0964d2 100644 --- a/test/run/async-calls.as +++ b/test/run/async-calls.as @@ -2,46 +2,46 @@ before delivery. */ -let sync_object = new self { - private var x : Bool = false; +let sync_object = object self { + var x : Bool = false; - bump() { assert (x == false); x := true; assert (x == true); }; + public func bump() { assert (x == false); x := true; assert (x == true); }; - test() { assert (x == false); self.bump(); assert (x == true); }; + public func test() { assert (x == false); self.bump(); assert (x == true); }; }; sync_object.test(); let async_actor = actor self { - private var x : Bool = false; + var x : Bool = false; - bump() { assert (x == false); x := true; assert (x == true); }; + public func bump() { assert (x == false); x := true; assert (x == true); }; - test() { assert (x == false); self.bump(); assert (x == false); }; + public func test() { assert (x == false); self.bump(); assert (x == false); }; }; async_actor.test(); let async2_actor = actor self { - private var x : Bool = false; + var x : Bool = false; - bump() { assert (x == false); x := true; assert (x == true); }; + public func bump() { assert (x == false); x := true; assert (x == true); }; - test() { assert (x == false); bump(); assert (x == false); is_true(); }; + public func test() { assert (x == false); bump(); assert (x == false); is_true(); }; - is_true() { assert (x == true); }; + public func is_true() { assert (x == true); }; }; async2_actor.test(); let async_rec_actor = actor self { - private var x : Bool = false; + var x : Bool = false; - test(b : Bool) { + public func test(b : Bool) { if (b) { assert (x == false); x := true; assert (x == true); } else { assert (x == false); test(false); assert (x == false); is_true(); } }; - is_true() { assert (x == true); }; + public func is_true() { assert (x == true); }; }; async_rec_actor.test(true); diff --git a/test/run/control.as b/test/run/control.as index a4eeab3dbc9..887e1289431 100644 --- a/test/run/control.as +++ b/test/run/control.as @@ -1,8 +1,8 @@ actor class Control() { - private condition() : Bool = false; + func condition() : Bool = false; - testBlock() { + public func testBlock() { label l1 { break l1 }; @@ -12,44 +12,44 @@ actor class Control() { let (x, y, z) = label l3 : (Int, Bool, Text) (break l3(2, true, "")); }; - testWhile() { + public func testWhile() { label l while (condition()) { if true break l else continue l; }; }; - testLoop() { + public func testLoop() { label l loop { if true break l else continue l; }; }; - testLoopWhile() { + public func testLoopWhile() { label l loop { if true break l else continue l; } while (condition()); }; - testLoopWhile2() { + public func testLoopWhile2() { loop { } while (false); }; - testLoopWhile3() { + public func testLoopWhile3() { label l { loop { } while (false and true) }; }; - testLoopWhile4() { + public func testLoopWhile4() { label l loop { } while (true and false); }; - testNestedWhile() { + public func testNestedWhile() { label l while (condition()) { if true break l else continue l; diff --git a/test/run/coverage.as b/test/run/coverage.as index 8f5f5404b2d..43e0d748f1f 100644 --- a/test/run/coverage.as +++ b/test/run/coverage.as @@ -34,13 +34,13 @@ func f() { switch (0, 0) { case (_, (6 or _)) {}; case _ {} }; switch (0, 0) { case (0, _) {}; case (_, 0) {} }; switch (0, 0) { case (0, _) {}; case (_, 0) {}; case _ {} }; - switch (object {a = 0; b = 0}) { case {a = _; b = _} {}; case {a = _; b = 6} {} }; - switch (object {a = 0; b = 0}) { case {} {}; case {b = 6} {} }; - switch (object {a = 0; b = 0}) { case {a = _; b = 6 or _} {}; case _ {} }; - switch (object {a = 0; b = 0}) { case {b = 6 or _} {}; case _ {} }; - switch (object {a = 0; b = 0}) { case {a = 0} {}; case {b = 0} {} }; - switch (object {a = 0; b = 0}) { case {a = 0} {}; case {b = 0} {}; case {} {} }; - switch (object {a = true}) { case {a = true} {}; case {a = false} {} }; + switch (new {a = 0; b = 0}) { case {a = _; b = _} {}; case {a = _; b = 6} {} }; + switch (new {a = 0; b = 0}) { case {} {}; case {b = 6} {} }; + switch (new {a = 0; b = 0}) { case {a = _; b = 6 or _} {}; case _ {} }; + switch (new {a = 0; b = 0}) { case {b = 6 or _} {}; case _ {} }; + switch (new {a = 0; b = 0}) { case {a = 0} {}; case {b = 0} {} }; + switch (new {a = 0; b = 0}) { case {a = 0} {}; case {b = 0} {}; case {} {} }; + switch (new {a = true}) { case {a = true} {}; case {a = false} {} }; switch (#a 6 : {#a : Nat; #b : Nat}) { case (#a _) {}; case (#b _) {} }; switch (#a 6 : {#a : Nat; #b : Nat}) { case (#a _) {}; case (#b 6) {} }; switch (#a 6 : {#a : Nat; #b : Nat}) { case (#a _) {}; case (#a 5) {}; case (#b _) {} }; diff --git a/test/run/import-module.as b/test/run/import-module.as index 6a164620a6e..1b26b471a87 100644 --- a/test/run/import-module.as +++ b/test/run/import-module.as @@ -1,3 +1,3 @@ let L = import "lib/ListM.as"; type stack = L.List; -let s = L.cons(1,L.nil()); +let s = L.cons(1, L.nil()); diff --git a/test/run/ir-pat-subtype.as b/test/run/ir-pat-subtype.as index 0fc6bad58f4..7b1fa3eb0b2 100644 --- a/test/run/ir-pat-subtype.as +++ b/test/run/ir-pat-subtype.as @@ -1,23 +1,23 @@ -type L = {a:{}}; +type L = {a : {}}; type U = {}; let l = new {a = new {}}; -func f(l:L):U = switch l { - case (u:U) u; +func f(l : L) : U = switch l { + case (u : U) u; }; let {} = f(l); // tuples -func t1(tl : (L, L) ) : (U, U) = switch tl { +func t1(tl : (L, L)) : (U, U) = switch tl { case (tu : (U, U)) tu; }; -let ({}, {}) = t1((l,l)); +let ({}, {}) = t1((l, l)); func t2(tl : (L, L)) : (U, U) = switch tl { - case (u1 : U, u2 : U) (u1,u2); + case (u1 : U, u2 : U) (u1, u2); }; let ({}, {}) = t2((l, l)); @@ -41,34 +41,34 @@ let (? {} or _) = o2(? l); // records -func r1(rl : object { a : L }) : object { a : U } = switch rl { - case (ru : { a : U }) ru; +func r1(rl : {a : L}) : {a : U} = switch rl { + case (ru : {a : U}) ru; }; -let { a = {} } : object { a : U } = r1(object { a = l }); +let {a = {}} : {a : U} = r1(new {a = l}); -func r2(rl : object { a : L }) : object { a : U } = switch rl { - case ({a=u:U}) object {a=u}; +func r2(rl : {a : L}) : {a : U} = switch rl { + case ({a = u : U}) (new {a = u}); }; -let { a = {} } : object { a : U } = r2(object { a = l }); +let {a = {}} : {a : U} = r2(new {a = l}); -func r3(rl : object { a : L }) : object {} = switch rl { - case {} object {}; +func r3(rl : {a : L}) : {} = switch rl { + case {} (new {}); }; -let {}:object{} = r3(object{a=l}); +let {} : {} = r3(new {a = l}); // variants -func v1(vl : { #a : L }) : {#a:U} = switch vl { - case (vu : { #a : U }) vu; +func v1(vl : {#a : L}) : {#a : U} = switch vl { + case (vu : {#a : U}) vu; }; let (#a {})= v1(#a l); -func v2(vl : { #a : L }) : { #a : U } = switch vl { +func v2(vl : {#a : L}) : {#a : U} = switch vl { case (#a u) #a u; }; @@ -76,9 +76,8 @@ let (#a {}) = v2(#a l); // alternative patterns -func a(l : object { a : Int }):U = switch l { - case (({ a = 1 }:object { a : Int }) or ( _ : U) ) l; +func a(l : {a : Int}):U = switch l { + case (({a = 1} : {a : Int}) or (_ : U) ) l; }; -let {} = a(object {a = 2}); - +let {} = a(new {a = 2}); diff --git a/test/run/issue150.as b/test/run/issue150.as index baf5603978f..12047c10be5 100644 --- a/test/run/issue150.as +++ b/test/run/issue150.as @@ -1,6 +1,6 @@ -func f(x:C)=(); +func f(x : C) = (); class C() = this { - apply():() = f(this); + public func apply() : () = f(this); }; diff --git a/test/run/lib/ListM.as b/test/run/lib/ListM.as index 432fa38a153..5f09b3fea39 100644 --- a/test/run/lib/ListM.as +++ b/test/run/lib/ListM.as @@ -1,5 +1,6 @@ module { - type List = ?(T, List); - func nil() : List = null; - func cons(x : T, l : List) : List = ?(x, l); + public type List = ?(T, List); + + public func nil() : List = null; + public func cons(x : T, l : List) : List = ?(x, l); } diff --git a/test/run/module1.as b/test/run/module1.as index 0472186fbf9..b230c35646a 100644 --- a/test/run/module1.as +++ b/test/run/module1.as @@ -1,7 +1,7 @@ { -module X = -{ type T = Int; - let x:T = 1; +module X = { + public type T = Int; + public let x : T = 1; }; type T = X.T; @@ -12,14 +12,14 @@ let y = X.x + 1; { module X = { - type T = (A,A); - let x:T = (1,2); + public type T = (A,A); + public let x : T = (1, 2); }; type T = X.T; let x = X.x; -let (x1,x2) : T = X.x; +let (x1, x2) : T = X.x; assert (x1 == 1); assert (x2 == 2); @@ -28,32 +28,32 @@ assert (x2 == 2); { module X = { - module X = { - type T = (A,A); - let x:T = (1,2); + public module X = { + public type T = (A, A); + public let x : T = (1, 2); }; }; type T = X.X.T; let x = X.X.x; -let (x1,x2) : T = X.X.x; +let (x1, x2) : T = X.X.x; assert (x1 == 1); assert (x2 == 2); }; { module X = { - module X = { - type T = (A,A); - let x:T = (1,2); + public module X = { + public type T = (A, A); + public let x : T = (1, 2); }; }; module Y = { - type T = X.X.T; + public type T = X.X.T; - let x = X.X.x; - let (x1,x2) : T = X.X.x; + public let x = X.X.x; + public let (x1, x2) : T = X.X.x; }; let _ = assert (Y.x1 == 1); diff --git a/test/run/module2.as b/test/run/module2.as index 1edf73a741c..2b6f217a666 100644 --- a/test/run/module2.as +++ b/test/run/module2.as @@ -1,5 +1,5 @@ // check types and terms have separate namespaces -module X = { type x = Int; let x = 1; }; +module X = { public type x = Int; public let x = 1; }; type x = X.x; let x = X.x; -/* assert (x == 1); */ \ No newline at end of file +/* assert (x == 1); */ diff --git a/test/run/module3.as b/test/run/module3.as index baa59ecaebc..79ccfcc82c4 100644 --- a/test/run/module3.as +++ b/test/run/module3.as @@ -1,11 +1,12 @@ // test equivalence of various type references module List = { - type List = ?(A,List.List); + public type List = ?(A,List.List); + func rev(x : List, acc : List.List) : List { switch (x) { case (null) acc; - case (?(h,t)) rev(t,?(h,acc)); + case (?(h, t)) rev(t, ?(h, acc)); }; }; }; diff --git a/test/run/mut-field-bound.as b/test/run/mut-field-bound.as index 21ddc51f11a..100b94c0b3d 100644 --- a/test/run/mut-field-bound.as +++ b/test/run/mut-field-bound.as @@ -2,5 +2,5 @@ type Obj = {var x : Nat}; func foo(o : O) : Nat { o.x }; -let o : Obj = new {var x : Nat = 1}; +let o : Obj = new {var x = 1 : Nat}; assert(foo<{var x : Nat}>(o) == 1); diff --git a/test/run/nested-class-rec.as b/test/run/nested-class-rec.as index 4ab62442d0c..8a8a9b351d9 100644 --- a/test/run/nested-class-rec.as +++ b/test/run/nested-class-rec.as @@ -2,9 +2,7 @@ class Foo(f1:Int -> Int, f2:Int -> Int) { }; class Bar () { + func g(n:Int) : Int = n + 1; - private g(n:Int) : Int = n + 1; - - let Bar = Foo(g, g) : Foo; // annotation needed to typecheck constructor call - + public let Bar = Foo(g, g) : Foo; // annotation needed to typecheck constructor call }; diff --git a/test/run/nested-lexpr.as b/test/run/nested-lexpr.as index 2a9768bf52f..3d7371a1b4b 100644 --- a/test/run/nested-lexpr.as +++ b/test/run/nested-lexpr.as @@ -3,7 +3,7 @@ assert (a[0][0] == 1); a[0][0] := 2; assert (a[0][0] == 2); -let b : [{var x : Int}] = [new {var x : Int = 1}]; +let b : [{var x : Int}] = [new {var x = 1 : Int}]; assert (b[0].x == 1); b[0].x := 2; assert (b[0].x == 2); diff --git a/test/run/objects1.as b/test/run/objects1.as index faf19f324f9..8ec85aaa2c3 100644 --- a/test/run/objects1.as +++ b/test/run/objects1.as @@ -1,17 +1,17 @@ -let p = new {x = 3; private y = 2; get_y() : Int = y}; +let p = object {public let x = 3; let y = 2; public func get_y() : Int = y}; assert(p.x == 3); assert(p.get_y() == 2); let o : {a : {}; b : Nat} = new {a = new {x = 0}; b = a.x}; let oo = object { - private type T = Int; - let x : T = 3; - let (y, z) = (3, ""); - var v = 0; - func f() : T { g() + x }; - func g() : T { f() + y }; - private class C() {}; + type T = Int; + public let x : T = 3; + public let (y, z) = (3, ""); + public var v = 0; + public func f() : T { g() + x }; + public func g() : T { f() + y }; + class C() {}; }; // pattern matching @@ -38,7 +38,7 @@ assert (get_a () == -42); // subtyping and tuple patterns for comparison -let row : (Nat, Int, {c : Char; d : Text}) = (100, -42, new {c='C'; d="D"}); +let row : (Nat, Int, {c : Char; d : Text}) = (100, -42, new {c = 'C'; d = "D"}); func foo () : Int = switch row { case (a : Int, -42, {c} : {c : Char}) (word32ToNat(charToWord32 c)) // OK diff --git a/test/run/objects2.as b/test/run/objects2.as index db7ed3cee68..6fbfa236f5c 100644 --- a/test/run/objects2.as +++ b/test/run/objects2.as @@ -1,5 +1,5 @@ type O = {self : () -> O; x : Nat}; -let o = new this {self() : O = this; x = 1}; +let o = object this {public func self() : O = this; public let x = 1}; assert(o.x == 1); assert(o.self().x == 1); assert(o.self().self().x == 1); diff --git a/test/run/objects3.as b/test/run/objects3.as index 3c9de95c5d5..975a3e13a03 100644 --- a/test/run/objects3.as +++ b/test/run/objects3.as @@ -1,5 +1,5 @@ type Q = {var this : ?Q; x : Nat}; -let q : Q = new {var this : ?Q = null; x = 4}; +let q : Q = new {var this = null : ?Q; x = 4}; q.this := ?q; func unopt(x : ?T) : T = switch x { case (?y) y; case _ unopt(x) }; assert(unopt(unopt(q.this).this).x == 4); diff --git a/test/run/objects4.as b/test/run/objects4.as index 525387c8891..2f20b46f468 100644 --- a/test/run/objects4.as +++ b/test/run/objects4.as @@ -1,5 +1,5 @@ -let oddeven = new this { - odd(n : Int) : Bool = if (n > 0) this.odd(n - 1) else false; - even(n : Int) : Bool = if (n > 0) this.even(n - 1) else true; +let oddeven = object this { + public func odd(n : Int) : Bool = if (n > 0) this.odd(n - 1) else false; + public func even(n : Int) : Bool = if (n > 0) this.even(n - 1) else true; }; assert (oddeven.even(10)); diff --git a/test/run/objects5.as b/test/run/objects5.as index d5ef10c05be..1e7a576d555 100644 --- a/test/run/objects5.as +++ b/test/run/objects5.as @@ -1,5 +1,5 @@ -let p1 = new {var x = 3; private y = 2; get_y() : Int = y}; -let p2 = new {var x = 3; private y = 2; get_y() : Int = y}; +let p1 = object {public var x = 3; let y = 2; public func get_y() : Int = y}; +let p2 = object {public var x = 3; let y = 2; public func get_y() : Int = y}; assert(p1.x == 3); assert(p1.get_y() == 2); diff --git a/test/run/ok/coverage.run-ir.ok b/test/run/ok/coverage.run-ir.ok index 39ee1621c2d..5c8074a5068 100644 --- a/test/run/ok/coverage.run-ir.ok +++ b/test/run/ok/coverage.run-ir.ok @@ -13,10 +13,10 @@ coverage.as:31.25-31.34: warning, this case is never reached coverage.as:32.43-32.44: warning, this pattern is never matched coverage.as:33.35-33.49: warning, this case is never reached coverage.as:34.42-34.51: warning, this case is never reached -coverage.as:37.60-37.82: warning, this case is never reached -coverage.as:38.48-38.63: warning, this case is never reached -coverage.as:39.65-39.74: warning, this case is never reached -coverage.as:40.58-40.67: warning, this case is never reached +coverage.as:37.57-37.79: warning, this case is never reached +coverage.as:38.45-38.60: warning, this case is never reached +coverage.as:39.62-39.71: warning, this case is never reached +coverage.as:40.55-40.64: warning, this case is never reached coverage.as:46.58-46.72: warning, this case is never reached coverage.as:61.22-61.31: warning, this case is never reached coverage.as:62.28-62.37: warning, this case is never reached @@ -71,7 +71,7 @@ coverage.as:35.3-35.51: warning, the cases in this switch over type (Nat, Nat) do not cover value (1 or 2 or _, 1 or 2 or _) -coverage.as:41.3-41.70: warning, the cases in this switch over type +coverage.as:41.3-41.67: warning, the cases in this switch over type {a : Nat; b : Nat} do not cover value {a = 1 or 2 or _; b = 1 or 2 or _) diff --git a/test/run/ok/coverage.run-low.ok b/test/run/ok/coverage.run-low.ok index 39ee1621c2d..5c8074a5068 100644 --- a/test/run/ok/coverage.run-low.ok +++ b/test/run/ok/coverage.run-low.ok @@ -13,10 +13,10 @@ coverage.as:31.25-31.34: warning, this case is never reached coverage.as:32.43-32.44: warning, this pattern is never matched coverage.as:33.35-33.49: warning, this case is never reached coverage.as:34.42-34.51: warning, this case is never reached -coverage.as:37.60-37.82: warning, this case is never reached -coverage.as:38.48-38.63: warning, this case is never reached -coverage.as:39.65-39.74: warning, this case is never reached -coverage.as:40.58-40.67: warning, this case is never reached +coverage.as:37.57-37.79: warning, this case is never reached +coverage.as:38.45-38.60: warning, this case is never reached +coverage.as:39.62-39.71: warning, this case is never reached +coverage.as:40.55-40.64: warning, this case is never reached coverage.as:46.58-46.72: warning, this case is never reached coverage.as:61.22-61.31: warning, this case is never reached coverage.as:62.28-62.37: warning, this case is never reached @@ -71,7 +71,7 @@ coverage.as:35.3-35.51: warning, the cases in this switch over type (Nat, Nat) do not cover value (1 or 2 or _, 1 or 2 or _) -coverage.as:41.3-41.70: warning, the cases in this switch over type +coverage.as:41.3-41.67: warning, the cases in this switch over type {a : Nat; b : Nat} do not cover value {a = 1 or 2 or _; b = 1 or 2 or _) diff --git a/test/run/ok/coverage.run.ok b/test/run/ok/coverage.run.ok index 39ee1621c2d..5c8074a5068 100644 --- a/test/run/ok/coverage.run.ok +++ b/test/run/ok/coverage.run.ok @@ -13,10 +13,10 @@ coverage.as:31.25-31.34: warning, this case is never reached coverage.as:32.43-32.44: warning, this pattern is never matched coverage.as:33.35-33.49: warning, this case is never reached coverage.as:34.42-34.51: warning, this case is never reached -coverage.as:37.60-37.82: warning, this case is never reached -coverage.as:38.48-38.63: warning, this case is never reached -coverage.as:39.65-39.74: warning, this case is never reached -coverage.as:40.58-40.67: warning, this case is never reached +coverage.as:37.57-37.79: warning, this case is never reached +coverage.as:38.45-38.60: warning, this case is never reached +coverage.as:39.62-39.71: warning, this case is never reached +coverage.as:40.55-40.64: warning, this case is never reached coverage.as:46.58-46.72: warning, this case is never reached coverage.as:61.22-61.31: warning, this case is never reached coverage.as:62.28-62.37: warning, this case is never reached @@ -71,7 +71,7 @@ coverage.as:35.3-35.51: warning, the cases in this switch over type (Nat, Nat) do not cover value (1 or 2 or _, 1 or 2 or _) -coverage.as:41.3-41.70: warning, the cases in this switch over type +coverage.as:41.3-41.67: warning, the cases in this switch over type {a : Nat; b : Nat} do not cover value {a = 1 or 2 or _; b = 1 or 2 or _) diff --git a/test/run/ok/coverage.tc.ok b/test/run/ok/coverage.tc.ok index 39ee1621c2d..5c8074a5068 100644 --- a/test/run/ok/coverage.tc.ok +++ b/test/run/ok/coverage.tc.ok @@ -13,10 +13,10 @@ coverage.as:31.25-31.34: warning, this case is never reached coverage.as:32.43-32.44: warning, this pattern is never matched coverage.as:33.35-33.49: warning, this case is never reached coverage.as:34.42-34.51: warning, this case is never reached -coverage.as:37.60-37.82: warning, this case is never reached -coverage.as:38.48-38.63: warning, this case is never reached -coverage.as:39.65-39.74: warning, this case is never reached -coverage.as:40.58-40.67: warning, this case is never reached +coverage.as:37.57-37.79: warning, this case is never reached +coverage.as:38.45-38.60: warning, this case is never reached +coverage.as:39.62-39.71: warning, this case is never reached +coverage.as:40.55-40.64: warning, this case is never reached coverage.as:46.58-46.72: warning, this case is never reached coverage.as:61.22-61.31: warning, this case is never reached coverage.as:62.28-62.37: warning, this case is never reached @@ -71,7 +71,7 @@ coverage.as:35.3-35.51: warning, the cases in this switch over type (Nat, Nat) do not cover value (1 or 2 or _, 1 or 2 or _) -coverage.as:41.3-41.70: warning, the cases in this switch over type +coverage.as:41.3-41.67: warning, the cases in this switch over type {a : Nat; b : Nat} do not cover value {a = 1 or 2 or _; b = 1 or 2 or _) diff --git a/test/run/ok/coverage.wasm.stderr.ok b/test/run/ok/coverage.wasm.stderr.ok index 39ee1621c2d..5c8074a5068 100644 --- a/test/run/ok/coverage.wasm.stderr.ok +++ b/test/run/ok/coverage.wasm.stderr.ok @@ -13,10 +13,10 @@ coverage.as:31.25-31.34: warning, this case is never reached coverage.as:32.43-32.44: warning, this pattern is never matched coverage.as:33.35-33.49: warning, this case is never reached coverage.as:34.42-34.51: warning, this case is never reached -coverage.as:37.60-37.82: warning, this case is never reached -coverage.as:38.48-38.63: warning, this case is never reached -coverage.as:39.65-39.74: warning, this case is never reached -coverage.as:40.58-40.67: warning, this case is never reached +coverage.as:37.57-37.79: warning, this case is never reached +coverage.as:38.45-38.60: warning, this case is never reached +coverage.as:39.62-39.71: warning, this case is never reached +coverage.as:40.55-40.64: warning, this case is never reached coverage.as:46.58-46.72: warning, this case is never reached coverage.as:61.22-61.31: warning, this case is never reached coverage.as:62.28-62.37: warning, this case is never reached @@ -71,7 +71,7 @@ coverage.as:35.3-35.51: warning, the cases in this switch over type (Nat, Nat) do not cover value (1 or 2 or _, 1 or 2 or _) -coverage.as:41.3-41.70: warning, the cases in this switch over type +coverage.as:41.3-41.67: warning, the cases in this switch over type {a : Nat; b : Nat} do not cover value {a = 1 or 2 or _; b = 1 or 2 or _) diff --git a/test/run/quicksort.as b/test/run/quicksort.as index 96412a19a3d..cd5d77dabf6 100644 --- a/test/run/quicksort.as +++ b/test/run/quicksort.as @@ -1,5 +1,5 @@ class QS(cmp : (T, T) -> Int) { - quicksort(a : [var T], lo : Nat, hi : Nat) { + public func quicksort(a : [var T], lo : Nat, hi : Nat) { if (lo < hi) { let p = partition(a, lo, hi); quicksort(a, lo, p); @@ -7,15 +7,15 @@ class QS(cmp : (T, T) -> Int) { } }; - private swap(a : [var T], i : Nat, j : Nat) { + func swap(a : [var T], i : Nat, j : Nat) { let temp = a[i]; a[i] := a[j]; a[j] := temp; }; - private trace(v : T) {}; + func trace(v : T) {}; - private partition(a : [var T], lo : Nat, hi : Nat) : Nat { + func partition(a : [var T], lo : Nat, hi : Nat) : Nat { trace<[var T]>(a); let pivot = a[lo]; var i = lo; diff --git a/test/run/type-definition.as b/test/run/type-definition.as index 3ae60c90970..e24aefa80d7 100644 --- a/test/run/type-definition.as +++ b/test/run/type-definition.as @@ -10,10 +10,10 @@ type None = (); // shadowing prelude // Test printing of shadowed type constructors class C() {}; type T = {f : X -> C}; -class D(x : T) {r = x.f}; +class D(x : T) {let r = x.f}; type U = {f : X -> Y}; -class E(x : U) {r = x.f}; +class E(x : U) {let r = x.f}; // This is an expected forward reference error //class F(x : FF) {r = x.a}; diff --git a/test/run/type-inclusion.as b/test/run/type-inclusion.as index 14217da15eb..6bdb863287f 100644 --- a/test/run/type-inclusion.as +++ b/test/run/type-inclusion.as @@ -90,14 +90,14 @@ func f(x : A) : B = x; // Classes { -class C() {f(x : X) {}}; +class C() {public func f(x : X) {}}; type A = C; type B = {f : X -> ()}; func f(x : A) : B = x; }; { -class C() {f (x : X) {}}; +class C() {public func f(x : X) {}}; type A = C; type B = {f : X -> ()}; func f(x : A) : B = x; @@ -137,21 +137,21 @@ func f(x : A) : B = x; }; { -class C() { x = 0 }; +class C() { public let x = 0 }; type A = X -> X; type B = X -> X; func f(x : A) : B = x; }; { -class C() {f() : X { f() }}; +class C() {public func f() : X { f() }}; type A = X}> X -> X; type B = > X -> X; func f(x : A) : B = x; }; { -class C() {f() : X { f() }}; +class C() {public func f() : X { f() }}; type A = Nat}> X -> X; type B = > X -> X; func f(x : A) : B = x; From f64f3f89252ce949db7b1d4cbda890a814de4c63 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Tue, 16 Jul 2019 11:26:06 -0700 Subject: [PATCH 0284/1176] sync with master --- test/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/run.sh b/test/run.sh index 3a98ad4b2dd..5dccbbf92a0 100755 --- a/test/run.sh +++ b/test/run.sh @@ -233,7 +233,7 @@ do if [ -e $out/$base.js ] then $ECHO -n " [node]" - export NODE_PATH=$NODE_PATH:$JSCLIENT/node_modules:$JSCLIENT/src + export NODE_PATH=$NODE_PATH:$JSCLIENT:$JSCLIENT/src $NODE $out/$base.js > $out/$base.err 2>&1 diff_files="$diff_files $base.err" fi From 74e87152fd621bc43d2d66ca6e25f736e32f3af9 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Tue, 16 Jul 2019 12:17:15 -0700 Subject: [PATCH 0285/1176] do not run node.js for quick --- test/quick.mk | 2 +- test/run.sh | 21 ++++++++++++++------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/test/quick.mk b/test/quick.mk index 50ebab5d391..1217ed0bbdc 100644 --- a/test/quick.mk +++ b/test/quick.mk @@ -22,4 +22,4 @@ _out/%.done: %.sh $(wildcard ../../src/asc) ../run.sh | _out _out/%.done: %.wat $(wildcard ../../src/asc) ../run.sh | _out @+ (../run.sh $(RUNFLAGS) $< > $@.tmp && mv $@.tmp $@) || (cat $@.tmp; rm -f $@.tmp; false) _out/%.done: %.did $(wildcard ../../src/didc) ../run.sh | _out - @+ (../run.sh $(RUNFLAGS) $< > $@.tmp && mv $@.tmp $@) || (cat $@.tmp; rm -f $@.tmp; false) + @+ (../run.sh -n $(RUNFLAGS) $< > $@.tmp && mv $@.tmp $@) || (cat $@.tmp; rm -f $@.tmp; false) diff --git a/test/run.sh b/test/run.sh index 5dccbbf92a0..18e713e8214 100755 --- a/test/run.sh +++ b/test/run.sh @@ -8,6 +8,7 @@ # # -a: Update the files in ok/ # -d: Compile without -no-dfinity-api, uses dvm to run +# -n: Do not check JS binding via node.js # -s: Be silent in sunny-day execution # @@ -25,11 +26,11 @@ DIDC=${DIDC:-$(realpath $(dirname $0)/../src/didc)} export AS_LD WASM=${WASM:-wasm} DVM_WRAPPER=$(realpath $(dirname $0)/dvm.sh) +NODE=yes JSCLIENT=${JSCLIENT:-$(realpath $(dirname $0)/../../dev/experimental/js-dfinity-client)} -NODE=node ECHO=echo -while getopts "ads" o; do +while getopts "adns" o; do case "${o}" in a) ACCEPT=yes @@ -37,6 +38,9 @@ while getopts "ads" o; do d) DFINITY=yes ;; + n) + NODE=no + ;; s) ECHO=true ;; @@ -230,12 +234,15 @@ do $DIDC --js $base.did > $out/$base.js 2>&1 diff_files="$diff_files $base.js" - if [ -e $out/$base.js ] + if [ $NODE = 'yes' ] then - $ECHO -n " [node]" - export NODE_PATH=$NODE_PATH:$JSCLIENT:$JSCLIENT/src - $NODE $out/$base.js > $out/$base.err 2>&1 - diff_files="$diff_files $base.err" + if [ -e $out/$base.js ] + then + $ECHO -n " [node]" + export NODE_PATH=$NODE_PATH:$JSCLIENT:$JSCLIENT/src + node $out/$base.js > $out/$base.err 2>&1 + diff_files="$diff_files $base.err" + fi fi fi fi From 695daf285eab3526f20a2f32794942a3b78f00c2 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 17 Jul 2019 10:51:07 +0200 Subject: [PATCH 0286/1176] IR: Let primitive expressions take manifest arguments (#572) Triggered by the clean-up necessary post #560 I finally fixe something that bothered me a long time: The IR pretends that primitive values are first-class functions, but they are never compiled that way (and should not, and maybe even cannot, as in the case of `@serialize` with a lying polymorophic type), instead they _always_ have manifest arguments. So this gives `PrimE` an `exp list`. At this point, there is no fundamental difference anymore between an unary operation and a primitive with one argument. So unary and binary operations and relations become just one such primtive operations. This removes redundancy in IR-to-IR passes. There is currently an `OtherPrim` constructor that still takes a string. Eventually, this should disappear, replaced by an ADT of the actual prims we support, e.g. a `NumericConversion of (Type.prim, Type.prim)` constructor instead of the unstructured `"Int->Word32"` strings right now. This would also allow for a nicer backend, as common code is easiler shared between the many conversions. --- src/as_values/prim.ml | 2 - src/codegen/compile.ml | 548 +++++++++--------- src/ir_def/arrange_ir.ml | 15 +- src/ir_def/check_ir.ml | 86 +-- src/ir_def/construct.ml | 37 +- src/ir_def/construct.mli | 13 +- src/ir_def/freevars.ml | 6 +- src/ir_def/ir.ml | 14 +- src/ir_def/ir_effect.ml | 6 +- src/ir_interpreter/interpret_ir.ml | 58 +- src/ir_passes/async.ml | 44 +- src/ir_passes/await.ml | 31 +- src/ir_passes/rename.ml | 6 +- src/ir_passes/serialization.ml | 26 +- src/ir_passes/show.ml | 12 +- src/ir_passes/tailcall.ml | 9 +- src/lowering/desugar.ml | 15 +- .../fail/ok/use-before-define5.wasm.stderr.ok | 2 +- .../ok/counter-class.wasm.stderr.ok | 13 +- 19 files changed, 462 insertions(+), 481 deletions(-) diff --git a/src/as_values/prim.ml b/src/as_values/prim.ml index 92e0bcba75f..1adc64a5ba5 100644 --- a/src/as_values/prim.ml +++ b/src/as_values/prim.ml @@ -253,8 +253,6 @@ let prim = function let nobbles = mapi (fun i f -> f i) (classify_utf8_leader (of_int (Char.code s.[0]))) in let code = fold_left (fun acc nobble -> logor (shift_left acc 6) nobble) 0l nobbles in k (Tup [Word32 (of_int (length nobbles)); Char (to_int code)]) - | "@serialize" -> fun v k -> k (Serialized v) - | "@deserialize" -> fun v k -> k (as_serialized v) | "array_len" -> fun v k -> k (Int (Int.of_int (Array.length (Value.as_array v)))) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 66ceea44434..42486dcceb2 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -5208,258 +5208,284 @@ and compile_exp (env : E.t) ae exp = SR.UnboxedReference, compile_exp_as env ae SR.UnboxedReference e ^^ actor_fake_object_idx env name - (* We only allow prims of certain shapes, as they occur in the prelude *) - | CallE (_, ({ it = PrimE p; _} as pe), typ_args, e) -> - begin - (* First check for all unary prims. *) - match p with - | "array_len" -> - SR.Vanilla, - compile_exp_vanilla env ae e ^^ - Heap.load_field Arr.len_field ^^ - BigNum.from_word32 env - - | "text_len" -> - SR.Vanilla, - compile_exp_vanilla env ae e ^^ - Text.len env - - | "text_chars" -> - SR.Vanilla, - compile_exp_vanilla env ae e ^^ - Text.text_chars_direct env - - | "@serialize" -> - SR.UnboxedReference, - let t = match typ_args with [t] -> t | _ -> assert false in - compile_exp_vanilla env ae e ^^ - Serialization.serialize env t - - | "@deserialize" -> - SR.Vanilla, - let t = match typ_args with [t] -> t | _ -> assert false in - compile_exp_as env ae SR.UnboxedReference e ^^ - Serialization.deserialize env t - - | "abs" -> - SR.Vanilla, - compile_exp_vanilla env ae e ^^ - BigNum.compile_abs env - - | "rts_version" -> - SR.Vanilla, - compile_exp_as env ae SR.unit e ^^ - E.call_import env "rts" "version" - - | "idlHash" -> - SR.Vanilla, - E.trap_with env "idlHash only implemented in interpreter " - - | "Nat->Word8" - | "Int->Word8" -> - SR.Vanilla, - compile_exp_vanilla env ae e ^^ - Prim.prim_shiftToWordN env (UnboxedSmallWord.shift_of_type Type.Word8) - - | "Nat->Word16" - | "Int->Word16" -> - SR.Vanilla, - compile_exp_vanilla env ae e ^^ - Prim.prim_shiftToWordN env (UnboxedSmallWord.shift_of_type Type.Word16) - - | "Nat->Word32" - | "Int->Word32" -> - SR.UnboxedWord32, - compile_exp_vanilla env ae e ^^ - Prim.prim_intToWord32 env - - | "Nat->Word64" - | "Int->Word64" -> - SR.UnboxedWord64, - compile_exp_vanilla env ae e ^^ - BigNum.to_word64 env - - | "Nat64->Word64" - | "Int64->Word64" - | "Word64->Nat64" - | "Word64->Int64" - | "Nat32->Word32" - | "Int32->Word32" - | "Word32->Nat32" - | "Word32->Int32" - | "Nat16->Word16" - | "Int16->Word16" - | "Word16->Nat16" - | "Word16->Int16" - | "Nat8->Word8" - | "Int8->Word8" - | "Word8->Nat8" - | "Word8->Int8" -> - SR.Vanilla, - compile_exp_vanilla env ae e ^^ - G.nop - - | "Int->Int64" -> - SR.UnboxedWord64, - compile_exp_vanilla env ae e ^^ - Func.share_code1 env "Int->Int64" ("n", I32Type) [I64Type] (fun env get_n -> - get_n ^^ - BigNum.fits_signed_bits env 64 ^^ - E.else_trap_with env "losing precision" ^^ - get_n ^^ - BigNum.truncate_to_word64 env) - - | "Int->Int32" - | "Int->Int16" - | "Int->Int8" -> - let ty = exp.note.note_typ in - StackRep.of_type ty, - let pty = prim_of_typ ty in - compile_exp_vanilla env ae e ^^ - Func.share_code1 env (UnboxedSmallWord.name_of_type pty "Int->") ("n", I32Type) [I32Type] (fun env get_n -> - get_n ^^ - BigNum.fits_signed_bits env (UnboxedSmallWord.bits_of_type pty) ^^ - E.else_trap_with env "losing precision" ^^ - get_n ^^ - BigNum.truncate_to_word32 env ^^ - UnboxedSmallWord.msb_adjust pty) - - | "Nat->Nat64" -> - SR.UnboxedWord64, - compile_exp_vanilla env ae e ^^ - Func.share_code1 env "Nat->Nat64" ("n", I32Type) [I64Type] (fun env get_n -> - get_n ^^ - BigNum.fits_unsigned_bits env 64 ^^ - E.else_trap_with env "losing precision" ^^ - get_n ^^ - BigNum.truncate_to_word64 env) - - | "Nat->Nat32" - | "Nat->Nat16" - | "Nat->Nat8" -> - let ty = exp.note.note_typ in - StackRep.of_type ty, - let pty = prim_of_typ ty in - compile_exp_vanilla env ae e ^^ - Func.share_code1 env (UnboxedSmallWord.name_of_type pty "Nat->") ("n", I32Type) [I32Type] (fun env get_n -> - get_n ^^ - BigNum.fits_unsigned_bits env (UnboxedSmallWord.bits_of_type pty) ^^ - E.else_trap_with env "losing precision" ^^ - get_n ^^ - BigNum.truncate_to_word32 env ^^ - UnboxedSmallWord.msb_adjust pty) - - | "Char->Word32" -> - SR.UnboxedWord32, - compile_exp_vanilla env ae e ^^ - UnboxedSmallWord.unbox_codepoint - - | "Nat8->Nat" - | "Word8->Nat" -> - SR.Vanilla, - compile_exp_vanilla env ae e ^^ - Prim.prim_shiftWordNtoUnsigned env (UnboxedSmallWord.shift_of_type Type.Word8) - | "Int8->Int" - | "Word8->Int" -> - SR.Vanilla, - compile_exp_vanilla env ae e ^^ - Prim.prim_shiftWordNtoSigned env (UnboxedSmallWord.shift_of_type Type.Word8) - - | "Nat16->Nat" - | "Word16->Nat" -> - SR.Vanilla, - compile_exp_vanilla env ae e ^^ - Prim.prim_shiftWordNtoUnsigned env (UnboxedSmallWord.shift_of_type Type.Word16) - | "Int16->Int" - | "Word16->Int" -> - SR.Vanilla, - compile_exp_vanilla env ae e ^^ - Prim.prim_shiftWordNtoSigned env (UnboxedSmallWord.shift_of_type Type.Word16) - - | "Nat32->Nat" - | "Word32->Nat" -> - SR.Vanilla, - compile_exp_as env ae SR.UnboxedWord32 e ^^ - Prim.prim_word32toNat env - | "Int32->Int" - | "Word32->Int" -> - SR.Vanilla, - compile_exp_as env ae SR.UnboxedWord32 e ^^ - Prim.prim_word32toInt env - - | "Nat64->Nat" - | "Word64->Nat" -> - SR.Vanilla, - compile_exp_as env ae SR.UnboxedWord64 e ^^ - BigNum.from_word64 env - | "Int64->Int" - | "Word64->Int" -> - SR.Vanilla, - compile_exp_as env ae SR.UnboxedWord64 e ^^ - BigNum.from_signed_word64 env - - | "Word32->Char" -> - SR.Vanilla, - compile_exp_as env ae SR.UnboxedWord32 e ^^ - UnboxedSmallWord.box_codepoint - - | "popcnt" -> - SR.UnboxedWord32, - compile_exp_as env ae SR.UnboxedWord32 e ^^ - G.i (Unary (Wasm.Values.I32 I32Op.Popcnt)) - | "popcnt8" - | "popcnt16" -> - SR.Vanilla, - compile_exp_vanilla env ae e ^^ - G.i (Unary (Wasm.Values.I32 I32Op.Popcnt)) ^^ - UnboxedSmallWord.msb_adjust (match p with | "popcnt8" -> Type.Word8 | _ -> Type.Word16) - | "popcnt64" -> - SR.UnboxedWord64, - compile_exp_as env ae SR.UnboxedWord64 e ^^ - G.i (Unary (Wasm.Values.I64 I64Op.Popcnt)) - | "clz" -> SR.UnboxedWord32, compile_exp_as env ae SR.UnboxedWord32 e ^^ G.i (Unary (Wasm.Values.I32 I32Op.Clz)) - | "clz8" -> SR.Vanilla, compile_exp_vanilla env ae e ^^ UnboxedSmallWord.clz_kernel Type.Word8 - | "clz16" -> SR.Vanilla, compile_exp_vanilla env ae e ^^ UnboxedSmallWord.clz_kernel Type.Word16 - | "clz64" -> SR.UnboxedWord64, compile_exp_as env ae SR.UnboxedWord64 e ^^ G.i (Unary (Wasm.Values.I64 I64Op.Clz)) - | "ctz" -> SR.UnboxedWord32, compile_exp_as env ae SR.UnboxedWord32 e ^^ G.i (Unary (Wasm.Values.I32 I32Op.Ctz)) - | "ctz8" -> SR.Vanilla, compile_exp_vanilla env ae e ^^ UnboxedSmallWord.ctz_kernel Type.Word8 - | "ctz16" -> SR.Vanilla, compile_exp_vanilla env ae e ^^ UnboxedSmallWord.ctz_kernel Type.Word16 - | "ctz64" -> SR.UnboxedWord64, compile_exp_as env ae SR.UnboxedWord64 e ^^ G.i (Unary (Wasm.Values.I64 I64Op.Ctz)) - - | "Char->Text" -> - SR.Vanilla, - compile_exp_vanilla env ae e ^^ - Text.prim_showChar env - - | "print" -> - SR.unit, - compile_exp_vanilla env ae e ^^ - Dfinity.prim_print env - | "decodeUTF8" -> - SR.UnboxedTuple 2, - compile_exp_vanilla env ae e ^^ - Text.prim_decodeUTF8 env - | _ -> - (* Now try the binary prims, expecting a manifest tuple argument *) - begin match e.it with - | TupE [e1;e2] -> - begin - let compile_kernel_as sr inst = sr, compile_exp_as env ae sr e1 ^^ compile_exp_as env ae sr e2 ^^ inst - in match p with - | "Array.init" -> compile_kernel_as SR.Vanilla (Arr.init env) - | "Array.tabulate" -> compile_kernel_as SR.Vanilla (Arr.tabulate env) - | "btst8" -> compile_kernel_as SR.Vanilla (UnboxedSmallWord.btst_kernel env Type.Word8) - | "btst16" -> compile_kernel_as SR.Vanilla (UnboxedSmallWord.btst_kernel env Type.Word16) - | "btst" -> compile_kernel_as SR.UnboxedWord32 (UnboxedSmallWord.btst_kernel env Type.Word32) - | "btst64" -> compile_kernel_as SR.UnboxedWord64 ( - let (set_b, get_b) = new_local64 env "b" - in set_b ^^ compile_const_64 1L ^^ get_b ^^ G.i (Binary (Wasm.Values.I64 I64Op.Shl)) ^^ - G.i (Binary (Wasm.Values.I64 I64Op.And))) - - | _ -> SR.Unreachable, todo_trap env "compile_exp" (Arrange_ir.exp pe) - end - | _ -> SR.Unreachable, todo_trap env "compile_exp" (Arrange_ir.exp pe) - end + | PrimE (p, es) -> + + (* for more concise code when all arguments and result use the same sr *) + let const_sr sr inst = sr, G.concat_map (compile_exp_as env ae sr) es ^^ inst in + + begin match p, es with + + (* Operators *) + + | UnPrim (_, Operator.PosOp), [e1] -> compile_exp env ae e1 + | UnPrim (t, op), [e1] -> + let sr_in, sr_out, code = compile_unop env t op in + sr_out, + compile_exp_as env ae sr_in e1 ^^ + code + | BinPrim (t, op), [e1;e2] -> + let sr_in, sr_out, code = compile_binop env t op in + sr_out, + compile_exp_as env ae sr_in e1 ^^ + compile_exp_as env ae sr_in e2 ^^ + code + | RelPrim (t, op), [e1;e2] -> + let sr, code = compile_relop env t op in + SR.bool, + compile_exp_as env ae sr e1 ^^ + compile_exp_as env ae sr e2 ^^ + code + + (* Special prims *) + + | SerializePrim t, [e] -> + SR.UnboxedReference, + compile_exp_vanilla env ae e ^^ + Serialization.serialize env t + + | DeserializePrim t, [e] -> + SR.Vanilla, + compile_exp_as env ae SR.UnboxedReference e ^^ + Serialization.deserialize env t + + (* Other prims, unary*) + + | OtherPrim "array_len", [e] -> + SR.Vanilla, + compile_exp_vanilla env ae e ^^ + Heap.load_field Arr.len_field ^^ + BigNum.from_word32 env + + | OtherPrim "text_len", [e] -> + SR.Vanilla, + compile_exp_vanilla env ae e ^^ + Text.len env + + | OtherPrim "text_chars", [e] -> + SR.Vanilla, + compile_exp_vanilla env ae e ^^ + Text.text_chars_direct env + + | OtherPrim "abs", [e] -> + SR.Vanilla, + compile_exp_vanilla env ae e ^^ + BigNum.compile_abs env + + | OtherPrim "rts_version", [] -> + SR.Vanilla, + E.call_import env "rts" "version" + + | OtherPrim "idlHash", [e] -> + SR.Vanilla, + E.trap_with env "idlHash only implemented in interpreter " + + | OtherPrim "Nat->Word8", [e] + | OtherPrim "Int->Word8", [e] -> + SR.Vanilla, + compile_exp_vanilla env ae e ^^ + Prim.prim_shiftToWordN env (UnboxedSmallWord.shift_of_type Type.Word8) + + | OtherPrim "Nat->Word16", [e] + | OtherPrim "Int->Word16", [e] -> + SR.Vanilla, + compile_exp_vanilla env ae e ^^ + Prim.prim_shiftToWordN env (UnboxedSmallWord.shift_of_type Type.Word16) + + | OtherPrim "Nat->Word32", [e] + | OtherPrim "Int->Word32", [e] -> + SR.UnboxedWord32, + compile_exp_vanilla env ae e ^^ + Prim.prim_intToWord32 env + + | OtherPrim "Nat->Word64", [e] + | OtherPrim "Int->Word64", [e] -> + SR.UnboxedWord64, + compile_exp_vanilla env ae e ^^ + BigNum.to_word64 env + + | OtherPrim "Nat64->Word64", [e] + | OtherPrim "Int64->Word64", [e] + | OtherPrim "Word64->Nat64", [e] + | OtherPrim "Word64->Int64", [e] + | OtherPrim "Nat32->Word32", [e] + | OtherPrim "Int32->Word32", [e] + | OtherPrim "Word32->Nat32", [e] + | OtherPrim "Word32->Int32", [e] + | OtherPrim "Nat16->Word16", [e] + | OtherPrim "Int16->Word16", [e] + | OtherPrim "Word16->Nat16", [e] + | OtherPrim "Word16->Int16", [e] + | OtherPrim "Nat8->Word8", [e] + | OtherPrim "Int8->Word8", [e] + | OtherPrim "Word8->Nat8", [e] + | OtherPrim "Word8->Int8", [e] -> + SR.Vanilla, + compile_exp_vanilla env ae e ^^ + G.nop + + | OtherPrim "Int->Int64", [e] -> + SR.UnboxedWord64, + compile_exp_vanilla env ae e ^^ + Func.share_code1 env "Int->Int64" ("n", I32Type) [I64Type] (fun env get_n -> + get_n ^^ + BigNum.fits_signed_bits env 64 ^^ + E.else_trap_with env "losing precision" ^^ + get_n ^^ + BigNum.truncate_to_word64 env) + + | OtherPrim "Int->Int32", [e] + | OtherPrim "Int->Int16", [e] + | OtherPrim "Int->Int8", [e] -> + let ty = exp.note.note_typ in + StackRep.of_type ty, + let pty = prim_of_typ ty in + compile_exp_vanilla env ae e ^^ + Func.share_code1 env (UnboxedSmallWord.name_of_type pty "Int->") ("n", I32Type) [I32Type] (fun env get_n -> + get_n ^^ + BigNum.fits_signed_bits env (UnboxedSmallWord.bits_of_type pty) ^^ + E.else_trap_with env "losing precision" ^^ + get_n ^^ + BigNum.truncate_to_word32 env ^^ + UnboxedSmallWord.msb_adjust pty) + + | OtherPrim "Nat->Nat64", [e] -> + SR.UnboxedWord64, + compile_exp_vanilla env ae e ^^ + Func.share_code1 env "Nat->Nat64" ("n", I32Type) [I64Type] (fun env get_n -> + get_n ^^ + BigNum.fits_unsigned_bits env 64 ^^ + E.else_trap_with env "losing precision" ^^ + get_n ^^ + BigNum.truncate_to_word64 env) + + | OtherPrim "Nat->Nat32", [e] + | OtherPrim "Nat->Nat16", [e] + | OtherPrim "Nat->Nat8", [e] -> + let ty = exp.note.note_typ in + StackRep.of_type ty, + let pty = prim_of_typ ty in + compile_exp_vanilla env ae e ^^ + Func.share_code1 env (UnboxedSmallWord.name_of_type pty "Nat->") ("n", I32Type) [I32Type] (fun env get_n -> + get_n ^^ + BigNum.fits_unsigned_bits env (UnboxedSmallWord.bits_of_type pty) ^^ + E.else_trap_with env "losing precision" ^^ + get_n ^^ + BigNum.truncate_to_word32 env ^^ + UnboxedSmallWord.msb_adjust pty) + + | OtherPrim "Char->Word32", [e] -> + SR.UnboxedWord32, + compile_exp_vanilla env ae e ^^ + UnboxedSmallWord.unbox_codepoint + + | OtherPrim "Nat8->Nat", [e] + | OtherPrim "Word8->Nat", [e] -> + SR.Vanilla, + compile_exp_vanilla env ae e ^^ + Prim.prim_shiftWordNtoUnsigned env (UnboxedSmallWord.shift_of_type Type.Word8) + | OtherPrim "Int8->Int", [e] + | OtherPrim "Word8->Int", [e] -> + SR.Vanilla, + compile_exp_vanilla env ae e ^^ + Prim.prim_shiftWordNtoSigned env (UnboxedSmallWord.shift_of_type Type.Word8) + + | OtherPrim "Nat16->Nat", [e] + | OtherPrim "Word16->Nat", [e] -> + SR.Vanilla, + compile_exp_vanilla env ae e ^^ + Prim.prim_shiftWordNtoUnsigned env (UnboxedSmallWord.shift_of_type Type.Word16) + | OtherPrim "Int16->Int", [e] + | OtherPrim "Word16->Int", [e] -> + SR.Vanilla, + compile_exp_vanilla env ae e ^^ + Prim.prim_shiftWordNtoSigned env (UnboxedSmallWord.shift_of_type Type.Word16) + + | OtherPrim "Nat32->Nat", [e] + | OtherPrim "Word32->Nat", [e] -> + SR.Vanilla, + compile_exp_as env ae SR.UnboxedWord32 e ^^ + Prim.prim_word32toNat env + | OtherPrim "Int32->Int", [e] + | OtherPrim "Word32->Int", [e] -> + SR.Vanilla, + compile_exp_as env ae SR.UnboxedWord32 e ^^ + Prim.prim_word32toInt env + + | OtherPrim "Nat64->Nat", [e] + | OtherPrim "Word64->Nat", [e] -> + SR.Vanilla, + compile_exp_as env ae SR.UnboxedWord64 e ^^ + BigNum.from_word64 env + | OtherPrim "Int64->Int", [e] + | OtherPrim "Word64->Int", [e] -> + SR.Vanilla, + compile_exp_as env ae SR.UnboxedWord64 e ^^ + BigNum.from_signed_word64 env + + | OtherPrim "Word32->Char", [e] -> + SR.Vanilla, + compile_exp_as env ae SR.UnboxedWord32 e ^^ + UnboxedSmallWord.box_codepoint + + | OtherPrim "popcnt", [e] -> + SR.UnboxedWord32, + compile_exp_as env ae SR.UnboxedWord32 e ^^ + G.i (Unary (Wasm.Values.I32 I32Op.Popcnt)) + | OtherPrim "popcnt8", [e] -> + SR.Vanilla, + compile_exp_vanilla env ae e ^^ + G.i (Unary (Wasm.Values.I32 I32Op.Popcnt)) ^^ + UnboxedSmallWord.msb_adjust Type.Word8 + | OtherPrim "popcnt16", [e] -> + SR.Vanilla, + compile_exp_vanilla env ae e ^^ + G.i (Unary (Wasm.Values.I32 I32Op.Popcnt)) ^^ + UnboxedSmallWord.msb_adjust Type.Word16 + | OtherPrim "popcnt64", [e] -> + SR.UnboxedWord64, + compile_exp_as env ae SR.UnboxedWord64 e ^^ + G.i (Unary (Wasm.Values.I64 I64Op.Popcnt)) + | OtherPrim "clz", [e] -> SR.UnboxedWord32, compile_exp_as env ae SR.UnboxedWord32 e ^^ G.i (Unary (Wasm.Values.I32 I32Op.Clz)) + | OtherPrim "clz8", [e] -> SR.Vanilla, compile_exp_vanilla env ae e ^^ UnboxedSmallWord.clz_kernel Type.Word8 + | OtherPrim "clz16", [e] -> SR.Vanilla, compile_exp_vanilla env ae e ^^ UnboxedSmallWord.clz_kernel Type.Word16 + | OtherPrim "clz64", [e] -> SR.UnboxedWord64, compile_exp_as env ae SR.UnboxedWord64 e ^^ G.i (Unary (Wasm.Values.I64 I64Op.Clz)) + | OtherPrim "ctz", [e] -> SR.UnboxedWord32, compile_exp_as env ae SR.UnboxedWord32 e ^^ G.i (Unary (Wasm.Values.I32 I32Op.Ctz)) + | OtherPrim "ctz8", [e] -> SR.Vanilla, compile_exp_vanilla env ae e ^^ UnboxedSmallWord.ctz_kernel Type.Word8 + | OtherPrim "ctz16", [e] -> SR.Vanilla, compile_exp_vanilla env ae e ^^ UnboxedSmallWord.ctz_kernel Type.Word16 + | OtherPrim "ctz64", [e] -> SR.UnboxedWord64, compile_exp_as env ae SR.UnboxedWord64 e ^^ G.i (Unary (Wasm.Values.I64 I64Op.Ctz)) + + | OtherPrim "Char->Text", [e] -> + SR.Vanilla, + compile_exp_vanilla env ae e ^^ + Text.prim_showChar env + + | OtherPrim "print", [e] -> + SR.unit, + compile_exp_vanilla env ae e ^^ + Dfinity.prim_print env + | OtherPrim "decodeUTF8", [e] -> + SR.UnboxedTuple 2, + compile_exp_vanilla env ae e ^^ + Text.prim_decodeUTF8 env + + (* Other prims, binary*) + | OtherPrim "Array.init", [_;_] -> + const_sr SR.Vanilla (Arr.init env) + | OtherPrim "Array.tabulate", [_;_] -> + const_sr SR.Vanilla (Arr.tabulate env) + | OtherPrim "btst8", [_;_] -> + const_sr SR.Vanilla (UnboxedSmallWord.btst_kernel env Type.Word8) + | OtherPrim "btst16", [_;_] -> + const_sr SR.Vanilla (UnboxedSmallWord.btst_kernel env Type.Word16) + | OtherPrim "btst", [_;_] -> + const_sr SR.UnboxedWord32 (UnboxedSmallWord.btst_kernel env Type.Word32) + | OtherPrim "btst64", [_;_] -> + const_sr SR.UnboxedWord64 ( + let (set_b, get_b) = new_local64 env "b" in + set_b ^^ compile_const_64 1L ^^ get_b ^^ G.i (Binary (Wasm.Values.I64 I64Op.Shl)) ^^ + G.i (Binary (Wasm.Values.I64 I64Op.And)) + ) + | _ -> SR.Unreachable, todo_trap env "compile_exp" (Arrange_ir.exp exp) end | VarE var -> Var.get_val env ae var @@ -5475,24 +5501,6 @@ and compile_exp (env : E.t) ae exp = SR.unit, compile_exp_as env ae SR.bool e1 ^^ G.if_ (ValBlockType None) G.nop (G.i Unreachable) - | UnE (_, Operator.PosOp, e1) -> compile_exp env ae e1 - | UnE (t, op, e1) -> - let sr_in, sr_out, code = compile_unop env t op in - sr_out, - compile_exp_as env ae sr_in e1 ^^ - code - | BinE (t, e1, op, e2) -> - let sr_in, sr_out, code = compile_binop env t op in - sr_out, - compile_exp_as env ae sr_in e1 ^^ - compile_exp_as env ae sr_in e2 ^^ - code - | RelE (t, e1, op, e2) -> - let sr, code = compile_relop env t op in - SR.bool, - compile_exp_as env ae sr e1 ^^ - compile_exp_as env ae sr e2 ^^ - code | IfE (scrut, e1, e2) -> let code_scrut = compile_exp_as env ae SR.bool scrut in let sr1, code1 = compile_exp env ae e1 in diff --git a/src/ir_def/arrange_ir.ml b/src/ir_def/arrange_ir.ml index 49e9b52a743..41da72302d7 100644 --- a/src/ir_def/arrange_ir.ml +++ b/src/ir_def/arrange_ir.ml @@ -14,10 +14,7 @@ let kind k = Atom (Type.string_of_kind k) let rec exp e = match e.it with | VarE i -> "VarE" $$ [id i] | LitE l -> "LitE" $$ [lit l] - | UnE (t, uo, e) -> "UnE" $$ [typ t; Arrange_ops.unop uo; exp e] - | BinE (t, e1, bo, e2)-> "BinE" $$ [typ t; exp e1; Arrange_ops.binop bo; exp e2] - | RelE (t, e1, ro, e2)-> "RelE" $$ [typ t; exp e1; Arrange_ops.relop ro; exp e2] - | ShowE (t, e) -> "ShowE" $$ [typ t; exp e] + | PrimE (p, es) -> "PrimE" $$ [prim p] @ List.map exp es | TupE es -> "TupE" $$ List.map exp es | ProjE (e, i) -> "ProjE" $$ [exp e; Atom (string_of_int i)] | DotE (e, n) -> "DotE" $$ [exp e; Atom n] @@ -38,7 +35,6 @@ let rec exp e = match e.it with | AssertE e -> "AssertE" $$ [exp e] | OptE e -> "OptE" $$ [exp e] | TagE (i, e) -> "TagE" $$ [id i; exp e] - | PrimE p -> "PrimE" $$ [Atom p] | DeclareE (i, t, e1) -> "DeclareE" $$ [id i; exp e1] | DefineE (i, m, e1) -> "DefineE" $$ [id i; mut m; exp e1] | FuncE (x, cc, tp, as_, ts, e) -> @@ -54,6 +50,15 @@ and args = function and arg a = Atom a.it +and prim = function + | UnPrim (t, uo) -> "UnPrim" $$ [typ t; Arrange_ops.unop uo] + | BinPrim (t, bo) -> "BinPrim" $$ [typ t; Arrange_ops.binop bo] + | RelPrim (t, ro) -> "RelPrim" $$ [typ t; Arrange_ops.relop ro] + | ShowPrim t -> "ShowPrim" $$ [typ t] + | SerializePrim t -> "SerializePrim" $$ [typ t] + | DeserializePrim t -> "DeserializePrim" $$ [typ t] + | OtherPrim s -> Atom s + and mut = function | Const -> Atom "Const" | Var -> Atom "Var" diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 35c745847ae..8fd605064d3 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -196,11 +196,8 @@ let rec check_typ env typ : unit = check env no_region env.flavor.Ir.serialized "Serialized in non-serialized flavor"; check_typ env typ; - (* TODO: we cannot currently express abstract shared types, - so @serialize is a hack *) - (*check env no_region (T.shared typ) - * "serialized type is not sharable:\n %s" (T.string_of_typ_expand typ) - *) + check env no_region (T.shared typ) + "serialized type is not sharable:\n %s" (T.string_of_typ_expand typ) | T.Typ c -> check_con env c @@ -285,12 +282,10 @@ let type_lit env lit at : T.prim = let isAsyncE exp = match exp.it with - | AsyncE _ -> (* pre await transformation *) - true - | CallE(_,{it=PrimE("@async");_}, _, cps) -> (* post await transformation *) - true - | _ -> - false + | AsyncE _ (* pre await transformation *) + | PrimE(OtherPrim "@async", [_]) (* post await transformation *) + -> true + | _ -> false let rec check_exp env (exp:Ir.exp) : unit = (* helpers *) @@ -305,7 +300,6 @@ let rec check_exp env (exp:Ir.exp) : unit = "inferred effect not a subtype of expected effect"; (* check typing *) match exp.it with - | PrimE _ -> () | VarE id -> let t0 = try T.Env.find id env.vals with | Not_found -> error env exp.at "unbound variable %s" id @@ -313,31 +307,49 @@ let rec check_exp env (exp:Ir.exp) : unit = t0 <~ t | LitE lit -> T.Prim (type_lit env lit exp.at) <: t - | UnE (ot, op, exp1) -> - check (Operator.has_unop op ot) "unary operator is not defined for operand type"; - check_exp env exp1; - typ exp1 <: ot; - ot <: t - | BinE (ot, exp1, op, exp2) -> - check (Operator.has_binop op ot) "binary operator is not defined for operand type"; - check_exp env exp1; - check_exp env exp2; - typ exp1 <: ot; - typ exp2 <: ot; - ot <: t - | ShowE (ot, exp1) -> - check env.flavor.has_show "show expression in non-show flavor"; - check (Show.can_show ot) "show is not defined for operand type"; - check_exp env exp1; - typ exp1 <: ot; - T.Prim T.Text <: t - | RelE (ot, exp1, op, exp2) -> - check (Operator.has_relop op ot) "relational operator is not defined for operand type"; - check_exp env exp1; - check_exp env exp2; - typ exp1 <: ot; - typ exp2 <: ot; - T.bool <: t + | PrimE (p, es) -> + begin match p, es with + | UnPrim (ot, op), [exp1] -> + check (Operator.has_unop op ot) "unary operator is not defined for operand type"; + check_exp env exp1; + typ exp1 <: ot; + ot <: t + | BinPrim (ot, op), [exp1; exp2] -> + check (Operator.has_binop op ot) "binary operator is not defined for operand type"; + check_exp env exp1; + check_exp env exp2; + typ exp1 <: ot; + typ exp2 <: ot; + ot <: t + | RelPrim (ot, op), [exp1; exp2] -> + check (Operator.has_relop op ot) "relational operator is not defined for operand type"; + check_exp env exp1; + check_exp env exp2; + typ exp1 <: ot; + typ exp2 <: ot; + T.bool <: t + | ShowPrim ot, [exp1] -> + check env.flavor.has_show "show expression in non-show flavor"; + check (Show.can_show ot) "show is not defined for operand type"; + check_exp env exp1; + typ exp1 <: ot; + T.Prim T.Text <: t + | SerializePrim ot, [exp1] -> + check env.flavor.serialized "Serialized expression in wrong flavor"; + check (T.shared ot) "argument to SerializePrim not shared"; + check_exp env exp1; + typ exp1 <: ot; + T.Serialized ot <: t + | DeserializePrim ot, [exp1] -> + check env.flavor.serialized "Serialized expression in wrong flavor"; + check (T.shared ot) "argument to SerializePrim not shared"; + check_exp env exp1; + typ exp1 <: T.Serialized ot; + ot <: t + | OtherPrim _, _ -> () + | _ -> + error env exp.at "PrimE with wrong number of arguments" + end | TupE exps -> List.iter (check_exp env) exps; T.Tup (List.map typ exps) <: t diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index f2867a2bb76..b81e3a9dae5 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -82,12 +82,33 @@ let as_seqP p = (* Primitives *) -let primE name typ = - { it = PrimE name; +let primE prim es = + let ty = match prim with + | DeserializePrim t -> t + | SerializePrim t -> T.Serialized t + | ShowPrim _ -> T.text + | _ -> assert false (* implement more as needed *) + in + let effs = List.map eff es in + let e = List.fold_left max_eff T.Triv effs in + { it = PrimE (prim, es); at = no_region; - note = { note_typ = typ; note_eff = T.Triv } + note = { note_typ = ty; note_eff = e } + } + +let asyncE typ e = + { it = PrimE (OtherPrim "@async", [e]); + at = no_region; + note = { note_typ = T.Async typ; note_eff = eff e } + } + +let awaitE typ e1 e2 = + { it = PrimE (OtherPrim "@await", [e1; e2]); + at = no_region; + note = { note_typ = T.unit; note_eff = max_eff (eff e1) (eff e2) } } + (* tuples *) let projE e n = @@ -438,16 +459,6 @@ let ( -*- ) exp1 exp2 = (Wasm.Sexpr.to_string 80 (Arrange_ir.exp exp2))) -(* Intermediate, cps-based @async and @await primitives, - introduced by await(opt).ml, removed by async.ml -*) - -let prim_async typ = - primE "@async" (T.Func (T.Local, T.Returns, [], [cpsT typ], [T.Async typ])) - -let prim_await typ = - primE "@await" (T.Func (T.Local, T.Returns, [], [T.Async typ; contT typ], [])) - (* derived loop forms; each can be expressed as an unconditional loop *) let whileE exp1 exp2 = diff --git a/src/ir_def/construct.mli b/src/ir_def/construct.mli index ff788c746da..13c4152fe66 100644 --- a/src/ir_def/construct.mli +++ b/src/ir_def/construct.mli @@ -39,7 +39,9 @@ val as_seqP : pat -> pat list (* Expressions *) -val primE : string -> typ -> exp +val primE : Ir.prim -> exp list -> exp +val asyncE : typ -> exp -> exp +val awaitE : typ -> exp -> exp -> exp val projE : exp -> int -> exp val blockE : dec list -> exp -> exp val textE : string -> exp @@ -99,12 +101,3 @@ val (-->) : var -> exp -> exp val (-->*) : var list -> exp -> exp (* n-ary local *) val (-@>*) : var list -> exp -> exp (* n-ary shared *) val (-*-) : exp -> exp -> exp (* application *) - - -(* intermediate, cps-based @async and @await primitives, - introduced by await(opt).ml to be removed by async.ml *) - -val prim_async : typ -> exp - -val prim_await : typ -> exp - diff --git a/src/ir_def/freevars.ml b/src/ir_def/freevars.ml index fd44e06b080..a99f6ffacfd 100644 --- a/src/ir_def/freevars.ml +++ b/src/ir_def/freevars.ml @@ -59,11 +59,7 @@ let close (f,d) = diff f d let rec exp e : f = match e.it with | VarE i -> M.singleton i {captured = false} | LitE l -> M.empty - | PrimE _ -> M.empty - | UnE (_, uo, e) -> exp e - | BinE (_, e1, bo, e2) -> exps [e1; e2] - | RelE (_, e1, ro, e2) -> exps [e1; e2] - | ShowE (_, e) -> exp e + | PrimE (_, es) -> exps es | TupE es -> exps es | ProjE (e, i) -> exp e | DotE (e, i) -> exp e diff --git a/src/ir_def/ir.ml b/src/ir_def/ir.ml index 05131e9e193..a4fe9a9a911 100644 --- a/src/ir_def/ir.ml +++ b/src/ir_def/ir.ml @@ -61,13 +61,9 @@ type arg = (string, Type.typ) Source.annotated_phrase type exp = exp' phrase and exp' = - | PrimE of string (* primitive *) + | PrimE of (prim * exp list) (* primitive *) | VarE of id (* variable *) | LitE of lit (* literal *) - | UnE of Type.typ * unop * exp (* unary operator *) - | BinE of Type.typ * exp * binop * exp (* binary operator *) - | RelE of Type.typ * exp * relop * exp (* relational operator *) - | ShowE of Type.typ * exp (* debug show *) | TupE of exp list (* tuple *) | ProjE of exp * int (* tuple projection *) | OptE of exp (* option injection *) @@ -102,6 +98,14 @@ and field' = {name : Type.lab; var : id} (* the var is by reference, not by valu and case = case' Source.phrase and case' = {pat : pat; exp : exp} +and prim = + | UnPrim of Type.typ * unop (* unary operator *) + | BinPrim of Type.typ * binop (* binary operator *) + | RelPrim of Type.typ * relop (* relational operator *) + | ShowPrim of Type.typ (* debug show *) + | SerializePrim of Type.typ (* serialize *) + | DeserializePrim of Type.typ (* deserialize *) + | OtherPrim of string (* Other primitive operation, no custom typing rule *) (* Declarations *) diff --git a/src/ir_def/ir_effect.ml b/src/ir_def/ir_effect.ml index 43289ba8101..981f76fa6c1 100644 --- a/src/ir_def/ir_effect.ml +++ b/src/ir_def/ir_effect.ml @@ -25,12 +25,9 @@ let effect_exp (exp: exp) : T.eff = eff exp (* infer the effect of an expression, assuming all sub-expressions are correctly effect-annotated es*) let rec infer_effect_exp (exp: exp) : T.eff = match exp.it with - | PrimE _ | VarE _ | LitE _ -> T.Triv - | UnE (_, _, exp1) - | ShowE (_, exp1) | ProjE (exp1, _) | OptE exp1 | TagE (_, exp1) @@ -42,14 +39,13 @@ let rec infer_effect_exp (exp: exp) : T.eff = | RetE exp1 | LoopE exp1 -> effect_exp exp1 - | BinE (_, exp1, _, exp2) | IdxE (exp1, exp2) - | RelE (_, exp1, _, exp2) | AssignE (exp1, exp2) | CallE (_, exp1, _, exp2) -> let t1 = effect_exp exp1 in let t2 = effect_exp exp2 in max_eff t1 t2 + | PrimE (_, exps) | TupE exps | ArrayE (_, _, exps) -> let es = List.map effect_exp exps in diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index 230d4715aa8..487899e4059 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -288,11 +288,6 @@ and interpret_exp_mut env exp (k : V.value V.cont) = last_env := env; Profiler.bump_region exp.at ; match exp.it with - | PrimE s -> - let at = exp.at in - let t = exp.note.note_typ in - let cc = call_conv_of_typ t in - k (V.Func (cc, extended_prim env s t at)) | VarE id -> (match Lib.Promise.value_opt (find id env.vals) with | Some v -> k v @@ -300,26 +295,43 @@ and interpret_exp_mut env exp (k : V.value V.cont) = ) | LitE lit -> k (interpret_lit env lit) - | UnE (ot, op, exp1) -> - interpret_exp env exp1 (fun v1 -> k (try Operator.unop op ot v1 with Invalid_argument s -> trap exp.at "%s" s)) - | ShowE (ot, exp1) -> - interpret_exp env exp1 (fun v -> - if Show.can_show ot - then k (Value.Text (Show.show_val ot v)) - else raise (Invalid_argument "debug_show")) - | BinE (ot, exp1, op, exp2) -> - interpret_exp env exp1 (fun v1 -> - interpret_exp env exp2 (fun v2 -> - k (try Operator.binop op ot v1 v2 with _ -> - trap exp.at "arithmetic overflow") + | PrimE (p, es) -> + begin match p, es with + | UnPrim (ot, op), [exp1] -> + interpret_exp env exp1 (fun v1 -> k (try Operator.unop op ot v1 with Invalid_argument s -> trap exp.at "%s" s)) + | BinPrim (ot, op), [exp1; exp2] -> + interpret_exp env exp1 (fun v1 -> + interpret_exp env exp2 (fun v2 -> + k (try Operator.binop op ot v1 v2 with _ -> + trap exp.at "arithmetic overflow") + ) ) - ) - | RelE (ot, exp1, op, exp2) -> - interpret_exp env exp1 (fun v1 -> - interpret_exp env exp2 (fun v2 -> - k (Operator.relop op ot v1 v2) + | RelPrim (ot, op), [exp1; exp2] -> + interpret_exp env exp1 (fun v1 -> + interpret_exp env exp2 (fun v2 -> + k (Operator.relop op ot v1 v2) + ) ) - ) + | ShowPrim ot, [exp1] -> + interpret_exp env exp1 (fun v -> + if Show.can_show ot + then k (Value.Text (Show.show_val ot v)) + else raise (Invalid_argument "debug_show")) + | SerializePrim t, [exp1] -> + interpret_exp env exp1 (fun v -> k (V.Serialized v)) + | DeserializePrim t, [exp1] -> + interpret_exp env exp1 (fun v -> k (V.as_serialized v)) + | OtherPrim s, exps -> + interpret_exps env exps [] (fun vs -> + let at = exp.at in + let t = exp.note.note_typ in + let arg = match vs with [v] -> v | _ -> V.Tup vs in + extended_prim env s t at arg k + ) + | _ -> + trap exp.at "Unknown prim or wrong number of arguments (%d given):\n %s" + (List.length es) (Wasm.Sexpr.to_string 80 (Arrange_ir.prim p)) + end | TupE exps -> interpret_exps env exps [] (fun vs -> k (V.Tup vs)) | OptE exp1 -> diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index d0072e39ef3..a2bdc82938d 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -193,11 +193,14 @@ module Transform() = struct Type.set_kind clone (t_kind (Con.kind c)); clone - and t_operator_type ot = - (* We recreate the reference here. That is ok, because it - we run after type inference. Once we move async past desugaring, - it will be a pure value anyways. *) - t_typ ot + and prim = function + | UnPrim (ot, op) -> UnPrim (t_typ ot, op) + | BinPrim (ot, op) -> BinPrim (t_typ ot, op) + | RelPrim (ot, op) -> RelPrim (t_typ ot, op) + | ShowPrim ot -> ShowPrim (t_typ ot) + | SerializePrim ot -> SerializePrim (t_typ ot) + | DeserializePrim ot -> DeserializePrim (t_typ ot) + | OtherPrim s -> OtherPrim s and t_field {lab; typ} = { lab; typ = t_typ typ } @@ -211,17 +214,8 @@ module Transform() = struct and t_exp' (exp:exp) = let exp' = exp.it in match exp' with - | PrimE _ - | LitE _ -> exp' + | LitE _ -> exp' | VarE id -> exp' - | UnE (ot, op, exp1) -> - UnE (t_operator_type ot, op, t_exp exp1) - | ShowE (ot, exp1) -> - ShowE (t_operator_type ot, t_exp exp1) - | BinE (ot, exp1, op, exp2) -> - BinE (t_operator_type ot, t_exp exp1, op, t_exp exp2) - | RelE (ot, exp1, op, exp2) -> - RelE (t_operator_type ot, t_exp exp1, op, t_exp exp2) | TupE exps -> TupE (List.map t_exp exps) | OptE exp1 -> @@ -240,13 +234,9 @@ module Transform() = struct ArrayE (mut, t_typ t, List.map t_exp exps) | IdxE (exp1, exp2) -> IdxE (t_exp exp1, t_exp exp2) - | CallE (cc,{it=PrimE "@await";_}, typs, exp2) -> - begin - match exp2.it with - | TupE [a;k] -> ((t_exp a) -*- (t_exp k)).it - | _ -> assert false - end - | CallE (cc,{it=PrimE "@async";_}, typs, exp2) -> + | PrimE (OtherPrim "@await", [a;k]) -> + ((t_exp a) -*- (t_exp k)).it + | PrimE (OtherPrim "@async", [exp2]) -> let t1, contT = match typ exp2 with | Func(_,_, [], @@ -286,6 +276,8 @@ module Transform() = struct ) nary_async) .it + | PrimE (p, exps) -> + PrimE (prim p, List.map t_exp exps) | CallE (cc, exp1, typs, exp2) -> CallE(cc, t_exp exp1, List.map t_typ typs, t_exp exp2) | BlockE b -> @@ -336,12 +328,8 @@ module Transform() = struct let y = fresh_var "y" res_typ in let exp' = match exp.it with - | CallE(_, async,_,cps) -> - begin - match async.it with - | PrimE("@async") -> ((t_exp cps) -*- (y --> (k -*- y))) - | _ -> assert false - end + | PrimE (OtherPrim "@async", [cps]) -> + (t_exp cps) -*- (y --> (k -*- y)) | _ -> assert false in FuncE (x, cc', typbinds', args', [], exp') diff --git a/src/ir_passes/await.ml b/src/ir_passes/await.ml index 33e3eb54f54..d3427e74b51 100644 --- a/src/ir_passes/await.ml +++ b/src/ir_passes/await.ml @@ -61,17 +61,10 @@ let rec t_exp context exp = { exp with it = t_exp' context exp.it } and t_exp' context exp' = match exp' with - | PrimE _ | VarE _ | LitE _ -> exp' - | UnE (ot, op, exp1) -> - UnE (ot, op, t_exp context exp1) - | BinE (ot, exp1, op, exp2) -> - BinE (ot, t_exp context exp1, op, t_exp context exp2) - | RelE (ot, exp1, op, exp2) -> - RelE (ot, t_exp context exp1, op, t_exp context exp2) - | ShowE (ot, exp1) -> - ShowE (ot, t_exp context exp1) + | PrimE (p, exps) -> + PrimE (p, List.map (t_exp context) exps) | TupE exps -> TupE (List.map (t_exp context) exps) | OptE exp1 -> @@ -127,8 +120,7 @@ and t_exp' context exp' = (* add the implicit return label *) let k_ret = fresh_cont (typ exp1) in let context' = LabelEnv.add id_ret (Cont (ContVar k_ret)) LabelEnv.empty in - (prim_async (typ exp1) -*- (k_ret --> (c_exp context' exp1 (ContVar k_ret)))) - .it + (asyncE (typ exp1) (k_ret --> (c_exp context' exp1 (ContVar k_ret)))).it | AwaitE _ -> assert false (* an await never has effect T.Triv *) | AssertE exp1 -> AssertE (t_exp context exp1) @@ -235,19 +227,12 @@ and c_exp' context exp k = match exp.it with | _ when is_triv exp -> k -@- (t_exp context exp) - | PrimE _ | VarE _ | LitE _ | FuncE _ -> assert false - | UnE (ot, op, exp1) -> - unary context k (fun v1 -> e (UnE (ot, op, v1))) exp1 - | BinE (ot, exp1, op, exp2) -> - binary context k (fun v1 v2 -> e (BinE (ot, v1, op, v2))) exp1 exp2 - | RelE (ot, exp1, op, exp2) -> - binary context k (fun v1 v2 -> e (RelE (ot, v1, op, v2))) exp1 exp2 - | ShowE (ot, exp1) -> - unary context k (fun v1 -> e (ShowE (ot, v1))) exp1 + | PrimE (p, exps) -> + nary context k (fun vs -> e (PrimE (p, vs))) exps | TupE exps -> nary context k (fun vs -> e (TupE vs)) exps | OptE exp1 -> @@ -321,16 +306,16 @@ and c_exp' context exp k = (* add the implicit return label *) let k_ret = fresh_cont (typ exp1) in let context' = LabelEnv.add id_ret (Cont (ContVar k_ret)) LabelEnv.empty in - k -@- (prim_async (typ exp1) -*- (k_ret --> (c_exp context' exp1 (ContVar k_ret)))) + k -@- (asyncE (typ exp1) (k_ret --> (c_exp context' exp1 (ContVar k_ret)))) | AwaitE exp1 -> letcont k (fun k -> match eff exp1 with | T.Triv -> - prim_await (typ exp) -*- (tupE [t_exp context exp1;k]) + awaitE (typ exp) (t_exp context exp1) k | T.Await -> c_exp context exp1 - (meta (typ exp1) (fun v1 -> (prim_await (typ exp) -*- (tupE [v1;k])))) + (meta (typ exp1) (fun v1 -> (awaitE (typ exp) v1 k))) ) | AssertE exp1 -> unary context k (fun v1 -> e (AssertE v1)) exp1 diff --git a/src/ir_passes/rename.ml b/src/ir_passes/rename.ml index ed77b58f224..7e0f41192f1 100644 --- a/src/ir_passes/rename.ml +++ b/src/ir_passes/rename.ml @@ -33,11 +33,7 @@ let rec exp rho e = and exp' rho e = match e with | VarE i -> VarE (id rho i) | LitE l -> e - | PrimE _ -> e - | UnE (ot, uo, e) -> UnE (ot, uo, exp rho e) - | BinE (ot, e1, bo, e2)-> BinE (ot, exp rho e1, bo, exp rho e2) - | RelE (ot, e1, ro, e2)-> RelE (ot, exp rho e1, ro, exp rho e2) - | ShowE (ot, e) -> ShowE (ot, exp rho e) + | PrimE (p, es) -> PrimE (p, List.map (exp rho) es) | TupE es -> TupE (List.map (exp rho) es) | ProjE (e, i) -> ProjE (exp rho e, i) | ActorE (i, ds, fs, t)-> let i',rho' = id_bind rho i in diff --git a/src/ir_passes/serialization.ml b/src/ir_passes/serialization.ml index 52811aa5b2d..6846e4a3e5a 100644 --- a/src/ir_passes/serialization.ml +++ b/src/ir_passes/serialization.ml @@ -31,23 +31,12 @@ module Transform() = struct let con_renaming = ref ConRenaming.empty (* The primitive serialization functions *) - let deserialize_prim = - let open Type in - let var : var = "A" in - primE "@deserialize" - (Func (Local, Returns, [{var; bound = Any}], [Serialized (Var (var, 0))], [(Var (var, 0))])) - let serialize_prim = - let open Type in - let var : var = "A" in - primE "@serialize" - (Func (Local, Returns, [{var; bound = Any}], [Var (var, 0)], [Serialized (Var (var, 0))])) - let deserialize e = let t = T.as_serialized e.note.note_typ in - callE deserialize_prim [t] e + primE (DeserializePrim t) [e] let serialize e t = - callE serialize_prim [t] e + primE (SerializePrim t) [e] let serialized_arg a = { it = a.it ^ "/raw"; note = T.Serialized a.note; at = a.at } @@ -155,17 +144,10 @@ module Transform() = struct (t_exp exp) in FuncE (x, cc, [], raw_args, [], body') end - | PrimE _ | LitE _ -> exp' | VarE id -> exp' - | UnE (ot, op, exp1) -> - UnE (t_typ ot, op, t_exp exp1) - | BinE (ot, exp1, op, exp2) -> - BinE (t_typ ot, t_exp exp1, op, t_exp exp2) - | RelE (ot, exp1, op, exp2) -> - RelE (t_typ ot, t_exp exp1, op, t_exp exp2) - | ShowE (ot, exp1) -> - ShowE (t_typ ot, t_exp exp1) + | PrimE (p, exps) -> + PrimE (p, List.map t_exp exps) | TupE exps -> TupE (List.map t_exp exps) | OptE exp1 -> diff --git a/src/ir_passes/show.ml b/src/ir_passes/show.ml index 6ce4b8efb53..3376239cf33 100644 --- a/src/ir_passes/show.ml +++ b/src/ir_passes/show.ml @@ -64,20 +64,14 @@ and t_exp env (e : Ir.exp) = { e with it = t_exp' env e.it } and t_exp' env = function - | PrimE p -> PrimE p | LitE l -> LitE l | VarE id -> VarE id - | ShowE (ot, exp1) -> + | PrimE (ShowPrim ot, [exp1]) -> let t' = T.normalize ot in add_type env t'; let f = idE (show_name_for t') (show_fun_typ_for t') in CallE (Call_conv.local_cc 1 1, f, [], t_exp env exp1) - | UnE (ot, op, exp1) -> - UnE (ot, op, t_exp env exp1) - | BinE (ot, exp1, op, exp2) -> - BinE (ot, t_exp env exp1, op, t_exp env exp2) - | RelE (ot, exp1, op, exp2) -> - RelE (ot, t_exp env exp1, op, t_exp env exp2) + | PrimE (p, es) -> PrimE (p, t_exps env es) | TupE exps -> TupE (t_exps env exps) | OptE exp1 -> OptE (t_exp env exp1) @@ -253,7 +247,7 @@ let list_build : 'a -> 'a -> 'a -> 'a list -> 'a list = fun pre sep post xs -> in [ pre ] @ go xs let catE : Ir.exp -> Ir.exp -> Ir.exp = fun e1 e2 -> - { it = BinE (T.Prim T.Text, e1, Operator.CatOp, e2) + { it = PrimE (BinPrim (T.text, Operator.CatOp), [e1; e2]) ; at = no_region ; note = { note_typ = T.Prim T.Text; note_eff = T.Triv } } diff --git a/src/ir_passes/tailcall.ml b/src/ir_passes/tailcall.ml index d775af681b4..e28953fbc77 100644 --- a/src/ir_passes/tailcall.ml +++ b/src/ir_passes/tailcall.ml @@ -92,13 +92,8 @@ and assignEs vars exp : dec list = List.mapi (fun i v -> expD (assignE v (projE v i))) vars and exp' env e : exp' = match e.it with - | VarE _ - | LitE _ - | PrimE _ -> e.it - | UnE (ot, uo, e) -> UnE (ot, uo, exp env e) - | BinE (ot, e1, bo, e2)-> BinE (ot, exp env e1, bo, exp env e2) - | RelE (ot, e1, ro, e2)-> RelE (ot, exp env e1, ro, exp env e2) - | ShowE (ot, e) -> ShowE (ot, exp env e) + | VarE _ | LitE _ -> e.it + | PrimE (p, es) -> PrimE (p, List.map (exp env) es) | TupE es -> TupE (List.map (exp env) es) | ProjE (e, i) -> ProjE (exp env e, i) | DotE (e, sn) -> DotE (exp env e, sn) diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 9c9be101aa9..4c385454538 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -56,17 +56,16 @@ and exp e = | _ -> typed_phrase' exp' e and exp' at note = function - | S.PrimE p -> I.PrimE p | S.VarE i -> I.VarE i.it | S.LitE l -> I.LitE (lit !l) | S.UnE (ot, o, e) -> - I.UnE (!ot, o, exp e) + I.PrimE (I.UnPrim (!ot, o), [exp e]) | S.BinE (ot, e1, o, e2) -> - I.BinE (!ot, exp e1, o, exp e2) + I.PrimE (I.BinPrim (!ot, o), [exp e1; exp e2]) | S.RelE (ot, e1, o, e2) -> - I.RelE (!ot, exp e1, o, exp e2) + I.PrimE (I.RelPrim (!ot, o), [exp e1; exp e2]) | S.ShowE (ot, e) -> - I.ShowE (!ot, exp e) + I.PrimE (I.ShowPrim !ot, [exp e]) | S.TupE es -> I.TupE (exps es) | S.ProjE (e, i) -> I.ProjE (exp e, i) | S.OptE e -> I.OptE (exp e) @@ -96,6 +95,11 @@ and exp' at note = function let ty = T.open_ vars ty in let tys = if cc.Call_conv.n_res = 1 then [ty] else T.as_seq ty in I.FuncE (name, cc, tbs', args, tys, wrap (exp e)) + (* Primitive functions in the prelude have particular shapes *) + | S.CallE ({it=S.AnnotE ({it=S.PrimE p;_},_);_}, _, {it=S.TupE es;_}) -> + I.PrimE (I.OtherPrim p, exps es) + | S.CallE ({it=S.AnnotE ({it=S.PrimE p;_},_);_}, _, e) -> + I.PrimE (I.OtherPrim p, [exp e]) | S.CallE (e1, inst, e2) -> let t = e1.Source.note.S.note_typ in if T.is_non t @@ -126,6 +130,7 @@ and exp' at note = function | S.ImportE (f, fp) -> if !fp = "" then assert false; (* unresolved import *) I.VarE (id_of_full_path !fp).it + | S.PrimE s -> raise (Invalid_argument ("Unapplied prim " ^ s)) and mut m = match m.it with | S.Const -> Ir.Const diff --git a/test/fail/ok/use-before-define5.wasm.stderr.ok b/test/fail/ok/use-before-define5.wasm.stderr.ok index ae7d5dd979a..338435413bd 100644 --- a/test/fail/ok/use-before-define5.wasm.stderr.ok +++ b/test/fail/ok/use-before-define5.wasm.stderr.ok @@ -6,7 +6,7 @@ non-closed actor: (ActorE foo (shared 0 -> 0) () - (AssertE (RelE Nat (VarE x) EqOp (LitE (NatLit 1)))) + (AssertE (PrimE (RelPrim Nat EqOp) (VarE x) (LitE (NatLit 1)))) ) ) (foo foo) diff --git a/test/run-dfinity/ok/counter-class.wasm.stderr.ok b/test/run-dfinity/ok/counter-class.wasm.stderr.ok index 2677c7e0195..c2f74b31a4d 100644 --- a/test/run-dfinity/ok/counter-class.wasm.stderr.ok +++ b/test/run-dfinity/ok/counter-class.wasm.stderr.ok @@ -9,7 +9,10 @@ non-closed actor: (ActorE () (BlockE (LetD WildP (CallE (1 -> 0) (VarE showCounter) (VarE j))) - (AssignE (VarE j) (BinE Int (VarE j) SubOp (LitE (IntLit 1)))) + (AssignE + (VarE j) + (PrimE (BinPrim Int SubOp) (VarE j) (LitE (IntLit 1))) + ) ) ) ) @@ -24,10 +27,8 @@ non-closed actor: (ActorE (LetD (TupP (VarP $k/0)) (TupE - (CallE - (1 -> 1) - (PrimE @deserialize) - shared (serialized Int) -> () + (PrimE + (DeserializePrim shared (serialized Int) -> ()) (VarE $k/0/raw) ) ) @@ -49,7 +50,7 @@ non-closed actor: (ActorE (CallE (shared 1 -> 0) (VarE $k/0) - (CallE (1 -> 1) (PrimE @serialize) Int (VarE $y/0)) + (PrimE (SerializePrim Int) (VarE $y/0)) ) ) ) From 9cf33759d538f9c69feeaba78cc21e0c70373d99 Mon Sep 17 00:00:00 2001 From: Christoph Hegemann Date: Wed, 17 Jul 2019 18:11:53 +0200 Subject: [PATCH 0287/1176] Various LSP completion improvements (#575) * turns off debug hover output for now * extract module alias AND prefix for completions This means that List.fil| now finds both `List` as well as `fil` * returns completion templates with placeholders for type args * removes indirections in the completion code No need to go through a tuple, if we convert it into a record right after * formatting and more descriptive comments * Be more specific about the server capabilities This makes it so the emacs-lsp package knows how to talk to us --- src/languageServer/completion.ml | 102 ++++++++++++++++++++------ src/languageServer/completion_test.ml | 28 ++++--- src/languageServer/languageServer.ml | 20 +++-- src/lsp/lsp.atd | 21 +++++- 4 files changed, 130 insertions(+), 41 deletions(-) diff --git a/src/languageServer/completion.ml b/src/languageServer/completion.ml index 82da606c281..c5930c72a1d 100644 --- a/src/languageServer/completion.ml +++ b/src/languageServer/completion.ml @@ -14,11 +14,52 @@ let string_of_list f xs = |> String.concat "; " |> fun x -> "[ " ^ x ^ " ]" -let item_of_ide_decl = function +let template_of_ide_decl decl = + let supply = ref 0 in + let fresh () = supply := !supply + 1; string_of_int !supply in + match decl with | ValueDecl (lbl, ty) -> - (lbl, Some(Type.string_of_typ ty)) + (match ty with + | Type.Func(_, _, binds, ty_list1, ty_list2) -> + let ty_args = + binds + |> List.map (fun Type.{ var = var; bound = bound} -> + Printf.sprintf "${%s:%s}" (fresh ()) var) + |> String.concat ", " in + let args = + ty_list1 + |> List.map (fun _ -> Printf.sprintf "$%s" (fresh ())) + |> String.concat ", " in + let ty_args = if ty_args = "" then "" else "<" ^ ty_args ^ ">" in + Printf.sprintf "%s%s(%s)" lbl ty_args args + | _ -> lbl) | TypeDecl (lbl, ty) -> - (lbl, Some(Type.string_of_typ ty)) + lbl + +let lbl_of_ide_decl (d : ide_decl) : string = + match d with + | ValueDecl (lbl, _) -> lbl + | TypeDecl (lbl, _) -> lbl + +let item_of_ide_decl (d : ide_decl) : Lsp_t.completion_item = + let tmpl = template_of_ide_decl d in + match d with + | ValueDecl (lbl, ty) -> + Lsp_t.{ + completion_item_label = lbl; + completion_item_kind = 3; + completion_item_insertText = tmpl; + completion_item_insertTextFormat = 2; + completion_item_detail = Some(Type.string_of_typ ty); + } + | TypeDecl (lbl, ty) -> + Lsp_t.{ + completion_item_label = lbl; + completion_item_kind = 7; + completion_item_insertText = tmpl; + completion_item_insertTextFormat = 2; + completion_item_detail = Some(Type.string_of_typ ty); + } let string_of_ide_decl = function | ValueDecl (lbl, ty) -> @@ -108,26 +149,33 @@ let parse_module_header project_root current_file_path file = (* Given a source file and a cursor position in that file, figure out the prefix relevant to searching completions. For example, given: - List.| (where | is the cursor) return `List.` *) -let find_completion_prefix logger file line column = + List.fi| (where | is the cursor) return `Some ("List", "fi")` *) +let find_completion_prefix logger file line column: (string * string) option = (* The LSP sends 0 based line numbers *) let line = line + 1 in let lexbuf = Lexing.from_string file in let next () = Lexer.token Lexer.Normal lexbuf in + let pos_eq_cursor pos = + pos.Source.line = line && pos.Source.column = column in let pos_past_cursor pos = pos.Source.line > line || (pos.Source.line = line && pos.Source.column >= column) in let rec loop = function | _ when (pos_past_cursor (Lexer.region lexbuf).Source.right) -> None | Parser.ID ident -> - (match next () with + (match next () with | Parser.DOT -> - (match next () with - | Parser.EOF -> Some ident + (match next () with + | Parser.EOF -> Some (ident, "") + | Parser.ID prefix -> + let next_token_end = (Lexer.region lexbuf).Source.right in + if pos_eq_cursor next_token_end + then Some (ident, prefix) + else loop (Parser.ID prefix) | tkn -> let next_token_start = (Lexer.region lexbuf).Source.left in if pos_past_cursor next_token_start - then Some ident + then Some (ident, "") else loop tkn) | tkn -> loop tkn) | Parser.EOF -> None @@ -139,37 +187,43 @@ let find_completion_prefix logger file line column = let completions (* index *) logger project_root file_path file_contents line column = let index = make_index () in let imported = parse_module_header project_root file_path file_contents in + let module_alias_completion_item alias = + Lsp_t.{ + completion_item_label = alias; + completion_item_kind = 9; + completion_item_insertText = alias; + completion_item_insertTextFormat = 1; + completion_item_detail = None; + } in match find_completion_prefix logger file_contents line column with | None -> + (* If we don't have any prefix to work with, just suggest the + imported module aliases *) imported - |> List.map (fun (alias, _) -> alias, None) - | Some prefix -> + |> List.map (fun (alias, _) -> module_alias_completion_item alias) + | Some (alias, prefix) -> let module_path = imported - |> List.find_opt (fun (mn, _) -> String.equal mn prefix) in - let index_keys = - Index.bindings index - |> List.map fst - |> string_of_list Lib.Fun.id in + |> List.find_opt (fun (mn, _) -> String.equal mn alias) in match module_path with | Some mp -> (match Index.find_opt (snd mp) index with | Some decls -> - List.map item_of_ide_decl decls + decls + |> List.filter (fun d -> d |> lbl_of_ide_decl |> Lib.String.chop_prefix prefix |> Lib.Option.is_some) + |> List.map item_of_ide_decl | None -> - [ (("ERROR: Couldn't find module in index: " ^ index_keys), None) ]) + (* The matching import references a module we haven't loaded *) + []) | None -> - [ (("ERROR: Couldn't find module for prefix: " ^ prefix), None) ] + (* No module with the given prefix was found *) + [] let completion_handler logger project_root file_path file_contents position = let line = position.Lsp_t.position_line in let column = position.Lsp_t.position_character in - let completion_item (lbl, detail) = - Lsp_t.{ completion_item_label = lbl - ; completion_item_detail = detail } in `CompletionResponse - (List.map completion_item - (completions logger project_root file_path file_contents line column)) + (completions logger project_root file_path file_contents line column) let test_completion () = Printf.printf "%s\n" (string_of_index (make_index ())) diff --git a/src/languageServer/completion_test.ml b/src/languageServer/completion_test.ml index 8b404956abe..34edc38febd 100644 --- a/src/languageServer/completion_test.ml +++ b/src/languageServer/completion_test.ml @@ -18,9 +18,17 @@ let dummy_logger _ _ = () let prefix_test_case file expected = let (file, (line, column)) = extract_cursor file in - let prefix = + let show = function + | None -> "None" + | Some (m, p) -> "Some (" ^ m ^ ", " ^ p ^ ")" in + let actual = Completion.find_completion_prefix dummy_logger file line column in - Lib.Option.equal String.equal prefix expected + Lib.Option.equal (=) actual expected || + (Printf.printf + "\nExpected: %s\nActual: %s\n" + (show expected) + (show actual); + false) let import_relative_test_case root module_path import expected = let actual = @@ -55,25 +63,25 @@ let parse_module_header_test_case project_root current_file file expected = let%test "it finds a simple prefix" = - prefix_test_case "List.|" (Some "List") + prefix_test_case "List.|" (Some ("List", "")) let%test "it doesn't find non-qualified idents" = prefix_test_case "List.filter we|" None let%test "it picks the qualified closest to the cursor" = - prefix_test_case "Stack.some List.|" (Some "List") + prefix_test_case "Stack.some List.|" (Some ("List", "")) let%test "it handles immediately following single character tokens" = - prefix_test_case "List.|<" (Some "List") + prefix_test_case "List.|<" (Some ("List", "")) -let%test "TODO(Christoph): it doesn't handle qualifier + partial identifierf" = - prefix_test_case "Stack.so|" (None) +let%test "it handles qualifier + partial identifier" = + prefix_test_case "Stack.so|" (Some ("Stack", "so")) let%test "it handles multiline files" = prefix_test_case {|Stak. List.| -|} (Some "List") +|} (Some ("List", "")) let%test "it handles a full module" = prefix_test_case @@ -85,7 +93,7 @@ let%test "it handles a full module" = func doubleton(x: T): List.List = List.cons(x, List.cons(x, List.nil())); - }|} (Some "Test") + }|} (Some ("Test", "")) let%test "it doesn't fall through to the next valid prefix" = prefix_test_case @@ -98,7 +106,7 @@ func empty():Stack = List.nil(); func singleton(x : Int) : Stack = List.we| ListFns.singleton(x); -}|} None +}|} (Some ("List", "we")) let%test "it makes an import relative to the project root" = import_relative_test_case diff --git a/src/languageServer/languageServer.ml b/src/languageServer/languageServer.ml index fa70c695ad2..aad5437edbc 100644 --- a/src/languageServer/languageServer.ml +++ b/src/languageServer/languageServer.ml @@ -142,13 +142,23 @@ let start () = | (Some id, `Initialize params) -> client_capabilities := Some params.Lsp_t.initialize_params_capabilities; let completion_options = - Lsp_t.{ completion_options_resolveProvider = Some false; - completion_options_triggerCharacters = Some ["."] + Lsp_t.{ + completion_options_resolveProvider = Some false; + completion_options_triggerCharacters = Some ["."] } in + let text_document_sync_options = + Lsp_t.{ + text_document_sync_options_openClose = Some true; + text_document_sync_options_change = Some 1; + text_document_sync_options_willSave = Some false; + text_document_sync_options_willSaveWaitUntil = Some false; + text_document_sync_options_save = Some { + save_options_includeText = Some true + } } in let result = `Initialize (Lsp_t.{ initialize_result_capabilities = { - server_capabilities_textDocumentSync = 1; - server_capabilities_hoverProvider = Some true; + server_capabilities_textDocumentSync = text_document_sync_options; + server_capabilities_hoverProvider = Some false; server_capabilities_completionProvider = Some completion_options; } }) in @@ -158,7 +168,7 @@ let start () = | (Some id, `TextDocumentHover params) -> let position = params.Lsp_t.text_document_position_params_position in let textDocument = params.Lsp_t.text_document_position_params_textDocument in - let result = `TextDocumentHoverResponse (Lsp_t. { + let result = `TextDocumentHoverResponse (Some Lsp_t. { hover_result_contents = "hovered over: " ^ textDocument.text_document_identifier_uri ^ " " ^ string_of_int position.position_line ^ ", " ^ string_of_int position.position_character diff --git a/src/lsp/lsp.atd b/src/lsp/lsp.atd index e3fd3f4d9ab..4c46bf73e62 100644 --- a/src/lsp/lsp.atd +++ b/src/lsp/lsp.atd @@ -70,7 +70,7 @@ type response_message = { type response_result = [ Initialize of initialize_result - | TextDocumentHoverResponse of hover_result + | TextDocumentHoverResponse of hover_result nullable | CompletionResponse of completion_item list ] @@ -87,6 +87,9 @@ type hover_result = { type completion_item = { label : string; + kind : int; + insertText : string; + insertTextFormat : int; ?detail: string nullable; } @@ -245,6 +248,20 @@ type initialize_result = { } +type text_document_sync_options = { + ?openClose : bool nullable; + ?change : int nullable; + ?willSave : bool nullable; + ?willSaveWaitUntil : bool nullable; + ?save : save_options nullable; +} + + +type save_options = { + ?includeText: bool nullable; +} + + type completion_options = { ?resolveProvider : bool nullable; ?triggerCharacters : string list nullable; @@ -253,7 +270,7 @@ type completion_options = { (* FIXME: incomplete *) type server_capabilities = { - textDocumentSync : int; + textDocumentSync : text_document_sync_options; ?hoverProvider : bool nullable; ?completionProvider : completion_options nullable; } From 5370438d08891687b4e89f15a26327d0dcb7a3f5 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Wed, 17 Jul 2019 11:05:46 -0700 Subject: [PATCH 0288/1176] remove flag for skipping node --- test/quick.mk | 2 +- test/run.sh | 20 ++++++-------------- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/test/quick.mk b/test/quick.mk index 1217ed0bbdc..50ebab5d391 100644 --- a/test/quick.mk +++ b/test/quick.mk @@ -22,4 +22,4 @@ _out/%.done: %.sh $(wildcard ../../src/asc) ../run.sh | _out _out/%.done: %.wat $(wildcard ../../src/asc) ../run.sh | _out @+ (../run.sh $(RUNFLAGS) $< > $@.tmp && mv $@.tmp $@) || (cat $@.tmp; rm -f $@.tmp; false) _out/%.done: %.did $(wildcard ../../src/didc) ../run.sh | _out - @+ (../run.sh -n $(RUNFLAGS) $< > $@.tmp && mv $@.tmp $@) || (cat $@.tmp; rm -f $@.tmp; false) + @+ (../run.sh $(RUNFLAGS) $< > $@.tmp && mv $@.tmp $@) || (cat $@.tmp; rm -f $@.tmp; false) diff --git a/test/run.sh b/test/run.sh index 18e713e8214..76a5acaa764 100755 --- a/test/run.sh +++ b/test/run.sh @@ -8,7 +8,6 @@ # # -a: Update the files in ok/ # -d: Compile without -no-dfinity-api, uses dvm to run -# -n: Do not check JS binding via node.js # -s: Be silent in sunny-day execution # @@ -26,11 +25,10 @@ DIDC=${DIDC:-$(realpath $(dirname $0)/../src/didc)} export AS_LD WASM=${WASM:-wasm} DVM_WRAPPER=$(realpath $(dirname $0)/dvm.sh) -NODE=yes JSCLIENT=${JSCLIENT:-$(realpath $(dirname $0)/../../dev/experimental/js-dfinity-client)} ECHO=echo -while getopts "adns" o; do +while getopts "ads" o; do case "${o}" in a) ACCEPT=yes @@ -38,9 +36,6 @@ while getopts "adns" o; do d) DFINITY=yes ;; - n) - NODE=no - ;; s) ECHO=true ;; @@ -234,15 +229,12 @@ do $DIDC --js $base.did > $out/$base.js 2>&1 diff_files="$diff_files $base.js" - if [ $NODE = 'yes' ] + if [ -e $out/$base.js ] then - if [ -e $out/$base.js ] - then - $ECHO -n " [node]" - export NODE_PATH=$NODE_PATH:$JSCLIENT:$JSCLIENT/src - node $out/$base.js > $out/$base.err 2>&1 - diff_files="$diff_files $base.err" - fi + $ECHO -n " [node]" + export NODE_PATH=$NODE_PATH:$JSCLIENT:$JSCLIENT/src + node $out/$base.js > $out/$base.err 2>&1 + diff_files="$diff_files $base.err" fi fi fi From 1f1f91749d47f6b40366b0d87dd7653f57318e28 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 18 Jul 2019 00:25:48 +0200 Subject: [PATCH 0289/1176] Building.md: Recommend `--no-out-link` (#579) and do not advise to run `make install` inside `/nix/store` (sorry for that). --- Building.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Building.md b/Building.md index 644dc62ee14..0b4499fe2e2 100644 --- a/Building.md +++ b/Building.md @@ -10,7 +10,7 @@ $ nix-env -i -f . -A asc This is the command that should always pass on master is the following, which builds everything: ``` -$ nix-build +$ nix-build --no-out-link ``` To enter a shell with the necessary dependencies, you can use @@ -43,7 +43,8 @@ installing all required tools without nix is out of scope). the precise repository and version. You can use `nix` to fetch the correct source for you, and run the manual installation inside: ``` - cd $(nix-build -Q -A wasm.src)/interpreter + cp -R $(nix-build --no-out-link -Q -A wasm.src)/interpreter /tmp/interpreter + cd /tmp/interpreter make install ``` * Install various command line tools used by, in particuar, the test suite: From f9104849d857058729547feb114b4260817ea335 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 18 Jul 2019 11:07:30 +0200 Subject: [PATCH 0290/1176] Bump libtommath (#568) * Bump libtommath this fixes #537, and also provides more conventient (and better typed) conversion functions with `{u,}int{32,64}_t`. Futher clean-up based on these functions might be possible. * Stop doing horrible header hacks Today I learned about the existence of `stddef.h`, so no need to fake an `stdint.h` to get `size_t`. * test whether 70 ** 32 is misbehaving (this test exercises `mp_realloc`) * fix object offset computation to skewed block in `mp_realloc` * add assertion that block type matches --- default.nix | 4 +- rts/Makefile | 13 +++--- rts/includes/stdlib.h | 19 -------- rts/rts.c | 87 +++++++++++++++--------------------- test/run-dfinity/log-slow.as | 2 +- test/run/issue537.as | 6 +++ 6 files changed, 52 insertions(+), 79 deletions(-) delete mode 100644 rts/includes/stdlib.h create mode 100644 test/run/issue537.as diff --git a/default.nix b/default.nix index aab99f0ecdc..fae05cb5f97 100644 --- a/default.nix +++ b/default.nix @@ -62,8 +62,8 @@ let libtommath = nixpkgs.fetchFromGitHub { owner = "libtom"; repo = "libtommath"; - rev = "9e1a75cfdc4de614eaf4f88c52d8faf384e54dd0"; - sha256 = "0qwmzmp3a2rg47pnrsls99jpk5cjj92m75alh1kfhcg104qq6w3d"; + rev = "584405ff8e357290362671b5e7db6110a959cbaa"; + sha256 = "1vl606rm8ba7vjhr0rbdqvih5d4r5iqalqlj5mnz6j3bnsn83b2a"; }; llvmBuildInputs = [ diff --git a/rts/Makefile b/rts/Makefile index 706419c32aa..880962f1340 100644 --- a/rts/Makefile +++ b/rts/Makefile @@ -2,8 +2,10 @@ CLANG ?= clang-9 WASM_LD ?= wasm-ld-9 TOMMATHFILES=\ - mp_init mp_add mp_sub mp_mul mp_zero mp_cmp mp_init_set_int mp_set_long mp_set_int \ - mp_div mp_init_copy mp_get_int mp_get_long mp_set_long_long mp_get_long_long mp_neg mp_abs mp_2expt mp_expt_d_ex mp_set mp_sqr \ + mp_init mp_add mp_sub mp_mul mp_zero mp_cmp \ + mp_set_u32 mp_set_i32 mp_get_i32 mp_get_mag_u32 \ + mp_set_u64 mp_set_i64 mp_get_i64 mp_get_mag_u64 \ + mp_div mp_init_copy mp_neg mp_abs mp_2expt mp_expt_u32 mp_set mp_sqr \ s_mp_add mp_cmp_mag s_mp_sub mp_grow mp_clamp \ mp_init_size mp_exch mp_clear mp_copy mp_count_bits mp_mul_2d mp_rshd mp_mul_d mp_div_2d mp_mod_2d \ s_mp_balance_mul s_mp_toom_mul s_mp_toom_sqr s_mp_karatsuba_sqr s_mp_sqr_fast s_mp_sqr s_mp_karatsuba_mul s_mp_mul_digs_fast s_mp_mul_digs mp_init_multi mp_clear_multi mp_mul_2 mp_div_2 mp_div_3 mp_lshd mp_incr mp_decr mp_add_d mp_sub_d @@ -13,13 +15,14 @@ TOMMATH_O=$(patsubst %,_build/tommath_%.o,$(TOMMATHFILES)) TOMMATHSRC ?= $(PWD)/../../libtommath MP_FLAGS = \ + -DMP_32BIT \ -DMP_MALLOC=mp_malloc \ -DMP_REALLOC=mp_realloc \ -DMP_CALLOC=mp_calloc \ -DMP_FREE=mp_free \ -DMP_MEMSET=0 \ -DMP_FIXED_CUTOFFS \ - -DLTM_NO_FILE \ + -DMP_NO_FILE \ CLANG_FLAGS = \ --compile \ @@ -27,12 +30,10 @@ CLANG_FLAGS = \ --target=wasm32-unknown-unknown-wasm -fvisibility=hidden \ -fno-builtin -ffreestanding \ --optimize=3 \ - -Iincludes \ -fvisibility=hidden \ -HEADER_STUBS = $(wildcard includes/*.h) -_build/tommath_%.o: $(TOMMATHSRC)/bn_%.c $(HEADER_STUBS) | _build +_build/tommath_%.o: $(TOMMATHSRC)/bn_%.c | _build $(CLANG) $(CLANG_FLAGS) $(MP_FLAGS)$< --output $@ all: as-rts.wasm diff --git a/rts/includes/stdlib.h b/rts/includes/stdlib.h deleted file mode 100644 index e389864ac9a..00000000000 --- a/rts/includes/stdlib.h +++ /dev/null @@ -1,19 +0,0 @@ -/* -For some reason, clang comes with files like intstd.h, but not with stdlib.h. - -If we do not define this here, clang might pick up glibc's stdlib.h, which -tries to pull in files related to 32 bits, which are not always installed. And -installing 32 bit headers is also non-trivial. And using glibc's headers feels -wrong anyways when we don't actually use glibc. - -So for now we stub this out manually (inspired by musl's stdlib.h). - -At some point we might actually use a proper C library. Then this library will -provide the proper headers. -*/ - -#define _Addr int -#define _Int64 long long -#define NULL ((void*)0) -typedef unsigned _Addr size_t; - diff --git a/rts/rts.c b/rts/rts.c index 3408b08fdca..ca021b90d0d 100644 --- a/rts/rts.c +++ b/rts/rts.c @@ -4,7 +4,7 @@ #define from_rts __attribute__ ((import_module("env"))) extern #include -#include +#include #include export void as_memcpy(char *str1, const char *str2, size_t n) { @@ -189,7 +189,7 @@ pointer to a data array. _payload_ in the `mp_digit* dp` field of the struct. This way, things look all nice and dandy from libtommath’s point of view. - Our gargabe collector has special knowledge about the dp field of the struct + Our garbage collector has special knowledge about the dp field of the struct and understands that this pointer points inside the TAG_TEXT heap object. But we can still move them around in the GC without issues. @@ -212,10 +212,16 @@ export void* mp_calloc(size_t n, size_t size) { return payload; } +from_rts __attribute__ ((noreturn)) void bigint_trap(); + export void* mp_realloc(void *ptr, size_t old_size, size_t new_size) { - as_ptr r = (as_ptr)(((char *)ptr) - (2 * sizeof(void*) - 1)); + as_ptr r = (as_ptr)(((char *)ptr) - (2 * sizeof(void*) + 1)); + + if (FIELD(r, 0) != TAG_TEXT) bigint_trap(); // assert block type + if (new_size > FIELD(r, 1)) { void *newptr = mp_alloc(new_size); + if (old_size != FIELD(r, 1)) bigint_trap(); as_memcpy(newptr, ptr, old_size); return newptr; } else { @@ -232,9 +238,9 @@ export void mp_free(void *ptr, size_t size) { #define BIGINT_PAYLOAD(p) ((mp_int *)(&FIELD(p,1))) /* -Note on libtommmath error handling +Note on libtommath error handling -Most libtommmath operations return an int to signal error codes. +Most libtommath operations return an int to signal error codes. These are (see tommath.h): #define MP_OKAY 0 / * ok result * / @@ -249,7 +255,6 @@ we call a trap function provided by the Wasm part of the runtime. */ #define CHECK(e) ((e == 0)?0:bigint_trap()) -from_rts __attribute__ ((noreturn)) void bigint_trap(); as_ptr bigint_alloc() { as_ptr r = alloc_bytes (1*sizeof(void*) + sizeof(mp_int)); @@ -258,99 +263,81 @@ as_ptr bigint_alloc() { return r; } -export as_ptr bigint_of_word32(unsigned long b) { +export as_ptr bigint_of_word32(uint32_t b) { as_ptr r = bigint_alloc(); - CHECK(mp_set_long(BIGINT_PAYLOAD(r), b)); + mp_set_u32(BIGINT_PAYLOAD(r), b); return r; } -export as_ptr bigint_of_word32_signed(signed long b) { +export as_ptr bigint_of_word32_signed(int32_t b) { as_ptr r = bigint_alloc(); mp_int *n = BIGINT_PAYLOAD(r); - CHECK(mp_set_long(n, b)); - if (b < 0) { - mp_int sub; - CHECK(mp_init(&sub)); - CHECK(mp_2expt(&sub, 32)); - CHECK(mp_sub(n,&sub,n)); - } + mp_set_i32(n, b); return r; } -export unsigned long bigint_to_word32_wrap(as_ptr a) { +export uint32_t bigint_to_word32_wrap(as_ptr a) { mp_int *n = BIGINT_PAYLOAD(a); - if (mp_isneg(n)) - return - mp_get_long(n); - else - return mp_get_long(n); + return mp_get_u32(n); } -export unsigned long bigint_to_word32_trap(as_ptr a) { +export uint32_t bigint_to_word32_trap(as_ptr a) { mp_int *n = BIGINT_PAYLOAD(a); if (mp_isneg(n)) bigint_trap(); if (mp_count_bits(n) > 32) bigint_trap(); - return mp_get_long(n); + return mp_get_u32(n); } -export signed long bigint_to_word32_signed_trap(as_ptr a) { +export int32_t bigint_to_word32_signed_trap(as_ptr a) { mp_int *n = BIGINT_PAYLOAD(a); if (mp_count_bits(n) > 32) bigint_trap(); if (mp_isneg(n)) { - long x = - (signed long)(mp_get_long(n)); + int32_t x = - (int32_t)(mp_get_mag_u32(n)); if (x >= 0) bigint_trap(); return x; } else { - long x = (signed long)(mp_get_long(n)); + int32_t x = (int32_t)(mp_get_mag_u32(n)); if (x < 0) bigint_trap(); return x; } } -export unsigned long long bigint_to_word64_wrap(as_ptr a) { +export uint64_t bigint_to_word64_wrap(as_ptr a) { mp_int *n = BIGINT_PAYLOAD(a); - if (mp_isneg(n)) - return - mp_get_long_long(n); - else - return mp_get_long_long(n); + return mp_get_u64(n); } -export unsigned long long bigint_to_word64_trap(as_ptr a) { +export uint64_t bigint_to_word64_trap(as_ptr a) { mp_int *n = BIGINT_PAYLOAD(a); if (mp_isneg(n)) bigint_trap(); if (mp_count_bits(n) > 64) bigint_trap(); - return mp_get_long_long(n); + return mp_get_u64(n); } -export signed long long bigint_to_word64_signed_trap(as_ptr a) { +export int64_t bigint_to_word64_signed_trap(as_ptr a) { mp_int *n = BIGINT_PAYLOAD(a); if (mp_count_bits(n) > 64) bigint_trap(); if (mp_isneg(n)) { - long long x = - (signed long long)(mp_get_long_long(n)); + int64_t x = - (int64_t)(mp_get_mag_u64(n)); if (x >= 0) bigint_trap(); return x; } else { - long long x = (signed long long)(mp_get_long_long(n)); + int64_t x = (int64_t)(mp_get_mag_u64(n)); if (x < 0) bigint_trap(); return x; } } -export as_ptr bigint_of_word64(unsigned long long b) { +export as_ptr bigint_of_word64(uint64_t b) { as_ptr r = bigint_alloc(); - CHECK(mp_set_long_long(BIGINT_PAYLOAD(r), b)); + mp_set_u64(BIGINT_PAYLOAD(r), b); return r; } -export as_ptr bigint_of_word64_signed(signed long long b) { +export as_ptr bigint_of_word64_signed(int64_t b) { as_ptr r = bigint_alloc(); mp_int *n = BIGINT_PAYLOAD(r); - CHECK(mp_set_long_long(n, b)); - if (b < 0) { - mp_int sub; - CHECK(mp_init(&sub)); - CHECK(mp_2expt(&sub, 64)); - CHECK(mp_sub(n,&sub,n)); - } + mp_set_i64(n, b); return r; } @@ -389,11 +376,9 @@ export as_ptr bigint_mul(as_ptr a, as_ptr b) { } export as_ptr bigint_pow(as_ptr a, as_ptr b) { - unsigned long exp = bigint_to_word32_trap(b); + uint32_t exp = bigint_to_word32_trap(b); as_ptr r = bigint_alloc(); - // Replace with mp_expt_long once available, - // see https://github.com/libtom/libtommath/issues/243 - CHECK(mp_expt_d_ex(BIGINT_PAYLOAD(a), exp, BIGINT_PAYLOAD(r), 1)); + CHECK(mp_expt_u32(BIGINT_PAYLOAD(a), exp, BIGINT_PAYLOAD(r))); return r; } @@ -450,7 +435,7 @@ void leb128_encode_go(mp_int *tmp, unsigned char *buf) { // now the number should be positive if (mp_isneg(tmp)) bigint_trap(); while (true) { - buf[0] = (char)(mp_get_int(tmp)); // get low bits + buf[0] = (char)(mp_get_u32(tmp)); // get low bits CHECK(mp_div_2d(tmp, 7, tmp, NULL)); if (mp_iszero(tmp)) { // we are done. high bit should be cleared anyways diff --git a/test/run-dfinity/log-slow.as b/test/run-dfinity/log-slow.as index 7358e9fe804..d73e746e510 100644 --- a/test/run-dfinity/log-slow.as +++ b/test/run-dfinity/log-slow.as @@ -1,4 +1,4 @@ -// These are rather lon-running tests, not advisable for wasm-run! +// These are rather long-running tests, not advisable for wasm-run! // Nat* diff --git a/test/run/issue537.as b/test/run/issue537.as new file mode 100644 index 00000000000..98d2384fc2a --- /dev/null +++ b/test/run/issue537.as @@ -0,0 +1,6 @@ +assert (103 ** 127 == 103 ** 126 * 103); +assert (103 ** 127 == 4_269_013_592_117_498_034_997_558_046_282_487_265_942_699_651_905_311_118_970_875_553_034_372_996_827_816_387_179_106_080_355_447_043_951_181_894_133_123_089_357_842_167_573_729_019_136_353_548_950_162_081_781_983_668_816_912_015_868_244_846_819_280_408_580_537_502_130_350_367_377_730_109_374_605_635_541_888_269_735_349_418_143_631_507_287); + +assert (70 ** 31 == 1_577_753_820_348_458_066_150_427_430_000_000_000_000_000_000_000_000_000_000); +assert (70 ** 32 == 110442767424392064630529920100000000000000000000000000000000); +assert (70 ** 31 * 70 == 110442767424392064630529920100000000000000000000000000000000); From 9c7ffd6ffcbf1a432a76c14185032d796e07457c Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Thu, 18 Jul 2019 13:22:31 +0200 Subject: [PATCH 0291/1176] Simplify chat example in docs (#563) --- README.md | 56 +++++++++++++++++++++---------------------------------- 1 file changed, 21 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index e9193f3ceeb..cac77ff8c15 100644 --- a/README.md +++ b/README.md @@ -205,62 +205,48 @@ A simple language for writing Dfinity actors. ## Example ``` -type List = ?{head : T; var tail : List}; +import List "as:std/list"; type Post = shared Text -> (); actor class Server() = { - private var clients : List = null; - - private shared broadcast(message : Text) { - var next = clients; - loop { - switch next { - case null return; - case (?l) { - l.head.send(message); - next := l.tail; - }; - }; + private var clients : List = List.empty(); + + private func broadcast(msg : Text) { + for (client in List.iter(clients)) { + client.send(msg); }; }; - subscribe(client : Client) : async Post { - let cs = new {head = client; var tail = clients}; - clients := ?cs; - return broadcast; + public func subscribe(name : Text, client : Client) : async Post { + clients := List.cons(client, clients); + return shared func(msg) { broadcast(name # "> " # msg) }; }; }; -actor class Client() = this { - // TODO: these should be constructor params once we can compile them - private var name : Text = ""; - private var server : ?Server = null; - - go(n : Text, s : Server) { - name := n; - server := ?s; +actor class Client(name : Text, server : Server) = this { + public func go() { ignore(async { - let post = await s.subscribe(this); - post("hello from " # name); - post("goodbye from " # name); + let post = await s.subscribe(name, this); + post("hello"); + post("goodbye"); }); }; - send(msg : Text) { + public func send(msg : Text) { print(name # " received " # msg # "\n"); }; }; let server = Server(); -let bob = Client(); -let alice = Client(); -let charlie = Client(); -bob.go("bob", server); -alice.go("alice", server); -charlie.go("charlie", server); +let bob = Client("bob", server); +let alice = Client("bob", server); +let charlie = Client("charlie", server); +bob.go(); +alice.go(); +charlie.go(); ``` From edce2bc9199f9c70178d9fc4c7f5f292fc175df3 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 18 Jul 2019 21:47:24 +0200 Subject: [PATCH 0292/1176] More comments in mp_realloc (#582) --- rts/rts.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/rts/rts.c b/rts/rts.c index ca021b90d0d..0a77fd8b91a 100644 --- a/rts/rts.c +++ b/rts/rts.c @@ -185,7 +185,7 @@ pointer to a data array. * The data array is allocated with mp_calloc and mp_realloc. We provide these calls, allocate ActorScript arrays (using the TAG_TEXT tag for byte arrays, - not TAG_ARRAY for arrays of pointers) and store the pointer to the + not TAG_ARRAY for arrays of pointers) and store the pointer to the _payload_ in the `mp_digit* dp` field of the struct. This way, things look all nice and dandy from libtommath’s point of view. @@ -193,6 +193,11 @@ pointer to a data array. and understands that this pointer points inside the TAG_TEXT heap object. But we can still move them around in the GC without issues. + The length of the byte array is always equal to the allocation asked for by + libtommath (no shrinking via mp_realloc supported). + This means we can assert that it matches the old_size passed to mp_realloc as + an additional check. + We can also support shrinking via mp_realloc, but then we have to drop that check. */ void* mp_alloc(size_t l) { @@ -224,8 +229,14 @@ export void* mp_realloc(void *ptr, size_t old_size, size_t new_size) { if (old_size != FIELD(r, 1)) bigint_trap(); as_memcpy(newptr, ptr, old_size); return newptr; - } else { + } else if (new_size == FIELD(r, 1)) { + // No need to grow return ptr; + } else { + // libtommath only shrinks on explicit demand via mp_shrink + // and we do not use that function + // so this should not happen. + bigint_trap(); } } From d7b36c67df2bb6892b3f4be8c07a14bd746852e5 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 19 Jul 2019 10:27:31 +0200 Subject: [PATCH 0293/1176] IDL-AS mapping spec (#465) (result of many iterations on the PR, see there for discussion if curious) --- design/IDL-AS.md | 287 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 287 insertions(+) create mode 100644 design/IDL-AS.md diff --git a/design/IDL-AS.md b/design/IDL-AS.md new file mode 100644 index 00000000000..5737dac70fa --- /dev/null +++ b/design/IDL-AS.md @@ -0,0 +1,287 @@ +The IDL-ActorScript integration +=============================== + +## Goals + +This document specifies the integration of the IDL with the ActorScript +language, in particular: + + * How to translate between an ActorScript `actor` type and an IDL `service` + description in both ways (i.e. _exporting_ IDL from ActorScript, and _importing_ + IDL into ActorScript), and how to translate between the values of these types. + + * The supported work-flows, including a sketch of the involved tools. + +We try to achieve the following goals (but do not achieve them completely) + + * We can round-trip all ActorScript values of sharable type. More precisely: + + When exporting an ActorScript type `ta` into an IDL type `ti`, then + round-tripping a value `va : ta` through `ti` yields a value that is + indistinguishable from `va` at type `ta`. + + * ActorScript can receive all IDL types: The type export has an inverse, the + type import mapping, which is injective (up-to IDL type equivalence via + shorthands). + + * ActorScript can receive all IDL values when importing an IDL: + + When importing an IDL type `ti` into `ta`, then every IDL value `vi : ti` + will successfully translated to an ActorScript value of type `ta`. + +The following are not necessary true: + + * The type export mapping is not total: there are ActorScript types that cannot + be exported, such as mutable arrays. + + * The type export mapping is not injective: there may be different + ActorScript types that map to the same IDL type, e.g. `Char`, `Word32` and + `Nat32`. + + This implies that round-tripping an ActorScript type via the IDL can yield + different types. + + * For some types, not all IDL values may be accepted: for example, `Char` is + may be exported as `nat32`, but not all `nat32` values can be read as + `Char`. This can only be the case for types not in the image of the type + import mapping. + +NB: These properties (and non-properties) are not specific to ActorScript, and +we expect that they will hold similarly for interfaces to other typed languages +with seamless serialization (e.g. built-in, macro or type class based +integration). In this sense, this document serves as a blueprint. Untyped +languages or languages with a code-generation workflow may have a different +story. + +## The type mappings + +We define + * a partial function `e` from ActorScript types to IDL types. + Types that are not in the domain of `e` cannot be exported. + * a partial function `i` from IDL types to ActorScript types. + Types that are not in the domain of `i` cannot be imported. + +These definition treats ActorScript types and IDL types as structural and +infinite; a concrete implementation will have to look through type constructors +in ActorScript and introduce type definitions in the IDL as necessary. + +It assumes that the IDL short-hands (e.g. named or anonymous fields) +are part of the grammar of types, and that `i` is allowed to make difference +choices for types that are short-hands. + +The function is defined with regard to the grammars in [IDL.md](IDL.md) and [Syntax.md](Syntax.md). + +### Type export + +``` +e : -> +e(Null) = null +e(Bool) = bool +e(Nat) = nat +e(Int) = int +e(Nat) = nat for n = 8, 16, 32, 64 +e(Int) = int for n = 8, 16, 32, 64 +e(Word) = nat for n = 8, 16, 32, 64 +e(Float) = float64 +e(Char) = nat32 +e(Text) = text +e(shared { ;* }) = record { ef();* } +e(variant { ;* }) = variant { ef();* } +e([]) = vec (e()) +e(? ) = opt (e()) +e(shared -> ) = func (efn(shared -> )) +e(actor { ;* }) = service { em();* } +e( ( ,* ) ) = record { e();* } +e(Any) = reserved +e(None) = empty + +ef : -> +ef ( : ) = unescape() : e() + +efn : -> +efn(shared -> ()) = ea() -> () oneway +efn(shared -> async ) = ea() -> ea() + +ea : -> ,* +ea( ( ,* ) ) = e();* +ea() = ( e() ) otherwise + +em : -> +em( : ) = unescape() : efn() + +unescape : -> | +unescape("_" "_") = +unescape( "_") = +unescape() = +``` + +### Type import + +``` +i : -> +i(null) = Null +i(bool) = Bool +i(nat) = Nat +i(int) = Int +i(nat) = Nat for n = 8, 16, 32, 64 +i(int) = Int for n = 8, 16, 32, 64 +// i(float32) not defined +i(float64) = Float +i(text) = Text +i(reserved) = Any +i(opt ) = ? i() +i(vec ) = [ i() ] +i(blob) = [ word8 ] // if ActorScript had a bytes type, it would show up here +i(record { ;* }) = ( i(),* ) // matches tuple short-hand +i(record { ;* }) = shared { if();* } +i(variant { ;* }) = variant { if();* } +i(func ) = ifn() +i(service { ;* }) = actor { im();* } + +if : -> +if( : ) = escape() : i() +if( : ) = "_" "_": i() // also for implicit labels + +ifn : -> +ifn((,*) -> () oneway pure?) = shared ia() -> () +ifn((,*) -> (,*) pure?) = shared ia(,*) -> ia(,*) + +ia : ,* -> +ia(,) = i() +ia(,*) = ( i(),* ) otherwise + +im : -> +im( : ) = escape() : ifn() + +escape : -> +escape = "_" if is a reserved identifier in ActorScript +escape = "_" if ends with "_" +escape = if is a valid ActorScript not ending in "_" +escape = "_" hash() "_" otherwise +``` + +### Notes: + + * Up-to short-hands, `i` is injective and the right-inverse of `e`. + + Formally: For all IDL types `t ∈ dom i`, we have that `e(i(t))` is equivalent to + `t`, i.e. either they are the same types, or short-hands of each other. + + * Tuples are exported using the unnamed field short-hand, which is how tuples + are idiomatically expressed in the IDL: + ``` + e(()) = record {} + e((Int, )) = record {int} + e((Int, Nat)) = record {int;nat} + e(shared {i:Int, n:Nat)) = record {i:int; n:nat} + e(shared {_0_:Int, _1_:Nat)) = record {0:int; 1:nat} + ``` + + * The mapping `i` tries to detect types that can be expressed as tuples in + ActorScript. + ``` + i(record {int;nat}) = (Int, Nat) + i(record {int; nat; foo:text}) = shared {_0_:Int; _1_:Nat; foo:Text} + i(record {0:Int, 1:Nat)) = shared {_0_:int; _1_:nat} + ``` + + * The `escape` and `unescape` functions allow round-tripping of IDL field + names that are not valid ActorScript names (fake hash values): + ``` + i(record {int; if:text; foobar_:nat; "_0_":bool}) + = shared (_0_:Int; if_:Text; _1234_:Nat; _4321_:Bool) + ``` + This is another source of partiality for `e`: + ``` + e(shared {clash_ : Nat; clash : Int}) + ``` + is undefined, because `unescape(clash_) = unescape(clash)`. + + * ActorScript functions with type parameters are not in the domain of `e`. + + * Abstract ActorScript types are not in the domain of `e` + + * The translation produces IDL functions without parameter names. But both + the IDL and ActorScript conveniently support non-significant names in + parameter lists. These are essentially comments, and do not affect, for + example, the type section in a message, so it is not necessary to specify + them here. + + But tooling (e.g. `asc` exporting an IDL from an ActorScript type) is of + course free to use any annotations in the ActorScript type (or even names + from pattern in function definitions) also in the exported IDL. + + * The soundness of the ActorScript type system, when it comes to higher-order + use of actor and function references, relies on + ``` + ∀ t1 t2 : dom(e), t1 <: t2 ⟹ e(t1) <: e(t2) + ``` + In other words: ActorScript subtyping must be contained in IDL subtyping. + + * There is no way to produce `float32` or functions with a `pure` annotation. + Importing interfaces that contain these types fails. + +## The value mappings + +For each ActorScript type `t` in the domain of `e`, we need mapping from +ActorScript value of type `t` to an IDL value of type `e(t)`, and vice-versa. + +Note that decoding may only fail for those `t` that are not in the range of `i`. + +These mappings should be straight-forward, given the following clarifications: + +* Characters (of type `Char`) are mapped to their Unicode scalar as a `nat32`. + Decoding a `nat32` that is not a valid Unicode scalar fails. + +## Works flows + +The mapping specified here can be used to support the following use-cases. The +user interfaces (e.g. flag names, or whether `asc`, `idlc`, `dfx` is used) are +just suggestions. + +* Generating IDL from ActorScript + + If `foo.as` is an ActorScript `actor` compilation unit, then + + asc --generate-idl foo.as -o foo.didl + + will type-check `foo.as` as `t = actor { … }`, map the ActorScript type `t` + to an IDL type `e(t)` of the form `service `, and produce a + textual IDL file `foo.didl` that ends with a `service n : `, + where `n` is the name of the actor class, actor, or basename of the source + file. + +* Checking ActorScript against a given IDL + + If `foo.as` is an ActorScript `actor` compilation unit and `foo.didl` a + textual IDL file, then + + asc --check-idl foo.didl foo.as -o foo.wasm + + will import the type service `t_spec` specified in `foo.didl`, using the + mapping `i`, will generate an IDL type `e(t)` as in the previous point, and + and check that `e(t) <: t_spec` (using IDL subtyping). + +* Converting IDL types to ActorScript types + + If `foo.didl` a textual IDL file, then + + idlc foo.didl -o foo.as + + will create an ActorScript library unit `foo.as` that consists of type + definitions. + All ``s and the final `` from `foo.didl` is turned into a `type` + declaration in ActorScript, according to `i`. + Imported IDL files are recursively inlined. + + Variant: Imported IDL files are translated separately and included via + `import` in ActorScript. + +* Importing IDL types from the ActorScript compiler + + If `path/to/foo.didl` a textual IDL file, then a declaration + + import Foo "path/to/foo" + + is treated by `asc` by reading `foo.didl` as if the developer had + run `idlc path/to/foo.didl -o path/to/foo.as`. From e720625c0f44d2639fcdcc980094ca8f67f27c91 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 19 Jul 2019 18:19:18 +0200 Subject: [PATCH 0294/1176] gitSource.nix: Do not warn when source is in /nix/store (#585) * gitSource.nix: Do not warn when source is in /nix/store this quenches a warning when this repo is imported via `builtins.fetchGit`. * Update nix/gitSource.nix --- default.nix | 2 +- nix/gitSource.nix | 15 ++++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/default.nix b/default.nix index be33b0bc912..a6cbe1382d3 100644 --- a/default.nix +++ b/default.nix @@ -26,7 +26,7 @@ let ocaml_bisect_ppx-ocamlbuild = import ./nix/ocaml-bisect_ppx-ocamlbuild.nix n let dev = import (builtins.fetchGit { url = "ssh://git@github.com/dfinity-lab/dev"; ref = "master"; - rev = "fcd387ce757fcc1ee697a19665ada9bc3f453adc"; + rev = "49627900050b2db1b641cd402e832a165b8d47f5"; }) { system = nixpkgs.system; }; in # Include dvm diff --git a/nix/gitSource.nix b/nix/gitSource.nix index 7d3af5e5e3d..fea7f6cb544 100644 --- a/nix/gitSource.nix +++ b/nix/gitSource.nix @@ -85,10 +85,15 @@ then } else - trace "gitSource.nix: ${toString ../.} does not seem to be a git repository,\nassuming it is a clean checkout." ( - subdir: path { + let warn_unless = b: m: x: if b then x else trace m x; in + # No .git directory found, we should warn the user. + # But when this repository is imported using something like + # `builtins.fetchGit` then the source is extracted to /nix/store without a + # .git directory, but in this case we know that it is clean, so do not warn + warn_unless + (has_prefix "/nix/store" (toString ../.)) + "gitSource.nix: ${toString ../.} does not seem to be a git repository,\nassuming it is a clean checkout." + (subdir: path { name = baseNameOf (toString subdir); path = if isString subdir then (../. + "/${subdir}") else subdir; - } - ) - + }) From a19c33858c8b0b3d6d3b9d66c6f3ea1a2add6c31 Mon Sep 17 00:00:00 2001 From: Christoph Hegemann Date: Mon, 22 Jul 2019 11:30:02 +0200 Subject: [PATCH 0295/1176] [SDK-233] Display type information on hover (#584) * Display type information on hover * remove dead code * fix test --- src/languageServer/hover.ml | 75 ++++++++++++++++++++++++++++ src/languageServer/hover_tests.ml | 45 +++++++++++++++++ src/languageServer/languageServer.ml | 32 ++++++++---- src/lsp/lsp.atd | 7 ++- 4 files changed, 148 insertions(+), 11 deletions(-) create mode 100644 src/languageServer/hover.ml create mode 100644 src/languageServer/hover_tests.ml diff --git a/src/languageServer/hover.ml b/src/languageServer/hover.ml new file mode 100644 index 00000000000..750545681ee --- /dev/null +++ b/src/languageServer/hover.ml @@ -0,0 +1,75 @@ +open As_frontend +open As_types +module Lsp = Lsp.Lsp_t + +type hover_target = + | Ident of string + | Qualified of string * string + +let hovered_identifier + (position : Lsp.position) + (file_contents : string) + : hover_target option = + let line = position.Lsp.position_line + 1 in + let column = position.Lsp.position_character + 1 in + let lexbuf = Lexing.from_string file_contents in + let next () = Lexer.token Lexer.Normal lexbuf in + let pos_past_cursor pos = + pos.Source.line > line + || (pos.Source.line = line && pos.Source.column >= column) in + let rec loop = function + | _ when (pos_past_cursor (Lexer.region lexbuf).Source.left) -> None + | Parser.ID ident -> + (match next () with + | Parser.DOT -> + (match next () with + | Parser.ID prefix -> + let next_token_end = (Lexer.region lexbuf).Source.right in + if pos_past_cursor next_token_end + then Some (Qualified (ident, prefix)) + else loop (Parser.ID prefix) + | tkn -> + let next_token_start = (Lexer.region lexbuf).Source.left in + if pos_past_cursor next_token_start + then Some (Ident ident) + else loop tkn) + | _ when pos_past_cursor (Lexer.region lexbuf).Source.left -> + Some (Ident ident) + | tkn -> loop tkn) + | Parser.EOF -> None + | _ -> loop (next ()) in + loop (next ()) + +let hover_detail = function + | Completion.ValueDecl (lbl, ty) -> + lbl ^ " : " ^ Type.string_of_typ ty + | Completion.TypeDecl (lbl, ty) -> + lbl ^ Type.string_of_typ ty + +let hover_handler (* index *) position file_contents project_root file_path = + (* TODO(Christoph): Don't rebuild index on every hover *) + let index = Completion.make_index () in + let imported = + Completion.parse_module_header + project_root + file_path + file_contents in + let hover_result = + Lib.Option.bind (hovered_identifier position file_contents) (function + | Ident s -> + List.find_opt (fun (alias, _) -> alias = s) imported + |> Lib.Option.map (fun (_, path) -> + Lsp.{ hover_result_contents = path }) + | Qualified (qual, ident) -> + List.find_opt (fun (alias, _) -> alias = qual) imported + |> Lib.Fun.flip Lib.Option.bind (fun (_, path) -> + Completion.Index.find_opt path index) + |> Lib.Fun.flip Lib.Option.bind (fun decls -> + List.find_opt + (fun d -> Completion.lbl_of_ide_decl d = ident) + decls) + |> Lib.Option.map (fun ide_decl -> + Lsp.{ hover_result_contents = hover_detail ide_decl }) + ) in + let result = `TextDocumentHoverResponse hover_result in + result diff --git a/src/languageServer/hover_tests.ml b/src/languageServer/hover_tests.ml new file mode 100644 index 00000000000..fc7484c6b40 --- /dev/null +++ b/src/languageServer/hover_tests.ml @@ -0,0 +1,45 @@ +module Lsp = Lsp.Lsp_t +let extract_cursor input = + let cursor_pos = ref (0, 0) in + String.split_on_char '\n' input + |> List.mapi + (fun line_num line -> + match String.index_opt line '|' with + | Some column_num -> + cursor_pos := (line_num, column_num); + line + |> String.split_on_char '|' + |> String.concat "" + | None -> line + ) + |> String.concat "\n" + |> fun f -> (f, !cursor_pos) + +let hovered_identifier_test_case file expected = + let (file, (line, column)) = extract_cursor file in + let show = function + | Some(Hover.Ident i) -> i + | Some(Hover.Qualified (qualifier, ident)) -> qualifier ^ "." ^ ident + | None -> "None" in + let actual = + Hover.hovered_identifier + Lsp.{ position_line = line; position_character = column } file in + Lib.Option.equal (=) actual expected || + (Printf.printf + "\nExpected: %s\nActual: %s\n" + (show expected) + (show actual); + false) + +let%test "it finds an identifier" = + hovered_identifier_test_case + "f|ilter" + (Some (Hover.Ident "filter")) + +let%test "it ignores hovering over whitespace" = + hovered_identifier_test_case "filter |" None + +let%test "it finds a qualified identifier" = + hovered_identifier_test_case + "List.f|ilter" + (Some (Hover.Qualified ("List", "filter"))) diff --git a/src/languageServer/languageServer.ml b/src/languageServer/languageServer.ml index aad5437edbc..294891e9c69 100644 --- a/src/languageServer/languageServer.ml +++ b/src/languageServer/languageServer.ml @@ -158,7 +158,7 @@ let start () = let result = `Initialize (Lsp_t.{ initialize_result_capabilities = { server_capabilities_textDocumentSync = text_document_sync_options; - server_capabilities_hoverProvider = Some false; + server_capabilities_hoverProvider = Some true; server_capabilities_completionProvider = Some completion_options; } }) in @@ -166,15 +166,27 @@ let start () = send_response (Lsp_j.string_of_response_message response); | (Some id, `TextDocumentHover params) -> - let position = params.Lsp_t.text_document_position_params_position in - let textDocument = params.Lsp_t.text_document_position_params_textDocument in - let result = `TextDocumentHoverResponse (Some Lsp_t. { - hover_result_contents = "hovered over: " ^ textDocument.text_document_identifier_uri - ^ " " ^ string_of_int position.position_line - ^ ", " ^ string_of_int position.position_character - }) in - let response = response_result_message id result in - send_response (Lsp_j.string_of_response_message response); + let uri = + params + .Lsp_t.text_document_position_params_textDocument + .Lsp_t.text_document_identifier_uri in + let position = + params.Lsp_t.text_document_position_params_position in + let response = match Vfs.read_file uri !vfs with + | None -> + response_error_message + id + Lsp_t.{ code = 1 + ; message = "Tried to find hover a file that hadn't been opened yet"} + | Some file_content -> + let result = + Hover.hover_handler + position + file_content + project_root + (abs_file_from_uri log_to_file uri) in + response_result_message id result in + send_response (Lsp_j.string_of_response_message response); | (_, `TextDocumentDidOpen params) -> vfs := Vfs.open_file params !vfs | (_, `TextDocumentDidChange params) -> diff --git a/src/lsp/lsp.atd b/src/lsp/lsp.atd index 4c46bf73e62..7ceffe54d92 100644 --- a/src/lsp/lsp.atd +++ b/src/lsp/lsp.atd @@ -48,7 +48,7 @@ type incoming_message_params = [ | TextDocumentHover of text_document_position_params (* NOTE(Christoph) There are more parameters than just text_document_position on the completion request *) | CompletionRequest of text_document_position_params - | CancelRequest of unit + | CancelRequest of cancel_request_params ] (* @@ -118,6 +118,11 @@ type initialize_params = { } +type cancel_request_params = { + id : int +} + + type text_document_did_open_params = { textDocument : text_document_item; } From a0dda18d1461ce16ba93557da11744e10c2fbb12 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Mon, 22 Jul 2019 13:33:50 +0200 Subject: [PATCH 0296/1176] Make sure not to run coverage checker when patterns are malformed (#587) --- src/as_frontend/typing.ml | 55 ++++++++++++------------ src/as_values/value.ml | 10 ++--- src/as_values/value.mli | 4 +- test/fail/ok/one-tuple-ambiguity.tc.ok | 2 - test/fail/ok/pat-inconsistent.tc.ok | 6 +++ test/fail/ok/pat-subtyping-fail.tc.ok | 2 + test/fail/pat-inconsistent.as | 14 ++++++ test/fail/pat-subtyping-fail.as | 6 +++ test/run/ok/pat-subtyping.run-ir.ok | 8 ++++ test/run/ok/pat-subtyping.run-low.ok | 8 ++++ test/run/ok/pat-subtyping.run.ok | 8 ++++ test/run/ok/pat-subtyping.tc.ok | 8 ++++ test/run/ok/pat-subtyping.wasm.stderr.ok | 9 ++++ test/run/pat-subtyping.as | 10 +++++ 14 files changed, 111 insertions(+), 39 deletions(-) diff --git a/src/as_frontend/typing.ml b/src/as_frontend/typing.ml index 709e55ea22e..8ce72cf465a 100644 --- a/src/as_frontend/typing.ml +++ b/src/as_frontend/typing.ml @@ -9,15 +9,6 @@ module T = Type module A = Effect -(* Error recovery *) - -exception Recover - -let recover_with (x : 'a) (f : 'b -> 'a) (y : 'b) = try f y with Recover -> x -let recover_opt f y = recover_with None (fun y -> Some (f y)) y -let recover f y = recover_with () f y - - (* Contexts *) type lab_env = T.typ T.Env.t @@ -52,18 +43,24 @@ let env_of_scope msgs scope = (* Error bookkeeping *) +exception Recover + +let recover_with (x : 'a) (f : 'b -> 'a) (y : 'b) = try f y with Recover -> x +let recover_opt f y = recover_with None (fun y -> Some (f y)) y +let recover f y = recover_with () f y + let type_error at text : Diag.message = Diag.{sev = Diag.Error; at; cat = "type"; text} let type_warning at text : Diag.message = Diag.{sev = Diag.Warning; at; cat = "type"; text} -let local_error env at fmt = - Printf.ksprintf (fun s -> Diag.add_msg env.msgs (type_error at s)) fmt - let error env at fmt = Printf.ksprintf (fun s -> Diag.add_msg env.msgs (type_error at s); raise Recover) fmt +let local_error env at fmt = + Printf.ksprintf (fun s -> Diag.add_msg env.msgs (type_error at s)) fmt + let warn env at fmt = Printf.ksprintf (fun s -> Diag.add_msg env.msgs (type_warning at s)) fmt @@ -366,7 +363,7 @@ let infer_lit env lit at : T.prim = assert false let check_lit env t lit at = - match T.normalize t, !lit with + match t, !lit with | T.Prim T.Nat, PreLit (s, T.Nat) -> lit := NatLit (check_nat env at s) | T.Prim T.Nat8, PreLit (s, T.Nat) -> @@ -400,7 +397,7 @@ let check_lit env t lit at = | t, _ -> let t' = T.Prim (infer_lit env lit at) in if not (T.sub t' t) then - local_error env at + error env at "literal of type\n %s\ndoes not have expected type\n %s" (T.string_of_typ t') (T.string_of_typ_expand t) @@ -858,15 +855,14 @@ and check_exp' env t exp : T.typ = | SwitchE (exp1, cases), _ -> let t1 = infer_exp_promote env exp1 in check_cases env t1 t cases; - if not env.pre then begin - match Coverage.check_cases cases t1 with - | [] -> () - | ss -> - warn env exp.at - "the cases in this switch over type\n %s\ndo not cover value\n %s" - (Type.string_of_typ_expand t1) - (String.concat " or\n " ss) - end; + (match Coverage.check_cases cases t1 with + | [] -> () + | ss -> + warn env exp.at + "the cases in this switch over type\n %s\ndo not cover value\n %s" + (Type.string_of_typ_expand t1) + (String.concat " or\n " ss) + ); t | FuncE (_, s', [], pat, typ_opt, exp), T.Func (s, _, [], ts1, ts2) -> let ve = check_pat_exhaustive env (T.seq ts1) pat in @@ -903,12 +899,14 @@ and check_exp' env t exp : T.typ = and infer_cases env t_pat t cases : T.typ = List.fold_left (infer_case env t_pat) t cases -and infer_case env t_pat t {it = {pat; exp}; at; _} = +and infer_case env t_pat t case = + let {pat; exp} = case.it in let ve = check_pat env t_pat pat in let t' = recover_with T.Non (infer_exp (adjoin_vals env ve)) exp in let t'' = T.lub t t' in if not env.pre && inconsistent t'' [t; t'] then - warn env at "the switch has type %s because branches have inconsistent types,\nthis case produces type\n %s\nthe previous produce type\n %s" + warn env case.at + "the switch has type %s because branches have inconsistent types,\nthis case produces type\n %s\nthe previous produce type\n %s" (T.string_of_typ t'') (T.string_of_typ_expand t) (T.string_of_typ_expand t'); @@ -917,7 +915,8 @@ and infer_case env t_pat t {it = {pat; exp}; at; _} = and check_cases env t_pat t cases = List.iter (check_case env t_pat t) cases -and check_case env t_pat t {it = {pat; exp}; _} = +and check_case env t_pat t case = + let {pat; exp} = case.it in let ve = check_pat env t_pat pat in recover (check_exp (adjoin_vals env ve) t) exp @@ -959,7 +958,7 @@ and infer_pat' env pat : T.typ * Scope.val_env = let t1 = T.Prim (infer_lit env lit pat.at) in let t = Operator.type_unop op t1 in if not (Operator.has_unop op t) then - local_error env pat.at "operator is not defined for operand type\n %s" + error env pat.at "operator is not defined for operand type\n %s" (T.string_of_typ_expand t); t, T.Env.empty | TupP pats -> @@ -1049,7 +1048,7 @@ and check_pat' env t pat : Scope.val_env = | SignP (op, lit) -> if not env.pre then begin if not (Operator.has_unop op (T.promote t)) then - local_error env pat.at "operator cannot consume expected type\n %s" + error env pat.at "operator cannot consume expected type\n %s" (T.string_of_typ_expand t); if T.sub t T.Non then ignore (infer_lit env lit pat.at) diff --git a/src/as_values/value.ml b/src/as_values/value.ml index d826d3b6df3..66b1690026b 100644 --- a/src/as_values/value.ml +++ b/src/as_values/value.ml @@ -1,6 +1,7 @@ open As_types open Printf + (* Environments *) module Env = Env.Make(String) @@ -283,7 +284,9 @@ and def = value Lib.Promise.t and 'a cont = 'a -> unit -(* Smart constructors *) +(* Shorthands *) + +let unit = Tup [] let local_func n m f = Func (Call_conv.local_cc n m, f) let message_func n f = Func (Call_conv.message_cc n, f) @@ -325,11 +328,6 @@ let as_async = function Async a -> a | _ -> invalid "as_async" let as_mut = function Mut r -> r | _ -> invalid "as_mut" -(* Primitives *) - -let unit = Tup [] - - (* Ordering *) let generic_compare = compare diff --git a/src/as_values/value.mli b/src/as_values/value.mli index 8ca39331c91..3931e13192e 100644 --- a/src/as_values/value.mli +++ b/src/as_values/value.mli @@ -113,13 +113,11 @@ and 'a cont = 'a -> unit val unit : value - -(* Smart constructors *) - val local_func : int -> int -> func -> value val message_func : int -> func -> value val async_func : int -> func -> value + (* Projections *) val as_null : value -> unit diff --git a/test/fail/ok/one-tuple-ambiguity.tc.ok b/test/fail/ok/one-tuple-ambiguity.tc.ok index 5baf5c2e6d0..a595b7f4473 100644 --- a/test/fail/ok/one-tuple-ambiguity.tc.ok +++ b/test/fail/ok/one-tuple-ambiguity.tc.ok @@ -2,5 +2,3 @@ one-tuple-ambiguity.as:16.3-16.5: type error, literal of type Nat does not have expected type (Nat, Bool) -one-tuple-ambiguity.as:16.1-16.5: type error, expected function type, but expression produces type - () diff --git a/test/fail/ok/pat-inconsistent.tc.ok b/test/fail/ok/pat-inconsistent.tc.ok index 2f6bdb9c9af..754f7b10e7d 100644 --- a/test/fail/ok/pat-inconsistent.tc.ok +++ b/test/fail/ok/pat-inconsistent.tc.ok @@ -126,3 +126,9 @@ left consumes {#A : Nat} right consumes {#A : Any} +pat-inconsistent.as:42.9-42.11: type error, variant pattern cannot consume expected type + {#A} +pat-inconsistent.as:49.8-49.9: type error, literal of type + Nat +does not have expected type + Bool diff --git a/test/fail/ok/pat-subtyping-fail.tc.ok b/test/fail/ok/pat-subtyping-fail.tc.ok index 9779245d9ea..227bfbe1c5c 100644 --- a/test/fail/ok/pat-subtyping-fail.tc.ok +++ b/test/fail/ok/pat-subtyping-fail.tc.ok @@ -1,3 +1,5 @@ +pat-subtyping-fail.as:123.3-123.15: warning, this case is never reached +pat-subtyping-fail.as:124.3-124.12: warning, this case is never reached pat-subtyping-fail.as:4.9-4.11: type error, operator cannot consume expected type Nat pat-subtyping-fail.as:8.9-8.11: type error, operator cannot consume expected type diff --git a/test/fail/pat-inconsistent.as b/test/fail/pat-inconsistent.as index b24ff39b4e9..ffabcff2061 100644 --- a/test/fail/pat-inconsistent.as +++ b/test/fail/pat-inconsistent.as @@ -35,3 +35,17 @@ let _ = func(#A or #B(_ : Nat)) {}; { let _ = func(("", 1) or ("", _ : Any)) {} }; { let _ = func(#A or #A(_ : Any)) {}; }; { let _ = func(#A(5) or #A(_ : Any)) {}; }; + +// No coverage check for ill-typed cases +switch (#A : {#A}) { + case (#A) {}; + case (#B : {#A; #B}) {}; + case _ {}; + case _ {}; +}; + +switch (true : Bool) { + case true {}; + case 1 {}; + case false {}; +}; diff --git a/test/fail/pat-subtyping-fail.as b/test/fail/pat-subtyping-fail.as index e0ed59ec39c..7092d67c6d0 100644 --- a/test/fail/pat-subtyping-fail.as +++ b/test/fail/pat-subtyping-fail.as @@ -117,3 +117,9 @@ switch (magic () : {#A : Nat; #B}) { case (#B : {#B}) {}; case _ {}; }; + + +switch (magic ()) { + case true {}; + case 1 {}; +}; diff --git a/test/run/ok/pat-subtyping.run-ir.ok b/test/run/ok/pat-subtyping.run-ir.ok index 8819fa5dc63..6fcdb8f75c5 100644 --- a/test/run/ok/pat-subtyping.run-ir.ok +++ b/test/run/ok/pat-subtyping.run-ir.ok @@ -31,3 +31,11 @@ pat-subtyping.as:172.3-172.32: warning, this case is never reached pat-subtyping.as:182.3-182.49: warning, this case is never reached pat-subtyping.as:185.3-185.31: warning, this case is never reached pat-subtyping.as:188.3-188.39: warning, this case is never reached +pat-subtyping.as:208.3-208.15: warning, this case is never reached +pat-subtyping.as:209.3-209.12: warning, this case is never reached +pat-subtyping.as:210.3-210.14: warning, this case is never reached +pat-subtyping.as:211.3-211.13: warning, this case is never reached +pat-subtyping.as:212.3-212.13: warning, this case is never reached +pat-subtyping.as:213.3-213.13: warning, this case is never reached +pat-subtyping.as:214.3-214.15: warning, this case is never reached +pat-subtyping.as:215.3-215.15: warning, this case is never reached diff --git a/test/run/ok/pat-subtyping.run-low.ok b/test/run/ok/pat-subtyping.run-low.ok index 8819fa5dc63..6fcdb8f75c5 100644 --- a/test/run/ok/pat-subtyping.run-low.ok +++ b/test/run/ok/pat-subtyping.run-low.ok @@ -31,3 +31,11 @@ pat-subtyping.as:172.3-172.32: warning, this case is never reached pat-subtyping.as:182.3-182.49: warning, this case is never reached pat-subtyping.as:185.3-185.31: warning, this case is never reached pat-subtyping.as:188.3-188.39: warning, this case is never reached +pat-subtyping.as:208.3-208.15: warning, this case is never reached +pat-subtyping.as:209.3-209.12: warning, this case is never reached +pat-subtyping.as:210.3-210.14: warning, this case is never reached +pat-subtyping.as:211.3-211.13: warning, this case is never reached +pat-subtyping.as:212.3-212.13: warning, this case is never reached +pat-subtyping.as:213.3-213.13: warning, this case is never reached +pat-subtyping.as:214.3-214.15: warning, this case is never reached +pat-subtyping.as:215.3-215.15: warning, this case is never reached diff --git a/test/run/ok/pat-subtyping.run.ok b/test/run/ok/pat-subtyping.run.ok index 8819fa5dc63..6fcdb8f75c5 100644 --- a/test/run/ok/pat-subtyping.run.ok +++ b/test/run/ok/pat-subtyping.run.ok @@ -31,3 +31,11 @@ pat-subtyping.as:172.3-172.32: warning, this case is never reached pat-subtyping.as:182.3-182.49: warning, this case is never reached pat-subtyping.as:185.3-185.31: warning, this case is never reached pat-subtyping.as:188.3-188.39: warning, this case is never reached +pat-subtyping.as:208.3-208.15: warning, this case is never reached +pat-subtyping.as:209.3-209.12: warning, this case is never reached +pat-subtyping.as:210.3-210.14: warning, this case is never reached +pat-subtyping.as:211.3-211.13: warning, this case is never reached +pat-subtyping.as:212.3-212.13: warning, this case is never reached +pat-subtyping.as:213.3-213.13: warning, this case is never reached +pat-subtyping.as:214.3-214.15: warning, this case is never reached +pat-subtyping.as:215.3-215.15: warning, this case is never reached diff --git a/test/run/ok/pat-subtyping.tc.ok b/test/run/ok/pat-subtyping.tc.ok index 8819fa5dc63..6fcdb8f75c5 100644 --- a/test/run/ok/pat-subtyping.tc.ok +++ b/test/run/ok/pat-subtyping.tc.ok @@ -31,3 +31,11 @@ pat-subtyping.as:172.3-172.32: warning, this case is never reached pat-subtyping.as:182.3-182.49: warning, this case is never reached pat-subtyping.as:185.3-185.31: warning, this case is never reached pat-subtyping.as:188.3-188.39: warning, this case is never reached +pat-subtyping.as:208.3-208.15: warning, this case is never reached +pat-subtyping.as:209.3-209.12: warning, this case is never reached +pat-subtyping.as:210.3-210.14: warning, this case is never reached +pat-subtyping.as:211.3-211.13: warning, this case is never reached +pat-subtyping.as:212.3-212.13: warning, this case is never reached +pat-subtyping.as:213.3-213.13: warning, this case is never reached +pat-subtyping.as:214.3-214.15: warning, this case is never reached +pat-subtyping.as:215.3-215.15: warning, this case is never reached diff --git a/test/run/ok/pat-subtyping.wasm.stderr.ok b/test/run/ok/pat-subtyping.wasm.stderr.ok index 8819fa5dc63..b3256f3ba03 100644 --- a/test/run/ok/pat-subtyping.wasm.stderr.ok +++ b/test/run/ok/pat-subtyping.wasm.stderr.ok @@ -31,3 +31,12 @@ pat-subtyping.as:172.3-172.32: warning, this case is never reached pat-subtyping.as:182.3-182.49: warning, this case is never reached pat-subtyping.as:185.3-185.31: warning, this case is never reached pat-subtyping.as:188.3-188.39: warning, this case is never reached +pat-subtyping.as:208.3-208.15: warning, this case is never reached +pat-subtyping.as:209.3-209.12: warning, this case is never reached +pat-subtyping.as:210.3-210.14: warning, this case is never reached +pat-subtyping.as:211.3-211.13: warning, this case is never reached +pat-subtyping.as:212.3-212.13: warning, this case is never reached +pat-subtyping.as:213.3-213.13: warning, this case is never reached +pat-subtyping.as:214.3-214.15: warning, this case is never reached +pat-subtyping.as:215.3-215.15: warning, this case is never reached +compile_lit_pat: (FloatLit 2.5) diff --git a/test/run/pat-subtyping.as b/test/run/pat-subtyping.as index 22931ad66a9..dc6fb56345b 100644 --- a/test/run/pat-subtyping.as +++ b/test/run/pat-subtyping.as @@ -204,4 +204,14 @@ switch (magic () : {#A : Nat; #B}) { case _ {}; }; +switch (magic ()) { + case true {}; + case 1 {}; + case 2.5 {}; + case "" {}; + case () {}; + case {} {}; + case null {}; + case (?_) {}; +}; }; From 6e5974f7b196b0e7885344bc8ca24e43deea12c4 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 22 Jul 2019 13:46:25 +0200 Subject: [PATCH 0297/1176] RTS: A simple test-driver from C (#583) this allows us to test the code in `rts.c` from a C program, compiled natively, to narrow down bugs. --- default.nix | 19 ++++++++--- rts/.gitignore | 1 + rts/Makefile | 84 +++++++++++++++++++++++++++++++++++++++--------- rts/README.md | 18 +++++++++-- rts/test_rts.c | 39 ++++++++++++++++++++++ test/ld/Makefile | 4 +-- 6 files changed, 140 insertions(+), 25 deletions(-) create mode 100644 rts/test_rts.c diff --git a/default.nix b/default.nix index a6cbe1382d3..5d0ce6d2d23 100644 --- a/default.nix +++ b/default.nix @@ -69,18 +69,23 @@ let }; llvmBuildInputs = [ - llvm.clang_9 - llvm.lld_9 + nixpkgs.clang # for native building + llvm.clang_9 # for wasm building + llvm.lld_9 # for wasm building ]; + # When compiling natively, we want to use `clang` (which is a nixpkgs + # provided wrapper that sets various include paths etc). + # But for some reason it does not handle building for Wasm well, so + # there we use plain clang-9. There is no stdlib there anyways. llvmEnv = '' - export CLANG="clang-9" + export CLANG="clang" + export WASM_CLANG="clang-9" export WASM_LD=wasm-ld ''; in rec { - rts = stdenv.mkDerivation { name = "asc-rts"; @@ -94,6 +99,12 @@ rec { export TOMMATHSRC=${libtommath} ''; + doCheck = true; + + checkPhase = '' + ./test_rts + ''; + installPhase = '' mkdir -p $out/rts cp as-rts.wasm $out/rts diff --git a/rts/.gitignore b/rts/.gitignore index a6192aa985a..b23b77784b5 100644 --- a/rts/.gitignore +++ b/rts/.gitignore @@ -1,2 +1,3 @@ as-rts.wasm +test_rts _build diff --git a/rts/Makefile b/rts/Makefile index 880962f1340..c666a350c45 100644 --- a/rts/Makefile +++ b/rts/Makefile @@ -1,6 +1,12 @@ CLANG ?= clang-9 +WASM_CLANG ?= clang-9 WASM_LD ?= wasm-ld-9 +# +# We manually list all the .c files of libtommath that we care about. +# (Usually the Wasm linker embedded in asc will complain if something is missing.) +# + TOMMATHFILES=\ mp_init mp_add mp_sub mp_mul mp_zero mp_cmp \ mp_set_u32 mp_set_i32 mp_get_i32 mp_get_mag_u32 \ @@ -10,11 +16,14 @@ TOMMATHFILES=\ mp_init_size mp_exch mp_clear mp_copy mp_count_bits mp_mul_2d mp_rshd mp_mul_d mp_div_2d mp_mod_2d \ s_mp_balance_mul s_mp_toom_mul s_mp_toom_sqr s_mp_karatsuba_sqr s_mp_sqr_fast s_mp_sqr s_mp_karatsuba_mul s_mp_mul_digs_fast s_mp_mul_digs mp_init_multi mp_clear_multi mp_mul_2 mp_div_2 mp_div_3 mp_lshd mp_incr mp_decr mp_add_d mp_sub_d -TOMMATH_O=$(patsubst %,_build/tommath_%.o,$(TOMMATHFILES)) - TOMMATHSRC ?= $(PWD)/../../libtommath -MP_FLAGS = \ +# +# Various libtommath flags, in particuliar telling it to use our own memory +# manager +# + +TOMMATH_FLAGS = \ -DMP_32BIT \ -DMP_MALLOC=mp_malloc \ -DMP_REALLOC=mp_realloc \ @@ -24,31 +33,74 @@ MP_FLAGS = \ -DMP_FIXED_CUTOFFS \ -DMP_NO_FILE \ +# +# clang flags used both for Wasm compilation and native (i.e. test suite) compilation +# + CLANG_FLAGS = \ --compile \ -fpic \ + -fvisibility=hidden \ + +# +# clang flags only used during Wasm compilation +# + +WASM_FLAGS = \ --target=wasm32-unknown-unknown-wasm -fvisibility=hidden \ -fno-builtin -ffreestanding \ --optimize=3 \ - -fvisibility=hidden \ +# +# Build targets +# + +all: as-rts.wasm test_rts + +_build/wasm _build/native: + mkdir -p $@ + +# +# Building the libtommath files, Wasm and native +# + +TOMMATH_WASM_O=$(patsubst %,_build/wasm/tommath_%.o,$(TOMMATHFILES)) + +_build/wasm/tommath_%.o: $(TOMMATHSRC)/bn_%.c | _build/wasm + $(WASM_CLANG) -c $(CLANG_FLAGS) $(WASM_FLAGS) $(TOMMATH_FLAGS) $< --output $@ + +TOMMATH_NATIVE_O=$(patsubst %,_build/native/tommath_%.o,$(TOMMATHFILES)) + +_build/native/tommath_%.o: $(TOMMATHSRC)/bn_%.c | _build/native + $(CLANG) -c $(CLANG_FLAGS) $(TOMMATH_FLAGS) $< --output $@ + +# +# Our part of the RTS, Wasm and native +# -_build/tommath_%.o: $(TOMMATHSRC)/bn_%.c | _build - $(CLANG) $(CLANG_FLAGS) $(MP_FLAGS)$< --output $@ +_build/wasm/rts.o: rts.c | _build/wasm + $(WASM_CLANG) -c $(CLANG_FLAGS) $(WASM_FLAGS) $(TOMMATH_FLAGS) -I$(TOMMATHSRC) --std=c11 $< --output $@ -all: as-rts.wasm +_build/native/rts.o: rts.c | _build/native + $(CLANG) -c $(CLANG_FLAGS) $(TOMMATH_FLAGS) -I$(TOMMATHSRC) --std=c11 $< --output $@ -_build: - mkdir _build +# +# The actual RTS, a we ship it with the compiler +# -_build/rts.o: rts.c $(HEADER_STUBS) | _build - $(CLANG) $(CLANG_FLAGS) $(MP_FLAGS) -I$(TOMMATHSRC) --std=c11 $< --output $@ +as-rts.wasm: _build/wasm/rts.o $(TOMMATH_WASM_O) + $(WASM_LD) -o $@ \ + --import-memory --shared --no-entry --gc-sections \ + --export=__wasm_call_ctors \ + $+ -as-rts.wasm: _build/rts.o $(TOMMATH_O) - $(WASM_LD) --import-memory --shared --no-entry --gc-sections \ - _build/rts.o $(TOMMATH_O) -o $@ \ - --export=__wasm_call_ctors +# +# A simple program to do simple tests of rts.c, using native compilation +# +test_rts: test_rts.c _build/native/rts.o $(TOMMATH_NATIVE_O) + $(CLANG) -o $@ \ + $+ clean: - rm -rf _build as-rts.wasm + rm -rf _build as-rts.wasm test_rts diff --git a/rts/README.md b/rts/README.md index 5790ab36368..940cac5bd3f 100644 --- a/rts/README.md +++ b/rts/README.md @@ -17,9 +17,10 @@ Compilation Running `make` should produce `as-rts.wasm`. -If run within `nix-shell`, the environment variables `CLANG` and `WASM_LD` -should point to suitable binaries. If not present, the `Makefile` will try to -use `clang-9` and `wasm-ld-9`. +If run within `nix-shell`, the environment variables `WASM_CLANG` and `WASM_LD` +should point to suitable binaries (we track a specific unreleased version of +`llvm`). If not present, the `Makefile` will try to use `clang-9` and +`wasm-ld-9`. The runtime compiles and links in [libtommath]. It needs the source, so `nix-build` and `nix-shell` will set the environment variable `TOMMATHSRC` to @@ -44,3 +45,14 @@ libtommath and memory managment We have to make libtommath’s memory management (which expects C-like functions `alloc`, `calloc` and `realloc`) work with the ActorScript runtime. See the comment next to `mp_alloc` in `rts.c` for the techical details. + +C tests +------- + +To narrow down issues, or do regression testing on the C level, you can interact +with the code provided by `rts.c` from `test_rts.c`. With + + make test_rts && ./test_rts + +this is executed. This is compiled natively, so may not hide bugs that are tied to +WebAssembly. diff --git a/rts/test_rts.c b/rts/test_rts.c new file mode 100644 index 00000000000..e9e40496679 --- /dev/null +++ b/rts/test_rts.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include + +typedef intptr_t as_ptr; + +as_ptr alloc_bytes(size_t n) { + void *ptr = malloc(n); + if (ptr == NULL) { printf("OOM\n"); exit(1); }; + return ((as_ptr)ptr) - 1; +}; + +void idl_trap() { + printf("IDL trap\n"); + exit(1); +} +void bigint_trap() { + printf("Bigint trap\n"); + exit(1); +} + +extern as_ptr bigint_of_word32(uint32_t b); +extern as_ptr bigint_mul(as_ptr a, as_ptr b); +extern as_ptr bigint_pow(as_ptr a, as_ptr b); +extern bool bigint_eq(as_ptr a, as_ptr b); + + +int main () { + printf("ASC RTS test suite\n"); + + printf("70**32 = 70**31 * 70: %s\n", + bigint_eq( + bigint_pow(bigint_of_word32(70), bigint_of_word32(32)), + bigint_mul( + bigint_pow(bigint_of_word32(70), bigint_of_word32(31)), + bigint_of_word32(70) + )) ? "ok" : "not ok"); +} diff --git a/test/ld/Makefile b/test/ld/Makefile index 9b0a87d25bd..85b81f47d6f 100644 --- a/test/ld/Makefile +++ b/test/ld/Makefile @@ -9,12 +9,12 @@ accept: clean: rm -rf _out -CLANG?=clang-9 +WASM_CLANG?=clang-9 WASM_LD?=wasm-ld-9 AS_LD?=../../src/as-ld _out/%.lib.o: %.c | _out - $(CLANG) --compile -fpic --std=c11 --target=wasm32-unknown-unknown-wasm -fvisibility=hidden --optimize=3 \ + $(WASM_CLANG) --compile -fpic --std=c11 --target=wasm32-unknown-unknown-wasm -fvisibility=hidden --optimize=3 \ -fno-builtin -Wall \ $< --output $@ From f2631a63e91b4e0d2886d01058381c606daa0462 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 22 Jul 2019 14:14:01 +0200 Subject: [PATCH 0298/1176] Bump dev (#590) this should finanlly get rid of the `gitSource.nix` warnign (this took several PRs because we import `dev` with a pinned version which imports `actorscript` with a pinned version.) --- default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/default.nix b/default.nix index 5d0ce6d2d23..6ff6489ba10 100644 --- a/default.nix +++ b/default.nix @@ -26,7 +26,7 @@ let ocaml_bisect_ppx-ocamlbuild = import ./nix/ocaml-bisect_ppx-ocamlbuild.nix n let dev = import (builtins.fetchGit { url = "ssh://git@github.com/dfinity-lab/dev"; ref = "master"; - rev = "49627900050b2db1b641cd402e832a165b8d47f5"; + rev = "ad50bcea8db6d55decf2622ad836435aa36fa33f"; }) { system = nixpkgs.system; }; in # Include dvm From 73717df84eb03a9496a5811eeb02e3c1bf02a307 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 22 Jul 2019 16:05:07 +0200 Subject: [PATCH 0299/1176] Split RTS into multiple files (#589) cherry-picked from #588. --- rts/Makefile | 18 +- rts/bigint.c | 373 +++++++++++++++++++++++++++++ rts/idl.c | 101 ++++++++ rts/rts.c | 519 +---------------------------------------- rts/rts.h | 66 ++++++ src/codegen/compile.ml | 6 +- 6 files changed, 557 insertions(+), 526 deletions(-) create mode 100644 rts/bigint.c create mode 100644 rts/idl.c create mode 100644 rts/rts.h diff --git a/rts/Makefile b/rts/Makefile index c666a350c45..0e424a877ae 100644 --- a/rts/Makefile +++ b/rts/Makefile @@ -64,31 +64,37 @@ _build/wasm _build/native: # Building the libtommath files, Wasm and native # -TOMMATH_WASM_O=$(patsubst %,_build/wasm/tommath_%.o,$(TOMMATHFILES)) _build/wasm/tommath_%.o: $(TOMMATHSRC)/bn_%.c | _build/wasm $(WASM_CLANG) -c $(CLANG_FLAGS) $(WASM_FLAGS) $(TOMMATH_FLAGS) $< --output $@ -TOMMATH_NATIVE_O=$(patsubst %,_build/native/tommath_%.o,$(TOMMATHFILES)) _build/native/tommath_%.o: $(TOMMATHSRC)/bn_%.c | _build/native $(CLANG) -c $(CLANG_FLAGS) $(TOMMATH_FLAGS) $< --output $@ +TOMMATH_WASM_O=$(TOMMATHFILES:%=_build/wasm/tommath_%.o) +TOMMATH_NATIVE_O=$(TOMMATHFILES:%=_build/native/tommath_%.o) + # # Our part of the RTS, Wasm and native # -_build/wasm/rts.o: rts.c | _build/wasm +RTSFILES=rts idl bigint + +_build/wasm/%.o: %.c | _build/wasm $(WASM_CLANG) -c $(CLANG_FLAGS) $(WASM_FLAGS) $(TOMMATH_FLAGS) -I$(TOMMATHSRC) --std=c11 $< --output $@ -_build/native/rts.o: rts.c | _build/native +_build/native/%.o: %.c | _build/native $(CLANG) -c $(CLANG_FLAGS) $(TOMMATH_FLAGS) -I$(TOMMATHSRC) --std=c11 $< --output $@ +RTS_WASM_O=$(RTSFILES:%=_build/wasm/%.o) +RTS_NATIVE_O=$(RTSFILES:%=_build/native/%.o) + # # The actual RTS, a we ship it with the compiler # -as-rts.wasm: _build/wasm/rts.o $(TOMMATH_WASM_O) +as-rts.wasm: $(RTS_WASM_O) $(TOMMATH_WASM_O) $(WASM_LD) -o $@ \ --import-memory --shared --no-entry --gc-sections \ --export=__wasm_call_ctors \ @@ -98,7 +104,7 @@ as-rts.wasm: _build/wasm/rts.o $(TOMMATH_WASM_O) # A simple program to do simple tests of rts.c, using native compilation # -test_rts: test_rts.c _build/native/rts.o $(TOMMATH_NATIVE_O) +test_rts: test_rts.c $(RTS_NATIVE_O) $(TOMMATH_NATIVE_O) $(CLANG) -o $@ \ $+ clean: diff --git a/rts/bigint.c b/rts/bigint.c new file mode 100644 index 00000000000..d206d007fed --- /dev/null +++ b/rts/bigint.c @@ -0,0 +1,373 @@ +#include "rts.h" + +/* Memory management for libtommath */ + +/* +A libtommath arbitrary precision integer is a struct (`mp_int`) that contains a +pointer to a data array. + + * The libtommath library never allocates the struct, so we are in full + control. We can embed the struct simply in an ActorScript heap object + with a dedicated tag for it. + + * The data array is allocated with mp_calloc and mp_realloc. We provide these + calls, allocate ActorScript arrays (using the TAG_TEXT tag for byte arrays, + not TAG_ARRAY for arrays of pointers) and store the pointer to the + _payload_ in the `mp_digit* dp` field of the struct. This way, things look all nice + and dandy from libtommath’s point of view. + + Our garbage collector has special knowledge about the dp field of the struct + and understands that this pointer points inside the TAG_TEXT heap object. But + we can still move them around in the GC without issues. + + The length of the byte array is always equal to the allocation asked for by + libtommath (no shrinking via mp_realloc supported). + This means we can assert that it matches the old_size passed to mp_realloc as + an additional check. + We can also support shrinking via mp_realloc, but then we have to drop that check. +*/ + +void* mp_alloc(size_t l) { + as_ptr r = alloc_bytes (2*sizeof(void*) + l); + FIELD(r, 0) = TAG_TEXT; // abusing text as byte array here + FIELD(r, 1) = l; + return &FIELD(r,2); +} + +export void* mp_calloc(size_t n, size_t size) { + size_t l = n * size; // check overflow? + void *payload = mp_alloc(l); + char *tmp = (char *)payload; + for (size_t i = 0; i < l; i++) { + *tmp++ = 0; + } + return payload; +} + +export void* mp_realloc(void *ptr, size_t old_size, size_t new_size) { + as_ptr r = (as_ptr)(((char *)ptr) - (2 * sizeof(void*) + 1)); + + if (FIELD(r, 0) != TAG_TEXT) bigint_trap(); // assert block type + + if (new_size > FIELD(r, 1)) { + void *newptr = mp_alloc(new_size); + if (old_size != FIELD(r, 1)) bigint_trap(); + as_memcpy(newptr, ptr, old_size); + return newptr; + } else if (new_size == FIELD(r, 1)) { + // No need to grow + return ptr; + } else { + // libtommath only shrinks on explicit demand via mp_shrink + // and we do not use that function + // so this should not happen. + bigint_trap(); + } +} + +export void mp_free(void *ptr, size_t size) { +} + +/* Wrapper functions for libtommath */ + +#include +#define BIGINT_PAYLOAD(p) ((mp_int *)(&FIELD(p,1))) + +/* +Note on libtommath error handling + +Most libtommath operations return an int to signal error codes. +These are (see tommath.h): + + #define MP_OKAY 0 / * ok result * / + #define MP_MEM -2 / * out of mem * / + #define MP_VAL -3 / * invalid input * / + #define MP_RANGE MP_VAL + #define MP_ITER -4 / * Max. iterations reached * / + +We will never hit MP_MEM, because our allocation functions trap if they cannot +allocate. But the others can happen (e.g. division by 0). In that case, +we call a trap function provided by the Wasm part of the runtime. +*/ + +#define CHECK(e) ((e == 0)?0:bigint_trap()) + +as_ptr bigint_alloc() { + as_ptr r = alloc_bytes (1*sizeof(void*) + sizeof(mp_int)); + FIELD(r, 0) = TAG_BIGINT; + CHECK(mp_init(BIGINT_PAYLOAD(r))); + return r; +} + +export as_ptr bigint_of_word32(uint32_t b) { + as_ptr r = bigint_alloc(); + mp_set_u32(BIGINT_PAYLOAD(r), b); + return r; +} + +export as_ptr bigint_of_word32_signed(int32_t b) { + as_ptr r = bigint_alloc(); + mp_int *n = BIGINT_PAYLOAD(r); + mp_set_i32(n, b); + return r; +} + +export uint32_t bigint_to_word32_wrap(as_ptr a) { + mp_int *n = BIGINT_PAYLOAD(a); + return mp_get_u32(n); +} + +export uint32_t bigint_to_word32_trap(as_ptr a) { + mp_int *n = BIGINT_PAYLOAD(a); + if (mp_isneg(n)) bigint_trap(); + if (mp_count_bits(n) > 32) bigint_trap(); + return mp_get_u32(n); +} + +export int32_t bigint_to_word32_signed_trap(as_ptr a) { + mp_int *n = BIGINT_PAYLOAD(a); + if (mp_count_bits(n) > 32) bigint_trap(); + if (mp_isneg(n)) { + int32_t x = - (int32_t)(mp_get_mag_u32(n)); + if (x >= 0) bigint_trap(); + return x; + } else { + int32_t x = (int32_t)(mp_get_mag_u32(n)); + if (x < 0) bigint_trap(); + return x; + } +} + +export uint64_t bigint_to_word64_wrap(as_ptr a) { + mp_int *n = BIGINT_PAYLOAD(a); + return mp_get_u64(n); +} + +export uint64_t bigint_to_word64_trap(as_ptr a) { + mp_int *n = BIGINT_PAYLOAD(a); + if (mp_isneg(n)) bigint_trap(); + if (mp_count_bits(n) > 64) bigint_trap(); + return mp_get_u64(n); +} + +export int64_t bigint_to_word64_signed_trap(as_ptr a) { + mp_int *n = BIGINT_PAYLOAD(a); + if (mp_count_bits(n) > 64) bigint_trap(); + if (mp_isneg(n)) { + int64_t x = - (int64_t)(mp_get_mag_u64(n)); + if (x >= 0) bigint_trap(); + return x; + } else { + int64_t x = (int64_t)(mp_get_mag_u64(n)); + if (x < 0) bigint_trap(); + return x; + } +} + +export as_ptr bigint_of_word64(uint64_t b) { + as_ptr r = bigint_alloc(); + mp_set_u64(BIGINT_PAYLOAD(r), b); + return r; +} + +export as_ptr bigint_of_word64_signed(int64_t b) { + as_ptr r = bigint_alloc(); + mp_int *n = BIGINT_PAYLOAD(r); + mp_set_i64(n, b); + return r; +} + +export bool bigint_eq(as_ptr a, as_ptr b) { + return mp_cmp(BIGINT_PAYLOAD(a), BIGINT_PAYLOAD(b)) == 0; +} +export bool bigint_lt(as_ptr a, as_ptr b) { + return mp_cmp(BIGINT_PAYLOAD(a), BIGINT_PAYLOAD(b)) < 0; +} +export bool bigint_gt(as_ptr a, as_ptr b) { + return mp_cmp(BIGINT_PAYLOAD(a), BIGINT_PAYLOAD(b)) > 0; +} +export bool bigint_le(as_ptr a, as_ptr b) { + return mp_cmp(BIGINT_PAYLOAD(a), BIGINT_PAYLOAD(b)) <= 0; +} +export bool bigint_ge(as_ptr a, as_ptr b) { + return mp_cmp(BIGINT_PAYLOAD(a), BIGINT_PAYLOAD(b)) >= 0; +} + +export as_ptr bigint_add(as_ptr a, as_ptr b) { + as_ptr r = bigint_alloc(); + CHECK(mp_add(BIGINT_PAYLOAD(a), BIGINT_PAYLOAD(b), BIGINT_PAYLOAD(r))); + return r; +} + +export as_ptr bigint_sub(as_ptr a, as_ptr b) { + as_ptr r = bigint_alloc(); + CHECK(mp_sub(BIGINT_PAYLOAD(a), BIGINT_PAYLOAD(b), BIGINT_PAYLOAD(r))); + return r; +} + +export as_ptr bigint_mul(as_ptr a, as_ptr b) { + as_ptr r = bigint_alloc(); + CHECK(mp_mul(BIGINT_PAYLOAD(a), BIGINT_PAYLOAD(b), BIGINT_PAYLOAD(r))); + return r; +} + +export as_ptr bigint_pow(as_ptr a, as_ptr b) { + uint32_t exp = bigint_to_word32_trap(b); + as_ptr r = bigint_alloc(); + CHECK(mp_expt_u32(BIGINT_PAYLOAD(a), exp, BIGINT_PAYLOAD(r))); + return r; +} + +export as_ptr bigint_div(as_ptr a, as_ptr b) { + as_ptr r = bigint_alloc(); + mp_int rem; + CHECK(mp_init(&rem)); + CHECK(mp_div(BIGINT_PAYLOAD(a), BIGINT_PAYLOAD(b), BIGINT_PAYLOAD(r), &rem)); + return r; +} + +export as_ptr bigint_rem(as_ptr a, as_ptr b) { + as_ptr r = bigint_alloc(); + mp_int quot; + CHECK(mp_init(")); + CHECK(mp_div(BIGINT_PAYLOAD(a), BIGINT_PAYLOAD(b), ", BIGINT_PAYLOAD(r))); + return r; +} + +export as_ptr bigint_neg(as_ptr a) { + as_ptr r = bigint_alloc(); + CHECK(mp_neg(BIGINT_PAYLOAD(a), BIGINT_PAYLOAD(r))); + return r; +} + +export as_ptr bigint_abs(as_ptr a) { + as_ptr r = bigint_alloc(); + CHECK(mp_abs(BIGINT_PAYLOAD(a), BIGINT_PAYLOAD(r))); + return r; +} + +export bool bigint_isneg(as_ptr a) { + return mp_isneg(BIGINT_PAYLOAD(a)); +} + +export as_ptr bigint_lsh(as_ptr a, int b) { + as_ptr r = bigint_alloc(); + CHECK(mp_mul_2d(BIGINT_PAYLOAD(a), b, BIGINT_PAYLOAD(r))); + return r; +} + +export int bigint_count_bits(as_ptr a) { + return mp_count_bits(BIGINT_PAYLOAD(a)); +} + +/* LEB128 Encoding-decoding */ +export int bigint_leb128_size(as_ptr n) { + if (mp_iszero(BIGINT_PAYLOAD(n))) return 1; + int x = bigint_count_bits(n); + return ((x + 6) / 7); // divide by 7, round up +} + +void leb128_encode_go(mp_int *tmp, unsigned char *buf) { + // now the number should be positive + if (mp_isneg(tmp)) bigint_trap(); + while (true) { + buf[0] = (char)(mp_get_u32(tmp)); // get low bits + CHECK(mp_div_2d(tmp, 7, tmp, NULL)); + if (mp_iszero(tmp)) { + // we are done. high bit should be cleared anyways + return; + } else { + // more bytes to come, set high bit and continue + buf[0] |= 1<<7; + buf++; + } + } +} + +export void bigint_leb128_encode(as_ptr n, unsigned char *buf) { + mp_int tmp; + CHECK(mp_init_copy(&tmp, BIGINT_PAYLOAD(n))); + leb128_encode_go(&tmp, buf); +} + + +int leb128_encoding_size(unsigned char *buf) { + // zoom to the end + int i = 0; + while (buf[i] & (1<<7)) i++; + return i+1; +} + +as_ptr leb128_decode_go(unsigned char *buf, int bytes) { + // do not accept overlong encodings + if (buf[bytes-1] == 1<<7) bigint_trap(); + + as_ptr r = bigint_alloc(); + CHECK(mp_init(BIGINT_PAYLOAD(r))); + int i = bytes-1; + while (true) { + CHECK(mp_add_d(BIGINT_PAYLOAD(r), buf[i] & ((1<<7)-1), BIGINT_PAYLOAD(r))); + if (i > 0) { + CHECK(mp_mul_2d(BIGINT_PAYLOAD(r), 7, BIGINT_PAYLOAD(r))); + i--; + } else { + break; + } + } + return r; +} + +export as_ptr bigint_leb128_decode(unsigned char *buf) { + int bytes = leb128_encoding_size(buf); + return leb128_decode_go(buf, bytes); +} + +/* SLEB128 Encoding-decoding */ +export int bigint_2complement_bits(as_ptr n) { + if (mp_isneg(BIGINT_PAYLOAD(n))) { + mp_int tmp; + CHECK(mp_init_copy(&tmp, BIGINT_PAYLOAD(n))); + CHECK(mp_incr(&tmp)); + return 1 + mp_count_bits(&tmp); + } else { + return 1 + mp_count_bits(BIGINT_PAYLOAD(n)); + } +} + +export int bigint_sleb128_size(as_ptr n) { + int x = bigint_2complement_bits(n); + return ((x + 6) / 7); // divide by 7, round up +} + +export void bigint_sleb128_encode(as_ptr n, unsigned char *buf) { + mp_int tmp; + CHECK(mp_init_copy(&tmp, BIGINT_PAYLOAD(n))); + + if (mp_isneg(&tmp)) { + // turn negative numbers into the two's complement of the right size + int bytes = bigint_sleb128_size(n); + mp_int big; + CHECK(mp_init(&big)); + CHECK(mp_2expt(&big, 7*bytes)); + CHECK(mp_add(&tmp, &big, &tmp)); + } + + leb128_encode_go(&tmp, buf); +} + +export as_ptr bigint_sleb128_decode(unsigned char *buf) { + int bytes = leb128_encoding_size(buf); + + as_ptr r = leb128_decode_go(buf, bytes); + + // Now adjust sign if necessary + if (buf[bytes-1] & (1<<6)) { + // negative number + mp_int big; + CHECK(mp_init(&big)); + CHECK(mp_2expt(&big, 7*bytes)); + CHECK(mp_sub(BIGINT_PAYLOAD(r), &big, BIGINT_PAYLOAD(r))); + } + + return r; +} diff --git a/rts/idl.c b/rts/idl.c new file mode 100644 index 00000000000..b3b9013cc6d --- /dev/null +++ b/rts/idl.c @@ -0,0 +1,101 @@ +#include "rts.h" + +// Initially, we just want to be able to zoom past the type description +// TODO: Defensive programming +// (not going past the size of the message, trapping if leb128 does not fit in int) + +uint32_t read_leb128(char **ptr, char *end) { + uint32_t r = 0; + unsigned int s = 0; + uint8_t b; + do { + if (*ptr >= end) (idl_trap()); + b = *((*ptr)++); + if (s == 28 && !((b & (uint8_t)0xF0) == 0x00)) { + // the 5th byte needs to be the last, and it must contribute at most 4 bits + // else we have an int overflow + idl_trap(); + } + r += (b & (uint8_t)0x7f) << s; + s += 7; + } while (b & (uint8_t)0x80); + return r; +} + +int32_t read_sleb128(char **ptr, char *end) { + uint32_t r = 0; + unsigned int s = 0; + uint8_t b; + do { + if (*ptr >= end) (idl_trap()); + b = *((*ptr)++); + if (s == 28 && !((b & (uint8_t)0xF0) == 0x00 || (b & (uint8_t)0xF0) == 0x70)) { + // the 5th byte needs to be the last, and it must contribute at most 4 bits + // else we have an int overflow + idl_trap(); + } + r += (b & (uint8_t)0x7f) << s; + s += 7; + } while (b & (uint8_t)0x80); + // sign extend + if (s < 32 && (b & (uint8_t)0x40)) { + r |= (~(uint32_t)0 << s); + } + return r; +} + +export char *skip_idl_header(char *ptr, char *end) { + // Magic bytes + if (*ptr++ != 'D') idl_trap(); + if (*ptr++ != 'I') idl_trap(); + if (*ptr++ != 'D') idl_trap(); + if (*ptr++ != 'L') idl_trap(); + // Size of type list + for (int count = read_leb128(&ptr,end); count > 0; count --) { + int ty = read_sleb128(&ptr,end); + if (ty >= -17) { + idl_trap(); // illegal + } else if (ty == -18) { // opt + read_sleb128(&ptr,end); + } + else if (ty == -19) { // vec + read_sleb128(&ptr,end); + } else if (ty == -20) { // record + for (int n = read_leb128(&ptr,end); n > 0; n--) { + read_leb128(&ptr,end); + read_sleb128(&ptr,end); + } + } else if (ty == -21) { // variant + for (int n = read_leb128(&ptr,end); n > 0; n--) { + read_leb128(&ptr,end); + read_sleb128(&ptr,end); + } + } else if (ty == -22) { // func + // arg types + for (int n = read_leb128(&ptr,end); n > 0; n--) { + read_sleb128(&ptr,end); + } + // ret types + for (int n = read_leb128(&ptr,end); n > 0; n--) { + read_sleb128(&ptr,end); + } + // annotations + for (int n = read_leb128(&ptr,end); n > 0; n--) { + ptr++; + } + } else if (ty == -23) { // service + for (int n = read_leb128(&ptr,end); n > 0; n--) { + // name + unsigned int size = read_leb128(&ptr,end); + ptr += size; + // type + read_sleb128(&ptr,end); + } + } else { + // no support for future types yet + idl_trap(); + } + } + read_sleb128(&ptr,end); // index + return ptr; +} diff --git a/rts/rts.c b/rts/rts.c index 0a77fd8b91a..7debe03ede7 100644 --- a/rts/rts.c +++ b/rts/rts.c @@ -1,11 +1,4 @@ -#pragma GCC diagnostic ignored "-Wattributes" -#pragma GCC diagnostic ignored "-Wincompatible-library-redeclaration" -#define export __attribute__ ((visibility("default"))) -#define from_rts __attribute__ ((import_module("env"))) extern - -#include -#include -#include +#include "rts.h" export void as_memcpy(char *str1, const char *str2, size_t n) { for (size_t i = 0; i < n; i++) { @@ -13,53 +6,6 @@ export void as_memcpy(char *str1, const char *str2, size_t n) { } } -/* -ActorScript pointers are offset by one. So let us represent -them as a typedef, and access the fields using the payload macro. -*/ -typedef intptr_t as_ptr; -#define FIELD(p,n) (((size_t *)(p+1))[n]) -#define TAG(p) FIELD(p,0) -#define TEXT_LEN(p) ((char *)(&FIELD(p,1))) -#define TEXT_PAYLOAD(p) ((char *)(&FIELD(p,2))) - -/* - -Ideally I’d do something like this - - __attribute__((global)) extern char* heap_ptr; - export char* alloc_bytes(int n) { - char *r = heap_ptr; - heap_ptr += (n + 3) & ~0x03; - return r; - } - -But seems we can’t import mutable globals like that, -see https://bugs.llvm.org/show_bug.cgi?id=41610 - -So in order to allocate on the ActorScript heap from C, we import -alloc_bytes from the Actorscript RTS: -*/ -from_rts as_ptr alloc_bytes(size_t n); - -/* Heap tags. Needs to stay in sync with compile.ml */ -enum as_heap_tag { - TAG_INVALID = 0, - TAG_OBJECT = 1, - TAG_OBJIND = 2, - TAG_ARRAY = 3, - TAG_REFERENCE = 4, - TAG_INT = 5, - TAG_MUTBOX = 6, - TAG_CLOSURE = 7, - TAG_SOME = 8, - TAG_VARIANT = 9, - TAG_TEXT = 10, - TAG_INDIRECTION = 11, - TAG_SMALLWORD = 12, - TAG_BIGINT = 13, - }; - size_t as_strlen(const char* p) { size_t i = 0; while (p[i]) i++; @@ -83,466 +29,3 @@ as_ptr get_version() { return as_str_of_cstr(RTS_VERSION); } as_ptr (*version_getter)() = &get_version; export as_ptr version() { return (*version_getter)(); } - -/* IDL code */ -from_rts __attribute__ ((noreturn)) void idl_trap(); - -// Initially, we just want to be able to zoom past the type description -// TODO: Defensive programming -// (not going past the size of the message, trapping if leb128 does not fit in int) - -int read_leb128(char **ptr) { - int r = 0; - int s = 0; - char b; - do { - b = *(*ptr)++; - r += (b & (char)0x7f) << s; - s += 7; - } while (b & (char)0x80); - return r; -} -int read_sleb128(char **ptr) { - int r = 0; - int s = 0; - char b; - do { - b = *(*ptr)++; - r += (b & (char)0x7f) << s; - s += 7; - } while (b & (char)0x80); - // sign extend - if (b & (char)0x40) { - r |= (~0 << s); - } - return r; -} - -export char *skip_idl_header(char *ptr) { - // Magic bytes - if (*ptr++ != 'D') idl_trap(); - if (*ptr++ != 'I') idl_trap(); - if (*ptr++ != 'D') idl_trap(); - if (*ptr++ != 'L') idl_trap(); - // Size of type list - for (int count = read_leb128(&ptr); count > 0; count --) { - int ty = read_sleb128(&ptr); - if (ty >= -17) { - idl_trap(); // illegal - } else if (ty == -18) { // opt - read_sleb128(&ptr); - } - else if (ty == -19) { // vec - read_sleb128(&ptr); - } else if (ty == -20) { // record - for (int n = read_leb128(&ptr); n > 0; n--) { - read_leb128(&ptr); - read_sleb128(&ptr); - } - } else if (ty == -21) { // variant - for (int n = read_leb128(&ptr); n > 0; n--) { - read_leb128(&ptr); - read_sleb128(&ptr); - } - } else if (ty == -22) { // func - // arg types - for (int n = read_leb128(&ptr); n > 0; n--) { - read_sleb128(&ptr); - } - // ret types - for (int n = read_leb128(&ptr); n > 0; n--) { - read_sleb128(&ptr); - } - // annotations - for (int n = read_leb128(&ptr); n > 0; n--) { - ptr++; - } - } else if (ty == -23) { // service - for (int n = read_leb128(&ptr); n > 0; n--) { - // name - ptr += read_leb128(&ptr); - // type - read_sleb128(&ptr); - } - } else { - // no support for future types yet - idl_trap(); - } - } - read_sleb128(&ptr); // index - return ptr; -} - -/* Memory management for libtommath */ - -/* -A libtommath arbitrary precision integer is a struct (`mp_int`) that contains a -pointer to a data array. - - * The libtommath library never allocates the struct, so we are in full - control. We can embed the struct simply in an ActorScript heap object - with a dedicated tag for it. - - * The data array is allocated with mp_calloc and mp_realloc. We provide these - calls, allocate ActorScript arrays (using the TAG_TEXT tag for byte arrays, - not TAG_ARRAY for arrays of pointers) and store the pointer to the - _payload_ in the `mp_digit* dp` field of the struct. This way, things look all nice - and dandy from libtommath’s point of view. - - Our garbage collector has special knowledge about the dp field of the struct - and understands that this pointer points inside the TAG_TEXT heap object. But - we can still move them around in the GC without issues. - - The length of the byte array is always equal to the allocation asked for by - libtommath (no shrinking via mp_realloc supported). - This means we can assert that it matches the old_size passed to mp_realloc as - an additional check. - We can also support shrinking via mp_realloc, but then we have to drop that check. -*/ - -void* mp_alloc(size_t l) { - as_ptr r = alloc_bytes (2*sizeof(void*) + l); - FIELD(r, 0) = TAG_TEXT; // abusing text as byte array here - FIELD(r, 1) = l; - return &FIELD(r,2); -} - -export void* mp_calloc(size_t n, size_t size) { - size_t l = n * size; // check overflow? - void *payload = mp_alloc(l); - char *tmp = (char *)payload; - for (size_t i = 0; i < l; i++) { - *tmp++ = 0; - } - return payload; -} - -from_rts __attribute__ ((noreturn)) void bigint_trap(); - -export void* mp_realloc(void *ptr, size_t old_size, size_t new_size) { - as_ptr r = (as_ptr)(((char *)ptr) - (2 * sizeof(void*) + 1)); - - if (FIELD(r, 0) != TAG_TEXT) bigint_trap(); // assert block type - - if (new_size > FIELD(r, 1)) { - void *newptr = mp_alloc(new_size); - if (old_size != FIELD(r, 1)) bigint_trap(); - as_memcpy(newptr, ptr, old_size); - return newptr; - } else if (new_size == FIELD(r, 1)) { - // No need to grow - return ptr; - } else { - // libtommath only shrinks on explicit demand via mp_shrink - // and we do not use that function - // so this should not happen. - bigint_trap(); - } -} - -export void mp_free(void *ptr, size_t size) { -} - -/* Wrapper functions for libtommath */ - -#include -#define BIGINT_PAYLOAD(p) ((mp_int *)(&FIELD(p,1))) - -/* -Note on libtommath error handling - -Most libtommath operations return an int to signal error codes. -These are (see tommath.h): - - #define MP_OKAY 0 / * ok result * / - #define MP_MEM -2 / * out of mem * / - #define MP_VAL -3 / * invalid input * / - #define MP_RANGE MP_VAL - #define MP_ITER -4 / * Max. iterations reached * / - -We will never hit MP_MEM, because our allocation functions trap if they cannot -allocate. But the others can happen (e.g. division by 0). In that case, -we call a trap function provided by the Wasm part of the runtime. -*/ - -#define CHECK(e) ((e == 0)?0:bigint_trap()) - -as_ptr bigint_alloc() { - as_ptr r = alloc_bytes (1*sizeof(void*) + sizeof(mp_int)); - FIELD(r, 0) = TAG_BIGINT; - CHECK(mp_init(BIGINT_PAYLOAD(r))); - return r; -} - -export as_ptr bigint_of_word32(uint32_t b) { - as_ptr r = bigint_alloc(); - mp_set_u32(BIGINT_PAYLOAD(r), b); - return r; -} - -export as_ptr bigint_of_word32_signed(int32_t b) { - as_ptr r = bigint_alloc(); - mp_int *n = BIGINT_PAYLOAD(r); - mp_set_i32(n, b); - return r; -} - -export uint32_t bigint_to_word32_wrap(as_ptr a) { - mp_int *n = BIGINT_PAYLOAD(a); - return mp_get_u32(n); -} - -export uint32_t bigint_to_word32_trap(as_ptr a) { - mp_int *n = BIGINT_PAYLOAD(a); - if (mp_isneg(n)) bigint_trap(); - if (mp_count_bits(n) > 32) bigint_trap(); - return mp_get_u32(n); -} - -export int32_t bigint_to_word32_signed_trap(as_ptr a) { - mp_int *n = BIGINT_PAYLOAD(a); - if (mp_count_bits(n) > 32) bigint_trap(); - if (mp_isneg(n)) { - int32_t x = - (int32_t)(mp_get_mag_u32(n)); - if (x >= 0) bigint_trap(); - return x; - } else { - int32_t x = (int32_t)(mp_get_mag_u32(n)); - if (x < 0) bigint_trap(); - return x; - } -} - -export uint64_t bigint_to_word64_wrap(as_ptr a) { - mp_int *n = BIGINT_PAYLOAD(a); - return mp_get_u64(n); -} - -export uint64_t bigint_to_word64_trap(as_ptr a) { - mp_int *n = BIGINT_PAYLOAD(a); - if (mp_isneg(n)) bigint_trap(); - if (mp_count_bits(n) > 64) bigint_trap(); - return mp_get_u64(n); -} - -export int64_t bigint_to_word64_signed_trap(as_ptr a) { - mp_int *n = BIGINT_PAYLOAD(a); - if (mp_count_bits(n) > 64) bigint_trap(); - if (mp_isneg(n)) { - int64_t x = - (int64_t)(mp_get_mag_u64(n)); - if (x >= 0) bigint_trap(); - return x; - } else { - int64_t x = (int64_t)(mp_get_mag_u64(n)); - if (x < 0) bigint_trap(); - return x; - } -} - -export as_ptr bigint_of_word64(uint64_t b) { - as_ptr r = bigint_alloc(); - mp_set_u64(BIGINT_PAYLOAD(r), b); - return r; -} - -export as_ptr bigint_of_word64_signed(int64_t b) { - as_ptr r = bigint_alloc(); - mp_int *n = BIGINT_PAYLOAD(r); - mp_set_i64(n, b); - return r; -} - -export bool bigint_eq(as_ptr a, as_ptr b) { - return mp_cmp(BIGINT_PAYLOAD(a), BIGINT_PAYLOAD(b)) == 0; -} -export bool bigint_lt(as_ptr a, as_ptr b) { - return mp_cmp(BIGINT_PAYLOAD(a), BIGINT_PAYLOAD(b)) < 0; -} -export bool bigint_gt(as_ptr a, as_ptr b) { - return mp_cmp(BIGINT_PAYLOAD(a), BIGINT_PAYLOAD(b)) > 0; -} -export bool bigint_le(as_ptr a, as_ptr b) { - return mp_cmp(BIGINT_PAYLOAD(a), BIGINT_PAYLOAD(b)) <= 0; -} -export bool bigint_ge(as_ptr a, as_ptr b) { - return mp_cmp(BIGINT_PAYLOAD(a), BIGINT_PAYLOAD(b)) >= 0; -} - -export as_ptr bigint_add(as_ptr a, as_ptr b) { - as_ptr r = bigint_alloc(); - CHECK(mp_add(BIGINT_PAYLOAD(a), BIGINT_PAYLOAD(b), BIGINT_PAYLOAD(r))); - return r; -} - -export as_ptr bigint_sub(as_ptr a, as_ptr b) { - as_ptr r = bigint_alloc(); - CHECK(mp_sub(BIGINT_PAYLOAD(a), BIGINT_PAYLOAD(b), BIGINT_PAYLOAD(r))); - return r; -} - -export as_ptr bigint_mul(as_ptr a, as_ptr b) { - as_ptr r = bigint_alloc(); - CHECK(mp_mul(BIGINT_PAYLOAD(a), BIGINT_PAYLOAD(b), BIGINT_PAYLOAD(r))); - return r; -} - -export as_ptr bigint_pow(as_ptr a, as_ptr b) { - uint32_t exp = bigint_to_word32_trap(b); - as_ptr r = bigint_alloc(); - CHECK(mp_expt_u32(BIGINT_PAYLOAD(a), exp, BIGINT_PAYLOAD(r))); - return r; -} - -export as_ptr bigint_div(as_ptr a, as_ptr b) { - as_ptr r = bigint_alloc(); - mp_int rem; - CHECK(mp_init(&rem)); - CHECK(mp_div(BIGINT_PAYLOAD(a), BIGINT_PAYLOAD(b), BIGINT_PAYLOAD(r), &rem)); - return r; -} - -export as_ptr bigint_rem(as_ptr a, as_ptr b) { - as_ptr r = bigint_alloc(); - mp_int quot; - CHECK(mp_init(")); - CHECK(mp_div(BIGINT_PAYLOAD(a), BIGINT_PAYLOAD(b), ", BIGINT_PAYLOAD(r))); - return r; -} - -export as_ptr bigint_neg(as_ptr a) { - as_ptr r = bigint_alloc(); - CHECK(mp_neg(BIGINT_PAYLOAD(a), BIGINT_PAYLOAD(r))); - return r; -} - -export as_ptr bigint_abs(as_ptr a) { - as_ptr r = bigint_alloc(); - CHECK(mp_abs(BIGINT_PAYLOAD(a), BIGINT_PAYLOAD(r))); - return r; -} - -export bool bigint_isneg(as_ptr a) { - return mp_isneg(BIGINT_PAYLOAD(a)); -} - -export as_ptr bigint_lsh(as_ptr a, int b) { - as_ptr r = bigint_alloc(); - CHECK(mp_mul_2d(BIGINT_PAYLOAD(a), b, BIGINT_PAYLOAD(r))); - return r; -} - -export int bigint_count_bits(as_ptr a) { - return mp_count_bits(BIGINT_PAYLOAD(a)); -} - -/* LEB128 Encoding-decoding */ -export int bigint_leb128_size(as_ptr n) { - if (mp_iszero(BIGINT_PAYLOAD(n))) return 1; - int x = bigint_count_bits(n); - return ((x + 6) / 7); // divide by 7, round up -} - -void leb128_encode_go(mp_int *tmp, unsigned char *buf) { - // now the number should be positive - if (mp_isneg(tmp)) bigint_trap(); - while (true) { - buf[0] = (char)(mp_get_u32(tmp)); // get low bits - CHECK(mp_div_2d(tmp, 7, tmp, NULL)); - if (mp_iszero(tmp)) { - // we are done. high bit should be cleared anyways - return; - } else { - // more bytes to come, set high bit and continue - buf[0] |= 1<<7; - buf++; - } - } -} - -export void bigint_leb128_encode(as_ptr n, unsigned char *buf) { - mp_int tmp; - CHECK(mp_init_copy(&tmp, BIGINT_PAYLOAD(n))); - leb128_encode_go(&tmp, buf); -} - - -int leb128_encoding_size(unsigned char *buf) { - // zoom to the end - int i = 0; - while (buf[i] & (1<<7)) i++; - return i+1; -} - -as_ptr leb128_decode_go(unsigned char *buf, int bytes) { - // do not accept overlong encodings - if (buf[bytes-1] == 1<<7) bigint_trap(); - - as_ptr r = bigint_alloc(); - CHECK(mp_init(BIGINT_PAYLOAD(r))); - int i = bytes-1; - while (true) { - CHECK(mp_add_d(BIGINT_PAYLOAD(r), buf[i] & ((1<<7)-1), BIGINT_PAYLOAD(r))); - if (i > 0) { - CHECK(mp_mul_2d(BIGINT_PAYLOAD(r), 7, BIGINT_PAYLOAD(r))); - i--; - } else { - break; - } - } - return r; -} - -export as_ptr bigint_leb128_decode(unsigned char *buf) { - int bytes = leb128_encoding_size(buf); - return leb128_decode_go(buf, bytes); -} - -/* SLEB128 Encoding-decoding */ -export int bigint_2complement_bits(as_ptr n) { - if (mp_isneg(BIGINT_PAYLOAD(n))) { - mp_int tmp; - CHECK(mp_init_copy(&tmp, BIGINT_PAYLOAD(n))); - CHECK(mp_incr(&tmp)); - return 1 + mp_count_bits(&tmp); - } else { - return 1 + mp_count_bits(BIGINT_PAYLOAD(n)); - } -} - -export int bigint_sleb128_size(as_ptr n) { - int x = bigint_2complement_bits(n); - return ((x + 6) / 7); // divide by 7, round up -} - -export void bigint_sleb128_encode(as_ptr n, unsigned char *buf) { - mp_int tmp; - CHECK(mp_init_copy(&tmp, BIGINT_PAYLOAD(n))); - - if (mp_isneg(&tmp)) { - // turn negative numbers into the two's complement of the right size - int bytes = bigint_sleb128_size(n); - mp_int big; - CHECK(mp_init(&big)); - CHECK(mp_2expt(&big, 7*bytes)); - CHECK(mp_add(&tmp, &big, &tmp)); - } - - leb128_encode_go(&tmp, buf); -} - -export as_ptr bigint_sleb128_decode(unsigned char *buf) { - int bytes = leb128_encoding_size(buf); - - as_ptr r = leb128_decode_go(buf, bytes); - - // Now adjust sign if necessary - if (buf[bytes-1] & (1<<6)) { - // negative number - mp_int big; - CHECK(mp_init(&big)); - CHECK(mp_2expt(&big, 7*bytes)); - CHECK(mp_sub(BIGINT_PAYLOAD(r), &big, BIGINT_PAYLOAD(r))); - } - - return r; -} diff --git a/rts/rts.h b/rts/rts.h new file mode 100644 index 00000000000..552363300b4 --- /dev/null +++ b/rts/rts.h @@ -0,0 +1,66 @@ +#pragma GCC diagnostic ignored "-Wattributes" +#pragma GCC diagnostic ignored "-Wincompatible-library-redeclaration" +#define export __attribute__ ((visibility("default"))) +#define from_rts __attribute__ ((import_module("env"))) extern + +#include +#include +#include + +/* +ActorScript pointers are offset by one. So let us represent +them as a typedef, and access the fields using the payload macro. +*/ +typedef intptr_t as_ptr; +#define FIELD(p,n) (((size_t *)(p+1))[n]) +#define TAG(p) FIELD(p,0) +#define TEXT_LEN(p) ((char *)(&FIELD(p,1))) +#define TEXT_PAYLOAD(p) ((char *)(&FIELD(p,2))) + +/* Heap tags. Needs to stay in sync with compile.ml */ +enum as_heap_tag { + TAG_INVALID = 0, + TAG_OBJECT = 1, + TAG_OBJIND = 2, + TAG_ARRAY = 3, + TAG_REFERENCE = 4, + TAG_INT = 5, + TAG_MUTBOX = 6, + TAG_CLOSURE = 7, + TAG_SOME = 8, + TAG_VARIANT = 9, + TAG_TEXT = 10, + TAG_INDIRECTION = 11, + TAG_SMALLWORD = 12, + TAG_BIGINT = 13, + }; + +/** Functions imported from the ActorScript RTS */ + +/* +Ideally I’d do something like this + + __attribute__((global)) extern char* heap_ptr; + export char* alloc_bytes(int n) { + char *r = heap_ptr; + heap_ptr += (n + 3) & ~0x03; + return r; + } + +But seems we can’t import mutable globals like that, +see https://bugs.llvm.org/show_bug.cgi?id=41610 + +So in order to allocate on the ActorScript heap from C, we import +alloc_bytes from the Actorscript RTS: +*/ +from_rts as_ptr alloc_bytes(size_t n); + + +/* IDL code */ +/*@ assigns \nothing; ensures \false ; */ +from_rts __attribute__ ((noreturn)) void idl_trap(); +from_rts __attribute__ ((noreturn)) void bigint_trap(); + +/** Functions used in multiple modules of the RTS */ +export void as_memcpy(char *str1, const char *str2, size_t n); + diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 42486dcceb2..b8793e2287a 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -531,7 +531,7 @@ module RTS = struct let system_imports env = E.add_func_import env "rts" "as_memcpy" [I32Type; I32Type; I32Type] []; E.add_func_import env "rts" "version" [] [I32Type]; - E.add_func_import env "rts" "skip_idl_header" [I32Type] [I32Type]; + E.add_func_import env "rts" "skip_idl_header" [I32Type; I32Type] [I32Type]; E.add_func_import env "rts" "bigint_of_word32" [I32Type] [I32Type]; E.add_func_import env "rts" "bigint_of_word32_signed" [I32Type] [I32Type]; E.add_func_import env "rts" "bigint_to_word32_wrap" [I32Type] [I32Type]; @@ -3488,7 +3488,9 @@ module Serialization = struct Dfinity.system_call env "data_internalize" ^^ (* Go! *) - get_data_start ^^ E.call_import env "rts" "skip_idl_header" ^^ + get_data_start ^^ + get_data_start ^^ get_data_size ^^ G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ + E.call_import env "rts" "skip_idl_header" ^^ get_refs_start ^^ compile_add_const Heap.word_size ^^ deserialize_go env t ^^ G.i Drop ^^ From 6468c7e50ac1c21252aa3c47d4a892440bdb65a9 Mon Sep 17 00:00:00 2001 From: Norton Wang Date: Mon, 22 Jul 2019 09:55:14 -0700 Subject: [PATCH 0300/1176] Publish asc.tar as build product (#580) * Publish asc.tar as build product * Use relative paths in tarballs * Tarball should use unwrapped asc * Move asc-tar to seperate derivation * Specify darwin and linux builds in ci.nix --- ci.nix | 2 ++ default.nix | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/ci.nix b/ci.nix index 6b56ac1e2ab..6e984224b1a 100644 --- a/ci.nix +++ b/ci.nix @@ -10,6 +10,8 @@ let in linux // { darwin = darwin.all-systems-go; + asc-tar-x86_64-darwin = darwin.asc-tar; + asc-tar-x86_64-linux = linux.asc-tar; all-systems-go = inject-rev (nixpkgs.releaseTools.aggregate { name = "all-systems-go"; constituents = [ diff --git a/default.nix b/default.nix index 6ff6489ba10..35af0969e36 100644 --- a/default.nix +++ b/default.nix @@ -138,6 +138,16 @@ rec { ''; }; + asc-tar = nixpkgs.symlinkJoin { + name = "asc-tar"; + paths = [ asc-bin rts ]; + postBuild = '' + tar -chf $out/asc.tar -C $out bin/asc rts/as-rts.wasm + mkdir -p $out/nix-support + echo "file bin $out/asc.tar" >> $out/nix-support/hydra-build-products + ''; + }; + tests = stdenv.mkDerivation { name = "tests"; src = subpath ./test; @@ -320,7 +330,7 @@ rec { ''; installPhase = '' mkdir -p $out - tar -rf $out/stdlib.tar $src + tar -rf $out/stdlib.tar -C $src *.as mkdir -p $out/nix-support echo "report stdlib $out/stdlib.tar" >> $out/nix-support/hydra-build-products ''; @@ -356,7 +366,7 @@ rec { ''; installPhase = '' mkdir -p $out - tar -rf $out/stdlib-doc.tar doc + tar -rf $out/stdlib-doc.tar -C doc . mkdir -p $out/nix-support echo "report stdlib-doc $out/stdlib-doc.tar" >> $out/nix-support/hydra-build-products ''; From 0e8fd277e04ad7bbbb6d6d02f844cafe682b5dac Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Mon, 22 Jul 2019 13:44:50 -0700 Subject: [PATCH 0301/1176] build didc.tar for SDK build tool --- default.nix | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/default.nix b/default.nix index 35af0969e36..dd8e2c69242 100644 --- a/default.nix +++ b/default.nix @@ -285,6 +285,16 @@ rec { ''; }; + didc-tar = nixpkgs.symlinkJoin { + name = "didc-tar"; + paths = didc; + postBuild = '' + tar -chf $out/didc.tar -C $out bin/didc + mkdir -p $out/nix-support + echo "file bin $out/didc.tar" >> $out/nix-support/hydra-build-products + ''; + }; + wasm = ocaml_wasm; dvm = real-dvm; filecheck = nixpkgs.linkFarm "FileCheck" From 12323688f463c9c2583d68b3cc399084bdcfe6f2 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Mon, 22 Jul 2019 13:54:52 -0700 Subject: [PATCH 0302/1176] update ci.nix --- ci.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ci.nix b/ci.nix index 6e984224b1a..001e52a0711 100644 --- a/ci.nix +++ b/ci.nix @@ -12,6 +12,8 @@ linux // { darwin = darwin.all-systems-go; asc-tar-x86_64-darwin = darwin.asc-tar; asc-tar-x86_64-linux = linux.asc-tar; + didc-tar-x86_64-darwin = darwin.didc-tar; + didc-tar-x86_64-linux = linux.didc-tar; all-systems-go = inject-rev (nixpkgs.releaseTools.aggregate { name = "all-systems-go"; constituents = [ From aa8983ce63a255e041300213a3ff2cf656f1d952 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Mon, 22 Jul 2019 16:09:22 -0700 Subject: [PATCH 0303/1176] add didc to asc.tar --- ci.nix | 2 -- default.nix | 14 ++------------ 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/ci.nix b/ci.nix index 001e52a0711..6e984224b1a 100644 --- a/ci.nix +++ b/ci.nix @@ -12,8 +12,6 @@ linux // { darwin = darwin.all-systems-go; asc-tar-x86_64-darwin = darwin.asc-tar; asc-tar-x86_64-linux = linux.asc-tar; - didc-tar-x86_64-darwin = darwin.didc-tar; - didc-tar-x86_64-linux = linux.didc-tar; all-systems-go = inject-rev (nixpkgs.releaseTools.aggregate { name = "all-systems-go"; constituents = [ diff --git a/default.nix b/default.nix index dd8e2c69242..1057fe9ccb9 100644 --- a/default.nix +++ b/default.nix @@ -140,9 +140,9 @@ rec { asc-tar = nixpkgs.symlinkJoin { name = "asc-tar"; - paths = [ asc-bin rts ]; + paths = [ asc-bin rts didc ]; postBuild = '' - tar -chf $out/asc.tar -C $out bin/asc rts/as-rts.wasm + tar -chf $out/asc.tar -C $out bin/asc rts/as-rts.wasm bin/didc mkdir -p $out/nix-support echo "file bin $out/asc.tar" >> $out/nix-support/hydra-build-products ''; @@ -285,16 +285,6 @@ rec { ''; }; - didc-tar = nixpkgs.symlinkJoin { - name = "didc-tar"; - paths = didc; - postBuild = '' - tar -chf $out/didc.tar -C $out bin/didc - mkdir -p $out/nix-support - echo "file bin $out/didc.tar" >> $out/nix-support/hydra-build-products - ''; - }; - wasm = ocaml_wasm; dvm = real-dvm; filecheck = nixpkgs.linkFarm "FileCheck" From fd57a619cc4d8097c8cc8429ba3c8ff70902dcfd Mon Sep 17 00:00:00 2001 From: Paul Young Date: Tue, 9 Jul 2019 15:19:32 +0100 Subject: [PATCH 0304/1176] [WIP] Rx --- default.nix | 20 ++++++++++++++++++++ rx/Makefile | 36 ++++++++++++++++++++++++++++++++++++ rx/src/Disposable.as | 21 +++++++++++++++++++++ rx/src/Event.as | 7 +++++++ rx/src/Observable.as | 16 ++++++++++++++++ rx/src/Observer.as | 17 +++++++++++++++++ rx/src/Rx.as | 3 +++ rx/test/RxTest.as | 33 +++++++++++++++++++++++++++++++++ 8 files changed, 153 insertions(+) create mode 100644 rx/Makefile create mode 100644 rx/src/Disposable.as create mode 100644 rx/src/Event.as create mode 100644 rx/src/Observable.as create mode 100644 rx/src/Observer.as create mode 100644 rx/src/Rx.as create mode 100644 rx/test/RxTest.as diff --git a/default.nix b/default.nix index 35af0969e36..d64ebb1efc0 100644 --- a/default.nix +++ b/default.nix @@ -393,6 +393,25 @@ rec { ''; }; + rx = stdenv.mkDerivation { + name = "rx-actorscript"; + src = subpath ./rx; + buildInputs = [ + asc + ]; + buildPhase = '' + make ASC=asc OUTDIR=_out _out/Rx.wasm + ''; + doCheck = true; + checkPhase = '' + make ASC=asc OUTDIR=_out _out/RxTest.out + ''; + installPhase = '' + mkdir -p $out + cp _out/Rx.wasm $out + ''; + }; + all-systems-go = nixpkgs.releaseTools.aggregate { name = "all-systems-go"; constituents = [ @@ -404,6 +423,7 @@ rec { unit-tests samples rts + rx stdlib stdlib-doc stdlib-doc-live diff --git a/rx/Makefile b/rx/Makefile new file mode 100644 index 00000000000..83482672f6f --- /dev/null +++ b/rx/Makefile @@ -0,0 +1,36 @@ +ASC=../src/asc +OUTDIR=_out + +MODULES=\ + RxTest \ + +WASM=\ + Rx \ + +OUTFILES=$(addsuffix .out, $(MODULES)) $(addsuffix .wasm, $(WASM)) + +OUTPATHS=$(addprefix $(OUTDIR)/, $(OUTFILES)) + +.PHONY: default all clean alltests + +default: all + +alltests: $(OUTDIR) $(OUTPATHS) + +all: alltests + +clean: + rm -rf $(OUTDIR) + +$(OUTDIR): + @mkdir $@ + +RX_ACTORSCRIPT_SRC=\ + src/Rx.as \ + +$(OUTDIR)/RxTest.out: $(RX_ACTORSCRIPT_SRC) \ + test/RxTest.as | $(OUTDIR) + $(ASC) -r test/RxTest.as > $@ + +$(OUTDIR)/Rx.wasm: $(RX_ACTORSCRIPT_SRC) | $(OUTDIR) + $(ASC) -c -o $@ src/Rx.as diff --git a/rx/src/Disposable.as b/rx/src/Disposable.as new file mode 100644 index 00000000000..7c3573e2702 --- /dev/null +++ b/rx/src/Disposable.as @@ -0,0 +1,21 @@ +module { + private type Params = { + dispose : () -> (); + }; + + class Type(params : Params) { + let dispose = params.dispose; + }; + + func init(params : Params) : Type { + Type(params); + }; + + // NOTE: we wrap this in a function because otherwise the compiler complains + // with "type error, non-static expression in library or module". + func empty() : Type { + Type(new { + dispose = func () {}; + }); + }; +}; diff --git a/rx/src/Event.as b/rx/src/Event.as new file mode 100644 index 00000000000..825b8b68166 --- /dev/null +++ b/rx/src/Event.as @@ -0,0 +1,7 @@ +module { + type Type = { + #next Value; + #error Error; + #completed; + }; +} diff --git a/rx/src/Observable.as b/rx/src/Observable.as new file mode 100644 index 00000000000..deea627127c --- /dev/null +++ b/rx/src/Observable.as @@ -0,0 +1,16 @@ +module { + import Disposable = "Disposable.as"; + import Observer = "Observer.as"; + + private type Params = { + subscribe : Observer.Type -> Disposable.Type; + }; + + class Type(params : Params) { + let subscribe = params.subscribe; + }; + + func init(params : Params) : Type { + Type(params); + }; +}; diff --git a/rx/src/Observer.as b/rx/src/Observer.as new file mode 100644 index 00000000000..dd9ad1f9fa3 --- /dev/null +++ b/rx/src/Observer.as @@ -0,0 +1,17 @@ +module { + private type Params = { + onNext : Value -> (); + onError : Error -> (); + onCompleted : () -> (); + }; + + class Type(params : Params) { + let onNext = params.onNext; + let onError = params.onError; + let onCompleted = params.onCompleted; + }; + + func init(params : Params) : Type { + Type(params); + }; +}; diff --git a/rx/src/Rx.as b/rx/src/Rx.as new file mode 100644 index 00000000000..4db80a2d144 --- /dev/null +++ b/rx/src/Rx.as @@ -0,0 +1,3 @@ +import Disposable = "Disposable.as"; +import Observable = "Observable.as"; +import Observer = "Observer.as"; diff --git a/rx/test/RxTest.as b/rx/test/RxTest.as new file mode 100644 index 00000000000..d4e0eda0ba7 --- /dev/null +++ b/rx/test/RxTest.as @@ -0,0 +1,33 @@ +import Rx = "../src/Rx.as"; + +func printLn(x : Text) { + print(x # "\n"); +}; + +type Error = { + description : Text; +}; + +let printLnObserver = Rx.Observer.init(new { + onNext = func (value : Int) { + printLn("onNext: " # debug_show(value)); + }; + onError = func (error : Error) { + printLn("onError: " # error.description); + }; + onCompleted = func () { + printLn("onCompleted"); + }; +}); + +let sequence = Rx.Observable.init(new { + subscribe = func (observer : Rx.Observer.Type) : Rx.Disposable.Type { + observer.onNext(1); + observer.onNext(2); + observer.onNext(3); + observer.onCompleted(); + Rx.Disposable.empty(); + }; +}); + +let disposable = sequence.subscribe(printLnObserver); From be21a48918af1f8d665bee3db08e893bf6b44921 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Mon, 22 Jul 2019 18:29:46 -0700 Subject: [PATCH 0305/1176] Add tests --- default.nix | 9 +-- rx/src/Disposable.as | 18 +++--- rx/src/Event.as | 8 +-- rx/src/Observable.as | 16 +++--- rx/src/Observer.as | 32 +++++++---- rx/src/Rx.as | 1 + rx/test/RxTest.as | 127 ++++++++++++++++++++++++++++++++++--------- stdlib/array.as | 18 ++++++ 8 files changed, 164 insertions(+), 65 deletions(-) create mode 100644 stdlib/array.as diff --git a/default.nix b/default.nix index d64ebb1efc0..64d827d20bc 100644 --- a/default.nix +++ b/default.nix @@ -395,20 +395,21 @@ rec { rx = stdenv.mkDerivation { name = "rx-actorscript"; - src = subpath ./rx; + src = subpath ./.; # FIXME: we only want ./rx and ./stdlib buildInputs = [ asc ]; buildPhase = '' - make ASC=asc OUTDIR=_out _out/Rx.wasm + make -C rx ASC=asc OUTDIR=_out _out/Rx.wasm ''; doCheck = true; checkPhase = '' - make ASC=asc OUTDIR=_out _out/RxTest.out + make -C rx ASC=asc OUTDIR=_out _out/RxTest.out ''; installPhase = '' mkdir -p $out - cp _out/Rx.wasm $out + # cp _out/Rx.wasm $out + cp rx/_out/Rx.wasm $out ''; }; diff --git a/rx/src/Disposable.as b/rx/src/Disposable.as index 7c3573e2702..22eb55ea01f 100644 --- a/rx/src/Disposable.as +++ b/rx/src/Disposable.as @@ -1,21 +1,17 @@ module { - private type Params = { - dispose : () -> (); - }; + type Dispose = () -> (); - class Type(params : Params) { - let dispose = params.dispose; + public class Type(dispose_ : Dispose) { + let dispose = dispose_; }; - func init(params : Params) : Type { - Type(params); + public func init(dispose : Dispose) : Type { + Type(dispose); }; // NOTE: we wrap this in a function because otherwise the compiler complains // with "type error, non-static expression in library or module". - func empty() : Type { - Type(new { - dispose = func () {}; - }); + public func empty() : Type { + Type(func () {}); }; }; diff --git a/rx/src/Event.as b/rx/src/Event.as index 825b8b68166..4dedcb8b00c 100644 --- a/rx/src/Event.as +++ b/rx/src/Event.as @@ -1,7 +1,7 @@ module { - type Type = { - #next Value; - #error Error; + public type Type = { + #next: Value; + #error: Error; #completed; }; -} +}; diff --git a/rx/src/Observable.as b/rx/src/Observable.as index deea627127c..d0a882972a9 100644 --- a/rx/src/Observable.as +++ b/rx/src/Observable.as @@ -1,16 +1,14 @@ module { - import Disposable = "Disposable.as"; - import Observer = "Observer.as"; + import Disposable "Disposable.as"; + import Observer "Observer.as"; - private type Params = { - subscribe : Observer.Type -> Disposable.Type; - }; + type Subscriber = Observer.Type -> Disposable.Type; - class Type(params : Params) { - let subscribe = params.subscribe; + public class Type(subscribe_ : Subscriber) { + public let subscribe = subscribe_; }; - func init(params : Params) : Type { - Type(params); + public func init(subscriber : Subscriber) : Type { + Type(subscriber); }; }; diff --git a/rx/src/Observer.as b/rx/src/Observer.as index dd9ad1f9fa3..b16a5b018aa 100644 --- a/rx/src/Observer.as +++ b/rx/src/Observer.as @@ -1,17 +1,27 @@ module { - private type Params = { - onNext : Value -> (); - onError : Error -> (); - onCompleted : () -> (); - }; + import Event "Event.as"; + + public type EventHandler = Event.Type -> (); + + public class Type(handler_ : EventHandler) { + let handler = handler_; + var isDone = false; - class Type(params : Params) { - let onNext = params.onNext; - let onError = params.onError; - let onCompleted = params.onCompleted; + public func send(event : Event.Type) : () { + if (isDone) { + return; + }; + handler(event); + switch (event) { + case (#next _) {}; + case _ { + isDone := true; + }; + }; + } }; - func init(params : Params) : Type { - Type(params); + public func init(send : EventHandler) : Type { + Type(send); }; }; diff --git a/rx/src/Rx.as b/rx/src/Rx.as index 4db80a2d144..60b1b8f3960 100644 --- a/rx/src/Rx.as +++ b/rx/src/Rx.as @@ -1,3 +1,4 @@ import Disposable = "Disposable.as"; +import Event = "Event.as"; import Observable = "Observable.as"; import Observer = "Observer.as"; diff --git a/rx/test/RxTest.as b/rx/test/RxTest.as index d4e0eda0ba7..7283d1160dc 100644 --- a/rx/test/RxTest.as +++ b/rx/test/RxTest.as @@ -1,33 +1,108 @@ -import Rx = "../src/Rx.as"; - -func printLn(x : Text) { - print(x # "\n"); -}; +import Array "../../stdlib/array.as"; +import Rx "../src/Rx.as"; type Error = { description : Text; }; -let printLnObserver = Rx.Observer.init(new { - onNext = func (value : Int) { - printLn("onNext: " # debug_show(value)); - }; - onError = func (error : Error) { - printLn("onError: " # error.description); - }; - onCompleted = func () { - printLn("onCompleted"); - }; -}); - -let sequence = Rx.Observable.init(new { - subscribe = func (observer : Rx.Observer.Type) : Rx.Disposable.Type { - observer.onNext(1); - observer.onNext(2); - observer.onNext(3); - observer.onCompleted(); - Rx.Disposable.empty(); +func assertEqualError(e1 : Error, e2 : Error) { + assert (e1.description == e2.description); +}; + +func assertEqualEvent( + ev1 : Rx.Event.Type, + ev2 : Rx.Event.Type, +) { + switch (ev1, ev2) { + case (#next v1, #next v2) { + assert (v1 == v2); + }; + case (#error e1, #error e2) { + assertEqualError(e1, e2); + }; + case (#completed, #completed) { + assert true; + }; + case _ { + assert false; + }; }; -}); +}; + +{ + var events : [Rx.Event.Type] = []; + + let observer = Rx.Observer.init( + func (event : Rx.Event.Type) { + events := Array.append>(events, [event]); + } + ); -let disposable = sequence.subscribe(printLnObserver); + let sequence = Rx.Observable.init( + func (observer : Rx.Observer.Type) : Rx.Disposable.Type { + observer.send(#next 1); + observer.send(#next 2); + observer.send(#next 3); + observer.send(#completed); + Rx.Disposable.empty(); + } + ); + + let disposable = sequence.subscribe(observer); + + assert (events.len() == 4); + assertEqualEvent(events[0], #next 1); + assertEqualEvent(events[1], #next 2); + assertEqualEvent(events[2], #next 3); + assertEqualEvent(events[3], #completed); +}; + +{ + var events : [Rx.Event.Type] = []; + + let observer = Rx.Observer.init( + func (event : Rx.Event.Type) { + events := Array.append>(events, [event]); + } + ); + + let sequence = Rx.Observable.init( + func (observer : Rx.Observer.Type) : Rx.Disposable.Type { + observer.send(#completed); + observer.send(#next 1); + observer.send(#error (new { description = "Error"; })); + observer.send(#completed); + Rx.Disposable.empty(); + } + ); + + let disposable = sequence.subscribe(observer); + + assert (events.len() == 1); + assertEqualEvent(events[0], #completed); +}; + +{ + var events : [Rx.Event.Type] = []; + + let observer = Rx.Observer.init( + func (event : Rx.Event.Type) { + events := Array.append>(events, [event]); + } + ); + + let sequence = Rx.Observable.init( + func (observer : Rx.Observer.Type) : Rx.Disposable.Type { + observer.send(#error (new { description = "Error"; })); + observer.send(#next 1); + observer.send(#error (new { description = "Another error"; })); + observer.send(#completed); + Rx.Disposable.empty(); + } + ); + + let disposable = sequence.subscribe(observer); + + assert (events.len() == 1); + assertEqualEvent(events[0], #error (new { description = "Error"; })); +}; diff --git a/stdlib/array.as b/stdlib/array.as new file mode 100644 index 00000000000..bcb91ec6516 --- /dev/null +++ b/stdlib/array.as @@ -0,0 +1,18 @@ +module { + public func append(xs : [A], ys : [A]) : [A] { + switch(xs.len(), ys.len()) { + case (0, 0) { []; }; + case (0, _) { ys; }; + case (_, 0) { xs; }; + case (xsLen, ysLen) { + Array_tabulate(xsLen + ysLen, func (i : Nat) : A { + if (i < xsLen) { + xs[i]; + } else { + ys[i - xsLen]; + }; + }); + }; + }; + }; +} From d414f8b506519a401752609321e4bcfb6a233ac5 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 23 Jul 2019 11:58:22 +0100 Subject: [PATCH 0306/1176] lub/glb for T.Typ fields (#592) * lub/glb for T.Typ fields * add missing test output * address Gabor's review, cleanup negative test and test for arity mismatch --- src/as_types/type.ml | 66 +++++++++++++++--- test/fail/ok/typ-field-lub-glb-fail.tc.ok | 12 ++++ test/fail/typ-field-lub-glb-fail.as | 27 ++++++++ test/run/typ-field-lub-glb.as | 83 +++++++++++++++++++++++ 4 files changed, 177 insertions(+), 11 deletions(-) create mode 100644 test/fail/ok/typ-field-lub-glb-fail.tc.ok create mode 100644 test/fail/typ-field-lub-glb-fail.as create mode 100644 test/run/typ-field-lub-glb.as diff --git a/src/as_types/type.ml b/src/as_types/type.ml index d65439098ac..194ccc220e6 100644 --- a/src/as_types/type.ml +++ b/src/as_types/type.ml @@ -638,7 +638,7 @@ let rec rel_typ rel eq t1 t2 = | Serialized t1', Serialized t2' -> rel_typ rel eq t1' t2' | Typ c1, Typ c2 -> - Con.eq c1 c2 + eq_con eq c1 c2 | _, _ -> false end @@ -695,8 +695,7 @@ and eq t1 t2 : bool = and sub t1 t2 : bool = rel_typ (ref SS.empty) (ref SS.empty) t1 t2 -and eq_kind k1 k2 : bool = - let eq = ref SS.empty in +and eq_kind' eq k1 k2 : bool = match k1, k2 with | Def (tbs1, t1), Def (tbs2, t2) | Abs (tbs1, t1), Abs (tbs2, t2) -> @@ -706,6 +705,20 @@ and eq_kind k1 k2 : bool = ) | _ -> false +and eq_con eq c1 c2 = + match Con.kind c1, Con.kind c2 with + | (Def (tbs1, t1)) as k1, (Def (tbs2, t2) as k2) -> + eq_kind' eq k1 k2 + | Abs _, Abs _ -> + Con.eq c1 c2 + | Def (tbs1, t1), Abs (tbs2, t2) + | Abs (tbs2, t2), Def (tbs1, t1) -> + (match rel_binds eq eq tbs1 tbs2 with + | Some ts -> eq_typ eq eq (open_ ts t1) (Con (c2, ts)) + | None -> false + ) + +let eq_kind k1 k2 : bool = eq_kind' (ref SS.empty) k1 k2 (* Compatibility *) @@ -850,6 +863,8 @@ let rec lub' lubs glbs t1 t2 = | _, Con _ -> (* TODO(rossberg): fix handling of bounds *) combine_con_parts t1 t2 "lub" lubs (lub' lubs glbs) + | Typ _, _ + | _, Typ _ -> assert false | _ when eq t1 t2 -> t1 | _ -> Any @@ -860,7 +875,17 @@ and lub_fields lubs glbs fs1 fs2 = match fs1, fs2 with match compare_field f1 f2 with | -1 -> lub_fields lubs glbs fs1' fs2 | +1 -> lub_fields lubs glbs fs1 fs2' - | _ -> {f1 with typ = lub' lubs glbs f1.typ f2.typ}::lub_fields lubs glbs fs1' fs2' + | _ -> + match f1.typ, f2.typ with + | Typ _, Typ _ -> + if eq f1.typ f2.typ then + f1::lub_fields lubs glbs fs1' fs2' + else + lub_fields lubs glbs fs1' fs2' + | Typ _, _ + | _, Typ _ -> assert false + | _, _ -> + {f1 with typ = lub' lubs glbs f1.typ f2.typ}::lub_fields lubs glbs fs1' fs2' and lub_tags lubs glbs fs1 fs2 = match fs1, fs2 with | fs1, [] -> fs1 @@ -896,7 +921,9 @@ and glb' lubs glbs t1 t2 = | Array t1', Array t2' -> Array (glb' lubs glbs t1' t2') | Obj (s1, tf1), Obj (s2, tf2) when s1 = s2 -> - Obj (s1, glb_fields lubs glbs tf1 tf2) + (match glb_fields lubs glbs tf1 tf2 with + | None -> Non + | Some fs -> Obj (s1, fs)) | Func (s1, c1, bs1, args1, res1), Func (s2, c2, bs2, args2, res2) when s1 = s2 && c1 = c2 && List.(length bs1 = length bs2) && List.(length args1 = length args2 && length res1 = length res2) -> @@ -907,17 +934,34 @@ and glb' lubs glbs t1 t2 = | _, Con _ -> (* TODO(rossberg): fix handling of bounds *) combine_con_parts t1 t2 "glb" glbs (glb' lubs glbs) + | Typ _, _ + | _, Typ _ -> assert false | _ when eq t1 t2 -> t1 | _ -> Non -and glb_fields lubs glbs fs1 fs2 = match fs1, fs2 with - | fs1, [] -> fs1 - | [], fs2 -> fs2 +and glb_fields lubs glbs fs1 fs2 : field list option = + let (+?) h t_opt = match t_opt with + | None -> None + | Some t -> Some (h::t) + in + match fs1, fs2 with + | fs1, [] -> Some fs1 + | [], fs2 -> Some fs2 | f1::fs1', f2::fs2' -> match compare_field f1 f2 with - | -1 -> f1::glb_fields lubs glbs fs1' fs2 - | +1 -> f2::glb_fields lubs glbs fs1 fs2' - | _ -> {f1 with typ = glb' lubs glbs f1.typ f2.typ}::glb_fields lubs glbs fs1' fs2' + | -1 -> f1 +? glb_fields lubs glbs fs1' fs2 + | +1 -> f2 +? glb_fields lubs glbs fs1 fs2' + | _ -> + match f1.typ, f2.typ with + | Typ _, Typ _ -> + if eq f1.typ f2.typ then + f1 +? glb_fields lubs glbs fs1' fs2' + else + None + | Typ _, _ + | _, Typ _ -> assert false + | _, _ -> + {f1 with typ = glb' lubs glbs f1.typ f2.typ} +? glb_fields lubs glbs fs1' fs2' and glb_tags lubs glbs fs1 fs2 = match fs1, fs2 with | fs1, [] -> [] diff --git a/test/fail/ok/typ-field-lub-glb-fail.tc.ok b/test/fail/ok/typ-field-lub-glb-fail.tc.ok new file mode 100644 index 00000000000..7a8d1ad52ed --- /dev/null +++ b/test/fail/ok/typ-field-lub-glb-fail.tc.ok @@ -0,0 +1,12 @@ +typ-field-lub-glb-fail.as:14.31-14.35: type error, expression of type + Cx = {x : Nat} +cannot produce expected type + {type T = Int; x : Nat} +typ-field-lub-glb-fail.as:15.31-15.35: type error, expression of type + Ct = {type T = Int} +cannot produce expected type + {type T = Int; x : Nat} +typ-field-lub-glb-fail.as:21.29-21.30: type error, type field T does not exist in type + {x : Nat} +typ-field-lub-glb-fail.as:27.29-27.30: type error, type field T does not exist in type + {x : Nat} diff --git a/test/fail/typ-field-lub-glb-fail.as b/test/fail/typ-field-lub-glb-fail.as new file mode 100644 index 00000000000..1172222b8bd --- /dev/null +++ b/test/fail/typ-field-lub-glb-fail.as @@ -0,0 +1,27 @@ +class Ctx() { + public type T = Int; + public let x = 0; +}; + +class Ct() { + public type T = Int; +}; + +class Cx() { + public let x = 1; +}; + +let wrong1 : [Ctx] = [ Ctx(), Cx() ]; //wrong +let wrong2 : [Ctx] = [ Ctx(), Ct() ]; //wrong + +let ox = + [ object { public type T = Int; public let x = 1 }, + object { public type T = Bool; public let x = 2 } ][0]; + +func wrong3() { type U = ox.T }; // wrong, type component mismatch + +let px = + [ object { public type T = Int; public let x = 1 }, + object { public type T = Int; public let x = 2 } ][0]; + +func wrong4() { type U = px.T }; // wrong, type component arity mismatch diff --git a/test/run/typ-field-lub-glb.as b/test/run/typ-field-lub-glb.as new file mode 100644 index 00000000000..50b914ac0e8 --- /dev/null +++ b/test/run/typ-field-lub-glb.as @@ -0,0 +1,83 @@ +class Ctx() { + public type T = Int; + public let x = 0; +}; + +class Ctx2() { + public type T = Int; + public let x : Int = 0 +}; + +class Cty() { + public type T = Int; + public let y = true +}; + + +class Ct() { + public type T = Int; +}; + +class Cx() { + public let x = 1; +}; + +class Dtx() { + public type T = Bool; + public let x = 1 +}; + +let _ : [Ctx] = [ Ctx(), Ctx() ]; +let _ : [Ct] = [ Ct(), Ctx() ]; +let _ : [Ct] = [ Ctx(), Ct() ]; + +// let _ : [Ctx] = [ Ctx(), Cx() ]; //wrong +// let _ : [Ctx] = [ Ctx(), Ct() ]; //wrong + +let _ : [Cx] = [ Ctx(), Cx() ]; +let _ : [Cx] = [ Cx(), Ctx() ]; + +let _ : [Cx] = [ Dtx(), Cx() ]; +let _ : [Cx] = [ Dtx(), Ctx() ]; +let _ : Any = [ Dtx(), Ctx() ]; + +let _ : [Cx] = [ Ctx(), Dtx() ]; + +let otx : Ctx = + [ object { public type T = Int; public let x = 1 }, + object { public type T = Int; public let x = 2 } ][0]; + +func oktx() { type U = otx.T; let x:Nat = otx.x }; + +let ox = + [ object { public type T = Int; public let x = 1 }, + object { public type T = Bool; public let x = 2 } ][0]; + +func okx() { let x : Nat = ox.x }; + +// func wrong3() { type U = ox.T }; + +let _ : [ Ctx -> () ] = [ + func (_ : Ctx) {}, + func (_ : Ctx) {} +]; + +let _ : [ None -> () ] = [ + func (_ : Cx) {}, + func (_ : Ct) {} +]; + +let _ : [ None -> () ] = [ + func (_ : Ctx) {}, + func (_ : Cty) {} +]; + +let _ : [ Ctx -> () ] = [ + func (_ : Ctx) {}, + func (_ : Ctx2) {} +]; + +let _ : [ None -> () ] = [ + func (_ : Dtx) {}, + func (_ : Ctx) {} +]; From 9e2ec1e8c302733a89a3ca4011681c02d872438d Mon Sep 17 00:00:00 2001 From: Paul Young Date: Tue, 23 Jul 2019 10:25:03 -0700 Subject: [PATCH 0307/1176] Update src --- default.nix | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/default.nix b/default.nix index 64d827d20bc..977676f7aae 100644 --- a/default.nix +++ b/default.nix @@ -395,7 +395,11 @@ rec { rx = stdenv.mkDerivation { name = "rx-actorscript"; - src = subpath ./.; # FIXME: we only want ./rx and ./stdlib + src = null; + unpackPhase = '' + cp -R --no-preserve=mode ${subpath ./rx} rx + cp -R --no-preserve=mode ${subpath ./stdlib} stdlib + ''; buildInputs = [ asc ]; @@ -408,7 +412,6 @@ rec { ''; installPhase = '' mkdir -p $out - # cp _out/Rx.wasm $out cp rx/_out/Rx.wasm $out ''; }; From 511b979e2efff2802c96f43583a135129bfc8126 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Tue, 23 Jul 2019 10:34:05 -0700 Subject: [PATCH 0308/1176] Set sourceRoot instead --- default.nix | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/default.nix b/default.nix index 977676f7aae..2d26058e559 100644 --- a/default.nix +++ b/default.nix @@ -395,11 +395,11 @@ rec { rx = stdenv.mkDerivation { name = "rx-actorscript"; - src = null; - unpackPhase = '' - cp -R --no-preserve=mode ${subpath ./rx} rx - cp -R --no-preserve=mode ${subpath ./stdlib} stdlib - ''; + sourceRoot = ./.; + src = [ + (subpath ./rx) + (subpath ./stdlib) + ]; buildInputs = [ asc ]; From c852a08eeb04a27126e4eda3f7572fa151f16859 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Tue, 23 Jul 2019 10:50:33 -0700 Subject: [PATCH 0309/1176] Revert "Set sourceRoot instead" This reverts commit 511b979e2efff2802c96f43583a135129bfc8126. --- default.nix | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/default.nix b/default.nix index 2d26058e559..977676f7aae 100644 --- a/default.nix +++ b/default.nix @@ -395,11 +395,11 @@ rec { rx = stdenv.mkDerivation { name = "rx-actorscript"; - sourceRoot = ./.; - src = [ - (subpath ./rx) - (subpath ./stdlib) - ]; + src = null; + unpackPhase = '' + cp -R --no-preserve=mode ${subpath ./rx} rx + cp -R --no-preserve=mode ${subpath ./stdlib} stdlib + ''; buildInputs = [ asc ]; From d0fd4d4252d6e038c632a77f1c2a4a8ac36220ea Mon Sep 17 00:00:00 2001 From: Paul Young Date: Tue, 23 Jul 2019 11:56:50 -0700 Subject: [PATCH 0310/1176] Run the stdlib tests --- default.nix | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/default.nix b/default.nix index 1057fe9ccb9..50f6a3a45d8 100644 --- a/default.nix +++ b/default.nix @@ -328,6 +328,14 @@ rec { buildPhase = '' patchShebangs . ''; + doCheck = true; + checkInputs = [ + asc + nixpkgs.python + ]; + checkPhase = '' + make ASC=${asc}/bin/asc alltests + ''; installPhase = '' mkdir -p $out tar -rf $out/stdlib.tar -C $src *.as From 0cef3edeab76421f48052abc82b504a346b3e72e Mon Sep 17 00:00:00 2001 From: Paul Young Date: Tue, 23 Jul 2019 11:58:01 -0700 Subject: [PATCH 0311/1176] Bring stdlib tests up to date --- .../produce-exchange/test/evalBulk.as | 142 +++++++++--------- .../test/producerRemInventory.as | 142 +++++++++--------- .../test/retailerReserveMany.as | 2 +- 3 files changed, 143 insertions(+), 143 deletions(-) diff --git a/stdlib/examples/produce-exchange/test/evalBulk.as b/stdlib/examples/produce-exchange/test/evalBulk.as index 1bfd42e3035..92256729b5a 100644 --- a/stdlib/examples/produce-exchange/test/evalBulk.as +++ b/stdlib/examples/produce-exchange/test/evalBulk.as @@ -16,7 +16,7 @@ func printLabeledCost(lab:Text, cost:Nat) { }; actor class Test() = this { - go() { + public func go() { ignore(async { let s = A.Server(); @@ -32,82 +32,82 @@ actor class Test() = this { let bulkResp = s.evalBulkArray( [ #add([ - #truckType (shared { id=0; short_name="tta"; description=""; capacity=10; isFridge=false; isFreezer=false }), - #truckType (shared { id=1; short_name="ttb"; description=""; capacity=20; isFridge=false; isFreezer=false }), - #truckType (shared { id=2; short_name="ttc"; description=""; capacity=30; isFridge=true; isFreezer=false }), - #truckType (shared { id=3; short_name="ttd"; description=""; capacity=40; isFridge=true; isFreezer=false }), - #truckType (shared { id=4; short_name="tte"; description=""; capacity=50; isFridge=true; isFreezer=true }), - - #region (shared { id=0; short_name="rega"; description=""; }), - #region (shared { id=1; short_name="regb"; description=""; }), - #region (shared { id=2; short_name="regc"; description=""; }), - #region (shared { id=3; short_name="regd"; description=""; }), - - #produce (shared { id=0; short_name="avocado"; description=""; grade=1}), - #produce (shared { id=1; short_name="apple"; description=""; grade=1}), - #produce (shared { id=2; short_name="banana"; description=""; grade=1}), - #produce (shared { id=3; short_name="grapefruit"; description=""; grade=1}), - - #user (shared { user_name="a"; public_key=pka; description=""; region=0; + #truckType (new { id=0; short_name="tta"; description=""; capacity=10; isFridge=false; isFreezer=false }), + #truckType (new { id=1; short_name="ttb"; description=""; capacity=20; isFridge=false; isFreezer=false }), + #truckType (new { id=2; short_name="ttc"; description=""; capacity=30; isFridge=true; isFreezer=false }), + #truckType (new { id=3; short_name="ttd"; description=""; capacity=40; isFridge=true; isFreezer=false }), + #truckType (new { id=4; short_name="tte"; description=""; capacity=50; isFridge=true; isFreezer=true }), + + #region (new { id=0; short_name="rega"; description=""; }), + #region (new { id=1; short_name="regb"; description=""; }), + #region (new { id=2; short_name="regc"; description=""; }), + #region (new { id=3; short_name="regd"; description=""; }), + + #produce (new { id=0; short_name="avocado"; description=""; grade=1}), + #produce (new { id=1; short_name="apple"; description=""; grade=1}), + #produce (new { id=2; short_name="banana"; description=""; grade=1}), + #produce (new { id=3; short_name="grapefruit"; description=""; grade=1}), + + #user (new { user_name="a"; public_key=pka; description=""; region=0; isDeveloper=true; isProducer=true; isRetailer=true; isTransporter=true }), - #user (shared { user_name="b"; public_key=pkb; description=""; region=1; + #user (new { user_name="b"; public_key=pkb; description=""; region=1; isDeveloper=true; isProducer=true; isRetailer=true; isTransporter=true }), - #user (shared { user_name="c"; public_key=pkc; description=""; region=2; + #user (new { user_name="c"; public_key=pkc; description=""; region=2; isDeveloper=true; isProducer=true; isRetailer=true; isTransporter=true }), - #user (shared { user_name="d"; public_key=pkd; description=""; region=3; + #user (new { user_name="d"; public_key=pkd; description=""; region=3; isDeveloper=true; isProducer=true; isRetailer=true; isTransporter=true }), - #user (shared { user_name="e"; public_key=pke; description=""; region=0; + #user (new { user_name="e"; public_key=pke; description=""; region=0; isDeveloper=true; isProducer=true; isRetailer=true; isTransporter=true }), - #inventory (shared { id=0; produce=0; producer=0; start_date=0; end_date=10; quantity=100; weight=100; ppu=2; comments=""}), - #inventory (shared { id=0; produce=1; producer=0; start_date=1; end_date=10; quantity=100; weight=100; ppu=2; comments=""}), - #inventory (shared { id=0; produce=2; producer=0; start_date=2; end_date=10; quantity=100; weight=100; ppu=2; comments=""}), - #inventory (shared { id=0; produce=3; producer=0; start_date=3; end_date=10; quantity=100; weight=100; ppu=2; comments=""}), - - #inventory (shared { id=0; produce=0; producer=1; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (shared { id=0; produce=1; producer=1; start_date=0; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (shared { id=0; produce=2; producer=1; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (shared { id=0; produce=3; producer=1; start_date=0; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - - #inventory (shared { id=0; produce=0; producer=2; start_date=0; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (shared { id=0; produce=1; producer=2; start_date=1; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (shared { id=0; produce=2; producer=2; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (shared { id=0; produce=3; producer=2; start_date=5; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - - #inventory (shared { id=0; produce=0; producer=3; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (shared { id=0; produce=1; producer=3; start_date=1; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (shared { id=0; produce=2; producer=3; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (shared { id=0; produce=3; producer=3; start_date=1; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - - #inventory (shared { id=0; produce=0; producer=4; start_date=6; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (shared { id=0; produce=1; producer=4; start_date=7; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (shared { id=0; produce=2; producer=4; start_date=8; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (shared { id=0; produce=3; producer=4; start_date=9; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - - #route (shared { id=0; transporter=0; truck_type=0; start_region=0; end_region=1; start_date=0; end_date=10; cost=100 }), - #route (shared { id=0; transporter=0; truck_type=0; start_region=0; end_region=2; start_date=1; end_date=10; cost=100 }), - #route (shared { id=0; transporter=0; truck_type=0; start_region=0; end_region=3; start_date=2; end_date=10; cost=100 }), - #route (shared { id=0; transporter=0; truck_type=0; start_region=0; end_region=4; start_date=3; end_date=10; cost=100 }), - - #route (shared { id=0; transporter=1; truck_type=0; start_region=1; end_region=1; start_date=0; end_date=10; cost=100 }), - #route (shared { id=0; transporter=1; truck_type=0; start_region=1; end_region=2; start_date=1; end_date=10; cost=100 }), - #route (shared { id=0; transporter=1; truck_type=0; start_region=1; end_region=3; start_date=2; end_date=10; cost=100 }), - #route (shared { id=0; transporter=1; truck_type=0; start_region=1; end_region=4; start_date=3; end_date=10; cost=100 }), - - #route (shared { id=0; transporter=2; truck_type=0; start_region=2; end_region=1; start_date=0; end_date=10; cost=100 }), - #route (shared { id=0; transporter=2; truck_type=0; start_region=2; end_region=2; start_date=1; end_date=10; cost=100 }), - #route (shared { id=0; transporter=2; truck_type=0; start_region=2; end_region=3; start_date=2; end_date=10; cost=100 }), - #route (shared { id=0; transporter=2; truck_type=0; start_region=2; end_region=4; start_date=3; end_date=10; cost=100 }), - - #route (shared { id=0; transporter=3; truck_type=0; start_region=3; end_region=1; start_date=0; end_date=10; cost=100 }), - #route (shared { id=0; transporter=3; truck_type=0; start_region=3; end_region=2; start_date=1; end_date=10; cost=100 }), - #route (shared { id=0; transporter=3; truck_type=0; start_region=3; end_region=3; start_date=2; end_date=10; cost=100 }), - #route (shared { id=0; transporter=3; truck_type=0; start_region=3; end_region=4; start_date=3; end_date=10; cost=100 }), - - #route (shared { id=0; transporter=4; truck_type=0; start_region=4; end_region=1; start_date=0; end_date=10; cost=100 }), - #route (shared { id=0; transporter=4; truck_type=0; start_region=4; end_region=2; start_date=1; end_date=10; cost=100 }), - #route (shared { id=0; transporter=4; truck_type=0; start_region=4; end_region=3; start_date=2; end_date=10; cost=100 }), - #route (shared { id=0; transporter=4; truck_type=0; start_region=4; end_region=4; start_date=3; end_date=10; cost=100 }), + #inventory (new { id=0; produce=0; producer=0; start_date=0; end_date=10; quantity=100; weight=100; ppu=2; comments=""}), + #inventory (new { id=0; produce=1; producer=0; start_date=1; end_date=10; quantity=100; weight=100; ppu=2; comments=""}), + #inventory (new { id=0; produce=2; producer=0; start_date=2; end_date=10; quantity=100; weight=100; ppu=2; comments=""}), + #inventory (new { id=0; produce=3; producer=0; start_date=3; end_date=10; quantity=100; weight=100; ppu=2; comments=""}), + + #inventory (new { id=0; produce=0; producer=1; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), + #inventory (new { id=0; produce=1; producer=1; start_date=0; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), + #inventory (new { id=0; produce=2; producer=1; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), + #inventory (new { id=0; produce=3; producer=1; start_date=0; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), + + #inventory (new { id=0; produce=0; producer=2; start_date=0; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), + #inventory (new { id=0; produce=1; producer=2; start_date=1; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), + #inventory (new { id=0; produce=2; producer=2; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), + #inventory (new { id=0; produce=3; producer=2; start_date=5; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), + + #inventory (new { id=0; produce=0; producer=3; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), + #inventory (new { id=0; produce=1; producer=3; start_date=1; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), + #inventory (new { id=0; produce=2; producer=3; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), + #inventory (new { id=0; produce=3; producer=3; start_date=1; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), + + #inventory (new { id=0; produce=0; producer=4; start_date=6; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), + #inventory (new { id=0; produce=1; producer=4; start_date=7; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), + #inventory (new { id=0; produce=2; producer=4; start_date=8; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), + #inventory (new { id=0; produce=3; producer=4; start_date=9; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), + + #route (new { id=0; transporter=0; truck_type=0; start_region=0; end_region=1; start_date=0; end_date=10; cost=100 }), + #route (new { id=0; transporter=0; truck_type=0; start_region=0; end_region=2; start_date=1; end_date=10; cost=100 }), + #route (new { id=0; transporter=0; truck_type=0; start_region=0; end_region=3; start_date=2; end_date=10; cost=100 }), + #route (new { id=0; transporter=0; truck_type=0; start_region=0; end_region=4; start_date=3; end_date=10; cost=100 }), + + #route (new { id=0; transporter=1; truck_type=0; start_region=1; end_region=1; start_date=0; end_date=10; cost=100 }), + #route (new { id=0; transporter=1; truck_type=0; start_region=1; end_region=2; start_date=1; end_date=10; cost=100 }), + #route (new { id=0; transporter=1; truck_type=0; start_region=1; end_region=3; start_date=2; end_date=10; cost=100 }), + #route (new { id=0; transporter=1; truck_type=0; start_region=1; end_region=4; start_date=3; end_date=10; cost=100 }), + + #route (new { id=0; transporter=2; truck_type=0; start_region=2; end_region=1; start_date=0; end_date=10; cost=100 }), + #route (new { id=0; transporter=2; truck_type=0; start_region=2; end_region=2; start_date=1; end_date=10; cost=100 }), + #route (new { id=0; transporter=2; truck_type=0; start_region=2; end_region=3; start_date=2; end_date=10; cost=100 }), + #route (new { id=0; transporter=2; truck_type=0; start_region=2; end_region=4; start_date=3; end_date=10; cost=100 }), + + #route (new { id=0; transporter=3; truck_type=0; start_region=3; end_region=1; start_date=0; end_date=10; cost=100 }), + #route (new { id=0; transporter=3; truck_type=0; start_region=3; end_region=2; start_date=1; end_date=10; cost=100 }), + #route (new { id=0; transporter=3; truck_type=0; start_region=3; end_region=3; start_date=2; end_date=10; cost=100 }), + #route (new { id=0; transporter=3; truck_type=0; start_region=3; end_region=4; start_date=3; end_date=10; cost=100 }), + + #route (new { id=0; transporter=4; truck_type=0; start_region=4; end_region=1; start_date=0; end_date=10; cost=100 }), + #route (new { id=0; transporter=4; truck_type=0; start_region=4; end_region=2; start_date=1; end_date=10; cost=100 }), + #route (new { id=0; transporter=4; truck_type=0; start_region=4; end_region=3; start_date=2; end_date=10; cost=100 }), + #route (new { id=0; transporter=4; truck_type=0; start_region=4; end_region=4; start_date=3; end_date=10; cost=100 }), ]) ] diff --git a/stdlib/examples/produce-exchange/test/producerRemInventory.as b/stdlib/examples/produce-exchange/test/producerRemInventory.as index 77a18304a66..605831e3edd 100644 --- a/stdlib/examples/produce-exchange/test/producerRemInventory.as +++ b/stdlib/examples/produce-exchange/test/producerRemInventory.as @@ -16,7 +16,7 @@ func printLabeledCost(lab:Text, cost:Nat) { }; actor class Test() = this { - go() { + public func go() { ignore(async { let s = A.Server(); @@ -32,82 +32,82 @@ actor class Test() = this { let bulkResp = s.evalBulkArray( [ #add([ - #truckType (shared { id=0; short_name="tta"; description=""; capacity=10; isFridge=false; isFreezer=false }), - #truckType (shared { id=1; short_name="ttb"; description=""; capacity=20; isFridge=false; isFreezer=false }), - #truckType (shared { id=2; short_name="ttc"; description=""; capacity=30; isFridge=true; isFreezer=false }), - #truckType (shared { id=3; short_name="ttd"; description=""; capacity=40; isFridge=true; isFreezer=false }), - #truckType (shared { id=4; short_name="tte"; description=""; capacity=50; isFridge=true; isFreezer=true }), - - #region (shared { id=0; short_name="rega"; description=""; }), - #region (shared { id=1; short_name="regb"; description=""; }), - #region (shared { id=2; short_name="regc"; description=""; }), - #region (shared { id=3; short_name="regd"; description=""; }), - - #produce (shared { id=0; short_name="avocado"; description=""; grade=1}), - #produce (shared { id=1; short_name="apple"; description=""; grade=1}), - #produce (shared { id=2; short_name="banana"; description=""; grade=1}), - #produce (shared { id=3; short_name="grapefruit"; description=""; grade=1}), - - #user (shared { user_name="a"; public_key=pka; description=""; region=0; + #truckType (new { id=0; short_name="tta"; description=""; capacity=10; isFridge=false; isFreezer=false }), + #truckType (new { id=1; short_name="ttb"; description=""; capacity=20; isFridge=false; isFreezer=false }), + #truckType (new { id=2; short_name="ttc"; description=""; capacity=30; isFridge=true; isFreezer=false }), + #truckType (new { id=3; short_name="ttd"; description=""; capacity=40; isFridge=true; isFreezer=false }), + #truckType (new { id=4; short_name="tte"; description=""; capacity=50; isFridge=true; isFreezer=true }), + + #region (new { id=0; short_name="rega"; description=""; }), + #region (new { id=1; short_name="regb"; description=""; }), + #region (new { id=2; short_name="regc"; description=""; }), + #region (new { id=3; short_name="regd"; description=""; }), + + #produce (new { id=0; short_name="avocado"; description=""; grade=1}), + #produce (new { id=1; short_name="apple"; description=""; grade=1}), + #produce (new { id=2; short_name="banana"; description=""; grade=1}), + #produce (new { id=3; short_name="grapefruit"; description=""; grade=1}), + + #user (new { user_name="a"; public_key=pka; description=""; region=0; isDeveloper=true; isProducer=true; isRetailer=true; isTransporter=true }), - #user (shared { user_name="b"; public_key=pkb; description=""; region=1; + #user (new { user_name="b"; public_key=pkb; description=""; region=1; isDeveloper=true; isProducer=true; isRetailer=true; isTransporter=true }), - #user (shared { user_name="c"; public_key=pkc; description=""; region=2; + #user (new { user_name="c"; public_key=pkc; description=""; region=2; isDeveloper=true; isProducer=true; isRetailer=true; isTransporter=true }), - #user (shared { user_name="d"; public_key=pkd; description=""; region=3; + #user (new { user_name="d"; public_key=pkd; description=""; region=3; isDeveloper=true; isProducer=true; isRetailer=true; isTransporter=true }), - #user (shared { user_name="e"; public_key=pke; description=""; region=0; + #user (new { user_name="e"; public_key=pke; description=""; region=0; isDeveloper=true; isProducer=true; isRetailer=true; isTransporter=true }), - #inventory (shared { id=0; produce=0; producer=0; start_date=0; end_date=10; quantity=100; weight=100; ppu=2; comments=""}), - #inventory (shared { id=0; produce=1; producer=0; start_date=1; end_date=10; quantity=100; weight=100; ppu=2; comments=""}), - #inventory (shared { id=0; produce=2; producer=0; start_date=2; end_date=10; quantity=100; weight=100; ppu=2; comments=""}), - #inventory (shared { id=0; produce=3; producer=0; start_date=3; end_date=10; quantity=100; weight=100; ppu=2; comments=""}), - - #inventory (shared { id=0; produce=0; producer=1; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (shared { id=0; produce=1; producer=1; start_date=0; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (shared { id=0; produce=2; producer=1; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (shared { id=0; produce=3; producer=1; start_date=0; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - - #inventory (shared { id=0; produce=0; producer=2; start_date=0; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (shared { id=0; produce=1; producer=2; start_date=1; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (shared { id=0; produce=2; producer=2; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (shared { id=0; produce=3; producer=2; start_date=5; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - - #inventory (shared { id=0; produce=0; producer=3; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (shared { id=0; produce=1; producer=3; start_date=1; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (shared { id=0; produce=2; producer=3; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (shared { id=0; produce=3; producer=3; start_date=1; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - - #inventory (shared { id=0; produce=0; producer=4; start_date=6; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (shared { id=0; produce=1; producer=4; start_date=7; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (shared { id=0; produce=2; producer=4; start_date=8; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (shared { id=0; produce=3; producer=4; start_date=9; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - - #route (shared { id=0; transporter=0; truck_type=0; start_region=0; end_region=1; start_date=0; end_date=10; cost=100 }), - #route (shared { id=0; transporter=0; truck_type=0; start_region=0; end_region=2; start_date=1; end_date=10; cost=100 }), - #route (shared { id=0; transporter=0; truck_type=0; start_region=0; end_region=3; start_date=2; end_date=10; cost=100 }), - #route (shared { id=0; transporter=0; truck_type=0; start_region=0; end_region=4; start_date=3; end_date=10; cost=100 }), - - #route (shared { id=0; transporter=1; truck_type=0; start_region=1; end_region=1; start_date=0; end_date=10; cost=100 }), - #route (shared { id=0; transporter=1; truck_type=0; start_region=1; end_region=2; start_date=1; end_date=10; cost=100 }), - #route (shared { id=0; transporter=1; truck_type=0; start_region=1; end_region=3; start_date=2; end_date=10; cost=100 }), - #route (shared { id=0; transporter=1; truck_type=0; start_region=1; end_region=4; start_date=3; end_date=10; cost=100 }), - - #route (shared { id=0; transporter=2; truck_type=0; start_region=2; end_region=1; start_date=0; end_date=10; cost=100 }), - #route (shared { id=0; transporter=2; truck_type=0; start_region=2; end_region=2; start_date=1; end_date=10; cost=100 }), - #route (shared { id=0; transporter=2; truck_type=0; start_region=2; end_region=3; start_date=2; end_date=10; cost=100 }), - #route (shared { id=0; transporter=2; truck_type=0; start_region=2; end_region=4; start_date=3; end_date=10; cost=100 }), - - #route (shared { id=0; transporter=3; truck_type=0; start_region=3; end_region=1; start_date=0; end_date=10; cost=100 }), - #route (shared { id=0; transporter=3; truck_type=0; start_region=3; end_region=2; start_date=1; end_date=10; cost=100 }), - #route (shared { id=0; transporter=3; truck_type=0; start_region=3; end_region=3; start_date=2; end_date=10; cost=100 }), - #route (shared { id=0; transporter=3; truck_type=0; start_region=3; end_region=4; start_date=3; end_date=10; cost=100 }), - - #route (shared { id=0; transporter=4; truck_type=0; start_region=4; end_region=1; start_date=0; end_date=10; cost=100 }), - #route (shared { id=0; transporter=4; truck_type=0; start_region=4; end_region=2; start_date=1; end_date=10; cost=100 }), - #route (shared { id=0; transporter=4; truck_type=0; start_region=4; end_region=3; start_date=2; end_date=10; cost=100 }), - #route (shared { id=0; transporter=4; truck_type=0; start_region=4; end_region=4; start_date=3; end_date=10; cost=100 }), + #inventory (new { id=0; produce=0; producer=0; start_date=0; end_date=10; quantity=100; weight=100; ppu=2; comments=""}), + #inventory (new { id=0; produce=1; producer=0; start_date=1; end_date=10; quantity=100; weight=100; ppu=2; comments=""}), + #inventory (new { id=0; produce=2; producer=0; start_date=2; end_date=10; quantity=100; weight=100; ppu=2; comments=""}), + #inventory (new { id=0; produce=3; producer=0; start_date=3; end_date=10; quantity=100; weight=100; ppu=2; comments=""}), + + #inventory (new { id=0; produce=0; producer=1; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), + #inventory (new { id=0; produce=1; producer=1; start_date=0; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), + #inventory (new { id=0; produce=2; producer=1; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), + #inventory (new { id=0; produce=3; producer=1; start_date=0; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), + + #inventory (new { id=0; produce=0; producer=2; start_date=0; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), + #inventory (new { id=0; produce=1; producer=2; start_date=1; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), + #inventory (new { id=0; produce=2; producer=2; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), + #inventory (new { id=0; produce=3; producer=2; start_date=5; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), + + #inventory (new { id=0; produce=0; producer=3; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), + #inventory (new { id=0; produce=1; producer=3; start_date=1; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), + #inventory (new { id=0; produce=2; producer=3; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), + #inventory (new { id=0; produce=3; producer=3; start_date=1; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), + + #inventory (new { id=0; produce=0; producer=4; start_date=6; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), + #inventory (new { id=0; produce=1; producer=4; start_date=7; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), + #inventory (new { id=0; produce=2; producer=4; start_date=8; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), + #inventory (new { id=0; produce=3; producer=4; start_date=9; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), + + #route (new { id=0; transporter=0; truck_type=0; start_region=0; end_region=1; start_date=0; end_date=10; cost=100 }), + #route (new { id=0; transporter=0; truck_type=0; start_region=0; end_region=2; start_date=1; end_date=10; cost=100 }), + #route (new { id=0; transporter=0; truck_type=0; start_region=0; end_region=3; start_date=2; end_date=10; cost=100 }), + #route (new { id=0; transporter=0; truck_type=0; start_region=0; end_region=4; start_date=3; end_date=10; cost=100 }), + + #route (new { id=0; transporter=1; truck_type=0; start_region=1; end_region=1; start_date=0; end_date=10; cost=100 }), + #route (new { id=0; transporter=1; truck_type=0; start_region=1; end_region=2; start_date=1; end_date=10; cost=100 }), + #route (new { id=0; transporter=1; truck_type=0; start_region=1; end_region=3; start_date=2; end_date=10; cost=100 }), + #route (new { id=0; transporter=1; truck_type=0; start_region=1; end_region=4; start_date=3; end_date=10; cost=100 }), + + #route (new { id=0; transporter=2; truck_type=0; start_region=2; end_region=1; start_date=0; end_date=10; cost=100 }), + #route (new { id=0; transporter=2; truck_type=0; start_region=2; end_region=2; start_date=1; end_date=10; cost=100 }), + #route (new { id=0; transporter=2; truck_type=0; start_region=2; end_region=3; start_date=2; end_date=10; cost=100 }), + #route (new { id=0; transporter=2; truck_type=0; start_region=2; end_region=4; start_date=3; end_date=10; cost=100 }), + + #route (new { id=0; transporter=3; truck_type=0; start_region=3; end_region=1; start_date=0; end_date=10; cost=100 }), + #route (new { id=0; transporter=3; truck_type=0; start_region=3; end_region=2; start_date=1; end_date=10; cost=100 }), + #route (new { id=0; transporter=3; truck_type=0; start_region=3; end_region=3; start_date=2; end_date=10; cost=100 }), + #route (new { id=0; transporter=3; truck_type=0; start_region=3; end_region=4; start_date=3; end_date=10; cost=100 }), + + #route (new { id=0; transporter=4; truck_type=0; start_region=4; end_region=1; start_date=0; end_date=10; cost=100 }), + #route (new { id=0; transporter=4; truck_type=0; start_region=4; end_region=2; start_date=1; end_date=10; cost=100 }), + #route (new { id=0; transporter=4; truck_type=0; start_region=4; end_region=3; start_date=2; end_date=10; cost=100 }), + #route (new { id=0; transporter=4; truck_type=0; start_region=4; end_region=4; start_date=3; end_date=10; cost=100 }), ]) ] diff --git a/stdlib/examples/produce-exchange/test/retailerReserveMany.as b/stdlib/examples/produce-exchange/test/retailerReserveMany.as index b4a4a664971..9e4e84e91ac 100644 --- a/stdlib/examples/produce-exchange/test/retailerReserveMany.as +++ b/stdlib/examples/produce-exchange/test/retailerReserveMany.as @@ -16,7 +16,7 @@ func printLabeledCost(lab:Text, cost:Nat) { }; actor class Test() = this { - go() { + public func go() { ignore(async { let s = A.Server(); From 092c277a1812b6806dfd38449b520d36bf0e2a91 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Tue, 23 Jul 2019 12:43:11 -0700 Subject: [PATCH 0312/1176] Stdlib additions and tests --- stdlib/Makefile | 39 +++ stdlib/array.as | 101 +++++++ stdlib/arrayTest.as | 181 +++++++++++++ .../examples/produce-exchange/serverModel.as | 8 +- stdlib/int.as | 39 +++ stdlib/intTest.as | 23 ++ stdlib/nat.as | 12 + stdlib/natTest.as | 21 ++ stdlib/option.as | 48 ++-- stdlib/optionTest.as | 255 ++++++++++++++++++ stdlib/prelude.as | 12 + stdlib/text.as | 5 + stdlib/textTest.as | 13 + 13 files changed, 738 insertions(+), 19 deletions(-) create mode 100644 stdlib/array.as create mode 100644 stdlib/arrayTest.as create mode 100644 stdlib/int.as create mode 100644 stdlib/intTest.as create mode 100644 stdlib/nat.as create mode 100644 stdlib/natTest.as create mode 100644 stdlib/optionTest.as create mode 100644 stdlib/text.as create mode 100644 stdlib/textTest.as diff --git a/stdlib/Makefile b/stdlib/Makefile index 07f58835290..b9fa16ac404 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -11,12 +11,21 @@ STOPWATCH=$(OUTDIR)/stopwatch WASM=ProduceExchange TESTS=\ + Array \ + ArrayTest \ + Int \ + IntTest \ + Nat \ + NatTest \ Option \ + OptionTest \ Result \ Hash \ List \ ListTest \ AssocList \ + Text \ + TextTest \ Trie \ Trie2 \ Set \ @@ -48,12 +57,33 @@ clean: $(OUTDIR): @mkdir $@ +$(OUTDIR)/Array.out: array.as | $(OUTDIR) + $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ + +$(OUTDIR)/ArrayTest.out: arrayTest.as | $(OUTDIR) + $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ + +$(OUTDIR)/Int.out: int.as | $(OUTDIR) + $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ + +$(OUTDIR)/IntTest.out: intTest.as | $(OUTDIR) + $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ + +$(OUTDIR)/Nat.out: nat.as | $(OUTDIR) + $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ + +$(OUTDIR)/NatTest.out: natTest.as | $(OUTDIR) + $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ + $(OUTDIR)/Hash.out: hash.as | $(OUTDIR) $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ $(OUTDIR)/Option.out: option.as | $(OUTDIR) $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ +$(OUTDIR)/OptionTest.out: optionTest.as | $(OUTDIR) + $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ + $(OUTDIR)/Result.out: result.as | $(OUTDIR) $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ @@ -66,6 +96,13 @@ $(OUTDIR)/ListTest.out: listTest.as | $(OUTDIR) $(OUTDIR)/AssocList.out: assocList.as | $(OUTDIR) $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ +$(OUTDIR)/Text.out: text.as | $(OUTDIR) + $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ + +$(OUTDIR)/TextTest.out: textTest.as | $(OUTDIR) + $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ + + $(OUTDIR)/Trie.out: trie.as | $(OUTDIR) $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ @@ -105,6 +142,7 @@ alldoc: docMd docHtml docMd: \ $(DOCDIR)/README.md \ $(DOCDIR)/prelude.md \ + $(DOCDIR)/array.md \ $(DOCDIR)/option.md \ $(DOCDIR)/result.md \ $(DOCDIR)/hash.md \ @@ -128,6 +166,7 @@ docMd: \ docHtml: \ $(DOCDIR)/README.html \ $(DOCDIR)/prelude.html \ + $(DOCDIR)/array.html \ $(DOCDIR)/option.html \ $(DOCDIR)/result.html \ $(DOCDIR)/hash.html \ diff --git a/stdlib/array.as b/stdlib/array.as new file mode 100644 index 00000000000..26c6d765387 --- /dev/null +++ b/stdlib/array.as @@ -0,0 +1,101 @@ +module { + public func append(xs : [A], ys : [A]) : [A] { + switch(xs.len(), ys.len()) { + case (0, 0) { []; }; + case (0, _) { ys; }; + case (_, 0) { xs; }; + case (xsLen, ysLen) { + Array_tabulate(xsLen + ysLen, func (i : Nat) : A { + if (i < xsLen) { + xs[i]; + } else { + ys[i - xsLen]; + }; + }); + }; + }; + }; + + public func apply(fs : [A -> B], xs : [A]) : [B] { + let fsLen = fs.len(); + let xsLen = xs.len(); + var ys : [B] = []; + for (f in fs.vals()) { + ys := append(ys, map(f, xs)); + }; + ys; + }; + + public func bind(xs : [A], f : A -> [B]) : [B] { + var ys : [B] = []; + for (i in xs.keys()) { + ys := append(ys, f(xs[i])); + }; + ys; + }; + + public func foldl(f : (B, A) -> B, initial : B, xs : [A]) : B { + var acc = initial; + let len = xs.len(); + var i = 0; + while (i < len) { + acc := f(acc, xs[i]); + i += 1; + }; + acc; + }; + + public func foldr(f : (A, B) -> B, initial : B, xs : [A]) : B { + var acc = initial; + let len = xs.len(); + var i = len; + while (i > 0) { + i -= 1; + acc := f(xs[i], acc); + }; + acc; + }; + + public func find(f : A -> Bool, xs : [A]) : ?A { + for (x in xs.vals()) { + if (f(x)) { + return ?x; + } + }; + return null; + }; + + public func freeze(xs : [var A]) : [A] { + Array_tabulate(xs.len(), func (i : Nat) : A { + xs[i]; + }); + }; + + public func join(xs : [[A]]) : [A] { + bind<[A], A>(xs, func (x : [A]) : [A] { + x; + }); + }; + + public func map(f : A -> B, xs : [A]) : [B] { + Array_tabulate(xs.len(), func (i : Nat) : B { + f(xs[i]); + }); + }; + + public func pure(x: A) : [A] { + [x]; + }; + + public func thaw(xs : [A]) : [var A] { + let xsLen = xs.len(); + if (xsLen == 0) { + return [var]; + }; + let ys = Array_init(xsLen, xs[0]); + for (i in ys.keys()) { + ys[i] := xs[i]; + }; + ys; + }; +} diff --git a/stdlib/arrayTest.as b/stdlib/arrayTest.as new file mode 100644 index 00000000000..b971baa01fc --- /dev/null +++ b/stdlib/arrayTest.as @@ -0,0 +1,181 @@ +import Array "array.as"; +import Prelude "prelude.as"; +import Text "text.as"; + +Prelude.printLn("Array"); + +{ + Prelude.printLn(" append"); + + let actual = Array.append([ 1, 2, 3 ], [ 4, 5, 6 ]); + let expected = [ 1, 2, 3, 4, 5, 6 ]; + + assert(actual.len() == expected.len()); + + for (i in actual.keys()) { + assert(actual[i] == expected[i]); + }; +}; + +{ + Prelude.printLn(" apply"); + + let ask = func (x : Text) : Text { + x # "?"; + }; + + let exclaim = func (x : Text) : Text { + x # "!"; + }; + + let actual = Array.apply([ ask, exclaim ], [ "good", "bad" ]); + let expected = [ "good?", "bad?", "good!", "bad!" ]; + + assert(actual.len() == expected.len()); + + for (i in actual.keys()) { + assert(actual[i] == expected[i]); + }; +}; + +{ + Prelude.printLn(" bind"); + + let purePlusOne = func (x : Int) : [Int] { + [ x + 1 ]; + }; + + let actual = Array.bind([ 0, 1, 2 ], purePlusOne); + let expected = [ 1, 2, 3 ]; + + assert(actual.len() == expected.len()); + + for (i in actual.keys()) { + assert(actual[i] == expected[i]); + }; +}; + +{ + Prelude.printLn(" find"); + + type Element = { + key : Text; + value : Int; + }; + + let xs = [ + new { key = "a"; value = 0; }, + new { key = "b"; value = 1; }, + new { key = "c"; value = 2; }, + ]; + + let b : ?Element = Array.find(func (x : Element) : Bool { + x.key == "b"; + }, xs); + + switch (b) { + case (?element) { + assert(element.key == "b" and element.value == 1); + }; + case (_) { + assert(false); + }; + }; +}; + +{ + Prelude.printLn(" foldl"); + + let xs = [ "a", "b", "c" ]; + + let actual = Array.foldl(Text.append, "", xs); + let expected = "abc"; + + assert(actual == expected); +}; + +{ + Prelude.printLn(" foldr"); + + let xs = [ "a", "b", "c" ]; + + let actual = Array.foldr(Text.append, "", xs); + let expected = "abc"; + + assert(actual == expected); +}; + +{ + Prelude.printLn(" freeze"); + + var xs : [var Int] = [ var 1, 2, 3 ]; + + let actual = Array.freeze(xs); + let expected : [Int] = [ 1, 2, 3 ]; + + assert(actual.len() == expected.len()); + + for (i in actual.keys()) { + assert(actual[i] == expected[i]); + }; +}; + +{ + Prelude.printLn(" join"); + + let xs = [ [ 1, 2, 3 ] ]; + + let actual = Array.join(xs); + let expected : [Int] = [ 1, 2, 3 ]; + + assert(actual.len() == expected.len()); + + for (i in actual.keys()) { + assert(actual[i] == expected[i]); + }; +}; + +{ + Prelude.printLn(" map"); + + let isEven = func (x : Int) : Bool { + x % 2 == 0; + }; + + let actual = Array.map(isEven, [ 1, 2, 3, 4, 5, 6 ]); + let expected = [ false, true, false, true, false, true ]; + + assert(actual.len() == expected.len()); + + for (i in actual.keys()) { + assert(actual[i] == expected[i]); + }; +}; + +{ + Prelude.printLn(" pure"); + + let actual = Array.pure(0); + let expected = [0]; + + assert(actual.len() == expected.len()); + + for (i in actual.keys()) { + assert(actual[i] == expected[i]); + }; +}; + +{ + Prelude.printLn(" thaw"); + + let xs : [Int] = [ 1, 2, 3 ]; + + let actual = Array.thaw(xs); + var expected : [Int] = [ 1, 2, 3 ]; + + assert(actual.len() == expected.len()); + + for (i in actual.keys()) { + assert(actual[i] == expected[i]); + }; +}; diff --git a/stdlib/examples/produce-exchange/serverModel.as b/stdlib/examples/produce-exchange/serverModel.as index fa1f10df178..c1024e36515 100644 --- a/stdlib/examples/produce-exchange/serverModel.as +++ b/stdlib/examples/produce-exchange/serverModel.as @@ -816,7 +816,6 @@ secondary maps. }, func(info:T.ProducerInfo):?M.ProducerDoc = Option.map( - regionTable.getDoc(info.region), func (regionDoc: M.RegionDoc): M.ProducerDoc = new { id=info.id; public_key=info.public_key; @@ -825,7 +824,8 @@ secondary maps. region=regionDoc; inventory=Table.empty(); reserved=Table.empty(); - } + }, + regionTable.getDoc(info.region), ) ); @@ -928,7 +928,6 @@ secondary maps. }, func(info:T.RetailerInfo):?M.RetailerDoc = Option.map( - regionTable.getDoc(info.region), func (regionDoc: M.RegionDoc): M.RetailerDoc = new { id=info.id; public_key=info.public_key; @@ -936,7 +935,8 @@ secondary maps. description=info.description; region=regionDoc; reserved=Map.empty(); - } + }, + regionTable.getDoc(info.region), ) ); diff --git a/stdlib/int.as b/stdlib/int.as new file mode 100644 index 00000000000..8dbf0083bcf --- /dev/null +++ b/stdlib/int.as @@ -0,0 +1,39 @@ +module { + import Prelude "prelude.as"; + + public func add(x : Int, y : Int) : Int { + x + y; + }; + + public func toText(x : Int) : Text { + if (x == 0) { + return "0"; + }; + + let isNegative = x < 0; + var int = if isNegative (-x) else x; + + var text = ""; + let base = 10; + + while (int > 0) { + let rem = int % base; + text := (switch (rem) { + case 0 "0"; + case 1 "1"; + case 2 "2"; + case 3 "3"; + case 4 "4"; + case 5 "5"; + case 6 "6"; + case 7 "7"; + case 8 "8"; + case 9 "9"; + case _ Prelude.unreachable(); + }) # text; + int := int / base; + }; + + return if isNegative ("-" # text) else text; + }; +} diff --git a/stdlib/intTest.as b/stdlib/intTest.as new file mode 100644 index 00000000000..6e5b4fc0e21 --- /dev/null +++ b/stdlib/intTest.as @@ -0,0 +1,23 @@ +import Prelude "prelude.as"; +import Int "int.as"; + +Prelude.printLn("Int"); + +{ + Prelude.printLn(" add"); + + assert(Int.add(1, Int.add(2, 3)) == Int.add(1, Int.add(2, 3))); + assert(Int.add(0, 1) == 1); + assert(1 == Int.add(1, 0)); + assert(Int.add(0, 1) == Int.add(1, 0)); + assert(Int.add(1, 2) == Int.add(2, 1)); +}; + +{ + Prelude.printLn(" toText"); + + assert(Int.toText(0) == "0"); + assert(Int.toText(-0) == "0"); + assert(Int.toText(1234) == "1234"); + assert(Int.toText(-1234) == "-1234"); +}; diff --git a/stdlib/nat.as b/stdlib/nat.as new file mode 100644 index 00000000000..5bfc670e8c9 --- /dev/null +++ b/stdlib/nat.as @@ -0,0 +1,12 @@ +module { + import Int "int.as"; + import Prelude "prelude.as"; + + public func add(x : Nat, y : Nat) : Nat { + x + y; + }; + + public func toText(x : Nat) : Text { + Int.toText(x); + }; +} diff --git a/stdlib/natTest.as b/stdlib/natTest.as new file mode 100644 index 00000000000..910b5b142af --- /dev/null +++ b/stdlib/natTest.as @@ -0,0 +1,21 @@ +import Prelude "prelude.as"; +import Nat "nat.as"; + +Prelude.printLn("Nat"); + +{ + Prelude.printLn(" add"); + + assert(Nat.add(1, Nat.add(2, 3)) == Nat.add(1, Nat.add(2, 3))); + assert(Nat.add(0, 1) == 1); + assert(1 == Nat.add(1, 0)); + assert(Nat.add(0, 1) == Nat.add(1, 0)); + assert(Nat.add(1, 2) == Nat.add(2, 1)); +}; + +{ + Prelude.printLn(" toText"); + + assert(Nat.toText(0) == "0"); + assert(Nat.toText(1234) == "1234"); +}; diff --git a/stdlib/option.as b/stdlib/option.as index c992ebac0bf..58656d06a19 100644 --- a/stdlib/option.as +++ b/stdlib/option.as @@ -87,26 +87,12 @@ public func option(x: ?A, f: A->B, d: B): B = Apply a function to the wrapped value. */ -public func map(x: ?A, f: A->B): ?B = +public func map(f: A->B, x: ?A): ?B = switch x { case null null; case (?x_) ?f(x_); }; -/*** - - `fmap` - -------------------- - - Apply a function to the wrapped value. - -*/ -public func fmap(x: ?A, f: A->?B): ?B = - switch x { - case null null; - case (?x_) f(x_); - }; - /*** `assertSome` @@ -153,4 +139,36 @@ public func printOpInt(x : ?Int) = case (?x_) { print "?"; printInt x_ }; }; +public func apply(f : ?(A -> B), x : ?A) : ?B { + switch (f, x) { + case (?f_, ?x_) { + ?f_(x_); + }; + case (_, _) { + null; + }; + }; +}; + +public func bind(x : ?A, f : A -> ?B) : ?B { + switch(x) { + case (?x_) { + f(x_); + }; + case (null) { + null; + }; + }; +}; + +public func join(x : ??A) : ?A { + bind(x, func (x_ : ?A) : ?A { + x_; + }); +}; + +public func pure(x: A) : ?A { + ?x; +}; + } diff --git a/stdlib/optionTest.as b/stdlib/optionTest.as new file mode 100644 index 00000000000..ccf94eba908 --- /dev/null +++ b/stdlib/optionTest.as @@ -0,0 +1,255 @@ +import Option "option.as"; +import Prelude "prelude.as"; + +Prelude.printLn("Option"); + +{ + Prelude.printLn(" apply"); + + { + Prelude.printLn(" null function, null value"); + + let actual = Option.apply(null, null); + let expected : ?Bool = null; + + switch (actual, expected) { + case (?actual_, ?expected_) { + assert(false); + }; + case (_, _) { + assert(true); + }; + }; + }; + + { + Prelude.printLn(" null function, non-null value"); + + let actual = Option.apply(null, ?0); + let expected : ?Bool = null; + + switch (actual, expected) { + case (?actual_, ?expected_) { + assert(false); + }; + case (_, _) { + assert(true); + }; + }; + }; + + { + Prelude.printLn(" non-null function, null value"); + + let isEven = func (x : Int) : Bool { + x % 2 == 0; + }; + + let actual = Option.apply(?isEven, null); + let expected : ?Bool = null; + + switch (actual, expected) { + case (?actual_, ?expected_) { + assert(false); + }; + case (_, _) { + assert(true); + }; + }; + }; + + { + Prelude.printLn(" non-null function, non-null value"); + + let isEven = func (x : Int) : Bool { + x % 2 == 0; + }; + + let actual = Option.apply(?isEven, ?0); + let expected = ?true; + + switch (actual, expected) { + case (?actual_, ?expected_) { + assert(actual_ == expected_); + }; + case (_, _) { + assert(false); + }; + }; + }; + + }; + +{ + Prelude.printLn(" bind"); + + { + Prelude.printLn(" null value to null value"); + + let safeInt = func (x : Int) : ?Int { + if (x > 9007199254740991) { + null; + } else { + ?x; + } + }; + + let actual = Option.bind(null, safeInt); + let expected : ?Int = null; + + switch (actual, expected) { + case (?actual_, ?expected_) { + assert(false); + }; + case (_, _) { + assert(true); + }; + }; + }; + + { + Prelude.printLn(" non-null value to null value"); + + let safeInt = func (x : Int) : ?Int { + if (x > 9007199254740991) { + null; + } else { + ?x; + } + }; + + let actual = Option.bind(?9007199254740992, safeInt); + let expected : ?Int = null; + + switch (actual, expected) { + case (?actual_, ?expected_) { + assert(false); + }; + case (_, _) { + assert(true); + }; + }; + }; + + { + Prelude.printLn(" non-null value to non-null value"); + + let safeInt = func (x : Int) : ?Int { + if (x > 9007199254740991) { + null; + } else { + ?x; + } + }; + + let actual = Option.bind(?0, safeInt); + let expected = ?0; + + switch (actual, expected) { + case (?actual_, ?expected_) { + assert(actual_ == expected_); + }; + case (_, _) { + assert(false); + }; + }; + }; + +}; + +{ + Prelude.printLn(" join"); + + { + Prelude.printLn(" null value"); + + let actual = Option.join(?null); + let expected : ?Int = null; + + switch (actual, expected) { + case (?actual_, ?expected_) { + assert(false); + }; + case (_, _) { + assert(true); + }; + }; + }; + + { + Prelude.printLn(" non-null value"); + let actual = Option.join(??0); + let expected = ?0; + + switch (actual, expected) { + case (?actual_, ?expected_) { + assert(actual_ == expected_); + }; + case (_, _) { + assert(false); + }; + }; + }; + +}; + +{ + Prelude.printLn(" map"); + + { + Prelude.printLn(" null value"); + + let isEven = func (x : Int) : Bool { + x % 2 == 0; + }; + + let actual = Option.map(isEven, null); + let expected : ?Bool = null; + + switch (actual, expected) { + case (?actual_, ?expected_) { + assert(false); + }; + case (_, _) { + assert(true); + }; + }; + }; + + { + Prelude.printLn(" non-null value"); + + let isEven = func (x : Int) : Bool { + x % 2 == 0; + }; + + let actual = Option.map(isEven, ?0); + let expected = ?true; + + switch (actual, expected) { + case (?actual_, ?expected_) { + assert(actual_ == expected_); + }; + case (_, _) { + assert(false); + }; + }; + }; + +}; + +{ + Prelude.printLn(" pure"); + + let actual = Option.pure(0); + let expected = ?0; + + switch (actual, expected) { + case (?actual_, ?expected_) { + assert(actual_ == expected_); + }; + case (_, _) { + assert(false); + }; + }; +}; diff --git a/stdlib/prelude.as b/stdlib/prelude.as index 2588945387c..6199cf0d996 100644 --- a/stdlib/prelude.as +++ b/stdlib/prelude.as @@ -10,6 +10,18 @@ some further experience and discussion. Until then, they live here. */ +/*** + + `printLn` + --------- + + Print text followed by a newline. + +*/ +public func printLn(x : Text) { + print(x # "\n"); +}; + /*** `nyi`: Not yet implemented diff --git a/stdlib/text.as b/stdlib/text.as new file mode 100644 index 00000000000..8d74ff17cb3 --- /dev/null +++ b/stdlib/text.as @@ -0,0 +1,5 @@ +module { + public func append(x : Text, y : Text) : Text { + x # y; + }; +} diff --git a/stdlib/textTest.as b/stdlib/textTest.as new file mode 100644 index 00000000000..4dbffa819eb --- /dev/null +++ b/stdlib/textTest.as @@ -0,0 +1,13 @@ +import Prelude "prelude.as"; +import Text "text.as"; + +Prelude.printLn("Text"); + +{ + Prelude.printLn(" append"); + + let actual = Text.append("x", "y"); + let expected = "xy"; + + assert(actual == expected); +}; From 1fda510038661c741e465f9ae30987a703b0fe85 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Tue, 23 Jul 2019 12:44:51 -0700 Subject: [PATCH 0313/1176] Fix indentation --- stdlib/Makefile | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/stdlib/Makefile b/stdlib/Makefile index b9fa16ac404..88b0a808407 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -13,10 +13,10 @@ WASM=ProduceExchange TESTS=\ Array \ ArrayTest \ - Int \ - IntTest \ - Nat \ - NatTest \ + Int \ + IntTest \ + Nat \ + NatTest \ Option \ OptionTest \ Result \ @@ -24,8 +24,8 @@ TESTS=\ List \ ListTest \ AssocList \ - Text \ - TextTest \ + Text \ + TextTest \ Trie \ Trie2 \ Set \ From 7b97043bc8a29ba879322164b20e12a9d7b42d44 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Wed, 24 Jul 2019 15:48:30 +0200 Subject: [PATCH 0314/1176] Compact bignums (#469) * introduce functor to perform memory compaction of BigNum * add tests --- rts/bigint.c | 36 +- src/codegen/compile.ml | 647 ++++++++++++++++----- test/run-dfinity/data-params.as | 8 + test/run-dfinity/ok/data-params.dvm-run.ok | 8 + test/run-dfinity/ok/data-params.run-ir.ok | 8 + test/run-dfinity/ok/data-params.run-low.ok | 8 + test/run-dfinity/ok/data-params.run.ok | 8 + test/run/numeric-ops.as | 35 +- test/run/ok/overflow.wasm-run.ok | 2 +- test/run/small-pow.as | 516 ++++++++++++++++ 10 files changed, 1137 insertions(+), 139 deletions(-) create mode 100644 test/run/small-pow.as diff --git a/rts/bigint.c b/rts/bigint.c index d206d007fed..efc63b60071 100644 --- a/rts/bigint.c +++ b/rts/bigint.c @@ -267,11 +267,11 @@ export int bigint_leb128_size(as_ptr n) { return ((x + 6) / 7); // divide by 7, round up } -void leb128_encode_go(mp_int *tmp, unsigned char *buf) { +void bigint_leb128_encode_go(mp_int *tmp, unsigned char *buf) { // now the number should be positive if (mp_isneg(tmp)) bigint_trap(); while (true) { - buf[0] = (char)(mp_get_u32(tmp)); // get low bits + buf[0] = (unsigned char)(mp_get_u32(tmp)); // get low bits CHECK(mp_div_2d(tmp, 7, tmp, NULL)); if (mp_iszero(tmp)) { // we are done. high bit should be cleared anyways @@ -287,7 +287,7 @@ void leb128_encode_go(mp_int *tmp, unsigned char *buf) { export void bigint_leb128_encode(as_ptr n, unsigned char *buf) { mp_int tmp; CHECK(mp_init_copy(&tmp, BIGINT_PAYLOAD(n))); - leb128_encode_go(&tmp, buf); + bigint_leb128_encode_go(&tmp, buf); } @@ -352,7 +352,7 @@ export void bigint_sleb128_encode(as_ptr n, unsigned char *buf) { CHECK(mp_add(&tmp, &big, &tmp)); } - leb128_encode_go(&tmp, buf); + bigint_leb128_encode_go(&tmp, buf); } export as_ptr bigint_sleb128_decode(unsigned char *buf) { @@ -371,3 +371,31 @@ export as_ptr bigint_sleb128_decode(unsigned char *buf) { return r; } + +export void leb128_encode(unsigned n, unsigned char *buf) { + while (true) { + buf[0] = (unsigned char)n; // get low bits + if (n >>= 7) { + // more bytes to come, set high bit and continue + buf[0] |= 1<<7; + buf++; + } else { + // we are done. high bit should be cleared anyway + return; + } + } +} + +export void sleb128_encode(signed n, unsigned char *buf) { + while (true) { + *buf = n & 0x7F; // get low bits + if (n >= -64 && n < 64) { + // last byte written, high bit is clear + return; + } else { + // more bytes to come, set high bit and continue + *buf++ |= 0x80; + n >>= 7; + } + } +} diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index b8793e2287a..646990a3819 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -371,6 +371,8 @@ let compile_divU_const = compile_op_const I32Op.DivU let compile_shrU_const = compile_op_const I32Op.ShrU let compile_shrS_const = compile_op_const I32Op.ShrS let compile_shl_const = compile_op_const I32Op.Shl +let compile_rotr_const = compile_op_const I32Op.Rotr +let compile_rotl_const = compile_op_const I32Op.Rotl let compile_bitand_const = compile_op_const I32Op.And let compile_bitor_const = function | 0l -> G.nop | n -> compile_op_const I32Op.Or n @@ -385,9 +387,12 @@ let _compile_add64_const = compile_op64_const I64Op.Add let compile_sub64_const = compile_op64_const I64Op.Sub let _compile_mul64_const = compile_op64_const I64Op.Mul let _compile_divU64_const = compile_op64_const I64Op.DivU -let compile_shrU64_const = compile_op64_const I64Op.ShrU -let compile_shrS64_const = compile_op64_const I64Op.ShrS -let compile_shl64_const = compile_op64_const I64Op.Shl +let compile_shrU64_const = function + | 0L -> G.nop | n -> compile_op64_const I64Op.ShrU n +let compile_shrS64_const = function + | 0L -> G.nop | n -> compile_op64_const I64Op.ShrS n +let compile_shl64_const = function + | 0L -> G.nop | n -> compile_op64_const I64Op.Shl n let compile_bitand64_const = compile_op64_const I64Op.And let _compile_bitor64_const = function | 0L -> G.nop | n -> compile_op64_const I64Op.Or n @@ -564,7 +569,9 @@ module RTS = struct E.add_func_import env "rts" "bigint_leb128_decode" [I32Type] [I32Type]; E.add_func_import env "rts" "bigint_sleb128_size" [I32Type] [I32Type]; E.add_func_import env "rts" "bigint_sleb128_encode" [I32Type; I32Type] []; - E.add_func_import env "rts" "bigint_sleb128_decode" [I32Type] [I32Type] + E.add_func_import env "rts" "bigint_sleb128_decode" [I32Type] [I32Type]; + E.add_func_import env "rts" "leb128_encode" [I32Type; I32Type] []; + E.add_func_import env "rts" "sleb128_encode" [I32Type; I32Type] [] let system_exports env = E.add_export env (nr { @@ -907,6 +914,14 @@ module BitTagged = struct ) ^^ G.if_ retty is1 is2 + (* With two bit-tagged pointers on the stack, decide + whether both are scalars and invoke is1 (the fast path) + if so, and otherwise is2 (the slow path). + *) + let if_both_unboxed env retty is1 is2 = + G.i (Binary (Wasm.Values.I32 I32Op.Or)) ^^ + if_unboxed env retty is1 is2 + (* The untag_scalar and tag functions expect 64 bit numbers *) let untag_scalar env = compile_shrU_const scalar_shift ^^ @@ -914,8 +929,7 @@ module BitTagged = struct let tag = G.i (Convert (Wasm.Values.I32 I32Op.WrapI64)) ^^ - compile_unboxed_const scalar_shift ^^ - G.i (Binary (Wasm.Values.I32 I32Op.Shl)) + compile_shl_const scalar_shift (* The untag_i32 and tag_i32 functions expect 32 bit numbers *) let untag_i32 env = @@ -1218,14 +1232,13 @@ module BoxedWord64 = struct let _lit env n = compile_const_64 n ^^ box env - (* from/to SR.UnboxedWord64 *) - let to_word64 env = G.nop - let from_word64 env = G.nop (* TODO trap if negative *) - let _from_signed_word64 env = G.nop - let to_word32 env = G.i (Convert (Wasm.Values.I32 I32Op.WrapI64)) - let from_word32 env = G.i (Convert (Wasm.Values.I64 I64Op.ExtendUI32)) - let from_signed_word32 env = G.i (Convert (Wasm.Values.I64 I64Op.ExtendSI32)) - + let compile_add env = G.i (Binary (Wasm.Values.I64 I64Op.Add)) + let compile_signed_sub env = G.i (Binary (Wasm.Values.I64 I64Op.Sub)) + let compile_mul env = G.i (Binary (Wasm.Values.I64 I64Op.Mul)) + let compile_signed_div env = G.i (Binary (Wasm.Values.I64 I64Op.DivS)) + let compile_signed_mod env = G.i (Binary (Wasm.Values.I64 I64Op.RemS)) + let compile_unsigned_div env = G.i (Binary (Wasm.Values.I64 I64Op.DivU)) + let compile_unsigned_rem env = G.i (Binary (Wasm.Values.I64 I64Op.RemU)) let compile_unsigned_sub env = Func.share_code2 env "nat_sub" (("n1", I64Type), ("n2", I64Type)) [I64Type] (fun env get_n1 get_n2 -> get_n1 ^^ get_n2 ^^ G.i (Compare (Wasm.Values.I64 I64Op.LtU)) ^^ @@ -1254,6 +1267,9 @@ module BoxedWord64 = struct G.i (Binary (Wasm.Values.I64 I64Op.Mul))))) in pow () + let compile_eq env = G.i (Compare (Wasm.Values.I64 I64Op.Eq)) + let compile_relop env i64op = G.i (Compare (Wasm.Values.I64 i64op)) + end (* BoxedWord64 *) @@ -1332,9 +1348,7 @@ module UnboxedSmallWord = struct | Type.Word32 -> G.nop | ty -> compile_bitand_const (bitwidth_mask_of_type ty) - let shift_leftWordNtoI32 b = - compile_unboxed_const b ^^ - G.i (Binary (Wasm.Values.I32 I32Op.Shl)) + let shift_leftWordNtoI32 = compile_shl_const (* Makes sure that the word payload (e.g. shift/rotate amount) is in the LSB bits of the word. *) let lsb_adjust = function @@ -1367,8 +1381,7 @@ module UnboxedSmallWord = struct (* Kernel for counting trailing zeros, according to the word invariant. *) let ctz_kernel ty = compile_word_padding ty ^^ - compile_unboxed_const (shift_of_type ty) ^^ - G.i (Binary (Wasm.Values.I32 I32Op.Rotr)) ^^ + compile_rotr_const (shift_of_type ty) ^^ G.i (Unary (Wasm.Values.I32 I32Op.Ctz)) ^^ msb_adjust ty @@ -1542,122 +1555,499 @@ sig val fits_unsigned_bits : E.t -> int -> G.t end -[@@@warning "-60"] (* Do not warn about unused module *) -module BigNum64 : BigNumType = struct - include BoxedWord64 - - (* examine the skewed pointer and determine if the unsigned number - it points to fits into N bits *) - let fits_unsigned_bits env = function - | 64 -> G.i Drop ^^ compile_unboxed_one - | n when n > 64 || n < 1 -> assert false - | n -> - unbox env ^^ - compile_bitand64_const Int64.(shift_left minus_one n) ^^ - G.i (Test (Wasm.Values.I64 I64Op.Eqz)) - - (* examine the skewed pointer and determine if the signed number - it points to fits into N bits *) - let fits_signed_bits env = function - | n when n > 64 || n < 2 -> assert false - | 64 -> Bool.lit true - | n -> - let set_num, get_num = new_local64 env "num" in - unbox env ^^ set_num ^^ get_num ^^ get_num ^^ - compile_shl64_const 1L ^^ - G.i (Binary (Wasm.Values.I64 I64Op.Xor)) ^^ - compile_bitand64_const Int64.(shift_left minus_one n) ^^ - G.i (Test (Wasm.Values.I64 I64Op.Eqz)) +let i64op_from_relop = function + | Lt -> I64Op.LtS + | Le -> I64Op.LeS + | Ge -> I64Op.GeS + | Gt -> I64Op.GtS - let to_word32 env = - let (set_num, get_num) = new_local env "num" in - set_num ^^ get_num ^^ - fits_unsigned_bits env 32 ^^ - E.else_trap_with env "losing precision" ^^ - get_num ^^ - unbox env ^^ - BoxedWord64.to_word32 env +let name_from_relop = function + | Lt -> "B_lt" + | Le -> "B_le" + | Ge -> "B_ge" + | Gt -> "B_gt" - let from_word32 env = BoxedWord64.from_word32 env ^^ box env - let from_signed_word32 env = BoxedWord64.from_signed_word32 env ^^ box env - let from_signed_word64 env = G.i Unreachable (* FIXME *) - let to_word64 env = unbox env ^^ BoxedWord64.to_word64 env - let from_word64 env = BoxedWord64.from_word64 env ^^ box env +(* helper, measures the dynamics of the unsigned i32, returns (32 - effective bits) + expects i32 on stack *) +let unsigned_dynamics = + G.i (Unary (Wasm.Values.I32 I32Op.Clz)) - let truncate_to_word32 env = unbox env ^^ BoxedWord64.to_word32 env - let truncate_to_word64 env = unbox env ^^ BoxedWord64.to_word64 env +(* helper, measures the dynamics of the signed i32, returns (32 - effective bits) + expects two identical i32 copies on stack *) +let signed_dynamics = + compile_shl_const 1l ^^ + G.i (Binary (Wasm.Values.I32 I32Op.Xor)) ^^ + unsigned_dynamics - let compile_lit env n = compile_const_64 (Big_int.int64_of_big_int n) ^^ box env +module MakeCompact (Num : BigNumType) : BigNumType = struct - let compile_data_size_signed env = G.i Drop ^^ compile_unboxed_const 8l (* 64 bit for now *) - let compile_data_size_unsigned = compile_data_size_signed + (* Compact BigNums are a representation of signed 31-bit bignums (of the + underlying boxed representation `Num`), that fit into an i32. + The bits are encoded as - let compile_store_to_data_buf_unsigned env = - unbox env ^^ - G.i (Store {ty = I64Type; align = 0; offset = 0l; sz = None}) ^^ - compile_unboxed_const 8l (* 64 bit for now *) - let compile_store_to_data_buf_signed = compile_store_to_data_buf_unsigned + ┌──────────┬───┬──────┐ + │ mantissa │ 0 │ sign │ = i32 + └──────────┴───┴──────┘ + The 2nd LSBit makes unboxed bignums distinguishable from boxed ones, + the latter always being skewed pointers. - let compile_load_from_data_buf_signed env = - G.i (Load {ty = I64Type; align = 2; offset = 0l; sz = None}) ^^ - box env ^^ - compile_unboxed_const 8l (* 64 bit for now *) - let compile_load_from_data_buf_unsigned = compile_load_from_data_buf_signed + By a right rotation one obtains the signed (right-zero-padded) representation, + which is usable for arithmetic (e.g. addition-like operators). For some + operations (e.g. multiplication) the second argument needs to be furthermore + right-shifted. Similarly, for division the result must be left-shifted. - let compile_abs env = - let (set_i, get_i) = new_local env "abs_param" in - set_i ^^ - get_i ^^ - unbox env ^^ - compile_const_64 0L ^^ - G.i (Compare (Wasm.Values.I64 I64Op.LtS)) ^^ - G.if_ (ValBlockType (Some I32Type)) - ( compile_const_64 0L ^^ - get_i ^^ - unbox env ^^ - G.i (Binary (Wasm.Values.I64 I64Op.Sub)) ^^ - box env - ) - ( get_i ) - - let with_both_unboxed op env = - let set_tmp, get_tmp = new_local64 env "top" in - unbox env ^^ set_tmp ^^ unbox env ^^ get_tmp ^^ op ^^ box env - - let compile_add = with_both_unboxed (G.i (Binary (Wasm.Values.I64 I64Op.Add))) - let compile_signed_sub = with_both_unboxed (G.i (Binary (Wasm.Values.I64 I64Op.Sub))) - let compile_mul = with_both_unboxed (G.i (Binary (Wasm.Values.I64 I64Op.Mul))) - let compile_signed_div = with_both_unboxed (G.i (Binary (Wasm.Values.I64 I64Op.DivS))) - let compile_signed_mod = with_both_unboxed (G.i (Binary (Wasm.Values.I64 I64Op.RemS))) - let compile_unsigned_div = with_both_unboxed (G.i (Binary (Wasm.Values.I64 I64Op.DivU))) - let compile_unsigned_rem = with_both_unboxed (G.i (Binary (Wasm.Values.I64 I64Op.RemU))) - let compile_unsigned_sub env = with_both_unboxed (BoxedWord64.compile_unsigned_sub env) env - let compile_unsigned_pow env = with_both_unboxed (BoxedWord64.compile_unsigned_pow env) env + Generally all operations begin with checking whether both arguments are + already in unboxed form. If so, the arithmetic can be performed in machine + registers (fast path). Otherwise one or both arguments need boxing and the + arithmetic needs to be carried out on the underlying boxed representation + (slow path). + + The result appears as a boxed number in the latter case, so a check is + performed for possible compactification of the result. Conversely in the + former case the 64-bit result is either compactable or needs to be boxed. + + Manipulation of the result is unnecessary for the comparison predicates. + + For the `pow` operation the check that both arguments are unboxed is not + sufficient. Here we count and multiply effective bitwidths to figure out + whether the operation will overflow 64 bits, and if so, we fall back to the + slow path. + *) + + (* TODO: There is some unnecessary result shifting when the div result needs + to be boxed. Is this possible at all to happen? With (/-1) maybe! *) + + (* TODO: Does the result of the rem/mod fast path ever needs boxing? *) + + (* examine the skewed pointer and determine if number fits into 31 bits *) + let fits_in_vanilla env = Num.fits_signed_bits env 31 + + (* input right-padded with 0 *) + let extend = + compile_rotr_const 1l + + (* input right-padded with 0 *) + let extend64 = + extend ^^ + G.i (Convert (Wasm.Values.I64 I64Op.ExtendSI32)) + + (* predicate for i64 signed value, checking whether + the compact representation is viable; + bits should be 31 for right-aligned + and 32 for right-0-padded values *) + let speculate_compact64 bits = + compile_shl64_const 1L ^^ + G.i (Binary (Wasm.Values.I64 I64Op.Xor)) ^^ + compile_const_64 Int64.(shift_left minus_one bits) ^^ + G.i (Binary (Wasm.Values.I64 I64Op.And)) ^^ + G.i (Test (Wasm.Values.I64 I64Op.Eqz)) + + (* input is right-padded with 0 *) + let compress32 = compile_rotl_const 1l + + (* input is right-padded with 0 + precondition: upper 32 bits must be same as 32-bit sign, + i.e. speculate_compact64 is valid + *) + let compress64 = + G.i (Convert (Wasm.Values.I32 I32Op.WrapI64)) ^^ + compress32 + + let speculate_compact = + compile_shl_const 1l ^^ + G.i (Binary (Wasm.Values.I32 I32Op.Xor)) ^^ + compile_unboxed_const Int32.(shift_left minus_one 31) ^^ + G.i (Binary (Wasm.Values.I32 I32Op.And)) ^^ + G.i (Test (Wasm.Values.I32 I32Op.Eqz)) + + let compress = + compile_shl_const 1l ^^ compress32 + + (* creates a boxed bignum from a right-0-padded signed i64 *) + let box64 env = compile_shrS64_const 1L ^^ Num.from_signed_word64 env + + (* creates a boxed bignum from an unboxed 31-bit signed (and rotated) value *) + let extend_and_box64 env = extend64 ^^ box64 env + + (* check if both arguments are compact (i.e. unboxed), + if so, promote to signed i64 (with right bit (i.e. LSB) zero) and perform the fast path. + Otherwise make sure that both arguments are in heap representation, + and run the slow path on them. + In both cases bring the results into normal form. + *) + let try_unbox2 name fast slow env = + Func.share_code2 env name (("a", I32Type), ("b", I32Type)) [I32Type] + (fun env get_a get_b -> + let set_res, get_res = new_local env "res" in + let set_res64, get_res64 = new_local64 env "res64" in + get_a ^^ get_b ^^ + BitTagged.if_both_unboxed env (ValBlockType (Some I32Type)) + begin + get_a ^^ extend64 ^^ + get_b ^^ extend64 ^^ + fast env ^^ set_res64 ^^ + get_res64 ^^ get_res64 ^^ speculate_compact64 32 ^^ + G.if_ (ValBlockType (Some I32Type)) + (get_res64 ^^ compress64) + (get_res64 ^^ box64 env) + end + begin + get_a ^^ BitTagged.if_unboxed env (ValBlockType (Some I32Type)) + (get_a ^^ extend_and_box64 env) + get_a ^^ + get_b ^^ BitTagged.if_unboxed env (ValBlockType (Some I32Type)) + (get_b ^^ extend_and_box64 env) + get_b ^^ + slow env ^^ set_res ^^ get_res ^^ + fits_in_vanilla env ^^ + G.if_ (ValBlockType (Some I32Type)) + (get_res ^^ Num.truncate_to_word32 env ^^ compress) + get_res + end) + + let compile_add = try_unbox2 "B_add" BoxedWord64.compile_add Num.compile_add + + let adjust_arg2 code env = compile_shrS64_const 1L ^^ code env + let adjust_result code env = code env ^^ compile_shl64_const 1L + + let compile_mul = try_unbox2 "B_mul" (adjust_arg2 BoxedWord64.compile_mul) Num.compile_mul + let compile_signed_sub = try_unbox2 "B+sub" BoxedWord64.compile_signed_sub Num.compile_signed_sub + let compile_signed_div = try_unbox2 "B+div" (adjust_result BoxedWord64.compile_signed_div) Num.compile_signed_div + let compile_signed_mod = try_unbox2 "B_mod" BoxedWord64.compile_signed_mod Num.compile_signed_mod + let compile_unsigned_div = try_unbox2 "B_div" (adjust_result BoxedWord64.compile_unsigned_div) Num.compile_unsigned_div + let compile_unsigned_rem = try_unbox2 "B_rem" BoxedWord64.compile_unsigned_rem Num.compile_unsigned_rem + let compile_unsigned_sub = try_unbox2 "B_sub" BoxedWord64.compile_unsigned_sub Num.compile_unsigned_sub + + let compile_unsigned_pow env = + Func.share_code2 env "B_pow" (("a", I32Type), ("b", I32Type)) [I32Type] + (fun env get_a get_b -> + let set_res, get_res = new_local env "res" in + let set_a64, get_a64 = new_local64 env "a64" in + let set_b64, get_b64 = new_local64 env "b64" in + let set_res64, get_res64 = new_local64 env "res64" in + get_a ^^ get_b ^^ + BitTagged.if_both_unboxed env (ValBlockType (Some I32Type)) + begin + (* estimate bitcount of result: `bits(a) * b <= 65` guarantees + the absence of overflow in 64-bit arithmetic *) + get_a ^^ extend64 ^^ set_a64 ^^ compile_const_64 64L ^^ + get_a64 ^^ get_a64 ^^ compile_shrS64_const 1L ^^ + G.i (Binary (Wasm.Values.I64 I64Op.Xor)) ^^ + G.i (Unary (Wasm.Values.I64 I64Op.Clz)) ^^ G.i (Binary (Wasm.Values.I64 I64Op.Sub)) ^^ + get_b ^^ extend64 ^^ set_b64 ^^ get_b64 ^^ + G.i (Binary (Wasm.Values.I64 I64Op.Mul)) ^^ + compile_const_64 130L ^^ G.i (Compare (Wasm.Values.I64 I64Op.LeU)) ^^ + G.if_ (ValBlockType (Some I32Type)) + begin + get_a64 ^^ compile_shrS64_const 1L ^^ + get_b64 ^^ compile_shrS64_const 1L ^^ + BoxedWord64.compile_unsigned_pow env ^^ + compile_shl64_const 1L ^^ set_res64 ^^ + get_res64 ^^ get_res64 ^^ speculate_compact64 32 ^^ + G.if_ (ValBlockType (Some I32Type)) + (get_res64 ^^ compress64) + (get_res64 ^^ box64 env) + end + begin + get_a64 ^^ box64 env ^^ + get_b64 ^^ box64 env ^^ + Num.compile_unsigned_pow env ^^ set_res ^^ get_res ^^ + fits_in_vanilla env ^^ + G.if_ (ValBlockType (Some I32Type)) + (get_res ^^ Num.truncate_to_word32 env ^^ compress) + get_res + end + end + begin + get_a ^^ BitTagged.if_unboxed env (ValBlockType (Some I32Type)) + (get_a ^^ extend_and_box64 env) + get_a ^^ + get_b ^^ BitTagged.if_unboxed env (ValBlockType (Some I32Type)) + (get_b ^^ extend_and_box64 env) + get_b ^^ + Num.compile_unsigned_pow env ^^ set_res ^^ get_res ^^ + fits_in_vanilla env ^^ + G.if_ (ValBlockType (Some I32Type)) + (get_res ^^ Num.truncate_to_word32 env ^^ compress) + get_res + end) + + let compile_is_negative env = + let set_n, get_n = new_local env "n" in + set_n ^^ get_n ^^ + BitTagged.if_unboxed env (ValBlockType (Some I32Type)) + (get_n ^^ compile_bitand_const 1l) + (get_n ^^ Num.compile_is_negative env) + + let compile_lit env = function + | n when Big_int.(is_int_big_int n + && int_of_big_int n >= Int32.(to_int (shift_left 3l 30)) + && int_of_big_int n <= Int32.(to_int (shift_right_logical minus_one 2))) -> + let i = Int32.of_int (Big_int.int_of_big_int n) in + compile_unboxed_const Int32.(logor (shift_left i 2) (shift_right_logical i 31)) + | n -> Num.compile_lit env n let compile_neg env = - Func.share_code1 env "neg" ("n", I32Type) [I32Type] (fun env get_n -> - compile_lit env (Big_int.big_int_of_int 0) ^^ - get_n ^^ - compile_signed_sub env + Func.share_code1 env "B_neg" ("n", I32Type) [I32Type] (fun env get_n -> + get_n ^^ BitTagged.if_unboxed env (ValBlockType (Some I32Type)) + begin + get_n ^^ compile_unboxed_one ^^ + G.i (Compare (Wasm.Values.I32 I32Op.Eq)) ^^ + G.if_ (ValBlockType (Some I32Type)) + (compile_lit env (Big_int.big_int_of_int 0x40000000)) + begin + compile_unboxed_zero ^^ + get_n ^^ extend ^^ + G.i (Binary (Wasm.Values.I32 I32Op.Sub)) ^^ + compress32 + end + end + (get_n ^^ Num.compile_neg env) ) - let with_comp_unboxed op env = - let set_tmp, get_tmp = new_local64 env "top" in - unbox env ^^ set_tmp ^^ unbox env ^^ get_tmp ^^ op + let try_comp_unbox2 name fast slow env = + Func.share_code2 env name (("a", I32Type), ("b", I32Type)) [I32Type] + (fun env get_a get_b -> + get_a ^^ get_b ^^ + BitTagged.if_both_unboxed env (ValBlockType (Some I32Type)) + begin + get_a ^^ extend64 ^^ + get_b ^^ extend64 ^^ + fast env + end + begin + get_a ^^ BitTagged.if_unboxed env (ValBlockType (Some I32Type)) + (get_a ^^ extend_and_box64 env) + get_a ^^ + get_b ^^ BitTagged.if_unboxed env (ValBlockType (Some I32Type)) + (get_b ^^ extend_and_box64 env) + get_b ^^ + slow env + end) + + let compile_eq = try_comp_unbox2 "B_eq" BoxedWord64.compile_eq Num.compile_eq + let compile_relop env bigintop = + try_comp_unbox2 (name_from_relop bigintop) + (fun env' -> BoxedWord64.compile_relop env' (i64op_from_relop bigintop)) + (fun env' -> Num.compile_relop env' bigintop) + env + + let try_unbox iN fast slow env = + let set_a, get_a = new_local env "a" in + set_a ^^ get_a ^^ + BitTagged.if_unboxed env (ValBlockType (Some iN)) + (get_a ^^ fast env) + (get_a ^^ slow env) + + let fits_unsigned_bits env n = + try_unbox I32Type + (fun _ -> match n with + | _ when n >= 31 -> G.i Drop ^^ Bool.lit true + | 30 -> compile_bitand_const 1l ^^ G.i (Test (Wasm.Values.I32 I32Op.Eqz)) + | _ -> + compile_bitand_const + Int32.(logor 1l (shift_left minus_one (n + 2))) ^^ + G.i (Test (Wasm.Values.I32 I32Op.Eqz))) + (fun env -> Num.fits_unsigned_bits env n) + env + + let fits_signed_bits env n = + let set_a, get_a = new_local env "a" in + try_unbox I32Type + (fun _ -> match n with + | _ when n >= 31 -> G.i Drop ^^ Bool.lit true + | 30 -> + set_a ^^ get_a ^^ compile_shrU_const 31l ^^ + get_a ^^ compile_bitand_const 1l ^^ + G.i (Binary (Wasm.Values.I32 I32Op.And)) ^^ + G.i (Test (Wasm.Values.I32 I32Op.Eqz)) + | _ -> set_a ^^ get_a ^^ compile_rotr_const 1l ^^ set_a ^^ + get_a ^^ get_a ^^ compile_shrS_const 1l ^^ + G.i (Binary (Wasm.Values.I32 I32Op.Xor)) ^^ + compile_bitand_const + Int32.(shift_left minus_one n) ^^ + G.i (Test (Wasm.Values.I32 I32Op.Eqz))) + (fun env -> Num.fits_signed_bits env n) + env + + let compile_abs env = + try_unbox I32Type + begin + fun _ -> + let set_a, get_a = new_local env "a" in + set_a ^^ get_a ^^ + compile_bitand_const 1l ^^ + G.if_ (ValBlockType (Some I32Type)) + begin + get_a ^^ + compile_unboxed_one ^^ (* i.e. -(2**30) == -1073741824 *) + G.i (Compare (Wasm.Values.I32 I32Op.Eq)) ^^ + G.if_ (ValBlockType (Some I32Type)) + (compile_unboxed_const 0x40000000l ^^ Num.from_word32 env) (* is non-representable *) + begin + get_a ^^ + compile_unboxed_const Int32.minus_one ^^ G.i (Binary (Wasm.Values.I32 I32Op.Xor)) ^^ + compile_unboxed_const 2l ^^ G.i (Binary (Wasm.Values.I32 I32Op.Add)) + end + end + get_a + end + Num.compile_abs + env + + let compile_load_from_data_buf_unsigned env = + let set_res, get_res = new_local env "res" in + let set_size, get_size = new_local env "size" in + Num.compile_load_from_data_buf_unsigned env ^^ + set_size ^^ set_res ^^ get_res ^^ + fits_in_vanilla env ^^ + begin G.if_ (ValBlockType (Some I32Type)) + (get_res ^^ Num.truncate_to_word32 env ^^ compress) + get_res + end ^^ + get_size + + let compile_load_from_data_buf_signed env = + let set_res, get_res = new_local env "res" in + let set_size, get_size = new_local env "size" in + Num.compile_load_from_data_buf_signed env ^^ + set_size ^^ set_res ^^ get_res ^^ + fits_in_vanilla env ^^ + begin G.if_ (ValBlockType (Some I32Type)) + (get_res ^^ Num.truncate_to_word32 env ^^ compress) + get_res + end ^^ + get_size + + let compile_encoding_size dynamics get_x = + get_x ^^ G.if_ (ValBlockType (Some I32Type)) + begin + compile_unboxed_const 38l ^^ + get_x ^^ dynamics ^^ + G.i (Binary (Wasm.Values.I32 I32Op.Sub)) ^^ + compile_divU_const 7l + end + compile_unboxed_one + + let compile_leb128_size = compile_encoding_size unsigned_dynamics + let compile_sleb128_size get_x = compile_encoding_size (get_x ^^ signed_dynamics) get_x + + let compile_store_to_data_buf_unsigned env = + let set_x, get_x = new_local env "x" in + let set_buf, get_buf = new_local env "buf" in + set_x ^^ set_buf ^^ + get_x ^^ + try_unbox I32Type + (fun env -> + extend ^^ compile_shrS_const 1l ^^ set_x ^^ get_x ^^ + get_buf ^^ E.call_import env "rts" "leb128_encode" ^^ + compile_leb128_size get_x + ) + (fun env -> G.i Drop ^^ get_buf ^^ get_x ^^ Num.compile_store_to_data_buf_unsigned env) + env + + let compile_store_to_data_buf_signed env = + let set_x, get_x = new_local env "x" in + let set_buf, get_buf = new_local env "buf" in + set_x ^^ set_buf ^^ + get_x ^^ + try_unbox I32Type + (fun env -> + extend ^^ compile_shrS_const 1l ^^ set_x ^^ get_x ^^ + get_buf ^^ E.call_import env "rts" "sleb128_encode" ^^ + compile_sleb128_size get_x + ) + (fun env -> G.i Drop ^^ get_buf ^^ get_x ^^ Num.compile_store_to_data_buf_signed env) + env - let i64op_from_relop = function - | Lt -> I64Op.LtS - | Le -> I64Op.LeS - | Ge -> I64Op.GeS - | Gt -> I64Op.GtS + let compile_data_size_unsigned env = + try_unbox I32Type + (fun _ -> + let set_x, get_x = new_local env "x" in + extend ^^ compile_shrS_const 1l ^^ set_x ^^ + compile_leb128_size get_x + ) + (fun env -> Num.compile_data_size_unsigned env) + env + + let compile_data_size_signed env = + try_unbox I32Type + (fun _ -> + let set_x, get_x = new_local env "x" in + extend ^^ compile_shrS_const 1l ^^ set_x ^^ + compile_sleb128_size get_x + ) + (fun env -> Num.compile_data_size_unsigned env) + env + + let from_signed_word32 env = + let set_a, get_a = new_local env "a" in + set_a ^^ get_a ^^ get_a ^^ + speculate_compact ^^ + G.if_ (ValBlockType (Some I32Type)) + (get_a ^^ compress) + (get_a ^^ Num.from_signed_word32 env) + + let from_signed_word64 env = + let set_a, get_a = new_local64 env "a" in + set_a ^^ get_a ^^ get_a ^^ + speculate_compact64 31 ^^ + G.if_ (ValBlockType (Some I32Type)) + (get_a ^^ compile_shl64_const 1L ^^ compress64) + (get_a ^^ Num.from_signed_word64 env) + + let from_word32 env = + let set_a, get_a = new_local env "a" in + set_a ^^ get_a ^^ + compile_unboxed_const Int32.(shift_left minus_one 30) ^^ + G.i (Binary (Wasm.Values.I32 I32Op.And)) ^^ + G.i (Test (Wasm.Values.I32 I32Op.Eqz)) ^^ + G.if_ (ValBlockType (Some I32Type)) + (get_a ^^ compile_rotl_const 2l) + (get_a ^^ G.i (Convert (Wasm.Values.I64 I64Op.ExtendUI32)) ^^ Num.from_word64 env) + + let from_word64 env = + let set_a, get_a = new_local64 env "a" in + set_a ^^ get_a ^^ + compile_const_64 Int64.(shift_left minus_one 30) ^^ + G.i (Binary (Wasm.Values.I64 I64Op.And)) ^^ + G.i (Test (Wasm.Values.I64 I64Op.Eqz)) ^^ + G.if_ (ValBlockType (Some I32Type)) + (get_a ^^ G.i (Convert (Wasm.Values.I32 I32Op.WrapI64)) ^^ compile_rotl_const 2l) + (get_a ^^ Num.from_word64 env) - let compile_eq = with_comp_unboxed (G.i (Compare (Wasm.Values.I64 I64Op.Eq))) - let compile_relop env relop = with_comp_unboxed (G.i (Compare (Wasm.Values.I64 (i64op_from_relop relop)))) env - let compile_is_negative env = unbox env ^^ compile_const_64 0L ^^ G.i (Compare (Wasm.Values.I64 I64Op.LtS)) + let truncate_to_word64 env = + let set_a, get_a = new_local env "a" in + set_a ^^ get_a ^^ + BitTagged.if_unboxed env (ValBlockType (Some I64Type)) + begin + get_a ^^ extend ^^ compile_unboxed_one ^^ + G.i (Binary (Wasm.Values.I32 I32Op.ShrS)) ^^ + G.i (Convert (Wasm.Values.I64 I64Op.ExtendSI32)) + end + (get_a ^^ Num.truncate_to_word64 env) + let truncate_to_word32 env = + let set_a, get_a = new_local env "a" in + set_a ^^ get_a ^^ + BitTagged.if_unboxed env (ValBlockType (Some I32Type)) + (get_a ^^ extend ^^ compile_unboxed_one ^^ G.i (Binary (Wasm.Values.I32 I32Op.ShrS))) + (get_a ^^ Num.truncate_to_word32 env) + + let to_word64 env = + let set_a, get_a = new_local env "a" in + set_a ^^ get_a ^^ + BitTagged.if_unboxed env (ValBlockType (Some I64Type)) + (get_a ^^ extend64 ^^ compile_shrS64_const 1L) + (get_a ^^ Num.to_word64 env) + let to_word32 env = + let set_a, get_a = new_local env "a" in + set_a ^^ get_a ^^ + BitTagged.if_unboxed env (ValBlockType (Some I32Type)) + (get_a ^^ extend ^^ compile_unboxed_one ^^ G.i (Binary (Wasm.Values.I32 I32Op.ShrS))) + (get_a ^^ Num.to_word32 env) end -[@@@warning "+60"] -module BigNumLibtommmath : BigNumType = struct +module BigNumLibtommath : BigNumType = struct let to_word32 env = E.call_import env "rts" "bigint_to_word32_trap" let to_word64 env = E.call_import env "rts" "bigint_to_word64_trap" @@ -1763,9 +2153,9 @@ module BigNumLibtommmath : BigNumType = struct compile_unboxed_const (Int32.of_int bits) ^^ G.i (Compare (Wasm.Values.I32 I32Op.LeU)) -end (* BigNumLibtommmath *) +end (* BigNumLibtommath *) -module BigNum = BigNumLibtommmath +module BigNum = MakeCompact(BigNumLibtommath) (* Primitive functions *) module Prim = struct @@ -2807,6 +3197,9 @@ module Serialization = struct first that I can test, until we properly exercise this code (i.e. there is also the JS-side of things and we know it is bug-free). Writing a Wasm-native implementation of this will then be done separately. + + Update as of #469: we have leb128_encode and sleb128_encode in rts now! + This is #581. *) (* The IDL serialization prefaces the data with a type description. @@ -4615,18 +5008,6 @@ let compile_unop env t op = (* Logarithmic helpers for deciding whether we can carry out operations in constant bitwidth *) -(* helper, measures the dynamics of the signed i32, returns (32 - effective bits) - expects two identical i32 copies on stack *) -let signed_dynamics = - compile_shl_const 1l ^^ - G.i (Binary (Wasm.Values.I32 I32Op.Xor)) ^^ - G.i (Unary (Wasm.Values.I32 I32Op.Clz)) - -(* helper, measures the dynamics of the unsigned i32, returns (32 - effective bits) - expects i32 on stack *) -let unsigned_dynamics = - G.i (Unary (Wasm.Values.I32 I32Op.Clz)) - (* Compiling Int/Nat64 ops by conversion to/from BigNum. This is currently consing a lot, but compact bignums will get back efficiency as soon as they are merged. *) diff --git a/test/run-dfinity/data-params.as b/test/run-dfinity/data-params.as index c0f0036d724..c21161a79ae 100644 --- a/test/run-dfinity/data-params.as +++ b/test/run-dfinity/data-params.as @@ -88,6 +88,7 @@ let a = actor { }; +a.incn(0); a.incn(1); a.incn(2); a.incn(3); @@ -117,3 +118,10 @@ a.incints(-1,-2,-3,-4); a.incn(2**100); a.inci(2**100); a.inci(-(2**101)); +a.inci(-2**30); // lowest compact +a.inci(2**30 - 1); // highest compact +a.inci(0); +a.inci(1); +a.inci(42); +a.inci(-42); +a.incn(2**31 - 1); // highest compact diff --git a/test/run-dfinity/ok/data-params.dvm-run.ok b/test/run-dfinity/ok/data-params.dvm-run.ok index ad92e1130d0..0b6beb06559 100644 --- a/test/run-dfinity/ok/data-params.dvm-run.ok +++ b/test/run-dfinity/ok/data-params.dvm-run.ok @@ -1,3 +1,4 @@ +0 1 3 6 @@ -27,3 +28,10 @@ Foo2: 1006211 1267650600228229401496704211597 2535301200456458802993407416973 1006221 +1074748045 +2148489868 +2148489868 +2148489869 +2148489911 +2148489869 +4295973516 diff --git a/test/run-dfinity/ok/data-params.run-ir.ok b/test/run-dfinity/ok/data-params.run-ir.ok index 82fef50ca40..38d840277a7 100644 --- a/test/run-dfinity/ok/data-params.run-ir.ok +++ b/test/run-dfinity/ok/data-params.run-ir.ok @@ -2,6 +2,7 @@ data-params.as:59.30-59.40: warning, this pattern consuming type ?Text does not cover value null +0 1 3 6 @@ -31,3 +32,10 @@ Foo2: 1006211 1267650600228229401496704211597 2535301200456458802993407416973 1006221 +1074748045 +2148489868 +2148489868 +2148489869 +2148489911 +2148489869 +4295973516 diff --git a/test/run-dfinity/ok/data-params.run-low.ok b/test/run-dfinity/ok/data-params.run-low.ok index 82fef50ca40..38d840277a7 100644 --- a/test/run-dfinity/ok/data-params.run-low.ok +++ b/test/run-dfinity/ok/data-params.run-low.ok @@ -2,6 +2,7 @@ data-params.as:59.30-59.40: warning, this pattern consuming type ?Text does not cover value null +0 1 3 6 @@ -31,3 +32,10 @@ Foo2: 1006211 1267650600228229401496704211597 2535301200456458802993407416973 1006221 +1074748045 +2148489868 +2148489868 +2148489869 +2148489911 +2148489869 +4295973516 diff --git a/test/run-dfinity/ok/data-params.run.ok b/test/run-dfinity/ok/data-params.run.ok index 82fef50ca40..38d840277a7 100644 --- a/test/run-dfinity/ok/data-params.run.ok +++ b/test/run-dfinity/ok/data-params.run.ok @@ -2,6 +2,7 @@ data-params.as:59.30-59.40: warning, this pattern consuming type ?Text does not cover value null +0 1 3 6 @@ -31,3 +32,10 @@ Foo2: 1006211 1267650600228229401496704211597 2535301200456458802993407416973 1006221 +1074748045 +2148489868 +2148489868 +2148489869 +2148489911 +2148489869 +4295973516 diff --git a/test/run/numeric-ops.as b/test/run/numeric-ops.as index 719d36b673e..240df731f9c 100644 --- a/test/run/numeric-ops.as +++ b/test/run/numeric-ops.as @@ -13,6 +13,7 @@ func verify(etalon : [T], results : [T], cmp : (T, T) -> Bool) { }; func intCompare (a : Int, b : Int) : Bool = a == b; +func natCompare (a : Nat, b : Nat) : Bool = a == b; // Numeric operators @@ -32,7 +33,10 @@ func testNat(a : Nat, b : Nat) : [Nat] { [sum1, sum2, diff1, diff2, prod1, prod2, rat1, rat2, mod1, mod2, pow1, pow2] }; -verify([8, 2, 15, 1, 2, 125], testNat(5, 3), func (a : Nat, b : Nat) : Bool = a == b); +verify([8, 2, 15, 1, 2, 125], testNat(5, 3), natCompare); +verify([41, 21, 310, 3, 1, 819628286980801], testNat(31, 10), natCompare); +verify([42, 20, 341, 2, 9, 25408476896404831], testNat(31, 11), natCompare); +verify([1500000002, 1499999998, 3000000000, 750000000, 0, 2250000000000000000], testNat(1500000000, 2), natCompare); func testInt(a : Int, b : Int) : [Int] { let pos1 = + a; @@ -55,6 +59,35 @@ func testInt(a : Int, b : Int) : [Int] { }; verify([3, -3, 8, -2, 15, 0, 3, 243], testInt(3, 5), intCompare); +verify([-31, 31, -21, -41, -310, -3, -1, 819628286980801], testInt(-31, 10), intCompare); +verify([-31, 31, -20, -42, -341, -2, -9, -25408476896404831], testInt(-31, 11), intCompare); +verify([-1500000000, 1500000000, -1499999998, -1500000002, -3000000000, -750000000, 0, 2250000000000000000], testInt(-1500000000, 2), intCompare); + +func testIntAbs(a : Int) : [Int] { + let abs1 = abs a; + let abs2 = (abs a) : Int; + let abs3 = abs (-a); + let abs4 = (abs (-a)) : Int; + [abs1, abs2, abs3, abs4] +}; + +verify([4567, 4567], testIntAbs(-4567), intCompare); +verify([1073741824, 1073741824], testIntAbs(-1073741824), intCompare); + +func testIntNegation(a : Int) : [Int] { + let neg1 = -a; + let neg2 = (-a) : Int; + [neg1, neg2] +}; + +verify([0x80000000], testIntNegation(-0x80000000), intCompare); +verify([-0x80000000], testIntNegation(0x80000000), intCompare); +verify([0x40000000], testIntNegation(-0x40000000), intCompare); +verify([-0x40000000], testIntNegation(0x40000000), intCompare); +verify([0x30000000], testIntNegation(-0x30000000), intCompare); +verify([-0x30000000], testIntNegation(0x30000000), intCompare); +verify([3], testIntNegation(-3), intCompare); +verify([-3], testIntNegation(3), intCompare); func testNatInt(a : Nat, b : Int) : [Int] { let pos1 = + a; diff --git a/test/run/ok/overflow.wasm-run.ok b/test/run/ok/overflow.wasm-run.ok index 880c476f3f5..7c22e438c43 100644 --- a/test/run/ok/overflow.wasm-run.ok +++ b/test/run/ok/overflow.wasm-run.ok @@ -1 +1 @@ -_out/overflow.wasm:0x___: runtime trap: unreachable executed +_out/overflow.wasm:0x___: runtime trap: integer divide by zero diff --git a/test/run/small-pow.as b/test/run/small-pow.as new file mode 100644 index 00000000000..8d0af321938 --- /dev/null +++ b/test/run/small-pow.as @@ -0,0 +1,516 @@ +/* +This can be read as literate Haskell (temporarily `ln ../test/run/small-pow.as ../test/run/small-pow.lhs`) + +> import Data.Bits +> import Data.Word +> +> effbits :: FiniteBits a => a -> Int +> effbits a = finiteBitSize a - countLeadingZeros (a `xor` (a `shiftL` 1)) +> +> extremal :: FiniteBits a => Int -> [a] +> extremal 0 = [zeroBits] +> extremal 1 = [complement zeroBits] +> extremal n = [complement zeroBits `shiftL` pred n, let max = complement zeroBits `shiftR` (finiteBitSize max - pred n) in max] +> +> asBigNum :: (Integral a, FiniteBits a) => a -> Integer +> asBigNum a | a `testBit` 63 = - fromIntegral (complement a) - 1 +> asBigNum a = fromIntegral a +> +> showBig = show . asBigNum +> +> main = sequence_ [ putStrLn ("assert (" ++ showBig n ++ " ** " ++ show e ++ " == " ++ show n' ++ ");") +> | b <- [0 .. 31], e <- [0 .. 31], b * e <= 65, n <- extremal b :: [Word64] +> , let n' = asBigNum n ^ fromIntegral e ] + +*/ + +assert (0 ** 0 == 1); +assert (0 ** 1 == 0); +assert (0 ** 2 == 0); +assert (0 ** 3 == 0); +assert (0 ** 4 == 0); +assert (0 ** 5 == 0); +assert (0 ** 6 == 0); +assert (0 ** 7 == 0); +assert (0 ** 8 == 0); +assert (0 ** 9 == 0); +assert (0 ** 10 == 0); +assert (0 ** 11 == 0); +assert (0 ** 12 == 0); +assert (0 ** 13 == 0); +assert (0 ** 14 == 0); +assert (0 ** 15 == 0); +assert (0 ** 16 == 0); +assert (0 ** 17 == 0); +assert (0 ** 18 == 0); +assert (0 ** 19 == 0); +assert (0 ** 20 == 0); +assert (0 ** 21 == 0); +assert (0 ** 22 == 0); +assert (0 ** 23 == 0); +assert (0 ** 24 == 0); +assert (0 ** 25 == 0); +assert (0 ** 26 == 0); +assert (0 ** 27 == 0); +assert (0 ** 28 == 0); +assert (0 ** 29 == 0); +assert (0 ** 30 == 0); +assert (0 ** 31 == 0); +assert (-1 ** 0 == 1); +assert (-1 ** 1 == -1); +assert (-1 ** 2 == 1); +assert (-1 ** 3 == -1); +assert (-1 ** 4 == 1); +assert (-1 ** 5 == -1); +assert (-1 ** 6 == 1); +assert (-1 ** 7 == -1); +assert (-1 ** 8 == 1); +assert (-1 ** 9 == -1); +assert (-1 ** 10 == 1); +assert (-1 ** 11 == -1); +assert (-1 ** 12 == 1); +assert (-1 ** 13 == -1); +assert (-1 ** 14 == 1); +assert (-1 ** 15 == -1); +assert (-1 ** 16 == 1); +assert (-1 ** 17 == -1); +assert (-1 ** 18 == 1); +assert (-1 ** 19 == -1); +assert (-1 ** 20 == 1); +assert (-1 ** 21 == -1); +assert (-1 ** 22 == 1); +assert (-1 ** 23 == -1); +assert (-1 ** 24 == 1); +assert (-1 ** 25 == -1); +assert (-1 ** 26 == 1); +assert (-1 ** 27 == -1); +assert (-1 ** 28 == 1); +assert (-1 ** 29 == -1); +assert (-1 ** 30 == 1); +assert (-1 ** 31 == -1); +assert (-2 ** 0 == 1); +assert (1 ** 0 == 1); +assert (-2 ** 1 == -2); +assert (1 ** 1 == 1); +assert (-2 ** 2 == 4); +assert (1 ** 2 == 1); +assert (-2 ** 3 == -8); +assert (1 ** 3 == 1); +assert (-2 ** 4 == 16); +assert (1 ** 4 == 1); +assert (-2 ** 5 == -32); +assert (1 ** 5 == 1); +assert (-2 ** 6 == 64); +assert (1 ** 6 == 1); +assert (-2 ** 7 == -128); +assert (1 ** 7 == 1); +assert (-2 ** 8 == 256); +assert (1 ** 8 == 1); +assert (-2 ** 9 == -512); +assert (1 ** 9 == 1); +assert (-2 ** 10 == 1024); +assert (1 ** 10 == 1); +assert (-2 ** 11 == -2048); +assert (1 ** 11 == 1); +assert (-2 ** 12 == 4096); +assert (1 ** 12 == 1); +assert (-2 ** 13 == -8192); +assert (1 ** 13 == 1); +assert (-2 ** 14 == 16384); +assert (1 ** 14 == 1); +assert (-2 ** 15 == -32768); +assert (1 ** 15 == 1); +assert (-2 ** 16 == 65536); +assert (1 ** 16 == 1); +assert (-2 ** 17 == -131072); +assert (1 ** 17 == 1); +assert (-2 ** 18 == 262144); +assert (1 ** 18 == 1); +assert (-2 ** 19 == -524288); +assert (1 ** 19 == 1); +assert (-2 ** 20 == 1048576); +assert (1 ** 20 == 1); +assert (-2 ** 21 == -2097152); +assert (1 ** 21 == 1); +assert (-2 ** 22 == 4194304); +assert (1 ** 22 == 1); +assert (-2 ** 23 == -8388608); +assert (1 ** 23 == 1); +assert (-2 ** 24 == 16777216); +assert (1 ** 24 == 1); +assert (-2 ** 25 == -33554432); +assert (1 ** 25 == 1); +assert (-2 ** 26 == 67108864); +assert (1 ** 26 == 1); +assert (-2 ** 27 == -134217728); +assert (1 ** 27 == 1); +assert (-2 ** 28 == 268435456); +assert (1 ** 28 == 1); +assert (-2 ** 29 == -536870912); +assert (1 ** 29 == 1); +assert (-2 ** 30 == 1073741824); +assert (1 ** 30 == 1); +assert (-2 ** 31 == -2147483648); +assert (1 ** 31 == 1); +assert (-4 ** 0 == 1); +assert (3 ** 0 == 1); +assert (-4 ** 1 == -4); +assert (3 ** 1 == 3); +assert (-4 ** 2 == 16); +assert (3 ** 2 == 9); +assert (-4 ** 3 == -64); +assert (3 ** 3 == 27); +assert (-4 ** 4 == 256); +assert (3 ** 4 == 81); +assert (-4 ** 5 == -1024); +assert (3 ** 5 == 243); +assert (-4 ** 6 == 4096); +assert (3 ** 6 == 729); +assert (-4 ** 7 == -16384); +assert (3 ** 7 == 2187); +assert (-4 ** 8 == 65536); +assert (3 ** 8 == 6561); +assert (-4 ** 9 == -262144); +assert (3 ** 9 == 19683); +assert (-4 ** 10 == 1048576); +assert (3 ** 10 == 59049); +assert (-4 ** 11 == -4194304); +assert (3 ** 11 == 177147); +assert (-4 ** 12 == 16777216); +assert (3 ** 12 == 531441); +assert (-4 ** 13 == -67108864); +assert (3 ** 13 == 1594323); +assert (-4 ** 14 == 268435456); +assert (3 ** 14 == 4782969); +assert (-4 ** 15 == -1073741824); +assert (3 ** 15 == 14348907); +assert (-4 ** 16 == 4294967296); +assert (3 ** 16 == 43046721); +assert (-4 ** 17 == -17179869184); +assert (3 ** 17 == 129140163); +assert (-4 ** 18 == 68719476736); +assert (3 ** 18 == 387420489); +assert (-4 ** 19 == -274877906944); +assert (3 ** 19 == 1162261467); +assert (-4 ** 20 == 1099511627776); +assert (3 ** 20 == 3486784401); +assert (-4 ** 21 == -4398046511104); +assert (3 ** 21 == 10460353203); +assert (-8 ** 0 == 1); +assert (7 ** 0 == 1); +assert (-8 ** 1 == -8); +assert (7 ** 1 == 7); +assert (-8 ** 2 == 64); +assert (7 ** 2 == 49); +assert (-8 ** 3 == -512); +assert (7 ** 3 == 343); +assert (-8 ** 4 == 4096); +assert (7 ** 4 == 2401); +assert (-8 ** 5 == -32768); +assert (7 ** 5 == 16807); +assert (-8 ** 6 == 262144); +assert (7 ** 6 == 117649); +assert (-8 ** 7 == -2097152); +assert (7 ** 7 == 823543); +assert (-8 ** 8 == 16777216); +assert (7 ** 8 == 5764801); +assert (-8 ** 9 == -134217728); +assert (7 ** 9 == 40353607); +assert (-8 ** 10 == 1073741824); +assert (7 ** 10 == 282475249); +assert (-8 ** 11 == -8589934592); +assert (7 ** 11 == 1977326743); +assert (-8 ** 12 == 68719476736); +assert (7 ** 12 == 13841287201); +assert (-8 ** 13 == -549755813888); +assert (7 ** 13 == 96889010407); +assert (-8 ** 14 == 4398046511104); +assert (7 ** 14 == 678223072849); +assert (-8 ** 15 == -35184372088832); +assert (7 ** 15 == 4747561509943); +assert (-8 ** 16 == 281474976710656); +assert (7 ** 16 == 33232930569601); +assert (-16 ** 0 == 1); +assert (15 ** 0 == 1); +assert (-16 ** 1 == -16); +assert (15 ** 1 == 15); +assert (-16 ** 2 == 256); +assert (15 ** 2 == 225); +assert (-16 ** 3 == -4096); +assert (15 ** 3 == 3375); +assert (-16 ** 4 == 65536); +assert (15 ** 4 == 50625); +assert (-16 ** 5 == -1048576); +assert (15 ** 5 == 759375); +assert (-16 ** 6 == 16777216); +assert (15 ** 6 == 11390625); +assert (-16 ** 7 == -268435456); +assert (15 ** 7 == 170859375); +assert (-16 ** 8 == 4294967296); +assert (15 ** 8 == 2562890625); +assert (-16 ** 9 == -68719476736); +assert (15 ** 9 == 38443359375); +assert (-16 ** 10 == 1099511627776); +assert (15 ** 10 == 576650390625); +assert (-16 ** 11 == -17592186044416); +assert (15 ** 11 == 8649755859375); +assert (-16 ** 12 == 281474976710656); +assert (15 ** 12 == 129746337890625); +assert (-16 ** 13 == -4503599627370496); +assert (15 ** 13 == 1946195068359375); +assert (-32 ** 0 == 1); +assert (31 ** 0 == 1); +assert (-32 ** 1 == -32); +assert (31 ** 1 == 31); +assert (-32 ** 2 == 1024); +assert (31 ** 2 == 961); +assert (-32 ** 3 == -32768); +assert (31 ** 3 == 29791); +assert (-32 ** 4 == 1048576); +assert (31 ** 4 == 923521); +assert (-32 ** 5 == -33554432); +assert (31 ** 5 == 28629151); +assert (-32 ** 6 == 1073741824); +assert (31 ** 6 == 887503681); +assert (-32 ** 7 == -34359738368); +assert (31 ** 7 == 27512614111); +assert (-32 ** 8 == 1099511627776); +assert (31 ** 8 == 852891037441); +assert (-32 ** 9 == -35184372088832); +assert (31 ** 9 == 26439622160671); +assert (-32 ** 10 == 1125899906842624); +assert (31 ** 10 == 819628286980801); +assert (-64 ** 0 == 1); +assert (63 ** 0 == 1); +assert (-64 ** 1 == -64); +assert (63 ** 1 == 63); +assert (-64 ** 2 == 4096); +assert (63 ** 2 == 3969); +assert (-64 ** 3 == -262144); +assert (63 ** 3 == 250047); +assert (-64 ** 4 == 16777216); +assert (63 ** 4 == 15752961); +assert (-64 ** 5 == -1073741824); +assert (63 ** 5 == 992436543); +assert (-64 ** 6 == 68719476736); +assert (63 ** 6 == 62523502209); +assert (-64 ** 7 == -4398046511104); +assert (63 ** 7 == 3938980639167); +assert (-64 ** 8 == 281474976710656); +assert (63 ** 8 == 248155780267521); +assert (-64 ** 9 == -18014398509481984); +assert (63 ** 9 == 15633814156853823); +assert (-128 ** 0 == 1); +assert (127 ** 0 == 1); +assert (-128 ** 1 == -128); +assert (127 ** 1 == 127); +assert (-128 ** 2 == 16384); +assert (127 ** 2 == 16129); +assert (-128 ** 3 == -2097152); +assert (127 ** 3 == 2048383); +assert (-128 ** 4 == 268435456); +assert (127 ** 4 == 260144641); +assert (-128 ** 5 == -34359738368); +assert (127 ** 5 == 33038369407); +assert (-128 ** 6 == 4398046511104); +assert (127 ** 6 == 4195872914689); +assert (-128 ** 7 == -562949953421312); +assert (127 ** 7 == 532875860165503); +assert (-128 ** 8 == 72057594037927936); +assert (127 ** 8 == 67675234241018881); +assert (-256 ** 0 == 1); +assert (255 ** 0 == 1); +assert (-256 ** 1 == -256); +assert (255 ** 1 == 255); +assert (-256 ** 2 == 65536); +assert (255 ** 2 == 65025); +assert (-256 ** 3 == -16777216); +assert (255 ** 3 == 16581375); +assert (-256 ** 4 == 4294967296); +assert (255 ** 4 == 4228250625); +assert (-256 ** 5 == -1099511627776); +assert (255 ** 5 == 1078203909375); +assert (-256 ** 6 == 281474976710656); +assert (255 ** 6 == 274941996890625); +assert (-256 ** 7 == -72057594037927936); +assert (255 ** 7 == 70110209207109375); +assert (-512 ** 0 == 1); +assert (511 ** 0 == 1); +assert (-512 ** 1 == -512); +assert (511 ** 1 == 511); +assert (-512 ** 2 == 262144); +assert (511 ** 2 == 261121); +assert (-512 ** 3 == -134217728); +assert (511 ** 3 == 133432831); +assert (-512 ** 4 == 68719476736); +assert (511 ** 4 == 68184176641); +assert (-512 ** 5 == -35184372088832); +assert (511 ** 5 == 34842114263551); +assert (-512 ** 6 == 18014398509481984); +assert (511 ** 6 == 17804320388674561); +assert (-1024 ** 0 == 1); +assert (1023 ** 0 == 1); +assert (-1024 ** 1 == -1024); +assert (1023 ** 1 == 1023); +assert (-1024 ** 2 == 1048576); +assert (1023 ** 2 == 1046529); +assert (-1024 ** 3 == -1073741824); +assert (1023 ** 3 == 1070599167); +assert (-1024 ** 4 == 1099511627776); +assert (1023 ** 4 == 1095222947841); +assert (-1024 ** 5 == -1125899906842624); +assert (1023 ** 5 == 1120413075641343); +assert (-2048 ** 0 == 1); +assert (2047 ** 0 == 1); +assert (-2048 ** 1 == -2048); +assert (2047 ** 1 == 2047); +assert (-2048 ** 2 == 4194304); +assert (2047 ** 2 == 4190209); +assert (-2048 ** 3 == -8589934592); +assert (2047 ** 3 == 8577357823); +assert (-2048 ** 4 == 17592186044416); +assert (2047 ** 4 == 17557851463681); +assert (-2048 ** 5 == -36028797018963968); +assert (2047 ** 5 == 35940921946155007); +assert (-4096 ** 0 == 1); +assert (4095 ** 0 == 1); +assert (-4096 ** 1 == -4096); +assert (4095 ** 1 == 4095); +assert (-4096 ** 2 == 16777216); +assert (4095 ** 2 == 16769025); +assert (-4096 ** 3 == -68719476736); +assert (4095 ** 3 == 68669157375); +assert (-4096 ** 4 == 281474976710656); +assert (4095 ** 4 == 281200199450625); +assert (-4096 ** 5 == -1152921504606846976); +assert (4095 ** 5 == 1151514816750309375); +assert (-8192 ** 0 == 1); +assert (8191 ** 0 == 1); +assert (-8192 ** 1 == -8192); +assert (8191 ** 1 == 8191); +assert (-8192 ** 2 == 67108864); +assert (8191 ** 2 == 67092481); +assert (-8192 ** 3 == -549755813888); +assert (8191 ** 3 == 549554511871); +assert (-8192 ** 4 == 4503599627370496); +assert (8191 ** 4 == 4501401006735361); +assert (-16384 ** 0 == 1); +assert (16383 ** 0 == 1); +assert (-16384 ** 1 == -16384); +assert (16383 ** 1 == 16383); +assert (-16384 ** 2 == 268435456); +assert (16383 ** 2 == 268402689); +assert (-16384 ** 3 == -4398046511104); +assert (16383 ** 3 == 4397241253887); +assert (-16384 ** 4 == 72057594037927936); +assert (16383 ** 4 == 72040003462430721); +assert (-32768 ** 0 == 1); +assert (32767 ** 0 == 1); +assert (-32768 ** 1 == -32768); +assert (32767 ** 1 == 32767); +assert (-32768 ** 2 == 1073741824); +assert (32767 ** 2 == 1073676289); +assert (-32768 ** 3 == -35184372088832); +assert (32767 ** 3 == 35181150961663); +assert (-32768 ** 4 == 1152921504606846976); +assert (32767 ** 4 == 1152780773560811521); +assert (-65536 ** 0 == 1); +assert (65535 ** 0 == 1); +assert (-65536 ** 1 == -65536); +assert (65535 ** 1 == 65535); +assert (-65536 ** 2 == 4294967296); +assert (65535 ** 2 == 4294836225); +assert (-65536 ** 3 == -281474976710656); +assert (65535 ** 3 == 281462092005375); +assert (-131072 ** 0 == 1); +assert (131071 ** 0 == 1); +assert (-131072 ** 1 == -131072); +assert (131071 ** 1 == 131071); +assert (-131072 ** 2 == 17179869184); +assert (131071 ** 2 == 17179607041); +assert (-131072 ** 3 == -2251799813685248); +assert (131071 ** 3 == 2251748274470911); +assert (-262144 ** 0 == 1); +assert (262143 ** 0 == 1); +assert (-262144 ** 1 == -262144); +assert (262143 ** 1 == 262143); +assert (-262144 ** 2 == 68719476736); +assert (262143 ** 2 == 68718952449); +assert (-262144 ** 3 == -18014398509481984); +assert (262143 ** 3 == 18014192351838207); +assert (-524288 ** 0 == 1); +assert (524287 ** 0 == 1); +assert (-524288 ** 1 == -524288); +assert (524287 ** 1 == 524287); +assert (-524288 ** 2 == 274877906944); +assert (524287 ** 2 == 274876858369); +assert (-524288 ** 3 == -144115188075855872); +assert (524287 ** 3 == 144114363443707903); +assert (-1048576 ** 0 == 1); +assert (1048575 ** 0 == 1); +assert (-1048576 ** 1 == -1048576); +assert (1048575 ** 1 == 1048575); +assert (-1048576 ** 2 == 1099511627776); +assert (1048575 ** 2 == 1099509530625); +assert (-1048576 ** 3 == -1152921504606846976); +assert (1048575 ** 3 == 1152918206075109375); +assert (-2097152 ** 0 == 1); +assert (2097151 ** 0 == 1); +assert (-2097152 ** 1 == -2097152); +assert (2097151 ** 1 == 2097151); +assert (-2097152 ** 2 == 4398046511104); +assert (2097151 ** 2 == 4398042316801); +assert (-4194304 ** 0 == 1); +assert (4194303 ** 0 == 1); +assert (-4194304 ** 1 == -4194304); +assert (4194303 ** 1 == 4194303); +assert (-4194304 ** 2 == 17592186044416); +assert (4194303 ** 2 == 17592177655809); +assert (-8388608 ** 0 == 1); +assert (8388607 ** 0 == 1); +assert (-8388608 ** 1 == -8388608); +assert (8388607 ** 1 == 8388607); +assert (-8388608 ** 2 == 70368744177664); +assert (8388607 ** 2 == 70368727400449); +assert (-16777216 ** 0 == 1); +assert (16777215 ** 0 == 1); +assert (-16777216 ** 1 == -16777216); +assert (16777215 ** 1 == 16777215); +assert (-16777216 ** 2 == 281474976710656); +assert (16777215 ** 2 == 281474943156225); +assert (-33554432 ** 0 == 1); +assert (33554431 ** 0 == 1); +assert (-33554432 ** 1 == -33554432); +assert (33554431 ** 1 == 33554431); +assert (-33554432 ** 2 == 1125899906842624); +assert (33554431 ** 2 == 1125899839733761); +assert (-67108864 ** 0 == 1); +assert (67108863 ** 0 == 1); +assert (-67108864 ** 1 == -67108864); +assert (67108863 ** 1 == 67108863); +assert (-67108864 ** 2 == 4503599627370496); +assert (67108863 ** 2 == 4503599493152769); +assert (-134217728 ** 0 == 1); +assert (134217727 ** 0 == 1); +assert (-134217728 ** 1 == -134217728); +assert (134217727 ** 1 == 134217727); +assert (-134217728 ** 2 == 18014398509481984); +assert (134217727 ** 2 == 18014398241046529); +assert (-268435456 ** 0 == 1); +assert (268435455 ** 0 == 1); +assert (-268435456 ** 1 == -268435456); +assert (268435455 ** 1 == 268435455); +assert (-268435456 ** 2 == 72057594037927936); +assert (268435455 ** 2 == 72057593501057025); +assert (-536870912 ** 0 == 1); +assert (536870911 ** 0 == 1); +assert (-536870912 ** 1 == -536870912); +assert (536870911 ** 1 == 536870911); +assert (-536870912 ** 2 == 288230376151711744); +assert (536870911 ** 2 == 288230375077969921); +assert (-1073741824 ** 0 == 1); +assert (1073741823 ** 0 == 1); +assert (-1073741824 ** 1 == -1073741824); +assert (1073741823 ** 1 == 1073741823); +assert (-1073741824 ** 2 == 1152921504606846976); +assert (1073741823 ** 2 == 1152921502459363329); From bbe5fc0cbd38b782fa7240c78c65b47c7ec84a42 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Wed, 24 Jul 2019 15:54:20 +0200 Subject: [PATCH 0315/1176] ACT-65 range-check word32ToChar (#595) --- src/as_values/prim.ml | 2 +- src/codegen/compile.ml | 7 ++++++- test/fail/char-trap.as | 1 + test/fail/ok/char-trap.run-ir.ok | 1 + test/fail/ok/char-trap.run-low.ok | 1 + test/fail/ok/char-trap.run.ok | 1 + test/fail/ok/char-trap.wasm-run.ok | 1 + 7 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 test/fail/char-trap.as create mode 100644 test/fail/ok/char-trap.run-ir.ok create mode 100644 test/fail/ok/char-trap.run-low.ok create mode 100644 test/fail/ok/char-trap.run.ok create mode 100644 test/fail/ok/char-trap.wasm-run.ok diff --git a/src/as_values/prim.ml b/src/as_values/prim.ml index 1adc64a5ba5..ce2e966d8bc 100644 --- a/src/as_values/prim.ml +++ b/src/as_values/prim.ml @@ -192,7 +192,7 @@ let prim = function in k (Word32 (Word32.of_int_u i)) | "Word32->Char" -> fun v k -> let i = Conv.of_signed_Word32 (as_word32 v) - in k (Char i) + in if i <= 0x10FFFF then k (Char i) else raise (Invalid_argument "codepoint out of bounds") | "popcnt8" | "popcnt16" | "popcnt" | "popcnt64" -> fun v k -> diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 646990a3819..1ba4854f5ff 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -5808,7 +5808,12 @@ and compile_exp (env : E.t) ae exp = | OtherPrim "Word32->Char", [e] -> SR.Vanilla, compile_exp_as env ae SR.UnboxedWord32 e ^^ - UnboxedSmallWord.box_codepoint + Func.share_code1 env "Word32->Char" ("n", I32Type) [I32Type] + (fun env get_n -> + get_n ^^ compile_unboxed_const 0x10FFFFl ^^ + G.i (Compare (Wasm.Values.I32 I32Op.GtU)) ^^ + E.then_trap_with env "codepoint out of range" ^^ + get_n ^^ UnboxedSmallWord.box_codepoint) | OtherPrim "popcnt", [e] -> SR.UnboxedWord32, diff --git a/test/fail/char-trap.as b/test/fail/char-trap.as new file mode 100644 index 00000000000..84430038a79 --- /dev/null +++ b/test/fail/char-trap.as @@ -0,0 +1 @@ +let _ = word32ToChar 0x110000 diff --git a/test/fail/ok/char-trap.run-ir.ok b/test/fail/ok/char-trap.run-ir.ok new file mode 100644 index 00000000000..46eac08816e --- /dev/null +++ b/test/fail/ok/char-trap.run-ir.ok @@ -0,0 +1 @@ +prelude:___: execution error, codepoint out of bounds diff --git a/test/fail/ok/char-trap.run-low.ok b/test/fail/ok/char-trap.run-low.ok new file mode 100644 index 00000000000..46eac08816e --- /dev/null +++ b/test/fail/ok/char-trap.run-low.ok @@ -0,0 +1 @@ +prelude:___: execution error, codepoint out of bounds diff --git a/test/fail/ok/char-trap.run.ok b/test/fail/ok/char-trap.run.ok new file mode 100644 index 00000000000..46eac08816e --- /dev/null +++ b/test/fail/ok/char-trap.run.ok @@ -0,0 +1 @@ +prelude:___: execution error, codepoint out of bounds diff --git a/test/fail/ok/char-trap.wasm-run.ok b/test/fail/ok/char-trap.wasm-run.ok new file mode 100644 index 00000000000..1aa5d820042 --- /dev/null +++ b/test/fail/ok/char-trap.wasm-run.ok @@ -0,0 +1 @@ +_out/char-trap.wasm:0x___: runtime trap: unreachable executed From 6488f6b37edfe182617d2776b9ad12184b986faa Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Thu, 25 Jul 2019 12:36:44 +0100 Subject: [PATCH 0316/1176] Claudio/cyclic bounds (#586) * reject cyclic bounds in source and ir * reject cyclic bounds in source and ir * split into three tests * add normalizaton step; test for cyclic bounds via type abbreviations; address nits --- src/as_frontend/typing.ml | 24 ++++++++++++++++++++++-- src/as_types/type.mli | 1 + src/ir_def/check_ir.ml | 29 +++++++++++++++++++++++------ test/fail/cyclic-bound1.as | 7 +++++++ test/fail/cyclic-bound2.as | 7 +++++++ test/fail/cyclic-bound3.as | 7 +++++++ test/fail/cyclic-bound4.as | 11 +++++++++++ test/fail/cyclic-bound5.as | 7 +++++++ test/fail/ok/cyclic-bound1.tc.ok | 1 + test/fail/ok/cyclic-bound2.tc.ok | 1 + test/fail/ok/cyclic-bound3.tc.ok | 1 + test/fail/ok/cyclic-bound4.tc.ok | 1 + test/fail/ok/cyclic-bound5.tc.ok | 1 + 13 files changed, 90 insertions(+), 8 deletions(-) create mode 100644 test/fail/cyclic-bound1.as create mode 100644 test/fail/cyclic-bound2.as create mode 100644 test/fail/cyclic-bound3.as create mode 100644 test/fail/cyclic-bound4.as create mode 100644 test/fail/cyclic-bound5.as create mode 100644 test/fail/ok/cyclic-bound1.tc.ok create mode 100644 test/fail/ok/cyclic-bound2.tc.ok create mode 100644 test/fail/ok/cyclic-bound3.tc.ok create mode 100644 test/fail/ok/cyclic-bound4.tc.ok create mode 100644 test/fail/ok/cyclic-bound5.tc.ok diff --git a/src/as_frontend/typing.ml b/src/as_frontend/typing.ml index 8ce72cf465a..ba9a699f508 100644 --- a/src/as_frontend/typing.ml +++ b/src/as_frontend/typing.ml @@ -251,8 +251,27 @@ and check_typ_tag env typ_tag = let t = check_typ env typ in T.{lab = tag.it; typ = t} +and check_typ_binds_acyclic env typ_binds cs ts = + let n = List.length cs in + let ce = List.fold_right2 T.ConEnv.add cs ts T.ConEnv.empty in + let chase typ_bind c = + let rec chase i ts c' = + if i > n then + error env typ_bind.at "type parameter %s has cyclic bounds %s" + (T.string_of_con c) + (String.concat " <: " (List.map T.string_of_typ ts)) (List.rev ts) + else + match T.ConEnv.find_opt c' ce with + | None -> () + | Some t -> + (match T.normalize t with + | T.Con (c'', []) as t' -> + chase (i+1) (t'::ts) c'' + | _ -> ()) + in chase 0 [] c + in List.iter2 chase typ_binds cs + and check_typ_binds env typ_binds : T.con list * T.typ list * Scope.typ_env * Scope.con_env = - (* TODO: rule out cyclic bounds *) let xs = List.map (fun typ_bind -> typ_bind.it.var.it) typ_binds in let cs = List.map2 (fun x tb -> @@ -267,6 +286,7 @@ and check_typ_binds env typ_binds : T.con list * T.typ list * Scope.typ_env * Sc ) T.Env.empty typ_binds cs in let pre_env' = add_typs {env with pre = true} xs cs in let ts = List.map (fun typ_bind -> check_typ pre_env' typ_bind.it.bound) typ_binds in + check_typ_binds_acyclic env typ_binds cs ts; let ks = List.map (fun t -> T.Abs ([], t)) ts in List.iter2 (fun c k -> match Con.kind c with @@ -594,7 +614,7 @@ and infer_exp'' env exp : T.typ = (T.string_of_typ_expand t1) ) | FuncE (_, sort, typ_binds, pat, typ_opt, exp) -> - let typ = + let typ = match typ_opt with | Some typ -> typ | None -> {it = TupT []; at = no_region; note = T.Pre} diff --git a/src/as_types/type.mli b/src/as_types/type.mli index ae42e8f9cff..77344f22f08 100644 --- a/src/as_types/type.mli +++ b/src/as_types/type.mli @@ -133,6 +133,7 @@ val compare_field : field -> field -> int val set_kind : con -> kind -> unit +module ConEnv : Env.S with type key = con module ConSet : Dom.S with type elt = con diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 8fd605064d3..e26ab8d54d4 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -221,16 +221,33 @@ and check_typ_field env s typ_field : unit = "actor field has non-shared type" end +and check_typ_binds_acyclic env cs ts = + let n = List.length cs in + let ce = List.fold_right2 T.ConEnv.add cs ts T.ConEnv.empty in + let chase c = + let rec chase i ts c' = + if i > n then + error env no_region "type parameter %s has cyclic bounds %s" + (T.string_of_con c) + (String.concat " <: " (List.map T.string_of_typ ts)) (List.rev ts) + else + match T.ConEnv.find_opt c' ce with + | None -> () + | Some t -> + (match T.normalize t with + | T.Con (c'', []) as t' -> + chase (i+1) (t'::ts) c'' + | _ -> ()) + in chase 0 [] c + in List.iter chase cs + and check_typ_binds env typ_binds : T.con list * con_env = let ts = Type.open_binds typ_binds in let cs = List.map (function T.Con (c, []) -> c | _ -> assert false) ts in let env' = add_typs env cs in - let _ = List.map - (fun typ_bind -> - let bd = T.open_ ts typ_bind.T.bound in - check_typ env' bd) - typ_binds - in + let bds = List.map (fun typ_bind -> T.open_ ts typ_bind.T.bound) typ_binds in + check_typ_binds_acyclic env' cs bds; + List.iter (check_typ env') bds; cs, T.ConSet.of_list cs and check_typ_bounds env (tbs : T.bind list) typs at : unit = diff --git a/test/fail/cyclic-bound1.as b/test/fail/cyclic-bound1.as new file mode 100644 index 00000000000..d339fd45272 --- /dev/null +++ b/test/fail/cyclic-bound1.as @@ -0,0 +1,7 @@ +/* check cyclic bounds are rejected, would loop sans check */ + +func f(a : A) +{ + let _ : () = a; +}; + diff --git a/test/fail/cyclic-bound2.as b/test/fail/cyclic-bound2.as new file mode 100644 index 00000000000..1345f7cecff --- /dev/null +++ b/test/fail/cyclic-bound2.as @@ -0,0 +1,7 @@ +/* check cyclic bounds are rejected, would loop sans check */ + +func f(a : A, b : B) { + let _ : () = a; let _ : () = b; +}; + + diff --git a/test/fail/cyclic-bound3.as b/test/fail/cyclic-bound3.as new file mode 100644 index 00000000000..56f4f62e392 --- /dev/null +++ b/test/fail/cyclic-bound3.as @@ -0,0 +1,7 @@ +/* check cyclic bounds are rejected, would loop sans check */ + +func f(a : A, b : B, c : C) { + let _ : () = a; + let _ : () = b; + let _ : () = c; +}; diff --git a/test/fail/cyclic-bound4.as b/test/fail/cyclic-bound4.as new file mode 100644 index 00000000000..48de66d5fb8 --- /dev/null +++ b/test/fail/cyclic-bound4.as @@ -0,0 +1,11 @@ +/* check cyclic bounds are rejected, would loop sans check */ + +type C = U; + +type T = C; + +func f, B <: T, C <: T>(a : A, b : B, c : C) { + let _ : () = a; + let _ : () = b; + let _ : () = c; +}; diff --git a/test/fail/cyclic-bound5.as b/test/fail/cyclic-bound5.as new file mode 100644 index 00000000000..7dd50e477a8 --- /dev/null +++ b/test/fail/cyclic-bound5.as @@ -0,0 +1,7 @@ +/* check cyclic bounds are rejected, would loop sans check */ + + + +type T = U; + +type C> = (); \ No newline at end of file diff --git a/test/fail/ok/cyclic-bound1.tc.ok b/test/fail/ok/cyclic-bound1.tc.ok new file mode 100644 index 00000000000..0672e7b81c3 --- /dev/null +++ b/test/fail/ok/cyclic-bound1.tc.ok @@ -0,0 +1 @@ +cyclic-bound1.as:3.8-3.14: type error, type parameter A/9 has cyclic bounds A/9 <: A/9 diff --git a/test/fail/ok/cyclic-bound2.tc.ok b/test/fail/ok/cyclic-bound2.tc.ok new file mode 100644 index 00000000000..a2345990137 --- /dev/null +++ b/test/fail/ok/cyclic-bound2.tc.ok @@ -0,0 +1 @@ +cyclic-bound2.as:3.8-3.14: type error, type parameter A/9 has cyclic bounds B <: A/9 <: B diff --git a/test/fail/ok/cyclic-bound3.tc.ok b/test/fail/ok/cyclic-bound3.tc.ok new file mode 100644 index 00000000000..c930aac4bf5 --- /dev/null +++ b/test/fail/ok/cyclic-bound3.tc.ok @@ -0,0 +1 @@ +cyclic-bound3.as:3.8-3.14: type error, type parameter A/9 has cyclic bounds B <: A/9 <: C <: B diff --git a/test/fail/ok/cyclic-bound4.tc.ok b/test/fail/ok/cyclic-bound4.tc.ok new file mode 100644 index 00000000000..5f2d686a07a --- /dev/null +++ b/test/fail/ok/cyclic-bound4.tc.ok @@ -0,0 +1 @@ +cyclic-bound4.as:7.8-7.17: type error, type parameter A/9 has cyclic bounds B <: A/9 <: C/1 <: B diff --git a/test/fail/ok/cyclic-bound5.tc.ok b/test/fail/ok/cyclic-bound5.tc.ok new file mode 100644 index 00000000000..893a82c4281 --- /dev/null +++ b/test/fail/ok/cyclic-bound5.tc.ok @@ -0,0 +1 @@ +cyclic-bound5.as:7.8-7.17: type error, type parameter U/1 has cyclic bounds U/1 <: U/1 From 77354973f97aeb20f80cb1976edabc3ab92828a3 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Thu, 25 Jul 2019 10:19:33 -0700 Subject: [PATCH 0317/1176] Remove unused let bindings --- stdlib/array.as | 2 -- 1 file changed, 2 deletions(-) diff --git a/stdlib/array.as b/stdlib/array.as index 26c6d765387..db7b39ed615 100644 --- a/stdlib/array.as +++ b/stdlib/array.as @@ -17,8 +17,6 @@ module { }; public func apply(fs : [A -> B], xs : [A]) : [B] { - let fsLen = fs.len(); - let xsLen = xs.len(); var ys : [B] = []; for (f in fs.vals()) { ys := append(ys, map(f, xs)); From a66e4fab3149feb97a37049d9ff9f7af19ba17b1 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity <48968912+chenyan-dfinity@users.noreply.github.com> Date: Thu, 25 Jul 2019 14:04:12 -0700 Subject: [PATCH 0318/1176] Output JS binding to a file (#598) * output JS binding to a file * Update test/run.sh Co-Authored-By: Joachim Breitner * fix typo --- src/exes/didc.ml | 9 +++++++-- test/run.sh | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/exes/didc.ml b/src/exes/didc.ml index 0a6cef4c42b..813eac9c776 100644 --- a/src/exes/didc.ml +++ b/src/exes/didc.ml @@ -44,8 +44,13 @@ let process_file file : unit = | Check -> ignore (Diag.run (Pipeline.check_file file)) | Js -> - let out = Diag.run Pipeline.(compile_js_file file) in - Buffer.contents out |> print_endline + if !out_file = "" then + out_file := Filename.remove_extension (Filename.basename file) ^ ".js"; + let buf = Diag.run Pipeline.(compile_js_file file) in + let oc = open_out !out_file in + Buffer.add_string buf "\n"; + Buffer.output_buffer oc buf; + close_out oc let print_exn exn = Printf.printf "%!"; diff --git a/test/run.sh b/test/run.sh index 76a5acaa764..5c1e84ad02d 100755 --- a/test/run.sh +++ b/test/run.sh @@ -226,7 +226,8 @@ do if [ "$tc_succeeded" -eq 0 ]; then $ECHO -n " [js]" - $DIDC --js $base.did > $out/$base.js 2>&1 + $DIDC --js $base.did -o $out/$base.js >& $out/$base.js.out + diff_files="$diff_files $base.js.out" diff_files="$diff_files $base.js" if [ -e $out/$base.js ] From 0d1862ce50e7f8ae4ba560e2bbbb096f67d869bf Mon Sep 17 00:00:00 2001 From: Paul Young Date: Thu, 25 Jul 2019 15:14:34 -0700 Subject: [PATCH 0319/1176] Move Rx example --- default.nix | 24 ----------- rx/Makefile | 36 ---------------- stdlib/Makefile | 45 +++++++++++++------- {rx => stdlib/examples/rx}/src/Disposable.as | 0 {rx => stdlib/examples/rx}/src/Event.as | 0 {rx => stdlib/examples/rx}/src/Observable.as | 0 {rx => stdlib/examples/rx}/src/Observer.as | 0 {rx => stdlib/examples/rx}/src/Rx.as | 0 {rx => stdlib/examples/rx}/test/RxTest.as | 2 +- 9 files changed, 31 insertions(+), 76 deletions(-) delete mode 100644 rx/Makefile rename {rx => stdlib/examples/rx}/src/Disposable.as (100%) rename {rx => stdlib/examples/rx}/src/Event.as (100%) rename {rx => stdlib/examples/rx}/src/Observable.as (100%) rename {rx => stdlib/examples/rx}/src/Observer.as (100%) rename {rx => stdlib/examples/rx}/src/Rx.as (100%) rename {rx => stdlib/examples/rx}/test/RxTest.as (98%) diff --git a/default.nix b/default.nix index f2e817084c7..50f6a3a45d8 100644 --- a/default.nix +++ b/default.nix @@ -401,29 +401,6 @@ rec { ''; }; - rx = stdenv.mkDerivation { - name = "rx-actorscript"; - src = null; - unpackPhase = '' - cp -R --no-preserve=mode ${subpath ./rx} rx - cp -R --no-preserve=mode ${subpath ./stdlib} stdlib - ''; - buildInputs = [ - asc - ]; - buildPhase = '' - make -C rx ASC=asc OUTDIR=_out _out/Rx.wasm - ''; - doCheck = true; - checkPhase = '' - make -C rx ASC=asc OUTDIR=_out _out/RxTest.out - ''; - installPhase = '' - mkdir -p $out - cp rx/_out/Rx.wasm $out - ''; - }; - all-systems-go = nixpkgs.releaseTools.aggregate { name = "all-systems-go"; constituents = [ @@ -435,7 +412,6 @@ rec { unit-tests samples rts - rx stdlib stdlib-doc stdlib-doc-live diff --git a/rx/Makefile b/rx/Makefile deleted file mode 100644 index 83482672f6f..00000000000 --- a/rx/Makefile +++ /dev/null @@ -1,36 +0,0 @@ -ASC=../src/asc -OUTDIR=_out - -MODULES=\ - RxTest \ - -WASM=\ - Rx \ - -OUTFILES=$(addsuffix .out, $(MODULES)) $(addsuffix .wasm, $(WASM)) - -OUTPATHS=$(addprefix $(OUTDIR)/, $(OUTFILES)) - -.PHONY: default all clean alltests - -default: all - -alltests: $(OUTDIR) $(OUTPATHS) - -all: alltests - -clean: - rm -rf $(OUTDIR) - -$(OUTDIR): - @mkdir $@ - -RX_ACTORSCRIPT_SRC=\ - src/Rx.as \ - -$(OUTDIR)/RxTest.out: $(RX_ACTORSCRIPT_SRC) \ - test/RxTest.as | $(OUTDIR) - $(ASC) -r test/RxTest.as > $@ - -$(OUTDIR)/Rx.wasm: $(RX_ACTORSCRIPT_SRC) | $(OUTDIR) - $(ASC) -c -o $@ src/Rx.as diff --git a/stdlib/Makefile b/stdlib/Makefile index 88b0a808407..edaad628dc3 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -8,7 +8,9 @@ MDofMD=./tools/markdown-of-markdown.py PANDOC=pandoc STOPWATCH=$(OUTDIR)/stopwatch -WASM=ProduceExchange +WASM=\ + ProduceExchange \ + Rx \ TESTS=\ Array \ @@ -30,11 +32,14 @@ TESTS=\ Trie2 \ Set \ DocTable \ + ProduceExchange \ producerRemInventory \ retailerReserveMany \ evalBulk \ + RxTest \ + OUTFILES=$(addsuffix .out, $(TESTS)) $(addsuffix .wasm, $(WASM)) OUTPATHS=$(addprefix $(OUTDIR)/, $(OUTFILES)) @@ -118,20 +123,6 @@ $(OUTDIR)/DocTable.out: docTable.as | $(OUTDIR) #########################################################################################################33 -## -## PX Unit tests -## - -PRODUCE_EXCHANGE_SRC=\ - prelude.as option.as hash.as list.as assocList.as trie.as trie2.as docTable.as result.as \ - examples/produce-exchange/serverTypes.as \ - examples/produce-exchange/serverLang.as \ - examples/produce-exchange/serverModelTypes.as \ - examples/produce-exchange/serverModel.as \ - examples/produce-exchange/serverActor.as \ - -#########################################################################################################33 - ## ## Documentation ## @@ -202,6 +193,12 @@ $(DOCDIR)/examples/produce-exchange/README.md: examples/produce-exchange/README. @echo "" >> $@ $(MDofMD) $< >> $@ +#########################################################################################################33 + +## +## PX Unit tests +## + PRODUCE_EXCHANGE_SRC=\ prelude.as option.as hash.as list.as assocList.as trie2.as docTable.as result.as \ examples/produce-exchange/serverTypes.as \ @@ -240,6 +237,24 @@ $(DOCDIR)/%.html: $(DOCDIR)/%.md #########################################################################################################33 +## +## Rx Example +## + +RX_SRC=\ + array.as \ + examples/rx/src/Rx.as \ + examples/rx/test/RxTest.as \ + +$(OUTDIR)/RxTest.out: $(RX_SRC) \ + examples/rx/test/RxTest.as | $(OUTDIR) + $(ASC) -r examples/rx/test/RxTest.as > $@ + +$(OUTDIR)/Rx.wasm: $(RX_SRC) | $(OUTDIR) + $(ASC) -c -o $@ examples/rx/src/Rx.as + +#########################################################################################################33 + ## ## Profiling ## diff --git a/rx/src/Disposable.as b/stdlib/examples/rx/src/Disposable.as similarity index 100% rename from rx/src/Disposable.as rename to stdlib/examples/rx/src/Disposable.as diff --git a/rx/src/Event.as b/stdlib/examples/rx/src/Event.as similarity index 100% rename from rx/src/Event.as rename to stdlib/examples/rx/src/Event.as diff --git a/rx/src/Observable.as b/stdlib/examples/rx/src/Observable.as similarity index 100% rename from rx/src/Observable.as rename to stdlib/examples/rx/src/Observable.as diff --git a/rx/src/Observer.as b/stdlib/examples/rx/src/Observer.as similarity index 100% rename from rx/src/Observer.as rename to stdlib/examples/rx/src/Observer.as diff --git a/rx/src/Rx.as b/stdlib/examples/rx/src/Rx.as similarity index 100% rename from rx/src/Rx.as rename to stdlib/examples/rx/src/Rx.as diff --git a/rx/test/RxTest.as b/stdlib/examples/rx/test/RxTest.as similarity index 98% rename from rx/test/RxTest.as rename to stdlib/examples/rx/test/RxTest.as index 7283d1160dc..6a0b48ab153 100644 --- a/rx/test/RxTest.as +++ b/stdlib/examples/rx/test/RxTest.as @@ -1,4 +1,4 @@ -import Array "../../stdlib/array.as"; +import Array "../../../array.as"; import Rx "../src/Rx.as"; type Error = { From af2c0d3a537ed956ea360686c3d47f7638cf0c8e Mon Sep 17 00:00:00 2001 From: Paul Young Date: Thu, 25 Jul 2019 15:14:45 -0700 Subject: [PATCH 0320/1176] Sort files --- stdlib/Makefile | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/stdlib/Makefile b/stdlib/Makefile index edaad628dc3..260a112b99f 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -15,23 +15,23 @@ WASM=\ TESTS=\ Array \ ArrayTest \ + AssocList \ + DocTable \ + Hash \ Int \ IntTest \ + List \ + ListTest \ Nat \ NatTest \ Option \ OptionTest \ Result \ - Hash \ - List \ - ListTest \ - AssocList \ + Set \ Text \ TextTest \ Trie \ Trie2 \ - Set \ - DocTable \ ProduceExchange \ producerRemInventory \ From 0334673dc8ecda2267dca31ca42201affddc3b92 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Thu, 25 Jul 2019 15:17:26 -0700 Subject: [PATCH 0321/1176] Add README --- stdlib/examples/rx/README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 stdlib/examples/rx/README.md diff --git a/stdlib/examples/rx/README.md b/stdlib/examples/rx/README.md new file mode 100644 index 00000000000..45ba3d2fe3e --- /dev/null +++ b/stdlib/examples/rx/README.md @@ -0,0 +1,3 @@ +# RxActorScript + +A [ReactiveX](http://reactivex.io/) implementation in ActorScript. From ea31debffeebead1b8fa5d2c029e3ece8eb96224 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Thu, 25 Jul 2019 15:20:25 -0700 Subject: [PATCH 0322/1176] Remove empty lines to fix Makefile --- stdlib/Makefile | 2 -- 1 file changed, 2 deletions(-) diff --git a/stdlib/Makefile b/stdlib/Makefile index 260a112b99f..6a48be2e6c6 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -32,12 +32,10 @@ TESTS=\ TextTest \ Trie \ Trie2 \ - ProduceExchange \ producerRemInventory \ retailerReserveMany \ evalBulk \ - RxTest \ OUTFILES=$(addsuffix .out, $(TESTS)) $(addsuffix .wasm, $(WASM)) From 9f186abe0b899f7c28d5d2f100e674e95e99cac1 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 26 Jul 2019 18:39:18 +0200 Subject: [PATCH 0323/1176] Ir: explicit NumConvPrim (#599) Use an explicit NumConvPrim instead of string-typed prim names This extend the IR AST with that node. IR checker not (yet) extended. The transition from Source (with untyped prims of arbitrary string) to IR (with a more structured AST) is a bit, eh, bumpy. But that might be fine, as this bumpyness only applies to code written in the sacred prelude. --- src/as_types/type.ml | 2 +- src/as_values/prim.ml | 306 +++++++++++++++-------------- src/as_values/prim.mli | 2 + src/codegen/compile.ml | 285 +++++++++++++-------------- src/ir_def/arrange_ir.ml | 6 +- src/ir_def/ir.ml | 1 + src/ir_interpreter/interpret_ir.ml | 5 + src/ir_passes/async.ml | 1 + src/lowering/desugar.ml | 9 + src/prelude/prelude.ml | 115 +++++------ 10 files changed, 374 insertions(+), 358 deletions(-) diff --git a/src/as_types/type.ml b/src/as_types/type.ml index 194ccc220e6..a3654eadd56 100644 --- a/src/as_types/type.ml +++ b/src/as_types/type.ml @@ -97,7 +97,7 @@ let prim = function | "Float" -> Float | "Char" -> Char | "Text" -> Text - | _ -> raise (Invalid_argument "Type.prim") + | s -> raise (Invalid_argument ("Type.prim: " ^ s)) let seq = function [t] -> t | ts -> Tup ts diff --git a/src/as_values/prim.ml b/src/as_values/prim.ml index ce2e966d8bc..9fbecd362c1 100644 --- a/src/as_values/prim.ml +++ b/src/as_values/prim.ml @@ -1,4 +1,5 @@ (* Primitives *) +open As_types open Value @@ -42,157 +43,162 @@ end (* Conv *) let range_violation () = raise (Invalid_argument "numeric overflow") -let prim = function - | "abs" -> fun v k -> k (Int (Nat.abs (as_int v))) +let num_conv_prim t1 t2 = + let module T = Type in + match (t1, t2) with + | T.Nat8, T.Word8 -> fun v k -> + let i = Nat8.to_int (as_nat8 v) + in k (Word8 (Word8.of_int_u i)) + | T.Nat, T.Word8 -> fun v k -> + let i = Conv.wrapped_int_of_big_int (as_int v) + in k (Word8 (Word8.of_int_u i)) + | T.Nat, T.Nat8 -> fun v k -> + let q, r = Big_int.quomod_big_int (as_int v) (Big_int.power_int_positive_int 2 8) in + let i = Big_int.int_of_big_int r + in Big_int.(if eq_big_int q zero_big_int then k (Nat8 (Nat8.of_int i)) else range_violation ()) + | T.Int8, T.Word8 -> fun v k -> + let i = Int_8.to_int (as_int8 v) + in k (Word8 (Word8.of_int_s i)) + | T.Int, T.Word8 -> fun v k -> + let i = Conv.wrapped_int_of_big_int (as_int v) + in k (Word8 (Word8.of_int_s i)) + | T.Int, T.Int8 -> fun v k -> + let q, r = Big_int.quomod_big_int (as_int v) (Big_int.power_int_positive_int 2 7) in + let i = Big_int.int_of_big_int r in + Big_int. + (if eq_big_int q zero_big_int || eq_big_int q (pred_big_int zero_big_int) + then k (Int8(Int_8.of_int (Conv.to_signed i q 0x80))) else range_violation ()) + | T.Nat16, T.Word16 -> fun v k -> + let i = Nat16.to_int (as_nat16 v) + in k (Word16 (Word16.of_int_u i)) + | T.Nat, T.Word16 -> fun v k -> + let i = Conv.wrapped_int_of_big_int (as_int v) + in k (Word16 (Word16.of_int_u i)) + | T.Nat, T.Nat16 -> fun v k -> + let q, r = Big_int.quomod_big_int (as_int v) (Big_int.power_int_positive_int 2 16) in + let i = Big_int.int_of_big_int r + in Big_int.(if eq_big_int q zero_big_int then k (Nat16 (Nat16.of_int i)) else range_violation ()) + | T.Int16, T.Word16 -> fun v k -> + let i = Int_16.to_int (as_int16 v) + in k (Word16 (Word16.of_int_s i)) + | T.Int, T.Word16 -> fun v k -> + let i = Conv.wrapped_int_of_big_int (as_int v) + in k (Word16 (Word16.of_int_s i)) + | T.Int, T.Int16 -> fun v k -> + let q, r = Big_int.quomod_big_int (as_int v) (Big_int.power_int_positive_int 2 15) in + let i = Big_int.int_of_big_int r in + Big_int. + (if eq_big_int q zero_big_int || eq_big_int q (pred_big_int zero_big_int) + then k (Int16(Int_16.of_int (Conv.to_signed i q 0x8000))) else range_violation ()) + | T.Nat32, T.Word32 -> fun v k -> + let i = Nat32.to_int (as_nat32 v) + in k (Word32 (Word32.of_int_u i)) + | T.Nat, T.Word32 -> fun v k -> + let i = Conv.wrapped_int_of_big_int (as_int v) + in k (Word32 (Word32.of_int_u i)) + | T.Nat, T.Nat32 -> fun v k -> + let q, r = Big_int.quomod_big_int (as_int v) (Big_int.power_int_positive_int 2 32) in + let i = Big_int.int_of_big_int r + in Big_int.(if eq_big_int q zero_big_int then k (Nat32 (Nat32.of_int i)) else range_violation ()) + | T.Int32, T.Word32 -> fun v k -> + let i = Int_32.to_int (as_int32 v) + in k (Word32 (Word32.of_int_s i)) + | T.Int, T.Word32 -> fun v k -> + let i = Conv.wrapped_int_of_big_int (as_int v) + in k (Word32 (Word32.of_int_s i)) + | T.Int, T.Int32 -> fun v k -> + let q, r = Big_int.quomod_big_int (as_int v) (Big_int.power_int_positive_int 2 31) in + let i = Big_int.int_of_big_int r in + Big_int. + (if eq_big_int q zero_big_int || eq_big_int q (pred_big_int zero_big_int) + then k (Int32 (Int_32.of_int (Conv.to_signed i q 0x80000000))) else range_violation ()) + + | T.Nat64, T.Word64 -> fun v k -> + let q, r = Big_int.quomod_big_int (Nat64.to_big_int (as_nat64 v)) Conv.twoRaised63 in + let i = Conv.(to_signed_big_int r q twoRaised63) in + k (Word64 (Big_int.int64_of_big_int i)) + | T.Nat, T.Word64 -> fun v k -> k (Word64 (Conv.word64_of_nat_big_int (as_int v))) + | T.Nat, T.Nat64 -> fun v k -> + let q, r = Big_int.quomod_big_int (as_int v) Conv.twoRaised64 in + Big_int. + (if eq_big_int q zero_big_int + then k (Nat64 (Nat64.of_big_int r)) + else range_violation ()) + | T.Int64, T.Word64 -> fun v k -> k (Word64 (Big_int.int64_of_big_int (Int_64.to_big_int (as_int64 v)))) + | T.Int, T.Word64 -> fun v k -> k (Word64 (Conv.word64_of_big_int (as_int v))) + | T.Int, T.Int64 -> fun v k -> + let q, r = Big_int.quomod_big_int (as_int v) Conv.twoRaised63 in + Big_int. + (if eq_big_int q zero_big_int || eq_big_int q (pred_big_int zero_big_int) + then k (Int64 (Int_64.of_big_int Conv.(to_signed_big_int r q twoRaised63))) + else range_violation ()) - | "Nat8->Word8" -> fun v k -> - let i = Nat8.to_int (as_nat8 v) - in k (Word8 (Word8.of_int_u i)) - | "Nat->Word8" -> fun v k -> - let i = Conv.wrapped_int_of_big_int (as_int v) - in k (Word8 (Word8.of_int_u i)) - | "Nat->Nat8" -> fun v k -> - let q, r = Big_int.quomod_big_int (as_int v) (Big_int.power_int_positive_int 2 8) in - let i = Big_int.int_of_big_int r - in Big_int.(if eq_big_int q zero_big_int then k (Nat8 (Nat8.of_int i)) else range_violation ()) - | "Int8->Word8" -> fun v k -> - let i = Int_8.to_int (as_int8 v) - in k (Word8 (Word8.of_int_s i)) - | "Int->Word8" -> fun v k -> - let i = Conv.wrapped_int_of_big_int (as_int v) - in k (Word8 (Word8.of_int_s i)) - | "Int->Int8" -> fun v k -> - let q, r = Big_int.quomod_big_int (as_int v) (Big_int.power_int_positive_int 2 7) in - let i = Big_int.int_of_big_int r in - Big_int. - (if eq_big_int q zero_big_int || eq_big_int q (pred_big_int zero_big_int) - then k (Int8(Int_8.of_int (Conv.to_signed i q 0x80))) else range_violation ()) - | "Nat16->Word16" -> fun v k -> - let i = Nat16.to_int (as_nat16 v) - in k (Word16 (Word16.of_int_u i)) - | "Nat->Word16" -> fun v k -> - let i = Conv.wrapped_int_of_big_int (as_int v) - in k (Word16 (Word16.of_int_u i)) - | "Nat->Nat16" -> fun v k -> - let q, r = Big_int.quomod_big_int (as_int v) (Big_int.power_int_positive_int 2 16) in - let i = Big_int.int_of_big_int r - in Big_int.(if eq_big_int q zero_big_int then k (Nat16 (Nat16.of_int i)) else range_violation ()) - | "Int16->Word16" -> fun v k -> - let i = Int_16.to_int (as_int16 v) - in k (Word16 (Word16.of_int_s i)) - | "Int->Word16" -> fun v k -> - let i = Conv.wrapped_int_of_big_int (as_int v) - in k (Word16 (Word16.of_int_s i)) - | "Int->Int16" -> fun v k -> - let q, r = Big_int.quomod_big_int (as_int v) (Big_int.power_int_positive_int 2 15) in - let i = Big_int.int_of_big_int r in - Big_int. - (if eq_big_int q zero_big_int || eq_big_int q (pred_big_int zero_big_int) - then k (Int16(Int_16.of_int (Conv.to_signed i q 0x8000))) else range_violation ()) - | "Nat32->Word32" -> fun v k -> - let i = Nat32.to_int (as_nat32 v) - in k (Word32 (Word32.of_int_u i)) - | "Nat->Word32" -> fun v k -> - let i = Conv.wrapped_int_of_big_int (as_int v) - in k (Word32 (Word32.of_int_u i)) - | "Nat->Nat32" -> fun v k -> - let q, r = Big_int.quomod_big_int (as_int v) (Big_int.power_int_positive_int 2 32) in - let i = Big_int.int_of_big_int r - in Big_int.(if eq_big_int q zero_big_int then k (Nat32 (Nat32.of_int i)) else range_violation ()) - | "Int32->Word32" -> fun v k -> - let i = Int_32.to_int (as_int32 v) - in k (Word32 (Word32.of_int_s i)) - | "Int->Word32" -> fun v k -> - let i = Conv.wrapped_int_of_big_int (as_int v) - in k (Word32 (Word32.of_int_s i)) - | "Int->Int32" -> fun v k -> - let q, r = Big_int.quomod_big_int (as_int v) (Big_int.power_int_positive_int 2 31) in - let i = Big_int.int_of_big_int r in - Big_int. - (if eq_big_int q zero_big_int || eq_big_int q (pred_big_int zero_big_int) - then k (Int32 (Int_32.of_int (Conv.to_signed i q 0x80000000))) else range_violation ()) + | T.Word8, T.Nat -> fun v k -> + let i = Int32.to_int (Int32.shift_right_logical (Word8.to_bits (as_word8 v)) 24) + in k (Int (Big_int.big_int_of_int i)) + | T.Word8, T.Nat8 -> fun v k -> + let i = Int32.to_int (Int32.shift_right_logical (Word8.to_bits (as_word8 v)) 24) + in k (Nat8 (Nat8.of_int i)) + | T.Int8, T.Int -> fun v k -> k (Int (Int.of_int (Int_8.to_int (as_int8 v)))) + | T.Nat8, T.Nat -> fun v k -> k (Int (Nat.of_int (Nat8.to_int (as_nat8 v)))) + | T.Word8, T.Int -> fun v k -> + let i = Int32.to_int (Int32.shift_right (Word8.to_bits (as_word8 v)) 24) + in k (Int (Big_int.big_int_of_int i)) + | T.Word8, T.Int8 -> fun v k -> + let i = Int32.to_int (Int32.shift_right (Word8.to_bits (as_word8 v)) 24) + in k (Int8 (Int_8.of_int i)) + | T.Word16, T.Nat -> fun v k -> + let i = Int32.to_int (Int32.shift_right_logical (Word16.to_bits (as_word16 v)) 16) + in k (Int (Big_int.big_int_of_int i)) + | T.Word16, T.Nat16 -> fun v k -> + let i = Int32.to_int (Int32.shift_right_logical (Word16.to_bits (as_word16 v)) 16) + in k (Nat16 (Nat16.of_int i)) + | T.Int16, T.Int -> fun v k -> k (Int (Int.of_int (Int_16.to_int (as_int16 v)))) + | T.Nat16, T.Nat -> fun v k -> k (Int (Nat.of_int (Nat16.to_int (as_nat16 v)))) + | T.Word16, T.Int -> fun v k -> + let i = Int32.to_int (Int32.shift_right (Word16.to_bits (as_word16 v)) 16) + in k (Int (Big_int.big_int_of_int i)) + | T.Word16, T.Int16 -> fun v k -> + let i = Int32.to_int (Int32.shift_right (Word16.to_bits (as_word16 v)) 16) + in k (Int16 (Int_16.of_int i)) + | T.Int32, T.Int -> fun v k -> k (Int (Int.of_int (Int_32.to_int (as_int32 v)))) + | T.Nat32, T.Nat -> fun v k -> k (Int (Nat.of_int (Nat32.to_int (as_nat32 v)))) + | T.Word32, T.Nat -> fun v k -> + let i = Conv.of_signed_Word32 (as_word32 v) + in k (Int (Big_int.big_int_of_int i)) + | T.Word32, T.Int -> fun v k -> k (Int (Big_int.big_int_of_int32 (as_word32 v))) + | T.Word32, T.Int32 -> fun v k -> + let i = Big_int.(int_of_big_int (big_int_of_int32 (as_word32 v))) in + k (Int32 (Int_32.of_int i)) + | T.Word32, T.Nat32 -> fun v k -> + let i = Big_int.(int_of_big_int (big_int_of_int32 (as_word32 v))) in + let i' = if i < 0 then i + 0x100000000 else i in + k (Nat32 (Nat32.of_int i')) - | "Nat64->Word64" -> fun v k -> - let q, r = Big_int.quomod_big_int (Nat64.to_big_int (as_nat64 v)) Conv.twoRaised63 in - let i = Conv.(to_signed_big_int r q twoRaised63) in - k (Word64 (Big_int.int64_of_big_int i)) - | "Nat->Word64" -> fun v k -> k (Word64 (Conv.word64_of_nat_big_int (as_int v))) - | "Nat->Nat64" -> fun v k -> - let q, r = Big_int.quomod_big_int (as_int v) Conv.twoRaised64 in - Big_int. - (if eq_big_int q zero_big_int - then k (Nat64 (Nat64.of_big_int r)) - else range_violation ()) - | "Int64->Word64" -> fun v k -> k (Word64 (Big_int.int64_of_big_int (Int_64.to_big_int (as_int64 v)))) - | "Int->Word64" -> fun v k -> k (Word64 (Conv.word64_of_big_int (as_int v))) - | "Int->Int64" -> fun v k -> - let q, r = Big_int.quomod_big_int (as_int v) Conv.twoRaised63 in - Big_int. - (if eq_big_int q zero_big_int || eq_big_int q (pred_big_int zero_big_int) - then k (Int64 (Int_64.of_big_int Conv.(to_signed_big_int r q twoRaised63))) - else range_violation ()) + | T.Int64, T.Int -> fun v k -> k (Int (Int_64.to_big_int (as_int64 v))) + | T.Nat64, T.Nat -> fun v k -> k (Int (Nat64.to_big_int (as_nat64 v))) + | T.Word64, T.Nat -> fun v k -> + let i = Conv.big_int_of_unsigned_word64 (as_word64 v) + in k (Int i) + | T.Word64, T.Nat64 -> fun v k -> + let i = Conv.big_int_of_unsigned_word64 (as_word64 v) + in k (Nat64 (Nat64.of_big_int i)) + | T.Word64, T.Int -> fun v k -> k (Int (Big_int.big_int_of_int64 (as_word64 v))) + | T.Word64, T.Int64 -> fun v k -> + let i = Big_int.big_int_of_int64 (as_word64 v) + in k (Int64 (Int_64.of_big_int i)) - | "Word8->Nat" -> fun v k -> - let i = Int32.to_int (Int32.shift_right_logical (Word8.to_bits (as_word8 v)) 24) - in k (Int (Big_int.big_int_of_int i)) - | "Word8->Nat8" -> fun v k -> - let i = Int32.to_int (Int32.shift_right_logical (Word8.to_bits (as_word8 v)) 24) - in k (Nat8 (Nat8.of_int i)) - | "Int8->Int" -> fun v k -> k (Int (Int.of_int (Int_8.to_int (as_int8 v)))) - | "Nat8->Nat" -> fun v k -> k (Int (Nat.of_int (Nat8.to_int (as_nat8 v)))) - | "Word8->Int" -> fun v k -> - let i = Int32.to_int (Int32.shift_right (Word8.to_bits (as_word8 v)) 24) - in k (Int (Big_int.big_int_of_int i)) - | "Word8->Int8" -> fun v k -> - let i = Int32.to_int (Int32.shift_right (Word8.to_bits (as_word8 v)) 24) - in k (Int8 (Int_8.of_int i)) - | "Word16->Nat" -> fun v k -> - let i = Int32.to_int (Int32.shift_right_logical (Word16.to_bits (as_word16 v)) 16) - in k (Int (Big_int.big_int_of_int i)) - | "Word16->Nat16" -> fun v k -> - let i = Int32.to_int (Int32.shift_right_logical (Word16.to_bits (as_word16 v)) 16) - in k (Nat16 (Nat16.of_int i)) - | "Int16->Int" -> fun v k -> k (Int (Int.of_int (Int_16.to_int (as_int16 v)))) - | "Nat16->Nat" -> fun v k -> k (Int (Nat.of_int (Nat16.to_int (as_nat16 v)))) - | "Word16->Int" -> fun v k -> - let i = Int32.to_int (Int32.shift_right (Word16.to_bits (as_word16 v)) 16) - in k (Int (Big_int.big_int_of_int i)) - | "Word16->Int16" -> fun v k -> - let i = Int32.to_int (Int32.shift_right (Word16.to_bits (as_word16 v)) 16) - in k (Int16 (Int_16.of_int i)) - | "Int32->Int" -> fun v k -> k (Int (Int.of_int (Int_32.to_int (as_int32 v)))) - | "Nat32->Nat" -> fun v k -> k (Int (Nat.of_int (Nat32.to_int (as_nat32 v)))) - | "Word32->Nat" -> fun v k -> - let i = Conv.of_signed_Word32 (as_word32 v) - in k (Int (Big_int.big_int_of_int i)) - | "Word32->Int" -> fun v k -> k (Int (Big_int.big_int_of_int32 (as_word32 v))) - | "Word32->Int32" -> fun v k -> - let i = Big_int.(int_of_big_int (big_int_of_int32 (as_word32 v))) in - k (Int32 (Int_32.of_int i)) - | "Word32->Nat32" -> fun v k -> - let i = Big_int.(int_of_big_int (big_int_of_int32 (as_word32 v))) in - let i' = if i < 0 then i + 0x100000000 else i in - k (Nat32 (Nat32.of_int i')) + | T.Char, T.Word32 -> fun v k -> + let i = as_char v + in k (Word32 (Word32.of_int_u i)) + | T.Word32, T.Char -> fun v k -> + let i = Conv.of_signed_Word32 (as_word32 v) + in if i <= 0x10FFFF then k (Char i) else raise (Invalid_argument "codepoint out of bounds") + | t1, t2 -> raise (Invalid_argument ("Value.num_conv_prim: " ^ T.string_of_typ (T.Prim t1) ^ T.string_of_typ (T.Prim t2) )) - | "Int64->Int" -> fun v k -> k (Int (Int_64.to_big_int (as_int64 v))) - | "Nat64->Nat" -> fun v k -> k (Int (Nat64.to_big_int (as_nat64 v))) - | "Word64->Nat" -> fun v k -> - let i = Conv.big_int_of_unsigned_word64 (as_word64 v) - in k (Int i) - | "Word64->Nat64" -> fun v k -> - let i = Conv.big_int_of_unsigned_word64 (as_word64 v) - in k (Nat64 (Nat64.of_big_int i)) - | "Word64->Int" -> fun v k -> k (Int (Big_int.big_int_of_int64 (as_word64 v))) - | "Word64->Int64" -> fun v k -> - let i = Big_int.big_int_of_int64 (as_word64 v) - in k (Int64 (Int_64.of_big_int i)) +let prim = function + | "abs" -> fun v k -> k (Int (Nat.abs (as_int v))) - | "Char->Word32" -> fun v k -> - let i = as_char v - in k (Word32 (Word32.of_int_u i)) - | "Word32->Char" -> fun v k -> - let i = Conv.of_signed_Word32 (as_word32 v) - in if i <= 0x10FFFF then k (Char i) else raise (Invalid_argument "codepoint out of bounds") | "popcnt8" | "popcnt16" | "popcnt" | "popcnt64" -> fun v k -> @@ -284,4 +290,12 @@ let prim = function in go (fun xs -> xs) k 0 | _ -> assert false ) + | p when Lib.String.chop_prefix "num_conv" p <> None -> + begin match String.split_on_char '_' p with + | [_;_;s1;s2] -> + let p1 = Type.prim s1 in + let p2 = Type.prim s2 in + num_conv_prim p1 p2 + | _ -> assert false + end | s -> raise (Invalid_argument ("Value.prim: " ^ s)) diff --git a/src/as_values/prim.mli b/src/as_values/prim.mli index ae9fff98e92..20b47a50726 100644 --- a/src/as_values/prim.mli +++ b/src/as_values/prim.mli @@ -1 +1,3 @@ +open As_types val prim : string -> Value.func +val num_conv_prim : Type.prim -> Type.prim -> Value.func diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 1ba4854f5ff..caebe928c0f 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -5631,6 +5631,139 @@ and compile_exp (env : E.t) ae exp = compile_exp_as env ae SR.UnboxedReference e ^^ Serialization.deserialize env t + (* Numeric conversions *) + | NumConvPrim (t1, t2), [e] -> begin + let open Type in + match t1, t2 with + | (Nat|Int), (Word8|Word16) -> + SR.Vanilla, + compile_exp_vanilla env ae e ^^ + Prim.prim_shiftToWordN env (UnboxedSmallWord.shift_of_type t2) + + | (Nat|Int), Word32 -> + SR.UnboxedWord32, + compile_exp_vanilla env ae e ^^ + Prim.prim_intToWord32 env + + | (Nat|Int), Word64 -> + SR.UnboxedWord64, + compile_exp_vanilla env ae e ^^ + BigNum.to_word64 env + + | Nat64, Word64 + | Int64, Word64 + | Word64, Nat64 + | Word64, Int64 + | Nat32, Word32 + | Int32, Word32 + | Word32, Nat32 + | Word32, Int32 + | Nat16, Word16 + | Int16, Word16 + | Word16, Nat16 + | Word16, Int16 + | Nat8, Word8 + | Int8, Word8 + | Word8, Nat8 + | Word8, Int8 -> + SR.Vanilla, + compile_exp_vanilla env ae e ^^ + G.nop + + | Int, Int64 -> + SR.UnboxedWord64, + compile_exp_vanilla env ae e ^^ + Func.share_code1 env "Int->Int64" ("n", I32Type) [I64Type] (fun env get_n -> + get_n ^^ + BigNum.fits_signed_bits env 64 ^^ + E.else_trap_with env "losing precision" ^^ + get_n ^^ + BigNum.truncate_to_word64 env) + + | Int, (Int8|Int16|Int32) -> + let ty = exp.note.note_typ in + StackRep.of_type ty, + let pty = prim_of_typ ty in + compile_exp_vanilla env ae e ^^ + Func.share_code1 env (UnboxedSmallWord.name_of_type pty "Int->") ("n", I32Type) [I32Type] (fun env get_n -> + get_n ^^ + BigNum.fits_signed_bits env (UnboxedSmallWord.bits_of_type pty) ^^ + E.else_trap_with env "losing precision" ^^ + get_n ^^ + BigNum.truncate_to_word32 env ^^ + UnboxedSmallWord.msb_adjust pty) + + | Nat, Nat64 -> + SR.UnboxedWord64, + compile_exp_vanilla env ae e ^^ + Func.share_code1 env "Nat->Nat64" ("n", I32Type) [I64Type] (fun env get_n -> + get_n ^^ + BigNum.fits_unsigned_bits env 64 ^^ + E.else_trap_with env "losing precision" ^^ + get_n ^^ + BigNum.truncate_to_word64 env) + + | Nat, (Nat8|Nat16|Nat32) -> + let ty = exp.note.note_typ in + StackRep.of_type ty, + let pty = prim_of_typ ty in + compile_exp_vanilla env ae e ^^ + Func.share_code1 env (UnboxedSmallWord.name_of_type pty "Nat->") ("n", I32Type) [I32Type] (fun env get_n -> + get_n ^^ + BigNum.fits_unsigned_bits env (UnboxedSmallWord.bits_of_type pty) ^^ + E.else_trap_with env "losing precision" ^^ + get_n ^^ + BigNum.truncate_to_word32 env ^^ + UnboxedSmallWord.msb_adjust pty) + + | Char, Word32 -> + SR.UnboxedWord32, + compile_exp_vanilla env ae e ^^ + UnboxedSmallWord.unbox_codepoint + + | (Nat8|Word8|Nat16|Word16), Nat -> + SR.Vanilla, + compile_exp_vanilla env ae e ^^ + Prim.prim_shiftWordNtoUnsigned env (UnboxedSmallWord.shift_of_type t1) + + | (Int8|Word8|Int16|Word16), Int -> + SR.Vanilla, + compile_exp_vanilla env ae e ^^ + Prim.prim_shiftWordNtoSigned env (UnboxedSmallWord.shift_of_type t1) + + | (Nat32|Word32), Nat -> + SR.Vanilla, + compile_exp_as env ae SR.UnboxedWord32 e ^^ + Prim.prim_word32toNat env + + | (Int32|Word32), Int -> + SR.Vanilla, + compile_exp_as env ae SR.UnboxedWord32 e ^^ + Prim.prim_word32toInt env + + | (Nat64|Word64), Nat -> + SR.Vanilla, + compile_exp_as env ae SR.UnboxedWord64 e ^^ + BigNum.from_word64 env + + | (Int64|Word64), Int -> + SR.Vanilla, + compile_exp_as env ae SR.UnboxedWord64 e ^^ + BigNum.from_signed_word64 env + + | Word32, Char -> + SR.Vanilla, + compile_exp_as env ae SR.UnboxedWord32 e ^^ + Func.share_code1 env "Word32->Char" ("n", I32Type) [I32Type] + (fun env get_n -> + get_n ^^ compile_unboxed_const 0x10FFFFl ^^ + G.i (Compare (Wasm.Values.I32 I32Op.GtU)) ^^ + E.then_trap_with env "codepoint out of range" ^^ + get_n ^^ UnboxedSmallWord.box_codepoint) + + | _ -> SR.Unreachable, todo_trap env "compile_exp" (Arrange_ir.exp exp) + end + (* Other prims, unary*) | OtherPrim "array_len", [e] -> @@ -5662,158 +5795,6 @@ and compile_exp (env : E.t) ae exp = SR.Vanilla, E.trap_with env "idlHash only implemented in interpreter " - | OtherPrim "Nat->Word8", [e] - | OtherPrim "Int->Word8", [e] -> - SR.Vanilla, - compile_exp_vanilla env ae e ^^ - Prim.prim_shiftToWordN env (UnboxedSmallWord.shift_of_type Type.Word8) - - | OtherPrim "Nat->Word16", [e] - | OtherPrim "Int->Word16", [e] -> - SR.Vanilla, - compile_exp_vanilla env ae e ^^ - Prim.prim_shiftToWordN env (UnboxedSmallWord.shift_of_type Type.Word16) - - | OtherPrim "Nat->Word32", [e] - | OtherPrim "Int->Word32", [e] -> - SR.UnboxedWord32, - compile_exp_vanilla env ae e ^^ - Prim.prim_intToWord32 env - - | OtherPrim "Nat->Word64", [e] - | OtherPrim "Int->Word64", [e] -> - SR.UnboxedWord64, - compile_exp_vanilla env ae e ^^ - BigNum.to_word64 env - - | OtherPrim "Nat64->Word64", [e] - | OtherPrim "Int64->Word64", [e] - | OtherPrim "Word64->Nat64", [e] - | OtherPrim "Word64->Int64", [e] - | OtherPrim "Nat32->Word32", [e] - | OtherPrim "Int32->Word32", [e] - | OtherPrim "Word32->Nat32", [e] - | OtherPrim "Word32->Int32", [e] - | OtherPrim "Nat16->Word16", [e] - | OtherPrim "Int16->Word16", [e] - | OtherPrim "Word16->Nat16", [e] - | OtherPrim "Word16->Int16", [e] - | OtherPrim "Nat8->Word8", [e] - | OtherPrim "Int8->Word8", [e] - | OtherPrim "Word8->Nat8", [e] - | OtherPrim "Word8->Int8", [e] -> - SR.Vanilla, - compile_exp_vanilla env ae e ^^ - G.nop - - | OtherPrim "Int->Int64", [e] -> - SR.UnboxedWord64, - compile_exp_vanilla env ae e ^^ - Func.share_code1 env "Int->Int64" ("n", I32Type) [I64Type] (fun env get_n -> - get_n ^^ - BigNum.fits_signed_bits env 64 ^^ - E.else_trap_with env "losing precision" ^^ - get_n ^^ - BigNum.truncate_to_word64 env) - - | OtherPrim "Int->Int32", [e] - | OtherPrim "Int->Int16", [e] - | OtherPrim "Int->Int8", [e] -> - let ty = exp.note.note_typ in - StackRep.of_type ty, - let pty = prim_of_typ ty in - compile_exp_vanilla env ae e ^^ - Func.share_code1 env (UnboxedSmallWord.name_of_type pty "Int->") ("n", I32Type) [I32Type] (fun env get_n -> - get_n ^^ - BigNum.fits_signed_bits env (UnboxedSmallWord.bits_of_type pty) ^^ - E.else_trap_with env "losing precision" ^^ - get_n ^^ - BigNum.truncate_to_word32 env ^^ - UnboxedSmallWord.msb_adjust pty) - - | OtherPrim "Nat->Nat64", [e] -> - SR.UnboxedWord64, - compile_exp_vanilla env ae e ^^ - Func.share_code1 env "Nat->Nat64" ("n", I32Type) [I64Type] (fun env get_n -> - get_n ^^ - BigNum.fits_unsigned_bits env 64 ^^ - E.else_trap_with env "losing precision" ^^ - get_n ^^ - BigNum.truncate_to_word64 env) - - | OtherPrim "Nat->Nat32", [e] - | OtherPrim "Nat->Nat16", [e] - | OtherPrim "Nat->Nat8", [e] -> - let ty = exp.note.note_typ in - StackRep.of_type ty, - let pty = prim_of_typ ty in - compile_exp_vanilla env ae e ^^ - Func.share_code1 env (UnboxedSmallWord.name_of_type pty "Nat->") ("n", I32Type) [I32Type] (fun env get_n -> - get_n ^^ - BigNum.fits_unsigned_bits env (UnboxedSmallWord.bits_of_type pty) ^^ - E.else_trap_with env "losing precision" ^^ - get_n ^^ - BigNum.truncate_to_word32 env ^^ - UnboxedSmallWord.msb_adjust pty) - - | OtherPrim "Char->Word32", [e] -> - SR.UnboxedWord32, - compile_exp_vanilla env ae e ^^ - UnboxedSmallWord.unbox_codepoint - - | OtherPrim "Nat8->Nat", [e] - | OtherPrim "Word8->Nat", [e] -> - SR.Vanilla, - compile_exp_vanilla env ae e ^^ - Prim.prim_shiftWordNtoUnsigned env (UnboxedSmallWord.shift_of_type Type.Word8) - | OtherPrim "Int8->Int", [e] - | OtherPrim "Word8->Int", [e] -> - SR.Vanilla, - compile_exp_vanilla env ae e ^^ - Prim.prim_shiftWordNtoSigned env (UnboxedSmallWord.shift_of_type Type.Word8) - - | OtherPrim "Nat16->Nat", [e] - | OtherPrim "Word16->Nat", [e] -> - SR.Vanilla, - compile_exp_vanilla env ae e ^^ - Prim.prim_shiftWordNtoUnsigned env (UnboxedSmallWord.shift_of_type Type.Word16) - | OtherPrim "Int16->Int", [e] - | OtherPrim "Word16->Int", [e] -> - SR.Vanilla, - compile_exp_vanilla env ae e ^^ - Prim.prim_shiftWordNtoSigned env (UnboxedSmallWord.shift_of_type Type.Word16) - - | OtherPrim "Nat32->Nat", [e] - | OtherPrim "Word32->Nat", [e] -> - SR.Vanilla, - compile_exp_as env ae SR.UnboxedWord32 e ^^ - Prim.prim_word32toNat env - | OtherPrim "Int32->Int", [e] - | OtherPrim "Word32->Int", [e] -> - SR.Vanilla, - compile_exp_as env ae SR.UnboxedWord32 e ^^ - Prim.prim_word32toInt env - - | OtherPrim "Nat64->Nat", [e] - | OtherPrim "Word64->Nat", [e] -> - SR.Vanilla, - compile_exp_as env ae SR.UnboxedWord64 e ^^ - BigNum.from_word64 env - | OtherPrim "Int64->Int", [e] - | OtherPrim "Word64->Int", [e] -> - SR.Vanilla, - compile_exp_as env ae SR.UnboxedWord64 e ^^ - BigNum.from_signed_word64 env - - | OtherPrim "Word32->Char", [e] -> - SR.Vanilla, - compile_exp_as env ae SR.UnboxedWord32 e ^^ - Func.share_code1 env "Word32->Char" ("n", I32Type) [I32Type] - (fun env get_n -> - get_n ^^ compile_unboxed_const 0x10FFFFl ^^ - G.i (Compare (Wasm.Values.I32 I32Op.GtU)) ^^ - E.then_trap_with env "codepoint out of range" ^^ - get_n ^^ UnboxedSmallWord.box_codepoint) | OtherPrim "popcnt", [e] -> SR.UnboxedWord32, diff --git a/src/ir_def/arrange_ir.ml b/src/ir_def/arrange_ir.ml index 41da72302d7..311d50dd9d9 100644 --- a/src/ir_def/arrange_ir.ml +++ b/src/ir_def/arrange_ir.ml @@ -9,6 +9,7 @@ let ($$) head inner = Node (head, inner) let id i = Atom i let typ t = Atom (Type.string_of_typ t) +let prim_ty p = typ (Type.Prim p) let kind k = Atom (Type.string_of_kind k) let rec exp e = match e.it with @@ -55,8 +56,9 @@ and prim = function | BinPrim (t, bo) -> "BinPrim" $$ [typ t; Arrange_ops.binop bo] | RelPrim (t, ro) -> "RelPrim" $$ [typ t; Arrange_ops.relop ro] | ShowPrim t -> "ShowPrim" $$ [typ t] - | SerializePrim t -> "SerializePrim" $$ [typ t] - | DeserializePrim t -> "DeserializePrim" $$ [typ t] + | SerializePrim t -> "SerializePrim" $$ [typ t] + | DeserializePrim t -> "DeserializePrim" $$ [typ t] + | NumConvPrim (t1, t2) -> "NumConvPrim" $$ [prim_ty t1; prim_ty t2] | OtherPrim s -> Atom s and mut = function diff --git a/src/ir_def/ir.ml b/src/ir_def/ir.ml index a4fe9a9a911..ce16210cd93 100644 --- a/src/ir_def/ir.ml +++ b/src/ir_def/ir.ml @@ -105,6 +105,7 @@ and prim = | ShowPrim of Type.typ (* debug show *) | SerializePrim of Type.typ (* serialize *) | DeserializePrim of Type.typ (* deserialize *) + | NumConvPrim of Type.prim * Type.prim | OtherPrim of string (* Other primitive operation, no custom typing rule *) (* Declarations *) diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index 487899e4059..222605beb33 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -328,6 +328,11 @@ and interpret_exp_mut env exp (k : V.value V.cont) = let arg = match vs with [v] -> v | _ -> V.Tup vs in extended_prim env s t at arg k ) + | NumConvPrim (t1, t2), exps -> + interpret_exps env exps [] (fun vs -> + let arg = match vs with [v] -> v | _ -> V.Tup vs in + Prim.num_conv_prim t1 t2 arg k + ) | _ -> trap exp.at "Unknown prim or wrong number of arguments (%d given):\n %s" (List.length es) (Wasm.Sexpr.to_string 80 (Arrange_ir.prim p)) diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index a2bdc82938d..1798704574f 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -200,6 +200,7 @@ module Transform() = struct | ShowPrim ot -> ShowPrim (t_typ ot) | SerializePrim ot -> SerializePrim (t_typ ot) | DeserializePrim ot -> DeserializePrim (t_typ ot) + | NumConvPrim (t1,t2) -> NumConvPrim (t1,t2) | OtherPrim s -> OtherPrim s and t_field {lab; typ} = diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 4c385454538..287913b3753 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -96,6 +96,15 @@ and exp' at note = function let tys = if cc.Call_conv.n_res = 1 then [ty] else T.as_seq ty in I.FuncE (name, cc, tbs', args, tys, wrap (exp e)) (* Primitive functions in the prelude have particular shapes *) + | S.CallE ({it=S.AnnotE ({it=S.PrimE p;_}, _);note;_}, _, e) + when Lib.String.chop_prefix "num_conv" p <> None -> + begin match String.split_on_char '_' p with + | [_;_;s1;s2] -> + let p1 = Type.prim s1 in + let p2 = Type.prim s2 in + I.PrimE (I.NumConvPrim (p1, p2), [exp e]) + | _ -> assert false + end | S.CallE ({it=S.AnnotE ({it=S.PrimE p;_},_);_}, _, {it=S.TupE es;_}) -> I.PrimE (I.OtherPrim p, exps es) | S.CallE ({it=S.AnnotE ({it=S.PrimE p;_},_);_}, _, e) -> diff --git a/src/prelude/prelude.ml b/src/prelude/prelude.ml index 15d535700a0..b52a78f9cba 100644 --- a/src/prelude/prelude.ml +++ b/src/prelude/prelude.ml @@ -110,63 +110,64 @@ func hashInt(x : Int) : Word32 { // Conversions -func int64ToInt(n : Int64) : Int = (prim "Int64->Int" : Int64 -> Int) n; -func intToInt64(n : Int) : Int64 = (prim "Int->Int64" : Int -> Int64) n; -func int64ToWord64(n : Int64) : Word64 = (prim "Int64->Word64" : Int64 -> Word64) n; -func word64ToInt64(n : Word64) : Int64 = (prim "Word64->Int64" : Word64 -> Int64) n; -func int32ToInt(n : Int32) : Int = (prim "Int32->Int" : Int32 -> Int) n; -func intToInt32(n : Int) : Int32 = (prim "Int->Int32" : Int -> Int32) n; -func int32ToWord32(n : Int32) : Word32 = (prim "Int32->Word32" : Int32 -> Word32) n; -func word32ToInt32(n : Word32) : Int32 = (prim "Word32->Int32" : Word32 -> Int32) n; -func int16ToInt(n : Int16) : Int = (prim "Int16->Int" : Int16 -> Int) n; -func intToInt16(n : Int) : Int16 = (prim "Int->Int16" : Int -> Int16) n; -func int16ToWord16(n : Int16) : Word16 = (prim "Int16->Word16" : Int16 -> Word16) n; -func word16ToInt16(n : Word16) : Int16 = (prim "Word16->Int16" : Word16 -> Int16) n; -func int8ToInt(n : Int8) : Int = (prim "Int8->Int" : Int8 -> Int) n; -func intToInt8(n : Int) : Int8 = (prim "Int->Int8" : Int -> Int8) n; -func int8ToWord8(n : Int8) : Word8 = (prim "Int8->Word8" : Int8 -> Word8) n; -func word8ToInt8(n : Word8) : Int8 = (prim "Word8->Int8" : Word8 -> Int8) n; - -func nat64ToNat(n : Nat64) : Nat = (prim "Nat64->Nat" : Nat64 -> Nat) n; -func natToNat64(n : Nat) : Nat64 = (prim "Nat->Nat64" : Nat -> Nat64) n; -func nat64ToWord64(n : Nat64) : Word64 = (prim "Nat64->Word64" : Nat64 -> Word64) n; -func word64ToNat64(n : Word64) : Nat64 = (prim "Word64->Nat64" : Word64 -> Nat64) n; -func nat32ToNat(n : Nat32) : Nat = (prim "Nat32->Nat" : Nat32 -> Nat) n; -func natToNat32(n : Nat) : Nat32 = (prim "Nat->Nat32" : Nat -> Nat32) n; -func nat32ToWord32(n : Nat32) : Word32 = (prim "Nat32->Word32" : Nat32 -> Word32) n; -func word32ToNat32(n : Word32) : Nat32 = (prim "Word32->Nat32" : Word32 -> Nat32) n; -func nat16ToNat(n : Nat16) : Nat = (prim "Nat16->Nat" : Nat16 -> Nat) n; -func natToNat16(n : Nat) : Nat16 = (prim "Nat->Nat16" : Nat -> Nat16) n; -func nat16ToWord16(n : Nat16) : Word16 = (prim "Nat16->Word16" : Nat16 -> Word16) n; -func word16ToNat16(n : Word16) : Nat16 = (prim "Word16->Nat16" : Word16 -> Nat16) n; -func nat8ToNat(n : Nat8) : Nat = (prim "Nat8->Nat" : Nat8 -> Nat) n; -func natToNat8(n : Nat) : Nat8 = (prim "Nat->Nat8" : Nat -> Nat8) n; -func nat8ToWord8(n : Nat8) : Word8 = (prim "Nat8->Word8" : Nat8 -> Word8) n; -func word8ToNat8(n : Word8) : Nat8 = (prim "Word8->Nat8" : Word8 -> Nat8) n; - - -func natToWord8(n : Nat) : Word8 = (prim "Nat->Word8" : Nat -> Word8) n; -func word8ToNat(n : Word8) : Nat = (prim "Word8->Nat" : Word8 -> Nat) n; -func intToWord8(n : Int) : Word8 = (prim "Int->Word8" : Int -> Word8) n; -func word8ToInt(n : Word8) : Int = (prim "Word8->Int" : Word8 -> Int) n; - -func natToWord16(n : Nat) : Word16 = (prim "Nat->Word16" : Nat -> Word16) n; -func word16ToNat(n : Word16) : Nat = (prim "Word16->Nat" : Word16 -> Nat) n; -func intToWord16(n : Int) : Word16 = (prim "Int->Word16" : Int -> Word16) n; -func word16ToInt(n : Word16) : Int = (prim "Word16->Int" : Word16 -> Int) n; - -func natToWord32(n : Nat) : Word32 = (prim "Nat->Word32" : Nat -> Word32) n; -func word32ToNat(n : Word32) : Nat = (prim "Word32->Nat" : Word32 -> Nat) n; -func intToWord32(n : Int) : Word32 = (prim "Int->Word32" : Int -> Word32) n; -func word32ToInt(n : Word32) : Int = (prim "Word32->Int" : Word32 -> Int) n; - -func natToWord64(n : Nat) : Word64 = (prim "Nat->Word64" : Nat -> Word64) n; -func word64ToNat(n : Word64) : Nat = (prim "Word64->Nat" : Word64 -> Nat) n; -func intToWord64(n : Int) : Word64 = (prim "Int->Word64" : Int -> Word64) n; -func word64ToInt(n : Word64) : Int = (prim "Word64->Int" : Word64 -> Int) n; - -func charToWord32(c : Char) : Word32 = (prim "Char->Word32" : Char -> Word32) c; -func word32ToChar(w : Word32) : Char = (prim "Word32->Char" : Word32 -> Char) w; +func int64ToInt(n : Int64) : Int = (prim "num_conv_Int64_Int" : Int64 -> Int) n; +func intToInt64(n : Int) : Int64 = (prim "num_conv_Int_Int64" : Int -> Int64) n; +func int64ToWord64(n : Int64) : Word64 = (prim "num_conv_Int64_Word64" : Int64 -> Word64) n; +func word64ToInt64(n : Word64) : Int64 = (prim "num_conv_Word64_Int64" : Word64 -> Int64) n; +func int32ToInt(n : Int32) : Int = (prim "num_conv_Int32_Int" : Int32 -> Int) n; +func intToInt32(n : Int) : Int32 = (prim "num_conv_Int_Int32" : Int -> Int32) n; +func int32ToWord32(n : Int32) : Word32 = (prim "num_conv_Int32_Word32" : Int32 -> Word32) n; +func word32ToInt32(n : Word32) : Int32 = (prim "num_conv_Word32_Int32" : Word32 -> Int32) n; +func int16ToInt(n : Int16) : Int = (prim "num_conv_Int16_Int" : Int16 -> Int) n; +func intToInt16(n : Int) : Int16 = (prim "num_conv_Int_Int16" : Int -> Int16) n; +func int16ToWord16(n : Int16) : Word16 = (prim "num_conv_Int16_Word16" : Int16 -> Word16) n; +func word16ToInt16(n : Word16) : Int16 = (prim "num_conv_Word16_Int16" : Word16 -> Int16) n; +func int8ToInt(n : Int8) : Int = (prim "num_conv_Int8_Int" : Int8 -> Int) n; +func intToInt8(n : Int) : Int8 = (prim "num_conv_Int_Int8" : Int -> Int8) n; +func int8ToWord8(n : Int8) : Word8 = (prim "num_conv_Int8_Word8" : Int8 -> Word8) n; +func word8ToInt8(n : Word8) : Int8 = (prim "num_conv_Word8_Int8" : Word8 -> Int8) n; + +func nat64ToNat(n : Nat64) : Nat = (prim "num_conv_Nat64_Nat" : Nat64 -> Nat) n; +func natToNat64(n : Nat) : Nat64 = (prim "num_conv_Nat_Nat64" : Nat -> Nat64) n; +func nat64ToWord64(n : Nat64) : Word64 = (prim "num_conv_Nat64_Word64" : Nat64 -> Word64) n; +func word64ToNat64(n : Word64) : Nat64 = (prim "num_conv_Word64_Nat64" : Word64 -> Nat64) n; +func nat32ToNat(n : Nat32) : Nat = (prim "num_conv_Nat32_Nat" : Nat32 -> Nat) n; +func natToNat32(n : Nat) : Nat32 = (prim "num_conv_Nat_Nat32" : Nat -> Nat32) n; +func nat32ToWord32(n : Nat32) : Word32 = (prim "num_conv_Nat32_Word32" : Nat32 -> Word32) n; +func word32ToNat32(n : Word32) : Nat32 = (prim "num_conv_Word32_Nat32" : Word32 -> Nat32) n; +func nat16ToNat(n : Nat16) : Nat = (prim "num_conv_Nat16_Nat" : Nat16 -> Nat) n; +func natToNat16(n : Nat) : Nat16 = (prim "num_conv_Nat_Nat16" : Nat -> Nat16) n; +func nat16ToWord16(n : Nat16) : Word16 = (prim "num_conv_Nat16_Word16" : Nat16 -> Word16) n; +func word16ToNat16(n : Word16) : Nat16 = (prim "num_conv_Word16_Nat16" : Word16 -> Nat16) n; +func nat8ToNat(n : Nat8) : Nat = (prim "num_conv_Nat8_Nat" : Nat8 -> Nat) n; +func natToNat8(n : Nat) : Nat8 = (prim "num_conv_Nat_Nat8" : Nat -> Nat8) n; +func nat8ToWord8(n : Nat8) : Word8 = (prim "num_conv_Nat8_Word8" : Nat8 -> Word8) n; +func word8ToNat8(n : Word8) : Nat8 = (prim "num_conv_Word8_Nat8" : Word8 -> Nat8) n; + + +func natToWord8(n : Nat) : Word8 = (prim "num_conv_Nat_Word8" : Nat -> Word8) n; +func word8ToNat(n : Word8) : Nat = (prim "num_conv_Word8_Nat" : Word8 -> Nat) n; +func intToWord8(n : Int) : Word8 = (prim "num_conv_Int_Word8" : Int -> Word8) n; +func word8ToInt(n : Word8) : Int = (prim "num_conv_Word8_Int" : Word8 -> Int) n; + +func natToWord16(n : Nat) : Word16 = (prim "num_conv_Nat_Word16" : Nat -> Word16) n; +func word16ToNat(n : Word16) : Nat = (prim "num_conv_Word16_Nat" : Word16 -> Nat) n; +func intToWord16(n : Int) : Word16 = (prim "num_conv_Int_Word16" : Int -> Word16) n; +func word16ToInt(n : Word16) : Int = (prim "num_conv_Word16_Int" : Word16 -> Int) n; + +func natToWord32(n : Nat) : Word32 = (prim "num_conv_Nat_Word32" : Nat -> Word32) n; +func word32ToNat(n : Word32) : Nat = (prim "num_conv_Word32_Nat" : Word32 -> Nat) n; +func intToWord32(n : Int) : Word32 = (prim "num_conv_Int_Word32" : Int -> Word32) n; +func word32ToInt(n : Word32) : Int = (prim "num_conv_Word32_Int" : Word32 -> Int) n; + +func natToWord64(n : Nat) : Word64 = (prim "num_conv_Nat_Word64" : Nat -> Word64) n; +func word64ToNat(n : Word64) : Nat = (prim "num_conv_Word64_Nat" : Word64 -> Nat) n; +func intToWord64(n : Int) : Word64 = (prim "num_conv_Int_Word64" : Int -> Word64) n; +func word64ToInt(n : Word64) : Int = (prim "num_conv_Word64_Int" : Word64 -> Int) n; + +func charToWord32(c : Char) : Word32 = (prim "num_conv_Char_Word32" : Char -> Word32) c; +func word32ToChar(w : Word32) : Char = (prim "num_conv_Word32_Char" : Word32 -> Char) w; + func decodeUTF8(s : Text) : (Word32, Char) = (prim "decodeUTF8" : Text -> (Word32, Char)) s; // Exotic bitwise operations From cd5a7204c5a1b6d321d00fa62a0c1c02f5081c32 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity <48968912+chenyan-dfinity@users.noreply.github.com> Date: Mon, 29 Jul 2019 15:24:29 -0700 Subject: [PATCH 0324/1176] fix pa_cars example (#601) --- samples/pa_cars.as | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/samples/pa_cars.as b/samples/pa_cars.as index 946089ddfc3..a475b288629 100644 --- a/samples/pa_cars.as +++ b/samples/pa_cars.as @@ -8,9 +8,9 @@ // - Client: Pick a parking spot from a Google Map like interface + time // - Server: Register the parking spot for the user -type Car = shared { model : Text; plate : Text }; +type Car = { model : Text; plate : Text }; type DMV = actor { check : Car -> async CarInfo }; -type CarInfo = shared { +type CarInfo = { model : Text; plate : Text; isValid : Bool; @@ -36,8 +36,8 @@ actor class PACars(dmv : DMV) { return null; }; - type Location = shared { lat : Float; long : Float }; - type TimeSpan = shared { start : Int; end : Int }; - type Result = ?(shared { reservationId : Text }); - type User = shared { name : Text }; + type Location = { lat : Float; long : Float }; + type TimeSpan = { start : Int; end : Int }; + type Result = ?({ reservationId : Text }); + type User = { name : Text }; }; From e5d33d2b27d1726355e959443fae46f1987c45ba Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Wed, 31 Jul 2019 14:26:35 +0200 Subject: [PATCH 0325/1176] Drop new keyword from object literals (#600) --- guide/as-slides.md | 4 +- guide/chat.as | 4 +- guide/guide.md | 10 +- samples/app/server.as | 4 +- src/as_frontend/lexer.mll | 1 - src/as_frontend/parser.mly | 162 ++++++++++-------- src/as_types/type.ml | 2 + stdlib/arrayTest.as | 6 +- stdlib/docTable.as | 2 +- .../examples/produce-exchange/serverActor.as | 16 +- .../examples/produce-exchange/serverModel.as | 158 ++++++++--------- .../produce-exchange/test/evalBulk.as | 152 ++++++++-------- .../test/producerRemInventory.as | 152 ++++++++-------- stdlib/examples/rx/test/RxTest.as | 8 +- stdlib/set.as | 6 +- stdlib/trie.as | 20 +-- stdlib/trie2.as | 18 +- test/fail/issue36.as | 4 +- test/fail/object-patterns.as | 2 +- test/fail/objpat-duplicate.as | 2 +- test/fail/objpat-infer.as | 24 +-- test/fail/ok/const-var-field.tc.ok | 2 +- test/fail/ok/objpat-infer.tc.ok | 8 +- test/fail/ok/var-const-field.tc.ok | 4 +- test/fail/var-const-field.as | 2 +- test/run-dfinity/chat.as | 2 +- test/run-dfinity/chatpp.as | 4 +- test/run-dfinity/data-params.as | 4 +- test/run-dfinity/shared-object.as | 2 +- test/run-dfinity/transpose.as | 2 +- test/run/coverage.as | 14 +- test/run/ir-pat-subtype.as | 14 +- test/run/issue129.as | 2 +- test/run/mut-field-bound.as | 2 +- test/run/nested-lexpr.as | 2 +- test/run/objects-order.as | 4 +- test/run/objects1.as | 6 +- test/run/objects3.as | 2 +- test/run/ok/coverage.run-ir.ok | 10 +- test/run/ok/coverage.run-low.ok | 10 +- test/run/ok/coverage.run.ok | 10 +- test/run/ok/coverage.tc.ok | 10 +- test/run/ok/coverage.wasm.stderr.ok | 10 +- test/run/ok/type-inference.run-ir.ok | 2 +- test/run/ok/type-inference.run-low.ok | 2 +- test/run/ok/type-inference.run.ok | 2 +- test/run/ok/type-inference.tc.ok | 2 +- test/run/ok/type-inference.wasm.stderr.ok | 2 +- test/run/prelude.as | 2 +- test/run/records.as | 4 +- test/run/switch.as | 4 +- test/run/type-inference.as | 6 +- test/run/type-lub.as | 4 +- 53 files changed, 470 insertions(+), 443 deletions(-) diff --git a/guide/as-slides.md b/guide/as-slides.md index 206a4b5a081..04cdcf5110c 100644 --- a/guide/as-slides.md +++ b/guide/as-slides.md @@ -228,7 +228,7 @@ AS distinguishes sharable types: * sharable (think serializable) objects have immutable fields of sharable type: ``` - new { x = 0; color = Colors.Red } + { x = 0; color = Colors.Red } ``` * full `object`s can be mutable, stateful @@ -577,7 +577,7 @@ actor Server { ``` ``` public func subscribe(client : Client) : async Post { - let cs = new {head = client; var tail = clients}; + let cs = {head = client; var tail = clients}; clients := ?cs; return broadcast; }; diff --git a/guide/chat.as b/guide/chat.as index ba672f0b9a3..bcef183c8d9 100644 --- a/guide/chat.as +++ b/guide/chat.as @@ -19,8 +19,8 @@ actor Server = { }; public func subscribe(client : Client) : async Post { - let cs = new {head = client; var tail = clients}; - clients := ?cs; + let cs = {head = client; var tail = clients}; + clients := ?cs; return broadcast; }; }; diff --git a/guide/guide.md b/guide/guide.md index 89ea93207c2..f7ed1da9561 100644 --- a/guide/guide.md +++ b/guide/guide.md @@ -660,7 +660,7 @@ A type `T` is *shared* if it is ( ,* ) tuple . tuple projection ? option injection - new { ;* } object + { ;* } object . object projection := assignment = unary update @@ -758,15 +758,13 @@ The literal `null` has type `Null`. Since `Null <: ? T` for any `T`, literal `nu ## Objects -Objects can be written in literal form `new { ;* }`, consisting of a list of expression fields: +Objects can be written in literal form `{ ;* }`, consisting of a list of expression fields: ```bnf ::= var? = ``` Such an object literal is equivalent to the object declaration `object { ;* }` where the declaration fields are obtained from the expression fields by prefixing each of them with `public let`, or just `public` in case of `var` fields. -_TBR can we delete `new`?_ - ## Object projection (Member access) The object projection ` . ` has type `var? T` provided `` has object type @@ -1281,7 +1279,7 @@ In particular: * if the sort is `actor` then all public fields must be non-`var` (immutable) `shared` functions (the public interface of an actor can only provide asynchronous messaging via shared functions). -Evaluation of `(new|object|actor) ? =? { ;* }` proceeds by +Evaluation of `(object|actor)? ? =? { ;* }` proceeds by evaluating the declarations in `;*`. If the evaluation of `;*` traps, so does the object declaration. Otherwise, `;*` produces a set of bindings for identifiers in `Id`. let `v0`, ..., `vn` be the values or locations bound to identifiers ``, ..., ``. @@ -1318,7 +1316,7 @@ obj_sort? class ? (: )? =? ? { ; where: -* `` is `object` if `obj_sort?` is absent or `new` and `sort == obj_sort` otherwise. +* `` is `object` if `obj_sort?` is absent or `sort == obj_sort` otherwise. * `?` is the sequence of type identifiers bound by `?` (if any), and * `;*` is the set of public field types inferred from ``. * `?` is the optional `this` parameter of the object instance. diff --git a/samples/app/server.as b/samples/app/server.as index e1a8322b78f..06348443abf 100644 --- a/samples/app/server.as +++ b/samples/app/server.as @@ -25,9 +25,9 @@ actor class Server() = { }; public func subscribe(aclient : shared Text -> ()) : async T.Subscription { - let c = new {id = nextId; client = aclient; var revoked = false}; + let c = {id = nextId; client = aclient; var revoked = false}; nextId += 1; - let cs = new {head = c; var tail = clients}; + let cs = {head = c; var tail = clients}; clients := ?cs; return object { public shared func post(message : Text) { diff --git a/src/as_frontend/lexer.mll b/src/as_frontend/lexer.mll index 50c09787961..5fbb4473a25 100644 --- a/src/as_frontend/lexer.mll +++ b/src/as_frontend/lexer.mll @@ -202,7 +202,6 @@ rule token mode = parse | "in" { IN } | "import" { IMPORT } | "module" { MODULE } - | "new" { NEW } | "not" { NOT } | "null" { NULL } | "object" { OBJECT } diff --git a/src/as_frontend/parser.mly b/src/as_frontend/parser.mly index e37299dd4aa..ccf19848185 100644 --- a/src/as_frontend/parser.mly +++ b/src/as_frontend/parser.mly @@ -98,7 +98,7 @@ let share_expfield (ef : exp_field) = %token AWAIT ASYNC BREAK CASE CONTINUE LABEL %token IF IN ELSE SWITCH LOOP WHILE FOR RETURN %token ARROW ASSIGN -%token FUNC TYPE OBJECT ACTOR CLASS PUBLIC PRIVATE SHARED NEW +%token FUNC TYPE OBJECT ACTOR CLASS PUBLIC PRIVATE SHARED %token SEMICOLON SEMICOLON_EOL COMMA COLON SUB DOT QUEST %token AND OR NOT %token IMPORT MODULE @@ -138,7 +138,7 @@ let share_expfield (ef : exp_field) = %nonassoc SHLOP USHROP SSHROP ROTLOP ROTROP %left POWOP -%type exp exp_nullary +%type exp(ob) exp_nullary(ob) %start As_def.Syntax.prog> parse_prog %start As_def.Syntax.prog> parse_prog_interactive @@ -348,89 +348,96 @@ lit : | CATASSIGN { CatOp } +(* Default {} to block or object, respectively *) +bl : { fun ds -> BlockE(ds) } +ob : { fun ds -> ObjE(Type.Object @@ no_region, + List.map (fun d -> {dec = d; vis = Public @@ d.at} @@ d.at) ds) } + exp_block : | LCURLY ds=seplist(dec, semicolon) RCURLY { BlockE(ds) @? at $sloc } -exp_nullary : - | e=exp_block - { e } +exp_nullary(B) : + | LCURLY ds=seplist(dec_var, semicolon) RCURLY e=B + { e ds @? at $sloc } + | LCURLY efs=exp_field_list_unamb RCURLY + { ObjE(Type.Object @@ at $sloc, efs) @? at $sloc } + | LCURLY ds=dec_list_unamb RCURLY + { BlockE(ds) @? at $sloc } | x=id { VarE(x) @? at $sloc } | l=lit { LitE(ref l) @? at $sloc } - | LPAR es=seplist(exp, COMMA) RPAR + | LPAR es=seplist(exp(ob), COMMA) RPAR { match es with [e] -> e | _ -> TupE(es) @? at $sloc } | PRIM s=TEXT { PrimE(s) @? at $sloc } -exp_post : - | e=exp_nullary +exp_post(B) : + | e=exp_nullary(B) { e } - | LBRACKET m=var_opt es=seplist(exp_nonvar, COMMA) RBRACKET + | LBRACKET m=var_opt es=seplist(exp_nonvar(ob), COMMA) RBRACKET { ArrayE(m, es) @? at $sloc } - | e1=exp_post LBRACKET e2=exp RBRACKET + | e1=exp_post(ob) LBRACKET e2=exp(ob) RBRACKET { IdxE(e1, e2) @? at $sloc } - | e=exp_post s=DOT_NUM + | e=exp_post(ob) s=DOT_NUM { ProjE (e, int_of_string s) @? at $sloc } - | e=exp_post DOT x=id + | e=exp_post(ob) DOT x=id { DotE(e, x) @? at $sloc } - | e1=exp_post tso=typ_args? e2=exp_nullary + | e1=exp_post(ob) tso=typ_args? e2=exp_nullary(ob) { let typ_args = Lib.Option.get tso [] in CallE(e1, typ_args, e2) @? at $sloc } -exp_un : - | e=exp_post +exp_un(B) : + | e=exp_post(B) { e } | x=tag { TagE (x, TupE([]) @? at $sloc) @? at $sloc } - | x=tag e=exp_nullary + | x=tag e=exp_nullary(ob) { TagE (x, e) @? at $sloc } - | QUEST e=exp_un + | QUEST e=exp_un(ob) { OptE(e) @? at $sloc } - | op=unop e=exp_un + | op=unop e=exp_un(ob) { UnE(ref Type.Pre, op, e) @? at $sloc } - | op=unassign e=exp_un + | op=unassign e=exp_un(ob) { assign_op e (fun e' -> UnE(ref Type.Pre, op, e') @? at $sloc) (at $sloc) } - | NOT e=exp_un + | NOT e=exp_un(ob) { NotE e @? at $sloc } - | DEBUG_SHOW e=exp_un + | DEBUG_SHOW e=exp_un(ob) { ShowE (ref Type.Pre, e) @? at $sloc } -exp_bin : - | e=exp_un +exp_bin(B) : + | e=exp_un(B) { e } - | e1=exp_bin op=binop e2=exp_bin + | e1=exp_bin(ob) op=binop e2=exp_bin(ob) { BinE(ref Type.Pre, e1, op, e2) @? at $sloc } - | e1=exp_bin op=relop e2=exp_bin + | e1=exp_bin(ob) op=relop e2=exp_bin(ob) { RelE(ref Type.Pre, e1, op, e2) @? at $sloc } - | e1=exp_bin ASSIGN e2=exp_bin + | e1=exp_bin(ob) ASSIGN e2=exp_bin(ob) { AssignE(e1, e2) @? at $sloc} - | e1=exp_bin op=binassign e2=exp_bin + | e1=exp_bin(ob) op=binassign e2=exp_bin(ob) { assign_op e1 (fun e1' -> BinE(ref Type.Pre, e1', op, e2) @? at $sloc) (at $sloc) } - | e1=exp_bin AND e2=exp_bin + | e1=exp_bin(ob) AND e2=exp_bin(ob) { AndE(e1, e2) @? at $sloc } - | e1=exp_bin OR e2=exp_bin + | e1=exp_bin(ob) OR e2=exp_bin(ob) { OrE(e1, e2) @? at $sloc } - | e=exp_bin COLON t=typ + | e=exp_bin(ob) COLON t=typ { AnnotE(e, t) @? at $sloc } -exp_nondec : - | e=exp_bin +exp_nondec(B) : + | e=exp_bin(B) { e } - | NEW LCURLY efs=seplist(exp_field, semicolon) RCURLY - { ObjE(Type.Object @@ at $sloc, efs) @? at $sloc } | RETURN %prec RETURN_NO_ARG { RetE(TupE([]) @? at $sloc) @? at $sloc } - | RETURN e=exp + | RETURN e=exp(ob) { RetE(e) @? at $sloc } - | ASYNC e=exp + | ASYNC e=exp(bl) { AsyncE(e) @? at $sloc } - | AWAIT e=exp + | AWAIT e=exp(bl) { AwaitE(e) @? at $sloc } - | ASSERT e=exp + | ASSERT e=exp(bl) { AssertE(e) @? at $sloc } - | LABEL x=id rt=return_typ_nullary? e=exp + | LABEL x=id rt=return_typ_nullary? e=exp(bl) { let x' = ("continue " ^ x.it) @@ x.at in let t = Lib.Option.get rt (TupT [] @! at $sloc) in let e' = @@ -440,51 +447,60 @@ exp_nondec : | ForE (p, e1, e2) -> ForE (p, e1, LabelE (x', t, e2) @? e2.at) @? e.at | _ -> e in LabelE(x, t, e') @? at $sloc } - | BREAK x=id eo=exp_nullary? + | BREAK x=id eo=exp_nullary(ob)? { let e = Lib.Option.get eo (TupE([]) @? at $sloc) in BreakE(x, e) @? at $sloc } | CONTINUE x=id { let x' = ("continue " ^ x.it) @@ x.at in BreakE(x', TupE([]) @? no_region) @? at $sloc } - | IF b=exp_nullary e1=exp %prec IF_NO_ELSE + | IF b=exp_nullary(ob) e1=exp(bl) %prec IF_NO_ELSE { IfE(b, e1, TupE([]) @? no_region) @? at $sloc } - | IF b=exp_nullary e1=exp ELSE e2=exp + | IF b=exp_nullary(ob) e1=exp(bl) ELSE e2=exp(bl) { IfE(b, e1, e2) @? at $sloc } - | SWITCH e=exp_nullary LCURLY cs=seplist(case, semicolon) RCURLY + | SWITCH e=exp_nullary(ob) LCURLY cs=seplist(case, semicolon) RCURLY { SwitchE(e, cs) @? at $sloc } - | WHILE e1=exp_nullary e2=exp + | WHILE e1=exp_nullary(ob) e2=exp(bl) { WhileE(e1, e2) @? at $sloc } - | LOOP e=exp %prec LOOP_NO_WHILE + | LOOP e=exp(bl) %prec LOOP_NO_WHILE { LoopE(e, None) @? at $sloc } - | LOOP e1=exp WHILE e2=exp + | LOOP e1=exp(bl) WHILE e2=exp(bl) { LoopE(e1, Some e2) @? at $sloc } - | FOR LPAR p=pat IN e1=exp RPAR e2=exp + | FOR LPAR p=pat IN e1=exp(ob) RPAR e2=exp(bl) { ForE(p, e1, e2) @? at $sloc } -exp_nonvar : - | e=exp_nondec +exp_nonvar(B) : + | e=exp_nondec(B) { e } | d=dec_nonvar { match d.it with ExpD e -> e | _ -> BlockE([d]) @? at $sloc } -exp : - | e=exp_nonvar +exp(B) : + | e=exp_nonvar(B) { e } | d=dec_var { match d.it with ExpD e -> e | _ -> BlockE([d]) @? at $sloc } case : - | CASE p=pat_nullary e=exp + | CASE p=pat_nullary e=exp(bl) { {pat = p; exp = e} @@ at $sloc } -exp_field : - | x=id EQ e=exp +exp_field_nonvar : + | x=id EQ e=exp(ob) { let d = LetD(VarP(x) @! x.at, e) @? at $sloc in {dec = d; vis = Public @@ x.at} @@ at $sloc } - | VAR x=id EQ e=exp - { let d = VarD(x, e) @? at $sloc in - {dec = d; vis = Public @@ x.at} @@ at $sloc } + +exp_field : + | ef=exp_field_nonvar { ef } + | d=dec_var { {dec = d; vis = Public @@ d.at} @@ at $sloc } + +exp_field_list_unamb : (* does not overlap with dec_list_unamb *) + | ef=exp_field_nonvar + { [ef] } + | ef=exp_field_nonvar semicolon efs=seplist(exp_field, semicolon) + { ef::efs } + | d=dec_var semicolon efs=exp_field_list_unamb + { ({dec = d; vis = Public @@ d.at} @@ at $sloc) :: efs } dec_field : | v=vis d=dec @@ -498,7 +514,7 @@ vis : (* Patterns *) -pat_argument : +pat_param : | UNDERSCORE { WildP @! at $sloc } | x=id @@ -509,7 +525,7 @@ pat_argument : { (match ps with [p] -> ParP(p) | _ -> TupP(ps)) @! at $sloc } pat_nullary : - | p=pat_argument + | p=pat_param { p } | LCURLY fps=seplist(pat_field, semicolon) RCURLY { ObjP(fps) @! at $sloc } @@ -554,13 +570,15 @@ pat_field : (* Declarations *) dec_var : - | VAR x=id t=return_typ? EQ e=exp + | VAR x=id t=return_typ? EQ e=exp(ob) { let e' = match t with | None -> e | Some t -> AnnotE (e, t) @? span t.at e.at in VarD(x, e') @? at $sloc } - | LET p=pat EQ e=exp + +dec_nonvar : + | LET p=pat EQ e=exp(ob) { let p', e' = match p.it with | AnnotP (p', t) -> p', AnnotE (e, t) @? p.at @@ -568,8 +586,6 @@ dec_var : in LetD (p', e') @? at $sloc } | TYPE x=typ_id tps=typ_params_opt EQ t=typ { TypD(x, tps, t) @? at $sloc } - -dec_nonvar : | s=obj_sort xf=id_opt EQ? efs=obj_body { let named, x = xf "object" $sloc in let efs' = @@ -578,7 +594,7 @@ dec_nonvar : | s=func_sort_opt FUNC xf=id_opt fe=func_exp { let named, x = xf "func" $sloc in let_or_exp named x (fe s x.it).it (at $sloc) } - | s=obj_sort_opt CLASS xf=typ_id_opt tps=typ_params_opt p=pat_argument xefs=class_body + | s=obj_sort_opt CLASS xf=typ_id_opt tps=typ_params_opt p=pat_param xefs=class_body { let x, efs = xefs in let efs' = if s.it = Type.Actor then List.map share_expfield efs else efs @@ -592,11 +608,23 @@ dec : { d } | d=dec_nonvar { d } - | e=exp_nondec + | e=exp_nondec(ob) { ExpD e @? at $sloc } +dec_list_unamb : (* does not overlap with exp_field_list_unamb *) + | e=exp_nondec(ob) + { [ExpD e @? e.at] } + | d=dec_nonvar + { [d] } + | e=exp_nondec(ob) semicolon ds=seplist(dec, semicolon) + { (ExpD e @? e.at) :: ds } + | d=dec_nonvar semicolon ds=seplist(dec, semicolon) + { d::ds } + | d=dec_var semicolon ds=dec_list_unamb + { d::ds } + func_exp : - | tps=typ_params_opt p=pat_argument t=return_typ? fb=func_body + | tps=typ_params_opt p=pat_param t=return_typ? fb=func_body { (* This is a hack to support local func declarations that return a computed async. These should be defined using RHS syntax EQ e to avoid the implicit AsyncE introduction around bodies declared as blocks *) @@ -609,7 +637,7 @@ func_exp : in fun s x -> FuncE(x, s, tps, p, t, e) @? at $sloc } func_body : - | EQ e=exp { (false, e) } + | EQ e=exp(bl) { (false, e) } | e=exp_block { (true, e) } obj_body : diff --git a/src/as_types/type.ml b/src/as_types/type.ml index a3654eadd56..1f2ac7ec002 100644 --- a/src/as_types/type.ml +++ b/src/as_types/type.ml @@ -1127,6 +1127,8 @@ and string_of_field vs {lab; typ} = | Typ c -> let op, sbs, st = strings_of_kind (Con.kind c) in sprintf "type %s%s %s %s" lab sbs op st + | Mut t' -> + sprintf "var %s : %s" lab (string_of_typ' vs t') | _ -> sprintf "%s : %s" lab (string_of_typ' vs typ) diff --git a/stdlib/arrayTest.as b/stdlib/arrayTest.as index b971baa01fc..68022c62320 100644 --- a/stdlib/arrayTest.as +++ b/stdlib/arrayTest.as @@ -64,9 +64,9 @@ Prelude.printLn("Array"); }; let xs = [ - new { key = "a"; value = 0; }, - new { key = "b"; value = 1; }, - new { key = "c"; value = 2; }, + { key = "a"; value = 0; }, + { key = "b"; value = 1; }, + { key = "c"; value = 2; }, ]; let b : ?Element = Array.find(func (x : Element) : Bool { diff --git a/stdlib/docTable.as b/stdlib/docTable.as index a4baf4f5795..0ec6d6a3740 100644 --- a/stdlib/docTable.as +++ b/stdlib/docTable.as @@ -342,7 +342,7 @@ public class DocTable( =============== */ - public func keyOfId(x:Id) : Key = new { key = x ; hash = idHash(x) }; + public func keyOfId(x:Id) : Key = { key = x ; hash = idHash(x) }; public func getIdIsEq() :(Id,Id)->Bool = idIsEq; public func getIdHash() : Id->Hash = idHash; diff --git a/stdlib/examples/produce-exchange/serverActor.as b/stdlib/examples/produce-exchange/serverActor.as index 37e84de7af9..2b506197289 100644 --- a/stdlib/examples/produce-exchange/serverActor.as +++ b/stdlib/examples/produce-exchange/serverActor.as @@ -159,7 +159,7 @@ actor class Server () { // but two other sources exist for each type: the type of `insert` is known, and hence, this record has a known type, // and, the type of each of these `variables` is known, as well. - new { + { id=id_ :T.TruckTypeId; short_name=short_name_:Text; description=description_:Text; @@ -229,7 +229,7 @@ actor class Server () { Result.fromSome( getModel().regionTable.addInfoGetId( func (id_:T.RegionId) : T.RegionInfo = - new { + { id = id_:T.RegionId; short_name=short_name_:Text; description=description_:Text @@ -306,7 +306,7 @@ actor class Server () { Result.fromSome( getModel().produceTable.addInfoGetId( func (id_:T.ProduceId) : T.ProduceInfo = - new { + { id = id_:T.ProduceId; short_name=short_name_:Text; description=description_:Text; @@ -378,7 +378,7 @@ actor class Server () { Result.fromOption( getModel().producerTable.addInfoGetId( func(id_:T.ProducerId):T.ProducerInfo { - new { + { id=id_:T.ProducerId; public_key=producer_public_key; short_name=short_name_:Text; @@ -455,7 +455,7 @@ actor class Server () { Result.fromOption( getModel().retailerTable.addInfoGetId( func(id_:T.RetailerId):T.RetailerInfo { - new { + { id=id_:T.RetailerId; public_key=retailer_public_key; short_name=short_name_:Text; @@ -526,7 +526,7 @@ actor class Server () { Result.fromOption( getModel().transporterTable.addInfoGetId( func(id_:T.TransporterId):T.TransporterInfo { - new { + { id=id_:T.TransporterId; public_key=transporter_public_key; short_name=short_name_:Text; @@ -923,7 +923,7 @@ actor class Server () { public func getCounts() : async T.ProduceExchangeCounts { let m = getModel(); - new { + { hash_bit_length = 0; truck_type_count = m.truckTypeTable.count(); region_count = m.regionTable.count(); @@ -1059,7 +1059,7 @@ been processed public func devTestLoadQuery (region_count:Nat, scale_factor:Nat) { func scaledParams(region_count_:Nat, factor:Nat) : T.WorkloadParams = { - new { + { region_count = region_count_:Nat; day_count = 3:Nat; max_route_duration = 1:Nat; diff --git a/stdlib/examples/produce-exchange/serverModel.as b/stdlib/examples/produce-exchange/serverModel.as index c1024e36515..eed7ebf3d9e 100644 --- a/stdlib/examples/produce-exchange/serverModel.as +++ b/stdlib/examples/produce-exchange/serverModel.as @@ -171,7 +171,7 @@ public class Model() { case (#add (#truckType info)) Result.fromSomeMap( truckTypeTable.addInfoGetId( func (id_:T.TruckTypeId) : T.TruckTypeInfo = - new { + { id=id_; short_name=info.short_name; description=info.description; @@ -187,7 +187,7 @@ public class Model() { case (#add (#region info)) Result.fromSomeMap( regionTable.addInfoGetId( func (id_:T.RegionId) : T.RegionInfo = - new { + { id = id_; short_name=info.short_name; description=info.description @@ -200,7 +200,7 @@ public class Model() { case (#add (#produce info)) Result.fromSomeMap( produceTable.addInfoGetId( func (id_:T.ProduceId) : T.ProduceInfo = - new { + { id = id_; short_name=info.short_name; description=info.description; @@ -214,7 +214,7 @@ public class Model() { case (#add (#producer info)) Result.fromSomeMap( producerTable.addInfoGetId( func(id_:T.ProducerId):T.ProducerInfo { - new { + { id=id_; public_key=info.public_key; short_name=info.short_name; @@ -232,7 +232,7 @@ public class Model() { case (#add (#transporter info)) Result.fromSomeMap( transporterTable.addInfoGetId( func(id_:T.TransporterId):T.TransporterInfo { - new { + { id=id_; public_key=info.public_key; short_name=info.short_name; @@ -249,7 +249,7 @@ public class Model() { case (#add (#retailer info)) Result.fromSomeMap( retailerTable.addInfoGetId( func(id_:T.RetailerId):T.RetailerInfo { - new { + { id=id_; public_key=info.public_key; short_name=info.short_name; @@ -451,7 +451,7 @@ public class Model() { for (i in range(0, 1)) { reqs := ?( #truckType ( - new { + { id=i; short_name=""; description=""; capacity=i * 50; isFridge=true; isFreezer=true @@ -460,37 +460,37 @@ public class Model() { }; /**- add regions */ for (i in range(0, region_count - 1)) { - reqs := ?(#region (new { + reqs := ?(#region { id=i; short_name=""; description="" - }), reqs); + }, reqs); }; /**- add produce types, one per region. */ for (i in range(0, region_count - 1)) { - reqs := ?(#produce (new { + reqs := ?(#produce { id=i; short_name=""; description=""; grade=1; - }), reqs); + }, reqs); }; /**- add producers */ for (i in range(0, producer_count - 1)) { - reqs := ?(#producer (new { - id=i; public_key=""; short_name=""; description=""; - region=(i % region_count); - inventory=[]; reserved=[]; - }), reqs); + reqs := ?(#producer { + id=i; public_key=""; short_name=""; description=""; + region=(i % region_count); + inventory=[]; reserved=[]; + }, reqs); }; /**- add transporters */ for (i in range(0, producer_count - 1)) { - reqs := ?(#transporter (new { + reqs := ?(#transporter { id=i; public_key=""; short_name=""; description=""; routes=[]; reserved=[]; - }), reqs); + }, reqs); }; /**- add retailers */ for (i in range(0, retailer_count - 1)) { - reqs := ?(#retailer (new { - id=i; public_key=""; short_name=""; description=""; - region=(i % region_count); - }), reqs); + reqs := ?(#retailer { + id=i; public_key=""; short_name=""; description=""; + region=(i % region_count); + }, reqs); }; /**- add routes and inventory, across time and space: */ for (start_day in range(0, day_count-1)) { @@ -513,7 +513,7 @@ public class Model() { /**- choose this producer iff they are located in the start region: */ if ((p % region_count) == start_reg) { reqs := ?(#inventory - (new { + { id=666; producer = p; produce = start_reg; @@ -523,7 +523,7 @@ public class Model() { weight = 66; ppu = 22; comments = ""; - }), reqs); + }, reqs); } }; @@ -535,7 +535,7 @@ public class Model() { /**- choose this transporter iff their id matches the id of the region, modulo the number of regions: */ if ((t % region_count) == start_reg) { reqs := ?(#route - (new { + { id=666; transporter = t; start_region = start_reg; @@ -547,7 +547,7 @@ public class Model() { // cost is inversely proportional to route duration: slower is cheaper. // this example cost formula is "linear in duration, with a fixed base cost": cost = 100 + ((end_day - start_day) * 20); - }), reqs); + }, reqs); } }; }; @@ -619,15 +619,15 @@ public class Model() { func idPairHash(x:(Nat,Nat)):Hash { Hash.hashOfIntAcc(Hash.hashOfInt(x.0), x.1) }; func keyOf(x:Nat):Key { - new { key = x ; hash = idHash(x) } + { key = x ; hash = idHash(x) } }; func keyOfIdPair(x:Nat, y:Nat):Key<(Nat,Nat)> { - new { key = (x,y) ; hash = idPairHash(x,y) } + { key = (x,y) ; hash = idPairHash(x,y) } }; func keyOfText(x:Text):Key { - new { key = x ; hash = Hash.hashOfText(x) } + { key = x ; hash = Hash.hashOfText(x) } }; /** @@ -692,7 +692,7 @@ secondary maps. func(x:T.UserId):T.UserId{x+1}, func(x:T.UserId,y:T.UserId):Bool{x==y}, idHash, - func(doc:M.UserDoc):T.UserInfo = new { + func(doc:M.UserDoc):T.UserInfo = { id=doc.id; user_name=doc.user_name; public_key=doc.public_key; @@ -703,7 +703,7 @@ secondary maps. retailerId=doc.retailerId; isDeveloper=doc.isDeveloper; }, - func(info:T.UserInfo):?M.UserDoc = ?(new { + func(info:T.UserInfo):?M.UserDoc = ?{ id=info.id; user_name=info.user_name; public_key=info.public_key; @@ -713,7 +713,7 @@ secondary maps. transporterId=info.transporterId; retailerId=info.retailerId; isDeveloper=info.isDeveloper; - }), + }, ); @@ -728,7 +728,7 @@ secondary maps. func(x:T.TruckTypeId):T.TruckTypeId{x+1}, func(x:T.TruckTypeId,y:T.TruckTypeId):Bool{x==y}, idHash, - func(doc:M.TruckTypeDoc):T.TruckTypeInfo = new { + func(doc:M.TruckTypeDoc):T.TruckTypeInfo = { id=doc.id; short_name=doc.short_name; description=doc.description; @@ -736,14 +736,14 @@ secondary maps. isFridge=doc.isFridge; isFreezer=doc.isFreezer; }, - func(info:T.TruckTypeInfo):?M.TruckTypeDoc = ?(new { + func(info:T.TruckTypeInfo):?M.TruckTypeDoc = ?{ id=info.id; short_name=info.short_name; description=info.description; capacity=info.capacity; isFridge=info.isFridge; isFreezer=info.isFreezer; - }), + }, ); /** @@ -757,16 +757,16 @@ secondary maps. func(x:T.RegionId):T.RegionId{x+1}, func(x:T.RegionId,y:T.RegionId):Bool{x==y}, idHash, - func(doc:M.RegionDoc):T.RegionInfo = new { + func(doc:M.RegionDoc):T.RegionInfo = { id=doc.id; short_name=doc.short_name; description=doc.description; }, - func(info:T.RegionInfo):?M.RegionDoc = ?(new { + func(info:T.RegionInfo):?M.RegionDoc = ?{ id=info.id; short_name=info.short_name; description=info.description; - }), + }, ); /** @@ -780,18 +780,18 @@ secondary maps. func(x:T.ProduceId):T.ProduceId{x+1}, func(x:T.ProduceId,y:T.ProduceId):Bool{x==y}, idHash, - func(doc:M.ProduceDoc):T.ProduceInfo = new { + func(doc:M.ProduceDoc):T.ProduceInfo = { id=doc.id; short_name=doc.short_name; description=doc.description; grade=doc.grade; }, - func(info:T.ProduceInfo):?M.ProduceDoc = ?(new { + func(info:T.ProduceInfo):?M.ProduceDoc = ?{ id=info.id; short_name=info.short_name; description=info.description; grade=info.grade; - }), + }, ); /** @@ -805,7 +805,7 @@ secondary maps. func(x:T.ProducerId):T.ProducerId{x+1}, func(x:T.ProducerId,y:T.ProducerId):Bool{x==y}, idHash, - func(doc:M.ProducerDoc):T.ProducerInfo = new { + func(doc:M.ProducerDoc):T.ProducerInfo = { id=doc.id; public_key=doc.public_key; short_name=doc.short_name; @@ -816,7 +816,7 @@ secondary maps. }, func(info:T.ProducerInfo):?M.ProducerDoc = Option.map( - func (regionDoc: M.RegionDoc): M.ProducerDoc = new { + func (regionDoc: M.RegionDoc): M.ProducerDoc = { id=info.id; public_key=info.public_key; short_name=info.short_name; @@ -841,7 +841,7 @@ secondary maps. func(x:T.InventoryId):T.InventoryId{x+1}, func(x:T.InventoryId,y:T.InventoryId):Bool{x==y}, idHash, - func(doc:M.InventoryDoc):T.InventoryInfo = new { + func(doc:M.InventoryDoc):T.InventoryInfo = { id=doc.id; produce=doc.produce.id; producer=doc.producer; @@ -857,7 +857,7 @@ secondary maps. switch (producerTable.getDoc(info.producer), produceTable.getDoc(info.produce)) { case (?producerDoc, ?produceDoc) { - ?(new { + ?{ id=info.id; produce=produceDoc; producer=producerDoc.id; @@ -867,7 +867,7 @@ secondary maps. start_date=info.start_date; end_date=info.end_date; comments=info.comments; - }) + } }; case _ { null @@ -887,7 +887,7 @@ secondary maps. func(x:T.TransporterId):T.TransporterId{x+1}, func(x:T.TransporterId,y:T.TransporterId):Bool{x==y}, idHash, - func(doc:M.TransporterDoc):T.TransporterInfo = new { + func(doc:M.TransporterDoc):T.TransporterInfo = { id=doc.id; public_key=doc.public_key; short_name=doc.short_name; @@ -896,14 +896,14 @@ secondary maps. reserved=[]; }, func(info:T.TransporterInfo):?M.TransporterDoc = - ?(new { + ?{ id=info.id; public_key=info.public_key; short_name=info.short_name; description=info.description; routes=Table.empty(); reserved=Table.empty(); - }) + } ); /** @@ -917,7 +917,7 @@ secondary maps. func(x:T.RetailerId):T.RetailerId{x+1}, func(x:T.RetailerId,y:T.RetailerId):Bool{x==y}, idHash, - func(doc:M.RetailerDoc):T.RetailerInfo = new { + func(doc:M.RetailerDoc):T.RetailerInfo = { id=doc.id; public_key=doc.public_key; short_name=doc.short_name; @@ -928,7 +928,7 @@ secondary maps. }, func(info:T.RetailerInfo):?M.RetailerDoc = Option.map( - func (regionDoc: M.RegionDoc): M.RetailerDoc = new { + func (regionDoc: M.RegionDoc): M.RetailerDoc = { id=info.id; public_key=info.public_key; short_name=info.short_name; @@ -955,7 +955,7 @@ secondary maps. func(x:T.RouteId):T.RouteId{x+1}, func(x:T.RouteId,y:T.RouteId):Bool{x==y}, idHash, - func(doc:M.RouteDoc):T.RouteInfo = new { + func(doc:M.RouteDoc):T.RouteInfo = { id=doc.id; transporter=doc.transporter; truck_type=(truckTypeTable.getInfoOfDoc())(doc.truck_type); @@ -972,7 +972,7 @@ secondary maps. regionTable.getDoc(info.end_region)) { case (?_, ?truckType, ?startRegion, ?endRegion) { - ?(new { + ?{ id=info.id; transporter=info.transporter; truck_type=truckType; @@ -981,7 +981,7 @@ secondary maps. start_date=info.start_date; end_date=info.end_date; cost=info.cost; - }) + } }; case _ { null } }} @@ -999,10 +999,10 @@ secondary maps. func(x:T.ReservedInventoryId):T.ReservedInventoryId{x+1}, func(x:T.ReservedInventoryId,y:T.ReservedInventoryId):Bool{x==y}, idHash, - func(doc:M.ReservedInventoryDoc):T.ReservedInventoryInfo = new { + func(doc:M.ReservedInventoryDoc):T.ReservedInventoryInfo = { id=doc.id; retailer=doc.retailer; - item=new { + item={ id=doc.item.id; produce=doc.item.produce.id; producer=doc.item.producer; @@ -1019,11 +1019,11 @@ secondary maps. switch (inventoryTable.getDoc(info.id), retailerTable.getDoc(info.retailer)) { case (?item_, ?_) { - ?(new { + ?{ id=info.id; item=item_:M.InventoryDoc; retailer=info.retailer; - }) + } }; case _ { null @@ -1042,13 +1042,13 @@ secondary maps. func(x:T.ReservedRouteId):T.ReservedRouteId{x+1}, func(x:T.ReservedRouteId,y:T.ReservedRouteId):Bool{x==y}, idHash, - func(doc:M.ReservedRouteDoc):T.ReservedRouteInfo = new { + func(doc:M.ReservedRouteDoc):T.ReservedRouteInfo = { id=doc.id; retailer=doc.retailer; - route=new { + route={ id=doc.route.id; transporter=doc.route.transporter; - truck_type=new { + truck_type={ id=doc.route.truck_type.id; short_name=doc.route.truck_type.short_name; description=doc.route.truck_type.description; @@ -1068,11 +1068,11 @@ secondary maps. switch (routeTable.getDoc(info.id), retailerTable.getDoc(info.retailer)) { case (?route_, ?_) { - ?(new { + ?{ id=info.id; route=route_:M.RouteDoc; retailer=info.retailer; - }) + } }; case _ { null @@ -1237,7 +1237,7 @@ than the MVP goals, however. /**- Create a producer role for the user: */ let prId = if isProducer { producerTable.addInfoGetId( func(id_:T.ProducerId):T.ProducerInfo { - new { + { id=id_:T.ProducerId; public_key=public_key_; short_name=user_name_; @@ -1251,7 +1251,7 @@ than the MVP goals, however. /**- Create a transporter role for the user: */ let trId = if isTransporter { transporterTable.addInfoGetId( func(id_:T.TransporterId):T.TransporterInfo { - new { + { id=id_:T.TransporterId; public_key=public_key_; short_name=user_name_; @@ -1264,7 +1264,7 @@ than the MVP goals, however. /**- Create a retailer role for the user: */ let rrId = if isRetailer { retailerTable.addInfoGetId( func(id_:T.RetailerId):T.RetailerInfo { - new { + { id=id_; public_key=public_key_; short_name=user_name_; @@ -1276,7 +1276,7 @@ than the MVP goals, however. /**- Record the user information: */ let id = userTable.addInfoGetId( func (id_: T.UserId) : T.UserInfo = - new { + { id = id_; user_name = user_name_; public_key = public_key_; @@ -1378,7 +1378,7 @@ than the MVP goals, however. let (_, item) = { switch (inventoryTable.addInfoAs(iid_, func(iid:T.InventoryId):T.InventoryInfo{ - new { + { id = iid :T.InventoryId; produce = produce_id:T.ProduceId; producer = id_ :T.ProducerId; @@ -1407,7 +1407,7 @@ than the MVP goals, however. /**- Update the producer document; xxx more concise syntax for functional record updates would be nice: */ let _ = producerTable.updateDoc( producer_.id, - new { + { id = producer_.id; public_key = producer_.public_key; short_name = producer_.short_name; @@ -1510,7 +1510,7 @@ than the MVP goals, however. producer.inventory, keyOf(id), idIsEq); /// xxx syntax for functional record updates? - let updatedProducer = new { + let updatedProducer = { id = producer.id ; public_key = producer.public_key ; short_name = producer.short_name ; @@ -1600,7 +1600,7 @@ than the MVP goals, however. /**- Create the route item document: */ let route : M.RouteDoc = { switch (routeTable.addInfoAs(rid_, func(routeId:T.RouteId):T.RouteInfo{ - new { + { id= routeId; transporter=transporterId; truck_type=truck_type_; @@ -1628,7 +1628,7 @@ than the MVP goals, however. /**- Update the transporter document; xxx more concise syntax for functional record updates would be nice: */ let _ = transporterTable.updateDoc( transporter.id, - new { + { id = transporter.id; public_key = transporter.public_key; short_name = transporter.short_name; @@ -1730,7 +1730,7 @@ than the MVP goals, however. Trie.remove( transporter.routes, keyOf(id), idIsEq); - let updatedTransporter = new { + let updatedTransporter = { id = transporter.id ; public_key = transporter.public_key; short_name = transporter.short_name ; @@ -1816,7 +1816,7 @@ than the MVP goals, however. based on the given inventory and route documents. */ public func makeReservationInfo(item:M.InventoryDoc, route:M.RouteDoc) : T.ReservationInfo { - new { + { produce =item.produce.id :T.ProduceId; producer =item.producer :T.ProducerId; quant =item.quantity :T.Quantity; @@ -2175,7 +2175,7 @@ than the MVP goals, however. /**- move route document into reserved route table, and mint an ID. */ let (_, reservedRouteDoc) = reservedRouteTable.addDoc( func (rrid:T.ReservedRouteId):M.ReservedRouteDoc { - new { + { id=rrid; retailer=retailerDoc.id; route=routeDoc; @@ -2186,7 +2186,7 @@ than the MVP goals, however. /**- move inventory document into reserved inventory table, and mint an ID. */ let (_, reservedInventoryDoc) = reservedInventoryTable.addDoc( func (rrid:T.ReservedInventoryId):M.ReservedInventoryDoc { - new { + { id=rrid; retailer=retailerDoc.id; item=inventoryDoc; @@ -2211,7 +2211,7 @@ than the MVP goals, however. reservedInventoryDoc); // xxx -- AS wishlist: better syntax for functional record update: - let updatedProducer = new { + let updatedProducer = { id=producerDoc2.id; public_key=producerDoc2.public_key; short_name=producerDoc2.short_name; @@ -2235,7 +2235,7 @@ than the MVP goals, however. reservedRouteDoc); // xxx -- AS wishlist: better syntax for functional record update: - let updatedTransporter = new { + let updatedTransporter = { id=transporterDoc2.id; public_key=transporterDoc2.public_key; short_name=transporterDoc2.short_name; @@ -2258,7 +2258,7 @@ than the MVP goals, however. (reservedInventoryDoc, reservedRouteDoc)); // xxx -- AS wishlist: better syntax for functional record update: - let updatedRetailer = new { + let updatedRetailer = { id=retailerDoc.id; public_key=retailerDoc.public_key; short_name=retailerDoc.short_name; diff --git a/stdlib/examples/produce-exchange/test/evalBulk.as b/stdlib/examples/produce-exchange/test/evalBulk.as index 92256729b5a..a212ac9a1ef 100644 --- a/stdlib/examples/produce-exchange/test/evalBulk.as +++ b/stdlib/examples/produce-exchange/test/evalBulk.as @@ -32,82 +32,82 @@ actor class Test() = this { let bulkResp = s.evalBulkArray( [ #add([ - #truckType (new { id=0; short_name="tta"; description=""; capacity=10; isFridge=false; isFreezer=false }), - #truckType (new { id=1; short_name="ttb"; description=""; capacity=20; isFridge=false; isFreezer=false }), - #truckType (new { id=2; short_name="ttc"; description=""; capacity=30; isFridge=true; isFreezer=false }), - #truckType (new { id=3; short_name="ttd"; description=""; capacity=40; isFridge=true; isFreezer=false }), - #truckType (new { id=4; short_name="tte"; description=""; capacity=50; isFridge=true; isFreezer=true }), - - #region (new { id=0; short_name="rega"; description=""; }), - #region (new { id=1; short_name="regb"; description=""; }), - #region (new { id=2; short_name="regc"; description=""; }), - #region (new { id=3; short_name="regd"; description=""; }), - - #produce (new { id=0; short_name="avocado"; description=""; grade=1}), - #produce (new { id=1; short_name="apple"; description=""; grade=1}), - #produce (new { id=2; short_name="banana"; description=""; grade=1}), - #produce (new { id=3; short_name="grapefruit"; description=""; grade=1}), - - #user (new { user_name="a"; public_key=pka; description=""; region=0; - isDeveloper=true; isProducer=true; isRetailer=true; isTransporter=true }), - #user (new { user_name="b"; public_key=pkb; description=""; region=1; - isDeveloper=true; isProducer=true; isRetailer=true; isTransporter=true }), - #user (new { user_name="c"; public_key=pkc; description=""; region=2; - isDeveloper=true; isProducer=true; isRetailer=true; isTransporter=true }), - #user (new { user_name="d"; public_key=pkd; description=""; region=3; - isDeveloper=true; isProducer=true; isRetailer=true; isTransporter=true }), - #user (new { user_name="e"; public_key=pke; description=""; region=0; - isDeveloper=true; isProducer=true; isRetailer=true; isTransporter=true }), - - #inventory (new { id=0; produce=0; producer=0; start_date=0; end_date=10; quantity=100; weight=100; ppu=2; comments=""}), - #inventory (new { id=0; produce=1; producer=0; start_date=1; end_date=10; quantity=100; weight=100; ppu=2; comments=""}), - #inventory (new { id=0; produce=2; producer=0; start_date=2; end_date=10; quantity=100; weight=100; ppu=2; comments=""}), - #inventory (new { id=0; produce=3; producer=0; start_date=3; end_date=10; quantity=100; weight=100; ppu=2; comments=""}), - - #inventory (new { id=0; produce=0; producer=1; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (new { id=0; produce=1; producer=1; start_date=0; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (new { id=0; produce=2; producer=1; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (new { id=0; produce=3; producer=1; start_date=0; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - - #inventory (new { id=0; produce=0; producer=2; start_date=0; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (new { id=0; produce=1; producer=2; start_date=1; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (new { id=0; produce=2; producer=2; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (new { id=0; produce=3; producer=2; start_date=5; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - - #inventory (new { id=0; produce=0; producer=3; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (new { id=0; produce=1; producer=3; start_date=1; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (new { id=0; produce=2; producer=3; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (new { id=0; produce=3; producer=3; start_date=1; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - - #inventory (new { id=0; produce=0; producer=4; start_date=6; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (new { id=0; produce=1; producer=4; start_date=7; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (new { id=0; produce=2; producer=4; start_date=8; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (new { id=0; produce=3; producer=4; start_date=9; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - - #route (new { id=0; transporter=0; truck_type=0; start_region=0; end_region=1; start_date=0; end_date=10; cost=100 }), - #route (new { id=0; transporter=0; truck_type=0; start_region=0; end_region=2; start_date=1; end_date=10; cost=100 }), - #route (new { id=0; transporter=0; truck_type=0; start_region=0; end_region=3; start_date=2; end_date=10; cost=100 }), - #route (new { id=0; transporter=0; truck_type=0; start_region=0; end_region=4; start_date=3; end_date=10; cost=100 }), - - #route (new { id=0; transporter=1; truck_type=0; start_region=1; end_region=1; start_date=0; end_date=10; cost=100 }), - #route (new { id=0; transporter=1; truck_type=0; start_region=1; end_region=2; start_date=1; end_date=10; cost=100 }), - #route (new { id=0; transporter=1; truck_type=0; start_region=1; end_region=3; start_date=2; end_date=10; cost=100 }), - #route (new { id=0; transporter=1; truck_type=0; start_region=1; end_region=4; start_date=3; end_date=10; cost=100 }), - - #route (new { id=0; transporter=2; truck_type=0; start_region=2; end_region=1; start_date=0; end_date=10; cost=100 }), - #route (new { id=0; transporter=2; truck_type=0; start_region=2; end_region=2; start_date=1; end_date=10; cost=100 }), - #route (new { id=0; transporter=2; truck_type=0; start_region=2; end_region=3; start_date=2; end_date=10; cost=100 }), - #route (new { id=0; transporter=2; truck_type=0; start_region=2; end_region=4; start_date=3; end_date=10; cost=100 }), - - #route (new { id=0; transporter=3; truck_type=0; start_region=3; end_region=1; start_date=0; end_date=10; cost=100 }), - #route (new { id=0; transporter=3; truck_type=0; start_region=3; end_region=2; start_date=1; end_date=10; cost=100 }), - #route (new { id=0; transporter=3; truck_type=0; start_region=3; end_region=3; start_date=2; end_date=10; cost=100 }), - #route (new { id=0; transporter=3; truck_type=0; start_region=3; end_region=4; start_date=3; end_date=10; cost=100 }), - - #route (new { id=0; transporter=4; truck_type=0; start_region=4; end_region=1; start_date=0; end_date=10; cost=100 }), - #route (new { id=0; transporter=4; truck_type=0; start_region=4; end_region=2; start_date=1; end_date=10; cost=100 }), - #route (new { id=0; transporter=4; truck_type=0; start_region=4; end_region=3; start_date=2; end_date=10; cost=100 }), - #route (new { id=0; transporter=4; truck_type=0; start_region=4; end_region=4; start_date=3; end_date=10; cost=100 }), + #truckType { id=0; short_name="tta"; description=""; capacity=10; isFridge=false; isFreezer=false }, + #truckType { id=1; short_name="ttb"; description=""; capacity=20; isFridge=false; isFreezer=false }, + #truckType { id=2; short_name="ttc"; description=""; capacity=30; isFridge=true; isFreezer=false }, + #truckType { id=3; short_name="ttd"; description=""; capacity=40; isFridge=true; isFreezer=false }, + #truckType { id=4; short_name="tte"; description=""; capacity=50; isFridge=true; isFreezer=true }, + + #region { id=0; short_name="rega"; description=""; }, + #region { id=1; short_name="regb"; description=""; }, + #region { id=2; short_name="regc"; description=""; }, + #region { id=3; short_name="regd"; description=""; }, + + #produce { id=0; short_name="avocado"; description=""; grade=1}, + #produce { id=1; short_name="apple"; description=""; grade=1}, + #produce { id=2; short_name="banana"; description=""; grade=1}, + #produce { id=3; short_name="grapefruit"; description=""; grade=1}, + + #user { user_name="a"; public_key=pka; description=""; region=0; + isDeveloper=true; isProducer=true; isRetailer=true; isTransporter=true }, + #user { user_name="b"; public_key=pkb; description=""; region=1; + isDeveloper=true; isProducer=true; isRetailer=true; isTransporter=true }, + #user { user_name="c"; public_key=pkc; description=""; region=2; + isDeveloper=true; isProducer=true; isRetailer=true; isTransporter=true }, + #user { user_name="d"; public_key=pkd; description=""; region=3; + isDeveloper=true; isProducer=true; isRetailer=true; isTransporter=true }, + #user { user_name="e"; public_key=pke; description=""; region=0; + isDeveloper=true; isProducer=true; isRetailer=true; isTransporter=true }, + + #inventory { id=0; produce=0; producer=0; start_date=0; end_date=10; quantity=100; weight=100; ppu=2; comments=""}, + #inventory { id=0; produce=1; producer=0; start_date=1; end_date=10; quantity=100; weight=100; ppu=2; comments=""}, + #inventory { id=0; produce=2; producer=0; start_date=2; end_date=10; quantity=100; weight=100; ppu=2; comments=""}, + #inventory { id=0; produce=3; producer=0; start_date=3; end_date=10; quantity=100; weight=100; ppu=2; comments=""}, + + #inventory { id=0; produce=0; producer=1; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}, + #inventory { id=0; produce=1; producer=1; start_date=0; end_date=10; quantity=100; weight=100; ppu=3; comments=""}, + #inventory { id=0; produce=2; producer=1; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}, + #inventory { id=0; produce=3; producer=1; start_date=0; end_date=10; quantity=100; weight=100; ppu=3; comments=""}, + + #inventory { id=0; produce=0; producer=2; start_date=0; end_date=10; quantity=100; weight=100; ppu=3; comments=""}, + #inventory { id=0; produce=1; producer=2; start_date=1; end_date=10; quantity=100; weight=100; ppu=3; comments=""}, + #inventory { id=0; produce=2; producer=2; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}, + #inventory { id=0; produce=3; producer=2; start_date=5; end_date=10; quantity=100; weight=100; ppu=3; comments=""}, + + #inventory { id=0; produce=0; producer=3; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}, + #inventory { id=0; produce=1; producer=3; start_date=1; end_date=10; quantity=100; weight=100; ppu=3; comments=""}, + #inventory { id=0; produce=2; producer=3; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}, + #inventory { id=0; produce=3; producer=3; start_date=1; end_date=10; quantity=100; weight=100; ppu=3; comments=""}, + + #inventory { id=0; produce=0; producer=4; start_date=6; end_date=10; quantity=100; weight=100; ppu=3; comments=""}, + #inventory { id=0; produce=1; producer=4; start_date=7; end_date=10; quantity=100; weight=100; ppu=3; comments=""}, + #inventory { id=0; produce=2; producer=4; start_date=8; end_date=10; quantity=100; weight=100; ppu=3; comments=""}, + #inventory { id=0; produce=3; producer=4; start_date=9; end_date=10; quantity=100; weight=100; ppu=3; comments=""}, + + #route { id=0; transporter=0; truck_type=0; start_region=0; end_region=1; start_date=0; end_date=10; cost=100 }, + #route { id=0; transporter=0; truck_type=0; start_region=0; end_region=2; start_date=1; end_date=10; cost=100 }, + #route { id=0; transporter=0; truck_type=0; start_region=0; end_region=3; start_date=2; end_date=10; cost=100 }, + #route { id=0; transporter=0; truck_type=0; start_region=0; end_region=4; start_date=3; end_date=10; cost=100 }, + + #route { id=0; transporter=1; truck_type=0; start_region=1; end_region=1; start_date=0; end_date=10; cost=100 }, + #route { id=0; transporter=1; truck_type=0; start_region=1; end_region=2; start_date=1; end_date=10; cost=100 }, + #route { id=0; transporter=1; truck_type=0; start_region=1; end_region=3; start_date=2; end_date=10; cost=100 }, + #route { id=0; transporter=1; truck_type=0; start_region=1; end_region=4; start_date=3; end_date=10; cost=100 }, + + #route { id=0; transporter=2; truck_type=0; start_region=2; end_region=1; start_date=0; end_date=10; cost=100 }, + #route { id=0; transporter=2; truck_type=0; start_region=2; end_region=2; start_date=1; end_date=10; cost=100 }, + #route { id=0; transporter=2; truck_type=0; start_region=2; end_region=3; start_date=2; end_date=10; cost=100 }, + #route { id=0; transporter=2; truck_type=0; start_region=2; end_region=4; start_date=3; end_date=10; cost=100 }, + + #route { id=0; transporter=3; truck_type=0; start_region=3; end_region=1; start_date=0; end_date=10; cost=100 }, + #route { id=0; transporter=3; truck_type=0; start_region=3; end_region=2; start_date=1; end_date=10; cost=100 }, + #route { id=0; transporter=3; truck_type=0; start_region=3; end_region=3; start_date=2; end_date=10; cost=100 }, + #route { id=0; transporter=3; truck_type=0; start_region=3; end_region=4; start_date=3; end_date=10; cost=100 }, + + #route { id=0; transporter=4; truck_type=0; start_region=4; end_region=1; start_date=0; end_date=10; cost=100 }, + #route { id=0; transporter=4; truck_type=0; start_region=4; end_region=2; start_date=1; end_date=10; cost=100 }, + #route { id=0; transporter=4; truck_type=0; start_region=4; end_region=3; start_date=2; end_date=10; cost=100 }, + #route { id=0; transporter=4; truck_type=0; start_region=4; end_region=4; start_date=3; end_date=10; cost=100 }, ]) ] diff --git a/stdlib/examples/produce-exchange/test/producerRemInventory.as b/stdlib/examples/produce-exchange/test/producerRemInventory.as index 605831e3edd..46390b0b127 100644 --- a/stdlib/examples/produce-exchange/test/producerRemInventory.as +++ b/stdlib/examples/produce-exchange/test/producerRemInventory.as @@ -32,82 +32,82 @@ actor class Test() = this { let bulkResp = s.evalBulkArray( [ #add([ - #truckType (new { id=0; short_name="tta"; description=""; capacity=10; isFridge=false; isFreezer=false }), - #truckType (new { id=1; short_name="ttb"; description=""; capacity=20; isFridge=false; isFreezer=false }), - #truckType (new { id=2; short_name="ttc"; description=""; capacity=30; isFridge=true; isFreezer=false }), - #truckType (new { id=3; short_name="ttd"; description=""; capacity=40; isFridge=true; isFreezer=false }), - #truckType (new { id=4; short_name="tte"; description=""; capacity=50; isFridge=true; isFreezer=true }), - - #region (new { id=0; short_name="rega"; description=""; }), - #region (new { id=1; short_name="regb"; description=""; }), - #region (new { id=2; short_name="regc"; description=""; }), - #region (new { id=3; short_name="regd"; description=""; }), - - #produce (new { id=0; short_name="avocado"; description=""; grade=1}), - #produce (new { id=1; short_name="apple"; description=""; grade=1}), - #produce (new { id=2; short_name="banana"; description=""; grade=1}), - #produce (new { id=3; short_name="grapefruit"; description=""; grade=1}), - - #user (new { user_name="a"; public_key=pka; description=""; region=0; - isDeveloper=true; isProducer=true; isRetailer=true; isTransporter=true }), - #user (new { user_name="b"; public_key=pkb; description=""; region=1; - isDeveloper=true; isProducer=true; isRetailer=true; isTransporter=true }), - #user (new { user_name="c"; public_key=pkc; description=""; region=2; - isDeveloper=true; isProducer=true; isRetailer=true; isTransporter=true }), - #user (new { user_name="d"; public_key=pkd; description=""; region=3; - isDeveloper=true; isProducer=true; isRetailer=true; isTransporter=true }), - #user (new { user_name="e"; public_key=pke; description=""; region=0; - isDeveloper=true; isProducer=true; isRetailer=true; isTransporter=true }), - - #inventory (new { id=0; produce=0; producer=0; start_date=0; end_date=10; quantity=100; weight=100; ppu=2; comments=""}), - #inventory (new { id=0; produce=1; producer=0; start_date=1; end_date=10; quantity=100; weight=100; ppu=2; comments=""}), - #inventory (new { id=0; produce=2; producer=0; start_date=2; end_date=10; quantity=100; weight=100; ppu=2; comments=""}), - #inventory (new { id=0; produce=3; producer=0; start_date=3; end_date=10; quantity=100; weight=100; ppu=2; comments=""}), - - #inventory (new { id=0; produce=0; producer=1; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (new { id=0; produce=1; producer=1; start_date=0; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (new { id=0; produce=2; producer=1; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (new { id=0; produce=3; producer=1; start_date=0; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - - #inventory (new { id=0; produce=0; producer=2; start_date=0; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (new { id=0; produce=1; producer=2; start_date=1; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (new { id=0; produce=2; producer=2; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (new { id=0; produce=3; producer=2; start_date=5; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - - #inventory (new { id=0; produce=0; producer=3; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (new { id=0; produce=1; producer=3; start_date=1; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (new { id=0; produce=2; producer=3; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (new { id=0; produce=3; producer=3; start_date=1; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - - #inventory (new { id=0; produce=0; producer=4; start_date=6; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (new { id=0; produce=1; producer=4; start_date=7; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (new { id=0; produce=2; producer=4; start_date=8; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - #inventory (new { id=0; produce=3; producer=4; start_date=9; end_date=10; quantity=100; weight=100; ppu=3; comments=""}), - - #route (new { id=0; transporter=0; truck_type=0; start_region=0; end_region=1; start_date=0; end_date=10; cost=100 }), - #route (new { id=0; transporter=0; truck_type=0; start_region=0; end_region=2; start_date=1; end_date=10; cost=100 }), - #route (new { id=0; transporter=0; truck_type=0; start_region=0; end_region=3; start_date=2; end_date=10; cost=100 }), - #route (new { id=0; transporter=0; truck_type=0; start_region=0; end_region=4; start_date=3; end_date=10; cost=100 }), - - #route (new { id=0; transporter=1; truck_type=0; start_region=1; end_region=1; start_date=0; end_date=10; cost=100 }), - #route (new { id=0; transporter=1; truck_type=0; start_region=1; end_region=2; start_date=1; end_date=10; cost=100 }), - #route (new { id=0; transporter=1; truck_type=0; start_region=1; end_region=3; start_date=2; end_date=10; cost=100 }), - #route (new { id=0; transporter=1; truck_type=0; start_region=1; end_region=4; start_date=3; end_date=10; cost=100 }), - - #route (new { id=0; transporter=2; truck_type=0; start_region=2; end_region=1; start_date=0; end_date=10; cost=100 }), - #route (new { id=0; transporter=2; truck_type=0; start_region=2; end_region=2; start_date=1; end_date=10; cost=100 }), - #route (new { id=0; transporter=2; truck_type=0; start_region=2; end_region=3; start_date=2; end_date=10; cost=100 }), - #route (new { id=0; transporter=2; truck_type=0; start_region=2; end_region=4; start_date=3; end_date=10; cost=100 }), - - #route (new { id=0; transporter=3; truck_type=0; start_region=3; end_region=1; start_date=0; end_date=10; cost=100 }), - #route (new { id=0; transporter=3; truck_type=0; start_region=3; end_region=2; start_date=1; end_date=10; cost=100 }), - #route (new { id=0; transporter=3; truck_type=0; start_region=3; end_region=3; start_date=2; end_date=10; cost=100 }), - #route (new { id=0; transporter=3; truck_type=0; start_region=3; end_region=4; start_date=3; end_date=10; cost=100 }), - - #route (new { id=0; transporter=4; truck_type=0; start_region=4; end_region=1; start_date=0; end_date=10; cost=100 }), - #route (new { id=0; transporter=4; truck_type=0; start_region=4; end_region=2; start_date=1; end_date=10; cost=100 }), - #route (new { id=0; transporter=4; truck_type=0; start_region=4; end_region=3; start_date=2; end_date=10; cost=100 }), - #route (new { id=0; transporter=4; truck_type=0; start_region=4; end_region=4; start_date=3; end_date=10; cost=100 }), + #truckType { id=0; short_name="tta"; description=""; capacity=10; isFridge=false; isFreezer=false }, + #truckType { id=1; short_name="ttb"; description=""; capacity=20; isFridge=false; isFreezer=false }, + #truckType { id=2; short_name="ttc"; description=""; capacity=30; isFridge=true; isFreezer=false }, + #truckType { id=3; short_name="ttd"; description=""; capacity=40; isFridge=true; isFreezer=false }, + #truckType { id=4; short_name="tte"; description=""; capacity=50; isFridge=true; isFreezer=true }, + + #region { id=0; short_name="rega"; description=""; }, + #region { id=1; short_name="regb"; description=""; }, + #region { id=2; short_name="regc"; description=""; }, + #region { id=3; short_name="regd"; description=""; }, + + #produce { id=0; short_name="avocado"; description=""; grade=1}, + #produce { id=1; short_name="apple"; description=""; grade=1}, + #produce { id=2; short_name="banana"; description=""; grade=1}, + #produce { id=3; short_name="grapefruit"; description=""; grade=1}, + + #user { user_name="a"; public_key=pka; description=""; region=0; + isDeveloper=true; isProducer=true; isRetailer=true; isTransporter=true }, + #user { user_name="b"; public_key=pkb; description=""; region=1; + isDeveloper=true; isProducer=true; isRetailer=true; isTransporter=true }, + #user { user_name="c"; public_key=pkc; description=""; region=2; + isDeveloper=true; isProducer=true; isRetailer=true; isTransporter=true }, + #user { user_name="d"; public_key=pkd; description=""; region=3; + isDeveloper=true; isProducer=true; isRetailer=true; isTransporter=true }, + #user { user_name="e"; public_key=pke; description=""; region=0; + isDeveloper=true; isProducer=true; isRetailer=true; isTransporter=true }, + + #inventory { id=0; produce=0; producer=0; start_date=0; end_date=10; quantity=100; weight=100; ppu=2; comments=""}, + #inventory { id=0; produce=1; producer=0; start_date=1; end_date=10; quantity=100; weight=100; ppu=2; comments=""}, + #inventory { id=0; produce=2; producer=0; start_date=2; end_date=10; quantity=100; weight=100; ppu=2; comments=""}, + #inventory { id=0; produce=3; producer=0; start_date=3; end_date=10; quantity=100; weight=100; ppu=2; comments=""}, + + #inventory { id=0; produce=0; producer=1; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}, + #inventory { id=0; produce=1; producer=1; start_date=0; end_date=10; quantity=100; weight=100; ppu=3; comments=""}, + #inventory { id=0; produce=2; producer=1; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}, + #inventory { id=0; produce=3; producer=1; start_date=0; end_date=10; quantity=100; weight=100; ppu=3; comments=""}, + + #inventory { id=0; produce=0; producer=2; start_date=0; end_date=10; quantity=100; weight=100; ppu=3; comments=""}, + #inventory { id=0; produce=1; producer=2; start_date=1; end_date=10; quantity=100; weight=100; ppu=3; comments=""}, + #inventory { id=0; produce=2; producer=2; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}, + #inventory { id=0; produce=3; producer=2; start_date=5; end_date=10; quantity=100; weight=100; ppu=3; comments=""}, + + #inventory { id=0; produce=0; producer=3; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}, + #inventory { id=0; produce=1; producer=3; start_date=1; end_date=10; quantity=100; weight=100; ppu=3; comments=""}, + #inventory { id=0; produce=2; producer=3; start_date=2; end_date=10; quantity=100; weight=100; ppu=3; comments=""}, + #inventory { id=0; produce=3; producer=3; start_date=1; end_date=10; quantity=100; weight=100; ppu=3; comments=""}, + + #inventory { id=0; produce=0; producer=4; start_date=6; end_date=10; quantity=100; weight=100; ppu=3; comments=""}, + #inventory { id=0; produce=1; producer=4; start_date=7; end_date=10; quantity=100; weight=100; ppu=3; comments=""}, + #inventory { id=0; produce=2; producer=4; start_date=8; end_date=10; quantity=100; weight=100; ppu=3; comments=""}, + #inventory { id=0; produce=3; producer=4; start_date=9; end_date=10; quantity=100; weight=100; ppu=3; comments=""}, + + #route { id=0; transporter=0; truck_type=0; start_region=0; end_region=1; start_date=0; end_date=10; cost=100 }, + #route { id=0; transporter=0; truck_type=0; start_region=0; end_region=2; start_date=1; end_date=10; cost=100 }, + #route { id=0; transporter=0; truck_type=0; start_region=0; end_region=3; start_date=2; end_date=10; cost=100 }, + #route { id=0; transporter=0; truck_type=0; start_region=0; end_region=4; start_date=3; end_date=10; cost=100 }, + + #route { id=0; transporter=1; truck_type=0; start_region=1; end_region=1; start_date=0; end_date=10; cost=100 }, + #route { id=0; transporter=1; truck_type=0; start_region=1; end_region=2; start_date=1; end_date=10; cost=100 }, + #route { id=0; transporter=1; truck_type=0; start_region=1; end_region=3; start_date=2; end_date=10; cost=100 }, + #route { id=0; transporter=1; truck_type=0; start_region=1; end_region=4; start_date=3; end_date=10; cost=100 }, + + #route { id=0; transporter=2; truck_type=0; start_region=2; end_region=1; start_date=0; end_date=10; cost=100 }, + #route { id=0; transporter=2; truck_type=0; start_region=2; end_region=2; start_date=1; end_date=10; cost=100 }, + #route { id=0; transporter=2; truck_type=0; start_region=2; end_region=3; start_date=2; end_date=10; cost=100 }, + #route { id=0; transporter=2; truck_type=0; start_region=2; end_region=4; start_date=3; end_date=10; cost=100 }, + + #route { id=0; transporter=3; truck_type=0; start_region=3; end_region=1; start_date=0; end_date=10; cost=100 }, + #route { id=0; transporter=3; truck_type=0; start_region=3; end_region=2; start_date=1; end_date=10; cost=100 }, + #route { id=0; transporter=3; truck_type=0; start_region=3; end_region=3; start_date=2; end_date=10; cost=100 }, + #route { id=0; transporter=3; truck_type=0; start_region=3; end_region=4; start_date=3; end_date=10; cost=100 }, + + #route { id=0; transporter=4; truck_type=0; start_region=4; end_region=1; start_date=0; end_date=10; cost=100 }, + #route { id=0; transporter=4; truck_type=0; start_region=4; end_region=2; start_date=1; end_date=10; cost=100 }, + #route { id=0; transporter=4; truck_type=0; start_region=4; end_region=3; start_date=2; end_date=10; cost=100 }, + #route { id=0; transporter=4; truck_type=0; start_region=4; end_region=4; start_date=3; end_date=10; cost=100 }, ]) ] diff --git a/stdlib/examples/rx/test/RxTest.as b/stdlib/examples/rx/test/RxTest.as index 6a0b48ab153..1eb5024ec8b 100644 --- a/stdlib/examples/rx/test/RxTest.as +++ b/stdlib/examples/rx/test/RxTest.as @@ -70,7 +70,7 @@ func assertEqualEvent( func (observer : Rx.Observer.Type) : Rx.Disposable.Type { observer.send(#completed); observer.send(#next 1); - observer.send(#error (new { description = "Error"; })); + observer.send(#error { description = "Error"; }); observer.send(#completed); Rx.Disposable.empty(); } @@ -93,9 +93,9 @@ func assertEqualEvent( let sequence = Rx.Observable.init( func (observer : Rx.Observer.Type) : Rx.Disposable.Type { - observer.send(#error (new { description = "Error"; })); + observer.send(#error { description = "Error"; }); observer.send(#next 1); - observer.send(#error (new { description = "Another error"; })); + observer.send(#error { description = "Another error"; }); observer.send(#completed); Rx.Disposable.empty(); } @@ -104,5 +104,5 @@ func assertEqualEvent( let disposable = sequence.subscribe(observer); assert (events.len() == 1); - assertEqualEvent(events[0], #error (new { description = "Error"; })); + assertEqualEvent(events[0], #error { description = "Error"; }); }; diff --git a/stdlib/set.as b/stdlib/set.as index 826d6ab5b0b..b8247561ed4 100644 --- a/stdlib/set.as +++ b/stdlib/set.as @@ -29,12 +29,12 @@ public type Set = Trie.Trie; Trie.empty(); public func insert(s:Set, x:T, xh:Hash, eq:(T,T)->Bool) : Set = { - let (s2, _) = Trie.insert(s, new {key=x; hash=xh}, eq, ()); + let (s2, _) = Trie.insert(s, {key=x; hash=xh}, eq, ()); s2 }; public func remove(s:Set, x:T, xh:Hash, eq:(T,T)->Bool) : Set = { - let (s2, _) = Trie.remove(s, new {key=x; hash=xh}, eq); + let (s2, _) = Trie.remove(s, {key=x; hash=xh}, eq); s2 }; @@ -52,7 +52,7 @@ public type Set = Trie.Trie; }; public func mem(s:Set, x:T, xh:Hash, eq:(T,T)->Bool):Bool { - switch (Trie.find(s, new {key=x; hash=xh}, eq)) { + switch (Trie.find(s, {key=x; hash=xh}, eq)) { case null { false }; case (?_) { true }; } diff --git a/stdlib/trie.as b/stdlib/trie.as index f3293e1ba18..92f739ef3e3 100644 --- a/stdlib/trie.as +++ b/stdlib/trie.as @@ -173,11 +173,11 @@ public type Trie3D = Trie >; // rebuild either the left or right path with the inserted (k,v) pair if (not bit) { let (l, v_) = rec(n.left, bitpos+1); - (?(new {left=l; right=n.right; keyvals=null; }), v_) + (?{left=l; right=n.right; keyvals=null; }, v_) } else { let (r, v_) = rec(n.right, bitpos+1); - (?(new {left=n.left; right=r; keyvals=null; }), v_) + (?{left=n.left; right=r; keyvals=null; }, v_) } }; } @@ -190,7 +190,7 @@ public type Trie3D = Trie >; // a list/array of KV pairs in each leaf: let (kvs2, old_val) = AssocList.replace,V>(l.keyvals, k, key_eq, v); - (?(new{left=null; right=null; keyvals=kvs2}), old_val) + (?{left=null; right=null; keyvals=kvs2}, old_val) }; } } @@ -1015,7 +1015,7 @@ public type Trie3D = Trie >; func ((k:Key,v:V)):?(Key,W) = { switch (f(k.key,v)) { case (null) null; - case (?w) (?(new {key=k.key; hash=k.hash}, w)); + case (?w) (?({key=k.key; hash=k.hash}, w)); }} )) }; @@ -1127,7 +1127,7 @@ public type Trie3D = Trie >; // XXX: until AST-42: public func makeBin(l:Trie, r:Trie) : Trie { - ?(new {left=l; right=r; keyvals=null; }) + ?{left=l; right=r; keyvals=null; } }; // XXX: until AST-42: @@ -1145,7 +1145,7 @@ public type Trie3D = Trie >; // XXX: until AST-42: public func makeLeaf(kvs:AssocList,V>) : Trie { - ?(new {left=null; right=null; keyvals=kvs }) + ?{left=null; right=null; keyvals=kvs } }; // XXX: until AST-42: @@ -1223,16 +1223,16 @@ public type Trie3D = Trie >; let path = rec(bitpos+1); let bit = Hash.getHashBit(k.hash, bitpos); if (not bit) { - ?(new {left=path; right=null; keyvals=null}) + ?{left=path; right=null; keyvals=null} } else { - ?(new {left=null; right=path; keyvals=null}) + ?{left=null; right=path; keyvals=null} } } else { // create new leaf for (k,v) pair, if the value is non-null: switch ov { - case null { ?(new {left=null; right=null; keyvals=null }) }; - case (?v) { ?(new {left=null; right=null; keyvals=?((k,v),null) }) }; + case null { ?{left=null; right=null; keyvals=null } }; + case (?v) { ?{left=null; right=null; keyvals=?((k,v),null) } }; } } }; diff --git a/stdlib/trie2.as b/stdlib/trie2.as index 9b69581daf1..ad036dcb65e 100644 --- a/stdlib/trie2.as +++ b/stdlib/trie2.as @@ -235,7 +235,7 @@ public func count(t: Trie) : Nat = label profile_trie_count : Nat { public func branch(l:Trie, r:Trie) : Trie = label profile_trie_branch : Trie { let sum = count(l) + count(r); #branch( - new{ + { count=sum; left=l; right=r @@ -267,12 +267,12 @@ public func fromList(kvs:AssocList,V>, bitpos:Nat) : Trie = else if ( List.lenIsEqLessThan<(Key,V)>(kvs, MAX_LEAF_COUNT - 1) ) label profile_trie_fromList_end_validleaf : (Trie) { let len = List.len<(Key,V)>(kvs); - #leaf(new{count=len;keyvals=kvs}) + #leaf{count=len;keyvals=kvs} } else if ( bitpos >= 31 ) label profile_trie_fromList_end_bitposIs31 : (Trie) { let len = List.len<(Key,V)>(kvs); - #leaf(new{count=len;keyvals=kvs}) + #leaf{count=len;keyvals=kvs} } else /* too many keys for a leaf, so introduce a branch */ label profile_trie_fromList_branch : (Trie) { @@ -292,7 +292,7 @@ public func fromSizedList(kvc:?Nat, kvs:AssocList,V>, bitpos:Nat) : switch (List.lenClamp<(Key,V)>(kvs, MAX_LEAF_COUNT)) { case null () /* fall through to branch case. */; case (?len) { - return #leaf(new{count=len; keyvals=kvs}) + return #leaf{count=len; keyvals=kvs} }; } }; @@ -300,7 +300,7 @@ public func fromSizedList(kvc:?Nat, kvs:AssocList,V>, bitpos:Nat) : if ( c == 0 ) { return #empty } else if ( c <= MAX_LEAF_COUNT ) { - return #leaf(new{count=c; keyvals=kvs}) + return #leaf{count=c; keyvals=kvs} } else { /* fall through to branch case */ } @@ -310,9 +310,9 @@ public func fromSizedList(kvc:?Nat, kvs:AssocList,V>, bitpos:Nat) : if ( ls == 0 and rs == 0 ) { #empty } else if (rs == 0 and ls <= MAX_LEAF_COUNT) { - #leaf(new{count=ls; keyvals=l}) + #leaf{count=ls; keyvals=l} } else if (ls == 0 and rs <= MAX_LEAF_COUNT) { - #leaf(new{count=rs; keyvals=r}) + #leaf{count=rs; keyvals=r} } else { branch(rec(?ls, l, bitpos + 1), rec(?rs, r, bitpos + 1)) } @@ -867,7 +867,7 @@ public func disj( public func buildSeq(l:TrieBuild, r:TrieBuild) : TrieBuild = label profile_trie_buildSeq : TrieBuild { let sum = buildCount(l) + buildCount(r); - #seq(new { count = sum; left = l; right = r }) + #seq { count = sum; left = l; right = r } }; /** @@ -1205,7 +1205,7 @@ public func disj( func ((k:Key,v:V)):?(Key,W) = { switch (f(k.key,v)) { case (null) null; - case (?w) (?(new {key=k.key; hash=k.hash}, w)); + case (?w) (?({key=k.key; hash=k.hash}, w)); }} ), bitpos diff --git a/test/fail/issue36.as b/test/fail/issue36.as index f47935c9cb6..7d01db19262 100644 --- a/test/fail/issue36.as +++ b/test/fail/issue36.as @@ -3,8 +3,8 @@ type Z = { zap : Nat }; type B = { bar : (Int, Z) }; -let inner : Z = new { zap = 42 }; -let foo : B = new { bar = (25, inner) }; +let inner : Z = { zap = 42 }; +let foo : B = { bar = (25, inner) }; assert(foo.bar.0 == 25); diff --git a/test/fail/object-patterns.as b/test/fail/object-patterns.as index 2db0aeca32e..ffdbec94639 100644 --- a/test/fail/object-patterns.as +++ b/test/fail/object-patterns.as @@ -1,6 +1,6 @@ // Subtyping in patterns -let q : {a : Int; b : Nat} = new {a = -42; b = 25}; +let q : {a : Int; b : Nat} = {a = -42; b = 25}; func get_a () : Int = switch (q) { case {a = 25 : Nat} 1; // NOT OK: Nat cannot consume all Ints diff --git a/test/fail/objpat-duplicate.as b/test/fail/objpat-duplicate.as index e31294bbd9f..230da97a800 100644 --- a/test/fail/objpat-duplicate.as +++ b/test/fail/objpat-duplicate.as @@ -1,4 +1,4 @@ -let o = new {a = 1; b = 2}; +let o = {a = 1; b = 2}; switch o { case {a = x; b; a} {} diff --git a/test/fail/objpat-infer.as b/test/fail/objpat-infer.as index 9073e468939..e087588fa58 100644 --- a/test/fail/objpat-infer.as +++ b/test/fail/objpat-infer.as @@ -8,26 +8,26 @@ for ({} in [object {}].vals()) { print "hey" }; // infers -func foo ({}) : Int = 42; +func foo({}) : Int = 42; // infers -shared func baz (a : actor {}) : async Int { 42 }; +shared func baz(a : actor {}) : async Int { 42 }; // call it -ignore (foo (new {})); -ignore (foo (object {})); -ignore (foo (actor {})); +ignore (foo({})); +ignore (foo(object {})); +ignore (foo(actor {})); -let a = actor { public func bar ({}) : async Nat = async 25 }; +let a = actor { public func bar({}) : async Nat = async 25 }; ignore (foo a); -ignore (baz (new {})); -ignore (baz (object {})); -ignore (baz (actor {})); +ignore (baz({})); +ignore (baz(object {})); +ignore (baz(actor {})); -ignore (a.bar (new {})); -ignore (a.bar (object {})); -ignore (a.bar (actor {})); +ignore (a.bar({})); +ignore (a.bar(object {})); +ignore (a.bar(actor {})); diff --git a/test/fail/ok/const-var-field.tc.ok b/test/fail/ok/const-var-field.tc.ok index 980dbf67a3b..d9e34d9b401 100644 --- a/test/fail/ok/const-var-field.tc.ok +++ b/test/fail/ok/const-var-field.tc.ok @@ -1,4 +1,4 @@ const-var-field.as:1.21-1.48: type error, expression of type - {x : var Nat} + {var x : Nat} cannot produce expected type {x : Nat} diff --git a/test/fail/ok/objpat-infer.tc.ok b/test/fail/ok/objpat-infer.tc.ok index 2d3042e069b..4fd06cec2b0 100644 --- a/test/fail/ok/objpat-infer.tc.ok +++ b/test/fail/ok/objpat-infer.tc.ok @@ -1,6 +1,6 @@ objpat-infer.as:3.36-3.37: type error, object field a is not contained in expected type {} -objpat-infer.as:21.14-21.22: type error, expression of type +objpat-infer.as:21.13-21.21: type error, expression of type actor {} cannot produce expected type {} @@ -8,15 +8,15 @@ objpat-infer.as:24.13-24.14: type error, expression of type actor {bar : shared {} -> async Nat} cannot produce expected type {} -objpat-infer.as:27.14-27.20: type error, expression of type +objpat-infer.as:27.13-27.15: type error, expression of type {} cannot produce expected type actor {} -objpat-infer.as:28.14-28.23: type error, expression of type +objpat-infer.as:28.13-28.22: type error, expression of type {} cannot produce expected type actor {} -objpat-infer.as:33.16-33.24: type error, expression of type +objpat-infer.as:33.15-33.23: type error, expression of type actor {} cannot produce expected type {} diff --git a/test/fail/ok/var-const-field.tc.ok b/test/fail/ok/var-const-field.tc.ok index 6b0806b18da..34fa404da7c 100644 --- a/test/fail/ok/var-const-field.tc.ok +++ b/test/fail/ok/var-const-field.tc.ok @@ -1,4 +1,4 @@ -var-const-field.as:1.25-1.36: type error, expression of type +var-const-field.as:1.25-1.32: type error, expression of type {x : Nat} cannot produce expected type - {x : var Nat} + {var x : Nat} diff --git a/test/fail/var-const-field.as b/test/fail/var-const-field.as index 69c9fa88b49..ce6f4e3153f 100644 --- a/test/fail/var-const-field.as +++ b/test/fail/var-const-field.as @@ -1 +1 @@ -let o : {var x : Nat} = new {x = 0}; +let o : {var x : Nat} = {x = 0}; diff --git a/test/run-dfinity/chat.as b/test/run-dfinity/chat.as index 2f565f57724..d42f97793fb 100644 --- a/test/run-dfinity/chat.as +++ b/test/run-dfinity/chat.as @@ -19,7 +19,7 @@ actor class Server() = { }; public func subscribe(client : Client) : async Post { - let cs = new {head = client; var tail = clients}; + let cs = {head = client; var tail = clients}; clients := ?cs; return broadcast; }; diff --git a/test/run-dfinity/chatpp.as b/test/run-dfinity/chatpp.as index cbedc2115b6..8382528c667 100644 --- a/test/run-dfinity/chatpp.as +++ b/test/run-dfinity/chatpp.as @@ -29,9 +29,9 @@ actor class Server() = { }; public func subscribe(aclient : Client) : async Subscription { - let c = new {id = nextId; client = aclient; var revoked = false}; + let c = {id = nextId; client = aclient; var revoked = false}; nextId += 1; - let cs = new {head = c; var tail = clients}; + let cs = {head = c; var tail = clients}; clients := ?cs; return object { public shared func post(message : Text) { diff --git a/test/run-dfinity/data-params.as b/test/run-dfinity/data-params.as index c21161a79ae..115f6c700bd 100644 --- a/test/run-dfinity/data-params.as +++ b/test/run-dfinity/data-params.as @@ -100,8 +100,8 @@ a.incnested(7,(8,9)); a.incarray([10,11,12,13]); a.incopt(null); a.incopt(?14); -a.increcord(new {x = 15; y = 16}); -a.increcord(new {x = 17; y = 18; z = 19}); +a.increcord({x = 15; y = 16}); +a.increcord({x = 17; y = 18; z = 19}); a.incVariant(#foo 20); a.incVariant(#bar 20); a.printCounter(); diff --git a/test/run-dfinity/shared-object.as b/test/run-dfinity/shared-object.as index 1ae89ea1b23..b93c6b9a217 100644 --- a/test/run-dfinity/shared-object.as +++ b/test/run-dfinity/shared-object.as @@ -1,6 +1,6 @@ type Shob = { a : Int; b : { c : ?Nat } }; -let foo : Shob = new { a = 17; b = new { c = ?25 } }; +let foo : Shob = { a = 17; b = { c = ?25 } }; // check whether we can pattern match shared objects diff --git a/test/run-dfinity/transpose.as b/test/run-dfinity/transpose.as index a974c2da176..38c224426f0 100644 --- a/test/run-dfinity/transpose.as +++ b/test/run-dfinity/transpose.as @@ -1,6 +1,6 @@ actor foo { public func transpose (data : [(Int,Text)]) : async {ints: [Int]; txts: [Text]} { - return new { + return { ints = Array_tabulate(data.len(), func (i:Nat) : Int = (data[i].0)); txts = Array_tabulate(data.len(), func (i:Nat) : Text = (data[i].1)) } diff --git a/test/run/coverage.as b/test/run/coverage.as index 43e0d748f1f..7a0b297455d 100644 --- a/test/run/coverage.as +++ b/test/run/coverage.as @@ -34,13 +34,13 @@ func f() { switch (0, 0) { case (_, (6 or _)) {}; case _ {} }; switch (0, 0) { case (0, _) {}; case (_, 0) {} }; switch (0, 0) { case (0, _) {}; case (_, 0) {}; case _ {} }; - switch (new {a = 0; b = 0}) { case {a = _; b = _} {}; case {a = _; b = 6} {} }; - switch (new {a = 0; b = 0}) { case {} {}; case {b = 6} {} }; - switch (new {a = 0; b = 0}) { case {a = _; b = 6 or _} {}; case _ {} }; - switch (new {a = 0; b = 0}) { case {b = 6 or _} {}; case _ {} }; - switch (new {a = 0; b = 0}) { case {a = 0} {}; case {b = 0} {} }; - switch (new {a = 0; b = 0}) { case {a = 0} {}; case {b = 0} {}; case {} {} }; - switch (new {a = true}) { case {a = true} {}; case {a = false} {} }; + switch {a = 0; b = 0} { case {a = _; b = _} {}; case {a = _; b = 6} {} }; + switch {a = 0; b = 0} { case {} {}; case {b = 6} {} }; + switch {a = 0; b = 0} { case {a = _; b = 6 or _} {}; case _ {} }; + switch {a = 0; b = 0} { case {b = 6 or _} {}; case _ {} }; + switch {a = 0; b = 0} { case {a = 0} {}; case {b = 0} {} }; + switch {a = 0; b = 0} { case {a = 0} {}; case {b = 0} {}; case {} {} }; + switch {a = true} { case {a = true} {}; case {a = false} {} }; switch (#a 6 : {#a : Nat; #b : Nat}) { case (#a _) {}; case (#b _) {} }; switch (#a 6 : {#a : Nat; #b : Nat}) { case (#a _) {}; case (#b 6) {} }; switch (#a 6 : {#a : Nat; #b : Nat}) { case (#a _) {}; case (#a 5) {}; case (#b _) {} }; diff --git a/test/run/ir-pat-subtype.as b/test/run/ir-pat-subtype.as index 7b1fa3eb0b2..d2225d14948 100644 --- a/test/run/ir-pat-subtype.as +++ b/test/run/ir-pat-subtype.as @@ -1,7 +1,7 @@ type L = {a : {}}; type U = {}; -let l = new {a = new {}}; +let l = {a = {}}; func f(l : L) : U = switch l { case (u : U) u; @@ -45,19 +45,19 @@ func r1(rl : {a : L}) : {a : U} = switch rl { case (ru : {a : U}) ru; }; -let {a = {}} : {a : U} = r1(new {a = l}); +let {a = {}} : {a : U} = r1({a = l}); func r2(rl : {a : L}) : {a : U} = switch rl { - case ({a = u : U}) (new {a = u}); + case ({a = u : U}) ({a = u}); }; -let {a = {}} : {a : U} = r2(new {a = l}); +let {a = {}} : {a : U} = r2({a = l}); func r3(rl : {a : L}) : {} = switch rl { - case {} (new {}); + case {} ({}); }; -let {} : {} = r3(new {a = l}); +let {} : {} = r3({a = l}); // variants @@ -80,4 +80,4 @@ func a(l : {a : Int}):U = switch l { case (({a = 1} : {a : Int}) or (_ : U) ) l; }; -let {} = a(new {a = 2}); +let {} = a({a = 2}); diff --git a/test/run/issue129.as b/test/run/issue129.as index 8cdfde339f3..8c5e5091885 100644 --- a/test/run/issue129.as +++ b/test/run/issue129.as @@ -6,7 +6,7 @@ type Status = { }; let appendStatus = func (x : Status, y : Status) : Status { - new { + { failed_ = x.failed_ + y.failed_; passed_ = x.passed_ + y.passed_; pending_ = x.pending_ + y.pending_; diff --git a/test/run/mut-field-bound.as b/test/run/mut-field-bound.as index 100b94c0b3d..5390fd188e2 100644 --- a/test/run/mut-field-bound.as +++ b/test/run/mut-field-bound.as @@ -2,5 +2,5 @@ type Obj = {var x : Nat}; func foo(o : O) : Nat { o.x }; -let o : Obj = new {var x = 1 : Nat}; +let o : Obj = {var x = 1 : Nat}; assert(foo<{var x : Nat}>(o) == 1); diff --git a/test/run/nested-lexpr.as b/test/run/nested-lexpr.as index 3d7371a1b4b..bba38a5b22d 100644 --- a/test/run/nested-lexpr.as +++ b/test/run/nested-lexpr.as @@ -3,7 +3,7 @@ assert (a[0][0] == 1); a[0][0] := 2; assert (a[0][0] == 2); -let b : [{var x : Int}] = [new {var x = 1 : Int}]; +let b : [{var x : Int}] = [{var x = 1 : Int}]; assert (b[0].x == 1); b[0].x := 2; assert (b[0].x == 2); diff --git a/test/run/objects-order.as b/test/run/objects-order.as index d439d30787b..72b30332441 100644 --- a/test/run/objects-order.as +++ b/test/run/objects-order.as @@ -1,8 +1,8 @@ var x : Int = 0; assert (x == 0); -let _ = new {a = x := 1; b = x := 2}; +let _ = {a = x := 1; b = x := 2}; assert (x == 2); -let _ = new {b = x := 3; a = x := 4}; +let _ = {b = x := 3; a = x := 4}; assert (x == 4); diff --git a/test/run/objects1.as b/test/run/objects1.as index 8ec85aaa2c3..ef91c97ead3 100644 --- a/test/run/objects1.as +++ b/test/run/objects1.as @@ -2,7 +2,7 @@ let p = object {public let x = 3; let y = 2; public func get_y() : Int = y}; assert(p.x == 3); assert(p.get_y() == 2); -let o : {a : {}; b : Nat} = new {a = new {x = 0}; b = a.x}; +let o : {a : {}; b : Nat} = {a = {x = 0}; b = a.x}; let oo = object { type T = Int; @@ -27,7 +27,7 @@ assert(get_b () == 0); // subtyping in patterns -let q : {a : Int; b : Nat} = new {a = -42; b = 25}; +let q : {a : Int; b : Nat} = {a = -42; b = 25}; func get_a () : Int = switch (q) { case {a = 42; b} b; // OK: 42 is Int by subtyping @@ -38,7 +38,7 @@ assert (get_a () == -42); // subtyping and tuple patterns for comparison -let row : (Nat, Int, {c : Char; d : Text}) = (100, -42, new {c = 'C'; d = "D"}); +let row : (Nat, Int, {c : Char; d : Text}) = (100, -42, {c = 'C'; d = "D"}); func foo () : Int = switch row { case (a : Int, -42, {c} : {c : Char}) (word32ToNat(charToWord32 c)) // OK diff --git a/test/run/objects3.as b/test/run/objects3.as index 975a3e13a03..db62e75b1ad 100644 --- a/test/run/objects3.as +++ b/test/run/objects3.as @@ -1,5 +1,5 @@ type Q = {var this : ?Q; x : Nat}; -let q : Q = new {var this = null : ?Q; x = 4}; +let q : Q = {var this = null : ?Q; x = 4}; q.this := ?q; func unopt(x : ?T) : T = switch x { case (?y) y; case _ unopt(x) }; assert(unopt(unopt(q.this).this).x == 4); diff --git a/test/run/ok/coverage.run-ir.ok b/test/run/ok/coverage.run-ir.ok index 5c8074a5068..9749151ddcd 100644 --- a/test/run/ok/coverage.run-ir.ok +++ b/test/run/ok/coverage.run-ir.ok @@ -13,10 +13,10 @@ coverage.as:31.25-31.34: warning, this case is never reached coverage.as:32.43-32.44: warning, this pattern is never matched coverage.as:33.35-33.49: warning, this case is never reached coverage.as:34.42-34.51: warning, this case is never reached -coverage.as:37.57-37.79: warning, this case is never reached -coverage.as:38.45-38.60: warning, this case is never reached -coverage.as:39.62-39.71: warning, this case is never reached -coverage.as:40.55-40.64: warning, this case is never reached +coverage.as:37.51-37.73: warning, this case is never reached +coverage.as:38.39-38.54: warning, this case is never reached +coverage.as:39.56-39.65: warning, this case is never reached +coverage.as:40.49-40.58: warning, this case is never reached coverage.as:46.58-46.72: warning, this case is never reached coverage.as:61.22-61.31: warning, this case is never reached coverage.as:62.28-62.37: warning, this case is never reached @@ -71,7 +71,7 @@ coverage.as:35.3-35.51: warning, the cases in this switch over type (Nat, Nat) do not cover value (1 or 2 or _, 1 or 2 or _) -coverage.as:41.3-41.67: warning, the cases in this switch over type +coverage.as:41.3-41.61: warning, the cases in this switch over type {a : Nat; b : Nat} do not cover value {a = 1 or 2 or _; b = 1 or 2 or _) diff --git a/test/run/ok/coverage.run-low.ok b/test/run/ok/coverage.run-low.ok index 5c8074a5068..9749151ddcd 100644 --- a/test/run/ok/coverage.run-low.ok +++ b/test/run/ok/coverage.run-low.ok @@ -13,10 +13,10 @@ coverage.as:31.25-31.34: warning, this case is never reached coverage.as:32.43-32.44: warning, this pattern is never matched coverage.as:33.35-33.49: warning, this case is never reached coverage.as:34.42-34.51: warning, this case is never reached -coverage.as:37.57-37.79: warning, this case is never reached -coverage.as:38.45-38.60: warning, this case is never reached -coverage.as:39.62-39.71: warning, this case is never reached -coverage.as:40.55-40.64: warning, this case is never reached +coverage.as:37.51-37.73: warning, this case is never reached +coverage.as:38.39-38.54: warning, this case is never reached +coverage.as:39.56-39.65: warning, this case is never reached +coverage.as:40.49-40.58: warning, this case is never reached coverage.as:46.58-46.72: warning, this case is never reached coverage.as:61.22-61.31: warning, this case is never reached coverage.as:62.28-62.37: warning, this case is never reached @@ -71,7 +71,7 @@ coverage.as:35.3-35.51: warning, the cases in this switch over type (Nat, Nat) do not cover value (1 or 2 or _, 1 or 2 or _) -coverage.as:41.3-41.67: warning, the cases in this switch over type +coverage.as:41.3-41.61: warning, the cases in this switch over type {a : Nat; b : Nat} do not cover value {a = 1 or 2 or _; b = 1 or 2 or _) diff --git a/test/run/ok/coverage.run.ok b/test/run/ok/coverage.run.ok index 5c8074a5068..9749151ddcd 100644 --- a/test/run/ok/coverage.run.ok +++ b/test/run/ok/coverage.run.ok @@ -13,10 +13,10 @@ coverage.as:31.25-31.34: warning, this case is never reached coverage.as:32.43-32.44: warning, this pattern is never matched coverage.as:33.35-33.49: warning, this case is never reached coverage.as:34.42-34.51: warning, this case is never reached -coverage.as:37.57-37.79: warning, this case is never reached -coverage.as:38.45-38.60: warning, this case is never reached -coverage.as:39.62-39.71: warning, this case is never reached -coverage.as:40.55-40.64: warning, this case is never reached +coverage.as:37.51-37.73: warning, this case is never reached +coverage.as:38.39-38.54: warning, this case is never reached +coverage.as:39.56-39.65: warning, this case is never reached +coverage.as:40.49-40.58: warning, this case is never reached coverage.as:46.58-46.72: warning, this case is never reached coverage.as:61.22-61.31: warning, this case is never reached coverage.as:62.28-62.37: warning, this case is never reached @@ -71,7 +71,7 @@ coverage.as:35.3-35.51: warning, the cases in this switch over type (Nat, Nat) do not cover value (1 or 2 or _, 1 or 2 or _) -coverage.as:41.3-41.67: warning, the cases in this switch over type +coverage.as:41.3-41.61: warning, the cases in this switch over type {a : Nat; b : Nat} do not cover value {a = 1 or 2 or _; b = 1 or 2 or _) diff --git a/test/run/ok/coverage.tc.ok b/test/run/ok/coverage.tc.ok index 5c8074a5068..9749151ddcd 100644 --- a/test/run/ok/coverage.tc.ok +++ b/test/run/ok/coverage.tc.ok @@ -13,10 +13,10 @@ coverage.as:31.25-31.34: warning, this case is never reached coverage.as:32.43-32.44: warning, this pattern is never matched coverage.as:33.35-33.49: warning, this case is never reached coverage.as:34.42-34.51: warning, this case is never reached -coverage.as:37.57-37.79: warning, this case is never reached -coverage.as:38.45-38.60: warning, this case is never reached -coverage.as:39.62-39.71: warning, this case is never reached -coverage.as:40.55-40.64: warning, this case is never reached +coverage.as:37.51-37.73: warning, this case is never reached +coverage.as:38.39-38.54: warning, this case is never reached +coverage.as:39.56-39.65: warning, this case is never reached +coverage.as:40.49-40.58: warning, this case is never reached coverage.as:46.58-46.72: warning, this case is never reached coverage.as:61.22-61.31: warning, this case is never reached coverage.as:62.28-62.37: warning, this case is never reached @@ -71,7 +71,7 @@ coverage.as:35.3-35.51: warning, the cases in this switch over type (Nat, Nat) do not cover value (1 or 2 or _, 1 or 2 or _) -coverage.as:41.3-41.67: warning, the cases in this switch over type +coverage.as:41.3-41.61: warning, the cases in this switch over type {a : Nat; b : Nat} do not cover value {a = 1 or 2 or _; b = 1 or 2 or _) diff --git a/test/run/ok/coverage.wasm.stderr.ok b/test/run/ok/coverage.wasm.stderr.ok index 5c8074a5068..9749151ddcd 100644 --- a/test/run/ok/coverage.wasm.stderr.ok +++ b/test/run/ok/coverage.wasm.stderr.ok @@ -13,10 +13,10 @@ coverage.as:31.25-31.34: warning, this case is never reached coverage.as:32.43-32.44: warning, this pattern is never matched coverage.as:33.35-33.49: warning, this case is never reached coverage.as:34.42-34.51: warning, this case is never reached -coverage.as:37.57-37.79: warning, this case is never reached -coverage.as:38.45-38.60: warning, this case is never reached -coverage.as:39.62-39.71: warning, this case is never reached -coverage.as:40.55-40.64: warning, this case is never reached +coverage.as:37.51-37.73: warning, this case is never reached +coverage.as:38.39-38.54: warning, this case is never reached +coverage.as:39.56-39.65: warning, this case is never reached +coverage.as:40.49-40.58: warning, this case is never reached coverage.as:46.58-46.72: warning, this case is never reached coverage.as:61.22-61.31: warning, this case is never reached coverage.as:62.28-62.37: warning, this case is never reached @@ -71,7 +71,7 @@ coverage.as:35.3-35.51: warning, the cases in this switch over type (Nat, Nat) do not cover value (1 or 2 or _, 1 or 2 or _) -coverage.as:41.3-41.67: warning, the cases in this switch over type +coverage.as:41.3-41.61: warning, the cases in this switch over type {a : Nat; b : Nat} do not cover value {a = 1 or 2 or _; b = 1 or 2 or _) diff --git a/test/run/ok/type-inference.run-ir.ok b/test/run/ok/type-inference.run-ir.ok index 2de3eceb85b..2e8cbb9f0af 100644 --- a/test/run/ok/type-inference.run-ir.ok +++ b/test/run/ok/type-inference.run-ir.ok @@ -13,7 +13,7 @@ true produces Nat false produces Float -type-inference.as:6.9-6.33: warning, this if has type Any because branches have inconsistent types, +type-inference.as:6.9-6.29: warning, this if has type Any because branches have inconsistent types, true produces () false produces diff --git a/test/run/ok/type-inference.run-low.ok b/test/run/ok/type-inference.run-low.ok index 2de3eceb85b..2e8cbb9f0af 100644 --- a/test/run/ok/type-inference.run-low.ok +++ b/test/run/ok/type-inference.run-low.ok @@ -13,7 +13,7 @@ true produces Nat false produces Float -type-inference.as:6.9-6.33: warning, this if has type Any because branches have inconsistent types, +type-inference.as:6.9-6.29: warning, this if has type Any because branches have inconsistent types, true produces () false produces diff --git a/test/run/ok/type-inference.run.ok b/test/run/ok/type-inference.run.ok index 2de3eceb85b..2e8cbb9f0af 100644 --- a/test/run/ok/type-inference.run.ok +++ b/test/run/ok/type-inference.run.ok @@ -13,7 +13,7 @@ true produces Nat false produces Float -type-inference.as:6.9-6.33: warning, this if has type Any because branches have inconsistent types, +type-inference.as:6.9-6.29: warning, this if has type Any because branches have inconsistent types, true produces () false produces diff --git a/test/run/ok/type-inference.tc.ok b/test/run/ok/type-inference.tc.ok index 2de3eceb85b..2e8cbb9f0af 100644 --- a/test/run/ok/type-inference.tc.ok +++ b/test/run/ok/type-inference.tc.ok @@ -13,7 +13,7 @@ true produces Nat false produces Float -type-inference.as:6.9-6.33: warning, this if has type Any because branches have inconsistent types, +type-inference.as:6.9-6.29: warning, this if has type Any because branches have inconsistent types, true produces () false produces diff --git a/test/run/ok/type-inference.wasm.stderr.ok b/test/run/ok/type-inference.wasm.stderr.ok index 73cc0a6f37b..8ce0ed1f0e7 100644 --- a/test/run/ok/type-inference.wasm.stderr.ok +++ b/test/run/ok/type-inference.wasm.stderr.ok @@ -14,7 +14,7 @@ true produces Nat false produces Float -type-inference.as:6.9-6.33: warning, this if has type Any because branches have inconsistent types, +type-inference.as:6.9-6.29: warning, this if has type Any because branches have inconsistent types, true produces () false produces diff --git a/test/run/prelude.as b/test/run/prelude.as index 294695bc283..0031a6e72d6 100644 --- a/test/run/prelude.as +++ b/test/run/prelude.as @@ -1,5 +1,5 @@ //ignore(3); -ignore(new {}); +ignore({}); /* assert(abs(-3) == 3); diff --git a/test/run/records.as b/test/run/records.as index b57b6e3bfdd..2b41a8fe249 100644 --- a/test/run/records.as +++ b/test/run/records.as @@ -1,4 +1,4 @@ -let rec1 = new {a = 1; b = 2}; +let rec1 = {a = 1; b = 2}; assert(rec1.a == 1); assert(rec1.b == 2); @@ -8,7 +8,7 @@ assert(x == 1); assert(y == 2); */ -let rec2 = new {b = 3; c = 4; d = rec1}; +let rec2 = {b = 3; c = 4; d = rec1}; assert(rec2.b == 3); assert(rec2.c == 4); diff --git a/test/run/switch.as b/test/run/switch.as index 5442a665a26..057ff370079 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 (?{}) { case null 0; case x 1; }; assert (x5 == 1); -let oo : ?{} = ?(new {}); +let oo : ?{} = ?{}; let x6 = switch oo { case null 0; case _ 1; diff --git a/test/run/type-inference.as b/test/run/type-inference.as index aaf9f8b57cc..26f434967a0 100644 --- a/test/run/type-inference.as +++ b/test/run/type-inference.as @@ -3,8 +3,8 @@ let _ = if true true else 5; let _ = if true true else [var 5]; let _ = if true 5 else 5.1; -let _ = if true {} else (new {}); -let _ = if true (new {x = 5}) else (new {var x = 5}); +let _ = if true {} else ({}); +let _ = if true ({x = 5}) else ({var x = 5}); let _ = if true 1 else (-1); // ok let _ = if true true else (5 : Any); // ok @@ -25,7 +25,7 @@ let _ = [true, [var 5]]; let x = { type T = {}; - let o : T = new {}; + let o : T = {}; o; }; diff --git a/test/run/type-lub.as b/test/run/type-lub.as index e52f1d98fcb..49e2bf6c940 100644 --- a/test/run/type-lub.as +++ b/test/run/type-lub.as @@ -1,8 +1,8 @@ let opts = [null, ?42, ?-25]; let nulls = [null, null]; -let incompatible_objs = [new {a = 42}, new {b = 42}]; -let objs = [new {a = 42}, new {b = 42; a = 1}, new {a = -25}]; +let incompatible_objs = [{a = 42}, {b = 42}]; +let objs = [{a = 42}, {b = 42; a = 1}, {a = -25}]; let tups = [(12, -1), (-42, 25)]; let tup1s = [(-1,), 25]; From 3bb455f0ca5cc355893d89556fb759dc297b0fb1 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Wed, 31 Jul 2019 15:06:42 -0700 Subject: [PATCH 0326/1176] AS-to-IDL type mapping --- src/as_idl/as_to_idl.ml | 130 ++++++++++++++++++++++++++++++++++++++ src/as_idl/dune | 4 ++ src/exes/asc.ml | 8 ++- src/idllib/arrange_idl.ml | 28 ++++++-- src/idllib/compile_js.ml | 3 +- src/idllib/parser.mly | 2 +- src/idllib/syntax.ml | 3 +- src/pipeline/dune | 1 + src/pipeline/pipeline.ml | 6 ++ src/pipeline/pipeline.mli | 2 + 10 files changed, 175 insertions(+), 12 deletions(-) create mode 100644 src/as_idl/as_to_idl.ml create mode 100644 src/as_idl/dune diff --git a/src/as_idl/as_to_idl.ml b/src/as_idl/as_to_idl.ml new file mode 100644 index 00000000000..fc9549e74c2 --- /dev/null +++ b/src/as_idl/as_to_idl.ml @@ -0,0 +1,130 @@ +open As_types +open As_types.Type +open Source +open Printf +module I = Idllib.Syntax + +type label = Nat of Lib.Uint32.t | Id of string + +let dec_set = ref ConSet.empty + +let unescape lab : label = + let len = String.length lab in + try if lab.[len-1] = '_' then begin + if lab.[0] = '_' then + Nat (Lib.Uint32.of_string lab) + else Id (String.sub lab 0 (len-1)) + end else Id lab + with _ -> + if len >= 2 && lab.[len-1] = '_' + then Id (String.sub lab 0 (len-1)) + else Id lab + +let prim p = + match p with + | Null -> I.Null + | Bool -> I.Bool + | Nat -> I.Nat + | Nat8 -> I.Nat8 + | Nat16 -> I.Nat16 + | Nat32 -> I.Nat32 + | Nat64 -> I.Nat64 + | Int -> I.Int + | Int8 -> I.Int8 + | Int16 -> I.Int16 + | Int32 -> I.Int32 + | Int64 -> I.Int64 + | Word8 -> I.Nat8 + | Word16 -> I.Nat16 + | Word32 -> I.Nat32 + | Word64 -> I.Nat64 + | Float -> I.Float64 + | Char -> I.Nat32 + | Text -> I.Text + +let rec typ env t = + (match t with + | Pre -> assert false + | Any -> I.PrimT I.Reserved + | Non -> I.PrimT I.Empty + | Prim p -> I.PrimT (prim p) + | Var (s, i) -> assert false + | Con (c, ts) -> + (* TODO monomorphization *) + let id = + (if List.length ts = 0 then string_of_con c + else sprintf "%s<%s>" (string_of_con c) (String.concat ", " (List.map string_of_typ ts))) @@ no_region in + dec_set := ConSet.add c !dec_set; + I.VarT id + | Tup ts -> + I.RecordT (tuple env ts) + | Array t -> I.VecT (typ env t) + | Obj (Object, fs) -> + I.RecordT (List.map (field env) fs) + | Obj (Actor, fs) -> I.ServT (List.map (meth env) fs) + | Obj (Module, _) -> assert false + | Variant fs -> + I.VariantT (List.map (field env) fs) + | Typ c -> assert false + | Func (Shared, c, [], ts1, ts2) -> + let fs1 = tuple env ts1 in + (match ts2 with + | [] when c = Returns -> I.FuncT ([I.Oneway @@ no_region], fs1, []) + | [Async t] when c = Promises -> I.FuncT ([], fs1, tuple env [t]) + | _ -> assert false) + | Func _ -> assert false + | Opt t -> I.OptT (typ env t) + | Async t -> assert false + | Mut t -> assert false + | Serialized t -> assert false + ) @@ no_region +and field env {lab; typ=t} = + match unescape lab with + | Nat nat -> + let name = Lib.Uint32.to_string nat @@ no_region in + I.{id = nat; name = name; typ = typ env t} @@ no_region + | Id id -> + let name = id @@ no_region in + let id = Idllib.IdlHash.idl_hash id in + I.{id = id; name = name; typ = typ env t} @@ no_region +and tuple env ts = + List.mapi (fun i x -> + let id = Lib.Uint32.of_int i in + let name = Lib.Uint32.to_string id @@ no_region in + I.{id = id; name = name; typ = typ env x} @@ no_region + ) ts +and meth env {lab; typ=t} = + match unescape lab with + | Nat nat -> I.{var = Lib.Uint32.to_string nat @@ no_region; meth = typ env t} @@ no_region + | Id id -> I.{var = id @@ no_region; meth = typ env t} @@ no_region + +let actor env = + let set = + ConSet.filter (fun c -> + match Con.kind c with + | Def ([], Obj (Actor, fs)) -> true + | _ -> false + ) env.Scope.con_env in + assert (ConSet.cardinal set <= 1); + match ConSet.choose_opt set with + | None -> None + | Some c -> + (match Con.kind c with + | Def (_, Obj (Actor, fs)) -> + let t = I.ServT (List.map (meth env) fs) @@ no_region in + Some (I.ActorD (Con.to_string c @@ no_region, t) @@ no_region) + | _ -> assert false) + +let decs env set = + ConSet.fold (fun c list -> + match Con.kind c with + | Def ([], t) -> (I.TypD (Con.to_string c @@ no_region, typ env t) @@ no_region) :: list + | _ -> list) + set [] + +let prog env : I.prog = + let actor = actor env in + let decs = decs env !dec_set in + let it = I.{decs = decs; actor = actor} in + {it = it; at = no_region; note = ""} + diff --git a/src/as_idl/dune b/src/as_idl/dune new file mode 100644 index 00000000000..a6e1415a4c1 --- /dev/null +++ b/src/as_idl/dune @@ -0,0 +1,4 @@ +(library + (name as_idl) + (libraries lib idllib lang_utils as_types) +) diff --git a/src/exes/asc.ml b/src/exes/asc.ml index 914c7e0a12f..f4b377615a2 100644 --- a/src/exes/asc.ml +++ b/src/exes/asc.ml @@ -10,7 +10,7 @@ let usage = "Usage: " ^ name ^ " [option] [file ...]" (* Argument handling *) -type mode = Default | Check | Compile | Run | Interact +type mode = Default | Check | Compile | Run | Interact | Idl let mode = ref Default let args = ref [] @@ -34,6 +34,7 @@ let argspec = Arg.align "-r", Arg.Unit (set_mode Run), " interpret programs"; "-i", Arg.Unit (set_mode Interact), " run interactive REPL (implies -r)"; "--check", Arg.Unit (set_mode Check), " type-check only"; + "--idl", Arg.Unit (set_mode Idl), " generate IDL spec"; "-v", Arg.Set Pipeline.Flags.verbose, " verbose output"; "-p", Arg.Set_int Pipeline.Flags.print_depth, " set print depth"; "-o", Arg.Set_string out_file, " output file"; @@ -94,7 +95,10 @@ let process_files files : unit = printf "%s\n%!" banner; exit_on_none (Pipeline.run_files_and_stdin files) | Check -> - Diag.run (Pipeline.check_files files) + Diag.run (Pipeline.check_files files) + | Idl -> + let idl_ast = Diag.run (Pipeline.generate_idl files) in + Printf.printf "%s" (Idllib.Arrange_idl.string_of_prog idl_ast) | Compile -> if !out_file = "" then begin match files with diff --git a/src/idllib/arrange_idl.ml b/src/idllib/arrange_idl.ml index 39cb25eef1c..ba19f7af348 100644 --- a/src/idllib/arrange_idl.ml +++ b/src/idllib/arrange_idl.ml @@ -19,12 +19,13 @@ let string_of_prim p = | Bool -> "bool" | Text -> "text" | Null -> "null" - | Reserved -> "reserved" + | Reserved -> "reserved" + | Empty -> "empty" let string_of_mode m = match m.it with - | Oneway -> "oneway" - | Pure -> "pure" + | Oneway -> " oneway" + | Pure -> " pure" let ($$) head inner = Node (head, inner) @@ -74,19 +75,32 @@ let string_of_list f sep list = String.concat sep (List.map f list) let rec string_of_typ t = match t.it with - | VarT id -> sprintf "var %s" id.it + | VarT id -> sprintf "%s" id.it | PrimT s -> string_of_prim s | FuncT (ms,s,t) -> - sprintf "(%s) -> (%s) %s" (string_of_list string_of_field ", " s) (string_of_list string_of_field ", " t) (string_of_list string_of_mode " " ms) + sprintf "(%s) -> (%s)%s" (string_of_list string_of_field ", " s) (string_of_list string_of_field ", " t) (string_of_list string_of_mode " " ms) | OptT t -> "opt " ^ string_of_typ t | VecT t -> "vec " ^ string_of_typ t | RecordT fs -> sprintf "{%s}" (string_of_list string_of_field "; " fs) | VariantT fs -> sprintf "variant {%s}" (string_of_list string_of_field "; " fs) - | ServT ms -> sprintf "service {%s}" (string_of_list string_of_meth "; " ms) + | ServT ms -> sprintf "service {%s}" (string_of_list string_of_meth "" ms) | PreT -> "Pre" and string_of_field f = sprintf "%s : %s" f.it.name.it (string_of_typ f.it.typ) and string_of_meth m = - sprintf "%s : %s" m.it.var.it (string_of_typ m.it.meth) + sprintf "%s : %s;\n" m.it.var.it (string_of_typ m.it.meth) +let string_of_dec d = + match d.it with + | TypD (id, typ) -> sprintf "type %s = %s;\n" id.it (string_of_typ typ) + | ImportD (f, fp) -> sprintf "import \"%s\";\n" f + +let string_of_actor a = + match a with + | None -> "" + | Some {it = ActorD (id, {it=ServT ms; _}); _} -> sprintf "service %s {\n%s}" id.it (string_of_list string_of_meth "" ms) + | Some _ -> assert false + +let string_of_prog prog = + sprintf "%s%s\n" (string_of_list string_of_dec "" prog.it.decs) (string_of_actor prog.it.actor) diff --git a/src/idllib/compile_js.ml b/src/idllib/compile_js.ml index 4e774298869..ff0f5d8ed34 100644 --- a/src/idllib/compile_js.ml +++ b/src/idllib/compile_js.ml @@ -90,7 +90,8 @@ let pp_prim p = | Text -> "Text" | Null -> "Unit" | Reserved -> "None" - + | Empty -> "Empty" + let rec concat ppf f sep list = match list with | [] -> () diff --git a/src/idllib/parser.mly b/src/idllib/parser.mly index 4080faaee7d..d72ff1bc8e6 100644 --- a/src/idllib/parser.mly +++ b/src/idllib/parser.mly @@ -27,7 +27,7 @@ let _anon sort at = "anon-" ^ sort ^ "-" ^ string_of_pos at.left let prim_typs = ["nat", Nat; "nat8", Nat8; "nat16", Nat16; "nat32", Nat32; "nat64", Nat64; "int", Int; "int8", Int8; "int16", Int16; "int32", Int32; "int64", Int64; "float32", Float32; "float64", Float64; "bool", Bool; "text", Text; - "null", Null; "reserved", Reserved] + "null", Null; "reserved", Reserved; "empty", Empty] let is_prim_typs t = List.assoc_opt t prim_typs let func_modes = ["oneway", Oneway; "pure", Pure] diff --git a/src/idllib/syntax.ml b/src/idllib/syntax.ml index f43dd2e89c1..afbfd4cd3e3 100644 --- a/src/idllib/syntax.ml +++ b/src/idllib/syntax.ml @@ -21,7 +21,8 @@ type prim = | Bool | Text | Null - | Reserved + | Reserved + | Empty type func_mode = func_mode' Source.phrase and func_mode' = Oneway | Pure diff --git a/src/pipeline/dune b/src/pipeline/dune index 68bd990da2f..c3970d24518 100644 --- a/src/pipeline/dune +++ b/src/pipeline/dune @@ -7,6 +7,7 @@ as_types as_values as_frontend + as_idl as_interpreter lowering wasm_exts diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index c49daac6186..dc701ad05bc 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -345,6 +345,12 @@ let check_files files : check_result = let check_string s name : check_result = Diag.map ignore (load_decl (parse_string s name) initial_stat_env) +(* Generate IDL *) + +let generate_idl files : Idllib.Syntax.prog Diag.result = + Diag.bind (load_progs (parse_files files) initial_stat_env) + (fun (libraries, progs, senv) -> + Diag.return (As_idl.As_to_idl.prog senv)) (* Running *) diff --git a/src/pipeline/pipeline.mli b/src/pipeline/pipeline.mli index c4af0490e3f..38330b9ba9c 100644 --- a/src/pipeline/pipeline.mli +++ b/src/pipeline/pipeline.mli @@ -23,6 +23,8 @@ end val check_files : string list -> unit Diag.result val check_string : string -> string -> unit Diag.result +val generate_idl : string list -> Idllib.Syntax.prog Diag.result + val initial_stat_env : Scope.scope val chase_imports : Scope.scope -> Resolve_import.S.t -> (Syntax.libraries * Scope.scope) Diag.result From 9881595461fcf23ca6d77a09e5d210bf7266181c Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Wed, 31 Jul 2019 15:50:48 -0700 Subject: [PATCH 0327/1176] fix CI --- test/idl/ok/func.tc.ok | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/idl/ok/func.tc.ok b/test/idl/ok/func.tc.ok index aba71bbb729..89340ff03c8 100644 --- a/test/idl/ok/func.tc.ok +++ b/test/idl/ok/func.tc.ok @@ -1,2 +1,2 @@ func.did:10.3-10.8: type error, p is a non-function type - var o + o From 6bb14c18a552899bbec2696587545d75abf29bb7 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Thu, 1 Aug 2019 17:09:22 +0200 Subject: [PATCH 0328/1176] Allow type annotations on classes (#605) --- guide/guide.md | 4 +- src/as_def/arrange.ml | 8 +- src/as_def/syntax.ml | 2 +- src/as_frontend/definedness.ml | 2 +- src/as_frontend/parser.mly | 37 +++++---- src/as_frontend/typing.ml | 134 +++++++++++++++++--------------- src/as_interpreter/interpret.ml | 4 +- src/as_types/call_conv.ml | 2 +- src/as_types/type.ml | 72 +++++++++-------- src/lowering/desugar.ml | 6 +- src/pipeline/resolve_import.ml | 2 +- test/fail/class.as | 54 +++++++++++++ test/fail/ok/class.tc.ok | 18 +++++ 13 files changed, 219 insertions(+), 126 deletions(-) create mode 100644 test/fail/class.as create mode 100644 test/fail/ok/class.tc.ok diff --git a/guide/guide.md b/guide/guide.md index f7ed1da9561..e29569bbca7 100644 --- a/guide/guide.md +++ b/guide/guide.md @@ -1198,7 +1198,7 @@ matching ``, if it succeeds, or the result of matching ``, if the fi (object|module|actor) ? =? { ;* } object shared? func ? ? (: )? =? function type ? = type - obj_sort? class ? =? { ;* }` class + obj_sort? class ? (: )? =? { ;* }` class ``` ```bnf @@ -1305,7 +1305,7 @@ Named function definitions are recursive. ## Class declarations -The declaration `obj_sort? class ? =? ? { ;* }` is sugar for pair of a +The declaration `obj_sort? class ? (: )? =? ? { ;* }` is sugar for pair of a a type and function declaration: ```bnf diff --git a/src/as_def/arrange.ml b/src/as_def/arrange.ml index 48d28c9e7e1..f0174b2efb4 100644 --- a/src/as_def/arrange.ml +++ b/src/as_def/arrange.ml @@ -150,7 +150,11 @@ and dec d = match d.it with | VarD (x, e) -> "VarD" $$ [id x; exp e] | TypD (x, tp, t) -> "TypD" $$ [id x] @ List.map typ_bind tp @ [typ t] - | ClassD (x, tp, s, p, i', efs) -> - "ClassD" $$ id x :: List.map typ_bind tp @ [obj_sort s; pat p; id i'] @ List.map exp_field efs + | ClassD (x, tp, p, rt, s, i', efs) -> + "ClassD" $$ id x :: List.map typ_bind tp @ [ + pat p; + (match rt with None -> Atom "_" | Some t -> typ t); + obj_sort s; id i' + ] @ List.map exp_field efs and prog prog = "BlockE" $$ List.map dec prog.it diff --git a/src/as_def/syntax.ml b/src/as_def/syntax.ml index 3a055d9c4e1..cbfdc14aafe 100644 --- a/src/as_def/syntax.ml +++ b/src/as_def/syntax.ml @@ -168,7 +168,7 @@ and dec' = | VarD of id * exp (* mutable *) | TypD of typ_id * typ_bind list * typ (* type *) | ClassD of (* class *) - typ_id * typ_bind list * obj_sort * pat * id * exp_field list + typ_id * typ_bind list * pat * typ option * obj_sort * id * exp_field list (* Program *) diff --git a/src/as_frontend/definedness.ml b/src/as_frontend/definedness.ml index 246e13662a5..aa02e054640 100644 --- a/src/as_frontend/definedness.ml +++ b/src/as_frontend/definedness.ml @@ -155,7 +155,7 @@ and dec msgs d = match d.it with | LetD (p, e) -> pat msgs p +++ exp msgs e | VarD (i, e) -> (M.empty, S.singleton i.it) +++ exp msgs e | TypD (i, tp, t) -> (M.empty, S.empty) - | ClassD (i, tp, s, p, i', efs) -> + | ClassD (i, tp, p, t, s, i', efs) -> (M.empty, S.singleton i.it) +++ delayify (exp_fields msgs efs /// pat msgs p // i'.it) and decs msgs decs : f = diff --git a/src/as_frontend/parser.mly b/src/as_frontend/parser.mly index ccf19848185..ad1d61546f2 100644 --- a/src/as_frontend/parser.mly +++ b/src/as_frontend/parser.mly @@ -591,14 +591,26 @@ dec_nonvar : let efs' = if s.it = Type.Actor then List.map share_expfield efs else efs in let_or_exp named x (ObjE(s, efs')) (at $sloc) } - | s=func_sort_opt FUNC xf=id_opt fe=func_exp - { let named, x = xf "func" $sloc in - let_or_exp named x (fe s x.it).it (at $sloc) } - | s=obj_sort_opt CLASS xf=typ_id_opt tps=typ_params_opt p=pat_param xefs=class_body - { let x, efs = xefs in + | s=func_sort_opt FUNC xf=id_opt + tps=typ_params_opt p=pat_param t=return_typ? fb=func_body + { (* This is a hack to support local func declarations that return a computed async. + These should be defined using RHS syntax EQ e to avoid the implicit AsyncE introduction + around bodies declared as blocks *) + let e = match fb with + | (false, e) -> e (* body declared as EQ e *) + | (true, e) -> (* body declared as immediate block *) + match t with + | Some {it = AsyncT _; _} -> AsyncE(e) @? e.at + | _ -> e + in + let named, x = xf "func" $sloc in + let_or_exp named x (FuncE(x.it, s, tps, p, t, e)) (at $sloc) } + | s=obj_sort_opt CLASS xf=typ_id_opt + tps=typ_params_opt p=pat_param t=return_typ? cb=class_body + { let x, efs = cb in let efs' = if s.it = Type.Actor then List.map share_expfield efs else efs - in ClassD(xf "class" $sloc, tps, s, p, x, efs') @? at $sloc } + in ClassD(xf "class" $sloc, tps, p, t, s, x, efs') @? at $sloc } | IMPORT xf=id_opt EQ? f=TEXT { let named, x = xf "import" $sloc in let_or_exp named x (ImportE (f, ref "")) (at $sloc) } @@ -623,19 +635,6 @@ dec_list_unamb : (* does not overlap with exp_field_list_unamb *) | d=dec_var semicolon ds=dec_list_unamb { d::ds } -func_exp : - | tps=typ_params_opt p=pat_param t=return_typ? fb=func_body - { (* This is a hack to support local func declarations that return a computed async. - These should be defined using RHS syntax EQ e to avoid the implicit AsyncE introduction - around bodies declared as blocks *) - let e = match fb with - | (false, e) -> e (* body declared as EQ e *) - | (true, e) -> (* body declared as immediate block *) - match t with - | Some {it = AsyncT _; _} -> AsyncE(e) @? e.at - | _ -> e - in fun s x -> FuncE(x, s, tps, p, t, e) @? at $sloc } - func_body : | EQ e=exp(bl) { (false, e) } | e=exp_block { (true, e) } diff --git a/src/as_frontend/typing.ml b/src/as_frontend/typing.ml index ba9a699f508..29f36a5d861 100644 --- a/src/as_frontend/typing.ml +++ b/src/as_frontend/typing.ml @@ -1211,7 +1211,7 @@ and pub_dec dec xs : region T.Env.t * region T.Env.t = | ExpD _ -> xs | LetD (pat, _) -> pub_pat pat xs | VarD (id, _) -> pub_val_id id xs - | ClassD (id, _, _, _, _, _) -> + | ClassD (id, _, _, _, _, _, _) -> pub_val_id {id with note = ()} (pub_typ_id id xs) | TypD (id, _, _) -> pub_typ_id id xs @@ -1252,33 +1252,35 @@ and gather_typ_field T.{lab; typ} con_env = and object_of_scope env sort fields scope at = let pub_typ, pub_val = pub_fields fields in - let typ_fields = + let tfs = T.Env.fold - (fun id con flds -> - if T.Env.mem id pub_typ then - { T.lab = id; T.typ = T.Typ con }::flds - else flds) scope.Scope.typ_env [] + (fun id c tfs -> + if T.Env.mem id pub_typ + then T.{lab = id; typ = T.Typ c}::tfs + else tfs + ) scope.Scope.typ_env [] in - let fields = + let tfs' = T.Env.fold - (fun id typ flds -> - if T.Env.mem id pub_val then - { T.lab = id; T.typ = typ }::flds - else flds) scope.Scope.val_env typ_fields + (fun id t tfs -> + if T.Env.mem id pub_val + then T.{lab = id; typ = t}::tfs + else tfs + ) scope.Scope.val_env tfs in - let t = T.Obj (sort, List.sort T.compare_field fields) in + let t = T.Obj (sort, List.sort T.compare_field tfs') in let accessible_cons = gather_typ T.ConSet.empty t in let inaccessible_cons = T.ConSet.diff scope.Scope.con_env accessible_cons in try T.avoid_cons inaccessible_cons accessible_cons; T.avoid inaccessible_cons t with T.Unavoidable c -> - error env at "local class type %s is contained in object or actor type\n %s" - (Con.to_string c) - (T.string_of_typ_expand t) + error env at "local class type %s is contained in object or actor type\n %s" + (Con.to_string c) + (T.string_of_typ_expand t) and is_actor_method dec : bool = match dec.it with - | LetD ({ it = VarP _; _}, {it = FuncE _; _} ) -> true + | LetD ({it = VarP _; _}, {it = FuncE _; _}) -> true | _ -> false and is_typ_dec dec : bool = match dec.it with @@ -1344,21 +1346,32 @@ and infer_dec env dec : T.typ = | VarD (_, exp) -> if not env.pre then ignore (infer_exp env exp); T.unit - | ClassD (id, typ_binds, sort, pat, self_id, fields) -> + | ClassD (id, typ_binds, pat, typ_opt, sort, self_id, fields) -> let t = T.Env.find id.it env.vals in if not env.pre then begin let c = T.Env.find id.it env.typs in let cs, _ts, te, ce = check_typ_binds env typ_binds in let env' = adjoin_typs env te ce in let _, ve = infer_pat_exhaustive env' pat in + let env'' = adjoin_vals env' ve in let self_typ = T.Con (c, List.map (fun c -> T.Con (c, [])) cs) in - let env'' = - { (add_val (adjoin_vals env' ve) self_id.it self_typ) with + let env''' = + { (add_val env'' self_id.it self_typ) with labs = T.Env.empty; rets = None; async = false } - in ignore (infer_obj env'' sort.it fields dec.at) + in + let t' = infer_obj env''' sort.it fields dec.at in + match typ_opt with + | None -> () + | Some typ -> + let t'' = check_typ env'' typ in + if not (T.sub t' t'') then + local_error env dec.at + "class body of type\n %s\ndoes not match expected type\n %s" + (T.string_of_typ_expand t') + (T.string_of_typ_expand t'') end; t | TypD _ -> @@ -1441,14 +1454,15 @@ and gather_dec env scope dec : Scope.t = let scope' = gather_block_decs env decs in let ve' = T.Env.add id.it (object_of_scope env sort fields scope' at) scope.val_env in let obj_env = T.Env.add id.it scope' scope.obj_env in - {val_env = ve'; - typ_env = scope.typ_env; - lib_env = scope.lib_env; - con_env = scope.con_env; - obj_env = obj_env } + { val_env = ve'; + typ_env = scope.typ_env; + lib_env = scope.lib_env; + con_env = scope.con_env; + obj_env = obj_env + } | LetD (pat, _) -> Scope.adjoin_val_env scope (gather_pat env scope.Scope.val_env pat) | VarD (id, _) -> Scope.adjoin_val_env scope (gather_id env scope.Scope.val_env id) - | TypD (id, binds, _) | ClassD (id, binds, _, _, _, _) -> + | TypD (id, binds, _) | ClassD (id, binds, _, _, _, _, _) -> let open Scope in if T.Env.mem id.it scope.typ_env then error env dec.at "duplicate definition for type %s in block" id.it; @@ -1523,8 +1537,8 @@ and infer_dec_typdecs env dec : Scope.t = ) | LetD _ | ExpD _ | VarD _ -> Scope.empty - | TypD (con_id, binds, typ) -> - let c = T.Env.find con_id.it env.typs in + | 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 @@ -1542,15 +1556,15 @@ and infer_dec_typdecs env dec : Scope.t = if not (T.ConSet.is_empty free_params) then error env dec.at "type definition %s %s references type parameter(s) %s from an outer scope" - con_id.it + id.it (T.string_of_kind k) (String.concat ", " (T.ConSet.fold (fun c cs -> T.string_of_con c::cs) free_params [])) end; Scope.{ empty with - typ_env = T.Env.singleton con_id.it c; - con_env = infer_id_typdecs con_id c k; + typ_env = T.Env.singleton id.it c; + con_env = infer_id_typdecs id c k; } - | ClassD (id, binds, sort, pat, self_id, fields) -> + | ClassD (id, binds, pat, _typ_opt, sort, self_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 @@ -1600,23 +1614,21 @@ and infer_dec_valdecs env dec : Scope.t = in let obj_typ = object_of_scope env sort fields obj_scope' at in let _ve = check_pat env obj_typ pat in - Scope.{ Scope.empty with - val_env = T.Env.singleton id.it obj_typ } + Scope.{empty with val_env = T.Env.singleton id.it obj_typ} | LetD (pat, exp) -> let t = infer_exp {env with pre = true} exp in let ve' = check_pat_exhaustive env t pat in - Scope.{ Scope.empty with val_env = ve' } + Scope.{empty with val_env = ve'} | VarD (id, exp) -> let t = infer_exp {env with pre = true} exp in - Scope.{ Scope.empty with val_env = T.Env.singleton id.it (T.Mut t) } - | TypD (con_id, binds, typ) -> - let c = match con_id.note with - | Some c -> c | _ -> assert false in - Scope.{ Scope.empty with - typ_env = T.Env.singleton con_id.it c; + Scope.{empty with val_env = T.Env.singleton id.it (T.Mut t)} + | TypD (id, _, _) -> + let c = Lib.Option.value id.note in + Scope.{ empty with + typ_env = T.Env.singleton id.it c; con_env = T.ConSet.singleton c ; } - | ClassD (id, typ_binds, sort, pat, self_id, fields) -> + | ClassD (id, typ_binds, pat, _, _, _, _) -> let cs, ts, te, ce = check_typ_binds env typ_binds in let env' = adjoin_typs env te ce in let c = T.Env.find id.it env.typs in @@ -1625,7 +1637,7 @@ and infer_dec_valdecs env dec : Scope.t = let t2 = T.Con (c, List.map (fun c -> T.Con (c, [])) cs) in let tbs = List.map2 (fun c t -> {T.var = Con.name c; bound = T.close cs t}) cs ts in let t = T.Func (T.Local, T.Returns, tbs, List.map (T.close cs) ts1, [T.close cs t2]) in - Scope.{ Scope.empty with + Scope.{ empty with val_env = T.Env.singleton id.it t; typ_env = T.Env.singleton id.it c; con_env = T.ConSet.singleton c; @@ -1636,32 +1648,32 @@ and infer_dec_valdecs env dec : Scope.t = let infer_prog scope prog : (T.typ * Scope.t) Diag.result = Diag.with_message_store (fun msgs -> - recover_opt - (fun prog -> - let env = env_of_scope msgs scope in - let res = infer_block env prog.it prog.at in - res - ) - prog + recover_opt + (fun prog -> + let env = env_of_scope msgs scope in + let res = infer_block env prog.it prog.at in + res + ) prog ) let infer_library env prog at = let typ,scope = infer_block env prog at in match prog with - | [{it = Syntax.ExpD _;_}] -> - typ + | [{it = Syntax.ExpD _;_}] -> + typ (* HACK: to be removed once we insist on single expression imports *) - | ds -> - object_of_scope env T.Module (List.map (fun d -> { vis = Public @@ no_region ; dec = d } @@ no_region) ds) scope at + | ds -> + object_of_scope env T.Module + (List.map (fun d -> {vis = Public @@ no_region; dec = d} @@ no_region) ds) + scope at let check_library scope (filename, prog) : Scope.t Diag.result = Diag.with_message_store (fun msgs -> - recover_opt - (fun prog -> - let env = env_of_scope msgs scope in - let typ = infer_library env prog.it prog.at in - Scope.library filename typ - ) - prog + recover_opt + (fun prog -> + let env = env_of_scope msgs scope in + let typ = infer_library env prog.it prog.at in + Scope.library filename typ + ) prog ) diff --git a/src/as_interpreter/interpret.ml b/src/as_interpreter/interpret.ml index dcbdcd7cc73..e4b591be678 100644 --- a/src/as_interpreter/interpret.ml +++ b/src/as_interpreter/interpret.ml @@ -747,7 +747,7 @@ and declare_dec dec : val_env = | TypD _ -> V.Env.empty | LetD (pat, _) -> declare_pat pat | VarD (id, _) -> declare_id id - | ClassD (id, _, _, _, _, _) -> declare_id {id with note = ()} + | ClassD (id, _, _, _, _, _, _) -> declare_id {id with note = ()} and declare_decs decs ve : val_env = match decs with @@ -773,7 +773,7 @@ and interpret_dec env dec (k : V.value V.cont) = ) | TypD _ -> k V.unit - | ClassD (id, _typbinds, sort, pat, id', fields) -> + | ClassD (id, _typbinds, pat, _typ_opt, sort, id', fields) -> let f = interpret_func env id.it pat (fun env' k' -> let env'' = adjoin_vals env' (declare_id id') in interpret_obj env'' sort fields (fun v' -> diff --git a/src/as_types/call_conv.ml b/src/as_types/call_conv.ml index 6c1acb006e0..8adc8121116 100644 --- a/src/as_types/call_conv.ml +++ b/src/as_types/call_conv.ml @@ -14,7 +14,7 @@ let async_cc n = { sort = Shared; control = Promises; n_args = n; n_res = 1} let call_conv_of_typ typ = match typ with - | Func(sort, control, tbds, dom, res) -> + | Func (sort, control, tbds, dom, res) -> { sort; control; n_args = List.length dom; n_res = List.length res } | Non -> { sort = Local; control = Returns; n_args = 1; n_res = 1 } diff --git a/src/as_types/type.ml b/src/as_types/type.ml index 1f2ac7ec002..ef127846a3b 100644 --- a/src/as_types/type.ml +++ b/src/as_types/type.ml @@ -102,19 +102,13 @@ let prim = function let seq = function [t] -> t | ts -> Tup ts -let compare_field f1 f2 = - match f1,f2 with - | {lab = l1; typ = Typ _}, {lab = l2; typ = Typ _ } -> compare l1 l2 - | {lab = l1; typ = Typ _}, {lab = l2; typ = _ } -> -1 - | {lab = l1; typ = _}, {lab = l2; typ = Typ _ } -> 1 - | {lab = l1; typ = _}, {lab = l2; typ = _ } -> compare l1 l2 - (* Coercions *) let iter_obj t = Obj (Object, [{lab = "next"; typ = Func (Local, Returns, [], [], [Opt t])}]) + (* Shifting *) let rec shift i n t = @@ -270,6 +264,7 @@ let open_binds tbs = List.iter2 set_kind cs ks; ts + (* Normalization and Classification *) let reduce tbs t ts = @@ -386,6 +381,13 @@ let lookup_typ_field l tfs = | Some {typ = Typ c; _} -> c | _ -> invalid "lookup_typ_field" +let compare_field f1 f2 = + match f1,f2 with + | {lab = l1; typ = Typ _}, {lab = l2; typ = Typ _ } -> compare l1 l2 + | {lab = l1; typ = Typ _}, {lab = l2; typ = _ } -> -1 + | {lab = l1; typ = _}, {lab = l2; typ = Typ _ } -> 1 + | {lab = l1; typ = _}, {lab = l2; typ = _ } -> compare l1 l2 + (* Span *) @@ -405,7 +407,7 @@ let rec span = function | Mut t -> span t | Serialized t -> None | Non -> Some 0 - | Typ _ -> assert false (* TBR *) + | Typ _ -> Some 1 (* Avoiding local constructors *) @@ -416,33 +418,33 @@ let rec avoid' cons seen = function | (Prim _ | Var _ | Any | Non | Pre) as t -> t | Con (c, ts) -> if ConSet.mem c seen then raise (Unavoidable c) else - if ConSet.mem c cons - then match Con.kind c with + if ConSet.mem c cons then + match Con.kind c with | Abs _ -> raise (Unavoidable c) | Def (tbs, t) -> avoid' cons (ConSet.add c seen) (reduce tbs t ts) else - begin try - Con (c, List.map (avoid' cons seen) ts) - with Unavoidable d -> + (try Con (c, List.map (avoid' cons seen) ts) with Unavoidable d -> match Con.kind c with | Def (tbs, t) -> avoid' cons seen (reduce tbs t ts) | Abs _ -> raise (Unavoidable d) - end + ) | Array t -> Array (avoid' cons seen t) | Tup ts -> Tup (List.map (avoid' cons seen) ts) | Func (s, c, tbs, ts1, ts2) -> - Func (s, - c, - List.map (avoid_bind cons seen) tbs, - List.map (avoid' cons seen) ts1, List.map (avoid' cons seen) ts2) + Func ( + s, c, + List.map (avoid_bind cons seen) tbs, + List.map (avoid' cons seen) ts1, + List.map (avoid' cons seen) ts2 + ) | Opt t -> Opt (avoid' cons seen t) | Async t -> Async (avoid' cons seen t) | Obj (s, fs) -> Obj (s, List.map (avoid_field cons seen) fs) | Variant fs -> Variant (List.map (avoid_field cons seen) fs) | Mut t -> Mut (avoid' cons seen t) | Serialized t -> Serialized (avoid' cons seen t) - | Typ c -> if ConSet.mem c cons then raise (Unavoidable c) - else Typ c (* TBR *) + | Typ c -> + if ConSet.mem c cons then raise (Unavoidable c) else Typ c (* TBR *) and avoid_bind cons seen {var; bound} = {var; bound = avoid' cons seen bound} @@ -922,8 +924,9 @@ and glb' lubs glbs t1 t2 = Array (glb' lubs glbs t1' t2') | Obj (s1, tf1), Obj (s2, tf2) when s1 = s2 -> (match glb_fields lubs glbs tf1 tf2 with - | None -> Non - | Some fs -> Obj (s1, fs)) + | None -> Non + | Some fs -> Obj (s1, fs) + ) | Func (s1, c1, bs1, args1, res1), Func (s2, c2, bs2, args2, res2) when s1 = s2 && c1 = c2 && List.(length bs1 = length bs2) && List.(length args1 = length args2 && length res1 = length res2) -> @@ -954,14 +957,14 @@ and glb_fields lubs glbs fs1 fs2 : field list option = | _ -> match f1.typ, f2.typ with | Typ _, Typ _ -> - if eq f1.typ f2.typ then - f1 +? glb_fields lubs glbs fs1' fs2' - else - None + if eq f1.typ f2.typ + then f1 +? glb_fields lubs glbs fs1' fs2' + else None | Typ _, _ | _, Typ _ -> assert false | _, _ -> - {f1 with typ = glb' lubs glbs f1.typ f2.typ} +? glb_fields lubs glbs fs1' fs2' + {f1 with typ = glb' lubs glbs f1.typ f2.typ} +? + glb_fields lubs glbs fs1' fs2' and glb_tags lubs glbs fs1 fs2 = match fs1, fs2 with | fs1, [] -> [] @@ -970,7 +973,9 @@ and glb_tags lubs glbs fs1 fs2 = match fs1, fs2 with match compare_field f1 f2 with | -1 -> glb_tags lubs glbs fs1' fs2 | +1 -> glb_tags lubs glbs fs1 fs2' - | _ -> {f1 with typ = glb' lubs glbs f1.typ f2.typ}::glb_tags lubs glbs fs1' fs2' + | _ -> + {f1 with typ = glb' lubs glbs f1.typ f2.typ} :: + glb_tags lubs glbs fs1' fs2' and combine_func_parts s c bs1 args1 res1 bs2 args2 res2 lubs glbs contra co = let open List in @@ -981,10 +986,11 @@ and combine_func_parts s c bs1 args1 res1 bs2 args2 res2 lubs glbs contra co = let cl = map (close cs) in let combine_binds = map2 (fun b1 b2 -> {b1 with bound = contra lubs glbs b1.bound b2.bound}) in - Func - (s, c, combine_binds bs1 bs2, - cl (map2 (contra lubs glbs) (op args1) (op args2)), - cl (map2 (co lubs glbs) (op res1) (op res2))) + Func ( + s, c, combine_binds bs1 bs2, + cl (map2 (contra lubs glbs) (op args1) (op args2)), + cl (map2 (co lubs glbs) (op res1) (op res2)) + ) and combine_con_parts t1 t2 naming re how = let s1, s2 = !str t1, !str t2 in @@ -1075,7 +1081,7 @@ let rec string_of_typ_nullary vs = function | Variant fs -> sprintf "{%s}" (String.concat "; " (List.map (string_of_tag vs) fs)) | Typ c -> - sprintf "= {%s}" (string_of_kind (Con.kind c)) + sprintf "= (type %s)" (string_of_kind (Con.kind c)) | t -> sprintf "(%s)" (string_of_typ' vs t) and string_of_dom vs ts = diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 287913b3753..e3b4ffacdae 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -86,7 +86,7 @@ and exp' at note = function let t = T.as_array note.I.note_typ in I.ArrayE (mut m, T.as_immut t, exps es) | S.IdxE (e1, e2) -> I.IdxE (exp e1, exp e2) - | S.FuncE (name, s, tbs, p, ty_opt, e) -> + | S.FuncE (name, s, tbs, p, _t_opt, e) -> let cc = Call_conv.call_conv_of_typ note.I.note_typ in let args, wrap = to_args cc p in let _, _, _, ty = T.as_func_sub s.it (List.length tbs) note.I.note_typ in @@ -248,7 +248,7 @@ and extra_typDs ds = | [] -> [] | d::ds -> match d.it with - | S.ClassD (id, _, _, _, _, _) -> + | S.ClassD (id, _, _, _, _, _, _) -> let c = Lib.Option.value id.note in let typD = I.TypD c @@ d.at in typD :: extra_typDs ds @@ -273,7 +273,7 @@ and dec' at n d = match d with | S.TypD (id, typ_bind, t) -> let c = Lib.Option.value id.note in I.TypD c - | S.ClassD (id, tbs, s, p, self_id, es) -> + | S.ClassD (id, tbs, p, _t_opt, s, self_id, es) -> let id' = {id with note = ()} in let cc = Call_conv.call_conv_of_typ n.S.note_typ in let inst = List.map diff --git a/src/pipeline/resolve_import.ml b/src/pipeline/resolve_import.ml index 5524ff5037d..70e3fb096b8 100644 --- a/src/pipeline/resolve_import.ml +++ b/src/pipeline/resolve_import.ml @@ -193,7 +193,7 @@ and dec env d = match d.it with | VarD (_, e) | LetD (_, e) -> exp env e - | ClassD (_, _, _, _ , _, efs) -> + | ClassD (_, _, _, _, _ , _, efs) -> List.iter (fun ef -> dec env ef.it.dec) efs let prog env p = decs env p.it diff --git a/test/fail/class.as b/test/fail/class.as new file mode 100644 index 00000000000..db4c96cfb10 --- /dev/null +++ b/test/fail/class.as @@ -0,0 +1,54 @@ +// Correct annotations +class B() : {x : Int} = { + public let x : Nat = 0 +}; + +type T = {x : Int; f : A -> B}; + +class C(y : Nat) : T { + public let x = y; + public let z = 1; + public func f(x : A) : A { x }; + public func g() {}; +}; + +let c = C(7); +let _ = c.x + c.z; +if (c.f(true)) { c.g() }; + +class D() : C { + public let x = 0; + public let z = 1; + public func f(x : B) : B { x }; + public func g() {}; + public func h(x : A) {}; +}; + + +type A = actor {m : () -> ()}; + +actor class AA() : A { + public func m() {}; +}; + + +object o { public type T = Nat }; +class E() : {a : o.T} = o { + public let a = 0; + public type T = Bool; +}; + + +// Incorrect annotations +class D1() : {x : Int} {}; +class D2() : {x : Nat} { + public let x = -3; +}; + +class D3() : actor {} = {}; +actor class D4() : {} = {}; + +object x { public type T = Nat }; +class D5(x : {}) : {a : x.T} = { + public let a = 0; +}; diff --git a/test/fail/ok/class.tc.ok b/test/fail/ok/class.tc.ok new file mode 100644 index 00000000000..bd29ff5289f --- /dev/null +++ b/test/fail/ok/class.tc.ok @@ -0,0 +1,18 @@ +class.as:43.1-43.26: type error, class body of type + {} +does not match expected type + {x : Int} +class.as:44.1-46.2: type error, class body of type + {x : Int} +does not match expected type + {x : Nat} +class.as:48.1-48.27: type error, class body of type + {} +does not match expected type + actor {} +class.as:49.1-49.27: type error, class body of type + actor {} +does not match expected type + {} +class.as:52.27-52.28: type error, type field T does not exist in type + {} From 3a2c085c0c2e38efad0699f0749966b453195954 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Thu, 1 Aug 2019 16:19:56 -0700 Subject: [PATCH 0329/1176] finish mono type defs --- src/as_idl/as_to_idl.ml | 94 ++++++++++++++++++++++----------------- src/idllib/arrange_idl.ml | 22 ++++++--- src/idllib/pipeline.ml | 8 ++-- 3 files changed, 74 insertions(+), 50 deletions(-) diff --git a/src/as_idl/as_to_idl.ml b/src/as_idl/as_to_idl.ml index fc9549e74c2..895b0443a82 100644 --- a/src/as_idl/as_to_idl.ml +++ b/src/as_idl/as_to_idl.ml @@ -6,8 +6,8 @@ module I = Idllib.Syntax type label = Nat of Lib.Uint32.t | Id of string -let dec_set = ref ConSet.empty - +let dec_env = ref ConEnv.empty +(* let unescape lab : label = let len = String.length lab in try if lab.[len-1] = '_' then begin @@ -19,7 +19,9 @@ let unescape lab : label = if len >= 2 && lab.[len-1] = '_' then Id (String.sub lab 0 (len-1)) else Id lab - + *) +let unescape lab = Id lab + let prim p = match p with | Null -> I.Null @@ -48,24 +50,28 @@ let rec typ env t = | Any -> I.PrimT I.Reserved | Non -> I.PrimT I.Empty | Prim p -> I.PrimT (prim p) - | Var (s, i) -> assert false + | Var (s, i) -> + printf "VAR %s.%d" s i; + assert false | Con (c, ts) -> (* TODO monomorphization *) - let id = - (if List.length ts = 0 then string_of_con c - else sprintf "%s<%s>" (string_of_con c) (String.concat ", " (List.map string_of_typ ts))) @@ no_region in - dec_set := ConSet.add c !dec_set; + let id = Con.to_string c @@ no_region in + (* TODO(if List.length ts = 0 then string_of_con c + else sprintf "%s<%s>" (string_of_con c) (String.concat ", " (List.map string_of_typ ts))) @@ no_region in*) + chase_con env c; I.VarT id + | Typ c -> assert false + (*chase_con env c; + I.VarT (string_of_con c @@ no_region)*) | Tup ts -> I.RecordT (tuple env ts) | Array t -> I.VecT (typ env t) | Obj (Object, fs) -> I.RecordT (List.map (field env) fs) - | Obj (Actor, fs) -> I.ServT (List.map (meth env) fs) + | Obj (Actor, fs) -> I.ServT (meths env fs) | Obj (Module, _) -> assert false | Variant fs -> I.VariantT (List.map (field env) fs) - | Typ c -> assert false | Func (Shared, c, [], ts1, ts2) -> let fs1 = tuple env ts1 in (match ts2 with @@ -93,38 +99,46 @@ and tuple env ts = let name = Lib.Uint32.to_string id @@ no_region in I.{id = id; name = name; typ = typ env x} @@ no_region ) ts -and meth env {lab; typ=t} = - match unescape lab with - | Nat nat -> I.{var = Lib.Uint32.to_string nat @@ no_region; meth = typ env t} @@ no_region - | Id id -> I.{var = id @@ no_region; meth = typ env t} @@ no_region - -let actor env = - let set = - ConSet.filter (fun c -> - match Con.kind c with - | Def ([], Obj (Actor, fs)) -> true - | _ -> false - ) env.Scope.con_env in - assert (ConSet.cardinal set <= 1); - match ConSet.choose_opt set with - | None -> None - | Some c -> - (match Con.kind c with - | Def (_, Obj (Actor, fs)) -> - let t = I.ServT (List.map (meth env) fs) @@ no_region in - Some (I.ActorD (Con.to_string c @@ no_region, t) @@ no_region) - | _ -> assert false) +and meths env fs = + List.fold_right (fun f list -> + match f.typ with + | Typ c -> + chase_con env c; + list + | _ -> + let meth = + match unescape f.lab with + | Nat nat -> + I.{var = Lib.Uint32.to_string nat @@ no_region; + meth = typ env f.typ} @@ no_region + | Id id -> + I.{var = id @@ no_region; + meth = typ env f.typ} @@ no_region in + meth :: list + ) fs [] +and chase_con env c = + if not (ConEnv.mem c !dec_env) then + (match Con.kind c with + | Def ([], t) -> + dec_env := ConEnv.add c (I.PreT @@ no_region) !dec_env; + let t = typ env t in + dec_env := ConEnv.add c t !dec_env + | _ -> ()) -let decs env set = - ConSet.fold (fun c list -> +let chase_decs env = + ConSet.iter (fun c -> match Con.kind c with - | Def ([], t) -> (I.TypD (Con.to_string c @@ no_region, typ env t) @@ no_region) :: list - | _ -> list) - set [] + | Def ([], Obj (Actor, fs)) -> + chase_con env c; + | _ -> () + ) env.Scope.con_env; + ConEnv.fold (fun c t list -> + let dec = I.TypD (Con.to_string c @@ no_region, t) @@ no_region in + dec::list + ) !dec_env [] let prog env : I.prog = - let actor = actor env in - let decs = decs env !dec_set in - let it = I.{decs = decs; actor = actor} in - {it = it; at = no_region; note = ""} + let decs = chase_decs env in + let prog = I.{decs = decs; actor = None} in + {it = prog; at = no_region; note = ""} diff --git a/src/idllib/arrange_idl.ml b/src/idllib/arrange_idl.ml index ba19f7af348..20fa0d01670 100644 --- a/src/idllib/arrange_idl.ml +++ b/src/idllib/arrange_idl.ml @@ -78,18 +78,28 @@ let rec string_of_typ t = | VarT id -> sprintf "%s" id.it | PrimT s -> string_of_prim s | FuncT (ms,s,t) -> - sprintf "(%s) -> (%s)%s" (string_of_list string_of_field ", " s) (string_of_list string_of_field ", " t) (string_of_list string_of_mode " " ms) + sprintf "func %s" (string_of_func (ms,s,t)) | OptT t -> "opt " ^ string_of_typ t | VecT t -> "vec " ^ string_of_typ t - | RecordT fs -> sprintf "{%s}" (string_of_list string_of_field "; " fs) + | RecordT fs -> sprintf "record {%s}" (string_of_list string_of_field "; " fs) | VariantT fs -> sprintf "variant {%s}" (string_of_list string_of_field "; " fs) - | ServT ms -> sprintf "service {%s}" (string_of_list string_of_meth "" ms) + | ServT ms -> sprintf "service {\n%s}" (string_of_list string_of_meth "" ms) | PreT -> "Pre" - +and string_of_func (ms,s,t) = + sprintf "(%s) -> (%s)%s" + (string_of_list string_of_field ", " s) + (string_of_list string_of_field ", " t) + (string_of_list string_of_mode " " ms) and string_of_field f = - sprintf "%s : %s" f.it.name.it (string_of_typ f.it.typ) + let unnamed = (f.it.name.it = Lib.Uint32.to_string f.it.id) in + if unnamed then string_of_typ f.it.typ + else sprintf "%s : %s" f.it.name.it (string_of_typ f.it.typ) and string_of_meth m = - sprintf "%s : %s;\n" m.it.var.it (string_of_typ m.it.meth) + sprintf "%s : %s;\n" + m.it.var.it + (match m.it.meth.it with + | FuncT (ms,s,t) -> string_of_func (ms,s,t) + | _ -> string_of_typ m.it.meth) let string_of_dec d = match d.it with diff --git a/src/idllib/pipeline.ml b/src/idllib/pipeline.ml index ddc0c02747e..6e6f0105d55 100644 --- a/src/idllib/pipeline.ml +++ b/src/idllib/pipeline.ml @@ -8,10 +8,10 @@ let phase heading name = let error at cat text = Error [{ Diag.sev = Diag.Error; at; cat; text }] -let print_stat_ve = +let print_stat_te = Typing.Env.iter (fun x t -> - printf "%s %s : %s\n" - "var" x (Arrange_idl.string_of_typ t) + printf "%s %s = %s\n" + "type" x (Arrange_idl.string_of_typ t) ) let dump_prog flag prog = @@ -63,7 +63,7 @@ let check_prog senv prog let r = Typing.check_prog senv prog in (match r with | Ok (scope, _) -> - if !Flags.verbose then print_stat_ve scope; + if !Flags.verbose then print_stat_te scope; | Error _ -> ()); r From 5a83c7c3c4480d528b10e071f1f4de17971a8177 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Fri, 2 Aug 2019 12:11:42 -0700 Subject: [PATCH 0330/1176] add actor --- src/as_idl/as_to_idl.ml | 50 +++++++++++++++++++++++++++++---------- src/as_idl/dune | 2 +- src/idllib/arrange_idl.ml | 1 + src/pipeline/pipeline.ml | 4 ++-- 4 files changed, 42 insertions(+), 15 deletions(-) diff --git a/src/as_idl/as_to_idl.ml b/src/as_idl/as_to_idl.ml index 895b0443a82..67b185d5cf3 100644 --- a/src/as_idl/as_to_idl.ml +++ b/src/as_idl/as_to_idl.ml @@ -2,12 +2,13 @@ open As_types open As_types.Type open Source open Printf +module E = As_def.Syntax module I = Idllib.Syntax type label = Nat of Lib.Uint32.t | Id of string let dec_env = ref ConEnv.empty -(* + let unescape lab : label = let len = String.length lab in try if lab.[len-1] = '_' then begin @@ -19,8 +20,6 @@ let unescape lab : label = if len >= 2 && lab.[len-1] = '_' then Id (String.sub lab 0 (len-1)) else Id lab - *) -let unescape lab = Id lab let prim p = match p with @@ -55,14 +54,12 @@ let rec typ env t = assert false | Con (c, ts) -> (* TODO monomorphization *) - let id = Con.to_string c @@ no_region in - (* TODO(if List.length ts = 0 then string_of_con c - else sprintf "%s<%s>" (string_of_con c) (String.concat ", " (List.map string_of_typ ts))) @@ no_region in*) + let id = + (if List.length ts = 0 then string_of_con c + else sprintf "%s<%s>" (string_of_con c) (String.concat ", " (List.map string_of_typ ts))) @@ no_region in chase_con env c; I.VarT id | Typ c -> assert false - (*chase_con env c; - I.VarT (string_of_con c @@ no_region)*) | Tup ts -> I.RecordT (tuple env ts) | Array t -> I.VecT (typ env t) @@ -131,14 +128,43 @@ let chase_decs env = | Def ([], Obj (Actor, fs)) -> chase_con env c; | _ -> () - ) env.Scope.con_env; + ) env.Scope.con_env + +let gather_decs env = ConEnv.fold (fun c t list -> let dec = I.TypD (Con.to_string c @@ no_region, t) @@ no_region in dec::list ) !dec_env [] -let prog env : I.prog = - let decs = chase_decs env in - let prog = I.{decs = decs; actor = None} in +let actor env progs = + let open E in + let find_last_actor (prog : prog) = + let anon = "anon_" ^ (Filename.remove_extension prog.note) in + List.fold_left + (fun actor (d : dec) -> + match d.note.note_typ with + | Obj (Actor, _) | Con (_, []) as t -> + (match d.it with + | ExpD _ -> Some (anon, t) + | LetD ({it=WildP;_}, _) -> Some (anon, t) + | LetD ({it=VarP id;_}, _) -> Some (id.it, t) + | _ -> actor + ) + | _ -> actor + ) None prog.it in + + match progs with + | [] -> None + | _ -> + let prog = Lib.List.last progs in + match find_last_actor prog with + | None -> None + | Some (id, t) -> Some (I.ActorD (id @@ no_region, typ env t) @@ no_region) + +let prog (progs, env) : I.prog = + let actor = actor env progs in + if actor = None then chase_decs env; + let decs = gather_decs env in + let prog = I.{decs = decs; actor = actor} in {it = prog; at = no_region; note = ""} diff --git a/src/as_idl/dune b/src/as_idl/dune index a6e1415a4c1..4d2cd7373e0 100644 --- a/src/as_idl/dune +++ b/src/as_idl/dune @@ -1,4 +1,4 @@ (library (name as_idl) - (libraries lib idllib lang_utils as_types) + (libraries lib idllib lang_utils as_types as_def) ) diff --git a/src/idllib/arrange_idl.ml b/src/idllib/arrange_idl.ml index 20fa0d01670..f3204dc25dd 100644 --- a/src/idllib/arrange_idl.ml +++ b/src/idllib/arrange_idl.ml @@ -110,6 +110,7 @@ let string_of_actor a = match a with | None -> "" | Some {it = ActorD (id, {it=ServT ms; _}); _} -> sprintf "service %s {\n%s}" id.it (string_of_list string_of_meth "" ms) + | Some {it = ActorD (id, {it=VarT x; _}); _} -> sprintf "service %s : %s" id.it x.it | Some _ -> assert false let string_of_prog prog = diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index dc701ad05bc..0a54eb778f2 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -350,8 +350,8 @@ let check_string s name : check_result = let generate_idl files : Idllib.Syntax.prog Diag.result = Diag.bind (load_progs (parse_files files) initial_stat_env) (fun (libraries, progs, senv) -> - Diag.return (As_idl.As_to_idl.prog senv)) - + Diag.return (As_idl.As_to_idl.prog (progs, senv))) + (* Running *) let run_files files : unit option = From 2ee2c52f64ded22d67115773dd9dafa5a2a836df Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Fri, 2 Aug 2019 14:24:09 -0700 Subject: [PATCH 0331/1176] add tests --- samples/pa_cars.as | 11 +- src/as_idl/as_to_idl.ml | 81 ++++++------ src/exes/asc.ml | 25 +++- src/idllib/arrange_idl.ml | 6 +- src/idllib/pipeline.ml | 3 +- src/idllib/pipeline.mli | 2 +- test/run-dfinity/ok/chat.did.ok | 10 ++ test/run-dfinity/ok/chatpp.did.ok | 10 ++ test/run-dfinity/ok/closure-params.did.ok | 5 + test/run-dfinity/ok/counter-class.did.ok | 6 + test/run-dfinity/ok/counter.did.ok | 4 + test/run-dfinity/ok/counter2.did.ok | 4 + test/run-dfinity/ok/data-params.did.ok | 31 +++++ test/run-dfinity/ok/data-params.idl.stderr.ok | 4 + test/run-dfinity/ok/empty-actor.did.ok | 2 + test/run-dfinity/ok/flatten-awaitables.did.ok | 21 +++ .../ok/flatten-awaitables.idl.stderr.ok | 120 ++++++++++++++++++ .../ok/general-type-components.did.ok | 5 + test/run-dfinity/ok/hello-world-async.did.ok | 4 + test/run-dfinity/ok/hello-world-await.did.ok | 6 + .../run-dfinity/ok/hello-world-message.did.ok | 3 + .../ok/hello-world-message2.did.ok | 3 + test/run-dfinity/ok/hello-world2.did.ok | 3 + test/run-dfinity/ok/hello-world3.did.ok | 5 + test/run-dfinity/ok/indirect-counter.did.ok | 4 + test/run-dfinity/ok/reference-params.did.ok | 6 + test/run-dfinity/ok/transpose.did.ok | 5 + test/run.sh | 8 +- 28 files changed, 339 insertions(+), 58 deletions(-) create mode 100644 test/run-dfinity/ok/chat.did.ok create mode 100644 test/run-dfinity/ok/chatpp.did.ok create mode 100644 test/run-dfinity/ok/closure-params.did.ok create mode 100644 test/run-dfinity/ok/counter-class.did.ok create mode 100644 test/run-dfinity/ok/counter.did.ok create mode 100644 test/run-dfinity/ok/counter2.did.ok create mode 100644 test/run-dfinity/ok/data-params.did.ok create mode 100644 test/run-dfinity/ok/data-params.idl.stderr.ok create mode 100644 test/run-dfinity/ok/empty-actor.did.ok create mode 100644 test/run-dfinity/ok/flatten-awaitables.did.ok create mode 100644 test/run-dfinity/ok/flatten-awaitables.idl.stderr.ok create mode 100644 test/run-dfinity/ok/general-type-components.did.ok create mode 100644 test/run-dfinity/ok/hello-world-async.did.ok create mode 100644 test/run-dfinity/ok/hello-world-await.did.ok create mode 100644 test/run-dfinity/ok/hello-world-message.did.ok create mode 100644 test/run-dfinity/ok/hello-world-message2.did.ok create mode 100644 test/run-dfinity/ok/hello-world2.did.ok create mode 100644 test/run-dfinity/ok/hello-world3.did.ok create mode 100644 test/run-dfinity/ok/indirect-counter.did.ok create mode 100644 test/run-dfinity/ok/reference-params.did.ok create mode 100644 test/run-dfinity/ok/transpose.did.ok diff --git a/samples/pa_cars.as b/samples/pa_cars.as index a475b288629..80a51e39899 100644 --- a/samples/pa_cars.as +++ b/samples/pa_cars.as @@ -7,7 +7,6 @@ // - Server: Validate car is registered under the given name // - Client: Pick a parking spot from a Google Map like interface + time // - Server: Register the parking spot for the user - type Car = { model : Text; plate : Text }; type DMV = actor { check : Car -> async CarInfo }; type CarInfo = { @@ -19,7 +18,7 @@ type CarInfo = { }; actor class PACars(dmv : DMV) { - func verifyCarInformation(user : User, car : Car) : async ?(shared (Location, TimeSpan) -> async Result) { + public func verifyCarInformation(user : User, car : Car) : async ?(shared (Location, TimeSpan) -> async Result) { let carInfo = await dmv.check(car); if (carInfo.isValid and not carInfo.wasStolen) { return ?(shared func (location, time) : async Result { @@ -36,8 +35,8 @@ actor class PACars(dmv : DMV) { return null; }; - type Location = { lat : Float; long : Float }; - type TimeSpan = { start : Int; end : Int }; - type Result = ?({ reservationId : Text }); - type User = { name : Text }; + public type Location = { lat : Float; long : Float }; + public type TimeSpan = { start : Int; end : Int }; + public type Result = ?({ reservationId : Text }); + public type User = { name : Text }; }; diff --git a/src/as_idl/as_to_idl.ml b/src/as_idl/as_to_idl.ml index 67b185d5cf3..f55b5d5f750 100644 --- a/src/as_idl/as_to_idl.ml +++ b/src/as_idl/as_to_idl.ml @@ -43,9 +43,8 @@ let prim p = | Char -> I.Nat32 | Text -> I.Text -let rec typ env t = +let rec typ t = (match t with - | Pre -> assert false | Any -> I.PrimT I.Reserved | Non -> I.PrimT I.Empty | Prim p -> I.PrimT (prim p) @@ -57,99 +56,104 @@ let rec typ env t = let id = (if List.length ts = 0 then string_of_con c else sprintf "%s<%s>" (string_of_con c) (String.concat ", " (List.map string_of_typ ts))) @@ no_region in - chase_con env c; + chase_con c; I.VarT id | Typ c -> assert false | Tup ts -> - I.RecordT (tuple env ts) - | Array t -> I.VecT (typ env t) + I.RecordT (tuple ts) + | Array t -> I.VecT (typ t) + | Opt t -> I.OptT (typ t) | Obj (Object, fs) -> - I.RecordT (List.map (field env) fs) - | Obj (Actor, fs) -> I.ServT (meths env fs) + I.RecordT (List.map field fs) + | Obj (Actor, fs) -> I.ServT (meths fs) | Obj (Module, _) -> assert false | Variant fs -> - I.VariantT (List.map (field env) fs) + I.VariantT (List.map field fs) | Func (Shared, c, [], ts1, ts2) -> - let fs1 = tuple env ts1 in + let fs1 = tuple ts1 in (match ts2 with | [] when c = Returns -> I.FuncT ([I.Oneway @@ no_region], fs1, []) - | [Async t] when c = Promises -> I.FuncT ([], fs1, tuple env [t]) + | [Async t] when c = Promises -> I.FuncT ([], fs1, tuple [t]) | _ -> assert false) | Func _ -> assert false - | Opt t -> I.OptT (typ env t) | Async t -> assert false | Mut t -> assert false | Serialized t -> assert false + | Pre -> assert false ) @@ no_region -and field env {lab; typ=t} = +and field {lab; typ=t} = match unescape lab with | Nat nat -> let name = Lib.Uint32.to_string nat @@ no_region in - I.{id = nat; name = name; typ = typ env t} @@ no_region + I.{id = nat; name = name; typ = typ t} @@ no_region | Id id -> let name = id @@ no_region in let id = Idllib.IdlHash.idl_hash id in - I.{id = id; name = name; typ = typ env t} @@ no_region -and tuple env ts = + I.{id = id; name = name; typ = typ t} @@ no_region +and tuple ts = List.mapi (fun i x -> let id = Lib.Uint32.of_int i in let name = Lib.Uint32.to_string id @@ no_region in - I.{id = id; name = name; typ = typ env x} @@ no_region + I.{id = id; name = name; typ = typ x} @@ no_region ) ts -and meths env fs = +and meths fs = List.fold_right (fun f list -> match f.typ with | Typ c -> - chase_con env c; + chase_con c; list | _ -> let meth = match unescape f.lab with | Nat nat -> I.{var = Lib.Uint32.to_string nat @@ no_region; - meth = typ env f.typ} @@ no_region + meth = typ f.typ} @@ no_region | Id id -> I.{var = id @@ no_region; - meth = typ env f.typ} @@ no_region in + meth = typ f.typ} @@ no_region in meth :: list ) fs [] -and chase_con env c = +and chase_con c = if not (ConEnv.mem c !dec_env) then (match Con.kind c with | Def ([], t) -> dec_env := ConEnv.add c (I.PreT @@ no_region) !dec_env; - let t = typ env t in + let t = typ t in dec_env := ConEnv.add c t !dec_env | _ -> ()) +let is_actor_con c = + match Con.kind c with + | Def ([], Obj (Actor, _)) -> true + | _ -> false + let chase_decs env = ConSet.iter (fun c -> - match Con.kind c with - | Def ([], Obj (Actor, fs)) -> - chase_con env c; - | _ -> () + if is_actor_con c then chase_con c ) env.Scope.con_env -let gather_decs env = +let gather_decs () = ConEnv.fold (fun c t list -> let dec = I.TypD (Con.to_string c @@ no_region, t) @@ no_region in dec::list ) !dec_env [] -let actor env progs = +let actor progs = let open E in let find_last_actor (prog : prog) = let anon = "anon_" ^ (Filename.remove_extension prog.note) in + let check_dec d t def = + match d.it with + | ExpD _ -> Some (anon, t) + | LetD ({it=WildP;_}, _) -> Some (anon, t) + | LetD ({it=VarP id;_}, _) -> Some (id.it, t) + | _ -> def + in List.fold_left (fun actor (d : dec) -> match d.note.note_typ with - | Obj (Actor, _) | Con (_, []) as t -> - (match d.it with - | ExpD _ -> Some (anon, t) - | LetD ({it=WildP;_}, _) -> Some (anon, t) - | LetD ({it=VarP id;_}, _) -> Some (id.it, t) - | _ -> actor - ) + | Obj (Actor, _) as t -> check_dec d t actor + | Con (c, []) as t when is_actor_con c -> check_dec d t actor | _ -> actor ) None prog.it in @@ -159,12 +163,13 @@ let actor env progs = let prog = Lib.List.last progs in match find_last_actor prog with | None -> None - | Some (id, t) -> Some (I.ActorD (id @@ no_region, typ env t) @@ no_region) + | Some (id, t) -> Some (I.ActorD (id @@ no_region, typ t) @@ no_region) let prog (progs, env) : I.prog = - let actor = actor env progs in + dec_env := ConEnv.empty; + let actor = actor progs in if actor = None then chase_decs env; - let decs = gather_decs env in + let decs = gather_decs () in let prog = I.{decs = decs; actor = actor} in {it = prog; at = no_region; note = ""} diff --git a/src/exes/asc.ml b/src/exes/asc.ml index f4b377615a2..fdaf85d14fd 100644 --- a/src/exes/asc.ml +++ b/src/exes/asc.ml @@ -77,6 +77,13 @@ let argspec = Arg.align ] +let fill_out_file files ext = + if !out_file = "" then begin + match files with + | [n] -> out_file := Filename.remove_extension (Filename.basename n) ^ ext + | ns -> eprintf "asc: no output file specified"; exit 1 + end + (* Main *) let exit_on_none = function @@ -97,14 +104,18 @@ let process_files files : unit = | Check -> Diag.run (Pipeline.check_files files) | Idl -> - let idl_ast = Diag.run (Pipeline.generate_idl files) in - Printf.printf "%s" (Idllib.Arrange_idl.string_of_prog idl_ast) + let prog = Diag.run (Pipeline.generate_idl files) in + let idl_code = Idllib.Arrange_idl.string_of_prog prog in + if !out_file = "" then + (printf "%s" idl_code; + ignore (Diag.run (Idllib.Pipeline.check_prog prog))) + else begin + ignore (Diag.run (Idllib.Pipeline.check_prog prog)); + let oc = open_out !out_file in + output_string oc idl_code; close_out oc + end | Compile -> - if !out_file = "" then begin - match files with - | [n] -> out_file := Filename.remove_extension (Filename.basename n) ^ ".wasm" - | ns -> eprintf "asc: no output file specified"; exit 1 - end; + fill_out_file files ".wasm"; let module_ = Diag.run Pipeline.(compile_files !compile_mode !link files) in let oc = open_out !out_file in let (source_map, wasm) = CustomModuleEncode.encode module_ in diff --git a/src/idllib/arrange_idl.ml b/src/idllib/arrange_idl.ml index f3204dc25dd..becd3726c07 100644 --- a/src/idllib/arrange_idl.ml +++ b/src/idllib/arrange_idl.ml @@ -109,9 +109,9 @@ let string_of_dec d = let string_of_actor a = match a with | None -> "" - | Some {it = ActorD (id, {it=ServT ms; _}); _} -> sprintf "service %s {\n%s}" id.it (string_of_list string_of_meth "" ms) - | Some {it = ActorD (id, {it=VarT x; _}); _} -> sprintf "service %s : %s" id.it x.it + | Some {it = ActorD (id, {it=ServT ms; _}); _} -> sprintf "service %s {\n%s}\n" id.it (string_of_list string_of_meth "" ms) + | Some {it = ActorD (id, {it=VarT x; _}); _} -> sprintf "service %s : %s\n" id.it x.it | Some _ -> assert false let string_of_prog prog = - sprintf "%s%s\n" (string_of_list string_of_dec "" prog.it.decs) (string_of_actor prog.it.actor) + sprintf "%s%s" (string_of_list string_of_dec "" prog.it.decs) (string_of_actor prog.it.actor) diff --git a/src/idllib/pipeline.ml b/src/idllib/pipeline.ml index 6e6f0105d55..7744d4f63d8 100644 --- a/src/idllib/pipeline.ml +++ b/src/idllib/pipeline.ml @@ -121,7 +121,8 @@ let load_prog parse senv = let initial_stat_env = Typing.empty_scope let check_file file : load_result = load_prog (parse_file file) initial_stat_env - +let check_prog prog : Typing.scope Diag.result = check_prog initial_stat_env prog + (* JS Compilation *) type compile_result = Buffer.t Diag.result diff --git a/src/idllib/pipeline.mli b/src/idllib/pipeline.mli index 76c62bd46b1..129f2b08619 100644 --- a/src/idllib/pipeline.mli +++ b/src/idllib/pipeline.mli @@ -1,3 +1,3 @@ val check_file : string -> (Syntax.prog * Typing.scope) Diag.result - +val check_prog : Syntax.prog -> Typing.scope Diag.result val compile_js_file : string -> Buffer.t Diag.result diff --git a/test/run-dfinity/ok/chat.did.ok b/test/run-dfinity/ok/chat.did.ok new file mode 100644 index 00000000000..cce88b93072 --- /dev/null +++ b/test/run-dfinity/ok/chat.did.ok @@ -0,0 +1,10 @@ +type Text = text; +type Server = service { +subscribe : (Client) -> (Post); +}; +type Post = func (Text) -> () oneway; +type Client = service { +go : (Text, Server) -> () oneway; +send : (Text) -> () oneway; +}; +service charlie : Client diff --git a/test/run-dfinity/ok/chatpp.did.ok b/test/run-dfinity/ok/chatpp.did.ok new file mode 100644 index 00000000000..5fc47e0b4a1 --- /dev/null +++ b/test/run-dfinity/ok/chatpp.did.ok @@ -0,0 +1,10 @@ +type Text = text; +type Subscription = record {cancel : func () -> () oneway; post : func (Text) -> () oneway}; +type Server = service { +subscribe : (Client) -> (Subscription); +}; +type Client = service { +go : (Text, Server) -> () oneway; +send : (Text) -> () oneway; +}; +service charlie : Client diff --git a/test/run-dfinity/ok/closure-params.did.ok b/test/run-dfinity/ok/closure-params.did.ok new file mode 100644 index 00000000000..96d24dc71a3 --- /dev/null +++ b/test/run-dfinity/ok/closure-params.did.ok @@ -0,0 +1,5 @@ +type Nat = nat; +service a { +incn : (Nat) -> () oneway; +readCounter : (func (Nat) -> () oneway) -> () oneway; +} diff --git a/test/run-dfinity/ok/counter-class.did.ok b/test/run-dfinity/ok/counter-class.did.ok new file mode 100644 index 00000000000..034c524ba95 --- /dev/null +++ b/test/run-dfinity/ok/counter-class.did.ok @@ -0,0 +1,6 @@ +type Int = int; +type Counter = service { +dec : () -> () oneway; +read : () -> (Int); +}; +service c : Counter diff --git a/test/run-dfinity/ok/counter.did.ok b/test/run-dfinity/ok/counter.did.ok new file mode 100644 index 00000000000..27e056d18c8 --- /dev/null +++ b/test/run-dfinity/ok/counter.did.ok @@ -0,0 +1,4 @@ +service a { +inc : () -> () oneway; +printCounter : () -> () oneway; +} diff --git a/test/run-dfinity/ok/counter2.did.ok b/test/run-dfinity/ok/counter2.did.ok new file mode 100644 index 00000000000..8c3ecd78383 --- /dev/null +++ b/test/run-dfinity/ok/counter2.did.ok @@ -0,0 +1,4 @@ +service anon_counter2 { +inc : () -> () oneway; +printCounter : () -> () oneway; +} diff --git a/test/run-dfinity/ok/data-params.did.ok b/test/run-dfinity/ok/data-params.did.ok new file mode 100644 index 00000000000..f187012d7cd --- /dev/null +++ b/test/run-dfinity/ok/data-params.did.ok @@ -0,0 +1,31 @@ +type Word8 = nat8; +type Word64 = nat64; +type Word32 = nat32; +type Word16 = nat16; +type Text = text; +type Nat8 = nat8; +type Nat64 = nat64; +type Nat32 = nat32; +type Nat16 = nat16; +type Nat = nat; +type Int8 = int8; +type Int64 = int64; +type Int32 = int32; +type Int16 = int16; +type Int = int; +service a { +incVariant : (variant {bar : Nat; foo : Nat}) -> () oneway; +incarray : (vec Nat) -> () oneway; +inci : (Int) -> () oneway; +incints : (Int8, Int16, Int32, Int64) -> () oneway; +incn : (Nat) -> () oneway; +incnats : (Nat8, Nat16, Nat32, Nat64) -> () oneway; +incnested : (Nat, record {Nat; Nat}) -> () oneway; +incnn : (Nat, Nat) -> () oneway; +incopt : (opt Nat) -> () oneway; +increcord : (record {x : Nat; y : Nat}) -> () oneway; +incwords : (Word8, Word16, Word32, Word64) -> () oneway; +printCounter : () -> () oneway; +printLabeled : (Text) -> () oneway; +printLabeledOpt : (opt Text) -> () oneway; +} diff --git a/test/run-dfinity/ok/data-params.idl.stderr.ok b/test/run-dfinity/ok/data-params.idl.stderr.ok new file mode 100644 index 00000000000..fdcd0402292 --- /dev/null +++ b/test/run-dfinity/ok/data-params.idl.stderr.ok @@ -0,0 +1,4 @@ +data-params.as:59.30-59.40: warning, this pattern consuming type + ?Text +does not cover value + null diff --git a/test/run-dfinity/ok/empty-actor.did.ok b/test/run-dfinity/ok/empty-actor.did.ok new file mode 100644 index 00000000000..dc6de6a63c3 --- /dev/null +++ b/test/run-dfinity/ok/empty-actor.did.ok @@ -0,0 +1,2 @@ +service anon_empty-actor { +} diff --git a/test/run-dfinity/ok/flatten-awaitables.did.ok b/test/run-dfinity/ok/flatten-awaitables.did.ok new file mode 100644 index 00000000000..0fa4156f0d6 --- /dev/null +++ b/test/run-dfinity/ok/flatten-awaitables.did.ok @@ -0,0 +1,21 @@ +type Text = text; +type Int = int; +type Bool = bool; +service a { +g0 : (func (record {}) -> (record {}), record {}) -> (record {}); +g1 : (func (Int) -> (Int), Int) -> (Int); +g2 : (func (record {Int; Bool}) -> (record {Int; Bool}), record {Int; Bool}) -> (record {Int; Bool}); +g3 : (func (record {Int; Bool; Text}) -> (record {Int; Bool; Text}), record {Int; Bool; Text}) -> (record {Int; Bool; Text}); +h0 : (func () -> (record {}), record {}) -> (record {}); +h1 : (func (Int) -> (Int), Int) -> (Int); +h2 : (func (Int, Bool) -> (record {Int; Bool}), record {Int; Bool}) -> (record {Int; Bool}); +h3 : (func (Int, Bool, Text) -> (record {Int; Bool; Text}), record {Int; Bool; Text}) -> (record {Int; Bool; Text}); +m0 : () -> (record {}); +m1 : (Int) -> (Int); +m2 : (Int, Bool) -> (record {Int; Bool}); +m3 : (Int, Bool, Text) -> (record {Int; Bool; Text}); +n0 : (record {}) -> (record {}); +n1 : (Int) -> (Int); +n2 : (record {Int; Bool}) -> (record {Int; Bool}); +n3 : (record {Int; Bool; Text}) -> (record {Int; Bool; Text}); +} diff --git a/test/run-dfinity/ok/flatten-awaitables.idl.stderr.ok b/test/run-dfinity/ok/flatten-awaitables.idl.stderr.ok new file mode 100644 index 00000000000..132c1167a2f --- /dev/null +++ b/test/run-dfinity/ok/flatten-awaitables.idl.stderr.ok @@ -0,0 +1,120 @@ +flatten-awaitables.as:43.9-43.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:45.9-45.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:47.9-47.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:52.9-52.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:54.9-54.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:56.9-56.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:66.9-66.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:68.9-68.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:70.9-70.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:75.9-75.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:77.9-77.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:79.9-79.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:85.9-85.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:87.9-87.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:89.9-89.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:94.9-94.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:96.9-96.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:98.9-98.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:103.9-103.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:105.9-105.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:107.9-107.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) +flatten-awaitables.as:112.9-112.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +flatten-awaitables.as:114.9-114.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (2, false) or + (0 or 1 or _, _) +flatten-awaitables.as:116.9-116.25: warning, this pattern consuming type + (Int, Bool, Text) +does not cover value + (3, false, _) or + (3, true, _) or + (0 or 1 or _, _, _) diff --git a/test/run-dfinity/ok/general-type-components.did.ok b/test/run-dfinity/ok/general-type-components.did.ok new file mode 100644 index 00000000000..4273bb16561 --- /dev/null +++ b/test/run-dfinity/ok/general-type-components.did.ok @@ -0,0 +1,5 @@ +type T/14 = Int; +type Int = int; +service A { +f : () -> () oneway; +} diff --git a/test/run-dfinity/ok/hello-world-async.did.ok b/test/run-dfinity/ok/hello-world-async.did.ok new file mode 100644 index 00000000000..665301cdcb2 --- /dev/null +++ b/test/run-dfinity/ok/hello-world-async.did.ok @@ -0,0 +1,4 @@ +service a { +go : () -> () oneway; +world : () -> () oneway; +} diff --git a/test/run-dfinity/ok/hello-world-await.did.ok b/test/run-dfinity/ok/hello-world-await.did.ok new file mode 100644 index 00000000000..2a830c0a0d7 --- /dev/null +++ b/test/run-dfinity/ok/hello-world-await.did.ok @@ -0,0 +1,6 @@ +type Text = text; +service a { +go : () -> (record {}); +hello : () -> (Text); +world : () -> (Text); +} diff --git a/test/run-dfinity/ok/hello-world-message.did.ok b/test/run-dfinity/ok/hello-world-message.did.ok new file mode 100644 index 00000000000..d6da6f01712 --- /dev/null +++ b/test/run-dfinity/ok/hello-world-message.did.ok @@ -0,0 +1,3 @@ +service anon_hello-world-message { +hello : () -> () oneway; +} diff --git a/test/run-dfinity/ok/hello-world-message2.did.ok b/test/run-dfinity/ok/hello-world-message2.did.ok new file mode 100644 index 00000000000..4e2545e1f56 --- /dev/null +++ b/test/run-dfinity/ok/hello-world-message2.did.ok @@ -0,0 +1,3 @@ +service hello_world { +hello : () -> () oneway; +} diff --git a/test/run-dfinity/ok/hello-world2.did.ok b/test/run-dfinity/ok/hello-world2.did.ok new file mode 100644 index 00000000000..43f4aef3442 --- /dev/null +++ b/test/run-dfinity/ok/hello-world2.did.ok @@ -0,0 +1,3 @@ +service a { +hello : () -> () oneway; +} diff --git a/test/run-dfinity/ok/hello-world3.did.ok b/test/run-dfinity/ok/hello-world3.did.ok new file mode 100644 index 00000000000..c05798fab2a --- /dev/null +++ b/test/run-dfinity/ok/hello-world3.did.ok @@ -0,0 +1,5 @@ +service a { +go : () -> () oneway; +hello : () -> () oneway; +world : () -> () oneway; +} diff --git a/test/run-dfinity/ok/indirect-counter.did.ok b/test/run-dfinity/ok/indirect-counter.did.ok new file mode 100644 index 00000000000..88d86644fc4 --- /dev/null +++ b/test/run-dfinity/ok/indirect-counter.did.ok @@ -0,0 +1,4 @@ +service a { +inc : () -> () oneway; +print : () -> () oneway; +} diff --git a/test/run-dfinity/ok/reference-params.did.ok b/test/run-dfinity/ok/reference-params.did.ok new file mode 100644 index 00000000000..6e99db590f8 --- /dev/null +++ b/test/run-dfinity/ok/reference-params.did.ok @@ -0,0 +1,6 @@ +service e { +hello : () -> () oneway; +send_to : (func (service { +hello : () -> () oneway; +}) -> () oneway) -> () oneway; +} diff --git a/test/run-dfinity/ok/transpose.did.ok b/test/run-dfinity/ok/transpose.did.ok new file mode 100644 index 00000000000..d6c33bda95c --- /dev/null +++ b/test/run-dfinity/ok/transpose.did.ok @@ -0,0 +1,5 @@ +type Text = text; +type Int = int; +service foo { +transpose : (vec record {Int; Text}) -> (record {ints : vec Int; txts : vec Text}); +} diff --git a/test/run.sh b/test/run.sh index 5c1e84ad02d..4203591a46b 100755 --- a/test/run.sh +++ b/test/run.sh @@ -177,6 +177,11 @@ do then if [ $DFINITY = 'yes' ] then + $ECHO -n " [idl]" + $ASC $ASC_FLAGS $EXTRA_ASC_FLAGS --idl $base.as -o $out/$base.did 2> $out/$base.idl.stderr + normalize $out/$base.idl.stderr + diff_files="$diff_files $base.did $base.idl.stderr" + $ECHO -n " [dvm]" $DVM_WRAPPER $out/$base.wasm $base.as > $out/$base.dvm-run 2>&1 normalize $out/$base.dvm-run @@ -227,8 +232,7 @@ do then $ECHO -n " [js]" $DIDC --js $base.did -o $out/$base.js >& $out/$base.js.out - diff_files="$diff_files $base.js.out" - diff_files="$diff_files $base.js" + diff_files="$diff_files $base.js.out $base.js" if [ -e $out/$base.js ] then From dea8394023c9b46c6d9be3e110c8d911578adb63 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Fri, 2 Aug 2019 16:25:37 -0700 Subject: [PATCH 0332/1176] more tests --- src/exes/asc.ml | 22 ++++++------- test/Makefile | 4 +++ test/as-idl/Makefile | 12 +++++++ test/as-idl/counter.as | 49 +++++++++++++++++++++++++++++ test/as-idl/ok/counter.did.ok | 6 ++++ test/as-idl/ok/pa_cars.did.ok | 17 ++++++++++ test/as-idl/ok/result.idl.stderr.ok | 1 + test/as-idl/pa_cars.as | 42 +++++++++++++++++++++++++ test/as-idl/result.as | 12 +++++++ test/run.sh | 23 ++++++++++++-- 10 files changed, 175 insertions(+), 13 deletions(-) create mode 100644 test/as-idl/Makefile create mode 100644 test/as-idl/counter.as create mode 100644 test/as-idl/ok/counter.did.ok create mode 100644 test/as-idl/ok/pa_cars.did.ok create mode 100644 test/as-idl/ok/result.idl.stderr.ok create mode 100644 test/as-idl/pa_cars.as create mode 100644 test/as-idl/result.as diff --git a/src/exes/asc.ml b/src/exes/asc.ml index fdaf85d14fd..d2402f72833 100644 --- a/src/exes/asc.ml +++ b/src/exes/asc.ml @@ -102,18 +102,18 @@ let process_files files : unit = printf "%s\n%!" banner; exit_on_none (Pipeline.run_files_and_stdin files) | Check -> - Diag.run (Pipeline.check_files files) + Diag.run (Pipeline.check_files files) | Idl -> - let prog = Diag.run (Pipeline.generate_idl files) in - let idl_code = Idllib.Arrange_idl.string_of_prog prog in - if !out_file = "" then - (printf "%s" idl_code; - ignore (Diag.run (Idllib.Pipeline.check_prog prog))) - else begin - ignore (Diag.run (Idllib.Pipeline.check_prog prog)); - let oc = open_out !out_file in - output_string oc idl_code; close_out oc - end + let prog = Diag.run (Pipeline.generate_idl files) in + let idl_code = Idllib.Arrange_idl.string_of_prog prog in + if !out_file = "" then + (printf "%s" idl_code; + ignore (Diag.run (Idllib.Pipeline.check_prog prog))) + else begin + ignore (Diag.run (Idllib.Pipeline.check_prog prog)); + let oc = open_out !out_file in + output_string oc idl_code; close_out oc + end | Compile -> fill_out_file files ".wasm"; let module_ = Diag.run Pipeline.(compile_files !compile_mode !link files) in diff --git a/test/Makefile b/test/Makefile index a349d1fd5c0..6689499ccb5 100644 --- a/test/Makefile +++ b/test/Makefile @@ -5,6 +5,7 @@ all: $(MAKE) -C repl $(MAKE) -C ld $(MAKE) -C idl + $(MAKE) -C as-idl $(MAKE) -C trap MAKE_PAR := $(MAKE) --no-print-directory --load-average -j $(shell getconf _NPROCESSORS_ONLN) --keep-going @@ -15,6 +16,7 @@ quick: $(MAKE_PAR) -C repl quick $(MAKE_PAR) -C ld quick $(MAKE_PAR) -C idl quick + $(MAKE_PAR) -C as-idl quick parallel: quick $(MAKE_PAR) -C run-dfinity quick @@ -40,6 +42,7 @@ accept: $(MAKE) -C repl accept $(MAKE) -C ld accept $(MAKE) -C idl accept + $(MAKE) -C as-idl accept $(MAKE) -C trap accept $(MAKE) -C trap check @@ -49,6 +52,7 @@ clean: $(MAKE) -C run-dfinity clean $(MAKE) -C repl clean $(MAKE) -C ld clean + $(MAKE) -C as-idl clean $(MAKE) -C idl clean $(MAKE) -C trap clean diff --git a/test/as-idl/Makefile b/test/as-idl/Makefile new file mode 100644 index 00000000000..942d9205bd9 --- /dev/null +++ b/test/as-idl/Makefile @@ -0,0 +1,12 @@ +RUNFLAGS = -i + +all: + ../run.sh $(RUNFLAGS) *.as + +accept: + ../run.sh $(RUNFLAGS) -a *.as + +clean: + rm -rf _out + +include ../*.mk diff --git a/test/as-idl/counter.as b/test/as-idl/counter.as new file mode 100644 index 00000000000..636588fa7ed --- /dev/null +++ b/test/as-idl/counter.as @@ -0,0 +1,49 @@ +// A simple Counter actor. + +actor class Counter(i : Int) { + var c = i; + + // Decrement counter + public func dec() { + show("dec", c); + c -= 1; + }; + + // Read counter, asynchronous + public func read() : async Int { c }; +}; + +// Dummy functions to show intermediate value in trace. +func show(note : Text, c : Int) {}; +func showAsync(note : Text, a : async Int) {}; + +// Create an actor. +let c = Counter(10); + +// Issue ten `dec` messages. +func testDec() { + var i : Int = 10; + while (i > 0) { + c.dec(); + i -= 1; + } +}; + +testDec(); + +// Issue ten `dec` & `read` messages. +func testRead() { + var i : Int = 10; + let _ = async { + while (i > 0) { + c.dec(); + let t = c.read(); + showAsync("before", t); + show("await", await t); + showAsync("after", t); + i -= 1; + } + } +}; + +testRead(); diff --git a/test/as-idl/ok/counter.did.ok b/test/as-idl/ok/counter.did.ok new file mode 100644 index 00000000000..034c524ba95 --- /dev/null +++ b/test/as-idl/ok/counter.did.ok @@ -0,0 +1,6 @@ +type Int = int; +type Counter = service { +dec : () -> () oneway; +read : () -> (Int); +}; +service c : Counter diff --git a/test/as-idl/ok/pa_cars.did.ok b/test/as-idl/ok/pa_cars.did.ok new file mode 100644 index 00000000000..ec810918233 --- /dev/null +++ b/test/as-idl/ok/pa_cars.did.ok @@ -0,0 +1,17 @@ +type User = record {name : Text}; +type TimeSpan = record {end : Int; start : Int}; +type Text = text; +type Result = opt record {reservationId : Text}; +type PACars = service { +verifyCarInformation : (User, Car) -> (opt func (Location, TimeSpan) -> (Result)); +}; +type Nat = nat; +type Location = record {lat : Float; long : Float}; +type Int = int; +type Float = float64; +type DMV = service { +check : (Car) -> (CarInfo); +}; +type CarInfo = record {expires : Nat; isValid : Bool; model : Text; plate : Text; wasStolen : Bool}; +type Car = record {model : Text; plate : Text}; +type Bool = bool; diff --git a/test/as-idl/ok/result.idl.stderr.ok b/test/as-idl/ok/result.idl.stderr.ok new file mode 100644 index 00000000000..d91ebdfe58d --- /dev/null +++ b/test/as-idl/ok/result.idl.stderr.ok @@ -0,0 +1 @@ +(unknown location): type error, unbound type identifier Result diff --git a/test/as-idl/pa_cars.as b/test/as-idl/pa_cars.as new file mode 100644 index 00000000000..80a51e39899 --- /dev/null +++ b/test/as-idl/pa_cars.as @@ -0,0 +1,42 @@ +// Stateless Suspendable Workflow +// ============================== + +// Creating an Account for the PA parking service + +// - Client: Insert Car data and holder's name +// - Server: Validate car is registered under the given name +// - Client: Pick a parking spot from a Google Map like interface + time +// - Server: Register the parking spot for the user +type Car = { model : Text; plate : Text }; +type DMV = actor { check : Car -> async CarInfo }; +type CarInfo = { + model : Text; + plate : Text; + isValid : Bool; + wasStolen : Bool; + expires : Nat; +}; + +actor class PACars(dmv : DMV) { + public func verifyCarInformation(user : User, car : Car) : async ?(shared (Location, TimeSpan) -> async Result) { + let carInfo = await dmv.check(car); + if (carInfo.isValid and not carInfo.wasStolen) { + return ?(shared func (location, time) : async Result { + return reserveSpot(user, carInfo, location, time); + }) + } else { + return null; + } + }; + + private func reserveSpot(user : User, carInfo : CarInfo, location : Location, timeSpan : TimeSpan) : Result { + // Do the actual work of registering the parking spot for the + // given car in the given time span + return null; + }; + + public type Location = { lat : Float; long : Float }; + public type TimeSpan = { start : Int; end : Int }; + public type Result = ?({ reservationId : Text }); + public type User = { name : Text }; +}; diff --git a/test/as-idl/result.as b/test/as-idl/result.as new file mode 100644 index 00000000000..9c7cfa1ccc9 --- /dev/null +++ b/test/as-idl/result.as @@ -0,0 +1,12 @@ +type Result = { + #ok:Ok; + #err:Err; +}; +actor { + public func f(x:?Nat):async Result { + switch x { + case (? x) {#ok x}; + case null {#err "error"}; + } + }; +} diff --git a/test/run.sh b/test/run.sh index 4203591a46b..46ceba0ee90 100755 --- a/test/run.sh +++ b/test/run.sh @@ -9,6 +9,7 @@ # -a: Update the files in ok/ # -d: Compile without -no-dfinity-api, uses dvm to run # -s: Be silent in sunny-day execution +# -i: Only check as to idl generation # function realpath() { @@ -18,6 +19,7 @@ function realpath() { ACCEPT=no DFINITY=no +CHECK_IDL_ONLY=no EXTRA_ASC_FLAGS= ASC=${ASC:-$(realpath $(dirname $0)/../src/asc)} AS_LD=${AS_LD:-$(realpath $(dirname $0)/../src/as-ld)} @@ -28,7 +30,7 @@ DVM_WRAPPER=$(realpath $(dirname $0)/dvm.sh) JSCLIENT=${JSCLIENT:-$(realpath $(dirname $0)/../../dev/experimental/js-dfinity-client)} ECHO=echo -while getopts "ads" o; do +while getopts "adsi" o; do case "${o}" in a) ACCEPT=yes @@ -39,6 +41,9 @@ while getopts "ads" o; do s) ECHO=true ;; + i) + CHECK_IDL_ONLY=yes + ;; esac done @@ -122,6 +127,15 @@ do if [ "$tc_succeeded" -eq 0 ]; then + if [ $CHECK_IDL_ONLY = 'yes' ] + then + $ECHO -n " [idl]" + $ASC $ASC_FLAGS $EXTRA_ASC_FLAGS --idl $base.as -o $out/$base.did 2> $out/$base.idl.stderr + normalize $out/$base.did + normalize $out/$base.idl.stderr + diff_files="$diff_files $base.did $base.idl.stderr" + else + if [ "$SKIP_RUNNING" != yes ] then # Interpret @@ -179,9 +193,10 @@ do then $ECHO -n " [idl]" $ASC $ASC_FLAGS $EXTRA_ASC_FLAGS --idl $base.as -o $out/$base.did 2> $out/$base.idl.stderr + normalize $out/$base.did normalize $out/$base.idl.stderr diff_files="$diff_files $base.did $base.idl.stderr" - + $ECHO -n " [dvm]" $DVM_WRAPPER $out/$base.wasm $base.as > $out/$base.dvm-run 2>&1 normalize $out/$base.dvm-run @@ -194,6 +209,7 @@ do fi fi fi + fi fi elif [ ${file: -3} == ".sh" ] then @@ -232,6 +248,8 @@ do then $ECHO -n " [js]" $DIDC --js $base.did -o $out/$base.js >& $out/$base.js.out + normalize $out/$base.js + normalize $out/$base.js.out diff_files="$diff_files $base.js.out $base.js" if [ -e $out/$base.js ] @@ -239,6 +257,7 @@ do $ECHO -n " [node]" export NODE_PATH=$NODE_PATH:$JSCLIENT:$JSCLIENT/src node $out/$base.js > $out/$base.err 2>&1 + normalize $out/$base.err diff_files="$diff_files $base.err" fi fi From b324d1a267f56328a028235a8aa48b6298fa9e65 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Fri, 2 Aug 2019 16:29:36 -0700 Subject: [PATCH 0333/1176] tab --- test/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/Makefile b/test/Makefile index 6689499ccb5..254233837e3 100644 --- a/test/Makefile +++ b/test/Makefile @@ -5,7 +5,7 @@ all: $(MAKE) -C repl $(MAKE) -C ld $(MAKE) -C idl - $(MAKE) -C as-idl + $(MAKE) -C as-idl $(MAKE) -C trap MAKE_PAR := $(MAKE) --no-print-directory --load-average -j $(shell getconf _NPROCESSORS_ONLN) --keep-going @@ -42,7 +42,7 @@ accept: $(MAKE) -C repl accept $(MAKE) -C ld accept $(MAKE) -C idl accept - $(MAKE) -C as-idl accept + $(MAKE) -C as-idl accept $(MAKE) -C trap accept $(MAKE) -C trap check @@ -52,7 +52,7 @@ clean: $(MAKE) -C run-dfinity clean $(MAKE) -C repl clean $(MAKE) -C ld clean - $(MAKE) -C as-idl clean + $(MAKE) -C as-idl clean $(MAKE) -C idl clean $(MAKE) -C trap clean From ff3904208bd74450e79506b48ea2ec94ce7a28de Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Fri, 2 Aug 2019 20:51:27 -0700 Subject: [PATCH 0334/1176] more tests --- test/as-idl/fields.as | 12 ++++++++++++ test/as-idl/inline_result.as | 15 +++++++++++++++ test/as-idl/ok/fields.idl.stderr.ok | 1 + test/as-idl/ok/inline_result.did.ok | 7 +++++++ test/as-idl/result.as | 3 +++ test/run.sh | 14 ++++++++++++++ 6 files changed, 52 insertions(+) create mode 100644 test/as-idl/fields.as create mode 100644 test/as-idl/inline_result.as create mode 100644 test/as-idl/ok/fields.idl.stderr.ok create mode 100644 test/as-idl/ok/inline_result.did.ok diff --git a/test/as-idl/fields.as b/test/as-idl/fields.as new file mode 100644 index 00000000000..51dd1fb4146 --- /dev/null +++ b/test/as-idl/fields.as @@ -0,0 +1,12 @@ +type Info = { + name : Text; + // TODO not accepted by parser + //_1_ : Info; + //_34_5_ : Text; + name_ : Nat; +}; +type Tup = (Text, Info, Text, Nat); +actor Server { + public func f_(user1 : Info, user2 : Tup) : async () { + }; +} diff --git a/test/as-idl/inline_result.as b/test/as-idl/inline_result.as new file mode 100644 index 00000000000..ccca2218ff6 --- /dev/null +++ b/test/as-idl/inline_result.as @@ -0,0 +1,15 @@ +actor { + type Result = { + #ok:Ok; + #err:Err; + }; + public func f(x:?Nat):async Result { + switch x { + case (? x) {#ok x}; + case null {#err "error"}; + } + }; + public func g(x:Result):async Result { + #ok(1); + }; +} diff --git a/test/as-idl/ok/fields.idl.stderr.ok b/test/as-idl/ok/fields.idl.stderr.ok new file mode 100644 index 00000000000..63274d81be3 --- /dev/null +++ b/test/as-idl/ok/fields.idl.stderr.ok @@ -0,0 +1 @@ +(unknown location): type error, field name name hash collision with field name diff --git a/test/as-idl/ok/inline_result.did.ok b/test/as-idl/ok/inline_result.did.ok new file mode 100644 index 00000000000..f86cf46f63b --- /dev/null +++ b/test/as-idl/ok/inline_result.did.ok @@ -0,0 +1,7 @@ +type Text = text; +type Nat = nat; +type Int = int; +service anon_inline_result { +f : (opt Nat) -> (variant {err : Text; ok : Nat}); +g : (variant {err : Text; ok : Nat}) -> (variant {err : record {}; ok : Int}); +} diff --git a/test/as-idl/result.as b/test/as-idl/result.as index 9c7cfa1ccc9..0e6ead46b34 100644 --- a/test/as-idl/result.as +++ b/test/as-idl/result.as @@ -9,4 +9,7 @@ actor { case null {#err "error"}; } }; + public func g(x:Result):async Result { + #ok(1); + }; } diff --git a/test/run.sh b/test/run.sh index 46ceba0ee90..2f88725c007 100755 --- a/test/run.sh +++ b/test/run.sh @@ -131,9 +131,16 @@ do then $ECHO -n " [idl]" $ASC $ASC_FLAGS $EXTRA_ASC_FLAGS --idl $base.as -o $out/$base.did 2> $out/$base.idl.stderr + idl_succeeded=$? normalize $out/$base.did normalize $out/$base.idl.stderr diff_files="$diff_files $base.did $base.idl.stderr" + if [ "$idl_succeeded" -eq 0 ]; + then + $ECHO -n " [didc]" + $DIDC --check $out/$base.did > $out/$base.did.tc 2>&1 + diff_files="$diff_files $base.did.tc" + fi else if [ "$SKIP_RUNNING" != yes ] @@ -193,9 +200,16 @@ do then $ECHO -n " [idl]" $ASC $ASC_FLAGS $EXTRA_ASC_FLAGS --idl $base.as -o $out/$base.did 2> $out/$base.idl.stderr + idl_succeeded=$? normalize $out/$base.did normalize $out/$base.idl.stderr diff_files="$diff_files $base.did $base.idl.stderr" + if [ "$idl_succeeded" -eq 0 ]; + then + $ECHO -n " [didc]" + $DIDC --check $out/$base.did > $out/$base.did.tc 2>&1 + diff_files="$diff_files $base.did.tc" + fi $ECHO -n " [dvm]" $DVM_WRAPPER $out/$base.wasm $base.as > $out/$base.dvm-run 2>&1 From fe89fa26ebe0dbf4e55aa1bdf17e6edb9f22a021 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Fri, 2 Aug 2019 21:32:44 -0700 Subject: [PATCH 0335/1176] fix tests --- src/as_idl/as_to_idl.ml | 13 ++++++++++--- test/run-dfinity/ok/empty-actor.did.ok | 2 +- test/run-dfinity/ok/general-type-components.did.ok | 2 +- test/run-dfinity/ok/hello-world-message.did.ok | 2 +- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/as_idl/as_to_idl.ml b/src/as_idl/as_to_idl.ml index f55b5d5f750..5229d752ada 100644 --- a/src/as_idl/as_to_idl.ml +++ b/src/as_idl/as_to_idl.ml @@ -9,7 +9,14 @@ type label = Nat of Lib.Uint32.t | Id of string let dec_env = ref ConEnv.empty +let normalize str = + let illegal_chars = ['-'; '/'] in + String.map (fun c -> if List.mem c illegal_chars then '_' else c) str + +let string_of_con c = normalize (string_of_con c) + let unescape lab : label = + let lab = normalize lab in let len = String.length lab in try if lab.[len-1] = '_' then begin if lab.[0] = '_' then @@ -20,7 +27,7 @@ let unescape lab : label = if len >= 2 && lab.[len-1] = '_' then Id (String.sub lab 0 (len-1)) else Id lab - + let prim p = match p with | Null -> I.Null @@ -134,14 +141,14 @@ let chase_decs env = let gather_decs () = ConEnv.fold (fun c t list -> - let dec = I.TypD (Con.to_string c @@ no_region, t) @@ no_region in + let dec = I.TypD (string_of_con c @@ no_region, t) @@ no_region in dec::list ) !dec_env [] let actor progs = let open E in let find_last_actor (prog : prog) = - let anon = "anon_" ^ (Filename.remove_extension prog.note) in + let anon = normalize ("anon_" ^ (Filename.remove_extension prog.note)) in let check_dec d t def = match d.it with | ExpD _ -> Some (anon, t) diff --git a/test/run-dfinity/ok/empty-actor.did.ok b/test/run-dfinity/ok/empty-actor.did.ok index dc6de6a63c3..66928f4d759 100644 --- a/test/run-dfinity/ok/empty-actor.did.ok +++ b/test/run-dfinity/ok/empty-actor.did.ok @@ -1,2 +1,2 @@ -service anon_empty-actor { +service anon_empty_actor { } diff --git a/test/run-dfinity/ok/general-type-components.did.ok b/test/run-dfinity/ok/general-type-components.did.ok index 4273bb16561..56d106595e9 100644 --- a/test/run-dfinity/ok/general-type-components.did.ok +++ b/test/run-dfinity/ok/general-type-components.did.ok @@ -1,4 +1,4 @@ -type T/14 = Int; +type T_14 = Int; type Int = int; service A { f : () -> () oneway; diff --git a/test/run-dfinity/ok/hello-world-message.did.ok b/test/run-dfinity/ok/hello-world-message.did.ok index d6da6f01712..d63c9fb0b5b 100644 --- a/test/run-dfinity/ok/hello-world-message.did.ok +++ b/test/run-dfinity/ok/hello-world-message.did.ok @@ -1,3 +1,3 @@ -service anon_hello-world-message { +service anon_hello_world_message { hello : () -> () oneway; } From 2f18ab84b7581326634130d842a8cd3bc993c447 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 5 Aug 2019 14:18:19 +0200 Subject: [PATCH 0336/1176] Deserialization: Keep mutable buffer pointer in memory (#608) This is a pure refactoring, and maybe it makes sense to merge the refactoring first, and then base new features (#602) on top of that. --- rts/idl.c | 79 ++++++++++------- src/codegen/compile.ml | 189 ++++++++++++++++++++++++++--------------- 2 files changed, 167 insertions(+), 101 deletions(-) diff --git a/rts/idl.c b/rts/idl.c index b3b9013cc6d..020597ef10b 100644 --- a/rts/idl.c +++ b/rts/idl.c @@ -1,16 +1,31 @@ #include "rts.h" +/* +An abstraction for a buffer with and end-pointer. + +This mirrors module Serialization.Buf in `compile.ml` +*/ + +typedef struct { + uint8_t *p; + uint8_t *e; +} buf; + +uint8_t read_byte(buf *buf) { + if (buf->p >= buf->e) (idl_trap()); + return ((buf->p)++)[0]; +} + // Initially, we just want to be able to zoom past the type description // TODO: Defensive programming // (not going past the size of the message, trapping if leb128 does not fit in int) -uint32_t read_leb128(char **ptr, char *end) { +uint32_t read_leb128(buf *buf) { uint32_t r = 0; unsigned int s = 0; uint8_t b; do { - if (*ptr >= end) (idl_trap()); - b = *((*ptr)++); + b = read_byte(buf); if (s == 28 && !((b & (uint8_t)0xF0) == 0x00)) { // the 5th byte needs to be the last, and it must contribute at most 4 bits // else we have an int overflow @@ -22,13 +37,12 @@ uint32_t read_leb128(char **ptr, char *end) { return r; } -int32_t read_sleb128(char **ptr, char *end) { +int32_t read_sleb128(buf *buf) { uint32_t r = 0; unsigned int s = 0; uint8_t b; do { - if (*ptr >= end) (idl_trap()); - b = *((*ptr)++); + b = read_byte(buf); if (s == 28 && !((b & (uint8_t)0xF0) == 0x00 || (b & (uint8_t)0xF0) == 0x70)) { // the 5th byte needs to be the last, and it must contribute at most 4 bits // else we have an int overflow @@ -44,58 +58,57 @@ int32_t read_sleb128(char **ptr, char *end) { return r; } -export char *skip_idl_header(char *ptr, char *end) { +export void skip_idl_header(buf *buf) { // Magic bytes - if (*ptr++ != 'D') idl_trap(); - if (*ptr++ != 'I') idl_trap(); - if (*ptr++ != 'D') idl_trap(); - if (*ptr++ != 'L') idl_trap(); + if (read_byte(buf) != 'D') idl_trap(); + if (read_byte(buf) != 'I') idl_trap(); + if (read_byte(buf) != 'D') idl_trap(); + if (read_byte(buf) != 'L') idl_trap(); // Size of type list - for (int count = read_leb128(&ptr,end); count > 0; count --) { - int ty = read_sleb128(&ptr,end); + for (int count = read_leb128(buf); count > 0; count --) { + int ty = read_sleb128(buf); if (ty >= -17) { idl_trap(); // illegal } else if (ty == -18) { // opt - read_sleb128(&ptr,end); + read_sleb128(buf); } else if (ty == -19) { // vec - read_sleb128(&ptr,end); + read_sleb128(buf); } else if (ty == -20) { // record - for (int n = read_leb128(&ptr,end); n > 0; n--) { - read_leb128(&ptr,end); - read_sleb128(&ptr,end); + for (int n = read_leb128(buf); n > 0; n--) { + read_leb128(buf); + read_sleb128(buf); } } else if (ty == -21) { // variant - for (int n = read_leb128(&ptr,end); n > 0; n--) { - read_leb128(&ptr,end); - read_sleb128(&ptr,end); + for (int n = read_leb128(buf); n > 0; n--) { + read_leb128(buf); + read_sleb128(buf); } } else if (ty == -22) { // func // arg types - for (int n = read_leb128(&ptr,end); n > 0; n--) { - read_sleb128(&ptr,end); + for (int n = read_leb128(buf); n > 0; n--) { + read_sleb128(buf); } // ret types - for (int n = read_leb128(&ptr,end); n > 0; n--) { - read_sleb128(&ptr,end); + for (int n = read_leb128(buf); n > 0; n--) { + read_sleb128(buf); } // annotations - for (int n = read_leb128(&ptr,end); n > 0; n--) { - ptr++; + for (int n = read_leb128(buf); n > 0; n--) { + (buf->p)++; } } else if (ty == -23) { // service - for (int n = read_leb128(&ptr,end); n > 0; n--) { + for (int n = read_leb128(buf); n > 0; n--) { // name - unsigned int size = read_leb128(&ptr,end); - ptr += size; + unsigned int size = read_leb128(buf); + (buf->p) += size; // type - read_sleb128(&ptr,end); + read_sleb128(buf); } } else { // no support for future types yet idl_trap(); } } - read_sleb128(&ptr,end); // index - return ptr; + read_sleb128(buf); // index } diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index caebe928c0f..8399a9a00b1 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -536,7 +536,7 @@ module RTS = struct let system_imports env = E.add_func_import env "rts" "as_memcpy" [I32Type; I32Type; I32Type] []; E.add_func_import env "rts" "version" [] [I32Type]; - E.add_func_import env "rts" "skip_idl_header" [I32Type; I32Type] [I32Type]; + E.add_func_import env "rts" "skip_idl_header" [I32Type] []; E.add_func_import env "rts" "bigint_of_word32" [I32Type] [I32Type]; E.add_func_import env "rts" "bigint_of_word32_signed" [I32Type] [I32Type]; E.add_func_import env "rts" "bigint_to_word32_wrap" [I32Type] [I32Type]; @@ -738,14 +738,35 @@ module Stack = struct wasm-l would), this way stack overflow would cause out-of-memory, and not just overwrite static data. - We don’t use the stack space (yet), but we could easily start to use it for - scratch space, as long as we don’t need more than 64k. + We sometimes use the stack space if we need small amounts of scratch space. *) let stack_global = 2l let end_of_stack = page_size (* 64k of stack *) + let get_stack_ptr = G.i (GlobalGet (nr stack_global)) + let set_stack_ptr = G.i (GlobalSet (nr stack_global)) + + let alloc_words env n = + get_stack_ptr ^^ + compile_unboxed_const (Int32.mul n Heap.word_size) ^^ + G.i (Binary (Wasm.Values.I32 I32Op.Sub)) ^^ + set_stack_ptr ^^ + get_stack_ptr + + let free_words env n = + get_stack_ptr ^^ + compile_unboxed_const (Int32.mul n Heap.word_size) ^^ + G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ + set_stack_ptr + + let with_words env name n f = + let (set_x, get_x) = new_local env name in + alloc_words env n ^^ set_x ^^ + f get_x ^^ + free_words env n + end (* Stack *) module ElemHeap = struct @@ -3581,110 +3602,141 @@ module Serialization = struct get_ref_buf ) + module Buf = struct + (* + Combinators to safely read from a dynamic buffer. + + We represent a buffer by a pointer to two words in memory (usually allocated + on the shadow stack): The first is a pointer to the current position of the buffer, + the second one a pointer to the end (to check out-of-bounds). + + Code that reads from this buffer will update the former, i.e. it is mutuable. + + The format is compatible with C (pointer to a struct) and avoids the need for the + multi-value extension that we used before to return both parse result _and_ + updated pointer. + + All pointers here are unskewed! + *) + + let get_ptr get_buf = + get_buf ^^ G.i (Load {ty = I32Type; align = 2; offset = 0l; sz = None}) + let _get_end get_buf = + get_buf ^^ G.i (Load {ty = I32Type; align = 2; offset = Heap.word_size; sz = None}) + let set_ptr get_buf new_val = + get_buf ^^ new_val ^^ G.i (Store {ty = I32Type; align = 2; offset = 0l; sz = None}) + let set_end get_buf new_val = + get_buf ^^ new_val ^^ G.i (Store {ty = I32Type; align = 2; offset = Heap.word_size; sz = None}) + let set_size get_buf get_size = + set_end get_buf + (get_ptr get_buf ^^ get_size ^^ G.i (Binary (Wasm.Values.I32 I32Op.Add))) + + let alloc env f = Stack.with_words env "buf" 2l f + + let advance get_buf get_delta = + set_ptr get_buf (get_ptr get_buf ^^ get_delta ^^ G.i (Binary (Wasm.Values.I32 I32Op.Add))) + + let read_byte get_buf = + get_ptr get_buf ^^ + G.i (Load {ty = I32Type; align = 0; offset = 0l; sz = Some (Wasm.Memory.Pack8, Wasm.Memory.ZX)}) ^^ + advance get_buf (compile_unboxed_const 1l) + + let read_word env get_buf = + (* See TODO (leb128 for i32) *) + get_ptr get_buf ^^ + BigNum.compile_load_from_data_buf_unsigned env ^^ + let (set_leb_len, get_leb_len) = new_local env "leb_len" in + set_leb_len ^^ + advance get_buf get_leb_len ^^ + BigNum.to_word32 env + + + end (* Buf *) + let rec deserialize_go env t = let open Type in let t = normalize t in let name = "@deserialize_go<" ^ typ_id t ^ ">" in - Func.share_code2 env name (("data_buffer", I32Type), ("ref_buffer", I32Type)) [I32Type; I32Type; I32Type] + Func.share_code2 env name (("data_buffer", I32Type), ("ref_buffer", I32Type)) [I32Type] (fun env get_data_buf get_ref_buf -> - let set_data_buf = G.i (LocalSet (nr 0l)) in - let set_ref_buf = G.i (LocalSet (nr 1l)) in - - (* Some combinators for reading values *) - let advance_data_buf = - get_data_buf ^^ G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ set_data_buf in - let advance_ref_buf = - get_ref_buf ^^ compile_add_const Heap.word_size ^^ set_ref_buf in - let read_byte = - get_data_buf ^^ - G.i (Load {ty = I32Type; align = 0; offset = 0l; sz = Some (Wasm.Memory.Pack8, Wasm.Memory.ZX)}) ^^ - compile_unboxed_const 1l ^^ advance_data_buf - in - - let read_word = - (* See TODO (leb128 for i32) *) - get_data_buf ^^ - BigNum.compile_load_from_data_buf_unsigned env ^^ - advance_data_buf ^^ - BigNum.to_word32 env - in - - let read env t = + let go env t = get_data_buf ^^ get_ref_buf ^^ - deserialize_go env t ^^ - set_ref_buf ^^ - set_data_buf + deserialize_go env t in (* Now the actual deserialization *) begin match t with | Prim Nat -> - get_data_buf ^^ + Buf.get_ptr get_data_buf ^^ BigNum.compile_load_from_data_buf_unsigned env ^^ - advance_data_buf + let (set_leb_len, get_leb_len) = new_local env "leb_len" in + set_leb_len ^^ + Buf.advance get_data_buf get_leb_len | Prim Int -> - get_data_buf ^^ + Buf.get_ptr get_data_buf ^^ BigNum.compile_load_from_data_buf_signed env ^^ - advance_data_buf + let (set_leb_len, get_leb_len) = new_local env "leb_len" in + set_leb_len ^^ + Buf.advance get_data_buf get_leb_len | Prim (Int64|Nat64|Word64) -> - get_data_buf ^^ + Buf.get_ptr get_data_buf ^^ G.i (Load {ty = I64Type; align = 2; offset = 0l; sz = None}) ^^ BoxedWord64.box env ^^ - compile_unboxed_const 8l ^^ advance_data_buf (* 64 bit *) + Buf.advance get_data_buf (compile_unboxed_const 8l) | Prim (Int32|Nat32|Word32) -> - get_data_buf ^^ + Buf.get_ptr get_data_buf ^^ G.i (Load {ty = I32Type; align = 0; offset = 0l; sz = None}) ^^ BoxedSmallWord.box env ^^ - compile_unboxed_const 4l ^^ advance_data_buf + Buf.advance get_data_buf (compile_unboxed_const 4l) | Prim (Int16|Nat16|Word16) -> - get_data_buf ^^ + Buf.get_ptr get_data_buf ^^ G.i (Load {ty = I32Type; align = 0; offset = 0l; sz = Some (Wasm.Memory.Pack16, Wasm.Memory.ZX)}) ^^ UnboxedSmallWord.msb_adjust Word16 ^^ - compile_unboxed_const 2l ^^ advance_data_buf + Buf.advance get_data_buf (compile_unboxed_const 2l) | Prim (Int8|Nat8|Word8) -> - get_data_buf ^^ + Buf.get_ptr get_data_buf ^^ G.i (Load {ty = I32Type; align = 0; offset = 0l; sz = Some (Wasm.Memory.Pack8, Wasm.Memory.ZX)}) ^^ UnboxedSmallWord.msb_adjust Word8 ^^ - compile_unboxed_const 1l ^^ advance_data_buf + Buf.advance get_data_buf (compile_unboxed_const 1l) | Prim Bool -> - get_data_buf ^^ + Buf.get_ptr get_data_buf ^^ G.i (Load {ty = I32Type; align = 0; offset = 0l; sz = Some (Wasm.Memory.Pack8, Wasm.Memory.ZX)}) ^^ - compile_unboxed_const 1l ^^ advance_data_buf + Buf.advance get_data_buf (compile_unboxed_const 1l) | Tup ts -> - G.concat_map (fun t -> read env t) ts ^^ + G.concat_map (fun t -> go env t) ts ^^ Tuple.from_stack env (List.length ts) | Obj (Object, fs) -> Object.lit_raw env (List.map (fun (_h,f) -> - f.Type.lab, fun () -> read env f.typ + f.Type.lab, fun () -> go env f.typ ) (sort_by_hash fs)) | Array t -> let (set_len, get_len) = new_local env "len" in let (set_x, get_x) = new_local env "x" in - read_word ^^ set_len ^^ + Buf.read_word env get_data_buf ^^ set_len ^^ get_len ^^ Arr.alloc env ^^ set_x ^^ get_len ^^ from_0_to_n env (fun get_i -> get_x ^^ get_i ^^ Arr.idx env ^^ - read env t ^^ store_ptr + go env t ^^ store_ptr ) ^^ get_x | Prim Null -> Opt.null | Opt t -> - read_byte ^^ + Buf.read_byte get_data_buf ^^ compile_eq_const 0l ^^ G.if_ (ValBlockType (Some I32Type)) ( Opt.null ) - ( Opt.inject env (read env t) ) + ( Opt.inject env (go env t) ) | Variant vs -> let (set_tag, get_tag) = new_local env "tag" in - read_word ^^ set_tag ^^ + Buf.read_word env get_data_buf ^^ set_tag ^^ List.fold_right (fun (i, {lab = l; typ = t}) continue -> get_tag ^^ compile_eq_const (Int32.of_int i) ^^ G.if_ (ValBlockType (Some I32Type)) - ( Variant.inject env l (read env t) ) + ( Variant.inject env l (go env t) ) continue ) ( List.mapi (fun i (_h, f) -> (i,f)) (sort_by_hash vs) ) @@ -3692,29 +3744,27 @@ module Serialization = struct | Prim Text -> let (set_len, get_len) = new_local env "len" in let (set_x, get_x) = new_local env "x" in - read_word ^^ set_len ^^ + Buf.read_word env get_data_buf ^^ set_len ^^ get_len ^^ Text.alloc env ^^ set_x ^^ get_x ^^ Text.payload_ptr_unskewed ^^ - get_data_buf ^^ + Buf.get_ptr get_data_buf ^^ get_len ^^ Heap.memcpy env ^^ - get_len ^^ advance_data_buf ^^ + Buf.advance get_data_buf get_len ^^ get_x | (Func _ | Obj (Actor, _)) -> - get_ref_buf ^^ + Buf.get_ptr get_ref_buf ^^ load_unskewed_ptr ^^ Dfinity.box_reference env ^^ - advance_ref_buf + Buf.advance get_ref_buf (compile_unboxed_const Heap.word_size) | Non -> E.trap_with env "deserializing value of type None" | _ -> todo_trap env "deserialize" (Arrange_ir.typ t) - end ^^ - get_data_buf ^^ - get_ref_buf + end ) let serialize env t = @@ -3880,14 +3930,17 @@ module Serialization = struct compile_unboxed_const 0l ^^ Dfinity.system_call env "data_internalize" ^^ - (* Go! *) - get_data_start ^^ - get_data_start ^^ get_data_size ^^ G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ - E.call_import env "rts" "skip_idl_header" ^^ - get_refs_start ^^ compile_add_const Heap.word_size ^^ - deserialize_go env t ^^ - G.i Drop ^^ - G.i Drop + (* Set up read buffers *) + Buf.alloc env (fun get_data_buf -> Buf.alloc env (fun get_ref_buf -> + Buf.set_ptr get_data_buf get_data_start ^^ + Buf.set_size get_data_buf get_data_size ^^ + Buf.set_ptr get_ref_buf (get_refs_start ^^ compile_add_const Heap.word_size) ^^ + Buf.set_size get_ref_buf (get_refs_size ^^ compile_sub_const 1l ^^ compile_mul_const Heap.word_size) ^^ + + (* Go! *) + get_data_buf ^^ E.call_import env "rts" "skip_idl_header" ^^ + get_data_buf ^^ get_ref_buf ^^ deserialize_go env t + )) ) let dfinity_type t = From 7dbb8715992ee2112c415547394ccb74fd721650 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 5 Aug 2019 16:13:10 +0200 Subject: [PATCH 0337/1176] asc: Add add -no-fake-op flag (#606) for internal use only (but I hope that we can soon drop the whole fake OP stuff anyways, has been around for embarrassing long) --- src/codegen/compile.ml | 12 +++++++++--- src/codegen/flags.ml | 1 + src/exes/asc.ml | 1 + 3 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 src/codegen/flags.ml diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 8399a9a00b1..f3d14eb6e0e 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -2855,12 +2855,16 @@ module Dfinity = struct (* Create an empty message *) let empty_f = Func.of_body env [] [] (fun env1 -> (* Set up memory *) - G.i (Call (nr (E.built_in env1 "restore_mem"))) ^^ + (if !Flags.fake_orthogonal_persistence + then G.i (Call (nr (E.built_in env1 "restore_mem"))) + else G.nop) ^^ (* Collect garbage *) G.i (Call (nr (E.built_in env1 "collect"))) ^^ (* Save memory *) - G.i (Call (nr (E.built_in env1 "save_mem"))) - ) in + (if !Flags.fake_orthogonal_persistence + then G.i (Call (nr (E.built_in env1 "save_mem"))) + else G.nop) + ) in let fi = E.add_fun env "start_stub" empty_f in E.add_export env (nr { name = Wasm.Utf8.decode "start"; @@ -2978,11 +2982,13 @@ module OrthogonalPersistence = struct ) let save_mem env = + if not !Flags.fake_orthogonal_persistence then G.nop else if E.mode env = DfinityMode then G.i (Call (nr (E.built_in env "save_mem"))) else G.i Unreachable let restore_mem env = + if not !Flags.fake_orthogonal_persistence then G.nop else if E.mode env = DfinityMode then G.i (Call (nr (E.built_in env "restore_mem"))) else G.i Unreachable diff --git a/src/codegen/flags.ml b/src/codegen/flags.ml new file mode 100644 index 00000000000..0910f59c3ab --- /dev/null +++ b/src/codegen/flags.ml @@ -0,0 +1 @@ +let fake_orthogonal_persistence = ref true diff --git a/src/exes/asc.ml b/src/exes/asc.ml index 914c7e0a12f..db0354109d8 100644 --- a/src/exes/asc.ml +++ b/src/exes/asc.ml @@ -68,6 +68,7 @@ let argspec = Arg.align "-no-dfinity-api", Arg.Unit (fun () -> compile_mode := Pipeline.WasmMode), " do not import the DFINITY system API"; + "-no-fake-op", Arg.Clear Codegen.Flags.fake_orthogonal_persistence, " do not fake OP"; "-dp", Arg.Set Pipeline.Flags.dump_parse, " dump parse"; "-dt", Arg.Set Pipeline.Flags.dump_tc, " dump type-checked AST"; From 04127ba7a20bb4c10529e1771a96c083c68cc2db Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 5 Aug 2019 16:19:58 +0200 Subject: [PATCH 0338/1176] asc: -no-multi-value (#607) For some use-cases (e.g. processing the compiler output with analysis tools) it is useful to avoid the multi-value extension. This flag provides mostly transparent wrappers that put multiple values in statically allocated globals (at most 10...) and pull them off again. If the flag is not used, the code is unchanged. Also test the -no-multi-value flag in CI, as it is bad style to have code paths that are not tested. --- default.nix | 5 +++ src/codegen/compile.ml | 96 +++++++++++++++++++++++++++++++++--------- src/codegen/flags.ml | 1 + src/exes/asc.ml | 1 + 4 files changed, 84 insertions(+), 19 deletions(-) diff --git a/default.nix b/default.nix index 50f6a3a45d8..bcec48b37de 100644 --- a/default.nix +++ b/default.nix @@ -186,6 +186,10 @@ rec { ''; }; + tests-no-mv = tests.overrideAttrs (oldAttrs: { + ASC_FLAGS = "-no-multi-value"; + }); + unit-tests = stdenv.mkDerivation { name = "unit-tests"; @@ -409,6 +413,7 @@ rec { js didc tests + tests-no-mv unit-tests samples rts diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index f3d14eb6e0e..da7b5b306c7 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -480,6 +480,37 @@ let load_ptr : G.t = let store_ptr : G.t = G.i (Store {ty = I32Type; align = 2; offset = ptr_unskew; sz = None}) +module FakeMultiVal = struct + (* For some use-cases (e.g. processing the compiler output with analysis + tools) it is useful to avoid the multi-value extension. + + This module provides mostly transparent wrappers that put multiple values + in statically allocated globals (at most 10...) and pull them off again. + + If the multi_value flag is on, these do not do anything. + *) + let first_multival_global = 6 + + let ty tys = + if !Flags.multi_value || List.length tys <= 1 + then tys + else [] + + let store tys = + if !Flags.multi_value || List.length tys <= 1 then G.nop else + G.concat_mapi (fun i _ -> + G.i (GlobalSet (nr (Int32.of_int (first_multival_global + i)))) + ) tys + + let load tys = + if !Flags.multi_value || List.length tys <= 1 then G.nop else + let n = first_multival_global + List.length tys - 1 in + G.concat_mapi (fun i _ -> + G.i (GlobalGet (nr (Int32.of_int (n - i)))) + ) tys + +end (* FakeMultiVal *) + module Func = struct (* This module contains basic bookkeeping functionality to define functions, in particular creating the environment, and finally adding it to the environment. @@ -488,8 +519,10 @@ module Func = struct let of_body env params retty mk_body = let env1 = E.mk_fun_env env (Int32.of_int (List.length params)) (List.length retty) in List.iteri (fun i (n,_t) -> E.add_local_name env1 (Int32.of_int i) n) params; - let ty = FuncType (List.map snd params, retty) in - let body = G.to_instr_list (mk_body env1) in + let ty = FuncType (List.map snd params, FakeMultiVal.ty retty) in + let body = G.to_instr_list ( + mk_body env1 ^^ FakeMultiVal.store retty + ) in (nr { ftype = nr (E.func_type env ty); locals = E.get_locals env1; body } @@ -499,9 +532,12 @@ module Func = struct E.define_built_in env name (fun () -> of_body env params retty mk_body) (* (Almost) transparently lift code into a function and call this function. *) + (* Also add a hack to support multiple return values *) let share_code env name params retty mk_body = define_built_in env name params retty mk_body; - G.i (Call (nr (E.built_in env name))) + G.i (Call (nr (E.built_in env name))) ^^ + FakeMultiVal.load retty + (* Shorthands for various arities *) let _share_code0 env name retty mk_body = @@ -1182,23 +1218,22 @@ module Closure = struct let load_data i = Heap.load_field (Int32.add header_size i) let store_data i = Heap.store_field (Int32.add header_size i) - (* Calculate the wasm type for a given calling convention. - An extra first argument for the closure! *) - let ty env cc = - E.func_type env (FuncType ( - I32Type :: Lib.List.make cc.Call_conv.n_args I32Type, - Lib.List.make cc.Call_conv.n_res I32Type)) - (* Expect on the stack * the function closure * and arguments (n-ary!) * the function closure again! *) let call_closure env cc = + (* Calculate the wasm type for a given calling convention. + An extra first argument for the closure! *) + let ty = E.func_type env (FuncType ( + I32Type :: Lib.List.make cc.Call_conv.n_args I32Type, + FakeMultiVal.ty (Lib.List.make cc.Call_conv.n_res I32Type))) in (* get the table index *) Heap.load_field funptr_field ^^ (* All done: Call! *) - G.i (CallIndirect (nr (ty env cc))) + G.i (CallIndirect (nr ty)) ^^ + FakeMultiVal.load (Lib.List.make cc.Call_conv.n_res I32Type) let fixed_closure env fi fields = Tagged.obj env Tagged.Closure @@ -2770,11 +2805,13 @@ module Tuple = struct (* Takes an argument tuple and puts the elements on the stack: *) let to_stack env n = if n = 0 then G.i Drop else - let name = Printf.sprintf "from_%i_tuple" n in - let retty = Lib.List.make n I32Type in - Func.share_code1 env name ("tup", I32Type) retty (fun env get_tup -> - G.table n (fun i -> get_tup ^^ load_n (Int32.of_int i)) - ) + begin + let name = Printf.sprintf "from_%i_tuple" n in + let retty = Lib.List.make n I32Type in + Func.share_code1 env name ("tup", I32Type) retty (fun env get_tup -> + G.table n (fun i -> get_tup ^^ load_n (Int32.of_int i)) + ) + end end (* Tuple *) module Dfinity = struct @@ -4216,9 +4253,11 @@ module StackRep = struct | UnboxedReference -> ValBlockType (Some I32Type) | UnboxedTuple 0 -> ValBlockType None | UnboxedTuple 1 -> ValBlockType (Some I32Type) + | UnboxedTuple n when not !Flags.multi_value -> assert false | UnboxedTuple n -> VarBlockType (nr (E.func_type env (FuncType ([], Lib.List.make n I32Type)))) | UnboxedRefTuple 0 -> ValBlockType None | UnboxedRefTuple 1 -> ValBlockType (Some I32Type) + | UnboxedRefTuple n when not !Flags.multi_value -> assert false | UnboxedRefTuple n -> VarBlockType (nr (E.func_type env (FuncType ([], Lib.List.make n I32Type)))) | StaticThing _ -> ValBlockType None | Unreachable -> ValBlockType None @@ -4247,6 +4286,15 @@ module StackRep = struct Printf.eprintf "Invalid stack rep join (%s, %s)\n" (to_string sr1) (to_string sr2); sr1 + (* This is used when two blocks join, e.g. in an if. In that + case, they cannot return multiple values. *) + let relax = + if !Flags.multi_value + then fun sr -> sr + else function + | UnboxedTuple n when n > 1 -> Vanilla + | sr -> sr + let drop env (sr_in : t) = match sr_in with | Vanilla -> G.i Drop @@ -5933,7 +5981,7 @@ and compile_exp (env : E.t) ae exp = let code_scrut = compile_exp_as env ae SR.bool scrut in let sr1, code1 = compile_exp env ae e1 in let sr2, code2 = compile_exp env ae e2 in - let sr = StackRep.join sr1 sr2 in + let sr = StackRep.relax (StackRep.join sr1 sr2) in sr, code_scrut ^^ G.if_ (StackRep.to_block_type env sr) @@ -5970,6 +6018,7 @@ and compile_exp (env : E.t) ae exp = | RetE e -> SR.Unreachable, compile_exp_as env ae (StackRep.of_arity (E.get_n_res env)) e ^^ + FakeMultiVal.store (Lib.List.make (E.get_n_res env) I32Type) ^^ G.i Return | OptE e -> SR.Vanilla, @@ -5994,7 +6043,8 @@ and compile_exp (env : E.t) ae exp = code1 ^^ compile_unboxed_zero ^^ (* A dummy closure *) compile_exp_as env ae (StackRep.of_arity cc.Call_conv.n_args) e2 ^^ (* the args *) - G.i (Call (nr fi)) + G.i (Call (nr fi)) ^^ + FakeMultiVal.load (Lib.List.make cc.Call_conv.n_res I32Type) | _, Type.Local -> let (set_clos, get_clos) = new_local env "clos" in code1 ^^ StackRep.adjust env fun_sr SR.Vanilla ^^ @@ -6573,7 +6623,15 @@ and conclude_module env module_name start_fi_o = nr { gtype = GlobalType (I32Type, Mutable); value = nr (G.to_instr_list compile_unboxed_zero) }; - ] in + ] @ + (* multi value return emulations *) + begin if !Flags.multi_value then [] else + Lib.List.table 10 (fun i -> + nr { gtype = GlobalType (I32Type, Mutable); + value = nr (G.to_instr_list compile_unboxed_zero) + }) + end + in E.add_export env (nr { name = Wasm.Utf8.decode "__stack_pointer"; edesc = nr (GlobalExport (nr Stack.stack_global)) diff --git a/src/codegen/flags.ml b/src/codegen/flags.ml index 0910f59c3ab..6d8e7f786fb 100644 --- a/src/codegen/flags.ml +++ b/src/codegen/flags.ml @@ -1 +1,2 @@ let fake_orthogonal_persistence = ref true +let multi_value = ref true diff --git a/src/exes/asc.ml b/src/exes/asc.ml index db0354109d8..24a6214a607 100644 --- a/src/exes/asc.ml +++ b/src/exes/asc.ml @@ -69,6 +69,7 @@ let argspec = Arg.align Arg.Unit (fun () -> compile_mode := Pipeline.WasmMode), " do not import the DFINITY system API"; "-no-fake-op", Arg.Clear Codegen.Flags.fake_orthogonal_persistence, " do not fake OP"; + "-no-multi-value", Arg.Clear Codegen.Flags.multi_value, " avoid multi-value extension"; "-dp", Arg.Set Pipeline.Flags.dump_parse, " dump parse"; "-dt", Arg.Set Pipeline.Flags.dump_tc, " dump type-checked AST"; From fb057a65420c2f6c6c593dea47bf706838547c6d Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Mon, 5 Aug 2019 22:00:21 -0700 Subject: [PATCH 0339/1176] inline defs for polymorphic defs --- src/as_idl/as_to_idl.ml | 89 ++++++++++++++++++----------- test/as-idl/ok/result.did.ok | 7 +++ test/as-idl/ok/result.idl.stderr.ok | 1 - test/as-idl/result.as | 10 +++- 4 files changed, 71 insertions(+), 36 deletions(-) create mode 100644 test/as-idl/ok/result.did.ok delete mode 100644 test/as-idl/ok/result.idl.stderr.ok diff --git a/src/as_idl/as_to_idl.ml b/src/as_idl/as_to_idl.ml index 5229d752ada..3b7df7f6ff4 100644 --- a/src/as_idl/as_to_idl.ml +++ b/src/as_idl/as_to_idl.ml @@ -27,7 +27,14 @@ let unescape lab : label = if len >= 2 && lab.[len-1] = '_' then Id (String.sub lab 0 (len-1)) else Id lab - + +let vars_of_binds vs (tbs : bind list) = + let rec name_of_var vs v = + match vs with + | [] -> v + | v'::vs' -> name_of_var vs' (if v = v' then (fst v, snd v + 1) else v) in + List.map (fun b -> name_of_var vs (b.var, 0)) tbs + let prim p = match p with | Null -> I.Null @@ -50,37 +57,45 @@ let prim p = | Char -> I.Nat32 | Text -> I.Text -let rec typ t = +let rec typ vs t = (match t with | Any -> I.PrimT I.Reserved | Non -> I.PrimT I.Empty | Prim p -> I.PrimT (prim p) | Var (s, i) -> - printf "VAR %s.%d" s i; - assert false + (try (typ vs (List.nth vs i)).it + with _ -> assert false) + | Con (c, []) -> + chase_con vs c; + I.VarT (string_of_con c @@ no_region) | Con (c, ts) -> - (* TODO monomorphization *) - let id = - (if List.length ts = 0 then string_of_con c - else sprintf "%s<%s>" (string_of_con c) (String.concat ", " (List.map string_of_typ ts))) @@ no_region in - chase_con c; - I.VarT id + let ts = + List.map (fun t -> + match t with + | Var (s, i) -> List.nth vs i + | _ -> t + ) ts in + (match Con.kind c with + | Def (tbs, t) -> + assert (List.length tbs = List.length ts); + (typ ts t).it + | _ -> assert false) | Typ c -> assert false | Tup ts -> - I.RecordT (tuple ts) - | Array t -> I.VecT (typ t) - | Opt t -> I.OptT (typ t) + I.RecordT (tuple vs ts) + | Array t -> I.VecT (typ vs t) + | Opt t -> I.OptT (typ vs t) | Obj (Object, fs) -> - I.RecordT (List.map field fs) - | Obj (Actor, fs) -> I.ServT (meths fs) + I.RecordT (List.map (field vs) fs) + | Obj (Actor, fs) -> I.ServT (meths vs fs) | Obj (Module, _) -> assert false | Variant fs -> - I.VariantT (List.map field fs) + I.VariantT (List.map (field vs) fs) | Func (Shared, c, [], ts1, ts2) -> - let fs1 = tuple ts1 in + let fs1 = tuple vs ts1 in (match ts2 with | [] when c = Returns -> I.FuncT ([I.Oneway @@ no_region], fs1, []) - | [Async t] when c = Promises -> I.FuncT ([], fs1, tuple [t]) + | [Async t] when c = Promises -> I.FuncT ([], fs1, tuple vs [t]) | _ -> assert false) | Func _ -> assert false | Async t -> assert false @@ -88,46 +103,46 @@ let rec typ t = | Serialized t -> assert false | Pre -> assert false ) @@ no_region -and field {lab; typ=t} = +and field vs {lab; typ=t} = match unescape lab with | Nat nat -> let name = Lib.Uint32.to_string nat @@ no_region in - I.{id = nat; name = name; typ = typ t} @@ no_region + I.{id = nat; name = name; typ = typ vs t} @@ no_region | Id id -> let name = id @@ no_region in let id = Idllib.IdlHash.idl_hash id in - I.{id = id; name = name; typ = typ t} @@ no_region -and tuple ts = + I.{id = id; name = name; typ = typ vs t} @@ no_region +and tuple vs ts = List.mapi (fun i x -> let id = Lib.Uint32.of_int i in let name = Lib.Uint32.to_string id @@ no_region in - I.{id = id; name = name; typ = typ x} @@ no_region + I.{id = id; name = name; typ = typ vs x} @@ no_region ) ts -and meths fs = +and meths vs fs = List.fold_right (fun f list -> match f.typ with | Typ c -> - chase_con c; + chase_con vs c; list | _ -> let meth = match unescape f.lab with | Nat nat -> I.{var = Lib.Uint32.to_string nat @@ no_region; - meth = typ f.typ} @@ no_region + meth = typ vs f.typ} @@ no_region | Id id -> I.{var = id @@ no_region; - meth = typ f.typ} @@ no_region in + meth = typ vs f.typ} @@ no_region in meth :: list ) fs [] -and chase_con c = +and chase_con vs c = if not (ConEnv.mem c !dec_env) then (match Con.kind c with | Def ([], t) -> dec_env := ConEnv.add c (I.PreT @@ no_region) !dec_env; - let t = typ t in + let t = typ vs t in dec_env := ConEnv.add c t !dec_env - | _ -> ()) + | _ -> assert false) let is_actor_con c = match Con.kind c with @@ -136,7 +151,7 @@ let is_actor_con c = let chase_decs env = ConSet.iter (fun c -> - if is_actor_con c then chase_con c + if is_actor_con c then chase_con [] c ) env.Scope.con_env let gather_decs () = @@ -150,10 +165,16 @@ let actor progs = let find_last_actor (prog : prog) = let anon = normalize ("anon_" ^ (Filename.remove_extension prog.note)) in let check_dec d t def = + let rec check_pat p = + match p.it with + | WildP -> Some (anon, t) + | VarP id -> Some (id.it, t) + | ParP p -> check_pat p + | _ -> def + in match d.it with | ExpD _ -> Some (anon, t) - | LetD ({it=WildP;_}, _) -> Some (anon, t) - | LetD ({it=VarP id;_}, _) -> Some (id.it, t) + | LetD (pat, _) -> check_pat pat | _ -> def in List.fold_left @@ -170,7 +191,7 @@ let actor progs = let prog = Lib.List.last progs in match find_last_actor prog with | None -> None - | Some (id, t) -> Some (I.ActorD (id @@ no_region, typ t) @@ no_region) + | Some (id, t) -> Some (I.ActorD (id @@ no_region, typ [] t) @@ no_region) let prog (progs, env) : I.prog = dec_env := ConEnv.empty; diff --git a/test/as-idl/ok/result.did.ok b/test/as-idl/ok/result.did.ok new file mode 100644 index 00000000000..fdc38c94cae --- /dev/null +++ b/test/as-idl/ok/result.did.ok @@ -0,0 +1,7 @@ +type Text = text; +type Nat = nat; +type Int = int; +service anon_result { +f : (opt Nat) -> (variant {err : Text; ok : Nat}); +g : (variant {err : variant {err : variant {err : Text; ok : Text}; ok : Text}; ok : Text}) -> (variant {err : variant {err : Int; ok : Text}; ok : Int}); +} diff --git a/test/as-idl/ok/result.idl.stderr.ok b/test/as-idl/ok/result.idl.stderr.ok deleted file mode 100644 index d91ebdfe58d..00000000000 --- a/test/as-idl/ok/result.idl.stderr.ok +++ /dev/null @@ -1 +0,0 @@ -(unknown location): type error, unbound type identifier Result diff --git a/test/as-idl/result.as b/test/as-idl/result.as index 0e6ead46b34..258ea595278 100644 --- a/test/as-idl/result.as +++ b/test/as-idl/result.as @@ -2,6 +2,14 @@ type Result = { #ok:Ok; #err:Err; }; +type Result2 = { + #ok:Ok; + #err:Result; +}; +type Result3 = { + #ok:Ok; + #err:Result2; +}; actor { public func f(x:?Nat):async Result { switch x { @@ -9,7 +17,7 @@ actor { case null {#err "error"}; } }; - public func g(x:Result):async Result { + public func g(x:Result3):async Result2 { #ok(1); }; } From 62dad551d222e17d20dd02fd1c758d2206717a57 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Mon, 5 Aug 2019 22:11:32 -0700 Subject: [PATCH 0340/1176] fix --- src/as_idl/as_to_idl.ml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/as_idl/as_to_idl.ml b/src/as_idl/as_to_idl.ml index 3b7df7f6ff4..fbb1247799c 100644 --- a/src/as_idl/as_to_idl.ml +++ b/src/as_idl/as_to_idl.ml @@ -1,7 +1,6 @@ open As_types open As_types.Type open Source -open Printf module E = As_def.Syntax module I = Idllib.Syntax @@ -28,13 +27,6 @@ let unescape lab : label = then Id (String.sub lab 0 (len-1)) else Id lab -let vars_of_binds vs (tbs : bind list) = - let rec name_of_var vs v = - match vs with - | [] -> v - | v'::vs' -> name_of_var vs' (if v = v' then (fst v, snd v + 1) else v) in - List.map (fun b -> name_of_var vs (b.var, 0)) tbs - let prim p = match p with | Null -> I.Null From 06fa3d10462e0f4552f317c44bc442d22693d12d Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Tue, 6 Aug 2019 14:24:34 -0700 Subject: [PATCH 0341/1176] monomorphise polymorphic recursion --- src/as_idl/as_to_idl.ml | 67 ++++++++++++++++++++++----------- test/as-idl/ok/recursion.did.ok | 8 ++++ test/as-idl/ok/result.did.ok | 10 +++-- test/as-idl/recursion.as | 13 +++++++ test/as-idl/result.as | 4 +- 5 files changed, 75 insertions(+), 27 deletions(-) create mode 100644 test/as-idl/ok/recursion.did.ok create mode 100644 test/as-idl/recursion.as diff --git a/src/as_idl/as_to_idl.ml b/src/as_idl/as_to_idl.ml index fbb1247799c..32f98b23388 100644 --- a/src/as_idl/as_to_idl.ml +++ b/src/as_idl/as_to_idl.ml @@ -1,18 +1,42 @@ open As_types open As_types.Type -open Source +open Source +open Printf module E = As_def.Syntax module I = Idllib.Syntax type label = Nat of Lib.Uint32.t | Id of string -let dec_env = ref ConEnv.empty - +let env = ref Env.empty +(* For monomorphization *) +let stamp = ref Env.empty +let type_map = ref Env.empty + let normalize str = - let illegal_chars = ['-'; '/'] in + let illegal_chars = ['-'; '/';] in String.map (fun c -> if List.mem c illegal_chars then '_' else c) str -let string_of_con c = normalize (string_of_con c) +let string_of_con vs c = + let name = string_of_con c in + match Con.kind c with + | Def ([], _) -> normalize name + | Def (tbs, _) -> + let id = sprintf "%s<%s>" name (String.concat "," (List.map string_of_typ vs)) in + let n = + match Env.find_opt id !type_map with + | None -> + (match Env.find_opt name !stamp with + | None -> + stamp := Env.add name 1 !stamp; + type_map := Env.add id 1 !type_map; + 1 + | Some n -> + stamp := Env.add name (n+1) !stamp; + type_map := Env.add id (n+1) !type_map; + n+1) + | Some n -> n + in Printf.sprintf "%s_%d" (normalize name) n + | _ -> assert false let unescape lab : label = let lab = normalize lab in @@ -54,12 +78,10 @@ let rec typ vs t = | Any -> I.PrimT I.Reserved | Non -> I.PrimT I.Empty | Prim p -> I.PrimT (prim p) - | Var (s, i) -> - (try (typ vs (List.nth vs i)).it - with _ -> assert false) + | Var (s, i) -> (typ vs (List.nth vs i)).it | Con (c, []) -> chase_con vs c; - I.VarT (string_of_con c @@ no_region) + I.VarT (string_of_con vs c @@ no_region) | Con (c, ts) -> let ts = List.map (fun t -> @@ -69,8 +91,8 @@ let rec typ vs t = ) ts in (match Con.kind c with | Def (tbs, t) -> - assert (List.length tbs = List.length ts); - (typ ts t).it + chase_con ts c; + I.VarT (string_of_con ts c @@ no_region) | _ -> assert false) | Typ c -> assert false | Tup ts -> @@ -128,12 +150,13 @@ and meths vs fs = meth :: list ) fs [] and chase_con vs c = - if not (ConEnv.mem c !dec_env) then + let id = string_of_con vs c in + if not (Env.mem id !env) then (match Con.kind c with - | Def ([], t) -> - dec_env := ConEnv.add c (I.PreT @@ no_region) !dec_env; - let t = typ vs t in - dec_env := ConEnv.add c t !dec_env + | Def (_, t) -> + env := Env.add id (I.PreT @@ no_region) !env; + let t = typ vs t in + env := Env.add id t !env | _ -> assert false) let is_actor_con c = @@ -147,10 +170,10 @@ let chase_decs env = ) env.Scope.con_env let gather_decs () = - ConEnv.fold (fun c t list -> - let dec = I.TypD (string_of_con c @@ no_region, t) @@ no_region in + Env.fold (fun id t list -> + let dec = I.TypD (id @@ no_region, t) @@ no_region in dec::list - ) !dec_env [] + ) !env [] let actor progs = let open E in @@ -185,10 +208,10 @@ let actor progs = | None -> None | Some (id, t) -> Some (I.ActorD (id @@ no_region, typ [] t) @@ no_region) -let prog (progs, env) : I.prog = - dec_env := ConEnv.empty; +let prog (progs, senv) : I.prog = + env := Env.empty; let actor = actor progs in - if actor = None then chase_decs env; + if actor = None then chase_decs senv; let decs = gather_decs () in let prog = I.{decs = decs; actor = actor} in {it = prog; at = no_region; note = ""} diff --git a/test/as-idl/ok/recursion.did.ok b/test/as-idl/ok/recursion.did.ok new file mode 100644 index 00000000000..92776b6dc59 --- /dev/null +++ b/test/as-idl/ok/recursion.did.ok @@ -0,0 +1,8 @@ +type Nat = nat; +type List_2 = record {head : Nat; tail : opt List_2}; +type List_1 = record {head : Int; tail : opt List_1}; +type Int = int; +service anon_recursion { +f : (Nat) -> (List_2); +g : (Int) -> (List_1); +} diff --git a/test/as-idl/ok/result.did.ok b/test/as-idl/ok/result.did.ok index fdc38c94cae..7ce3b6a1727 100644 --- a/test/as-idl/ok/result.did.ok +++ b/test/as-idl/ok/result.did.ok @@ -1,7 +1,11 @@ type Text = text; +type Result_2 = variant {err : Text; ok : Nat}; +type Result_1 = variant {err : Text; ok : record {}}; +type Result3_1 = variant {err : Result2_1; ok : record {}}; +type Result2_2 = variant {err : Result_2; ok : Nat}; +type Result2_1 = variant {err : Result_1; ok : record {}}; type Nat = nat; -type Int = int; service anon_result { -f : (opt Nat) -> (variant {err : Text; ok : Nat}); -g : (variant {err : variant {err : variant {err : Text; ok : Text}; ok : Text}; ok : Text}) -> (variant {err : variant {err : Int; ok : Text}; ok : Int}); +f : (opt Nat) -> (Result_2); +g : (Result3_1) -> (Result2_2); } diff --git a/test/as-idl/recursion.as b/test/as-idl/recursion.as new file mode 100644 index 00000000000..ebee5754cea --- /dev/null +++ b/test/as-idl/recursion.as @@ -0,0 +1,13 @@ +type List = { + head:A; + tail:?List; +}; +actor { + public func f(x:Nat):async List { + {head=x; tail=null}; + }; + public func g(x:Int):async List { + {head=x; tail=null}; + }; +} + diff --git a/test/as-idl/result.as b/test/as-idl/result.as index 258ea595278..ed88744328d 100644 --- a/test/as-idl/result.as +++ b/test/as-idl/result.as @@ -4,7 +4,7 @@ type Result = { }; type Result2 = { #ok:Ok; - #err:Result; + #err:Result; }; type Result3 = { #ok:Ok; @@ -17,7 +17,7 @@ actor { case null {#err "error"}; } }; - public func g(x:Result3):async Result2 { + public func g(x:Result3<()>):async Result2 { #ok(1); }; } From fde01ea20488e7482c9b39fa0e0db3e3f8bab2a6 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Thu, 8 Aug 2019 19:49:36 +0200 Subject: [PATCH 0342/1176] Randomised arithmetic testing [ACT-109, ACT-110] (#609) * beginnings of a randomised property-testing tool for ActorScript AST * minimal integration into the CI pipeline --- default.nix | 8 +- test/README.md | 15 + test/random/Main.hs | 760 +++++++++++++++++++++++++++++++ test/random/README.md | 63 +++ test/random/qc-actorscript.cabal | 25 + 5 files changed, 870 insertions(+), 1 deletion(-) create mode 100644 test/random/Main.hs create mode 100644 test/random/README.md create mode 100644 test/random/qc-actorscript.cabal diff --git a/default.nix b/default.nix index bcec48b37de..fa5118a26d7 100644 --- a/default.nix +++ b/default.nix @@ -2,6 +2,7 @@ test-dvm ? true, dvm ? null, export-shell ? false, + replay ? 0 }: let llvm = import ./nix/llvm.nix { system = nixpkgs.system; }; in @@ -148,6 +149,10 @@ rec { ''; }; + qc-actorscript = nixpkgs.haskellPackages.callCabal2nix "qc-actorscript" test/random { }; + + replay-option = if replay != 0 then " --quickcheck-replay=${toString replay}" else ""; + tests = stdenv.mkDerivation { name = "tests"; src = subpath ./test; @@ -163,7 +168,7 @@ rec { filecheck js-client ] ++ - (if test-dvm then [ real-dvm ] else []) ++ + (if test-dvm then [ real-dvm qc-actorscript ] else []) ++ llvmBuildInputs; buildPhase = '' @@ -177,6 +182,7 @@ rec { '' + (if test-dvm then '' make parallel + qc-actorscript${replay-option} '' else '' make quick ''); diff --git a/test/README.md b/test/README.md index 5bc7d6ea307..a7348f08319 100644 --- a/test/README.md +++ b/test/README.md @@ -38,3 +38,18 @@ Adding a new test 1. Create `foo.as` 2. Run `make accept` (or, more targeted, `../run.sh -a foo.as`) 3. Add `foo.as` and `ok/foo.*.ok` to git. + + +Running as a `nix` derivation +----------------------------- + +You can run the test suite from the `actorscript` (top-level) directory as: + +``` shell +$ nix-build -A tests +``` + +Randomised testing +------------------ + +See `README.md` in the `random/` subdirectory. diff --git a/test/random/Main.hs b/test/random/Main.hs new file mode 100644 index 00000000000..ea8c3e1dd9c --- /dev/null +++ b/test/random/Main.hs @@ -0,0 +1,760 @@ +{-# language ConstraintKinds, DataKinds, FlexibleContexts, FlexibleInstances, GADTs + , KindSignatures, MultiParamTypeClasses, OverloadedStrings, ScopedTypeVariables, StandaloneDeriving + , TypeApplications, TypeOperators, TypeFamilies, TupleSections + , UndecidableInstances, ViewPatterns #-} + +{-# options_ghc -Wno-missing-methods #-} + +module Main where + +import Control.Applicative +import Control.Monad +import Test.QuickCheck.Monadic +import Test.Tasty +import Test.Tasty.QuickCheck as QC hiding ((.&.)) +import qualified Data.Text (null, unpack) +import Data.Maybe +import Data.Bool (bool) +import Data.Proxy +import GHC.Natural +import GHC.TypeLits +import qualified Data.Word +import Data.Bits (Bits(..), FiniteBits(..)) + +import System.Process hiding (proc) +import Turtle +import Debug.Trace (traceShowId) + +main = defaultMain tests + where tests :: TestTree + tests = testGroup "Arithmetic-logic operations" [properties] + +properties :: TestTree +properties = testGroup "Properties" [qcProps] + +qcProps = testGroup "(checked by QuickCheck)" + [ QC.testProperty "expected failures" $ prop_rejects + , QC.testProperty "expected successes" $ prop_verifies + ] + + + +assertSuccessNoFuzz relevant (compiled, (exitCode, out, err)) = do + let fuzzErr = not $ Data.Text.null err + when fuzzErr $ do + monitor (counterexample "STDERR:") + monitor (counterexample . Data.Text.unpack $ err) + let fuzzOut = not $ Data.Text.null out + let fuzzOutRelevant = relevant fuzzOut + when (fuzzOut && fuzzOutRelevant) $ do + monitor (counterexample "STDOUT:") + monitor (counterexample . Data.Text.unpack $ out) + assert (not $ ExitSuccess /= exitCode || (if compiled then fuzzOutRelevant else fuzzOut) || fuzzErr) + +newtype Failing a = Failing a deriving Show + +instance Arbitrary (Failing String) where + arbitrary = do let failed as = "let _ = " ++ unparseAS as ++ ";" + Failing . failed <$> suchThat (resize 5 arbitrary) (\(evaluate @ Integer -> res) -> null res) + +prop_rejects (Failing testCase) = monadicIO $ do + let script = do Turtle.output "fails.as" $ fromString testCase + res@(exitCode, _, _) <- procStrictWithErr "asc" + ["-no-dfinity-api", "-no-check-ir", "fails.as"] empty + if ExitSuccess == exitCode + then (True,) <$> procStrictWithErr "wasm-interp" ["--enable-multi", "fails.wasm"] empty + else pure (False, res) + run script >>= assertSuccessNoFuzz not + + +halve [] = ([], []) +halve a@[_] = (a, []) +halve (clown : joker : (halve -> (cs, js))) = (clown : cs, joker : js) + +newtype TestCase = TestCase [String] deriving Show + +instance Arbitrary TestCase where + arbitrary = do tests <- infiniteListOf arbitrary + let expected = evaluate @ Integer <$> tests + let paired as = fmap (\res -> "assert (" ++ unparseAS as ++ " == " ++ show res ++ ");") + pure . TestCase . take 100 . catMaybes $ zipWith paired tests expected + + + + +prop_verifies (TestCase (map fromString -> testCase)) = monadicIO $ do + let script cases = do Turtle.output "tests.as" $ msum cases + res@(exitCode, _, _) <- procStrictWithErr "asc" + ["-no-dfinity-api", "-no-check-ir", "tests.as"] empty + if ExitSuccess == exitCode + then (True,) <$> procStrictWithErr "wasm-interp" ["--enable-multi", "tests.wasm"] empty + else pure (False, res) + res@(compiled, (exitCode, out, err)) <- run $ script testCase + when compiled $ do + pre (ExitSuccess == exitCode) + let bisect (clowns, jokers) = + do (True, (cExitCode, cOut, _)) <- script clowns + (True, (jExitCode, jOut, _)) <- script jokers + case (Data.Text.null cOut, Data.Text.null jOut) of + (False, _) -> if length clowns == 1 + then reduce (Fold (<>) empty linesToText) $ sequence clowns + else bisect $ halve clowns + (_, False) -> bisect $ halve jokers + let good = Data.Text.null out + unless good $ (run . bisect $ halve testCase) >>= monitor . (counterexample . Data.Text.unpack $) + assertSuccessNoFuzz id res + + +data Off = TwoLess | OneLess | OneMore | TwoMore + deriving (Enum, Eq, Ord, Show) + +instance Arbitrary Off where + arbitrary = elements [TwoLess .. TwoMore] + +-- Below data structure tries to focus test case generation of +-- numeric values to *neuralgic points* of the numeric line, namely +-- areas where (from our white-box knowledge of ActorScript's inner +-- workings) representation changes are expected to happen. These +-- are mostly at a power-of-two boundary and around it, e.g. we have +-- signed 30 bit numbers (`Int` and `Nat`) that have a compact representation +-- and out of this range the number gets heap-allocated. +-- +data Neuralgic t + = LargeNeg + | AroundNeg Integer + | Around0 + | AroundPos Integer + | LargePos + | Offset (Neuralgic t) Off + deriving (Eq, Ord, Show) + +instance Arbitrary (Neuralgic Integer) where + arbitrary = frequency [ (5, elements [LargeNeg, AroundNeg 63, AroundNeg 30, Around0, AroundPos 30, AroundPos 63, LargePos]) + , (8, Offset <$> arbitrary <*> arbitrary)] + + +pred `guardedFrom` set = frequency [ (5, elements set) + , (3, Offset <$> arbitrary <*> arbitrary)] + `suchThat` (isJust . guardedEvalN pred) +infix 1 `guardedFrom` + +instance Arbitrary (Neuralgic Natural) where + arbitrary = (\n -> if n >= 0 then pure (fromIntegral n) else Nothing) + `guardedFrom` [Around0, AroundPos 30, AroundPos 63, LargePos] + +instance Arbitrary (Neuralgic Nat8) where + arbitrary = fmap NatN <$> trapNat 8 `guardedFrom` [Around0, AroundPos 3, AroundPos 5, AroundPos 8] + +instance Arbitrary (Neuralgic Nat16) where + arbitrary = fmap NatN <$> trapNat 16 `guardedFrom` [Around0, AroundPos 3, AroundPos 5, AroundPos 8, AroundPos 13, AroundPos 16] + +instance Arbitrary (Neuralgic Nat32) where + arbitrary = fmap NatN <$> trapNat 32 `guardedFrom` [Around0, AroundPos 8, AroundPos 13, AroundPos 16, AroundPos 23, AroundPos 32] + +instance Arbitrary (Neuralgic Nat64) where + arbitrary = fmap NatN <$> trapNat 64 `guardedFrom` [Around0, AroundPos 8, AroundPos 13, AroundPos 23, AroundPos 31, AroundPos 47, AroundPos 64] + + + +instance Arbitrary (Neuralgic Int8) where + arbitrary = fmap IntN <$> trapInt 8 `guardedFrom` [Around0, AroundNeg 3, AroundNeg 5, AroundNeg 7, AroundPos 3, AroundPos 5, AroundPos 7] + +instance Arbitrary (Neuralgic Int16) where + arbitrary = fmap IntN <$> trapInt 16 `guardedFrom` [Around0, AroundNeg 3, AroundNeg 7, AroundNeg 10, AroundNeg 15, AroundPos 3, AroundPos 8, AroundPos 10, AroundPos 15] + +instance Arbitrary (Neuralgic Int32) where + arbitrary = fmap IntN <$> trapInt 32 `guardedFrom` [Around0, AroundNeg 3, AroundNeg 17, AroundNeg 27, AroundNeg 31, AroundPos 3, AroundPos 18, AroundPos 25, AroundPos 31] + +instance Arbitrary (Neuralgic Int64) where + arbitrary = fmap IntN <$> trapInt 64 `guardedFrom` [Around0, AroundNeg 9, AroundNeg 27, AroundNeg 51, AroundNeg 63, AroundPos 10, AroundPos 28, AroundPos 55, AroundPos 63] + + + +instance Arbitrary (Neuralgic Word8) where + arbitrary = fmap WordN <$> trapWord 8 `guardedFrom` [Around0, AroundNeg 3, AroundNeg 5, AroundNeg 8, AroundPos 3, AroundPos 5, AroundPos 8] + +instance Arbitrary (Neuralgic Word16) where + arbitrary = fmap WordN <$> trapWord 16 `guardedFrom` [Around0, AroundNeg 3, AroundNeg 12, AroundNeg 16, AroundPos 6, AroundPos 13, AroundPos 16] + +instance Arbitrary (Neuralgic Word32) where + arbitrary = fmap WordN <$> trapWord 32 `guardedFrom` [Around0, AroundNeg 3, AroundNeg 12, AroundNeg 23, AroundNeg 32, AroundPos 6, AroundPos 15, AroundPos 26, AroundPos 32] + +instance Arbitrary (Neuralgic Word64) where + arbitrary = fmap WordN <$> trapWord 64 `guardedFrom` [Around0, AroundNeg 3, AroundNeg 11, AroundNeg 21, AroundNeg 31, AroundNeg 42, AroundNeg 64, AroundPos 6, AroundPos 14, AroundPos 27, AroundPos 43, AroundPos 57, AroundPos 64] + + +data ActorScriptTerm a + = About a + | Pos (ActorScriptTerm a) + | Neg (ActorScriptTerm a) + | Abs (ActorScriptTerm a) + | ActorScriptTerm a `Add` ActorScriptTerm a + | ActorScriptTerm a `Sub` ActorScriptTerm a + | ActorScriptTerm a `Mul` ActorScriptTerm a + | ActorScriptTerm a `Div` ActorScriptTerm a + | ActorScriptTerm a `Mod` ActorScriptTerm a + | ActorScriptTerm a `Pow` ActorScriptTerm a + | ActorScriptTerm a `Or` ActorScriptTerm a + | ActorScriptTerm a `And` ActorScriptTerm a + | ActorScriptTerm a `Xor` ActorScriptTerm a + | ActorScriptTerm a `RotL` ActorScriptTerm a + | ActorScriptTerm a `RotR` ActorScriptTerm a + | ActorScriptTerm a `ShiftL` ActorScriptTerm a + | ActorScriptTerm a `ShiftR` ActorScriptTerm a + | ActorScriptTerm a `ShiftRSigned` ActorScriptTerm a + | PopCnt (ActorScriptTerm a) + | Clz (ActorScriptTerm a) + | Ctz (ActorScriptTerm a) + | Five + | ConvertNatural (ActorScriptTerm (Neuralgic Natural)) + | forall n . KnownNat n => ConvertNat (ActorScriptTerm (Neuralgic (BitLimited n Natural))) + | forall n . KnownNat n => ConvertInt (ActorScriptTerm (Neuralgic (BitLimited n Integer))) + | forall n . WordLike n => ConvertWord (ActorScriptTerm (Neuralgic (BitLimited n Word))) + | Rel (ActorScriptTyped Bool) + | IfThenElse (ActorScriptTerm a) (ActorScriptTerm a) (ActorScriptTyped Bool) -- cond is last! + +deriving instance Show a => Show (ActorScriptTerm a) + + +data ActorScriptTyped :: * -> * where + NotEqual, Equals, GreaterEqual, Greater, LessEqual, Less + :: (Show (Neuralgic a), Annot a, Literal a, Evaluatable a) => ActorScriptTerm (Neuralgic a) -> ActorScriptTerm (Neuralgic a) -> ActorScriptTyped Bool + ShortAnd, ShortOr + :: ActorScriptTyped Bool -> ActorScriptTyped Bool -> ActorScriptTyped Bool + Not :: ActorScriptTyped Bool -> ActorScriptTyped Bool + Bool :: Bool -> ActorScriptTyped Bool +deriving instance Show (ActorScriptTyped t) + +subTerm :: Arbitrary (ActorScriptTerm t) => Bool -> Int -> [(Int, Gen (ActorScriptTerm t))] +subTerm fullPow n = + [ (1, resize (n `div` 5) $ Pow <$> arbitrary <*> arbitrary) | fullPow] ++ + [ (n, resize (n `div` 3) $ Add <$> arbitrary <*> arbitrary) + , (n, resize (n `div` 3) $ Sub <$> arbitrary <*> arbitrary) + , (n, resize (n `div` 3) $ Mul <$> arbitrary <*> arbitrary) + , (n, resize (n `div` 3) $ Div <$> arbitrary <*> arbitrary) + , (n, resize (n `div` 3) $ Mod <$> arbitrary <*> arbitrary) + , (n, resize (n `div` 4) $ IfThenElse <$> arbitrary <*> arbitrary <*> arbitrary) + ] + +subTermPow :: Arbitrary (ActorScriptTerm t) => (ActorScriptTerm t -> ActorScriptTerm t) -> Int -> [(Int, Gen (ActorScriptTerm t))] +subTermPow mod n = (n, resize (n `div` 5) $ Pow <$> arbitrary <*> (mod <$> arbitrary)) + : subTerm False n + +subTermPow5 :: Arbitrary (ActorScriptTerm (Neuralgic t)) + => Int -> [(Int, Gen (ActorScriptTerm (Neuralgic t)))] +subTermPow5 n = (n, resize (n `div` 5) + $ Pow <$> arbitrary + <*> (About <$> elements [ Around0 + , Around0 `Offset` OneMore + , AroundPos 1 + , AroundPos 1 `Offset` OneMore + , AroundPos 2 + ])) + : subTerm False n + +bitwiseTerm :: Arbitrary (ActorScriptTerm t) => Int -> [(Int, Gen (ActorScriptTerm t))] +bitwiseTerm n = + [ (n `div` 5, resize (n `div` 3) $ Or <$> arbitrary <*> arbitrary) + , (n `div` 5, resize (n `div` 3) $ And <$> arbitrary <*> arbitrary) + , (n `div` 5, resize (n `div` 3) $ Xor <$> arbitrary <*> arbitrary) + , (n `div` 5, resize (n `div` 3) $ RotL <$> arbitrary <*> arbitrary) + , (n `div` 5, resize (n `div` 3) $ RotR <$> arbitrary <*> arbitrary) + , (n `div` 5, resize (n `div` 3) $ ShiftL <$> arbitrary <*> arbitrary) + , (n `div` 5, resize (n `div` 3) $ ShiftR <$> arbitrary <*> arbitrary) + , (n `div` 5, resize (n `div` 3) $ ShiftRSigned <$> arbitrary <*> arbitrary) + , (n `div` 5, PopCnt <$> arbitrary) + , (n `div` 5, Clz <$> arbitrary) + , (n `div` 5, Ctz <$> arbitrary) + ] + +-- generate reasonably formed trees from subterms +-- +reasonablyShaped :: Arbitrary a + => (Int -> [(Int, Gen (ActorScriptTerm a))]) + -> Gen (ActorScriptTerm a) +reasonablyShaped sub = sized $ \(succ -> n) -> frequency $ + (30 `div` n, About <$> arbitrary) + : if n > 1 then sub n else [] + +instance Arbitrary (ActorScriptTerm (Neuralgic Nat8)) where + arbitrary = reasonablyShaped $ subTerm True + +instance Arbitrary (ActorScriptTerm (Neuralgic Nat16)) where + arbitrary = reasonablyShaped $ subTermPow (`Mod` Five) + +instance Arbitrary (ActorScriptTerm (Neuralgic Nat32)) where + arbitrary = reasonablyShaped $ subTermPow (`Mod` Five) + +instance Arbitrary (ActorScriptTerm (Neuralgic Nat64)) where + arbitrary = reasonablyShaped $ subTermPow (`Mod` Five) + + +instance Arbitrary (ActorScriptTerm (Neuralgic Int8)) where + arbitrary = reasonablyShaped $ subTerm True + +instance Arbitrary (ActorScriptTerm (Neuralgic Int16)) where + arbitrary = reasonablyShaped subTermPow5 + +instance Arbitrary (ActorScriptTerm (Neuralgic Int32)) where + arbitrary = reasonablyShaped subTermPow5 + +instance Arbitrary (ActorScriptTerm (Neuralgic Int64)) where + arbitrary = reasonablyShaped subTermPow5 + + +instance Arbitrary (ActorScriptTerm (Neuralgic Word8)) where + arbitrary = reasonablyShaped $ (<>) <$> subTerm True <*> bitwiseTerm + +instance Arbitrary (ActorScriptTerm (Neuralgic Word16)) where + arbitrary = reasonablyShaped $ (<>) <$> subTermPow (`Mod` Five) <*> bitwiseTerm + +instance Arbitrary (ActorScriptTerm (Neuralgic Word32)) where + arbitrary = reasonablyShaped $ (<>) <$> subTermPow (`Mod` Five) <*> bitwiseTerm + +instance Arbitrary (ActorScriptTerm (Neuralgic Word64)) where + arbitrary = reasonablyShaped $ (<>) <$> subTermPow (`Mod` Five) <*> bitwiseTerm + + +instance Arbitrary (ActorScriptTyped Bool) where + arbitrary = sized $ \(succ -> n) -> -- TODO: use frequency? + oneof $ (Bool <$> arbitrary) : if n <= 1 then [] else + [ resize (n `div` 3) $ elements [NotEqual @Integer, Equals, GreaterEqual, Greater, LessEqual, Less] <*> arbitrary <*> arbitrary + , resize (n `div` 5) $ elements [ShortAnd, ShortOr] <*> arbitrary <*> arbitrary + , resize (n `div` 2) $ Not <$> arbitrary + ] + + +instance Arbitrary (ActorScriptTerm (Neuralgic Natural)) where + arbitrary = reasonablyShaped $ subTermPow (`Mod` Five) + +instance Arbitrary (ActorScriptTerm (Neuralgic Integer)) where + arbitrary = reasonablyShaped $ \n -> + [ (n, resize (n `div` 2) $ Pos <$> arbitrary) + , (n, resize (n `div` 2) $ Neg <$> arbitrary) + , (n, resize (n `div` 2) $ Abs <$> arbitrary) + , (n, ConvertNatural <$> arbitrary) + , (n `div` 2, ConvertNat <$> (arbitrary @(ActorScriptTerm (Neuralgic Nat8)))) + , (n `div` 2, ConvertNat <$> (arbitrary @(ActorScriptTerm (Neuralgic Nat16)))) + , (n `div` 2, ConvertNat <$> (arbitrary @(ActorScriptTerm (Neuralgic Nat32)))) + , (n `div` 2, ConvertNat <$> (arbitrary @(ActorScriptTerm (Neuralgic Nat64)))) + , (n `div` 3, ConvertWord <$> (arbitrary @(ActorScriptTerm (Neuralgic Word8)))) + , (n `div` 3, ConvertWord <$> (arbitrary @(ActorScriptTerm (Neuralgic Word16)))) + , (n `div` 3, ConvertWord <$> (arbitrary @(ActorScriptTerm (Neuralgic Word32)))) + , (n `div` 3, ConvertWord <$> (arbitrary @(ActorScriptTerm (Neuralgic Word64)))) + , (n `div` 3, ConvertInt <$> (arbitrary @(ActorScriptTerm (Neuralgic Int8)))) + , (n `div` 3, ConvertInt <$> (arbitrary @(ActorScriptTerm (Neuralgic Int16)))) + , (n `div` 3, ConvertInt <$> (arbitrary @(ActorScriptTerm (Neuralgic Int32)))) + , (n `div` 3, ConvertInt <$> (arbitrary @(ActorScriptTerm (Neuralgic Int64)))) + ] <> subTermPow ((`Mod` Five) . Abs) n + +instance Num a => Num (Maybe a) where + (+) = liftA2 (+) + (-) = liftA2 (-) + (*) = liftA2 (*) + abs = liftA abs + signum = liftA signum + fromInteger = pure . fromInteger + +instance Real a => Real (Maybe a) where + toRational = undefined + +instance Enum a => Enum (Maybe a) + +instance (Enum (Maybe a), Eq a, Integral a) => Integral (Maybe a) where + _ `quotRem` Just 0 = (Nothing, Nothing) + a `quotRem` b = case liftA2 quotRem a b of + Just (pure -> x, pure -> y) -> (x, y) + _ -> (Nothing, Nothing) + + +{- +instance (Eq a, Fractional a) => Fractional (Maybe a) where + _ / Just 0 = Nothing + a / b = liftA2 (/) a b +-} + +evalO TwoLess = \n -> n - 2 +evalO OneLess = \n -> n - 1 +evalO OneMore = (+1) +evalO TwoMore = (+2) + + +evalN LargeNeg = fromIntegral (minBound :: Int) - 111 +evalN (AroundNeg n) = - 2 ^ n +evalN Around0 = 0 +evalN (AroundPos n) = 2 ^ n - 1 +evalN LargePos = fromIntegral (maxBound :: Int) + 333 +evalN (Offset (evalN -> n) (evalO -> o)) = o n + + +guardedEvalN :: Integral a => (Integer -> Maybe a) -> Neuralgic a -> Maybe a +guardedEvalN g (Offset (guardedEvalN g -> n) (evalO -> o)) = g =<< (o . toInteger) <$> n +guardedEvalN g (g . evalN -> res) = res + +noExponentRestriction, nonNegativeExponentRestriction, defaultExponentRestriction :: (Ord a, Num a) => a -> Maybe () +noExponentRestriction _ = pure () +nonNegativeExponentRestriction = guard . (>= 0) +defaultExponentRestriction = guard . ((&&) <$> (>= 0) <*> (< 5)) + +class Restricted a where + substractable :: Maybe a -> Maybe a -> Bool + exponentiable :: (Num a, Ord a) => a -> Maybe () + exponentiable = defaultExponentRestriction + +instance Restricted Integer where substractable _ _ = True +instance Restricted Natural where substractable a b = isJust $ do m <- a; n <- b; guard $ m >= n +instance KnownNat n => Restricted (BitLimited n Natural) where + substractable a b = isJust $ do NatN m <- a; NatN n <- b; guard $ m >= n + exponentiable = if natVal (Proxy @n) <= 8 + then noExponentRestriction + else defaultExponentRestriction +instance KnownNat n => Restricted (BitLimited n Integer) where + exponentiable = if natVal (Proxy @n) <= 8 + then nonNegativeExponentRestriction + else defaultExponentRestriction +instance KnownNat n => Restricted (BitLimited n Word) where + exponentiable = if natVal (Proxy @n) <= 8 + then noExponentRestriction + else defaultExponentRestriction + +class Integral a => Evaluatable a where + evaluate :: ActorScriptTerm (Neuralgic a) -> Maybe a + + +data BitLimited (n :: Nat) (a :: *) where + NatN :: KnownNat n => Natural -> BitLimited n Natural + IntN :: KnownNat n => Integer -> BitLimited n Integer + WordN :: KnownNat n => Natural -> BitLimited n Word + +deriving instance Show (BitLimited n a) +deriving instance Eq (BitLimited n a) +deriving instance Ord (BitLimited n a) + +class WordView a where + type WordType a :: * + toWord :: a -> WordType a + fromWord :: WordType a -> a + lift1 :: (WordType a -> WordType a) -> a -> a + lift1 f (fromWord . f . toWord -> res) = res + lift1b :: (WordType a -> b) -> a -> b + lift1b f (f . toWord -> res) = res + lift2 :: (WordType a -> WordType a -> WordType a) -> a -> a -> a + lift2 f (toWord -> a) (toWord -> b) = fromWord (a `f` b) + + +type family WordTypeForBits a where + WordTypeForBits 8 = Data.Word.Word8 + WordTypeForBits 16 = Data.Word.Word16 + WordTypeForBits 32 = Data.Word.Word32 + WordTypeForBits 64 = Data.Word.Word64 + + +instance (Integral (WordTypeForBits n), FiniteBits (WordTypeForBits n), KnownNat n) => WordView (BitLimited n Word) where + type WordType (BitLimited n Word) = WordTypeForBits n + toWord (WordN n) = fromIntegral n + fromWord = WordN . fromIntegral + +type WordLike n = ( Integral (WordTypeForBits n) + , FiniteBits (WordTypeForBits n) + , KnownNat n + , WordView (BitLimited n Word)) + +instance WordLike n => Bits (BitLimited n Word) where + (.&.) = lift2 (.&.) + (.|.) = lift2 (.|.) + xor = lift2 xor + complement = lift1 complement + shift a b = lift1 (`shift` b) a + rotate a b = lift1 (`rotate` b) a + bitSize = finiteBitSize + bitSizeMaybe = pure . finiteBitSize + isSigned _ = False + testBit a b = lift1b (`testBit` b) a + bit = fromWord . bit + popCount = lift1b popCount + +instance WordLike n => FiniteBits (BitLimited n Word) where + finiteBitSize b = fromIntegral $ natVal (Proxy @n) + countLeadingZeros = lift1b countLeadingZeros + countTrailingZeros = lift1b countTrailingZeros + +type Nat8 = BitLimited 8 Natural +type Nat16 = BitLimited 16 Natural +type Nat32 = BitLimited 32 Natural +type Nat64 = BitLimited 64 Natural +type Int8 = BitLimited 8 Integer +type Int16 = BitLimited 16 Integer +type Int32 = BitLimited 32 Integer +type Int64 = BitLimited 64 Integer +type Word8 = BitLimited 8 Word +type Word16 = BitLimited 16 Word +type Word32 = BitLimited 32 Word +type Word64 = BitLimited 64 Word + +instance ToBitLimited bits a => Num (BitLimited bits a) where + NatN m + NatN n = NatN . fromJust $ trapNat (natVal (Proxy @bits)) (toInteger m + toInteger n) + IntN m + IntN n = IntN . fromJust $ trapInt (natVal (Proxy @bits)) (m + n) + WordN m + WordN n = WordN . fromJust $ trapWord (natVal (Proxy @bits)) (toInteger m + toInteger n) + NatN m - NatN n = NatN . fromJust $ trapNat (natVal (Proxy @bits)) (toInteger m - toInteger n) + IntN m - IntN n = IntN . fromJust $ trapInt (natVal (Proxy @bits)) (m - n) + WordN m - WordN n = WordN . fromJust $ trapWord (natVal (Proxy @bits)) (toInteger m - toInteger n) + NatN m * NatN n = NatN . fromJust $ trapNat (natVal (Proxy @bits)) (toInteger m * toInteger n) + IntN m * IntN n = IntN . fromJust $ trapInt (natVal (Proxy @bits)) (m * n) + WordN m * WordN n = WordN . fromJust $ trapWord (natVal (Proxy @bits)) (toInteger m * toInteger n) + + abs (NatN m) = NatN (abs m) + abs (IntN m) = IntN . fromJust $ trapInt (natVal (Proxy @bits)) (abs m) + abs (WordN m) = WordN (abs m) + + signum (NatN m) = NatN (signum m) + signum (IntN m) = IntN (signum m) + signum (WordN m) = WordN (signum m) + + fromInteger = toBitLimited . fromInteger + +-- Helper class ToBitLimited, to build correct BitLimited variant +class KnownNat bits => ToBitLimited bits a where toBitLimited :: Integer -> BitLimited bits a + +instance KnownNat bits => ToBitLimited bits Natural where + toBitLimited = NatN @bits . fromJust . trapNat (natVal (Proxy @bits)) . fromIntegral +instance KnownNat bits => ToBitLimited bits Integer where + toBitLimited = IntN @bits . fromJust . trapInt (natVal (Proxy @bits)) +instance KnownNat bits => ToBitLimited bits Word where + toBitLimited = WordN @bits . fromJust . trapWord (natVal (Proxy @bits)) . fromIntegral + +instance ToBitLimited n a => Real (BitLimited n a) +instance Enum (BitLimited n a) +instance ToBitLimited n a => Integral (BitLimited n a) where + toInteger (NatN n) = toInteger n + toInteger (IntN n) = n + toInteger (WordN n) = toInteger n + +trapNat :: Integer -> Integer -> Maybe Natural +trapNat n v = do guard (v >= 0 && v < 2 ^ n); pure (fromIntegral v) + +trapInt :: Integer -> Integer -> Maybe Integer +trapInt (pred -> n) v = do guard (v < 2 ^ n && v >= - 2 ^ n); pure v + +trapWord :: Integer -> Integer -> Maybe Natural +trapWord n v = pure . fromIntegral $ v `mod` 2 ^ n + + +instance KnownNat bits => Evaluatable (BitLimited bits Natural) where + evaluate Five = pure $ NatN 5 + evaluate (About n) = NatN <$> trapNat (natVal (Proxy @bits)) (evalN n) + evaluate ab = + case ab of + a `Add` b -> go (+) a b + a `Sub` b -> go (-) a b + a `Mul` b -> go (*) a b + _ `Div` (evaluate -> Just 0) -> Nothing + a `Div` b -> go quot a b + _ `Mod` (evaluate -> Just 0) -> Nothing + a `Mod` b -> go rem a b + a `Pow` b -> do b' <- evaluate b; exponentiable b'; go (^) a b + IfThenElse a b c -> do c <- evalR c + evaluate $ if c then a else b + _ -> error $ show ab + where go op a b = do NatN a <- evaluate a; NatN b <- evaluate b; NatN <$> trapNat (natVal (Proxy @bits)) (toInteger a `op` toInteger b) + +instance KnownNat bits => Evaluatable (BitLimited bits Integer) where + evaluate Five = pure $ IntN 5 + evaluate (About n) = IntN <$> trapInt (natVal (Proxy @bits)) (evalN n) + evaluate ab = + case ab of + a `Add` b -> go (+) a b + a `Sub` b -> go (-) a b + a `Mul` b -> go (*) a b + _ `Div` (evaluate -> Just 0) -> Nothing + a `Div` b -> go quot a b + _ `Mod` (evaluate -> Just 0) -> Nothing + a `Mod` b -> go rem a b + a `Pow` b -> do b' <- evaluate b; exponentiable b'; go (^) a b + IfThenElse a b c -> do c <- evalR c + evaluate $ if c then a else b + _ -> error $ show ab + where go op a b = do IntN a <- evaluate a; IntN b <- evaluate b; IntN <$> trapInt (natVal (Proxy @bits)) (toInteger a `op` toInteger b) + +instance WordLike bits => Evaluatable (BitLimited bits Word) where + evaluate Five = pure $ WordN 5 + evaluate (About n) = WordN <$> trapWord (natVal (Proxy @bits)) (evalN n) + evaluate ab = + case ab of + a `Add` b -> go (+) a b + a `Sub` b -> go (-) a b + a `Mul` b -> go (*) a b + _ `Div` (evaluate -> Just 0) -> Nothing + a `Div` b -> go quot a b + _ `Mod` (evaluate -> Just 0) -> Nothing + a `Mod` b -> go rem a b + a `Pow` b -> do b' <- evaluate b; exponentiable b'; go (^) a b + a `Or` b -> log (.|.) a b + a `And` b -> log (.&.) a b + a `Xor` b -> log xor a b + a `RotL` b -> log (flip rotateL . fromIntegral) b a + a `RotR` b -> log (flip rotateR . fromIntegral) b a + a `ShiftL` b -> log (flip shiftL . (`mod` fromIntegral bitcount) . fromIntegral) b a + a `ShiftR` b -> log (flip shiftR . (`mod` fromIntegral bitcount) . fromIntegral) b a + a `ShiftRSigned` b -> log signedShiftR a b + PopCnt (evaluate -> a) -> fromIntegral . popCount <$> a + Clz (evaluate -> a) -> fromIntegral . countLeadingZeros <$> a + Ctz (evaluate -> a) -> fromIntegral . countTrailingZeros <$> a + IfThenElse a b c -> do c <- evalR c + evaluate $ if c then a else b + _ -> error $ show ab + where go op a b = do WordN a <- evaluate a; WordN b <- evaluate b; WordN <$> trapWord bitcount (toInteger a `op` toInteger b) + log op a b = op <$> evaluate a <*> evaluate b + bitcount = natVal (Proxy @bits) + signedShiftR a b = fromIntegral $ a' `shiftR` (fromIntegral b `mod` fromIntegral bitcount) + where a' = toInteger a - (toInteger (((a `rotateL` 1) .&. 1) `rotateR` 1) `shiftL` 1) +instance Evaluatable Integer where + evaluate = eval +instance Evaluatable Natural where + evaluate = eval + +eval :: (Restricted a, Integral a) => ActorScriptTerm (Neuralgic a) -> Maybe a +eval Five = pure 5 +eval (About n) = evalN n +eval (Pos n) = eval n +eval (Neg n) = - eval n +eval (Abs n) = abs $ eval n +eval (a `Add` b) = eval a + eval b +eval ((eval -> a) `Sub` (eval -> b)) = do guard $ substractable a b; a - b +eval (a `Mul` b) = eval a * eval b +eval (a `Div` b) = eval a `quot` eval b +eval (a `Mod` b) = eval a `rem` eval b +eval (a `Pow` (eval -> b)) = do b' <- b; exponentiable b'; (^) <$> eval a <*> b +eval (ConvertNatural t) = fromIntegral <$> evaluate t +eval (ConvertNat t) = fromIntegral <$> evaluate t +eval (ConvertInt t) = fromIntegral <$> evaluate t +eval (ConvertWord t) = fromIntegral <$> evaluate t +eval (IfThenElse a b c) = do c <- evalR c + eval $ if c then a else b +eval (Rel r) = bool 0 1 <$> evalR r +--eval _ = Nothing + +evalR :: ActorScriptTyped a -> Maybe a +evalR (a `NotEqual` b) = (/=) <$> evaluate a <*> evaluate b +evalR (a `Equals` b) = (==) <$> evaluate a <*> evaluate b +evalR (a `GreaterEqual` b) = (>=) <$> evaluate a <*> evaluate b +evalR (a `Greater` b) = (>) <$> evaluate a <*> evaluate b +evalR (a `LessEqual` b) = (<=) <$> evaluate a <*> evaluate b +evalR (a `Less` b) = (<) <$> evaluate a <*> evaluate b +evalR (a `ShortAnd` b) = evalR a >>= bool (pure False) (evalR b) +evalR (a `ShortOr` b) = evalR a >>= bool (evalR b) (pure True) +evalR (Not a) = not <$> evalR a +evalR (Bool b) = pure b + + +class Annot t where + annot :: ActorScriptTerm (Neuralgic t) -> String -> String + sizeSuffix :: ActorScriptTerm (Neuralgic t) -> String -> String + sizeSuffix _ = id + +instance Annot Integer where + annot _ s = "((" <> s <> ") : Int)" + +instance Annot Natural where + annot _ s = "((" <> s <> ") : Nat)" + + +bitWidth :: KnownNat n => Proxy n -> String +bitWidth p = show (natVal p) + +instance KnownNat n => Annot (BitLimited n Natural) where + annot _ s = "((" <> s <> ") : Nat" <> bitWidth (Proxy @n) <> ")" + +instance KnownNat n => Annot (BitLimited n Integer) where + annot _ s = "((" <> s <> ") : Int" <> bitWidth (Proxy @n) <> ")" + +instance KnownNat n => Annot (BitLimited n Word) where + annot _ s = "((" <> s <> ") : Word" <> bitWidth (Proxy @n) <> ")" + sizeSuffix _ = (<> bitWidth (Proxy @n)) + +instance Annot Bool where + annot _ = id + +class Literal a where + literal :: Neuralgic a -> String + literal (evalN -> n) = if n < 0 then "(" <> show n <> ")" else show n + +instance Literal Integer +instance Literal Natural +instance Literal (BitLimited n Natural) +instance KnownNat bits => Literal (BitLimited bits Integer) where + -- compensate for https://github.com/dfinity-lab/actorscript/issues/505 + literal (evalN -> n) = if buggy n then "intToInt" <> bitWidth pr <> "(" <> show n <> ")" + else if n < 0 + then "(" <> show n <> ")" + else show n + where buggy n = n == - 2 ^ (numbits - 1) + numbits = natVal pr + pr = Proxy @bits +instance KnownNat bits => Literal (BitLimited bits Word) where + literal n = show . fromJust $ trapWord (natVal (Proxy @bits)) (evalN n) + +instance Literal Bool where + literal _ = undefined + +inParens :: (a -> String) -> String -> a -> a -> String +inParens to op lhs rhs = "(" <> to lhs <> " " <> op <> " " <> to rhs <> ")" + +unparseAS :: (Annot a, Literal a) => ActorScriptTerm (Neuralgic a) -> String +unparseAS f@Five = annot f "5" +unparseAS a@(About n) = annot a $ literal n +unparseAS (Pos n) = "(+" <> unparseAS n <> ")" +unparseAS (Neg n) = "(-" <> unparseAS n <> ")" +unparseAS (Abs n) = "(abs " <> unparseAS n <> ")" +unparseAS (a `Add` b) = inParens unparseAS "+" a b +unparseAS (a `Sub` b) = annot a $ inParens unparseAS "-" a b +unparseAS (a `Mul` b) = inParens unparseAS "*" a b +unparseAS (a `Div` b) = inParens unparseAS "/" a b +unparseAS (a `Mod` b) = inParens unparseAS "%" a b +unparseAS (a `Pow` b) = inParens unparseAS "**" a b +unparseAS (a `Or` b) = inParens unparseAS "|" a b +unparseAS (a `And` b) = inParens unparseAS "&" a b +unparseAS (a `Xor` b) = inParens unparseAS "^" a b +unparseAS (a `RotL` b) = inParens unparseAS "<<>" a b +unparseAS (a `RotR` b) = inParens unparseAS "<>>" a b +unparseAS (a `ShiftL` b) = inParens unparseAS "<<" a b +unparseAS (a `ShiftR` b) = inParens unparseAS ">>" a b +unparseAS (a `ShiftRSigned` b) = inParens unparseAS "+>>" a b +unparseAS (PopCnt n) = sizeSuffix n "(popcntWord" <> " " <> unparseAS n <> ")" +unparseAS (Clz n) = sizeSuffix n "(clzWord" <> " " <> unparseAS n <> ")" +unparseAS (Ctz n) = sizeSuffix n "(ctzWord" <> " " <> unparseAS n <> ")" +unparseAS (ConvertNatural a) = "(++++(" <> unparseAS a <> "))" +unparseAS (ConvertNat a) = unparseNat Proxy a +unparseAS (ConvertInt a) = unparseInt Proxy a +unparseAS (ConvertWord a) = unparseWord Proxy a +unparseAS (Rel r) = unparseBool r +unparseAS (IfThenElse a b c) = "(if (" <> unparseBool c <> ") " <> unparseAS a <> " else " <> unparseAS b <> ")" + +unparseBool :: ActorScriptTyped Bool -> String +unparseBool (a `NotEqual` b) = inParens unparseAS "!=" a b +unparseBool (a `Equals` b) = inParens unparseAS "==" a b +unparseBool (a `GreaterEqual` b) = inParens unparseAS ">=" a b +unparseBool (a `Greater` b) = inParens unparseAS ">" a b +unparseBool (a `LessEqual` b) = inParens unparseAS "<=" a b +unparseBool (a `Less` b) = inParens unparseAS "<" a b +unparseBool (a `ShortAnd` b) = inParens unparseBool "and" a b +unparseBool (a `ShortOr` b) = inParens unparseBool "or" a b +unparseBool (Not a) = "(not " <> unparseBool a <> ")" +unparseBool (Bool False) = "false" +unparseBool (Bool True) = "true" + +unparseNat :: KnownNat n => Proxy n -> ActorScriptTerm (Neuralgic (BitLimited n Natural)) -> String +unparseNat p a = "(nat" <> bitWidth p <> "ToNat(" <> unparseAS a <> "))" + +unparseInt :: KnownNat n => Proxy n -> ActorScriptTerm (Neuralgic (BitLimited n Integer)) -> String +unparseInt p a = "(int" <> bitWidth p <> "ToInt(" <> unparseAS a <> "))" + +unparseWord :: KnownNat n => Proxy n -> ActorScriptTerm (Neuralgic (BitLimited n Word)) -> String +unparseWord p a = "(word" <> bitWidth p <> "ToNat(" <> unparseAS a <> "))" -- TODO we want signed too: wordToInt + + + +-- TODOs: +-- - wordToInt +-- - bitwise ops (btst?) +-- - bitwise not, a.k.a unary (^) +-- - pattern matches (over numeric, bool) diff --git a/test/random/README.md b/test/random/README.md new file mode 100644 index 00000000000..ed2fe5dda8d --- /dev/null +++ b/test/random/README.md @@ -0,0 +1,63 @@ +# QA tool `qc-actorscript` + +This tool generates ActorScript AST fragments and executes them, +checking for the same outcome as the Haskell (here: reference) +implementation. + +In order to compile and test it expects following tools to be in the +`PATH`: +- `asc` (the ActorScript compiler) +- `wasm-interp` (part of `nixpkgs.wabt`) + +## How to spot failures + +`qc-actorscript` is run from the CI infrastructure on each commit. On failures, something like + +``` + Properties + (checked by QuickCheck) + expected failures: FAIL (0.08s) + *** Failed! Assertion failed (after 1 test): + Failing "let _ = (-(nat32ToNat(((((0) : Nat32) * ((65535) : Nat32)) % (((65535) : Nat32) * ((0) : Nat32))))));" + Use --quickcheck-replay=232458 to reproduce. + expected successes: OK (13.22s) + +++ OK, passed 100 tests. + +1 out of 2 tests failed (13.30s) +``` + +will appear in the CI log. The relevant recipe for reliable reproduction is the +`--quickcheck-replay=232458` hint. + +## How to run locally + +With this piece of information you can run the identical test locally, +using the following `nix-build` invocation from your `actorscript` +directory: +``` shell +$ nix-build -A tests --arg replay 232458 +``` + +## Running in `asc` and `wasm-interp` + +Of course you can dump the failing test case into a file, compile it +to WASM, and execute it in (e.g.) `wasm-interp`: + +``` shell +$ asc -no-dfinity-api snippet.as +$ wasm-interp --enable-multi snippet.wasm +``` + +In tests under category *expected failures*, this should trap. +For *expected successes* it should execute without errors. + +## Troubleshooting + +When something doesn't build like expected, check for a file called (approximately) +`test/random/.ghc.environment.x86_64-darwin-8.6.4`. This usually trips +up `nix-build`'s ability to build `qc-actorscript` locally, and should +be deleted. + +## 0 -- 2019-08-08 + +* First version. Released on a suspecting world. See also [GitHub issue 609](https://github.com/dfinity-lab/actorscript/pull/609). diff --git a/test/random/qc-actorscript.cabal b/test/random/qc-actorscript.cabal new file mode 100644 index 00000000000..1bcdd9be7ae --- /dev/null +++ b/test/random/qc-actorscript.cabal @@ -0,0 +1,25 @@ +cabal-version: 2.4 + +name: qc-actorscript +version: 0 +synopsis: generate randomised tests for ActorScript +-- description: +author: Gabor Greif +maintainer: gabor@dfinity.org +-- copyright: +category: Testing +extra-source-files: CHANGELOG.md + +executable qc-actorscript + main-is: Main.hs + -- other-modules: + other-extensions: ConstraintKinds, StandaloneDeriving, DataKinds, KindSignatures, GADTs, MultiParamTypeClasses + build-depends: base ^>=4.12.0.0 + , text ^>=1.2.3.1 + , process + , QuickCheck + , tasty + , tasty-quickcheck + , turtle + -- hs-source-dirs: + default-language: Haskell2010 From ea54f84e89c6af2114466eca7a56123d036e3219 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Fri, 9 Aug 2019 13:51:18 -0700 Subject: [PATCH 0343/1176] add comments for inlining --- src/as_idl/as_to_idl.ml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/as_idl/as_to_idl.ml b/src/as_idl/as_to_idl.ml index 32f98b23388..38f45144674 100644 --- a/src/as_idl/as_to_idl.ml +++ b/src/as_idl/as_to_idl.ml @@ -91,6 +91,9 @@ let rec typ vs t = ) ts in (match Con.kind c with | Def (tbs, t) -> + (* use this for inlining defs, doesn't work with recursion + (typ ts t).it + *) chase_con ts c; I.VarT (string_of_con ts c @@ no_region) | _ -> assert false) From ed6f02e4c7ff98754faf15b655fc55993081ac3f Mon Sep 17 00:00:00 2001 From: Christoph Hegemann Date: Mon, 12 Aug 2019 13:49:11 +0200 Subject: [PATCH 0344/1176] Adds a minimal LSP setup for Emacs (#612) * adds a minimal setup for Emacs * set better defaults --- emacs/README.md | 8 +++++ emacs/init.el | 94 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 emacs/README.md create mode 100644 emacs/init.el diff --git a/emacs/README.md b/emacs/README.md new file mode 100644 index 00000000000..ac7dd969504 --- /dev/null +++ b/emacs/README.md @@ -0,0 +1,8 @@ +ActorScript Emacs playground +=== + +A minimal set of packages + configuration that lets you use the ActorScript LSP support from within Emacs without having to change your personal configuration. + +## Getting started + +Read the instructions in `init.el` diff --git a/emacs/init.el b/emacs/init.el new file mode 100644 index 00000000000..21ced8a3678 --- /dev/null +++ b/emacs/init.el @@ -0,0 +1,94 @@ +;; ActorScript Emacs IDE +;; === +;; +;; A minimal set of packages + configuration that lets you use the +;; ActorScript LSP support from within Emacs without having to change +;; your personal configuration. +;; +;; Requirements: +;; - Emacs 26 or newer +;; - `as-ide` binary (Can be generated with `make as-ide` in the +;; compiler repo) +;; +;; How to use: +;; +;; 1. Change the settings below to match your setup and preferences +;; +;; 2. Start Emacs from your command line like so: +;; +;; `emacs -q --load ~/code/actorscript/emacs/init.el` +;; +;; (adjust to match the path to this file) +;; +;; 3. Open an AS source file in an AS project and select the project +;; root from the menu + +;;======== SETTINGS ========== +;; Change this to point to your `as-ide` binary, or leave it if the +;; binary can be found on your PATH +(setq as/ide-binary "as-ide") + +;; Change this to point to the directory where you cloned the +;; actorscript repo +(setq as/installation-directory "~/code/actorscript") + +;; Change nil to t if you want to use vim bindings for editing and +;; navigation +(setq as/use-evil nil) +;;============================ + +(require 'package) +(setq package-enable-at-startup nil) +(setq package-archives + '(("gnu" . "http://elpa.gnu.org/packages/") + ("melpa" . "https://melpa.org/packages/"))) +(package-initialize) +(unless (package-installed-p 'use-package) + (package-refresh-contents) + (package-install 'use-package)) +(require 'use-package) + +;; We use ivy to make the popup asking for the project root +;; non-obnoxious. It's not necessarily required for the LSP to work, +;; so if you're working this into your existing config helm would work +;; just as well. +(use-package ivy + :ensure t + :config (ivy-mode 1)) + +(use-package swift-mode :ensure t) +(eval-and-compile + (defun as/as-mode-load-path () + (format "%s/emacs" as/installation-directory))) +(use-package actorscript-mode + :load-path (lambda () (list (as/as-mode-load-path))) + :config + (add-hook 'actorscript-mode-hook 'flycheck-mode) + (add-hook 'actorscript-mode-hook 'lsp) + (add-hook 'actorscript-mode-hook 'company-mode)) + +(use-package lsp-mode :ensure t + :config + (setq lsp-prefer-flymake nil) + (setq lsp-auto-configure t) + (add-to-list 'lsp-language-id-configuration '(actorscript-mode . "actorscript")) + (lsp-register-client + (make-lsp-client + :new-connection (lsp-stdio-connection as/ide-binary) + :major-modes '(actorscript-mode) + :server-id 'asls))) + +(use-package lsp-ui :ensure t :commands lsp-ui-mode) +(use-package company :ensure t) +(use-package company-lsp :ensure t :commands company-lsp) +(use-package yasnippet :ensure t) +(use-package flycheck :ensure t) + +(when as/use-evil + (use-package evil + :ensure t + :init + (progn + (setq evil-want-C-u-scroll t) + (evil-mode 1) + (evil-declare-change-repeat 'company-complete)))) From 7b2139c505cd721cb630789371cc578871f3c83b Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Tue, 13 Aug 2019 10:50:22 +0200 Subject: [PATCH 0345/1176] compile CharLit patterns (#615) * compile CharLit patterns * add test --- src/codegen/compile.ml | 5 ++++- test/run/char-pats.as | 12 ++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 test/run/char-pats.as diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index da7b5b306c7..67c4e57d9ab 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -6222,11 +6222,14 @@ and compile_lit_pat env l = BoxedSmallWord.unbox env ^^ snd (compile_lit env l) ^^ compile_eq env Type.(Prim Word32) + | CharLit _ -> + snd (compile_lit env l) ^^ + compile_eq env Type.(Prim Char) | Word64Lit _ -> BoxedWord64.unbox env ^^ snd (compile_lit env l) ^^ compile_eq env Type.(Prim Word64) - | (TextLit t) -> + | TextLit t -> Text.lit env t ^^ Text.compare env | _ -> todo_trap env "compile_lit_pat" (Arrange_ir.lit l) diff --git a/test/run/char-pats.as b/test/run/char-pats.as new file mode 100644 index 00000000000..eaee5fbca34 --- /dev/null +++ b/test/run/char-pats.as @@ -0,0 +1,12 @@ +switch 'a' { + case 'b' assert false; + case 'a' assert true; + case _ assert false; +}; + +switch (?'\u{28ae4}') { + case (?'a') assert false; + case (?'\u{28ae4}') assert true; + case _ assert false; +} + From ab3f3979b67efce997d72bd34341b68fee25b6c3 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Tue, 13 Aug 2019 11:08:17 +0200 Subject: [PATCH 0346/1176] Text roundtrip tests [ACT-110 related] (#614) * test charToText followed by decodeUTF8 roundtrip * test explode followed by concat --- test/random/Main.hs | 73 +++++++++++++++++++++++++------- test/random/qc-actorscript.cabal | 3 ++ 2 files changed, 61 insertions(+), 15 deletions(-) diff --git a/test/random/Main.hs b/test/random/Main.hs index ea8c3e1dd9c..5bab517efe0 100644 --- a/test/random/Main.hs +++ b/test/random/Main.hs @@ -12,6 +12,7 @@ import Control.Monad import Test.QuickCheck.Monadic import Test.Tasty import Test.Tasty.QuickCheck as QC hiding ((.&.)) +import Test.QuickCheck.Unicode import qualified Data.Text (null, unpack) import Data.Maybe import Data.Bool (bool) @@ -20,24 +21,74 @@ import GHC.Natural import GHC.TypeLits import qualified Data.Word import Data.Bits (Bits(..), FiniteBits(..)) +import qualified Data.ByteString.UTF8 +import Numeric import System.Process hiding (proc) import Turtle -import Debug.Trace (traceShowId) +-- import Debug.Trace (traceShowId) main = defaultMain tests where tests :: TestTree - tests = testGroup "Arithmetic-logic operations" [properties] + tests = testGroup "ActorScript tests" [arithProps, utf8Props] -properties :: TestTree -properties = testGroup "Properties" [qcProps] - -qcProps = testGroup "(checked by QuickCheck)" +arithProps = testGroup "Arithmetic/logic" [ QC.testProperty "expected failures" $ prop_rejects , QC.testProperty "expected successes" $ prop_verifies ] +utf8Props = testGroup "UTF-8 coding" + [ QC.testProperty "explode >>> concat roundtrips" $ prop_explodeConcat + , QC.testProperty "charToText >>> decodeUTF8 roundtrips" $ prop_charToText + ] + + +(runScriptNoFuzz, runScriptWantFuzz) = (runner id, runner not) + where runner relevant name testCase = + let as = name <.> "as" + wasm = name <.> "wasm" + fileArg = fromString . encodeString + script = do Turtle.output as $ fromString testCase + res@(exitCode, _, _) <- procStrictWithErr "asc" + ["-no-dfinity-api", "-no-check-ir", fileArg as] empty + if ExitSuccess == exitCode + then (True,) <$> procStrictWithErr "wasm-interp" ["--enable-multi", fileArg wasm] empty + else pure (False, res) + in run script >>= assertSuccessNoFuzz relevant + +prop_explodeConcat :: UTF8 String -> Property +prop_explodeConcat (UTF8 str) = monadicIO $ do + let testCase :: String + testCase = "{ var str = \"\"; for (c in \"" + <> s <> "\".chars()) { str #= charToText c }; assert (str == \"" <> s <> "\") }" + + s = concatMap escape str + runScriptNoFuzz "explodeConcat" testCase + +-- TODO: why can't we use Test.QuickCheck.Unicode.Unicode? (see https://github.com/bos/quickcheck-unicode/issues/5) +newtype UTF8 a = UTF8 a deriving Show + +instance Arbitrary (UTF8 String) where + arbitrary = UTF8 <$> string1 + +instance Arbitrary (UTF8 Char) where + arbitrary = UTF8 <$> Test.QuickCheck.Unicode.char + +hex :: Int -> String +hex = (`showHex` "") + +escape ch | '\\' `elem` show ch = "\\u{" <> hex (fromEnum ch) <> "}" +escape '"' = "\\\"" +escape ch = pure ch + +prop_charToText (UTF8 char) = monadicIO $ do + let testCase = "assert (switch (decodeUTF8 (charToText '" + <> c <> "')) { case (" <> show octets <> ", '" <> c <> "') true; case _ false })" + + c = escape char + Just (_, octets) = Data.ByteString.UTF8.decode (Data.ByteString.UTF8.fromString $ pure char) + runScriptNoFuzz "charToText" testCase assertSuccessNoFuzz relevant (compiled, (exitCode, out, err)) = do let fuzzErr = not $ Data.Text.null err @@ -57,15 +108,7 @@ instance Arbitrary (Failing String) where arbitrary = do let failed as = "let _ = " ++ unparseAS as ++ ";" Failing . failed <$> suchThat (resize 5 arbitrary) (\(evaluate @ Integer -> res) -> null res) -prop_rejects (Failing testCase) = monadicIO $ do - let script = do Turtle.output "fails.as" $ fromString testCase - res@(exitCode, _, _) <- procStrictWithErr "asc" - ["-no-dfinity-api", "-no-check-ir", "fails.as"] empty - if ExitSuccess == exitCode - then (True,) <$> procStrictWithErr "wasm-interp" ["--enable-multi", "fails.wasm"] empty - else pure (False, res) - run script >>= assertSuccessNoFuzz not - +prop_rejects (Failing testCase) = monadicIO $ runScriptWantFuzz "fails" testCase halve [] = ([], []) halve a@[_] = (a, []) diff --git a/test/random/qc-actorscript.cabal b/test/random/qc-actorscript.cabal index 1bcdd9be7ae..3c9ecd8fe97 100644 --- a/test/random/qc-actorscript.cabal +++ b/test/random/qc-actorscript.cabal @@ -18,8 +18,11 @@ executable qc-actorscript , text ^>=1.2.3.1 , process , QuickCheck + , quickcheck-text + , quickcheck-unicode , tasty , tasty-quickcheck , turtle + , utf8-string -- hs-source-dirs: default-language: Haskell2010 From a94b8aa824aa9b79e44f4c8790bb662d42389f01 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Tue, 13 Aug 2019 20:50:22 +0200 Subject: [PATCH 0347/1176] Exclude surrogates (#617) * exclude surrogates when parsing (in Char and Text) * exclude surrogates from word32ToChar in interpreter * trap for surrogates in word32ToChar codegen * reject surrogates in IDL lexer * test unicode escapes in IDL --- src/as_frontend/lexer.mll | 2 +- src/as_values/prim.ml | 2 +- src/codegen/compile.ml | 6 ++++++ src/idllib/lexer.mll | 2 +- test/fail/char-high-surrogate-trap.as | 1 + test/fail/char-high-surrogate.as | 1 + test/fail/char-low-surrogate-trap.as | 1 + test/fail/char-low-surrogate.as | 1 + test/fail/ok/char-high-surrogate-trap.run-ir.ok | 1 + test/fail/ok/char-high-surrogate-trap.run-low.ok | 1 + test/fail/ok/char-high-surrogate-trap.run.ok | 1 + test/fail/ok/char-high-surrogate-trap.wasm-run.ok | 1 + test/fail/ok/char-high-surrogate.tc.ok | 1 + test/fail/ok/char-low-surrogate-trap.run-ir.ok | 1 + test/fail/ok/char-low-surrogate-trap.run-low.ok | 1 + test/fail/ok/char-low-surrogate-trap.run.ok | 1 + test/fail/ok/char-low-surrogate-trap.wasm-run.ok | 1 + test/fail/ok/char-low-surrogate.tc.ok | 1 + test/fail/ok/text-high-surrogate.tc.ok | 1 + test/fail/ok/text-low-surrogate.tc.ok | 1 + test/fail/text-high-surrogate.as | 1 + test/fail/text-low-surrogate.as | 1 + test/idl/ok/surrogate.tc.ok | 1 + test/idl/ok/unicode.js.ok | 4 ++-- test/idl/surrogate.did | 3 +++ test/idl/unicode.did | 1 + 26 files changed, 34 insertions(+), 5 deletions(-) create mode 100644 test/fail/char-high-surrogate-trap.as create mode 100644 test/fail/char-high-surrogate.as create mode 100644 test/fail/char-low-surrogate-trap.as create mode 100644 test/fail/char-low-surrogate.as create mode 100644 test/fail/ok/char-high-surrogate-trap.run-ir.ok create mode 100644 test/fail/ok/char-high-surrogate-trap.run-low.ok create mode 100644 test/fail/ok/char-high-surrogate-trap.run.ok create mode 100644 test/fail/ok/char-high-surrogate-trap.wasm-run.ok create mode 100644 test/fail/ok/char-high-surrogate.tc.ok create mode 100644 test/fail/ok/char-low-surrogate-trap.run-ir.ok create mode 100644 test/fail/ok/char-low-surrogate-trap.run-low.ok create mode 100644 test/fail/ok/char-low-surrogate-trap.run.ok create mode 100644 test/fail/ok/char-low-surrogate-trap.wasm-run.ok create mode 100644 test/fail/ok/char-low-surrogate.tc.ok create mode 100644 test/fail/ok/text-high-surrogate.tc.ok create mode 100644 test/fail/ok/text-low-surrogate.tc.ok create mode 100644 test/fail/text-high-surrogate.as create mode 100644 test/fail/text-low-surrogate.as create mode 100644 test/idl/ok/surrogate.tc.ok create mode 100644 test/idl/surrogate.did diff --git a/src/as_frontend/lexer.mll b/src/as_frontend/lexer.mll index 5fbb4473a25..32ab8f6972b 100644 --- a/src/as_frontend/lexer.mll +++ b/src/as_frontend/lexer.mll @@ -44,7 +44,7 @@ let codepoint lexbuf s i = i := String.index_from s j '}'; (try let n = int_of_string ("0x" ^ String.sub s j (!i - j)) in - if 0 <= n && n < 0x110000 then n else raise (Failure "") + if 0 <= n && n < 0xD800 || 0xE000 <= n && n < 0x110000 then n else raise (Failure "") with Failure _ -> error lexbuf "unicode escape out of range") | h -> incr i; diff --git a/src/as_values/prim.ml b/src/as_values/prim.ml index 9fbecd362c1..8728b037579 100644 --- a/src/as_values/prim.ml +++ b/src/as_values/prim.ml @@ -193,7 +193,7 @@ let num_conv_prim t1 t2 = in k (Word32 (Word32.of_int_u i)) | T.Word32, T.Char -> fun v k -> let i = Conv.of_signed_Word32 (as_word32 v) - in if i <= 0x10FFFF then k (Char i) else raise (Invalid_argument "codepoint out of bounds") + in if i <= 0xD7FF || i >= 0xE000 && i <= 0x10FFFF then k (Char i) else raise (Invalid_argument "codepoint out of bounds") | t1, t2 -> raise (Invalid_argument ("Value.num_conv_prim: " ^ T.string_of_typ (T.Prim t1) ^ T.string_of_typ (T.Prim t2) )) let prim = function diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 67c4e57d9ab..d2583393ae8 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -5863,8 +5863,14 @@ and compile_exp (env : E.t) ae exp = compile_exp_as env ae SR.UnboxedWord32 e ^^ Func.share_code1 env "Word32->Char" ("n", I32Type) [I32Type] (fun env get_n -> + get_n ^^ compile_unboxed_const 0xD800l ^^ + G.i (Compare (Wasm.Values.I32 I32Op.GeU)) ^^ + get_n ^^ compile_unboxed_const 0xE000l ^^ + G.i (Compare (Wasm.Values.I32 I32Op.LtU)) ^^ + G.i (Binary (Wasm.Values.I32 I32Op.And)) ^^ get_n ^^ compile_unboxed_const 0x10FFFFl ^^ G.i (Compare (Wasm.Values.I32 I32Op.GtU)) ^^ + G.i (Binary (Wasm.Values.I32 I32Op.Or)) ^^ E.then_trap_with env "codepoint out of range" ^^ get_n ^^ UnboxedSmallWord.box_codepoint) diff --git a/src/idllib/lexer.mll b/src/idllib/lexer.mll index cccb54a8cdd..6cc856a2955 100644 --- a/src/idllib/lexer.mll +++ b/src/idllib/lexer.mll @@ -42,7 +42,7 @@ let codepoint lexbuf s i = i := String.index_from s j '}'; (try let n = int_of_string ("0x" ^ String.sub s j (!i - j)) in - if 0 <= n && n < 0x110000 then n else raise (Failure "") + if 0 <= n && n < 0xD800 || 0xE000 <= n && n < 0x110000 then n else raise (Failure "") with Failure _ -> error lexbuf "unicode escape out of range") | h -> incr i; diff --git a/test/fail/char-high-surrogate-trap.as b/test/fail/char-high-surrogate-trap.as new file mode 100644 index 00000000000..f643094a948 --- /dev/null +++ b/test/fail/char-high-surrogate-trap.as @@ -0,0 +1 @@ +let _ = word32ToChar 0xdfff diff --git a/test/fail/char-high-surrogate.as b/test/fail/char-high-surrogate.as new file mode 100644 index 00000000000..b38f68811ba --- /dev/null +++ b/test/fail/char-high-surrogate.as @@ -0,0 +1 @@ +let _ = '\u{dfff}'; diff --git a/test/fail/char-low-surrogate-trap.as b/test/fail/char-low-surrogate-trap.as new file mode 100644 index 00000000000..aada8d6bd59 --- /dev/null +++ b/test/fail/char-low-surrogate-trap.as @@ -0,0 +1 @@ +let _ = word32ToChar 0xd800 diff --git a/test/fail/char-low-surrogate.as b/test/fail/char-low-surrogate.as new file mode 100644 index 00000000000..50ad85b433c --- /dev/null +++ b/test/fail/char-low-surrogate.as @@ -0,0 +1 @@ +let _ = '\u{d800}'; diff --git a/test/fail/ok/char-high-surrogate-trap.run-ir.ok b/test/fail/ok/char-high-surrogate-trap.run-ir.ok new file mode 100644 index 00000000000..46eac08816e --- /dev/null +++ b/test/fail/ok/char-high-surrogate-trap.run-ir.ok @@ -0,0 +1 @@ +prelude:___: execution error, codepoint out of bounds diff --git a/test/fail/ok/char-high-surrogate-trap.run-low.ok b/test/fail/ok/char-high-surrogate-trap.run-low.ok new file mode 100644 index 00000000000..46eac08816e --- /dev/null +++ b/test/fail/ok/char-high-surrogate-trap.run-low.ok @@ -0,0 +1 @@ +prelude:___: execution error, codepoint out of bounds diff --git a/test/fail/ok/char-high-surrogate-trap.run.ok b/test/fail/ok/char-high-surrogate-trap.run.ok new file mode 100644 index 00000000000..46eac08816e --- /dev/null +++ b/test/fail/ok/char-high-surrogate-trap.run.ok @@ -0,0 +1 @@ +prelude:___: execution error, codepoint out of bounds diff --git a/test/fail/ok/char-high-surrogate-trap.wasm-run.ok b/test/fail/ok/char-high-surrogate-trap.wasm-run.ok new file mode 100644 index 00000000000..f8094194cdc --- /dev/null +++ b/test/fail/ok/char-high-surrogate-trap.wasm-run.ok @@ -0,0 +1 @@ +_out/char-high-surrogate-trap.wasm:0x___: runtime trap: unreachable executed diff --git a/test/fail/ok/char-high-surrogate.tc.ok b/test/fail/ok/char-high-surrogate.tc.ok new file mode 100644 index 00000000000..d6971c274cc --- /dev/null +++ b/test/fail/ok/char-high-surrogate.tc.ok @@ -0,0 +1 @@ +char-high-surrogate.as:1.9-1.19: syntax error, unicode escape out of range diff --git a/test/fail/ok/char-low-surrogate-trap.run-ir.ok b/test/fail/ok/char-low-surrogate-trap.run-ir.ok new file mode 100644 index 00000000000..46eac08816e --- /dev/null +++ b/test/fail/ok/char-low-surrogate-trap.run-ir.ok @@ -0,0 +1 @@ +prelude:___: execution error, codepoint out of bounds diff --git a/test/fail/ok/char-low-surrogate-trap.run-low.ok b/test/fail/ok/char-low-surrogate-trap.run-low.ok new file mode 100644 index 00000000000..46eac08816e --- /dev/null +++ b/test/fail/ok/char-low-surrogate-trap.run-low.ok @@ -0,0 +1 @@ +prelude:___: execution error, codepoint out of bounds diff --git a/test/fail/ok/char-low-surrogate-trap.run.ok b/test/fail/ok/char-low-surrogate-trap.run.ok new file mode 100644 index 00000000000..46eac08816e --- /dev/null +++ b/test/fail/ok/char-low-surrogate-trap.run.ok @@ -0,0 +1 @@ +prelude:___: execution error, codepoint out of bounds diff --git a/test/fail/ok/char-low-surrogate-trap.wasm-run.ok b/test/fail/ok/char-low-surrogate-trap.wasm-run.ok new file mode 100644 index 00000000000..af88b01be92 --- /dev/null +++ b/test/fail/ok/char-low-surrogate-trap.wasm-run.ok @@ -0,0 +1 @@ +_out/char-low-surrogate-trap.wasm:0x___: runtime trap: unreachable executed diff --git a/test/fail/ok/char-low-surrogate.tc.ok b/test/fail/ok/char-low-surrogate.tc.ok new file mode 100644 index 00000000000..d8b84c45181 --- /dev/null +++ b/test/fail/ok/char-low-surrogate.tc.ok @@ -0,0 +1 @@ +char-low-surrogate.as:1.9-1.19: syntax error, unicode escape out of range diff --git a/test/fail/ok/text-high-surrogate.tc.ok b/test/fail/ok/text-high-surrogate.tc.ok new file mode 100644 index 00000000000..18a9b5e868e --- /dev/null +++ b/test/fail/ok/text-high-surrogate.tc.ok @@ -0,0 +1 @@ +text-high-surrogate.as:1.9-1.19: syntax error, unicode escape out of range diff --git a/test/fail/ok/text-low-surrogate.tc.ok b/test/fail/ok/text-low-surrogate.tc.ok new file mode 100644 index 00000000000..6ba634e6205 --- /dev/null +++ b/test/fail/ok/text-low-surrogate.tc.ok @@ -0,0 +1 @@ +text-low-surrogate.as:1.9-1.19: syntax error, unicode escape out of range diff --git a/test/fail/text-high-surrogate.as b/test/fail/text-high-surrogate.as new file mode 100644 index 00000000000..1aa2b844aea --- /dev/null +++ b/test/fail/text-high-surrogate.as @@ -0,0 +1 @@ +let _ = "\u{dfff}"; diff --git a/test/fail/text-low-surrogate.as b/test/fail/text-low-surrogate.as new file mode 100644 index 00000000000..56a05e0758b --- /dev/null +++ b/test/fail/text-low-surrogate.as @@ -0,0 +1 @@ +let _ = "\u{d800}"; diff --git a/test/idl/ok/surrogate.tc.ok b/test/idl/ok/surrogate.tc.ok new file mode 100644 index 00000000000..f2ff537eb35 --- /dev/null +++ b/test/idl/ok/surrogate.tc.ok @@ -0,0 +1 @@ +surrogate.did:2.2-2.12: syntax error, unicode escape out of range diff --git a/test/idl/ok/unicode.js.ok b/test/idl/ok/unicode.js.ok index 47b5d653c9c..f8f246b20ae 100644 --- a/test/idl/ok/unicode.js.ok +++ b/test/idl/ok/unicode.js.ok @@ -1,7 +1,7 @@ const IDL = require('IDL') const A = - IDL.Obj({'📦🍦': IDL.Nat, '字段名': IDL.Nat, '字 段 名2': IDL.Nat - }) + IDL.Obj({'': IDL.Nat, '📦🍦': IDL.Nat, '字段名': IDL.Nat, + '字 段 名2': IDL.Nat}) const B = IDL.Variant({'': IDL.Unit, '空的': IDL.Unit, ' 空的 ': IDL.Unit, '1⃣️2⃣️3⃣️': IDL.Unit}) diff --git a/test/idl/surrogate.did b/test/idl/surrogate.did new file mode 100644 index 00000000000..a57fbce381f --- /dev/null +++ b/test/idl/surrogate.did @@ -0,0 +1,3 @@ +type A = record { + "\u{D800}":nat; +}; diff --git a/test/idl/unicode.did b/test/idl/unicode.did index ebf9fe334c5..55f94072c14 100644 --- a/test/idl/unicode.did +++ b/test/idl/unicode.did @@ -2,6 +2,7 @@ type A = record { "字段名":nat; "字 段 名2":nat; "📦🍦":nat; + "\u{E000}":nat; }; type B = variant { ""; "空的"; " 空的 "; "1⃣️2⃣️3⃣️"; }; From d32ffa6e32b5716e65b37ccf9bc7a01afd7f589c Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Wed, 14 Aug 2019 15:27:21 +0200 Subject: [PATCH 0348/1176] Update README.md (#619) `Nat` and `Int` are arbitrary precision now. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cac77ff8c15..cfd0456bd04 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ A simple language for writing Dfinity actors. ### Types * Primitive types: integers, naturals, words, floats, characters, (unicode) text, bool, null - - `Int`, `Nat` (trap on overflow) + - `Int`, `Nat` (arbitrary precision) - `Word8`, `Word16`, `Word32`, `Word64` (wrap around) - `Int8`, `Int16`, `Int32`, `Int64`, `Nat8`, `Nat16`, `Nat32`, `Nat64` (trap on over/underflow) - `Float` From 5288dab385424d30b62d2e4a65c44c89a45c0e01 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Wed, 14 Aug 2019 18:07:10 +0200 Subject: [PATCH 0349/1176] Improve pretty printing (#618) --- src/as_frontend/coverage.ml | 4 +- src/as_values/prim.ml | 35 ++-- src/as_values/show.ml | 32 ++-- src/as_values/value.ml | 98 ++++++----- src/codegen/compile.ml | 16 +- src/ir_passes/show.ml | 3 + src/prelude/prelude.ml | 109 ++++++++----- .../examples/produce-exchange/profileActor.as | 2 +- .../ok/char-high-surrogate-trap.run-ir.ok | 2 +- .../ok/char-high-surrogate-trap.run-low.ok | 2 +- test/fail/ok/char-high-surrogate-trap.run.ok | 2 +- .../fail/ok/char-low-surrogate-trap.run-ir.ok | 2 +- .../ok/char-low-surrogate-trap.run-low.ok | 2 +- test/fail/ok/char-low-surrogate-trap.run.ok | 2 +- test/fail/ok/char-trap.run-ir.ok | 2 +- test/fail/ok/char-trap.run-low.ok | 2 +- test/fail/ok/char-trap.run.ok | 2 +- test/random/Main.hs | 8 +- test/random/qc-actorscript.cabal | 1 - test/repl/ok/outrange-int-nat.stdout.ok | 8 +- test/repl/ok/type-lub-repl.stdout.ok | 4 +- test/repl/ok/variant-shorthand.stdout.ok | 2 +- test/repl/variant-shorthand.sh | 2 +- test/run-dfinity/async-loop-while.as | 8 +- test/run-dfinity/async-loop.as | 8 +- test/run-dfinity/async-obj-mut.as | 12 +- test/run-dfinity/async-while.as | 8 +- test/run-dfinity/chatpp.as | 2 +- test/run-dfinity/closure-params.as | 12 +- test/run-dfinity/counter.as | 4 +- test/run-dfinity/counter2.as | 4 +- test/run-dfinity/fac.as | 2 +- test/run-dfinity/indirect-counter.as | 4 +- test/run-dfinity/ok/data-params.dvm-run.ok | 72 ++++---- test/run-dfinity/ok/data-params.run-ir.ok | 72 ++++---- test/run-dfinity/ok/data-params.run-low.ok | 72 ++++---- test/run-dfinity/ok/data-params.run.ok | 72 ++++---- test/run-dfinity/ok/show.dvm-run.ok | 37 +++-- test/run-dfinity/ok/show.run-ir.ok | 37 +++-- test/run-dfinity/ok/show.run-low.ok | 37 +++-- test/run-dfinity/ok/show.run.ok | 37 +++-- test/run-dfinity/ok/text-iter.dvm-run.ok | 2 - test/run-dfinity/ok/text-iter.run-ir.ok | 2 - test/run-dfinity/ok/text-iter.run-low.ok | 2 - test/run-dfinity/ok/text-iter.run.ok | 2 - test/run-dfinity/show.as | 13 +- test/run-dfinity/text-iter.as | 23 ++- test/run-dfinity/the-answer.as | 2 +- test/run/await.as | 8 +- test/run/block.as | 8 +- test/run/conversions.as | 2 +- test/run/for.as | 4 +- test/run/idlHash.as | 1 - test/run/ok/conversions.run-ir.ok | 10 +- test/run/ok/conversions.run-low.ok | 10 +- test/run/ok/conversions.run.ok | 10 +- test/run/ok/idlHash.run-ir.ok | 16 +- test/run/ok/idlHash.run-low.ok | 16 +- test/run/ok/idlHash.run.ok | 16 +- test/run/ok/words.run-ir.ok | 154 +++++++++--------- test/run/ok/words.run-low.ok | 154 +++++++++--------- test/run/ok/words.run.ok | 154 +++++++++--------- test/run/variants.as | 6 +- test/run/words.as | 8 +- 64 files changed, 778 insertions(+), 687 deletions(-) diff --git a/src/as_frontend/coverage.ml b/src/as_frontend/coverage.ml index f7d90734a2d..5806d57a28d 100644 --- a/src/as_frontend/coverage.ml +++ b/src/as_frontend/coverage.ml @@ -147,8 +147,8 @@ let rec string_of_desc t = function "?(" ^ string_of_desc t' desc ^ ")" | Tag (desc, l) -> let t' = T.lookup_val_field l (T.as_variant_sub l t) in - if T.sub t' T.unit - then "#" ^ l + if T.sub t' T.unit then "#" ^ l + else if T.is_tup t' then "#" ^ l ^ string_of_desc t' desc else "#" ^ l ^ "(" ^ string_of_desc t' desc ^ ")" | NotTag ls -> let tfs = T.as_variant (T.promote t) in diff --git a/src/as_values/prim.ml b/src/as_values/prim.ml index 8728b037579..2915f90e9df 100644 --- a/src/as_values/prim.ml +++ b/src/as_values/prim.ml @@ -4,29 +4,28 @@ open As_types open Value module Conv = struct - open Nativeint open Big_int - let of_signed_Word32 w = to_int (logand 0xFFFFFFFFn (of_int32 w)) + let int_of_word32_u w = Int32.to_int w land 0xffff_ffff let twoRaised62 = power_int_positive_int 2 62 let twoRaised63 = power_int_positive_int 2 63 - let word_twoRaised63 = Word64.(pow 2L 63L) let twoRaised64 = power_int_positive_int 2 64 + let word_twoRaised63 = Word64.(pow 2L 63L) - let word64_of_nat_big_int i = + let word64_of_big_int_u i = assert (sign_big_int i > -1); let wrapped = mod_big_int i twoRaised64 in match int64_of_big_int_opt wrapped with | Some n -> n | _ -> Word64.add (int64_of_big_int (sub_big_int wrapped twoRaised63)) word_twoRaised63 - let word64_of_big_int i = + let word64_of_big_int_s i = let wrapped = mod_big_int i twoRaised64 in match int64_of_big_int_opt wrapped with | Some n -> n | _ -> Word64.sub (int64_of_big_int (sub_big_int wrapped twoRaised63)) word_twoRaised63 - let big_int_of_unsigned_word64 w = + let big_int_of_word64_u w = let i = big_int_of_int64 w in if sign_big_int i > -1 then i else add_big_int i twoRaised64 @@ -117,7 +116,7 @@ let num_conv_prim t1 t2 = let q, r = Big_int.quomod_big_int (Nat64.to_big_int (as_nat64 v)) Conv.twoRaised63 in let i = Conv.(to_signed_big_int r q twoRaised63) in k (Word64 (Big_int.int64_of_big_int i)) - | T.Nat, T.Word64 -> fun v k -> k (Word64 (Conv.word64_of_nat_big_int (as_int v))) + | T.Nat, T.Word64 -> fun v k -> k (Word64 (Conv.word64_of_big_int_u (as_int v))) | T.Nat, T.Nat64 -> fun v k -> let q, r = Big_int.quomod_big_int (as_int v) Conv.twoRaised64 in Big_int. @@ -125,7 +124,7 @@ let num_conv_prim t1 t2 = then k (Nat64 (Nat64.of_big_int r)) else range_violation ()) | T.Int64, T.Word64 -> fun v k -> k (Word64 (Big_int.int64_of_big_int (Int_64.to_big_int (as_int64 v)))) - | T.Int, T.Word64 -> fun v k -> k (Word64 (Conv.word64_of_big_int (as_int v))) + | T.Int, T.Word64 -> fun v k -> k (Word64 (Conv.word64_of_big_int_s (as_int v))) | T.Int, T.Int64 -> fun v k -> let q, r = Big_int.quomod_big_int (as_int v) Conv.twoRaised63 in Big_int. @@ -164,7 +163,7 @@ let num_conv_prim t1 t2 = | T.Int32, T.Int -> fun v k -> k (Int (Int.of_int (Int_32.to_int (as_int32 v)))) | T.Nat32, T.Nat -> fun v k -> k (Int (Nat.of_int (Nat32.to_int (as_nat32 v)))) | T.Word32, T.Nat -> fun v k -> - let i = Conv.of_signed_Word32 (as_word32 v) + let i = Conv.int_of_word32_u (as_word32 v) in k (Int (Big_int.big_int_of_int i)) | T.Word32, T.Int -> fun v k -> k (Int (Big_int.big_int_of_int32 (as_word32 v))) | T.Word32, T.Int32 -> fun v k -> @@ -178,10 +177,10 @@ let num_conv_prim t1 t2 = | T.Int64, T.Int -> fun v k -> k (Int (Int_64.to_big_int (as_int64 v))) | T.Nat64, T.Nat -> fun v k -> k (Int (Nat64.to_big_int (as_nat64 v))) | T.Word64, T.Nat -> fun v k -> - let i = Conv.big_int_of_unsigned_word64 (as_word64 v) + let i = Conv.big_int_of_word64_u (as_word64 v) in k (Int i) | T.Word64, T.Nat64 -> fun v k -> - let i = Conv.big_int_of_unsigned_word64 (as_word64 v) + let i = Conv.big_int_of_word64_u (as_word64 v) in k (Nat64 (Nat64.of_big_int i)) | T.Word64, T.Int -> fun v k -> k (Int (Big_int.big_int_of_int64 (as_word64 v))) | T.Word64, T.Int64 -> fun v k -> @@ -192,15 +191,15 @@ let num_conv_prim t1 t2 = let i = as_char v in k (Word32 (Word32.of_int_u i)) | T.Word32, T.Char -> fun v k -> - let i = Conv.of_signed_Word32 (as_word32 v) - in if i <= 0xD7FF || i >= 0xE000 && i <= 0x10FFFF then k (Char i) else raise (Invalid_argument "codepoint out of bounds") + let i = Conv.int_of_word32_u (as_word32 v) + in if i < 0xD800 || i >= 0xE000 && i < 0x110000 then k (Char i) else raise (Invalid_argument "character value out of bounds") | t1, t2 -> raise (Invalid_argument ("Value.num_conv_prim: " ^ T.string_of_typ (T.Prim t1) ^ T.string_of_typ (T.Prim t2) )) let prim = function | "abs" -> fun v k -> k (Int (Nat.abs (as_int v))) - | "popcnt8" | "popcnt16" | "popcnt" | "popcnt64" -> + | "popcnt8" | "popcnt16" | "popcnt32" | "popcnt64" -> fun v k -> k (match v with | Word8 w -> Word8 (Word8. popcnt w) @@ -209,7 +208,7 @@ let prim = function | Word64 w -> Word64 (Word64.popcnt w) | _ -> failwith "popcnt") - | "clz8" | "clz16" | "clz" | "clz64" -> + | "clz8" | "clz16" | "clz32" | "clz64" -> fun v k -> k (match v with | Word8 w -> Word8 (Word8. clz w) @@ -218,7 +217,7 @@ let prim = function | Word64 w -> Word64 (Word64.clz w) | _ -> failwith "clz") - | "ctz8" | "ctz16" | "ctz" | "ctz64" -> + | "ctz8" | "ctz16" | "ctz32" | "ctz64" -> fun v k -> k (match v with | Word8 w -> Word8 (Word8. ctz w) @@ -227,7 +226,7 @@ let prim = function | Word64 w -> Word64 (Word64.ctz w) | _ -> failwith "ctz") - | "btst8" | "btst16" | "btst" | "btst64" -> + | "btst8" | "btst16" | "btst32" | "btst64" -> fun v k -> let w, a = as_pair v in k (match w with @@ -237,7 +236,7 @@ let prim = function | Word64 y -> Word64 Word64.(and_ y (shl 1L (as_word64 a))) | _ -> failwith "btst") - | "Char->Text" -> fun v k -> let str = match as_char v with + | "conv_Char_Text" -> fun v k -> let str = match as_char v with | c when c <= 0o177 -> String.make 1 (Char.chr c) | code -> Wasm.Utf8.encode [code] in k (Text str) diff --git a/src/as_values/show.ml b/src/as_values/show.ml index 095437daf0d..353b2b18ab7 100644 --- a/src/as_values/show.ml +++ b/src/as_values/show.ml @@ -17,36 +17,43 @@ let rec can_show t = List.for_all (fun f -> can_show (as_immut f.typ)) fs | Variant cts -> List.for_all (fun f -> can_show f.typ) cts + | Non -> true | _ -> false (* Entry point for the interpreter (reference implementation) *) +let needs_parens s = s.[0] = '+' || s.[0] = '-' || s.[0] = '?' || s.[0] = '#' +let parens s = if needs_parens s then "(" ^ s ^ ")" else s +let sign b s = (if b then "+" else "") ^ s + let rec show_val t v = let t = T.normalize t in match t, v with | T.Prim T.Bool, Value.Bool b -> if b then "true" else "false" - | T.(Prim (Nat|Int)), Value.Int i -> Value.Int.to_string i + | T.(Prim Nat), Value.Int i -> Value.Int.to_string i | T.(Prim Nat8), Value.Nat8 i -> Value.Nat8.to_string i | T.(Prim Nat16), Value.Nat16 i -> Value.Nat16.to_string i | T.(Prim Nat32), Value.Nat32 i -> Value.Nat32.to_string i | T.(Prim Nat64), Value.Nat64 i -> Value.Nat64.to_string i - | T.(Prim Int8), Value.Int8 i -> Value.Int_8.to_string i - | T.(Prim Int16), Value.Int16 i -> Value.Int_16.to_string i - | T.(Prim Int32), Value.Int32 i -> Value.Int_32.to_string i - | T.(Prim Int64), Value.Int64 i -> Value.Int_64.to_string i - | T.(Prim Word8), Value.Word8 i -> Value.Word8.to_string i - | T.(Prim Word16), Value.Word16 i -> Value.Word16.to_string i - | T.(Prim Word32), Value.Word32 i -> Value.Word32.to_string i - | T.(Prim Word64), Value.Word64 i -> Value.Word64.to_string i + | T.(Prim Int), Value.Int i -> Value.Int.(sign (gt i zero) (to_string i)) + | T.(Prim Int8), Value.Int8 i -> Value.Int_8.(sign (gt i zero) (to_string i)) + | T.(Prim Int16), Value.Int16 i -> Value.Int_16.(sign (gt i zero) (to_string i)) + | T.(Prim Int32), Value.Int32 i -> Value.Int_32.(sign (gt i zero) (to_string i)) + | T.(Prim Int64), Value.Int64 i -> Value.Int_64.(sign (gt i zero) (to_string i)) + | T.(Prim Word8), Value.Word8 i -> "0x" ^ Value.Word8.to_string i + | T.(Prim Word16), Value.Word16 i -> "0x" ^ Value.Word16.to_string i + | T.(Prim Word32), Value.Word32 i -> "0x" ^ Value.Word32.to_string i + | T.(Prim Word64), Value.Word64 i -> "0x" ^ Value.Word64.to_string i | T.Prim T.Text, Value.Text s -> "\"" ^ s ^ "\"" | T.Prim T.Null, Value.Null -> "null" | T.Opt _, Value.Null -> "null" - | T.Opt t', Value.Opt v -> "?(" ^ show_val t' v ^ ")" + | T.Opt t', Value.Opt v -> "?" ^ parens (show_val t' v) | T.Tup ts', Value.Tup vs -> Printf.sprintf "(%s%s)" (String.concat ", " (List.map2 show_val ts' vs)) (if List.length vs = 1 then "," else "") | T.Array (T.Mut t'), Value.Array a -> + if a = [||] then "[var]" else Printf.sprintf "[var %s]" (String.concat ", " (List.map (fun v -> show_val t' !(Value.as_mut v)) (Array.to_list a))) | T.Array t', Value.Array a -> @@ -56,8 +63,9 @@ let rec show_val t v = Printf.sprintf "{%s}" (String.concat "; " (List.map (show_field fs) fts)) | T.Variant fs, Value.Variant (l, v) -> begin match List.find_opt (fun {T.lab = l'; _} -> l = l') fs with - | Some {T.typ = T.Tup []; _} -> Printf.sprintf "(#%s)" l - | Some {T.typ = t'; _} -> Printf.sprintf "(#%s %s)" l (show_val t' v) + | Some {T.typ = T.Tup []; _} -> Printf.sprintf "#%s" l + | Some {T.typ = T.Tup _ as t'; _} -> Printf.sprintf "#%s%s" l (show_val t' v) + | Some {T.typ = t'; _} -> Printf.sprintf "#%s(%s)" l (show_val t' v) | _ -> assert false end | _ -> diff --git a/src/as_values/value.ml b/src/as_values/value.ml index 66b1690026b..1b9a884f00a 100644 --- a/src/as_values/value.ml +++ b/src/as_values/value.ml @@ -34,7 +34,7 @@ let group_num s = Buffer.contents buf (* Represent n-bit integers using k-bit (n<=k) integers by shifting left/right by k-n bits *) -module SubRep(Rep : Wasm.Int.RepType)(Width : sig val bitwidth : int end) : +module SubRep (Rep : Wasm.Int.RepType) (Width : sig val bitwidth : int end) : Wasm.Int.RepType with type t = Rep.t = struct let _ = assert (Width.bitwidth < Rep.bitwidth) @@ -79,7 +79,8 @@ sig val to_pretty_string : t -> string end -module MakeWord(WasmInt : Wasm.Int.S) = +module MakeWord + (WasmInt : Wasm.Int.S) (ToInt : sig val to_int : WasmInt.t -> int end) = struct include WasmInt let neg w = sub zero w @@ -92,18 +93,28 @@ struct pow (mul x x) (shr_u y one) else mul x (pow x (sub y one)) - let to_string w = WasmInt.to_string_u w - let to_pretty_string w = group_num (WasmInt.to_string_u w) + + let base = of_int_u 16 + let digs = + [|"0"; "1"; "2"; "3"; "4"; "5"; "6"; "7"; + "8"; "9"; "A"; "B"; "C"; "D"; "E"; "F"|] + let rec to_pretty_string w = if w = zero then "0" else to_pretty_string' w 0 "" + and to_pretty_string' w i s = + if w = zero then s else + let dig = digs.(ToInt.to_int (WasmInt.rem_u w base)) in + let s' = dig ^ (if i = 4 then "_" else "") ^ s in + to_pretty_string' (WasmInt.div_u w base) (i mod 4 + 1) s' + let to_string = to_pretty_string end module Int32Rep = struct include Int32 let bitwidth = 32 end -module Int16Rep = SubRep(Int32Rep)(struct let bitwidth = 16 end) -module Int8Rep = SubRep(Int32Rep)(struct let bitwidth = 8 end) +module Int16Rep = SubRep (Int32Rep) (struct let bitwidth = 16 end) +module Int8Rep = SubRep (Int32Rep) (struct let bitwidth = 8 end) -module Word8 = MakeWord(Wasm.Int.Make(Int8Rep)) -module Word16 = MakeWord(Wasm.Int.Make(Int16Rep)) -module Word32 = MakeWord(Wasm.I32) -module Word64 = MakeWord(Wasm.I64) +module Word8 = MakeWord (Wasm.Int.Make (Int8Rep)) (Int8Rep) +module Word16 = MakeWord (Wasm.Int.Make (Int16Rep)) (Int16Rep) +module Word32 = MakeWord (Wasm.I32) (Int32) +module Word64 = MakeWord (Wasm.I64) (Int64) module type FloatType = sig @@ -117,6 +128,7 @@ struct include WasmFloat let pow x y = of_float (to_float x ** to_float y) let to_pretty_string w = group_num (WasmFloat.to_string w) + let to_string = to_pretty_string end module Float = MakeFloat(Wasm.F64) @@ -182,8 +194,8 @@ struct let of_int = big_int_of_int let of_big_int i = i let to_big_int i = i - let to_string i = string_of_big_int i let to_pretty_string i = group_num (string_of_big_int i) + let to_string = to_pretty_string let of_string s = big_int_of_string (String.concat "" (String.split_on_char '_' s)) @@ -203,7 +215,7 @@ struct if ge z zero then z else raise (Invalid_argument "Nat.sub") end -module RangeLimited(Rep : NumType)(Range : sig val is_range : Rep.t -> bool end) : NumType = +module Ranged (Rep : NumType) (Range : sig val is_range : Rep.t -> bool end) : NumType = struct let check i = if Range.is_range i then i @@ -222,27 +234,27 @@ struct let of_string s = let res = Rep.of_string s in check res end -module NatRange(Limit : sig val upper : Big_int.big_int end) = +module NatRange (Limit : sig val upper : Big_int.big_int end) = struct open Big_int let is_range n = ge_big_int n zero_big_int && lt_big_int n Limit.upper end -module Nat8 = RangeLimited(Nat)(NatRange(struct let upper = Big_int.big_int_of_int 0x100 end)) -module Nat16 = RangeLimited(Nat)(NatRange(struct let upper = Big_int.big_int_of_int 0x10000 end)) -module Nat32 = RangeLimited(Nat)(NatRange(struct let upper = Big_int.big_int_of_int 0x100000000 end)) -module Nat64 = RangeLimited(Nat)(NatRange(struct let upper = Big_int.power_int_positive_int 2 64 end)) +module Nat8 = Ranged (Nat) (NatRange (struct let upper = Big_int.big_int_of_int 0x100 end)) +module Nat16 = Ranged (Nat) (NatRange (struct let upper = Big_int.big_int_of_int 0x1_0000 end)) +module Nat32 = Ranged (Nat) (NatRange (struct let upper = Big_int.big_int_of_int 0x1_0000_0000 end)) +module Nat64 = Ranged (Nat) (NatRange (struct let upper = Big_int.power_int_positive_int 2 64 end)) -module IntRange(Limit : sig val upper : Big_int.big_int end) = +module IntRange (Limit : sig val upper : Big_int.big_int end) = struct open Big_int let is_range n = ge_big_int n (minus_big_int Limit.upper) && lt_big_int n Limit.upper end -module Int_8 = RangeLimited(Int)(IntRange(struct let upper = Big_int.big_int_of_int 0x80 end)) -module Int_16 = RangeLimited(Int)(IntRange(struct let upper = Big_int.big_int_of_int 0x8000 end)) -module Int_32 = RangeLimited(Int)(IntRange(struct let upper = Big_int.big_int_of_int 0x80000000 end)) -module Int_64 = RangeLimited(Int)(IntRange(struct let upper = Big_int.power_int_positive_int 2 63 end)) +module Int_8 = Ranged (Int) (IntRange (struct let upper = Big_int.big_int_of_int 0x80 end)) +module Int_16 = Ranged (Int) (IntRange (struct let upper = Big_int.big_int_of_int 0x8000 end)) +module Int_32 = Ranged (Int) (IntRange (struct let upper = Big_int.big_int_of_int 0x8000_0000 end)) +module Int_64 = Ranged (Int) (IntRange (struct let upper = Big_int.power_int_positive_int 2 63 end)) (* Types *) @@ -378,22 +390,24 @@ let string_of_string lsep s rsep = Buffer.add_char buf rsep; Buffer.contents buf +let pos_sign b = if b then "+" else "" + let rec string_of_val_nullary d = function | Null -> "null" | Bool b -> if b then "true" else "false" - | Int i -> Int.to_pretty_string i - | Int8 w -> Int_8.to_pretty_string w - | Int16 w -> Int_16.to_pretty_string w - | Int32 w -> Int_32.to_pretty_string w - | Int64 w -> Int_64.to_pretty_string w - | Nat8 w -> Nat8.to_pretty_string w - | Nat16 w -> Nat16.to_pretty_string w - | Nat32 w -> Nat32.to_pretty_string w - | Nat64 w -> Nat64.to_pretty_string w - | Word8 w -> Word8.to_pretty_string w - | Word16 w -> Word16.to_pretty_string w - | Word32 w -> Word32.to_pretty_string w - | Word64 w -> Word64.to_pretty_string w + | Int n when Int.(ge n zero) -> Int.to_pretty_string n + | Int8 n when Int_8.(n = zero) -> Int_8.to_pretty_string n + | Int16 n when Int_16.(n = zero) -> Int_16.to_pretty_string n + | Int32 n when Int_32.(n = zero) -> Int_32.to_pretty_string n + | Int64 n when Int_64.(n = zero) -> Int_64.to_pretty_string n + | Nat8 n -> Nat8.to_pretty_string n + | Nat16 n -> Nat16.to_pretty_string n + | Nat32 n -> Nat32.to_pretty_string n + | Nat64 n -> Nat64.to_pretty_string n + | Word8 w -> "0x" ^ Word8.to_pretty_string w + | Word16 w -> "0x" ^ Word16.to_pretty_string w + | Word32 w -> "0x" ^ Word32.to_pretty_string w + | Word64 w -> "0x" ^ Word64.to_pretty_string w | Float f -> Float.to_pretty_string f | Char c -> string_of_string '\'' [c] '\'' | Text t -> string_of_string '\"' (Wasm.Utf8.decode t) '\"' @@ -401,8 +415,6 @@ let rec string_of_val_nullary d = function sprintf "(%s%s)" (String.concat ", " (List.map (string_of_val d) vs)) (if List.length vs = 1 then "," else "") - | Opt v -> - sprintf "?%s" (string_of_val_nullary d v) | Obj ve -> if d = 0 then "{...}" else sprintf "{%s}" (String.concat "; " (List.map (fun (x, v) -> @@ -414,14 +426,20 @@ let rec string_of_val_nullary d = function | v -> "(" ^ string_of_val d v ^ ")" and string_of_val d = function + | Int i -> Int.to_pretty_string i + | Int8 i -> Int_8.(pos_sign (gt i zero) ^ to_pretty_string i) + | Int16 i -> Int_16.(pos_sign (gt i zero) ^ to_pretty_string i) + | Int32 i -> Int_32.(pos_sign (gt i zero) ^ to_pretty_string i) + | Int64 i -> Int_64.(pos_sign (gt i zero) ^ to_pretty_string i) + | Opt v -> sprintf "?%s" (string_of_val_nullary d v) + | Variant (l, Tup []) -> sprintf "#%s" l + | Variant (l, Tup vs) -> sprintf "#%s%s" l (string_of_val d (Tup vs)) + | Variant (l, v) -> sprintf "#%s(%s)" l (string_of_val d v) | Async {result; waiters = []} -> sprintf "async %s" (string_of_def_nullary d result) | Async {result; waiters} -> sprintf "async[%d] %s" (List.length waiters) (string_of_def_nullary d result) - | Variant (l, Tup []) -> sprintf "#%s" l - | Variant (l, v) when v <> unit -> - sprintf "#%s %s" l (string_of_val_nullary d v) | Mut r -> sprintf "%s" (string_of_val d !r) | v -> string_of_val_nullary d v diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index d2583393ae8..9e19fc706fc 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -5909,10 +5909,6 @@ and compile_exp (env : E.t) ae exp = E.trap_with env "idlHash only implemented in interpreter " - | OtherPrim "popcnt", [e] -> - SR.UnboxedWord32, - compile_exp_as env ae SR.UnboxedWord32 e ^^ - G.i (Unary (Wasm.Values.I32 I32Op.Popcnt)) | OtherPrim "popcnt8", [e] -> SR.Vanilla, compile_exp_vanilla env ae e ^^ @@ -5923,20 +5919,24 @@ and compile_exp (env : E.t) ae exp = compile_exp_vanilla env ae e ^^ G.i (Unary (Wasm.Values.I32 I32Op.Popcnt)) ^^ UnboxedSmallWord.msb_adjust Type.Word16 + | OtherPrim "popcnt32", [e] -> + SR.UnboxedWord32, + compile_exp_as env ae SR.UnboxedWord32 e ^^ + G.i (Unary (Wasm.Values.I32 I32Op.Popcnt)) | OtherPrim "popcnt64", [e] -> SR.UnboxedWord64, compile_exp_as env ae SR.UnboxedWord64 e ^^ G.i (Unary (Wasm.Values.I64 I64Op.Popcnt)) - | OtherPrim "clz", [e] -> SR.UnboxedWord32, compile_exp_as env ae SR.UnboxedWord32 e ^^ G.i (Unary (Wasm.Values.I32 I32Op.Clz)) | OtherPrim "clz8", [e] -> SR.Vanilla, compile_exp_vanilla env ae e ^^ UnboxedSmallWord.clz_kernel Type.Word8 | OtherPrim "clz16", [e] -> SR.Vanilla, compile_exp_vanilla env ae e ^^ UnboxedSmallWord.clz_kernel Type.Word16 + | OtherPrim "clz32", [e] -> SR.UnboxedWord32, compile_exp_as env ae SR.UnboxedWord32 e ^^ G.i (Unary (Wasm.Values.I32 I32Op.Clz)) | OtherPrim "clz64", [e] -> SR.UnboxedWord64, compile_exp_as env ae SR.UnboxedWord64 e ^^ G.i (Unary (Wasm.Values.I64 I64Op.Clz)) - | OtherPrim "ctz", [e] -> SR.UnboxedWord32, compile_exp_as env ae SR.UnboxedWord32 e ^^ G.i (Unary (Wasm.Values.I32 I32Op.Ctz)) | OtherPrim "ctz8", [e] -> SR.Vanilla, compile_exp_vanilla env ae e ^^ UnboxedSmallWord.ctz_kernel Type.Word8 | OtherPrim "ctz16", [e] -> SR.Vanilla, compile_exp_vanilla env ae e ^^ UnboxedSmallWord.ctz_kernel Type.Word16 + | OtherPrim "ctz32", [e] -> SR.UnboxedWord32, compile_exp_as env ae SR.UnboxedWord32 e ^^ G.i (Unary (Wasm.Values.I32 I32Op.Ctz)) | OtherPrim "ctz64", [e] -> SR.UnboxedWord64, compile_exp_as env ae SR.UnboxedWord64 e ^^ G.i (Unary (Wasm.Values.I64 I64Op.Ctz)) - | OtherPrim "Char->Text", [e] -> + | OtherPrim "conv_Char_Text", [e] -> SR.Vanilla, compile_exp_vanilla env ae e ^^ Text.prim_showChar env @@ -5959,7 +5959,7 @@ and compile_exp (env : E.t) ae exp = const_sr SR.Vanilla (UnboxedSmallWord.btst_kernel env Type.Word8) | OtherPrim "btst16", [_;_] -> const_sr SR.Vanilla (UnboxedSmallWord.btst_kernel env Type.Word16) - | OtherPrim "btst", [_;_] -> + | OtherPrim "btst32", [_;_] -> const_sr SR.UnboxedWord32 (UnboxedSmallWord.btst_kernel env Type.Word32) | OtherPrim "btst64", [_;_] -> const_sr SR.UnboxedWord64 ( diff --git a/src/ir_passes/show.ml b/src/ir_passes/show.ml index 3376239cf33..9cce4ba5fa7 100644 --- a/src/ir_passes/show.ml +++ b/src/ir_passes/show.ml @@ -385,6 +385,9 @@ let show_for : T.typ -> Ir.dec * T.typ list = fun t -> (T.Prim T.Text) ), List.map (fun (f : T.field) -> T.normalize f.T.typ) fs + | T.Non -> + define_show t unreachableE, + [] | _ -> assert false (* Should be prevented by can_show *) (* Synthesizing the types recursively. Hopefully well-founded. *) diff --git a/src/prelude/prelude.ml b/src/prelude/prelude.ml index b52a78f9cba..e942f142017 100644 --- a/src/prelude/prelude.ml +++ b/src/prelude/prelude.ml @@ -84,8 +84,7 @@ func @text_chars(xs : Text) : (() -> Iter) = // for testing func idlHash(x : Text) : Word32 { (prim "idlHash" : Text -> Word32) x }; -func charToText(c : Char) : Text = (prim "Char->Text" : Char -> Text) c; - +func printNat(x : Nat) { print (@text_of_Nat x) }; func printInt(x : Int) { print (@text_of_Int x) }; func printChar(x : Char) { print (charToText x) }; func print(x : Text) { (prim "print" : Text -> ()) x }; @@ -168,7 +167,7 @@ func word64ToInt(n : Word64) : Int = (prim "num_conv_Word64_Int" : Word64 -> Int func charToWord32(c : Char) : Word32 = (prim "num_conv_Char_Word32" : Char -> Word32) c; func word32ToChar(w : Word32) : Char = (prim "num_conv_Word32_Char" : Word32 -> Char) w; -func decodeUTF8(s : Text) : (Word32, Char) = (prim "decodeUTF8" : Text -> (Word32, Char)) s; +func charToText(c : Char) : Text = (prim "conv_Char_Text" : Char -> Text) c; // Exotic bitwise operations func popcntWord8(w : Word8) : Word8 = (prim "popcnt8" : Word8 -> Word8) w; @@ -181,10 +180,10 @@ func clzWord16(w : Word16) : Word16 = (prim "clz16" : Word16 -> Word16) w; func ctzWord16(w : Word16) : Word16 = (prim "ctz16" : Word16 -> Word16) w; func btstWord16(w : Word16, amount : Word16) : Bool = (prim "btst16" : (Word16, Word16) -> Word16) (w, amount) != (0 : Word16); -func popcntWord32(w : Word32) : Word32 = (prim "popcnt" : Word32 -> Word32) w; -func clzWord32(w : Word32) : Word32 = (prim "clz" : Word32 -> Word32) w; -func ctzWord32(w : Word32) : Word32 = (prim "ctz" : Word32 -> Word32) w; -func btstWord32(w : Word32, amount : Word32) : Bool = (prim "btst" : (Word32, Word32) -> Word32) (w, amount) != (0 : Word32); +func popcntWord32(w : Word32) : Word32 = (prim "popcnt32" : Word32 -> Word32) w; +func clzWord32(w : Word32) : Word32 = (prim "clz32" : Word32 -> Word32) w; +func ctzWord32(w : Word32) : Word32 = (prim "ctz32" : Word32 -> Word32) w; +func btstWord32(w : Word32, amount : Word32) : Bool = (prim "btst32" : (Word32, Word32) -> Word32) (w, amount) != (0 : Word32); func popcntWord64(w : Word64) : Word64 = (prim "popcnt64" : Word64 -> Word64) w; func clzWord64(w : Word64) : Word64 = (prim "clz64" : Word64 -> Word64) w; @@ -199,35 +198,37 @@ func btstWord64(w : Word64, amount : Word64) : Bool = (prim "btst64" : (Word64, // The text_of functions do not need to be exposed; the user can just use // the show above. -func @text_of_Nat(x : Nat) : Text { +func @text_of_num(x : Nat, base : Nat, sep : Nat, digits : [Text]) : Text { var text = ""; var n = x; - let base = 10; - let digits = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]; - assert(n >= 0); - - if (n == 0) { - return "0"; - }; + if (n == 0) return "0"; + var i = 0; while (n > 0) { let rem = n % base; + if (i == sep) { text := "_" # text; i := 0 }; text := digits[rem] # text; n := n / base; + i += 1; }; return text; }; +let @decdigits = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]; +func @text_of_Nat(x : Nat) : Text { + @text_of_num(x, 10, 3, @decdigits); +}; + func @text_of_Int(x : Int) : Text { - if (x == 0) { - return "0"; - }; - if (x < 0) { - "-" # @text_of_Nat(abs x) - } else { - @text_of_Nat(abs x) - } + if (x == 0) "0" else (if (x < 0) "-" else "+") # @text_of_Nat(abs x) +}; + +let @hexdigits = + [ "0", "1", "2", "3", "4", "5", "6", "7", + "8", "9", "A", "B", "C", "D", "E", "F" ]; +func @text_of_Word(x : Nat) : Text { + return "0x" # @text_of_num(x, 16, 4, @hexdigits); }; func @text_of_Nat8(x : Nat8) : Text = @text_of_Nat (nat8ToNat x); @@ -238,10 +239,10 @@ func @text_of_Int8(x : Int8) : Text = @text_of_Int (int8ToInt x); func @text_of_Int16(x : Int16) : Text = @text_of_Int (int16ToInt x); func @text_of_Int32(x : Int32) : Text = @text_of_Int (int32ToInt x); func @text_of_Int64(x : Int64) : Text = @text_of_Int (int64ToInt x); -func @text_of_Word8(x : Word8) : Text = @text_of_Nat (word8ToNat x); -func @text_of_Word16(x : Word16) : Text = @text_of_Nat (word16ToNat x); -func @text_of_Word32(x : Word32) : Text = @text_of_Nat (word32ToNat x); -func @text_of_Word64(x : Word64) : Text = @text_of_Nat (word64ToNat x); +func @text_of_Word8(x : Word8) : Text = @text_of_Word (word8ToNat x); +func @text_of_Word16(x : Word16) : Text = @text_of_Word (word16ToNat x); +func @text_of_Word32(x : Word32) : Text = @text_of_Word (word32ToNat x); +func @text_of_Word64(x : Word64) : Text = @text_of_Word (word64ToNat x); func @text_of_Bool(b : Bool) : Text { @@ -253,51 +254,73 @@ func @text_of_Text(t : Text) : Text { "\"" # t # "\""; }; +func @text_has_parens(t : Text) : Bool { + switch (t.chars().next()) { + case (?'(') true; + case _ false; + } +}; + +func @text_needs_parens(t : Text) : Bool { + switch (t.chars().next()) { + case (?('+' or '-' or '?' or '#')) true; + case _ false; + } +}; + func @text_of_option(f : T -> Text, x : ?T) : Text { switch (x) { - case (?y) {"?(" # f y # ")"}; + case (?y) { + let fy = f y; + if (@text_needs_parens(fy)) "?(" # fy # ")" + else "?" # fy + }; case null {"null"}; } }; func @text_of_variant(l : Text, f : T -> Text, x : T) : Text { let fx = f x; - if (fx == "()") "(#" # l # ")" - else "(#" # l # " " # fx # ")" + if (fx == "()") "#" # l + else if (@text_has_parens(fx)) "#" # l # fx + else "#" # l # "(" # fx # ")" }; func @text_of_array(f : T -> Text, xs : [T]) : Text { - var text = ""; + var text = "["; + var first = true; for (x in xs.vals()) { - if (text == "") { - text := text # "["; + if first { + first := false; } else { - text := text # ", "; + text #= ", "; }; - text := text # f x; + text #= f x; }; - text := text # "]"; + text #= "]"; return text; }; func @text_of_array_mut(f : T -> Text, xs : [var T]) : Text { - var text = ""; + var text = "[var"; + var first = true; for (x in xs.vals()) { - if (text == "") { - text := text # "[var "; + if first { + first := false; + text #= " "; } else { - text := text # ", "; + text #= ", "; }; - text := text # f x; + text #= f x; }; - text := text # "]"; + text #= "]"; return text; }; // Array utilities -// This would be nicer as a objects, but lets do them as functions +// TODO: These would be nicer as a objects, but lets do them as functions // until the compiler has a concept of “static objects” func Array_init(len : Nat, x : T) : [var T] { (prim "Array.init" : (Nat, T) -> [var T])(len, x) diff --git a/stdlib/examples/produce-exchange/profileActor.as b/stdlib/examples/produce-exchange/profileActor.as index d791a33c561..2ade64777d1 100644 --- a/stdlib/examples/produce-exchange/profileActor.as +++ b/stdlib/examples/produce-exchange/profileActor.as @@ -8,7 +8,7 @@ actor server { // var dummy = { func scaledParams(region_count_:Nat, factor:Nat) : T.WorkloadParams = { - new { + { region_count = region_count_:Nat; day_count = 3:Nat; max_route_duration = 1:Nat; diff --git a/test/fail/ok/char-high-surrogate-trap.run-ir.ok b/test/fail/ok/char-high-surrogate-trap.run-ir.ok index 46eac08816e..fe3a4aa9bb4 100644 --- a/test/fail/ok/char-high-surrogate-trap.run-ir.ok +++ b/test/fail/ok/char-high-surrogate-trap.run-ir.ok @@ -1 +1 @@ -prelude:___: execution error, codepoint out of bounds +prelude:___: execution error, character value out of bounds diff --git a/test/fail/ok/char-high-surrogate-trap.run-low.ok b/test/fail/ok/char-high-surrogate-trap.run-low.ok index 46eac08816e..fe3a4aa9bb4 100644 --- a/test/fail/ok/char-high-surrogate-trap.run-low.ok +++ b/test/fail/ok/char-high-surrogate-trap.run-low.ok @@ -1 +1 @@ -prelude:___: execution error, codepoint out of bounds +prelude:___: execution error, character value out of bounds diff --git a/test/fail/ok/char-high-surrogate-trap.run.ok b/test/fail/ok/char-high-surrogate-trap.run.ok index 46eac08816e..fe3a4aa9bb4 100644 --- a/test/fail/ok/char-high-surrogate-trap.run.ok +++ b/test/fail/ok/char-high-surrogate-trap.run.ok @@ -1 +1 @@ -prelude:___: execution error, codepoint out of bounds +prelude:___: execution error, character value out of bounds diff --git a/test/fail/ok/char-low-surrogate-trap.run-ir.ok b/test/fail/ok/char-low-surrogate-trap.run-ir.ok index 46eac08816e..fe3a4aa9bb4 100644 --- a/test/fail/ok/char-low-surrogate-trap.run-ir.ok +++ b/test/fail/ok/char-low-surrogate-trap.run-ir.ok @@ -1 +1 @@ -prelude:___: execution error, codepoint out of bounds +prelude:___: execution error, character value out of bounds diff --git a/test/fail/ok/char-low-surrogate-trap.run-low.ok b/test/fail/ok/char-low-surrogate-trap.run-low.ok index 46eac08816e..fe3a4aa9bb4 100644 --- a/test/fail/ok/char-low-surrogate-trap.run-low.ok +++ b/test/fail/ok/char-low-surrogate-trap.run-low.ok @@ -1 +1 @@ -prelude:___: execution error, codepoint out of bounds +prelude:___: execution error, character value out of bounds diff --git a/test/fail/ok/char-low-surrogate-trap.run.ok b/test/fail/ok/char-low-surrogate-trap.run.ok index 46eac08816e..fe3a4aa9bb4 100644 --- a/test/fail/ok/char-low-surrogate-trap.run.ok +++ b/test/fail/ok/char-low-surrogate-trap.run.ok @@ -1 +1 @@ -prelude:___: execution error, codepoint out of bounds +prelude:___: execution error, character value out of bounds diff --git a/test/fail/ok/char-trap.run-ir.ok b/test/fail/ok/char-trap.run-ir.ok index 46eac08816e..fe3a4aa9bb4 100644 --- a/test/fail/ok/char-trap.run-ir.ok +++ b/test/fail/ok/char-trap.run-ir.ok @@ -1 +1 @@ -prelude:___: execution error, codepoint out of bounds +prelude:___: execution error, character value out of bounds diff --git a/test/fail/ok/char-trap.run-low.ok b/test/fail/ok/char-trap.run-low.ok index 46eac08816e..fe3a4aa9bb4 100644 --- a/test/fail/ok/char-trap.run-low.ok +++ b/test/fail/ok/char-trap.run-low.ok @@ -1 +1 @@ -prelude:___: execution error, codepoint out of bounds +prelude:___: execution error, character value out of bounds diff --git a/test/fail/ok/char-trap.run.ok b/test/fail/ok/char-trap.run.ok index 46eac08816e..fe3a4aa9bb4 100644 --- a/test/fail/ok/char-trap.run.ok +++ b/test/fail/ok/char-trap.run.ok @@ -1 +1 @@ -prelude:___: execution error, codepoint out of bounds +prelude:___: execution error, character value out of bounds diff --git a/test/random/Main.hs b/test/random/Main.hs index 5bab517efe0..606c82d15d0 100644 --- a/test/random/Main.hs +++ b/test/random/Main.hs @@ -21,7 +21,6 @@ import GHC.Natural import GHC.TypeLits import qualified Data.Word import Data.Bits (Bits(..), FiniteBits(..)) -import qualified Data.ByteString.UTF8 import Numeric import System.Process hiding (proc) @@ -40,7 +39,7 @@ arithProps = testGroup "Arithmetic/logic" utf8Props = testGroup "UTF-8 coding" [ QC.testProperty "explode >>> concat roundtrips" $ prop_explodeConcat - , QC.testProperty "charToText >>> decodeUTF8 roundtrips" $ prop_charToText + , QC.testProperty "charToText >>> head roundtrips" $ prop_charToText ] @@ -83,11 +82,10 @@ escape '"' = "\\\"" escape ch = pure ch prop_charToText (UTF8 char) = monadicIO $ do - let testCase = "assert (switch (decodeUTF8 (charToText '" - <> c <> "')) { case (" <> show octets <> ", '" <> c <> "') true; case _ false })" + let testCase = "assert (switch ((charToText '" + <> c <> "').chars().next()) { case (?'" <> c <> "') true; case _ false })" c = escape char - Just (_, octets) = Data.ByteString.UTF8.decode (Data.ByteString.UTF8.fromString $ pure char) runScriptNoFuzz "charToText" testCase assertSuccessNoFuzz relevant (compiled, (exitCode, out, err)) = do diff --git a/test/random/qc-actorscript.cabal b/test/random/qc-actorscript.cabal index 3c9ecd8fe97..3010591701d 100644 --- a/test/random/qc-actorscript.cabal +++ b/test/random/qc-actorscript.cabal @@ -23,6 +23,5 @@ executable qc-actorscript , tasty , tasty-quickcheck , turtle - , utf8-string -- hs-source-dirs: default-language: Haskell2010 diff --git a/test/repl/ok/outrange-int-nat.stdout.ok b/test/repl/ok/outrange-int-nat.stdout.ok index 141ae75ff42..528624a3a1b 100644 --- a/test/repl/ok/outrange-int-nat.stdout.ok +++ b/test/repl/ok/outrange-int-nat.stdout.ok @@ -1,17 +1,17 @@ ActorScript 0.1 interpreter -> 127 : Int8 +> +127 : Int8 > prelude:___: execution error, numeric overflow > -128 : Int8 > prelude:___: execution error, numeric overflow -> 32_767 : Int16 +> +32_767 : Int16 > prelude:___: execution error, numeric overflow > -32_768 : Int16 > prelude:___: execution error, numeric overflow -> 2_147_483_647 : Int32 +> +2_147_483_647 : Int32 > prelude:___: execution error, numeric overflow > -2_147_483_648 : Int32 > prelude:___: execution error, numeric overflow -> 9_223_372_036_854_775_807 : Int64 +> +9_223_372_036_854_775_807 : Int64 > prelude:___: execution error, numeric overflow > -9_223_372_036_854_775_808 : Int64 > prelude:___: execution error, numeric overflow diff --git a/test/repl/ok/type-lub-repl.stdout.ok b/test/repl/ok/type-lub-repl.stdout.ok index 414f1561517..c402e4a0866 100644 --- a/test/repl/ok/type-lub-repl.stdout.ok +++ b/test/repl/ok/type-lub-repl.stdout.ok @@ -1,5 +1,5 @@ ActorScript 0.1 interpreter -> [null, ?42, ?-25] : [(?Int)] +> [null, ?42, ?(-25)] : [(?Int)] > [null, null] : [Null] > [{a = 42}, {b = 42}] : [{}] > [{a = 42}, {a = 1; b = 42}, {a = -25}] : [{a : Int}] @@ -28,5 +28,5 @@ ActorScript 0.1 interpreter > 25 : Int > 42 : Int > func : (C, D) -> [C] -> [async ?4, async ?-42] : [(async (?Int))] +> [async (?4), async (?(-42))] : [(async (?Int))] > diff --git a/test/repl/ok/variant-shorthand.stdout.ok b/test/repl/ok/variant-shorthand.stdout.ok index 05fc885c24c..44c26b7a0d9 100644 --- a/test/repl/ok/variant-shorthand.stdout.ok +++ b/test/repl/ok/variant-shorthand.stdout.ok @@ -1,5 +1,5 @@ ActorScript 0.1 interpreter > #bar : {#bar} -> #foo (#bar) : {#foo : {#bar}} +> #foo(#bar) : {#foo : {#bar}} > [#Monday, #Tuesday, #Wednesday, #Thursday, #Friday, #Saturday, #Sunday] : [{#Friday; #Monday; #Saturday; #Sunday; #Thursday; #Tuesday; #Wednesday}] > diff --git a/test/repl/variant-shorthand.sh b/test/repl/variant-shorthand.sh index 48ed3853f18..a52669b3e4e 100755 --- a/test/repl/variant-shorthand.sh +++ b/test/repl/variant-shorthand.sh @@ -2,6 +2,6 @@ # Tests that shorthand variants come out without parens ${ASC:-$(dirname "$BASH_SOURCE")/../../src/asc} -i <<__END__ #bar; -#foo (#bar); +#foo(#bar); [#Monday, #Tuesday, #Wednesday, #Thursday, #Friday, #Saturday, #Sunday]; __END__ diff --git a/test/run-dfinity/async-loop-while.as b/test/run-dfinity/async-loop-while.as index af238a947e5..c4bae925319 100644 --- a/test/run-dfinity/async-loop-while.as +++ b/test/run-dfinity/async-loop-while.as @@ -4,7 +4,7 @@ async { { var i = 0; var j = 0; loop { - printInt(j); + printNat(j); assert(j == i); i += 1; j += 1; @@ -17,7 +17,7 @@ async { var i = 0; var j = 0; loop { - printInt(j); + printNat(j); assert(j == i); i += 1; j += 1; @@ -29,7 +29,7 @@ async { var i = 0; var j = 0; loop { - printInt(j); + printNat(j); assert(j == i); await (async (i += 1)); j += 1; @@ -46,7 +46,7 @@ async { break l; assert(false); }; - printInt(j); + printNat(j); assert(j == i); await (async (i += 1)); j += 1; diff --git a/test/run-dfinity/async-loop.as b/test/run-dfinity/async-loop.as index 3149c72d81a..0cc9252d180 100644 --- a/test/run-dfinity/async-loop.as +++ b/test/run-dfinity/async-loop.as @@ -5,7 +5,7 @@ async { var j = 0; label l loop { - printInt(j); + printNat(j); assert(j == i); i += 1; j += 1; @@ -20,7 +20,7 @@ async { var j = 0; label l loop { - printInt(j); + printNat(j); assert(j == i); i += 1; j += 1; @@ -35,7 +35,7 @@ async { var j = 0; label l loop { - printInt(j); + printNat(j); assert(j == i); await (async (i += 1)); j += 1; @@ -54,7 +54,7 @@ async { break l; assert(false); }; - printInt(j); + printNat(j); assert(j == i); await (async (i += 1)); j += 1; diff --git a/test/run-dfinity/async-obj-mut.as b/test/run-dfinity/async-obj-mut.as index 2f7f2d18708..7628ba5bb25 100644 --- a/test/run-dfinity/async-obj-mut.as +++ b/test/run-dfinity/async-obj-mut.as @@ -1,19 +1,19 @@ let _ = async { let o = object { public var x = await { async { 1 } }; - let a = printInt(x); + let a = printNat(x); // private b = (x := await { async (x + 1) }); let b = (x := x + 1); - let c = printInt(x); + let c = printNat(x); public func foo() = { x := x + 1 }; let e = foo(); - let f = printInt(x); + let f = printNat(x); }; print("\ndone creating\n"); - printInt(o.x); + printNat(o.x); o.x := o.x + 1; - printInt(o.x); + printNat(o.x); o.foo(); - printInt(o.x); + printNat(o.x); print("\n"); } diff --git a/test/run-dfinity/async-while.as b/test/run-dfinity/async-while.as index 44e621f185a..63ec7b22e87 100644 --- a/test/run-dfinity/async-while.as +++ b/test/run-dfinity/async-while.as @@ -4,7 +4,7 @@ async { { var i = 0; var j = 0; while (j <= 10) { - printInt(j); + printNat(j); assert(j == i); i += 1; j += 1; @@ -17,7 +17,7 @@ async { var i = 0; var j = 0; while (await async (j <= 10)) { - printInt(j); + printNat(j); assert(j == i); i += 1; j += 1; @@ -29,7 +29,7 @@ async { var i = 0; var j = 0; while (j <= 10) { - printInt(j); + printNat(j); assert(j == i); await (async (i += 1)); j += 1; @@ -46,7 +46,7 @@ async { break l; assert(false); }; - printInt(j); + printNat(j); assert(j == i); await (async (i += 1)); j += 1; diff --git a/test/run-dfinity/chatpp.as b/test/run-dfinity/chatpp.as index 8382528c667..3898bb67678 100644 --- a/test/run-dfinity/chatpp.as +++ b/test/run-dfinity/chatpp.as @@ -53,7 +53,7 @@ actor class Server() = { case null { clients := n.tail }; case (?p) { p.tail := n.tail }; }; - print "(unsubscribe "; printInt id; print ")\n"; + print "(unsubscribe "; printNat id; print ")\n"; return; }; prev := next; diff --git a/test/run-dfinity/closure-params.as b/test/run-dfinity/closure-params.as index 4f7c66e77f4..12c4c1239c4 100644 --- a/test/run-dfinity/closure-params.as +++ b/test/run-dfinity/closure-params.as @@ -2,7 +2,7 @@ let a = actor { var c = 0; public func incn(n : Nat) : () { c += n; - printInt(c); + printNat(c); print("\n"); }; public func readCounter(f : shared Nat -> ()) : () { @@ -11,12 +11,12 @@ let a = actor { }; a.incn(1); -a.readCounter(shared func (n : Nat) = { printInt n; print("\n") }); +a.readCounter(shared func (n : Nat) = { printNat n; print("\n") }); a.incn(2); -a.readCounter(shared func (n : Nat) = { printInt n; print("\n") }); +a.readCounter(shared func (n : Nat) = { printNat n; print("\n") }); a.incn(3); -a.readCounter(shared func (n : Nat) = { printInt n; print("\n") }); +a.readCounter(shared func (n : Nat) = { printNat n; print("\n") }); a.incn(4); -a.readCounter(shared func (n : Nat) = { printInt n; print("\n") }); +a.readCounter(shared func (n : Nat) = { printNat n; print("\n") }); a.incn(5); -a.readCounter(shared func (n : Nat) = { printInt n; print("\n") }); +a.readCounter(shared func (n : Nat) = { printNat n; print("\n") }); diff --git a/test/run-dfinity/counter.as b/test/run-dfinity/counter.as index e99d656ef79..e91575f9043 100644 --- a/test/run-dfinity/counter.as +++ b/test/run-dfinity/counter.as @@ -2,10 +2,10 @@ let a = actor { var c = 1; public func inc() { c += 1; - printInt c; print "\n"; + printNat c; print "\n"; }; public func printCounter () { - printInt c; print "\n"; + printNat c; print "\n"; } }; diff --git a/test/run-dfinity/counter2.as b/test/run-dfinity/counter2.as index 303e4122e4c..c04514bc38a 100644 --- a/test/run-dfinity/counter2.as +++ b/test/run-dfinity/counter2.as @@ -2,10 +2,10 @@ actor { var c = 1; public func inc() { c += 1; - printInt c; print "\n"; + printNat c; print "\n"; }; public func printCounter () { - printInt c; print "\n"; + printNat c; print "\n"; } } //CALL inc diff --git a/test/run-dfinity/fac.as b/test/run-dfinity/fac.as index 5abb6c2e00c..4f546b8d70e 100644 --- a/test/run-dfinity/fac.as +++ b/test/run-dfinity/fac.as @@ -3,4 +3,4 @@ func fac(n : Nat) : Nat { n * fac (n-1); }; -printInt(fac 5); +printNat(fac 5); diff --git a/test/run-dfinity/indirect-counter.as b/test/run-dfinity/indirect-counter.as index 8537fd94dc1..3d3e76955f4 100644 --- a/test/run-dfinity/indirect-counter.as +++ b/test/run-dfinity/indirect-counter.as @@ -3,10 +3,10 @@ let a = actor { var c = 1; public func inc() { c += 1; - printInt(c) + printNat(c) }; public func print() { - printInt(c) + printNat(c) }; }; public func inc() { aa.inc() }; diff --git a/test/run-dfinity/ok/data-params.dvm-run.ok b/test/run-dfinity/ok/data-params.dvm-run.ok index 0b6beb06559..a21a447d9ad 100644 --- a/test/run-dfinity/ok/data-params.dvm-run.ok +++ b/test/run-dfinity/ok/data-params.dvm-run.ok @@ -1,37 +1,37 @@ 0 -1 -3 -6 -10 -1010 -1021 -6021 -6045 -6091 -1006091 -1006105 -1006136 -1006171 -1006191 -1006211 -1006211 -Foo1: 1006211 -Foo2: 1006211 -10000001006211 -20000001006211 -1006211 -1006221 -1006211 -1006221 -1006231 -1006221 -1267650600228229401496704211597 -2535301200456458802993407416973 -1006221 -1074748045 -2148489868 -2148489868 -2148489869 -2148489911 -2148489869 -4295973516 ++1 ++3 ++6 ++10 ++1_010 ++1_021 ++6_021 ++6_045 ++6_091 ++1_006_091 ++1_006_105 ++1_006_136 ++1_006_171 ++1_006_191 ++1_006_211 ++1_006_211 +Foo1: +1_006_211 +Foo2: +1_006_211 ++10_000_001_006_211 ++20_000_001_006_211 ++1_006_211 ++1_006_221 ++1_006_211 ++1_006_221 ++1_006_231 ++1_006_221 ++1_267_650_600_228_229_401_496_704_211_597 ++2_535_301_200_456_458_802_993_407_416_973 ++1_006_221 ++1_074_748_045 ++2_148_489_868 ++2_148_489_868 ++2_148_489_869 ++2_148_489_911 ++2_148_489_869 ++4_295_973_516 diff --git a/test/run-dfinity/ok/data-params.run-ir.ok b/test/run-dfinity/ok/data-params.run-ir.ok index 38d840277a7..61053f3b7c7 100644 --- a/test/run-dfinity/ok/data-params.run-ir.ok +++ b/test/run-dfinity/ok/data-params.run-ir.ok @@ -3,39 +3,39 @@ data-params.as:59.30-59.40: warning, this pattern consuming type does not cover value null 0 -1 -3 -6 -10 -1010 -1021 -6021 -6045 -6091 -1006091 -1006105 -1006136 -1006171 -1006191 -1006211 -1006211 -Foo1: 1006211 -Foo2: 1006211 -10000001006211 -20000001006211 -1006211 -1006221 -1006211 -1006221 -1006231 -1006221 -1267650600228229401496704211597 -2535301200456458802993407416973 -1006221 -1074748045 -2148489868 -2148489868 -2148489869 -2148489911 -2148489869 -4295973516 ++1 ++3 ++6 ++10 ++1_010 ++1_021 ++6_021 ++6_045 ++6_091 ++1_006_091 ++1_006_105 ++1_006_136 ++1_006_171 ++1_006_191 ++1_006_211 ++1_006_211 +Foo1: +1_006_211 +Foo2: +1_006_211 ++10_000_001_006_211 ++20_000_001_006_211 ++1_006_211 ++1_006_221 ++1_006_211 ++1_006_221 ++1_006_231 ++1_006_221 ++1_267_650_600_228_229_401_496_704_211_597 ++2_535_301_200_456_458_802_993_407_416_973 ++1_006_221 ++1_074_748_045 ++2_148_489_868 ++2_148_489_868 ++2_148_489_869 ++2_148_489_911 ++2_148_489_869 ++4_295_973_516 diff --git a/test/run-dfinity/ok/data-params.run-low.ok b/test/run-dfinity/ok/data-params.run-low.ok index 38d840277a7..61053f3b7c7 100644 --- a/test/run-dfinity/ok/data-params.run-low.ok +++ b/test/run-dfinity/ok/data-params.run-low.ok @@ -3,39 +3,39 @@ data-params.as:59.30-59.40: warning, this pattern consuming type does not cover value null 0 -1 -3 -6 -10 -1010 -1021 -6021 -6045 -6091 -1006091 -1006105 -1006136 -1006171 -1006191 -1006211 -1006211 -Foo1: 1006211 -Foo2: 1006211 -10000001006211 -20000001006211 -1006211 -1006221 -1006211 -1006221 -1006231 -1006221 -1267650600228229401496704211597 -2535301200456458802993407416973 -1006221 -1074748045 -2148489868 -2148489868 -2148489869 -2148489911 -2148489869 -4295973516 ++1 ++3 ++6 ++10 ++1_010 ++1_021 ++6_021 ++6_045 ++6_091 ++1_006_091 ++1_006_105 ++1_006_136 ++1_006_171 ++1_006_191 ++1_006_211 ++1_006_211 +Foo1: +1_006_211 +Foo2: +1_006_211 ++10_000_001_006_211 ++20_000_001_006_211 ++1_006_211 ++1_006_221 ++1_006_211 ++1_006_221 ++1_006_231 ++1_006_221 ++1_267_650_600_228_229_401_496_704_211_597 ++2_535_301_200_456_458_802_993_407_416_973 ++1_006_221 ++1_074_748_045 ++2_148_489_868 ++2_148_489_868 ++2_148_489_869 ++2_148_489_911 ++2_148_489_869 ++4_295_973_516 diff --git a/test/run-dfinity/ok/data-params.run.ok b/test/run-dfinity/ok/data-params.run.ok index 38d840277a7..61053f3b7c7 100644 --- a/test/run-dfinity/ok/data-params.run.ok +++ b/test/run-dfinity/ok/data-params.run.ok @@ -3,39 +3,39 @@ data-params.as:59.30-59.40: warning, this pattern consuming type does not cover value null 0 -1 -3 -6 -10 -1010 -1021 -6021 -6045 -6091 -1006091 -1006105 -1006136 -1006171 -1006191 -1006211 -1006211 -Foo1: 1006211 -Foo2: 1006211 -10000001006211 -20000001006211 -1006211 -1006221 -1006211 -1006221 -1006231 -1006221 -1267650600228229401496704211597 -2535301200456458802993407416973 -1006221 -1074748045 -2148489868 -2148489868 -2148489869 -2148489911 -2148489869 -4295973516 ++1 ++3 ++6 ++10 ++1_010 ++1_021 ++6_021 ++6_045 ++6_091 ++1_006_091 ++1_006_105 ++1_006_136 ++1_006_171 ++1_006_191 ++1_006_211 ++1_006_211 +Foo1: +1_006_211 +Foo2: +1_006_211 ++10_000_001_006_211 ++20_000_001_006_211 ++1_006_211 ++1_006_221 ++1_006_211 ++1_006_221 ++1_006_231 ++1_006_221 ++1_267_650_600_228_229_401_496_704_211_597 ++2_535_301_200_456_458_802_993_407_416_973 ++1_006_221 ++1_074_748_045 ++2_148_489_868 ++2_148_489_868 ++2_148_489_869 ++2_148_489_911 ++2_148_489_869 ++4_295_973_516 diff --git a/test/run-dfinity/ok/show.dvm-run.ok b/test/run-dfinity/ok/show.dvm-run.ok index 819767efd2e..7f4f28dc1ee 100644 --- a/test/run-dfinity/ok/show.dvm-run.ok +++ b/test/run-dfinity/ok/show.dvm-run.ok @@ -1,24 +1,35 @@ true false --42000000000000 --42000000 --42000 +-42_000_000_000_000 +-42_000_000 +-42_000 -42 0 0 ++42 ++42_000 ++42_000_000 ++420_000_000_000_000 +0 42 -42000 -42000000 -420000000000000 +42_000 +42_000_000 +420_000_000_000_000 (42, -42, ()) -("Foobar", null, null, ?(23)) +("Foobar", null, null, ?23) +[] [1, 2, 3] +[var] [var 1, 2, 3] -{bar = true; foo = 42} -(#foo) -(#bar 42) -(#foo 42) -42 -42 +{bar = true; foo = +42} +#foo +#bar(1, 2) +#bar({}) +#bar([]) +#bar(42) +#bar(-42) +#foo(+42) +0x2A 42 ++42 -42 diff --git a/test/run-dfinity/ok/show.run-ir.ok b/test/run-dfinity/ok/show.run-ir.ok index 819767efd2e..7f4f28dc1ee 100644 --- a/test/run-dfinity/ok/show.run-ir.ok +++ b/test/run-dfinity/ok/show.run-ir.ok @@ -1,24 +1,35 @@ true false --42000000000000 --42000000 --42000 +-42_000_000_000_000 +-42_000_000 +-42_000 -42 0 0 ++42 ++42_000 ++42_000_000 ++420_000_000_000_000 +0 42 -42000 -42000000 -420000000000000 +42_000 +42_000_000 +420_000_000_000_000 (42, -42, ()) -("Foobar", null, null, ?(23)) +("Foobar", null, null, ?23) +[] [1, 2, 3] +[var] [var 1, 2, 3] -{bar = true; foo = 42} -(#foo) -(#bar 42) -(#foo 42) -42 -42 +{bar = true; foo = +42} +#foo +#bar(1, 2) +#bar({}) +#bar([]) +#bar(42) +#bar(-42) +#foo(+42) +0x2A 42 ++42 -42 diff --git a/test/run-dfinity/ok/show.run-low.ok b/test/run-dfinity/ok/show.run-low.ok index 819767efd2e..7f4f28dc1ee 100644 --- a/test/run-dfinity/ok/show.run-low.ok +++ b/test/run-dfinity/ok/show.run-low.ok @@ -1,24 +1,35 @@ true false --42000000000000 --42000000 --42000 +-42_000_000_000_000 +-42_000_000 +-42_000 -42 0 0 ++42 ++42_000 ++42_000_000 ++420_000_000_000_000 +0 42 -42000 -42000000 -420000000000000 +42_000 +42_000_000 +420_000_000_000_000 (42, -42, ()) -("Foobar", null, null, ?(23)) +("Foobar", null, null, ?23) +[] [1, 2, 3] +[var] [var 1, 2, 3] -{bar = true; foo = 42} -(#foo) -(#bar 42) -(#foo 42) -42 -42 +{bar = true; foo = +42} +#foo +#bar(1, 2) +#bar({}) +#bar([]) +#bar(42) +#bar(-42) +#foo(+42) +0x2A 42 ++42 -42 diff --git a/test/run-dfinity/ok/show.run.ok b/test/run-dfinity/ok/show.run.ok index 819767efd2e..7f4f28dc1ee 100644 --- a/test/run-dfinity/ok/show.run.ok +++ b/test/run-dfinity/ok/show.run.ok @@ -1,24 +1,35 @@ true false --42000000000000 --42000000 --42000 +-42_000_000_000_000 +-42_000_000 +-42_000 -42 0 0 ++42 ++42_000 ++42_000_000 ++420_000_000_000_000 +0 42 -42000 -42000000 -420000000000000 +42_000 +42_000_000 +420_000_000_000_000 (42, -42, ()) -("Foobar", null, null, ?(23)) +("Foobar", null, null, ?23) +[] [1, 2, 3] +[var] [var 1, 2, 3] -{bar = true; foo = 42} -(#foo) -(#bar 42) -(#foo 42) -42 -42 +{bar = true; foo = +42} +#foo +#bar(1, 2) +#bar({}) +#bar([]) +#bar(42) +#bar(-42) +#foo(+42) +0x2A 42 ++42 -42 diff --git a/test/run-dfinity/ok/text-iter.dvm-run.ok b/test/run-dfinity/ok/text-iter.dvm-run.ok index 5ac6300d553..1a0889b1e4f 100644 --- a/test/run-dfinity/ok/text-iter.dvm-run.ok +++ b/test/run-dfinity/ok/text-iter.dvm-run.ok @@ -14,7 +14,5 @@ via iteration and `printChar` (Unicode): #4 1:'🙈' 2:'🎸' 3:'😋' Приветствую, мир! -2 П -4 🙈 diff --git a/test/run-dfinity/ok/text-iter.run-ir.ok b/test/run-dfinity/ok/text-iter.run-ir.ok index 5ac6300d553..1a0889b1e4f 100644 --- a/test/run-dfinity/ok/text-iter.run-ir.ok +++ b/test/run-dfinity/ok/text-iter.run-ir.ok @@ -14,7 +14,5 @@ via iteration and `printChar` (Unicode): #4 1:'🙈' 2:'🎸' 3:'😋' Приветствую, мир! -2 П -4 🙈 diff --git a/test/run-dfinity/ok/text-iter.run-low.ok b/test/run-dfinity/ok/text-iter.run-low.ok index 5ac6300d553..1a0889b1e4f 100644 --- a/test/run-dfinity/ok/text-iter.run-low.ok +++ b/test/run-dfinity/ok/text-iter.run-low.ok @@ -14,7 +14,5 @@ via iteration and `printChar` (Unicode): #4 1:'🙈' 2:'🎸' 3:'😋' Приветствую, мир! -2 П -4 🙈 diff --git a/test/run-dfinity/ok/text-iter.run.ok b/test/run-dfinity/ok/text-iter.run.ok index 5ac6300d553..1a0889b1e4f 100644 --- a/test/run-dfinity/ok/text-iter.run.ok +++ b/test/run-dfinity/ok/text-iter.run.ok @@ -14,7 +14,5 @@ via iteration and `printChar` (Unicode): #4 1:'🙈' 2:'🎸' 3:'😋' Приветствую, мир! -2 П -4 🙈 diff --git a/test/run-dfinity/show.as b/test/run-dfinity/show.as index 502d1be8b2a..b0948366ca9 100644 --- a/test/run-dfinity/show.as +++ b/test/run-dfinity/show.as @@ -6,6 +6,11 @@ printLn(debug_show (-42000000)); printLn(debug_show (-42000)); printLn(debug_show (-42)); printLn(debug_show (-0)); +printLn(debug_show (+0)); +printLn(debug_show (+42)); +printLn(debug_show (+42000)); +printLn(debug_show (+42000000)); +printLn(debug_show (+420000000000000)); printLn(debug_show (0)); printLn(debug_show (42)); printLn(debug_show (42000)); @@ -13,13 +18,19 @@ printLn(debug_show (42000000)); printLn(debug_show (420000000000000)); printLn(debug_show (42,-42,())); printLn(debug_show ("Foobar", null, null, ?23)); +printLn(debug_show ([])); printLn(debug_show ([1,2,3])); +printLn(debug_show ([var])); printLn(debug_show ([var 1,2,3])); class Foo() { public let foo : Int = 42; public var bar : Bool = true ; let hidden = [1,2] }; printLn(debug_show (Foo())); printLn(debug_show (#foo ())); +printLn(debug_show (#bar (1, 2))); +printLn(debug_show (#bar {})); +printLn(debug_show (#bar ([]))); printLn(debug_show (#bar 42)); -printLn(debug_show ((#foo 42): {#foo : Int; #bar : Text})); +printLn(debug_show (#bar (-42))); +printLn(debug_show (#foo 42 : {#foo : Int; #bar : Text})); printLn(debug_show (42 : Word16)); printLn(debug_show (42 : Nat8)); printLn(debug_show (42 : Int32)); diff --git a/test/run-dfinity/text-iter.as b/test/run-dfinity/text-iter.as index 36f987b9392..84693bb89d6 100644 --- a/test/run-dfinity/text-iter.as +++ b/test/run-dfinity/text-iter.as @@ -14,7 +14,7 @@ print "via iteration and `printChar`: #2\n"; var x = 0; for (a in s.chars()) { x += 1; - printInt x; + printNat x; print ":"; printChar '\''; printChar a; @@ -30,7 +30,7 @@ print "via iteration and `printChar` (Unicode): #3\n"; x := 0; for (a in russian.chars()) { x += 1; - printInt x; + printNat x; print ":"; printChar '\''; printChar a; @@ -47,7 +47,7 @@ print "via iteration and `printChar` (Unicode): #4\n"; x := 0; for (a in emojis.chars()) { x += 1; - printInt x; + printNat x; print ":"; printChar '\''; printChar a; @@ -57,16 +57,13 @@ for (a in emojis.chars()) { print "\n"; assert(x == 3); -{ - let (len, c) = decodeUTF8 russian; - print russian; print "\n"; - printInt (word32ToInt len); print "\n"; - printChar c; print "\n"; +print russian; print "\n"; +switch (russian.chars().next()) { + case (?c) { printChar c; print "\n" }; + case _ {}; }; -{ - let (len, c) = decodeUTF8 emojis; - assert ((len == (4 : Word32)) and (c == '\u{1f648}')); - printInt (word32ToInt len); print "\n"; - printChar c; print "\n"; +switch (emojis.chars().next()) { + case (?c) { assert (c == '\u{1f648}'); printChar c; print "\n" }; + case _ {}; }; diff --git a/test/run-dfinity/the-answer.as b/test/run-dfinity/the-answer.as index feb0a45a809..43657e60ede 100644 --- a/test/run-dfinity/the-answer.as +++ b/test/run-dfinity/the-answer.as @@ -1 +1 @@ -printInt(42); +printNat(42); diff --git a/test/run/await.as b/test/run/await.as index 2544e22650c..c0788bdf348 100644 --- a/test/run/await.as +++ b/test/run/await.as @@ -1,10 +1,10 @@ -var cnt : Int = 0; +var cnt : Nat = 0; -func f(i:Int) : async Int { +func f(i:Nat) : async Nat { print "cnt: "; - printInt cnt; + printNat cnt; print " i: "; - printInt i; + printNat i; print "\n"; cnt += 1; cnt; diff --git a/test/run/block.as b/test/run/block.as index 04163d95117..c5bd3f1b17a 100644 --- a/test/run/block.as +++ b/test/run/block.as @@ -18,18 +18,18 @@ let c = async { let d = async { var f = 1; - printInt (f); + printNat (f); let (a,b) = await (async ("a4","b4")); f += 2; - printInt (f); + printNat (f); }; let e = async { var f = await (async 5); - printInt (f); + printNat (f); let (a,b) = await (async ("a5","b5")); f += 1; - printInt (f); + printNat (f); }; diff --git a/test/run/conversions.as b/test/run/conversions.as index 17f3297accb..9316ba04756 100644 --- a/test/run/conversions.as +++ b/test/run/conversions.as @@ -161,7 +161,7 @@ assert(charToWord32 '\u{10ffff}' == (0x10FFFF : Word32)); assert(charToText 'П' == "П"); func snd((a : Word32, b : Char)) : Char = b; -assert(snd (decodeUTF8 "П") =='П'); +assert(switch ("П".chars().next()) { case (?'П') true; case _ false }); // Nat <--> Word64 diff --git a/test/run/for.as b/test/run/for.as index 1f62f884f24..42dbace9ea8 100644 --- a/test/run/for.as +++ b/test/run/for.as @@ -3,7 +3,7 @@ async { { var i = 0; for (j in range(0, 10)) { - printInt(j); + printNat(j); assert(j == i); i += 1; }; @@ -14,7 +14,7 @@ async { var i = 0; i := 0; for (j in range(0, 10)) { - printInt(j); + printNat(j); assert(j == i); await (async (i += 1)); }; diff --git a/test/run/idlHash.as b/test/run/idlHash.as index a118bac6e08..3d2546dbbcf 100644 --- a/test/run/idlHash.as +++ b/test/run/idlHash.as @@ -12,4 +12,3 @@ testHash("id", 23515); testHash("description", 1595738364); testHash("short_name", 3261810734); testHash("Hi ☃", 1419229646); - diff --git a/test/run/ok/conversions.run-ir.ok b/test/run/ok/conversions.run-ir.ok index bdd38965601..976fbb2ff3e 100644 --- a/test/run/ok/conversions.run-ir.ok +++ b/test/run/ok/conversions.run-ir.ok @@ -1,10 +1,10 @@ --2147483648 --2147483647 +-2_147_483_648 +-2_147_483_647 -42 -1 0 -42 -2147483647 --2147483648 ++42 ++2_147_483_647 +-2_147_483_648 -2 -1 diff --git a/test/run/ok/conversions.run-low.ok b/test/run/ok/conversions.run-low.ok index bdd38965601..976fbb2ff3e 100644 --- a/test/run/ok/conversions.run-low.ok +++ b/test/run/ok/conversions.run-low.ok @@ -1,10 +1,10 @@ --2147483648 --2147483647 +-2_147_483_648 +-2_147_483_647 -42 -1 0 -42 -2147483647 --2147483648 ++42 ++2_147_483_647 +-2_147_483_648 -2 -1 diff --git a/test/run/ok/conversions.run.ok b/test/run/ok/conversions.run.ok index bdd38965601..976fbb2ff3e 100644 --- a/test/run/ok/conversions.run.ok +++ b/test/run/ok/conversions.run.ok @@ -1,10 +1,10 @@ --2147483648 --2147483647 +-2_147_483_648 +-2_147_483_647 -42 -1 0 -42 -2147483647 --2147483648 ++42 ++2_147_483_647 +-2_147_483_648 -2 -1 diff --git a/test/run/ok/idlHash.run-ir.ok b/test/run/ok/idlHash.run-ir.ok index eb89fe0b5af..c09174ebcb4 100644 --- a/test/run/ok/idlHash.run-ir.ok +++ b/test/run/ok/idlHash.run-ir.ok @@ -2,14 +2,14 @@ Hash for : Expected: 0 Actual: 0 Hash for id: -Expected: 23515 -Actual: 23515 +Expected: 23_515 +Actual: 23_515 Hash for description: -Expected: 1595738364 -Actual: 1595738364 +Expected: 1_595_738_364 +Actual: 1_595_738_364 Hash for short_name: -Expected: 3261810734 -Actual: 3261810734 +Expected: 3_261_810_734 +Actual: 3_261_810_734 Hash for Hi ☃: -Expected: 1419229646 -Actual: 1419229646 +Expected: 1_419_229_646 +Actual: 1_419_229_646 diff --git a/test/run/ok/idlHash.run-low.ok b/test/run/ok/idlHash.run-low.ok index eb89fe0b5af..c09174ebcb4 100644 --- a/test/run/ok/idlHash.run-low.ok +++ b/test/run/ok/idlHash.run-low.ok @@ -2,14 +2,14 @@ Hash for : Expected: 0 Actual: 0 Hash for id: -Expected: 23515 -Actual: 23515 +Expected: 23_515 +Actual: 23_515 Hash for description: -Expected: 1595738364 -Actual: 1595738364 +Expected: 1_595_738_364 +Actual: 1_595_738_364 Hash for short_name: -Expected: 3261810734 -Actual: 3261810734 +Expected: 3_261_810_734 +Actual: 3_261_810_734 Hash for Hi ☃: -Expected: 1419229646 -Actual: 1419229646 +Expected: 1_419_229_646 +Actual: 1_419_229_646 diff --git a/test/run/ok/idlHash.run.ok b/test/run/ok/idlHash.run.ok index eb89fe0b5af..c09174ebcb4 100644 --- a/test/run/ok/idlHash.run.ok +++ b/test/run/ok/idlHash.run.ok @@ -2,14 +2,14 @@ Hash for : Expected: 0 Actual: 0 Hash for id: -Expected: 23515 -Actual: 23515 +Expected: 23_515 +Actual: 23_515 Hash for description: -Expected: 1595738364 -Actual: 1595738364 +Expected: 1_595_738_364 +Actual: 1_595_738_364 Hash for short_name: -Expected: 3261810734 -Actual: 3261810734 +Expected: 3_261_810_734 +Actual: 3_261_810_734 Hash for Hi ☃: -Expected: 1419229646 -Actual: 1419229646 +Expected: 1_419_229_646 +Actual: 1_419_229_646 diff --git a/test/run/ok/words.run-ir.ok b/test/run/ok/words.run-ir.ok index bead286abe0..dd9453afeb5 100644 --- a/test/run/ok/words.run-ir.ok +++ b/test/run/ok/words.run-ir.ok @@ -1,98 +1,98 @@ -8912765 8912765 -18446744073700638851 -8912765 -18446744073700638850 -8912766 -8917332 8917332 -8908198 8908198 -31969 31969 -652 652 -2548 2548 -20857489 20857489 -4437 4437 -8912895 8912895 -8908458 8908458 -584576 584576 -35 35 -826339054743125951 826339054743125951 -18446744073709551614 -2 -18120161623845830591 -326582449863721025 -1140833920 1140833920 -18014398509482053630 -432345564227497986 -61 61 -49 49 -5 5 +8_912_765 +8_912_765 +18_446_744_073_700_638_851 -8_912_765 +18_446_744_073_700_638_850 -8_912_766 +8_917_332 +8_917_332 +8_908_198 +8_908_198 +31_969 +31_969 +652 +652 +2_548 +2_548 +20_857_489 +20_857_489 +4_437 +4_437 +8_912_895 +8_912_895 +8_908_458 +8_908_458 +584_576 +584_576 +35 +35 +826_339_054_743_125_951 +826_339_054_743_125_951 +18_446_744_073_709_551_614 -2 +18_120_161_623_845_830_591 -326_582_449_863_721_025 +1_140_833_920 +1_140_833_920 +18_014_398_509_482_053_630 -432_345_564_227_497_986 +61 +61 +49 +49 +5 +5 set clear set -8912765 8912765 -4286054531 -8912765 -4286054530 -8912766 -8917332 8917332 -8908198 8908198 -31969 31969 -652 652 -2548 2548 -20857489 20857489 -4437 4437 -8912895 8912895 -8908458 8908458 -584576 584576 -35 35 -192397053 192397053 -4294967294 -2 -4218928893 -76038403 -1140833920 1140833920 -4194373630 -100593666 -29 29 -17 17 -5 5 +8_912_765 +8_912_765 +4_286_054_531 -8_912_765 +4_286_054_530 -8_912_766 +8_917_332 +8_917_332 +8_908_198 +8_908_198 +31_969 +31_969 +652 +652 +2_548 +2_548 +20_857_489 +20_857_489 +4_437 +4_437 +8_912_895 +8_912_895 +8_908_458 +8_908_458 +584_576 +584_576 +35 +35 +192_397_053 +192_397_053 +4_294_967_294 -2 +4_218_928_893 -76_038_403 +1_140_833_920 +1_140_833_920 +4_194_373_630 -100_593_666 +29 +29 +17 +17 +5 +5 set clear set -55734 -9802 -9802 9802 -9801 9801 -60301 -5235 -51167 -14369 -31969 31969 -652 652 -930 930 -17041 17041 -4502 4502 -55799 -9737 -51297 -14239 -60288 -5248 -35 35 -8190 8190 -65534 -2 -56172 -9364 -28083 28083 -13 13 -1 1 -5 5 +55_734 -9_802 +9_802 +9_802 +9_801 +9_801 +60_301 -5_235 +51_167 -14_369 +31_969 +31_969 +652 +652 +930 +930 +17_041 +17_041 +4_502 +4_502 +55_799 -9_737 +51_297 -14_239 +60_288 -5_248 +35 +35 +8_190 +8_190 +65_534 -2 +56_172 -9_364 +28_083 +28_083 +13 +13 +1 +1 +5 +5 set clear set -34 34 +34 +34 222 -34 221 -35 -101 101 +101 +101 223 -33 213 -43 -9 9 -34 34 +9 +9 +34 +34 137 -119 -2 2 -99 99 -97 97 +2 +2 +99 +99 +97 +97 128 -128 0 0 -30 30 +30 +30 254 -2 -17 17 -68 68 -5 5 +17 +17 +68 +68 +5 +5 0 0 -3 3 +3 +3 set clear set diff --git a/test/run/ok/words.run-low.ok b/test/run/ok/words.run-low.ok index bead286abe0..dd9453afeb5 100644 --- a/test/run/ok/words.run-low.ok +++ b/test/run/ok/words.run-low.ok @@ -1,98 +1,98 @@ -8912765 8912765 -18446744073700638851 -8912765 -18446744073700638850 -8912766 -8917332 8917332 -8908198 8908198 -31969 31969 -652 652 -2548 2548 -20857489 20857489 -4437 4437 -8912895 8912895 -8908458 8908458 -584576 584576 -35 35 -826339054743125951 826339054743125951 -18446744073709551614 -2 -18120161623845830591 -326582449863721025 -1140833920 1140833920 -18014398509482053630 -432345564227497986 -61 61 -49 49 -5 5 +8_912_765 +8_912_765 +18_446_744_073_700_638_851 -8_912_765 +18_446_744_073_700_638_850 -8_912_766 +8_917_332 +8_917_332 +8_908_198 +8_908_198 +31_969 +31_969 +652 +652 +2_548 +2_548 +20_857_489 +20_857_489 +4_437 +4_437 +8_912_895 +8_912_895 +8_908_458 +8_908_458 +584_576 +584_576 +35 +35 +826_339_054_743_125_951 +826_339_054_743_125_951 +18_446_744_073_709_551_614 -2 +18_120_161_623_845_830_591 -326_582_449_863_721_025 +1_140_833_920 +1_140_833_920 +18_014_398_509_482_053_630 -432_345_564_227_497_986 +61 +61 +49 +49 +5 +5 set clear set -8912765 8912765 -4286054531 -8912765 -4286054530 -8912766 -8917332 8917332 -8908198 8908198 -31969 31969 -652 652 -2548 2548 -20857489 20857489 -4437 4437 -8912895 8912895 -8908458 8908458 -584576 584576 -35 35 -192397053 192397053 -4294967294 -2 -4218928893 -76038403 -1140833920 1140833920 -4194373630 -100593666 -29 29 -17 17 -5 5 +8_912_765 +8_912_765 +4_286_054_531 -8_912_765 +4_286_054_530 -8_912_766 +8_917_332 +8_917_332 +8_908_198 +8_908_198 +31_969 +31_969 +652 +652 +2_548 +2_548 +20_857_489 +20_857_489 +4_437 +4_437 +8_912_895 +8_912_895 +8_908_458 +8_908_458 +584_576 +584_576 +35 +35 +192_397_053 +192_397_053 +4_294_967_294 -2 +4_218_928_893 -76_038_403 +1_140_833_920 +1_140_833_920 +4_194_373_630 -100_593_666 +29 +29 +17 +17 +5 +5 set clear set -55734 -9802 -9802 9802 -9801 9801 -60301 -5235 -51167 -14369 -31969 31969 -652 652 -930 930 -17041 17041 -4502 4502 -55799 -9737 -51297 -14239 -60288 -5248 -35 35 -8190 8190 -65534 -2 -56172 -9364 -28083 28083 -13 13 -1 1 -5 5 +55_734 -9_802 +9_802 +9_802 +9_801 +9_801 +60_301 -5_235 +51_167 -14_369 +31_969 +31_969 +652 +652 +930 +930 +17_041 +17_041 +4_502 +4_502 +55_799 -9_737 +51_297 -14_239 +60_288 -5_248 +35 +35 +8_190 +8_190 +65_534 -2 +56_172 -9_364 +28_083 +28_083 +13 +13 +1 +1 +5 +5 set clear set -34 34 +34 +34 222 -34 221 -35 -101 101 +101 +101 223 -33 213 -43 -9 9 -34 34 +9 +9 +34 +34 137 -119 -2 2 -99 99 -97 97 +2 +2 +99 +99 +97 +97 128 -128 0 0 -30 30 +30 +30 254 -2 -17 17 -68 68 -5 5 +17 +17 +68 +68 +5 +5 0 0 -3 3 +3 +3 set clear set diff --git a/test/run/ok/words.run.ok b/test/run/ok/words.run.ok index bead286abe0..dd9453afeb5 100644 --- a/test/run/ok/words.run.ok +++ b/test/run/ok/words.run.ok @@ -1,98 +1,98 @@ -8912765 8912765 -18446744073700638851 -8912765 -18446744073700638850 -8912766 -8917332 8917332 -8908198 8908198 -31969 31969 -652 652 -2548 2548 -20857489 20857489 -4437 4437 -8912895 8912895 -8908458 8908458 -584576 584576 -35 35 -826339054743125951 826339054743125951 -18446744073709551614 -2 -18120161623845830591 -326582449863721025 -1140833920 1140833920 -18014398509482053630 -432345564227497986 -61 61 -49 49 -5 5 +8_912_765 +8_912_765 +18_446_744_073_700_638_851 -8_912_765 +18_446_744_073_700_638_850 -8_912_766 +8_917_332 +8_917_332 +8_908_198 +8_908_198 +31_969 +31_969 +652 +652 +2_548 +2_548 +20_857_489 +20_857_489 +4_437 +4_437 +8_912_895 +8_912_895 +8_908_458 +8_908_458 +584_576 +584_576 +35 +35 +826_339_054_743_125_951 +826_339_054_743_125_951 +18_446_744_073_709_551_614 -2 +18_120_161_623_845_830_591 -326_582_449_863_721_025 +1_140_833_920 +1_140_833_920 +18_014_398_509_482_053_630 -432_345_564_227_497_986 +61 +61 +49 +49 +5 +5 set clear set -8912765 8912765 -4286054531 -8912765 -4286054530 -8912766 -8917332 8917332 -8908198 8908198 -31969 31969 -652 652 -2548 2548 -20857489 20857489 -4437 4437 -8912895 8912895 -8908458 8908458 -584576 584576 -35 35 -192397053 192397053 -4294967294 -2 -4218928893 -76038403 -1140833920 1140833920 -4194373630 -100593666 -29 29 -17 17 -5 5 +8_912_765 +8_912_765 +4_286_054_531 -8_912_765 +4_286_054_530 -8_912_766 +8_917_332 +8_917_332 +8_908_198 +8_908_198 +31_969 +31_969 +652 +652 +2_548 +2_548 +20_857_489 +20_857_489 +4_437 +4_437 +8_912_895 +8_912_895 +8_908_458 +8_908_458 +584_576 +584_576 +35 +35 +192_397_053 +192_397_053 +4_294_967_294 -2 +4_218_928_893 -76_038_403 +1_140_833_920 +1_140_833_920 +4_194_373_630 -100_593_666 +29 +29 +17 +17 +5 +5 set clear set -55734 -9802 -9802 9802 -9801 9801 -60301 -5235 -51167 -14369 -31969 31969 -652 652 -930 930 -17041 17041 -4502 4502 -55799 -9737 -51297 -14239 -60288 -5248 -35 35 -8190 8190 -65534 -2 -56172 -9364 -28083 28083 -13 13 -1 1 -5 5 +55_734 -9_802 +9_802 +9_802 +9_801 +9_801 +60_301 -5_235 +51_167 -14_369 +31_969 +31_969 +652 +652 +930 +930 +17_041 +17_041 +4_502 +4_502 +55_799 -9_737 +51_297 -14_239 +60_288 -5_248 +35 +35 +8_190 +8_190 +65_534 -2 +56_172 -9_364 +28_083 +28_083 +13 +13 +1 +1 +5 +5 set clear set -34 34 +34 +34 222 -34 221 -35 -101 101 +101 +101 223 -33 213 -43 -9 9 -34 34 +9 +9 +34 +34 137 -119 -2 2 -99 99 -97 97 +2 +2 +99 +99 +97 +97 128 -128 0 0 -30 30 +30 +30 254 -2 -17 17 -68 68 -5 5 +17 +17 +68 +68 +5 +5 0 0 -3 3 +3 +3 set clear set diff --git a/test/run/variants.as b/test/run/variants.as index ecb986a7cea..f8693c653be 100644 --- a/test/run/variants.as +++ b/test/run/variants.as @@ -10,8 +10,8 @@ func size(t : Tree) : Nat { let tt1 : Tree = #branch(#leaf 1, #leaf (-1)); let tt2 = #leaf ""; // infers type {#leaf : Text} which is a subtype of Tree -printInt(size(tt1)); print "\n"; -printInt(size(tt2)); print "\n"; +printNat(size(tt1)); print "\n"; +printNat(size(tt2)); print "\n"; // subtyping @@ -49,7 +49,7 @@ func sayIcelandic (day : Weekday) : Text = switch day { assert (sayIcelandic (#Wednesday) == "Miðvikudagur"); -assert (debug_show (#foo (#bar)) == "(#foo (#bar))"); +assert (debug_show (#foo (#bar)) == "#foo(#bar)"); assert ([#Monday, #Tuesday, #Wednesday, #Thursday, #Friday, #Saturday, #Sunday].len() == 7); diff --git a/test/run/words.as b/test/run/words.as index eb9f0444769..099fcb2cd78 100644 --- a/test/run/words.as +++ b/test/run/words.as @@ -16,7 +16,7 @@ func checkpointJuliett() {}; // Word64 operations { - func printW64ln(w : Word64) { printInt(word64ToNat w); print " "; printInt(word64ToInt w); print "\n" }; + func printW64ln(w : Word64) { printNat(word64ToNat w); print " "; printInt(word64ToInt w); print "\n" }; let a : Word64 = 4567; let b : Word64 = 7; @@ -71,7 +71,7 @@ func checkpointJuliett() {}; // Word32 operations { - func printW32ln(w : Word32) { printInt(word32ToNat w); print " "; printInt(word32ToInt w); print "\n" }; + func printW32ln(w : Word32) { printNat(word32ToNat w); print " "; printInt(word32ToInt w); print "\n" }; let a : Word32 = 4567; let b : Word32 = 7; @@ -125,7 +125,7 @@ func checkpointJuliett() {}; // Word16 operations { - func printW16ln(w : Word16) { printInt(word16ToNat w); print " "; printInt(word16ToInt w); print "\n" }; + func printW16ln(w : Word16) { printNat(word16ToNat w); print " "; printInt(word16ToInt w); print "\n" }; let a : Word16 = 4567; let b : Word16 = 7; @@ -205,7 +205,7 @@ func checkpointJuliett() {}; // Word8 operations { - func printW8ln(w : Word8) { printInt(word8ToNat w); print " "; printInt(word8ToInt w); print "\n" }; + func printW8ln(w : Word8) { printNat(word8ToNat w); print " "; printInt(word8ToInt w); print "\n" }; let a : Word8 = 67; let b : Word8 = 7; From a62c25102f19a0de47e1de6ef8bc365d3be68d91 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 15 Aug 2019 15:39:00 +0200 Subject: [PATCH 0350/1176] IDL parsing: Use type description table ACT-111 (#602) * Create type description table * Check that all references to it are valid and within bounds. * Deserialization: Keep mutable buffer pointer in memory, less use of multi-value, easier interop with C. * Use that buffer abstraction in idl.c * Deserialization: Do not go through bignum to read leb128-encoded words * Use the type table and add more sanity checking along the way. * Read primitive numbers with bounds check * Make signedness a flag of compile_load_from_data_buf * IDL: Let Nat/Int decoding use the buffer abstraction (simpler code, no need to calculate size separately, does bounds-checking.) * IDL parser: bounds-checking also when reading references * Array.alloc: Trap upon absurd allocation sizes * IDL: Do bounds-checking when reading Text values --- rts/Makefile | 6 +- rts/bigint.c | 114 +++++---- rts/buf.c | 17 ++ rts/buf.h | 20 ++ rts/idl.c | 171 +++++++++----- rts/rts.c | 39 +++ rts/rts.h | 5 + src/codegen/compile.ml | 523 ++++++++++++++++++++++++----------------- 8 files changed, 564 insertions(+), 331 deletions(-) create mode 100644 rts/buf.c create mode 100644 rts/buf.h diff --git a/rts/Makefile b/rts/Makefile index 0e424a877ae..df721f85a4e 100644 --- a/rts/Makefile +++ b/rts/Makefile @@ -79,12 +79,12 @@ TOMMATH_NATIVE_O=$(TOMMATHFILES:%=_build/native/tommath_%.o) # Our part of the RTS, Wasm and native # -RTSFILES=rts idl bigint +RTSFILES=rts idl bigint buf -_build/wasm/%.o: %.c | _build/wasm +_build/wasm/%.o: %.c rts.h buf.h | _build/wasm $(WASM_CLANG) -c $(CLANG_FLAGS) $(WASM_FLAGS) $(TOMMATH_FLAGS) -I$(TOMMATHSRC) --std=c11 $< --output $@ -_build/native/%.o: %.c | _build/native +_build/native/%.o: %.c rts.h buf.h | _build/native $(CLANG) -c $(CLANG_FLAGS) $(TOMMATH_FLAGS) -I$(TOMMATHSRC) --std=c11 $< --output $@ RTS_WASM_O=$(RTSFILES:%=_build/wasm/%.o) diff --git a/rts/bigint.c b/rts/bigint.c index efc63b60071..678c0ba19c8 100644 --- a/rts/bigint.c +++ b/rts/bigint.c @@ -1,4 +1,5 @@ #include "rts.h" +#include "buf.h" /* Memory management for libtommath */ @@ -260,7 +261,7 @@ export int bigint_count_bits(as_ptr a) { return mp_count_bits(BIGINT_PAYLOAD(a)); } -/* LEB128 Encoding-decoding */ +/* (S)LEB128 Encoding */ export int bigint_leb128_size(as_ptr n) { if (mp_iszero(BIGINT_PAYLOAD(n))) return 1; int x = bigint_count_bits(n); @@ -298,31 +299,7 @@ int leb128_encoding_size(unsigned char *buf) { return i+1; } -as_ptr leb128_decode_go(unsigned char *buf, int bytes) { - // do not accept overlong encodings - if (buf[bytes-1] == 1<<7) bigint_trap(); - as_ptr r = bigint_alloc(); - CHECK(mp_init(BIGINT_PAYLOAD(r))); - int i = bytes-1; - while (true) { - CHECK(mp_add_d(BIGINT_PAYLOAD(r), buf[i] & ((1<<7)-1), BIGINT_PAYLOAD(r))); - if (i > 0) { - CHECK(mp_mul_2d(BIGINT_PAYLOAD(r), 7, BIGINT_PAYLOAD(r))); - i--; - } else { - break; - } - } - return r; -} - -export as_ptr bigint_leb128_decode(unsigned char *buf) { - int bytes = leb128_encoding_size(buf); - return leb128_decode_go(buf, bytes); -} - -/* SLEB128 Encoding-decoding */ export int bigint_2complement_bits(as_ptr n) { if (mp_isneg(BIGINT_PAYLOAD(n))) { mp_int tmp; @@ -355,47 +332,66 @@ export void bigint_sleb128_encode(as_ptr n, unsigned char *buf) { bigint_leb128_encode_go(&tmp, buf); } -export as_ptr bigint_sleb128_decode(unsigned char *buf) { - int bytes = leb128_encoding_size(buf); +/* (S)LEB128 Decoding */ - as_ptr r = leb128_decode_go(buf, bytes); +export as_ptr bigint_leb128_decode(buf *buf) { + as_ptr r = bigint_alloc(); + mp_zero(BIGINT_PAYLOAD(r)); + mp_int tmp; + CHECK(mp_init(&tmp)); + unsigned int s = 0; + uint8_t b; + do { + b = read_byte(buf); + if (s > 0 && b == 0x00) { + // The high 7 bits are all zeros, this is not a shortest encoding + idl_trap(); + } + if (s + 7 < s) { + // shift overflow. number is absurdly large anyways + idl_trap(); + } + mp_set_u32(&tmp, (b & (uint8_t)0x7f)); + CHECK(mp_mul_2d(&tmp, s, &tmp)); + CHECK(mp_add(BIGINT_PAYLOAD(r), &tmp, BIGINT_PAYLOAD(r))); + s += 7; + } while (b & (uint8_t)0x80); + return r; +} - // Now adjust sign if necessary - if (buf[bytes-1] & (1<<6)) { - // negative number +export as_ptr bigint_sleb128_decode(buf *buf) { + as_ptr r = bigint_alloc(); + mp_zero(BIGINT_PAYLOAD(r)); + mp_int tmp; + CHECK(mp_init(&tmp)); + unsigned int s = 0; + uint8_t b; + bool last_sign_bit_set = 0; + do { + b = read_byte(buf); + if (s > 0 && ((!last_sign_bit_set && b == 0x00) || (last_sign_bit_set && b == 0x8F))) { + // The high 8 bits are all zeros or ones, so this is not a shortest encoding + idl_trap(); + } + if (s + 7 < s) { + // shift overflow. number is absurdly large anyways + idl_trap(); + } + mp_set_u32(&tmp, (b & (uint8_t)0x7f)); + CHECK(mp_mul_2d(&tmp, s, &tmp)); + CHECK(mp_add(BIGINT_PAYLOAD(r), &tmp, BIGINT_PAYLOAD(r))); + last_sign_bit_set = (b & (uint8_t)0x40); + s += 7; + } while (b & (uint8_t)0x80); + + if (last_sign_bit_set) { + // negative number, un-2-complement it mp_int big; CHECK(mp_init(&big)); - CHECK(mp_2expt(&big, 7*bytes)); + CHECK(mp_2expt(&big, s)); CHECK(mp_sub(BIGINT_PAYLOAD(r), &big, BIGINT_PAYLOAD(r))); } return r; } -export void leb128_encode(unsigned n, unsigned char *buf) { - while (true) { - buf[0] = (unsigned char)n; // get low bits - if (n >>= 7) { - // more bytes to come, set high bit and continue - buf[0] |= 1<<7; - buf++; - } else { - // we are done. high bit should be cleared anyway - return; - } - } -} - -export void sleb128_encode(signed n, unsigned char *buf) { - while (true) { - *buf = n & 0x7F; // get low bits - if (n >= -64 && n < 64) { - // last byte written, high bit is clear - return; - } else { - // more bytes to come, set high bit and continue - *buf++ |= 0x80; - n >>= 7; - } - } -} diff --git a/rts/buf.c b/rts/buf.c new file mode 100644 index 00000000000..4f4c009c2fa --- /dev/null +++ b/rts/buf.c @@ -0,0 +1,17 @@ +#include "rts.h" +#include "buf.h" + +// See comments in buf.h + +uint8_t read_byte(buf *buf) { + if (buf->p >= buf->e) (idl_trap()); + return ((buf->p)++)[0]; +} + +uint32_t read_word(buf *buf) { + if (buf->p + sizeof(uint8_t) > buf->e) (idl_trap()); + uint32_t r = ((uint32_t*)(buf->p))[0]; + buf->p += sizeof(uint32_t); + return r; +} + diff --git a/rts/buf.h b/rts/buf.h new file mode 100644 index 00000000000..c999681027e --- /dev/null +++ b/rts/buf.h @@ -0,0 +1,20 @@ +#ifndef BUF_H +#define BUF_H + +#include "rts.h" + +/* +An abstraction for a buffer with and end-pointer. + +This mirrors module ReadBuf in `compile.ml` +*/ + +typedef struct { + uint8_t *p; + uint8_t *e; +} buf; + +extern uint8_t read_byte(buf *buf); +extern uint32_t read_word(buf *buf); + +#endif /* BUF_H */ diff --git a/rts/idl.c b/rts/idl.c index 020597ef10b..3b065ce0aec 100644 --- a/rts/idl.c +++ b/rts/idl.c @@ -1,31 +1,18 @@ #include "rts.h" +#include "buf.h" -/* -An abstraction for a buffer with and end-pointer. - -This mirrors module Serialization.Buf in `compile.ml` -*/ - -typedef struct { - uint8_t *p; - uint8_t *e; -} buf; - -uint8_t read_byte(buf *buf) { - if (buf->p >= buf->e) (idl_trap()); - return ((buf->p)++)[0]; -} - -// Initially, we just want to be able to zoom past the type description -// TODO: Defensive programming -// (not going past the size of the message, trapping if leb128 does not fit in int) +/* Code to read (S)LEB128 to ints (traps if does not fit in return type) */ -uint32_t read_leb128(buf *buf) { +export uint32_t read_u32_of_leb128(buf *buf) { uint32_t r = 0; unsigned int s = 0; uint8_t b; do { b = read_byte(buf); + if (s > 0 && b == 0x00) { + // The high 7 bits is all zeros, this is not a shortest encoding + idl_trap(); + } if (s == 28 && !((b & (uint8_t)0xF0) == 0x00)) { // the 5th byte needs to be the last, and it must contribute at most 4 bits // else we have an int overflow @@ -37,10 +24,11 @@ uint32_t read_leb128(buf *buf) { return r; } -int32_t read_sleb128(buf *buf) { +export int32_t read_i32_of_sleb128(buf *buf) { uint32_t r = 0; unsigned int s = 0; uint8_t b; + bool last_sign_bit_set = 0; do { b = read_byte(buf); if (s == 28 && !((b & (uint8_t)0xF0) == 0x00 || (b & (uint8_t)0xF0) == 0x70)) { @@ -48,67 +36,136 @@ int32_t read_sleb128(buf *buf) { // else we have an int overflow idl_trap(); } + if (s > 0 && ((!last_sign_bit_set && b == 0x00) || (last_sign_bit_set && b == 0x8F))) { + // The high 8 bits are all zeros or ones, so this is not a shortest encoding + idl_trap(); + } + last_sign_bit_set = (b & (uint8_t)0x40); r += (b & (uint8_t)0x7f) << s; s += 7; } while (b & (uint8_t)0x80); // sign extend - if (s < 32 && (b & (uint8_t)0x40)) { - r |= (~(uint32_t)0 << s); + if (s < 32 && last_sign_bit_set) { + r |= ((~(uint32_t)0) << s); } return r; } -export void skip_idl_header(buf *buf) { - // Magic bytes - if (read_byte(buf) != 'D') idl_trap(); - if (read_byte(buf) != 'I') idl_trap(); - if (read_byte(buf) != 'D') idl_trap(); - if (read_byte(buf) != 'L') idl_trap(); - // Size of type list - for (int count = read_leb128(buf); count > 0; count --) { - int ty = read_sleb128(buf); - if (ty >= -17) { +/* + * IDL constants + */ +#define IDL_PRIM_null (-1) +#define IDL_PRIM_bool (-2) +#define IDL_PRIM_nat (-3) +#define IDL_PRIM_int (-4) +#define IDL_PRIM_nat8 (-5) +#define IDL_PRIM_nat16 (-6) +#define IDL_PRIM_nat32 (-7) +#define IDL_PRIM_nat64 (-8) +#define IDL_PRIM_int8 (-9) +#define IDL_PRIM_int16 (-10) +#define IDL_PRIM_int32 (-11) +#define IDL_PRIM_int64 (-12) +#define IDL_PRIM_float32 (-13) +#define IDL_PRIM_float64 (-14) +#define IDL_PRIM_text (-15) +#define IDL_PRIM_reserved (-16) +#define IDL_PRIM_empty (-17) + +#define IDL_PRIM_lowest (-17) + +#define IDL_CON_opt (-18) +#define IDL_CON_vec (-19) +#define IDL_CON_record (-20) +#define IDL_CON_variant (-21) +#define IDL_CON_func (-22) +#define IDL_CON_service (-23) + + +/* + * This function parses the IDL magic header and type description. It + * * traps if the type description is not well-formed. In particular, it traps if + * any index into the type description table is out of bounds, so that + * subsequent code can trust these values + * * returns a pointer to the first byte after the IDL header (via return) + * * allocates a type description table, and returns it + * (via pointer argument, for lack of multi-value returns in C) + * * returns the type index of the overall value + * (again via pointer argument, for lack of multi-value returns in C) + */ +export void parse_idl_header(buf *buf, uint8_t ***typtbl_out, int32_t *main_type_out) { + // Magic bytes (DIDL) + if (read_word(buf) != 0x4C444944) idl_trap(); + + // Create a table for the type description + int32_t n_types = read_u32_of_leb128(buf); + + // read_u32_of_leb128 returns an uint32_t, we want an int32_t here so that the + // comparisons below work, so let's make sure we did not wrap around in the + // conversion. + if (n_types < 0) { idl_trap(); } + + // Early sanity check + if (&buf->p[n_types] >= buf->e) { idl_trap(); } + + // Go through the table + uint8_t **typtbl = (uint8_t **)alloc(n_types * sizeof(uint8_t*)); + for (int i = 0; i < n_types; i++) { + typtbl[i] = buf->p; + int ty = read_i32_of_sleb128(buf); + if (ty >= IDL_PRIM_lowest) { idl_trap(); // illegal - } else if (ty == -18) { // opt - read_sleb128(buf); - } - else if (ty == -19) { // vec - read_sleb128(buf); - } else if (ty == -20) { // record - for (int n = read_leb128(buf); n > 0; n--) { - read_leb128(buf); - read_sleb128(buf); + } else if (ty == IDL_CON_opt) { + int32_t t = read_i32_of_sleb128(buf); + if (t < IDL_PRIM_lowest || t >= n_types) idl_trap(); + } else if (ty == IDL_CON_vec) { + int32_t t = read_i32_of_sleb128(buf); + if (t < IDL_PRIM_lowest || t >= n_types) idl_trap(); + } else if (ty == IDL_CON_record) { + for (int n = read_u32_of_leb128(buf); n > 0; n--) { + read_u32_of_leb128(buf); + int32_t t = read_i32_of_sleb128(buf); + if (t < IDL_PRIM_lowest || t >= n_types) idl_trap(); } - } else if (ty == -21) { // variant - for (int n = read_leb128(buf); n > 0; n--) { - read_leb128(buf); - read_sleb128(buf); + } else if (ty == IDL_CON_variant) { + for (int n = read_u32_of_leb128(buf); n > 0; n--) { + read_u32_of_leb128(buf); + int32_t t = read_i32_of_sleb128(buf); + if (t < IDL_PRIM_lowest || t >= n_types) idl_trap(); } - } else if (ty == -22) { // func + } else if (ty == IDL_CON_func) { // arg types - for (int n = read_leb128(buf); n > 0; n--) { - read_sleb128(buf); + for (int n = read_u32_of_leb128(buf); n > 0; n--) { + int32_t t = read_i32_of_sleb128(buf); + if (t < IDL_PRIM_lowest || t >= n_types) idl_trap(); } // ret types - for (int n = read_leb128(buf); n > 0; n--) { - read_sleb128(buf); + for (int n = read_u32_of_leb128(buf); n > 0; n--) { + int32_t t = read_i32_of_sleb128(buf); + if (t < IDL_PRIM_lowest || t >= n_types) idl_trap(); } // annotations - for (int n = read_leb128(buf); n > 0; n--) { + for (int n = read_u32_of_leb128(buf); n > 0; n--) { (buf->p)++; } - } else if (ty == -23) { // service - for (int n = read_leb128(buf); n > 0; n--) { + } else if (ty == IDL_CON_service) { + for (int n = read_u32_of_leb128(buf); n > 0; n--) { // name - unsigned int size = read_leb128(buf); + unsigned int size = read_u32_of_leb128(buf); (buf->p) += size; // type - read_sleb128(buf); + int32_t t = read_i32_of_sleb128(buf); + if (t < IDL_PRIM_lowest || t >= n_types) idl_trap(); } } else { // no support for future types yet idl_trap(); } } - read_sleb128(buf); // index + // Now read the main type + int32_t t = read_i32_of_sleb128(buf); + if (t < IDL_PRIM_lowest || t >= n_types) idl_trap(); + + *typtbl_out = typtbl; + *main_type_out = t; } diff --git a/rts/rts.c b/rts/rts.c index 7debe03ede7..154a0db5617 100644 --- a/rts/rts.c +++ b/rts/rts.c @@ -1,5 +1,13 @@ #include "rts.h" +char *alloc(size_t n) { + as_ptr r = alloc_bytes (2*sizeof(void*) + n); + FIELD(r, 0) = TAG_TEXT; + FIELD(r, 1) = n; + return (char *)&FIELD(r,2); +} + + export void as_memcpy(char *str1, const char *str2, size_t n) { for (size_t i = 0; i < n; i++) { str1[i] = str2[i]; @@ -29,3 +37,34 @@ as_ptr get_version() { return as_str_of_cstr(RTS_VERSION); } as_ptr (*version_getter)() = &get_version; export as_ptr version() { return (*version_getter)(); } + +/* (S)LEB128 Encoding of words */ + +export void leb128_encode(uint32_t n, unsigned char *buf) { + while (true) { + buf[0] = (unsigned char)n; // get low bits + if (n >>= 7) { + // more bytes to come, set high bit and continue + buf[0] |= 1<<7; + buf++; + } else { + // we are done. high bit should be cleared anyway + return; + } + } +} + +export void sleb128_encode(int32_t n, unsigned char *buf) { + while (true) { + *buf = n & 0x7F; // get low bits + if (n >= -64 && n < 64) { + // last byte written, high bit is clear + return; + } else { + // more bytes to come, set high bit and continue + *buf++ |= 0x80; + n >>= 7; + } + } +} + diff --git a/rts/rts.h b/rts/rts.h index 552363300b4..5c37d911678 100644 --- a/rts/rts.h +++ b/rts/rts.h @@ -1,3 +1,6 @@ +#ifndef RTS_H +#define RTS_H + #pragma GCC diagnostic ignored "-Wattributes" #pragma GCC diagnostic ignored "-Wincompatible-library-redeclaration" #define export __attribute__ ((visibility("default"))) @@ -54,6 +57,7 @@ So in order to allocate on the ActorScript heap from C, we import alloc_bytes from the Actorscript RTS: */ from_rts as_ptr alloc_bytes(size_t n); +char *alloc(size_t n); /* IDL code */ @@ -64,3 +68,4 @@ from_rts __attribute__ ((noreturn)) void bigint_trap(); /** Functions used in multiple modules of the RTS */ export void as_memcpy(char *str1, const char *str2, size_t n); +#endif /* RTS_H */ diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 9e19fc706fc..362b206d56b 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -572,7 +572,9 @@ module RTS = struct let system_imports env = E.add_func_import env "rts" "as_memcpy" [I32Type; I32Type; I32Type] []; E.add_func_import env "rts" "version" [] [I32Type]; - E.add_func_import env "rts" "skip_idl_header" [I32Type] []; + E.add_func_import env "rts" "parse_idl_header" [I32Type; I32Type; I32Type] []; + E.add_func_import env "rts" "read_u32_of_leb128" [I32Type] [I32Type]; + E.add_func_import env "rts" "read_i32_of_sleb128" [I32Type] [I32Type]; E.add_func_import env "rts" "bigint_of_word32" [I32Type] [I32Type]; E.add_func_import env "rts" "bigint_of_word32_signed" [I32Type] [I32Type]; E.add_func_import env "rts" "bigint_to_word32_wrap" [I32Type] [I32Type]; @@ -625,7 +627,7 @@ module RTS = struct }); let idl_trap_fi = E.add_fun env "idl_trap" ( Func.of_body env [] [] (fun env -> - E.trap_with env "idl function error" + E.trap_with env "IDL error: Unknown error" ) ) in E.add_export env (nr { @@ -1532,6 +1534,90 @@ module UnboxedSmallWord = struct end (* UnboxedSmallWord *) +module ReadBuf = struct + (* + Combinators to safely read from a dynamic buffer. + + We represent a buffer by a pointer to two words in memory (usually allocated + on the shadow stack): The first is a pointer to the current position of the buffer, + the second one a pointer to the end (to check out-of-bounds). + + Code that reads from this buffer will update the former, i.e. it is mutable. + + The format is compatible with C (pointer to a struct) and avoids the need for the + multi-value extension that we used before to return both parse result _and_ + updated pointer. + + All pointers here are unskewed! + + This module is mostly for serialization, but because there are bits of + serialization code in the BigNumType implementations, we put it here. + *) + + let get_ptr get_buf = + get_buf ^^ G.i (Load {ty = I32Type; align = 2; offset = 0l; sz = None}) + let get_end get_buf = + get_buf ^^ G.i (Load {ty = I32Type; align = 2; offset = Heap.word_size; sz = None}) + let set_ptr get_buf new_val = + get_buf ^^ new_val ^^ G.i (Store {ty = I32Type; align = 2; offset = 0l; sz = None}) + let set_end get_buf new_val = + get_buf ^^ new_val ^^ G.i (Store {ty = I32Type; align = 2; offset = Heap.word_size; sz = None}) + let set_size get_buf get_size = + set_end get_buf + (get_ptr get_buf ^^ get_size ^^ G.i (Binary (Wasm.Values.I32 I32Op.Add))) + + let alloc env f = Stack.with_words env "buf" 2l f + + let advance get_buf get_delta = + set_ptr get_buf (get_ptr get_buf ^^ get_delta ^^ G.i (Binary (Wasm.Values.I32 I32Op.Add))) + + let read_leb128 env get_buf = + get_buf ^^ E.call_import env "rts" "read_u32_of_leb128" + + let read_sleb128 env get_buf = + get_buf ^^ E.call_import env "rts" "read_i32_of_sleb128" + + let check_space env get_buf get_delta = + get_ptr get_buf ^^ get_delta ^^ G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ + get_end get_buf ^^ + G.i (Compare (Wasm.Values.I32 I64Op.LeU)) ^^ + E.else_trap_with env "IDL error: out of bounds read" + + let read_byte env get_buf = + check_space env get_buf (compile_unboxed_const 1l) ^^ + get_ptr get_buf ^^ + G.i (Load {ty = I32Type; align = 0; offset = 0l; sz = Some (Wasm.Memory.Pack8, Wasm.Memory.ZX)}) ^^ + advance get_buf (compile_unboxed_const 1l) + + let read_word16 env get_buf = + check_space env get_buf (compile_unboxed_const 2l) ^^ + get_ptr get_buf ^^ + G.i (Load {ty = I32Type; align = 0; offset = 0l; sz = Some (Wasm.Memory.Pack16, Wasm.Memory.ZX)}) ^^ + advance get_buf (compile_unboxed_const 2l) + + let read_word32 env get_buf = + check_space env get_buf (compile_unboxed_const 4l) ^^ + get_ptr get_buf ^^ + G.i (Load {ty = I32Type; align = 0; offset = 0l; sz = None}) ^^ + advance get_buf (compile_unboxed_const 4l) + + let read_word64 env get_buf = + check_space env get_buf (compile_unboxed_const 8l) ^^ + get_ptr get_buf ^^ + G.i (Load {ty = I64Type; align = 0; offset = 0l; sz = None}) ^^ + advance get_buf (compile_unboxed_const 8l) + + let read_blob env get_buf get_len = + check_space env get_buf get_len ^^ + (* Already has destination address on the stack *) + get_ptr get_buf ^^ + get_len ^^ + Heap.memcpy env ^^ + advance get_buf get_len + +end (* Buf *) + + type comparator = Lt | Le | Ge | Gt module type BigNumType = @@ -1566,14 +1652,12 @@ sig *) val compile_store_to_data_buf_signed : E.t -> G.t val compile_store_to_data_buf_unsigned : E.t -> G.t - (* given a data buffer on stack, consume bytes from it, + (* given a ReadBuf on stack, consume bytes from it, deserializing to a numeric object - and leave two words on stack: - - number of consumed bytes (i32, TOS) - - numeric object (vanilla) + and leave it on the stack (vanilla). + The boolean argument is true if the value to be read is signed. *) - val compile_load_from_data_buf_signed : E.t -> G.t - val compile_load_from_data_buf_unsigned : E.t -> G.t + val compile_load_from_data_buf : E.t -> bool -> G.t (* literals *) val compile_lit : E.t -> Big_int.big_int -> G.t @@ -1951,29 +2035,14 @@ module MakeCompact (Num : BigNumType) : BigNumType = struct Num.compile_abs env - let compile_load_from_data_buf_unsigned env = + let compile_load_from_data_buf env signed = let set_res, get_res = new_local env "res" in - let set_size, get_size = new_local env "size" in - Num.compile_load_from_data_buf_unsigned env ^^ - set_size ^^ set_res ^^ get_res ^^ - fits_in_vanilla env ^^ - begin G.if_ (ValBlockType (Some I32Type)) - (get_res ^^ Num.truncate_to_word32 env ^^ compress) - get_res - end ^^ - get_size - - let compile_load_from_data_buf_signed env = - let set_res, get_res = new_local env "res" in - let set_size, get_size = new_local env "size" in - Num.compile_load_from_data_buf_signed env ^^ - set_size ^^ set_res ^^ get_res ^^ - fits_in_vanilla env ^^ - begin G.if_ (ValBlockType (Some I32Type)) + Num.compile_load_from_data_buf env signed ^^ + set_res ^^ + get_res ^^ fits_in_vanilla env ^^ + G.if_ (ValBlockType (Some I32Type)) (get_res ^^ Num.truncate_to_word32 env ^^ compress) get_res - end ^^ - get_size let compile_encoding_size dynamics get_x = get_x ^^ G.if_ (ValBlockType (Some I32Type)) @@ -2132,18 +2201,9 @@ module BigNumLibtommath : BigNumType = struct get_n ^^ get_buf ^^ E.call_import env "rts" "bigint_sleb128_encode" ^^ get_n ^^ E.call_import env "rts" "bigint_sleb128_size" - let compile_load_from_data_buf_unsigned env = - E.call_import env "rts" "bigint_leb128_decode" ^^ - let (set_n, get_n) = new_local env "n" in - set_n ^^ - get_n ^^ - get_n ^^ E.call_import env "rts" "bigint_leb128_size" - let compile_load_from_data_buf_signed env = - E.call_import env "rts" "bigint_sleb128_decode" ^^ - let (set_n, get_n) = new_local env "n" in - set_n ^^ - get_n ^^ - get_n ^^ E.call_import env "rts" "bigint_sleb128_size" + let compile_load_from_data_buf env = function + | false -> E.call_import env "rts" "bigint_leb128_decode" + | true -> E.call_import env "rts" "bigint_sleb128_decode" let compile_lit env n = let limb_size = 31 in @@ -2486,8 +2546,7 @@ module Text = struct ) let unskewed_payload_offset = Int32.(add ptr_unskew (mul Heap.word_size header_size)) - let payload_ptr_unskewed = - compile_add_const unskewed_payload_offset + let payload_ptr_unskewed = compile_add_const unskewed_payload_offset (* String concatentation. Expects two strings on stack *) let concat env = Func.share_code2 env "concat" (("x", I32Type), ("y", I32Type)) [I32Type] (fun env get_x get_y -> @@ -2652,10 +2711,7 @@ module Text = struct (* We also use Text heap objects for byte arrays (really should rename Text to Bytes) *) - let dyn_alloc_scratch env = - compile_add_const (Int32.mul Heap.word_size header_size) ^^ - Heap.dyn_alloc_bytes env ^^ - payload_ptr_unskewed + let dyn_alloc_scratch env = alloc env ^^ payload_ptr_unskewed end (* Text *) @@ -2703,6 +2759,12 @@ module Arr = struct let (set_r, get_r) = new_local env "r" in set_len ^^ + (* Check size (should not be larger than half the memory space) *) + get_len ^^ + compile_unboxed_const Int32.(shift_left 1l (32-4-1)) ^^ + G.i (Compare (Wasm.Values.I32 I32Op.LtU)) ^^ + E.else_trap_with env "Array allocation too large" ^^ + (* Allocate *) get_len ^^ compile_add_const header_size ^^ @@ -3276,30 +3338,28 @@ module Serialization = struct *) module TM = Map.Make (struct type t = Type.typ let compare = compare end) + let to_idl_prim = let open Type in function + | Prim Null -> Some 1 + | Prim Bool -> Some 2 + | Prim Nat -> Some 3 + | Prim Int -> Some 4 + | Prim (Nat8|Word8) -> Some 5 + | Prim (Nat16|Word16) -> Some 6 + | Prim (Nat32|Word32) -> Some 7 + | Prim (Nat64|Word64) -> Some 8 + | Prim Int8 -> Some 9 + | Prim Int16 -> Some 10 + | Prim Int32 -> Some 11 + | Prim Int64 -> Some 12 + | Prim Float -> Some 14 + | Prim Text -> Some 15 + | Any -> Some 16 + | Non -> Some 17 + | _ -> None let type_desc t : string = let open Type in - let to_idl_prim = function - | Prim Null -> Some 1 - | Prim Bool -> Some 2 - | Prim Nat -> Some 3 - | Prim Int -> Some 4 - | Prim (Nat8|Word8) -> Some 5 - | Prim (Nat16|Word16) -> Some 6 - | Prim (Nat32|Word32) -> Some 7 - | Prim (Nat64|Word64) -> Some 8 - | Prim Int8 -> Some 9 - | Prim Int16 -> Some 10 - | Prim Int32 -> Some 11 - | Prim Int64 -> Some 12 - | Prim Float -> Some 14 - | Prim Text -> Some 15 - | Any -> Some 16 - | Non -> Some 17 - | _ -> None - in - (* Type traversal *) (* We do a first traversal to find out the indices of types *) let (typs, idx) = @@ -3645,167 +3705,201 @@ module Serialization = struct get_ref_buf ) - module Buf = struct - (* - Combinators to safely read from a dynamic buffer. - - We represent a buffer by a pointer to two words in memory (usually allocated - on the shadow stack): The first is a pointer to the current position of the buffer, - the second one a pointer to the end (to check out-of-bounds). - - Code that reads from this buffer will update the former, i.e. it is mutuable. - - The format is compatible with C (pointer to a struct) and avoids the need for the - multi-value extension that we used before to return both parse result _and_ - updated pointer. - - All pointers here are unskewed! - *) - - let get_ptr get_buf = - get_buf ^^ G.i (Load {ty = I32Type; align = 2; offset = 0l; sz = None}) - let _get_end get_buf = - get_buf ^^ G.i (Load {ty = I32Type; align = 2; offset = Heap.word_size; sz = None}) - let set_ptr get_buf new_val = - get_buf ^^ new_val ^^ G.i (Store {ty = I32Type; align = 2; offset = 0l; sz = None}) - let set_end get_buf new_val = - get_buf ^^ new_val ^^ G.i (Store {ty = I32Type; align = 2; offset = Heap.word_size; sz = None}) - let set_size get_buf get_size = - set_end get_buf - (get_ptr get_buf ^^ get_size ^^ G.i (Binary (Wasm.Values.I32 I32Op.Add))) - - let alloc env f = Stack.with_words env "buf" 2l f - - let advance get_buf get_delta = - set_ptr get_buf (get_ptr get_buf ^^ get_delta ^^ G.i (Binary (Wasm.Values.I32 I32Op.Add))) - - let read_byte get_buf = - get_ptr get_buf ^^ - G.i (Load {ty = I32Type; align = 0; offset = 0l; sz = Some (Wasm.Memory.Pack8, Wasm.Memory.ZX)}) ^^ - advance get_buf (compile_unboxed_const 1l) - - let read_word env get_buf = - (* See TODO (leb128 for i32) *) - get_ptr get_buf ^^ - BigNum.compile_load_from_data_buf_unsigned env ^^ - let (set_leb_len, get_leb_len) = new_local env "leb_len" in - set_leb_len ^^ - advance get_buf get_leb_len ^^ - BigNum.to_word32 env - - - end (* Buf *) - let rec deserialize_go env t = let open Type in let t = normalize t in let name = "@deserialize_go<" ^ typ_id t ^ ">" in - Func.share_code2 env name (("data_buffer", I32Type), ("ref_buffer", I32Type)) [I32Type] - (fun env get_data_buf get_ref_buf -> + Func.share_code4 env name + (("data_buffer", I32Type), + ("ref_buffer", I32Type), + ("typtbl", I32Type), + ("idltyp", I32Type) + ) [I32Type] + (fun env get_data_buf get_ref_buf get_typtbl get_idltyp -> let go env t = + let (set_idlty, get_idlty) = new_local env "idl_ty" in + set_idlty ^^ get_data_buf ^^ get_ref_buf ^^ + get_typtbl ^^ + get_idlty ^^ deserialize_go env t in + let check_prim_typ t = + get_idltyp ^^ + compile_eq_const (Int32.of_int (- (Lib.Option.value (to_idl_prim t)))) + in + + let assert_prim_typ () = + check_prim_typ t ^^ + E.else_trap_with env ("IDL error: unexpected IDL typ when parsing " ^ string_of_typ t) + in + + + (* checks that idltyp is positive, looks it up in the table, updates the typ_buf, + reads the type constructor index and traps if it is the wrong one. + typ_buf left in place to read the type constructor arguments *) + let with_composite_typ idl_tycon_id f = + (* make sure index is not negative *) + get_idltyp ^^ + compile_unboxed_const 0l ^^ G.i (Compare (Wasm.Values.I32 I32Op.GeS)) ^^ + E.else_trap_with env ("IDL error: expected composite typ when parsing " ^ string_of_typ t) ^^ + ReadBuf.alloc env (fun get_typ_buf -> + (* Update typ_buf *) + ReadBuf.set_ptr get_typ_buf ( + get_typtbl ^^ + get_idltyp ^^ compile_mul_const Heap.word_size ^^ + G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ + load_unskewed_ptr + ) ^^ + ReadBuf.set_end get_typ_buf (ReadBuf.get_end get_data_buf) ^^ + (* read sleb128 *) + ReadBuf.read_sleb128 env get_typ_buf ^^ + (* Check it is the expected value *) + compile_eq_const idl_tycon_id ^^ + E.else_trap_with env ("IDL error: wrong composite typ when parsing " ^ string_of_typ t) ^^ + (* to the work *) + f get_typ_buf + ) in + (* Now the actual deserialization *) begin match t with + (* Primitive types *) | Prim Nat -> - Buf.get_ptr get_data_buf ^^ - BigNum.compile_load_from_data_buf_unsigned env ^^ - let (set_leb_len, get_leb_len) = new_local env "leb_len" in - set_leb_len ^^ - Buf.advance get_data_buf get_leb_len + assert_prim_typ () ^^ + get_data_buf ^^ + BigNum.compile_load_from_data_buf env false | Prim Int -> - Buf.get_ptr get_data_buf ^^ - BigNum.compile_load_from_data_buf_signed env ^^ - let (set_leb_len, get_leb_len) = new_local env "leb_len" in - set_leb_len ^^ - Buf.advance get_data_buf get_leb_len + (* Subtyping with nat *) + check_prim_typ (Prim Nat) ^^ + G.if_ (ValBlockType (Some I32Type)) + begin + get_data_buf ^^ + BigNum.compile_load_from_data_buf env false + end + begin + assert_prim_typ () ^^ + get_data_buf ^^ + BigNum.compile_load_from_data_buf env true + end | Prim (Int64|Nat64|Word64) -> - Buf.get_ptr get_data_buf ^^ - G.i (Load {ty = I64Type; align = 2; offset = 0l; sz = None}) ^^ - BoxedWord64.box env ^^ - Buf.advance get_data_buf (compile_unboxed_const 8l) + assert_prim_typ () ^^ + ReadBuf.read_word64 env get_data_buf^^ + BoxedWord64.box env | Prim (Int32|Nat32|Word32) -> - Buf.get_ptr get_data_buf ^^ - G.i (Load {ty = I32Type; align = 0; offset = 0l; sz = None}) ^^ - BoxedSmallWord.box env ^^ - Buf.advance get_data_buf (compile_unboxed_const 4l) + assert_prim_typ () ^^ + ReadBuf.read_word32 env get_data_buf ^^ + BoxedSmallWord.box env | Prim (Int16|Nat16|Word16) -> - Buf.get_ptr get_data_buf ^^ - G.i (Load {ty = I32Type; align = 0; offset = 0l; sz = Some (Wasm.Memory.Pack16, Wasm.Memory.ZX)}) ^^ - UnboxedSmallWord.msb_adjust Word16 ^^ - Buf.advance get_data_buf (compile_unboxed_const 2l) + assert_prim_typ () ^^ + ReadBuf.read_word16 env get_data_buf ^^ + UnboxedSmallWord.msb_adjust Word16 | Prim (Int8|Nat8|Word8) -> - Buf.get_ptr get_data_buf ^^ - G.i (Load {ty = I32Type; align = 0; offset = 0l; sz = Some (Wasm.Memory.Pack8, Wasm.Memory.ZX)}) ^^ - UnboxedSmallWord.msb_adjust Word8 ^^ - Buf.advance get_data_buf (compile_unboxed_const 1l) + assert_prim_typ () ^^ + ReadBuf.read_byte env get_data_buf ^^ + UnboxedSmallWord.msb_adjust Word8 | Prim Bool -> - Buf.get_ptr get_data_buf ^^ - G.i (Load {ty = I32Type; align = 0; offset = 0l; sz = Some (Wasm.Memory.Pack8, Wasm.Memory.ZX)}) ^^ - Buf.advance get_data_buf (compile_unboxed_const 1l) + assert_prim_typ () ^^ + ReadBuf.read_byte env get_data_buf + | Prim Null -> + assert_prim_typ () ^^ + Opt.null + | Prim Text -> + assert_prim_typ () ^^ + let (set_len, get_len) = new_local env "len" in + let (set_x, get_x) = new_local env "x" in + ReadBuf.read_leb128 env get_data_buf ^^ set_len ^^ + + get_len ^^ Text.alloc env ^^ set_x ^^ + get_x ^^ Text.payload_ptr_unskewed ^^ + ReadBuf.read_blob env get_data_buf get_len ^^ + (* TODO: Check validty of utf8 *) + get_x + + (* Composite types *) | Tup ts -> - G.concat_map (fun t -> go env t) ts ^^ - Tuple.from_stack env (List.length ts) + with_composite_typ (-20l) (fun get_typ_buf -> + ReadBuf.read_leb128 env get_typ_buf ^^ G.i Drop ^^ + G.concat_map (fun t -> + ReadBuf.read_leb128 env get_typ_buf ^^ G.i Drop ^^ + ReadBuf.read_sleb128 env get_typ_buf ^^ + go env t + ) ts ^^ + Tuple.from_stack env (List.length ts) + ) | Obj (Object, fs) -> - Object.lit_raw env (List.map (fun (_h,f) -> - f.Type.lab, fun () -> go env f.typ - ) (sort_by_hash fs)) + with_composite_typ (-20l) (fun get_typ_buf -> + ReadBuf.read_leb128 env get_typ_buf ^^ G.i Drop ^^ + Object.lit_raw env (List.map (fun (_h,f) -> + f.Type.lab, fun () -> + ReadBuf.read_leb128 env get_typ_buf ^^ G.i Drop ^^ + ReadBuf.read_sleb128 env get_typ_buf ^^ + go env f.typ + ) (sort_by_hash fs)) + ) | Array t -> let (set_len, get_len) = new_local env "len" in let (set_x, get_x) = new_local env "x" in - - Buf.read_word env get_data_buf ^^ set_len ^^ - get_len ^^ Arr.alloc env ^^ set_x ^^ - get_len ^^ from_0_to_n env (fun get_i -> - get_x ^^ get_i ^^ Arr.idx env ^^ - go env t ^^ store_ptr - ) ^^ - get_x - | Prim Null -> Opt.null + let (set_idltyp, get_idltyp) = new_local env "idltyp" in + with_composite_typ (-19l) (fun get_typ_buf -> + ReadBuf.read_sleb128 env get_typ_buf ^^ set_idltyp ^^ + ReadBuf.read_leb128 env get_data_buf ^^ set_len ^^ + get_len ^^ Arr.alloc env ^^ set_x ^^ + get_len ^^ from_0_to_n env (fun get_i -> + get_x ^^ get_i ^^ Arr.idx env ^^ + get_idltyp ^^ go env t ^^ + store_ptr + ) ^^ + get_x + ) | Opt t -> - Buf.read_byte get_data_buf ^^ - compile_eq_const 0l ^^ - G.if_ (ValBlockType (Some I32Type)) - ( Opt.null ) - ( Opt.inject env (go env t) ) + (* TODO: Subtyping with primitive null *) + let (set_idltyp, get_idltyp) = new_local env "idltyp" in + with_composite_typ (-18l) (fun get_typ_buf -> + ReadBuf.read_sleb128 env get_typ_buf ^^ set_idltyp ^^ + ReadBuf.read_byte env get_data_buf ^^ + let (set_b, get_b) = new_local env "b" in + set_b ^^ + get_b ^^ + compile_eq_const 0l ^^ + G.if_ (ValBlockType (Some I32Type)) + begin + Opt.null + end begin + get_b ^^ compile_eq_const 1l ^^ + E.else_trap_with env "IDL error: opt tag not 0 or 1 " ^^ + Opt.inject env (get_idltyp ^^ go env t) + end + ) | Variant vs -> - let (set_tag, get_tag) = new_local env "tag" in - Buf.read_word env get_data_buf ^^ set_tag ^^ - List.fold_right (fun (i, {lab = l; typ = t}) continue -> - get_tag ^^ - compile_eq_const (Int32.of_int i) ^^ - G.if_ (ValBlockType (Some I32Type)) - ( Variant.inject env l (go env t) ) - continue - ) - ( List.mapi (fun i (_h, f) -> (i,f)) (sort_by_hash vs) ) - ( E.trap_with env "deserialize_go: unexpected variant tag" ) - | Prim Text -> - let (set_len, get_len) = new_local env "len" in - let (set_x, get_x) = new_local env "x" in - Buf.read_word env get_data_buf ^^ set_len ^^ + with_composite_typ (-21l) (fun get_typ_buf -> + ReadBuf.read_leb128 env get_typ_buf ^^ G.i Drop ^^ - get_len ^^ Text.alloc env ^^ set_x ^^ + let (set_tag, get_tag) = new_local env "tag" in + ReadBuf.read_leb128 env get_data_buf ^^ set_tag ^^ - get_x ^^ Text.payload_ptr_unskewed ^^ - Buf.get_ptr get_data_buf ^^ - get_len ^^ - Heap.memcpy env ^^ + let (set_idltyp, get_idltyp) = new_local env "idltyp" in + List.fold_right (fun (i, {lab = l; typ = t}) continue -> + (* type desc for this variant *) + ReadBuf.read_leb128 env get_typ_buf ^^ G.i Drop ^^ + ReadBuf.read_sleb128 env get_typ_buf ^^ set_idltyp ^^ - Buf.advance get_data_buf get_len ^^ - - get_x + get_tag ^^ + compile_eq_const (Int32.of_int i) ^^ + G.if_ (ValBlockType (Some I32Type)) + ( Variant.inject env l (get_idltyp ^^ go env t) ) + continue + ) + ( List.mapi (fun i (_h, f) -> (i,f)) (sort_by_hash vs) ) + ( E.trap_with env "IDL error: unexpected variant tag" ) + ) | (Func _ | Obj (Actor, _)) -> - Buf.get_ptr get_ref_buf ^^ - load_unskewed_ptr ^^ - Dfinity.box_reference env ^^ - Buf.advance get_ref_buf (compile_unboxed_const Heap.word_size) + ReadBuf.read_word32 env get_ref_buf ^^ + Dfinity.box_reference env | Non -> - E.trap_with env "deserializing value of type None" + E.trap_with env "IDL error: deserializing value of type None" | _ -> todo_trap env "deserialize" (Arrange_ir.typ t) end ) @@ -3958,13 +4052,7 @@ module Serialization = struct Dfinity.system_call env "data_length" ^^ set_data_size ^^ - get_data_size ^^ - compile_add_const 3l ^^ - compile_divU_const Heap.word_size ^^ - Arr.alloc env ^^ - compile_add_const Arr.header_size ^^ - compile_add_const ptr_unskew ^^ - set_data_start ^^ + get_data_size ^^ Text.dyn_alloc_scratch env ^^ set_data_start ^^ (* Copy data *) get_data_start ^^ @@ -3973,17 +4061,28 @@ module Serialization = struct compile_unboxed_const 0l ^^ Dfinity.system_call env "data_internalize" ^^ + (* Allocate space for out parameters of parse_idl_header *) + Stack.with_words env "get_typtbl_ptr" 1l (fun get_typtbl_ptr -> + Stack.with_words env "get_maintyp_ptr" 1l (fun get_maintyp_ptr -> + + (* Set up read buffers *) - Buf.alloc env (fun get_data_buf -> Buf.alloc env (fun get_ref_buf -> - Buf.set_ptr get_data_buf get_data_start ^^ - Buf.set_size get_data_buf get_data_size ^^ - Buf.set_ptr get_ref_buf (get_refs_start ^^ compile_add_const Heap.word_size) ^^ - Buf.set_size get_ref_buf (get_refs_size ^^ compile_sub_const 1l ^^ compile_mul_const Heap.word_size) ^^ - - (* Go! *) - get_data_buf ^^ E.call_import env "rts" "skip_idl_header" ^^ - get_data_buf ^^ get_ref_buf ^^ deserialize_go env t - )) + ReadBuf.alloc env (fun get_data_buf -> ReadBuf.alloc env (fun get_ref_buf -> + + ReadBuf.set_ptr get_data_buf get_data_start ^^ + ReadBuf.set_size get_data_buf get_data_size ^^ + ReadBuf.set_ptr get_ref_buf (get_refs_start ^^ compile_add_const Heap.word_size) ^^ + ReadBuf.set_size get_ref_buf (get_refs_size ^^ compile_sub_const 1l ^^ compile_mul_const Heap.word_size) ^^ + + (* Go! *) + get_data_buf ^^ get_typtbl_ptr ^^ get_maintyp_ptr ^^ + E.call_import env "rts" "parse_idl_header" ^^ + + get_data_buf ^^ get_ref_buf ^^ + get_typtbl_ptr ^^ load_unskewed_ptr ^^ + get_maintyp_ptr ^^ load_unskewed_ptr ^^ + deserialize_go env t + )))) ) let dfinity_type t = From 567c86b35fd362713e1aba43eafdec8fa53d0993 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 15 Aug 2019 22:37:35 +0200 Subject: [PATCH 0351/1176] LEB128 code: s/0x8F/0x7F/ (#621) --- rts/bigint.c | 2 +- rts/idl.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rts/bigint.c b/rts/bigint.c index 678c0ba19c8..4fc9bc4f28b 100644 --- a/rts/bigint.c +++ b/rts/bigint.c @@ -369,7 +369,7 @@ export as_ptr bigint_sleb128_decode(buf *buf) { bool last_sign_bit_set = 0; do { b = read_byte(buf); - if (s > 0 && ((!last_sign_bit_set && b == 0x00) || (last_sign_bit_set && b == 0x8F))) { + if (s > 0 && ((!last_sign_bit_set && b == 0x00) || (last_sign_bit_set && b == 0x7F))) { // The high 8 bits are all zeros or ones, so this is not a shortest encoding idl_trap(); } diff --git a/rts/idl.c b/rts/idl.c index 3b065ce0aec..de8ba01f1e6 100644 --- a/rts/idl.c +++ b/rts/idl.c @@ -36,7 +36,7 @@ export int32_t read_i32_of_sleb128(buf *buf) { // else we have an int overflow idl_trap(); } - if (s > 0 && ((!last_sign_bit_set && b == 0x00) || (last_sign_bit_set && b == 0x8F))) { + if (s > 0 && ((!last_sign_bit_set && b == 0x00) || (last_sign_bit_set && b == 0x7F))) { // The high 8 bits are all zeros or ones, so this is not a shortest encoding idl_trap(); } From c21ee61123eec0010c7d71b232443db31352f518 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Sat, 17 Aug 2019 01:27:55 +0200 Subject: [PATCH 0352/1176] Random checking complements (#623) * implement complement operator (unary) * refactor AST as a GADT * add TODOs --- test/random/Main.hs | 353 +++++++++++++++++++++----------------------- 1 file changed, 165 insertions(+), 188 deletions(-) diff --git a/test/random/Main.hs b/test/random/Main.hs index 606c82d15d0..44017433392 100644 --- a/test/random/Main.hs +++ b/test/random/Main.hs @@ -183,90 +183,65 @@ instance Arbitrary (Neuralgic Natural) where arbitrary = (\n -> if n >= 0 then pure (fromIntegral n) else Nothing) `guardedFrom` [Around0, AroundPos 30, AroundPos 63, LargePos] -instance Arbitrary (Neuralgic Nat8) where - arbitrary = fmap NatN <$> trapNat 8 `guardedFrom` [Around0, AroundPos 3, AroundPos 5, AroundPos 8] - -instance Arbitrary (Neuralgic Nat16) where - arbitrary = fmap NatN <$> trapNat 16 `guardedFrom` [Around0, AroundPos 3, AroundPos 5, AroundPos 8, AroundPos 13, AroundPos 16] - -instance Arbitrary (Neuralgic Nat32) where - arbitrary = fmap NatN <$> trapNat 32 `guardedFrom` [Around0, AroundPos 8, AroundPos 13, AroundPos 16, AroundPos 23, AroundPos 32] - -instance Arbitrary (Neuralgic Nat64) where - arbitrary = fmap NatN <$> trapNat 64 `guardedFrom` [Around0, AroundPos 8, AroundPos 13, AroundPos 23, AroundPos 31, AroundPos 47, AroundPos 64] - - - -instance Arbitrary (Neuralgic Int8) where - arbitrary = fmap IntN <$> trapInt 8 `guardedFrom` [Around0, AroundNeg 3, AroundNeg 5, AroundNeg 7, AroundPos 3, AroundPos 5, AroundPos 7] - -instance Arbitrary (Neuralgic Int16) where - arbitrary = fmap IntN <$> trapInt 16 `guardedFrom` [Around0, AroundNeg 3, AroundNeg 7, AroundNeg 10, AroundNeg 15, AroundPos 3, AroundPos 8, AroundPos 10, AroundPos 15] - -instance Arbitrary (Neuralgic Int32) where - arbitrary = fmap IntN <$> trapInt 32 `guardedFrom` [Around0, AroundNeg 3, AroundNeg 17, AroundNeg 27, AroundNeg 31, AroundPos 3, AroundPos 18, AroundPos 25, AroundPos 31] - -instance Arbitrary (Neuralgic Int64) where - arbitrary = fmap IntN <$> trapInt 64 `guardedFrom` [Around0, AroundNeg 9, AroundNeg 27, AroundNeg 51, AroundNeg 63, AroundPos 10, AroundPos 28, AroundPos 55, AroundPos 63] - - - -instance Arbitrary (Neuralgic Word8) where - arbitrary = fmap WordN <$> trapWord 8 `guardedFrom` [Around0, AroundNeg 3, AroundNeg 5, AroundNeg 8, AroundPos 3, AroundPos 5, AroundPos 8] - -instance Arbitrary (Neuralgic Word16) where - arbitrary = fmap WordN <$> trapWord 16 `guardedFrom` [Around0, AroundNeg 3, AroundNeg 12, AroundNeg 16, AroundPos 6, AroundPos 13, AroundPos 16] - -instance Arbitrary (Neuralgic Word32) where - arbitrary = fmap WordN <$> trapWord 32 `guardedFrom` [Around0, AroundNeg 3, AroundNeg 12, AroundNeg 23, AroundNeg 32, AroundPos 6, AroundPos 15, AroundPos 26, AroundPos 32] - -instance Arbitrary (Neuralgic Word64) where - arbitrary = fmap WordN <$> trapWord 64 `guardedFrom` [Around0, AroundNeg 3, AroundNeg 11, AroundNeg 21, AroundNeg 31, AroundNeg 42, AroundNeg 64, AroundPos 6, AroundPos 14, AroundPos 27, AroundPos 43, AroundPos 57, AroundPos 64] - - -data ActorScriptTerm a - = About a - | Pos (ActorScriptTerm a) - | Neg (ActorScriptTerm a) - | Abs (ActorScriptTerm a) - | ActorScriptTerm a `Add` ActorScriptTerm a - | ActorScriptTerm a `Sub` ActorScriptTerm a - | ActorScriptTerm a `Mul` ActorScriptTerm a - | ActorScriptTerm a `Div` ActorScriptTerm a - | ActorScriptTerm a `Mod` ActorScriptTerm a - | ActorScriptTerm a `Pow` ActorScriptTerm a - | ActorScriptTerm a `Or` ActorScriptTerm a - | ActorScriptTerm a `And` ActorScriptTerm a - | ActorScriptTerm a `Xor` ActorScriptTerm a - | ActorScriptTerm a `RotL` ActorScriptTerm a - | ActorScriptTerm a `RotR` ActorScriptTerm a - | ActorScriptTerm a `ShiftL` ActorScriptTerm a - | ActorScriptTerm a `ShiftR` ActorScriptTerm a - | ActorScriptTerm a `ShiftRSigned` ActorScriptTerm a - | PopCnt (ActorScriptTerm a) - | Clz (ActorScriptTerm a) - | Ctz (ActorScriptTerm a) - | Five - | ConvertNatural (ActorScriptTerm (Neuralgic Natural)) - | forall n . KnownNat n => ConvertNat (ActorScriptTerm (Neuralgic (BitLimited n Natural))) - | forall n . KnownNat n => ConvertInt (ActorScriptTerm (Neuralgic (BitLimited n Integer))) - | forall n . WordLike n => ConvertWord (ActorScriptTerm (Neuralgic (BitLimited n Word))) - | Rel (ActorScriptTyped Bool) - | IfThenElse (ActorScriptTerm a) (ActorScriptTerm a) (ActorScriptTyped Bool) -- cond is last! - -deriving instance Show a => Show (ActorScriptTerm a) - - -data ActorScriptTyped :: * -> * where +instance KnownNat n => Arbitrary (Neuralgic (BitLimited n Natural)) where + arbitrary = fmap NatN <$> trapNat bits `guardedFrom` menu bits + where bits = natVal (Proxy @n) + menu 8 = [Around0, AroundPos 3, AroundPos 5, AroundPos 8] + menu 16 = [Around0, AroundPos 3, AroundPos 5, AroundPos 8, AroundPos 13, AroundPos 16] + menu 32 = [Around0, AroundPos 8, AroundPos 13, AroundPos 16, AroundPos 23, AroundPos 32] + menu 64 = [Around0, AroundPos 8, AroundPos 13, AroundPos 23, AroundPos 31, AroundPos 47, AroundPos 64] + + +instance KnownNat n => Arbitrary (Neuralgic (BitLimited n Integer)) where + arbitrary = fmap IntN <$> trapInt bits `guardedFrom` menu bits + where bits = natVal (Proxy @n) + menu 8 = [Around0, AroundNeg 3, AroundNeg 5, AroundNeg 7, AroundPos 3, AroundPos 5, AroundPos 7] + menu 16 = [Around0, AroundNeg 3, AroundNeg 7, AroundNeg 10, AroundNeg 15, AroundPos 3, AroundPos 8, AroundPos 10, AroundPos 15] + menu 32 = [Around0, AroundNeg 3, AroundNeg 17, AroundNeg 27, AroundNeg 31, AroundPos 3, AroundPos 18, AroundPos 25, AroundPos 31] + menu 64 = [Around0, AroundNeg 9, AroundNeg 27, AroundNeg 51, AroundNeg 63, AroundPos 10, AroundPos 28, AroundPos 55, AroundPos 63] + + +instance KnownNat n => Arbitrary (Neuralgic (BitLimited n Word)) where + arbitrary = fmap WordN <$> trapWord bits `guardedFrom` menu bits + where bits = natVal (Proxy @n) + menu 8 = [Around0, AroundNeg 3, AroundNeg 5, AroundNeg 8, AroundPos 3, AroundPos 5, AroundPos 8] + menu 16 = [Around0, AroundNeg 3, AroundNeg 12, AroundNeg 16, AroundPos 6, AroundPos 13, AroundPos 16] + menu 32 = [Around0, AroundNeg 3, AroundNeg 12, AroundNeg 23, AroundNeg 32, AroundPos 6, AroundPos 15, AroundPos 26, AroundPos 32] + menu 64 = [Around0, AroundNeg 3, AroundNeg 11, AroundNeg 21, AroundNeg 31, AroundNeg 42, AroundNeg 64, AroundPos 6, AroundPos 14, AroundPos 27, AroundPos 43, AroundPos 57, AroundPos 64] + + +data ASTerm :: * -> * where + -- Comparisons NotEqual, Equals, GreaterEqual, Greater, LessEqual, Less - :: (Show (Neuralgic a), Annot a, Literal a, Evaluatable a) => ActorScriptTerm (Neuralgic a) -> ActorScriptTerm (Neuralgic a) -> ActorScriptTyped Bool + :: (Annot a, Literal a, Evaluatable a) => ASTerm a -> ASTerm a -> ASTerm Bool + -- Short-circuit ShortAnd, ShortOr - :: ActorScriptTyped Bool -> ActorScriptTyped Bool -> ActorScriptTyped Bool - Not :: ActorScriptTyped Bool -> ActorScriptTyped Bool - Bool :: Bool -> ActorScriptTyped Bool -deriving instance Show (ActorScriptTyped t) - -subTerm :: Arbitrary (ActorScriptTerm t) => Bool -> Int -> [(Int, Gen (ActorScriptTerm t))] + :: ASTerm Bool -> ASTerm Bool -> ASTerm Bool + -- Boolean + Not :: ASTerm Bool -> ASTerm Bool + Bool :: Bool -> ASTerm Bool + -- Bitwise + Complement :: ASTerm (BitLimited n Word) -> ASTerm (BitLimited n Word) + Or, And, Xor, RotL, RotR, ShiftL, ShiftR, ShiftRSigned + :: ASTerm (BitLimited n Word) -> ASTerm (BitLimited n Word) -> ASTerm (BitLimited n Word) + PopCnt, Clz, Ctz :: ASTerm (BitLimited n Word) -> ASTerm (BitLimited n Word) + -- Arithmetic + Pos, Neg, Abs :: ASTerm a -> ASTerm a + Add, Sub, Mul, Div, Mod, Pow :: ASTerm a -> ASTerm a -> ASTerm a + -- Numeric + Neuralgic :: Neuralgic a -> ASTerm a + Five :: ASTerm a + -- Conditional + IfThenElse :: ASTerm a -> ASTerm a -> ASTerm Bool -> ASTerm a + -- Conversion + ConvertNatural :: ASTerm Natural -> ASTerm Integer + ConvertNat :: KnownNat n => ASTerm (BitLimited n Natural) -> ASTerm Integer + ConvertInt :: KnownNat n => ASTerm (BitLimited n Integer) -> ASTerm Integer + ConvertWord :: WordLike n => ASTerm (BitLimited n Word) -> ASTerm Integer + +deriving instance Show (ASTerm t) + +subTerm :: Arbitrary (ASTerm t) => Bool -> Int -> [(Int, Gen (ASTerm t))] subTerm fullPow n = [ (1, resize (n `div` 5) $ Pow <$> arbitrary <*> arbitrary) | fullPow] ++ [ (n, resize (n `div` 3) $ Add <$> arbitrary <*> arbitrary) @@ -277,15 +252,15 @@ subTerm fullPow n = , (n, resize (n `div` 4) $ IfThenElse <$> arbitrary <*> arbitrary <*> arbitrary) ] -subTermPow :: Arbitrary (ActorScriptTerm t) => (ActorScriptTerm t -> ActorScriptTerm t) -> Int -> [(Int, Gen (ActorScriptTerm t))] +subTermPow :: Arbitrary (ASTerm t) => (ASTerm t -> ASTerm t) -> Int -> [(Int, Gen (ASTerm t))] subTermPow mod n = (n, resize (n `div` 5) $ Pow <$> arbitrary <*> (mod <$> arbitrary)) : subTerm False n -subTermPow5 :: Arbitrary (ActorScriptTerm (Neuralgic t)) - => Int -> [(Int, Gen (ActorScriptTerm (Neuralgic t)))] +subTermPow5 :: Arbitrary (ASTerm t) + => Int -> [(Int, Gen (ASTerm t))] subTermPow5 n = (n, resize (n `div` 5) $ Pow <$> arbitrary - <*> (About <$> elements [ Around0 + <*> (Neuralgic <$> elements [ Around0 , Around0 `Offset` OneMore , AroundPos 1 , AroundPos 1 `Offset` OneMore @@ -293,7 +268,7 @@ subTermPow5 n = (n, resize (n `div` 5) ])) : subTerm False n -bitwiseTerm :: Arbitrary (ActorScriptTerm t) => Int -> [(Int, Gen (ActorScriptTerm t))] +bitwiseTerm :: WordLike n => Arbitrary (ASTerm (BitLimited n Word)) => Int -> [(Int, Gen (ASTerm (BitLimited n Word)))] bitwiseTerm n = [ (n `div` 5, resize (n `div` 3) $ Or <$> arbitrary <*> arbitrary) , (n `div` 5, resize (n `div` 3) $ And <$> arbitrary <*> arbitrary) @@ -306,57 +281,67 @@ bitwiseTerm n = , (n `div` 5, PopCnt <$> arbitrary) , (n `div` 5, Clz <$> arbitrary) , (n `div` 5, Ctz <$> arbitrary) + , (n `div` 5, Complement <$> arbitrary) ] --- generate reasonably formed trees from subterms +-- generate reasonably formed trees from smaller subterms -- -reasonablyShaped :: Arbitrary a - => (Int -> [(Int, Gen (ActorScriptTerm a))]) - -> Gen (ActorScriptTerm a) +reasonablyShaped :: (Arbitrary (Neuralgic a), Annot a, Evaluatable a, Literal a) + => (Int -> [(Int, Gen (ASTerm a))]) + -> Gen (ASTerm a) reasonablyShaped sub = sized $ \(succ -> n) -> frequency $ - (30 `div` n, About <$> arbitrary) + (30 `div` n, Neuralgic <$> arbitrary) : if n > 1 then sub n else [] -instance Arbitrary (ActorScriptTerm (Neuralgic Nat8)) where +instance Arbitrary (ASTerm Nat8) where arbitrary = reasonablyShaped $ subTerm True -instance Arbitrary (ActorScriptTerm (Neuralgic Nat16)) where - arbitrary = reasonablyShaped $ subTermPow (`Mod` Five) +reasonableNatTerm :: (KnownNat n, Arbitrary (ASTerm (BitLimited n Natural))) => Gen (ASTerm (BitLimited n Natural)) +reasonableNatTerm = reasonablyShaped $ subTermPow (`Mod` Five) -instance Arbitrary (ActorScriptTerm (Neuralgic Nat32)) where - arbitrary = reasonablyShaped $ subTermPow (`Mod` Five) +instance Arbitrary (ASTerm Nat16) where + arbitrary = reasonableNatTerm -instance Arbitrary (ActorScriptTerm (Neuralgic Nat64)) where - arbitrary = reasonablyShaped $ subTermPow (`Mod` Five) +instance Arbitrary (ASTerm Nat32) where + arbitrary = reasonableNatTerm +instance Arbitrary (ASTerm Nat64) where + arbitrary = reasonableNatTerm -instance Arbitrary (ActorScriptTerm (Neuralgic Int8)) where + +instance Arbitrary (ASTerm Int8) where arbitrary = reasonablyShaped $ subTerm True -instance Arbitrary (ActorScriptTerm (Neuralgic Int16)) where - arbitrary = reasonablyShaped subTermPow5 +reasonableIntTerm :: (KnownNat n, Arbitrary (ASTerm (BitLimited n Integer))) => Gen (ASTerm (BitLimited n Integer)) +reasonableIntTerm = reasonablyShaped subTermPow5 + +instance Arbitrary (ASTerm Int16) where + arbitrary = reasonableIntTerm -instance Arbitrary (ActorScriptTerm (Neuralgic Int32)) where - arbitrary = reasonablyShaped subTermPow5 +instance Arbitrary (ASTerm Int32) where + arbitrary = reasonableIntTerm -instance Arbitrary (ActorScriptTerm (Neuralgic Int64)) where - arbitrary = reasonablyShaped subTermPow5 +instance Arbitrary (ASTerm Int64) where + arbitrary = reasonableIntTerm -instance Arbitrary (ActorScriptTerm (Neuralgic Word8)) where +instance Arbitrary (ASTerm Word8) where arbitrary = reasonablyShaped $ (<>) <$> subTerm True <*> bitwiseTerm -instance Arbitrary (ActorScriptTerm (Neuralgic Word16)) where - arbitrary = reasonablyShaped $ (<>) <$> subTermPow (`Mod` Five) <*> bitwiseTerm +reasonableWordTerm :: (WordLike n, Arbitrary (ASTerm (BitLimited n Word))) => Gen (ASTerm (BitLimited n Word)) +reasonableWordTerm = reasonablyShaped $ (<>) <$> subTermPow (`Mod` Five) <*> bitwiseTerm -instance Arbitrary (ActorScriptTerm (Neuralgic Word32)) where - arbitrary = reasonablyShaped $ (<>) <$> subTermPow (`Mod` Five) <*> bitwiseTerm +instance Arbitrary (ASTerm Word16) where + arbitrary = reasonableWordTerm -instance Arbitrary (ActorScriptTerm (Neuralgic Word64)) where - arbitrary = reasonablyShaped $ (<>) <$> subTermPow (`Mod` Five) <*> bitwiseTerm +instance Arbitrary (ASTerm Word32) where + arbitrary = reasonableWordTerm +instance Arbitrary (ASTerm Word64) where + arbitrary = reasonableWordTerm -instance Arbitrary (ActorScriptTyped Bool) where + +instance Arbitrary (ASTerm Bool) where arbitrary = sized $ \(succ -> n) -> -- TODO: use frequency? oneof $ (Bool <$> arbitrary) : if n <= 1 then [] else [ resize (n `div` 3) $ elements [NotEqual @Integer, Equals, GreaterEqual, Greater, LessEqual, Less] <*> arbitrary <*> arbitrary @@ -364,28 +349,27 @@ instance Arbitrary (ActorScriptTyped Bool) where , resize (n `div` 2) $ Not <$> arbitrary ] - -instance Arbitrary (ActorScriptTerm (Neuralgic Natural)) where +instance Arbitrary (ASTerm Natural) where arbitrary = reasonablyShaped $ subTermPow (`Mod` Five) -instance Arbitrary (ActorScriptTerm (Neuralgic Integer)) where +instance Arbitrary (ASTerm Integer) where arbitrary = reasonablyShaped $ \n -> [ (n, resize (n `div` 2) $ Pos <$> arbitrary) , (n, resize (n `div` 2) $ Neg <$> arbitrary) , (n, resize (n `div` 2) $ Abs <$> arbitrary) , (n, ConvertNatural <$> arbitrary) - , (n `div` 2, ConvertNat <$> (arbitrary @(ActorScriptTerm (Neuralgic Nat8)))) - , (n `div` 2, ConvertNat <$> (arbitrary @(ActorScriptTerm (Neuralgic Nat16)))) - , (n `div` 2, ConvertNat <$> (arbitrary @(ActorScriptTerm (Neuralgic Nat32)))) - , (n `div` 2, ConvertNat <$> (arbitrary @(ActorScriptTerm (Neuralgic Nat64)))) - , (n `div` 3, ConvertWord <$> (arbitrary @(ActorScriptTerm (Neuralgic Word8)))) - , (n `div` 3, ConvertWord <$> (arbitrary @(ActorScriptTerm (Neuralgic Word16)))) - , (n `div` 3, ConvertWord <$> (arbitrary @(ActorScriptTerm (Neuralgic Word32)))) - , (n `div` 3, ConvertWord <$> (arbitrary @(ActorScriptTerm (Neuralgic Word64)))) - , (n `div` 3, ConvertInt <$> (arbitrary @(ActorScriptTerm (Neuralgic Int8)))) - , (n `div` 3, ConvertInt <$> (arbitrary @(ActorScriptTerm (Neuralgic Int16)))) - , (n `div` 3, ConvertInt <$> (arbitrary @(ActorScriptTerm (Neuralgic Int32)))) - , (n `div` 3, ConvertInt <$> (arbitrary @(ActorScriptTerm (Neuralgic Int64)))) + , (n `div` 2, ConvertNat <$> (arbitrary @(ASTerm Nat8))) + , (n `div` 2, ConvertNat <$> (arbitrary @(ASTerm Nat16))) + , (n `div` 2, ConvertNat <$> (arbitrary @(ASTerm Nat32))) + , (n `div` 2, ConvertNat <$> (arbitrary @(ASTerm Nat64))) + , (n `div` 3, ConvertWord <$> (arbitrary @(ASTerm Word8))) + , (n `div` 3, ConvertWord <$> (arbitrary @(ASTerm Word16))) + , (n `div` 3, ConvertWord <$> (arbitrary @(ASTerm Word32))) + , (n `div` 3, ConvertWord <$> (arbitrary @(ASTerm Word64))) + , (n `div` 3, ConvertInt <$> (arbitrary @(ASTerm Int8))) + , (n `div` 3, ConvertInt <$> (arbitrary @(ASTerm Int16))) + , (n `div` 3, ConvertInt <$> (arbitrary @(ASTerm Int32))) + , (n `div` 3, ConvertInt <$> (arbitrary @(ASTerm Int64))) ] <> subTermPow ((`Mod` Five) . Abs) n instance Num a => Num (Maybe a) where @@ -408,12 +392,6 @@ instance (Enum (Maybe a), Eq a, Integral a) => Integral (Maybe a) where _ -> (Nothing, Nothing) -{- -instance (Eq a, Fractional a) => Fractional (Maybe a) where - _ / Just 0 = Nothing - a / b = liftA2 (/) a b --} - evalO TwoLess = \n -> n - 2 evalO OneLess = \n -> n - 1 evalO OneMore = (+1) @@ -458,8 +436,8 @@ instance KnownNat n => Restricted (BitLimited n Word) where then noExponentRestriction else defaultExponentRestriction -class Integral a => Evaluatable a where - evaluate :: ActorScriptTerm (Neuralgic a) -> Maybe a +class Ord a => Evaluatable a where + evaluate :: ASTerm a -> Maybe a data BitLimited (n :: Nat) (a :: *) where @@ -582,7 +560,7 @@ trapWord n v = pure . fromIntegral $ v `mod` 2 ^ n instance KnownNat bits => Evaluatable (BitLimited bits Natural) where evaluate Five = pure $ NatN 5 - evaluate (About n) = NatN <$> trapNat (natVal (Proxy @bits)) (evalN n) + evaluate (Neuralgic n) = NatN <$> trapNat (natVal (Proxy @bits)) (evalN n) evaluate ab = case ab of a `Add` b -> go (+) a b @@ -593,14 +571,14 @@ instance KnownNat bits => Evaluatable (BitLimited bits Natural) where _ `Mod` (evaluate -> Just 0) -> Nothing a `Mod` b -> go rem a b a `Pow` b -> do b' <- evaluate b; exponentiable b'; go (^) a b - IfThenElse a b c -> do c <- evalR c + IfThenElse a b c -> do c <- evaluate c evaluate $ if c then a else b _ -> error $ show ab where go op a b = do NatN a <- evaluate a; NatN b <- evaluate b; NatN <$> trapNat (natVal (Proxy @bits)) (toInteger a `op` toInteger b) instance KnownNat bits => Evaluatable (BitLimited bits Integer) where evaluate Five = pure $ IntN 5 - evaluate (About n) = IntN <$> trapInt (natVal (Proxy @bits)) (evalN n) + evaluate (Neuralgic n) = IntN <$> trapInt (natVal (Proxy @bits)) (evalN n) evaluate ab = case ab of a `Add` b -> go (+) a b @@ -611,14 +589,16 @@ instance KnownNat bits => Evaluatable (BitLimited bits Integer) where _ `Mod` (evaluate -> Just 0) -> Nothing a `Mod` b -> go rem a b a `Pow` b -> do b' <- evaluate b; exponentiable b'; go (^) a b - IfThenElse a b c -> do c <- evalR c + IfThenElse a b c -> do c <- evaluate c evaluate $ if c then a else b _ -> error $ show ab where go op a b = do IntN a <- evaluate a; IntN b <- evaluate b; IntN <$> trapInt (natVal (Proxy @bits)) (toInteger a `op` toInteger b) + instance WordLike bits => Evaluatable (BitLimited bits Word) where evaluate Five = pure $ WordN 5 - evaluate (About n) = WordN <$> trapWord (natVal (Proxy @bits)) (evalN n) + evaluate (Neuralgic n) = WordN <$> trapWord (natVal (Proxy @bits)) (evalN n) + evaluate (Complement a) = complement <$> evaluate a evaluate ab = case ab of a `Add` b -> go (+) a b @@ -629,6 +609,8 @@ instance WordLike bits => Evaluatable (BitLimited bits Word) where _ `Mod` (evaluate -> Just 0) -> Nothing a `Mod` b -> go rem a b a `Pow` b -> do b' <- evaluate b; exponentiable b'; go (^) a b + IfThenElse a b c -> do c <- evaluate c + evaluate $ if c then a else b a `Or` b -> log (.|.) a b a `And` b -> log (.&.) a b a `Xor` b -> log xor a b @@ -640,22 +622,20 @@ instance WordLike bits => Evaluatable (BitLimited bits Word) where PopCnt (evaluate -> a) -> fromIntegral . popCount <$> a Clz (evaluate -> a) -> fromIntegral . countLeadingZeros <$> a Ctz (evaluate -> a) -> fromIntegral . countTrailingZeros <$> a - IfThenElse a b c -> do c <- evalR c - evaluate $ if c then a else b - _ -> error $ show ab - where go op a b = do WordN a <- evaluate a; WordN b <- evaluate b; WordN <$> trapWord bitcount (toInteger a `op` toInteger b) - log op a b = op <$> evaluate a <*> evaluate b + where log op a b = op <$> evaluate a <*> evaluate b bitcount = natVal (Proxy @bits) signedShiftR a b = fromIntegral $ a' `shiftR` (fromIntegral b `mod` fromIntegral bitcount) where a' = toInteger a - (toInteger (((a `rotateL` 1) .&. 1) `rotateR` 1) `shiftL` 1) + go op a b = do WordN a <- evaluate a; WordN b <- evaluate b; WordN <$> trapWord bitcount (toInteger a `op` toInteger b) + instance Evaluatable Integer where evaluate = eval instance Evaluatable Natural where evaluate = eval -eval :: (Restricted a, Integral a) => ActorScriptTerm (Neuralgic a) -> Maybe a +eval :: (Restricted a, Integral a) => ASTerm a -> Maybe a eval Five = pure 5 -eval (About n) = evalN n +eval (Neuralgic n) = evalN n eval (Pos n) = eval n eval (Neg n) = - eval n eval (Abs n) = abs $ eval n @@ -669,27 +649,27 @@ eval (ConvertNatural t) = fromIntegral <$> evaluate t eval (ConvertNat t) = fromIntegral <$> evaluate t eval (ConvertInt t) = fromIntegral <$> evaluate t eval (ConvertWord t) = fromIntegral <$> evaluate t -eval (IfThenElse a b c) = do c <- evalR c +eval (IfThenElse a b c) = do c <- evaluate c eval $ if c then a else b -eval (Rel r) = bool 0 1 <$> evalR r --eval _ = Nothing -evalR :: ActorScriptTyped a -> Maybe a -evalR (a `NotEqual` b) = (/=) <$> evaluate a <*> evaluate b -evalR (a `Equals` b) = (==) <$> evaluate a <*> evaluate b -evalR (a `GreaterEqual` b) = (>=) <$> evaluate a <*> evaluate b -evalR (a `Greater` b) = (>) <$> evaluate a <*> evaluate b -evalR (a `LessEqual` b) = (<=) <$> evaluate a <*> evaluate b -evalR (a `Less` b) = (<) <$> evaluate a <*> evaluate b -evalR (a `ShortAnd` b) = evalR a >>= bool (pure False) (evalR b) -evalR (a `ShortOr` b) = evalR a >>= bool (evalR b) (pure True) -evalR (Not a) = not <$> evalR a -evalR (Bool b) = pure b + +instance Evaluatable Bool where + evaluate (a `NotEqual` b) = (/=) <$> evaluate a <*> evaluate b + evaluate (a `Equals` b) = (==) <$> evaluate a <*> evaluate b + evaluate (a `GreaterEqual` b) = (>=) <$> evaluate a <*> evaluate b + evaluate (a `Greater` b) = (>) <$> evaluate a <*> evaluate b + evaluate (a `LessEqual` b) = (<=) <$> evaluate a <*> evaluate b + evaluate (a `Less` b) = (<) <$> evaluate a <*> evaluate b + evaluate (a `ShortAnd` b) = evaluate a >>= bool (pure False) (evaluate b) + evaluate (a `ShortOr` b) = evaluate a >>= bool (evaluate b) (pure True) + evaluate (Not a) = not <$> evaluate a + evaluate (Bool b) = pure b class Annot t where - annot :: ActorScriptTerm (Neuralgic t) -> String -> String - sizeSuffix :: ActorScriptTerm (Neuralgic t) -> String -> String + annot :: ASTerm t -> String -> String + sizeSuffix :: ASTerm t -> String -> String sizeSuffix _ = id instance Annot Integer where @@ -740,9 +720,9 @@ instance Literal Bool where inParens :: (a -> String) -> String -> a -> a -> String inParens to op lhs rhs = "(" <> to lhs <> " " <> op <> " " <> to rhs <> ")" -unparseAS :: (Annot a, Literal a) => ActorScriptTerm (Neuralgic a) -> String +unparseAS :: (Annot a, Literal a) => ASTerm a -> String unparseAS f@Five = annot f "5" -unparseAS a@(About n) = annot a $ literal n +unparseAS a@(Neuralgic n) = annot a $ literal n unparseAS (Pos n) = "(+" <> unparseAS n <> ")" unparseAS (Neg n) = "(-" <> unparseAS n <> ")" unparseAS (Abs n) = "(abs " <> unparseAS n <> ")" @@ -763,39 +743,36 @@ unparseAS (a `ShiftRSigned` b) = inParens unparseAS "+>>" a b unparseAS (PopCnt n) = sizeSuffix n "(popcntWord" <> " " <> unparseAS n <> ")" unparseAS (Clz n) = sizeSuffix n "(clzWord" <> " " <> unparseAS n <> ")" unparseAS (Ctz n) = sizeSuffix n "(ctzWord" <> " " <> unparseAS n <> ")" +unparseAS (Complement a) = "(^ " <> unparseAS a <> ")" unparseAS (ConvertNatural a) = "(++++(" <> unparseAS a <> "))" unparseAS (ConvertNat a) = unparseNat Proxy a unparseAS (ConvertInt a) = unparseInt Proxy a unparseAS (ConvertWord a) = unparseWord Proxy a -unparseAS (Rel r) = unparseBool r -unparseAS (IfThenElse a b c) = "(if (" <> unparseBool c <> ") " <> unparseAS a <> " else " <> unparseAS b <> ")" - -unparseBool :: ActorScriptTyped Bool -> String -unparseBool (a `NotEqual` b) = inParens unparseAS "!=" a b -unparseBool (a `Equals` b) = inParens unparseAS "==" a b -unparseBool (a `GreaterEqual` b) = inParens unparseAS ">=" a b -unparseBool (a `Greater` b) = inParens unparseAS ">" a b -unparseBool (a `LessEqual` b) = inParens unparseAS "<=" a b -unparseBool (a `Less` b) = inParens unparseAS "<" a b -unparseBool (a `ShortAnd` b) = inParens unparseBool "and" a b -unparseBool (a `ShortOr` b) = inParens unparseBool "or" a b -unparseBool (Not a) = "(not " <> unparseBool a <> ")" -unparseBool (Bool False) = "false" -unparseBool (Bool True) = "true" - -unparseNat :: KnownNat n => Proxy n -> ActorScriptTerm (Neuralgic (BitLimited n Natural)) -> String +unparseAS (IfThenElse a b c) = "(if (" <> unparseAS c <> ") " <> unparseAS a <> " else " <> unparseAS b <> ")" +unparseAS (a `NotEqual` b) = inParens unparseAS "!=" a b +unparseAS (a `Equals` b) = inParens unparseAS "==" a b +unparseAS (a `GreaterEqual` b) = inParens unparseAS ">=" a b +unparseAS (a `Greater` b) = inParens unparseAS ">" a b +unparseAS (a `LessEqual` b) = inParens unparseAS "<=" a b +unparseAS (a `Less` b) = inParens unparseAS "<" a b +unparseAS (a `ShortAnd` b) = inParens unparseAS "and" a b +unparseAS (a `ShortOr` b) = inParens unparseAS "or" a b +unparseAS (Not a) = "(not " <> unparseAS a <> ")" +unparseAS (Bool False) = "false" +unparseAS (Bool True) = "true" + +unparseNat :: KnownNat n => Proxy n -> ASTerm (BitLimited n Natural) -> String unparseNat p a = "(nat" <> bitWidth p <> "ToNat(" <> unparseAS a <> "))" -unparseInt :: KnownNat n => Proxy n -> ActorScriptTerm (Neuralgic (BitLimited n Integer)) -> String +unparseInt :: KnownNat n => Proxy n -> ASTerm (BitLimited n Integer) -> String unparseInt p a = "(int" <> bitWidth p <> "ToInt(" <> unparseAS a <> "))" -unparseWord :: KnownNat n => Proxy n -> ActorScriptTerm (Neuralgic (BitLimited n Word)) -> String +unparseWord :: KnownNat n => Proxy n -> ASTerm (BitLimited n Word) -> String unparseWord p a = "(word" <> bitWidth p <> "ToNat(" <> unparseAS a <> "))" -- TODO we want signed too: wordToInt - - -- TODOs: -- - wordToInt -- - bitwise ops (btst?) --- - bitwise not, a.k.a unary (^) -- - pattern matches (over numeric, bool) +-- - trapping flavour-preserving conversions Nat -> NatN +-- - bitsize-preserving conversions From aae905f805340e674f4132cd8f7b61be4d9b31a5 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Sun, 18 Aug 2019 17:29:06 +0200 Subject: [PATCH 0353/1176] AFL fuzzing test setup for leb128 roundtrip (#622) This is not running in CI, see README for instructions. Would have caught #621. Does not seem to catch any more bugs. It only tests round-tripping leb128 and sleb128 from int so far. See branch `joachim/afl` for a more elaborate setup of fuzzing the IDL parser against out-of-memory-reads. --- rts/.gitignore | 2 + rts/Makefile | 11 +++-- rts/README.md | 22 +++++++++- rts/afl_leb128_in/issue621 | Bin 0 -> 5 bytes rts/afl_leb128_in/test | 1 + rts/run-afl-leb128.sh | 10 +++++ rts/test_leb128.c | 87 +++++++++++++++++++++++++++++++++++++ 7 files changed, 128 insertions(+), 5 deletions(-) create mode 100644 rts/afl_leb128_in/issue621 create mode 100644 rts/afl_leb128_in/test create mode 100755 rts/run-afl-leb128.sh create mode 100644 rts/test_leb128.c diff --git a/rts/.gitignore b/rts/.gitignore index b23b77784b5..c124feb3ee4 100644 --- a/rts/.gitignore +++ b/rts/.gitignore @@ -1,3 +1,5 @@ as-rts.wasm test_rts +test_leb128 +afl_leb128_out _build diff --git a/rts/Makefile b/rts/Makefile index df721f85a4e..fcfcb9d9310 100644 --- a/rts/Makefile +++ b/rts/Makefile @@ -55,7 +55,7 @@ WASM_FLAGS = \ # Build targets # -all: as-rts.wasm test_rts +all: as-rts.wasm test_rts test_leb128 _build/wasm _build/native: mkdir -p $@ @@ -105,8 +105,11 @@ as-rts.wasm: $(RTS_WASM_O) $(TOMMATH_WASM_O) # test_rts: test_rts.c $(RTS_NATIVE_O) $(TOMMATH_NATIVE_O) - $(CLANG) -o $@ \ - $+ + $(CLANG) -o $@ $+ + +test_leb128: test_leb128.c $(RTS_NATIVE_O) $(TOMMATH_NATIVE_O) + $(CLANG) -o $@ $+ + clean: - rm -rf _build as-rts.wasm test_rts + rm -rf _build as-rts.wasm test_rts test_leb128 diff --git a/rts/README.md b/rts/README.md index 940cac5bd3f..e1624ff9eed 100644 --- a/rts/README.md +++ b/rts/README.md @@ -54,5 +54,25 @@ with the code provided by `rts.c` from `test_rts.c`. With make test_rts && ./test_rts -this is executed. This is compiled natively, so may not hide bugs that are tied to +this is executed. This is compiled natively, so may not uncover bugs that are tied to WebAssembly. + +AFL tests +--------- + +Some tests are best run by AFL (American Fuzzy Lop), which is a whitebox +fuzzer that instruments the code to get more coverage. + +You can install `afl` using `nix-env -i afl`. + +You need to compile the code with instrumentation and then run it using the +helper script provided: + +``` +make clean +CLANG=afl-gcc make test_leb128 +./run-afl-leb128.sh +``` + + + diff --git a/rts/afl_leb128_in/issue621 b/rts/afl_leb128_in/issue621 new file mode 100644 index 0000000000000000000000000000000000000000..5be526444ef994c8020c9b110c53e632d58d6958 GIT binary patch literal 5 McmZSl&(6RI00bNX2><{9 literal 0 HcmV?d00001 diff --git a/rts/afl_leb128_in/test b/rts/afl_leb128_in/test new file mode 100644 index 00000000000..2321334cd90 --- /dev/null +++ b/rts/afl_leb128_in/test @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/rts/run-afl-leb128.sh b/rts/run-afl-leb128.sh new file mode 100755 index 00000000000..0f4511a8fd5 --- /dev/null +++ b/rts/run-afl-leb128.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +if test -e afl_leb128_out +then +# continue +AFL_SKIP_CPUFREQ=1 afl-fuzz -i - -o afl_leb128_out/ -- ./test_leb128 @@ +else +# start from scratch +AFL_SKIP_CPUFREQ=1 afl-fuzz -i afl_leb128_in/ -o afl_leb128_out/ -- ./test_leb128 @@ +fi diff --git a/rts/test_leb128.c b/rts/test_leb128.c new file mode 100644 index 00000000000..c1b2019b101 --- /dev/null +++ b/rts/test_leb128.c @@ -0,0 +1,87 @@ +#include +#include +#include +#include +#include +#include + +#include "buf.h" + +typedef intptr_t as_ptr; + +as_ptr alloc_bytes(size_t n) { + void *ptr = malloc(n); + if (ptr == NULL) { printf("OOM\n"); exit(1); }; + return ((as_ptr)ptr) - 1; +}; + +void idl_trap() { + printf("IDL trap\n"); + abort(); +} +void bigint_trap() { + printf("Bigint trap\n"); + abort(); +} + +extern void leb128_encode(uint32_t n, unsigned char *buf); +extern uint32_t read_u32_of_leb128(buf *buf); +extern void sleb128_encode(int32_t n, unsigned char *buf); +extern int32_t read_i32_of_sleb128(buf *buf); + + +int main(int argc, char** argv) { + printf("ASC LEB128 round-trip tests\n"); + + if (argc < 2) { + printf("Usage: %s inputfile\n", argv[0]); + return 1; + } + + // read file + FILE *f = fopen(argv[1], "rb"); + if (f == NULL) { + fprintf(stderr, "Error opening file %s: %s\n", argv[1], strerror( errno )); + exit(1); + } + fseek(f, 0, SEEK_END); + long input_size = ftell(f); + fseek(f, 0, SEEK_SET); /* same as rewind(f); */ + char *input = malloc(input_size); + fread(input, 1, input_size, f); + fclose(f); + + // read word + if (input_size != 1+sizeof(uint32_t)) { + printf("Input file should have %zu bytes", 1+sizeof(uint32_t)); + free(input); + return 1; + } + + uint8_t sign = *input; + + uint8_t b[100]; + buf buf = { b, b + 100 }; + + if (sign) { + int32_t i = *((int32_t *)(input+1)); + sleb128_encode(i, b); + int32_t o = read_i32_of_sleb128(&buf); + printf("Sign: %d Input: %d Output: %d\n", sign, i, o); + if (i != o) { abort(); } + } else { + uint32_t i = *((uint32_t *)(input+1)); + leb128_encode(i, b); + uint32_t o = read_u32_of_leb128(&buf); + printf("Sign: %d Input: %u Output: %u\n", sign, i, o); + if (i != o) { abort(); } + } + printf("Encoding: "); + for (uint8_t *p = b; p < buf.p; p++) printf("%02X", *p); + printf("\n"); + + free(input); + return 0; +} + + From f6f410a56c33402ebc3daaf8ce4f752ea1b00e05 Mon Sep 17 00:00:00 2001 From: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> Date: Mon, 19 Aug 2019 11:33:44 +0200 Subject: [PATCH 0354/1176] [ACT-112] Go-to-definition (#620) * Extracts declaration index into its own module * extracts some common functionality finding the identifier under the cursor is needed for more than just hovering * populates declarations in the index with definition sites * adds some List functions to the lib * adds a handler for the textDocument/definition command * populates type declarations in the index * better naming * removes redundant import * Apply suggestions from code review Co-Authored-By: Claudio Russo * rename lib functions with _opt postfix * makes type declaration carry a con rather than a type * less noisy info popups for types * removes dead comment --- src/languageServer/completion.ml | 99 ++++--------- src/languageServer/declaration_index.ml | 178 ++++++++++++++++++++++++ src/languageServer/definition.ml | 58 ++++++++ src/languageServer/hover.ml | 87 ++++-------- src/languageServer/hover_tests.ml | 10 +- src/languageServer/languageServer.ml | 26 +++- src/languageServer/source_file.ml | 105 ++++++++++++++ src/languageServer/source_file_tests.ml | 45 ++++++ src/lib/lib.ml | 15 +- src/lib/lib.mli | 4 +- src/lsp/lsp.atd | 3 + 11 files changed, 485 insertions(+), 145 deletions(-) create mode 100644 src/languageServer/declaration_index.ml create mode 100644 src/languageServer/definition.ml create mode 100644 src/languageServer/source_file.ml create mode 100644 src/languageServer/source_file_tests.ml diff --git a/src/languageServer/completion.ml b/src/languageServer/completion.ml index c5930c72a1d..38d99e93642 100644 --- a/src/languageServer/completion.ml +++ b/src/languageServer/completion.ml @@ -1,14 +1,8 @@ open As_types open As_frontend +open Declaration_index module Lsp_t = Lsp.Lsp_t -type ide_decl = - | ValueDecl of string * Type.typ - | TypeDecl of string * Type.typ - -module Index = Map.Make(String) -type completion_index = (ide_decl list) Index.t - let string_of_list f xs = List.map f xs |> String.concat "; " @@ -18,8 +12,8 @@ let template_of_ide_decl decl = let supply = ref 0 in let fresh () = supply := !supply + 1; string_of_int !supply in match decl with - | ValueDecl (lbl, ty) -> - (match ty with + | ValueDecl value -> + (match value.typ with | Type.Func(_, _, binds, ty_list1, ty_list2) -> let ty_args = binds @@ -31,82 +25,38 @@ let template_of_ide_decl decl = |> List.map (fun _ -> Printf.sprintf "$%s" (fresh ())) |> String.concat ", " in let ty_args = if ty_args = "" then "" else "<" ^ ty_args ^ ">" in - Printf.sprintf "%s%s(%s)" lbl ty_args args - | _ -> lbl) - | TypeDecl (lbl, ty) -> - lbl - -let lbl_of_ide_decl (d : ide_decl) : string = - match d with - | ValueDecl (lbl, _) -> lbl - | TypeDecl (lbl, _) -> lbl + Printf.sprintf "%s%s(%s)" value.name ty_args args + | _ -> value.name) + | TypeDecl ty -> + ty.name let item_of_ide_decl (d : ide_decl) : Lsp_t.completion_item = let tmpl = template_of_ide_decl d in match d with - | ValueDecl (lbl, ty) -> + | ValueDecl value -> Lsp_t.{ - completion_item_label = lbl; + completion_item_label = value.name; completion_item_kind = 3; completion_item_insertText = tmpl; completion_item_insertTextFormat = 2; - completion_item_detail = Some(Type.string_of_typ ty); + completion_item_detail = Some(Type.string_of_typ value.typ); } - | TypeDecl (lbl, ty) -> + | TypeDecl ty -> + let con = ty.typ in + let eq, params, typ = Type.strings_of_kind (Con.kind con) in Lsp_t.{ - completion_item_label = lbl; + completion_item_label = ty.name; completion_item_kind = 7; completion_item_insertText = tmpl; completion_item_insertTextFormat = 2; - completion_item_detail = Some(Type.string_of_typ ty); + completion_item_detail = + Some + (Printf.sprintf + "type %s%s" + ty.name + params); } -let string_of_ide_decl = function - | ValueDecl (lbl, ty) -> - "ValueDecl(" ^ String.escaped lbl ^ ", " ^ Type.string_of_typ ty ^ ")" - | TypeDecl (lbl, ty) -> - "TypeDecl(" ^ String.escaped lbl ^ ", " ^ Type.string_of_typ ty ^ ")" - -let lib_files () : string list = - let lib_dir = "lib" in - Sys.readdir lib_dir - |> Array.to_list - |> List.filter (fun file -> String.equal (Filename.extension file) ".as") - |> List.map (fun file -> Filename.concat lib_dir file) - -let read_single_module_lib (ty: Type.typ): ide_decl list option = - match ty with - | Type.Obj (Type.Module, fields) -> - fields - |> List.map (fun Type.{ lab = lab; typ = typ } -> ValueDecl (lab, typ)) - |> Lib.Option.some - | _ -> None - -let make_index (): completion_index = - let (libraries, scope) = - Diag.run - (Pipeline.chase_imports - Pipeline.initial_stat_env - (Pipeline__.Resolve_import.S.of_list (lib_files ()))) in - Type.Env.fold - (fun path ty acc -> - Index.add - path - (ty - |> read_single_module_lib - |> Lib.Fun.flip Lib.Option.get []) - acc) - scope.Scope.lib_env - Index.empty - -let string_of_index index = - Index.bindings index - |> string_of_list - (fun (path, decls) -> - path - ^ " =>\n " - ^ string_of_list string_of_ide_decl decls - ^ "\n") let import_relative_to_project_root root module_path dependency = match Pipeline__.File_path.relative_to root module_path with @@ -210,7 +160,11 @@ let completions (* index *) logger project_root file_path file_contents line col (match Index.find_opt (snd mp) index with | Some decls -> decls - |> List.filter (fun d -> d |> lbl_of_ide_decl |> Lib.String.chop_prefix prefix |> Lib.Option.is_some) + |> List.filter + (fun d -> d + |> name_of_ide_decl + |> Lib.String.chop_prefix prefix + |> Lib.Option.is_some) |> List.map item_of_ide_decl | None -> (* The matching import references a module we haven't loaded *) @@ -224,6 +178,3 @@ let completion_handler logger project_root file_path file_contents position = let column = position.Lsp_t.position_character in `CompletionResponse (completions logger project_root file_path file_contents line column) - -let test_completion () = - Printf.printf "%s\n" (string_of_index (make_index ())) diff --git a/src/languageServer/declaration_index.ml b/src/languageServer/declaration_index.ml new file mode 100644 index 00000000000..cd9944118b2 --- /dev/null +++ b/src/languageServer/declaration_index.ml @@ -0,0 +1,178 @@ +open As_types +open As_def +open Source +open Syntax + +type value_decl = { + name : string; + typ: Type.typ; + definition: region option; + } + +type type_decl = { + name : string; + typ: Type.con; + definition: region option; + } + +type ide_decl = + | ValueDecl of value_decl + | TypeDecl of type_decl + +(** For debugging purposes *) +let string_of_ide_decl = function + | ValueDecl value -> + "ValueDecl{ name = " + ^ String.escaped value.name + ^ ", typ = " + ^ Type.string_of_typ value.typ + ^ Lib.Option.get + (Lib.Option.map + (fun pos -> ", definition = " ^ string_of_region pos) + value.definition) + "" + ^ " }" + | TypeDecl ty -> + "TypeDecl{ name = " + ^ String.escaped ty.name + ^ ", typ = " + ^ Type.string_of_con ty.typ + ^ Lib.Option.get + (Lib.Option.map + (fun pos -> ", definition = " ^ string_of_region pos) + ty.definition) + "" + ^ " }" + +let name_of_ide_decl (d : ide_decl) : string = + match d with + | ValueDecl value -> value.name + | TypeDecl ty -> ty.name + +module Index = Map.Make(String) +type declaration_index = (ide_decl list) Index.t + +module PatternMap = Map.Make(String) +type pattern_map = Source.region PatternMap.t + +let rec gather_pat ve pat : pattern_map = + match pat.it with + | WildP | LitP _ | SignP _ -> ve + | VarP id -> PatternMap.add id.it id.at ve + | TupP pats -> List.fold_left gather_pat ve pats + | ObjP pfs -> List.fold_left gather_pat_field ve pfs + | TagP (_, pat1) | AltP (pat1, _) | OptP pat1 + | AnnotP (pat1, _) | ParP pat1 -> gather_pat ve pat1 + +and gather_pat_field ve pf = + gather_pat ve pf.it.pat + +let string_of_list f xs = + List.map f xs + |> String.concat "; " + |> fun x -> "[ " ^ x ^ " ]" + +let string_of_index index = + Index.bindings index + |> string_of_list + (fun (path, decls) -> + path + ^ " =>\n " + ^ string_of_list string_of_ide_decl decls + ^ "\n") + +let lib_files () : string list = + let lib_dir = "lib" in + Sys.readdir lib_dir + |> Array.to_list + |> List.filter (fun file -> String.equal (Filename.extension file) ".as") + |> List.map (fun file -> Filename.concat lib_dir file) + +let read_single_module_lib (ty: Type.typ): ide_decl list option = + match ty with + | Type.Obj (Type.Module, fields) -> + fields + |> List.map + (fun Type.{ lab = name; typ } -> + (match typ with + | Type.Typ con -> TypeDecl { name; typ = con; definition = None } + | typ -> ValueDecl { name; typ; definition = None } + ) + ) + |> Lib.Option.some + | _ -> None + +let unwrap_module_ast (prog : Syntax.dec list): Syntax.exp_field list option = + match prog with + | ({it=Syntax.ExpD {it= Syntax.ObjE(_,fields) ;_} ;_} :: _) -> + Some fields + | _ -> None + +let flat_map f xs = List.flatten (List.map f xs) + +let populate_definitions + (libraries : Syntax.libraries) + (path : string) + (decls : ide_decl list) + : ide_decl list = + let is_let_bound exp_field = + match exp_field.it.Syntax.dec.it with + | Syntax.LetD(pat, _) -> Some pat + | _ -> None in + let is_type_def exp_field = + match exp_field.it.Syntax.dec.it with + | Syntax.TypD (typ_id, _, _) -> + Some typ_id + | _ -> None in + let extract_binders env (pat : Syntax.pat) = gather_pat env pat in + let find_def (prog : Syntax.dec list) def = match def with + | ValueDecl value -> + let fields = Lib.Option.get (unwrap_module_ast prog) [] in + let positioned_binder = + fields + |> Lib.List.map_filter is_let_bound + |> List.fold_left extract_binders PatternMap.empty + |> PatternMap.find_opt value.name + in + ValueDecl { value with definition = positioned_binder } + | TypeDecl typ -> + let fields = Lib.Option.get (unwrap_module_ast prog) [] in + let type_definition = + fields + |> Lib.List.map_filter is_type_def + |> Lib.List.first_opt (fun ty_id -> + if ty_id.it = typ.name + then Some ty_id.at + else None) + in + TypeDecl { typ with definition = type_definition } in + let opt_lib = + List.find_opt + (fun (path', _) -> String.equal path path') + libraries in + match opt_lib with + | None -> decls + | Some (_, prog) -> + List.map (find_def prog.it) decls + +let make_index_inner () : declaration_index = + let (libraries, scope) = + Diag.run + (Pipeline.chase_imports + Pipeline.initial_stat_env + (Pipeline__.Resolve_import.S.of_list (lib_files ()))) in + Type.Env.fold + (fun path ty acc -> + Index.add + path + (ty + |> read_single_module_lib + |> Lib.Fun.flip Lib.Option.get [] + |> populate_definitions libraries path) + acc) + scope.Scope.lib_env + Index.empty + +let make_index () : declaration_index = + (* TODO(Christoph): Actually handle errors here *) + try make_index_inner () with _ -> Index.empty diff --git a/src/languageServer/definition.ml b/src/languageServer/definition.ml new file mode 100644 index 00000000000..b6bad98192b --- /dev/null +++ b/src/languageServer/definition.ml @@ -0,0 +1,58 @@ +module Lsp = Lsp.Lsp_t +open Declaration_index + +let position_of_pos (pos : Source.pos) : Lsp.position = Lsp. + (* The LSP spec requires zero-based positions *) + { position_line = if pos.Source.line > 0 then pos.Source.line - 1 else 0; + position_character = pos.Source.column; + } + +let range_of_region (at : Source.region) : Lsp.range = Lsp. + { range_start = position_of_pos at.Source.left; + range_end_ = position_of_pos at.Source.right; + } + +let definition_handler + (* index *) + position + file_contents + project_root + file_path = + let index = Declaration_index.make_index () in + let result = + Lib.Option.bind + (Source_file.identifier_at_pos + project_root + file_path + file_contents + position) + (function + | Source_file.Resolved resolved -> + Index.find_opt resolved.Source_file.path index + |> Lib.Fun.flip Lib.Option.bind (fun decls -> + decls + |> Lib.List.first_opt (function + | ValueDecl value -> + if String.equal value.name resolved.Source_file.ident + then + value.definition + |> Lib.Option.map (fun def -> + (resolved.Source_file.path, def)) + else None + | TypeDecl typ -> + if String.equal typ.name resolved.Source_file.ident + then + typ.definition + |> Lib.Option.map (fun def -> + (resolved.Source_file.path, def)) + else None)) + | Source_file.Alias _ -> None + | Source_file.Unresolved _ -> None + | Source_file.Ident _ -> None) in + let location = + Lib.Option.map (fun (path, region) -> + Lsp. + { location_uri = path; + location_range = range_of_region region + }) result in + `TextDocumentDefinitionResponse location diff --git a/src/languageServer/hover.ml b/src/languageServer/hover.ml index 750545681ee..ded9f96d055 100644 --- a/src/languageServer/hover.ml +++ b/src/languageServer/hover.ml @@ -1,75 +1,42 @@ -open As_frontend open As_types +open Declaration_index module Lsp = Lsp.Lsp_t -type hover_target = - | Ident of string - | Qualified of string * string - -let hovered_identifier - (position : Lsp.position) - (file_contents : string) - : hover_target option = - let line = position.Lsp.position_line + 1 in - let column = position.Lsp.position_character + 1 in - let lexbuf = Lexing.from_string file_contents in - let next () = Lexer.token Lexer.Normal lexbuf in - let pos_past_cursor pos = - pos.Source.line > line - || (pos.Source.line = line && pos.Source.column >= column) in - let rec loop = function - | _ when (pos_past_cursor (Lexer.region lexbuf).Source.left) -> None - | Parser.ID ident -> - (match next () with - | Parser.DOT -> - (match next () with - | Parser.ID prefix -> - let next_token_end = (Lexer.region lexbuf).Source.right in - if pos_past_cursor next_token_end - then Some (Qualified (ident, prefix)) - else loop (Parser.ID prefix) - | tkn -> - let next_token_start = (Lexer.region lexbuf).Source.left in - if pos_past_cursor next_token_start - then Some (Ident ident) - else loop tkn) - | _ when pos_past_cursor (Lexer.region lexbuf).Source.left -> - Some (Ident ident) - | tkn -> loop tkn) - | Parser.EOF -> None - | _ -> loop (next ()) in - loop (next ()) - let hover_detail = function - | Completion.ValueDecl (lbl, ty) -> - lbl ^ " : " ^ Type.string_of_typ ty - | Completion.TypeDecl (lbl, ty) -> - lbl ^ Type.string_of_typ ty + | ValueDecl value -> + value.name ^ " : " ^ Type.string_of_typ value.typ + | TypeDecl ty -> + let _, params, _ = Type.strings_of_kind (Con.kind ty.typ) in + Printf.sprintf "public type %s%s" ty.name params + let hover_handler (* index *) position file_contents project_root file_path = (* TODO(Christoph): Don't rebuild index on every hover *) - let index = Completion.make_index () in - let imported = - Completion.parse_module_header - project_root - file_path - file_contents in + let index = make_index () in let hover_result = - Lib.Option.bind (hovered_identifier position file_contents) (function - | Ident s -> - List.find_opt (fun (alias, _) -> alias = s) imported - |> Lib.Option.map (fun (_, path) -> - Lsp.{ hover_result_contents = path }) - | Qualified (qual, ident) -> - List.find_opt (fun (alias, _) -> alias = qual) imported - |> Lib.Fun.flip Lib.Option.bind (fun (_, path) -> - Completion.Index.find_opt path index) + Lib.Option.bind + (Source_file.identifier_at_pos + project_root + file_path + file_contents + position) + (function + | Source_file.Alias (_, path) -> + Some Lsp.{ hover_result_contents = path } + | Source_file.Resolved resolved -> + Index.find_opt resolved.Source_file.path index |> Lib.Fun.flip Lib.Option.bind (fun decls -> List.find_opt - (fun d -> Completion.lbl_of_ide_decl d = ident) + (fun d -> name_of_ide_decl d = resolved.Source_file.ident) decls) |> Lib.Option.map (fun ide_decl -> Lsp.{ hover_result_contents = hover_detail ide_decl }) - ) in + | Source_file.Ident _ -> + (* At some point we'll want to look this Ident up in the + local context*) + None + | Source_file.Unresolved _ -> + None) + in let result = `TextDocumentHoverResponse hover_result in result diff --git a/src/languageServer/hover_tests.ml b/src/languageServer/hover_tests.ml index fc7484c6b40..189f9f37108 100644 --- a/src/languageServer/hover_tests.ml +++ b/src/languageServer/hover_tests.ml @@ -18,11 +18,11 @@ let extract_cursor input = let hovered_identifier_test_case file expected = let (file, (line, column)) = extract_cursor file in let show = function - | Some(Hover.Ident i) -> i - | Some(Hover.Qualified (qualifier, ident)) -> qualifier ^ "." ^ ident + | Some(Source_file.CIdent i) -> i + | Some(Source_file.CQualified (qualifier, ident)) -> qualifier ^ "." ^ ident | None -> "None" in let actual = - Hover.hovered_identifier + Source_file.cursor_target_at_pos Lsp.{ position_line = line; position_character = column } file in Lib.Option.equal (=) actual expected || (Printf.printf @@ -34,7 +34,7 @@ let hovered_identifier_test_case file expected = let%test "it finds an identifier" = hovered_identifier_test_case "f|ilter" - (Some (Hover.Ident "filter")) + (Some (Source_file.CIdent "filter")) let%test "it ignores hovering over whitespace" = hovered_identifier_test_case "filter |" None @@ -42,4 +42,4 @@ let%test "it ignores hovering over whitespace" = let%test "it finds a qualified identifier" = hovered_identifier_test_case "List.f|ilter" - (Some (Hover.Qualified ("List", "filter"))) + (Some (Source_file.CQualified ("List", "filter"))) diff --git a/src/languageServer/languageServer.ml b/src/languageServer/languageServer.ml index 294891e9c69..0e4e71b749c 100644 --- a/src/languageServer/languageServer.ml +++ b/src/languageServer/languageServer.ml @@ -26,8 +26,6 @@ let response_error_message (id : int) (error : Lsp_t.response_error) : Lsp_t.res response_message_error = Some error; } -(* let response_error_message (id : int) (error : Lsp_t.response_error) : Lsp_t.response_message = *) - module Channel = struct let log_to_file (oc : out_channel) (lbl : string) (txt : string) : unit = Printf.fprintf oc "[%s] %s\n" lbl txt; @@ -160,6 +158,7 @@ let start () = server_capabilities_textDocumentSync = text_document_sync_options; server_capabilities_hoverProvider = Some true; server_capabilities_completionProvider = Some completion_options; + server_capabilities_definitionProvider = Some true; } }) in let response = response_result_message id result in @@ -187,6 +186,28 @@ let start () = (abs_file_from_uri log_to_file uri) in response_result_message id result in send_response (Lsp_j.string_of_response_message response); + | (Some id, `TextDocumentDefinition params) -> + let uri = + params + .Lsp_t.text_document_position_params_textDocument + .Lsp_t.text_document_identifier_uri in + let position = + params.Lsp_t.text_document_position_params_position in + let response = match Vfs.read_file uri !vfs with + | None -> + response_error_message + id + Lsp_t.{ code = 1 + ; message = "Tried to find a definition in a file that hadn't been opened yet"} + | Some file_content -> + let result = + Definition.definition_handler + position + file_content + project_root + (abs_file_from_uri log_to_file uri) in + response_result_message id result in + send_response (Lsp_j.string_of_response_message response); | (_, `TextDocumentDidOpen params) -> vfs := Vfs.open_file params !vfs | (_, `TextDocumentDidChange params) -> @@ -198,7 +219,6 @@ let start () = let uri = textDocumentIdent.Lsp_t.text_document_identifier_uri in let file_name = file_from_uri log_to_file uri in let result = Pipeline.check_files [file_name] in - show_message Lsp.MessageType.Info ("Compiling file: " ^ file_name); let msgs = match result with | Error msgs' -> msgs' | Ok (_, msgs') -> msgs' in diff --git a/src/languageServer/source_file.ml b/src/languageServer/source_file.ml new file mode 100644 index 00000000000..28b4871b821 --- /dev/null +++ b/src/languageServer/source_file.ml @@ -0,0 +1,105 @@ +open As_frontend +module Lsp = Lsp.Lsp_t + +type cursor_target = + | CIdent of string + | CQualified of string * string + +let cursor_target_at_pos + (position : Lsp.position) + (file_contents : string) + : cursor_target option = + let line = position.Lsp.position_line + 1 in + let column = position.Lsp.position_character + 1 in + let lexbuf = Lexing.from_string file_contents in + let next () = Lexer.token Lexer.Normal lexbuf in + let pos_past_cursor pos = + pos.Source.line > line + || (pos.Source.line = line && pos.Source.column >= column) in + let rec loop = function + | _ when (pos_past_cursor (Lexer.region lexbuf).Source.left) -> None + | Parser.ID ident -> + (match next () with + | Parser.DOT -> + (match next () with + | Parser.ID prefix -> + let next_token_end = (Lexer.region lexbuf).Source.right in + if pos_past_cursor next_token_end + then Some (CQualified (ident, prefix)) + else loop (Parser.ID prefix) + | tkn -> + let next_token_start = (Lexer.region lexbuf).Source.left in + if pos_past_cursor next_token_start + then Some (CIdent ident) + else loop tkn) + | _ when pos_past_cursor (Lexer.region lexbuf).Source.left -> + Some (CIdent ident) + | tkn -> loop tkn) + | Parser.EOF -> None + | _ -> loop (next ()) in + loop (next ()) + +let import_relative_to_project_root root module_path dependency = + match Pipeline__.File_path.relative_to root module_path with + | None -> None + | Some root_to_module -> + root_to_module + |> Filename.dirname + |> Lib.Fun.flip Filename.concat dependency + |> Pipeline__.File_path.normalise + |> Lib.Option.some + +(* Given the source of a module, figure out under what names what + modules have been imported. Normalizes the imported modules + filepaths relative to the project root *) +let parse_module_header project_root current_file_path file = + let lexbuf = Lexing.from_string file in + let next () = Lexer.token Lexer.Normal lexbuf in + let res = ref [] in + let rec loop = function + | Parser.IMPORT -> + (match next () with + | Parser.ID alias -> + (match next () with + | Parser.TEXT path -> + let path = + import_relative_to_project_root + project_root + current_file_path + path in + (match path with + | Some path -> res := (alias, path) :: !res + | None -> ()); + loop (next ()) + | tkn -> loop tkn) + | tkn -> loop tkn) + | Parser.EOF -> List.rev !res + | tkn -> loop (next ()) in + loop (next ()) + +type unresolved_target = + { qualifier : string; ident : string } +type resolved_target = + { qualifier : string; ident : string; path : string } +type identifier_target = + | Ident of string + | Alias of string * string + | Unresolved of unresolved_target + | Resolved of resolved_target + +let identifier_at_pos project_root file_path file_contents position = + let imported = + parse_module_header + project_root + file_path + file_contents in + cursor_target_at_pos position file_contents + |> Lib.Option.map (function + | CIdent s -> + (match List.find_opt (fun (alias, _) -> alias = s) imported with + | None -> Ident s + | Some (alias, path) -> Alias (alias, path)) + | CQualified (qual, ident) -> + (match List.find_opt (fun (alias, _) -> alias = qual) imported with + | None -> Unresolved { qualifier = qual; ident } + | Some (alias, path) -> Resolved { qualifier = qual; ident; path })) diff --git a/src/languageServer/source_file_tests.ml b/src/languageServer/source_file_tests.ml new file mode 100644 index 00000000000..189f9f37108 --- /dev/null +++ b/src/languageServer/source_file_tests.ml @@ -0,0 +1,45 @@ +module Lsp = Lsp.Lsp_t +let extract_cursor input = + let cursor_pos = ref (0, 0) in + String.split_on_char '\n' input + |> List.mapi + (fun line_num line -> + match String.index_opt line '|' with + | Some column_num -> + cursor_pos := (line_num, column_num); + line + |> String.split_on_char '|' + |> String.concat "" + | None -> line + ) + |> String.concat "\n" + |> fun f -> (f, !cursor_pos) + +let hovered_identifier_test_case file expected = + let (file, (line, column)) = extract_cursor file in + let show = function + | Some(Source_file.CIdent i) -> i + | Some(Source_file.CQualified (qualifier, ident)) -> qualifier ^ "." ^ ident + | None -> "None" in + let actual = + Source_file.cursor_target_at_pos + Lsp.{ position_line = line; position_character = column } file in + Lib.Option.equal (=) actual expected || + (Printf.printf + "\nExpected: %s\nActual: %s\n" + (show expected) + (show actual); + false) + +let%test "it finds an identifier" = + hovered_identifier_test_case + "f|ilter" + (Some (Source_file.CIdent "filter")) + +let%test "it ignores hovering over whitespace" = + hovered_identifier_test_case "filter |" None + +let%test "it finds a qualified identifier" = + hovered_identifier_test_case + "List.f|ilter" + (Some (Source_file.CQualified ("List", "filter"))) diff --git a/src/lib/lib.ml b/src/lib/lib.ml index b4ac557caa3..a7fe1ae7da9 100644 --- a/src/lib/lib.ml +++ b/src/lib/lib.ml @@ -126,13 +126,24 @@ struct | n, _::xs' when n > 0 -> drop (n - 1) xs' | _ -> failwith "drop" + let hd_opt = function + | x :: _ -> Some x + | _ -> None + let rec last = function - | x::[] -> x + | [x] -> x | _::xs -> last xs | [] -> failwith "last" + let rec first_opt f = function + | [] -> None + | x::xs -> + match f x with + | None -> first_opt f xs + | some -> some + let rec split_last = function - | x::[] -> [], x + | [x] -> [], x | x::xs -> let ys, y = split_last xs in x::ys, y | [] -> failwith "split_last" diff --git a/src/lib/lib.mli b/src/lib/lib.mli index f8adfc33fdf..97651783bd9 100644 --- a/src/lib/lib.mli +++ b/src/lib/lib.mli @@ -19,12 +19,14 @@ sig val take : int -> 'a list -> 'a list (* raises Failure *) val drop : int -> 'a list -> 'a list (* raises Failure *) + val hd_opt : 'a list -> 'a option val last : 'a list -> 'a (* raises Failure *) val split_last : 'a list -> 'a list * 'a (* raises Failure *) val index_of : 'a -> 'a list -> int option val index_where : ('a -> bool) -> 'a list -> int option val map_filter : ('a -> 'b option) -> 'a list -> 'b list + val first_opt : ('a -> 'b option) -> 'a list -> 'b option val compare : ('a -> 'a -> int) -> 'a list -> 'a list -> int val is_ordered : ('a -> 'a -> int) -> 'a list -> bool @@ -119,7 +121,7 @@ sig val logor : t -> t -> t val shift_right_logical : t -> int -> t end - + module String : sig val implode : char list -> string diff --git a/src/lsp/lsp.atd b/src/lsp/lsp.atd index 7ceffe54d92..cbf3da04854 100644 --- a/src/lsp/lsp.atd +++ b/src/lsp/lsp.atd @@ -46,6 +46,7 @@ type incoming_message_params = [ | TextDocumentDidChange of text_document_did_change_params | TextDocumentDidSave of text_document_did_save_params | TextDocumentHover of text_document_position_params + | TextDocumentDefinition of text_document_position_params (* NOTE(Christoph) There are more parameters than just text_document_position on the completion request *) | CompletionRequest of text_document_position_params | CancelRequest of cancel_request_params @@ -71,6 +72,7 @@ type response_message = { type response_result = [ Initialize of initialize_result | TextDocumentHoverResponse of hover_result nullable + | TextDocumentDefinitionResponse of location nullable | CompletionResponse of completion_item list ] @@ -278,6 +280,7 @@ type server_capabilities = { textDocumentSync : text_document_sync_options; ?hoverProvider : bool nullable; ?completionProvider : completion_options nullable; + ?definitionProvider : bool nullable; } From 7e1cf6770d0a0c118ca1c594b0b6573937f57816 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity <48968912+chenyan-dfinity@users.noreply.github.com> Date: Tue, 20 Aug 2019 11:04:13 -0700 Subject: [PATCH 0355/1176] Apply suggestions from code review Co-Authored-By: Joachim Breitner --- test/run.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/run.sh b/test/run.sh index 2f88725c007..5c9761b4128 100755 --- a/test/run.sh +++ b/test/run.sh @@ -125,7 +125,7 @@ do normalize $out/$base.tc diff_files="$diff_files $base.tc" - if [ "$tc_succeeded" -eq 0 ]; + if [ "$tc_succeeded" -eq 0 ] then if [ $CHECK_IDL_ONLY = 'yes' ] then @@ -135,7 +135,7 @@ do normalize $out/$base.did normalize $out/$base.idl.stderr diff_files="$diff_files $base.did $base.idl.stderr" - if [ "$idl_succeeded" -eq 0 ]; + if [ "$idl_succeeded" -eq 0 ] then $ECHO -n " [didc]" $DIDC --check $out/$base.did > $out/$base.did.tc 2>&1 @@ -204,7 +204,7 @@ do normalize $out/$base.did normalize $out/$base.idl.stderr diff_files="$diff_files $base.did $base.idl.stderr" - if [ "$idl_succeeded" -eq 0 ]; + if [ "$idl_succeeded" -eq 0 ] then $ECHO -n " [didc]" $DIDC --check $out/$base.did > $out/$base.did.tc 2>&1 From 1273615261543a9b25f5fd605e35197ff7273d6e Mon Sep 17 00:00:00 2001 From: chenyan-dfinity Date: Tue, 20 Aug 2019 11:14:40 -0700 Subject: [PATCH 0356/1176] address review --- src/exes/asc.ml | 18 +++---- test/run.sh | 138 ++++++++++++++++++++++++------------------------ 2 files changed, 76 insertions(+), 80 deletions(-) diff --git a/src/exes/asc.ml b/src/exes/asc.ml index d2402f72833..ddf281862e1 100644 --- a/src/exes/asc.ml +++ b/src/exes/asc.ml @@ -77,7 +77,7 @@ let argspec = Arg.align ] -let fill_out_file files ext = +let set_out_file files ext = if !out_file = "" then begin match files with | [n] -> out_file := Filename.remove_extension (Filename.basename n) ^ ext @@ -104,18 +104,14 @@ let process_files files : unit = | Check -> Diag.run (Pipeline.check_files files) | Idl -> + set_out_file files ".did"; let prog = Diag.run (Pipeline.generate_idl files) in - let idl_code = Idllib.Arrange_idl.string_of_prog prog in - if !out_file = "" then - (printf "%s" idl_code; - ignore (Diag.run (Idllib.Pipeline.check_prog prog))) - else begin - ignore (Diag.run (Idllib.Pipeline.check_prog prog)); - let oc = open_out !out_file in - output_string oc idl_code; close_out oc - end + ignore (Diag.run (Idllib.Pipeline.check_prog prog)); + let oc = open_out !out_file in + let idl_code = Idllib.Arrange_idl.string_of_prog prog in + output_string oc idl_code; close_out oc | Compile -> - fill_out_file files ".wasm"; + set_out_file files ".wasm"; let module_ = Diag.run Pipeline.(compile_files !compile_mode !link files) in let oc = open_out !out_file in let (source_map, wasm) = CustomModuleEncode.encode module_ in diff --git a/test/run.sh b/test/run.sh index 5c9761b4128..2a4baed6785 100755 --- a/test/run.sh +++ b/test/run.sh @@ -143,87 +143,87 @@ do fi else - if [ "$SKIP_RUNNING" != yes ] - then - # Interpret - $ECHO -n " [run]" - $ASC $ASC_FLAGS -r $base.as > $out/$base.run 2>&1 - normalize $out/$base.run - diff_files="$diff_files $base.run" - - # Interpret IR without lowering - $ECHO -n " [run-ir]" - $ASC $ASC_FLAGS -r -iR -no-async -no-await $base.as > $out/$base.run-ir 2>&1 - normalize $out/$base.run-ir - diff_files="$diff_files $base.run-ir" - - # Diff interpretations without/with lowering - diff -u -N --label "$base.run" $out/$base.run --label "$base.run-ir" $out/$base.run-ir > $out/$base.diff-ir - diff_files="$diff_files $base.diff-ir" - - # Interpret IR with lowering - $ECHO -n " [run-low]" - $ASC $ASC_FLAGS -r -iR $base.as > $out/$base.run-low 2>&1 - normalize $out/$base.run-low - diff_files="$diff_files $base.run-low" - - # Diff interpretations without/with lowering - diff -u -N --label "$base.run" $out/$base.run --label "$base.run-low" $out/$base.run-low > $out/$base.diff-low - diff_files="$diff_files $base.diff-low" + if [ "$SKIP_RUNNING" != yes ] + then + # Interpret + $ECHO -n " [run]" + $ASC $ASC_FLAGS -r $base.as > $out/$base.run 2>&1 + normalize $out/$base.run + diff_files="$diff_files $base.run" + + # Interpret IR without lowering + $ECHO -n " [run-ir]" + $ASC $ASC_FLAGS -r -iR -no-async -no-await $base.as > $out/$base.run-ir 2>&1 + normalize $out/$base.run-ir + diff_files="$diff_files $base.run-ir" + + # Diff interpretations without/with lowering + diff -u -N --label "$base.run" $out/$base.run --label "$base.run-ir" $out/$base.run-ir > $out/$base.diff-ir + diff_files="$diff_files $base.diff-ir" + + # Interpret IR with lowering + $ECHO -n " [run-low]" + $ASC $ASC_FLAGS -r -iR $base.as > $out/$base.run-low 2>&1 + normalize $out/$base.run-low + diff_files="$diff_files $base.run-low" + + # Diff interpretations without/with lowering + diff -u -N --label "$base.run" $out/$base.run --label "$base.run-low" $out/$base.run-low > $out/$base.diff-low + diff_files="$diff_files $base.diff-low" - fi + fi - # Compile - $ECHO -n " [wasm]" - $ASC $ASC_FLAGS $EXTRA_ASC_FLAGS --map -c $base.as -o $out/$base.wasm 2> $out/$base.wasm.stderr - normalize $out/$base.wasm.stderr - diff_files="$diff_files $base.wasm.stderr" + # Compile + $ECHO -n " [wasm]" + $ASC $ASC_FLAGS $EXTRA_ASC_FLAGS --map -c $base.as -o $out/$base.wasm 2> $out/$base.wasm.stderr + normalize $out/$base.wasm.stderr + diff_files="$diff_files $base.wasm.stderr" - # Check filecheck - if [ "$SKIP_RUNNING" != yes ] - then - if grep -F -q CHECK $base.as + # Check filecheck + if [ "$SKIP_RUNNING" != yes ] then - $ECHO -n " [FileCheck]" - wasm2wat --no-check --enable-multi-value $out/$base.wasm > $out/$base.wat - cat $out/$base.wat | FileCheck $base.as > $out/$base.filecheck 2>&1 - diff_files="$diff_files $base.filecheck" + if grep -F -q CHECK $base.as + then + $ECHO -n " [FileCheck]" + wasm2wat --no-check --enable-multi-value $out/$base.wasm > $out/$base.wat + cat $out/$base.wat | FileCheck $base.as > $out/$base.filecheck 2>&1 + diff_files="$diff_files $base.filecheck" + fi fi - fi - # Run compiled program - if [ -e $out/$base.wasm ] - then - if [ "$SKIP_RUNNING" != yes ] + # Run compiled program + if [ -e $out/$base.wasm ] then - if [ $DFINITY = 'yes' ] + if [ "$SKIP_RUNNING" != yes ] then - $ECHO -n " [idl]" - $ASC $ASC_FLAGS $EXTRA_ASC_FLAGS --idl $base.as -o $out/$base.did 2> $out/$base.idl.stderr - idl_succeeded=$? - normalize $out/$base.did - normalize $out/$base.idl.stderr - diff_files="$diff_files $base.did $base.idl.stderr" - if [ "$idl_succeeded" -eq 0 ] + if [ $DFINITY = 'yes' ] then - $ECHO -n " [didc]" - $DIDC --check $out/$base.did > $out/$base.did.tc 2>&1 - diff_files="$diff_files $base.did.tc" - fi - - $ECHO -n " [dvm]" - $DVM_WRAPPER $out/$base.wasm $base.as > $out/$base.dvm-run 2>&1 - normalize $out/$base.dvm-run - diff_files="$diff_files $base.dvm-run" - else - $ECHO -n " [wasm-run]" - $WASM $out/$base.wasm > $out/$base.wasm-run 2>&1 - normalize $out/$base.wasm-run - diff_files="$diff_files $base.wasm-run" + $ECHO -n " [idl]" + $ASC $ASC_FLAGS $EXTRA_ASC_FLAGS --idl $base.as -o $out/$base.did 2> $out/$base.idl.stderr + idl_succeeded=$? + normalize $out/$base.did + normalize $out/$base.idl.stderr + diff_files="$diff_files $base.did $base.idl.stderr" + if [ "$idl_succeeded" -eq 0 ] + then + $ECHO -n " [didc]" + $DIDC --check $out/$base.did > $out/$base.did.tc 2>&1 + diff_files="$diff_files $base.did.tc" + fi + + $ECHO -n " [dvm]" + $DVM_WRAPPER $out/$base.wasm $base.as > $out/$base.dvm-run 2>&1 + normalize $out/$base.dvm-run + diff_files="$diff_files $base.dvm-run" + else + $ECHO -n " [wasm-run]" + $WASM $out/$base.wasm > $out/$base.wasm-run 2>&1 + normalize $out/$base.wasm-run + diff_files="$diff_files $base.wasm-run" + fi fi fi fi - fi fi elif [ ${file: -3} == ".sh" ] then From a251239f88bbb3a1b03a9610df92ea06cf1b12db Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 23 Aug 2019 11:34:35 +0200 Subject: [PATCH 0357/1176] Fix typo in Building.md (#625) --- Building.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Building.md b/Building.md index 0b4499fe2e2..d81dd5b0656 100644 --- a/Building.md +++ b/Building.md @@ -8,7 +8,7 @@ $ nix-env -i -f . -A asc ## Development using Nix -This is the command that should always pass on master is the following, which builds everything: +The command that should always pass on master is the following; it builds everything: ``` $ nix-build --no-out-link ``` From 8639cf5c643c6a9a8998ba831edc7836f357c571 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Sat, 17 Aug 2019 19:03:00 +0200 Subject: [PATCH 0358/1176] use overlapping instances of Arbitrary for BitLimited AS terms For low bit counts we want to carry out the exponentiation without restrictions. Here we get overlaps. Anyway, this schema lets me remove quite some cruft. --- test/random/Main.hs | 47 ++++++++++----------------------------------- 1 file changed, 10 insertions(+), 37 deletions(-) diff --git a/test/random/Main.hs b/test/random/Main.hs index 44017433392..439782dfab7 100644 --- a/test/random/Main.hs +++ b/test/random/Main.hs @@ -293,53 +293,26 @@ reasonablyShaped sub = sized $ \(succ -> n) -> frequency $ (30 `div` n, Neuralgic <$> arbitrary) : if n > 1 then sub n else [] -instance Arbitrary (ASTerm Nat8) where - arbitrary = reasonablyShaped $ subTerm True - -reasonableNatTerm :: (KnownNat n, Arbitrary (ASTerm (BitLimited n Natural))) => Gen (ASTerm (BitLimited n Natural)) -reasonableNatTerm = reasonablyShaped $ subTermPow (`Mod` Five) - -instance Arbitrary (ASTerm Nat16) where - arbitrary = reasonableNatTerm - -instance Arbitrary (ASTerm Nat32) where - arbitrary = reasonableNatTerm - -instance Arbitrary (ASTerm Nat64) where - arbitrary = reasonableNatTerm - +instance {-# OVERLAPPABLE #-} KnownNat n => Arbitrary (ASTerm (BitLimited n Natural)) where + arbitrary = reasonablyShaped $ subTermPow (`Mod` Five) -instance Arbitrary (ASTerm Int8) where +instance {-# OVERLAPS #-} Arbitrary (ASTerm Nat8) where arbitrary = reasonablyShaped $ subTerm True -reasonableIntTerm :: (KnownNat n, Arbitrary (ASTerm (BitLimited n Integer))) => Gen (ASTerm (BitLimited n Integer)) -reasonableIntTerm = reasonablyShaped subTermPow5 -instance Arbitrary (ASTerm Int16) where - arbitrary = reasonableIntTerm +instance {-# OVERLAPPABLE #-} KnownNat n => Arbitrary (ASTerm (BitLimited n Integer)) where + arbitrary = reasonablyShaped subTermPow5 -instance Arbitrary (ASTerm Int32) where - arbitrary = reasonableIntTerm +instance {-# OVERLAPS #-} Arbitrary (ASTerm Int8) where + arbitrary = reasonablyShaped $ subTerm True -instance Arbitrary (ASTerm Int64) where - arbitrary = reasonableIntTerm +instance {-# OVERLAPPABLE #-} WordLike n => Arbitrary (ASTerm (BitLimited n Word)) where + arbitrary = reasonablyShaped $ (<>) <$> subTermPow (`Mod` Five) <*> bitwiseTerm -instance Arbitrary (ASTerm Word8) where +instance {-# OVERLAPS #-} Arbitrary (ASTerm Word8) where arbitrary = reasonablyShaped $ (<>) <$> subTerm True <*> bitwiseTerm -reasonableWordTerm :: (WordLike n, Arbitrary (ASTerm (BitLimited n Word))) => Gen (ASTerm (BitLimited n Word)) -reasonableWordTerm = reasonablyShaped $ (<>) <$> subTermPow (`Mod` Five) <*> bitwiseTerm - -instance Arbitrary (ASTerm Word16) where - arbitrary = reasonableWordTerm - -instance Arbitrary (ASTerm Word32) where - arbitrary = reasonableWordTerm - -instance Arbitrary (ASTerm Word64) where - arbitrary = reasonableWordTerm - instance Arbitrary (ASTerm Bool) where arbitrary = sized $ \(succ -> n) -> -- TODO: use frequency? From 6ed59826f1db685f914176e6201a44ff17174906 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Tue, 27 Aug 2019 15:01:42 +0200 Subject: [PATCH 0359/1176] there are no "like" types (#627) since we have no nominal ones (besides primitives) --- README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.md b/README.md index cfd0456bd04..c2552ef81b4 100644 --- a/README.md +++ b/README.md @@ -90,9 +90,6 @@ A simple language for writing Dfinity actors. * Async types: like futures/promises - `async T` -* Like types: structural expansions of nominal types - - `like T` - * Structural equi-recursive subtyping * Generics over reference types, uniform representation From dc187194127b76fa08f9b7fc9a9c4fc28573ba39 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 30 Aug 2019 16:17:49 +0200 Subject: [PATCH 0360/1176] Refactor system_call (#629) * Refactor system_call a small change cherry-picked from #628 * Move some await-using tests from `run` to `run-dfinity`. --- src/codegen/compile.ml | 91 +++++++++---------- test/{run => run-dfinity}/await.as | 0 test/{run => run-dfinity}/block.as | 0 test/run-dfinity/for-await.as | 15 +++ test/run-dfinity/ok/await.dvm-run.ok | 16 ++++ test/{run => run-dfinity}/ok/await.run-ir.ok | 0 test/{run => run-dfinity}/ok/await.run-low.ok | 0 test/{run => run-dfinity}/ok/await.run.ok | 0 test/run-dfinity/ok/block.dvm-run.ok | 1 + test/{run => run-dfinity}/ok/block.run-ir.ok | 0 test/{run => run-dfinity}/ok/block.run-low.ok | 0 test/{run => run-dfinity}/ok/block.run.ok | 0 test/run-dfinity/ok/for-await.dvm-run.ok | 1 + test/run-dfinity/ok/for-await.run-ir.ok | 1 + test/run-dfinity/ok/for-await.run-low.ok | 1 + test/run-dfinity/ok/for-await.run.ok | 1 + test/run/for.as | 29 ++---- test/run/ok/await.wasm-run.ok | 1 - test/run/ok/block.wasm-run.ok | 1 - test/run/ok/for.run-ir.ok | 2 +- test/run/ok/for.run-low.ok | 2 +- test/run/ok/for.run.ok | 2 +- 22 files changed, 89 insertions(+), 75 deletions(-) rename test/{run => run-dfinity}/await.as (100%) rename test/{run => run-dfinity}/block.as (100%) create mode 100644 test/run-dfinity/for-await.as create mode 100644 test/run-dfinity/ok/await.dvm-run.ok rename test/{run => run-dfinity}/ok/await.run-ir.ok (100%) rename test/{run => run-dfinity}/ok/await.run-low.ok (100%) rename test/{run => run-dfinity}/ok/await.run.ok (100%) create mode 100644 test/run-dfinity/ok/block.dvm-run.ok rename test/{run => run-dfinity}/ok/block.run-ir.ok (100%) rename test/{run => run-dfinity}/ok/block.run-low.ok (100%) rename test/{run => run-dfinity}/ok/block.run.ok (100%) create mode 100644 test/run-dfinity/ok/for-await.dvm-run.ok create mode 100644 test/run-dfinity/ok/for-await.run-ir.ok create mode 100644 test/run-dfinity/ok/for-await.run-low.ok create mode 100644 test/run-dfinity/ok/for-await.run.ok delete mode 100644 test/run/ok/await.wasm-run.ok delete mode 100644 test/run/ok/block.wasm-run.ok diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 362b206d56b..008bf36f67c 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -293,20 +293,18 @@ module E = struct idesc = nr (FuncImport (nr (func_type env (FuncType (arg_tys, ret_tys))))) } in let fi = reg env.func_imports (nr i) in - let name = modname ^ "_" ^ funcname in + let name = modname ^ "." ^ funcname in assert (not (NameEnv.mem name !(env.built_in_funcs))); env.built_in_funcs := NameEnv.add name (Defined fi) !(env.built_in_funcs); else assert false (* "add all imports before all functions!" *) let call_import (env : t) modname funcname = - let name = modname ^ "_" ^ funcname in - let fi = match NameEnv.find_opt name !(env.built_in_funcs) with - | Some (Defined fi) -> fi + let name = modname ^ "." ^ funcname in + match NameEnv.find_opt name !(env.built_in_funcs) with + | Some (Defined fi) -> G.i (Call (nr fi)) | _ -> - Printf.eprintf "Function import not declared: %s.%s\n" modname funcname; + Printf.eprintf "Function import not declared: %s\n" name; assert false - in - G.i (Call (nr fi)) let get_prelude (env : t) = env.prelude let get_rts (env : t) = env.rts @@ -2252,20 +2250,18 @@ module BigNumLibtommath : BigNumType = struct let compile_eq env = E.call_import env "rts" "bigint_eq" let compile_is_negative env = E.call_import env "rts" "bigint_isneg" - let compile_relop env op = - let fn = match op with - | Lt -> "rts_bigint_lt" - | Le -> "rts_bigint_le" - | Ge -> "rts_bigint_ge" - | Gt -> "rts_bigint_gt" in - G.i (Call (nr (E.built_in env fn))) + let compile_relop env = function + | Lt -> E.call_import env "rts" "bigint_lt" + | Le -> E.call_import env "rts" "bigint_le" + | Ge -> E.call_import env "rts" "bigint_ge" + | Gt -> E.call_import env "rts" "bigint_gt" let fits_signed_bits env bits = - G.i (Call (nr (E.built_in env ("rts_bigint_2complement_bits")))) ^^ + E.call_import env "rts" "bigint_2complement_bits" ^^ compile_unboxed_const (Int32.of_int bits) ^^ G.i (Compare (Wasm.Values.I32 I32Op.LeU)) let fits_unsigned_bits env bits = - G.i (Call (nr (E.built_in env ("rts_bigint_count_bits")))) ^^ + E.call_import env "rts" "bigint_count_bits" ^^ compile_unboxed_const (Int32.of_int bits) ^^ G.i (Compare (Wasm.Values.I32 I32Op.LeU)) @@ -2898,9 +2894,9 @@ module Dfinity = struct E.add_func_import env "func" "bind_i32" [I32Type; I32Type] [I32Type]; end - let system_call env name = + let system_call env modname funcname = if E.mode env = DfinityMode - then G.i (Call (nr (E.built_in env name))) + then E.call_import env modname funcname else G.i Unreachable let compile_databuf_of_text env = @@ -2914,7 +2910,7 @@ module Dfinity = struct Heap.load_field (Text.len_field) ^^ (* Externalize *) - system_call env "data_externalize" + system_call env "data" "externalize" ) let compile_databuf_of_bytes env (bytes : string) = @@ -2923,11 +2919,11 @@ module Dfinity = struct (* For debugging *) let compile_static_print env s = compile_databuf_of_bytes env s ^^ - system_call env "test_print" + system_call env "test" "print" let _compile_println_int env = - system_call env "test_show_i32" ^^ - system_call env "test_print" ^^ + system_call env "test" "show_i32" ^^ + system_call env "test" "print" ^^ compile_static_print env "\n" let trap_with env s = @@ -2937,7 +2933,7 @@ module Dfinity = struct let prim_print env = compile_databuf_of_text env ^^ - system_call env "test_print" + system_call env "test" "print" let default_exports env = (* these exports seem to be wanted by the hypervisor/v8 *) @@ -2984,12 +2980,12 @@ module Dfinity = struct ElemHeap.recall_reference env let get_self_reference env = - system_call env "actor_self" ^^ + system_call env "actor" "self" ^^ box_reference env let static_message_funcref env fi = compile_unboxed_const fi ^^ - system_call env "func_externalize" + system_call env "func" "externalize" end (* Dfinity *) @@ -3028,7 +3024,7 @@ module OrthogonalPersistence = struct Func.define_built_in env "restore_mem" [] [] (fun env1 -> let (set_i, get_i) = new_local env1 "len" in G.i (GlobalGet (nr mem_global)) ^^ - Dfinity.system_call env1 "data_length" ^^ + Dfinity.system_call env1 "data" "length" ^^ set_i ^^ get_i ^^ @@ -3049,11 +3045,11 @@ module OrthogonalPersistence = struct get_i ^^ G.i (GlobalGet (nr mem_global)) ^^ compile_unboxed_zero ^^ - Dfinity.system_call env1 "data_internalize" ^^ + Dfinity.system_call env1 "data" "internalize" ^^ (* Load reference counter *) G.i (GlobalGet (nr elem_global)) ^^ - Dfinity.system_call env1 "elem_length" ^^ + Dfinity.system_call env1 "elem" "length" ^^ ElemHeap.set_ref_ctr ^^ (* Load references *) @@ -3061,7 +3057,7 @@ module OrthogonalPersistence = struct ElemHeap.get_ref_ctr ^^ G.i (GlobalGet (nr elem_global)) ^^ compile_unboxed_zero ^^ - Dfinity.system_call env1 "elem_internalize" + Dfinity.system_call env1 "elem" "internalize" ) ); Func.define_built_in env "save_mem" [] [] (fun env1 -> @@ -3070,13 +3066,13 @@ module OrthogonalPersistence = struct Heap.get_heap_ptr ^^ compile_unboxed_const ElemHeap.table_end ^^ G.i (Binary (Wasm.Values.I32 I32Op.Sub)) ^^ - Dfinity.system_call env "data_externalize" ^^ + Dfinity.system_call env "data" "externalize" ^^ G.i (GlobalSet (nr mem_global)) ^^ (* Store references *) compile_unboxed_const ElemHeap.ref_location ^^ ElemHeap.get_ref_ctr ^^ - Dfinity.system_call env "elem_externalize" ^^ + Dfinity.system_call env "elem" "externalize" ^^ G.i (GlobalSet (nr elem_global)) ) @@ -3961,7 +3957,7 @@ module Serialization = struct get_refs_start ^^ get_data_start ^^ get_data_size ^^ - Dfinity.system_call env "data_externalize" ^^ + Dfinity.system_call env "data" "externalize" ^^ store_unskewed_ptr ^^ if has_no_references t @@ -3978,7 +3974,7 @@ module Serialization = struct (* Finally, create elembuf *) get_refs_start ^^ get_refs_size ^^ compile_divU_const Heap.word_size ^^ - Dfinity.system_call env "elem_externalize" + Dfinity.system_call env "elem" "externalize" ) let deserialize_text env get_databuf = @@ -3986,7 +3982,7 @@ module Serialization = struct let (set_x, get_x) = new_local env "x" in get_databuf ^^ - Dfinity.system_call env "data_length" ^^ + Dfinity.system_call env "data" "length" ^^ set_data_size ^^ get_data_size ^^ @@ -3997,7 +3993,7 @@ module Serialization = struct get_data_size ^^ get_databuf ^^ compile_unboxed_const 0l ^^ - Dfinity.system_call env "data_internalize" ^^ + Dfinity.system_call env "data" "internalize" ^^ get_x @@ -4025,7 +4021,7 @@ module Serialization = struct else (* Allocate space for the elem buffer *) get_elembuf ^^ - Dfinity.system_call env "elem_length" ^^ + Dfinity.system_call env "elem" "length" ^^ set_refs_size ^^ get_refs_size ^^ @@ -4039,7 +4035,7 @@ module Serialization = struct get_refs_size ^^ get_elembuf ^^ compile_unboxed_const 0l ^^ - Dfinity.system_call env "elem_internalize" ^^ + Dfinity.system_call env "elem" "internalize" ^^ (* Get databuf *) get_refs_start ^^ @@ -4049,7 +4045,7 @@ module Serialization = struct (* Allocate space for the data buffer *) get_databuf ^^ - Dfinity.system_call env "data_length" ^^ + Dfinity.system_call env "data" "length" ^^ set_data_size ^^ get_data_size ^^ Text.dyn_alloc_scratch env ^^ set_data_start ^^ @@ -4059,7 +4055,7 @@ module Serialization = struct get_data_size ^^ get_databuf ^^ compile_unboxed_const 0l ^^ - Dfinity.system_call env "data_internalize" ^^ + Dfinity.system_call env "data" "internalize" ^^ (* Allocate space for out parameters of parse_idl_header *) Stack.with_words env "get_typtbl_ptr" 1l (fun get_typtbl_ptr -> @@ -4655,7 +4651,7 @@ module FuncDec = struct let call_funcref env cc get_ref = compile_unboxed_const tmp_table_slot ^^ (* slot number *) get_ref ^^ (* the unboxed funcref *) - Dfinity.system_call env "func_internalize" ^^ + Dfinity.system_call env "func" "internalize" ^^ compile_unboxed_const tmp_table_slot ^^ G.i (CallIndirect (nr (message_ty env cc))) @@ -4664,9 +4660,9 @@ module FuncDec = struct Func.share_code1 env "export_self_message" ("name", I32Type) [I32Type] (fun env get_name -> Tagged.obj env Tagged.Reference [ (* Create a funcref for the message *) - Dfinity.system_call env "actor_self" ^^ + Dfinity.system_call env "actor" "self" ^^ get_name ^^ (* the databuf with the message name *) - Dfinity.system_call env "actor_export" ^^ + Dfinity.system_call env "actor" "export" ^^ ElemHeap.remember_reference env ] ) @@ -4862,10 +4858,10 @@ module FuncDec = struct SR.UnboxedReference, code ^^ compile_unboxed_const fi ^^ - Dfinity.system_call env "func_externalize" ^^ + Dfinity.system_call env "func" "externalize" ^^ get_clos ^^ ClosureTable.remember_closure env ^^ - Dfinity.system_call env "func_bind_i32" + Dfinity.system_call env "func" "bind_i32" let lit env ae how name cc free_vars args mk_body at = let captured = List.filter (ASEnv.needs_capture ae) free_vars in @@ -6552,6 +6548,7 @@ This function compiles the prelude, just to find out the bound names. and find_prelude_names env = (* Create a throw-away environment *) let env0 = E.mk_global (E.mode env) None (E.get_prelude env) (fun _ _ -> G.i Unreachable) 0l in + Dfinity.system_imports env0; RTS.system_imports env0; let env1 = E.mk_fun_env env0 0l 0 in let ae = ASEnv.empty_ae in @@ -6655,8 +6652,8 @@ and actor_lit outer_env this ds fs at = Dfinity.compile_databuf_of_bytes outer_env wasm_binary ^^ (* Create actorref *) - Dfinity.system_call outer_env "module_new" ^^ - Dfinity.system_call outer_env "actor_new" + Dfinity.system_call outer_env "module" "new" ^^ + Dfinity.system_call outer_env "actor" "new" (* Main actor: Just return the initialization code, and export functions as needed *) and main_actor env ae1 this ds fs = @@ -6673,7 +6670,7 @@ and main_actor env ae1 this ds fs = and actor_fake_object_idx env name = Dfinity.compile_databuf_of_bytes env name ^^ - Dfinity.system_call env "actor_export" + Dfinity.system_call env "actor" "export" and conclude_module env module_name start_fi_o = diff --git a/test/run/await.as b/test/run-dfinity/await.as similarity index 100% rename from test/run/await.as rename to test/run-dfinity/await.as diff --git a/test/run/block.as b/test/run-dfinity/block.as similarity index 100% rename from test/run/block.as rename to test/run-dfinity/block.as diff --git a/test/run-dfinity/for-await.as b/test/run-dfinity/for-await.as new file mode 100644 index 00000000000..88e296a3f45 --- /dev/null +++ b/test/run-dfinity/for-await.as @@ -0,0 +1,15 @@ +let _ = +async { + +{ + var i = 0; + i := 0; + for (j in range(0, 10)) { + printNat(j); + assert(j == i); + await (async (i += 1)); + }; + assert(i == 11); +}; + +}; diff --git a/test/run-dfinity/ok/await.dvm-run.ok b/test/run-dfinity/ok/await.dvm-run.ok new file mode 100644 index 00000000000..7569eb9e6fe --- /dev/null +++ b/test/run-dfinity/ok/await.dvm-run.ok @@ -0,0 +1,16 @@ +abcdegholycnt: 0 i: 0 +cnt: 1 i: 1 +cnt: 2 i: 2 +cnt: 3 i: 3 +cnt: 4 i: 4 +e-whilecnt: 5 i: 5 +cnt: 6 i: 6 +cnt: 7 i: 7 +cnt: 8 i: 8 +cnt: 9 i: 9 +e-exitg-label.cnt: 10 i: 10 +.cnt: 11 i: 11 +.cnt: 12 i: 12 +.cnt: 13 i: 13 +.cnt: 14 i: 14 +g-exitab diff --git a/test/run/ok/await.run-ir.ok b/test/run-dfinity/ok/await.run-ir.ok similarity index 100% rename from test/run/ok/await.run-ir.ok rename to test/run-dfinity/ok/await.run-ir.ok diff --git a/test/run/ok/await.run-low.ok b/test/run-dfinity/ok/await.run-low.ok similarity index 100% rename from test/run/ok/await.run-low.ok rename to test/run-dfinity/ok/await.run-low.ok diff --git a/test/run/ok/await.run.ok b/test/run-dfinity/ok/await.run.ok similarity index 100% rename from test/run/ok/await.run.ok rename to test/run-dfinity/ok/await.run.ok diff --git a/test/run-dfinity/ok/block.dvm-run.ok b/test/run-dfinity/ok/block.dvm-run.ok new file mode 100644 index 00000000000..c70e9fe9d72 --- /dev/null +++ b/test/run-dfinity/ok/block.dvm-run.ok @@ -0,0 +1 @@ +a1b1a2b2a3b31356 diff --git a/test/run/ok/block.run-ir.ok b/test/run-dfinity/ok/block.run-ir.ok similarity index 100% rename from test/run/ok/block.run-ir.ok rename to test/run-dfinity/ok/block.run-ir.ok diff --git a/test/run/ok/block.run-low.ok b/test/run-dfinity/ok/block.run-low.ok similarity index 100% rename from test/run/ok/block.run-low.ok rename to test/run-dfinity/ok/block.run-low.ok diff --git a/test/run/ok/block.run.ok b/test/run-dfinity/ok/block.run.ok similarity index 100% rename from test/run/ok/block.run.ok rename to test/run-dfinity/ok/block.run.ok diff --git a/test/run-dfinity/ok/for-await.dvm-run.ok b/test/run-dfinity/ok/for-await.dvm-run.ok new file mode 100644 index 00000000000..718ae076949 --- /dev/null +++ b/test/run-dfinity/ok/for-await.dvm-run.ok @@ -0,0 +1 @@ +012345678910 diff --git a/test/run-dfinity/ok/for-await.run-ir.ok b/test/run-dfinity/ok/for-await.run-ir.ok new file mode 100644 index 00000000000..718ae076949 --- /dev/null +++ b/test/run-dfinity/ok/for-await.run-ir.ok @@ -0,0 +1 @@ +012345678910 diff --git a/test/run-dfinity/ok/for-await.run-low.ok b/test/run-dfinity/ok/for-await.run-low.ok new file mode 100644 index 00000000000..718ae076949 --- /dev/null +++ b/test/run-dfinity/ok/for-await.run-low.ok @@ -0,0 +1 @@ +012345678910 diff --git a/test/run-dfinity/ok/for-await.run.ok b/test/run-dfinity/ok/for-await.run.ok new file mode 100644 index 00000000000..718ae076949 --- /dev/null +++ b/test/run-dfinity/ok/for-await.run.ok @@ -0,0 +1 @@ +012345678910 diff --git a/test/run/for.as b/test/run/for.as index 42dbace9ea8..15a83cf5266 100644 --- a/test/run/for.as +++ b/test/run/for.as @@ -1,24 +1,7 @@ -let _ = -async { - -{ var i = 0; - for (j in range(0, 10)) { - printNat(j); - assert(j == i); - i += 1; - }; - assert(i == 11); -}; - -{ - var i = 0; - i := 0; - for (j in range(0, 10)) { - printNat(j); - assert(j == i); - await (async (i += 1)); - }; - assert(i == 11); -}; - +var i = 0; +for (j in range(0, 10)) { + printNat(j); + assert(j == i); + i += 1; }; +assert(i == 11); diff --git a/test/run/ok/await.wasm-run.ok b/test/run/ok/await.wasm-run.ok deleted file mode 100644 index da185acef49..00000000000 --- a/test/run/ok/await.wasm-run.ok +++ /dev/null @@ -1 +0,0 @@ -_out/await.wasm:0x___: runtime trap: unreachable executed diff --git a/test/run/ok/block.wasm-run.ok b/test/run/ok/block.wasm-run.ok deleted file mode 100644 index fcc79ff8676..00000000000 --- a/test/run/ok/block.wasm-run.ok +++ /dev/null @@ -1 +0,0 @@ -_out/block.wasm:0x___: runtime trap: unreachable executed diff --git a/test/run/ok/for.run-ir.ok b/test/run/ok/for.run-ir.ok index 0b36fe95ae6..718ae076949 100644 --- a/test/run/ok/for.run-ir.ok +++ b/test/run/ok/for.run-ir.ok @@ -1 +1 @@ -012345678910012345678910 +012345678910 diff --git a/test/run/ok/for.run-low.ok b/test/run/ok/for.run-low.ok index 0b36fe95ae6..718ae076949 100644 --- a/test/run/ok/for.run-low.ok +++ b/test/run/ok/for.run-low.ok @@ -1 +1 @@ -012345678910012345678910 +012345678910 diff --git a/test/run/ok/for.run.ok b/test/run/ok/for.run.ok index 0b36fe95ae6..718ae076949 100644 --- a/test/run/ok/for.run.ok +++ b/test/run/ok/for.run.ok @@ -1 +1 @@ -012345678910012345678910 +012345678910 From 6663c7b54c479aa6fd2df69edd8cd5f0afb04a23 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Tue, 3 Sep 2019 13:44:19 +0200 Subject: [PATCH 0361/1176] Fix typo in function types (#632) --- design/IDL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/design/IDL.md b/design/IDL.md index 486210cd031..806c81d0851 100644 --- a/design/IDL.md +++ b/design/IDL.md @@ -937,7 +937,7 @@ T(:) = leb128() I() T : -> i8* T(func (*) -> (*) *) = - sleb128(-22) T*(*) T*(*) T*(*) + sleb128(-22) T*(*) T*(*) T*(*) T(service {*}) = sleb128(-23) T*(*) From 7f6d0b9e9a1274662004ed25f01802a3cebe94bc Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Tue, 3 Sep 2019 21:26:16 +0200 Subject: [PATCH 0362/1176] Typo in argument list (#633) * fix a typo --- design/IDL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/design/IDL.md b/design/IDL.md index 806c81d0851..e7b3e78ef9b 100644 --- a/design/IDL.md +++ b/design/IDL.md @@ -1059,7 +1059,7 @@ A(kv* : *) = ( B(kv* : *), R(kv* : *) ) B(kv* : *) = i8('D') i8('I') i8('D') i8('L') magic number T*(*) type definition table - I*(*) type of argument list + I*(*) types of the argument list M(kv* : *) values of argument list ``` The vector `T*(*)` contains an arbitrary sequence of type definitions (see above), to be referenced in the serialisation of the other `` vector. From 1afe9c44040f5244a5d65a4a7b68f8e3aed403d4 Mon Sep 17 00:00:00 2001 From: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> Date: Wed, 4 Sep 2019 23:59:57 +0200 Subject: [PATCH 0363/1176] [ACT-128] Caches declaration index in LSP (#631) * makes sure single file file paths are normalized correctly * populate index from all actorscript files underneath the current dir Also returns compiler errors encountered when chasing imports, rather than crashing * repopulate index after successful compilation * uses the chached index in the various handlers --- src/languageServer/completion.ml | 9 ++-- src/languageServer/declaration_index.ml | 58 ++++++++++++++----------- src/languageServer/definition.ml | 3 +- src/languageServer/hover.ml | 4 +- src/languageServer/languageServer.ml | 12 ++++- src/pipeline/file_path_test.ml | 3 ++ 6 files changed, 51 insertions(+), 38 deletions(-) diff --git a/src/languageServer/completion.ml b/src/languageServer/completion.ml index 38d99e93642..0232cb7a6d0 100644 --- a/src/languageServer/completion.ml +++ b/src/languageServer/completion.ml @@ -132,10 +132,7 @@ let find_completion_prefix logger file line column: (string * string) option = | _ -> loop (next ()) in loop (next ()) -(* TODO(Christoph): Don't recompute the index whenever completions are - requested *) -let completions (* index *) logger project_root file_path file_contents line column = - let index = make_index () in +let completions index logger project_root file_path file_contents line column = let imported = parse_module_header project_root file_path file_contents in let module_alias_completion_item alias = Lsp_t.{ @@ -173,8 +170,8 @@ let completions (* index *) logger project_root file_path file_contents line col (* No module with the given prefix was found *) [] -let completion_handler logger project_root file_path file_contents position = +let completion_handler index logger project_root file_path file_contents position = let line = position.Lsp_t.position_line in let column = position.Lsp_t.position_character in `CompletionResponse - (completions logger project_root file_path file_contents line column) + (completions index logger project_root file_path file_contents line column) diff --git a/src/languageServer/declaration_index.ml b/src/languageServer/declaration_index.ml index cd9944118b2..26fc6e8728e 100644 --- a/src/languageServer/declaration_index.ml +++ b/src/languageServer/declaration_index.ml @@ -3,6 +3,8 @@ open As_def open Source open Syntax +let flat_map f xs = List.flatten (List.map f xs) + type value_decl = { name : string; typ: Type.typ; @@ -81,12 +83,17 @@ let string_of_index index = ^ string_of_list string_of_ide_decl decls ^ "\n") -let lib_files () : string list = - let lib_dir = "lib" in - Sys.readdir lib_dir - |> Array.to_list +let project_files () : string list = + let rec read_dir d = + if Sys.is_directory d + then + let entries = + Array.to_list (Sys.readdir d) + |> List.map (fun file -> Filename.concat d file) in + flat_map read_dir entries + else [d] in + read_dir "." |> List.filter (fun file -> String.equal (Filename.extension file) ".as") - |> List.map (fun file -> Filename.concat lib_dir file) let read_single_module_lib (ty: Type.typ): ide_decl list option = match ty with @@ -108,7 +115,6 @@ let unwrap_module_ast (prog : Syntax.dec list): Syntax.exp_field list option = Some fields | _ -> None -let flat_map f xs = List.flatten (List.map f xs) let populate_definitions (libraries : Syntax.libraries) @@ -155,24 +161,24 @@ let populate_definitions | Some (_, prog) -> List.map (find_def prog.it) decls -let make_index_inner () : declaration_index = - let (libraries, scope) = - Diag.run - (Pipeline.chase_imports - Pipeline.initial_stat_env - (Pipeline__.Resolve_import.S.of_list (lib_files ()))) in - Type.Env.fold - (fun path ty acc -> - Index.add - path - (ty - |> read_single_module_lib - |> Lib.Fun.flip Lib.Option.get [] - |> populate_definitions libraries path) - acc) - scope.Scope.lib_env - Index.empty - -let make_index () : declaration_index = +let make_index_inner () : declaration_index Diag.result = + let entry_points = project_files () in + Pipeline.chase_imports + Pipeline.initial_stat_env + (Pipeline__.Resolve_import.S.of_list entry_points) + |> Diag.map (fun (libraries, scope) -> + Type.Env.fold + (fun path ty acc -> + Index.add + path + (ty + |> read_single_module_lib + |> Lib.Fun.flip Lib.Option.get [] + |> populate_definitions libraries path) + acc) + scope.Scope.lib_env + Index.empty) + +let make_index () : declaration_index Diag.result = (* TODO(Christoph): Actually handle errors here *) - try make_index_inner () with _ -> Index.empty + try make_index_inner () with _ -> Diag.return Index.empty diff --git a/src/languageServer/definition.ml b/src/languageServer/definition.ml index b6bad98192b..f6cc1622d9a 100644 --- a/src/languageServer/definition.ml +++ b/src/languageServer/definition.ml @@ -13,12 +13,11 @@ let range_of_region (at : Source.region) : Lsp.range = Lsp. } let definition_handler - (* index *) + index position file_contents project_root file_path = - let index = Declaration_index.make_index () in let result = Lib.Option.bind (Source_file.identifier_at_pos diff --git a/src/languageServer/hover.ml b/src/languageServer/hover.ml index ded9f96d055..aab4e1da47d 100644 --- a/src/languageServer/hover.ml +++ b/src/languageServer/hover.ml @@ -10,9 +10,7 @@ let hover_detail = function Printf.sprintf "public type %s%s" ty.name params -let hover_handler (* index *) position file_contents project_root file_path = - (* TODO(Christoph): Don't rebuild index on every hover *) - let index = make_index () in +let hover_handler index position file_contents project_root file_path = let hover_result = Lib.Option.bind (Source_file.identifier_at_pos diff --git a/src/languageServer/languageServer.ml b/src/languageServer/languageServer.ml index 0e4e71b749c..374e0a36ce1 100644 --- a/src/languageServer/languageServer.ml +++ b/src/languageServer/languageServer.ml @@ -112,7 +112,11 @@ let start () = let project_root = Sys.getcwd () in let vfs = ref Vfs.empty in - + let decl_index = + let ix = match Declaration_index.make_index () with + | Error(err) -> Declaration_index.Index.empty + | Ok((ix, _)) -> ix in + ref ix in let rec loop () = let clength = read_line () in log_to_file "content-length" clength; @@ -180,6 +184,7 @@ let start () = | Some file_content -> let result = Hover.hover_handler + !decl_index position file_content project_root @@ -202,6 +207,7 @@ let start () = | Some file_content -> let result = Definition.definition_handler + !decl_index position file_content project_root @@ -222,6 +228,9 @@ let start () = let msgs = match result with | Error msgs' -> msgs' | Ok (_, msgs') -> msgs' in + (match Declaration_index.make_index () with + | Error(err) -> () + | Ok((ix, _)) -> decl_index := ix); Lib.Fun.flip Lib.Option.iter !client_capabilities (fun _ -> (* TODO: determine if the client accepts diagnostics with related info *) (* let textDocument = capabilities.client_capabilities_textDocument in @@ -250,6 +259,7 @@ let start () = ; message = "Tried to find completions for a file that hadn't been opened yet"} | Some file_content -> Completion.completion_handler + !decl_index log_to_file project_root (abs_file_from_uri log_to_file uri) diff --git a/src/pipeline/file_path_test.ml b/src/pipeline/file_path_test.ml index da2294f7e6e..ea66a0d40f4 100644 --- a/src/pipeline/file_path_test.ml +++ b/src/pipeline/file_path_test.ml @@ -19,6 +19,9 @@ let relative_to_test_case root contained expected = (show actual); false) +let%test "it removes leading current directory" = + normalise_test_case "./ListClient.as" "ListClient.as" + let%test "it removes leading `./` for relative paths" = normalise_test_case "./lib/foo" "lib/foo" From 68b21015ee83473bea312e850e4730d6b2e5ea9e Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 6 Sep 2019 16:14:53 +0200 Subject: [PATCH 0364/1176] Implement serialization of `Any` (#637) now that we have `reserved` in the IDL. Note that there is no full subtyping support in the IDL decoder yet. Fixes #636 --- src/codegen/compile.ml | 7 +++++++ test/run-dfinity/async-any.as | 1 + 2 files changed, 8 insertions(+) create mode 100644 test/run-dfinity/async-any.as diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 008bf36f67c..c708447288a 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -3541,6 +3541,7 @@ module Serialization = struct size_word env (get_x ^^ Heap.load_field Text.len_field) ^^ inc_data_size (get_x ^^ Heap.load_field Text.len_field) | Prim Null -> G.nop + | Any -> G.nop | Opt t -> inc_data_size (compile_unboxed_const 1l) ^^ (* one byte tag *) get_x ^^ Opt.is_some env ^^ @@ -3661,6 +3662,7 @@ module Serialization = struct write env t ) | Prim Null -> G.nop + | Any -> G.nop | Opt t -> get_x ^^ Opt.is_some env ^^ @@ -3802,6 +3804,11 @@ module Serialization = struct | Prim Null -> assert_prim_typ () ^^ Opt.null + | Any -> + (* TODO: Accept actually any type, and skip its values *) + assert_prim_typ () ^^ + (* We can return essentially any value here *) + Opt.null | Prim Text -> assert_prim_typ () ^^ let (set_len, get_len) = new_local env "len" in diff --git a/test/run-dfinity/async-any.as b/test/run-dfinity/async-any.as new file mode 100644 index 00000000000..7e405dd4ecf --- /dev/null +++ b/test/run-dfinity/async-any.as @@ -0,0 +1 @@ +async { ():Any }; From 60aa0925039e73d0edb17c22544d5b5f488fdc54 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Mon, 9 Sep 2019 16:39:06 +0100 Subject: [PATCH 0365/1176] modify async lowering to support Platform V2 (#640) * modify async lowering to support Platform V2 (extracted from claudio/rejects branch) * Update src/ir_passes/async.ml * tidy * tidy sys_callE * restory lazy translation --- src/ir_passes/async.ml | 132 ++++++++++++++++++++++++++++++----------- 1 file changed, 98 insertions(+), 34 deletions(-) diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index 1798704574f..7ec32092c21 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -11,14 +11,12 @@ open T open Construct (* lower the async type itself - - adds a final callback argument to every awaitable shared function, replace + - adds a final reply argument to every awaitable shared function, replace the result by unit - - transforms types, introductions and eliminations awaitable shared + - transforms types, introductions and eliminations of awaitable shared functions only, leaving non-awaitable shared functions unchanged. - ensures every call to an awaitable shared function that takes a tuple has - a manifest tuple argument. - - (for debugging, the `flattening` function can be used to disable argument flattening and use uniform pairing instead) + a manifest tuple argument extended with a final reply continuation. *) (* written as a functor so we can allocate some temporary shared state without making it global *) @@ -40,6 +38,50 @@ module Transform() = struct let con_renaming = ref ConRenaming.empty + (* Configuring the translation for target platform V1 or V2 *) + + type platform = + V1 (* legacy, Haskell *) + | V2 (* new, Rust *) + + let platform = V1 + + let _ = V2 (* suppress warning on unused V2 *) + + (* Lowering options, specific to V1 or V2 *) + + let add_reply_parameter, add_reply_argument = + match platform with + | V1 -> (true, true) + | V2 -> (false, true) + + (* Helper for selective code generation based on predicated lazy expressions *) + let rec select bls = + match bls with + | [] -> [] + | (true, l)::bls' -> + (Lazy.force l)::select bls' + | (false, _)::bls' -> + select bls' + + (* Explicit invocation of reply and call System API functions; + implemented (as far as possible) for V1; + TBC for V2 *) + + let sys_replyE vs = + match platform with + | V1 -> assert false (* never required in V1, `reply` is by calling continuation*) + | V2 -> failwith "NYI" (* TODO: call dedicated prim *) + + let sys_callE v1 typs vs reply = + match platform with + | V1 -> + assert add_reply_argument; + callE v1 typs (seqE (vs @ [reply])) + | V2 -> failwith "NYI" (* TODO: call dedicated prim, separating args vs from reply *) + + (* End of configuration *) + let unary typ = [typ] let nary typ = T.as_seq typ @@ -49,9 +91,9 @@ module Transform() = struct let fulfillT as_seq typ = T.Func(T.Local, T.Returns, [], as_seq typ, []) let t_async as_seq t = - T.Func (T.Local, T.Returns, [], [T.Func(T.Local, T.Returns, [],as_seq t,[])], []) + T.Func (T.Local, T.Returns, [], [fulfillT as_seq t], []) - let new_async_ret as_seq t = [t_async as_seq t;fulfillT as_seq t] + let new_async_ret as_seq t = [t_async as_seq t; fulfillT as_seq t] let new_asyncT = T.Func ( @@ -69,10 +111,10 @@ module Transform() = struct let call_new_async = callE new_asyncE [t1] (tupE []) in let async = fresh_var "async" (typ (projE call_new_async 0)) in let fulfill = fresh_var "fulfill" (typ (projE call_new_async 1)) in - (async,fulfill),call_new_async + (async, fulfill), call_new_async let new_nary_async_reply t1 = - let (unary_async,unary_fulfill),call_new_async = new_async t1 in + let (unary_async, unary_fulfill), call_new_async = new_async t1 in let v' = fresh_var "v" t1 in let ts1 = T.as_seq t1 in (* construct the n-ary async value, coercing the continuation, if necessary *) @@ -83,9 +125,9 @@ module Transform() = struct unary_async | ts -> let seq_of_v' = tupE (List.mapi (fun i _ -> projE v' i) ts) in - k' --> (unary_async -*- ([v'] -->* (k' -*- seq_of_v'))) + [k'] -->* (unary_async -*- ([v'] -->* (k' -*- seq_of_v'))) in - (* construct the n-ary reply message that sends a sequence of value to fulfill the async *) + (* construct the n-ary reply message that sends a sequence of values to fulfill the async *) let nary_reply = let vs,seq_of_vs = match ts1 with @@ -96,11 +138,16 @@ module Transform() = struct let vs = fresh_vars "rep" ts in vs, tupE vs in - vs -@>* (unary_fulfill -*- seq_of_vs) + vs -@>* (unary_fulfill -*- seq_of_vs) in - let async,reply = fresh_var "async" (typ nary_async), fresh_var "fulfill" (typ nary_reply) in - (async,reply),blockE [letP (tupP [varP unary_async; varP unary_fulfill]) call_new_async] - (tupE [nary_async; nary_reply]) + + let async, reply = + fresh_var "async" (typ nary_async), + fresh_var "reply" (typ nary_reply) + in + (async, reply), + blockE [letP (tupP [varP unary_async; varP unary_fulfill]) call_new_async] + (tupE [nary_async; nary_reply]) let letEta e scope = @@ -114,7 +161,7 @@ module Transform() = struct | T.Func (T.Shared,T.Promises,_,_,[T.Async _]) -> true | _ -> false - let extendTup ts t2 = ts @ [t2] + let extendTup ts ts' = ts @ ts' (* Given sequence type ts, bind e of type (seq ts) to a sequence of expressions supplied to decs d_of_es, @@ -154,7 +201,11 @@ module Transform() = struct | [Async t2] -> assert (c = T.Promises); Func (s, T.Returns, List.map t_bind tbs, - extendTup (List.map t_typ t1) (replyT nary (t_typ t2)), []) + extendTup (List.map t_typ t1) + (select + [ add_reply_parameter, lazy (replyT nary (t_typ t2)) + ]), + []) | _ -> assert false end | T.Local -> @@ -235,28 +286,28 @@ module Transform() = struct ArrayE (mut, t_typ t, List.map t_exp exps) | IdxE (exp1, exp2) -> IdxE (t_exp exp1, t_exp exp2) - | PrimE (OtherPrim "@await", [a;k]) -> - ((t_exp a) -*- (t_exp k)).it + | PrimE (OtherPrim "@await", [a;kr]) -> + ((t_exp a) -*- (t_exp kr)).it | PrimE (OtherPrim "@async", [exp2]) -> let t1, contT = match typ exp2 with | Func(_,_, [], - [Func(_,_,[],ts1,[]) as contT], + [Func(_, _, [], ts1, []) as contT], []) -> (* TBR, why isn't this []? *) (t_typ (T.seq ts1),t_typ contT) | t -> assert false in let k = fresh_var "k" contT in let v1 = fresh_var "v" t1 in - let post = fresh_var "post" (T.Func(T.Shared,T.Returns,[],[],[])) in + let post = fresh_var "post" (T.Func(T.Shared, T.Returns, [], [], [])) in let u = fresh_var "u" T.unit in - let ((nary_async,nary_reply),def) = new_nary_async_reply t1 in + let ((nary_async, nary_reply), def) = new_nary_async_reply t1 in (blockE [letP (tupP [varP nary_async; varP nary_reply]) def; funcD k v1 (nary_reply -*- v1); funcD post u (t_exp exp2 -*- k); - expD (post -*- tupE[])] + expD (post -*- tupE [])] nary_async ).it - | CallE (cc,exp1, typs, exp2) when isAwaitableFunc exp1 -> + | CallE (cc, exp1, typs, exp2) when isAwaitableFunc exp1 -> let ts1,t2 = match typ exp1 with | T.Func (T.Shared,T.Promises,tbs,ts1,[T.Async t2]) -> @@ -266,28 +317,29 @@ module Transform() = struct let exp1' = t_exp exp1 in let exp2' = t_exp exp2 in let typs = List.map t_typ typs in - let ((nary_async,nary_reply),def) = new_nary_async_reply t2 in + let ((nary_async, nary_reply), def) = new_nary_async_reply t2 in let _ = letEta in (blockE ( letP (tupP [varP nary_async; varP nary_reply]) def :: letEta exp1' (fun v1 -> letSeq ts1 exp2' (fun vs -> - [ expD (callE v1 typs (seqE (vs@[nary_reply]))) ] + [ expD (sys_callE v1 typs vs nary_reply) ] + ) ) - ) - ) - nary_async) + ) + nary_async) .it | PrimE (p, exps) -> PrimE (prim p, List.map t_exp exps) | CallE (cc, exp1, typs, exp2) -> - CallE(cc, t_exp exp1, List.map t_typ typs, t_exp exp2) + assert (not (isAwaitableFunc exp1)); + CallE (cc, t_exp exp1, List.map t_typ typs, t_exp exp2) | BlockE b -> BlockE (t_block b) | IfE (exp1, exp2, exp3) -> IfE (t_exp exp1, t_exp exp2, t_exp exp3) | SwitchE (exp1, cases) -> let cases' = List.map - (fun {it = {pat;exp}; at; note} -> + (fun {it = {pat; exp}; at; note} -> {it = {pat = t_pat pat ;exp = t_exp exp}; at; note}) cases in @@ -300,7 +352,7 @@ module Transform() = struct BreakE (id, t_exp exp1) | RetE exp1 -> RetE (t_exp exp1) - | AsyncE _ -> assert false + | AsyncE _ | AwaitE _ -> assert false | AssertE exp1 -> AssertE (t_exp exp1) @@ -324,13 +376,25 @@ module Transform() = struct let res_typ = t_typ res_typ in let reply_typ = replyT nary res_typ in let k = fresh_var "k" reply_typ in - let args' = t_args args @ [ arg_of_exp k ] in + let args' = t_args args @ + (select [ add_reply_parameter, lazy (arg_of_exp k); + ]) + in let typbinds' = t_typ_binds typbinds in let y = fresh_var "y" res_typ in let exp' = match exp.it with | PrimE (OtherPrim "@async", [cps]) -> - (t_exp cps) -*- (y --> (k -*- y)) + blockE + (select + [ (not add_reply_parameter, + lazy ( + let vs = List.map (fresh_var "v") (nary res_typ) in + nary_funcD k vs (sys_replyE vs))) + ]) + ((t_exp cps) -*- + (y --> (k -*- y)) + ) | _ -> assert false in FuncE (x, cc', typbinds', args', [], exp') From eb150cf3d02d73510fdb315fad6601b40e6c1bf2 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 10 Sep 2019 15:59:06 +0200 Subject: [PATCH 0366/1176] RTS/IDL: Give more helpful messages in case of an IDL trap (#642) --- rts/bigint.c | 8 ++++---- rts/buf.c | 4 ++-- rts/idl.c | 34 +++++++++++++++++----------------- rts/rts.c | 5 +++++ rts/rts.h | 3 ++- src/codegen/compile.ml | 11 ++++++++++- 6 files changed, 40 insertions(+), 25 deletions(-) diff --git a/rts/bigint.c b/rts/bigint.c index 4fc9bc4f28b..ba9ca6d91c8 100644 --- a/rts/bigint.c +++ b/rts/bigint.c @@ -345,11 +345,11 @@ export as_ptr bigint_leb128_decode(buf *buf) { b = read_byte(buf); if (s > 0 && b == 0x00) { // The high 7 bits are all zeros, this is not a shortest encoding - idl_trap(); + idl_trap_with("not shortest encoding"); } if (s + 7 < s) { // shift overflow. number is absurdly large anyways - idl_trap(); + idl_trap_with("absurdly large number"); } mp_set_u32(&tmp, (b & (uint8_t)0x7f)); CHECK(mp_mul_2d(&tmp, s, &tmp)); @@ -371,11 +371,11 @@ export as_ptr bigint_sleb128_decode(buf *buf) { b = read_byte(buf); if (s > 0 && ((!last_sign_bit_set && b == 0x00) || (last_sign_bit_set && b == 0x7F))) { // The high 8 bits are all zeros or ones, so this is not a shortest encoding - idl_trap(); + idl_trap_with("not shortest encoding"); } if (s + 7 < s) { // shift overflow. number is absurdly large anyways - idl_trap(); + idl_trap_with("absurdly large number"); } mp_set_u32(&tmp, (b & (uint8_t)0x7f)); CHECK(mp_mul_2d(&tmp, s, &tmp)); diff --git a/rts/buf.c b/rts/buf.c index 4f4c009c2fa..89ea59c71da 100644 --- a/rts/buf.c +++ b/rts/buf.c @@ -4,12 +4,12 @@ // See comments in buf.h uint8_t read_byte(buf *buf) { - if (buf->p >= buf->e) (idl_trap()); + if (buf->p >= buf->e) (idl_trap_with("byte read out of buffer")); return ((buf->p)++)[0]; } uint32_t read_word(buf *buf) { - if (buf->p + sizeof(uint8_t) > buf->e) (idl_trap()); + if (buf->p + sizeof(uint8_t) > buf->e) (idl_trap_with("word read out of buffer")); uint32_t r = ((uint32_t*)(buf->p))[0]; buf->p += sizeof(uint32_t); return r; diff --git a/rts/idl.c b/rts/idl.c index de8ba01f1e6..7d28052d82f 100644 --- a/rts/idl.c +++ b/rts/idl.c @@ -11,12 +11,12 @@ export uint32_t read_u32_of_leb128(buf *buf) { b = read_byte(buf); if (s > 0 && b == 0x00) { // The high 7 bits is all zeros, this is not a shortest encoding - idl_trap(); + idl_trap_with("not shortest encoding"); } if (s == 28 && !((b & (uint8_t)0xF0) == 0x00)) { // the 5th byte needs to be the last, and it must contribute at most 4 bits // else we have an int overflow - idl_trap(); + idl_trap_with("int overflow"); } r += (b & (uint8_t)0x7f) << s; s += 7; @@ -34,11 +34,11 @@ export int32_t read_i32_of_sleb128(buf *buf) { if (s == 28 && !((b & (uint8_t)0xF0) == 0x00 || (b & (uint8_t)0xF0) == 0x70)) { // the 5th byte needs to be the last, and it must contribute at most 4 bits // else we have an int overflow - idl_trap(); + idl_trap_with("int overflow"); } if (s > 0 && ((!last_sign_bit_set && b == 0x00) || (last_sign_bit_set && b == 0x7F))) { // The high 8 bits are all zeros or ones, so this is not a shortest encoding - idl_trap(); + idl_trap_with("not shortest encoding"); } last_sign_bit_set = (b & (uint8_t)0x40); r += (b & (uint8_t)0x7f) << s; @@ -95,7 +95,7 @@ export int32_t read_i32_of_sleb128(buf *buf) { */ export void parse_idl_header(buf *buf, uint8_t ***typtbl_out, int32_t *main_type_out) { // Magic bytes (DIDL) - if (read_word(buf) != 0x4C444944) idl_trap(); + if (read_word(buf) != 0x4C444944) idl_trap_with("missing magic bytes"); // Create a table for the type description int32_t n_types = read_u32_of_leb128(buf); @@ -103,10 +103,10 @@ export void parse_idl_header(buf *buf, uint8_t ***typtbl_out, int32_t *main_type // read_u32_of_leb128 returns an uint32_t, we want an int32_t here so that the // comparisons below work, so let's make sure we did not wrap around in the // conversion. - if (n_types < 0) { idl_trap(); } + if (n_types < 0) { idl_trap_with("overflow in number of types"); } // Early sanity check - if (&buf->p[n_types] >= buf->e) { idl_trap(); } + if (&buf->p[n_types] >= buf->e) { idl_trap_with("too many types"); } // Go through the table uint8_t **typtbl = (uint8_t **)alloc(n_types * sizeof(uint8_t*)); @@ -114,35 +114,35 @@ export void parse_idl_header(buf *buf, uint8_t ***typtbl_out, int32_t *main_type typtbl[i] = buf->p; int ty = read_i32_of_sleb128(buf); if (ty >= IDL_PRIM_lowest) { - idl_trap(); // illegal + idl_trap_with("type index too high"); // illegal } else if (ty == IDL_CON_opt) { int32_t t = read_i32_of_sleb128(buf); - if (t < IDL_PRIM_lowest || t >= n_types) idl_trap(); + if (t < IDL_PRIM_lowest || t >= n_types) idl_trap_with("type index out of range"); } else if (ty == IDL_CON_vec) { int32_t t = read_i32_of_sleb128(buf); - if (t < IDL_PRIM_lowest || t >= n_types) idl_trap(); + if (t < IDL_PRIM_lowest || t >= n_types) idl_trap_with("type index out of range"); } else if (ty == IDL_CON_record) { for (int n = read_u32_of_leb128(buf); n > 0; n--) { read_u32_of_leb128(buf); int32_t t = read_i32_of_sleb128(buf); - if (t < IDL_PRIM_lowest || t >= n_types) idl_trap(); + if (t < IDL_PRIM_lowest || t >= n_types) idl_trap_with("type index out of range"); } } else if (ty == IDL_CON_variant) { for (int n = read_u32_of_leb128(buf); n > 0; n--) { read_u32_of_leb128(buf); int32_t t = read_i32_of_sleb128(buf); - if (t < IDL_PRIM_lowest || t >= n_types) idl_trap(); + if (t < IDL_PRIM_lowest || t >= n_types) idl_trap_with("type index out of range"); } } else if (ty == IDL_CON_func) { // arg types for (int n = read_u32_of_leb128(buf); n > 0; n--) { int32_t t = read_i32_of_sleb128(buf); - if (t < IDL_PRIM_lowest || t >= n_types) idl_trap(); + if (t < IDL_PRIM_lowest || t >= n_types) idl_trap_with("type index out of range"); } // ret types for (int n = read_u32_of_leb128(buf); n > 0; n--) { int32_t t = read_i32_of_sleb128(buf); - if (t < IDL_PRIM_lowest || t >= n_types) idl_trap(); + if (t < IDL_PRIM_lowest || t >= n_types) idl_trap_with("type index out of range"); } // annotations for (int n = read_u32_of_leb128(buf); n > 0; n--) { @@ -155,16 +155,16 @@ export void parse_idl_header(buf *buf, uint8_t ***typtbl_out, int32_t *main_type (buf->p) += size; // type int32_t t = read_i32_of_sleb128(buf); - if (t < IDL_PRIM_lowest || t >= n_types) idl_trap(); + if (t < IDL_PRIM_lowest || t >= n_types) idl_trap_with("type index out of range"); } } else { // no support for future types yet - idl_trap(); + idl_trap_with("future type"); } } // Now read the main type int32_t t = read_i32_of_sleb128(buf); - if (t < IDL_PRIM_lowest || t >= n_types) idl_trap(); + if (t < IDL_PRIM_lowest || t >= n_types) idl_trap_with("type index out of range"); *typtbl_out = typtbl; *main_type_out = t; diff --git a/rts/rts.c b/rts/rts.c index 154a0db5617..ffa8f0db029 100644 --- a/rts/rts.c +++ b/rts/rts.c @@ -29,6 +29,11 @@ as_ptr as_str_of_cstr(const char * const s) { return r; } +void idl_trap_with(const char *str) { + idl_trap(str, as_strlen(str)); +} + + // This is mostly to test static strings and access to the AS heap const char* RTS_VERSION = "0.1"; diff --git a/rts/rts.h b/rts/rts.h index 5c37d911678..aee0856cf6c 100644 --- a/rts/rts.h +++ b/rts/rts.h @@ -62,10 +62,11 @@ char *alloc(size_t n); /* IDL code */ /*@ assigns \nothing; ensures \false ; */ -from_rts __attribute__ ((noreturn)) void idl_trap(); +from_rts __attribute__ ((noreturn)) void idl_trap(const char* str, size_t n); from_rts __attribute__ ((noreturn)) void bigint_trap(); /** Functions used in multiple modules of the RTS */ export void as_memcpy(char *str1, const char *str2, size_t n); +export __attribute__ ((noreturn)) void idl_trap_with(const char *str1); #endif /* RTS_H */ diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index c708447288a..823c62e3ff4 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -624,7 +624,16 @@ module RTS = struct edesc = nr (FuncExport (nr bigint_trap_fi)) }); let idl_trap_fi = E.add_fun env "idl_trap" ( - Func.of_body env [] [] (fun env -> + Func.of_body env ["str", I32Type; "len", I32Type] [] (fun env -> + begin + if E.mode env = DfinityMode then + let get_str = G.i (LocalGet (nr 0l)) in + let get_len = G.i (LocalGet (nr 1l)) in + get_str ^^ get_len ^^ + E.call_import env "data" "externalize" ^^ + E.call_import env "test" "print" + else G.nop + end ^^ E.trap_with env "IDL error: Unknown error" ) ) in From af5d5b39d4546379c6dae471c660de570857f399 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 10 Sep 2019 12:11:07 +0200 Subject: [PATCH 0367/1176] Refactor serialization this changes the code, still on the old system, to better match what we will be doing in the new system: * All arguments are serialized as a single IDL value. * We represent and pass it as a `databuf`/`elembuf` pair. * No more special-casing of arguments that are just text or just a reference. * No need for the `serialize.as` pass any more. --- design/TmpWireFormat.md | 106 ---- rts/idl.c | 14 +- src/codegen/compile.ml | 499 ++++++------------ src/codegen/instrList.ml | 1 + src/pipeline/pipeline.ml | 3 +- test/run-dfinity/counter2.as | 8 +- test/run-dfinity/hello-world-message.as | 2 +- test/run-dfinity/hello-world-message2.as | 2 +- test/run-dfinity/no-boxed-references.as | 13 - .../ok/counter-class.wasm.stderr.ok | 45 +- test/run-dfinity/ok/counter2.dvm-run.ok | 8 +- .../ok/hello-world-message.dvm-run.ok | 2 +- .../ok/hello-world-message2.dvm-run.ok | 2 +- 13 files changed, 207 insertions(+), 498 deletions(-) delete mode 100644 design/TmpWireFormat.md delete mode 100644 test/run-dfinity/no-boxed-references.as diff --git a/design/TmpWireFormat.md b/design/TmpWireFormat.md deleted file mode 100644 index 253ceb7242b..00000000000 --- a/design/TmpWireFormat.md +++ /dev/null @@ -1,106 +0,0 @@ -Temporary Wire Format -===================== - -This document describes the serializaion format currently used by the -ActorScript runtime, i.e. a mapping from ActorScript types to DFINITY types (= -WebAssembly types + `databuf`, `elmembuf`, `funcref` and `actorref`), and a -mapping between the corresponding values. - -This is a scaffolding tool to prototype applications until we have decided upon -the actual IDL of the system, which will change all that is described here. - -It also does not support all features that we want to support eventually. In -particular, it does not support subtyping. - -Some types have a *specialized argument format* when used directly as a -function arguments, rather than nested inside a data structure. Other types use -the _general argument format (without references)_ or the _general argument -format (with references)_. - -Each argument of a function is serialized separately. If the function is -defined with a list of arguments, these all become arguments of the WebAssembly -function. See the [ActorScript guide](https://hydra.oregon.dfinity.build//job/dfinity-ci-build/actorscript.pr-252/users-guide/latest/download/1/guide/#function-types) for the precise rules for function arities. - - -Specialized argument format: `Text` -------------------------------------- - -A message entry point with an argument of type `Text` is represented as a `databuf` that contains the UTF8-encoded string. - -Note that there is no terminating `\0`, and the length is implicit as the -length of the `databuf`. - -Specialized argument format: `actor {…}` and `shared … -> …` ------------------------------------------------------------- - -A message entry point with an argument of actor type or of shared function type is represented as an `actorref` resp. `funcref.` - -General argument format (without references) --------------------------------------------- - -Arguments with a type that does not mention any reference types (no actors, no -shared functions), are represented as a `databuf`. This `databuf` is generated -by an in-order traversal of the data type. All numbers are in little endian -format. - - * A `Nat` is represented by its shortest [LEB128 encoding] - * An `Int` is represented by its shortest [SLEB128 encoding] - * A `Word64` is represented by 8 bytes. - * A `Word32` is represented by 4 bytes. - * A `Word16` is represented by 2 bytes. - * A `Word8` is represented by 1 byte. - * A `Bool` is represented by 1 byte that is `0` for `false` and `1` for `true`. - * A `Text` is represented by a LEB128-encoded number indicating the length of - the following payload, followed by the payload as a utf8-encoded string (no - trailing `\0`). - * An `Array` is represented by a LEB128-encoded number indicating the number - of entries, followed by the concatenation of the representation of these - entries. - * A `Tuple` is represented by the concatenation of the representation of its - entries. (No need for a length field, as it can be statically determined.) - * An `Object` is represented by the concatenation of the representation of its - fields, sorted by IDL hash of the field name. - (The field names are not serialized, as they are statically known.) - * An `Option` is represented by a single byte `0` if it is `null`, or - otherwise by a single byte `1` followed by the representation of the value - * An empty tuple, the type `Null` and the type `Shared` are represented by - zero bytes. - * A `Variant` with `n` constructors sorted by IDL hash of the constructor name - is represented by a LEB128-encoded number the constructor as a number - `0..n-1`, followed by the payload of the constructor. - -*Example:* The ActorScript value -``` -(null, ?4, "!") : (?Text, ?Int, Text) -``` -is represented as -``` -00 01 04 00 00 00 00 00 00 00 01 21 -``` - -[LEB128 encoding](https://en.wikipedia.org/wiki/LEB128) - -General argument format (with references) ------------------------------------------ - -Argument with a type that mentions reference types (actors or shared functions) -are represented as an `elembuf`: - - * the first entry is a `databuf` contains the data according to the format - above. - * all further entries are the references contained in the data. - -The above format is thus extended with the following case: - - * A reference (`actor`, `shared func`) is represented as zero bytes in the data - buffer, and writing the reference into the next position in `elembuf`. - - -*Example:* The ActorScript value -``` -(null, ?console) : (?actor {}, ?actor {log : Text -> () }) -``` -is represented as -``` -elembuf [databuf [00 01], console] -``` diff --git a/rts/idl.c b/rts/idl.c index 7d28052d82f..d75bc563287 100644 --- a/rts/idl.c +++ b/rts/idl.c @@ -90,10 +90,10 @@ export int32_t read_i32_of_sleb128(buf *buf) { * * returns a pointer to the first byte after the IDL header (via return) * * allocates a type description table, and returns it * (via pointer argument, for lack of multi-value returns in C) - * * returns the type index of the overall value + * * returns a pointer to the beginning of the list of main types * (again via pointer argument, for lack of multi-value returns in C) */ -export void parse_idl_header(buf *buf, uint8_t ***typtbl_out, int32_t *main_type_out) { +export void parse_idl_header(buf *buf, uint8_t ***typtbl_out, uint8_t **main_types_out) { // Magic bytes (DIDL) if (read_word(buf) != 0x4C444944) idl_trap_with("missing magic bytes"); @@ -162,10 +162,12 @@ export void parse_idl_header(buf *buf, uint8_t ***typtbl_out, int32_t *main_type idl_trap_with("future type"); } } - // Now read the main type - int32_t t = read_i32_of_sleb128(buf); - if (t < IDL_PRIM_lowest || t >= n_types) idl_trap_with("type index out of range"); + // Now read the main types + *main_types_out = buf->p; + for (int n = read_u32_of_leb128(buf); n > 0; n--) { + int32_t t = read_i32_of_sleb128(buf); + if (t < IDL_PRIM_lowest || t >= n_types) idl_trap_with("type index out of range"); + } *typtbl_out = typtbl; - *main_type_out = t; } diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 823c62e3ff4..4a1069f2e35 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -57,7 +57,6 @@ module SR = struct type t = | Vanilla | UnboxedTuple of int - | UnboxedRefTuple of int | UnboxedWord64 | UnboxedWord32 | UnboxedReference @@ -3239,33 +3238,25 @@ end (* HeapTraversal *) module Serialization = struct (* - Also see (and update) `design/TmpWireFormat.md`, which documents the format - in a “user-facing” way. - - We have a specific serialization strategy for `Text` and references for - easier interop with the console and the nonce. This is a stop-gap measure - until we have nailed down IDL and Bidirectional Messaging. - The general serialization strategy is as follows: + * We statically generate the IDL type description header. * We traverse the data to calculate the size needed for the data buffer and the reference buffer. * We allocate memory for the data buffer and the reference buffer (this memory area is not referenced, so will be dead with the next GC) - * We traverse the data, in a type-driven way, and copy it to the scratch space. - We thread through pointers to the current free space of the two scratch spaces. + * We copy the IDL type header to the data buffer. + * We traverse the data and serialize it into the data buffer. This is type driven, and we use the `share_code` machinery and names that properly encode the type to resolve loops in a convenient way. - * We externalize all that new data space into a databuf, and add this reference - to the reference space. + * We externalize all that new data space into a databuf * We externalize the reference space into a elembuf - - TODO: Cycles are not detected. + * We pass both databuf and elembuf to shared functions + (this mimicks the future system API) The deserialization is analogous: - * We allocate some scratch space, and internalize the elembuf into it. - * We allocate some more scratch space, and internalize the databuf into it. + * We allocate some scratch space, and internalize the databuf and elembuf into it. * We parse the data, in a type-driven way, using normal construction and - allocation. + allocation, while keeping tabs on the type description header for subtyping. * At the end, the scratch space is a hole in the heap, and will be reclaimed by the next GC. *) @@ -3278,7 +3269,8 @@ module Serialization = struct - It needs to be injective wrt. type equality - It needs to terminate, even for recursive types - It may fail upon type parameters (i.e. no polymorphism) - We can use string_of_typ here for now, it seems. + We can use string_of_typ here for now, it seems, but eventually we + want something more efficient and compact and less fragile. *) let typ_id : Type.typ -> string = Type.string_of_typ @@ -3287,41 +3279,6 @@ module Serialization = struct (fun (h1,_) (h2,_) -> Lib.Uint32.compare h1 h2) (List.map (fun f -> (Idllib.IdlHash.idl_hash f.Type.lab, f)) fs) - (* Checks whether the serialization of a given type could contain references *) - module TS = Set.Make (struct type t = Type.typ let compare = compare end) - let has_no_references : Type.typ -> bool = fun t -> - let open Type in - let seen = ref TS.empty in (* break the cycles *) - let rec go t = - TS.mem t !seen || - begin - seen := TS.add t !seen; - match t with - | Var _ -> assert false - | (Prim _ | Any | Non | Pre) -> true - | Con (c, ts) -> - begin match Con.kind c with - | Abs _ -> assert false - | Def (tbs,t) -> go (open_ ts t) (* TBR this may fail to terminate *) - end - | Array t -> go t - | Tup ts -> List.for_all go ts - | Func (Shared, c, tbs, ts1, ts2) -> false - | Func (s, c, tbs, ts1, ts2) -> - let ts = open_binds tbs in - List.for_all go (List.map (open_ ts) ts1) && - List.for_all go (List.map (open_ ts) ts2) - | Opt t -> go t - | Variant fs -> List.for_all (fun f -> go f.typ) fs - | Async t -> go t - | Obj (Actor, fs) -> false - | Obj (_, fs) -> List.for_all (fun f -> go f.typ) fs - | Mut t -> go t - | Serialized t -> go t - | Typ _ -> false - end - in go t - (* TODO (leb128 for i32): All leb128 currently goes through bignum. This is of course absurdly expensive and round-about, but I want _one_ implementation @@ -3362,7 +3319,7 @@ module Serialization = struct | Non -> Some 17 | _ -> None - let type_desc t : string = + let type_desc ts : string = let open Type in (* Type traversal *) @@ -3371,9 +3328,7 @@ module Serialization = struct let typs = ref [] in let idx = ref TM.empty in let rec go t = - let t = normalize t in - let t = match t with Serialized t -> t | _ -> t in - let t = normalize t in + let t = Type.normalize t in if to_idl_prim t <> None then () else if TM.mem t !idx then () else begin idx := TM.add t (List.length !typs) !idx; @@ -3392,7 +3347,7 @@ module Serialization = struct assert false end in - go t; + List.iter go ts; (!typs, !idx) in @@ -3428,9 +3383,7 @@ module Serialization = struct (* Actual binary data *) let add_idx t = - let t = normalize t in - let t = match t with Serialized t -> t | _ -> t in - let t = normalize t in + let t = Type.normalize t in match to_idl_prim t with | Some i -> add_sleb128 (-i) | None -> add_sleb128 (TM.find (normalize t) idx) in @@ -3483,13 +3436,14 @@ module Serialization = struct Buffer.add_string buf "DIDL"; add_leb128 (List.length typs); List.iter add_typ typs; - add_idx (normalize t); + add_leb128 (List.length ts); + List.iter add_idx ts; Buffer.contents buf (* Returns data (in bytes) and reference buffer size (in entries) needed *) let rec buffer_size env t = let open Type in - let t = normalize t in + let t = Type.normalize t in let name = "@buffer_size<" ^ typ_id t ^ ">" in Func.share_code1 env name ("x", I32Type) [I32Type; I32Type] (fun env get_x -> @@ -3579,7 +3533,7 @@ module Serialization = struct (* Copies x to the data_buffer, storing references after ref_count entries in ref_base *) let rec serialize_go env t = let open Type in - let t = normalize t in + let t = Type.normalize t in let name = "@serialize_go<" ^ typ_id t ^ ">" in Func.share_code3 env name (("x", I32Type), ("data_buffer", I32Type), ("ref_buffer", I32Type)) [I32Type; I32Type] (fun env get_x get_data_buf get_ref_buf -> @@ -3916,196 +3870,114 @@ module Serialization = struct end ) - let serialize env t = - let name = "@serialize<" ^ typ_id t ^ ">" in - Func.share_code1 env name ("x", I32Type) [I32Type] (fun env get_x -> - match Type.normalize t with - (* Special-cased formats for scaffolding *) - | Type.Prim Type.Text -> get_x ^^ Dfinity.compile_databuf_of_text env - | Type.Obj (Type.Actor, _) - | Type.Func (Type.Shared, _, _, _, _) -> get_x ^^ Dfinity.unbox_reference env - (* normal format *) - | _ -> - let (set_data_size, get_data_size) = new_local env "data_size" in - let (set_refs_size, get_refs_size) = new_local env "refs_size" in - - let tydesc = type_desc t in - let tydesc_len = Int32.of_int (String.length tydesc) in - - (* Get object sizes *) - get_x ^^ - buffer_size env t ^^ - compile_add_const 1l ^^ (* Leave space for databuf *) - compile_mul_const Heap.word_size ^^ - set_refs_size ^^ - - compile_add_const tydesc_len ^^ - set_data_size ^^ - - let (set_data_start, get_data_start) = new_local env "data_start" in - let (set_refs_start, get_refs_start) = new_local env "refs_start" in - - get_data_size ^^ Text.dyn_alloc_scratch env ^^ set_data_start ^^ - get_refs_size ^^ Text.dyn_alloc_scratch env ^^ set_refs_start ^^ - - (* Write ty desc *) - get_data_start ^^ - Text.lit env tydesc ^^ Text.payload_ptr_unskewed ^^ - compile_unboxed_const tydesc_len ^^ - Heap.memcpy env ^^ - - (* Serialize x into the buffer *) - get_x ^^ - get_data_start ^^ compile_add_const tydesc_len ^^ - get_refs_start ^^ compile_add_const Heap.word_size ^^ (* Leave space for databuf *) - serialize_go env t ^^ - - (* Sanity check: Did we fill exactly the buffer *) - get_refs_start ^^ get_refs_size ^^ G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ - G.i (Compare (Wasm.Values.I32 I32Op.Eq)) ^^ - E.else_trap_with env "reference buffer not filled " ^^ - - get_data_start ^^ get_data_size ^^ G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ - G.i (Compare (Wasm.Values.I32 I32Op.Eq)) ^^ - E.else_trap_with env "data buffer not filled " ^^ - - (* Create databuf, and store at beginning of ref area *) - get_refs_start ^^ - get_data_start ^^ - get_data_size ^^ - Dfinity.system_call env "data" "externalize" ^^ - store_unskewed_ptr ^^ - - if has_no_references t - then - (* Sanity check: Really no references *) - get_refs_size ^^ - compile_unboxed_const Heap.word_size ^^ - G.i (Compare (Wasm.Values.I32 I32Op.Eq)) ^^ - E.else_trap_with env "has_no_references wrong" ^^ - (* If there are no references, just return the databuf *) - get_refs_start ^^ - load_unskewed_ptr - else - (* Finally, create elembuf *) - get_refs_start ^^ - get_refs_size ^^ compile_divU_const Heap.word_size ^^ - Dfinity.system_call env "elem" "externalize" - ) - - let deserialize_text env get_databuf = - let (set_data_size, get_data_size) = new_local env "data_size" in - let (set_x, get_x) = new_local env "x" in - - get_databuf ^^ - Dfinity.system_call env "data" "length" ^^ - set_data_size ^^ - - get_data_size ^^ - Text.alloc env ^^ - set_x ^^ - - get_x ^^ Text.payload_ptr_unskewed ^^ - get_data_size ^^ - get_databuf ^^ - compile_unboxed_const 0l ^^ - Dfinity.system_call env "data" "internalize" ^^ - - get_x + let serialize env ts : G.t = + let ts_name = String.concat "," (List.map typ_id ts) in + let name = "@serialize<" ^ ts_name ^ ">" in + Func.share_code1 env name ("x", I32Type) [I32Type; I32Type] (fun env get_x -> + let (set_data_size, get_data_size) = new_local env "data_size" in + let (set_refs_size, get_refs_size) = new_local env "refs_size" in + let tydesc = type_desc ts in + let tydesc_len = Int32.of_int (String.length tydesc) in - let deserialize env t = - let name = "@deserialize<" ^ typ_id t ^ ">" in - Func.share_code1 env name ("elembuf", I32Type) [I32Type] (fun env get_elembuf -> - match Type.normalize t with - | Type.Prim Type.Text -> deserialize_text env get_elembuf - | Type.Obj (Type.Actor, _) - | Type.Func (Type.Shared, _, _, _, _) -> get_elembuf ^^ Dfinity.box_reference env - | _ -> - let (set_data_size, get_data_size) = new_local env "data_size" in - let (set_refs_size, get_refs_size) = new_local env "refs_size" in - let (set_data_start, get_data_start) = new_local env "data_start" in - let (set_refs_start, get_refs_start) = new_local env "refs_start" in - let (set_databuf, get_databuf) = new_local env "databuf" in - - begin - if has_no_references t - then - (* We have no elembuf wrapper, so the argument is the databuf *) - compile_unboxed_const 0l ^^ set_refs_start ^^ - get_elembuf ^^ set_databuf - else - (* Allocate space for the elem buffer *) - get_elembuf ^^ - Dfinity.system_call env "elem" "length" ^^ - set_refs_size ^^ - - get_refs_size ^^ - Arr.alloc env ^^ - compile_add_const Arr.header_size ^^ - compile_add_const ptr_unskew ^^ - set_refs_start ^^ - - (* Copy elembuf *) - get_refs_start ^^ - get_refs_size ^^ - get_elembuf ^^ - compile_unboxed_const 0l ^^ - Dfinity.system_call env "elem" "internalize" ^^ - - (* Get databuf *) - get_refs_start ^^ - load_unskewed_ptr ^^ - set_databuf - end ^^ + (* Get object sizes *) + get_x ^^ + buffer_size env (Type.seq ts) ^^ + compile_mul_const Heap.word_size ^^ + set_refs_size ^^ - (* Allocate space for the data buffer *) - get_databuf ^^ - Dfinity.system_call env "data" "length" ^^ - set_data_size ^^ + compile_add_const tydesc_len ^^ + set_data_size ^^ - get_data_size ^^ Text.dyn_alloc_scratch env ^^ set_data_start ^^ + let (set_data_start, get_data_start) = new_local env "data_start" in + let (set_refs_start, get_refs_start) = new_local env "refs_start" in - (* Copy data *) - get_data_start ^^ - get_data_size ^^ - get_databuf ^^ - compile_unboxed_const 0l ^^ - Dfinity.system_call env "data" "internalize" ^^ + get_data_size ^^ Text.dyn_alloc_scratch env ^^ set_data_start ^^ + get_refs_size ^^ Text.dyn_alloc_scratch env ^^ set_refs_start ^^ - (* Allocate space for out parameters of parse_idl_header *) - Stack.with_words env "get_typtbl_ptr" 1l (fun get_typtbl_ptr -> - Stack.with_words env "get_maintyp_ptr" 1l (fun get_maintyp_ptr -> + (* Write ty desc *) + get_data_start ^^ + Text.lit env tydesc ^^ Text.payload_ptr_unskewed ^^ + compile_unboxed_const tydesc_len ^^ + Heap.memcpy env ^^ + (* Serialize x into the buffer *) + get_x ^^ + get_data_start ^^ compile_add_const tydesc_len ^^ + get_refs_start ^^ + serialize_go env (Type.seq ts) ^^ - (* Set up read buffers *) - ReadBuf.alloc env (fun get_data_buf -> ReadBuf.alloc env (fun get_ref_buf -> + (* Sanity check: Did we fill exactly the buffer *) + get_refs_start ^^ get_refs_size ^^ G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ + G.i (Compare (Wasm.Values.I32 I32Op.Eq)) ^^ + E.else_trap_with env "reference buffer not filled " ^^ - ReadBuf.set_ptr get_data_buf get_data_start ^^ - ReadBuf.set_size get_data_buf get_data_size ^^ - ReadBuf.set_ptr get_ref_buf (get_refs_start ^^ compile_add_const Heap.word_size) ^^ - ReadBuf.set_size get_ref_buf (get_refs_size ^^ compile_sub_const 1l ^^ compile_mul_const Heap.word_size) ^^ + get_data_start ^^ get_data_size ^^ G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ + G.i (Compare (Wasm.Values.I32 I32Op.Eq)) ^^ + E.else_trap_with env "data buffer not filled " ^^ - (* Go! *) - get_data_buf ^^ get_typtbl_ptr ^^ get_maintyp_ptr ^^ - E.call_import env "rts" "parse_idl_header" ^^ + (* Store it all in a databuf and an elembuf *) + get_data_start ^^ get_data_size ^^ + Dfinity.system_call env "data" "externalize" ^^ - get_data_buf ^^ get_ref_buf ^^ - get_typtbl_ptr ^^ load_unskewed_ptr ^^ - get_maintyp_ptr ^^ load_unskewed_ptr ^^ - deserialize_go env t - )))) + get_refs_start ^^ get_refs_size ^^ + Dfinity.system_call env "elem" "externalize" ) - let dfinity_type t = - let open As_types.Type in - let open Wasm_exts.CustomModule in - match normalize t with - | Prim Text -> DataBuf - | Obj (Actor, _) -> ActorRef - | Func (Shared, _, _, _, _) -> FuncRef - | t' when has_no_references t' -> DataBuf - | _ -> ElemBuf + let deserialize env ts = + let ts_name = String.concat "," (List.map typ_id ts) in + let name = "@deserialize<" ^ ts_name ^ ">" in + Func.share_code2 env name (("databuf",I32Type),("elembuf", I32Type)) (List.map (fun _ -> I32Type) ts) (fun env get_databuf get_elembuf -> + let (set_data_size, get_data_size) = new_local env "data_size" in + let (set_refs_size, get_refs_size) = new_local env "refs_size" in + let (set_data_start, get_data_start) = new_local env "data_start" in + let (set_refs_start, get_refs_start) = new_local env "refs_start" in + + (* Allocate space for the data buffer and copy it *) + get_databuf ^^ Dfinity.system_call env "data" "length" ^^ set_data_size ^^ + get_data_size ^^ Text.dyn_alloc_scratch env ^^ set_data_start ^^ + get_data_start ^^ get_data_size ^^ get_databuf ^^ compile_unboxed_const 0l ^^ + Dfinity.system_call env "data" "internalize" ^^ + + (* Allocate space for the reference buffer and copy it *) + get_elembuf ^^ Dfinity.system_call env "elem" "length" ^^ set_refs_size ^^ + get_refs_size ^^ compile_mul_const Heap.word_size ^^ Text.dyn_alloc_scratch env ^^ set_refs_start ^^ + get_refs_start ^^ get_refs_size ^^ get_elembuf ^^ compile_unboxed_const 0l ^^ + Dfinity.system_call env "elem" "internalize" ^^ + + (* Allocate space for out parameters of parse_idl_header *) + Stack.with_words env "get_typtbl_ptr" 1l (fun get_typtbl_ptr -> + Stack.with_words env "get_maintyps_ptr" 1l (fun get_maintyps_ptr -> + + (* Set up read buffers *) + ReadBuf.alloc env (fun get_data_buf -> ReadBuf.alloc env (fun get_ref_buf -> + + ReadBuf.set_ptr get_data_buf get_data_start ^^ + ReadBuf.set_size get_data_buf get_data_size ^^ + ReadBuf.set_ptr get_ref_buf get_refs_start ^^ + ReadBuf.set_size get_ref_buf (get_refs_size ^^ compile_mul_const Heap.word_size) ^^ + + (* Go! *) + get_data_buf ^^ get_typtbl_ptr ^^ get_maintyps_ptr ^^ + E.call_import env "rts" "parse_idl_header" ^^ + + (* set up a dedicated read buffer for the list of main types *) + ReadBuf.alloc env (fun get_main_typs_buf -> + ReadBuf.set_ptr get_main_typs_buf (get_maintyps_ptr ^^ load_unskewed_ptr) ^^ + ReadBuf.set_end get_main_typs_buf (ReadBuf.get_end get_data_buf) ^^ + + (* read count *) + ReadBuf.read_leb128 env get_main_typs_buf ^^ + compile_eq_const (Int32.of_int (List.length ts)) ^^ + E.else_trap_with env ("IDL error: wrong arity parsing " ^ ts_name) ^^ + G.concat_map (fun t -> + get_data_buf ^^ get_ref_buf ^^ + get_typtbl_ptr ^^ load_unskewed_ptr ^^ + ReadBuf.read_sleb128 env get_main_typs_buf ^^ + deserialize_go env t + ) ts + ) + ))))) end (* Serialization *) @@ -4342,9 +4214,6 @@ module StackRep = struct let of_arity n = if n = 1 then Vanilla else UnboxedTuple n - let refs_of_arity n = - if n = 1 then UnboxedReference else UnboxedRefTuple n - (* The stack rel of a primitive type, i.e. what the binary operators expect *) let of_type t = let open Type in @@ -4366,10 +4235,6 @@ module StackRep = struct | UnboxedTuple 1 -> ValBlockType (Some I32Type) | UnboxedTuple n when not !Flags.multi_value -> assert false | UnboxedTuple n -> VarBlockType (nr (E.func_type env (FuncType ([], Lib.List.make n I32Type)))) - | UnboxedRefTuple 0 -> ValBlockType None - | UnboxedRefTuple 1 -> ValBlockType (Some I32Type) - | UnboxedRefTuple n when not !Flags.multi_value -> assert false - | UnboxedRefTuple n -> VarBlockType (nr (E.func_type env (FuncType ([], Lib.List.make n I32Type)))) | StaticThing _ -> ValBlockType None | Unreachable -> ValBlockType None @@ -4379,7 +4244,6 @@ module StackRep = struct | UnboxedWord32 -> "UnboxedWord32" | UnboxedReference -> "UnboxedReference" | UnboxedTuple n -> Printf.sprintf "UnboxedTuple %d" n - | UnboxedRefTuple n -> Printf.sprintf "UnboxedRefTuple %d" n | Unreachable -> "Unreachable" | StaticThing _ -> "StaticThing" @@ -4413,7 +4277,6 @@ module StackRep = struct | UnboxedWord32 -> G.i Drop | UnboxedReference -> G.i Drop | UnboxedTuple n -> G.table n (fun _ -> G.i Drop) - | UnboxedRefTuple n -> G.table n (fun _ -> G.i Drop) | StaticThing _ -> G.nop | Unreachable -> G.nop @@ -4435,33 +4298,7 @@ module StackRep = struct Dfinity.static_message_funcref env fi ^^ Dfinity.box_reference env - let unbox_reference_n env n = match n with - | 0 -> G.nop - | 1 -> Dfinity.unbox_reference env - | _ -> - let name = Printf.sprintf "unbox_reference_n %i" n in - let args = Lib.List.table n (fun i -> Printf.sprintf "arg%i" i, I32Type) in - let retty = Lib.List.make n I32Type in - Func.share_code env name args retty (fun env -> - G.table n (fun i -> - G.i (LocalGet (nr (Int32.of_int i))) ^^ Dfinity.unbox_reference env - ) - ) - - let box_reference_n env n = match n with - | 0 -> G.nop - | 1 -> Dfinity.box_reference env - | _ -> - let name = Printf.sprintf "box_reference_n %i" n in - let args = Lib.List.table n (fun i -> Printf.sprintf "arg%i" i, I32Type) in - let retty = Lib.List.make n I32Type in - Func.share_code env name args retty (fun env -> - G.table n (fun i -> - G.i (LocalGet (nr (Int32.of_int i))) ^^ Dfinity.box_reference env - ) - ) - - let rec adjust env (sr_in : t) sr_out = + let adjust env (sr_in : t) sr_out = if sr_in = sr_out then G.nop else match sr_in, sr_out with @@ -4471,15 +4308,6 @@ module StackRep = struct | UnboxedTuple n, Vanilla -> Tuple.from_stack env n | Vanilla, UnboxedTuple n -> Tuple.to_stack env n - | UnboxedRefTuple n, UnboxedTuple m when n = m -> box_reference_n env n - | UnboxedTuple n, UnboxedRefTuple m when n = m -> unbox_reference_n env n - - | UnboxedRefTuple n, sr -> - box_reference_n env n ^^ adjust env (UnboxedTuple n) sr - | sr, UnboxedRefTuple n -> - adjust env sr (UnboxedTuple n) ^^ unbox_reference_n env n - - | UnboxedWord64, Vanilla -> BoxedWord64.box env | Vanilla, UnboxedWord64 -> BoxedWord64.unbox env @@ -4554,6 +4382,16 @@ module ASEnv = struct E.add_local_name env i name; ({ ae with vars = NameEnv.add name (VarLoc.Local i) ae.vars }, i) + (* Adds the names to the environment and returns a list of setters *) + let rec add_argument_locals env (ae : t) = function + | [] -> (ae, []) + | (name :: names) -> + let i = E.add_anon_local env I32Type in + E.add_local_name env i name; + let ae' = { ae with vars = NameEnv.add name (VarLoc.Local i) ae.vars } in + let (ae_final, setters) = add_argument_locals env ae' names + in (ae_final, G.i (LocalSet (nr i)) :: setters) + let in_scope_set (ae : t) = NameEnv.fold (fun k _ -> Freevars.S.add k) ae.vars Freevars.S.empty @@ -4661,9 +4499,9 @@ module FuncDec = struct (* The type of messages *) let message_ty env cc = - E.func_type env (FuncType (Lib.List.make cc.Call_conv.n_args I32Type,[])) + E.func_type env (FuncType ([I32Type; I32Type], [])) - (* Expects all arguments on the stack, in serialized form. *) + (* Expects databuf and elembuf on the stack, in serialized form. *) let call_funcref env cc get_ref = compile_unboxed_const tmp_table_slot ^^ (* slot number *) get_ref ^^ (* the unboxed funcref *) @@ -4726,10 +4564,12 @@ module FuncDec = struct - Fake orthogonal persistence *) let compile_message outer_env outer_ae cc restore_env args mk_body at = - let arg_names = List.map (fun a -> a.it, I32Type) args in assert (cc.Call_conv.n_res = 0); let ae0 = ASEnv.mk_fun_ae outer_ae in - Func.of_body outer_env (["clos", I32Type] @ arg_names) [] (fun env -> G.with_region at ( + Func.of_body outer_env ["clos", I32Type; "databuf", I32Type; "elembuf", I32Type] [] (fun env -> G.with_region at ( + let get_databuf = G.i (LocalGet (nr 1l)) in + let get_elembuf = G.i (LocalGet (nr 2l)) in + (* Restore memory *) OrthogonalPersistence.restore_mem env ^^ @@ -4741,10 +4581,13 @@ module FuncDec = struct let (ae1, closure_code) = restore_env env ae0 get_closure in - (* Add arguments to the environment, as unboxed references *) - let ae2 = bind_args ae1 1 args (fun ae a get -> - ASEnv.add_local_deferred ae a.it SR.UnboxedReference (fun _ -> get) true - ) in + (* Deserialize argument and add params to the environment *) + let arg_names = List.map (fun a -> a.it) args in + let arg_tys = List.map (fun a -> a.note) args in + let (ae2, setters) = ASEnv.add_argument_locals env ae1 arg_names in + get_databuf ^^ get_elembuf ^^ + Serialization.deserialize env arg_tys ^^ + G.concat (List.rev setters) ^^ closure_code ^^ mk_body env ae2 ^^ @@ -4756,20 +4599,23 @@ module FuncDec = struct OrthogonalPersistence.save_mem env )) - let compile_static_message outer_env outer_ae cc args mk_body at : E.func_with_names = - let arg_names = List.map (fun a -> a.it, I32Type) args in + let compile_static_message outer_env outer_ae cc args mk_body ret_tys at : E.func_with_names = assert (cc.Call_conv.n_res = 0); let ae0 = ASEnv.mk_fun_ae outer_ae in - (* Messages take no closure, return nothing *) - Func.of_body outer_env arg_names [] (fun env -> + Func.of_body outer_env ["databuf", I32Type; "elembuf", I32Type] [] (fun env -> G.with_region at ( + let get_databuf = G.i (LocalGet (nr 0l)) in + let get_elembuf = G.i (LocalGet (nr 1l)) in + (* Set up memory *) OrthogonalPersistence.restore_mem env ^^ - (* Add arguments to the environment, as unboxed references *) - let ae1 = bind_args ae0 0 args (fun ae a get -> - ASEnv.add_local_deferred ae a.it SR.UnboxedReference (fun _ -> get) true - ) in - + (* Deserialize argument and add params to the environment *) + let arg_names = List.map (fun a -> a.it) args in + let arg_tys = List.map (fun a -> a.note) args in + let (ae1, setters) = ASEnv.add_argument_locals env ae0 arg_names in + get_databuf ^^ get_elembuf ^^ + Serialization.deserialize env arg_tys ^^ + G.concat (List.rev setters) ^^ mk_body env ae1 ^^ (* Collect garbage *) @@ -4777,24 +4623,22 @@ module FuncDec = struct (* Save memory *) OrthogonalPersistence.save_mem env - ) + )) - let declare_dfinity_type env has_closure fi args = + let declare_dfinity_type env has_closure fi = E.add_dfinity_type env (fi, (if has_closure then [ Wasm_exts.CustomModule.I32 ] else []) @ - List.map ( - fun a -> Serialization.dfinity_type (Type.as_serialized a.note) - ) args + [ Wasm_exts.CustomModule.DataBuf; Wasm_exts.CustomModule.ElemBuf ] ) (* Compile a closed function declaration (captures no local variables) *) - let closed pre_env cc name args mk_body at = + let closed pre_env cc name args mk_body ret_tys at = let (fi, fill) = E.reserve_fun pre_env name in if cc.Call_conv.sort = Type.Shared then begin - declare_dfinity_type pre_env false fi args; + declare_dfinity_type pre_env false fi ; ( SR.StaticMessage fi, fun env ae -> - fill (compile_static_message env ae cc args mk_body at) + fill (compile_static_message env ae cc args mk_body ret_tys at) ) end else ( SR.StaticFun fi, fun env ae -> @@ -4839,7 +4683,7 @@ module FuncDec = struct let fi = E.add_fun env name f in - if not is_local then declare_dfinity_type env true fi args; + if not is_local then declare_dfinity_type env true fi; let code = (* Allocate a heap object for the closure *) @@ -4879,12 +4723,12 @@ module FuncDec = struct ClosureTable.remember_closure env ^^ Dfinity.system_call env "func" "bind_i32" - let lit env ae how name cc free_vars args mk_body at = + let lit env ae how name cc free_vars args mk_body ret_tys at = let captured = List.filter (ASEnv.needs_capture ae) free_vars in if captured = [] then - let (st, fill) = closed env cc name args mk_body at in + let (st, fill) = closed env cc name args mk_body ret_tys at in fill env ae; (SR.StaticThing st, G.nop) else closure env ae cc name captured args mk_body at @@ -5839,6 +5683,7 @@ and compile_exp (env : E.t) ae exp = (* Special prims *) + (* | SerializePrim t, [e] -> SR.UnboxedReference, compile_exp_vanilla env ae e ^^ @@ -5848,6 +5693,7 @@ and compile_exp (env : E.t) ae exp = SR.Vanilla, compile_exp_as env ae SR.UnboxedReference e ^^ Serialization.deserialize env t + *) (* Numeric conversions *) | NumConvPrim (t1, t2), [e] -> begin @@ -6174,7 +6020,11 @@ and compile_exp (env : E.t) ae exp = let (set_funcref, get_funcref) = new_local env "funcref" in code1 ^^ StackRep.adjust env fun_sr SR.UnboxedReference ^^ set_funcref ^^ - compile_exp_as env ae (StackRep.refs_of_arity cc.Call_conv.n_args) e2 ^^ + compile_exp_as env ae SR.Vanilla e2 ^^ + (* We can try to avoid the boxing and pass the arguments to + serialize individually *) + let _, _, _, ts, _ = Type.as_func e1.note.note_typ in + Serialization.serialize env ts ^^ FuncDec.call_funcref env cc get_funcref end | SwitchE (e, cs) -> @@ -6205,10 +6055,10 @@ and compile_exp (env : E.t) ae exp = SR.unit, compile_exp_vanilla env ae e ^^ Var.set_val env ae name - | FuncE (x, cc, typ_binds, args, _rt, e) -> + | FuncE (x, cc, typ_binds, args, ret_tys, e) -> let captured = Freevars.captured exp in let mk_body env1 ae1 = compile_exp_as env1 ae1 (StackRep.of_arity cc.Call_conv.n_res) e in - FuncDec.lit env ae typ_binds x cc captured args mk_body exp.at + FuncDec.lit env ae typ_binds x cc captured args mk_body ret_tys exp.at | ActorE (i, ds, fs, _) -> SR.UnboxedReference, let captured = Freevars.exp exp in @@ -6230,10 +6080,6 @@ and compile_exp_as env ae sr_out e = G.with_region e.at ( match sr_out, e.it with (* Some optimizations for certain sr_out and expressions *) - | SR.UnboxedRefTuple n, TupE es when n = List.length es -> - G.concat_map (fun e -> - compile_exp_as env ae SR.UnboxedReference e - ) es | _ , BlockE (decs, exp) -> let captured = Freevars.captured_vars (Freevars.exp exp) in let (ae', code1) = compile_decs env ae AllocHow.NotTopLvl decs captured in @@ -6538,14 +6384,14 @@ and compile_prog env ae (ds, e) = (ae', code1 ^^ code2) and compile_static_exp env pre_ae how exp = match exp.it with - | FuncE (name, cc, typ_binds, args, _rt, e) -> + | FuncE (name, cc, typ_binds, args, ret_tys, e) -> let mk_body env ae = assert begin (* Is this really closed? *) List.for_all (fun v -> ASEnv.NameEnv.mem v ae.ASEnv.vars) (Freevars.M.keys (Freevars.exp e)) end; compile_exp_as env ae (StackRep.of_arity cc.Call_conv.n_res) e in - FuncDec.closed env cc name args mk_body exp.at + FuncDec.closed env cc name args mk_body ret_tys exp.at | _ -> assert false and compile_prelude env ae = @@ -6617,12 +6463,7 @@ and export_actor_field env ae (f : Ir.field) = | _ -> assert false in (* There should be no code associated with this *) assert (G.is_nop code); - let _, _, _, ts, _ = Type.as_func f.note in - E.add_dfinity_type env (fi, - List.map ( - fun t -> Serialization.dfinity_type (Type.as_serialized t) - ) ts - ); + FuncDec.declare_dfinity_type env false fi; E.add_export env (nr { name = Wasm.Utf8.decode f.it.name; edesc = nr (FuncExport (nr fi)) diff --git a/src/codegen/instrList.ml b/src/codegen/instrList.ml index 1de783e74a8..3644936b837 100644 --- a/src/codegen/instrList.ml +++ b/src/codegen/instrList.ml @@ -78,6 +78,7 @@ let (^^) (is1 : t) (is2 : t) : t = fun d pos rest -> is1 d pos (is2 d pos rest) let i (instr : instr') : t = fun _ pos rest -> (instr @@ pos) :: rest (* map and concat *) +let concat xs = List.fold_right (^^) xs nop let concat_map f xs = List.fold_right (^^) (List.map f xs) nop let concat_mapi f xs = List.fold_right (^^) (List.mapi f xs) nop let table n f = List.fold_right (^^) (Lib.List.table n f) nop diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index 0a54eb778f2..647dea7c5ab 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -454,7 +454,7 @@ let await_lowering = let async_lowering = transform_if "Async Lowering" Async.transform -let serialization = +let _serialization = transform_if "Synthesizing serialization code" Serialization.transform let tailcall_optimization = @@ -499,7 +499,6 @@ let lower_prog senv lib_env libraries progs name = let prog_ir = desugar senv lib_env libraries progs name in let prog_ir = await_lowering !Flags.await_lowering initial_stat_env prog_ir name in let prog_ir = async_lowering !Flags.async_lowering initial_stat_env prog_ir name in - let prog_ir = serialization !Flags.await_lowering initial_stat_env prog_ir name in let prog_ir = tailcall_optimization true initial_stat_env prog_ir name in let prog_ir = show_translation true initial_stat_env prog_ir name in prog_ir diff --git a/test/run-dfinity/counter2.as b/test/run-dfinity/counter2.as index c04514bc38a..fed194e2ba2 100644 --- a/test/run-dfinity/counter2.as +++ b/test/run-dfinity/counter2.as @@ -8,7 +8,7 @@ actor { printNat c; print "\n"; } } -//CALL inc -//CALL inc -//CALL inc -//CALL printCounter +//CALL inc 0x4449444C0000 [] +//CALL inc 0x4449444C0000 [] +//CALL inc 0x4449444C0000 [] +//CALL printCounter 0x4449444C0000 [] diff --git a/test/run-dfinity/hello-world-message.as b/test/run-dfinity/hello-world-message.as index 73608dd9731..9fc8fef1623 100644 --- a/test/run-dfinity/hello-world-message.as +++ b/test/run-dfinity/hello-world-message.as @@ -4,4 +4,4 @@ actor { } } -//CALL hello +//CALL hello 0x4449444C0000 [] diff --git a/test/run-dfinity/hello-world-message2.as b/test/run-dfinity/hello-world-message2.as index b177bac179c..25fa661eb50 100644 --- a/test/run-dfinity/hello-world-message2.as +++ b/test/run-dfinity/hello-world-message2.as @@ -4,4 +4,4 @@ actor hello_world { } } -//CALL hello +//CALL hello 0x4449444C0000 [] diff --git a/test/run-dfinity/no-boxed-references.as b/test/run-dfinity/no-boxed-references.as deleted file mode 100644 index 95003e5e9e9..00000000000 --- a/test/run-dfinity/no-boxed-references.as +++ /dev/null @@ -1,13 +0,0 @@ -// No unboxing between the start of foo and the call to serialize -// CHECK: (func $foo -// CHECK-NOT: box_reference -// CHECK: call $@deserialize -shared func foo(a : Text, b: Int) {}; - -// No boxing between the call to serialize and the indirect call -// CHECK: (func $start -// CHECK: call $@serialize -// CHECK-NOT: box_reference -// CHECK: call_indirect -foo("a", 42); - diff --git a/test/run-dfinity/ok/counter-class.wasm.stderr.ok b/test/run-dfinity/ok/counter-class.wasm.stderr.ok index c2f74b31a4d..d7e972aef47 100644 --- a/test/run-dfinity/ok/counter-class.wasm.stderr.ok +++ b/test/run-dfinity/ok/counter-class.wasm.stderr.ok @@ -21,43 +21,28 @@ non-closed actor: (ActorE (FuncE read (shared 1 -> 0) - (params $k/0/raw) + (params $k/0) () - (BlockE - (LetD - (TupP (VarP $k/0)) - (TupE - (PrimE - (DeserializePrim shared (serialized Int) -> ()) - (VarE $k/0/raw) - ) - ) + (CallE + (1 -> 0) + (FuncE + $lambda + (1 -> 0) + (params $cont/0) + () + (CallE (1 -> 0) (VarE $cont/0) (VarE j)) ) - (CallE + (FuncE + $lambda (1 -> 0) - (FuncE - $lambda - (1 -> 0) - (params $cont/0) - () - (CallE (1 -> 0) (VarE $cont/0) (VarE j)) - ) - (FuncE - $lambda - (1 -> 0) - (params $y/0) - () - (CallE - (shared 1 -> 0) - (VarE $k/0) - (PrimE (SerializePrim Int) (VarE $y/0)) - ) - ) + (params $y/0) + () + (CallE (shared 1 -> 0) (VarE $k/0) (VarE $y/0)) ) ) ) ) (read read) (dec dec) - actor {dec : shared () -> (); read : shared (serialized shared (serialized Int) -> ()) -> ()} + actor {dec : shared () -> (); read : shared (shared Int -> ()) -> ()} ) diff --git a/test/run-dfinity/ok/counter2.dvm-run.ok b/test/run-dfinity/ok/counter2.dvm-run.ok index 9f2f46495c3..ec8e4cf0a6f 100644 --- a/test/run-dfinity/ok/counter2.dvm-run.ok +++ b/test/run-dfinity/ok/counter2.dvm-run.ok @@ -1,8 +1,8 @@ -DVM: Calling method inc +DVM: Calling method inc 0x4449444C0000 [] 2 -DVM: Calling method inc +DVM: Calling method inc 0x4449444C0000 [] 3 -DVM: Calling method inc +DVM: Calling method inc 0x4449444C0000 [] 4 -DVM: Calling method printCounter +DVM: Calling method printCounter 0x4449444C0000 [] 4 diff --git a/test/run-dfinity/ok/hello-world-message.dvm-run.ok b/test/run-dfinity/ok/hello-world-message.dvm-run.ok index f01f4492e8f..9d1c9e2b129 100644 --- a/test/run-dfinity/ok/hello-world-message.dvm-run.ok +++ b/test/run-dfinity/ok/hello-world-message.dvm-run.ok @@ -1,2 +1,2 @@ -DVM: Calling method hello +DVM: Calling method hello 0x4449444C0000 [] Hello World! diff --git a/test/run-dfinity/ok/hello-world-message2.dvm-run.ok b/test/run-dfinity/ok/hello-world-message2.dvm-run.ok index f01f4492e8f..9d1c9e2b129 100644 --- a/test/run-dfinity/ok/hello-world-message2.dvm-run.ok +++ b/test/run-dfinity/ok/hello-world-message2.dvm-run.ok @@ -1,2 +1,2 @@ -DVM: Calling method hello +DVM: Calling method hello 0x4449444C0000 [] Hello World! From 4b42b4e95c04d449e2c5692b16365f59c71c7408 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 10 Sep 2019 15:21:14 +0200 Subject: [PATCH 0368/1176] Actually remove the serialization pass code --- src/ir_passes/serialization.ml | 261 -------------------------------- src/ir_passes/serialization.mli | 3 - src/pipeline/pipeline.ml | 3 - 3 files changed, 267 deletions(-) delete mode 100644 src/ir_passes/serialization.ml delete mode 100644 src/ir_passes/serialization.mli diff --git a/src/ir_passes/serialization.ml b/src/ir_passes/serialization.ml deleted file mode 100644 index 6846e4a3e5a..00000000000 --- a/src/ir_passes/serialization.ml +++ /dev/null @@ -1,261 +0,0 @@ -open Ir_def -open As_types - -open Source -open Ir -module T = Type -open Construct - -(* -This transforms - * the types of shared functions to pass ElemBufs (according to their arity) - * shared function definitions to call deserialize on the arguments - * calls to shared functions to call serialize on the arguments -*) - -module Transform() = struct - - module ConRenaming = Env.Make(struct type t = T.con let compare = Con.compare end) - - (* the state *) - - (* maps constructors to new constructors (new name, new stamp, new kind) - it is initialized with the type constructors defined outside here, which are - not rewritten. - - If we run this translation on two program fragments (e.g. prelude and program) - we would have to pass down the `con_renaming`. But this is simply the right thing - to do for a pass that changes the context. - *) - - let con_renaming = ref ConRenaming.empty - - (* The primitive serialization functions *) - let deserialize e = - let t = T.as_serialized e.note.note_typ in - primE (DeserializePrim t) [e] - - let serialize e t = - primE (SerializePrim t) [e] - - let serialized_arg a = - { it = a.it ^ "/raw"; note = T.Serialized a.note; at = a.at } - - let rec map_tuple n f e t = match n, e.it with - | 0, _ -> e - | 1, _ -> f e t - | _, TupE es -> - let ts = T.as_tup t in - assert (List.length es = n); - tupE (List.map2 f es ts) - | _, BlockE (ds, e) -> - blockE ds (map_tuple n f e t) - | _, _ -> - let ts = T.as_tup t in - assert (List.length ts = n); - let vs = fresh_vars "tup" ts in - blockE [letP (seqP (List.map varP vs)) e] - (tupE (List.map2 f vs ts)) - - let rec t_typ (t:T.typ) = - match t with - | T.Prim _ - | T.Any - | T.Non - | T.Pre - | T.Var _ -> t - - | T.Con (c, ts) -> - T.Con (t_con c, List.map t_typ ts) - | T.Array t -> T.Array (t_typ t) - | T.Tup ts -> T.Tup (List.map t_typ ts) - | T.Func (T.Shared, c, tbs, t1, t2) -> - assert (c = T.Returns); - assert (t2 = []); (* A returning sharable function has no return values *) - T.Func (T.Shared, T.Returns, tbs, List.map (fun t -> T.Serialized (t_typ t)) t1, []) - | T.Func (T.Local, c, tbs, t1, t2) -> - T.Func (T.Local, c, List.map t_bind tbs, List.map t_typ t1, List.map t_typ t2) - | T.Opt t -> T.Opt (t_typ t) - | T.Variant fs -> T.(Variant (List.map t_field fs)) - | T.Obj (s, fs) -> T.Obj (s, List.map t_field fs) - | T.Mut t -> T.Mut (t_typ t) - | T.Typ c -> T.Typ (t_con c) (* TBR *) - | T.Serialized t -> assert false (* This transformation should only run once *) - | T.Async t -> assert false (* Should happen after async-translation *) - - and t_bind {T.var; T.bound} = - {T.var; T.bound = t_typ bound} - - and t_binds typbinds = List.map t_bind typbinds - - and t_kind k = - match k with - | T.Abs(typ_binds,typ) -> - T.Abs(t_binds typ_binds, t_typ typ) - | T.Def(typ_binds,typ) -> - T.Def(t_binds typ_binds, t_typ typ) - - and t_con c = - match ConRenaming.find_opt c (!con_renaming) with - | Some c' -> c' - | None -> - let clone = Con.clone c (T.Abs ([], T.Pre)) in - con_renaming := ConRenaming.add c clone (!con_renaming); - (* Need to extend con_renaming before traversing the kind *) - Type.set_kind clone (t_kind (Con.kind c)); - clone - - and t_field {T.lab; T.typ} = - { T.lab; T.typ = t_typ typ } - - let rec t_exp (exp: exp) = - { it = t_exp' exp; - note = { note_typ = t_typ exp.note.note_typ; - note_eff = exp.note.note_eff}; - at = exp.at; - } - and t_exp' (exp:exp) = - let exp' = exp.it in - match exp' with - | CallE (cc, exp1, typs, exp2) -> - begin match cc.Call_conv.sort with - | T.Local -> - CallE(cc, t_exp exp1, List.map t_typ typs, t_exp exp2) - | T.Shared -> - (* We should take the type to serialize at from the function, not the - argument, as the latter could be a subtype *) - let fun_ty = exp1.note.note_typ in - let _, _, t_arg, t_ret = T.as_func_sub cc.Call_conv.sort (List.length typs) fun_ty in - assert (T.is_unit t_ret); - let exp2' = map_tuple cc.Call_conv.n_args serialize (t_exp exp2) (t_typ (T.open_ typs t_arg)) in - CallE (cc, t_exp exp1, [], exp2') - end - | FuncE (x, cc, typbinds, args, ret_tys, exp) -> - begin match cc.Call_conv.sort with - | T.Local -> - FuncE (x, cc, t_typ_binds typbinds, t_args args, List.map t_typ ret_tys, t_exp exp) - | T.Shared -> - assert (ret_tys = []); - let args' = t_args args in - let raw_args = List.map serialized_arg args' in - let body' = - blockE [letP (tupP (List.map varP (List.map exp_of_arg args'))) - (tupE (List.map deserialize (List.map exp_of_arg raw_args))) ] - (t_exp exp) in - FuncE (x, cc, [], raw_args, [], body') - end - | LitE _ -> exp' - | VarE id -> exp' - | PrimE (p, exps) -> - PrimE (p, List.map t_exp exps) - | TupE exps -> - TupE (List.map t_exp exps) - | OptE exp1 -> - OptE (t_exp exp1) - | TagE (i, exp1) -> - TagE (i, t_exp exp1) - | ProjE (exp1, n) -> - ProjE (t_exp exp1, n) - | DotE (exp1, id) -> - DotE (t_exp exp1, id) - | ActorDotE (exp1, id) -> - ActorDotE (t_exp exp1, id) - | AssignE (exp1, exp2) -> - AssignE (t_exp exp1, t_exp exp2) - | ArrayE (mut, t, exps) -> - ArrayE (mut, t_typ t, List.map t_exp exps) - | IdxE (exp1, exp2) -> - IdxE (t_exp exp1, t_exp exp2) - | BlockE b -> - BlockE (t_block b) - | IfE (exp1, exp2, exp3) -> - IfE (t_exp exp1, t_exp exp2, t_exp exp3) - | SwitchE (exp1, cases) -> - let cases' = List.map - (fun {it = {pat;exp}; at; note} -> - {it = {pat = t_pat pat ;exp = t_exp exp}; at; note}) - cases - in - SwitchE (t_exp exp1, cases') - | LoopE exp1 -> - LoopE (t_exp exp1) - | LabelE (id, typ, exp1) -> - LabelE (id, t_typ typ, t_exp exp1) - | BreakE (id, exp1) -> - BreakE (id, t_exp exp1) - | RetE exp1 -> - RetE (t_exp exp1) - | AsyncE _ -> assert false - | AwaitE _ -> assert false - | AssertE exp1 -> - AssertE (t_exp exp1) - | DeclareE (id, typ, exp1) -> - DeclareE (id, t_typ typ, t_exp exp1) - | DefineE (id, mut ,exp1) -> - DefineE (id, mut, t_exp exp1) - | ActorE (id, ds, fs, typ) -> - ActorE (id, t_decs ds, t_fields fs, t_typ typ) - | NewObjE (sort, ids, t) -> - NewObjE (sort, t_fields ids, t_typ t) - - and t_dec dec = { dec with it = t_dec' dec.it } - - and t_dec' dec' = - match dec' with - | TypD con_id -> TypD (t_con con_id) - | LetD (pat,exp) -> LetD (t_pat pat,t_exp exp) - | VarD (id,exp) -> VarD (id,t_exp exp) - - and t_decs decs = List.map t_dec decs - - and t_block (ds, exp) = (t_decs ds, t_exp exp) - - and t_fields fs = - List.map (fun f -> { f with note = t_typ f.note }) fs - - and t_args as_ = - List.map (fun a -> { a with note = t_typ a.note }) as_ - - and t_pat pat = - { pat with - it = t_pat' pat.it; - note = t_typ pat.note } - - and t_pat' pat = - match pat with - | WildP - | LitP _ - | VarP _ -> - pat - | TupP pats -> - TupP (List.map t_pat pats) - | ObjP pfs -> - ObjP (map_obj_pat t_pat pfs) - | OptP pat1 -> - OptP (t_pat pat1) - | TagP (id, pat1) -> - TagP (id, t_pat pat1) - | AltP (pat1, pat2) -> - AltP (t_pat pat1, t_pat pat2) - - and t_typ_bind' {con; bound} = - {con = t_con con; bound = t_typ bound} - - and t_typ_bind typ_bind = - { typ_bind with it = t_typ_bind' typ_bind.it } - - and t_typ_binds typbinds = List.map t_typ_bind typbinds - - and t_prog (prog, flavor) = (t_block prog, { flavor with serialized = true }) - -end - -let transform env prog = - let module T = Transform() in - (* - Initialized the con_renaming with those type constructors already in scope. - Eventually, pipeline will allow us to pass the con_renaming to downstream program - fragments, then we would simply start with an empty con_renaming and the prelude. - *) - Type.ConSet.iter (fun c -> T.con_renaming := T.ConRenaming.add c c (!T.con_renaming)) env.Scope.con_env; - T.t_prog prog diff --git a/src/ir_passes/serialization.mli b/src/ir_passes/serialization.mli deleted file mode 100644 index c25737838df..00000000000 --- a/src/ir_passes/serialization.mli +++ /dev/null @@ -1,3 +0,0 @@ -open Ir_def - -val transform : As_types.Scope.scope -> Ir.prog -> Ir.prog diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index 647dea7c5ab..afaccae2369 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -454,9 +454,6 @@ let await_lowering = let async_lowering = transform_if "Async Lowering" Async.transform -let _serialization = - transform_if "Synthesizing serialization code" Serialization.transform - let tailcall_optimization = transform_if "Tailcall optimization" (fun _ -> Tailcall.transform) From 1aa22db915e19e4037bfd697049aea58b52dbcbf Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 10 Sep 2019 15:26:07 +0200 Subject: [PATCH 0369/1176] Remove the Serialized type and values this was once part of a plan involving the serialized module, but is no longer needed. --- src/as_idl/as_to_idl.ml | 3 +-- src/as_types/arrange_type.ml | 1 - src/as_types/type.ml | 22 +++++----------------- src/as_types/type.mli | 3 --- src/as_values/value.ml | 2 -- src/as_values/value.mli | 2 -- src/codegen/compile.ml | 20 +++----------------- src/ir_def/arrange_ir.ml | 2 -- src/ir_def/check_ir.ml | 23 +---------------------- src/ir_def/construct.ml | 2 -- src/ir_def/ir.ml | 2 -- src/ir_interpreter/interpret_ir.ml | 4 ---- src/ir_passes/async.ml | 3 --- 13 files changed, 10 insertions(+), 79 deletions(-) diff --git a/src/as_idl/as_to_idl.ml b/src/as_idl/as_to_idl.ml index 38f45144674..9fdc0c63ec8 100644 --- a/src/as_idl/as_to_idl.ml +++ b/src/as_idl/as_to_idl.ml @@ -117,8 +117,7 @@ let rec typ vs t = | Func _ -> assert false | Async t -> assert false | Mut t -> assert false - | Serialized t -> assert false - | Pre -> assert false + | Pre -> assert false ) @@ no_region and field vs {lab; typ=t} = match unescape lab with diff --git a/src/as_types/arrange_type.ml b/src/as_types/arrange_type.ml index 1b5208d459e..c0e3b16aee7 100644 --- a/src/as_types/arrange_type.ml +++ b/src/as_types/arrange_type.ml @@ -51,7 +51,6 @@ let rec typ (t:Type.typ) = match t with | Func (s, c, tbs, at, rt) -> "Func" $$ [Atom (func_sort s); Atom (control c)] @ List.map typ_bind tbs @ [ "" $$ (List.map typ at); "" $$ (List.map typ rt)] | Async t -> "Async" $$ [typ t] | Mut t -> "Mut" $$ [typ t] - | Serialized t -> "Serialized" $$ [typ t] | Any -> Atom "Any" | Non -> Atom "Non" | Pre -> Atom "Pre" diff --git a/src/as_types/type.ml b/src/as_types/type.ml index ef127846a3b..eea66fd3812 100644 --- a/src/as_types/type.ml +++ b/src/as_types/type.ml @@ -42,7 +42,6 @@ and typ = | Func of func_sort * control * bind list * typ list * typ list (* function *) | Async of typ (* future *) | Mut of typ (* mutable type *) - | Serialized of typ (* a serialized value *) | Any (* top *) | Non (* bottom *) | Typ of con (* type (field of module) *) @@ -126,7 +125,6 @@ let rec shift i n t = | Obj (s, fs) -> Obj (s, List.map (shift_field n i) fs) | Variant fs -> Variant (List.map (shift_field n i) fs) | Mut t -> Mut (shift i n t) - | Serialized t -> Serialized (shift i n t) | Any -> Any | Non -> Non | Pre -> Pre @@ -173,7 +171,6 @@ let rec subst sigma t = | Obj (s, fs) -> Obj (s, List.map (subst_field sigma) fs) | Variant fs -> Variant (List.map (subst_field sigma) fs) | Mut t -> Mut (subst sigma t) - | Serialized t -> Serialized (subst sigma t) | Any -> Any | Non -> Non | Pre -> Pre @@ -229,7 +226,6 @@ let rec open' i ts t = | Obj (s, fs) -> Obj (s, List.map (open_field i ts) fs) | Variant fs -> Variant (List.map (open_field i ts) fs) | Mut t -> Mut (open' i ts t) - | Serialized t -> Serialized (open' i ts t) | Any -> Any | Non -> Non | Pre -> Pre @@ -301,7 +297,6 @@ let is_pair = function Tup [_; _] -> true | _ -> false let is_func = function Func _ -> true | _ -> false let is_async = function Async _ -> true | _ -> false let is_mut = function Mut _ -> true | _ -> false -let is_serialized = function Serialized _ -> true | _ -> false let is_typ = function Typ _ -> true | _ -> false let invalid s = raise (Invalid_argument ("Type." ^ s)) @@ -318,7 +313,6 @@ let as_func = function Func (s, c, tbs, ts1, ts2) -> s, c, tbs, ts1, ts2 | _ -> let as_async = function Async t -> t | _ -> invalid "as_async" let as_mut = function Mut t -> t | _ -> invalid "as_mut" let as_immut = function Mut t -> t | t -> t -let as_serialized = function Serialized t -> t | _ -> invalid "as_serialized" let as_typ = function Typ c -> c | _ -> invalid "as_typ" let as_seq = function Tup ts -> ts | t -> [t] @@ -405,7 +399,6 @@ let rec span = function | Array _ | Func _ | Any -> None | Opt _ -> Some 2 | Mut t -> span t - | Serialized t -> None | Non -> Some 0 | Typ _ -> Some 1 @@ -442,7 +435,6 @@ let rec avoid' cons seen = function | Obj (s, fs) -> Obj (s, List.map (avoid_field cons seen) fs) | Variant fs -> Variant (List.map (avoid_field cons seen) fs) | Mut t -> Mut (avoid' cons seen t) - | Serialized t -> Serialized (avoid' cons seen t) | Typ c -> if ConSet.mem c cons then raise (Unavoidable c) else Typ c (* TBR *) @@ -477,7 +469,7 @@ let rec cons t cs = | (Prim _ | Any | Non | Pre) -> cs | Con (c, ts) -> List.fold_right cons ts (ConSet.add c cs) - | (Opt t | Async t | Mut t | Serialized t | Array t) -> + | (Opt t | Async t | Mut t | Array t) -> cons t cs | Tup ts -> List.fold_right cons ts cs | Func (s, c, tbs, ts1, ts2) -> @@ -524,7 +516,7 @@ let concrete t = | Abs _ -> false | Def (_, t) -> go (open_ ts t) (* TBR this may fail to terminate *) ) - | Array t | Opt t | Async t | Mut t | Serialized t -> go t + | Array t | Opt t | Async t | Mut t -> go t | Tup ts -> List.for_all go ts | Obj (_, fs) | Variant fs -> List.for_all (fun f -> go f.typ) fs | Func (s, c, tbs, ts1, ts2) -> @@ -551,7 +543,7 @@ let shared t = | Abs _ -> false | Def (_, t) -> go (open_ ts t) (* TBR this may fail to terminate *) ) - | Array t | Opt t | Serialized t -> go t + | Array t | Opt t -> go t | Tup ts -> List.for_all go ts | Obj (s, fs) -> s = Actor || List.for_all (fun f -> go f.typ) fs | Variant fs -> List.for_all (fun f -> go f.typ) fs @@ -637,8 +629,6 @@ let rec rel_typ rel eq t1 t2 = rel_typ rel eq t1' t2' | Mut t1', Mut t2' -> eq_typ rel eq t1' t2' - | Serialized t1', Serialized t2' -> - rel_typ rel eq t1' t2' | Typ c1, Typ c2 -> eq_con eq c1 c2 | _, _ -> false @@ -731,7 +721,7 @@ let rec compatible_typ co t1 t2 = t1 == t2 || SS.mem (t1, t2) !co || begin co := SS.add (t1, t2) !co; match promote t1, promote t2 with - | (Pre | Serialized _), _ | _, (Pre | Serialized _) -> + | Pre, _ | _, Pre -> assert false | Any, Any -> true @@ -800,7 +790,7 @@ let rec inhabited_typ co t = S.mem t !co || begin co := S.add t !co; match promote t with - | Pre | Serialized _ -> assert false + | Pre -> assert false | Non -> false | Any | Prim _ | Array _ | Opt _ | Async _ | Func _ | Typ _ -> true | Mut t' -> inhabited_typ co t' @@ -1124,8 +1114,6 @@ and string_of_typ' vs t = sprintf "= (%s,%s)" (Con.to_string c) (string_of_kind (Con.kind c)) | Mut t -> sprintf "var %s" (string_of_typ' vs t) - | Serialized t -> - sprintf "serialized %s" (string_of_typ' vs t) | t -> string_of_typ_nullary vs t and string_of_field vs {lab; typ} = diff --git a/src/as_types/type.mli b/src/as_types/type.mli index 77344f22f08..531264c0500 100644 --- a/src/as_types/type.mli +++ b/src/as_types/type.mli @@ -42,7 +42,6 @@ and typ = | Func of func_sort * control * bind list * typ list * typ list (* function *) | Async of typ (* future *) | Mut of typ (* mutable type *) - | Serialized of typ (* a serialized value *) | Any (* top *) | Non (* bottom *) | Typ of con (* type (field of module) *) @@ -84,7 +83,6 @@ val is_pair : typ -> bool val is_func : typ -> bool val is_async : typ -> bool val is_mut : typ -> bool -val is_serialized : typ -> bool val is_typ : typ -> bool val as_prim : prim -> typ -> unit @@ -99,7 +97,6 @@ val as_func : typ -> func_sort * control * bind list * typ list * typ list val as_async : typ -> typ val as_mut : typ -> typ val as_immut : typ -> typ -val as_serialized : typ -> typ val as_typ : typ -> con val as_prim_sub : prim -> typ -> unit diff --git a/src/as_values/value.ml b/src/as_values/value.ml index 1b9a884f00a..8fc15121299 100644 --- a/src/as_values/value.ml +++ b/src/as_values/value.ml @@ -289,7 +289,6 @@ and value = | Func of Call_conv.t * func | Async of async | Mut of value ref - | Serialized of value and async = {result : def; mutable waiters : value cont list} and def = value Lib.Promise.t @@ -333,7 +332,6 @@ let as_variant = function Variant (i, v) -> i, v | _ -> invalid "as_variant" let as_tup = function Tup vs -> vs | _ -> invalid "as_tup" let as_unit = function Tup [] -> () | _ -> invalid "as_unit" let as_pair = function Tup [v1; v2] -> v1, v2 | _ -> invalid "as_pair" -let as_serialized = function Serialized v -> v | _ -> invalid "as_serialized" let as_obj = function Obj ve -> ve | _ -> invalid "as_obj" let as_func = function Func (cc, f) -> cc, f | _ -> invalid "as_func" let as_async = function Async a -> a | _ -> invalid "as_async" diff --git a/src/as_values/value.mli b/src/as_values/value.mli index 3931e13192e..1daac9069ea 100644 --- a/src/as_values/value.mli +++ b/src/as_values/value.mli @@ -102,7 +102,6 @@ and value = | Func of Call_conv.t * func | Async of async | Mut of value ref - | Serialized of value and async = {result : def; mutable waiters : value cont list} and def = value Lib.Promise.t @@ -148,7 +147,6 @@ val as_variant : value -> string * value val as_func : value -> Call_conv.t * func val as_async : value -> async val as_mut : value -> value ref -val as_serialized : value -> value (* Ordering *) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 4a1069f2e35..192df78bec1 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -1110,21 +1110,21 @@ module Tagged = struct begin match normalize ty with | (Con _ | Any) -> true | (Array _ | Tup _ | Obj _) -> true - | (Prim _ | Opt _ | Variant _ | Func _ | Serialized _ | Non) -> false + | (Prim _ | Opt _ | Variant _ | Func _ | Non) -> false | (Pre | Async _ | Mut _ | Var _ | Typ _) -> assert false end | Text -> begin match normalize ty with | (Con _ | Any) -> true | (Prim Text | Obj _) -> true - | (Prim _ | Array _ | Tup _ | Opt _ | Variant _ | Func _ | Serialized _ | Non) -> false + | (Prim _ | Array _ | Tup _ | Opt _ | Variant _ | Func _ | Non) -> false | (Pre | Async _ | Mut _ | Var _ | Typ _) -> assert false end | Object -> begin match normalize ty with | (Con _ | Any) -> true | (Obj _) -> true - | (Prim _ | Array _ | Tup _ | Opt _ | Variant _ | Func _ | Serialized _ | Non) -> false + | (Prim _ | Array _ | Tup _ | Opt _ | Variant _ | Func _ | Non) -> false | (Pre | Async _ | Mut _ | Var _ | Typ _) -> assert false end | _ -> true @@ -5681,20 +5681,6 @@ and compile_exp (env : E.t) ae exp = compile_exp_as env ae sr e2 ^^ code - (* Special prims *) - - (* - | SerializePrim t, [e] -> - SR.UnboxedReference, - compile_exp_vanilla env ae e ^^ - Serialization.serialize env t - - | DeserializePrim t, [e] -> - SR.Vanilla, - compile_exp_as env ae SR.UnboxedReference e ^^ - Serialization.deserialize env t - *) - (* Numeric conversions *) | NumConvPrim (t1, t2), [e] -> begin let open Type in diff --git a/src/ir_def/arrange_ir.ml b/src/ir_def/arrange_ir.ml index 311d50dd9d9..da60c1297fd 100644 --- a/src/ir_def/arrange_ir.ml +++ b/src/ir_def/arrange_ir.ml @@ -56,8 +56,6 @@ and prim = function | BinPrim (t, bo) -> "BinPrim" $$ [typ t; Arrange_ops.binop bo] | RelPrim (t, ro) -> "RelPrim" $$ [typ t; Arrange_ops.relop ro] | ShowPrim t -> "ShowPrim" $$ [typ t] - | SerializePrim t -> "SerializePrim" $$ [typ t] - | DeserializePrim t -> "DeserializePrim" $$ [typ t] | NumConvPrim (t1, t2) -> "NumConvPrim" $$ [prim_ty t1; prim_ty t2] | OtherPrim s -> Atom s diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index e26ab8d54d4..6fa1b8cdb66 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -112,10 +112,7 @@ let check_sub env at t1 t2 = (T.string_of_typ_expand t1) (T.string_of_typ_expand t2) let check_shared env at t = - if env.flavor.Ir.serialized - then check env at (T.is_serialized t) - "message argument is not serialized:\n %s" (T.string_of_typ_expand t) - else check env at (T.shared t) + check env at (T.shared t) "message argument is not sharable:\n %s" (T.string_of_typ_expand t) let check_concrete env at t = @@ -192,12 +189,6 @@ let rec check_typ env typ : unit = error env no_region "variant type's fields are not distinct and sorted %s" (T.string_of_typ typ) | T.Mut typ -> check_typ env typ - | T.Serialized typ -> - check env no_region env.flavor.Ir.serialized - "Serialized in non-serialized flavor"; - check_typ env typ; - check env no_region (T.shared typ) - "serialized type is not sharable:\n %s" (T.string_of_typ_expand typ) | T.Typ c -> check_con env c @@ -351,18 +342,6 @@ let rec check_exp env (exp:Ir.exp) : unit = check_exp env exp1; typ exp1 <: ot; T.Prim T.Text <: t - | SerializePrim ot, [exp1] -> - check env.flavor.serialized "Serialized expression in wrong flavor"; - check (T.shared ot) "argument to SerializePrim not shared"; - check_exp env exp1; - typ exp1 <: ot; - T.Serialized ot <: t - | DeserializePrim ot, [exp1] -> - check env.flavor.serialized "Serialized expression in wrong flavor"; - check (T.shared ot) "argument to SerializePrim not shared"; - check_exp env exp1; - typ exp1 <: T.Serialized ot; - ot <: t | OtherPrim _, _ -> () | _ -> error env exp.at "PrimE with wrong number of arguments" diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index b81e3a9dae5..07a53d421a9 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -84,8 +84,6 @@ let as_seqP p = let primE prim es = let ty = match prim with - | DeserializePrim t -> t - | SerializePrim t -> T.Serialized t | ShowPrim _ -> T.text | _ -> assert false (* implement more as needed *) in diff --git a/src/ir_def/ir.ml b/src/ir_def/ir.ml index ce16210cd93..a1f23791b13 100644 --- a/src/ir_def/ir.ml +++ b/src/ir_def/ir.ml @@ -103,8 +103,6 @@ and prim = | BinPrim of Type.typ * binop (* binary operator *) | RelPrim of Type.typ * relop (* relational operator *) | ShowPrim of Type.typ (* debug show *) - | SerializePrim of Type.typ (* serialize *) - | DeserializePrim of Type.typ (* deserialize *) | NumConvPrim of Type.prim * Type.prim | OtherPrim of string (* Other primitive operation, no custom typing rule *) diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index 222605beb33..b94e0860ebf 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -317,10 +317,6 @@ and interpret_exp_mut env exp (k : V.value V.cont) = if Show.can_show ot then k (Value.Text (Show.show_val ot v)) else raise (Invalid_argument "debug_show")) - | SerializePrim t, [exp1] -> - interpret_exp env exp1 (fun v -> k (V.Serialized v)) - | DeserializePrim t, [exp1] -> - interpret_exp env exp1 (fun v -> k (V.as_serialized v)) | OtherPrim s, exps -> interpret_exps env exps [] (fun vs -> let at = exp.at in diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index 7ec32092c21..f43770f42c0 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -216,7 +216,6 @@ module Transform() = struct | Async t -> t_async nary (t_typ t) | Obj (s, fs) -> Obj (s, List.map t_field fs) | Mut t -> Mut (t_typ t) - | Serialized t -> Serialized (t_typ t) | Any -> Any | Non -> Non | Pre -> Pre @@ -249,8 +248,6 @@ module Transform() = struct | BinPrim (ot, op) -> BinPrim (t_typ ot, op) | RelPrim (ot, op) -> RelPrim (t_typ ot, op) | ShowPrim ot -> ShowPrim (t_typ ot) - | SerializePrim ot -> SerializePrim (t_typ ot) - | DeserializePrim ot -> DeserializePrim (t_typ ot) | NumConvPrim (t1,t2) -> NumConvPrim (t1,t2) | OtherPrim s -> OtherPrim s From f783a0008537e1653f9321d33e9c820bb9131a31 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 11 Sep 2019 21:19:31 +0100 Subject: [PATCH 0370/1176] fix for async.ml to avoid creating local shared function on new platform (#644) * fix for async.ml to avoid creating local shared function on new platform * Update src/ir_passes/async.ml Co-Authored-By: Joachim Breitner --- src/ir_passes/async.ml | 23 ++++++++----------- .../ok/counter-class.wasm.stderr.ok | 6 ++--- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index f43770f42c0..c238689d5a2 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -68,7 +68,7 @@ module Transform() = struct implemented (as far as possible) for V1; TBC for V2 *) - let sys_replyE vs = + let sys_replyE v = match platform with | V1 -> assert false (* never required in V1, `reply` is by calling continuation*) | V2 -> failwith "NYI" (* TODO: call dedicated prim *) @@ -372,26 +372,21 @@ module Transform() = struct let cc' = Call_conv.message_cc (cc.Call_conv.n_args + 1) in let res_typ = t_typ res_typ in let reply_typ = replyT nary res_typ in - let k = fresh_var "k" reply_typ in + let r = fresh_var "r" reply_typ in let args' = t_args args @ - (select [ add_reply_parameter, lazy (arg_of_exp k); + (select [ add_reply_parameter, lazy (arg_of_exp r); ]) in let typbinds' = t_typ_binds typbinds in - let y = fresh_var "y" res_typ in let exp' = match exp.it with | PrimE (OtherPrim "@async", [cps]) -> - blockE - (select - [ (not add_reply_parameter, - lazy ( - let vs = List.map (fresh_var "v") (nary res_typ) in - nary_funcD k vs (sys_replyE vs))) - ]) - ((t_exp cps) -*- - (y --> (k -*- y)) - ) + let v = fresh_var "v" res_typ in + let k = if add_reply_parameter then + (v --> (r -*- v)) (* wrap shared function in local function *) + else + (v --> (sys_replyE v)) in + t_exp cps -*- k | _ -> assert false in FuncE (x, cc', typbinds', args', [], exp') diff --git a/test/run-dfinity/ok/counter-class.wasm.stderr.ok b/test/run-dfinity/ok/counter-class.wasm.stderr.ok index d7e972aef47..c3830263b38 100644 --- a/test/run-dfinity/ok/counter-class.wasm.stderr.ok +++ b/test/run-dfinity/ok/counter-class.wasm.stderr.ok @@ -21,7 +21,7 @@ non-closed actor: (ActorE (FuncE read (shared 1 -> 0) - (params $k/0) + (params $r/0) () (CallE (1 -> 0) @@ -35,9 +35,9 @@ non-closed actor: (ActorE (FuncE $lambda (1 -> 0) - (params $y/0) + (params $v/0) () - (CallE (shared 1 -> 0) (VarE $k/0) (VarE $y/0)) + (CallE (shared 1 -> 0) (VarE $r/0) (VarE $v/0)) ) ) ) From 0526e672db01ab2a05db1190a4804e8d5f7966ff Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 12 Sep 2019 11:21:15 +0200 Subject: [PATCH 0371/1176] Check_ir: Descend into the decs in an `ActorE` (#647) --- src/ir_def/check_ir.ml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 6fa1b8cdb66..33f798fd8e0 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -554,6 +554,7 @@ let rec check_exp env (exp:Ir.exp) : unit = let scope0 = { empty_scope with val_env = ve0 } in let scope1 = List.fold_left (gather_dec env') scope0 ds in let env'' = adjoin env' scope1 in + check_decs env'' ds; check (T.is_obj t0) "bad annotation (object type expected)"; let (s0, tfs0) = T.as_obj t0 in let val_tfs0 = List.filter (fun tf -> not (T.is_typ tf.T.typ)) tfs0 in From 8e3e38657a133fcd093c49431f2db7c62de3ef25 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 12 Sep 2019 11:41:19 +0200 Subject: [PATCH 0372/1176] IR.FuncE: Check calling convention against the parameter and return type list (#648) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ever since 4efd91586f3cb3d5b8354186494a062353541353 and 4e67f89dac0a4dc3904374d206e29f3848abf222 the parameter list and return type list of `FuncE` should match the Calling Convention field. This checks this fact. Maybe it is time to get rid of the calling convention, now that we have almost all relevant data in the other fields, moving `FuncE` closer to `FuncT` again. I wondered if this check breaks due to the way we put `[AyncT t]` in the return type list for shared functions, but the test case I added says we don’t. Maybe we just don't do n-ary returns in async these days. --- src/ir_def/check_ir.ml | 4 ++++ test/run-dfinity/idl-tuple.as | 9 +++++++++ test/run-dfinity/ok/idl-tuple.did.ok | 4 ++++ 3 files changed, 17 insertions(+) create mode 100644 test/run-dfinity/idl-tuple.as create mode 100644 test/run-dfinity/ok/idl-tuple.did.ok diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 33f798fd8e0..06d8361811e 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -535,6 +535,10 @@ let rec check_exp env (exp:Ir.exp) : unit = check ((cc.Call_conv.sort = T.Shared && Type.is_async (T.seq ret_tys)) ==> isAsyncE exp) "shared function with async type has non-async body"; + check (cc.Call_conv.n_args = List.length args) + "calling convention arity does not match number of parameters"; + check (cc.Call_conv.n_res = List.length ret_tys) + "calling convention arity does not match number of return types"; if (cc.Call_conv.sort = T.Shared) then List.iter (check_concrete env exp.at) ret_tys; let env'' = {env' with labs = T.Env.empty; rets = Some (T.seq ret_tys); async = false} in diff --git a/test/run-dfinity/idl-tuple.as b/test/run-dfinity/idl-tuple.as new file mode 100644 index 00000000000..b78782d33a9 --- /dev/null +++ b/test/run-dfinity/idl-tuple.as @@ -0,0 +1,9 @@ +let a = actor { + public func len2() : async (Int,Int) { + (23, 42) + } +}; + +a.len2(); + +// CALL len2 0x4449444c016a027c7c00000100 [console:logAny] diff --git a/test/run-dfinity/ok/idl-tuple.did.ok b/test/run-dfinity/ok/idl-tuple.did.ok new file mode 100644 index 00000000000..31492c6cad5 --- /dev/null +++ b/test/run-dfinity/ok/idl-tuple.did.ok @@ -0,0 +1,4 @@ +type Int = int; +service a { +len2 : () -> (record {Int; Int}); +} From 9328732fa407ef901765ec751afbbb232eb85e59 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Thu, 12 Sep 2019 12:09:19 +0100 Subject: [PATCH 0373/1176] correct translation of shard call_conv (#650) --- src/ir_passes/async.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index c238689d5a2..f19069a97eb 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -369,7 +369,6 @@ module Transform() = struct | T.Tup [] -> FuncE (x, cc, t_typ_binds typbinds, t_args args, List.map t_typ typT, t_exp exp) | T.Async res_typ -> - let cc' = Call_conv.message_cc (cc.Call_conv.n_args + 1) in let res_typ = t_typ res_typ in let reply_typ = replyT nary res_typ in let r = fresh_var "r" reply_typ in @@ -389,6 +388,7 @@ module Transform() = struct t_exp cps -*- k | _ -> assert false in + let cc' = Call_conv.message_cc (List.length args') in FuncE (x, cc', typbinds', args', [], exp') | _ -> assert false end From 0ed535400e22a552b92b79d430ae619ec9b22d1f Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Thu, 12 Sep 2019 15:40:26 +0200 Subject: [PATCH 0374/1176] Parse enclosing (Pos|Neg)Op around numeric literals as sign (#638) * Fix #505 in the parser by treating the innermost negation (also `+`) operator as a sign. The same idea is applied to expressions and patterns. --- src/as_frontend/parser.mly | 14 ++++++-- src/as_frontend/typing.ml | 8 ++--- src/as_values/value.ml | 4 +++ test/fail/ok/pat-subtyping-fail.tc.ok | 48 ++++++++++++++++++++------- test/random/Main.hs | 7 +--- test/run/neg-boundary.as | 24 ++++++++++++++ 6 files changed, 81 insertions(+), 24 deletions(-) create mode 100644 test/run/neg-boundary.as diff --git a/src/as_frontend/parser.mly b/src/as_frontend/parser.mly index ad1d61546f2..2881625e76f 100644 --- a/src/as_frontend/parser.mly +++ b/src/as_frontend/parser.mly @@ -398,7 +398,12 @@ exp_un(B) : | QUEST e=exp_un(ob) { OptE(e) @? at $sloc } | op=unop e=exp_un(ob) - { UnE(ref Type.Pre, op, e) @? at $sloc } + { match op, e.it with + | (PosOp | NegOp), LitE {contents = PreLit (s, Type.Nat)} -> + let signed = match op with NegOp -> "-" ^ s | _ -> "+" ^ s in + LitE(ref (PreLit (signed, Type.Int))) @? at $sloc + | _ -> UnE(ref Type.Pre, op, e) @? at $sloc + } | op=unassign e=exp_un(ob) { assign_op e (fun e' -> UnE(ref Type.Pre, op, e') @? at $sloc) (at $sloc) } | NOT e=exp_un(ob) @@ -540,7 +545,12 @@ pat_un : | QUEST p=pat_un { OptP(p) @! at $sloc } | op=unop l=lit - { SignP(op, ref l) @! at $sloc } + { match op, l with + | (PosOp | NegOp), PreLit (s, Type.Nat) -> + let signed = match op with NegOp -> "-" ^ s | _ -> "+" ^ s in + LitP(ref (PreLit (signed, Type.Int))) @! at $sloc + | _ -> SignP(op, ref l) @! at $sloc + } pat_bin : | p=pat_un diff --git a/src/as_frontend/typing.ml b/src/as_frontend/typing.ml index 29f36a5d861..583efb19bc8 100644 --- a/src/as_frontend/typing.ml +++ b/src/as_frontend/typing.ml @@ -342,10 +342,10 @@ let check_int8 env = check_lit_val env T.Int8 Value.Int_8.of_string let check_int16 env = check_lit_val env T.Int16 Value.Int_16.of_string let check_int32 env = check_lit_val env T.Int32 Value.Int_32.of_string let check_int64 env = check_lit_val env T.Int64 Value.Int_64.of_string -let check_word8 env = check_lit_val env T.Word8 Value.Word8.of_string_u -let check_word16 env = check_lit_val env T.Word16 Value.Word16.of_string_u -let check_word32 env = check_lit_val env T.Word32 Value.Word32.of_string_u -let check_word64 env = check_lit_val env T.Word64 Value.Word64.of_string_u +let check_word8 env = check_lit_val env T.Word8 Value.Word8.of_string_s +let check_word16 env = check_lit_val env T.Word16 Value.Word16.of_string_s +let check_word32 env = check_lit_val env T.Word32 Value.Word32.of_string_s +let check_word64 env = check_lit_val env T.Word64 Value.Word64.of_string_s let check_float env = check_lit_val env T.Float Value.Float.of_string diff --git a/src/as_values/value.ml b/src/as_values/value.ml index 8fc15121299..3443b7c40e7 100644 --- a/src/as_values/value.ml +++ b/src/as_values/value.ml @@ -105,6 +105,10 @@ struct let s' = dig ^ (if i = 4 then "_" else "") ^ s in to_pretty_string' (WasmInt.div_u w base) (i mod 4 + 1) s' let to_string = to_pretty_string + let of_string_s s = + if String.length s > 0 && String.get s 0 = '-' + then neg (of_string_u (String.sub s 1 (String.length s - 1))) + else of_string_u s end module Int32Rep = struct include Int32 let bitwidth = 32 end diff --git a/test/fail/ok/pat-subtyping-fail.tc.ok b/test/fail/ok/pat-subtyping-fail.tc.ok index 227bfbe1c5c..53da2a8563c 100644 --- a/test/fail/ok/pat-subtyping-fail.tc.ok +++ b/test/fail/ok/pat-subtyping-fail.tc.ok @@ -1,28 +1,52 @@ pat-subtyping-fail.as:123.3-123.15: warning, this case is never reached pat-subtyping-fail.as:124.3-124.12: warning, this case is never reached -pat-subtyping-fail.as:4.9-4.11: type error, operator cannot consume expected type +pat-subtyping-fail.as:4.9-4.11: type error, literal of type + Int +does not have expected type Nat -pat-subtyping-fail.as:8.9-8.11: type error, operator cannot consume expected type +pat-subtyping-fail.as:8.9-8.11: type error, literal of type + Int +does not have expected type Nat -pat-subtyping-fail.as:13.13-13.15: type error, operator cannot consume expected type +pat-subtyping-fail.as:13.13-13.15: type error, literal of type + Int +does not have expected type Nat -pat-subtyping-fail.as:17.18-17.20: type error, operator cannot consume expected type +pat-subtyping-fail.as:17.18-17.20: type error, literal of type + Int +does not have expected type Nat -pat-subtyping-fail.as:22.21-22.23: type error, operator cannot consume expected type +pat-subtyping-fail.as:22.21-22.23: type error, literal of type + Int +does not have expected type Nat -pat-subtyping-fail.as:26.26-26.28: type error, operator cannot consume expected type +pat-subtyping-fail.as:26.26-26.28: type error, literal of type + Int +does not have expected type Nat -pat-subtyping-fail.as:31.11-31.13: type error, operator cannot consume expected type +pat-subtyping-fail.as:31.11-31.13: type error, literal of type + Int +does not have expected type Nat -pat-subtyping-fail.as:35.11-35.13: type error, operator cannot consume expected type +pat-subtyping-fail.as:35.11-35.13: type error, literal of type + Int +does not have expected type Nat -pat-subtyping-fail.as:39.11-39.13: type error, operator cannot consume expected type +pat-subtyping-fail.as:39.11-39.13: type error, literal of type + Int +does not have expected type Nat -pat-subtyping-fail.as:44.12-44.14: type error, operator cannot consume expected type +pat-subtyping-fail.as:44.12-44.14: type error, literal of type + Int +does not have expected type Nat -pat-subtyping-fail.as:48.12-48.14: type error, operator cannot consume expected type +pat-subtyping-fail.as:48.12-48.14: type error, literal of type + Int +does not have expected type Nat -pat-subtyping-fail.as:52.12-52.14: type error, operator cannot consume expected type +pat-subtyping-fail.as:52.12-52.14: type error, literal of type + Int +does not have expected type Nat pat-subtyping-fail.as:57.9-57.16: type error, pattern of type Nat diff --git a/test/random/Main.hs b/test/random/Main.hs index 439782dfab7..5f6c4504f14 100644 --- a/test/random/Main.hs +++ b/test/random/Main.hs @@ -676,14 +676,9 @@ instance Literal Integer instance Literal Natural instance Literal (BitLimited n Natural) instance KnownNat bits => Literal (BitLimited bits Integer) where - -- compensate for https://github.com/dfinity-lab/actorscript/issues/505 - literal (evalN -> n) = if buggy n then "intToInt" <> bitWidth pr <> "(" <> show n <> ")" - else if n < 0 + literal (evalN -> n) = if n < 0 then "(" <> show n <> ")" else show n - where buggy n = n == - 2 ^ (numbits - 1) - numbits = natVal pr - pr = Proxy @bits instance KnownNat bits => Literal (BitLimited bits Word) where literal n = show . fromJust $ trapWord (natVal (Proxy @bits)) (evalN n) diff --git a/test/run/neg-boundary.as b/test/run/neg-boundary.as new file mode 100644 index 00000000000..81c605db079 --- /dev/null +++ b/test/run/neg-boundary.as @@ -0,0 +1,24 @@ +let _ : Int8 = -128; +let _ : Int16 = -32768; +let _ : Int32 = -2_147_483_648; +let _ : Int64 = -9_223_372_036_854_775_808; +{ + assert (switch (-128 : Int8) { case (-128) { true }; case _ { false }}); + func foo(i : Int8) = assert (switch i { case (-128) { true }; case _ { false }}); + func bar(i : Int8) = assert (switch i { case (-128 : Int8) { true }; case _ { false }}); +}; +{ + assert (switch (-32768 : Int16) { case (-32768) { true }; case _ { false }}); + func foo(i : Int16) = assert (switch i { case (-32768) { true }; case _ { false }}); + func bar(i : Int16) = assert (switch i { case (-32768 : Int16) { true }; case _ { false }}); +}; +{ + assert (switch (-2_147_483_648 : Int32) { case (-2_147_483_648) { true }; case _ { false }}); + func foo(i : Int32) = assert (switch i { case (-2_147_483_648) { true }; case _ { false }}); + func bar(i : Int32) = assert (switch i { case (-2_147_483_648 : Int32) { true }; case _ { false }}); +}; +{ + assert (switch (-9_223_372_036_854_775_808 : Int64) { case (-9_223_372_036_854_775_808) { true }; case _ { false }}); + func foo(i : Int64) = assert (switch i { case (-9_223_372_036_854_775_808) { true }; case _ { false }}); + func bar(i : Int64) = assert (switch i { case (-9_223_372_036_854_775_808 : Int64) { true }; case _ { false }}); +}; From b240d8d28a6cef470faa56cf7322127819111fbc Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Thu, 12 Sep 2019 16:08:36 +0200 Subject: [PATCH 0375/1176] Random testing of structures (#630) * Generate structured values and pattern match on them * Options (`?x`), pairs and triples for now * `inter-actor` is actually intra-actor for now (until we have cross-canister messaging) --- src/codegen/compile.ml | 8 +- test/random/Main.hs | 169 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 167 insertions(+), 10 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 192df78bec1..e9528567c00 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -878,7 +878,7 @@ module ClosureTable = struct two reasons: - we cannot just bind the address via i32.bind, because that is not stable, due to our moving GC, and - - we need to remember that these closures are roots (and currenlty never freed!) + - we need to remember that these closures are roots (and currently never freed!) Therefore we maintain a static table from closure index to address of the closure on the heap. @@ -888,7 +888,7 @@ module ClosureTable = struct let loc = ElemHeap.table_end let table_end = Int32.(add loc (mul max_entries Heap.word_size)) - (* For reasons I do not recall we use the first word of the table as the counter, + (* For reasons I do not recall, we use the first word of the table as the counter, and not a global. *) let get_counter = compile_unboxed_const loc ^^ load_unskewed_ptr @@ -3747,7 +3747,7 @@ module Serialization = struct end | Prim (Int64|Nat64|Word64) -> assert_prim_typ () ^^ - ReadBuf.read_word64 env get_data_buf^^ + ReadBuf.read_word64 env get_data_buf ^^ BoxedWord64.box env | Prim (Int32|Nat32|Word32) -> assert_prim_typ () ^^ @@ -3781,7 +3781,7 @@ module Serialization = struct get_len ^^ Text.alloc env ^^ set_x ^^ get_x ^^ Text.payload_ptr_unskewed ^^ ReadBuf.read_blob env get_data_buf get_len ^^ - (* TODO: Check validty of utf8 *) + (* TODO: Check validity of utf8 *) get_x (* Composite types *) diff --git a/test/random/Main.hs b/test/random/Main.hs index 5f6c4504f14..ab405cbb1e0 100644 --- a/test/random/Main.hs +++ b/test/random/Main.hs @@ -29,7 +29,7 @@ import Turtle main = defaultMain tests where tests :: TestTree - tests = testGroup "ActorScript tests" [arithProps, utf8Props] + tests = testGroup "ActorScript tests" [arithProps, utf8Props, matchingProps] arithProps = testGroup "Arithmetic/logic" [ QC.testProperty "expected failures" $ prop_rejects @@ -40,8 +40,13 @@ arithProps = testGroup "Arithmetic/logic" utf8Props = testGroup "UTF-8 coding" [ QC.testProperty "explode >>> concat roundtrips" $ prop_explodeConcat , QC.testProperty "charToText >>> head roundtrips" $ prop_charToText + , QC.testProperty "length computation" $ prop_textLength ] +matchingProps = testGroup "pattern matching" + [ QC.testProperty "intra-actor" $ prop_matchStructured + , QC.testProperty "inter-actor" $ prop_matchInActor + ] (runScriptNoFuzz, runScriptWantFuzz) = (runner id, runner not) where runner relevant name testCase = @@ -88,6 +93,10 @@ prop_charToText (UTF8 char) = monadicIO $ do c = escape char runScriptNoFuzz "charToText" testCase +prop_textLength (UTF8 text) = monadicIO $ do + let testCase = "assert(\"" <> (text >>= escape) <> "\".len() == " <> show (length text) <> ")" + runScriptNoFuzz "textLength" testCase + assertSuccessNoFuzz relevant (compiled, (exitCode, out, err)) = do let fuzzErr = not $ Data.Text.null err when fuzzErr $ do @@ -146,6 +155,98 @@ prop_verifies (TestCase (map fromString -> testCase)) = monadicIO $ do assertSuccessNoFuzz id res +data Matching where + Matching :: (AnnotLit t, ASValue t, Show t) => (ASTerm t, t) -> Matching + +deriving instance Show Matching + + +instance Arbitrary Matching where + arbitrary = oneof [ realise Matching <$> gen @Bool + , realise Matching <$> gen @(Bool, Bool) + , realise Matching <$> gen @(Bool, Integer) + , realise Matching <$> gen @((Bool, Natural), Integer) + , realise Matching <$> gen @(BitLimited 8 Natural, BitLimited 8 Integer, BitLimited 8 Word) + , realise Matching <$> gen @(Maybe Integer) + ] + where gen :: (Arbitrary (ASTerm a), Evaluatable a) => Gen (ASTerm a, Maybe a) + gen = (do term <- arbitrary + let val = evaluate term + pure (term, val)) `suchThat` (isJust . snd) + realise f (tm, Just v) = f (tm, v) + +prop_matchStructured :: Matching -> Property +prop_matchStructured (Matching a) = locally a + +locally :: (AnnotLit t, ASValue t) => (ASTerm t, t) -> Property +locally (tm, v) = monadicIO $ do + let testCase = "assert (switch (" <> expr <> ") { case (" <> eval'd <> ") true; case _ false })" + + eval'd = unparse v + expr = unparseAS tm + runScriptNoFuzz "matchLocally" testCase + +prop_matchInActor :: Matching -> Property +prop_matchInActor (Matching a) = mobile a + +mobile :: (AnnotLit t, ASValue t) => (ASTerm t, t) -> Property +mobile (tm, v) = monadicIO $ do + let testCase = "/*let a = actor { public func match (b : " <> typed <> ") : async Bool = async { true } };*/ assert (switch (" <> expr <> " : " <> typed <> ") { case (" <> eval'd <> ") true; case _ false })" + + eval'd = unparse v + typed = unparseType v + expr = unparseAS tm + runScriptNoFuzz "matchMobile" testCase + +-- instances of ASValue describe "ground values" in +-- ActorScript. These can appear in patterns and have +-- well-defined AS type. +-- +class ASValue a where + unparseType :: a -> String + unparse :: a -> String + +instance ASValue Bool where + unparseType _ = "Bool" + unparse = unparseAS . Bool + +instance ASValue Integer where + unparseType _ = "Int" + unparse = show + +instance ASValue Natural where + unparseType _ = "Nat" + unparse = show + +instance KnownNat n => ASValue (BitLimited n Natural) where + unparseType _ = "Nat" <> bitWidth (Proxy @n) + unparse (NatN a) = annot (Five @(BitLimited n Natural)) (show a) + +instance KnownNat n => ASValue (BitLimited n Integer) where + unparseType _ = "Int" <> bitWidth (Proxy @n) + unparse (IntN a) = annot (Five @(BitLimited n Integer)) (show a) + +instance KnownNat n => ASValue (BitLimited n Word) where + unparseType _ = "Word" <> bitWidth (Proxy @n) + unparse (WordN a) = annot (Five @(BitLimited n Word)) (show a) + +instance (ASValue a, ASValue b) => ASValue (a, b) where + unparseType (a, b) = "(" <> unparseType a <> ", " <> unparseType b <> ")" + unparse (a, b) = "(" <> unparse a <> ", " <> unparse b <> ")" + +instance (ASValue a, ASValue b, ASValue c) => ASValue (a, b, c) where + unparseType (a, b, c) = "(" <> unparseType a <> ", " <> unparseType b <> ", " <> unparseType c <> ")" + unparse (a, b, c) = "(" <> unparse a <> ", " <> unparse b <> ", " <> unparse c <> ")" + +instance ASValue a => ASValue (Maybe a) where + unparseType Nothing = "Null" + unparseType (Just a) = "?" <> unparseType a + unparse Nothing = "null" + unparse (Just a) = "?" <> unparse a + +-- wiggle room around an *important value* +-- think of it as a "fuzz" +-- data Off = TwoLess | OneLess | OneMore | TwoMore deriving (Enum, Eq, Ord, Show) @@ -213,7 +314,7 @@ instance KnownNat n => Arbitrary (Neuralgic (BitLimited n Word)) where data ASTerm :: * -> * where -- Comparisons NotEqual, Equals, GreaterEqual, Greater, LessEqual, Less - :: (Annot a, Literal a, Evaluatable a) => ASTerm a -> ASTerm a -> ASTerm Bool + :: (AnnotLit a, Evaluatable a) => ASTerm a -> ASTerm a -> ASTerm Bool -- Short-circuit ShortAnd, ShortOr :: ASTerm Bool -> ASTerm Bool -> ASTerm Bool @@ -238,6 +339,14 @@ data ASTerm :: * -> * where ConvertNat :: KnownNat n => ASTerm (BitLimited n Natural) -> ASTerm Integer ConvertInt :: KnownNat n => ASTerm (BitLimited n Integer) -> ASTerm Integer ConvertWord :: WordLike n => ASTerm (BitLimited n Word) -> ASTerm Integer + -- Constructors (intro forms) + Pair :: (AnnotLit a, AnnotLit b, Evaluatable a, Evaluatable b) => ASTerm a -> ASTerm b -> ASTerm (a, b) + Triple :: (AnnotLit a, AnnotLit b, AnnotLit c, Evaluatable a, Evaluatable b, Evaluatable c) + => ASTerm a -> ASTerm b -> ASTerm c -> ASTerm (a, b, c) + Array :: ASTerm a -> ASTerm [a] -- not matchable! + Null :: ASTerm (Maybe a) + Some :: (AnnotLit a, Evaluatable a) => ASTerm a -> ASTerm (Maybe a) + -- Variants, Objects (TODO) deriving instance Show (ASTerm t) @@ -286,7 +395,7 @@ bitwiseTerm n = -- generate reasonably formed trees from smaller subterms -- -reasonablyShaped :: (Arbitrary (Neuralgic a), Annot a, Evaluatable a, Literal a) +reasonablyShaped :: (Arbitrary (Neuralgic a), AnnotLit a, Evaluatable a) => (Int -> [(Int, Gen (ASTerm a))]) -> Gen (ASTerm a) reasonablyShaped sub = sized $ \(succ -> n) -> frequency $ @@ -313,6 +422,15 @@ instance {-# OVERLAPPABLE #-} WordLike n => Arbitrary (ASTerm (BitLimited n Word instance {-# OVERLAPS #-} Arbitrary (ASTerm Word8) where arbitrary = reasonablyShaped $ (<>) <$> subTerm True <*> bitwiseTerm +instance (AnnotLit a, AnnotLit b, Evaluatable a, Evaluatable b, Arbitrary (ASTerm a), Arbitrary (ASTerm b)) => Arbitrary (ASTerm (a, b)) where + arbitrary = scale (`quot` 2) $ Pair <$> arbitrary <*> arbitrary + +instance (AnnotLit a, AnnotLit b, AnnotLit c, Evaluatable a, Evaluatable b, Evaluatable c, Arbitrary (ASTerm a), Arbitrary (ASTerm b), Arbitrary (ASTerm c)) + => Arbitrary (ASTerm (a, b, c)) where + arbitrary = scale (`quot` 3) $ Triple <$> arbitrary <*> arbitrary <*> arbitrary + +instance (AnnotLit a, Evaluatable a, Arbitrary (ASTerm a)) => Arbitrary (ASTerm (Maybe a)) where + arbitrary = frequency [(1, pure Null), (10, Some <$> arbitrary)] instance Arbitrary (ASTerm Bool) where arbitrary = sized $ \(succ -> n) -> -- TODO: use frequency? @@ -422,6 +540,10 @@ deriving instance Show (BitLimited n a) deriving instance Eq (BitLimited n a) deriving instance Ord (BitLimited n a) + +-- for a BitLimited n Word, the instances of WordView provide the +-- change of perspective to the built-in Word types' semantics +-- class WordView a where type WordType a :: * toWord :: a -> WordType a @@ -432,6 +554,7 @@ class WordView a where lift1b f (f . toWord -> res) = res lift2 :: (WordType a -> WordType a -> WordType a) -> a -> a -> a lift2 f (toWord -> a) (toWord -> b) = fromWord (a `f` b) + {-# MINIMAL toWord, fromWord #-} type family WordTypeForBits a where @@ -606,6 +729,16 @@ instance Evaluatable Integer where instance Evaluatable Natural where evaluate = eval +instance (Evaluatable a, Evaluatable b) => Evaluatable (a, b) where + evaluate (Pair a b) = (,) <$> evaluate a <*> evaluate b + +instance (Evaluatable a, Evaluatable b, Evaluatable c) => Evaluatable (a, b, c) where + evaluate (Triple a b c) = (,,) <$> evaluate a <*> evaluate b <*> evaluate c + +instance Evaluatable a => Evaluatable (Maybe a) where + evaluate Null = pure Nothing + evaluate (Some a) = Just <$> evaluate a + eval :: (Restricted a, Integral a) => ASTerm a -> Maybe a eval Five = pure 5 eval (Neuralgic n) = evalN n @@ -639,12 +772,22 @@ instance Evaluatable Bool where evaluate (Not a) = not <$> evaluate a evaluate (Bool b) = pure b +type AnnotLit t = (Annot t, Literal t) class Annot t where annot :: ASTerm t -> String -> String sizeSuffix :: ASTerm t -> String -> String sizeSuffix _ = id +instance Annot (a, b) where + annot _ = id + +instance Annot (a, b, c) where + annot _ = id + +instance Annot (Maybe a) where + annot _ = id + instance Annot Integer where annot _ s = "((" <> s <> ") : Int)" @@ -672,6 +815,15 @@ class Literal a where literal :: Neuralgic a -> String literal (evalN -> n) = if n < 0 then "(" <> show n <> ")" else show n +instance Literal (a, b) where + literal _ = error "Literal (a, b) makes no sense" + +instance Literal (a, b, c) where + literal _ = error "Literal (a, b, c) makes no sense" + +instance Literal (Maybe a) where + literal _ = error "Literal (Maybe a) makes no sense" + instance Literal Integer instance Literal Natural instance Literal (BitLimited n Natural) @@ -683,12 +835,12 @@ instance KnownNat bits => Literal (BitLimited bits Word) where literal n = show . fromJust $ trapWord (natVal (Proxy @bits)) (evalN n) instance Literal Bool where - literal _ = undefined + literal _ = error "Literal Bool makes no sense" inParens :: (a -> String) -> String -> a -> a -> String inParens to op lhs rhs = "(" <> to lhs <> " " <> op <> " " <> to rhs <> ")" -unparseAS :: (Annot a, Literal a) => ASTerm a -> String +unparseAS :: AnnotLit a => ASTerm a -> String unparseAS f@Five = annot f "5" unparseAS a@(Neuralgic n) = annot a $ literal n unparseAS (Pos n) = "(+" <> unparseAS n <> ")" @@ -728,6 +880,10 @@ unparseAS (a `ShortOr` b) = inParens unparseAS "or" a b unparseAS (Not a) = "(not " <> unparseAS a <> ")" unparseAS (Bool False) = "false" unparseAS (Bool True) = "true" +unparseAS (a `Pair` b) = "(" <> unparseAS a <> ", " <> unparseAS b <> ")" +unparseAS (Triple a b c) = "(" <> unparseAS a <> ", " <> unparseAS b <> ", " <> unparseAS c <> ")" +unparseAS Null = "null" +unparseAS (Some a) = '?' : unparseAS a unparseNat :: KnownNat n => Proxy n -> ASTerm (BitLimited n Natural) -> String unparseNat p a = "(nat" <> bitWidth p <> "ToNat(" <> unparseAS a <> "))" @@ -741,6 +897,7 @@ unparseWord p a = "(word" <> bitWidth p <> "ToNat(" <> unparseAS a <> "))" -- TO -- TODOs: -- - wordToInt -- - bitwise ops (btst?) --- - pattern matches (over numeric, bool) +-- - pattern matches (over numeric, bool, structured) -- - trapping flavour-preserving conversions Nat -> NatN -- - bitsize-preserving conversions +-- - data ASTerm (p :: {Term, Pattern}) where ... Pattern :: ASValue a => a -> ASTerm (Pattern/both) a From 5f13b3faf6206a9d632428d308092a131cbadc5c Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Fri, 13 Sep 2019 17:17:33 +0200 Subject: [PATCH 0376/1176] Test unary operators that don't typecheck (#473) * test unary operators that don't typecheck * also with tests for `SignP` patterns --- test/fail/bad-unops.as | 22 ++++++++++++++++++++++ test/fail/ok/bad-unops.tc.ok | 24 ++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 test/fail/bad-unops.as create mode 100644 test/fail/ok/bad-unops.tc.ok diff --git a/test/fail/bad-unops.as b/test/fail/bad-unops.as new file mode 100644 index 00000000000..41e4cb3f5d4 --- /dev/null +++ b/test/fail/bad-unops.as @@ -0,0 +1,22 @@ +let a = ^3; // type error, operator is not defined for operand type +let b = ^-5; // type error, operator is not defined for operand type +let c : Nat = +3; // literal type mismatch +let d : Nat = -3; // literal type mismatch + +switch (1) { case (^1) { ignore "hmmm" }; case _ { ignore "unexpected" } }; // type error, operator cannot consume expected type +switch (1) { case (+1) { ignore "unexpected" }; case _ { ignore "hmmm" } }; // literal type mismatch +switch (1) { case (-1) { ignore "hmmm" }; case _ { ignore "unexpected" } }; // literal type mismatch + +switch (-1) { case (^1) { ignore "hmmm" }; case _ { ignore "unexpected" } }; // type error, operator cannot consume expected type +ignore (switch (-1) { case (+1) "hmmm"; case _ "as expected" }); +ignore (switch (-1) { case (-1) "as expected"; case _ "hmmm" }); + +ignore (switch (^1 : Word8) { case (^1) "as expected"; case _ "hmmm" }); +//switch (+1 : Word8) { case (+1) "as expected"; case _ "hmmm" }; // both `+1` are not accepted +ignore (switch (-1 : Word8) { case (-1) "as expected"; case _ "hmmm" }); + +// when testing the switch expression in the REPL, I either +// * expect the result being "as expected", or +// * a type error (as described in the comment) +// +// test steps wrapped in ignore should type-check diff --git a/test/fail/ok/bad-unops.tc.ok b/test/fail/ok/bad-unops.tc.ok new file mode 100644 index 00000000000..a198cbd0dc0 --- /dev/null +++ b/test/fail/ok/bad-unops.tc.ok @@ -0,0 +1,24 @@ +bad-unops.as:1.9-1.11: type error, operator is not defined for operand type + Int +bad-unops.as:2.9-2.12: type error, operator is not defined for operand type + Int +bad-unops.as:3.15-3.17: type error, literal of type + Int +does not have expected type + Nat +bad-unops.as:4.15-4.17: type error, literal of type + Int +does not have expected type + Nat +bad-unops.as:6.20-6.22: type error, operator cannot consume expected type + Nat +bad-unops.as:7.20-7.22: type error, literal of type + Int +does not have expected type + Nat +bad-unops.as:8.20-8.22: type error, literal of type + Int +does not have expected type + Nat +bad-unops.as:10.21-10.23: type error, operator cannot consume expected type + Int From 867735ef9c5329d910f30dfdeabc7126a954a0c1 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 16 Sep 2019 10:48:27 +0100 Subject: [PATCH 0377/1176] Do not go via BigNum when leb-encoding i32 (#653) this closes #581. Wasn't high priority, but it was bothering me. Also refactoring some code (dynamics) to use the `get_x`-parameter-pattern. I find this cleaner than expecting duplicate identical arguments on the stack. --- src/codegen/compile.ml | 98 +++++++++++++++++++++--------------------- 1 file changed, 48 insertions(+), 50 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index e9528567c00..a206814457c 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -1713,17 +1713,41 @@ let name_from_relop = function | Ge -> "B_ge" | Gt -> "B_gt" -(* helper, measures the dynamics of the unsigned i32, returns (32 - effective bits) - expects i32 on stack *) -let unsigned_dynamics = +(* helper, measures the dynamics of the unsigned i32, returns (32 - effective bits) *) +let unsigned_dynamics get_x = + get_x ^^ G.i (Unary (Wasm.Values.I32 I32Op.Clz)) -(* helper, measures the dynamics of the signed i32, returns (32 - effective bits) - expects two identical i32 copies on stack *) -let signed_dynamics = - compile_shl_const 1l ^^ +(* helper, measures the dynamics of the signed i32, returns (32 - effective bits) *) +let signed_dynamics get_x = + get_x ^^ compile_shl_const 1l ^^ + get_x ^^ G.i (Binary (Wasm.Values.I32 I32Op.Xor)) ^^ - unsigned_dynamics + G.i (Unary (Wasm.Values.I32 I32Op.Clz)) + +module I32Leb = struct + let compile_size dynamics get_x = + get_x ^^ G.if_ (ValBlockType (Some I32Type)) + begin + compile_unboxed_const 38l ^^ + dynamics get_x ^^ + G.i (Binary (Wasm.Values.I32 I32Op.Sub)) ^^ + compile_divU_const 7l + end + compile_unboxed_one + + let compile_leb128_size get_x = compile_size unsigned_dynamics get_x + let compile_sleb128_size get_x = compile_size signed_dynamics get_x + + let compile_store_to_data_buf_unsigned env get_x get_buf = + get_x ^^ get_buf ^^ E.call_import env "rts" "leb128_encode" ^^ + compile_leb128_size get_x + + let compile_store_to_data_buf_signed env get_x get_buf = + get_x ^^ get_buf ^^ E.call_import env "rts" "sleb128_encode" ^^ + compile_sleb128_size get_x + +end module MakeCompact (Num : BigNumType) : BigNumType = struct @@ -2050,19 +2074,6 @@ module MakeCompact (Num : BigNumType) : BigNumType = struct (get_res ^^ Num.truncate_to_word32 env ^^ compress) get_res - let compile_encoding_size dynamics get_x = - get_x ^^ G.if_ (ValBlockType (Some I32Type)) - begin - compile_unboxed_const 38l ^^ - get_x ^^ dynamics ^^ - G.i (Binary (Wasm.Values.I32 I32Op.Sub)) ^^ - compile_divU_const 7l - end - compile_unboxed_one - - let compile_leb128_size = compile_encoding_size unsigned_dynamics - let compile_sleb128_size get_x = compile_encoding_size (get_x ^^ signed_dynamics) get_x - let compile_store_to_data_buf_unsigned env = let set_x, get_x = new_local env "x" in let set_buf, get_buf = new_local env "buf" in @@ -2070,9 +2081,8 @@ module MakeCompact (Num : BigNumType) : BigNumType = struct get_x ^^ try_unbox I32Type (fun env -> - extend ^^ compile_shrS_const 1l ^^ set_x ^^ get_x ^^ - get_buf ^^ E.call_import env "rts" "leb128_encode" ^^ - compile_leb128_size get_x + extend ^^ compile_shrS_const 1l ^^ set_x ^^ + I32Leb.compile_store_to_data_buf_unsigned env get_x get_buf ) (fun env -> G.i Drop ^^ get_buf ^^ get_x ^^ Num.compile_store_to_data_buf_unsigned env) env @@ -2084,9 +2094,8 @@ module MakeCompact (Num : BigNumType) : BigNumType = struct get_x ^^ try_unbox I32Type (fun env -> - extend ^^ compile_shrS_const 1l ^^ set_x ^^ get_x ^^ - get_buf ^^ E.call_import env "rts" "sleb128_encode" ^^ - compile_sleb128_size get_x + extend ^^ compile_shrS_const 1l ^^ set_x ^^ + I32Leb.compile_store_to_data_buf_signed env get_x get_buf ) (fun env -> G.i Drop ^^ get_buf ^^ get_x ^^ Num.compile_store_to_data_buf_signed env) env @@ -2096,7 +2105,7 @@ module MakeCompact (Num : BigNumType) : BigNumType = struct (fun _ -> let set_x, get_x = new_local env "x" in extend ^^ compile_shrS_const 1l ^^ set_x ^^ - compile_leb128_size get_x + I32Leb.compile_leb128_size get_x ) (fun env -> Num.compile_data_size_unsigned env) env @@ -2106,7 +2115,7 @@ module MakeCompact (Num : BigNumType) : BigNumType = struct (fun _ -> let set_x, get_x = new_local env "x" in extend ^^ compile_shrS_const 1l ^^ set_x ^^ - compile_sleb128_size get_x + I32Leb.compile_sleb128_size get_x ) (fun env -> Num.compile_data_size_unsigned env) env @@ -3279,17 +3288,6 @@ module Serialization = struct (fun (h1,_) (h2,_) -> Lib.Uint32.compare h1 h2) (List.map (fun f -> (Idllib.IdlHash.idl_hash f.Type.lab, f)) fs) - (* TODO (leb128 for i32): - All leb128 currently goes through bignum. This is of course - absurdly expensive and round-about, but I want _one_ implementation - first that I can test, until we properly exercise this code (i.e. there - is also the JS-side of things and we know it is bug-free). - Writing a Wasm-native implementation of this will then be done separately. - - Update as of #469: we have leb128_encode and sleb128_encode in rts now! - This is #581. - *) - (* The IDL serialization prefaces the data with a type description. We can statically create the type description in Ocaml code, store it in the program, and just copy it to the beginning of the message. @@ -3463,9 +3461,10 @@ module Serialization = struct get_ref_size ^^ compile_add_const i ^^ set_ref_size in - (* See TODO (leb128 for i32) *) let size_word env code = - inc_data_size (code ^^ BigNum.from_word32 env ^^ BigNum.compile_data_size_unsigned env) + let (set_word, get_word) = new_local env "word" in + code ^^ set_word ^^ + inc_data_size (I32Leb.compile_leb128_size get_word) in let size env t = @@ -3548,10 +3547,9 @@ module Serialization = struct get_ref_buf ^^ compile_add_const Heap.word_size ^^ set_ref_buf in let write_word code = - (* See TODO (leb128 for i32) *) - get_data_buf ^^ - code ^^ BigNum.from_word32 env ^^ - BigNum.compile_store_to_data_buf_unsigned env ^^ + let (set_word, get_word) = new_local env "word" in + code ^^ set_word ^^ + I32Leb.compile_store_to_data_buf_unsigned env get_word get_data_buf ^^ advance_data_buf in @@ -5395,7 +5393,7 @@ let compile_binop env t op = get_n ^^ compile_shrU_const Int32.(sub 33l (of_int bits)) ^^ G.if_ (ValBlockType (Some I32Type)) begin - get_n ^^ unsigned_dynamics ^^ compile_sub_const (Int32.of_int bits) ^^ + unsigned_dynamics get_n ^^ compile_sub_const (Int32.of_int bits) ^^ get_exp ^^ UnboxedSmallWord.lsb_adjust ty ^^ G.i (Binary (Wasm.Values.I32 I32Op.Mul)) ^^ compile_unboxed_const (-30l) ^^ G.i (Compare (Wasm.Values.I32 I32Op.LtS)) ^^ then_arithmetic_overflow env ^^ @@ -5422,7 +5420,7 @@ let compile_binop env t op = begin get_exp ^^ compile_unboxed_const 32l ^^ G.i (Compare (Wasm.Values.I32 I32Op.GeU)) ^^ then_arithmetic_overflow env ^^ - get_n ^^ unsigned_dynamics ^^ compile_sub_const 32l ^^ + unsigned_dynamics get_n ^^ compile_sub_const 32l ^^ get_exp ^^ UnboxedSmallWord.lsb_adjust Type.Nat32 ^^ G.i (Binary (Wasm.Values.I32 I32Op.Mul)) ^^ compile_unboxed_const (-62l) ^^ G.i (Compare (Wasm.Values.I32 I32Op.LtS)) ^^ then_arithmetic_overflow env ^^ @@ -5449,7 +5447,7 @@ let compile_binop env t op = get_n ^^ compile_shrS_const Int32.(sub 33l (of_int bits)) ^^ G.if_ (ValBlockType (Some I32Type)) begin - get_n ^^ get_n ^^ signed_dynamics ^^ compile_sub_const (Int32.of_int (bits - 1)) ^^ + signed_dynamics get_n ^^ compile_sub_const (Int32.of_int (bits - 1)) ^^ get_exp ^^ UnboxedSmallWord.lsb_adjust ty ^^ G.i (Binary (Wasm.Values.I32 I32Op.Mul)) ^^ compile_unboxed_const (-30l) ^^ G.i (Compare (Wasm.Values.I32 I32Op.LtS)) ^^ then_arithmetic_overflow env ^^ @@ -5492,7 +5490,7 @@ let compile_binop env t op = begin get_exp ^^ compile_unboxed_const 32l ^^ G.i (Compare (Wasm.Values.I32 I32Op.GeU)) ^^ then_arithmetic_overflow env ^^ - get_n ^^ get_n ^^ signed_dynamics ^^ compile_sub_const 31l ^^ + signed_dynamics get_n ^^ compile_sub_const 31l ^^ get_exp ^^ UnboxedSmallWord.lsb_adjust Type.Int32 ^^ G.i (Binary (Wasm.Values.I32 I32Op.Mul)) ^^ compile_unboxed_const (-62l) ^^ G.i (Compare (Wasm.Values.I32 I32Op.LtS)) ^^ then_arithmetic_overflow env ^^ From d8aa2c553b100d82137df0e62ed6541594abb48c Mon Sep 17 00:00:00 2001 From: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> Date: Mon, 16 Sep 2019 16:18:35 +0200 Subject: [PATCH 0378/1176] Adds an implementation of incrementally applying diffs in the vfs (#646) * adds an implementation of incrementally applying diffs in the vfs * concat lines into a string buffer * use OCaml stdlib function to concat strings * Update src/lib/lib.ml Co-Authored-By: Gabor Greif --- src/languageServer/languageServer.ml | 5 +- src/languageServer/vfs.ml | 87 ++++++++++++++++++++++------ src/languageServer/vfs.mli | 6 +- src/languageServer/vfs_tests.ml | 72 +++++++++++++++++++++++ src/lib/lib.ml | 7 ++- src/lib/lib.mli | 1 + 6 files changed, 157 insertions(+), 21 deletions(-) create mode 100644 src/languageServer/vfs_tests.ml diff --git a/src/languageServer/languageServer.ml b/src/languageServer/languageServer.ml index 374e0a36ce1..e3598eb3a97 100644 --- a/src/languageServer/languageServer.ml +++ b/src/languageServer/languageServer.ml @@ -150,7 +150,10 @@ let start () = let text_document_sync_options = Lsp_t.{ text_document_sync_options_openClose = Some true; - text_document_sync_options_change = Some 1; + (* Full *) + (* text_document_sync_options_change = Some 1; *) + (* Incremental *) + text_document_sync_options_change = Some 2; text_document_sync_options_willSave = Some false; text_document_sync_options_willSaveWaitUntil = Some false; text_document_sync_options_save = Some { diff --git a/src/languageServer/vfs.ml b/src/languageServer/vfs.ml index f98b9caf3fd..820d219349a 100644 --- a/src/languageServer/vfs.ml +++ b/src/languageServer/vfs.ml @@ -2,7 +2,9 @@ module Lsp_t = Lsp.Lsp_t module VfsStore = Map.Make(String) -type virtual_file = string +(* TODO(Christoph): Terrible format, ideally we want some RRB or HAMT + backed vector type with a zipper *) +type virtual_file = string list type t = virtual_file VfsStore.t @@ -20,25 +22,15 @@ let open_file did_open_params vfs = let _ = text_document_item.Lsp_t.text_document_item_version in let text = - text_document_item.Lsp_t.text_document_item_text in - VfsStore.add uri text vfs + text_document_item.Lsp_t.text_document_item_text in + let lines = + (* TODO(Christoph): Windows compatibility issues *) + Lib.String.split text '\n' in + VfsStore.add uri lines vfs let read_file uri vfs = VfsStore.find_opt uri vfs - -let update_file did_change_params = - let change_event = - did_change_params.Lsp_t.text_document_did_change_params_contentChanges - |> (* TODO(Christoph): This needs to change once we allow - incremental file updates*) - Lib.Fun.flip List.nth 0 - in - let new_content = change_event.Lsp_t.text_document_content_change_event_text in - let uri = - did_change_params - .Lsp_t.text_document_did_change_params_textDocument - .Lsp_t.versioned_text_document_identifier_uri in - VfsStore.add uri new_content + |> Lib.Option.map (String.concat "\n") let close_file did_close_params = let uri = @@ -46,3 +38,64 @@ let close_file did_close_params = .Lsp_t.text_document_did_close_params_textDocument .Lsp_t.text_document_identifier_uri in VfsStore.remove uri + +(* This isn't recursive, but I prefer apply_change to be defined after + update_file, to keep the public API of the module in one place *) +let rec update_file did_change_params (vfs : t) : t = + let uri = + did_change_params + .Lsp_t.text_document_did_change_params_textDocument + .Lsp_t.versioned_text_document_identifier_uri in + let change_events = + did_change_params.Lsp_t.text_document_did_change_params_contentChanges in + let previous_content = + (* TODO Let's not crash here *) + VfsStore.find uri vfs in + let new_content = + List.fold_left apply_change previous_content change_events in + VfsStore.add uri new_content vfs + +and apply_change lines Lsp_t.{ + text_document_content_change_event_range = range; + text_document_content_change_event_rangeLength = rangeLength; + text_document_content_change_event_text = text + } = + match range with + | None -> + (* If the range is None, the editor expects us to fully replace + the file content *) + (* TODO(Christoph): We should be normalising file endings here *) + Lib.String.split text '\n' + | Some Lsp_t.{ + range_start = + { position_line = sl; + position_character = sc + }; + range_end_ = + { position_line = el; + position_character = ec + } + } -> + let (prev_lines, rest) = Lib.List.split_at sl lines in + let (affected, past_lines) = Lib.List.split_at (el - sl + 1) rest in + (* let print_lines lbl ls = + * Printf.printf "%s: %s\n" lbl ("[" ^ join_with "; " ls ^ "]") in + * let _ = print_lines "prev" prev_lines; + * print_lines "aff" affected; + * print_lines "past" past_lines in *) + (* TODO(Christoph): All the String.sub calls following should + operate on UTF16 code unit boundaries instead, as that's what + LSP talks. *) + let new_ = match affected with + | [] -> text + | [aff] -> + String.sub aff 0 sc + ^ text + ^ String.sub aff ec (String.length aff - ec) + | affected -> + let (init, last) = Lib.List.split_last affected in + String.sub (String.concat "\n" init) 0 sc + ^ text + ^ String.sub last ec (String.length last - ec) + in + prev_lines @ Lib.String.split new_ '\n' @ past_lines diff --git a/src/languageServer/vfs.mli b/src/languageServer/vfs.mli index ffe8f3a6e31..1ceeeaacac7 100644 --- a/src/languageServer/vfs.mli +++ b/src/languageServer/vfs.mli @@ -4,7 +4,6 @@ type t type uri = string (* NOTE(Christoph): Track file version *) -type virtual_file = string (** Creates a new virtual file system *) val empty: t @@ -13,10 +12,13 @@ val empty: t val open_file: Lsp_t.text_document_did_open_params -> t -> t (** Reads a file from the vfs *) -val read_file: uri -> t -> virtual_file option +val read_file: uri -> t -> string option (** Updates the contents of a file in the vfs *) val update_file: Lsp_t.text_document_did_change_params -> t -> t (** Removes a file from the vfs *) val close_file: Lsp_t.text_document_did_close_params -> t -> t + +(** For tests *) +val apply_change: string list -> Lsp_t.text_document_content_change_event -> string list diff --git a/src/languageServer/vfs_tests.ml b/src/languageServer/vfs_tests.ml new file mode 100644 index 00000000000..1cb2af954f1 --- /dev/null +++ b/src/languageServer/vfs_tests.ml @@ -0,0 +1,72 @@ +module Lsp = Lsp.Lsp_t + +let extract_cursors input = + let cursor_start = ref (0, 0) in + let start_found = ref false in + let cursor_end = ref (0, 0) in + String.split_on_char '\n' input + |> List.mapi + (fun line_num line -> + match String.index_opt line '|' with + | Some column_num -> + if not !start_found + then begin + start_found := true; + cursor_start := (line_num, column_num); + (* See if we can find a second pipe in the same line *) + (match String.index_from_opt line (column_num + 1) '|' with + | Some column_num -> + (* Need to account for the previously found pipe, + so we subtract 1 from the column_num *) + cursor_end := (line_num, column_num - 1); + | None -> ()) + end + else + cursor_end := (line_num, column_num); + line + |> String.split_on_char '|' + |> String.concat "" + | None -> line + ) + |> String.concat "\n" + |> fun f -> (f, !cursor_start, !cursor_end) + +let apply_change_test_case file replacement expected = + let (input, (sl, sc), (el, ec)) = extract_cursors file in + (* let _ = Printf.printf "start: %d:%d, end: %d:%d" sl sc el ec in *) + let range = + Lsp.{ + range_start = { position_line = sl; position_character = sc }; + range_end_ = { position_line = el; position_character = ec }; + } + in + let actual = + String.concat "\n" + (Vfs.apply_change + (Lib.String.split input '\n') + Lsp.{ + text_document_content_change_event_range = Some range; + text_document_content_change_event_rangeLength = Some 0; + text_document_content_change_event_text = replacement; + }) in + String.equal actual expected || + (Printf.printf + "\nExpected: %s\nActual: %s\n" + expected + actual; + false) + +let%test "it applies the empty change" = + apply_change_test_case "hi ||dude" "" "hi dude" + +let%test "it applies a change" = + apply_change_test_case "1\n|2|\n3" "4" "1\n4\n3" + +let%test "it applies a two-line change" = + apply_change_test_case "1\n|2|\n3" "4\n5" "1\n4\n5\n3" + +let%test "it removes a line" = + apply_change_test_case "a\n|b\n|c" "" "a\nc" + +let%test "it inserts a newline" = + apply_change_test_case "a\n||b" "\n" "a\n\nb" diff --git a/src/lib/lib.ml b/src/lib/lib.ml index a7fe1ae7da9..0df5cded111 100644 --- a/src/lib/lib.ml +++ b/src/lib/lib.ml @@ -116,7 +116,7 @@ struct let rec take n xs = match n, xs with - | 0, _ -> [] + | _ when n <= 0 -> [] | n, x::xs' when n > 0 -> x :: take (n - 1) xs' | _ -> failwith "take" @@ -126,6 +126,11 @@ struct | n, _::xs' when n > 0 -> drop (n - 1) xs' | _ -> failwith "drop" + let split_at n xs = + if n <= List.length xs + then (take n xs, drop n xs) + else (xs, []) + let hd_opt = function | x :: _ -> Some x | _ -> None diff --git a/src/lib/lib.mli b/src/lib/lib.mli index 97651783bd9..44e3dcdb682 100644 --- a/src/lib/lib.mli +++ b/src/lib/lib.mli @@ -18,6 +18,7 @@ sig val table : int -> (int -> 'a) -> 'a list val take : int -> 'a list -> 'a list (* raises Failure *) val drop : int -> 'a list -> 'a list (* raises Failure *) + val split_at : int -> 'a list -> ('a list * 'a list) val hd_opt : 'a list -> 'a option val last : 'a list -> 'a (* raises Failure *) From 9023ee59b02bf26d50a23bd5ad49dad8a3791520 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Mon, 16 Sep 2019 17:53:58 +0200 Subject: [PATCH 0379/1176] Accept +128 : Word8 (#651) * accept plus sign on words * test rejection outside of canonical range * comprehensively test word literals (positive and negative) --- src/as_frontend/typing.ml | 8 +++--- src/as_values/value.ml | 4 --- src/exes/didc.ml | 2 +- test/fail/bad-unops.as | 2 +- test/fail/ok/word-range.tc.ok | 24 ++++++++++++++++ test/fail/word-range.as | 54 +++++++++++++++++++++++++++++++++++ 6 files changed, 84 insertions(+), 10 deletions(-) create mode 100644 test/fail/ok/word-range.tc.ok create mode 100644 test/fail/word-range.as diff --git a/src/as_frontend/typing.ml b/src/as_frontend/typing.ml index 583efb19bc8..d08d54eec63 100644 --- a/src/as_frontend/typing.ml +++ b/src/as_frontend/typing.ml @@ -342,10 +342,10 @@ let check_int8 env = check_lit_val env T.Int8 Value.Int_8.of_string let check_int16 env = check_lit_val env T.Int16 Value.Int_16.of_string let check_int32 env = check_lit_val env T.Int32 Value.Int_32.of_string let check_int64 env = check_lit_val env T.Int64 Value.Int_64.of_string -let check_word8 env = check_lit_val env T.Word8 Value.Word8.of_string_s -let check_word16 env = check_lit_val env T.Word16 Value.Word16.of_string_s -let check_word32 env = check_lit_val env T.Word32 Value.Word32.of_string_s -let check_word64 env = check_lit_val env T.Word64 Value.Word64.of_string_s +let check_word8 env = check_lit_val env T.Word8 Value.Word8.of_string +let check_word16 env = check_lit_val env T.Word16 Value.Word16.of_string +let check_word32 env = check_lit_val env T.Word32 Value.Word32.of_string +let check_word64 env = check_lit_val env T.Word64 Value.Word64.of_string let check_float env = check_lit_val env T.Float Value.Float.of_string diff --git a/src/as_values/value.ml b/src/as_values/value.ml index 3443b7c40e7..8fc15121299 100644 --- a/src/as_values/value.ml +++ b/src/as_values/value.ml @@ -105,10 +105,6 @@ struct let s' = dig ^ (if i = 4 then "_" else "") ^ s in to_pretty_string' (WasmInt.div_u w base) (i mod 4 + 1) s' let to_string = to_pretty_string - let of_string_s s = - if String.length s > 0 && String.get s 0 = '-' - then neg (of_string_u (String.sub s 1 (String.length s - 1))) - else of_string_u s end module Int32Rep = struct include Int32 let bitwidth = 32 end diff --git a/src/exes/didc.ml b/src/exes/didc.ml index 813eac9c776..36e3848f02e 100644 --- a/src/exes/didc.ml +++ b/src/exes/didc.ml @@ -61,7 +61,7 @@ let print_exn exn = let () = (* Sys.catch_break true; - enable to get stacktrace on interrupt - (usefull for debugging infinite loops) + (useful for debugging infinite loops) *) Printexc.record_backtrace true; try diff --git a/test/fail/bad-unops.as b/test/fail/bad-unops.as index 41e4cb3f5d4..ef58e879cb6 100644 --- a/test/fail/bad-unops.as +++ b/test/fail/bad-unops.as @@ -12,7 +12,7 @@ ignore (switch (-1) { case (+1) "hmmm"; case _ "as expected" }); ignore (switch (-1) { case (-1) "as expected"; case _ "hmmm" }); ignore (switch (^1 : Word8) { case (^1) "as expected"; case _ "hmmm" }); -//switch (+1 : Word8) { case (+1) "as expected"; case _ "hmmm" }; // both `+1` are not accepted +ignore (switch (+1 : Word8) { case (+1) "as expected"; case _ "hmmm" }); ignore (switch (-1 : Word8) { case (-1) "as expected"; case _ "hmmm" }); // when testing the switch expression in the REPL, I either diff --git a/test/fail/ok/word-range.tc.ok b/test/fail/ok/word-range.tc.ok new file mode 100644 index 00000000000..cd5a6292265 --- /dev/null +++ b/test/fail/ok/word-range.tc.ok @@ -0,0 +1,24 @@ +word-range.as:31.17-31.20: type error, literal out of range for type Word8 +word-range.as:32.17-32.22: type error, literal out of range for type Word8 +word-range.as:33.17-33.21: type error, literal out of range for type Word8 +word-range.as:34.17-34.23: type error, literal out of range for type Word8 +word-range.as:35.17-35.21: type error, literal out of range for type Word8 +word-range.as:36.17-36.22: type error, literal out of range for type Word8 +word-range.as:37.18-37.23: type error, literal out of range for type Word16 +word-range.as:38.18-38.25: type error, literal out of range for type Word16 +word-range.as:39.18-39.24: type error, literal out of range for type Word16 +word-range.as:40.18-40.26: type error, literal out of range for type Word16 +word-range.as:41.18-41.24: type error, literal out of range for type Word16 +word-range.as:42.18-42.25: type error, literal out of range for type Word16 +word-range.as:43.18-43.28: type error, literal out of range for type Word32 +word-range.as:44.18-44.29: type error, literal out of range for type Word32 +word-range.as:45.18-45.29: type error, literal out of range for type Word32 +word-range.as:46.18-46.30: type error, literal out of range for type Word32 +word-range.as:47.18-47.29: type error, literal out of range for type Word32 +word-range.as:48.18-48.29: type error, literal out of range for type Word32 +word-range.as:49.18-49.44: type error, literal out of range for type Word64 +word-range.as:50.18-50.37: type error, literal out of range for type Word64 +word-range.as:51.18-51.45: type error, literal out of range for type Word64 +word-range.as:52.18-52.38: type error, literal out of range for type Word64 +word-range.as:53.18-53.44: type error, literal out of range for type Word64 +word-range.as:54.18-54.37: type error, literal out of range for type Word64 diff --git a/test/fail/word-range.as b/test/fail/word-range.as new file mode 100644 index 00000000000..85d6df286eb --- /dev/null +++ b/test/fail/word-range.as @@ -0,0 +1,54 @@ +// Tests that the non-canonical range for words is accepted as literals, +// and conversely literals out of the range are rejected. + +// accept these +let _ : Word8 = 255; +let _ : Word8 = 0xFF; +let _ : Word8 = +255; +let _ : Word8 = +0xFF; +let _ : Word8 = -128; +let _ : Word8 = -0x80; +let _ : Word16 = 65535; +let _ : Word16 = 0xFFFF; +let _ : Word16 = +65535; +let _ : Word16 = +0xFFFF; +let _ : Word16 = -32768; +let _ : Word16 = -0x8000; +let _ : Word32 = 4294967295; +let _ : Word32 = 0xFFFFFFFF; +let _ : Word32 = +4294967295; +let _ : Word32 = +0xFFFFFFFF; +let _ : Word32 = -2147483648; +let _ : Word32 = -0x80000000; +let _ : Word64 = 18_446_744_073_709_551_615; +let _ : Word64 = 0xFFFFFFFFFFFFFFFF; +let _ : Word64 = +18_446_744_073_709_551_615; +let _ : Word64 = +0xFFFFFFFFFFFFFFFF; +let _ : Word64 = -9_223_372_036_854_775_808; +let _ : Word64 = -0x8000000000000000; + +// reject these +let _ : Word8 = 256; +let _ : Word8 = 0x100; +let _ : Word8 = +256; +let _ : Word8 = +0x100; +let _ : Word8 = -129; +let _ : Word8 = -0x81; +let _ : Word16 = 65536; +let _ : Word16 = 0x10000; +let _ : Word16 = +65536; +let _ : Word16 = +0x10000; +let _ : Word16 = -32769; +let _ : Word16 = -0x8001; +let _ : Word32 = 4294967296; +let _ : Word32 = 0x100000000; +let _ : Word32 = +4294967296; +let _ : Word32 = +0x100000000; +let _ : Word32 = -2147483649; +let _ : Word32 = -0x80000001; +let _ : Word64 = 18_446_744_073_709_551_616; +let _ : Word64 = 0x10000000000000000; +let _ : Word64 = +18_446_744_073_709_551_616; +let _ : Word64 = +0x10000000000000000; +let _ : Word64 = -9_223_372_036_854_775_809; +let _ : Word64 = -0x8000000000000001; From b286faf7f956b204788dc4c78c78a5a85c5df452 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 17 Sep 2019 17:13:06 +0100 Subject: [PATCH 0380/1176] Try to fix user guide hydra output --- default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/default.nix b/default.nix index fa5118a26d7..c858a034a9b 100644 --- a/default.nix +++ b/default.nix @@ -326,7 +326,7 @@ rec { mv * $out/ rm $out/Makefile mkdir -p $out/nix-support - echo "report guide $out/guide index.html" >> $out/nix-support/hydra-build-products + echo "report guide $out index.html" >> $out/nix-support/hydra-build-products ''; }; From 1f1e21f9033d3851072a036d51b09bf39b0d4f85 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 18 Sep 2019 22:08:10 +0100 Subject: [PATCH 0381/1176] Support new System API ACT-117 (#628) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Defaults to thew new System API (with reduced functionality) * Pulls in `drun` and uses it in the tests in `test/run-drun` * Supports the old System API with `-ancient-system-api`, all tests still executed * Now defaults to “No use of multi-value” (the hack to fake it needs to be made more robust) * On the new platform, do use `memory.grow`, as the System does not implement that yet. --- default.nix | 36 +- src/codegen/compile.ml | 364 +++++++++++++----- src/codegen/compile.mli | 2 +- src/codegen/flags.ml | 3 +- src/exes/asc.ml | 13 +- src/ir_def/construct.ml | 6 + src/ir_def/construct.mli | 1 + src/ir_passes/async.ml | 32 +- src/ir_passes/async.mli | 6 +- src/js/as_js.ml | 2 +- src/linking/linkModule.ml | 20 +- src/pipeline/pipeline.ml | 15 +- src/pipeline/pipeline.mli | 2 +- stdlib/Makefile | 67 +--- test/Makefile | 5 + test/drun-wrapper.sh | 14 + test/fail/ok/use-before-define5.did.ok | 3 + test/ld/ok/representative.linked.wat.ok | 1 - test/random/Main.hs | 4 +- test/random/README.md | 2 +- test/repl/type-lub-repl.sh | 2 +- test/run-dfinity/Makefile | 2 +- test/{run => run-dfinity}/async-calls.as | 0 test/{run => run-dfinity}/control.as | 0 test/run-dfinity/ok/async-calls.did.ok | 5 + test/run-dfinity/ok/control.did.ok | 10 + test/{run => run-dfinity}/type-lub.as | 0 test/run-drun/Makefile | 12 + test/run-drun/counter.as | 14 + test/run-drun/hello-world-return.as | 11 + test/run-drun/idl-tuple.as | 7 + test/run-drun/idl-unit.as | 7 + test/run-drun/ok/counter.did.ok | 4 + test/run-drun/ok/counter.drun-run.ok | 17 + test/run-drun/ok/hello-world-return.did.ok | 5 + .../ok/hello-world-return.drun-run.ok | 3 + test/run-drun/ok/idl-tuple.did.ok | 5 + test/run-drun/ok/idl-tuple.drun-run.ok | 2 + test/run-drun/ok/idl-unit.did.ok | 3 + test/run-drun/ok/idl-unit.drun-run.ok | 2 + test/run-drun/ok/print-from-init.did.ok | 2 + test/run-drun/ok/print-from-init.drun-run.ok | 2 + test/run-drun/ok/print-from-init.run-ir.ok | 1 + test/run-drun/ok/print-from-init.run-low.ok | 1 + test/run-drun/ok/print-from-init.run.ok | 1 + test/run-drun/print-from-init.as | 3 + test/run.sh | 65 ++-- test/run/actors.as | 22 -- test/run/ok/actors.run-ir.ok | 2 - test/run/ok/actors.run-low.ok | 2 - test/run/ok/actors.run.ok | 2 - test/run/ok/actors.wasm-run.ok | 1 - test/run/ok/async-calls.wasm-run.ok | 1 - test/run/ok/coverage.idl.stderr.ok | 101 +++++ test/run/ok/for.wasm-run.ok | 1 - test/run/ok/issue120.did.ok | 5 + test/run/ok/issue442.idl.stderr.ok | 6 + test/run/ok/objects1.idl.stderr.ok | 10 + test/run/ok/pat-subtyping.idl.stderr.ok | 41 ++ test/run/ok/switch.idl.stderr.ok | 17 + test/run/ok/type-inference.idl.stderr.ok | 37 ++ test/run/ok/type-lub.wasm-run.ok | 1 - test/run/ok/variants.wasm-run.ok | 1 - test/run/ok/words.wasm-run.ok | 1 - 64 files changed, 756 insertions(+), 279 deletions(-) create mode 100755 test/drun-wrapper.sh create mode 100644 test/fail/ok/use-before-define5.did.ok rename test/{run => run-dfinity}/async-calls.as (100%) rename test/{run => run-dfinity}/control.as (100%) create mode 100644 test/run-dfinity/ok/async-calls.did.ok create mode 100644 test/run-dfinity/ok/control.did.ok rename test/{run => run-dfinity}/type-lub.as (100%) create mode 100644 test/run-drun/Makefile create mode 100644 test/run-drun/counter.as create mode 100644 test/run-drun/hello-world-return.as create mode 100644 test/run-drun/idl-tuple.as create mode 100644 test/run-drun/idl-unit.as create mode 100644 test/run-drun/ok/counter.did.ok create mode 100644 test/run-drun/ok/counter.drun-run.ok create mode 100644 test/run-drun/ok/hello-world-return.did.ok create mode 100644 test/run-drun/ok/hello-world-return.drun-run.ok create mode 100644 test/run-drun/ok/idl-tuple.did.ok create mode 100644 test/run-drun/ok/idl-tuple.drun-run.ok create mode 100644 test/run-drun/ok/idl-unit.did.ok create mode 100644 test/run-drun/ok/idl-unit.drun-run.ok create mode 100644 test/run-drun/ok/print-from-init.did.ok create mode 100644 test/run-drun/ok/print-from-init.drun-run.ok create mode 100644 test/run-drun/ok/print-from-init.run-ir.ok create mode 100644 test/run-drun/ok/print-from-init.run-low.ok create mode 100644 test/run-drun/ok/print-from-init.run.ok create mode 100644 test/run-drun/print-from-init.as delete mode 100644 test/run/actors.as delete mode 100644 test/run/ok/actors.run-ir.ok delete mode 100644 test/run/ok/actors.run-low.ok delete mode 100644 test/run/ok/actors.run.ok delete mode 100644 test/run/ok/actors.wasm-run.ok delete mode 100644 test/run/ok/async-calls.wasm-run.ok create mode 100644 test/run/ok/coverage.idl.stderr.ok delete mode 100644 test/run/ok/for.wasm-run.ok create mode 100644 test/run/ok/issue120.did.ok create mode 100644 test/run/ok/issue442.idl.stderr.ok create mode 100644 test/run/ok/objects1.idl.stderr.ok create mode 100644 test/run/ok/pat-subtyping.idl.stderr.ok create mode 100644 test/run/ok/switch.idl.stderr.ok create mode 100644 test/run/ok/type-inference.idl.stderr.ok delete mode 100644 test/run/ok/type-lub.wasm-run.ok delete mode 100644 test/run/ok/variants.wasm-run.ok delete mode 100644 test/run/ok/words.wasm-run.ok diff --git a/default.nix b/default.nix index c858a034a9b..a8dfc7a11cd 100644 --- a/default.nix +++ b/default.nix @@ -1,6 +1,6 @@ { nixpkgs ? (import ./nix/nixpkgs.nix).nixpkgs {}, - test-dvm ? true, dvm ? null, + drun ? null, export-shell ? false, replay ? 0 }: @@ -30,14 +30,22 @@ let dev = import (builtins.fetchGit { rev = "ad50bcea8db6d55decf2622ad836435aa36fa33f"; }) { system = nixpkgs.system; }; in -# Include dvm +let dfinity-repo = import (builtins.fetchGit { + url = "ssh://git@github.com/dfinity-lab/dfinity"; + ref = "master"; + rev = "a50367859416ef7c12ca103b7fc03f5a7654f6ad"; +}) { system = nixpkgs.system; }; in + let real-dvm = if dvm == null - then if test-dvm - then dev.dvm - else null + then dev.dvm else dvm; in +let real-drun = + if drun == null + then dfinity-repo.dfinity.drun + else drun; in + # Include js-client let js-client = dev.js-dfinity-client; in @@ -167,8 +175,10 @@ rec { nixpkgs.nodejs-10_x filecheck js-client + dvm + drun + qc-actorscript ] ++ - (if test-dvm then [ real-dvm qc-actorscript ] else []) ++ llvmBuildInputs; buildPhase = '' @@ -179,23 +189,15 @@ rec { export DIDC=didc export JSCLIENT=${js-client} asc --version - '' + - (if test-dvm then '' make parallel qc-actorscript${replay-option} - '' else '' - make quick - ''); + ''; installPhase = '' touch $out ''; }; - tests-no-mv = tests.overrideAttrs (oldAttrs: { - ASC_FLAGS = "-no-multi-value"; - }); - unit-tests = stdenv.mkDerivation { name = "unit-tests"; @@ -240,8 +242,8 @@ rec { nixpkgs.bash nixpkgs.perl filecheck + real-drun ] ++ - (if test-dvm then [ real-dvm ] else []) ++ llvmBuildInputs; buildPhase = '' @@ -297,6 +299,7 @@ rec { wasm = ocaml_wasm; dvm = real-dvm; + drun = real-drun; filecheck = nixpkgs.linkFarm "FileCheck" [ { name = "bin/FileCheck"; path = "${nixpkgs.llvm}/bin/FileCheck";} ]; wabt = nixpkgs.wabt; @@ -419,7 +422,6 @@ rec { js didc tests - tests-no-mv unit-tests samples rts diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index a206814457c..b2d78dcbced 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -81,7 +81,7 @@ in one big record, for convenience). The fields fall into the following categories: 1. Static global fields. Never change. - Example: whether we are compiling with -no-dfinity-api; the prelude code + Example: whether we are compiling with -no-system-api; the prelude code 2. Immutable global fields. Change in a well-scoped manner. Example: Mapping from ActorScript names to their location. @@ -106,7 +106,7 @@ The fields fall into the following categories: (* Before we can define the environment, we need some auxillary types *) -type mode = WasmMode | DfinityMode +type mode = WasmMode | AncientMode | ICMode module E = struct @@ -227,6 +227,7 @@ module E = struct ignore (reg env.exports e) let add_dfinity_type (env : t) e = + assert (mode env = AncientMode); ignore (reg env.dfinity_types e) let reserve_fun (env : t) name = @@ -303,7 +304,7 @@ module E = struct | Some (Defined fi) -> G.i (Call (nr fi)) | _ -> Printf.eprintf "Function import not declared: %s\n" name; - assert false + G.i Unreachable let get_prelude (env : t) = env.prelude let get_rts (env : t) = env.rts @@ -486,7 +487,7 @@ module FakeMultiVal = struct If the multi_value flag is on, these do not do anything. *) - let first_multival_global = 6 + let first_multival_global = 7 let ty tys = if !Flags.multi_value || List.length tys <= 1 @@ -537,7 +538,7 @@ module Func = struct (* Shorthands for various arities *) - let _share_code0 env name retty mk_body = + let share_code0 env name retty mk_body = share_code env name [] retty (fun env -> mk_body env) let share_code1 env name p1 retty mk_body = share_code env name [p1] retty (fun env -> mk_body env @@ -624,16 +625,18 @@ module RTS = struct }); let idl_trap_fi = E.add_fun env "idl_trap" ( Func.of_body env ["str", I32Type; "len", I32Type] [] (fun env -> - begin - if E.mode env = DfinityMode then - let get_str = G.i (LocalGet (nr 0l)) in - let get_len = G.i (LocalGet (nr 1l)) in - get_str ^^ get_len ^^ - E.call_import env "data" "externalize" ^^ - E.call_import env "test" "print" - else G.nop - end ^^ - E.trap_with env "IDL error: Unknown error" + let get_str = G.i (LocalGet (nr 0l)) in + let get_len = G.i (LocalGet (nr 1l)) in + get_str ^^ get_len ^^ + match E.mode env with + | AncientMode -> + E.call_import env "data" "externalize" ^^ + E.call_import env "test" "print" ^^ + G.i Unreachable + | ICMode -> + E.call_import env "debug" "print" ^^ + G.i Unreachable + | WasmMode -> G.i Unreachable ) ) in E.add_export env (nr { @@ -660,7 +663,10 @@ module Heap = struct (* Page allocation. Ensures that the memory up to the given unskewed pointer is allocated. *) let grow_memory env = - Func.share_code1 env "grow_memory" ("ptr", I32Type) [] (fun env get_ptr -> + (* No growing of memory on drun yet *) + if E.mode env = ICMode + then G.i Drop + else Func.share_code1 env "grow_memory" ("ptr", I32Type) [] (fun env get_ptr -> let (set_pages_needed, get_pages_needed) = new_local env "pages_needed" in get_ptr ^^ compile_divU_const page_size ^^ compile_add_const 1l ^^ @@ -2892,8 +2898,18 @@ end (* Tuple *) module Dfinity = struct (* Dfinity-specific stuff: System imports, databufs etc. *) + let api_nonce_global = 6l + let set_api_nonce = G.i (GlobalSet (nr api_nonce_global)) + let get_api_nonce = G.i (GlobalGet (nr api_nonce_global)) + let system_imports env = - begin + match E.mode env with + | ICMode -> + E.add_func_import env "debug" "print" [I32Type; I32Type] []; + E.add_func_import env "msg" "arg_data_size" [I64Type] [I32Type]; + E.add_func_import env "msg" "arg_data_copy" [I64Type; I32Type; I32Type; I32Type] []; + E.add_func_import env "msg" "reply" [I64Type; I32Type; I32Type] [] + | AncientMode -> E.add_func_import env "test" "print" [I32Type] []; E.add_func_import env "test" "show_i32" [I32Type] [I32Type]; E.add_func_import env "data" "externalize" [I32Type; I32Type] [I32Type]; @@ -2908,13 +2924,10 @@ module Dfinity = struct E.add_func_import env "actor" "export" [I32Type; I32Type] [I32Type]; E.add_func_import env "func" "internalize" [I32Type; I32Type] []; E.add_func_import env "func" "externalize" [I32Type] [I32Type]; - E.add_func_import env "func" "bind_i32" [I32Type; I32Type] [I32Type]; - end + E.add_func_import env "func" "bind_i32" [I32Type; I32Type] [I32Type] + | _ -> () - let system_call env modname funcname = - if E.mode env = DfinityMode - then E.call_import env modname funcname - else G.i Unreachable + let system_call env modname funcname = E.call_import env modname funcname let compile_databuf_of_text env = Func.share_code1 env "databuf_of_text" ("string", I32Type) [I32Type] (fun env get_string -> @@ -2933,10 +2946,22 @@ module Dfinity = struct let compile_databuf_of_bytes env (bytes : string) = Text.lit env bytes ^^ compile_databuf_of_text env + let prim_print env = + match E.mode env with + | WasmMode -> G.i Drop + | ICMode -> + Func.share_code1 env "print_text" ("str", I32Type) [] (fun env get_str -> + get_str ^^ Text.payload_ptr_unskewed ^^ + get_str ^^ Heap.load_field (Text.len_field) ^^ + system_call env "debug" "print" + ) + | AncientMode -> + compile_databuf_of_text env ^^ + system_call env "test" "print" + (* For debugging *) let compile_static_print env s = - compile_databuf_of_bytes env s ^^ - system_call env "test" "print" + Text.lit env s ^^ prim_print env let _compile_println_int env = system_call env "test" "show_i32" ^^ @@ -2944,13 +2969,10 @@ module Dfinity = struct compile_static_print env "\n" let trap_with env s = - if E.mode env = DfinityMode - then compile_static_print env (s ^ "\n") ^^ G.i Unreachable - else G.i Unreachable + if E.mode env = WasmMode + then G.i Unreachable + else compile_static_print env (s ^ "\n") ^^ G.i Unreachable - let prim_print env = - compile_databuf_of_text env ^^ - system_call env "test" "print" let default_exports env = (* these exports seem to be wanted by the hypervisor/v8 *) @@ -2964,18 +2986,14 @@ module Dfinity = struct }) let export_start_stub env = - (* Create an empty message *) + assert (E.mode env = AncientMode); let empty_f = Func.of_body env [] [] (fun env1 -> (* Set up memory *) - (if !Flags.fake_orthogonal_persistence - then G.i (Call (nr (E.built_in env1 "restore_mem"))) - else G.nop) ^^ + G.i (Call (nr (E.built_in env1 "restore_mem"))) ^^ (* Collect garbage *) G.i (Call (nr (E.built_in env1 "collect"))) ^^ (* Save memory *) - (if !Flags.fake_orthogonal_persistence - then G.i (Call (nr (E.built_in env1 "save_mem"))) - else G.nop) + G.i (Call (nr (E.built_in env1 "save_mem"))) ) in let fi = E.add_fun env "start_stub" empty_f in E.add_export env (nr { @@ -2984,6 +3002,20 @@ module Dfinity = struct }); E.add_dfinity_type env (fi, []) + let export_start env start_fi = + assert (E.mode env = ICMode); + (* Create an empty message *) + let empty_f = Func.of_body env ["api_nonce",I64Type] [] (fun env1 -> + G.i (Call (nr start_fi)) ^^ + (* Collect garbage *) + G.i (Call (nr (E.built_in env1 "collect"))) + ) in + let fi = E.add_fun env "start_stub" empty_f in + E.add_export env (nr { + name = Wasm.Utf8.decode "canister_init"; + edesc = nr (FuncExport (nr fi)) + }) + let box_reference env = Func.share_code1 env "box_reference" ("ref", I32Type) [I32Type] (fun env get_ref -> Tagged.obj env Tagged.Reference [ @@ -3024,8 +3056,6 @@ module OrthogonalPersistence = struct the global with the end-of-memory pointer to the length. * save_mem simply copies the whole dynamic memory (up to the end-of-memory pointer) to a new databuf and stores that in memstore. - - This does not persist references yet. *) let register env start_funid = @@ -3094,16 +3124,12 @@ module OrthogonalPersistence = struct ) let save_mem env = - if not !Flags.fake_orthogonal_persistence then G.nop else - if E.mode env = DfinityMode - then G.i (Call (nr (E.built_in env "save_mem"))) - else G.i Unreachable + assert (E.mode env = AncientMode); + G.i (Call (nr (E.built_in env "save_mem"))) let restore_mem env = - if not !Flags.fake_orthogonal_persistence then G.nop else - if E.mode env = DfinityMode - then G.i (Call (nr (E.built_in env "restore_mem"))) - else G.i Unreachable + assert (E.mode env = AncientMode); + G.i (Call (nr (E.built_in env "restore_mem"))) end (* OrthogonalPersistence *) @@ -3288,6 +3314,40 @@ module Serialization = struct (fun (h1,_) (h2,_) -> Lib.Uint32.compare h1 h2) (List.map (fun f -> (Idllib.IdlHash.idl_hash f.Type.lab, f)) fs) + (* Checks whether the serialization of a given type could contain references *) + module TS = Set.Make (struct type t = Type.typ let compare = compare end) + let has_no_references : Type.typ -> bool = fun t -> + let open Type in + let seen = ref TS.empty in (* break the cycles *) + let rec go t = + TS.mem t !seen || + begin + seen := TS.add t !seen; + match t with + | Var _ -> assert false + | (Prim _ | Any | Non | Pre) -> true + | Con (c, ts) -> + begin match Con.kind c with + | Abs _ -> assert false + | Def (tbs,t) -> go (open_ ts t) (* TBR this may fail to terminate *) + end + | Array t -> go t + | Tup ts -> List.for_all go ts + | Func (Shared, c, tbs, ts1, ts2) -> false + | Func (s, c, tbs, ts1, ts2) -> + let ts = open_binds tbs in + List.for_all go (List.map (open_ ts) ts1) && + List.for_all go (List.map (open_ ts) ts2) + | Opt t -> go t + | Variant fs -> List.for_all (fun f -> go f.typ) fs + | Async t -> go t + | Obj (Actor, fs) -> false + | Obj (_, fs) -> List.for_all (fun f -> go f.typ) fs + | Mut t -> go t + | Typ _ -> false + end + in go t + (* The IDL serialization prefaces the data with a type description. We can statically create the type description in Ocaml code, store it in the program, and just copy it to the beginning of the message. @@ -3868,10 +3928,38 @@ module Serialization = struct end ) + let reply_with_data env get_data_start get_data_size = + Dfinity.get_api_nonce ^^ + get_data_start ^^ + get_data_size ^^ + Dfinity.system_call env "msg" "reply" + + let argument_data_size env = + Dfinity.get_api_nonce ^^ + Dfinity.system_call env "msg" "arg_data_size" + + let argument_data_copy env get_dest get_length = + Dfinity.get_api_nonce ^^ + get_dest ^^ + get_length ^^ + (compile_unboxed_const 0l) ^^ + Dfinity.system_call env "msg" "arg_data_copy" + + let serialize_unit env = + Func.share_code0 env "@serialize_unit" [] (fun env -> + let data = "DIDL\x00\x00" in + reply_with_data env + (Text.lit env data ^^ Text.payload_ptr_unskewed) + (compile_unboxed_const (Int32.of_int (String.length data))) + ) + let serialize env ts : G.t = let ts_name = String.concat "," (List.map typ_id ts) in let name = "@serialize<" ^ ts_name ^ ">" in - Func.share_code1 env name ("x", I32Type) [I32Type; I32Type] (fun env get_x -> + if E.mode env = ICMode then assert (List.for_all has_no_references ts); + (* On ancient API returns databuf/elembuf, on new API returns nothing *) + let ret_tys = if E.mode env = ICMode then [] else [I32Type; I32Type] in + Func.share_code1 env name ("x", I32Type) ret_tys (fun env get_x -> let (set_data_size, get_data_size) = new_local env "data_size" in let (set_refs_size, get_refs_size) = new_local env "refs_size" in @@ -3914,34 +4002,64 @@ module Serialization = struct G.i (Compare (Wasm.Values.I32 I32Op.Eq)) ^^ E.else_trap_with env "data buffer not filled " ^^ - (* Store it all in a databuf and an elembuf *) - get_data_start ^^ get_data_size ^^ - Dfinity.system_call env "data" "externalize" ^^ + match E.mode env with + | AncientMode -> + (* Store it all in a databuf and an elembuf *) + get_data_start ^^ get_data_size ^^ + Dfinity.system_call env "data" "externalize" ^^ + + get_refs_start ^^ get_refs_size ^^ + Dfinity.system_call env "elem" "externalize" + + | ICMode -> + get_refs_size ^^ + compile_unboxed_const 0l ^^ + G.i (Compare (Wasm.Values.I32 I32Op.Eq)) ^^ + E.else_trap_with env "has_no_references wrong" ^^ + + (* Copy out the bytes *) + reply_with_data env get_data_start get_data_size - get_refs_start ^^ get_refs_size ^^ - Dfinity.system_call env "elem" "externalize" + | WasmMode -> assert false ) let deserialize env ts = + if E.mode env = ICMode then assert (List.for_all has_no_references ts); let ts_name = String.concat "," (List.map typ_id ts) in let name = "@deserialize<" ^ ts_name ^ ">" in - Func.share_code2 env name (("databuf",I32Type),("elembuf", I32Type)) (List.map (fun _ -> I32Type) ts) (fun env get_databuf get_elembuf -> + let args = if E.mode env = ICMode then [] else [("databuf",I32Type);("elembuf", I32Type)] in + Func.share_code env name args (List.map (fun _ -> I32Type) ts) (fun env -> let (set_data_size, get_data_size) = new_local env "data_size" in let (set_refs_size, get_refs_size) = new_local env "refs_size" in let (set_data_start, get_data_start) = new_local env "data_start" in let (set_refs_start, get_refs_start) = new_local env "refs_start" in - (* Allocate space for the data buffer and copy it *) - get_databuf ^^ Dfinity.system_call env "data" "length" ^^ set_data_size ^^ - get_data_size ^^ Text.dyn_alloc_scratch env ^^ set_data_start ^^ - get_data_start ^^ get_data_size ^^ get_databuf ^^ compile_unboxed_const 0l ^^ - Dfinity.system_call env "data" "internalize" ^^ - - (* Allocate space for the reference buffer and copy it *) - get_elembuf ^^ Dfinity.system_call env "elem" "length" ^^ set_refs_size ^^ - get_refs_size ^^ compile_mul_const Heap.word_size ^^ Text.dyn_alloc_scratch env ^^ set_refs_start ^^ - get_refs_start ^^ get_refs_size ^^ get_elembuf ^^ compile_unboxed_const 0l ^^ - Dfinity.system_call env "elem" "internalize" ^^ + begin match E.mode env with + | AncientMode -> + let get_databuf = G.i (LocalGet (nr 0l)) in + let get_elembuf = G.i (LocalGet (nr 1l)) in + + (* Allocate space for the data buffer and copy it *) + get_databuf ^^ Dfinity.system_call env "data" "length" ^^ set_data_size ^^ + get_data_size ^^ Text.dyn_alloc_scratch env ^^ set_data_start ^^ + get_data_start ^^ get_data_size ^^ get_databuf ^^ compile_unboxed_const 0l ^^ + Dfinity.system_call env "data" "internalize" ^^ + + (* Allocate space for the reference buffer and copy it *) + get_elembuf ^^ Dfinity.system_call env "elem" "length" ^^ set_refs_size ^^ + get_refs_size ^^ compile_mul_const Heap.word_size ^^ Text.dyn_alloc_scratch env ^^ set_refs_start ^^ + get_refs_start ^^ get_refs_size ^^ get_elembuf ^^ compile_unboxed_const 0l ^^ + Dfinity.system_call env "elem" "internalize" + | ICMode -> + (* Allocate space for the data buffer and copy it *) + argument_data_size env ^^ set_data_size ^^ + get_data_size ^^ Text.dyn_alloc_scratch env ^^ set_data_start ^^ + argument_data_copy env get_data_start get_data_size ^^ + + (* Allocate space for the reference buffer and copy it *) + compile_unboxed_const 0l ^^ set_refs_size (* none yet *) + | _ -> assert false + end ^^ (* Allocate space for out parameters of parse_idl_header *) Stack.with_words env "get_typtbl_ptr" 1l (fun get_typtbl_ptr -> @@ -4562,6 +4680,7 @@ module FuncDec = struct - Fake orthogonal persistence *) let compile_message outer_env outer_ae cc restore_env args mk_body at = + assert (E.mode outer_env = AncientMode); assert (cc.Call_conv.n_res = 0); let ae0 = ASEnv.mk_fun_ae outer_ae in Func.of_body outer_env ["clos", I32Type; "databuf", I32Type; "elembuf", I32Type] [] (fun env -> G.with_region at ( @@ -4598,36 +4717,58 @@ module FuncDec = struct )) let compile_static_message outer_env outer_ae cc args mk_body ret_tys at : E.func_with_names = - assert (cc.Call_conv.n_res = 0); - let ae0 = ASEnv.mk_fun_ae outer_ae in - Func.of_body outer_env ["databuf", I32Type; "elembuf", I32Type] [] (fun env -> G.with_region at ( - let get_databuf = G.i (LocalGet (nr 0l)) in - let get_elembuf = G.i (LocalGet (nr 1l)) in - - (* Set up memory *) - OrthogonalPersistence.restore_mem env ^^ - - (* Deserialize argument and add params to the environment *) - let arg_names = List.map (fun a -> a.it) args in - let arg_tys = List.map (fun a -> a.note) args in - let (ae1, setters) = ASEnv.add_argument_locals env ae0 arg_names in - get_databuf ^^ get_elembuf ^^ - Serialization.deserialize env arg_tys ^^ - G.concat (List.rev setters) ^^ - mk_body env ae1 ^^ - - (* Collect garbage *) - G.i (Call (nr (E.built_in env "collect"))) ^^ - - (* Save memory *) - OrthogonalPersistence.save_mem env - )) + match E.mode outer_env with + | AncientMode -> + assert (cc.Call_conv.n_res = 0); + let ae0 = ASEnv.mk_fun_ae outer_ae in + Func.of_body outer_env ["databuf", I32Type; "elembuf", I32Type] [] (fun env -> G.with_region at ( + let get_databuf = G.i (LocalGet (nr 0l)) in + let get_elembuf = G.i (LocalGet (nr 1l)) in + + (* Set up memory *) + OrthogonalPersistence.restore_mem env ^^ + + (* Deserialize argument and add params to the environment *) + let arg_names = List.map (fun a -> a.it) args in + let arg_tys = List.map (fun a -> a.note) args in + let (ae1, setters) = ASEnv.add_argument_locals env ae0 arg_names in + get_databuf ^^ get_elembuf ^^ + Serialization.deserialize env arg_tys ^^ + G.concat (List.rev setters) ^^ + mk_body env ae1 ^^ + + (* Collect garbage *) + G.i (Call (nr (E.built_in env "collect"))) ^^ + + (* Save memory *) + OrthogonalPersistence.save_mem env + )) + | ICMode -> + let ae0 = ASEnv.mk_fun_ae outer_ae in + Func.of_body outer_env ["api_nonce", I64Type] [] (fun env -> G.with_region at ( + G.i (LocalGet (nr 0l)) ^^ Dfinity.set_api_nonce ^^ + + (* Deserialize argument and add params to the environment *) + let arg_names = List.map (fun a -> a.it) args in + let arg_tys = List.map (fun a -> a.note) args in + let (ae1, setters) = ASEnv.add_argument_locals env ae0 arg_names in + Serialization.deserialize env arg_tys ^^ + G.concat (List.rev setters) ^^ + mk_body env ae1 ^^ + (* Hack: Emit a unit response for one-shot functions *) + if ret_tys = [] then Serialization.serialize_unit env else G.nop ^^ + + (* Collect garbage *) + G.i (Call (nr (E.built_in env "collect"))) + )) + | WasmMode -> assert false let declare_dfinity_type env has_closure fi = - E.add_dfinity_type env (fi, - (if has_closure then [ Wasm_exts.CustomModule.I32 ] else []) @ - [ Wasm_exts.CustomModule.DataBuf; Wasm_exts.CustomModule.ElemBuf ] - ) + if E.mode env = AncientMode then + E.add_dfinity_type env (fi, + (if has_closure then [ Wasm_exts.CustomModule.I32 ] else []) @ + [ Wasm_exts.CustomModule.DataBuf; Wasm_exts.CustomModule.ElemBuf ] + ) (* Compile a closed function declaration (captures no local variables) *) let closed pre_env cc name args mk_body ret_tys at = @@ -5908,6 +6049,13 @@ and compile_exp (env : E.t) ae exp = set_b ^^ compile_const_64 1L ^^ get_b ^^ G.i (Binary (Wasm.Values.I64 I64Op.Shl)) ^^ G.i (Binary (Wasm.Values.I64 I64Op.And)) ) + + | OtherPrim "reply", [e] -> + SR.unit, + compile_exp_vanilla env ae e ^^ + Serialization.serialize env [e.note.note_typ] + + (* Unknown prim *) | _ -> SR.Unreachable, todo_trap env "compile_exp" (Arrange_ir.exp exp) end | VarE var -> @@ -6449,7 +6597,10 @@ and export_actor_field env ae (f : Ir.field) = assert (G.is_nop code); FuncDec.declare_dfinity_type env false fi; E.add_export env (nr { - name = Wasm.Utf8.decode f.it.name; + name = Wasm.Utf8.decode (match E.mode env with + | AncientMode -> f.it.name + | ICMode -> "canister_update " ^ f.it.name + | _ -> assert false); edesc = nr (FuncExport (nr fi)) }) @@ -6463,7 +6614,7 @@ and actor_lit outer_env this ds fs at = (E.get_trap_with outer_env) ClosureTable.table_end in - if E.mode mod_env = DfinityMode then Dfinity.system_imports mod_env; + Dfinity.system_imports mod_env; RTS.system_imports mod_env; RTS.system_exports mod_env; @@ -6485,7 +6636,8 @@ and actor_lit outer_env this ds fs at = prelude_code ^^ decls_code) in let start_fi = E.add_fun mod_env "start" start_fun in - OrthogonalPersistence.register mod_env start_fi; + if E.mode mod_env = ICMode then Dfinity.export_start mod_env start_fi; + if E.mode mod_env = AncientMode then OrthogonalPersistence.register mod_env start_fi; let m = conclude_module mod_env this None in let (_map, wasm_binary) = Wasm_exts.CustomModuleEncode.encode m in @@ -6569,6 +6721,10 @@ and conclude_module env module_name start_fi_o = nr { gtype = GlobalType (I32Type, Mutable); value = nr (G.to_instr_list compile_unboxed_zero) }; + (* current api_nonce *) + nr { gtype = GlobalType (I64Type, Mutable); + value = nr (G.to_instr_list (compile_const_64 Int64.zero)) + }; ] @ (* multi value return emulations *) begin if !Flags.multi_value then [] else @@ -6621,10 +6777,10 @@ and conclude_module env module_name start_fi_o = List.mapi (fun i (f,_,ln) -> Int32.(add ni' (of_int i), ln)) funcs; }; types = E.get_dfinity_types env; - persist = + persist = if E.mode env = AncientMode then [ (OrthogonalPersistence.mem_global, Wasm_exts.CustomModule.DataBuf) ; (OrthogonalPersistence.elem_global, Wasm_exts.CustomModule.ElemBuf) - ]; + ] else []; } in match E.get_rts env with @@ -6634,18 +6790,18 @@ and conclude_module env module_name start_fi_o = let compile mode module_name rts (prelude : Ir.prog) (progs : Ir.prog list) : Wasm_exts.CustomModule.extended_module = let env = E.mk_global mode rts prelude Dfinity.trap_with ClosureTable.table_end in - if E.mode env = DfinityMode then Dfinity.system_imports env; + Dfinity.system_imports env; RTS.system_imports env; RTS.system_exports env; let start_fun = compile_start_func env (prelude :: progs) in let start_fi = E.add_fun env "start" start_fun in - let start_fi_o = - if E.mode env = DfinityMode - then begin + let start_fi_o = match E.mode env with + | AncientMode -> OrthogonalPersistence.register env start_fi; Dfinity.export_start_stub env; None - end else Some (nr start_fi) in + | ICMode -> Dfinity.export_start env start_fi; None + | WasmMode -> Some (nr start_fi) in conclude_module env module_name start_fi_o diff --git a/src/codegen/compile.mli b/src/codegen/compile.mli index 15f98fa3712..2cc6cdf680e 100644 --- a/src/codegen/compile.mli +++ b/src/codegen/compile.mli @@ -1,5 +1,5 @@ open Ir_def -type mode = WasmMode | DfinityMode +type mode = WasmMode | AncientMode | ICMode val compile : mode -> string -> Wasm_exts.CustomModule.extended_module option -> Ir.prog -> Ir.prog list -> Wasm_exts.CustomModule.extended_module diff --git a/src/codegen/flags.ml b/src/codegen/flags.ml index 6d8e7f786fb..848563b2737 100644 --- a/src/codegen/flags.ml +++ b/src/codegen/flags.ml @@ -1,2 +1 @@ -let fake_orthogonal_persistence = ref true -let multi_value = ref true +let multi_value = ref false diff --git a/src/exes/asc.ml b/src/exes/asc.ml index fba387d4ede..cc18ebd30eb 100644 --- a/src/exes/asc.ml +++ b/src/exes/asc.ml @@ -22,7 +22,7 @@ let set_mode m () = end; mode := m -let compile_mode = ref Pipeline.DfinityMode +let compile_mode = ref Pipeline.ICMode let out_file = ref "" let link = ref true let interpret_ir = ref false @@ -34,7 +34,7 @@ let argspec = Arg.align "-r", Arg.Unit (set_mode Run), " interpret programs"; "-i", Arg.Unit (set_mode Interact), " run interactive REPL (implies -r)"; "--check", Arg.Unit (set_mode Check), " type-check only"; - "--idl", Arg.Unit (set_mode Idl), " generate IDL spec"; + "--idl", Arg.Unit (set_mode Idl), " generate IDL spec"; "-v", Arg.Set Pipeline.Flags.verbose, " verbose output"; "-p", Arg.Set_int Pipeline.Flags.print_depth, " set print depth"; "-o", Arg.Set_string out_file, " output file"; @@ -66,10 +66,13 @@ let argspec = Arg.align "-no-async", Arg.Clear Pipeline.Flags.async_lowering, " no async-lowering (with -iR)"; "-no-link", Arg.Clear link, " do not statically link-in runtime"; - "-no-dfinity-api", + "-no-system-api", Arg.Unit (fun () -> compile_mode := Pipeline.WasmMode), - " do not import the DFINITY system API"; - "-no-fake-op", Arg.Clear Codegen.Flags.fake_orthogonal_persistence, " do not fake OP"; + " do not import the any system API"; + "-ancient-system-api", + Arg.Unit (fun () -> compile_mode := Pipeline.AncientMode), + " use the ancient DFINITY system API (dvm)"; + "-multi-value", Arg.Set Codegen.Flags.multi_value, " use multi-value extension"; "-no-multi-value", Arg.Clear Codegen.Flags.multi_value, " avoid multi-value extension"; "-dp", Arg.Set Pipeline.Flags.dump_parse, " dump parse"; diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index 07a53d421a9..50cff75a573 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -106,6 +106,12 @@ let awaitE typ e1 e2 = note = { note_typ = T.unit; note_eff = max_eff (eff e1) (eff e2) } } +let replyE e = + { it = PrimE (OtherPrim "reply", [e]); + at = no_region; + note = { note_typ = T.unit; note_eff = eff e } + } + (* tuples *) diff --git a/src/ir_def/construct.mli b/src/ir_def/construct.mli index 13c4152fe66..51508d2885b 100644 --- a/src/ir_def/construct.mli +++ b/src/ir_def/construct.mli @@ -42,6 +42,7 @@ val as_seqP : pat -> pat list val primE : Ir.prim -> exp list -> exp val asyncE : typ -> exp -> exp val awaitE : typ -> exp -> exp -> exp +val replyE : exp -> exp val projE : exp -> int -> exp val blockE : dec list -> exp -> exp val textE : string -> exp diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index f19069a97eb..6d4e8824dce 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -21,7 +21,11 @@ open Construct (* written as a functor so we can allocate some temporary shared state without making it global *) -module Transform() = struct +type platform = + V1 (* legacy, Haskell *) + | V2 (* new, Rust *) + +module Transform(Platform : sig val platform : platform end) = struct module ConRenaming = E.Make(struct type t = T.con let compare = Con.compare end) @@ -38,20 +42,10 @@ module Transform() = struct let con_renaming = ref ConRenaming.empty - (* Configuring the translation for target platform V1 or V2 *) - - type platform = - V1 (* legacy, Haskell *) - | V2 (* new, Rust *) - - let platform = V1 - - let _ = V2 (* suppress warning on unused V2 *) - (* Lowering options, specific to V1 or V2 *) let add_reply_parameter, add_reply_argument = - match platform with + match Platform.platform with | V1 -> (true, true) | V2 -> (false, true) @@ -68,17 +62,18 @@ module Transform() = struct implemented (as far as possible) for V1; TBC for V2 *) + (* NB: The type annotations on the v needs to match the IDL type of the function *) let sys_replyE v = - match platform with + match Platform.platform with | V1 -> assert false (* never required in V1, `reply` is by calling continuation*) - | V2 -> failwith "NYI" (* TODO: call dedicated prim *) + | V2 -> replyE v let sys_callE v1 typs vs reply = - match platform with + match Platform.platform with | V1 -> assert add_reply_argument; callE v1 typs (seqE (vs @ [reply])) - | V2 -> failwith "NYI" (* TODO: call dedicated prim, separating args vs from reply *) + | V2 -> assert false (* NYI, needs a dedicated prim, separating args vs from reply *) (* End of configuration *) @@ -451,8 +446,9 @@ module Transform() = struct end -let transform env prog = - let module T = Transform() in +let transform platform = + let module T = Transform(struct let platform = platform end) in + fun env prog -> (* Initialized the con_renaming with those type constructors already in scope. Eventually, pipeline will allow us to pass the con_renaming to downstream program diff --git a/src/ir_passes/async.mli b/src/ir_passes/async.mli index c0fc1977ef3..7f6ec8652e0 100644 --- a/src/ir_passes/async.mli +++ b/src/ir_passes/async.mli @@ -1,4 +1,8 @@ (* lower uses of async type appropriately *) open Ir_def -val transform : As_types.Scope.scope -> Ir.prog -> Ir.prog +type platform = + V1 (* legacy, Haskell *) + | V2 (* new, Rust *) + +val transform : platform -> As_types.Scope.scope -> Ir.prog -> Ir.prog diff --git a/src/js/as_js.ml b/src/js/as_js.ml index 3c23d072c70..1ffd4fd159b 100644 --- a/src/js/as_js.ml +++ b/src/js/as_js.ml @@ -40,7 +40,7 @@ let js_check source = let js_compile_with mode_string source convert = let mode = match Js.to_string mode_string with - | "dfinity" -> Pipeline.DfinityMode + | "dfinity" -> Pipeline.AncientMode | _ -> Pipeline.WasmMode in match Pipeline.compile_string mode (Js.to_string source) "js-input" with diff --git a/src/linking/linkModule.ml b/src/linking/linkModule.ml index 74e1a5babe4..c27ffb43aaf 100644 --- a/src/linking/linkModule.ml +++ b/src/linking/linkModule.ml @@ -72,7 +72,7 @@ let count_imports is_thing m = let remove_export is_thing name : module_' -> module_' = fun m -> let to_remove e = - is_thing e.it.edesc.it <> None && e.it.name = Wasm.Utf8.decode name + not (is_thing e.it.edesc.it <> None && e.it.name = Wasm.Utf8.decode name) in { m with exports = List.filter to_remove m.exports } @@ -177,6 +177,10 @@ let prepend_to_start fi (em : extended_module) = } } +let _remove_non_canister_exports (em : extended_module) : extended_module = + let is_canister_export (exp : export) = Lib.String.chop_prefix "canister_" (Wasm.Utf8.encode exp.it.name) <> None in + map_module (fun m -> { m with exports = List.filter is_canister_export m.exports }) em + module VarMap = Map.Make(Int32) let remove_non_dfinity_exports (em : extended_module) : extended_module = @@ -187,12 +191,22 @@ let remove_non_dfinity_exports (em : extended_module) : extended_module = (fun map (fi, _) -> VarMap.add fi () map) VarMap.empty em.types in - let is_dfinity_export exp = match exp.it.edesc.it with + let is_canister_export (exp : export) = + Lib.String.chop_prefix "canister_" (Wasm.Utf8.encode exp.it.name) <> None in + + let is_interesting_global (exp : export) = + (* For the ancient system API *) + Wasm.Utf8.encode exp.it.name = "datastore" || + Wasm.Utf8.encode exp.it.name = "elemstore" in + + let is_dfinity_export exp = + is_canister_export exp || + match exp.it.edesc.it with | FuncExport var -> VarMap.mem var.it dfinity_exports + | GlobalExport _ -> is_interesting_global exp | _ -> true in map_module (fun m -> { m with exports = List.filter is_dfinity_export m.exports }) em - (* Generic linking logic *) exception LinkError of string diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index afaccae2369..417507732e6 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -451,8 +451,9 @@ let desugar env lib_env libraries progs name = let await_lowering = transform_if "Await Lowering" (fun _ -> Await.transform) -let async_lowering = - transform_if "Async Lowering" Async.transform +let async_lowering mode = + let platform = if mode = Codegen.Compile.ICMode then Async.V2 else Async.V1 in + transform_if "Async Lowering" (Async.transform platform) let tailcall_optimization = transform_if "Tailcall optimization" (fun _ -> Tailcall.transform) @@ -484,7 +485,7 @@ let load_as_rts () = let wasm = load_file wasm_filename in Wasm_exts.CustomModuleDecode.decode "rts.wasm" wasm -type compile_mode = Codegen.Compile.mode = WasmMode | DfinityMode +type compile_mode = Codegen.Compile.mode = WasmMode | AncientMode | ICMode type compile_result = Wasm_exts.CustomModule.extended_module Diag.result let name_progs progs = @@ -492,10 +493,10 @@ let name_progs progs = then "empty" else (Lib.List.last progs).Source.note -let lower_prog senv lib_env libraries progs name = +let lower_prog mode senv lib_env libraries progs name = let prog_ir = desugar senv lib_env libraries progs name in let prog_ir = await_lowering !Flags.await_lowering initial_stat_env prog_ir name in - let prog_ir = async_lowering !Flags.async_lowering initial_stat_env prog_ir name in + let prog_ir = async_lowering mode !Flags.async_lowering initial_stat_env prog_ir name in let prog_ir = tailcall_optimization true initial_stat_env prog_ir name in let prog_ir = show_translation true initial_stat_env prog_ir name in prog_ir @@ -503,7 +504,7 @@ let lower_prog senv lib_env libraries progs name = let compile_prog mode do_link lib_env libraries progs : Wasm_exts.CustomModule.extended_module = let prelude_ir = Lowering.Desugar.transform prelude in let name = name_progs progs in - let prog_ir = lower_prog initial_stat_env lib_env libraries progs name in + let prog_ir = lower_prog mode initial_stat_env lib_env libraries progs name in phase "Compiling" name; let rts = if do_link then Some (load_as_rts ()) else None in Codegen.Compile.compile mode name rts prelude_ir [prog_ir] @@ -523,7 +524,7 @@ let compile_string mode s name : compile_result = let interpret_ir_prog inp_env libraries progs = let prelude_ir = Lowering.Desugar.transform prelude in let name = name_progs progs in - let prog_ir = lower_prog initial_stat_env inp_env libraries progs name in + let prog_ir = lower_prog WasmMode initial_stat_env inp_env libraries progs name in phase "Interpreting" name; let open Interpret_ir in let flags = { trace = !Flags.trace; print_depth = !Flags.print_depth } in diff --git a/src/pipeline/pipeline.mli b/src/pipeline/pipeline.mli index 38330b9ba9c..5eb935d77d5 100644 --- a/src/pipeline/pipeline.mli +++ b/src/pipeline/pipeline.mli @@ -33,7 +33,7 @@ val run_files : string list -> unit option val interpret_ir_files : string list -> unit option val run_files_and_stdin : string list -> unit option -type compile_mode = WasmMode | DfinityMode +type compile_mode = WasmMode | AncientMode | ICMode type compile_result = Wasm_exts.CustomModule.extended_module Diag.result val compile_string : compile_mode -> string -> string -> compile_result diff --git a/stdlib/Makefile b/stdlib/Makefile index 6a48be2e6c6..eae1d34861b 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -1,5 +1,5 @@ ASC=../src/asc -DVM=dvm +DRUN=drun OUTDIR=_out DOCDIR=doc STOPWATCH_C=./tools/stopwatch.c @@ -432,92 +432,53 @@ $(STOPWATCH): $(STOPWATCH_C) gcc $< -o $@ $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm $(STOPWATCH) - rm -rf ./.dvm - $(DVM) reset - $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm - $(STOPWATCH) "$(DVM) run 1 start " "5, 1, " > $@ + $(STOPWATCH) "$(DRUN) $< /dev/zero" "5, 1, " > $@ cat $@ $(OUTDIR)/ProduceExchangeLoadQuery_5_2.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_2.wasm $(STOPWATCH) - rm -rf ./.dvm - $(DVM) reset - $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_2.wasm - $(STOPWATCH) "$(DVM) run 1 start " "5, 2, " > $@ + $(STOPWATCH) "$(DRUN) $< /dev/zero" "5, 2, " > $@ cat $@ $(OUTDIR)/ProduceExchangeLoadQuery_5_3.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_3.wasm $(STOPWATCH) - rm -rf ./.dvm - $(DVM) reset - $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_3.wasm - $(STOPWATCH) "$(DVM) run 1 start " "5, 3, " > $@ + $(STOPWATCH) "$(DRUN) $< /dev/zero" "5, 3, " > $@ cat $@ $(OUTDIR)/ProduceExchangeLoadQuery_5_4.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_4.wasm $(STOPWATCH) - rm -rf ./.dvm - $(DVM) reset - $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_4.wasm - $(STOPWATCH) "$(DVM) run 1 start " "5, 4, " > $@ + $(STOPWATCH) "$(DRUN) $< /dev/zero" "5, 4, " > $@ cat $@ $(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm $(STOPWATCH) - rm -rf ./.dvm - $(DVM) reset - $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm - $(STOPWATCH) "$(DVM) run 1 start " "5, 5, " > $@ + $(STOPWATCH) "$(DRUN) $< /dev/zero" "5, 5, " > $@ cat $@ $(OUTDIR)/ProduceExchangeLoadQuery_5_6.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_6.wasm $(STOPWATCH) - rm -rf ./.dvm - $(DVM) reset - $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_6.wasm - $(STOPWATCH) "$(DVM) run 1 start " "5, 6, " > $@ + $(STOPWATCH) "$(DRUN) $< /dev/zero" "5, 6, " > $@ cat $@ $(OUTDIR)/ProduceExchangeLoadQuery_5_7.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_7.wasm $(STOPWATCH) - rm -rf ./.dvm - $(DVM) reset - $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_7.wasm - $(STOPWATCH) "$(DVM) run 1 start " "5, 7, " > $@ + $(STOPWATCH) "$(DRUN) $< /dev/zero" "5, 7, " > $@ cat $@ $(OUTDIR)/ProduceExchangeLoadQuery_5_8.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_8.wasm $(STOPWATCH) - rm -rf ./.dvm - $(DVM) reset - $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_8.wasm - $(STOPWATCH) "$(DVM) run 1 start " "5, 8, " > $@ + $(STOPWATCH) "$(DRUN) $< /dev/zero" "5, 8, " > $@ cat $@ $(OUTDIR)/ProduceExchangeLoadQuery_5_9.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_9.wasm $(STOPWATCH) - rm -rf ./.dvm - $(DVM) reset - $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm - $(STOPWATCH) "$(DVM) run 1 start " "5, 9, " > $@ + $(STOPWATCH) "$(DRUN) $< /dev/zero" "5, 9, " > $@ cat $@ $(OUTDIR)/ProduceExchangeLoadQuery_5_10.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_10.wasm $(STOPWATCH) - rm -rf ./.dvm - $(DVM) reset - $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_10.wasm - $(STOPWATCH) "$(DVM) run 1 start " "5, 10, " > $@ + $(STOPWATCH) "$(DRUN) $< /dev/zero" "5, 10, " > $@ cat $@ $(OUTDIR)/ProduceExchangeLoadQuery_5_20.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_20.wasm $(STOPWATCH) - rm -rf ./.dvm - $(DVM) reset - $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_20.wasm - $(STOPWATCH) "$(DVM) run 1 start " "5, 20, " > $@ + $(STOPWATCH) "$(DRUN) $< /dev/zero" "5, 20, " > $@ cat $@ $(OUTDIR)/ProduceExchangeLoadQuery_5_50.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_50.wasm $(STOPWATCH) - rm -rf ./.dvm - $(DVM) reset - $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_50.wasm - $(STOPWATCH) "$(DVM) run 1 start " "5, 50, " > $@ + $(STOPWATCH) "$(DRUN) $< /dev/zero" "5, 50, " > $@ cat $@ $(OUTDIR)/ProduceExchangeLoadQuery_5_100.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_100.wasm $(STOPWATCH) - rm -rf ./.dvm - $(DVM) reset - $(DVM) new $(OUTDIR)/ProduceExchangeLoadQuery_5_100.wasm - $(STOPWATCH) "$(DVM) run 1 start " "5, 100, " > $@ + $(STOPWATCH) "$(DRUN) $< /dev/zero" "5, 100, " > $@ cat $@ diff --git a/test/Makefile b/test/Makefile index 254233837e3..9910ef1c9a8 100644 --- a/test/Makefile +++ b/test/Makefile @@ -2,6 +2,7 @@ all: $(MAKE) -C fail $(MAKE) -C run $(MAKE) -C run-dfinity + $(MAKE) -C run-drun $(MAKE) -C repl $(MAKE) -C ld $(MAKE) -C idl @@ -20,6 +21,7 @@ quick: parallel: quick $(MAKE_PAR) -C run-dfinity quick + $(MAKE_PAR) -C run-drun quick $(MAKE_PAR) -C trap quick coverage: @@ -30,6 +32,7 @@ coverage: $(MAKE) -C fail; \ $(MAKE) -C run; \ $(MAKE) -C run-dfinity; \ + $(MAKE) -C run-drun; \ $(MAKE) -C repl; $(MAKE) -C ld || true bisect-ppx-report -I ../src/_build/ -html coverage/ _coverage/bisect*.out @@ -39,6 +42,7 @@ accept: $(MAKE) -C fail accept $(MAKE) -C run accept $(MAKE) -C run-dfinity accept + $(MAKE) -C run-drun accept $(MAKE) -C repl accept $(MAKE) -C ld accept $(MAKE) -C idl accept @@ -50,6 +54,7 @@ clean: $(MAKE) -C fail clean $(MAKE) -C run clean $(MAKE) -C run-dfinity clean + $(MAKE) -C run-drun clean $(MAKE) -C repl clean $(MAKE) -C ld clean $(MAKE) -C as-idl clean diff --git a/test/drun-wrapper.sh b/test/drun-wrapper.sh new file mode 100755 index 00000000000..03e1c1f036a --- /dev/null +++ b/test/drun-wrapper.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +DRUN=${DRUN:-drun} + + +if [ -z "$1" ] +then + echo "Usage: $0 .wasm [call-script]" + exit 1 +fi + +export LANG=C + +( if [ -n "$2" ]; then grep '^//CALL ' $2 | cut -c8-; fi;) | $DRUN $1 /dev/stdin diff --git a/test/fail/ok/use-before-define5.did.ok b/test/fail/ok/use-before-define5.did.ok new file mode 100644 index 00000000000..b753b2ca84c --- /dev/null +++ b/test/fail/ok/use-before-define5.did.ok @@ -0,0 +1,3 @@ +service a { +foo : () -> () oneway; +} diff --git a/test/ld/ok/representative.linked.wat.ok b/test/ld/ok/representative.linked.wat.ok index 92dd30ac74f..207c392a946 100644 --- a/test/ld/ok/representative.linked.wat.ok +++ b/test/ld/ok/representative.linked.wat.ok @@ -28,5 +28,4 @@ (table (;0;) 0 0 anyfunc) (memory (;0;) 2) (global (;0;) i32 (i32.const 65536)) - (export "__heap_base" (global 0)) (start 8)) diff --git a/test/random/Main.hs b/test/random/Main.hs index ab405cbb1e0..4327bd89a76 100644 --- a/test/random/Main.hs +++ b/test/random/Main.hs @@ -55,7 +55,7 @@ matchingProps = testGroup "pattern matching" fileArg = fromString . encodeString script = do Turtle.output as $ fromString testCase res@(exitCode, _, _) <- procStrictWithErr "asc" - ["-no-dfinity-api", "-no-check-ir", fileArg as] empty + ["-no-system-api", "-no-check-ir", fileArg as] empty if ExitSuccess == exitCode then (True,) <$> procStrictWithErr "wasm-interp" ["--enable-multi", fileArg wasm] empty else pure (False, res) @@ -135,7 +135,7 @@ instance Arbitrary TestCase where prop_verifies (TestCase (map fromString -> testCase)) = monadicIO $ do let script cases = do Turtle.output "tests.as" $ msum cases res@(exitCode, _, _) <- procStrictWithErr "asc" - ["-no-dfinity-api", "-no-check-ir", "tests.as"] empty + ["-no-system-api", "-no-check-ir", "tests.as"] empty if ExitSuccess == exitCode then (True,) <$> procStrictWithErr "wasm-interp" ["--enable-multi", "tests.wasm"] empty else pure (False, res) diff --git a/test/random/README.md b/test/random/README.md index ed2fe5dda8d..4653efcf632 100644 --- a/test/random/README.md +++ b/test/random/README.md @@ -44,7 +44,7 @@ Of course you can dump the failing test case into a file, compile it to WASM, and execute it in (e.g.) `wasm-interp`: ``` shell -$ asc -no-dfinity-api snippet.as +$ asc -no-system-api snippet.as $ wasm-interp --enable-multi snippet.wasm ``` diff --git a/test/repl/type-lub-repl.sh b/test/repl/type-lub-repl.sh index 63bae92abd3..7f1092a9702 100755 --- a/test/repl/type-lub-repl.sh +++ b/test/repl/type-lub-repl.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # Tests that correct lub types are inferred when values appear in arrays -${ASC:-$(dirname "$BASH_SOURCE")/../../src/asc} -i ../run/type-lub.as <<__END__ +${ASC:-$(dirname "$BASH_SOURCE")/../../src/asc} -i ../run-dfinity/type-lub.as <<__END__ opts; nulls; incompatible_objs; diff --git a/test/run-dfinity/Makefile b/test/run-dfinity/Makefile index 356eab76f18..3714325baa0 100644 --- a/test/run-dfinity/Makefile +++ b/test/run-dfinity/Makefile @@ -1,4 +1,4 @@ -RUNFLAGS = -d +RUNFLAGS = -1 all: ../run.sh $(RUNFLAGS) *.as diff --git a/test/run/async-calls.as b/test/run-dfinity/async-calls.as similarity index 100% rename from test/run/async-calls.as rename to test/run-dfinity/async-calls.as diff --git a/test/run/control.as b/test/run-dfinity/control.as similarity index 100% rename from test/run/control.as rename to test/run-dfinity/control.as diff --git a/test/run-dfinity/ok/async-calls.did.ok b/test/run-dfinity/ok/async-calls.did.ok new file mode 100644 index 00000000000..d6a2c02c683 --- /dev/null +++ b/test/run-dfinity/ok/async-calls.did.ok @@ -0,0 +1,5 @@ +type Bool = bool; +service async_rec_actor { +is_true : () -> () oneway; +test : (Bool) -> () oneway; +} diff --git a/test/run-dfinity/ok/control.did.ok b/test/run-dfinity/ok/control.did.ok new file mode 100644 index 00000000000..e46e64c3539 --- /dev/null +++ b/test/run-dfinity/ok/control.did.ok @@ -0,0 +1,10 @@ +type Control = service { +testBlock : () -> () oneway; +testLoop : () -> () oneway; +testLoopWhile : () -> () oneway; +testLoopWhile2 : () -> () oneway; +testLoopWhile3 : () -> () oneway; +testLoopWhile4 : () -> () oneway; +testNestedWhile : () -> () oneway; +testWhile : () -> () oneway; +}; diff --git a/test/run/type-lub.as b/test/run-dfinity/type-lub.as similarity index 100% rename from test/run/type-lub.as rename to test/run-dfinity/type-lub.as diff --git a/test/run-drun/Makefile b/test/run-drun/Makefile new file mode 100644 index 00000000000..b45cabbf006 --- /dev/null +++ b/test/run-drun/Makefile @@ -0,0 +1,12 @@ +RUNFLAGS = -2 + +all: + ../run.sh $(RUNFLAGS) *.as + +accept: + ../run.sh $(RUNFLAGS) -a *.as + +clean: + rm -rf _out + +include ../*.mk diff --git a/test/run-drun/counter.as b/test/run-drun/counter.as new file mode 100644 index 00000000000..1be9df19103 --- /dev/null +++ b/test/run-drun/counter.as @@ -0,0 +1,14 @@ +actor { + var c = 1; + public func inc() { + c += 1; + printNat c; print "\n"; + }; + public func printCounter () { + printNat c; print "\n"; + } +} +//CALL ingress inc 0x4449444C0000 +//CALL ingress inc 0x4449444C0000 +//CALL ingress inc 0x4449444C0000 +//CALL ingress printCounter 0x4449444C0000 diff --git a/test/run-drun/hello-world-return.as b/test/run-drun/hello-world-return.as new file mode 100644 index 00000000000..c6e7c727da8 --- /dev/null +++ b/test/run-drun/hello-world-return.as @@ -0,0 +1,11 @@ +actor { + public func hello(who : Text) : async Text { + "Hello " # who # "!"; + }; + public func hello2(who : Text) : async Text { + return ("Hello " # who # "!"); + } +} + +//CALL query hello "DIDL\x00\x01\x71\x05World" +//CALL query hello2 "DIDL\x00\x01\x71\x05World" diff --git a/test/run-drun/idl-tuple.as b/test/run-drun/idl-tuple.as new file mode 100644 index 00000000000..cbadf7cd564 --- /dev/null +++ b/test/run-drun/idl-tuple.as @@ -0,0 +1,7 @@ +actor { + public func len2(x:Text, y:Text) : async (Int,Int) { + (x.len(), y.len()) + } +} + +//CALL query len2 "DIDL\x00\x02\x71\x71\x02Hi\x05World" diff --git a/test/run-drun/idl-unit.as b/test/run-drun/idl-unit.as new file mode 100644 index 00000000000..8402ad366f3 --- /dev/null +++ b/test/run-drun/idl-unit.as @@ -0,0 +1,7 @@ +actor { + public func unit_id() : () { + () + } +} + +//CALL query unit_id "DIDL\x00\x00" diff --git a/test/run-drun/ok/counter.did.ok b/test/run-drun/ok/counter.did.ok new file mode 100644 index 00000000000..2159d70ccfe --- /dev/null +++ b/test/run-drun/ok/counter.did.ok @@ -0,0 +1,4 @@ +service anon_counter { +inc : () -> () oneway; +printCounter : () -> () oneway; +} diff --git a/test/run-drun/ok/counter.drun-run.ok b/test/run-drun/ok/counter.drun-run.ok new file mode 100644 index 00000000000..51a04dc9ef4 --- /dev/null +++ b/test/run-drun/ok/counter.drun-run.ok @@ -0,0 +1,17 @@ +ingress(0) System +debug.print: 2 +debug.print: + +ingress(1) Completed: Canister: Payload: 0x4449444c0000 +debug.print: 3 +debug.print: + +ingress(2) Completed: Canister: Payload: 0x4449444c0000 +debug.print: 4 +debug.print: + +ingress(3) Completed: Canister: Payload: 0x4449444c0000 +debug.print: 4 +debug.print: + +ingress(4) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/hello-world-return.did.ok b/test/run-drun/ok/hello-world-return.did.ok new file mode 100644 index 00000000000..fd39d844f0a --- /dev/null +++ b/test/run-drun/ok/hello-world-return.did.ok @@ -0,0 +1,5 @@ +type Text = text; +service anon_hello_world_return { +hello : (Text) -> (Text); +hello2 : (Text) -> (Text); +} diff --git a/test/run-drun/ok/hello-world-return.drun-run.ok b/test/run-drun/ok/hello-world-return.drun-run.ok new file mode 100644 index 00000000000..a8c1535f920 --- /dev/null +++ b/test/run-drun/ok/hello-world-return.drun-run.ok @@ -0,0 +1,3 @@ +ingress(0) System +Ok: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-tuple.did.ok b/test/run-drun/ok/idl-tuple.did.ok new file mode 100644 index 00000000000..444fff7e984 --- /dev/null +++ b/test/run-drun/ok/idl-tuple.did.ok @@ -0,0 +1,5 @@ +type Text = text; +type Int = int; +service anon_idl_tuple { +len2 : (Text, Text) -> (record {Int; Int}); +} diff --git a/test/run-drun/ok/idl-tuple.drun-run.ok b/test/run-drun/ok/idl-tuple.drun-run.ok new file mode 100644 index 00000000000..139fbf3fc92 --- /dev/null +++ b/test/run-drun/ok/idl-tuple.drun-run.ok @@ -0,0 +1,2 @@ +ingress(0) System +Ok: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-unit.did.ok b/test/run-drun/ok/idl-unit.did.ok new file mode 100644 index 00000000000..e710b6e0c23 --- /dev/null +++ b/test/run-drun/ok/idl-unit.did.ok @@ -0,0 +1,3 @@ +service anon_idl_unit { +unit_id : () -> () oneway; +} diff --git a/test/run-drun/ok/idl-unit.drun-run.ok b/test/run-drun/ok/idl-unit.drun-run.ok new file mode 100644 index 00000000000..139fbf3fc92 --- /dev/null +++ b/test/run-drun/ok/idl-unit.drun-run.ok @@ -0,0 +1,2 @@ +ingress(0) System +Ok: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/print-from-init.did.ok b/test/run-drun/ok/print-from-init.did.ok new file mode 100644 index 00000000000..5255f7a9c4f --- /dev/null +++ b/test/run-drun/ok/print-from-init.did.ok @@ -0,0 +1,2 @@ +service anon_print_from_init { +} diff --git a/test/run-drun/ok/print-from-init.drun-run.ok b/test/run-drun/ok/print-from-init.drun-run.ok new file mode 100644 index 00000000000..4d57fad6ec2 --- /dev/null +++ b/test/run-drun/ok/print-from-init.drun-run.ok @@ -0,0 +1,2 @@ +debug.print: Debug out +ingress(0) System diff --git a/test/run-drun/ok/print-from-init.run-ir.ok b/test/run-drun/ok/print-from-init.run-ir.ok new file mode 100644 index 00000000000..2c5e67992ab --- /dev/null +++ b/test/run-drun/ok/print-from-init.run-ir.ok @@ -0,0 +1 @@ +Debug out diff --git a/test/run-drun/ok/print-from-init.run-low.ok b/test/run-drun/ok/print-from-init.run-low.ok new file mode 100644 index 00000000000..2c5e67992ab --- /dev/null +++ b/test/run-drun/ok/print-from-init.run-low.ok @@ -0,0 +1 @@ +Debug out diff --git a/test/run-drun/ok/print-from-init.run.ok b/test/run-drun/ok/print-from-init.run.ok new file mode 100644 index 00000000000..2c5e67992ab --- /dev/null +++ b/test/run-drun/ok/print-from-init.run.ok @@ -0,0 +1 @@ +Debug out diff --git a/test/run-drun/print-from-init.as b/test/run-drun/print-from-init.as new file mode 100644 index 00000000000..15b4e8c6731 --- /dev/null +++ b/test/run-drun/print-from-init.as @@ -0,0 +1,3 @@ +actor { + print("Debug out"); +} diff --git a/test/run.sh b/test/run.sh index 2a4baed6785..b133db69e21 100755 --- a/test/run.sh +++ b/test/run.sh @@ -7,7 +7,8 @@ # Options: # # -a: Update the files in ok/ -# -d: Compile without -no-dfinity-api, uses dvm to run +# -1: Use Ancient API +# -2: Use IC API # -s: Be silent in sunny-day execution # -i: Only check as to idl generation # @@ -18,7 +19,7 @@ function realpath() { ACCEPT=no -DFINITY=no +API=wasm CHECK_IDL_ONLY=no EXTRA_ASC_FLAGS= ASC=${ASC:-$(realpath $(dirname $0)/../src/asc)} @@ -27,16 +28,20 @@ DIDC=${DIDC:-$(realpath $(dirname $0)/../src/didc)} export AS_LD WASM=${WASM:-wasm} DVM_WRAPPER=$(realpath $(dirname $0)/dvm.sh) +DRUN_WRAPPER=$(realpath $(dirname $0)/drun-wrapper.sh) JSCLIENT=${JSCLIENT:-$(realpath $(dirname $0)/../../dev/experimental/js-dfinity-client)} ECHO=echo -while getopts "adsi" o; do +while getopts "a12si" o; do case "${o}" in a) ACCEPT=yes ;; - d) - DFINITY=yes + 1) + API=ancient + ;; + 2) + API=ic ;; s) ECHO=true @@ -47,10 +52,8 @@ while getopts "adsi" o; do esac done -if [ $DFINITY = "no" ] -then - EXTRA_ASC_FLAGS=-no-dfinity-api -fi +if [ $API = "wasm" ]; then EXTRA_ASC_FLAGS=-no-system-api; fi +if [ $API = "ancient" ]; then EXTRA_ASC_FLAGS=-ancient-system-api; fi shift $((OPTIND-1)) @@ -65,9 +68,13 @@ function normalize () { sed 's/^.*[IW], hypervisor:/hypervisor:/g' | sed 's/wasm:0x[a-f0-9]*:/wasm:0x___:/g' | sed 's/prelude:[^:]*:/prelude:___:/g' | - sed 's/^.*run-dfinity\/\.\.\/dvm.sh: line/dvm.sh: line/g' | - sed 's/ *[0-9]* Illegal instruction.*dvm/ Illegal instruction dvm/g' | sed 's/ calling func\$[0-9]*/ calling func$NNN/g' | + sed 's/rip_addr: [0-9]*/rip_addr: XXX/g' | + sed 's,/tmp/.*dfinity.[^/]*,/tmp/dfinity.XXX,g' | + sed 's,/build/.*dfinity.[^/]*,/tmp/dfinity.XXX,g' | + sed 's,/tmp/.*ic.[^/]*,/tmp/ic.XXX,g' | + sed 's,/build/.*ic.[^/]*,/tmp/ic.XXX,g' | + sed 's/^.*run-dfinity\/\.\.\/drun.sh: line/drun.sh: line/g' | cat > $1.norm mv $1.norm $1 fi @@ -107,10 +114,10 @@ do [ -d $out ] || mkdir $out [ -d $ok ] || mkdir $ok - rm -f $out/$base.{tc,wasm,wasm.map,wasm-run,dvm-run,filecheck,diff-ir,diff-low,stdout,stderr,linked.wat} + rm -f $out/$base.{tc,wasm,wasm.map,wasm-run,drun-run,filecheck,diff-ir,diff-low,stdout,stderr,linked.wat} if [ $ACCEPT = yes ] then - rm -f $ok/$base.{tc,wasm,wasm.map,wasm-run,dvm-run,filecheck,diff-ir,diff-low,stdout,stderr,linked.wat}.ok + rm -f $ok/$base.{tc,wasm,wasm.map,wasm-run,drun-run,filecheck,diff-ir,diff-low,stdout,stderr,linked.wat}.ok fi # First run all the steps, and remember what to diff @@ -196,25 +203,31 @@ do then if [ "$SKIP_RUNNING" != yes ] then - if [ $DFINITY = 'yes' ] + $ECHO -n " [idl]" + $ASC $ASC_FLAGS $EXTRA_ASC_FLAGS --idl $base.as -o $out/$base.did 2> $out/$base.idl.stderr + idl_succeeded=$? + normalize $out/$base.did + normalize $out/$base.idl.stderr + diff_files="$diff_files $base.did $base.idl.stderr" + if [ "$idl_succeeded" -eq 0 ] then - $ECHO -n " [idl]" - $ASC $ASC_FLAGS $EXTRA_ASC_FLAGS --idl $base.as -o $out/$base.did 2> $out/$base.idl.stderr - idl_succeeded=$? - normalize $out/$base.did - normalize $out/$base.idl.stderr - diff_files="$diff_files $base.did $base.idl.stderr" - if [ "$idl_succeeded" -eq 0 ] - then - $ECHO -n " [didc]" - $DIDC --check $out/$base.did > $out/$base.did.tc 2>&1 - diff_files="$diff_files $base.did.tc" - fi + $ECHO -n " [didc]" + $DIDC --check $out/$base.did > $out/$base.did.tc 2>&1 + diff_files="$diff_files $base.did.tc" + fi + if [ $API = ancient ] + then $ECHO -n " [dvm]" $DVM_WRAPPER $out/$base.wasm $base.as > $out/$base.dvm-run 2>&1 normalize $out/$base.dvm-run diff_files="$diff_files $base.dvm-run" + elif [ $API = ic ] + then + $ECHO -n " [drun]" + $DRUN_WRAPPER $out/$base.wasm $base.as > $out/$base.drun-run 2>&1 + normalize $out/$base.drun-run + diff_files="$diff_files $base.drun-run" else $ECHO -n " [wasm-run]" $WASM $out/$base.wasm > $out/$base.wasm-run 2>&1 diff --git a/test/run/actors.as b/test/run/actors.as deleted file mode 100644 index 3da046ff45c..00000000000 --- a/test/run/actors.as +++ /dev/null @@ -1,22 +0,0 @@ -actor tictac_actor { - public func tic_msg(n : Int) { if (n > 0) tictac_actor.tac_msg(n - 1) }; - public func tac_msg(n : Int) { if (n > 0) tictac_actor.tic_msg(n - 1) }; -}; -let _ = tictac_actor.tic_msg(10); - -func ignore(_ : async ()) = (); - -object tictac_async { - public func tic_async(n : Int) : async () { if (n > 0) ignore(tictac_async.tac_async(n - 1)) }; - public func tac_async(n : Int) : async () { if (n > 0) ignore(tictac_async.tic_async(n - 1)) }; -}; -let _ = tictac_async.tic_async(10); - -actor tictac_actor_async { - public func tic_msg_async(n : Int) : async () { if (n > 0) ignore(tictac_actor_async.tac_msg_async(n - 1)) }; - public func 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); - -let _ = async 1/0; -let _ = 1/0; diff --git a/test/run/ok/actors.run-ir.ok b/test/run/ok/actors.run-ir.ok deleted file mode 100644 index 1b2727b5701..00000000000 --- a/test/run/ok/actors.run-ir.ok +++ /dev/null @@ -1,2 +0,0 @@ -actors.as:22.9-22.12: execution error, arithmetic overflow -actors.as:21.15-21.18: execution error, arithmetic overflow diff --git a/test/run/ok/actors.run-low.ok b/test/run/ok/actors.run-low.ok deleted file mode 100644 index 1b2727b5701..00000000000 --- a/test/run/ok/actors.run-low.ok +++ /dev/null @@ -1,2 +0,0 @@ -actors.as:22.9-22.12: execution error, arithmetic overflow -actors.as:21.15-21.18: execution error, arithmetic overflow diff --git a/test/run/ok/actors.run.ok b/test/run/ok/actors.run.ok deleted file mode 100644 index 1b2727b5701..00000000000 --- a/test/run/ok/actors.run.ok +++ /dev/null @@ -1,2 +0,0 @@ -actors.as:22.9-22.12: execution error, arithmetic overflow -actors.as:21.15-21.18: execution error, arithmetic overflow diff --git a/test/run/ok/actors.wasm-run.ok b/test/run/ok/actors.wasm-run.ok deleted file mode 100644 index fd492e3b4f5..00000000000 --- a/test/run/ok/actors.wasm-run.ok +++ /dev/null @@ -1 +0,0 @@ -_out/actors.wasm:0x___: runtime trap: unreachable executed diff --git a/test/run/ok/async-calls.wasm-run.ok b/test/run/ok/async-calls.wasm-run.ok deleted file mode 100644 index 8fca2e68476..00000000000 --- a/test/run/ok/async-calls.wasm-run.ok +++ /dev/null @@ -1 +0,0 @@ -_out/async-calls.wasm:0x___: runtime trap: unreachable executed diff --git a/test/run/ok/coverage.idl.stderr.ok b/test/run/ok/coverage.idl.stderr.ok new file mode 100644 index 00000000000..9749151ddcd --- /dev/null +++ b/test/run/ok/coverage.idl.stderr.ok @@ -0,0 +1,101 @@ +coverage.as:5.13-5.14: warning, this pattern is never matched +coverage.as:7.13-7.14: warning, this pattern is never matched +coverage.as:8.13-8.14: warning, this pattern is never matched +coverage.as:16.16-16.17: warning, this pattern is never matched +coverage.as:18.16-18.17: warning, this pattern is never matched +coverage.as:19.17-19.18: warning, this pattern is never matched +coverage.as:24.25-24.34: warning, this case is never reached +coverage.as:27.25-27.34: warning, this case is never reached +coverage.as:28.25-28.34: warning, this case is never reached +coverage.as:29.25-29.34: warning, this case is never reached +coverage.as:30.25-30.34: warning, this case is never reached +coverage.as:31.25-31.34: warning, this case is never reached +coverage.as:32.43-32.44: warning, this pattern is never matched +coverage.as:33.35-33.49: warning, this case is never reached +coverage.as:34.42-34.51: warning, this case is never reached +coverage.as:37.51-37.73: warning, this case is never reached +coverage.as:38.39-38.54: warning, this case is never reached +coverage.as:39.56-39.65: warning, this case is never reached +coverage.as:40.49-40.58: warning, this case is never reached +coverage.as:46.58-46.72: warning, this case is never reached +coverage.as:61.22-61.31: warning, this case is never reached +coverage.as:62.28-62.37: warning, this case is never reached +coverage.as:63.49-63.50: warning, this pattern is never matched +coverage.as:64.48-64.49: warning, this pattern is never matched +coverage.as:65.41-65.42: warning, this pattern is never matched +coverage.as:66.40-66.41: warning, this pattern is never matched +coverage.as:77.5-77.55: warning, this case is never reached +coverage.as:109.3-109.52: warning, this case is never reached +coverage.as:4.7-4.8: warning, this pattern consuming type + Nat +does not cover value + 0 or 1 or _ +coverage.as:5.7-5.15: warning, this pattern consuming type + Nat +does not cover value + 0 or 1 or _ +coverage.as:9.7-9.9: warning, this pattern consuming type + ?Nat +does not cover value + null +coverage.as:10.7-10.9: warning, this pattern consuming type + ?Nat +does not cover value + null +coverage.as:11.7-11.9: warning, this pattern consuming type + ?Nat +does not cover value + ?(0 or 1 or _) or + null +coverage.as:15.10-15.13: warning, this pattern consuming type + Nat +does not cover value + 0 or 1 or _ +coverage.as:16.10-16.18: warning, this pattern consuming type + Nat +does not cover value + 0 or 1 or _ +coverage.as:23.3-23.25: warning, the cases in this switch over type + Nat +do not cover value + 0 or 1 or _ +coverage.as:24.3-24.36: warning, the cases in this switch over type + Nat +do not cover value + 0 or 1 or _ +coverage.as:32.3-32.50: warning, the cases in this switch over type + Nat +do not cover value + 0 or 1 or _ +coverage.as:35.3-35.51: warning, the cases in this switch over type + (Nat, Nat) +do not cover value + (1 or 2 or _, 1 or 2 or _) +coverage.as:41.3-41.61: warning, the cases in this switch over type + {a : Nat; b : Nat} +do not cover value + {a = 1 or 2 or _; b = 1 or 2 or _) +coverage.as:45.3-45.74: warning, the cases in this switch over type + {#a : Nat; #b : Nat} +do not cover value + #b(0 or 1 or _) +coverage.as:47.3-47.58: warning, the cases in this switch over type + {#a : Nat; #b : Nat} +do not cover value + #b(_) +coverage.as:48.3-48.58: warning, the cases in this switch over type + {#a : Nat; #b : Nat} +do not cover value + #a(_) +coverage.as:49.3-49.62: warning, the cases in this switch over type + {#a : Nat; #b : Nat; #c} +do not cover value + #a(_) or #c +coverage.as:50.3-50.42: warning, the cases in this switch over type + {#a : Nat; #b : Nat} +do not cover value + _ +coverage.as:74.3-78.4: warning, the cases in this switch over type + {#branch : (Tree, Tree); #leaf : Int} +do not cover value + #leaf(0 or 1 or _) diff --git a/test/run/ok/for.wasm-run.ok b/test/run/ok/for.wasm-run.ok deleted file mode 100644 index 808d296fa47..00000000000 --- a/test/run/ok/for.wasm-run.ok +++ /dev/null @@ -1 +0,0 @@ -_out/for.wasm:0x___: runtime trap: unreachable executed diff --git a/test/run/ok/issue120.did.ok b/test/run/ok/issue120.did.ok new file mode 100644 index 00000000000..a962dbbffb4 --- /dev/null +++ b/test/run/ok/issue120.did.ok @@ -0,0 +1,5 @@ +type Foo = service { +foo : (Bar) -> () oneway; +}; +type Bar = service { +}; diff --git a/test/run/ok/issue442.idl.stderr.ok b/test/run/ok/issue442.idl.stderr.ok new file mode 100644 index 00000000000..136d5ad0c79 --- /dev/null +++ b/test/run/ok/issue442.idl.stderr.ok @@ -0,0 +1,6 @@ +issue442.as:1.11-1.24: warning, this array has type [Any] because elements have inconsistent types +issue442.as:2.11-2.29: warning, this if has type Any because branches have inconsistent types, +true produces + Nat +false produces + Text diff --git a/test/run/ok/objects1.idl.stderr.ok b/test/run/ok/objects1.idl.stderr.ok new file mode 100644 index 00000000000..91dcd890805 --- /dev/null +++ b/test/run/ok/objects1.idl.stderr.ok @@ -0,0 +1,10 @@ +objects1.as:22.3-22.26: warning, this case is never reached +objects1.as:23.3-23.14: warning, this case is never reached +objects1.as:32.23-35.2: warning, the cases in this switch over type + {a : Int; b : Nat} +do not cover value + {a = 0 or 1 or _; b = 0 or 1 or _) +objects1.as:43.21-45.2: warning, the cases in this switch over type + (Nat, Int, {c : Char; d : Text}) +do not cover value + (_, 0 or 1 or _, _) diff --git a/test/run/ok/pat-subtyping.idl.stderr.ok b/test/run/ok/pat-subtyping.idl.stderr.ok new file mode 100644 index 00000000000..6fcdb8f75c5 --- /dev/null +++ b/test/run/ok/pat-subtyping.idl.stderr.ok @@ -0,0 +1,41 @@ +pat-subtyping.as:6.3-6.12: warning, this case is never reached +pat-subtyping.as:7.3-7.15: warning, this case is never reached +pat-subtyping.as:10.3-10.20: warning, this case is never reached +pat-subtyping.as:11.3-11.20: warning, this case is never reached +pat-subtyping.as:18.3-18.28: warning, this case is never reached +pat-subtyping.as:25.3-25.28: warning, this case is never reached +pat-subtyping.as:32.3-32.42: warning, this case is never reached +pat-subtyping.as:38.3-38.47: warning, this case is never reached +pat-subtyping.as:44.3-44.44: warning, this case is never reached +pat-subtyping.as:51.3-51.47: warning, this case is never reached +pat-subtyping.as:58.3-58.44: warning, this case is never reached +pat-subtyping.as:65.3-65.58: warning, this case is never reached +pat-subtyping.as:71.3-71.63: warning, this case is never reached +pat-subtyping.as:77.3-77.60: warning, this case is never reached +pat-subtyping.as:84.3-84.71: warning, this case is never reached +pat-subtyping.as:91.3-91.60: warning, this case is never reached +pat-subtyping.as:97.3-97.49: warning, this case is never reached +pat-subtyping.as:103.3-103.51: warning, this case is never reached +pat-subtyping.as:109.3-109.42: warning, this case is never reached +pat-subtyping.as:115.3-115.36: warning, this case is never reached +pat-subtyping.as:119.3-119.17: warning, this case is never reached +pat-subtyping.as:120.3-120.16: warning, this case is never reached +pat-subtyping.as:130.3-130.33: warning, this case is never reached +pat-subtyping.as:137.3-137.31: warning, this case is never reached +pat-subtyping.as:138.3-138.15: warning, this case is never reached +pat-subtyping.as:145.3-145.30: warning, this case is never reached +pat-subtyping.as:156.3-156.31: warning, this case is never reached +pat-subtyping.as:163.3-163.30: warning, this case is never reached +pat-subtyping.as:171.3-171.34: warning, this case is never reached +pat-subtyping.as:172.3-172.32: warning, this case is never reached +pat-subtyping.as:182.3-182.49: warning, this case is never reached +pat-subtyping.as:185.3-185.31: warning, this case is never reached +pat-subtyping.as:188.3-188.39: warning, this case is never reached +pat-subtyping.as:208.3-208.15: warning, this case is never reached +pat-subtyping.as:209.3-209.12: warning, this case is never reached +pat-subtyping.as:210.3-210.14: warning, this case is never reached +pat-subtyping.as:211.3-211.13: warning, this case is never reached +pat-subtyping.as:212.3-212.13: warning, this case is never reached +pat-subtyping.as:213.3-213.13: warning, this case is never reached +pat-subtyping.as:214.3-214.15: warning, this case is never reached +pat-subtyping.as:215.3-215.15: warning, this case is never reached diff --git a/test/run/ok/switch.idl.stderr.ok b/test/run/ok/switch.idl.stderr.ok new file mode 100644 index 00000000000..0a7d23907a0 --- /dev/null +++ b/test/run/ok/switch.idl.stderr.ok @@ -0,0 +1,17 @@ +switch.as:86.29-86.30: warning, this pattern is never matched +switch.as:75.11-77.2: warning, the cases in this switch over type + ?Int +do not cover value + ?(_) +switch.as:81.3-81.14: warning, the cases in this switch over type + Nat +do not cover value + _ +switch.as:92.11-94.2: warning, the cases in this switch over type + ?Nat +do not cover value + null +switch.as:97.11-99.2: warning, the cases in this switch over type + ?Nat +do not cover value + ?(_) diff --git a/test/run/ok/type-inference.idl.stderr.ok b/test/run/ok/type-inference.idl.stderr.ok new file mode 100644 index 00000000000..2e8cbb9f0af --- /dev/null +++ b/test/run/ok/type-inference.idl.stderr.ok @@ -0,0 +1,37 @@ +type-inference.as:3.9-3.28: warning, this if has type Any because branches have inconsistent types, +true produces + Bool +false produces + Nat +type-inference.as:4.9-4.34: warning, this if has type Any because branches have inconsistent types, +true produces + Bool +false produces + [var Nat] +type-inference.as:5.9-5.27: warning, this if has type Any because branches have inconsistent types, +true produces + Nat +false produces + Float +type-inference.as:6.9-6.29: warning, this if has type Any because branches have inconsistent types, +true produces + () +false produces + {} +type-inference.as:11.33-11.41: warning, the switch has type Any because branches have inconsistent types, +this case produces type + Bool +the previous produce type + Nat +type-inference.as:12.33-12.47: warning, the switch has type Any because branches have inconsistent types, +this case produces type + Bool +the previous produce type + [var Nat] +type-inference.as:13.43-13.56: warning, the switch has type Any because branches have inconsistent types, +this case produces type + Int +the previous produce type + Text +type-inference.as:19.9-19.18: warning, this array has type [Any] because elements have inconsistent types +type-inference.as:20.9-20.24: warning, this array has type [Any] because elements have inconsistent types diff --git a/test/run/ok/type-lub.wasm-run.ok b/test/run/ok/type-lub.wasm-run.ok deleted file mode 100644 index ded9968ad6a..00000000000 --- a/test/run/ok/type-lub.wasm-run.ok +++ /dev/null @@ -1 +0,0 @@ -_out/type-lub.wasm:0x___: runtime trap: unreachable executed diff --git a/test/run/ok/variants.wasm-run.ok b/test/run/ok/variants.wasm-run.ok deleted file mode 100644 index 9ec358209cb..00000000000 --- a/test/run/ok/variants.wasm-run.ok +++ /dev/null @@ -1 +0,0 @@ -_out/variants.wasm:0x___: runtime trap: unreachable executed diff --git a/test/run/ok/words.wasm-run.ok b/test/run/ok/words.wasm-run.ok deleted file mode 100644 index 786f43e5405..00000000000 --- a/test/run/ok/words.wasm-run.ok +++ /dev/null @@ -1 +0,0 @@ -_out/words.wasm:0x___: runtime trap: unreachable executed From 83807ead74931d4aafc4a75e90fbd4f8a3ec320d Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 18 Sep 2019 22:30:00 +0100 Subject: [PATCH 0382/1176] Test suite: Do not produce `did` files outside `test/as-idl` (#657) --- shell.nix | 3 +- test/fail/ok/use-before-define5.did.ok | 3 -- test/run-dfinity/ok/async-calls.did.ok | 5 --- test/run-dfinity/ok/chat.did.ok | 10 ------ test/run-dfinity/ok/chatpp.did.ok | 10 ------ test/run-dfinity/ok/closure-params.did.ok | 5 --- test/run-dfinity/ok/control.did.ok | 10 ------ test/run-dfinity/ok/counter-class.did.ok | 6 ---- test/run-dfinity/ok/counter.did.ok | 4 --- test/run-dfinity/ok/counter2.did.ok | 4 --- test/run-dfinity/ok/data-params.did.ok | 31 ------------------- test/run-dfinity/ok/empty-actor.did.ok | 2 -- test/run-dfinity/ok/flatten-awaitables.did.ok | 21 ------------- .../ok/general-type-components.did.ok | 5 --- test/run-dfinity/ok/hello-world-async.did.ok | 4 --- test/run-dfinity/ok/hello-world-await.did.ok | 6 ---- .../run-dfinity/ok/hello-world-message.did.ok | 3 -- .../ok/hello-world-message2.did.ok | 3 -- test/run-dfinity/ok/hello-world2.did.ok | 3 -- test/run-dfinity/ok/hello-world3.did.ok | 5 --- test/run-dfinity/ok/idl-tuple.did.ok | 4 --- test/run-dfinity/ok/indirect-counter.did.ok | 4 --- test/run-dfinity/ok/reference-params.did.ok | 6 ---- test/run-dfinity/ok/transpose.did.ok | 5 --- test/run-drun/ok/counter.did.ok | 4 --- test/run-drun/ok/hello-world-return.did.ok | 5 --- test/run-drun/ok/idl-tuple.did.ok | 5 --- test/run-drun/ok/idl-unit.did.ok | 3 -- test/run-drun/ok/print-from-init.did.ok | 2 -- test/run.sh | 30 +++++------------- test/run/ok/issue120.did.ok | 5 --- 31 files changed, 9 insertions(+), 207 deletions(-) delete mode 100644 test/fail/ok/use-before-define5.did.ok delete mode 100644 test/run-dfinity/ok/async-calls.did.ok delete mode 100644 test/run-dfinity/ok/chat.did.ok delete mode 100644 test/run-dfinity/ok/chatpp.did.ok delete mode 100644 test/run-dfinity/ok/closure-params.did.ok delete mode 100644 test/run-dfinity/ok/control.did.ok delete mode 100644 test/run-dfinity/ok/counter-class.did.ok delete mode 100644 test/run-dfinity/ok/counter.did.ok delete mode 100644 test/run-dfinity/ok/counter2.did.ok delete mode 100644 test/run-dfinity/ok/data-params.did.ok delete mode 100644 test/run-dfinity/ok/empty-actor.did.ok delete mode 100644 test/run-dfinity/ok/flatten-awaitables.did.ok delete mode 100644 test/run-dfinity/ok/general-type-components.did.ok delete mode 100644 test/run-dfinity/ok/hello-world-async.did.ok delete mode 100644 test/run-dfinity/ok/hello-world-await.did.ok delete mode 100644 test/run-dfinity/ok/hello-world-message.did.ok delete mode 100644 test/run-dfinity/ok/hello-world-message2.did.ok delete mode 100644 test/run-dfinity/ok/hello-world2.did.ok delete mode 100644 test/run-dfinity/ok/hello-world3.did.ok delete mode 100644 test/run-dfinity/ok/idl-tuple.did.ok delete mode 100644 test/run-dfinity/ok/indirect-counter.did.ok delete mode 100644 test/run-dfinity/ok/reference-params.did.ok delete mode 100644 test/run-dfinity/ok/transpose.did.ok delete mode 100644 test/run-drun/ok/counter.did.ok delete mode 100644 test/run-drun/ok/hello-world-return.did.ok delete mode 100644 test/run-drun/ok/idl-tuple.did.ok delete mode 100644 test/run-drun/ok/idl-unit.did.ok delete mode 100644 test/run-drun/ok/print-from-init.did.ok delete mode 100644 test/run/ok/issue120.did.ok diff --git a/shell.nix b/shell.nix index 3f1449cf553..429f224b81f 100644 --- a/shell.nix +++ b/shell.nix @@ -1,5 +1,4 @@ { nixpkgs ? (import ./nix/nixpkgs.nix).nixpkgs {}, - test-dvm ? true, }: -(import ./default.nix { inherit nixpkgs test-dvm; export-shell = true; }).shell +(import ./default.nix { inherit nixpkgs; export-shell = true; }).shell diff --git a/test/fail/ok/use-before-define5.did.ok b/test/fail/ok/use-before-define5.did.ok deleted file mode 100644 index b753b2ca84c..00000000000 --- a/test/fail/ok/use-before-define5.did.ok +++ /dev/null @@ -1,3 +0,0 @@ -service a { -foo : () -> () oneway; -} diff --git a/test/run-dfinity/ok/async-calls.did.ok b/test/run-dfinity/ok/async-calls.did.ok deleted file mode 100644 index d6a2c02c683..00000000000 --- a/test/run-dfinity/ok/async-calls.did.ok +++ /dev/null @@ -1,5 +0,0 @@ -type Bool = bool; -service async_rec_actor { -is_true : () -> () oneway; -test : (Bool) -> () oneway; -} diff --git a/test/run-dfinity/ok/chat.did.ok b/test/run-dfinity/ok/chat.did.ok deleted file mode 100644 index cce88b93072..00000000000 --- a/test/run-dfinity/ok/chat.did.ok +++ /dev/null @@ -1,10 +0,0 @@ -type Text = text; -type Server = service { -subscribe : (Client) -> (Post); -}; -type Post = func (Text) -> () oneway; -type Client = service { -go : (Text, Server) -> () oneway; -send : (Text) -> () oneway; -}; -service charlie : Client diff --git a/test/run-dfinity/ok/chatpp.did.ok b/test/run-dfinity/ok/chatpp.did.ok deleted file mode 100644 index 5fc47e0b4a1..00000000000 --- a/test/run-dfinity/ok/chatpp.did.ok +++ /dev/null @@ -1,10 +0,0 @@ -type Text = text; -type Subscription = record {cancel : func () -> () oneway; post : func (Text) -> () oneway}; -type Server = service { -subscribe : (Client) -> (Subscription); -}; -type Client = service { -go : (Text, Server) -> () oneway; -send : (Text) -> () oneway; -}; -service charlie : Client diff --git a/test/run-dfinity/ok/closure-params.did.ok b/test/run-dfinity/ok/closure-params.did.ok deleted file mode 100644 index 96d24dc71a3..00000000000 --- a/test/run-dfinity/ok/closure-params.did.ok +++ /dev/null @@ -1,5 +0,0 @@ -type Nat = nat; -service a { -incn : (Nat) -> () oneway; -readCounter : (func (Nat) -> () oneway) -> () oneway; -} diff --git a/test/run-dfinity/ok/control.did.ok b/test/run-dfinity/ok/control.did.ok deleted file mode 100644 index e46e64c3539..00000000000 --- a/test/run-dfinity/ok/control.did.ok +++ /dev/null @@ -1,10 +0,0 @@ -type Control = service { -testBlock : () -> () oneway; -testLoop : () -> () oneway; -testLoopWhile : () -> () oneway; -testLoopWhile2 : () -> () oneway; -testLoopWhile3 : () -> () oneway; -testLoopWhile4 : () -> () oneway; -testNestedWhile : () -> () oneway; -testWhile : () -> () oneway; -}; diff --git a/test/run-dfinity/ok/counter-class.did.ok b/test/run-dfinity/ok/counter-class.did.ok deleted file mode 100644 index 034c524ba95..00000000000 --- a/test/run-dfinity/ok/counter-class.did.ok +++ /dev/null @@ -1,6 +0,0 @@ -type Int = int; -type Counter = service { -dec : () -> () oneway; -read : () -> (Int); -}; -service c : Counter diff --git a/test/run-dfinity/ok/counter.did.ok b/test/run-dfinity/ok/counter.did.ok deleted file mode 100644 index 27e056d18c8..00000000000 --- a/test/run-dfinity/ok/counter.did.ok +++ /dev/null @@ -1,4 +0,0 @@ -service a { -inc : () -> () oneway; -printCounter : () -> () oneway; -} diff --git a/test/run-dfinity/ok/counter2.did.ok b/test/run-dfinity/ok/counter2.did.ok deleted file mode 100644 index 8c3ecd78383..00000000000 --- a/test/run-dfinity/ok/counter2.did.ok +++ /dev/null @@ -1,4 +0,0 @@ -service anon_counter2 { -inc : () -> () oneway; -printCounter : () -> () oneway; -} diff --git a/test/run-dfinity/ok/data-params.did.ok b/test/run-dfinity/ok/data-params.did.ok deleted file mode 100644 index f187012d7cd..00000000000 --- a/test/run-dfinity/ok/data-params.did.ok +++ /dev/null @@ -1,31 +0,0 @@ -type Word8 = nat8; -type Word64 = nat64; -type Word32 = nat32; -type Word16 = nat16; -type Text = text; -type Nat8 = nat8; -type Nat64 = nat64; -type Nat32 = nat32; -type Nat16 = nat16; -type Nat = nat; -type Int8 = int8; -type Int64 = int64; -type Int32 = int32; -type Int16 = int16; -type Int = int; -service a { -incVariant : (variant {bar : Nat; foo : Nat}) -> () oneway; -incarray : (vec Nat) -> () oneway; -inci : (Int) -> () oneway; -incints : (Int8, Int16, Int32, Int64) -> () oneway; -incn : (Nat) -> () oneway; -incnats : (Nat8, Nat16, Nat32, Nat64) -> () oneway; -incnested : (Nat, record {Nat; Nat}) -> () oneway; -incnn : (Nat, Nat) -> () oneway; -incopt : (opt Nat) -> () oneway; -increcord : (record {x : Nat; y : Nat}) -> () oneway; -incwords : (Word8, Word16, Word32, Word64) -> () oneway; -printCounter : () -> () oneway; -printLabeled : (Text) -> () oneway; -printLabeledOpt : (opt Text) -> () oneway; -} diff --git a/test/run-dfinity/ok/empty-actor.did.ok b/test/run-dfinity/ok/empty-actor.did.ok deleted file mode 100644 index 66928f4d759..00000000000 --- a/test/run-dfinity/ok/empty-actor.did.ok +++ /dev/null @@ -1,2 +0,0 @@ -service anon_empty_actor { -} diff --git a/test/run-dfinity/ok/flatten-awaitables.did.ok b/test/run-dfinity/ok/flatten-awaitables.did.ok deleted file mode 100644 index 0fa4156f0d6..00000000000 --- a/test/run-dfinity/ok/flatten-awaitables.did.ok +++ /dev/null @@ -1,21 +0,0 @@ -type Text = text; -type Int = int; -type Bool = bool; -service a { -g0 : (func (record {}) -> (record {}), record {}) -> (record {}); -g1 : (func (Int) -> (Int), Int) -> (Int); -g2 : (func (record {Int; Bool}) -> (record {Int; Bool}), record {Int; Bool}) -> (record {Int; Bool}); -g3 : (func (record {Int; Bool; Text}) -> (record {Int; Bool; Text}), record {Int; Bool; Text}) -> (record {Int; Bool; Text}); -h0 : (func () -> (record {}), record {}) -> (record {}); -h1 : (func (Int) -> (Int), Int) -> (Int); -h2 : (func (Int, Bool) -> (record {Int; Bool}), record {Int; Bool}) -> (record {Int; Bool}); -h3 : (func (Int, Bool, Text) -> (record {Int; Bool; Text}), record {Int; Bool; Text}) -> (record {Int; Bool; Text}); -m0 : () -> (record {}); -m1 : (Int) -> (Int); -m2 : (Int, Bool) -> (record {Int; Bool}); -m3 : (Int, Bool, Text) -> (record {Int; Bool; Text}); -n0 : (record {}) -> (record {}); -n1 : (Int) -> (Int); -n2 : (record {Int; Bool}) -> (record {Int; Bool}); -n3 : (record {Int; Bool; Text}) -> (record {Int; Bool; Text}); -} diff --git a/test/run-dfinity/ok/general-type-components.did.ok b/test/run-dfinity/ok/general-type-components.did.ok deleted file mode 100644 index 56d106595e9..00000000000 --- a/test/run-dfinity/ok/general-type-components.did.ok +++ /dev/null @@ -1,5 +0,0 @@ -type T_14 = Int; -type Int = int; -service A { -f : () -> () oneway; -} diff --git a/test/run-dfinity/ok/hello-world-async.did.ok b/test/run-dfinity/ok/hello-world-async.did.ok deleted file mode 100644 index 665301cdcb2..00000000000 --- a/test/run-dfinity/ok/hello-world-async.did.ok +++ /dev/null @@ -1,4 +0,0 @@ -service a { -go : () -> () oneway; -world : () -> () oneway; -} diff --git a/test/run-dfinity/ok/hello-world-await.did.ok b/test/run-dfinity/ok/hello-world-await.did.ok deleted file mode 100644 index 2a830c0a0d7..00000000000 --- a/test/run-dfinity/ok/hello-world-await.did.ok +++ /dev/null @@ -1,6 +0,0 @@ -type Text = text; -service a { -go : () -> (record {}); -hello : () -> (Text); -world : () -> (Text); -} diff --git a/test/run-dfinity/ok/hello-world-message.did.ok b/test/run-dfinity/ok/hello-world-message.did.ok deleted file mode 100644 index d63c9fb0b5b..00000000000 --- a/test/run-dfinity/ok/hello-world-message.did.ok +++ /dev/null @@ -1,3 +0,0 @@ -service anon_hello_world_message { -hello : () -> () oneway; -} diff --git a/test/run-dfinity/ok/hello-world-message2.did.ok b/test/run-dfinity/ok/hello-world-message2.did.ok deleted file mode 100644 index 4e2545e1f56..00000000000 --- a/test/run-dfinity/ok/hello-world-message2.did.ok +++ /dev/null @@ -1,3 +0,0 @@ -service hello_world { -hello : () -> () oneway; -} diff --git a/test/run-dfinity/ok/hello-world2.did.ok b/test/run-dfinity/ok/hello-world2.did.ok deleted file mode 100644 index 43f4aef3442..00000000000 --- a/test/run-dfinity/ok/hello-world2.did.ok +++ /dev/null @@ -1,3 +0,0 @@ -service a { -hello : () -> () oneway; -} diff --git a/test/run-dfinity/ok/hello-world3.did.ok b/test/run-dfinity/ok/hello-world3.did.ok deleted file mode 100644 index c05798fab2a..00000000000 --- a/test/run-dfinity/ok/hello-world3.did.ok +++ /dev/null @@ -1,5 +0,0 @@ -service a { -go : () -> () oneway; -hello : () -> () oneway; -world : () -> () oneway; -} diff --git a/test/run-dfinity/ok/idl-tuple.did.ok b/test/run-dfinity/ok/idl-tuple.did.ok deleted file mode 100644 index 31492c6cad5..00000000000 --- a/test/run-dfinity/ok/idl-tuple.did.ok +++ /dev/null @@ -1,4 +0,0 @@ -type Int = int; -service a { -len2 : () -> (record {Int; Int}); -} diff --git a/test/run-dfinity/ok/indirect-counter.did.ok b/test/run-dfinity/ok/indirect-counter.did.ok deleted file mode 100644 index 88d86644fc4..00000000000 --- a/test/run-dfinity/ok/indirect-counter.did.ok +++ /dev/null @@ -1,4 +0,0 @@ -service a { -inc : () -> () oneway; -print : () -> () oneway; -} diff --git a/test/run-dfinity/ok/reference-params.did.ok b/test/run-dfinity/ok/reference-params.did.ok deleted file mode 100644 index 6e99db590f8..00000000000 --- a/test/run-dfinity/ok/reference-params.did.ok +++ /dev/null @@ -1,6 +0,0 @@ -service e { -hello : () -> () oneway; -send_to : (func (service { -hello : () -> () oneway; -}) -> () oneway) -> () oneway; -} diff --git a/test/run-dfinity/ok/transpose.did.ok b/test/run-dfinity/ok/transpose.did.ok deleted file mode 100644 index d6c33bda95c..00000000000 --- a/test/run-dfinity/ok/transpose.did.ok +++ /dev/null @@ -1,5 +0,0 @@ -type Text = text; -type Int = int; -service foo { -transpose : (vec record {Int; Text}) -> (record {ints : vec Int; txts : vec Text}); -} diff --git a/test/run-drun/ok/counter.did.ok b/test/run-drun/ok/counter.did.ok deleted file mode 100644 index 2159d70ccfe..00000000000 --- a/test/run-drun/ok/counter.did.ok +++ /dev/null @@ -1,4 +0,0 @@ -service anon_counter { -inc : () -> () oneway; -printCounter : () -> () oneway; -} diff --git a/test/run-drun/ok/hello-world-return.did.ok b/test/run-drun/ok/hello-world-return.did.ok deleted file mode 100644 index fd39d844f0a..00000000000 --- a/test/run-drun/ok/hello-world-return.did.ok +++ /dev/null @@ -1,5 +0,0 @@ -type Text = text; -service anon_hello_world_return { -hello : (Text) -> (Text); -hello2 : (Text) -> (Text); -} diff --git a/test/run-drun/ok/idl-tuple.did.ok b/test/run-drun/ok/idl-tuple.did.ok deleted file mode 100644 index 444fff7e984..00000000000 --- a/test/run-drun/ok/idl-tuple.did.ok +++ /dev/null @@ -1,5 +0,0 @@ -type Text = text; -type Int = int; -service anon_idl_tuple { -len2 : (Text, Text) -> (record {Int; Int}); -} diff --git a/test/run-drun/ok/idl-unit.did.ok b/test/run-drun/ok/idl-unit.did.ok deleted file mode 100644 index e710b6e0c23..00000000000 --- a/test/run-drun/ok/idl-unit.did.ok +++ /dev/null @@ -1,3 +0,0 @@ -service anon_idl_unit { -unit_id : () -> () oneway; -} diff --git a/test/run-drun/ok/print-from-init.did.ok b/test/run-drun/ok/print-from-init.did.ok deleted file mode 100644 index 5255f7a9c4f..00000000000 --- a/test/run-drun/ok/print-from-init.did.ok +++ /dev/null @@ -1,2 +0,0 @@ -service anon_print_from_init { -} diff --git a/test/run.sh b/test/run.sh index b133db69e21..97de087562c 100755 --- a/test/run.sh +++ b/test/run.sh @@ -20,7 +20,7 @@ function realpath() { ACCEPT=no API=wasm -CHECK_IDL_ONLY=no +IDL=no EXTRA_ASC_FLAGS= ASC=${ASC:-$(realpath $(dirname $0)/../src/asc)} AS_LD=${AS_LD:-$(realpath $(dirname $0)/../src/as-ld)} @@ -47,7 +47,7 @@ while getopts "a12si" o; do ECHO=true ;; i) - CHECK_IDL_ONLY=yes + IDL=yes ;; esac done @@ -114,10 +114,10 @@ do [ -d $out ] || mkdir $out [ -d $ok ] || mkdir $ok - rm -f $out/$base.{tc,wasm,wasm.map,wasm-run,drun-run,filecheck,diff-ir,diff-low,stdout,stderr,linked.wat} + rm -f $out/$base.{tc,wasm,wasm.map,wasm-run,wasm.stderr,drun-run,filecheck,diff-ir,diff-low,stdout,stderr,linked.wat,did,did.tc,js.out} if [ $ACCEPT = yes ] then - rm -f $ok/$base.{tc,wasm,wasm.map,wasm-run,drun-run,filecheck,diff-ir,diff-low,stdout,stderr,linked.wat}.ok + rm -f $ok/$base.{tc,wasm,wasm.map,wasm-run,wasm.stderr,drun-run,filecheck,diff-ir,diff-low,stdout,stderr,linked.wat,did,did.tc,js.out}.ok fi # First run all the steps, and remember what to diff @@ -134,7 +134,7 @@ do if [ "$tc_succeeded" -eq 0 ] then - if [ $CHECK_IDL_ONLY = 'yes' ] + if [ $IDL = 'yes' ] then $ECHO -n " [idl]" $ASC $ASC_FLAGS $EXTRA_ASC_FLAGS --idl $base.as -o $out/$base.did 2> $out/$base.idl.stderr @@ -149,7 +149,6 @@ do diff_files="$diff_files $base.did.tc" fi else - if [ "$SKIP_RUNNING" != yes ] then # Interpret @@ -203,19 +202,6 @@ do then if [ "$SKIP_RUNNING" != yes ] then - $ECHO -n " [idl]" - $ASC $ASC_FLAGS $EXTRA_ASC_FLAGS --idl $base.as -o $out/$base.did 2> $out/$base.idl.stderr - idl_succeeded=$? - normalize $out/$base.did - normalize $out/$base.idl.stderr - diff_files="$diff_files $base.did $base.idl.stderr" - if [ "$idl_succeeded" -eq 0 ] - then - $ECHO -n " [didc]" - $DIDC --check $out/$base.did > $out/$base.did.tc 2>&1 - diff_files="$diff_files $base.did.tc" - fi - if [ $API = ancient ] then $ECHO -n " [dvm]" @@ -283,9 +269,9 @@ do then $ECHO -n " [node]" export NODE_PATH=$NODE_PATH:$JSCLIENT:$JSCLIENT/src - node $out/$base.js > $out/$base.err 2>&1 - normalize $out/$base.err - diff_files="$diff_files $base.err" + node $out/$base.js > $out/$base.js.out 2>&1 + normalize $out/$base.js.out + diff_files="$diff_files $base.js.out" fi fi fi diff --git a/test/run/ok/issue120.did.ok b/test/run/ok/issue120.did.ok deleted file mode 100644 index a962dbbffb4..00000000000 --- a/test/run/ok/issue120.did.ok +++ /dev/null @@ -1,5 +0,0 @@ -type Foo = service { -foo : (Bar) -> () oneway; -}; -type Bar = service { -}; From 852e31c44742c31f77dd759a4888f3b727631f6f Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Wed, 18 Sep 2019 23:55:32 +0200 Subject: [PATCH 0383/1176] UTF-8 validate incoming IDL text (#656) * import from https://github.com/chansen/c-utf8-valid * adapt and include utf8 validator into rts build * unit-test some invalid sequences (transcribed from Markus Kuhn) * CI: make sure we don't return zero from test_rts if something went wrong --- rts/Makefile | 6 +- rts/test_rts.c | 68 +++++++++- rts/utf8_valid.c | 142 +++++++++++++++++++++ src/codegen/compile.ml | 6 +- stdlib/trie.as | 2 +- stdlib/trie2.as | 2 +- test/run-dfinity/data-params.as | 1 + test/run-dfinity/ok/data-params.dvm-run.ok | 1 + test/run-dfinity/ok/data-params.run-ir.ok | 1 + test/run-dfinity/ok/data-params.run-low.ok | 1 + test/run-dfinity/ok/data-params.run.ok | 1 + 11 files changed, 224 insertions(+), 7 deletions(-) create mode 100644 rts/utf8_valid.c diff --git a/rts/Makefile b/rts/Makefile index fcfcb9d9310..cf3540f79c0 100644 --- a/rts/Makefile +++ b/rts/Makefile @@ -55,6 +55,8 @@ WASM_FLAGS = \ # Build targets # +.PHONY: all + all: as-rts.wasm test_rts test_leb128 _build/wasm _build/native: @@ -79,7 +81,7 @@ TOMMATH_NATIVE_O=$(TOMMATHFILES:%=_build/native/tommath_%.o) # Our part of the RTS, Wasm and native # -RTSFILES=rts idl bigint buf +RTSFILES=rts idl bigint buf utf8_valid _build/wasm/%.o: %.c rts.h buf.h | _build/wasm $(WASM_CLANG) -c $(CLANG_FLAGS) $(WASM_FLAGS) $(TOMMATH_FLAGS) -I$(TOMMATHSRC) --std=c11 $< --output $@ @@ -91,7 +93,7 @@ RTS_WASM_O=$(RTSFILES:%=_build/wasm/%.o) RTS_NATIVE_O=$(RTSFILES:%=_build/native/%.o) # -# The actual RTS, a we ship it with the compiler +# The actual RTS, as we ship it with the compiler # as-rts.wasm: $(RTS_WASM_O) $(TOMMATH_WASM_O) diff --git a/rts/test_rts.c b/rts/test_rts.c index e9e40496679..57285607c31 100644 --- a/rts/test_rts.c +++ b/rts/test_rts.c @@ -2,6 +2,7 @@ #include #include #include +#include typedef intptr_t as_ptr; @@ -29,11 +30,76 @@ extern bool bigint_eq(as_ptr a, as_ptr b); int main () { printf("ASC RTS test suite\n"); + int ret = EXIT_SUCCESS; + printf("70**32 = 70**31 * 70: %s\n", bigint_eq( bigint_pow(bigint_of_word32(70), bigint_of_word32(32)), bigint_mul( bigint_pow(bigint_of_word32(70), bigint_of_word32(31)), bigint_of_word32(70) - )) ? "ok" : "not ok"); + )) ? "ok" : (ret = EXIT_FAILURE, "not ok")); + + + extern bool utf8_valid(const char*, size_t); + const int cases = 33; + const char* utf8_inputs[cases] = { + "abcd", + + // from https://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt + // + // 3.5 Impossible bytes + "\xfe", + "\xff", + + // 4.1 Examples of an overlong ASCII character + "\xc0\xaf", + "\xe0\x80\xaf", + "\xf0\x80\x80\xaf", + "\xf8\x80\x80\x80\xaf", + "\xfc\x80\x80\x80\x80\xaf", + + // 4.2 Maximum overlong sequences + "\xc1\xbf", + "\xe0\x9f\xbf", + "\xf0\x8f\xbf\xbf", + "\xf8\x87\xbf\xbf\xbf", + "\xfc\x83\xbf\xbf\xbf\xbf", + + // 4.3 Overlong representation of the NUL character + "\xc0\x80", + "\xe0\x80\x80", + "\xf0\x80\x80\x80", + "\xf8\x80\x80\x80\x80", + "\xfc\x80\x80\x80\x80\x80", + + // 5.1 Single UTF-16 surrogates + "\xed\xa0\x80", + "\xed\xad\xbf", + "\xed\xae\x80", + "\xed\xaf\xbf", + "\xed\xb0\x80", + "\xed\xbe\x80", + "\xed\xbf\xbf", + + // 5.2 Paired UTF-16 surrogates + "\xed\xa0\x80\xed\xb0\x80", + "\xed\xa0\x80\xed\xbf\xbf", + "\xed\xad\xbf\xed\xb0\x80", + "\xed\xad\xbf\xed\xbf\xbf", + "\xed\xae\x80\xed\xb0\x80", + "\xed\xae\x80\xed\xbf\xbf", + "\xed\xaf\xbf\xed\xb0\x80", + "\xed\xaf\xbf\xed\xbf\xbf" + }; + for (int i = 0; i < cases; ++i) + { + bool invalid = i > 0; + printf("%svalid UTF-8 test #%d: %s\n", + invalid ? "in" : "", + i + 1, + invalid != utf8_valid(utf8_inputs[i], strlen(utf8_inputs[i])) ? "ok" : (ret = EXIT_FAILURE, "not ok")); + } + + return ret; } diff --git a/rts/utf8_valid.c b/rts/utf8_valid.c new file mode 100644 index 00000000000..b2b484ee7a6 --- /dev/null +++ b/rts/utf8_valid.c @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2017 Christian Hansen + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define UTF8_VALID_H +#include +#include +#include + +#include "rts.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * UTF-8 Encoding Form + * + * U+0000..U+007F 0xxxxxxx + * U+0080..U+07FF 110xxxxx 10xxxxxx + * U+0800..U+FFFF 1110xxxx 10xxxxxx 10xxxxxx + * U+10000..U+10FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + * + * + * U+0000..U+007F 00..7F + * N C0..C1 80..BF 1100000x 10xxxxxx + * U+0080..U+07FF C2..DF 80..BF + * N E0 80..9F 80..BF 11100000 100xxxxx + * U+0800..U+0FFF E0 A0..BF 80..BF + * U+1000..U+CFFF E1..EC 80..BF 80..BF + * U+D000..U+D7FF ED 80..9F 80..BF + * S ED A0..BF 80..BF 11101101 101xxxxx + * U+E000..U+FFFF EE..EF 80..BF 80..BF + * N F0 80..8F 80..BF 80..BF 11110000 1000xxxx + * U+10000..U+3FFFF F0 90..BF 80..BF 80..BF + * U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF + * U+100000..U+10FFFF F4 80..8F 80..BF 80..BF 11110100 1000xxxx + * + * Legend: + * N = Non-shortest form + * S = Surrogates + */ + +bool +utf8_check(const char *src, size_t len, size_t *cursor) { + const unsigned char *cur = (const unsigned char *)src; + const unsigned char *end = cur + len; + const unsigned char *p; + unsigned char buf[4]; + uint32_t v; + + for (p = cur;;) { + if (cur >= end - 3) { + if (cur == end) + break; + buf[0] = buf[1] = buf[2] = buf[3] = 0; + as_memcpy((char *)buf, (const char *)cur, end - cur); + p = (const unsigned char *)buf; + } + + v = p[0]; + /* 0xxxxxxx */ + if ((v & 0x80) == 0) { + cur += 1; + continue; + } + + v = (v << 8) | p[1]; + /* 110xxxxx 10xxxxxx */ + if ((v & 0xE0C0) == 0xC080) { + /* Ensure that the top 4 bits is not zero */ + v = v & 0x1E00; + if (v == 0) + break; + cur += 2; + continue; + } + + v = (v << 8) | p[2]; + /* 1110xxxx 10xxxxxx 10xxxxxx */ + if ((v & 0xF0C0C0) == 0xE08080) { + /* Ensure that the top 5 bits is not zero and not a surrogate */ + v = v & 0x0F2000; + if (v == 0 || v == 0x0D2000) + break; + cur += 3; + continue; + } + + v = (v << 8) | p[3]; + /* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ + if ((v & 0xF8C0C0C0) == 0xF0808080) { + /* Ensure that the top 5 bits is not zero and not out of range */ + v = v & 0x07300000; + if (v == 0 || v > 0x04000000) + break; + cur += 4; + continue; + } + + break; + } + + if (cursor) + *cursor = (const char *)cur - src; + + return cur == end; +} + +bool +utf8_valid(const char *src, size_t len) { + return utf8_check(src, len, NULL); +} + + +export void utf8_validate(const char *src, size_t len) { + if (utf8_valid(src, len)) + return; + idl_trap_with("UTF-8 validation failure"); +} diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index b2d78dcbced..0307af3dd7f 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -607,7 +607,8 @@ module RTS = struct E.add_func_import env "rts" "bigint_sleb128_encode" [I32Type; I32Type] []; E.add_func_import env "rts" "bigint_sleb128_decode" [I32Type] [I32Type]; E.add_func_import env "rts" "leb128_encode" [I32Type; I32Type] []; - E.add_func_import env "rts" "sleb128_encode" [I32Type; I32Type] [] + E.add_func_import env "rts" "sleb128_encode" [I32Type; I32Type] []; + E.add_func_import env "rts" "utf8_validate" [I32Type; I32Type] [] let system_exports env = E.add_export env (nr { @@ -3839,7 +3840,8 @@ module Serialization = struct get_len ^^ Text.alloc env ^^ set_x ^^ get_x ^^ Text.payload_ptr_unskewed ^^ ReadBuf.read_blob env get_data_buf get_len ^^ - (* TODO: Check validity of utf8 *) + get_x ^^ Text.payload_ptr_unskewed ^^ get_len ^^ + E.call_import env "rts" "utf8_validate" ^^ get_x (* Composite types *) diff --git a/stdlib/trie.as b/stdlib/trie.as index 92f739ef3e3..d8b55aee50c 100644 --- a/stdlib/trie.as +++ b/stdlib/trie.as @@ -424,7 +424,7 @@ public type Trie3D = Trie >; --------- merge tries, preferring the right trie where there are collisions in common keys. note: the `disj` operation generalizes this `merge` - operation in various ways, and does not (in general) loose + operation in various ways, and does not (in general) lose information; this operation is a simpler, special case. See also: diff --git a/stdlib/trie2.as b/stdlib/trie2.as index ad036dcb65e..76c90186606 100644 --- a/stdlib/trie2.as +++ b/stdlib/trie2.as @@ -451,7 +451,7 @@ public func splitSizedList(l:AssocList,V>, bitpos:Nat) --------- merge tries, preferring the right trie where there are collisions in common keys. note: the `disj` operation generalizes this `merge` - operation in various ways, and does not (in general) loose + operation in various ways, and does not (in general) lose information; this operation is a simpler, special case. See also: diff --git a/test/run-dfinity/data-params.as b/test/run-dfinity/data-params.as index 115f6c700bd..4427bcdd8f3 100644 --- a/test/run-dfinity/data-params.as +++ b/test/run-dfinity/data-params.as @@ -106,6 +106,7 @@ a.incVariant(#foo 20); a.incVariant(#bar 20); a.printCounter(); a.printLabeled("Foo1: "); +a.printLabeled("μεταγράψτε: "); a.printLabeledOpt(?"Foo2: "); a.incn(10000000000000); a.inci(10000000000000); diff --git a/test/run-dfinity/ok/data-params.dvm-run.ok b/test/run-dfinity/ok/data-params.dvm-run.ok index a21a447d9ad..732e96d5e47 100644 --- a/test/run-dfinity/ok/data-params.dvm-run.ok +++ b/test/run-dfinity/ok/data-params.dvm-run.ok @@ -16,6 +16,7 @@ +1_006_211 +1_006_211 Foo1: +1_006_211 +μεταγράψτε: +1_006_211 Foo2: +1_006_211 +10_000_001_006_211 +20_000_001_006_211 diff --git a/test/run-dfinity/ok/data-params.run-ir.ok b/test/run-dfinity/ok/data-params.run-ir.ok index 61053f3b7c7..216ee86db4a 100644 --- a/test/run-dfinity/ok/data-params.run-ir.ok +++ b/test/run-dfinity/ok/data-params.run-ir.ok @@ -20,6 +20,7 @@ does not cover value +1_006_211 +1_006_211 Foo1: +1_006_211 +μεταγράψτε: +1_006_211 Foo2: +1_006_211 +10_000_001_006_211 +20_000_001_006_211 diff --git a/test/run-dfinity/ok/data-params.run-low.ok b/test/run-dfinity/ok/data-params.run-low.ok index 61053f3b7c7..216ee86db4a 100644 --- a/test/run-dfinity/ok/data-params.run-low.ok +++ b/test/run-dfinity/ok/data-params.run-low.ok @@ -20,6 +20,7 @@ does not cover value +1_006_211 +1_006_211 Foo1: +1_006_211 +μεταγράψτε: +1_006_211 Foo2: +1_006_211 +10_000_001_006_211 +20_000_001_006_211 diff --git a/test/run-dfinity/ok/data-params.run.ok b/test/run-dfinity/ok/data-params.run.ok index 61053f3b7c7..216ee86db4a 100644 --- a/test/run-dfinity/ok/data-params.run.ok +++ b/test/run-dfinity/ok/data-params.run.ok @@ -20,6 +20,7 @@ does not cover value +1_006_211 +1_006_211 Foo1: +1_006_211 +μεταγράψτε: +1_006_211 Foo2: +1_006_211 +10_000_001_006_211 +20_000_001_006_211 From 15096671ec183f882ac7ba594a4ed334af12597d Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 19 Sep 2019 12:07:18 +0100 Subject: [PATCH 0384/1176] Allow arrays up to 2^29 elements (#663) which is essentially half the address space. (Previous code was confused about the word size, 4 vs. 2^2 vs. 2^4). --- src/codegen/compile.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 0307af3dd7f..d7f1ac3dbbb 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -2781,7 +2781,7 @@ module Arr = struct (* Check size (should not be larger than half the memory space) *) get_len ^^ - compile_unboxed_const Int32.(shift_left 1l (32-4-1)) ^^ + compile_unboxed_const Int32.(shift_left 1l (32-2-1)) ^^ G.i (Compare (Wasm.Values.I32 I32Op.LtU)) ^^ E.else_trap_with env "Array allocation too large" ^^ From 7bbe039dcffb18c784a134e1717af0548c2e3dea Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 19 Sep 2019 10:06:01 +0100 Subject: [PATCH 0385/1176] First step towards registering globals instead of hard-coding their index --- src/codegen/compile.ml | 101 ++++++++++++++++++++++++---------------- test/run/large-tuple.as | 5 ++ 2 files changed, 67 insertions(+), 39 deletions(-) create mode 100644 test/run/large-tuple.as diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index d7f1ac3dbbb..b9dda35987b 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -151,6 +151,8 @@ module E = struct exports : export list ref; dfinity_types : (int32 * Wasm_exts.CustomModule.type_ list) list ref; (* Dfinity types of exports *) funcs : (func * string * local_names) Lib.Promise.t list ref; + globals : (global * string) list ref; + global_names : int32 NameEnv.t ref; built_in_funcs : lazy_built_in NameEnv.t ref; static_strings : int32 StringEnv.t ref; end_of_static_memory : int32 ref; (* End of statically allocated memory *) @@ -183,6 +185,8 @@ module E = struct exports = ref []; dfinity_types = ref []; funcs = ref []; + globals = ref []; + global_names = ref NameEnv.empty; built_in_funcs = ref NameEnv.empty; static_strings = ref StringEnv.empty; end_of_static_memory = ref dyn_mem; @@ -230,6 +234,35 @@ module E = struct assert (mode env = AncientMode); ignore (reg env.dfinity_types e) + let add_global (env : t) name g = + assert (not (NameEnv.mem name !(env.global_names))); + let gi = reg env.globals (g, name) in + env.global_names := NameEnv.add name gi !(env.global_names) + + let add_global32 (env : t) name mut init = + add_global env name ( + nr { gtype = GlobalType (I32Type, mut); + value = nr (G.to_instr_list (G.i (Wasm.Ast.Const (nr (Wasm.Values.I32 init))))) + }) + + let add_global64 (env : t) name mut init = + add_global env name ( + nr { gtype = GlobalType (I64Type, mut); + value = nr (G.to_instr_list (G.i (Wasm.Ast.Const (nr (Wasm.Values.I64 init))))) + }) + + let get_global (env : t) name : int32 = + match NameEnv.find_opt name !(env.global_names) with + | Some gi -> gi + | None -> raise (Invalid_argument (Printf.sprintf "No global named %s declared" name)) + + let get_global32_lazy (env : t) name mut init : int32 = + match NameEnv.find_opt name !(env.global_names) with + | Some gi -> gi + | None -> add_global32 env name mut init; get_global env name + + let get_globals (env : t) = List.map (fun (g,n) -> g) !(env.globals) + let reserve_fun (env : t) name = let (j, fill) = reserve_promise env.funcs name in let n = Int32.of_int (List.length !(env.func_imports)) in @@ -6697,45 +6730,35 @@ and conclude_module env module_name start_fi_o = (* We want to put all persistent globals first: The index in the persist annotation refers to the index in the - list of *exported* globals, not all globals (at least with v8) *) - let globals = [ - (* persistent databuf for memory *) - nr { gtype = GlobalType (I32Type, Mutable); - value = nr (G.to_instr_list compile_unboxed_zero) - }; - (* persistent elembuf for references *) - nr { gtype = GlobalType (I32Type, Mutable); - value = nr (G.to_instr_list compile_unboxed_zero) - }; - (* stack pointer *) - nr { gtype = GlobalType (I32Type, Mutable); - value = nr (G.to_instr_list (compile_unboxed_const Stack.end_of_stack)) - }; - (* beginning-of-heap pointer, may be changed by linker *) - nr { gtype = GlobalType (I32Type, Immutable); - value = nr (G.to_instr_list (compile_unboxed_const (E.get_end_of_static_memory env))) - }; - (* end-of-heap pointer, initialized to __heap_base upon start *) - nr { gtype = GlobalType (I32Type, Mutable); - value = nr (G.to_instr_list (compile_unboxed_const 0xDEAFBEEFl)) - }; - (* reference counter *) - nr { gtype = GlobalType (I32Type, Mutable); - value = nr (G.to_instr_list compile_unboxed_zero) - }; - (* current api_nonce *) - nr { gtype = GlobalType (I64Type, Mutable); - value = nr (G.to_instr_list (compile_const_64 Int64.zero)) - }; - ] @ - (* multi value return emulations *) - begin if !Flags.multi_value then [] else - Lib.List.table 10 (fun i -> - nr { gtype = GlobalType (I32Type, Mutable); - value = nr (G.to_instr_list compile_unboxed_zero) - }) - end - in + list of *exported* globals, not all globals (at least with v8/dvm) *) + (* persistent databuf for memory *) + ignore (E.add_global32 env "datastore" Mutable 0l); + (* persistent elembuf for references *) + ignore (E.add_global32 env "elemstore" Mutable 0l); + (* stack pointer *) + ignore (E.add_global32 env "__stack_pointer" Mutable Stack.end_of_stack); + (* beginning-of-heap pointer, may be changed by linker *) + ignore (E.add_global32 env "__heap_base" Immutable (E.get_end_of_static_memory env)); + (* end-of-heap pointer, initialized to __heap_base upon start *) + ignore (E.add_global32 env "end_of_heap" Mutable 0xDEADBEEFl); + (* reference counter *) + ignore (E.add_global32 env "refcounter" Mutable 0l); + (* current api_nonce *) + ignore (E.add_global64 env "api_nonce" Mutable 0L); + (* multi value return emulations *) + ignore (E.add_global32 env "multi_val_0" Mutable 0l); + ignore (E.add_global32 env "multi_val_1" Mutable 0l); + ignore (E.add_global32 env "multi_val_2" Mutable 0l); + ignore (E.add_global32 env "multi_val_3" Mutable 0l); + ignore (E.add_global32 env "multi_val_4" Mutable 0l); + ignore (E.add_global32 env "multi_val_5" Mutable 0l); + ignore (E.add_global32 env "multi_val_6" Mutable 0l); + ignore (E.add_global32 env "multi_val_7" Mutable 0l); + ignore (E.add_global32 env "multi_val_8" Mutable 0l); + ignore (E.add_global32 env "multi_val_9" Mutable 0l); + ignore (E.add_global32 env "multi_val_10" Mutable 0l); + let globals = E.get_globals env in + E.add_export env (nr { name = Wasm.Utf8.decode "__stack_pointer"; edesc = nr (GlobalExport (nr Stack.stack_global)) diff --git a/test/run/large-tuple.as b/test/run/large-tuple.as new file mode 100644 index 00000000000..6cb3599a616 --- /dev/null +++ b/test/run/large-tuple.as @@ -0,0 +1,5 @@ +// This mainly exercises the multi-value-faking code in the backend + +func returnsLargeTuple() : ((),(),(),(),(),(),(),(),(),(),(),(),(),(),(),()) = ((),(),(),(),(),(),(),(),(),(),(),(),(),(),(),()); +func wantsLargeTuple((),(),(),(),(),(),(),(),(),(),(),(),(),(),(),()) = (); +wantsLargeTuple(returnsLargeTuple()); From 08a37f4e87f99b48dec379cee7c7cf2e5e38a509 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 19 Sep 2019 10:39:31 +0100 Subject: [PATCH 0386/1176] Get rid of hard-coded global ids --- src/codegen/compile.ml | 214 ++++++++++++++++++++++------------------- 1 file changed, 115 insertions(+), 99 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index b9dda35987b..44818eeef70 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -516,28 +516,31 @@ module FakeMultiVal = struct tools) it is useful to avoid the multi-value extension. This module provides mostly transparent wrappers that put multiple values - in statically allocated globals (at most 10...) and pull them off again. + in statically allocated globals and pull them off again. + + So far only does I32Type (but that could be changed). If the multi_value flag is on, these do not do anything. *) - let first_multival_global = 7 - let ty tys = if !Flags.multi_value || List.length tys <= 1 then tys else [] - let store tys = + let global env i = + E.get_global32_lazy env (Printf.sprintf "multi_val_%d" i) Mutable 0l + + let store env tys = if !Flags.multi_value || List.length tys <= 1 then G.nop else G.concat_mapi (fun i _ -> - G.i (GlobalSet (nr (Int32.of_int (first_multival_global + i)))) + G.i (GlobalSet (nr (global env i))) ) tys - let load tys = + let load env tys = if !Flags.multi_value || List.length tys <= 1 then G.nop else - let n = first_multival_global + List.length tys - 1 in + let n = List.length tys - 1 in G.concat_mapi (fun i _ -> - G.i (GlobalGet (nr (Int32.of_int (n - i)))) + G.i (GlobalGet (nr (global env (n - i)))) ) tys end (* FakeMultiVal *) @@ -552,7 +555,7 @@ module Func = struct List.iteri (fun i (n,_t) -> E.add_local_name env1 (Int32.of_int i) n) params; let ty = FuncType (List.map snd params, FakeMultiVal.ty retty) in let body = G.to_instr_list ( - mk_body env1 ^^ FakeMultiVal.store retty + mk_body env1 ^^ FakeMultiVal.store env1 retty ) in (nr { ftype = nr (E.func_type env ty); locals = E.get_locals env1; @@ -567,7 +570,7 @@ module Func = struct let share_code env name params retty mk_body = define_built_in env name params retty mk_body; G.i (Call (nr (E.built_in env name))) ^^ - FakeMultiVal.load retty + FakeMultiVal.load env retty (* Shorthands for various arities *) @@ -686,14 +689,19 @@ module Heap = struct (* Memory addresses are 32 bit (I32Type). *) let word_size = 4l + let register_globals env = + (* end-of-heap pointer, we set this to __heap_base upon start *) + E.add_global32 env "end_of_heap" Mutable 0xDEADBEEFl + (* We keep track of the end of the used heap in this global, and bump it if we allocate stuff. This is the actual memory offset, not-skewed yet *) - let base_global = 3l - let heap_global = 4l - let get_heap_base = G.i (GlobalGet (nr base_global)) - let get_heap_ptr = G.i (GlobalGet (nr heap_global)) - let set_heap_ptr = G.i (GlobalSet (nr heap_global)) - let get_skewed_heap_ptr = get_heap_ptr ^^ compile_add_const ptr_skew + let get_heap_base env = + G.i (GlobalGet (nr (E.get_global env "__heap_base"))) + let get_heap_ptr env = + G.i (GlobalGet (nr (E.get_global env "end_of_heap"))) + let set_heap_ptr env = + G.i (GlobalSet (nr (E.get_global env "end_of_heap"))) + let get_skewed_heap_ptr env = get_heap_ptr env ^^ compile_add_const ptr_skew (* Page allocation. Ensures that the memory up to the given unskewed pointer is allocated. *) let grow_memory env = @@ -728,14 +736,14 @@ module Heap = struct (* expects the size (in words), returns the pointer *) (* return the current pointer (skewed) *) - get_skewed_heap_ptr ^^ + get_skewed_heap_ptr env ^^ (* Update heap pointer *) - get_heap_ptr ^^ + get_heap_ptr env ^^ get_n ^^ compile_mul_const word_size ^^ G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ - set_heap_ptr ^^ - get_heap_ptr ^^ grow_memory env + set_heap_ptr env ^^ + get_heap_ptr env ^^ grow_memory env ) let dyn_alloc_bytes env = @@ -825,25 +833,29 @@ module Stack = struct We sometimes use the stack space if we need small amounts of scratch space. *) - let stack_global = 2l - let end_of_stack = page_size (* 64k of stack *) - let get_stack_ptr = G.i (GlobalGet (nr stack_global)) - let set_stack_ptr = G.i (GlobalSet (nr stack_global)) + let register_globals env = + (* stack pointer *) + E.add_global32 env "__stack_pointer" Mutable end_of_stack + + let get_stack_ptr env = + G.i (GlobalGet (nr (E.get_global env "__stack_pointer"))) + let set_stack_ptr env = + G.i (GlobalSet (nr (E.get_global env "__stack_pointer"))) let alloc_words env n = - get_stack_ptr ^^ + get_stack_ptr env ^^ compile_unboxed_const (Int32.mul n Heap.word_size) ^^ G.i (Binary (Wasm.Values.I32 I32Op.Sub)) ^^ - set_stack_ptr ^^ - get_stack_ptr + set_stack_ptr env ^^ + get_stack_ptr env let free_words env n = - get_stack_ptr ^^ + get_stack_ptr env ^^ compile_unboxed_const (Int32.mul n Heap.word_size) ^^ G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ - set_stack_ptr + set_stack_ptr env let with_words env name n f = let (set_x, get_x) = new_local env name in @@ -863,9 +875,13 @@ module ElemHeap = struct target orthogonal persistence anyways. *) - let ref_counter_global = 5l - let get_ref_ctr = G.i (GlobalGet (nr ref_counter_global)) - let set_ref_ctr = G.i (GlobalSet (nr ref_counter_global)) + let register_globals env = + (* reference counter *) + E.add_global32 env "refcounter" Mutable 0l + let get_ref_ctr env = + G.i (GlobalGet (nr (E.get_global env "refcounter"))) + let set_ref_ctr env = + G.i (GlobalSet (nr (E.get_global env "refcounter"))) (* For now, we allocate a fixed size range. This obviously cannot stay. *) let max_references = 1024l @@ -879,25 +895,25 @@ module ElemHeap = struct let remember_reference env : G.t = Func.share_code1 env "remember_reference" ("ref", I32Type) [I32Type] (fun env get_ref -> (* Check table space *) - get_ref_ctr ^^ + get_ref_ctr env ^^ compile_unboxed_const max_references ^^ G.i (Compare (Wasm.Values.I32 I64Op.LtU)) ^^ E.else_trap_with env "Reference table full" ^^ (* Return index *) - get_ref_ctr ^^ + get_ref_ctr env ^^ (* Store reference *) - get_ref_ctr ^^ + get_ref_ctr env ^^ compile_mul_const Heap.word_size ^^ compile_add_const ref_location ^^ get_ref ^^ store_unskewed_ptr ^^ (* Bump counter *) - get_ref_ctr ^^ + get_ref_ctr env ^^ compile_add_const 1l ^^ - set_ref_ctr + set_ref_ctr env ) (* Assumes a index into the table on the stack, and replaces it with the reference *) @@ -1281,7 +1297,7 @@ module Closure = struct Heap.load_field funptr_field ^^ (* All done: Call! *) G.i (CallIndirect (nr ty)) ^^ - FakeMultiVal.load (Lib.List.make cc.Call_conv.n_res I32Type) + FakeMultiVal.load env (Lib.List.make cc.Call_conv.n_res I32Type) let fixed_closure env fi fields = Tagged.obj env Tagged.Closure @@ -2932,9 +2948,12 @@ end (* Tuple *) module Dfinity = struct (* Dfinity-specific stuff: System imports, databufs etc. *) - let api_nonce_global = 6l - let set_api_nonce = G.i (GlobalSet (nr api_nonce_global)) - let get_api_nonce = G.i (GlobalGet (nr api_nonce_global)) + let set_api_nonce env = G.i (GlobalSet (nr (E.get_global env "api_nonce"))) + let get_api_nonce env = G.i (GlobalGet (nr (E.get_global env "api_nonce"))) + + let register_globals env = + (* current api_nonce *) + E.add_global64 env "api_nonce" Mutable 0L let system_imports env = match E.mode env with @@ -3075,24 +3094,33 @@ end (* Dfinity *) module OrthogonalPersistence = struct (* This module implements the code that fakes orthogonal persistence *) - let mem_global = 0l - let elem_global = 1l - (* Strategy: * There is a persistent global databuf called `datastore` * Two helper functions are installed in each actor: restore_mem and save_mem. (The don’t actually have names, just numbers, of course). * Upon each message entry, call restore_mem. At the end, call save_mem. - * restore_mem checks if memstore is defined. + * restore_mem checks if datastore is defined. - If it is 0, then this is the first message ever received. Run the actor’s start function (e.g. to initialize globals). - If it is not 0, then load the databuf into memory, and set the global with the end-of-memory pointer to the length. * save_mem simply copies the whole dynamic memory (up to the end-of-memory - pointer) to a new databuf and stores that in memstore. + pointer) to a new databuf and stores that in datastore. *) + let register_globals env = + (* We want to put all persistent globals first: + The index in the persist annotation refers to the index in the + list of *exported* globals, not all globals (at least with v8/dvm) *) + (* persistent databuf for memory *) + E.add_global32 env "datastore" Mutable 0l; + (* persistent elembuf for references *) + E.add_global32 env "elemstore" Mutable 0l + let register env start_funid = + let mem_global = E.get_global env "datastore" in + let elem_global = E.get_global env "elemstore" in + E.add_export env (nr { name = Wasm.Utf8.decode "datastore"; edesc = nr (GlobalExport (nr mem_global)) @@ -3118,8 +3146,8 @@ module OrthogonalPersistence = struct ( (* Set heap pointer based on databuf length *) get_i ^^ compile_add_const ElemHeap.table_end ^^ - Heap.set_heap_ptr ^^ - Heap.get_heap_ptr ^^ Heap.grow_memory env ^^ + Heap.set_heap_ptr env ^^ + Heap.get_heap_ptr env ^^ Heap.grow_memory env ^^ (* Load memory *) compile_unboxed_const ElemHeap.table_end ^^ @@ -3131,11 +3159,11 @@ module OrthogonalPersistence = struct (* Load reference counter *) G.i (GlobalGet (nr elem_global)) ^^ Dfinity.system_call env1 "elem" "length" ^^ - ElemHeap.set_ref_ctr ^^ + ElemHeap.set_ref_ctr env ^^ (* Load references *) compile_unboxed_const ElemHeap.ref_location ^^ - ElemHeap.get_ref_ctr ^^ + ElemHeap.get_ref_ctr env ^^ G.i (GlobalGet (nr elem_global)) ^^ compile_unboxed_zero ^^ Dfinity.system_call env1 "elem" "internalize" @@ -3144,7 +3172,7 @@ module OrthogonalPersistence = struct Func.define_built_in env "save_mem" [] [] (fun env1 -> (* Store memory *) compile_unboxed_const ElemHeap.table_end ^^ - Heap.get_heap_ptr ^^ + Heap.get_heap_ptr env ^^ compile_unboxed_const ElemHeap.table_end ^^ G.i (Binary (Wasm.Values.I32 I32Op.Sub)) ^^ Dfinity.system_call env "data" "externalize" ^^ @@ -3152,7 +3180,7 @@ module OrthogonalPersistence = struct (* Store references *) compile_unboxed_const ElemHeap.ref_location ^^ - ElemHeap.get_ref_ctr ^^ + ElemHeap.get_ref_ctr env ^^ Dfinity.system_call env "elem" "externalize" ^^ G.i (GlobalSet (nr elem_global)) ) @@ -3964,17 +3992,17 @@ module Serialization = struct ) let reply_with_data env get_data_start get_data_size = - Dfinity.get_api_nonce ^^ + Dfinity.get_api_nonce env ^^ get_data_start ^^ get_data_size ^^ Dfinity.system_call env "msg" "reply" let argument_data_size env = - Dfinity.get_api_nonce ^^ + Dfinity.get_api_nonce env ^^ Dfinity.system_call env "msg" "arg_data_size" let argument_data_copy env get_dest get_length = - Dfinity.get_api_nonce ^^ + Dfinity.get_api_nonce env ^^ get_dest ^^ get_length ^^ (compile_unboxed_const 0l) ^^ @@ -4254,9 +4282,9 @@ module GC = struct let (set_begin_to_space, get_begin_to_space) = new_local env "begin_to_space" in let (set_end_to_space, get_end_to_space) = new_local env "end_to_space" in - Heap.get_heap_base ^^ compile_add_const ptr_skew ^^ set_begin_from_space ^^ - Heap.get_skewed_heap_ptr ^^ set_begin_to_space ^^ - Heap.get_skewed_heap_ptr ^^ set_end_to_space ^^ + Heap.get_heap_base env ^^ compile_add_const ptr_skew ^^ set_begin_from_space ^^ + Heap.get_skewed_heap_ptr env ^^ set_begin_to_space ^^ + Heap.get_skewed_heap_ptr env ^^ set_end_to_space ^^ (* Common arguments for evacuate *) @@ -4308,7 +4336,7 @@ module GC = struct get_begin_from_space ^^ compile_add_const ptr_unskew ^^ get_end_to_space ^^ get_begin_to_space ^^ G.i (Binary (Wasm.Values.I32 I32Op.Sub)) ^^ G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ - Heap.set_heap_ptr + Heap.set_heap_ptr env ) end (* GC *) @@ -4781,7 +4809,7 @@ module FuncDec = struct | ICMode -> let ae0 = ASEnv.mk_fun_ae outer_ae in Func.of_body outer_env ["api_nonce", I64Type] [] (fun env -> G.with_region at ( - G.i (LocalGet (nr 0l)) ^^ Dfinity.set_api_nonce ^^ + G.i (LocalGet (nr 0l)) ^^ Dfinity.set_api_nonce env ^^ (* Deserialize argument and add params to the environment *) let arg_names = List.map (fun a -> a.it) args in @@ -6148,7 +6176,7 @@ and compile_exp (env : E.t) ae exp = | RetE e -> SR.Unreachable, compile_exp_as env ae (StackRep.of_arity (E.get_n_res env)) e ^^ - FakeMultiVal.store (Lib.List.make (E.get_n_res env) I32Type) ^^ + FakeMultiVal.store env (Lib.List.make (E.get_n_res env) I32Type) ^^ G.i Return | OptE e -> SR.Vanilla, @@ -6174,7 +6202,7 @@ and compile_exp (env : E.t) ae exp = compile_unboxed_zero ^^ (* A dummy closure *) compile_exp_as env ae (StackRep.of_arity cc.Call_conv.n_args) e2 ^^ (* the args *) G.i (Call (nr fi)) ^^ - FakeMultiVal.load (Lib.List.make cc.Call_conv.n_res I32Type) + FakeMultiVal.load env (Lib.List.make cc.Call_conv.n_res I32Type) | _, Type.Local -> let (set_clos, get_clos) = new_local env "clos" in code1 ^^ StackRep.adjust env fun_sr SR.Vanilla ^^ @@ -6577,6 +6605,7 @@ This function compiles the prelude, just to find out the bound names. and find_prelude_names env = (* Create a throw-away environment *) let env0 = E.mk_global (E.mode env) None (E.get_prelude env) (fun _ _ -> G.i Unreachable) 0l in + Heap.register_globals env0; Dfinity.system_imports env0; RTS.system_imports env0; let env1 = E.mk_fun_env env0 0l 0 in @@ -6649,10 +6678,17 @@ and actor_lit outer_env this ds fs at = (E.get_trap_with outer_env) ClosureTable.table_end in + if E.mode mod_env = AncientMode then OrthogonalPersistence.register_globals mod_env; + Heap.register_globals mod_env; + ElemHeap.register_globals mod_env; + Stack.register_globals mod_env; + Dfinity.register_globals mod_env; + Dfinity.system_imports mod_env; RTS.system_imports mod_env; RTS.system_exports mod_env; + let start_fun = Func.of_body mod_env [] [] (fun env -> G.with_region at @@ let ae0 = ASEnv.empty_ae in @@ -6702,10 +6738,14 @@ and actor_fake_object_idx env name = and conclude_module env module_name start_fi_o = + (* add beginning-of-heap pointer, may be changed by linker *) + (* needs to happen here now that we know the size of static memory *) + E.add_global32 env "__heap_base" Immutable (E.get_end_of_static_memory env); + (* Wrap the start function with the RTS initialization *) let rts_start_fi = E.add_fun env "rts_start" (Func.of_body env [] [] (fun env1 -> - Heap.get_heap_base ^^ - Heap.set_heap_ptr ^^ + G.i (GlobalGet (nr (E.get_global env "__heap_base"))) ^^ + Heap.set_heap_ptr env ^^ match start_fi_o with | Some fi -> G.i (Call fi) | None -> G.nop @@ -6728,44 +6768,14 @@ and conclude_module env module_name start_fi_o = let memories = [nr {mtype = MemoryType {min = E.mem_size env; max = None}} ] in - (* We want to put all persistent globals first: - The index in the persist annotation refers to the index in the - list of *exported* globals, not all globals (at least with v8/dvm) *) - (* persistent databuf for memory *) - ignore (E.add_global32 env "datastore" Mutable 0l); - (* persistent elembuf for references *) - ignore (E.add_global32 env "elemstore" Mutable 0l); - (* stack pointer *) - ignore (E.add_global32 env "__stack_pointer" Mutable Stack.end_of_stack); - (* beginning-of-heap pointer, may be changed by linker *) - ignore (E.add_global32 env "__heap_base" Immutable (E.get_end_of_static_memory env)); - (* end-of-heap pointer, initialized to __heap_base upon start *) - ignore (E.add_global32 env "end_of_heap" Mutable 0xDEADBEEFl); - (* reference counter *) - ignore (E.add_global32 env "refcounter" Mutable 0l); - (* current api_nonce *) - ignore (E.add_global64 env "api_nonce" Mutable 0L); - (* multi value return emulations *) - ignore (E.add_global32 env "multi_val_0" Mutable 0l); - ignore (E.add_global32 env "multi_val_1" Mutable 0l); - ignore (E.add_global32 env "multi_val_2" Mutable 0l); - ignore (E.add_global32 env "multi_val_3" Mutable 0l); - ignore (E.add_global32 env "multi_val_4" Mutable 0l); - ignore (E.add_global32 env "multi_val_5" Mutable 0l); - ignore (E.add_global32 env "multi_val_6" Mutable 0l); - ignore (E.add_global32 env "multi_val_7" Mutable 0l); - ignore (E.add_global32 env "multi_val_8" Mutable 0l); - ignore (E.add_global32 env "multi_val_9" Mutable 0l); - ignore (E.add_global32 env "multi_val_10" Mutable 0l); - let globals = E.get_globals env in E.add_export env (nr { name = Wasm.Utf8.decode "__stack_pointer"; - edesc = nr (GlobalExport (nr Stack.stack_global)) + edesc = nr (GlobalExport (nr (E.get_global env "__stack_pointer"))) }); E.add_export env (nr { name = Wasm.Utf8.decode "__heap_base"; - edesc = nr (GlobalExport (nr Heap.base_global)) + edesc = nr (GlobalExport (nr (E.get_global env "__heap_base"))) }); let data = List.map (fun (offset, init) -> nr { @@ -6783,7 +6793,7 @@ and conclude_module env module_name start_fi_o = offset = nr (G.to_instr_list (compile_unboxed_const ni')); init = List.mapi (fun i _ -> nr (Wasm.I32.of_int_u (ni + i))) funcs } ]; start = Some (nr rts_start_fi); - globals = globals; + globals = E.get_globals env; memories = memories; imports = func_imports @ other_imports; exports = E.get_exports env; @@ -6803,8 +6813,8 @@ and conclude_module env module_name start_fi_o = }; types = E.get_dfinity_types env; persist = if E.mode env = AncientMode then - [ (OrthogonalPersistence.mem_global, Wasm_exts.CustomModule.DataBuf) - ; (OrthogonalPersistence.elem_global, Wasm_exts.CustomModule.ElemBuf) + [ (E.get_global env "datastore", Wasm_exts.CustomModule.DataBuf) + ; (E.get_global env "elemstore", Wasm_exts.CustomModule.ElemBuf) ] else []; } in @@ -6815,6 +6825,12 @@ and conclude_module env module_name start_fi_o = let compile mode module_name rts (prelude : Ir.prog) (progs : Ir.prog list) : Wasm_exts.CustomModule.extended_module = let env = E.mk_global mode rts prelude Dfinity.trap_with ClosureTable.table_end in + if E.mode env = AncientMode then OrthogonalPersistence.register_globals env; + Heap.register_globals env; + ElemHeap.register_globals env; + Stack.register_globals env; + Dfinity.register_globals env; + Dfinity.system_imports env; RTS.system_imports env; RTS.system_exports env; From 4e8895121445460539a57734aaa0e779806231a5 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 19 Sep 2019 10:42:32 +0100 Subject: [PATCH 0387/1176] Nicer export of globals --- src/codegen/compile.ml | 34 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 44818eeef70..a9ea8fdaede 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -261,6 +261,12 @@ module E = struct | Some gi -> gi | None -> add_global32 env name mut init; get_global env name + let export_global env name = + add_export env (nr { + name = Wasm.Utf8.decode name; + edesc = nr (GlobalExport (nr (get_global env name))) + }) + let get_globals (env : t) = List.map (fun (g,n) -> g) !(env.globals) let reserve_fun (env : t) name = @@ -837,7 +843,8 @@ module Stack = struct let register_globals env = (* stack pointer *) - E.add_global32 env "__stack_pointer" Mutable end_of_stack + E.add_global32 env "__stack_pointer" Mutable end_of_stack; + E.export_global env "__stack_pointer" let get_stack_ptr env = G.i (GlobalGet (nr (E.get_global env "__stack_pointer"))) @@ -3112,24 +3119,15 @@ module OrthogonalPersistence = struct (* We want to put all persistent globals first: The index in the persist annotation refers to the index in the list of *exported* globals, not all globals (at least with v8/dvm) *) - (* persistent databuf for memory *) E.add_global32 env "datastore" Mutable 0l; - (* persistent elembuf for references *) - E.add_global32 env "elemstore" Mutable 0l + E.add_global32 env "elemstore" Mutable 0l; + E.export_global env "datastore"; + E.export_global env "elemstore" let register env start_funid = let mem_global = E.get_global env "datastore" in let elem_global = E.get_global env "elemstore" in - E.add_export env (nr { - name = Wasm.Utf8.decode "datastore"; - edesc = nr (GlobalExport (nr mem_global)) - }); - E.add_export env (nr { - name = Wasm.Utf8.decode "elemstore"; - edesc = nr (GlobalExport (nr elem_global)) - }); - Func.define_built_in env "restore_mem" [] [] (fun env1 -> let (set_i, get_i) = new_local env1 "len" in G.i (GlobalGet (nr mem_global)) ^^ @@ -6741,6 +6739,7 @@ and conclude_module env module_name start_fi_o = (* add beginning-of-heap pointer, may be changed by linker *) (* needs to happen here now that we know the size of static memory *) E.add_global32 env "__heap_base" Immutable (E.get_end_of_static_memory env); + E.export_global env "__heap_base"; (* Wrap the start function with the RTS initialization *) let rts_start_fi = E.add_fun env "rts_start" (Func.of_body env [] [] (fun env1 -> @@ -6769,15 +6768,6 @@ and conclude_module env module_name start_fi_o = let memories = [nr {mtype = MemoryType {min = E.mem_size env; max = None}} ] in - E.add_export env (nr { - name = Wasm.Utf8.decode "__stack_pointer"; - edesc = nr (GlobalExport (nr (E.get_global env "__stack_pointer"))) - }); - E.add_export env (nr { - name = Wasm.Utf8.decode "__heap_base"; - edesc = nr (GlobalExport (nr (E.get_global env "__heap_base"))) - }); - let data = List.map (fun (offset, init) -> nr { index = nr 0l; offset = nr (G.to_instr_list (compile_unboxed_const offset)); From 63090fff1bd613fd29942fd4d80535d3c94516ed Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 19 Sep 2019 10:46:52 +0100 Subject: [PATCH 0388/1176] Register globals that need to be persisted to keep stuff where it belongs. --- src/codegen/compile.ml | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index a9ea8fdaede..6608902b245 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -153,6 +153,7 @@ module E = struct funcs : (func * string * local_names) Lib.Promise.t list ref; globals : (global * string) list ref; global_names : int32 NameEnv.t ref; + persist : (int32 * Wasm_exts.CustomModule.type_) list ref; built_in_funcs : lazy_built_in NameEnv.t ref; static_strings : int32 StringEnv.t ref; end_of_static_memory : int32 ref; (* End of statically allocated memory *) @@ -187,6 +188,7 @@ module E = struct funcs = ref []; globals = ref []; global_names = ref NameEnv.empty; + persist = ref []; built_in_funcs = ref NameEnv.empty; static_strings = ref StringEnv.empty; end_of_static_memory = ref dyn_mem; @@ -269,6 +271,11 @@ module E = struct let get_globals (env : t) = List.map (fun (g,n) -> g) !(env.globals) + let persist (env : t) i t = + env.persist := !(env.persist) @ [(i, t)] + + let get_persist (env : t) = !(env.persist) + let reserve_fun (env : t) name = let (j, fill) = reserve_promise env.funcs name in let n = Int32.of_int (List.length !(env.func_imports)) in @@ -3122,7 +3129,9 @@ module OrthogonalPersistence = struct E.add_global32 env "datastore" Mutable 0l; E.add_global32 env "elemstore" Mutable 0l; E.export_global env "datastore"; - E.export_global env "elemstore" + E.export_global env "elemstore"; + E.persist env (E.get_global env "datastore") Wasm_exts.CustomModule.DataBuf; + E.persist env (E.get_global env "elemstore") Wasm_exts.CustomModule.ElemBuf let register env start_funid = let mem_global = E.get_global env "datastore" in @@ -6802,10 +6811,7 @@ and conclude_module env module_name start_fi_o = List.mapi (fun i (f,_,ln) -> Int32.(add ni' (of_int i), ln)) funcs; }; types = E.get_dfinity_types env; - persist = if E.mode env = AncientMode then - [ (E.get_global env "datastore", Wasm_exts.CustomModule.DataBuf) - ; (E.get_global env "elemstore", Wasm_exts.CustomModule.ElemBuf) - ] else []; + persist = E.get_persist env } in match E.get_rts env with From f5e9323f8deb26fe9112c8eaf08ebd7a034689be Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 19 Sep 2019 10:55:16 +0100 Subject: [PATCH 0389/1176] Fake OP: Assert we are using this only in AncientMode --- src/codegen/compile.ml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 6608902b245..3395301a0ee 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -3123,6 +3123,7 @@ module OrthogonalPersistence = struct *) let register_globals env = + assert (E.mode env = AncientMode); (* We want to put all persistent globals first: The index in the persist annotation refers to the index in the list of *exported* globals, not all globals (at least with v8/dvm) *) @@ -3134,6 +3135,7 @@ module OrthogonalPersistence = struct E.persist env (E.get_global env "elemstore") Wasm_exts.CustomModule.ElemBuf let register env start_funid = + assert (E.mode env = AncientMode); let mem_global = E.get_global env "datastore" in let elem_global = E.get_global env "elemstore" in From 128e37bf6800125056269454a21acd8f2c70b226 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 19 Sep 2019 17:15:09 +0200 Subject: [PATCH 0390/1176] Large tuple test case: Check order --- test/run/large-tuple.as | 4 ++-- test/run/ok/large-tuple.idl.stderr.ok | 23 +++++++++++++++++++++++ test/run/ok/large-tuple.run-ir.ok | 23 +++++++++++++++++++++++ test/run/ok/large-tuple.run-low.ok | 23 +++++++++++++++++++++++ test/run/ok/large-tuple.run.ok | 23 +++++++++++++++++++++++ test/run/ok/large-tuple.tc.ok | 23 +++++++++++++++++++++++ test/run/ok/large-tuple.wasm.stderr.ok | 23 +++++++++++++++++++++++ 7 files changed, 140 insertions(+), 2 deletions(-) create mode 100644 test/run/ok/large-tuple.idl.stderr.ok create mode 100644 test/run/ok/large-tuple.run-ir.ok create mode 100644 test/run/ok/large-tuple.run-low.ok create mode 100644 test/run/ok/large-tuple.run.ok create mode 100644 test/run/ok/large-tuple.tc.ok create mode 100644 test/run/ok/large-tuple.wasm.stderr.ok diff --git a/test/run/large-tuple.as b/test/run/large-tuple.as index 6cb3599a616..c58eb9db1a5 100644 --- a/test/run/large-tuple.as +++ b/test/run/large-tuple.as @@ -1,5 +1,5 @@ // This mainly exercises the multi-value-faking code in the backend -func returnsLargeTuple() : ((),(),(),(),(),(),(),(),(),(),(),(),(),(),(),()) = ((),(),(),(),(),(),(),(),(),(),(),(),(),(),(),()); -func wantsLargeTuple((),(),(),(),(),(),(),(),(),(),(),(),(),(),(),()) = (); +func returnsLargeTuple() : (Nat,Nat,Nat,Nat,Nat,Nat,Nat,Nat,Nat,Nat,Nat,Nat,Nat,Nat,Nat,Nat,Nat,Nat,Nat,Nat) = (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20); +func wantsLargeTuple(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20) = (); wantsLargeTuple(returnsLargeTuple()); diff --git a/test/run/ok/large-tuple.idl.stderr.ok b/test/run/ok/large-tuple.idl.stderr.ok new file mode 100644 index 00000000000..6d7e9529fe2 --- /dev/null +++ b/test/run/ok/large-tuple.idl.stderr.ok @@ -0,0 +1,23 @@ +large-tuple.as:4.21-4.73: warning, this pattern consuming type + (Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat) +does not cover value + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0 or 1 or _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 0 or 1 or _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 0 or 1 or _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0 or 1 or _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0 or 1 or _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0 or 1 or _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0 or 1 or _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0 or 1 or _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0 or 1 or _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0 or 1 or _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or + (0 or 2 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) diff --git a/test/run/ok/large-tuple.run-ir.ok b/test/run/ok/large-tuple.run-ir.ok new file mode 100644 index 00000000000..6d7e9529fe2 --- /dev/null +++ b/test/run/ok/large-tuple.run-ir.ok @@ -0,0 +1,23 @@ +large-tuple.as:4.21-4.73: warning, this pattern consuming type + (Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat) +does not cover value + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0 or 1 or _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 0 or 1 or _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 0 or 1 or _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0 or 1 or _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0 or 1 or _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0 or 1 or _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0 or 1 or _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0 or 1 or _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0 or 1 or _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0 or 1 or _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or + (0 or 2 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) diff --git a/test/run/ok/large-tuple.run-low.ok b/test/run/ok/large-tuple.run-low.ok new file mode 100644 index 00000000000..6d7e9529fe2 --- /dev/null +++ b/test/run/ok/large-tuple.run-low.ok @@ -0,0 +1,23 @@ +large-tuple.as:4.21-4.73: warning, this pattern consuming type + (Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat) +does not cover value + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0 or 1 or _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 0 or 1 or _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 0 or 1 or _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0 or 1 or _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0 or 1 or _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0 or 1 or _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0 or 1 or _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0 or 1 or _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0 or 1 or _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0 or 1 or _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or + (0 or 2 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) diff --git a/test/run/ok/large-tuple.run.ok b/test/run/ok/large-tuple.run.ok new file mode 100644 index 00000000000..6d7e9529fe2 --- /dev/null +++ b/test/run/ok/large-tuple.run.ok @@ -0,0 +1,23 @@ +large-tuple.as:4.21-4.73: warning, this pattern consuming type + (Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat) +does not cover value + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0 or 1 or _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 0 or 1 or _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 0 or 1 or _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0 or 1 or _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0 or 1 or _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0 or 1 or _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0 or 1 or _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0 or 1 or _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0 or 1 or _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0 or 1 or _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or + (0 or 2 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) diff --git a/test/run/ok/large-tuple.tc.ok b/test/run/ok/large-tuple.tc.ok new file mode 100644 index 00000000000..6d7e9529fe2 --- /dev/null +++ b/test/run/ok/large-tuple.tc.ok @@ -0,0 +1,23 @@ +large-tuple.as:4.21-4.73: warning, this pattern consuming type + (Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat) +does not cover value + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0 or 1 or _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 0 or 1 or _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 0 or 1 or _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0 or 1 or _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0 or 1 or _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0 or 1 or _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0 or 1 or _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0 or 1 or _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0 or 1 or _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0 or 1 or _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or + (0 or 2 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) diff --git a/test/run/ok/large-tuple.wasm.stderr.ok b/test/run/ok/large-tuple.wasm.stderr.ok new file mode 100644 index 00000000000..6d7e9529fe2 --- /dev/null +++ b/test/run/ok/large-tuple.wasm.stderr.ok @@ -0,0 +1,23 @@ +large-tuple.as:4.21-4.73: warning, this pattern consuming type + (Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat) +does not cover value + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0 or 1 or _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 0 or 1 or _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 0 or 1 or _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0 or 1 or _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0 or 1 or _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0 or 1 or _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0 or 1 or _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0 or 1 or _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0 or 1 or _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0 or 1 or _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 9, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 8, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 7, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 6, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 5, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 4, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 3, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 2, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or + (1, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or + (0 or 2 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) From b2e8f71b098ace84121624f5dc4a7cf11066c1a4 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity <48968912+chenyan-dfinity@users.noreply.github.com> Date: Thu, 19 Sep 2019 23:12:01 -0700 Subject: [PATCH 0391/1176] Rename pure attribute to query (#669) --- design/IDL-AS.md | 30 +++++++++++++++--------------- design/IDL.md | 12 ++++++------ src/idllib/arrange_idl.ml | 2 +- src/idllib/parser.mly | 2 +- src/idllib/syntax.ml | 2 +- test/idl/import.did | 2 +- test/idl/ok/oneway.tc.ok | 2 +- test/idl/oneway.did | 4 ++-- test/idl/px.did | 2 +- test/idl/recursion.did | 2 +- test/idl/test.did | 4 ++-- test/idl/unicode.did | 2 +- 12 files changed, 33 insertions(+), 33 deletions(-) diff --git a/design/IDL-AS.md b/design/IDL-AS.md index 5737dac70fa..053aeedba1b 100644 --- a/design/IDL-AS.md +++ b/design/IDL-AS.md @@ -143,8 +143,8 @@ if( : ) = escape() : i() if( : ) = "_" "_": i() // also for implicit labels ifn : -> -ifn((,*) -> () oneway pure?) = shared ia() -> () -ifn((,*) -> (,*) pure?) = shared ia(,*) -> ia(,*) +ifn((,*) -> () oneway query?) = shared ia() -> () +ifn((,*) -> (,*) query?) = shared ia(,*) -> ia(,*) ia : ,* -> ia(,) = i() @@ -218,7 +218,7 @@ escape = "_" hash() "_" otherwise ``` In other words: ActorScript subtyping must be contained in IDL subtyping. - * There is no way to produce `float32` or functions with a `pure` annotation. + * There is no way to produce `float32` or functions with a `query` annotation. Importing interfaces that contain these types fails. ## The value mappings @@ -236,41 +236,41 @@ These mappings should be straight-forward, given the following clarifications: ## Works flows The mapping specified here can be used to support the following use-cases. The -user interfaces (e.g. flag names, or whether `asc`, `idlc`, `dfx` is used) are +user interfaces (e.g. flag names, or whether `asc`, `didc`, `dfx` is used) are just suggestions. * Generating IDL from ActorScript If `foo.as` is an ActorScript `actor` compilation unit, then - asc --generate-idl foo.as -o foo.didl + asc --generate-idl foo.as -o foo.did will type-check `foo.as` as `t = actor { … }`, map the ActorScript type `t` to an IDL type `e(t)` of the form `service `, and produce a - textual IDL file `foo.didl` that ends with a `service n : `, + textual IDL file `foo.did` that ends with a `service n : `, where `n` is the name of the actor class, actor, or basename of the source file. * Checking ActorScript against a given IDL - If `foo.as` is an ActorScript `actor` compilation unit and `foo.didl` a + If `foo.as` is an ActorScript `actor` compilation unit and `foo.did` a textual IDL file, then - asc --check-idl foo.didl foo.as -o foo.wasm + asc --check-idl foo.did foo.as -o foo.wasm - will import the type service `t_spec` specified in `foo.didl`, using the + will import the type service `t_spec` specified in `foo.did`, using the mapping `i`, will generate an IDL type `e(t)` as in the previous point, and and check that `e(t) <: t_spec` (using IDL subtyping). * Converting IDL types to ActorScript types - If `foo.didl` a textual IDL file, then + If `foo.did` a textual IDL file, then - idlc foo.didl -o foo.as + didc foo.did -o foo.as will create an ActorScript library unit `foo.as` that consists of type definitions. - All ``s and the final `` from `foo.didl` is turned into a `type` + All ``s and the final `` from `foo.did` is turned into a `type` declaration in ActorScript, according to `i`. Imported IDL files are recursively inlined. @@ -279,9 +279,9 @@ just suggestions. * Importing IDL types from the ActorScript compiler - If `path/to/foo.didl` a textual IDL file, then a declaration + If `path/to/foo.did` a textual IDL file, then a declaration import Foo "path/to/foo" - is treated by `asc` by reading `foo.didl` as if the developer had - run `idlc path/to/foo.didl -o path/to/foo.as`. + is treated by `asc` by reading `foo.did` as if the developer had + run `didc path/to/foo.did -o path/to/foo.as`. diff --git a/design/IDL.md b/design/IDL.md index e7b3e78ef9b..8501b67e916 100644 --- a/design/IDL.md +++ b/design/IDL.md @@ -65,7 +65,7 @@ This is a summary of the grammar proposed: ::= { ;* } ::= : ( | ) ::= ( ,* ) -> ( ,* ) * - ::= oneway | pure + ::= oneway | query ::= ::= : ::= | | | @@ -161,8 +161,8 @@ Identifiers cannot be keywords of the IDL grammar. In case a name is needed that ``` service { addUser : (name : text, age : nat8) -> (id : nat64); - userName : (id : nat64) -> (text) pure; - userAge : (id : nat64) -> (nat8) pure; + userName : (id : nat64) -> (text) query; + userAge : (id : nat64) -> (nat8) query; deleteUser : (id : nat64) -> () oneway; } ``` @@ -178,11 +178,11 @@ service { #### Structure -A function type describes the list of parameters and results and their respective types. It can optionally be annotated to be *pure*, which indicates that it does not modify any state and can potentially be executed more efficiently (e.g., on cached state). (Other annotations may be added in the future.) +A function type describes the list of parameters and results and their respective types. It can optionally be annotated to be *query*, which indicates that it does not modify any state and can potentially be executed more efficiently (e.g., on cached state). (Other annotations may be added in the future.) ``` ::= ( ,* ) -> ( ,* ) * - ::= oneway | pure + ::= oneway | query ::= ``` We identify `` lists in a function type up to reordering. @@ -945,7 +945,7 @@ T : -> i8* T(:) = leb128(|utf8()|) i8*(utf8()) I() T : -> i8* -T(pure) = i8(1) +T(query) = i8(1) T(oneway) = i8(2) T* : * -> i8* diff --git a/src/idllib/arrange_idl.ml b/src/idllib/arrange_idl.ml index becd3726c07..08cfd9e5920 100644 --- a/src/idllib/arrange_idl.ml +++ b/src/idllib/arrange_idl.ml @@ -25,7 +25,7 @@ let string_of_prim p = let string_of_mode m = match m.it with | Oneway -> " oneway" - | Pure -> " pure" + | Query -> " query" let ($$) head inner = Node (head, inner) diff --git a/src/idllib/parser.mly b/src/idllib/parser.mly index d72ff1bc8e6..c3f0617c480 100644 --- a/src/idllib/parser.mly +++ b/src/idllib/parser.mly @@ -30,7 +30,7 @@ let prim_typs = ["nat", Nat; "nat8", Nat8; "nat16", Nat16; "nat32", Nat32; "nat6 "null", Null; "reserved", Reserved; "empty", Empty] let is_prim_typs t = List.assoc_opt t prim_typs -let func_modes = ["oneway", Oneway; "pure", Pure] +let func_modes = ["oneway", Oneway; "query", Query] let get_func_mode m = List.assoc m func_modes let hash = IdlHash.idl_hash diff --git a/src/idllib/syntax.ml b/src/idllib/syntax.ml index afbfd4cd3e3..851b3074734 100644 --- a/src/idllib/syntax.ml +++ b/src/idllib/syntax.ml @@ -25,7 +25,7 @@ type prim = | Empty type func_mode = func_mode' Source.phrase -and func_mode' = Oneway | Pure +and func_mode' = Oneway | Query type typ = typ' Source.phrase and typ' = diff --git a/test/idl/import.did b/test/idl/import.did index 4a4d1a67ee9..1b9d4bca99c 100644 --- a/test/idl/import.did +++ b/test/idl/import.did @@ -5,5 +5,5 @@ import "import1.did"; service S { f: (t, t1, t2) -> (list, IdErr); - getInventory: (producer_id: nat) -> (Inventory) pure; + getInventory: (producer_id: nat) -> (Inventory) query; } diff --git a/test/idl/ok/oneway.tc.ok b/test/idl/ok/oneway.tc.ok index 848eb80046e..c06d4d1af22 100644 --- a/test/idl/ok/oneway.tc.ok +++ b/test/idl/ok/oneway.tc.ok @@ -1 +1 @@ -oneway.did:2.15-2.41: type error, oneway function has non-unit return type +oneway.did:2.15-2.42: type error, oneway function has non-unit return type diff --git a/test/idl/oneway.did b/test/idl/oneway.did index 32666deec39..7ac77bb19cf 100644 --- a/test/idl/oneway.did +++ b/test/idl/oneway.did @@ -1,3 +1,3 @@ -type g = func (nat) -> () oneway pure; -type f = func (nat) -> (nat) pure oneway; +type g = func (nat) -> () oneway query; +type f = func (nat) -> (nat) query oneway; diff --git a/test/idl/px.did b/test/idl/px.did index 3f9db345cf8..4a21e8afc26 100644 --- a/test/idl/px.did +++ b/test/idl/px.did @@ -26,6 +26,6 @@ type Inventory = record { } service ProduceExchange { - getInventory: (producer_id: nat, UserInfo) -> (Inventory, IdErr) pure; + getInventory: (producer_id: nat, UserInfo) -> (Inventory, IdErr) query; } diff --git a/test/idl/recursion.did b/test/idl/recursion.did index 5efc5f72137..9ec25c1be79 100644 --- a/test/idl/recursion.did +++ b/test/idl/recursion.did @@ -8,6 +8,6 @@ type tree = variant { }; type s = service { f : t; g : (list) -> (B,tree,stream); }; type t = func (server : s) -> (); -type stream = opt record {head:nat; next:func ()-> (stream) pure}; +type stream = opt record {head:nat; next:func ()-> (stream) query}; service A : s diff --git a/test/idl/test.did b/test/idl/test.did index 42e9fbdd293..999f151f3d0 100644 --- a/test/idl/test.did +++ b/test/idl/test.did @@ -13,8 +13,8 @@ type broker = service { service server { addUser : (name : text, age : nat8) -> (id : nat64); - userName : (id : nat64) -> (text) pure; - userAge : (id : nat64) -> (nat8) pure; + userName : (id : nat64) -> (text) query; + userAge : (id : nat64) -> (nat8) query; deleteUser : (id : nat64) -> () oneway; f : (message) -> (broker); } diff --git a/test/idl/unicode.did b/test/idl/unicode.did index 55f94072c14..aad635a43ad 100644 --- a/test/idl/unicode.did +++ b/test/idl/unicode.did @@ -9,7 +9,7 @@ type B = variant { ""; "空的"; " 空的 "; "1⃣️2⃣️3⃣️"; }; service C { "函数名": (A) -> (B); "": (nat) -> (nat); - "👀": (nat) -> (nat) pure; + "👀": (nat) -> (nat) query; "✈️ 🚗 ⛱️ ": () -> () oneway; } From b8fb07335e6f0bc6f8129df2fb50c730177039d4 Mon Sep 17 00:00:00 2001 From: Bas van Dijk Date: Fri, 20 Sep 2019 15:04:33 +0200 Subject: [PATCH 0392/1176] Fix Nix eval error by not representing replay-option as a CI job --- default.nix | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/default.nix b/default.nix index a8dfc7a11cd..d85006cbb93 100644 --- a/default.nix +++ b/default.nix @@ -159,8 +159,6 @@ rec { qc-actorscript = nixpkgs.haskellPackages.callCabal2nix "qc-actorscript" test/random { }; - replay-option = if replay != 0 then " --quickcheck-replay=${toString replay}" else ""; - tests = stdenv.mkDerivation { name = "tests"; src = subpath ./test; @@ -190,7 +188,8 @@ rec { export JSCLIENT=${js-client} asc --version make parallel - qc-actorscript${replay-option} + qc-actorscript${nixpkgs.lib.optionalString (replay != 0) + " --quickcheck-replay=${toString replay}"} ''; installPhase = '' From 1080e0619328f7a36fe18592ccfe4ed84fb28f86 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 20 Sep 2019 16:15:42 +0200 Subject: [PATCH 0393/1176] Do not return unexpected unit tuple (#673) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is left-over code from when `ret_tys` was still meaningful in the backend. With the async pass back it, `ret_tys = []` is always true, so we cannot detect one-shot functions this way. It seems that the system does not actually check yet if `reply` is actually called, so if we just don’t call it, that’s fine too. That is of course a bug in the system, but it helps us for now. Looking forward we have to do one of these: * Get rid of one-shot functions (#661) (my favorite) * Reliable detect them in the backend, and reply there. * Detect them in the async translation, and create a fake reply there. * Add proper support for them to the system BTW, the `idl-tuple` output shows that our treatment of functions returning multiple values is curretly broken, because the pair hides behind the `async` constructor it is not treated as a n-ary return. I hope that we soon get to refactor our function types to get rid of this “administrative `async`” in the return type, which would hopefully fix this. --- src/codegen/compile.ml | 12 +----------- test/run-drun/counter.as | 6 +++++- test/run-drun/ok/counter.drun-run.ok | 9 +++++---- test/run-drun/ok/hello-world-return.drun-run.ok | 4 ++-- test/run-drun/ok/idl-tuple.drun-run.ok | 2 +- test/run-drun/ok/idl-unit.drun-run.ok | 2 +- 6 files changed, 15 insertions(+), 20 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 3395301a0ee..4c7b5b7205b 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -587,7 +587,7 @@ module Func = struct (* Shorthands for various arities *) - let share_code0 env name retty mk_body = + let _share_code0 env name retty mk_body = share_code env name [] retty (fun env -> mk_body env) let share_code1 env name p1 retty mk_body = share_code env name [p1] retty (fun env -> mk_body env @@ -4017,14 +4017,6 @@ module Serialization = struct (compile_unboxed_const 0l) ^^ Dfinity.system_call env "msg" "arg_data_copy" - let serialize_unit env = - Func.share_code0 env "@serialize_unit" [] (fun env -> - let data = "DIDL\x00\x00" in - reply_with_data env - (Text.lit env data ^^ Text.payload_ptr_unskewed) - (compile_unboxed_const (Int32.of_int (String.length data))) - ) - let serialize env ts : G.t = let ts_name = String.concat "," (List.map typ_id ts) in let name = "@serialize<" ^ ts_name ^ ">" in @@ -4827,8 +4819,6 @@ module FuncDec = struct Serialization.deserialize env arg_tys ^^ G.concat (List.rev setters) ^^ mk_body env ae1 ^^ - (* Hack: Emit a unit response for one-shot functions *) - if ret_tys = [] then Serialization.serialize_unit env else G.nop ^^ (* Collect garbage *) G.i (Call (nr (E.built_in env "collect"))) diff --git a/test/run-drun/counter.as b/test/run-drun/counter.as index 1be9df19103..7f086642a3d 100644 --- a/test/run-drun/counter.as +++ b/test/run-drun/counter.as @@ -6,9 +6,13 @@ actor { }; public func printCounter () { printNat c; print "\n"; - } + }; + public func get() : async Nat { + return c + }; } //CALL ingress inc 0x4449444C0000 //CALL ingress inc 0x4449444C0000 //CALL ingress inc 0x4449444C0000 //CALL ingress printCounter 0x4449444C0000 +//CALL ingress get 0x4449444C0000 diff --git a/test/run-drun/ok/counter.drun-run.ok b/test/run-drun/ok/counter.drun-run.ok index 51a04dc9ef4..7d9bd915a92 100644 --- a/test/run-drun/ok/counter.drun-run.ok +++ b/test/run-drun/ok/counter.drun-run.ok @@ -2,16 +2,17 @@ ingress(0) System debug.print: 2 debug.print: -ingress(1) Completed: Canister: Payload: 0x4449444c0000 +ingress(1) Completed: Canister: Empty debug.print: 3 debug.print: -ingress(2) Completed: Canister: Payload: 0x4449444c0000 +ingress(2) Completed: Canister: Empty debug.print: 4 debug.print: -ingress(3) Completed: Canister: Payload: 0x4449444c0000 +ingress(3) Completed: Canister: Empty debug.print: 4 debug.print: -ingress(4) Completed: Canister: Payload: 0x4449444c0000 +ingress(4) Completed: Canister: Empty +ingress(5) Completed: Canister: Payload: 0x4449444c00017d04 diff --git a/test/run-drun/ok/hello-world-return.drun-run.ok b/test/run-drun/ok/hello-world-return.drun-run.ok index a8c1535f920..c1f0a27528b 100644 --- a/test/run-drun/ok/hello-world-return.drun-run.ok +++ b/test/run-drun/ok/hello-world-return.drun-run.ok @@ -1,3 +1,3 @@ ingress(0) System -Ok: Payload: 0x4449444c0000 -Ok: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0001710c48656c6c6f20576f726c6421 +Ok: Payload: 0x4449444c0001710c48656c6c6f20576f726c6421 diff --git a/test/run-drun/ok/idl-tuple.drun-run.ok b/test/run-drun/ok/idl-tuple.drun-run.ok index 139fbf3fc92..428fcb5b372 100644 --- a/test/run-drun/ok/idl-tuple.drun-run.ok +++ b/test/run-drun/ok/idl-tuple.drun-run.ok @@ -1,2 +1,2 @@ ingress(0) System -Ok: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c016c02007c017c01000205 diff --git a/test/run-drun/ok/idl-unit.drun-run.ok b/test/run-drun/ok/idl-unit.drun-run.ok index 139fbf3fc92..939d1cbe7b7 100644 --- a/test/run-drun/ok/idl-unit.drun-run.ok +++ b/test/run-drun/ok/idl-unit.drun-run.ok @@ -1,2 +1,2 @@ ingress(0) System -Ok: Payload: 0x4449444c0000 +Ok: Empty From 339340cc3c3dad8f61b4a849beacd8cea9482631 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Fri, 20 Sep 2019 18:01:10 +0100 Subject: [PATCH 0394/1176] fix bitrot in samples; echo sample output using cat (#672) --- samples/Makefile | 4 +++- samples/app/Makefile | 9 +++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/samples/Makefile b/samples/Makefile index 9b0b286e53e..a30743dbfdf 100644 --- a/samples/Makefile +++ b/samples/Makefile @@ -14,9 +14,11 @@ all: @for sample in $(SAMPLES); do \ echo "$(ASC) $(ASC_FLAGS) $$sample.as >$$sample.txt 2>&1"; \ $(ASC) $(ASC_FLAGS) $$sample.as >$$sample.txt 2>&1; \ + cat $$sample.txt; \ done @for dir in $(SUBDIRS); do \ - make -C $$dir ; \ + echo "make -s -C $$dir"; \ + make -s -C $$dir ; \ done clean: diff --git a/samples/app/Makefile b/samples/app/Makefile index a4302b8b957..926ff070520 100644 --- a/samples/app/Makefile +++ b/samples/app/Makefile @@ -6,17 +6,18 @@ ASC?=../../src/asc DVM?=../../test/dvm.sh # we need to specify the output if there is more than one .as file OUT=main.wasm -#ASC_FLAGS=-r -t -v LIB=list.as types.as server.as client.as SAMPLES:= test all: - $(ASC) -r -t -v main.as >main.txt 2>&1 + rm -f main.txt + $(ASC) -ancient-system-api -r -t -v main.as >main.txt 2>&1 + cat main.txt dvm: - $(ASC) -o $(OUT) main.as + $(ASC) -ancient-system-api -o $(OUT) main.as $(DVM) $(OUT) clean: - rm -f $(OUT) + rm -f $(OUT) main.txt From 90d2434b3c044aa1455904168866c6f37a903240 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Sat, 21 Sep 2019 11:25:33 +0200 Subject: [PATCH 0395/1176] Bump nixpkgs (#676) to the version used by the `dfinity` repository. --- nix/nixpkgs.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nix/nixpkgs.nix b/nix/nixpkgs.nix index 7343b1e1efa..b8a6502553d 100644 --- a/nix/nixpkgs.nix +++ b/nix/nixpkgs.nix @@ -1,9 +1,9 @@ rec { - rev = "3cd3d1eeb6b26f3acb9e9e16cd7220cd5eb07148"; + rev = "e0c7712eac67c6b820d9d1020f46bac96fd8cede"; src = builtins.fetchTarball { - sha256 = "0671riiyzw2y3vw2apxhnq6vq67py64cqkgwiajfnw5qcrva86pw"; - url = "https://github.com/dfinity-lab/nixpkgs/archive/${rev}.tar.gz"; + sha256 = "08rcnqxkninl5a560ss39s4nbqf0a677q6qh1fh7i0lr9pxf6aan"; + url = "https://github.com/NixOS/nixpkgs/archive/${rev}.tar.gz"; }; nixpkgs = import src; From 5a2fd3a60c96b00e234147e75156bde9acea96c2 Mon Sep 17 00:00:00 2001 From: lsgunnlsgunn Date: Sat, 21 Sep 2019 10:14:55 -0700 Subject: [PATCH 0396/1176] Change doc title, change introduction, move some stuff around --- guide/guide.md | 126 +++++++++++++++++++++++-------------------------- 1 file changed, 60 insertions(+), 66 deletions(-) diff --git a/guide/guide.md b/guide/guide.md index e29569bbca7..e2204fdbb4c 100644 --- a/guide/guide.md +++ b/guide/guide.md @@ -1,4 +1,4 @@ -% ActorScript’s Users Guide +% Language Reference Guide % [DFINITY Foundation](https://dfinity.org/) + TODO: * [X] *Sort* primitives and operations as arithmetic (A), boolean (L), bitwise (B) and comparable (C) and use these sorts to concisely present sorted operators (unop, binop, relop, a(ssing)op) etc. @@ -17,96 +17,90 @@ TODO: * [ ] Import expressions * [ ] Modules * [ ] Prelude - +--> # Introduction -ActorScript is a new, general purpose programming language for the -Dfinity platform. - -## Why a new language? - -Dfinity has chosen WebAssembly as its low-level virtual machine. - -The currently -available compilers targeting WebAssembly are for languages that are -either too unsafe (C, C++) or too complex (Rust) for mainstream -programmers. - -To promote correctness and reduce complexity, Dfinity is designing its own language, *ActorScript*, that is safe and expressive, yet simple and approachable to mainstream programmers. +The *internet computer* is a network of connected computers that communicate securely and provide processing services to registered users, developers, and other computers. +If you think of the internet computer as an infrastructure platform, it is similar to a public cloud provider, like Amazon Web Services (AWS), Google Cloud Platform (GCP), or Microsoft Azure, or a private cloud managed internally by private organizations. +Unlike a public or private cloud, however, the internet computer platform is not owned and operated by a single private company. +Its architecture enables multiple computers to operate like one, very powerful, virtual machine that does not dependent on legacy technologies that are vulnerable to attack. -### Interoperability +=== Why develop applications to run on the internet computer? -ActorScript is just one of hopefully many languages able to run on the Dfinity platform. +For programmers and software developers, the **internet computer** platform provides unique capabilities and opportunities within a framework that simplifies how you can design, build, and deploy applications. -Since WebAssembly is language agnostic and, unlike other virtual machines, does not mandate a high-level type system for language interoperation, Dfinity will provide an *Interface Definition Language* to support typed, cross-language communication. +*{proglang}* is a programming language that has been specifically designed for writing applications, services, and microservices that run on the **internet computer** platform and that take full advantage of the unique features that the **internet computer** provides, such as orthogonal persistence, autonomous operation, and tamper-proof message handling. For more information about the unique features of the **internet computer** along with tutorials and examples to help you develop programs that make use of them, see the _Developer's Guide_. -The ActorScript compiler will automate the production and consumption of IDL files, driven by type signatures ActorScript programs and the structure of imported IDL interfaces. +{proglang} provides: -The IDL language is currently under design and outside the scope of this document. +* A high-level language for programming applications to run on the internet computer platform. +* A simple design that uses familiar syntax that is easy for programmers to learn. -## Design Goals +* A well-constructed *actor-based* programming model optimized for efficient message handling. -ActorScript provides: +* An integrated approach to using compiled WebAssembly code to run autonomous applications. -* A high-level language for programming Dfinity applications +* A flexible architecture that anticipates future extensions and improvement to WebAssembly. -* A simple ("K.I.S.S.") design and familiar syntax for average programmers +## Why a new language? -* Good and convenient support for the actor model embodied in Dfinity canisters +The internet computer provides a network platform that can support programs written in different languages. +The only requirement is that the program must support compiling to WebAssembly code. +WebAssembly (commonly-abbreviated as Wasm) is a low-level computer instruction format for virtual machines. +Because WebAssembly code is designed to provide portable low-level instructions that enable client and server applications to be deployed on the web, it is a natural fit for deploying applications that are intended to run on the internet computer platform. +However, most of the higher-level languages--like C, C++, and Rust--that support compiling to WebAssembly are either too unsafe (for example, C or C++) or too complex (for example, Rust) for developers who want to deliver secure applications with minimal overhead. -* A good fit for underlying Wasm and Dfinity execution model +To address the need for correctness without complexity, {company-id} has designed its own *{proglang}* programming language. *{proglang}* provides a simple and expressive alternative to other programming languages that is easy to learn whether you are a new or experienced programmer. +=== Support for other languages -* A forward looking design that anticipates future extensions to WebAssembly +WebAssembly is language-agnostic. +It does not require a high-level type system for language inter-operation. +Although {proglang} is specifically designed to compile to WebAssembly and make it easy to write programs to run on the internet computer, it just one of many languages you can use to develop applications for the internet computer platform. -## Key Features +To support multiple languages and typed, cross-language communication, {company-id} also provides an *Interface Definition Language* (IDL). +The {proglang} compiler automates the production and consumption of IDL files using the type signatures in {proglang} programs and the structure of imported IDL interfaces. -The key language features of ActorScript are: +For information about the *Interface Definition Language* interfaces, see XXX. -* JavaScript/TypeScript-style syntax. +== Highlights and important features -* Automatic memory management (by precise garbage collection). +Although {proglang} is, strictly-speaking, a new language, you might find it is similar to a language you already know. For example, the {proglang} syntax is similar to coding using a functional programming language such as OCaml (Objective Caml). +It also draws on elements that are common in other, more familiar, languages, including JavaScript, TypeScript, C#, Swift, Pony, ML, and Haskell. +Unlike other programming languages, however, {proglang} extends and optimizes features that are uniquely suited to the internet computer platform. -* Strong, static typing with parametric polymorphism, subtype polymorphism and structural typing. +=== Actors and objects -* Unbounded and bounded numeric types with explicit conversions - between them. Bounded numeric types are overflow-checked. +One of the most important principles to keep in mind when preparing to use {proglang} is that it is an *actor-based* programming model. +An actor is a special kind of object that can query and update fields) remotely and asynchronously. +All communication with and between actors involves passing messages asynchronously, in an isolated state, over the network using the internet computer's messaging protocol. +An actor’s messages are processed in sequence, so state modifications never cause race conditions. -* Imperative programming features such a mutable variables and arrays - and flexible, local control flow constructs (`return`, `break` and `continue`). +Classes can be used to produce object of a predetermined type, with a predetermined interface and behavior. +Because actors are essentially objects, you can also define actor classes. +In general, each actor object is used to create one application which is then deployed as a *canister* containing compiled WebAssembly, some environment configuration information, and interface bindings. +For more information about the developing applications and deploying applications, see the _Developer's Guide_. -* Functions (and messages) are first-class values, argument evaluation - is strict (call-by-value). +=== Key language features -* Pattern matching on scalar and compound values. +Some of the other important language features of {proglang} include the following: +* JavaScript/TypeScript-style syntax. +* Automatic memory management by precise garbage collection between messages. +* Bounded polymorphic type system that can assign types without explicit type annotations. +Strong, static typing ensures type safety and includes subtype polymorphism, and structural typing. +Unbounded and bounded numeric types with explicit conversions between +them. +Bounded numeric types are checked for overflow. +* Support for imperative programming features, including mutable variables and arrays, +and local control flow constructs, such as `+return+`, `+break+` and +`+continue+`. +* Functions and messages are first-class values. Call-by-value argument evaluation +is strict. +Pattern-matching is supported for scalar and compound values. * A simple, class-based object system without inheritance. - -* The value of a reference can never implicitly be `null`, - preventing a large class of `null`-reference failures. - Instead, an explicitly handled, possibly `null`, *option type* `?` is provided. - -* Classes can be actors (canisters). - -* An Actor based concurrency model: - - * Actor state is isolated. - - * All communication with and between actors is by message passing (never through shared state). - - * An actor's messages are processed in sequence, so state modifications are - always data-race free. - -* Message passing is asynchronous (to hide network latency). - -* A familiar `async`/`await` constructs enables sequential programming with asynchronous messaging. - -Like most programming languages, ActorScript borrows features from others and -draws inspirations from Java, C#, JavaScript, Swift, Pony, ML, Haskell. - -# ActorScript Syntax (Sketch) - -Productions marked * probably deferred to later versions. +* The value of a reference can never implicitly be `+null+` to prevent many common `+null+`-reference failures. Instead, the language enables you to explicitly handle `+null+` reference values using `+null+`, _option type_ `+?+`. +* Asynchronous message handling enables sequential programming with familiar `+async+` and `+await+` constructs and `promise` replies. # Lexical conventions From 46da2643b9066f27fef90f0a3af3468adf195ad3 Mon Sep 17 00:00:00 2001 From: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> Date: Mon, 23 Sep 2019 15:05:41 +0200 Subject: [PATCH 0397/1176] [ACT-127] Integration tests for the language server (#670) * returns the content of hover responses in the supported format Just sending a String is supported by most editors, but officially deprecated in the protocol * disables overly invasive emacs UI elements * allow building a new lsp-test * adds initial skeleton and nix definition * add directory * pass custom lsp-test * refactor along the lines of Bas' review https://dfinity.slack.com/archives/CCK4B0XE3/p1568899977125800?thread_ts=1568887151.114700&cid=CCK4B0XE3 * prune unnecessary commonBuildInputs * properly handle shutdown/exit requests * adds test project for integration tests * Apply suggestions from code review * expect as-ide path * persist and copy out the test project also make the directories writable otherwise the as-ide will choke * adds a test for completions Also makes all the imports explicit and gives an informative error if too few arguments are provided to the test binary --- default.nix | 103 ++++- emacs/init.el | 3 +- src/languageServer/hover.ml | 8 +- src/languageServer/languageServer.ml | 18 +- src/lsp/lsp.atd | 12 +- test/lsp-int/Main.hs | 91 ++++ test/lsp-int/lsp-int.cabal | 26 ++ test/lsp-int/test-project/.gitignore | 1 + test/lsp-int/test-project/ListClient.as | 18 + test/lsp-int/test-project/app.as | 9 + test/lsp-int/test-project/lib/ListFuncs.as | 9 + test/lsp-int/test-project/lib/ListLib.as | 5 + test/lsp-int/test-project/lib/list.as | 507 +++++++++++++++++++++ test/lsp-int/test-project/lib/option.as | 174 +++++++ test/lsp-int/test-project/lib/prelude.as | 55 +++ 15 files changed, 1026 insertions(+), 13 deletions(-) create mode 100644 test/lsp-int/Main.hs create mode 100644 test/lsp-int/lsp-int.cabal create mode 100644 test/lsp-int/test-project/.gitignore create mode 100644 test/lsp-int/test-project/ListClient.as create mode 100644 test/lsp-int/test-project/app.as create mode 100644 test/lsp-int/test-project/lib/ListFuncs.as create mode 100644 test/lsp-int/test-project/lib/ListLib.as create mode 100644 test/lsp-int/test-project/lib/list.as create mode 100644 test/lsp-int/test-project/lib/option.as create mode 100644 test/lsp-int/test-project/lib/prelude.as diff --git a/default.nix b/default.nix index d85006cbb93..f788368a265 100644 --- a/default.nix +++ b/default.nix @@ -49,6 +49,101 @@ let real-drun = # Include js-client let js-client = dev.js-dfinity-client; in +let haskellPackages = nixpkgs.haskellPackages.override { + overrides = self: super: { + haskell-lsp-types = self.callPackage + ({ mkDerivation, aeson, base, bytestring, data-default, deepseq + , filepath, hashable, lens, network-uri, scientific, text + , unordered-containers + }: + mkDerivation { + pname = "haskell-lsp-types"; + version = "0.16.0.0"; + sha256 = "14wlv54ydbddpw6cwgykcas3rb55w7m78q0s1wdbi594wg1bscqg"; + libraryHaskellDepends = [ + aeson base bytestring data-default deepseq filepath hashable lens + network-uri scientific text unordered-containers + ]; + description = "Haskell library for the Microsoft Language Server Protocol, data types"; + license = stdenv.lib.licenses.mit; + hydraPlatforms = stdenv.lib.platforms.none; + }) {}; + + rope-utf16-splay = self.callPackage + ({ mkDerivation, base, QuickCheck, tasty, tasty-hunit + , tasty-quickcheck, text + }: + mkDerivation { + pname = "rope-utf16-splay"; + version = "0.3.1.0"; + sha256 = "1ilcgwmdwqnp95vb7652fc03ji9dnzy6cm24pvbiwi2mhc4piy6b"; + libraryHaskellDepends = [ base text ]; + testHaskellDepends = [ + base QuickCheck tasty tasty-hunit tasty-quickcheck text + ]; + description = "Ropes optimised for updating using UTF-16 code units and row/column pairs"; + license = stdenv.lib.licenses.bsd3; + }) {}; + + haskell-lsp = self.callPackage + ({ mkDerivation, aeson, async, attoparsec, base, bytestring + , containers, data-default, directory, filepath, hashable + , haskell-lsp-types, hslogger, hspec, hspec-discover, lens, mtl + , network-uri, QuickCheck, quickcheck-instances, rope-utf16-splay + , sorted-list, stm, temporary, text, time, unordered-containers + }: + mkDerivation { + pname = "haskell-lsp"; + version = "0.16.0.0"; + sha256 = "1s04lfnb3c0g9bkwp4j7j59yw8ypps63dq27ayybynrfci4bpj95"; + isLibrary = true; + isExecutable = true; + libraryHaskellDepends = [ + aeson async attoparsec base bytestring containers data-default + directory filepath hashable haskell-lsp-types hslogger lens mtl + network-uri rope-utf16-splay sorted-list stm temporary text time + unordered-containers + ]; + testHaskellDepends = [ + aeson base bytestring containers data-default directory filepath + hashable hspec lens network-uri QuickCheck quickcheck-instances + rope-utf16-splay sorted-list stm text + ]; + testToolDepends = [ hspec-discover ]; + description = "Haskell library for the Microsoft Language Server Protocol"; + license = stdenv.lib.licenses.mit; + hydraPlatforms = stdenv.lib.platforms.none; + }) {}; + + lsp-test = self.callPackage + ({ mkDerivation, aeson, aeson-pretty, ansi-terminal, async, base + , bytestring, conduit, conduit-parse, containers, data-default + , Diff, directory, filepath, hspec, haskell-lsp, lens, mtl + , parser-combinators, process, rope-utf16-splay, text, transformers + , unix, unordered-containers + }: + mkDerivation { + pname = "lsp-test"; + version = "0.7.0.0"; + sha256 = "1lm299gbahrnwfrprhhpzxrmjljj33pps1gzz2wzmp3m9gzl1dx5"; + libraryHaskellDepends = [ + aeson aeson-pretty ansi-terminal async base bytestring conduit + conduit-parse containers data-default Diff directory filepath + haskell-lsp lens mtl parser-combinators process rope-utf16-splay + text transformers unix unordered-containers + ]; + doCheck = false; + testHaskellDepends = [ + aeson base data-default haskell-lsp hspec lens text + unordered-containers + ]; + description = "Functional test framework for LSP servers"; + license = stdenv.lib.licenses.bsd3; + hydraPlatforms = stdenv.lib.platforms.none; + }) {}; + }; + }; in + let commonBuildInputs = [ nixpkgs.ocaml nixpkgs.dune @@ -157,7 +252,9 @@ rec { ''; }; - qc-actorscript = nixpkgs.haskellPackages.callCabal2nix "qc-actorscript" test/random { }; + lsp-int = haskellPackages.callCabal2nix "lsp-int" test/lsp-int { }; + + qc-actorscript = haskellPackages.callCabal2nix "qc-actorscript" test/random { }; tests = stdenv.mkDerivation { name = "tests"; @@ -176,6 +273,7 @@ rec { dvm drun qc-actorscript + lsp-int ] ++ llvmBuildInputs; @@ -190,6 +288,9 @@ rec { make parallel qc-actorscript${nixpkgs.lib.optionalString (replay != 0) " --quickcheck-replay=${toString replay}"} + cp -R ${subpath ./test/lsp-int/test-project} test-project + find ./test-project -type d -exec chmod +w {} + + lsp-int ${as-ide}/bin/as-ide ./test-project ''; installPhase = '' diff --git a/emacs/init.el b/emacs/init.el index 21ced8a3678..d40736bd2d9 100644 --- a/emacs/init.el +++ b/emacs/init.el @@ -78,7 +78,8 @@ :major-modes '(actorscript-mode) :server-id 'asls))) -(use-package lsp-ui :ensure t :commands lsp-ui-mode) +(use-package lsp-ui :ensure t :commands lsp-ui-mode + :config (setq lsp-ui-sideline-enable nil)) (use-package company :ensure t) (use-package company-lsp :ensure t :commands company-lsp) (use-package yasnippet :ensure t) diff --git a/src/languageServer/hover.ml b/src/languageServer/hover.ml index aab4e1da47d..ffbd056206c 100644 --- a/src/languageServer/hover.ml +++ b/src/languageServer/hover.ml @@ -9,6 +9,9 @@ let hover_detail = function let _, params, _ = Type.strings_of_kind (Con.kind ty.typ) in Printf.sprintf "public type %s%s" ty.name params +let markup_content (msg : string) : Lsp.markup_content = + Lsp.{ markup_content_kind = "plaintext"; + markup_content_value = msg } let hover_handler index position file_contents project_root file_path = let hover_result = @@ -20,7 +23,7 @@ let hover_handler index position file_contents project_root file_path = position) (function | Source_file.Alias (_, path) -> - Some Lsp.{ hover_result_contents = path } + Some Lsp.{ hover_result_contents = markup_content path } | Source_file.Resolved resolved -> Index.find_opt resolved.Source_file.path index |> Lib.Fun.flip Lib.Option.bind (fun decls -> @@ -28,7 +31,8 @@ let hover_handler index position file_contents project_root file_path = (fun d -> name_of_ide_decl d = resolved.Source_file.ident) decls) |> Lib.Option.map (fun ide_decl -> - Lsp.{ hover_result_contents = hover_detail ide_decl }) + Lsp.{ hover_result_contents = + markup_content (hover_detail ide_decl) }) | Source_file.Ident _ -> (* At some point we'll want to look this Ident up in the local context*) diff --git a/src/languageServer/languageServer.ml b/src/languageServer/languageServer.ml index e3598eb3a97..7491d22ef02 100644 --- a/src/languageServer/languageServer.ml +++ b/src/languageServer/languageServer.ml @@ -107,7 +107,7 @@ let start () = let publish_diagnostics = Channel.publish_diagnostics oc in let send_response = Channel.send_response oc in let show_message = Channel.show_message oc in - + let shutdown = ref false in let client_capabilities = ref None in let project_root = Sys.getcwd () in @@ -234,19 +234,21 @@ let start () = (match Declaration_index.make_index () with | Error(err) -> () | Ok((ix, _)) -> decl_index := ix); - Lib.Fun.flip Lib.Option.iter !client_capabilities (fun _ -> - (* TODO: determine if the client accepts diagnostics with related info *) - (* let textDocument = capabilities.client_capabilities_textDocument in - * let send_related_information = textDocument.publish_diagnostics.relatedInformation in *) - let diags = List.map diagnostics_of_message msgs in - publish_diagnostics uri diags; - ); + let diags = List.map diagnostics_of_message msgs in + publish_diagnostics uri diags; (* Notification messages *) | (None, `Initialized _) -> show_message Lsp.MessageType.Info "Language server initialized" + | (Some id, `Shutdown _) -> + shutdown := true; + response_result_message id (`ShutdownResponse None) + |> Lsp_j.string_of_response_message + |> send_response + | (_, `Exit _) -> + if !shutdown then exit 0 else exit 1 | (Some id, `CompletionRequest params) -> let uri = params diff --git a/src/lsp/lsp.atd b/src/lsp/lsp.atd index cbf3da04854..0b0b2f94fb9 100644 --- a/src/lsp/lsp.atd +++ b/src/lsp/lsp.atd @@ -50,6 +50,8 @@ type incoming_message_params = [ (* NOTE(Christoph) There are more parameters than just text_document_position on the completion request *) | CompletionRequest of text_document_position_params | CancelRequest of cancel_request_params + | Shutdown of unit nullable + | Exit of unit nullable ] (* @@ -74,6 +76,7 @@ type response_result = [ | TextDocumentHoverResponse of hover_result nullable | TextDocumentDefinitionResponse of location nullable | CompletionResponse of completion_item list + | ShutdownResponse of unit nullable ] type response_error = { @@ -83,10 +86,17 @@ type response_error = { } type hover_result = { - contents : string; + contents : markup_content; } +type markup_content = { + kind : string; + value : string; +} + + + type completion_item = { label : string; kind : int; diff --git a/test/lsp-int/Main.hs b/test/lsp-int/Main.hs new file mode 100644 index 00000000000..7d77aa0bf14 --- /dev/null +++ b/test/lsp-int/Main.hs @@ -0,0 +1,91 @@ +{-# language OverloadedStrings #-} +{-# language DuplicateRecordFields #-} + +module Main where + +import Control.Lens ((^.)) +import Control.Monad (unless) +import Control.Monad.IO.Class (liftIO) +import Data.Default +import Data.Text (Text) +import Language.Haskell.LSP.Test +import Language.Haskell.LSP.Types (TextDocumentIdentifier(..), Position(..), HoverContents(..), MarkupContent(..), MarkupKind(..), TextEdit(..), Range(..)) +import Language.Haskell.LSP.Types.Lens (contents, label, detail) +import System.Directory (setCurrentDirectory) +import System.Environment (getArgs) +import Test.Hspec (shouldBe, shouldMatchList) + +completionTestCase + :: TextDocumentIdentifier + -> Position + -> [(Text, Maybe Text)] + -> Session () +completionTestCase doc pos expected = do + actual <- getCompletions doc pos + liftIO + (shouldMatchList + (map (\c -> (c^.label, c^.detail)) actual) + expected) + +hoverTestCase + :: TextDocumentIdentifier + -> Position + -> Maybe HoverContents + -> Session () +hoverTestCase doc pos expected = do + actual <- getHover doc pos + liftIO (shouldBe (fmap (^.contents) actual) expected) + +plainMarkup :: Text -> Maybe HoverContents +plainMarkup t = + Just + (HoverContents MarkupContent + { _kind = MkPlainText + , _value = t + }) + +main :: IO () +main = do + args <- getArgs + unless (length args == 2) + (putStrLn + "This test expects two command line arguments,\ + \the path to the as-ide binary and the path to\ + \the test project it's supposed to run in") + let [as_ide, project] = args + setCurrentDirectory project + runSession as_ide fullCaps "." $ do + initRes <- initializeResponse + doc <- openDoc "ListClient.as" "actorscript" + hoverTestCase + doc + (Position 13 11) + (plainMarkup "push : (T, List) -> List") + hoverTestCase + doc + (Position 16 11) + (plainMarkup "pop : List -> (?T, List)") + hoverTestCase + doc + (Position 50 50) + Nothing + -- 14 | List.push(x, s); + -- ==> 14 | List.pus + let edit = TextEdit (Range (Position 13 11) (Position 13 27)) "pus" + _ <- applyEdit doc edit + completionTestCase + doc + -- 14 | List.pus| + (Position 13 14) + [("push",Just "(T, List) -> List")] + pure () + + + +-- To make tests involving diagnostics work, we need the compiler +-- pipeline to read its files from the VFS + +-- let edit = TextEdit (Range (Position 1 1) (Position 1 3)) "" +-- _ <- applyEdit doc edit +-- request_ TextDocumentDidSave (DidSaveTextDocumentParams doc) +-- diags <- waitForDiagnostics diff --git a/test/lsp-int/lsp-int.cabal b/test/lsp-int/lsp-int.cabal new file mode 100644 index 00000000000..d076e3bb9c6 --- /dev/null +++ b/test/lsp-int/lsp-int.cabal @@ -0,0 +1,26 @@ +cabal-version: 2.4 + +name: lsp-int +version: 0 +synopsis: Integration tests for the language server +-- description: +author: Christoph Hegemann +maintainer: christoph@dfinity.org +-- copyright: +category: Testing +extra-source-files: CHANGELOG.md + +executable lsp-int + main-is: Main.hs + -- other-modules: + other-extensions: OverloadedStrings, DuplicateRecordFields + build-depends: base ^>=4.12.0.0 + , text ^>=1.2.3.1 + , hspec + , directory + , lens + , data-default + , haskell-lsp-types + , lsp-test ^>=0.7.0.0 + -- hs-source-dirs: + default-language: Haskell2010 diff --git a/test/lsp-int/test-project/.gitignore b/test/lsp-int/test-project/.gitignore new file mode 100644 index 00000000000..53c5e9c22ac --- /dev/null +++ b/test/lsp-int/test-project/.gitignore @@ -0,0 +1 @@ +ls.log diff --git a/test/lsp-int/test-project/ListClient.as b/test/lsp-int/test-project/ListClient.as new file mode 100644 index 00000000000..ef9046a04ba --- /dev/null +++ b/test/lsp-int/test-project/ListClient.as @@ -0,0 +1,18 @@ +module { + import List "lib/list.as"; + import Option "lib/option.as"; + import P "lib/prelude.as"; + + public type Stack = List.List; + + let (a, b) = (1, 2); + + public func empty(): Stack = + List.nil(); + + public func push(x: Int, s: Stack): Stack = + List.push(x, s); + + public func pop(s: Stack): Option.t = + List.pop(s).0 +} diff --git a/test/lsp-int/test-project/app.as b/test/lsp-int/test-project/app.as new file mode 100644 index 00000000000..4d087335404 --- /dev/null +++ b/test/lsp-int/test-project/app.as @@ -0,0 +1,9 @@ +actor { + + import Stack "ListClient.as"; + + func main(): () { + let st = Stack.empty(); + let newst = Stack.push(0, st); + } +} diff --git a/test/lsp-int/test-project/lib/ListFuncs.as b/test/lsp-int/test-project/lib/ListFuncs.as new file mode 100644 index 00000000000..b060d89e2f8 --- /dev/null +++ b/test/lsp-int/test-project/lib/ListFuncs.as @@ -0,0 +1,9 @@ +module { + import List = "./ListLib.as"; + + public func singleton(x: T): List.List = + List.cons(x, List.nil()); + + public func doubleton(x: T, y: T): List.List = + List.cons(x, List.cons(x, List.nil())); +} diff --git a/test/lsp-int/test-project/lib/ListLib.as b/test/lsp-int/test-project/lib/ListLib.as new file mode 100644 index 00000000000..9a1b61271ce --- /dev/null +++ b/test/lsp-int/test-project/lib/ListLib.as @@ -0,0 +1,5 @@ +module { + public type List = ?(T, List); + public func nil(): List = null; + public func cons(x: T, l: List): List = ?(x, l); +} diff --git a/test/lsp-int/test-project/lib/list.as b/test/lsp-int/test-project/lib/list.as new file mode 100644 index 00000000000..d2269903b7a --- /dev/null +++ b/test/lsp-int/test-project/lib/list.as @@ -0,0 +1,507 @@ +module { +/** + +# List + +Purely-functional, singly-linked lists. + +*/ + +/** + Representation + ================= + + A singly-linked list consists of zero or more _cons cells_, wherein +each cell contains a single list element (the cell's _head_), and a pointer to the +remainder of the list (the cell's _tail_). + +*/ + +public type List = ?(T, List); + +/** + Interface + ============== +*/ + + /** + `nil` + ------ + empty list + */ + public func nil() : List = + null; + + + /** + `isNil` + -------- + test for empty list + */ + public func isNil(l : List) : Bool { + switch l { + case null { true }; + case _ { false }; + } + }; + + /** + `push` + ------------- + aka "list cons" + */ + public func push(x : T, l : List) : List = + ?(x, l); + + /** + `last` + ---------- + last element, optionally; tail recursive + */ + public func last(l : List) : ?T = { + switch l { + case null { null }; + case (?(x,null)) { ?x }; + case (?(_,t)) { last(t) }; + } + }; + + /** + `pop` + -------- + treat the list as a stack; combines the usual operations `head` and (non-failing) `tail` into one operation + */ + public func pop(l : List) : (?T, List) = { + switch l { + case null { (null, null) }; + case (?(h, t)) { (?h, t) }; + } + }; + + /** + `len` + -------- + length; tail recursive + */ + public func len(l : List) : Nat = label profile_list_len : Nat { + func rec(l : List, n : Nat) : Nat = label profile_list_len_rec : Nat { + switch l { + case null { n }; + case (?(_,t)) { rec(t,n+1) }; + } + }; + rec(l,0) + }; + + /** + `lenIsLessThan` + -------- + test length against a maximum value; tail recursive + */ + public func lenIsEqLessThan(l : List, i : Nat) : Bool = + label profile_list_lenIsEqLessThan_begin : Bool { + func rec(l : List, i : Nat) : Bool = label profile_list_lenIsEqLessThan_rec : Bool { + switch l { + case null label profile_list_lenIsEqLessThan_end_true : Bool true; + case (?(_, t)) { + if ( i == 0 ) { + label profile_list_lenIsEqLessThan_end_false : Bool + false + } + else { + rec(t, i - 1) + } + }; + } + }; + rec(l, i) + }; + + /** + `lenClamp` + -------- + get the length, unless greater than a maximum value, in which return null; tail recursive + */ + public func lenClamp(l : List, i0 : Nat) : ?Nat = + label profile_list_lenClamp : (?Nat) { + func rec(l : List, i : Nat) : ?Nat = label profile_list_lenClamp_rec : (?Nat) { + switch l { + case null { label profile_list_lenClamp_end_some : (?Nat) ?(i0 - i) }; + case (?(_, t)) { + if ( i == 0 ) { + label profile_list_lenClamp_end_null : (?Nat) + null + } + else { + rec(t, i - 1) + } + }; + } + }; + rec(l, i0) + }; + + /** + `nth` + --------- + array-like list access, but in linear time; tail recursive + */ + public func nth(l : List, n : Nat) : ?T = { + switch (n, l) { + case (_, null) { null }; + case (0, (?(h,t))) { ?h }; + case (_, (?(_,t))) { nth(t, n - 1) }; + } + }; + + /** + `rev` + -------- + reverse the list; tail recursive + */ + public func rev(l : List) : List = { + func rec(l : List, r : List) : List { + switch l { + case null { r }; + case (?(h,t)) { rec(t,?(h,r)) }; + } + }; + rec(l, null) + }; + + /** + `iter` + --------- + Called `app` in SML Basis, and `iter` in OCaml; tail recursive + */ + public func iter(l : List, f:T -> ()) : () = { + func rec(l : List) : () { + switch l { + case null { () }; + case (?(h,t)) { f(h) ; rec(t) }; + } + }; + rec(l) + }; + + /** + `map` + --------- + map the list elements; non-tail recursive + + Note: need mutable Cons tails for tail-recursive map. + */ + public func map(l : List, f:T -> S) : List = { + func rec(l : List) : List { + switch l { + case null { null }; + case (?(h,t)) { ?(f(h),rec(t)) }; + } + }; + rec(l) + }; + + /** + `filter` + ---------- + filter the list elements; non-tail recursive + */ + public func filter(l : List, f:T -> Bool) : List = { + func rec(l : List) : List { + switch l { + case null { null }; + case (?(h,t)) { if (f(h)){ ?(h,rec(t)) } else { rec(t) } }; + } + }; + rec(l) + }; + + /** + `split` + ---------- + split the list elements; non-tail recursive + */ + public func split(l : List, f:T -> Bool) : (List, List) = { + func rec(l : List) : (List, List) = + label profile_list_split_rec : (List, List) { + switch l { + case null { (null, null) }; + case (?(h,t)) { let (l,r) = rec(t) ; + if (f(h)){ (?(h,l), r) } else { (l, ?(h,r)) } }; + } + }; + label profile_list_split_begin : (List, List) + rec(l) + }; + + /** + `mapFilter` + -------------- + map and filter the list elements; non-tail recursive + */ + public func mapFilter(l : List, f:T -> ?S) : List = { + func rec(l : List) : List { + switch l { + case null { null }; + case (?(h,t)) { + switch (f(h)) { + case null { rec(t) }; + case (?h_){ ?(h_,rec(t)) }; + } + }; + } + }; + rec(l) + }; + + /** + `append` + --------- + append two lists; non-tail recursive + */ + public func append(l : List, m : List) : List = { + func rec(l : List) : List { + switch l { + case null { m }; + case (?(h,t)) {?(h,rec(l))}; + } + }; + rec(l) + }; + + /** + `concat` + ----------- + concat (aka "list join"); tail recursive, but requires "two passes" + */ + public func concat(l : List>) : List = { + // 1/2: fold from left to right, reverse-appending the sublists... + let r = + { let f = func(a:List, b:List) : List { revAppend(a,b) }; + foldLeft, List>(l, null, f) + }; + // 2/2: ...re-reverse the elements, to their original order: + rev(r) + }; + + /** + `revAppend` + ------------- + See SML Basis library; tail recursive + */ + public func revAppend(l1 : List, l2 : List) : List = { + switch l1 { + case null { l2 }; + case (?(h,t)) { revAppend(t, ?(h,l2)) }; + } + }; + + /** + `take` + --------- + "take" `n` elements from the prefix of the given list. + If the given list has fewer than `n` elements, we return the full input list. + */ + public func take(l : List, n:Nat) : List = { + switch (l, n) { + case (_, 0) { null }; + case (null,_) { null }; + case (?(h, t), m) {?(h, take(t, m - 1))}; + } + }; + + /** + `drop` + ---------- + */ + public func drop(l : List, n:Nat) : List = { + switch (l, n) { + case (l_, 0) { l_ }; + case (null, _) { null }; + case ((?(h,t)), m) { drop(t, m - 1) }; + } + }; + + /** + `foldLeft` + --------------- + fold list left-to-right using function `f`; tail recursive + */ + public func foldLeft(l : List, a:S, f:(T,S) -> S) : S = { + func rec(l:List, a:S) : S = { + switch l { + case null { a }; + case (?(h,t)) { rec(t, f(h,a)) }; + } + }; + rec(l,a) + }; + + /*** + `foldRight` + ------------ + fold the list right-to-left using function `f`; non-tail recursive + */ + public func foldRight(l : List, a:S, f:(T,S) -> S) : S = { + func rec(l:List) : S = { + switch l { + case null { a }; + case (?(h,t)) { f(h, rec(t)) }; + } + }; + rec(l) + }; + + /** + `find` + ----------- + test if there exists list element for which given predicate is true + */ + public func find(l: List, f:T -> Bool) : ?T = { + func rec(l:List) : ?T { + switch l { + case null { null }; + case (?(h,t)) { if (f(h)) { ?h } else { rec(t) } }; + } + }; + rec(l) + }; + + /** + `exists` + --------- + test if there exists list element for which given predicate is true + */ + public func exists(l: List, f:T -> Bool) : Bool = { + func rec(l:List) : Bool { + switch l { + case null { false }; + // XXX/minor --- Missing parens on condition leads to unhelpful error: + //case (?(h,t)) { if f(h) { true } else { rec(t) } }; + case (?(h,t)) { if (f(h)) { true } else { rec(t) } }; + } + }; + rec(l) + }; + + /** + `all` + ------- + test if given predicate is true for all list elements + */ + public func all(l: List, f:T -> Bool) : Bool = { + func rec(l:List) : Bool { + switch l { + case null { true }; + case (?(h,t)) { if (not f(h)) { false } else { rec(t) } }; + } + }; + rec(l) + }; + + /** + `merge` + --------- + Given two ordered lists, merge them into a single ordered list + */ + public func merge(l1: List, l2: List, lte:(T,T) -> Bool) : List { + func rec(l1: List, l2: List) : List { + switch (l1, l2) { + case (null, _) { l2 }; + case (_, null) { l1 }; + case (?(h1,t1), ?(h2,t2)) { + if (lte(h1,h2)) { + ?(h1, rec(t1, ?(h2,t2))) + } else { + ?(h2, rec(?(h1,t1), t2)) + } + }; + } + }; + rec(l1, l2) + }; + + /** + `lessThanEq` + -------------- + + Compare two lists lexicographic` ordering. tail recursive. + + To do: Eventually, follow `collate` design from SML Basis, with real sum types, use 3-valued `order` type here. + */ + public func lessThanEq(l1: List, l2: List, lte:(T,T) -> Bool) : Bool { + func rec(l1: List, l2: List) : Bool { + switch (l1, l2) { + case (null, _) { true }; + case (_, null) { false }; + case (?(h1,t1), ?(h2,t2)) { lte(h1,h2) and rec(t1, t2) }; + } + }; + rec(l1, l2) + }; + + /** + `isEq` + --------- + Compare two lists for equality. tail recursive. + + `isEq(l1, l2)` is equivalent to `lessThanEq(l1,l2) && lessThanEq(l2,l1)`, but the former is more efficient. + */ + public func isEq(l1: List, l2: List, eq:(T,T) -> Bool) : Bool { + func rec(l1: List, l2: List) : Bool { + switch (l1, l2) { + case (null, null) { true }; + case (null, _) { false }; + case (_, null) { false }; + case (?(h1,t1), ?(h2,t2)) { eq(h1,h2) and rec(t1, t2) }; + } + }; + rec(l1, l2) + }; + + /** + `partition` + --------------- + using a predicate, create two lists from one: the "true" list, and the "false" list. + (See SML basis library); non-tail recursive. + */ + public func partition(l: List, f:T -> Bool) : (List, List) { + func rec(l: List) : (List, List) { + switch l { + case null { (null, null) }; + case (?(h,t)) { + let (pl,pr) = rec(t); + if (f(h)) { + (?(h, pl), pr) + } else { + (pl, ?(h, pr)) + } + }; + } + }; + rec(l) + }; + + /** + `tabulate` + -------------- + generate a list based on a length, and a function from list index to list element. + (See SML basis library); non-tail recursive. + */ + public func tabulate(n:Nat, f:Nat -> T) : List { + func rec(i:Nat) : List { + if (i == n) { null } else { ?(f(i), rec(i+1)) } + }; + rec(0) + }; + +/** + +To do: +-------- +- iterator objects, for use in `for ... in ...` patterns +- operations for lists of pairs and pairs of lists: zip, split, etc +- more regression tests for everything that is below + +*/ +} diff --git a/test/lsp-int/test-project/lib/option.as b/test/lsp-int/test-project/lib/option.as new file mode 100644 index 00000000000..58656d06a19 --- /dev/null +++ b/test/lsp-int/test-project/lib/option.as @@ -0,0 +1,174 @@ +module { +/** + +Functions for Option types. + +*/ + +import P "prelude.as"; + +public type t = ?A; + +/*** + + `isSome` + -------------------- + + Returns true if the value is not `null`. + +*/ +public func isSomeAny(x: ?Any): Bool = + switch x { + case null false; + case _ true; + }; + +public func isSome(x: t): Bool = isSomeAny(x); + +/*** + + `isNull` + -------------------- + + Returns true if the value is `null`. + +*/ +public func isNullAny(x: ?Any): Bool = not isSome(x); + +public func isNull(x: t): Bool = not isSome(x); + +/*** + + `unwrap` + -------------------- + + Unwrap an optional value, and fail if it is `null`. + +*/ +public func unwrap(x: ?T): T = + switch x { + case null { P.unreachable() }; + case (?x_) x_; + }; + +/*** + + `unwrapOr` + -------------------- + + Unwrap an optional value or a default. + +*/ +public func unwrapOr(x: ?T, d: T): T = + switch x { + case null { d }; + case (?x_) x_; + }; + +/*** + + `option` + -------------------- + + Unwrap an optional value. If null, return the default, else, apply the function to the unwrapped value. + +*/ +public func option(x: ?A, f: A->B, d: B): B = + switch x { + case null { d }; + case (?x_) f(x_); + }; + +/*** + + `map` + -------------------- + + Apply a function to the wrapped value. + +*/ +public func map(f: A->B, x: ?A): ?B = + switch x { + case null null; + case (?x_) ?f(x_); + }; + +/*** + + `assertSome` + -------------------- + + Assert that the given value is not `null`; ignore this value and return unit. + +*/ +public func assertSomeAny(x: ?Any) = + switch x { + case null { P.unreachable() }; + case _ {}; + }; + +public func assertSome(x: ?A) = assertSomeAny(x); + +/*** + + `assertNull` + -------------------- + + Assert that the given value is `null`; ignore this value and return unit. + +*/ +public func assertNullAny(x: ?Any) = + switch x { + case null { }; + case _ { P.unreachable() }; + }; + +public func assertNull(x: ?A) = assertNullAny(x); + +/*** + + `printOpInt` + -------------------- + + Print an optional integer. + +*/ +public func printOpInt(x : ?Int) = + switch x { + case null { print "null" }; + case (?x_) { print "?"; printInt x_ }; + }; + +public func apply(f : ?(A -> B), x : ?A) : ?B { + switch (f, x) { + case (?f_, ?x_) { + ?f_(x_); + }; + case (_, _) { + null; + }; + }; +}; + +public func bind(x : ?A, f : A -> ?B) : ?B { + switch(x) { + case (?x_) { + f(x_); + }; + case (null) { + null; + }; + }; +}; + +public func join(x : ??A) : ?A { + bind(x, func (x_ : ?A) : ?A { + x_; + }); +}; + +public func pure(x: A) : ?A { + ?x; +}; + +} diff --git a/test/lsp-int/test-project/lib/prelude.as b/test/lsp-int/test-project/lib/prelude.as new file mode 100644 index 00000000000..6199cf0d996 --- /dev/null +++ b/test/lsp-int/test-project/lib/prelude.as @@ -0,0 +1,55 @@ +module { +/** + +Stdlib prelude +=============== + + This prelude file proposes standard library features that _may_ +belong in the _language_ (compiler-internal) prelude sometime, after +some further experience and discussion. Until then, they live here. + +*/ + +/*** + + `printLn` + --------- + + Print text followed by a newline. + +*/ +public func printLn(x : Text) { + print(x # "\n"); +}; + +/*** + + `nyi`: Not yet implemented + ----------------------------- + + Mark incomplete code with the `nyi` and `xxx` functions. + + Each have calls are well-typed in all typing contexts, which +trap in all execution contexts. + +*/ + +public func nyi() : None = + { assert false ; loop { } }; + +public func xxx() : None = + { assert false ; loop { } }; + +/*** + + `unreachable` + -------------------- + + Mark unreachable code with the `unreachable` function. + + Calls are well-typed in all typing contexts, and they + trap in all execution contexts. + +*/ +public func unreachable() : None = { assert false ; loop { } }; +} From 73d98b27adacf6c5c4501a69dc06b1ff3ef9ab94 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Mon, 23 Sep 2019 15:18:09 +0200 Subject: [PATCH 0398/1176] don't hardcode gcc (#681) it is not present on darwin --- stdlib/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/Makefile b/stdlib/Makefile index eae1d34861b..206e28d5016 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -429,7 +429,7 @@ $(OUTDIR)/ProduceExchangeLoadQuery_5_100.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDI $(STOPWATCH): $(STOPWATCH_C) - gcc $< -o $@ + $(CC) $< -o $@ $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm $(STOPWATCH) $(STOPWATCH) "$(DRUN) $< /dev/zero" "5, 1, " > $@ From 5cf475bb2da64e6c07bc2a2e90c4c8067d8e2f46 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Mon, 23 Sep 2019 20:50:26 +0100 Subject: [PATCH 0399/1176] Add support for reject continuations (via Try-Catch/Throw) (#610) * async-double-cps.md * copy asynccps.md * sketch double-barelled cps conversion * parsing and source typing of try/throw * exploit structured exception handling to simplify cps * incorporate exceptions * clobber asynccps.md, adding try/catch * try -> throw * WIP * WIP: sketch extended_prim implementation after async/await rewrite * refine catch and throw types to accommodate system errors on catch only * add Throw/Catch to IR * modify interpreters to propagate uncaught error (not trap) * add test throw.as * implement Try/Throw for show.ml and serialization.ml * Update guide/guide.md Co-Authored-By: Andreas Rossberg * Update design/asynccps.md Co-Authored-By: Andreas Rossberg * Update src/ir_interpreter/interpret_ir.ml Co-Authored-By: Andreas Rossberg * Apply suggestions from code review fix typos in spec Co-Authored-By: Andreas Rossberg * Update design/asynccps.md Co-Authored-By: Andreas Rossberg * Update design/asynccps.md * adapt tailcall.ml (conservatively) * upgrade await.ml with throw/try/catch, for now using trapping failure continuation on entry to async * add errors to async values, fix bug in await.ml, add simpler tests with local exception handling only * updated throw tests * WIP async translation (committing for travel) * fix error continuation bugs * fixed bugs; all tests passing; refactored async lowering to accommodate legacy and new platform * revert debugging change * make error type opaque WIP * don't lower Error, just implement prims in codegen * made reply shared function take just a text argument, not an unsharable Error, to match the new platform (and satisfy the IR type checker * add error code masking to interpreters to match compilation * adapt interpretation of @await and @async (still to be tested) * simple try catch to single case; comment out (already supported) mult-case from grammar * remove unnessary try/throw cases from (post-lowering) serialzation.ml * implement missing cases on T.Error * rough documentation * doc changes * typos * describe error code * improve explanation of system error masking * Update src/codegen/compile.ml Co-Authored-By: Joachim Breitner * Update src/codegen/compile.ml Co-Authored-By: Joachim Breitner * Update src/ir_passes/await.ml * refactor compile.ml for Joachim * tidy * got returns working again on drun * got rejects working on new api * clean up merge residue * add IC prims for reply, reject, error_code and type them; asser mode in backend; merge with master * accept throw.as; these failures are expected * Update design/asynccps.md Co-Authored-By: Joachim Breitner * fix codegen error in error prim * compile.ml: remove dependency of Error on IR, as requested * implement Dfinity.reject and .error_code to hide details * add workaround for asc-js bug --- design/Syntax.md | 8 +- design/async.md | 161 -------------- design/asynccps.md | 196 +++++++++++------- guide/guide.md | 85 ++++++-- src/as_def/arrange.ml | 4 + src/as_def/syntax.ml | 4 +- src/as_frontend/coverage.ml | 1 + src/as_frontend/definedness.ml | 5 +- src/as_frontend/effect.ml | 6 +- src/as_frontend/lexer.mll | 3 + src/as_frontend/parser.mly | 17 +- src/as_frontend/static.ml | 2 + src/as_frontend/typing.ml | 32 +++ src/as_idl/as_to_idl.ml | 22 +- src/as_interpreter/interpret.ml | 67 ++++-- src/as_types/arrange_type.ml | 1 + src/as_types/type.ml | 36 +++- src/as_types/type.mli | 8 + src/as_values/prim.ml | 14 ++ src/as_values/value.ml | 15 +- src/as_values/value.mli | 4 +- src/codegen/compile.ml | 71 ++++++- src/exes/asc.ml | 2 +- src/ir_def/arrange_ir.ml | 7 +- src/ir_def/check_ir.ml | 26 +++ src/ir_def/construct.ml | 36 +++- src/ir_def/construct.mli | 7 +- src/ir_def/freevars.ml | 2 + src/ir_def/ir.ml | 6 + src/ir_def/ir_effect.ml | 4 +- src/ir_interpreter/interpret_ir.ml | 103 ++++++--- src/ir_passes/async.ml | 148 +++++++++---- src/ir_passes/await.ml | 102 +++++++-- src/ir_passes/rename.ml | 2 + src/ir_passes/show.ml | 19 +- src/ir_passes/tailcall.ml | 2 + src/lowering/desugar.ml | 2 + src/pipeline/resolve_import.ml | 2 + src/prelude/prelude.ml | 63 +++++- src/profiler/profiler.ml | 3 +- test/as-idl/ok/pa_cars.did.ok | 4 +- test/as-idl/ok/result.did.ok | 10 +- test/fail/ok/modexp5.tc.ok | 2 +- test/run-dfinity/local-throw.as | 67 ++++++ .../ok/counter-class.wasm.stderr.ok | 31 ++- test/run-dfinity/ok/local-throw.dvm-run.ok | 3 + test/run-dfinity/ok/local-throw.run-ir.ok | 3 + test/run-dfinity/ok/local-throw.run-low.ok | 3 + test/run-dfinity/ok/local-throw.run.ok | 3 + test/run-dfinity/ok/simple-throw.dvm-run.ok | 1 + test/run-dfinity/ok/simple-throw.run-ir.ok | 1 + test/run-dfinity/ok/simple-throw.run-low.ok | 1 + test/run-dfinity/ok/simple-throw.run.ok | 1 + test/run-dfinity/simple-throw.as | 21 ++ test/run-dfinity/tiny.as | 8 + test/run-drun/ok/reject.drun-run.ok | 9 + test/run-drun/reject.as | 28 +++ test/run/ok/throw.diff-low.ok | 10 + test/run/ok/throw.run-ir.ok | 6 + test/run/ok/throw.run-low.ok | 1 + test/run/ok/throw.run.ok | 6 + test/run/ok/throw.wasm.stderr.ok | 1 + test/run/throw.as | 128 ++++++++++++ 63 files changed, 1206 insertions(+), 440 deletions(-) delete mode 100644 design/async.md create mode 100644 test/run-dfinity/local-throw.as create mode 100644 test/run-dfinity/ok/local-throw.dvm-run.ok create mode 100644 test/run-dfinity/ok/local-throw.run-ir.ok create mode 100644 test/run-dfinity/ok/local-throw.run-low.ok create mode 100644 test/run-dfinity/ok/local-throw.run.ok create mode 100644 test/run-dfinity/ok/simple-throw.dvm-run.ok create mode 100644 test/run-dfinity/ok/simple-throw.run-ir.ok create mode 100644 test/run-dfinity/ok/simple-throw.run-low.ok create mode 100644 test/run-dfinity/ok/simple-throw.run.ok create mode 100644 test/run-dfinity/simple-throw.as create mode 100644 test/run-dfinity/tiny.as create mode 100644 test/run-drun/ok/reject.drun-run.ok create mode 100644 test/run-drun/reject.as create mode 100644 test/run/ok/throw.diff-low.ok create mode 100644 test/run/ok/throw.run-ir.ok create mode 100644 test/run/ok/throw.run-low.ok create mode 100644 test/run/ok/throw.run.ok create mode 100644 test/run/ok/throw.wasm.stderr.ok create mode 100644 test/run/throw.as diff --git a/design/Syntax.md b/design/Syntax.md index f015d8dccc1..78247fdceb2 100644 --- a/design/Syntax.md +++ b/design/Syntax.md @@ -17,6 +17,7 @@ Productions marked * probably deferred to later versions. ( (( :)? ),* ) tuple Any top None bottom + Error errors/exceptions ::= object type fields : immutable @@ -68,7 +69,7 @@ Productions marked * probably deferred to later versions. and conjunction or disjunction if (else )? conditional - switch { (case )+ } switch + switch { (case ;)+ } switch while while loop loop (while )? loop for ? in iteration @@ -81,8 +82,9 @@ Productions marked * probably deferred to later versions. assert assertion : type annotation declaration (scopes to block) -* throw raise exception -* try (catch )+ ( )? try + throw raise error (only in async) + try catch try (only in async) +* try catch { (case ;) +} ( )? try-finally ::= object expression fields var? = field diff --git a/design/async.md b/design/async.md deleted file mode 100644 index a52949813a0..00000000000 --- a/design/async.md +++ /dev/null @@ -1,161 +0,0 @@ -# Lowering Async (following C\# async/await) - -Assuming a promise-like interface: - -``` -class Async(){ - setresult(t:T):T; - continuewith(k:()->()):(); - result(): T; -} -``` - -## Example 1 (no control flow) - -``` -async { -let a = await f(); -let b = await g(); -a+b; -} : Async -``` - -Our approach is inspired by the C# translation (which does, however, assume closures are stateful and can capture l-values). - -The basic idea is to hoist all locals (mutable or not) to mutable, outermost variables. - -The async expression (typically a block) is lowered to a block that -1. defines a mutable async value `a : Async` to return the result of type `T`. -2. declares all locals as mutable globals (global to the block) (to save the values of locals in the state machine). -3. declares a mutable integral state variable, `s`, initially `0`, (to save the next state of the state machine). -4. defines a (recursive) side-effecting function, `SM:()->()`, encoding a state machine that acts as a call-back to each enclosed await. -5. runs the state machine, SM(), until the first await (if any, with `a.result` unset) or completion (with a.result set). - * note that SM() must have access to `a` in its closure. -6. returns the task `a` (whether complete or not). - -The state machine is function `SM():()` that: -- enters a loop that switches on the current value of `s` to resume the machine from the next state. -- pauses the state machine (at an `await`) by first advancing `s` to the next logical state and returning from `SM()` (thus exiting the loop, too). -- returning a value `t` from the async block (whether implicitly or explicity), sets the result of `a` (`a.setresult(t)`) - -Here's a manual translation of the example above. - -``` -{ -let a0 = Async(); -let mutable a : Int; -let mutable b : Int; -let mutable s : Int = 0; // state of the machine, one state for entry plus each await (for now) -func SM() { - do loop - switch s { - case 0 : - s = 1; - let a1 = f(); - a1.continuewith(SM); - return; - case 1 : - a = a_1.result; - s = 2; - let a2 = g(); - a2.continuewith(SM); - return; - case 2: - b := a_2.result; - a0.setresult(b1+a2); - return; - } -SM(); -a_0; -} -``` - -C# actually has an optimization that allows one to test whether an awaited async is already complete (Async.IsCompleted:()->Bool) and continue the loop, -avoiding the cost of scheduling a continuation, but that's a local optimization we could do too. - -## Example 2 (with strutured control flow) - -With control constructs, the C# approach is to first lower structured control flow to explicit labels and jumps. -Each control point now has a label that can then be interpreted as an additional state of the state machine. -Implicit flow is lowered to *Jumping* to a label. In turn jumping to a label is just setting the state, s, accordingly and re-entering the m/c interpreter (without pausing) with a ```continue loop```. - -Roughly: - -``` -async () { - while (await f()) - await g() -} -``` - -First, lower control flow to labelled loops (see l): - -``` -async () { - loop l { - if (await f()) then { - await g(); - continue l; - } - else break l; -} -``` -Then a-normalize awaits (i.e. name the awaited values, so we can reference their ```.continuewith``` and ```.result``` fields) - -``` -async () { - loop l { - let b = await f(); - if (b) then { - await g(); - continue l; - } - else break l; - } -} -``` - -Finally, translate as in the previous example, using ```s = ```*nextstate*```; continue loop``` -to interpret inserted jumps appropriately. - -Roughly, the result might look something like this: - -``` -{ -let a0 = Async(); -let mutable s = 0; -func SM():(){ - do loop - switch s { - case 0 : - let a1 = f(); - a1.continuewith(SM); - return; - case 1 : - b = a_1.result; - if (b) then { state = 2; continue loop }; - else {state = 3; continue loop;} - s = 2; - let a2 = g(); - a2.continuewith(SM); - return; - case 2: - { - state = 0; - continue loop; - } - case 3: - { - state = 4; - continue loop; - } - case 4; - { - a_0.setresult(()); - return; - } - } -SM(); -a_0; -} -``` diff --git a/design/asynccps.md b/design/asynccps.md index 0516ba6d63c..e9353317633 100644 --- a/design/asynccps.md +++ b/design/asynccps.md @@ -18,72 +18,94 @@ e = x | let x = e in e | if e then e else e | async e - | await e + | await e // may throw | while e do e | label l e | break l e | return e + | try e with x -> e // evaluate e, handling error x using e. + | throw e // throw error e to nearest enclosing handler or async block ``` -The aim of game is to remove async and await by a source-to-source translation, leaving as much code as possible in direct-style. + +The aim of the game is to remove async and await and try catch/throw by a source-to-source translation, leaving as much code as possible in direct-style. Terms have effect `T` (trivial) or `A` (await) with `T` < `A`. A term has effect `A` if any subterm not enclosed by `async` is `await`. -The only term that introduce effect `A` is `await` - the effect is masked by its innermost enclosing async (if any). +The only terms that introduce effect `A` is `await`, `try` or `throw` - the effect is masked by its innermost enclosing `async` (if any). + +Note `await`, `try` and `throw` may only occur within an `async` block. The body of every lambda must be trivial. We write `t` for trivial terms and `e` otherwise. Every trival term is also a non-trivial term since `T` < `A`. -Term 't' are await free terms (in the sense that await can only occur within a nested async (with no intervening lambdas)). +Terms `t` are `await/try/throw` free terms (in the sense that await can only occur within a nested async (with no intervening lambdas)). + +Trivial terms can be compiled in direct style by translation `T[t]`. + +Non-trivial terms must be cps-converted by translations `C r [e]` and `CPS[e] r`. +Their translations expect a pair `r = (reply,reject)` and `reply` and `reject` continuations (for interpreting early `return` and `throw`). We write 'r.reply' and `r.reject` for the obvious projections. +The `reply` continuation only changes when we enter an async block. +The `reject` continuation changes when we enter a `async` or `try`. +The translation `C r [e]` produces a term in cps, taking a single continuation argument. + +Since `async` and `try catch` are block structured, we can record the +`reply/reject` continuation in an environment argument, simplifying +the translation by not threading two continuations throughout. -Trivial terms can be compiled in direct style by translation T[t]. -Non-trivial terms must be cps-converted by translations C[e] and CPS[e] and their translations expect a continutation. ```JS -CPS[ e ] = \\k.let kret = k in C[e] k +CPS[ e ] = \\r.C r [e] @ r.reply where -C[ t ] = +C r [ t ] = \\k. k @ T[ t ] -C[ t1 e2 ] = - \\k. let f = T[ t1 ] in C[ e2 ] @ \\v. k @ (f @ v)) -C[ e1 e2 ] = - \\k. C[ e1 ] @ (\\f.C[ e2 ] @ \\v. k @ (f @ v)) -C[ let x = t1 in e2 ] = - \\k.let x = T[t1] in C[e2] @ k -C[ let x = e1 in e2 ] = - \\k.C[ t1 ] @ (\\x. C[e2] @ k) -C[ await t ] = - \\k.await(T[t1],k) -C[ await e ] = - \\k.C[e] (\\v.await(v,k)) -C[ if e1 then e2 else e3 ] = - \\k.C[e1](\\b.if b then C[e1]@k else C[e2]@k) -C[ if t1 then e2 else e3 ] = - \\k.if T[t1] then C[e1] k else C[e2]@k) -C[ if e1 then t2 else t3 ] = - \\k.C[e1](\\b.k @ (if b then T[t1] else T[t2])) -C[ while t1 do e2 ] = - \\k. let rec l = \u. if T[t1] then C[e2]@l else k@u in - l@() -C[ while e1 do t2 ] = - \\k. let rec l = \u. C[e1](\\v.if v then T[t2] ; l@u else k@u)in - l@() -C[ while e1 do e2 ] = - \\k. let rec l = \u. C[e1](\\v.if v then C[e2]@l else k@()) in - l@() -C[ label l e ] = \\l. C[e] @ l // we use label l to name the continuation -C[ break l e ] = \\k. C[e] @ l // discard k, continue from l -C[ return e ] = \\_. C[e] @ kret // discard k, return +C r [ t1 e2 ] = + \\k. let f = T[ t1 ] in C r [ e2 ] @ \\v. k @ (f @ v)) +C r [ e1 e2 ] = + \\k. C r [ e1 ] @ (\\f.C r [ e2 ] @ (\\v. k @ (f @ v)) +C r [ let x = t1 in e2 ] = + \\k.let x = T[t1] in C r [e2] @ k +C r [ let x = e1 in e2 ] = + \\k.C r [ t1 ] @ (\\x. C r [e2] @ k) +C r [ await t ] = + \\k.await(T[t1], (k, r) ) +C r [ await e ] = + \\k.C r [e] @ (\\v.await(v,(k,r)) +C r [ if e1 then e2 else e3 ] = + \\k.C r [e1] @ (\\b.if b then C r [e1]@k else C r [e2]@k) +C r [ if t1 then e2 else e3 ] = + \\k.if T[t1] then C r [e1] @ k else C r [e2] @ k +C r [ if e1 then t2 else t3 ] = + \\k.C r [e1] @ (\\b.k @ (if b then T[t1] else T[t2]))) +C r [ while t1 do e2 ] = + \\k. + let rec l = \u. if T[t1] then C r [e2]@l else k@u in + l@() +C r [ while e1 do t2 ] = + \\k. + let rec l = \u. C r [e1](\\v.if v then T[t2] ; l@u else k@u) in + l@() +C r [ while e1 do e2 ] = + \\k. + let rec l = \u. C r [e1] (\\v.if v then C r [e2]@l else k@()) in + l@() +C r [ label l e ] = \\l. C r [e] @ l // we use label l to name the success continuation +C r [ break l e ] = \\k. C r [e] @ l // discard k, continue from l +C r [ return e ] = \\k. C r [e] @ r.reply // discard k, exit via r.reply +C r [ try e1 with x -> e2 ] = + let reject' = \\x. C r [e2] @ k in + \\k. C (r.reply,reject') [e1] @ k +C r [ throw e] = \\k. C r [e] @ r.reject // discard k, exit async or try via reject ``` -The translation of trivial terms, `T[ _ ]`, is homomorpic on all terms but `async _`, at which point we switch to the CPS[-] translation. -Note `T[await _]` is (deliberately) undefined. +The translation of trivial terms, `T[ _ ]`, is homomorphic on all terms but `async _`, at which point we switch to the `CPS[-]` translation. +Note `T[await _]`, `T[throw _]` and `T[try _ with _ -> _]`, are (deliberately) undefined. ```JS -T[ async e ] = spawn (\t.CPS(e) @ (\v.complete(t,v)) +T[ async e ] = spawn (\t.CPS[e] @ ((\v.complete(t,v)),(\e.reject(t,e))) T[ x ]= x T[ c ] = c T[ \x.t ] = \x.T[t] @@ -101,23 +123,44 @@ T[ return T[t] ] = return T[t] ``` -We use the following primitives for scheduling actions (that complete tasks). +We use the following primitives for scheduling actions (that complete asyncs). ```JS -spawn(f) = let t = task{result=None;waiters=[]} in +type 'a cont = 'a -> unit; + +type 'a result = + Pending + | Rejected of error + | Completed of 'a + +type error = ...; + +type 'a async = { mutable result : 'a result; mutable waiters: ('a cont * error cont) list } + +spawn(f) = let t = async { result = Pending; waiters = [] } in schedule (\u.f(t)); t -await(t,k) = match t with - | {result=Some v} -> k v - | {result=None} -> t.waiters <- k::t.waiters; yield() +await(t,reply,reject) = match t with + | {result = Completed v} -> reply v + | {result = Rejected e} -> reject e + | {result = Pending} -> + t.waiters <- (k,r)::t.waiters; + yield() complete(t,v) = match t with - | {result=None;waiters} -> - t.result = Some v; - foreach waiter in waiters do - schedule(\u.waiter(v)) - | {result=Some _ } -> assert(false) + | {result = Pending; waiters} -> + t.result <- Completed v; + foreach (reply,_reject) in waiters do + schedule(\u.reply(v)) + | {result = _ } -> assert(false) + +reject(t,v) = match t with + | { result = Pending; waiters} -> + t.result <- Rejected v; + foreach (_reply,reject) in waiters do + schedule(\u.reject(v)) + | { result = _ } -> assert(false) yield() = schedule.Next() ``` @@ -138,41 +181,45 @@ The first call to break occurs in a trivial sub-expression and is compiled to `b However, the second call to `break l (await{2})` is a non-trivial expression (due to the await()) and compiled as the application to a continuation `C[await{2}] @ l`. Our remedy is to track the target representation of a source label as either target label (Label) or target continuation (Cont) and -translate accordingly. +translate accordingly. To handle the translation of (source) `return` to (target) `reply` or `return`, we use a distinguished label `l_ret`. Thus extend the translations `C[]`, `CPS[]` and `T[]` with an implicit environment argument,`env`, classifying labels and consulted and modified in select rules. The other cases are unchanged (apart from propagating the `env` argument). ``` -C env [ label l e ] = +C env r [ label l e ] = let env' = env[l->Cont] in - \\l. C env' ;[e] @ l // we use label l to name the continuation -C env [ break l e ] = + \\l. C env' r [e] @ l // we use label l to name the success continuation + +C env r [ break l e ] = assert(env[l] = Cont) - \\k. C env [e] @ l // discard k, continue from l + \\k. C env r [e] @ l // discard k, continue from l -C env [ return e ] = +C env r [ return e ] = assert(env[kret] = Cont) - \\_. C env [e] @ kret // discard k, return + \\k. C env r [e] @ r.reply // discard k, using reply T env [ async e ] = - let env' = [kret->Cont] in - spawn (\t.CPS env' [e] @ (\v.complete(t,v)) + let env' = [l_ret->Cont] in + spawn (\t.CPS env' [e] @ ((\v.complete(t,v)),(\e.reject(t,e))) T env [\x.t] = - let env' = [kret->Label] - \x.T env' [t] + let env' = [l_ret->Label] + \x.T env' [t] + T env [ break l t ] = - match env[t] with - | Cont -> return l@(T env [t]) - | Label -> break l (T env [t]) + match env[t] with + | Cont -> l @ (T env [t]) + | Label -> break l (T env [t]) + T env [ label l t ] = - let env' = env[l->Label] - label l (T env' [t]) + let env' = env[l->Label] + label l (T env' [t]) + T env [ return t ] = - match env[kret] with - | Cont -> return kret@(T env [t]) - | Label -> return (T env [t]) + match env[l_ret] with + | Cont -> l_ret @ (T env [t]) + | Label -> return (T env [t]) ``` @@ -185,3 +232,12 @@ async { break l (await {2}) } ``` + + +AS syntax + +``` + ::= + throw + try { (catch )+ } +``` diff --git a/guide/guide.md b/guide/guide.md index e29569bbca7..5b0a5b5d9c4 100644 --- a/guide/guide.md +++ b/guide/guide.md @@ -16,6 +16,7 @@ TODO: * [ ] Object patterns * [ ] Import expressions * [ ] Modules +* [ ] Complete draft of Try/Throw expressions and primitive Error/ErrorCode type * [ ] Prelude # Introduction @@ -133,9 +134,9 @@ All comments are treated as whitespace. The following keywords are reserved and may not be used as identifiers: ```bnf -actor and async assert await break case class continue else +actor and async assert await break case catch class continue else false for func if in new not null object or label let loop -private public return shared switch true type var while +private public return shared switch true try type var while ``` ## Identifiers @@ -337,6 +338,7 @@ Type expressions are used to specify the types of arguments, constraints (a.k.a ( (( :)? ),* ) tuple Any top None bottom + Error errors/exceptions Shared sharable types ( type ) parenthesized type ``` @@ -358,6 +360,7 @@ The sort of a type determines the operators (unary, binary, relational and assig | `Word64` | A, B, C | unsigned 64-bit integers with bitwise operations | | `Char` | C | unicode characters | | `Text` | T, C | unicode strings of characters with concatentation `_ # _` | +| `Error` | | (opaque) error values | ### Type `Bool` @@ -429,6 +432,30 @@ other arithmetic types, and their literals need type annotation, e.g. `(-42 : Word16)`. For negative literals the two's-complement representation is applied. +### Error type + +Errors are opaque values constructed using operation +* `error: Text -> Unit` +and examined using operations: +* `errorCode`: `Error -> ErrorCode` (TBC) +* `errorMessage`: `Error -> Text` + +(where `ErrorCode` is the prelude defined variant type: + +``` +type ErrorCode = {#error; #system ; /*...*/ }; +``` +) + +`Error` values can be thrown and caught within an `async` expression or `shared` function (only). + +A constructed error `e = error(m)` has `errorCode(e) = #error` and `errorMessage(e)=m`. +Errors with non-`#error` (system) error codes may be caught and thrown, but not constructed. + +Note: Exiting an async block or shared function with a system error +exits with a copy of the error with revised code `#error` and the original error message. +This prevents programmatic forgery of system errors. (TBR) + ## Constructed types ` ?` is the application of type a identifier, either built-in (i.e. `Int`) or user defined, to zero or more type *arguments*. @@ -629,7 +656,7 @@ Two types `T`, `U` are related by subtyping, written `T <: U`, whenever, one of A type `T` is *shared* if it is * `Any` or `None`, or -* a primitive type, or +* a primitive type other than `Error`, or * an option type `? V` where `V` is shared, or * a tuple type `(T0, ..., Tn)` where all `Ti` are shared, or * an immutable array type `[V]` where `V` is shared, or @@ -684,6 +711,8 @@ A type `T` is *shared* if it is return ? return async async expression await await future (only in async) + throw raise an error (only in async) + try catch catch an error (only in async) assert assertion : type annotation dec declaration @@ -905,8 +934,8 @@ Otherwise, the expression returns the result of evaluating ``. ## Or The or expression ` or ` has type `Bool` provided `` and `` have type `Bool`. -switch -The expression ` and ` evaluates `exp1` to a switchresult `r1`. If `r1` is `trap`, the expression results in `trap`. Otherwise `r1` switchis a Boolean value `v`. + +The expression ` and ` evaluates `exp1` to a result `r1`. If `r1` is `trap`, the expression results in `trap`. Otherwise `r1` is a Boolean value `v`. If `v == true` the expression returns the value `true` (without evaluating ``). Otherwise, the expression returns the result of evaluating ``. @@ -1018,7 +1047,7 @@ The label-expression `label (: )? ` has type `T` provided: The result of evaluating `label (: )? ` is the result of evaluating ``. -### Labeled loops +## Labeled loops If `` in `label (: )? ` is a looping construct: @@ -1063,7 +1092,7 @@ The `return` expression exits the corresponding dynamic function invocation or c TBR async traps? -### Async +## Async The async expression `async ` has type `async T` provided: @@ -1079,28 +1108,53 @@ The implicit return type in `` is `T`. That is, the | `==` | equals | Evaluation of `async ` queues a message to evaluate `` in the nearest enclosing or top-level actor. It immediately returns a promise of type `async T` that can be used to `await` the result of the pending evaluation of ``. -### Await +## Await The `await` expression `await ` has type `T` provided: * `` has type `async T`, * `T` is shared, -* the `await` is explicitly enclosed by an `async`-expression. +* the `await` is explicitly enclosed by an `async`-expression or appears in the body of a `shared` function. -`await ` evaluates `` to a result `r`. If `r` is `trap`, evaluation returns `trap`. Otherwise `r1` is a promise. If the promise is complete with value `v`, then `await ` evaluates to value `v`. If the `promise` is incomplete, that is, its evaluation is still pending, `await ` suspends evaluation of the neared enclosing `async` or `shared`-function, adding the suspension to the wait-queue of the `promise`. Execution of the suspension is resumed once the promise is completed (if ever). +Expression `await ` evaluates `` to a result `r`. If `r` is `trap`, evaluation returns `trap`. Otherwise `r` is a promise. If the promise is complete with value `v`, then `await ` evaluates to value `v`. +If the promise is complete with (thrown) error value `e`, then `await ` re-throws the error `e`. +If the `promise` is incomplete, that is, its evaluation is still pending, `await ` suspends evaluation of the neared enclosing `async` or `shared`-function, adding the suspension to the wait-queue of the `promise`. Execution of the suspension is resumed once the promise is completed (if ever). _WARNING:_ between suspension and resumption of a computation, the state of the enclosing actor may change due to concurrent processing of other incoming actor messages. It is the programmer's responsibility to guard against non-synchronized state changes. -### Assert + +## Throw + +The `throw` expression `throw ` has type `None` provided: + +* `` has type `Error`, +* the `throw` is explicitly enclosed by an `async`-expression or appears in the body of a `shared` function. + +Expression `throw ` evaluates `` to a result `r`. If `r` is `trap`, evaluation returns `trap`. Otherwise `r` is an error value `e`. Execution proceeds from the `catch` clause of the nearest enclosing `try catch ` whose pattern `` matches value `e`. If there is no such `try` expression, `e` is stored as the erroneous result of the `async` value of the nearest enclosing `async` expression or `shared` function invocation. + +## Try + +The `try` expression `try catch ` has type `T` provided: + +* `` has type `T`. +* `` has type `Error` and `` has type `T` in the context extended with `` +* the `try` is explicitly enclosed by an `async`-expression or appears in the body of a `shared` function. + +Expression `try catch ` evaluates `` to a result `r`. +If evaluation of `` throws an uncaught error value `e`, the result of the `try` is the result of evaluating `` under the bindings determined by the match of `e` against `pat`. + +Note: because the `Error` type is opaque, the pattern match cannot fail (typing ensures that `` is an irrefutable wildcard or identifier pattern). + +## Assert The assert expression `assert ` has type `()` provided `exp` has type `Bool`. -`assert ` evaluates `` to a result `r`. If `r` is `trap` evaluation returns `trap`. Otherwise `r` is a boolean value `v`. The result of `assert ` is +Expression `assert ` evaluates `` to a result `r`. If `r` is `trap` evaluation returns `trap`. Otherwise `r` is a boolean value `v`. The result of `assert ` is * the value `()`, when `v` is `true`; or * `trap`, when `v` is `false`. -### Type Annotation +## Type Annotation The type annotation expression ` : ` has type `T` provided: @@ -1113,13 +1167,13 @@ The result of evaluating ` : ` is the result of evaluating ``. Note: type annotations have no-runtime cost and cannot be used to perform the (checked or unchecked) `down-casts` available in other object-oriented languages. -### Declaration Expression +## Declaration Expression The declaration expression `` has type `T` provided the declaration `` has type `T`. Evaluating the expression `` proceed by evaluating ``, returning the result of `` but discarding the bindings introduced by `` (if any). -### Parentheses +## Parentheses The parenthesized expression `( )` has type `T` provided `` has type `T`. @@ -1153,7 +1207,6 @@ The consequences of pattern match failure depends on the context of the pattern. The wildcard pattern `_` matches a single value without binding its contents to an identifier. - ## Identifier pattern The identifier pattern `` matches a single value and binds it to the identifier ``. diff --git a/src/as_def/arrange.ml b/src/as_def/arrange.ml index f0174b2efb4..5f106d01e18 100644 --- a/src/as_def/arrange.ml +++ b/src/as_def/arrange.ml @@ -56,6 +56,8 @@ let rec exp e = match e.it with | TagE (i, e) -> "TagE" $$ [id i; exp e] | PrimE p -> "PrimE" $$ [Atom p] | ImportE (f, fp) -> "ImportE" $$ [Atom (if !fp = "" then f else !fp)] + | ThrowE e -> "ThrowE" $$ [exp e] + | TryE (e, cs) -> "TryE" $$ [exp e] @ List.map catch cs and pat p = match p.it with | WildP -> Atom "WildP" @@ -95,6 +97,8 @@ and lit (l:lit) = match l with and case c = "case" $$ [pat c.it.pat; exp c.it.exp] +and catch c = "catch" $$ [pat c.it.pat; exp c.it.exp] + and pat_field pf = pf.it.id.it $$ [pat pf.it.pat] and obj_sort s = match s.it with diff --git a/src/as_def/syntax.ml b/src/as_def/syntax.ml index cbfdc14aafe..8051c976e28 100644 --- a/src/as_def/syntax.ml +++ b/src/as_def/syntax.ml @@ -145,9 +145,9 @@ and exp' = | AssertE of exp (* assertion *) | AnnotE of exp * typ (* type annotation *) | ImportE of (string * string ref) (* import statement *) -(* - | ThrowE of exp list (* throw exception *) + | ThrowE of exp (* throw exception *) | TryE of exp * case list (* catch exception *) +(* | FinalE of exp * exp (* finally *) | AtomE of string (* atom *) *) diff --git a/src/as_frontend/coverage.ml b/src/as_frontend/coverage.ml index 5806d57a28d..6d13214b2b1 100644 --- a/src/as_frontend/coverage.ml +++ b/src/as_frontend/coverage.ml @@ -102,6 +102,7 @@ let pick_val vs = function | T.Word64 -> pick_word (module V.Word64) (fun x -> V.Word64 x) vs | T.Char -> pick_char vs | T.Text + | T.Error | T.Float -> Any let rec expand_notval t n vs : desc list = diff --git a/src/as_frontend/definedness.ml b/src/as_frontend/definedness.ml index aa02e054640..aba9354c4ef 100644 --- a/src/as_frontend/definedness.ml +++ b/src/as_frontend/definedness.ml @@ -81,10 +81,10 @@ let rec exp msgs e : f = match e.it with | VarE i -> M.singleton i.it Eager (* Or anything that is occurring in a call (as this may call a closure): *) | CallE (e1, ts, e2) -> eagerify (exps msgs [e1; e2]) - (* And break and return can be thought of as calling a continuation: *) + (* And break, return, throw can be thought of as calling a continuation: *) | BreakE (i, e) -> eagerify (exp msgs e) | RetE e -> eagerify (exp msgs e) - + | ThrowE e -> eagerify (exp msgs e) (* Uses are delayed by function expressions *) | FuncE (_, s, tp, p, t, e) -> delayify (exp msgs e /// pat msgs p) @@ -112,6 +112,7 @@ let rec exp msgs e : f = match e.it with | OrE (e1, e2) -> exps msgs [e1; e2] | IfE (e1, e2, e3) -> exps msgs [e1; e2; e3] | SwitchE (e, cs) -> exp msgs e ++ cases msgs cs + | TryE (e, cs) -> exp msgs e ++ cases msgs cs | WhileE (e1, e2) -> exps msgs [e1; e2] | LoopE (e1, None) -> exp msgs e1 | LoopE (e1, Some e2) -> exps msgs [e1; e2] diff --git a/src/as_frontend/effect.ml b/src/as_frontend/effect.ml index 4f3ac993d3c..e1664a56fb3 100644 --- a/src/as_frontend/effect.ml +++ b/src/as_frontend/effect.ml @@ -82,8 +82,10 @@ let rec infer_effect_exp (exp:Syntax.exp) : T.eff = max_eff e1 e2 | AsyncE exp1 -> T.Triv - | AwaitE exp1 -> - T.Await + | ThrowE _ + | TryE _ + | AwaitE _ -> + T.Await (* TBR: perhaps we should rename the effect *) and effect_cases cases = match cases with diff --git a/src/as_frontend/lexer.mll b/src/as_frontend/lexer.mll index 32ab8f6972b..1ce617e577c 100644 --- a/src/as_frontend/lexer.mll +++ b/src/as_frontend/lexer.mll @@ -191,6 +191,7 @@ rule token mode = parse | "await" { AWAIT } | "break" { BREAK } | "case" { CASE } + | "catch" { CATCH } | "class" { CLASS } | "continue" { CONTINUE } | "label" { LABEL } @@ -212,6 +213,8 @@ rule token mode = parse | "public" { PUBLIC } | "return" { RETURN } | "shared" { SHARED } + | "try" { TRY } + | "throw" { THROW } | "debug_show" { DEBUG_SHOW } | "switch" { SWITCH } | "true" { BOOL true } diff --git a/src/as_frontend/parser.mly b/src/as_frontend/parser.mly index 2881625e76f..7de19fe6dba 100644 --- a/src/as_frontend/parser.mly +++ b/src/as_frontend/parser.mly @@ -95,8 +95,8 @@ let share_expfield (ef : exp_field) = %token LET VAR %token LPAR RPAR LBRACKET RBRACKET LCURLY RCURLY -%token AWAIT ASYNC BREAK CASE CONTINUE LABEL -%token IF IN ELSE SWITCH LOOP WHILE FOR RETURN +%token AWAIT ASYNC BREAK CASE CATCH CONTINUE LABEL +%token IF IN ELSE SWITCH LOOP WHILE FOR RETURN TRY THROW %token ARROW ASSIGN %token FUNC TYPE OBJECT ACTOR CLASS PUBLIC PRIVATE SHARED %token SEMICOLON SEMICOLON_EOL COMMA COLON SUB DOT QUEST @@ -462,6 +462,14 @@ exp_nondec(B) : { IfE(b, e1, TupE([]) @? no_region) @? at $sloc } | IF b=exp_nullary(ob) e1=exp(bl) ELSE e2=exp(bl) { IfE(b, e1, e2) @? at $sloc } + | TRY e1=exp_nullary(ob) CATCH c=catch + { TryE(e1, [c]) @? at $sloc } +(* TODO: enable multi-branch TRY (already supported by compiler) + | TRY e=exp_nullary(ob) LCURLY cs=seplist(case, semicolon) RCURLY + { TryE(e, cs) @? at $sloc } +*) + | THROW e=exp(bl) + { ThrowE(e) @? at $sloc } | SWITCH e=exp_nullary(ob) LCURLY cs=seplist(case, semicolon) RCURLY { SwitchE(e, cs) @? at $sloc } | WHILE e1=exp_nullary(ob) e2=exp(bl) @@ -485,11 +493,14 @@ exp(B) : | d=dec_var { match d.it with ExpD e -> e | _ -> BlockE([d]) @? at $sloc } - case : | CASE p=pat_nullary e=exp(bl) { {pat = p; exp = e} @@ at $sloc } +catch : + | p=pat_nullary e=exp(bl) + { {pat = p; exp = e} @@ at $sloc } + exp_field_nonvar : | x=id EQ e=exp(ob) { let d = LetD(VarP(x) @! x.at, e) @? at $sloc in diff --git a/src/as_frontend/static.ml b/src/as_frontend/static.ml index d726b826448..494b6e1e635 100644 --- a/src/as_frontend/static.ml +++ b/src/as_frontend/static.ml @@ -73,6 +73,8 @@ let rec exp m e = match e.it with | ForE _ | IfE _ | SwitchE _ + | ThrowE _ + | TryE _ -> err m e.at and fields m efs = List.iter (fun ef -> dec m ef.it.dec) efs diff --git a/src/as_frontend/typing.ml b/src/as_frontend/typing.ml index d08d54eec63..78765c96490 100644 --- a/src/as_frontend/typing.ml +++ b/src/as_frontend/typing.ml @@ -726,6 +726,20 @@ and infer_exp'' env exp : T.typ = (String.concat " or\n " ss) end; t + | TryE (exp1, cases) -> + if not env.async then + error env exp.at "misplaced try"; + let t1 = infer_exp env exp1 in + let t2 = infer_cases env T.catch T.Non cases in + if not env.pre then begin + match Coverage.check_cases cases T.catch with + | [] -> () + | ss -> + warn env exp.at + "the catches in this try do not cover error value\n %s" + (String.concat " or\n " ss) + end; + T.lub t1 t2 | WhileE (exp1, exp2) -> if not env.pre then begin check_exp env T.bool exp1; @@ -788,6 +802,11 @@ and infer_exp'' env exp : T.typ = local_error env exp.at "misplaced return" end; T.Non + | ThrowE exp1 -> + if not env.async then + error env exp.at "misplaced throw"; + if not env.pre then check_exp env T.throw exp1; + T.Non | AsyncE exp1 -> let env' = {env with labs = T.Env.empty; rets = Some T.Pre; async = true} in @@ -884,6 +903,19 @@ and check_exp' env t exp : T.typ = (String.concat " or\n " ss) ); t + | TryE (exp1, cases), _ -> + if not env.async then + error env exp.at "misplaced try"; + check_exp env t exp1; + check_cases env T.catch t cases; + (match Coverage.check_cases cases T.catch with + | [] -> () + | ss -> + warn env exp.at + "the catches in this try do not cover value\n %s" + (String.concat " or\n " ss) + ); + t | FuncE (_, s', [], pat, typ_opt, exp), T.Func (s, _, [], ts1, ts2) -> let ve = check_pat_exhaustive env (T.seq ts1) pat in let t2 = diff --git a/src/as_idl/as_to_idl.ml b/src/as_idl/as_to_idl.ml index 9fdc0c63ec8..2eb52bb8564 100644 --- a/src/as_idl/as_to_idl.ml +++ b/src/as_idl/as_to_idl.ml @@ -11,7 +11,7 @@ let env = ref Env.empty (* For monomorphization *) let stamp = ref Env.empty let type_map = ref Env.empty - + let normalize str = let illegal_chars = ['-'; '/';] in String.map (fun c -> if List.mem c illegal_chars then '_' else c) str @@ -26,7 +26,7 @@ let string_of_con vs c = match Env.find_opt id !type_map with | None -> (match Env.find_opt name !stamp with - | None -> + | None -> stamp := Env.add name 1 !stamp; type_map := Env.add id 1 !type_map; 1 @@ -37,12 +37,12 @@ let string_of_con vs c = | Some n -> n in Printf.sprintf "%s_%d" (normalize name) n | _ -> assert false - + let unescape lab : label = let lab = normalize lab in let len = String.length lab in try if lab.[len-1] = '_' then begin - if lab.[0] = '_' then + if lab.[0] = '_' then Nat (Lib.Uint32.of_string lab) else Id (String.sub lab 0 (len-1)) end else Id lab @@ -72,7 +72,8 @@ let prim p = | Float -> I.Float64 | Char -> I.Nat32 | Text -> I.Text - + | Error -> assert false + let rec typ vs t = (match t with | Any -> I.PrimT I.Reserved @@ -101,7 +102,7 @@ let rec typ vs t = | Tup ts -> I.RecordT (tuple vs ts) | Array t -> I.VecT (typ vs t) - | Opt t -> I.OptT (typ vs t) + | Opt t -> I.OptT (typ vs t) | Obj (Object, fs) -> I.RecordT (List.map (field vs) fs) | Obj (Actor, fs) -> I.ServT (meths vs fs) @@ -124,7 +125,7 @@ and field vs {lab; typ=t} = | Nat nat -> let name = Lib.Uint32.to_string nat @@ no_region in I.{id = nat; name = name; typ = typ vs t} @@ no_region - | Id id -> + | Id id -> let name = id @@ no_region in let id = Idllib.IdlHash.idl_hash id in I.{id = id; name = name; typ = typ vs t} @@ no_region @@ -170,7 +171,7 @@ let chase_decs env = ConSet.iter (fun c -> if is_actor_con c then chase_con [] c ) env.Scope.con_env - + let gather_decs () = Env.fold (fun id t list -> let dec = I.TypD (id @@ no_region, t) @@ no_region in @@ -209,12 +210,11 @@ let actor progs = match find_last_actor prog with | None -> None | Some (id, t) -> Some (I.ActorD (id @@ no_region, typ [] t) @@ no_region) - + let prog (progs, senv) : I.prog = env := Env.empty; let actor = actor progs in if actor = None then chase_decs senv; - let decs = gather_decs () in + let decs = gather_decs () in let prog = I.{decs = decs; actor = actor} in {it = prog; at = no_region; note = ""} - diff --git a/src/as_interpreter/interpret.ml b/src/as_interpreter/interpret.ml index e4b591be678..3da5d9dcbc9 100644 --- a/src/as_interpreter/interpret.ml +++ b/src/as_interpreter/interpret.ml @@ -15,6 +15,7 @@ type val_env = V.def V.Env.t type lib_env = V.value V.Env.t type lab_env = V.value V.cont V.Env.t type ret_env = V.value V.cont option +type throw_env = V.value V.cont option type flags = { trace : bool; @@ -32,6 +33,7 @@ type env = labs : lab_env; libs : lib_env; rets : ret_env; + throws : throw_env; async : bool } @@ -53,6 +55,7 @@ let env_of_scope flags scope = libs = scope.lib_env; labs = V.Env.empty; rets = None; + throws = None; async = false; } @@ -122,24 +125,38 @@ end let make_async () : V.async = {V.result = Lib.Promise.make (); waiters = []} -let get_async async (k : V.value V.cont) = +let get_async async (k : V.value V.cont) (r : V.value V.cont) = match Lib.Promise.value_opt async.V.result with - | Some v -> k v - | None -> async.V.waiters <- k::async.V.waiters + | Some (V.Ok v) -> k v + | Some (V.Error v) -> r v + | None -> async.V.waiters <- (k,r)::async.V.waiters let set_async async v = - List.iter (fun k -> Scheduler.queue (fun () -> k v)) async.V.waiters; - Lib.Promise.fulfill async.V.result v; + List.iter (fun (k,_) -> Scheduler.queue (fun () -> k v)) async.V.waiters; + Lib.Promise.fulfill async.V.result (V.Ok v); async.V.waiters <- [] -let fulfill async v = +let reject_async async v = + List.iter (fun (_,k) -> Scheduler.queue (fun () -> k v)) async.V.waiters; + Lib.Promise.fulfill async.V.result (V.Error v); + async.V.waiters <- [] + +let reply async v = Scheduler.queue (fun () -> set_async async v) +let reject async v = + match v with + | V.Tup [ _code; message ] -> + (* mask the error code before rejecting *) + Scheduler.queue + (fun () -> reject_async async (V.Tup [V.Variant("error", V.unit); message])) + | _ -> assert false -let async env at (f: (V.value V.cont) -> unit) (k : V.value V.cont) = +let async env at (f: (V.value V.cont) -> (V.value V.cont) -> unit) (k : V.value V.cont) = let async = make_async () in (* let k' = fun v1 -> set_async async v1 in *) - let k' = fun v1 -> fulfill async v1 in + let k' = reply async in + let r = reject async in if env.flags.trace then trace "-> async %s" (string_of_region at); Scheduler.queue (fun () -> if env.flags.trace then trace "<- async %s" (string_of_region at); @@ -148,6 +165,7 @@ let async env at (f: (V.value V.cont) -> unit) (k : V.value V.cont) = if env.flags.trace then trace "<= %s" (string_of_val env v); decr trace_depth; k' v) + r ); k (V.Async async) @@ -162,6 +180,14 @@ let await env at async k = k v ) ) + (let r = Lib.Option.value (env.throws) in + fun v -> + Scheduler.queue (fun () -> + if env.flags.trace then + trace "<- await %s threw %s" (string_of_region at) (string_of_arg env v); + incr trace_depth; + r v + )) let actor_msg env id f v (k : V.value V.cont) = if env.flags.trace then trace "-> message %s%s" id (string_of_arg env v); @@ -191,7 +217,7 @@ let make_async_message env id v = Value.async_func call_conv.n_args (fun v k -> let async = make_async () in actor_msg env id f v (fun v_async -> - get_async (V.as_async v_async) (fun v_r -> set_async async v_r) + get_async (V.as_async v_async) (set_async async) (reject_async async) ); k (V.Async async) ) @@ -476,7 +502,11 @@ and interpret_exp_mut env exp (k : V.value V.cont) = | SwitchE (exp1, cases) -> interpret_exp env exp1 (fun v1 -> interpret_cases env cases exp.at v1 k - ) + ) + | TryE (exp1, cases) -> + let k' = fun v1 -> interpret_catches env cases exp.at v1 k in + let env' = { env with throws = Some k' } in + interpret_exp env' exp1 k | WhileE (exp1, exp2) -> let k_continue = fun v -> V.as_unit v; interpret_exp env exp k in interpret_exp env exp1 (fun v1 -> @@ -523,11 +553,13 @@ and interpret_exp_mut env exp (k : V.value V.cont) = interpret_exp env exp1 (find id.it env.labs) | RetE exp1 -> interpret_exp env exp1 (Lib.Option.value env.rets) + | ThrowE exp1 -> + interpret_exp env exp1 (Lib.Option.value env.throws) | AsyncE exp1 -> async env exp.at - (fun k' -> - let env' = {env with labs = V.Env.empty; rets = Some k'; async = true} + (fun k' r -> + let env' = {env with labs = V.Env.empty; rets = Some k'; throws = Some r; async = true} in interpret_exp env' exp1 k') k @@ -549,7 +581,6 @@ and interpret_exps env exps vs (k : V.value list V.cont) = | exp::exps' -> interpret_exp env exp (fun v -> interpret_exps env exps' (v::vs) k) - (* Cases *) and interpret_cases env cases at v (k : V.value V.cont) = @@ -561,6 +592,16 @@ and interpret_cases env cases at v (k : V.value V.cont) = | Some ve -> interpret_exp (adjoin_vals env ve) exp k | None -> interpret_cases env cases' at v k +(* Catches *) + +and interpret_catches env cases at v (k : V.value V.cont) = + match cases with + | [] -> + Lib.Option.value env.throws v (* re-throw v *) + | {it = {pat; exp}; at; _}::cases' -> + match match_pat pat v with + | Some ve -> interpret_exp (adjoin_vals env ve) exp k + | None -> interpret_catches env cases' at v k (* Patterns *) diff --git a/src/as_types/arrange_type.ml b/src/as_types/arrange_type.ml index c0e3b16aee7..72bc43f4d19 100644 --- a/src/as_types/arrange_type.ml +++ b/src/as_types/arrange_type.ml @@ -36,6 +36,7 @@ let prim p = match p with | Float -> Atom "Float" | Char -> Atom "Char" | Text -> Atom "Text" + | Error -> Atom "Error" let con c = Atom (Con.to_string c) diff --git a/src/as_types/type.ml b/src/as_types/type.ml index eea66fd3812..136fed438bd 100644 --- a/src/as_types/type.ml +++ b/src/as_types/type.ml @@ -28,6 +28,7 @@ type prim = | Float | Char | Text + | Error type t = typ and typ = @@ -67,6 +68,16 @@ module ConEnv = Env.Make(struct type t = con let compare = Con.compare end) module ConSet = ConEnv.Dom +(* Field ordering *) + +let compare_field f1 f2 = + match f1,f2 with + | {lab = l1; typ = Typ _}, {lab = l2; typ = Typ _ } -> compare l1 l2 + | {lab = l1; typ = Typ _}, {lab = l2; typ = _ } -> -1 + | {lab = l1; typ = _}, {lab = l2; typ = Typ _ } -> 1 + | {lab = l1; typ = _}, {lab = l2; typ = _ } -> compare l1 l2 + + (* Short-hands *) let unit = Tup [] @@ -76,6 +87,19 @@ let int = Prim Int let text = Prim Text let char = Prim Char +let throwErrorCodes = List.sort compare_field [ + { lab = "error"; typ = unit } +] + +let catchErrorCodes = List.sort compare_field ( + throwErrorCodes @ [ + { lab = "system"; typ = unit} + (* TBC *) + ]) + +let throw = Prim Error (* Tup [Variant throwErrorCodes; text] *) +let catch = Prim Error (* Tup [Variant catchErrorCodes; text] *) + let prim = function | "Null" -> Null | "Bool" -> Bool @@ -96,6 +120,7 @@ let prim = function | "Float" -> Float | "Char" -> Char | "Text" -> Text + | "Error" -> Error | s -> raise (Invalid_argument ("Type.prim: " ^ s)) let seq = function [t] -> t | ts -> Tup ts @@ -375,13 +400,6 @@ let lookup_typ_field l tfs = | Some {typ = Typ c; _} -> c | _ -> invalid "lookup_typ_field" -let compare_field f1 f2 = - match f1,f2 with - | {lab = l1; typ = Typ _}, {lab = l2; typ = Typ _ } -> compare l1 l2 - | {lab = l1; typ = Typ _}, {lab = l2; typ = _ } -> -1 - | {lab = l1; typ = _}, {lab = l2; typ = Typ _ } -> 1 - | {lab = l1; typ = _}, {lab = l2; typ = _ } -> compare l1 l2 - (* Span *) @@ -390,7 +408,7 @@ let rec span = function | Con _ as t -> span (promote t) | Prim Null -> Some 1 | Prim Bool -> Some 2 - | Prim (Nat | Int | Float | Text) -> None + | Prim (Nat | Int | Float | Text | Error) -> None | Prim (Nat8 | Int8 | Word8) -> Some 0x100 | Prim (Nat16 | Int16 | Word16) -> Some 0x10000 | Prim (Nat32 | Int32 | Word32 | Nat64 | Int64 | Word64 | Char) -> None (* for all practical purposes *) @@ -536,6 +554,7 @@ let shared t = seen := S.add t !seen; match t with | Var _ | Pre -> assert false + | Prim Error -> false | Any | Non | Prim _ | Typ _ -> true | Async _ | Mut _ -> false | Con (c, ts) -> @@ -1030,6 +1049,7 @@ let string_of_prim = function | Word64 -> "Word64" | Char -> "Char" | Text -> "Text" + | Error -> "Error" let string_of_var (x, i) = if i = 0 then sprintf "%s" x else sprintf "%s.%d" x i diff --git a/src/as_types/type.mli b/src/as_types/type.mli index 531264c0500..40259e91b4a 100644 --- a/src/as_types/type.mli +++ b/src/as_types/type.mli @@ -28,6 +28,7 @@ type prim = | Float | Char | Text + | Error type t = typ and typ = @@ -64,6 +65,13 @@ val nat : typ val int : typ val text : typ val char : typ + +val throwErrorCodes : field list +val catchErrorCodes : field list +val throw : typ +val catch : typ + + val iter_obj : typ -> typ val prim : string -> prim diff --git a/src/as_values/prim.ml b/src/as_values/prim.ml index 2915f90e9df..171cb564702 100644 --- a/src/as_values/prim.ml +++ b/src/as_values/prim.ml @@ -289,6 +289,20 @@ let prim = function in go (fun xs -> xs) k 0 | _ -> assert false ) + | "error" -> fun v k -> + k (Value.Tup [Variant ("error", Tup []); v]) + | "errorCode" -> fun v k -> + (match Value.as_tup v with + | [code; _message] -> + k code + | _ -> assert false + ) + | "errorMessage" -> fun v k -> + (match Value.as_tup v with + | [_code; message] -> + k message + | _ -> assert false + ) | p when Lib.String.chop_prefix "num_conv" p <> None -> begin match String.split_on_char '_' p with | [_;_;s1;s2] -> diff --git a/src/as_values/value.ml b/src/as_values/value.ml index 8fc15121299..4a3ddb1bffe 100644 --- a/src/as_values/value.ml +++ b/src/as_values/value.ml @@ -290,7 +290,9 @@ and value = | Async of async | Mut of value ref -and async = {result : def; mutable waiters : value cont list} +and res = Ok of value | Error of value +and async = {result : res Lib.Promise.t ; mutable waiters : (value cont * value cont) list} + and def = value Lib.Promise.t and 'a cont = 'a -> unit @@ -434,16 +436,17 @@ and string_of_val d = function | Variant (l, Tup vs) -> sprintf "#%s%s" l (string_of_val d (Tup vs)) | Variant (l, v) -> sprintf "#%s(%s)" l (string_of_val d v) | Async {result; waiters = []} -> - sprintf "async %s" (string_of_def_nullary d result) + sprintf "async %s" (string_of_res d result) | Async {result; waiters} -> sprintf "async[%d] %s" - (List.length waiters) (string_of_def_nullary d result) + (List.length waiters) (string_of_res d result) | Mut r -> sprintf "%s" (string_of_val d !r) | v -> string_of_val_nullary d v -and string_of_def_nullary d def = - match Lib.Promise.value_opt def with - | Some v -> string_of_val_nullary d v +and string_of_res d result = + match Lib.Promise.value_opt result with + | Some (Error v)-> sprintf "Error %s" (string_of_val_nullary d v) + | Some (Ok v) -> string_of_val_nullary d v | None -> "_" and string_of_def d def = diff --git a/src/as_values/value.mli b/src/as_values/value.mli index 1daac9069ea..69787d9fc0c 100644 --- a/src/as_values/value.mli +++ b/src/as_values/value.mli @@ -103,7 +103,9 @@ and value = | Async of async | Mut of value ref -and async = {result : def; mutable waiters : value cont list} +and res = Ok of value | Error of value +and async = {result : res Lib.Promise.t ; mutable waiters : (value cont * value cont) list} + and def = value Lib.Promise.t and 'a cont = 'a -> unit diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 4c7b5b7205b..f632fbf0ae4 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -367,7 +367,6 @@ module E = struct env.end_of_static_memory := Int32.add ptr aligned; ptr - let add_mutable_static_bytes (env : t) data : int32 = let ptr = reserve_static_memory env (Int32.of_int (String.length data)) in env.static_memory := !(env.static_memory) @ [ (ptr, data) ]; @@ -2975,7 +2974,9 @@ module Dfinity = struct E.add_func_import env "debug" "print" [I32Type; I32Type] []; E.add_func_import env "msg" "arg_data_size" [I64Type] [I32Type]; E.add_func_import env "msg" "arg_data_copy" [I64Type; I32Type; I32Type; I32Type] []; - E.add_func_import env "msg" "reply" [I64Type; I32Type; I32Type] [] + E.add_func_import env "msg" "reply" [I64Type; I32Type; I32Type] []; + E.add_func_import env "msg" "reject" [I64Type; I32Type] []; + E.add_func_import env "msg" "error_code" [I64Type] [I32Type] | AncientMode -> E.add_func_import env "test" "print" [I32Type] []; E.add_func_import env "test" "show_i32" [I32Type] [I32Type]; @@ -3103,6 +3104,23 @@ module Dfinity = struct compile_unboxed_const fi ^^ system_call env "func" "externalize" + let error_code_CANISTER_REJECT = 4l (* Api's CANISTER_REJECT *) + + let reject env arg_instrs = + SR.unit, + get_api_nonce env ^^ + arg_instrs ^^ + G.i Drop ^^ (* TODO: + https://github.com/dfinity-lab/actorscript/issues/679 + don't drop but extract payload, once reject complies with spec *) + compile_unboxed_const error_code_CANISTER_REJECT ^^ + system_call env "msg" "reject" + + let error_code env = + SR.UnboxedWord32, + get_api_nonce env ^^ + system_call env "msg" "error_code" + end (* Dfinity *) module OrthogonalPersistence = struct @@ -4999,6 +5017,32 @@ open PatCode (* All the code above is independent of the IR *) open Ir +(* Compiling Error primitives *) +module Error = struct + + (* Opaque type `Error` is represented as concrete type `(ErrorCode,Text)` *) + + let compile_error env arg_instrs = + SR.UnboxedTuple 2, + Variant.inject env "error" Tuple.compile_unit ^^ + arg_instrs + + let compile_errorCode arg_instrs = + SR.Vanilla, + arg_instrs ^^ + Tuple.load_n (Int32.of_int 0) + + let compile_errorMessage arg_instrs = + SR.Vanilla, + arg_instrs ^^ + Tuple.load_n (Int32.of_int 1) + + let compile_make_error arg_instrs1 arg_instrs2 = + SR.UnboxedTuple 2, + arg_instrs1 ^^ + arg_instrs2 + +end module AllocHow = struct (* @@ -6112,10 +6156,29 @@ and compile_exp (env : E.t) ae exp = G.i (Binary (Wasm.Values.I64 I64Op.And)) ) - | OtherPrim "reply", [e] -> + (* Error related prims *) + | OtherPrim "error", [e] -> + Error.compile_error env (compile_exp_vanilla env ae e) + | OtherPrim "errorCode", [e] -> + Error.compile_errorCode (compile_exp_vanilla env ae e) + | OtherPrim "errorMessage", [e] -> + Error.compile_errorMessage (compile_exp_vanilla env ae e) + | OtherPrim "make_error", [e1; e2] -> + Error.compile_make_error (compile_exp_vanilla env ae e1) (compile_exp_vanilla env ae e2) + + | ICReplyPrim t, [e] -> + assert (E.mode env = ICMode); SR.unit, compile_exp_vanilla env ae e ^^ - Serialization.serialize env [e.note.note_typ] + Serialization.serialize env [t] + + | ICRejectPrim, [e] -> + assert (E.mode env = ICMode); + Dfinity.reject env (compile_exp_vanilla env ae e) + + | ICErrorCodePrim, [] -> + assert (E.mode env = ICMode); + Dfinity.error_code env (* Unknown prim *) | _ -> SR.Unreachable, todo_trap env "compile_exp" (Arrange_ir.exp exp) diff --git a/src/exes/asc.ml b/src/exes/asc.ml index cc18ebd30eb..856572ecac1 100644 --- a/src/exes/asc.ml +++ b/src/exes/asc.ml @@ -68,7 +68,7 @@ let argspec = Arg.align "-no-link", Arg.Clear link, " do not statically link-in runtime"; "-no-system-api", Arg.Unit (fun () -> compile_mode := Pipeline.WasmMode), - " do not import the any system API"; + " do not import any system API"; "-ancient-system-api", Arg.Unit (fun () -> compile_mode := Pipeline.AncientMode), " use the ancient DFINITY system API (dvm)"; diff --git a/src/ir_def/arrange_ir.ml b/src/ir_def/arrange_ir.ml index da60c1297fd..a7cf8fd3f66 100644 --- a/src/ir_def/arrange_ir.ml +++ b/src/ir_def/arrange_ir.ml @@ -42,6 +42,8 @@ let rec exp e = match e.it with "FuncE" $$ [Atom x; call_conv cc] @ List.map typ_bind tp @ args as_@ [ typ (Type.seq ts); exp e] | ActorE (i, ds, fs, t) -> "ActorE" $$ [id i] @ List.map dec ds @ fields fs @ [typ t] | NewObjE (s, fs, t) -> "NewObjE" $$ (Arrange_type.obj_sort s :: fields fs @ [typ t]) + | ThrowE e -> "ThrowE" $$ [exp e] + | TryE (e, cs) -> "TryE" $$ [exp e] @ List.map case cs and fields fs = List.fold_left (fun flds (f : field) -> (f.it.name $$ [ id f.it.var ]):: flds) [] fs @@ -57,7 +59,10 @@ and prim = function | RelPrim (t, ro) -> "RelPrim" $$ [typ t; Arrange_ops.relop ro] | ShowPrim t -> "ShowPrim" $$ [typ t] | NumConvPrim (t1, t2) -> "NumConvPrim" $$ [prim_ty t1; prim_ty t2] - | OtherPrim s -> Atom s + | OtherPrim s -> Atom s + | ICReplyPrim t -> "ICReplyPrim" $$ [typ t] + | ICRejectPrim -> Atom "ICRejectPrim" + | ICErrorCodePrim -> Atom "ICErrorCodePrim" and mut = function | Const -> Atom "Const" diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 06d8361811e..193a578ae65 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -342,6 +342,20 @@ let rec check_exp env (exp:Ir.exp) : unit = check_exp env exp1; typ exp1 <: ot; T.Prim T.Text <: t + | ICReplyPrim ot, [exp1] -> + check (not (env.flavor.has_async_typ)) "ICReplyPrim in async flavor"; + check (T.shared t) "ICReplyPrim is not defined for non-shared operand type"; + (* TODO: check against expected reply typ; note this may not be env.ret_tys. *) + check_exp env exp1; + typ exp1 <: ot; + T.unit <: t + | ICRejectPrim, [exp1] -> + check (not (env.flavor.has_async_typ)) "ICRejectPrim in async flavor"; + check_exp env exp1; + typ exp1 <: T.text; + T.unit <: t + | ICErrorCodePrim, [] -> + T.Prim (T.Int32) <: t | OtherPrim _, _ -> () | _ -> error env exp.at "PrimE with wrong number of arguments" @@ -451,6 +465,12 @@ let rec check_exp env (exp:Ir.exp) : unit = warn env exp.at "the cases in this switch do not cover all possible values"; *) check_cases env t1 t cases + | TryE (exp1, cases) -> + check env.flavor.has_await "try in non-await flavor"; + check env.async "misplaced try"; + check_exp env exp1; + typ exp1 <: t; + check_cases env T.catch t cases; | LoopE exp1 -> check_exp env exp1; typ exp1 <: T.unit; @@ -482,6 +502,12 @@ let rec check_exp env (exp:Ir.exp) : unit = typ exp1 <: t0; end; T.Non <: t (* vacuously true *) + | ThrowE exp1 -> + check env.flavor.has_await "throw in non-await flavor"; + check env.async "misplaced throw"; + check_exp env exp1; + typ exp1 <: T.throw; + T.Non <: t (* vacuously true *) | AsyncE exp1 -> check env.flavor.has_await "async expression in non-await flavor"; let t1 = typ exp1 in diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index 50cff75a573..f25425161f3 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -85,6 +85,9 @@ let as_seqP p = let primE prim es = let ty = match prim with | ShowPrim _ -> T.text + | ICReplyPrim _ -> T.unit + | ICRejectPrim -> T.unit + | ICErrorCodePrim -> T.Prim T.Int32 | _ -> assert false (* implement more as needed *) in let effs = List.map eff es in @@ -100,18 +103,36 @@ let asyncE typ e = note = { note_typ = T.Async typ; note_eff = eff e } } +let assertE e = + { it = AssertE e; + at = no_region; + note = { note_typ = T.unit; note_eff = eff e} + } + let awaitE typ e1 e2 = { it = PrimE (OtherPrim "@await", [e1; e2]); at = no_region; note = { note_typ = T.unit; note_eff = max_eff (eff e1) (eff e2) } } -let replyE e = - { it = PrimE (OtherPrim "reply", [e]); +let ic_replyE t e = + { it = PrimE (ICReplyPrim t, [e]); at = no_region; note = { note_typ = T.unit; note_eff = eff e } } +let ic_rejectE e = + { it = PrimE (ICRejectPrim, [e]); + at = no_region; + note = { note_typ = T.unit; note_eff = eff e } + } + +let ic_error_codeE () = + { it = PrimE (ICErrorCodePrim, []); + at = no_region; + note = { note_typ = T.Prim T.Int32; note_eff = T.Triv } + } + (* tuples *) @@ -152,7 +173,6 @@ let textE s = note = { note_typ = T.Prim T.Text; note_eff = T.Triv } } - let unitE = { it = TupE []; at = no_region; @@ -408,9 +428,14 @@ let nary_funcD f xs exp = let answerT = T.unit let contT typ = T.Func (T.Local, T.Returns, [], T.as_seq typ, []) -let cpsT typ = T.Func (T.Local, T.Returns, [], [contT typ], []) -let fresh_cont typ = fresh_var "cont" (contT typ) +let err_contT = T.Func (T.Local, T.Returns, [], [T.catch], []) + +let cpsT typ = T.Func (T.Local, T.Returns, [], [contT typ; err_contT], []) + +let fresh_cont typ = fresh_var "k" (contT typ) + +let fresh_err_cont () = fresh_var "r" (err_contT) (* Sequence expressions *) @@ -528,3 +553,4 @@ let forE pat exp1 exp2 = let unreachableE = (* Do we want UnreachableE in the AST *) loopE unitE + diff --git a/src/ir_def/construct.mli b/src/ir_def/construct.mli index 51508d2885b..ad3edf4b36b 100644 --- a/src/ir_def/construct.mli +++ b/src/ir_def/construct.mli @@ -41,8 +41,11 @@ val as_seqP : pat -> pat list val primE : Ir.prim -> exp list -> exp val asyncE : typ -> exp -> exp +val assertE : exp -> exp val awaitE : typ -> exp -> exp -> exp -val replyE : exp -> exp +val ic_replyE : typ -> exp -> exp +val ic_rejectE : exp -> exp +val ic_error_codeE : unit -> exp val projE : exp -> int -> exp val blockE : dec list -> exp -> exp val textE : string -> exp @@ -88,8 +91,10 @@ val nary_funcD : var -> var list -> exp -> dec val answerT : typ val contT : typ -> typ +val err_contT : typ val cpsT : typ -> typ val fresh_cont : typ -> var +val fresh_err_cont : unit -> var (* Sequence expressions *) diff --git a/src/ir_def/freevars.ml b/src/ir_def/freevars.ml index a99f6ffacfd..55d510158e2 100644 --- a/src/ir_def/freevars.ml +++ b/src/ir_def/freevars.ml @@ -85,6 +85,8 @@ let rec exp e : f = match e.it with | FuncE (x, cc, tp, as_, t, e) -> under_lambda (exp e /// args as_) | ActorE (i, ds, fs, _) -> close (decs ds +++ fields fs) // i | NewObjE (_, fs, _) -> fields fs + | ThrowE e -> exp e + | TryE (e, cs) -> exp e ++ cases cs and fields fs = unions (fun f -> id f.it.var) fs diff --git a/src/ir_def/ir.ml b/src/ir_def/ir.ml index a1f23791b13..a4e164f26a2 100644 --- a/src/ir_def/ir.ml +++ b/src/ir_def/ir.ml @@ -91,6 +91,8 @@ and exp' = string * Call_conv.t * typ_bind list * arg list * Type.typ list * exp | ActorE of id * dec list * field list * Type.typ (* actor *) | NewObjE of Type.obj_sort * field list * Type.typ (* make an object *) + | ThrowE of exp (* throw *) + | TryE of exp * case list (* try/catch *) and field = (field', Type.typ) Source.annotated_phrase and field' = {name : Type.lab; var : id} (* the var is by reference, not by value *) @@ -105,6 +107,10 @@ and prim = | ShowPrim of Type.typ (* debug show *) | NumConvPrim of Type.prim * Type.prim | OtherPrim of string (* Other primitive operation, no custom typing rule *) + | ICReplyPrim of Type.typ + | ICRejectPrim + | ICErrorCodePrim + (* Declarations *) diff --git a/src/ir_def/ir_effect.ml b/src/ir_def/ir_effect.ml index 981f76fa6c1..997ce09b6f8 100644 --- a/src/ir_def/ir_effect.ml +++ b/src/ir_def/ir_effect.ml @@ -64,7 +64,9 @@ let rec infer_effect_exp (exp: exp) : T.eff = max_eff e1 e2 | AsyncE exp1 -> T.Triv - | AwaitE exp1 -> + | ThrowE _ + | TryE _ + | AwaitE _ -> T.Await | DeclareE (_, _, exp1) -> effect_exp exp1 diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index b94e0860ebf..c07d77958b1 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -14,6 +14,7 @@ module CC = As_types.Call_conv type val_env = V.def V.Env.t type lab_env = V.value V.cont V.Env.t type ret_env = V.value V.cont option +type throw_env = V.value V.cont option type scope = val_env @@ -28,6 +29,7 @@ type env = vals : val_env; labs : lab_env; rets : ret_env; + throws : throw_env; async : bool } @@ -42,6 +44,7 @@ let env_of_scope flags flavor ve = vals = ve; labs = V.Env.empty; rets = None; + throws = None; async = false; } @@ -109,27 +112,43 @@ end (* Async auxiliary functions *) +(* Are these just duplicates of the corresponding functions in interpret.ml? If so, refactor *) + let make_async () : V.async = {V.result = Lib.Promise.make (); waiters = []} -let get_async async (k : V.value V.cont) = +let get_async async (k : V.value V.cont) (r : V.value V.cont) = match Lib.Promise.value_opt async.V.result with - | Some v -> k v - | None -> async.V.waiters <- k::async.V.waiters + | Some (V.Ok v) -> k v + | Some (V.Error v) -> r v + | None -> async.V.waiters <- (k,r)::async.V.waiters let set_async async v = - List.iter (fun k -> Scheduler.queue (fun () -> k v)) async.V.waiters; - Lib.Promise.fulfill async.V.result v; + List.iter (fun (k,_) -> Scheduler.queue (fun () -> k v)) async.V.waiters; + Lib.Promise.fulfill async.V.result (V.Ok v); + async.V.waiters <- [] + +let reject_async async v = + List.iter (fun (_,r) -> Scheduler.queue (fun () -> r v)) async.V.waiters; + Lib.Promise.fulfill async.V.result (V.Error v); async.V.waiters <- [] -let fulfill async v = +let reply async v = Scheduler.queue (fun () -> set_async async v) +let reject async v = + match v with + | V.Tup [ _code; message ] -> + (* mask the error code before rejecting *) + Scheduler.queue + (fun () -> reject_async async (V.Tup [V.Variant("error", V.unit); message])) + | _ -> assert false -let async env at (f: (V.value V.cont) -> unit) (k : V.value V.cont) = +let async env at (f: (V.value V.cont) -> (V.value V.cont) -> unit) (k : V.value V.cont) = let async = make_async () in (* let k' = fun v1 -> set_async async v1 in *) - let k' = fun v1 -> fulfill async v1 in + let k' = reply async in + let r = reject async in if env.flags.trace then trace "-> async %s" (string_of_region at); Scheduler.queue (fun () -> if env.flags.trace then trace "<- async %s" (string_of_region at); @@ -138,6 +157,7 @@ let async env at (f: (V.value V.cont) -> unit) (k : V.value V.cont) = if env.flags.trace then trace "<= %s" (string_of_val env v); decr trace_depth; k' v) + r ); k (V.Async async) @@ -184,7 +204,7 @@ let make_async_message env id v = Value.async_func call_conv.n_args (fun v k -> let async = make_async () in actor_msg env id f v (fun v_async -> - get_async (V.as_async v_async) (fun v_r -> set_async async v_r) + get_async (V.as_async v_async) (set_async async) (reject_async async) ); k (V.Async async) ) @@ -204,26 +224,34 @@ let extended_prim env s typ at = | "@async" -> assert (not env.flavor.has_await && env.flavor.has_async_typ); (fun v k -> - let (_, f) = V.as_func v in - match typ with - | T.Func(_, _, _, [T.Func(_, _, _, [f_dom], _)], _) -> - let call_conv = CC.call_conv_of_typ f_dom in - async env at - (fun k' -> - let k' = Value.Func (call_conv, fun v _ -> k' v) in - f k' V.as_unit - ) k - | _ -> assert false + let (_, f) = V.as_func v in + match typ with + | T.Func(_, _, _, [T.Func(_, _, _, [f_dom], _);T.Func(_, _, _, [r_dom], _)], _) -> + let call_conv_f = CC.call_conv_of_typ f_dom in + let call_conv_r = CC.call_conv_of_typ r_dom in + async env at + (fun k' r -> + let vk' = Value.Func (call_conv_f, fun v _ -> k' v) in + let vr = Value.Func (call_conv_r, fun v _ -> r v) in + f (V.Tup [vk';vr]) V.as_unit + ) + k + | _ -> assert false ) | "@await" -> assert (not env.flavor.has_await && env.flavor.has_async_typ); - fun v k -> - (match V.as_tup v with - | [async; w] -> - let (_, f) = V.as_func w in - await env at (V.as_async async) (fun v -> f v k) - | _ -> assert false - ) + (fun v k -> + match V.as_tup v with + | [async; v1] -> + (match V.as_tup v1 with + | [vf; vr] -> + let (_, f) = V.as_func vf in + let (_, r) = V.as_func vr in + await env at (V.as_async async) + (fun v -> f v k) + (fun e -> r e k) (* TBR *) + | _ -> assert false) + | _ -> assert false) | _ -> Prim.prim s @@ -390,6 +418,10 @@ and interpret_exp_mut env exp (k : V.value V.cont) = interpret_exp env exp1 (fun v1 -> interpret_cases env cases exp.at v1 k ) + | TryE (exp1, cases) -> + let k' = fun v1 -> interpret_catches env cases exp.at v1 k in + let env' = { env with throws = Some k' } in + interpret_exp env' exp1 k | LoopE exp1 -> interpret_exp env exp1 (fun v -> V.as_unit v; interpret_exp env exp k) | LabelE (id, _typ, exp1) -> @@ -399,19 +431,21 @@ and interpret_exp_mut env exp (k : V.value V.cont) = interpret_exp env exp1 (find id env.labs) | RetE exp1 -> interpret_exp env exp1 (Lib.Option.value env.rets) + | ThrowE exp1 -> + interpret_exp env exp1 (Lib.Option.value env.throws) | AsyncE exp1 -> assert env.flavor.has_await; async env exp.at - (fun k' -> - let env' = {env with labs = V.Env.empty; rets = Some k'; async = true} + (fun k' r -> + let env' = {env with labs = V.Env.empty; rets = Some k'; throws = Some r; async = true} in interpret_exp env' exp1 k') k | AwaitE exp1 -> assert env.flavor.has_await; interpret_exp env exp1 - (fun v1 -> await env exp.at (V.as_async v1) k) + (fun v1 -> await env exp.at (V.as_async v1) k (Lib.Option.value env.throws)) | AssertE exp1 -> interpret_exp env exp1 (fun v -> if V.as_bool v @@ -477,6 +511,17 @@ and interpret_cases env cases at v (k : V.value V.cont) = | Some ve -> interpret_exp (adjoin_vals env ve) exp k | None -> interpret_cases env cases' at v k +(* Catches *) + +and interpret_catches env cases at v (k : V.value V.cont) = + match cases with + | [] -> + Lib.Option.value env.throws v (* re-throw v *) + | {it = {pat; exp}; at; _}::cases' -> + match match_pat pat v with + | Some ve -> interpret_exp (adjoin_vals env ve) exp k + | None -> interpret_catches env cases' at v k + (* Argument lists *) and match_arg a v : val_env = V.Env.singleton a.it (Lib.Promise.make_fulfilled v) diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index 6d4e8824dce..3f0dc730c7a 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -13,6 +13,7 @@ open Construct (* lower the async type itself - adds a final reply argument to every awaitable shared function, replace the result by unit + - declares a trapping reject callback in every awaitable shared function - transforms types, introductions and eliminations of awaitable shared functions only, leaving non-awaitable shared functions unchanged. - ensures every call to an awaitable shared function that takes a tuple has @@ -27,9 +28,11 @@ type platform = module Transform(Platform : sig val platform : platform end) = struct + let platform = Platform.platform + module ConRenaming = E.Make(struct type t = T.con let compare = Con.compare end) - (* the state *) + (* the state *) (* maps constructors to new constructors (name name, new stamp, new kind) it is initialized with the type constructors defined outside here, which are @@ -42,12 +45,10 @@ module Transform(Platform : sig val platform : platform end) = struct let con_renaming = ref ConRenaming.empty - (* Lowering options, specific to V1 or V2 *) - - let add_reply_parameter, add_reply_argument = - match Platform.platform with - | V1 -> (true, true) - | V2 -> (false, true) + let add_reply_parameter, add_reject_parameter, add_reply_argument, add_reject_argument = + match platform with + | V1 -> (true, false, true, false) + | V2 -> (false, false, true, true) (* Helper for selective code generation based on predicated lazy expressions *) let rec select bls = @@ -58,22 +59,53 @@ module Transform(Platform : sig val platform : platform end) = struct | (false, _)::bls' -> select bls' - (* Explicit invocation of reply and call System API functions; + + (* Explicit invocation of reply, reject and call System API functions; implemented (as far as possible) for V1; TBC for V2 *) - (* NB: The type annotations on the v needs to match the IDL type of the function *) - let sys_replyE v = - match Platform.platform with + let sys_replyE t v = + match platform with | V1 -> assert false (* never required in V1, `reply` is by calling continuation*) - | V2 -> replyE v + | V2 -> ic_replyE t v - let sys_callE v1 typs vs reply = - match Platform.platform with + let sys_rejectE e = + match platform with + | V1 -> assertE (boolE false) (* used in V1 to cause traps on non-local throws *) + | V2 -> ic_rejectE e + + let sys_callE v1 typs vs reply reject = + match platform with | V1 -> - assert add_reply_argument; + assert (add_reply_argument && not add_reject_argument); callE v1 typs (seqE (vs @ [reply])) - | V2 -> assert false (* NYI, needs a dedicated prim, separating args vs from reply *) + | V2 -> failwith "NYI" (* TODO: call dedicated prim, separating args vs from reply & reject *) + + let sys_error_codeE () = + match platform with + | V1 -> { it = TagE ("error", tupE []); + at = no_region; + note = { + note_typ = T.Variant (T.catchErrorCodes); + note_eff = T.Triv } + } + | V2 -> callE + (idE "@int32ToErrorCode" + (T.Func(T.Local,T.Returns,[],[T.Prim T.Int32],[T.Variant T.catchErrorCodes]))) + [] + (ic_error_codeE()) + + let errorMessageE e = + { it = PrimE (OtherPrim "errorMessage", [e]); + at = no_region; + note = { note_typ = T.text; note_eff = eff e } + } + + let make_errorE e_code e_msg = + { it = PrimE (OtherPrim "make_error", [e_code; e_msg]); + at = no_region; + note = { note_typ = T.Prim T.Error; note_eff = max (eff e_code) (eff e_msg) } + } (* End of configuration *) @@ -83,12 +115,16 @@ module Transform(Platform : sig val platform : platform end) = struct let replyT as_seq typ = T.Func(T.Shared, T.Returns, [], as_seq typ, []) + let rejectT = T.Func(T.Shared, T.Returns, [], [T.text], []) + let fulfillT as_seq typ = T.Func(T.Local, T.Returns, [], as_seq typ, []) + let failT = T.Func(T.Local, T.Returns, [], [T.catch], []) + let t_async as_seq t = - T.Func (T.Local, T.Returns, [], [fulfillT as_seq t], []) + T.Func (T.Local, T.Returns, [], [fulfillT as_seq t; failT], []) - let new_async_ret as_seq t = [t_async as_seq t; fulfillT as_seq t] + let new_async_ret as_seq t = [t_async as_seq t; fulfillT as_seq t; failT] let new_asyncT = T.Func ( @@ -106,21 +142,23 @@ module Transform(Platform : sig val platform : platform end) = struct let call_new_async = callE new_asyncE [t1] (tupE []) in let async = fresh_var "async" (typ (projE call_new_async 0)) in let fulfill = fresh_var "fulfill" (typ (projE call_new_async 1)) in - (async, fulfill), call_new_async + let fail = fresh_var "fail" (typ (projE call_new_async 2)) in + (async, fulfill, fail), call_new_async let new_nary_async_reply t1 = - let (unary_async, unary_fulfill), call_new_async = new_async t1 in + let (unary_async, unary_fulfill, fail), call_new_async = new_async t1 in let v' = fresh_var "v" t1 in let ts1 = T.as_seq t1 in (* construct the n-ary async value, coercing the continuation, if necessary *) let nary_async = let k' = fresh_var "k" (contT t1) in + let r' = fresh_var "r" err_contT in match ts1 with | [t] -> unary_async | ts -> let seq_of_v' = tupE (List.mapi (fun i _ -> projE v' i) ts) in - [k'] -->* (unary_async -*- ([v'] -->* (k' -*- seq_of_v'))) + [k';r'] -->* (unary_async -*- (tupE[([v'] -->* (k' -*- seq_of_v'));r'])) in (* construct the n-ary reply message that sends a sequence of values to fulfill the async *) let nary_reply = @@ -135,15 +173,18 @@ module Transform(Platform : sig val platform : platform end) = struct in vs -@>* (unary_fulfill -*- seq_of_vs) in - - let async, reply = + let nary_reject = + let v = fresh_var "msg" T.text in + [v] -@>* (fail -*- (make_errorE (sys_error_codeE()) v)) + in + let async,reply,reject = fresh_var "async" (typ nary_async), - fresh_var "reply" (typ nary_reply) + fresh_var "reply" (typ nary_reply), + fresh_var "reject" (typ nary_reject) in - (async, reply), - blockE [letP (tupP [varP unary_async; varP unary_fulfill]) call_new_async] - (tupE [nary_async; nary_reply]) - + (async, reply, reject), + blockE [letP (tupP [varP unary_async; varP unary_fulfill; varP fail]) call_new_async] + (tupE [nary_async; nary_reply; nary_reject]) let letEta e scope = match e.it with @@ -198,8 +239,8 @@ module Transform(Platform : sig val platform : platform end) = struct Func (s, T.Returns, List.map t_bind tbs, extendTup (List.map t_typ t1) (select - [ add_reply_parameter, lazy (replyT nary (t_typ t2)) - ]), + [ add_reply_parameter, lazy (replyT nary (t_typ t2)); + add_reject_parameter, lazy rejectT ]), []) | _ -> assert false end @@ -244,7 +285,8 @@ module Transform(Platform : sig val platform : platform end) = struct | RelPrim (ot, op) -> RelPrim (t_typ ot, op) | ShowPrim ot -> ShowPrim (t_typ ot) | NumConvPrim (t1,t2) -> NumConvPrim (t1,t2) - | OtherPrim s -> OtherPrim s + | ICReplyPrim t -> ICReplyPrim(t_typ t) + | p -> p and t_field {lab; typ} = { lab; typ = t_typ typ } @@ -284,19 +326,22 @@ module Transform(Platform : sig val platform : platform end) = struct let t1, contT = match typ exp2 with | Func(_,_, [], - [Func(_, _, [], ts1, []) as contT], + [Func(_, _, [], ts1, []) as contT; _], []) -> (* TBR, why isn't this []? *) (t_typ (T.seq ts1),t_typ contT) | t -> assert false in let k = fresh_var "k" contT in let v1 = fresh_var "v" t1 in + let r = fresh_var "r" err_contT in + let e = fresh_var "e" T.catch in let post = fresh_var "post" (T.Func(T.Shared, T.Returns, [], [], [])) in let u = fresh_var "u" T.unit in - let ((nary_async, nary_reply), def) = new_nary_async_reply t1 in - (blockE [letP (tupP [varP nary_async; varP nary_reply]) def; + let ((nary_async, nary_reply, reject), def) = new_nary_async_reply t1 in + (blockE [letP (tupP [varP nary_async; varP nary_reply; varP reject]) def; funcD k v1 (nary_reply -*- v1); - funcD post u (t_exp exp2 -*- k); - expD (post -*- tupE [])] + nary_funcD r [e] (reject -*- (errorMessageE e)); + funcD post u (t_exp exp2 -*- (tupE [k;r])); + expD (post -*- tupE[])] nary_async ).it | CallE (cc, exp1, typs, exp2) when isAwaitableFunc exp1 -> @@ -309,12 +354,12 @@ module Transform(Platform : sig val platform : platform end) = struct let exp1' = t_exp exp1 in let exp2' = t_exp exp2 in let typs = List.map t_typ typs in - let ((nary_async, nary_reply), def) = new_nary_async_reply t2 in + let ((nary_async, nary_reply, reject), def) = new_nary_async_reply t2 in let _ = letEta in - (blockE ( letP (tupP [varP nary_async; varP nary_reply]) def :: + (blockE ( letP (tupP [varP nary_async; varP nary_reply; varP reject]) def :: letEta exp1' (fun v1 -> letSeq ts1 exp2' (fun vs -> - [ expD (sys_callE v1 typs vs nary_reply) ] + [ expD (sys_callE v1 typs vs nary_reply reject) ] ) ) ) @@ -345,7 +390,9 @@ module Transform(Platform : sig val platform : platform end) = struct | RetE exp1 -> RetE (t_exp exp1) | AsyncE _ - | AwaitE _ -> assert false + | AwaitE _ + | TryE _ + | ThrowE _ -> assert false | AssertE exp1 -> AssertE (t_exp exp1) | DeclareE (id, typ, exp1) -> @@ -366,10 +413,11 @@ module Transform(Platform : sig val platform : platform end) = struct | T.Async res_typ -> let res_typ = t_typ res_typ in let reply_typ = replyT nary res_typ in - let r = fresh_var "r" reply_typ in + let reply = fresh_var "reply" reply_typ in + let reject = fresh_var "reject" rejectT in let args' = t_args args @ - (select [ add_reply_parameter, lazy (arg_of_exp r); - ]) + (select [ add_reply_parameter, lazy (arg_of_exp reply); + add_reject_parameter, lazy (arg_of_exp reject)]) in let typbinds' = t_typ_binds typbinds in let exp' = @@ -377,10 +425,18 @@ module Transform(Platform : sig val platform : platform end) = struct | PrimE (OtherPrim "@async", [cps]) -> let v = fresh_var "v" res_typ in let k = if add_reply_parameter then - (v --> (r -*- v)) (* wrap shared function in local function *) + (* wrap shared reply function in local function *) + (v --> (reply -*- v)) + else + (v --> (sys_replyE res_typ v)) in + let e = fresh_var "e" T.catch in + let r = if add_reject_parameter then + (* wrap shared reject function in local function *) + ([e] -->* (reject -*- (errorMessageE e))) else - (v --> (sys_replyE v)) in - t_exp cps -*- k + ([e] -->* (sys_rejectE (errorMessageE e))) + in + (t_exp cps) -*- tupE [k;r] | _ -> assert false in let cc' = Call_conv.message_cc (List.length args') in diff --git a/src/ir_passes/await.ml b/src/ir_passes/await.ml index d3427e74b51..98e1e082c1e 100644 --- a/src/ir_passes/await.ml +++ b/src/ir_passes/await.ml @@ -32,7 +32,8 @@ let letcont k scope = (scope k') (* The empty identifier names the implicit return label *) -let id_ret = "" + +type label = Return | Throw | Named of string let ( -@- ) k exp2 = match k with @@ -47,7 +48,7 @@ let ( -@- ) k exp2 = (* Label environments *) -module LabelEnv = Env.Make(String) +module LabelEnv = Env.Make(struct type t = label let compare = compare end) module PatEnv = Env.Make(String) @@ -99,29 +100,37 @@ and t_exp' context exp' = | LoopE exp1 -> LoopE (t_exp context exp1) | LabelE (id, _typ, exp1) -> - let context' = LabelEnv.add id Label context in + let context' = LabelEnv.add (Named id) Label context in LabelE (id, _typ, t_exp context' exp1) | BreakE (id, exp1) -> begin - match LabelEnv.find_opt id context with + match LabelEnv.find_opt (Named id) context with | Some (Cont k) -> RetE (k -@- (t_exp context exp1)) | Some Label -> BreakE (id, t_exp context exp1) | None -> assert false end | RetE exp1 -> begin - match LabelEnv.find_opt id_ret context with + match LabelEnv.find_opt Return context with | Some (Cont k) -> RetE (k -@- (t_exp context exp1)) | Some Label -> RetE (t_exp context exp1) | None -> assert false end | AsyncE exp1 -> let exp1 = R.exp R.Renaming.empty exp1 in (* rename all bound vars apart *) - (* add the implicit return label *) + (* add the implicit return/throw label *) let k_ret = fresh_cont (typ exp1) in - let context' = LabelEnv.add id_ret (Cont (ContVar k_ret)) LabelEnv.empty in - (asyncE (typ exp1) (k_ret --> (c_exp context' exp1 (ContVar k_ret)))).it - | AwaitE _ -> assert false (* an await never has effect T.Triv *) + let k_fail = fresh_err_cont () in + let context' = + LabelEnv.add Return (Cont (ContVar k_ret)) + (LabelEnv.add Throw (Cont (ContVar k_fail)) LabelEnv.empty) + in + (* TODO: bind k_fail *) + (asyncE (typ exp1) ([k_ret; k_fail] -->* + c_exp context' exp1 (ContVar k_ret))).it + | TryE _ + | ThrowE _ + | AwaitE _ -> assert false (* these never have effect T.Triv *) | AssertE exp1 -> AssertE (t_exp context exp1) | DeclareE (id, typ, exp1) -> @@ -129,7 +138,7 @@ and t_exp' context exp' = | DefineE (id, mut ,exp1) -> DefineE (id, mut, t_exp context exp1) | FuncE (x, s, typbinds, pat, typ, exp) -> - let context' = LabelEnv.add id_ret Label LabelEnv.empty in + let context' = LabelEnv.add Return Label LabelEnv.empty in FuncE (x, s, typbinds, pat, typ,t_exp context' exp) | ActorE (id, ds, ids, t) -> ActorE (id, t_decs context ds, ids, t) @@ -205,7 +214,7 @@ and c_if context k e1 e2 e3 = | T.Triv -> ifE (t_exp context e1) e2 e3 answerT | T.Await -> - c_exp context e1 (meta (typ e1) (fun v1 -> ifE v1 e2 e3 answerT)) + c_exp context e1 (meta (typ e1) (fun v1 -> ifE v1 e2 e3 answerT)) ) and c_loop context k e1 = @@ -279,16 +288,50 @@ and c_exp' context exp k = (meta (typ exp1) (fun v1 -> {exp with it = SwitchE(v1,cases')})) end) + | TryE (exp1, cases) -> + (* TODO: do we need to reify f? *) + let f = match LabelEnv.find Throw context with Cont f -> f | _ -> assert false in + letcont f (fun f -> + letcont k (fun k -> + let cases' = List.map + (fun {it = {pat;exp}; at; note} -> + let exp' = match eff exp with + | T.Triv -> k -*- (t_exp context exp) + | T.Await -> c_exp context exp (ContVar k) + in + {it = {pat;exp = exp' }; at; note}) + cases + in + let error = fresh_var "v" T.catch in + let cases' = cases' @ [{it = {pat = varP error; exp = f -*- error}; + at = no_region; + note = ()}] in + let throw = fresh_err_cont () in + let e = fresh_var "e" T.catch in + let context' = LabelEnv.add Throw (Cont (ContVar throw)) context in + begin + match eff exp1 with + | T.Triv -> + k -*- (t_exp context exp1) + | T.Await -> + blockE + [funcD throw e { it = SwitchE (e, cases'); + at = exp.at; + note = {note_eff = T.Await; (* shouldn't matter *) + note_typ = T.unit} + }] + (c_exp context' exp1 (ContVar k)) + end)) | LoopE exp1 -> c_loop context k exp1 | LabelE (id, _typ, exp1) -> letcont k (fun k -> - let context' = LabelEnv.add id (Cont (ContVar k)) context in + let context' = LabelEnv.add (Named id) (Cont (ContVar k)) context in c_exp context' exp1 (ContVar k)) (* TODO optimize me, if possible *) | BreakE (id, exp1) -> begin - match LabelEnv.find_opt id context with + match LabelEnv.find_opt (Named id) context with | Some (Cont k') -> c_exp context exp1 k' | Some Label -> assert false @@ -296,27 +339,48 @@ and c_exp' context exp k = end | RetE exp1 -> begin - match LabelEnv.find_opt id_ret context with + match LabelEnv.find_opt Return context with | Some (Cont k') -> c_exp context exp1 k' | Some Label -> assert false | None -> assert false end + | ThrowE exp1 -> + begin + match LabelEnv.find_opt Throw context with + | Some (Cont k') -> c_exp context exp1 k' + | Some Label + | None -> assert false + end | AsyncE exp1 -> (* add the implicit return label *) - let k_ret = fresh_cont (typ exp1) in - let context' = LabelEnv.add id_ret (Cont (ContVar k_ret)) LabelEnv.empty in - k -@- (asyncE (typ exp1) (k_ret --> (c_exp context' exp1 (ContVar k_ret)))) + let k_ret = fresh_cont (typ exp1) in + let k_fail = fresh_err_cont () in + let context' = + LabelEnv.add Return (Cont (ContVar k_ret)) + (LabelEnv.add Throw (Cont (ContVar k_fail)) LabelEnv.empty) + in + k -@- (asyncE (typ exp1) ([k_ret; k_fail] -->* + (c_exp context' exp1 (ContVar k_ret)))) | AwaitE exp1 -> + let r = match LabelEnv.find_opt Throw context with + | Some (Cont r) -> r + | Some Label + | None -> assert false + in + letcont r + (fun r -> letcont k (fun k -> + let kr = tupE [k;r] in match eff exp1 with | T.Triv -> - awaitE (typ exp) (t_exp context exp1) k + awaitE (typ exp) (t_exp context exp1) kr | T.Await -> c_exp context exp1 - (meta (typ exp1) (fun v1 -> (awaitE (typ exp) v1 k))) + (meta (typ exp1) (fun v1 -> (awaitE (typ exp) v1 kr))) ) + ) | AssertE exp1 -> unary context k (fun v1 -> e (AssertE v1)) exp1 | DeclareE (id, typ, exp1) -> diff --git a/src/ir_passes/rename.ml b/src/ir_passes/rename.ml index 7e0f41192f1..cb08fb99bb1 100644 --- a/src/ir_passes/rename.ml +++ b/src/ir_passes/rename.ml @@ -68,6 +68,8 @@ and exp' rho e = match e with let e' = exp rho' e in FuncE (x, s, tp, p', ts, e') | NewObjE (s, fs, t) -> NewObjE (s, fields rho fs, t) + | ThrowE e -> ThrowE (exp rho e) + | TryE (e, cs) -> TryE (exp rho e, cases rho cs) and exps rho es = List.map (exp rho) es diff --git a/src/ir_passes/show.ml b/src/ir_passes/show.ml index 9cce4ba5fa7..c3e5def44df 100644 --- a/src/ir_passes/show.ml +++ b/src/ir_passes/show.ml @@ -99,12 +99,21 @@ and t_exp' env = function | IfE (exp1, exp2, exp3) -> IfE (t_exp env exp1, t_exp env exp2, t_exp env exp3) | SwitchE (exp1, cases) -> - let cases' = List.map - (fun {it = {pat;exp}; at; note} -> - {it = {pat = pat; exp = t_exp env exp}; at; note}) - cases + let cases' = + List.map + (fun {it = {pat;exp}; at; note} -> + {it = {pat = pat; exp = t_exp env exp}; at; note}) + cases in SwitchE (t_exp env exp1, cases') + | TryE (exp1, cases) -> + let cases' = + List.map + (fun {it = {pat;exp}; at; note} -> + {it = {pat = pat; exp = t_exp env exp}; at; note}) + cases + in + TryE (t_exp env exp1, cases') | LoopE exp1 -> LoopE (t_exp env exp1) | LabelE (id, typ, exp1) -> @@ -113,6 +122,8 @@ and t_exp' env = function BreakE (id, t_exp env exp1) | RetE exp1 -> RetE (t_exp env exp1) + | ThrowE exp1 -> + ThrowE (t_exp env exp1) | AsyncE e -> AsyncE (t_exp env e) | AwaitE e -> AwaitE (t_exp env e) | AssertE exp1 -> diff --git a/src/ir_passes/tailcall.ml b/src/ir_passes/tailcall.ml index e28953fbc77..cf786d4ac90 100644 --- a/src/ir_passes/tailcall.ml +++ b/src/ir_passes/tailcall.ml @@ -115,12 +115,14 @@ and exp' env e : exp' = match e.it with | BlockE (ds, e) -> BlockE (block env ds e) | IfE (e1, e2, e3) -> IfE (exp env e1, tailexp env e2, tailexp env e3) | SwitchE (e, cs) -> SwitchE (exp env e, cases env cs) + | TryE (e, cs) -> TryE (exp env e, cases env cs) (* TBR *) | LoopE e1 -> LoopE (exp env e1) | LabelE (i, t, e) -> let env1 = bind env i None in LabelE(i, t, exp env1 e) | BreakE (i, e) -> BreakE(i,exp env e) | RetE e -> RetE (tailexp { env with tail_pos = true } e) (* NB:^ e is always in tailposition, regardless of fst env *) + | ThrowE e -> ThrowE (exp env e) (* TODO: make me a tail call *) | AsyncE e -> AsyncE (exp { tail_pos = true; info = None } e) | AwaitE e -> AwaitE (exp env e) | AssertE e -> AssertE (exp env e) diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index e3b4ffacdae..c3c56b90818 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -125,6 +125,7 @@ and exp' at note = function | S.OrE (e1, e2) -> I.IfE (exp e1, trueE, exp e2) | S.IfE (e1, e2, e3) -> I.IfE (exp e1, exp e2, exp e3) | S.SwitchE (e1, cs) -> I.SwitchE (exp e1, cases cs) + | S.TryE (e1, cs) -> I.TryE (exp e1, cases cs) | S.WhileE (e1, e2) -> (whileE (exp e1) (exp e2)).it | S.LoopE (e1, None) -> I.LoopE (exp e1) | S.LoopE (e1, Some e2) -> (loopWhileE (exp e1) (exp e2)).it @@ -132,6 +133,7 @@ and exp' at note = function | S.LabelE (l, t, e) -> I.LabelE (l.it, t.Source.note, exp e) | S.BreakE (l, e) -> I.BreakE (l.it, exp e) | S.RetE e -> I.RetE (exp e) + | S.ThrowE e -> I.ThrowE (exp e) | S.AsyncE e -> I.AsyncE (exp e) | S.AwaitE e -> I.AwaitE (exp e) | S.AssertE e -> I.AssertE (exp e) diff --git a/src/pipeline/resolve_import.ml b/src/pipeline/resolve_import.ml index 70e3fb096b8..76a4202d545 100644 --- a/src/pipeline/resolve_import.ml +++ b/src/pipeline/resolve_import.ml @@ -156,6 +156,7 @@ let rec | AnnotE (exp1, _) | AsyncE exp1 | AwaitE exp1 + | ThrowE exp1 | LoopE (exp1, None) -> exp env exp1 | BinE (_, exp1, _, exp2) @@ -180,6 +181,7 @@ let rec exp env exp1; exp env exp2; exp env exp3 + | TryE (exp1, cases) | SwitchE (exp1, cases) -> exp env exp1; List.iter (fun c -> exp env c.it.exp) cases diff --git a/src/prelude/prelude.ml b/src/prelude/prelude.ml index e942f142017..393e094ac58 100644 --- a/src/prelude/prelude.ml +++ b/src/prelude/prelude.ml @@ -21,6 +21,7 @@ type Word64 = prim "Word64"; type Float = prim "Float"; type Char = prim "Char"; type Text = prim "Text"; +type Error = prim "Error"; type Iter = {next : () -> ?T_}; @@ -330,36 +331,76 @@ func Array_tabulate(len : Nat, gen : Nat -> T) : [T] { (prim "Array.tabulate" : (Nat, Nat -> T) -> [T])(len, gen) }; +// these will change +type ErrorCode = {#error; #system}; /* TBC */ + +func error(message : Text) : Error = + (prim "error" : Text -> Error)(message); + +func errorCode(e : Error) : ErrorCode = + (prim "errorCode" : Error -> ErrorCode)(e); + +func errorMessage(e : Error) : Text = + (prim "errorMessage" : Error -> Text)(e); + +func @int32ToErrorCode(i : Int32) : ErrorCode { + switch (int32ToInt(i)) { /*TODO: conversion only to avoid bug in asc-js, TBR */ + case 4 /* CANISTER_REJECT */ #error; + case _ #system; /* TBC */ + } +}; + type Cont = T -> () ; -type Async = Cont -> (); +type Async = (Cont,Cont) -> (); -func @new_async() : (Async, Cont) { - let empty = func(t : T) {}; - var result : ?T = null; - var ks : T -> () = empty; +type Result = {#ok : T; #error : Error}; + +func @new_async() : (Async, Cont, Cont) { + let k_null = func(_ : T) {}; + let r_null = func(_ : Error) {}; + var result : ?(Result) = null; + var ks : Cont = k_null; + var rs : Cont = r_null; func fulfill(t : T) { switch result { case null { - result := ?t; + result := ?(#ok t); let ks_ = ks; - ks := empty; + ks := k_null; + rs := r_null; ks_(t); }; - case (?t) { assert false }; + case (? _) { assert false }; + }; + }; + + func fail(e : Error) { + switch result { + case null { + result := ?(#error e); + let rs_ = rs; + ks := k_null; + rs := r_null; + rs_(e); + }; + case (? _) { assert false }; }; }; - func enqueue(k : Cont) { + func enqueue(k : Cont, r : Cont) { switch result { case null { let ks_ = ks; ks := (func(t : T) { ks_(t); k(t) }); + let rs_ = rs; + rs := (func(e : Error) { rs_(e); r(e) }); }; - case (?t) { k(t) }; + case (? (#ok t)) { k(t) }; + case (? (#error e)) { r(e) }; }; }; - (enqueue, fulfill) + (enqueue, fulfill, fail) }; |} diff --git a/src/profiler/profiler.ml b/src/profiler/profiler.ml index 5a26fccd973..b0dececb521 100644 --- a/src/profiler/profiler.ml +++ b/src/profiler/profiler.ml @@ -14,7 +14,8 @@ let process_prog_result result = match result with Some(Value.Async a,_) -> begin match Lib.Promise.value_opt a.Value.result with - | Some v -> Counters.dump counters (Value.as_obj v) + | Some (Value.Ok v) -> Counters.dump counters (Value.as_obj v) + | Some _ | None -> () end | _ -> () diff --git a/test/as-idl/ok/pa_cars.did.ok b/test/as-idl/ok/pa_cars.did.ok index ec810918233..7c1167a417a 100644 --- a/test/as-idl/ok/pa_cars.did.ok +++ b/test/as-idl/ok/pa_cars.did.ok @@ -1,9 +1,9 @@ type User = record {name : Text}; type TimeSpan = record {end : Int; start : Int}; type Text = text; -type Result = opt record {reservationId : Text}; +type Result_1 = opt record {reservationId : Text}; type PACars = service { -verifyCarInformation : (User, Car) -> (opt func (Location, TimeSpan) -> (Result)); +verifyCarInformation : (User, Car) -> (opt func (Location, TimeSpan) -> (Result_1)); }; type Nat = nat; type Location = record {lat : Float; long : Float}; diff --git a/test/as-idl/ok/result.did.ok b/test/as-idl/ok/result.did.ok index 7ce3b6a1727..ecb6c2807a1 100644 --- a/test/as-idl/ok/result.did.ok +++ b/test/as-idl/ok/result.did.ok @@ -1,11 +1,11 @@ type Text = text; -type Result_2 = variant {err : Text; ok : Nat}; -type Result_1 = variant {err : Text; ok : record {}}; +type Result_1_2 = variant {err : Text; ok : Nat}; +type Result_1_1 = variant {err : Text; ok : record {}}; type Result3_1 = variant {err : Result2_1; ok : record {}}; -type Result2_2 = variant {err : Result_2; ok : Nat}; -type Result2_1 = variant {err : Result_1; ok : record {}}; +type Result2_2 = variant {err : Result_1_2; ok : Nat}; +type Result2_1 = variant {err : Result_1_1; ok : record {}}; type Nat = nat; service anon_result { -f : (opt Nat) -> (Result_2); +f : (opt Nat) -> (Result_1_2); g : (Result3_1) -> (Result2_2); } diff --git a/test/fail/ok/modexp5.tc.ok b/test/fail/ok/modexp5.tc.ok index 35aaf210788..ec7093950fd 100644 --- a/test/fail/ok/modexp5.tc.ok +++ b/test/fail/ok/modexp5.tc.ok @@ -1 +1 @@ -modexp5.as:6.20-6.30: type error, type definition U = T/15 references type parameter(s) T/15 from an outer scope +modexp5.as:6.20-6.30: type error, type definition U = T/17 references type parameter(s) T/17 from an outer scope diff --git a/test/run-dfinity/local-throw.as b/test/run-dfinity/local-throw.as new file mode 100644 index 00000000000..d49a7c37d96 --- /dev/null +++ b/test/run-dfinity/local-throw.as @@ -0,0 +1,67 @@ +// This file only exercises local throws that don't cross function boundaries. +// In principle, it should run on all targets. + +shared func t2() : async () { + try { + throw error("t2"); + assert(false); + } catch e { + switch (errorCode(e),errorMessage(e)) { + case (#error, "t2") { }; + case (#system, _ ) { assert false;}; + case (#error, _) { assert false;}; + } + } +}; + +shared func t3() : async () { + try { + try { + throw error("t3"); + assert(false); + } catch e1 { + switch (errorCode(e1), errorMessage(e1)) { + case (#error, "t3") { + throw error("t31"); + }; + case (#system, _) { + assert false; + }; + case (#error, _) { + assert false; + }; + } + } + } + catch e2 { + switch (errorCode(e2),errorMessage(e2)) { + case (#error, "t31") { }; + case (#system, _) { + assert false; + }; + case (#error, _) { + assert true; + }; + } + } +}; + + +async { + + try { + await t2(); + print ("\n t2 ok"); + } catch _ { + assert false; + }; + + try { + await t3(); + print ("\n t3 ok"); + } catch _ { + assert false; + }; + +}; + diff --git a/test/run-dfinity/ok/counter-class.wasm.stderr.ok b/test/run-dfinity/ok/counter-class.wasm.stderr.ok index c3830263b38..31e833d6ed6 100644 --- a/test/run-dfinity/ok/counter-class.wasm.stderr.ok +++ b/test/run-dfinity/ok/counter-class.wasm.stderr.ok @@ -21,23 +21,32 @@ non-closed actor: (ActorE (FuncE read (shared 1 -> 0) - (params $r/0) + (params $reply/0) () (CallE - (1 -> 0) + (2 -> 0) (FuncE $lambda - (1 -> 0) - (params $cont/0) + (2 -> 0) + (params $k/0 $r/0) () - (CallE (1 -> 0) (VarE $cont/0) (VarE j)) + (CallE (1 -> 0) (VarE $k/0) (VarE j)) ) - (FuncE - $lambda - (1 -> 0) - (params $v/0) - () - (CallE (shared 1 -> 0) (VarE $r/0) (VarE $v/0)) + (TupE + (FuncE + $lambda + (1 -> 0) + (params $v/0) + () + (CallE (shared 1 -> 0) (VarE $reply/0) (VarE $v/0)) + ) + (FuncE + $lambda + (1 -> 0) + (params $e/0) + () + (AssertE (LitE (BoolLit false))) + ) ) ) ) diff --git a/test/run-dfinity/ok/local-throw.dvm-run.ok b/test/run-dfinity/ok/local-throw.dvm-run.ok new file mode 100644 index 00000000000..1633cd29053 --- /dev/null +++ b/test/run-dfinity/ok/local-throw.dvm-run.ok @@ -0,0 +1,3 @@ + + t2 ok + t3 ok diff --git a/test/run-dfinity/ok/local-throw.run-ir.ok b/test/run-dfinity/ok/local-throw.run-ir.ok new file mode 100644 index 00000000000..1633cd29053 --- /dev/null +++ b/test/run-dfinity/ok/local-throw.run-ir.ok @@ -0,0 +1,3 @@ + + t2 ok + t3 ok diff --git a/test/run-dfinity/ok/local-throw.run-low.ok b/test/run-dfinity/ok/local-throw.run-low.ok new file mode 100644 index 00000000000..1633cd29053 --- /dev/null +++ b/test/run-dfinity/ok/local-throw.run-low.ok @@ -0,0 +1,3 @@ + + t2 ok + t3 ok diff --git a/test/run-dfinity/ok/local-throw.run.ok b/test/run-dfinity/ok/local-throw.run.ok new file mode 100644 index 00000000000..1633cd29053 --- /dev/null +++ b/test/run-dfinity/ok/local-throw.run.ok @@ -0,0 +1,3 @@ + + t2 ok + t3 ok diff --git a/test/run-dfinity/ok/simple-throw.dvm-run.ok b/test/run-dfinity/ok/simple-throw.dvm-run.ok new file mode 100644 index 00000000000..e357299a076 --- /dev/null +++ b/test/run-dfinity/ok/simple-throw.dvm-run.ok @@ -0,0 +1 @@ +1234done diff --git a/test/run-dfinity/ok/simple-throw.run-ir.ok b/test/run-dfinity/ok/simple-throw.run-ir.ok new file mode 100644 index 00000000000..e357299a076 --- /dev/null +++ b/test/run-dfinity/ok/simple-throw.run-ir.ok @@ -0,0 +1 @@ +1234done diff --git a/test/run-dfinity/ok/simple-throw.run-low.ok b/test/run-dfinity/ok/simple-throw.run-low.ok new file mode 100644 index 00000000000..e357299a076 --- /dev/null +++ b/test/run-dfinity/ok/simple-throw.run-low.ok @@ -0,0 +1 @@ +1234done diff --git a/test/run-dfinity/ok/simple-throw.run.ok b/test/run-dfinity/ok/simple-throw.run.ok new file mode 100644 index 00000000000..e357299a076 --- /dev/null +++ b/test/run-dfinity/ok/simple-throw.run.ok @@ -0,0 +1 @@ +1234done diff --git a/test/run-dfinity/simple-throw.as b/test/run-dfinity/simple-throw.as new file mode 100644 index 00000000000..7e1b7b04cc5 --- /dev/null +++ b/test/run-dfinity/simple-throw.as @@ -0,0 +1,21 @@ +// This file only exercises local throws that don't cross function boundaries. +// In principle, it should run on all targets. + +async { + print "1"; + try { + print "2"; + throw error("t2"); + assert(false); + } catch e { + switch (errorCode(e), errorMessage(e)) { + case (#error, "t1") { assert false; }; + case (#system, _ ) { assert false; }; + case (#error, _) { print "3"; }; + } + }; + print "4"; + print "done"; +}; + + diff --git a/test/run-dfinity/tiny.as b/test/run-dfinity/tiny.as new file mode 100644 index 00000000000..847802eec64 --- /dev/null +++ b/test/run-dfinity/tiny.as @@ -0,0 +1,8 @@ +// This file only exercises local throws that don't cross function boundaries. +// In principle, it should run on all targets. + +async { +}; + + + diff --git a/test/run-drun/ok/reject.drun-run.ok b/test/run-drun/ok/reject.drun-run.ok new file mode 100644 index 00000000000..3d9ebbd374b --- /dev/null +++ b/test/run-drun/ok/reject.drun-run.ok @@ -0,0 +1,9 @@ +ingress(0) System +debug.print: 1 +ingress(1) Completed: Canister: Reject: 4 +debug.print: 1 +debug.print: ok +ingress(2) Completed: Canister: Payload: 0x4449444c016c000100 +debug.print: 1 +debug.print: ok +ingress(3) Completed: Canister: Reject: 4 diff --git a/test/run-drun/reject.as b/test/run-drun/reject.as new file mode 100644 index 00000000000..4dc3b0a3658 --- /dev/null +++ b/test/run-drun/reject.as @@ -0,0 +1,28 @@ +actor { + public func reject1() : async () { + print "1"; + throw (error("Error")); + print "wrong"; + }; + + public func reject2() : async () { + print "1"; + try { throw (error("Error")) } + catch e {}; + print "ok"; + }; + + public func reject3() : async () { + print "1"; + try { throw (error("Error")) } + catch e { + print "ok"; + throw e; + }; + print "wrong"; + }; + +} +//CALL ingress reject1 0x4449444C0000 +//CALL ingress reject2 0x4449444C0000 +//CALL ingress reject3 0x4449444C0000 diff --git a/test/run/ok/throw.diff-low.ok b/test/run/ok/throw.diff-low.ok new file mode 100644 index 00000000000..0d77417c49a --- /dev/null +++ b/test/run/ok/throw.diff-low.ok @@ -0,0 +1,10 @@ +--- throw.run ++++ throw.run-low +@@ -1,6 +1 @@ +- +- t1 ok +- t2 ok +- t3 ok +- t4 ok +- t5 ok ++(unknown location): execution error, assertion failure diff --git a/test/run/ok/throw.run-ir.ok b/test/run/ok/throw.run-ir.ok new file mode 100644 index 00000000000..5c38b98138f --- /dev/null +++ b/test/run/ok/throw.run-ir.ok @@ -0,0 +1,6 @@ + + t1 ok + t2 ok + t3 ok + t4 ok + t5 ok diff --git a/test/run/ok/throw.run-low.ok b/test/run/ok/throw.run-low.ok new file mode 100644 index 00000000000..aa7af77560b --- /dev/null +++ b/test/run/ok/throw.run-low.ok @@ -0,0 +1 @@ +(unknown location): execution error, assertion failure diff --git a/test/run/ok/throw.run.ok b/test/run/ok/throw.run.ok new file mode 100644 index 00000000000..5c38b98138f --- /dev/null +++ b/test/run/ok/throw.run.ok @@ -0,0 +1,6 @@ + + t1 ok + t2 ok + t3 ok + t4 ok + t5 ok diff --git a/test/run/ok/throw.wasm.stderr.ok b/test/run/ok/throw.wasm.stderr.ok new file mode 100644 index 00000000000..ff36ca0e2f6 --- /dev/null +++ b/test/run/ok/throw.wasm.stderr.ok @@ -0,0 +1 @@ +Fatal error: exception "Assert_failure codegen/compile.ml:4844:18" diff --git a/test/run/throw.as b/test/run/throw.as new file mode 100644 index 00000000000..382403982ef --- /dev/null +++ b/test/run/throw.as @@ -0,0 +1,128 @@ +shared func t1() : async () { + throw error("t1"); + assert false; +}; + +shared func t2() : async () { + try { + throw error("t2"); + assert(false); + } catch e { + switch (errorCode(e), errorMessage(e)) { + case (#error, "t1") { assert false;}; + case (#system, _) { assert false;}; + case (#error, _) { assert true;}; + } + } +}; + +shared func t3() : async () { + try { + try { + throw error("t3"); + assert(false); + } catch e1 { + switch (errorCode(e1), errorMessage(e1)) { + case (#error, "t3") { throw error("t31");}; + case (#system, _) {assert false;}; + case (#error, _) { assert false;}; + } + } + } catch e2 { + switch (errorCode(e2), errorMessage(e2)) { + case (#error, "t31") { assert true;}; + case (#system, _ ) { assert false;}; + case (#error, _) { assert false;}; + } + } +}; + +shared func t4() : async () { + try { + try { + throw error("t4"); + assert(false); + } catch e1 { + switch (errorCode(e1), errorMessage(e1)) { + case (#error, "t4") { throw error("t41");}; + case (#system, _) { assert false;}; + case (#error, _) { assert false;}; + } + } + } catch e2 { + switch (errorCode(e2), errorMessage(e2)) { + case (#error, "t41") { throw error("t42");}; + case (#system, _ ) { assert false;}; + case (#error, _ ) { assert false;}; + } + } +}; + + +shared func t5() : async () { + try { + try { + throw error("t5"); + assert(false); + } catch e1 { + switch (errorCode(e1), errorMessage(e1)) { + case (#system, _ ) { assert false;}; + case _ { throw e1; } + } + } + } catch e2 { + switch (errorCode(e2), errorMessage(e2)) { + case (#error, "t5") { throw error("t51");}; + case (#system, _ ) { assert false;}; + case (#error, _ ) { assert false;}; + } + } +}; + +async { + + try { + await t1(); + assert false; + } catch e { + switch (errorCode(e), errorMessage(e)) { + case (#error, "t1") { print ("\n t1 ok")}; + case _ { assert false; } + } + }; + + try { + await t2(); + print ("\n t2 ok"); + } catch _ { + assert false; + }; + + try { + await t3(); + print ("\n t3 ok"); + } catch _ { + assert false; + }; + + try { + await t4(); + assert false; + } catch e { + switch (errorCode(e), errorMessage(e)) { + case (#error, "t42") { print ("\n t4 ok"); }; + case _ { assert false; }; + } + }; + + try { + await t5(); + assert false; + } catch e { + switch (errorCode(e), errorMessage(e)) { + case (#error, "t51") { print ("\n t5 ok"); }; + case _ { assert false; }; + } + }; + +}; From a4e5f3277211580c2ffdcf9a8e996e860838b4f5 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 24 Sep 2019 10:28:01 +0200 Subject: [PATCH 0400/1176] Update Tagged.can_have_tag in light of #529 (#566) --- src/codegen/compile.ml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index f632fbf0ae4..a6297230f89 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -1178,15 +1178,15 @@ module Tagged = struct | Array -> begin match normalize ty with | (Con _ | Any) -> true - | (Array _ | Tup _ | Obj _) -> true - | (Prim _ | Opt _ | Variant _ | Func _ | Non) -> false + | (Array _ | Tup _) -> true + | (Prim _ | Obj _ | Opt _ | Variant _ | Func _ | Non) -> false | (Pre | Async _ | Mut _ | Var _ | Typ _) -> assert false end | Text -> begin match normalize ty with | (Con _ | Any) -> true - | (Prim Text | Obj _) -> true - | (Prim _ | Array _ | Tup _ | Opt _ | Variant _ | Func _ | Non) -> false + | (Prim Text) -> true + | (Prim _ | Obj _ | Array _ | Tup _ | Opt _ | Variant _ | Func _ | Non) -> false | (Pre | Async _ | Mut _ | Var _ | Typ _) -> assert false end | Object -> From bb8c3f80a648f92ee920bdbb8860593914f31e20 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 24 Sep 2019 16:03:38 +0200 Subject: [PATCH 0401/1176] IDL spec: spell out leb encoding of crucial constants (#685) before I get too good at calculating these in my head, lets make this document a bit easier to use when writing or reading raw IDL --- design/IDL.md | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/design/IDL.md b/design/IDL.md index 8501b67e916..7d3c1e9aff0 100644 --- a/design/IDL.md +++ b/design/IDL.md @@ -915,37 +915,44 @@ We assume that the fields in a record or function type are sorted by increasing ``` T : -> i8* -T(null) = sleb128(-1) -T(bool) = sleb128(-2) -T(nat) = sleb128(-3) -T(int) = sleb128(-4) -T(nat) = sleb128(-5 - log2(N/8)) -T(int) = sleb128(-9 - log2(N/8)) -T(float) = sleb128(-13 - log2(N/32)) -T(text) = sleb128(-15) -T(reserved) = sleb128(-16) -T(empty) = sleb128(-17) +T(null) = sleb128(-1) = 0x7f +T(bool) = sleb128(-2) = 0x7e +T(nat) = sleb128(-3) = 0x7d +T(int) = sleb128(-4) = 0x7c +T(nat8) = sleb128(-5) = 0x7b +T(nat16) = sleb128(-6) = 0x7a +T(nat32) = sleb128(-7) = 0x79 +T(nat32) = sleb128(-8) = 0x78 +T(int8) = sleb128(-9) = 0x77 +T(int16) = sleb128(-10) = 0x76 +T(int32) = sleb128(-11) = 0x75 +T(int64) = sleb128(-12) = 0x74 +T(float32) = sleb128(-13) = 0x73 +T(float64) = sleb128(-14) = 0x72 +T(text) = sleb128(-15) = 0x71 +T(reserved) = sleb128(-16) = 0x70 +T(empty) = sleb128(-17) = 0x6f T : -> i8* -T(opt ) = sleb128(-18) I() -T(vec ) = sleb128(-19) I() -T(record {^N}) = sleb128(-20) T*(^N) -T(variant {^N}) = sleb128(-21) T*(^N) +T(opt ) = sleb128(-18) I() // 0x6e +T(vec ) = sleb128(-19) I() // 0x6d +T(record {^N}) = sleb128(-20) T*(^N) // 0x6c +T(variant {^N}) = sleb128(-21) T*(^N) // 0x6b T : -> i8* T(:) = leb128() I() T : -> i8* T(func (*) -> (*) *) = - sleb128(-22) T*(*) T*(*) T*(*) + sleb128(-22) T*(*) T*(*) T*(*) // 0x6a T(service {*}) = - sleb128(-23) T*(*) + sleb128(-23) T*(*) // 0x69 T : -> i8* T(:) = leb128(|utf8()|) i8*(utf8()) I() T : -> i8* -T(query) = i8(1) +T(query) = i8(1) T(oneway) = i8(2) T* : * -> i8* From 880d0ef94cd1283b79c1d4293148bfb3922e8365 Mon Sep 17 00:00:00 2001 From: Lisa Gunn <44206363+lsgunnlsgunn@users.noreply.github.com> Date: Tue, 24 Sep 2019 08:50:30 -0700 Subject: [PATCH 0402/1176] Update guide/guide.md Co-Authored-By: Andreas Rossberg --- guide/guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guide/guide.md b/guide/guide.md index e2204fdbb4c..0e702371d1c 100644 --- a/guide/guide.md +++ b/guide/guide.md @@ -23,7 +23,7 @@ TODO: The *internet computer* is a network of connected computers that communicate securely and provide processing services to registered users, developers, and other computers. If you think of the internet computer as an infrastructure platform, it is similar to a public cloud provider, like Amazon Web Services (AWS), Google Cloud Platform (GCP), or Microsoft Azure, or a private cloud managed internally by private organizations. Unlike a public or private cloud, however, the internet computer platform is not owned and operated by a single private company. -Its architecture enables multiple computers to operate like one, very powerful, virtual machine that does not dependent on legacy technologies that are vulnerable to attack. +Its architecture enables multiple computers to operate like one, very powerful, virtual machine that does not depend on legacy technologies that are vulnerable to attack. === Why develop applications to run on the internet computer? From 6b467bccb5dcf87eb5a33643f5d3119e60ea30cd Mon Sep 17 00:00:00 2001 From: Lisa Gunn <44206363+lsgunnlsgunn@users.noreply.github.com> Date: Tue, 24 Sep 2019 08:57:31 -0700 Subject: [PATCH 0403/1176] Remove bold for internet computer, fix markdown --- guide/guide.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/guide/guide.md b/guide/guide.md index 0e702371d1c..8add0ae4858 100644 --- a/guide/guide.md +++ b/guide/guide.md @@ -1,4 +1,4 @@ -% Language Reference Guide +% Language Reference Manual % [DFINITY Foundation](https://dfinity.org/) # Introduction -The *internet computer* is a network of connected computers that communicate securely and provide processing services to registered users, developers, and other computers. +The **internet computer** is a network of connected computers that communicate securely and provide processing services to registered users, developers, and other computers. If you think of the internet computer as an infrastructure platform, it is similar to a public cloud provider, like Amazon Web Services (AWS), Google Cloud Platform (GCP), or Microsoft Azure, or a private cloud managed internally by private organizations. Unlike a public or private cloud, however, the internet computer platform is not owned and operated by a single private company. Its architecture enables multiple computers to operate like one, very powerful, virtual machine that does not depend on legacy technologies that are vulnerable to attack. === Why develop applications to run on the internet computer? -For programmers and software developers, the **internet computer** platform provides unique capabilities and opportunities within a framework that simplifies how you can design, build, and deploy applications. +For programmers and software developers, the internet computer platform provides unique capabilities and opportunities within a framework that simplifies how you can design, build, and deploy applications. -*{proglang}* is a programming language that has been specifically designed for writing applications, services, and microservices that run on the **internet computer** platform and that take full advantage of the unique features that the **internet computer** provides, such as orthogonal persistence, autonomous operation, and tamper-proof message handling. For more information about the unique features of the **internet computer** along with tutorials and examples to help you develop programs that make use of them, see the _Developer's Guide_. +*{proglang}* is a programming language that has been specifically designed for writing applications, services, and microservices that run on the internet computer platform and that take full advantage of the unique features that the internet computer provides, such as orthogonal persistence, autonomous operation, and tamper-proof message handling. For more information about the unique features of the internet computer along with tutorials and examples to help you develop programs that make use of them, see the _Developer's Guide_. {proglang} provides: @@ -52,7 +52,8 @@ Because WebAssembly code is designed to provide portable low-level instructions However, most of the higher-level languages--like C, C++, and Rust--that support compiling to WebAssembly are either too unsafe (for example, C or C++) or too complex (for example, Rust) for developers who want to deliver secure applications with minimal overhead. To address the need for correctness without complexity, {company-id} has designed its own *{proglang}* programming language. *{proglang}* provides a simple and expressive alternative to other programming languages that is easy to learn whether you are a new or experienced programmer. -=== Support for other languages + +## Support for other languages WebAssembly is language-agnostic. It does not require a high-level type system for language inter-operation. @@ -63,13 +64,13 @@ The {proglang} compiler automates the production and consumption of IDL files us For information about the *Interface Definition Language* interfaces, see XXX. -== Highlights and important features +## Highlights and important features Although {proglang} is, strictly-speaking, a new language, you might find it is similar to a language you already know. For example, the {proglang} syntax is similar to coding using a functional programming language such as OCaml (Objective Caml). It also draws on elements that are common in other, more familiar, languages, including JavaScript, TypeScript, C#, Swift, Pony, ML, and Haskell. Unlike other programming languages, however, {proglang} extends and optimizes features that are uniquely suited to the internet computer platform. -=== Actors and objects +### Actors and objects One of the most important principles to keep in mind when preparing to use {proglang} is that it is an *actor-based* programming model. An actor is a special kind of object that can query and update fields) remotely and asynchronously. @@ -81,7 +82,7 @@ Because actors are essentially objects, you can also define actor classes. In general, each actor object is used to create one application which is then deployed as a *canister* containing compiled WebAssembly, some environment configuration information, and interface bindings. For more information about the developing applications and deploying applications, see the _Developer's Guide_. -=== Key language features +### Key language features Some of the other important language features of {proglang} include the following: From b372664cdad808862d2f81a43206fed4ec0ac5b7 Mon Sep 17 00:00:00 2001 From: Lisa Gunn <44206363+lsgunnlsgunn@users.noreply.github.com> Date: Tue, 24 Sep 2019 09:00:16 -0700 Subject: [PATCH 0404/1176] Update guide/guide.md agreed Co-Authored-By: Andreas Rossberg --- guide/guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guide/guide.md b/guide/guide.md index 8add0ae4858..22d3ae10c05 100644 --- a/guide/guide.md +++ b/guide/guide.md @@ -37,7 +37,7 @@ For programmers and software developers, the internet computer platform provides * A simple design that uses familiar syntax that is easy for programmers to learn. -* A well-constructed *actor-based* programming model optimized for efficient message handling. +* An *actor-based* programming model optimized for efficient message handling. * An integrated approach to using compiled WebAssembly code to run autonomous applications. From 60a701ffc3872fb780ba2dbfc32050400f3385dc Mon Sep 17 00:00:00 2001 From: Lisa Gunn <44206363+lsgunnlsgunn@users.noreply.github.com> Date: Tue, 24 Sep 2019 09:02:01 -0700 Subject: [PATCH 0405/1176] Update guide/guide.md agreed Co-Authored-By: Andreas Rossberg --- guide/guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guide/guide.md b/guide/guide.md index 22d3ae10c05..09eb1cdea47 100644 --- a/guide/guide.md +++ b/guide/guide.md @@ -46,7 +46,7 @@ For programmers and software developers, the internet computer platform provides ## Why a new language? The internet computer provides a network platform that can support programs written in different languages. -The only requirement is that the program must support compiling to WebAssembly code. +The only requirement is that the program must support compilation to WebAssembly code. WebAssembly (commonly-abbreviated as Wasm) is a low-level computer instruction format for virtual machines. Because WebAssembly code is designed to provide portable low-level instructions that enable client and server applications to be deployed on the web, it is a natural fit for deploying applications that are intended to run on the internet computer platform. However, most of the higher-level languages--like C, C++, and Rust--that support compiling to WebAssembly are either too unsafe (for example, C or C++) or too complex (for example, Rust) for developers who want to deliver secure applications with minimal overhead. From eed4a378fb68204f31facb82542b5d732b91d0d4 Mon Sep 17 00:00:00 2001 From: Lisa Gunn <44206363+lsgunnlsgunn@users.noreply.github.com> Date: Tue, 24 Sep 2019 09:02:41 -0700 Subject: [PATCH 0406/1176] Update guide/guide.md agreed Co-Authored-By: Andreas Rossberg --- guide/guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guide/guide.md b/guide/guide.md index 09eb1cdea47..81db53b88e4 100644 --- a/guide/guide.md +++ b/guide/guide.md @@ -96,7 +96,7 @@ Bounded numeric types are checked for overflow. * Support for imperative programming features, including mutable variables and arrays, and local control flow constructs, such as `+return+`, `+break+` and `+continue+`. -* Functions and messages are first-class values. Call-by-value argument evaluation +* Functions and messages are first-class values. is strict. Pattern-matching is supported for scalar and compound values. * A simple, class-based object system without inheritance. From 3a5db16e3b4c83cd57f26f5a6cdf6c9c9895292c Mon Sep 17 00:00:00 2001 From: Lisa Gunn <44206363+lsgunnlsgunn@users.noreply.github.com> Date: Tue, 24 Sep 2019 09:03:03 -0700 Subject: [PATCH 0407/1176] Update guide/guide.md Co-Authored-By: Andreas Rossberg --- guide/guide.md | 1 - 1 file changed, 1 deletion(-) diff --git a/guide/guide.md b/guide/guide.md index 81db53b88e4..569ebf074b7 100644 --- a/guide/guide.md +++ b/guide/guide.md @@ -97,7 +97,6 @@ Bounded numeric types are checked for overflow. and local control flow constructs, such as `+return+`, `+break+` and `+continue+`. * Functions and messages are first-class values. -is strict. Pattern-matching is supported for scalar and compound values. * A simple, class-based object system without inheritance. * The value of a reference can never implicitly be `+null+` to prevent many common `+null+`-reference failures. Instead, the language enables you to explicitly handle `+null+` reference values using `+null+`, _option type_ `+?+`. From 08bbf4d7911cb454301b8f583a1cf11efbbe1066 Mon Sep 17 00:00:00 2001 From: Lisa Gunn <44206363+lsgunnlsgunn@users.noreply.github.com> Date: Tue, 24 Sep 2019 09:03:42 -0700 Subject: [PATCH 0408/1176] Update guide/guide.md Co-Authored-By: Andreas Rossberg --- guide/guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guide/guide.md b/guide/guide.md index 569ebf074b7..adaaafe9714 100644 --- a/guide/guide.md +++ b/guide/guide.md @@ -99,7 +99,7 @@ and local control flow constructs, such as `+return+`, `+break+` and * Functions and messages are first-class values. Pattern-matching is supported for scalar and compound values. * A simple, class-based object system without inheritance. -* The value of a reference can never implicitly be `+null+` to prevent many common `+null+`-reference failures. Instead, the language enables you to explicitly handle `+null+` reference values using `+null+`, _option type_ `+?+`. +* The value of a reference can never implicitly be `+null+` to prevent many common `+null+`-reference failures. Instead, the language enables you to explicitly handle `+null+` values using `+null+`, _option type_ `+?+`. * Asynchronous message handling enables sequential programming with familiar `+async+` and `+await+` constructs and `promise` replies. # Lexical conventions From 820d99110b83092bc825bafd10c777c270d9c0c1 Mon Sep 17 00:00:00 2001 From: Lisa Gunn <44206363+lsgunnlsgunn@users.noreply.github.com> Date: Tue, 24 Sep 2019 09:18:01 -0700 Subject: [PATCH 0409/1176] Change high-level bullets --- guide/guide.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/guide/guide.md b/guide/guide.md index adaaafe9714..42be57f34e0 100644 --- a/guide/guide.md +++ b/guide/guide.md @@ -25,7 +25,7 @@ If you think of the internet computer as an infrastructure platform, it is simil Unlike a public or private cloud, however, the internet computer platform is not owned and operated by a single private company. Its architecture enables multiple computers to operate like one, very powerful, virtual machine that does not depend on legacy technologies that are vulnerable to attack. -=== Why develop applications to run on the internet computer? +### Why develop applications to run on the internet computer? For programmers and software developers, the internet computer platform provides unique capabilities and opportunities within a framework that simplifies how you can design, build, and deploy applications. @@ -39,11 +39,11 @@ For programmers and software developers, the internet computer platform provides * An *actor-based* programming model optimized for efficient message handling. -* An integrated approach to using compiled WebAssembly code to run autonomous applications. +* An interpreter and compiler that you can use to test and compile the WebAssembly code for autonomous applications. -* A flexible architecture that anticipates future extensions and improvement to WebAssembly. +* Support for features not-yet implemented that anticipate future extensions and improvement to WebAssembly. -## Why a new language? +### Why a new language? The internet computer provides a network platform that can support programs written in different languages. The only requirement is that the program must support compilation to WebAssembly code. @@ -53,7 +53,7 @@ However, most of the higher-level languages--like C, C++, and Rust--that support To address the need for correctness without complexity, {company-id} has designed its own *{proglang}* programming language. *{proglang}* provides a simple and expressive alternative to other programming languages that is easy to learn whether you are a new or experienced programmer. -## Support for other languages +### Support for other languages WebAssembly is language-agnostic. It does not require a high-level type system for language inter-operation. @@ -87,9 +87,9 @@ For more information about the developing applications and deploying application Some of the other important language features of {proglang} include the following: * JavaScript/TypeScript-style syntax. -* Automatic memory management by precise garbage collection between messages. * Bounded polymorphic type system that can assign types without explicit type annotations. Strong, static typing ensures type safety and includes subtype polymorphism, and structural typing. +Types can be inferred in many common situations. Unbounded and bounded numeric types with explicit conversions between them. Bounded numeric types are checked for overflow. From 6645c1573b5bcb165d9a01f49af9a6dd53e13b96 Mon Sep 17 00:00:00 2001 From: Lisa Gunn <44206363+lsgunnlsgunn@users.noreply.github.com> Date: Tue, 24 Sep 2019 09:26:09 -0700 Subject: [PATCH 0410/1176] Update guide/guide.md Co-Authored-By: Andreas Rossberg --- guide/guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guide/guide.md b/guide/guide.md index 42be57f34e0..106fff26dba 100644 --- a/guide/guide.md +++ b/guide/guide.md @@ -48,7 +48,7 @@ For programmers and software developers, the internet computer platform provides The internet computer provides a network platform that can support programs written in different languages. The only requirement is that the program must support compilation to WebAssembly code. WebAssembly (commonly-abbreviated as Wasm) is a low-level computer instruction format for virtual machines. -Because WebAssembly code is designed to provide portable low-level instructions that enable client and server applications to be deployed on the web, it is a natural fit for deploying applications that are intended to run on the internet computer platform. +Because WebAssembly code is designed to provide portable low-level instructions that enable applications to be deployed on platforms such as the web, it is a natural fit for deploying applications that are intended to run on the internet computer platform. However, most of the higher-level languages--like C, C++, and Rust--that support compiling to WebAssembly are either too unsafe (for example, C or C++) or too complex (for example, Rust) for developers who want to deliver secure applications with minimal overhead. To address the need for correctness without complexity, {company-id} has designed its own *{proglang}* programming language. *{proglang}* provides a simple and expressive alternative to other programming languages that is easy to learn whether you are a new or experienced programmer. From 16db9ca5b484b3eba76030e17d4b9fc635b2c644 Mon Sep 17 00:00:00 2001 From: lsgunnlsgunn Date: Tue, 24 Sep 2019 09:57:50 -0700 Subject: [PATCH 0411/1176] ACT-129-Edit/Update intro section, incorporate comments from Andreas --- guide/guide.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/guide/guide.md b/guide/guide.md index 106fff26dba..0d23964a06b 100644 --- a/guide/guide.md +++ b/guide/guide.md @@ -49,7 +49,7 @@ The internet computer provides a network platform that can support programs writ The only requirement is that the program must support compilation to WebAssembly code. WebAssembly (commonly-abbreviated as Wasm) is a low-level computer instruction format for virtual machines. Because WebAssembly code is designed to provide portable low-level instructions that enable applications to be deployed on platforms such as the web, it is a natural fit for deploying applications that are intended to run on the internet computer platform. -However, most of the higher-level languages--like C, C++, and Rust--that support compiling to WebAssembly are either too unsafe (for example, C or C++) or too complex (for example, Rust) for developers who want to deliver secure applications with minimal overhead. +However, most of the higher-level languages--like C, C++, and Rust--that support compiling to WebAssembly are either too unsafe (for example, C or C++) or too complex (for example, Rust) for developers who want to deliver secure applications without a long learning curve. To address the need for correctness without complexity, {company-id} has designed its own *{proglang}* programming language. *{proglang}* provides a simple and expressive alternative to other programming languages that is easy to learn whether you are a new or experienced programmer. @@ -57,7 +57,7 @@ To address the need for correctness without complexity, {company-id} has designe WebAssembly is language-agnostic. It does not require a high-level type system for language inter-operation. -Although {proglang} is specifically designed to compile to WebAssembly and make it easy to write programs to run on the internet computer, it just one of many languages you can use to develop applications for the internet computer platform. +Although {proglang} is specifically designed to compile to WebAssembly and make it easy to write programs to run on the internet computer, it is just one of many languages you can eventually use to develop applications for the internet computer platform. To support multiple languages and typed, cross-language communication, {company-id} also provides an *Interface Definition Language* (IDL). The {proglang} compiler automates the production and consumption of IDL files using the type signatures in {proglang} programs and the structure of imported IDL interfaces. @@ -66,18 +66,18 @@ For information about the *Interface Definition Language* interfaces, see XXX. ## Highlights and important features -Although {proglang} is, strictly-speaking, a new language, you might find it is similar to a language you already know. For example, the {proglang} syntax is similar to coding using a functional programming language such as OCaml (Objective Caml). +Although {proglang} is, strictly-speaking, a new language, you might find it is similar to a language you already know. For example, the {proglang} typing system is similar to a functional programming language such as OCaml (Objective Caml), but the syntax you use in defining functions is more like coding in JavaScript. It also draws on elements that are common in other, more familiar, languages, including JavaScript, TypeScript, C#, Swift, Pony, ML, and Haskell. Unlike other programming languages, however, {proglang} extends and optimizes features that are uniquely suited to the internet computer platform. ### Actors and objects One of the most important principles to keep in mind when preparing to use {proglang} is that it is an *actor-based* programming model. -An actor is a special kind of object that can query and update fields) remotely and asynchronously. -All communication with and between actors involves passing messages asynchronously, in an isolated state, over the network using the internet computer's messaging protocol. +An actor is a special kind of object with an isolated state that can interacted with remotely and asynchronously. +All communication with and between actors involves passing messages asynchronously over the network using the internet computer's messaging protocol. An actor’s messages are processed in sequence, so state modifications never cause race conditions. -Classes can be used to produce object of a predetermined type, with a predetermined interface and behavior. +Classes can be used to produce objects of a predetermined type, with a predetermined interface and behavior. Because actors are essentially objects, you can also define actor classes. In general, each actor object is used to create one application which is then deployed as a *canister* containing compiled WebAssembly, some environment configuration information, and interface bindings. For more information about the developing applications and deploying applications, see the _Developer's Guide_. @@ -87,14 +87,14 @@ For more information about the developing applications and deploying application Some of the other important language features of {proglang} include the following: * JavaScript/TypeScript-style syntax. -* Bounded polymorphic type system that can assign types without explicit type annotations. -Strong, static typing ensures type safety and includes subtype polymorphism, and structural typing. +* Bounded polymorphic type system that can assign types without explicit type annotations. Types can be inferred in many common situations. +Strong, static typing ensures type safety and includes subtype polymorphism, and structural typing. Unbounded and bounded numeric types with explicit conversions between them. Bounded numeric types are checked for overflow. * Support for imperative programming features, including mutable variables and arrays, -and local control flow constructs, such as `+return+`, `+break+` and +and local control flow constructs, such as loops, `+return+`, `+break+` and `+continue+`. * Functions and messages are first-class values. Pattern-matching is supported for scalar and compound values. From 900deeea6b6f63243121d42974f9b3222f55cf08 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 24 Sep 2019 23:19:43 +0100 Subject: [PATCH 0412/1176] Update documentation (#641) * fix typos, use category for (operator) sort, sort for obj_sort; add finite int/nat types * rename category C/Comparable to R/Relational * typos and all cap DFINITY * describe fix-sized integers, fix typos. * typo * Update guide/guide.md Co-Authored-By: Gabor Greif * Update guide/guide.md Co-Authored-By: Gabor Greif * Update guide/guide.md Co-Authored-By: Gabor Greif * Update guide/guide.md Co-Authored-By: Gabor Greif * address Gabor's comment; capitalize Unicode; fix corrupted in async section; typos; add TODOs * spacing --- guide/as-slides.md | 2 +- guide/guide.md | 261 +++++++++++++++++++++++++-------------------- 2 files changed, 146 insertions(+), 117 deletions(-) diff --git a/guide/as-slides.md b/guide/as-slides.md index 04cdcf5110c..8ebdc824e63 100644 --- a/guide/as-slides.md +++ b/guide/as-slides.md @@ -188,7 +188,7 @@ AS distinguishes sharable types: - all primitive types are sharable (scalars + text) - any `shared` function type is sharable - - an object type is sharable if it's fields are sharable and immutable + - an object type is sharable if its fields are sharable and immutable - any `actor` type is sharable - `[T]` and `?T` are sharable if `T` is sharable. - `(T1,...,Tn)` is sharable if `T1`,..., `Tn` all sharable. diff --git a/guide/guide.md b/guide/guide.md index 5b0a5b5d9c4..cf0d191173b 100644 --- a/guide/guide.md +++ b/guide/guide.md @@ -9,37 +9,44 @@ TODO --> TODO: -* [X] *Sort* primitives and operations as arithmetic (A), boolean (L), bitwise (B) and comparable (C) and use these sorts to concisely present sorted operators (unop, binop, relop, a(ssing)op) etc. +* [X] *Categorize* primitives and operations as arithmetic (A), logical (L), bitwise (B) and relational (R) and use these categories to concisely present categorized operators (unop, binop, relop, a(ssigning)op) etc. * [ ] Various inline TBCs and TBRs and TODOs * [ ] Typing of patterns * [ ] Variants * [ ] Object patterns * [ ] Import expressions -* [ ] Modules * [ ] Complete draft of Try/Throw expressions and primitive Error/ErrorCode type * [ ] Prelude +* [ ] Modules and static restriction +* [ ] Type components and paths +* [ ] Prelude (move scattered descriptions of assorted prims like charToText here) +* [ ] Split category R into E (Equality) and O (Ordering) if we don't want Bool to support O. +* [ ] Include actual grammar (extracted from menhir) in appendix? +* [ ] Prose description of definedness checks +* [ ] Platform changes: remove async expressions (and perhaps types); restrict await to shared calls. + # Introduction ActorScript is a new, general purpose programming language for the -Dfinity platform. +DFINITY platform. ## Why a new language? -Dfinity has chosen WebAssembly as its low-level virtual machine. +DFINITY has chosen WebAssembly as its low-level virtual machine. The currently available compilers targeting WebAssembly are for languages that are either too unsafe (C, C++) or too complex (Rust) for mainstream programmers. -To promote correctness and reduce complexity, Dfinity is designing its own language, *ActorScript*, that is safe and expressive, yet simple and approachable to mainstream programmers. +To promote correctness and reduce complexity, DFINITY is designing its own language, *ActorScript*, that is safe and expressive, yet simple and approachable to mainstream programmers. ### Interoperability -ActorScript is just one of hopefully many languages able to run on the Dfinity platform. +ActorScript is just one of hopefully many languages able to run on the DFINITY platform. -Since WebAssembly is language agnostic and, unlike other virtual machines, does not mandate a high-level type system for language interoperation, Dfinity will provide an *Interface Definition Language* to support typed, cross-language communication. +Since WebAssembly is language agnostic and, unlike other virtual machines, does not mandate a high-level type system for language interoperation, DFINITY will provide an *Interface Definition Language* to support typed, cross-language communication. The ActorScript compiler will automate the production and consumption of IDL files, driven by type signatures ActorScript programs and the structure of imported IDL interfaces. @@ -50,13 +57,13 @@ The IDL language is currently under design and outside the scope of this documen ActorScript provides: -* A high-level language for programming Dfinity applications +* A high-level language for programming DFINITY applications * A simple ("K.I.S.S.") design and familiar syntax for average programmers -* Good and convenient support for the actor model embodied in Dfinity canisters +* Good and convenient support for the actor model embodied in DFINITY canisters -* A good fit for underlying Wasm and Dfinity execution model +* A good fit for underlying Wasm and DFINITY execution model * A forward looking design that anticipates future extensions to WebAssembly @@ -100,10 +107,10 @@ The key language features of ActorScript are: * Message passing is asynchronous (to hide network latency). -* A familiar `async`/`await` constructs enables sequential programming with asynchronous messaging. +* Familiar `async`/`await` constructs enable sequential programming with asynchronous messaging. Like most programming languages, ActorScript borrows features from others and -draws inspirations from Java, C#, JavaScript, Swift, Pony, ML, Haskell. +draws inspirations from Java, C#, JavaScript, Swift, Pony, ML and Haskell. # ActorScript Syntax (Sketch) @@ -167,10 +174,10 @@ Negative integers may be constructed by applying a prefix negation `-` operation ## Characters A character is a single quote (`'`) delimited: -* unicode character in UTF-8, +* Unicode character in UTF-8, * `\`-escaped newline, carriage return, tab, single or double quotation mark * `\`-prefixed ASCII character (TBR), -* or `\u{` hexnum `}` enclosed valid, escaped unicode character in hexadecimal (TBR). +* or `\u{` hexnum `}` enclosed valid, escaped Unicode character in hexadecimal (TBR). ```bnf ascii ::= ['\x00'-'\x7f'] @@ -210,24 +217,24 @@ text ::= '"' character* '"' ## Operators -### Sorts +### Categories -To simplify the presentation of available operators, operators and primitive types are classified into basic sorts: +To simplify the presentation of available operators, operators and primitive types are classified into basic categories: -| Sort| Sort | | +| Abbreviation| Category | | |---|----|-------| | A | Arithmetic | arithmetic operations | -| L | Logical A | boolean operations | +| L | Logical | logical/Boolean operations | | B | Bitwise | bitwise operations| -| C | Comparable | equality and comparison | -| T | Text | concatention | +| R | Relational | equality and comparison | +| T | Text | concatenation | -Some types have several sorts, e.g. type `Int` is both arithmetic and comparable and supports both addition and less than (amongst other operations). +Some types have several categories, e.g. type `Int` is both arithmetic (A) and relational (R) and supports both arithmentic addition ('+') and relational less than ('<=') (amongst other operations). ### Unary Operators -| ``| Sort | | +| ``| Category | | |------|----|-------| | `-` | A | numeric negation | | `+` | A | numeric identity | @@ -237,21 +244,21 @@ Some types have several sorts, e.g. type `Int` is both arithmetic and comparable ### Relational Operators -| `` | Sort | | +| `` | Category | | |-------|---|------| -| `␣<␣` | C | less than *(must be enclosed in whitespace)* | -| `␣>␣` | C | greater than *(must be enclosed in whitespace)* | -| `==` | C | equals | -| `!=` | C | not equals | -| `<=` | C | less than or equal | -| `>=` | C |greater than or equal | +| `␣<␣` | R | less than *(must be enclosed in whitespace)* | +| `␣>␣` | R | greater than *(must be enclosed in whitespace)* | +| `==` | R | equals | +| `!=` | R | not equals | +| `<=` | R | less than or equal | +| `>=` | R | greater than or equal | Equality is structural. ### Numeric Binary Operators -| ``| Sort | | +| ``| Category | | |------|---|----------| | `+` | A | addition | | `-` | A | subtraction | @@ -262,7 +269,7 @@ Equality is structural. ### Bitwise Binary Operators -| `` | Sort | | +| `` | Category | | |-------|---|------| | `&` | B | bitwise and | | `|` | B | bitwise or | @@ -274,13 +281,13 @@ Equality is structural. ### String Operators -| `` | Sort | +| `` | Category | | |------|---|------| | `#` | T | concatenation | ### Assignment Operators -|`:=`, `=`, `=`| Sort| | +|`:=`, `=`, `=`| Category| | |--------| ----|----| | `:=` | * | assignment (in place update) | | `+=` | A | in place add | @@ -290,7 +297,7 @@ Equality is structural. | `%=` | A | in place modulo | | `**=` | A | in place exponentiation | | `&=` | B | in place logical and | -| `|=` | B | in place logical or | +| `\|=` | B | in place logical or | | `^=` | B | in place exclusive or | | `<<=` | B | in place shift left | | `>>=` | B | in place shift right | @@ -298,24 +305,25 @@ Equality is structural. | `<>>=` | B | in place rotate right | | `#=` | T | in place concatenation | -The sort of a compound assigment `=`/`=` is given by the sort of the operator ``/``. +The category of a compound assigment `=`/`=` is given by the category of the operator ``/``. ## Operator and Keyword Precedence -The following table defines the relative precedence and associativity of operators and token, order from lowest to highest precedence. Tokens on the same line have equal precedence with the indicated associativity. +The following table defines the relative precedence and associativity of operators and tokens, ordered from lowest to highest precedence. +Tokens on the same line have equal precedence with the indicated associativity. Precedence | Associativity | Token | |---|------------|--------| LOWEST | none | `if _ _` (no `else`), `loop _` (no `while`) || none | `else`, `while` -|| right | `:= `, `+=`, `-=`, `*=`, `|=`, `%=`, `**=`, `#=`, `&=`, `|=`, `^=`, `<<=`, `>>-`, `<<>=`, `<>>=` +|| right | `:= `, `+=`, `-=`, `*=`, `/=`, `%=`, `**=`, `#=`, `&=`, `\|=`, `^=`, `<<=`, `>>-`, `<<>=`, `<>>=` || left | `:` || left | `or` || left | `and` || none | `==`, `!=`, `<`, `>`, `<=`, `>`, `>=` || left | `+`, `-`, `#` || left | `*`, `/`, `%` -|| left | `|` +|| left | `\|` || left | `&` || left | `^` || none | `<<`, `>>`, `<<>`, `<>>` @@ -329,7 +337,7 @@ Type expressions are used to specify the types of arguments, constraints (a.k.a ``` ::= type expressions ? constructor - actor? { ;* } object + ? { ;* } object [ var? ] array Null null type ? option @@ -341,76 +349,93 @@ Type expressions are used to specify the types of arguments, constraints (a.k.a Error errors/exceptions Shared sharable types ( type ) parenthesized type + + ::= (actor | module | object) ``` +An absent `?` abbreviates `object`. + + ## Primitive types -ActorScript provides the following primitive types, including support for Booleans, integers, words of various sizes, characters and text. +ActorScript provides the following primitive type identifiers, including support for Booleans, signed and unsigned integers and machine words of various sizes, characters and text. -The sort of a type determines the operators (unary, binary, relational and assigment) applicable to values of that type. +The category of a type determines the operators (unary, binary, relational and in-place update via assigment) applicable to values of that type. -| Identifier | Sort | Description | +| Identifier | Category | Description | |---|------------|--------| -| `Bool` | L, C | boolean values `true` and `false` and logical operators | -| `Int` | A, C | signed integer values with checked arithmetic (currently 64-bit, eventually unbounded)| -| `Nat` | A, C | non-negative integer values with checked arithmetic (currently 63-bit, eventually unbounded)| -| `Word8` | A, B, C | unsigned 8-bit integers with bitwise operations | -| `Word16` | A, B, C | unsigned 16-bit integers with bitwise operations | -| `Word32` | A, B, C | unsigned 32-bit integers with bitwise operations | -| `Word64` | A, B, C | unsigned 64-bit integers with bitwise operations | -| `Char` | C | unicode characters | -| `Text` | T, C | unicode strings of characters with concatentation `_ # _` | +| `Bool` | L, R | boolean values `true` and `false` and logical operators | +| `Int` | A, R | signed integer values with arithmetic (unbounded)| +| `Int8` | A, R | signed 8-bit integer values with checked arithmetic| +| `Int16` | A, R | signed 16-bit integer values with checked arithmetic| +| `Int32` | A, R | signed 32-bit integer values with checked arithmetic| +| `Int64` | A, R | signed 64-bit integer values with checked arithmetic| +| `Nat` | A, R | non-negative integer values with arithmetic (unbounded)| +| `Nat8` | A, R | non-negative 8-bit integer values with checked arithmetic| +| `Nat16` | A, R | non-negative 16-bit integer values with checked arithmetic| +| `Nat32` | A, R | non-negative 32-bit integer values with checked arithmetic| +| `Nat64` | A, R | non-negative 64-bit integer values with checked arithmetic| +| `Word8` | A, B, R | unsigned 8-bit integers with bitwise operations | +| `Word16` | A, B, R | unsigned 16-bit integers with bitwise operations | +| `Word32` | A, B, R | unsigned 32-bit integers with bitwise operations | +| `Word64` | A, B, R | unsigned 64-bit integers with bitwise operations | +| `Char` | R | Unicode characters | +| `Text` | T, R | Unicode strings of characters with concatenation `_ # _` | | `Error` | | (opaque) error values | ### Type `Bool` -The type `Bool` of sorts L, C (Logical, Comparable) has values `true` and `false` and is supported by one and two branch `if _ (else )?`, `not `, `_ and _` and `_ or _` expressions. Expressions `if`, `and` and `or` are short-circuiting. +The type `Bool` of categories L, R (Logical, Relational) has values `true` and `false` and is supported by one and two branch `if _ (else )?`, `not `, `_ and _` and `_ or _` expressions. Expressions `if`, `and` and `or` are short-circuiting. Comparison TODO. ### Type `Char` -A `Char` of sort C (Comparable) represents characters as a code point in the Unicode character -set. Characters can be converteinhabitd to `Word32`, and `Word32`s in the +A `Char` of category R (Relational) represents characters as a code point in the Unicode character +set. Characters can be converted to `Word32`, and `Word32`s in the range *0 .. 0x1FFFFF* can be converted to `Char` (the conversion traps -if outside of this range). With `singletonText` a character can be +if outside of this range). With `charToText` a character can be converted into a text of length 1. -Comparison TODO. - ### Type `Text` -The type `Text` of sorts T and C ( Text, Comparable) represents sequences of unicode characters (i.e. strings). -Operations on text values include concatenation (`_ # _`) and sequential iteration over characters via `for (c in _) ... c ...`. The `textLength` function returns the number of characters in a `Text` value. +The type `Text` of categories T and R (Text, Relational) represents sequences of Unicode characters (i.e. strings). +Operations on text values include concatenation (`_ # _`) and sequential iteration over characters via `for (c in _) ... c ...`. +The `textLength` function returns the number of characters in a `Text` value. Comparison TODO. ### Type `Int` and `Nat` -The types `Int` and `Nat` are signed integral and natural numbers of sorts A (Arithmetic) and C (omparable). -The usual arithmetic operations of addition `+`, subtraction `-` (which -may trap for `Nat`), multiplication `*`, division `/`, modulus `%` and -exponentiation `**` are available. +The types `Int` and `Nat` are signed integral and natural numbers of categories A (Arithmetic) and R (Relational). +Both `Int` and `Nat` are arbitrary precision, +with only subtraction `-` on `Nat` trapping on underflow. -Additionally, since every inhabitant -of `Nat` is also an inhabitant of `Int`, the subtype relation `Nat <: Int` holds. +The subtype relation `Nat <: Int` holds, so every expression of type 'Nat' is also an expression of type `Int` (but *not* vice versa). +In particular, every value of type `Nat` is also a value of type `Int`, without change of representation. -Both `Int` and `Nat` will be arbitrary precision, -with only subtraction `-` on `Nat` trapping on underflow. +### Bounded Integers `Int8`, `Int16`, `Int32` and `Int64` -Due to subtyping, every value of type `Nat` is also a value of type `Int`, without change of representation. +The types `Int8`, `Int16`, `Int32` and `Int64` represent +signed integers with respectively 8, 16, 32 and 64 bit precision. +All have categories A (Arithmetic) and R (Relational). -> In `asc` compiled wasm code, `Int` and `Nat` values are represented with only 64-bit precision, and operations that would over or underflow trap. -> Moreover, viewing a natural number value as an integer value is only meaning preserving if the value of the natural is between 0 and 2^64-1. TBR +Operations that may under- or overflow the representation are checked and trap on error. -Comparison TODO. +### Bounded Naturals `Nat8`, `Nat16`, `Nat32` and `Nat64` + +The types `Nat8`, `Nat16`, `Nat32` and `Nat64` represent +unsigned integers with respectively 8, 16, 32 and 64 bit precision. +All have categories A (Arithmetic) and R (Relational). + +Operations that may under- or overflow the representation are checked and trap on error. ### Word types The types `Word8`, `Word16`, `Word32` and `Word64` represent fixed-width bit patterns of width *n* (8, 16, 32 and 64). -All word types have sorts A (Arithmetic), B (Bitwise) and C (Comparable). +All word types have categories A (Arithmetic), B (Bitwise) and R (Relational). As arithmetic types, word types implementing numeric wrap-around (modulo *2^n*). As bitwise types, word types support bitwise operations *and* `(&)`, @@ -463,13 +488,13 @@ This prevents programmatic forgery of system errors. (TBR) ## Object types -`actor? { ;* }` specifies an object type by listing its zero or more named *type fields*. +`? { ;* }` specifies an object type by listing its zero or more named *type fields*. Within an object type, the names of fields must be distinct. Object types that differ only in the ordering of the fields are equivalent. -The optional qualifier `actor` constrains the object's fields to be *shared* functions (i.e. messages). +When `?` is `actor`, all fields have `shared` function type (specifying messages). ## Variant types @@ -509,11 +534,11 @@ Promise types typically appear as the result type of a `shared` function that pr `( (( :)? ),* )` specifies the type of a tuple with zero or more ordered components. -The optional identifier ``, naming its components, is for documentation purposes only and cannot be used for component access. In particular, tuple types that differ only in the names of fields are equivalent. +The optional identifier ``, naming its components, is for documentation purposes only and cannot be used for component access. In particular, tuple types that differ only in the names of components are equivalent. ## Any type -Type `Any` is the *top* type, i.e. the super-type of all types, (think Object in Java or C#). All values have type any. +Type `Any` is the *top* type, i.e. the super-type of all types, (think Object in Java or C#). All values have type 'Any'. ## None type @@ -522,7 +547,6 @@ No value has type `None`. As an empty type, `None` can be used to specify the impossible return value of an infinite loop or unconditional trap. - ## Parenthesised type A function that takes an immediate, syntactic tuple of length *n >= 0* as its domain or range is a function that takes (respectively returns) *n* values. @@ -580,12 +604,11 @@ All type parameters declared in a vector are in scope within its bounds. ::= type arguments < ,* > ``` - Type constructors and functions may take type arguments. The number of type arguments must agree with the number of declared type parameters of the function. -Given a vector of type arguments instantiating a vector of type parametbooleaners, +Given a vector of type arguments instantiating a vector of type parameters, each type argument must satisfy the instantiated bounds of the corresponding type parameter. @@ -624,7 +647,7 @@ Two types `T`, `U` are related by subtyping, written `T <: U`, whenever, one of * `T` is a mutable array type `[ var T ]`, `V` is a mutable array type `[ var W ]` and `V == W`. -* `T` is `Null` and `U` is the an option type `? W`. +* `T` is `Null` and `U` is an option type `? W` for some 'W'. * `T` is `? V`, `U` is `? W` and `V <: W`. @@ -672,13 +695,15 @@ A type `T` is *shared* if it is natural float character - unicode text + Unicode text ``` +Literals are constant values. The syntactic validity of a literal depends on the precision of the type at which it is used. + # Expressions ```bnf - ::= + ::= expressions variable literal unary operator @@ -725,6 +750,8 @@ The expression `` evaluates to the value bound to `` in the current eval ## Literals +A literal has type 'T' only when its value is within the prescribed range of values of type 'T'. + The literal (or constant) expression `` evaluates to itself. ## Unary operators @@ -732,7 +759,7 @@ The literal (or constant) expression `` evaluates to itself. The unary operator ` ` has type `T` provided: * `` has type `T`, and -* ``'s sort is a sort of `T`. +* ``'s category is a category of `T`. The unary operator expression ` ` evaluates `exp` to a result. If the result is a value `v`, it returns the result of ` v`. If the result is a trap, it, too, traps. @@ -743,7 +770,7 @@ The binary compound assigment ` ` has type `T` provided: * `` has type `T`, and * `` has type `T`, and -* ``'s sort is a sort of `T`. +* ``'s category is a category of `T`. The binary operator expression ` ` evaluates `exp1` to a result `r1`. If `r1` is `trap`, the expression results in `trap`. @@ -754,11 +781,11 @@ the result of `v1 v2`. ## Relational operators -The relational expression ` ` has type `Bpol` provided: +The relational expression ` ` has type `Bool` provided: * `` has type `T`, and * `` has type `T`, and -* ``'s sort C is a sort of `T`. +* ``'s category R is a category of `T`. The binary operator expression ` ` evaluates `exp1` to a result `r1`. If `r1` is `trap`, the expression results in `trap`. @@ -828,7 +855,7 @@ Otherwise `r1` and `r2` are (respectively) a location `v1` (a mutable identifie The unary compound assignment `= ` has type `()` provided: * `` has type `var T`, and -* ``'s sort is a sort of `T`. +* ``'s category is a category of `T`. The unary compound assignment `= ` evaluates `` to a result `r`. If `r` is 'trap' the evaluation traps, otherwise `r` is a location storing value `v` and `r` is updated to @@ -840,7 +867,7 @@ The binary compound assigment ` = ` has type `()` provided: * `` has type `var T`, and * `` has type `T`, and -* ``'s sort is a sort of `T`. +* ``'s category is a category of `T`. For binary operator ``, ` = `, the compound assignment expression ` = ` evaluates `` to a result `r1`. If `r1` is `trap`, the expression results in `trap`. @@ -853,7 +880,7 @@ Otherwise `r1` and `r2` are (respectively) a location `v1` (a mutable identifie The expression `[ var? ,* ]` has type `[var? T]` provided each expression `` in the sequence `*` has type T. - The array expression `[ var , ..., ]` evaluates the expressions false`exp0` ... `expn` in order, trapping as soon as some expression `` traps. If no evaluation traps and `exp0`, ..., `` evaluate to values `v0`,...,`vn` then the array expression returns the array value `[var? v0, ... , vn]` (of size `n+1`). +The array expression `[ var , ..., ]` evaluates the expressions `exp0` ... `expn` in order, trapping as soon as some expression `` traps. If no evaluation traps and `exp0`, ..., `` evaluate to values `v0`,...,`vn` then the array expression returns the array value `[var? v0, ... , vn]` (of size `n+1`). The array indexing expression ` [ ]` has type `var? T` provided has (mutable or immutable) array type `[var? T1]`. @@ -861,7 +888,7 @@ The projection ` . ` evaluates `exp1` to a result `r1`. If `r1` is ` Otherwise, `exp2` is evaluated to a result `r2`. If `r2` is `trap`, the expression results in `trap`. -Otherwise, `r1` is an array value, `var? [v0, ..., vn]`, and r2 is a natural integer `i`. If 'i > n' the index expression returns `trap`. +Otherwise, `r1` is an array value, `var? [v0, ..., vn]`, and `r2` is a natural integer `i`. If 'i > n' the index expression returns `trap`. Otherwise, the index expression returns the value `v`, obtained as follows: @@ -888,7 +915,10 @@ The call expression ` ? ` evaluates `exp1` to a result `r Otherwise, `exp2` is evaluated to a result `r2`. If `r2` is `trap`, the expression results in `trap`. -Otherwise, `r1` is a function value, `shared? func pat { exp }` (for some implicit environment), and `r2` is a value `v2`. Evaluation continues by matching `v1` against `pat`. If matching succeeds with some bindings, evaluation proceeds with `exp` using the environment of the function value (not shown) extended with those bindings. Otherwise, the pattern match has failed and the call results in `trap`. +Otherwise, `r1` is a function value, `shared? func pat { exp }` (for some implicit environment), and `r2` is a value `v2`. +Evaluation continues by matching `v1` against `pat`. +If matching succeeds with some bindings, evaluation proceeds with `exp` using the environment of the function value (not shown) extended with those bindings. +Otherwise, the pattern match has failed and the call results in `trap`. ## Functions @@ -1055,7 +1085,7 @@ If `` in `label (: )? ` is a looping construct: * `loop (while ())?`, or * `for ( in ` -the body, ``, of the loop is implicitly enclosed in `label (...)` allowing early continuation of loop by the evaluation of expression `continue `. +the body, ``, of the loop is implicitly enclosed in `label (...)` allowing early continuation of the loop by the evaluation of expression `continue `. `` is fresh identifier that can only be referenced by `continue ` (through its implicit expansion to `break `). @@ -1099,12 +1129,10 @@ The async expression `async ` has type `async T` provided: * `` has type `T`; * `T` is shared. -Any control-flow label in scope for `async ` is not in scope for `` (that `` may declare its own, local, labels. +Any control-flow label in scope for `async ` is not in scope for ``. However, +`` may declare and use its own, local, labels. -The implicit return type in `` is `T`. That is, the | `==` | equals | -| `!=` | not equals | -| `<=` | less than or equal | -| `>=` | greater than or equal |return argument, ``, (implicit or explicit) to any enclosed `return ?` expression, must have type `T`. +The implicit return type in `` is `T`. That is, the return expression, ``, (implicit or explicit) to any enclosed `return ?` expression, must have type `T`. Evaluation of `async ` queues a message to evaluate `` in the nearest enclosing or top-level actor. It immediately returns a promise of type `async T` that can be used to `await` the result of the pending evaluation of ``. @@ -1149,7 +1177,7 @@ Note: because the `Error` type is opaque, the pattern match cannot fail (typing The assert expression `assert ` has type `()` provided `exp` has type `Bool`. -Expression `assert ` evaluates `` to a result `r`. If `r` is `trap` evaluation returns `trap`. Otherwise `r` is a boolean value `v`. The result of `assert ` is +Expression `assert ` evaluates `` to a result `r`. If `r` is `trap` evaluation returns `trap`. Otherwise `r` is a boolean value `v`. The result of `assert ` is: * the value `()`, when `v` is `true`; or * `trap`, when `v` is `false`. @@ -1244,14 +1272,16 @@ matching ``, if it succeeds, or the result of matching ``, if the fi # Declarations ```bnf - ::= declaration - expression - let = immutable - var (: )? = mutable - (object|module|actor) ? =? { ;* } object - shared? func ? ? (: )? =? function - type ? = type - obj_sort? class ? (: )? =? { ;* }` class + ::= declaration + expression + let = immutable + var (: )? = mutable + ? =? { ;* } object + shared? func ? ? (: )? =? function + type ? = type + ? class ? (: )? =? { ;* } class + + ``` ```bnf @@ -1311,10 +1341,10 @@ In scope of the declaration `type C < X0<:T0>, ..., Xn <: Tn > = U`, any well- ## Object Declaration -Declaration `(object|module|actor) ? =? { ;* }` declares an object with optional identifier `` and zero or more fields `;*`. +Declaration ` ? =? { ;* }` declares an object with optional identifier `` and zero or more fields `;*`. Fields can be declared with `public` or `private` visibility; if the visibility is omitted, it defaults to `private`. -The qualifier `object|module|actor` specifies the *sort* of the object's type. The sort imposes restrictions on the types of the public object fields. +The qualifier `` (one of 'actor', 'module' or 'object') specifies the *sort* of the object's type. The sort imposes restrictions on the types of the public object fields. Let `T = sort { [var0] id0 : T0, ... , [varn] idn : T0 }` denote the type of the object. Let `;*` be the sequence of declarations in `;*`. @@ -1327,7 +1357,7 @@ The object declaration has type `T` provided that: * `{ id0, ..., idn } == Id_public`, and * for all `i in 0 <= i <= n`, `[vari] Ti == T(idi)`. -Note that requirement 1. imposes further constraints on the fields type of `T`. +Note that requirement 1. imposes further constraints on the field types of `T`. In particular: * if the sort is `actor` then all public fields must be non-`var` (immutable) `shared` functions (the public interface of an actor can only provide asynchronous messaging via shared functions). @@ -1358,18 +1388,16 @@ Named function definitions are recursive. ## Class declarations -The declaration `obj_sort? class ? (: )? =? ? { ;* }` is sugar for pair of a -a type and function declaration: +The declaration `? class ? (: )? =? ? { ;* }` is sugar for pair of a type and function declaration: ```bnf -obj_sort? class ? (: )? =? ? { ;* } := - type = sort { ;* }; - func ? : = sort ? { ;* } +? class ? (: )? =? ? { ;* } := + type = { ;* }; + func ? : = ? { ;* } ``` where: -* `` is `object` if `obj_sort?` is absent or `sort == obj_sort` otherwise. * `?` is the sequence of type identifiers bound by `?` (if any), and * `;*` is the set of public field types inferred from ``. * `?` is the optional `this` parameter of the object instance. @@ -1415,7 +1443,8 @@ conservative static analysis not described here. # Programs ```bnf - ::= ;* + ::= + ;* ``` From 89da0848b637a60e9b9c1949d20a7b9e9e9ac49a Mon Sep 17 00:00:00 2001 From: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> Date: Thu, 26 Sep 2019 10:57:14 +0200 Subject: [PATCH 0413/1176] [ACT-133] Makes pipeline's parse functions configurable (#686) * Makes the parsing function used in the pipeline configurable * adds a test that checks parse errors are being reported * removes unused function * clean up integration test * adds a testcase for transitive modules --- src/languageServer/declaration_index.ml | 7 +++-- src/languageServer/languageServer.ml | 28 +++++------------- src/languageServer/vfs.ml | 20 +++++++++++++ src/languageServer/vfs.mli | 5 ++++ src/pipeline/pipeline.ml | 38 +++++++++++++------------ src/pipeline/pipeline.mli | 7 ++++- test/lsp-int/Main.hs | 35 ++++++++++++++--------- 7 files changed, 84 insertions(+), 56 deletions(-) diff --git a/src/languageServer/declaration_index.ml b/src/languageServer/declaration_index.ml index 26fc6e8728e..19d29ab8586 100644 --- a/src/languageServer/declaration_index.ml +++ b/src/languageServer/declaration_index.ml @@ -161,9 +161,10 @@ let populate_definitions | Some (_, prog) -> List.map (find_def prog.it) decls -let make_index_inner () : declaration_index Diag.result = +let make_index_inner vfs : declaration_index Diag.result = let entry_points = project_files () in Pipeline.chase_imports + (Vfs.parse_file vfs) Pipeline.initial_stat_env (Pipeline__.Resolve_import.S.of_list entry_points) |> Diag.map (fun (libraries, scope) -> @@ -179,6 +180,6 @@ let make_index_inner () : declaration_index Diag.result = scope.Scope.lib_env Index.empty) -let make_index () : declaration_index Diag.result = +let make_index vfs : declaration_index Diag.result = (* TODO(Christoph): Actually handle errors here *) - try make_index_inner () with _ -> Diag.return Index.empty + try make_index_inner vfs with _ -> Diag.return Index.empty diff --git a/src/languageServer/languageServer.ml b/src/languageServer/languageServer.ml index 7491d22ef02..691662831b0 100644 --- a/src/languageServer/languageServer.ml +++ b/src/languageServer/languageServer.ml @@ -86,20 +86,6 @@ let diagnostics_of_message (msg : Diag.message) : Lsp_t.diagnostic = Lsp_t. diagnostic_relatedInformation = None; } -let file_uri_prefix = "file://" ^ Sys.getcwd () ^ "/" -let file_from_uri logger uri = - match Lib.String.chop_prefix file_uri_prefix uri with - | Some file -> file - | None -> - let _ = logger "error" ("Failed to strip filename from: " ^ uri) in - uri -let abs_file_from_uri logger uri = - match Lib.String.chop_prefix "file://" uri with - | Some file -> file - | None -> - let _ = logger "error" ("Failed to strip filename from: " ^ uri) in - uri - let start () = let oc: out_channel = open_out_gen [Open_append; Open_creat] 0o666 "ls.log"; in @@ -113,7 +99,7 @@ let start () = let vfs = ref Vfs.empty in let decl_index = - let ix = match Declaration_index.make_index () with + let ix = match Declaration_index.make_index !vfs with | Error(err) -> Declaration_index.Index.empty | Ok((ix, _)) -> ix in ref ix in @@ -191,7 +177,7 @@ let start () = position file_content project_root - (abs_file_from_uri log_to_file uri) in + (Vfs.abs_file_from_uri log_to_file uri) in response_result_message id result in send_response (Lsp_j.string_of_response_message response); | (Some id, `TextDocumentDefinition params) -> @@ -214,7 +200,7 @@ let start () = position file_content project_root - (abs_file_from_uri log_to_file uri) in + (Vfs.abs_file_from_uri log_to_file uri) in response_result_message id result in send_response (Lsp_j.string_of_response_message response); | (_, `TextDocumentDidOpen params) -> @@ -226,12 +212,12 @@ let start () = | (_, `TextDocumentDidSave params) -> let textDocumentIdent = params.Lsp_t.text_document_did_save_params_textDocument in let uri = textDocumentIdent.Lsp_t.text_document_identifier_uri in - let file_name = file_from_uri log_to_file uri in - let result = Pipeline.check_files [file_name] in + let file_name = Vfs.file_from_uri log_to_file uri in + let result = Pipeline.check_files' (Vfs.parse_file !vfs) [file_name] in let msgs = match result with | Error msgs' -> msgs' | Ok (_, msgs') -> msgs' in - (match Declaration_index.make_index () with + (match Declaration_index.make_index !vfs with | Error(err) -> () | Ok((ix, _)) -> decl_index := ix); let diags = List.map diagnostics_of_message msgs in @@ -267,7 +253,7 @@ let start () = !decl_index log_to_file project_root - (abs_file_from_uri log_to_file uri) + (Vfs.abs_file_from_uri log_to_file uri) file_content position |> response_result_message id in diff --git a/src/languageServer/vfs.ml b/src/languageServer/vfs.ml index 820d219349a..534ec4d9a25 100644 --- a/src/languageServer/vfs.ml +++ b/src/languageServer/vfs.ml @@ -10,6 +10,21 @@ type t = virtual_file VfsStore.t type uri = string +let file_uri_prefix = "file://" ^ Sys.getcwd () ^ "/" +let uri_from_file path = file_uri_prefix ^ path +let file_from_uri logger uri = + match Lib.String.chop_prefix file_uri_prefix uri with + | Some file -> file + | None -> + let _ = logger "error" ("Failed to strip filename from: " ^ uri) in + uri +let abs_file_from_uri logger uri = + match Lib.String.chop_prefix "file://" uri with + | Some file -> file + | None -> + let _ = logger "error" ("Failed to strip filename from: " ^ uri) in + uri + let empty = VfsStore.empty let open_file did_open_params vfs = @@ -99,3 +114,8 @@ and apply_change lines Lsp_t.{ ^ String.sub last ec (String.length last - ec) in prev_lines @ Lib.String.split new_ '\n' @ past_lines + +let parse_file vfs path = + match read_file (uri_from_file path) vfs with + | None -> Pipeline.parse_file path + | Some(file) -> Pipeline.parse_string path file diff --git a/src/languageServer/vfs.mli b/src/languageServer/vfs.mli index 1ceeeaacac7..23b37541533 100644 --- a/src/languageServer/vfs.mli +++ b/src/languageServer/vfs.mli @@ -5,6 +5,11 @@ type t type uri = string (* NOTE(Christoph): Track file version *) +val uri_from_file : string -> uri +val file_from_uri : (string -> string -> 'a) -> uri -> string +val abs_file_from_uri : (string -> string -> 'a) -> uri -> string +val parse_file : t -> Pipeline.parse_fn + (** Creates a new virtual file system *) val empty: t diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index 417507732e6..b85e7d61c76 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -87,6 +87,8 @@ type rel_path = string type parse_result = (Syntax.prog * rel_path) Diag.result +type parse_fn = rel_path -> parse_result + let parse_with mode lexer parse name = try phase "Parsing" name; @@ -101,7 +103,7 @@ let parse_with mode lexer parse name = | Parser.Error -> error (Lexer.region lexer) "syntax" "unexpected token" -let parse_string s name : parse_result = +let parse_string name s : parse_result = let lexer = Lexing.from_string s in let parse = Parser.parse_prog in match parse_with Lexer.Normal lexer parse name with @@ -119,9 +121,6 @@ let parse_file filename : parse_result = | Ok prog -> Diag.return (prog, filename) | Error e -> Error [e] -let parse_files = - Diag.traverse parse_file - (* Import file name resolution *) type resolve_result = (Syntax.prog * Resolve_import.S.t) Diag.result @@ -190,7 +189,7 @@ type load_result = type load_decl_result = (Syntax.libraries * Syntax.prog * Scope.scope * Type.typ * Scope.scope) Diag.result -let chase_imports senv0 imports : (Syntax.libraries * Scope.scope) Diag.result = +let chase_imports parsefn senv0 imports : (Syntax.libraries * Scope.scope) Diag.result = (* This function loads and type-checkes the files given in `imports`, including any further dependencies. @@ -219,7 +218,7 @@ let chase_imports senv0 imports : (Syntax.libraries * Scope.scope) Diag.result = }] else begin pending := add f !pending; - Diag.bind (parse_file f) (fun (prog, base) -> + Diag.bind (parsefn f) (fun (prog, base) -> Diag.bind (Static.prog prog) (fun () -> Diag.bind (Resolve_import.resolve !Flags.package_urls prog base) (fun more_imports -> Diag.bind (go_set more_imports) (fun () -> @@ -235,14 +234,14 @@ let chase_imports senv0 imports : (Syntax.libraries * Scope.scope) Diag.result = in Diag.map (fun () -> (List.rev !libraries, !senv)) (go_set imports) -let load_progs parse senv : load_result = - Diag.bind parse (fun parsed -> +let load_progs parsefn files senv : load_result = + Diag.bind (Diag.traverse parsefn files) (fun parsed -> Diag.bind (resolve_progs parsed) (fun rs -> let progs' = List.map fst rs in let libraries = List.fold_left Resolve_import.S.union Resolve_import.S.empty (List.map snd rs) in - Diag.bind (chase_imports senv libraries) (fun (libraries, senv') -> + Diag.bind (chase_imports parsefn senv libraries) (fun (libraries, senv') -> Diag.bind (typecheck_progs senv' progs') (fun senv'' -> Diag.bind (defindeness_progs progs') (fun _ -> Diag.return (libraries, progs', senv'') @@ -251,7 +250,7 @@ let load_progs parse senv : load_result = let load_decl parse_one senv : load_decl_result = Diag.bind parse_one (fun parsed -> Diag.bind (resolve_prog parsed) (fun (prog, libraries) -> - Diag.bind (chase_imports senv libraries) (fun (libraries, senv') -> + Diag.bind (chase_imports parse_file senv libraries) (fun (libraries, senv') -> Diag.bind (infer_prog senv' prog) (fun (t, sscope) -> let senv'' = Scope.adjoin senv' sscope in Diag.return (libraries, prog, senv'', t, sscope) @@ -291,7 +290,7 @@ let rec interpret_progs denv progs : Interpret.scope option = let interpret_files (senv0, denv0) files : (Scope.scope * Interpret.scope) option = Lib.Option.bind - (Diag.flush_messages (load_progs (parse_files files) senv0)) + (Diag.flush_messages (load_progs parse_file files senv0)) (fun (libraries, progs, senv1) -> let denv1 = interpret_libraries denv0 libraries in match interpret_progs denv1 progs with @@ -339,19 +338,22 @@ let initial_env = (initial_stat_env, initial_dyn_env) type check_result = unit Diag.result +let check_files' parsefn files : check_result = + Diag.map ignore (load_progs parsefn files initial_stat_env) + let check_files files : check_result = - Diag.map ignore (load_progs (parse_files files) initial_stat_env) + check_files' parse_file files let check_string s name : check_result = - Diag.map ignore (load_decl (parse_string s name) initial_stat_env) + Diag.map ignore (load_decl (parse_string name s) initial_stat_env) (* Generate IDL *) let generate_idl files : Idllib.Syntax.prog Diag.result = - Diag.bind (load_progs (parse_files files) initial_stat_env) + Diag.bind (load_progs parse_file files initial_stat_env) (fun (libraries, progs, senv) -> Diag.return (As_idl.As_to_idl.prog (progs, senv))) - + (* Running *) let run_files files : unit option = @@ -510,12 +512,12 @@ let compile_prog mode do_link lib_env libraries progs : Wasm_exts.CustomModule.e Codegen.Compile.compile mode name rts prelude_ir [prog_ir] let compile_files mode do_link files : compile_result = - Diag.bind (load_progs (parse_files files) initial_stat_env) + Diag.bind (load_progs parse_file files initial_stat_env) (fun (libraries, progs, senv) -> Diag.return (compile_prog mode do_link senv.Scope.lib_env libraries progs)) let compile_string mode s name : compile_result = - Diag.bind (load_decl (parse_string s name) initial_stat_env) + Diag.bind (load_decl (parse_string name s) initial_stat_env) (fun (libraries, prog, senv, _t, _sscope) -> Diag.return (compile_prog mode false senv.Scope.lib_env libraries [prog])) @@ -537,4 +539,4 @@ let interpret_ir_prog inp_env libraries progs = let interpret_ir_files files = Lib.Option.map (fun (libraries, progs, senv) -> interpret_ir_prog senv.Scope.lib_env libraries progs) - (Diag.flush_messages (load_progs (parse_files files) initial_stat_env)) + (Diag.flush_messages (load_progs parse_file files initial_stat_env)) diff --git a/src/pipeline/pipeline.mli b/src/pipeline/pipeline.mli index 5eb935d77d5..66dde4622ba 100644 --- a/src/pipeline/pipeline.mli +++ b/src/pipeline/pipeline.mli @@ -20,13 +20,18 @@ sig val profile_field_names : string list ref end +type parse_fn = string -> (Syntax.prog * string) Diag.result +val parse_file: parse_fn +val parse_string: string -> parse_fn + val check_files : string list -> unit Diag.result +val check_files' : parse_fn -> string list -> unit Diag.result val check_string : string -> string -> unit Diag.result val generate_idl : string list -> Idllib.Syntax.prog Diag.result val initial_stat_env : Scope.scope -val chase_imports : Scope.scope -> Resolve_import.S.t -> +val chase_imports : parse_fn -> Scope.scope -> Resolve_import.S.t -> (Syntax.libraries * Scope.scope) Diag.result val run_files : string list -> unit option diff --git a/test/lsp-int/Main.hs b/test/lsp-int/Main.hs index 7d77aa0bf14..bd675560113 100644 --- a/test/lsp-int/Main.hs +++ b/test/lsp-int/Main.hs @@ -8,9 +8,9 @@ import Control.Monad (unless) import Control.Monad.IO.Class (liftIO) import Data.Default import Data.Text (Text) -import Language.Haskell.LSP.Test -import Language.Haskell.LSP.Types (TextDocumentIdentifier(..), Position(..), HoverContents(..), MarkupContent(..), MarkupKind(..), TextEdit(..), Range(..)) -import Language.Haskell.LSP.Types.Lens (contents, label, detail) +import Language.Haskell.LSP.Test hiding (message) +import Language.Haskell.LSP.Types (TextDocumentIdentifier(..), Position(..), HoverContents(..), MarkupContent(..), MarkupKind(..), TextEdit(..), Range(..), DidSaveTextDocumentParams(..), ClientMethod(..)) +import Language.Haskell.LSP.Types.Lens (contents, label, detail, message) import System.Directory (setCurrentDirectory) import System.Environment (getArgs) import Test.Hspec (shouldBe, shouldMatchList) @@ -78,14 +78,23 @@ main = do -- 14 | List.pus| (Position 13 14) [("push",Just "(T, List) -> List")] - pure () - - - --- To make tests involving diagnostics work, we need the compiler --- pipeline to read its files from the VFS + closeDoc doc + doc <- openDoc "ListClient.as" "actorscript" + -- 1 | module { + -- ==> 1 | ule { + let edit = TextEdit (Range (Position 0 1) (Position 0 3)) "" + _ <- applyEdit doc edit + sendNotification TextDocumentDidSave (DidSaveTextDocumentParams doc) + (diagnostic:_) <- waitForDiagnostics + liftIO (diagnostic^.message `shouldBe` "unexpected token") + closeDoc doc --- let edit = TextEdit (Range (Position 1 1) (Position 1 3)) "" --- _ <- applyEdit doc edit --- request_ TextDocumentDidSave (DidSaveTextDocumentParams doc) --- diags <- waitForDiagnostics + -- It finds errors in transitive modules that have been changed in + -- the vfs but not yet stored to disc + doc <- openDoc "ListClient.as" "actorscript" + let edit = TextEdit (Range (Position 0 1) (Position 0 3)) "" + _ <- applyEdit doc edit + appDoc <- openDoc "app.as" "actorscript" + sendNotification TextDocumentDidSave (DidSaveTextDocumentParams appDoc) + (diagnostic:_) <- waitForDiagnostics + liftIO (diagnostic^.message `shouldBe` "unexpected token") From 8a9ab67ec176086689e9cce34dfb2e2e7f6832f6 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Fri, 27 Sep 2019 13:58:10 +0100 Subject: [PATCH 0414/1176] remove noisy test throw.as (#689) --- test/run/ok/throw.diff-low.ok | 10 --- test/run/ok/throw.run-ir.ok | 6 -- test/run/ok/throw.run-low.ok | 1 - test/run/ok/throw.run.ok | 6 -- test/run/ok/throw.wasm.stderr.ok | 1 - test/run/throw.as | 128 ------------------------------- 6 files changed, 152 deletions(-) delete mode 100644 test/run/ok/throw.diff-low.ok delete mode 100644 test/run/ok/throw.run-ir.ok delete mode 100644 test/run/ok/throw.run-low.ok delete mode 100644 test/run/ok/throw.run.ok delete mode 100644 test/run/ok/throw.wasm.stderr.ok delete mode 100644 test/run/throw.as diff --git a/test/run/ok/throw.diff-low.ok b/test/run/ok/throw.diff-low.ok deleted file mode 100644 index 0d77417c49a..00000000000 --- a/test/run/ok/throw.diff-low.ok +++ /dev/null @@ -1,10 +0,0 @@ ---- throw.run -+++ throw.run-low -@@ -1,6 +1 @@ -- -- t1 ok -- t2 ok -- t3 ok -- t4 ok -- t5 ok -+(unknown location): execution error, assertion failure diff --git a/test/run/ok/throw.run-ir.ok b/test/run/ok/throw.run-ir.ok deleted file mode 100644 index 5c38b98138f..00000000000 --- a/test/run/ok/throw.run-ir.ok +++ /dev/null @@ -1,6 +0,0 @@ - - t1 ok - t2 ok - t3 ok - t4 ok - t5 ok diff --git a/test/run/ok/throw.run-low.ok b/test/run/ok/throw.run-low.ok deleted file mode 100644 index aa7af77560b..00000000000 --- a/test/run/ok/throw.run-low.ok +++ /dev/null @@ -1 +0,0 @@ -(unknown location): execution error, assertion failure diff --git a/test/run/ok/throw.run.ok b/test/run/ok/throw.run.ok deleted file mode 100644 index 5c38b98138f..00000000000 --- a/test/run/ok/throw.run.ok +++ /dev/null @@ -1,6 +0,0 @@ - - t1 ok - t2 ok - t3 ok - t4 ok - t5 ok diff --git a/test/run/ok/throw.wasm.stderr.ok b/test/run/ok/throw.wasm.stderr.ok deleted file mode 100644 index ff36ca0e2f6..00000000000 --- a/test/run/ok/throw.wasm.stderr.ok +++ /dev/null @@ -1 +0,0 @@ -Fatal error: exception "Assert_failure codegen/compile.ml:4844:18" diff --git a/test/run/throw.as b/test/run/throw.as deleted file mode 100644 index 382403982ef..00000000000 --- a/test/run/throw.as +++ /dev/null @@ -1,128 +0,0 @@ -shared func t1() : async () { - throw error("t1"); - assert false; -}; - -shared func t2() : async () { - try { - throw error("t2"); - assert(false); - } catch e { - switch (errorCode(e), errorMessage(e)) { - case (#error, "t1") { assert false;}; - case (#system, _) { assert false;}; - case (#error, _) { assert true;}; - } - } -}; - -shared func t3() : async () { - try { - try { - throw error("t3"); - assert(false); - } catch e1 { - switch (errorCode(e1), errorMessage(e1)) { - case (#error, "t3") { throw error("t31");}; - case (#system, _) {assert false;}; - case (#error, _) { assert false;}; - } - } - } catch e2 { - switch (errorCode(e2), errorMessage(e2)) { - case (#error, "t31") { assert true;}; - case (#system, _ ) { assert false;}; - case (#error, _) { assert false;}; - } - } -}; - -shared func t4() : async () { - try { - try { - throw error("t4"); - assert(false); - } catch e1 { - switch (errorCode(e1), errorMessage(e1)) { - case (#error, "t4") { throw error("t41");}; - case (#system, _) { assert false;}; - case (#error, _) { assert false;}; - } - } - } catch e2 { - switch (errorCode(e2), errorMessage(e2)) { - case (#error, "t41") { throw error("t42");}; - case (#system, _ ) { assert false;}; - case (#error, _ ) { assert false;}; - } - } -}; - - -shared func t5() : async () { - try { - try { - throw error("t5"); - assert(false); - } catch e1 { - switch (errorCode(e1), errorMessage(e1)) { - case (#system, _ ) { assert false;}; - case _ { throw e1; } - } - } - } catch e2 { - switch (errorCode(e2), errorMessage(e2)) { - case (#error, "t5") { throw error("t51");}; - case (#system, _ ) { assert false;}; - case (#error, _ ) { assert false;}; - } - } -}; - -async { - - try { - await t1(); - assert false; - } catch e { - switch (errorCode(e), errorMessage(e)) { - case (#error, "t1") { print ("\n t1 ok")}; - case _ { assert false; } - } - }; - - try { - await t2(); - print ("\n t2 ok"); - } catch _ { - assert false; - }; - - try { - await t3(); - print ("\n t3 ok"); - } catch _ { - assert false; - }; - - try { - await t4(); - assert false; - } catch e { - switch (errorCode(e), errorMessage(e)) { - case (#error, "t42") { print ("\n t4 ok"); }; - case _ { assert false; }; - } - }; - - try { - await t5(); - assert false; - } catch e { - switch (errorCode(e), errorMessage(e)) { - case (#error, "t51") { print ("\n t5 ok"); }; - case _ { assert false; }; - } - }; - -}; From 26033b9e8455a229388566a58213c17e57d4fcdc Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 27 Sep 2019 15:30:10 +0200 Subject: [PATCH 0415/1176] RTS: Prefix idl errors with "Idl error:" (#696) * RTS: Prefix idl errors with "Idl error:" * Use sizeof, not strlen --- rts/rts.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/rts/rts.c b/rts/rts.c index ffa8f0db029..98a02a95c49 100644 --- a/rts/rts.c +++ b/rts/rts.c @@ -30,7 +30,12 @@ as_ptr as_str_of_cstr(const char * const s) { } void idl_trap_with(const char *str) { - idl_trap(str, as_strlen(str)); + const char prefix[] = "IDL error: "; + int len = as_strlen(str); + char msg[sizeof prefix + len]; + as_memcpy(msg, prefix, sizeof prefix - 1); + as_memcpy(msg + sizeof prefix - 1, str, len); + idl_trap(msg, sizeof prefix - 1 + len); } From 97a77eb958e0d5c82201fd5e135e8fea2ac669b3 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Fri, 27 Sep 2019 21:18:39 +0200 Subject: [PATCH 0416/1176] Implement debug expressions (#684) * implement debug blocks (ACT-118) * adds tests for release mode * factor out flags into library as_config --- src/as_config/dune | 3 ++ src/as_config/flags.ml | 18 +++++++ src/as_def/arrange.ml | 1 + src/as_def/syntax.ml | 1 + src/as_frontend/definedness.ml | 1 + src/as_frontend/effect.ml | 2 + src/as_frontend/lexer.mll | 3 +- src/as_frontend/parser.mly | 4 +- src/as_frontend/static.ml | 1 + src/as_frontend/typing.ml | 3 ++ src/as_interpreter/dune | 2 +- src/as_interpreter/interpret.ml | 5 +- src/exes/asc.ml | 49 +++++++++++-------- src/lowering/desugar.ml | 1 + src/lowering/dune | 2 +- src/pipeline/dune | 1 + src/pipeline/pipeline.ml | 20 +------- src/pipeline/pipeline.mli | 19 ------- src/pipeline/resolve_import.ml | 2 + .../examples/produce-exchange/serverModel.as | 10 ++-- test/Makefile | 5 ++ test/fail/debug.as | 1 + test/fail/ok/debug.tc.ok | 4 ++ test/run-release/Makefile | 12 +++++ test/run-release/debug.as | 4 ++ test/run-release/ok/debug.run-ir.ok | 2 + test/run-release/ok/debug.run-low.ok | 2 + test/run-release/ok/debug.run.ok | 2 + test/run.sh | 8 ++- test/run/debug.as | 1 + test/run/ok/debug.run-ir.ok | 1 + test/run/ok/debug.run-low.ok | 1 + test/run/ok/debug.run.ok | 1 + 33 files changed, 123 insertions(+), 69 deletions(-) create mode 100644 src/as_config/dune create mode 100644 src/as_config/flags.ml create mode 100644 test/fail/debug.as create mode 100644 test/fail/ok/debug.tc.ok create mode 100644 test/run-release/Makefile create mode 100644 test/run-release/debug.as create mode 100644 test/run-release/ok/debug.run-ir.ok create mode 100644 test/run-release/ok/debug.run-low.ok create mode 100644 test/run-release/ok/debug.run.ok create mode 100644 test/run/debug.as create mode 100644 test/run/ok/debug.run-ir.ok create mode 100644 test/run/ok/debug.run-low.ok create mode 100644 test/run/ok/debug.run.ok diff --git a/src/as_config/dune b/src/as_config/dune new file mode 100644 index 00000000000..af688334322 --- /dev/null +++ b/src/as_config/dune @@ -0,0 +1,3 @@ +(library + (name as_config) +) diff --git a/src/as_config/flags.ml b/src/as_config/flags.ml new file mode 100644 index 00000000000..1727d14fab2 --- /dev/null +++ b/src/as_config/flags.ml @@ -0,0 +1,18 @@ +(* common flags for the asc compiler *) + +let trace = ref false +let verbose = ref false +let print_depth = ref 2 +let release_mode = ref false +let await_lowering = ref true +let async_lowering = ref true +let dump_parse = ref false +let dump_tc = ref false +let dump_lowering = ref false +let check_ir = ref true +let package_urls : (string * string) list ref = ref [] +let profile = ref false +let profile_verbose = ref false +let profile_file = ref "profiling-counters.csv" +let profile_line_prefix = ref "" +let profile_field_names : string list ref = ref [] diff --git a/src/as_def/arrange.ml b/src/as_def/arrange.ml index 5f106d01e18..3f979abdc0e 100644 --- a/src/as_def/arrange.ml +++ b/src/as_def/arrange.ml @@ -46,6 +46,7 @@ let rec exp e = match e.it with | LoopE (e1, Some e2) -> "LoopE" $$ [exp e1; exp e2] | ForE (p, e1, e2) -> "ForE" $$ [pat p; exp e1; exp e2] | LabelE (i, t, e) -> "LabelE" $$ [id i; typ t; exp e] + | DebugE e -> "DebugE" $$ [exp e] | BreakE (i, e) -> "BreakE" $$ [id i; exp e] | RetE e -> "RetE" $$ [exp e] | AsyncE e -> "AsyncE" $$ [exp e] diff --git a/src/as_def/syntax.ml b/src/as_def/syntax.ml index 8051c976e28..918e20f6c29 100644 --- a/src/as_def/syntax.ml +++ b/src/as_def/syntax.ml @@ -140,6 +140,7 @@ and exp' = | LabelE of id * typ * exp (* label *) | BreakE of id * exp (* break *) | RetE of exp (* return *) + | DebugE of exp (* debugging *) | AsyncE of exp (* async *) | AwaitE of exp (* await *) | AssertE of exp (* assertion *) diff --git a/src/as_frontend/definedness.ml b/src/as_frontend/definedness.ml index aba9354c4ef..6b73501f691 100644 --- a/src/as_frontend/definedness.ml +++ b/src/as_frontend/definedness.ml @@ -118,6 +118,7 @@ let rec exp msgs e : f = match e.it with | LoopE (e1, Some e2) -> exps msgs [e1; e2] | ForE (p, e1, e2) -> exp msgs e1 ++ (exp msgs e2 /// pat msgs p) | LabelE (i, t, e) -> exp msgs e + | DebugE e -> exp msgs e | AsyncE e -> exp msgs e | AwaitE e -> exp msgs e | AssertE e -> exp msgs e diff --git a/src/as_frontend/effect.ml b/src/as_frontend/effect.ml index e1664a56fb3..c4f3c347231 100644 --- a/src/as_frontend/effect.ml +++ b/src/as_frontend/effect.ml @@ -62,6 +62,8 @@ let rec infer_effect_exp (exp:Syntax.exp) : T.eff = let t1 = effect_exp exp1 in let t2 = effect_exp exp2 in max_eff t1 t2 + | DebugE exp1 -> + effect_exp exp1 | TupE exps | ArrayE (_, exps) -> let es = List.map effect_exp exps in diff --git a/src/as_frontend/lexer.mll b/src/as_frontend/lexer.mll index 1ce617e577c..87431f8722c 100644 --- a/src/as_frontend/lexer.mll +++ b/src/as_frontend/lexer.mll @@ -194,7 +194,7 @@ rule token mode = parse | "catch" { CATCH } | "class" { CLASS } | "continue" { CONTINUE } - | "label" { LABEL } + | "debug" { DEBUG } | "else" { ELSE } | "false" { BOOL false } | "for" { FOR } @@ -207,6 +207,7 @@ rule token mode = parse | "null" { NULL } | "object" { OBJECT } | "or" { OR } + | "label" { LABEL } | "let" { LET } | "loop" { LOOP } | "private" { PRIVATE } diff --git a/src/as_frontend/parser.mly b/src/as_frontend/parser.mly index 7de19fe6dba..8f1bb158e2d 100644 --- a/src/as_frontend/parser.mly +++ b/src/as_frontend/parser.mly @@ -95,7 +95,7 @@ let share_expfield (ef : exp_field) = %token LET VAR %token LPAR RPAR LBRACKET RBRACKET LCURLY RCURLY -%token AWAIT ASYNC BREAK CASE CATCH CONTINUE LABEL +%token AWAIT ASYNC BREAK CASE CATCH CONTINUE LABEL DEBUG %token IF IN ELSE SWITCH LOOP WHILE FOR RETURN TRY THROW %token ARROW ASSIGN %token FUNC TYPE OBJECT ACTOR CLASS PUBLIC PRIVATE SHARED @@ -458,6 +458,8 @@ exp_nondec(B) : | CONTINUE x=id { let x' = ("continue " ^ x.it) @@ x.at in BreakE(x', TupE([]) @? no_region) @? at $sloc } + | DEBUG e=exp(bl) + { DebugE(e) @? at $sloc } | IF b=exp_nullary(ob) e1=exp(bl) %prec IF_NO_ELSE { IfE(b, e1, TupE([]) @? no_region) @? at $sloc } | IF b=exp_nullary(ob) e1=exp(bl) ELSE e2=exp(bl) diff --git a/src/as_frontend/static.ml b/src/as_frontend/static.ml index 494b6e1e635..056a7bf8cc0 100644 --- a/src/as_frontend/static.ml +++ b/src/as_frontend/static.ml @@ -71,6 +71,7 @@ let rec exp m e = match e.it with | OrE _ | WhileE _ | ForE _ + | DebugE _ | IfE _ | SwitchE _ | ThrowE _ diff --git a/src/as_frontend/typing.ml b/src/as_frontend/typing.ml index 78765c96490..16cf951b801 100644 --- a/src/as_frontend/typing.ml +++ b/src/as_frontend/typing.ml @@ -779,6 +779,9 @@ and infer_exp'' env exp : T.typ = let t = check_typ env typ in if not env.pre then check_exp (add_lab env id.it t) t exp1; t + | DebugE exp1 -> + if not env.pre then check_exp env T.unit exp1; + T.unit | BreakE (id, exp1) -> (match T.Env.find_opt id.it env.labs with | Some t -> diff --git a/src/as_interpreter/dune b/src/as_interpreter/dune index c23e20322d8..a42874c2048 100644 --- a/src/as_interpreter/dune +++ b/src/as_interpreter/dune @@ -1,4 +1,4 @@ (library (name as_interpreter) - (libraries lib as_def as_types as_values profiler) + (libraries lib as_config as_def as_types as_values profiler) ) diff --git a/src/as_interpreter/interpret.ml b/src/as_interpreter/interpret.ml index 3da5d9dcbc9..7d7ae3c503f 100644 --- a/src/as_interpreter/interpret.ml +++ b/src/as_interpreter/interpret.ml @@ -364,7 +364,6 @@ let check_call_conv_arg env exp v call_conv = (string_of_val env v) ) - let rec interpret_exp env exp (k : V.value V.cont) = interpret_exp_mut env exp (function V.Mut r -> k !r | v -> k v) @@ -551,6 +550,8 @@ and interpret_exp_mut env exp (k : V.value V.cont) = interpret_exp env' exp1 k | BreakE (id, exp1) -> interpret_exp env exp1 (find id.it env.labs) + | DebugE exp1 -> + if !As_config.Flags.release_mode then k V.unit else interpret_exp env exp1 k | RetE exp1 -> interpret_exp env exp1 (Lib.Option.value env.rets) | ThrowE exp1 -> @@ -880,6 +881,8 @@ let interpret_prog flags scope p : (V.value * scope) option = None +(* Libraries *) + let interpret_library flags scope (filename, p) : scope = let env = env_of_scope flags scope in trace_depth := 0; diff --git a/src/exes/asc.ml b/src/exes/asc.ml index 856572ecac1..c70ef64cc07 100644 --- a/src/exes/asc.ml +++ b/src/exes/asc.ml @@ -1,4 +1,5 @@ open Wasm_exts +open As_config open Printf @@ -35,35 +36,35 @@ let argspec = Arg.align "-i", Arg.Unit (set_mode Interact), " run interactive REPL (implies -r)"; "--check", Arg.Unit (set_mode Check), " type-check only"; "--idl", Arg.Unit (set_mode Idl), " generate IDL spec"; - "-v", Arg.Set Pipeline.Flags.verbose, " verbose output"; - "-p", Arg.Set_int Pipeline.Flags.print_depth, " set print depth"; + "-v", Arg.Set Flags.verbose, " verbose output"; + "-p", Arg.Set_int Flags.print_depth, " set print depth"; "-o", Arg.Set_string out_file, " output file"; "--version", Arg.Unit (fun () -> printf "%s\n%!" banner; exit 0), " show version"; "--map", Arg.Set gen_source_map, " output source map"; - "-t", Arg.Set Pipeline.Flags.trace, " activate tracing"; + "-t", Arg.Set Flags.trace, " activate tracing"; "--package", (let package_name_ref = ref "DEADBEEF" in Arg.Tuple [ Arg.Set_string package_name_ref ; Arg.String begin fun package_url -> (* push (package_name, package_url) onto the list. *) - Pipeline.Flags.package_urls := ( + Flags.package_urls := ( !package_name_ref, package_url - ) :: ! Pipeline.Flags.package_urls + ) :: ! Flags.package_urls end ]), " Specify a package-name-package-URL pair, separated by a space" ; - "--profile", Arg.Set Pipeline.Flags.profile, " activate profiling counters in interpreters "; - "--profile-file", Arg.Set_string Pipeline.Flags.profile_file, " set profiling output file "; - "--profile-line-prefix", Arg.Set_string Pipeline.Flags.profile_line_prefix, " prefix each profile line with the given string "; + "--profile", Arg.Set Flags.profile, " activate profiling counters in interpreters "; + "--profile-file", Arg.Set_string Flags.profile_file, " set profiling output file "; + "--profile-line-prefix", Arg.Set_string Flags.profile_line_prefix, " prefix each profile line with the given string "; "--profile-field", - Arg.String (fun n -> Pipeline.Flags.(profile_field_names := n :: !profile_field_names)), + Arg.String (fun n -> Flags.(profile_field_names := n :: !profile_field_names)), " profile file includes the given field from the program result "; "-iR", Arg.Set interpret_ir, " interpret the lowered code"; - "-no-await", Arg.Clear Pipeline.Flags.await_lowering, " no await-lowering (with -iR)"; - "-no-async", Arg.Clear Pipeline.Flags.async_lowering, " no async-lowering (with -iR)"; + "-no-await", Arg.Clear Flags.await_lowering, " no await-lowering (with -iR)"; + "-no-async", Arg.Clear Flags.async_lowering, " no async-lowering (with -iR)"; "-no-link", Arg.Clear link, " do not statically link-in runtime"; "-no-system-api", @@ -75,10 +76,18 @@ let argspec = Arg.align "-multi-value", Arg.Set Codegen.Flags.multi_value, " use multi-value extension"; "-no-multi-value", Arg.Clear Codegen.Flags.multi_value, " avoid multi-value extension"; - "-dp", Arg.Set Pipeline.Flags.dump_parse, " dump parse"; - "-dt", Arg.Set Pipeline.Flags.dump_tc, " dump type-checked AST"; - "-dl", Arg.Set Pipeline.Flags.dump_lowering, " dump intermediate representation "; - "-no-check-ir", Arg.Clear Pipeline.Flags.check_ir, " do not check intermediate code"; + "-dp", Arg.Set Flags.dump_parse, " dump parse"; + "-dt", Arg.Set Flags.dump_tc, " dump type-checked AST"; + "-dl", Arg.Set Flags.dump_lowering, " dump intermediate representation "; + "-no-check-ir", Arg.Clear Flags.check_ir, " do not check intermediate code"; + "--release", + Arg.Unit + (fun () -> Flags.release_mode := true), + " ignore debug expressions in source"; + "--debug", + Arg.Unit + (fun () -> Flags.release_mode := false), + " respect debug expressions in source (the default)"; ] @@ -134,11 +143,11 @@ let process_files files : unit = https://github.com/dfinity-lab/actorscript/pull/405#issuecomment-503326551 *) let process_profiler_flags () = - ProfilerFlags.profile := !Pipeline.Flags.profile; - ProfilerFlags.profile_verbose := !Pipeline.Flags.profile_verbose; - ProfilerFlags.profile_file := !Pipeline.Flags.profile_file; - ProfilerFlags.profile_line_prefix := !Pipeline.Flags.profile_line_prefix; - ProfilerFlags.profile_field_names := !Pipeline.Flags.profile_field_names; + ProfilerFlags.profile := !Flags.profile; + ProfilerFlags.profile_verbose := !Flags.profile_verbose; + ProfilerFlags.profile_file := !Flags.profile_file; + ProfilerFlags.profile_line_prefix := !Flags.profile_line_prefix; + ProfilerFlags.profile_field_names := !Flags.profile_field_names; () let () = diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index c3c56b90818..ebdbf711852 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -130,6 +130,7 @@ and exp' at note = function | S.LoopE (e1, None) -> I.LoopE (exp e1) | S.LoopE (e1, Some e2) -> (loopWhileE (exp e1) (exp e2)).it | S.ForE (p, e1, e2) -> (forE (pat p) (exp e1) (exp e2)).it + | S.DebugE e -> if !As_config.Flags.release_mode then I.TupE [] else (exp e).it | S.LabelE (l, t, e) -> I.LabelE (l.it, t.Source.note, exp e) | S.BreakE (l, e) -> I.BreakE (l.it, exp e) | S.RetE e -> I.RetE (exp e) diff --git a/src/lowering/dune b/src/lowering/dune index 617ce491e6c..c8ab0651e29 100644 --- a/src/lowering/dune +++ b/src/lowering/dune @@ -1,4 +1,4 @@ (library (name lowering) - (libraries lib as_def ir_def) + (libraries lib as_config as_def ir_def) ) diff --git a/src/pipeline/dune b/src/pipeline/dune index c3970d24518..0b8e5414e2b 100644 --- a/src/pipeline/dune +++ b/src/pipeline/dune @@ -4,6 +4,7 @@ lib lang_utils as_def + as_config as_types as_values as_frontend diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index b85e7d61c76..195265378f6 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -6,6 +6,7 @@ open As_interpreter open Ir_def open Ir_interpreter open Ir_passes +open As_config open Printf @@ -13,25 +14,6 @@ type stat_env = Scope.t type dyn_env = Interpret.scope type env = stat_env * dyn_env -module Flags = struct - let trace = ref false - let verbose = ref false - let print_depth = ref 2 - let await_lowering = ref true - let async_lowering = ref true - let dump_parse = ref false - let dump_tc = ref false - let dump_lowering = ref false - let check_ir = ref true - let package_urls : (string * string) list ref = ref [] - let profile = ref false - let profile_verbose = ref false - let profile_file = ref "profiling-counters.csv" - let profile_line_prefix = ref "" - let profile_field_names : string list ref = ref [] -end (* Flags *) - - (* Diagnostics *) let phase heading name = diff --git a/src/pipeline/pipeline.mli b/src/pipeline/pipeline.mli index 66dde4622ba..d292c67a694 100644 --- a/src/pipeline/pipeline.mli +++ b/src/pipeline/pipeline.mli @@ -1,25 +1,6 @@ open As_def open As_types -module Flags : -sig - val trace : bool ref - val verbose : bool ref - val print_depth : int ref - val await_lowering : bool ref - val async_lowering : bool ref - val dump_parse : bool ref - val dump_tc : bool ref - val dump_lowering : bool ref - val check_ir : bool ref - val package_urls : (string * string) list ref - val profile : bool ref - val profile_verbose : bool ref - val profile_file : string ref - val profile_line_prefix : string ref - val profile_field_names : string list ref -end - type parse_fn = string -> (Syntax.prog * string) Diag.result val parse_file: parse_fn val parse_string: string -> parse_fn diff --git a/src/pipeline/resolve_import.ml b/src/pipeline/resolve_import.ml index 76a4202d545..9e26e301654 100644 --- a/src/pipeline/resolve_import.ml +++ b/src/pipeline/resolve_import.ml @@ -170,6 +170,8 @@ let rec | LoopE (exp1, Some exp2) | ForE (_, exp1, exp2) -> exp env exp1; exp env exp2 + | DebugE exp1 -> + exp env exp1 | TupE exps | ArrayE (_, exps) -> List.iter (exp env) exps diff --git a/stdlib/examples/produce-exchange/serverModel.as b/stdlib/examples/produce-exchange/serverModel.as index eed7ebf3d9e..5ac6d4e9ba6 100644 --- a/stdlib/examples/produce-exchange/serverModel.as +++ b/stdlib/examples/produce-exchange/serverModel.as @@ -601,12 +601,12 @@ public class Model() { ================== */ - func debug (t:Text) { print t }; - func debugInt (i:Int) { printInt i }; + func debugOut (t:Text) { debug { print t } }; + func debugInt (i:Int) { debug { printInt i } }; - func debugOff (t:Text) { }; - func debugIntOff (i:Int) { }; - func debugOffInt (i:Int) { }; + func debugOff (t:Text) { debug { } }; + func debugIntOff (i:Int) { debug { } }; + func debugOffInt (i:Int) { debug { } }; func idIsEq(x:Nat,y:Nat):Bool { x == y }; diff --git a/test/Makefile b/test/Makefile index 9910ef1c9a8..6291a5b30d5 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,6 +1,7 @@ all: $(MAKE) -C fail $(MAKE) -C run + $(MAKE) -C run-release $(MAKE) -C run-dfinity $(MAKE) -C run-drun $(MAKE) -C repl @@ -14,6 +15,7 @@ MAKE_PAR := $(MAKE) --no-print-directory --load-average -j $(shell getconf _NPRO quick: $(MAKE_PAR) -C fail quick $(MAKE_PAR) -C run quick + $(MAKE_PAR) -C run-release quick $(MAKE_PAR) -C repl quick $(MAKE_PAR) -C ld quick $(MAKE_PAR) -C idl quick @@ -31,6 +33,7 @@ coverage: export SKIP_RUNNING=yes; \ $(MAKE) -C fail; \ $(MAKE) -C run; \ + $(MAKE) -C run-release; \ $(MAKE) -C run-dfinity; \ $(MAKE) -C run-drun; \ $(MAKE) -C repl; @@ -41,6 +44,7 @@ coverage: accept: $(MAKE) -C fail accept $(MAKE) -C run accept + $(MAKE) -C run-release accept $(MAKE) -C run-dfinity accept $(MAKE) -C run-drun accept $(MAKE) -C repl accept @@ -53,6 +57,7 @@ accept: clean: $(MAKE) -C fail clean $(MAKE) -C run clean + $(MAKE) -C run-release clean $(MAKE) -C run-dfinity clean $(MAKE) -C run-drun clean $(MAKE) -C repl clean diff --git a/test/fail/debug.as b/test/fail/debug.as new file mode 100644 index 00000000000..1cc1c1c1c36 --- /dev/null +++ b/test/fail/debug.as @@ -0,0 +1 @@ +debug { 42 }; // error: result Int diff --git a/test/fail/ok/debug.tc.ok b/test/fail/ok/debug.tc.ok new file mode 100644 index 00000000000..70d2b72adaf --- /dev/null +++ b/test/fail/ok/debug.tc.ok @@ -0,0 +1,4 @@ +debug.as:1.9-1.11: type error, literal of type + Nat +does not have expected type + () diff --git a/test/run-release/Makefile b/test/run-release/Makefile new file mode 100644 index 00000000000..135924dae80 --- /dev/null +++ b/test/run-release/Makefile @@ -0,0 +1,12 @@ +RUNFLAGS = -r + +all: + ../run.sh $(RUNFLAGS) *.as + +accept: + ../run.sh $(RUNFLAGS) -a *.as + +clean: + rm -rf _out + +include ../*.mk diff --git a/test/run-release/debug.as b/test/run-release/debug.as new file mode 100644 index 00000000000..f52dc765b48 --- /dev/null +++ b/test/run-release/debug.as @@ -0,0 +1,4 @@ +print "This should appear\n"; +debug { print "This shouldn't appear\n" }; +print "This should appear too\n"; + diff --git a/test/run-release/ok/debug.run-ir.ok b/test/run-release/ok/debug.run-ir.ok new file mode 100644 index 00000000000..f5e5eab0d0a --- /dev/null +++ b/test/run-release/ok/debug.run-ir.ok @@ -0,0 +1,2 @@ +This should appear +This should appear too diff --git a/test/run-release/ok/debug.run-low.ok b/test/run-release/ok/debug.run-low.ok new file mode 100644 index 00000000000..f5e5eab0d0a --- /dev/null +++ b/test/run-release/ok/debug.run-low.ok @@ -0,0 +1,2 @@ +This should appear +This should appear too diff --git a/test/run-release/ok/debug.run.ok b/test/run-release/ok/debug.run.ok new file mode 100644 index 00000000000..f5e5eab0d0a --- /dev/null +++ b/test/run-release/ok/debug.run.ok @@ -0,0 +1,2 @@ +This should appear +This should appear too diff --git a/test/run.sh b/test/run.sh index 97de087562c..5275bb4305d 100755 --- a/test/run.sh +++ b/test/run.sh @@ -11,6 +11,7 @@ # -2: Use IC API # -s: Be silent in sunny-day execution # -i: Only check as to idl generation +# -r: Activate release mode (eliminate `debug` blocks) # function realpath() { @@ -21,6 +22,7 @@ function realpath() { ACCEPT=no API=wasm IDL=no +RELEASE=no EXTRA_ASC_FLAGS= ASC=${ASC:-$(realpath $(dirname $0)/../src/asc)} AS_LD=${AS_LD:-$(realpath $(dirname $0)/../src/as-ld)} @@ -32,7 +34,7 @@ DRUN_WRAPPER=$(realpath $(dirname $0)/drun-wrapper.sh) JSCLIENT=${JSCLIENT:-$(realpath $(dirname $0)/../../dev/experimental/js-dfinity-client)} ECHO=echo -while getopts "a12si" o; do +while getopts "a12sir" o; do case "${o}" in a) ACCEPT=yes @@ -49,11 +51,15 @@ while getopts "a12si" o; do i) IDL=yes ;; + r) + RELEASE=yes + ;; esac done if [ $API = "wasm" ]; then EXTRA_ASC_FLAGS=-no-system-api; fi if [ $API = "ancient" ]; then EXTRA_ASC_FLAGS=-ancient-system-api; fi +if [ $RELEASE = "yes" ]; then ASC_FLAGS=--release; fi shift $((OPTIND-1)) diff --git a/test/run/debug.as b/test/run/debug.as new file mode 100644 index 00000000000..b0b3281f042 --- /dev/null +++ b/test/run/debug.as @@ -0,0 +1 @@ +debug { print "This is for debugging only" }; // okay: result () diff --git a/test/run/ok/debug.run-ir.ok b/test/run/ok/debug.run-ir.ok new file mode 100644 index 00000000000..dfe5154ed76 --- /dev/null +++ b/test/run/ok/debug.run-ir.ok @@ -0,0 +1 @@ +This is for debugging only diff --git a/test/run/ok/debug.run-low.ok b/test/run/ok/debug.run-low.ok new file mode 100644 index 00000000000..dfe5154ed76 --- /dev/null +++ b/test/run/ok/debug.run-low.ok @@ -0,0 +1 @@ +This is for debugging only diff --git a/test/run/ok/debug.run.ok b/test/run/ok/debug.run.ok new file mode 100644 index 00000000000..dfe5154ed76 --- /dev/null +++ b/test/run/ok/debug.run.ok @@ -0,0 +1 @@ +This is for debugging only From 3b1172cd69cb50b196067525dcee0639af7d2102 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Sat, 28 Sep 2019 00:22:59 +0200 Subject: [PATCH 0417/1176] IDL Variant decoding: Make use of type description (#697) --- src/codegen/compile.ml | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index a6297230f89..d94b998dadb 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -3989,24 +3989,36 @@ module Serialization = struct ) | Variant vs -> with_composite_typ (-21l) (fun get_typ_buf -> - ReadBuf.read_leb128 env get_typ_buf ^^ G.i Drop ^^ + (* Find the tag *) + let (set_n, get_n) = new_local env "len" in + ReadBuf.read_leb128 env get_typ_buf ^^ set_n ^^ - let (set_tag, get_tag) = new_local env "tag" in - ReadBuf.read_leb128 env get_data_buf ^^ set_tag ^^ + let (set_tagidx, get_tagidx) = new_local env "tagidx" in + ReadBuf.read_leb128 env get_data_buf ^^ set_tagidx ^^ - let (set_idltyp, get_idltyp) = new_local env "idltyp" in - List.fold_right (fun (i, {lab = l; typ = t}) continue -> - (* type desc for this variant *) + get_tagidx ^^ get_n ^^ + G.i (Compare (Wasm.Values.I32 I32Op.LtU)) ^^ + E.else_trap_with env "IDL error: variant index out of bounds" ^^ + + (* Zoom past the previous entries *) + get_tagidx ^^ from_0_to_n env (fun _ -> ReadBuf.read_leb128 env get_typ_buf ^^ G.i Drop ^^ - ReadBuf.read_sleb128 env get_typ_buf ^^ set_idltyp ^^ + ReadBuf.read_sleb128 env get_typ_buf ^^ G.i Drop + ) ^^ + + (* Now read the tag *) + let (set_tag, get_tag) = new_local env "tag" in + ReadBuf.read_leb128 env get_typ_buf ^^ set_tag ^^ + let (set_idltyp, get_idltyp) = new_local env "idltyp" in + ReadBuf.read_sleb128 env get_typ_buf ^^ set_idltyp ^^ - get_tag ^^ - compile_eq_const (Int32.of_int i) ^^ + List.fold_right (fun (h, {lab = l; typ = t}) continue -> + get_tag ^^ compile_eq_const (Lib.Uint32.to_int32 h) ^^ G.if_ (ValBlockType (Some I32Type)) ( Variant.inject env l (get_idltyp ^^ go env t) ) continue ) - ( List.mapi (fun i (_h, f) -> (i,f)) (sort_by_hash vs) ) + ( sort_by_hash vs ) ( E.trap_with env "IDL error: unexpected variant tag" ) ) | (Func _ | Obj (Actor, _)) -> From 54165d9877ae8dcdc83ac366fd3324dbd5e4dc58 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Sun, 29 Sep 2019 12:50:12 +0200 Subject: [PATCH 0418/1176] Static wasm linker: update memory size (#700) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit previously, we would leave the memory limits in place, but by adding the `(data)` sections from the other module, might have data sections out of range. * `wasm-validate` did not notice * V8’s validator did not notice (but we’d get this unhandled exception) * `wasm-opt` from the binaryen toolset gave me the right hint. This bug was dependent on the number of static strings in the C RTS code, hence the seemingly random occurrence of this problem in #687. --- src/linking/linkModule.ml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/linking/linkModule.ml b/src/linking/linkModule.ml index c27ffb43aaf..6ec76768dbb 100644 --- a/src/linking/linkModule.ml +++ b/src/linking/linkModule.ml @@ -454,6 +454,19 @@ let read_table_size (m : module_') : int32 = else min | _ -> raise (LinkError "Expect one table in first module") +let set_memory_size new_size_bytes : module_' -> module_' = fun m -> + let open Wasm.Types in + let page_size = Int32.of_int (64*1024) in + let new_size_pages = Int32.(add (div new_size_bytes page_size) 1l) in + match m.memories with + | [t] -> + { m with + memories = [ phrase (fun m -> + { mtype = MemoryType ({min = new_size_pages; max = None}) } + ) t ] + } + | _ -> raise (LinkError "Expect one memory in first module") + let set_table_size new_size : module_' -> module_' = fun m -> let open Wasm.Types in match m.tables with @@ -663,6 +676,7 @@ let link (em1 : extended_module) libname (em2 : extended_module) = |> rename_funcs_extended funs1 |> rename_globals_extended globals1 |> map_module (set_global heap_global new_heap_start) + |> map_module (set_memory_size new_heap_start) |> map_module (set_table_size new_elem_size) ) ( dm2 From 8505e0e69e36a6096a3610ca11a5ecb8a220d008 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Sun, 29 Sep 2019 22:52:06 +0200 Subject: [PATCH 0419/1176] consolidate flags (#692) --- src/as_config/flags.ml | 4 ++ src/codegen/compile.ml | 92 +++++++++++++++++++-------------------- src/codegen/compile.mli | 4 +- src/codegen/dune | 2 +- src/codegen/flags.ml | 1 - src/exes/asc.ml | 11 +++-- src/js/as_js.ml | 5 ++- src/js/dune | 2 +- src/pipeline/pipeline.ml | 5 +-- src/pipeline/pipeline.mli | 6 +-- 10 files changed, 65 insertions(+), 67 deletions(-) delete mode 100644 src/codegen/flags.ml diff --git a/src/as_config/flags.ml b/src/as_config/flags.ml index 1727d14fab2..0d818939934 100644 --- a/src/as_config/flags.ml +++ b/src/as_config/flags.ml @@ -1,9 +1,13 @@ (* common flags for the asc compiler *) +type compile_mode = WasmMode | AncientMode | ICMode + let trace = ref false let verbose = ref false let print_depth = ref 2 let release_mode = ref false +let compile_mode = ref ICMode +let multi_value = ref false let await_lowering = ref true let async_lowering = ref true let dump_parse = ref false diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index d94b998dadb..70004015e39 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -13,6 +13,7 @@ this keeps documentation close to the code (a lesson learned from Simon PJ). open Ir_def open As_values open As_types +open As_config open Wasm.Ast open Wasm.Types @@ -106,9 +107,6 @@ The fields fall into the following categories: (* Before we can define the environment, we need some auxillary types *) -type mode = WasmMode | AncientMode | ICMode - - module E = struct (* Utilities, internal to E *) @@ -136,7 +134,7 @@ module E = struct type t = { (* Global fields *) (* Static *) - mode : mode; + mode : Flags.compile_mode; prelude : Ir.prog; (* The prelude. Re-used when compiling actors *) rts : Wasm_exts.CustomModule.extended_module option; (* The rts. Re-used when compiling actors *) trap_with : t -> string -> G.t; @@ -233,7 +231,7 @@ module E = struct ignore (reg env.exports e) let add_dfinity_type (env : t) e = - assert (mode env = AncientMode); + assert (mode env = Flags.AncientMode); ignore (reg env.dfinity_types e) let add_global (env : t) name g = @@ -678,14 +676,14 @@ module RTS = struct let get_len = G.i (LocalGet (nr 1l)) in get_str ^^ get_len ^^ match E.mode env with - | AncientMode -> + | Flags.AncientMode -> E.call_import env "data" "externalize" ^^ E.call_import env "test" "print" ^^ G.i Unreachable - | ICMode -> + | Flags.ICMode -> E.call_import env "debug" "print" ^^ G.i Unreachable - | WasmMode -> G.i Unreachable + | Flags.WasmMode -> G.i Unreachable ) ) in E.add_export env (nr { @@ -718,7 +716,7 @@ module Heap = struct (* Page allocation. Ensures that the memory up to the given unskewed pointer is allocated. *) let grow_memory env = (* No growing of memory on drun yet *) - if E.mode env = ICMode + if E.mode env = Flags.ICMode then G.i Drop else Func.share_code1 env "grow_memory" ("ptr", I32Type) [] (fun env get_ptr -> let (set_pages_needed, get_pages_needed) = new_local env "pages_needed" in @@ -2970,14 +2968,14 @@ module Dfinity = struct let system_imports env = match E.mode env with - | ICMode -> + | Flags.ICMode -> E.add_func_import env "debug" "print" [I32Type; I32Type] []; E.add_func_import env "msg" "arg_data_size" [I64Type] [I32Type]; E.add_func_import env "msg" "arg_data_copy" [I64Type; I32Type; I32Type; I32Type] []; E.add_func_import env "msg" "reply" [I64Type; I32Type; I32Type] []; E.add_func_import env "msg" "reject" [I64Type; I32Type] []; E.add_func_import env "msg" "error_code" [I64Type] [I32Type] - | AncientMode -> + | Flags.AncientMode -> E.add_func_import env "test" "print" [I32Type] []; E.add_func_import env "test" "show_i32" [I32Type] [I32Type]; E.add_func_import env "data" "externalize" [I32Type; I32Type] [I32Type]; @@ -3016,14 +3014,14 @@ module Dfinity = struct let prim_print env = match E.mode env with - | WasmMode -> G.i Drop - | ICMode -> + | Flags.WasmMode -> G.i Drop + | Flags.ICMode -> Func.share_code1 env "print_text" ("str", I32Type) [] (fun env get_str -> get_str ^^ Text.payload_ptr_unskewed ^^ get_str ^^ Heap.load_field (Text.len_field) ^^ system_call env "debug" "print" ) - | AncientMode -> + | Flags.AncientMode -> compile_databuf_of_text env ^^ system_call env "test" "print" @@ -3037,7 +3035,7 @@ module Dfinity = struct compile_static_print env "\n" let trap_with env s = - if E.mode env = WasmMode + if E.mode env = Flags.WasmMode then G.i Unreachable else compile_static_print env (s ^ "\n") ^^ G.i Unreachable @@ -3054,7 +3052,7 @@ module Dfinity = struct }) let export_start_stub env = - assert (E.mode env = AncientMode); + assert (E.mode env = Flags.AncientMode); let empty_f = Func.of_body env [] [] (fun env1 -> (* Set up memory *) G.i (Call (nr (E.built_in env1 "restore_mem"))) ^^ @@ -3071,7 +3069,7 @@ module Dfinity = struct E.add_dfinity_type env (fi, []) let export_start env start_fi = - assert (E.mode env = ICMode); + assert (E.mode env = Flags.ICMode); (* Create an empty message *) let empty_f = Func.of_body env ["api_nonce",I64Type] [] (fun env1 -> G.i (Call (nr start_fi)) ^^ @@ -3141,7 +3139,7 @@ module OrthogonalPersistence = struct *) let register_globals env = - assert (E.mode env = AncientMode); + assert (E.mode env = Flags.AncientMode); (* We want to put all persistent globals first: The index in the persist annotation refers to the index in the list of *exported* globals, not all globals (at least with v8/dvm) *) @@ -3153,7 +3151,7 @@ module OrthogonalPersistence = struct E.persist env (E.get_global env "elemstore") Wasm_exts.CustomModule.ElemBuf let register env start_funid = - assert (E.mode env = AncientMode); + assert (E.mode env = Flags.AncientMode); let mem_global = E.get_global env "datastore" in let elem_global = E.get_global env "elemstore" in @@ -3213,11 +3211,11 @@ module OrthogonalPersistence = struct ) let save_mem env = - assert (E.mode env = AncientMode); + assert (E.mode env = Flags.AncientMode); G.i (Call (nr (E.built_in env "save_mem"))) let restore_mem env = - assert (E.mode env = AncientMode); + assert (E.mode env = Flags.AncientMode); G.i (Call (nr (E.built_in env "restore_mem"))) end (* OrthogonalPersistence *) @@ -4050,9 +4048,9 @@ module Serialization = struct let serialize env ts : G.t = let ts_name = String.concat "," (List.map typ_id ts) in let name = "@serialize<" ^ ts_name ^ ">" in - if E.mode env = ICMode then assert (List.for_all has_no_references ts); + if E.mode env = Flags.ICMode then assert (List.for_all has_no_references ts); (* On ancient API returns databuf/elembuf, on new API returns nothing *) - let ret_tys = if E.mode env = ICMode then [] else [I32Type; I32Type] in + let ret_tys = if E.mode env = Flags.ICMode then [] else [I32Type; I32Type] in Func.share_code1 env name ("x", I32Type) ret_tys (fun env get_x -> let (set_data_size, get_data_size) = new_local env "data_size" in let (set_refs_size, get_refs_size) = new_local env "refs_size" in @@ -4097,7 +4095,7 @@ module Serialization = struct E.else_trap_with env "data buffer not filled " ^^ match E.mode env with - | AncientMode -> + | Flags.AncientMode -> (* Store it all in a databuf and an elembuf *) get_data_start ^^ get_data_size ^^ Dfinity.system_call env "data" "externalize" ^^ @@ -4105,7 +4103,7 @@ module Serialization = struct get_refs_start ^^ get_refs_size ^^ Dfinity.system_call env "elem" "externalize" - | ICMode -> + | Flags.ICMode -> get_refs_size ^^ compile_unboxed_const 0l ^^ G.i (Compare (Wasm.Values.I32 I32Op.Eq)) ^^ @@ -4114,14 +4112,14 @@ module Serialization = struct (* Copy out the bytes *) reply_with_data env get_data_start get_data_size - | WasmMode -> assert false + | Flags.WasmMode -> assert false ) let deserialize env ts = - if E.mode env = ICMode then assert (List.for_all has_no_references ts); + if E.mode env = Flags.ICMode then assert (List.for_all has_no_references ts); let ts_name = String.concat "," (List.map typ_id ts) in let name = "@deserialize<" ^ ts_name ^ ">" in - let args = if E.mode env = ICMode then [] else [("databuf",I32Type);("elembuf", I32Type)] in + let args = if E.mode env = Flags.ICMode then [] else [("databuf",I32Type);("elembuf", I32Type)] in Func.share_code env name args (List.map (fun _ -> I32Type) ts) (fun env -> let (set_data_size, get_data_size) = new_local env "data_size" in let (set_refs_size, get_refs_size) = new_local env "refs_size" in @@ -4129,7 +4127,7 @@ module Serialization = struct let (set_refs_start, get_refs_start) = new_local env "refs_start" in begin match E.mode env with - | AncientMode -> + | Flags.AncientMode -> let get_databuf = G.i (LocalGet (nr 0l)) in let get_elembuf = G.i (LocalGet (nr 1l)) in @@ -4144,7 +4142,7 @@ module Serialization = struct get_refs_size ^^ compile_mul_const Heap.word_size ^^ Text.dyn_alloc_scratch env ^^ set_refs_start ^^ get_refs_start ^^ get_refs_size ^^ get_elembuf ^^ compile_unboxed_const 0l ^^ Dfinity.system_call env "elem" "internalize" - | ICMode -> + | Flags.ICMode -> (* Allocate space for the data buffer and copy it *) argument_data_size env ^^ set_data_size ^^ get_data_size ^^ Text.dyn_alloc_scratch env ^^ set_data_start ^^ @@ -4774,7 +4772,7 @@ module FuncDec = struct - Fake orthogonal persistence *) let compile_message outer_env outer_ae cc restore_env args mk_body at = - assert (E.mode outer_env = AncientMode); + assert (E.mode outer_env = Flags.AncientMode); assert (cc.Call_conv.n_res = 0); let ae0 = ASEnv.mk_fun_ae outer_ae in Func.of_body outer_env ["clos", I32Type; "databuf", I32Type; "elembuf", I32Type] [] (fun env -> G.with_region at ( @@ -4812,7 +4810,7 @@ module FuncDec = struct let compile_static_message outer_env outer_ae cc args mk_body ret_tys at : E.func_with_names = match E.mode outer_env with - | AncientMode -> + | Flags.AncientMode -> assert (cc.Call_conv.n_res = 0); let ae0 = ASEnv.mk_fun_ae outer_ae in Func.of_body outer_env ["databuf", I32Type; "elembuf", I32Type] [] (fun env -> G.with_region at ( @@ -4837,7 +4835,7 @@ module FuncDec = struct (* Save memory *) OrthogonalPersistence.save_mem env )) - | ICMode -> + | Flags.ICMode -> let ae0 = ASEnv.mk_fun_ae outer_ae in Func.of_body outer_env ["api_nonce", I64Type] [] (fun env -> G.with_region at ( G.i (LocalGet (nr 0l)) ^^ Dfinity.set_api_nonce env ^^ @@ -4853,10 +4851,10 @@ module FuncDec = struct (* Collect garbage *) G.i (Call (nr (E.built_in env "collect"))) )) - | WasmMode -> assert false + | Flags.WasmMode -> assert false let declare_dfinity_type env has_closure fi = - if E.mode env = AncientMode then + if E.mode env = Flags.AncientMode then E.add_dfinity_type env (fi, (if has_closure then [ Wasm_exts.CustomModule.I32 ] else []) @ [ Wasm_exts.CustomModule.DataBuf; Wasm_exts.CustomModule.ElemBuf ] @@ -6179,17 +6177,17 @@ and compile_exp (env : E.t) ae exp = Error.compile_make_error (compile_exp_vanilla env ae e1) (compile_exp_vanilla env ae e2) | ICReplyPrim t, [e] -> - assert (E.mode env = ICMode); + assert (E.mode env = Flags.ICMode); SR.unit, compile_exp_vanilla env ae e ^^ Serialization.serialize env [t] | ICRejectPrim, [e] -> - assert (E.mode env = ICMode); + assert (E.mode env = Flags.ICMode); Dfinity.reject env (compile_exp_vanilla env ae e) | ICErrorCodePrim, [] -> - assert (E.mode env = ICMode); + assert (E.mode env = Flags.ICMode); Dfinity.error_code env (* Unknown prim *) @@ -6736,8 +6734,8 @@ and export_actor_field env ae (f : Ir.field) = FuncDec.declare_dfinity_type env false fi; E.add_export env (nr { name = Wasm.Utf8.decode (match E.mode env with - | AncientMode -> f.it.name - | ICMode -> "canister_update " ^ f.it.name + | Flags.AncientMode -> f.it.name + | Flags.ICMode -> "canister_update " ^ f.it.name | _ -> assert false); edesc = nr (FuncExport (nr fi)) }) @@ -6752,7 +6750,7 @@ and actor_lit outer_env this ds fs at = (E.get_trap_with outer_env) ClosureTable.table_end in - if E.mode mod_env = AncientMode then OrthogonalPersistence.register_globals mod_env; + if E.mode mod_env = Flags.AncientMode then OrthogonalPersistence.register_globals mod_env; Heap.register_globals mod_env; ElemHeap.register_globals mod_env; Stack.register_globals mod_env; @@ -6781,8 +6779,8 @@ and actor_lit outer_env this ds fs at = prelude_code ^^ decls_code) in let start_fi = E.add_fun mod_env "start" start_fun in - if E.mode mod_env = ICMode then Dfinity.export_start mod_env start_fi; - if E.mode mod_env = AncientMode then OrthogonalPersistence.register mod_env start_fi; + if E.mode mod_env = Flags.ICMode then Dfinity.export_start mod_env start_fi; + if E.mode mod_env = Flags.AncientMode then OrthogonalPersistence.register mod_env start_fi; let m = conclude_module mod_env this None in let (_map, wasm_binary) = Wasm_exts.CustomModuleEncode.encode m in @@ -6888,7 +6886,7 @@ and conclude_module env module_name start_fi_o = let compile mode module_name rts (prelude : Ir.prog) (progs : Ir.prog list) : Wasm_exts.CustomModule.extended_module = let env = E.mk_global mode rts prelude Dfinity.trap_with ClosureTable.table_end in - if E.mode env = AncientMode then OrthogonalPersistence.register_globals env; + if E.mode env = Flags.AncientMode then OrthogonalPersistence.register_globals env; Heap.register_globals env; ElemHeap.register_globals env; Stack.register_globals env; @@ -6901,11 +6899,11 @@ let compile mode module_name rts (prelude : Ir.prog) (progs : Ir.prog list) : Wa let start_fun = compile_start_func env (prelude :: progs) in let start_fi = E.add_fun env "start" start_fun in let start_fi_o = match E.mode env with - | AncientMode -> + | Flags.AncientMode -> OrthogonalPersistence.register env start_fi; Dfinity.export_start_stub env; None - | ICMode -> Dfinity.export_start env start_fi; None - | WasmMode -> Some (nr start_fi) in + | Flags.ICMode -> Dfinity.export_start env start_fi; None + | Flags.WasmMode -> Some (nr start_fi) in conclude_module env module_name start_fi_o diff --git a/src/codegen/compile.mli b/src/codegen/compile.mli index 2cc6cdf680e..7233dfb6786 100644 --- a/src/codegen/compile.mli +++ b/src/codegen/compile.mli @@ -1,5 +1,3 @@ open Ir_def -type mode = WasmMode | AncientMode | ICMode - -val compile : mode -> string -> Wasm_exts.CustomModule.extended_module option -> Ir.prog -> Ir.prog list -> Wasm_exts.CustomModule.extended_module +val compile : As_config.Flags.compile_mode -> string -> Wasm_exts.CustomModule.extended_module option -> Ir.prog -> Ir.prog list -> Wasm_exts.CustomModule.extended_module diff --git a/src/codegen/dune b/src/codegen/dune index fd155db2fa2..3f4b795c8d7 100644 --- a/src/codegen/dune +++ b/src/codegen/dune @@ -1,4 +1,4 @@ (library (name codegen) - (libraries wasm lib lang_utils wasm_exts ir_def linking) + (libraries wasm lib as_config lang_utils wasm_exts ir_def linking) ) diff --git a/src/codegen/flags.ml b/src/codegen/flags.ml deleted file mode 100644 index 848563b2737..00000000000 --- a/src/codegen/flags.ml +++ /dev/null @@ -1 +0,0 @@ -let multi_value = ref false diff --git a/src/exes/asc.ml b/src/exes/asc.ml index c70ef64cc07..fe0b6e9fee8 100644 --- a/src/exes/asc.ml +++ b/src/exes/asc.ml @@ -23,7 +23,6 @@ let set_mode m () = end; mode := m -let compile_mode = ref Pipeline.ICMode let out_file = ref "" let link = ref true let interpret_ir = ref false @@ -68,13 +67,13 @@ let argspec = Arg.align "-no-link", Arg.Clear link, " do not statically link-in runtime"; "-no-system-api", - Arg.Unit (fun () -> compile_mode := Pipeline.WasmMode), + Arg.Unit (fun () -> Flags.(compile_mode := WasmMode)), " do not import any system API"; "-ancient-system-api", - Arg.Unit (fun () -> compile_mode := Pipeline.AncientMode), + Arg.Unit (fun () -> Flags.(compile_mode := AncientMode)), " use the ancient DFINITY system API (dvm)"; - "-multi-value", Arg.Set Codegen.Flags.multi_value, " use multi-value extension"; - "-no-multi-value", Arg.Clear Codegen.Flags.multi_value, " avoid multi-value extension"; + "-multi-value", Arg.Set Flags.multi_value, " use multi-value extension"; + "-no-multi-value", Arg.Clear Flags.multi_value, " avoid multi-value extension"; "-dp", Arg.Set Flags.dump_parse, " dump parse"; "-dt", Arg.Set Flags.dump_tc, " dump type-checked AST"; @@ -126,7 +125,7 @@ let process_files files : unit = output_string oc idl_code; close_out oc | Compile -> set_out_file files ".wasm"; - let module_ = Diag.run Pipeline.(compile_files !compile_mode !link files) in + let module_ = Diag.run Pipeline.(compile_files !Flags.compile_mode !link files) in let oc = open_out !out_file in let (source_map, wasm) = CustomModuleEncode.encode module_ in output_string oc wasm; close_out oc; diff --git a/src/js/as_js.ml b/src/js/as_js.ml index 1ffd4fd159b..14c8745a71e 100644 --- a/src/js/as_js.ml +++ b/src/js/as_js.ml @@ -1,5 +1,6 @@ open Wasm_exts open Source +open As_config module Js = Js_of_ocaml.Js @@ -40,8 +41,8 @@ let js_check source = let js_compile_with mode_string source convert = let mode = match Js.to_string mode_string with - | "dfinity" -> Pipeline.AncientMode - | _ -> Pipeline.WasmMode + | "dfinity" -> Flags.AncientMode + | _ -> Flags.WasmMode in match Pipeline.compile_string mode (Js.to_string source) "js-input" with | Ok (module_, msgs) -> diff --git a/src/js/dune b/src/js/dune index d7ee87b5b5d..faa9d4cdcfa 100644 --- a/src/js/dune +++ b/src/js/dune @@ -1,7 +1,7 @@ (executable (name as_js) (modules as_js) - (libraries pipeline) + (libraries as_config pipeline) (preprocess (pps js_of_ocaml-ppx)) (js_of_ocaml (flags :standard "+nat.js") ) ) diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index 195265378f6..5f0c1fcc0ea 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -436,7 +436,7 @@ let await_lowering = transform_if "Await Lowering" (fun _ -> Await.transform) let async_lowering mode = - let platform = if mode = Codegen.Compile.ICMode then Async.V2 else Async.V1 in + let platform = if mode = Flags.ICMode then Async.V2 else Async.V1 in transform_if "Async Lowering" (Async.transform platform) let tailcall_optimization = @@ -469,7 +469,6 @@ let load_as_rts () = let wasm = load_file wasm_filename in Wasm_exts.CustomModuleDecode.decode "rts.wasm" wasm -type compile_mode = Codegen.Compile.mode = WasmMode | AncientMode | ICMode type compile_result = Wasm_exts.CustomModule.extended_module Diag.result let name_progs progs = @@ -508,7 +507,7 @@ let compile_string mode s name : compile_result = let interpret_ir_prog inp_env libraries progs = let prelude_ir = Lowering.Desugar.transform prelude in let name = name_progs progs in - let prog_ir = lower_prog WasmMode initial_stat_env inp_env libraries progs name in + let prog_ir = lower_prog Flags.WasmMode initial_stat_env inp_env libraries progs name in phase "Interpreting" name; let open Interpret_ir in let flags = { trace = !Flags.trace; print_depth = !Flags.print_depth } in diff --git a/src/pipeline/pipeline.mli b/src/pipeline/pipeline.mli index d292c67a694..372f5b946c2 100644 --- a/src/pipeline/pipeline.mli +++ b/src/pipeline/pipeline.mli @@ -1,4 +1,5 @@ open As_def +open As_config open As_types type parse_fn = string -> (Syntax.prog * string) Diag.result @@ -19,8 +20,7 @@ val run_files : string list -> unit option val interpret_ir_files : string list -> unit option val run_files_and_stdin : string list -> unit option -type compile_mode = WasmMode | AncientMode | ICMode type compile_result = Wasm_exts.CustomModule.extended_module Diag.result -val compile_string : compile_mode -> string -> string -> compile_result -val compile_files : compile_mode -> bool -> string list -> compile_result +val compile_string : Flags.compile_mode -> string -> string -> compile_result +val compile_files : Flags.compile_mode -> bool -> string list -> compile_result From 06ee66387ed05a30b6f141b9525b1eff31a4e334 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 30 Sep 2019 09:27:07 +0200 Subject: [PATCH 0420/1176] =?UTF-8?q?IDL=20Decoding:=20Implement=20?= =?UTF-8?q?=E2=80=9CAny=E2=80=9C=20ACT-111=20(#687)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit by writing RTS code (in the C section) that can skip any kind of data. Writing test cases by hand, but maybe some fuzzying would be useful at some point. This puts a bound on nested records (which are empty types) in lieu of a proper loop detection. --- rts/buf.c | 10 ++- rts/buf.h | 1 + rts/idl.c | 105 +++++++++++++++++++++++++++ src/codegen/compile.ml | 11 ++- test/run-drun/idl-any.as | 38 ++++++++++ test/run-drun/ok/idl-any.drun-run.ok | 55 ++++++++++++++ 6 files changed, 214 insertions(+), 6 deletions(-) create mode 100644 test/run-drun/idl-any.as create mode 100644 test/run-drun/ok/idl-any.drun-run.ok diff --git a/rts/buf.c b/rts/buf.c index 89ea59c71da..0d262d1eb56 100644 --- a/rts/buf.c +++ b/rts/buf.c @@ -4,14 +4,20 @@ // See comments in buf.h uint8_t read_byte(buf *buf) { - if (buf->p >= buf->e) (idl_trap_with("byte read out of buffer")); + if (buf->p >= buf->e) idl_trap_with("byte read out of buffer"); return ((buf->p)++)[0]; } uint32_t read_word(buf *buf) { - if (buf->p + sizeof(uint8_t) > buf->e) (idl_trap_with("word read out of buffer")); + if (buf->p + sizeof(uint8_t) > buf->e) idl_trap_with("word read out of buffer"); uint32_t r = ((uint32_t*)(buf->p))[0]; buf->p += sizeof(uint32_t); return r; } +void advance(buf *buf, uint32_t n) { + if (n > buf->e - buf->p) { + idl_trap_with("advance out of buffer"); + } + buf->p += n; +} diff --git a/rts/buf.h b/rts/buf.h index c999681027e..04a05887e6b 100644 --- a/rts/buf.h +++ b/rts/buf.h @@ -16,5 +16,6 @@ typedef struct { extern uint8_t read_byte(buf *buf); extern uint32_t read_word(buf *buf); +extern void advance(buf *buf, uint32_t n); #endif /* BUF_H */ diff --git a/rts/idl.c b/rts/idl.c index d75bc563287..3e06546c61f 100644 --- a/rts/idl.c +++ b/rts/idl.c @@ -171,3 +171,108 @@ export void parse_idl_header(buf *buf, uint8_t ***typtbl_out, uint8_t **main_typ *typtbl_out = typtbl; } + +// can also be used for sleb +void skip_leb128(buf *buf) { + uint8_t b; + do { + b = read_byte(buf); + } while (b & (uint8_t)0x80); +} + +// Assumes that buf is the encoding of type t, and fast-forwards past that +// Assumes that all type references in the typtbl are already checked +// +// This is currently implemented recursively, but we could +// do this in a loop (by maintaing a stack of the t arguments) +export void skip_any(buf *b, uint8_t **typtbl, int32_t t, int32_t depth) { + if (depth > 100) { + idl_trap_with("skip_any: too deeply nested record"); + } + if (t < 0) { // primitive type + switch(t) { + case IDL_PRIM_null: + case IDL_PRIM_reserved: + return; + case IDL_PRIM_bool: + case IDL_PRIM_nat8: + case IDL_PRIM_int8: + advance(b, 1); + return; + case IDL_PRIM_nat: + case IDL_PRIM_int: + skip_leb128(b); + return; + case IDL_PRIM_nat16: + case IDL_PRIM_int16: + advance(b, 2); + return; + case IDL_PRIM_nat32: + case IDL_PRIM_int32: + case IDL_PRIM_float32: + advance(b, 4); + return; + case IDL_PRIM_nat64: + case IDL_PRIM_int64: + case IDL_PRIM_float64: + advance(b, 8); + return; + case IDL_PRIM_text: + { + uint32_t len = read_u32_of_leb128(b); + advance(b, len); + } + return; + case IDL_PRIM_empty: + idl_trap_with("skip_any: encountered empty"); + default: + idl_trap_with("skip_any: unknown prim"); + } + } else { + buf tb = { typtbl[t], b->e }; + int32_t tc = read_i32_of_sleb128(&tb); + switch(tc) { + case IDL_CON_opt: { + int32_t it = read_i32_of_sleb128(&tb); + if (read_byte(b)) { + skip_any(b, typtbl, it, 0); + } + return; + } + case IDL_CON_vec: { + int32_t it = read_i32_of_sleb128(&tb); + for (uint32_t n = read_u32_of_leb128(b); n > 0; n--) { + skip_any(b, typtbl, it, 0); + } + return; + } + case IDL_CON_record: { + for (uint32_t n = read_u32_of_leb128(&tb); n > 0; n--) { + skip_leb128(&tb); + int32_t it = read_i32_of_sleb128(&tb); + // This is just a quick check; we should be keeping + // track of all enclosing records to detect larger loops + if (it == t) idl_trap_with("skip_any: recursive record"); + skip_any(b, typtbl, it, depth + 1); + } + return; + } + case IDL_CON_variant: { + uint32_t n = read_u32_of_leb128(&tb); + uint32_t i = read_u32_of_leb128(b); + if (i >= n) idl_trap_with("skip_any: variant tag too large"); + for (; i > 0; i--) { + skip_leb128(&tb); + skip_leb128(&tb); + } + skip_leb128(&tb); + int32_t it = read_i32_of_sleb128(&tb); + skip_any(b, typtbl, it, 0); + return; + } + + default: + idl_trap_with("skip_any: unknown tycon"); + } + } +} diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 70004015e39..9813660e29d 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -654,7 +654,8 @@ module RTS = struct E.add_func_import env "rts" "bigint_sleb128_decode" [I32Type] [I32Type]; E.add_func_import env "rts" "leb128_encode" [I32Type; I32Type] []; E.add_func_import env "rts" "sleb128_encode" [I32Type; I32Type] []; - E.add_func_import env "rts" "utf8_validate" [I32Type; I32Type] [] + E.add_func_import env "rts" "utf8_validate" [I32Type; I32Type] []; + E.add_func_import env "rts" "skip_any" [I32Type; I32Type; I32Type; I32Type] [] let system_exports env = E.add_export env (nr { @@ -3913,9 +3914,11 @@ module Serialization = struct assert_prim_typ () ^^ Opt.null | Any -> - (* TODO: Accept actually any type, and skip its values *) - assert_prim_typ () ^^ - (* We can return essentially any value here *) + (* Skip values of any possible type *) + get_data_buf ^^ get_typtbl ^^ get_idltyp ^^ compile_unboxed_const 0l ^^ + E.call_import env "rts" "skip_any" ^^ + + (* Any vanilla value works here *) Opt.null | Prim Text -> assert_prim_typ () ^^ diff --git a/test/run-drun/idl-any.as b/test/run-drun/idl-any.as new file mode 100644 index 00000000000..3d6552eacb0 --- /dev/null +++ b/test/run-drun/idl-any.as @@ -0,0 +1,38 @@ +// This tests checks that the IDL decoder properly +// zooms past the any argument and finds the beginning of the string +actor { + public func any(_ : Any, x : Text) : async () { + print ("ok: " # x); + }; +} + +// Primitive values: +//CALL ingress any 0x4449444C00027f7103466F6F +//CALL ingress any 0x4449444C00027e710103466F6F +//CALL ingress any 0x4449444C00027d718080800803466F6F +//CALL ingress any 0x4449444C00027c718080800803466F6F +//CALL ingress any 0x4449444C00027b71AB03466F6F +//CALL ingress any 0x4449444C00027a71ABCD03466F6F +//CALL ingress any 0x4449444C00027971DEADBEEF03466F6F +//CALL ingress any 0x4449444C00027871DEADBEEFCAFFEE6603466F6F +//CALL ingress any 0x4449444C00027771AB03466F6F +//CALL ingress any 0x4449444C00027671ABCD03466F6F +//CALL ingress any 0x4449444C00027571DEADBEEF03466F6F +//CALL ingress any 0x4449444C00027471DEADBEEFCAFFEE6603466F6F +//CALL ingress any 0x4449444C00027371DEADBEEF03466F6F +//CALL ingress any 0x4449444C00027271DEADBEEFCAFFEE6603466F6F +//CALL ingress any 0x4449444C0002717103466F6F03466F6F +//CALL ingress any 0x4449444C0002707103466F6F + +// Composite values: +//CALL ingress any 0x4449444C016e710200710003466F6F +//CALL ingress any 0x4449444C016e710200710103466F6F03466F6F +//CALL ingress any 0x4449444C016d710200710003466F6F +//CALL ingress any 0x4449444C016d710200710103466F6F03466F6F +//CALL ingress any 0x4449444C016d71020071020003466F6F03466F6F +//CALL ingress any 0x4449444C016c0002007103466F6F +//CALL ingress any 0x4449444C016c01800175020071DEADBEEF03466F6F +//CALL ingress any 0x4449444C016c02007180017502007101A0DEADBEEF03466F6F +//CALL ingress any 0x4449444C016b0180017502007100DEADBEEF03466F6F +//CALL ingress any 0x4449444C016b0200718001750200710001A003466F6F +//CALL ingress any 0x4449444C016b02007180017502007101DEADBEEF03466F6F diff --git a/test/run-drun/ok/idl-any.drun-run.ok b/test/run-drun/ok/idl-any.drun-run.ok new file mode 100644 index 00000000000..dc989777185 --- /dev/null +++ b/test/run-drun/ok/idl-any.drun-run.ok @@ -0,0 +1,55 @@ +ingress(0) System +debug.print: ok: Foo +ingress(1) Completed: Canister: Payload: 0x4449444c016c000100 +debug.print: ok: Foo +ingress(2) Completed: Canister: Payload: 0x4449444c016c000100 +debug.print: ok: Foo +ingress(3) Completed: Canister: Payload: 0x4449444c016c000100 +debug.print: ok: Foo +ingress(4) Completed: Canister: Payload: 0x4449444c016c000100 +debug.print: ok: Foo +ingress(5) Completed: Canister: Payload: 0x4449444c016c000100 +debug.print: ok: Foo +ingress(6) Completed: Canister: Payload: 0x4449444c016c000100 +debug.print: ok: Foo +ingress(7) Completed: Canister: Payload: 0x4449444c016c000100 +debug.print: ok: Foo +ingress(8) Completed: Canister: Payload: 0x4449444c016c000100 +debug.print: ok: Foo +ingress(9) Completed: Canister: Payload: 0x4449444c016c000100 +debug.print: ok: Foo +ingress(10) Completed: Canister: Payload: 0x4449444c016c000100 +debug.print: ok: Foo +ingress(11) Completed: Canister: Payload: 0x4449444c016c000100 +debug.print: ok: Foo +ingress(12) Completed: Canister: Payload: 0x4449444c016c000100 +debug.print: ok: Foo +ingress(13) Completed: Canister: Payload: 0x4449444c016c000100 +debug.print: ok: Foo +ingress(14) Completed: Canister: Payload: 0x4449444c016c000100 +debug.print: ok: Foo +ingress(15) Completed: Canister: Payload: 0x4449444c016c000100 +debug.print: ok: Foo +ingress(16) Completed: Canister: Payload: 0x4449444c016c000100 +debug.print: ok: Foo +ingress(17) Completed: Canister: Payload: 0x4449444c016c000100 +debug.print: ok: Foo +ingress(18) Completed: Canister: Payload: 0x4449444c016c000100 +debug.print: ok: Foo +ingress(19) Completed: Canister: Payload: 0x4449444c016c000100 +debug.print: ok: Foo +ingress(20) Completed: Canister: Payload: 0x4449444c016c000100 +debug.print: ok: Foo +ingress(21) Completed: Canister: Payload: 0x4449444c016c000100 +debug.print: ok: Foo +ingress(22) Completed: Canister: Payload: 0x4449444c016c000100 +debug.print: ok: Foo +ingress(23) Completed: Canister: Payload: 0x4449444c016c000100 +debug.print: ok: Foo +ingress(24) Completed: Canister: Payload: 0x4449444c016c000100 +debug.print: ok: Foo +ingress(25) Completed: Canister: Payload: 0x4449444c016c000100 +debug.print: ok: Foo +ingress(26) Completed: Canister: Payload: 0x4449444c016c000100 +debug.print: ok: Foo +ingress(27) Completed: Canister: Payload: 0x4449444c016c000100 From 3cf2c8f6fa5da761404336fc2b7ed0e523071fb2 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 30 Sep 2019 09:34:31 +0200 Subject: [PATCH 0421/1176] Allow ids to start with underscore (#701) --- src/as_frontend/lexer.mll | 2 +- test/run/underscore-ids.as | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 test/run/underscore-ids.as diff --git a/src/as_frontend/lexer.mll b/src/as_frontend/lexer.mll index 87431f8722c..2b57ea8def9 100644 --- a/src/as_frontend/lexer.mll +++ b/src/as_frontend/lexer.mll @@ -107,7 +107,7 @@ let float = | "0x" hexnum ('.' hexfrac?)? ('p' | 'P') sign? num let char = '\'' character '\'' let text = '"' character* '"' -let id = letter ((letter | digit | '_')*) +let id = (letter | '_') ((letter | digit | '_')*) let privileged_id = "@" id let reserved = ([^'\"''('')'';'] # space)+ (* hack for table size *) diff --git a/test/run/underscore-ids.as b/test/run/underscore-ids.as new file mode 100644 index 00000000000..610a8c6f089 --- /dev/null +++ b/test/run/underscore-ids.as @@ -0,0 +1,3 @@ +type _foo = { _bar : _foo }; + +func _fun( _arg : _foo) : _foo = _arg; From 4313d18dccabcfaddbea86d3203e78bc71d6966a Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 30 Sep 2019 10:44:13 +0200 Subject: [PATCH 0422/1176] IDL decoding: Use `skip_leb128` (#702) cheaper than parsing and allocating a proper BigInt and then just dropping it. --- rts/idl.c | 2 +- src/codegen/compile.ml | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/rts/idl.c b/rts/idl.c index 3e06546c61f..5477f9c826a 100644 --- a/rts/idl.c +++ b/rts/idl.c @@ -173,7 +173,7 @@ export void parse_idl_header(buf *buf, uint8_t ***typtbl_out, uint8_t **main_typ } // can also be used for sleb -void skip_leb128(buf *buf) { +export void skip_leb128(buf *buf) { uint8_t b; do { b = read_byte(buf); diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 9813660e29d..4e263da4d53 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -655,6 +655,7 @@ module RTS = struct E.add_func_import env "rts" "leb128_encode" [I32Type; I32Type] []; E.add_func_import env "rts" "sleb128_encode" [I32Type; I32Type] []; E.add_func_import env "rts" "utf8_validate" [I32Type; I32Type] []; + E.add_func_import env "rts" "skip_leb128" [I32Type] []; E.add_func_import env "rts" "skip_any" [I32Type; I32Type; I32Type; I32Type] [] let system_exports env = @@ -4003,8 +4004,8 @@ module Serialization = struct (* Zoom past the previous entries *) get_tagidx ^^ from_0_to_n env (fun _ -> - ReadBuf.read_leb128 env get_typ_buf ^^ G.i Drop ^^ - ReadBuf.read_sleb128 env get_typ_buf ^^ G.i Drop + get_typ_buf ^^ E.call_import env "rts" "skip_leb128" ^^ + get_typ_buf ^^ E.call_import env "rts" "skip_leb128" ) ^^ (* Now read the tag *) From d225527d04245a5c04532fa2981843b9c14098c9 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 30 Sep 2019 11:13:24 +0200 Subject: [PATCH 0423/1176] Fix bounds checking in buf.c:read_word() (#704) --- rts/buf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rts/buf.c b/rts/buf.c index 0d262d1eb56..c68e74dd996 100644 --- a/rts/buf.c +++ b/rts/buf.c @@ -9,7 +9,7 @@ uint8_t read_byte(buf *buf) { } uint32_t read_word(buf *buf) { - if (buf->p + sizeof(uint8_t) > buf->e) idl_trap_with("word read out of buffer"); + if (buf->p + sizeof(uint32_t) > buf->e) idl_trap_with("word read out of buffer"); uint32_t r = ((uint32_t*)(buf->p))[0]; buf->p += sizeof(uint32_t); return r; From bd5587d05ab03a065b73413ac8ae935120bbb6c9 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 30 Sep 2019 12:29:11 +0200 Subject: [PATCH 0424/1176] IDL decoder: Use uint32, not int (#706) otherwise we can get an out-of-bounds read. This was found using AFL. --- rts/idl.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/rts/idl.c b/rts/idl.c index 5477f9c826a..eb1d0ae7557 100644 --- a/rts/idl.c +++ b/rts/idl.c @@ -112,7 +112,7 @@ export void parse_idl_header(buf *buf, uint8_t ***typtbl_out, uint8_t **main_typ uint8_t **typtbl = (uint8_t **)alloc(n_types * sizeof(uint8_t*)); for (int i = 0; i < n_types; i++) { typtbl[i] = buf->p; - int ty = read_i32_of_sleb128(buf); + int32_t ty = read_i32_of_sleb128(buf); if (ty >= IDL_PRIM_lowest) { idl_trap_with("type index too high"); // illegal } else if (ty == IDL_CON_opt) { @@ -122,36 +122,36 @@ export void parse_idl_header(buf *buf, uint8_t ***typtbl_out, uint8_t **main_typ int32_t t = read_i32_of_sleb128(buf); if (t < IDL_PRIM_lowest || t >= n_types) idl_trap_with("type index out of range"); } else if (ty == IDL_CON_record) { - for (int n = read_u32_of_leb128(buf); n > 0; n--) { + for (uint32_t n = read_u32_of_leb128(buf); n > 0; n--) { read_u32_of_leb128(buf); int32_t t = read_i32_of_sleb128(buf); if (t < IDL_PRIM_lowest || t >= n_types) idl_trap_with("type index out of range"); } } else if (ty == IDL_CON_variant) { - for (int n = read_u32_of_leb128(buf); n > 0; n--) { + for (uint32_t n = read_u32_of_leb128(buf); n > 0; n--) { read_u32_of_leb128(buf); int32_t t = read_i32_of_sleb128(buf); if (t < IDL_PRIM_lowest || t >= n_types) idl_trap_with("type index out of range"); } } else if (ty == IDL_CON_func) { // arg types - for (int n = read_u32_of_leb128(buf); n > 0; n--) { + for (uint32_t n = read_u32_of_leb128(buf); n > 0; n--) { int32_t t = read_i32_of_sleb128(buf); if (t < IDL_PRIM_lowest || t >= n_types) idl_trap_with("type index out of range"); } // ret types - for (int n = read_u32_of_leb128(buf); n > 0; n--) { + for (uint32_t n = read_u32_of_leb128(buf); n > 0; n--) { int32_t t = read_i32_of_sleb128(buf); if (t < IDL_PRIM_lowest || t >= n_types) idl_trap_with("type index out of range"); } // annotations - for (int n = read_u32_of_leb128(buf); n > 0; n--) { + for (uint32_t n = read_u32_of_leb128(buf); n > 0; n--) { (buf->p)++; } } else if (ty == IDL_CON_service) { - for (int n = read_u32_of_leb128(buf); n > 0; n--) { + for (uint32_t n = read_u32_of_leb128(buf); n > 0; n--) { // name - unsigned int size = read_u32_of_leb128(buf); + uint32_t size = read_u32_of_leb128(buf); (buf->p) += size; // type int32_t t = read_i32_of_sleb128(buf); @@ -164,7 +164,7 @@ export void parse_idl_header(buf *buf, uint8_t ***typtbl_out, uint8_t **main_typ } // Now read the main types *main_types_out = buf->p; - for (int n = read_u32_of_leb128(buf); n > 0; n--) { + for (uint32_t n = read_u32_of_leb128(buf); n > 0; n--) { int32_t t = read_i32_of_sleb128(buf); if (t < IDL_PRIM_lowest || t >= n_types) idl_trap_with("type index out of range"); } From 6b80e196dbddc1d2e2c4c103b64feee72b0bc965 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 30 Sep 2019 12:37:41 +0200 Subject: [PATCH 0425/1176] IDL parser: Avoid integer overflow in text decoding length check (#708) --- src/codegen/compile.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 4e263da4d53..a063051d26d 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -1653,8 +1653,8 @@ module ReadBuf = struct get_buf ^^ E.call_import env "rts" "read_i32_of_sleb128" let check_space env get_buf get_delta = - get_ptr get_buf ^^ get_delta ^^ G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ - get_end get_buf ^^ + get_delta ^^ + get_end get_buf ^^ get_ptr get_buf ^^ G.i (Binary (Wasm.Values.I32 I32Op.Sub)) ^^ G.i (Compare (Wasm.Values.I32 I64Op.LeU)) ^^ E.else_trap_with env "IDL error: out of bounds read" From d3d2a3bfe15fd489cd365a0ed74fb1c55804635d Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 30 Sep 2019 13:08:06 +0200 Subject: [PATCH 0426/1176] IDL parser: Implement null <: opt t subtyping ACT-111 (#709) * IDL parser: Implement null <: opt t subtyping ACT-111 * Update test/run-drun/idl-option.as Co-Authored-By: Gabor Greif * Update src/codegen/compile.ml Co-Authored-By: Gabor Greif --- src/codegen/compile.ml | 38 ++++++++++++++----------- test/run-drun/idl-option.as | 14 +++++++++ test/run-drun/ok/idl-option.drun-run.ok | 7 +++++ 3 files changed, 43 insertions(+), 16 deletions(-) create mode 100644 test/run-drun/idl-option.as create mode 100644 test/run-drun/ok/idl-option.drun-run.ok diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index a063051d26d..bf03fe3e908 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -3971,24 +3971,30 @@ module Serialization = struct get_x ) | Opt t -> - (* TODO: Subtyping with primitive null *) - let (set_idltyp, get_idltyp) = new_local env "idltyp" in - with_composite_typ (-18l) (fun get_typ_buf -> - ReadBuf.read_sleb128 env get_typ_buf ^^ set_idltyp ^^ - ReadBuf.read_byte env get_data_buf ^^ - let (set_b, get_b) = new_local env "b" in - set_b ^^ - get_b ^^ - compile_eq_const 0l ^^ - G.if_ (ValBlockType (Some I32Type)) + check_prim_typ (Prim Null) ^^ + G.if_ (ValBlockType (Some I32Type)) begin - Opt.null - end begin - get_b ^^ compile_eq_const 1l ^^ - E.else_trap_with env "IDL error: opt tag not 0 or 1 " ^^ - Opt.inject env (get_idltyp ^^ go env t) + Opt.null + end + begin + let (set_idltyp, get_idltyp) = new_local env "idltyp" in + with_composite_typ (-18l) (fun get_typ_buf -> + ReadBuf.read_sleb128 env get_typ_buf ^^ set_idltyp ^^ + ReadBuf.read_byte env get_data_buf ^^ + let (set_b, get_b) = new_local env "b" in + set_b ^^ + get_b ^^ + compile_eq_const 0l ^^ + G.if_ (ValBlockType (Some I32Type)) + begin + Opt.null + end begin + get_b ^^ compile_eq_const 1l ^^ + E.else_trap_with env "IDL error: opt tag not 0 or 1" ^^ + Opt.inject env (get_idltyp ^^ go env t) + end + ) end - ) | Variant vs -> with_composite_typ (-21l) (fun get_typ_buf -> (* Find the tag *) diff --git a/test/run-drun/idl-option.as b/test/run-drun/idl-option.as new file mode 100644 index 00000000000..3fbe8f0a620 --- /dev/null +++ b/test/run-drun/idl-option.as @@ -0,0 +1,14 @@ +// This test checks that the IDL decoder can +// do the subtyping from null to option +actor { + public func any(o : ?Text) : async () { + switch o { + case null print ("ok: null"); + case (?x) print ("ok: " # x); + } + }; +} + +//CALL ingress any 0x4449444C00017f +//CALL ingress any 0x4449444C016e71010000 +//CALL ingress any 0x4449444C016e7101000103466F6F diff --git a/test/run-drun/ok/idl-option.drun-run.ok b/test/run-drun/ok/idl-option.drun-run.ok new file mode 100644 index 00000000000..99e54d0b73a --- /dev/null +++ b/test/run-drun/ok/idl-option.drun-run.ok @@ -0,0 +1,7 @@ +ingress(0) System +debug.print: ok: null +ingress(1) Completed: Canister: Payload: 0x4449444c016c000100 +debug.print: ok: null +ingress(2) Completed: Canister: Payload: 0x4449444c016c000100 +debug.print: ok: Foo +ingress(3) Completed: Canister: Payload: 0x4449444c016c000100 From 60e56f4b517e04f83ae2a34a685998d40dbc2db0 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 1 Oct 2019 14:38:40 +0200 Subject: [PATCH 0427/1176] IDL Design: remove premise from null <: opt rule (#712) as discussed in https://github.com/dfinity-lab/actorscript/issues/711#issuecomment-536919941 --- design/IDL.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/design/IDL.md b/design/IDL.md index 7d3c1e9aff0..669339341e5 100644 --- a/design/IDL.md +++ b/design/IDL.md @@ -593,7 +593,6 @@ vec <: vec ``` Furthermore, an option type can be specialised to either `null` or to its constituent type: ``` -not (null <: ) ------------------------ null <: opt @@ -602,7 +601,7 @@ not (null <: ) ----------------------------- <: opt ``` -The premise means that the rule does not apply when the constituent type is itself `null` or an option. That restriction is necessary so that there is no ambiguity. For example, there would be two ways to interpret `null` when going from `opt nat` to `opt opt nat`, either as `null` or as `?null`. +The premise means that the rule does not apply when the constituent type is itself `null`, an option or `reserved`. That restriction is necessary so that there is no ambiguity. For example, otherwise there would be two ways to interpret `null` when going from `opt nat` to `opt opt nat`, either as `null` or as `?null`. Q: The negated nature of this premise isn't really compatible with parametric polymorphism. Is that a problem? We could always introduce a supertype of all non-nullable types and rephrase it with that. From 5794885f0f81eb4fba37a96b02ca507ac4855ac2 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 1 Oct 2019 16:05:01 +0200 Subject: [PATCH 0428/1176] Deserialization: Support record subtyping ACT-111 (#698) Including some sunny-day scenarios curtesy of Gabor. --- rts/idl.c | 23 +++++++++++++ src/codegen/compile.ml | 43 ++++++++++++++++++------- test/run-drun/idl-record.as | 34 +++++++++++++++++++ test/run-drun/ok/idl-record.drun-run.ok | 9 ++++++ 4 files changed, 97 insertions(+), 12 deletions(-) create mode 100644 test/run-drun/idl-record.as create mode 100644 test/run-drun/ok/idl-record.drun-run.ok diff --git a/rts/idl.c b/rts/idl.c index eb1d0ae7557..b8ace108259 100644 --- a/rts/idl.c +++ b/rts/idl.c @@ -276,3 +276,26 @@ export void skip_any(buf *b, uint8_t **typtbl, int32_t t, int32_t depth) { } } } + +export uint32_t find_field(buf *tb, buf *b, uint8_t **typtbl, uint32_t tag, uint32_t remaining_fields) { + while (remaining_fields-- > 0) { + uint32_t this_tag = read_u32_of_leb128(tb); + if (this_tag < tag) { + int32_t it = read_i32_of_sleb128(tb); + skip_any(b, typtbl, it, 0); + } else if (tag == this_tag) { + return remaining_fields; + } else { + idl_trap_with("expected record field skipped"); + } + } + idl_trap_with("expected record field missing"); +} + +export void skip_fields(buf *tb, buf *b, uint8_t **typtbl, uint32_t remaining_fields) { + while (remaining_fields-- > 0) { + skip_leb128(tb); + int32_t it = read_i32_of_sleb128(tb); + skip_any(b, typtbl, it, 0); + } +} diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index bf03fe3e908..69ada15952e 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -656,7 +656,9 @@ module RTS = struct E.add_func_import env "rts" "sleb128_encode" [I32Type; I32Type] []; E.add_func_import env "rts" "utf8_validate" [I32Type; I32Type] []; E.add_func_import env "rts" "skip_leb128" [I32Type] []; - E.add_func_import env "rts" "skip_any" [I32Type; I32Type; I32Type; I32Type] [] + E.add_func_import env "rts" "skip_any" [I32Type; I32Type; I32Type; I32Type] []; + E.add_func_import env "rts" "find_field" [I32Type; I32Type; I32Type; I32Type; I32Type] [I32Type]; + E.add_func_import env "rts" "skip_fields" [I32Type; I32Type; I32Type; I32Type] [] let system_exports env = E.add_export env (nr { @@ -3937,23 +3939,40 @@ module Serialization = struct (* Composite types *) | Tup ts -> with_composite_typ (-20l) (fun get_typ_buf -> - ReadBuf.read_leb128 env get_typ_buf ^^ G.i Drop ^^ - G.concat_map (fun t -> - ReadBuf.read_leb128 env get_typ_buf ^^ G.i Drop ^^ - ReadBuf.read_sleb128 env get_typ_buf ^^ - go env t + let (set_n, get_n) = new_local env "record_fields" in + ReadBuf.read_leb128 env get_typ_buf ^^ set_n ^^ + + G.concat_mapi (fun i t -> + (* skip all possible intermediate extra fields *) + get_typ_buf ^^ get_data_buf ^^ get_typtbl ^^ compile_unboxed_const (Int32.of_int i) ^^ get_n ^^ + E.call_import env "rts" "find_field" ^^ set_n ^^ + + ReadBuf.read_sleb128 env get_typ_buf ^^ go env t ) ts ^^ + + (* skip all possible trailing extra fields *) + get_typ_buf ^^ get_data_buf ^^ get_typtbl ^^ get_n ^^ + E.call_import env "rts" "skip_fields" ^^ + Tuple.from_stack env (List.length ts) ) | Obj (Object, fs) -> with_composite_typ (-20l) (fun get_typ_buf -> - ReadBuf.read_leb128 env get_typ_buf ^^ G.i Drop ^^ - Object.lit_raw env (List.map (fun (_h,f) -> + let (set_n, get_n) = new_local env "record_fields" in + ReadBuf.read_leb128 env get_typ_buf ^^ set_n ^^ + + Object.lit_raw env (List.map (fun (h,f) -> f.Type.lab, fun () -> - ReadBuf.read_leb128 env get_typ_buf ^^ G.i Drop ^^ - ReadBuf.read_sleb128 env get_typ_buf ^^ - go env f.typ - ) (sort_by_hash fs)) + (* skip all possible intermediate extra fields *) + get_typ_buf ^^ get_data_buf ^^ get_typtbl ^^ compile_unboxed_const (Lib.Uint32.to_int32 h) ^^ get_n ^^ + E.call_import env "rts" "find_field" ^^ set_n ^^ + + ReadBuf.read_sleb128 env get_typ_buf ^^ go env f.typ + ) (sort_by_hash fs)) ^^ + + (* skip all possible trailing extra fields *) + get_typ_buf ^^ get_data_buf ^^ get_typtbl ^^ get_n ^^ + E.call_import env "rts" "skip_fields" ) | Array t -> let (set_len, get_len) = new_local env "len" in diff --git a/test/run-drun/idl-record.as b/test/run-drun/idl-record.as new file mode 100644 index 00000000000..d1f23c1d553 --- /dev/null +++ b/test/run-drun/idl-record.as @@ -0,0 +1,34 @@ +// This test checks that the IDL decoder can +// do the subtyping from received many-field record +// to a double-field one (field names are in hash order) +actor { + public func pair(o : (Text, Int)) : async () { + switch o { + case (content, num) print ("ok: " # debug_show num); + } + }; + public func record(o : {content: Text; value : Int}) : async () { + switch o { + case {content} print ("ok: " # content); + } + }; + public func record1(o : {value : Int; byte : Int8}) : async () { + switch o { + case {byte} print ("ok: " # debug_show byte); + } + }; + public func record2(o : {content: Text; value : Int}, follower : Int8) : async Int8 { + switch o { + case {content} { print ("ok: " # " " # content # " " # debug_show follower); follower }; + } + }; +} + +//CALL ingress pair 0x4449444C016C020071017C010004486579212A +//CALL ingress record 0x4449444C016C02b99adecb0171f1fee18d037C010004486579212A +// SKIPPED +// CALL ingress record1 0x4449444C016C0388be8c890477b99adecb0171f1fee18d037C010004486579212A19 +// needs to jump over redundant `content` field +//CALL ingress record1 0x4449444C016C03b99adecb0171f1fee18d037C88be8c890477010004486579212A19 +// needs to jump over redundant trailing `byte` field +//CALL ingress record2 0x4449444C016C03b99adecb0171f1fee18d037C88be8c89047702007704486579212A1819 diff --git a/test/run-drun/ok/idl-record.drun-run.ok b/test/run-drun/ok/idl-record.drun-run.ok new file mode 100644 index 00000000000..4cb766a7111 --- /dev/null +++ b/test/run-drun/ok/idl-record.drun-run.ok @@ -0,0 +1,9 @@ +ingress(0) System +debug.print: ok: +42 +ingress(1) Completed: Canister: Payload: 0x4449444c016c000100 +debug.print: ok: Hey! +ingress(2) Completed: Canister: Payload: 0x4449444c016c000100 +debug.print: ok: +25 +ingress(3) Completed: Canister: Payload: 0x4449444c016c000100 +debug.print: ok: Hey! +25 +ingress(4) Completed: Canister: Payload: 0x4449444c00017719 From f1615167686e4f5bd7dee74e186db31b5cba23a9 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Tue, 1 Oct 2019 10:32:09 -0700 Subject: [PATCH 0429/1176] Add ActorSpec example (#626) --- stdlib/Makefile | 26 +++- stdlib/examples/actorspec/README.md | 28 ++++ stdlib/examples/actorspec/demo/Demo.as | 35 +++++ stdlib/examples/actorspec/src/ActorSpec.as | 147 +++++++++++++++++++++ 4 files changed, 234 insertions(+), 2 deletions(-) create mode 100644 stdlib/examples/actorspec/README.md create mode 100644 stdlib/examples/actorspec/demo/Demo.as create mode 100644 stdlib/examples/actorspec/src/ActorSpec.as diff --git a/stdlib/Makefile b/stdlib/Makefile index 206e28d5016..131fd4a7be9 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -9,6 +9,8 @@ PANDOC=pandoc STOPWATCH=$(OUTDIR)/stopwatch WASM=\ + ActorSpec \ + ActorSpecDemo \ ProduceExchange \ Rx \ @@ -235,14 +237,34 @@ $(DOCDIR)/%.html: $(DOCDIR)/%.md #########################################################################################################33 +## +## ActorSpec Example +## + +ACTORSPEC_SRC=\ + array.as \ + int.as \ + text.as \ + examples/actorspec/src/ActorSpec.as \ + examples/actorspec/demo/Demo.as \ + +$(OUTDIR)/ActorSpec.wasm: $(ACTORSPEC_SRC) | $(OUTDIR) + $(ASC) -c -o $@ examples/actorspec/src/ActorSpec.as + +$(OUTDIR)/ActorSpecDemo.wasm: $(ACTORSPEC_SRC) | $(OUTDIR) + $(ASC) -c -o $@ examples/actorspec/demo/Demo.as + + +#########################################################################################################33 + ## ## Rx Example ## RX_SRC=\ - array.as \ + array.as \ examples/rx/src/Rx.as \ - examples/rx/test/RxTest.as \ + examples/rx/test/RxTest.as \ $(OUTDIR)/RxTest.out: $(RX_SRC) \ examples/rx/test/RxTest.as | $(OUTDIR) diff --git a/stdlib/examples/actorspec/README.md b/stdlib/examples/actorspec/README.md new file mode 100644 index 00000000000..08c595584b1 --- /dev/null +++ b/stdlib/examples/actorspec/README.md @@ -0,0 +1,28 @@ +# ActorSpec + +A testing framework for ActorScript. + +## Demo + +```sh +$ cd dev/sdk/actorspec +$ nix-build demo +``` + +``` +ActorSpec: Failed: 1, Passed: 2, Pending: 1 + + passing specs: Failed: 0, Passed: 1, Pending: 0 + should pass: Passed + + failing specs: Failed: 1, Passed: 0, Pending: 0 + should fail: Failed + + pending specs: Failed: 0, Passed: 0, Pending: 1 + should be marked as pending: Pending + + nested groups: Failed: 0, Passed: 1, Pending: 0 + should have the correct indentation: Passed + +Failed: 1, Passed: 2, Pending: 1 +``` diff --git a/stdlib/examples/actorspec/demo/Demo.as b/stdlib/examples/actorspec/demo/Demo.as new file mode 100644 index 00000000000..f366682d8f4 --- /dev/null +++ b/stdlib/examples/actorspec/demo/Demo.as @@ -0,0 +1,35 @@ +import ActorSpec "../src/ActorSpec.as"; + +type Group = ActorSpec.Group; + +let assertTrue = ActorSpec.assertTrue; +let describe = ActorSpec.describe; +let it = ActorSpec.it; +let pending = ActorSpec.pending; +let run = ActorSpec.run; + +run([ + describe("ActorSpec", [ + describe("passing specs", [ + it("should pass", { + assertTrue(true); + }), + ]), + + describe("failing specs", [ + it("should fail", { + assertTrue(false); + }), + ]), + + describe("pending specs", [ + pending("should be marked as pending"), + ]), + + describe("nested groups", [ + it("should have the correct indentation", { + assertTrue(true); + }), + ]), + ]), +]); diff --git a/stdlib/examples/actorspec/src/ActorSpec.as b/stdlib/examples/actorspec/src/ActorSpec.as new file mode 100644 index 00000000000..14c9c4e8b6f --- /dev/null +++ b/stdlib/examples/actorspec/src/ActorSpec.as @@ -0,0 +1,147 @@ +module { + import Array "../../../array.as"; + import Int "../../../int.as"; + import Text "../../../text.as"; + + public type Group = { + name : Text; + groups : [Group]; + status : Status; + }; + + + type Status = { + failed : Nat; + passed : Nat; + pending : Nat; + }; + + func eqStatus(x : Status, y : Status) : Bool { + x.failed == y.failed and x.passed == y.passed and x.pending == y.pending; + }; + + let emptyStatus : Status = { + failed = 0; + passed = 0; + pending = 0; + }; + + func appendStatus(x : Status, y : Status) : Status { + { + failed = x.failed + y.failed; + passed = x.passed + y.passed; + pending = x.pending + y.pending; + }; + }; + + func printStatus(status : Status) : Text { + "Failed: " # Int.toText(status.failed) # ", Passed: " # Int.toText(status.passed) # ", Pending: " # Int.toText(status.pending); + }; + + + public func run(groups_ : [Group]) : Bool { + let (groups, status) = getGroups(groups_); + printGroups(groups, ""); + print("\n"); + print(printStatus(status)); + print("\n"); + print("\n"); + status.failed == 0; + }; + + func getGroups(groups_ : [Group]) : ([Group], Status) { + let groups = Array.thaw(groups_); + var status = emptyStatus; + for (index in groups_.keys()) { + let group = groups[index]; + let (newGroups, newGroupsStatus) = getGroups(group.groups); + let newStatus = appendStatus(group.status, newGroupsStatus); + status := appendStatus(status, newStatus); + let newGroup = { + name = group.name; + groups = newGroups; + status = newStatus; + }; + groups[index] := newGroup; + }; + (Array.freeze(groups), status); + }; + + func printGroups(groups_ : [Group], indent : Text) { + for (group in groups_.vals()) { + let isDescribe = group.groups.len() > 0; + let newline = if isDescribe "\n" else ""; + let status = group.status; + let statusText = if (isDescribe) { + ": " # printStatus(status); + } else { + let failed = status.failed; + let passed = status.passed; + let pending = status.pending; + switch(failed, passed, pending) { + case (0, 0, 0) { ""; }; + case (1, 0, 0) { ": Failed"; }; + case (0, 1, 0) { ": Passed"; }; + case (0, 0, 1) { ": Pending"; }; + case (_, _, _) { ":" # printStatus(status); }; + }; + }; + print(newline # indent # group.name # statusText # "\n"); + printGroups(group.groups, indent # " "); + }; + }; + + + public func describe(name_ : Text, groups_ : [Group]) : Group { + { + name = name_; + groups = groups_; + status = emptyStatus; + }; + }; + + public func it(name_ : Text, passed_ : Bool) : Group { + { + name = name_; + groups = []; + status = { + failed = if passed_ 0 else 1; + passed = if passed_ 1 else 0; + pending = 0; + }; + }; + }; + + public let test = it; + + public func pending(name_ : Text) : Group { + { + name = name_; + groups = []; + status = { + failed = 0; + passed = 0; + pending = 1; + }; + }; + }; + + public func assertTrue(x : Bool) : Bool { + x == true; + }; + + public func assertFalse(x : Bool) : Bool { + x == false; + }; + + public func assertAllTrue(xs : [Bool]) : Bool { + var allTrue = true; + for (val in xs.vals()) { + if (val == false) { + return false; + }; + allTrue := allTrue and val; + }; + allTrue; + }; +} From 44d6d3c937e330e697bfeb2e19b15e34d9031452 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Wed, 2 Oct 2019 11:46:22 +0200 Subject: [PATCH 0430/1176] typos (#717) --- src/codegen/compile.ml | 2 +- stdlib/trie.as | 2 +- stdlib/trie2.as | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 69ada15952e..ca8dae60200 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -2632,7 +2632,7 @@ module Text = struct let unskewed_payload_offset = Int32.(add ptr_unskew (mul Heap.word_size header_size)) let payload_ptr_unskewed = compile_add_const unskewed_payload_offset - (* String concatentation. Expects two strings on stack *) + (* String concatenation. Expects two strings on stack *) let concat env = Func.share_code2 env "concat" (("x", I32Type), ("y", I32Type)) [I32Type] (fun env get_x get_y -> let (set_z, get_z) = new_local env "z" in let (set_len1, get_len1) = new_local env "len1" in diff --git a/stdlib/trie.as b/stdlib/trie.as index d8b55aee50c..cc78a549bc8 100644 --- a/stdlib/trie.as +++ b/stdlib/trie.as @@ -1082,7 +1082,7 @@ public type Trie3D = Trie >; rec(tl, tr) }; - // Equality function for two `Key`s, in terms of equaltiy of `K`'s. + // Equality function for two `Key`s, in terms of equality of `K`'s. public func keyEq(keq:(K,K) -> Bool) : ((Key,Key) -> Bool) = { func (key1:Key, key2:Key) : Bool = label profile_trie_keyEq : Bool diff --git a/stdlib/trie2.as b/stdlib/trie2.as index 76c90186606..e01aa54ef5d 100644 --- a/stdlib/trie2.as +++ b/stdlib/trie2.as @@ -95,7 +95,7 @@ public type Key = { key: K; }; -/** Equality function for two `Key`s, in terms of equaltiy of `K`'s. */ +/** Equality function for two `Key`s, in terms of equality of `K`'s. */ public func keyEq(keq:(K,K) -> Bool) : ((Key,Key) -> Bool) = { func (key1:Key, key2:Key) : Bool = label profile_trie_keyEq : Bool From 318bbe8b066d402e8f4246db31dfb34d127129cf Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Wed, 2 Oct 2019 15:54:15 +0200 Subject: [PATCH 0431/1176] State that natural storage types are submitted in little endian (#720) --- design/IDL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/design/IDL.md b/design/IDL.md index 669339341e5..7e2e2634a88 100644 --- a/design/IDL.md +++ b/design/IDL.md @@ -894,7 +894,7 @@ Note: #### Notation -`T` and `M` create a byte sequence described below in terms of natural storage types (`i` for `N = 8, 16, 32, 64`, `f` for `N = 32, 64`). +`T` and `M` create a byte sequence described below in terms of natural storage types (`i` for `N = 8, 16, 32, 64`, `f` for `N = 32, 64`). The bytes are sequenced according to increasing significance (least significant byte first, a.k.a. little-endian). The following notation is used: From 1e5e456e650cfce87647fe8209978026387c6036 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Wed, 2 Oct 2019 17:12:03 +0200 Subject: [PATCH 0432/1176] Add a test with proper tuples (i.e. non-top-level) ACT-138 (#722) * add a test with proper tuples (i.e. non-top-level) * test ignoring of redundant tuple members * Update test/run-drun/idl-tuple.as Co-Authored-By: Joachim Breitner --- test/run-drun/idl-tuple.as | 10 ++++++++++ test/run-drun/ok/idl-tuple.drun-run.ok | 3 +++ 2 files changed, 13 insertions(+) diff --git a/test/run-drun/idl-tuple.as b/test/run-drun/idl-tuple.as index cbadf7cd564..374edb88ec0 100644 --- a/test/run-drun/idl-tuple.as +++ b/test/run-drun/idl-tuple.as @@ -1,7 +1,17 @@ actor { + // top-level tuple public func len2(x:Text, y:Text) : async (Int,Int) { (x.len(), y.len()) + }; + // a pair embedded in top-level tuple + public func len3((x:Text, i:Int32), y:Text) : async (Int,Int,Int) { + (x.len(), y.len(), int32ToInt i) } } //CALL query len2 "DIDL\x00\x02\x71\x71\x02Hi\x05World" +//CALL query len3 0x4449444c016c02007101750200710548656c6c6f0102030405576f726c64 +// testing redundant first tuple member (repeated hash with different type), currently ignored, it is although invalid IDL data +//CALL query len3 0x4449444c016c030071007601750200710548656c6c6fdead0102030405576f726c64 +// testing redundant third tuple member, gets ignored +//CALL query len3 0x4449444c016c030071017502760200710548656c6c6f01020304dead05576f726c64 diff --git a/test/run-drun/ok/idl-tuple.drun-run.ok b/test/run-drun/ok/idl-tuple.drun-run.ok index 428fcb5b372..3ec4595483e 100644 --- a/test/run-drun/ok/idl-tuple.drun-run.ok +++ b/test/run-drun/ok/idl-tuple.drun-run.ok @@ -1,2 +1,5 @@ ingress(0) System Ok: Payload: 0x4449444c016c02007c017c01000205 +Ok: Payload: 0x4449444c016c03007c017c027c0100050581848c20 +Ok: Payload: 0x4449444c016c03007c017c027c0100050581848c20 +Ok: Payload: 0x4449444c016c03007c017c027c0100050581848c20 From e58e1e3cce5a136d356180adbbd095b5a3ecde18 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 2 Oct 2019 18:43:29 +0100 Subject: [PATCH 0433/1176] Claudio/query ACT-120 (#713) * remove noisy test throw.as * first-stab at query support; faked on dvm; still committing in interpeter * make interpreters run on queries (sans state rollback, though); add drun test * omit collection in (static) query method in ICMode * reduce diff with original type checker * add longform as well as shorthand for function/function space modifier; add dvm test; add todo to guide.md * cleanup check_ir * add missing test * Update src/ir_def/check_ir.ml Co-Authored-By: Joachim Breitner * Update src/as_types/type.ml Co-Authored-By: Andreas Rossberg * Update src/as_frontend/typing.ml Co-Authored-By: Andreas Rossberg * Update src/as_types/arrange_type.ml Co-Authored-By: Andreas Rossberg * address review * nits * nit --- guide/guide.md | 3 ++ src/as_def/arrange.ml | 3 +- src/as_frontend/lexer.mll | 1 + src/as_frontend/parser.mly | 13 ++++-- src/as_frontend/typing.ml | 13 +++--- src/as_idl/as_to_idl.ml | 9 +++- src/as_interpreter/interpret.ml | 10 ++--- src/as_types/arrange_type.ml | 3 +- src/as_types/call_conv.ml | 4 +- src/as_types/call_conv.mli | 4 +- src/as_types/type.ml | 17 +++++--- src/as_types/type.mli | 7 +++- src/as_values/value.ml | 4 +- src/as_values/value.mli | 4 +- src/codegen/compile.ml | 50 ++++++++++++++-------- src/ir_def/check_ir.ml | 12 +++--- src/ir_def/construct.ml | 2 +- src/ir_interpreter/interpret_ir.ml | 10 ++--- src/ir_passes/async.ml | 16 +++---- src/lowering/desugar.ml | 2 +- test/run-dfinity/ok/query.dvm-run.ok | 8 ++++ test/run-dfinity/ok/query.run-ir.ok | 9 ++++ test/run-dfinity/ok/query.run-low.ok | 9 ++++ test/run-dfinity/ok/query.run.ok | 9 ++++ test/run-dfinity/query.as | 62 ++++++++++++++++++++++++++++ test/run-drun/ok/query.drun-run.ok | 34 +++++++++++++++ test/run-drun/query.as | 29 +++++++++++++ 27 files changed, 276 insertions(+), 71 deletions(-) create mode 100644 test/run-dfinity/ok/query.dvm-run.ok create mode 100644 test/run-dfinity/ok/query.run-ir.ok create mode 100644 test/run-dfinity/ok/query.run-low.ok create mode 100644 test/run-dfinity/ok/query.run.ok create mode 100644 test/run-dfinity/query.as create mode 100644 test/run-drun/ok/query.drun-run.ok create mode 100644 test/run-drun/query.as diff --git a/guide/guide.md b/guide/guide.md index b44bead848c..5c846247de2 100644 --- a/guide/guide.md +++ b/guide/guide.md @@ -24,7 +24,10 @@ TODO: * [ ] Include actual grammar (extracted from menhir) in appendix? * [ ] Prose description of definedness checks * [ ] Platform changes: remove async expressions (and perhaps types); restrict await to shared calls. +* [ ] Queries +* [ ] Remove Shared type --> + # Introduction The **internet computer** is a network of connected computers that communicate securely and provide processing services to registered users, developers, and other computers. diff --git a/src/as_def/arrange.ml b/src/as_def/arrange.ml index 3f979abdc0e..8fffc8379bd 100644 --- a/src/as_def/arrange.ml +++ b/src/as_def/arrange.ml @@ -109,7 +109,8 @@ and obj_sort s = match s.it with and func_sort s = match s.it with | Type.Local -> Atom "Local" - | Type.Shared -> Atom "Shared" + | Type.Shared Type.Write -> Atom "Shared" + | Type.Shared Type.Query -> Atom "Query" and mut m = match m.it with | Const -> Atom "Const" diff --git a/src/as_frontend/lexer.mll b/src/as_frontend/lexer.mll index 2b57ea8def9..3a4998ecff1 100644 --- a/src/as_frontend/lexer.mll +++ b/src/as_frontend/lexer.mll @@ -217,6 +217,7 @@ rule token mode = parse | "try" { TRY } | "throw" { THROW } | "debug_show" { DEBUG_SHOW } + | "query" { QUERY } | "switch" { SWITCH } | "true" { BOOL true } | "type" { TYPE } diff --git a/src/as_frontend/parser.mly b/src/as_frontend/parser.mly index 8f1bb158e2d..abb188f5b8f 100644 --- a/src/as_frontend/parser.mly +++ b/src/as_frontend/parser.mly @@ -67,7 +67,7 @@ let let_or_exp named x e' at = let share_typ t = match t.it with | FuncT ({it = Type.Local; _} as s, tbs, t1, t2) -> - { t with it = FuncT ({s with it = Type.Shared}, tbs, t1, t2)} + { t with it = FuncT ({s with it = Type.Shared Type.Write}, tbs, t1, t2)} | _ -> t let share_typfield (tf : typ_field) = @@ -76,7 +76,7 @@ let share_typfield (tf : typ_field) = let share_exp e = match e.it with | FuncE (x, ({it = Type.Local; _} as s), tbs, p, t, e) -> - FuncE (x, {s with it = Type.Shared}, tbs, p, t, e) @? e.at + FuncE (x, {s with it = Type.Shared Type.Write}, tbs, p, t, e) @? e.at | _ -> e let share_dec d = @@ -98,7 +98,7 @@ let share_expfield (ef : exp_field) = %token AWAIT ASYNC BREAK CASE CATCH CONTINUE LABEL DEBUG %token IF IN ELSE SWITCH LOOP WHILE FOR RETURN TRY THROW %token ARROW ASSIGN -%token FUNC TYPE OBJECT ACTOR CLASS PUBLIC PRIVATE SHARED +%token FUNC TYPE OBJECT ACTOR CLASS PUBLIC PRIVATE SHARED QUERY %token SEMICOLON SEMICOLON_EOL COMMA COLON SUB DOT QUEST %token AND OR NOT %token IMPORT MODULE @@ -192,9 +192,14 @@ seplist1(X, SEP) : | (* empty *) { Type.Object @@ no_region } | s=obj_sort { s } +%inline mode_opt : + | (* empty *) { Type.Write } + | QUERY { Type.Query } + %inline func_sort_opt : | (* empty *) { Type.Local @@ no_region } - | SHARED { Type.Shared @@ at $sloc } + | SHARED m=mode_opt { Type.Shared m @@ at $sloc } + | QUERY { Type.Shared Type.Query @@ at $sloc } (* Paths *) diff --git a/src/as_frontend/typing.ml b/src/as_frontend/typing.ml index 16cf951b801..cbcde50973c 100644 --- a/src/as_frontend/typing.ml +++ b/src/as_frontend/typing.ml @@ -196,7 +196,7 @@ and check_typ' env typ : T.typ = let ts1 = List.map (check_typ env') typs1 in let ts2 = List.map (check_typ env') typs2 in let c = match typs2 with [{it = AsyncT _; _}] -> T.Promises | _ -> T.Returns in - if sort.it = T.Shared then + if Type.is_shared_sort sort.it then if not env.pre then begin let t1 = T.seq ts1 in if not (T.shared t1) then @@ -204,7 +204,8 @@ and check_typ' env typ : T.typ = "shared function has non-shared parameter type\n %s" (T.string_of_typ_expand t1); match ts2 with - | [] | [T.Async _] -> () + | [] when sort.it = T.Shared T.Write -> () + | [T.Async _] -> () | _ -> error env typ2.at "shared function has non-async result type\n %s" @@ -627,13 +628,13 @@ and infer_exp'' env exp : T.typ = let env'' = {env' with labs = T.Env.empty; rets = Some t2; async = false} in check_exp (adjoin_vals env'' ve) t2 exp; - if sort.it = T.Shared then begin + if Type.is_shared_sort sort.it then begin if not (T.shared t1) then error env pat.at "shared function has non-shared parameter type\n %s" (T.string_of_typ_expand t1); match t2 with - | T.Tup [] -> () + | T.Tup [] when sort.it = T.Shared T.Write -> () | T.Async _ -> if not (isAsyncE exp) then error env exp.at @@ -647,7 +648,7 @@ and infer_exp'' env exp : T.typ = let ts2 = match typ.it with TupT _ -> T.as_seq t2 | _ -> [t2] in let c = match sort.it, typ.it with - | T.Shared, (AsyncT _) -> T.Promises (* TBR: do we want this for T.Local too? *) + | T.Shared _, AsyncT _ -> T.Promises | _ -> T.Returns in let tbs = List.map2 (fun c t -> {T.var = Con.name c; bound = T.close cs t}) cs ts in @@ -666,7 +667,7 @@ and infer_exp'' env exp : T.typ = let t_ret = T.open_ ts t_ret in if not env.pre then begin check_exp env t_arg exp2; - if sort = T.Shared then begin + if Type.is_shared_sort sort then begin if not (T.concrete t_arg) then error env exp1.at "shared function argument contains abstract type\n %s" diff --git a/src/as_idl/as_to_idl.ml b/src/as_idl/as_to_idl.ml index 2eb52bb8564..aa3f9f33022 100644 --- a/src/as_idl/as_to_idl.ml +++ b/src/as_idl/as_to_idl.ml @@ -109,11 +109,16 @@ let rec typ vs t = | Obj (Module, _) -> assert false | Variant fs -> I.VariantT (List.map (field vs) fs) - | Func (Shared, c, [], ts1, ts2) -> + | Func (Shared s, c, [], ts1, ts2) -> let fs1 = tuple vs ts1 in (match ts2 with | [] when c = Returns -> I.FuncT ([I.Oneway @@ no_region], fs1, []) - | [Async t] when c = Promises -> I.FuncT ([], fs1, tuple vs [t]) + | [Async t] when c = Promises -> + I.FuncT ( + (match s with + | Query -> [I.Query @@ no_region] + | Write -> []), + fs1, tuple vs [t]) | _ -> assert false) | Func _ -> assert false | Async t -> assert false diff --git a/src/as_interpreter/interpret.ml b/src/as_interpreter/interpret.ml index 7d7ae3c503f..116f36ff39b 100644 --- a/src/as_interpreter/interpret.ml +++ b/src/as_interpreter/interpret.ml @@ -201,8 +201,8 @@ let make_unit_message env id v = let open CC in let call_conv, f = V.as_func v in match call_conv with - | {sort = T.Shared; n_res = 0; _} -> - Value.message_func call_conv.n_args (fun v k -> + | {sort = T.Shared s; n_res = 0; _} -> + Value.message_func s call_conv.n_args (fun v k -> actor_msg env id f v (fun _ -> ()); k V.unit ) @@ -213,8 +213,8 @@ let make_async_message env id v = let open CC in let call_conv, f = V.as_func v in match call_conv with - | {sort = T.Shared; control = T.Promises; n_res = 1; _} -> - Value.async_func call_conv.n_args (fun v k -> + | {sort = T.Shared s; control = T.Promises; n_res = 1; _} -> + Value.async_func s call_conv.n_args (fun v k -> let async = make_async () in actor_msg env id f v (fun v_async -> get_async (V.as_async v_async) (set_async async) (reject_async async) @@ -463,7 +463,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = let v = V.Func (CC.call_conv_of_typ exp.note.note_typ, f) in let v' = match _sort.it with - | T.Shared -> make_message env name exp.note.note_typ v + | T.Shared _ -> make_message env name exp.note.note_typ v | T.Local -> v in k v' | CallE (exp1, typs, exp2) -> diff --git a/src/as_types/arrange_type.ml b/src/as_types/arrange_type.ml index 72bc43f4d19..693b10a14da 100644 --- a/src/as_types/arrange_type.ml +++ b/src/as_types/arrange_type.ml @@ -14,7 +14,8 @@ let obj_sort s = match s with let func_sort s = match s with | Local -> "Local" - | Shared -> "Shared" + | Shared Write -> "Shared" + | Shared Query -> "Shared Query" let prim p = match p with | Null -> Atom "Null" diff --git a/src/as_types/call_conv.ml b/src/as_types/call_conv.ml index 8adc8121116..8497ea0ad69 100644 --- a/src/as_types/call_conv.ml +++ b/src/as_types/call_conv.ml @@ -9,8 +9,8 @@ type call_conv = { type t = call_conv let local_cc n m = { sort = Local; control = Returns; n_args = n; n_res = m} -let message_cc n = { sort = Shared; control = Returns; n_args = n; n_res = 0} -let async_cc n = { sort = Shared; control = Promises; n_args = n; n_res = 1} +let message_cc s n = { sort = Shared s; control = Returns; n_args = n; n_res = 0} +let async_cc s n = { sort = Shared s; control = Promises; n_args = n; n_res = 1} let call_conv_of_typ typ = match typ with diff --git a/src/as_types/call_conv.mli b/src/as_types/call_conv.mli index b1930824765..9ab6ee92631 100644 --- a/src/as_types/call_conv.mli +++ b/src/as_types/call_conv.mli @@ -9,8 +9,8 @@ type call_conv = { type t = call_conv val local_cc : int -> int -> call_conv -val message_cc : int -> call_conv -val async_cc : int -> call_conv +val message_cc : Type.shared_sort -> int -> call_conv +val async_cc : Type.shared_sort -> int -> call_conv val call_conv_of_typ : Type.typ -> call_conv diff --git a/src/as_types/type.ml b/src/as_types/type.ml index 136fed438bd..4d91a92ad40 100644 --- a/src/as_types/type.ml +++ b/src/as_types/type.ml @@ -5,7 +5,8 @@ type var = string type control = Returns | Promises (* Returns a computed value or immediate promise *) type obj_sort = Object | Actor | Module -type func_sort = Local | Shared +type shared_sort = Query | Write +type func_sort = Local | Shared of shared_sort type eff = Triv | Await type prim = @@ -56,6 +57,9 @@ and kind = | Def of bind list * typ | Abs of bind list * typ +(* Function sorts *) + +let is_shared_sort sort = sort <> Local (* Constructors *) @@ -97,8 +101,8 @@ let catchErrorCodes = List.sort compare_field ( (* TBC *) ]) -let throw = Prim Error (* Tup [Variant throwErrorCodes; text] *) -let catch = Prim Error (* Tup [Variant catchErrorCodes; text] *) +let throw = Prim Error +let catch = Prim Error let prim = function | "Null" -> Null @@ -566,7 +570,7 @@ let shared t = | Tup ts -> List.for_all go ts | Obj (s, fs) -> s = Actor || List.for_all (fun f -> go f.typ) fs | Variant fs -> List.for_all (fun f -> go f.typ) fs - | Func (s, c, tbs, ts1, ts2) -> s = Shared + | Func (s, c, tbs, ts1, ts2) -> is_shared_sort s end in go t @@ -1065,7 +1069,8 @@ let string_of_obj_sort = function let string_of_func_sort = function | Local -> "" - | Shared -> "shared " + | Shared Write -> "shared " + | Shared Query -> "shared query " let rec string_of_typ_nullary vs = function | Pre -> "???" @@ -1197,3 +1202,5 @@ let rec string_of_typ_expand t = | t' -> s ^ " = " ^ string_of_typ_expand t' ) | _ -> s + +let is_shared_sort sort = sort <> Local diff --git a/src/as_types/type.mli b/src/as_types/type.mli index 40259e91b4a..74ed4e408b3 100644 --- a/src/as_types/type.mli +++ b/src/as_types/type.mli @@ -5,7 +5,8 @@ type var = string type control = Returns | Promises (* returns a computed value or immediate promise *) type obj_sort = Object | Actor | Module -type func_sort = Local | Shared +type shared_sort = Query | Write +type func_sort = Local | Shared of shared_sort type eff = Triv | Await type prim = @@ -56,6 +57,9 @@ and kind = | Def of bind list * typ | Abs of bind list * typ +(* Function sorts *) + +val is_shared_sort : func_sort -> bool (* Short-hands *) @@ -198,3 +202,4 @@ val string_of_typ : typ -> string val string_of_kind : kind -> string val strings_of_kind : kind -> string * string * string val string_of_typ_expand : typ -> string + diff --git a/src/as_values/value.ml b/src/as_values/value.ml index 4a3ddb1bffe..5370c1a1561 100644 --- a/src/as_values/value.ml +++ b/src/as_values/value.ml @@ -302,8 +302,8 @@ and 'a cont = 'a -> unit let unit = Tup [] let local_func n m f = Func (Call_conv.local_cc n m, f) -let message_func n f = Func (Call_conv.message_cc n, f) -let async_func n f = Func (Call_conv.async_cc n, f) +let message_func s n f = Func (Call_conv.message_cc s n, f) +let async_func s n f = Func ( Call_conv.async_cc s n, f) (* Projections *) diff --git a/src/as_values/value.mli b/src/as_values/value.mli index 69787d9fc0c..5e0b4c92987 100644 --- a/src/as_values/value.mli +++ b/src/as_values/value.mli @@ -115,8 +115,8 @@ and 'a cont = 'a -> unit val unit : value val local_func : int -> int -> func -> value -val message_func : int -> func -> value -val async_func : int -> func -> value +val message_func : Type.shared_sort -> int -> func -> value +val async_func : Type.shared_sort -> int -> func -> value (* Projections *) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index ca8dae60200..83d28f5a925 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -3424,7 +3424,7 @@ module Serialization = struct end | Array t -> go t | Tup ts -> List.for_all go ts - | Func (Shared, c, tbs, ts1, ts2) -> false + | Func (Shared _, c, tbs, ts1, ts2) -> false | Func (s, c, tbs, ts1, ts2) -> let ts = open_binds tbs in List.for_all go (List.map (open_ ts) ts1) && @@ -4830,11 +4830,16 @@ module FuncDec = struct closure_code ^^ mk_body env ae2 ^^ - (* Collect garbage *) - G.i (Call (nr (E.built_in env "collect"))) ^^ - - (* Save memory *) - OrthogonalPersistence.save_mem env + match cc.Call_conv.sort with + | Type.Shared Type.Write -> + (* Collect garbage *) + G.i (Call (nr (E.built_in env "collect"))) ^^ + (* Save memory *) + OrthogonalPersistence.save_mem env + | Type.Shared Type.Query -> + (* Don't collect or persist *) + G.i Nop + | _ -> assert false )) let compile_static_message outer_env outer_ae cc args mk_body ret_tys at : E.func_with_names = @@ -4856,13 +4861,19 @@ module FuncDec = struct get_databuf ^^ get_elembuf ^^ Serialization.deserialize env arg_tys ^^ G.concat (List.rev setters) ^^ - mk_body env ae1 ^^ - (* Collect garbage *) - G.i (Call (nr (E.built_in env "collect"))) ^^ + mk_body env ae1 ^^ - (* Save memory *) - OrthogonalPersistence.save_mem env + match cc.Call_conv.sort with + | Type.Shared Type.Write -> + (* Collect garbage *) + G.i (Call (nr (E.built_in env "collect"))) ^^ + (* Save memory *) + OrthogonalPersistence.save_mem env + | Type.Shared Type.Query -> + (* Don't collect or persist *) + G.i Nop + | _ -> assert false )) | Flags.ICMode -> let ae0 = ASEnv.mk_fun_ae outer_ae in @@ -4876,9 +4887,14 @@ module FuncDec = struct Serialization.deserialize env arg_tys ^^ G.concat (List.rev setters) ^^ mk_body env ae1 ^^ - - (* Collect garbage *) - G.i (Call (nr (E.built_in env "collect"))) + match cc.Call_conv.sort with + | Type.Shared Type.Write -> + (* Collect garbage *) + G.i (Call (nr (E.built_in env "collect"))) + | Type.Shared Type.Query -> + (* Don't collect *) + G.i Nop + | _ -> assert false )) | Flags.WasmMode -> assert false @@ -4892,7 +4908,7 @@ module FuncDec = struct (* Compile a closed function declaration (captures no local variables) *) let closed pre_env cc name args mk_body ret_tys at = let (fi, fill) = E.reserve_fun pre_env name in - if cc.Call_conv.sort = Type.Shared + if Type.is_shared_sort cc.Call_conv.sort then begin declare_dfinity_type pre_env false fi ; ( SR.StaticMessage fi, fun env ae -> @@ -4906,7 +4922,7 @@ module FuncDec = struct (* Compile a closure declaration (captures local variables) *) let closure env ae cc name captured args mk_body at = - let is_local = cc.Call_conv.sort <> Type.Shared in + let is_local = cc.Call_conv.sort = Type.Local in let (set_clos, get_clos) = new_local env (name ^ "_clos") in @@ -6312,7 +6328,7 @@ and compile_exp (env : E.t) ae exp = compile_exp_as env ae (StackRep.of_arity cc.Call_conv.n_args) e2 ^^ get_clos ^^ Closure.call_closure env cc - | _, Type.Shared -> + | _, Type.Shared _ -> let (set_funcref, get_funcref) = new_local env "funcref" in code1 ^^ StackRep.adjust env fun_sr SR.UnboxedReference ^^ set_funcref ^^ diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 193a578ae65..bd3650d93c7 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -162,10 +162,10 @@ let rec check_typ env typ : unit = error env no_region "promising function with non-async result type \n %s" (T.string_of_typ_expand t2) end; - if sort = T.Shared then begin + if T.is_shared_sort sort then begin List.iter (fun t -> check_shared env no_region t) ts1; match ts2 with - | [] -> () + | [] when not env.flavor.Ir.has_async_typ || sort = T.Shared T.Write -> () | [T.Async t2] -> check env' no_region (T.shared t2) "message result is not sharable:\n %s" (T.string_of_typ_expand t2) @@ -438,7 +438,7 @@ let rec check_exp env (exp:Ir.exp) : unit = check_exp env exp2; let t_arg = T.open_ insts t2 in let t_ret = T.open_ insts t3 in - if (call_conv.Call_conv.sort = T.Shared) then begin + if T.is_shared_sort call_conv.Call_conv.sort then begin check_concrete env exp.at t_arg; check_concrete env exp.at t_ret; end; @@ -558,21 +558,21 @@ let rec check_exp env (exp:Ir.exp) : unit = let env' = adjoin_cons env ce in let ve = check_args env' args in List.iter (check_typ env') ret_tys; - check ((cc.Call_conv.sort = T.Shared && Type.is_async (T.seq ret_tys)) + check ((T.is_shared_sort cc.Call_conv.sort && Type.is_async (T.seq ret_tys)) ==> isAsyncE exp) "shared function with async type has non-async body"; check (cc.Call_conv.n_args = List.length args) "calling convention arity does not match number of parameters"; check (cc.Call_conv.n_res = List.length ret_tys) "calling convention arity does not match number of return types"; - if (cc.Call_conv.sort = T.Shared) then List.iter (check_concrete env exp.at) ret_tys; + if T.is_shared_sort cc.Call_conv.sort then List.iter (check_concrete env exp.at) ret_tys; let env'' = {env' with labs = T.Env.empty; rets = Some (T.seq ret_tys); async = false} in check_exp (adjoin_vals env'' ve) exp; check_sub env' exp.at (typ exp) (T.seq ret_tys); (* Now construct the function type and compare with the annotation *) let ts1 = List.map (fun a -> a.note) args in - if (cc.Call_conv.sort = T.Shared) then List.iter (check_concrete env exp.at) ts1; + if T.is_shared_sort cc.Call_conv.sort then List.iter (check_concrete env exp.at) ts1; let fun_ty = T.Func ( cc.Call_conv.sort, cc.Call_conv.control , tbs, List.map (T.close cs) ts1, List.map (T.close cs) ret_tys diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index f25425161f3..093d0d61ed2 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -466,7 +466,7 @@ let (-->*) xs exp = (* n-ary shared lambda *) let (-@>*) xs exp = - let fun_ty = T.Func (T.Shared, T.Returns, [], List.map typ xs, T.as_seq (typ exp)) in + let fun_ty = T.Func (T.Shared T.Write, T.Returns, [], List.map typ xs, T.as_seq (typ exp)) in nary_funcE "$lambda" fun_ty xs exp diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index c07d77958b1..96603cb4b89 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -186,8 +186,8 @@ let make_unit_message env id v = let open CC in let call_conv, f = V.as_func v in match call_conv with - | {sort = T.Shared; n_res = 0; _} -> - Value.message_func call_conv.n_args (fun v k -> + | {sort = T.Shared s; n_res = 0; _} -> + Value.message_func s call_conv.n_args (fun v k -> actor_msg env id f v (fun _ -> ()); k V.unit ) @@ -200,8 +200,8 @@ let make_async_message env id v = let open CC in let call_conv, f = V.as_func v in match call_conv with - | {sort = T.Shared; control = T.Promises; n_res = 1; _} -> - Value.async_func call_conv.n_args (fun v k -> + | {sort = T.Shared s; control = T.Promises; n_res = 1; _} -> + Value.async_func s call_conv.n_args (fun v k -> let async = make_async () in actor_msg env id f v (fun v_async -> get_async (V.as_async v_async) (set_async async) (reject_async async) @@ -471,7 +471,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = let v = V.Func (cc, f) in let v = match cc.sort with - | T.Shared -> make_message env x cc v + | T.Shared _ -> make_message env x cc v | _-> v in k v diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index 3f0dc730c7a..5d03409222e 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -113,9 +113,9 @@ module Transform(Platform : sig val platform : platform end) = struct let nary typ = T.as_seq typ - let replyT as_seq typ = T.Func(T.Shared, T.Returns, [], as_seq typ, []) + let replyT as_seq typ = T.Func(T.Shared T.Write, T.Returns, [], as_seq typ, []) - let rejectT = T.Func(T.Shared, T.Returns, [], [T.text], []) + let rejectT = T.Func(T.Shared T.Write, T.Returns, [], [T.text], []) let fulfillT as_seq typ = T.Func(T.Local, T.Returns, [], as_seq typ, []) @@ -194,7 +194,7 @@ module Transform(Platform : sig val platform : platform end) = struct let isAwaitableFunc exp = match typ exp with - | T.Func (T.Shared,T.Promises,_,_,[T.Async _]) -> true + | T.Func (T.Shared _,T.Promises,_,_,[T.Async _]) -> true | _ -> false let extendTup ts ts' = ts @ ts' @@ -228,7 +228,7 @@ module Transform(Platform : sig val platform : platform end) = struct | Func (s, c, tbs, t1, t2) -> begin match s with - | T.Shared -> + | T.Shared _ -> begin match t2 with | [] -> @@ -334,7 +334,7 @@ module Transform(Platform : sig val platform : platform end) = struct let v1 = fresh_var "v" t1 in let r = fresh_var "r" err_contT in let e = fresh_var "e" T.catch in - let post = fresh_var "post" (T.Func(T.Shared, T.Returns, [], [], [])) in + let post = fresh_var "post" (T.Func(T.Shared T.Write, T.Returns, [], [], [])) in let u = fresh_var "u" T.unit in let ((nary_async, nary_reply, reject), def) = new_nary_async_reply t1 in (blockE [letP (tupP [varP nary_async; varP nary_reply; varP reject]) def; @@ -347,7 +347,7 @@ module Transform(Platform : sig val platform : platform end) = struct | CallE (cc, exp1, typs, exp2) when isAwaitableFunc exp1 -> let ts1,t2 = match typ exp1 with - | T.Func (T.Shared,T.Promises,tbs,ts1,[T.Async t2]) -> + | T.Func (T.Shared _, T.Promises,tbs,ts1,[T.Async t2]) -> List.map t_typ ts1, t_typ t2 | _ -> assert(false) in @@ -405,7 +405,7 @@ module Transform(Platform : sig val platform : platform end) = struct match s with | T.Local -> FuncE (x, cc, t_typ_binds typbinds, t_args args, List.map t_typ typT, t_exp exp) - | T.Shared -> + | T.Shared s' -> begin match typ exp with | T.Tup [] -> @@ -439,7 +439,7 @@ module Transform(Platform : sig val platform : platform end) = struct (t_exp cps) -*- tupE [k;r] | _ -> assert false in - let cc' = Call_conv.message_cc (List.length args') in + let cc' = Call_conv.message_cc s' (List.length args') in FuncE (x, cc', typbinds', args', [], exp') | _ -> assert false end diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index ebdbf711852..97574d61c17 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -399,7 +399,7 @@ and to_args cc p : (Ir.arg list * (Ir.exp -> Ir.exp)) = in let wrap_under_async e = - if cc.Call_conv.sort = T.Shared && cc.Call_conv.control = T.Promises + if T.is_shared_sort cc.Call_conv.sort && cc.Call_conv.control = T.Promises then match e.it with | Ir.AsyncE e' -> { e with it = Ir.AsyncE (wrap e') } | _ -> assert false diff --git a/test/run-dfinity/ok/query.dvm-run.ok b/test/run-dfinity/ok/query.dvm-run.ok new file mode 100644 index 00000000000..c10e912b5d0 --- /dev/null +++ b/test/run-dfinity/ok/query.dvm-run.ok @@ -0,0 +1,8 @@ +2 +3 +4 +4 +5(read) +4 +5(read) +4 diff --git a/test/run-dfinity/ok/query.run-ir.ok b/test/run-dfinity/ok/query.run-ir.ok new file mode 100644 index 00000000000..93b07b45408 --- /dev/null +++ b/test/run-dfinity/ok/query.run-ir.ok @@ -0,0 +1,9 @@ +2 +3 +4 +4 +5(read) +5 +6(read) +query.as:61.2-61.16: execution error, assertion failure +6 diff --git a/test/run-dfinity/ok/query.run-low.ok b/test/run-dfinity/ok/query.run-low.ok new file mode 100644 index 00000000000..93b07b45408 --- /dev/null +++ b/test/run-dfinity/ok/query.run-low.ok @@ -0,0 +1,9 @@ +2 +3 +4 +4 +5(read) +5 +6(read) +query.as:61.2-61.16: execution error, assertion failure +6 diff --git a/test/run-dfinity/ok/query.run.ok b/test/run-dfinity/ok/query.run.ok new file mode 100644 index 00000000000..93b07b45408 --- /dev/null +++ b/test/run-dfinity/ok/query.run.ok @@ -0,0 +1,9 @@ +2 +3 +4 +4 +5(read) +5 +6(read) +query.as:61.2-61.16: execution error, assertion failure +6 diff --git a/test/run-dfinity/query.as b/test/run-dfinity/query.as new file mode 100644 index 00000000000..8f34ec56b64 --- /dev/null +++ b/test/run-dfinity/query.as @@ -0,0 +1,62 @@ +actor counter = { + var c = 1; + public func inc() { + c += 1; + printNat c; print "\n"; + }; + public func printCounter () { + printNat c; print "\n"; + }; + public func get() : async Nat { + return c + }; + public query func read() : async Nat { + let tmp = c; + c += 1; + printNat c; print "(read)\n"; + return tmp; + }; + +}; + + +{ // fully explicit syntax + +let _ : actor { read : shared query () -> async Nat } = counter; + +shared query func f () : async Nat { 666; }; + +type Query = shared query () -> async Nat; + +let _ : Query = counter.read; + +}; + +{ + +// sugar, surpressing shared + +let _ : actor { read: query () -> async Nat } = counter; + +query func f () : async Nat { 666; }; + +type Query = query () -> async Nat; + +let _ : Query = counter.read; + +}; + +async { + counter.inc(); + counter.inc(); + counter.inc(); + counter.printCounter(); + let c1 = await counter.get(); + assert c1 == 4; + let c2 = await counter.read(); + counter.printCounter(); + assert c2 == 4; + let c3 = await counter.read(); + counter.printCounter(); + assert c3 == 4; +}; diff --git a/test/run-drun/ok/query.drun-run.ok b/test/run-drun/ok/query.drun-run.ok new file mode 100644 index 00000000000..5137d9c8055 --- /dev/null +++ b/test/run-drun/ok/query.drun-run.ok @@ -0,0 +1,34 @@ +ingress(0) System +debug.print: 2 +debug.print: + +ingress(1) Completed: Canister: Empty +debug.print: 3 +debug.print: + +ingress(2) Completed: Canister: Empty +debug.print: 4 +debug.print: + +ingress(3) Completed: Canister: Empty +debug.print: 4 +debug.print: + +ingress(4) Completed: Canister: Empty +ingress(5) Completed: Canister: Payload: 0x4449444c00017d04 +debug.print: 5 +debug.print: + +Ok: Payload: 0x4449444c00017d04 +debug.print: 4 +debug.print: + +ingress(6) Completed: Canister: Empty +debug.print: 5 +debug.print: + +Ok: Payload: 0x4449444c00017d04 +debug.print: 4 +debug.print: + +ingress(7) Completed: Canister: Empty diff --git a/test/run-drun/query.as b/test/run-drun/query.as new file mode 100644 index 00000000000..3c97f7a3357 --- /dev/null +++ b/test/run-drun/query.as @@ -0,0 +1,29 @@ +actor { + var c = 1; + public func inc() { + c += 1; + printNat c; print "\n"; + }; + public func printCounter () { + printNat c; print "\n"; + }; + public func get() : async Nat { + return c + }; + public query func read() : async Nat { + let tmp = c; + c += 1; + printNat c; print "\n"; + return tmp; + }; + +} +//CALL ingress inc 0x4449444C0000 +//CALL ingress inc 0x4449444C0000 +//CALL ingress inc 0x4449444C0000 +//CALL ingress printCounter 0x4449444C0000 +//CALL ingress get 0x4449444C0000 +//CALL query read 0x4449444C0000 +//CALL ingress printCounter 0x4449444C0000 +//CALL query read 0x4449444C0000 +//CALL ingress printCounter 0x4449444C0000 From 71e333aacd83e05d94c5720cb07419bcd0a1858e Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 2 Oct 2019 19:54:48 +0200 Subject: [PATCH 0434/1176] IDL-AS-Mapping: `e(()) = null` (#723) to resolve the tension with variant short-hands described in https://github.com/dfinity-lab/actorscript/pull/719/files#r330531215 --- design/IDL-AS.md | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/design/IDL-AS.md b/design/IDL-AS.md index 053aeedba1b..287d0515af9 100644 --- a/design/IDL-AS.md +++ b/design/IDL-AS.md @@ -85,13 +85,14 @@ e(Word) = nat for n = 8, 16, 32, 64 e(Float) = float64 e(Char) = nat32 e(Text) = text -e(shared { ;* }) = record { ef();* } +e({ ;* }) = record { ef();* } e(variant { ;* }) = variant { ef();* } e([]) = vec (e()) e(? ) = opt (e()) e(shared -> ) = func (efn(shared -> )) e(actor { ;* }) = service { em();* } -e( ( ,* ) ) = record { e();* } +e( () ) = null +e( ( ,+ ) ) = record { e();+ } e(Any) = reserved e(None) = empty @@ -132,8 +133,8 @@ i(reserved) = Any i(opt ) = ? i() i(vec ) = [ i() ] i(blob) = [ word8 ] // if ActorScript had a bytes type, it would show up here -i(record { ;* }) = ( i(),* ) // matches tuple short-hand -i(record { ;* }) = shared { if();* } +i(record { ;+ }) = ( i(),+ ) // matches tuple short-hand +i(record { ;* }) = { if();* } i(variant { ;* }) = variant { if();* } i(func ) = ifn() i(service { ;* }) = actor { im();* } @@ -173,27 +174,30 @@ escape = "_" hash() "_" otherwise e(()) = record {} e((Int, )) = record {int} e((Int, Nat)) = record {int;nat} - e(shared {i:Int, n:Nat)) = record {i:int; n:nat} - e(shared {_0_:Int, _1_:Nat)) = record {0:int; 1:nat} + e({i:Int, n:Nat)) = record {i:int; n:nat} + e({_0_:Int, _1_:Nat)) = record {0:int; 1:nat} ``` - * The mapping `i` tries to detect types that can be expressed as tuples in - ActorScript. + * The mapping `i` tries to detect types that can be expressed as (non-nullary) + tuples in ActorScript. ``` i(record {int;nat}) = (Int, Nat) - i(record {int; nat; foo:text}) = shared {_0_:Int; _1_:Nat; foo:Text} - i(record {0:Int, 1:Nat)) = shared {_0_:int; _1_:nat} + i(record {int; nat; foo:text}) = {_0_:Int; _1_:Nat; foo:Text} + i(record {0:Int, 1:Nat)) = {_0_:int; _1_:nat} ``` + But note that `i(record {}) ≠ ()` because `e(()) = null` and we want + `e(i(record {})) = record {}`. + * The `escape` and `unescape` functions allow round-tripping of IDL field names that are not valid ActorScript names (fake hash values): ``` i(record {int; if:text; foobar_:nat; "_0_":bool}) - = shared (_0_:Int; if_:Text; _1234_:Nat; _4321_:Bool) + = (_0_:Int; if_:Text; _1234_:Nat; _4321_:Bool) ``` This is another source of partiality for `e`: ``` - e(shared {clash_ : Nat; clash : Int}) + e({clash_ : Nat; clash : Int}) ``` is undefined, because `unescape(clash_) = unescape(clash)`. From a5f8c29d4f17553655fe75fe4fe1092fad746908 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Thu, 3 Oct 2019 08:22:32 +0100 Subject: [PATCH 0435/1176] emit canister_query exports (#724) --- src/codegen/compile.ml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 83d28f5a925..918e39302cc 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -6780,7 +6780,14 @@ and export_actor_field env ae (f : Ir.field) = E.add_export env (nr { name = Wasm.Utf8.decode (match E.mode env with | Flags.AncientMode -> f.it.name - | Flags.ICMode -> "canister_update " ^ f.it.name + | Flags.ICMode -> + As_types.Type.( + match normalize f.note with + | Func(Shared sort,_,_,_,_) -> + (match sort with + | Write -> "canister_update " ^ f.it.name + | Query -> "canister_query " ^ f.it.name) + | _ -> assert false) | _ -> assert false); edesc = nr (FuncExport (nr fi)) }) From 2b4fca99fb750a7065f72435227220c24860dfd5 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Thu, 3 Oct 2019 18:24:22 +0100 Subject: [PATCH 0436/1176] flatten async type in idl translation (#721) --- src/as_idl/as_to_idl.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/as_idl/as_to_idl.ml b/src/as_idl/as_to_idl.ml index aa3f9f33022..831543866d0 100644 --- a/src/as_idl/as_to_idl.ml +++ b/src/as_idl/as_to_idl.ml @@ -118,7 +118,7 @@ let rec typ vs t = (match s with | Query -> [I.Query @@ no_region] | Write -> []), - fs1, tuple vs [t]) + fs1, tuple vs (as_seq t)) | _ -> assert false) | Func _ -> assert false | Async t -> assert false From 73c635086131ad08df2fa9439ad075cc1cd154c4 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Fri, 4 Oct 2019 13:10:16 +0200 Subject: [PATCH 0437/1176] IDL decoding: test Nat <: Int ACT-111 (#727) * test Nat :< Int IDL decoding ACT-111 * same with vectors --- test/run-drun/idl-nat-int.as | 18 ++++++++++++++++++ test/run-drun/ok/idl-nat-int.drun-run.ok | 5 +++++ 2 files changed, 23 insertions(+) create mode 100644 test/run-drun/idl-nat-int.as create mode 100644 test/run-drun/ok/idl-nat-int.drun-run.ok diff --git a/test/run-drun/idl-nat-int.as b/test/run-drun/idl-nat-int.as new file mode 100644 index 00000000000..7c971b93ff7 --- /dev/null +++ b/test/run-drun/idl-nat-int.as @@ -0,0 +1,18 @@ +actor { + public query func absolute(x:Int) : async Nat { + abs x + }; + public query func absolutes(xs:[Int]) : async [Nat] { + Array_tabulate(xs.len(), func (i:Int) : Nat = abs(xs[i])) + }; +} + +// with Nat +//CALL query absolute "DIDL\x00\x01\x7d\x2a" +// with Int +//CALL query absolute "DIDL\x00\x01\x7c\x56" + +// with Nats +//CALL query absolutes "DIDL\x01\x6d\x7d\x01\x00\x02\x2a\x19" +// with Ints +//CALL query absolutes "DIDL\x01\x6d\x7c\x01\x00\x02\x56\x19" diff --git a/test/run-drun/ok/idl-nat-int.drun-run.ok b/test/run-drun/ok/idl-nat-int.drun-run.ok new file mode 100644 index 00000000000..f450261cb17 --- /dev/null +++ b/test/run-drun/ok/idl-nat-int.drun-run.ok @@ -0,0 +1,5 @@ +ingress(0) System +Ok: Payload: 0x4449444c00017d2a +Ok: Payload: 0x4449444c00017d2a +Ok: Payload: 0x4449444c016d7d0100022a19 +Ok: Payload: 0x4449444c016d7d0100022a19 From 43c876a78cb30cb1ec5516559a483b72b61834f2 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Fri, 4 Oct 2019 18:07:11 +0200 Subject: [PATCH 0438/1176] Bump to most recent dfinity (#728) * decorate query message handlers * bump dfinity and dev to recent --- default.nix | 8 ++++---- test/run-drun/hello-world-return.as | 4 ++-- test/run-drun/idl-tuple.as | 4 ++-- test/run-drun/idl-unit.as | 2 +- test/run-drun/ok/idl-unit.drun-run.ok | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/default.nix b/default.nix index f788368a265..95857d5e9c3 100644 --- a/default.nix +++ b/default.nix @@ -26,14 +26,14 @@ let ocaml_bisect_ppx-ocamlbuild = import ./nix/ocaml-bisect_ppx-ocamlbuild.nix n let dev = import (builtins.fetchGit { url = "ssh://git@github.com/dfinity-lab/dev"; - ref = "master"; - rev = "ad50bcea8db6d55decf2622ad836435aa36fa33f"; + # ref = "master"; + rev = "9030c90efe5b3de33670d4f4f0331482d51c5858"; }) { system = nixpkgs.system; }; in let dfinity-repo = import (builtins.fetchGit { url = "ssh://git@github.com/dfinity-lab/dfinity"; - ref = "master"; - rev = "a50367859416ef7c12ca103b7fc03f5a7654f6ad"; + # ref = "master"; + rev = "261a330bb6282f864f0de411adf5abe287d7f8be"; }) { system = nixpkgs.system; }; in let real-dvm = diff --git a/test/run-drun/hello-world-return.as b/test/run-drun/hello-world-return.as index c6e7c727da8..e1a4ca1644d 100644 --- a/test/run-drun/hello-world-return.as +++ b/test/run-drun/hello-world-return.as @@ -1,8 +1,8 @@ actor { - public func hello(who : Text) : async Text { + public query func hello(who : Text) : async Text { "Hello " # who # "!"; }; - public func hello2(who : Text) : async Text { + public query func hello2(who : Text) : async Text { return ("Hello " # who # "!"); } } diff --git a/test/run-drun/idl-tuple.as b/test/run-drun/idl-tuple.as index 374edb88ec0..0f86f4a9a06 100644 --- a/test/run-drun/idl-tuple.as +++ b/test/run-drun/idl-tuple.as @@ -1,10 +1,10 @@ actor { // top-level tuple - public func len2(x:Text, y:Text) : async (Int,Int) { + public query func len2(x:Text, y:Text) : async (Int,Int) { (x.len(), y.len()) }; // a pair embedded in top-level tuple - public func len3((x:Text, i:Int32), y:Text) : async (Int,Int,Int) { + public query func len3((x:Text, i:Int32), y:Text) : async (Int,Int,Int) { (x.len(), y.len(), int32ToInt i) } } diff --git a/test/run-drun/idl-unit.as b/test/run-drun/idl-unit.as index 8402ad366f3..09e6f9b85ec 100644 --- a/test/run-drun/idl-unit.as +++ b/test/run-drun/idl-unit.as @@ -1,5 +1,5 @@ actor { - public func unit_id() : () { + public query func unit_id() : async () { () } } diff --git a/test/run-drun/ok/idl-unit.drun-run.ok b/test/run-drun/ok/idl-unit.drun-run.ok index 939d1cbe7b7..7a9005737f9 100644 --- a/test/run-drun/ok/idl-unit.drun-run.ok +++ b/test/run-drun/ok/idl-unit.drun-run.ok @@ -1,2 +1,2 @@ ingress(0) System -Ok: Empty +Ok: Payload: 0x4449444c016c000100 From 08d90b5cfc3f2e27c0e1252092815ca2e06a89e3 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Fri, 4 Oct 2019 21:06:16 +0100 Subject: [PATCH 0439/1176] flatten async returns types in IDL and compiler ACT-138 (#729) Fixes the hack that was PR #731 Use Promise control flag to track syntactic arity of async returns. Propagate to back-end and generated IDL Flatten accordingly using modified ICReplyPrim taking list of types Add test idl-nary test and revised expected drun-test output. * flatten async type in idl translation * track arity in T.Promise; propagate; TODO: ICReplyPrim * test nary returns * modify ICPrim to take list of typs to guide correct, n-ary serialization; update test output to reflect flattening; add idl-nary.as test * Update test/run-drun/idl-nary.as Co-Authored-By: Gabor Greif * Update test/run-drun/idl-nary.as Co-Authored-By: Gabor Greif * Update test/run-drun/idl-nary.as Co-Authored-By: Gabor Greif * check promise arity again return type * reject shared functions that don't return () or async; update tests; refactoring * Update test/run-drun/idl-nary.as * Update test/run-drun/idl-nary.as * Update test/run-drun/idl-nary.as * Update test/run-drun/idl-nary.as * changed query to ingress as mismatch now rejected * Update test/run-drun/idl-nary.as * Update test/run-drun/idl-nary.as * Update test/run-drun/idl-nary.as * fix tests to use proper ingress/query calls * fix tests to use proper ingress/query calls --- src/as_def/syntax.ml | 5 +++ src/as_frontend/typing.ml | 16 +++++--- src/as_idl/as_to_idl.ml | 8 ++-- src/as_interpreter/interpret.ml | 4 +- src/as_types/arrange_type.ml | 2 +- src/as_types/call_conv.ml | 4 +- src/as_types/call_conv.mli | 2 +- src/as_types/type.ml | 14 +++++-- src/as_types/type.mli | 4 +- src/as_values/value.ml | 2 +- src/as_values/value.mli | 2 +- src/codegen/compile.ml | 8 ++-- src/ir_def/arrange_ir.ml | 2 +- src/ir_def/check_ir.ml | 22 ++++++---- src/ir_def/construct.ml | 7 +++- src/ir_def/construct.mli | 2 +- src/ir_def/ir.ml | 2 +- src/ir_interpreter/interpret_ir.ml | 6 +-- src/ir_passes/async.ml | 53 ++++++++++++++---------- src/lowering/desugar.ml | 2 +- test/fail/ok/abstract-msgs.tc.ok | 19 +++++---- test/fail/ok/asyncret1.tc.ok | 3 +- test/run-drun/idl-nary.as | 47 +++++++++++++++++++++ test/run-drun/idl-pair.as | 8 ++++ test/run-drun/ok/idl-any.drun-run.ok | 54 ++++++++++++------------- test/run-drun/ok/idl-nary.drun-run.ok | 9 +++++ test/run-drun/ok/idl-option.drun-run.ok | 6 +-- test/run-drun/ok/idl-pair.drun-run.ok | 2 + test/run-drun/ok/idl-record.drun-run.ok | 6 +-- test/run-drun/ok/idl-tuple.drun-run.ok | 8 ++-- test/run-drun/ok/idl-unit.drun-run.ok | 2 +- test/run-drun/ok/reject.drun-run.ok | 2 +- 32 files changed, 217 insertions(+), 116 deletions(-) create mode 100644 test/run-drun/idl-nary.as create mode 100644 test/run-drun/idl-pair.as create mode 100644 test/run-drun/ok/idl-nary.drun-run.ok create mode 100644 test/run-drun/ok/idl-pair.drun-run.ok diff --git a/src/as_def/syntax.ml b/src/as_def/syntax.ml index 918e20f6c29..3b638e0de10 100644 --- a/src/as_def/syntax.ml +++ b/src/as_def/syntax.ml @@ -196,6 +196,11 @@ let as_seqT t = | TupT ts -> ts | _ -> [t] +let arity t = + match t.Source.it with + | TupT ts -> List.length ts + | _ -> 1 + (* Literals *) let string_of_lit = function diff --git a/src/as_frontend/typing.ml b/src/as_frontend/typing.ml index cbcde50973c..4c0aefa9046 100644 --- a/src/as_frontend/typing.ml +++ b/src/as_frontend/typing.ml @@ -168,6 +168,14 @@ let rec check_typ env typ : T.typ = typ.note <- t; t +and infer_control env sort typ = + match sort.it, typ.it with + | T.Shared _, AsyncT ret_typ -> T.Promises (arity ret_typ) + | T.Shared T.Write, TupT [] -> T.Returns + | T.Shared T.Write, _ -> error env typ.at "shared function must have syntactic return type `()` or `async `" + | T.Shared T.Query, _ -> error env typ.at "shared query function must have syntactic return type `async `" + | _ -> T.Returns + and check_typ' env typ : T.typ = match typ.it with | PathT (path, typs) -> @@ -195,7 +203,7 @@ and check_typ' env typ : T.typ = let typs2 = as_seqT typ2 in let ts1 = List.map (check_typ env') typs1 in let ts2 = List.map (check_typ env') typs2 in - let c = match typs2 with [{it = AsyncT _; _}] -> T.Promises | _ -> T.Returns in + let c = infer_control env sort typ2 in if Type.is_shared_sort sort.it then if not env.pre then begin let t1 = T.seq ts1 in @@ -620,6 +628,7 @@ and infer_exp'' env exp : T.typ = | Some typ -> typ | None -> {it = TupT []; at = no_region; note = T.Pre} in + let c = infer_control env sort typ in let cs, ts, te, ce = check_typ_binds env typ_binds in let env' = adjoin_typs env te ce in let t1, ve = infer_pat_exhaustive env' pat in @@ -646,11 +655,6 @@ and infer_exp'' env exp : T.typ = end; let ts1 = match pat.it with TupP _ -> T.as_seq t1 | _ -> [t1] in let ts2 = match typ.it with TupT _ -> T.as_seq t2 | _ -> [t2] in - let c = - match sort.it, typ.it with - | T.Shared _, AsyncT _ -> T.Promises - | _ -> T.Returns - in let tbs = List.map2 (fun c t -> {T.var = Con.name c; bound = T.close cs t}) cs ts in T.Func (sort.it, c, tbs, List.map (T.close cs) ts1, List.map (T.close cs) ts2) | CallE (exp1, insts, exp2) -> diff --git a/src/as_idl/as_to_idl.ml b/src/as_idl/as_to_idl.ml index 831543866d0..0af3d42aab5 100644 --- a/src/as_idl/as_to_idl.ml +++ b/src/as_idl/as_to_idl.ml @@ -111,14 +111,14 @@ let rec typ vs t = I.VariantT (List.map (field vs) fs) | Func (Shared s, c, [], ts1, ts2) -> let fs1 = tuple vs ts1 in - (match ts2 with - | [] when c = Returns -> I.FuncT ([I.Oneway @@ no_region], fs1, []) - | [Async t] when c = Promises -> + (match ts2, c with + | [], Returns -> I.FuncT ([I.Oneway @@ no_region], fs1, []) + | [Async t], Promises p -> I.FuncT ( (match s with | Query -> [I.Query @@ no_region] | Write -> []), - fs1, tuple vs (as_seq t)) + fs1, tuple vs (if p = 1 then [t] else as_seq t)) | _ -> assert false) | Func _ -> assert false | Async t -> assert false diff --git a/src/as_interpreter/interpret.ml b/src/as_interpreter/interpret.ml index 116f36ff39b..e6dc423adef 100644 --- a/src/as_interpreter/interpret.ml +++ b/src/as_interpreter/interpret.ml @@ -213,8 +213,8 @@ let make_async_message env id v = let open CC in let call_conv, f = V.as_func v in match call_conv with - | {sort = T.Shared s; control = T.Promises; n_res = 1; _} -> - Value.async_func s call_conv.n_args (fun v k -> + | {sort = T.Shared s; control = T.Promises p; n_res = 1; _} -> + Value.async_func s call_conv.n_args p (fun v k -> let async = make_async () in actor_msg env id f v (fun v_async -> get_async (V.as_async v_async) (set_async async) (reject_async async) diff --git a/src/as_types/arrange_type.ml b/src/as_types/arrange_type.ml index 693b10a14da..8524f290a83 100644 --- a/src/as_types/arrange_type.ml +++ b/src/as_types/arrange_type.ml @@ -5,7 +5,7 @@ let ($$) head inner = Node (head, inner) let control c = match c with | Returns -> "Returns" - | Promises -> "Promises" + | Promises n -> "Promises " ^ string_of_int n let obj_sort s = match s with | Object -> Atom "Object" diff --git a/src/as_types/call_conv.ml b/src/as_types/call_conv.ml index 8497ea0ad69..e25e6d8692b 100644 --- a/src/as_types/call_conv.ml +++ b/src/as_types/call_conv.ml @@ -10,7 +10,7 @@ type t = call_conv let local_cc n m = { sort = Local; control = Returns; n_args = n; n_res = m} let message_cc s n = { sort = Shared s; control = Returns; n_args = n; n_res = 0} -let async_cc s n = { sort = Shared s; control = Promises; n_args = n; n_res = 1} +let async_cc s n p = { sort = Shared s; control = Promises p; n_args = n; n_res = 1} let call_conv_of_typ typ = match typ with @@ -24,6 +24,6 @@ let string_of_call_conv {sort;control;n_args;n_res} = Printf.sprintf "(%s%i %s %i)" (string_of_func_sort sort) n_args - (match control with Returns -> "->" | Promises -> "@>") + (match control with Returns -> "->" | Promises p -> "@>"^ string_of_int p) n_res diff --git a/src/as_types/call_conv.mli b/src/as_types/call_conv.mli index 9ab6ee92631..3e6296e2dbc 100644 --- a/src/as_types/call_conv.mli +++ b/src/as_types/call_conv.mli @@ -10,7 +10,7 @@ type t = call_conv val local_cc : int -> int -> call_conv val message_cc : Type.shared_sort -> int -> call_conv -val async_cc : Type.shared_sort -> int -> call_conv +val async_cc : Type.shared_sort -> int -> int -> call_conv val call_conv_of_typ : Type.typ -> call_conv diff --git a/src/as_types/type.ml b/src/as_types/type.ml index 4d91a92ad40..f5e5ef41ee6 100644 --- a/src/as_types/type.ml +++ b/src/as_types/type.ml @@ -3,7 +3,7 @@ type lab = string type var = string -type control = Returns | Promises (* Returns a computed value or immediate promise *) +type control = Returns | Promises of int (* Returns a computed value or immediate promise *) type obj_sort = Object | Actor | Module type shared_sort = Query | Write type func_sort = Local | Shared of shared_sort @@ -344,7 +344,15 @@ let as_mut = function Mut t -> t | _ -> invalid "as_mut" let as_immut = function Mut t -> t | t -> t let as_typ = function Typ c -> c | _ -> invalid "as_typ" -let as_seq = function Tup ts -> ts | t -> [t] +let as_seq t = + match normalize t with + | Tup ts -> ts + | t -> [t] + +let arity t = + match normalize t with + | Tup ts -> List.length ts + | t -> 1 let as_prim_sub p t = match promote t with | Prim p' when p = p' -> () @@ -1114,7 +1122,7 @@ and string_of_cod c vs ts = | [Async _] -> (match c with | Returns -> sprintf "(%s)" cod - | Promises -> sprintf "%s" cod + | Promises _ -> sprintf "%s" cod ) | _ -> cod diff --git a/src/as_types/type.mli b/src/as_types/type.mli index 74ed4e408b3..757a75252aa 100644 --- a/src/as_types/type.mli +++ b/src/as_types/type.mli @@ -3,7 +3,7 @@ type lab = string type var = string -type control = Returns | Promises (* returns a computed value or immediate promise *) +type control = Returns | Promises of int (* returns a computed value or immediate promise *) type obj_sort = Object | Actor | Module type shared_sort = Query | Write type func_sort = Local | Shared of shared_sort @@ -128,7 +128,7 @@ val as_async_sub : typ -> typ val seq : typ list -> typ val as_seq : typ -> typ list - +val arity : typ -> int (* Fields *) diff --git a/src/as_values/value.ml b/src/as_values/value.ml index 5370c1a1561..4ec5eff501f 100644 --- a/src/as_values/value.ml +++ b/src/as_values/value.ml @@ -303,7 +303,7 @@ let unit = Tup [] let local_func n m f = Func (Call_conv.local_cc n m, f) let message_func s n f = Func (Call_conv.message_cc s n, f) -let async_func s n f = Func ( Call_conv.async_cc s n, f) +let async_func s n p f = Func ( Call_conv.async_cc s n p, f) (* Projections *) diff --git a/src/as_values/value.mli b/src/as_values/value.mli index 5e0b4c92987..37125ae675d 100644 --- a/src/as_values/value.mli +++ b/src/as_values/value.mli @@ -116,7 +116,7 @@ val unit : value val local_func : int -> int -> func -> value val message_func : Type.shared_sort -> int -> func -> value -val async_func : Type.shared_sort -> int -> func -> value +val async_func : Type.shared_sort -> int -> int -> func -> value (* Projections *) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 918e39302cc..9331462d33b 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -6221,11 +6221,13 @@ and compile_exp (env : E.t) ae exp = | OtherPrim "make_error", [e1; e2] -> Error.compile_make_error (compile_exp_vanilla env ae e1) (compile_exp_vanilla env ae e2) - | ICReplyPrim t, [e] -> + | ICReplyPrim ts, [e] -> assert (E.mode env = Flags.ICMode); SR.unit, - compile_exp_vanilla env ae e ^^ - Serialization.serialize env [t] + compile_exp_as env ae SR.Vanilla e ^^ + (* TODO: We can try to avoid the boxing and pass the arguments to + serialize individually *) + Serialization.serialize env ts | ICRejectPrim, [e] -> assert (E.mode env = Flags.ICMode); diff --git a/src/ir_def/arrange_ir.ml b/src/ir_def/arrange_ir.ml index a7cf8fd3f66..181aa59dee8 100644 --- a/src/ir_def/arrange_ir.ml +++ b/src/ir_def/arrange_ir.ml @@ -60,7 +60,7 @@ and prim = function | ShowPrim t -> "ShowPrim" $$ [typ t] | NumConvPrim (t1, t2) -> "NumConvPrim" $$ [prim_ty t1; prim_ty t2] | OtherPrim s -> Atom s - | ICReplyPrim t -> "ICReplyPrim" $$ [typ t] + | ICReplyPrim ts -> "ICReplyPrim" $$ List.map typ ts | ICRejectPrim -> Atom "ICRejectPrim" | ICErrorCodePrim -> Atom "ICErrorCodePrim" diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index bd3650d93c7..83f5e06f95f 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -154,14 +154,20 @@ let rec check_typ env typ : unit = let ts2 = List.map (T.open_ ts) ts2 in List.iter (check_typ env') ts1; List.iter (check_typ env') ts2; - if control = T.Promises then begin + (match control with + | T.Returns -> () + | T.Promises p -> begin match ts2 with - | [T.Async _ ] -> () + | [T.Async t ] -> + let a = T.arity t in + if p <> 1 && a <> p then + error env no_region + "promising function of arity %i has async result type\n %s\n of mismatched arity %i" + p (T.string_of_typ_expand (T.seq ts2)) a | _ -> - let t2 = T.seq ts2 in - error env no_region "promising function with non-async result type \n %s" - (T.string_of_typ_expand t2) - end; + error env no_region "promising function with non-async result type\n %s" + (T.string_of_typ_expand (T.seq ts2)) + end); if T.is_shared_sort sort then begin List.iter (fun t -> check_shared env no_region t) ts1; match ts2 with @@ -342,12 +348,12 @@ let rec check_exp env (exp:Ir.exp) : unit = check_exp env exp1; typ exp1 <: ot; T.Prim T.Text <: t - | ICReplyPrim ot, [exp1] -> + | ICReplyPrim ts, [exp1] -> check (not (env.flavor.has_async_typ)) "ICReplyPrim in async flavor"; check (T.shared t) "ICReplyPrim is not defined for non-shared operand type"; (* TODO: check against expected reply typ; note this may not be env.ret_tys. *) check_exp env exp1; - typ exp1 <: ot; + typ exp1 <: (T.seq ts); T.unit <: t | ICRejectPrim, [exp1] -> check (not (env.flavor.has_async_typ)) "ICRejectPrim in async flavor"; diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index 093d0d61ed2..d09287403e7 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -115,8 +115,11 @@ let awaitE typ e1 e2 = note = { note_typ = T.unit; note_eff = max_eff (eff e1) (eff e2) } } -let ic_replyE t e = - { it = PrimE (ICReplyPrim t, [e]); +let ic_replyE ts e = + (match ts with + | [t] -> assert (T.sub (e.note.note_typ) t) + | _ -> assert (T.sub (T.Tup ts) (e.note.note_typ))); + { it = PrimE (ICReplyPrim ts, [e]); at = no_region; note = { note_typ = T.unit; note_eff = eff e } } diff --git a/src/ir_def/construct.mli b/src/ir_def/construct.mli index ad3edf4b36b..284e04f658c 100644 --- a/src/ir_def/construct.mli +++ b/src/ir_def/construct.mli @@ -43,7 +43,7 @@ val primE : Ir.prim -> exp list -> exp val asyncE : typ -> exp -> exp val assertE : exp -> exp val awaitE : typ -> exp -> exp -> exp -val ic_replyE : typ -> exp -> exp +val ic_replyE : typ list -> exp -> exp val ic_rejectE : exp -> exp val ic_error_codeE : unit -> exp val projE : exp -> int -> exp diff --git a/src/ir_def/ir.ml b/src/ir_def/ir.ml index a4e164f26a2..9200330aed8 100644 --- a/src/ir_def/ir.ml +++ b/src/ir_def/ir.ml @@ -107,7 +107,7 @@ and prim = | ShowPrim of Type.typ (* debug show *) | NumConvPrim of Type.prim * Type.prim | OtherPrim of string (* Other primitive operation, no custom typing rule *) - | ICReplyPrim of Type.typ + | ICReplyPrim of Type.typ list | ICRejectPrim | ICErrorCodePrim diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index 96603cb4b89..86824de047c 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -200,8 +200,8 @@ let make_async_message env id v = let open CC in let call_conv, f = V.as_func v in match call_conv with - | {sort = T.Shared s; control = T.Promises; n_res = 1; _} -> - Value.async_func s call_conv.n_args (fun v k -> + | {sort = T.Shared s; control = T.Promises p; n_res = 1; _} -> + Value.async_func s call_conv.n_args p (fun v k -> let async = make_async () in actor_msg env id f v (fun v_async -> get_async (V.as_async v_async) (set_async async) (reject_async async) @@ -216,7 +216,7 @@ let make_async_message env id v = let make_message env x cc v : V.value = match cc.CC.control with | T.Returns -> make_unit_message env x v - | T.Promises -> make_async_message env x v + | T.Promises _ -> make_async_message env x v let extended_prim env s typ at = diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index 5d03409222e..53af99e967b 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -64,10 +64,10 @@ module Transform(Platform : sig val platform : platform end) = struct implemented (as far as possible) for V1; TBC for V2 *) - let sys_replyE t v = + let sys_replyE ts v = match platform with | V1 -> assert false (* never required in V1, `reply` is by calling continuation*) - | V2 -> ic_replyE t v + | V2 -> ic_replyE ts v let sys_rejectE e = match platform with @@ -113,6 +113,8 @@ module Transform(Platform : sig val platform : platform end) = struct let nary typ = T.as_seq typ + let flatten arity = if arity = 1 then unary else nary + let replyT as_seq typ = T.Func(T.Shared T.Write, T.Returns, [], as_seq typ, []) let rejectT = T.Func(T.Shared T.Write, T.Returns, [], [T.text], []) @@ -145,7 +147,7 @@ module Transform(Platform : sig val platform : platform end) = struct let fail = fresh_var "fail" (typ (projE call_new_async 2)) in (async, fulfill, fail), call_new_async - let new_nary_async_reply t1 = + let new_nary_async_reply p t1 = let (unary_async, unary_fulfill, fail), call_new_async = new_async t1 in let v' = fresh_var "v" t1 in let ts1 = T.as_seq t1 in @@ -194,7 +196,7 @@ module Transform(Platform : sig val platform : platform end) = struct let isAwaitableFunc exp = match typ exp with - | T.Func (T.Shared _,T.Promises,_,_,[T.Async _]) -> true + | T.Func (T.Shared _,T.Promises _,_,_,[T.Async _]) -> true | _ -> false let extendTup ts ts' = ts @ ts' @@ -230,16 +232,15 @@ module Transform(Platform : sig val platform : platform end) = struct match s with | T.Shared _ -> begin - match t2 with - | [] -> + match t2,c with + | [],_ -> assert (c = T.Returns); Func(s, c, List.map t_bind tbs, List.map t_typ t1, List.map t_typ t2) - | [Async t2] -> - assert (c = T.Promises); + | [Async t2], T.Promises p -> Func (s, T.Returns, List.map t_bind tbs, extendTup (List.map t_typ t1) (select - [ add_reply_parameter, lazy (replyT nary (t_typ t2)); + [ add_reply_parameter, lazy (replyT (flatten p) (t_typ t2)); add_reject_parameter, lazy rejectT ]), []) | _ -> assert false @@ -285,7 +286,7 @@ module Transform(Platform : sig val platform : platform end) = struct | RelPrim (ot, op) -> RelPrim (t_typ ot, op) | ShowPrim ot -> ShowPrim (t_typ ot) | NumConvPrim (t1,t2) -> NumConvPrim (t1,t2) - | ICReplyPrim t -> ICReplyPrim(t_typ t) + | ICReplyPrim ts -> ICReplyPrim (List.map t_typ ts) | p -> p and t_field {lab; typ} = @@ -327,7 +328,7 @@ module Transform(Platform : sig val platform : platform end) = struct | Func(_,_, [], [Func(_, _, [], ts1, []) as contT; _], - []) -> (* TBR, why isn't this []? *) + []) -> (t_typ (T.seq ts1),t_typ contT) | t -> assert false in let k = fresh_var "k" contT in @@ -336,7 +337,7 @@ module Transform(Platform : sig val platform : platform end) = struct let e = fresh_var "e" T.catch in let post = fresh_var "post" (T.Func(T.Shared T.Write, T.Returns, [], [], [])) in let u = fresh_var "u" T.unit in - let ((nary_async, nary_reply, reject), def) = new_nary_async_reply t1 in + let ((nary_async, nary_reply, reject), def) = new_nary_async_reply 1 t1 in (blockE [letP (tupP [varP nary_async; varP nary_reply; varP reject]) def; funcD k v1 (nary_reply -*- v1); nary_funcD r [e] (reject -*- (errorMessageE e)); @@ -345,16 +346,16 @@ module Transform(Platform : sig val platform : platform end) = struct nary_async ).it | CallE (cc, exp1, typs, exp2) when isAwaitableFunc exp1 -> - let ts1,t2 = + let p, ts1,t2 = match typ exp1 with - | T.Func (T.Shared _, T.Promises,tbs,ts1,[T.Async t2]) -> - List.map t_typ ts1, t_typ t2 + | T.Func (T.Shared _, T.Promises p,tbs,ts1,[T.Async t2]) -> + p, List.map t_typ ts1, t_typ t2 | _ -> assert(false) in let exp1' = t_exp exp1 in let exp2' = t_exp exp2 in let typs = List.map t_typ typs in - let ((nary_async, nary_reply, reject), def) = new_nary_async_reply t2 in + let ((nary_async, nary_reply, reject), def) = new_nary_async_reply p t2 in let _ = letEta in (blockE ( letP (tupP [varP nary_async; varP nary_reply; varP reject]) def :: letEta exp1' (fun v1 -> @@ -407,12 +408,13 @@ module Transform(Platform : sig val platform : platform end) = struct FuncE (x, cc, t_typ_binds typbinds, t_args args, List.map t_typ typT, t_exp exp) | T.Shared s' -> begin - match typ exp with - | T.Tup [] -> + match typ exp, cc.Call_conv.control with + | T.Tup [], _ -> FuncE (x, cc, t_typ_binds typbinds, t_args args, List.map t_typ typT, t_exp exp) - | T.Async res_typ -> + | T.Async res_typ, Promises p -> let res_typ = t_typ res_typ in - let reply_typ = replyT nary res_typ in + let res_typs = flatten p res_typ in + let reply_typ = replyT (flatten p) res_typ in let reply = fresh_var "reply" reply_typ in let reject = fresh_var "reject" rejectT in let args' = t_args args @ @@ -423,12 +425,19 @@ module Transform(Platform : sig val platform : platform end) = struct let exp' = match exp.it with | PrimE (OtherPrim "@async", [cps]) -> - let v = fresh_var "v" res_typ in + let t1, contT = match typ cps with + | Func(_,_, + [], + [Func(_, _, [], ts1, []) as contT; _], + []) -> + (t_typ (T.seq ts1),t_typ contT) + | t -> assert false in + let v = fresh_var "v" t1 in let k = if add_reply_parameter then (* wrap shared reply function in local function *) (v --> (reply -*- v)) else - (v --> (sys_replyE res_typ v)) in + (v --> (sys_replyE res_typs v)) in let e = fresh_var "e" T.catch in let r = if add_reject_parameter then (* wrap shared reject function in local function *) diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 97574d61c17..f6f613c0aaf 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -399,7 +399,7 @@ and to_args cc p : (Ir.arg list * (Ir.exp -> Ir.exp)) = in let wrap_under_async e = - if T.is_shared_sort cc.Call_conv.sort && cc.Call_conv.control = T.Promises + if T.is_shared_sort cc.Call_conv.sort && cc.Call_conv.control <> T.Returns then match e.it with | Ir.AsyncE e' -> { e with it = Ir.AsyncE (wrap e') } | _ -> assert false diff --git a/test/fail/ok/abstract-msgs.tc.ok b/test/fail/ok/abstract-msgs.tc.ok index d62841c511e..3e72f5ede4d 100644 --- a/test/fail/ok/abstract-msgs.tc.ok +++ b/test/fail/ok/abstract-msgs.tc.ok @@ -1,20 +1,19 @@ abstract-msgs.as:2.28-2.37: type error, shared function has non-shared parameter type A/9 -abstract-msgs.as:3.33-3.35: type error, shared function has non-async result type - ?A/10 +abstract-msgs.as:3.33-3.35: type error, shared function must have syntactic return type `()` or `async ` abstract-msgs.as:5.20-5.29: type error, shared function has non-shared parameter type - A/11 + A/10 abstract-msgs.as:6.31-6.33: type error, async has non-shared content type - ?A/11 + ?A/10 abstract-msgs.as:10.34-10.35: type error, shared function has non-shared parameter type - A/12 + A/11 abstract-msgs.as:11.46-11.47: type error, async has non-shared content type - A/13 + A/12 abstract-msgs.as:14.30-14.31: type error, shared function has non-shared parameter type - A/14 + A/13 abstract-msgs.as:15.42-15.43: type error, async has non-shared content type - A/15 + A/14 abstract-msgs.as:16.31-16.32: type error, shared function has non-shared parameter type - A/16 + A/15 abstract-msgs.as:17.43-17.44: type error, async has non-shared content type - A/17 + A/16 diff --git a/test/fail/ok/asyncret1.tc.ok b/test/fail/ok/asyncret1.tc.ok index 2879cd8331c..d309c7fde94 100644 --- a/test/fail/ok/asyncret1.tc.ok +++ b/test/fail/ok/asyncret1.tc.ok @@ -1,2 +1 @@ -asyncret1.as:1.39-1.40: type error, shared function has non-async result type - C +asyncret1.as:1.39-1.40: type error, shared function must have syntactic return type `()` or `async ` diff --git a/test/run-drun/idl-nary.as b/test/run-drun/idl-nary.as new file mode 100644 index 00000000000..4329585d6cb --- /dev/null +++ b/test/run-drun/idl-nary.as @@ -0,0 +1,47 @@ +actor { + public func two(x:Text, y:Text) : async (Text, Text) { + (x, y) + }; + + public func three(x:Text, y:Text, z: Text) : async (Text, Text, Text) { + (x, y, z) + }; + + public func four(x:Text, y:Text, z: Text, w: Text) : async (Text, Text, Text, Text) { + (x, y, z, w) + }; + + public func mkRecord() : async ((Text, Text, Text, Text)) { + ("One", "Two", "Three", "Four") + }; + + public func unary1((x:Text, y:Text, z: Text, w: Text)) : async ((Text, Text, Text, Text)) { + (x, y, z, w) + }; + + public func unary2(xyzw : (Text, Text, Text, Text)) : async ((Text, Text, Text, Text)) { + xyzw + }; + + public func unary3(xyzw : (Text, Text, Text, Text)) : async ((Text, Text, Text, Text)) { + xyzw + }; + + type T = (Text, Text, Text, Text); + public func unary4(xyzw : (Text, Text, Text, Text)) : async T { + xyzw + } + + +} + +//CALL ingress two "DIDL\x00\x02\x71\x71\x03One\x03Two" +//CALL ingress three "DIDL\x00\x03\x71\x71\x71\x03One\x03Two\x05Three" +//CALL ingress four "DIDL\x00\x04\x71\x71\x71\x71\x03One\x03Two\x05Three\x04Four" +//CALL ingress mkRecord "DIDL\x00\x00" +//CALL ingress unary1 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 +//CALL ingress unary2 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 +//CALL ingress unary3 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 +//CALL ingress unary4 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 + + diff --git a/test/run-drun/idl-pair.as b/test/run-drun/idl-pair.as new file mode 100644 index 00000000000..57a487bcd64 --- /dev/null +++ b/test/run-drun/idl-pair.as @@ -0,0 +1,8 @@ +type Pair = (Int,Int); +actor { + public func len2(x:Text, y:Text) : async Pair { + (x.len(), y.len()) + } +} + +//CALL ingress len2 "DIDL\x00\x02\x71\x71\x02Hi\x05World" diff --git a/test/run-drun/ok/idl-any.drun-run.ok b/test/run-drun/ok/idl-any.drun-run.ok index dc989777185..bad9a039c2f 100644 --- a/test/run-drun/ok/idl-any.drun-run.ok +++ b/test/run-drun/ok/idl-any.drun-run.ok @@ -1,55 +1,55 @@ ingress(0) System debug.print: ok: Foo -ingress(1) Completed: Canister: Payload: 0x4449444c016c000100 +ingress(1) Completed: Canister: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(2) Completed: Canister: Payload: 0x4449444c016c000100 +ingress(2) Completed: Canister: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(3) Completed: Canister: Payload: 0x4449444c016c000100 +ingress(3) Completed: Canister: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(4) Completed: Canister: Payload: 0x4449444c016c000100 +ingress(4) Completed: Canister: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(5) Completed: Canister: Payload: 0x4449444c016c000100 +ingress(5) Completed: Canister: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(6) Completed: Canister: Payload: 0x4449444c016c000100 +ingress(6) Completed: Canister: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(7) Completed: Canister: Payload: 0x4449444c016c000100 +ingress(7) Completed: Canister: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(8) Completed: Canister: Payload: 0x4449444c016c000100 +ingress(8) Completed: Canister: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(9) Completed: Canister: Payload: 0x4449444c016c000100 +ingress(9) Completed: Canister: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(10) Completed: Canister: Payload: 0x4449444c016c000100 +ingress(10) Completed: Canister: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(11) Completed: Canister: Payload: 0x4449444c016c000100 +ingress(11) Completed: Canister: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(12) Completed: Canister: Payload: 0x4449444c016c000100 +ingress(12) Completed: Canister: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(13) Completed: Canister: Payload: 0x4449444c016c000100 +ingress(13) Completed: Canister: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(14) Completed: Canister: Payload: 0x4449444c016c000100 +ingress(14) Completed: Canister: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(15) Completed: Canister: Payload: 0x4449444c016c000100 +ingress(15) Completed: Canister: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(16) Completed: Canister: Payload: 0x4449444c016c000100 +ingress(16) Completed: Canister: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(17) Completed: Canister: Payload: 0x4449444c016c000100 +ingress(17) Completed: Canister: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(18) Completed: Canister: Payload: 0x4449444c016c000100 +ingress(18) Completed: Canister: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(19) Completed: Canister: Payload: 0x4449444c016c000100 +ingress(19) Completed: Canister: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(20) Completed: Canister: Payload: 0x4449444c016c000100 +ingress(20) Completed: Canister: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(21) Completed: Canister: Payload: 0x4449444c016c000100 +ingress(21) Completed: Canister: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(22) Completed: Canister: Payload: 0x4449444c016c000100 +ingress(22) Completed: Canister: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(23) Completed: Canister: Payload: 0x4449444c016c000100 +ingress(23) Completed: Canister: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(24) Completed: Canister: Payload: 0x4449444c016c000100 +ingress(24) Completed: Canister: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(25) Completed: Canister: Payload: 0x4449444c016c000100 +ingress(25) Completed: Canister: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(26) Completed: Canister: Payload: 0x4449444c016c000100 +ingress(26) Completed: Canister: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(27) Completed: Canister: Payload: 0x4449444c016c000100 +ingress(27) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-nary.drun-run.ok b/test/run-drun/ok/idl-nary.drun-run.ok new file mode 100644 index 00000000000..4fa7f5b6645 --- /dev/null +++ b/test/run-drun/ok/idl-nary.drun-run.ok @@ -0,0 +1,9 @@ +ingress(0) System +ingress(1) Completed: Canister: Payload: 0x4449444c00027171034f6e650354776f +ingress(2) Completed: Canister: Payload: 0x4449444c0003717171034f6e650354776f055468726565 +ingress(3) Completed: Canister: Payload: 0x4449444c000471717171034f6e650354776f05546872656504466f7572 +ingress(4) Completed: Canister: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 +ingress(5) Completed: Canister: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 +ingress(6) Completed: Canister: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 +ingress(7) Completed: Canister: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 +ingress(8) Completed: Canister: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 diff --git a/test/run-drun/ok/idl-option.drun-run.ok b/test/run-drun/ok/idl-option.drun-run.ok index 99e54d0b73a..028b1b4aa2e 100644 --- a/test/run-drun/ok/idl-option.drun-run.ok +++ b/test/run-drun/ok/idl-option.drun-run.ok @@ -1,7 +1,7 @@ ingress(0) System debug.print: ok: null -ingress(1) Completed: Canister: Payload: 0x4449444c016c000100 +ingress(1) Completed: Canister: Payload: 0x4449444c0000 debug.print: ok: null -ingress(2) Completed: Canister: Payload: 0x4449444c016c000100 +ingress(2) Completed: Canister: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(3) Completed: Canister: Payload: 0x4449444c016c000100 +ingress(3) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-pair.drun-run.ok b/test/run-drun/ok/idl-pair.drun-run.ok new file mode 100644 index 00000000000..fd1ef07bac7 --- /dev/null +++ b/test/run-drun/ok/idl-pair.drun-run.ok @@ -0,0 +1,2 @@ +ingress(0) System +ingress(1) Completed: Canister: Payload: 0x4449444c016c02007c017c01000205 diff --git a/test/run-drun/ok/idl-record.drun-run.ok b/test/run-drun/ok/idl-record.drun-run.ok index 4cb766a7111..933c43b7393 100644 --- a/test/run-drun/ok/idl-record.drun-run.ok +++ b/test/run-drun/ok/idl-record.drun-run.ok @@ -1,9 +1,9 @@ ingress(0) System debug.print: ok: +42 -ingress(1) Completed: Canister: Payload: 0x4449444c016c000100 +ingress(1) Completed: Canister: Payload: 0x4449444c0000 debug.print: ok: Hey! -ingress(2) Completed: Canister: Payload: 0x4449444c016c000100 +ingress(2) Completed: Canister: Payload: 0x4449444c0000 debug.print: ok: +25 -ingress(3) Completed: Canister: Payload: 0x4449444c016c000100 +ingress(3) Completed: Canister: Payload: 0x4449444c0000 debug.print: ok: Hey! +25 ingress(4) Completed: Canister: Payload: 0x4449444c00017719 diff --git a/test/run-drun/ok/idl-tuple.drun-run.ok b/test/run-drun/ok/idl-tuple.drun-run.ok index 3ec4595483e..6789a1dbd26 100644 --- a/test/run-drun/ok/idl-tuple.drun-run.ok +++ b/test/run-drun/ok/idl-tuple.drun-run.ok @@ -1,5 +1,5 @@ ingress(0) System -Ok: Payload: 0x4449444c016c02007c017c01000205 -Ok: Payload: 0x4449444c016c03007c017c027c0100050581848c20 -Ok: Payload: 0x4449444c016c03007c017c027c0100050581848c20 -Ok: Payload: 0x4449444c016c03007c017c027c0100050581848c20 +Ok: Payload: 0x4449444c00027c7c0205 +Ok: Payload: 0x4449444c00037c7c7c050581848c20 +Ok: Payload: 0x4449444c00037c7c7c050581848c20 +Ok: Payload: 0x4449444c00037c7c7c050581848c20 diff --git a/test/run-drun/ok/idl-unit.drun-run.ok b/test/run-drun/ok/idl-unit.drun-run.ok index 7a9005737f9..139fbf3fc92 100644 --- a/test/run-drun/ok/idl-unit.drun-run.ok +++ b/test/run-drun/ok/idl-unit.drun-run.ok @@ -1,2 +1,2 @@ ingress(0) System -Ok: Payload: 0x4449444c016c000100 +Ok: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/reject.drun-run.ok b/test/run-drun/ok/reject.drun-run.ok index 3d9ebbd374b..73e9549eaa4 100644 --- a/test/run-drun/ok/reject.drun-run.ok +++ b/test/run-drun/ok/reject.drun-run.ok @@ -3,7 +3,7 @@ debug.print: 1 ingress(1) Completed: Canister: Reject: 4 debug.print: 1 debug.print: ok -ingress(2) Completed: Canister: Payload: 0x4449444c016c000100 +ingress(2) Completed: Canister: Payload: 0x4449444c0000 debug.print: 1 debug.print: ok ingress(3) Completed: Canister: Reject: 4 From afdb0b8539f6118e9606991b2b0479c29cea0acf Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Sat, 5 Oct 2019 17:56:27 +0200 Subject: [PATCH 0440/1176] Test runner: Do not override node output (#726) * Test runner: Do not override node output `run.sh` was previously writing to `$base.js.out` twice. This fixes this. It uncovers some regressions; committing the status quo here, they will be fixed in #693. * Update test output not sure why my non-nix-node prints these exceptions. * Update test/run.sh --- test/run.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/run.sh b/test/run.sh index 5275bb4305d..5c4373816ed 100755 --- a/test/run.sh +++ b/test/run.sh @@ -68,7 +68,7 @@ failures=no function normalize () { if [ -e "$1" ] then - grep -a -E -v '^Raised by|Raised at|^Re-raised at|^Re-Raised at|^Called from' $1 | + grep -a -E -v '^Raised by|^Raised at|^Re-raised at|^Re-Raised at|^Called from|^ *at ' $1 | sed 's/\x00//g' | sed 's/\x1b\[[0-9;]*[a-zA-Z]//g' | sed 's/^.*[IW], hypervisor:/hypervisor:/g' | @@ -275,9 +275,9 @@ do then $ECHO -n " [node]" export NODE_PATH=$NODE_PATH:$JSCLIENT:$JSCLIENT/src - node $out/$base.js > $out/$base.js.out 2>&1 - normalize $out/$base.js.out - diff_files="$diff_files $base.js.out" + node $out/$base.js >& $out/$base.node 2>&1 + normalize $out/$base.node + diff_files="$diff_files $base.node" fi fi fi From 84d38804dad8519adf2e8d5355f8fff69732b8e6 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Sat, 5 Oct 2019 18:51:06 +0200 Subject: [PATCH 0441/1176] add vector test (#734) --- test/run-drun/idl-vector.as | 13 +++++++++++++ test/run-drun/ok/idl-vector.drun-run.ok | 2 ++ 2 files changed, 15 insertions(+) create mode 100644 test/run-drun/idl-vector.as create mode 100644 test/run-drun/ok/idl-vector.drun-run.ok diff --git a/test/run-drun/idl-vector.as b/test/run-drun/idl-vector.as new file mode 100644 index 00000000000..48391f2a241 --- /dev/null +++ b/test/run-drun/idl-vector.as @@ -0,0 +1,13 @@ +type Rose = [Rose]; +type MayRose = ?[MayRose]; + +func may(r : Rose) : MayRose = ?Array_tabulate(r.len(), func (i : Nat) = may(r[i])); + +actor { + public query func rose(r : Rose) : async MayRose { + may r + } +} + +// [[], [[], [[], [],], [], []], []] +//CALL query rose 0x4449444c016d00010003000400020000000000 diff --git a/test/run-drun/ok/idl-vector.drun-run.ok b/test/run-drun/ok/idl-vector.drun-run.ok new file mode 100644 index 00000000000..a8c227d6d03 --- /dev/null +++ b/test/run-drun/ok/idl-vector.drun-run.ok @@ -0,0 +1,2 @@ +ingress(0) System +Ok: Payload: 0x4449444c026e016d0001000103010001040100010201000100010001000100 From d345f7426f8a275ce7e603fee5a85869659f8387 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Sun, 6 Oct 2019 12:32:07 +0200 Subject: [PATCH 0442/1176] test variants (#737) --- test/run-drun/idl-variant.as | 16 ++++++++++++++++ test/run-drun/ok/idl-variant.drun-run.ok | 2 ++ 2 files changed, 18 insertions(+) create mode 100644 test/run-drun/idl-variant.as create mode 100644 test/run-drun/ok/idl-variant.drun-run.ok diff --git a/test/run-drun/idl-variant.as b/test/run-drun/idl-variant.as new file mode 100644 index 00000000000..730d6b9b7a2 --- /dev/null +++ b/test/run-drun/idl-variant.as @@ -0,0 +1,16 @@ +type Either = { #left: Word32; #right: Word32/* Char */; #fix: Either }; + +func to_left(e : Either) : Either + = switch e { + case (#right n) #left n; + case (#fix t) #fix (to_left t); + case other other + }; + +actor { + public query func numify(t: Either) : async Either { + to_left t + } +} + +//CALL query numify 0x4449444c016b03d583b702008790c0bd0479dc9790cb0e790100000220000000 diff --git a/test/run-drun/ok/idl-variant.drun-run.ok b/test/run-drun/ok/idl-variant.drun-run.ok new file mode 100644 index 00000000000..2e39e7bfc87 --- /dev/null +++ b/test/run-drun/ok/idl-variant.drun-run.ok @@ -0,0 +1,2 @@ +ingress(0) System +Ok: Payload: 0x4449444c016b03d583b702008790c0bd0479dc9790cb0e790100000120000000 From 765c81df5b6662d765973d0acf17dca506c162f5 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Sun, 6 Oct 2019 12:34:13 +0200 Subject: [PATCH 0443/1176] Fix nat64 (#736) --- design/IDL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/design/IDL.md b/design/IDL.md index 7e2e2634a88..1011bcf9c63 100644 --- a/design/IDL.md +++ b/design/IDL.md @@ -921,7 +921,7 @@ T(int) = sleb128(-4) = 0x7c T(nat8) = sleb128(-5) = 0x7b T(nat16) = sleb128(-6) = 0x7a T(nat32) = sleb128(-7) = 0x79 -T(nat32) = sleb128(-8) = 0x78 +T(nat64) = sleb128(-8) = 0x78 T(int8) = sleb128(-9) = 0x77 T(int16) = sleb128(-10) = 0x76 T(int32) = sleb128(-11) = 0x75 From e287db4adf3b73d707f071a42ef2e453fb769893 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 7 Oct 2019 13:35:10 +0200 Subject: [PATCH 0444/1176] =?UTF-8?q?IDL=E2=86=92AS:=20Avoid=20unary=20tup?= =?UTF-8?q?le=20(#732)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit as pointed out by @crusso in https://github.com/dfinity-lab/actorscript/pull/729#issuecomment-538489862 --- design/IDL-AS.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/design/IDL-AS.md b/design/IDL-AS.md index 287d0515af9..18d4b6a1a42 100644 --- a/design/IDL-AS.md +++ b/design/IDL-AS.md @@ -133,7 +133,7 @@ i(reserved) = Any i(opt ) = ? i() i(vec ) = [ i() ] i(blob) = [ word8 ] // if ActorScript had a bytes type, it would show up here -i(record { ;+ }) = ( i(),+ ) // matches tuple short-hand +i(record { ;^N }) = ( i(),^N ) if n > 1 // matches tuple short-hand i(record { ;* }) = { if();* } i(variant { ;* }) = variant { if();* } i(func ) = ifn() @@ -178,7 +178,7 @@ escape = "_" hash() "_" otherwise e({_0_:Int, _1_:Nat)) = record {0:int; 1:nat} ``` - * The mapping `i` tries to detect types that can be expressed as (non-nullary) + * The mapping `i` tries to detect types that can be expressed as tuples in ActorScript. ``` i(record {int;nat}) = (Int, Nat) @@ -186,8 +186,14 @@ escape = "_" hash() "_" otherwise i(record {0:Int, 1:Nat)) = {_0_:int; _1_:nat} ``` - But note that `i(record {}) ≠ ()` because `e(()) = null` and we want - `e(i(record {})) = record {}`. + But note that + + * `i(record {}) ≠ ()` because `e(()) = null` and we want + `e(i(record {})) = record {}`. + + * `i(record {int}) ≠ (int,)` because we do not have unary tuples in AS. + Instead, `i(record {int}) = { _0_ : int}` so that `e(i(record {int})) = + record {int}`. * The `escape` and `unescape` functions allow round-tripping of IDL field names that are not valid ActorScript names (fake hash values): From e1a2270053c9c32603ca9c7b414f93e627f7517b Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Mon, 7 Oct 2019 16:08:17 +0200 Subject: [PATCH 0445/1176] IDL handling of Char (#739) * IDL handling of Char * refactor code point check and comment it --- src/codegen/compile.ml | 40 ++++++++++++++++++++++++------------ test/run-drun/idl-variant.as | 4 ++-- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 9331462d33b..14a002c08dd 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -1532,6 +1532,20 @@ module UnboxedSmallWord = struct let unbox_codepoint = compile_shrU_const 8l let box_codepoint = compile_shl_const 8l + (* Checks (n < 0xD800 || 0xE000 ≤ n ≤ 0x10FFFF), + ensuring the codepoint range and the absence of surrogates. *) + let check_and_box_codepoint env get_n = + get_n ^^ compile_unboxed_const 0xD800l ^^ + G.i (Compare (Wasm.Values.I32 I32Op.GeU)) ^^ + get_n ^^ compile_unboxed_const 0xE000l ^^ + G.i (Compare (Wasm.Values.I32 I32Op.LtU)) ^^ + G.i (Binary (Wasm.Values.I32 I32Op.And)) ^^ + get_n ^^ compile_unboxed_const 0x10FFFFl ^^ + G.i (Compare (Wasm.Values.I32 I32Op.GtU)) ^^ + G.i (Binary (Wasm.Values.I32 I32Op.Or)) ^^ + E.then_trap_with env "codepoint out of range" ^^ + get_n ^^ box_codepoint + (* Two utilities for dealing with utf-8 encoded bytes. *) let compile_load_byte get_ptr offset = get_ptr ^^ G.i (Load {ty = I32Type; align = 0; offset; sz = Some (Wasm.Memory.Pack8, Wasm.Memory.ZX)}) @@ -3456,7 +3470,7 @@ module Serialization = struct | Prim Int -> Some 4 | Prim (Nat8|Word8) -> Some 5 | Prim (Nat16|Word16) -> Some 6 - | Prim (Nat32|Word32) -> Some 7 + | Prim (Nat32|Word32|Char) -> Some 7 | Prim (Nat64|Word64) -> Some 8 | Prim Int8 -> Some 9 | Prim Int16 -> Some 10 @@ -3630,7 +3644,7 @@ module Serialization = struct | Prim Int -> inc_data_size (get_x ^^ BigNum.compile_data_size_signed env) | Prim (Int8|Nat8|Word8) -> inc_data_size (compile_unboxed_const 1l) | Prim (Int16|Nat16|Word16) -> inc_data_size (compile_unboxed_const 2l) - | Prim (Int32|Nat32|Word32) -> inc_data_size (compile_unboxed_const 4l) + | Prim (Int32|Nat32|Word32|Char) -> inc_data_size (compile_unboxed_const 4l) | Prim (Int64|Nat64|Word64) -> inc_data_size (compile_unboxed_const 8l) | Prim Bool -> inc_data_size (compile_unboxed_const 1l) | Tup ts -> @@ -3741,6 +3755,11 @@ module Serialization = struct get_x ^^ BoxedSmallWord.unbox env ^^ G.i (Store {ty = I32Type; align = 0; offset = 0l; sz = None}) ^^ compile_unboxed_const 4l ^^ advance_data_buf + | Prim Char -> + get_data_buf ^^ + get_x ^^ UnboxedSmallWord.unbox_codepoint ^^ + G.i (Store {ty = I32Type; align = 0; offset = 0l; sz = None}) ^^ + compile_unboxed_const 4l ^^ advance_data_buf | Prim (Int16|Nat16|Word16) -> get_data_buf ^^ get_x ^^ UnboxedSmallWord.lsb_adjust Word16 ^^ @@ -3902,6 +3921,11 @@ module Serialization = struct assert_prim_typ () ^^ ReadBuf.read_word32 env get_data_buf ^^ BoxedSmallWord.box env + | Prim Char -> + let set_n, get_n = new_local env "len" in + assert_prim_typ () ^^ + ReadBuf.read_word32 env get_data_buf ^^ set_n ^^ + UnboxedSmallWord.check_and_box_codepoint env get_n | Prim (Int16|Nat16|Word16) -> assert_prim_typ () ^^ ReadBuf.read_word16 env get_data_buf ^^ @@ -6105,17 +6129,7 @@ and compile_exp (env : E.t) ae exp = SR.Vanilla, compile_exp_as env ae SR.UnboxedWord32 e ^^ Func.share_code1 env "Word32->Char" ("n", I32Type) [I32Type] - (fun env get_n -> - get_n ^^ compile_unboxed_const 0xD800l ^^ - G.i (Compare (Wasm.Values.I32 I32Op.GeU)) ^^ - get_n ^^ compile_unboxed_const 0xE000l ^^ - G.i (Compare (Wasm.Values.I32 I32Op.LtU)) ^^ - G.i (Binary (Wasm.Values.I32 I32Op.And)) ^^ - get_n ^^ compile_unboxed_const 0x10FFFFl ^^ - G.i (Compare (Wasm.Values.I32 I32Op.GtU)) ^^ - G.i (Binary (Wasm.Values.I32 I32Op.Or)) ^^ - E.then_trap_with env "codepoint out of range" ^^ - get_n ^^ UnboxedSmallWord.box_codepoint) + UnboxedSmallWord.check_and_box_codepoint | _ -> SR.Unreachable, todo_trap env "compile_exp" (Arrange_ir.exp exp) end diff --git a/test/run-drun/idl-variant.as b/test/run-drun/idl-variant.as index 730d6b9b7a2..594cf29f99f 100644 --- a/test/run-drun/idl-variant.as +++ b/test/run-drun/idl-variant.as @@ -1,8 +1,8 @@ -type Either = { #left: Word32; #right: Word32/* Char */; #fix: Either }; +type Either = { #left: Word32; #right: Char; #fix: Either }; func to_left(e : Either) : Either = switch e { - case (#right n) #left n; + case (#right n) #left (charToWord32 n); case (#fix t) #fix (to_left t); case other other }; From cf14d101db13e947051aabeb2522c58ade3e4832 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Tue, 8 Oct 2019 13:19:23 +0200 Subject: [PATCH 0446/1176] update keyword and operator lists (#746) --- emacs/actorscript-mode.el | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/emacs/actorscript-mode.el b/emacs/actorscript-mode.el index 3e87ae6ffa3..64485ab2236 100644 --- a/emacs/actorscript-mode.el +++ b/emacs/actorscript-mode.el @@ -41,25 +41,31 @@ "await" "break" "case" + "catch" "class" "continue" - "label" + "debug" "else" "for" "func" "if" "in" + "import" "module" - "new" "not" "object" "or" + "label" "let" "loop" "private" + "public" "return" "shared" "switch" + "try" + "throw" + "query" "type" "var" "while" @@ -97,6 +103,7 @@ ;"\\^" "<<" ">>" + "+>>" "<<>" "<>>" "#" @@ -116,6 +123,7 @@ "^=" "<<=" ">>=" + "+>>=" "<<>=" "<>>=" "#=" From 4a7c1fa4ee3cb0a29338ab31de2203c678f2c26a Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 8 Oct 2019 13:47:28 +0200 Subject: [PATCH 0447/1176] Bump drun (#747) for no particular reason. --- default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/default.nix b/default.nix index 95857d5e9c3..5ede45f76fb 100644 --- a/default.nix +++ b/default.nix @@ -33,7 +33,7 @@ let dev = import (builtins.fetchGit { let dfinity-repo = import (builtins.fetchGit { url = "ssh://git@github.com/dfinity-lab/dfinity"; # ref = "master"; - rev = "261a330bb6282f864f0de411adf5abe287d7f8be"; + rev = "ab9d9d6ccba33748fc92f6e8d631327f7f25aead"; }) { system = nixpkgs.system; }; in let real-dvm = From 4ff71fef74d1de75c19a06a0fc4f3116733eca3f Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Wed, 9 Oct 2019 16:30:28 +0200 Subject: [PATCH 0448/1176] IDL value syntax (#719) --- design/IDL.md | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/design/IDL.md b/design/IDL.md index 1011bcf9c63..116af51d1bb 100644 --- a/design/IDL.md +++ b/design/IDL.md @@ -1075,3 +1075,51 @@ The same representation is used for function results. Note: * It is unspecified how the pair (B,R) representing a serialised value is bundled together in an external environment. + + +## Text Format + +To enable convenient debugging, we also specify a text format for IDL values. +The types of these values are assumed to be known from context, so the syntax does not attempt to be self-describing. + +``` + ::= + | | | + | : + + ::= + | | | (TODO: same as ActorScript grammar plus sign) + | (TODO: same as ActorScript grammar) + | true | false + | null + + ::= + | opt + | vec { ;* } + | record { ;* } + | variant { } + + ::= = + + ::= + | service (canister URI) + | func . (canister URI and message name) + + ::= ( ,* ) + +``` + +#### Syntactic Shorthands + +Analoguous to types, a few syntactic shorthands are supported that can be reduced to the basic value forms: + +``` + ::= ... + | blob := vec { N;* } where N* are of bytes in the string, interpreted [as in the WebAssembly textual format](https://webassembly.github.io/spec/core/text/values.html#strings) + + ::= ... + | = := = + | := N = where N is either 0 or previous + 1 (only in records) + | := = null (only in variants) + | := = null (only in variants) +``` From 8fb99021e6e224f09bf353ed8b3ef06d8815fad8 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity <48968912+chenyan-dfinity@users.noreply.github.com> Date: Wed, 9 Oct 2019 20:38:03 -0700 Subject: [PATCH 0449/1176] Do not generate empty JS bindings for IDL (#748) * Do not generate empty JS bindings for IDL * update error message --- src/exes/didc.ml | 3 +++ test/idl/ok/diamond2.js.ok | 1 - test/idl/ok/diamond2.js.out.ok | 1 + test/idl/ok/diamond3.js.ok | 1 - test/idl/ok/diamond3.js.out.ok | 1 + test/idl/ok/diamond4.js.ok | 1 - test/idl/ok/diamond4.js.out.ok | 1 + 7 files changed, 6 insertions(+), 3 deletions(-) delete mode 100644 test/idl/ok/diamond2.js.ok create mode 100644 test/idl/ok/diamond2.js.out.ok delete mode 100644 test/idl/ok/diamond3.js.ok create mode 100644 test/idl/ok/diamond3.js.out.ok delete mode 100644 test/idl/ok/diamond4.js.ok create mode 100644 test/idl/ok/diamond4.js.out.ok diff --git a/src/exes/didc.ml b/src/exes/didc.ml index 36e3848f02e..c4167569098 100644 --- a/src/exes/didc.ml +++ b/src/exes/didc.ml @@ -47,6 +47,9 @@ let process_file file : unit = if !out_file = "" then out_file := Filename.remove_extension (Filename.basename file) ^ ".js"; let buf = Diag.run Pipeline.(compile_js_file file) in + if Buffer.length buf = 0 then begin + eprintf "No actor found, cannot generate JS bindings"; exit 1 + end; let oc = open_out !out_file in Buffer.add_string buf "\n"; Buffer.output_buffer oc buf; diff --git a/test/idl/ok/diamond2.js.ok b/test/idl/ok/diamond2.js.ok deleted file mode 100644 index 8b137891791..00000000000 --- a/test/idl/ok/diamond2.js.ok +++ /dev/null @@ -1 +0,0 @@ - diff --git a/test/idl/ok/diamond2.js.out.ok b/test/idl/ok/diamond2.js.out.ok new file mode 100644 index 00000000000..f2dc373ca80 --- /dev/null +++ b/test/idl/ok/diamond2.js.out.ok @@ -0,0 +1 @@ +No actor found, cannot generate JS bindings diff --git a/test/idl/ok/diamond3.js.ok b/test/idl/ok/diamond3.js.ok deleted file mode 100644 index 8b137891791..00000000000 --- a/test/idl/ok/diamond3.js.ok +++ /dev/null @@ -1 +0,0 @@ - diff --git a/test/idl/ok/diamond3.js.out.ok b/test/idl/ok/diamond3.js.out.ok new file mode 100644 index 00000000000..f2dc373ca80 --- /dev/null +++ b/test/idl/ok/diamond3.js.out.ok @@ -0,0 +1 @@ +No actor found, cannot generate JS bindings diff --git a/test/idl/ok/diamond4.js.ok b/test/idl/ok/diamond4.js.ok deleted file mode 100644 index 8b137891791..00000000000 --- a/test/idl/ok/diamond4.js.ok +++ /dev/null @@ -1 +0,0 @@ - diff --git a/test/idl/ok/diamond4.js.out.ok b/test/idl/ok/diamond4.js.out.ok new file mode 100644 index 00000000000..f2dc373ca80 --- /dev/null +++ b/test/idl/ok/diamond4.js.out.ok @@ -0,0 +1 @@ +No actor found, cannot generate JS bindings From d4732ebf09d75ba870d9b1f1e420cfe543e1738d Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 11 Oct 2019 23:46:32 +0200 Subject: [PATCH 0450/1176] Serialization: Allow reference _types_ (even if not values) (#750) this helps @ggreif to use the system to see how certain type descriptions are formed. --- src/codegen/compile.ml | 38 +------------------------------------- 1 file changed, 1 insertion(+), 37 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 14a002c08dd..af0acd26916 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -3419,40 +3419,6 @@ module Serialization = struct (fun (h1,_) (h2,_) -> Lib.Uint32.compare h1 h2) (List.map (fun f -> (Idllib.IdlHash.idl_hash f.Type.lab, f)) fs) - (* Checks whether the serialization of a given type could contain references *) - module TS = Set.Make (struct type t = Type.typ let compare = compare end) - let has_no_references : Type.typ -> bool = fun t -> - let open Type in - let seen = ref TS.empty in (* break the cycles *) - let rec go t = - TS.mem t !seen || - begin - seen := TS.add t !seen; - match t with - | Var _ -> assert false - | (Prim _ | Any | Non | Pre) -> true - | Con (c, ts) -> - begin match Con.kind c with - | Abs _ -> assert false - | Def (tbs,t) -> go (open_ ts t) (* TBR this may fail to terminate *) - end - | Array t -> go t - | Tup ts -> List.for_all go ts - | Func (Shared _, c, tbs, ts1, ts2) -> false - | Func (s, c, tbs, ts1, ts2) -> - let ts = open_binds tbs in - List.for_all go (List.map (open_ ts) ts1) && - List.for_all go (List.map (open_ ts) ts2) - | Opt t -> go t - | Variant fs -> List.for_all (fun f -> go f.typ) fs - | Async t -> go t - | Obj (Actor, fs) -> false - | Obj (_, fs) -> List.for_all (fun f -> go f.typ) fs - | Mut t -> go t - | Typ _ -> false - end - in go t - (* The IDL serialization prefaces the data with a type description. We can statically create the type description in Ocaml code, store it in the program, and just copy it to the beginning of the message. @@ -4101,7 +4067,6 @@ module Serialization = struct let serialize env ts : G.t = let ts_name = String.concat "," (List.map typ_id ts) in let name = "@serialize<" ^ ts_name ^ ">" in - if E.mode env = Flags.ICMode then assert (List.for_all has_no_references ts); (* On ancient API returns databuf/elembuf, on new API returns nothing *) let ret_tys = if E.mode env = Flags.ICMode then [] else [I32Type; I32Type] in Func.share_code1 env name ("x", I32Type) ret_tys (fun env get_x -> @@ -4160,7 +4125,7 @@ module Serialization = struct get_refs_size ^^ compile_unboxed_const 0l ^^ G.i (Compare (Wasm.Values.I32 I32Op.Eq)) ^^ - E.else_trap_with env "has_no_references wrong" ^^ + E.else_trap_with env "cannot send references on IC System API" ^^ (* Copy out the bytes *) reply_with_data env get_data_start get_data_size @@ -4169,7 +4134,6 @@ module Serialization = struct ) let deserialize env ts = - if E.mode env = Flags.ICMode then assert (List.for_all has_no_references ts); let ts_name = String.concat "," (List.map typ_id ts) in let name = "@deserialize<" ^ ts_name ^ ">" in let args = if E.mode env = Flags.ICMode then [] else [("databuf",I32Type);("elembuf", I32Type)] in From 425ab44a51d5152ebb7437b4c9995db477ee67bd Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 14 Oct 2019 08:16:11 +0200 Subject: [PATCH 0451/1176] IDL: Fix T for func (#752) ignoring shorthands, a `func` has an array of `datatype`, not `fieldtype` (since #514). This was not reflected in the `T` definition, as @ggreif pointed out in https://github.com/dfinity-lab/actorscript/pull/750#issuecomment-541242760 This fixes this. --- design/IDL.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/design/IDL.md b/design/IDL.md index 116af51d1bb..e44a20127d9 100644 --- a/design/IDL.md +++ b/design/IDL.md @@ -942,8 +942,8 @@ T : -> i8* T(:) = leb128() I() T : -> i8* -T(func (*) -> (*) *) = - sleb128(-22) T*(*) T*(*) T*(*) // 0x6a +T(func (*) -> (*) *) = + sleb128(-22) T*(*) T*(*) T*(*) // 0x6a T(service {*}) = sleb128(-23) T*(*) // 0x69 From 7469f684a71f58f55ce03ce0ce0e9416bc661133 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 14 Oct 2019 19:33:10 +0200 Subject: [PATCH 0452/1176] Get rid of call_conv (#730) * Try to get rid call_conv the `call_conv` idea as part of `FuncE` was mostly misguided, at least in the current form (with `FuncE` having a list of argument and return types), as there is a redundancy. Here I explore if we can get rid of it, or at least confine it to the interpreter code (for now). In principle yes, I think. In practice I have introduced bugs that I will have to look at later. * Typo (`run` tests work now) * Update test output this actually works. Nice. * More IR dump test output updates * Fix Ocaml warning * Use ret_tys in async pass * A comment in call_conv.ml --- src/{as_types => as_values}/call_conv.ml | 8 ++ src/{as_types => as_values}/call_conv.mli | 1 + src/as_values/value.ml | 1 - src/codegen/compile.ml | 92 ++++++++++--------- src/ir_def/arrange_ir.ml | 10 +- src/ir_def/check_ir.ml | 46 +++++----- src/ir_def/construct.ml | 52 +++++------ src/ir_def/freevars.ml | 4 +- src/ir_def/ir.ml | 5 +- src/ir_def/ir_effect.ml | 2 +- src/ir_interpreter/interpret_ir.ml | 8 +- src/ir_passes/async.ml | 22 ++--- src/ir_passes/await.ml | 12 +-- src/ir_passes/rename.ml | 7 +- src/ir_passes/show.ml | 27 +++--- src/ir_passes/tailcall.ml | 14 +-- src/lowering/desugar.ml | 38 ++++---- .../fail/ok/use-before-define5.wasm.stderr.ok | 3 +- .../ok/counter-class.wasm.stderr.ok | 22 +++-- 19 files changed, 194 insertions(+), 180 deletions(-) rename src/{as_types => as_values}/call_conv.ml (73%) rename src/{as_types => as_values}/call_conv.mli (96%) diff --git a/src/as_types/call_conv.ml b/src/as_values/call_conv.ml similarity index 73% rename from src/as_types/call_conv.ml rename to src/as_values/call_conv.ml index e25e6d8692b..b9774c7fcb2 100644 --- a/src/as_types/call_conv.ml +++ b/src/as_values/call_conv.ml @@ -1,5 +1,13 @@ +open As_types open Type +(* +Functions of different arities (even if the look like they have the same type) +are not compatible, but the interpreters just pass tuples to them. In order to +still catch mismatching arities in the interpreter, we tag function values +with their “calling convention”, and check them in calls. +*) + type call_conv = { sort: func_sort; control : control; diff --git a/src/as_types/call_conv.mli b/src/as_values/call_conv.mli similarity index 96% rename from src/as_types/call_conv.mli rename to src/as_values/call_conv.mli index 3e6296e2dbc..7bf71f39b83 100644 --- a/src/as_types/call_conv.mli +++ b/src/as_values/call_conv.mli @@ -1,4 +1,5 @@ (* Calling convention *) +open As_types type call_conv = { sort: Type.func_sort; diff --git a/src/as_values/value.ml b/src/as_values/value.ml index 4ec5eff501f..054361acf82 100644 --- a/src/as_values/value.ml +++ b/src/as_values/value.ml @@ -1,4 +1,3 @@ -open As_types open Printf diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index af0acd26916..6613346ee82 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -1302,17 +1302,17 @@ module Closure = struct * and arguments (n-ary!) * the function closure again! *) - let call_closure env cc = + let call_closure env n_args n_res = (* Calculate the wasm type for a given calling convention. An extra first argument for the closure! *) let ty = E.func_type env (FuncType ( - I32Type :: Lib.List.make cc.Call_conv.n_args I32Type, - FakeMultiVal.ty (Lib.List.make cc.Call_conv.n_res I32Type))) in + I32Type :: Lib.List.make n_args I32Type, + FakeMultiVal.ty (Lib.List.make n_res I32Type))) in (* get the table index *) Heap.load_field funptr_field ^^ (* All done: Call! *) G.i (CallIndirect (nr ty)) ^^ - FakeMultiVal.load env (Lib.List.make cc.Call_conv.n_res I32Type) + FakeMultiVal.load env (Lib.List.make n_res I32Type) let fixed_closure env fi fields = Tagged.obj env Tagged.Closure @@ -2930,7 +2930,7 @@ module Arr = struct (* The closure again *) get_f ^^ (* Call *) - Closure.call_closure env (Call_conv.local_cc 1 1) ^^ + Closure.call_closure env 1 1 ^^ store_ptr ) ^^ get_r @@ -4723,17 +4723,17 @@ module FuncDec = struct let tmp_table_slot = 0l (* The type of messages *) - let message_ty env cc = + let message_ty env = E.func_type env (FuncType ([I32Type; I32Type], [])) (* Expects databuf and elembuf on the stack, in serialized form. *) - let call_funcref env cc get_ref = + let call_funcref env get_ref = compile_unboxed_const tmp_table_slot ^^ (* slot number *) get_ref ^^ (* the unboxed funcref *) Dfinity.system_call env "func" "internalize" ^^ compile_unboxed_const tmp_table_slot ^^ - G.i (CallIndirect (nr (message_ty env cc))) + G.i (CallIndirect (nr (message_ty env))) let export_self_message env = Func.share_code1 env "export_self_message" ("name", I32Type) [I32Type] (fun env get_name -> @@ -4762,9 +4762,10 @@ module FuncDec = struct (* Create a WebAssembly func from a pattern (for the argument) and the body. Parameter `captured` should contain the, well, captured local variables that the function will find in the closure. *) - let compile_local_function outer_env outer_ae cc restore_env args mk_body at = + let compile_local_function outer_env outer_ae restore_env args mk_body ret_tys at = let arg_names = List.map (fun a -> a.it, I32Type) args in - let retty = Lib.List.make cc.Call_conv.n_res I32Type in + let n_res = List.length ret_tys in + let retty = Lib.List.make n_res I32Type in let ae0 = ASEnv.mk_fun_ae outer_ae in Func.of_body outer_env (["clos", I32Type] @ arg_names) retty (fun env -> G.with_region at ( let get_closure = G.i (LocalGet (nr 0l)) in @@ -4788,9 +4789,9 @@ module FuncDec = struct - Do GC at the end - Fake orthogonal persistence *) - let compile_message outer_env outer_ae cc restore_env args mk_body at = + let compile_message outer_env outer_ae sort restore_env args mk_body ret_tys at = assert (E.mode outer_env = Flags.AncientMode); - assert (cc.Call_conv.n_res = 0); + assert (List.length ret_tys = 0); let ae0 = ASEnv.mk_fun_ae outer_ae in Func.of_body outer_env ["clos", I32Type; "databuf", I32Type; "elembuf", I32Type] [] (fun env -> G.with_region at ( let get_databuf = G.i (LocalGet (nr 1l)) in @@ -4818,7 +4819,7 @@ module FuncDec = struct closure_code ^^ mk_body env ae2 ^^ - match cc.Call_conv.sort with + match sort with | Type.Shared Type.Write -> (* Collect garbage *) G.i (Call (nr (E.built_in env "collect"))) ^^ @@ -4830,10 +4831,10 @@ module FuncDec = struct | _ -> assert false )) - let compile_static_message outer_env outer_ae cc args mk_body ret_tys at : E.func_with_names = + let compile_static_message outer_env outer_ae sort args mk_body ret_tys at : E.func_with_names = match E.mode outer_env with | Flags.AncientMode -> - assert (cc.Call_conv.n_res = 0); + assert (List.length ret_tys = 0); let ae0 = ASEnv.mk_fun_ae outer_ae in Func.of_body outer_env ["databuf", I32Type; "elembuf", I32Type] [] (fun env -> G.with_region at ( let get_databuf = G.i (LocalGet (nr 0l)) in @@ -4852,7 +4853,7 @@ module FuncDec = struct mk_body env ae1 ^^ - match cc.Call_conv.sort with + match sort with | Type.Shared Type.Write -> (* Collect garbage *) G.i (Call (nr (E.built_in env "collect"))) ^^ @@ -4875,7 +4876,7 @@ module FuncDec = struct Serialization.deserialize env arg_tys ^^ G.concat (List.rev setters) ^^ mk_body env ae1 ^^ - match cc.Call_conv.sort with + match sort with | Type.Shared Type.Write -> (* Collect garbage *) G.i (Call (nr (E.built_in env "collect"))) @@ -4894,23 +4895,23 @@ module FuncDec = struct ) (* Compile a closed function declaration (captures no local variables) *) - let closed pre_env cc name args mk_body ret_tys at = + let closed pre_env sort name args mk_body ret_tys at = let (fi, fill) = E.reserve_fun pre_env name in - if Type.is_shared_sort cc.Call_conv.sort + if Type.is_shared_sort sort then begin declare_dfinity_type pre_env false fi ; ( SR.StaticMessage fi, fun env ae -> - fill (compile_static_message env ae cc args mk_body ret_tys at) + fill (compile_static_message env ae sort args mk_body ret_tys at) ) end else ( SR.StaticFun fi, fun env ae -> let restore_no_env _env ae _ = (ae, G.nop) in - fill (compile_local_function env ae cc restore_no_env args mk_body at) + fill (compile_local_function env ae restore_no_env args mk_body ret_tys at) ) (* Compile a closure declaration (captures local variables) *) - let closure env ae cc name captured args mk_body at = - let is_local = cc.Call_conv.sort = Type.Local in + let closure env ae sort name captured args mk_body ret_tys at = + let is_local = sort = Type.Local in let (set_clos, get_clos) = new_local env (name ^ "_clos") in @@ -4940,8 +4941,8 @@ module FuncDec = struct let f = if is_local - then compile_local_function env ae cc restore_env args mk_body at - else compile_message env ae cc restore_env args mk_body at in + then compile_local_function env ae restore_env args mk_body ret_tys at + else compile_message env ae sort restore_env args mk_body ret_tys at in let fi = E.add_fun env name f in @@ -4985,15 +4986,15 @@ module FuncDec = struct ClosureTable.remember_closure env ^^ Dfinity.system_call env "func" "bind_i32" - let lit env ae how name cc free_vars args mk_body ret_tys at = + let lit env ae how name sort free_vars args mk_body ret_tys at = let captured = List.filter (ASEnv.needs_capture ae) free_vars in if captured = [] then - let (st, fill) = closed env cc name args mk_body ret_tys at in + let (st, fill) = closed env sort name args mk_body ret_tys at in fill env ae; (SR.StaticThing st, G.nop) - else closure env ae cc name captured args mk_body at + else closure env ae sort name captured args mk_body ret_tys at end (* FuncDec *) @@ -6290,24 +6291,28 @@ and compile_exp (env : E.t) ae exp = Tuple.load_n (Int32.of_int n) | ArrayE (m, t, es) -> SR.Vanilla, Arr.lit env (List.map (compile_exp_vanilla env ae) es) - | CallE (cc, e1, _, e2) -> - StackRep.of_arity cc.Call_conv.n_res, + | CallE (e1, _, e2) -> + let sort, _, _, arg_tys, ret_tys = Type.as_func e1.note.note_typ in + let n_args = List.length arg_tys in + let n_res = List.length ret_tys in + + StackRep.of_arity n_res, let fun_sr, code1 = compile_exp env ae e1 in - begin match fun_sr, cc.Call_conv.sort with + begin match fun_sr, sort with | SR.StaticThing (SR.StaticFun fi), _ -> code1 ^^ compile_unboxed_zero ^^ (* A dummy closure *) - compile_exp_as env ae (StackRep.of_arity cc.Call_conv.n_args) e2 ^^ (* the args *) + compile_exp_as env ae (StackRep.of_arity n_args) e2 ^^ (* the args *) G.i (Call (nr fi)) ^^ - FakeMultiVal.load env (Lib.List.make cc.Call_conv.n_res I32Type) + FakeMultiVal.load env (Lib.List.make n_res I32Type) | _, Type.Local -> let (set_clos, get_clos) = new_local env "clos" in code1 ^^ StackRep.adjust env fun_sr SR.Vanilla ^^ set_clos ^^ get_clos ^^ - compile_exp_as env ae (StackRep.of_arity cc.Call_conv.n_args) e2 ^^ + compile_exp_as env ae (StackRep.of_arity n_args) e2 ^^ get_clos ^^ - Closure.call_closure env cc + Closure.call_closure env n_args n_res | _, Type.Shared _ -> let (set_funcref, get_funcref) = new_local env "funcref" in code1 ^^ StackRep.adjust env fun_sr SR.UnboxedReference ^^ @@ -6317,7 +6322,7 @@ and compile_exp (env : E.t) ae exp = serialize individually *) let _, _, _, ts, _ = Type.as_func e1.note.note_typ in Serialization.serialize env ts ^^ - FuncDec.call_funcref env cc get_funcref + FuncDec.call_funcref env get_funcref end | SwitchE (e, cs) -> SR.Vanilla, @@ -6347,10 +6352,11 @@ and compile_exp (env : E.t) ae exp = SR.unit, compile_exp_vanilla env ae e ^^ Var.set_val env ae name - | FuncE (x, cc, typ_binds, args, ret_tys, e) -> + | FuncE (x, sort, _control, typ_binds, args, ret_tys, e) -> let captured = Freevars.captured exp in - let mk_body env1 ae1 = compile_exp_as env1 ae1 (StackRep.of_arity cc.Call_conv.n_res) e in - FuncDec.lit env ae typ_binds x cc captured args mk_body ret_tys exp.at + let n_res = List.length ret_tys in + let mk_body env1 ae1 = compile_exp_as env1 ae1 (StackRep.of_arity n_res) e in + FuncDec.lit env ae typ_binds x sort captured args mk_body ret_tys exp.at | ActorE (i, ds, fs, _) -> SR.UnboxedReference, let captured = Freevars.exp exp in @@ -6676,14 +6682,14 @@ and compile_prog env ae (ds, e) = (ae', code1 ^^ code2) and compile_static_exp env pre_ae how exp = match exp.it with - | FuncE (name, cc, typ_binds, args, ret_tys, e) -> + | FuncE (name, sort, _control, typ_binds, args, ret_tys, e) -> let mk_body env ae = assert begin (* Is this really closed? *) List.for_all (fun v -> ASEnv.NameEnv.mem v ae.ASEnv.vars) (Freevars.M.keys (Freevars.exp e)) end; - compile_exp_as env ae (StackRep.of_arity cc.Call_conv.n_res) e in - FuncDec.closed env cc name args mk_body ret_tys exp.at + compile_exp_as env ae (StackRep.of_arity (List.length ret_tys)) e in + FuncDec.closed env sort name args mk_body ret_tys exp.at | _ -> assert false and compile_prelude env ae = @@ -6724,7 +6730,7 @@ and compile_start_func mod_env (progs : Ir.prog list) : E.func_with_names = let find_last_actor (ds,e) = match find_last_expr ds e with | ds1, ActorE (i, ds2, fs, _) -> Some (i, ds1 @ ds2, fs) - | ds1, FuncE (_name, _cc, [], [], _, {it = ActorE (i, ds2, fs, _);_}) -> + | ds1, FuncE (_name, _sort, _control, [], [], _, {it = ActorE (i, ds2, fs, _);_}) -> Some (i, ds1 @ ds2, fs) | _, _ -> None diff --git a/src/ir_def/arrange_ir.ml b/src/ir_def/arrange_ir.ml index 181aa59dee8..48ea27c9e4e 100644 --- a/src/ir_def/arrange_ir.ml +++ b/src/ir_def/arrange_ir.ml @@ -23,7 +23,7 @@ let rec exp e = match e.it with | AssignE (e1, e2) -> "AssignE" $$ [exp e1; exp e2] | ArrayE (m, t, es) -> "ArrayE" $$ [mut m; typ t] @ List.map exp es | IdxE (e1, e2) -> "IdxE" $$ [exp e1; exp e2] - | CallE (cc, e1, ts, e2) -> "CallE" $$ [call_conv cc; exp e1] @ List.map typ ts @ [exp e2] + | CallE (e1, ts, e2) -> "CallE" $$ [exp e1] @ List.map typ ts @ [exp e2] | BlockE (ds, e1) -> "BlockE" $$ List.map dec ds @ [exp e1] | IfE (e1, e2, e3) -> "IfE" $$ [exp e1; exp e2; exp e3] | SwitchE (e, cs) -> "SwitchE" $$ [exp e] @ List.map case cs @@ -38,8 +38,8 @@ let rec exp e = match e.it with | TagE (i, e) -> "TagE" $$ [id i; exp e] | DeclareE (i, t, e1) -> "DeclareE" $$ [id i; exp e1] | DefineE (i, m, e1) -> "DefineE" $$ [id i; mut m; exp e1] - | FuncE (x, cc, tp, as_, ts, e) -> - "FuncE" $$ [Atom x; call_conv cc] @ List.map typ_bind tp @ args as_@ [ typ (Type.seq ts); exp e] + | FuncE (x, s, c, tp, as_, ts, e) -> + "FuncE" $$ [Atom x; func_sort s; control c] @ List.map typ_bind tp @ args as_@ [ typ (Type.seq ts); exp e] | ActorE (i, ds, fs, t) -> "ActorE" $$ [id i] @ List.map dec ds @ fields fs @ [typ t] | NewObjE (s, fs, t) -> "NewObjE" $$ (Arrange_type.obj_sort s :: fields fs @ [typ t]) | ThrowE e -> "ThrowE" $$ [exp e] @@ -104,7 +104,9 @@ and pat_field pf = pf.it.name $$ [pat pf.it.pat] and case c = "case" $$ [pat c.it.pat; exp c.it.exp] -and call_conv cc = Atom (Call_conv.string_of_call_conv cc) +and func_sort s = Atom (Arrange_type.func_sort s) + +and control s = Atom (Arrange_type.control s) and dec d = match d.it with | LetD (p, e) -> "LetD" $$ [pat p; exp e] diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 83f5e06f95f..f14fdd8ee44 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -429,27 +429,27 @@ let rec check_exp env (exp:Ir.exp) : unit = in typ exp2 <: T.nat; t2 <~ t - | CallE (call_conv, exp1, insts, exp2) -> + | CallE (exp1, insts, exp2) -> check_exp env exp1; check_exp env exp2; - (* TODO: check call_conv (assuming there's something to check) *) let t1 = T.promote (typ exp1) in - let _, tbs, t2, t3 = - try T.as_func_sub call_conv.Call_conv.sort (List.length insts) t1 with - | Invalid_argument _ -> + begin match t1 with + | T.Func (sort, control, tbs, arg_tys, ret_tys) -> + check_inst_bounds env tbs insts exp.at; + check_exp env exp2; + let t_arg = T.open_ insts (T.seq arg_tys) in + let t_ret = T.open_ insts (T.seq ret_tys) in + if T.is_shared_sort sort then begin + check_concrete env exp.at t_arg; + check_concrete env exp.at t_ret; + end; + typ exp2 <: t_arg; + t_ret <: t + | T.Non -> () (* dead code, not much to check here *) + | _ -> error env exp1.at "expected function type, but expression produces type\n %s" (T.string_of_typ_expand t1) - in - check_inst_bounds env tbs insts exp.at; - check_exp env exp2; - let t_arg = T.open_ insts t2 in - let t_ret = T.open_ insts t3 in - if T.is_shared_sort call_conv.Call_conv.sort then begin - check_concrete env exp.at t_arg; - check_concrete env exp.at t_ret; - end; - typ exp2 <: t_arg; - t_ret <: t + end | BlockE (ds, exp1) -> let scope = gather_block_decs env ds in let env' = adjoin env scope in @@ -559,28 +559,24 @@ let rec check_exp env (exp:Ir.exp) : unit = typ exp1 <: t0 end; T.unit <: t - | FuncE (x, cc, typ_binds, args, ret_tys, exp) -> + | FuncE (x, sort, control, typ_binds, args, ret_tys, exp) -> let cs, tbs, ce = check_open_typ_binds env typ_binds in let env' = adjoin_cons env ce in let ve = check_args env' args in List.iter (check_typ env') ret_tys; - check ((T.is_shared_sort cc.Call_conv.sort && Type.is_async (T.seq ret_tys)) + check ((T.is_shared_sort sort && Type.is_async (T.seq ret_tys)) ==> isAsyncE exp) "shared function with async type has non-async body"; - check (cc.Call_conv.n_args = List.length args) - "calling convention arity does not match number of parameters"; - check (cc.Call_conv.n_res = List.length ret_tys) - "calling convention arity does not match number of return types"; - if T.is_shared_sort cc.Call_conv.sort then List.iter (check_concrete env exp.at) ret_tys; + if T.is_shared_sort sort then List.iter (check_concrete env exp.at) ret_tys; let env'' = {env' with labs = T.Env.empty; rets = Some (T.seq ret_tys); async = false} in check_exp (adjoin_vals env'' ve) exp; check_sub env' exp.at (typ exp) (T.seq ret_tys); (* Now construct the function type and compare with the annotation *) let ts1 = List.map (fun a -> a.note) args in - if T.is_shared_sort cc.Call_conv.sort then List.iter (check_concrete env exp.at) ts1; + if T.is_shared_sort sort then List.iter (check_concrete env exp.at) ts1; let fun_ty = T.Func - ( cc.Call_conv.sort, cc.Call_conv.control + ( sort, control , tbs, List.map (T.close cs) ts1, List.map (T.close cs) ret_tys ) in fun_ty <: t diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index d09287403e7..388edf63980 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -1,5 +1,3 @@ -open As_types - (* WIP translation of syntaxops to use IR in place of Source *) open Source open Ir @@ -189,16 +187,17 @@ let boolE b = } let callE exp1 ts exp2 = - let fun_ty = typ exp1 in - let cc = Call_conv.call_conv_of_typ fun_ty in - let _, _, _, ret_ty = T.as_func_sub cc.Call_conv.sort (List.length ts) fun_ty in - { it = CallE (cc, exp1, ts, exp2); - at = no_region; - note = { - note_typ = T.open_ ts ret_ty; - note_eff = max_eff (eff exp1) (eff exp2) + match T.promote (typ exp1) with + | T.Func (_sort, _control, _, _, ret_tys) -> + { it = CallE (exp1, ts, exp2); + at = no_region; + note = { + note_typ = T.open_ ts (T.seq ret_tys); + note_eff = max_eff (eff exp1) (eff exp2) + } } - } + | T.Non -> exp1 + | _ -> raise (Invalid_argument "callE expect a function") let ifE exp1 exp2 exp3 typ = { it = IfE (exp1, exp2, exp3); @@ -367,12 +366,11 @@ let ignoreE exp = (* Mono-morphic function expression *) let funcE name t x exp = - let arg_tys, retty = match t with - | T.Func(_, _, _, ts1, ts2) -> ts1, ts2 + let sort, control, arg_tys, ret_tys = match t with + | T.Func(s, c, _, ts1, ts2) -> s, c, ts1, ts2 | _ -> assert false in - let cc = Call_conv.call_conv_of_typ t in let args, exp' = - if cc.Call_conv.n_args = 1; + if List.length arg_tys = 1; then [ arg_of_exp x ], exp else @@ -382,11 +380,12 @@ let funcE name t x exp = in ({it = FuncE ( name, - cc, + sort, + control, [], args, (* TODO: Assert invariant: retty has no free (unbound) DeBruijn indices -- Claudio *) - retty, + ret_tys, exp' ); at = no_region; @@ -394,17 +393,17 @@ let funcE name t x exp = }) let nary_funcE name t xs exp = - let retty = match t with - | T.Func(_, _, _, _, ts2) -> ts2 + let sort, control, arg_tys, ret_tys = match t with + | T.Func(s, c, _, ts1, ts2) -> s, c, ts1, ts2 | _ -> assert false in - let cc = Call_conv.call_conv_of_typ t in - assert (cc.Call_conv.n_args = List.length xs); + assert (List.length arg_tys = List.length xs); ({it = FuncE ( name, - cc, + sort, + control, [], List.map arg_of_exp xs, - retty, + ret_tys, exp ); at = no_region; @@ -477,11 +476,10 @@ let (-@>*) xs exp = let ( -*- ) exp1 exp2 = match typ exp1 with - | T.Func (_, _, [], ts1, ts2) -> - let cc = Call_conv.call_conv_of_typ (typ exp1) in - { it = CallE (cc, exp1, [], exp2); + | T.Func (_, _, [], _, ret_tys) -> + { it = CallE (exp1, [], exp2); at = no_region; - note = {note_typ = T.seq ts2; + note = {note_typ = T.seq ret_tys; note_eff = max_eff (eff exp1) (eff exp2)} } | typ1 -> failwith diff --git a/src/ir_def/freevars.ml b/src/ir_def/freevars.ml index 55d510158e2..9e158801167 100644 --- a/src/ir_def/freevars.ml +++ b/src/ir_def/freevars.ml @@ -67,7 +67,7 @@ let rec exp e : f = match e.it with | AssignE (e1, e2) -> exps [e1; e2] | ArrayE (m, t, es) -> exps es | IdxE (e1, e2) -> exps [e1; e2] - | CallE (_, e1, ts, e2) -> exps [e1; e2] + | CallE (e1, ts, e2) -> exps [e1; e2] | BlockE (ds, e1) -> close (decs ds +++ exp e1) | IfE (e1, e2, e3) -> exps [e1; e2; e3] | SwitchE (e, cs) -> exp e ++ cases cs @@ -82,7 +82,7 @@ let rec exp e : f = match e.it with | TagE (_, e) -> exp e | DeclareE (i, t, e) -> exp e // i | DefineE (i, m, e) -> id i ++ exp e - | FuncE (x, cc, tp, as_, t, e) -> under_lambda (exp e /// args as_) + | FuncE (x, s, c, tp, as_, t, e) -> under_lambda (exp e /// args as_) | ActorE (i, ds, fs, _) -> close (decs ds +++ fields fs) // i | NewObjE (_, fs, _) -> fields fs | ThrowE e -> exp e diff --git a/src/ir_def/ir.ml b/src/ir_def/ir.ml index 9200330aed8..7c6a88213c0 100644 --- a/src/ir_def/ir.ml +++ b/src/ir_def/ir.ml @@ -73,8 +73,7 @@ and exp' = | AssignE of exp * exp (* assignment *) | ArrayE of mut * Type.typ * exp list (* array *) | IdxE of exp * exp (* array indexing *) - | CallE of (* function call *) - Call_conv.t * exp * Type.typ list * exp + | CallE of exp * Type.typ list * exp (* function call *) | BlockE of (dec list * exp) (* block *) | IfE of exp * exp * exp (* conditional *) | SwitchE of exp * case list (* switch *) @@ -88,7 +87,7 @@ and exp' = | DeclareE of id * Type.typ * exp (* local promise *) | DefineE of id * mut * exp (* promise fulfillment *) | FuncE of (* function *) - string * Call_conv.t * typ_bind list * arg list * Type.typ list * exp + string * Type.func_sort * Type.control * typ_bind list * arg list * Type.typ list * exp | ActorE of id * dec list * field list * Type.typ (* actor *) | NewObjE of Type.obj_sort * field list * Type.typ (* make an object *) | ThrowE of exp (* throw *) diff --git a/src/ir_def/ir_effect.ml b/src/ir_def/ir_effect.ml index 997ce09b6f8..813fe153fc9 100644 --- a/src/ir_def/ir_effect.ml +++ b/src/ir_def/ir_effect.ml @@ -41,7 +41,7 @@ let rec infer_effect_exp (exp: exp) : T.eff = effect_exp exp1 | IdxE (exp1, exp2) | AssignE (exp1, exp2) - | CallE (_, exp1, _, exp2) -> + | CallE (exp1, _, exp2) -> let t1 = effect_exp exp1 in let t2 = effect_exp exp2 in max_eff t1 t2 diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index 86824de047c..342d300490d 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -7,7 +7,7 @@ open Source module V = Value module T = Type -module CC = As_types.Call_conv +module CC = Call_conv (* Context *) @@ -396,7 +396,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = with Invalid_argument s -> trap exp.at "%s" s) ) ) - | CallE (_cc, exp1, typs, exp2) -> + | CallE (exp1, typs, exp2) -> interpret_exp env exp1 (fun v1 -> interpret_exp env exp2 (fun v2 -> let call_conv, f = V.as_func v1 in @@ -465,7 +465,9 @@ and interpret_exp_mut env exp (k : V.value V.cont) = define_id env id v'; k V.unit ) - | FuncE (x, cc, _typbinds, args, _typ, e) -> + | FuncE (x, sort, control, _typbinds, args, ret_typs, e) -> + let cc = { sort; control; n_args = List.length args; n_res = List.length ret_typs } in + let f = interpret_func env exp.at x args (fun env' -> interpret_exp env' e) in let v = V.Func (cc, f) in diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index 53af99e967b..f9f38774e78 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -345,7 +345,7 @@ module Transform(Platform : sig val platform : platform end) = struct expD (post -*- tupE[])] nary_async ).it - | CallE (cc, exp1, typs, exp2) when isAwaitableFunc exp1 -> + | CallE (exp1, typs, exp2) when isAwaitableFunc exp1 -> let p, ts1,t2 = match typ exp1 with | T.Func (T.Shared _, T.Promises p,tbs,ts1,[T.Async t2]) -> @@ -368,9 +368,9 @@ module Transform(Platform : sig val platform : platform end) = struct .it | PrimE (p, exps) -> PrimE (prim p, List.map t_exp exps) - | CallE (cc, exp1, typs, exp2) -> + | CallE (exp1, typs, exp2) -> assert (not (isAwaitableFunc exp1)); - CallE (cc, t_exp exp1, List.map t_typ typs, t_exp exp2) + CallE (t_exp exp1, List.map t_typ typs, t_exp exp2) | BlockE b -> BlockE (t_block b) | IfE (exp1, exp2, exp3) -> @@ -400,18 +400,17 @@ module Transform(Platform : sig val platform : platform end) = struct DeclareE (id, t_typ typ, t_exp exp1) | DefineE (id, mut ,exp1) -> DefineE (id, mut, t_exp exp1) - | FuncE (x, cc, typbinds, args, typT, exp) -> - let s = cc.Call_conv.sort in + | FuncE (x, s, c, typbinds, args, ret_tys, exp) -> begin match s with | T.Local -> - FuncE (x, cc, t_typ_binds typbinds, t_args args, List.map t_typ typT, t_exp exp) + FuncE (x, s, c, t_typ_binds typbinds, t_args args, List.map t_typ ret_tys, t_exp exp) | T.Shared s' -> begin - match typ exp, cc.Call_conv.control with - | T.Tup [], _ -> - FuncE (x, cc, t_typ_binds typbinds, t_args args, List.map t_typ typT, t_exp exp) - | T.Async res_typ, Promises p -> + match ret_tys, c with + | [], _ -> + FuncE (x, s, c, t_typ_binds typbinds, t_args args, List.map t_typ ret_tys, t_exp exp) + | [T.Async res_typ], Promises p -> let res_typ = t_typ res_typ in let res_typs = flatten p res_typ in let reply_typ = replyT (flatten p) res_typ in @@ -448,8 +447,7 @@ module Transform(Platform : sig val platform : platform end) = struct (t_exp cps) -*- tupE [k;r] | _ -> assert false in - let cc' = Call_conv.message_cc s' (List.length args') in - FuncE (x, cc', typbinds', args', [], exp') + FuncE (x, T.Shared s', Returns, typbinds', args', [], exp') | _ -> assert false end end diff --git a/src/ir_passes/await.ml b/src/ir_passes/await.ml index 98e1e082c1e..48ba0ac295d 100644 --- a/src/ir_passes/await.ml +++ b/src/ir_passes/await.ml @@ -84,8 +84,8 @@ and t_exp' context exp' = ArrayE (mut, typ, List.map (t_exp context) exps) | IdxE (exp1, exp2) -> IdxE (t_exp context exp1, t_exp context exp2) - | CallE (cc, exp1, typs, exp2) -> - CallE (cc, t_exp context exp1, typs, t_exp context exp2) + | CallE (exp1, typs, exp2) -> + CallE (t_exp context exp1, typs, t_exp context exp2) | BlockE b -> BlockE (t_block context b) | IfE (exp1, exp2, exp3) -> @@ -137,9 +137,9 @@ and t_exp' context exp' = DeclareE (id, typ, t_exp context exp1) | DefineE (id, mut ,exp1) -> DefineE (id, mut, t_exp context exp1) - | FuncE (x, s, typbinds, pat, typ, exp) -> + | FuncE (x, s, c, typbinds, pat, typ, exp) -> let context' = LabelEnv.add Return Label LabelEnv.empty in - FuncE (x, s, typbinds, pat, typ,t_exp context' exp) + FuncE (x, s, c, typbinds, pat, typ,t_exp context' exp) | ActorE (id, ds, ids, t) -> ActorE (id, t_decs context ds, ids, t) | NewObjE (sort, ids, typ) -> exp' @@ -262,8 +262,8 @@ and c_exp' context exp k = nary context k (fun vs -> e (ArrayE (mut, typ, vs))) exps | IdxE (exp1, exp2) -> binary context k (fun v1 v2 -> e (IdxE (v1, v2))) exp1 exp2 - | CallE (cc, exp1, typs, exp2) -> - binary context k (fun v1 v2 -> e (CallE (cc, v1, typs, v2))) exp1 exp2 + | CallE (exp1, typs, exp2) -> + binary context k (fun v1 v2 -> e (CallE (v1, typs, v2))) exp1 exp2 | BlockE (decs, exp) -> c_block context decs exp k | IfE (exp1, exp2, exp3) -> diff --git a/src/ir_passes/rename.ml b/src/ir_passes/rename.ml index cb08fb99bb1..e60d6993711 100644 --- a/src/ir_passes/rename.ml +++ b/src/ir_passes/rename.ml @@ -44,8 +44,7 @@ and exp' rho e = match e with | AssignE (e1, e2) -> AssignE (exp rho e1, exp rho e2) | ArrayE (m, t, es) -> ArrayE (m, t, exps rho es) | IdxE (e1, e2) -> IdxE (exp rho e1, exp rho e2) - | CallE (cc, e1, ts, e2) - -> CallE (cc, exp rho e1, ts, exp rho e2) + | CallE (e1, ts, e2) -> CallE (exp rho e1, ts, exp rho e2) | BlockE (ds, e1) -> let ds', rho' = decs rho ds in BlockE (ds', exp rho' e1) | IfE (e1, e2, e3) -> IfE (exp rho e1, exp rho e2, exp rho e3) @@ -63,10 +62,10 @@ and exp' rho e = match e with | DeclareE (i, t, e) -> let i',rho' = id_bind rho i in DeclareE (i', t, exp rho' e) | DefineE (i, m, e) -> DefineE (id rho i, m, exp rho e) - | FuncE (x, s, tp, p, ts, e) -> + | FuncE (x, s, c, tp, p, ts, e) -> let p', rho' = args rho p in let e' = exp rho' e in - FuncE (x, s, tp, p', ts, e') + FuncE (x, s, c, tp, p', ts, e') | NewObjE (s, fs, t) -> NewObjE (s, fields rho fs, t) | ThrowE e -> ThrowE (exp rho e) | TryE (e, cs) -> TryE (exp rho e, cases rho cs) diff --git a/src/ir_passes/show.ml b/src/ir_passes/show.ml index c3e5def44df..95ec31a0e2d 100644 --- a/src/ir_passes/show.ml +++ b/src/ir_passes/show.ml @@ -70,7 +70,7 @@ and t_exp' env = function let t' = T.normalize ot in add_type env t'; let f = idE (show_name_for t') (show_fun_typ_for t') in - CallE (Call_conv.local_cc 1 1, f, [], t_exp env exp1) + CallE (f, [], t_exp env exp1) | PrimE (p, es) -> PrimE (p, t_exps env es) | TupE exps -> TupE (t_exps env exps) | OptE exp1 -> @@ -91,10 +91,10 @@ and t_exp' env = function ArrayE (mut, t, t_exps env exps) | IdxE (exp1, exp2) -> IdxE (t_exp env exp1, t_exp env exp2) - | FuncE (cc, id, typbinds, pat, typT, exp) -> - FuncE (cc, id, typbinds, pat, typT, t_exp env exp) - | CallE (cc, exp1, typs, exp2) -> - CallE(cc, t_exp env exp1, typs, t_exp env exp2) + | FuncE (s, c, id, typbinds, pat, typT, exp) -> + FuncE (s, c, id, typbinds, pat, typT, t_exp env exp) + | CallE (exp1, typs, exp2) -> + CallE(t_exp env exp1, typs, t_exp env exp2) | BlockE block -> BlockE (t_block env block) | IfE (exp1, exp2, exp3) -> IfE (t_exp env exp1, t_exp env exp2, t_exp env exp3) @@ -167,13 +167,12 @@ let text_exp : Ir.exp' -> Ir.exp = fun e -> } let invoke_generated_show : T.typ -> Ir.exp -> Ir.exp = fun t e -> - text_exp (CallE (Call_conv.local_cc 1 1, show_var_for t, [], e)) + text_exp (CallE (show_var_for t, [], e)) let invoke_prelude_show : string -> T.typ -> Ir.exp -> Ir.exp = fun n t e -> let fun_typ = T.Func (T.Local, T.Returns, [], [t], [T.Prim T.Text]) in text_exp (CallE - ( Call_conv.local_cc 1 1 - , { it = VarE n + ( { it = VarE n ; at = no_region ; note = { note_typ = fun_typ; note_eff = T.Triv } } @@ -186,8 +185,7 @@ let invoke_text_of_option : T.typ -> Ir.exp -> Ir.exp -> Ir.exp = fun t f e -> let fun_typ = T.Func (T.Local, T.Returns, [{T.var="T";T.bound=T.Any}], [show_fun_typ_for (T.Var ("T",0)); T.Opt (T.Var ("T",0))], [T.Prim T.Text]) in text_exp (CallE - ( Call_conv.local_cc 2 1 - , { it = VarE "@text_of_option" + ( { it = VarE "@text_of_option" ; at = no_region ; note = { note_typ = fun_typ; note_eff = T.Triv } } @@ -203,8 +201,7 @@ let invoke_text_of_variant : T.typ -> Ir.exp -> T.lab -> Ir.exp -> Ir.exp = fun let fun_typ = T.Func (T.Local, T.Returns, [{T.var="T";T.bound=T.Any}], [T.Prim T.Text; show_fun_typ_for (T.Var ("T",0)); T.Var ("T",0)], [T.Prim T.Text]) in text_exp (CallE - ( Call_conv.local_cc 3 1 - , { it = VarE "@text_of_variant" + ( { it = VarE "@text_of_variant" ; at = no_region ; note = { note_typ = fun_typ; note_eff = T.Triv } } @@ -220,8 +217,7 @@ let invoke_text_of_array : T.typ -> Ir.exp -> Ir.exp -> Ir.exp = fun t f e -> let fun_typ = T.Func (T.Local, T.Returns, [{T.var="T";T.bound=T.Any}], [show_fun_typ_for (T.Var ("T",0)); T.Array (T.Var ("T",0))], [T.Prim T.Text]) in text_exp (CallE - ( Call_conv.local_cc 2 1 - , { it = VarE "@text_of_array" + ( { it = VarE "@text_of_array" ; at = no_region ; note = { note_typ = fun_typ; note_eff = T.Triv } } @@ -237,8 +233,7 @@ let invoke_text_of_array_mut : T.typ -> Ir.exp -> Ir.exp -> Ir.exp = fun t f e - let fun_typ = T.Func (T.Local, T.Returns, [{T.var="T";T.bound=T.Any}], [show_fun_typ_for (T.Var ("T",0)); T.Array (T.Mut (T.Var ("T",0)))], [T.Prim T.Text]) in text_exp (CallE - ( Call_conv.local_cc 2 1 - , { it = VarE "@text_of_array_mut" + ( { it = VarE "@text_of_array_mut" ; at = no_region ; note = { note_typ = fun_typ; note_eff = T.Triv } } diff --git a/src/ir_passes/tailcall.ml b/src/ir_passes/tailcall.ml index cf786d4ac90..f93bf6f7ec0 100644 --- a/src/ir_passes/tailcall.ml +++ b/src/ir_passes/tailcall.ml @@ -101,7 +101,7 @@ and exp' env e : exp' = match e.it with | AssignE (e1, e2) -> AssignE (exp env e1, exp env e2) | ArrayE (m,t,es) -> ArrayE (m,t,(exps env es)) | IdxE (e1, e2) -> IdxE (exp env e1, exp env e2) - | CallE (cc, e1, insts, e2) -> + | CallE (e1, insts, e2) -> begin match e1.it, env with | VarE f1, { tail_pos = true; @@ -110,7 +110,7 @@ and exp' env e : exp' = match e.it with tail_called := true; (blockE (assignEs temps (exp env e2)) (breakE label (tupE []))).it - | _,_-> CallE(cc, exp env e1, insts, exp env e2) + | _,_-> CallE (exp env e1, insts, exp env e2) end | BlockE (ds, e) -> BlockE (block env ds e) | IfE (e1, e2, e3) -> IfE (exp env e1, tailexp env e2, tailexp env e3) @@ -131,11 +131,11 @@ and exp' env e : exp' = match e.it with | DeclareE (i, t, e) -> let env1 = bind env i None in DeclareE (i, t, tailexp env1 e) | DefineE (i, m, e) -> DefineE (i, m, exp env e) - | FuncE (x, cc, tbs, as_, ret_tys, exp0) -> + | FuncE (x, s, c, tbs, as_, ret_tys, exp0) -> let env1 = { tail_pos = true; info = None} in let env2 = args env1 as_ in let exp0' = tailexp env2 exp0 in - FuncE (x, cc, tbs, as_, ret_tys, exp0') + FuncE (x, s, c, tbs, as_, ret_tys, exp0') | ActorE (i, ds, fs, t) -> ActorE (i, ds, fs, t) (* TODO: descent into ds *) | NewObjE (s,is,t) -> NewObjE (s, is, t) @@ -188,7 +188,7 @@ and dec' env d = (* A local let bound function, this is what we are looking for *) (* TODO: Do we need to detect more? A tuple of functions? *) | LetD (({it = VarP id;_} as id_pat), - ({it = FuncE (x, ({ Call_conv.sort = Local; _} as cc), tbs, as_, typT, exp0);_} as funexp)) -> + ({it = FuncE (x, Local, c, tbs, as_, typT, exp0);_} as funexp)) -> let env = bind env id None in begin fun env1 -> let temps = fresh_vars "temp" (List.map (fun a -> Mut a.note) as_) in @@ -220,9 +220,9 @@ and dec' env d = ) ) in - LetD (id_pat, {funexp with it = FuncE (x, cc, tbs, List.map arg_of_exp ids, typT, body)}) + LetD (id_pat, {funexp with it = FuncE (x, Local, c, tbs, List.map arg_of_exp ids, typT, body)}) else - LetD (id_pat, {funexp with it = FuncE (x, cc, tbs, as_, typT, exp0')}) + LetD (id_pat, {funexp with it = FuncE (x, Local, c, tbs, as_, typT, exp0')}) end, env | LetD (p, e) -> diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index f6f613c0aaf..93ae831150d 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -87,14 +87,13 @@ and exp' at note = function I.ArrayE (mut m, T.as_immut t, exps es) | S.IdxE (e1, e2) -> I.IdxE (exp e1, exp e2) | S.FuncE (name, s, tbs, p, _t_opt, e) -> - let cc = Call_conv.call_conv_of_typ note.I.note_typ in - let args, wrap = to_args cc p in + let args, wrap, control, n_res = to_args note.I.note_typ p in let _, _, _, ty = T.as_func_sub s.it (List.length tbs) note.I.note_typ in let tbs' = typ_binds tbs in let vars = List.map (fun (tb : I.typ_bind) -> T.Con (tb.it.I.con, [])) tbs' in let ty = T.open_ vars ty in - let tys = if cc.Call_conv.n_res = 1 then [ty] else T.as_seq ty in - I.FuncE (name, cc, tbs', args, tys, wrap (exp e)) + let tys = if n_res = 1 then [ty] else T.as_seq ty in + I.FuncE (name, s.it, control, tbs', args, tys, wrap (exp e)) (* Primitive functions in the prelude have particular shapes *) | S.CallE ({it=S.AnnotE ({it=S.PrimE p;_}, _);note;_}, _, e) when Lib.String.chop_prefix "num_conv" p <> None -> @@ -114,9 +113,8 @@ and exp' at note = function if T.is_non t then unreachableE.it else - let cc = Call_conv.call_conv_of_typ t in let inst = List.map (fun t -> t.Source.note) inst in - I.CallE (cc, exp e1, inst, exp e2) + I.CallE (exp e1, inst, exp e2) | S.BlockE [] -> I.TupE [] | S.BlockE [{it = S.ExpD e; _}] -> (exp e).it | S.BlockE ds -> I.BlockE (block (T.is_unit note.I.note_typ) ds) @@ -278,7 +276,7 @@ and dec' at n d = match d with I.TypD c | S.ClassD (id, tbs, p, _t_opt, s, self_id, es) -> let id' = {id with note = ()} in - let cc = Call_conv.call_conv_of_typ n.S.note_typ in + let sort, _, _, _, _ = Type.as_func n.S.note_typ in let inst = List.map (fun tb -> match tb.note with @@ -294,9 +292,9 @@ and dec' at n d = match d with | _ -> assert false in let varPat = {it = I.VarP id'.it; at = at; note = fun_typ } in - let args, wrap = to_args cc p in + let args, wrap, control, _n_res = to_args n.S.note_typ p in let fn = { - it = I.FuncE (id.it, cc, typ_binds tbs, args, [obj_typ], wrap + it = I.FuncE (id.it, sort, control, typ_binds tbs, args, [obj_typ], wrap { it = obj at s (Some self_id) es obj_typ; at = at; note = { I.note_typ = obj_typ; I.note_eff = T.Triv } }); @@ -371,12 +369,20 @@ and to_arg p : (Ir.arg * (Ir.exp -> Ir.exp)) = (fun e -> blockE [letP (pat p) v] e) -and to_args cc p : (Ir.arg list * (Ir.exp -> Ir.exp)) = - let n = cc.Call_conv.n_args in - let tys = if n = 1 then [p.note] else T.as_seq p.note in +and to_args typ p : (Ir.arg list * (Ir.exp -> Ir.exp) * T.control * int) = + let sort, control, n_args, n_res = + match typ with + | Type.Func (sort, control, tbds, dom, res) -> + sort, control, List.length dom, List.length res + | Type.Non -> + Type.Local, Type.Returns, 1, 1 + | _ -> raise (Invalid_argument ("to_args " ^ Type.string_of_typ typ)) + in + + let tys = if n_args = 1 then [p.note] else T.as_seq p.note in let args, wrap = - match n, p.it with + match n_args, p.it with | _, S.WildP -> let vs = fresh_vars "param" tys in List.map arg_of_exp vs, @@ -387,7 +393,7 @@ and to_args cc p : (Ir.arg list * (Ir.exp -> Ir.exp)) = | 0, S.TupP [] -> [] , (fun e -> e) | _, S.TupP ps -> - assert (List.length ps = n); + assert (List.length ps = n_args); List.fold_right (fun p (args, wrap) -> let (a, wrap1) = to_arg p in (a::args, fun e -> wrap1 (wrap e)) @@ -399,13 +405,13 @@ and to_args cc p : (Ir.arg list * (Ir.exp -> Ir.exp)) = in let wrap_under_async e = - if T.is_shared_sort cc.Call_conv.sort && cc.Call_conv.control <> T.Returns + if T.is_shared_sort sort && control <> T.Returns then match e.it with | Ir.AsyncE e' -> { e with it = Ir.AsyncE (wrap e') } | _ -> assert false else wrap e in - args, wrap_under_async + args, wrap_under_async, control, n_res and prog (p : Syntax.prog) : Ir.prog = begin match p.it with diff --git a/test/fail/ok/use-before-define5.wasm.stderr.ok b/test/fail/ok/use-before-define5.wasm.stderr.ok index 338435413bd..328a44f1679 100644 --- a/test/fail/ok/use-before-define5.wasm.stderr.ok +++ b/test/fail/ok/use-before-define5.wasm.stderr.ok @@ -4,7 +4,8 @@ non-closed actor: (ActorE (VarP foo) (FuncE foo - (shared 0 -> 0) + Shared + Returns () (AssertE (PrimE (RelPrim Nat EqOp) (VarE x) (LitE (NatLit 1)))) ) diff --git a/test/run-dfinity/ok/counter-class.wasm.stderr.ok b/test/run-dfinity/ok/counter-class.wasm.stderr.ok index 31e833d6ed6..3b0a2a05f55 100644 --- a/test/run-dfinity/ok/counter-class.wasm.stderr.ok +++ b/test/run-dfinity/ok/counter-class.wasm.stderr.ok @@ -5,10 +5,11 @@ non-closed actor: (ActorE (VarP dec) (FuncE dec - (shared 0 -> 0) + Shared + Returns () (BlockE - (LetD WildP (CallE (1 -> 0) (VarE showCounter) (VarE j))) + (LetD WildP (CallE (VarE showCounter) (VarE j))) (AssignE (VarE j) (PrimE (BinPrim Int SubOp) (VarE j) (LitE (IntLit 1))) @@ -20,29 +21,32 @@ non-closed actor: (ActorE (VarP read) (FuncE read - (shared 1 -> 0) + Shared + Returns (params $reply/0) () (CallE - (2 -> 0) (FuncE $lambda - (2 -> 0) + Local + Returns (params $k/0 $r/0) () - (CallE (1 -> 0) (VarE $k/0) (VarE j)) + (CallE (VarE $k/0) (VarE j)) ) (TupE (FuncE $lambda - (1 -> 0) + Local + Returns (params $v/0) () - (CallE (shared 1 -> 0) (VarE $reply/0) (VarE $v/0)) + (CallE (VarE $reply/0) (VarE $v/0)) ) (FuncE $lambda - (1 -> 0) + Local + Returns (params $e/0) () (AssertE (LitE (BoolLit false))) From 775038fae469dcb6bcfb5b3faa417e00feab1e59 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Mon, 14 Oct 2019 14:44:47 -0700 Subject: [PATCH 0453/1176] IDL: update generated JS bindings (#693) * IDL: update generated JS bindings Motivation for these changes are as follows: 1. The previous implementation used `require` to import a dependency instead of using the standardized ECMAScript module syntax. Some environments (including Node.js and web browsers) already support ECMAScript module syntax but know nothing about `require`. By using ECMAScript module syntax, we don't impose a particular module system on consumers, allowing them to bring in a polyfill only if necessary. 2. The previous implementation "imported" (using `require`) a module named "IDL". No such module exists; this only worked as a result of some extra setup. This approach is also inflexible in that it required hard-coding a package name, and creating a direct dependency on it. 3. The previously implementation did not export anything, making it difficult to use with a module system. Now, the module exports a function that accepts a record with an IDL field that represents the IDL module. 4. As recently discussed, "Message" was renamed to "Func". This change is now reflected in the generated JavaScript. However, due to the way we depend on the IDL module, breaking changes of this nature can now be handled at the call site if necessary. For example, if the JS bindings still used `IDL.Message`, we could do this: ```javascript import makeActorInterface from "actor.js"; const actorInterface = makeActorInterface({ IDL: { ...IDL, Message: IDL.Func, }, }); ``` * Remove unused environment variable * Test generated JS bindings against js-user-library * Don't run Node.js tests on empty gemerated files * Make esm & js-user-library available in nix-shell To allow for running the tests in a nix shell with make: ```sh $ cd actorscript $ nix-shell $ cd src $ make asc && make didc $ cd ../test/idl $ make ``` * Revert "Don't run Node.js tests on empty gemerated files" This reverts commit 079eb4d14b4e32553ce457af6a1013c40c04cb88. * Ensure recursive data exports an ActorInterface * fixup: Ensure recursive data exports an ActorInterface * add .__typ for recursive types only --- default.nix | 23 ++++++++++++++++----- src/idllib/compile_js.ml | 41 ++++++++++++++++++++++++------------- test/idl/ok/actor.js.ok | 12 ++++++----- test/idl/ok/cyclic.js.ok | 8 +++++--- test/idl/ok/diamond.js.ok | 7 +++++-- test/idl/ok/fields.js.ok | 8 +++++--- test/idl/ok/import.js.ok | 9 +++++--- test/idl/ok/import1.js.ok | 6 ++++-- test/idl/ok/import3.js.ok | 14 +++++++------ test/idl/ok/integer.js.ok | 10 +++++---- test/idl/ok/px.js.ok | 8 +++++--- test/idl/ok/recursion.js.ok | 14 +++++++------ test/idl/ok/test.js.ok | 21 ++++++++++--------- test/idl/ok/unicode.js.ok | 12 ++++++----- test/run.sh | 13 +++++++++--- 15 files changed, 132 insertions(+), 74 deletions(-) diff --git a/default.nix b/default.nix index 5ede45f76fb..d5e1d099368 100644 --- a/default.nix +++ b/default.nix @@ -36,6 +36,17 @@ let dfinity-repo = import (builtins.fetchGit { rev = "ab9d9d6ccba33748fc92f6e8d631327f7f25aead"; }) { system = nixpkgs.system; }; in +let sdk = import (builtins.fetchGit { + url = "ssh://git@github.com/dfinity-lab/sdk"; + ref = "paulyoung/ts-user-library"; + rev = "42f15621bc5b228c7fd349cb52f265917d33a3a0"; +}) { system = nixpkgs.system; }; in + +let esm = builtins.fetchTarball { + sha256 = "116k10q9v0yzpng9bgdx3xrjm2kppma2db62mnbilbi66dvrvz9q"; + url = "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz"; +}; in + let real-dvm = if dvm == null then dev.dvm @@ -46,8 +57,7 @@ let real-drun = then dfinity-repo.dfinity.drun else drun; in -# Include js-client -let js-client = dev.js-dfinity-client; in +let js-user-library = sdk.js-user-library; in let haskellPackages = nixpkgs.haskellPackages.override { overrides = self: super: { @@ -269,11 +279,12 @@ rec { nixpkgs.getconf nixpkgs.nodejs-10_x filecheck - js-client + js-user-library dvm drun qc-actorscript lsp-int + esm ] ++ llvmBuildInputs; @@ -283,7 +294,8 @@ rec { export ASC=asc export AS_LD=as-ld export DIDC=didc - export JSCLIENT=${js-client} + export ESM=${esm} + export JS_USER_LIBRARY=${js-user-library} asc --version make parallel qc-actorscript${nixpkgs.lib.optionalString (replay != 0) @@ -552,8 +564,9 @@ rec { )); shellHook = llvmEnv; + ESM=esm; + JS_USER_LIBRARY=js-user-library; TOMMATHSRC = libtommath; - JSCLIENT = js-client; NIX_FONTCONFIG_FILE = users-guide.NIX_FONTCONFIG_FILE; } else null; diff --git a/src/idllib/compile_js.ml b/src/idllib/compile_js.ml index ff0f5d8ed34..1e159436d64 100644 --- a/src/idllib/compile_js.ml +++ b/src/idllib/compile_js.ml @@ -108,7 +108,7 @@ let rec pp_typ ppf t = | OptT t -> str ppf "IDL.Opt("; pp_typ ppf t; str ppf ")"; | VariantT ts -> str ppf "IDL.Variant({"; concat ppf pp_field "," ts; str ppf "})"; | FuncT (ms, t1, t2) -> - str ppf "IDL.Message("; + str ppf "IDL.Func("; pp_fields ppf t1; kwd ppf ","; pp_fields ppf t2; @@ -169,28 +169,40 @@ let pp_rec ppf x = pp_close_box ppf (); pp_print_cut ppf () -let pp_actor ppf actor = +let pp_actor ppf actor recs = pp_open_hovbox ppf 1; kwd ppf "const"; (match actor.it with | ActorD (x, t) -> let x = ("actor_" ^ x.it) @@ x.at in - match t.it with - | ServT tp -> - id ppf x; space ppf (); kwd ppf "="; kwd ppf "new"; - str ppf "IDL.ActorInterface({"; - concat ppf pp_meth "," tp; - str ppf "})" - | VarT var -> id ppf x; space ppf (); kwd ppf "="; id ppf var - | _ -> assert false + (match t.it with + | ServT tp -> + id ppf x; space ppf (); kwd ppf "="; kwd ppf "new"; + str ppf "IDL.ActorInterface({"; + concat ppf pp_meth "," tp; + str ppf "});" + | VarT var -> + id ppf x; space ppf (); kwd ppf "="; + if TS.mem var.it recs then + str ppf (var.it ^ ".__typ;") + else + str ppf var.it; + | _ -> assert false + ); + pp_force_newline ppf (); + kwd ppf "return"; id ppf x; str ppf ";" ); pp_close_box ppf () let pp_header ppf () = pp_open_vbox ppf 0; - str ppf "const IDL = require('IDL')"; + str ppf "export default ({ IDL }) => {"; pp_close_box ppf () - + +let pp_footer ppf () = + pp_force_newline ppf (); + pp_print_string ppf "};" + let pp_prog ppf env prog = match prog.it.actor with | None -> () @@ -205,8 +217,9 @@ let pp_prog ppf env prog = pp_open_vbox ppf 0; TS.iter (pp_rec ppf) recs; List.iter (pp_dec ppf) env_list; - pp_actor ppf actor; - pp_close_box ppf () + pp_actor ppf actor recs; + pp_close_box ppf (); + pp_footer ppf () let compile (scope : Typing.scope) (prog : Syntax.prog) = let buf = Buffer.create 100 in diff --git a/test/idl/ok/actor.js.ok b/test/idl/ok/actor.js.ok index 2225b3b1fd9..36fbe4a2d93 100644 --- a/test/idl/ok/actor.js.ok +++ b/test/idl/ok/actor.js.ok @@ -1,9 +1,11 @@ -const IDL = require('IDL') +export default ({ IDL }) => { const o = IDL.Rec() -const f = IDL.Message(IDL.Obj({'0': IDL.Int8}), IDL.Obj({'0': IDL.Int8})) -const h = IDL.Message(IDL.Obj({'0': f}), IDL.Obj({'0': f})) +const f = IDL.Func(IDL.Obj({'0': IDL.Int8}), IDL.Obj({'0': IDL.Int8})) +const h = IDL.Func(IDL.Obj({'0': f}), IDL.Obj({'0': f})) const g = f o.fill(IDL.Opt(o)) const actor_g = new IDL.ActorInterface({ - 'f': IDL.Message(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': h})), 'g': f, - 'h': g, 'o': IDL.Message(IDL.Obj({'0': o}), IDL.Obj({'0': o}))}) + 'f': IDL.Func(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': h})), 'g': f, 'h': g, + 'o': IDL.Func(IDL.Obj({'0': o}), IDL.Obj({'0': o}))}); + return actor_g; +}; diff --git a/test/idl/ok/cyclic.js.ok b/test/idl/ok/cyclic.js.ok index f04f438c3ba..6aaa361324b 100644 --- a/test/idl/ok/cyclic.js.ok +++ b/test/idl/ok/cyclic.js.ok @@ -1,4 +1,4 @@ -const IDL = require('IDL') +export default ({ IDL }) => { const A = IDL.Rec() const C = A const B = IDL.Opt(C) @@ -8,5 +8,7 @@ const Y = Z const X = Y const actor_S = new IDL.ActorInterface({ 'f': - IDL.Message(IDL.Obj({'0': A, '1': B, '2': C, '3': X, '4': Y, '5': Z}), - IDL.Obj({}))}) + IDL.Func(IDL.Obj({'0': A, '1': B, '2': C, '3': X, '4': Y, '5': Z}), + IDL.Obj({}))}); + return actor_S; +}; diff --git a/test/idl/ok/diamond.js.ok b/test/idl/ok/diamond.js.ok index 360efbdc716..0570db603c6 100644 --- a/test/idl/ok/diamond.js.ok +++ b/test/idl/ok/diamond.js.ok @@ -1,7 +1,10 @@ -const IDL = require('IDL') +export default ({ IDL }) => { const t = IDL.Nat const t2 = IDL.Arr(t) const t3 = IDL.Opt(t) const t1 = IDL.Obj({'0': t2, '1': t3, '2': t}) const actor_S = new IDL.ActorInterface({ - 'f': IDL.Message(IDL.Obj({'0': t, '1': t2, '2': t3}), IDL.Obj({'0': t1}))}) + 'f': IDL.Func(IDL.Obj({'0': t, '1': t2, '2': t3}), IDL.Obj({'0': t1}))}); + + return actor_S; +}; diff --git a/test/idl/ok/fields.js.ok b/test/idl/ok/fields.js.ok index 4e2493fcfad..00c249c0f3c 100644 --- a/test/idl/ok/fields.js.ok +++ b/test/idl/ok/fields.js.ok @@ -1,4 +1,4 @@ -const IDL = require('IDL') +export default ({ IDL }) => { const A = IDL.Obj({'0': IDL.Nat, '1': IDL.Nat, '2': IDL.Nat}) const B = IDL.Obj({'0': IDL.Arr(IDL.Nat8), '35': IDL.Arr(IDL.Nat8), '36': IDL.Nat, @@ -15,5 +15,7 @@ const nest_record = '5': IDL.Nat, '6': IDL.Nat, '7': A, '8': B, '9': C, '10': IDL.Nat}) const actor_S = new IDL.ActorInterface({ 'f': - IDL.Message(IDL.Obj({'0': A, '1': B, '2': C, '3': nest_record}), - IDL.Obj({}))}) + IDL.Func(IDL.Obj({'0': A, '1': B, '2': C, '3': nest_record}), IDL.Obj({})) + }); + return actor_S; +}; diff --git a/test/idl/ok/import.js.ok b/test/idl/ok/import.js.ok index fa9377df38d..daef8d6b5e0 100644 --- a/test/idl/ok/import.js.ok +++ b/test/idl/ok/import.js.ok @@ -1,4 +1,4 @@ -const IDL = require('IDL') +export default ({ IDL }) => { const t = IDL.Arr(IDL.Nat8) const t1 = t const UserId = IDL.Nat @@ -13,7 +13,10 @@ const IdErr = IDL.Obj({'idErr': OpEntId}) const Inventory = IDL.Obj({'produce_id': IDL.Nat, 'quantity': IDL.Nat}) const actor_S = new IDL.ActorInterface({ 'f': - IDL.Message(IDL.Obj({'0': t, '1': t1, '2': t2}), + IDL.Func(IDL.Obj({'0': t, '1': t1, '2': t2}), IDL.Obj({'0': list, '1': IdErr})), 'getInventory': - IDL.Message(IDL.Obj({'producer_id': IDL.Nat}), IDL.Obj({'0': Inventory}))}) + IDL.Func(IDL.Obj({'producer_id': IDL.Nat}), IDL.Obj({'0': Inventory}))}); + + return actor_S; +}; diff --git a/test/idl/ok/import1.js.ok b/test/idl/ok/import1.js.ok index 23a298b9391..944ff4a8b2b 100644 --- a/test/idl/ok/import1.js.ok +++ b/test/idl/ok/import1.js.ok @@ -1,7 +1,9 @@ -const IDL = require('IDL') +export default ({ IDL }) => { const t = IDL.Arr(IDL.Nat8) const t1 = t const UserId = IDL.Nat const t2 = UserId const actor_S = new IDL.ActorInterface({ - 'f': IDL.Message(IDL.Obj({'0': t, '1': t1, '2': t2}), IDL.Obj({}))}) + 'f': IDL.Func(IDL.Obj({'0': t, '1': t1, '2': t2}), IDL.Obj({}))}); + return actor_S; +}; diff --git a/test/idl/ok/import3.js.ok b/test/idl/ok/import3.js.ok index 517f9849fb4..fbd7f269d06 100644 --- a/test/idl/ok/import3.js.ok +++ b/test/idl/ok/import3.js.ok @@ -1,16 +1,16 @@ -const IDL = require('IDL') +export default ({ IDL }) => { const B = IDL.Rec() const list = IDL.Rec() const s = IDL.Rec() const stream = IDL.Rec() const tree = IDL.Rec() -const t = IDL.Message(IDL.Obj({'server': s}), IDL.Obj({})) +const t = IDL.Func(IDL.Obj({'server': s}), IDL.Obj({})) const node = IDL.Obj({'head': IDL.Nat, 'tail': list}) list.fill(IDL.Opt(node)) stream.fill( IDL.Opt( IDL.Obj({'head': IDL.Nat, - 'next': IDL.Message(IDL.Obj({}), IDL.Obj({'0': stream}))})) + 'next': IDL.Func(IDL.Obj({}), IDL.Obj({'0': stream}))})) ) tree.fill( IDL.Variant({ @@ -21,6 +21,8 @@ B.fill(IDL.Opt(A)) s.fill( new IDL.ActorInterface({'f': t, 'g': - IDL.Message(IDL.Obj({'0': list}), - IDL.Obj({'2': stream, '1': tree, '0': B}))})) -const actor_S = s + IDL.Func(IDL.Obj({'0': list}), IDL.Obj({'2': stream, '1': tree, '0': B})) + })) +const actor_S = s.__typ; + return actor_S; +}; diff --git a/test/idl/ok/integer.js.ok b/test/idl/ok/integer.js.ok index 436f404354e..970e4d46cb8 100644 --- a/test/idl/ok/integer.js.ok +++ b/test/idl/ok/integer.js.ok @@ -1,5 +1,7 @@ -const IDL = require('IDL') +export default ({ IDL }) => { const actor_num = new IDL.ActorInterface({ - 'f': IDL.Message(IDL.Obj({'0': IDL.Nat8}), IDL.Obj({'0': IDL.Int16})), - 'g': IDL.Message(IDL.Obj({'0': IDL.Nat64}), IDL.Obj({'0': IDL.Int64})), - 'h': IDL.Message(IDL.Obj({'0': IDL.Int8}), IDL.Obj({'0': IDL.Nat}))}) + 'f': IDL.Func(IDL.Obj({'0': IDL.Nat8}), IDL.Obj({'0': IDL.Int16})), + 'g': IDL.Func(IDL.Obj({'0': IDL.Nat64}), IDL.Obj({'0': IDL.Int64})), + 'h': IDL.Func(IDL.Obj({'0': IDL.Int8}), IDL.Obj({'0': IDL.Nat}))}); + return actor_num; +}; diff --git a/test/idl/ok/px.js.ok b/test/idl/ok/px.js.ok index 06ea8d3f87f..25173a75769 100644 --- a/test/idl/ok/px.js.ok +++ b/test/idl/ok/px.js.ok @@ -1,4 +1,4 @@ -const IDL = require('IDL') +export default ({ IDL }) => { const UserId = IDL.Nat const RegionId = IDL.Nat const ProducerId = IDL.Nat @@ -14,5 +14,7 @@ const OpEntId = IDL.Opt(EntId) const IdErr = IDL.Obj({'idErr': OpEntId}) const actor_ProduceExchange = new IDL.ActorInterface({ 'getInventory': - IDL.Message(IDL.Obj({'producer_id': IDL.Nat, '3667444713': UserInfo}), - IDL.Obj({'0': Inventory, '1': IdErr}))}) + IDL.Func(IDL.Obj({'producer_id': IDL.Nat, '3667444713': UserInfo}), + IDL.Obj({'0': Inventory, '1': IdErr}))}); + return actor_ProduceExchange; +}; diff --git a/test/idl/ok/recursion.js.ok b/test/idl/ok/recursion.js.ok index 1b71a15819f..5d828a96773 100644 --- a/test/idl/ok/recursion.js.ok +++ b/test/idl/ok/recursion.js.ok @@ -1,16 +1,16 @@ -const IDL = require('IDL') +export default ({ IDL }) => { const B = IDL.Rec() const list = IDL.Rec() const s = IDL.Rec() const stream = IDL.Rec() const tree = IDL.Rec() -const t = IDL.Message(IDL.Obj({'server': s}), IDL.Obj({})) +const t = IDL.Func(IDL.Obj({'server': s}), IDL.Obj({})) const node = IDL.Obj({'head': IDL.Nat, 'tail': list}) list.fill(IDL.Opt(node)) stream.fill( IDL.Opt( IDL.Obj({'head': IDL.Nat, - 'next': IDL.Message(IDL.Obj({}), IDL.Obj({'0': stream}))})) + 'next': IDL.Func(IDL.Obj({}), IDL.Obj({'0': stream}))})) ) tree.fill( IDL.Variant({ @@ -21,6 +21,8 @@ B.fill(IDL.Opt(A)) s.fill( new IDL.ActorInterface({'f': t, 'g': - IDL.Message(IDL.Obj({'0': list}), - IDL.Obj({'2': stream, '1': tree, '0': B}))})) -const actor_A = s + IDL.Func(IDL.Obj({'0': list}), IDL.Obj({'2': stream, '1': tree, '0': B})) + })) +const actor_A = s.__typ; + return actor_A; +}; diff --git a/test/idl/ok/test.js.ok b/test/idl/ok/test.js.ok index dc13ef34670..178c3c7ff66 100644 --- a/test/idl/ok/test.js.ok +++ b/test/idl/ok/test.js.ok @@ -1,23 +1,24 @@ -const IDL = require('IDL') +export default ({ IDL }) => { const my_type = IDL.Nat const B = my_type const message = IDL.Obj({'25': B, '26': IDL.None, 'name': IDL.Text}) const broker = new IDL.ActorInterface({ 'find': - IDL.Message(IDL.Obj({'name': IDL.Text}), + IDL.Func(IDL.Obj({'name': IDL.Text}), IDL.Obj({ '0': - new IDL.ActorInterface({'up': IDL.Message(IDL.Obj({}), IDL.Obj({})), - 'current': IDL.Message(IDL.Obj({}), IDL.Obj({'0': IDL.Nat}))}) + new IDL.ActorInterface({'up': IDL.Func(IDL.Obj({}), IDL.Obj({})), + 'current': IDL.Func(IDL.Obj({}), IDL.Obj({'0': IDL.Nat}))}) })) }) const actor_server = new IDL.ActorInterface({ 'addUser': - IDL.Message(IDL.Obj({'name': IDL.Text, 'age': IDL.Nat8}), + IDL.Func(IDL.Obj({'name': IDL.Text, 'age': IDL.Nat8}), IDL.Obj({'id': IDL.Nat64})), - 'userName': - IDL.Message(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({'0': IDL.Text})), - 'userAge': IDL.Message(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({'0': IDL.Nat8})), - 'deleteUser': IDL.Message(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({})), - 'f': IDL.Message(IDL.Obj({'0': message}), IDL.Obj({'0': broker}))}) + 'userName': IDL.Func(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({'0': IDL.Text})), + 'userAge': IDL.Func(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({'0': IDL.Nat8})), + 'deleteUser': IDL.Func(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({})), + 'f': IDL.Func(IDL.Obj({'0': message}), IDL.Obj({'0': broker}))}); + return actor_server; +}; diff --git a/test/idl/ok/unicode.js.ok b/test/idl/ok/unicode.js.ok index f8f246b20ae..8c6ac0b1ec6 100644 --- a/test/idl/ok/unicode.js.ok +++ b/test/idl/ok/unicode.js.ok @@ -1,4 +1,4 @@ -const IDL = require('IDL') +export default ({ IDL }) => { const A = IDL.Obj({'': IDL.Nat, '📦🍦': IDL.Nat, '字段名': IDL.Nat, '字 段 名2': IDL.Nat}) @@ -6,7 +6,9 @@ const B = IDL.Variant({'': IDL.Unit, '空的': IDL.Unit, ' 空的 ': IDL.Unit, '1⃣️2⃣️3⃣️': IDL.Unit}) const actor_C = new IDL.ActorInterface({ - '函数名': IDL.Message(IDL.Obj({'0': A}), IDL.Obj({'0': B})), - '': IDL.Message(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': IDL.Nat})), - '👀': IDL.Message(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': IDL.Nat})), - '✈️ 🚗 ⛱️ ': IDL.Message(IDL.Obj({}), IDL.Obj({}))}) + '函数名': IDL.Func(IDL.Obj({'0': A}), IDL.Obj({'0': B})), + '': IDL.Func(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': IDL.Nat})), + '👀': IDL.Func(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': IDL.Nat})), + '✈️ 🚗 ⛱️ ': IDL.Func(IDL.Obj({}), IDL.Obj({}))}); + return actor_C; +}; diff --git a/test/run.sh b/test/run.sh index 5c4373816ed..edab391f9ae 100755 --- a/test/run.sh +++ b/test/run.sh @@ -31,7 +31,6 @@ export AS_LD WASM=${WASM:-wasm} DVM_WRAPPER=$(realpath $(dirname $0)/dvm.sh) DRUN_WRAPPER=$(realpath $(dirname $0)/drun-wrapper.sh) -JSCLIENT=${JSCLIENT:-$(realpath $(dirname $0)/../../dev/experimental/js-dfinity-client)} ECHO=echo while getopts "a12sir" o; do @@ -274,10 +273,18 @@ do if [ -e $out/$base.js ] then $ECHO -n " [node]" - export NODE_PATH=$NODE_PATH:$JSCLIENT:$JSCLIENT/src - node $out/$base.js >& $out/$base.node 2>&1 + export NODE_PATH=$NODE_PATH:$ESM + + node -r esm $out/$base.js > $out/$base.node 2>&1 normalize $out/$base.node diff_files="$diff_files $base.node" + + node -r esm -e \ + "import actorInterface from './$out/$base.js'; + import { makeActor, makeHttpAgent } from '$JS_USER_LIBRARY'; + const httpAgent = makeHttpAgent({ canisterId: 1 }); + const actor = makeActor(actorInterface)(httpAgent); + assert(Object.entries(actor).length > 0);" fi fi fi From a73825932e8d32ac75d344016523717921bd0055 Mon Sep 17 00:00:00 2001 From: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> Date: Tue, 15 Oct 2019 11:57:55 +0200 Subject: [PATCH 0454/1176] points sdk at newest sdk master (#758) --- default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/default.nix b/default.nix index d5e1d099368..181f4cd02e3 100644 --- a/default.nix +++ b/default.nix @@ -38,7 +38,7 @@ let dfinity-repo = import (builtins.fetchGit { let sdk = import (builtins.fetchGit { url = "ssh://git@github.com/dfinity-lab/sdk"; - ref = "paulyoung/ts-user-library"; + ref = "paulyoung/js-user-library"; rev = "42f15621bc5b228c7fd349cb52f265917d33a3a0"; }) { system = nixpkgs.system; }; in From 20bf6106faf547c1280871942e4e09690d13af27 Mon Sep 17 00:00:00 2001 From: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> Date: Tue, 15 Oct 2019 17:48:53 +0200 Subject: [PATCH 0455/1176] Pretty prints test failures for the LSP integration tests (#763) This should make it easier to tell what's going wrong for a given test failure --- test/lsp-int/Main.hs | 40 ++++++++++++++++++++++++++------------ test/lsp-int/lsp-int.cabal | 1 + 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/test/lsp-int/Main.hs b/test/lsp-int/Main.hs index bd675560113..5a0073ddbd6 100644 --- a/test/lsp-int/Main.hs +++ b/test/lsp-int/Main.hs @@ -1,19 +1,25 @@ {-# language OverloadedStrings #-} {-# language DuplicateRecordFields #-} +{-# language ExplicitForAll #-} +{-# language ScopedTypeVariables #-} module Main where -import Control.Lens ((^.)) -import Control.Monad (unless) -import Control.Monad.IO.Class (liftIO) -import Data.Default -import Data.Text (Text) -import Language.Haskell.LSP.Test hiding (message) -import Language.Haskell.LSP.Types (TextDocumentIdentifier(..), Position(..), HoverContents(..), MarkupContent(..), MarkupKind(..), TextEdit(..), Range(..), DidSaveTextDocumentParams(..), ClientMethod(..)) -import Language.Haskell.LSP.Types.Lens (contents, label, detail, message) -import System.Directory (setCurrentDirectory) -import System.Environment (getArgs) -import Test.Hspec (shouldBe, shouldMatchList) +import qualified Control.Exception as Exception +import Control.Lens ((^.)) +import Control.Monad (unless) +import Control.Monad.IO.Class (liftIO) +import Data.Default +import Data.Text (Text) +import Language.Haskell.LSP.Test hiding (message) +import Language.Haskell.LSP.Types (TextDocumentIdentifier(..), Position(..), HoverContents(..), MarkupContent(..), MarkupKind(..), TextEdit(..), Range(..), DidSaveTextDocumentParams(..), ClientMethod(..)) +import Language.Haskell.LSP.Types.Lens (contents, label, detail, message) +import System.Directory (setCurrentDirectory) +import System.Environment (getArgs) +import System.Exit (exitFailure) +import System.IO (hPutStr, stderr) +import Test.HUnit.Lang (HUnitFailure(..), formatFailureReason) +import Test.Hspec (shouldBe, shouldMatchList) completionTestCase :: TextDocumentIdentifier @@ -44,8 +50,18 @@ plainMarkup t = , _value = t }) +handleHUnitFailure :: forall a. IO a -> IO a +handleHUnitFailure act = do + result :: Either HUnitFailure a <- Exception.try act + case result of + Right res -> + pure res + Left (HUnitFailure _ reason) -> do + hPutStr stderr (formatFailureReason reason) + exitFailure + main :: IO () -main = do +main = handleHUnitFailure $ do args <- getArgs unless (length args == 2) (putStrLn diff --git a/test/lsp-int/lsp-int.cabal b/test/lsp-int/lsp-int.cabal index d076e3bb9c6..436e19d917f 100644 --- a/test/lsp-int/lsp-int.cabal +++ b/test/lsp-int/lsp-int.cabal @@ -17,6 +17,7 @@ executable lsp-int build-depends: base ^>=4.12.0.0 , text ^>=1.2.3.1 , hspec + , HUnit , directory , lens , data-default From 4e77b47d0134cde3d4e7ed9e445bda4e2314d685 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Tue, 15 Oct 2019 18:03:24 +0200 Subject: [PATCH 0456/1176] Tool: pretty print IDL values (#718) * adds an executable for converting binary IDL values to text * add minimal test suite for deser --- default.nix | 17 + src/Makefile | 12 +- src/exes/deser.ml | 514 ++++++++++++++++++++++++++ src/exes/dune | 5 + test/Makefile | 2 + test/run-deser/Makefile | 19 + test/run-deser/five.bin | Bin 0 -> 35 bytes test/run-deser/ok/five.ok | 18 + test/run-drun/idl-func.as | 13 + test/run-drun/ok/idl-func.drun-run.ok | 3 + 10 files changed, 600 insertions(+), 3 deletions(-) create mode 100644 src/exes/deser.ml create mode 100644 test/run-deser/Makefile create mode 100644 test/run-deser/five.bin create mode 100644 test/run-deser/ok/five.ok create mode 100644 test/run-drun/idl-func.as create mode 100644 test/run-drun/ok/idl-func.drun-run.ok diff --git a/default.nix b/default.nix index 181f4cd02e3..6aa2d331adb 100644 --- a/default.nix +++ b/default.nix @@ -272,6 +272,7 @@ rec { buildInputs = [ asc didc + deser ocaml_wasm nixpkgs.wabt nixpkgs.bash @@ -294,6 +295,7 @@ rec { export ASC=asc export AS_LD=as-ld export DIDC=didc + export DESER=deser export ESM=${esm} export JS_USER_LIBRARY=${js-user-library} asc --version @@ -409,6 +411,19 @@ rec { ''; }; + deser = stdenv.mkDerivation { + name = "deser"; + src = subpath ./src; + buildInputs = commonBuildInputs; + buildPhase = '' + make DUNE_OPTS="--display=short --profile release" deser + ''; + installPhase = '' + mkdir -p $out/bin + cp --verbose --dereference deser $out/bin + ''; + }; + wasm = ocaml_wasm; dvm = real-dvm; drun = real-drun; @@ -533,6 +548,7 @@ rec { as-ide js didc + deser tests unit-tests samples @@ -558,6 +574,7 @@ rec { js.buildInputs ++ rts.buildInputs ++ didc.buildInputs ++ + deser.buildInputs ++ tests.buildInputs ++ users-guide.buildInputs ++ [ nixpkgs.ncurses nixpkgs.ocamlPackages.merlin ] diff --git a/src/Makefile b/src/Makefile index 5a690143288..911014ec603 100644 --- a/src/Makefile +++ b/src/Makefile @@ -7,12 +7,13 @@ AS_LD_TARGET = _build/default/exes/as_ld.exe ASC_TARGET = _build/default/exes/asc.exe DIDC_TARGET = _build/default/exes/didc.exe ASC_JS_TARGET = _build/default/js/as_js.bc.js +DESER_TARGET = _build/default/exes/deser.exe DUNE_OPTS ?= -ALL_TARGETS = $(AS_IDE_TARGET) $(AS_LD_TARGET) $(ASC_TARGET) $(ASC_JS_TARGET) $(DIDC_TARGET) +ALL_TARGETS = $(AS_IDE_TARGET) $(AS_LD_TARGET) $(ASC_TARGET) $(ASC_JS_TARGET) $(DIDC_TARGET) $(DESER_TARGET) -.PHONY: all clean asc as-ide as-ld asc.js didc unit-tests +.PHONY: all clean asc as-ide as-ld asc.js didc deser unit-tests # This targets is spelled out so that `make` # only invokes `dune` once, much faster @@ -23,6 +24,7 @@ all: @ln -fs $(AS_LD_TARGET) as-ld @ln -fs $(ASC_JS_TARGET) asc.js @ln -fs $(DIDC_TARGET) didc + @ln -fs $(DESER_TARGET) deser asc: dune build $(DUNE_OPTS) $(ASC_TARGET) @@ -44,11 +46,15 @@ didc: dune build $(DUNE_OPTS) $(DIDC_TARGET) @ln -fs $(DIDC_TARGET) didc +deser: + dune build $(DUNE_OPTS) $(DESER_TARGET) + @ln -fs $(DESER_TARGET) deser + unit-tests: dune runtest $(DUNE_OPTS) clean: - rm -f asc as-ide as-ld asc.js didc + rm -f asc as-ide as-ld asc.js didc deser dune clean test: $(NAME) diff --git a/src/exes/deser.ml b/src/exes/deser.ml new file mode 100644 index 00000000000..8f9eb886471 --- /dev/null +++ b/src/exes/deser.ml @@ -0,0 +1,514 @@ +open Stdio.In_channel +open Lazy + +(* The type of outputters + + While decoding a type, we simultaneously build an outputter (IO action), + that reads bytes from the stdin and dumps to stdout in a formatted way. +*) + +type outputter = unit -> unit + +(* read nothing *) + +let epsilon : outputter = ignore + +(* reading at byte-level *) + +let read_byte () : int = + let b = input_byte stdin in + match b with + | Some b -> b + | None -> failwith "EOF" + +let read_2byte () : int = + let lsb = read_byte () in + let msb = read_byte () in + msb * 256 + lsb + +let read_4byte () : int = + let lsb = read_2byte () in + let msb = read_2byte () in + msb * 65536 + lsb + +let read_8byte () : int = (* TODO: should be bigint *) + let lsb = read_4byte () in + let msb = read_4byte () in + msb * 4294967296 + lsb + +let read_signed_byte () : bool * int = + let b = read_byte () in + if b > 127 then true, b - 128 else false, b + +let read_known char : unit = + match read_byte () with + | b when b = Char.code char -> () + | _ -> failwith "unexpected" + +(* reading numbers *) + +let read_leb128 () : int = (* TODO: should be bigint *) + let rec leb128 w : int = + match read_signed_byte () with + | (true, n) -> w * n + leb128 (w * 128) + | (_, n) -> w * n in + leb128 1 + +let read_sleb128 () : int = (* TODO: should be bigint *) + let rec sleb128 w : int = + match read_signed_byte () with + | (true, n) -> w * n + sleb128 (w * 128) + | (_, n) -> w * if n > 63 then n - 128 else n in + sleb128 1 + +let read_int8 () : int = + match read_signed_byte () with + | (true, n) -> n - 128 + | (_, n) -> n + +let read_int16 () : int = + let lsb = read_byte () in + let msb = read_int8 () in + msb * 256 + lsb + +let read_int32 () : int = + let lsb = read_2byte () in + let msb = read_int16 () in + msb * 65536 + lsb + +let read_int64 () : int = (* TODO: should be bigint *) + let lsb = read_4byte () in + let msb = read_int32 () in + msb * 4294967296 + lsb + +(* bool: M(b : bool) = i8(if b then 1 else 0) *) +let read_bool () : bool = + match read_byte () with + | 0 -> false + | 1 -> true + | _ -> failwith "invalid boolean" + +(* Magic *) + +let read_magic () : unit = + read_known 'D'; + read_known 'I'; + read_known 'D'; + read_known 'L' + +(* Repetition *) + +let read_star_heralding a (heralder : int -> outputter * ('a -> int -> outputter -> outputter)) (t : outputter) : unit = + let rep = read_leb128 () in + let herald_vector, herald_member = heralder rep in + herald_vector (); + for i = 0 to rep - 1 do + herald_member a i t () + done + +let read_t_star (t : unit -> 'a) : 'a array = + let rep = read_leb128 () in + Array.init rep (fun _ -> t ()) + +(* Annotations *) + +type ann = Pure | Oneway + +let read_annotation () : ann = + match read_byte () with + | 1 -> Pure + | 2 -> Oneway + | _ -> failwith "invalid annotation" + +type typ = Null | Bool | Nat | NatN of int + | Int | IntN of int | Text | Reserved | Empty + | Opt of typ Lazy.t | Vec of typ Lazy.t + | Record of fields + | Variant of alts + | Function of typ Lazy.t array * typ Lazy.t array * ann array + +and alts = (int * typ Lazy.t) array +and fields = (int * typ Lazy.t) array + +(* type index/ground type (negative) *) + +let read_type_index () = let ty = read_sleb128 () in assert (ty > -18); ty + +let read_assoc () = let hash = read_leb128 () in + let tynum = read_type_index () in + Printf.printf "hash: %d, tynum: %d\n" hash tynum; hash, tynum + +module type Dump = +sig +val output_nat : int -> unit +val output_int : int -> unit +val output_bool : bool -> unit +val output_nil : outputter +val output_byte : int -> unit +val output_2byte : int -> unit +val output_4byte : int -> unit +val output_8byte : int -> unit +val output_int8 : int -> unit +val output_int16 : int -> unit +val output_int32 : int -> unit +val output_int64 : int -> unit +val output_text : int -> Stdio.In_channel.t -> Stdio.Out_channel.t -> unit +val output_some : outputter -> unit +val output_arguments : int -> outputter * (unit -> int -> outputter -> outputter) +val output_vector : int -> outputter * (unit -> int -> outputter -> outputter) +val output_record : int -> outputter * (fields -> int -> outputter -> outputter) +val output_variant : int -> outputter * (alts -> int -> outputter -> outputter) +end + + +module OutputProse : Dump = struct + +(* indentation *) + +let indent_amount : int = 4 +let indentation : int ref = ref 0 +let continue_line : bool ref = ref false + +let indent () = indentation := !indentation + indent_amount +let outdent () = indentation := !indentation - indent_amount +let ind i = if i = 0 then indent () +let outd max i = if i + 1 = max then outdent () +let bracket max g p i f () = ind i; g p i f; outd max i + +let fill () = if !continue_line then (continue_line := false; "") else String.make !indentation ' ' + +let output_string what (s : string) = Printf.printf "%s%s: %s\n" (fill ()) what s +let output_decimal what (i : int) = Printf.printf "%s%s: %d\n" (fill ()) what i + +(* outputters *) +let output_nat nat = output_decimal "output_nat" nat +let output_int int = output_decimal "output_int" int +let output_bool b = output_string "output_bool" (if b then "true" else "false") +let output_nil () = Printf.printf "%snull (0 bytes)\n" (fill ()) +let output_some consumer = Printf.printf "%sSome: value follows on the next line\n" (fill ()); consumer () +let output_byte b = output_decimal "output_byte" b +let output_2byte b = output_decimal "output_2byte" b +let output_4byte b = output_decimal "output_4byte" b +let output_8byte b = output_decimal "output_8byte" b +let output_int8 i = output_decimal "output_int8" i +let output_int16 i = output_decimal "output_int16" i +let output_int32 i = output_decimal "output_int32" i +let output_int64 i = output_decimal "output_int64" i +let output_text bytes from tostream = + let buf = Buffer.create 0 in + ignore (input_buffer from buf ~len:bytes); + Printf.printf "%sText: %d bytes follow on next line\n" (fill ()) bytes; + Printf.printf "%s---->" (fill ()); (* TODO: puts? *) + Stdio.Out_channel.output_buffer tostream buf; + Printf.printf "\n" + +let output_arguments args : outputter * (unit -> int -> outputter -> outputter) = + let herald_arguments = function + | () when args = 0 -> Printf.printf "%sNo arguments...\n" (fill ()) + | _ when args = 1 -> Printf.printf "%s1 argument follows\n" (fill ()) + | _ -> Printf.printf "%s%d arguments follow\n" (fill ()) args in + let herald_member () i f = Printf.printf "%sArgument #%d%s: " (fill ()) i (if i + 1 = args then " (last)" else ""); continue_line := true; f () in + herald_arguments, bracket args herald_member + +let output_vector members : outputter * (unit -> int -> outputter -> outputter) = + let herald_vector () = if members = 0 then Printf.printf "%sEmpty Vector\n" (fill ()) + else Printf.printf "%sVector with %d members follows\n" (fill ()) members in + let herald_member () i f = Printf.printf "%sVector member %d%s: " (fill ()) i (if i + 1 = members then " (last)" else ""); continue_line := true; f () in + herald_vector, bracket members herald_member + +let output_record members : outputter * (fields -> int -> outputter -> outputter) = + let herald_record () = if members = 0 then Printf.printf "%sEmpty Record\n" (fill ()) + else Printf.printf "%sRecord with %d members follows\n" (fill ()) members in + let herald_member fields i f = Printf.printf "%sRecord member %d%s: " (fill ()) (fst (Array.get fields i)) (if i + 1 = members then " (last)" else ""); continue_line := true; f () in + herald_record, bracket members herald_member + +let output_variant members : outputter * (alts -> int -> outputter -> outputter) = + let herald_variant () = assert (members <> 0); + Printf.printf "%sVariant with %d members follows\n" (fill ()) members in + let herald_member alts i f () = indent (); Printf.printf "%sVariant member %d: " (fill ()) (fst (Array.get alts i)); continue_line := true; f (); outdent () in + herald_variant, herald_member + +end + +module OutputIdl : Dump = struct + +let output_string (s : string) = print_string s +let output_string_space (s : string) = Printf.printf "%s " s +let output_decimal (i : int) = Printf.printf "%d" i +let output_bignum (i : int) = output_decimal i (* for now *) + +let output_bool b = output_string (if b then "true" else "false") +let output_nil () = output_string "null" +let output_some consumer = output_string_space "opt"; consumer () +let output_byte, output_2byte, output_4byte = output_decimal, output_decimal, output_decimal +let output_8byte = output_bignum +let output_nat, output_int = output_bignum, output_bignum +let output_int8, output_int16, output_int32 = output_decimal, output_decimal, output_decimal +let output_int64 = output_bignum +let output_text n froms tos = + output_string "\""; + let buf = Buffer.create 0 in + ignore (input_buffer froms buf ~len:n); + Stdio.Out_channel.output_buffer tos buf; + output_string "\"" + + +let output_arguments args : outputter * (unit -> int -> outputter -> outputter) = + let herald_arguments = function + | () when args = 0 -> output_string "# No arguments...\n" + | _ when args = 1 -> output_string "# 1 argument follows" + | _ -> Printf.printf "# %d arguments follow" args in + let herald_member () i f () = Printf.printf "\n# Argument #%d%s:\n" i (if i + 1 = args then " (last)" else ""); f () in + herald_arguments, (*bracket args*) herald_member + +let start i = if i = 0 then output_string_space "{" +let stop max i = if i + 1 = max then output_string " }" +let bracket max g p i f () = start i; g p i f; stop max i + +let output_vector members : outputter * (unit -> int -> outputter -> outputter) = + let herald_vector () = if members = 0 then output_string_space "vec { }" + else output_string_space "vec" in + let herald_member () i f = f (); output_string_space ";" in + herald_vector, bracket members herald_member + +let output_record members : outputter * (fields -> int -> outputter -> outputter) = + let herald_record () = if members = 0 then output_string_space "record { }" + else output_string_space "record" in + let herald_member fields i f = Printf.printf "%d : " (fst (Array.get fields i)); f (); output_string_space ";" in + herald_record, bracket members herald_member + +let output_variant members : outputter * (alts -> int -> outputter -> outputter) = + let herald_variant () = assert (members <> 0); + output_string_space "variant" in + let herald_member alts i f () = start 0; Printf.printf "%d : " (fst (Array.get alts i)); f (); stop 1 0 in + herald_variant, herald_member +end + + +module OutputJson : Dump = struct + +let output_string (s : string) = print_string s +let output_string_space (s : string) = Printf.printf "%s " s +let output_decimal (i : int) = Printf.printf "%d" i +let output_bignum (i : int) = output_decimal i (* for now *) + +let output_bool b = output_string (if b then "true" else "false") +let output_nil () = output_string "null" +let output_some consumer = output_string "["; consumer (); output_string "]" +let output_byte, output_2byte, output_4byte = output_decimal, output_decimal, output_decimal +let output_8byte = output_bignum +let output_nat, output_int = output_bignum, output_bignum +let output_int8, output_int16, output_int32 = output_decimal, output_decimal, output_decimal +let output_int64 = output_bignum +let output_text n froms tos = + output_string "\""; + let buf = Buffer.create 0 in + ignore (input_buffer froms buf ~len:n); + Stdio.Out_channel.output_buffer tos buf; + output_string "\"" + + +let output_arguments args : outputter * (unit -> int -> outputter -> outputter) = + let herald_arguments = function + | () when args = 0 -> output_string "# No arguments...\n" + | _ when args = 1 -> output_string "# 1 argument follows" + | _ -> Printf.printf "# %d arguments follow" args in + let herald_member () i f () = Printf.printf "\n# Argument #%d%s:\n" i (if i + 1 = args then " (last)" else ""); f () in + herald_arguments, (*bracket args*) herald_member + +let start punct i = if i = 0 then output_string (String.make 1 punct) +let stop punct max i = if i + 1 = max then output_string (String.make 1 punct) +let bracket punct max g p i f () = start (punct.[0]) i; g p i f; stop (punct.[1]) max i + +let output_vector members : outputter * (unit -> int -> outputter -> outputter) = + let punct = "[]" in + let herald_vector () = if members = 0 then output_string_space punct in + let herald_member () i f = if (i > 0) then output_string_space ","; f () in + herald_vector, bracket punct members herald_member + +let output_record members : outputter * (fields -> int -> outputter -> outputter) = + let punct = "{}" in + let herald_record () = if members = 0 then output_string_space punct in + let herald_member fields i f = if (i > 0) then output_string_space ","; Printf.printf "\"_%d_\": " (fst (Array.get fields i)); f () in + herald_record, bracket punct members herald_member + +let output_variant members : outputter * (alts -> int -> outputter -> outputter) = + let herald_variant () = assert (members <> 0) in + let herald_member alts i f () = start '{' 0; Printf.printf "_%d_ : " (fst (Array.get alts i)); f (); stop '}' 1 0 in + herald_variant, herald_member +end + +(* IDL binary mode: + - Legacy: top-level encoded as one value + - Default: top-level are several values + *) +type mode = Unary | Nary + +module MakeOutputter(F : Dump) = struct + +let decode_primitive_type : int -> typ * outputter = + let open F in + function + | -1 -> Null, output_nil + | -2 -> Bool, (fun () -> output_bool (read_bool ())) + | -3 -> Nat, (fun () -> output_nat (read_leb128 ())) + | -4 -> Int, (fun () -> output_int (read_sleb128 ())) + | -5 -> NatN 8, (fun () -> output_byte (read_byte ())) + | -6 -> NatN 16, (fun () -> output_2byte (read_2byte ())) + | -7 -> NatN 32, (fun () -> output_4byte (read_4byte ())) + | -8 -> NatN 64, (fun () -> output_8byte (read_8byte ())) + | -9 -> IntN 8, (fun () -> output_int8 (read_int8 ())) + | -10 -> IntN 16, (fun () -> output_int16 (read_int16 ())) + | -11 -> IntN 32, (fun () -> output_int32 (read_int32 ())) + | -12 -> IntN 64, (fun () -> output_int64 (read_int64 ())) + | -13 | -14 -> failwith "no floats yet" (* TODO *) + | -15 -> Text, (fun () -> let len = read_leb128 () in output_text len stdin stdout) + | -16 -> Reserved, ignore + | -17 -> Empty, ignore + | _ -> failwith "unrecognised primitive type" + + +let read_type lookup : (typ * outputter) Lazy.t = + let lprim_or_lookup = function + | p when p < -17 -> assert false + | p when p < 0 -> lazy (decode_primitive_type p) + | i -> lookup i in + let prim_or_lookup ty = force (lprim_or_lookup ty) in + + let lfst p = lazy (let lazy (f, _) = p in f) in + let lsnd p = lazy (let lazy (_, s) = p in s) in + + let open F in + match read_sleb128 () with + | p when p < 0 && p > -18 -> from_val (decode_primitive_type p) + | -18 -> + let reader consumer () = + match read_byte () with + | 0 -> output_nil () + | 1 -> output_some (force consumer) + | _ -> failwith "invalid optional" in + let i = read_type_index () in + lazy (let p = lprim_or_lookup i in + Opt (lfst p), reader (lsnd p)) + | -19 -> let i = read_type_index () in + lazy + (let p = lprim_or_lookup i in + Vec (lfst p), fun () -> read_star_heralding () output_vector (force (lsnd p))) + | -20 -> let assocs = read_t_star read_assoc in + lazy (let herald_record, herald_member = output_record (Array.length assocs) in + let members = Array.map (fun (i, tynum) -> i, lfst (lprim_or_lookup tynum)) assocs in + let consumers = Array.mapi (herald_member members) (Array.map (fun (_, tynum) () -> snd (prim_or_lookup tynum) ()) assocs) in + Record members, fun () -> herald_record (); Array.iter (fun f -> f ()) consumers) + | -21 -> let assocs = read_t_star read_assoc in + lazy (let herald_variant, herald_member = output_variant (Array.length assocs) in + let alts = Array.map (fun (i, tynum) -> i, lfst (lprim_or_lookup tynum)) assocs in + let consumers = Array.map (fun (_, tynum) () -> snd (prim_or_lookup tynum) ()) assocs in + Variant alts, fun () -> herald_variant (); let i = read_leb128 () in herald_member alts i (Array.get consumers i) ()) + | -22 -> let types1 = read_t_star read_type_index in + let types2 = read_t_star read_type_index in + let anns = read_t_star read_annotation in + lazy (let args = Array.map (fun tynum -> lfst (lprim_or_lookup tynum)) types1 in + let rslts = Array.map (fun tynum -> lfst (lprim_or_lookup tynum)) types2 in + Function (args, rslts, anns), epsilon) + +(* +T(service {*}) = sleb128(-23) T*(* ) +*) + + | t -> failwith (Printf.sprintf "unrecognised structured type: %d" t) + + +let read_type_table (t : unit -> (typ * outputter) Lazy.t) : (typ * outputter) Lazy.t array = + let rep = read_leb128 () in + Array.init rep (fun i -> Printf.printf "read_type_table: %d\n" i;t ()) + +(* Top-level *) + +let top_level md : unit = + Printf.printf "\nDESER, to your service!\n"; + read_magic (); + Printf.printf "\n========================== Type section\n"; + let tab = + let rec tab = lazy (read_type_table (fun () -> read_type lookup)) + and lookup = fun indx -> (*Printf.printf "{indx: %d}" indx; *)Array.get (force tab) indx in + Array.map force (force tab) in + Printf.printf "\n========================== Value section\n"; + let open F in + begin match md with + | Nary -> + let argtys = read_t_star read_type_index in + let herald_arguments, herald_member = output_arguments (Array.length argtys) in + herald_arguments (); + let typ_ingester = function + | prim when prim < 0 -> decode_primitive_type prim + | index -> Array.get tab index in + let consumers = Array.map (fun tynum -> let (ty, m) = typ_ingester tynum in m) argtys in + Array.iteri (fun i f -> herald_member () i f ()) consumers + | Unary -> + let argty = read_type_index () in + Printf.printf "ARGTY: %d\n" argty; + snd (Array.get tab argty) () + end; + Printf.printf "\n-------- DESER DONE\n" + +end + +(* CLI *) + +let name = "deser" +let version = "0.1" +let banner = "Interface Description Language (IDL) " ^ version ^ " message dumper" +let usage = "Usage: " ^ name ^ " [option] [file ...]" + +let mode = ref Nary + +let set_mode m () = + if !mode <> Nary then begin + Printf.eprintf "deser: multiple execution modes specified"; exit 1 + end; + mode := m + +type format = Idl | Prose | Json + +let output_format = ref Idl + +let set_format f () = + if !output_format <> Idl then begin + Printf.eprintf "deser: multiple output formats specified"; exit 1 + end; + output_format := f + +let argspec = Arg.align +[ + "--unary", Arg.Unit (set_mode Unary), " decode legacy (unary) message API"; + "--prose", Arg.Unit (set_format Prose), " output indented prose"; + "--json", Arg.Unit (set_format Json), " output JSON values"; + "--idl", Arg.Unit (set_format Idl), " output IDL values (default)"; + "--version", + Arg.Unit (fun () -> Printf.printf "%s\n" banner; exit 0), " show version"; +] + +let add_arg source = () (* args := !args @ [source] *) + +(* run it *) + +let () = + Arg.parse argspec add_arg usage; + begin match !output_format with + | Prose -> let module Prose = MakeOutputter(OutputProse) in Prose.top_level !mode; + | Idl -> let module Idl = MakeOutputter(OutputIdl) in Idl.top_level !mode; + | Json -> let module Json = MakeOutputter(OutputJson) in Json.top_level !mode; + end; + match input_byte stdin with + | Some _ -> failwith "surplus bytes in input" + | None -> () + + + +(* TODOs: + - use bigint where necessary + - floats + - service types + - escaping in text + - heralding/outputting of type table + *) diff --git a/src/exes/dune b/src/exes/dune index d94e942a9fa..22bf5c23e2f 100644 --- a/src/exes/dune +++ b/src/exes/dune @@ -18,3 +18,8 @@ (modules didc) (libraries idllib) ) +(executable + (name deser) + (modules deser) + (libraries stdio) +) diff --git a/test/Makefile b/test/Makefile index 6291a5b30d5..44b38a1604e 100644 --- a/test/Makefile +++ b/test/Makefile @@ -25,6 +25,7 @@ parallel: quick $(MAKE_PAR) -C run-dfinity quick $(MAKE_PAR) -C run-drun quick $(MAKE_PAR) -C trap quick + $(MAKE_PAR) -C run-deser quick coverage: rm -rf _coverage @@ -53,6 +54,7 @@ accept: $(MAKE) -C as-idl accept $(MAKE) -C trap accept $(MAKE) -C trap check + $(MAKE) -C run-deser accept clean: $(MAKE) -C fail clean diff --git a/test/run-deser/Makefile b/test/run-deser/Makefile new file mode 100644 index 00000000000..2a0f93b1193 --- /dev/null +++ b/test/run-deser/Makefile @@ -0,0 +1,19 @@ +DESER ?= ../../src/deser + +_out/%.done: %.bin | _out + $(DESER) < $< | diff -u $(patsubst %.bin, ok/%.ok, $<) - > $@ + @ cat $@ + +all: quick + +quick: $(patsubst %.bin, _out/%.done, $(wildcard *.bin)) + +accept: $(wildcard *.bin) + rm $(wildcard ok/*.ok) + echo $(foreach FILE,$^,"$(DESER) < $(FILE) > $(patsubst %.bin, ok/%.ok, $(FILE)) ;") \ + | sh + +clean: + rm -rf _out + +include ../*.mk diff --git a/test/run-deser/five.bin b/test/run-deser/five.bin new file mode 100644 index 0000000000000000000000000000000000000000..22053ff42e53679562051975b005562edccee937 GIT binary patch literal 35 ncmZ?qbn#(eEd&8(|GZS@kn()ikc^_#R2H}V(jpeO%(7Gfx?2k6 literal 0 HcmV?d00001 diff --git a/test/run-deser/ok/five.ok b/test/run-deser/ok/five.ok new file mode 100644 index 00000000000..2eabbaa19ef --- /dev/null +++ b/test/run-deser/ok/five.ok @@ -0,0 +1,18 @@ + +DESER, to your service! + +========================== Type section + +========================== Value section +# 5 arguments follow +# Argument #0: +"One" +# Argument #1: +"Two" +# Argument #2: +"Three" +# Argument #3: +"Four" +# Argument #4 (last): +"Five" +-------- DESER DONE diff --git a/test/run-drun/idl-func.as b/test/run-drun/idl-func.as new file mode 100644 index 00000000000..592c306ddf1 --- /dev/null +++ b/test/run-drun/idl-func.as @@ -0,0 +1,13 @@ +type Func = shared Int -> async Func; + +actor { + public query func fun() : async ?Func { + null + }; + public query func fun2(arg : ?Func) : async () { + }; +} + + +//CALL query fun 0x4449444C0000 +//CALL query fun2 0x4449444c026e016a017c0000010000 diff --git a/test/run-drun/ok/idl-func.drun-run.ok b/test/run-drun/ok/idl-func.drun-run.ok new file mode 100644 index 00000000000..c6cc701ed78 --- /dev/null +++ b/test/run-drun/ok/idl-func.drun-run.ok @@ -0,0 +1,3 @@ +ingress(0) System +Ok: Payload: 0x4449444c026e016a017c0000010000 +Ok: Payload: 0x4449444c0000 From 7f7def3a30f8e86a0ec7ba2f79990a12afb2605a Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 15 Oct 2019 17:14:04 +0100 Subject: [PATCH 0457/1176] add some links to doc and examples to README (#764) --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index c2552ef81b4..6feea42daa8 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,20 @@ A simple language for writing Dfinity actors. +## User Documentation & Samples + +Overview slides [here](guide/as-slides.md). + +Draft (incomplete) manual [here](guide/guide.md). + +Prelude [here](src/prelude/prelude.ml). + +Beginnings of standard library [here](stdlib). + +Small samples [here](samples). + +Produce Exchange [here](stdlib/examples/produce-exchange). + ## Introduction ### Motivation and Goals From c0543845f2730dd062dc0725c1037e38f3b7d866 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 16 Oct 2019 14:00:52 +0100 Subject: [PATCH 0458/1176] render .as as swfit on github (#765) --- .gitattributes | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000000..01f89156944 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# .gitattributes file which reclassifies `.as` files as Swift: +*.as linguist-language=Swift \ No newline at end of file From a75bd5310c157dee1c1cb933bbc2370ec7463c3c Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Wed, 16 Oct 2019 18:04:38 +0200 Subject: [PATCH 0459/1176] error out on conflicts (#766) --- src/as_frontend/dune | 2 +- src/idllib/dune | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/as_frontend/dune b/src/as_frontend/dune index 6d0524128c1..a4e2970b0b3 100644 --- a/src/as_frontend/dune +++ b/src/as_frontend/dune @@ -4,7 +4,7 @@ ) (menhir (modules parser) - (flags -v) + (flags -v --strict) (infer false) ) (ocamllex lexer) diff --git a/src/idllib/dune b/src/idllib/dune index 29b1abcce11..0faa69e99c7 100644 --- a/src/idllib/dune +++ b/src/idllib/dune @@ -5,6 +5,7 @@ (menhir (modules parser) + (flags -v --strict) (infer false) ) (ocamllex lexer) From 840d3951224844abd78b533ac034efc2049d83be Mon Sep 17 00:00:00 2001 From: chenyan-dfinity <48968912+chenyan-dfinity@users.noreply.github.com> Date: Wed, 16 Oct 2019 21:06:41 -0700 Subject: [PATCH 0460/1176] Refactor IDL parser.mly (#756) * fix func_mode error message * add pretty printing option for didc * add pretty printing to unit test * fix import path * add field label type in AST * fix asc dependency * fix * fix escape string * proper ident for js * idl pretty printer * better indent * Apply suggestions from code review Co-Authored-By: Gabor Greif * inline for record with one field --- src/as_idl/as_to_idl.ml | 10 +- src/exes/didc.ml | 6 +- src/idllib/arrange_idl.ml | 198 +++++++++++++++++++++------- src/idllib/compile_js.ml | 32 +++-- src/idllib/parser.mly | 24 ++-- src/idllib/pipeline.ml | 2 +- src/idllib/pipeline.mli | 6 +- src/idllib/syntax.ml | 5 +- src/idllib/typing.ml | 25 +++- src/lib/lib.ml | 30 +++++ src/lib/lib.mli | 1 + test/as-idl/ok/counter.did.ok | 9 +- test/as-idl/ok/inline_result.did.ok | 13 +- test/as-idl/ok/pa_cars.did.ok | 47 +++++-- test/as-idl/ok/recursion.did.ok | 16 ++- test/as-idl/ok/result.did.ok | 34 ++++- test/idl/escape.did | 5 + test/idl/fieldnat.did | 5 + test/idl/missing_semicolon.did | 5 + test/idl/ok/actor.js.ok | 16 +-- test/idl/ok/collision_fields.tc.ok | 2 +- test/idl/ok/cyclic.js.ok | 22 ++-- test/idl/ok/diamond.js.ok | 13 +- test/idl/ok/escape.js.ok | 8 ++ test/idl/ok/fieldnat.js.ok | 6 + test/idl/ok/fields.js.ok | 36 ++--- test/idl/ok/import.js.ok | 37 +++--- test/idl/ok/import1.js.ok | 12 +- test/idl/ok/import3.js.ok | 50 +++---- test/idl/ok/integer.js.ok | 8 +- test/idl/ok/missing_semicolon.tc.ok | 1 + test/idl/ok/px.js.ok | 34 ++--- test/idl/ok/recursion.js.ok | 50 +++---- test/idl/ok/test.js.ok | 42 +++--- test/idl/ok/unicode.js.ok | 22 ++-- test/run.sh | 6 + 36 files changed, 549 insertions(+), 289 deletions(-) create mode 100644 test/idl/escape.did create mode 100644 test/idl/fieldnat.did create mode 100644 test/idl/missing_semicolon.did create mode 100644 test/idl/ok/escape.js.ok create mode 100644 test/idl/ok/fieldnat.js.ok create mode 100644 test/idl/ok/missing_semicolon.tc.ok diff --git a/src/as_idl/as_to_idl.ml b/src/as_idl/as_to_idl.ml index 0af3d42aab5..f22ef8b4ff2 100644 --- a/src/as_idl/as_to_idl.ml +++ b/src/as_idl/as_to_idl.ml @@ -128,17 +128,13 @@ let rec typ vs t = and field vs {lab; typ=t} = match unescape lab with | Nat nat -> - let name = Lib.Uint32.to_string nat @@ no_region in - I.{id = nat; name = name; typ = typ vs t} @@ no_region + I.{label = I.Id nat @@ no_region; typ = typ vs t} @@ no_region | Id id -> - let name = id @@ no_region in - let id = Idllib.IdlHash.idl_hash id in - I.{id = id; name = name; typ = typ vs t} @@ no_region + I.{label = I.Named id @@ no_region; typ = typ vs t} @@ no_region and tuple vs ts = List.mapi (fun i x -> let id = Lib.Uint32.of_int i in - let name = Lib.Uint32.to_string id @@ no_region in - I.{id = id; name = name; typ = typ vs x} @@ no_region + I.{label = I.Unnamed id @@ no_region; typ = typ vs x} @@ no_region ) ts and meths vs fs = List.fold_right (fun f list -> diff --git a/src/exes/didc.ml b/src/exes/didc.ml index c4167569098..8cba5593981 100644 --- a/src/exes/didc.ml +++ b/src/exes/didc.ml @@ -9,7 +9,7 @@ let usage = "Usage: " ^ name ^ " [option] [file ...]" (* Argument handling *) -type mode = Default | Check | Js +type mode = Default | Check | Js | PrettyPrint let mode = ref Default let args = ref [] @@ -27,6 +27,7 @@ let argspec = Arg.align [ "--js", Arg.Unit (set_mode Js), " output Javascript binding"; "--check", Arg.Unit (set_mode Check), " type-check only"; + "--pp", Arg.Unit (set_mode PrettyPrint), " Pretty print did file"; "-v", Arg.Set Flags.verbose, " verbose output"; "-dp", Arg.Set Flags.dump_parse, " dump parse"; "-o", Arg.Set_string out_file, " output file"; @@ -43,6 +44,9 @@ let process_file file : unit = assert false | Check -> ignore (Diag.run (Pipeline.check_file file)) + | PrettyPrint -> + let (ast, _) = Diag.run (Pipeline.check_file file) in + printf "%s" (Idllib.Arrange_idl.string_of_prog ast); | Js -> if !out_file = "" then out_file := Filename.remove_extension (Filename.basename file) ^ ".js"; diff --git a/src/idllib/arrange_idl.ml b/src/idllib/arrange_idl.ml index 08cfd9e5920..6bb4d2628fc 100644 --- a/src/idllib/arrange_idl.ml +++ b/src/idllib/arrange_idl.ml @@ -32,11 +32,14 @@ let ($$) head inner = Node (head, inner) and id i = Atom i.it and tag i = Atom ("#" ^ i.it) -let field_tag (tf : typ_field) - = tf.it.name.it ^ "(" ^ Lib.Uint32.to_string tf.it.id ^ ")" +let field_tag (tf : field_label) + = match tf.it with + | Id n -> Lib.Uint32.to_string n + | Named name -> name + | Unnamed n -> Lib.Uint32.to_string n let rec typ_field (tf : typ_field) - = field_tag tf $$ [typ tf.it.typ] + = field_tag (tf.it.label) $$ [typ tf.it.typ] and typ_meth (tb : typ_meth) = tb.it.var.it $$ [typ tb.it.meth] @@ -69,49 +72,152 @@ and prog prog = "Decs" $$ List.map dec prog.it.decs @ [actor prog.it.actor] (* Pretty printing *) - -open Printf -let string_of_list f sep list = String.concat sep (List.map f list) - -let rec string_of_typ t = - match t.it with - | VarT id -> sprintf "%s" id.it - | PrimT s -> string_of_prim s +open Format +let str ppf s = pp_print_string ppf s +let space = pp_print_space +let kwd ppf s = str ppf s; space ppf () +let quote ppf s = + pp_open_hbox ppf (); + str ppf "\""; str ppf (Lib.String.lightweight_escaped s); str ppf "\""; + pp_close_box ppf () + +let rec pp_typ ppf t = + pp_open_hovbox ppf 1; + (match t.it with + | VarT id -> str ppf id.it + | PrimT p -> str ppf (string_of_prim p) + | OptT t -> kwd ppf "opt"; pp_typ ppf t + | VecT t -> kwd ppf "vec"; pp_typ ppf t + | RecordT fs -> pp_fields ppf "record" fs + | VariantT fs -> pp_fields ppf "variant" fs | FuncT (ms,s,t) -> - sprintf "func %s" (string_of_func (ms,s,t)) - | OptT t -> "opt " ^ string_of_typ t - | VecT t -> "vec " ^ string_of_typ t - | RecordT fs -> sprintf "record {%s}" (string_of_list string_of_field "; " fs) - | VariantT fs -> sprintf "variant {%s}" (string_of_list string_of_field "; " fs) - | ServT ms -> sprintf "service {\n%s}" (string_of_list string_of_meth "" ms) - | PreT -> "Pre" -and string_of_func (ms,s,t) = - sprintf "(%s) -> (%s)%s" - (string_of_list string_of_field ", " s) - (string_of_list string_of_field ", " t) - (string_of_list string_of_mode " " ms) -and string_of_field f = - let unnamed = (f.it.name.it = Lib.Uint32.to_string f.it.id) in - if unnamed then string_of_typ f.it.typ - else sprintf "%s : %s" f.it.name.it (string_of_typ f.it.typ) -and string_of_meth m = - sprintf "%s : %s;\n" - m.it.var.it - (match m.it.meth.it with - | FuncT (ms,s,t) -> string_of_func (ms,s,t) - | _ -> string_of_typ m.it.meth) - -let string_of_dec d = - match d.it with - | TypD (id, typ) -> sprintf "type %s = %s;\n" id.it (string_of_typ typ) - | ImportD (f, fp) -> sprintf "import \"%s\";\n" f - -let string_of_actor a = - match a with - | None -> "" - | Some {it = ActorD (id, {it=ServT ms; _}); _} -> sprintf "service %s {\n%s}\n" id.it (string_of_list string_of_meth "" ms) - | Some {it = ActorD (id, {it=VarT x; _}); _} -> sprintf "service %s : %s\n" id.it x.it - | Some _ -> assert false + kwd ppf "func"; + pp_func ppf (ms,s,t) + | ServT ms -> + pp_open_vbox ppf 2; + str ppf "service {"; + List.iter (fun m -> pp_print_cut ppf (); pp_meth ppf m; str ppf ";") ms; + pp_print_break ppf 0 (-2); + str ppf "}"; + pp_close_box ppf () + | PreT -> assert false); + pp_close_box ppf () +and pp_fields ppf name fs = + if List.length fs > 1 then + pp_open_vbox ppf 2 + else + pp_open_hovbox ppf 2; + str ppf (name ^ " {"); + List.iter (fun f -> pp_print_cut ppf (); pp_field ppf f; str ppf ";") fs; + pp_print_break ppf 0 (-2); + str ppf "}"; + pp_close_box ppf () +and pp_field ppf f = + pp_open_hovbox ppf 1; + (match f.it.label.it with + | Id n -> str ppf (Lib.Uint32.to_string n); kwd ppf ":" + | Named name -> + quote ppf name; + kwd ppf ":" + | Unnamed _ -> ()); + pp_typ ppf f.it.typ; + pp_close_box ppf () + +and pp_func ppf (ms,s,t) = + pp_args ppf s; + kwd ppf " ->"; + pp_args ppf t; + List.iter (fun m -> str ppf (string_of_mode m)) ms +and pp_args ppf fs = + let n = List.length fs in + str ppf "("; + List.iteri (fun i f -> + pp_field ppf f; + if i < n-1 then + kwd ppf ","; + ) fs; + str ppf ")" + +and pp_meth ppf m = + pp_open_hovbox ppf 1; + quote ppf m.it.var.it; + kwd ppf ":"; + (match m.it.meth.it with + | FuncT (ms,s,t) -> pp_func ppf (ms,s,t) + | _ -> pp_typ ppf m.it.meth); + pp_close_box ppf () + +let rec is_linebreak_type t = + match t.it with + | ServT _ -> true + | RecordT fs | VariantT fs -> List.length fs > 1 + | VecT t | OptT t -> is_linebreak_type t + | _ -> false + +let pp_dec ppf d = + pp_open_vbox ppf 1; + (match d.it with + | TypD (id, typ) -> + pp_open_hbox ppf (); + kwd ppf "type"; + kwd ppf id.it; + kwd ppf "="; + pp_close_box ppf (); + if is_linebreak_type typ then + pp_print_cut ppf (); + pp_typ ppf typ + | ImportD (f, fp) -> + str ppf "import \""; + str ppf f; + str ppf "\"" + ); + pp_close_box ppf () + +let pp_actor ppf actor = + (match actor with + | None -> () + | Some {it = ActorD (id, {it=ServT ms; _}); _} -> + pp_open_vbox ppf 2; + pp_open_hbox ppf (); + kwd ppf "service"; + kwd ppf id.it; + str ppf "{"; + pp_close_box ppf (); + List.iter (fun m -> pp_print_cut ppf (); pp_meth ppf m; str ppf ";") ms; + pp_print_break ppf 0 (-2); + str ppf "}"; + pp_close_box ppf () + | Some {it = ActorD (id, {it=VarT x; _}); _} -> + pp_open_hbox ppf (); + kwd ppf "service"; + kwd ppf id.it; + kwd ppf ":"; + str ppf x.it; + pp_close_box ppf () + | _ -> assert false); + pp_print_cut ppf () + +let pp_prog ppf prog = + pp_open_vbox ppf 0; + List.iter (fun d -> + pp_dec ppf d; + str ppf ";"; + pp_print_cut ppf () + ) prog.it.decs; + pp_actor ppf prog.it.actor; + pp_close_box ppf () + +let string_of_typ t = + let buf = Buffer.create 100 in + let ppf = formatter_of_buffer buf in + pp_typ ppf t; + pp_print_flush ppf (); + Buffer.contents buf + let string_of_prog prog = - sprintf "%s%s" (string_of_list string_of_dec "" prog.it.decs) (string_of_actor prog.it.actor) + let buf = Buffer.create 100 in + let ppf = formatter_of_buffer buf in + pp_prog ppf prog; + pp_print_flush ppf (); + Buffer.contents buf diff --git a/src/idllib/compile_js.ml b/src/idllib/compile_js.ml index 1e159436d64..f31c8c1ded4 100644 --- a/src/idllib/compile_js.ml +++ b/src/idllib/compile_js.ml @@ -70,7 +70,7 @@ let str ppf s = pp_print_string ppf s; pp_print_cut ppf () let id ppf s = str ppf s.it; pp_print_cut ppf () let space = pp_print_space let kwd ppf s = str ppf s; space ppf () -let field_name ppf s = str ppf "'"; str ppf s.it; str ppf "'"; pp_print_cut ppf () +let quote_name ppf s = pp_open_hbox ppf (); str ppf "'"; str ppf (Lib.String.lightweight_escaped s); str ppf "'"; pp_close_box ppf (); pp_print_cut ppf () let pp_prim p = match p with @@ -133,12 +133,17 @@ and pp_fields ppf fs = and pp_field ppf tf = pp_open_box ppf 1; - field_name ppf tf.it.name; kwd ppf ":"; pp_typ ppf tf.it.typ; + let f_name = + match tf.it.label.it with + | Id n -> Lib.Uint32.to_string n + | Named name -> name + | Unnamed n -> Lib.Uint32.to_string n + in quote_name ppf f_name; kwd ppf ":"; pp_typ ppf tf.it.typ; pp_close_box ppf () and pp_meth ppf meth = pp_open_box ppf 1; - field_name ppf meth.it.var; + quote_name ppf meth.it.var.it; kwd ppf ":"; pp_typ ppf meth.it.meth; pp_close_box ppf () @@ -170,11 +175,11 @@ let pp_rec ppf x = pp_print_cut ppf () let pp_actor ppf actor recs = - pp_open_hovbox ppf 1; - kwd ppf "const"; - (match actor.it with + match actor.it with | ActorD (x, t) -> let x = ("actor_" ^ x.it) @@ x.at in + pp_open_hovbox ppf 1; + kwd ppf "const"; (match t.it with | ServT tp -> id ppf x; space ppf (); kwd ppf "="; kwd ppf "new"; @@ -189,17 +194,18 @@ let pp_actor ppf actor recs = str ppf var.it; | _ -> assert false ); + pp_close_box ppf (); pp_force_newline ppf (); - kwd ppf "return"; id ppf x; str ppf ";" - ); - pp_close_box ppf () + pp_open_hovbox ppf 0; + kwd ppf "return"; id ppf x; str ppf ";"; + pp_close_box ppf () let pp_header ppf () = - pp_open_vbox ppf 0; - str ppf "export default ({ IDL }) => {"; - pp_close_box ppf () + pp_open_vbox ppf 1; + str ppf "export default ({ IDL }) => {" let pp_footer ppf () = + pp_close_box ppf (); pp_force_newline ppf (); pp_print_string ppf "};" @@ -214,11 +220,9 @@ let pp_prog ppf env prog = if TS.mem e.var recs then {e with is_rec = true} else e) env_list in pp_header ppf (); - pp_open_vbox ppf 0; TS.iter (pp_rec ppf) recs; List.iter (pp_dec ppf) env_list; pp_actor ppf actor recs; - pp_close_box ppf (); pp_footer ppf () let compile (scope : Typing.scope) (prog : Syntax.prog) = diff --git a/src/idllib/parser.mly b/src/idllib/parser.mly index c3f0617c480..e6701f4ed38 100644 --- a/src/idllib/parser.mly +++ b/src/idllib/parser.mly @@ -31,10 +31,9 @@ let prim_typs = ["nat", Nat; "nat8", Nat8; "nat16", Nat16; "nat32", Nat32; "nat6 let is_prim_typs t = List.assoc_opt t prim_typs let func_modes = ["oneway", Oneway; "query", Query] -let get_func_mode m = List.assoc m func_modes +let get_func_mode m = List.assoc_opt m func_modes let hash = IdlHash.idl_hash - let record_fields fs = let open Uint32 in let rec go start fs = @@ -42,7 +41,11 @@ let record_fields fs = | [] -> [] | hd :: tl -> let field = hd start in - let next = succ field.it.id in + let next = + (match field.it.label.it with + | Id n -> succ n + | Named name -> succ (hash name) + | Unnamed n -> succ n) in field :: (go next tl) in go zero fs %} @@ -92,21 +95,21 @@ ref_typ : field_typ : | n=NAT COLON t=data_typ - { { id = Uint32.of_string n; name = n @@ at $loc(n); typ = t } @@ at $sloc } + { { label = Id (Uint32.of_string n) @@ at $loc(n); typ = t } @@ at $sloc } | name=name COLON t=data_typ - { { id = hash name.it; name = name; typ = t } @@ at $sloc } + { { label = Named name.it @@ at $loc(name); typ = t } @@ at $sloc } record_typ : | f=field_typ { fun _ -> f } | t=data_typ - { fun x -> { id = x; name = Uint32.to_string x @@ no_region; typ = t } @@ at $sloc } + { fun x -> { label = Unnamed x @@ no_region; typ = t } @@ at $sloc } variant_typ : | f=field_typ { f } | name=name - { { id = hash name.it; name = name; typ = PrimT Null @@ no_region } @@ at $sloc } + { { label = Named name.it @@ at $loc(name); typ = PrimT Null @@ no_region } @@ at $sloc } | n=NAT - { { id = Uint32.of_string n; name = n @@ at $loc(n); typ = PrimT Null @@ no_region } @@ at $sloc } + { { label = Id (Uint32.of_string n) @@ at $loc(n); typ = PrimT Null @@ no_region } @@ at $sloc } record_typs : | LCURLY fs=seplist(record_typ, SEMICOLON) RCURLY @@ -133,7 +136,10 @@ param_typs : func_mode : | m=id - { get_func_mode m.it @@ at $sloc } + { match get_func_mode m.it with + Some m -> m @@ at $sloc + | None -> $syntaxerror + } func_modes_opt : | (* empty *) { [] } diff --git a/src/idllib/pipeline.ml b/src/idllib/pipeline.ml index 7744d4f63d8..ffe1e3e2684 100644 --- a/src/idllib/pipeline.ml +++ b/src/idllib/pipeline.ml @@ -122,7 +122,7 @@ let initial_stat_env = Typing.empty_scope let check_file file : load_result = load_prog (parse_file file) initial_stat_env let check_prog prog : Typing.scope Diag.result = check_prog initial_stat_env prog - + (* JS Compilation *) type compile_result = Buffer.t Diag.result diff --git a/src/idllib/pipeline.mli b/src/idllib/pipeline.mli index 129f2b08619..4e234a159c8 100644 --- a/src/idllib/pipeline.mli +++ b/src/idllib/pipeline.mli @@ -1,3 +1,3 @@ -val check_file : string -> (Syntax.prog * Typing.scope) Diag.result -val check_prog : Syntax.prog -> Typing.scope Diag.result -val compile_js_file : string -> Buffer.t Diag.result +val check_file : string -> (Syntax.prog * Typing.scope) Diag.result +val check_prog : Syntax.prog -> Typing.scope Diag.result +val compile_js_file : string -> Buffer.t Diag.result diff --git a/src/idllib/syntax.ml b/src/idllib/syntax.ml index 851b3074734..6cec88d7f08 100644 --- a/src/idllib/syntax.ml +++ b/src/idllib/syntax.ml @@ -27,6 +27,9 @@ type prim = type func_mode = func_mode' Source.phrase and func_mode' = Oneway | Query +type field_label = field_label' Source.phrase +and field_label' = Id of Lib.Uint32.t | Named of string | Unnamed of Lib.Uint32.t + type typ = typ' Source.phrase and typ' = | PrimT of prim (* primitive *) @@ -40,7 +43,7 @@ and typ' = | PreT (* pre-type *) and typ_field = typ_field' Source.phrase -and typ_field' = { id : Lib.Uint32.t; name : id; typ : typ } +and typ_field' = { label: field_label; typ : typ } and typ_meth = typ_meth' Source.phrase and typ_meth' = {var : id; meth : typ} diff --git a/src/idllib/typing.ml b/src/idllib/typing.ml index 2c531e2eed4..fca453ed9d3 100644 --- a/src/idllib/typing.ml +++ b/src/idllib/typing.ml @@ -61,7 +61,20 @@ let disjoint_union env at fmt env1 env2 = with Env.Clash k -> error env at fmt k (* Types *) -let compare_field (f1: typ_field) (f2: typ_field) = Lib.Uint32.compare f1.it.id f2.it.id +let hash = IdlHash.idl_hash + +let field_id (f: typ_field) = + match f.it.label.it with + | Id n -> n + | Named name -> hash name + | Unnamed n -> n +let field_name (f: typ_field) = + match f.it.label.it with + | Id n -> Lib.Uint32.to_string n + | Named name -> name + | Unnamed n -> "Unnamed " ^ (Lib.Uint32.to_string n) + +let compare_field (f1: typ_field) (f2: typ_field) = Lib.Uint32.compare (field_id f1) (field_id f2) let compare_meth (m1: typ_meth) (m2: typ_meth) = compare m1.it.var m2.it.var let find_type env id = match Env.find_opt id.it env.typs with @@ -121,13 +134,15 @@ let rec check_typ env t = and check_fields env fs = let _, fields = List.fold_left (fun (fenv, fields) f -> - match FieldEnv.find_opt f.it.id fenv with + let f_id = field_id f in + let f_name = field_name f in + match FieldEnv.find_opt f_id fenv with | Some name' -> - error env f.it.name.at "field name %s hash collision with field %s" f.it.name.it name' + error env f.it.label.at "field name %s hash collision with field %s" f_name name' | None -> let t' = check_typ env f.it.typ in - let f' = {id=f.it.id; name=f.it.name; typ=t'} @@ f.at in - FieldEnv.disjoint_add f.it.id f.it.name.it fenv, f'::fields + let f' = {label=f.it.label; typ=t'} @@ f.at in + FieldEnv.disjoint_add f_id f_name fenv, f'::fields ) (FieldEnv.empty, []) fs in fields diff --git a/src/lib/lib.ml b/src/lib/lib.ml index 0df5cded111..92508667946 100644 --- a/src/lib/lib.ml +++ b/src/lib/lib.ml @@ -99,6 +99,36 @@ struct Some (String.sub s 0 (s_len - suffix_len)) else None + + let lightweight_escaped str = + let n = ref 0 in + for i = 0 to String.length str - 1 do + n := !n + + (match str.[i] with + | '\"' | '\'' | '\\' | '\n' | '\r' | '\b' | '\t' -> 2 + | _ -> 1) + done; + if !n = String.length str then str else begin + let s' = Bytes.create !n in + n := 0; + for i = 0 to String.length str -1 do + begin match str.[i] with + | ('\"' | '\'' | '\\') as c -> + Bytes.set s' !n '\\'; n := !n + 1; Bytes.set s' !n c + | '\n' -> + Bytes.set s' !n '\\'; n := !n + 1; Bytes.set s' !n 'n' + | '\r' -> + Bytes.set s' !n '\\'; n := !n + 1; Bytes.set s' !n 'r' + | '\b' -> + Bytes.set s' !n '\\'; n := !n + 1; Bytes.set s' !n 'b' + | '\t' -> + Bytes.set s' !n '\\'; n := !n + 1; Bytes.set s' !n 't' + | c -> Bytes.set s' !n c + end; + n := !n + 1 + done; + Bytes.unsafe_to_string s' + end end module List = diff --git a/src/lib/lib.mli b/src/lib/lib.mli index 44e3dcdb682..f2b673aacc2 100644 --- a/src/lib/lib.mli +++ b/src/lib/lib.mli @@ -132,4 +132,5 @@ sig val find_from_opt : (char -> bool) -> string -> int -> int option val chop_prefix : string -> string -> string option val chop_suffix : string -> string -> string option + val lightweight_escaped : string -> string end diff --git a/test/as-idl/ok/counter.did.ok b/test/as-idl/ok/counter.did.ok index 034c524ba95..4274e7fac69 100644 --- a/test/as-idl/ok/counter.did.ok +++ b/test/as-idl/ok/counter.did.ok @@ -1,6 +1,7 @@ type Int = int; -type Counter = service { -dec : () -> () oneway; -read : () -> (Int); -}; +type Counter = + service { + "dec": () -> () oneway; + "read": () -> (Int); + }; service c : Counter diff --git a/test/as-idl/ok/inline_result.did.ok b/test/as-idl/ok/inline_result.did.ok index f86cf46f63b..af2f7ed6969 100644 --- a/test/as-idl/ok/inline_result.did.ok +++ b/test/as-idl/ok/inline_result.did.ok @@ -2,6 +2,15 @@ type Text = text; type Nat = nat; type Int = int; service anon_inline_result { -f : (opt Nat) -> (variant {err : Text; ok : Nat}); -g : (variant {err : Text; ok : Nat}) -> (variant {err : record {}; ok : Int}); + "f": (opt Nat) -> (variant { + "err": Text; + "ok": Nat; + }); + "g": (variant { + "err": Text; + "ok": Nat; + }) -> (variant { + "err": record {}; + "ok": Int; + }); } diff --git a/test/as-idl/ok/pa_cars.did.ok b/test/as-idl/ok/pa_cars.did.ok index 7c1167a417a..e5c23a58e4c 100644 --- a/test/as-idl/ok/pa_cars.did.ok +++ b/test/as-idl/ok/pa_cars.did.ok @@ -1,17 +1,40 @@ -type User = record {name : Text}; -type TimeSpan = record {end : Int; start : Int}; +type User = record {"name": Text;}; +type TimeSpan = + record { + "end": Int; + "start": Int; + }; type Text = text; -type Result_1 = opt record {reservationId : Text}; -type PACars = service { -verifyCarInformation : (User, Car) -> (opt func (Location, TimeSpan) -> (Result_1)); -}; +type Result_1 = opt record {"reservationId": Text;}; +type PACars = + service { + "verifyCarInformation": (User, Car) -> + (opt func (Location, TimeSpan) -> (Result_1)); + }; type Nat = nat; -type Location = record {lat : Float; long : Float}; +type Location = + record { + "lat": Float; + "long": Float; + }; type Int = int; type Float = float64; -type DMV = service { -check : (Car) -> (CarInfo); -}; -type CarInfo = record {expires : Nat; isValid : Bool; model : Text; plate : Text; wasStolen : Bool}; -type Car = record {model : Text; plate : Text}; +type DMV = + service { + "check": (Car) -> (CarInfo); + }; +type CarInfo = + record { + "expires": Nat; + "isValid": Bool; + "model": Text; + "plate": Text; + "wasStolen": Bool; + }; +type Car = + record { + "model": Text; + "plate": Text; + }; type Bool = bool; + diff --git a/test/as-idl/ok/recursion.did.ok b/test/as-idl/ok/recursion.did.ok index 92776b6dc59..267c0171831 100644 --- a/test/as-idl/ok/recursion.did.ok +++ b/test/as-idl/ok/recursion.did.ok @@ -1,8 +1,16 @@ type Nat = nat; -type List_2 = record {head : Nat; tail : opt List_2}; -type List_1 = record {head : Int; tail : opt List_1}; +type List_2 = + record { + "head": Nat; + "tail": opt List_2; + }; +type List_1 = + record { + "head": Int; + "tail": opt List_1; + }; type Int = int; service anon_recursion { -f : (Nat) -> (List_2); -g : (Int) -> (List_1); + "f": (Nat) -> (List_2); + "g": (Int) -> (List_1); } diff --git a/test/as-idl/ok/result.did.ok b/test/as-idl/ok/result.did.ok index ecb6c2807a1..154062fb5c7 100644 --- a/test/as-idl/ok/result.did.ok +++ b/test/as-idl/ok/result.did.ok @@ -1,11 +1,31 @@ type Text = text; -type Result_1_2 = variant {err : Text; ok : Nat}; -type Result_1_1 = variant {err : Text; ok : record {}}; -type Result3_1 = variant {err : Result2_1; ok : record {}}; -type Result2_2 = variant {err : Result_1_2; ok : Nat}; -type Result2_1 = variant {err : Result_1_1; ok : record {}}; +type Result_1_2 = + variant { + "err": Text; + "ok": Nat; + }; +type Result_1_1 = + variant { + "err": Text; + "ok": record {}; + }; +type Result3_1 = + variant { + "err": Result2_1; + "ok": record {}; + }; +type Result2_2 = + variant { + "err": Result_1_2; + "ok": Nat; + }; +type Result2_1 = + variant { + "err": Result_1_1; + "ok": record {}; + }; type Nat = nat; service anon_result { -f : (opt Nat) -> (Result_1_2); -g : (Result3_1) -> (Result2_2); + "f": (opt Nat) -> (Result_1_2); + "g": (Result3_1) -> (Result2_2); } diff --git a/test/idl/escape.did b/test/idl/escape.did new file mode 100644 index 00000000000..a811617704e --- /dev/null +++ b/test/idl/escape.did @@ -0,0 +1,5 @@ +type t = record {"'":nat; "\"":nat; "\"'":nat; "\\\n'\"":nat; }; +service E { + "\n'\"''\"\"\r\t": (t) -> (); +} + diff --git a/test/idl/fieldnat.did b/test/idl/fieldnat.did new file mode 100644 index 00000000000..12af354c150 --- /dev/null +++ b/test/idl/fieldnat.did @@ -0,0 +1,5 @@ +service Foo { + foo : (record {2 : int}) -> (); + bar : (record {"2" : int}) -> (); +} + diff --git a/test/idl/missing_semicolon.did b/test/idl/missing_semicolon.did new file mode 100644 index 00000000000..903fa08a587 --- /dev/null +++ b/test/idl/missing_semicolon.did @@ -0,0 +1,5 @@ +service Foo { + foo : (record {2 : int}) -> () + bar : (record {"2" : int}) -> () +} + diff --git a/test/idl/ok/actor.js.ok b/test/idl/ok/actor.js.ok index 36fbe4a2d93..875bc47239b 100644 --- a/test/idl/ok/actor.js.ok +++ b/test/idl/ok/actor.js.ok @@ -1,11 +1,11 @@ export default ({ IDL }) => { -const o = IDL.Rec() -const f = IDL.Func(IDL.Obj({'0': IDL.Int8}), IDL.Obj({'0': IDL.Int8})) -const h = IDL.Func(IDL.Obj({'0': f}), IDL.Obj({'0': f})) -const g = f -o.fill(IDL.Opt(o)) -const actor_g = new IDL.ActorInterface({ - 'f': IDL.Func(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': h})), 'g': f, 'h': g, - 'o': IDL.Func(IDL.Obj({'0': o}), IDL.Obj({'0': o}))}); + const o = IDL.Rec() + const f = IDL.Func(IDL.Obj({'0': IDL.Int8}), IDL.Obj({'0': IDL.Int8})) + const h = IDL.Func(IDL.Obj({'0': f}), IDL.Obj({'0': f})) + const g = f + o.fill(IDL.Opt(o)) + const actor_g = new IDL.ActorInterface({ + 'f': IDL.Func(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': h})), 'g': f, + 'h': g, 'o': IDL.Func(IDL.Obj({'0': o}), IDL.Obj({'0': o}))}); return actor_g; }; diff --git a/test/idl/ok/collision_fields.tc.ok b/test/idl/ok/collision_fields.tc.ok index 9d12b957398..2a469c8fa63 100644 --- a/test/idl/ok/collision_fields.tc.ok +++ b/test/idl/ok/collision_fields.tc.ok @@ -1 +1 @@ -collision_fields.did:3.2-3.3: type error, field name 2 hash collision with field 2 +collision_fields.did:3.2-3.3: type error, field name 2 hash collision with field Unnamed 2 diff --git a/test/idl/ok/cyclic.js.ok b/test/idl/ok/cyclic.js.ok index 6aaa361324b..119fbfd9030 100644 --- a/test/idl/ok/cyclic.js.ok +++ b/test/idl/ok/cyclic.js.ok @@ -1,14 +1,14 @@ export default ({ IDL }) => { -const A = IDL.Rec() -const C = A -const B = IDL.Opt(C) -A.fill(IDL.Opt(B)) -const Z = A -const Y = Z -const X = Y -const actor_S = new IDL.ActorInterface({ - 'f': - IDL.Func(IDL.Obj({'0': A, '1': B, '2': C, '3': X, '4': Y, '5': Z}), - IDL.Obj({}))}); + const A = IDL.Rec() + const C = A + const B = IDL.Opt(C) + A.fill(IDL.Opt(B)) + const Z = A + const Y = Z + const X = Y + const actor_S = new IDL.ActorInterface({ + 'f': + IDL.Func(IDL.Obj({'0': A, '1': B, '2': C, '3': X, '4': Y, '5': Z}), + IDL.Obj({}))}); return actor_S; }; diff --git a/test/idl/ok/diamond.js.ok b/test/idl/ok/diamond.js.ok index 0570db603c6..4dbe0a2d635 100644 --- a/test/idl/ok/diamond.js.ok +++ b/test/idl/ok/diamond.js.ok @@ -1,10 +1,9 @@ export default ({ IDL }) => { -const t = IDL.Nat -const t2 = IDL.Arr(t) -const t3 = IDL.Opt(t) -const t1 = IDL.Obj({'0': t2, '1': t3, '2': t}) -const actor_S = new IDL.ActorInterface({ - 'f': IDL.Func(IDL.Obj({'0': t, '1': t2, '2': t3}), IDL.Obj({'0': t1}))}); - + const t = IDL.Nat + const t2 = IDL.Arr(t) + const t3 = IDL.Opt(t) + const t1 = IDL.Obj({'0': t2, '1': t3, '2': t}) + const actor_S = new IDL.ActorInterface({ + 'f': IDL.Func(IDL.Obj({'0': t, '1': t2, '2': t3}), IDL.Obj({'0': t1}))}); return actor_S; }; diff --git a/test/idl/ok/escape.js.ok b/test/idl/ok/escape.js.ok new file mode 100644 index 00000000000..334209fb0e0 --- /dev/null +++ b/test/idl/ok/escape.js.ok @@ -0,0 +1,8 @@ +export default ({ IDL }) => { + const t = + IDL.Obj({'\"': IDL.Nat, '\'': IDL.Nat, '\"\'': IDL.Nat, '\\\n\'\"': IDL.Nat + }) + const actor_E = new IDL.ActorInterface({ + '\n\'\"\'\'\"\"\r\t': IDL.Func(IDL.Obj({'0': t}), IDL.Obj({}))}); + return actor_E; +}; diff --git a/test/idl/ok/fieldnat.js.ok b/test/idl/ok/fieldnat.js.ok new file mode 100644 index 00000000000..2dd0d31471b --- /dev/null +++ b/test/idl/ok/fieldnat.js.ok @@ -0,0 +1,6 @@ +export default ({ IDL }) => { + const actor_Foo = new IDL.ActorInterface({ + 'foo': IDL.Func(IDL.Obj({'0': IDL.Obj({'2': IDL.Int})}), IDL.Obj({})), + 'bar': IDL.Func(IDL.Obj({'0': IDL.Obj({'2': IDL.Int})}), IDL.Obj({}))}); + return actor_Foo; +}; diff --git a/test/idl/ok/fields.js.ok b/test/idl/ok/fields.js.ok index 00c249c0f3c..3f7599fe745 100644 --- a/test/idl/ok/fields.js.ok +++ b/test/idl/ok/fields.js.ok @@ -1,21 +1,21 @@ export default ({ IDL }) => { -const A = IDL.Obj({'0': IDL.Nat, '1': IDL.Nat, '2': IDL.Nat}) -const B = - IDL.Obj({'0': IDL.Arr(IDL.Nat8), '35': IDL.Arr(IDL.Nat8), '36': IDL.Nat, - '37': IDL.Nat, 'named_files': IDL.None, '3629958706': IDL.Nat, - '3629958707': IDL.Nat}) -const C = - IDL.Variant({'1': IDL.Unit, '2': IDL.Unit, '3': IDL.Unit, '4': IDL.Unit, - '10': IDL.Unit, 'A': IDL.Unit, 'B': IDL.Unit, 'C': IDL.Unit, - 'red': IDL.Unit, 'blue': IDL.Unit, 'reserved': IDL.Unit, 'green': IDL.Unit - }) -const nest_record = - IDL.Obj({'0': IDL.Nat, '1': IDL.Nat, '2': IDL.Nat, - '3': IDL.Obj({'0': IDL.Nat, '1': IDL.Nat, '2': IDL.Nat}), '4': IDL.Nat, - '5': IDL.Nat, '6': IDL.Nat, '7': A, '8': B, '9': C, '10': IDL.Nat}) -const actor_S = new IDL.ActorInterface({ - 'f': - IDL.Func(IDL.Obj({'0': A, '1': B, '2': C, '3': nest_record}), IDL.Obj({})) - }); + const A = IDL.Obj({'0': IDL.Nat, '1': IDL.Nat, '2': IDL.Nat}) + const B = + IDL.Obj({'0': IDL.Arr(IDL.Nat8), '35': IDL.Arr(IDL.Nat8), '36': IDL.Nat, + '37': IDL.Nat, 'named_files': IDL.None, '3629958706': IDL.Nat, + '3629958707': IDL.Nat}) + const C = + IDL.Variant({'1': IDL.Unit, '2': IDL.Unit, '3': IDL.Unit, '4': IDL.Unit, + '10': IDL.Unit, 'A': IDL.Unit, 'B': IDL.Unit, 'C': IDL.Unit, + 'red': IDL.Unit, 'blue': IDL.Unit, 'reserved': IDL.Unit, 'green': IDL.Unit + }) + const nest_record = + IDL.Obj({'0': IDL.Nat, '1': IDL.Nat, '2': IDL.Nat, + '3': IDL.Obj({'0': IDL.Nat, '1': IDL.Nat, '2': IDL.Nat}), '4': IDL.Nat, + '5': IDL.Nat, '6': IDL.Nat, '7': A, '8': B, '9': C, '10': IDL.Nat}) + const actor_S = new IDL.ActorInterface({ + 'f': + IDL.Func(IDL.Obj({'0': A, '1': B, '2': C, '3': nest_record}), IDL.Obj({})) + }); return actor_S; }; diff --git a/test/idl/ok/import.js.ok b/test/idl/ok/import.js.ok index daef8d6b5e0..0f4e9f52bf3 100644 --- a/test/idl/ok/import.js.ok +++ b/test/idl/ok/import.js.ok @@ -1,22 +1,21 @@ export default ({ IDL }) => { -const t = IDL.Arr(IDL.Nat8) -const t1 = t -const UserId = IDL.Nat -const t2 = UserId -const list = IDL.Arr(IDL.Nat) -const RegionId = IDL.Nat -const TruckTypeId = IDL.Nat -const EntId = - IDL.Obj({'region': RegionId, 'user': UserId, 'truckType': TruckTypeId}) -const OpEntId = IDL.Opt(EntId) -const IdErr = IDL.Obj({'idErr': OpEntId}) -const Inventory = IDL.Obj({'produce_id': IDL.Nat, 'quantity': IDL.Nat}) -const actor_S = new IDL.ActorInterface({ - 'f': - IDL.Func(IDL.Obj({'0': t, '1': t1, '2': t2}), - IDL.Obj({'0': list, '1': IdErr})), - 'getInventory': - IDL.Func(IDL.Obj({'producer_id': IDL.Nat}), IDL.Obj({'0': Inventory}))}); - + const t = IDL.Arr(IDL.Nat8) + const t1 = t + const UserId = IDL.Nat + const t2 = UserId + const list = IDL.Arr(IDL.Nat) + const RegionId = IDL.Nat + const TruckTypeId = IDL.Nat + const EntId = + IDL.Obj({'region': RegionId, 'user': UserId, 'truckType': TruckTypeId}) + const OpEntId = IDL.Opt(EntId) + const IdErr = IDL.Obj({'idErr': OpEntId}) + const Inventory = IDL.Obj({'produce_id': IDL.Nat, 'quantity': IDL.Nat}) + const actor_S = new IDL.ActorInterface({ + 'f': + IDL.Func(IDL.Obj({'0': t, '1': t1, '2': t2}), + IDL.Obj({'0': list, '1': IdErr})), + 'getInventory': + IDL.Func(IDL.Obj({'producer_id': IDL.Nat}), IDL.Obj({'0': Inventory}))}); return actor_S; }; diff --git a/test/idl/ok/import1.js.ok b/test/idl/ok/import1.js.ok index 944ff4a8b2b..2bee6bffe15 100644 --- a/test/idl/ok/import1.js.ok +++ b/test/idl/ok/import1.js.ok @@ -1,9 +1,9 @@ export default ({ IDL }) => { -const t = IDL.Arr(IDL.Nat8) -const t1 = t -const UserId = IDL.Nat -const t2 = UserId -const actor_S = new IDL.ActorInterface({ - 'f': IDL.Func(IDL.Obj({'0': t, '1': t1, '2': t2}), IDL.Obj({}))}); + const t = IDL.Arr(IDL.Nat8) + const t1 = t + const UserId = IDL.Nat + const t2 = UserId + const actor_S = new IDL.ActorInterface({ + 'f': IDL.Func(IDL.Obj({'0': t, '1': t1, '2': t2}), IDL.Obj({}))}); return actor_S; }; diff --git a/test/idl/ok/import3.js.ok b/test/idl/ok/import3.js.ok index fbd7f269d06..16299826063 100644 --- a/test/idl/ok/import3.js.ok +++ b/test/idl/ok/import3.js.ok @@ -1,28 +1,28 @@ export default ({ IDL }) => { -const B = IDL.Rec() -const list = IDL.Rec() -const s = IDL.Rec() -const stream = IDL.Rec() -const tree = IDL.Rec() -const t = IDL.Func(IDL.Obj({'server': s}), IDL.Obj({})) -const node = IDL.Obj({'head': IDL.Nat, 'tail': list}) -list.fill(IDL.Opt(node)) -stream.fill( - IDL.Opt( - IDL.Obj({'head': IDL.Nat, - 'next': IDL.Func(IDL.Obj({}), IDL.Obj({'0': stream}))})) - ) -tree.fill( - IDL.Variant({ - 'branch': IDL.Obj({'val': IDL.Int, 'left': tree, 'right': tree}), - 'leaf': IDL.Int})) -const A = B -B.fill(IDL.Opt(A)) -s.fill( - new IDL.ActorInterface({'f': t, - 'g': - IDL.Func(IDL.Obj({'0': list}), IDL.Obj({'2': stream, '1': tree, '0': B})) - })) -const actor_S = s.__typ; + const B = IDL.Rec() + const list = IDL.Rec() + const s = IDL.Rec() + const stream = IDL.Rec() + const tree = IDL.Rec() + const t = IDL.Func(IDL.Obj({'server': s}), IDL.Obj({})) + const node = IDL.Obj({'head': IDL.Nat, 'tail': list}) + list.fill(IDL.Opt(node)) + stream.fill( + IDL.Opt( + IDL.Obj({'head': IDL.Nat, + 'next': IDL.Func(IDL.Obj({}), IDL.Obj({'0': stream}))})) + ) + tree.fill( + IDL.Variant({ + 'branch': IDL.Obj({'val': IDL.Int, 'left': tree, 'right': tree}), + 'leaf': IDL.Int})) + const A = B + B.fill(IDL.Opt(A)) + s.fill( + new IDL.ActorInterface({'f': t, + 'g': + IDL.Func(IDL.Obj({'0': list}), IDL.Obj({'2': stream, '1': tree, '0': B})) + })) + const actor_S = s.__typ; return actor_S; }; diff --git a/test/idl/ok/integer.js.ok b/test/idl/ok/integer.js.ok index 970e4d46cb8..87da2b1e380 100644 --- a/test/idl/ok/integer.js.ok +++ b/test/idl/ok/integer.js.ok @@ -1,7 +1,7 @@ export default ({ IDL }) => { -const actor_num = new IDL.ActorInterface({ - 'f': IDL.Func(IDL.Obj({'0': IDL.Nat8}), IDL.Obj({'0': IDL.Int16})), - 'g': IDL.Func(IDL.Obj({'0': IDL.Nat64}), IDL.Obj({'0': IDL.Int64})), - 'h': IDL.Func(IDL.Obj({'0': IDL.Int8}), IDL.Obj({'0': IDL.Nat}))}); + const actor_num = new IDL.ActorInterface({ + 'f': IDL.Func(IDL.Obj({'0': IDL.Nat8}), IDL.Obj({'0': IDL.Int16})), + 'g': IDL.Func(IDL.Obj({'0': IDL.Nat64}), IDL.Obj({'0': IDL.Int64})), + 'h': IDL.Func(IDL.Obj({'0': IDL.Int8}), IDL.Obj({'0': IDL.Nat}))}); return actor_num; }; diff --git a/test/idl/ok/missing_semicolon.tc.ok b/test/idl/ok/missing_semicolon.tc.ok new file mode 100644 index 00000000000..81d455243a3 --- /dev/null +++ b/test/idl/ok/missing_semicolon.tc.ok @@ -0,0 +1 @@ +missing_semicolon.did:3.7-3.8: syntax error, unexpected token diff --git a/test/idl/ok/px.js.ok b/test/idl/ok/px.js.ok index 25173a75769..bec47c4fb9b 100644 --- a/test/idl/ok/px.js.ok +++ b/test/idl/ok/px.js.ok @@ -1,20 +1,20 @@ export default ({ IDL }) => { -const UserId = IDL.Nat -const RegionId = IDL.Nat -const ProducerId = IDL.Nat -const UserInfo = - IDL.Obj({'id': UserId, 'region': RegionId, 'user_name': IDL.Text, - 'public_key': IDL.Text, 'description': IDL.Text, - 'produceId': IDL.Opt(ProducerId)}) -const Inventory = IDL.Obj({'produce_id': IDL.Nat, 'quantity': IDL.Nat}) -const TruckTypeId = IDL.Nat -const EntId = - IDL.Obj({'region': RegionId, 'user': UserId, 'truckType': TruckTypeId}) -const OpEntId = IDL.Opt(EntId) -const IdErr = IDL.Obj({'idErr': OpEntId}) -const actor_ProduceExchange = new IDL.ActorInterface({ - 'getInventory': - IDL.Func(IDL.Obj({'producer_id': IDL.Nat, '3667444713': UserInfo}), - IDL.Obj({'0': Inventory, '1': IdErr}))}); + const UserId = IDL.Nat + const RegionId = IDL.Nat + const ProducerId = IDL.Nat + const UserInfo = + IDL.Obj({'id': UserId, 'region': RegionId, 'user_name': IDL.Text, + 'public_key': IDL.Text, 'description': IDL.Text, + 'produceId': IDL.Opt(ProducerId)}) + const Inventory = IDL.Obj({'produce_id': IDL.Nat, 'quantity': IDL.Nat}) + const TruckTypeId = IDL.Nat + const EntId = + IDL.Obj({'region': RegionId, 'user': UserId, 'truckType': TruckTypeId}) + const OpEntId = IDL.Opt(EntId) + const IdErr = IDL.Obj({'idErr': OpEntId}) + const actor_ProduceExchange = new IDL.ActorInterface({ + 'getInventory': + IDL.Func(IDL.Obj({'producer_id': IDL.Nat, '3667444713': UserInfo}), + IDL.Obj({'0': Inventory, '1': IdErr}))}); return actor_ProduceExchange; }; diff --git a/test/idl/ok/recursion.js.ok b/test/idl/ok/recursion.js.ok index 5d828a96773..9c0f918d693 100644 --- a/test/idl/ok/recursion.js.ok +++ b/test/idl/ok/recursion.js.ok @@ -1,28 +1,28 @@ export default ({ IDL }) => { -const B = IDL.Rec() -const list = IDL.Rec() -const s = IDL.Rec() -const stream = IDL.Rec() -const tree = IDL.Rec() -const t = IDL.Func(IDL.Obj({'server': s}), IDL.Obj({})) -const node = IDL.Obj({'head': IDL.Nat, 'tail': list}) -list.fill(IDL.Opt(node)) -stream.fill( - IDL.Opt( - IDL.Obj({'head': IDL.Nat, - 'next': IDL.Func(IDL.Obj({}), IDL.Obj({'0': stream}))})) - ) -tree.fill( - IDL.Variant({ - 'branch': IDL.Obj({'val': IDL.Int, 'left': tree, 'right': tree}), - 'leaf': IDL.Int})) -const A = B -B.fill(IDL.Opt(A)) -s.fill( - new IDL.ActorInterface({'f': t, - 'g': - IDL.Func(IDL.Obj({'0': list}), IDL.Obj({'2': stream, '1': tree, '0': B})) - })) -const actor_A = s.__typ; + const B = IDL.Rec() + const list = IDL.Rec() + const s = IDL.Rec() + const stream = IDL.Rec() + const tree = IDL.Rec() + const t = IDL.Func(IDL.Obj({'server': s}), IDL.Obj({})) + const node = IDL.Obj({'head': IDL.Nat, 'tail': list}) + list.fill(IDL.Opt(node)) + stream.fill( + IDL.Opt( + IDL.Obj({'head': IDL.Nat, + 'next': IDL.Func(IDL.Obj({}), IDL.Obj({'0': stream}))})) + ) + tree.fill( + IDL.Variant({ + 'branch': IDL.Obj({'val': IDL.Int, 'left': tree, 'right': tree}), + 'leaf': IDL.Int})) + const A = B + B.fill(IDL.Opt(A)) + s.fill( + new IDL.ActorInterface({'f': t, + 'g': + IDL.Func(IDL.Obj({'0': list}), IDL.Obj({'2': stream, '1': tree, '0': B})) + })) + const actor_A = s.__typ; return actor_A; }; diff --git a/test/idl/ok/test.js.ok b/test/idl/ok/test.js.ok index 178c3c7ff66..37feb3c96ad 100644 --- a/test/idl/ok/test.js.ok +++ b/test/idl/ok/test.js.ok @@ -1,24 +1,24 @@ export default ({ IDL }) => { -const my_type = IDL.Nat -const B = my_type -const message = IDL.Obj({'25': B, '26': IDL.None, 'name': IDL.Text}) -const broker = - new IDL.ActorInterface({ - 'find': - IDL.Func(IDL.Obj({'name': IDL.Text}), - IDL.Obj({ - '0': - new IDL.ActorInterface({'up': IDL.Func(IDL.Obj({}), IDL.Obj({})), - 'current': IDL.Func(IDL.Obj({}), IDL.Obj({'0': IDL.Nat}))}) - })) - }) -const actor_server = new IDL.ActorInterface({ - 'addUser': - IDL.Func(IDL.Obj({'name': IDL.Text, 'age': IDL.Nat8}), - IDL.Obj({'id': IDL.Nat64})), - 'userName': IDL.Func(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({'0': IDL.Text})), - 'userAge': IDL.Func(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({'0': IDL.Nat8})), - 'deleteUser': IDL.Func(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({})), - 'f': IDL.Func(IDL.Obj({'0': message}), IDL.Obj({'0': broker}))}); + const my_type = IDL.Nat + const B = my_type + const message = IDL.Obj({'25': B, '26': IDL.None, 'name': IDL.Text}) + const broker = + new IDL.ActorInterface({ + 'find': + IDL.Func(IDL.Obj({'name': IDL.Text}), + IDL.Obj({ + '0': + new IDL.ActorInterface({'up': IDL.Func(IDL.Obj({}), IDL.Obj({})), + 'current': IDL.Func(IDL.Obj({}), IDL.Obj({'0': IDL.Nat}))}) + })) + }) + const actor_server = new IDL.ActorInterface({ + 'addUser': + IDL.Func(IDL.Obj({'name': IDL.Text, 'age': IDL.Nat8}), + IDL.Obj({'id': IDL.Nat64})), + 'userName': IDL.Func(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({'0': IDL.Text})), + 'userAge': IDL.Func(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({'0': IDL.Nat8})), + 'deleteUser': IDL.Func(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({})), + 'f': IDL.Func(IDL.Obj({'0': message}), IDL.Obj({'0': broker}))}); return actor_server; }; diff --git a/test/idl/ok/unicode.js.ok b/test/idl/ok/unicode.js.ok index 8c6ac0b1ec6..55a1fa71b81 100644 --- a/test/idl/ok/unicode.js.ok +++ b/test/idl/ok/unicode.js.ok @@ -1,14 +1,14 @@ export default ({ IDL }) => { -const A = - IDL.Obj({'': IDL.Nat, '📦🍦': IDL.Nat, '字段名': IDL.Nat, - '字 段 名2': IDL.Nat}) -const B = - IDL.Variant({'': IDL.Unit, '空的': IDL.Unit, ' 空的 ': IDL.Unit, - '1⃣️2⃣️3⃣️': IDL.Unit}) -const actor_C = new IDL.ActorInterface({ - '函数名': IDL.Func(IDL.Obj({'0': A}), IDL.Obj({'0': B})), - '': IDL.Func(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': IDL.Nat})), - '👀': IDL.Func(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': IDL.Nat})), - '✈️ 🚗 ⛱️ ': IDL.Func(IDL.Obj({}), IDL.Obj({}))}); + const A = + IDL.Obj({'': IDL.Nat, '📦🍦': IDL.Nat, '字段名': IDL.Nat, + '字 段 名2': IDL.Nat}) + const B = + IDL.Variant({'': IDL.Unit, '空的': IDL.Unit, ' 空的 ': IDL.Unit, + '1⃣️2⃣️3⃣️': IDL.Unit}) + const actor_C = new IDL.ActorInterface({ + '函数名': IDL.Func(IDL.Obj({'0': A}), IDL.Obj({'0': B})), + '': IDL.Func(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': IDL.Nat})), + '👀': IDL.Func(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': IDL.Nat})), + '✈️ 🚗 ⛱️ ': IDL.Func(IDL.Obj({}), IDL.Obj({}))}); return actor_C; }; diff --git a/test/run.sh b/test/run.sh index edab391f9ae..5ebbb60d20d 100755 --- a/test/run.sh +++ b/test/run.sh @@ -264,6 +264,12 @@ do if [ "$tc_succeeded" -eq 0 ]; then + $ECHO -n " [pp]" + $DIDC --pp $base.did > $out/$base.pp.did + sed -i 's/import "/import "..\//g' $out/$base.pp.did + $DIDC --check $out/$base.pp.did > $out/$base.pp.tc 2>&1 + diff_files="$diff_files $base.pp.tc" + $ECHO -n " [js]" $DIDC --js $base.did -o $out/$base.js >& $out/$base.js.out normalize $out/$base.js From 161bc355c9596e2e5c42cf736df2a9d6c8a0e5f9 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Thu, 17 Oct 2019 08:38:49 +0200 Subject: [PATCH 0461/1176] Avoid grammar conflicts (#767) --- design/IDL.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/design/IDL.md b/design/IDL.md index e44a20127d9..201f06d481f 100644 --- a/design/IDL.md +++ b/design/IDL.md @@ -1085,6 +1085,10 @@ The types of these values are assumed to be known from context, so the syntax do ``` ::= | | | + | ( ) + + ::= + | | : ::= @@ -1095,17 +1099,17 @@ The types of these values are assumed to be known from context, so the syntax do ::= | opt - | vec { ;* } + | vec { ;* } | record { ;* } | variant { } - ::= = + ::= = ::= | service (canister URI) | func . (canister URI and message name) - ::= ( ,* ) + ::= ( ,* ) ``` From 8112ae0b34aafa304584c6445d42ba9306d58faf Mon Sep 17 00:00:00 2001 From: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> Date: Thu, 17 Oct 2019 12:12:21 +0200 Subject: [PATCH 0462/1176] git ignores the deser binary (#769) --- src/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/src/.gitignore b/src/.gitignore index b852156ba6a..e9564d5cf40 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -3,6 +3,7 @@ /as-ld /as-id /as-ide +/deser /asc.js /didc From 208ac9e8ca69ffffa1e796801a480eab86f4ddbc Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 17 Oct 2019 12:41:29 +0200 Subject: [PATCH 0463/1176] Re-enable use of `memory.grow` on `drun` (#694) also use a `drun` config file to set absurd gas limits. --- src/codegen/compile.ml | 5 +---- test/drun-wrapper.sh | 5 ++++- test/drun.toml | 4 ++++ test/run-drun/large-array.as | 3 +++ test/run-drun/ok/large-array.drun-run.ok | 1 + 5 files changed, 13 insertions(+), 5 deletions(-) create mode 100644 test/drun.toml create mode 100644 test/run-drun/large-array.as create mode 100644 test/run-drun/ok/large-array.drun-run.ok diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 6613346ee82..6d8b63bc9e5 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -719,10 +719,7 @@ module Heap = struct (* Page allocation. Ensures that the memory up to the given unskewed pointer is allocated. *) let grow_memory env = - (* No growing of memory on drun yet *) - if E.mode env = Flags.ICMode - then G.i Drop - else Func.share_code1 env "grow_memory" ("ptr", I32Type) [] (fun env get_ptr -> + Func.share_code1 env "grow_memory" ("ptr", I32Type) [] (fun env get_ptr -> let (set_pages_needed, get_pages_needed) = new_local env "pages_needed" in get_ptr ^^ compile_divU_const page_size ^^ compile_add_const 1l ^^ diff --git a/test/drun-wrapper.sh b/test/drun-wrapper.sh index 03e1c1f036a..167723a32d9 100755 --- a/test/drun-wrapper.sh +++ b/test/drun-wrapper.sh @@ -1,6 +1,8 @@ #!/usr/bin/env bash DRUN=${DRUN:-drun} +CONFIG=$(realpath $(dirname $0)/drun.toml) + if [ -z "$1" ] @@ -11,4 +13,5 @@ fi export LANG=C -( if [ -n "$2" ]; then grep '^//CALL ' $2 | cut -c8-; fi;) | $DRUN $1 /dev/stdin +( if [ -n "$2" ]; then grep '^//CALL ' $2 | cut -c8-; fi;) | + $DRUN -c "$CONFIG" $1 /dev/stdin diff --git a/test/drun.toml b/test/drun.toml new file mode 100644 index 00000000000..ba938f471e8 --- /dev/null +++ b/test/drun.toml @@ -0,0 +1,4 @@ +[application] +scheduler_cores = 1 +round_gas_max = 10_000_000_000_000 +exec_gas = 1_000_000_000_000 diff --git a/test/run-drun/large-array.as b/test/run-drun/large-array.as new file mode 100644 index 00000000000..21b4ac03b0b --- /dev/null +++ b/test/run-drun/large-array.as @@ -0,0 +1,3 @@ +// Should allocate 1G +ignore(Array_init<()>(1024*1024*1024/4, ())); + diff --git a/test/run-drun/ok/large-array.drun-run.ok b/test/run-drun/ok/large-array.drun-run.ok new file mode 100644 index 00000000000..43d7af40394 --- /dev/null +++ b/test/run-drun/ok/large-array.drun-run.ok @@ -0,0 +1 @@ +ingress(0) System From c095ffff487f065e5811013dd0fe8ea5eba979ce Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 17 Oct 2019 21:08:19 +0200 Subject: [PATCH 0464/1176] Implement AS-IDL field escaping (#743) * Implement AS-IDL field escaping and use it in the backend. * Add comment to lexer about adding keywords --- src/as_frontend/lexer.mll | 4 + src/as_idl/as_to_idl.ml | 17 +-- src/codegen/compile.ml | 2 +- src/idllib/escape.ml | 103 ++++++++++++++++++ src/idllib/escape.mli | 5 + test/run-drun/idl-field-escape.as | 27 +++++ test/run-drun/ok/idl-field-escape.drun-run.ok | 5 + 7 files changed, 147 insertions(+), 16 deletions(-) create mode 100644 src/idllib/escape.ml create mode 100644 src/idllib/escape.mli create mode 100644 test/run-drun/idl-field-escape.as create mode 100644 test/run-drun/ok/idl-field-escape.drun-run.ok diff --git a/src/as_frontend/lexer.mll b/src/as_frontend/lexer.mll index 3a4998ecff1..65947ba480c 100644 --- a/src/as_frontend/lexer.mll +++ b/src/as_frontend/lexer.mll @@ -184,6 +184,10 @@ rule token mode = parse | '"'character*'\\'_ { error_nest (Lexing.lexeme_end_p lexbuf) lexbuf "illegal escape" } + (* If you add keywords, please also update + - src/idllib/escape.ml + - emacs/actorscript-mode.el + *) | "actor" { ACTOR } | "and" { AND } | "async" { ASYNC } diff --git a/src/as_idl/as_to_idl.ml b/src/as_idl/as_to_idl.ml index f22ef8b4ff2..e268e5ca6a4 100644 --- a/src/as_idl/as_to_idl.ml +++ b/src/as_idl/as_to_idl.ml @@ -5,8 +5,6 @@ open Printf module E = As_def.Syntax module I = Idllib.Syntax -type label = Nat of Lib.Uint32.t | Id of string - let env = ref Env.empty (* For monomorphization *) let stamp = ref Env.empty @@ -38,19 +36,6 @@ let string_of_con vs c = in Printf.sprintf "%s_%d" (normalize name) n | _ -> assert false -let unescape lab : label = - let lab = normalize lab in - let len = String.length lab in - try if lab.[len-1] = '_' then begin - if lab.[0] = '_' then - Nat (Lib.Uint32.of_string lab) - else Id (String.sub lab 0 (len-1)) - end else Id lab - with _ -> - if len >= 2 && lab.[len-1] = '_' - then Id (String.sub lab 0 (len-1)) - else Id lab - let prim p = match p with | Null -> I.Null @@ -126,6 +111,7 @@ let rec typ vs t = | Pre -> assert false ) @@ no_region and field vs {lab; typ=t} = + let open Idllib.Escape in match unescape lab with | Nat nat -> I.{label = I.Id nat @@ no_region; typ = typ vs t} @@ no_region @@ -144,6 +130,7 @@ and meths vs fs = list | _ -> let meth = + let open Idllib.Escape in match unescape f.lab with | Nat nat -> I.{var = Lib.Uint32.to_string nat @@ no_region; diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 6d8b63bc9e5..7f3500d0144 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -3414,7 +3414,7 @@ module Serialization = struct let sort_by_hash fs = List.sort (fun (h1,_) (h2,_) -> Lib.Uint32.compare h1 h2) - (List.map (fun f -> (Idllib.IdlHash.idl_hash f.Type.lab, f)) fs) + (List.map (fun f -> (Idllib.Escape.unescape_hash f.Type.lab, f)) fs) (* The IDL serialization prefaces the data with a type description. We can statically create the type description in Ocaml code, diff --git a/src/idllib/escape.ml b/src/idllib/escape.ml new file mode 100644 index 00000000000..29b757c8067 --- /dev/null +++ b/src/idllib/escape.ml @@ -0,0 +1,103 @@ +(* +This module implements the field name mapping from AS to IDL +and back. + +(It could live in as_idl/, but as_idl depends on as_def/, codegen/ needs this +encoding, but codegen/ should not depend on as_def/.) +*) + +(* Utilities (cf. lexer.mll) *) + +let is_underscore c = c = '_' +let is_letter c = ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') +let is_digit c = '0' <= c && c <= '9' + +let is_valid_as_id str = match Lib.String.explode str with + | c::cs -> + (is_underscore c || is_letter c) && + List.for_all (fun c -> is_underscore c || is_letter c || is_digit c) cs + | _ -> false + +let ends_with_underscore str = Lib.String.chop_suffix "_" str <> None + +let is_keyword = function + | "actor" + | "and" + | "async" + | "assert" + | "await" + | "break" + | "case" + | "catch" + | "class" + | "continue" + | "debug" + | "else" + | "false" + | "for" + | "func" + | "if" + | "in" + | "import" + | "module" + | "not" + | "null" + | "object" + | "or" + | "label" + | "let" + | "loop" + | "private" + | "public" + | "return" + | "shared" + | "try" + | "throw" + | "debug_show" + | "query" + | "switch" + | "true" + | "type" + | "var" + | "while" + -> true + | _ + -> false + +(* Escaping (used for IDL → AS) *) + +let escape_num h = Printf.sprintf "_%s_" (Lib.Uint32.to_string h) + +let escape str = + if is_keyword str then str ^ "_" else + if is_valid_as_id str + then if ends_with_underscore str then str ^ "_" else str + else escape_num (IdlHash.idl_hash str) + +(* Unescaping (used for AS → IDL) *) + +let is_escaped_num str = + match Lib.String.chop_prefix "_" str with + | Some str -> + begin match Lib.String.chop_suffix "_" str with + | Some str + when String.length str > 0 && + List.for_all is_digit (Lib.String.explode str) + -> Some (Lib.Uint32.of_string str) + | _ -> None + end + | _ -> None + +(* This (or a type like this) could move into the IDL AST *) +type label = Nat of Lib.Uint32.t | Id of string + +let unescape str = + match is_escaped_num str with + | Some h -> Nat h + | _ -> match Lib.String.chop_suffix "_" str with + | Some str' -> Id str' + | _ -> Id str + +let unescape_hash str = match unescape str with + | Nat h -> h + | Id s -> IdlHash.idl_hash s diff --git a/src/idllib/escape.mli b/src/idllib/escape.mli new file mode 100644 index 00000000000..61001b6bf46 --- /dev/null +++ b/src/idllib/escape.mli @@ -0,0 +1,5 @@ +(* This (or a type like this) could move into the IDL AST *) +type label = Nat of Lib.Uint32.t | Id of string +val escape : string -> string +val unescape : string -> label +val unescape_hash : string -> Lib.Uint32.t diff --git a/test/run-drun/idl-field-escape.as b/test/run-drun/idl-field-escape.as new file mode 100644 index 00000000000..f84ca1556ec --- /dev/null +++ b/test/run-drun/idl-field-escape.as @@ -0,0 +1,27 @@ +// This test checks that the IDL encoder/decode implements +// the field escape logic +actor { + type R = { + _0_ : Int; + _1_ : Nat; + async_ : Text + }; + + public func out() : async R { + { _0_ = 0xFFFF; + _1_ = 0x1000; + async_ = "XXX" + } + }; + + public func foo1() : async {foo_ : ()} { { foo_ = () } }; + public func foo2() : async {foo : ()} { { foo = () } }; + + public func input(r : R) : async () { + }; +} + +//CALL ingress foo1 0x4449444C0000 +//CALL ingress foo2 0x4449444C0000 +//CALL ingress out 0x4449444C0000 +//CALL ingress input 0x4449444c016c03007c017dbcfef7b102710100ffff03802003585858 diff --git a/test/run-drun/ok/idl-field-escape.drun-run.ok b/test/run-drun/ok/idl-field-escape.drun-run.ok new file mode 100644 index 00000000000..2d425b83ef4 --- /dev/null +++ b/test/run-drun/ok/idl-field-escape.drun-run.ok @@ -0,0 +1,5 @@ +ingress(0) System +ingress(1) Completed: Canister: Payload: 0x4449444c026c01868eb702016c000100 +ingress(2) Completed: Canister: Payload: 0x4449444c026c01868eb702016c000100 +ingress(3) Completed: Canister: Payload: 0x4449444c016c03007c017dbcfef7b102710100ffff03802003585858 +ingress(4) Completed: Canister: Payload: 0x4449444c0000 From fd74c9b5ce530fb4831a43d65b997521594c6c7b Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 18 Oct 2019 16:31:37 +0200 Subject: [PATCH 0465/1176] README: Link to docs (#771) --- README.md | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 6feea42daa8..6a965d9aa69 100644 --- a/README.md +++ b/README.md @@ -4,17 +4,12 @@ A simple language for writing Dfinity actors. ## User Documentation & Samples -Overview slides [here](guide/as-slides.md). - -Draft (incomplete) manual [here](guide/guide.md). - -Prelude [here](src/prelude/prelude.ml). - -Beginnings of standard library [here](stdlib). - -Small samples [here](samples). - -Produce Exchange [here](stdlib/examples/produce-exchange). +* [Overview slides](https://hydra.dfinity.systems/job/dfinity-ci-build/actorscript/users-guide/latest/download/1/as-slides.html) ([sources](guide/as-slides.md)). +* [Draft (incomplete) manual](guide/guide.md). +* [Prelude](src/prelude/prelude.ml). +* Beginnings of [standard library](stdlib). +* [Small samples](samples). +* [Produce Exchange](stdlib/examples/produce-exchange). ## Introduction From a04725019b81efbf757c88379b436079a7158108 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Sun, 20 Oct 2019 07:59:55 +0200 Subject: [PATCH 0466/1176] nix-shell: do not depend on `deser` (#772) as that is something you want to build _inside_ the nix shell (just like `asc`, `didc` etc.) --- default.nix | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/default.nix b/default.nix index 6aa2d331adb..1ea66d39381 100644 --- a/default.nix +++ b/default.nix @@ -566,19 +566,21 @@ rec { # Since building asc, and testing it, are two different derivations in we # have to create a fake derivation for `nix-shell` that commons up the # build dependencies of the two to provide a build environment that offers - # both. + # both, while not actually building `asc` # - buildInputs = nixpkgs.lib.lists.unique (builtins.filter (i: i != asc && i != didc) ( - asc-bin.buildInputs ++ - js.buildInputs ++ - rts.buildInputs ++ - didc.buildInputs ++ - deser.buildInputs ++ - tests.buildInputs ++ - users-guide.buildInputs ++ - [ nixpkgs.ncurses nixpkgs.ocamlPackages.merlin ] - )); + buildInputs = + let dont_build = [ asc didc deser ]; in + nixpkgs.lib.lists.unique (builtins.filter (i: !(builtins.elem i dont_build)) ( + asc-bin.buildInputs ++ + js.buildInputs ++ + rts.buildInputs ++ + didc.buildInputs ++ + deser.buildInputs ++ + tests.buildInputs ++ + users-guide.buildInputs ++ + [ nixpkgs.ncurses nixpkgs.ocamlPackages.merlin ] + )); shellHook = llvmEnv; ESM=esm; From e3154685d5f9bac3088707d1e59ee45eb73ba478 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Sun, 20 Oct 2019 18:34:00 +0100 Subject: [PATCH 0467/1176] Claudio/platform checks ACT-144 (#735) * remove noisy test throw.as * make type checker reject first-class async (to fail early on incompatible tests) * reject freestanding async blocks; thus crippling many tests: * implement platform specific checks; modify run.sh to pass consistent compile_mode flags; fix one test in repl * fix stdlib/Makefile to pass -ancient-system-api to PX tests * move flag test into new error_in function * rule out shared actor and shared functions from T.shared in ICMode * forgot to add code changes * removed warning * update test file * fix * Update src/as_frontend/typing.ml Co-Authored-By: Joachim Breitner * update test result * Update src/as_frontend/typing.ml Co-Authored-By: Andreas Rossberg * Update src/as_frontend/typing.ml Co-Authored-By: Andreas Rossberg * Update src/as_frontend/typing.ml Co-Authored-By: Andreas Rossberg * Update src/as_frontend/typing.ml Co-Authored-By: Andreas Rossberg * Update src/as_frontend/typing.ml Co-Authored-By: Andreas Rossberg * really update test output * preserve in_await, in_shared of env when switching from checking to inference * rename is_shared_function -> is_shared_fun; simplify errors; nits * distinguish temporary and indefinite platform restrictions * reject actor classes in ICMode * rule out shared function defs that aren't public actor fields * reject non-toplevel actors in ICMode * update test * reject multiple actors in program * add disabled oneway checks * update tests * remove stateful actor counting; add pre-compilation check for multiple actors * refactor, swapping args * add negative test for local async function * Update src/as_frontend/typing.ml Co-Authored-By: Andreas Rossberg * Update src/as_frontend/typing.ml Co-Authored-By: Andreas Rossberg * Update src/as_frontend/typing.ml Co-Authored-By: Andreas Rossberg * Update src/as_frontend/typing.ml Co-Authored-By: Andreas Rossberg * Update src/as_types/type.ml Co-Authored-By: Andreas Rossberg * Update src/as_frontend/typing.ml Co-Authored-By: Andreas Rossberg * Update src/as_frontend/typing.ml Co-Authored-By: Andreas Rossberg * Update src/as_frontend/typing.ml Co-Authored-By: Andreas Rossberg * less advertising in error messages * less advertising in error messages * better errors for non-shared types * Update src/as_frontend/typing.ml Co-Authored-By: Andreas Rossberg * insert line-break * trivial change to tigger build --- README.md | 2 +- src/as_frontend/dune | 3 +- src/as_frontend/typing.ml | 164 +++++++++++++++--- src/as_frontend/typing.mli | 1 + src/as_types/dune | 2 +- src/as_types/type.ml | 51 +++++- src/as_types/type.mli | 2 + src/ir_def/check_ir.ml | 13 +- src/languageServer/languageServer.ml | 4 +- src/pipeline/pipeline.ml | 7 +- stdlib/Makefile | 10 +- .../produce-exchange/test/profileLoadQuery.as | 2 +- test/fail/ok/issue103.tc.ok | 16 ++ test/repl/type-lub-repl.sh | 2 +- test/run-drun/multiple-actors.as | 7 + test/run-drun/ok/idl-func.drun-run.ok | 3 - test/run-drun/ok/idl-func.tc.ok | 8 + .../ok/multiple-actors.wasm.stderr.ok | 4 + test/run-drun/ok/unsupported.tc.ok | 54 ++++++ test/run-drun/unsupported.as | 76 ++++++++ test/run.sh | 8 +- 21 files changed, 379 insertions(+), 60 deletions(-) create mode 100644 test/run-drun/multiple-actors.as delete mode 100644 test/run-drun/ok/idl-func.drun-run.ok create mode 100644 test/run-drun/ok/idl-func.tc.ok create mode 100644 test/run-drun/ok/multiple-actors.wasm.stderr.ok create mode 100644 test/run-drun/ok/unsupported.tc.ok create mode 100644 test/run-drun/unsupported.as diff --git a/README.md b/README.md index 6a965d9aa69..712146f6b9b 100644 --- a/README.md +++ b/README.md @@ -263,7 +263,7 @@ See [here](design/Syntax.html). ## Semantics -TODO... +TODO ... ## Implementation diff --git a/src/as_frontend/dune b/src/as_frontend/dune index a4e2970b0b3..4282935f210 100644 --- a/src/as_frontend/dune +++ b/src/as_frontend/dune @@ -1,6 +1,6 @@ (library (name as_frontend) - (libraries lib lang_utils as_def as_types as_values) + (libraries lib lang_utils as_config as_def as_types as_values) ) (menhir (modules parser) @@ -8,3 +8,4 @@ (infer false) ) (ocamllex lexer) + diff --git a/src/as_frontend/typing.ml b/src/as_frontend/typing.ml index 4c0aefa9046..678e233fc53 100644 --- a/src/as_frontend/typing.ml +++ b/src/as_frontend/typing.ml @@ -1,6 +1,7 @@ open As_def open As_types open As_values +module Flags = As_config.Flags open Syntax open Source @@ -23,6 +24,10 @@ type env = labs : lab_env; rets : ret_env; async : bool; + in_actor : bool; + in_await : bool; + in_shared : bool; + in_prog : bool; pre : bool; msgs : Diag.msg_store; } @@ -36,6 +41,10 @@ let env_of_scope msgs scope = labs = T.Env.empty; rets = None; async = false; + in_await = false; + in_shared = false; + in_actor = false; + in_prog = true; pre = false; msgs; } @@ -64,6 +73,26 @@ let local_error env at fmt = let warn env at fmt = Printf.ksprintf (fun s -> Diag.add_msg env.msgs (type_warning at s)) fmt +let flag_of_compile_mode mode = + match mode with + | Flags.ICMode -> "" + | Flags.WasmMode -> " and flag -no-system-api" + | Flags.AncientMode -> " and flag -ancient-system-api" + +let compile_mode_error mode env at fmt = + Printf.ksprintf + (fun s -> + let s = + Printf.sprintf "%s\n (This is a limitation of the current version%s.)" + s + (flag_of_compile_mode mode) + in + Diag.add_msg env.msgs (type_error at s); raise Recover) fmt + +let error_in modes env at fmt = + let mode = !Flags.compile_mode in + if List.mem mode modes then + compile_mode_error mode env at fmt (* Context extension *) @@ -163,6 +192,23 @@ and check_typ_path' env path : T.con = error env id.at "type field %s does not exist in type\n %s" id.it (T.string_of_typ_expand (T.Obj (s, fs))) +let error_shared env t at fmt = + match T.find_unshared t with + | None -> error env at fmt + | Some t1 -> + let s = Printf.sprintf "\ntype\n %s\nis or contains non-shared type\n %s" + (T.string_of_typ_expand t) (T.string_of_typ_expand t1) in + Printf.ksprintf + (fun s1 -> + Diag.add_msg env.msgs (type_error at (s1^s)); + match t1 with + | T.Obj (T.Actor, _) -> + error_in [Flags.ICMode] env at "actor types are non-shared." + | T.Func (T.Shared _, _, _, _, _) -> + error_in [Flags.ICMode] env at "shared function types are non-shared." + | _ -> raise Recover) + fmt + let rec check_typ env typ : T.typ = let t = check_typ' env typ in typ.note <- t; @@ -171,7 +217,8 @@ let rec check_typ env typ : T.typ = and infer_control env sort typ = match sort.it, typ.it with | T.Shared _, AsyncT ret_typ -> T.Promises (arity ret_typ) - | T.Shared T.Write, TupT [] -> T.Returns + | T.Shared T.Write, TupT [] -> + T.Returns | T.Shared T.Write, _ -> error env typ.at "shared function must have syntactic return type `()` or `async `" | T.Shared T.Query, _ -> error env typ.at "shared query function must have syntactic return type `async `" | _ -> T.Returns @@ -208,9 +255,7 @@ and check_typ' env typ : T.typ = if not env.pre then begin let t1 = T.seq ts1 in if not (T.shared t1) then - error env typ1.at - "shared function has non-shared parameter type\n %s" - (T.string_of_typ_expand t1); + error_shared env t1 typ1.at "shared function has non-shared parameter type\n %s" (T.string_of_typ_expand t1); match ts2 with | [] when sort.it = T.Shared T.Write -> () | [T.Async _] -> () @@ -231,7 +276,7 @@ and check_typ' env typ : T.typ = | AsyncT typ -> let t = check_typ env typ in if not env.pre && not (T.shared t) then - error env typ.at "async has non-shared content type\n %s" + error_shared env t typ.at "async has non-shared content type\n %s" (T.string_of_typ_expand t); T.Async t | ObjT (sort, fields) -> @@ -246,11 +291,8 @@ and check_typ_field env s typ_field : T.field = let {id; mut; typ} = typ_field.it in let t = infer_mut mut (check_typ env typ) in if not env.pre && s = T.Actor then begin - if not (T.is_func (T.promote t)) then - error env typ.at "actor field %s has non-function type\n %s" - id.it (T.string_of_typ_expand t); - if not (T.shared t) then - error env typ.at "actor field %s has non-shared type\n %s" + if not (T.is_shared_func t) then + error env typ.at "actor field %s must have shared function type, but has type\n %s" id.it (T.string_of_typ_expand t) end; T.{lab = id.it; typ = t} @@ -488,6 +530,11 @@ and infer_exp' f env exp : T.typ = t' and infer_exp'' env exp : T.typ = + let in_prog = env.in_prog in + let in_actor = env.in_actor in + let in_await = env.in_await in + let in_shared = env.in_shared in + let env = {env with in_actor = false; in_await = false; in_prog = false; in_shared = false} in match exp.it with | PrimE _ -> error env exp.at "cannot infer type of primitive" @@ -572,7 +619,9 @@ and infer_exp'' env exp : T.typ = (T.string_of_typ_expand t1) ) | ObjE (sort, fields) -> - let env' = if sort.it = T.Actor then {env with async = false} else env in + if not in_prog && sort.it = T.Actor then + error_in [Flags.ICMode] env exp.at "non-toplevel actor; an actor can only be declared at the toplevel of a program"; + let env' = if sort.it = T.Actor then {env with async = false; in_actor = true} else env in infer_obj env' sort.it fields exp.at | DotE (exp1, id) -> let t1 = infer_exp_promote env exp1 in @@ -623,6 +672,8 @@ and infer_exp'' env exp : T.typ = (T.string_of_typ_expand t1) ) | FuncE (_, sort, typ_binds, pat, typ_opt, exp) -> + if not env.pre && not in_actor && T.is_shared_sort sort.it then + error_in [Flags.ICMode] env exp.at "a shared function is only allowed as a public field of an actor"; let typ = match typ_opt with | Some typ -> typ @@ -635,11 +686,15 @@ and infer_exp'' env exp : T.typ = let t2 = check_typ env' typ in if not env.pre then begin let env'' = - {env' with labs = T.Env.empty; rets = Some t2; async = false} in + { env' with + labs = T.Env.empty; + rets = Some t2; + async = false; + in_shared = T.is_shared_sort sort.it} in check_exp (adjoin_vals env'' ve) t2 exp; if Type.is_shared_sort sort.it then begin if not (T.shared t1) then - error env pat.at + error_shared env t1 pat.at "shared function has non-shared parameter type\n %s" (T.string_of_typ_expand t1); match t2 with @@ -672,6 +727,10 @@ and infer_exp'' env exp : T.typ = if not env.pre then begin check_exp env t_arg exp2; if Type.is_shared_sort sort then begin + if T.is_async t_ret && not in_await then + error_in [Flags.ICMode] env exp2.at + "shared, async function must be called within an await expression"; + error_in [Flags.ICMode] env exp1.at "calling a shared function not yet supported"; if not (T.concrete t_arg) then error env exp1.at "shared function argument contains abstract type\n %s" @@ -816,17 +875,24 @@ and infer_exp'' env exp : T.typ = if not env.pre then check_exp env T.throw exp1; T.Non | AsyncE exp1 -> + if not in_shared then + error_in [Flags.ICMode] env exp.at "unsupported async block"; let env' = {env with labs = T.Env.empty; rets = Some T.Pre; async = true} in let t = infer_exp env' exp1 in if not (T.shared t) then - error env exp1.at "async type has non-shared content type\n %s" + error_shared env t exp1.at "async type has non-shared content type\n %s" (T.string_of_typ_expand t); T.Async t - | AwaitE exp1 -> + | AwaitE (exp1) -> if not env.async then error env exp.at "misplaced await"; - let t1 = infer_exp_promote env exp1 in + let t1 = infer_exp_promote {env with in_await = true} exp1 in + (match exp1.it with + | CallE (f, _, _) -> + if not env.pre && (Call_conv.call_conv_of_typ f.note.note_typ).Call_conv.control = T.Returns then + error_in [Flags.ICMode] env f.at "expecting call to shared async function in await"; + | _ -> error_in [Flags.ICMode] env exp1.at "argument to await must be a call expression"); (try T.as_async_sub t1 with Invalid_argument _ -> @@ -857,7 +923,9 @@ and check_exp env t exp = let e = A.infer_effect_exp exp in exp.note <- {note_typ = t'; note_eff = e} -and check_exp' env t exp : T.typ = +and check_exp' env0 t exp : T.typ = + let in_shared = env0.in_shared in + let env = {env0 with in_await = false; in_shared = false; in_prog = false} in match exp.it, t with | PrimE s, T.Func _ -> t @@ -888,6 +956,8 @@ and check_exp' env t exp : T.typ = List.iter (check_exp env (T.as_immut t')) exps; t | AsyncE exp1, T.Async t' -> + if not in_shared then + error_in [Flags.ICMode] env exp.at "freestanding async expression not yet supported"; let env' = {env with labs = T.Env.empty; rets = Some t'; async = true} in check_exp env' t' exp1; t @@ -941,13 +1011,18 @@ and check_exp' env t exp : T.typ = "function return type\n %s\ndoes not match expected return type\n %s" (T.string_of_typ_expand t2) (T.string_of_typ_expand (T.seq ts2)); let env' = - {env with labs = T.Env.empty; rets = Some t2; async = false} in + { env with + labs = T.Env.empty; + rets = Some t2; + async = false; + in_shared = T.is_shared_sort s'.it; + } in check_exp (adjoin_vals env' ve) t2 exp; t | _ -> - let t' = infer_exp env exp in + let t' = infer_exp env0 exp in if not (T.sub t' t) then - local_error env exp.at + local_error env0 exp.at "expression of type\n %s\ncannot produce expected type\n %s" (T.string_of_typ_expand t') (T.string_of_typ_expand t); @@ -1320,7 +1395,8 @@ and object_of_scope env sort fields scope at = (T.string_of_typ_expand t) and is_actor_method dec : bool = match dec.it with - | LetD ({it = VarP _; _}, {it = FuncE _; _}) -> true + | LetD ({it = VarP _; _}, {it = FuncE (_, sort, _, _, _, _); _}) -> + T.is_shared_sort sort.it | _ -> false and is_typ_dec dec : bool = match dec.it with @@ -1329,25 +1405,31 @@ and is_typ_dec dec : bool = match dec.it with and infer_obj env s fields at : T.typ = + let env = {env with in_actor = s = T.Actor} in let decs = List.map (fun (field : exp_field) -> field.it.dec) fields in let _, scope = infer_block env decs at in let t = object_of_scope env s fields scope at in let (_, tfs) = T.as_obj t in if not env.pre then begin - if s = T.Actor then + if s = T.Actor then begin List.iter (fun T.{lab; typ} -> - if not (T.is_typ typ) && not (T.shared typ) then + if not (T.is_typ typ) && not (T.is_shared_func typ) then let _, pub_val = pub_fields fields in error env (T.Env.find lab pub_val) - "public actor field %s has non-shared type\n %s" + "public actor field %s has non-shared function type\n %s" lab (T.string_of_typ_expand typ) ) tfs; - if s = T.Actor then List.iter (fun ef -> if ef.it.vis.it = Syntax.Public && not (is_actor_method ef.it.dec) && not (is_typ_dec ef.it.dec) then local_error env ef.it.dec.at "public actor field needs to be a manifest function" ) fields; + List.iter (fun ef -> + if ef.it.vis.it = Syntax.Private && is_actor_method ef.it.dec then + error_in [Flags.ICMode] env ef.it.dec.at + "a shared function cannot be private" + ) fields; + end; if s = T.Module then Static.fields env.msgs fields end; t @@ -1399,7 +1481,8 @@ and infer_dec env dec : T.typ = { (add_val env'' self_id.it self_typ) with labs = T.Env.empty; rets = None; - async = false + async = false; + in_actor = sort.it = T.Actor; } in let t' = infer_obj env''' sort.it fields dec.at in @@ -1668,7 +1751,10 @@ and infer_dec_valdecs env dec : Scope.t = typ_env = T.Env.singleton id.it c; con_env = T.ConSet.singleton c ; } - | ClassD (id, typ_binds, pat, _, _, _, _) -> + | ClassD (id, typ_binds, pat, _, sort, _, _) -> + if sort.it = T.Actor then + error_in [Flags.ICMode] env dec.at + "actor classes are not supported; use an actor declaration instead"; let cs, ts, te, ce = check_typ_binds env typ_binds in let env' = adjoin_typs env te ce in let c = T.Env.find id.it env.typs in @@ -1717,3 +1803,27 @@ let check_library scope (filename, prog) : Scope.t Diag.result = Scope.library filename typ ) prog ) + +let is_actor_dec d = + match d.it with + | LetD (_, {it = ObjE ({it = T.Actor; _}, _); _}) -> true + | _ -> false + +let check_actors scope progs : unit Diag.result = + Diag.with_message_store + (fun msgs -> + recover_opt (fun progs -> + let prog = List.concat (List.map (fun prog -> prog.Source.it) progs) in + let env = env_of_scope msgs scope in + match List.filter is_actor_dec prog with + | [] -> () + | [d] -> () + | ds -> + List.iter (fun d -> + recover + (error_in [Flags.ICMode] env d.at) + "multiple actors in program; there must be at most one actor declaration in a program") + ds + ) + progs) + diff --git a/src/as_frontend/typing.mli b/src/as_frontend/typing.mli index 95afd71bec9..871989a8130 100644 --- a/src/as_frontend/typing.mli +++ b/src/as_frontend/typing.mli @@ -6,3 +6,4 @@ open Scope val infer_prog : scope -> Syntax.prog -> (typ * scope) Diag.result val check_library : scope -> Syntax.library -> scope Diag.result +val check_actors : scope -> Syntax.prog list -> unit Diag.result diff --git a/src/as_types/dune b/src/as_types/dune index 1dab68e6563..9e5d4e891ac 100644 --- a/src/as_types/dune +++ b/src/as_types/dune @@ -1,4 +1,4 @@ (library (name as_types) - (libraries wasm lib lang_utils) + (libraries wasm lib lang_utils as_config) ) diff --git a/src/as_types/type.ml b/src/as_types/type.ml index f5e5ef41ee6..a1d084194e1 100644 --- a/src/as_types/type.ml +++ b/src/as_types/type.ml @@ -1,4 +1,5 @@ (* Representation *) +open As_config type lab = string type var = string @@ -557,8 +558,10 @@ let concrete t = end in go t - let shared t = + (* TBR: Hack to restrict sharing in ICMode *) + let allow_actor = not (!Flags.compile_mode = Flags.ICMode) in + let allow_shared = not (!Flags.compile_mode = Flags.ICMode) in let seen = ref S.empty in let rec go t = S.mem t !seen || @@ -576,12 +579,54 @@ let shared t = ) | Array t | Opt t -> go t | Tup ts -> List.for_all go ts - | Obj (s, fs) -> s = Actor || List.for_all (fun f -> go f.typ) fs + | Obj (s, fs) -> + (allow_actor && s = Actor) || + (not (s = Actor) && List.for_all (fun f -> go f.typ) fs) | Variant fs -> List.for_all (fun f -> go f.typ) fs - | Func (s, c, tbs, ts1, ts2) -> is_shared_sort s + | Func (s, c, tbs, ts1, ts2) -> allow_shared && is_shared_sort s end in go t +(* Find the first unshared subexpression in a type *) +let find_unshared t = + (* TBR: Hack to restrict sharing in ICMode *) + let allow_actor = not (!Flags.compile_mode = Flags.ICMode) in + let allow_shared = not (!Flags.compile_mode = Flags.ICMode) in + let seen = ref S.empty in + let rec go t = + if S.mem t !seen then None else + begin + seen := S.add t !seen; + match t with + | Var _ | Pre -> assert false + | Prim Error -> Some t + | Any | Non | Prim _ | Typ _ -> None + | Async _ | Mut _ -> Some t + | Con (c, ts) -> + (match Con.kind c with + | Abs _ -> None + | Def (_, t) -> go (open_ ts t) (* TBR this may fail to terminate *) + ) + | Array t | Opt t -> go t + | Tup ts -> Lib.List.first_opt go ts + | Obj (s, fs) -> + if s = Actor + then if allow_actor then None + else Some t + else Lib.List.first_opt (fun f -> go f.typ) fs + | Variant fs -> Lib.List.first_opt (fun f -> go f.typ) fs + | Func (s, c, tbs, ts1, ts2) -> + if allow_shared && is_shared_sort s + then None + else Some t + end + in go t + +let is_shared_func t = + match normalize t with + | Func (Shared _, _, _, _, _) -> true + | _ -> false + (* Equivalence & Subtyping *) diff --git a/src/as_types/type.mli b/src/as_types/type.mli index 757a75252aa..aed92491c4e 100644 --- a/src/as_types/type.mli +++ b/src/as_types/type.mli @@ -158,6 +158,8 @@ val avoid_cons : ConSet.t -> ConSet.t -> unit (* raise Unavoidable *) val opaque : typ -> bool val concrete : typ -> bool val shared : typ -> bool +val find_unshared : typ -> typ option +val is_shared_func : typ -> bool val inhabited : typ -> bool val span : typ -> int option diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index f14fdd8ee44..af5e1f581b8 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -211,11 +211,8 @@ and check_typ_field env s typ_field : unit = check_typ env typ; if not (T.is_typ typ) then begin check env no_region - (s <> Some T.Actor || T.is_func (T.promote typ)) - "actor field has non-function type"; - check env no_region - (s <> Some T.Actor || T.shared typ) - "actor field has non-shared type" + (s <> Some T.Actor || T.is_shared_func typ) + "actor field must have shared function type" end and check_typ_binds_acyclic env cs ts = @@ -731,10 +728,8 @@ and type_exp_field env s f : T.field = assert (t <> T.Pre); check_sub env f.at t f.note; if not (T.is_typ t) then begin - check env f.at ((s = T.Actor) ==> T.is_func t) - "public actor field is not a function"; - check env f.at ((s = T.Actor) ==> T.shared t) - "public actor field has non-shared type"; + check env f.at ((s = T.Actor) ==> T.is_shared_func t) + "public actor field must have shared function type"; end; T.{lab = name; typ = t} diff --git a/src/languageServer/languageServer.ml b/src/languageServer/languageServer.ml index 691662831b0..45c59297c90 100644 --- a/src/languageServer/languageServer.ml +++ b/src/languageServer/languageServer.ml @@ -100,7 +100,9 @@ let start () = let vfs = ref Vfs.empty in let decl_index = let ix = match Declaration_index.make_index !vfs with - | Error(err) -> Declaration_index.Index.empty + | Error(err) -> + List.iter (fun e -> log_to_file "Error" (Diag.string_of_message e)) err; + Declaration_index.Index.empty | Ok((ix, _)) -> ix in ref ix in let rec loop () = diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index 5f0c1fcc0ea..aab5267d300 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -493,9 +493,9 @@ let compile_prog mode do_link lib_env libraries progs : Wasm_exts.CustomModule.e Codegen.Compile.compile mode name rts prelude_ir [prog_ir] let compile_files mode do_link files : compile_result = - Diag.bind (load_progs parse_file files initial_stat_env) - (fun (libraries, progs, senv) -> - Diag.return (compile_prog mode do_link senv.Scope.lib_env libraries progs)) + Diag.bind (load_progs parse_file files initial_stat_env) (fun (libraries, progs, senv) -> + Diag.bind (Typing.check_actors senv progs) (fun () -> + Diag.return (compile_prog mode do_link senv.Scope.lib_env libraries progs))) let compile_string mode s name : compile_result = Diag.bind (load_decl (parse_string name s) initial_stat_env) @@ -507,6 +507,7 @@ let compile_string mode s name : compile_result = let interpret_ir_prog inp_env libraries progs = let prelude_ir = Lowering.Desugar.transform prelude in let name = name_progs progs in + Flags.compile_mode := Flags.WasmMode; (* REMOVE THIS HACK *) let prog_ir = lower_prog Flags.WasmMode initial_stat_env inp_env libraries progs name in phase "Interpreting" name; let open Interpret_ir in diff --git a/stdlib/Makefile b/stdlib/Makefile index 131fd4a7be9..4bc923fe621 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -209,22 +209,22 @@ PRODUCE_EXCHANGE_SRC=\ $(OUTDIR)/ProduceExchange.out: $(PRODUCE_EXCHANGE_SRC) \ examples/produce-exchange/test/simpleSetupAndQuery.as | $(OUTDIR) - $(ASC) -r examples/produce-exchange/test/simpleSetupAndQuery.as > $@ + $(ASC) -ancient-system-api -r examples/produce-exchange/test/simpleSetupAndQuery.as > $@ $(OUTDIR)/retailerReserveMany.out: $(PRODUCE_EXCHANGE_SRC) \ examples/produce-exchange/test/retailerReserveMany.as | $(OUTDIR) - $(ASC) -r examples/produce-exchange/test/retailerReserveMany.as > $@ + $(ASC) -ancient-system-api -r examples/produce-exchange/test/retailerReserveMany.as > $@ $(OUTDIR)/producerRemInventory.out: $(PRODUCE_EXCHANGE_SRC) \ examples/produce-exchange/test/producerRemInventory.as | $(OUTDIR) - $(ASC) -r examples/produce-exchange/test/producerRemInventory.as > $@ + $(ASC) -ancient-system-api -r examples/produce-exchange/test/producerRemInventory.as > $@ $(OUTDIR)/evalBulk.out: $(PRODUCE_EXCHANGE_SRC) \ examples/produce-exchange/test/evalBulk.as | $(OUTDIR) - $(ASC) -r examples/produce-exchange/test/evalBulk.as > $@ + $(ASC) -ancient-system-api -r examples/produce-exchange/test/evalBulk.as > $@ $(OUTDIR)/ProduceExchange.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c -o $@ examples/produce-exchange/serverActor.as + $(ASC) -ancient-system-api -c -o $@ examples/produce-exchange/serverActor.as $(DOCDIR)/%.md: %.as $(MDofAS) | $(DOCDIR) @echo "" > $@ diff --git a/stdlib/examples/produce-exchange/test/profileLoadQuery.as b/stdlib/examples/produce-exchange/test/profileLoadQuery.as index eb15d400c01..a4d322678fc 100644 --- a/stdlib/examples/produce-exchange/test/profileLoadQuery.as +++ b/stdlib/examples/produce-exchange/test/profileLoadQuery.as @@ -1,5 +1,5 @@ func scaledParams(region_count_:Nat, factor:Nat) : T.WorkloadParams = { - shared { + { region_count = region_count_:Nat; day_count = 3:Nat; max_route_duration = 1:Nat; diff --git a/test/fail/ok/issue103.tc.ok b/test/fail/ok/issue103.tc.ok index cb4947dde21..086b470addf 100644 --- a/test/fail/ok/issue103.tc.ok +++ b/test/fail/ok/issue103.tc.ok @@ -1,8 +1,24 @@ issue103.as:3.29-3.40: type error, shared function has non-shared parameter type () -> Nat +type + () -> Nat +is or contains non-shared type + () -> Nat issue103.as:10.29-10.46: type error, shared function has non-shared parameter type {foo : () -> Nat} +type + {foo : () -> Nat} +is or contains non-shared type + () -> Nat issue103.as:17.29-17.40: type error, async has non-shared content type () -> Nat +type + () -> Nat +is or contains non-shared type + () -> Nat issue103.as:24.29-24.48: type error, async has non-shared content type {foo : () -> Nat} +type + {foo : () -> Nat} +is or contains non-shared type + () -> Nat diff --git a/test/repl/type-lub-repl.sh b/test/repl/type-lub-repl.sh index 7f1092a9702..d7caab4c801 100755 --- a/test/repl/type-lub-repl.sh +++ b/test/repl/type-lub-repl.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # Tests that correct lub types are inferred when values appear in arrays -${ASC:-$(dirname "$BASH_SOURCE")/../../src/asc} -i ../run-dfinity/type-lub.as <<__END__ +${ASC:-$(dirname "$BASH_SOURCE")/../../src/asc} -i -ancient-system-api ../run-dfinity/type-lub.as <<__END__ opts; nulls; incompatible_objs; diff --git a/test/run-drun/multiple-actors.as b/test/run-drun/multiple-actors.as new file mode 100644 index 00000000000..33e4b920714 --- /dev/null +++ b/test/run-drun/multiple-actors.as @@ -0,0 +1,7 @@ +actor a { }; + +actor b { }; + + + + diff --git a/test/run-drun/ok/idl-func.drun-run.ok b/test/run-drun/ok/idl-func.drun-run.ok deleted file mode 100644 index c6cc701ed78..00000000000 --- a/test/run-drun/ok/idl-func.drun-run.ok +++ /dev/null @@ -1,3 +0,0 @@ -ingress(0) System -Ok: Payload: 0x4449444c026e016a017c0000010000 -Ok: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-func.tc.ok b/test/run-drun/ok/idl-func.tc.ok new file mode 100644 index 00000000000..3170d1bbf34 --- /dev/null +++ b/test/run-drun/ok/idl-func.tc.ok @@ -0,0 +1,8 @@ +idl-func.as:1.33-1.37: type error, async has non-shared content type + Func = shared Int -> async Func +type + Func = shared Int -> async Func +is or contains non-shared type + shared Int -> async Func +idl-func.as:1.33-1.37: type error, shared function types are non-shared. + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/multiple-actors.wasm.stderr.ok b/test/run-drun/ok/multiple-actors.wasm.stderr.ok new file mode 100644 index 00000000000..a4e05b33051 --- /dev/null +++ b/test/run-drun/ok/multiple-actors.wasm.stderr.ok @@ -0,0 +1,4 @@ +multiple-actors.as:1.1-1.12: type error, multiple actors in program; there must be at most one actor declaration in a program + (This is a limitation of the current version.) +multiple-actors.as:3.1-3.12: type error, multiple actors in program; there must be at most one actor declaration in a program + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/unsupported.tc.ok b/test/run-drun/ok/unsupported.tc.ok new file mode 100644 index 00000000000..4bd2f18387b --- /dev/null +++ b/test/run-drun/ok/unsupported.tc.ok @@ -0,0 +1,54 @@ +unsupported.as:6.28-6.39: type error, shared function has non-shared parameter type + actor {} +type + actor {} +is or contains non-shared type + actor {} +unsupported.as:6.28-6.39: type error, actor types are non-shared. + (This is a limitation of the current version.) +unsupported.as:8.31-8.53: type error, shared function has non-shared parameter type + shared () -> async () +type + shared () -> async () +is or contains non-shared type + shared () -> async () +unsupported.as:8.31-8.53: type error, shared function types are non-shared. + (This is a limitation of the current version.) +unsupported.as:19.19-19.21: type error, shared, async function must be called within an await expression + (This is a limitation of the current version.) +unsupported.as:23.16-23.18: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +unsupported.as:28.8-28.9: type error, argument to await must be a call expression + (This is a limitation of the current version.) +unsupported.as:32.17-32.29: type error, unsupported async block + (This is a limitation of the current version.) +unsupported.as:4.5-4.41: type error, a shared function cannot be private + (This is a limitation of the current version.) +unsupported.as:38.26-38.29: type error, a shared function is only allowed as a public field of an actor + (This is a limitation of the current version.) +unsupported.as:41.10-41.18: type error, unsupported async block + (This is a limitation of the current version.) +unsupported.as:46.31-46.48: type error, shared function has non-shared parameter type + shared () -> () +type + shared () -> () +is or contains non-shared type + shared () -> () +unsupported.as:46.31-46.48: type error, shared function types are non-shared. + (This is a limitation of the current version.) +unsupported.as:51.31-51.41: type error, shared function has non-shared parameter type + actor {} +type + actor {} +is or contains non-shared type + actor {} +unsupported.as:51.31-51.41: type error, actor types are non-shared. + (This is a limitation of the current version.) +unsupported.as:62.3-62.35: type error, actor classes are not supported; use an actor declaration instead + (This is a limitation of the current version.) +unsupported.as:66.45-66.53: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program + (This is a limitation of the current version.) +unsupported.as:70.29-70.37: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program + (This is a limitation of the current version.) +unsupported.as:76.34-76.37: type error, freestanding async expression not yet supported + (This is a limitation of the current version.) diff --git a/test/run-drun/unsupported.as b/test/run-drun/unsupported.as new file mode 100644 index 00000000000..bc1d44419b2 --- /dev/null +++ b/test/run-drun/unsupported.as @@ -0,0 +1,76 @@ +// top-level actor objects are supported +actor Counter { + + shared func bad_private_shared() { }; // not public + + public func badactorarg(a:actor{}) : async () {}; + + public func badfunctionarg(f:shared()->async ()) : async () {}; + + /* TODO + public func badoneway(){}; // unsupported oneway + */ + + public func ok() : async () {}; + + public func ok_explicit() : async () = async {}; + + public func bad_call() : async () { + ignore (ok()); // unsupported intercanister messaging + }; + + public func bad_await_call() : async () { + await (ok()); // unsupported intercanister messaging + }; + + public func bad_await() : async () { + let t : async Int = loop {}; + await t; // unsupported general await + }; + + public func badasync() : async () { + let a = async { 1; }; // unsupported async + }; + +} +; + +shared func bad_shared() { }; // not actor enclosed + +func local_spawn() { + ignore(async ()); // not yet supported +}; + +{ + // shared function types aren't sharable + type illformed_1 = shared (shared () -> ()) -> async (); +}; + +{ + // actors aren't shareable + type illformed_2 = shared (actor {}) -> async (); +}; + +/* TODO +{ + // oneway functions aren't supported + type illformed_3 = shared () -> (); +}; +*/ + +{ + actor class BadActorClass () { }; // no actor classes +}; + +{ + let bad_non_top_actor : actor {} = if true actor {} else actor {}; +}; + +{ + let bad_nested_actor = { actor {}; ()}; +}; + + +actor BadSecondActor { }; + +func implicit_async() : async () { }; // async functions not supported diff --git a/test/run.sh b/test/run.sh index 5ebbb60d20d..2375c6c4cc7 100755 --- a/test/run.sh +++ b/test/run.sh @@ -132,7 +132,7 @@ do then # Typecheck $ECHO -n " [tc]" - $ASC $ASC_FLAGS --check $base.as > $out/$base.tc 2>&1 + $ASC $ASC_FLAGS $EXTRA_ASC_FLAGS --check $base.as > $out/$base.tc 2>&1 tc_succeeded=$? normalize $out/$base.tc diff_files="$diff_files $base.tc" @@ -158,13 +158,13 @@ do then # Interpret $ECHO -n " [run]" - $ASC $ASC_FLAGS -r $base.as > $out/$base.run 2>&1 + $ASC $ASC_FLAGS $EXTRA_ASC_FLAGS -r $base.as > $out/$base.run 2>&1 normalize $out/$base.run diff_files="$diff_files $base.run" # Interpret IR without lowering $ECHO -n " [run-ir]" - $ASC $ASC_FLAGS -r -iR -no-async -no-await $base.as > $out/$base.run-ir 2>&1 + $ASC $ASC_FLAGS $EXTRA_ASC_FLAGS -r -iR -no-async -no-await $base.as > $out/$base.run-ir 2>&1 normalize $out/$base.run-ir diff_files="$diff_files $base.run-ir" @@ -174,7 +174,7 @@ do # Interpret IR with lowering $ECHO -n " [run-low]" - $ASC $ASC_FLAGS -r -iR $base.as > $out/$base.run-low 2>&1 + $ASC $ASC_FLAGS $EXTRA_ASC_FLAGS -r -iR $base.as > $out/$base.run-low 2>&1 normalize $out/$base.run-low diff_files="$diff_files $base.run-low" From 2cd00fadb804d1ee52cad26049457a66052b7884 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Mon, 21 Oct 2019 14:10:17 +0200 Subject: [PATCH 0468/1176] Decode future types (#775) * support ingesting future types * add test for future type --- src/exes/deser.ml | 13 ++++++++++++- test/run-deser/future.bin | Bin 0 -> 22 bytes test/run-deser/ok/future.ok | 13 +++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 test/run-deser/future.bin create mode 100644 test/run-deser/ok/future.ok diff --git a/src/exes/deser.ml b/src/exes/deser.ml index 8f9eb886471..24c5390c9fe 100644 --- a/src/exes/deser.ml +++ b/src/exes/deser.ml @@ -126,6 +126,7 @@ type typ = Null | Bool | Nat | NatN of int | Record of fields | Variant of alts | Function of typ Lazy.t array * typ Lazy.t array * ann array + | Future of int * Buffer.t and alts = (int * typ Lazy.t) array and fields = (int * typ Lazy.t) array @@ -415,7 +416,17 @@ let read_type lookup : (typ * outputter) Lazy.t = T(service {*}) = sleb128(-23) T*(* ) *) - | t -> failwith (Printf.sprintf "unrecognised structured type: %d" t) + | t -> (* future type *) + let bytes = read_leb128 () in + let buf = Buffer.create 0 in + ignore (input_buffer stdin buf ~len:bytes); + let ingest () = + let bytes = read_leb128 () in + let refs = read_leb128 () in + let buf = Buffer.create 0 in + assert (refs = 0); + ignore (input_buffer stdin buf ~len:bytes) in + lazy (Future (t, buf), ingest) let read_type_table (t : unit -> (typ * outputter) Lazy.t) : (typ * outputter) Lazy.t array = diff --git a/test/run-deser/future.bin b/test/run-deser/future.bin new file mode 100644 index 0000000000000000000000000000000000000000..87a4ab21ffbe49add57aaccb1d0a0906103edc87 GIT binary patch literal 22 dcmZ?qbn#(KV_JQdiJ_2%;ojPP@0s25^8rsJ2h{)o literal 0 HcmV?d00001 diff --git a/test/run-deser/ok/future.ok b/test/run-deser/ok/future.ok new file mode 100644 index 00000000000..7e8dfe272e7 --- /dev/null +++ b/test/run-deser/ok/future.ok @@ -0,0 +1,13 @@ + +DESER, to your service! + +========================== Type section +read_type_table: 0 + +========================== Value section +# 2 arguments follow +# Argument #0: + +# Argument #1 (last): +"Foo" +-------- DESER DONE From 25bb5a86646729e648219639683223ea56f4c908 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 21 Oct 2019 14:48:15 +0200 Subject: [PATCH 0469/1176] =?UTF-8?q?Deserialize:=20Understand=20=E2=80=9C?= =?UTF-8?q?future=20types=E2=80=9D=20when=20skipping=20values=20(#774)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Deserialize: Understand “future types” when skipping values * add test output --- rts/idl.c | 30 +++++++++++++++++++--------- test/run-drun/idl-any.as | 1 + test/run-drun/ok/idl-any.drun-run.ok | 2 ++ 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/rts/idl.c b/rts/idl.c index b8ace108259..4349ae08a3f 100644 --- a/rts/idl.c +++ b/rts/idl.c @@ -114,7 +114,7 @@ export void parse_idl_header(buf *buf, uint8_t ***typtbl_out, uint8_t **main_typ typtbl[i] = buf->p; int32_t ty = read_i32_of_sleb128(buf); if (ty >= IDL_PRIM_lowest) { - idl_trap_with("type index too high"); // illegal + idl_trap_with("primitive type in type table"); // illegal } else if (ty == IDL_CON_opt) { int32_t t = read_i32_of_sleb128(buf); if (t < IDL_PRIM_lowest || t >= n_types) idl_trap_with("type index out of range"); @@ -157,9 +157,9 @@ export void parse_idl_header(buf *buf, uint8_t ***typtbl_out, uint8_t **main_typ int32_t t = read_i32_of_sleb128(buf); if (t < IDL_PRIM_lowest || t >= n_types) idl_trap_with("type index out of range"); } - } else { - // no support for future types yet - idl_trap_with("future type"); + } else { // future type + uint32_t n = read_u32_of_leb128(buf); + advance(buf, n); } } // Now read the main types @@ -250,9 +250,9 @@ export void skip_any(buf *b, uint8_t **typtbl, int32_t t, int32_t depth) { for (uint32_t n = read_u32_of_leb128(&tb); n > 0; n--) { skip_leb128(&tb); int32_t it = read_i32_of_sleb128(&tb); - // This is just a quick check; we should be keeping - // track of all enclosing records to detect larger loops - if (it == t) idl_trap_with("skip_any: recursive record"); + // This is just a quick check; we should be keeping + // track of all enclosing records to detect larger loops + if (it == t) idl_trap_with("skip_any: recursive record"); skip_any(b, typtbl, it, depth + 1); } return; @@ -271,8 +271,20 @@ export void skip_any(buf *b, uint8_t **typtbl, int32_t t, int32_t depth) { return; } - default: - idl_trap_with("skip_any: unknown tycon"); + case IDL_CON_func: + idl_trap_with("skip_any: func"); + + case IDL_CON_service: + idl_trap_with("skip_any: service"); + + default: { // future type + uint32_t n_data = read_u32_of_leb128(b); + uint32_t n_ref = read_u32_of_leb128(b); + advance(b, n_data); + if (n_ref > 0) { + idl_trap_with("skip_any: skipping references"); + } + } } } } diff --git a/test/run-drun/idl-any.as b/test/run-drun/idl-any.as index 3d6552eacb0..eb0a5e82044 100644 --- a/test/run-drun/idl-any.as +++ b/test/run-drun/idl-any.as @@ -36,3 +36,4 @@ actor { //CALL ingress any 0x4449444C016b0180017502007100DEADBEEF03466F6F //CALL ingress any 0x4449444C016b0200718001750200710001A003466F6F //CALL ingress any 0x4449444C016b02007180017502007101DEADBEEF03466F6F +//CALL ingress any 0x4449444C016602ABCD0200710400DEADBEEF03466F6F diff --git a/test/run-drun/ok/idl-any.drun-run.ok b/test/run-drun/ok/idl-any.drun-run.ok index bad9a039c2f..4f76ce5ac28 100644 --- a/test/run-drun/ok/idl-any.drun-run.ok +++ b/test/run-drun/ok/idl-any.drun-run.ok @@ -53,3 +53,5 @@ debug.print: ok: Foo ingress(26) Completed: Canister: Payload: 0x4449444c0000 debug.print: ok: Foo ingress(27) Completed: Canister: Payload: 0x4449444c0000 +debug.print: ok: Foo +ingress(28) Completed: Canister: Payload: 0x4449444c0000 From 330f86edfe7a9e761119c590751c11eae7961375 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 22 Oct 2019 17:41:36 +0200 Subject: [PATCH 0470/1176] Bump drun (#779) to get https://github.com/dfinity-lab/dfinity/pull/1602 --- default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/default.nix b/default.nix index 1ea66d39381..e7f1f32206e 100644 --- a/default.nix +++ b/default.nix @@ -33,7 +33,7 @@ let dev = import (builtins.fetchGit { let dfinity-repo = import (builtins.fetchGit { url = "ssh://git@github.com/dfinity-lab/dfinity"; # ref = "master"; - rev = "ab9d9d6ccba33748fc92f6e8d631327f7f25aead"; + rev = "be855124bb48c8ff5534fbca1ce8e21e58d78634"; }) { system = nixpkgs.system; }; in let sdk = import (builtins.fetchGit { From 62a3e50336ac3d99960a9b75e83fc8f972066909 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Wed, 23 Oct 2019 21:13:26 +0200 Subject: [PATCH 0471/1176] correct arg sequence and comments (#781) in --idl mode --- src/exes/deser.ml | 13 +++++++++---- test/run-deser/ok/five.ok | 24 +++++++++++++----------- test/run-deser/ok/future.ok | 12 +++++++----- 3 files changed, 29 insertions(+), 20 deletions(-) diff --git a/src/exes/deser.ml b/src/exes/deser.ml index 24c5390c9fe..aa5f4de7563 100644 --- a/src/exes/deser.ml +++ b/src/exes/deser.ml @@ -255,11 +255,16 @@ let output_text n froms tos = let output_arguments args : outputter * (unit -> int -> outputter -> outputter) = + let last i = i + 1 = args in let herald_arguments = function - | () when args = 0 -> output_string "# No arguments...\n" - | _ when args = 1 -> output_string "# 1 argument follows" - | _ -> Printf.printf "# %d arguments follow" args in - let herald_member () i f () = Printf.printf "\n# Argument #%d%s:\n" i (if i + 1 = args then " (last)" else ""); f () in + | () when args = 0 -> output_string "// No arguments...\n()" + | _ when args = 1 -> output_string "// 1 argument follows\n(\n" + | _ -> Printf.printf "// %d arguments follow\n(\n" args in + let herald_member () i f () = + Printf.printf "// Argument #%d%s:\n" i (if last i then " (last)" else ""); + if i = 0 then print_string " " else print_string ", "; + f (); + if last i then print_string "\n)" else print_string "\n" in herald_arguments, (*bracket args*) herald_member let start i = if i = 0 then output_string_space "{" diff --git a/test/run-deser/ok/five.ok b/test/run-deser/ok/five.ok index 2eabbaa19ef..92e67e390dc 100644 --- a/test/run-deser/ok/five.ok +++ b/test/run-deser/ok/five.ok @@ -4,15 +4,17 @@ DESER, to your service! ========================== Type section ========================== Value section -# 5 arguments follow -# Argument #0: -"One" -# Argument #1: -"Two" -# Argument #2: -"Three" -# Argument #3: -"Four" -# Argument #4 (last): -"Five" +// 5 arguments follow +( +// Argument #0: + "One" +// Argument #1: +, "Two" +// Argument #2: +, "Three" +// Argument #3: +, "Four" +// Argument #4 (last): +, "Five" +) -------- DESER DONE diff --git a/test/run-deser/ok/future.ok b/test/run-deser/ok/future.ok index 7e8dfe272e7..77610c4fd4b 100644 --- a/test/run-deser/ok/future.ok +++ b/test/run-deser/ok/future.ok @@ -5,9 +5,11 @@ DESER, to your service! read_type_table: 0 ========================== Value section -# 2 arguments follow -# Argument #0: - -# Argument #1 (last): -"Foo" +// 2 arguments follow +( +// Argument #0: + +// Argument #1 (last): +, "Foo" +) -------- DESER DONE From f5823fad6cb35e96b82822406a5f7de38ca09c5b Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 24 Oct 2019 12:28:27 +0200 Subject: [PATCH 0472/1176] Use `ic.trap` (#782) gives explanations why we trap. --- default.nix | 2 +- src/codegen/compile.ml | 20 ++++++++++++++------ test/run-drun/idl-bad.as | 7 +++++++ test/run-drun/ok/idl-bad.drun-run.ok | 2 ++ 4 files changed, 24 insertions(+), 7 deletions(-) create mode 100644 test/run-drun/idl-bad.as create mode 100644 test/run-drun/ok/idl-bad.drun-run.ok diff --git a/default.nix b/default.nix index e7f1f32206e..81c2fb02fb8 100644 --- a/default.nix +++ b/default.nix @@ -33,7 +33,7 @@ let dev = import (builtins.fetchGit { let dfinity-repo = import (builtins.fetchGit { url = "ssh://git@github.com/dfinity-lab/dfinity"; # ref = "master"; - rev = "be855124bb48c8ff5534fbca1ce8e21e58d78634"; + rev = "50626f51b377c6cdf955b2b41dfae9e550025361"; }) { system = nixpkgs.system; }; in let sdk = import (builtins.fetchGit { diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 7f3500d0144..51ebbda6141 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -685,7 +685,7 @@ module RTS = struct E.call_import env "test" "print" ^^ G.i Unreachable | Flags.ICMode -> - E.call_import env "debug" "print" ^^ + E.call_import env "ic" "trap" ^^ G.i Unreachable | Flags.WasmMode -> G.i Unreachable ) @@ -2989,7 +2989,8 @@ module Dfinity = struct E.add_func_import env "msg" "arg_data_copy" [I64Type; I32Type; I32Type; I32Type] []; E.add_func_import env "msg" "reply" [I64Type; I32Type; I32Type] []; E.add_func_import env "msg" "reject" [I64Type; I32Type] []; - E.add_func_import env "msg" "error_code" [I64Type] [I32Type] + E.add_func_import env "msg" "error_code" [I64Type] [I32Type]; + E.add_func_import env "ic" "trap" [I32Type; I32Type] [] | Flags.AncientMode -> E.add_func_import env "test" "print" [I32Type] []; E.add_func_import env "test" "show_i32" [I32Type] [I32Type]; @@ -3049,11 +3050,18 @@ module Dfinity = struct system_call env "test" "print" ^^ compile_static_print env "\n" - let trap_with env s = - if E.mode env = Flags.WasmMode - then G.i Unreachable - else compile_static_print env (s ^ "\n") ^^ G.i Unreachable + let ic_trap env = + Func.share_code1 env "ic_trap" ("str", I32Type) [] (fun env get_str -> + get_str ^^ Text.payload_ptr_unskewed ^^ + get_str ^^ Heap.load_field (Text.len_field) ^^ + system_call env "ic" "trap" + ) + let trap_with env s = + match E.mode env with + | Flags.WasmMode -> G.i Unreachable + | Flags.AncientMode -> compile_static_print env (s ^ "\n") ^^ G.i Unreachable + | Flags.ICMode -> Text.lit env s ^^ ic_trap env ^^ G.i Unreachable let default_exports env = (* these exports seem to be wanted by the hypervisor/v8 *) diff --git a/test/run-drun/idl-bad.as b/test/run-drun/idl-bad.as new file mode 100644 index 00000000000..2b5b04be855 --- /dev/null +++ b/test/run-drun/idl-bad.as @@ -0,0 +1,7 @@ +actor { + public query func foo() : async () { + }; +} + +//CALL query foo "NOTDIDL" + diff --git a/test/run-drun/ok/idl-bad.drun-run.ok b/test/run-drun/ok/idl-bad.drun-run.ok new file mode 100644 index 00000000000..d01f43ad50d --- /dev/null +++ b/test/run-drun/ok/idl-bad.drun-run.ok @@ -0,0 +1,2 @@ +ingress(0) System +Err: Error { code: ContractViolation, description: "explicit canister trap: IDL error: missing magic bytes" } From b535a263e1b154824c4d58e34dc03e7b15414091 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 24 Oct 2019 13:18:24 +0200 Subject: [PATCH 0473/1176] IDL Decoder: Ignore extra args (vanilla argument list width subtyping) (#757) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * IDL Decoder: Ignore extra args (vanilla argument list width subtyping) the decoder did not ignore extra arguments, as envisioned by the current verison of the IDL. (This would change again a bit if we’d go for #755..) * Fix bug in reference serialization I had an off-by-factor-of-4 bug, which lead to extra references being transmitted. This also uncovered a mild bug with `dvm`, so this depends on https://github.com/dfinity-lab/dev/pull/1117 * Fix dev import * Back to `dev` master * More normalization * Update test output --- default.nix | 2 +- src/codegen/compile.ml | 36 +++++++++++++++++++-------- test/run-drun/idl-nary.as | 6 +++++ test/run-drun/ok/idl-nary.drun-run.ok | 3 +++ test/run.sh | 1 + 5 files changed, 37 insertions(+), 11 deletions(-) diff --git a/default.nix b/default.nix index 81c2fb02fb8..0ed1e680a01 100644 --- a/default.nix +++ b/default.nix @@ -27,7 +27,7 @@ let ocaml_bisect_ppx-ocamlbuild = import ./nix/ocaml-bisect_ppx-ocamlbuild.nix n let dev = import (builtins.fetchGit { url = "ssh://git@github.com/dfinity-lab/dev"; # ref = "master"; - rev = "9030c90efe5b3de33670d4f4f0331482d51c5858"; + rev = "6fca1936fcd027aaeaccab0beb51defeee38a0ff"; }) { system = nixpkgs.system; }; in let dfinity-repo = import (builtins.fetchGit { diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 51ebbda6141..647cd9ad9cd 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -417,9 +417,10 @@ let compile_rotl_const = compile_op_const I32Op.Rotl let compile_bitand_const = compile_op_const I32Op.And let compile_bitor_const = function | 0l -> G.nop | n -> compile_op_const I32Op.Or n -let compile_eq_const i = +let compile_rel_const rel i = compile_unboxed_const i ^^ - G.i (Compare (Wasm.Values.I32 I32Op.Eq)) + G.i (Compare (Wasm.Values.I32 rel)) +let compile_eq_const = compile_rel_const I32Op.Eq let compile_op64_const op i = compile_const_64 i ^^ @@ -1671,6 +1672,10 @@ module ReadBuf = struct G.i (Compare (Wasm.Values.I32 I64Op.LeU)) ^^ E.else_trap_with env "IDL error: out of bounds read" + let is_empty env get_buf = + get_end get_buf ^^ get_ptr get_buf ^^ + G.i (Compare (Wasm.Values.I32 I64Op.Eq)) + let read_byte env get_buf = check_space env get_buf (compile_unboxed_const 1l) ^^ get_ptr get_buf ^^ @@ -4084,7 +4089,6 @@ module Serialization = struct (* Get object sizes *) get_x ^^ buffer_size env (Type.seq ts) ^^ - compile_mul_const Heap.word_size ^^ set_refs_size ^^ compile_add_const tydesc_len ^^ @@ -4094,7 +4098,7 @@ module Serialization = struct let (set_refs_start, get_refs_start) = new_local env "refs_start" in get_data_size ^^ Text.dyn_alloc_scratch env ^^ set_data_start ^^ - get_refs_size ^^ Text.dyn_alloc_scratch env ^^ set_refs_start ^^ + get_refs_size ^^ compile_mul_const Heap.word_size ^^ Text.dyn_alloc_scratch env ^^ set_refs_start ^^ (* Write ty desc *) get_data_start ^^ @@ -4109,7 +4113,7 @@ module Serialization = struct serialize_go env (Type.seq ts) ^^ (* Sanity check: Did we fill exactly the buffer *) - get_refs_start ^^ get_refs_size ^^ G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ + get_refs_start ^^ get_refs_size ^^ compile_mul_const Heap.word_size ^^ G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ G.i (Compare (Wasm.Values.I32 I32Op.Eq)) ^^ E.else_trap_with env "reference buffer not filled " ^^ @@ -4147,6 +4151,7 @@ module Serialization = struct let (set_refs_size, get_refs_size) = new_local env "refs_size" in let (set_data_start, get_data_start) = new_local env "data_start" in let (set_refs_start, get_refs_start) = new_local env "refs_start" in + let (set_arg_count, get_arg_count) = new_local env "arg_count" in begin match E.mode env with | Flags.AncientMode -> @@ -4196,16 +4201,27 @@ module Serialization = struct ReadBuf.set_ptr get_main_typs_buf (get_maintyps_ptr ^^ load_unskewed_ptr) ^^ ReadBuf.set_end get_main_typs_buf (ReadBuf.get_end get_data_buf) ^^ - (* read count *) - ReadBuf.read_leb128 env get_main_typs_buf ^^ - compile_eq_const (Int32.of_int (List.length ts)) ^^ - E.else_trap_with env ("IDL error: wrong arity parsing " ^ ts_name) ^^ + ReadBuf.read_leb128 env get_main_typs_buf ^^ set_arg_count ^^ + + get_arg_count ^^ + compile_rel_const I32Op.GeU (Int32.of_int (List.length ts)) ^^ + E.else_trap_with env ("IDL error: too few arguments " ^ ts_name) ^^ + G.concat_map (fun t -> get_data_buf ^^ get_ref_buf ^^ get_typtbl_ptr ^^ load_unskewed_ptr ^^ ReadBuf.read_sleb128 env get_main_typs_buf ^^ deserialize_go env t - ) ts + ) ts ^^ + + get_arg_count ^^ compile_eq_const (Int32.of_int (List.length ts)) ^^ + G.if_ (ValBlockType None) + begin + ReadBuf.is_empty env get_data_buf ^^ + E.else_trap_with env ("IDL error: left-over bytes " ^ ts_name) ^^ + ReadBuf.is_empty env get_ref_buf ^^ + E.else_trap_with env ("IDL error: left-over references " ^ ts_name) + end G.nop ) ))))) diff --git a/test/run-drun/idl-nary.as b/test/run-drun/idl-nary.as index 4329585d6cb..25284781203 100644 --- a/test/run-drun/idl-nary.as +++ b/test/run-drun/idl-nary.as @@ -45,3 +45,9 @@ actor { //CALL ingress unary4 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 +// too few arguments +//CALL ingress three "DIDL\x00\x02\x71\x71\x03One\x03Two" +// extra bytes (bad) +//CALL ingress three "DIDL\x00\x03\x71\x71\x71\x03One\x03Two\x05ThreeEXTRABYTES" +// extra arguments (ok) +//CALL ingress four "DIDL\x00\x05\x71\x71\x71\x71\x71\x03One\x03Two\x05Three\x04Four\x04Five" diff --git a/test/run-drun/ok/idl-nary.drun-run.ok b/test/run-drun/ok/idl-nary.drun-run.ok index 4fa7f5b6645..0441f484047 100644 --- a/test/run-drun/ok/idl-nary.drun-run.ok +++ b/test/run-drun/ok/idl-nary.drun-run.ok @@ -7,3 +7,6 @@ ingress(5) Completed: Canister: Payload: 0x4449444c016c0400710171027103710100034 ingress(6) Completed: Canister: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 ingress(7) Completed: Canister: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 ingress(8) Completed: Canister: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 +ingress(9) Err: Error { code: ContractViolation, description: "explicit canister trap: IDL error: too few arguments Text,Text,Text" } +ingress(10) Err: Error { code: ContractViolation, description: "explicit canister trap: IDL error: left-over bytes Text,Text,Text" } +ingress(11) Completed: Canister: Payload: 0x4449444c000471717171034f6e650354776f05546872656504466f7572 diff --git a/test/run.sh b/test/run.sh index 2375c6c4cc7..043ffb5e074 100755 --- a/test/run.sh +++ b/test/run.sh @@ -75,6 +75,7 @@ function normalize () { sed 's/prelude:[^:]*:/prelude:___:/g' | sed 's/ calling func\$[0-9]*/ calling func$NNN/g' | sed 's/rip_addr: [0-9]*/rip_addr: XXX/g' | + sed 's,/private/tmp/,/tmp/,g' | sed 's,/tmp/.*dfinity.[^/]*,/tmp/dfinity.XXX,g' | sed 's,/build/.*dfinity.[^/]*,/tmp/dfinity.XXX,g' | sed 's,/tmp/.*ic.[^/]*,/tmp/ic.XXX,g' | From b6f57c36a0bf2e93a51c44db916640bb3fbe2730 Mon Sep 17 00:00:00 2001 From: Enzo Haussecker Date: Fri, 25 Oct 2019 10:47:23 -0700 Subject: [PATCH 0474/1176] Add some basic routines for lists --- stdlib/list.as | 57 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/stdlib/list.as b/stdlib/list.as index 05bab397f13..00f6b767a39 100644 --- a/stdlib/list.as +++ b/stdlib/list.as @@ -495,12 +495,67 @@ public type List = ?(T, List); rec(0) }; + /** + `singleton` + ---------------- + Creates a list with exactly one element. + */ + public func singleton(x : X) : List { + ?(x, null) + }; + + /** + `replicate` + ---------------- + Creates a list of the given length with the same value in each position. + */ + public func replicate(n : Nat, x : X) : List { + tabulate(n, func (_) { x }) + }; + + /** + `zip` + ------------- + Creates a list of pairs from a pair of lists. + */ + public func zip(xs : List, ys : List) : List<(X, Y)> { + zipWith(xs, ys, func (x, y) { (x, y) }) + }; + + /** + `zipWith` + ------------- + Creates a list whose elements are calculated from the given function and + elements occuring at the same position in the given lists. + */ + public func zipWith( + xs : List, + ys : List, + f : (X, Y) -> Z + ) : List { + switch (pop(xs)) { + case (null, _) { + nil() + }; + case (?x, xt) { + switch (pop(ys)) { + case (null, _) { + nil() + }; + case (?y, yt) { + push(f(x, y), zipWith(xt, yt, f)) + } + } + } + } + }; + /** To do: -------- - iterator objects, for use in `for ... in ...` patterns -- operations for lists of pairs and pairs of lists: zip, split, etc +- operations for lists of pairs and pairs of lists: split, etc - more regression tests for everything that is below */ From a4b5f01583000984fc50837f2a99a86efef9974f Mon Sep 17 00:00:00 2001 From: Enzo Haussecker Date: Fri, 25 Oct 2019 12:33:51 -0700 Subject: [PATCH 0475/1176] Add sentance about inconsistent lengths --- stdlib/list.as | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/stdlib/list.as b/stdlib/list.as index 00f6b767a39..92f6fa24cbb 100644 --- a/stdlib/list.as +++ b/stdlib/list.as @@ -516,7 +516,9 @@ public type List = ?(T, List); /** `zip` ------------- - Creates a list of pairs from a pair of lists. + Creates a list of pairs from a pair of lists. If the given lists have + inconsistent lengths, then the list created will have a length equal to the + minimum. */ public func zip(xs : List, ys : List) : List<(X, Y)> { zipWith(xs, ys, func (x, y) { (x, y) }) @@ -526,7 +528,9 @@ public type List = ?(T, List); `zipWith` ------------- Creates a list whose elements are calculated from the given function and - elements occuring at the same position in the given lists. + elements occuring at the same position in the given lists. If the given lists + have inconsistent lengths, then the list created will have a length equal to + the minimum. */ public func zipWith( xs : List, From 8e70700b02c24d329b0c5f5c2d4f6f724f8e00f7 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 28 Oct 2019 09:40:41 +0100 Subject: [PATCH 0476/1176] Implement text comparisons in the backend fixes #791. --- src/codegen/compile.ml | 113 +++++++++++++++++++++++++++++------------ test/run/text-op.as | 29 +++++++++++ 2 files changed, 110 insertions(+), 32 deletions(-) create mode 100644 test/run/text-op.as diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 647cd9ad9cd..f224475098a 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -1012,6 +1012,8 @@ module Bool = struct | false -> compile_unboxed_zero | true -> compile_unboxed_one + let neg = G.i (Test (Wasm.Values.I32 I32Op.Eqz)) + end (* Bool *) @@ -2680,40 +2682,86 @@ module Text = struct get_z ) - (* String comparison. Expects two strings on stack *) - let compare env = - Func.share_code2 env "Text.compare" (("x", I32Type), ("y", I32Type)) [I32Type] (fun env get_x get_y -> - let (set_len1, get_len1) = new_local env "len1" in - let (set_len2, get_len2) = new_local env "len2" in - - get_x ^^ Heap.load_field len_field ^^ set_len1 ^^ - get_y ^^ Heap.load_field len_field ^^ set_len2 ^^ - get_len1 ^^ - get_len2 ^^ - G.i (Compare (Wasm.Values.I32 I32Op.Eq)) ^^ - G.if_ (ValBlockType None) G.nop (Bool.lit false ^^ G.i Return) ^^ + (* String comparison. Expects two strings on stack *) + let rec compare env op = + let open Operator in + let name = match op with + | LtOp -> "Text.compare_lt" + | LeOp -> "Text.compare_le" + | GeOp -> "Text.compare_ge" + | GtOp -> "Text.compare_gt" + | EqOp -> "Text.compare_eq" + | NeqOp -> "Text.compare_ne" in + Func.share_code2 env name (("x", I32Type), ("y", I32Type)) [I32Type] (fun env get_x get_y -> + match op with + (* Some operators can be reduced to the negation of other operators *) + | LtOp -> get_x ^^ get_y ^^ compare env GeOp ^^ Bool.neg + | GtOp -> get_x ^^ get_y ^^ compare env LeOp ^^ Bool.neg + | NeqOp -> get_x ^^ get_y ^^ compare env EqOp ^^ Bool.neg + | _ -> + begin + let (set_len1, get_len1) = new_local env "len1" in + let (set_len2, get_len2) = new_local env "len2" in + let (set_len, get_len) = new_local env "len" in + let (set_a, get_a) = new_local env "a" in + let (set_b, get_b) = new_local env "b" in + + get_x ^^ Heap.load_field len_field ^^ set_len1 ^^ + get_y ^^ Heap.load_field len_field ^^ set_len2 ^^ + + (* Find mininum length *) + begin if op = EqOp then + (* Early exit for equality *) + get_len1 ^^ get_len2 ^^ G.i (Compare (Wasm.Values.I32 I32Op.Eq)) ^^ + G.if_ (ValBlockType None) G.nop (Bool.lit false ^^ G.i Return) ^^ + + get_len1 ^^ set_len + else + get_len1 ^^ get_len2 ^^ G.i (Compare (Wasm.Values.I32 I32Op.LeU)) ^^ + G.if_ (ValBlockType None) + (get_len1 ^^ set_len) + (get_len2 ^^ set_len) + end ^^ - (* We could do word-wise comparisons if we know that the trailing bytes - are zeroed *) - get_len1 ^^ - from_0_to_n env (fun get_i -> - get_x ^^ - payload_ptr_unskewed ^^ - get_i ^^ - G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ - G.i (Load {ty = I32Type; align = 0; offset = 0l; sz = Some (Wasm.Memory.Pack8, Wasm.Memory.ZX)}) ^^ + (* We could do word-wise comparisons if we know that the trailing bytes + are zeroed *) + get_len ^^ + from_0_to_n env (fun get_i -> + get_x ^^ + payload_ptr_unskewed ^^ + get_i ^^ + G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ + G.i (Load {ty = I32Type; align = 0; offset = 0l; sz = Some (Wasm.Memory.Pack8, Wasm.Memory.ZX)}) ^^ + set_a ^^ - get_y ^^ - payload_ptr_unskewed ^^ - get_i ^^ - G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ - G.i (Load {ty = I32Type; align = 0; offset = 0l; sz = Some (Wasm.Memory.Pack8, Wasm.Memory.ZX)}) ^^ - G.i (Compare (Wasm.Values.I32 I32Op.Eq)) ^^ - G.if_ (ValBlockType None) G.nop (Bool.lit false ^^ G.i Return) - ) ^^ - Bool.lit true + get_y ^^ + payload_ptr_unskewed ^^ + get_i ^^ + G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ + G.i (Load {ty = I32Type; align = 0; offset = 0l; sz = Some (Wasm.Memory.Pack8, Wasm.Memory.ZX)}) ^^ + set_b ^^ + + get_a ^^ get_b ^^ G.i (Compare (Wasm.Values.I32 I32Op.Eq)) ^^ + G.if_ (ValBlockType None) G.nop ( + (* first non-equal elements *) + begin match op with + | LeOp -> get_a ^^ get_b ^^ G.i (Compare (Wasm.Values.I32 I32Op.LeU)) + | GeOp -> get_a ^^ get_b ^^ G.i (Compare (Wasm.Values.I32 I32Op.GeU)) + | EqOp -> Bool.lit false + |_ -> assert false + end ^^ + G.i Return + ) + ) ^^ + (* Common prefix is same *) + match op with + | LeOp -> get_len1 ^^ get_len2 ^^ G.i (Compare (Wasm.Values.I32 I32Op.LeU)) + | GeOp -> get_len1 ^^ get_len2 ^^ G.i (Compare (Wasm.Values.I32 I32Op.GeU)) + | EqOp -> Bool.lit true + |_ -> assert false + end ) let prim_decodeUTF8 env = @@ -5882,7 +5930,7 @@ let compile_binop env t op = ) let compile_eq env = function - | Type.(Prim Text) -> Text.compare env + | Type.(Prim Text) -> Text.compare env Operator.EqOp | Type.(Prim Bool) -> G.i (Compare (Wasm.Values.I32 I32Op.Eq)) | Type.(Prim (Nat | Int)) -> BigNum.compile_eq env | Type.(Prim (Int64 | Nat64 | Word64)) -> G.i (Compare (Wasm.Values.I64 I64Op.Eq)) @@ -5914,6 +5962,7 @@ let compile_relop env t op = StackRep.of_type t, let open Operator in match t, op with + | Type.Prim Type.Text, _ -> Text.compare env op | _, EqOp -> compile_eq env t | _, NeqOp -> compile_eq env t ^^ G.i (Test (Wasm.Values.I32 I32Op.Eqz)) @@ -6513,7 +6562,7 @@ and compile_lit_pat env l = compile_eq env Type.(Prim Word64) | TextLit t -> Text.lit env t ^^ - Text.compare env + Text.compare env Operator.EqOp | _ -> todo_trap env "compile_lit_pat" (Arrange_ir.lit l) and fill_pat env ae pat : patternCode = diff --git a/test/run/text-op.as b/test/run/text-op.as new file mode 100644 index 00000000000..9d0304d99cf --- /dev/null +++ b/test/run/text-op.as @@ -0,0 +1,29 @@ +assert ( ("" <= "a")); +assert ( ("" < "a")); +assert (not ("" == "a")); +assert (not ("" >= "a")); +assert (not ("" > "a")); + +assert ( ("a" <= "a")); +assert (not ("a" < "a")); +assert ( ("a" == "a")); +assert ( ("a" >= "a")); +assert (not ("a" > "a")); + +assert ( ("a" <= "aa")); +assert ( ("a" < "aa")); +assert (not ("a" == "aa")); +assert (not ("a" >= "aa")); +assert (not ("a" > "aa")); + +assert ( ("a" <= "aa")); +assert ( ("a" < "aa")); +assert (not ("a" == "aa")); +assert (not ("a" >= "aa")); +assert (not ("a" > "aa")); + +assert ( ("a" <= "ä")); +assert ( ("a" < "ä")); +assert (not ("a" == "ä")); +assert (not ("a" >= "ä")); +assert (not ("a" > "ä")); From 190a0b0b333da7751f75565b931be5b4ea9c8600 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 28 Oct 2019 10:53:52 +0100 Subject: [PATCH 0477/1176] Update test output --- test/run/ok/relational-ops.wasm.stderr.ok | 8 -------- 1 file changed, 8 deletions(-) diff --git a/test/run/ok/relational-ops.wasm.stderr.ok b/test/run/ok/relational-ops.wasm.stderr.ok index 509dff09494..5fd57559c6d 100644 --- a/test/run/ok/relational-ops.wasm.stderr.ok +++ b/test/run/ok/relational-ops.wasm.stderr.ok @@ -22,11 +22,3 @@ compile_relop: GeOp of_type: Float compile_relop: GeOp of_type: Float -compile_relop: LtOp -compile_relop: LtOp -compile_relop: LeOp -compile_relop: LeOp -compile_relop: GtOp -compile_relop: GtOp -compile_relop: GeOp -compile_relop: GeOp From 6a70d64819adbf55b81599e699d292448fb99ae9 Mon Sep 17 00:00:00 2001 From: Enzo Haussecker Date: Mon, 28 Oct 2019 09:40:48 -0700 Subject: [PATCH 0478/1176] Bug fix (#790) --- stdlib/list.as | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/list.as b/stdlib/list.as index 92f6fa24cbb..8fe677571e9 100644 --- a/stdlib/list.as +++ b/stdlib/list.as @@ -263,7 +263,7 @@ public type List = ?(T, List); func rec(l : List) : List { switch l { case null { m }; - case (?(h,t)) {?(h,rec(l))}; + case (?(h,t)) {?(h,rec(t))}; } }; rec(l) From efb29145d95c8e30d15f869dbb38973c6d0e341a Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 28 Oct 2019 18:18:54 +0100 Subject: [PATCH 0479/1176] Mergify: Update name of test that must pass (#797) --- .mergify.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.mergify.yml b/.mergify.yml index 6160fbe6815..14ea4a46616 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -3,7 +3,7 @@ pull_request_rules: conditions: - "#approved-reviews-by>=1" - "#changes-requested-reviews-by=0" - - status-success=hydra:dfinity-ci-build:actorscript:all-systems-go + - status-success=hydra:dfinity-ci-build:motoko:all-systems-go - base=master - label=automerge actions: @@ -15,7 +15,7 @@ pull_request_rules: conditions: - "#approved-reviews-by>=1" - "#changes-requested-reviews-by=0" - - status-success=hydra:dfinity-ci-build:actorscript:all-systems-go + - status-success=hydra:dfinity-ci-build:motoko:all-systems-go - base=master - label=automerge-squash actions: @@ -27,7 +27,7 @@ pull_request_rules: conditions: - "#approved-reviews-by>=1" - "#changes-requested-reviews-by=0" - - status-success=hydra:dfinity-ci-build:actorscript:all-systems-go + - status-success=hydra:dfinity-ci-build:motoko:all-systems-go - base=master - label=automerge-rebase actions: From 9e568e267d57cf1ecf5b3dc71c3c21867caa106a Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 28 Oct 2019 18:33:19 +0100 Subject: [PATCH 0480/1176] Call the heap object Blob, not Text (#796) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Call the heap object Blob, not Text we use it for Text, but not exclusively. So let’s call it Blob. * Update src/codegen/compile.ml Co-Authored-By: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> --- rts/bigint.c | 8 +-- rts/rts.c | 4 +- rts/rts.h | 2 +- src/codegen/compile.ml | 127 +++++++++++++++++++++-------------------- 4 files changed, 73 insertions(+), 68 deletions(-) diff --git a/rts/bigint.c b/rts/bigint.c index ba9ca6d91c8..2a377257f95 100644 --- a/rts/bigint.c +++ b/rts/bigint.c @@ -12,13 +12,13 @@ pointer to a data array. with a dedicated tag for it. * The data array is allocated with mp_calloc and mp_realloc. We provide these - calls, allocate ActorScript arrays (using the TAG_TEXT tag for byte arrays, + calls, allocate ActorScript arrays (using the TAG_BLOB tag for byte arrays, not TAG_ARRAY for arrays of pointers) and store the pointer to the _payload_ in the `mp_digit* dp` field of the struct. This way, things look all nice and dandy from libtommath’s point of view. Our garbage collector has special knowledge about the dp field of the struct - and understands that this pointer points inside the TAG_TEXT heap object. But + and understands that this pointer points inside the TAG_BLOB heap object. But we can still move them around in the GC without issues. The length of the byte array is always equal to the allocation asked for by @@ -30,7 +30,7 @@ pointer to a data array. void* mp_alloc(size_t l) { as_ptr r = alloc_bytes (2*sizeof(void*) + l); - FIELD(r, 0) = TAG_TEXT; // abusing text as byte array here + FIELD(r, 0) = TAG_BLOB; FIELD(r, 1) = l; return &FIELD(r,2); } @@ -48,7 +48,7 @@ export void* mp_calloc(size_t n, size_t size) { export void* mp_realloc(void *ptr, size_t old_size, size_t new_size) { as_ptr r = (as_ptr)(((char *)ptr) - (2 * sizeof(void*) + 1)); - if (FIELD(r, 0) != TAG_TEXT) bigint_trap(); // assert block type + if (FIELD(r, 0) != TAG_BLOB) bigint_trap(); // assert block type if (new_size > FIELD(r, 1)) { void *newptr = mp_alloc(new_size); diff --git a/rts/rts.c b/rts/rts.c index 98a02a95c49..2f2ba743ab2 100644 --- a/rts/rts.c +++ b/rts/rts.c @@ -2,7 +2,7 @@ char *alloc(size_t n) { as_ptr r = alloc_bytes (2*sizeof(void*) + n); - FIELD(r, 0) = TAG_TEXT; + FIELD(r, 0) = TAG_BLOB; FIELD(r, 1) = n; return (char *)&FIELD(r,2); } @@ -23,7 +23,7 @@ size_t as_strlen(const char* p) { as_ptr as_str_of_cstr(const char * const s) { size_t l = as_strlen(s); as_ptr r = alloc_bytes (2*sizeof(void*) + l); - FIELD(r, 0) = TAG_TEXT; + FIELD(r, 0) = TAG_BLOB; FIELD(r, 1) = l; as_memcpy((char *)(&FIELD(r,2)), s, l); return r; diff --git a/rts/rts.h b/rts/rts.h index aee0856cf6c..5d4a668c8c5 100644 --- a/rts/rts.h +++ b/rts/rts.h @@ -32,7 +32,7 @@ enum as_heap_tag { TAG_CLOSURE = 7, TAG_SOME = 8, TAG_VARIANT = 9, - TAG_TEXT = 10, + TAG_BLOB = 10, TAG_INDIRECTION = 11, TAG_SMALLWORD = 12, TAG_BIGINT = 13, diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index f224475098a..247c0627002 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -1100,7 +1100,7 @@ module Tagged = struct | Closure | Some (* For opt *) | Variant - | Text + | Blob | Indirection | SmallWord (* Contains a 32 bit unsigned number *) | BigInt @@ -1116,7 +1116,7 @@ module Tagged = struct | Closure -> 7l | Some -> 8l | Variant -> 9l - | Text -> 10l + | Blob -> 10l | Indirection -> 11l | SmallWord -> 12l | BigInt -> 13l @@ -1184,7 +1184,7 @@ module Tagged = struct | (Prim _ | Obj _ | Opt _ | Variant _ | Func _ | Non) -> false | (Pre | Async _ | Mut _ | Var _ | Typ _) -> assert false end - | Text -> + | Blob -> begin match normalize ty with | (Con _ | Any) -> true | (Prim Text) -> true @@ -2613,14 +2613,17 @@ module Iterators = struct end (* Iterators *) -module Text = struct - (* The layout of a text object is +module Blob = struct + (* The layout of a blob object is ┌─────┬─────────┬──────────────────┐ │ tag │ n_bytes │ bytes (padded) … │ └─────┴─────────┴──────────────────┘ - Note: The bytes are UTF-8 encoded code points from Unicode. + This heap object is used for various kinds of binary, non-pointer data. + + When used for Text values, the bytes are UTF-8 encoded code points from + Unicode. *) let header_size = Int32.add Tagged.header_size 1l @@ -2628,13 +2631,13 @@ module Text = struct let len_field = Int32.add Tagged.header_size 0l let lit env s = - let tag = bytes_of_int32 (Tagged.int_of_tag Tagged.Text) in + let tag = bytes_of_int32 (Tagged.int_of_tag Tagged.Blob) in let len = bytes_of_int32 (Int32.of_int (String.length s)) in let data = tag ^ len ^ s in let ptr = E.add_static_bytes env data in compile_unboxed_const ptr - let alloc env = Func.share_code1 env "text_alloc" ("len", I32Type) [I32Type] (fun env get_len -> + let alloc env = Func.share_code1 env "blob_alloc" ("len", I32Type) [I32Type] (fun env get_len -> let (set_x, get_x) = new_local env "x" in compile_unboxed_const (Int32.mul Heap.word_size header_size) ^^ get_len ^^ @@ -2642,7 +2645,7 @@ module Text = struct Heap.dyn_alloc_bytes env ^^ set_x ^^ - get_x ^^ Tagged.store Tagged.Text ^^ + get_x ^^ Tagged.store Tagged.Blob ^^ get_x ^^ get_len ^^ Heap.store_field len_field ^^ get_x ) @@ -2650,7 +2653,7 @@ module Text = struct let unskewed_payload_offset = Int32.(add ptr_unskew (mul Heap.word_size header_size)) let payload_ptr_unskewed = compile_add_const unskewed_payload_offset - (* String concatenation. Expects two strings on stack *) + (* Blob concatenation. Expects two strings on stack *) let concat env = Func.share_code2 env "concat" (("x", I32Type), ("y", I32Type)) [I32Type] (fun env get_x get_y -> let (set_z, get_z) = new_local env "z" in let (set_len1, get_len1) = new_local env "len1" in @@ -2683,16 +2686,16 @@ module Text = struct ) - (* String comparison. Expects two strings on stack *) + (* Lexicographic blob comparison. Expects two blobs on the stack *) let rec compare env op = let open Operator in let name = match op with - | LtOp -> "Text.compare_lt" - | LeOp -> "Text.compare_le" - | GeOp -> "Text.compare_ge" - | GtOp -> "Text.compare_gt" - | EqOp -> "Text.compare_eq" - | NeqOp -> "Text.compare_ne" in + | LtOp -> "Blob.compare_lt" + | LeOp -> "Blob.compare_le" + | GeOp -> "Blob.compare_ge" + | GtOp -> "Blob.compare_gt" + | EqOp -> "Blob.compare_eq" + | NeqOp -> "Blob.compare_ne" in Func.share_code2 env name (("x", I32Type), ("y", I32Type)) [I32Type] (fun env get_x get_y -> match op with (* Some operators can be reduced to the negation of other operators *) @@ -2764,11 +2767,17 @@ module Text = struct end ) + let dyn_alloc_scratch env = alloc env ^^ payload_ptr_unskewed + +end (* Blob *) + +module Text = struct + let prim_decodeUTF8 env = Func.share_code1 env "decodeUTF8" ("string", I32Type) [I32Type; I32Type] (fun env get_string -> let (set_res, get_res) = new_local env "res" in - get_string ^^ payload_ptr_unskewed ^^ + get_string ^^ Blob.payload_ptr_unskewed ^^ UnboxedSmallWord.len_UTF8_head env set_res ^^ BoxedSmallWord.box env ^^ get_res ^^ UnboxedSmallWord.box_codepoint @@ -2776,10 +2785,10 @@ module Text = struct let text_chars_direct env = Iterators.create env "text_chars_direct" - (fun env get_x -> get_x ^^ Heap.load_field len_field) + (fun env get_x -> get_x ^^ Heap.load_field Blob.len_field) (fun env get_i get_x -> let (set_char, get_char) = new_local env "char" in - get_x ^^ payload_ptr_unskewed ^^ + get_x ^^ Blob.payload_ptr_unskewed ^^ get_i ^^ G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ UnboxedSmallWord.len_UTF8_head env set_char ^^ get_char ^^ UnboxedSmallWord.box_codepoint @@ -2792,11 +2801,11 @@ module Text = struct let (set_len, get_len) = new_local env "len" in compile_unboxed_zero ^^ set_n ^^ compile_unboxed_zero ^^ set_len ^^ - get_x ^^ Heap.load_field len_field ^^ set_max ^^ + get_x ^^ Heap.load_field Blob.len_field ^^ set_max ^^ compile_while (get_n ^^ get_max ^^ G.i (Compare (Wasm.Values.I32 I32Op.LtU))) begin - get_x ^^ payload_ptr_unskewed ^^ get_n ^^ + get_x ^^ Blob.payload_ptr_unskewed ^^ get_n ^^ G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ UnboxedSmallWord.len_UTF8_head env (G.i Drop) ^^ get_n ^^ G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ set_n ^^ @@ -2812,15 +2821,15 @@ module Text = struct let storeLeader bitpat shift = get_c ^^ compile_shrU_const shift ^^ compile_bitor_const bitpat ^^ G.i (Store {ty = I32Type; align = 0; - offset = unskewed_payload_offset; + offset = Blob.unskewed_payload_offset; sz = Some Wasm.Memory.Pack8}) in let storeFollower offset shift = get_c ^^ compile_shrU_const shift ^^ UnboxedSmallWord.compile_6bit_mask ^^ compile_bitor_const 0b10000000l ^^ G.i (Store {ty = I32Type; align = 0; - offset = Int32.add offset unskewed_payload_offset; + offset = Int32.add offset Blob.unskewed_payload_offset; sz = Some Wasm.Memory.Pack8}) in - let allocPayload n = compile_unboxed_const n ^^ alloc env ^^ set_utf8 ^^ get_utf8 in + let allocPayload n = compile_unboxed_const n ^^ Blob.alloc env ^^ set_utf8 ^^ get_utf8 in UnboxedSmallWord.unbox_codepoint ^^ set_c ^^ get_c ^^ @@ -2857,10 +2866,6 @@ module Text = struct end ^^ get_utf8 - (* We also use Text heap objects for byte arrays - (really should rename Text to Bytes) *) - let dyn_alloc_scratch env = alloc env ^^ payload_ptr_unskewed - end (* Text *) module Arr = struct @@ -3068,26 +3073,26 @@ module Dfinity = struct Func.share_code1 env "databuf_of_text" ("string", I32Type) [I32Type] (fun env get_string -> (* Calculate the offset *) get_string ^^ - compile_add_const Int32.(add (mul Heap.word_size Text.header_size) ptr_unskew) ^^ + compile_add_const Int32.(add (mul Heap.word_size Blob.header_size) ptr_unskew) ^^ (* Calculate the length *) get_string ^^ - Heap.load_field (Text.len_field) ^^ + Heap.load_field (Blob.len_field) ^^ (* Externalize *) system_call env "data" "externalize" ) let compile_databuf_of_bytes env (bytes : string) = - Text.lit env bytes ^^ compile_databuf_of_text env + Blob.lit env bytes ^^ compile_databuf_of_text env let prim_print env = match E.mode env with | Flags.WasmMode -> G.i Drop | Flags.ICMode -> Func.share_code1 env "print_text" ("str", I32Type) [] (fun env get_str -> - get_str ^^ Text.payload_ptr_unskewed ^^ - get_str ^^ Heap.load_field (Text.len_field) ^^ + get_str ^^ Blob.payload_ptr_unskewed ^^ + get_str ^^ Heap.load_field (Blob.len_field) ^^ system_call env "debug" "print" ) | Flags.AncientMode -> @@ -3096,7 +3101,7 @@ module Dfinity = struct (* For debugging *) let compile_static_print env s = - Text.lit env s ^^ prim_print env + Blob.lit env s ^^ prim_print env let _compile_println_int env = system_call env "test" "show_i32" ^^ @@ -3105,8 +3110,8 @@ module Dfinity = struct let ic_trap env = Func.share_code1 env "ic_trap" ("str", I32Type) [] (fun env get_str -> - get_str ^^ Text.payload_ptr_unskewed ^^ - get_str ^^ Heap.load_field (Text.len_field) ^^ + get_str ^^ Blob.payload_ptr_unskewed ^^ + get_str ^^ Heap.load_field (Blob.len_field) ^^ system_call env "ic" "trap" ) @@ -3114,7 +3119,7 @@ module Dfinity = struct match E.mode env with | Flags.WasmMode -> G.i Unreachable | Flags.AncientMode -> compile_static_print env (s ^ "\n") ^^ G.i Unreachable - | Flags.ICMode -> Text.lit env s ^^ ic_trap env ^^ G.i Unreachable + | Flags.ICMode -> Blob.lit env s ^^ ic_trap env ^^ G.i Unreachable let default_exports env = (* these exports seem to be wanted by the hypervisor/v8 *) @@ -3322,12 +3327,12 @@ module HeapTraversal = struct get_x ^^ Heap.load_field Arr.len_field ^^ compile_add_const Arr.header_size - ; Tagged.Text, + ; Tagged.Blob, get_x ^^ - Heap.load_field Text.len_field ^^ + Heap.load_field Blob.len_field ^^ compile_add_const 3l ^^ compile_divU_const Heap.word_size ^^ - compile_add_const Text.header_size + compile_add_const Blob.header_size ; Tagged.Object, get_x ^^ Heap.load_field Object.size_field ^^ @@ -3375,7 +3380,7 @@ module HeapTraversal = struct get_x ^^ compile_add_const (Int32.mul Heap.word_size 4l) ^^ set_ptr_loc ^^ - code_offset Text.unskewed_payload_offset + code_offset Blob.unskewed_payload_offset ; Tagged.Some, get_x ^^ compile_add_const (Int32.mul Heap.word_size Opt.payload_field) ^^ @@ -3689,8 +3694,8 @@ module Serialization = struct size env t ) | Prim Text -> - size_word env (get_x ^^ Heap.load_field Text.len_field) ^^ - inc_data_size (get_x ^^ Heap.load_field Text.len_field) + size_word env (get_x ^^ Heap.load_field Blob.len_field) ^^ + inc_data_size (get_x ^^ Heap.load_field Blob.len_field) | Prim Null -> G.nop | Any -> G.nop | Opt t -> @@ -3837,11 +3842,11 @@ module Serialization = struct ( E.trap_with env "serialize_go: unexpected variant" ) | Prim Text -> let (set_len, get_len) = new_local env "len" in - get_x ^^ Heap.load_field Text.len_field ^^ set_len ^^ + get_x ^^ Heap.load_field Blob.len_field ^^ set_len ^^ write_word get_len ^^ get_data_buf ^^ - get_x ^^ Text.payload_ptr_unskewed ^^ + get_x ^^ Blob.payload_ptr_unskewed ^^ get_len ^^ Heap.memcpy env ^^ get_len ^^ advance_data_buf @@ -3977,10 +3982,10 @@ module Serialization = struct let (set_x, get_x) = new_local env "x" in ReadBuf.read_leb128 env get_data_buf ^^ set_len ^^ - get_len ^^ Text.alloc env ^^ set_x ^^ - get_x ^^ Text.payload_ptr_unskewed ^^ + get_len ^^ Blob.alloc env ^^ set_x ^^ + get_x ^^ Blob.payload_ptr_unskewed ^^ ReadBuf.read_blob env get_data_buf get_len ^^ - get_x ^^ Text.payload_ptr_unskewed ^^ get_len ^^ + get_x ^^ Blob.payload_ptr_unskewed ^^ get_len ^^ E.call_import env "rts" "utf8_validate" ^^ get_x @@ -4145,12 +4150,12 @@ module Serialization = struct let (set_data_start, get_data_start) = new_local env "data_start" in let (set_refs_start, get_refs_start) = new_local env "refs_start" in - get_data_size ^^ Text.dyn_alloc_scratch env ^^ set_data_start ^^ - get_refs_size ^^ compile_mul_const Heap.word_size ^^ Text.dyn_alloc_scratch env ^^ set_refs_start ^^ + get_data_size ^^ Blob.dyn_alloc_scratch env ^^ set_data_start ^^ + get_refs_size ^^ compile_mul_const Heap.word_size ^^ Blob.dyn_alloc_scratch env ^^ set_refs_start ^^ (* Write ty desc *) get_data_start ^^ - Text.lit env tydesc ^^ Text.payload_ptr_unskewed ^^ + Blob.lit env tydesc ^^ Blob.payload_ptr_unskewed ^^ compile_unboxed_const tydesc_len ^^ Heap.memcpy env ^^ @@ -4208,19 +4213,19 @@ module Serialization = struct (* Allocate space for the data buffer and copy it *) get_databuf ^^ Dfinity.system_call env "data" "length" ^^ set_data_size ^^ - get_data_size ^^ Text.dyn_alloc_scratch env ^^ set_data_start ^^ + get_data_size ^^ Blob.dyn_alloc_scratch env ^^ set_data_start ^^ get_data_start ^^ get_data_size ^^ get_databuf ^^ compile_unboxed_const 0l ^^ Dfinity.system_call env "data" "internalize" ^^ (* Allocate space for the reference buffer and copy it *) get_elembuf ^^ Dfinity.system_call env "elem" "length" ^^ set_refs_size ^^ - get_refs_size ^^ compile_mul_const Heap.word_size ^^ Text.dyn_alloc_scratch env ^^ set_refs_start ^^ + get_refs_size ^^ compile_mul_const Heap.word_size ^^ Blob.dyn_alloc_scratch env ^^ set_refs_start ^^ get_refs_start ^^ get_refs_size ^^ get_elembuf ^^ compile_unboxed_const 0l ^^ Dfinity.system_call env "elem" "internalize" | Flags.ICMode -> (* Allocate space for the data buffer and copy it *) argument_data_size env ^^ set_data_size ^^ - get_data_size ^^ Text.dyn_alloc_scratch env ^^ set_data_start ^^ + get_data_size ^^ Blob.dyn_alloc_scratch env ^^ set_data_start ^^ argument_data_copy env get_data_start get_data_size ^^ (* Allocate space for the reference buffer and copy it *) @@ -5353,7 +5358,7 @@ let compile_lit env lit = | Nat64Lit n -> SR.UnboxedWord64, compile_const_64 (Big_int.int64_of_big_int (nat64_to_int64 n)) | CharLit c -> SR.Vanilla, compile_unboxed_const Int32.(shift_left (of_int c) 8) | NullLit -> SR.Vanilla, Opt.null - | TextLit t -> SR.Vanilla, Text.lit env t + | TextLit t -> SR.Vanilla, Blob.lit env t | _ -> todo_trap_SR env "compile_lit" (Arrange_ir.lit lit) with Failure _ -> Printf.eprintf "compile_lit: Overflow in literal %s\n" (string_of_lit lit); @@ -5924,13 +5929,13 @@ let compile_binop env t op = get_by ^^ lsb_adjust ty ^^ clamp_shift_amount ty ^^ G.i (Binary (I32 I32Op.Rotr)) ^^ sanitize_word_result ty)) - | Type.Prim Type.Text, CatOp -> Text.concat env + | Type.Prim Type.Text, CatOp -> Blob.concat env | Type.Non, _ -> G.i Unreachable | _ -> todo_trap env "compile_binop" (Arrange_ops.binop op) ) let compile_eq env = function - | Type.(Prim Text) -> Text.compare env Operator.EqOp + | Type.(Prim Text) -> Blob.compare env Operator.EqOp | Type.(Prim Bool) -> G.i (Compare (Wasm.Values.I32 I32Op.Eq)) | Type.(Prim (Nat | Int)) -> BigNum.compile_eq env | Type.(Prim (Int64 | Nat64 | Word64)) -> G.i (Compare (Wasm.Values.I64 I64Op.Eq)) @@ -5962,7 +5967,7 @@ let compile_relop env t op = StackRep.of_type t, let open Operator in match t, op with - | Type.Prim Type.Text, _ -> Text.compare env op + | Type.Prim Type.Text, _ -> Blob.compare env op | _, EqOp -> compile_eq env t | _, NeqOp -> compile_eq env t ^^ G.i (Test (Wasm.Values.I32 I32Op.Eqz)) @@ -6561,8 +6566,8 @@ and compile_lit_pat env l = snd (compile_lit env l) ^^ compile_eq env Type.(Prim Word64) | TextLit t -> - Text.lit env t ^^ - Text.compare env Operator.EqOp + Blob.lit env t ^^ + Blob.compare env Operator.EqOp | _ -> todo_trap env "compile_lit_pat" (Arrange_ir.lit l) and fill_pat env ae pat : patternCode = From 2c19bc6fa3faef599f74bacf1adebbae79725e96 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Mon, 28 Oct 2019 22:40:12 +0000 Subject: [PATCH 0481/1176] add ICCallPrim --- src/ir_def/arrange_ir.ml | 1 + src/ir_def/check_ir.ml | 24 ++++++++++++++++++++++++ src/ir_def/construct.ml | 9 +++++++++ src/ir_def/construct.mli | 1 + src/ir_def/ir.ml | 1 + src/ir_passes/async.ml | 4 +++- 6 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/ir_def/arrange_ir.ml b/src/ir_def/arrange_ir.ml index 48ea27c9e4e..d88e9e320eb 100644 --- a/src/ir_def/arrange_ir.ml +++ b/src/ir_def/arrange_ir.ml @@ -63,6 +63,7 @@ and prim = function | ICReplyPrim ts -> "ICReplyPrim" $$ List.map typ ts | ICRejectPrim -> Atom "ICRejectPrim" | ICErrorCodePrim -> Atom "ICErrorCodePrim" + | ICCallPrim -> Atom "ICCallPrim" and mut = function | Const -> Atom "Const" diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index af5e1f581b8..57704027067 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -359,6 +359,30 @@ let rec check_exp env (exp:Ir.exp) : unit = T.unit <: t | ICErrorCodePrim, [] -> T.Prim (T.Int32) <: t + | ICCallPrim, [exp1; exp2; k; r] -> + check_exp env exp1; + check_exp env exp2; + check_exp env k; + check_exp env r; + let t1 = T.promote (typ exp1) in + begin match t1 with + (* TODO: oneways *) + | T.Func (sort, T.Promises p, [], arg_tys, [T.Async ret_ty]) -> + check_exp env exp2; + let t_arg = T.seq arg_tys in + let t_rets = if (p = 1) then [ret_ty] else T.as_seq ret_ty in + if T.is_shared_sort sort then begin + check_concrete env exp.at t_arg; + check_concrete env exp.at ret_ty; + end; + typ exp2 <: t_arg; + typ k <: T.Func (T.Local, T.Returns, [], t_rets, []); + typ r <: T.Func (T.Local, T.Returns, [], [T.catch], []); + | T.Non -> () (* dead code, not much to check here *) + | _ -> + error env exp1.at "expected function type, but expression produces type\n %s" + (T.string_of_typ_expand t1) + end | OtherPrim _, _ -> () | _ -> error env exp.at "PrimE with wrong number of arguments" diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index 388edf63980..df71e23b081 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -134,6 +134,15 @@ let ic_error_codeE () = note = { note_typ = T.Prim T.Int32; note_eff = T.Triv } } +let ic_callE f e k r = + let es = [f; e; k; r] in + let effs = List.map eff es in + let eff = List.fold_left max_eff T.Triv effs in + { it = PrimE (ICRejectPrim, es); + at = no_region; + note = { note_typ = T.unit; note_eff = eff } + } + (* tuples *) diff --git a/src/ir_def/construct.mli b/src/ir_def/construct.mli index 284e04f658c..873443770d5 100644 --- a/src/ir_def/construct.mli +++ b/src/ir_def/construct.mli @@ -46,6 +46,7 @@ val awaitE : typ -> exp -> exp -> exp val ic_replyE : typ list -> exp -> exp val ic_rejectE : exp -> exp val ic_error_codeE : unit -> exp +val ic_callE : exp -> exp -> exp -> exp -> exp val projE : exp -> int -> exp val blockE : dec list -> exp -> exp val textE : string -> exp diff --git a/src/ir_def/ir.ml b/src/ir_def/ir.ml index 7c6a88213c0..cd9498002b1 100644 --- a/src/ir_def/ir.ml +++ b/src/ir_def/ir.ml @@ -109,6 +109,7 @@ and prim = | ICReplyPrim of Type.typ list | ICRejectPrim | ICErrorCodePrim + | ICCallPrim (* Declarations *) diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index f9f38774e78..fc54b4e5d11 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -79,7 +79,9 @@ module Transform(Platform : sig val platform : platform end) = struct | V1 -> assert (add_reply_argument && not add_reject_argument); callE v1 typs (seqE (vs @ [reply])) - | V2 -> failwith "NYI" (* TODO: call dedicated prim, separating args vs from reply & reject *) + | V2 -> + assert (typs = []); + ic_callE v1 (seqE vs) reply reject let sys_error_codeE () = match platform with From a6f6d5ae27ec52de53bcd39788b0940f1fdcf2d3 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Mon, 28 Oct 2019 22:50:01 +0000 Subject: [PATCH 0482/1176] only reject calls to oneways --- src/as_frontend/typing.ml | 3 ++- src/codegen/compile.ml | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/as_frontend/typing.ml b/src/as_frontend/typing.ml index 678e233fc53..74577daf032 100644 --- a/src/as_frontend/typing.ml +++ b/src/as_frontend/typing.ml @@ -730,7 +730,8 @@ and infer_exp'' env exp : T.typ = if T.is_async t_ret && not in_await then error_in [Flags.ICMode] env exp2.at "shared, async function must be called within an await expression"; - error_in [Flags.ICMode] env exp1.at "calling a shared function not yet supported"; + if t_ret = T.unit then + error_in [Flags.ICMode] env exp1.at "calling a oneway shared function not yet supported"; if not (T.concrete t_arg) then error env exp1.at "shared function argument contains abstract type\n %s" diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 247c0627002..15d55b1e5f6 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -6291,6 +6291,11 @@ and compile_exp (env : E.t) ae exp = assert (E.mode env = Flags.ICMode); Dfinity.error_code env +(* | ICCallPrim, [f;e;k;r] -> + assert (E.mode env = Flags.ICMode); + ... +*) + (* Unknown prim *) | _ -> SR.Unreachable, todo_trap env "compile_exp" (Arrange_ir.exp exp) end From c0ea49227c81b1211e8b4407ee07014758136a17 Mon Sep 17 00:00:00 2001 From: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> Date: Tue, 29 Oct 2019 10:52:37 +0100 Subject: [PATCH 0483/1176] Adds utop to our nix-shell inputs (#802) This allows us to open a repl with our project loaded by executing `dune utop` from within the `src/` directory. --- default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/default.nix b/default.nix index 0ed1e680a01..ed938e7e630 100644 --- a/default.nix +++ b/default.nix @@ -579,7 +579,7 @@ rec { deser.buildInputs ++ tests.buildInputs ++ users-guide.buildInputs ++ - [ nixpkgs.ncurses nixpkgs.ocamlPackages.merlin ] + [ nixpkgs.ncurses nixpkgs.ocamlPackages.merlin nixpkgs.ocamlPackages.utop ] )); shellHook = llvmEnv; From d931ee5b45d7d1e0d1e73bda5d0a82c874499969 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 29 Oct 2019 11:12:46 +0100 Subject: [PATCH 0484/1176] The big Motoko renaming PR (#801) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ActorScript → Motoko * actorScript → motoko * `asc` → `.moc` * `.as` → `.mo` * `as-ld` → `mo-ld` …and so on. --- .gitattributes | 4 +- Building.md | 22 +- README.md | 4 +- ci.nix | 4 +- default.nix | 92 ++++---- design/FAQ.md | 2 +- design/{IDL-AS.md => IDL-Motoko.md} | 96 ++++---- design/IDL.md | 6 +- design/Implementation.md | 2 +- design/Memory.md | 2 +- design/Syntax.md | 2 +- emacs/README.md | 4 +- emacs/init.el | 22 +- emacs/{actorscript-mode.el => motoko-mode.el} | 18 +- guide/.gitignore | 2 +- guide/Makefile | 4 +- guide/as-slides.md | 32 +-- guide/{chat.as => chat.mo} | 0 guide/guide.md | 2 +- guide/{schat.as => schat.mo} | 0 rts/.gitignore | 2 +- rts/Makefile | 8 +- rts/README.md | 16 +- rts/bigint.c | 4 +- rts/rts.h | 8 +- rts/test_leb128.c | 2 +- rts/test_rts.c | 2 +- samples/{ListClient.as => ListClient.mo} | 2 +- samples/ListClient.txt | 16 +- samples/{ListLib.as => ListLib.mo} | 0 samples/ListLib.txt | 8 +- samples/Makefile | 12 +- samples/app/Makefile | 12 +- samples/app/README.md | 4 +- samples/app/{client.as => client.mo} | 2 +- samples/app/{list.as => list.mo} | 0 samples/app/{main.as => main.mo} | 4 +- samples/app/{server.as => server.mo} | 4 +- samples/app/{types.as => types.mo} | 0 samples/{counter.as => counter.mo} | 0 samples/{hoare.as => hoare.mo} | 0 samples/{modules.as => modules.mo} | 0 samples/modules.txt | 8 +- samples/{pa_cars.as => pa_cars.mo} | 0 samples/{quicksort.as => quicksort.mo} | 0 spec/.gitignore | 2 +- spec/Makefile | 2 +- spec/main.tex | 2 +- src/.gitignore | 10 +- src/Makefile | 54 ++--- src/Structure.md | 50 ++--- src/as_config/dune | 3 - src/as_def/dune | 4 - src/as_idl/dune | 4 - src/as_interpreter/dune | 4 - src/as_types/dune | 4 - src/as_values/dune | 4 - src/codegen/compile.ml | 108 ++++----- src/codegen/compile.mli | 2 +- src/codegen/dune | 2 +- src/exes/dune | 12 +- src/exes/{as_ide.ml => mo_ide.ml} | 0 src/exes/{as_ld.ml => mo_ld.ml} | 6 +- src/exes/{asc.ml => moc.ml} | 12 +- src/exes/{asc.mli => moc.mli} | 0 src/ir_def/arrange_ir.ml | 4 +- src/ir_def/check_ir.ml | 4 +- src/ir_def/check_ir.mli | 2 +- src/ir_def/construct.ml | 2 +- src/ir_def/construct.mli | 2 +- src/ir_def/dune | 2 +- src/ir_def/ir.ml | 4 +- src/ir_def/ir_effect.ml | 2 +- src/ir_def/ir_effect.mli | 2 +- src/ir_interpreter/dune | 2 +- src/ir_interpreter/interpret_ir.ml | 4 +- src/ir_interpreter/interpret_ir.mli | 4 +- src/ir_passes/async.ml | 2 +- src/ir_passes/async.mli | 2 +- src/ir_passes/await.ml | 2 +- src/ir_passes/show.ml | 4 +- src/ir_passes/tailcall.ml | 2 +- src/js/dune | 6 +- src/js/{as_js.ml => mo_js.ml} | 6 +- src/languageServer/completion.ml | 4 +- src/languageServer/completion_test.ml | 36 +-- src/languageServer/declaration_index.ml | 6 +- src/languageServer/hover.ml | 2 +- src/languageServer/languageServer.ml | 2 +- src/languageServer/source_file.ml | 2 +- src/lowering/desugar.ml | 8 +- src/lowering/desugar.mli | 4 +- src/lowering/dune | 2 +- src/mo_config/dune | 3 + src/{as_config => mo_config}/flags.ml | 2 +- src/{as_def => mo_def}/arrange.ml | 4 +- src/mo_def/dune | 4 + src/{as_def => mo_def}/syntax.ml | 4 +- src/{as_frontend => mo_frontend}/coverage.ml | 6 +- src/{as_frontend => mo_frontend}/coverage.mli | 4 +- .../definedness.ml | 2 +- .../definedness.mli | 2 +- src/{as_frontend => mo_frontend}/dune | 4 +- src/{as_frontend => mo_frontend}/effect.ml | 4 +- src/{as_frontend => mo_frontend}/effect.mli | 4 +- src/{as_frontend => mo_frontend}/lexer.mli | 0 src/{as_frontend => mo_frontend}/lexer.mll | 2 +- src/{as_frontend => mo_frontend}/parser.mly | 12 +- src/{as_frontend => mo_frontend}/static.ml | 2 +- src/{as_frontend => mo_frontend}/static.mli | 2 +- src/{as_frontend => mo_frontend}/typing.ml | 8 +- src/{as_frontend => mo_frontend}/typing.mli | 4 +- src/mo_idl/dune | 4 + .../as_to_idl.ml => mo_idl/mo_to_idl.ml} | 6 +- src/mo_interpreter/dune | 4 + .../interpret.ml | 8 +- .../interpret.mli | 6 +- src/{as_types => mo_types}/arrange_type.ml | 0 src/{as_types => mo_types}/con.ml | 0 src/{as_types => mo_types}/con.mli | 0 src/mo_types/dune | 4 + src/{as_types => mo_types}/scope.ml | 0 src/{as_types => mo_types}/scope.mli | 0 src/{as_types => mo_types}/type.ml | 4 +- src/{as_types => mo_types}/type.mli | 0 src/{as_values => mo_values}/arrange_ops.ml | 0 src/{as_values => mo_values}/call_conv.ml | 2 +- src/{as_values => mo_values}/call_conv.mli | 2 +- src/mo_values/dune | 4 + src/{as_values => mo_values}/operator.ml | 2 +- src/{as_values => mo_values}/operator.mli | 2 +- src/{as_values => mo_values}/prim.ml | 2 +- src/{as_values => mo_values}/prim.mli | 2 +- src/{as_values => mo_values}/show.ml | 2 +- src/{as_values => mo_values}/show.mli | 2 +- src/{as_values => mo_values}/value.ml | 0 src/{as_values => mo_values}/value.mli | 2 +- src/pipeline/dune | 14 +- src/pipeline/file_path_test.ml | 20 +- src/pipeline/pipeline.ml | 20 +- src/pipeline/pipeline.mli | 6 +- src/pipeline/resolve_import.ml | 4 +- src/pipeline/resolve_import.mli | 2 +- src/prelude/prelude.ml | 2 +- src/profiler/counters.ml | 2 +- src/profiler/dune | 2 +- src/profiler/profiler.ml | 2 +- stdlib/Makefile | 208 +++++++++--------- stdlib/README.md | 8 +- stdlib/{array.as => array.mo} | 0 stdlib/{arrayTest.as => arrayTest.mo} | 6 +- stdlib/{assocList.as => assocList.mo} | 4 +- stdlib/{docTable.as => docTable.mo} | 8 +- stdlib/examples/actorspec/README.md | 2 +- .../actorspec/demo/{Demo.as => Demo.mo} | 2 +- .../src/{ActorSpec.as => ActorSpec.mo} | 6 +- stdlib/examples/produce-exchange/README.md | 60 ++--- .../{profileActor.as => profileActor.mo} | 4 +- .../{serverActor.as => serverActor.mo} | 18 +- .../{serverLang.as => serverLang.mo} | 4 +- .../{serverModel.as => serverModel.mo} | 20 +- ...erverModelTypes.as => serverModelTypes.mo} | 8 +- .../{serverTypes.as => serverTypes.mo} | 2 +- .../test/{evalBulk.as => evalBulk.mo} | 8 +- ...oadAndQuery.as => loadWorkloadAndQuery.mo} | 0 ...QueryBig.as => loadWorkloadAndQueryBig.mo} | 8 +- .../test/{params-5-1.as => params-5-1.mo} | 0 .../test/{params-5-10.as => params-5-10.mo} | 0 .../test/{params-5-100.as => params-5-100.mo} | 0 .../test/{params-5-2.as => params-5-2.mo} | 0 .../test/{params-5-20.as => params-5-20.mo} | 0 .../test/{params-5-3.as => params-5-3.mo} | 0 .../test/{params-5-4.as => params-5-4.mo} | 0 .../test/{params-5-5.as => params-5-5.mo} | 0 .../test/{params-5-50.as => params-5-50.mo} | 0 .../test/{params-5-6.as => params-5-6.mo} | 0 .../test/{params-5-7.as => params-5-7.mo} | 0 .../test/{params-5-8.as => params-5-8.mo} | 0 .../test/{params-5-9.as => params-5-9.mo} | 0 ...emInventory.as => producerRemInventory.mo} | 8 +- ...fileFastCounts.as => profileFastCounts.mo} | 4 +- .../test/{profileLoad.as => profileLoad.mo} | 0 ...rofileLoadQuery.as => profileLoadQuery.mo} | 0 ...rReserveMany.as => retailerReserveMany.mo} | 8 +- ...etupAndQuery.as => simpleSetupAndQuery.mo} | 8 +- stdlib/examples/rx/README.md | 4 +- .../rx/src/{Disposable.as => Disposable.mo} | 0 stdlib/examples/rx/src/{Event.as => Event.mo} | 0 .../rx/src/{Observable.as => Observable.mo} | 4 +- .../rx/src/{Observer.as => Observer.mo} | 2 +- stdlib/examples/rx/src/Rx.as | 4 - stdlib/examples/rx/src/Rx.mo | 4 + .../examples/rx/test/{RxTest.as => RxTest.mo} | 4 +- stdlib/{hash.as => hash.mo} | 0 stdlib/{int.as => int.mo} | 2 +- stdlib/{intTest.as => intTest.mo} | 4 +- stdlib/{list.as => list.mo} | 0 stdlib/{listTest.as => listTest.mo} | 2 +- stdlib/{nat.as => nat.mo} | 4 +- stdlib/{natTest.as => natTest.mo} | 4 +- stdlib/{option.as => option.mo} | 2 +- stdlib/{optionTest.as => optionTest.mo} | 4 +- stdlib/{prelude.as => prelude.mo} | 0 stdlib/{result.as => result.mo} | 4 +- stdlib/{set.as => set.mo} | 4 +- stdlib/{text.as => text.mo} | 0 stdlib/{textTest.as => textTest.mo} | 4 +- stdlib/tools/markdown-of-markdown.py | 4 +- ...f-actorscript.py => markdown-of-motoko.py} | 56 ++--- stdlib/{trie.as => trie.mo} | 8 +- stdlib/{trie2.as => trie2.mo} | 10 +- test/.gitignore | 4 +- test/README.md | 14 +- test/as-idl/Makefile | 4 +- test/as-idl/{counter.as => counter.mo} | 0 test/as-idl/{fields.as => fields.mo} | 0 .../{inline_result.as => inline_result.mo} | 0 test/as-idl/{pa_cars.as => pa_cars.mo} | 0 test/as-idl/{recursion.as => recursion.mo} | 0 test/as-idl/{result.as => result.mo} | 0 test/bugs/{aritybug.as => aritybug.mo} | 8 +- test/bugs/{freeclass1.as => freeclass1.mo} | 0 test/bugs/{sharingbug.as => sharingbug.mo} | 0 .../bugs/{unboundclass.as => unboundclass.mo} | 0 test/bugs/{usedefbug.as => usedefbug.mo} | 0 test/compare-wat.sh | 28 +-- test/fail/{AST-60.as => AST-60.mo} | 0 test/fail/Makefile | 4 +- .../{abstract-msgs.as => abstract-msgs.mo} | 0 test/fail/{actor-match.as => actor-match.mo} | 0 .../{actor-reexport.as => actor-reexport.mo} | 0 ...ent-subtyping.as => argument-subtyping.mo} | 0 test/fail/{ast81-clash.as => ast81-clash.mo} | 0 test/fail/{asyncret1.as => asyncret1.mo} | 0 test/fail/{asyncret2.as => asyncret2.mo} | 0 test/fail/{asyncret3.as => asyncret3.mo} | 0 .../{await-in-actor.as => await-in-actor.mo} | 0 test/fail/{bad-unops.as => bad-unops.mo} | 0 ...fore-define.as => branch-before-define.mo} | 0 ...te-trap.as => char-high-surrogate-trap.mo} | 0 ...gh-surrogate.as => char-high-surrogate.mo} | 0 ...ate-trap.as => char-low-surrogate-trap.mo} | 0 ...low-surrogate.as => char-low-surrogate.mo} | 0 test/fail/{char-trap.as => char-trap.mo} | 0 test/fail/{class.as => class.mo} | 0 ...{const-var-array.as => const-var-array.mo} | 0 ...{const-var-field.as => const-var-field.mo} | 0 .../{cyclic-bound1.as => cyclic-bound1.mo} | 0 .../{cyclic-bound2.as => cyclic-bound2.mo} | 0 .../{cyclic-bound3.as => cyclic-bound3.mo} | 0 .../{cyclic-bound4.as => cyclic-bound4.mo} | 0 .../{cyclic-bound5.as => cyclic-bound5.mo} | 0 test/fail/{debug.as => debug.mo} | 0 test/fail/{decl-clash.as => decl-clash.mo} | 0 ...{duplicate-field.as => duplicate-field.mo} | 0 .../{f-bounds-fail.as => f-bounds-fail.mo} | 0 test/fail/{issue103.as => issue103.mo} | 0 test/fail/{issue167.as => issue167.mo} | 0 test/fail/{issue36.as => issue36.mo} | 0 .../fail/lib/{not-static.as => not-static.mo} | 0 test/fail/{modexp1.as => modexp1.mo} | 0 test/fail/{modexp2.as => modexp2.mo} | 0 test/fail/{modexp3.as => modexp3.mo} | 0 test/fail/{modexp4.as => modexp4.mo} | 0 test/fail/{modexp5.as => modexp5.mo} | 0 test/fail/{modules-fwd.as => modules-fwd.mo} | 0 .../{modules-shadow.as => modules-shadow.mo} | 0 ...s-rec-fail.as => nested-class-rec-fail.mo} | 0 ..._static_module.as => non_static_module.mo} | 0 .../{nonlinear-pat.as => nonlinear-pat.mo} | 0 test/fail/not-static.as | 1 - test/fail/not-static.mo | 1 + ...{object-patterns.as => object-patterns.mo} | 0 ...bjpat-duplicate.as => objpat-duplicate.mo} | 0 .../fail/{objpat-infer.as => objpat-infer.mo} | 0 .../{objpat-mutable.as => objpat-mutable.mo} | 0 test/fail/ok/AST-60.tc.ok | 2 +- test/fail/ok/abstract-msgs.tc.ok | 20 +- test/fail/ok/actor-match.tc.ok | 2 +- test/fail/ok/actor-reexport.tc.ok | 6 +- test/fail/ok/argument-subtyping.tc.ok | 2 +- test/fail/ok/ast81-clash.tc.ok | 2 +- test/fail/ok/asyncret1.tc.ok | 2 +- test/fail/ok/asyncret2.tc.ok | 2 +- test/fail/ok/asyncret3.tc.ok | 2 +- test/fail/ok/await-in-actor.tc.ok | 2 +- test/fail/ok/bad-unops.tc.ok | 16 +- test/fail/ok/branch-before-define.tc.ok | 2 +- test/fail/ok/char-high-surrogate.tc.ok | 2 +- test/fail/ok/char-low-surrogate.tc.ok | 2 +- test/fail/ok/class.tc.ok | 10 +- test/fail/ok/const-var-array.tc.ok | 2 +- test/fail/ok/const-var-field.tc.ok | 2 +- test/fail/ok/cyclic-bound1.tc.ok | 2 +- test/fail/ok/cyclic-bound2.tc.ok | 2 +- test/fail/ok/cyclic-bound3.tc.ok | 2 +- test/fail/ok/cyclic-bound4.tc.ok | 2 +- test/fail/ok/cyclic-bound5.tc.ok | 2 +- test/fail/ok/debug.tc.ok | 2 +- test/fail/ok/decl-clash.tc.ok | 2 +- test/fail/ok/duplicate-field.tc.ok | 2 +- test/fail/ok/f-bounds-fail.tc.ok | 88 ++++---- test/fail/ok/issue103.tc.ok | 8 +- test/fail/ok/issue167.tc.ok | 2 +- test/fail/ok/modexp1.tc.ok | 2 +- test/fail/ok/modexp2.tc.ok | 2 +- test/fail/ok/modexp3.tc.ok | 2 +- test/fail/ok/modexp4.tc.ok | 2 +- test/fail/ok/modexp5.tc.ok | 2 +- test/fail/ok/modules-fwd.tc.ok | 2 +- test/fail/ok/modules-shadow.tc.ok | 2 +- test/fail/ok/nested-class-rec-fail.tc.ok | 2 +- test/fail/ok/non_static_module.tc.ok | 2 +- test/fail/ok/nonlinear-pat.tc.ok | 2 +- test/fail/ok/not-static.tc.ok | 2 +- test/fail/ok/object-patterns.tc.ok | 4 +- test/fail/ok/objpat-duplicate.tc.ok | 4 +- test/fail/ok/objpat-infer.tc.ok | 12 +- test/fail/ok/objpat-mutable.tc.ok | 2 +- test/fail/ok/one-tuple-ambiguity.tc.ok | 2 +- test/fail/ok/pat-inconsistent.tc.ok | 64 +++--- test/fail/ok/pat-subtyping-fail.tc.ok | 64 +++--- test/fail/ok/prim-in-source.tc.ok | 2 +- test/fail/ok/return-before-define.tc.ok | 2 +- test/fail/ok/self-import.tc.ok | 2 +- test/fail/ok/switch-type.tc.ok | 2 +- test/fail/ok/text-high-surrogate.tc.ok | 2 +- test/fail/ok/text-low-surrogate.tc.ok | 2 +- test/fail/ok/typ-field-lub-glb-fail.tc.ok | 8 +- test/fail/ok/use-before-define.tc.ok | 2 +- test/fail/ok/use-before-define2.tc.ok | 2 +- test/fail/ok/use-before-define4.tc.ok | 2 +- test/fail/ok/use-before-define6.tc.ok | 2 +- test/fail/ok/var-const-array.tc.ok | 2 +- test/fail/ok/var-const-field.tc.ok | 2 +- test/fail/ok/word-range.tc.ok | 48 ++-- ...le-ambiguity.as => one-tuple-ambiguity.mo} | 0 ...at-inconsistent.as => pat-inconsistent.mo} | 0 ...ubtyping-fail.as => pat-subtyping-fail.mo} | 0 .../{prim-in-source.as => prim-in-source.mo} | 0 ...fore-define.as => return-before-define.mo} | 0 test/fail/self-import.as | 1 - test/fail/self-import.mo | 1 + test/fail/{switch-type.as => switch-type.mo} | 0 ...gh-surrogate.as => text-high-surrogate.mo} | 0 ...low-surrogate.as => text-low-surrogate.mo} | 0 ...-glb-fail.as => typ-field-lub-glb-fail.mo} | 0 ...-before-define.as => use-before-define.mo} | 0 ...efore-define2.as => use-before-define2.mo} | 0 ...efore-define4.as => use-before-define4.mo} | 0 ...efore-define5.as => use-before-define5.mo} | 0 ...efore-define6.as => use-before-define6.mo} | 0 ...{var-const-array.as => var-const-array.mo} | 0 ...{var-const-field.as => var-const-field.mo} | 0 test/fail/{word-range.as => word-range.mo} | 0 test/ld/Makefile | 4 +- ...rong-type.as-ld.ok => wrong-type.mo-ld.ok} | 0 test/lsp-int/Main.hs | 8 +- .../{ListClient.as => ListClient.mo} | 6 +- test/lsp-int/test-project/{app.as => app.mo} | 2 +- .../lib/{ListFuncs.as => ListFuncs.mo} | 2 +- .../lib/{ListLib.as => ListLib.mo} | 0 .../test-project/lib/{list.as => list.mo} | 0 .../test-project/lib/{option.as => option.mo} | 2 +- .../lib/{prelude.as => prelude.mo} | 0 test/node-test.js | 20 +- test/quick.mk | 8 +- test/random/Main.hs | 14 +- test/random/README.md | 18 +- .../{qc-actorscript.cabal => qc-motoko.cabal} | 6 +- test/repl/double-import.sh | 6 +- test/repl/file-and-repl.sh | 2 +- test/repl/lib/a.as | 1 - test/repl/lib/a.mo | 1 + test/repl/lib/b.as | 1 - test/repl/lib/b.mo | 1 + test/repl/lib/{c.as => c.mo} | 0 test/repl/lib/{empty.as => empty.mo} | 0 test/repl/lib/nested.as | 2 - test/repl/lib/nested.mo | 2 + test/repl/lib/nested/{a.as => a.mo} | 0 test/repl/lib/nested/b.as | 3 - test/repl/lib/nested/b.mo | 3 + test/repl/lib/triangle.as | 1 - test/repl/lib/triangle.mo | 1 + test/repl/nested-import.sh | 4 +- test/repl/ok/double-import.stdout.ok | 10 +- test/repl/ok/file-and-repl.stdout.ok | 2 +- test/repl/ok/nested-import.stdout.ok | 6 +- test/repl/ok/outrange-int-nat.stdout.ok | 2 +- test/repl/ok/stateful.stdout.ok | 2 +- test/repl/ok/triangle-import.stdout.ok | 34 +-- test/repl/ok/type-lub-repl.stdout.ok | 2 +- test/repl/ok/variant-shorthand.stdout.ok | 2 +- test/repl/outrange-int-nat.sh | 2 +- test/repl/stateful.sh | 2 +- test/repl/triangle-import.sh | 10 +- test/repl/type-lub-repl.sh | 2 +- test/repl/variant-shorthand.sh | 2 +- test/run-dfinity/{AST-64.as => AST-64.mo} | 0 test/run-dfinity/{AST-66.as => AST-66.mo} | 0 test/run-dfinity/Makefile | 4 +- .../{arity_bug.as => arity_bug.mo} | 0 ...ut-of-bounds.as => array-out-of-bounds.mo} | 0 .../{async-any.as => async-any.mo} | 0 .../{async-calls.as => async-calls.mo} | 0 ...sync-loop-while.as => async-loop-while.mo} | 0 .../{async-loop.as => async-loop.mo} | 0 .../{async-new-obj.as => async-new-obj.mo} | 0 .../{async-obj-mut.as => async-obj-mut.mo} | 0 .../{async-while.as => async-while.mo} | 0 test/run-dfinity/{await.as => await.mo} | 0 test/run-dfinity/{block.as => block.mo} | 0 test/run-dfinity/{chat.as => chat.mo} | 0 test/run-dfinity/{chatpp.as => chatpp.mo} | 0 .../{closure-params.as => closure-params.mo} | 0 test/run-dfinity/{control.as => control.mo} | 0 .../{counter-class.as => counter-class.mo} | 0 test/run-dfinity/{counter.as => counter.mo} | 0 test/run-dfinity/{counter2.as => counter2.mo} | 0 .../{data-params.as => data-params.mo} | 0 .../{empty-actor.as => empty-actor.mo} | 0 test/run-dfinity/{fac.as => fac.mo} | 0 ...en-awaitables.as => flatten-awaitables.mo} | 0 .../{for-await.as => for-await.mo} | 0 ...mponents.as => general-type-components.mo} | 0 ...eneric-tail-rec.as => generic-tail-rec.mo} | 0 ...-concat-world.as => hello-concat-world.mo} | 0 ...lo-world-async.as => hello-world-async.mo} | 0 ...lo-world-await.as => hello-world-await.mo} | 0 ...orld-message.as => hello-world-message.mo} | 0 ...ld-message2.as => hello-world-message2.mo} | 0 .../{hello-world.as => hello-world.mo} | 0 .../{hello-world2.as => hello-world2.mo} | 0 .../{hello-world3.as => hello-world3.mo} | 0 .../{idl-tuple.as => idl-tuple.mo} | 0 ...ndirect-counter.as => indirect-counter.mo} | 0 .../{large-mem.as => large-mem.mo} | 0 .../{local-throw.as => local-throw.mo} | 0 test/run-dfinity/{log-slow.as => log-slow.mo} | 0 test/run-dfinity/{modexp1.as => modexp1.mo} | 0 test/run-dfinity/{modexp2.as => modexp2.mo} | 0 test/run-dfinity/{modexp3.as => modexp3.mo} | 0 test/run-dfinity/{modexp4.as => modexp4.mo} | 0 .../{modules-bwd.as => modules-bwd.mo} | 0 .../{nary-async.as => nary-async.mo} | 0 .../ok/array-out-of-bounds.run-ir.ok | 4 +- .../ok/array-out-of-bounds.run-low.ok | 4 +- .../run-dfinity/ok/array-out-of-bounds.run.ok | 4 +- test/run-dfinity/ok/data-params.idl.stderr.ok | 2 +- test/run-dfinity/ok/data-params.run-ir.ok | 2 +- test/run-dfinity/ok/data-params.run-low.ok | 2 +- test/run-dfinity/ok/data-params.run.ok | 2 +- test/run-dfinity/ok/data-params.tc.ok | 2 +- .../run-dfinity/ok/data-params.wasm.stderr.ok | 2 +- .../ok/flatten-awaitables.idl.stderr.ok | 48 ++-- .../ok/flatten-awaitables.run-ir.ok | 48 ++-- .../ok/flatten-awaitables.run-low.ok | 48 ++-- test/run-dfinity/ok/flatten-awaitables.run.ok | 48 ++-- test/run-dfinity/ok/flatten-awaitables.tc.ok | 48 ++-- .../ok/flatten-awaitables.wasm.stderr.ok | 48 ++-- test/run-dfinity/ok/overflow.run-ir.ok | 4 +- test/run-dfinity/ok/overflow.run-low.ok | 4 +- test/run-dfinity/ok/overflow.run.ok | 4 +- test/run-dfinity/ok/query.run-ir.ok | 2 +- test/run-dfinity/ok/query.run-low.ok | 2 +- test/run-dfinity/ok/query.run.ok | 2 +- test/run-dfinity/{overflow.as => overflow.mo} | 0 test/run-dfinity/{query.as => query.mo} | 0 ...eference-params.as => reference-params.mo} | 0 test/run-dfinity/{selftail.as => selftail.mo} | 0 .../{shared-object.as => shared-object.mo} | 0 test/run-dfinity/{show.as => show.mo} | 0 .../{simple-throw.as => simple-throw.mo} | 0 .../{tailpositions.as => tailpositions.mo} | 0 .../{text-iter.as => text-iter.mo} | 0 .../{the-answer.as => the-answer.mo} | 0 test/run-dfinity/{tiny.as => tiny.mo} | 0 .../{transpose.as => transpose.mo} | 0 test/run-dfinity/{type-lub.as => type-lub.mo} | 2 +- test/run-drun/Makefile | 4 +- test/run-drun/{counter.as => counter.mo} | 0 ...-world-return.as => hello-world-return.mo} | 0 test/run-drun/{idl-any.as => idl-any.mo} | 0 test/run-drun/{idl-bad.as => idl-bad.mo} | 0 ...dl-field-escape.as => idl-field-escape.mo} | 0 test/run-drun/{idl-func.as => idl-func.mo} | 0 test/run-drun/{idl-nary.as => idl-nary.mo} | 0 .../{idl-nat-int.as => idl-nat-int.mo} | 0 .../run-drun/{idl-option.as => idl-option.mo} | 0 test/run-drun/{idl-pair.as => idl-pair.mo} | 0 .../run-drun/{idl-record.as => idl-record.mo} | 0 test/run-drun/{idl-tuple.as => idl-tuple.mo} | 0 test/run-drun/{idl-unit.as => idl-unit.mo} | 0 .../{idl-variant.as => idl-variant.mo} | 0 .../run-drun/{idl-vector.as => idl-vector.mo} | 0 .../{large-array.as => large-array.mo} | 0 ...{multiple-actors.as => multiple-actors.mo} | 0 test/run-drun/ok/idl-func.tc.ok | 4 +- .../ok/multiple-actors.wasm.stderr.ok | 4 +- test/run-drun/ok/unsupported.tc.ok | 38 ++-- ...{print-from-init.as => print-from-init.mo} | 0 test/run-drun/{query.as => query.mo} | 0 test/run-drun/{reject.as => reject.mo} | 0 .../{unsupported.as => unsupported.mo} | 0 test/run-release/Makefile | 4 +- test/run-release/{debug.as => debug.mo} | 0 test/run.sh | 54 ++--- test/run/{AST-56.as => AST-56.mo} | 0 test/run/Makefile | 4 +- ...fore-init.as => TRAP-write-before-init.mo} | 0 test/run/{array-bounds.as => array-bounds.mo} | 0 test/run/{array-gen.as => array-gen.mo} | 0 test/run/{array.as => array.mo} | 0 test/run/{assert42.as => assert42.mo} | 0 test/run/{assertFalse.as => assertFalse.mo} | 0 test/run/{assertTrue.as => assertTrue.mo} | 0 test/run/{bit-ops.as => bit-ops.mo} | 0 test/run/{call-none.as => call-none.mo} | 0 test/run/{capture-mut.as => capture-mut.mo} | 0 test/run/{char-pats.as => char-pats.mo} | 0 test/run/{closures.as => closures.mo} | 0 test/run/{concat.as => concat.mo} | 0 test/run/{conversions.as => conversions.mo} | 0 test/run/{coverage.as => coverage.mo} | 0 test/run/{debug.as => debug.mo} | 0 .../{eager-and-lazy.as => eager-and-lazy.mo} | 0 .../{empty-tup-args.as => empty-tup-args.mo} | 0 test/run/{empty.as => empty.mo} | 0 test/run/{f-bounds.as => f-bounds.mo} | 0 test/run/{fac.as => fac.mo} | 0 test/run/{fib.as => fib.mo} | 0 test/run/{for.as => for.mo} | 0 test/run/{hashes.as => hashes.mo} | 0 test/run/{hoare.as => hoare.mo} | 0 test/run/{idlHash.as => idlHash.mo} | 0 .../{import-module.as => import-module.mo} | 2 +- test/run/import.as | 2 - test/run/import.mo | 2 + ...litpat-subtype.as => ir-litpat-subtype.mo} | 0 .../{ir-pat-subtype.as => ir-pat-subtype.mo} | 0 test/run/{issue120.as => issue120.mo} | 0 test/run/{issue122.as => issue122.mo} | 0 test/run/{issue129.as => issue129.mo} | 2 +- test/run/{issue135.as => issue135.mo} | 0 test/run/{issue150.as => issue150.mo} | 0 test/run/{issue442.as => issue442.mo} | 0 test/run/{issue537.as => issue537.mo} | 0 test/run/{issue551.as => issue551.mo} | 0 test/run/{issue83.as => issue83.mo} | 0 test/run/{iter-null.as => iter-null.mo} | 0 test/run/{large-mem.as => large-mem.mo} | 0 test/run/{large-tuple.as => large-tuple.mo} | 0 test/run/{last-dec-val.as => last-dec-val.mo} | 0 test/run/{let.as => let.mo} | 0 test/run/{let_fun.as => let_fun.mo} | 0 test/run/lib/{ListM.as => ListM.mo} | 0 test/run/lib/dir/{lib.as => lib.mo} | 0 .../lib/{hello-string.as => hello-string.mo} | 0 test/run/{literals.as => literals.mo} | 0 test/run/{menhir-bug.as => menhir-bug.mo} | 0 test/run/{module1.as => module1.mo} | 0 test/run/{module2.as => module2.mo} | 0 test/run/{module3.as => module3.mo} | 0 test/run/{modulus.as => modulus.mo} | 0 ...{mut-field-bound.as => mut-field-bound.mo} | 0 test/run/{mutrec.as => mutrec.mo} | 0 test/run/{mutrec2.as => mutrec2.mo} | 0 test/run/{mutrec3.as => mutrec3.mo} | 0 test/run/{n-ary.as => n-ary.mo} | 0 test/run/{neg-boundary.as => neg-boundary.mo} | 0 ...ested-class-rec.as => nested-class-rec.mo} | 0 test/run/{nested-eager.as => nested-eager.mo} | 0 test/run/{nested-lexpr.as => nested-lexpr.mo} | 0 test/run/{numeric-ops.as => numeric-ops.mo} | 0 .../{objects-order.as => objects-order.mo} | 0 test/run/{objects1.as => objects1.mo} | 0 test/run/{objects2.as => objects2.mo} | 0 test/run/{objects3.as => objects3.mo} | 0 test/run/{objects4.as => objects4.mo} | 0 test/run/{objects5.as => objects5.mo} | 0 test/run/ok/TRAP-write-before-init.tc.ok | 2 +- test/run/ok/array-bounds.run-ir.ok | 2 +- test/run/ok/array-bounds.run-low.ok | 2 +- test/run/ok/array-bounds.run.ok | 2 +- test/run/ok/assertFalse.run-ir.ok | 2 +- test/run/ok/assertFalse.run-low.ok | 2 +- test/run/ok/assertFalse.run.ok | 2 +- test/run/ok/coverage.idl.stderr.ok | 92 ++++---- test/run/ok/coverage.run-ir.ok | 92 ++++---- test/run/ok/coverage.run-low.ok | 92 ++++---- test/run/ok/coverage.run.ok | 92 ++++---- test/run/ok/coverage.tc.ok | 92 ++++---- test/run/ok/coverage.wasm.stderr.ok | 92 ++++---- test/run/ok/issue442.idl.stderr.ok | 4 +- test/run/ok/issue442.run-ir.ok | 4 +- test/run/ok/issue442.run-low.ok | 4 +- test/run/ok/issue442.run.ok | 4 +- test/run/ok/issue442.tc.ok | 4 +- test/run/ok/issue442.wasm.stderr.ok | 4 +- test/run/ok/large-tuple.idl.stderr.ok | 2 +- test/run/ok/large-tuple.run-ir.ok | 2 +- test/run/ok/large-tuple.run-low.ok | 2 +- test/run/ok/large-tuple.run.ok | 2 +- test/run/ok/large-tuple.tc.ok | 2 +- test/run/ok/large-tuple.wasm.stderr.ok | 2 +- test/run/ok/objects1.idl.stderr.ok | 8 +- test/run/ok/objects1.run-ir.ok | 8 +- test/run/ok/objects1.run-low.ok | 8 +- test/run/ok/objects1.run.ok | 8 +- test/run/ok/objects1.tc.ok | 8 +- test/run/ok/objects1.wasm.stderr.ok | 8 +- test/run/ok/overflow.run-ir.ok | 2 +- test/run/ok/overflow.run-low.ok | 2 +- test/run/ok/overflow.run.ok | 2 +- test/run/ok/pat-subtyping.idl.stderr.ok | 82 +++---- test/run/ok/pat-subtyping.run-ir.ok | 82 +++---- test/run/ok/pat-subtyping.run-low.ok | 82 +++---- test/run/ok/pat-subtyping.run.ok | 82 +++---- test/run/ok/pat-subtyping.tc.ok | 82 +++---- test/run/ok/pat-subtyping.wasm.stderr.ok | 82 +++---- test/run/ok/switch.idl.stderr.ok | 10 +- test/run/ok/switch.run-ir.ok | 10 +- test/run/ok/switch.run-low.ok | 10 +- test/run/ok/switch.run.ok | 10 +- test/run/ok/switch.tc.ok | 10 +- test/run/ok/switch.wasm.stderr.ok | 10 +- test/run/ok/type-inference.idl.stderr.ok | 18 +- test/run/ok/type-inference.run-ir.ok | 18 +- test/run/ok/type-inference.run-low.ok | 18 +- test/run/ok/type-inference.run.ok | 18 +- test/run/ok/type-inference.tc.ok | 18 +- test/run/ok/type-inference.wasm.stderr.ok | 18 +- ...{ott-typeclasses.as => ott-typeclasses.mo} | 0 test/run/{overflow.as => overflow.mo} | 0 .../{pat-subtyping.as => pat-subtyping.mo} | 0 test/run/{prelude.as => prelude.mo} | 0 test/run/{quicksort.as => quicksort.mo} | 0 test/run/{ranged-nums.as => ranged-nums.mo} | 0 test/run/{records.as => records.mo} | 0 .../{relational-ops.as => relational-ops.mo} | 0 test/run/{rts.as => rts.mo} | 0 test/run/{self-bounds.as => self-bounds.mo} | 0 .../{short-circuit.as => short-circuit.mo} | 0 test/run/{signed-div.as => signed-div.mo} | 0 test/run/small-pow.lhs | 2 +- test/run/{small-pow.as => small-pow.mo} | 2 +- ...tatic-func-call.as => static-func-call.mo} | 0 test/run/{sub-negative.as => sub-negative.mo} | 0 test/run/{switch.as => switch.mo} | 0 test/run/{text-concat.as => text-concat.mo} | 0 test/run/{text-op.as => text-op.mo} | 0 test/run/{text-pats.as => text-pats.mo} | 0 test/run/{tuples.as => tuples.mo} | 0 ...-field-lub-glb.as => typ-field-lub-glb.mo} | 0 test/run/{typdecl-last.as => typdecl-last.mo} | 0 ...{type-definition.as => type-definition.mo} | 0 ...ype-equivalence.as => type-equivalence.mo} | 0 .../{type-inclusion.as => type-inclusion.mo} | 0 .../{type-inference.as => type-inference.mo} | 0 .../{underscore-ids.as => underscore-ids.mo} | 0 ...efore-define3.as => use-before-define3.mo} | 0 test/run/{variants.as => variants.mo} | 0 test/run/{while.as => while.mo} | 0 .../{word-rotations.as => word-rotations.mo} | 0 test/run/{words.as => words.mo} | 0 test/test-reproducibility.sh | 8 +- test/trap/Makefile | 22 +- .../{addInt16-lower.as => addInt16-lower.mo} | 0 .../{addInt16-upper.as => addInt16-upper.mo} | 0 .../{addInt32-lower.as => addInt32-lower.mo} | 0 .../{addInt32-upper.as => addInt32-upper.mo} | 0 .../{addInt64-lower.as => addInt64-lower.mo} | 0 .../{addInt64-upper.as => addInt64-upper.mo} | 0 .../{addInt8-lower.as => addInt8-lower.mo} | 0 .../{addInt8-upper.as => addInt8-upper.mo} | 0 test/trap/{addNat16.as => addNat16.mo} | 0 test/trap/{addNat32.as => addNat32.mo} | 0 test/trap/{addNat64.as => addNat64.mo} | 0 test/trap/{addNat8.as => addNat8.mo} | 0 test/trap/{divInt16.as => divInt16.mo} | 0 test/trap/{divInt32.as => divInt32.mo} | 0 test/trap/{divInt64.as => divInt64.mo} | 0 test/trap/{divInt8.as => divInt8.mo} | 0 .../{mulInt16-lower.as => mulInt16-lower.mo} | 0 .../{mulInt16-upper.as => mulInt16-upper.mo} | 0 .../{mulInt32-lower.as => mulInt32-lower.mo} | 0 .../{mulInt32-upper.as => mulInt32-upper.mo} | 0 .../{mulInt64-lower.as => mulInt64-lower.mo} | 0 .../{mulInt64-upper.as => mulInt64-upper.mo} | 0 .../{mulInt8-lower.as => mulInt8-lower.mo} | 0 .../{mulInt8-upper.as => mulInt8-upper.mo} | 0 test/trap/{mulNat16.as => mulNat16.mo} | 0 test/trap/{mulNat32.as => mulNat32.mo} | 0 test/trap/{mulNat64.as => mulNat64.mo} | 0 test/trap/{mulNat8.as => mulNat8.mo} | 0 test/trap/ok/addInt16-lower.run-ir.ok | 2 +- test/trap/ok/addInt16-lower.run-low.ok | 2 +- test/trap/ok/addInt16-lower.run.ok | 2 +- test/trap/ok/addInt16-upper.run-ir.ok | 2 +- test/trap/ok/addInt16-upper.run-low.ok | 2 +- test/trap/ok/addInt16-upper.run.ok | 2 +- test/trap/ok/addInt32-lower.run-ir.ok | 2 +- test/trap/ok/addInt32-lower.run-low.ok | 2 +- test/trap/ok/addInt32-lower.run.ok | 2 +- test/trap/ok/addInt32-upper.run-ir.ok | 2 +- test/trap/ok/addInt32-upper.run-low.ok | 2 +- test/trap/ok/addInt32-upper.run.ok | 2 +- test/trap/ok/addInt64-lower.run-ir.ok | 2 +- test/trap/ok/addInt64-lower.run-low.ok | 2 +- test/trap/ok/addInt64-lower.run.ok | 2 +- test/trap/ok/addInt64-upper.run-ir.ok | 2 +- test/trap/ok/addInt64-upper.run-low.ok | 2 +- test/trap/ok/addInt64-upper.run.ok | 2 +- test/trap/ok/addInt8-lower.run-ir.ok | 2 +- test/trap/ok/addInt8-lower.run-low.ok | 2 +- test/trap/ok/addInt8-lower.run.ok | 2 +- test/trap/ok/addInt8-upper.run-ir.ok | 2 +- test/trap/ok/addInt8-upper.run-low.ok | 2 +- test/trap/ok/addInt8-upper.run.ok | 2 +- test/trap/ok/addNat16.run-ir.ok | 2 +- test/trap/ok/addNat16.run-low.ok | 2 +- test/trap/ok/addNat16.run.ok | 2 +- test/trap/ok/addNat32.run-ir.ok | 2 +- test/trap/ok/addNat32.run-low.ok | 2 +- test/trap/ok/addNat32.run.ok | 2 +- test/trap/ok/addNat64.run-ir.ok | 2 +- test/trap/ok/addNat64.run-low.ok | 2 +- test/trap/ok/addNat64.run.ok | 2 +- test/trap/ok/addNat8.run-ir.ok | 2 +- test/trap/ok/addNat8.run-low.ok | 2 +- test/trap/ok/addNat8.run.ok | 2 +- test/trap/ok/divInt16.run-ir.ok | 2 +- test/trap/ok/divInt16.run-low.ok | 2 +- test/trap/ok/divInt16.run.ok | 2 +- test/trap/ok/divInt32.run-ir.ok | 2 +- test/trap/ok/divInt32.run-low.ok | 2 +- test/trap/ok/divInt32.run.ok | 2 +- test/trap/ok/divInt64.run-ir.ok | 2 +- test/trap/ok/divInt64.run-low.ok | 2 +- test/trap/ok/divInt64.run.ok | 2 +- test/trap/ok/divInt8.run-ir.ok | 2 +- test/trap/ok/divInt8.run-low.ok | 2 +- test/trap/ok/divInt8.run.ok | 2 +- test/trap/ok/mulInt16-lower.run-ir.ok | 2 +- test/trap/ok/mulInt16-lower.run-low.ok | 2 +- test/trap/ok/mulInt16-lower.run.ok | 2 +- test/trap/ok/mulInt16-upper.run-ir.ok | 2 +- test/trap/ok/mulInt16-upper.run-low.ok | 2 +- test/trap/ok/mulInt16-upper.run.ok | 2 +- test/trap/ok/mulInt32-lower.run-ir.ok | 2 +- test/trap/ok/mulInt32-lower.run-low.ok | 2 +- test/trap/ok/mulInt32-lower.run.ok | 2 +- test/trap/ok/mulInt32-upper.run-ir.ok | 2 +- test/trap/ok/mulInt32-upper.run-low.ok | 2 +- test/trap/ok/mulInt32-upper.run.ok | 2 +- test/trap/ok/mulInt64-lower.run-ir.ok | 2 +- test/trap/ok/mulInt64-lower.run-low.ok | 2 +- test/trap/ok/mulInt64-lower.run.ok | 2 +- test/trap/ok/mulInt64-upper.run-ir.ok | 2 +- test/trap/ok/mulInt64-upper.run-low.ok | 2 +- test/trap/ok/mulInt64-upper.run.ok | 2 +- test/trap/ok/mulInt8-lower.run-ir.ok | 2 +- test/trap/ok/mulInt8-lower.run-low.ok | 2 +- test/trap/ok/mulInt8-lower.run.ok | 2 +- test/trap/ok/mulInt8-upper.run-ir.ok | 2 +- test/trap/ok/mulInt8-upper.run-low.ok | 2 +- test/trap/ok/mulInt8-upper.run.ok | 2 +- test/trap/ok/mulNat16.run-ir.ok | 2 +- test/trap/ok/mulNat16.run-low.ok | 2 +- test/trap/ok/mulNat16.run.ok | 2 +- test/trap/ok/mulNat32.run-ir.ok | 2 +- test/trap/ok/mulNat32.run-low.ok | 2 +- test/trap/ok/mulNat32.run.ok | 2 +- test/trap/ok/mulNat64.run-ir.ok | 2 +- test/trap/ok/mulNat64.run-low.ok | 2 +- test/trap/ok/mulNat64.run.ok | 2 +- test/trap/ok/mulNat8.run-ir.ok | 2 +- test/trap/ok/mulNat8.run-low.ok | 2 +- test/trap/ok/mulNat8.run.ok | 2 +- .../trap/ok/outrange-int16-negation.run-ir.ok | 2 +- .../ok/outrange-int16-negation.run-low.ok | 2 +- test/trap/ok/outrange-int16-negation.run.ok | 2 +- .../trap/ok/outrange-int32-negation.run-ir.ok | 2 +- .../ok/outrange-int32-negation.run-low.ok | 2 +- test/trap/ok/outrange-int32-negation.run.ok | 2 +- .../trap/ok/outrange-int64-negation.run-ir.ok | 2 +- .../ok/outrange-int64-negation.run-low.ok | 2 +- test/trap/ok/outrange-int64-negation.run.ok | 2 +- test/trap/ok/outrange-int8-negation.run-ir.ok | 2 +- .../trap/ok/outrange-int8-negation.run-low.ok | 2 +- test/trap/ok/outrange-int8-negation.run.ok | 2 +- test/trap/ok/powInt32-lower.run-ir.ok | 2 +- test/trap/ok/powInt32-lower.run-low.ok | 2 +- test/trap/ok/powInt32-lower.run.ok | 2 +- test/trap/ok/powInt32-raise-neg.run-ir.ok | 2 +- test/trap/ok/powInt32-raise-neg.run-low.ok | 2 +- test/trap/ok/powInt32-raise-neg.run.ok | 2 +- test/trap/ok/powInt32-upper.run-ir.ok | 2 +- test/trap/ok/powInt32-upper.run-low.ok | 2 +- test/trap/ok/powInt32-upper.run.ok | 2 +- test/trap/ok/powInt64-lower-fast.run-ir.ok | 2 +- test/trap/ok/powInt64-lower-fast.run-low.ok | 2 +- test/trap/ok/powInt64-lower-fast.run.ok | 2 +- test/trap/ok/powInt64-lower-slow.run-ir.ok | 2 +- test/trap/ok/powInt64-lower-slow.run-low.ok | 2 +- test/trap/ok/powInt64-lower-slow.run.ok | 2 +- test/trap/ok/powInt64-raise-neg.run-ir.ok | 2 +- test/trap/ok/powInt64-raise-neg.run-low.ok | 2 +- test/trap/ok/powInt64-raise-neg.run.ok | 2 +- test/trap/ok/powInt64-upper-fast.run-ir.ok | 2 +- test/trap/ok/powInt64-upper-fast.run-low.ok | 2 +- test/trap/ok/powInt64-upper-fast.run.ok | 2 +- test/trap/ok/powInt64-upper-slow.run-ir.ok | 2 +- test/trap/ok/powInt64-upper-slow.run-low.ok | 2 +- test/trap/ok/powInt64-upper-slow.run.ok | 2 +- test/trap/ok/powInt8-lower.run-ir.ok | 2 +- test/trap/ok/powInt8-lower.run-low.ok | 2 +- test/trap/ok/powInt8-lower.run.ok | 2 +- test/trap/ok/powInt8-raise-neg.run-ir.ok | 2 +- test/trap/ok/powInt8-raise-neg.run-low.ok | 2 +- test/trap/ok/powInt8-raise-neg.run.ok | 2 +- test/trap/ok/powInt8-upper.run-ir.ok | 2 +- test/trap/ok/powInt8-upper.run-low.ok | 2 +- test/trap/ok/powInt8-upper.run.ok | 2 +- test/trap/ok/powNat16.run-ir.ok | 2 +- test/trap/ok/powNat16.run-low.ok | 2 +- test/trap/ok/powNat16.run.ok | 2 +- test/trap/ok/powNat32.run-ir.ok | 2 +- test/trap/ok/powNat32.run-low.ok | 2 +- test/trap/ok/powNat32.run.ok | 2 +- test/trap/ok/powNat64.run-ir.ok | 2 +- test/trap/ok/powNat64.run-low.ok | 2 +- test/trap/ok/powNat64.run.ok | 2 +- test/trap/ok/powNat8.run-ir.ok | 2 +- test/trap/ok/powNat8.run-low.ok | 2 +- test/trap/ok/powNat8.run.ok | 2 +- test/trap/ok/subInt16-lower.run-ir.ok | 2 +- test/trap/ok/subInt16-lower.run-low.ok | 2 +- test/trap/ok/subInt16-lower.run.ok | 2 +- test/trap/ok/subInt16-upper.run-ir.ok | 2 +- test/trap/ok/subInt16-upper.run-low.ok | 2 +- test/trap/ok/subInt16-upper.run.ok | 2 +- test/trap/ok/subInt32-lower.run-ir.ok | 2 +- test/trap/ok/subInt32-lower.run-low.ok | 2 +- test/trap/ok/subInt32-lower.run.ok | 2 +- test/trap/ok/subInt32-upper.run-ir.ok | 2 +- test/trap/ok/subInt32-upper.run-low.ok | 2 +- test/trap/ok/subInt32-upper.run.ok | 2 +- test/trap/ok/subInt64-lower.run-ir.ok | 2 +- test/trap/ok/subInt64-lower.run-low.ok | 2 +- test/trap/ok/subInt64-lower.run.ok | 2 +- test/trap/ok/subInt64-upper.run-ir.ok | 2 +- test/trap/ok/subInt64-upper.run-low.ok | 2 +- test/trap/ok/subInt64-upper.run.ok | 2 +- test/trap/ok/subInt8-lower.run-ir.ok | 2 +- test/trap/ok/subInt8-lower.run-low.ok | 2 +- test/trap/ok/subInt8-lower.run.ok | 2 +- test/trap/ok/subInt8-upper.run-ir.ok | 2 +- test/trap/ok/subInt8-upper.run-low.ok | 2 +- test/trap/ok/subInt8-upper.run.ok | 2 +- test/trap/ok/subNat16.run-ir.ok | 2 +- test/trap/ok/subNat16.run-low.ok | 2 +- test/trap/ok/subNat16.run.ok | 2 +- test/trap/ok/subNat32.run-ir.ok | 2 +- test/trap/ok/subNat32.run-low.ok | 2 +- test/trap/ok/subNat32.run.ok | 2 +- test/trap/ok/subNat64-slow.run-ir.ok | 2 +- test/trap/ok/subNat64-slow.run-low.ok | 2 +- test/trap/ok/subNat64-slow.run.ok | 2 +- test/trap/ok/subNat64.run-ir.ok | 2 +- test/trap/ok/subNat64.run-low.ok | 2 +- test/trap/ok/subNat64.run.ok | 2 +- test/trap/ok/subNat8.run-ir.ok | 2 +- test/trap/ok/subNat8.run-low.ok | 2 +- test/trap/ok/subNat8.run.ok | 2 +- ...int16-lower.as => outrange-int16-lower.mo} | 0 ...negation.as => outrange-int16-negation.mo} | 0 ...int16-upper.as => outrange-int16-upper.mo} | 0 ...int32-lower.as => outrange-int32-lower.mo} | 0 ...negation.as => outrange-int32-negation.mo} | 0 ...int32-upper.as => outrange-int32-upper.mo} | 0 ...int64-lower.as => outrange-int64-lower.mo} | 0 ...negation.as => outrange-int64-negation.mo} | 0 ...int64-upper.as => outrange-int64-upper.mo} | 0 ...e-int8-lower.as => outrange-int8-lower.mo} | 0 ...-negation.as => outrange-int8-negation.mo} | 0 ...e-int8-upper.as => outrange-int8-upper.mo} | 0 .../{outrange-nat16.as => outrange-nat16.mo} | 0 .../{outrange-nat32.as => outrange-nat32.mo} | 0 .../{outrange-nat64.as => outrange-nat64.mo} | 0 .../{outrange-nat8.as => outrange-nat8.mo} | 0 .../{powInt32-lower.as => powInt32-lower.mo} | 0 ...t32-raise-neg.as => powInt32-raise-neg.mo} | 0 .../{powInt32-upper.as => powInt32-upper.mo} | 0 ...4-lower-fast.as => powInt64-lower-fast.mo} | 0 ...4-lower-slow.as => powInt64-lower-slow.mo} | 0 ...t64-raise-neg.as => powInt64-raise-neg.mo} | 0 ...4-upper-fast.as => powInt64-upper-fast.mo} | 0 ...4-upper-slow.as => powInt64-upper-slow.mo} | 0 .../{powInt8-lower.as => powInt8-lower.mo} | 0 ...Int8-raise-neg.as => powInt8-raise-neg.mo} | 0 .../{powInt8-upper.as => powInt8-upper.mo} | 0 test/trap/{powNat16.as => powNat16.mo} | 0 test/trap/{powNat32.as => powNat32.mo} | 0 test/trap/{powNat64.as => powNat64.mo} | 0 test/trap/{powNat8.as => powNat8.mo} | 0 .../{subInt16-lower.as => subInt16-lower.mo} | 0 .../{subInt16-upper.as => subInt16-upper.mo} | 0 .../{subInt32-lower.as => subInt32-lower.mo} | 0 .../{subInt32-upper.as => subInt32-upper.mo} | 0 .../{subInt64-lower.as => subInt64-lower.mo} | 0 .../{subInt64-upper.as => subInt64-upper.mo} | 0 .../{subInt8-lower.as => subInt8-lower.mo} | 0 .../{subInt8-upper.as => subInt8-upper.mo} | 0 test/trap/{subNat16.as => subNat16.mo} | 0 test/trap/{subNat32.as => subNat32.mo} | 0 .../{subNat64-slow.as => subNat64-slow.mo} | 0 test/trap/{subNat64.as => subNat64.mo} | 0 test/trap/{subNat8.as => subNat8.mo} | 0 920 files changed, 2230 insertions(+), 2230 deletions(-) rename design/{IDL-AS.md => IDL-Motoko.md} (71%) rename emacs/{actorscript-mode.el => motoko-mode.el} (90%) rename guide/{chat.as => chat.mo} (100%) rename guide/{schat.as => schat.mo} (100%) rename samples/{ListClient.as => ListClient.mo} (72%) rename samples/{ListLib.as => ListLib.mo} (100%) rename samples/app/{client.as => client.mo} (95%) rename samples/app/{list.as => list.mo} (100%) rename samples/app/{main.as => main.mo} (78%) rename samples/app/{server.as => server.mo} (97%) rename samples/app/{types.as => types.mo} (100%) rename samples/{counter.as => counter.mo} (100%) rename samples/{hoare.as => hoare.mo} (100%) rename samples/{modules.as => modules.mo} (100%) rename samples/{pa_cars.as => pa_cars.mo} (100%) rename samples/{quicksort.as => quicksort.mo} (100%) delete mode 100644 src/as_config/dune delete mode 100644 src/as_def/dune delete mode 100644 src/as_idl/dune delete mode 100644 src/as_interpreter/dune delete mode 100644 src/as_types/dune delete mode 100644 src/as_values/dune rename src/exes/{as_ide.ml => mo_ide.ml} (100%) rename src/exes/{as_ld.ml => mo_ld.ml} (92%) rename src/exes/{asc.ml => moc.ml} (95%) rename src/exes/{asc.mli => moc.mli} (100%) rename src/js/{as_js.ml => mo_js.ml} (95%) create mode 100644 src/mo_config/dune rename src/{as_config => mo_config}/flags.ml (93%) rename src/{as_def => mo_def}/arrange.ml (99%) create mode 100644 src/mo_def/dune rename src/{as_def => mo_def}/syntax.ml (99%) rename src/{as_frontend => mo_frontend}/coverage.ml (99%) rename src/{as_frontend => mo_frontend}/coverage.mli (81%) rename src/{as_frontend => mo_frontend}/definedness.ml (99%) rename src/{as_frontend => mo_frontend}/definedness.mli (80%) rename src/{as_frontend => mo_frontend}/dune (53%) rename src/{as_frontend => mo_frontend}/effect.ml (99%) rename src/{as_frontend => mo_frontend}/effect.mli (94%) rename src/{as_frontend => mo_frontend}/lexer.mli (100%) rename src/{as_frontend => mo_frontend}/lexer.mll (99%) rename src/{as_frontend => mo_frontend}/parser.mly (98%) rename src/{as_frontend => mo_frontend}/static.ml (99%) rename src/{as_frontend => mo_frontend}/static.mli (92%) rename src/{as_frontend => mo_frontend}/typing.ml (99%) rename src/{as_frontend => mo_frontend}/typing.mli (89%) create mode 100644 src/mo_idl/dune rename src/{as_idl/as_to_idl.ml => mo_idl/mo_to_idl.ml} (98%) create mode 100644 src/mo_interpreter/dune rename src/{as_interpreter => mo_interpreter}/interpret.ml (99%) rename src/{as_interpreter => mo_interpreter}/interpret.mli (91%) rename src/{as_types => mo_types}/arrange_type.ml (100%) rename src/{as_types => mo_types}/con.ml (100%) rename src/{as_types => mo_types}/con.mli (100%) create mode 100644 src/mo_types/dune rename src/{as_types => mo_types}/scope.ml (100%) rename src/{as_types => mo_types}/scope.mli (100%) rename src/{as_types => mo_types}/type.ml (99%) rename src/{as_types => mo_types}/type.mli (100%) rename src/{as_values => mo_values}/arrange_ops.ml (100%) rename src/{as_values => mo_values}/call_conv.ml (98%) rename src/{as_values => mo_values}/call_conv.mli (96%) create mode 100644 src/mo_values/dune rename src/{as_values => mo_values}/operator.ml (99%) rename src/{as_values => mo_values}/operator.mli (98%) rename src/{as_values => mo_values}/prim.ml (99%) rename src/{as_values => mo_values}/prim.mli (86%) rename src/{as_values => mo_values}/show.ml (99%) rename src/{as_values => mo_values}/show.mli (85%) rename src/{as_values => mo_values}/value.ml (100%) rename src/{as_values => mo_values}/value.mli (99%) rename stdlib/{array.as => array.mo} (100%) rename stdlib/{arrayTest.as => arrayTest.mo} (97%) rename stdlib/{assocList.as => assocList.mo} (98%) rename stdlib/{docTable.as => docTable.mo} (97%) rename stdlib/examples/actorspec/demo/{Demo.as => Demo.mo} (94%) rename stdlib/examples/actorspec/src/{ActorSpec.as => ActorSpec.mo} (97%) rename stdlib/examples/produce-exchange/{profileActor.as => profileActor.mo} (91%) rename stdlib/examples/produce-exchange/{serverActor.as => serverActor.mo} (98%) rename stdlib/examples/produce-exchange/{serverLang.as => serverLang.mo} (98%) rename stdlib/examples/produce-exchange/{serverModel.as => serverModel.mo} (99%) rename stdlib/examples/produce-exchange/{serverModelTypes.as => serverModelTypes.mo} (98%) rename stdlib/examples/produce-exchange/{serverTypes.as => serverTypes.mo} (99%) rename stdlib/examples/produce-exchange/test/{evalBulk.as => evalBulk.mo} (98%) rename stdlib/examples/produce-exchange/test/{loadWorkloadAndQuery.as => loadWorkloadAndQuery.mo} (100%) rename stdlib/examples/produce-exchange/test/{loadWorkloadAndQueryBig.as => loadWorkloadAndQueryBig.mo} (96%) rename stdlib/examples/produce-exchange/test/{params-5-1.as => params-5-1.mo} (100%) rename stdlib/examples/produce-exchange/test/{params-5-10.as => params-5-10.mo} (100%) rename stdlib/examples/produce-exchange/test/{params-5-100.as => params-5-100.mo} (100%) rename stdlib/examples/produce-exchange/test/{params-5-2.as => params-5-2.mo} (100%) rename stdlib/examples/produce-exchange/test/{params-5-20.as => params-5-20.mo} (100%) rename stdlib/examples/produce-exchange/test/{params-5-3.as => params-5-3.mo} (100%) rename stdlib/examples/produce-exchange/test/{params-5-4.as => params-5-4.mo} (100%) rename stdlib/examples/produce-exchange/test/{params-5-5.as => params-5-5.mo} (100%) rename stdlib/examples/produce-exchange/test/{params-5-50.as => params-5-50.mo} (100%) rename stdlib/examples/produce-exchange/test/{params-5-6.as => params-5-6.mo} (100%) rename stdlib/examples/produce-exchange/test/{params-5-7.as => params-5-7.mo} (100%) rename stdlib/examples/produce-exchange/test/{params-5-8.as => params-5-8.mo} (100%) rename stdlib/examples/produce-exchange/test/{params-5-9.as => params-5-9.mo} (100%) rename stdlib/examples/produce-exchange/test/{producerRemInventory.as => producerRemInventory.mo} (98%) rename stdlib/examples/produce-exchange/test/{profileFastCounts.as => profileFastCounts.mo} (88%) rename stdlib/examples/produce-exchange/test/{profileLoad.as => profileLoad.mo} (100%) rename stdlib/examples/produce-exchange/test/{profileLoadQuery.as => profileLoadQuery.mo} (100%) rename stdlib/examples/produce-exchange/test/{retailerReserveMany.as => retailerReserveMany.mo} (98%) rename stdlib/examples/produce-exchange/test/{simpleSetupAndQuery.as => simpleSetupAndQuery.mo} (99%) rename stdlib/examples/rx/src/{Disposable.as => Disposable.mo} (100%) rename stdlib/examples/rx/src/{Event.as => Event.mo} (100%) rename stdlib/examples/rx/src/{Observable.as => Observable.mo} (83%) rename stdlib/examples/rx/src/{Observer.as => Observer.mo} (95%) delete mode 100644 stdlib/examples/rx/src/Rx.as create mode 100644 stdlib/examples/rx/src/Rx.mo rename stdlib/examples/rx/test/{RxTest.as => RxTest.mo} (97%) rename stdlib/{hash.as => hash.mo} (100%) rename stdlib/{int.as => int.mo} (95%) rename stdlib/{intTest.as => intTest.mo} (90%) rename stdlib/{list.as => list.mo} (100%) rename stdlib/{listTest.as => listTest.mo} (98%) rename stdlib/{nat.as => nat.mo} (71%) rename stdlib/{natTest.as => natTest.mo} (88%) rename stdlib/{option.as => option.mo} (99%) rename stdlib/{optionTest.as => optionTest.mo} (98%) rename stdlib/{prelude.as => prelude.mo} (100%) rename stdlib/{result.as => result.mo} (96%) rename stdlib/{set.as => set.mo} (97%) rename stdlib/{text.as => text.mo} (100%) rename stdlib/{textTest.as => textTest.mo} (75%) rename stdlib/tools/{markdown-of-actorscript.py => markdown-of-motoko.py} (80%) rename stdlib/{trie.as => trie.mo} (99%) rename stdlib/{trie2.as => trie2.mo} (99%) rename test/as-idl/{counter.as => counter.mo} (100%) rename test/as-idl/{fields.as => fields.mo} (100%) rename test/as-idl/{inline_result.as => inline_result.mo} (100%) rename test/as-idl/{pa_cars.as => pa_cars.mo} (100%) rename test/as-idl/{recursion.as => recursion.mo} (100%) rename test/as-idl/{result.as => result.mo} (100%) rename test/bugs/{aritybug.as => aritybug.mo} (53%) rename test/bugs/{freeclass1.as => freeclass1.mo} (100%) rename test/bugs/{sharingbug.as => sharingbug.mo} (100%) rename test/bugs/{unboundclass.as => unboundclass.mo} (100%) rename test/bugs/{usedefbug.as => usedefbug.mo} (100%) rename test/fail/{AST-60.as => AST-60.mo} (100%) rename test/fail/{abstract-msgs.as => abstract-msgs.mo} (100%) rename test/fail/{actor-match.as => actor-match.mo} (100%) rename test/fail/{actor-reexport.as => actor-reexport.mo} (100%) rename test/fail/{argument-subtyping.as => argument-subtyping.mo} (100%) rename test/fail/{ast81-clash.as => ast81-clash.mo} (100%) rename test/fail/{asyncret1.as => asyncret1.mo} (100%) rename test/fail/{asyncret2.as => asyncret2.mo} (100%) rename test/fail/{asyncret3.as => asyncret3.mo} (100%) rename test/fail/{await-in-actor.as => await-in-actor.mo} (100%) rename test/fail/{bad-unops.as => bad-unops.mo} (100%) rename test/fail/{branch-before-define.as => branch-before-define.mo} (100%) rename test/fail/{char-high-surrogate-trap.as => char-high-surrogate-trap.mo} (100%) rename test/fail/{char-high-surrogate.as => char-high-surrogate.mo} (100%) rename test/fail/{char-low-surrogate-trap.as => char-low-surrogate-trap.mo} (100%) rename test/fail/{char-low-surrogate.as => char-low-surrogate.mo} (100%) rename test/fail/{char-trap.as => char-trap.mo} (100%) rename test/fail/{class.as => class.mo} (100%) rename test/fail/{const-var-array.as => const-var-array.mo} (100%) rename test/fail/{const-var-field.as => const-var-field.mo} (100%) rename test/fail/{cyclic-bound1.as => cyclic-bound1.mo} (100%) rename test/fail/{cyclic-bound2.as => cyclic-bound2.mo} (100%) rename test/fail/{cyclic-bound3.as => cyclic-bound3.mo} (100%) rename test/fail/{cyclic-bound4.as => cyclic-bound4.mo} (100%) rename test/fail/{cyclic-bound5.as => cyclic-bound5.mo} (100%) rename test/fail/{debug.as => debug.mo} (100%) rename test/fail/{decl-clash.as => decl-clash.mo} (100%) rename test/fail/{duplicate-field.as => duplicate-field.mo} (100%) rename test/fail/{f-bounds-fail.as => f-bounds-fail.mo} (100%) rename test/fail/{issue103.as => issue103.mo} (100%) rename test/fail/{issue167.as => issue167.mo} (100%) rename test/fail/{issue36.as => issue36.mo} (100%) rename test/fail/lib/{not-static.as => not-static.mo} (100%) rename test/fail/{modexp1.as => modexp1.mo} (100%) rename test/fail/{modexp2.as => modexp2.mo} (100%) rename test/fail/{modexp3.as => modexp3.mo} (100%) rename test/fail/{modexp4.as => modexp4.mo} (100%) rename test/fail/{modexp5.as => modexp5.mo} (100%) rename test/fail/{modules-fwd.as => modules-fwd.mo} (100%) rename test/fail/{modules-shadow.as => modules-shadow.mo} (100%) rename test/fail/{nested-class-rec-fail.as => nested-class-rec-fail.mo} (100%) rename test/fail/{non_static_module.as => non_static_module.mo} (100%) rename test/fail/{nonlinear-pat.as => nonlinear-pat.mo} (100%) delete mode 100644 test/fail/not-static.as create mode 100644 test/fail/not-static.mo rename test/fail/{object-patterns.as => object-patterns.mo} (100%) rename test/fail/{objpat-duplicate.as => objpat-duplicate.mo} (100%) rename test/fail/{objpat-infer.as => objpat-infer.mo} (100%) rename test/fail/{objpat-mutable.as => objpat-mutable.mo} (100%) rename test/fail/{one-tuple-ambiguity.as => one-tuple-ambiguity.mo} (100%) rename test/fail/{pat-inconsistent.as => pat-inconsistent.mo} (100%) rename test/fail/{pat-subtyping-fail.as => pat-subtyping-fail.mo} (100%) rename test/fail/{prim-in-source.as => prim-in-source.mo} (100%) rename test/fail/{return-before-define.as => return-before-define.mo} (100%) delete mode 100644 test/fail/self-import.as create mode 100644 test/fail/self-import.mo rename test/fail/{switch-type.as => switch-type.mo} (100%) rename test/fail/{text-high-surrogate.as => text-high-surrogate.mo} (100%) rename test/fail/{text-low-surrogate.as => text-low-surrogate.mo} (100%) rename test/fail/{typ-field-lub-glb-fail.as => typ-field-lub-glb-fail.mo} (100%) rename test/fail/{use-before-define.as => use-before-define.mo} (100%) rename test/fail/{use-before-define2.as => use-before-define2.mo} (100%) rename test/fail/{use-before-define4.as => use-before-define4.mo} (100%) rename test/fail/{use-before-define5.as => use-before-define5.mo} (100%) rename test/fail/{use-before-define6.as => use-before-define6.mo} (100%) rename test/fail/{var-const-array.as => var-const-array.mo} (100%) rename test/fail/{var-const-field.as => var-const-field.mo} (100%) rename test/fail/{word-range.as => word-range.mo} (100%) rename test/ld/ok/{wrong-type.as-ld.ok => wrong-type.mo-ld.ok} (100%) rename test/lsp-int/test-project/{ListClient.as => ListClient.mo} (74%) rename test/lsp-int/test-project/{app.as => app.mo} (76%) rename test/lsp-int/test-project/lib/{ListFuncs.as => ListFuncs.mo} (86%) rename test/lsp-int/test-project/lib/{ListLib.as => ListLib.mo} (100%) rename test/lsp-int/test-project/lib/{list.as => list.mo} (100%) rename test/lsp-int/test-project/lib/{option.as => option.mo} (99%) rename test/lsp-int/test-project/lib/{prelude.as => prelude.mo} (100%) rename test/random/{qc-actorscript.cabal => qc-motoko.cabal} (85%) delete mode 100644 test/repl/lib/a.as create mode 100644 test/repl/lib/a.mo delete mode 100644 test/repl/lib/b.as create mode 100644 test/repl/lib/b.mo rename test/repl/lib/{c.as => c.mo} (100%) rename test/repl/lib/{empty.as => empty.mo} (100%) delete mode 100644 test/repl/lib/nested.as create mode 100644 test/repl/lib/nested.mo rename test/repl/lib/nested/{a.as => a.mo} (100%) delete mode 100644 test/repl/lib/nested/b.as create mode 100644 test/repl/lib/nested/b.mo delete mode 100644 test/repl/lib/triangle.as create mode 100644 test/repl/lib/triangle.mo rename test/run-dfinity/{AST-64.as => AST-64.mo} (100%) rename test/run-dfinity/{AST-66.as => AST-66.mo} (100%) rename test/run-dfinity/{arity_bug.as => arity_bug.mo} (100%) rename test/run-dfinity/{array-out-of-bounds.as => array-out-of-bounds.mo} (100%) rename test/run-dfinity/{async-any.as => async-any.mo} (100%) rename test/run-dfinity/{async-calls.as => async-calls.mo} (100%) rename test/run-dfinity/{async-loop-while.as => async-loop-while.mo} (100%) rename test/run-dfinity/{async-loop.as => async-loop.mo} (100%) rename test/run-dfinity/{async-new-obj.as => async-new-obj.mo} (100%) rename test/run-dfinity/{async-obj-mut.as => async-obj-mut.mo} (100%) rename test/run-dfinity/{async-while.as => async-while.mo} (100%) rename test/run-dfinity/{await.as => await.mo} (100%) rename test/run-dfinity/{block.as => block.mo} (100%) rename test/run-dfinity/{chat.as => chat.mo} (100%) rename test/run-dfinity/{chatpp.as => chatpp.mo} (100%) rename test/run-dfinity/{closure-params.as => closure-params.mo} (100%) rename test/run-dfinity/{control.as => control.mo} (100%) rename test/run-dfinity/{counter-class.as => counter-class.mo} (100%) rename test/run-dfinity/{counter.as => counter.mo} (100%) rename test/run-dfinity/{counter2.as => counter2.mo} (100%) rename test/run-dfinity/{data-params.as => data-params.mo} (100%) rename test/run-dfinity/{empty-actor.as => empty-actor.mo} (100%) rename test/run-dfinity/{fac.as => fac.mo} (100%) rename test/run-dfinity/{flatten-awaitables.as => flatten-awaitables.mo} (100%) rename test/run-dfinity/{for-await.as => for-await.mo} (100%) rename test/run-dfinity/{general-type-components.as => general-type-components.mo} (100%) rename test/run-dfinity/{generic-tail-rec.as => generic-tail-rec.mo} (100%) rename test/run-dfinity/{hello-concat-world.as => hello-concat-world.mo} (100%) rename test/run-dfinity/{hello-world-async.as => hello-world-async.mo} (100%) rename test/run-dfinity/{hello-world-await.as => hello-world-await.mo} (100%) rename test/run-dfinity/{hello-world-message.as => hello-world-message.mo} (100%) rename test/run-dfinity/{hello-world-message2.as => hello-world-message2.mo} (100%) rename test/run-dfinity/{hello-world.as => hello-world.mo} (100%) rename test/run-dfinity/{hello-world2.as => hello-world2.mo} (100%) rename test/run-dfinity/{hello-world3.as => hello-world3.mo} (100%) rename test/run-dfinity/{idl-tuple.as => idl-tuple.mo} (100%) rename test/run-dfinity/{indirect-counter.as => indirect-counter.mo} (100%) rename test/run-dfinity/{large-mem.as => large-mem.mo} (100%) rename test/run-dfinity/{local-throw.as => local-throw.mo} (100%) rename test/run-dfinity/{log-slow.as => log-slow.mo} (100%) rename test/run-dfinity/{modexp1.as => modexp1.mo} (100%) rename test/run-dfinity/{modexp2.as => modexp2.mo} (100%) rename test/run-dfinity/{modexp3.as => modexp3.mo} (100%) rename test/run-dfinity/{modexp4.as => modexp4.mo} (100%) rename test/run-dfinity/{modules-bwd.as => modules-bwd.mo} (100%) rename test/run-dfinity/{nary-async.as => nary-async.mo} (100%) rename test/run-dfinity/{overflow.as => overflow.mo} (100%) rename test/run-dfinity/{query.as => query.mo} (100%) rename test/run-dfinity/{reference-params.as => reference-params.mo} (100%) rename test/run-dfinity/{selftail.as => selftail.mo} (100%) rename test/run-dfinity/{shared-object.as => shared-object.mo} (100%) rename test/run-dfinity/{show.as => show.mo} (100%) rename test/run-dfinity/{simple-throw.as => simple-throw.mo} (100%) rename test/run-dfinity/{tailpositions.as => tailpositions.mo} (100%) rename test/run-dfinity/{text-iter.as => text-iter.mo} (100%) rename test/run-dfinity/{the-answer.as => the-answer.mo} (100%) rename test/run-dfinity/{tiny.as => tiny.mo} (100%) rename test/run-dfinity/{transpose.as => transpose.mo} (100%) rename test/run-dfinity/{type-lub.as => type-lub.mo} (98%) rename test/run-drun/{counter.as => counter.mo} (100%) rename test/run-drun/{hello-world-return.as => hello-world-return.mo} (100%) rename test/run-drun/{idl-any.as => idl-any.mo} (100%) rename test/run-drun/{idl-bad.as => idl-bad.mo} (100%) rename test/run-drun/{idl-field-escape.as => idl-field-escape.mo} (100%) rename test/run-drun/{idl-func.as => idl-func.mo} (100%) rename test/run-drun/{idl-nary.as => idl-nary.mo} (100%) rename test/run-drun/{idl-nat-int.as => idl-nat-int.mo} (100%) rename test/run-drun/{idl-option.as => idl-option.mo} (100%) rename test/run-drun/{idl-pair.as => idl-pair.mo} (100%) rename test/run-drun/{idl-record.as => idl-record.mo} (100%) rename test/run-drun/{idl-tuple.as => idl-tuple.mo} (100%) rename test/run-drun/{idl-unit.as => idl-unit.mo} (100%) rename test/run-drun/{idl-variant.as => idl-variant.mo} (100%) rename test/run-drun/{idl-vector.as => idl-vector.mo} (100%) rename test/run-drun/{large-array.as => large-array.mo} (100%) rename test/run-drun/{multiple-actors.as => multiple-actors.mo} (100%) rename test/run-drun/{print-from-init.as => print-from-init.mo} (100%) rename test/run-drun/{query.as => query.mo} (100%) rename test/run-drun/{reject.as => reject.mo} (100%) rename test/run-drun/{unsupported.as => unsupported.mo} (100%) rename test/run-release/{debug.as => debug.mo} (100%) rename test/run/{AST-56.as => AST-56.mo} (100%) rename test/run/{TRAP-write-before-init.as => TRAP-write-before-init.mo} (100%) rename test/run/{array-bounds.as => array-bounds.mo} (100%) rename test/run/{array-gen.as => array-gen.mo} (100%) rename test/run/{array.as => array.mo} (100%) rename test/run/{assert42.as => assert42.mo} (100%) rename test/run/{assertFalse.as => assertFalse.mo} (100%) rename test/run/{assertTrue.as => assertTrue.mo} (100%) rename test/run/{bit-ops.as => bit-ops.mo} (100%) rename test/run/{call-none.as => call-none.mo} (100%) rename test/run/{capture-mut.as => capture-mut.mo} (100%) rename test/run/{char-pats.as => char-pats.mo} (100%) rename test/run/{closures.as => closures.mo} (100%) rename test/run/{concat.as => concat.mo} (100%) rename test/run/{conversions.as => conversions.mo} (100%) rename test/run/{coverage.as => coverage.mo} (100%) rename test/run/{debug.as => debug.mo} (100%) rename test/run/{eager-and-lazy.as => eager-and-lazy.mo} (100%) rename test/run/{empty-tup-args.as => empty-tup-args.mo} (100%) rename test/run/{empty.as => empty.mo} (100%) rename test/run/{f-bounds.as => f-bounds.mo} (100%) rename test/run/{fac.as => fac.mo} (100%) rename test/run/{fib.as => fib.mo} (100%) rename test/run/{for.as => for.mo} (100%) rename test/run/{hashes.as => hashes.mo} (100%) rename test/run/{hoare.as => hoare.mo} (100%) rename test/run/{idlHash.as => idlHash.mo} (100%) rename test/run/{import-module.as => import-module.mo} (67%) delete mode 100644 test/run/import.as create mode 100644 test/run/import.mo rename test/run/{ir-litpat-subtype.as => ir-litpat-subtype.mo} (100%) rename test/run/{ir-pat-subtype.as => ir-pat-subtype.mo} (100%) rename test/run/{issue120.as => issue120.mo} (100%) rename test/run/{issue122.as => issue122.mo} (100%) rename test/run/{issue129.as => issue129.mo} (95%) rename test/run/{issue135.as => issue135.mo} (100%) rename test/run/{issue150.as => issue150.mo} (100%) rename test/run/{issue442.as => issue442.mo} (100%) rename test/run/{issue537.as => issue537.mo} (100%) rename test/run/{issue551.as => issue551.mo} (100%) rename test/run/{issue83.as => issue83.mo} (100%) rename test/run/{iter-null.as => iter-null.mo} (100%) rename test/run/{large-mem.as => large-mem.mo} (100%) rename test/run/{large-tuple.as => large-tuple.mo} (100%) rename test/run/{last-dec-val.as => last-dec-val.mo} (100%) rename test/run/{let.as => let.mo} (100%) rename test/run/{let_fun.as => let_fun.mo} (100%) rename test/run/lib/{ListM.as => ListM.mo} (100%) rename test/run/lib/dir/{lib.as => lib.mo} (100%) rename test/run/lib/{hello-string.as => hello-string.mo} (100%) rename test/run/{literals.as => literals.mo} (100%) rename test/run/{menhir-bug.as => menhir-bug.mo} (100%) rename test/run/{module1.as => module1.mo} (100%) rename test/run/{module2.as => module2.mo} (100%) rename test/run/{module3.as => module3.mo} (100%) rename test/run/{modulus.as => modulus.mo} (100%) rename test/run/{mut-field-bound.as => mut-field-bound.mo} (100%) rename test/run/{mutrec.as => mutrec.mo} (100%) rename test/run/{mutrec2.as => mutrec2.mo} (100%) rename test/run/{mutrec3.as => mutrec3.mo} (100%) rename test/run/{n-ary.as => n-ary.mo} (100%) rename test/run/{neg-boundary.as => neg-boundary.mo} (100%) rename test/run/{nested-class-rec.as => nested-class-rec.mo} (100%) rename test/run/{nested-eager.as => nested-eager.mo} (100%) rename test/run/{nested-lexpr.as => nested-lexpr.mo} (100%) rename test/run/{numeric-ops.as => numeric-ops.mo} (100%) rename test/run/{objects-order.as => objects-order.mo} (100%) rename test/run/{objects1.as => objects1.mo} (100%) rename test/run/{objects2.as => objects2.mo} (100%) rename test/run/{objects3.as => objects3.mo} (100%) rename test/run/{objects4.as => objects4.mo} (100%) rename test/run/{objects5.as => objects5.mo} (100%) rename test/run/{ott-typeclasses.as => ott-typeclasses.mo} (100%) rename test/run/{overflow.as => overflow.mo} (100%) rename test/run/{pat-subtyping.as => pat-subtyping.mo} (100%) rename test/run/{prelude.as => prelude.mo} (100%) rename test/run/{quicksort.as => quicksort.mo} (100%) rename test/run/{ranged-nums.as => ranged-nums.mo} (100%) rename test/run/{records.as => records.mo} (100%) rename test/run/{relational-ops.as => relational-ops.mo} (100%) rename test/run/{rts.as => rts.mo} (100%) rename test/run/{self-bounds.as => self-bounds.mo} (100%) rename test/run/{short-circuit.as => short-circuit.mo} (100%) rename test/run/{signed-div.as => signed-div.mo} (100%) rename test/run/{small-pow.as => small-pow.mo} (99%) rename test/run/{static-func-call.as => static-func-call.mo} (100%) rename test/run/{sub-negative.as => sub-negative.mo} (100%) rename test/run/{switch.as => switch.mo} (100%) rename test/run/{text-concat.as => text-concat.mo} (100%) rename test/run/{text-op.as => text-op.mo} (100%) rename test/run/{text-pats.as => text-pats.mo} (100%) rename test/run/{tuples.as => tuples.mo} (100%) rename test/run/{typ-field-lub-glb.as => typ-field-lub-glb.mo} (100%) rename test/run/{typdecl-last.as => typdecl-last.mo} (100%) rename test/run/{type-definition.as => type-definition.mo} (100%) rename test/run/{type-equivalence.as => type-equivalence.mo} (100%) rename test/run/{type-inclusion.as => type-inclusion.mo} (100%) rename test/run/{type-inference.as => type-inference.mo} (100%) rename test/run/{underscore-ids.as => underscore-ids.mo} (100%) rename test/run/{use-before-define3.as => use-before-define3.mo} (100%) rename test/run/{variants.as => variants.mo} (100%) rename test/run/{while.as => while.mo} (100%) rename test/run/{word-rotations.as => word-rotations.mo} (100%) rename test/run/{words.as => words.mo} (100%) rename test/trap/{addInt16-lower.as => addInt16-lower.mo} (100%) rename test/trap/{addInt16-upper.as => addInt16-upper.mo} (100%) rename test/trap/{addInt32-lower.as => addInt32-lower.mo} (100%) rename test/trap/{addInt32-upper.as => addInt32-upper.mo} (100%) rename test/trap/{addInt64-lower.as => addInt64-lower.mo} (100%) rename test/trap/{addInt64-upper.as => addInt64-upper.mo} (100%) rename test/trap/{addInt8-lower.as => addInt8-lower.mo} (100%) rename test/trap/{addInt8-upper.as => addInt8-upper.mo} (100%) rename test/trap/{addNat16.as => addNat16.mo} (100%) rename test/trap/{addNat32.as => addNat32.mo} (100%) rename test/trap/{addNat64.as => addNat64.mo} (100%) rename test/trap/{addNat8.as => addNat8.mo} (100%) rename test/trap/{divInt16.as => divInt16.mo} (100%) rename test/trap/{divInt32.as => divInt32.mo} (100%) rename test/trap/{divInt64.as => divInt64.mo} (100%) rename test/trap/{divInt8.as => divInt8.mo} (100%) rename test/trap/{mulInt16-lower.as => mulInt16-lower.mo} (100%) rename test/trap/{mulInt16-upper.as => mulInt16-upper.mo} (100%) rename test/trap/{mulInt32-lower.as => mulInt32-lower.mo} (100%) rename test/trap/{mulInt32-upper.as => mulInt32-upper.mo} (100%) rename test/trap/{mulInt64-lower.as => mulInt64-lower.mo} (100%) rename test/trap/{mulInt64-upper.as => mulInt64-upper.mo} (100%) rename test/trap/{mulInt8-lower.as => mulInt8-lower.mo} (100%) rename test/trap/{mulInt8-upper.as => mulInt8-upper.mo} (100%) rename test/trap/{mulNat16.as => mulNat16.mo} (100%) rename test/trap/{mulNat32.as => mulNat32.mo} (100%) rename test/trap/{mulNat64.as => mulNat64.mo} (100%) rename test/trap/{mulNat8.as => mulNat8.mo} (100%) rename test/trap/{outrange-int16-lower.as => outrange-int16-lower.mo} (100%) rename test/trap/{outrange-int16-negation.as => outrange-int16-negation.mo} (100%) rename test/trap/{outrange-int16-upper.as => outrange-int16-upper.mo} (100%) rename test/trap/{outrange-int32-lower.as => outrange-int32-lower.mo} (100%) rename test/trap/{outrange-int32-negation.as => outrange-int32-negation.mo} (100%) rename test/trap/{outrange-int32-upper.as => outrange-int32-upper.mo} (100%) rename test/trap/{outrange-int64-lower.as => outrange-int64-lower.mo} (100%) rename test/trap/{outrange-int64-negation.as => outrange-int64-negation.mo} (100%) rename test/trap/{outrange-int64-upper.as => outrange-int64-upper.mo} (100%) rename test/trap/{outrange-int8-lower.as => outrange-int8-lower.mo} (100%) rename test/trap/{outrange-int8-negation.as => outrange-int8-negation.mo} (100%) rename test/trap/{outrange-int8-upper.as => outrange-int8-upper.mo} (100%) rename test/trap/{outrange-nat16.as => outrange-nat16.mo} (100%) rename test/trap/{outrange-nat32.as => outrange-nat32.mo} (100%) rename test/trap/{outrange-nat64.as => outrange-nat64.mo} (100%) rename test/trap/{outrange-nat8.as => outrange-nat8.mo} (100%) rename test/trap/{powInt32-lower.as => powInt32-lower.mo} (100%) rename test/trap/{powInt32-raise-neg.as => powInt32-raise-neg.mo} (100%) rename test/trap/{powInt32-upper.as => powInt32-upper.mo} (100%) rename test/trap/{powInt64-lower-fast.as => powInt64-lower-fast.mo} (100%) rename test/trap/{powInt64-lower-slow.as => powInt64-lower-slow.mo} (100%) rename test/trap/{powInt64-raise-neg.as => powInt64-raise-neg.mo} (100%) rename test/trap/{powInt64-upper-fast.as => powInt64-upper-fast.mo} (100%) rename test/trap/{powInt64-upper-slow.as => powInt64-upper-slow.mo} (100%) rename test/trap/{powInt8-lower.as => powInt8-lower.mo} (100%) rename test/trap/{powInt8-raise-neg.as => powInt8-raise-neg.mo} (100%) rename test/trap/{powInt8-upper.as => powInt8-upper.mo} (100%) rename test/trap/{powNat16.as => powNat16.mo} (100%) rename test/trap/{powNat32.as => powNat32.mo} (100%) rename test/trap/{powNat64.as => powNat64.mo} (100%) rename test/trap/{powNat8.as => powNat8.mo} (100%) rename test/trap/{subInt16-lower.as => subInt16-lower.mo} (100%) rename test/trap/{subInt16-upper.as => subInt16-upper.mo} (100%) rename test/trap/{subInt32-lower.as => subInt32-lower.mo} (100%) rename test/trap/{subInt32-upper.as => subInt32-upper.mo} (100%) rename test/trap/{subInt64-lower.as => subInt64-lower.mo} (100%) rename test/trap/{subInt64-upper.as => subInt64-upper.mo} (100%) rename test/trap/{subInt8-lower.as => subInt8-lower.mo} (100%) rename test/trap/{subInt8-upper.as => subInt8-upper.mo} (100%) rename test/trap/{subNat16.as => subNat16.mo} (100%) rename test/trap/{subNat32.as => subNat32.mo} (100%) rename test/trap/{subNat64-slow.as => subNat64-slow.mo} (100%) rename test/trap/{subNat64.as => subNat64.mo} (100%) rename test/trap/{subNat8.as => subNat8.mo} (100%) diff --git a/.gitattributes b/.gitattributes index 01f89156944..850c6cbd486 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,2 @@ -# .gitattributes file which reclassifies `.as` files as Swift: -*.as linguist-language=Swift \ No newline at end of file +# .gitattributes file which reclassifies `.mo` files as Swift: +*.mo linguist-language=Swift diff --git a/Building.md b/Building.md index d81dd5b0656..6db0d3d9ca2 100644 --- a/Building.md +++ b/Building.md @@ -1,9 +1,9 @@ ## Installation using Nix -To install the `asc` binary into your nix environment, use +To install the `moc` binary into your nix environment, use ``` -$ nix-env -i -f . -A asc +$ nix-env -i -f . -A moc ``` ## Development using Nix @@ -19,9 +19,9 @@ $ nix-shell ``` within this shell you can run * `make` in `src/` to build all binaries, - * `make asc` in `src/` to build just the `asc` binary, - * `make DUNE_OPTS=--watch asc` to keep rebuilding as source files are changing - * `make` in `rts/` to build the ActorScript runtime + * `make moc` in `src/` to build just the `moc` binary, + * `make DUNE_OPTS=--watch moc` to keep rebuilding as source files are changing + * `make` in `rts/` to build the Motoko runtime * `make` in `test/` to run the test suite. This invokes `dune` under the hood, which will, as a side effect, also create @@ -54,11 +54,11 @@ installing all required tools without nix is out of scope). nix-env -i -f . -A wabt nix-env -i -f . -A dvm ``` - * Building the ActorScript runtime without nix is tricky. But you can run + * Building the Motoko runtime without nix is tricky. But you can run ``` nix-shell --run 'make -C rts' ``` - to get `rts/as-rts.wasm`. + to get `rts/mo-rts.wasm`. ## Create a coverage report @@ -71,16 +71,16 @@ https://github.com/ocaml/dune/issues/57 to see when a coverage report is viable 1. Build with profiling (TODO: How to do with dune) ``` make -C src clean - make BUILD=p.native -C src asc + make BUILD=p.native -C src moc ``` -2. Run `asc` as normal, e.g. +2. Run `moc` as normal, e.g. ``` - ./src/asc -c foo.as -o foo.wasm + ./src/moc -c foo.mo -o foo.wasm ``` this should dump a `gmon.out` file in the current directory. 3. Create the report, e.g. using ``` - gprof --graph src/asc + gprof --graph src/moc ``` (Note that you have to _run_ this in the directory with `gmon.out`, but _pass_ it the path to the binary.) diff --git a/README.md b/README.md index 712146f6b9b..280094425ea 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -# ActorScript +# Motoko A simple language for writing Dfinity actors. ## User Documentation & Samples -* [Overview slides](https://hydra.dfinity.systems/job/dfinity-ci-build/actorscript/users-guide/latest/download/1/as-slides.html) ([sources](guide/as-slides.md)). +* [Overview slides](https://hydra.dfinity.systems/job/dfinity-ci-build/motoko/users-guide/latest/download/1/as-slides.html) ([sources](guide/as-slides.md)). * [Draft (incomplete) manual](guide/guide.md). * [Prelude](src/prelude/prelude.ml). * Beginnings of [standard library](stdlib). diff --git a/ci.nix b/ci.nix index 6e984224b1a..5bce20d368d 100644 --- a/ci.nix +++ b/ci.nix @@ -10,8 +10,8 @@ let in linux // { darwin = darwin.all-systems-go; - asc-tar-x86_64-darwin = darwin.asc-tar; - asc-tar-x86_64-linux = linux.asc-tar; + moc-tar-x86_64-darwin = darwin.moc-tar; + moc-tar-x86_64-linux = linux.moc-tar; all-systems-go = inject-rev (nixpkgs.releaseTools.aggregate { name = "all-systems-go"; constituents = [ diff --git a/default.nix b/default.nix index ed938e7e630..1cdb032894e 100644 --- a/default.nix +++ b/default.nix @@ -201,7 +201,7 @@ in rec { rts = stdenv.mkDerivation { - name = "asc-rts"; + name = "moc-rts"; src = subpath ./rts; nativeBuildInputs = [ nixpkgs.makeWrapper ]; @@ -221,56 +221,56 @@ rec { installPhase = '' mkdir -p $out/rts - cp as-rts.wasm $out/rts + cp mo-rts.wasm $out/rts ''; }; - asc-bin = stdenv.mkDerivation { - name = "asc-bin"; + moc-bin = stdenv.mkDerivation { + name = "moc-bin"; src = subpath ./src; buildInputs = commonBuildInputs; buildPhase = '' - make DUNE_OPTS="--display=short --profile release" asc as-ld + make DUNE_OPTS="--display=short --profile release" moc mo-ld ''; installPhase = '' mkdir -p $out/bin - cp --verbose --dereference asc as-ld $out/bin + cp --verbose --dereference moc mo-ld $out/bin ''; }; - asc = nixpkgs.symlinkJoin { - name = "asc"; - paths = [ asc-bin rts ]; + moc = nixpkgs.symlinkJoin { + name = "moc"; + paths = [ moc-bin rts ]; buildInputs = [ nixpkgs.makeWrapper ]; postBuild = '' - wrapProgram $out/bin/asc \ - --set-default ASC_RTS "$out/rts/as-rts.wasm" + wrapProgram $out/bin/moc \ + --set-default MOC_RTS "$out/rts/mo-rts.wasm" ''; }; - asc-tar = nixpkgs.symlinkJoin { - name = "asc-tar"; - paths = [ asc-bin rts didc ]; + moc-tar = nixpkgs.symlinkJoin { + name = "moc-tar"; + paths = [ moc-bin rts didc ]; postBuild = '' - tar -chf $out/asc.tar -C $out bin/asc rts/as-rts.wasm bin/didc + tar -chf $out/moc.tar -C $out bin/moc rts/mo-rts.wasm bin/didc mkdir -p $out/nix-support - echo "file bin $out/asc.tar" >> $out/nix-support/hydra-build-products + echo "file bin $out/moc.tar" >> $out/nix-support/hydra-build-products ''; }; lsp-int = haskellPackages.callCabal2nix "lsp-int" test/lsp-int { }; - qc-actorscript = haskellPackages.callCabal2nix "qc-actorscript" test/random { }; + qc-motoko = haskellPackages.callCabal2nix "qc-motoko" test/random { }; tests = stdenv.mkDerivation { name = "tests"; src = subpath ./test; buildInputs = - [ asc + [ moc didc deser ocaml_wasm @@ -283,7 +283,7 @@ rec { js-user-library dvm drun - qc-actorscript + qc-motoko lsp-int esm ] ++ @@ -292,19 +292,19 @@ rec { buildPhase = '' patchShebangs . ${llvmEnv} - export ASC=asc - export AS_LD=as-ld + export MOC=moc + export MO_LD=mo-ld export DIDC=didc export DESER=deser export ESM=${esm} export JS_USER_LIBRARY=${js-user-library} - asc --version + moc --version make parallel - qc-actorscript${nixpkgs.lib.optionalString (replay != 0) + qc-motoko${nixpkgs.lib.optionalString (replay != 0) " --quickcheck-replay=${toString replay}"} cp -R ${subpath ./test/lsp-int/test-project} test-project find ./test-project -type d -exec chmod +w {} + - lsp-int ${as-ide}/bin/as-ide ./test-project + lsp-int ${mo-ide}/bin/mo-ide ./test-project ''; installPhase = '' @@ -328,20 +328,20 @@ rec { ''; }; - as-ide = stdenv.mkDerivation { - name = "as-ide"; + mo-ide = stdenv.mkDerivation { + name = "mo-ide"; src = subpath ./src; buildInputs = commonBuildInputs; buildPhase = '' - make DUNE_OPTS="--display=short --profile release" as-ide + make DUNE_OPTS="--display=short --profile release" mo-ide ''; installPhase = '' mkdir -p $out/bin - cp --verbose --dereference as-ide $out/bin + cp --verbose --dereference mo-ide $out/bin ''; }; @@ -349,7 +349,7 @@ rec { name = "samples"; src = subpath ./samples; buildInputs = - [ asc + [ moc didc ocaml_wasm nixpkgs.wabt @@ -362,7 +362,7 @@ rec { buildPhase = '' patchShebangs . - export ASC=asc + export MOC=moc make all ''; installPhase = '' @@ -370,8 +370,8 @@ rec { ''; }; - js = asc-bin.overrideAttrs (oldAttrs: { - name = "asc.js"; + js = moc-bin.overrideAttrs (oldAttrs: { + name = "moc.js"; buildInputs = commonBuildInputs ++ [ nixpkgs.ocamlPackages.js_of_ocaml @@ -381,12 +381,12 @@ rec { ]; buildPhase = '' - make asc.js + make moc.js ''; installPhase = '' mkdir -p $out - cp -v asc.js $out + cp -v moc.js $out cp -vr ${rts}/rts $out ''; @@ -470,15 +470,15 @@ rec { ''; doCheck = true; checkInputs = [ - asc + moc nixpkgs.python ]; checkPhase = '' - make ASC=${asc}/bin/asc alltests + make MOC=${moc}/bin/moc alltests ''; installPhase = '' mkdir -p $out - tar -rf $out/stdlib.tar -C $src *.as + tar -rf $out/stdlib.tar -C $src *.mo mkdir -p $out/nix-support echo "report stdlib $out/stdlib.tar" >> $out/nix-support/hydra-build-products ''; @@ -525,15 +525,15 @@ rec { name = "produce-exchange"; src = subpath ./stdlib; buildInputs = [ - asc + moc ]; doCheck = true; buildPhase = '' - make ASC=asc OUTDIR=_out _out/ProduceExchange.wasm + make MOC=moc OUTDIR=_out _out/ProduceExchange.wasm ''; checkPhase = '' - make ASC=asc OUTDIR=_out _out/ProduceExchange.out + make MOC=moc OUTDIR=_out _out/ProduceExchange.out ''; installPhase = '' mkdir -p $out @@ -544,8 +544,8 @@ rec { all-systems-go = nixpkgs.releaseTools.aggregate { name = "all-systems-go"; constituents = [ - asc - as-ide + moc + mo-ide js didc deser @@ -563,16 +563,16 @@ rec { shell = if export-shell then nixpkgs.mkShell { # - # Since building asc, and testing it, are two different derivations in we + # Since building moc, and testing it, are two different derivations in we # have to create a fake derivation for `nix-shell` that commons up the # build dependencies of the two to provide a build environment that offers - # both, while not actually building `asc` + # both, while not actually building `moc` # buildInputs = - let dont_build = [ asc didc deser ]; in + let dont_build = [ moc didc deser ]; in nixpkgs.lib.lists.unique (builtins.filter (i: !(builtins.elem i dont_build)) ( - asc-bin.buildInputs ++ + moc-bin.buildInputs ++ js.buildInputs ++ rts.buildInputs ++ didc.buildInputs ++ diff --git a/design/FAQ.md b/design/FAQ.md index 363d9629843..b0bb0da07b7 100644 --- a/design/FAQ.md +++ b/design/FAQ.md @@ -6,7 +6,7 @@ An actor is instantiated as a separate wasm instance, with isolated state. Class At the moment, anywhere - they get compiled to async message sends to the enclosing (perhaps implicit) actor that return a promise. You might, however, not be able to await the result unless you are in an outer async context! But you could pass in into another async block that can await it. -> 3. What kinds of datatypes are permitted to be declared with the `share` qualifier; and why some but not others (what’s the source of the distinction, and its role in writing actorscript-based systems) +> 3. What kinds of datatypes are permitted to be declared with the `share` qualifier; and why some but not others (what’s the source of the distinction, and its role in writing motoko-based systems) Shared means transmittable without losing identity, essentially. So scalars, immutable data, option of shared, shared (immutable objects), shared functions and actor references can be sent/received, but nothing else that might contain or close over mutable state. That's the idea, assuming it isn't broken. Not all restrictions are currently checked (i.e. escape of shared state into actors and shared functions for instance.) Note that serialization is mostly by value, apart from actors and shared functions, which are by reference, so identity can't be preserved for most values, ruling out them containing state. diff --git a/design/IDL-AS.md b/design/IDL-Motoko.md similarity index 71% rename from design/IDL-AS.md rename to design/IDL-Motoko.md index 18d4b6a1a42..fd6fd77f0e1 100644 --- a/design/IDL-AS.md +++ b/design/IDL-Motoko.md @@ -1,44 +1,44 @@ -The IDL-ActorScript integration +The IDL-Motoko integration =============================== ## Goals -This document specifies the integration of the IDL with the ActorScript +This document specifies the integration of the IDL with the Motoko language, in particular: - * How to translate between an ActorScript `actor` type and an IDL `service` - description in both ways (i.e. _exporting_ IDL from ActorScript, and _importing_ - IDL into ActorScript), and how to translate between the values of these types. + * How to translate between an Motoko `actor` type and an IDL `service` + description in both ways (i.e. _exporting_ IDL from Motoko, and _importing_ + IDL into Motoko), and how to translate between the values of these types. * The supported work-flows, including a sketch of the involved tools. We try to achieve the following goals (but do not achieve them completely) - * We can round-trip all ActorScript values of sharable type. More precisely: + * We can round-trip all Motoko values of sharable type. More precisely: - When exporting an ActorScript type `ta` into an IDL type `ti`, then + When exporting an Motoko type `ta` into an IDL type `ti`, then round-tripping a value `va : ta` through `ti` yields a value that is indistinguishable from `va` at type `ta`. - * ActorScript can receive all IDL types: The type export has an inverse, the + * Motoko can receive all IDL types: The type export has an inverse, the type import mapping, which is injective (up-to IDL type equivalence via shorthands). - * ActorScript can receive all IDL values when importing an IDL: + * Motoko can receive all IDL values when importing an IDL: When importing an IDL type `ti` into `ta`, then every IDL value `vi : ti` - will successfully translated to an ActorScript value of type `ta`. + will successfully translated to an Motoko value of type `ta`. The following are not necessary true: - * The type export mapping is not total: there are ActorScript types that cannot + * The type export mapping is not total: there are Motoko types that cannot be exported, such as mutable arrays. * The type export mapping is not injective: there may be different - ActorScript types that map to the same IDL type, e.g. `Char`, `Word32` and + Motoko types that map to the same IDL type, e.g. `Char`, `Word32` and `Nat32`. - This implies that round-tripping an ActorScript type via the IDL can yield + This implies that round-tripping an Motoko type via the IDL can yield different types. * For some types, not all IDL values may be accepted: for example, `Char` is @@ -46,7 +46,7 @@ The following are not necessary true: `Char`. This can only be the case for types not in the image of the type import mapping. -NB: These properties (and non-properties) are not specific to ActorScript, and +NB: These properties (and non-properties) are not specific to Motoko, and we expect that they will hold similarly for interfaces to other typed languages with seamless serialization (e.g. built-in, macro or type class based integration). In this sense, this document serves as a blueprint. Untyped @@ -56,14 +56,14 @@ story. ## The type mappings We define - * a partial function `e` from ActorScript types to IDL types. + * a partial function `e` from Motoko types to IDL types. Types that are not in the domain of `e` cannot be exported. - * a partial function `i` from IDL types to ActorScript types. + * a partial function `i` from IDL types to Motoko types. Types that are not in the domain of `i` cannot be imported. -These definition treats ActorScript types and IDL types as structural and +These definition treats Motoko types and IDL types as structural and infinite; a concrete implementation will have to look through type constructors -in ActorScript and introduce type definitions in the IDL as necessary. +in Motoko and introduce type definitions in the IDL as necessary. It assumes that the IDL short-hands (e.g. named or anonymous fields) are part of the grammar of types, and that `i` is allowed to make difference @@ -132,7 +132,7 @@ i(text) = Text i(reserved) = Any i(opt ) = ? i() i(vec ) = [ i() ] -i(blob) = [ word8 ] // if ActorScript had a bytes type, it would show up here +i(blob) = [ word8 ] // if Motoko had a bytes type, it would show up here i(record { ;^N }) = ( i(),^N ) if n > 1 // matches tuple short-hand i(record { ;* }) = { if();* } i(variant { ;* }) = variant { if();* } @@ -155,9 +155,9 @@ im : -> im( : ) = escape() : ifn() escape : -> -escape = "_" if is a reserved identifier in ActorScript +escape = "_" if is a reserved identifier in Motoko escape = "_" if ends with "_" -escape = if is a valid ActorScript not ending in "_" +escape = if is a valid Motoko not ending in "_" escape = "_" hash() "_" otherwise ``` @@ -179,7 +179,7 @@ escape = "_" hash() "_" otherwise ``` * The mapping `i` tries to detect types that can be expressed as - tuples in ActorScript. + tuples in Motoko. ``` i(record {int;nat}) = (Int, Nat) i(record {int; nat; foo:text}) = {_0_:Int; _1_:Nat; foo:Text} @@ -196,7 +196,7 @@ escape = "_" hash() "_" otherwise record {int}`. * The `escape` and `unescape` functions allow round-tripping of IDL field - names that are not valid ActorScript names (fake hash values): + names that are not valid Motoko names (fake hash values): ``` i(record {int; if:text; foobar_:nat; "_0_":bool}) = (_0_:Int; if_:Text; _1234_:Nat; _4321_:Bool) @@ -207,34 +207,34 @@ escape = "_" hash() "_" otherwise ``` is undefined, because `unescape(clash_) = unescape(clash)`. - * ActorScript functions with type parameters are not in the domain of `e`. + * Motoko functions with type parameters are not in the domain of `e`. - * Abstract ActorScript types are not in the domain of `e` + * Abstract Motoko types are not in the domain of `e` * The translation produces IDL functions without parameter names. But both - the IDL and ActorScript conveniently support non-significant names in + the IDL and Motoko conveniently support non-significant names in parameter lists. These are essentially comments, and do not affect, for example, the type section in a message, so it is not necessary to specify them here. - But tooling (e.g. `asc` exporting an IDL from an ActorScript type) is of - course free to use any annotations in the ActorScript type (or even names + But tooling (e.g. `moc` exporting an IDL from an Motoko type) is of + course free to use any annotations in the Motoko type (or even names from pattern in function definitions) also in the exported IDL. - * The soundness of the ActorScript type system, when it comes to higher-order + * The soundness of the Motoko type system, when it comes to higher-order use of actor and function references, relies on ``` ∀ t1 t2 : dom(e), t1 <: t2 ⟹ e(t1) <: e(t2) ``` - In other words: ActorScript subtyping must be contained in IDL subtyping. + In other words: Motoko subtyping must be contained in IDL subtyping. * There is no way to produce `float32` or functions with a `query` annotation. Importing interfaces that contain these types fails. ## The value mappings -For each ActorScript type `t` in the domain of `e`, we need mapping from -ActorScript value of type `t` to an IDL value of type `e(t)`, and vice-versa. +For each Motoko type `t` in the domain of `e`, we need mapping from +Motoko value of type `t` to an IDL value of type `e(t)`, and vice-versa. Note that decoding may only fail for those `t` that are not in the range of `i`. @@ -246,52 +246,52 @@ These mappings should be straight-forward, given the following clarifications: ## Works flows The mapping specified here can be used to support the following use-cases. The -user interfaces (e.g. flag names, or whether `asc`, `didc`, `dfx` is used) are +user interfaces (e.g. flag names, or whether `moc`, `didc`, `dfx` is used) are just suggestions. -* Generating IDL from ActorScript +* Generating IDL from Motoko - If `foo.as` is an ActorScript `actor` compilation unit, then + If `foo.mo` is an Motoko `actor` compilation unit, then - asc --generate-idl foo.as -o foo.did + moc --generate-idl foo.mo -o foo.did - will type-check `foo.as` as `t = actor { … }`, map the ActorScript type `t` + will type-check `foo.mo` as `t = actor { … }`, map the Motoko type `t` to an IDL type `e(t)` of the form `service `, and produce a textual IDL file `foo.did` that ends with a `service n : `, where `n` is the name of the actor class, actor, or basename of the source file. -* Checking ActorScript against a given IDL +* Checking Motoko against a given IDL - If `foo.as` is an ActorScript `actor` compilation unit and `foo.did` a + If `foo.mo` is an Motoko `actor` compilation unit and `foo.did` a textual IDL file, then - asc --check-idl foo.did foo.as -o foo.wasm + moc --check-idl foo.did foo.mo -o foo.wasm will import the type service `t_spec` specified in `foo.did`, using the mapping `i`, will generate an IDL type `e(t)` as in the previous point, and and check that `e(t) <: t_spec` (using IDL subtyping). -* Converting IDL types to ActorScript types +* Converting IDL types to Motoko types If `foo.did` a textual IDL file, then - didc foo.did -o foo.as + didc foo.did -o foo.mo - will create an ActorScript library unit `foo.as` that consists of type + will create an Motoko library unit `foo.mo` that consists of type definitions. All ``s and the final `` from `foo.did` is turned into a `type` - declaration in ActorScript, according to `i`. + declaration in Motoko, according to `i`. Imported IDL files are recursively inlined. Variant: Imported IDL files are translated separately and included via - `import` in ActorScript. + `import` in Motoko. -* Importing IDL types from the ActorScript compiler +* Importing IDL types from the Motoko compiler If `path/to/foo.did` a textual IDL file, then a declaration import Foo "path/to/foo" - is treated by `asc` by reading `foo.did` as if the developer had - run `didc path/to/foo.did -o path/to/foo.as`. + is treated by `moc` by reading `foo.did` as if the developer had + run `didc path/to/foo.did -o path/to/foo.mo`. diff --git a/design/IDL.md b/design/IDL.md index 201f06d481f..534736c4717 100644 --- a/design/IDL.md +++ b/design/IDL.md @@ -852,7 +852,7 @@ service Server : { Note: * `TruckTypeId` and `nat` are used interchangeably. -With this IDL file, the server code in ActorScript could be: +With this IDL file, the server code in Motoko could be: ``` actor Server { registrarAddTruckType(truck_info : TruckTypeInfo) : async ?TruckTypeId { @@ -1092,8 +1092,8 @@ The types of these values are assumed to be known from context, so the syntax do | : ::= - | | | (TODO: same as ActorScript grammar plus sign) - | (TODO: same as ActorScript grammar) + | | | (TODO: same as Motoko grammar plus sign) + | (TODO: same as Motoko grammar) | true | false | null diff --git a/design/Implementation.md b/design/Implementation.md index de74cefdff5..8a2e7c12ead 100644 --- a/design/Implementation.md +++ b/design/Implementation.md @@ -1,4 +1,4 @@ -# ActorScript Implementation Strategy +# Motoko Implementation Strategy ## Subtyping diff --git a/design/Memory.md b/design/Memory.md index 845db5edac3..3c4acd72254 100644 --- a/design/Memory.md +++ b/design/Memory.md @@ -1,4 +1,4 @@ -# Memory Management and Persistence in Wasm/Dfinity/ActorScript +# Memory Management and Persistence in Wasm/Dfinity/Motoko ## Preliminaries diff --git a/design/Syntax.md b/design/Syntax.md index 78247fdceb2..7c69939a80b 100644 --- a/design/Syntax.md +++ b/design/Syntax.md @@ -1,4 +1,4 @@ -# ActorScript Syntax (Sketch) +# Motoko Syntax (Sketch) Productions marked * probably deferred to later versions. diff --git a/emacs/README.md b/emacs/README.md index ac7dd969504..1782208e523 100644 --- a/emacs/README.md +++ b/emacs/README.md @@ -1,7 +1,7 @@ -ActorScript Emacs playground +Motoko Emacs playground === -A minimal set of packages + configuration that lets you use the ActorScript LSP support from within Emacs without having to change your personal configuration. +A minimal set of packages + configuration that lets you use the Motoko LSP support from within Emacs without having to change your personal configuration. ## Getting started diff --git a/emacs/init.el b/emacs/init.el index d40736bd2d9..dd620c666bb 100644 --- a/emacs/init.el +++ b/emacs/init.el @@ -1,8 +1,8 @@ -;; ActorScript Emacs IDE +;; Motoko Emacs IDE ;; === ;; ;; A minimal set of packages + configuration that lets you use the -;; ActorScript LSP support from within Emacs without having to change +;; Motoko LSP support from within Emacs without having to change ;; your personal configuration. ;; ;; Requirements: @@ -16,7 +16,7 @@ ;; ;; 2. Start Emacs from your command line like so: ;; -;; `emacs -q --load ~/code/actorscript/emacs/init.el` +;; `emacs -q --load ~/code/motoko/emacs/init.el` ;; ;; (adjust to match the path to this file) ;; @@ -29,8 +29,8 @@ (setq as/ide-binary "as-ide") ;; Change this to point to the directory where you cloned the -;; actorscript repo -(setq as/installation-directory "~/code/actorscript") +;; motoko repo +(setq as/installation-directory "~/code/motoko") ;; Change nil to t if you want to use vim bindings for editing and ;; navigation @@ -60,22 +60,22 @@ (eval-and-compile (defun as/as-mode-load-path () (format "%s/emacs" as/installation-directory))) -(use-package actorscript-mode +(use-package motoko-mode :load-path (lambda () (list (as/as-mode-load-path))) :config - (add-hook 'actorscript-mode-hook 'flycheck-mode) - (add-hook 'actorscript-mode-hook 'lsp) - (add-hook 'actorscript-mode-hook 'company-mode)) + (add-hook 'motoko-mode-hook 'flycheck-mode) + (add-hook 'motoko-mode-hook 'lsp) + (add-hook 'motoko-mode-hook 'company-mode)) (use-package lsp-mode :ensure t :config (setq lsp-prefer-flymake nil) (setq lsp-auto-configure t) - (add-to-list 'lsp-language-id-configuration '(actorscript-mode . "actorscript")) + (add-to-list 'lsp-language-id-configuration '(motoko-mode . "motoko")) (lsp-register-client (make-lsp-client :new-connection (lsp-stdio-connection as/ide-binary) - :major-modes '(actorscript-mode) + :major-modes '(motoko-mode) :server-id 'asls))) (use-package lsp-ui :ensure t :commands lsp-ui-mode diff --git a/emacs/actorscript-mode.el b/emacs/motoko-mode.el similarity index 90% rename from emacs/actorscript-mode.el rename to emacs/motoko-mode.el index 64485ab2236..a15e95cf5f2 100644 --- a/emacs/actorscript-mode.el +++ b/emacs/motoko-mode.el @@ -1,10 +1,10 @@ -;; ActorScript major mode for Emacs +;; Motoko major mode for Emacs ;; initially based on Swift Mode. -(setq actorscript-font-lock-keywords +(setq motoko-font-lock-keywords (let* ( ;; define several category of keywords - ;; these are each taken from either ActorScript's `lexer.mll' or `prelude.ml' files. + ;; these are each taken from either Motoko's `lexer.mll' or `prelude.ml' files. (x-types '("Any" "None" @@ -155,13 +155,13 @@ (,x-symbols-more-regexp . font-lock-builtin-face) ))) -(define-derived-mode actorscript-mode - swift-mode "ActorScript" - "Major mode for ActorScript, aka 'CanisterScript'." - (setq font-lock-defaults '((actorscript-font-lock-keywords))) +(define-derived-mode motoko-mode + swift-mode "Motoko" + "Major mode for Motoko" + (setq font-lock-defaults '((motoko-font-lock-keywords))) ) -(add-to-list 'auto-mode-alist '("\\.as\\'" . actorscript-mode)) +(add-to-list 'auto-mode-alist '("\\.mo\\'" . motoko-mode)) ;; add the mode to the `features' list -(provide 'actorscript-mode) +(provide 'motoko-mode) diff --git a/guide/.gitignore b/guide/.gitignore index 04e7b8b3ee6..f8167f3d939 100644 --- a/guide/.gitignore +++ b/guide/.gitignore @@ -1,2 +1,2 @@ index.html -actorscript-guide.pdf +motoko-guide.pdf diff --git a/guide/Makefile b/guide/Makefile index b3e4391f316..39da2809415 100644 --- a/guide/Makefile +++ b/guide/Makefile @@ -1,4 +1,4 @@ -all: index.html actorscript-guide.pdf as-slides.html +all: index.html motoko-guide.pdf as-slides.html SHELL=bash @@ -36,7 +36,7 @@ TEX_OPTIONS=\ --include-in-header=<(echo '\newunicodechar{█}{\textrm{\textfallback{█}}}') \ --include-in-header=<(echo '\newunicodechar{ツ}{\textrm{\textfallback{ツ}}}') \ -actorscript-guide.pdf: guide.md +motoko-guide.pdf: guide.md if [ -n "$$NIX_FONTCONFIG_FILE" ]; then export FONTCONFIG_FILE="$$NIX_FONTCONFIG_FILE"; fi; \ pandoc \ --toc \ diff --git a/guide/as-slides.md b/guide/as-slides.md index 8ebdc824e63..437b31bf576 100644 --- a/guide/as-slides.md +++ b/guide/as-slides.md @@ -1,4 +1,4 @@ -% "ActorScript" +% "Motoko" # Overview @@ -59,7 +59,7 @@ Inspirations: Java(Script), C#, Swift, Pony, ML, Haskell * interpreter/compiler up and running via `dvm`. * compiles multiple files by concatenation (good enough for the Produce Exchange) -* documentation (see [draft](actorscript-guide.pdf), 30 pages) +* documentation (see [draft](motoko-guide.pdf), 30 pages) ### Backlog @@ -628,7 +628,7 @@ charlie.start("Charlie", Server); output ``` -[nix-shell:~/actorscript/guide]$ ../src/asc -r chat.as +[nix-shell:~/motoko/guide]$ ../src/moc -r chat.mo charlie received hello from bob alice received hello from bob bob received hello from bob @@ -661,16 +661,16 @@ bob received goodbye from charlie - Other entities: Produce and truck types, regions, reservations - As a communication tool: - Substance: Demonstrate example ActorScript app + Substance: Demonstrate example Motoko app Process: Document internal development process -- [WIP: Canister in ActorScript](https://github.com/dfinity-lab/actorscript/tree/stdlib-examples/stdlib/examples/produce-exchange) +- [WIP: Canister in Motoko](https://github.com/dfinity-lab/motoko/tree/stdlib-examples/stdlib/examples/produce-exchange) ### Produce Exchange: Define MVP [**Full MVP def** on Confluence](https://dfinity.atlassian.net/wiki/spaces/DE/pages/116654198/Produce+Exchange+MVP+Product+Requirements) -[**MVP on ActorScript Canister**](https://github.com/dfinity-lab/actorscript/tree/stdlib-examples/stdlib/examples/produce-exchange#produce-exchange-canister-mvp-requirements) +[**MVP on Motoko Canister**](https://github.com/dfinity-lab/motoko/tree/stdlib-examples/stdlib/examples/produce-exchange#produce-exchange-canister-mvp-requirements) **Summary:** @@ -687,13 +687,13 @@ bob received goodbye from charlie **Summary:** - - People: SDK + ActorScript teams. + - People: SDK + Motoko teams. - Feature-based criteria: Same as MVP. - Test-based criteria: Automated tests. - Operational criteria: Run on DFINITY node. - Performance criteria: Run at certain scales / rates. -### [Produce exchange server components](https://github.com/dfinity-lab/actorscript/tree/stdlib-examples/stdlib/examples/produce-exchange#server-components) +### [Produce exchange server components](https://github.com/dfinity-lab/motoko/tree/stdlib-examples/stdlib/examples/produce-exchange#server-components) - **Server types**: Types for client-server messages - **Server actor**: Interface for client-server messages @@ -701,28 +701,28 @@ bob received goodbye from charlie - **Server model implementation**: Implements the actor -### [Standard library](https://github.com/dfinity-lab/actorscript/tree/stdlib-examples/stdlib#actorscript-standard-library) +### [Standard library](https://github.com/dfinity-lab/motoko/tree/stdlib-examples/stdlib#motoko-standard-library) Why? - Gather reusable components, (e.g., collections for **server model types**) -- Codify best ActorScript practices +- Codify best Motoko practices How? -- ActorScript supports some namespace management, and multiple input files. -- [Documentation](https://github.com/dfinity-lab/actorscript/tree/stdlib-examples/stdlib#actorscript-standard-library) generated from the source code +- Motoko supports some namespace management, and multiple input files. +- [Documentation](https://github.com/dfinity-lab/motoko/tree/stdlib-examples/stdlib#motoko-standard-library) generated from the source code -### [Standard library: Produce exchange](https://github.com/dfinity-lab/actorscript/tree/stdlib-examples/stdlib#produce-exchange) +### [Standard library: Produce exchange](https://github.com/dfinity-lab/motoko/tree/stdlib-examples/stdlib#produce-exchange) We focus on abstractions for implementing the database for the produce exchange: -- [Document Table](https://github.com/dfinity-lab/actorscript/blob/stdlib-examples/design/stdlib/docTable.md): Mutable collection of immutable documents. +- [Document Table](https://github.com/dfinity-lab/motoko/blob/stdlib-examples/design/stdlib/docTable.md): Mutable collection of immutable documents. -- [Hash trie](https://github.com/dfinity-lab/actorscript/blob/stdlib-examples/design/stdlib/trie.md): Immutable finite map representation based on hashing each key. +- [Hash trie](https://github.com/dfinity-lab/motoko/blob/stdlib-examples/design/stdlib/trie.md): Immutable finite map representation based on hashing each key. -- [Association list](https://github.com/dfinity-lab/actorscript/blob/stdlib-examples/design/stdlib/assocList.md): Immutable finite map representation based on a list of key-value pairs. +- [Association list](https://github.com/dfinity-lab/motoko/blob/stdlib-examples/design/stdlib/assocList.md): Immutable finite map representation based on a list of key-value pairs. # (not yet) The End diff --git a/guide/chat.as b/guide/chat.mo similarity index 100% rename from guide/chat.as rename to guide/chat.mo diff --git a/guide/guide.md b/guide/guide.md index 5c846247de2..cc8b3a69a3a 100644 --- a/guide/guide.md +++ b/guide/guide.md @@ -355,7 +355,7 @@ An absent `?` abbreviates `object`. ## Primitive types -ActorScript provides the following primitive type identifiers, including support for Booleans, signed and unsigned integers and machine words of various sizes, characters and text. +Motoko provides the following primitive type identifiers, including support for Booleans, signed and unsigned integers and machine words of various sizes, characters and text. The category of a type determines the operators (unary, binary, relational and in-place update via assigment) applicable to values of that type. diff --git a/guide/schat.as b/guide/schat.mo similarity index 100% rename from guide/schat.as rename to guide/schat.mo diff --git a/rts/.gitignore b/rts/.gitignore index c124feb3ee4..6085d033049 100644 --- a/rts/.gitignore +++ b/rts/.gitignore @@ -1,4 +1,4 @@ -as-rts.wasm +mo-rts.wasm test_rts test_leb128 afl_leb128_out diff --git a/rts/Makefile b/rts/Makefile index cf3540f79c0..a4f5dd47994 100644 --- a/rts/Makefile +++ b/rts/Makefile @@ -4,7 +4,7 @@ WASM_LD ?= wasm-ld-9 # # We manually list all the .c files of libtommath that we care about. -# (Usually the Wasm linker embedded in asc will complain if something is missing.) +# (Usually the Wasm linker embedded in moc will complain if something is missing.) # TOMMATHFILES=\ @@ -57,7 +57,7 @@ WASM_FLAGS = \ .PHONY: all -all: as-rts.wasm test_rts test_leb128 +all: mo-rts.wasm test_rts test_leb128 _build/wasm _build/native: mkdir -p $@ @@ -96,7 +96,7 @@ RTS_NATIVE_O=$(RTSFILES:%=_build/native/%.o) # The actual RTS, as we ship it with the compiler # -as-rts.wasm: $(RTS_WASM_O) $(TOMMATH_WASM_O) +mo-rts.wasm: $(RTS_WASM_O) $(TOMMATH_WASM_O) $(WASM_LD) -o $@ \ --import-memory --shared --no-entry --gc-sections \ --export=__wasm_call_ctors \ @@ -113,5 +113,5 @@ test_leb128: test_leb128.c $(RTS_NATIVE_O) $(TOMMATH_NATIVE_O) $(CLANG) -o $@ $+ clean: - rm -rf _build as-rts.wasm test_rts test_leb128 + rm -rf _build mo-rts.wasm test_rts test_leb128 diff --git a/rts/README.md b/rts/README.md index e1624ff9eed..87eaaba5b89 100644 --- a/rts/README.md +++ b/rts/README.md @@ -1,21 +1,21 @@ -The ActorScript RTS (C parts) +The Motoko RTS (C parts) ============================= -This directory contains the parts of the ActorScript runtime implemented in C. +This directory contains the parts of the Motoko runtime implemented in C. tl;dr ----- -If you just want to get `as-rts.wasm` in this directory, run +If you just want to get `mo-rts.wasm` in this directory, run nix-shell --run 'make -C rts' -from the top-level directory of the ActorScript repository. +from the top-level directory of the Motoko repository. Compilation ----------- -Running `make` should produce `as-rts.wasm`. +Running `make` should produce `mo-rts.wasm`. If run within `nix-shell`, the environment variables `WASM_CLANG` and `WASM_LD` should point to suitable binaries (we track a specific unreleased version of @@ -26,14 +26,14 @@ The runtime compiles and links in [libtommath]. It needs the source, so `nix-build` and `nix-shell` will set the environment variable `TOMMATHSRC` to point to the source in `/nix/store`. If not present, the `Makefile` will look in `../../libtommath`, i.e. parallel to the -`actorscript` repository; this is useful if you need to hack on libtommath. +`motoko` repository; this is useful if you need to hack on libtommath. [libtommath]: https://github.com/libtom/libtommath Exporting and importing functions --------------------------------- -To export a function from C to ActorScript, use the `export` annotation. This +To export a function from C to Motoko, use the `export` annotation. This will make the function be visible in the final shared library. To import a function, use the `from_rts` annotation, e.g. `alloc_bytes`. @@ -43,7 +43,7 @@ libtommath and memory managment ------------------------------- We have to make libtommath’s memory management (which expects C-like functions -`alloc`, `calloc` and `realloc`) work with the ActorScript runtime. See the +`alloc`, `calloc` and `realloc`) work with the Motoko runtime. See the comment next to `mp_alloc` in `rts.c` for the techical details. C tests diff --git a/rts/bigint.c b/rts/bigint.c index 2a377257f95..8c8e7ae611a 100644 --- a/rts/bigint.c +++ b/rts/bigint.c @@ -8,11 +8,11 @@ A libtommath arbitrary precision integer is a struct (`mp_int`) that contains a pointer to a data array. * The libtommath library never allocates the struct, so we are in full - control. We can embed the struct simply in an ActorScript heap object + control. We can embed the struct simply in an Motoko heap object with a dedicated tag for it. * The data array is allocated with mp_calloc and mp_realloc. We provide these - calls, allocate ActorScript arrays (using the TAG_BLOB tag for byte arrays, + calls, allocate Motoko arrays (using the TAG_BLOB tag for byte arrays, not TAG_ARRAY for arrays of pointers) and store the pointer to the _payload_ in the `mp_digit* dp` field of the struct. This way, things look all nice and dandy from libtommath’s point of view. diff --git a/rts/rts.h b/rts/rts.h index 5d4a668c8c5..8f19b419577 100644 --- a/rts/rts.h +++ b/rts/rts.h @@ -11,7 +11,7 @@ #include /* -ActorScript pointers are offset by one. So let us represent +Motoko pointers are offset by one. So let us represent them as a typedef, and access the fields using the payload macro. */ typedef intptr_t as_ptr; @@ -38,7 +38,7 @@ enum as_heap_tag { TAG_BIGINT = 13, }; -/** Functions imported from the ActorScript RTS */ +/** Functions imported from the Motoko RTS */ /* Ideally I’d do something like this @@ -53,8 +53,8 @@ Ideally I’d do something like this But seems we can’t import mutable globals like that, see https://bugs.llvm.org/show_bug.cgi?id=41610 -So in order to allocate on the ActorScript heap from C, we import -alloc_bytes from the Actorscript RTS: +So in order to allocate on the Motoko heap from C, we import +alloc_bytes from the Motoko RTS: */ from_rts as_ptr alloc_bytes(size_t n); char *alloc(size_t n); diff --git a/rts/test_leb128.c b/rts/test_leb128.c index c1b2019b101..9f1e65c19cc 100644 --- a/rts/test_leb128.c +++ b/rts/test_leb128.c @@ -31,7 +31,7 @@ extern int32_t read_i32_of_sleb128(buf *buf); int main(int argc, char** argv) { - printf("ASC LEB128 round-trip tests\n"); + printf("LEB128 round-trip tests\n"); if (argc < 2) { printf("Usage: %s inputfile\n", argv[0]); diff --git a/rts/test_rts.c b/rts/test_rts.c index 57285607c31..41cd39c9e47 100644 --- a/rts/test_rts.c +++ b/rts/test_rts.c @@ -28,7 +28,7 @@ extern bool bigint_eq(as_ptr a, as_ptr b); int main () { - printf("ASC RTS test suite\n"); + printf("Motoko RTS test suite\n"); int ret = EXIT_SUCCESS; diff --git a/samples/ListClient.as b/samples/ListClient.mo similarity index 72% rename from samples/ListClient.as rename to samples/ListClient.mo index f348aadd971..f8c8647fcdf 100644 --- a/samples/ListClient.as +++ b/samples/ListClient.mo @@ -1,6 +1,6 @@ module { -import List = "ListLib.as"; // private, so we don't re-export List +import List = "ListLib.mo"; // private, so we don't re-export List public type Stack = List.List; diff --git a/samples/ListClient.txt b/samples/ListClient.txt index 983cec6ede1..03f7ebe32f4 100644 --- a/samples/ListClient.txt +++ b/samples/ListClient.txt @@ -1,8 +1,8 @@ --- Parsing ListClient.as: --- Parsing ListLib.as: --- Checking ListLib.as: --- Definedness ListLib.as: --- Checking ListClient.as: --- Definedness ListClient.as: --- Interpreting ListLib.as: --- Interpreting ListClient.as: +-- Parsing ListClient.mo: +-- Parsing ListLib.mo: +-- Checking ListLib.mo: +-- Definedness ListLib.mo: +-- Checking ListClient.mo: +-- Definedness ListClient.mo: +-- Interpreting ListLib.mo: +-- Interpreting ListClient.mo: diff --git a/samples/ListLib.as b/samples/ListLib.mo similarity index 100% rename from samples/ListLib.as rename to samples/ListLib.mo diff --git a/samples/ListLib.txt b/samples/ListLib.txt index 0d67633918e..33ec543ee83 100644 --- a/samples/ListLib.txt +++ b/samples/ListLib.txt @@ -1,4 +1,4 @@ --- Parsing ListLib.as: --- Checking ListLib.as: --- Definedness ListLib.as: --- Interpreting ListLib.as: +-- Parsing ListLib.mo: +-- Checking ListLib.mo: +-- Definedness ListLib.mo: +-- Interpreting ListLib.mo: diff --git a/samples/Makefile b/samples/Makefile index a30743dbfdf..f603cf87151 100644 --- a/samples/Makefile +++ b/samples/Makefile @@ -1,19 +1,19 @@ -# Makefile for actorscript demos +# Makefile for motoko demos # This works with bash -ASC?=../src/asc -ASC_FLAGS=-r -t -v +MOC?=../src/moc +MOC_FLAGS=-r -t -v -SAMPLES:=$(basename $(wildcard *.as)) +SAMPLES:=$(basename $(wildcard *.mo)) SUBDIRS:=$(shell ls -d */) all: rm -f *.txt @for sample in $(SAMPLES); do \ - echo "$(ASC) $(ASC_FLAGS) $$sample.as >$$sample.txt 2>&1"; \ - $(ASC) $(ASC_FLAGS) $$sample.as >$$sample.txt 2>&1; \ + echo "$(MOC) $(MOC_FLAGS) $$sample.mo >$$sample.txt 2>&1"; \ + $(MOC) $(MOC_FLAGS) $$sample.mo >$$sample.txt 2>&1; \ cat $$sample.txt; \ done @for dir in $(SUBDIRS); do \ diff --git a/samples/app/Makefile b/samples/app/Makefile index 926ff070520..dfbc817f364 100644 --- a/samples/app/Makefile +++ b/samples/app/Makefile @@ -1,22 +1,22 @@ -# Makefile for actorscript demos +# Makefile for motoko demos # This works with bash -ASC?=../../src/asc +MOC?=../../src/moc DVM?=../../test/dvm.sh -# we need to specify the output if there is more than one .as file +# we need to specify the output if there is more than one .mo file OUT=main.wasm -LIB=list.as types.as server.as client.as +LIB=list.mo types.mo server.mo client.mo SAMPLES:= test all: rm -f main.txt - $(ASC) -ancient-system-api -r -t -v main.as >main.txt 2>&1 + $(MOC) -ancient-system-api -r -t -v main.mo >main.txt 2>&1 cat main.txt dvm: - $(ASC) -ancient-system-api -o $(OUT) main.as + $(MOC) -ancient-system-api -o $(OUT) main.mo $(DVM) $(OUT) clean: diff --git a/samples/app/README.md b/samples/app/README.md index 4edaef412f2..65b9d9538b7 100644 --- a/samples/app/README.md +++ b/samples/app/README.md @@ -1,7 +1,7 @@ # Compiling multiple-files as a single application -This sample shows how to interpret/compile an application consisting of multipl e `.as` files by passing several files on the `asc` command-line. +This sample shows how to interpret/compile an application consisting of multipl e `.mo` files by passing several files on the `moc` command-line. -The application is a version of the single-file [chatpp][../chatpp.as], split into several files. +The application is a version of the single-file [chatpp][../chatpp.mo], split into several files. See the [Makefile](./Makefile) for more details. \ No newline at end of file diff --git a/samples/app/client.as b/samples/app/client.mo similarity index 95% rename from samples/app/client.as rename to samples/app/client.mo index df1dc53466d..9c911992130 100644 --- a/samples/app/client.as +++ b/samples/app/client.mo @@ -1,4 +1,4 @@ -import S "server.as"; +import S "server.mo"; actor class Client() = this { // TODO: these should be constructor params once we can compile them diff --git a/samples/app/list.as b/samples/app/list.mo similarity index 100% rename from samples/app/list.as rename to samples/app/list.mo diff --git a/samples/app/main.as b/samples/app/main.mo similarity index 78% rename from samples/app/main.as rename to samples/app/main.mo index 6632f551174..fb06fc323c6 100644 --- a/samples/app/main.as +++ b/samples/app/main.mo @@ -1,5 +1,5 @@ -import Server "server.as"; -import Client "client.as"; +import Server "server.mo"; +import Client "client.mo"; let server = Server.Server(); let bob = Client.Client(); diff --git a/samples/app/server.as b/samples/app/server.mo similarity index 97% rename from samples/app/server.as rename to samples/app/server.mo index 06348443abf..b8c6c7de039 100644 --- a/samples/app/server.as +++ b/samples/app/server.mo @@ -1,5 +1,5 @@ -import L "list.as"; -import T "types.as"; +import L "list.mo"; +import T "types.mo"; type ClientData = { id : Nat; diff --git a/samples/app/types.as b/samples/app/types.mo similarity index 100% rename from samples/app/types.as rename to samples/app/types.mo diff --git a/samples/counter.as b/samples/counter.mo similarity index 100% rename from samples/counter.as rename to samples/counter.mo diff --git a/samples/hoare.as b/samples/hoare.mo similarity index 100% rename from samples/hoare.as rename to samples/hoare.mo diff --git a/samples/modules.as b/samples/modules.mo similarity index 100% rename from samples/modules.as rename to samples/modules.mo diff --git a/samples/modules.txt b/samples/modules.txt index c86b7edacf7..53f09790293 100644 --- a/samples/modules.txt +++ b/samples/modules.txt @@ -1,12 +1,12 @@ --- Parsing modules.as: --- Checking modules.as: +-- Parsing modules.mo: +-- Checking modules.mo: type List = ?(T, List) type Stack = List let Collections : module {List : module {type List = ?(T, List); cons : (T, List) -> List; nil : () -> List}} let List : module {type List = ?(T, List); cons : (T, List) -> List; nil : () -> List} let empty : ?(Int, List) let push : (Int, Stack) -> Stack --- Definedness modules.as: --- Interpreting modules.as: +-- Definedness modules.mo: +-- Interpreting modules.mo: nil() <= null diff --git a/samples/pa_cars.as b/samples/pa_cars.mo similarity index 100% rename from samples/pa_cars.as rename to samples/pa_cars.mo diff --git a/samples/quicksort.as b/samples/quicksort.mo similarity index 100% rename from samples/quicksort.as rename to samples/quicksort.mo diff --git a/spec/.gitignore b/spec/.gitignore index e4a5546ba1a..2bda39172c8 100644 --- a/spec/.gitignore +++ b/spec/.gitignore @@ -1,5 +1,5 @@ main.pdf -actorscript.pdf +motoko.pdf ## Core latex/pdflatex auxiliary files: *.aux diff --git a/spec/Makefile b/spec/Makefile index dbead843030..f3a2a64a7aa 100644 --- a/spec/Makefile +++ b/spec/Makefile @@ -1,4 +1,4 @@ -NAME = actorscript +NAME = motoko MAIN = main DIRS = figures SRCFILES = $(wildcard *.cls *.tex *.bib Makefile) diff --git a/spec/main.tex b/spec/main.tex index 85f8394c1bc..239f00ee335 100644 --- a/spec/main.tex +++ b/spec/main.tex @@ -14,7 +14,7 @@ \input{defs} -\title{ActorScript} +\title{Motoko} \author{Andreas Rossberg, Claudio Russo} diff --git a/src/.gitignore b/src/.gitignore index e9564d5cf40..31865ff95a7 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -1,10 +1,10 @@ # generated by Makefile -/asc -/as-ld -/as-id -/as-ide +/moc +/mo-ld +/mo-id +/mo-ide /deser -/asc.js +/moc.js /didc # generated by dune diff --git a/src/Makefile b/src/Makefile index 911014ec603..eeb9eb5ea8a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2,45 +2,45 @@ # dependency tracking makefile, it just # calls `dune` -AS_IDE_TARGET = _build/default/exes/as_ide.exe -AS_LD_TARGET = _build/default/exes/as_ld.exe -ASC_TARGET = _build/default/exes/asc.exe +MO_IDE_TARGET = _build/default/exes/mo_ide.exe +MO_LD_TARGET = _build/default/exes/mo_ld.exe +MOC_TARGET = _build/default/exes/moc.exe DIDC_TARGET = _build/default/exes/didc.exe -ASC_JS_TARGET = _build/default/js/as_js.bc.js +MOC_JS_TARGET = _build/default/js/mo_js.bc.js DESER_TARGET = _build/default/exes/deser.exe DUNE_OPTS ?= -ALL_TARGETS = $(AS_IDE_TARGET) $(AS_LD_TARGET) $(ASC_TARGET) $(ASC_JS_TARGET) $(DIDC_TARGET) $(DESER_TARGET) +ALL_TARGETS = $(MO_IDE_TARGET) $(MO_LD_TARGET) $(MOC_TARGET) $(MOC_JS_TARGET) $(DIDC_TARGET) $(DESER_TARGET) -.PHONY: all clean asc as-ide as-ld asc.js didc deser unit-tests +.PHONY: all clean moc mo-ide mo-ld moc.js didc deser unit-tests # This targets is spelled out so that `make` # only invokes `dune` once, much faster all: dune build $(DUNE_OPTS) $(ALL_TARGETS) - @ln -fs $(ASC_TARGET) asc - @ln -fs $(AS_IDE_TARGET) as-ide - @ln -fs $(AS_LD_TARGET) as-ld - @ln -fs $(ASC_JS_TARGET) asc.js + @ln -fs $(MOC_TARGET) moc + @ln -fs $(MO_IDE_TARGET) mo-ide + @ln -fs $(MO_LD_TARGET) mo-ld + @ln -fs $(MOC_JS_TARGET) moc.js @ln -fs $(DIDC_TARGET) didc @ln -fs $(DESER_TARGET) deser -asc: - dune build $(DUNE_OPTS) $(ASC_TARGET) - @ln -fs $(ASC_TARGET) asc +moc: + dune build $(DUNE_OPTS) $(MOC_TARGET) + @ln -fs $(MOC_TARGET) moc -as-ide: - dune build $(DUNE_OPTS) $(AS_IDE_TARGET) - @ln -fs $(AS_IDE_TARGET) as-ide +mo-ide: + dune build $(DUNE_OPTS) $(MO_IDE_TARGET) + @ln -fs $(MO_IDE_TARGET) mo-ide -as-ld: - dune build $(DUNE_OPTS) $(AS_LD_TARGET) - @ln -fs $(AS_LD_TARGET) as-ld +mo-ld: + dune build $(DUNE_OPTS) $(MO_LD_TARGET) + @ln -fs $(MO_LD_TARGET) mo-ld -asc.js: - dune build $(DUNE_OPTS) $(ASC_JS_TARGET) - @ln -fs $(ASC_JS_TARGET) asc.js +moc.js: + dune build $(DUNE_OPTS) $(MOC_JS_TARGET) + @ln -fs $(MOC_JS_TARGET) moc.js didc: dune build $(DUNE_OPTS) $(DIDC_TARGET) @@ -54,13 +54,13 @@ unit-tests: dune runtest $(DUNE_OPTS) clean: - rm -f asc as-ide as-ld asc.js didc deser + rm -f moc mo-ide mo-ld moc.js didc deser dune clean test: $(NAME) - make -C ../test ASC=$(ASC) all - make -C ../stdlib ASC=$(ASC) all - make -C ../samples ASC=$(ASC) all + make -C ../test MOC=$(MOC) all + make -C ../stdlib MOC=$(MOC) all + make -C ../samples MOC=$(MOC) all test-quick: $(NAME) - make -C ../test ASC=$(ASC) quick + make -C ../test MOC=$(MOC) quick diff --git a/src/Structure.md b/src/Structure.md index 7b5a0e59477..4298780be3b 100644 --- a/src/Structure.md +++ b/src/Structure.md @@ -27,63 +27,63 @@ for the real deal; some shortcuts had to be taken. Stuff that could be in the Ocaml standard library. - * `lang_utils/` (asc, didc; using `lib/`) + * `lang_utils/` (moc, didc; using `lib/`) General PL-related utility-functions, useful for AS Source, AS IR, the IDL AST: Environments, diagnostic error messages, source locations. - * `as_def/` (asc; using `lang_utils/`) + * `mo_def/` (moc; using `lang_utils/`) - The ActorScript AST and pretty-printer. + The Motoko AST and pretty-printer. - * `as_types/` (asc; using `lang_utils/`) + * `mo_types/` (moc; using `lang_utils/`) - The ActorScript type definition, as used by both Source and IR. Includes + The Motoko type definition, as used by both Source and IR. Includes pretty-printer. - * `as_values/` (asc; using `lang_utils/`) + * `mo_values/` (moc; using `lang_utils/`) Value definitions, as used for literals, interpreter. Also includes operations on values and primitive operations. - * `as_frontend/` (asc; using `lang_utils/` and `as_def`) + * `mo_frontend/` (moc; using `lang_utils/` and `mo_def`) - The ActorScript parser and type checker. + The Motoko parser and type checker. - * `ir_def/` (asc; using `lang_utils/`) + * `ir_def/` (moc; using `lang_utils/`) - The ActorScript IR AST, including type checker and pretty-printer. + The Motoko IR AST, including type checker and pretty-printer. - * `lowering/` (asc; using `as_def/` and `ir_def/`) + * `lowering/` (moc; using `mo_def/` and `ir_def/`) The IR to Source pass. - * `ir_passes/` (asc; using `as_def/`) + * `ir_passes/` (moc; using `mo_def/`) The various IR to IR passes. - * `wasm_exts/` (asc, as-ld; using `lib/`) + * `wasm_exts/` (moc, mo-ld; using `lib/`) Extensions to the wasm library: Support for additional custom sections, including serialization and de-serialization. - * `linking/` (asc, as-ld; using `wasm_exts/`) + * `linking/` (moc, mo-ld; using `wasm_exts/`) Wasm linking code - * `codegen/` (asc; using `ir_def/`, `linking/`) + * `codegen/` (moc; using `ir_def/`, `linking/`) The backend, including the instruction list generator. - * `interpreter/` (asc; using `as_def/`) + * `interpreter/` (moc; using `mo_def/`) Source interpreter. - * `ir_interpreter/` (asc; using `ir_def/`) + * `ir_interpreter/` (moc; using `ir_def/`) IR interpreter. - * `pipeline/` (asc; using `as_frontend/`, `lowering/`, `ir_passes/`, `codegen/`, `as_interpreter/`, `ir_interpreter/`) + * `pipeline/` (moc; using `mo_frontend/`, `lowering/`, `ir_passes/`, `codegen/`, `mo_interpreter/`, `ir_interpreter/`) The pipeline, prelude text and flags @@ -106,19 +106,19 @@ All exectuables are in the directory `exe/`, and should be kept rather small; essentially only the command line parsing should be there, so that actual functionality is easily shared. - * `asc` (using `pipeline/`) + * `moc` (using `pipeline/`) - The ActorScript compiler + The Motoko compiler - * `as-ide` (using `languageServer/`) + * `mo-ide` (using `languageServer/`) - The ActorScript language server + The Motoko language server - * `as.js` (using `pipeline/`) + * `mo.js` (using `pipeline/`) - The ActorScript compiler, as a JS library + The Motoko compiler, as a JS library - * `as-ld` (using `linking/`) + * `mo-ld` (using `linking/`) The stand-alone Wasm linker diff --git a/src/as_config/dune b/src/as_config/dune deleted file mode 100644 index af688334322..00000000000 --- a/src/as_config/dune +++ /dev/null @@ -1,3 +0,0 @@ -(library - (name as_config) -) diff --git a/src/as_def/dune b/src/as_def/dune deleted file mode 100644 index f943cacfa60..00000000000 --- a/src/as_def/dune +++ /dev/null @@ -1,4 +0,0 @@ -(library - (name as_def) - (libraries lib lang_utils as_types as_values) -) diff --git a/src/as_idl/dune b/src/as_idl/dune deleted file mode 100644 index 4d2cd7373e0..00000000000 --- a/src/as_idl/dune +++ /dev/null @@ -1,4 +0,0 @@ -(library - (name as_idl) - (libraries lib idllib lang_utils as_types as_def) -) diff --git a/src/as_interpreter/dune b/src/as_interpreter/dune deleted file mode 100644 index a42874c2048..00000000000 --- a/src/as_interpreter/dune +++ /dev/null @@ -1,4 +0,0 @@ -(library - (name as_interpreter) - (libraries lib as_config as_def as_types as_values profiler) -) diff --git a/src/as_types/dune b/src/as_types/dune deleted file mode 100644 index 9e5d4e891ac..00000000000 --- a/src/as_types/dune +++ /dev/null @@ -1,4 +0,0 @@ -(library - (name as_types) - (libraries wasm lib lang_utils as_config) -) diff --git a/src/as_values/dune b/src/as_values/dune deleted file mode 100644 index 341f197eb55..00000000000 --- a/src/as_values/dune +++ /dev/null @@ -1,4 +0,0 @@ -(library - (name as_values) - (libraries num wasm lib lang_utils as_types idllib) -) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 247c0627002..659561d0f46 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -1,5 +1,5 @@ (* -This module is the backend of the ActorScript compiler. It takes a program in +This module is the backend of the Motoko compiler. It takes a program in the intermediate representation (ir.ml), and produces a WebAssembly module, with DFINITY extensions (customModule.ml). An important helper module is instrList.ml, which provides a more convenient way of assembling WebAssembly @@ -11,9 +11,9 @@ this keeps documentation close to the code (a lesson learned from Simon PJ). *) open Ir_def -open As_values -open As_types -open As_config +open Mo_values +open Mo_types +open Mo_config open Wasm.Ast open Wasm.Types @@ -85,7 +85,7 @@ The fields fall into the following categories: Example: whether we are compiling with -no-system-api; the prelude code 2. Immutable global fields. Change in a well-scoped manner. - Example: Mapping from ActorScript names to their location. + Example: Mapping from Motoko names to their location. 3. Mutable global fields. Change only monotonously. These are used to register things like functions. This should be monotone @@ -391,7 +391,7 @@ end (* General code generation functions: - Rule of thumb: Here goes stuff that independent of the ActorScript AST. + Rule of thumb: Here goes stuff that independent of the Motoko AST. *) (* Function called compile_* return a list of instructions (and maybe other stuff) *) @@ -1175,7 +1175,7 @@ module Tagged = struct (* Needs to be conservative, i.e. return `true` if unsure *) (* This function can also be used as assertions in a lint mode, e.g. in compile_exp *) let can_have_tag ty tag = - let open As_types.Type in + let open Mo_types.Type in match (tag : tag) with | Array -> begin match normalize ty with @@ -1260,7 +1260,7 @@ module Variant = struct let tag_field = Tagged.header_size let payload_field = Int32.add Tagged.header_size 1l - let hash_variant_label : As_types.Type.lab -> int32 = fun l -> + let hash_variant_label : Mo_types.Type.lab -> int32 = fun l -> Int32.of_int (Hashtbl.hash l) let inject env l e = @@ -3190,7 +3190,7 @@ module Dfinity = struct get_api_nonce env ^^ arg_instrs ^^ G.i Drop ^^ (* TODO: - https://github.com/dfinity-lab/actorscript/issues/679 + https://github.com/dfinity-lab/motoko/issues/679 don't drop but extract payload, once reject complies with spec *) compile_unboxed_const error_code_CANISTER_REJECT ^^ system_call env "msg" "reject" @@ -4474,7 +4474,7 @@ module VarLoc = struct ; is_local : bool (* Only valid within the current function *) } - (* A type to record where ActorScript names are stored. *) + (* A type to record where Motoko names are stored. *) type varloc = (* A Wasm Local of the current function, directly containing the value (note that most values are pointers, but not all) @@ -4627,9 +4627,9 @@ module StackRep = struct end (* StackRep *) -module ASEnv = struct +module VarEnv = struct (* - The ActorScript specific environment: + The source variable environment: In scope variables and in-scope jump labels *) @@ -4702,16 +4702,16 @@ module ASEnv = struct | Some d -> d | None -> Printf.eprintf "Could not find %s\n" name; raise Not_found -end (* ASEnv *) +end (* VarEnv *) module Var = struct - (* This module is all about looking up ActorScript variables in the environment, + (* This module is all about looking up Motoko variables in the environment, and dealing with mutable variables *) open VarLoc (* Stores the payload (which is found on the stack) *) - let set_val env ae var = match ASEnv.lookup_var ae var with + let set_val env ae var = match VarEnv.lookup_var ae var with | Some (Local i) -> G.i (LocalSet (nr i)) | Some (HeapInd (i, off)) -> @@ -4730,7 +4730,7 @@ module Var = struct | None -> assert false (* Returns the payload (optimized representation) *) - let get_val (env : E.t) (ae : ASEnv.t) var = match ASEnv.lookup_var ae var with + let get_val (env : E.t) (ae : VarEnv.t) var = match VarEnv.lookup_var ae var with | Some (Local i) -> SR.Vanilla, G.i (LocalGet (nr i)) | Some (HeapInd (i, off)) -> @@ -4742,26 +4742,26 @@ module Var = struct | None -> assert false (* Returns the payload (vanilla representation) *) - let get_val_vanilla (env : E.t) (ae : ASEnv.t) var = + let get_val_vanilla (env : E.t) (ae : VarEnv.t) var = let sr, code = get_val env ae var in code ^^ StackRep.adjust env sr SR.Vanilla (* Returns the value to put in the closure, and code to restore it, including adding to the environment *) - let capture old_env ae0 var : G.t * (E.t -> ASEnv.t -> (ASEnv.t * G.t)) = - match ASEnv.lookup_var ae0 var with + let capture old_env ae0 var : G.t * (E.t -> VarEnv.t -> (VarEnv.t * G.t)) = + match VarEnv.lookup_var ae0 var with | Some (Local i) -> ( G.i (LocalGet (nr i)) , fun new_env ae1 -> - let (ae2, j) = ASEnv.add_direct_local new_env ae1 var in + let (ae2, j) = VarEnv.add_direct_local new_env ae1 var in let restore_code = G.i (LocalSet (nr j)) in (ae2, restore_code) ) | Some (HeapInd (i, off)) -> ( G.i (LocalGet (nr i)) , fun new_env ae1 -> - let (ae2, j) = ASEnv.add_local_with_offset new_env ae1 var off in + let (ae2, j) = VarEnv.add_local_with_offset new_env ae1 var off in let restore_code = G.i (LocalSet (nr j)) in (ae2, restore_code) ) @@ -4770,7 +4770,7 @@ module Var = struct ( d.materialize old_env ^^ StackRep.adjust old_env d.stack_rep SR.Vanilla , fun new_env ae1 -> - let (ae2, j) = ASEnv.add_direct_local new_env ae1 var in + let (ae2, j) = VarEnv.add_direct_local new_env ae1 var in let restore_code = G.i (LocalSet (nr j)) in (ae2, restore_code) ) @@ -4782,7 +4782,7 @@ module Var = struct let field_box env code = Tagged.obj env Tagged.ObjInd [ code ] - let get_val_ptr env ae var = match ASEnv.lookup_var ae var with + let get_val_ptr env ae var = match VarEnv.lookup_var ae var with | Some (HeapInd (i, 1l)) -> G.i (LocalGet (nr i)) | Some (Static _) -> assert false (* we never do this on the toplevel *) | _ -> field_box env (get_val_vanilla env ae var) @@ -4840,7 +4840,7 @@ module FuncDec = struct let arg_names = List.map (fun a -> a.it, I32Type) args in let n_res = List.length ret_tys in let retty = Lib.List.make n_res I32Type in - let ae0 = ASEnv.mk_fun_ae outer_ae in + let ae0 = VarEnv.mk_fun_ae outer_ae in Func.of_body outer_env (["clos", I32Type] @ arg_names) retty (fun env -> G.with_region at ( let get_closure = G.i (LocalGet (nr 0l)) in @@ -4848,7 +4848,7 @@ module FuncDec = struct (* Add arguments to the environment *) let ae2 = bind_args ae1 1 args (fun env a get -> - ASEnv.add_local_deferred env a.it SR.Vanilla (fun _ -> get) true + VarEnv.add_local_deferred env a.it SR.Vanilla (fun _ -> get) true ) in closure_code ^^ @@ -4866,7 +4866,7 @@ module FuncDec = struct let compile_message outer_env outer_ae sort restore_env args mk_body ret_tys at = assert (E.mode outer_env = Flags.AncientMode); assert (List.length ret_tys = 0); - let ae0 = ASEnv.mk_fun_ae outer_ae in + let ae0 = VarEnv.mk_fun_ae outer_ae in Func.of_body outer_env ["clos", I32Type; "databuf", I32Type; "elembuf", I32Type] [] (fun env -> G.with_region at ( let get_databuf = G.i (LocalGet (nr 1l)) in let get_elembuf = G.i (LocalGet (nr 2l)) in @@ -4885,7 +4885,7 @@ module FuncDec = struct (* Deserialize argument and add params to the environment *) let arg_names = List.map (fun a -> a.it) args in let arg_tys = List.map (fun a -> a.note) args in - let (ae2, setters) = ASEnv.add_argument_locals env ae1 arg_names in + let (ae2, setters) = VarEnv.add_argument_locals env ae1 arg_names in get_databuf ^^ get_elembuf ^^ Serialization.deserialize env arg_tys ^^ G.concat (List.rev setters) ^^ @@ -4909,7 +4909,7 @@ module FuncDec = struct match E.mode outer_env with | Flags.AncientMode -> assert (List.length ret_tys = 0); - let ae0 = ASEnv.mk_fun_ae outer_ae in + let ae0 = VarEnv.mk_fun_ae outer_ae in Func.of_body outer_env ["databuf", I32Type; "elembuf", I32Type] [] (fun env -> G.with_region at ( let get_databuf = G.i (LocalGet (nr 0l)) in let get_elembuf = G.i (LocalGet (nr 1l)) in @@ -4920,7 +4920,7 @@ module FuncDec = struct (* Deserialize argument and add params to the environment *) let arg_names = List.map (fun a -> a.it) args in let arg_tys = List.map (fun a -> a.note) args in - let (ae1, setters) = ASEnv.add_argument_locals env ae0 arg_names in + let (ae1, setters) = VarEnv.add_argument_locals env ae0 arg_names in get_databuf ^^ get_elembuf ^^ Serialization.deserialize env arg_tys ^^ G.concat (List.rev setters) ^^ @@ -4939,14 +4939,14 @@ module FuncDec = struct | _ -> assert false )) | Flags.ICMode -> - let ae0 = ASEnv.mk_fun_ae outer_ae in + let ae0 = VarEnv.mk_fun_ae outer_ae in Func.of_body outer_env ["api_nonce", I64Type] [] (fun env -> G.with_region at ( G.i (LocalGet (nr 0l)) ^^ Dfinity.set_api_nonce env ^^ (* Deserialize argument and add params to the environment *) let arg_names = List.map (fun a -> a.it) args in let arg_tys = List.map (fun a -> a.note) args in - let (ae1, setters) = ASEnv.add_argument_locals env ae0 arg_names in + let (ae1, setters) = VarEnv.add_argument_locals env ae0 arg_names in Serialization.deserialize env arg_tys ^^ G.concat (List.rev setters) ^^ mk_body env ae1 ^^ @@ -5061,7 +5061,7 @@ module FuncDec = struct Dfinity.system_call env "func" "bind_i32" let lit env ae how name sort free_vars args mk_body ret_tys at = - let captured = List.filter (ASEnv.needs_capture ae) free_vars in + let captured = List.filter (VarEnv.needs_capture ae) free_vars in if captured = [] then @@ -5215,7 +5215,7 @@ module AllocHow = struct (* Does this capture nothing from outside? *) (S.is_empty (S.inter (Freevars.captured_vars f) - (set_of_map (M.filter (fun _ x -> not (VarLoc.is_non_local x)) (ae.ASEnv.vars))))) && + (set_of_map (M.filter (fun _ x -> not (VarLoc.is_non_local x)) (ae.VarEnv.vars))))) && (* Does this capture nothing non-static from here? *) (S.is_empty (S.inter (Freevars.captured_vars f) @@ -5306,12 +5306,12 @@ module AllocHow = struct (* Functions to extend the environment (and possibly allocate memory) based on how we want to store them. *) - let add_how env ae name : nonStatic option -> ASEnv.t * G.t = function + let add_how env ae name : nonStatic option -> VarEnv.t * G.t = function | Some LocalImmut | Some LocalMut -> - let (ae1, i) = ASEnv.add_direct_local env ae name in + let (ae1, i) = VarEnv.add_direct_local env ae name in (ae1, G.nop) | Some StoreHeap -> - let (ae1, i) = ASEnv.add_local_with_offset env ae name 1l in + let (ae1, i) = VarEnv.add_local_with_offset env ae name 1l in let alloc_code = Tagged.obj env Tagged.MutBox [ compile_unboxed_zero ] ^^ G.i (LocalSet (nr i)) in @@ -5320,7 +5320,7 @@ module AllocHow = struct let tag = bytes_of_int32 (Tagged.int_of_tag Tagged.MutBox) in let zero = bytes_of_int32 0l in let ptr = E.add_mutable_static_bytes env (tag ^ zero) in - let ae1 = ASEnv.add_local_static ae name ptr in + let ae1 = VarEnv.add_local_static ae name ptr in (ae1, G.nop) | None -> (ae, G.nop) @@ -6331,12 +6331,12 @@ and compile_exp (env : E.t) ae exp = SR.Vanilla, G.block_ (StackRep.to_block_type env SR.Vanilla) ( G.with_current_depth (fun depth -> - let ae1 = ASEnv.add_label ae name depth in + let ae1 = VarEnv.add_label ae name depth in compile_exp_vanilla env ae1 e ) ) | BreakE (name, e) -> - let d = ASEnv.get_label_depth ae name in + let d = VarEnv.get_label_depth ae name in SR.Unreachable, compile_exp_vanilla env ae e ^^ G.branch_to_ d @@ -6417,7 +6417,7 @@ and compile_exp (env : E.t) ae exp = code1 ^^ set_i ^^ orTrap env code2 ^^ get_j (* Async-wait lowering support features *) | DeclareE (name, _, e) -> - let (ae1, i) = ASEnv.add_local_with_offset env ae name 1l in + let (ae1, i) = VarEnv.add_local_with_offset env ae name 1l in let sr, code = compile_exp env ae1 e in sr, Tagged.obj env Tagged.MutBox [ compile_unboxed_zero ] ^^ @@ -6636,11 +6636,11 @@ and fill_pat env ae pat : patternCode = and alloc_pat_local env ae pat = let (_,d) = Freevars.pat pat in AllocHow.S.fold (fun v ae -> - let (ae1, _i) = ASEnv.add_direct_local env ae v + let (ae1, _i) = VarEnv.add_direct_local env ae v in ae1 ) d ae -and alloc_pat env ae how pat : ASEnv.t * G.t = +and alloc_pat env ae how pat : VarEnv.t * G.t = (fun (ae,code) -> (ae, G.with_region pat.at code)) @@ let (_,d) = Freevars.pat pat in AllocHow.S.fold (fun v (ae,code0) -> @@ -6648,7 +6648,7 @@ and alloc_pat env ae how pat : ASEnv.t * G.t = in (ae1, code0 ^^ code1) ) d (ae, G.nop) -and compile_pat_local env ae pat : ASEnv.t * patternCode = +and compile_pat_local env ae pat : VarEnv.t * patternCode = (* It returns: - the extended environment - the code to do the pattern matching. @@ -6692,7 +6692,7 @@ and compile_n_ary_pat env ae how pat = orTrap env (fill_pat env ae1 pat) in (ae1, alloc_code, arity, fill_code) -and compile_dec env pre_ae how dec : ASEnv.t * G.t * (ASEnv.t -> G.t) = +and compile_dec env pre_ae how dec : VarEnv.t * G.t * (VarEnv.t -> G.t) = (fun (pre_ae,alloc_code,mk_code) -> (pre_ae, G.with_region dec.at alloc_code, fun ae -> G.with_region dec.at (mk_code ae))) @@ @@ -6702,7 +6702,7 @@ and compile_dec env pre_ae how dec : ASEnv.t * G.t * (ASEnv.t -> G.t) = (* A special case for static expressions *) | LetD ({it = VarP v; _}, e) when not (AllocHow.M.mem v how) -> let (static_thing, fill) = compile_static_exp env pre_ae how e in - let pre_ae1 = ASEnv.add_local_deferred pre_ae v + let pre_ae1 = VarEnv.add_local_deferred pre_ae v (SR.StaticThing static_thing) (fun _ -> G.nop) false in ( pre_ae1, G.nop, fun ae -> fill env ae; G.nop) | LetD (p, e) -> @@ -6722,7 +6722,7 @@ and compile_dec env pre_ae how dec : ASEnv.t * G.t * (ASEnv.t -> G.t) = Var.set_val env ae name ) -and compile_decs env ae lvl decs captured_in_body : ASEnv.t * G.t = +and compile_decs env ae lvl decs captured_in_body : VarEnv.t * G.t = let how = AllocHow.decs ae lvl decs captured_in_body in let rec go pre_ae decs = match decs with | [] -> (pre_ae, G.nop, fun _ -> G.nop) @@ -6760,7 +6760,7 @@ and compile_static_exp env pre_ae how exp = match exp.it with | FuncE (name, sort, _control, typ_binds, args, ret_tys, e) -> let mk_body env ae = assert begin (* Is this really closed? *) - List.for_all (fun v -> ASEnv.NameEnv.mem v ae.ASEnv.vars) + List.for_all (fun v -> VarEnv.NameEnv.mem v ae.VarEnv.vars) (Freevars.M.keys (Freevars.exp e)) end; compile_exp_as env ae (StackRep.of_arity (List.length ret_tys)) e in @@ -6787,9 +6787,9 @@ and find_prelude_names env = Dfinity.system_imports env0; RTS.system_imports env0; let env1 = E.mk_fun_env env0 0l 0 in - let ae = ASEnv.empty_ae in + let ae = VarEnv.empty_ae in let (env2, _) = compile_prelude env1 ae in - ASEnv.in_scope_set env2 + VarEnv.in_scope_set env2 and compile_start_func mod_env (progs : Ir.prog list) : E.func_with_names = @@ -6826,7 +6826,7 @@ and compile_start_func mod_env (progs : Ir.prog list) : E.func_with_names = let (ae1, code1) = compile_prog env ae prog in let code2 = go ae1 progs in code1 ^^ code2 in - go ASEnv.empty_ae progs + go VarEnv.empty_ae progs ) and export_actor_field env ae (f : Ir.field) = @@ -6842,7 +6842,7 @@ and export_actor_field env ae (f : Ir.field) = name = Wasm.Utf8.decode (match E.mode env with | Flags.AncientMode -> f.it.name | Flags.ICMode -> - As_types.Type.( + Mo_types.Type.( match normalize f.note with | Func(Shared sort,_,_,_,_) -> (match sort with @@ -6875,13 +6875,13 @@ and actor_lit outer_env this ds fs at = let start_fun = Func.of_body mod_env [] [] (fun env -> G.with_region at @@ - let ae0 = ASEnv.empty_ae in + let ae0 = VarEnv.empty_ae in (* Compile the prelude *) let (ae1, prelude_code) = compile_prelude env ae0 in (* Add this pointer *) - let ae2 = ASEnv.add_local_deferred ae1 this SR.Vanilla Dfinity.get_self_reference false in + let ae2 = VarEnv.add_local_deferred ae1 this SR.Vanilla Dfinity.get_self_reference false in (* Compile the declarations *) let (ae3, decls_code) = compile_decs env ae2 AllocHow.TopLvl ds Freevars.S.empty in @@ -6907,7 +6907,7 @@ and actor_lit outer_env this ds fs at = (* Main actor: Just return the initialization code, and export functions as needed *) and main_actor env ae1 this ds fs = (* Add this pointer *) - let ae2 = ASEnv.add_local_deferred ae1 this SR.Vanilla Dfinity.get_self_reference false in + let ae2 = VarEnv.add_local_deferred ae1 this SR.Vanilla Dfinity.get_self_reference false in (* Compile the declarations *) let (ae3, decls_code) = compile_decs env ae2 AllocHow.TopLvl ds Freevars.S.empty in diff --git a/src/codegen/compile.mli b/src/codegen/compile.mli index 7233dfb6786..b5073d43fd8 100644 --- a/src/codegen/compile.mli +++ b/src/codegen/compile.mli @@ -1,3 +1,3 @@ open Ir_def -val compile : As_config.Flags.compile_mode -> string -> Wasm_exts.CustomModule.extended_module option -> Ir.prog -> Ir.prog list -> Wasm_exts.CustomModule.extended_module +val compile : Mo_config.Flags.compile_mode -> string -> Wasm_exts.CustomModule.extended_module option -> Ir.prog -> Ir.prog list -> Wasm_exts.CustomModule.extended_module diff --git a/src/codegen/dune b/src/codegen/dune index 3f4b795c8d7..c3490d60fbe 100644 --- a/src/codegen/dune +++ b/src/codegen/dune @@ -1,4 +1,4 @@ (library (name codegen) - (libraries wasm lib as_config lang_utils wasm_exts ir_def linking) + (libraries wasm lib mo_config lang_utils wasm_exts ir_def linking) ) diff --git a/src/exes/dune b/src/exes/dune index 22bf5c23e2f..82c5d3e6046 100644 --- a/src/exes/dune +++ b/src/exes/dune @@ -1,16 +1,16 @@ (executable - (name asc) - (modules asc) + (name moc) + (modules moc) (libraries profiler pipeline) ) (executable - (name as_ide) - (modules as_ide) + (name mo_ide) + (modules mo_ide) (libraries languageServer) ) (executable - (name as_ld) - (modules as_ld) + (name mo_ld) + (modules mo_ld) (libraries wasm_exts linking) ) (executable diff --git a/src/exes/as_ide.ml b/src/exes/mo_ide.ml similarity index 100% rename from src/exes/as_ide.ml rename to src/exes/mo_ide.ml diff --git a/src/exes/as_ld.ml b/src/exes/mo_ld.ml similarity index 92% rename from src/exes/as_ld.ml rename to src/exes/mo_ld.ml index 16d7a317e6b..8248b9133a3 100644 --- a/src/exes/as_ld.ml +++ b/src/exes/mo_ld.ml @@ -2,9 +2,9 @@ open Linking open Wasm_exts open Printf -let name = "as-ld" +let name = "mo-ld" let version = "0.1" -let banner = "ActorScript " ^ version ^ " linker" +let banner = "Motoko " ^ version ^ " linker" let usage = "Usage: " ^ name ^ " -b base.wasm -l shared.wasm -o out.wasm" (* Argument handling *) @@ -25,7 +25,7 @@ let usage_err s = let argspec = Arg.align [ - "-b", Arg.Set_string base_file, " base file (e.g. output of asc --no-link)"; + "-b", Arg.Set_string base_file, " base file (e.g. output of moc --no-link)"; "-l", Arg.Set_string lib_file, " library file"; "-o", Arg.Set_string out_file, " output file"; "-n", Arg.Set_string lib_name, " library name (defaults to \"rts\")"; diff --git a/src/exes/asc.ml b/src/exes/moc.ml similarity index 95% rename from src/exes/asc.ml rename to src/exes/moc.ml index fe0b6e9fee8..aa866b1420e 100644 --- a/src/exes/asc.ml +++ b/src/exes/moc.ml @@ -1,11 +1,11 @@ open Wasm_exts -open As_config +open Mo_config open Printf -let name = "asc" +let name = "moc" let version = "0.1" -let banner = "ActorScript " ^ version ^ " interpreter" +let banner = "Motoko " ^ version ^ " interpreter" let usage = "Usage: " ^ name ^ " [option] [file ...]" @@ -19,7 +19,7 @@ let add_arg source = args := !args @ [source] let set_mode m () = if !mode <> Default then begin - eprintf "asc: multiple execution modes specified"; exit 1 + eprintf "moc: multiple execution modes specified"; exit 1 end; mode := m @@ -94,7 +94,7 @@ let set_out_file files ext = if !out_file = "" then begin match files with | [n] -> out_file := Filename.remove_extension (Filename.basename n) ^ ext - | ns -> eprintf "asc: no output file specified"; exit 1 + | ns -> eprintf "moc: no output file specified"; exit 1 end (* Main *) @@ -139,7 +139,7 @@ let process_files files : unit = (* Copy relevant flags into the profiler library's (global) settings. This indirection affords the profiler library an independence from the (hacky) Flags library. See also, this discussion: - https://github.com/dfinity-lab/actorscript/pull/405#issuecomment-503326551 + https://github.com/dfinity-lab/motoko/pull/405#issuecomment-503326551 *) let process_profiler_flags () = ProfilerFlags.profile := !Flags.profile; diff --git a/src/exes/asc.mli b/src/exes/moc.mli similarity index 100% rename from src/exes/asc.mli rename to src/exes/moc.mli diff --git a/src/ir_def/arrange_ir.ml b/src/ir_def/arrange_ir.ml index 48ea27c9e4e..4cf0bb0473d 100644 --- a/src/ir_def/arrange_ir.ml +++ b/src/ir_def/arrange_ir.ml @@ -1,5 +1,5 @@ -open As_types -open As_values +open Mo_types +open Mo_values open Source open Ir open Wasm.Sexpr diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index af5e1f581b8..fee306d94c5 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -1,5 +1,5 @@ -open As_types -open As_values +open Mo_types +open Mo_values open Source module T = Type diff --git a/src/ir_def/check_ir.mli b/src/ir_def/check_ir.mli index da01840917f..4ca842d7c72 100644 --- a/src/ir_def/check_ir.mli +++ b/src/ir_def/check_ir.mli @@ -1 +1 @@ -val check_prog : bool -> As_types.Scope.scope -> string -> Ir.prog -> unit +val check_prog : bool -> Mo_types.Scope.scope -> string -> Ir.prog -> unit diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index 388edf63980..e6e564180bc 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -3,7 +3,7 @@ open Source open Ir open Ir_effect -module T = As_types.Type +module T = Mo_types.Type type var = exp diff --git a/src/ir_def/construct.mli b/src/ir_def/construct.mli index 284e04f658c..da83b639391 100644 --- a/src/ir_def/construct.mli +++ b/src/ir_def/construct.mli @@ -1,4 +1,4 @@ -open As_types +open Mo_types open Ir open Type diff --git a/src/ir_def/dune b/src/ir_def/dune index e2314901c80..42612b316ca 100644 --- a/src/ir_def/dune +++ b/src/ir_def/dune @@ -1,4 +1,4 @@ (library (name ir_def) - (libraries lib as_types as_values) + (libraries lib mo_types mo_values) ) diff --git a/src/ir_def/ir.ml b/src/ir_def/ir.ml index 7c6a88213c0..418ff4d2298 100644 --- a/src/ir_def/ir.ml +++ b/src/ir_def/ir.ml @@ -1,5 +1,5 @@ -open As_types -open As_values +open Mo_types +open Mo_values type id = string diff --git a/src/ir_def/ir_effect.ml b/src/ir_def/ir_effect.ml index 813fe153fc9..e818cd03a66 100644 --- a/src/ir_def/ir_effect.ml +++ b/src/ir_def/ir_effect.ml @@ -1,6 +1,6 @@ open Ir open Source -module T = As_types.Type +module T = Mo_types.Type (* a simple effect analysis to annote expressions as Triv(ial) (await-free) or Await (containing unprotected awaits) *) diff --git a/src/ir_def/ir_effect.mli b/src/ir_def/ir_effect.mli index e6a52ba911c..9fddc14f0b4 100644 --- a/src/ir_def/ir_effect.mli +++ b/src/ir_def/ir_effect.mli @@ -1,6 +1,6 @@ open Source open Ir -open As_types.Type +open Mo_types.Type val max_eff : eff -> eff -> eff diff --git a/src/ir_interpreter/dune b/src/ir_interpreter/dune index 76f2ee2a74a..2ce46af9bed 100644 --- a/src/ir_interpreter/dune +++ b/src/ir_interpreter/dune @@ -1,4 +1,4 @@ (library (name ir_interpreter) - (libraries lib as_types as_values ir_def profiler) + (libraries lib mo_types mo_values ir_def profiler) ) diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index 342d300490d..511ed4cd872 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -1,5 +1,5 @@ -open As_types -open As_values +open Mo_types +open Mo_values open Ir_def open Ir diff --git a/src/ir_interpreter/interpret_ir.mli b/src/ir_interpreter/interpret_ir.mli index 97c54b6cfb9..420224d67e6 100644 --- a/src/ir_interpreter/interpret_ir.mli +++ b/src/ir_interpreter/interpret_ir.mli @@ -1,5 +1,5 @@ -open As_types -open As_values +open Mo_types +open Mo_values open Ir_def module V = Value diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index f9f38774e78..d2120536fd6 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -1,4 +1,4 @@ -open As_types +open Mo_types open Ir_def module E = Env diff --git a/src/ir_passes/async.mli b/src/ir_passes/async.mli index 7f6ec8652e0..40b6fa4e956 100644 --- a/src/ir_passes/async.mli +++ b/src/ir_passes/async.mli @@ -5,4 +5,4 @@ type platform = V1 (* legacy, Haskell *) | V2 (* new, Rust *) -val transform : platform -> As_types.Scope.scope -> Ir.prog -> Ir.prog +val transform : platform -> Mo_types.Scope.scope -> Ir.prog -> Ir.prog diff --git a/src/ir_passes/await.ml b/src/ir_passes/await.ml index 48ba0ac295d..b26ce5b3000 100644 --- a/src/ir_passes/await.ml +++ b/src/ir_passes/await.ml @@ -1,5 +1,5 @@ open Ir_def -open As_types +open Mo_types open Source open Ir diff --git a/src/ir_passes/show.ml b/src/ir_passes/show.ml index 95ec31a0e2d..5348d8d2723 100644 --- a/src/ir_passes/show.ml +++ b/src/ir_passes/show.ml @@ -1,6 +1,6 @@ open Ir_def -open As_types -open As_values +open Mo_types +open Mo_values (* Translates away calls to `show`. *) open Source open Ir diff --git a/src/ir_passes/tailcall.ml b/src/ir_passes/tailcall.ml index f93bf6f7ec0..dc5ca3ca8b7 100644 --- a/src/ir_passes/tailcall.ml +++ b/src/ir_passes/tailcall.ml @@ -1,5 +1,5 @@ open Ir_def -open As_types +open Mo_types open Source open Ir diff --git a/src/js/dune b/src/js/dune index faa9d4cdcfa..99b19de3ad9 100644 --- a/src/js/dune +++ b/src/js/dune @@ -1,7 +1,7 @@ (executable - (name as_js) - (modules as_js) - (libraries as_config pipeline) + (name mo_js) + (modules mo_js) + (libraries mo_config pipeline) (preprocess (pps js_of_ocaml-ppx)) (js_of_ocaml (flags :standard "+nat.js") ) ) diff --git a/src/js/as_js.ml b/src/js/mo_js.ml similarity index 95% rename from src/js/as_js.ml rename to src/js/mo_js.ml index 14c8745a71e..30d0cb8e938 100644 --- a/src/js/as_js.ml +++ b/src/js/mo_js.ml @@ -1,6 +1,6 @@ open Wasm_exts open Source -open As_config +open Mo_config module Js = Js_of_ocaml.Js @@ -19,7 +19,7 @@ let range_of_region at = let diagnostics_of_msg (msg : Diag.message) = Diag.(object%js - val source = Js.string "actorscript" + val source = Js.string "motoko" val severity = match msg.sev with Diag.Error -> 1 | Diag.Warning -> 2 val range = range_of_region msg.at val message = Js.string msg.text @@ -64,7 +64,7 @@ let js_compile_wasm mode s = (fun m -> let (map, wasm) = CustomModuleEncode.encode m in Js.bytestring wasm, Js.string map) let () = - Js.export "ActorScript" + Js.export "Motoko" (object%js method check s = js_check s method compileWasm mode s = js_compile_wasm mode s diff --git a/src/languageServer/completion.ml b/src/languageServer/completion.ml index 0232cb7a6d0..874d9884e56 100644 --- a/src/languageServer/completion.ml +++ b/src/languageServer/completion.ml @@ -1,5 +1,5 @@ -open As_types -open As_frontend +open Mo_types +open Mo_frontend open Declaration_index module Lsp_t = Lsp.Lsp_t diff --git a/src/languageServer/completion_test.ml b/src/languageServer/completion_test.ml index 34edc38febd..cf7d644ae7b 100644 --- a/src/languageServer/completion_test.ml +++ b/src/languageServer/completion_test.ml @@ -86,7 +86,7 @@ List.| let%test "it handles a full module" = prefix_test_case {|module { - private import List = "./ListLib.as"; + private import List = "./ListLib.mo"; func singleton(x: T): List.List = List.cons(x, Test.|()); @@ -98,8 +98,8 @@ let%test "it handles a full module" = let%test "it doesn't fall through to the next valid prefix" = prefix_test_case {|module { -private import List = "lib/ListLib.as"; // private, so we don't re-export List -private import ListFns = "lib/ListFuncs.as"; // private, so we don't re-export List +private import List = "lib/ListLib.mo"; // private, so we don't re-export List +private import ListFns = "lib/ListFuncs.mo"; // private, so we don't re-export List type Stack = List.List; func push(x : Int, s : Stack) : Stack = List.cons(x, s); func empty():Stack = List.nil(); @@ -111,40 +111,40 @@ func singleton(x : Int) : Stack = let%test "it makes an import relative to the project root" = import_relative_test_case "/home/project" - "/home/project/src/main.as" - "lib/List.as" - (Some "src/lib/List.as") + "/home/project/src/main.mo" + "lib/List.mo" + (Some "src/lib/List.mo") let%test "it preserves trailing slashes for directory imports" = import_relative_test_case "/home/project" - "/home/project/src/main.as" + "/home/project/src/main.mo" "lib/List/" (Some "src/lib/List/") let%test "it can handle parent directory relationships" = import_relative_test_case "/home/project" - "/home/project/src/main.as" - "../lib/List.as" - (Some "lib/List.as") + "/home/project/src/main.mo" + "../lib/List.mo" + (Some "lib/List.mo") let%test "it parses a simple module header" = parse_module_header_test_case "/project" - "/project/src/Main.as" - "import P \"lib/prelude.as\"" - ["P", "src/lib/prelude.as"] + "/project/src/Main.mo" + "import P \"lib/prelude.mo\"" + ["P", "src/lib/prelude.mo"] let%test "it parses a simple module header" = parse_module_header_test_case "/project" - "/project/Main.as" + "/project/Main.mo" {| module { -private import List "lib/ListLib.as"; -private import ListFuncs "lib/ListFuncs.as"; +private import List "lib/ListLib.mo"; +private import ListFuncs "lib/ListFuncs.mo"; type Stack = List.List; @@ -158,6 +158,6 @@ func singleton(x: Int): Stack = ListFuncs.doubleton(x, x); } |} - [ ("List", "lib/ListLib.as") - ; ("ListFuncs", "lib/ListFuncs.as") + [ ("List", "lib/ListLib.mo") + ; ("ListFuncs", "lib/ListFuncs.mo") ] diff --git a/src/languageServer/declaration_index.ml b/src/languageServer/declaration_index.ml index 19d29ab8586..2d3453e3c91 100644 --- a/src/languageServer/declaration_index.ml +++ b/src/languageServer/declaration_index.ml @@ -1,5 +1,5 @@ -open As_types -open As_def +open Mo_types +open Mo_def open Source open Syntax @@ -93,7 +93,7 @@ let project_files () : string list = flat_map read_dir entries else [d] in read_dir "." - |> List.filter (fun file -> String.equal (Filename.extension file) ".as") + |> List.filter (fun file -> String.equal (Filename.extension file) ".mo") let read_single_module_lib (ty: Type.typ): ide_decl list option = match ty with diff --git a/src/languageServer/hover.ml b/src/languageServer/hover.ml index ffbd056206c..c78520119f0 100644 --- a/src/languageServer/hover.ml +++ b/src/languageServer/hover.ml @@ -1,4 +1,4 @@ -open As_types +open Mo_types open Declaration_index module Lsp = Lsp.Lsp_t diff --git a/src/languageServer/languageServer.ml b/src/languageServer/languageServer.ml index 45c59297c90..85e4a4b2a27 100644 --- a/src/languageServer/languageServer.ml +++ b/src/languageServer/languageServer.ml @@ -81,7 +81,7 @@ let diagnostics_of_message (msg : Diag.message) : Lsp_t.diagnostic = Lsp_t. { diagnostic_range = range_of_region msg.Diag.at; diagnostic_severity = Some (severity_of_sev msg.Diag.sev); diagnostic_code = None; - diagnostic_source = Some "ActorScript"; + diagnostic_source = Some "Motoko"; diagnostic_message = msg.Diag.text; diagnostic_relatedInformation = None; } diff --git a/src/languageServer/source_file.ml b/src/languageServer/source_file.ml index 28b4871b821..6315210b9c6 100644 --- a/src/languageServer/source_file.ml +++ b/src/languageServer/source_file.ml @@ -1,4 +1,4 @@ -open As_frontend +open Mo_frontend module Lsp = Lsp.Lsp_t type cursor_target = diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 93ae831150d..0d69cb147fc 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -1,7 +1,7 @@ open Ir_def -open As_def -open As_types -open As_values +open Mo_def +open Mo_types +open Mo_values open Source open Operator @@ -128,7 +128,7 @@ and exp' at note = function | S.LoopE (e1, None) -> I.LoopE (exp e1) | S.LoopE (e1, Some e2) -> (loopWhileE (exp e1) (exp e2)).it | S.ForE (p, e1, e2) -> (forE (pat p) (exp e1) (exp e2)).it - | S.DebugE e -> if !As_config.Flags.release_mode then I.TupE [] else (exp e).it + | S.DebugE e -> if !Mo_config.Flags.release_mode then I.TupE [] else (exp e).it | S.LabelE (l, t, e) -> I.LabelE (l.it, t.Source.note, exp e) | S.BreakE (l, e) -> I.BreakE (l.it, exp e) | S.RetE e -> I.RetE (exp e) diff --git a/src/lowering/desugar.mli b/src/lowering/desugar.mli index 00110d42f0e..b3015fe89c2 100644 --- a/src/lowering/desugar.mli +++ b/src/lowering/desugar.mli @@ -1,5 +1,5 @@ -open As_def -open As_types +open Mo_def +open Mo_types open Ir_def val transform : Syntax.prog -> Ir.prog diff --git a/src/lowering/dune b/src/lowering/dune index c8ab0651e29..9f6c51b44de 100644 --- a/src/lowering/dune +++ b/src/lowering/dune @@ -1,4 +1,4 @@ (library (name lowering) - (libraries lib as_config as_def ir_def) + (libraries lib mo_config mo_def ir_def) ) diff --git a/src/mo_config/dune b/src/mo_config/dune new file mode 100644 index 00000000000..670c708dde6 --- /dev/null +++ b/src/mo_config/dune @@ -0,0 +1,3 @@ +(library + (name mo_config) +) diff --git a/src/as_config/flags.ml b/src/mo_config/flags.ml similarity index 93% rename from src/as_config/flags.ml rename to src/mo_config/flags.ml index 0d818939934..1da5cdd1474 100644 --- a/src/as_config/flags.ml +++ b/src/mo_config/flags.ml @@ -1,4 +1,4 @@ -(* common flags for the asc compiler *) +(* common flags for the moc compiler *) type compile_mode = WasmMode | AncientMode | ICMode diff --git a/src/as_def/arrange.ml b/src/mo_def/arrange.ml similarity index 99% rename from src/as_def/arrange.ml rename to src/mo_def/arrange.ml index 8fffc8379bd..7a3377c9f2e 100644 --- a/src/as_def/arrange.ml +++ b/src/mo_def/arrange.ml @@ -1,5 +1,5 @@ -open As_types -open As_values +open Mo_types +open Mo_values open Source open Syntax diff --git a/src/mo_def/dune b/src/mo_def/dune new file mode 100644 index 00000000000..4ff37a47cab --- /dev/null +++ b/src/mo_def/dune @@ -0,0 +1,4 @@ +(library + (name mo_def) + (libraries lib lang_utils mo_types mo_values) +) diff --git a/src/as_def/syntax.ml b/src/mo_def/syntax.ml similarity index 99% rename from src/as_def/syntax.ml rename to src/mo_def/syntax.ml index 3b638e0de10..83593f94b04 100644 --- a/src/as_def/syntax.ml +++ b/src/mo_def/syntax.ml @@ -1,5 +1,5 @@ -open As_types -open As_values +open Mo_types +open Mo_values open Operator diff --git a/src/as_frontend/coverage.ml b/src/mo_frontend/coverage.ml similarity index 99% rename from src/as_frontend/coverage.ml rename to src/mo_frontend/coverage.ml index 6d13214b2b1..5b641e4a3a0 100644 --- a/src/as_frontend/coverage.ml +++ b/src/mo_frontend/coverage.ml @@ -1,6 +1,6 @@ -open As_def -open As_types -open As_values +open Mo_def +open Mo_types +open Mo_values open Syntax open Source diff --git a/src/as_frontend/coverage.mli b/src/mo_frontend/coverage.mli similarity index 81% rename from src/as_frontend/coverage.mli rename to src/mo_frontend/coverage.mli index ebe4ddb3056..4a9ada4a76d 100644 --- a/src/as_frontend/coverage.mli +++ b/src/mo_frontend/coverage.mli @@ -1,5 +1,5 @@ -open As_def -open As_types +open Mo_def +open Mo_types val check_pat : Syntax.pat -> Type.typ -> string list val check_cases : Syntax.case list -> Type.typ -> string list diff --git a/src/as_frontend/definedness.ml b/src/mo_frontend/definedness.ml similarity index 99% rename from src/as_frontend/definedness.ml rename to src/mo_frontend/definedness.ml index 6b73501f691..f6f0ce8283d 100644 --- a/src/as_frontend/definedness.ml +++ b/src/mo_frontend/definedness.ml @@ -10,7 +10,7 @@ We keep it still separate, because we are doing much more interesting things here in for blocks (function decs). *) -open As_def +open Mo_def open Source open Syntax diff --git a/src/as_frontend/definedness.mli b/src/mo_frontend/definedness.mli similarity index 80% rename from src/as_frontend/definedness.mli rename to src/mo_frontend/definedness.mli index 40925eaf093..d2377acf3e3 100644 --- a/src/as_frontend/definedness.mli +++ b/src/mo_frontend/definedness.mli @@ -1,3 +1,3 @@ -open As_def +open Mo_def val check_prog : Syntax.prog -> unit Diag.result diff --git a/src/as_frontend/dune b/src/mo_frontend/dune similarity index 53% rename from src/as_frontend/dune rename to src/mo_frontend/dune index 4282935f210..5d5caccba3f 100644 --- a/src/as_frontend/dune +++ b/src/mo_frontend/dune @@ -1,6 +1,6 @@ (library - (name as_frontend) - (libraries lib lang_utils as_config as_def as_types as_values) + (name mo_frontend) + (libraries lib lang_utils mo_config mo_def mo_types mo_values) ) (menhir (modules parser) diff --git a/src/as_frontend/effect.ml b/src/mo_frontend/effect.ml similarity index 99% rename from src/as_frontend/effect.ml rename to src/mo_frontend/effect.ml index c4f3c347231..5f89c72e0fd 100644 --- a/src/as_frontend/effect.ml +++ b/src/mo_frontend/effect.ml @@ -1,5 +1,5 @@ -open As_def -open As_types +open Mo_def +open Mo_types open Syntax open Source diff --git a/src/as_frontend/effect.mli b/src/mo_frontend/effect.mli similarity index 94% rename from src/as_frontend/effect.mli rename to src/mo_frontend/effect.mli index 0469849bba1..eca1e6c3c7c 100644 --- a/src/as_frontend/effect.mli +++ b/src/mo_frontend/effect.mli @@ -1,5 +1,5 @@ -open As_def -open As_types +open Mo_def +open Mo_types open Source open Syntax diff --git a/src/as_frontend/lexer.mli b/src/mo_frontend/lexer.mli similarity index 100% rename from src/as_frontend/lexer.mli rename to src/mo_frontend/lexer.mli diff --git a/src/as_frontend/lexer.mll b/src/mo_frontend/lexer.mll similarity index 99% rename from src/as_frontend/lexer.mll rename to src/mo_frontend/lexer.mll index 65947ba480c..ebd0c3f6977 100644 --- a/src/as_frontend/lexer.mll +++ b/src/mo_frontend/lexer.mll @@ -186,7 +186,7 @@ rule token mode = parse (* If you add keywords, please also update - src/idllib/escape.ml - - emacs/actorscript-mode.el + - emacs/motoko-mode.el *) | "actor" { ACTOR } | "and" { AND } diff --git a/src/as_frontend/parser.mly b/src/mo_frontend/parser.mly similarity index 98% rename from src/as_frontend/parser.mly rename to src/mo_frontend/parser.mly index abb188f5b8f..b0a2c9a877c 100644 --- a/src/as_frontend/parser.mly +++ b/src/mo_frontend/parser.mly @@ -1,7 +1,7 @@ %{ -open As_def -open As_types -open As_values +open Mo_def +open Mo_types +open Mo_values open Syntax open Source @@ -115,7 +115,7 @@ let share_expfield (ef : exp_field) = %token DOT_NUM %token NAT %token FLOAT -%token CHAR +%token CHAR %token BOOL %token ID %token TEXT @@ -139,8 +139,8 @@ let share_expfield (ef : exp_field) = %left POWOP %type exp(ob) exp_nullary(ob) -%start As_def.Syntax.prog> parse_prog -%start As_def.Syntax.prog> parse_prog_interactive +%start Mo_def.Syntax.prog> parse_prog +%start Mo_def.Syntax.prog> parse_prog_interactive %% diff --git a/src/as_frontend/static.ml b/src/mo_frontend/static.ml similarity index 99% rename from src/as_frontend/static.ml rename to src/mo_frontend/static.ml index 056a7bf8cc0..bd026dca468 100644 --- a/src/as_frontend/static.ml +++ b/src/mo_frontend/static.ml @@ -10,7 +10,7 @@ some kind of beta-reduction, and can actually cause loops, but are required to allow re-exporting names in modules. *) -open As_def +open Mo_def open Source open Syntax diff --git a/src/as_frontend/static.mli b/src/mo_frontend/static.mli similarity index 92% rename from src/as_frontend/static.mli rename to src/mo_frontend/static.mli index 7b6cc8ac514..018aac2fe5c 100644 --- a/src/as_frontend/static.mli +++ b/src/mo_frontend/static.mli @@ -1,4 +1,4 @@ -open As_def +open Mo_def val exp : Diag.msg_store -> Syntax.exp -> unit val fields : Diag.msg_store -> Syntax.exp_field list -> unit diff --git a/src/as_frontend/typing.ml b/src/mo_frontend/typing.ml similarity index 99% rename from src/as_frontend/typing.ml rename to src/mo_frontend/typing.ml index 678e233fc53..274d51daf05 100644 --- a/src/as_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -1,7 +1,7 @@ -open As_def -open As_types -open As_values -module Flags = As_config.Flags +open Mo_def +open Mo_types +open Mo_values +module Flags = Mo_config.Flags open Syntax open Source diff --git a/src/as_frontend/typing.mli b/src/mo_frontend/typing.mli similarity index 89% rename from src/as_frontend/typing.mli rename to src/mo_frontend/typing.mli index 871989a8130..87ba3eaba81 100644 --- a/src/as_frontend/typing.mli +++ b/src/mo_frontend/typing.mli @@ -1,5 +1,5 @@ -open As_def -open As_types +open Mo_def +open Mo_types open Type open Scope diff --git a/src/mo_idl/dune b/src/mo_idl/dune new file mode 100644 index 00000000000..4ce54e079c6 --- /dev/null +++ b/src/mo_idl/dune @@ -0,0 +1,4 @@ +(library + (name mo_idl) + (libraries lib idllib lang_utils mo_types mo_def) +) diff --git a/src/as_idl/as_to_idl.ml b/src/mo_idl/mo_to_idl.ml similarity index 98% rename from src/as_idl/as_to_idl.ml rename to src/mo_idl/mo_to_idl.ml index e268e5ca6a4..352b5beaff0 100644 --- a/src/as_idl/as_to_idl.ml +++ b/src/mo_idl/mo_to_idl.ml @@ -1,8 +1,8 @@ -open As_types -open As_types.Type +open Mo_types +open Mo_types.Type open Source open Printf -module E = As_def.Syntax +module E = Mo_def.Syntax module I = Idllib.Syntax let env = ref Env.empty diff --git a/src/mo_interpreter/dune b/src/mo_interpreter/dune new file mode 100644 index 00000000000..53fef77303a --- /dev/null +++ b/src/mo_interpreter/dune @@ -0,0 +1,4 @@ +(library + (name mo_interpreter) + (libraries lib mo_config mo_def mo_types mo_values profiler) +) diff --git a/src/as_interpreter/interpret.ml b/src/mo_interpreter/interpret.ml similarity index 99% rename from src/as_interpreter/interpret.ml rename to src/mo_interpreter/interpret.ml index e6dc423adef..a56ffb492aa 100644 --- a/src/as_interpreter/interpret.ml +++ b/src/mo_interpreter/interpret.ml @@ -1,6 +1,6 @@ -open As_def -open As_values -open As_types +open Mo_def +open Mo_values +open Mo_types open Syntax open Source @@ -551,7 +551,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = | BreakE (id, exp1) -> interpret_exp env exp1 (find id.it env.labs) | DebugE exp1 -> - if !As_config.Flags.release_mode then k V.unit else interpret_exp env exp1 k + if !Mo_config.Flags.release_mode then k V.unit else interpret_exp env exp1 k | RetE exp1 -> interpret_exp env exp1 (Lib.Option.value env.rets) | ThrowE exp1 -> diff --git a/src/as_interpreter/interpret.mli b/src/mo_interpreter/interpret.mli similarity index 91% rename from src/as_interpreter/interpret.mli rename to src/mo_interpreter/interpret.mli index 7bf2f131c2d..eef3336211e 100644 --- a/src/as_interpreter/interpret.mli +++ b/src/mo_interpreter/interpret.mli @@ -1,6 +1,6 @@ -open As_def -open As_values -open As_types +open Mo_def +open Mo_values +open Mo_types module V = Value module T = Type diff --git a/src/as_types/arrange_type.ml b/src/mo_types/arrange_type.ml similarity index 100% rename from src/as_types/arrange_type.ml rename to src/mo_types/arrange_type.ml diff --git a/src/as_types/con.ml b/src/mo_types/con.ml similarity index 100% rename from src/as_types/con.ml rename to src/mo_types/con.ml diff --git a/src/as_types/con.mli b/src/mo_types/con.mli similarity index 100% rename from src/as_types/con.mli rename to src/mo_types/con.mli diff --git a/src/mo_types/dune b/src/mo_types/dune new file mode 100644 index 00000000000..edf236700fe --- /dev/null +++ b/src/mo_types/dune @@ -0,0 +1,4 @@ +(library + (name mo_types) + (libraries wasm lib lang_utils mo_config) +) diff --git a/src/as_types/scope.ml b/src/mo_types/scope.ml similarity index 100% rename from src/as_types/scope.ml rename to src/mo_types/scope.ml diff --git a/src/as_types/scope.mli b/src/mo_types/scope.mli similarity index 100% rename from src/as_types/scope.mli rename to src/mo_types/scope.mli diff --git a/src/as_types/type.ml b/src/mo_types/type.ml similarity index 99% rename from src/as_types/type.ml rename to src/mo_types/type.ml index a1d084194e1..9978f2649b1 100644 --- a/src/as_types/type.ml +++ b/src/mo_types/type.ml @@ -1,5 +1,5 @@ (* Representation *) -open As_config +open Mo_config type lab = string type var = string @@ -530,7 +530,7 @@ module S = Set.Make (struct type t = typ let compare = compare end) (* This check is a stop-gap measure until we have an IDL strategy that -allows polymorphic types, see #250. It is not what we desire for ActorScript. +allows polymorphic types, see #250. It is not what we desire for Motoko. *) let concrete t = diff --git a/src/as_types/type.mli b/src/mo_types/type.mli similarity index 100% rename from src/as_types/type.mli rename to src/mo_types/type.mli diff --git a/src/as_values/arrange_ops.ml b/src/mo_values/arrange_ops.ml similarity index 100% rename from src/as_values/arrange_ops.ml rename to src/mo_values/arrange_ops.ml diff --git a/src/as_values/call_conv.ml b/src/mo_values/call_conv.ml similarity index 98% rename from src/as_values/call_conv.ml rename to src/mo_values/call_conv.ml index b9774c7fcb2..736a95b27bf 100644 --- a/src/as_values/call_conv.ml +++ b/src/mo_values/call_conv.ml @@ -1,4 +1,4 @@ -open As_types +open Mo_types open Type (* diff --git a/src/as_values/call_conv.mli b/src/mo_values/call_conv.mli similarity index 96% rename from src/as_values/call_conv.mli rename to src/mo_values/call_conv.mli index 7bf71f39b83..0b013a8526e 100644 --- a/src/as_values/call_conv.mli +++ b/src/mo_values/call_conv.mli @@ -1,5 +1,5 @@ (* Calling convention *) -open As_types +open Mo_types type call_conv = { sort: Type.func_sort; diff --git a/src/mo_values/dune b/src/mo_values/dune new file mode 100644 index 00000000000..85cf9c0d448 --- /dev/null +++ b/src/mo_values/dune @@ -0,0 +1,4 @@ +(library + (name mo_values) + (libraries num wasm lib lang_utils mo_types idllib) +) diff --git a/src/as_values/operator.ml b/src/mo_values/operator.ml similarity index 99% rename from src/as_values/operator.ml rename to src/mo_values/operator.ml index a95b3deac78..378fbf18652 100644 --- a/src/as_values/operator.ml +++ b/src/mo_values/operator.ml @@ -1,6 +1,6 @@ open Value -module T = As_types.Type +module T = Mo_types.Type (* Operators *) diff --git a/src/as_values/operator.mli b/src/mo_values/operator.mli similarity index 98% rename from src/as_values/operator.mli rename to src/mo_values/operator.mli index 1e94f92bc70..fd4d66d2f9f 100644 --- a/src/as_values/operator.mli +++ b/src/mo_values/operator.mli @@ -1,4 +1,4 @@ -open As_types.Type +open Mo_types.Type open Value (* Operators *) diff --git a/src/as_values/prim.ml b/src/mo_values/prim.ml similarity index 99% rename from src/as_values/prim.ml rename to src/mo_values/prim.ml index 171cb564702..d05f2bbea8b 100644 --- a/src/as_values/prim.ml +++ b/src/mo_values/prim.ml @@ -1,5 +1,5 @@ (* Primitives *) -open As_types +open Mo_types open Value diff --git a/src/as_values/prim.mli b/src/mo_values/prim.mli similarity index 86% rename from src/as_values/prim.mli rename to src/mo_values/prim.mli index 20b47a50726..89bde4ab843 100644 --- a/src/as_values/prim.mli +++ b/src/mo_values/prim.mli @@ -1,3 +1,3 @@ -open As_types +open Mo_types val prim : string -> Value.func val num_conv_prim : Type.prim -> Type.prim -> Value.func diff --git a/src/as_values/show.ml b/src/mo_values/show.ml similarity index 99% rename from src/as_values/show.ml rename to src/mo_values/show.ml index 353b2b18ab7..eedd7a07a86 100644 --- a/src/as_values/show.ml +++ b/src/mo_values/show.ml @@ -1,4 +1,4 @@ -module T = As_types.Type +module T = Mo_types.Type (* Entry point for type checking: *) diff --git a/src/as_values/show.mli b/src/mo_values/show.mli similarity index 85% rename from src/as_values/show.mli rename to src/mo_values/show.mli index 289cfc6269d..a1c3cb06d61 100644 --- a/src/as_values/show.mli +++ b/src/mo_values/show.mli @@ -1,4 +1,4 @@ -open As_types +open Mo_types val can_show : Type.typ -> bool val show_val : Type.typ -> Value.value -> string diff --git a/src/as_values/value.ml b/src/mo_values/value.ml similarity index 100% rename from src/as_values/value.ml rename to src/mo_values/value.ml diff --git a/src/as_values/value.mli b/src/mo_values/value.mli similarity index 99% rename from src/as_values/value.mli rename to src/mo_values/value.mli index 37125ae675d..cf62e3e99c7 100644 --- a/src/as_values/value.mli +++ b/src/mo_values/value.mli @@ -1,4 +1,4 @@ -open As_types +open Mo_types (* Numeric Representations *) diff --git a/src/pipeline/dune b/src/pipeline/dune index 0b8e5414e2b..3828550a006 100644 --- a/src/pipeline/dune +++ b/src/pipeline/dune @@ -3,13 +3,13 @@ (libraries lib lang_utils - as_def - as_config - as_types - as_values - as_frontend - as_idl - as_interpreter + mo_def + mo_config + mo_types + mo_values + mo_frontend + mo_idl + mo_interpreter lowering wasm_exts ir_def diff --git a/src/pipeline/file_path_test.ml b/src/pipeline/file_path_test.ml index ea66a0d40f4..a86db8f1da7 100644 --- a/src/pipeline/file_path_test.ml +++ b/src/pipeline/file_path_test.ml @@ -20,7 +20,7 @@ let relative_to_test_case root contained expected = false) let%test "it removes leading current directory" = - normalise_test_case "./ListClient.as" "ListClient.as" + normalise_test_case "./ListClient.mo" "ListClient.mo" let%test "it removes leading `./` for relative paths" = normalise_test_case "./lib/foo" "lib/foo" @@ -52,20 +52,20 @@ let%test "it handles absolute directory paths" = let%test "it makes one absolute path relative to another one" = relative_to_test_case "/home/project" - "/home/project/src/main.as" - (Some "src/main.as") + "/home/project/src/main.mo" + (Some "src/main.mo") let%test "it's robust in the face of trailing slashes" = relative_to_test_case "/home/project/" - "/home/project/src/main.as" - (Some "src/main.as") + "/home/project/src/main.mo" + (Some "src/main.mo") let%test "it makes a file path relative to a path" = relative_to_test_case "/home/project" - "/home/project/main.as" - (Some "main.as") + "/home/project/main.mo" + (Some "main.mo") let%test "it preserves trailing slashes" = relative_to_test_case @@ -82,11 +82,11 @@ let%test "it handles directory traversals" = let%test "it fails to make disjoint paths relative to one another" = relative_to_test_case "/home/project" - "/home/main.as" + "/home/main.mo" None let%test "it handles relative paths" = relative_to_test_case "project/src" - "project/src/Main.as" - (Some "Main.as") + "project/src/Main.mo" + (Some "Main.mo") diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index aab5267d300..63665ba706f 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -1,12 +1,12 @@ -open As_def -open As_frontend -open As_types -open As_values -open As_interpreter +open Mo_def +open Mo_frontend +open Mo_types +open Mo_values +open Mo_interpreter open Ir_def open Ir_interpreter open Ir_passes -open As_config +open Mo_config open Printf @@ -334,7 +334,7 @@ let check_string s name : check_result = let generate_idl files : Idllib.Syntax.prog Diag.result = Diag.bind (load_progs parse_file files initial_stat_env) (fun (libraries, progs, senv) -> - Diag.return (As_idl.As_to_idl.prog (progs, senv))) + Diag.return (Mo_idl.Mo_to_idl.prog (progs, senv))) (* Running *) @@ -460,12 +460,12 @@ let load_as_rts () = (* The RTS can be found via environment (in particular when built via nix), - or relative to the directory of the invoked asc (when developing) + or relative to the directory of the invoked moc (when developing) *) let wasm_filename = - match Sys.getenv_opt "ASC_RTS" with + match Sys.getenv_opt "MOC_RTS" with | Some filename -> filename - | None -> Filename.(concat (dirname Sys.argv.(0)) "../rts/as-rts.wasm") in + | None -> Filename.(concat (dirname Sys.argv.(0)) "../rts/mo-rts.wasm") in let wasm = load_file wasm_filename in Wasm_exts.CustomModuleDecode.decode "rts.wasm" wasm diff --git a/src/pipeline/pipeline.mli b/src/pipeline/pipeline.mli index 372f5b946c2..16b874c6c24 100644 --- a/src/pipeline/pipeline.mli +++ b/src/pipeline/pipeline.mli @@ -1,6 +1,6 @@ -open As_def -open As_config -open As_types +open Mo_def +open Mo_config +open Mo_types type parse_fn = string -> (Syntax.prog * string) Diag.result val parse_file: parse_fn diff --git a/src/pipeline/resolve_import.ml b/src/pipeline/resolve_import.ml index 9e26e301654..c6cb668798b 100644 --- a/src/pipeline/resolve_import.ml +++ b/src/pipeline/resolve_import.ml @@ -1,4 +1,4 @@ -open As_def +open Mo_def (* This module traverses the syntax tree. For each `import` statement, it looks @@ -100,7 +100,7 @@ let resolve_import_string env region (f: string) (fp: string ref) = else f in let f = if Sys.file_exists f && Sys.is_directory f - then Filename.concat f "lib.as" + then Filename.concat f "lib.mo" else f in let f = File_path.normalise f in if Sys.file_exists f diff --git a/src/pipeline/resolve_import.mli b/src/pipeline/resolve_import.mli index 8f97a5bd5b2..114eea7b96e 100644 --- a/src/pipeline/resolve_import.mli +++ b/src/pipeline/resolve_import.mli @@ -1,4 +1,4 @@ -open As_def +open Mo_def module S : Set.S with type elt = String.t diff --git a/src/prelude/prelude.ml b/src/prelude/prelude.ml index 393e094ac58..2530744fab4 100644 --- a/src/prelude/prelude.ml +++ b/src/prelude/prelude.ml @@ -344,7 +344,7 @@ func errorMessage(e : Error) : Text = (prim "errorMessage" : Error -> Text)(e); func @int32ToErrorCode(i : Int32) : ErrorCode { - switch (int32ToInt(i)) { /*TODO: conversion only to avoid bug in asc-js, TBR */ + switch (int32ToInt(i)) { /*TODO: conversion only to avoid bug in moc-js, TBR */ case 4 /* CANISTER_REJECT */ #error; case _ #system; /* TBC */ } diff --git a/src/profiler/counters.ml b/src/profiler/counters.ml index acb6964a041..c396f493094 100644 --- a/src/profiler/counters.ml +++ b/src/profiler/counters.ml @@ -9,7 +9,7 @@ such as search, sorting, etc. *) open Source -module Value = As_values.Value +module Value = Mo_values.Value type t = { label : ((region * string), int) Hashtbl.t ; diff --git a/src/profiler/dune b/src/profiler/dune index 4e3cbb18e29..e6c338af14b 100644 --- a/src/profiler/dune +++ b/src/profiler/dune @@ -3,5 +3,5 @@ (wrapped false) (modules profilerFlags counters profiler) (private_modules counters) - (libraries lang_utils as_values) + (libraries lang_utils mo_values) ) diff --git a/src/profiler/profiler.ml b/src/profiler/profiler.ml index b0dececb521..1b3fb42419b 100644 --- a/src/profiler/profiler.ml +++ b/src/profiler/profiler.ml @@ -1,4 +1,4 @@ -open As_values +open Mo_values let counters : Counters.t = Counters.zeros () diff --git a/stdlib/Makefile b/stdlib/Makefile index 4bc923fe621..4e5eff22988 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -1,9 +1,9 @@ -ASC=../src/asc +MOC=../src/moc DRUN=drun OUTDIR=_out DOCDIR=doc STOPWATCH_C=./tools/stopwatch.c -MDofAS=./tools/markdown-of-actorscript.py +MDofMO=./tools/markdown-of-motoko.py MDofMD=./tools/markdown-of-markdown.py PANDOC=pandoc STOPWATCH=$(OUTDIR)/stopwatch @@ -62,63 +62,63 @@ clean: $(OUTDIR): @mkdir $@ -$(OUTDIR)/Array.out: array.as | $(OUTDIR) - $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ +$(OUTDIR)/Array.out: array.mo | $(OUTDIR) + $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ -$(OUTDIR)/ArrayTest.out: arrayTest.as | $(OUTDIR) - $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ +$(OUTDIR)/ArrayTest.out: arrayTest.mo | $(OUTDIR) + $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ -$(OUTDIR)/Int.out: int.as | $(OUTDIR) - $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ +$(OUTDIR)/Int.out: int.mo | $(OUTDIR) + $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ -$(OUTDIR)/IntTest.out: intTest.as | $(OUTDIR) - $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ +$(OUTDIR)/IntTest.out: intTest.mo | $(OUTDIR) + $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ -$(OUTDIR)/Nat.out: nat.as | $(OUTDIR) - $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ +$(OUTDIR)/Nat.out: nat.mo | $(OUTDIR) + $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ -$(OUTDIR)/NatTest.out: natTest.as | $(OUTDIR) - $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ +$(OUTDIR)/NatTest.out: natTest.mo | $(OUTDIR) + $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ -$(OUTDIR)/Hash.out: hash.as | $(OUTDIR) - $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ +$(OUTDIR)/Hash.out: hash.mo | $(OUTDIR) + $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ -$(OUTDIR)/Option.out: option.as | $(OUTDIR) - $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ +$(OUTDIR)/Option.out: option.mo | $(OUTDIR) + $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ -$(OUTDIR)/OptionTest.out: optionTest.as | $(OUTDIR) - $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ +$(OUTDIR)/OptionTest.out: optionTest.mo | $(OUTDIR) + $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ -$(OUTDIR)/Result.out: result.as | $(OUTDIR) - $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ +$(OUTDIR)/Result.out: result.mo | $(OUTDIR) + $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ -$(OUTDIR)/List.out: list.as | $(OUTDIR) - $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ +$(OUTDIR)/List.out: list.mo | $(OUTDIR) + $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ -$(OUTDIR)/ListTest.out: listTest.as | $(OUTDIR) - $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ +$(OUTDIR)/ListTest.out: listTest.mo | $(OUTDIR) + $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ -$(OUTDIR)/AssocList.out: assocList.as | $(OUTDIR) - $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ +$(OUTDIR)/AssocList.out: assocList.mo | $(OUTDIR) + $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ -$(OUTDIR)/Text.out: text.as | $(OUTDIR) - $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ +$(OUTDIR)/Text.out: text.mo | $(OUTDIR) + $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ -$(OUTDIR)/TextTest.out: textTest.as | $(OUTDIR) - $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ +$(OUTDIR)/TextTest.out: textTest.mo | $(OUTDIR) + $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ -$(OUTDIR)/Trie.out: trie.as | $(OUTDIR) - $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ +$(OUTDIR)/Trie.out: trie.mo | $(OUTDIR) + $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ -$(OUTDIR)/Trie2.out:trie2.as | $(OUTDIR) - $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ +$(OUTDIR)/Trie2.out:trie2.mo | $(OUTDIR) + $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ -$(OUTDIR)/Set.out: set.as | $(OUTDIR) - $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ +$(OUTDIR)/Set.out: set.mo | $(OUTDIR) + $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ -$(OUTDIR)/DocTable.out: docTable.as | $(OUTDIR) - $(ASC) -r $(filter-out $(OUTDIR), $^) > $@ +$(OUTDIR)/DocTable.out: docTable.mo | $(OUTDIR) + $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ #########################################################################################################33 @@ -200,37 +200,37 @@ $(DOCDIR)/examples/produce-exchange/README.md: examples/produce-exchange/README. ## PRODUCE_EXCHANGE_SRC=\ - prelude.as option.as hash.as list.as assocList.as trie2.as docTable.as result.as \ - examples/produce-exchange/serverTypes.as \ - examples/produce-exchange/serverLang.as \ - examples/produce-exchange/serverModelTypes.as \ - examples/produce-exchange/serverModel.as \ - examples/produce-exchange/serverActor.as \ + prelude.mo option.mo hash.mo list.mo assocList.mo trie2.mo docTable.mo result.mo \ + examples/produce-exchange/serverTypes.mo \ + examples/produce-exchange/serverLang.mo \ + examples/produce-exchange/serverModelTypes.mo \ + examples/produce-exchange/serverModel.mo \ + examples/produce-exchange/serverActor.mo \ $(OUTDIR)/ProduceExchange.out: $(PRODUCE_EXCHANGE_SRC) \ - examples/produce-exchange/test/simpleSetupAndQuery.as | $(OUTDIR) - $(ASC) -ancient-system-api -r examples/produce-exchange/test/simpleSetupAndQuery.as > $@ + examples/produce-exchange/test/simpleSetupAndQuery.mo | $(OUTDIR) + $(MOC) -ancient-system-api -r examples/produce-exchange/test/simpleSetupAndQuery.mo > $@ $(OUTDIR)/retailerReserveMany.out: $(PRODUCE_EXCHANGE_SRC) \ - examples/produce-exchange/test/retailerReserveMany.as | $(OUTDIR) - $(ASC) -ancient-system-api -r examples/produce-exchange/test/retailerReserveMany.as > $@ + examples/produce-exchange/test/retailerReserveMany.mo | $(OUTDIR) + $(MOC) -ancient-system-api -r examples/produce-exchange/test/retailerReserveMany.mo > $@ $(OUTDIR)/producerRemInventory.out: $(PRODUCE_EXCHANGE_SRC) \ - examples/produce-exchange/test/producerRemInventory.as | $(OUTDIR) - $(ASC) -ancient-system-api -r examples/produce-exchange/test/producerRemInventory.as > $@ + examples/produce-exchange/test/producerRemInventory.mo | $(OUTDIR) + $(MOC) -ancient-system-api -r examples/produce-exchange/test/producerRemInventory.mo > $@ $(OUTDIR)/evalBulk.out: $(PRODUCE_EXCHANGE_SRC) \ - examples/produce-exchange/test/evalBulk.as | $(OUTDIR) - $(ASC) -ancient-system-api -r examples/produce-exchange/test/evalBulk.as > $@ + examples/produce-exchange/test/evalBulk.mo | $(OUTDIR) + $(MOC) -ancient-system-api -r examples/produce-exchange/test/evalBulk.mo > $@ $(OUTDIR)/ProduceExchange.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -ancient-system-api -c -o $@ examples/produce-exchange/serverActor.as + $(MOC) -ancient-system-api -c -o $@ examples/produce-exchange/serverActor.mo -$(DOCDIR)/%.md: %.as $(MDofAS) | $(DOCDIR) +$(DOCDIR)/%.md: %.mo $(MDofMO) | $(DOCDIR) @echo "" > $@ @echo "" >> $@ @echo "" >> $@ - $(MDofAS) $< >> $@ + $(MDofMO) $< >> $@ $(DOCDIR)/%.html: $(DOCDIR)/%.md $(PANDOC) -f gfm $^ > $@ @@ -242,17 +242,17 @@ $(DOCDIR)/%.html: $(DOCDIR)/%.md ## ACTORSPEC_SRC=\ - array.as \ - int.as \ - text.as \ - examples/actorspec/src/ActorSpec.as \ - examples/actorspec/demo/Demo.as \ + array.mo \ + int.mo \ + text.mo \ + examples/actorspec/src/ActorSpec.mo \ + examples/actorspec/demo/Demo.mo \ $(OUTDIR)/ActorSpec.wasm: $(ACTORSPEC_SRC) | $(OUTDIR) - $(ASC) -c -o $@ examples/actorspec/src/ActorSpec.as + $(MOC) -c -o $@ examples/actorspec/src/ActorSpec.mo $(OUTDIR)/ActorSpecDemo.wasm: $(ACTORSPEC_SRC) | $(OUTDIR) - $(ASC) -c -o $@ examples/actorspec/demo/Demo.as + $(MOC) -c -o $@ examples/actorspec/demo/Demo.mo #########################################################################################################33 @@ -262,16 +262,16 @@ $(OUTDIR)/ActorSpecDemo.wasm: $(ACTORSPEC_SRC) | $(OUTDIR) ## RX_SRC=\ - array.as \ - examples/rx/src/Rx.as \ - examples/rx/test/RxTest.as \ + array.mo \ + examples/rx/src/Rx.mo \ + examples/rx/test/RxTest.mo \ $(OUTDIR)/RxTest.out: $(RX_SRC) \ - examples/rx/test/RxTest.as | $(OUTDIR) - $(ASC) -r examples/rx/test/RxTest.as > $@ + examples/rx/test/RxTest.mo | $(OUTDIR) + $(MOC) -r examples/rx/test/RxTest.mo > $@ $(OUTDIR)/Rx.wasm: $(RX_SRC) | $(OUTDIR) - $(ASC) -c -o $@ examples/rx/src/Rx.as + $(MOC) -c -o $@ examples/rx/src/Rx.mo #########################################################################################################33 @@ -283,12 +283,12 @@ $(OUTDIR)/Rx.wasm: $(RX_SRC) | $(OUTDIR) # There is lot of redundancy, but I don't know how to hack the Makefile to overcome it without also making it too complex. PROFILE_LOAD_SRC=\ - examples/produce-exchange/serverActor.as \ - examples/produce-exchange/test/profileLoad.as + examples/produce-exchange/serverActor.mo \ + examples/produce-exchange/test/profileLoad.mo PROFILE_LOAD_QUERY_SRC=\ - examples/produce-exchange/serverActor.as \ - examples/produce-exchange/test/profileLoadQuery.as + examples/produce-exchange/serverActor.mo \ + examples/produce-exchange/test/profileLoadQuery.mo PROFILE_FIELDS=\ --profile-field "hash_bit_length" \ @@ -307,8 +307,8 @@ PROFILE_FIELDS=\ profile-fast-counts: \ $(OUTDIR)/profileFastCounts.csv -$(OUTDIR)/profileFastCounts.csv: examples/produce-exchange/test/profileFastCounts.as - $(ASC) -r examples/produce-exchange/test/profileFastCounts.as > $@ +$(OUTDIR)/profileFastCounts.csv: examples/produce-exchange/test/profileFastCounts.mo + $(MOC) -r examples/produce-exchange/test/profileFastCounts.mo > $@ profile-interp: \ $(OUTDIR)/profileLoadQuery.05-01.csv \ @@ -325,47 +325,47 @@ profile-interp: \ $(OUTDIR)/profileLoadQuery.05-50.csv \ $(OUTDIR)/profileLoadQuery.05-100.csv \ -## AS wishlist: the following various targets each take a params file that defines two variables used in the common test file. -## it would be better if we could accept named AS values as CLI params; that feature would obviate the need for the `param-X-Y.as` files used below: +## MO wishlist: the following various targets each take a params file that defines two variables used in the common test file. +## it would be better if we could accept named MO values as CLI params; that feature would obviate the need for the `param-X-Y.mo` files used below: $(OUTDIR)/profileLoadQuery.05-01.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) - time $(ASC) -r --profile examples/produce-exchange/test/params-5-1.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + time $(MOC) -r --profile examples/produce-exchange/test/params-5-1.mo $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) $(OUTDIR)/profileLoadQuery.05-02.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) - time $(ASC) -r --profile examples/produce-exchange/test/params-5-2.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + time $(MOC) -r --profile examples/produce-exchange/test/params-5-2.mo $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) $(OUTDIR)/profileLoadQuery.05-03.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) - time $(ASC) -r --profile examples/produce-exchange/test/params-5-3.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + time $(MOC) -r --profile examples/produce-exchange/test/params-5-3.mo $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) $(OUTDIR)/profileLoadQuery.05-04.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) - time $(ASC) -r --profile examples/produce-exchange/test/params-5-4.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + time $(MOC) -r --profile examples/produce-exchange/test/params-5-4.mo $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) $(OUTDIR)/profileLoadQuery.05-05.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) - time $(ASC) -r --profile examples/produce-exchange/test/params-5-5.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + time $(MOC) -r --profile examples/produce-exchange/test/params-5-5.mo $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) $(OUTDIR)/profileLoadQuery.05-06.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) - time $(ASC) -r --profile examples/produce-exchange/test/params-5-6.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + time $(MOC) -r --profile examples/produce-exchange/test/params-5-6.mo $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) $(OUTDIR)/profileLoadQuery.05-07.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) - time $(ASC) -r --profile examples/produce-exchange/test/params-5-7.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + time $(MOC) -r --profile examples/produce-exchange/test/params-5-7.mo $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) $(OUTDIR)/profileLoadQuery.05-08.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) - time $(ASC) -r --profile examples/produce-exchange/test/params-5-8.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + time $(MOC) -r --profile examples/produce-exchange/test/params-5-8.mo $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) $(OUTDIR)/profileLoadQuery.05-09.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) - time $(ASC) -r --profile examples/produce-exchange/test/params-5-9.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + time $(MOC) -r --profile examples/produce-exchange/test/params-5-9.mo $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) $(OUTDIR)/profileLoadQuery.05-10.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) - time $(ASC) -r --profile examples/produce-exchange/test/params-5-10.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + time $(MOC) -r --profile examples/produce-exchange/test/params-5-10.mo $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) $(OUTDIR)/profileLoadQuery.05-20.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) - time $(ASC) -r --profile examples/produce-exchange/test/params-5-20.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + time $(MOC) -r --profile examples/produce-exchange/test/params-5-20.mo $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) $(OUTDIR)/profileLoadQuery.05-50.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) - time $(ASC) -r --profile examples/produce-exchange/test/params-5-50.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + time $(MOC) -r --profile examples/produce-exchange/test/params-5-50.mo $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) $(OUTDIR)/profileLoadQuery.05-100.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) - time $(ASC) -r --profile examples/produce-exchange/test/params-5-100.as $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + time $(MOC) -r --profile examples/produce-exchange/test/params-5-100.mo $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) # wasm binaries and time measurements for various-sized PX workloads profile-wasm: $(OUTDIR) profile-fast-counts \ @@ -411,43 +411,43 @@ profile-wasm: $(OUTDIR) profile-fast-counts \ $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-1.as examples/produce-exchange/profileActor.as + $(MOC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-1.mo examples/produce-exchange/profileActor.mo $(OUTDIR)/ProduceExchangeLoadQuery_5_2.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-2.as examples/produce-exchange/profileActor.as + $(MOC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-2.mo examples/produce-exchange/profileActor.mo $(OUTDIR)/ProduceExchangeLoadQuery_5_3.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-3.as examples/produce-exchange/profileActor.as + $(MOC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-3.mo examples/produce-exchange/profileActor.mo $(OUTDIR)/ProduceExchangeLoadQuery_5_4.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-4.as examples/produce-exchange/profileActor.as + $(MOC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-4.mo examples/produce-exchange/profileActor.mo $(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-5.as examples/produce-exchange/profileActor.as + $(MOC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-5.mo examples/produce-exchange/profileActor.mo $(OUTDIR)/ProduceExchangeLoadQuery_5_6.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-6.as examples/produce-exchange/profileActor.as + $(MOC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-6.mo examples/produce-exchange/profileActor.mo $(OUTDIR)/ProduceExchangeLoadQuery_5_7.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-7.as examples/produce-exchange/profileActor.as + $(MOC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-7.mo examples/produce-exchange/profileActor.mo $(OUTDIR)/ProduceExchangeLoadQuery_5_8.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-8.as examples/produce-exchange/profileActor.as + $(MOC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-8.mo examples/produce-exchange/profileActor.mo $(OUTDIR)/ProduceExchangeLoadQuery_5_9.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-9.as examples/produce-exchange/profileActor.as + $(MOC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-9.mo examples/produce-exchange/profileActor.mo $(OUTDIR)/ProduceExchangeLoadQuery_5_10.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-10.as examples/produce-exchange/profileActor.as + $(MOC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-10.mo examples/produce-exchange/profileActor.mo $(OUTDIR)/ProduceExchangeLoadQuery_5_20.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-20.as examples/produce-exchange/profileActor.as + $(MOC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-20.mo examples/produce-exchange/profileActor.mo $(OUTDIR)/ProduceExchangeLoadQuery_5_50.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-50.as examples/produce-exchange/profileActor.as + $(MOC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-50.mo examples/produce-exchange/profileActor.mo $(OUTDIR)/ProduceExchangeLoadQuery_5_100.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(ASC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-100.as examples/produce-exchange/profileActor.as + $(MOC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-100.mo examples/produce-exchange/profileActor.mo $(STOPWATCH): $(STOPWATCH_C) diff --git a/stdlib/README.md b/stdlib/README.md index 2e81fabd39d..77fd7573f59 100644 --- a/stdlib/README.md +++ b/stdlib/README.md @@ -1,11 +1,11 @@ -ActorScript Standard Library +Motoko Standard Library ============================== Prior Documentation ------------------------- - [(Jira Story)](https://dfinity.atlassian.net/browse/AST-31): -- Older [See #127](https://github.com/dfinity-lab/actorscript/issues/127) +- Older [See #127](https://github.com/dfinity-lab/motoko/issues/127) -------------------------------------------------------------- @@ -13,7 +13,7 @@ Produce Exchange ================= We focus on explaining the role of these collections from perspective -of the [produce exchange example](https://github.com/dfinity-lab/actorscript/tree/stdlib-examples/stdlib/examples/produce-exchange). +of the [produce exchange example](https://github.com/dfinity-lab/motoko/tree/stdlib-examples/stdlib/examples/produce-exchange). See also, the [library modules by priority](#library-modules-by-priority). @@ -144,7 +144,7 @@ To do **Open questions** - If, how and when will the compiler/language just support this stuff "for free"? -- versus, how much should we write as ActorScript-based abstractions? +- versus, how much should we write as Motoko-based abstractions? --------------------------------------------------------------- diff --git a/stdlib/array.as b/stdlib/array.mo similarity index 100% rename from stdlib/array.as rename to stdlib/array.mo diff --git a/stdlib/arrayTest.as b/stdlib/arrayTest.mo similarity index 97% rename from stdlib/arrayTest.as rename to stdlib/arrayTest.mo index 68022c62320..02e77e5cc77 100644 --- a/stdlib/arrayTest.as +++ b/stdlib/arrayTest.mo @@ -1,6 +1,6 @@ -import Array "array.as"; -import Prelude "prelude.as"; -import Text "text.as"; +import Array "array.mo"; +import Prelude "prelude.mo"; +import Text "text.mo"; Prelude.printLn("Array"); diff --git a/stdlib/assocList.as b/stdlib/assocList.mo similarity index 98% rename from stdlib/assocList.as rename to stdlib/assocList.mo index ad354fc331f..01a9fa10b61 100644 --- a/stdlib/assocList.as +++ b/stdlib/assocList.mo @@ -4,13 +4,13 @@ module { Association Lists ================== -Association Lists, a la functional programming, in ActorScript. +Association Lists, a la functional programming, in Motoko. Implements the same interface as `Trie`, but as a linked-list of key-value pairs. */ -import List "list.as"; +import List "list.mo"; // polymorphic association linked lists between keys and values public type AssocList = List.List<(K,V)>; diff --git a/stdlib/docTable.as b/stdlib/docTable.mo similarity index 97% rename from stdlib/docTable.as rename to stdlib/docTable.mo index 0ec6d6a3740..2dc2201623f 100644 --- a/stdlib/docTable.as +++ b/stdlib/docTable.mo @@ -31,7 +31,7 @@ type information. notes on representation ------------------------- - The ActorScript standard library provides several purely-functional finite map representations: + The Motoko standard library provides several purely-functional finite map representations: - as association lists (via modules `List` and `AssocList`) - and as hash tries (via (module `Trie`), whose representation uses those lists, for its @@ -43,10 +43,10 @@ type information. */ -import Hash "hash.as"; +import Hash "hash.mo"; -//import Trie "trie.as"; -import Trie "trie2.as"; +//import Trie "trie.mo"; +import Trie "trie2.mo"; public type Hash = Hash.Hash; public type Trie = Trie.Trie; diff --git a/stdlib/examples/actorspec/README.md b/stdlib/examples/actorspec/README.md index 08c595584b1..00dddab68ff 100644 --- a/stdlib/examples/actorspec/README.md +++ b/stdlib/examples/actorspec/README.md @@ -1,6 +1,6 @@ # ActorSpec -A testing framework for ActorScript. +A testing framework for Motoko. ## Demo diff --git a/stdlib/examples/actorspec/demo/Demo.as b/stdlib/examples/actorspec/demo/Demo.mo similarity index 94% rename from stdlib/examples/actorspec/demo/Demo.as rename to stdlib/examples/actorspec/demo/Demo.mo index f366682d8f4..4da0be7bccf 100644 --- a/stdlib/examples/actorspec/demo/Demo.as +++ b/stdlib/examples/actorspec/demo/Demo.mo @@ -1,4 +1,4 @@ -import ActorSpec "../src/ActorSpec.as"; +import ActorSpec "../src/ActorSpec.mo"; type Group = ActorSpec.Group; diff --git a/stdlib/examples/actorspec/src/ActorSpec.as b/stdlib/examples/actorspec/src/ActorSpec.mo similarity index 97% rename from stdlib/examples/actorspec/src/ActorSpec.as rename to stdlib/examples/actorspec/src/ActorSpec.mo index 14c9c4e8b6f..3f8bed143c9 100644 --- a/stdlib/examples/actorspec/src/ActorSpec.as +++ b/stdlib/examples/actorspec/src/ActorSpec.mo @@ -1,7 +1,7 @@ module { - import Array "../../../array.as"; - import Int "../../../int.as"; - import Text "../../../text.as"; + import Array "../../../array.mo"; + import Int "../../../int.mo"; + import Text "../../../text.mo"; public type Group = { name : Text; diff --git a/stdlib/examples/produce-exchange/README.md b/stdlib/examples/produce-exchange/README.md index ac1e5882ba8..177dc04a17a 100644 --- a/stdlib/examples/produce-exchange/README.md +++ b/stdlib/examples/produce-exchange/README.md @@ -1,13 +1,13 @@ Produce Exchange Canister Component ===================================== -We give an example of ActorScript by implementing -the **Produce Exchange Canister** in ActorScript. +We give an example of Motoko by implementing +the **Produce Exchange Canister** in Motoko. The **produce exchange** gives a realistic marketplace-like application, and serves as a canonical example DFINITY Dapp. -We use it here to illustrate ActorScript the language, the standard +We use it here to illustrate Motoko the language, the standard library, and the associated the DFINITY Dapp design process. Prior documentation @@ -23,20 +23,20 @@ Current design documentation: The documentation of this design now evolves in two places: - 1. The SDK and ActorScript teams' documentation: + 1. The SDK and Motoko teams' documentation: i. Current [design document, under the SDK space](https://dfinity.atlassian.net/wiki/x/MwD2Bg). ii. Current [requirements document for the MVP Design](https://dfinity.atlassian.net/wiki/spaces/DE/pages/116654198/Produce+Exchange+MVP+Product+Requirements). - iii. Early, older [documentation under the ActorScript space](https://dfinity.atlassian.net/wiki/spaces/AST/pages/104401122/Example+Dapp+Produce+Exchange). + iii. Early, older [documentation under the Motoko space](https://dfinity.atlassian.net/wiki/spaces/AST/pages/104401122/Example+Dapp+Produce+Exchange). 2. [**This documentation and associated source - code**](https://github.com/dfinity-lab/actorscript/tree/stdlib-examples/stdlib/examples/produce-exchange) + code**](https://github.com/dfinity-lab/motoko/tree/stdlib-examples/stdlib/examples/produce-exchange) This code is implementing the **Produce Exchange Canister component**, - as a way to push the development of the ActorScript language, its + as a way to push the development of the Motoko language, its standard library, and elsewhere, the ambient DFINITY system that - runs ActorScript canisters. + runs Motoko canisters. -------------------------------------------------------------- @@ -56,9 +56,9 @@ We break the standards definition into several files, described below in detail **Server message formats** -As ActorScript-based documentation, the embedded source code for these +As Motoko-based documentation, the embedded source code for these components makes the standards definition into a **formal definition**, to -the same degree that ActorScript has a formal semantics of its own, in +the same degree that Motoko has a formal semantics of its own, in terms of DFINITY's semantics, etc: - The [server types](#server-types) define `shared` data types for client and server messages. @@ -97,7 +97,7 @@ into the **server _model_ components**, with the aspiration of the server component itself being a minimal wrapper over model definitions, and little to no logic of its own. -These models are based closely on the ActorScript **standard library**, +These models are based closely on the Motoko **standard library**, and basic functional programming design patterns, which we demonstrate through this example. @@ -116,7 +116,7 @@ Server components ========================== We decompose the _Canister_ for the **Produce Exchange example Dapp** -into an _ActorScript-based_ implementation of a "**Server**" with the +into an _Motoko-based_ implementation of a "**Server**" with the following definitional pieces, listed below. **Server types** @@ -126,7 +126,7 @@ Basic types used in messages, and published/stored internally in the server acto See [`serverTypes.md`]($DOCURL/examples/produce-exchange/serverTypes.html) for authoritative documentation. -See [`serverTypes.as`](https://github.com/dfinity-lab/actorscript/blob/stdlib-examples/stdlib/examples/produce-exchange/serverTypes.as) for the source code. +See [`serverTypes.mo`](https://github.com/dfinity-lab/motoko/blob/stdlib-examples/stdlib/examples/produce-exchange/serverTypes.mo) for the source code. **Server actor** ---------------------- @@ -135,7 +135,7 @@ Defined by the server actor's public signature, which specifies the messages and See [`serverActor.md`]($DOCURL/examples/produce-exchange/serverActor.html) for authoritative documentation. -See [`serverActor.as`](https://github.com/dfinity-lab/actorscript/blob/stdlib-examples/stdlib/examples/produce-exchange/serverActor.as) for the source code. +See [`serverActor.mo`](https://github.com/dfinity-lab/motoko/blob/stdlib-examples/stdlib/examples/produce-exchange/serverActor.mo) for the source code. **Server model types** @@ -145,12 +145,12 @@ This component defines structures that the next component uses to implement the See [`serverModelTypes.md`]($DOCURL/examples/produce-exchange/serverModelTypes.html) for authoritative documentation. -See [`serverModelTypes.as`](https://github.com/dfinity-lab/actorscript/blob/stdlib-examples/stdlib/examples/produce-exchange/serverModelTypes.as) for the source code. +See [`serverModelTypes.mo`](https://github.com/dfinity-lab/motoko/blob/stdlib-examples/stdlib/examples/produce-exchange/serverModelTypes.mo) for the source code. **Standard library** -------------------------- -See [the standard library](https://github.com/dfinity-lab/actorscript/tree/stdlib-examples/stdlib/#produce-exchange) +See [the standard library](https://github.com/dfinity-lab/motoko/tree/stdlib-examples/stdlib/#produce-exchange) for collection abstractions, including the [`DocTable` class]($DOCURL/docTable.html) @@ -166,7 +166,7 @@ types_](#server-model-types). See [`serverModel.md`]($DOCURL/examples/produce-exchange/serverModel.html) for authoritative documentation. -See [`serverModel.as`](https://github.com/dfinity-lab/actorscript/blob/stdlib-examples/stdlib/examples/produce-exchange/serverModel.as) for the source code. +See [`serverModel.mo`](https://github.com/dfinity-lab/motoko/blob/stdlib-examples/stdlib/examples/produce-exchange/serverModel.mo) for the source code. Note that while we define the **behavior for the server**, the _implementation details of this component and [server model @@ -176,7 +176,7 @@ subject to change independently of this definition. **Aside:** This model implementation is highly formulaic. In the future, we could likely _derive_ such implementations (auto-generate them) from a higher-level property and relation markup language -defined over, and targeting, the existing actorscript type system and +defined over, and targeting, the existing motoko type system and associated standard library patterns. @@ -344,20 +344,20 @@ Merge to `master` requirements: This example is a work in progress. It will be finished (and merged to `master`) when the following are in a stable state, and working -locally, as locally-running ActorScript. +locally, as locally-running Motoko. **Requirements list**: - 1. **the exchange’s interface definition**, as an ActorScript actor. + 1. **the exchange’s interface definition**, as an Motoko actor. 2. **the behavior of the exchange**, as that actor’s prototype implementation. 3. **the internal data model representation**, based on the - ActorScript language and standard library, used internally to the + Motoko language and standard library, used internally to the actor, to implement the specification behavior. 4. **test suite** for all of the above, using local execution and - ActorScript-based test cases. + Motoko-based test cases. **Canister component**: The requirements listed above also correspond with those of the *Canister component* in Milestone 2.0 of the [MVP @@ -428,12 +428,12 @@ Exit criteria for this Canister **Dates and people** -- [MVP features](#produce-exchange-canister-mvp-requirements) done on or before March 26 ActorScript team meeting +- [MVP features](#produce-exchange-canister-mvp-requirements) done on or before March 26 Motoko team meeting -- Full exit criteria met asap, before ActorScript and/or SDK launch (?) +- Full exit criteria met asap, before Motoko and/or SDK launch (?) - Most items below are tasked to @Matthewhammer; some require support - from other teams at DFINITY, including the ActorScript and SDK + from other teams at DFINITY, including the Motoko and SDK teams. **Feature-based metrics** @@ -518,7 +518,7 @@ We have the following questions: **2019.03.12 -- TODO-Cursors:** Introduce the idea of "cursors", with allocation, de-allocation and movement messages, as per discussion in - the 2019.03.12 ActorScript Team meeting. + the 2019.03.12 Motoko Team meeting. 2. For now, can we assume that the canister is maintained by the central authority? @@ -532,7 +532,7 @@ We have the following questions: ship on a single truck route? Presumably, we can? 5. Define a query language? - --- Not until ActorScript implements variant types. + --- Not until Motoko implements variant types. 6. [Canister upgrades](#canisterupgrades) @@ -546,11 +546,11 @@ The standards evolve according to the "central authority" (cf PE spec document), who we identify as the github repo and open source developer community that surrounds this implementation. -Updating the types in the standards requires changing the file `serverTypes.as` +Updating the types in the standards requires changing the file `serverTypes.mo` mentioned above, and performing a canister upgrade on the running system. Similarly, to evolve the behavioral definition of standards, the -implementation of this actor will change (in `serverActor.as` and -`serverModel.as`), and will also require a canister upgrade. +implementation of this actor will change (in `serverActor.mo` and +`serverModel.mo`), and will also require a canister upgrade. --------------------------------------------------------------------------------------- diff --git a/stdlib/examples/produce-exchange/profileActor.as b/stdlib/examples/produce-exchange/profileActor.mo similarity index 91% rename from stdlib/examples/produce-exchange/profileActor.as rename to stdlib/examples/produce-exchange/profileActor.mo index 2ade64777d1..0c788d1610e 100644 --- a/stdlib/examples/produce-exchange/profileActor.as +++ b/stdlib/examples/produce-exchange/profileActor.mo @@ -1,5 +1,5 @@ -let T = (import "serverTypes.as"); -let Model = (import "serverModel.as"); +let T = (import "serverTypes.mo"); +let Model = (import "serverModel.mo"); actor server { // morally: loadQuery (region_count:Nat, scale_factor:Nat) { diff --git a/stdlib/examples/produce-exchange/serverActor.as b/stdlib/examples/produce-exchange/serverActor.mo similarity index 98% rename from stdlib/examples/produce-exchange/serverActor.as rename to stdlib/examples/produce-exchange/serverActor.mo index 2b506197289..bd092a233bf 100644 --- a/stdlib/examples/produce-exchange/serverActor.as +++ b/stdlib/examples/produce-exchange/serverActor.mo @@ -4,16 +4,16 @@ -------------------- */ -import P = "../../prelude.as"; -import Option = "../../option.as"; -import T = "serverTypes.as"; -import L = "serverLang.as"; -import Model = "serverModel.as"; -import Result = "../../result.as"; +import P = "../../prelude.mo"; +import Option = "../../option.mo"; +import T = "serverTypes.mo"; +import L = "serverLang.mo"; +import Model = "serverModel.mo"; +import Result = "../../result.mo"; -let Trie = (import "../../trie2.as"); +let Trie = (import "../../trie2.mo"); -let List = (import "../../list.as"); +let List = (import "../../list.mo"); type List = List.List; type Result = Result.Result; @@ -1075,7 +1075,7 @@ been processed /////////////////////////////////////////////////////////////////////////// - // See `serverModel.as` for the Model class's implementation + // See `serverModel.mo` for the Model class's implementation // Matthew-Says: // There are two initialization options for the model field: diff --git a/stdlib/examples/produce-exchange/serverLang.as b/stdlib/examples/produce-exchange/serverLang.mo similarity index 98% rename from stdlib/examples/produce-exchange/serverLang.as rename to stdlib/examples/produce-exchange/serverLang.mo index 77f0e84affc..bdd64ad2ae1 100644 --- a/stdlib/examples/produce-exchange/serverLang.as +++ b/stdlib/examples/produce-exchange/serverLang.mo @@ -8,8 +8,8 @@ module { */ -import Result = "../../result.as"; -import T = "serverTypes.as"; +import Result = "../../result.mo"; +import T = "serverTypes.mo"; public type Result = Result.Result; diff --git a/stdlib/examples/produce-exchange/serverModel.as b/stdlib/examples/produce-exchange/serverModel.mo similarity index 99% rename from stdlib/examples/produce-exchange/serverModel.as rename to stdlib/examples/produce-exchange/serverModel.mo index 5ac6d4e9ba6..4e5c8782ca4 100644 --- a/stdlib/examples/produce-exchange/serverModel.as +++ b/stdlib/examples/produce-exchange/serverModel.mo @@ -22,20 +22,20 @@ uses are is not. */ -import P = "../../prelude.as"; +import P = "../../prelude.mo"; -import T = "serverTypes.as"; -import L = "serverLang.as"; -import M = "serverModelTypes.as"; +import T = "serverTypes.mo"; +import L = "serverLang.mo"; +import M = "serverModelTypes.mo"; -public let List = (import "../../list.as"); +public let List = (import "../../list.mo"); public type List = List.List; -public let Hash = (import "../../hash.as").BitVec; +public let Hash = (import "../../hash.mo").BitVec; public type Hash = Hash.t; -import Option = "../../option.as"; -import Trie = "../../trie2.as"; +import Option = "../../option.mo"; +import Trie = "../../trie2.mo"; public type Trie = Trie.Trie; public type TrieBuild = Trie.Build.TrieBuild; @@ -47,11 +47,11 @@ public let Table = Trie; public type Map = Trie.Trie; public let Map = Trie; -import DT = "../../docTable.as"; +import DT = "../../docTable.mo"; public let DocTable = DT.DocTable; public type DocTable = DT.DocTable; -import Result = "../../result.as"; +import Result = "../../result.mo"; public type Result = Result.Result; public type RouteInventoryMap = Trie<(T.RouteId, T.InventoryId), (M.RouteDoc, M.InventoryDoc)>; diff --git a/stdlib/examples/produce-exchange/serverModelTypes.as b/stdlib/examples/produce-exchange/serverModelTypes.mo similarity index 98% rename from stdlib/examples/produce-exchange/serverModelTypes.as rename to stdlib/examples/produce-exchange/serverModelTypes.mo index bc1bd858cab..6a499eb8fca 100644 --- a/stdlib/examples/produce-exchange/serverModelTypes.as +++ b/stdlib/examples/produce-exchange/serverModelTypes.mo @@ -12,7 +12,7 @@ internal model of the exchange. They are _not_ present in the public-facing interface of the server; they are only are used in its internal model implementation -`serverModel.as`. +`serverModel.mo`. */ @@ -33,9 +33,9 @@ Representation */ -import T = "serverTypes.as"; +import T = "serverTypes.mo"; -import Trie = "../../trie2.as"; +import Trie = "../../trie2.mo"; public type Trie = Trie.Trie; public type Map = Trie; @@ -97,7 +97,7 @@ internal sharing: */ -public let DocTable = (import "../../docTable.as"); +public let DocTable = (import "../../docTable.mo"); public type DocTable = DocTable.DocTable; /** diff --git a/stdlib/examples/produce-exchange/serverTypes.as b/stdlib/examples/produce-exchange/serverTypes.mo similarity index 99% rename from stdlib/examples/produce-exchange/serverTypes.as rename to stdlib/examples/produce-exchange/serverTypes.mo index 8594fc64628..e9ad4b26ca1 100644 --- a/stdlib/examples/produce-exchange/serverTypes.as +++ b/stdlib/examples/produce-exchange/serverTypes.mo @@ -380,7 +380,7 @@ xxx how to represent huge result messages? 2019.03.12 *** TODO-Cursors: Introduce the idea of "cursors", with allocation, de-allocation and movement messages, as per discussion in -the 2019.03.12 ActorScript Team meeting. +the 2019.03.12 Motoko Team meeting. */ diff --git a/stdlib/examples/produce-exchange/test/evalBulk.as b/stdlib/examples/produce-exchange/test/evalBulk.mo similarity index 98% rename from stdlib/examples/produce-exchange/test/evalBulk.as rename to stdlib/examples/produce-exchange/test/evalBulk.mo index a212ac9a1ef..8ddc4ea9da6 100644 --- a/stdlib/examples/produce-exchange/test/evalBulk.as +++ b/stdlib/examples/produce-exchange/test/evalBulk.mo @@ -1,7 +1,7 @@ -let T = (import "../serverTypes.as"); -let A = (import "../serverActor.as"); -let Result = (import "../../../result.as"); -let Option = (import "../../../option.as"); +let T = (import "../serverTypes.mo"); +let A = (import "../serverActor.mo"); +let Result = (import "../../../result.mo"); +let Option = (import "../../../option.mo"); func printEntityCount(entname:Text, count:Nat) { print ("- " # entname # " count: "); diff --git a/stdlib/examples/produce-exchange/test/loadWorkloadAndQuery.as b/stdlib/examples/produce-exchange/test/loadWorkloadAndQuery.mo similarity index 100% rename from stdlib/examples/produce-exchange/test/loadWorkloadAndQuery.as rename to stdlib/examples/produce-exchange/test/loadWorkloadAndQuery.mo diff --git a/stdlib/examples/produce-exchange/test/loadWorkloadAndQueryBig.as b/stdlib/examples/produce-exchange/test/loadWorkloadAndQueryBig.mo similarity index 96% rename from stdlib/examples/produce-exchange/test/loadWorkloadAndQueryBig.as rename to stdlib/examples/produce-exchange/test/loadWorkloadAndQueryBig.mo index 852721c2a58..cdf4772de9b 100644 --- a/stdlib/examples/produce-exchange/test/loadWorkloadAndQueryBig.as +++ b/stdlib/examples/produce-exchange/test/loadWorkloadAndQueryBig.mo @@ -1,7 +1,7 @@ -//let T = (import "../serverTypes.as"); -//let A = (import "../serverActor.as"); -//let Result = (import "../../../result.as"); -//let Option = (import "../../../option.as"); +//let T = (import "../serverTypes.mo"); +//let A = (import "../serverActor.mo"); +//let Result = (import "../../../result.mo"); +//let Option = (import "../../../option.mo"); func scaledParams(region_count_:Nat, factor:Nat) : T.WorkloadParams = shared { region_count = region_count_:Nat; diff --git a/stdlib/examples/produce-exchange/test/params-5-1.as b/stdlib/examples/produce-exchange/test/params-5-1.mo similarity index 100% rename from stdlib/examples/produce-exchange/test/params-5-1.as rename to stdlib/examples/produce-exchange/test/params-5-1.mo diff --git a/stdlib/examples/produce-exchange/test/params-5-10.as b/stdlib/examples/produce-exchange/test/params-5-10.mo similarity index 100% rename from stdlib/examples/produce-exchange/test/params-5-10.as rename to stdlib/examples/produce-exchange/test/params-5-10.mo diff --git a/stdlib/examples/produce-exchange/test/params-5-100.as b/stdlib/examples/produce-exchange/test/params-5-100.mo similarity index 100% rename from stdlib/examples/produce-exchange/test/params-5-100.as rename to stdlib/examples/produce-exchange/test/params-5-100.mo diff --git a/stdlib/examples/produce-exchange/test/params-5-2.as b/stdlib/examples/produce-exchange/test/params-5-2.mo similarity index 100% rename from stdlib/examples/produce-exchange/test/params-5-2.as rename to stdlib/examples/produce-exchange/test/params-5-2.mo diff --git a/stdlib/examples/produce-exchange/test/params-5-20.as b/stdlib/examples/produce-exchange/test/params-5-20.mo similarity index 100% rename from stdlib/examples/produce-exchange/test/params-5-20.as rename to stdlib/examples/produce-exchange/test/params-5-20.mo diff --git a/stdlib/examples/produce-exchange/test/params-5-3.as b/stdlib/examples/produce-exchange/test/params-5-3.mo similarity index 100% rename from stdlib/examples/produce-exchange/test/params-5-3.as rename to stdlib/examples/produce-exchange/test/params-5-3.mo diff --git a/stdlib/examples/produce-exchange/test/params-5-4.as b/stdlib/examples/produce-exchange/test/params-5-4.mo similarity index 100% rename from stdlib/examples/produce-exchange/test/params-5-4.as rename to stdlib/examples/produce-exchange/test/params-5-4.mo diff --git a/stdlib/examples/produce-exchange/test/params-5-5.as b/stdlib/examples/produce-exchange/test/params-5-5.mo similarity index 100% rename from stdlib/examples/produce-exchange/test/params-5-5.as rename to stdlib/examples/produce-exchange/test/params-5-5.mo diff --git a/stdlib/examples/produce-exchange/test/params-5-50.as b/stdlib/examples/produce-exchange/test/params-5-50.mo similarity index 100% rename from stdlib/examples/produce-exchange/test/params-5-50.as rename to stdlib/examples/produce-exchange/test/params-5-50.mo diff --git a/stdlib/examples/produce-exchange/test/params-5-6.as b/stdlib/examples/produce-exchange/test/params-5-6.mo similarity index 100% rename from stdlib/examples/produce-exchange/test/params-5-6.as rename to stdlib/examples/produce-exchange/test/params-5-6.mo diff --git a/stdlib/examples/produce-exchange/test/params-5-7.as b/stdlib/examples/produce-exchange/test/params-5-7.mo similarity index 100% rename from stdlib/examples/produce-exchange/test/params-5-7.as rename to stdlib/examples/produce-exchange/test/params-5-7.mo diff --git a/stdlib/examples/produce-exchange/test/params-5-8.as b/stdlib/examples/produce-exchange/test/params-5-8.mo similarity index 100% rename from stdlib/examples/produce-exchange/test/params-5-8.as rename to stdlib/examples/produce-exchange/test/params-5-8.mo diff --git a/stdlib/examples/produce-exchange/test/params-5-9.as b/stdlib/examples/produce-exchange/test/params-5-9.mo similarity index 100% rename from stdlib/examples/produce-exchange/test/params-5-9.as rename to stdlib/examples/produce-exchange/test/params-5-9.mo diff --git a/stdlib/examples/produce-exchange/test/producerRemInventory.as b/stdlib/examples/produce-exchange/test/producerRemInventory.mo similarity index 98% rename from stdlib/examples/produce-exchange/test/producerRemInventory.as rename to stdlib/examples/produce-exchange/test/producerRemInventory.mo index 46390b0b127..8792d4545ef 100644 --- a/stdlib/examples/produce-exchange/test/producerRemInventory.as +++ b/stdlib/examples/produce-exchange/test/producerRemInventory.mo @@ -1,7 +1,7 @@ -let T = (import "../serverTypes.as"); -let A = (import "../serverActor.as"); -let Result = (import "../../../result.as"); -let Option = (import "../../../option.as"); +let T = (import "../serverTypes.mo"); +let A = (import "../serverActor.mo"); +let Result = (import "../../../result.mo"); +let Option = (import "../../../option.mo"); func printEntityCount(entname:Text, count:Nat) { print ("- " # entname # " count: "); diff --git a/stdlib/examples/produce-exchange/test/profileFastCounts.as b/stdlib/examples/produce-exchange/test/profileFastCounts.mo similarity index 88% rename from stdlib/examples/produce-exchange/test/profileFastCounts.as rename to stdlib/examples/produce-exchange/test/profileFastCounts.mo index c45d79ce2e9..a194af18ae2 100644 --- a/stdlib/examples/produce-exchange/test/profileFastCounts.as +++ b/stdlib/examples/produce-exchange/test/profileFastCounts.mo @@ -2,8 +2,8 @@ // we correlate these numbers with times that we // measure elsewhere, where these numbers are not available. -let T = (import "../serverTypes.as"); -let Model = (import "../serverModel.as"); +let T = (import "../serverTypes.mo"); +let Model = (import "../serverModel.mo"); let m = Model.Model(); diff --git a/stdlib/examples/produce-exchange/test/profileLoad.as b/stdlib/examples/produce-exchange/test/profileLoad.mo similarity index 100% rename from stdlib/examples/produce-exchange/test/profileLoad.as rename to stdlib/examples/produce-exchange/test/profileLoad.mo diff --git a/stdlib/examples/produce-exchange/test/profileLoadQuery.as b/stdlib/examples/produce-exchange/test/profileLoadQuery.mo similarity index 100% rename from stdlib/examples/produce-exchange/test/profileLoadQuery.as rename to stdlib/examples/produce-exchange/test/profileLoadQuery.mo diff --git a/stdlib/examples/produce-exchange/test/retailerReserveMany.as b/stdlib/examples/produce-exchange/test/retailerReserveMany.mo similarity index 98% rename from stdlib/examples/produce-exchange/test/retailerReserveMany.as rename to stdlib/examples/produce-exchange/test/retailerReserveMany.mo index 9e4e84e91ac..dff476cbd6f 100644 --- a/stdlib/examples/produce-exchange/test/retailerReserveMany.as +++ b/stdlib/examples/produce-exchange/test/retailerReserveMany.mo @@ -1,7 +1,7 @@ -let T = (import "../serverTypes.as"); -let A = (import "../serverActor.as"); -let Result = (import "../../../result.as"); -let Option = (import "../../../option.as"); +let T = (import "../serverTypes.mo"); +let A = (import "../serverActor.mo"); +let Result = (import "../../../result.mo"); +let Option = (import "../../../option.mo"); func printEntityCount(entname:Text, count:Nat) { print ("- " # entname # " count: "); diff --git a/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.as b/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.mo similarity index 99% rename from stdlib/examples/produce-exchange/test/simpleSetupAndQuery.as rename to stdlib/examples/produce-exchange/test/simpleSetupAndQuery.mo index ab2a1956886..080b47f906f 100644 --- a/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.as +++ b/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.mo @@ -1,7 +1,7 @@ -import T = "../serverTypes.as"; -import A = "../serverActor.as"; -import Result = "../../../result.as"; -import Option = "../../../option.as"; +import T = "../serverTypes.mo"; +import A = "../serverActor.mo"; +import Result = "../../../result.mo"; +import Option = "../../../option.mo"; func printEntityCount(entname:Text, count:Nat) { print ("- " # entname # " count: "); diff --git a/stdlib/examples/rx/README.md b/stdlib/examples/rx/README.md index 45ba3d2fe3e..bbc528f94ab 100644 --- a/stdlib/examples/rx/README.md +++ b/stdlib/examples/rx/README.md @@ -1,3 +1,3 @@ -# RxActorScript +# RxMotoko -A [ReactiveX](http://reactivex.io/) implementation in ActorScript. +A [ReactiveX](http://reactivex.io/) implementation in Motoko. diff --git a/stdlib/examples/rx/src/Disposable.as b/stdlib/examples/rx/src/Disposable.mo similarity index 100% rename from stdlib/examples/rx/src/Disposable.as rename to stdlib/examples/rx/src/Disposable.mo diff --git a/stdlib/examples/rx/src/Event.as b/stdlib/examples/rx/src/Event.mo similarity index 100% rename from stdlib/examples/rx/src/Event.as rename to stdlib/examples/rx/src/Event.mo diff --git a/stdlib/examples/rx/src/Observable.as b/stdlib/examples/rx/src/Observable.mo similarity index 83% rename from stdlib/examples/rx/src/Observable.as rename to stdlib/examples/rx/src/Observable.mo index d0a882972a9..bf8d830324a 100644 --- a/stdlib/examples/rx/src/Observable.as +++ b/stdlib/examples/rx/src/Observable.mo @@ -1,6 +1,6 @@ module { - import Disposable "Disposable.as"; - import Observer "Observer.as"; + import Disposable "Disposable.mo"; + import Observer "Observer.mo"; type Subscriber = Observer.Type -> Disposable.Type; diff --git a/stdlib/examples/rx/src/Observer.as b/stdlib/examples/rx/src/Observer.mo similarity index 95% rename from stdlib/examples/rx/src/Observer.as rename to stdlib/examples/rx/src/Observer.mo index b16a5b018aa..0812f3c273b 100644 --- a/stdlib/examples/rx/src/Observer.as +++ b/stdlib/examples/rx/src/Observer.mo @@ -1,5 +1,5 @@ module { - import Event "Event.as"; + import Event "Event.mo"; public type EventHandler = Event.Type -> (); diff --git a/stdlib/examples/rx/src/Rx.as b/stdlib/examples/rx/src/Rx.as deleted file mode 100644 index 60b1b8f3960..00000000000 --- a/stdlib/examples/rx/src/Rx.as +++ /dev/null @@ -1,4 +0,0 @@ -import Disposable = "Disposable.as"; -import Event = "Event.as"; -import Observable = "Observable.as"; -import Observer = "Observer.as"; diff --git a/stdlib/examples/rx/src/Rx.mo b/stdlib/examples/rx/src/Rx.mo new file mode 100644 index 00000000000..a0bb5ec6605 --- /dev/null +++ b/stdlib/examples/rx/src/Rx.mo @@ -0,0 +1,4 @@ +import Disposable = "Disposable.mo"; +import Event = "Event.mo"; +import Observable = "Observable.mo"; +import Observer = "Observer.mo"; diff --git a/stdlib/examples/rx/test/RxTest.as b/stdlib/examples/rx/test/RxTest.mo similarity index 97% rename from stdlib/examples/rx/test/RxTest.as rename to stdlib/examples/rx/test/RxTest.mo index 1eb5024ec8b..69eaf73d630 100644 --- a/stdlib/examples/rx/test/RxTest.as +++ b/stdlib/examples/rx/test/RxTest.mo @@ -1,5 +1,5 @@ -import Array "../../../array.as"; -import Rx "../src/Rx.as"; +import Array "../../../array.mo"; +import Rx "../src/Rx.mo"; type Error = { description : Text; diff --git a/stdlib/hash.as b/stdlib/hash.mo similarity index 100% rename from stdlib/hash.as rename to stdlib/hash.mo diff --git a/stdlib/int.as b/stdlib/int.mo similarity index 95% rename from stdlib/int.as rename to stdlib/int.mo index 8dbf0083bcf..cbb1fc2ab33 100644 --- a/stdlib/int.as +++ b/stdlib/int.mo @@ -1,5 +1,5 @@ module { - import Prelude "prelude.as"; + import Prelude "prelude.mo"; public func add(x : Int, y : Int) : Int { x + y; diff --git a/stdlib/intTest.as b/stdlib/intTest.mo similarity index 90% rename from stdlib/intTest.as rename to stdlib/intTest.mo index 6e5b4fc0e21..495116948b9 100644 --- a/stdlib/intTest.as +++ b/stdlib/intTest.mo @@ -1,5 +1,5 @@ -import Prelude "prelude.as"; -import Int "int.as"; +import Prelude "prelude.mo"; +import Int "int.mo"; Prelude.printLn("Int"); diff --git a/stdlib/list.as b/stdlib/list.mo similarity index 100% rename from stdlib/list.as rename to stdlib/list.mo diff --git a/stdlib/listTest.as b/stdlib/listTest.mo similarity index 98% rename from stdlib/listTest.as rename to stdlib/listTest.mo index 21a9439898b..92e8091a648 100644 --- a/stdlib/listTest.as +++ b/stdlib/listTest.mo @@ -1,5 +1,5 @@ type X = Nat; -import List "list.as"; +import List "list.mo"; func opnatEq(a : ?Nat, b : ?Nat) : Bool { switch (a, b) { diff --git a/stdlib/nat.as b/stdlib/nat.mo similarity index 71% rename from stdlib/nat.as rename to stdlib/nat.mo index 5bfc670e8c9..365250d31fa 100644 --- a/stdlib/nat.as +++ b/stdlib/nat.mo @@ -1,6 +1,6 @@ module { - import Int "int.as"; - import Prelude "prelude.as"; + import Int "int.mo"; + import Prelude "prelude.mo"; public func add(x : Nat, y : Nat) : Nat { x + y; diff --git a/stdlib/natTest.as b/stdlib/natTest.mo similarity index 88% rename from stdlib/natTest.as rename to stdlib/natTest.mo index 910b5b142af..c6a2b7c3b49 100644 --- a/stdlib/natTest.as +++ b/stdlib/natTest.mo @@ -1,5 +1,5 @@ -import Prelude "prelude.as"; -import Nat "nat.as"; +import Prelude "prelude.mo"; +import Nat "nat.mo"; Prelude.printLn("Nat"); diff --git a/stdlib/option.as b/stdlib/option.mo similarity index 99% rename from stdlib/option.as rename to stdlib/option.mo index 58656d06a19..adb2b3d3209 100644 --- a/stdlib/option.as +++ b/stdlib/option.mo @@ -5,7 +5,7 @@ Functions for Option types. */ -import P "prelude.as"; +import P "prelude.mo"; public type t = ?A; diff --git a/stdlib/optionTest.as b/stdlib/optionTest.mo similarity index 98% rename from stdlib/optionTest.as rename to stdlib/optionTest.mo index ccf94eba908..70f09ced846 100644 --- a/stdlib/optionTest.as +++ b/stdlib/optionTest.mo @@ -1,5 +1,5 @@ -import Option "option.as"; -import Prelude "prelude.as"; +import Option "option.mo"; +import Prelude "prelude.mo"; Prelude.printLn("Option"); diff --git a/stdlib/prelude.as b/stdlib/prelude.mo similarity index 100% rename from stdlib/prelude.as rename to stdlib/prelude.mo diff --git a/stdlib/result.as b/stdlib/result.mo similarity index 96% rename from stdlib/result.as rename to stdlib/result.mo index 101fbb249a7..017e3cdadee 100644 --- a/stdlib/result.as +++ b/stdlib/result.mo @@ -1,5 +1,5 @@ module { -import P "prelude.as"; +import P "prelude.mo"; /** @@ -8,7 +8,7 @@ import P "prelude.as"; The result of a computation that may contain errors, exceptions, etc. - ActorScript does not have exceptions, so we use a datatype to encode these outcomes. + Motoko does not have exceptions, so we use a datatype to encode these outcomes. Rust does something analogous, for the same reason. We use the Rust nomenclature for the datatype and its constructors. diff --git a/stdlib/set.as b/stdlib/set.mo similarity index 97% rename from stdlib/set.as rename to stdlib/set.mo index b8247561ed4..88003b68a71 100644 --- a/stdlib/set.as +++ b/stdlib/set.mo @@ -18,8 +18,8 @@ */ module { -import Trie "trie2.as"; -import Hash "hash.as"; +import Trie "trie2.mo"; +import Hash "hash.mo"; public type Hash = Hash.Hash; public type Set = Trie.Trie; diff --git a/stdlib/text.as b/stdlib/text.mo similarity index 100% rename from stdlib/text.as rename to stdlib/text.mo diff --git a/stdlib/textTest.as b/stdlib/textTest.mo similarity index 75% rename from stdlib/textTest.as rename to stdlib/textTest.mo index 4dbffa819eb..af3cdbd46de 100644 --- a/stdlib/textTest.as +++ b/stdlib/textTest.mo @@ -1,5 +1,5 @@ -import Prelude "prelude.as"; -import Text "text.as"; +import Prelude "prelude.mo"; +import Text "text.mo"; Prelude.printLn("Text"); diff --git a/stdlib/tools/markdown-of-markdown.py b/stdlib/tools/markdown-of-markdown.py index 14c719d9b7d..e703fec09d5 100755 --- a/stdlib/tools/markdown-of-markdown.py +++ b/stdlib/tools/markdown-of-markdown.py @@ -2,12 +2,12 @@ ## Stable links ## ----------- -## https://hydra.oregon.dfinity.build//job/dfinity-ci-build/actorscript.pr-234/stdlib-reference/latest/download/1/doc/ +## https://hydra.oregon.dfinity.build//job/dfinity-ci-build/motoko.pr-234/stdlib-reference/latest/download/1/doc/ ## ## (PR 234 is the current PR for the standard library and produce exchange) ## -DOCURL="https://hydra.oregon.dfinity.build//job/dfinity-ci-build/actorscript.pr-234/stdlib-reference/latest/download/1/doc/" +DOCURL="https://hydra.oregon.dfinity.build//job/dfinity-ci-build/motoko.pr-234/stdlib-reference/latest/download/1/doc/" ############################################################################################################# diff --git a/stdlib/tools/markdown-of-actorscript.py b/stdlib/tools/markdown-of-motoko.py similarity index 80% rename from stdlib/tools/markdown-of-actorscript.py rename to stdlib/tools/markdown-of-motoko.py index 4fee319ca7a..31f9013d8ab 100755 --- a/stdlib/tools/markdown-of-actorscript.py +++ b/stdlib/tools/markdown-of-motoko.py @@ -3,21 +3,21 @@ ## Objective ## ---------- ## -## The objective of this program is to "Invert" an ActorScript source +## The objective of this program is to "Invert" an Motoko source ## file into a corresponding Markdown file with snippets of -## ActorScript. The markdown becomes the "outer format" with -## ActorScript (as code blocks) as the "inner format". In this sense, +## Motoko. The markdown becomes the "outer format" with +## Motoko (as code blocks) as the "inner format". In this sense, ## the objective is to "invert" the inner/outer relationship, and ## preserve everything else that's sensible. ## ## Design question: If we have the freedom to order the Decls of an -## ActorScript file any way we choose, then what's the best order to +## Motoko file any way we choose, then what's the best order to ## tell a **narrative** version of the file? ## The immediate benefit of using this tool: ## ## - The stdlib directory is source code that documents itself to seed -## WIP guide for ActorScript; this workflow is possible via a +## WIP guide for Motoko; this workflow is possible via a ## Makefile. ## ## - By exposing the Markdown on the outside, the outline/narrative @@ -33,50 +33,50 @@ ## ------------ ## ## - KISS: This tool is a placeholder for a better tool that actually -## understands ActorScript. +## understands Motoko. ## ## - KISS: This tool does not try to be intelligent ## when it can force you (the programmer) to do something only ## somewhat annoying, e.g.: ## -## - KISS: Dont mix mode-switch patterns and other ActorScript comments on a single line +## - KISS: Dont mix mode-switch patterns and other Motoko comments on a single line ## - KISS: Dont mix mode switches on a single line. ## ## Stable links ## ----------- -## https://hydra.oregon.dfinity.build//job/dfinity-ci-build/actorscript.pr-234/stdlib-reference/latest/download/1/doc/ +## https://hydra.oregon.dfinity.build//job/dfinity-ci-build/motoko.pr-234/stdlib-reference/latest/download/1/doc/ ## ## (PR 234 is the current PR for the standard library and produce exchange) ## -DOCURL="https://hydra.oregon.dfinity.build//job/dfinity-ci-build/actorscript.pr-234/stdlib-reference/latest/download/1/doc/" +DOCURL="https://hydra.oregon.dfinity.build//job/dfinity-ci-build/motoko.pr-234/stdlib-reference/latest/download/1/doc/" ############################################################################################################# import sys import re -showActorScript=True -#showActorScript=False +showMotoko=True +#showMotoko=False -OmitActorScript="OmitActorScript" -ActorScript="ActorScript" +OmitMotoko="OmitMotoko" +Motoko="Motoko" Markdown="Markdown" Comment="Comment" Done="Done" -modeType=[ActorScript, Markdown, Comment, OmitActorScript, Done] +modeType=[Motoko, Markdown, Comment, OmitMotoko, Done] # eventually, detect this `outerMode` based on the input file name and # handle the other way around; for now, we assume only this way # around: -outerMode = ActorScript +outerMode = Motoko ignoreNonMarkdownComments= False mode = outerMode -modeOpen="```ActorScript" +modeOpen="```Motoko" modeLines = [] modeClose="```" @@ -91,7 +91,7 @@ def switchModeTo(toMode, toModeOpen, toModeClose): if len(modeLines) > 0: # Normal case: - if mode != OmitActorScript and (showActorScript or mode != ActorScript): + if mode != OmitMotoko and (showMotoko or mode != Motoko): print modeOpen if modeLines[-1] == "": modeLines.pop() @@ -101,14 +101,14 @@ def switchModeTo(toMode, toModeOpen, toModeClose): print(l.rstrip()) print modeClose # The source file explicitly omitted this - elif mode == OmitActorScript: + elif mode == OmitMotoko: print "```" print ". . . (selectively omitted, explicitly) . . ." print "```" # the flag says no - elif mode == ActorScript and not showActorScript: + elif mode == Motoko and not showMotoko: print "```" - print ". . . (all ActorScript is omitted) . . ." + print ". . . (all Motoko is omitted) . . ." print "```" # impossible! else: @@ -156,10 +156,10 @@ def whiteSpaceLine(): elif re.match(r'/\*', line.lstrip()): switchModeTo(Comment, "/* ", "*/") - # Horizontal rule, in actorscript code + # Horizontal rule, in motoko code elif re.match(r'//////////+', line.lstrip()): - # Horizontal rule in ActorScript - if mode == ActorScript: + # Horizontal rule in Motoko + if mode == Motoko: if len(modeLines) > 0: modeLines.append("```") modeLines.append("-----------------------------------------------------------------------") @@ -167,16 +167,16 @@ def whiteSpaceLine(): else: assert True - # Close markdown or comment block and omit the next otherwise-ActorScript block: + # Close markdown or comment block and omit the next otherwise-Motoko block: elif re.match(r'//\s*@Omit:', line.lstrip()): - switchModeTo(OmitActorScript, "", "") + switchModeTo(OmitMotoko, "", "") # One-line comment elif re.match(r'//+ \S*\s*', line.lstrip()): matches = re.split(r'//+ ', line.lstrip()) if mode == Markdown: modeLines.append(matches[1].rstrip()) - elif mode == ActorScript: + elif mode == Motoko: if ignoreNonMarkdownComments: #debug "ignoring single-line comment." assert True @@ -185,7 +185,7 @@ def whiteSpaceLine(): modeLines.append(line.rstrip()) elif mode == Comment: modeLines.append(matches[1].rstrip()) - elif mode == OmitActorScript: + elif mode == OmitMotoko: assert True else: assert False @@ -196,7 +196,7 @@ def whiteSpaceLine(): # Close markdown or comment block elif re.match(r'\*/', line.lstrip()): - switchModeTo(ActorScript, "```ActorScript", "```") + switchModeTo(Motoko, "```Motoko", "```") else: #debug "non-empty line" diff --git a/stdlib/trie.as b/stdlib/trie.mo similarity index 99% rename from stdlib/trie.as rename to stdlib/trie.mo index cc78a549bc8..a714ca7dbd9 100644 --- a/stdlib/trie.as +++ b/stdlib/trie.mo @@ -61,14 +61,14 @@ See the full details in the definitions below: */ -import H "hash.as"; +import H "hash.mo"; public let Hash = H.BitVec; public type Hash = Hash.t; -import List "list.as"; +import List "list.mo"; public type List = List.List; -import AssocList "assocList.as"; +import AssocList "assocList.mo"; public type AssocList = AssocList.AssocList; public let HASH_BITS = 4; @@ -1092,7 +1092,7 @@ public type Trie3D = Trie >; /** Helpers for missing variants ============================== - Until ActorScript has variant types, we need various helper functions here. They are uninteresting. + Until Motoko has variant types, we need various helper functions here. They are uninteresting. */ // @Omit: diff --git a/stdlib/trie2.as b/stdlib/trie2.mo similarity index 99% rename from stdlib/trie2.as rename to stdlib/trie2.mo index e01aa54ef5d..9c73b6a14e9 100644 --- a/stdlib/trie2.as +++ b/stdlib/trie2.mo @@ -73,18 +73,18 @@ public let MAX_LEAF_COUNT = 8; // <-- beats both 4 and 16 for me, now //let MAX_LEAF_COUNT = 16; //let MAX_LEAF_COUNT = 32; -import P "prelude.as"; +import P "prelude.mo"; -import Option "option.as"; +import Option "option.mo"; -import H "hash.as"; +import H "hash.mo"; public let Hash = H.BitVec; public type Hash = Hash.t; -import List "list.as"; +import List "list.mo"; public type List = List.List; -import AssocList "assocList.as"; +import AssocList "assocList.mo"; public type AssocList = AssocList.AssocList; /** A `Key` for the trie has an associated hash value */ diff --git a/test/.gitignore b/test/.gitignore index dd444a1bdfb..7acb84c198f 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -1,7 +1,7 @@ _out -new-asc -old-asc +new-moc +old-moc compare-out coverage diff --git a/test/README.md b/test/README.md index a7348f08319..6ca993c1438 100644 --- a/test/README.md +++ b/test/README.md @@ -1,4 +1,4 @@ -The ActorScript test suite +The Motoko test suite ========================== Commands @@ -24,26 +24,26 @@ Run these either in the top level directory, or in one of the subdirectories. You can also run individual tests, for example: - ./run.sh run/fac.as + ./run.sh run/fac.mo to run and - ./run.sh -a run/fac.as + ./run.sh -a run/fac.mo to accept. Adding a new test ----------------- -1. Create `foo.as` -2. Run `make accept` (or, more targeted, `../run.sh -a foo.as`) -3. Add `foo.as` and `ok/foo.*.ok` to git. +1. Create `foo.mo` +2. Run `make accept` (or, more targeted, `../run.sh -a foo.mo`) +3. Add `foo.mo` and `ok/foo.*.ok` to git. Running as a `nix` derivation ----------------------------- -You can run the test suite from the `actorscript` (top-level) directory as: +You can run the test suite from the `motoko` (top-level) directory as: ``` shell $ nix-build -A tests diff --git a/test/as-idl/Makefile b/test/as-idl/Makefile index 942d9205bd9..ea891c3e46b 100644 --- a/test/as-idl/Makefile +++ b/test/as-idl/Makefile @@ -1,10 +1,10 @@ RUNFLAGS = -i all: - ../run.sh $(RUNFLAGS) *.as + ../run.sh $(RUNFLAGS) *.mo accept: - ../run.sh $(RUNFLAGS) -a *.as + ../run.sh $(RUNFLAGS) -a *.mo clean: rm -rf _out diff --git a/test/as-idl/counter.as b/test/as-idl/counter.mo similarity index 100% rename from test/as-idl/counter.as rename to test/as-idl/counter.mo diff --git a/test/as-idl/fields.as b/test/as-idl/fields.mo similarity index 100% rename from test/as-idl/fields.as rename to test/as-idl/fields.mo diff --git a/test/as-idl/inline_result.as b/test/as-idl/inline_result.mo similarity index 100% rename from test/as-idl/inline_result.as rename to test/as-idl/inline_result.mo diff --git a/test/as-idl/pa_cars.as b/test/as-idl/pa_cars.mo similarity index 100% rename from test/as-idl/pa_cars.as rename to test/as-idl/pa_cars.mo diff --git a/test/as-idl/recursion.as b/test/as-idl/recursion.mo similarity index 100% rename from test/as-idl/recursion.as rename to test/as-idl/recursion.mo diff --git a/test/as-idl/result.as b/test/as-idl/result.mo similarity index 100% rename from test/as-idl/result.as rename to test/as-idl/result.mo diff --git a/test/bugs/aritybug.as b/test/bugs/aritybug.mo similarity index 53% rename from test/bugs/aritybug.as rename to test/bugs/aritybug.mo index d0d526a24c8..caf9bb00324 100644 --- a/test/bugs/aritybug.as +++ b/test/bugs/aritybug.mo @@ -1,10 +1,10 @@ -// fails in the interpreter at line * with ../../src/asc -r u.as -// fails in the interpreter at line * with ../../src/asc -r -a u.as -// but succeeds ../../src/asc -r -a -A u.as +// fails in the interpreter at line * with ../../src/moc -r u.mo +// fails in the interpreter at line * with ../../src/moc -r -a u.mo +// but succeeds ../../src/moc -r -a -A u.mo // the problem is that the type-checker accepts line * because (Int,) and Int domain types -// aren't distinguished after arity raising, since Type.as_seq Int = Type.as_seq (Tup[Int]), +// aren't distinguished after arity raising, since Type.mo_seq Int = Type.mo_seq (Tup[Int]), // eventhough Int != Tup[Int] { diff --git a/test/bugs/freeclass1.as b/test/bugs/freeclass1.mo similarity index 100% rename from test/bugs/freeclass1.as rename to test/bugs/freeclass1.mo diff --git a/test/bugs/sharingbug.as b/test/bugs/sharingbug.mo similarity index 100% rename from test/bugs/sharingbug.as rename to test/bugs/sharingbug.mo diff --git a/test/bugs/unboundclass.as b/test/bugs/unboundclass.mo similarity index 100% rename from test/bugs/unboundclass.as rename to test/bugs/unboundclass.mo diff --git a/test/bugs/usedefbug.as b/test/bugs/usedefbug.mo similarity index 100% rename from test/bugs/usedefbug.as rename to test/bugs/usedefbug.mo diff --git a/test/compare-wat.sh b/test/compare-wat.sh index 70965888d0c..129c2c9792c 100755 --- a/test/compare-wat.sh +++ b/test/compare-wat.sh @@ -24,15 +24,15 @@ done shift $((OPTIND-1)) function build_ref_to { - rm -f $2-asc + rm -f $2-moc if [ -z "$1" ] then - echo "Building $2 asc from working copy.." - chronic nix-build -E '((import ./..) {}).asc' \ + echo "Building $2 moc from working copy.." + chronic nix-build -E '((import ./..) {}).moc' \ --option binary-caches '' \ - -o $2-asc/ + -o $2-moc/ else - echo "Building $2 asc (rev $1).." + echo "Building $2 moc (rev $1).." chronic nix-build \ --argstr ref "$(git for-each-ref --count 1 --contains "$1" --format '%(refname)')" \ --argstr rev "$1" \ @@ -40,13 +40,13 @@ function build_ref_to { -E ' {rev, ref, path}: let nixpkg = import (../nix/nixpkgs.nix).nixpkgs {}; in - let checkout = (builtins.fetchGit {url = path; ref = ref; rev = rev; name = "old-asc";}).outPath; in + let checkout = (builtins.fetchGit {url = path; ref = ref; rev = rev; name = "old-moc";}).outPath; in builtins.trace checkout ( - ((import checkout) {}).asc)' \ + ((import checkout) {}).moc)' \ --option binary-caches '' \ - -o $2-asc/ + -o $2-moc/ fi - test -x $2-asc/bin/asc || exit 1 + test -x $2-moc/bin/moc || exit 1 } build_ref_to "$old" old build_ref_to "$new" new @@ -54,7 +54,7 @@ build_ref_to "$new" new mkdir -p compare-out/ if [[ $# -eq 0 ]] ; then - args="*/*.as" + args="*/*.mo" else args="$@" fi @@ -63,22 +63,22 @@ for file in $args do if [ ! -e $file ] then - echo "ActorScript file $file does not exist." + echo "Motoko file $file does not exist." exit 1 fi - base=$(basename $file .as) + base=$(basename $file .mo) rm -rf compare-out/$base.old mkdir compare-out/$base.old - old-asc/bin/asc $file -o compare-out/$base.old/$base.wasm 2> compare-out/$base.old/$base.stderr + old-moc/bin/moc $file -o compare-out/$base.old/$base.wasm 2> compare-out/$base.old/$base.stderr test ! -e compare-out/$base.old/$base.wasm || $WASM2WAT compare-out/$base.old/$base.wasm >& compare-out/$base.old/$base.wat #wasm-objdump -s -h -d compare-out/$base.old/$base.wasm > compare-out/$base.old/$base.dump rm -rf compare-out/$base.new mkdir compare-out/$base.new - new-asc/bin/asc $file -o compare-out/$base.new/$base.wasm 2> compare-out/$base.new/$base.stderr + new-moc/bin/moc $file -o compare-out/$base.new/$base.wasm 2> compare-out/$base.new/$base.stderr test ! -e compare-out/$base.new/$base.wasm || $WASM2WAT compare-out/$base.new/$base.wasm >& compare-out/$base.new/$base.wat #wasm-objdump -s -h -d compare-out/$base.new/$base.wasm > compare-out/$base.new/$base.dump diff --git a/test/fail/AST-60.as b/test/fail/AST-60.mo similarity index 100% rename from test/fail/AST-60.as rename to test/fail/AST-60.mo diff --git a/test/fail/Makefile b/test/fail/Makefile index ca32260888f..733076dc3a2 100644 --- a/test/fail/Makefile +++ b/test/fail/Makefile @@ -1,10 +1,10 @@ RUNFLAGS = all: - ../run.sh $(RUNFLAGS) *.as + ../run.sh $(RUNFLAGS) *.mo accept: - ../run.sh $(RUNFLAGS) -a *.as + ../run.sh $(RUNFLAGS) -a *.mo clean: rm -rf _out diff --git a/test/fail/abstract-msgs.as b/test/fail/abstract-msgs.mo similarity index 100% rename from test/fail/abstract-msgs.as rename to test/fail/abstract-msgs.mo diff --git a/test/fail/actor-match.as b/test/fail/actor-match.mo similarity index 100% rename from test/fail/actor-match.as rename to test/fail/actor-match.mo diff --git a/test/fail/actor-reexport.as b/test/fail/actor-reexport.mo similarity index 100% rename from test/fail/actor-reexport.as rename to test/fail/actor-reexport.mo diff --git a/test/fail/argument-subtyping.as b/test/fail/argument-subtyping.mo similarity index 100% rename from test/fail/argument-subtyping.as rename to test/fail/argument-subtyping.mo diff --git a/test/fail/ast81-clash.as b/test/fail/ast81-clash.mo similarity index 100% rename from test/fail/ast81-clash.as rename to test/fail/ast81-clash.mo diff --git a/test/fail/asyncret1.as b/test/fail/asyncret1.mo similarity index 100% rename from test/fail/asyncret1.as rename to test/fail/asyncret1.mo diff --git a/test/fail/asyncret2.as b/test/fail/asyncret2.mo similarity index 100% rename from test/fail/asyncret2.as rename to test/fail/asyncret2.mo diff --git a/test/fail/asyncret3.as b/test/fail/asyncret3.mo similarity index 100% rename from test/fail/asyncret3.as rename to test/fail/asyncret3.mo diff --git a/test/fail/await-in-actor.as b/test/fail/await-in-actor.mo similarity index 100% rename from test/fail/await-in-actor.as rename to test/fail/await-in-actor.mo diff --git a/test/fail/bad-unops.as b/test/fail/bad-unops.mo similarity index 100% rename from test/fail/bad-unops.as rename to test/fail/bad-unops.mo diff --git a/test/fail/branch-before-define.as b/test/fail/branch-before-define.mo similarity index 100% rename from test/fail/branch-before-define.as rename to test/fail/branch-before-define.mo diff --git a/test/fail/char-high-surrogate-trap.as b/test/fail/char-high-surrogate-trap.mo similarity index 100% rename from test/fail/char-high-surrogate-trap.as rename to test/fail/char-high-surrogate-trap.mo diff --git a/test/fail/char-high-surrogate.as b/test/fail/char-high-surrogate.mo similarity index 100% rename from test/fail/char-high-surrogate.as rename to test/fail/char-high-surrogate.mo diff --git a/test/fail/char-low-surrogate-trap.as b/test/fail/char-low-surrogate-trap.mo similarity index 100% rename from test/fail/char-low-surrogate-trap.as rename to test/fail/char-low-surrogate-trap.mo diff --git a/test/fail/char-low-surrogate.as b/test/fail/char-low-surrogate.mo similarity index 100% rename from test/fail/char-low-surrogate.as rename to test/fail/char-low-surrogate.mo diff --git a/test/fail/char-trap.as b/test/fail/char-trap.mo similarity index 100% rename from test/fail/char-trap.as rename to test/fail/char-trap.mo diff --git a/test/fail/class.as b/test/fail/class.mo similarity index 100% rename from test/fail/class.as rename to test/fail/class.mo diff --git a/test/fail/const-var-array.as b/test/fail/const-var-array.mo similarity index 100% rename from test/fail/const-var-array.as rename to test/fail/const-var-array.mo diff --git a/test/fail/const-var-field.as b/test/fail/const-var-field.mo similarity index 100% rename from test/fail/const-var-field.as rename to test/fail/const-var-field.mo diff --git a/test/fail/cyclic-bound1.as b/test/fail/cyclic-bound1.mo similarity index 100% rename from test/fail/cyclic-bound1.as rename to test/fail/cyclic-bound1.mo diff --git a/test/fail/cyclic-bound2.as b/test/fail/cyclic-bound2.mo similarity index 100% rename from test/fail/cyclic-bound2.as rename to test/fail/cyclic-bound2.mo diff --git a/test/fail/cyclic-bound3.as b/test/fail/cyclic-bound3.mo similarity index 100% rename from test/fail/cyclic-bound3.as rename to test/fail/cyclic-bound3.mo diff --git a/test/fail/cyclic-bound4.as b/test/fail/cyclic-bound4.mo similarity index 100% rename from test/fail/cyclic-bound4.as rename to test/fail/cyclic-bound4.mo diff --git a/test/fail/cyclic-bound5.as b/test/fail/cyclic-bound5.mo similarity index 100% rename from test/fail/cyclic-bound5.as rename to test/fail/cyclic-bound5.mo diff --git a/test/fail/debug.as b/test/fail/debug.mo similarity index 100% rename from test/fail/debug.as rename to test/fail/debug.mo diff --git a/test/fail/decl-clash.as b/test/fail/decl-clash.mo similarity index 100% rename from test/fail/decl-clash.as rename to test/fail/decl-clash.mo diff --git a/test/fail/duplicate-field.as b/test/fail/duplicate-field.mo similarity index 100% rename from test/fail/duplicate-field.as rename to test/fail/duplicate-field.mo diff --git a/test/fail/f-bounds-fail.as b/test/fail/f-bounds-fail.mo similarity index 100% rename from test/fail/f-bounds-fail.as rename to test/fail/f-bounds-fail.mo diff --git a/test/fail/issue103.as b/test/fail/issue103.mo similarity index 100% rename from test/fail/issue103.as rename to test/fail/issue103.mo diff --git a/test/fail/issue167.as b/test/fail/issue167.mo similarity index 100% rename from test/fail/issue167.as rename to test/fail/issue167.mo diff --git a/test/fail/issue36.as b/test/fail/issue36.mo similarity index 100% rename from test/fail/issue36.as rename to test/fail/issue36.mo diff --git a/test/fail/lib/not-static.as b/test/fail/lib/not-static.mo similarity index 100% rename from test/fail/lib/not-static.as rename to test/fail/lib/not-static.mo diff --git a/test/fail/modexp1.as b/test/fail/modexp1.mo similarity index 100% rename from test/fail/modexp1.as rename to test/fail/modexp1.mo diff --git a/test/fail/modexp2.as b/test/fail/modexp2.mo similarity index 100% rename from test/fail/modexp2.as rename to test/fail/modexp2.mo diff --git a/test/fail/modexp3.as b/test/fail/modexp3.mo similarity index 100% rename from test/fail/modexp3.as rename to test/fail/modexp3.mo diff --git a/test/fail/modexp4.as b/test/fail/modexp4.mo similarity index 100% rename from test/fail/modexp4.as rename to test/fail/modexp4.mo diff --git a/test/fail/modexp5.as b/test/fail/modexp5.mo similarity index 100% rename from test/fail/modexp5.as rename to test/fail/modexp5.mo diff --git a/test/fail/modules-fwd.as b/test/fail/modules-fwd.mo similarity index 100% rename from test/fail/modules-fwd.as rename to test/fail/modules-fwd.mo diff --git a/test/fail/modules-shadow.as b/test/fail/modules-shadow.mo similarity index 100% rename from test/fail/modules-shadow.as rename to test/fail/modules-shadow.mo diff --git a/test/fail/nested-class-rec-fail.as b/test/fail/nested-class-rec-fail.mo similarity index 100% rename from test/fail/nested-class-rec-fail.as rename to test/fail/nested-class-rec-fail.mo diff --git a/test/fail/non_static_module.as b/test/fail/non_static_module.mo similarity index 100% rename from test/fail/non_static_module.as rename to test/fail/non_static_module.mo diff --git a/test/fail/nonlinear-pat.as b/test/fail/nonlinear-pat.mo similarity index 100% rename from test/fail/nonlinear-pat.as rename to test/fail/nonlinear-pat.mo diff --git a/test/fail/not-static.as b/test/fail/not-static.as deleted file mode 100644 index 596308eee35..00000000000 --- a/test/fail/not-static.as +++ /dev/null @@ -1 +0,0 @@ -import "lib/not-static.as" diff --git a/test/fail/not-static.mo b/test/fail/not-static.mo new file mode 100644 index 00000000000..d6e681668bb --- /dev/null +++ b/test/fail/not-static.mo @@ -0,0 +1 @@ +import "lib/not-static.mo" diff --git a/test/fail/object-patterns.as b/test/fail/object-patterns.mo similarity index 100% rename from test/fail/object-patterns.as rename to test/fail/object-patterns.mo diff --git a/test/fail/objpat-duplicate.as b/test/fail/objpat-duplicate.mo similarity index 100% rename from test/fail/objpat-duplicate.as rename to test/fail/objpat-duplicate.mo diff --git a/test/fail/objpat-infer.as b/test/fail/objpat-infer.mo similarity index 100% rename from test/fail/objpat-infer.as rename to test/fail/objpat-infer.mo diff --git a/test/fail/objpat-mutable.as b/test/fail/objpat-mutable.mo similarity index 100% rename from test/fail/objpat-mutable.as rename to test/fail/objpat-mutable.mo diff --git a/test/fail/ok/AST-60.tc.ok b/test/fail/ok/AST-60.tc.ok index e74c5ac71fc..f6fe12e8ca9 100644 --- a/test/fail/ok/AST-60.tc.ok +++ b/test/fail/ok/AST-60.tc.ok @@ -1 +1 @@ -AST-60.as:2.5-2.9: type error, duplicate definition for test in block +AST-60.mo:2.5-2.9: type error, duplicate definition for test in block diff --git a/test/fail/ok/abstract-msgs.tc.ok b/test/fail/ok/abstract-msgs.tc.ok index 3e72f5ede4d..c89d6e6a5b1 100644 --- a/test/fail/ok/abstract-msgs.tc.ok +++ b/test/fail/ok/abstract-msgs.tc.ok @@ -1,19 +1,19 @@ -abstract-msgs.as:2.28-2.37: type error, shared function has non-shared parameter type +abstract-msgs.mo:2.28-2.37: type error, shared function has non-shared parameter type A/9 -abstract-msgs.as:3.33-3.35: type error, shared function must have syntactic return type `()` or `async ` -abstract-msgs.as:5.20-5.29: type error, shared function has non-shared parameter type +abstract-msgs.mo:3.33-3.35: type error, shared function must have syntactic return type `()` or `async ` +abstract-msgs.mo:5.20-5.29: type error, shared function has non-shared parameter type A/10 -abstract-msgs.as:6.31-6.33: type error, async has non-shared content type +abstract-msgs.mo:6.31-6.33: type error, async has non-shared content type ?A/10 -abstract-msgs.as:10.34-10.35: type error, shared function has non-shared parameter type +abstract-msgs.mo:10.34-10.35: type error, shared function has non-shared parameter type A/11 -abstract-msgs.as:11.46-11.47: type error, async has non-shared content type +abstract-msgs.mo:11.46-11.47: type error, async has non-shared content type A/12 -abstract-msgs.as:14.30-14.31: type error, shared function has non-shared parameter type +abstract-msgs.mo:14.30-14.31: type error, shared function has non-shared parameter type A/13 -abstract-msgs.as:15.42-15.43: type error, async has non-shared content type +abstract-msgs.mo:15.42-15.43: type error, async has non-shared content type A/14 -abstract-msgs.as:16.31-16.32: type error, shared function has non-shared parameter type +abstract-msgs.mo:16.31-16.32: type error, shared function has non-shared parameter type A/15 -abstract-msgs.as:17.43-17.44: type error, async has non-shared content type +abstract-msgs.mo:17.43-17.44: type error, async has non-shared content type A/16 diff --git a/test/fail/ok/actor-match.tc.ok b/test/fail/ok/actor-match.tc.ok index 215e094f045..e2d46f432a7 100644 --- a/test/fail/ok/actor-match.tc.ok +++ b/test/fail/ok/actor-match.tc.ok @@ -1,2 +1,2 @@ -actor-match.as:7.8-7.14: type error, object pattern cannot consume actor type +actor-match.mo:7.8-7.14: type error, object pattern cannot consume actor type actor {f : shared () -> (); g : shared () -> ()} diff --git a/test/fail/ok/actor-reexport.tc.ok b/test/fail/ok/actor-reexport.tc.ok index b677a38239d..b62fb6463f0 100644 --- a/test/fail/ok/actor-reexport.tc.ok +++ b/test/fail/ok/actor-reexport.tc.ok @@ -1,3 +1,3 @@ -actor-reexport.as:5.10-5.37: type error, public actor field needs to be a manifest function -actor-reexport.as:9.10-9.48: type error, public actor field needs to be a manifest function -actor-reexport.as:10.10-14.39: type error, public actor field needs to be a manifest function +actor-reexport.mo:5.10-5.37: type error, public actor field needs to be a manifest function +actor-reexport.mo:9.10-9.48: type error, public actor field needs to be a manifest function +actor-reexport.mo:10.10-14.39: type error, public actor field needs to be a manifest function diff --git a/test/fail/ok/argument-subtyping.tc.ok b/test/fail/ok/argument-subtyping.tc.ok index 2f9ad83d739..3c605bf39d5 100644 --- a/test/fail/ok/argument-subtyping.tc.ok +++ b/test/fail/ok/argument-subtyping.tc.ok @@ -1,4 +1,4 @@ -argument-subtyping.as:12.58-12.59: type error, expression of type +argument-subtyping.mo:12.58-12.59: type error, expression of type shared Nat -> () cannot produce expected type shared Text -> () diff --git a/test/fail/ok/ast81-clash.tc.ok b/test/fail/ok/ast81-clash.tc.ok index 5523bebdb52..e9b16244c7e 100644 --- a/test/fail/ok/ast81-clash.tc.ok +++ b/test/fail/ok/ast81-clash.tc.ok @@ -1 +1 @@ -ast81-clash.as:8.11-8.12: type error, duplicate definition for x in block +ast81-clash.mo:8.11-8.12: type error, duplicate definition for x in block diff --git a/test/fail/ok/asyncret1.tc.ok b/test/fail/ok/asyncret1.tc.ok index d309c7fde94..fcfc5b51505 100644 --- a/test/fail/ok/asyncret1.tc.ok +++ b/test/fail/ok/asyncret1.tc.ok @@ -1 +1 @@ -asyncret1.as:1.39-1.40: type error, shared function must have syntactic return type `()` or `async ` +asyncret1.mo:1.39-1.40: type error, shared function must have syntactic return type `()` or `async ` diff --git a/test/fail/ok/asyncret2.tc.ok b/test/fail/ok/asyncret2.tc.ok index c9e51a16899..e8b9e5ae132 100644 --- a/test/fail/ok/asyncret2.tc.ok +++ b/test/fail/ok/asyncret2.tc.ok @@ -1,4 +1,4 @@ -asyncret2.as:1.54-1.57: type error, expression of type +asyncret2.mo:1.54-1.57: type error, expression of type async Int cannot produce expected type Int diff --git a/test/fail/ok/asyncret3.tc.ok b/test/fail/ok/asyncret3.tc.ok index d42f77fb1b0..f9e804955a7 100644 --- a/test/fail/ok/asyncret3.tc.ok +++ b/test/fail/ok/asyncret3.tc.ok @@ -1 +1 @@ -asyncret3.as:1.61-1.64: type error, shared function with async result type has non-async body +asyncret3.mo:1.61-1.64: type error, shared function with async result type has non-async body diff --git a/test/fail/ok/await-in-actor.tc.ok b/test/fail/ok/await-in-actor.tc.ok index f597d1e26dd..716028fe7db 100644 --- a/test/fail/ok/await-in-actor.tc.ok +++ b/test/fail/ok/await-in-actor.tc.ok @@ -1 +1 @@ -await-in-actor.as:3.13-3.30: type error, misplaced await +await-in-actor.mo:3.13-3.30: type error, misplaced await diff --git a/test/fail/ok/bad-unops.tc.ok b/test/fail/ok/bad-unops.tc.ok index a198cbd0dc0..86fbb1c5e46 100644 --- a/test/fail/ok/bad-unops.tc.ok +++ b/test/fail/ok/bad-unops.tc.ok @@ -1,24 +1,24 @@ -bad-unops.as:1.9-1.11: type error, operator is not defined for operand type +bad-unops.mo:1.9-1.11: type error, operator is not defined for operand type Int -bad-unops.as:2.9-2.12: type error, operator is not defined for operand type +bad-unops.mo:2.9-2.12: type error, operator is not defined for operand type Int -bad-unops.as:3.15-3.17: type error, literal of type +bad-unops.mo:3.15-3.17: type error, literal of type Int does not have expected type Nat -bad-unops.as:4.15-4.17: type error, literal of type +bad-unops.mo:4.15-4.17: type error, literal of type Int does not have expected type Nat -bad-unops.as:6.20-6.22: type error, operator cannot consume expected type +bad-unops.mo:6.20-6.22: type error, operator cannot consume expected type Nat -bad-unops.as:7.20-7.22: type error, literal of type +bad-unops.mo:7.20-7.22: type error, literal of type Int does not have expected type Nat -bad-unops.as:8.20-8.22: type error, literal of type +bad-unops.mo:8.20-8.22: type error, literal of type Int does not have expected type Nat -bad-unops.as:10.21-10.23: type error, operator cannot consume expected type +bad-unops.mo:10.21-10.23: type error, operator cannot consume expected type Int diff --git a/test/fail/ok/branch-before-define.tc.ok b/test/fail/ok/branch-before-define.tc.ok index a9e4d22abb8..2d6a970dae5 100644 --- a/test/fail/ok/branch-before-define.tc.ok +++ b/test/fail/ok/branch-before-define.tc.ok @@ -1 +1 @@ -branch-before-define.as:4.7-4.40: definedness error, cannot use g before x has been defined +branch-before-define.mo:4.7-4.40: definedness error, cannot use g before x has been defined diff --git a/test/fail/ok/char-high-surrogate.tc.ok b/test/fail/ok/char-high-surrogate.tc.ok index d6971c274cc..e096a515ab5 100644 --- a/test/fail/ok/char-high-surrogate.tc.ok +++ b/test/fail/ok/char-high-surrogate.tc.ok @@ -1 +1 @@ -char-high-surrogate.as:1.9-1.19: syntax error, unicode escape out of range +char-high-surrogate.mo:1.9-1.19: syntax error, unicode escape out of range diff --git a/test/fail/ok/char-low-surrogate.tc.ok b/test/fail/ok/char-low-surrogate.tc.ok index d8b84c45181..a2b338aa590 100644 --- a/test/fail/ok/char-low-surrogate.tc.ok +++ b/test/fail/ok/char-low-surrogate.tc.ok @@ -1 +1 @@ -char-low-surrogate.as:1.9-1.19: syntax error, unicode escape out of range +char-low-surrogate.mo:1.9-1.19: syntax error, unicode escape out of range diff --git a/test/fail/ok/class.tc.ok b/test/fail/ok/class.tc.ok index bd29ff5289f..fc737580530 100644 --- a/test/fail/ok/class.tc.ok +++ b/test/fail/ok/class.tc.ok @@ -1,18 +1,18 @@ -class.as:43.1-43.26: type error, class body of type +class.mo:43.1-43.26: type error, class body of type {} does not match expected type {x : Int} -class.as:44.1-46.2: type error, class body of type +class.mo:44.1-46.2: type error, class body of type {x : Int} does not match expected type {x : Nat} -class.as:48.1-48.27: type error, class body of type +class.mo:48.1-48.27: type error, class body of type {} does not match expected type actor {} -class.as:49.1-49.27: type error, class body of type +class.mo:49.1-49.27: type error, class body of type actor {} does not match expected type {} -class.as:52.27-52.28: type error, type field T does not exist in type +class.mo:52.27-52.28: type error, type field T does not exist in type {} diff --git a/test/fail/ok/const-var-array.tc.ok b/test/fail/ok/const-var-array.tc.ok index 74f605301e2..c4afcceafa8 100644 --- a/test/fail/ok/const-var-array.tc.ok +++ b/test/fail/ok/const-var-array.tc.ok @@ -1,2 +1,2 @@ -const-var-array.as:1.17-1.22: type error, mutable array expression cannot produce expected type +const-var-array.mo:1.17-1.22: type error, mutable array expression cannot produce expected type [Nat] diff --git a/test/fail/ok/const-var-field.tc.ok b/test/fail/ok/const-var-field.tc.ok index d9e34d9b401..56bb51440bd 100644 --- a/test/fail/ok/const-var-field.tc.ok +++ b/test/fail/ok/const-var-field.tc.ok @@ -1,4 +1,4 @@ -const-var-field.as:1.21-1.48: type error, expression of type +const-var-field.mo:1.21-1.48: type error, expression of type {var x : Nat} cannot produce expected type {x : Nat} diff --git a/test/fail/ok/cyclic-bound1.tc.ok b/test/fail/ok/cyclic-bound1.tc.ok index 0672e7b81c3..7693c99e7c9 100644 --- a/test/fail/ok/cyclic-bound1.tc.ok +++ b/test/fail/ok/cyclic-bound1.tc.ok @@ -1 +1 @@ -cyclic-bound1.as:3.8-3.14: type error, type parameter A/9 has cyclic bounds A/9 <: A/9 +cyclic-bound1.mo:3.8-3.14: type error, type parameter A/9 has cyclic bounds A/9 <: A/9 diff --git a/test/fail/ok/cyclic-bound2.tc.ok b/test/fail/ok/cyclic-bound2.tc.ok index a2345990137..4b8c98012f8 100644 --- a/test/fail/ok/cyclic-bound2.tc.ok +++ b/test/fail/ok/cyclic-bound2.tc.ok @@ -1 +1 @@ -cyclic-bound2.as:3.8-3.14: type error, type parameter A/9 has cyclic bounds B <: A/9 <: B +cyclic-bound2.mo:3.8-3.14: type error, type parameter A/9 has cyclic bounds B <: A/9 <: B diff --git a/test/fail/ok/cyclic-bound3.tc.ok b/test/fail/ok/cyclic-bound3.tc.ok index c930aac4bf5..1bfe11c1eba 100644 --- a/test/fail/ok/cyclic-bound3.tc.ok +++ b/test/fail/ok/cyclic-bound3.tc.ok @@ -1 +1 @@ -cyclic-bound3.as:3.8-3.14: type error, type parameter A/9 has cyclic bounds B <: A/9 <: C <: B +cyclic-bound3.mo:3.8-3.14: type error, type parameter A/9 has cyclic bounds B <: A/9 <: C <: B diff --git a/test/fail/ok/cyclic-bound4.tc.ok b/test/fail/ok/cyclic-bound4.tc.ok index 5f2d686a07a..5c35400b6f6 100644 --- a/test/fail/ok/cyclic-bound4.tc.ok +++ b/test/fail/ok/cyclic-bound4.tc.ok @@ -1 +1 @@ -cyclic-bound4.as:7.8-7.17: type error, type parameter A/9 has cyclic bounds B <: A/9 <: C/1 <: B +cyclic-bound4.mo:7.8-7.17: type error, type parameter A/9 has cyclic bounds B <: A/9 <: C/1 <: B diff --git a/test/fail/ok/cyclic-bound5.tc.ok b/test/fail/ok/cyclic-bound5.tc.ok index 893a82c4281..15f641b3628 100644 --- a/test/fail/ok/cyclic-bound5.tc.ok +++ b/test/fail/ok/cyclic-bound5.tc.ok @@ -1 +1 @@ -cyclic-bound5.as:7.8-7.17: type error, type parameter U/1 has cyclic bounds U/1 <: U/1 +cyclic-bound5.mo:7.8-7.17: type error, type parameter U/1 has cyclic bounds U/1 <: U/1 diff --git a/test/fail/ok/debug.tc.ok b/test/fail/ok/debug.tc.ok index 70d2b72adaf..660805d48c2 100644 --- a/test/fail/ok/debug.tc.ok +++ b/test/fail/ok/debug.tc.ok @@ -1,4 +1,4 @@ -debug.as:1.9-1.11: type error, literal of type +debug.mo:1.9-1.11: type error, literal of type Nat does not have expected type () diff --git a/test/fail/ok/decl-clash.tc.ok b/test/fail/ok/decl-clash.tc.ok index a8d57a3427b..523c6240ed4 100644 --- a/test/fail/ok/decl-clash.tc.ok +++ b/test/fail/ok/decl-clash.tc.ok @@ -1 +1 @@ -decl-clash.as:2.5-2.9: type error, duplicate definition for test in block +decl-clash.mo:2.5-2.9: type error, duplicate definition for test in block diff --git a/test/fail/ok/duplicate-field.tc.ok b/test/fail/ok/duplicate-field.tc.ok index 5c8099b99da..65b3f73815e 100644 --- a/test/fail/ok/duplicate-field.tc.ok +++ b/test/fail/ok/duplicate-field.tc.ok @@ -1 +1 @@ -duplicate-field.as:4.15-4.16: type error, duplicate definition for m in block +duplicate-field.mo:4.15-4.16: type error, duplicate definition for m in block diff --git a/test/fail/ok/f-bounds-fail.tc.ok b/test/fail/ok/f-bounds-fail.tc.ok index ff8436a1726..75012ff3fd1 100644 --- a/test/fail/ok/f-bounds-fail.tc.ok +++ b/test/fail/ok/f-bounds-fail.tc.ok @@ -1,176 +1,176 @@ -f-bounds-fail.as:13.42-13.43: type error, type argument +f-bounds-fail.mo:13.42-13.43: type error, type argument A/10 does not match parameter bound C -f-bounds-fail.as:14.42-14.43: type error, type argument +f-bounds-fail.mo:14.42-14.43: type error, type argument A/11 does not match parameter bound C/1 -f-bounds-fail.as:15.42-15.43: type error, type argument +f-bounds-fail.mo:15.42-15.43: type error, type argument A/12 does not match parameter bound C/2 -f-bounds-fail.as:3.38-3.41: type error, type argument +f-bounds-fail.mo:3.38-3.41: type error, type argument Int does not match parameter bound Nat -f-bounds-fail.as:9.53-9.54: type error, expression of type +f-bounds-fail.mo:9.53-9.54: type error, expression of type A/19 cannot produce expected type C/6 -f-bounds-fail.as:10.52-10.53: type error, expression of type +f-bounds-fail.mo:10.52-10.53: type error, expression of type A/20 cannot produce expected type C/7 -f-bounds-fail.as:11.52-11.53: type error, expression of type +f-bounds-fail.mo:11.52-11.53: type error, expression of type A/21 cannot produce expected type C/8 -f-bounds-fail.as:45.23-45.25: type error, expression of type +f-bounds-fail.mo:45.23-45.25: type error, expression of type () cannot produce expected type A/22 -> A/22 -f-bounds-fail.as:46.23-46.25: type error, expression of type +f-bounds-fail.mo:46.23-46.25: type error, expression of type () cannot produce expected type A/22 -> B/13 -f-bounds-fail.as:47.23-47.25: type error, expression of type +f-bounds-fail.mo:47.23-47.25: type error, expression of type () cannot produce expected type A/22 -> B/13 -f-bounds-fail.as:48.23-48.25: type error, expression of type +f-bounds-fail.mo:48.23-48.25: type error, expression of type () cannot produce expected type B/13 -> B/13 -f-bounds-fail.as:49.23-49.25: type error, expression of type +f-bounds-fail.mo:49.23-49.25: type error, expression of type () cannot produce expected type B/13 -> C/9 -f-bounds-fail.as:50.14-50.15: type error, type argument +f-bounds-fail.mo:50.14-50.15: type error, type argument B/13 does not match parameter bound C/9 -f-bounds-fail.as:50.23-50.25: type error, expression of type +f-bounds-fail.mo:50.23-50.25: type error, expression of type () cannot produce expected type B/13 -> C/9 -f-bounds-fail.as:51.23-51.25: type error, expression of type +f-bounds-fail.mo:51.23-51.25: type error, expression of type () cannot produce expected type C/9 -> C/9 -f-bounds-fail.as:53.23-53.25: type error, expression of type +f-bounds-fail.mo:53.23-53.25: type error, expression of type () cannot produce expected type A/22 -> A/22 -f-bounds-fail.as:54.23-54.25: type error, expression of type +f-bounds-fail.mo:54.23-54.25: type error, expression of type () cannot produce expected type A/22 -> B/13 -f-bounds-fail.as:55.23-55.25: type error, expression of type +f-bounds-fail.mo:55.23-55.25: type error, expression of type () cannot produce expected type A/22 -> B/13 -f-bounds-fail.as:56.23-56.25: type error, expression of type +f-bounds-fail.mo:56.23-56.25: type error, expression of type () cannot produce expected type B/13 -> B/13 -f-bounds-fail.as:57.23-57.25: type error, expression of type +f-bounds-fail.mo:57.23-57.25: type error, expression of type () cannot produce expected type B/13 -> C/9 -f-bounds-fail.as:58.16-58.17: type error, type argument +f-bounds-fail.mo:58.16-58.17: type error, type argument B/13 does not match parameter bound C/9 -f-bounds-fail.as:58.23-58.25: type error, expression of type +f-bounds-fail.mo:58.23-58.25: type error, expression of type () cannot produce expected type B/13 -> C/9 -f-bounds-fail.as:59.23-59.25: type error, expression of type +f-bounds-fail.mo:59.23-59.25: type error, expression of type () cannot produce expected type C/9 -> C/9 -f-bounds-fail.as:61.23-61.25: type error, expression of type +f-bounds-fail.mo:61.23-61.25: type error, expression of type () cannot produce expected type A/22 -> A/22 -f-bounds-fail.as:62.23-62.25: type error, expression of type +f-bounds-fail.mo:62.23-62.25: type error, expression of type () cannot produce expected type A/22 -> B/13 -f-bounds-fail.as:63.23-63.25: type error, expression of type +f-bounds-fail.mo:63.23-63.25: type error, expression of type () cannot produce expected type A/22 -> B/13 -f-bounds-fail.as:64.23-64.25: type error, expression of type +f-bounds-fail.mo:64.23-64.25: type error, expression of type () cannot produce expected type B/13 -> B/13 -f-bounds-fail.as:65.23-65.25: type error, expression of type +f-bounds-fail.mo:65.23-65.25: type error, expression of type () cannot produce expected type B/13 -> C/9 -f-bounds-fail.as:66.18-66.19: type error, type argument +f-bounds-fail.mo:66.18-66.19: type error, type argument B/13 does not match parameter bound C/9 -f-bounds-fail.as:66.23-66.25: type error, expression of type +f-bounds-fail.mo:66.23-66.25: type error, expression of type () cannot produce expected type B/13 -> C/9 -f-bounds-fail.as:67.23-67.25: type error, expression of type +f-bounds-fail.mo:67.23-67.25: type error, expression of type () cannot produce expected type C/9 -> C/9 -f-bounds-fail.as:70.27-70.28: type error, expression of type +f-bounds-fail.mo:70.27-70.28: type error, expression of type A/22 cannot produce expected type C/9 -f-bounds-fail.as:71.27-71.28: type error, expression of type +f-bounds-fail.mo:71.27-71.28: type error, expression of type B/13 cannot produce expected type C/9 -f-bounds-fail.as:74.27-74.28: type error, expression of type +f-bounds-fail.mo:74.27-74.28: type error, expression of type A/22 cannot produce expected type C/9 -f-bounds-fail.as:75.27-75.28: type error, expression of type +f-bounds-fail.mo:75.27-75.28: type error, expression of type B/13 cannot produce expected type C/9 -f-bounds-fail.as:77.27-77.28: type error, expression of type +f-bounds-fail.mo:77.27-77.28: type error, expression of type B/13 cannot produce expected type C/9 -f-bounds-fail.as:80.23-80.24: type error, expression of type +f-bounds-fail.mo:80.23-80.24: type error, expression of type A/22 cannot produce expected type C/9 -f-bounds-fail.as:80.25-80.26: type error, expression of type +f-bounds-fail.mo:80.25-80.26: type error, expression of type A/22 cannot produce expected type C/9 -f-bounds-fail.as:80.27-80.28: type error, expression of type +f-bounds-fail.mo:80.27-80.28: type error, expression of type A/22 cannot produce expected type C/9 -f-bounds-fail.as:81.23-81.24: type error, expression of type +f-bounds-fail.mo:81.23-81.24: type error, expression of type A/22 cannot produce expected type C/9 -f-bounds-fail.as:81.25-81.26: type error, expression of type +f-bounds-fail.mo:81.25-81.26: type error, expression of type A/22 cannot produce expected type C/9 -f-bounds-fail.as:81.27-81.28: type error, expression of type +f-bounds-fail.mo:81.27-81.28: type error, expression of type B/13 cannot produce expected type C/9 -f-bounds-fail.as:82.24-82.25: type error, expression of type +f-bounds-fail.mo:82.24-82.25: type error, expression of type A/22 cannot produce expected type C/9 -f-bounds-fail.as:82.26-82.27: type error, expression of type +f-bounds-fail.mo:82.26-82.27: type error, expression of type B/13 cannot produce expected type C/9 diff --git a/test/fail/ok/issue103.tc.ok b/test/fail/ok/issue103.tc.ok index 086b470addf..11bc4be6872 100644 --- a/test/fail/ok/issue103.tc.ok +++ b/test/fail/ok/issue103.tc.ok @@ -1,22 +1,22 @@ -issue103.as:3.29-3.40: type error, shared function has non-shared parameter type +issue103.mo:3.29-3.40: type error, shared function has non-shared parameter type () -> Nat type () -> Nat is or contains non-shared type () -> Nat -issue103.as:10.29-10.46: type error, shared function has non-shared parameter type +issue103.mo:10.29-10.46: type error, shared function has non-shared parameter type {foo : () -> Nat} type {foo : () -> Nat} is or contains non-shared type () -> Nat -issue103.as:17.29-17.40: type error, async has non-shared content type +issue103.mo:17.29-17.40: type error, async has non-shared content type () -> Nat type () -> Nat is or contains non-shared type () -> Nat -issue103.as:24.29-24.48: type error, async has non-shared content type +issue103.mo:24.29-24.48: type error, async has non-shared content type {foo : () -> Nat} type {foo : () -> Nat} diff --git a/test/fail/ok/issue167.tc.ok b/test/fail/ok/issue167.tc.ok index d4f77135651..27928e6ca9f 100644 --- a/test/fail/ok/issue167.tc.ok +++ b/test/fail/ok/issue167.tc.ok @@ -1 +1 @@ -issue167.as:1.13-1.19: type error, too many type arguments +issue167.mo:1.13-1.19: type error, too many type arguments diff --git a/test/fail/ok/modexp1.tc.ok b/test/fail/ok/modexp1.tc.ok index 0aff7395238..86824cab313 100644 --- a/test/fail/ok/modexp1.tc.ok +++ b/test/fail/ok/modexp1.tc.ok @@ -1,2 +1,2 @@ -modexp1.as:8.13-8.14: type error, field g does not exist in type +modexp1.mo:8.13-8.14: type error, field g does not exist in type module {f : () -> ()} diff --git a/test/fail/ok/modexp2.tc.ok b/test/fail/ok/modexp2.tc.ok index 83c854e1664..c36ba16ab97 100644 --- a/test/fail/ok/modexp2.tc.ok +++ b/test/fail/ok/modexp2.tc.ok @@ -1,2 +1,2 @@ -modexp2.as:11.16-11.17: type error, type field U does not exist in type +modexp2.mo:11.16-11.17: type error, type field U does not exist in type module {type T = Int} diff --git a/test/fail/ok/modexp3.tc.ok b/test/fail/ok/modexp3.tc.ok index 512e759c4fe..2b37e312262 100644 --- a/test/fail/ok/modexp3.tc.ok +++ b/test/fail/ok/modexp3.tc.ok @@ -1,2 +1,2 @@ -modexp3.as:1.1-7.2: type error, local class type U is contained in object or actor type +modexp3.mo:1.1-7.2: type error, local class type U is contained in object or actor type module {type T = U} diff --git a/test/fail/ok/modexp4.tc.ok b/test/fail/ok/modexp4.tc.ok index 374834a0910..dc7f20d07ac 100644 --- a/test/fail/ok/modexp4.tc.ok +++ b/test/fail/ok/modexp4.tc.ok @@ -1,2 +1,2 @@ -modexp4.as:2.1-10.2: type error, local class type U is contained in object or actor type +modexp4.mo:2.1-10.2: type error, local class type U is contained in object or actor type module {type T = U} diff --git a/test/fail/ok/modexp5.tc.ok b/test/fail/ok/modexp5.tc.ok index ec7093950fd..ec638653931 100644 --- a/test/fail/ok/modexp5.tc.ok +++ b/test/fail/ok/modexp5.tc.ok @@ -1 +1 @@ -modexp5.as:6.20-6.30: type error, type definition U = T/17 references type parameter(s) T/17 from an outer scope +modexp5.mo:6.20-6.30: type error, type definition U = T/17 references type parameter(s) T/17 from an outer scope diff --git a/test/fail/ok/modules-fwd.tc.ok b/test/fail/ok/modules-fwd.tc.ok index 862b1878667..c653a0a2c7b 100644 --- a/test/fail/ok/modules-fwd.tc.ok +++ b/test/fail/ok/modules-fwd.tc.ok @@ -1,2 +1,2 @@ -modules-fwd.as:5.9-5.10: type error, field v does not exist in type +modules-fwd.mo:5.9-5.10: type error, field v does not exist in type module {type T = ()} diff --git a/test/fail/ok/modules-shadow.tc.ok b/test/fail/ok/modules-shadow.tc.ok index 105da5eb07c..e77790098f2 100644 --- a/test/fail/ok/modules-shadow.tc.ok +++ b/test/fail/ok/modules-shadow.tc.ok @@ -1 +1 @@ -modules-shadow.as:5.12-5.13: type error, cannot infer type of forward variable reference X +modules-shadow.mo:5.12-5.13: type error, cannot infer type of forward variable reference X diff --git a/test/fail/ok/nested-class-rec-fail.tc.ok b/test/fail/ok/nested-class-rec-fail.tc.ok index 1471fa653f8..50c1e46f9a1 100644 --- a/test/fail/ok/nested-class-rec-fail.tc.ok +++ b/test/fail/ok/nested-class-rec-fail.tc.ok @@ -1 +1 @@ -nested-class-rec-fail.as:7.13-7.16: type error, cannot infer type of forward variable Foo +nested-class-rec-fail.mo:7.13-7.16: type error, cannot infer type of forward variable Foo diff --git a/test/fail/ok/non_static_module.tc.ok b/test/fail/ok/non_static_module.tc.ok index 76eda2b076b..790c0bd9fa9 100644 --- a/test/fail/ok/non_static_module.tc.ok +++ b/test/fail/ok/non_static_module.tc.ok @@ -1 +1 @@ -non_static_module.as:3.11-3.14: type error, non-static expression in library or module +non_static_module.mo:3.11-3.14: type error, non-static expression in library or module diff --git a/test/fail/ok/nonlinear-pat.tc.ok b/test/fail/ok/nonlinear-pat.tc.ok index 437888dae5b..764c801e35a 100644 --- a/test/fail/ok/nonlinear-pat.tc.ok +++ b/test/fail/ok/nonlinear-pat.tc.ok @@ -1 +1 @@ -nonlinear-pat.as:1.11-1.12: type error, duplicate definition for x in block +nonlinear-pat.mo:1.11-1.12: type error, duplicate definition for x in block diff --git a/test/fail/ok/not-static.tc.ok b/test/fail/ok/not-static.tc.ok index 8fbc3f7692e..71bab0557a2 100644 --- a/test/fail/ok/not-static.tc.ok +++ b/test/fail/ok/not-static.tc.ok @@ -1 +1 @@ -not-static.as:1.1-1.36: type error, non-static expression in library or module +not-static.mo:1.1-1.36: type error, non-static expression in library or module diff --git a/test/fail/ok/object-patterns.tc.ok b/test/fail/ok/object-patterns.tc.ok index 9ae9b148c88..16a592d7510 100644 --- a/test/fail/ok/object-patterns.tc.ok +++ b/test/fail/ok/object-patterns.tc.ok @@ -1,8 +1,8 @@ -object-patterns.as:6.13-6.21: type error, pattern of type +object-patterns.mo:6.13-6.21: type error, pattern of type Nat cannot consume expected type Int -object-patterns.as:17.9-17.16: type error, pattern of type +object-patterns.mo:17.9-17.16: type error, pattern of type Nat cannot consume expected type Int diff --git a/test/fail/ok/objpat-duplicate.tc.ok b/test/fail/ok/objpat-duplicate.tc.ok index 1a6f85ce453..5e1a08ddeae 100644 --- a/test/fail/ok/objpat-duplicate.tc.ok +++ b/test/fail/ok/objpat-duplicate.tc.ok @@ -1,2 +1,2 @@ -objpat-duplicate.as:4.19-4.20: type error, duplicate field a in object pattern -objpat-duplicate.as:8.8-8.18: type error, duplicate binding for a in pattern +objpat-duplicate.mo:4.19-4.20: type error, duplicate field a in object pattern +objpat-duplicate.mo:8.8-8.18: type error, duplicate binding for a in pattern diff --git a/test/fail/ok/objpat-infer.tc.ok b/test/fail/ok/objpat-infer.tc.ok index 4fd06cec2b0..bea0e0d5256 100644 --- a/test/fail/ok/objpat-infer.tc.ok +++ b/test/fail/ok/objpat-infer.tc.ok @@ -1,22 +1,22 @@ -objpat-infer.as:3.36-3.37: type error, object field a is not contained in expected type +objpat-infer.mo:3.36-3.37: type error, object field a is not contained in expected type {} -objpat-infer.as:21.13-21.21: type error, expression of type +objpat-infer.mo:21.13-21.21: type error, expression of type actor {} cannot produce expected type {} -objpat-infer.as:24.13-24.14: type error, expression of type +objpat-infer.mo:24.13-24.14: type error, expression of type actor {bar : shared {} -> async Nat} cannot produce expected type {} -objpat-infer.as:27.13-27.15: type error, expression of type +objpat-infer.mo:27.13-27.15: type error, expression of type {} cannot produce expected type actor {} -objpat-infer.as:28.13-28.22: type error, expression of type +objpat-infer.mo:28.13-28.22: type error, expression of type {} cannot produce expected type actor {} -objpat-infer.as:33.15-33.23: type error, expression of type +objpat-infer.mo:33.15-33.23: type error, expression of type actor {} cannot produce expected type {} diff --git a/test/fail/ok/objpat-mutable.tc.ok b/test/fail/ok/objpat-mutable.tc.ok index 156c10c52f3..93b9f497d6d 100644 --- a/test/fail/ok/objpat-mutable.tc.ok +++ b/test/fail/ok/objpat-mutable.tc.ok @@ -1 +1 @@ -objpat-mutable.as:8.12-8.13: type error, cannot pattern match mutable field x +objpat-mutable.mo:8.12-8.13: type error, cannot pattern match mutable field x diff --git a/test/fail/ok/one-tuple-ambiguity.tc.ok b/test/fail/ok/one-tuple-ambiguity.tc.ok index a595b7f4473..e1dd4e0be87 100644 --- a/test/fail/ok/one-tuple-ambiguity.tc.ok +++ b/test/fail/ok/one-tuple-ambiguity.tc.ok @@ -1,4 +1,4 @@ -one-tuple-ambiguity.as:16.3-16.5: type error, literal of type +one-tuple-ambiguity.mo:16.3-16.5: type error, literal of type Nat does not have expected type (Nat, Bool) diff --git a/test/fail/ok/pat-inconsistent.tc.ok b/test/fail/ok/pat-inconsistent.tc.ok index 754f7b10e7d..4873d5c267b 100644 --- a/test/fail/ok/pat-inconsistent.tc.ok +++ b/test/fail/ok/pat-inconsistent.tc.ok @@ -1,134 +1,134 @@ -pat-inconsistent.as:6.31-6.44: warning, this pattern is never matched -pat-inconsistent.as:7.34-7.50: warning, this pattern is never matched -pat-inconsistent.as:9.20-9.22: warning, this pattern is never matched -pat-inconsistent.as:10.20-10.24: warning, this pattern is never matched -pat-inconsistent.as:11.20-11.30: warning, this pattern is never matched -pat-inconsistent.as:2.13-2.21: warning, this pattern consuming type +pat-inconsistent.mo:6.31-6.44: warning, this pattern is never matched +pat-inconsistent.mo:7.34-7.50: warning, this pattern is never matched +pat-inconsistent.mo:9.20-9.22: warning, this pattern is never matched +pat-inconsistent.mo:10.20-10.24: warning, this pattern is never matched +pat-inconsistent.mo:11.20-11.30: warning, this pattern is never matched +pat-inconsistent.mo:2.13-2.21: warning, this pattern consuming type Nat does not cover value 0 or 3 or _ -pat-inconsistent.as:3.13-3.22: warning, this pattern consuming type +pat-inconsistent.mo:3.13-3.22: warning, this pattern consuming type Int does not cover value 0 or 2 or _ -pat-inconsistent.as:5.13-5.29: warning, this pattern consuming type +pat-inconsistent.mo:5.13-5.29: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -pat-inconsistent.as:8.13-8.33: warning, this pattern consuming type +pat-inconsistent.mo:8.13-8.33: warning, this pattern consuming type (Int, Int) does not cover value (-1, 0 or 1 or _) or (2, 0 or 1 or _) or (0 or 1 or _, _) -pat-inconsistent.as:16.16-16.24: type error, pattern branches have incompatible types, +pat-inconsistent.mo:16.16-16.24: type error, pattern branches have incompatible types, left consumes Nat right consumes Float -pat-inconsistent.as:17.16-17.23: type error, pattern branches have incompatible types, +pat-inconsistent.mo:17.16-17.23: type error, pattern branches have incompatible types, left consumes Nat right consumes Text -pat-inconsistent.as:18.16-18.26: type error, pattern branches have incompatible types, +pat-inconsistent.mo:18.16-18.26: type error, pattern branches have incompatible types, left consumes Bool right consumes Text -pat-inconsistent.as:19.16-19.23: type error, pattern branches have incompatible types, +pat-inconsistent.mo:19.16-19.23: type error, pattern branches have incompatible types, left consumes Nat right consumes () -pat-inconsistent.as:20.16-20.23: type error, pattern branches have incompatible types, +pat-inconsistent.mo:20.16-20.23: type error, pattern branches have incompatible types, left consumes Nat right consumes {} -pat-inconsistent.as:21.16-21.31: type error, pattern branches have incompatible types, +pat-inconsistent.mo:21.16-21.31: type error, pattern branches have incompatible types, left consumes Nat right consumes Text -pat-inconsistent.as:22.16-22.46: type error, pattern branches have incompatible types, +pat-inconsistent.mo:22.16-22.46: type error, pattern branches have incompatible types, left consumes {a : Int} right consumes {b : Nat} -pat-inconsistent.as:23.16-23.40: type error, pattern branches have incompatible types, +pat-inconsistent.mo:23.16-23.40: type error, pattern branches have incompatible types, left consumes Int8 right consumes Nat8 -pat-inconsistent.as:24.16-24.36: type error, pattern branches have incompatible types, +pat-inconsistent.mo:24.16-24.36: type error, pattern branches have incompatible types, left consumes (Text, Nat) right consumes (Text, Float) -pat-inconsistent.as:25.16-25.50: type error, pattern branches have incompatible types, +pat-inconsistent.mo:25.16-25.50: type error, pattern branches have incompatible types, left consumes (Int16, Text) right consumes (Nat16, Text) -pat-inconsistent.as:26.16-26.28: type error, pattern branches have incompatible types, +pat-inconsistent.mo:26.16-26.28: type error, pattern branches have incompatible types, left consumes {#A} right consumes {#A : Text} -pat-inconsistent.as:27.16-27.31: type error, pattern branches have incompatible types, +pat-inconsistent.mo:27.16-27.31: type error, pattern branches have incompatible types, left consumes {#A : Nat} right consumes {#A : Text} -pat-inconsistent.as:29.16-29.30: type error, pattern branches have incompatible types, +pat-inconsistent.mo:29.16-29.30: type error, pattern branches have incompatible types, left consumes Nat right consumes Any -pat-inconsistent.as:30.16-30.32: type error, pattern branches have incompatible types, +pat-inconsistent.mo:30.16-30.32: type error, pattern branches have incompatible types, left consumes Any right consumes Float -pat-inconsistent.as:31.16-31.31: type error, pattern branches have incompatible types, +pat-inconsistent.mo:31.16-31.31: type error, pattern branches have incompatible types, left consumes () right consumes Any -pat-inconsistent.as:32.19-32.32: type error, pattern branches have incompatible types, +pat-inconsistent.mo:32.19-32.32: type error, pattern branches have incompatible types, left consumes Text right consumes A/9 -pat-inconsistent.as:33.16-33.40: type error, pattern branches have incompatible types, +pat-inconsistent.mo:33.16-33.40: type error, pattern branches have incompatible types, left consumes Any right consumes [Nat] -pat-inconsistent.as:34.16-34.43: type error, pattern branches have incompatible types, +pat-inconsistent.mo:34.16-34.43: type error, pattern branches have incompatible types, left consumes Any right consumes () -> () -pat-inconsistent.as:35.16-35.40: type error, pattern branches have incompatible types, +pat-inconsistent.mo:35.16-35.40: type error, pattern branches have incompatible types, left consumes (Text, Nat) right consumes (Text, Any) -pat-inconsistent.as:36.16-36.33: type error, pattern branches have incompatible types, +pat-inconsistent.mo:36.16-36.33: type error, pattern branches have incompatible types, left consumes {#A} right consumes {#A : Any} -pat-inconsistent.as:37.16-37.36: type error, pattern branches have incompatible types, +pat-inconsistent.mo:37.16-37.36: type error, pattern branches have incompatible types, left consumes {#A : Nat} right consumes {#A : Any} -pat-inconsistent.as:42.9-42.11: type error, variant pattern cannot consume expected type +pat-inconsistent.mo:42.9-42.11: type error, variant pattern cannot consume expected type {#A} -pat-inconsistent.as:49.8-49.9: type error, literal of type +pat-inconsistent.mo:49.8-49.9: type error, literal of type Nat does not have expected type Bool diff --git a/test/fail/ok/pat-subtyping-fail.tc.ok b/test/fail/ok/pat-subtyping-fail.tc.ok index 53da2a8563c..085534d99b1 100644 --- a/test/fail/ok/pat-subtyping-fail.tc.ok +++ b/test/fail/ok/pat-subtyping-fail.tc.ok @@ -1,118 +1,118 @@ -pat-subtyping-fail.as:123.3-123.15: warning, this case is never reached -pat-subtyping-fail.as:124.3-124.12: warning, this case is never reached -pat-subtyping-fail.as:4.9-4.11: type error, literal of type +pat-subtyping-fail.mo:123.3-123.15: warning, this case is never reached +pat-subtyping-fail.mo:124.3-124.12: warning, this case is never reached +pat-subtyping-fail.mo:4.9-4.11: type error, literal of type Int does not have expected type Nat -pat-subtyping-fail.as:8.9-8.11: type error, literal of type +pat-subtyping-fail.mo:8.9-8.11: type error, literal of type Int does not have expected type Nat -pat-subtyping-fail.as:13.13-13.15: type error, literal of type +pat-subtyping-fail.mo:13.13-13.15: type error, literal of type Int does not have expected type Nat -pat-subtyping-fail.as:17.18-17.20: type error, literal of type +pat-subtyping-fail.mo:17.18-17.20: type error, literal of type Int does not have expected type Nat -pat-subtyping-fail.as:22.21-22.23: type error, literal of type +pat-subtyping-fail.mo:22.21-22.23: type error, literal of type Int does not have expected type Nat -pat-subtyping-fail.as:26.26-26.28: type error, literal of type +pat-subtyping-fail.mo:26.26-26.28: type error, literal of type Int does not have expected type Nat -pat-subtyping-fail.as:31.11-31.13: type error, literal of type +pat-subtyping-fail.mo:31.11-31.13: type error, literal of type Int does not have expected type Nat -pat-subtyping-fail.as:35.11-35.13: type error, literal of type +pat-subtyping-fail.mo:35.11-35.13: type error, literal of type Int does not have expected type Nat -pat-subtyping-fail.as:39.11-39.13: type error, literal of type +pat-subtyping-fail.mo:39.11-39.13: type error, literal of type Int does not have expected type Nat -pat-subtyping-fail.as:44.12-44.14: type error, literal of type +pat-subtyping-fail.mo:44.12-44.14: type error, literal of type Int does not have expected type Nat -pat-subtyping-fail.as:48.12-48.14: type error, literal of type +pat-subtyping-fail.mo:48.12-48.14: type error, literal of type Int does not have expected type Nat -pat-subtyping-fail.as:52.12-52.14: type error, literal of type +pat-subtyping-fail.mo:52.12-52.14: type error, literal of type Int does not have expected type Nat -pat-subtyping-fail.as:57.9-57.16: type error, pattern of type +pat-subtyping-fail.mo:57.9-57.16: type error, pattern of type Nat cannot consume expected type Int -pat-subtyping-fail.as:61.9-61.23: type error, pattern of type +pat-subtyping-fail.mo:61.9-61.23: type error, pattern of type (Nat, Nat) cannot consume expected type (Int, Int) -pat-subtyping-fail.as:64.9-64.28: type error, pattern of type +pat-subtyping-fail.mo:64.9-64.28: type error, pattern of type (Nat, Nat) cannot consume expected type (Int, Int) -pat-subtyping-fail.as:67.9-67.16: type error, pattern of type +pat-subtyping-fail.mo:67.9-67.16: type error, pattern of type Nat cannot consume expected type Int -pat-subtyping-fail.as:71.9-71.31: type error, pattern of type +pat-subtyping-fail.mo:71.9-71.31: type error, pattern of type {a : Nat; b : Nat} cannot consume expected type {a : Int; b : Int} -pat-subtyping-fail.as:74.9-74.36: type error, pattern of type +pat-subtyping-fail.mo:74.9-74.36: type error, pattern of type {a : Nat; b : Nat} cannot consume expected type {a : Int; b : Int} -pat-subtyping-fail.as:77.13-77.20: type error, pattern of type +pat-subtyping-fail.mo:77.13-77.20: type error, pattern of type Nat cannot consume expected type Int -pat-subtyping-fail.as:80.9-80.31: type error, pattern of type +pat-subtyping-fail.mo:80.9-80.31: type error, pattern of type {a : Nat; b : Nat} cannot consume expected type {a : Nat} -pat-subtyping-fail.as:83.9-83.36: type error, pattern of type +pat-subtyping-fail.mo:83.9-83.36: type error, pattern of type {a : Nat; b : Nat} cannot consume expected type {a : Nat} -pat-subtyping-fail.as:86.9-86.31: type error, pattern of type +pat-subtyping-fail.mo:86.9-86.31: type error, pattern of type {a : Nat; b : Nat} cannot consume expected type {} -pat-subtyping-fail.as:89.9-89.36: type error, pattern of type +pat-subtyping-fail.mo:89.9-89.36: type error, pattern of type {a : Nat; b : Nat} cannot consume expected type {} -pat-subtyping-fail.as:94.9-94.12: type error, option pattern cannot consume expected type +pat-subtyping-fail.mo:94.9-94.12: type error, option pattern cannot consume expected type Null -pat-subtyping-fail.as:97.9-97.20: type error, pattern of type +pat-subtyping-fail.mo:97.9-97.20: type error, pattern of type Null cannot consume expected type ?Nat -pat-subtyping-fail.as:101.9-101.18: type error, pattern of type +pat-subtyping-fail.mo:101.9-101.18: type error, pattern of type ?Nat cannot consume expected type ?Int -pat-subtyping-fail.as:105.11-105.18: type error, pattern of type +pat-subtyping-fail.mo:105.11-105.18: type error, pattern of type Nat cannot consume expected type Int -pat-subtyping-fail.as:110.9-110.13: type error, variant pattern cannot consume expected type +pat-subtyping-fail.mo:110.9-110.13: type error, variant pattern cannot consume expected type {#} -pat-subtyping-fail.as:113.9-113.26: type error, pattern of type +pat-subtyping-fail.mo:113.9-113.26: type error, pattern of type {#A : Nat} cannot consume expected type {#A : Nat; #B} -pat-subtyping-fail.as:117.9-117.18: type error, pattern of type +pat-subtyping-fail.mo:117.9-117.18: type error, pattern of type {#B} cannot consume expected type {#A : Nat; #B} diff --git a/test/fail/ok/prim-in-source.tc.ok b/test/fail/ok/prim-in-source.tc.ok index 186587781a1..1fe6746f452 100644 --- a/test/fail/ok/prim-in-source.tc.ok +++ b/test/fail/ok/prim-in-source.tc.ok @@ -1 +1 @@ -prim-in-source.as:1.22-1.26: type error, unbound variable prim +prim-in-source.mo:1.22-1.26: type error, unbound variable prim diff --git a/test/fail/ok/return-before-define.tc.ok b/test/fail/ok/return-before-define.tc.ok index 8163fadae2c..fd459cd7fd6 100644 --- a/test/fail/ok/return-before-define.tc.ok +++ b/test/fail/ok/return-before-define.tc.ok @@ -1 +1 @@ -return-before-define.as:3.5-3.34: definedness error, cannot use g before x has been defined +return-before-define.mo:3.5-3.34: definedness error, cannot use g before x has been defined diff --git a/test/fail/ok/self-import.tc.ok b/test/fail/ok/self-import.tc.ok index 3ee8ccd9faf..7d8d8da903a 100644 --- a/test/fail/ok/self-import.tc.ok +++ b/test/fail/ok/self-import.tc.ok @@ -1 +1 @@ -(unknown location): import error, file self-import.as must not depend on itself +(unknown location): import error, file self-import.mo must not depend on itself diff --git a/test/fail/ok/switch-type.tc.ok b/test/fail/ok/switch-type.tc.ok index 4707fa56300..0942c85758a 100644 --- a/test/fail/ok/switch-type.tc.ok +++ b/test/fail/ok/switch-type.tc.ok @@ -1,4 +1,4 @@ -switch-type.as:1.29-1.36: type error, pattern of type +switch-type.mo:1.29-1.36: type error, pattern of type Nat cannot consume expected type Int diff --git a/test/fail/ok/text-high-surrogate.tc.ok b/test/fail/ok/text-high-surrogate.tc.ok index 18a9b5e868e..578b3d301f1 100644 --- a/test/fail/ok/text-high-surrogate.tc.ok +++ b/test/fail/ok/text-high-surrogate.tc.ok @@ -1 +1 @@ -text-high-surrogate.as:1.9-1.19: syntax error, unicode escape out of range +text-high-surrogate.mo:1.9-1.19: syntax error, unicode escape out of range diff --git a/test/fail/ok/text-low-surrogate.tc.ok b/test/fail/ok/text-low-surrogate.tc.ok index 6ba634e6205..ee396c82c5a 100644 --- a/test/fail/ok/text-low-surrogate.tc.ok +++ b/test/fail/ok/text-low-surrogate.tc.ok @@ -1 +1 @@ -text-low-surrogate.as:1.9-1.19: syntax error, unicode escape out of range +text-low-surrogate.mo:1.9-1.19: syntax error, unicode escape out of range diff --git a/test/fail/ok/typ-field-lub-glb-fail.tc.ok b/test/fail/ok/typ-field-lub-glb-fail.tc.ok index 7a8d1ad52ed..6fa62fe9b5a 100644 --- a/test/fail/ok/typ-field-lub-glb-fail.tc.ok +++ b/test/fail/ok/typ-field-lub-glb-fail.tc.ok @@ -1,12 +1,12 @@ -typ-field-lub-glb-fail.as:14.31-14.35: type error, expression of type +typ-field-lub-glb-fail.mo:14.31-14.35: type error, expression of type Cx = {x : Nat} cannot produce expected type {type T = Int; x : Nat} -typ-field-lub-glb-fail.as:15.31-15.35: type error, expression of type +typ-field-lub-glb-fail.mo:15.31-15.35: type error, expression of type Ct = {type T = Int} cannot produce expected type {type T = Int; x : Nat} -typ-field-lub-glb-fail.as:21.29-21.30: type error, type field T does not exist in type +typ-field-lub-glb-fail.mo:21.29-21.30: type error, type field T does not exist in type {x : Nat} -typ-field-lub-glb-fail.as:27.29-27.30: type error, type field T does not exist in type +typ-field-lub-glb-fail.mo:27.29-27.30: type error, type field T does not exist in type {x : Nat} diff --git a/test/fail/ok/use-before-define.tc.ok b/test/fail/ok/use-before-define.tc.ok index 97b714bd0c2..d8cb5f5f0ca 100644 --- a/test/fail/ok/use-before-define.tc.ok +++ b/test/fail/ok/use-before-define.tc.ok @@ -1 +1 @@ -use-before-define.as:2.1-2.12: definedness error, cannot use f before x has been defined +use-before-define.mo:2.1-2.12: definedness error, cannot use f before x has been defined diff --git a/test/fail/ok/use-before-define2.tc.ok b/test/fail/ok/use-before-define2.tc.ok index 3fc8aa9ab35..979919ddd85 100644 --- a/test/fail/ok/use-before-define2.tc.ok +++ b/test/fail/ok/use-before-define2.tc.ok @@ -1 +1 @@ -use-before-define2.as:5.1-5.43: definedness error, cannot use x before x has been defined +use-before-define2.mo:5.1-5.43: definedness error, cannot use x before x has been defined diff --git a/test/fail/ok/use-before-define4.tc.ok b/test/fail/ok/use-before-define4.tc.ok index 0a19ec22571..39ac04145ad 100644 --- a/test/fail/ok/use-before-define4.tc.ok +++ b/test/fail/ok/use-before-define4.tc.ok @@ -1 +1 @@ -use-before-define4.as:3.1-3.17: definedness error, cannot use f before x has been defined +use-before-define4.mo:3.1-3.17: definedness error, cannot use f before x has been defined diff --git a/test/fail/ok/use-before-define6.tc.ok b/test/fail/ok/use-before-define6.tc.ok index bba698b0347..e7ea0dca92c 100644 --- a/test/fail/ok/use-before-define6.tc.ok +++ b/test/fail/ok/use-before-define6.tc.ok @@ -1 +1 @@ -use-before-define6.as:6.3-6.20: definedness error, cannot use g before g has been defined +use-before-define6.mo:6.3-6.20: definedness error, cannot use g before g has been defined diff --git a/test/fail/ok/var-const-array.tc.ok b/test/fail/ok/var-const-array.tc.ok index 79453817fc9..338636100d9 100644 --- a/test/fail/ok/var-const-array.tc.ok +++ b/test/fail/ok/var-const-array.tc.ok @@ -1,2 +1,2 @@ -var-const-array.as:1.21-1.23: type error, immutable array expression cannot produce expected type +var-const-array.mo:1.21-1.23: type error, immutable array expression cannot produce expected type [var Nat] diff --git a/test/fail/ok/var-const-field.tc.ok b/test/fail/ok/var-const-field.tc.ok index 34fa404da7c..71da89e4e4e 100644 --- a/test/fail/ok/var-const-field.tc.ok +++ b/test/fail/ok/var-const-field.tc.ok @@ -1,4 +1,4 @@ -var-const-field.as:1.25-1.32: type error, expression of type +var-const-field.mo:1.25-1.32: type error, expression of type {x : Nat} cannot produce expected type {var x : Nat} diff --git a/test/fail/ok/word-range.tc.ok b/test/fail/ok/word-range.tc.ok index cd5a6292265..9b56291e4b6 100644 --- a/test/fail/ok/word-range.tc.ok +++ b/test/fail/ok/word-range.tc.ok @@ -1,24 +1,24 @@ -word-range.as:31.17-31.20: type error, literal out of range for type Word8 -word-range.as:32.17-32.22: type error, literal out of range for type Word8 -word-range.as:33.17-33.21: type error, literal out of range for type Word8 -word-range.as:34.17-34.23: type error, literal out of range for type Word8 -word-range.as:35.17-35.21: type error, literal out of range for type Word8 -word-range.as:36.17-36.22: type error, literal out of range for type Word8 -word-range.as:37.18-37.23: type error, literal out of range for type Word16 -word-range.as:38.18-38.25: type error, literal out of range for type Word16 -word-range.as:39.18-39.24: type error, literal out of range for type Word16 -word-range.as:40.18-40.26: type error, literal out of range for type Word16 -word-range.as:41.18-41.24: type error, literal out of range for type Word16 -word-range.as:42.18-42.25: type error, literal out of range for type Word16 -word-range.as:43.18-43.28: type error, literal out of range for type Word32 -word-range.as:44.18-44.29: type error, literal out of range for type Word32 -word-range.as:45.18-45.29: type error, literal out of range for type Word32 -word-range.as:46.18-46.30: type error, literal out of range for type Word32 -word-range.as:47.18-47.29: type error, literal out of range for type Word32 -word-range.as:48.18-48.29: type error, literal out of range for type Word32 -word-range.as:49.18-49.44: type error, literal out of range for type Word64 -word-range.as:50.18-50.37: type error, literal out of range for type Word64 -word-range.as:51.18-51.45: type error, literal out of range for type Word64 -word-range.as:52.18-52.38: type error, literal out of range for type Word64 -word-range.as:53.18-53.44: type error, literal out of range for type Word64 -word-range.as:54.18-54.37: type error, literal out of range for type Word64 +word-range.mo:31.17-31.20: type error, literal out of range for type Word8 +word-range.mo:32.17-32.22: type error, literal out of range for type Word8 +word-range.mo:33.17-33.21: type error, literal out of range for type Word8 +word-range.mo:34.17-34.23: type error, literal out of range for type Word8 +word-range.mo:35.17-35.21: type error, literal out of range for type Word8 +word-range.mo:36.17-36.22: type error, literal out of range for type Word8 +word-range.mo:37.18-37.23: type error, literal out of range for type Word16 +word-range.mo:38.18-38.25: type error, literal out of range for type Word16 +word-range.mo:39.18-39.24: type error, literal out of range for type Word16 +word-range.mo:40.18-40.26: type error, literal out of range for type Word16 +word-range.mo:41.18-41.24: type error, literal out of range for type Word16 +word-range.mo:42.18-42.25: type error, literal out of range for type Word16 +word-range.mo:43.18-43.28: type error, literal out of range for type Word32 +word-range.mo:44.18-44.29: type error, literal out of range for type Word32 +word-range.mo:45.18-45.29: type error, literal out of range for type Word32 +word-range.mo:46.18-46.30: type error, literal out of range for type Word32 +word-range.mo:47.18-47.29: type error, literal out of range for type Word32 +word-range.mo:48.18-48.29: type error, literal out of range for type Word32 +word-range.mo:49.18-49.44: type error, literal out of range for type Word64 +word-range.mo:50.18-50.37: type error, literal out of range for type Word64 +word-range.mo:51.18-51.45: type error, literal out of range for type Word64 +word-range.mo:52.18-52.38: type error, literal out of range for type Word64 +word-range.mo:53.18-53.44: type error, literal out of range for type Word64 +word-range.mo:54.18-54.37: type error, literal out of range for type Word64 diff --git a/test/fail/one-tuple-ambiguity.as b/test/fail/one-tuple-ambiguity.mo similarity index 100% rename from test/fail/one-tuple-ambiguity.as rename to test/fail/one-tuple-ambiguity.mo diff --git a/test/fail/pat-inconsistent.as b/test/fail/pat-inconsistent.mo similarity index 100% rename from test/fail/pat-inconsistent.as rename to test/fail/pat-inconsistent.mo diff --git a/test/fail/pat-subtyping-fail.as b/test/fail/pat-subtyping-fail.mo similarity index 100% rename from test/fail/pat-subtyping-fail.as rename to test/fail/pat-subtyping-fail.mo diff --git a/test/fail/prim-in-source.as b/test/fail/prim-in-source.mo similarity index 100% rename from test/fail/prim-in-source.as rename to test/fail/prim-in-source.mo diff --git a/test/fail/return-before-define.as b/test/fail/return-before-define.mo similarity index 100% rename from test/fail/return-before-define.as rename to test/fail/return-before-define.mo diff --git a/test/fail/self-import.as b/test/fail/self-import.as deleted file mode 100644 index 40cc17ca387..00000000000 --- a/test/fail/self-import.as +++ /dev/null @@ -1 +0,0 @@ -import "self-import.as"; diff --git a/test/fail/self-import.mo b/test/fail/self-import.mo new file mode 100644 index 00000000000..2dbe7b954c5 --- /dev/null +++ b/test/fail/self-import.mo @@ -0,0 +1 @@ +import "self-import.mo"; diff --git a/test/fail/switch-type.as b/test/fail/switch-type.mo similarity index 100% rename from test/fail/switch-type.as rename to test/fail/switch-type.mo diff --git a/test/fail/text-high-surrogate.as b/test/fail/text-high-surrogate.mo similarity index 100% rename from test/fail/text-high-surrogate.as rename to test/fail/text-high-surrogate.mo diff --git a/test/fail/text-low-surrogate.as b/test/fail/text-low-surrogate.mo similarity index 100% rename from test/fail/text-low-surrogate.as rename to test/fail/text-low-surrogate.mo diff --git a/test/fail/typ-field-lub-glb-fail.as b/test/fail/typ-field-lub-glb-fail.mo similarity index 100% rename from test/fail/typ-field-lub-glb-fail.as rename to test/fail/typ-field-lub-glb-fail.mo diff --git a/test/fail/use-before-define.as b/test/fail/use-before-define.mo similarity index 100% rename from test/fail/use-before-define.as rename to test/fail/use-before-define.mo diff --git a/test/fail/use-before-define2.as b/test/fail/use-before-define2.mo similarity index 100% rename from test/fail/use-before-define2.as rename to test/fail/use-before-define2.mo diff --git a/test/fail/use-before-define4.as b/test/fail/use-before-define4.mo similarity index 100% rename from test/fail/use-before-define4.as rename to test/fail/use-before-define4.mo diff --git a/test/fail/use-before-define5.as b/test/fail/use-before-define5.mo similarity index 100% rename from test/fail/use-before-define5.as rename to test/fail/use-before-define5.mo diff --git a/test/fail/use-before-define6.as b/test/fail/use-before-define6.mo similarity index 100% rename from test/fail/use-before-define6.as rename to test/fail/use-before-define6.mo diff --git a/test/fail/var-const-array.as b/test/fail/var-const-array.mo similarity index 100% rename from test/fail/var-const-array.as rename to test/fail/var-const-array.mo diff --git a/test/fail/var-const-field.as b/test/fail/var-const-field.mo similarity index 100% rename from test/fail/var-const-field.as rename to test/fail/var-const-field.mo diff --git a/test/fail/word-range.as b/test/fail/word-range.mo similarity index 100% rename from test/fail/word-range.as rename to test/fail/word-range.mo diff --git a/test/ld/Makefile b/test/ld/Makefile index 85b81f47d6f..5e37ac34bf6 100644 --- a/test/ld/Makefile +++ b/test/ld/Makefile @@ -11,7 +11,7 @@ clean: WASM_CLANG?=clang-9 WASM_LD?=wasm-ld-9 -AS_LD?=../../src/as-ld +MO_LD?=../../src/mo-ld _out/%.lib.o: %.c | _out $(WASM_CLANG) --compile -fpic --std=c11 --target=wasm32-unknown-unknown-wasm -fvisibility=hidden --optimize=3 \ @@ -27,7 +27,7 @@ _out/%.base.wasm: %.wat | _out wat2wasm --debug-names --enable-multi-value $< -o $@ _out/%.linked.wasm: _out/%.base.wasm _out/%.lib.wasm - $(AS_LD) -b _out/$*.base.wasm -l _out/$*.lib.wasm -o _out/$*.linked.wasm + $(MO_LD) -b _out/$*.base.wasm -l _out/$*.lib.wasm -o _out/$*.linked.wasm _out/%.wat: _out/%.wasm wasm2wat --no-check $< -o $@ diff --git a/test/ld/ok/wrong-type.as-ld.ok b/test/ld/ok/wrong-type.mo-ld.ok similarity index 100% rename from test/ld/ok/wrong-type.as-ld.ok rename to test/ld/ok/wrong-type.mo-ld.ok diff --git a/test/lsp-int/Main.hs b/test/lsp-int/Main.hs index 5a0073ddbd6..d39377ffaa6 100644 --- a/test/lsp-int/Main.hs +++ b/test/lsp-int/Main.hs @@ -72,7 +72,7 @@ main = handleHUnitFailure $ do setCurrentDirectory project runSession as_ide fullCaps "." $ do initRes <- initializeResponse - doc <- openDoc "ListClient.as" "actorscript" + doc <- openDoc "ListClient.mo" "motoko" hoverTestCase doc (Position 13 11) @@ -95,7 +95,7 @@ main = handleHUnitFailure $ do (Position 13 14) [("push",Just "(T, List) -> List")] closeDoc doc - doc <- openDoc "ListClient.as" "actorscript" + doc <- openDoc "ListClient.mo" "motoko" -- 1 | module { -- ==> 1 | ule { let edit = TextEdit (Range (Position 0 1) (Position 0 3)) "" @@ -107,10 +107,10 @@ main = handleHUnitFailure $ do -- It finds errors in transitive modules that have been changed in -- the vfs but not yet stored to disc - doc <- openDoc "ListClient.as" "actorscript" + doc <- openDoc "ListClient.mo" "motoko" let edit = TextEdit (Range (Position 0 1) (Position 0 3)) "" _ <- applyEdit doc edit - appDoc <- openDoc "app.as" "actorscript" + appDoc <- openDoc "app.mo" "motoko" sendNotification TextDocumentDidSave (DidSaveTextDocumentParams appDoc) (diagnostic:_) <- waitForDiagnostics liftIO (diagnostic^.message `shouldBe` "unexpected token") diff --git a/test/lsp-int/test-project/ListClient.as b/test/lsp-int/test-project/ListClient.mo similarity index 74% rename from test/lsp-int/test-project/ListClient.as rename to test/lsp-int/test-project/ListClient.mo index ef9046a04ba..a749967a85e 100644 --- a/test/lsp-int/test-project/ListClient.as +++ b/test/lsp-int/test-project/ListClient.mo @@ -1,7 +1,7 @@ module { - import List "lib/list.as"; - import Option "lib/option.as"; - import P "lib/prelude.as"; + import List "lib/list.mo"; + import Option "lib/option.mo"; + import P "lib/prelude.mo"; public type Stack = List.List; diff --git a/test/lsp-int/test-project/app.as b/test/lsp-int/test-project/app.mo similarity index 76% rename from test/lsp-int/test-project/app.as rename to test/lsp-int/test-project/app.mo index 4d087335404..e5e2a89a69b 100644 --- a/test/lsp-int/test-project/app.as +++ b/test/lsp-int/test-project/app.mo @@ -1,6 +1,6 @@ actor { - import Stack "ListClient.as"; + import Stack "ListClient.mo"; func main(): () { let st = Stack.empty(); diff --git a/test/lsp-int/test-project/lib/ListFuncs.as b/test/lsp-int/test-project/lib/ListFuncs.mo similarity index 86% rename from test/lsp-int/test-project/lib/ListFuncs.as rename to test/lsp-int/test-project/lib/ListFuncs.mo index b060d89e2f8..dc430e44e93 100644 --- a/test/lsp-int/test-project/lib/ListFuncs.as +++ b/test/lsp-int/test-project/lib/ListFuncs.mo @@ -1,5 +1,5 @@ module { - import List = "./ListLib.as"; + import List = "./ListLib.mo"; public func singleton(x: T): List.List = List.cons(x, List.nil()); diff --git a/test/lsp-int/test-project/lib/ListLib.as b/test/lsp-int/test-project/lib/ListLib.mo similarity index 100% rename from test/lsp-int/test-project/lib/ListLib.as rename to test/lsp-int/test-project/lib/ListLib.mo diff --git a/test/lsp-int/test-project/lib/list.as b/test/lsp-int/test-project/lib/list.mo similarity index 100% rename from test/lsp-int/test-project/lib/list.as rename to test/lsp-int/test-project/lib/list.mo diff --git a/test/lsp-int/test-project/lib/option.as b/test/lsp-int/test-project/lib/option.mo similarity index 99% rename from test/lsp-int/test-project/lib/option.as rename to test/lsp-int/test-project/lib/option.mo index 58656d06a19..adb2b3d3209 100644 --- a/test/lsp-int/test-project/lib/option.as +++ b/test/lsp-int/test-project/lib/option.mo @@ -5,7 +5,7 @@ Functions for Option types. */ -import P "prelude.as"; +import P "prelude.mo"; public type t = ?A; diff --git a/test/lsp-int/test-project/lib/prelude.as b/test/lsp-int/test-project/lib/prelude.mo similarity index 100% rename from test/lsp-int/test-project/lib/prelude.as rename to test/lsp-int/test-project/lib/prelude.mo diff --git a/test/node-test.js b/test/node-test.js index 55296cfbddc..7b28e4c3e21 100644 --- a/test/node-test.js +++ b/test/node-test.js @@ -2,12 +2,12 @@ process.on('unhandledRejection', error => { assert.fail(error); }); const assert = require('assert').strict; -// Load asc.js -const m = require('asc.js'); +// Load moc.js +const m = require('moc.js'); // Compile the empty module in plain and dfinity mode -const empty_wasm_plain = m.ActorScript.compileWasm('wasm', ''); -const empty_wasm_dfinity = m.ActorScript.compileWasm('dfinity', ''); +const empty_wasm_plain = m.Motoko.compileWasm('wasm', ''); +const empty_wasm_dfinity = m.Motoko.compileWasm('dfinity', ''); // For the plain module... // Check that the code looks like a WebAssembly binary @@ -33,7 +33,7 @@ WebAssembly.compile(Buffer.from(empty_wasm_dfinity.code, 'ascii')); assert.notEqual(empty_wasm_plain.code, empty_wasm_dfinity.code); // Check if error messages are correctly returned -const bad_result = m.ActorScript.compileWasm('dfinity', '1+'); +const bad_result = m.Motoko.compileWasm('dfinity', '1+'); // Uncomment to see what to paste below // console.log(JSON.stringify(bad_result, null, 2)); assert.deepStrictEqual(bad_result, { @@ -50,7 +50,7 @@ assert.deepStrictEqual(bad_result, { } }, "severity": 1, - "source": "actorscript", + "source": "motoko", "message": "unexpected token" } ], @@ -59,12 +59,12 @@ assert.deepStrictEqual(bad_result, { }); // Check the check command (should print errors, but have no code) -assert.deepStrictEqual(m.ActorScript.check('1'), { +assert.deepStrictEqual(m.Motoko.check('1'), { "diagnostics": [], "code": null }); -assert.deepStrictEqual(m.ActorScript.check('1+'), { +assert.deepStrictEqual(m.Motoko.check('1+'), { "diagnostics": [ { "range": { @@ -78,7 +78,7 @@ assert.deepStrictEqual(m.ActorScript.check('1+'), { } }, "severity": 1, - "source": "actorscript", + "source": "motoko", "message": "unexpected token" } ], @@ -86,7 +86,7 @@ assert.deepStrictEqual(m.ActorScript.check('1+'), { }); // Create a source map, and check some of its structure -const with_map = m.ActorScript.compileWasm('dfinity', ''); +const with_map = m.Motoko.compileWasm('dfinity', ''); assert.equal(typeof(with_map.map), 'string') let map assert.doesNotThrow(() => map = JSON.parse(with_map.map), SyntaxError) diff --git a/test/quick.mk b/test/quick.mk index 50ebab5d391..d603610aea0 100644 --- a/test/quick.mk +++ b/test/quick.mk @@ -1,7 +1,7 @@ # Note: this rule collection is included from one level deeper TO-TEST = \ - $(patsubst %.as,_out/%.done,$(wildcard *.as)) \ + $(patsubst %.mo,_out/%.done,$(wildcard *.mo)) \ $(patsubst %.sh,_out/%.done,$(wildcard *.sh)) \ $(patsubst %.wat,_out/%.done,$(wildcard *.wat)) \ $(patsubst %.did,_out/%.done,$(wildcard *.did)) \ @@ -15,11 +15,11 @@ _out: @ mkdir -p $@ # run single test, e.g. make _out/AST-56.done -_out/%.done: %.as $(wildcard ../../src/asc) ../run.sh | _out +_out/%.done: %.mo $(wildcard ../../src/moc) ../run.sh | _out @+ (../run.sh $(RUNFLAGS) $< > $@.tmp && mv $@.tmp $@) || (cat $@.tmp; rm -f $@.tmp; false) -_out/%.done: %.sh $(wildcard ../../src/asc) ../run.sh | _out +_out/%.done: %.sh $(wildcard ../../src/moc) ../run.sh | _out @+ (../run.sh $(RUNFLAGS) $< > $@.tmp && mv $@.tmp $@) || (cat $@.tmp; rm -f $@.tmp; false) -_out/%.done: %.wat $(wildcard ../../src/asc) ../run.sh | _out +_out/%.done: %.wat $(wildcard ../../src/moc) ../run.sh | _out @+ (../run.sh $(RUNFLAGS) $< > $@.tmp && mv $@.tmp $@) || (cat $@.tmp; rm -f $@.tmp; false) _out/%.done: %.did $(wildcard ../../src/didc) ../run.sh | _out @+ (../run.sh $(RUNFLAGS) $< > $@.tmp && mv $@.tmp $@) || (cat $@.tmp; rm -f $@.tmp; false) diff --git a/test/random/Main.hs b/test/random/Main.hs index 4327bd89a76..1a679631c8c 100644 --- a/test/random/Main.hs +++ b/test/random/Main.hs @@ -29,7 +29,7 @@ import Turtle main = defaultMain tests where tests :: TestTree - tests = testGroup "ActorScript tests" [arithProps, utf8Props, matchingProps] + tests = testGroup "Motoko tests" [arithProps, utf8Props, matchingProps] arithProps = testGroup "Arithmetic/logic" [ QC.testProperty "expected failures" $ prop_rejects @@ -54,7 +54,7 @@ matchingProps = testGroup "pattern matching" wasm = name <.> "wasm" fileArg = fromString . encodeString script = do Turtle.output as $ fromString testCase - res@(exitCode, _, _) <- procStrictWithErr "asc" + res@(exitCode, _, _) <- procStrictWithErr "moc" ["-no-system-api", "-no-check-ir", fileArg as] empty if ExitSuccess == exitCode then (True,) <$> procStrictWithErr "wasm-interp" ["--enable-multi", fileArg wasm] empty @@ -133,9 +133,9 @@ instance Arbitrary TestCase where prop_verifies (TestCase (map fromString -> testCase)) = monadicIO $ do - let script cases = do Turtle.output "tests.as" $ msum cases - res@(exitCode, _, _) <- procStrictWithErr "asc" - ["-no-system-api", "-no-check-ir", "tests.as"] empty + let script cases = do Turtle.output "tests.mo" $ msum cases + res@(exitCode, _, _) <- procStrictWithErr "moc" + ["-no-system-api", "-no-check-ir", "tests.mo"] empty if ExitSuccess == exitCode then (True,) <$> procStrictWithErr "wasm-interp" ["--enable-multi", "tests.wasm"] empty else pure (False, res) @@ -199,7 +199,7 @@ mobile (tm, v) = monadicIO $ do runScriptNoFuzz "matchMobile" testCase -- instances of ASValue describe "ground values" in --- ActorScript. These can appear in patterns and have +-- Motoko. These can appear in patterns and have -- well-defined AS type. -- class ASValue a where @@ -255,7 +255,7 @@ instance Arbitrary Off where -- Below data structure tries to focus test case generation of -- numeric values to *neuralgic points* of the numeric line, namely --- areas where (from our white-box knowledge of ActorScript's inner +-- areas where (from our white-box knowledge of Motoko's inner -- workings) representation changes are expected to happen. These -- are mostly at a power-of-two boundary and around it, e.g. we have -- signed 30 bit numbers (`Int` and `Nat`) that have a compact representation diff --git a/test/random/README.md b/test/random/README.md index 4653efcf632..faa86214107 100644 --- a/test/random/README.md +++ b/test/random/README.md @@ -1,17 +1,17 @@ -# QA tool `qc-actorscript` +# QA tool `qc-motoko` -This tool generates ActorScript AST fragments and executes them, +This tool generates Motoko AST fragments and executes them, checking for the same outcome as the Haskell (here: reference) implementation. In order to compile and test it expects following tools to be in the `PATH`: -- `asc` (the ActorScript compiler) +- `moc` (the Motoko compiler) - `wasm-interp` (part of `nixpkgs.wabt`) ## How to spot failures -`qc-actorscript` is run from the CI infrastructure on each commit. On failures, something like +`qc-motoko` is run from the CI infrastructure on each commit. On failures, something like ``` Properties @@ -32,19 +32,19 @@ will appear in the CI log. The relevant recipe for reliable reproduction is the ## How to run locally With this piece of information you can run the identical test locally, -using the following `nix-build` invocation from your `actorscript` +using the following `nix-build` invocation from your `motoko` directory: ``` shell $ nix-build -A tests --arg replay 232458 ``` -## Running in `asc` and `wasm-interp` +## Running in `moc` and `wasm-interp` Of course you can dump the failing test case into a file, compile it to WASM, and execute it in (e.g.) `wasm-interp`: ``` shell -$ asc -no-system-api snippet.as +$ moc -no-system-api snippet.mo $ wasm-interp --enable-multi snippet.wasm ``` @@ -55,9 +55,9 @@ For *expected successes* it should execute without errors. When something doesn't build like expected, check for a file called (approximately) `test/random/.ghc.environment.x86_64-darwin-8.6.4`. This usually trips -up `nix-build`'s ability to build `qc-actorscript` locally, and should +up `nix-build`'s ability to build `qc-motoko` locally, and should be deleted. ## 0 -- 2019-08-08 -* First version. Released on a suspecting world. See also [GitHub issue 609](https://github.com/dfinity-lab/actorscript/pull/609). +* First version. Released on a suspecting world. See also [GitHub issue 609](https://github.com/dfinity-lab/motoko/pull/609). diff --git a/test/random/qc-actorscript.cabal b/test/random/qc-motoko.cabal similarity index 85% rename from test/random/qc-actorscript.cabal rename to test/random/qc-motoko.cabal index 3010591701d..50a61ad5e8a 100644 --- a/test/random/qc-actorscript.cabal +++ b/test/random/qc-motoko.cabal @@ -1,8 +1,8 @@ cabal-version: 2.4 -name: qc-actorscript +name: qc-motoko version: 0 -synopsis: generate randomised tests for ActorScript +synopsis: generate randomised tests for Motoko -- description: author: Gabor Greif maintainer: gabor@dfinity.org @@ -10,7 +10,7 @@ maintainer: gabor@dfinity.org category: Testing extra-source-files: CHANGELOG.md -executable qc-actorscript +executable qc-motoko main-is: Main.hs -- other-modules: other-extensions: ConstraintKinds, StandaloneDeriving, DataKinds, KindSignatures, GADTs, MultiParamTypeClasses diff --git a/test/repl/double-import.sh b/test/repl/double-import.sh index 42eb0c4bf65..052db3fb5cf 100755 --- a/test/repl/double-import.sh +++ b/test/repl/double-import.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -${ASC:-$(dirname "$BASH_SOURCE")/../../src/asc} -v -i <<__END__ -import "lib/empty.as"; -import "lib/empty.as"; +${MOC:-$(dirname "$BASH_SOURCE")/../../src/moc} -v -i <<__END__ +import "lib/empty.mo"; +import "lib/empty.mo"; __END__ diff --git a/test/repl/file-and-repl.sh b/test/repl/file-and-repl.sh index cddbbed8fac..0cf4ce95d5e 100755 --- a/test/repl/file-and-repl.sh +++ b/test/repl/file-and-repl.sh @@ -1,5 +1,5 @@ #!/bin/bash -${ASC:-$(dirname "$BASH_SOURCE")/../../src/asc} -v -i \ +${MOC:-$(dirname "$BASH_SOURCE")/../../src/moc} -v -i \ <(echo "let x = 1; switch (true) {case true ()}") <<__END__ assert (x == 1); __END__ diff --git a/test/repl/lib/a.as b/test/repl/lib/a.as deleted file mode 100644 index abd23b38d95..00000000000 --- a/test/repl/lib/a.as +++ /dev/null @@ -1 +0,0 @@ -import "c.as" diff --git a/test/repl/lib/a.mo b/test/repl/lib/a.mo new file mode 100644 index 00000000000..1927c9a60c6 --- /dev/null +++ b/test/repl/lib/a.mo @@ -0,0 +1 @@ +import "c.mo" diff --git a/test/repl/lib/b.as b/test/repl/lib/b.as deleted file mode 100644 index abd23b38d95..00000000000 --- a/test/repl/lib/b.as +++ /dev/null @@ -1 +0,0 @@ -import "c.as" diff --git a/test/repl/lib/b.mo b/test/repl/lib/b.mo new file mode 100644 index 00000000000..1927c9a60c6 --- /dev/null +++ b/test/repl/lib/b.mo @@ -0,0 +1 @@ +import "c.mo" diff --git a/test/repl/lib/c.as b/test/repl/lib/c.mo similarity index 100% rename from test/repl/lib/c.as rename to test/repl/lib/c.mo diff --git a/test/repl/lib/empty.as b/test/repl/lib/empty.mo similarity index 100% rename from test/repl/lib/empty.as rename to test/repl/lib/empty.mo diff --git a/test/repl/lib/nested.as b/test/repl/lib/nested.as deleted file mode 100644 index b22aecefea3..00000000000 --- a/test/repl/lib/nested.as +++ /dev/null @@ -1,2 +0,0 @@ -import A "nested/a.as"; -import "nested/b.as" diff --git a/test/repl/lib/nested.mo b/test/repl/lib/nested.mo new file mode 100644 index 00000000000..92801627663 --- /dev/null +++ b/test/repl/lib/nested.mo @@ -0,0 +1,2 @@ +import A "nested/a.mo"; +import "nested/b.mo" diff --git a/test/repl/lib/nested/a.as b/test/repl/lib/nested/a.mo similarity index 100% rename from test/repl/lib/nested/a.as rename to test/repl/lib/nested/a.mo diff --git a/test/repl/lib/nested/b.as b/test/repl/lib/nested/b.as deleted file mode 100644 index ac75e1c4228..00000000000 --- a/test/repl/lib/nested/b.as +++ /dev/null @@ -1,3 +0,0 @@ -module { - import "./a.as"; -} diff --git a/test/repl/lib/nested/b.mo b/test/repl/lib/nested/b.mo new file mode 100644 index 00000000000..0419dbf6552 --- /dev/null +++ b/test/repl/lib/nested/b.mo @@ -0,0 +1,3 @@ +module { + import "./a.mo"; +} diff --git a/test/repl/lib/triangle.as b/test/repl/lib/triangle.as deleted file mode 100644 index 7aba706615e..00000000000 --- a/test/repl/lib/triangle.as +++ /dev/null @@ -1 +0,0 @@ -import "a.as" diff --git a/test/repl/lib/triangle.mo b/test/repl/lib/triangle.mo new file mode 100644 index 00000000000..b5f67a31883 --- /dev/null +++ b/test/repl/lib/triangle.mo @@ -0,0 +1 @@ +import "a.mo" diff --git a/test/repl/nested-import.sh b/test/repl/nested-import.sh index 2d8a2f5602d..4400a0a52b5 100755 --- a/test/repl/nested-import.sh +++ b/test/repl/nested-import.sh @@ -1,4 +1,4 @@ #!/bin/bash -${ASC:-$(dirname "$BASH_SOURCE")/../../src/asc} -v -i <<__END__ | grep Parsing -import "lib/nested.as"; +${MOC:-$(dirname "$BASH_SOURCE")/../../src/moc} -v -i <<__END__ | grep Parsing +import "lib/nested.mo"; __END__ diff --git a/test/repl/ok/double-import.stdout.ok b/test/repl/ok/double-import.stdout.ok index fcb5a4f25f6..f3cfb0ebca8 100644 --- a/test/repl/ok/double-import.stdout.ok +++ b/test/repl/ok/double-import.stdout.ok @@ -1,10 +1,10 @@ -ActorScript 0.1 interpreter +Motoko 0.1 interpreter -- Parsing stdin: -> -- Parsing empty.as: --- Checking empty.as: --- Definedness empty.as: +> -- Parsing empty.mo: +-- Checking empty.mo: +-- Definedness empty.mo: -- Checking stdin: --- Interpreting empty.as: +-- Interpreting empty.mo: -- Interpreting stdin: -- Finished stdin: {} : module {} diff --git a/test/repl/ok/file-and-repl.stdout.ok b/test/repl/ok/file-and-repl.stdout.ok index c50a24d93a4..9a7d8f3cb9f 100644 --- a/test/repl/ok/file-and-repl.stdout.ok +++ b/test/repl/ok/file-and-repl.stdout.ok @@ -1,4 +1,4 @@ -ActorScript 0.1 interpreter +Motoko 0.1 interpreter -- Parsing 63: -- Checking 63: -- Definedness 63: diff --git a/test/repl/ok/nested-import.stdout.ok b/test/repl/ok/nested-import.stdout.ok index a5d14862a3a..f4819100728 100644 --- a/test/repl/ok/nested-import.stdout.ok +++ b/test/repl/ok/nested-import.stdout.ok @@ -1,5 +1,5 @@ -- Parsing stdin: -> -- Parsing nested.as: --- Parsing a.as: --- Parsing b.as: +> -- Parsing nested.mo: +-- Parsing a.mo: +-- Parsing b.mo: -- Parsing stdin: diff --git a/test/repl/ok/outrange-int-nat.stdout.ok b/test/repl/ok/outrange-int-nat.stdout.ok index 528624a3a1b..75ef205c01f 100644 --- a/test/repl/ok/outrange-int-nat.stdout.ok +++ b/test/repl/ok/outrange-int-nat.stdout.ok @@ -1,4 +1,4 @@ -ActorScript 0.1 interpreter +Motoko 0.1 interpreter > +127 : Int8 > prelude:___: execution error, numeric overflow > -128 : Int8 diff --git a/test/repl/ok/stateful.stdout.ok b/test/repl/ok/stateful.stdout.ok index 4951661b559..de1ae251ba1 100644 --- a/test/repl/ok/stateful.stdout.ok +++ b/test/repl/ok/stateful.stdout.ok @@ -1,3 +1,3 @@ -ActorScript 0.1 interpreter +Motoko 0.1 interpreter > let x : Nat = 42 > > > > diff --git a/test/repl/ok/triangle-import.stdout.ok b/test/repl/ok/triangle-import.stdout.ok index daa4d66a983..4479154f8d5 100644 --- a/test/repl/ok/triangle-import.stdout.ok +++ b/test/repl/ok/triangle-import.stdout.ok @@ -1,24 +1,24 @@ -ActorScript 0.1 interpreter +Motoko 0.1 interpreter -- Parsing stdin: -> -- Parsing b.as: --- Parsing c.as: --- Checking c.as: --- Definedness c.as: --- Checking b.as: --- Definedness b.as: +> -- Parsing b.mo: +-- Parsing c.mo: +-- Checking c.mo: +-- Definedness c.mo: +-- Checking b.mo: +-- Definedness b.mo: -- Checking stdin: --- Interpreting c.as: --- Interpreting b.as: +-- Interpreting c.mo: +-- Interpreting b.mo: -- Interpreting stdin: -- Finished stdin: 42 : Nat -- Parsing stdin: -> -- Parsing a.as: --- Checking a.as: --- Definedness a.as: +> -- Parsing a.mo: +-- Checking a.mo: +-- Definedness a.mo: -- Checking stdin: --- Interpreting a.as: +-- Interpreting a.mo: -- Interpreting stdin: -- Finished stdin: 42 : Nat @@ -30,11 +30,11 @@ ActorScript 0.1 interpreter 42 : Nat -- Parsing stdin: -> -- Parsing triangle.as: --- Checking triangle.as: --- Definedness triangle.as: +> -- Parsing triangle.mo: +-- Checking triangle.mo: +-- Definedness triangle.mo: -- Checking stdin: --- Interpreting triangle.as: +-- Interpreting triangle.mo: -- Interpreting stdin: -- Finished stdin: 42 : Nat diff --git a/test/repl/ok/type-lub-repl.stdout.ok b/test/repl/ok/type-lub-repl.stdout.ok index c402e4a0866..b3f4ed53aa5 100644 --- a/test/repl/ok/type-lub-repl.stdout.ok +++ b/test/repl/ok/type-lub-repl.stdout.ok @@ -1,4 +1,4 @@ -ActorScript 0.1 interpreter +Motoko 0.1 interpreter > [null, ?42, ?(-25)] : [(?Int)] > [null, null] : [Null] > [{a = 42}, {b = 42}] : [{}] diff --git a/test/repl/ok/variant-shorthand.stdout.ok b/test/repl/ok/variant-shorthand.stdout.ok index 44c26b7a0d9..98c2894b838 100644 --- a/test/repl/ok/variant-shorthand.stdout.ok +++ b/test/repl/ok/variant-shorthand.stdout.ok @@ -1,4 +1,4 @@ -ActorScript 0.1 interpreter +Motoko 0.1 interpreter > #bar : {#bar} > #foo(#bar) : {#foo : {#bar}} > [#Monday, #Tuesday, #Wednesday, #Thursday, #Friday, #Saturday, #Sunday] : [{#Friday; #Monday; #Saturday; #Sunday; #Thursday; #Tuesday; #Wednesday}] diff --git a/test/repl/outrange-int-nat.sh b/test/repl/outrange-int-nat.sh index 8554b134278..762427192e7 100755 --- a/test/repl/outrange-int-nat.sh +++ b/test/repl/outrange-int-nat.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # Tests that the repl Int* and Nat* types properly trap -${ASC:-$(dirname "$BASH_SOURCE")/../../src/asc} -i <<__END__ +${MOC:-$(dirname "$BASH_SOURCE")/../../src/moc} -i <<__END__ intToInt8 0x7F; intToInt8 0x80; intToInt8 (-0x80); diff --git a/test/repl/stateful.sh b/test/repl/stateful.sh index 19bb6dcff52..23e8a7f3907 100755 --- a/test/repl/stateful.sh +++ b/test/repl/stateful.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # Tests that the repl preserves the state across # syntax and type errors -${ASC:-$(dirname "$BASH_SOURCE")/../../src/asc} -i <<__END__ +${MOC:-$(dirname "$BASH_SOURCE")/../../src/moc} -i <<__END__ let x = 42; let x = "foobar let x = 1 + true; diff --git a/test/repl/triangle-import.sh b/test/repl/triangle-import.sh index 7e79f5c5e6b..6890ac4f8b4 100755 --- a/test/repl/triangle-import.sh +++ b/test/repl/triangle-import.sh @@ -1,7 +1,7 @@ #!/bin/bash -${ASC:-$(dirname "$BASH_SOURCE")/../../src/asc} -v -i <<__END__ -import "lib/b.as"; -import "lib/a.as"; -import "lib/c.as"; -import "lib/triangle.as"; +${MOC:-$(dirname "$BASH_SOURCE")/../../src/moc} -v -i <<__END__ +import "lib/b.mo"; +import "lib/a.mo"; +import "lib/c.mo"; +import "lib/triangle.mo"; __END__ diff --git a/test/repl/type-lub-repl.sh b/test/repl/type-lub-repl.sh index d7caab4c801..7d672c90b91 100755 --- a/test/repl/type-lub-repl.sh +++ b/test/repl/type-lub-repl.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # Tests that correct lub types are inferred when values appear in arrays -${ASC:-$(dirname "$BASH_SOURCE")/../../src/asc} -i -ancient-system-api ../run-dfinity/type-lub.as <<__END__ +${MOC:-$(dirname "$BASH_SOURCE")/../../src/moc} -i -ancient-system-api ../run-dfinity/type-lub.mo <<__END__ opts; nulls; incompatible_objs; diff --git a/test/repl/variant-shorthand.sh b/test/repl/variant-shorthand.sh index a52669b3e4e..70a0e932904 100755 --- a/test/repl/variant-shorthand.sh +++ b/test/repl/variant-shorthand.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # Tests that shorthand variants come out without parens -${ASC:-$(dirname "$BASH_SOURCE")/../../src/asc} -i <<__END__ +${MOC:-$(dirname "$BASH_SOURCE")/../../src/moc} -i <<__END__ #bar; #foo(#bar); [#Monday, #Tuesday, #Wednesday, #Thursday, #Friday, #Saturday, #Sunday]; diff --git a/test/run-dfinity/AST-64.as b/test/run-dfinity/AST-64.mo similarity index 100% rename from test/run-dfinity/AST-64.as rename to test/run-dfinity/AST-64.mo diff --git a/test/run-dfinity/AST-66.as b/test/run-dfinity/AST-66.mo similarity index 100% rename from test/run-dfinity/AST-66.as rename to test/run-dfinity/AST-66.mo diff --git a/test/run-dfinity/Makefile b/test/run-dfinity/Makefile index 3714325baa0..97145fb5c64 100644 --- a/test/run-dfinity/Makefile +++ b/test/run-dfinity/Makefile @@ -1,10 +1,10 @@ RUNFLAGS = -1 all: - ../run.sh $(RUNFLAGS) *.as + ../run.sh $(RUNFLAGS) *.mo accept: - ../run.sh $(RUNFLAGS) -a *.as + ../run.sh $(RUNFLAGS) -a *.mo clean: rm -rf _out diff --git a/test/run-dfinity/arity_bug.as b/test/run-dfinity/arity_bug.mo similarity index 100% rename from test/run-dfinity/arity_bug.as rename to test/run-dfinity/arity_bug.mo diff --git a/test/run-dfinity/array-out-of-bounds.as b/test/run-dfinity/array-out-of-bounds.mo similarity index 100% rename from test/run-dfinity/array-out-of-bounds.as rename to test/run-dfinity/array-out-of-bounds.mo diff --git a/test/run-dfinity/async-any.as b/test/run-dfinity/async-any.mo similarity index 100% rename from test/run-dfinity/async-any.as rename to test/run-dfinity/async-any.mo diff --git a/test/run-dfinity/async-calls.as b/test/run-dfinity/async-calls.mo similarity index 100% rename from test/run-dfinity/async-calls.as rename to test/run-dfinity/async-calls.mo diff --git a/test/run-dfinity/async-loop-while.as b/test/run-dfinity/async-loop-while.mo similarity index 100% rename from test/run-dfinity/async-loop-while.as rename to test/run-dfinity/async-loop-while.mo diff --git a/test/run-dfinity/async-loop.as b/test/run-dfinity/async-loop.mo similarity index 100% rename from test/run-dfinity/async-loop.as rename to test/run-dfinity/async-loop.mo diff --git a/test/run-dfinity/async-new-obj.as b/test/run-dfinity/async-new-obj.mo similarity index 100% rename from test/run-dfinity/async-new-obj.as rename to test/run-dfinity/async-new-obj.mo diff --git a/test/run-dfinity/async-obj-mut.as b/test/run-dfinity/async-obj-mut.mo similarity index 100% rename from test/run-dfinity/async-obj-mut.as rename to test/run-dfinity/async-obj-mut.mo diff --git a/test/run-dfinity/async-while.as b/test/run-dfinity/async-while.mo similarity index 100% rename from test/run-dfinity/async-while.as rename to test/run-dfinity/async-while.mo diff --git a/test/run-dfinity/await.as b/test/run-dfinity/await.mo similarity index 100% rename from test/run-dfinity/await.as rename to test/run-dfinity/await.mo diff --git a/test/run-dfinity/block.as b/test/run-dfinity/block.mo similarity index 100% rename from test/run-dfinity/block.as rename to test/run-dfinity/block.mo diff --git a/test/run-dfinity/chat.as b/test/run-dfinity/chat.mo similarity index 100% rename from test/run-dfinity/chat.as rename to test/run-dfinity/chat.mo diff --git a/test/run-dfinity/chatpp.as b/test/run-dfinity/chatpp.mo similarity index 100% rename from test/run-dfinity/chatpp.as rename to test/run-dfinity/chatpp.mo diff --git a/test/run-dfinity/closure-params.as b/test/run-dfinity/closure-params.mo similarity index 100% rename from test/run-dfinity/closure-params.as rename to test/run-dfinity/closure-params.mo diff --git a/test/run-dfinity/control.as b/test/run-dfinity/control.mo similarity index 100% rename from test/run-dfinity/control.as rename to test/run-dfinity/control.mo diff --git a/test/run-dfinity/counter-class.as b/test/run-dfinity/counter-class.mo similarity index 100% rename from test/run-dfinity/counter-class.as rename to test/run-dfinity/counter-class.mo diff --git a/test/run-dfinity/counter.as b/test/run-dfinity/counter.mo similarity index 100% rename from test/run-dfinity/counter.as rename to test/run-dfinity/counter.mo diff --git a/test/run-dfinity/counter2.as b/test/run-dfinity/counter2.mo similarity index 100% rename from test/run-dfinity/counter2.as rename to test/run-dfinity/counter2.mo diff --git a/test/run-dfinity/data-params.as b/test/run-dfinity/data-params.mo similarity index 100% rename from test/run-dfinity/data-params.as rename to test/run-dfinity/data-params.mo diff --git a/test/run-dfinity/empty-actor.as b/test/run-dfinity/empty-actor.mo similarity index 100% rename from test/run-dfinity/empty-actor.as rename to test/run-dfinity/empty-actor.mo diff --git a/test/run-dfinity/fac.as b/test/run-dfinity/fac.mo similarity index 100% rename from test/run-dfinity/fac.as rename to test/run-dfinity/fac.mo diff --git a/test/run-dfinity/flatten-awaitables.as b/test/run-dfinity/flatten-awaitables.mo similarity index 100% rename from test/run-dfinity/flatten-awaitables.as rename to test/run-dfinity/flatten-awaitables.mo diff --git a/test/run-dfinity/for-await.as b/test/run-dfinity/for-await.mo similarity index 100% rename from test/run-dfinity/for-await.as rename to test/run-dfinity/for-await.mo diff --git a/test/run-dfinity/general-type-components.as b/test/run-dfinity/general-type-components.mo similarity index 100% rename from test/run-dfinity/general-type-components.as rename to test/run-dfinity/general-type-components.mo diff --git a/test/run-dfinity/generic-tail-rec.as b/test/run-dfinity/generic-tail-rec.mo similarity index 100% rename from test/run-dfinity/generic-tail-rec.as rename to test/run-dfinity/generic-tail-rec.mo diff --git a/test/run-dfinity/hello-concat-world.as b/test/run-dfinity/hello-concat-world.mo similarity index 100% rename from test/run-dfinity/hello-concat-world.as rename to test/run-dfinity/hello-concat-world.mo diff --git a/test/run-dfinity/hello-world-async.as b/test/run-dfinity/hello-world-async.mo similarity index 100% rename from test/run-dfinity/hello-world-async.as rename to test/run-dfinity/hello-world-async.mo diff --git a/test/run-dfinity/hello-world-await.as b/test/run-dfinity/hello-world-await.mo similarity index 100% rename from test/run-dfinity/hello-world-await.as rename to test/run-dfinity/hello-world-await.mo diff --git a/test/run-dfinity/hello-world-message.as b/test/run-dfinity/hello-world-message.mo similarity index 100% rename from test/run-dfinity/hello-world-message.as rename to test/run-dfinity/hello-world-message.mo diff --git a/test/run-dfinity/hello-world-message2.as b/test/run-dfinity/hello-world-message2.mo similarity index 100% rename from test/run-dfinity/hello-world-message2.as rename to test/run-dfinity/hello-world-message2.mo diff --git a/test/run-dfinity/hello-world.as b/test/run-dfinity/hello-world.mo similarity index 100% rename from test/run-dfinity/hello-world.as rename to test/run-dfinity/hello-world.mo diff --git a/test/run-dfinity/hello-world2.as b/test/run-dfinity/hello-world2.mo similarity index 100% rename from test/run-dfinity/hello-world2.as rename to test/run-dfinity/hello-world2.mo diff --git a/test/run-dfinity/hello-world3.as b/test/run-dfinity/hello-world3.mo similarity index 100% rename from test/run-dfinity/hello-world3.as rename to test/run-dfinity/hello-world3.mo diff --git a/test/run-dfinity/idl-tuple.as b/test/run-dfinity/idl-tuple.mo similarity index 100% rename from test/run-dfinity/idl-tuple.as rename to test/run-dfinity/idl-tuple.mo diff --git a/test/run-dfinity/indirect-counter.as b/test/run-dfinity/indirect-counter.mo similarity index 100% rename from test/run-dfinity/indirect-counter.as rename to test/run-dfinity/indirect-counter.mo diff --git a/test/run-dfinity/large-mem.as b/test/run-dfinity/large-mem.mo similarity index 100% rename from test/run-dfinity/large-mem.as rename to test/run-dfinity/large-mem.mo diff --git a/test/run-dfinity/local-throw.as b/test/run-dfinity/local-throw.mo similarity index 100% rename from test/run-dfinity/local-throw.as rename to test/run-dfinity/local-throw.mo diff --git a/test/run-dfinity/log-slow.as b/test/run-dfinity/log-slow.mo similarity index 100% rename from test/run-dfinity/log-slow.as rename to test/run-dfinity/log-slow.mo diff --git a/test/run-dfinity/modexp1.as b/test/run-dfinity/modexp1.mo similarity index 100% rename from test/run-dfinity/modexp1.as rename to test/run-dfinity/modexp1.mo diff --git a/test/run-dfinity/modexp2.as b/test/run-dfinity/modexp2.mo similarity index 100% rename from test/run-dfinity/modexp2.as rename to test/run-dfinity/modexp2.mo diff --git a/test/run-dfinity/modexp3.as b/test/run-dfinity/modexp3.mo similarity index 100% rename from test/run-dfinity/modexp3.as rename to test/run-dfinity/modexp3.mo diff --git a/test/run-dfinity/modexp4.as b/test/run-dfinity/modexp4.mo similarity index 100% rename from test/run-dfinity/modexp4.as rename to test/run-dfinity/modexp4.mo diff --git a/test/run-dfinity/modules-bwd.as b/test/run-dfinity/modules-bwd.mo similarity index 100% rename from test/run-dfinity/modules-bwd.as rename to test/run-dfinity/modules-bwd.mo diff --git a/test/run-dfinity/nary-async.as b/test/run-dfinity/nary-async.mo similarity index 100% rename from test/run-dfinity/nary-async.as rename to test/run-dfinity/nary-async.mo diff --git a/test/run-dfinity/ok/array-out-of-bounds.run-ir.ok b/test/run-dfinity/ok/array-out-of-bounds.run-ir.ok index 48afd57d5df..130db1c6b7f 100644 --- a/test/run-dfinity/ok/array-out-of-bounds.run-ir.ok +++ b/test/run-dfinity/ok/array-out-of-bounds.run-ir.ok @@ -1,2 +1,2 @@ -array-out-of-bounds.as:5.10-5.14: execution error, index out of bounds -array-out-of-bounds.as:9.10-9.14: execution error, index out of bounds +array-out-of-bounds.mo:5.10-5.14: execution error, index out of bounds +array-out-of-bounds.mo:9.10-9.14: execution error, index out of bounds diff --git a/test/run-dfinity/ok/array-out-of-bounds.run-low.ok b/test/run-dfinity/ok/array-out-of-bounds.run-low.ok index 48afd57d5df..130db1c6b7f 100644 --- a/test/run-dfinity/ok/array-out-of-bounds.run-low.ok +++ b/test/run-dfinity/ok/array-out-of-bounds.run-low.ok @@ -1,2 +1,2 @@ -array-out-of-bounds.as:5.10-5.14: execution error, index out of bounds -array-out-of-bounds.as:9.10-9.14: execution error, index out of bounds +array-out-of-bounds.mo:5.10-5.14: execution error, index out of bounds +array-out-of-bounds.mo:9.10-9.14: execution error, index out of bounds diff --git a/test/run-dfinity/ok/array-out-of-bounds.run.ok b/test/run-dfinity/ok/array-out-of-bounds.run.ok index 48afd57d5df..130db1c6b7f 100644 --- a/test/run-dfinity/ok/array-out-of-bounds.run.ok +++ b/test/run-dfinity/ok/array-out-of-bounds.run.ok @@ -1,2 +1,2 @@ -array-out-of-bounds.as:5.10-5.14: execution error, index out of bounds -array-out-of-bounds.as:9.10-9.14: execution error, index out of bounds +array-out-of-bounds.mo:5.10-5.14: execution error, index out of bounds +array-out-of-bounds.mo:9.10-9.14: execution error, index out of bounds diff --git a/test/run-dfinity/ok/data-params.idl.stderr.ok b/test/run-dfinity/ok/data-params.idl.stderr.ok index fdcd0402292..4f513b4d81a 100644 --- a/test/run-dfinity/ok/data-params.idl.stderr.ok +++ b/test/run-dfinity/ok/data-params.idl.stderr.ok @@ -1,4 +1,4 @@ -data-params.as:59.30-59.40: warning, this pattern consuming type +data-params.mo:59.30-59.40: warning, this pattern consuming type ?Text does not cover value null diff --git a/test/run-dfinity/ok/data-params.run-ir.ok b/test/run-dfinity/ok/data-params.run-ir.ok index 216ee86db4a..78262242d6f 100644 --- a/test/run-dfinity/ok/data-params.run-ir.ok +++ b/test/run-dfinity/ok/data-params.run-ir.ok @@ -1,4 +1,4 @@ -data-params.as:59.30-59.40: warning, this pattern consuming type +data-params.mo:59.30-59.40: warning, this pattern consuming type ?Text does not cover value null diff --git a/test/run-dfinity/ok/data-params.run-low.ok b/test/run-dfinity/ok/data-params.run-low.ok index 216ee86db4a..78262242d6f 100644 --- a/test/run-dfinity/ok/data-params.run-low.ok +++ b/test/run-dfinity/ok/data-params.run-low.ok @@ -1,4 +1,4 @@ -data-params.as:59.30-59.40: warning, this pattern consuming type +data-params.mo:59.30-59.40: warning, this pattern consuming type ?Text does not cover value null diff --git a/test/run-dfinity/ok/data-params.run.ok b/test/run-dfinity/ok/data-params.run.ok index 216ee86db4a..78262242d6f 100644 --- a/test/run-dfinity/ok/data-params.run.ok +++ b/test/run-dfinity/ok/data-params.run.ok @@ -1,4 +1,4 @@ -data-params.as:59.30-59.40: warning, this pattern consuming type +data-params.mo:59.30-59.40: warning, this pattern consuming type ?Text does not cover value null diff --git a/test/run-dfinity/ok/data-params.tc.ok b/test/run-dfinity/ok/data-params.tc.ok index fdcd0402292..4f513b4d81a 100644 --- a/test/run-dfinity/ok/data-params.tc.ok +++ b/test/run-dfinity/ok/data-params.tc.ok @@ -1,4 +1,4 @@ -data-params.as:59.30-59.40: warning, this pattern consuming type +data-params.mo:59.30-59.40: warning, this pattern consuming type ?Text does not cover value null diff --git a/test/run-dfinity/ok/data-params.wasm.stderr.ok b/test/run-dfinity/ok/data-params.wasm.stderr.ok index fdcd0402292..4f513b4d81a 100644 --- a/test/run-dfinity/ok/data-params.wasm.stderr.ok +++ b/test/run-dfinity/ok/data-params.wasm.stderr.ok @@ -1,4 +1,4 @@ -data-params.as:59.30-59.40: warning, this pattern consuming type +data-params.mo:59.30-59.40: warning, this pattern consuming type ?Text does not cover value null diff --git a/test/run-dfinity/ok/flatten-awaitables.idl.stderr.ok b/test/run-dfinity/ok/flatten-awaitables.idl.stderr.ok index 132c1167a2f..4734a23a649 100644 --- a/test/run-dfinity/ok/flatten-awaitables.idl.stderr.ok +++ b/test/run-dfinity/ok/flatten-awaitables.idl.stderr.ok @@ -1,118 +1,118 @@ -flatten-awaitables.as:43.9-43.10: warning, this pattern consuming type +flatten-awaitables.mo:43.9-43.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:45.9-45.17: warning, this pattern consuming type +flatten-awaitables.mo:45.9-45.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:47.9-47.25: warning, this pattern consuming type +flatten-awaitables.mo:47.9-47.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:52.9-52.10: warning, this pattern consuming type +flatten-awaitables.mo:52.9-52.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:54.9-54.17: warning, this pattern consuming type +flatten-awaitables.mo:54.9-54.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:56.9-56.25: warning, this pattern consuming type +flatten-awaitables.mo:56.9-56.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:66.9-66.10: warning, this pattern consuming type +flatten-awaitables.mo:66.9-66.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:68.9-68.17: warning, this pattern consuming type +flatten-awaitables.mo:68.9-68.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:70.9-70.25: warning, this pattern consuming type +flatten-awaitables.mo:70.9-70.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:75.9-75.10: warning, this pattern consuming type +flatten-awaitables.mo:75.9-75.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:77.9-77.17: warning, this pattern consuming type +flatten-awaitables.mo:77.9-77.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:79.9-79.25: warning, this pattern consuming type +flatten-awaitables.mo:79.9-79.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:85.9-85.10: warning, this pattern consuming type +flatten-awaitables.mo:85.9-85.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:87.9-87.17: warning, this pattern consuming type +flatten-awaitables.mo:87.9-87.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:89.9-89.25: warning, this pattern consuming type +flatten-awaitables.mo:89.9-89.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:94.9-94.10: warning, this pattern consuming type +flatten-awaitables.mo:94.9-94.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:96.9-96.17: warning, this pattern consuming type +flatten-awaitables.mo:96.9-96.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:98.9-98.25: warning, this pattern consuming type +flatten-awaitables.mo:98.9-98.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:103.9-103.10: warning, this pattern consuming type +flatten-awaitables.mo:103.9-103.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:105.9-105.17: warning, this pattern consuming type +flatten-awaitables.mo:105.9-105.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:107.9-107.25: warning, this pattern consuming type +flatten-awaitables.mo:107.9-107.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:112.9-112.10: warning, this pattern consuming type +flatten-awaitables.mo:112.9-112.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:114.9-114.17: warning, this pattern consuming type +flatten-awaitables.mo:114.9-114.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:116.9-116.25: warning, this pattern consuming type +flatten-awaitables.mo:116.9-116.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or diff --git a/test/run-dfinity/ok/flatten-awaitables.run-ir.ok b/test/run-dfinity/ok/flatten-awaitables.run-ir.ok index e5bc31fb875..71bc01633c6 100644 --- a/test/run-dfinity/ok/flatten-awaitables.run-ir.ok +++ b/test/run-dfinity/ok/flatten-awaitables.run-ir.ok @@ -1,118 +1,118 @@ -flatten-awaitables.as:43.9-43.10: warning, this pattern consuming type +flatten-awaitables.mo:43.9-43.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:45.9-45.17: warning, this pattern consuming type +flatten-awaitables.mo:45.9-45.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:47.9-47.25: warning, this pattern consuming type +flatten-awaitables.mo:47.9-47.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:52.9-52.10: warning, this pattern consuming type +flatten-awaitables.mo:52.9-52.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:54.9-54.17: warning, this pattern consuming type +flatten-awaitables.mo:54.9-54.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:56.9-56.25: warning, this pattern consuming type +flatten-awaitables.mo:56.9-56.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:66.9-66.10: warning, this pattern consuming type +flatten-awaitables.mo:66.9-66.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:68.9-68.17: warning, this pattern consuming type +flatten-awaitables.mo:68.9-68.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:70.9-70.25: warning, this pattern consuming type +flatten-awaitables.mo:70.9-70.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:75.9-75.10: warning, this pattern consuming type +flatten-awaitables.mo:75.9-75.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:77.9-77.17: warning, this pattern consuming type +flatten-awaitables.mo:77.9-77.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:79.9-79.25: warning, this pattern consuming type +flatten-awaitables.mo:79.9-79.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:85.9-85.10: warning, this pattern consuming type +flatten-awaitables.mo:85.9-85.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:87.9-87.17: warning, this pattern consuming type +flatten-awaitables.mo:87.9-87.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:89.9-89.25: warning, this pattern consuming type +flatten-awaitables.mo:89.9-89.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:94.9-94.10: warning, this pattern consuming type +flatten-awaitables.mo:94.9-94.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:96.9-96.17: warning, this pattern consuming type +flatten-awaitables.mo:96.9-96.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:98.9-98.25: warning, this pattern consuming type +flatten-awaitables.mo:98.9-98.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:103.9-103.10: warning, this pattern consuming type +flatten-awaitables.mo:103.9-103.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:105.9-105.17: warning, this pattern consuming type +flatten-awaitables.mo:105.9-105.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:107.9-107.25: warning, this pattern consuming type +flatten-awaitables.mo:107.9-107.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:112.9-112.10: warning, this pattern consuming type +flatten-awaitables.mo:112.9-112.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:114.9-114.17: warning, this pattern consuming type +flatten-awaitables.mo:114.9-114.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:116.9-116.25: warning, this pattern consuming type +flatten-awaitables.mo:116.9-116.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or diff --git a/test/run-dfinity/ok/flatten-awaitables.run-low.ok b/test/run-dfinity/ok/flatten-awaitables.run-low.ok index e5bc31fb875..71bc01633c6 100644 --- a/test/run-dfinity/ok/flatten-awaitables.run-low.ok +++ b/test/run-dfinity/ok/flatten-awaitables.run-low.ok @@ -1,118 +1,118 @@ -flatten-awaitables.as:43.9-43.10: warning, this pattern consuming type +flatten-awaitables.mo:43.9-43.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:45.9-45.17: warning, this pattern consuming type +flatten-awaitables.mo:45.9-45.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:47.9-47.25: warning, this pattern consuming type +flatten-awaitables.mo:47.9-47.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:52.9-52.10: warning, this pattern consuming type +flatten-awaitables.mo:52.9-52.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:54.9-54.17: warning, this pattern consuming type +flatten-awaitables.mo:54.9-54.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:56.9-56.25: warning, this pattern consuming type +flatten-awaitables.mo:56.9-56.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:66.9-66.10: warning, this pattern consuming type +flatten-awaitables.mo:66.9-66.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:68.9-68.17: warning, this pattern consuming type +flatten-awaitables.mo:68.9-68.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:70.9-70.25: warning, this pattern consuming type +flatten-awaitables.mo:70.9-70.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:75.9-75.10: warning, this pattern consuming type +flatten-awaitables.mo:75.9-75.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:77.9-77.17: warning, this pattern consuming type +flatten-awaitables.mo:77.9-77.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:79.9-79.25: warning, this pattern consuming type +flatten-awaitables.mo:79.9-79.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:85.9-85.10: warning, this pattern consuming type +flatten-awaitables.mo:85.9-85.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:87.9-87.17: warning, this pattern consuming type +flatten-awaitables.mo:87.9-87.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:89.9-89.25: warning, this pattern consuming type +flatten-awaitables.mo:89.9-89.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:94.9-94.10: warning, this pattern consuming type +flatten-awaitables.mo:94.9-94.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:96.9-96.17: warning, this pattern consuming type +flatten-awaitables.mo:96.9-96.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:98.9-98.25: warning, this pattern consuming type +flatten-awaitables.mo:98.9-98.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:103.9-103.10: warning, this pattern consuming type +flatten-awaitables.mo:103.9-103.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:105.9-105.17: warning, this pattern consuming type +flatten-awaitables.mo:105.9-105.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:107.9-107.25: warning, this pattern consuming type +flatten-awaitables.mo:107.9-107.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:112.9-112.10: warning, this pattern consuming type +flatten-awaitables.mo:112.9-112.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:114.9-114.17: warning, this pattern consuming type +flatten-awaitables.mo:114.9-114.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:116.9-116.25: warning, this pattern consuming type +flatten-awaitables.mo:116.9-116.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or diff --git a/test/run-dfinity/ok/flatten-awaitables.run.ok b/test/run-dfinity/ok/flatten-awaitables.run.ok index e5bc31fb875..71bc01633c6 100644 --- a/test/run-dfinity/ok/flatten-awaitables.run.ok +++ b/test/run-dfinity/ok/flatten-awaitables.run.ok @@ -1,118 +1,118 @@ -flatten-awaitables.as:43.9-43.10: warning, this pattern consuming type +flatten-awaitables.mo:43.9-43.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:45.9-45.17: warning, this pattern consuming type +flatten-awaitables.mo:45.9-45.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:47.9-47.25: warning, this pattern consuming type +flatten-awaitables.mo:47.9-47.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:52.9-52.10: warning, this pattern consuming type +flatten-awaitables.mo:52.9-52.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:54.9-54.17: warning, this pattern consuming type +flatten-awaitables.mo:54.9-54.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:56.9-56.25: warning, this pattern consuming type +flatten-awaitables.mo:56.9-56.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:66.9-66.10: warning, this pattern consuming type +flatten-awaitables.mo:66.9-66.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:68.9-68.17: warning, this pattern consuming type +flatten-awaitables.mo:68.9-68.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:70.9-70.25: warning, this pattern consuming type +flatten-awaitables.mo:70.9-70.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:75.9-75.10: warning, this pattern consuming type +flatten-awaitables.mo:75.9-75.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:77.9-77.17: warning, this pattern consuming type +flatten-awaitables.mo:77.9-77.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:79.9-79.25: warning, this pattern consuming type +flatten-awaitables.mo:79.9-79.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:85.9-85.10: warning, this pattern consuming type +flatten-awaitables.mo:85.9-85.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:87.9-87.17: warning, this pattern consuming type +flatten-awaitables.mo:87.9-87.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:89.9-89.25: warning, this pattern consuming type +flatten-awaitables.mo:89.9-89.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:94.9-94.10: warning, this pattern consuming type +flatten-awaitables.mo:94.9-94.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:96.9-96.17: warning, this pattern consuming type +flatten-awaitables.mo:96.9-96.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:98.9-98.25: warning, this pattern consuming type +flatten-awaitables.mo:98.9-98.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:103.9-103.10: warning, this pattern consuming type +flatten-awaitables.mo:103.9-103.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:105.9-105.17: warning, this pattern consuming type +flatten-awaitables.mo:105.9-105.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:107.9-107.25: warning, this pattern consuming type +flatten-awaitables.mo:107.9-107.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:112.9-112.10: warning, this pattern consuming type +flatten-awaitables.mo:112.9-112.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:114.9-114.17: warning, this pattern consuming type +flatten-awaitables.mo:114.9-114.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:116.9-116.25: warning, this pattern consuming type +flatten-awaitables.mo:116.9-116.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or diff --git a/test/run-dfinity/ok/flatten-awaitables.tc.ok b/test/run-dfinity/ok/flatten-awaitables.tc.ok index 132c1167a2f..4734a23a649 100644 --- a/test/run-dfinity/ok/flatten-awaitables.tc.ok +++ b/test/run-dfinity/ok/flatten-awaitables.tc.ok @@ -1,118 +1,118 @@ -flatten-awaitables.as:43.9-43.10: warning, this pattern consuming type +flatten-awaitables.mo:43.9-43.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:45.9-45.17: warning, this pattern consuming type +flatten-awaitables.mo:45.9-45.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:47.9-47.25: warning, this pattern consuming type +flatten-awaitables.mo:47.9-47.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:52.9-52.10: warning, this pattern consuming type +flatten-awaitables.mo:52.9-52.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:54.9-54.17: warning, this pattern consuming type +flatten-awaitables.mo:54.9-54.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:56.9-56.25: warning, this pattern consuming type +flatten-awaitables.mo:56.9-56.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:66.9-66.10: warning, this pattern consuming type +flatten-awaitables.mo:66.9-66.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:68.9-68.17: warning, this pattern consuming type +flatten-awaitables.mo:68.9-68.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:70.9-70.25: warning, this pattern consuming type +flatten-awaitables.mo:70.9-70.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:75.9-75.10: warning, this pattern consuming type +flatten-awaitables.mo:75.9-75.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:77.9-77.17: warning, this pattern consuming type +flatten-awaitables.mo:77.9-77.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:79.9-79.25: warning, this pattern consuming type +flatten-awaitables.mo:79.9-79.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:85.9-85.10: warning, this pattern consuming type +flatten-awaitables.mo:85.9-85.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:87.9-87.17: warning, this pattern consuming type +flatten-awaitables.mo:87.9-87.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:89.9-89.25: warning, this pattern consuming type +flatten-awaitables.mo:89.9-89.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:94.9-94.10: warning, this pattern consuming type +flatten-awaitables.mo:94.9-94.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:96.9-96.17: warning, this pattern consuming type +flatten-awaitables.mo:96.9-96.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:98.9-98.25: warning, this pattern consuming type +flatten-awaitables.mo:98.9-98.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:103.9-103.10: warning, this pattern consuming type +flatten-awaitables.mo:103.9-103.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:105.9-105.17: warning, this pattern consuming type +flatten-awaitables.mo:105.9-105.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:107.9-107.25: warning, this pattern consuming type +flatten-awaitables.mo:107.9-107.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:112.9-112.10: warning, this pattern consuming type +flatten-awaitables.mo:112.9-112.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:114.9-114.17: warning, this pattern consuming type +flatten-awaitables.mo:114.9-114.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:116.9-116.25: warning, this pattern consuming type +flatten-awaitables.mo:116.9-116.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or diff --git a/test/run-dfinity/ok/flatten-awaitables.wasm.stderr.ok b/test/run-dfinity/ok/flatten-awaitables.wasm.stderr.ok index 132c1167a2f..4734a23a649 100644 --- a/test/run-dfinity/ok/flatten-awaitables.wasm.stderr.ok +++ b/test/run-dfinity/ok/flatten-awaitables.wasm.stderr.ok @@ -1,118 +1,118 @@ -flatten-awaitables.as:43.9-43.10: warning, this pattern consuming type +flatten-awaitables.mo:43.9-43.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:45.9-45.17: warning, this pattern consuming type +flatten-awaitables.mo:45.9-45.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:47.9-47.25: warning, this pattern consuming type +flatten-awaitables.mo:47.9-47.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:52.9-52.10: warning, this pattern consuming type +flatten-awaitables.mo:52.9-52.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:54.9-54.17: warning, this pattern consuming type +flatten-awaitables.mo:54.9-54.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:56.9-56.25: warning, this pattern consuming type +flatten-awaitables.mo:56.9-56.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:66.9-66.10: warning, this pattern consuming type +flatten-awaitables.mo:66.9-66.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:68.9-68.17: warning, this pattern consuming type +flatten-awaitables.mo:68.9-68.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:70.9-70.25: warning, this pattern consuming type +flatten-awaitables.mo:70.9-70.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:75.9-75.10: warning, this pattern consuming type +flatten-awaitables.mo:75.9-75.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:77.9-77.17: warning, this pattern consuming type +flatten-awaitables.mo:77.9-77.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:79.9-79.25: warning, this pattern consuming type +flatten-awaitables.mo:79.9-79.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:85.9-85.10: warning, this pattern consuming type +flatten-awaitables.mo:85.9-85.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:87.9-87.17: warning, this pattern consuming type +flatten-awaitables.mo:87.9-87.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:89.9-89.25: warning, this pattern consuming type +flatten-awaitables.mo:89.9-89.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:94.9-94.10: warning, this pattern consuming type +flatten-awaitables.mo:94.9-94.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:96.9-96.17: warning, this pattern consuming type +flatten-awaitables.mo:96.9-96.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:98.9-98.25: warning, this pattern consuming type +flatten-awaitables.mo:98.9-98.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:103.9-103.10: warning, this pattern consuming type +flatten-awaitables.mo:103.9-103.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:105.9-105.17: warning, this pattern consuming type +flatten-awaitables.mo:105.9-105.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:107.9-107.25: warning, this pattern consuming type +flatten-awaitables.mo:107.9-107.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.as:112.9-112.10: warning, this pattern consuming type +flatten-awaitables.mo:112.9-112.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.as:114.9-114.17: warning, this pattern consuming type +flatten-awaitables.mo:114.9-114.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.as:116.9-116.25: warning, this pattern consuming type +flatten-awaitables.mo:116.9-116.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or diff --git a/test/run-dfinity/ok/overflow.run-ir.ok b/test/run-dfinity/ok/overflow.run-ir.ok index 99ef5a02d51..481b58663c2 100644 --- a/test/run-dfinity/ok/overflow.run-ir.ok +++ b/test/run-dfinity/ok/overflow.run-ir.ok @@ -1,6 +1,6 @@ This is reachable. This is reachable. -overflow.as:14.14-14.17: execution error, arithmetic overflow -overflow.as:18.14-18.17: execution error, arithmetic overflow +overflow.mo:14.14-14.17: execution error, arithmetic overflow +overflow.mo:18.14-18.17: execution error, arithmetic overflow This is reachable. This is reachable. diff --git a/test/run-dfinity/ok/overflow.run-low.ok b/test/run-dfinity/ok/overflow.run-low.ok index 99ef5a02d51..481b58663c2 100644 --- a/test/run-dfinity/ok/overflow.run-low.ok +++ b/test/run-dfinity/ok/overflow.run-low.ok @@ -1,6 +1,6 @@ This is reachable. This is reachable. -overflow.as:14.14-14.17: execution error, arithmetic overflow -overflow.as:18.14-18.17: execution error, arithmetic overflow +overflow.mo:14.14-14.17: execution error, arithmetic overflow +overflow.mo:18.14-18.17: execution error, arithmetic overflow This is reachable. This is reachable. diff --git a/test/run-dfinity/ok/overflow.run.ok b/test/run-dfinity/ok/overflow.run.ok index 99ef5a02d51..481b58663c2 100644 --- a/test/run-dfinity/ok/overflow.run.ok +++ b/test/run-dfinity/ok/overflow.run.ok @@ -1,6 +1,6 @@ This is reachable. This is reachable. -overflow.as:14.14-14.17: execution error, arithmetic overflow -overflow.as:18.14-18.17: execution error, arithmetic overflow +overflow.mo:14.14-14.17: execution error, arithmetic overflow +overflow.mo:18.14-18.17: execution error, arithmetic overflow This is reachable. This is reachable. diff --git a/test/run-dfinity/ok/query.run-ir.ok b/test/run-dfinity/ok/query.run-ir.ok index 93b07b45408..5a78e7ebee9 100644 --- a/test/run-dfinity/ok/query.run-ir.ok +++ b/test/run-dfinity/ok/query.run-ir.ok @@ -5,5 +5,5 @@ 5(read) 5 6(read) -query.as:61.2-61.16: execution error, assertion failure +query.mo:61.2-61.16: execution error, assertion failure 6 diff --git a/test/run-dfinity/ok/query.run-low.ok b/test/run-dfinity/ok/query.run-low.ok index 93b07b45408..5a78e7ebee9 100644 --- a/test/run-dfinity/ok/query.run-low.ok +++ b/test/run-dfinity/ok/query.run-low.ok @@ -5,5 +5,5 @@ 5(read) 5 6(read) -query.as:61.2-61.16: execution error, assertion failure +query.mo:61.2-61.16: execution error, assertion failure 6 diff --git a/test/run-dfinity/ok/query.run.ok b/test/run-dfinity/ok/query.run.ok index 93b07b45408..5a78e7ebee9 100644 --- a/test/run-dfinity/ok/query.run.ok +++ b/test/run-dfinity/ok/query.run.ok @@ -5,5 +5,5 @@ 5(read) 5 6(read) -query.as:61.2-61.16: execution error, assertion failure +query.mo:61.2-61.16: execution error, assertion failure 6 diff --git a/test/run-dfinity/overflow.as b/test/run-dfinity/overflow.mo similarity index 100% rename from test/run-dfinity/overflow.as rename to test/run-dfinity/overflow.mo diff --git a/test/run-dfinity/query.as b/test/run-dfinity/query.mo similarity index 100% rename from test/run-dfinity/query.as rename to test/run-dfinity/query.mo diff --git a/test/run-dfinity/reference-params.as b/test/run-dfinity/reference-params.mo similarity index 100% rename from test/run-dfinity/reference-params.as rename to test/run-dfinity/reference-params.mo diff --git a/test/run-dfinity/selftail.as b/test/run-dfinity/selftail.mo similarity index 100% rename from test/run-dfinity/selftail.as rename to test/run-dfinity/selftail.mo diff --git a/test/run-dfinity/shared-object.as b/test/run-dfinity/shared-object.mo similarity index 100% rename from test/run-dfinity/shared-object.as rename to test/run-dfinity/shared-object.mo diff --git a/test/run-dfinity/show.as b/test/run-dfinity/show.mo similarity index 100% rename from test/run-dfinity/show.as rename to test/run-dfinity/show.mo diff --git a/test/run-dfinity/simple-throw.as b/test/run-dfinity/simple-throw.mo similarity index 100% rename from test/run-dfinity/simple-throw.as rename to test/run-dfinity/simple-throw.mo diff --git a/test/run-dfinity/tailpositions.as b/test/run-dfinity/tailpositions.mo similarity index 100% rename from test/run-dfinity/tailpositions.as rename to test/run-dfinity/tailpositions.mo diff --git a/test/run-dfinity/text-iter.as b/test/run-dfinity/text-iter.mo similarity index 100% rename from test/run-dfinity/text-iter.as rename to test/run-dfinity/text-iter.mo diff --git a/test/run-dfinity/the-answer.as b/test/run-dfinity/the-answer.mo similarity index 100% rename from test/run-dfinity/the-answer.as rename to test/run-dfinity/the-answer.mo diff --git a/test/run-dfinity/tiny.as b/test/run-dfinity/tiny.mo similarity index 100% rename from test/run-dfinity/tiny.as rename to test/run-dfinity/tiny.mo diff --git a/test/run-dfinity/transpose.as b/test/run-dfinity/transpose.mo similarity index 100% rename from test/run-dfinity/transpose.as rename to test/run-dfinity/transpose.mo diff --git a/test/run-dfinity/type-lub.as b/test/run-dfinity/type-lub.mo similarity index 98% rename from test/run-dfinity/type-lub.as rename to test/run-dfinity/type-lub.mo index 49e2bf6c940..ede56742f62 100644 --- a/test/run-dfinity/type-lub.as +++ b/test/run-dfinity/type-lub.mo @@ -40,7 +40,7 @@ let variant_funcs = [ func (a : {#foo; #bar}) { switch a { case (#foo) (); case // TODO(gabor), mutable arrays let mut_arrs = [[var 42], [var 25], [77]]; // boring -// TODO(gabor), mutable fields, see fail/type-inference.as:13 +// TODO(gabor), mutable fields, see fail/type-inference.mo:13 let sh : Any = 42; let shareds = [sh, 77, [1, 2, 3]]; diff --git a/test/run-drun/Makefile b/test/run-drun/Makefile index b45cabbf006..5193a683b31 100644 --- a/test/run-drun/Makefile +++ b/test/run-drun/Makefile @@ -1,10 +1,10 @@ RUNFLAGS = -2 all: - ../run.sh $(RUNFLAGS) *.as + ../run.sh $(RUNFLAGS) *.mo accept: - ../run.sh $(RUNFLAGS) -a *.as + ../run.sh $(RUNFLAGS) -a *.mo clean: rm -rf _out diff --git a/test/run-drun/counter.as b/test/run-drun/counter.mo similarity index 100% rename from test/run-drun/counter.as rename to test/run-drun/counter.mo diff --git a/test/run-drun/hello-world-return.as b/test/run-drun/hello-world-return.mo similarity index 100% rename from test/run-drun/hello-world-return.as rename to test/run-drun/hello-world-return.mo diff --git a/test/run-drun/idl-any.as b/test/run-drun/idl-any.mo similarity index 100% rename from test/run-drun/idl-any.as rename to test/run-drun/idl-any.mo diff --git a/test/run-drun/idl-bad.as b/test/run-drun/idl-bad.mo similarity index 100% rename from test/run-drun/idl-bad.as rename to test/run-drun/idl-bad.mo diff --git a/test/run-drun/idl-field-escape.as b/test/run-drun/idl-field-escape.mo similarity index 100% rename from test/run-drun/idl-field-escape.as rename to test/run-drun/idl-field-escape.mo diff --git a/test/run-drun/idl-func.as b/test/run-drun/idl-func.mo similarity index 100% rename from test/run-drun/idl-func.as rename to test/run-drun/idl-func.mo diff --git a/test/run-drun/idl-nary.as b/test/run-drun/idl-nary.mo similarity index 100% rename from test/run-drun/idl-nary.as rename to test/run-drun/idl-nary.mo diff --git a/test/run-drun/idl-nat-int.as b/test/run-drun/idl-nat-int.mo similarity index 100% rename from test/run-drun/idl-nat-int.as rename to test/run-drun/idl-nat-int.mo diff --git a/test/run-drun/idl-option.as b/test/run-drun/idl-option.mo similarity index 100% rename from test/run-drun/idl-option.as rename to test/run-drun/idl-option.mo diff --git a/test/run-drun/idl-pair.as b/test/run-drun/idl-pair.mo similarity index 100% rename from test/run-drun/idl-pair.as rename to test/run-drun/idl-pair.mo diff --git a/test/run-drun/idl-record.as b/test/run-drun/idl-record.mo similarity index 100% rename from test/run-drun/idl-record.as rename to test/run-drun/idl-record.mo diff --git a/test/run-drun/idl-tuple.as b/test/run-drun/idl-tuple.mo similarity index 100% rename from test/run-drun/idl-tuple.as rename to test/run-drun/idl-tuple.mo diff --git a/test/run-drun/idl-unit.as b/test/run-drun/idl-unit.mo similarity index 100% rename from test/run-drun/idl-unit.as rename to test/run-drun/idl-unit.mo diff --git a/test/run-drun/idl-variant.as b/test/run-drun/idl-variant.mo similarity index 100% rename from test/run-drun/idl-variant.as rename to test/run-drun/idl-variant.mo diff --git a/test/run-drun/idl-vector.as b/test/run-drun/idl-vector.mo similarity index 100% rename from test/run-drun/idl-vector.as rename to test/run-drun/idl-vector.mo diff --git a/test/run-drun/large-array.as b/test/run-drun/large-array.mo similarity index 100% rename from test/run-drun/large-array.as rename to test/run-drun/large-array.mo diff --git a/test/run-drun/multiple-actors.as b/test/run-drun/multiple-actors.mo similarity index 100% rename from test/run-drun/multiple-actors.as rename to test/run-drun/multiple-actors.mo diff --git a/test/run-drun/ok/idl-func.tc.ok b/test/run-drun/ok/idl-func.tc.ok index 3170d1bbf34..362a324e3f9 100644 --- a/test/run-drun/ok/idl-func.tc.ok +++ b/test/run-drun/ok/idl-func.tc.ok @@ -1,8 +1,8 @@ -idl-func.as:1.33-1.37: type error, async has non-shared content type +idl-func.mo:1.33-1.37: type error, async has non-shared content type Func = shared Int -> async Func type Func = shared Int -> async Func is or contains non-shared type shared Int -> async Func -idl-func.as:1.33-1.37: type error, shared function types are non-shared. +idl-func.mo:1.33-1.37: type error, shared function types are non-shared. (This is a limitation of the current version.) diff --git a/test/run-drun/ok/multiple-actors.wasm.stderr.ok b/test/run-drun/ok/multiple-actors.wasm.stderr.ok index a4e05b33051..1e157831f17 100644 --- a/test/run-drun/ok/multiple-actors.wasm.stderr.ok +++ b/test/run-drun/ok/multiple-actors.wasm.stderr.ok @@ -1,4 +1,4 @@ -multiple-actors.as:1.1-1.12: type error, multiple actors in program; there must be at most one actor declaration in a program +multiple-actors.mo:1.1-1.12: type error, multiple actors in program; there must be at most one actor declaration in a program (This is a limitation of the current version.) -multiple-actors.as:3.1-3.12: type error, multiple actors in program; there must be at most one actor declaration in a program +multiple-actors.mo:3.1-3.12: type error, multiple actors in program; there must be at most one actor declaration in a program (This is a limitation of the current version.) diff --git a/test/run-drun/ok/unsupported.tc.ok b/test/run-drun/ok/unsupported.tc.ok index 4bd2f18387b..15fb6b8cfa8 100644 --- a/test/run-drun/ok/unsupported.tc.ok +++ b/test/run-drun/ok/unsupported.tc.ok @@ -1,54 +1,54 @@ -unsupported.as:6.28-6.39: type error, shared function has non-shared parameter type +unsupported.mo:6.28-6.39: type error, shared function has non-shared parameter type actor {} type actor {} is or contains non-shared type actor {} -unsupported.as:6.28-6.39: type error, actor types are non-shared. +unsupported.mo:6.28-6.39: type error, actor types are non-shared. (This is a limitation of the current version.) -unsupported.as:8.31-8.53: type error, shared function has non-shared parameter type +unsupported.mo:8.31-8.53: type error, shared function has non-shared parameter type shared () -> async () type shared () -> async () is or contains non-shared type shared () -> async () -unsupported.as:8.31-8.53: type error, shared function types are non-shared. +unsupported.mo:8.31-8.53: type error, shared function types are non-shared. (This is a limitation of the current version.) -unsupported.as:19.19-19.21: type error, shared, async function must be called within an await expression +unsupported.mo:19.19-19.21: type error, shared, async function must be called within an await expression (This is a limitation of the current version.) -unsupported.as:23.16-23.18: type error, calling a shared function not yet supported +unsupported.mo:23.16-23.18: type error, calling a shared function not yet supported (This is a limitation of the current version.) -unsupported.as:28.8-28.9: type error, argument to await must be a call expression +unsupported.mo:28.8-28.9: type error, argument to await must be a call expression (This is a limitation of the current version.) -unsupported.as:32.17-32.29: type error, unsupported async block +unsupported.mo:32.17-32.29: type error, unsupported async block (This is a limitation of the current version.) -unsupported.as:4.5-4.41: type error, a shared function cannot be private +unsupported.mo:4.5-4.41: type error, a shared function cannot be private (This is a limitation of the current version.) -unsupported.as:38.26-38.29: type error, a shared function is only allowed as a public field of an actor +unsupported.mo:38.26-38.29: type error, a shared function is only allowed as a public field of an actor (This is a limitation of the current version.) -unsupported.as:41.10-41.18: type error, unsupported async block +unsupported.mo:41.10-41.18: type error, unsupported async block (This is a limitation of the current version.) -unsupported.as:46.31-46.48: type error, shared function has non-shared parameter type +unsupported.mo:46.31-46.48: type error, shared function has non-shared parameter type shared () -> () type shared () -> () is or contains non-shared type shared () -> () -unsupported.as:46.31-46.48: type error, shared function types are non-shared. +unsupported.mo:46.31-46.48: type error, shared function types are non-shared. (This is a limitation of the current version.) -unsupported.as:51.31-51.41: type error, shared function has non-shared parameter type +unsupported.mo:51.31-51.41: type error, shared function has non-shared parameter type actor {} type actor {} is or contains non-shared type actor {} -unsupported.as:51.31-51.41: type error, actor types are non-shared. +unsupported.mo:51.31-51.41: type error, actor types are non-shared. (This is a limitation of the current version.) -unsupported.as:62.3-62.35: type error, actor classes are not supported; use an actor declaration instead +unsupported.mo:62.3-62.35: type error, actor classes are not supported; use an actor declaration instead (This is a limitation of the current version.) -unsupported.as:66.45-66.53: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program +unsupported.mo:66.45-66.53: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program (This is a limitation of the current version.) -unsupported.as:70.29-70.37: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program +unsupported.mo:70.29-70.37: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program (This is a limitation of the current version.) -unsupported.as:76.34-76.37: type error, freestanding async expression not yet supported +unsupported.mo:76.34-76.37: type error, freestanding async expression not yet supported (This is a limitation of the current version.) diff --git a/test/run-drun/print-from-init.as b/test/run-drun/print-from-init.mo similarity index 100% rename from test/run-drun/print-from-init.as rename to test/run-drun/print-from-init.mo diff --git a/test/run-drun/query.as b/test/run-drun/query.mo similarity index 100% rename from test/run-drun/query.as rename to test/run-drun/query.mo diff --git a/test/run-drun/reject.as b/test/run-drun/reject.mo similarity index 100% rename from test/run-drun/reject.as rename to test/run-drun/reject.mo diff --git a/test/run-drun/unsupported.as b/test/run-drun/unsupported.mo similarity index 100% rename from test/run-drun/unsupported.as rename to test/run-drun/unsupported.mo diff --git a/test/run-release/Makefile b/test/run-release/Makefile index 135924dae80..b81927e20ed 100644 --- a/test/run-release/Makefile +++ b/test/run-release/Makefile @@ -1,10 +1,10 @@ RUNFLAGS = -r all: - ../run.sh $(RUNFLAGS) *.as + ../run.sh $(RUNFLAGS) *.mo accept: - ../run.sh $(RUNFLAGS) -a *.as + ../run.sh $(RUNFLAGS) -a *.mo clean: rm -rf _out diff --git a/test/run-release/debug.as b/test/run-release/debug.mo similarity index 100% rename from test/run-release/debug.as rename to test/run-release/debug.mo diff --git a/test/run.sh b/test/run.sh index 043ffb5e074..9cd4c6eff14 100755 --- a/test/run.sh +++ b/test/run.sh @@ -2,7 +2,7 @@ # A simple test runner. Synopsis: # -# ./run.sh foo.as [bar.as ..] +# ./run.sh foo.mo [bar.mo ..] # # Options: # @@ -10,7 +10,7 @@ # -1: Use Ancient API # -2: Use IC API # -s: Be silent in sunny-day execution -# -i: Only check as to idl generation +# -i: Only check mo to idl generation # -r: Activate release mode (eliminate `debug` blocks) # @@ -23,11 +23,11 @@ ACCEPT=no API=wasm IDL=no RELEASE=no -EXTRA_ASC_FLAGS= -ASC=${ASC:-$(realpath $(dirname $0)/../src/asc)} -AS_LD=${AS_LD:-$(realpath $(dirname $0)/../src/as-ld)} +EXTRA_MOC_FLAGS= +MOC=${MOC:-$(realpath $(dirname $0)/../src/moc)} +MO_LD=${MO_LD:-$(realpath $(dirname $0)/../src/mo-ld)} DIDC=${DIDC:-$(realpath $(dirname $0)/../src/didc)} -export AS_LD +export MO_LD WASM=${WASM:-wasm} DVM_WRAPPER=$(realpath $(dirname $0)/dvm.sh) DRUN_WRAPPER=$(realpath $(dirname $0)/drun-wrapper.sh) @@ -56,9 +56,9 @@ while getopts "a12sir" o; do esac done -if [ $API = "wasm" ]; then EXTRA_ASC_FLAGS=-no-system-api; fi -if [ $API = "ancient" ]; then EXTRA_ASC_FLAGS=-ancient-system-api; fi -if [ $RELEASE = "yes" ]; then ASC_FLAGS=--release; fi +if [ $API = "wasm" ]; then EXTRA_MOC_FLAGS=-no-system-api; fi +if [ $API = "ancient" ]; then EXTRA_MOC_FLAGS=-ancient-system-api; fi +if [ $RELEASE = "yes" ]; then MOC_FLAGS=--release; fi shift $((OPTIND-1)) @@ -95,8 +95,8 @@ do continue fi - if [ ${file: -3} == ".as" ] - then base=$(basename $file .as) + if [ ${file: -3} == ".mo" ] + then base=$(basename $file .mo) elif [ ${file: -3} == ".sh" ] then base=$(basename $file .sh) elif [ ${file: -4} == ".wat" ] @@ -104,12 +104,12 @@ do elif [ ${file: -4} == ".did" ] then base=$(basename $file .did) else - echo "Unknown file extension in $file, expected .as, .sh, .wat or .did"; exit 1 + echo "Unknown file extension in $file, expected .mo, .sh, .wat or .did"; exit 1 failures=yes continue fi - # We run all commands in the directory of the .as file, + # We run all commands in the directory of the .mo file, # so that no paths leak into the output pushd $(dirname $file) >/dev/null @@ -129,11 +129,11 @@ do # First run all the steps, and remember what to diff diff_files= - if [ ${file: -3} == ".as" ] + if [ ${file: -3} == ".mo" ] then # Typecheck $ECHO -n " [tc]" - $ASC $ASC_FLAGS $EXTRA_ASC_FLAGS --check $base.as > $out/$base.tc 2>&1 + $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS --check $base.mo > $out/$base.tc 2>&1 tc_succeeded=$? normalize $out/$base.tc diff_files="$diff_files $base.tc" @@ -143,7 +143,7 @@ do if [ $IDL = 'yes' ] then $ECHO -n " [idl]" - $ASC $ASC_FLAGS $EXTRA_ASC_FLAGS --idl $base.as -o $out/$base.did 2> $out/$base.idl.stderr + $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS --idl $base.mo -o $out/$base.did 2> $out/$base.idl.stderr idl_succeeded=$? normalize $out/$base.did normalize $out/$base.idl.stderr @@ -159,13 +159,13 @@ do then # Interpret $ECHO -n " [run]" - $ASC $ASC_FLAGS $EXTRA_ASC_FLAGS -r $base.as > $out/$base.run 2>&1 + $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS -r $base.mo > $out/$base.run 2>&1 normalize $out/$base.run diff_files="$diff_files $base.run" # Interpret IR without lowering $ECHO -n " [run-ir]" - $ASC $ASC_FLAGS $EXTRA_ASC_FLAGS -r -iR -no-async -no-await $base.as > $out/$base.run-ir 2>&1 + $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS -r -iR -no-async -no-await $base.mo > $out/$base.run-ir 2>&1 normalize $out/$base.run-ir diff_files="$diff_files $base.run-ir" @@ -175,7 +175,7 @@ do # Interpret IR with lowering $ECHO -n " [run-low]" - $ASC $ASC_FLAGS $EXTRA_ASC_FLAGS -r -iR $base.as > $out/$base.run-low 2>&1 + $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS -r -iR $base.mo > $out/$base.run-low 2>&1 normalize $out/$base.run-low diff_files="$diff_files $base.run-low" @@ -187,18 +187,18 @@ do # Compile $ECHO -n " [wasm]" - $ASC $ASC_FLAGS $EXTRA_ASC_FLAGS --map -c $base.as -o $out/$base.wasm 2> $out/$base.wasm.stderr + $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS --map -c $base.mo -o $out/$base.wasm 2> $out/$base.wasm.stderr normalize $out/$base.wasm.stderr diff_files="$diff_files $base.wasm.stderr" # Check filecheck if [ "$SKIP_RUNNING" != yes ] then - if grep -F -q CHECK $base.as + if grep -F -q CHECK $base.mo then $ECHO -n " [FileCheck]" wasm2wat --no-check --enable-multi-value $out/$base.wasm > $out/$base.wat - cat $out/$base.wat | FileCheck $base.as > $out/$base.filecheck 2>&1 + cat $out/$base.wat | FileCheck $base.mo > $out/$base.filecheck 2>&1 diff_files="$diff_files $base.filecheck" fi fi @@ -211,13 +211,13 @@ do if [ $API = ancient ] then $ECHO -n " [dvm]" - $DVM_WRAPPER $out/$base.wasm $base.as > $out/$base.dvm-run 2>&1 + $DVM_WRAPPER $out/$base.wasm $base.mo > $out/$base.dvm-run 2>&1 normalize $out/$base.dvm-run diff_files="$diff_files $base.dvm-run" elif [ $API = ic ] then $ECHO -n " [drun]" - $DRUN_WRAPPER $out/$base.wasm $base.as > $out/$base.drun-run 2>&1 + $DRUN_WRAPPER $out/$base.wasm $base.mo > $out/$base.drun-run 2>&1 normalize $out/$base.drun-run diff_files="$diff_files $base.drun-run" else @@ -241,11 +241,11 @@ do elif [ ${file: -4} == ".wat" ] then # The file is a .wat file, so we are expected to test linking - $ECHO -n " [as-ld]" + $ECHO -n " [mo-ld]" rm -f $out/$base.{base,lib,linked}.{wasm,wat,o} make --quiet $out/$base.{base,lib}.wasm - $AS_LD -b $out/$base.base.wasm -l $out/$base.lib.wasm -o $out/$base.linked.wasm > $out/$base.as-ld 2>&1 - diff_files="$diff_files $base.as-ld" + $MO_LD -b $out/$base.base.wasm -l $out/$base.lib.wasm -o $out/$base.linked.wasm > $out/$base.mo-ld 2>&1 + diff_files="$diff_files $base.mo-ld" if [ -e $out/$base.linked.wasm ] then diff --git a/test/run/AST-56.as b/test/run/AST-56.mo similarity index 100% rename from test/run/AST-56.as rename to test/run/AST-56.mo diff --git a/test/run/Makefile b/test/run/Makefile index ca32260888f..733076dc3a2 100644 --- a/test/run/Makefile +++ b/test/run/Makefile @@ -1,10 +1,10 @@ RUNFLAGS = all: - ../run.sh $(RUNFLAGS) *.as + ../run.sh $(RUNFLAGS) *.mo accept: - ../run.sh $(RUNFLAGS) -a *.as + ../run.sh $(RUNFLAGS) -a *.mo clean: rm -rf _out diff --git a/test/run/TRAP-write-before-init.as b/test/run/TRAP-write-before-init.mo similarity index 100% rename from test/run/TRAP-write-before-init.as rename to test/run/TRAP-write-before-init.mo diff --git a/test/run/array-bounds.as b/test/run/array-bounds.mo similarity index 100% rename from test/run/array-bounds.as rename to test/run/array-bounds.mo diff --git a/test/run/array-gen.as b/test/run/array-gen.mo similarity index 100% rename from test/run/array-gen.as rename to test/run/array-gen.mo diff --git a/test/run/array.as b/test/run/array.mo similarity index 100% rename from test/run/array.as rename to test/run/array.mo diff --git a/test/run/assert42.as b/test/run/assert42.mo similarity index 100% rename from test/run/assert42.as rename to test/run/assert42.mo diff --git a/test/run/assertFalse.as b/test/run/assertFalse.mo similarity index 100% rename from test/run/assertFalse.as rename to test/run/assertFalse.mo diff --git a/test/run/assertTrue.as b/test/run/assertTrue.mo similarity index 100% rename from test/run/assertTrue.as rename to test/run/assertTrue.mo diff --git a/test/run/bit-ops.as b/test/run/bit-ops.mo similarity index 100% rename from test/run/bit-ops.as rename to test/run/bit-ops.mo diff --git a/test/run/call-none.as b/test/run/call-none.mo similarity index 100% rename from test/run/call-none.as rename to test/run/call-none.mo diff --git a/test/run/capture-mut.as b/test/run/capture-mut.mo similarity index 100% rename from test/run/capture-mut.as rename to test/run/capture-mut.mo diff --git a/test/run/char-pats.as b/test/run/char-pats.mo similarity index 100% rename from test/run/char-pats.as rename to test/run/char-pats.mo diff --git a/test/run/closures.as b/test/run/closures.mo similarity index 100% rename from test/run/closures.as rename to test/run/closures.mo diff --git a/test/run/concat.as b/test/run/concat.mo similarity index 100% rename from test/run/concat.as rename to test/run/concat.mo diff --git a/test/run/conversions.as b/test/run/conversions.mo similarity index 100% rename from test/run/conversions.as rename to test/run/conversions.mo diff --git a/test/run/coverage.as b/test/run/coverage.mo similarity index 100% rename from test/run/coverage.as rename to test/run/coverage.mo diff --git a/test/run/debug.as b/test/run/debug.mo similarity index 100% rename from test/run/debug.as rename to test/run/debug.mo diff --git a/test/run/eager-and-lazy.as b/test/run/eager-and-lazy.mo similarity index 100% rename from test/run/eager-and-lazy.as rename to test/run/eager-and-lazy.mo diff --git a/test/run/empty-tup-args.as b/test/run/empty-tup-args.mo similarity index 100% rename from test/run/empty-tup-args.as rename to test/run/empty-tup-args.mo diff --git a/test/run/empty.as b/test/run/empty.mo similarity index 100% rename from test/run/empty.as rename to test/run/empty.mo diff --git a/test/run/f-bounds.as b/test/run/f-bounds.mo similarity index 100% rename from test/run/f-bounds.as rename to test/run/f-bounds.mo diff --git a/test/run/fac.as b/test/run/fac.mo similarity index 100% rename from test/run/fac.as rename to test/run/fac.mo diff --git a/test/run/fib.as b/test/run/fib.mo similarity index 100% rename from test/run/fib.as rename to test/run/fib.mo diff --git a/test/run/for.as b/test/run/for.mo similarity index 100% rename from test/run/for.as rename to test/run/for.mo diff --git a/test/run/hashes.as b/test/run/hashes.mo similarity index 100% rename from test/run/hashes.as rename to test/run/hashes.mo diff --git a/test/run/hoare.as b/test/run/hoare.mo similarity index 100% rename from test/run/hoare.as rename to test/run/hoare.mo diff --git a/test/run/idlHash.as b/test/run/idlHash.mo similarity index 100% rename from test/run/idlHash.as rename to test/run/idlHash.mo diff --git a/test/run/import-module.as b/test/run/import-module.mo similarity index 67% rename from test/run/import-module.as rename to test/run/import-module.mo index 1b26b471a87..f8f438de04c 100644 --- a/test/run/import-module.as +++ b/test/run/import-module.mo @@ -1,3 +1,3 @@ -let L = import "lib/ListM.as"; +let L = import "lib/ListM.mo"; type stack = L.List; let s = L.cons(1, L.nil()); diff --git a/test/run/import.as b/test/run/import.as deleted file mode 100644 index dcc1c4d69dc..00000000000 --- a/test/run/import.as +++ /dev/null @@ -1,2 +0,0 @@ -assert ((import "lib/hello-string.as") == "Hello!"); -assert ((import "lib/dir") == "Hello!"); diff --git a/test/run/import.mo b/test/run/import.mo new file mode 100644 index 00000000000..2c15c064d2a --- /dev/null +++ b/test/run/import.mo @@ -0,0 +1,2 @@ +assert ((import "lib/hello-string.mo") == "Hello!"); +assert ((import "lib/dir") == "Hello!"); diff --git a/test/run/ir-litpat-subtype.as b/test/run/ir-litpat-subtype.mo similarity index 100% rename from test/run/ir-litpat-subtype.as rename to test/run/ir-litpat-subtype.mo diff --git a/test/run/ir-pat-subtype.as b/test/run/ir-pat-subtype.mo similarity index 100% rename from test/run/ir-pat-subtype.as rename to test/run/ir-pat-subtype.mo diff --git a/test/run/issue120.as b/test/run/issue120.mo similarity index 100% rename from test/run/issue120.as rename to test/run/issue120.mo diff --git a/test/run/issue122.as b/test/run/issue122.mo similarity index 100% rename from test/run/issue122.as rename to test/run/issue122.mo diff --git a/test/run/issue129.as b/test/run/issue129.mo similarity index 95% rename from test/run/issue129.as rename to test/run/issue129.mo index 8c5e5091885..83ecf471097 100644 --- a/test/run/issue129.as +++ b/test/run/issue129.mo @@ -1,4 +1,4 @@ -// status.as +// status.mo type Status = { failed_ : Nat; passed_ : Nat; diff --git a/test/run/issue135.as b/test/run/issue135.mo similarity index 100% rename from test/run/issue135.as rename to test/run/issue135.mo diff --git a/test/run/issue150.as b/test/run/issue150.mo similarity index 100% rename from test/run/issue150.as rename to test/run/issue150.mo diff --git a/test/run/issue442.as b/test/run/issue442.mo similarity index 100% rename from test/run/issue442.as rename to test/run/issue442.mo diff --git a/test/run/issue537.as b/test/run/issue537.mo similarity index 100% rename from test/run/issue537.as rename to test/run/issue537.mo diff --git a/test/run/issue551.as b/test/run/issue551.mo similarity index 100% rename from test/run/issue551.as rename to test/run/issue551.mo diff --git a/test/run/issue83.as b/test/run/issue83.mo similarity index 100% rename from test/run/issue83.as rename to test/run/issue83.mo diff --git a/test/run/iter-null.as b/test/run/iter-null.mo similarity index 100% rename from test/run/iter-null.as rename to test/run/iter-null.mo diff --git a/test/run/large-mem.as b/test/run/large-mem.mo similarity index 100% rename from test/run/large-mem.as rename to test/run/large-mem.mo diff --git a/test/run/large-tuple.as b/test/run/large-tuple.mo similarity index 100% rename from test/run/large-tuple.as rename to test/run/large-tuple.mo diff --git a/test/run/last-dec-val.as b/test/run/last-dec-val.mo similarity index 100% rename from test/run/last-dec-val.as rename to test/run/last-dec-val.mo diff --git a/test/run/let.as b/test/run/let.mo similarity index 100% rename from test/run/let.as rename to test/run/let.mo diff --git a/test/run/let_fun.as b/test/run/let_fun.mo similarity index 100% rename from test/run/let_fun.as rename to test/run/let_fun.mo diff --git a/test/run/lib/ListM.as b/test/run/lib/ListM.mo similarity index 100% rename from test/run/lib/ListM.as rename to test/run/lib/ListM.mo diff --git a/test/run/lib/dir/lib.as b/test/run/lib/dir/lib.mo similarity index 100% rename from test/run/lib/dir/lib.as rename to test/run/lib/dir/lib.mo diff --git a/test/run/lib/hello-string.as b/test/run/lib/hello-string.mo similarity index 100% rename from test/run/lib/hello-string.as rename to test/run/lib/hello-string.mo diff --git a/test/run/literals.as b/test/run/literals.mo similarity index 100% rename from test/run/literals.as rename to test/run/literals.mo diff --git a/test/run/menhir-bug.as b/test/run/menhir-bug.mo similarity index 100% rename from test/run/menhir-bug.as rename to test/run/menhir-bug.mo diff --git a/test/run/module1.as b/test/run/module1.mo similarity index 100% rename from test/run/module1.as rename to test/run/module1.mo diff --git a/test/run/module2.as b/test/run/module2.mo similarity index 100% rename from test/run/module2.as rename to test/run/module2.mo diff --git a/test/run/module3.as b/test/run/module3.mo similarity index 100% rename from test/run/module3.as rename to test/run/module3.mo diff --git a/test/run/modulus.as b/test/run/modulus.mo similarity index 100% rename from test/run/modulus.as rename to test/run/modulus.mo diff --git a/test/run/mut-field-bound.as b/test/run/mut-field-bound.mo similarity index 100% rename from test/run/mut-field-bound.as rename to test/run/mut-field-bound.mo diff --git a/test/run/mutrec.as b/test/run/mutrec.mo similarity index 100% rename from test/run/mutrec.as rename to test/run/mutrec.mo diff --git a/test/run/mutrec2.as b/test/run/mutrec2.mo similarity index 100% rename from test/run/mutrec2.as rename to test/run/mutrec2.mo diff --git a/test/run/mutrec3.as b/test/run/mutrec3.mo similarity index 100% rename from test/run/mutrec3.as rename to test/run/mutrec3.mo diff --git a/test/run/n-ary.as b/test/run/n-ary.mo similarity index 100% rename from test/run/n-ary.as rename to test/run/n-ary.mo diff --git a/test/run/neg-boundary.as b/test/run/neg-boundary.mo similarity index 100% rename from test/run/neg-boundary.as rename to test/run/neg-boundary.mo diff --git a/test/run/nested-class-rec.as b/test/run/nested-class-rec.mo similarity index 100% rename from test/run/nested-class-rec.as rename to test/run/nested-class-rec.mo diff --git a/test/run/nested-eager.as b/test/run/nested-eager.mo similarity index 100% rename from test/run/nested-eager.as rename to test/run/nested-eager.mo diff --git a/test/run/nested-lexpr.as b/test/run/nested-lexpr.mo similarity index 100% rename from test/run/nested-lexpr.as rename to test/run/nested-lexpr.mo diff --git a/test/run/numeric-ops.as b/test/run/numeric-ops.mo similarity index 100% rename from test/run/numeric-ops.as rename to test/run/numeric-ops.mo diff --git a/test/run/objects-order.as b/test/run/objects-order.mo similarity index 100% rename from test/run/objects-order.as rename to test/run/objects-order.mo diff --git a/test/run/objects1.as b/test/run/objects1.mo similarity index 100% rename from test/run/objects1.as rename to test/run/objects1.mo diff --git a/test/run/objects2.as b/test/run/objects2.mo similarity index 100% rename from test/run/objects2.as rename to test/run/objects2.mo diff --git a/test/run/objects3.as b/test/run/objects3.mo similarity index 100% rename from test/run/objects3.as rename to test/run/objects3.mo diff --git a/test/run/objects4.as b/test/run/objects4.mo similarity index 100% rename from test/run/objects4.as rename to test/run/objects4.mo diff --git a/test/run/objects5.as b/test/run/objects5.mo similarity index 100% rename from test/run/objects5.as rename to test/run/objects5.mo diff --git a/test/run/ok/TRAP-write-before-init.tc.ok b/test/run/ok/TRAP-write-before-init.tc.ok index 4981a9261e8..12476bafe5f 100644 --- a/test/run/ok/TRAP-write-before-init.tc.ok +++ b/test/run/ok/TRAP-write-before-init.tc.ok @@ -1 +1 @@ -TRAP-write-before-init.as:1.1-1.7: definedness error, cannot use x before x has been defined +TRAP-write-before-init.mo:1.1-1.7: definedness error, cannot use x before x has been defined diff --git a/test/run/ok/array-bounds.run-ir.ok b/test/run/ok/array-bounds.run-ir.ok index 62abb269136..a0e3effa7e6 100644 --- a/test/run/ok/array-bounds.run-ir.ok +++ b/test/run/ok/array-bounds.run-ir.ok @@ -1 +1 @@ -array-bounds.as:5.15-5.19: execution error, index out of bounds +array-bounds.mo:5.15-5.19: execution error, index out of bounds diff --git a/test/run/ok/array-bounds.run-low.ok b/test/run/ok/array-bounds.run-low.ok index 62abb269136..a0e3effa7e6 100644 --- a/test/run/ok/array-bounds.run-low.ok +++ b/test/run/ok/array-bounds.run-low.ok @@ -1 +1 @@ -array-bounds.as:5.15-5.19: execution error, index out of bounds +array-bounds.mo:5.15-5.19: execution error, index out of bounds diff --git a/test/run/ok/array-bounds.run.ok b/test/run/ok/array-bounds.run.ok index 62abb269136..a0e3effa7e6 100644 --- a/test/run/ok/array-bounds.run.ok +++ b/test/run/ok/array-bounds.run.ok @@ -1 +1 @@ -array-bounds.as:5.15-5.19: execution error, index out of bounds +array-bounds.mo:5.15-5.19: execution error, index out of bounds diff --git a/test/run/ok/assertFalse.run-ir.ok b/test/run/ok/assertFalse.run-ir.ok index 1ade64fd09c..41b09a76d68 100644 --- a/test/run/ok/assertFalse.run-ir.ok +++ b/test/run/ok/assertFalse.run-ir.ok @@ -1 +1 @@ -assertFalse.as:1.1-1.14: execution error, assertion failure +assertFalse.mo:1.1-1.14: execution error, assertion failure diff --git a/test/run/ok/assertFalse.run-low.ok b/test/run/ok/assertFalse.run-low.ok index 1ade64fd09c..41b09a76d68 100644 --- a/test/run/ok/assertFalse.run-low.ok +++ b/test/run/ok/assertFalse.run-low.ok @@ -1 +1 @@ -assertFalse.as:1.1-1.14: execution error, assertion failure +assertFalse.mo:1.1-1.14: execution error, assertion failure diff --git a/test/run/ok/assertFalse.run.ok b/test/run/ok/assertFalse.run.ok index 1ade64fd09c..41b09a76d68 100644 --- a/test/run/ok/assertFalse.run.ok +++ b/test/run/ok/assertFalse.run.ok @@ -1 +1 @@ -assertFalse.as:1.1-1.14: execution error, assertion failure +assertFalse.mo:1.1-1.14: execution error, assertion failure diff --git a/test/run/ok/coverage.idl.stderr.ok b/test/run/ok/coverage.idl.stderr.ok index 9749151ddcd..6cd2a586f70 100644 --- a/test/run/ok/coverage.idl.stderr.ok +++ b/test/run/ok/coverage.idl.stderr.ok @@ -1,101 +1,101 @@ -coverage.as:5.13-5.14: warning, this pattern is never matched -coverage.as:7.13-7.14: warning, this pattern is never matched -coverage.as:8.13-8.14: warning, this pattern is never matched -coverage.as:16.16-16.17: warning, this pattern is never matched -coverage.as:18.16-18.17: warning, this pattern is never matched -coverage.as:19.17-19.18: warning, this pattern is never matched -coverage.as:24.25-24.34: warning, this case is never reached -coverage.as:27.25-27.34: warning, this case is never reached -coverage.as:28.25-28.34: warning, this case is never reached -coverage.as:29.25-29.34: warning, this case is never reached -coverage.as:30.25-30.34: warning, this case is never reached -coverage.as:31.25-31.34: warning, this case is never reached -coverage.as:32.43-32.44: warning, this pattern is never matched -coverage.as:33.35-33.49: warning, this case is never reached -coverage.as:34.42-34.51: warning, this case is never reached -coverage.as:37.51-37.73: warning, this case is never reached -coverage.as:38.39-38.54: warning, this case is never reached -coverage.as:39.56-39.65: warning, this case is never reached -coverage.as:40.49-40.58: warning, this case is never reached -coverage.as:46.58-46.72: warning, this case is never reached -coverage.as:61.22-61.31: warning, this case is never reached -coverage.as:62.28-62.37: warning, this case is never reached -coverage.as:63.49-63.50: warning, this pattern is never matched -coverage.as:64.48-64.49: warning, this pattern is never matched -coverage.as:65.41-65.42: warning, this pattern is never matched -coverage.as:66.40-66.41: warning, this pattern is never matched -coverage.as:77.5-77.55: warning, this case is never reached -coverage.as:109.3-109.52: warning, this case is never reached -coverage.as:4.7-4.8: warning, this pattern consuming type +coverage.mo:5.13-5.14: warning, this pattern is never matched +coverage.mo:7.13-7.14: warning, this pattern is never matched +coverage.mo:8.13-8.14: warning, this pattern is never matched +coverage.mo:16.16-16.17: warning, this pattern is never matched +coverage.mo:18.16-18.17: warning, this pattern is never matched +coverage.mo:19.17-19.18: warning, this pattern is never matched +coverage.mo:24.25-24.34: warning, this case is never reached +coverage.mo:27.25-27.34: warning, this case is never reached +coverage.mo:28.25-28.34: warning, this case is never reached +coverage.mo:29.25-29.34: warning, this case is never reached +coverage.mo:30.25-30.34: warning, this case is never reached +coverage.mo:31.25-31.34: warning, this case is never reached +coverage.mo:32.43-32.44: warning, this pattern is never matched +coverage.mo:33.35-33.49: warning, this case is never reached +coverage.mo:34.42-34.51: warning, this case is never reached +coverage.mo:37.51-37.73: warning, this case is never reached +coverage.mo:38.39-38.54: warning, this case is never reached +coverage.mo:39.56-39.65: warning, this case is never reached +coverage.mo:40.49-40.58: warning, this case is never reached +coverage.mo:46.58-46.72: warning, this case is never reached +coverage.mo:61.22-61.31: warning, this case is never reached +coverage.mo:62.28-62.37: warning, this case is never reached +coverage.mo:63.49-63.50: warning, this pattern is never matched +coverage.mo:64.48-64.49: warning, this pattern is never matched +coverage.mo:65.41-65.42: warning, this pattern is never matched +coverage.mo:66.40-66.41: warning, this pattern is never matched +coverage.mo:77.5-77.55: warning, this case is never reached +coverage.mo:109.3-109.52: warning, this case is never reached +coverage.mo:4.7-4.8: warning, this pattern consuming type Nat does not cover value 0 or 1 or _ -coverage.as:5.7-5.15: warning, this pattern consuming type +coverage.mo:5.7-5.15: warning, this pattern consuming type Nat does not cover value 0 or 1 or _ -coverage.as:9.7-9.9: warning, this pattern consuming type +coverage.mo:9.7-9.9: warning, this pattern consuming type ?Nat does not cover value null -coverage.as:10.7-10.9: warning, this pattern consuming type +coverage.mo:10.7-10.9: warning, this pattern consuming type ?Nat does not cover value null -coverage.as:11.7-11.9: warning, this pattern consuming type +coverage.mo:11.7-11.9: warning, this pattern consuming type ?Nat does not cover value ?(0 or 1 or _) or null -coverage.as:15.10-15.13: warning, this pattern consuming type +coverage.mo:15.10-15.13: warning, this pattern consuming type Nat does not cover value 0 or 1 or _ -coverage.as:16.10-16.18: warning, this pattern consuming type +coverage.mo:16.10-16.18: warning, this pattern consuming type Nat does not cover value 0 or 1 or _ -coverage.as:23.3-23.25: warning, the cases in this switch over type +coverage.mo:23.3-23.25: warning, the cases in this switch over type Nat do not cover value 0 or 1 or _ -coverage.as:24.3-24.36: warning, the cases in this switch over type +coverage.mo:24.3-24.36: warning, the cases in this switch over type Nat do not cover value 0 or 1 or _ -coverage.as:32.3-32.50: warning, the cases in this switch over type +coverage.mo:32.3-32.50: warning, the cases in this switch over type Nat do not cover value 0 or 1 or _ -coverage.as:35.3-35.51: warning, the cases in this switch over type +coverage.mo:35.3-35.51: warning, the cases in this switch over type (Nat, Nat) do not cover value (1 or 2 or _, 1 or 2 or _) -coverage.as:41.3-41.61: warning, the cases in this switch over type +coverage.mo:41.3-41.61: warning, the cases in this switch over type {a : Nat; b : Nat} do not cover value {a = 1 or 2 or _; b = 1 or 2 or _) -coverage.as:45.3-45.74: warning, the cases in this switch over type +coverage.mo:45.3-45.74: warning, the cases in this switch over type {#a : Nat; #b : Nat} do not cover value #b(0 or 1 or _) -coverage.as:47.3-47.58: warning, the cases in this switch over type +coverage.mo:47.3-47.58: warning, the cases in this switch over type {#a : Nat; #b : Nat} do not cover value #b(_) -coverage.as:48.3-48.58: warning, the cases in this switch over type +coverage.mo:48.3-48.58: warning, the cases in this switch over type {#a : Nat; #b : Nat} do not cover value #a(_) -coverage.as:49.3-49.62: warning, the cases in this switch over type +coverage.mo:49.3-49.62: warning, the cases in this switch over type {#a : Nat; #b : Nat; #c} do not cover value #a(_) or #c -coverage.as:50.3-50.42: warning, the cases in this switch over type +coverage.mo:50.3-50.42: warning, the cases in this switch over type {#a : Nat; #b : Nat} do not cover value _ -coverage.as:74.3-78.4: warning, the cases in this switch over type +coverage.mo:74.3-78.4: warning, the cases in this switch over type {#branch : (Tree, Tree); #leaf : Int} do not cover value #leaf(0 or 1 or _) diff --git a/test/run/ok/coverage.run-ir.ok b/test/run/ok/coverage.run-ir.ok index 9749151ddcd..6cd2a586f70 100644 --- a/test/run/ok/coverage.run-ir.ok +++ b/test/run/ok/coverage.run-ir.ok @@ -1,101 +1,101 @@ -coverage.as:5.13-5.14: warning, this pattern is never matched -coverage.as:7.13-7.14: warning, this pattern is never matched -coverage.as:8.13-8.14: warning, this pattern is never matched -coverage.as:16.16-16.17: warning, this pattern is never matched -coverage.as:18.16-18.17: warning, this pattern is never matched -coverage.as:19.17-19.18: warning, this pattern is never matched -coverage.as:24.25-24.34: warning, this case is never reached -coverage.as:27.25-27.34: warning, this case is never reached -coverage.as:28.25-28.34: warning, this case is never reached -coverage.as:29.25-29.34: warning, this case is never reached -coverage.as:30.25-30.34: warning, this case is never reached -coverage.as:31.25-31.34: warning, this case is never reached -coverage.as:32.43-32.44: warning, this pattern is never matched -coverage.as:33.35-33.49: warning, this case is never reached -coverage.as:34.42-34.51: warning, this case is never reached -coverage.as:37.51-37.73: warning, this case is never reached -coverage.as:38.39-38.54: warning, this case is never reached -coverage.as:39.56-39.65: warning, this case is never reached -coverage.as:40.49-40.58: warning, this case is never reached -coverage.as:46.58-46.72: warning, this case is never reached -coverage.as:61.22-61.31: warning, this case is never reached -coverage.as:62.28-62.37: warning, this case is never reached -coverage.as:63.49-63.50: warning, this pattern is never matched -coverage.as:64.48-64.49: warning, this pattern is never matched -coverage.as:65.41-65.42: warning, this pattern is never matched -coverage.as:66.40-66.41: warning, this pattern is never matched -coverage.as:77.5-77.55: warning, this case is never reached -coverage.as:109.3-109.52: warning, this case is never reached -coverage.as:4.7-4.8: warning, this pattern consuming type +coverage.mo:5.13-5.14: warning, this pattern is never matched +coverage.mo:7.13-7.14: warning, this pattern is never matched +coverage.mo:8.13-8.14: warning, this pattern is never matched +coverage.mo:16.16-16.17: warning, this pattern is never matched +coverage.mo:18.16-18.17: warning, this pattern is never matched +coverage.mo:19.17-19.18: warning, this pattern is never matched +coverage.mo:24.25-24.34: warning, this case is never reached +coverage.mo:27.25-27.34: warning, this case is never reached +coverage.mo:28.25-28.34: warning, this case is never reached +coverage.mo:29.25-29.34: warning, this case is never reached +coverage.mo:30.25-30.34: warning, this case is never reached +coverage.mo:31.25-31.34: warning, this case is never reached +coverage.mo:32.43-32.44: warning, this pattern is never matched +coverage.mo:33.35-33.49: warning, this case is never reached +coverage.mo:34.42-34.51: warning, this case is never reached +coverage.mo:37.51-37.73: warning, this case is never reached +coverage.mo:38.39-38.54: warning, this case is never reached +coverage.mo:39.56-39.65: warning, this case is never reached +coverage.mo:40.49-40.58: warning, this case is never reached +coverage.mo:46.58-46.72: warning, this case is never reached +coverage.mo:61.22-61.31: warning, this case is never reached +coverage.mo:62.28-62.37: warning, this case is never reached +coverage.mo:63.49-63.50: warning, this pattern is never matched +coverage.mo:64.48-64.49: warning, this pattern is never matched +coverage.mo:65.41-65.42: warning, this pattern is never matched +coverage.mo:66.40-66.41: warning, this pattern is never matched +coverage.mo:77.5-77.55: warning, this case is never reached +coverage.mo:109.3-109.52: warning, this case is never reached +coverage.mo:4.7-4.8: warning, this pattern consuming type Nat does not cover value 0 or 1 or _ -coverage.as:5.7-5.15: warning, this pattern consuming type +coverage.mo:5.7-5.15: warning, this pattern consuming type Nat does not cover value 0 or 1 or _ -coverage.as:9.7-9.9: warning, this pattern consuming type +coverage.mo:9.7-9.9: warning, this pattern consuming type ?Nat does not cover value null -coverage.as:10.7-10.9: warning, this pattern consuming type +coverage.mo:10.7-10.9: warning, this pattern consuming type ?Nat does not cover value null -coverage.as:11.7-11.9: warning, this pattern consuming type +coverage.mo:11.7-11.9: warning, this pattern consuming type ?Nat does not cover value ?(0 or 1 or _) or null -coverage.as:15.10-15.13: warning, this pattern consuming type +coverage.mo:15.10-15.13: warning, this pattern consuming type Nat does not cover value 0 or 1 or _ -coverage.as:16.10-16.18: warning, this pattern consuming type +coverage.mo:16.10-16.18: warning, this pattern consuming type Nat does not cover value 0 or 1 or _ -coverage.as:23.3-23.25: warning, the cases in this switch over type +coverage.mo:23.3-23.25: warning, the cases in this switch over type Nat do not cover value 0 or 1 or _ -coverage.as:24.3-24.36: warning, the cases in this switch over type +coverage.mo:24.3-24.36: warning, the cases in this switch over type Nat do not cover value 0 or 1 or _ -coverage.as:32.3-32.50: warning, the cases in this switch over type +coverage.mo:32.3-32.50: warning, the cases in this switch over type Nat do not cover value 0 or 1 or _ -coverage.as:35.3-35.51: warning, the cases in this switch over type +coverage.mo:35.3-35.51: warning, the cases in this switch over type (Nat, Nat) do not cover value (1 or 2 or _, 1 or 2 or _) -coverage.as:41.3-41.61: warning, the cases in this switch over type +coverage.mo:41.3-41.61: warning, the cases in this switch over type {a : Nat; b : Nat} do not cover value {a = 1 or 2 or _; b = 1 or 2 or _) -coverage.as:45.3-45.74: warning, the cases in this switch over type +coverage.mo:45.3-45.74: warning, the cases in this switch over type {#a : Nat; #b : Nat} do not cover value #b(0 or 1 or _) -coverage.as:47.3-47.58: warning, the cases in this switch over type +coverage.mo:47.3-47.58: warning, the cases in this switch over type {#a : Nat; #b : Nat} do not cover value #b(_) -coverage.as:48.3-48.58: warning, the cases in this switch over type +coverage.mo:48.3-48.58: warning, the cases in this switch over type {#a : Nat; #b : Nat} do not cover value #a(_) -coverage.as:49.3-49.62: warning, the cases in this switch over type +coverage.mo:49.3-49.62: warning, the cases in this switch over type {#a : Nat; #b : Nat; #c} do not cover value #a(_) or #c -coverage.as:50.3-50.42: warning, the cases in this switch over type +coverage.mo:50.3-50.42: warning, the cases in this switch over type {#a : Nat; #b : Nat} do not cover value _ -coverage.as:74.3-78.4: warning, the cases in this switch over type +coverage.mo:74.3-78.4: warning, the cases in this switch over type {#branch : (Tree, Tree); #leaf : Int} do not cover value #leaf(0 or 1 or _) diff --git a/test/run/ok/coverage.run-low.ok b/test/run/ok/coverage.run-low.ok index 9749151ddcd..6cd2a586f70 100644 --- a/test/run/ok/coverage.run-low.ok +++ b/test/run/ok/coverage.run-low.ok @@ -1,101 +1,101 @@ -coverage.as:5.13-5.14: warning, this pattern is never matched -coverage.as:7.13-7.14: warning, this pattern is never matched -coverage.as:8.13-8.14: warning, this pattern is never matched -coverage.as:16.16-16.17: warning, this pattern is never matched -coverage.as:18.16-18.17: warning, this pattern is never matched -coverage.as:19.17-19.18: warning, this pattern is never matched -coverage.as:24.25-24.34: warning, this case is never reached -coverage.as:27.25-27.34: warning, this case is never reached -coverage.as:28.25-28.34: warning, this case is never reached -coverage.as:29.25-29.34: warning, this case is never reached -coverage.as:30.25-30.34: warning, this case is never reached -coverage.as:31.25-31.34: warning, this case is never reached -coverage.as:32.43-32.44: warning, this pattern is never matched -coverage.as:33.35-33.49: warning, this case is never reached -coverage.as:34.42-34.51: warning, this case is never reached -coverage.as:37.51-37.73: warning, this case is never reached -coverage.as:38.39-38.54: warning, this case is never reached -coverage.as:39.56-39.65: warning, this case is never reached -coverage.as:40.49-40.58: warning, this case is never reached -coverage.as:46.58-46.72: warning, this case is never reached -coverage.as:61.22-61.31: warning, this case is never reached -coverage.as:62.28-62.37: warning, this case is never reached -coverage.as:63.49-63.50: warning, this pattern is never matched -coverage.as:64.48-64.49: warning, this pattern is never matched -coverage.as:65.41-65.42: warning, this pattern is never matched -coverage.as:66.40-66.41: warning, this pattern is never matched -coverage.as:77.5-77.55: warning, this case is never reached -coverage.as:109.3-109.52: warning, this case is never reached -coverage.as:4.7-4.8: warning, this pattern consuming type +coverage.mo:5.13-5.14: warning, this pattern is never matched +coverage.mo:7.13-7.14: warning, this pattern is never matched +coverage.mo:8.13-8.14: warning, this pattern is never matched +coverage.mo:16.16-16.17: warning, this pattern is never matched +coverage.mo:18.16-18.17: warning, this pattern is never matched +coverage.mo:19.17-19.18: warning, this pattern is never matched +coverage.mo:24.25-24.34: warning, this case is never reached +coverage.mo:27.25-27.34: warning, this case is never reached +coverage.mo:28.25-28.34: warning, this case is never reached +coverage.mo:29.25-29.34: warning, this case is never reached +coverage.mo:30.25-30.34: warning, this case is never reached +coverage.mo:31.25-31.34: warning, this case is never reached +coverage.mo:32.43-32.44: warning, this pattern is never matched +coverage.mo:33.35-33.49: warning, this case is never reached +coverage.mo:34.42-34.51: warning, this case is never reached +coverage.mo:37.51-37.73: warning, this case is never reached +coverage.mo:38.39-38.54: warning, this case is never reached +coverage.mo:39.56-39.65: warning, this case is never reached +coverage.mo:40.49-40.58: warning, this case is never reached +coverage.mo:46.58-46.72: warning, this case is never reached +coverage.mo:61.22-61.31: warning, this case is never reached +coverage.mo:62.28-62.37: warning, this case is never reached +coverage.mo:63.49-63.50: warning, this pattern is never matched +coverage.mo:64.48-64.49: warning, this pattern is never matched +coverage.mo:65.41-65.42: warning, this pattern is never matched +coverage.mo:66.40-66.41: warning, this pattern is never matched +coverage.mo:77.5-77.55: warning, this case is never reached +coverage.mo:109.3-109.52: warning, this case is never reached +coverage.mo:4.7-4.8: warning, this pattern consuming type Nat does not cover value 0 or 1 or _ -coverage.as:5.7-5.15: warning, this pattern consuming type +coverage.mo:5.7-5.15: warning, this pattern consuming type Nat does not cover value 0 or 1 or _ -coverage.as:9.7-9.9: warning, this pattern consuming type +coverage.mo:9.7-9.9: warning, this pattern consuming type ?Nat does not cover value null -coverage.as:10.7-10.9: warning, this pattern consuming type +coverage.mo:10.7-10.9: warning, this pattern consuming type ?Nat does not cover value null -coverage.as:11.7-11.9: warning, this pattern consuming type +coverage.mo:11.7-11.9: warning, this pattern consuming type ?Nat does not cover value ?(0 or 1 or _) or null -coverage.as:15.10-15.13: warning, this pattern consuming type +coverage.mo:15.10-15.13: warning, this pattern consuming type Nat does not cover value 0 or 1 or _ -coverage.as:16.10-16.18: warning, this pattern consuming type +coverage.mo:16.10-16.18: warning, this pattern consuming type Nat does not cover value 0 or 1 or _ -coverage.as:23.3-23.25: warning, the cases in this switch over type +coverage.mo:23.3-23.25: warning, the cases in this switch over type Nat do not cover value 0 or 1 or _ -coverage.as:24.3-24.36: warning, the cases in this switch over type +coverage.mo:24.3-24.36: warning, the cases in this switch over type Nat do not cover value 0 or 1 or _ -coverage.as:32.3-32.50: warning, the cases in this switch over type +coverage.mo:32.3-32.50: warning, the cases in this switch over type Nat do not cover value 0 or 1 or _ -coverage.as:35.3-35.51: warning, the cases in this switch over type +coverage.mo:35.3-35.51: warning, the cases in this switch over type (Nat, Nat) do not cover value (1 or 2 or _, 1 or 2 or _) -coverage.as:41.3-41.61: warning, the cases in this switch over type +coverage.mo:41.3-41.61: warning, the cases in this switch over type {a : Nat; b : Nat} do not cover value {a = 1 or 2 or _; b = 1 or 2 or _) -coverage.as:45.3-45.74: warning, the cases in this switch over type +coverage.mo:45.3-45.74: warning, the cases in this switch over type {#a : Nat; #b : Nat} do not cover value #b(0 or 1 or _) -coverage.as:47.3-47.58: warning, the cases in this switch over type +coverage.mo:47.3-47.58: warning, the cases in this switch over type {#a : Nat; #b : Nat} do not cover value #b(_) -coverage.as:48.3-48.58: warning, the cases in this switch over type +coverage.mo:48.3-48.58: warning, the cases in this switch over type {#a : Nat; #b : Nat} do not cover value #a(_) -coverage.as:49.3-49.62: warning, the cases in this switch over type +coverage.mo:49.3-49.62: warning, the cases in this switch over type {#a : Nat; #b : Nat; #c} do not cover value #a(_) or #c -coverage.as:50.3-50.42: warning, the cases in this switch over type +coverage.mo:50.3-50.42: warning, the cases in this switch over type {#a : Nat; #b : Nat} do not cover value _ -coverage.as:74.3-78.4: warning, the cases in this switch over type +coverage.mo:74.3-78.4: warning, the cases in this switch over type {#branch : (Tree, Tree); #leaf : Int} do not cover value #leaf(0 or 1 or _) diff --git a/test/run/ok/coverage.run.ok b/test/run/ok/coverage.run.ok index 9749151ddcd..6cd2a586f70 100644 --- a/test/run/ok/coverage.run.ok +++ b/test/run/ok/coverage.run.ok @@ -1,101 +1,101 @@ -coverage.as:5.13-5.14: warning, this pattern is never matched -coverage.as:7.13-7.14: warning, this pattern is never matched -coverage.as:8.13-8.14: warning, this pattern is never matched -coverage.as:16.16-16.17: warning, this pattern is never matched -coverage.as:18.16-18.17: warning, this pattern is never matched -coverage.as:19.17-19.18: warning, this pattern is never matched -coverage.as:24.25-24.34: warning, this case is never reached -coverage.as:27.25-27.34: warning, this case is never reached -coverage.as:28.25-28.34: warning, this case is never reached -coverage.as:29.25-29.34: warning, this case is never reached -coverage.as:30.25-30.34: warning, this case is never reached -coverage.as:31.25-31.34: warning, this case is never reached -coverage.as:32.43-32.44: warning, this pattern is never matched -coverage.as:33.35-33.49: warning, this case is never reached -coverage.as:34.42-34.51: warning, this case is never reached -coverage.as:37.51-37.73: warning, this case is never reached -coverage.as:38.39-38.54: warning, this case is never reached -coverage.as:39.56-39.65: warning, this case is never reached -coverage.as:40.49-40.58: warning, this case is never reached -coverage.as:46.58-46.72: warning, this case is never reached -coverage.as:61.22-61.31: warning, this case is never reached -coverage.as:62.28-62.37: warning, this case is never reached -coverage.as:63.49-63.50: warning, this pattern is never matched -coverage.as:64.48-64.49: warning, this pattern is never matched -coverage.as:65.41-65.42: warning, this pattern is never matched -coverage.as:66.40-66.41: warning, this pattern is never matched -coverage.as:77.5-77.55: warning, this case is never reached -coverage.as:109.3-109.52: warning, this case is never reached -coverage.as:4.7-4.8: warning, this pattern consuming type +coverage.mo:5.13-5.14: warning, this pattern is never matched +coverage.mo:7.13-7.14: warning, this pattern is never matched +coverage.mo:8.13-8.14: warning, this pattern is never matched +coverage.mo:16.16-16.17: warning, this pattern is never matched +coverage.mo:18.16-18.17: warning, this pattern is never matched +coverage.mo:19.17-19.18: warning, this pattern is never matched +coverage.mo:24.25-24.34: warning, this case is never reached +coverage.mo:27.25-27.34: warning, this case is never reached +coverage.mo:28.25-28.34: warning, this case is never reached +coverage.mo:29.25-29.34: warning, this case is never reached +coverage.mo:30.25-30.34: warning, this case is never reached +coverage.mo:31.25-31.34: warning, this case is never reached +coverage.mo:32.43-32.44: warning, this pattern is never matched +coverage.mo:33.35-33.49: warning, this case is never reached +coverage.mo:34.42-34.51: warning, this case is never reached +coverage.mo:37.51-37.73: warning, this case is never reached +coverage.mo:38.39-38.54: warning, this case is never reached +coverage.mo:39.56-39.65: warning, this case is never reached +coverage.mo:40.49-40.58: warning, this case is never reached +coverage.mo:46.58-46.72: warning, this case is never reached +coverage.mo:61.22-61.31: warning, this case is never reached +coverage.mo:62.28-62.37: warning, this case is never reached +coverage.mo:63.49-63.50: warning, this pattern is never matched +coverage.mo:64.48-64.49: warning, this pattern is never matched +coverage.mo:65.41-65.42: warning, this pattern is never matched +coverage.mo:66.40-66.41: warning, this pattern is never matched +coverage.mo:77.5-77.55: warning, this case is never reached +coverage.mo:109.3-109.52: warning, this case is never reached +coverage.mo:4.7-4.8: warning, this pattern consuming type Nat does not cover value 0 or 1 or _ -coverage.as:5.7-5.15: warning, this pattern consuming type +coverage.mo:5.7-5.15: warning, this pattern consuming type Nat does not cover value 0 or 1 or _ -coverage.as:9.7-9.9: warning, this pattern consuming type +coverage.mo:9.7-9.9: warning, this pattern consuming type ?Nat does not cover value null -coverage.as:10.7-10.9: warning, this pattern consuming type +coverage.mo:10.7-10.9: warning, this pattern consuming type ?Nat does not cover value null -coverage.as:11.7-11.9: warning, this pattern consuming type +coverage.mo:11.7-11.9: warning, this pattern consuming type ?Nat does not cover value ?(0 or 1 or _) or null -coverage.as:15.10-15.13: warning, this pattern consuming type +coverage.mo:15.10-15.13: warning, this pattern consuming type Nat does not cover value 0 or 1 or _ -coverage.as:16.10-16.18: warning, this pattern consuming type +coverage.mo:16.10-16.18: warning, this pattern consuming type Nat does not cover value 0 or 1 or _ -coverage.as:23.3-23.25: warning, the cases in this switch over type +coverage.mo:23.3-23.25: warning, the cases in this switch over type Nat do not cover value 0 or 1 or _ -coverage.as:24.3-24.36: warning, the cases in this switch over type +coverage.mo:24.3-24.36: warning, the cases in this switch over type Nat do not cover value 0 or 1 or _ -coverage.as:32.3-32.50: warning, the cases in this switch over type +coverage.mo:32.3-32.50: warning, the cases in this switch over type Nat do not cover value 0 or 1 or _ -coverage.as:35.3-35.51: warning, the cases in this switch over type +coverage.mo:35.3-35.51: warning, the cases in this switch over type (Nat, Nat) do not cover value (1 or 2 or _, 1 or 2 or _) -coverage.as:41.3-41.61: warning, the cases in this switch over type +coverage.mo:41.3-41.61: warning, the cases in this switch over type {a : Nat; b : Nat} do not cover value {a = 1 or 2 or _; b = 1 or 2 or _) -coverage.as:45.3-45.74: warning, the cases in this switch over type +coverage.mo:45.3-45.74: warning, the cases in this switch over type {#a : Nat; #b : Nat} do not cover value #b(0 or 1 or _) -coverage.as:47.3-47.58: warning, the cases in this switch over type +coverage.mo:47.3-47.58: warning, the cases in this switch over type {#a : Nat; #b : Nat} do not cover value #b(_) -coverage.as:48.3-48.58: warning, the cases in this switch over type +coverage.mo:48.3-48.58: warning, the cases in this switch over type {#a : Nat; #b : Nat} do not cover value #a(_) -coverage.as:49.3-49.62: warning, the cases in this switch over type +coverage.mo:49.3-49.62: warning, the cases in this switch over type {#a : Nat; #b : Nat; #c} do not cover value #a(_) or #c -coverage.as:50.3-50.42: warning, the cases in this switch over type +coverage.mo:50.3-50.42: warning, the cases in this switch over type {#a : Nat; #b : Nat} do not cover value _ -coverage.as:74.3-78.4: warning, the cases in this switch over type +coverage.mo:74.3-78.4: warning, the cases in this switch over type {#branch : (Tree, Tree); #leaf : Int} do not cover value #leaf(0 or 1 or _) diff --git a/test/run/ok/coverage.tc.ok b/test/run/ok/coverage.tc.ok index 9749151ddcd..6cd2a586f70 100644 --- a/test/run/ok/coverage.tc.ok +++ b/test/run/ok/coverage.tc.ok @@ -1,101 +1,101 @@ -coverage.as:5.13-5.14: warning, this pattern is never matched -coverage.as:7.13-7.14: warning, this pattern is never matched -coverage.as:8.13-8.14: warning, this pattern is never matched -coverage.as:16.16-16.17: warning, this pattern is never matched -coverage.as:18.16-18.17: warning, this pattern is never matched -coverage.as:19.17-19.18: warning, this pattern is never matched -coverage.as:24.25-24.34: warning, this case is never reached -coverage.as:27.25-27.34: warning, this case is never reached -coverage.as:28.25-28.34: warning, this case is never reached -coverage.as:29.25-29.34: warning, this case is never reached -coverage.as:30.25-30.34: warning, this case is never reached -coverage.as:31.25-31.34: warning, this case is never reached -coverage.as:32.43-32.44: warning, this pattern is never matched -coverage.as:33.35-33.49: warning, this case is never reached -coverage.as:34.42-34.51: warning, this case is never reached -coverage.as:37.51-37.73: warning, this case is never reached -coverage.as:38.39-38.54: warning, this case is never reached -coverage.as:39.56-39.65: warning, this case is never reached -coverage.as:40.49-40.58: warning, this case is never reached -coverage.as:46.58-46.72: warning, this case is never reached -coverage.as:61.22-61.31: warning, this case is never reached -coverage.as:62.28-62.37: warning, this case is never reached -coverage.as:63.49-63.50: warning, this pattern is never matched -coverage.as:64.48-64.49: warning, this pattern is never matched -coverage.as:65.41-65.42: warning, this pattern is never matched -coverage.as:66.40-66.41: warning, this pattern is never matched -coverage.as:77.5-77.55: warning, this case is never reached -coverage.as:109.3-109.52: warning, this case is never reached -coverage.as:4.7-4.8: warning, this pattern consuming type +coverage.mo:5.13-5.14: warning, this pattern is never matched +coverage.mo:7.13-7.14: warning, this pattern is never matched +coverage.mo:8.13-8.14: warning, this pattern is never matched +coverage.mo:16.16-16.17: warning, this pattern is never matched +coverage.mo:18.16-18.17: warning, this pattern is never matched +coverage.mo:19.17-19.18: warning, this pattern is never matched +coverage.mo:24.25-24.34: warning, this case is never reached +coverage.mo:27.25-27.34: warning, this case is never reached +coverage.mo:28.25-28.34: warning, this case is never reached +coverage.mo:29.25-29.34: warning, this case is never reached +coverage.mo:30.25-30.34: warning, this case is never reached +coverage.mo:31.25-31.34: warning, this case is never reached +coverage.mo:32.43-32.44: warning, this pattern is never matched +coverage.mo:33.35-33.49: warning, this case is never reached +coverage.mo:34.42-34.51: warning, this case is never reached +coverage.mo:37.51-37.73: warning, this case is never reached +coverage.mo:38.39-38.54: warning, this case is never reached +coverage.mo:39.56-39.65: warning, this case is never reached +coverage.mo:40.49-40.58: warning, this case is never reached +coverage.mo:46.58-46.72: warning, this case is never reached +coverage.mo:61.22-61.31: warning, this case is never reached +coverage.mo:62.28-62.37: warning, this case is never reached +coverage.mo:63.49-63.50: warning, this pattern is never matched +coverage.mo:64.48-64.49: warning, this pattern is never matched +coverage.mo:65.41-65.42: warning, this pattern is never matched +coverage.mo:66.40-66.41: warning, this pattern is never matched +coverage.mo:77.5-77.55: warning, this case is never reached +coverage.mo:109.3-109.52: warning, this case is never reached +coverage.mo:4.7-4.8: warning, this pattern consuming type Nat does not cover value 0 or 1 or _ -coverage.as:5.7-5.15: warning, this pattern consuming type +coverage.mo:5.7-5.15: warning, this pattern consuming type Nat does not cover value 0 or 1 or _ -coverage.as:9.7-9.9: warning, this pattern consuming type +coverage.mo:9.7-9.9: warning, this pattern consuming type ?Nat does not cover value null -coverage.as:10.7-10.9: warning, this pattern consuming type +coverage.mo:10.7-10.9: warning, this pattern consuming type ?Nat does not cover value null -coverage.as:11.7-11.9: warning, this pattern consuming type +coverage.mo:11.7-11.9: warning, this pattern consuming type ?Nat does not cover value ?(0 or 1 or _) or null -coverage.as:15.10-15.13: warning, this pattern consuming type +coverage.mo:15.10-15.13: warning, this pattern consuming type Nat does not cover value 0 or 1 or _ -coverage.as:16.10-16.18: warning, this pattern consuming type +coverage.mo:16.10-16.18: warning, this pattern consuming type Nat does not cover value 0 or 1 or _ -coverage.as:23.3-23.25: warning, the cases in this switch over type +coverage.mo:23.3-23.25: warning, the cases in this switch over type Nat do not cover value 0 or 1 or _ -coverage.as:24.3-24.36: warning, the cases in this switch over type +coverage.mo:24.3-24.36: warning, the cases in this switch over type Nat do not cover value 0 or 1 or _ -coverage.as:32.3-32.50: warning, the cases in this switch over type +coverage.mo:32.3-32.50: warning, the cases in this switch over type Nat do not cover value 0 or 1 or _ -coverage.as:35.3-35.51: warning, the cases in this switch over type +coverage.mo:35.3-35.51: warning, the cases in this switch over type (Nat, Nat) do not cover value (1 or 2 or _, 1 or 2 or _) -coverage.as:41.3-41.61: warning, the cases in this switch over type +coverage.mo:41.3-41.61: warning, the cases in this switch over type {a : Nat; b : Nat} do not cover value {a = 1 or 2 or _; b = 1 or 2 or _) -coverage.as:45.3-45.74: warning, the cases in this switch over type +coverage.mo:45.3-45.74: warning, the cases in this switch over type {#a : Nat; #b : Nat} do not cover value #b(0 or 1 or _) -coverage.as:47.3-47.58: warning, the cases in this switch over type +coverage.mo:47.3-47.58: warning, the cases in this switch over type {#a : Nat; #b : Nat} do not cover value #b(_) -coverage.as:48.3-48.58: warning, the cases in this switch over type +coverage.mo:48.3-48.58: warning, the cases in this switch over type {#a : Nat; #b : Nat} do not cover value #a(_) -coverage.as:49.3-49.62: warning, the cases in this switch over type +coverage.mo:49.3-49.62: warning, the cases in this switch over type {#a : Nat; #b : Nat; #c} do not cover value #a(_) or #c -coverage.as:50.3-50.42: warning, the cases in this switch over type +coverage.mo:50.3-50.42: warning, the cases in this switch over type {#a : Nat; #b : Nat} do not cover value _ -coverage.as:74.3-78.4: warning, the cases in this switch over type +coverage.mo:74.3-78.4: warning, the cases in this switch over type {#branch : (Tree, Tree); #leaf : Int} do not cover value #leaf(0 or 1 or _) diff --git a/test/run/ok/coverage.wasm.stderr.ok b/test/run/ok/coverage.wasm.stderr.ok index 9749151ddcd..6cd2a586f70 100644 --- a/test/run/ok/coverage.wasm.stderr.ok +++ b/test/run/ok/coverage.wasm.stderr.ok @@ -1,101 +1,101 @@ -coverage.as:5.13-5.14: warning, this pattern is never matched -coverage.as:7.13-7.14: warning, this pattern is never matched -coverage.as:8.13-8.14: warning, this pattern is never matched -coverage.as:16.16-16.17: warning, this pattern is never matched -coverage.as:18.16-18.17: warning, this pattern is never matched -coverage.as:19.17-19.18: warning, this pattern is never matched -coverage.as:24.25-24.34: warning, this case is never reached -coverage.as:27.25-27.34: warning, this case is never reached -coverage.as:28.25-28.34: warning, this case is never reached -coverage.as:29.25-29.34: warning, this case is never reached -coverage.as:30.25-30.34: warning, this case is never reached -coverage.as:31.25-31.34: warning, this case is never reached -coverage.as:32.43-32.44: warning, this pattern is never matched -coverage.as:33.35-33.49: warning, this case is never reached -coverage.as:34.42-34.51: warning, this case is never reached -coverage.as:37.51-37.73: warning, this case is never reached -coverage.as:38.39-38.54: warning, this case is never reached -coverage.as:39.56-39.65: warning, this case is never reached -coverage.as:40.49-40.58: warning, this case is never reached -coverage.as:46.58-46.72: warning, this case is never reached -coverage.as:61.22-61.31: warning, this case is never reached -coverage.as:62.28-62.37: warning, this case is never reached -coverage.as:63.49-63.50: warning, this pattern is never matched -coverage.as:64.48-64.49: warning, this pattern is never matched -coverage.as:65.41-65.42: warning, this pattern is never matched -coverage.as:66.40-66.41: warning, this pattern is never matched -coverage.as:77.5-77.55: warning, this case is never reached -coverage.as:109.3-109.52: warning, this case is never reached -coverage.as:4.7-4.8: warning, this pattern consuming type +coverage.mo:5.13-5.14: warning, this pattern is never matched +coverage.mo:7.13-7.14: warning, this pattern is never matched +coverage.mo:8.13-8.14: warning, this pattern is never matched +coverage.mo:16.16-16.17: warning, this pattern is never matched +coverage.mo:18.16-18.17: warning, this pattern is never matched +coverage.mo:19.17-19.18: warning, this pattern is never matched +coverage.mo:24.25-24.34: warning, this case is never reached +coverage.mo:27.25-27.34: warning, this case is never reached +coverage.mo:28.25-28.34: warning, this case is never reached +coverage.mo:29.25-29.34: warning, this case is never reached +coverage.mo:30.25-30.34: warning, this case is never reached +coverage.mo:31.25-31.34: warning, this case is never reached +coverage.mo:32.43-32.44: warning, this pattern is never matched +coverage.mo:33.35-33.49: warning, this case is never reached +coverage.mo:34.42-34.51: warning, this case is never reached +coverage.mo:37.51-37.73: warning, this case is never reached +coverage.mo:38.39-38.54: warning, this case is never reached +coverage.mo:39.56-39.65: warning, this case is never reached +coverage.mo:40.49-40.58: warning, this case is never reached +coverage.mo:46.58-46.72: warning, this case is never reached +coverage.mo:61.22-61.31: warning, this case is never reached +coverage.mo:62.28-62.37: warning, this case is never reached +coverage.mo:63.49-63.50: warning, this pattern is never matched +coverage.mo:64.48-64.49: warning, this pattern is never matched +coverage.mo:65.41-65.42: warning, this pattern is never matched +coverage.mo:66.40-66.41: warning, this pattern is never matched +coverage.mo:77.5-77.55: warning, this case is never reached +coverage.mo:109.3-109.52: warning, this case is never reached +coverage.mo:4.7-4.8: warning, this pattern consuming type Nat does not cover value 0 or 1 or _ -coverage.as:5.7-5.15: warning, this pattern consuming type +coverage.mo:5.7-5.15: warning, this pattern consuming type Nat does not cover value 0 or 1 or _ -coverage.as:9.7-9.9: warning, this pattern consuming type +coverage.mo:9.7-9.9: warning, this pattern consuming type ?Nat does not cover value null -coverage.as:10.7-10.9: warning, this pattern consuming type +coverage.mo:10.7-10.9: warning, this pattern consuming type ?Nat does not cover value null -coverage.as:11.7-11.9: warning, this pattern consuming type +coverage.mo:11.7-11.9: warning, this pattern consuming type ?Nat does not cover value ?(0 or 1 or _) or null -coverage.as:15.10-15.13: warning, this pattern consuming type +coverage.mo:15.10-15.13: warning, this pattern consuming type Nat does not cover value 0 or 1 or _ -coverage.as:16.10-16.18: warning, this pattern consuming type +coverage.mo:16.10-16.18: warning, this pattern consuming type Nat does not cover value 0 or 1 or _ -coverage.as:23.3-23.25: warning, the cases in this switch over type +coverage.mo:23.3-23.25: warning, the cases in this switch over type Nat do not cover value 0 or 1 or _ -coverage.as:24.3-24.36: warning, the cases in this switch over type +coverage.mo:24.3-24.36: warning, the cases in this switch over type Nat do not cover value 0 or 1 or _ -coverage.as:32.3-32.50: warning, the cases in this switch over type +coverage.mo:32.3-32.50: warning, the cases in this switch over type Nat do not cover value 0 or 1 or _ -coverage.as:35.3-35.51: warning, the cases in this switch over type +coverage.mo:35.3-35.51: warning, the cases in this switch over type (Nat, Nat) do not cover value (1 or 2 or _, 1 or 2 or _) -coverage.as:41.3-41.61: warning, the cases in this switch over type +coverage.mo:41.3-41.61: warning, the cases in this switch over type {a : Nat; b : Nat} do not cover value {a = 1 or 2 or _; b = 1 or 2 or _) -coverage.as:45.3-45.74: warning, the cases in this switch over type +coverage.mo:45.3-45.74: warning, the cases in this switch over type {#a : Nat; #b : Nat} do not cover value #b(0 or 1 or _) -coverage.as:47.3-47.58: warning, the cases in this switch over type +coverage.mo:47.3-47.58: warning, the cases in this switch over type {#a : Nat; #b : Nat} do not cover value #b(_) -coverage.as:48.3-48.58: warning, the cases in this switch over type +coverage.mo:48.3-48.58: warning, the cases in this switch over type {#a : Nat; #b : Nat} do not cover value #a(_) -coverage.as:49.3-49.62: warning, the cases in this switch over type +coverage.mo:49.3-49.62: warning, the cases in this switch over type {#a : Nat; #b : Nat; #c} do not cover value #a(_) or #c -coverage.as:50.3-50.42: warning, the cases in this switch over type +coverage.mo:50.3-50.42: warning, the cases in this switch over type {#a : Nat; #b : Nat} do not cover value _ -coverage.as:74.3-78.4: warning, the cases in this switch over type +coverage.mo:74.3-78.4: warning, the cases in this switch over type {#branch : (Tree, Tree); #leaf : Int} do not cover value #leaf(0 or 1 or _) diff --git a/test/run/ok/issue442.idl.stderr.ok b/test/run/ok/issue442.idl.stderr.ok index 136d5ad0c79..2ec06928058 100644 --- a/test/run/ok/issue442.idl.stderr.ok +++ b/test/run/ok/issue442.idl.stderr.ok @@ -1,5 +1,5 @@ -issue442.as:1.11-1.24: warning, this array has type [Any] because elements have inconsistent types -issue442.as:2.11-2.29: warning, this if has type Any because branches have inconsistent types, +issue442.mo:1.11-1.24: warning, this array has type [Any] because elements have inconsistent types +issue442.mo:2.11-2.29: warning, this if has type Any because branches have inconsistent types, true produces Nat false produces diff --git a/test/run/ok/issue442.run-ir.ok b/test/run/ok/issue442.run-ir.ok index 136d5ad0c79..2ec06928058 100644 --- a/test/run/ok/issue442.run-ir.ok +++ b/test/run/ok/issue442.run-ir.ok @@ -1,5 +1,5 @@ -issue442.as:1.11-1.24: warning, this array has type [Any] because elements have inconsistent types -issue442.as:2.11-2.29: warning, this if has type Any because branches have inconsistent types, +issue442.mo:1.11-1.24: warning, this array has type [Any] because elements have inconsistent types +issue442.mo:2.11-2.29: warning, this if has type Any because branches have inconsistent types, true produces Nat false produces diff --git a/test/run/ok/issue442.run-low.ok b/test/run/ok/issue442.run-low.ok index 136d5ad0c79..2ec06928058 100644 --- a/test/run/ok/issue442.run-low.ok +++ b/test/run/ok/issue442.run-low.ok @@ -1,5 +1,5 @@ -issue442.as:1.11-1.24: warning, this array has type [Any] because elements have inconsistent types -issue442.as:2.11-2.29: warning, this if has type Any because branches have inconsistent types, +issue442.mo:1.11-1.24: warning, this array has type [Any] because elements have inconsistent types +issue442.mo:2.11-2.29: warning, this if has type Any because branches have inconsistent types, true produces Nat false produces diff --git a/test/run/ok/issue442.run.ok b/test/run/ok/issue442.run.ok index 136d5ad0c79..2ec06928058 100644 --- a/test/run/ok/issue442.run.ok +++ b/test/run/ok/issue442.run.ok @@ -1,5 +1,5 @@ -issue442.as:1.11-1.24: warning, this array has type [Any] because elements have inconsistent types -issue442.as:2.11-2.29: warning, this if has type Any because branches have inconsistent types, +issue442.mo:1.11-1.24: warning, this array has type [Any] because elements have inconsistent types +issue442.mo:2.11-2.29: warning, this if has type Any because branches have inconsistent types, true produces Nat false produces diff --git a/test/run/ok/issue442.tc.ok b/test/run/ok/issue442.tc.ok index 136d5ad0c79..2ec06928058 100644 --- a/test/run/ok/issue442.tc.ok +++ b/test/run/ok/issue442.tc.ok @@ -1,5 +1,5 @@ -issue442.as:1.11-1.24: warning, this array has type [Any] because elements have inconsistent types -issue442.as:2.11-2.29: warning, this if has type Any because branches have inconsistent types, +issue442.mo:1.11-1.24: warning, this array has type [Any] because elements have inconsistent types +issue442.mo:2.11-2.29: warning, this if has type Any because branches have inconsistent types, true produces Nat false produces diff --git a/test/run/ok/issue442.wasm.stderr.ok b/test/run/ok/issue442.wasm.stderr.ok index 136d5ad0c79..2ec06928058 100644 --- a/test/run/ok/issue442.wasm.stderr.ok +++ b/test/run/ok/issue442.wasm.stderr.ok @@ -1,5 +1,5 @@ -issue442.as:1.11-1.24: warning, this array has type [Any] because elements have inconsistent types -issue442.as:2.11-2.29: warning, this if has type Any because branches have inconsistent types, +issue442.mo:1.11-1.24: warning, this array has type [Any] because elements have inconsistent types +issue442.mo:2.11-2.29: warning, this if has type Any because branches have inconsistent types, true produces Nat false produces diff --git a/test/run/ok/large-tuple.idl.stderr.ok b/test/run/ok/large-tuple.idl.stderr.ok index 6d7e9529fe2..c20cc4ea334 100644 --- a/test/run/ok/large-tuple.idl.stderr.ok +++ b/test/run/ok/large-tuple.idl.stderr.ok @@ -1,4 +1,4 @@ -large-tuple.as:4.21-4.73: warning, this pattern consuming type +large-tuple.mo:4.21-4.73: warning, this pattern consuming type (Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat) does not cover value (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0 or 1 or _) or diff --git a/test/run/ok/large-tuple.run-ir.ok b/test/run/ok/large-tuple.run-ir.ok index 6d7e9529fe2..c20cc4ea334 100644 --- a/test/run/ok/large-tuple.run-ir.ok +++ b/test/run/ok/large-tuple.run-ir.ok @@ -1,4 +1,4 @@ -large-tuple.as:4.21-4.73: warning, this pattern consuming type +large-tuple.mo:4.21-4.73: warning, this pattern consuming type (Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat) does not cover value (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0 or 1 or _) or diff --git a/test/run/ok/large-tuple.run-low.ok b/test/run/ok/large-tuple.run-low.ok index 6d7e9529fe2..c20cc4ea334 100644 --- a/test/run/ok/large-tuple.run-low.ok +++ b/test/run/ok/large-tuple.run-low.ok @@ -1,4 +1,4 @@ -large-tuple.as:4.21-4.73: warning, this pattern consuming type +large-tuple.mo:4.21-4.73: warning, this pattern consuming type (Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat) does not cover value (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0 or 1 or _) or diff --git a/test/run/ok/large-tuple.run.ok b/test/run/ok/large-tuple.run.ok index 6d7e9529fe2..c20cc4ea334 100644 --- a/test/run/ok/large-tuple.run.ok +++ b/test/run/ok/large-tuple.run.ok @@ -1,4 +1,4 @@ -large-tuple.as:4.21-4.73: warning, this pattern consuming type +large-tuple.mo:4.21-4.73: warning, this pattern consuming type (Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat) does not cover value (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0 or 1 or _) or diff --git a/test/run/ok/large-tuple.tc.ok b/test/run/ok/large-tuple.tc.ok index 6d7e9529fe2..c20cc4ea334 100644 --- a/test/run/ok/large-tuple.tc.ok +++ b/test/run/ok/large-tuple.tc.ok @@ -1,4 +1,4 @@ -large-tuple.as:4.21-4.73: warning, this pattern consuming type +large-tuple.mo:4.21-4.73: warning, this pattern consuming type (Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat) does not cover value (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0 or 1 or _) or diff --git a/test/run/ok/large-tuple.wasm.stderr.ok b/test/run/ok/large-tuple.wasm.stderr.ok index 6d7e9529fe2..c20cc4ea334 100644 --- a/test/run/ok/large-tuple.wasm.stderr.ok +++ b/test/run/ok/large-tuple.wasm.stderr.ok @@ -1,4 +1,4 @@ -large-tuple.as:4.21-4.73: warning, this pattern consuming type +large-tuple.mo:4.21-4.73: warning, this pattern consuming type (Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat) does not cover value (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0 or 1 or _) or diff --git a/test/run/ok/objects1.idl.stderr.ok b/test/run/ok/objects1.idl.stderr.ok index 91dcd890805..53be7fa8068 100644 --- a/test/run/ok/objects1.idl.stderr.ok +++ b/test/run/ok/objects1.idl.stderr.ok @@ -1,10 +1,10 @@ -objects1.as:22.3-22.26: warning, this case is never reached -objects1.as:23.3-23.14: warning, this case is never reached -objects1.as:32.23-35.2: warning, the cases in this switch over type +objects1.mo:22.3-22.26: warning, this case is never reached +objects1.mo:23.3-23.14: warning, this case is never reached +objects1.mo:32.23-35.2: warning, the cases in this switch over type {a : Int; b : Nat} do not cover value {a = 0 or 1 or _; b = 0 or 1 or _) -objects1.as:43.21-45.2: warning, the cases in this switch over type +objects1.mo:43.21-45.2: warning, the cases in this switch over type (Nat, Int, {c : Char; d : Text}) do not cover value (_, 0 or 1 or _, _) diff --git a/test/run/ok/objects1.run-ir.ok b/test/run/ok/objects1.run-ir.ok index 91dcd890805..53be7fa8068 100644 --- a/test/run/ok/objects1.run-ir.ok +++ b/test/run/ok/objects1.run-ir.ok @@ -1,10 +1,10 @@ -objects1.as:22.3-22.26: warning, this case is never reached -objects1.as:23.3-23.14: warning, this case is never reached -objects1.as:32.23-35.2: warning, the cases in this switch over type +objects1.mo:22.3-22.26: warning, this case is never reached +objects1.mo:23.3-23.14: warning, this case is never reached +objects1.mo:32.23-35.2: warning, the cases in this switch over type {a : Int; b : Nat} do not cover value {a = 0 or 1 or _; b = 0 or 1 or _) -objects1.as:43.21-45.2: warning, the cases in this switch over type +objects1.mo:43.21-45.2: warning, the cases in this switch over type (Nat, Int, {c : Char; d : Text}) do not cover value (_, 0 or 1 or _, _) diff --git a/test/run/ok/objects1.run-low.ok b/test/run/ok/objects1.run-low.ok index 91dcd890805..53be7fa8068 100644 --- a/test/run/ok/objects1.run-low.ok +++ b/test/run/ok/objects1.run-low.ok @@ -1,10 +1,10 @@ -objects1.as:22.3-22.26: warning, this case is never reached -objects1.as:23.3-23.14: warning, this case is never reached -objects1.as:32.23-35.2: warning, the cases in this switch over type +objects1.mo:22.3-22.26: warning, this case is never reached +objects1.mo:23.3-23.14: warning, this case is never reached +objects1.mo:32.23-35.2: warning, the cases in this switch over type {a : Int; b : Nat} do not cover value {a = 0 or 1 or _; b = 0 or 1 or _) -objects1.as:43.21-45.2: warning, the cases in this switch over type +objects1.mo:43.21-45.2: warning, the cases in this switch over type (Nat, Int, {c : Char; d : Text}) do not cover value (_, 0 or 1 or _, _) diff --git a/test/run/ok/objects1.run.ok b/test/run/ok/objects1.run.ok index 91dcd890805..53be7fa8068 100644 --- a/test/run/ok/objects1.run.ok +++ b/test/run/ok/objects1.run.ok @@ -1,10 +1,10 @@ -objects1.as:22.3-22.26: warning, this case is never reached -objects1.as:23.3-23.14: warning, this case is never reached -objects1.as:32.23-35.2: warning, the cases in this switch over type +objects1.mo:22.3-22.26: warning, this case is never reached +objects1.mo:23.3-23.14: warning, this case is never reached +objects1.mo:32.23-35.2: warning, the cases in this switch over type {a : Int; b : Nat} do not cover value {a = 0 or 1 or _; b = 0 or 1 or _) -objects1.as:43.21-45.2: warning, the cases in this switch over type +objects1.mo:43.21-45.2: warning, the cases in this switch over type (Nat, Int, {c : Char; d : Text}) do not cover value (_, 0 or 1 or _, _) diff --git a/test/run/ok/objects1.tc.ok b/test/run/ok/objects1.tc.ok index 91dcd890805..53be7fa8068 100644 --- a/test/run/ok/objects1.tc.ok +++ b/test/run/ok/objects1.tc.ok @@ -1,10 +1,10 @@ -objects1.as:22.3-22.26: warning, this case is never reached -objects1.as:23.3-23.14: warning, this case is never reached -objects1.as:32.23-35.2: warning, the cases in this switch over type +objects1.mo:22.3-22.26: warning, this case is never reached +objects1.mo:23.3-23.14: warning, this case is never reached +objects1.mo:32.23-35.2: warning, the cases in this switch over type {a : Int; b : Nat} do not cover value {a = 0 or 1 or _; b = 0 or 1 or _) -objects1.as:43.21-45.2: warning, the cases in this switch over type +objects1.mo:43.21-45.2: warning, the cases in this switch over type (Nat, Int, {c : Char; d : Text}) do not cover value (_, 0 or 1 or _, _) diff --git a/test/run/ok/objects1.wasm.stderr.ok b/test/run/ok/objects1.wasm.stderr.ok index 91dcd890805..53be7fa8068 100644 --- a/test/run/ok/objects1.wasm.stderr.ok +++ b/test/run/ok/objects1.wasm.stderr.ok @@ -1,10 +1,10 @@ -objects1.as:22.3-22.26: warning, this case is never reached -objects1.as:23.3-23.14: warning, this case is never reached -objects1.as:32.23-35.2: warning, the cases in this switch over type +objects1.mo:22.3-22.26: warning, this case is never reached +objects1.mo:23.3-23.14: warning, this case is never reached +objects1.mo:32.23-35.2: warning, the cases in this switch over type {a : Int; b : Nat} do not cover value {a = 0 or 1 or _; b = 0 or 1 or _) -objects1.as:43.21-45.2: warning, the cases in this switch over type +objects1.mo:43.21-45.2: warning, the cases in this switch over type (Nat, Int, {c : Char; d : Text}) do not cover value (_, 0 or 1 or _, _) diff --git a/test/run/ok/overflow.run-ir.ok b/test/run/ok/overflow.run-ir.ok index fa160f7b0c0..c5b2db61806 100644 --- a/test/run/ok/overflow.run-ir.ok +++ b/test/run/ok/overflow.run-ir.ok @@ -1 +1 @@ -overflow.as:17.9-17.24: execution error, arithmetic overflow +overflow.mo:17.9-17.24: execution error, arithmetic overflow diff --git a/test/run/ok/overflow.run-low.ok b/test/run/ok/overflow.run-low.ok index fa160f7b0c0..c5b2db61806 100644 --- a/test/run/ok/overflow.run-low.ok +++ b/test/run/ok/overflow.run-low.ok @@ -1 +1 @@ -overflow.as:17.9-17.24: execution error, arithmetic overflow +overflow.mo:17.9-17.24: execution error, arithmetic overflow diff --git a/test/run/ok/overflow.run.ok b/test/run/ok/overflow.run.ok index fa160f7b0c0..c5b2db61806 100644 --- a/test/run/ok/overflow.run.ok +++ b/test/run/ok/overflow.run.ok @@ -1 +1 @@ -overflow.as:17.9-17.24: execution error, arithmetic overflow +overflow.mo:17.9-17.24: execution error, arithmetic overflow diff --git a/test/run/ok/pat-subtyping.idl.stderr.ok b/test/run/ok/pat-subtyping.idl.stderr.ok index 6fcdb8f75c5..76a04dc98af 100644 --- a/test/run/ok/pat-subtyping.idl.stderr.ok +++ b/test/run/ok/pat-subtyping.idl.stderr.ok @@ -1,41 +1,41 @@ -pat-subtyping.as:6.3-6.12: warning, this case is never reached -pat-subtyping.as:7.3-7.15: warning, this case is never reached -pat-subtyping.as:10.3-10.20: warning, this case is never reached -pat-subtyping.as:11.3-11.20: warning, this case is never reached -pat-subtyping.as:18.3-18.28: warning, this case is never reached -pat-subtyping.as:25.3-25.28: warning, this case is never reached -pat-subtyping.as:32.3-32.42: warning, this case is never reached -pat-subtyping.as:38.3-38.47: warning, this case is never reached -pat-subtyping.as:44.3-44.44: warning, this case is never reached -pat-subtyping.as:51.3-51.47: warning, this case is never reached -pat-subtyping.as:58.3-58.44: warning, this case is never reached -pat-subtyping.as:65.3-65.58: warning, this case is never reached -pat-subtyping.as:71.3-71.63: warning, this case is never reached -pat-subtyping.as:77.3-77.60: warning, this case is never reached -pat-subtyping.as:84.3-84.71: warning, this case is never reached -pat-subtyping.as:91.3-91.60: warning, this case is never reached -pat-subtyping.as:97.3-97.49: warning, this case is never reached -pat-subtyping.as:103.3-103.51: warning, this case is never reached -pat-subtyping.as:109.3-109.42: warning, this case is never reached -pat-subtyping.as:115.3-115.36: warning, this case is never reached -pat-subtyping.as:119.3-119.17: warning, this case is never reached -pat-subtyping.as:120.3-120.16: warning, this case is never reached -pat-subtyping.as:130.3-130.33: warning, this case is never reached -pat-subtyping.as:137.3-137.31: warning, this case is never reached -pat-subtyping.as:138.3-138.15: warning, this case is never reached -pat-subtyping.as:145.3-145.30: warning, this case is never reached -pat-subtyping.as:156.3-156.31: warning, this case is never reached -pat-subtyping.as:163.3-163.30: warning, this case is never reached -pat-subtyping.as:171.3-171.34: warning, this case is never reached -pat-subtyping.as:172.3-172.32: warning, this case is never reached -pat-subtyping.as:182.3-182.49: warning, this case is never reached -pat-subtyping.as:185.3-185.31: warning, this case is never reached -pat-subtyping.as:188.3-188.39: warning, this case is never reached -pat-subtyping.as:208.3-208.15: warning, this case is never reached -pat-subtyping.as:209.3-209.12: warning, this case is never reached -pat-subtyping.as:210.3-210.14: warning, this case is never reached -pat-subtyping.as:211.3-211.13: warning, this case is never reached -pat-subtyping.as:212.3-212.13: warning, this case is never reached -pat-subtyping.as:213.3-213.13: warning, this case is never reached -pat-subtyping.as:214.3-214.15: warning, this case is never reached -pat-subtyping.as:215.3-215.15: warning, this case is never reached +pat-subtyping.mo:6.3-6.12: warning, this case is never reached +pat-subtyping.mo:7.3-7.15: warning, this case is never reached +pat-subtyping.mo:10.3-10.20: warning, this case is never reached +pat-subtyping.mo:11.3-11.20: warning, this case is never reached +pat-subtyping.mo:18.3-18.28: warning, this case is never reached +pat-subtyping.mo:25.3-25.28: warning, this case is never reached +pat-subtyping.mo:32.3-32.42: warning, this case is never reached +pat-subtyping.mo:38.3-38.47: warning, this case is never reached +pat-subtyping.mo:44.3-44.44: warning, this case is never reached +pat-subtyping.mo:51.3-51.47: warning, this case is never reached +pat-subtyping.mo:58.3-58.44: warning, this case is never reached +pat-subtyping.mo:65.3-65.58: warning, this case is never reached +pat-subtyping.mo:71.3-71.63: warning, this case is never reached +pat-subtyping.mo:77.3-77.60: warning, this case is never reached +pat-subtyping.mo:84.3-84.71: warning, this case is never reached +pat-subtyping.mo:91.3-91.60: warning, this case is never reached +pat-subtyping.mo:97.3-97.49: warning, this case is never reached +pat-subtyping.mo:103.3-103.51: warning, this case is never reached +pat-subtyping.mo:109.3-109.42: warning, this case is never reached +pat-subtyping.mo:115.3-115.36: warning, this case is never reached +pat-subtyping.mo:119.3-119.17: warning, this case is never reached +pat-subtyping.mo:120.3-120.16: warning, this case is never reached +pat-subtyping.mo:130.3-130.33: warning, this case is never reached +pat-subtyping.mo:137.3-137.31: warning, this case is never reached +pat-subtyping.mo:138.3-138.15: warning, this case is never reached +pat-subtyping.mo:145.3-145.30: warning, this case is never reached +pat-subtyping.mo:156.3-156.31: warning, this case is never reached +pat-subtyping.mo:163.3-163.30: warning, this case is never reached +pat-subtyping.mo:171.3-171.34: warning, this case is never reached +pat-subtyping.mo:172.3-172.32: warning, this case is never reached +pat-subtyping.mo:182.3-182.49: warning, this case is never reached +pat-subtyping.mo:185.3-185.31: warning, this case is never reached +pat-subtyping.mo:188.3-188.39: warning, this case is never reached +pat-subtyping.mo:208.3-208.15: warning, this case is never reached +pat-subtyping.mo:209.3-209.12: warning, this case is never reached +pat-subtyping.mo:210.3-210.14: warning, this case is never reached +pat-subtyping.mo:211.3-211.13: warning, this case is never reached +pat-subtyping.mo:212.3-212.13: warning, this case is never reached +pat-subtyping.mo:213.3-213.13: warning, this case is never reached +pat-subtyping.mo:214.3-214.15: warning, this case is never reached +pat-subtyping.mo:215.3-215.15: warning, this case is never reached diff --git a/test/run/ok/pat-subtyping.run-ir.ok b/test/run/ok/pat-subtyping.run-ir.ok index 6fcdb8f75c5..76a04dc98af 100644 --- a/test/run/ok/pat-subtyping.run-ir.ok +++ b/test/run/ok/pat-subtyping.run-ir.ok @@ -1,41 +1,41 @@ -pat-subtyping.as:6.3-6.12: warning, this case is never reached -pat-subtyping.as:7.3-7.15: warning, this case is never reached -pat-subtyping.as:10.3-10.20: warning, this case is never reached -pat-subtyping.as:11.3-11.20: warning, this case is never reached -pat-subtyping.as:18.3-18.28: warning, this case is never reached -pat-subtyping.as:25.3-25.28: warning, this case is never reached -pat-subtyping.as:32.3-32.42: warning, this case is never reached -pat-subtyping.as:38.3-38.47: warning, this case is never reached -pat-subtyping.as:44.3-44.44: warning, this case is never reached -pat-subtyping.as:51.3-51.47: warning, this case is never reached -pat-subtyping.as:58.3-58.44: warning, this case is never reached -pat-subtyping.as:65.3-65.58: warning, this case is never reached -pat-subtyping.as:71.3-71.63: warning, this case is never reached -pat-subtyping.as:77.3-77.60: warning, this case is never reached -pat-subtyping.as:84.3-84.71: warning, this case is never reached -pat-subtyping.as:91.3-91.60: warning, this case is never reached -pat-subtyping.as:97.3-97.49: warning, this case is never reached -pat-subtyping.as:103.3-103.51: warning, this case is never reached -pat-subtyping.as:109.3-109.42: warning, this case is never reached -pat-subtyping.as:115.3-115.36: warning, this case is never reached -pat-subtyping.as:119.3-119.17: warning, this case is never reached -pat-subtyping.as:120.3-120.16: warning, this case is never reached -pat-subtyping.as:130.3-130.33: warning, this case is never reached -pat-subtyping.as:137.3-137.31: warning, this case is never reached -pat-subtyping.as:138.3-138.15: warning, this case is never reached -pat-subtyping.as:145.3-145.30: warning, this case is never reached -pat-subtyping.as:156.3-156.31: warning, this case is never reached -pat-subtyping.as:163.3-163.30: warning, this case is never reached -pat-subtyping.as:171.3-171.34: warning, this case is never reached -pat-subtyping.as:172.3-172.32: warning, this case is never reached -pat-subtyping.as:182.3-182.49: warning, this case is never reached -pat-subtyping.as:185.3-185.31: warning, this case is never reached -pat-subtyping.as:188.3-188.39: warning, this case is never reached -pat-subtyping.as:208.3-208.15: warning, this case is never reached -pat-subtyping.as:209.3-209.12: warning, this case is never reached -pat-subtyping.as:210.3-210.14: warning, this case is never reached -pat-subtyping.as:211.3-211.13: warning, this case is never reached -pat-subtyping.as:212.3-212.13: warning, this case is never reached -pat-subtyping.as:213.3-213.13: warning, this case is never reached -pat-subtyping.as:214.3-214.15: warning, this case is never reached -pat-subtyping.as:215.3-215.15: warning, this case is never reached +pat-subtyping.mo:6.3-6.12: warning, this case is never reached +pat-subtyping.mo:7.3-7.15: warning, this case is never reached +pat-subtyping.mo:10.3-10.20: warning, this case is never reached +pat-subtyping.mo:11.3-11.20: warning, this case is never reached +pat-subtyping.mo:18.3-18.28: warning, this case is never reached +pat-subtyping.mo:25.3-25.28: warning, this case is never reached +pat-subtyping.mo:32.3-32.42: warning, this case is never reached +pat-subtyping.mo:38.3-38.47: warning, this case is never reached +pat-subtyping.mo:44.3-44.44: warning, this case is never reached +pat-subtyping.mo:51.3-51.47: warning, this case is never reached +pat-subtyping.mo:58.3-58.44: warning, this case is never reached +pat-subtyping.mo:65.3-65.58: warning, this case is never reached +pat-subtyping.mo:71.3-71.63: warning, this case is never reached +pat-subtyping.mo:77.3-77.60: warning, this case is never reached +pat-subtyping.mo:84.3-84.71: warning, this case is never reached +pat-subtyping.mo:91.3-91.60: warning, this case is never reached +pat-subtyping.mo:97.3-97.49: warning, this case is never reached +pat-subtyping.mo:103.3-103.51: warning, this case is never reached +pat-subtyping.mo:109.3-109.42: warning, this case is never reached +pat-subtyping.mo:115.3-115.36: warning, this case is never reached +pat-subtyping.mo:119.3-119.17: warning, this case is never reached +pat-subtyping.mo:120.3-120.16: warning, this case is never reached +pat-subtyping.mo:130.3-130.33: warning, this case is never reached +pat-subtyping.mo:137.3-137.31: warning, this case is never reached +pat-subtyping.mo:138.3-138.15: warning, this case is never reached +pat-subtyping.mo:145.3-145.30: warning, this case is never reached +pat-subtyping.mo:156.3-156.31: warning, this case is never reached +pat-subtyping.mo:163.3-163.30: warning, this case is never reached +pat-subtyping.mo:171.3-171.34: warning, this case is never reached +pat-subtyping.mo:172.3-172.32: warning, this case is never reached +pat-subtyping.mo:182.3-182.49: warning, this case is never reached +pat-subtyping.mo:185.3-185.31: warning, this case is never reached +pat-subtyping.mo:188.3-188.39: warning, this case is never reached +pat-subtyping.mo:208.3-208.15: warning, this case is never reached +pat-subtyping.mo:209.3-209.12: warning, this case is never reached +pat-subtyping.mo:210.3-210.14: warning, this case is never reached +pat-subtyping.mo:211.3-211.13: warning, this case is never reached +pat-subtyping.mo:212.3-212.13: warning, this case is never reached +pat-subtyping.mo:213.3-213.13: warning, this case is never reached +pat-subtyping.mo:214.3-214.15: warning, this case is never reached +pat-subtyping.mo:215.3-215.15: warning, this case is never reached diff --git a/test/run/ok/pat-subtyping.run-low.ok b/test/run/ok/pat-subtyping.run-low.ok index 6fcdb8f75c5..76a04dc98af 100644 --- a/test/run/ok/pat-subtyping.run-low.ok +++ b/test/run/ok/pat-subtyping.run-low.ok @@ -1,41 +1,41 @@ -pat-subtyping.as:6.3-6.12: warning, this case is never reached -pat-subtyping.as:7.3-7.15: warning, this case is never reached -pat-subtyping.as:10.3-10.20: warning, this case is never reached -pat-subtyping.as:11.3-11.20: warning, this case is never reached -pat-subtyping.as:18.3-18.28: warning, this case is never reached -pat-subtyping.as:25.3-25.28: warning, this case is never reached -pat-subtyping.as:32.3-32.42: warning, this case is never reached -pat-subtyping.as:38.3-38.47: warning, this case is never reached -pat-subtyping.as:44.3-44.44: warning, this case is never reached -pat-subtyping.as:51.3-51.47: warning, this case is never reached -pat-subtyping.as:58.3-58.44: warning, this case is never reached -pat-subtyping.as:65.3-65.58: warning, this case is never reached -pat-subtyping.as:71.3-71.63: warning, this case is never reached -pat-subtyping.as:77.3-77.60: warning, this case is never reached -pat-subtyping.as:84.3-84.71: warning, this case is never reached -pat-subtyping.as:91.3-91.60: warning, this case is never reached -pat-subtyping.as:97.3-97.49: warning, this case is never reached -pat-subtyping.as:103.3-103.51: warning, this case is never reached -pat-subtyping.as:109.3-109.42: warning, this case is never reached -pat-subtyping.as:115.3-115.36: warning, this case is never reached -pat-subtyping.as:119.3-119.17: warning, this case is never reached -pat-subtyping.as:120.3-120.16: warning, this case is never reached -pat-subtyping.as:130.3-130.33: warning, this case is never reached -pat-subtyping.as:137.3-137.31: warning, this case is never reached -pat-subtyping.as:138.3-138.15: warning, this case is never reached -pat-subtyping.as:145.3-145.30: warning, this case is never reached -pat-subtyping.as:156.3-156.31: warning, this case is never reached -pat-subtyping.as:163.3-163.30: warning, this case is never reached -pat-subtyping.as:171.3-171.34: warning, this case is never reached -pat-subtyping.as:172.3-172.32: warning, this case is never reached -pat-subtyping.as:182.3-182.49: warning, this case is never reached -pat-subtyping.as:185.3-185.31: warning, this case is never reached -pat-subtyping.as:188.3-188.39: warning, this case is never reached -pat-subtyping.as:208.3-208.15: warning, this case is never reached -pat-subtyping.as:209.3-209.12: warning, this case is never reached -pat-subtyping.as:210.3-210.14: warning, this case is never reached -pat-subtyping.as:211.3-211.13: warning, this case is never reached -pat-subtyping.as:212.3-212.13: warning, this case is never reached -pat-subtyping.as:213.3-213.13: warning, this case is never reached -pat-subtyping.as:214.3-214.15: warning, this case is never reached -pat-subtyping.as:215.3-215.15: warning, this case is never reached +pat-subtyping.mo:6.3-6.12: warning, this case is never reached +pat-subtyping.mo:7.3-7.15: warning, this case is never reached +pat-subtyping.mo:10.3-10.20: warning, this case is never reached +pat-subtyping.mo:11.3-11.20: warning, this case is never reached +pat-subtyping.mo:18.3-18.28: warning, this case is never reached +pat-subtyping.mo:25.3-25.28: warning, this case is never reached +pat-subtyping.mo:32.3-32.42: warning, this case is never reached +pat-subtyping.mo:38.3-38.47: warning, this case is never reached +pat-subtyping.mo:44.3-44.44: warning, this case is never reached +pat-subtyping.mo:51.3-51.47: warning, this case is never reached +pat-subtyping.mo:58.3-58.44: warning, this case is never reached +pat-subtyping.mo:65.3-65.58: warning, this case is never reached +pat-subtyping.mo:71.3-71.63: warning, this case is never reached +pat-subtyping.mo:77.3-77.60: warning, this case is never reached +pat-subtyping.mo:84.3-84.71: warning, this case is never reached +pat-subtyping.mo:91.3-91.60: warning, this case is never reached +pat-subtyping.mo:97.3-97.49: warning, this case is never reached +pat-subtyping.mo:103.3-103.51: warning, this case is never reached +pat-subtyping.mo:109.3-109.42: warning, this case is never reached +pat-subtyping.mo:115.3-115.36: warning, this case is never reached +pat-subtyping.mo:119.3-119.17: warning, this case is never reached +pat-subtyping.mo:120.3-120.16: warning, this case is never reached +pat-subtyping.mo:130.3-130.33: warning, this case is never reached +pat-subtyping.mo:137.3-137.31: warning, this case is never reached +pat-subtyping.mo:138.3-138.15: warning, this case is never reached +pat-subtyping.mo:145.3-145.30: warning, this case is never reached +pat-subtyping.mo:156.3-156.31: warning, this case is never reached +pat-subtyping.mo:163.3-163.30: warning, this case is never reached +pat-subtyping.mo:171.3-171.34: warning, this case is never reached +pat-subtyping.mo:172.3-172.32: warning, this case is never reached +pat-subtyping.mo:182.3-182.49: warning, this case is never reached +pat-subtyping.mo:185.3-185.31: warning, this case is never reached +pat-subtyping.mo:188.3-188.39: warning, this case is never reached +pat-subtyping.mo:208.3-208.15: warning, this case is never reached +pat-subtyping.mo:209.3-209.12: warning, this case is never reached +pat-subtyping.mo:210.3-210.14: warning, this case is never reached +pat-subtyping.mo:211.3-211.13: warning, this case is never reached +pat-subtyping.mo:212.3-212.13: warning, this case is never reached +pat-subtyping.mo:213.3-213.13: warning, this case is never reached +pat-subtyping.mo:214.3-214.15: warning, this case is never reached +pat-subtyping.mo:215.3-215.15: warning, this case is never reached diff --git a/test/run/ok/pat-subtyping.run.ok b/test/run/ok/pat-subtyping.run.ok index 6fcdb8f75c5..76a04dc98af 100644 --- a/test/run/ok/pat-subtyping.run.ok +++ b/test/run/ok/pat-subtyping.run.ok @@ -1,41 +1,41 @@ -pat-subtyping.as:6.3-6.12: warning, this case is never reached -pat-subtyping.as:7.3-7.15: warning, this case is never reached -pat-subtyping.as:10.3-10.20: warning, this case is never reached -pat-subtyping.as:11.3-11.20: warning, this case is never reached -pat-subtyping.as:18.3-18.28: warning, this case is never reached -pat-subtyping.as:25.3-25.28: warning, this case is never reached -pat-subtyping.as:32.3-32.42: warning, this case is never reached -pat-subtyping.as:38.3-38.47: warning, this case is never reached -pat-subtyping.as:44.3-44.44: warning, this case is never reached -pat-subtyping.as:51.3-51.47: warning, this case is never reached -pat-subtyping.as:58.3-58.44: warning, this case is never reached -pat-subtyping.as:65.3-65.58: warning, this case is never reached -pat-subtyping.as:71.3-71.63: warning, this case is never reached -pat-subtyping.as:77.3-77.60: warning, this case is never reached -pat-subtyping.as:84.3-84.71: warning, this case is never reached -pat-subtyping.as:91.3-91.60: warning, this case is never reached -pat-subtyping.as:97.3-97.49: warning, this case is never reached -pat-subtyping.as:103.3-103.51: warning, this case is never reached -pat-subtyping.as:109.3-109.42: warning, this case is never reached -pat-subtyping.as:115.3-115.36: warning, this case is never reached -pat-subtyping.as:119.3-119.17: warning, this case is never reached -pat-subtyping.as:120.3-120.16: warning, this case is never reached -pat-subtyping.as:130.3-130.33: warning, this case is never reached -pat-subtyping.as:137.3-137.31: warning, this case is never reached -pat-subtyping.as:138.3-138.15: warning, this case is never reached -pat-subtyping.as:145.3-145.30: warning, this case is never reached -pat-subtyping.as:156.3-156.31: warning, this case is never reached -pat-subtyping.as:163.3-163.30: warning, this case is never reached -pat-subtyping.as:171.3-171.34: warning, this case is never reached -pat-subtyping.as:172.3-172.32: warning, this case is never reached -pat-subtyping.as:182.3-182.49: warning, this case is never reached -pat-subtyping.as:185.3-185.31: warning, this case is never reached -pat-subtyping.as:188.3-188.39: warning, this case is never reached -pat-subtyping.as:208.3-208.15: warning, this case is never reached -pat-subtyping.as:209.3-209.12: warning, this case is never reached -pat-subtyping.as:210.3-210.14: warning, this case is never reached -pat-subtyping.as:211.3-211.13: warning, this case is never reached -pat-subtyping.as:212.3-212.13: warning, this case is never reached -pat-subtyping.as:213.3-213.13: warning, this case is never reached -pat-subtyping.as:214.3-214.15: warning, this case is never reached -pat-subtyping.as:215.3-215.15: warning, this case is never reached +pat-subtyping.mo:6.3-6.12: warning, this case is never reached +pat-subtyping.mo:7.3-7.15: warning, this case is never reached +pat-subtyping.mo:10.3-10.20: warning, this case is never reached +pat-subtyping.mo:11.3-11.20: warning, this case is never reached +pat-subtyping.mo:18.3-18.28: warning, this case is never reached +pat-subtyping.mo:25.3-25.28: warning, this case is never reached +pat-subtyping.mo:32.3-32.42: warning, this case is never reached +pat-subtyping.mo:38.3-38.47: warning, this case is never reached +pat-subtyping.mo:44.3-44.44: warning, this case is never reached +pat-subtyping.mo:51.3-51.47: warning, this case is never reached +pat-subtyping.mo:58.3-58.44: warning, this case is never reached +pat-subtyping.mo:65.3-65.58: warning, this case is never reached +pat-subtyping.mo:71.3-71.63: warning, this case is never reached +pat-subtyping.mo:77.3-77.60: warning, this case is never reached +pat-subtyping.mo:84.3-84.71: warning, this case is never reached +pat-subtyping.mo:91.3-91.60: warning, this case is never reached +pat-subtyping.mo:97.3-97.49: warning, this case is never reached +pat-subtyping.mo:103.3-103.51: warning, this case is never reached +pat-subtyping.mo:109.3-109.42: warning, this case is never reached +pat-subtyping.mo:115.3-115.36: warning, this case is never reached +pat-subtyping.mo:119.3-119.17: warning, this case is never reached +pat-subtyping.mo:120.3-120.16: warning, this case is never reached +pat-subtyping.mo:130.3-130.33: warning, this case is never reached +pat-subtyping.mo:137.3-137.31: warning, this case is never reached +pat-subtyping.mo:138.3-138.15: warning, this case is never reached +pat-subtyping.mo:145.3-145.30: warning, this case is never reached +pat-subtyping.mo:156.3-156.31: warning, this case is never reached +pat-subtyping.mo:163.3-163.30: warning, this case is never reached +pat-subtyping.mo:171.3-171.34: warning, this case is never reached +pat-subtyping.mo:172.3-172.32: warning, this case is never reached +pat-subtyping.mo:182.3-182.49: warning, this case is never reached +pat-subtyping.mo:185.3-185.31: warning, this case is never reached +pat-subtyping.mo:188.3-188.39: warning, this case is never reached +pat-subtyping.mo:208.3-208.15: warning, this case is never reached +pat-subtyping.mo:209.3-209.12: warning, this case is never reached +pat-subtyping.mo:210.3-210.14: warning, this case is never reached +pat-subtyping.mo:211.3-211.13: warning, this case is never reached +pat-subtyping.mo:212.3-212.13: warning, this case is never reached +pat-subtyping.mo:213.3-213.13: warning, this case is never reached +pat-subtyping.mo:214.3-214.15: warning, this case is never reached +pat-subtyping.mo:215.3-215.15: warning, this case is never reached diff --git a/test/run/ok/pat-subtyping.tc.ok b/test/run/ok/pat-subtyping.tc.ok index 6fcdb8f75c5..76a04dc98af 100644 --- a/test/run/ok/pat-subtyping.tc.ok +++ b/test/run/ok/pat-subtyping.tc.ok @@ -1,41 +1,41 @@ -pat-subtyping.as:6.3-6.12: warning, this case is never reached -pat-subtyping.as:7.3-7.15: warning, this case is never reached -pat-subtyping.as:10.3-10.20: warning, this case is never reached -pat-subtyping.as:11.3-11.20: warning, this case is never reached -pat-subtyping.as:18.3-18.28: warning, this case is never reached -pat-subtyping.as:25.3-25.28: warning, this case is never reached -pat-subtyping.as:32.3-32.42: warning, this case is never reached -pat-subtyping.as:38.3-38.47: warning, this case is never reached -pat-subtyping.as:44.3-44.44: warning, this case is never reached -pat-subtyping.as:51.3-51.47: warning, this case is never reached -pat-subtyping.as:58.3-58.44: warning, this case is never reached -pat-subtyping.as:65.3-65.58: warning, this case is never reached -pat-subtyping.as:71.3-71.63: warning, this case is never reached -pat-subtyping.as:77.3-77.60: warning, this case is never reached -pat-subtyping.as:84.3-84.71: warning, this case is never reached -pat-subtyping.as:91.3-91.60: warning, this case is never reached -pat-subtyping.as:97.3-97.49: warning, this case is never reached -pat-subtyping.as:103.3-103.51: warning, this case is never reached -pat-subtyping.as:109.3-109.42: warning, this case is never reached -pat-subtyping.as:115.3-115.36: warning, this case is never reached -pat-subtyping.as:119.3-119.17: warning, this case is never reached -pat-subtyping.as:120.3-120.16: warning, this case is never reached -pat-subtyping.as:130.3-130.33: warning, this case is never reached -pat-subtyping.as:137.3-137.31: warning, this case is never reached -pat-subtyping.as:138.3-138.15: warning, this case is never reached -pat-subtyping.as:145.3-145.30: warning, this case is never reached -pat-subtyping.as:156.3-156.31: warning, this case is never reached -pat-subtyping.as:163.3-163.30: warning, this case is never reached -pat-subtyping.as:171.3-171.34: warning, this case is never reached -pat-subtyping.as:172.3-172.32: warning, this case is never reached -pat-subtyping.as:182.3-182.49: warning, this case is never reached -pat-subtyping.as:185.3-185.31: warning, this case is never reached -pat-subtyping.as:188.3-188.39: warning, this case is never reached -pat-subtyping.as:208.3-208.15: warning, this case is never reached -pat-subtyping.as:209.3-209.12: warning, this case is never reached -pat-subtyping.as:210.3-210.14: warning, this case is never reached -pat-subtyping.as:211.3-211.13: warning, this case is never reached -pat-subtyping.as:212.3-212.13: warning, this case is never reached -pat-subtyping.as:213.3-213.13: warning, this case is never reached -pat-subtyping.as:214.3-214.15: warning, this case is never reached -pat-subtyping.as:215.3-215.15: warning, this case is never reached +pat-subtyping.mo:6.3-6.12: warning, this case is never reached +pat-subtyping.mo:7.3-7.15: warning, this case is never reached +pat-subtyping.mo:10.3-10.20: warning, this case is never reached +pat-subtyping.mo:11.3-11.20: warning, this case is never reached +pat-subtyping.mo:18.3-18.28: warning, this case is never reached +pat-subtyping.mo:25.3-25.28: warning, this case is never reached +pat-subtyping.mo:32.3-32.42: warning, this case is never reached +pat-subtyping.mo:38.3-38.47: warning, this case is never reached +pat-subtyping.mo:44.3-44.44: warning, this case is never reached +pat-subtyping.mo:51.3-51.47: warning, this case is never reached +pat-subtyping.mo:58.3-58.44: warning, this case is never reached +pat-subtyping.mo:65.3-65.58: warning, this case is never reached +pat-subtyping.mo:71.3-71.63: warning, this case is never reached +pat-subtyping.mo:77.3-77.60: warning, this case is never reached +pat-subtyping.mo:84.3-84.71: warning, this case is never reached +pat-subtyping.mo:91.3-91.60: warning, this case is never reached +pat-subtyping.mo:97.3-97.49: warning, this case is never reached +pat-subtyping.mo:103.3-103.51: warning, this case is never reached +pat-subtyping.mo:109.3-109.42: warning, this case is never reached +pat-subtyping.mo:115.3-115.36: warning, this case is never reached +pat-subtyping.mo:119.3-119.17: warning, this case is never reached +pat-subtyping.mo:120.3-120.16: warning, this case is never reached +pat-subtyping.mo:130.3-130.33: warning, this case is never reached +pat-subtyping.mo:137.3-137.31: warning, this case is never reached +pat-subtyping.mo:138.3-138.15: warning, this case is never reached +pat-subtyping.mo:145.3-145.30: warning, this case is never reached +pat-subtyping.mo:156.3-156.31: warning, this case is never reached +pat-subtyping.mo:163.3-163.30: warning, this case is never reached +pat-subtyping.mo:171.3-171.34: warning, this case is never reached +pat-subtyping.mo:172.3-172.32: warning, this case is never reached +pat-subtyping.mo:182.3-182.49: warning, this case is never reached +pat-subtyping.mo:185.3-185.31: warning, this case is never reached +pat-subtyping.mo:188.3-188.39: warning, this case is never reached +pat-subtyping.mo:208.3-208.15: warning, this case is never reached +pat-subtyping.mo:209.3-209.12: warning, this case is never reached +pat-subtyping.mo:210.3-210.14: warning, this case is never reached +pat-subtyping.mo:211.3-211.13: warning, this case is never reached +pat-subtyping.mo:212.3-212.13: warning, this case is never reached +pat-subtyping.mo:213.3-213.13: warning, this case is never reached +pat-subtyping.mo:214.3-214.15: warning, this case is never reached +pat-subtyping.mo:215.3-215.15: warning, this case is never reached diff --git a/test/run/ok/pat-subtyping.wasm.stderr.ok b/test/run/ok/pat-subtyping.wasm.stderr.ok index b3256f3ba03..42db4b04d5b 100644 --- a/test/run/ok/pat-subtyping.wasm.stderr.ok +++ b/test/run/ok/pat-subtyping.wasm.stderr.ok @@ -1,42 +1,42 @@ -pat-subtyping.as:6.3-6.12: warning, this case is never reached -pat-subtyping.as:7.3-7.15: warning, this case is never reached -pat-subtyping.as:10.3-10.20: warning, this case is never reached -pat-subtyping.as:11.3-11.20: warning, this case is never reached -pat-subtyping.as:18.3-18.28: warning, this case is never reached -pat-subtyping.as:25.3-25.28: warning, this case is never reached -pat-subtyping.as:32.3-32.42: warning, this case is never reached -pat-subtyping.as:38.3-38.47: warning, this case is never reached -pat-subtyping.as:44.3-44.44: warning, this case is never reached -pat-subtyping.as:51.3-51.47: warning, this case is never reached -pat-subtyping.as:58.3-58.44: warning, this case is never reached -pat-subtyping.as:65.3-65.58: warning, this case is never reached -pat-subtyping.as:71.3-71.63: warning, this case is never reached -pat-subtyping.as:77.3-77.60: warning, this case is never reached -pat-subtyping.as:84.3-84.71: warning, this case is never reached -pat-subtyping.as:91.3-91.60: warning, this case is never reached -pat-subtyping.as:97.3-97.49: warning, this case is never reached -pat-subtyping.as:103.3-103.51: warning, this case is never reached -pat-subtyping.as:109.3-109.42: warning, this case is never reached -pat-subtyping.as:115.3-115.36: warning, this case is never reached -pat-subtyping.as:119.3-119.17: warning, this case is never reached -pat-subtyping.as:120.3-120.16: warning, this case is never reached -pat-subtyping.as:130.3-130.33: warning, this case is never reached -pat-subtyping.as:137.3-137.31: warning, this case is never reached -pat-subtyping.as:138.3-138.15: warning, this case is never reached -pat-subtyping.as:145.3-145.30: warning, this case is never reached -pat-subtyping.as:156.3-156.31: warning, this case is never reached -pat-subtyping.as:163.3-163.30: warning, this case is never reached -pat-subtyping.as:171.3-171.34: warning, this case is never reached -pat-subtyping.as:172.3-172.32: warning, this case is never reached -pat-subtyping.as:182.3-182.49: warning, this case is never reached -pat-subtyping.as:185.3-185.31: warning, this case is never reached -pat-subtyping.as:188.3-188.39: warning, this case is never reached -pat-subtyping.as:208.3-208.15: warning, this case is never reached -pat-subtyping.as:209.3-209.12: warning, this case is never reached -pat-subtyping.as:210.3-210.14: warning, this case is never reached -pat-subtyping.as:211.3-211.13: warning, this case is never reached -pat-subtyping.as:212.3-212.13: warning, this case is never reached -pat-subtyping.as:213.3-213.13: warning, this case is never reached -pat-subtyping.as:214.3-214.15: warning, this case is never reached -pat-subtyping.as:215.3-215.15: warning, this case is never reached +pat-subtyping.mo:6.3-6.12: warning, this case is never reached +pat-subtyping.mo:7.3-7.15: warning, this case is never reached +pat-subtyping.mo:10.3-10.20: warning, this case is never reached +pat-subtyping.mo:11.3-11.20: warning, this case is never reached +pat-subtyping.mo:18.3-18.28: warning, this case is never reached +pat-subtyping.mo:25.3-25.28: warning, this case is never reached +pat-subtyping.mo:32.3-32.42: warning, this case is never reached +pat-subtyping.mo:38.3-38.47: warning, this case is never reached +pat-subtyping.mo:44.3-44.44: warning, this case is never reached +pat-subtyping.mo:51.3-51.47: warning, this case is never reached +pat-subtyping.mo:58.3-58.44: warning, this case is never reached +pat-subtyping.mo:65.3-65.58: warning, this case is never reached +pat-subtyping.mo:71.3-71.63: warning, this case is never reached +pat-subtyping.mo:77.3-77.60: warning, this case is never reached +pat-subtyping.mo:84.3-84.71: warning, this case is never reached +pat-subtyping.mo:91.3-91.60: warning, this case is never reached +pat-subtyping.mo:97.3-97.49: warning, this case is never reached +pat-subtyping.mo:103.3-103.51: warning, this case is never reached +pat-subtyping.mo:109.3-109.42: warning, this case is never reached +pat-subtyping.mo:115.3-115.36: warning, this case is never reached +pat-subtyping.mo:119.3-119.17: warning, this case is never reached +pat-subtyping.mo:120.3-120.16: warning, this case is never reached +pat-subtyping.mo:130.3-130.33: warning, this case is never reached +pat-subtyping.mo:137.3-137.31: warning, this case is never reached +pat-subtyping.mo:138.3-138.15: warning, this case is never reached +pat-subtyping.mo:145.3-145.30: warning, this case is never reached +pat-subtyping.mo:156.3-156.31: warning, this case is never reached +pat-subtyping.mo:163.3-163.30: warning, this case is never reached +pat-subtyping.mo:171.3-171.34: warning, this case is never reached +pat-subtyping.mo:172.3-172.32: warning, this case is never reached +pat-subtyping.mo:182.3-182.49: warning, this case is never reached +pat-subtyping.mo:185.3-185.31: warning, this case is never reached +pat-subtyping.mo:188.3-188.39: warning, this case is never reached +pat-subtyping.mo:208.3-208.15: warning, this case is never reached +pat-subtyping.mo:209.3-209.12: warning, this case is never reached +pat-subtyping.mo:210.3-210.14: warning, this case is never reached +pat-subtyping.mo:211.3-211.13: warning, this case is never reached +pat-subtyping.mo:212.3-212.13: warning, this case is never reached +pat-subtyping.mo:213.3-213.13: warning, this case is never reached +pat-subtyping.mo:214.3-214.15: warning, this case is never reached +pat-subtyping.mo:215.3-215.15: warning, this case is never reached compile_lit_pat: (FloatLit 2.5) diff --git a/test/run/ok/switch.idl.stderr.ok b/test/run/ok/switch.idl.stderr.ok index 0a7d23907a0..d8896858554 100644 --- a/test/run/ok/switch.idl.stderr.ok +++ b/test/run/ok/switch.idl.stderr.ok @@ -1,17 +1,17 @@ -switch.as:86.29-86.30: warning, this pattern is never matched -switch.as:75.11-77.2: warning, the cases in this switch over type +switch.mo:86.29-86.30: warning, this pattern is never matched +switch.mo:75.11-77.2: warning, the cases in this switch over type ?Int do not cover value ?(_) -switch.as:81.3-81.14: warning, the cases in this switch over type +switch.mo:81.3-81.14: warning, the cases in this switch over type Nat do not cover value _ -switch.as:92.11-94.2: warning, the cases in this switch over type +switch.mo:92.11-94.2: warning, the cases in this switch over type ?Nat do not cover value null -switch.as:97.11-99.2: warning, the cases in this switch over type +switch.mo:97.11-99.2: warning, the cases in this switch over type ?Nat do not cover value ?(_) diff --git a/test/run/ok/switch.run-ir.ok b/test/run/ok/switch.run-ir.ok index 0a7d23907a0..d8896858554 100644 --- a/test/run/ok/switch.run-ir.ok +++ b/test/run/ok/switch.run-ir.ok @@ -1,17 +1,17 @@ -switch.as:86.29-86.30: warning, this pattern is never matched -switch.as:75.11-77.2: warning, the cases in this switch over type +switch.mo:86.29-86.30: warning, this pattern is never matched +switch.mo:75.11-77.2: warning, the cases in this switch over type ?Int do not cover value ?(_) -switch.as:81.3-81.14: warning, the cases in this switch over type +switch.mo:81.3-81.14: warning, the cases in this switch over type Nat do not cover value _ -switch.as:92.11-94.2: warning, the cases in this switch over type +switch.mo:92.11-94.2: warning, the cases in this switch over type ?Nat do not cover value null -switch.as:97.11-99.2: warning, the cases in this switch over type +switch.mo:97.11-99.2: warning, the cases in this switch over type ?Nat do not cover value ?(_) diff --git a/test/run/ok/switch.run-low.ok b/test/run/ok/switch.run-low.ok index 0a7d23907a0..d8896858554 100644 --- a/test/run/ok/switch.run-low.ok +++ b/test/run/ok/switch.run-low.ok @@ -1,17 +1,17 @@ -switch.as:86.29-86.30: warning, this pattern is never matched -switch.as:75.11-77.2: warning, the cases in this switch over type +switch.mo:86.29-86.30: warning, this pattern is never matched +switch.mo:75.11-77.2: warning, the cases in this switch over type ?Int do not cover value ?(_) -switch.as:81.3-81.14: warning, the cases in this switch over type +switch.mo:81.3-81.14: warning, the cases in this switch over type Nat do not cover value _ -switch.as:92.11-94.2: warning, the cases in this switch over type +switch.mo:92.11-94.2: warning, the cases in this switch over type ?Nat do not cover value null -switch.as:97.11-99.2: warning, the cases in this switch over type +switch.mo:97.11-99.2: warning, the cases in this switch over type ?Nat do not cover value ?(_) diff --git a/test/run/ok/switch.run.ok b/test/run/ok/switch.run.ok index 0a7d23907a0..d8896858554 100644 --- a/test/run/ok/switch.run.ok +++ b/test/run/ok/switch.run.ok @@ -1,17 +1,17 @@ -switch.as:86.29-86.30: warning, this pattern is never matched -switch.as:75.11-77.2: warning, the cases in this switch over type +switch.mo:86.29-86.30: warning, this pattern is never matched +switch.mo:75.11-77.2: warning, the cases in this switch over type ?Int do not cover value ?(_) -switch.as:81.3-81.14: warning, the cases in this switch over type +switch.mo:81.3-81.14: warning, the cases in this switch over type Nat do not cover value _ -switch.as:92.11-94.2: warning, the cases in this switch over type +switch.mo:92.11-94.2: warning, the cases in this switch over type ?Nat do not cover value null -switch.as:97.11-99.2: warning, the cases in this switch over type +switch.mo:97.11-99.2: warning, the cases in this switch over type ?Nat do not cover value ?(_) diff --git a/test/run/ok/switch.tc.ok b/test/run/ok/switch.tc.ok index 0a7d23907a0..d8896858554 100644 --- a/test/run/ok/switch.tc.ok +++ b/test/run/ok/switch.tc.ok @@ -1,17 +1,17 @@ -switch.as:86.29-86.30: warning, this pattern is never matched -switch.as:75.11-77.2: warning, the cases in this switch over type +switch.mo:86.29-86.30: warning, this pattern is never matched +switch.mo:75.11-77.2: warning, the cases in this switch over type ?Int do not cover value ?(_) -switch.as:81.3-81.14: warning, the cases in this switch over type +switch.mo:81.3-81.14: warning, the cases in this switch over type Nat do not cover value _ -switch.as:92.11-94.2: warning, the cases in this switch over type +switch.mo:92.11-94.2: warning, the cases in this switch over type ?Nat do not cover value null -switch.as:97.11-99.2: warning, the cases in this switch over type +switch.mo:97.11-99.2: warning, the cases in this switch over type ?Nat do not cover value ?(_) diff --git a/test/run/ok/switch.wasm.stderr.ok b/test/run/ok/switch.wasm.stderr.ok index 0a7d23907a0..d8896858554 100644 --- a/test/run/ok/switch.wasm.stderr.ok +++ b/test/run/ok/switch.wasm.stderr.ok @@ -1,17 +1,17 @@ -switch.as:86.29-86.30: warning, this pattern is never matched -switch.as:75.11-77.2: warning, the cases in this switch over type +switch.mo:86.29-86.30: warning, this pattern is never matched +switch.mo:75.11-77.2: warning, the cases in this switch over type ?Int do not cover value ?(_) -switch.as:81.3-81.14: warning, the cases in this switch over type +switch.mo:81.3-81.14: warning, the cases in this switch over type Nat do not cover value _ -switch.as:92.11-94.2: warning, the cases in this switch over type +switch.mo:92.11-94.2: warning, the cases in this switch over type ?Nat do not cover value null -switch.as:97.11-99.2: warning, the cases in this switch over type +switch.mo:97.11-99.2: warning, the cases in this switch over type ?Nat do not cover value ?(_) diff --git a/test/run/ok/type-inference.idl.stderr.ok b/test/run/ok/type-inference.idl.stderr.ok index 2e8cbb9f0af..a1077f043f0 100644 --- a/test/run/ok/type-inference.idl.stderr.ok +++ b/test/run/ok/type-inference.idl.stderr.ok @@ -1,37 +1,37 @@ -type-inference.as:3.9-3.28: warning, this if has type Any because branches have inconsistent types, +type-inference.mo:3.9-3.28: warning, this if has type Any because branches have inconsistent types, true produces Bool false produces Nat -type-inference.as:4.9-4.34: warning, this if has type Any because branches have inconsistent types, +type-inference.mo:4.9-4.34: warning, this if has type Any because branches have inconsistent types, true produces Bool false produces [var Nat] -type-inference.as:5.9-5.27: warning, this if has type Any because branches have inconsistent types, +type-inference.mo:5.9-5.27: warning, this if has type Any because branches have inconsistent types, true produces Nat false produces Float -type-inference.as:6.9-6.29: warning, this if has type Any because branches have inconsistent types, +type-inference.mo:6.9-6.29: warning, this if has type Any because branches have inconsistent types, true produces () false produces {} -type-inference.as:11.33-11.41: warning, the switch has type Any because branches have inconsistent types, +type-inference.mo:11.33-11.41: warning, the switch has type Any because branches have inconsistent types, this case produces type Bool the previous produce type Nat -type-inference.as:12.33-12.47: warning, the switch has type Any because branches have inconsistent types, +type-inference.mo:12.33-12.47: warning, the switch has type Any because branches have inconsistent types, this case produces type Bool the previous produce type [var Nat] -type-inference.as:13.43-13.56: warning, the switch has type Any because branches have inconsistent types, +type-inference.mo:13.43-13.56: warning, the switch has type Any because branches have inconsistent types, this case produces type Int the previous produce type Text -type-inference.as:19.9-19.18: warning, this array has type [Any] because elements have inconsistent types -type-inference.as:20.9-20.24: warning, this array has type [Any] because elements have inconsistent types +type-inference.mo:19.9-19.18: warning, this array has type [Any] because elements have inconsistent types +type-inference.mo:20.9-20.24: warning, this array has type [Any] because elements have inconsistent types diff --git a/test/run/ok/type-inference.run-ir.ok b/test/run/ok/type-inference.run-ir.ok index 2e8cbb9f0af..a1077f043f0 100644 --- a/test/run/ok/type-inference.run-ir.ok +++ b/test/run/ok/type-inference.run-ir.ok @@ -1,37 +1,37 @@ -type-inference.as:3.9-3.28: warning, this if has type Any because branches have inconsistent types, +type-inference.mo:3.9-3.28: warning, this if has type Any because branches have inconsistent types, true produces Bool false produces Nat -type-inference.as:4.9-4.34: warning, this if has type Any because branches have inconsistent types, +type-inference.mo:4.9-4.34: warning, this if has type Any because branches have inconsistent types, true produces Bool false produces [var Nat] -type-inference.as:5.9-5.27: warning, this if has type Any because branches have inconsistent types, +type-inference.mo:5.9-5.27: warning, this if has type Any because branches have inconsistent types, true produces Nat false produces Float -type-inference.as:6.9-6.29: warning, this if has type Any because branches have inconsistent types, +type-inference.mo:6.9-6.29: warning, this if has type Any because branches have inconsistent types, true produces () false produces {} -type-inference.as:11.33-11.41: warning, the switch has type Any because branches have inconsistent types, +type-inference.mo:11.33-11.41: warning, the switch has type Any because branches have inconsistent types, this case produces type Bool the previous produce type Nat -type-inference.as:12.33-12.47: warning, the switch has type Any because branches have inconsistent types, +type-inference.mo:12.33-12.47: warning, the switch has type Any because branches have inconsistent types, this case produces type Bool the previous produce type [var Nat] -type-inference.as:13.43-13.56: warning, the switch has type Any because branches have inconsistent types, +type-inference.mo:13.43-13.56: warning, the switch has type Any because branches have inconsistent types, this case produces type Int the previous produce type Text -type-inference.as:19.9-19.18: warning, this array has type [Any] because elements have inconsistent types -type-inference.as:20.9-20.24: warning, this array has type [Any] because elements have inconsistent types +type-inference.mo:19.9-19.18: warning, this array has type [Any] because elements have inconsistent types +type-inference.mo:20.9-20.24: warning, this array has type [Any] because elements have inconsistent types diff --git a/test/run/ok/type-inference.run-low.ok b/test/run/ok/type-inference.run-low.ok index 2e8cbb9f0af..a1077f043f0 100644 --- a/test/run/ok/type-inference.run-low.ok +++ b/test/run/ok/type-inference.run-low.ok @@ -1,37 +1,37 @@ -type-inference.as:3.9-3.28: warning, this if has type Any because branches have inconsistent types, +type-inference.mo:3.9-3.28: warning, this if has type Any because branches have inconsistent types, true produces Bool false produces Nat -type-inference.as:4.9-4.34: warning, this if has type Any because branches have inconsistent types, +type-inference.mo:4.9-4.34: warning, this if has type Any because branches have inconsistent types, true produces Bool false produces [var Nat] -type-inference.as:5.9-5.27: warning, this if has type Any because branches have inconsistent types, +type-inference.mo:5.9-5.27: warning, this if has type Any because branches have inconsistent types, true produces Nat false produces Float -type-inference.as:6.9-6.29: warning, this if has type Any because branches have inconsistent types, +type-inference.mo:6.9-6.29: warning, this if has type Any because branches have inconsistent types, true produces () false produces {} -type-inference.as:11.33-11.41: warning, the switch has type Any because branches have inconsistent types, +type-inference.mo:11.33-11.41: warning, the switch has type Any because branches have inconsistent types, this case produces type Bool the previous produce type Nat -type-inference.as:12.33-12.47: warning, the switch has type Any because branches have inconsistent types, +type-inference.mo:12.33-12.47: warning, the switch has type Any because branches have inconsistent types, this case produces type Bool the previous produce type [var Nat] -type-inference.as:13.43-13.56: warning, the switch has type Any because branches have inconsistent types, +type-inference.mo:13.43-13.56: warning, the switch has type Any because branches have inconsistent types, this case produces type Int the previous produce type Text -type-inference.as:19.9-19.18: warning, this array has type [Any] because elements have inconsistent types -type-inference.as:20.9-20.24: warning, this array has type [Any] because elements have inconsistent types +type-inference.mo:19.9-19.18: warning, this array has type [Any] because elements have inconsistent types +type-inference.mo:20.9-20.24: warning, this array has type [Any] because elements have inconsistent types diff --git a/test/run/ok/type-inference.run.ok b/test/run/ok/type-inference.run.ok index 2e8cbb9f0af..a1077f043f0 100644 --- a/test/run/ok/type-inference.run.ok +++ b/test/run/ok/type-inference.run.ok @@ -1,37 +1,37 @@ -type-inference.as:3.9-3.28: warning, this if has type Any because branches have inconsistent types, +type-inference.mo:3.9-3.28: warning, this if has type Any because branches have inconsistent types, true produces Bool false produces Nat -type-inference.as:4.9-4.34: warning, this if has type Any because branches have inconsistent types, +type-inference.mo:4.9-4.34: warning, this if has type Any because branches have inconsistent types, true produces Bool false produces [var Nat] -type-inference.as:5.9-5.27: warning, this if has type Any because branches have inconsistent types, +type-inference.mo:5.9-5.27: warning, this if has type Any because branches have inconsistent types, true produces Nat false produces Float -type-inference.as:6.9-6.29: warning, this if has type Any because branches have inconsistent types, +type-inference.mo:6.9-6.29: warning, this if has type Any because branches have inconsistent types, true produces () false produces {} -type-inference.as:11.33-11.41: warning, the switch has type Any because branches have inconsistent types, +type-inference.mo:11.33-11.41: warning, the switch has type Any because branches have inconsistent types, this case produces type Bool the previous produce type Nat -type-inference.as:12.33-12.47: warning, the switch has type Any because branches have inconsistent types, +type-inference.mo:12.33-12.47: warning, the switch has type Any because branches have inconsistent types, this case produces type Bool the previous produce type [var Nat] -type-inference.as:13.43-13.56: warning, the switch has type Any because branches have inconsistent types, +type-inference.mo:13.43-13.56: warning, the switch has type Any because branches have inconsistent types, this case produces type Int the previous produce type Text -type-inference.as:19.9-19.18: warning, this array has type [Any] because elements have inconsistent types -type-inference.as:20.9-20.24: warning, this array has type [Any] because elements have inconsistent types +type-inference.mo:19.9-19.18: warning, this array has type [Any] because elements have inconsistent types +type-inference.mo:20.9-20.24: warning, this array has type [Any] because elements have inconsistent types diff --git a/test/run/ok/type-inference.tc.ok b/test/run/ok/type-inference.tc.ok index 2e8cbb9f0af..a1077f043f0 100644 --- a/test/run/ok/type-inference.tc.ok +++ b/test/run/ok/type-inference.tc.ok @@ -1,37 +1,37 @@ -type-inference.as:3.9-3.28: warning, this if has type Any because branches have inconsistent types, +type-inference.mo:3.9-3.28: warning, this if has type Any because branches have inconsistent types, true produces Bool false produces Nat -type-inference.as:4.9-4.34: warning, this if has type Any because branches have inconsistent types, +type-inference.mo:4.9-4.34: warning, this if has type Any because branches have inconsistent types, true produces Bool false produces [var Nat] -type-inference.as:5.9-5.27: warning, this if has type Any because branches have inconsistent types, +type-inference.mo:5.9-5.27: warning, this if has type Any because branches have inconsistent types, true produces Nat false produces Float -type-inference.as:6.9-6.29: warning, this if has type Any because branches have inconsistent types, +type-inference.mo:6.9-6.29: warning, this if has type Any because branches have inconsistent types, true produces () false produces {} -type-inference.as:11.33-11.41: warning, the switch has type Any because branches have inconsistent types, +type-inference.mo:11.33-11.41: warning, the switch has type Any because branches have inconsistent types, this case produces type Bool the previous produce type Nat -type-inference.as:12.33-12.47: warning, the switch has type Any because branches have inconsistent types, +type-inference.mo:12.33-12.47: warning, the switch has type Any because branches have inconsistent types, this case produces type Bool the previous produce type [var Nat] -type-inference.as:13.43-13.56: warning, the switch has type Any because branches have inconsistent types, +type-inference.mo:13.43-13.56: warning, the switch has type Any because branches have inconsistent types, this case produces type Int the previous produce type Text -type-inference.as:19.9-19.18: warning, this array has type [Any] because elements have inconsistent types -type-inference.as:20.9-20.24: warning, this array has type [Any] because elements have inconsistent types +type-inference.mo:19.9-19.18: warning, this array has type [Any] because elements have inconsistent types +type-inference.mo:20.9-20.24: warning, this array has type [Any] because elements have inconsistent types diff --git a/test/run/ok/type-inference.wasm.stderr.ok b/test/run/ok/type-inference.wasm.stderr.ok index 8ce0ed1f0e7..b8e76a3ed94 100644 --- a/test/run/ok/type-inference.wasm.stderr.ok +++ b/test/run/ok/type-inference.wasm.stderr.ok @@ -1,38 +1,38 @@ compile_lit: (FloatLit 5.1) -type-inference.as:3.9-3.28: warning, this if has type Any because branches have inconsistent types, +type-inference.mo:3.9-3.28: warning, this if has type Any because branches have inconsistent types, true produces Bool false produces Nat -type-inference.as:4.9-4.34: warning, this if has type Any because branches have inconsistent types, +type-inference.mo:4.9-4.34: warning, this if has type Any because branches have inconsistent types, true produces Bool false produces [var Nat] -type-inference.as:5.9-5.27: warning, this if has type Any because branches have inconsistent types, +type-inference.mo:5.9-5.27: warning, this if has type Any because branches have inconsistent types, true produces Nat false produces Float -type-inference.as:6.9-6.29: warning, this if has type Any because branches have inconsistent types, +type-inference.mo:6.9-6.29: warning, this if has type Any because branches have inconsistent types, true produces () false produces {} -type-inference.as:11.33-11.41: warning, the switch has type Any because branches have inconsistent types, +type-inference.mo:11.33-11.41: warning, the switch has type Any because branches have inconsistent types, this case produces type Bool the previous produce type Nat -type-inference.as:12.33-12.47: warning, the switch has type Any because branches have inconsistent types, +type-inference.mo:12.33-12.47: warning, the switch has type Any because branches have inconsistent types, this case produces type Bool the previous produce type [var Nat] -type-inference.as:13.43-13.56: warning, the switch has type Any because branches have inconsistent types, +type-inference.mo:13.43-13.56: warning, the switch has type Any because branches have inconsistent types, this case produces type Int the previous produce type Text -type-inference.as:19.9-19.18: warning, this array has type [Any] because elements have inconsistent types -type-inference.as:20.9-20.24: warning, this array has type [Any] because elements have inconsistent types +type-inference.mo:19.9-19.18: warning, this array has type [Any] because elements have inconsistent types +type-inference.mo:20.9-20.24: warning, this array has type [Any] because elements have inconsistent types diff --git a/test/run/ott-typeclasses.as b/test/run/ott-typeclasses.mo similarity index 100% rename from test/run/ott-typeclasses.as rename to test/run/ott-typeclasses.mo diff --git a/test/run/overflow.as b/test/run/overflow.mo similarity index 100% rename from test/run/overflow.as rename to test/run/overflow.mo diff --git a/test/run/pat-subtyping.as b/test/run/pat-subtyping.mo similarity index 100% rename from test/run/pat-subtyping.as rename to test/run/pat-subtyping.mo diff --git a/test/run/prelude.as b/test/run/prelude.mo similarity index 100% rename from test/run/prelude.as rename to test/run/prelude.mo diff --git a/test/run/quicksort.as b/test/run/quicksort.mo similarity index 100% rename from test/run/quicksort.as rename to test/run/quicksort.mo diff --git a/test/run/ranged-nums.as b/test/run/ranged-nums.mo similarity index 100% rename from test/run/ranged-nums.as rename to test/run/ranged-nums.mo diff --git a/test/run/records.as b/test/run/records.mo similarity index 100% rename from test/run/records.as rename to test/run/records.mo diff --git a/test/run/relational-ops.as b/test/run/relational-ops.mo similarity index 100% rename from test/run/relational-ops.as rename to test/run/relational-ops.mo diff --git a/test/run/rts.as b/test/run/rts.mo similarity index 100% rename from test/run/rts.as rename to test/run/rts.mo diff --git a/test/run/self-bounds.as b/test/run/self-bounds.mo similarity index 100% rename from test/run/self-bounds.as rename to test/run/self-bounds.mo diff --git a/test/run/short-circuit.as b/test/run/short-circuit.mo similarity index 100% rename from test/run/short-circuit.as rename to test/run/short-circuit.mo diff --git a/test/run/signed-div.as b/test/run/signed-div.mo similarity index 100% rename from test/run/signed-div.as rename to test/run/signed-div.mo diff --git a/test/run/small-pow.lhs b/test/run/small-pow.lhs index 8d0af321938..9ae8a7cc888 100644 --- a/test/run/small-pow.lhs +++ b/test/run/small-pow.lhs @@ -1,5 +1,5 @@ /* -This can be read as literate Haskell (temporarily `ln ../test/run/small-pow.as ../test/run/small-pow.lhs`) +This can be read as literate Haskell (temporarily `ln ../test/run/small-pow.mo ../test/run/small-pow.lhs`) > import Data.Bits > import Data.Word diff --git a/test/run/small-pow.as b/test/run/small-pow.mo similarity index 99% rename from test/run/small-pow.as rename to test/run/small-pow.mo index 8d0af321938..9ae8a7cc888 100644 --- a/test/run/small-pow.as +++ b/test/run/small-pow.mo @@ -1,5 +1,5 @@ /* -This can be read as literate Haskell (temporarily `ln ../test/run/small-pow.as ../test/run/small-pow.lhs`) +This can be read as literate Haskell (temporarily `ln ../test/run/small-pow.mo ../test/run/small-pow.lhs`) > import Data.Bits > import Data.Word diff --git a/test/run/static-func-call.as b/test/run/static-func-call.mo similarity index 100% rename from test/run/static-func-call.as rename to test/run/static-func-call.mo diff --git a/test/run/sub-negative.as b/test/run/sub-negative.mo similarity index 100% rename from test/run/sub-negative.as rename to test/run/sub-negative.mo diff --git a/test/run/switch.as b/test/run/switch.mo similarity index 100% rename from test/run/switch.as rename to test/run/switch.mo diff --git a/test/run/text-concat.as b/test/run/text-concat.mo similarity index 100% rename from test/run/text-concat.as rename to test/run/text-concat.mo diff --git a/test/run/text-op.as b/test/run/text-op.mo similarity index 100% rename from test/run/text-op.as rename to test/run/text-op.mo diff --git a/test/run/text-pats.as b/test/run/text-pats.mo similarity index 100% rename from test/run/text-pats.as rename to test/run/text-pats.mo diff --git a/test/run/tuples.as b/test/run/tuples.mo similarity index 100% rename from test/run/tuples.as rename to test/run/tuples.mo diff --git a/test/run/typ-field-lub-glb.as b/test/run/typ-field-lub-glb.mo similarity index 100% rename from test/run/typ-field-lub-glb.as rename to test/run/typ-field-lub-glb.mo diff --git a/test/run/typdecl-last.as b/test/run/typdecl-last.mo similarity index 100% rename from test/run/typdecl-last.as rename to test/run/typdecl-last.mo diff --git a/test/run/type-definition.as b/test/run/type-definition.mo similarity index 100% rename from test/run/type-definition.as rename to test/run/type-definition.mo diff --git a/test/run/type-equivalence.as b/test/run/type-equivalence.mo similarity index 100% rename from test/run/type-equivalence.as rename to test/run/type-equivalence.mo diff --git a/test/run/type-inclusion.as b/test/run/type-inclusion.mo similarity index 100% rename from test/run/type-inclusion.as rename to test/run/type-inclusion.mo diff --git a/test/run/type-inference.as b/test/run/type-inference.mo similarity index 100% rename from test/run/type-inference.as rename to test/run/type-inference.mo diff --git a/test/run/underscore-ids.as b/test/run/underscore-ids.mo similarity index 100% rename from test/run/underscore-ids.as rename to test/run/underscore-ids.mo diff --git a/test/run/use-before-define3.as b/test/run/use-before-define3.mo similarity index 100% rename from test/run/use-before-define3.as rename to test/run/use-before-define3.mo diff --git a/test/run/variants.as b/test/run/variants.mo similarity index 100% rename from test/run/variants.as rename to test/run/variants.mo diff --git a/test/run/while.as b/test/run/while.mo similarity index 100% rename from test/run/while.as rename to test/run/while.mo diff --git a/test/run/word-rotations.as b/test/run/word-rotations.mo similarity index 100% rename from test/run/word-rotations.as rename to test/run/word-rotations.mo diff --git a/test/run/words.as b/test/run/words.mo similarity index 100% rename from test/run/words.as rename to test/run/words.mo diff --git a/test/test-reproducibility.sh b/test/test-reproducibility.sh index 6c6f039672d..20cd8cabd90 100755 --- a/test/test-reproducibility.sh +++ b/test/test-reproducibility.sh @@ -6,12 +6,12 @@ # It needs the tool reprotest to be installed -ASC=${ASC:-$(realpath $(dirname $0)/../src/asc)} +MOC=${MOC:-$(realpath $(dirname $0)/../src/moc)} -files="*/*.as" +files="*/*.mo" -reprotest --source-pattern "*/*.as" \ +reprotest --source-pattern "*/*.mo" \ --vary=-fileordering,-user_group,-domain_host \ - "for file in */*.as; do ${ASC} -c --map \$file 2> \$(basename \$file).stderr || true ; done" \ + "for file in */*.mo; do ${MOC} -c --map \$file 2> \$(basename \$file).stderr || true ; done" \ '*.wasm *.map *.stderr' diff --git a/test/trap/Makefile b/test/trap/Makefile index 6caa4f56e49..d64789ece47 100644 --- a/test/trap/Makefile +++ b/test/trap/Makefile @@ -1,10 +1,10 @@ RUNFLAGS = all: - ../run.sh $(RUNFLAGS) *.as + ../run.sh $(RUNFLAGS) *.mo accept: - ../run.sh $(RUNFLAGS) -a *.as + ../run.sh $(RUNFLAGS) -a *.mo clean: rm -rf _out @@ -12,20 +12,20 @@ clean: include ../*.mk .PHONY: check _out/%.checked -check: $(patsubst %.as,_out/%.checked,$(wildcard *.as)) +check: $(patsubst %.mo,_out/%.checked,$(wildcard *.mo)) -## for each %.as test there should be 4 ok/%.*.ok files with defined contents -_out/%.checked: %.as - @ (cat $(patsubst %.as,ok/%.run*.ok,$^) \ +## for each %.mo test there should be 4 ok/%.*.ok files with defined contents +_out/%.checked: %.mo + @ (cat $(patsubst %.mo,ok/%.run*.ok,$^) \ | grep -e "execution error, arithmetic overflow" \ -e "execution error, numeric overflow" \ -e "execution error, value out of bounds" \ | wc -l | grep 3 > /dev/null) \ - || (cat $(patsubst %.as,ok/%.run*.ok,$^); ls $(patsubst %.as,ok/%.run*.ok,$^); false) - @ (cat $(patsubst %.as,ok/%.wasm-run.ok,$^) \ + || (cat $(patsubst %.mo,ok/%.run*.ok,$^); ls $(patsubst %.mo,ok/%.run*.ok,$^); false) + @ (cat $(patsubst %.mo,ok/%.wasm-run.ok,$^) \ | grep -e "runtime trap: unreachable" \ -e "runtime trap: integer overflow" \ | wc -l | grep 1 > /dev/null) \ - || (cat $(patsubst %.as,ok/%.wasm-run.ok,$^); ls $(patsubst %.as,ok/%.wasm-run.ok,$^); false) - @ (ls $(patsubst %.as,ok/%.*.ok,$^) | wc -l | grep 4 > /dev/null) \ - || (ls $(patsubst %.as,ok/%.*.ok,$^); false) + || (cat $(patsubst %.mo,ok/%.wasm-run.ok,$^); ls $(patsubst %.mo,ok/%.wasm-run.ok,$^); false) + @ (ls $(patsubst %.mo,ok/%.*.ok,$^) | wc -l | grep 4 > /dev/null) \ + || (ls $(patsubst %.mo,ok/%.*.ok,$^); false) diff --git a/test/trap/addInt16-lower.as b/test/trap/addInt16-lower.mo similarity index 100% rename from test/trap/addInt16-lower.as rename to test/trap/addInt16-lower.mo diff --git a/test/trap/addInt16-upper.as b/test/trap/addInt16-upper.mo similarity index 100% rename from test/trap/addInt16-upper.as rename to test/trap/addInt16-upper.mo diff --git a/test/trap/addInt32-lower.as b/test/trap/addInt32-lower.mo similarity index 100% rename from test/trap/addInt32-lower.as rename to test/trap/addInt32-lower.mo diff --git a/test/trap/addInt32-upper.as b/test/trap/addInt32-upper.mo similarity index 100% rename from test/trap/addInt32-upper.as rename to test/trap/addInt32-upper.mo diff --git a/test/trap/addInt64-lower.as b/test/trap/addInt64-lower.mo similarity index 100% rename from test/trap/addInt64-lower.as rename to test/trap/addInt64-lower.mo diff --git a/test/trap/addInt64-upper.as b/test/trap/addInt64-upper.mo similarity index 100% rename from test/trap/addInt64-upper.as rename to test/trap/addInt64-upper.mo diff --git a/test/trap/addInt8-lower.as b/test/trap/addInt8-lower.mo similarity index 100% rename from test/trap/addInt8-lower.as rename to test/trap/addInt8-lower.mo diff --git a/test/trap/addInt8-upper.as b/test/trap/addInt8-upper.mo similarity index 100% rename from test/trap/addInt8-upper.as rename to test/trap/addInt8-upper.mo diff --git a/test/trap/addNat16.as b/test/trap/addNat16.mo similarity index 100% rename from test/trap/addNat16.as rename to test/trap/addNat16.mo diff --git a/test/trap/addNat32.as b/test/trap/addNat32.mo similarity index 100% rename from test/trap/addNat32.as rename to test/trap/addNat32.mo diff --git a/test/trap/addNat64.as b/test/trap/addNat64.mo similarity index 100% rename from test/trap/addNat64.as rename to test/trap/addNat64.mo diff --git a/test/trap/addNat8.as b/test/trap/addNat8.mo similarity index 100% rename from test/trap/addNat8.as rename to test/trap/addNat8.mo diff --git a/test/trap/divInt16.as b/test/trap/divInt16.mo similarity index 100% rename from test/trap/divInt16.as rename to test/trap/divInt16.mo diff --git a/test/trap/divInt32.as b/test/trap/divInt32.mo similarity index 100% rename from test/trap/divInt32.as rename to test/trap/divInt32.mo diff --git a/test/trap/divInt64.as b/test/trap/divInt64.mo similarity index 100% rename from test/trap/divInt64.as rename to test/trap/divInt64.mo diff --git a/test/trap/divInt8.as b/test/trap/divInt8.mo similarity index 100% rename from test/trap/divInt8.as rename to test/trap/divInt8.mo diff --git a/test/trap/mulInt16-lower.as b/test/trap/mulInt16-lower.mo similarity index 100% rename from test/trap/mulInt16-lower.as rename to test/trap/mulInt16-lower.mo diff --git a/test/trap/mulInt16-upper.as b/test/trap/mulInt16-upper.mo similarity index 100% rename from test/trap/mulInt16-upper.as rename to test/trap/mulInt16-upper.mo diff --git a/test/trap/mulInt32-lower.as b/test/trap/mulInt32-lower.mo similarity index 100% rename from test/trap/mulInt32-lower.as rename to test/trap/mulInt32-lower.mo diff --git a/test/trap/mulInt32-upper.as b/test/trap/mulInt32-upper.mo similarity index 100% rename from test/trap/mulInt32-upper.as rename to test/trap/mulInt32-upper.mo diff --git a/test/trap/mulInt64-lower.as b/test/trap/mulInt64-lower.mo similarity index 100% rename from test/trap/mulInt64-lower.as rename to test/trap/mulInt64-lower.mo diff --git a/test/trap/mulInt64-upper.as b/test/trap/mulInt64-upper.mo similarity index 100% rename from test/trap/mulInt64-upper.as rename to test/trap/mulInt64-upper.mo diff --git a/test/trap/mulInt8-lower.as b/test/trap/mulInt8-lower.mo similarity index 100% rename from test/trap/mulInt8-lower.as rename to test/trap/mulInt8-lower.mo diff --git a/test/trap/mulInt8-upper.as b/test/trap/mulInt8-upper.mo similarity index 100% rename from test/trap/mulInt8-upper.as rename to test/trap/mulInt8-upper.mo diff --git a/test/trap/mulNat16.as b/test/trap/mulNat16.mo similarity index 100% rename from test/trap/mulNat16.as rename to test/trap/mulNat16.mo diff --git a/test/trap/mulNat32.as b/test/trap/mulNat32.mo similarity index 100% rename from test/trap/mulNat32.as rename to test/trap/mulNat32.mo diff --git a/test/trap/mulNat64.as b/test/trap/mulNat64.mo similarity index 100% rename from test/trap/mulNat64.as rename to test/trap/mulNat64.mo diff --git a/test/trap/mulNat8.as b/test/trap/mulNat8.mo similarity index 100% rename from test/trap/mulNat8.as rename to test/trap/mulNat8.mo diff --git a/test/trap/ok/addInt16-lower.run-ir.ok b/test/trap/ok/addInt16-lower.run-ir.ok index d62a0f9e2ac..dc0309e958c 100644 --- a/test/trap/ok/addInt16-lower.run-ir.ok +++ b/test/trap/ok/addInt16-lower.run-ir.ok @@ -1 +1 @@ -addInt16-lower.as:1.9-1.40: execution error, arithmetic overflow +addInt16-lower.mo:1.9-1.40: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt16-lower.run-low.ok b/test/trap/ok/addInt16-lower.run-low.ok index d62a0f9e2ac..dc0309e958c 100644 --- a/test/trap/ok/addInt16-lower.run-low.ok +++ b/test/trap/ok/addInt16-lower.run-low.ok @@ -1 +1 @@ -addInt16-lower.as:1.9-1.40: execution error, arithmetic overflow +addInt16-lower.mo:1.9-1.40: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt16-lower.run.ok b/test/trap/ok/addInt16-lower.run.ok index d62a0f9e2ac..dc0309e958c 100644 --- a/test/trap/ok/addInt16-lower.run.ok +++ b/test/trap/ok/addInt16-lower.run.ok @@ -1 +1 @@ -addInt16-lower.as:1.9-1.40: execution error, arithmetic overflow +addInt16-lower.mo:1.9-1.40: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt16-upper.run-ir.ok b/test/trap/ok/addInt16-upper.run-ir.ok index d79caaf1e0e..4c5e380fc42 100644 --- a/test/trap/ok/addInt16-upper.run-ir.ok +++ b/test/trap/ok/addInt16-upper.run-ir.ok @@ -1 +1 @@ -addInt16-upper.as:1.9-1.38: execution error, arithmetic overflow +addInt16-upper.mo:1.9-1.38: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt16-upper.run-low.ok b/test/trap/ok/addInt16-upper.run-low.ok index d79caaf1e0e..4c5e380fc42 100644 --- a/test/trap/ok/addInt16-upper.run-low.ok +++ b/test/trap/ok/addInt16-upper.run-low.ok @@ -1 +1 @@ -addInt16-upper.as:1.9-1.38: execution error, arithmetic overflow +addInt16-upper.mo:1.9-1.38: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt16-upper.run.ok b/test/trap/ok/addInt16-upper.run.ok index d79caaf1e0e..4c5e380fc42 100644 --- a/test/trap/ok/addInt16-upper.run.ok +++ b/test/trap/ok/addInt16-upper.run.ok @@ -1 +1 @@ -addInt16-upper.as:1.9-1.38: execution error, arithmetic overflow +addInt16-upper.mo:1.9-1.38: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt32-lower.run-ir.ok b/test/trap/ok/addInt32-lower.run-ir.ok index cf0ff2993d8..23cabc7138d 100644 --- a/test/trap/ok/addInt32-lower.run-ir.ok +++ b/test/trap/ok/addInt32-lower.run-ir.ok @@ -1 +1 @@ -addInt32-lower.as:1.9-1.48: execution error, arithmetic overflow +addInt32-lower.mo:1.9-1.48: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt32-lower.run-low.ok b/test/trap/ok/addInt32-lower.run-low.ok index cf0ff2993d8..23cabc7138d 100644 --- a/test/trap/ok/addInt32-lower.run-low.ok +++ b/test/trap/ok/addInt32-lower.run-low.ok @@ -1 +1 @@ -addInt32-lower.as:1.9-1.48: execution error, arithmetic overflow +addInt32-lower.mo:1.9-1.48: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt32-lower.run.ok b/test/trap/ok/addInt32-lower.run.ok index cf0ff2993d8..23cabc7138d 100644 --- a/test/trap/ok/addInt32-lower.run.ok +++ b/test/trap/ok/addInt32-lower.run.ok @@ -1 +1 @@ -addInt32-lower.as:1.9-1.48: execution error, arithmetic overflow +addInt32-lower.mo:1.9-1.48: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt32-upper.run-ir.ok b/test/trap/ok/addInt32-upper.run-ir.ok index acd452bb58a..16e9ad5d77f 100644 --- a/test/trap/ok/addInt32-upper.run-ir.ok +++ b/test/trap/ok/addInt32-upper.run-ir.ok @@ -1 +1 @@ -addInt32-upper.as:1.9-1.46: execution error, arithmetic overflow +addInt32-upper.mo:1.9-1.46: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt32-upper.run-low.ok b/test/trap/ok/addInt32-upper.run-low.ok index acd452bb58a..16e9ad5d77f 100644 --- a/test/trap/ok/addInt32-upper.run-low.ok +++ b/test/trap/ok/addInt32-upper.run-low.ok @@ -1 +1 @@ -addInt32-upper.as:1.9-1.46: execution error, arithmetic overflow +addInt32-upper.mo:1.9-1.46: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt32-upper.run.ok b/test/trap/ok/addInt32-upper.run.ok index acd452bb58a..16e9ad5d77f 100644 --- a/test/trap/ok/addInt32-upper.run.ok +++ b/test/trap/ok/addInt32-upper.run.ok @@ -1 +1 @@ -addInt32-upper.as:1.9-1.46: execution error, arithmetic overflow +addInt32-upper.mo:1.9-1.46: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt64-lower.run-ir.ok b/test/trap/ok/addInt64-lower.run-ir.ok index 928eca69453..6f3bbe943ad 100644 --- a/test/trap/ok/addInt64-lower.run-ir.ok +++ b/test/trap/ok/addInt64-lower.run-ir.ok @@ -1 +1 @@ -addInt64-lower.as:1.9-1.60: execution error, arithmetic overflow +addInt64-lower.mo:1.9-1.60: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt64-lower.run-low.ok b/test/trap/ok/addInt64-lower.run-low.ok index 928eca69453..6f3bbe943ad 100644 --- a/test/trap/ok/addInt64-lower.run-low.ok +++ b/test/trap/ok/addInt64-lower.run-low.ok @@ -1 +1 @@ -addInt64-lower.as:1.9-1.60: execution error, arithmetic overflow +addInt64-lower.mo:1.9-1.60: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt64-lower.run.ok b/test/trap/ok/addInt64-lower.run.ok index 928eca69453..6f3bbe943ad 100644 --- a/test/trap/ok/addInt64-lower.run.ok +++ b/test/trap/ok/addInt64-lower.run.ok @@ -1 +1 @@ -addInt64-lower.as:1.9-1.60: execution error, arithmetic overflow +addInt64-lower.mo:1.9-1.60: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt64-upper.run-ir.ok b/test/trap/ok/addInt64-upper.run-ir.ok index 0de67ff7676..f69cf9a6364 100644 --- a/test/trap/ok/addInt64-upper.run-ir.ok +++ b/test/trap/ok/addInt64-upper.run-ir.ok @@ -1 +1 @@ -addInt64-upper.as:1.9-1.58: execution error, arithmetic overflow +addInt64-upper.mo:1.9-1.58: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt64-upper.run-low.ok b/test/trap/ok/addInt64-upper.run-low.ok index 0de67ff7676..f69cf9a6364 100644 --- a/test/trap/ok/addInt64-upper.run-low.ok +++ b/test/trap/ok/addInt64-upper.run-low.ok @@ -1 +1 @@ -addInt64-upper.as:1.9-1.58: execution error, arithmetic overflow +addInt64-upper.mo:1.9-1.58: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt64-upper.run.ok b/test/trap/ok/addInt64-upper.run.ok index 0de67ff7676..f69cf9a6364 100644 --- a/test/trap/ok/addInt64-upper.run.ok +++ b/test/trap/ok/addInt64-upper.run.ok @@ -1 +1 @@ -addInt64-upper.as:1.9-1.58: execution error, arithmetic overflow +addInt64-upper.mo:1.9-1.58: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt8-lower.run-ir.ok b/test/trap/ok/addInt8-lower.run-ir.ok index 9fe0fcb4891..1fdbe71a225 100644 --- a/test/trap/ok/addInt8-lower.run-ir.ok +++ b/test/trap/ok/addInt8-lower.run-ir.ok @@ -1 +1 @@ -addInt8-lower.as:1.9-1.36: execution error, arithmetic overflow +addInt8-lower.mo:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt8-lower.run-low.ok b/test/trap/ok/addInt8-lower.run-low.ok index 9fe0fcb4891..1fdbe71a225 100644 --- a/test/trap/ok/addInt8-lower.run-low.ok +++ b/test/trap/ok/addInt8-lower.run-low.ok @@ -1 +1 @@ -addInt8-lower.as:1.9-1.36: execution error, arithmetic overflow +addInt8-lower.mo:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt8-lower.run.ok b/test/trap/ok/addInt8-lower.run.ok index 9fe0fcb4891..1fdbe71a225 100644 --- a/test/trap/ok/addInt8-lower.run.ok +++ b/test/trap/ok/addInt8-lower.run.ok @@ -1 +1 @@ -addInt8-lower.as:1.9-1.36: execution error, arithmetic overflow +addInt8-lower.mo:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt8-upper.run-ir.ok b/test/trap/ok/addInt8-upper.run-ir.ok index e9473ec9d23..f31891d0802 100644 --- a/test/trap/ok/addInt8-upper.run-ir.ok +++ b/test/trap/ok/addInt8-upper.run-ir.ok @@ -1 +1 @@ -addInt8-upper.as:1.9-1.34: execution error, arithmetic overflow +addInt8-upper.mo:1.9-1.34: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt8-upper.run-low.ok b/test/trap/ok/addInt8-upper.run-low.ok index e9473ec9d23..f31891d0802 100644 --- a/test/trap/ok/addInt8-upper.run-low.ok +++ b/test/trap/ok/addInt8-upper.run-low.ok @@ -1 +1 @@ -addInt8-upper.as:1.9-1.34: execution error, arithmetic overflow +addInt8-upper.mo:1.9-1.34: execution error, arithmetic overflow diff --git a/test/trap/ok/addInt8-upper.run.ok b/test/trap/ok/addInt8-upper.run.ok index e9473ec9d23..f31891d0802 100644 --- a/test/trap/ok/addInt8-upper.run.ok +++ b/test/trap/ok/addInt8-upper.run.ok @@ -1 +1 @@ -addInt8-upper.as:1.9-1.34: execution error, arithmetic overflow +addInt8-upper.mo:1.9-1.34: execution error, arithmetic overflow diff --git a/test/trap/ok/addNat16.run-ir.ok b/test/trap/ok/addNat16.run-ir.ok index df835aa414d..f6c89197ebb 100644 --- a/test/trap/ok/addNat16.run-ir.ok +++ b/test/trap/ok/addNat16.run-ir.ok @@ -1 +1 @@ -addNat16.as:1.9-1.56: execution error, arithmetic overflow +addNat16.mo:1.9-1.56: execution error, arithmetic overflow diff --git a/test/trap/ok/addNat16.run-low.ok b/test/trap/ok/addNat16.run-low.ok index df835aa414d..f6c89197ebb 100644 --- a/test/trap/ok/addNat16.run-low.ok +++ b/test/trap/ok/addNat16.run-low.ok @@ -1 +1 @@ -addNat16.as:1.9-1.56: execution error, arithmetic overflow +addNat16.mo:1.9-1.56: execution error, arithmetic overflow diff --git a/test/trap/ok/addNat16.run.ok b/test/trap/ok/addNat16.run.ok index df835aa414d..f6c89197ebb 100644 --- a/test/trap/ok/addNat16.run.ok +++ b/test/trap/ok/addNat16.run.ok @@ -1 +1 @@ -addNat16.as:1.9-1.56: execution error, arithmetic overflow +addNat16.mo:1.9-1.56: execution error, arithmetic overflow diff --git a/test/trap/ok/addNat32.run-ir.ok b/test/trap/ok/addNat32.run-ir.ok index 44c1c0e581f..1aa377aafb9 100644 --- a/test/trap/ok/addNat32.run-ir.ok +++ b/test/trap/ok/addNat32.run-ir.ok @@ -1 +1 @@ -addNat32.as:1.9-1.72: execution error, arithmetic overflow +addNat32.mo:1.9-1.72: execution error, arithmetic overflow diff --git a/test/trap/ok/addNat32.run-low.ok b/test/trap/ok/addNat32.run-low.ok index 44c1c0e581f..1aa377aafb9 100644 --- a/test/trap/ok/addNat32.run-low.ok +++ b/test/trap/ok/addNat32.run-low.ok @@ -1 +1 @@ -addNat32.as:1.9-1.72: execution error, arithmetic overflow +addNat32.mo:1.9-1.72: execution error, arithmetic overflow diff --git a/test/trap/ok/addNat32.run.ok b/test/trap/ok/addNat32.run.ok index 44c1c0e581f..1aa377aafb9 100644 --- a/test/trap/ok/addNat32.run.ok +++ b/test/trap/ok/addNat32.run.ok @@ -1 +1 @@ -addNat32.as:1.9-1.72: execution error, arithmetic overflow +addNat32.mo:1.9-1.72: execution error, arithmetic overflow diff --git a/test/trap/ok/addNat64.run-ir.ok b/test/trap/ok/addNat64.run-ir.ok index 9ba553ba038..14b2162ab61 100644 --- a/test/trap/ok/addNat64.run-ir.ok +++ b/test/trap/ok/addNat64.run-ir.ok @@ -1 +1 @@ -addNat64.as:1.9-1.96: execution error, arithmetic overflow +addNat64.mo:1.9-1.96: execution error, arithmetic overflow diff --git a/test/trap/ok/addNat64.run-low.ok b/test/trap/ok/addNat64.run-low.ok index 9ba553ba038..14b2162ab61 100644 --- a/test/trap/ok/addNat64.run-low.ok +++ b/test/trap/ok/addNat64.run-low.ok @@ -1 +1 @@ -addNat64.as:1.9-1.96: execution error, arithmetic overflow +addNat64.mo:1.9-1.96: execution error, arithmetic overflow diff --git a/test/trap/ok/addNat64.run.ok b/test/trap/ok/addNat64.run.ok index 9ba553ba038..14b2162ab61 100644 --- a/test/trap/ok/addNat64.run.ok +++ b/test/trap/ok/addNat64.run.ok @@ -1 +1 @@ -addNat64.as:1.9-1.96: execution error, arithmetic overflow +addNat64.mo:1.9-1.96: execution error, arithmetic overflow diff --git a/test/trap/ok/addNat8.run-ir.ok b/test/trap/ok/addNat8.run-ir.ok index c11ce155102..3d57e4e9c56 100644 --- a/test/trap/ok/addNat8.run-ir.ok +++ b/test/trap/ok/addNat8.run-ir.ok @@ -1 +1 @@ -addNat8.as:1.9-1.49: execution error, arithmetic overflow +addNat8.mo:1.9-1.49: execution error, arithmetic overflow diff --git a/test/trap/ok/addNat8.run-low.ok b/test/trap/ok/addNat8.run-low.ok index c11ce155102..3d57e4e9c56 100644 --- a/test/trap/ok/addNat8.run-low.ok +++ b/test/trap/ok/addNat8.run-low.ok @@ -1 +1 @@ -addNat8.as:1.9-1.49: execution error, arithmetic overflow +addNat8.mo:1.9-1.49: execution error, arithmetic overflow diff --git a/test/trap/ok/addNat8.run.ok b/test/trap/ok/addNat8.run.ok index c11ce155102..3d57e4e9c56 100644 --- a/test/trap/ok/addNat8.run.ok +++ b/test/trap/ok/addNat8.run.ok @@ -1 +1 @@ -addNat8.as:1.9-1.49: execution error, arithmetic overflow +addNat8.mo:1.9-1.49: execution error, arithmetic overflow diff --git a/test/trap/ok/divInt16.run-ir.ok b/test/trap/ok/divInt16.run-ir.ok index 0fa6f654fec..d7f65b77c81 100644 --- a/test/trap/ok/divInt16.run-ir.ok +++ b/test/trap/ok/divInt16.run-ir.ok @@ -1 +1 @@ -divInt16.as:1.9-1.43: execution error, arithmetic overflow +divInt16.mo:1.9-1.43: execution error, arithmetic overflow diff --git a/test/trap/ok/divInt16.run-low.ok b/test/trap/ok/divInt16.run-low.ok index 0fa6f654fec..d7f65b77c81 100644 --- a/test/trap/ok/divInt16.run-low.ok +++ b/test/trap/ok/divInt16.run-low.ok @@ -1 +1 @@ -divInt16.as:1.9-1.43: execution error, arithmetic overflow +divInt16.mo:1.9-1.43: execution error, arithmetic overflow diff --git a/test/trap/ok/divInt16.run.ok b/test/trap/ok/divInt16.run.ok index 0fa6f654fec..d7f65b77c81 100644 --- a/test/trap/ok/divInt16.run.ok +++ b/test/trap/ok/divInt16.run.ok @@ -1 +1 @@ -divInt16.as:1.9-1.43: execution error, arithmetic overflow +divInt16.mo:1.9-1.43: execution error, arithmetic overflow diff --git a/test/trap/ok/divInt32.run-ir.ok b/test/trap/ok/divInt32.run-ir.ok index 63925b7f704..0f006e8e76c 100644 --- a/test/trap/ok/divInt32.run-ir.ok +++ b/test/trap/ok/divInt32.run-ir.ok @@ -1 +1 @@ -divInt32.as:1.9-1.48: execution error, arithmetic overflow +divInt32.mo:1.9-1.48: execution error, arithmetic overflow diff --git a/test/trap/ok/divInt32.run-low.ok b/test/trap/ok/divInt32.run-low.ok index 63925b7f704..0f006e8e76c 100644 --- a/test/trap/ok/divInt32.run-low.ok +++ b/test/trap/ok/divInt32.run-low.ok @@ -1 +1 @@ -divInt32.as:1.9-1.48: execution error, arithmetic overflow +divInt32.mo:1.9-1.48: execution error, arithmetic overflow diff --git a/test/trap/ok/divInt32.run.ok b/test/trap/ok/divInt32.run.ok index 63925b7f704..0f006e8e76c 100644 --- a/test/trap/ok/divInt32.run.ok +++ b/test/trap/ok/divInt32.run.ok @@ -1 +1 @@ -divInt32.as:1.9-1.48: execution error, arithmetic overflow +divInt32.mo:1.9-1.48: execution error, arithmetic overflow diff --git a/test/trap/ok/divInt64.run-ir.ok b/test/trap/ok/divInt64.run-ir.ok index 6fea9ac0cd6..25e8067c48b 100644 --- a/test/trap/ok/divInt64.run-ir.ok +++ b/test/trap/ok/divInt64.run-ir.ok @@ -1 +1 @@ -divInt64.as:1.9-1.56: execution error, arithmetic overflow +divInt64.mo:1.9-1.56: execution error, arithmetic overflow diff --git a/test/trap/ok/divInt64.run-low.ok b/test/trap/ok/divInt64.run-low.ok index 6fea9ac0cd6..25e8067c48b 100644 --- a/test/trap/ok/divInt64.run-low.ok +++ b/test/trap/ok/divInt64.run-low.ok @@ -1 +1 @@ -divInt64.as:1.9-1.56: execution error, arithmetic overflow +divInt64.mo:1.9-1.56: execution error, arithmetic overflow diff --git a/test/trap/ok/divInt64.run.ok b/test/trap/ok/divInt64.run.ok index 6fea9ac0cd6..25e8067c48b 100644 --- a/test/trap/ok/divInt64.run.ok +++ b/test/trap/ok/divInt64.run.ok @@ -1 +1 @@ -divInt64.as:1.9-1.56: execution error, arithmetic overflow +divInt64.mo:1.9-1.56: execution error, arithmetic overflow diff --git a/test/trap/ok/divInt8.run-ir.ok b/test/trap/ok/divInt8.run-ir.ok index 463f3dfb55a..5252362a667 100644 --- a/test/trap/ok/divInt8.run-ir.ok +++ b/test/trap/ok/divInt8.run-ir.ok @@ -1 +1 @@ -divInt8.as:1.9-1.39: execution error, arithmetic overflow +divInt8.mo:1.9-1.39: execution error, arithmetic overflow diff --git a/test/trap/ok/divInt8.run-low.ok b/test/trap/ok/divInt8.run-low.ok index 463f3dfb55a..5252362a667 100644 --- a/test/trap/ok/divInt8.run-low.ok +++ b/test/trap/ok/divInt8.run-low.ok @@ -1 +1 @@ -divInt8.as:1.9-1.39: execution error, arithmetic overflow +divInt8.mo:1.9-1.39: execution error, arithmetic overflow diff --git a/test/trap/ok/divInt8.run.ok b/test/trap/ok/divInt8.run.ok index 463f3dfb55a..5252362a667 100644 --- a/test/trap/ok/divInt8.run.ok +++ b/test/trap/ok/divInt8.run.ok @@ -1 +1 @@ -divInt8.as:1.9-1.39: execution error, arithmetic overflow +divInt8.mo:1.9-1.39: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt16-lower.run-ir.ok b/test/trap/ok/mulInt16-lower.run-ir.ok index 8bd0a01b943..c5392dd64b8 100644 --- a/test/trap/ok/mulInt16-lower.run-ir.ok +++ b/test/trap/ok/mulInt16-lower.run-ir.ok @@ -1 +1 @@ -mulInt16-lower.as:1.9-1.39: execution error, arithmetic overflow +mulInt16-lower.mo:1.9-1.39: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt16-lower.run-low.ok b/test/trap/ok/mulInt16-lower.run-low.ok index 8bd0a01b943..c5392dd64b8 100644 --- a/test/trap/ok/mulInt16-lower.run-low.ok +++ b/test/trap/ok/mulInt16-lower.run-low.ok @@ -1 +1 @@ -mulInt16-lower.as:1.9-1.39: execution error, arithmetic overflow +mulInt16-lower.mo:1.9-1.39: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt16-lower.run.ok b/test/trap/ok/mulInt16-lower.run.ok index 8bd0a01b943..c5392dd64b8 100644 --- a/test/trap/ok/mulInt16-lower.run.ok +++ b/test/trap/ok/mulInt16-lower.run.ok @@ -1 +1 @@ -mulInt16-lower.as:1.9-1.39: execution error, arithmetic overflow +mulInt16-lower.mo:1.9-1.39: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt16-upper.run-ir.ok b/test/trap/ok/mulInt16-upper.run-ir.ok index f508a0f4f21..4305f2a026a 100644 --- a/test/trap/ok/mulInt16-upper.run-ir.ok +++ b/test/trap/ok/mulInt16-upper.run-ir.ok @@ -1 +1 @@ -mulInt16-upper.as:1.9-1.38: execution error, arithmetic overflow +mulInt16-upper.mo:1.9-1.38: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt16-upper.run-low.ok b/test/trap/ok/mulInt16-upper.run-low.ok index f508a0f4f21..4305f2a026a 100644 --- a/test/trap/ok/mulInt16-upper.run-low.ok +++ b/test/trap/ok/mulInt16-upper.run-low.ok @@ -1 +1 @@ -mulInt16-upper.as:1.9-1.38: execution error, arithmetic overflow +mulInt16-upper.mo:1.9-1.38: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt16-upper.run.ok b/test/trap/ok/mulInt16-upper.run.ok index f508a0f4f21..4305f2a026a 100644 --- a/test/trap/ok/mulInt16-upper.run.ok +++ b/test/trap/ok/mulInt16-upper.run.ok @@ -1 +1 @@ -mulInt16-upper.as:1.9-1.38: execution error, arithmetic overflow +mulInt16-upper.mo:1.9-1.38: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt32-lower.run-ir.ok b/test/trap/ok/mulInt32-lower.run-ir.ok index 7c36e38f828..756deb55afe 100644 --- a/test/trap/ok/mulInt32-lower.run-ir.ok +++ b/test/trap/ok/mulInt32-lower.run-ir.ok @@ -1 +1 @@ -mulInt32-lower.as:1.9-1.43: execution error, arithmetic overflow +mulInt32-lower.mo:1.9-1.43: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt32-lower.run-low.ok b/test/trap/ok/mulInt32-lower.run-low.ok index 7c36e38f828..756deb55afe 100644 --- a/test/trap/ok/mulInt32-lower.run-low.ok +++ b/test/trap/ok/mulInt32-lower.run-low.ok @@ -1 +1 @@ -mulInt32-lower.as:1.9-1.43: execution error, arithmetic overflow +mulInt32-lower.mo:1.9-1.43: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt32-lower.run.ok b/test/trap/ok/mulInt32-lower.run.ok index 7c36e38f828..756deb55afe 100644 --- a/test/trap/ok/mulInt32-lower.run.ok +++ b/test/trap/ok/mulInt32-lower.run.ok @@ -1 +1 @@ -mulInt32-lower.as:1.9-1.43: execution error, arithmetic overflow +mulInt32-lower.mo:1.9-1.43: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt32-upper.run-ir.ok b/test/trap/ok/mulInt32-upper.run-ir.ok index e2b4edd024f..aa11d362396 100644 --- a/test/trap/ok/mulInt32-upper.run-ir.ok +++ b/test/trap/ok/mulInt32-upper.run-ir.ok @@ -1 +1 @@ -mulInt32-upper.as:1.9-1.42: execution error, arithmetic overflow +mulInt32-upper.mo:1.9-1.42: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt32-upper.run-low.ok b/test/trap/ok/mulInt32-upper.run-low.ok index e2b4edd024f..aa11d362396 100644 --- a/test/trap/ok/mulInt32-upper.run-low.ok +++ b/test/trap/ok/mulInt32-upper.run-low.ok @@ -1 +1 @@ -mulInt32-upper.as:1.9-1.42: execution error, arithmetic overflow +mulInt32-upper.mo:1.9-1.42: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt32-upper.run.ok b/test/trap/ok/mulInt32-upper.run.ok index e2b4edd024f..aa11d362396 100644 --- a/test/trap/ok/mulInt32-upper.run.ok +++ b/test/trap/ok/mulInt32-upper.run.ok @@ -1 +1 @@ -mulInt32-upper.as:1.9-1.42: execution error, arithmetic overflow +mulInt32-upper.mo:1.9-1.42: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt64-lower.run-ir.ok b/test/trap/ok/mulInt64-lower.run-ir.ok index 0411d2c52dc..f6645accc0e 100644 --- a/test/trap/ok/mulInt64-lower.run-ir.ok +++ b/test/trap/ok/mulInt64-lower.run-ir.ok @@ -1 +1 @@ -mulInt64-lower.as:1.9-1.59: execution error, arithmetic overflow +mulInt64-lower.mo:1.9-1.59: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt64-lower.run-low.ok b/test/trap/ok/mulInt64-lower.run-low.ok index 0411d2c52dc..f6645accc0e 100644 --- a/test/trap/ok/mulInt64-lower.run-low.ok +++ b/test/trap/ok/mulInt64-lower.run-low.ok @@ -1 +1 @@ -mulInt64-lower.as:1.9-1.59: execution error, arithmetic overflow +mulInt64-lower.mo:1.9-1.59: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt64-lower.run.ok b/test/trap/ok/mulInt64-lower.run.ok index 0411d2c52dc..f6645accc0e 100644 --- a/test/trap/ok/mulInt64-lower.run.ok +++ b/test/trap/ok/mulInt64-lower.run.ok @@ -1 +1 @@ -mulInt64-lower.as:1.9-1.59: execution error, arithmetic overflow +mulInt64-lower.mo:1.9-1.59: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt64-upper.run-ir.ok b/test/trap/ok/mulInt64-upper.run-ir.ok index a6fce3b9824..7dae136e4a0 100644 --- a/test/trap/ok/mulInt64-upper.run-ir.ok +++ b/test/trap/ok/mulInt64-upper.run-ir.ok @@ -1 +1 @@ -mulInt64-upper.as:1.9-1.58: execution error, arithmetic overflow +mulInt64-upper.mo:1.9-1.58: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt64-upper.run-low.ok b/test/trap/ok/mulInt64-upper.run-low.ok index a6fce3b9824..7dae136e4a0 100644 --- a/test/trap/ok/mulInt64-upper.run-low.ok +++ b/test/trap/ok/mulInt64-upper.run-low.ok @@ -1 +1 @@ -mulInt64-upper.as:1.9-1.58: execution error, arithmetic overflow +mulInt64-upper.mo:1.9-1.58: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt64-upper.run.ok b/test/trap/ok/mulInt64-upper.run.ok index a6fce3b9824..7dae136e4a0 100644 --- a/test/trap/ok/mulInt64-upper.run.ok +++ b/test/trap/ok/mulInt64-upper.run.ok @@ -1 +1 @@ -mulInt64-upper.as:1.9-1.58: execution error, arithmetic overflow +mulInt64-upper.mo:1.9-1.58: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt8-lower.run-ir.ok b/test/trap/ok/mulInt8-lower.run-ir.ok index b0ea4be6c13..11bd86d5518 100644 --- a/test/trap/ok/mulInt8-lower.run-ir.ok +++ b/test/trap/ok/mulInt8-lower.run-ir.ok @@ -1 +1 @@ -mulInt8-lower.as:1.9-1.34: execution error, arithmetic overflow +mulInt8-lower.mo:1.9-1.34: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt8-lower.run-low.ok b/test/trap/ok/mulInt8-lower.run-low.ok index b0ea4be6c13..11bd86d5518 100644 --- a/test/trap/ok/mulInt8-lower.run-low.ok +++ b/test/trap/ok/mulInt8-lower.run-low.ok @@ -1 +1 @@ -mulInt8-lower.as:1.9-1.34: execution error, arithmetic overflow +mulInt8-lower.mo:1.9-1.34: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt8-lower.run.ok b/test/trap/ok/mulInt8-lower.run.ok index b0ea4be6c13..11bd86d5518 100644 --- a/test/trap/ok/mulInt8-lower.run.ok +++ b/test/trap/ok/mulInt8-lower.run.ok @@ -1 +1 @@ -mulInt8-lower.as:1.9-1.34: execution error, arithmetic overflow +mulInt8-lower.mo:1.9-1.34: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt8-upper.run-ir.ok b/test/trap/ok/mulInt8-upper.run-ir.ok index d08ca12303c..b9a1a4c574c 100644 --- a/test/trap/ok/mulInt8-upper.run-ir.ok +++ b/test/trap/ok/mulInt8-upper.run-ir.ok @@ -1 +1 @@ -mulInt8-upper.as:1.9-1.33: execution error, arithmetic overflow +mulInt8-upper.mo:1.9-1.33: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt8-upper.run-low.ok b/test/trap/ok/mulInt8-upper.run-low.ok index d08ca12303c..b9a1a4c574c 100644 --- a/test/trap/ok/mulInt8-upper.run-low.ok +++ b/test/trap/ok/mulInt8-upper.run-low.ok @@ -1 +1 @@ -mulInt8-upper.as:1.9-1.33: execution error, arithmetic overflow +mulInt8-upper.mo:1.9-1.33: execution error, arithmetic overflow diff --git a/test/trap/ok/mulInt8-upper.run.ok b/test/trap/ok/mulInt8-upper.run.ok index d08ca12303c..b9a1a4c574c 100644 --- a/test/trap/ok/mulInt8-upper.run.ok +++ b/test/trap/ok/mulInt8-upper.run.ok @@ -1 +1 @@ -mulInt8-upper.as:1.9-1.33: execution error, arithmetic overflow +mulInt8-upper.mo:1.9-1.33: execution error, arithmetic overflow diff --git a/test/trap/ok/mulNat16.run-ir.ok b/test/trap/ok/mulNat16.run-ir.ok index 2761ae3d89d..f5f0b363200 100644 --- a/test/trap/ok/mulNat16.run-ir.ok +++ b/test/trap/ok/mulNat16.run-ir.ok @@ -1 +1 @@ -mulNat16.as:1.9-1.38: execution error, arithmetic overflow +mulNat16.mo:1.9-1.38: execution error, arithmetic overflow diff --git a/test/trap/ok/mulNat16.run-low.ok b/test/trap/ok/mulNat16.run-low.ok index 2761ae3d89d..f5f0b363200 100644 --- a/test/trap/ok/mulNat16.run-low.ok +++ b/test/trap/ok/mulNat16.run-low.ok @@ -1 +1 @@ -mulNat16.as:1.9-1.38: execution error, arithmetic overflow +mulNat16.mo:1.9-1.38: execution error, arithmetic overflow diff --git a/test/trap/ok/mulNat16.run.ok b/test/trap/ok/mulNat16.run.ok index 2761ae3d89d..f5f0b363200 100644 --- a/test/trap/ok/mulNat16.run.ok +++ b/test/trap/ok/mulNat16.run.ok @@ -1 +1 @@ -mulNat16.as:1.9-1.38: execution error, arithmetic overflow +mulNat16.mo:1.9-1.38: execution error, arithmetic overflow diff --git a/test/trap/ok/mulNat32.run-ir.ok b/test/trap/ok/mulNat32.run-ir.ok index 37e7a009b19..99b5cefbbdb 100644 --- a/test/trap/ok/mulNat32.run-ir.ok +++ b/test/trap/ok/mulNat32.run-ir.ok @@ -1 +1 @@ -mulNat32.as:1.9-1.42: execution error, arithmetic overflow +mulNat32.mo:1.9-1.42: execution error, arithmetic overflow diff --git a/test/trap/ok/mulNat32.run-low.ok b/test/trap/ok/mulNat32.run-low.ok index 37e7a009b19..99b5cefbbdb 100644 --- a/test/trap/ok/mulNat32.run-low.ok +++ b/test/trap/ok/mulNat32.run-low.ok @@ -1 +1 @@ -mulNat32.as:1.9-1.42: execution error, arithmetic overflow +mulNat32.mo:1.9-1.42: execution error, arithmetic overflow diff --git a/test/trap/ok/mulNat32.run.ok b/test/trap/ok/mulNat32.run.ok index 37e7a009b19..99b5cefbbdb 100644 --- a/test/trap/ok/mulNat32.run.ok +++ b/test/trap/ok/mulNat32.run.ok @@ -1 +1 @@ -mulNat32.as:1.9-1.42: execution error, arithmetic overflow +mulNat32.mo:1.9-1.42: execution error, arithmetic overflow diff --git a/test/trap/ok/mulNat64.run-ir.ok b/test/trap/ok/mulNat64.run-ir.ok index 816128a21e8..30cfb8ccc81 100644 --- a/test/trap/ok/mulNat64.run-ir.ok +++ b/test/trap/ok/mulNat64.run-ir.ok @@ -1 +1 @@ -mulNat64.as:1.9-1.58: execution error, arithmetic overflow +mulNat64.mo:1.9-1.58: execution error, arithmetic overflow diff --git a/test/trap/ok/mulNat64.run-low.ok b/test/trap/ok/mulNat64.run-low.ok index 816128a21e8..30cfb8ccc81 100644 --- a/test/trap/ok/mulNat64.run-low.ok +++ b/test/trap/ok/mulNat64.run-low.ok @@ -1 +1 @@ -mulNat64.as:1.9-1.58: execution error, arithmetic overflow +mulNat64.mo:1.9-1.58: execution error, arithmetic overflow diff --git a/test/trap/ok/mulNat64.run.ok b/test/trap/ok/mulNat64.run.ok index 816128a21e8..30cfb8ccc81 100644 --- a/test/trap/ok/mulNat64.run.ok +++ b/test/trap/ok/mulNat64.run.ok @@ -1 +1 @@ -mulNat64.as:1.9-1.58: execution error, arithmetic overflow +mulNat64.mo:1.9-1.58: execution error, arithmetic overflow diff --git a/test/trap/ok/mulNat8.run-ir.ok b/test/trap/ok/mulNat8.run-ir.ok index 5873fd751db..02eb231f35b 100644 --- a/test/trap/ok/mulNat8.run-ir.ok +++ b/test/trap/ok/mulNat8.run-ir.ok @@ -1 +1 @@ -mulNat8.as:1.9-1.34: execution error, arithmetic overflow +mulNat8.mo:1.9-1.34: execution error, arithmetic overflow diff --git a/test/trap/ok/mulNat8.run-low.ok b/test/trap/ok/mulNat8.run-low.ok index 5873fd751db..02eb231f35b 100644 --- a/test/trap/ok/mulNat8.run-low.ok +++ b/test/trap/ok/mulNat8.run-low.ok @@ -1 +1 @@ -mulNat8.as:1.9-1.34: execution error, arithmetic overflow +mulNat8.mo:1.9-1.34: execution error, arithmetic overflow diff --git a/test/trap/ok/mulNat8.run.ok b/test/trap/ok/mulNat8.run.ok index 5873fd751db..02eb231f35b 100644 --- a/test/trap/ok/mulNat8.run.ok +++ b/test/trap/ok/mulNat8.run.ok @@ -1 +1 @@ -mulNat8.as:1.9-1.34: execution error, arithmetic overflow +mulNat8.mo:1.9-1.34: execution error, arithmetic overflow diff --git a/test/trap/ok/outrange-int16-negation.run-ir.ok b/test/trap/ok/outrange-int16-negation.run-ir.ok index ddbdfed7780..853ee28f05a 100644 --- a/test/trap/ok/outrange-int16-negation.run-ir.ok +++ b/test/trap/ok/outrange-int16-negation.run-ir.ok @@ -1 +1 @@ -outrange-int16-negation.as:1.9-1.33: execution error, value out of bounds +outrange-int16-negation.mo:1.9-1.33: execution error, value out of bounds diff --git a/test/trap/ok/outrange-int16-negation.run-low.ok b/test/trap/ok/outrange-int16-negation.run-low.ok index ddbdfed7780..853ee28f05a 100644 --- a/test/trap/ok/outrange-int16-negation.run-low.ok +++ b/test/trap/ok/outrange-int16-negation.run-low.ok @@ -1 +1 @@ -outrange-int16-negation.as:1.9-1.33: execution error, value out of bounds +outrange-int16-negation.mo:1.9-1.33: execution error, value out of bounds diff --git a/test/trap/ok/outrange-int16-negation.run.ok b/test/trap/ok/outrange-int16-negation.run.ok index ddbdfed7780..853ee28f05a 100644 --- a/test/trap/ok/outrange-int16-negation.run.ok +++ b/test/trap/ok/outrange-int16-negation.run.ok @@ -1 +1 @@ -outrange-int16-negation.as:1.9-1.33: execution error, value out of bounds +outrange-int16-negation.mo:1.9-1.33: execution error, value out of bounds diff --git a/test/trap/ok/outrange-int32-negation.run-ir.ok b/test/trap/ok/outrange-int32-negation.run-ir.ok index 0f7f8d168ac..792f81de9e7 100644 --- a/test/trap/ok/outrange-int32-negation.run-ir.ok +++ b/test/trap/ok/outrange-int32-negation.run-ir.ok @@ -1 +1 @@ -outrange-int32-negation.as:1.9-1.33: execution error, value out of bounds +outrange-int32-negation.mo:1.9-1.33: execution error, value out of bounds diff --git a/test/trap/ok/outrange-int32-negation.run-low.ok b/test/trap/ok/outrange-int32-negation.run-low.ok index 0f7f8d168ac..792f81de9e7 100644 --- a/test/trap/ok/outrange-int32-negation.run-low.ok +++ b/test/trap/ok/outrange-int32-negation.run-low.ok @@ -1 +1 @@ -outrange-int32-negation.as:1.9-1.33: execution error, value out of bounds +outrange-int32-negation.mo:1.9-1.33: execution error, value out of bounds diff --git a/test/trap/ok/outrange-int32-negation.run.ok b/test/trap/ok/outrange-int32-negation.run.ok index 0f7f8d168ac..792f81de9e7 100644 --- a/test/trap/ok/outrange-int32-negation.run.ok +++ b/test/trap/ok/outrange-int32-negation.run.ok @@ -1 +1 @@ -outrange-int32-negation.as:1.9-1.33: execution error, value out of bounds +outrange-int32-negation.mo:1.9-1.33: execution error, value out of bounds diff --git a/test/trap/ok/outrange-int64-negation.run-ir.ok b/test/trap/ok/outrange-int64-negation.run-ir.ok index a02a1a02263..45f6894b18d 100644 --- a/test/trap/ok/outrange-int64-negation.run-ir.ok +++ b/test/trap/ok/outrange-int64-negation.run-ir.ok @@ -1 +1 @@ -outrange-int64-negation.as:1.9-1.33: execution error, value out of bounds +outrange-int64-negation.mo:1.9-1.33: execution error, value out of bounds diff --git a/test/trap/ok/outrange-int64-negation.run-low.ok b/test/trap/ok/outrange-int64-negation.run-low.ok index a02a1a02263..45f6894b18d 100644 --- a/test/trap/ok/outrange-int64-negation.run-low.ok +++ b/test/trap/ok/outrange-int64-negation.run-low.ok @@ -1 +1 @@ -outrange-int64-negation.as:1.9-1.33: execution error, value out of bounds +outrange-int64-negation.mo:1.9-1.33: execution error, value out of bounds diff --git a/test/trap/ok/outrange-int64-negation.run.ok b/test/trap/ok/outrange-int64-negation.run.ok index a02a1a02263..45f6894b18d 100644 --- a/test/trap/ok/outrange-int64-negation.run.ok +++ b/test/trap/ok/outrange-int64-negation.run.ok @@ -1 +1 @@ -outrange-int64-negation.as:1.9-1.33: execution error, value out of bounds +outrange-int64-negation.mo:1.9-1.33: execution error, value out of bounds diff --git a/test/trap/ok/outrange-int8-negation.run-ir.ok b/test/trap/ok/outrange-int8-negation.run-ir.ok index ad485b61ad4..17851ac1bc7 100644 --- a/test/trap/ok/outrange-int8-negation.run-ir.ok +++ b/test/trap/ok/outrange-int8-negation.run-ir.ok @@ -1 +1 @@ -outrange-int8-negation.as:1.9-1.31: execution error, value out of bounds +outrange-int8-negation.mo:1.9-1.31: execution error, value out of bounds diff --git a/test/trap/ok/outrange-int8-negation.run-low.ok b/test/trap/ok/outrange-int8-negation.run-low.ok index ad485b61ad4..17851ac1bc7 100644 --- a/test/trap/ok/outrange-int8-negation.run-low.ok +++ b/test/trap/ok/outrange-int8-negation.run-low.ok @@ -1 +1 @@ -outrange-int8-negation.as:1.9-1.31: execution error, value out of bounds +outrange-int8-negation.mo:1.9-1.31: execution error, value out of bounds diff --git a/test/trap/ok/outrange-int8-negation.run.ok b/test/trap/ok/outrange-int8-negation.run.ok index ad485b61ad4..17851ac1bc7 100644 --- a/test/trap/ok/outrange-int8-negation.run.ok +++ b/test/trap/ok/outrange-int8-negation.run.ok @@ -1 +1 @@ -outrange-int8-negation.as:1.9-1.31: execution error, value out of bounds +outrange-int8-negation.mo:1.9-1.31: execution error, value out of bounds diff --git a/test/trap/ok/powInt32-lower.run-ir.ok b/test/trap/ok/powInt32-lower.run-ir.ok index 768b933644b..59af997ef73 100644 --- a/test/trap/ok/powInt32-lower.run-ir.ok +++ b/test/trap/ok/powInt32-lower.run-ir.ok @@ -1 +1 @@ -powInt32-lower.as:1.9-1.39: execution error, arithmetic overflow +powInt32-lower.mo:1.9-1.39: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt32-lower.run-low.ok b/test/trap/ok/powInt32-lower.run-low.ok index 768b933644b..59af997ef73 100644 --- a/test/trap/ok/powInt32-lower.run-low.ok +++ b/test/trap/ok/powInt32-lower.run-low.ok @@ -1 +1 @@ -powInt32-lower.as:1.9-1.39: execution error, arithmetic overflow +powInt32-lower.mo:1.9-1.39: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt32-lower.run.ok b/test/trap/ok/powInt32-lower.run.ok index 768b933644b..59af997ef73 100644 --- a/test/trap/ok/powInt32-lower.run.ok +++ b/test/trap/ok/powInt32-lower.run.ok @@ -1 +1 @@ -powInt32-lower.as:1.9-1.39: execution error, arithmetic overflow +powInt32-lower.mo:1.9-1.39: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt32-raise-neg.run-ir.ok b/test/trap/ok/powInt32-raise-neg.run-ir.ok index 6660e86c6ff..9c69bdd41ba 100644 --- a/test/trap/ok/powInt32-raise-neg.run-ir.ok +++ b/test/trap/ok/powInt32-raise-neg.run-ir.ok @@ -1 +1 @@ -powInt32-raise-neg.as:1.9-1.37: execution error, arithmetic overflow +powInt32-raise-neg.mo:1.9-1.37: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt32-raise-neg.run-low.ok b/test/trap/ok/powInt32-raise-neg.run-low.ok index 6660e86c6ff..9c69bdd41ba 100644 --- a/test/trap/ok/powInt32-raise-neg.run-low.ok +++ b/test/trap/ok/powInt32-raise-neg.run-low.ok @@ -1 +1 @@ -powInt32-raise-neg.as:1.9-1.37: execution error, arithmetic overflow +powInt32-raise-neg.mo:1.9-1.37: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt32-raise-neg.run.ok b/test/trap/ok/powInt32-raise-neg.run.ok index 6660e86c6ff..9c69bdd41ba 100644 --- a/test/trap/ok/powInt32-raise-neg.run.ok +++ b/test/trap/ok/powInt32-raise-neg.run.ok @@ -1 +1 @@ -powInt32-raise-neg.as:1.9-1.37: execution error, arithmetic overflow +powInt32-raise-neg.mo:1.9-1.37: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt32-upper.run-ir.ok b/test/trap/ok/powInt32-upper.run-ir.ok index 0c18eae037c..569611dcf30 100644 --- a/test/trap/ok/powInt32-upper.run-ir.ok +++ b/test/trap/ok/powInt32-upper.run-ir.ok @@ -1 +1 @@ -powInt32-upper.as:1.9-1.36: execution error, arithmetic overflow +powInt32-upper.mo:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt32-upper.run-low.ok b/test/trap/ok/powInt32-upper.run-low.ok index 0c18eae037c..569611dcf30 100644 --- a/test/trap/ok/powInt32-upper.run-low.ok +++ b/test/trap/ok/powInt32-upper.run-low.ok @@ -1 +1 @@ -powInt32-upper.as:1.9-1.36: execution error, arithmetic overflow +powInt32-upper.mo:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt32-upper.run.ok b/test/trap/ok/powInt32-upper.run.ok index 0c18eae037c..569611dcf30 100644 --- a/test/trap/ok/powInt32-upper.run.ok +++ b/test/trap/ok/powInt32-upper.run.ok @@ -1 +1 @@ -powInt32-upper.as:1.9-1.36: execution error, arithmetic overflow +powInt32-upper.mo:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt64-lower-fast.run-ir.ok b/test/trap/ok/powInt64-lower-fast.run-ir.ok index 66a5a93a328..1683f288141 100644 --- a/test/trap/ok/powInt64-lower-fast.run-ir.ok +++ b/test/trap/ok/powInt64-lower-fast.run-ir.ok @@ -1 +1 @@ -powInt64-lower-fast.as:1.9-1.37: execution error, arithmetic overflow +powInt64-lower-fast.mo:1.9-1.37: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt64-lower-fast.run-low.ok b/test/trap/ok/powInt64-lower-fast.run-low.ok index 66a5a93a328..1683f288141 100644 --- a/test/trap/ok/powInt64-lower-fast.run-low.ok +++ b/test/trap/ok/powInt64-lower-fast.run-low.ok @@ -1 +1 @@ -powInt64-lower-fast.as:1.9-1.37: execution error, arithmetic overflow +powInt64-lower-fast.mo:1.9-1.37: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt64-lower-fast.run.ok b/test/trap/ok/powInt64-lower-fast.run.ok index 66a5a93a328..1683f288141 100644 --- a/test/trap/ok/powInt64-lower-fast.run.ok +++ b/test/trap/ok/powInt64-lower-fast.run.ok @@ -1 +1 @@ -powInt64-lower-fast.as:1.9-1.37: execution error, arithmetic overflow +powInt64-lower-fast.mo:1.9-1.37: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt64-lower-slow.run-ir.ok b/test/trap/ok/powInt64-lower-slow.run-ir.ok index 0fd2e8c791f..e78c61fff0f 100644 --- a/test/trap/ok/powInt64-lower-slow.run-ir.ok +++ b/test/trap/ok/powInt64-lower-slow.run-ir.ok @@ -1 +1 @@ -powInt64-lower-slow.as:1.9-1.37: execution error, arithmetic overflow +powInt64-lower-slow.mo:1.9-1.37: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt64-lower-slow.run-low.ok b/test/trap/ok/powInt64-lower-slow.run-low.ok index 0fd2e8c791f..e78c61fff0f 100644 --- a/test/trap/ok/powInt64-lower-slow.run-low.ok +++ b/test/trap/ok/powInt64-lower-slow.run-low.ok @@ -1 +1 @@ -powInt64-lower-slow.as:1.9-1.37: execution error, arithmetic overflow +powInt64-lower-slow.mo:1.9-1.37: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt64-lower-slow.run.ok b/test/trap/ok/powInt64-lower-slow.run.ok index 0fd2e8c791f..e78c61fff0f 100644 --- a/test/trap/ok/powInt64-lower-slow.run.ok +++ b/test/trap/ok/powInt64-lower-slow.run.ok @@ -1 +1 @@ -powInt64-lower-slow.as:1.9-1.37: execution error, arithmetic overflow +powInt64-lower-slow.mo:1.9-1.37: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt64-raise-neg.run-ir.ok b/test/trap/ok/powInt64-raise-neg.run-ir.ok index 529eba25595..71e9cc0da5c 100644 --- a/test/trap/ok/powInt64-raise-neg.run-ir.ok +++ b/test/trap/ok/powInt64-raise-neg.run-ir.ok @@ -1 +1 @@ -powInt64-raise-neg.as:1.9-1.37: execution error, arithmetic overflow +powInt64-raise-neg.mo:1.9-1.37: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt64-raise-neg.run-low.ok b/test/trap/ok/powInt64-raise-neg.run-low.ok index 529eba25595..71e9cc0da5c 100644 --- a/test/trap/ok/powInt64-raise-neg.run-low.ok +++ b/test/trap/ok/powInt64-raise-neg.run-low.ok @@ -1 +1 @@ -powInt64-raise-neg.as:1.9-1.37: execution error, arithmetic overflow +powInt64-raise-neg.mo:1.9-1.37: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt64-raise-neg.run.ok b/test/trap/ok/powInt64-raise-neg.run.ok index 529eba25595..71e9cc0da5c 100644 --- a/test/trap/ok/powInt64-raise-neg.run.ok +++ b/test/trap/ok/powInt64-raise-neg.run.ok @@ -1 +1 @@ -powInt64-raise-neg.as:1.9-1.37: execution error, arithmetic overflow +powInt64-raise-neg.mo:1.9-1.37: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt64-upper-fast.run-ir.ok b/test/trap/ok/powInt64-upper-fast.run-ir.ok index 31662af7ca5..6838145b198 100644 --- a/test/trap/ok/powInt64-upper-fast.run-ir.ok +++ b/test/trap/ok/powInt64-upper-fast.run-ir.ok @@ -1 +1 @@ -powInt64-upper-fast.as:1.9-1.36: execution error, arithmetic overflow +powInt64-upper-fast.mo:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt64-upper-fast.run-low.ok b/test/trap/ok/powInt64-upper-fast.run-low.ok index 31662af7ca5..6838145b198 100644 --- a/test/trap/ok/powInt64-upper-fast.run-low.ok +++ b/test/trap/ok/powInt64-upper-fast.run-low.ok @@ -1 +1 @@ -powInt64-upper-fast.as:1.9-1.36: execution error, arithmetic overflow +powInt64-upper-fast.mo:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt64-upper-fast.run.ok b/test/trap/ok/powInt64-upper-fast.run.ok index 31662af7ca5..6838145b198 100644 --- a/test/trap/ok/powInt64-upper-fast.run.ok +++ b/test/trap/ok/powInt64-upper-fast.run.ok @@ -1 +1 @@ -powInt64-upper-fast.as:1.9-1.36: execution error, arithmetic overflow +powInt64-upper-fast.mo:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt64-upper-slow.run-ir.ok b/test/trap/ok/powInt64-upper-slow.run-ir.ok index c3f19d51285..622f5cf7982 100644 --- a/test/trap/ok/powInt64-upper-slow.run-ir.ok +++ b/test/trap/ok/powInt64-upper-slow.run-ir.ok @@ -1 +1 @@ -powInt64-upper-slow.as:1.9-1.36: execution error, arithmetic overflow +powInt64-upper-slow.mo:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt64-upper-slow.run-low.ok b/test/trap/ok/powInt64-upper-slow.run-low.ok index c3f19d51285..622f5cf7982 100644 --- a/test/trap/ok/powInt64-upper-slow.run-low.ok +++ b/test/trap/ok/powInt64-upper-slow.run-low.ok @@ -1 +1 @@ -powInt64-upper-slow.as:1.9-1.36: execution error, arithmetic overflow +powInt64-upper-slow.mo:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt64-upper-slow.run.ok b/test/trap/ok/powInt64-upper-slow.run.ok index c3f19d51285..622f5cf7982 100644 --- a/test/trap/ok/powInt64-upper-slow.run.ok +++ b/test/trap/ok/powInt64-upper-slow.run.ok @@ -1 +1 @@ -powInt64-upper-slow.as:1.9-1.36: execution error, arithmetic overflow +powInt64-upper-slow.mo:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt8-lower.run-ir.ok b/test/trap/ok/powInt8-lower.run-ir.ok index aaca6f96edc..2c61cabb093 100644 --- a/test/trap/ok/powInt8-lower.run-ir.ok +++ b/test/trap/ok/powInt8-lower.run-ir.ok @@ -1 +1 @@ -powInt8-lower.as:1.9-1.34: execution error, arithmetic overflow +powInt8-lower.mo:1.9-1.34: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt8-lower.run-low.ok b/test/trap/ok/powInt8-lower.run-low.ok index aaca6f96edc..2c61cabb093 100644 --- a/test/trap/ok/powInt8-lower.run-low.ok +++ b/test/trap/ok/powInt8-lower.run-low.ok @@ -1 +1 @@ -powInt8-lower.as:1.9-1.34: execution error, arithmetic overflow +powInt8-lower.mo:1.9-1.34: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt8-lower.run.ok b/test/trap/ok/powInt8-lower.run.ok index aaca6f96edc..2c61cabb093 100644 --- a/test/trap/ok/powInt8-lower.run.ok +++ b/test/trap/ok/powInt8-lower.run.ok @@ -1 +1 @@ -powInt8-lower.as:1.9-1.34: execution error, arithmetic overflow +powInt8-lower.mo:1.9-1.34: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt8-raise-neg.run-ir.ok b/test/trap/ok/powInt8-raise-neg.run-ir.ok index 37e5942034d..41aad3c106b 100644 --- a/test/trap/ok/powInt8-raise-neg.run-ir.ok +++ b/test/trap/ok/powInt8-raise-neg.run-ir.ok @@ -1 +1 @@ -powInt8-raise-neg.as:1.9-1.35: execution error, arithmetic overflow +powInt8-raise-neg.mo:1.9-1.35: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt8-raise-neg.run-low.ok b/test/trap/ok/powInt8-raise-neg.run-low.ok index 37e5942034d..41aad3c106b 100644 --- a/test/trap/ok/powInt8-raise-neg.run-low.ok +++ b/test/trap/ok/powInt8-raise-neg.run-low.ok @@ -1 +1 @@ -powInt8-raise-neg.as:1.9-1.35: execution error, arithmetic overflow +powInt8-raise-neg.mo:1.9-1.35: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt8-raise-neg.run.ok b/test/trap/ok/powInt8-raise-neg.run.ok index 37e5942034d..41aad3c106b 100644 --- a/test/trap/ok/powInt8-raise-neg.run.ok +++ b/test/trap/ok/powInt8-raise-neg.run.ok @@ -1 +1 @@ -powInt8-raise-neg.as:1.9-1.35: execution error, arithmetic overflow +powInt8-raise-neg.mo:1.9-1.35: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt8-upper.run-ir.ok b/test/trap/ok/powInt8-upper.run-ir.ok index f6fcd37f57f..9feed71d821 100644 --- a/test/trap/ok/powInt8-upper.run-ir.ok +++ b/test/trap/ok/powInt8-upper.run-ir.ok @@ -1 +1 @@ -powInt8-upper.as:1.9-1.34: execution error, arithmetic overflow +powInt8-upper.mo:1.9-1.34: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt8-upper.run-low.ok b/test/trap/ok/powInt8-upper.run-low.ok index f6fcd37f57f..9feed71d821 100644 --- a/test/trap/ok/powInt8-upper.run-low.ok +++ b/test/trap/ok/powInt8-upper.run-low.ok @@ -1 +1 @@ -powInt8-upper.as:1.9-1.34: execution error, arithmetic overflow +powInt8-upper.mo:1.9-1.34: execution error, arithmetic overflow diff --git a/test/trap/ok/powInt8-upper.run.ok b/test/trap/ok/powInt8-upper.run.ok index f6fcd37f57f..9feed71d821 100644 --- a/test/trap/ok/powInt8-upper.run.ok +++ b/test/trap/ok/powInt8-upper.run.ok @@ -1 +1 @@ -powInt8-upper.as:1.9-1.34: execution error, arithmetic overflow +powInt8-upper.mo:1.9-1.34: execution error, arithmetic overflow diff --git a/test/trap/ok/powNat16.run-ir.ok b/test/trap/ok/powNat16.run-ir.ok index e94d06ffe4f..70c92fed48f 100644 --- a/test/trap/ok/powNat16.run-ir.ok +++ b/test/trap/ok/powNat16.run-ir.ok @@ -1 +1 @@ -powNat16.as:1.9-1.35: execution error, arithmetic overflow +powNat16.mo:1.9-1.35: execution error, arithmetic overflow diff --git a/test/trap/ok/powNat16.run-low.ok b/test/trap/ok/powNat16.run-low.ok index e94d06ffe4f..70c92fed48f 100644 --- a/test/trap/ok/powNat16.run-low.ok +++ b/test/trap/ok/powNat16.run-low.ok @@ -1 +1 @@ -powNat16.as:1.9-1.35: execution error, arithmetic overflow +powNat16.mo:1.9-1.35: execution error, arithmetic overflow diff --git a/test/trap/ok/powNat16.run.ok b/test/trap/ok/powNat16.run.ok index e94d06ffe4f..70c92fed48f 100644 --- a/test/trap/ok/powNat16.run.ok +++ b/test/trap/ok/powNat16.run.ok @@ -1 +1 @@ -powNat16.as:1.9-1.35: execution error, arithmetic overflow +powNat16.mo:1.9-1.35: execution error, arithmetic overflow diff --git a/test/trap/ok/powNat32.run-ir.ok b/test/trap/ok/powNat32.run-ir.ok index 723841a34e6..5ce27e89c62 100644 --- a/test/trap/ok/powNat32.run-ir.ok +++ b/test/trap/ok/powNat32.run-ir.ok @@ -1 +1 @@ -powNat32.as:1.9-1.36: execution error, arithmetic overflow +powNat32.mo:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/powNat32.run-low.ok b/test/trap/ok/powNat32.run-low.ok index 723841a34e6..5ce27e89c62 100644 --- a/test/trap/ok/powNat32.run-low.ok +++ b/test/trap/ok/powNat32.run-low.ok @@ -1 +1 @@ -powNat32.as:1.9-1.36: execution error, arithmetic overflow +powNat32.mo:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/powNat32.run.ok b/test/trap/ok/powNat32.run.ok index 723841a34e6..5ce27e89c62 100644 --- a/test/trap/ok/powNat32.run.ok +++ b/test/trap/ok/powNat32.run.ok @@ -1 +1 @@ -powNat32.as:1.9-1.36: execution error, arithmetic overflow +powNat32.mo:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/powNat64.run-ir.ok b/test/trap/ok/powNat64.run-ir.ok index befe74d8029..ffc5d86d454 100644 --- a/test/trap/ok/powNat64.run-ir.ok +++ b/test/trap/ok/powNat64.run-ir.ok @@ -1 +1 @@ -powNat64.as:1.9-1.41: execution error, arithmetic overflow +powNat64.mo:1.9-1.41: execution error, arithmetic overflow diff --git a/test/trap/ok/powNat64.run-low.ok b/test/trap/ok/powNat64.run-low.ok index befe74d8029..ffc5d86d454 100644 --- a/test/trap/ok/powNat64.run-low.ok +++ b/test/trap/ok/powNat64.run-low.ok @@ -1 +1 @@ -powNat64.as:1.9-1.41: execution error, arithmetic overflow +powNat64.mo:1.9-1.41: execution error, arithmetic overflow diff --git a/test/trap/ok/powNat64.run.ok b/test/trap/ok/powNat64.run.ok index befe74d8029..ffc5d86d454 100644 --- a/test/trap/ok/powNat64.run.ok +++ b/test/trap/ok/powNat64.run.ok @@ -1 +1 @@ -powNat64.as:1.9-1.41: execution error, arithmetic overflow +powNat64.mo:1.9-1.41: execution error, arithmetic overflow diff --git a/test/trap/ok/powNat8.run-ir.ok b/test/trap/ok/powNat8.run-ir.ok index a1d4ca72c2e..83aa9a75afd 100644 --- a/test/trap/ok/powNat8.run-ir.ok +++ b/test/trap/ok/powNat8.run-ir.ok @@ -1 +1 @@ -powNat8.as:1.9-1.33: execution error, arithmetic overflow +powNat8.mo:1.9-1.33: execution error, arithmetic overflow diff --git a/test/trap/ok/powNat8.run-low.ok b/test/trap/ok/powNat8.run-low.ok index a1d4ca72c2e..83aa9a75afd 100644 --- a/test/trap/ok/powNat8.run-low.ok +++ b/test/trap/ok/powNat8.run-low.ok @@ -1 +1 @@ -powNat8.as:1.9-1.33: execution error, arithmetic overflow +powNat8.mo:1.9-1.33: execution error, arithmetic overflow diff --git a/test/trap/ok/powNat8.run.ok b/test/trap/ok/powNat8.run.ok index a1d4ca72c2e..83aa9a75afd 100644 --- a/test/trap/ok/powNat8.run.ok +++ b/test/trap/ok/powNat8.run.ok @@ -1 +1 @@ -powNat8.as:1.9-1.33: execution error, arithmetic overflow +powNat8.mo:1.9-1.33: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt16-lower.run-ir.ok b/test/trap/ok/subInt16-lower.run-ir.ok index 22d529184b6..2ddb1339a84 100644 --- a/test/trap/ok/subInt16-lower.run-ir.ok +++ b/test/trap/ok/subInt16-lower.run-ir.ok @@ -1 +1 @@ -subInt16-lower.as:1.9-1.39: execution error, arithmetic overflow +subInt16-lower.mo:1.9-1.39: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt16-lower.run-low.ok b/test/trap/ok/subInt16-lower.run-low.ok index 22d529184b6..2ddb1339a84 100644 --- a/test/trap/ok/subInt16-lower.run-low.ok +++ b/test/trap/ok/subInt16-lower.run-low.ok @@ -1 +1 @@ -subInt16-lower.as:1.9-1.39: execution error, arithmetic overflow +subInt16-lower.mo:1.9-1.39: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt16-lower.run.ok b/test/trap/ok/subInt16-lower.run.ok index 22d529184b6..2ddb1339a84 100644 --- a/test/trap/ok/subInt16-lower.run.ok +++ b/test/trap/ok/subInt16-lower.run.ok @@ -1 +1 @@ -subInt16-lower.as:1.9-1.39: execution error, arithmetic overflow +subInt16-lower.mo:1.9-1.39: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt16-upper.run-ir.ok b/test/trap/ok/subInt16-upper.run-ir.ok index c440d4eaa3b..003aa877208 100644 --- a/test/trap/ok/subInt16-upper.run-ir.ok +++ b/test/trap/ok/subInt16-upper.run-ir.ok @@ -1 +1 @@ -subInt16-upper.as:1.9-1.39: execution error, arithmetic overflow +subInt16-upper.mo:1.9-1.39: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt16-upper.run-low.ok b/test/trap/ok/subInt16-upper.run-low.ok index c440d4eaa3b..003aa877208 100644 --- a/test/trap/ok/subInt16-upper.run-low.ok +++ b/test/trap/ok/subInt16-upper.run-low.ok @@ -1 +1 @@ -subInt16-upper.as:1.9-1.39: execution error, arithmetic overflow +subInt16-upper.mo:1.9-1.39: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt16-upper.run.ok b/test/trap/ok/subInt16-upper.run.ok index c440d4eaa3b..003aa877208 100644 --- a/test/trap/ok/subInt16-upper.run.ok +++ b/test/trap/ok/subInt16-upper.run.ok @@ -1 +1 @@ -subInt16-upper.as:1.9-1.39: execution error, arithmetic overflow +subInt16-upper.mo:1.9-1.39: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt32-lower.run-ir.ok b/test/trap/ok/subInt32-lower.run-ir.ok index 11e292f395f..a221d37dc58 100644 --- a/test/trap/ok/subInt32-lower.run-ir.ok +++ b/test/trap/ok/subInt32-lower.run-ir.ok @@ -1 +1 @@ -subInt32-lower.as:1.9-1.47: execution error, arithmetic overflow +subInt32-lower.mo:1.9-1.47: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt32-lower.run-low.ok b/test/trap/ok/subInt32-lower.run-low.ok index 11e292f395f..a221d37dc58 100644 --- a/test/trap/ok/subInt32-lower.run-low.ok +++ b/test/trap/ok/subInt32-lower.run-low.ok @@ -1 +1 @@ -subInt32-lower.as:1.9-1.47: execution error, arithmetic overflow +subInt32-lower.mo:1.9-1.47: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt32-lower.run.ok b/test/trap/ok/subInt32-lower.run.ok index 11e292f395f..a221d37dc58 100644 --- a/test/trap/ok/subInt32-lower.run.ok +++ b/test/trap/ok/subInt32-lower.run.ok @@ -1 +1 @@ -subInt32-lower.as:1.9-1.47: execution error, arithmetic overflow +subInt32-lower.mo:1.9-1.47: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt32-upper.run-ir.ok b/test/trap/ok/subInt32-upper.run-ir.ok index b1db8940b4c..580e61e23c0 100644 --- a/test/trap/ok/subInt32-upper.run-ir.ok +++ b/test/trap/ok/subInt32-upper.run-ir.ok @@ -1 +1 @@ -subInt32-upper.as:1.9-1.47: execution error, arithmetic overflow +subInt32-upper.mo:1.9-1.47: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt32-upper.run-low.ok b/test/trap/ok/subInt32-upper.run-low.ok index b1db8940b4c..580e61e23c0 100644 --- a/test/trap/ok/subInt32-upper.run-low.ok +++ b/test/trap/ok/subInt32-upper.run-low.ok @@ -1 +1 @@ -subInt32-upper.as:1.9-1.47: execution error, arithmetic overflow +subInt32-upper.mo:1.9-1.47: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt32-upper.run.ok b/test/trap/ok/subInt32-upper.run.ok index b1db8940b4c..580e61e23c0 100644 --- a/test/trap/ok/subInt32-upper.run.ok +++ b/test/trap/ok/subInt32-upper.run.ok @@ -1 +1 @@ -subInt32-upper.as:1.9-1.47: execution error, arithmetic overflow +subInt32-upper.mo:1.9-1.47: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt64-lower.run-ir.ok b/test/trap/ok/subInt64-lower.run-ir.ok index f3f2790aaf7..c642ae23d98 100644 --- a/test/trap/ok/subInt64-lower.run-ir.ok +++ b/test/trap/ok/subInt64-lower.run-ir.ok @@ -1 +1 @@ -subInt64-lower.as:1.9-1.59: execution error, arithmetic overflow +subInt64-lower.mo:1.9-1.59: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt64-lower.run-low.ok b/test/trap/ok/subInt64-lower.run-low.ok index f3f2790aaf7..c642ae23d98 100644 --- a/test/trap/ok/subInt64-lower.run-low.ok +++ b/test/trap/ok/subInt64-lower.run-low.ok @@ -1 +1 @@ -subInt64-lower.as:1.9-1.59: execution error, arithmetic overflow +subInt64-lower.mo:1.9-1.59: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt64-lower.run.ok b/test/trap/ok/subInt64-lower.run.ok index f3f2790aaf7..c642ae23d98 100644 --- a/test/trap/ok/subInt64-lower.run.ok +++ b/test/trap/ok/subInt64-lower.run.ok @@ -1 +1 @@ -subInt64-lower.as:1.9-1.59: execution error, arithmetic overflow +subInt64-lower.mo:1.9-1.59: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt64-upper.run-ir.ok b/test/trap/ok/subInt64-upper.run-ir.ok index 5f3501be12a..adbcdb6cfef 100644 --- a/test/trap/ok/subInt64-upper.run-ir.ok +++ b/test/trap/ok/subInt64-upper.run-ir.ok @@ -1 +1 @@ -subInt64-upper.as:1.9-1.59: execution error, arithmetic overflow +subInt64-upper.mo:1.9-1.59: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt64-upper.run-low.ok b/test/trap/ok/subInt64-upper.run-low.ok index 5f3501be12a..adbcdb6cfef 100644 --- a/test/trap/ok/subInt64-upper.run-low.ok +++ b/test/trap/ok/subInt64-upper.run-low.ok @@ -1 +1 @@ -subInt64-upper.as:1.9-1.59: execution error, arithmetic overflow +subInt64-upper.mo:1.9-1.59: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt64-upper.run.ok b/test/trap/ok/subInt64-upper.run.ok index 5f3501be12a..adbcdb6cfef 100644 --- a/test/trap/ok/subInt64-upper.run.ok +++ b/test/trap/ok/subInt64-upper.run.ok @@ -1 +1 @@ -subInt64-upper.as:1.9-1.59: execution error, arithmetic overflow +subInt64-upper.mo:1.9-1.59: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt8-lower.run-ir.ok b/test/trap/ok/subInt8-lower.run-ir.ok index ead4dc243a5..e767c7f0404 100644 --- a/test/trap/ok/subInt8-lower.run-ir.ok +++ b/test/trap/ok/subInt8-lower.run-ir.ok @@ -1 +1 @@ -subInt8-lower.as:1.9-1.35: execution error, arithmetic overflow +subInt8-lower.mo:1.9-1.35: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt8-lower.run-low.ok b/test/trap/ok/subInt8-lower.run-low.ok index ead4dc243a5..e767c7f0404 100644 --- a/test/trap/ok/subInt8-lower.run-low.ok +++ b/test/trap/ok/subInt8-lower.run-low.ok @@ -1 +1 @@ -subInt8-lower.as:1.9-1.35: execution error, arithmetic overflow +subInt8-lower.mo:1.9-1.35: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt8-lower.run.ok b/test/trap/ok/subInt8-lower.run.ok index ead4dc243a5..e767c7f0404 100644 --- a/test/trap/ok/subInt8-lower.run.ok +++ b/test/trap/ok/subInt8-lower.run.ok @@ -1 +1 @@ -subInt8-lower.as:1.9-1.35: execution error, arithmetic overflow +subInt8-lower.mo:1.9-1.35: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt8-upper.run-ir.ok b/test/trap/ok/subInt8-upper.run-ir.ok index 9ae20177fb6..ca24e63152c 100644 --- a/test/trap/ok/subInt8-upper.run-ir.ok +++ b/test/trap/ok/subInt8-upper.run-ir.ok @@ -1 +1 @@ -subInt8-upper.as:1.9-1.35: execution error, arithmetic overflow +subInt8-upper.mo:1.9-1.35: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt8-upper.run-low.ok b/test/trap/ok/subInt8-upper.run-low.ok index 9ae20177fb6..ca24e63152c 100644 --- a/test/trap/ok/subInt8-upper.run-low.ok +++ b/test/trap/ok/subInt8-upper.run-low.ok @@ -1 +1 @@ -subInt8-upper.as:1.9-1.35: execution error, arithmetic overflow +subInt8-upper.mo:1.9-1.35: execution error, arithmetic overflow diff --git a/test/trap/ok/subInt8-upper.run.ok b/test/trap/ok/subInt8-upper.run.ok index 9ae20177fb6..ca24e63152c 100644 --- a/test/trap/ok/subInt8-upper.run.ok +++ b/test/trap/ok/subInt8-upper.run.ok @@ -1 +1 @@ -subInt8-upper.as:1.9-1.35: execution error, arithmetic overflow +subInt8-upper.mo:1.9-1.35: execution error, arithmetic overflow diff --git a/test/trap/ok/subNat16.run-ir.ok b/test/trap/ok/subNat16.run-ir.ok index 3667438a5e7..361e5994c14 100644 --- a/test/trap/ok/subNat16.run-ir.ok +++ b/test/trap/ok/subNat16.run-ir.ok @@ -1 +1 @@ -subNat16.as:1.9-1.36: execution error, arithmetic overflow +subNat16.mo:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/subNat16.run-low.ok b/test/trap/ok/subNat16.run-low.ok index 3667438a5e7..361e5994c14 100644 --- a/test/trap/ok/subNat16.run-low.ok +++ b/test/trap/ok/subNat16.run-low.ok @@ -1 +1 @@ -subNat16.as:1.9-1.36: execution error, arithmetic overflow +subNat16.mo:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/subNat16.run.ok b/test/trap/ok/subNat16.run.ok index 3667438a5e7..361e5994c14 100644 --- a/test/trap/ok/subNat16.run.ok +++ b/test/trap/ok/subNat16.run.ok @@ -1 +1 @@ -subNat16.as:1.9-1.36: execution error, arithmetic overflow +subNat16.mo:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/subNat32.run-ir.ok b/test/trap/ok/subNat32.run-ir.ok index 398ff3eef50..28ed9f02ff8 100644 --- a/test/trap/ok/subNat32.run-ir.ok +++ b/test/trap/ok/subNat32.run-ir.ok @@ -1 +1 @@ -subNat32.as:1.9-1.36: execution error, arithmetic overflow +subNat32.mo:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/subNat32.run-low.ok b/test/trap/ok/subNat32.run-low.ok index 398ff3eef50..28ed9f02ff8 100644 --- a/test/trap/ok/subNat32.run-low.ok +++ b/test/trap/ok/subNat32.run-low.ok @@ -1 +1 @@ -subNat32.as:1.9-1.36: execution error, arithmetic overflow +subNat32.mo:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/subNat32.run.ok b/test/trap/ok/subNat32.run.ok index 398ff3eef50..28ed9f02ff8 100644 --- a/test/trap/ok/subNat32.run.ok +++ b/test/trap/ok/subNat32.run.ok @@ -1 +1 @@ -subNat32.as:1.9-1.36: execution error, arithmetic overflow +subNat32.mo:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/subNat64-slow.run-ir.ok b/test/trap/ok/subNat64-slow.run-ir.ok index b2fa6c6e4cd..0bb48f62af8 100644 --- a/test/trap/ok/subNat64-slow.run-ir.ok +++ b/test/trap/ok/subNat64-slow.run-ir.ok @@ -1 +1 @@ -subNat64-slow.as:1.9-1.84: execution error, arithmetic overflow +subNat64-slow.mo:1.9-1.84: execution error, arithmetic overflow diff --git a/test/trap/ok/subNat64-slow.run-low.ok b/test/trap/ok/subNat64-slow.run-low.ok index b2fa6c6e4cd..0bb48f62af8 100644 --- a/test/trap/ok/subNat64-slow.run-low.ok +++ b/test/trap/ok/subNat64-slow.run-low.ok @@ -1 +1 @@ -subNat64-slow.as:1.9-1.84: execution error, arithmetic overflow +subNat64-slow.mo:1.9-1.84: execution error, arithmetic overflow diff --git a/test/trap/ok/subNat64-slow.run.ok b/test/trap/ok/subNat64-slow.run.ok index b2fa6c6e4cd..0bb48f62af8 100644 --- a/test/trap/ok/subNat64-slow.run.ok +++ b/test/trap/ok/subNat64-slow.run.ok @@ -1 +1 @@ -subNat64-slow.as:1.9-1.84: execution error, arithmetic overflow +subNat64-slow.mo:1.9-1.84: execution error, arithmetic overflow diff --git a/test/trap/ok/subNat64.run-ir.ok b/test/trap/ok/subNat64.run-ir.ok index c06ed2bd1f9..91dae0e28c1 100644 --- a/test/trap/ok/subNat64.run-ir.ok +++ b/test/trap/ok/subNat64.run-ir.ok @@ -1 +1 @@ -subNat64.as:1.9-1.36: execution error, arithmetic overflow +subNat64.mo:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/subNat64.run-low.ok b/test/trap/ok/subNat64.run-low.ok index c06ed2bd1f9..91dae0e28c1 100644 --- a/test/trap/ok/subNat64.run-low.ok +++ b/test/trap/ok/subNat64.run-low.ok @@ -1 +1 @@ -subNat64.as:1.9-1.36: execution error, arithmetic overflow +subNat64.mo:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/subNat64.run.ok b/test/trap/ok/subNat64.run.ok index c06ed2bd1f9..91dae0e28c1 100644 --- a/test/trap/ok/subNat64.run.ok +++ b/test/trap/ok/subNat64.run.ok @@ -1 +1 @@ -subNat64.as:1.9-1.36: execution error, arithmetic overflow +subNat64.mo:1.9-1.36: execution error, arithmetic overflow diff --git a/test/trap/ok/subNat8.run-ir.ok b/test/trap/ok/subNat8.run-ir.ok index d0dfd63bcad..de4c1a85352 100644 --- a/test/trap/ok/subNat8.run-ir.ok +++ b/test/trap/ok/subNat8.run-ir.ok @@ -1 +1 @@ -subNat8.as:1.9-1.34: execution error, arithmetic overflow +subNat8.mo:1.9-1.34: execution error, arithmetic overflow diff --git a/test/trap/ok/subNat8.run-low.ok b/test/trap/ok/subNat8.run-low.ok index d0dfd63bcad..de4c1a85352 100644 --- a/test/trap/ok/subNat8.run-low.ok +++ b/test/trap/ok/subNat8.run-low.ok @@ -1 +1 @@ -subNat8.as:1.9-1.34: execution error, arithmetic overflow +subNat8.mo:1.9-1.34: execution error, arithmetic overflow diff --git a/test/trap/ok/subNat8.run.ok b/test/trap/ok/subNat8.run.ok index d0dfd63bcad..de4c1a85352 100644 --- a/test/trap/ok/subNat8.run.ok +++ b/test/trap/ok/subNat8.run.ok @@ -1 +1 @@ -subNat8.as:1.9-1.34: execution error, arithmetic overflow +subNat8.mo:1.9-1.34: execution error, arithmetic overflow diff --git a/test/trap/outrange-int16-lower.as b/test/trap/outrange-int16-lower.mo similarity index 100% rename from test/trap/outrange-int16-lower.as rename to test/trap/outrange-int16-lower.mo diff --git a/test/trap/outrange-int16-negation.as b/test/trap/outrange-int16-negation.mo similarity index 100% rename from test/trap/outrange-int16-negation.as rename to test/trap/outrange-int16-negation.mo diff --git a/test/trap/outrange-int16-upper.as b/test/trap/outrange-int16-upper.mo similarity index 100% rename from test/trap/outrange-int16-upper.as rename to test/trap/outrange-int16-upper.mo diff --git a/test/trap/outrange-int32-lower.as b/test/trap/outrange-int32-lower.mo similarity index 100% rename from test/trap/outrange-int32-lower.as rename to test/trap/outrange-int32-lower.mo diff --git a/test/trap/outrange-int32-negation.as b/test/trap/outrange-int32-negation.mo similarity index 100% rename from test/trap/outrange-int32-negation.as rename to test/trap/outrange-int32-negation.mo diff --git a/test/trap/outrange-int32-upper.as b/test/trap/outrange-int32-upper.mo similarity index 100% rename from test/trap/outrange-int32-upper.as rename to test/trap/outrange-int32-upper.mo diff --git a/test/trap/outrange-int64-lower.as b/test/trap/outrange-int64-lower.mo similarity index 100% rename from test/trap/outrange-int64-lower.as rename to test/trap/outrange-int64-lower.mo diff --git a/test/trap/outrange-int64-negation.as b/test/trap/outrange-int64-negation.mo similarity index 100% rename from test/trap/outrange-int64-negation.as rename to test/trap/outrange-int64-negation.mo diff --git a/test/trap/outrange-int64-upper.as b/test/trap/outrange-int64-upper.mo similarity index 100% rename from test/trap/outrange-int64-upper.as rename to test/trap/outrange-int64-upper.mo diff --git a/test/trap/outrange-int8-lower.as b/test/trap/outrange-int8-lower.mo similarity index 100% rename from test/trap/outrange-int8-lower.as rename to test/trap/outrange-int8-lower.mo diff --git a/test/trap/outrange-int8-negation.as b/test/trap/outrange-int8-negation.mo similarity index 100% rename from test/trap/outrange-int8-negation.as rename to test/trap/outrange-int8-negation.mo diff --git a/test/trap/outrange-int8-upper.as b/test/trap/outrange-int8-upper.mo similarity index 100% rename from test/trap/outrange-int8-upper.as rename to test/trap/outrange-int8-upper.mo diff --git a/test/trap/outrange-nat16.as b/test/trap/outrange-nat16.mo similarity index 100% rename from test/trap/outrange-nat16.as rename to test/trap/outrange-nat16.mo diff --git a/test/trap/outrange-nat32.as b/test/trap/outrange-nat32.mo similarity index 100% rename from test/trap/outrange-nat32.as rename to test/trap/outrange-nat32.mo diff --git a/test/trap/outrange-nat64.as b/test/trap/outrange-nat64.mo similarity index 100% rename from test/trap/outrange-nat64.as rename to test/trap/outrange-nat64.mo diff --git a/test/trap/outrange-nat8.as b/test/trap/outrange-nat8.mo similarity index 100% rename from test/trap/outrange-nat8.as rename to test/trap/outrange-nat8.mo diff --git a/test/trap/powInt32-lower.as b/test/trap/powInt32-lower.mo similarity index 100% rename from test/trap/powInt32-lower.as rename to test/trap/powInt32-lower.mo diff --git a/test/trap/powInt32-raise-neg.as b/test/trap/powInt32-raise-neg.mo similarity index 100% rename from test/trap/powInt32-raise-neg.as rename to test/trap/powInt32-raise-neg.mo diff --git a/test/trap/powInt32-upper.as b/test/trap/powInt32-upper.mo similarity index 100% rename from test/trap/powInt32-upper.as rename to test/trap/powInt32-upper.mo diff --git a/test/trap/powInt64-lower-fast.as b/test/trap/powInt64-lower-fast.mo similarity index 100% rename from test/trap/powInt64-lower-fast.as rename to test/trap/powInt64-lower-fast.mo diff --git a/test/trap/powInt64-lower-slow.as b/test/trap/powInt64-lower-slow.mo similarity index 100% rename from test/trap/powInt64-lower-slow.as rename to test/trap/powInt64-lower-slow.mo diff --git a/test/trap/powInt64-raise-neg.as b/test/trap/powInt64-raise-neg.mo similarity index 100% rename from test/trap/powInt64-raise-neg.as rename to test/trap/powInt64-raise-neg.mo diff --git a/test/trap/powInt64-upper-fast.as b/test/trap/powInt64-upper-fast.mo similarity index 100% rename from test/trap/powInt64-upper-fast.as rename to test/trap/powInt64-upper-fast.mo diff --git a/test/trap/powInt64-upper-slow.as b/test/trap/powInt64-upper-slow.mo similarity index 100% rename from test/trap/powInt64-upper-slow.as rename to test/trap/powInt64-upper-slow.mo diff --git a/test/trap/powInt8-lower.as b/test/trap/powInt8-lower.mo similarity index 100% rename from test/trap/powInt8-lower.as rename to test/trap/powInt8-lower.mo diff --git a/test/trap/powInt8-raise-neg.as b/test/trap/powInt8-raise-neg.mo similarity index 100% rename from test/trap/powInt8-raise-neg.as rename to test/trap/powInt8-raise-neg.mo diff --git a/test/trap/powInt8-upper.as b/test/trap/powInt8-upper.mo similarity index 100% rename from test/trap/powInt8-upper.as rename to test/trap/powInt8-upper.mo diff --git a/test/trap/powNat16.as b/test/trap/powNat16.mo similarity index 100% rename from test/trap/powNat16.as rename to test/trap/powNat16.mo diff --git a/test/trap/powNat32.as b/test/trap/powNat32.mo similarity index 100% rename from test/trap/powNat32.as rename to test/trap/powNat32.mo diff --git a/test/trap/powNat64.as b/test/trap/powNat64.mo similarity index 100% rename from test/trap/powNat64.as rename to test/trap/powNat64.mo diff --git a/test/trap/powNat8.as b/test/trap/powNat8.mo similarity index 100% rename from test/trap/powNat8.as rename to test/trap/powNat8.mo diff --git a/test/trap/subInt16-lower.as b/test/trap/subInt16-lower.mo similarity index 100% rename from test/trap/subInt16-lower.as rename to test/trap/subInt16-lower.mo diff --git a/test/trap/subInt16-upper.as b/test/trap/subInt16-upper.mo similarity index 100% rename from test/trap/subInt16-upper.as rename to test/trap/subInt16-upper.mo diff --git a/test/trap/subInt32-lower.as b/test/trap/subInt32-lower.mo similarity index 100% rename from test/trap/subInt32-lower.as rename to test/trap/subInt32-lower.mo diff --git a/test/trap/subInt32-upper.as b/test/trap/subInt32-upper.mo similarity index 100% rename from test/trap/subInt32-upper.as rename to test/trap/subInt32-upper.mo diff --git a/test/trap/subInt64-lower.as b/test/trap/subInt64-lower.mo similarity index 100% rename from test/trap/subInt64-lower.as rename to test/trap/subInt64-lower.mo diff --git a/test/trap/subInt64-upper.as b/test/trap/subInt64-upper.mo similarity index 100% rename from test/trap/subInt64-upper.as rename to test/trap/subInt64-upper.mo diff --git a/test/trap/subInt8-lower.as b/test/trap/subInt8-lower.mo similarity index 100% rename from test/trap/subInt8-lower.as rename to test/trap/subInt8-lower.mo diff --git a/test/trap/subInt8-upper.as b/test/trap/subInt8-upper.mo similarity index 100% rename from test/trap/subInt8-upper.as rename to test/trap/subInt8-upper.mo diff --git a/test/trap/subNat16.as b/test/trap/subNat16.mo similarity index 100% rename from test/trap/subNat16.as rename to test/trap/subNat16.mo diff --git a/test/trap/subNat32.as b/test/trap/subNat32.mo similarity index 100% rename from test/trap/subNat32.as rename to test/trap/subNat32.mo diff --git a/test/trap/subNat64-slow.as b/test/trap/subNat64-slow.mo similarity index 100% rename from test/trap/subNat64-slow.as rename to test/trap/subNat64-slow.mo diff --git a/test/trap/subNat64.as b/test/trap/subNat64.mo similarity index 100% rename from test/trap/subNat64.as rename to test/trap/subNat64.mo diff --git a/test/trap/subNat8.as b/test/trap/subNat8.mo similarity index 100% rename from test/trap/subNat8.as rename to test/trap/subNat8.mo From d2eb45ed6d30de5a2a94cb6d0a31ff262fc0ec81 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 29 Oct 2019 10:32:47 +0000 Subject: [PATCH 0485/1176] merge with master, update tes --- test/run-drun/ok/unsupported.tc.ok | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/run-drun/ok/unsupported.tc.ok b/test/run-drun/ok/unsupported.tc.ok index 15fb6b8cfa8..8bf627ddd69 100644 --- a/test/run-drun/ok/unsupported.tc.ok +++ b/test/run-drun/ok/unsupported.tc.ok @@ -16,8 +16,6 @@ unsupported.mo:8.31-8.53: type error, shared function types are non-shared. (This is a limitation of the current version.) unsupported.mo:19.19-19.21: type error, shared, async function must be called within an await expression (This is a limitation of the current version.) -unsupported.mo:23.16-23.18: type error, calling a shared function not yet supported - (This is a limitation of the current version.) unsupported.mo:28.8-28.9: type error, argument to await must be a call expression (This is a limitation of the current version.) unsupported.mo:32.17-32.29: type error, unsupported async block From f05808648506e03b2d982f4a601a3cfd19a421a6 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 29 Oct 2019 12:22:51 +0000 Subject: [PATCH 0486/1176] check ICCallPrim (as much as we can) --- src/codegen/compile.ml | 7 ++++--- src/ir_def/check_ir.ml | 14 ++++++++++++++ src/ir_def/construct.ml | 2 +- test/run-drun/ic-calls.mo | 24 ++++++++++++++++++++++++ test/run-drun/ok/ic-calls.run-ir.ok | 9 +++++++++ test/run-drun/ok/ic-calls.run-low.ok | 9 +++++++++ test/run-drun/ok/ic-calls.run.ok | 9 +++++++++ test/run-drun/ok/ic-calls.tc.ok | 9 +++++++++ test/run-drun/ok/ic-calls.wasm.stderr.ok | 1 + 9 files changed, 80 insertions(+), 4 deletions(-) create mode 100644 test/run-drun/ic-calls.mo create mode 100644 test/run-drun/ok/ic-calls.run-ir.ok create mode 100644 test/run-drun/ok/ic-calls.run-low.ok create mode 100644 test/run-drun/ok/ic-calls.run.ok create mode 100644 test/run-drun/ok/ic-calls.tc.ok create mode 100644 test/run-drun/ok/ic-calls.wasm.stderr.ok diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index e9d634a8a4b..360e1f77a67 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -6291,10 +6291,11 @@ and compile_exp (env : E.t) ae exp = assert (E.mode env = Flags.ICMode); Dfinity.error_code env -(* | ICCallPrim, [f;e;k;r] -> + | ICCallPrim, [f;e;k;r] -> assert (E.mode env = Flags.ICMode); - ... -*) + SR.Unreachable, + todo_trap env "compile_exp" (Arrange_ir.exp exp) + (* Unknown prim *) | _ -> SR.Unreachable, todo_trap env "compile_exp" (Arrange_ir.exp exp) diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 10d5cf71d37..ebfdf3f5ca7 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -367,6 +367,7 @@ let rec check_exp env (exp:Ir.exp) : unit = let t1 = T.promote (typ exp1) in begin match t1 with (* TODO: oneways *) +(* | T.Func (sort, T.Promises p, [], arg_tys, [T.Async ret_ty]) -> check_exp env exp2; let t_arg = T.seq arg_tys in @@ -378,6 +379,19 @@ let rec check_exp env (exp:Ir.exp) : unit = typ exp2 <: t_arg; typ k <: T.Func (T.Local, T.Returns, [], t_rets, []); typ r <: T.Func (T.Local, T.Returns, [], [T.catch], []); +*) + | T.Func (sort, T.Returns, [], arg_tys, []) -> + check_exp env exp2; + let t_arg = T.seq arg_tys in + typ exp2 <: t_arg; + (match (T.promote (typ k)) with + | T.Func (T.Shared _, T.Returns, [], t_rets, []) -> + check_concrete env exp.at (T.seq t_rets) + | T.Non -> () (* dead code, not much to check here *) + | _ -> + error env k.at "expected continuation type, but expression produces type\n %s" + (T.string_of_typ_expand t1)); + typ r <: T.Func (T.Shared T.Write, T.Returns, [], [T.text], []); | T.Non -> () (* dead code, not much to check here *) | _ -> error env exp1.at "expected function type, but expression produces type\n %s" diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index febcce01be0..19ec22fa980 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -138,7 +138,7 @@ let ic_callE f e k r = let es = [f; e; k; r] in let effs = List.map eff es in let eff = List.fold_left max_eff T.Triv effs in - { it = PrimE (ICRejectPrim, es); + { it = PrimE (ICCallPrim, es); at = no_region; note = { note_typ = T.unit; note_eff = eff } } diff --git a/test/run-drun/ic-calls.mo b/test/run-drun/ic-calls.mo new file mode 100644 index 00000000000..01dc01475dd --- /dev/null +++ b/test/run-drun/ic-calls.mo @@ -0,0 +1,24 @@ +actor { + + + public func A() : async () { + }; + + + public func B(x : Int) : async Int { + x + }; + + public func C(x : Int, y: Bool) : async (Int,Bool) { + (x,y); + }; + + public func test() : async () { + let () = await A(); + let 1 = await B(1); + let (1,true) = await C(1,true); + }; + +} +//CALL ingress inc 0x4449444C0000 + diff --git a/test/run-drun/ok/ic-calls.run-ir.ok b/test/run-drun/ok/ic-calls.run-ir.ok new file mode 100644 index 00000000000..dec54dfc5ac --- /dev/null +++ b/test/run-drun/ok/ic-calls.run-ir.ok @@ -0,0 +1,9 @@ +ic-calls.mo:18.9-18.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +ic-calls.mo:19.9-19.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (1, false) or + (0 or -1 or _, _) diff --git a/test/run-drun/ok/ic-calls.run-low.ok b/test/run-drun/ok/ic-calls.run-low.ok new file mode 100644 index 00000000000..dec54dfc5ac --- /dev/null +++ b/test/run-drun/ok/ic-calls.run-low.ok @@ -0,0 +1,9 @@ +ic-calls.mo:18.9-18.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +ic-calls.mo:19.9-19.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (1, false) or + (0 or -1 or _, _) diff --git a/test/run-drun/ok/ic-calls.run.ok b/test/run-drun/ok/ic-calls.run.ok new file mode 100644 index 00000000000..dec54dfc5ac --- /dev/null +++ b/test/run-drun/ok/ic-calls.run.ok @@ -0,0 +1,9 @@ +ic-calls.mo:18.9-18.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +ic-calls.mo:19.9-19.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (1, false) or + (0 or -1 or _, _) diff --git a/test/run-drun/ok/ic-calls.tc.ok b/test/run-drun/ok/ic-calls.tc.ok new file mode 100644 index 00000000000..dec54dfc5ac --- /dev/null +++ b/test/run-drun/ok/ic-calls.tc.ok @@ -0,0 +1,9 @@ +ic-calls.mo:18.9-18.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +ic-calls.mo:19.9-19.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (1, false) or + (0 or -1 or _, _) diff --git a/test/run-drun/ok/ic-calls.wasm.stderr.ok b/test/run-drun/ok/ic-calls.wasm.stderr.ok new file mode 100644 index 00000000000..c3da9321d4b --- /dev/null +++ b/test/run-drun/ok/ic-calls.wasm.stderr.ok @@ -0,0 +1 @@ +Fatal error: exception "Assert_failure codegen/compile.ml:4867:4" From 7382d60cb5a89e02128272d408725e36d2f3fb92 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 30 Oct 2019 09:58:54 +0100 Subject: [PATCH 0487/1176] Remove add_reply_argument, add_reject_argument they are not actually used anywhere. --- src/ir_passes/async.ml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index 2b7eaa879f2..55ae7991d11 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -45,10 +45,10 @@ module Transform(Platform : sig val platform : platform end) = struct let con_renaming = ref ConRenaming.empty - let add_reply_parameter, add_reject_parameter, add_reply_argument, add_reject_argument = + let add_reply_parameter, add_reject_parameter = match platform with - | V1 -> (true, false, true, false) - | V2 -> (false, false, true, true) + | V1 -> (true, false) + | V2 -> (false, false) (* Helper for selective code generation based on predicated lazy expressions *) let rec select bls = @@ -76,9 +76,7 @@ module Transform(Platform : sig val platform : platform end) = struct let sys_callE v1 typs vs reply reject = match platform with - | V1 -> - assert (add_reply_argument && not add_reject_argument); - callE v1 typs (seqE (vs @ [reply])) + | V1 -> callE v1 typs (seqE (vs @ [reply])) | V2 -> assert (typs = []); ic_callE v1 (seqE vs) reply reject From a82dd5ae3ac2aca5e2f5b91303c6efb2ba913613 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 30 Oct 2019 10:29:19 +0000 Subject: [PATCH 0488/1176] Bump Dfinity and upgrade compiler to call revised msg.reject API function (taking a string, not errorCode) (#795) * temporarilly disable calls to msg.reject for signature change * bump dfinity * renable msg.reject, passing a string * spurious change to trigger build * Update default.nix * one more try * Work around `drun` failing when called in parallel for the first time --- default.nix | 5 +++-- src/codegen/compile.ml | 12 +++++------- test/run-drun/ok/idl-bad.drun-run.ok | 2 +- test/run-drun/ok/idl-nary.drun-run.ok | 4 ++-- test/run-drun/ok/reject.drun-run.ok | 4 ++-- test/run-drun/reject.mo | 1 + 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/default.nix b/default.nix index 1cdb032894e..59e038a3f18 100644 --- a/default.nix +++ b/default.nix @@ -33,7 +33,7 @@ let dev = import (builtins.fetchGit { let dfinity-repo = import (builtins.fetchGit { url = "ssh://git@github.com/dfinity-lab/dfinity"; # ref = "master"; - rev = "50626f51b377c6cdf955b2b41dfae9e550025361"; + rev = "3c82c6400b0eb8c5785669996f5b8007623cd9fc"; }) { system = nixpkgs.system; }; in let sdk = import (builtins.fetchGit { @@ -299,6 +299,7 @@ rec { export ESM=${esm} export JS_USER_LIBRARY=${js-user-library} moc --version + drun --version # run this once to work around self-unpacking-race-condition make parallel qc-motoko${nixpkgs.lib.optionalString (replay != 0) " --quickcheck-replay=${toString replay}"} @@ -356,7 +357,7 @@ rec { nixpkgs.bash nixpkgs.perl filecheck - real-drun + real-drun ] ++ llvmBuildInputs; diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 659561d0f46..7d508fc667b 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -3046,7 +3046,7 @@ module Dfinity = struct E.add_func_import env "msg" "arg_data_size" [I64Type] [I32Type]; E.add_func_import env "msg" "arg_data_copy" [I64Type; I32Type; I32Type; I32Type] []; E.add_func_import env "msg" "reply" [I64Type; I32Type; I32Type] []; - E.add_func_import env "msg" "reject" [I64Type; I32Type] []; + E.add_func_import env "msg" "reject" [I64Type; I32Type; I32Type] []; E.add_func_import env "msg" "error_code" [I64Type] [I32Type]; E.add_func_import env "ic" "trap" [I32Type; I32Type] [] | Flags.AncientMode -> @@ -3183,16 +3183,14 @@ module Dfinity = struct compile_unboxed_const fi ^^ system_call env "func" "externalize" - let error_code_CANISTER_REJECT = 4l (* Api's CANISTER_REJECT *) - let reject env arg_instrs = SR.unit, get_api_nonce env ^^ + let (set_text, get_text) = new_local env "text" in arg_instrs ^^ - G.i Drop ^^ (* TODO: - https://github.com/dfinity-lab/motoko/issues/679 - don't drop but extract payload, once reject complies with spec *) - compile_unboxed_const error_code_CANISTER_REJECT ^^ + set_text ^^ + get_text ^^ Blob.payload_ptr_unskewed ^^ + get_text ^^ Heap.load_field (Blob.len_field) ^^ system_call env "msg" "reject" let error_code env = diff --git a/test/run-drun/ok/idl-bad.drun-run.ok b/test/run-drun/ok/idl-bad.drun-run.ok index d01f43ad50d..d5e839da5d6 100644 --- a/test/run-drun/ok/idl-bad.drun-run.ok +++ b/test/run-drun/ok/idl-bad.drun-run.ok @@ -1,2 +1,2 @@ ingress(0) System -Err: Error { code: ContractViolation, description: "explicit canister trap: IDL error: missing magic bytes" } +Err: IC0503: Canister 42 called 'ic.trap' with message 'explicit canister trap: IDL error: missing magic bytes' diff --git a/test/run-drun/ok/idl-nary.drun-run.ok b/test/run-drun/ok/idl-nary.drun-run.ok index 0441f484047..3ceb8691eaa 100644 --- a/test/run-drun/ok/idl-nary.drun-run.ok +++ b/test/run-drun/ok/idl-nary.drun-run.ok @@ -7,6 +7,6 @@ ingress(5) Completed: Canister: Payload: 0x4449444c016c0400710171027103710100034 ingress(6) Completed: Canister: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 ingress(7) Completed: Canister: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 ingress(8) Completed: Canister: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 -ingress(9) Err: Error { code: ContractViolation, description: "explicit canister trap: IDL error: too few arguments Text,Text,Text" } -ingress(10) Err: Error { code: ContractViolation, description: "explicit canister trap: IDL error: left-over bytes Text,Text,Text" } +ingress(9) Err: IC0503: Canister 42 called 'ic.trap' with message 'explicit canister trap: IDL error: too few arguments Text,Text,Text' +ingress(10) Err: IC0503: Canister 42 called 'ic.trap' with message 'explicit canister trap: IDL error: left-over bytes Text,Text,Text' ingress(11) Completed: Canister: Payload: 0x4449444c000471717171034f6e650354776f05546872656504466f7572 diff --git a/test/run-drun/ok/reject.drun-run.ok b/test/run-drun/ok/reject.drun-run.ok index 73e9549eaa4..8ea07ed3242 100644 --- a/test/run-drun/ok/reject.drun-run.ok +++ b/test/run-drun/ok/reject.drun-run.ok @@ -1,9 +1,9 @@ ingress(0) System debug.print: 1 -ingress(1) Completed: Canister: Reject: 4 +ingress(1) Completed: Canister: Reject: Error debug.print: 1 debug.print: ok ingress(2) Completed: Canister: Payload: 0x4449444c0000 debug.print: 1 debug.print: ok -ingress(3) Completed: Canister: Reject: 4 +ingress(3) Completed: Canister: Reject: Error diff --git a/test/run-drun/reject.mo b/test/run-drun/reject.mo index 4dc3b0a3658..788c0273c3a 100644 --- a/test/run-drun/reject.mo +++ b/test/run-drun/reject.mo @@ -23,6 +23,7 @@ actor { }; } + //CALL ingress reject1 0x4449444C0000 //CALL ingress reject2 0x4449444C0000 //CALL ingress reject3 0x4449444C0000 From b3285e36e207fb85feb13465230abe45a93d4374 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 30 Oct 2019 12:05:37 +0100 Subject: [PATCH 0489/1176] Emulate ICReplyE/ICCallE on the old platform MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This models the IC’s bookkeeping of the current reply-target: * For promising functions, the backend adds another argument for the reply continuation. * During execution, it keeps track of the reply continuation in a global * When doing further calls, it uses `func.bind_ref` to bundle the continuation with the callbacks. This requires the backend to distinguish promising functions from others. It uses the control field (`Promises 0`). The list of return types is still set to `[]`. This is probably a _bad hack_. In general, the typing needs to be cleaned up for the new platform. Maybe the `async` does not have to change any types, and we merely adjust the typing rules in the presence of a flavor flag. Callbacks are still shared functions, for now. The IR interpreter cannot handle `ICCallPrim` yet. This simply disables running the IR interpreter for now. Not everything works yet. --- src/codegen/compile.ml | 297 ++++++++++++++++++++++++++++------------ src/ir_def/check_ir.ml | 12 +- src/ir_def/construct.ml | 4 +- src/ir_passes/async.ml | 68 ++------- test/run.sh | 2 + 5 files changed, 228 insertions(+), 155 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 360e1f77a67..a402d9a09b2 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -3035,9 +3035,13 @@ module Dfinity = struct let set_api_nonce env = G.i (GlobalSet (nr (E.get_global env "api_nonce"))) let get_api_nonce env = G.i (GlobalGet (nr (E.get_global env "api_nonce"))) + let set_reply_cont env = G.i (GlobalSet (nr (E.get_global env "reply_cont"))) + let get_reply_cont env = G.i (GlobalGet (nr (E.get_global env "reply_cont"))) + let register_globals env = (* current api_nonce *) - E.add_global64 env "api_nonce" Mutable 0L + E.add_global64 env "api_nonce" Mutable 0L; + E.add_global32 env "reply_cont" Mutable 0l let system_imports env = match E.mode env with @@ -3064,7 +3068,8 @@ module Dfinity = struct E.add_func_import env "actor" "export" [I32Type; I32Type] [I32Type]; E.add_func_import env "func" "internalize" [I32Type; I32Type] []; E.add_func_import env "func" "externalize" [I32Type] [I32Type]; - E.add_func_import env "func" "bind_i32" [I32Type; I32Type] [I32Type] + E.add_func_import env "func" "bind_i32" [I32Type; I32Type] [I32Type]; + E.add_func_import env "func" "bind_ref" [I32Type; I32Type] [I32Type] | _ -> () let system_call env modname funcname = E.call_import env modname funcname @@ -3132,9 +3137,20 @@ module Dfinity = struct edesc = nr (TableExport (nr 0l)) }) + let initial_reply env = + assert (E.mode env = Flags.AncientMode); + let f = Func.of_body env ["databuf", I32Type; "elembuf", I32Type] [] + (fun env -> trap_with env "initial_reply reached") in + let fi = E.add_fun env "empty_reply" f in + E.add_dfinity_type env (fi, [ Wasm_exts.CustomModule.DataBuf; Wasm_exts.CustomModule.ElemBuf ]); + compile_unboxed_const fi ^^ + system_call env "func" "externalize" + let export_start_stub env = assert (E.mode env = Flags.AncientMode); let empty_f = Func.of_body env [] [] (fun env1 -> + (* Set initial reply continuation *) + initial_reply env ^^ set_reply_cont env ^^ (* Set up memory *) G.i (Call (nr (E.built_in env1 "restore_mem"))) ^^ (* Collect garbage *) @@ -3186,7 +3202,8 @@ module Dfinity = struct let error_code_CANISTER_REJECT = 4l (* Api's CANISTER_REJECT *) let reject env arg_instrs = - SR.unit, + match E.mode env with + | Flags.ICMode -> get_api_nonce env ^^ arg_instrs ^^ G.i Drop ^^ (* TODO: @@ -3194,6 +3211,10 @@ module Dfinity = struct don't drop but extract payload, once reject complies with spec *) compile_unboxed_const error_code_CANISTER_REJECT ^^ system_call env "msg" "reject" + | Flags.AncientMode -> + trap_with env "Explicit reject on ancient system" + | _ -> + assert false let error_code env = SR.UnboxedWord32, @@ -4796,12 +4817,12 @@ module FuncDec = struct is at least one imported function (which we do not add to the table) *) let tmp_table_slot = 0l - (* The type of messages *) + (* The type of messages (no return: one-shot, callbacks) *) let message_ty env = E.func_type env (FuncType ([I32Type; I32Type], [])) (* Expects databuf and elembuf on the stack, in serialized form. *) - let call_funcref env get_ref = + let call_message_funcref env get_ref = compile_unboxed_const tmp_table_slot ^^ (* slot number *) get_ref ^^ (* the unboxed funcref *) Dfinity.system_call env "func" "internalize" ^^ @@ -4809,6 +4830,19 @@ module FuncDec = struct compile_unboxed_const tmp_table_slot ^^ G.i (CallIndirect (nr (message_ty env))) + (* The type of messages (with return: expect a callback, first argument (for binding) *) + let call_ty env = + E.func_type env (FuncType ([I32Type; I32Type; I32Type], [])) + + (* Expects reply callback, databuf and elembuf on the stack, in serialized form. *) + let call_await_funcref env get_ref = + compile_unboxed_const tmp_table_slot ^^ (* slot number *) + get_ref ^^ (* the unboxed funcref *) + Dfinity.system_call env "func" "internalize" ^^ + + compile_unboxed_const tmp_table_slot ^^ + G.i (CallIndirect (nr (call_ty env))) + let export_self_message env = Func.share_code1 env "export_self_message" ("name", I32Type) [I32Type] (fun env get_name -> Tagged.obj env Tagged.Reference [ @@ -4855,6 +4889,19 @@ module FuncDec = struct mk_body env ae2 )) + let message_cleanup env sort = match sort with + | Type.Shared Type.Write -> + (* Collect garbage *) + G.i (Call (nr (E.built_in env "collect"))) ^^ + (* Save memory *) + if E.mode env = Flags.AncientMode + then OrthogonalPersistence.save_mem env + else G.nop + | Type.Shared Type.Query -> + (* Don't collect or persist *) + G.i Nop + | _ -> assert false + (* Similar, but for shared functions aka messages. Differences are: - The closure is actually an index into the closure table - The arguments need to be deserialized. @@ -4863,51 +4910,75 @@ module FuncDec = struct - Do GC at the end - Fake orthogonal persistence *) - let compile_message outer_env outer_ae sort restore_env args mk_body ret_tys at = + let compile_message outer_env outer_ae sort control restore_env args mk_body ret_tys at = assert (E.mode outer_env = Flags.AncientMode); assert (List.length ret_tys = 0); let ae0 = VarEnv.mk_fun_ae outer_ae in - Func.of_body outer_env ["clos", I32Type; "databuf", I32Type; "elembuf", I32Type] [] (fun env -> G.with_region at ( - let get_databuf = G.i (LocalGet (nr 1l)) in - let get_elembuf = G.i (LocalGet (nr 2l)) in + match control with + | Type.Returns -> + Func.of_body outer_env ["clos", I32Type; "databuf", I32Type; "elembuf", I32Type] [] (fun env -> G.with_region at ( + let get_databuf = G.i (LocalGet (nr 1l)) in + let get_elembuf = G.i (LocalGet (nr 2l)) in - (* Restore memory *) - OrthogonalPersistence.restore_mem env ^^ + (* Restore memory *) + OrthogonalPersistence.restore_mem env ^^ - (* Look up closure *) - let (set_closure, get_closure) = new_local env "closure" in - G.i (LocalGet (nr 0l)) ^^ - ClosureTable.recall_closure env ^^ - set_closure ^^ + (* Look up closure *) + let (set_closure, get_closure) = new_local env "closure" in + G.i (LocalGet (nr 0l)) ^^ + ClosureTable.recall_closure env ^^ + set_closure ^^ - let (ae1, closure_code) = restore_env env ae0 get_closure in + let (ae1, closure_code) = restore_env env ae0 get_closure in - (* Deserialize argument and add params to the environment *) - let arg_names = List.map (fun a -> a.it) args in - let arg_tys = List.map (fun a -> a.note) args in - let (ae2, setters) = VarEnv.add_argument_locals env ae1 arg_names in - get_databuf ^^ get_elembuf ^^ - Serialization.deserialize env arg_tys ^^ - G.concat (List.rev setters) ^^ + (* Deserialize argument and add params to the environment *) + let arg_names = List.map (fun a -> a.it) args in + let arg_tys = List.map (fun a -> a.note) args in + let (ae2, setters) = VarEnv.add_argument_locals env ae1 arg_names in + get_databuf ^^ get_elembuf ^^ + Serialization.deserialize env arg_tys ^^ + G.concat (List.rev setters) ^^ - closure_code ^^ - mk_body env ae2 ^^ + closure_code ^^ + mk_body env ae2 ^^ + message_cleanup env sort + )) + | Type.Promises _ -> + Func.of_body outer_env ["clos", I32Type; "reply", I32Type; "databuf", I32Type; "elembuf", I32Type] [] (fun env -> G.with_region at ( + let get_reply = G.i (LocalGet (nr 1l)) in + let get_databuf = G.i (LocalGet (nr 2l)) in + let get_elembuf = G.i (LocalGet (nr 3l)) in - match sort with - | Type.Shared Type.Write -> - (* Collect garbage *) - G.i (Call (nr (E.built_in env "collect"))) ^^ - (* Save memory *) - OrthogonalPersistence.save_mem env - | Type.Shared Type.Query -> - (* Don't collect or persist *) - G.i Nop - | _ -> assert false - )) + (* Restore memory *) + OrthogonalPersistence.restore_mem env ^^ - let compile_static_message outer_env outer_ae sort args mk_body ret_tys at : E.func_with_names = - match E.mode outer_env with - | Flags.AncientMode -> + (* Story reply contiuation *) + get_reply ^^ Dfinity.set_reply_cont env ^^ + + (* Look up closure *) + let (set_closure, get_closure) = new_local env "closure" in + G.i (LocalGet (nr 0l)) ^^ + ClosureTable.recall_closure env ^^ + set_closure ^^ + + let (ae1, closure_code) = restore_env env ae0 get_closure in + + (* Deserialize argument and add params to the environment *) + let arg_names = List.map (fun a -> a.it) args in + let arg_tys = List.map (fun a -> a.note) args in + let (ae2, setters) = VarEnv.add_argument_locals env ae1 arg_names in + get_databuf ^^ get_elembuf ^^ + Serialization.deserialize env arg_tys ^^ + G.concat (List.rev setters) ^^ + + closure_code ^^ + mk_body env ae2 ^^ + message_cleanup env sort + )) + + let compile_static_message outer_env outer_ae sort control args mk_body ret_tys at : E.func_with_names = + match E.mode outer_env, control with + | Flags.AncientMode, Type.Returns -> (* no callback *) assert (List.length ret_tys = 0); let ae0 = VarEnv.mk_fun_ae outer_ae in Func.of_body outer_env ["databuf", I32Type; "elembuf", I32Type] [] (fun env -> G.with_region at ( @@ -4926,19 +4997,34 @@ module FuncDec = struct G.concat (List.rev setters) ^^ mk_body env ae1 ^^ + message_cleanup env sort + )) + | Flags.AncientMode, Type.Promises _ -> (* with callback *) + assert (List.length ret_tys = 0); + let ae0 = VarEnv.mk_fun_ae outer_ae in + Func.of_body outer_env ["reply", I32Type; "databuf", I32Type; "elembuf", I32Type] [] (fun env -> G.with_region at ( + let get_reply = G.i (LocalGet (nr 0l)) in + let get_databuf = G.i (LocalGet (nr 1l)) in + let get_elembuf = G.i (LocalGet (nr 2l)) in + + (* Set up memory *) + OrthogonalPersistence.restore_mem env ^^ + + (* Story reply contiuation *) + get_reply ^^ Dfinity.set_reply_cont env ^^ + + (* Deserialize argument and add params to the environment *) + let arg_names = List.map (fun a -> a.it) args in + let arg_tys = List.map (fun a -> a.note) args in + let (ae1, setters) = VarEnv.add_argument_locals env ae0 arg_names in + get_databuf ^^ get_elembuf ^^ + Serialization.deserialize env arg_tys ^^ + G.concat (List.rev setters) ^^ - match sort with - | Type.Shared Type.Write -> - (* Collect garbage *) - G.i (Call (nr (E.built_in env "collect"))) ^^ - (* Save memory *) - OrthogonalPersistence.save_mem env - | Type.Shared Type.Query -> - (* Don't collect or persist *) - G.i Nop - | _ -> assert false + mk_body env ae1 ^^ + message_cleanup env sort )) - | Flags.ICMode -> + | Flags.ICMode, _ -> let ae0 = VarEnv.mk_fun_ae outer_ae in Func.of_body outer_env ["api_nonce", I64Type] [] (fun env -> G.with_region at ( G.i (LocalGet (nr 0l)) ^^ Dfinity.set_api_nonce env ^^ @@ -4950,41 +5036,37 @@ module FuncDec = struct Serialization.deserialize env arg_tys ^^ G.concat (List.rev setters) ^^ mk_body env ae1 ^^ - match sort with - | Type.Shared Type.Write -> - (* Collect garbage *) - G.i (Call (nr (E.built_in env "collect"))) - | Type.Shared Type.Query -> - (* Don't collect *) - G.i Nop - | _ -> assert false + message_cleanup env sort )) - | Flags.WasmMode -> assert false + | Flags.WasmMode, _ -> assert false - let declare_dfinity_type env has_closure fi = + let declare_dfinity_type env has_closure has_reply fi = if E.mode env = Flags.AncientMode then E.add_dfinity_type env (fi, (if has_closure then [ Wasm_exts.CustomModule.I32 ] else []) @ + (if has_reply then [ Wasm_exts.CustomModule.FuncRef ] else []) @ [ Wasm_exts.CustomModule.DataBuf; Wasm_exts.CustomModule.ElemBuf ] ) (* Compile a closed function declaration (captures no local variables) *) - let closed pre_env sort name args mk_body ret_tys at = + let closed pre_env sort control name args mk_body ret_tys at = let (fi, fill) = E.reserve_fun pre_env name in if Type.is_shared_sort sort then begin - declare_dfinity_type pre_env false fi ; + declare_dfinity_type pre_env false (control <> Type.Returns) fi ; ( SR.StaticMessage fi, fun env ae -> - fill (compile_static_message env ae sort args mk_body ret_tys at) + fill (compile_static_message env ae sort control args mk_body ret_tys at) ) - end else + end else begin + assert (control = Type.Returns); ( SR.StaticFun fi, fun env ae -> let restore_no_env _env ae _ = (ae, G.nop) in fill (compile_local_function env ae restore_no_env args mk_body ret_tys at) ) + end (* Compile a closure declaration (captures local variables) *) - let closure env ae sort name captured args mk_body ret_tys at = + let closure env ae sort control name captured args mk_body ret_tys at = let is_local = sort = Type.Local in let (set_clos, get_clos) = new_local env (name ^ "_clos") in @@ -5016,11 +5098,11 @@ module FuncDec = struct let f = if is_local then compile_local_function env ae restore_env args mk_body ret_tys at - else compile_message env ae sort restore_env args mk_body ret_tys at in + else compile_message env ae sort control restore_env args mk_body ret_tys at in let fi = E.add_fun env name f in - if not is_local then declare_dfinity_type env true fi; + if not is_local then declare_dfinity_type env true (control <> Type.Returns) fi; let code = (* Allocate a heap object for the closure *) @@ -5060,15 +5142,15 @@ module FuncDec = struct ClosureTable.remember_closure env ^^ Dfinity.system_call env "func" "bind_i32" - let lit env ae how name sort free_vars args mk_body ret_tys at = + let lit env ae how name sort control free_vars args mk_body ret_tys at = let captured = List.filter (VarEnv.needs_capture ae) free_vars in if captured = [] then - let (st, fill) = closed env sort name args mk_body ret_tys at in + let (st, fill) = closed env sort control name args mk_body ret_tys at in fill env ae; (SR.StaticThing st, G.nop) - else closure env ae sort name captured args mk_body ret_tys at + else closure env ae sort control name captured args mk_body ret_tys at end (* FuncDec *) @@ -6276,26 +6358,56 @@ and compile_exp (env : E.t) ae exp = Error.compile_make_error (compile_exp_vanilla env ae e1) (compile_exp_vanilla env ae e2) | ICReplyPrim ts, [e] -> - assert (E.mode env = Flags.ICMode); - SR.unit, - compile_exp_as env ae SR.Vanilla e ^^ - (* TODO: We can try to avoid the boxing and pass the arguments to - serialize individually *) - Serialization.serialize env ts + SR.unit, begin match E.mode env with + | Flags.ICMode -> + compile_exp_as env ae SR.Vanilla e ^^ + (* TODO: We can try to avoid the boxing and pass the arguments to + serialize individually *) + Serialization.serialize env ts + | Flags.AncientMode -> + let (set_funcref, get_funcref) = new_local env "funcref" in + Dfinity.get_reply_cont env ^^ + set_funcref ^^ + compile_exp_as env ae SR.Vanilla e ^^ + (* TODO: We can try to avoid the boxing and pass the arguments to + serialize individually *) + Serialization.serialize env ts ^^ + FuncDec.call_message_funcref env get_funcref + | _ -> assert false + end | ICRejectPrim, [e] -> - assert (E.mode env = Flags.ICMode); - Dfinity.reject env (compile_exp_vanilla env ae e) + SR.unit, Dfinity.reject env (compile_exp_vanilla env ae e) | ICErrorCodePrim, [] -> assert (E.mode env = Flags.ICMode); Dfinity.error_code env | ICCallPrim, [f;e;k;r] -> - assert (E.mode env = Flags.ICMode); - SR.Unreachable, - todo_trap env "compile_exp" (Arrange_ir.exp exp) + SR.unit, begin match E.mode env with + | Flags.ICMode -> + todo_trap env "compile_exp" (Arrange_ir.exp exp) + | Flags.AncientMode -> + let (set_funcref, get_funcref) = new_local env "funcref" in + let (set_arg, get_arg) = new_local env "arg" in + let (set_k, get_k) = new_local env "k" in + let fun_sr, code1 = compile_exp env ae f in + code1 ^^ StackRep.adjust env fun_sr SR.UnboxedReference ^^ + set_funcref ^^ + compile_exp_as env ae SR.Vanilla e ^^ set_arg ^^ + compile_exp_as env ae SR.UnboxedReference k ^^ set_k ^^ + (* We drop the reject continuation on the ancient platform, but still + need to evaluate it *) + let (r_sr, code_r) = compile_exp env ae r in + code_r ^^ StackRep.drop env r_sr ^^ + + get_k ^^ Dfinity.get_reply_cont env ^^ Dfinity.system_call env "func" "bind_ref" ^^ + let _, _, _, ts, _ = Type.as_func f.note.note_typ in + get_arg ^^ Serialization.serialize env ts ^^ + FuncDec.call_await_funcref env get_funcref + | _ -> assert false + end (* Unknown prim *) | _ -> SR.Unreachable, todo_trap env "compile_exp" (Arrange_ir.exp exp) @@ -6373,7 +6485,7 @@ and compile_exp (env : E.t) ae exp = | ArrayE (m, t, es) -> SR.Vanilla, Arr.lit env (List.map (compile_exp_vanilla env ae) es) | CallE (e1, _, e2) -> - let sort, _, _, arg_tys, ret_tys = Type.as_func e1.note.note_typ in + let sort, control, _, arg_tys, ret_tys = Type.as_func e1.note.note_typ in let n_args = List.length arg_tys in let n_res = List.length ret_tys in @@ -6395,6 +6507,8 @@ and compile_exp (env : E.t) ae exp = get_clos ^^ Closure.call_closure env n_args n_res | _, Type.Shared _ -> + (* Non-one-shot functions have been rewritten in async.ml *) + assert (control = Type.Returns); let (set_funcref, get_funcref) = new_local env "funcref" in code1 ^^ StackRep.adjust env fun_sr SR.UnboxedReference ^^ set_funcref ^^ @@ -6403,7 +6517,7 @@ and compile_exp (env : E.t) ae exp = serialize individually *) let _, _, _, ts, _ = Type.as_func e1.note.note_typ in Serialization.serialize env ts ^^ - FuncDec.call_funcref env get_funcref + FuncDec.call_message_funcref env get_funcref end | SwitchE (e, cs) -> SR.Vanilla, @@ -6433,11 +6547,11 @@ and compile_exp (env : E.t) ae exp = SR.unit, compile_exp_vanilla env ae e ^^ Var.set_val env ae name - | FuncE (x, sort, _control, typ_binds, args, ret_tys, e) -> + | FuncE (x, sort, control, typ_binds, args, ret_tys, e) -> let captured = Freevars.captured exp in let n_res = List.length ret_tys in let mk_body env1 ae1 = compile_exp_as env1 ae1 (StackRep.of_arity n_res) e in - FuncDec.lit env ae typ_binds x sort captured args mk_body ret_tys exp.at + FuncDec.lit env ae typ_binds x sort control captured args mk_body ret_tys exp.at | ActorE (i, ds, fs, _) -> SR.UnboxedReference, let captured = Freevars.exp exp in @@ -6763,14 +6877,14 @@ and compile_prog env ae (ds, e) = (ae', code1 ^^ code2) and compile_static_exp env pre_ae how exp = match exp.it with - | FuncE (name, sort, _control, typ_binds, args, ret_tys, e) -> + | FuncE (name, sort, control, typ_binds, args, ret_tys, e) -> let mk_body env ae = assert begin (* Is this really closed? *) List.for_all (fun v -> VarEnv.NameEnv.mem v ae.VarEnv.vars) (Freevars.M.keys (Freevars.exp e)) end; compile_exp_as env ae (StackRep.of_arity (List.length ret_tys)) e in - FuncDec.closed env sort name args mk_body ret_tys exp.at + FuncDec.closed env sort control name args mk_body ret_tys exp.at | _ -> assert false and compile_prelude env ae = @@ -6843,7 +6957,12 @@ and export_actor_field env ae (f : Ir.field) = | _ -> assert false in (* There should be no code associated with this *) assert (G.is_nop code); - FuncDec.declare_dfinity_type env false fi; + + let is_await = match Type.normalize f.note with + | Type.Func(_,Type.Promises _,_,_,_) -> true + | _ -> false in + + FuncDec.declare_dfinity_type env false is_await fi; E.add_export env (nr { name = Wasm.Utf8.decode (match E.mode env with | Flags.AncientMode -> f.it.name diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index ebfdf3f5ca7..050200626b1 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -164,6 +164,8 @@ let rec check_typ env typ : unit = error env no_region "promising function of arity %i has async result type\n %s\n of mismatched arity %i" p (T.string_of_typ_expand (T.seq ts2)) a + | [] -> + check env no_region (not (env.flavor.Ir.has_async_typ)) "promising function with unit result pre-async-pass" | _ -> error env no_region "promising function with non-async result type\n %s" (T.string_of_typ_expand (T.seq ts2)) @@ -380,18 +382,18 @@ let rec check_exp env (exp:Ir.exp) : unit = typ k <: T.Func (T.Local, T.Returns, [], t_rets, []); typ r <: T.Func (T.Local, T.Returns, [], [T.catch], []); *) - | T.Func (sort, T.Returns, [], arg_tys, []) -> + | T.Func (sort, T.Promises _, [], arg_tys, []) -> check_exp env exp2; let t_arg = T.seq arg_tys in typ exp2 <: t_arg; (match (T.promote (typ k)) with - | T.Func (T.Shared _, T.Returns, [], t_rets, []) -> + | T.Func (T.Shared T.Write, T.Promises 0, [], t_rets, []) -> check_concrete env exp.at (T.seq t_rets) | T.Non -> () (* dead code, not much to check here *) - | _ -> + | t -> error env k.at "expected continuation type, but expression produces type\n %s" - (T.string_of_typ_expand t1)); - typ r <: T.Func (T.Shared T.Write, T.Returns, [], [T.text], []); + (T.string_of_typ_expand t)); + typ r <: T.Func (T.Shared T.Write, T.Promises 0, [], [T.text], []); | T.Non -> () (* dead code, not much to check here *) | _ -> error env exp1.at "expected function type, but expression produces type\n %s" diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index 19ec22fa980..6661790dd24 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -475,9 +475,9 @@ let (-->*) xs exp = nary_funcE "$lambda" fun_ty xs exp -(* n-ary shared lambda *) +(* n-ary shared lambda, used for callbacks *) let (-@>*) xs exp = - let fun_ty = T.Func (T.Shared T.Write, T.Returns, [], List.map typ xs, T.as_seq (typ exp)) in + let fun_ty = T.Func (T.Shared T.Write, T.Promises 0, [], List.map typ xs, T.as_seq (typ exp)) in nary_funcE "$lambda" fun_ty xs exp diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index 55ae7991d11..d8ead1cbdf7 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -45,41 +45,17 @@ module Transform(Platform : sig val platform : platform end) = struct let con_renaming = ref ConRenaming.empty - let add_reply_parameter, add_reject_parameter = - match platform with - | V1 -> (true, false) - | V2 -> (false, false) - - (* Helper for selective code generation based on predicated lazy expressions *) - let rec select bls = - match bls with - | [] -> [] - | (true, l)::bls' -> - (Lazy.force l)::select bls' - | (false, _)::bls' -> - select bls' - - (* Explicit invocation of reply, reject and call System API functions; implemented (as far as possible) for V1; TBC for V2 *) - let sys_replyE ts v = - match platform with - | V1 -> assert false (* never required in V1, `reply` is by calling continuation*) - | V2 -> ic_replyE ts v + let sys_replyE ts v = ic_replyE ts v - let sys_rejectE e = - match platform with - | V1 -> assertE (boolE false) (* used in V1 to cause traps on non-local throws *) - | V2 -> ic_rejectE e + let sys_rejectE e = ic_rejectE e let sys_callE v1 typs vs reply reject = - match platform with - | V1 -> callE v1 typs (seqE (vs @ [reply])) - | V2 -> - assert (typs = []); - ic_callE v1 (seqE vs) reply reject + assert (typs = []); + ic_callE v1 (seqE vs) reply reject let sys_error_codeE () = match platform with @@ -115,10 +91,6 @@ module Transform(Platform : sig val platform : platform end) = struct let flatten arity = if arity = 1 then unary else nary - let replyT as_seq typ = T.Func(T.Shared T.Write, T.Returns, [], as_seq typ, []) - - let rejectT = T.Func(T.Shared T.Write, T.Returns, [], [T.text], []) - let fulfillT as_seq typ = T.Func(T.Local, T.Returns, [], as_seq typ, []) let failT = T.Func(T.Local, T.Returns, [], [T.catch], []) @@ -199,8 +171,6 @@ module Transform(Platform : sig val platform : platform end) = struct | T.Func (T.Shared _,T.Promises _,_,_,[T.Async _]) -> true | _ -> false - let extendTup ts ts' = ts @ ts' - (* Given sequence type ts, bind e of type (seq ts) to a sequence of expressions supplied to decs d_of_es, preserving effects of e when the sequence type is empty. @@ -237,12 +207,7 @@ module Transform(Platform : sig val platform : platform end) = struct assert (c = T.Returns); Func(s, c, List.map t_bind tbs, List.map t_typ t1, List.map t_typ t2) | [Async t2], T.Promises p -> - Func (s, T.Returns, List.map t_bind tbs, - extendTup (List.map t_typ t1) - (select - [ add_reply_parameter, lazy (replyT (flatten p) (t_typ t2)); - add_reject_parameter, lazy rejectT ]), - []) + Func (s, T.Promises p, List.map t_bind tbs, List.map t_typ t1, []) | _ -> assert false end | T.Local -> @@ -413,13 +378,7 @@ module Transform(Platform : sig val platform : platform end) = struct | [T.Async res_typ], Promises p -> let res_typ = t_typ res_typ in let res_typs = flatten p res_typ in - let reply_typ = replyT (flatten p) res_typ in - let reply = fresh_var "reply" reply_typ in - let reject = fresh_var "reject" rejectT in - let args' = t_args args @ - (select [ add_reply_parameter, lazy (arg_of_exp reply); - add_reject_parameter, lazy (arg_of_exp reject)]) - in + let args' = t_args args in let typbinds' = t_typ_binds typbinds in let exp' = match exp.it with @@ -432,22 +391,13 @@ module Transform(Platform : sig val platform : platform end) = struct (t_typ (T.seq ts1),t_typ contT) | t -> assert false in let v = fresh_var "v" t1 in - let k = if add_reply_parameter then - (* wrap shared reply function in local function *) - (v --> (reply -*- v)) - else - (v --> (sys_replyE res_typs v)) in + let k = v --> (sys_replyE res_typs v) in let e = fresh_var "e" T.catch in - let r = if add_reject_parameter then - (* wrap shared reject function in local function *) - ([e] -->* (reject -*- (errorMessageE e))) - else - ([e] -->* (sys_rejectE (errorMessageE e))) - in + let r = [e] -->* (sys_rejectE (errorMessageE e)) in (t_exp cps) -*- tupE [k;r] | _ -> assert false in - FuncE (x, T.Shared s', Returns, typbinds', args', [], exp') + FuncE (x, T.Shared s', Promises p, typbinds', args', [], exp') | _ -> assert false end end diff --git a/test/run.sh b/test/run.sh index 9cd4c6eff14..ee422abae74 100755 --- a/test/run.sh +++ b/test/run.sh @@ -163,6 +163,7 @@ do normalize $out/$base.run diff_files="$diff_files $base.run" + if false; then # Interpret IR without lowering $ECHO -n " [run-ir]" $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS -r -iR -no-async -no-await $base.mo > $out/$base.run-ir 2>&1 @@ -182,6 +183,7 @@ do # Diff interpretations without/with lowering diff -u -N --label "$base.run" $out/$base.run --label "$base.run-low" $out/$base.run-low > $out/$base.diff-low diff_files="$diff_files $base.diff-low" + fi fi From 972b4d4d6048f4618a8d7ba51203511547c3fc52 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 30 Oct 2019 12:32:47 +0100 Subject: [PATCH 0490/1176] Implement `async {}` via ICCallE --- src/ir_passes/async.ml | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index d8ead1cbdf7..f51efef0c25 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -289,25 +289,26 @@ module Transform(Platform : sig val platform : platform end) = struct | PrimE (OtherPrim "@await", [a;kr]) -> ((t_exp a) -*- (t_exp kr)).it | PrimE (OtherPrim "@async", [exp2]) -> - let t1, contT = match typ exp2 with + let t1, ts, contT = match typ exp2 with | Func(_,_, [], [Func(_, _, [], ts1, []) as contT; _], []) -> - (t_typ (T.seq ts1),t_typ contT) + (t_typ (T.seq ts1), ts1, t_typ contT) | t -> assert false in - let k = fresh_var "k" contT in - let v1 = fresh_var "v" t1 in - let r = fresh_var "r" err_contT in - let e = fresh_var "e" T.catch in - let post = fresh_var "post" (T.Func(T.Shared T.Write, T.Returns, [], [], [])) in + let post = fresh_var "post" (T.Func(T.Shared T.Write, T.Promises 0, [], [], [])) in let u = fresh_var "u" T.unit in let ((nary_async, nary_reply, reject), def) = new_nary_async_reply 1 t1 in (blockE [letP (tupP [varP nary_async; varP nary_reply; varP reject]) def; - funcD k v1 (nary_reply -*- v1); - nary_funcD r [e] (reject -*- (errorMessageE e)); - funcD post u (t_exp exp2 -*- (tupE [k;r])); - expD (post -*- tupE[])] + funcD post u ( + let v = fresh_var "v" t1 in + let k = v --> (sys_replyE ts v) in + let e = fresh_var "e" T.catch in + let r = [e] -->* (sys_rejectE (errorMessageE e)) in + (t_exp exp2) -*- tupE [k;r]); + + expD (sys_callE post [] [] nary_reply reject); + ] nary_async ).it | CallE (exp1, typs, exp2) when isAwaitableFunc exp1 -> From ded8e49c79579be8a9e578c668f285b8b1ba2d18 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 30 Oct 2019 12:36:07 +0100 Subject: [PATCH 0491/1176] Update IR dump --- test/run-dfinity/ok/counter-class.wasm.stderr.ok | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/test/run-dfinity/ok/counter-class.wasm.stderr.ok b/test/run-dfinity/ok/counter-class.wasm.stderr.ok index 3b0a2a05f55..dd9b7209cd5 100644 --- a/test/run-dfinity/ok/counter-class.wasm.stderr.ok +++ b/test/run-dfinity/ok/counter-class.wasm.stderr.ok @@ -22,8 +22,7 @@ non-closed actor: (ActorE (FuncE read Shared - Returns - (params $reply/0) + Promises 1 () (CallE (FuncE @@ -41,7 +40,7 @@ non-closed actor: (ActorE Returns (params $v/0) () - (CallE (VarE $reply/0) (VarE $v/0)) + (PrimE (ICReplyPrim Int) (VarE $v/0)) ) (FuncE $lambda @@ -49,7 +48,7 @@ non-closed actor: (ActorE Returns (params $e/0) () - (AssertE (LitE (BoolLit false))) + (PrimE ICRejectPrim (PrimE errorMessage (VarE $e/0))) ) ) ) @@ -57,5 +56,5 @@ non-closed actor: (ActorE ) (read read) (dec dec) - actor {dec : shared () -> (); read : shared (shared Int -> ()) -> ()} + actor {dec : shared () -> (); read : shared () -> ()} ) From 9d8d2c6088903273aa8c025a54296c292da3fdc2 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 30 Oct 2019 14:16:27 +0100 Subject: [PATCH 0492/1176] tests/run-dfinity work now (more dummy reply continuations) --- src/codegen/compile.ml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index a402d9a09b2..9832b265ad3 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -4923,6 +4923,9 @@ module FuncDec = struct (* Restore memory *) OrthogonalPersistence.restore_mem env ^^ + (* Set initial dummy continuation *) + Dfinity.initial_reply env ^^ Dfinity.set_reply_cont env ^^ + (* Look up closure *) let (set_closure, get_closure) = new_local env "closure" in G.i (LocalGet (nr 0l)) ^^ @@ -4988,6 +4991,9 @@ module FuncDec = struct (* Set up memory *) OrthogonalPersistence.restore_mem env ^^ + (* Set initial dummy continuation *) + Dfinity.initial_reply env ^^ Dfinity.set_reply_cont env ^^ + (* Deserialize argument and add params to the environment *) let arg_names = List.map (fun a -> a.it) args in let arg_tys = List.map (fun a -> a.note) args in From b57aaf85413f709a549430f56a3472a1fb40000d Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 30 Oct 2019 14:35:01 +0100 Subject: [PATCH 0493/1176] =?UTF-8?q?Slightly=20better=20handling=20of=20t?= =?UTF-8?q?he=20=E2=80=9Cglobal=20reply=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/codegen/compile.ml | 38 ++++++++++++++++-------- test/run-drun/ok/ic-calls.wasm.stderr.ok | 2 +- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 9832b265ad3..3573dd930fc 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -3040,8 +3040,7 @@ module Dfinity = struct let register_globals env = (* current api_nonce *) - E.add_global64 env "api_nonce" Mutable 0L; - E.add_global32 env "reply_cont" Mutable 0l + E.add_global64 env "api_nonce" Mutable 0L let system_imports env = match E.mode env with @@ -3137,20 +3136,29 @@ module Dfinity = struct edesc = nr (TableExport (nr 0l)) }) - let initial_reply env = - assert (E.mode env = Flags.AncientMode); - let f = Func.of_body env ["databuf", I32Type; "elembuf", I32Type] [] - (fun env -> trap_with env "initial_reply reached") in - let fi = E.add_fun env "empty_reply" f in - E.add_dfinity_type env (fi, [ Wasm_exts.CustomModule.DataBuf; Wasm_exts.CustomModule.ElemBuf ]); - compile_unboxed_const fi ^^ - system_call env "func" "externalize" + let register_reply env = + if E.mode env = Flags.AncientMode + then begin + (* in-canister emulation of the call context, in particular the “current reply” *) + Func.define_built_in env "empty_reply" ["databuf", I32Type; "elembuf", I32Type] [] + (fun env -> trap_with env "dummy_reply called"); + let fi = E.built_in env "empty_reply" in + E.add_dfinity_type env (fi, [ Wasm_exts.CustomModule.DataBuf; Wasm_exts.CustomModule.ElemBuf ]); + E.add_global32 env "reply_cont" Mutable 0l + end + + let set_dummy_reply env = + if E.mode env = Flags.AncientMode then + compile_unboxed_const (E.built_in env "empty_reply") ^^ + system_call env "func" "externalize" ^^ + set_reply_cont env + else G.nop let export_start_stub env = assert (E.mode env = Flags.AncientMode); let empty_f = Func.of_body env [] [] (fun env1 -> (* Set initial reply continuation *) - initial_reply env ^^ set_reply_cont env ^^ + set_dummy_reply env ^^ (* Set up memory *) G.i (Call (nr (E.built_in env1 "restore_mem"))) ^^ (* Collect garbage *) @@ -4924,7 +4932,7 @@ module FuncDec = struct OrthogonalPersistence.restore_mem env ^^ (* Set initial dummy continuation *) - Dfinity.initial_reply env ^^ Dfinity.set_reply_cont env ^^ + Dfinity.set_dummy_reply env ^^ (* Look up closure *) let (set_closure, get_closure) = new_local env "closure" in @@ -4992,7 +5000,7 @@ module FuncDec = struct OrthogonalPersistence.restore_mem env ^^ (* Set initial dummy continuation *) - Dfinity.initial_reply env ^^ Dfinity.set_reply_cont env ^^ + Dfinity.set_dummy_reply env ^^ (* Deserialize argument and add params to the environment *) let arg_names = List.map (fun a -> a.it) args in @@ -7004,6 +7012,8 @@ and actor_lit outer_env this ds fs at = RTS.system_imports mod_env; RTS.system_exports mod_env; + Dfinity.register_reply mod_env; + let start_fun = Func.of_body mod_env [] [] (fun env -> G.with_region at @@ let ae0 = VarEnv.empty_ae in @@ -7140,6 +7150,8 @@ let compile mode module_name rts (prelude : Ir.prog) (progs : Ir.prog list) : Wa RTS.system_imports env; RTS.system_exports env; + Dfinity.register_reply env; + let start_fun = compile_start_func env (prelude :: progs) in let start_fi = E.add_fun env "start" start_fun in let start_fi_o = match E.mode env with diff --git a/test/run-drun/ok/ic-calls.wasm.stderr.ok b/test/run-drun/ok/ic-calls.wasm.stderr.ok index c3da9321d4b..3c4077bf861 100644 --- a/test/run-drun/ok/ic-calls.wasm.stderr.ok +++ b/test/run-drun/ok/ic-calls.wasm.stderr.ok @@ -1 +1 @@ -Fatal error: exception "Assert_failure codegen/compile.ml:4867:4" +Fatal error: exception "Assert_failure codegen/compile.ml:4922:4" From 4015ec7496459eb07fc9c7b2185e5e92b9e3e130 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity <48968912+chenyan-dfinity@users.noreply.github.com> Date: Wed, 30 Oct 2019 13:26:05 -0700 Subject: [PATCH 0494/1176] Rename module prefix from as to mo (#807) * Rename module prefix from as to mo * retrigger ci --- src/pipeline/resolve_import.ml | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/pipeline/resolve_import.ml b/src/pipeline/resolve_import.ml index c6cb668798b..5fd5dde93eb 100644 --- a/src/pipeline/resolve_import.ml +++ b/src/pipeline/resolve_import.ml @@ -23,9 +23,10 @@ module M = Map.Make(String) which for now is just a filesystem path: e.g., - packages("std") = "/Users/home/username/.dfinity-sdk/src/as-stdlib/0.1.0/" + packages("std") = "/Users/home/username/.dfinity-sdk/src/mo-stdlib/0.1.0/" packages("foo") = "/Users/home/username/fooPackage/1.2.3/src" *) + type package_map = string M.t type env = { @@ -38,16 +39,16 @@ type env = { open Syntax open Source -(* match `f` against the URL pattern 'as://package-name/path', +(* match `f` against the URL pattern 'mo://package-name/path', optionally returning the package-name and path components as a pair of strings. e.g., - match_package_name "as:std/list" = Some("std", "list") - match_package_name "as:std/foo/bar" = Some("std", "foo/bar") - match_package_name "as:foo/bar" = Some("foo", "bar") + match_package_name "mo:std/list" = Some("std", "list") + match_package_name "mo:std/foo/bar" = Some("std", "foo/bar") + match_package_name "mo:foo/bar" = Some("foo", "bar") - match_package_name "as:" = None - match_package_name "as:std" = None + match_package_name "mo:" = None + match_package_name "mo:std" = None match_package_name "std/foo" = None match_package_name "std/foo/bar" = None @@ -72,10 +73,10 @@ let match_package_name (f: string) : (string * string) option = ) in match prefix with - | "as:" -> loop suffix "" + | "mo:" -> loop suffix "" | _ -> None -(* using env, resolve import strings of the form "as:package-name/mod1/mod2/item" +(* using env, resolve import strings of the form "mo:package-name/mod1/mod2/item" into the triple ("package-name", "package-url", "mod1/mod2/item") when the package name is defined. Does not validate the package url or path. *) From 4ed14a108b0df27407fd2f2f9c13f9c71051a1e1 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 31 Oct 2019 10:51:36 +0100 Subject: [PATCH 0495/1176] Make `large-array.mo` smaller (#809) Allocating a 1GB array was putting too much strain on CI, especially during interpretation. Let's do 50MB instead. --- test/run-drun/large-array.mo | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/run-drun/large-array.mo b/test/run-drun/large-array.mo index 21b4ac03b0b..9c78a314ce4 100644 --- a/test/run-drun/large-array.mo +++ b/test/run-drun/large-array.mo @@ -1,3 +1,6 @@ // Should allocate 1G -ignore(Array_init<()>(1024*1024*1024/4, ())); +// ignore(Array_init<()>(1024*1024*1024/4, ())); + +// Should allocate 50MB (easier on CI) +ignore(Array_init<()>(50*1024*1024/4, ())); From d86a7dc10f1b60275ef9fd749fd891a60be7f99f Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 31 Oct 2019 10:58:34 +0100 Subject: [PATCH 0496/1176] The T.Func refactoring: Getting rid of as_seq (#806) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * The T.Func refactoring: Getting rid of as_seq the goal of this PR is to get rid of `T.as_seq`, as almost any use of that is a code smell: From the type `(t1,t2)` we cannot tell any more whether this was meant to be a two-element sequence, or a one-element sequence with a first-class tuple inside. The core of the refactoring is to change the `T.Func` type to put the async’s return _sequence_ into the `ret_tys` field. I.e. ``` T.Func (Shared, Promises n, tbs, ts1, [Async (Tup ts2)]) where n = length ts2 ``` becomes ``` T.Func (Shared, Promises, tbs, ts1, ts2) ``` Note that there is much less redundancy in these types, much less invalid combinations are possible. A fair number of pattern matches on both `control` and the `return typ` now becomes a simple `match` on the `control`, and other things become easier. This is a good sign. The `T.codom c ts` function can be used to easily construct the codomain of the function (like `T.seq ts` for arguments); it adds `Tup` and `Async` as needed. The biggest wart is that the IR-check needs a different `T.codom` post the `async` translation pass. Maybe we can clean that up later. There is still a bit use of `T.as_seq` in `Ir_construct`; this might be ok, it might just “opportunistically unbox tuples in arguments in synthesized code”. And a use in `T.async`. Maybe one can get rid of it if `T.Async` itself becomes n-ary. But otherwise `T.as_seq` is gone. There is now a safer `T.seq_of_tup` used in the desugarer when there is guaranteed to be a `T.Tup` in the argument. * Update src/ir_passes/async.ml Co-Authored-By: Claudio Russo * Only Shared functions can be promising and the type inference code needs to take care of that. So `as_codomT` needs to adjust. * Small reformatting to trigger CI build --- src/ir_def/check_ir.ml | 49 ++++++-------- src/ir_def/construct.ml | 10 --- src/ir_def/construct.mli | 2 - src/ir_interpreter/interpret_ir.ml | 6 +- src/ir_passes/async.ml | 104 ++++++++++++++--------------- src/lowering/desugar.ml | 18 +++-- src/mo_def/syntax.ml | 5 -- src/mo_frontend/typing.ml | 85 ++++++++++++++--------- src/mo_idl/mo_to_idl.ml | 4 +- src/mo_interpreter/interpret.ml | 8 +-- src/mo_types/arrange_type.ml | 2 +- src/mo_types/type.ml | 32 +++++---- src/mo_types/type.mli | 6 +- src/mo_values/call_conv.ml | 4 +- test/fail/ok/abstract-msgs.tc.ok | 8 +-- test/run-drun/ok/idl-func.tc.ok | 4 +- 16 files changed, 176 insertions(+), 171 deletions(-) diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index fee306d94c5..e8ccac85c3d 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -154,30 +154,25 @@ let rec check_typ env typ : unit = let ts2 = List.map (T.open_ ts) ts2 in List.iter (check_typ env') ts1; List.iter (check_typ env') ts2; - (match control with - | T.Returns -> () - | T.Promises p -> begin - match ts2 with - | [T.Async t ] -> - let a = T.arity t in - if p <> 1 && a <> p then - error env no_region - "promising function of arity %i has async result type\n %s\n of mismatched arity %i" - p (T.string_of_typ_expand (T.seq ts2)) a - | _ -> - error env no_region "promising function with non-async result type\n %s" - (T.string_of_typ_expand (T.seq ts2)) - end); if T.is_shared_sort sort then begin List.iter (fun t -> check_shared env no_region t) ts1; - match ts2 with - | [] when not env.flavor.Ir.has_async_typ || sort = T.Shared T.Write -> () - | [T.Async t2] -> - check env' no_region (T.shared t2) - "message result is not sharable:\n %s" (T.string_of_typ_expand t2) - | _ -> error env no_region "shared function has non-async result type\n %s" - (T.string_of_typ_expand (T.seq ts2)) - end + match control with + | T.Returns -> + (* async translations changes result of one-shot function. + this can change once we preserve the return type of Promising functions + past async translation + *) + if env.flavor.Ir.has_async_typ then + check env' no_region (sort = T.Shared T.Write) + "one-shot query function pointless" + | T.Promises -> + check env' no_region (sort <> T.Local) + "promising function cannot be local:\n %s" (T.string_of_typ_expand (T.seq ts)); + check env' no_region (List.for_all T.shared ts) + "message result is not sharable:\n %s" (T.string_of_typ_expand (T.seq ts)) + end else + check env' no_region (control = T.Returns) + "promising function cannot be local:\n %s" (T.string_of_typ_expand typ); | T.Opt typ -> check_typ env typ | T.Async typ -> @@ -435,7 +430,7 @@ let rec check_exp env (exp:Ir.exp) : unit = check_inst_bounds env tbs insts exp.at; check_exp env exp2; let t_arg = T.open_ insts (T.seq arg_tys) in - let t_ret = T.open_ insts (T.seq ret_tys) in + let t_ret = T.open_ insts (T.codom control ret_tys) in if T.is_shared_sort sort then begin check_concrete env exp.at t_arg; check_concrete env exp.at t_ret; @@ -561,14 +556,14 @@ let rec check_exp env (exp:Ir.exp) : unit = let env' = adjoin_cons env ce in let ve = check_args env' args in List.iter (check_typ env') ret_tys; - check ((T.is_shared_sort sort && Type.is_async (T.seq ret_tys)) - ==> isAsyncE exp) + check ((T.is_shared_sort sort && control = T.Promises) ==> isAsyncE exp) "shared function with async type has non-async body"; if T.is_shared_sort sort then List.iter (check_concrete env exp.at) ret_tys; + let codom = T.codom control ret_tys in let env'' = - {env' with labs = T.Env.empty; rets = Some (T.seq ret_tys); async = false} in + {env' with labs = T.Env.empty; rets = Some codom; async = false} in check_exp (adjoin_vals env'' ve) exp; - check_sub env' exp.at (typ exp) (T.seq ret_tys); + check_sub env' exp.at (typ exp) codom; (* Now construct the function type and compare with the annotation *) let ts1 = List.map (fun a -> a.note) args in if T.is_shared_sort sort then List.iter (check_concrete env exp.at) ts1; diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index e6e564180bc..1ea5e7d99f8 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -73,11 +73,6 @@ let seqP ps = | [p] -> p | ps -> tupP ps -let as_seqP p = - match p.it with - | TupP ps -> ps - | _ -> [p] - (* Primitives *) let primE prim es = @@ -446,11 +441,6 @@ let seqE es = | [e] -> e | es -> tupE es -let as_seqE e = - match e.it with - | TupE es -> es - | _ -> [e] - (* Lambdas & continuations *) (* Lambda abstraction *) diff --git a/src/ir_def/construct.mli b/src/ir_def/construct.mli index da83b639391..f19b1a2d544 100644 --- a/src/ir_def/construct.mli +++ b/src/ir_def/construct.mli @@ -35,7 +35,6 @@ val varP : var -> pat val tupP : pat list -> pat val seqP : pat list -> pat -val as_seqP : pat -> pat list (* Expressions *) @@ -99,7 +98,6 @@ val fresh_err_cont : unit -> var (* Sequence expressions *) val seqE : exp list -> exp -val as_seqE : exp -> exp list (* Lambdas *) diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index 511ed4cd872..415adf7b543 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -200,8 +200,8 @@ let make_async_message env id v = let open CC in let call_conv, f = V.as_func v in match call_conv with - | {sort = T.Shared s; control = T.Promises p; n_res = 1; _} -> - Value.async_func s call_conv.n_args p (fun v k -> + | {sort = T.Shared s; control = T.Promises; _} -> + Value.async_func s call_conv.n_args call_conv.n_res (fun v k -> let async = make_async () in actor_msg env id f v (fun v_async -> get_async (V.as_async v_async) (set_async async) (reject_async async) @@ -216,7 +216,7 @@ let make_async_message env id v = let make_message env x cc v : V.value = match cc.CC.control with | T.Returns -> make_unit_message env x v - | T.Promises _ -> make_async_message env x v + | T.Promises-> make_async_message env x v let extended_prim env s typ at = diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index d2120536fd6..7bc3fcef9e3 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -113,9 +113,7 @@ module Transform(Platform : sig val platform : platform end) = struct let nary typ = T.as_seq typ - let flatten arity = if arity = 1 then unary else nary - - let replyT as_seq typ = T.Func(T.Shared T.Write, T.Returns, [], as_seq typ, []) + let replyT ts = T.Func(T.Shared T.Write, T.Returns, [], ts, []) let rejectT = T.Func(T.Shared T.Write, T.Returns, [], [T.text], []) @@ -147,18 +145,19 @@ module Transform(Platform : sig val platform : platform end) = struct let fail = fresh_var "fail" (typ (projE call_new_async 2)) in (async, fulfill, fail), call_new_async - let new_nary_async_reply p t1 = + let new_nary_async_reply ts1 = + (* The async implementation isn't n-ary *) + let t1 = T.seq ts1 in let (unary_async, unary_fulfill, fail), call_new_async = new_async t1 in let v' = fresh_var "v" t1 in - let ts1 = T.as_seq t1 in (* construct the n-ary async value, coercing the continuation, if necessary *) let nary_async = - let k' = fresh_var "k" (contT t1) in - let r' = fresh_var "r" err_contT in match ts1 with | [t] -> unary_async | ts -> + let k' = fresh_var "k" (contT t1) in + let r' = fresh_var "r" err_contT in let seq_of_v' = tupE (List.mapi (fun i _ -> projE v' i) ts) in [k';r'] -->* (unary_async -*- (tupE[([v'] -->* (k' -*- seq_of_v'));r'])) in @@ -196,7 +195,7 @@ module Transform(Platform : sig val platform : platform end) = struct let isAwaitableFunc exp = match typ exp with - | T.Func (T.Shared _,T.Promises _,_,_,[T.Async _]) -> true + | T.Func (T.Shared _,T.Promises,_,_,_) -> true | _ -> false let extendTup ts ts' = ts @ ts' @@ -232,18 +231,17 @@ module Transform(Platform : sig val platform : platform end) = struct match s with | T.Shared _ -> begin - match t2,c with - | [],_ -> - assert (c = T.Returns); + match c with + | T.Returns -> + assert (t2 = []); Func(s, c, List.map t_bind tbs, List.map t_typ t1, List.map t_typ t2) - | [Async t2], T.Promises p -> + | T.Promises -> Func (s, T.Returns, List.map t_bind tbs, extendTup (List.map t_typ t1) (select - [ add_reply_parameter, lazy (replyT (flatten p) (t_typ t2)); + [ add_reply_parameter, lazy (replyT (List.map t_typ t2)); add_reject_parameter, lazy rejectT ]), []) - | _ -> assert false end | T.Local -> Func (s, c, List.map t_bind tbs, List.map t_typ t1, List.map t_typ t2) @@ -324,38 +322,38 @@ module Transform(Platform : sig val platform : platform end) = struct | PrimE (OtherPrim "@await", [a;kr]) -> ((t_exp a) -*- (t_exp kr)).it | PrimE (OtherPrim "@async", [exp2]) -> - let t1, contT = match typ exp2 with + let ts1, contT = match typ exp2 with | Func(_,_, [], [Func(_, _, [], ts1, []) as contT; _], []) -> - (t_typ (T.seq ts1),t_typ contT) + (List.map t_typ ts1,t_typ contT) | t -> assert false in let k = fresh_var "k" contT in - let v1 = fresh_var "v" t1 in + let vs1 = fresh_vars "v" ts1 in let r = fresh_var "r" err_contT in let e = fresh_var "e" T.catch in let post = fresh_var "post" (T.Func(T.Shared T.Write, T.Returns, [], [], [])) in let u = fresh_var "u" T.unit in - let ((nary_async, nary_reply, reject), def) = new_nary_async_reply 1 t1 in + let ((nary_async, nary_reply, reject), def) = new_nary_async_reply ts1 in (blockE [letP (tupP [varP nary_async; varP nary_reply; varP reject]) def; - funcD k v1 (nary_reply -*- v1); + nary_funcD k vs1 (nary_reply -*- (seqE vs1)); nary_funcD r [e] (reject -*- (errorMessageE e)); funcD post u (t_exp exp2 -*- (tupE [k;r])); expD (post -*- tupE[])] nary_async ).it | CallE (exp1, typs, exp2) when isAwaitableFunc exp1 -> - let p, ts1,t2 = + let ts1,ts2 = match typ exp1 with - | T.Func (T.Shared _, T.Promises p,tbs,ts1,[T.Async t2]) -> - p, List.map t_typ ts1, t_typ t2 + | T.Func (T.Shared _, T.Promises,tbs,ts1,ts2) -> + List.map t_typ ts1, List.map t_typ ts2 | _ -> assert(false) in let exp1' = t_exp exp1 in let exp2' = t_exp exp2 in let typs = List.map t_typ typs in - let ((nary_async, nary_reply, reject), def) = new_nary_async_reply p t2 in + let ((nary_async, nary_reply, reject), def) = new_nary_async_reply ts2 in let _ = letEta in (blockE ( letP (tupP [varP nary_async; varP nary_reply; varP reject]) def :: letEta exp1' (fun v1 -> @@ -407,13 +405,12 @@ module Transform(Platform : sig val platform : platform end) = struct FuncE (x, s, c, t_typ_binds typbinds, t_args args, List.map t_typ ret_tys, t_exp exp) | T.Shared s' -> begin - match ret_tys, c with - | [], _ -> + match c with + | Returns -> FuncE (x, s, c, t_typ_binds typbinds, t_args args, List.map t_typ ret_tys, t_exp exp) - | [T.Async res_typ], Promises p -> - let res_typ = t_typ res_typ in - let res_typs = flatten p res_typ in - let reply_typ = replyT (flatten p) res_typ in + | Promises -> + let ret_tys = List.map t_typ ret_tys in + let reply_typ = replyT ret_tys in let reply = fresh_var "reply" reply_typ in let reject = fresh_var "reject" rejectT in let args' = t_args args @ @@ -421,34 +418,31 @@ module Transform(Platform : sig val platform : platform end) = struct add_reject_parameter, lazy (arg_of_exp reject)]) in let typbinds' = t_typ_binds typbinds in - let exp' = - match exp.it with - | PrimE (OtherPrim "@async", [cps]) -> - let t1, contT = match typ cps with - | Func(_,_, - [], - [Func(_, _, [], ts1, []) as contT; _], - []) -> - (t_typ (T.seq ts1),t_typ contT) - | t -> assert false in - let v = fresh_var "v" t1 in - let k = if add_reply_parameter then - (* wrap shared reply function in local function *) - (v --> (reply -*- v)) - else - (v --> (sys_replyE res_typs v)) in - let e = fresh_var "e" T.catch in - let r = if add_reject_parameter then - (* wrap shared reject function in local function *) - ([e] -->* (reject -*- (errorMessageE e))) - else - ([e] -->* (sys_rejectE (errorMessageE e))) - in - (t_exp cps) -*- tupE [k;r] - | _ -> assert false + let cps = match exp.it with + | PrimE (OtherPrim "@async", [cps]) -> cps + | _ -> assert false in + let t1, contT = match typ cps with + | Func(_,_, + [], + [Func(_, _, [], ts1, []) as contT; _], + []) -> + (t_typ (T.seq ts1),t_typ contT) + | t -> assert false in + let v = fresh_var "v" t1 in + let k = if add_reply_parameter then + (* wrap shared reply function in local function *) + (v --> (reply -*- v)) + else + (v --> (sys_replyE ret_tys v)) in + let e = fresh_var "e" T.catch in + let r = if add_reject_parameter then + (* wrap shared reject function in local function *) + ([e] -->* (reject -*- (errorMessageE e))) + else + ([e] -->* (sys_rejectE (errorMessageE e))) in + let exp' = (t_exp cps) -*- tupE [k;r] in FuncE (x, T.Shared s', Returns, typbinds', args', [], exp') - | _ -> assert false end end | ActorE (id, ds, fs, typ) -> diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 0d69cb147fc..e531167a4b2 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -87,12 +87,10 @@ and exp' at note = function I.ArrayE (mut m, T.as_immut t, exps es) | S.IdxE (e1, e2) -> I.IdxE (exp e1, exp e2) | S.FuncE (name, s, tbs, p, _t_opt, e) -> - let args, wrap, control, n_res = to_args note.I.note_typ p in - let _, _, _, ty = T.as_func_sub s.it (List.length tbs) note.I.note_typ in + let args, wrap, control, res_tys = to_args note.I.note_typ p in let tbs' = typ_binds tbs in let vars = List.map (fun (tb : I.typ_bind) -> T.Con (tb.it.I.con, [])) tbs' in - let ty = T.open_ vars ty in - let tys = if n_res = 1 then [ty] else T.as_seq ty in + let tys = List.map (T.open_ vars) res_tys in I.FuncE (name, s.it, control, tbs', args, tys, wrap (exp e)) (* Primitive functions in the prelude have particular shapes *) | S.CallE ({it=S.AnnotE ({it=S.PrimE p;_}, _);note;_}, _, e) @@ -369,17 +367,17 @@ and to_arg p : (Ir.arg * (Ir.exp -> Ir.exp)) = (fun e -> blockE [letP (pat p) v] e) -and to_args typ p : (Ir.arg list * (Ir.exp -> Ir.exp) * T.control * int) = - let sort, control, n_args, n_res = +and to_args typ p : Ir.arg list * (Ir.exp -> Ir.exp) * T.control * T.typ list = + let sort, control, n_args, res_tys = match typ with | Type.Func (sort, control, tbds, dom, res) -> - sort, control, List.length dom, List.length res + sort, control, List.length dom, res | Type.Non -> - Type.Local, Type.Returns, 1, 1 + Type.Local, Type.Returns, 1, [] | _ -> raise (Invalid_argument ("to_args " ^ Type.string_of_typ typ)) in - let tys = if n_args = 1 then [p.note] else T.as_seq p.note in + let tys = if n_args = 1 then [p.note] else T.seq_of_tup p.note in let args, wrap = match n_args, p.it with @@ -411,7 +409,7 @@ and to_args typ p : (Ir.arg list * (Ir.exp -> Ir.exp) * T.control * int) = | _ -> assert false else wrap e in - args, wrap_under_async, control, n_res + args, wrap_under_async, control, res_tys and prog (p : Syntax.prog) : Ir.prog = begin match p.it with diff --git a/src/mo_def/syntax.ml b/src/mo_def/syntax.ml index 83593f94b04..700694154b8 100644 --- a/src/mo_def/syntax.ml +++ b/src/mo_def/syntax.ml @@ -191,11 +191,6 @@ let seqT ts = at = Source.no_region; Source.note = Type.Tup (List.map (fun t -> t.Source.note) ts) } -let as_seqT t = - match t.Source.it with - | TupT ts -> ts - | _ -> [t] - let arity t = match t.Source.it with | TupT ts -> List.length ts diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 274d51daf05..fe48dee2cab 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -209,20 +209,29 @@ let error_shared env t at fmt = | _ -> raise Recover) fmt +let as_domT t = + match t.Source.it with + | TupT ts -> ts + | _ -> [t] + +let as_codomT sort t = + match sort, t.Source.it with + | T.Shared _, AsyncT t -> T.Promises, as_domT t + | _ -> T.Returns, as_domT t + +let check_shared_return env at sort c ts = + match sort, c, ts with + | T.Shared _, T.Promises, _ -> () + | T.Shared T.Write, T.Returns, [] -> () + | T.Shared T.Write, _, _ -> error env at "shared function must have syntactic return type `()` or `async `" + | T.Shared T.Query, _, _ -> error env at "shared query function must have syntactic return type `async `" + | _ -> () + let rec check_typ env typ : T.typ = let t = check_typ' env typ in typ.note <- t; t -and infer_control env sort typ = - match sort.it, typ.it with - | T.Shared _, AsyncT ret_typ -> T.Promises (arity ret_typ) - | T.Shared T.Write, TupT [] -> - T.Returns - | T.Shared T.Write, _ -> error env typ.at "shared function must have syntactic return type `()` or `async `" - | T.Shared T.Query, _ -> error env typ.at "shared query function must have syntactic return type `async `" - | _ -> T.Returns - and check_typ' env typ : T.typ = match typ.it with | PathT (path, typs) -> @@ -246,19 +255,26 @@ and check_typ' env typ : T.typ = | FuncT (sort, binds, typ1, typ2) -> let cs, ts, te, ce = check_typ_binds env binds in let env' = adjoin_typs env te ce in - let typs1 = as_seqT typ1 in - let typs2 = as_seqT typ2 in + let typs1 = as_domT typ1 in + let c, typs2 = as_codomT sort.it typ2 in let ts1 = List.map (check_typ env') typs1 in let ts2 = List.map (check_typ env') typs2 in - let c = infer_control env sort typ2 in + check_shared_return env typ2.at sort.it c ts2; + if Type.is_shared_sort sort.it then if not env.pre then begin let t1 = T.seq ts1 in if not (T.shared t1) then error_shared env t1 typ1.at "shared function has non-shared parameter type\n %s" (T.string_of_typ_expand t1); - match ts2 with - | [] when sort.it = T.Shared T.Write -> () - | [T.Async _] -> () + List.iter (fun t -> + if not (T.shared t) then + error_shared env t typ.at + "shared function has non-shared return type\n %s" + (T.string_of_typ_expand t); + ) ts2; + match c, ts2 with + | T.Returns, [] when sort.it = T.Shared T.Write -> () + | T.Promises, _ -> () | _ -> error env typ2.at "shared function has non-async result type\n %s" @@ -679,37 +695,45 @@ and infer_exp'' env exp : T.typ = | Some typ -> typ | None -> {it = TupT []; at = no_region; note = T.Pre} in - let c = infer_control env sort typ in + let c, ts2 = as_codomT sort.it typ in + check_shared_return env typ.at sort.it c ts2; + let cs, ts, te, ce = check_typ_binds env typ_binds in let env' = adjoin_typs env te ce in let t1, ve = infer_pat_exhaustive env' pat in - let t2 = check_typ env' typ in + let ts2 = List.map (check_typ env') ts2 in + let codom = T.codom c ts2 in if not env.pre then begin let env'' = { env' with labs = T.Env.empty; - rets = Some t2; + rets = Some codom; async = false; in_shared = T.is_shared_sort sort.it} in - check_exp (adjoin_vals env'' ve) t2 exp; + check_exp (adjoin_vals env'' ve) codom exp; if Type.is_shared_sort sort.it then begin if not (T.shared t1) then error_shared env t1 pat.at "shared function has non-shared parameter type\n %s" (T.string_of_typ_expand t1); - match t2 with - | T.Tup [] when sort.it = T.Shared T.Write -> () - | T.Async _ -> + List.iter (fun t -> + if not (T.shared t) then + error_shared env t typ.at + "shared function has non-shared return type\n %s" + (T.string_of_typ_expand t); + ) ts2; + match c, ts2 with + | T.Returns, [] when sort.it = T.Shared T.Write -> () + | T.Promises, _ -> if not (isAsyncE exp) then error env exp.at "shared function with async result type has non-async body" | _ -> error env typ.at "shared function has non-async result type\n %s" - (T.string_of_typ_expand t2) + (T.string_of_typ_expand codom) end end; - let ts1 = match pat.it with TupP _ -> T.as_seq t1 | _ -> [t1] in - let ts2 = match typ.it with TupT _ -> T.as_seq t2 | _ -> [t2] in + let ts1 = match pat.it with TupP _ -> T.seq_of_tup t1 | _ -> [t1] in let tbs = List.map2 (fun c t -> {T.var = Con.name c; bound = T.close cs t}) cs ts in T.Func (sort.it, c, tbs, List.map (T.close cs) ts1, List.map (T.close cs) ts2) | CallE (exp1, insts, exp2) -> @@ -994,11 +1018,12 @@ and check_exp' env0 t exp : T.typ = (String.concat " or\n " ss) ); t - | FuncE (_, s', [], pat, typ_opt, exp), T.Func (s, _, [], ts1, ts2) -> + | FuncE (_, s', [], pat, typ_opt, exp), T.Func (s, c, [], ts1, ts2) -> let ve = check_pat_exhaustive env (T.seq ts1) pat in + let codom = T.codom c ts2 in let t2 = match typ_opt with - | None -> T.seq ts2 + | None -> codom | Some typ -> check_typ env typ in if s'.it <> s then @@ -1006,10 +1031,10 @@ and check_exp' env0 t exp : T.typ = "%sshared function does not match expected %sshared function type" (if s'.it = T.Local then "non-" else "") (if s = T.Local then "non-" else ""); - if not (T.sub t2 (T.seq ts2)) then + if not (T.sub t2 codom) then error env exp.at "function return type\n %s\ndoes not match expected return type\n %s" - (T.string_of_typ_expand t2) (T.string_of_typ_expand (T.seq ts2)); + (T.string_of_typ_expand t2) (T.string_of_typ_expand codom); let env' = { env with labs = T.Env.empty; @@ -1759,7 +1784,7 @@ and infer_dec_valdecs env dec : Scope.t = let env' = adjoin_typs env te ce in let c = T.Env.find id.it env.typs in let t1, _ = infer_pat {env' with pre = true} pat in - let ts1 = match pat.it with TupP _ -> T.as_seq t1 | _ -> [t1] in + let ts1 = match pat.it with TupP _ -> T.seq_of_tup t1 | _ -> [t1] in let t2 = T.Con (c, List.map (fun c -> T.Con (c, [])) cs) in let tbs = List.map2 (fun c t -> {T.var = Con.name c; bound = T.close cs t}) cs ts in let t = T.Func (T.Local, T.Returns, tbs, List.map (T.close cs) ts1, [T.close cs t2]) in diff --git a/src/mo_idl/mo_to_idl.ml b/src/mo_idl/mo_to_idl.ml index 352b5beaff0..9915cce9eb1 100644 --- a/src/mo_idl/mo_to_idl.ml +++ b/src/mo_idl/mo_to_idl.ml @@ -98,12 +98,12 @@ let rec typ vs t = let fs1 = tuple vs ts1 in (match ts2, c with | [], Returns -> I.FuncT ([I.Oneway @@ no_region], fs1, []) - | [Async t], Promises p -> + | ts, Promises -> I.FuncT ( (match s with | Query -> [I.Query @@ no_region] | Write -> []), - fs1, tuple vs (if p = 1 then [t] else as_seq t)) + fs1, tuple vs ts) | _ -> assert false) | Func _ -> assert false | Async t -> assert false diff --git a/src/mo_interpreter/interpret.ml b/src/mo_interpreter/interpret.ml index a56ffb492aa..0ae643c0e00 100644 --- a/src/mo_interpreter/interpret.ml +++ b/src/mo_interpreter/interpret.ml @@ -213,8 +213,8 @@ let make_async_message env id v = let open CC in let call_conv, f = V.as_func v in match call_conv with - | {sort = T.Shared s; control = T.Promises p; n_res = 1; _} -> - Value.async_func s call_conv.n_args p (fun v k -> + | {sort = T.Shared s; control = T.Promises; _} -> + Value.async_func s call_conv.n_args call_conv.n_res (fun v k -> let async = make_async () in actor_msg env id f v (fun v_async -> get_async (V.as_async v_async) (set_async async) (reject_async async) @@ -227,8 +227,8 @@ let make_async_message env id v = let make_message env name t v : V.value = match t with - | T.Func (_, _, _, _, []) -> make_unit_message env name v - | T.Func (_, _, _, _, [T.Async _]) -> make_async_message env name v + | T.Func (_, T.Returns, _, _, _) -> make_unit_message env name v + | T.Func (_, T.Promises, _, _, _) -> make_async_message env name v | _ -> (* assert false *) failwith (Printf.sprintf "actorfield: %s %s" name (T.string_of_typ t)) diff --git a/src/mo_types/arrange_type.ml b/src/mo_types/arrange_type.ml index 8524f290a83..693b10a14da 100644 --- a/src/mo_types/arrange_type.ml +++ b/src/mo_types/arrange_type.ml @@ -5,7 +5,7 @@ let ($$) head inner = Node (head, inner) let control c = match c with | Returns -> "Returns" - | Promises n -> "Promises " ^ string_of_int n + | Promises -> "Promises" let obj_sort s = match s with | Object -> Atom "Object" diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index 9978f2649b1..6da2971e63e 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -4,7 +4,7 @@ open Mo_config type lab = string type var = string -type control = Returns | Promises of int (* Returns a computed value or immediate promise *) +type control = Returns | Promises type obj_sort = Object | Actor | Module type shared_sort = Query | Write type func_sort = Local | Shared of shared_sort @@ -130,6 +130,9 @@ let prim = function let seq = function [t] -> t | ts -> Tup ts +let codom c ts = match c with + | Promises -> Async (seq ts) + | Returns -> seq ts (* Coercions *) @@ -350,6 +353,11 @@ let as_seq t = | Tup ts -> ts | t -> [t] +let seq_of_tup t = + match normalize t with + | Tup ts -> ts + | t -> invalid "seq_of_tup" + let arity t = match normalize t with | Tup ts -> List.length ts @@ -388,7 +396,7 @@ let as_pair_sub t = match promote t with | Non -> Non, Non | _ -> invalid "as_pair_sub" let as_func_sub default_s default_arity t = match promote t with - | Func (s, _, tbs, ts1, ts2) -> s, tbs, seq ts1, seq ts2 + | Func (s, c, tbs, ts1, ts2) -> s, tbs, seq ts1, codom c ts2 | Non -> default_s, Lib.List.make default_arity {var = "X"; bound = Any}, Any, Non | _ -> invalid "as_func_sub" let as_mono_func_sub t = match promote t with @@ -1159,29 +1167,29 @@ and string_of_dom vs ts = sprintf "(%s)" dom | _ -> dom -and string_of_cod c vs ts = +and string_of_cod vs ts = let cod = string_of_typ' vs (seq ts) in match ts with - | [Tup _] -> - sprintf "(%s)" cod - | [Async _] -> - (match c with - | Returns -> sprintf "(%s)" cod - | Promises _ -> sprintf "%s" cod - ) + | [Tup _] -> sprintf "(%s)" cod | _ -> cod +and string_of_control_cod c vs ts = + let cod = string_of_cod vs ts in + match c with + | Returns -> cod + | Promises -> sprintf "async %s" cod + and string_of_typ' vs t = match t with | Func (s, c, [], ts1, ts2) -> sprintf "%s%s -> %s" (string_of_func_sort s) (string_of_dom vs ts1) - (string_of_cod c vs ts2) + (string_of_control_cod c vs ts2) | Func (s, c, tbs, ts1, ts2) -> let vs' = vars_of_binds vs tbs in sprintf "%s%s%s -> %s" (string_of_func_sort s) (string_of_binds (vs' @ vs) vs' tbs) - (string_of_dom (vs' @ vs) ts1) (string_of_cod c (vs' @ vs) ts2) + (string_of_dom (vs' @ vs) ts1) (string_of_control_cod c (vs' @ vs) ts2) | Opt t -> sprintf "?%s" (string_of_typ_nullary vs t) | Async t -> diff --git a/src/mo_types/type.mli b/src/mo_types/type.mli index aed92491c4e..4b8772cbbc2 100644 --- a/src/mo_types/type.mli +++ b/src/mo_types/type.mli @@ -3,7 +3,7 @@ type lab = string type var = string -type control = Returns | Promises of int (* returns a computed value or immediate promise *) +type control = Returns | Promises type obj_sort = Object | Actor | Module type shared_sort = Query | Write type func_sort = Local | Shared of shared_sort @@ -127,7 +127,9 @@ val as_async_sub : typ -> typ (* Argument/result sequences *) val seq : typ list -> typ -val as_seq : typ -> typ list +val codom : control -> typ list -> typ +val as_seq : typ -> typ list (* This needs to go away *) +val seq_of_tup : typ -> typ list val arity : typ -> int (* Fields *) diff --git a/src/mo_values/call_conv.ml b/src/mo_values/call_conv.ml index 736a95b27bf..539f9d5be28 100644 --- a/src/mo_values/call_conv.ml +++ b/src/mo_values/call_conv.ml @@ -18,7 +18,7 @@ type t = call_conv let local_cc n m = { sort = Local; control = Returns; n_args = n; n_res = m} let message_cc s n = { sort = Shared s; control = Returns; n_args = n; n_res = 0} -let async_cc s n p = { sort = Shared s; control = Promises p; n_args = n; n_res = 1} +let async_cc s n m = { sort = Shared s; control = Promises; n_args = n; n_res = m} let call_conv_of_typ typ = match typ with @@ -32,6 +32,6 @@ let string_of_call_conv {sort;control;n_args;n_res} = Printf.sprintf "(%s%i %s %i)" (string_of_func_sort sort) n_args - (match control with Returns -> "->" | Promises p -> "@>"^ string_of_int p) + (match control with Returns -> "->" | Promises -> "@>") n_res diff --git a/test/fail/ok/abstract-msgs.tc.ok b/test/fail/ok/abstract-msgs.tc.ok index c89d6e6a5b1..31c88c8727a 100644 --- a/test/fail/ok/abstract-msgs.tc.ok +++ b/test/fail/ok/abstract-msgs.tc.ok @@ -3,17 +3,17 @@ abstract-msgs.mo:2.28-2.37: type error, shared function has non-shared parameter abstract-msgs.mo:3.33-3.35: type error, shared function must have syntactic return type `()` or `async ` abstract-msgs.mo:5.20-5.29: type error, shared function has non-shared parameter type A/10 -abstract-msgs.mo:6.31-6.33: type error, async has non-shared content type +abstract-msgs.mo:6.25-6.33: type error, shared function has non-shared return type ?A/10 abstract-msgs.mo:10.34-10.35: type error, shared function has non-shared parameter type A/11 -abstract-msgs.mo:11.46-11.47: type error, async has non-shared content type +abstract-msgs.mo:11.27-11.47: type error, shared function has non-shared return type A/12 abstract-msgs.mo:14.30-14.31: type error, shared function has non-shared parameter type A/13 -abstract-msgs.mo:15.42-15.43: type error, async has non-shared content type +abstract-msgs.mo:15.13-15.43: type error, shared function has non-shared return type A/14 abstract-msgs.mo:16.31-16.32: type error, shared function has non-shared parameter type A/15 -abstract-msgs.mo:17.43-17.44: type error, async has non-shared content type +abstract-msgs.mo:17.24-17.44: type error, shared function has non-shared return type A/16 diff --git a/test/run-drun/ok/idl-func.tc.ok b/test/run-drun/ok/idl-func.tc.ok index 362a324e3f9..b796bc5ed9d 100644 --- a/test/run-drun/ok/idl-func.tc.ok +++ b/test/run-drun/ok/idl-func.tc.ok @@ -1,8 +1,8 @@ -idl-func.mo:1.33-1.37: type error, async has non-shared content type +idl-func.mo:1.13-1.37: type error, shared function has non-shared return type Func = shared Int -> async Func type Func = shared Int -> async Func is or contains non-shared type shared Int -> async Func -idl-func.mo:1.33-1.37: type error, shared function types are non-shared. +idl-func.mo:1.13-1.37: type error, shared function types are non-shared. (This is a limitation of the current version.) From 1cf45adc1c41b868afff06c36111d06346fa313c Mon Sep 17 00:00:00 2001 From: DavidM-D Date: Thu, 31 Oct 2019 11:05:50 +0100 Subject: [PATCH 0497/1176] Added the correct list of keywords from the lexer to the docs (#805) * Added the correct list of keywords from the lexer * In lexer, note that this needs to be updated too --- guide/guide.md | 7 ++++--- src/mo_frontend/lexer.mll | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/guide/guide.md b/guide/guide.md index cc8b3a69a3a..13c13b305de 100644 --- a/guide/guide.md +++ b/guide/guide.md @@ -138,9 +138,10 @@ All comments are treated as whitespace. The following keywords are reserved and may not be used as identifiers: ```bnf -actor and async assert await break case catch class continue else -false for func if in new not null object or label let loop -private public return shared switch true try type var while +actor and async assert await break case catch class continue debug +else false for func if in import module not null object or label +let loop private public return shared try throw debug_show query +switch true type var while ``` ## Identifiers diff --git a/src/mo_frontend/lexer.mll b/src/mo_frontend/lexer.mll index ebd0c3f6977..675268d8984 100644 --- a/src/mo_frontend/lexer.mll +++ b/src/mo_frontend/lexer.mll @@ -187,6 +187,7 @@ rule token mode = parse (* If you add keywords, please also update - src/idllib/escape.ml - emacs/motoko-mode.el + - guide/guide.md *) | "actor" { ACTOR } | "and" { AND } From 50b0fd96f596557116f2c0d523c9a4a976c1768c Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 31 Oct 2019 12:14:20 +0100 Subject: [PATCH 0498/1176] =?UTF-8?q?Introduce=20a=20=E2=80=9CReplies?= =?UTF-8?q?=E2=80=9D=20control?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit this only exits post the async translation, and describes functions that yield their result via `reply`, rather than `return`. It preseves the replied type in the `res_tys` field, so that we could check whether calls to `ICReply` are well-typed, and more in that direction. --- src/codegen/compile.ml | 60 +++++++++++-------- src/ir_def/check_ir.ml | 26 ++++---- src/ir_def/construct.ml | 4 +- src/ir_interpreter/interpret_ir.ml | 1 + src/ir_passes/async.ml | 21 ++----- src/mo_types/arrange_type.ml | 1 + src/mo_types/type.ml | 7 ++- src/mo_types/type.mli | 2 +- src/mo_values/call_conv.ml | 2 +- .../ok/counter-class.wasm.stderr.ok | 6 +- test/run-drun/ok/ic-calls.wasm.stderr.ok | 2 +- 11 files changed, 72 insertions(+), 60 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index a6a2982d1aa..a9ee1b2979b 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -162,7 +162,7 @@ module E = struct (* Local fields (only valid/used inside a function) *) (* Static *) n_param : int32; (* Number of parameters (to calculate indices of locals) *) - n_res : int; (* Number of return values (for type of Return) *) + return_arity : int; (* Number of return values (for type of Return) *) (* Immutable *) @@ -194,16 +194,16 @@ module E = struct static_memory_frozen = ref false; (* Actually unused outside mk_fun_env: *) n_param = 0l; - n_res = 0; + return_arity = 0; locals = ref []; local_names = ref []; } - let mk_fun_env env n_param n_res = + let mk_fun_env env n_param return_arity = { env with n_param; - n_res; + return_arity; locals = ref []; local_names = ref []; } @@ -310,7 +310,7 @@ module E = struct | Some (Defined fi) -> () | Some (Pending mk_fun) -> () - let get_n_res (env : t) = env.n_res + let get_return_arity (env : t) = env.return_arity let get_func_imports (env : t) = !(env.func_imports) let get_other_imports (env : t) = !(env.other_imports) @@ -4878,8 +4878,8 @@ module FuncDec = struct the function will find in the closure. *) let compile_local_function outer_env outer_ae restore_env args mk_body ret_tys at = let arg_names = List.map (fun a -> a.it, I32Type) args in - let n_res = List.length ret_tys in - let retty = Lib.List.make n_res I32Type in + let return_arity = List.length ret_tys in + let retty = Lib.List.make return_arity I32Type in let ae0 = VarEnv.mk_fun_ae outer_ae in Func.of_body outer_env (["clos", I32Type] @ arg_names) retty (fun env -> G.with_region at ( let get_closure = G.i (LocalGet (nr 0l)) in @@ -4952,7 +4952,8 @@ module FuncDec = struct mk_body env ae2 ^^ message_cleanup env sort )) - | Type.Promises _ -> + | Type.Promises -> assert false + | Type.Replies -> Func.of_body outer_env ["clos", I32Type; "reply", I32Type; "databuf", I32Type; "elembuf", I32Type] [] (fun env -> G.with_region at ( let get_reply = G.i (LocalGet (nr 1l)) in let get_databuf = G.i (LocalGet (nr 2l)) in @@ -5011,8 +5012,8 @@ module FuncDec = struct mk_body env ae1 ^^ message_cleanup env sort )) - | Flags.AncientMode, Type.Promises _ -> (* with callback *) - assert (List.length ret_tys = 0); + | Flags.AncientMode, Type.Promises -> assert false + | Flags.AncientMode, Type.Replies -> (* with callback *) let ae0 = VarEnv.mk_fun_ae outer_ae in Func.of_body outer_env ["reply", I32Type; "databuf", I32Type; "elembuf", I32Type] [] (fun env -> G.with_region at ( let get_reply = G.i (LocalGet (nr 0l)) in @@ -6478,8 +6479,8 @@ and compile_exp (env : E.t) ae exp = G.i Unreachable | RetE e -> SR.Unreachable, - compile_exp_as env ae (StackRep.of_arity (E.get_n_res env)) e ^^ - FakeMultiVal.store env (Lib.List.make (E.get_n_res env) I32Type) ^^ + compile_exp_as env ae (StackRep.of_arity (E.get_return_arity env)) e ^^ + FakeMultiVal.store env (Lib.List.make (E.get_return_arity env) I32Type) ^^ G.i Return | OptE e -> SR.Vanilla, @@ -6499,9 +6500,12 @@ and compile_exp (env : E.t) ae exp = | CallE (e1, _, e2) -> let sort, control, _, arg_tys, ret_tys = Type.as_func e1.note.note_typ in let n_args = List.length arg_tys in - let n_res = List.length ret_tys in + let return_arity = match control with + | Type.Returns -> List.length ret_tys + | Type.Replies -> 0 + | Type.Promises -> assert false in - StackRep.of_arity n_res, + StackRep.of_arity return_arity, let fun_sr, code1 = compile_exp env ae e1 in begin match fun_sr, sort with | SR.StaticThing (SR.StaticFun fi), _ -> @@ -6509,7 +6513,7 @@ and compile_exp (env : E.t) ae exp = compile_unboxed_zero ^^ (* A dummy closure *) compile_exp_as env ae (StackRep.of_arity n_args) e2 ^^ (* the args *) G.i (Call (nr fi)) ^^ - FakeMultiVal.load env (Lib.List.make n_res I32Type) + FakeMultiVal.load env (Lib.List.make return_arity I32Type) | _, Type.Local -> let (set_clos, get_clos) = new_local env "clos" in code1 ^^ StackRep.adjust env fun_sr SR.Vanilla ^^ @@ -6517,7 +6521,7 @@ and compile_exp (env : E.t) ae exp = get_clos ^^ compile_exp_as env ae (StackRep.of_arity n_args) e2 ^^ get_clos ^^ - Closure.call_closure env n_args n_res + Closure.call_closure env n_args return_arity | _, Type.Shared _ -> (* Non-one-shot functions have been rewritten in async.ml *) assert (control = Type.Returns); @@ -6559,11 +6563,15 @@ and compile_exp (env : E.t) ae exp = SR.unit, compile_exp_vanilla env ae e ^^ Var.set_val env ae name - | FuncE (x, sort, control, typ_binds, args, ret_tys, e) -> + | FuncE (x, sort, control, typ_binds, args, res_tys, e) -> let captured = Freevars.captured exp in - let n_res = List.length ret_tys in - let mk_body env1 ae1 = compile_exp_as env1 ae1 (StackRep.of_arity n_res) e in - FuncDec.lit env ae typ_binds x sort control captured args mk_body ret_tys exp.at + let return_tys = match control with + | Type.Returns -> res_tys + | Type.Replies -> [] + | Type.Promises -> assert false in + let return_arity = List.length return_tys in + let mk_body env1 ae1 = compile_exp_as env1 ae1 (StackRep.of_arity return_arity) e in + FuncDec.lit env ae typ_binds x sort control captured args mk_body return_tys exp.at | ActorE (i, ds, fs, _) -> SR.UnboxedReference, let captured = Freevars.exp exp in @@ -6889,14 +6897,18 @@ and compile_prog env ae (ds, e) = (ae', code1 ^^ code2) and compile_static_exp env pre_ae how exp = match exp.it with - | FuncE (name, sort, control, typ_binds, args, ret_tys, e) -> + | FuncE (name, sort, control, typ_binds, args, res_tys, e) -> + let return_tys = match control with + | Type.Returns -> res_tys + | Type.Replies -> [] + | Type.Promises -> assert false in let mk_body env ae = assert begin (* Is this really closed? *) List.for_all (fun v -> VarEnv.NameEnv.mem v ae.VarEnv.vars) (Freevars.M.keys (Freevars.exp e)) end; - compile_exp_as env ae (StackRep.of_arity (List.length ret_tys)) e in - FuncDec.closed env sort control name args mk_body ret_tys exp.at + compile_exp_as env ae (StackRep.of_arity (List.length return_tys)) e in + FuncDec.closed env sort control name args mk_body return_tys exp.at | _ -> assert false and compile_prelude env ae = @@ -6971,7 +6983,7 @@ and export_actor_field env ae (f : Ir.field) = assert (G.is_nop code); let is_await = match Type.normalize f.note with - | Type.Func(_,Type.Promises _,_,_,_) -> true + | Type.Func(_,Type.Replies,_,_,_) -> true | _ -> false in FuncDec.declare_dfinity_type env false is_await fi; diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index f35de411d70..eee63c0ebba 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -158,18 +158,22 @@ let rec check_typ env typ : unit = List.iter (fun t -> check_shared env no_region t) ts1; match control with | T.Returns -> - (* async translations changes result of one-shot function. - this can change once we preserve the return type of Promising functions - past async translation - *) - if env.flavor.Ir.has_async_typ then - check env' no_region (sort = T.Shared T.Write) - "one-shot query function pointless" + check env' no_region (sort = T.Shared T.Write) + "one-shot query function pointless" | T.Promises -> + check env no_region env.flavor.Ir.has_async_typ + "promising function in post-async flavor"; check env' no_region (sort <> T.Local) "promising function cannot be local:\n %s" (T.string_of_typ_expand (T.seq ts)); check env' no_region (List.for_all T.shared ts) "message result is not sharable:\n %s" (T.string_of_typ_expand (T.seq ts)) + | T.Replies -> + check env no_region (not env.flavor.Ir.has_async_typ) + "replying function in pre-async flavor"; + check env' no_region (sort <> T.Local) + "replying function cannot be local:\n %s" (T.string_of_typ_expand (T.seq ts)); + check env' no_region (List.for_all T.shared ts) + "message result is not sharable:\n %s" (T.string_of_typ_expand (T.seq ts)) end else check env' no_region (control = T.Returns) "promising function cannot be local:\n %s" (T.string_of_typ_expand typ); @@ -375,18 +379,18 @@ let rec check_exp env (exp:Ir.exp) : unit = typ k <: T.Func (T.Local, T.Returns, [], t_rets, []); typ r <: T.Func (T.Local, T.Returns, [], [T.catch], []); *) - | T.Func (sort, T.Promises, [], arg_tys, []) -> + | T.Func (sort, T.Replies, [], arg_tys, _ret_tys) -> check_exp env exp2; let t_arg = T.seq arg_tys in typ exp2 <: t_arg; - (match (T.promote (typ k)) with - | T.Func (T.Shared T.Write, T.Promises, [], t_rets, []) -> + (match T.promote (typ k) with + | T.Func (T.Shared T.Write, T.Replies, [], t_rets, []) -> check_concrete env exp.at (T.seq t_rets) | T.Non -> () (* dead code, not much to check here *) | t -> error env k.at "expected continuation type, but expression produces type\n %s" (T.string_of_typ_expand t)); - typ r <: T.Func (T.Shared T.Write, T.Promises, [], [T.text], []); + typ r <: T.Func (T.Shared T.Write, T.Replies, [], [T.text], []); | T.Non -> () (* dead code, not much to check here *) | _ -> error env exp1.at "expected function type, but expression produces type\n %s" diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index e58fa34c582..075b57e817a 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -465,9 +465,9 @@ let (-->*) xs exp = nary_funcE "$lambda" fun_ty xs exp -(* n-ary shared lambda, used for callbacks *) +(* n-ary shared lambda, used for callbacks in async *) let (-@>*) xs exp = - let fun_ty = T.Func (T.Shared T.Write, T.Promises, [], List.map typ xs, T.as_seq (typ exp)) in + let fun_ty = T.Func (T.Shared T.Write, T.Replies, [], List.map typ xs, T.as_seq (typ exp)) in nary_funcE "$lambda" fun_ty xs exp diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index 415adf7b543..a07f26b0394 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -217,6 +217,7 @@ let make_message env x cc v : V.value = match cc.CC.control with | T.Returns -> make_unit_message env x v | T.Promises-> make_async_message env x v + | T.Replies -> make_async_message env x v (* TBR *) let extended_prim env s typ at = diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index eaf55b73ca5..1cd621b36fa 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -197,20 +197,8 @@ module Transform(Platform : sig val platform : platform end) = struct | Array t -> Array (t_typ t) | Tup ts -> Tup (List.map t_typ ts) | Func (s, c, tbs, t1, t2) -> - begin - match s with - | T.Shared _ -> - begin - match c with - | T.Returns -> - assert (t2 = []); - Func(s, c, List.map t_bind tbs, List.map t_typ t1, List.map t_typ t2) - | T.Promises -> - Func (s, T.Promises, List.map t_bind tbs, List.map t_typ t1, []) - end - | T.Local -> - Func (s, c, List.map t_bind tbs, List.map t_typ t1, List.map t_typ t2) - end + let c' = if c = T.Promises then T.Replies else c in + Func (s, c', List.map t_bind tbs, List.map t_typ t1, List.map t_typ t2) | Opt t -> Opt (t_typ t) | Variant fs -> Variant (List.map t_field fs) | Async t -> t_async nary (t_typ t) @@ -294,7 +282,7 @@ module Transform(Platform : sig val platform : platform end) = struct []) -> (List.map t_typ ts1, t_typ contT) | t -> assert false in - let post = fresh_var "post" (T.Func(T.Shared T.Write, T.Promises, [], [], [])) in + let post = fresh_var "post" (T.Func(T.Shared T.Write, T.Replies, [], [], [])) in let u = fresh_var "u" T.unit in let ((nary_async, nary_reply, reject), def) = new_nary_async_reply ts1 in (blockE [letP (tupP [varP nary_async; varP nary_reply; varP reject]) def; @@ -393,7 +381,8 @@ module Transform(Platform : sig val platform : platform end) = struct let e = fresh_var "e" T.catch in let r = [e] -->* (sys_rejectE (errorMessageE e)) in let exp' = (t_exp cps) -*- tupE [k;r] in - FuncE (x, T.Shared s', Returns, typbinds', args', [], exp') + FuncE (x, T.Shared s', Replies, typbinds', args', ret_tys, exp') + | Replies -> assert false end end | ActorE (id, ds, fs, typ) -> diff --git a/src/mo_types/arrange_type.ml b/src/mo_types/arrange_type.ml index 693b10a14da..51fb22d106a 100644 --- a/src/mo_types/arrange_type.ml +++ b/src/mo_types/arrange_type.ml @@ -6,6 +6,7 @@ let ($$) head inner = Node (head, inner) let control c = match c with | Returns -> "Returns" | Promises -> "Promises" + | Replies -> "Replies" let obj_sort s = match s with | Object -> Atom "Object" diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index 6da2971e63e..c725b41a5bd 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -4,7 +4,10 @@ open Mo_config type lab = string type var = string -type control = Returns | Promises +type control = + | Returns (* regular local function or one-shot shared function *) + | Promises (* shared function producing a future value upon call *) + | Replies (* (IR only): responds asynchronously using `reply` *) type obj_sort = Object | Actor | Module type shared_sort = Query | Write type func_sort = Local | Shared of shared_sort @@ -133,6 +136,7 @@ let seq = function [t] -> t | ts -> Tup ts let codom c ts = match c with | Promises -> Async (seq ts) | Returns -> seq ts + | Replies -> Tup [] (* Coercions *) @@ -1178,6 +1182,7 @@ and string_of_control_cod c vs ts = match c with | Returns -> cod | Promises -> sprintf "async %s" cod + | Replies -> sprintf "replies %s" cod and string_of_typ' vs t = match t with diff --git a/src/mo_types/type.mli b/src/mo_types/type.mli index 4b8772cbbc2..e980366e0f6 100644 --- a/src/mo_types/type.mli +++ b/src/mo_types/type.mli @@ -3,7 +3,7 @@ type lab = string type var = string -type control = Returns | Promises +type control = Returns | Promises | Replies type obj_sort = Object | Actor | Module type shared_sort = Query | Write type func_sort = Local | Shared of shared_sort diff --git a/src/mo_values/call_conv.ml b/src/mo_values/call_conv.ml index 539f9d5be28..33750ca4df5 100644 --- a/src/mo_values/call_conv.ml +++ b/src/mo_values/call_conv.ml @@ -32,6 +32,6 @@ let string_of_call_conv {sort;control;n_args;n_res} = Printf.sprintf "(%s%i %s %i)" (string_of_func_sort sort) n_args - (match control with Returns -> "->" | Promises -> "@>") + (match control with Returns -> "->" | Promises -> "@>" | Replies -> "@>") n_res diff --git a/test/run-dfinity/ok/counter-class.wasm.stderr.ok b/test/run-dfinity/ok/counter-class.wasm.stderr.ok index dd9b7209cd5..f59ec22908c 100644 --- a/test/run-dfinity/ok/counter-class.wasm.stderr.ok +++ b/test/run-dfinity/ok/counter-class.wasm.stderr.ok @@ -22,8 +22,8 @@ non-closed actor: (ActorE (FuncE read Shared - Promises 1 - () + Replies + Int (CallE (FuncE $lambda @@ -56,5 +56,5 @@ non-closed actor: (ActorE ) (read read) (dec dec) - actor {dec : shared () -> (); read : shared () -> ()} + actor {dec : shared () -> (); read : shared () -> replies Int} ) diff --git a/test/run-drun/ok/ic-calls.wasm.stderr.ok b/test/run-drun/ok/ic-calls.wasm.stderr.ok index 3c4077bf861..16bed23dc0f 100644 --- a/test/run-drun/ok/ic-calls.wasm.stderr.ok +++ b/test/run-drun/ok/ic-calls.wasm.stderr.ok @@ -1 +1 @@ -Fatal error: exception "Assert_failure codegen/compile.ml:4922:4" +Fatal error: exception "Assert_failure codegen/compile.ml:4920:4" From b23fa02133a2a4134006192120f04f83ae866f93 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 31 Oct 2019 13:07:31 +0100 Subject: [PATCH 0499/1176] Check_Ir: Argument to IcCallPrim needs to be sharable --- src/ir_def/check_ir.ml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index eee63c0ebba..1ec3eea19b6 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -383,6 +383,7 @@ let rec check_exp env (exp:Ir.exp) : unit = check_exp env exp2; let t_arg = T.seq arg_tys in typ exp2 <: t_arg; + check_concrete env exp.at t_arg; (match T.promote (typ k) with | T.Func (T.Shared T.Write, T.Replies, [], t_rets, []) -> check_concrete env exp.at (T.seq t_rets) From 2099391bfffe1882981704886ba8ea3e5d9cbb74 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 31 Oct 2019 13:17:50 +0100 Subject: [PATCH 0500/1176] Run pre-lowering ir output again --- test/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/run.sh b/test/run.sh index ee422abae74..6b8fbab2733 100755 --- a/test/run.sh +++ b/test/run.sh @@ -163,7 +163,6 @@ do normalize $out/$base.run diff_files="$diff_files $base.run" - if false; then # Interpret IR without lowering $ECHO -n " [run-ir]" $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS -r -iR -no-async -no-await $base.mo > $out/$base.run-ir 2>&1 @@ -174,6 +173,7 @@ do diff -u -N --label "$base.run" $out/$base.run --label "$base.run-ir" $out/$base.run-ir > $out/$base.diff-ir diff_files="$diff_files $base.diff-ir" + if false; then # Interpret IR with lowering $ECHO -n " [run-low]" $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS -r -iR $base.mo > $out/$base.run-low 2>&1 From c5bceab59f643c36d095cb334f305c064b302714 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Thu, 31 Oct 2019 14:31:20 +0100 Subject: [PATCH 0501/1176] Toplevel imports (#751) --- src/languageServer/declaration_index.ml | 32 ++-- src/lowering/desugar.ml | 56 +------ src/lowering/desugar.mli | 2 +- src/mo_def/syntax.ml | 6 +- src/mo_frontend/definedness.ml | 6 + src/mo_frontend/definedness.mli | 1 + src/mo_frontend/parser.mly | 16 +- src/mo_frontend/typing.ml | 21 +-- src/mo_frontend/typing.mli | 2 +- src/mo_interpreter/interpret.ml | 17 +- src/mo_interpreter/interpret.mli | 2 +- src/mo_types/scope.ml | 2 +- src/mo_types/scope.mli | 2 +- src/pipeline/pipeline.ml | 149 +++++++++++------- src/pipeline/pipeline.mli | 2 +- stdlib/assocList.mo | 4 +- stdlib/docTable.mo | 10 +- stdlib/examples/actorspec/src/ActorSpec.mo | 8 +- .../examples/produce-exchange/profileActor.mo | 4 +- .../examples/produce-exchange/serverActor.mo | 4 +- .../examples/produce-exchange/serverLang.mo | 7 +- .../examples/produce-exchange/serverModel.mo | 29 ++-- .../produce-exchange/serverModelTypes.mo | 10 +- .../produce-exchange/test/evalBulk.mo | 8 +- .../test/producerRemInventory.mo | 8 +- .../test/profileFastCounts.mo | 4 +- .../test/retailerReserveMany.mo | 8 +- stdlib/examples/rx/src/Observable.mo | 6 +- stdlib/examples/rx/src/Observer.mo | 4 +- stdlib/examples/rx/src/Rx.mo | 15 +- stdlib/int.mo | 4 +- stdlib/listTest.mo | 3 +- stdlib/nat.mo | 6 +- stdlib/option.mo | 4 +- stdlib/result.mo | 2 +- stdlib/set.mo | 2 +- stdlib/trie.mo | 9 +- stdlib/trie2.mo | 17 +- test/lsp-int/Main.hs | 2 + test/lsp-int/test-project/ListClient.mo | 8 +- test/lsp-int/test-project/app.mo | 5 +- test/lsp-int/test-project/lib/ListFuncs.mo | 4 +- test/lsp-int/test-project/lib/option.mo | 4 +- test/repl/lib/a.mo | 4 +- test/repl/lib/b.mo | 3 +- test/repl/lib/c.mo | 2 +- test/repl/lib/nested.mo | 4 +- test/repl/lib/nested/a.mo | 2 +- test/repl/lib/nested/b.mo | 3 +- test/repl/ok/double-import.stdout.ok | 6 +- test/repl/ok/file-and-repl.stdout.ok | 1 + test/repl/ok/triangle-import.stdout.ok | 12 +- test/run/import-module.mo | 2 +- test/run/import.mo | 7 +- test/run/lib/dir/lib.mo | 2 +- test/run/lib/hello-string.mo | 2 +- 56 files changed, 287 insertions(+), 278 deletions(-) diff --git a/src/languageServer/declaration_index.ml b/src/languageServer/declaration_index.ml index 2d3453e3c91..0ceb0a6b953 100644 --- a/src/languageServer/declaration_index.ml +++ b/src/languageServer/declaration_index.ml @@ -109,15 +109,18 @@ let read_single_module_lib (ty: Type.typ): ide_decl list option = |> Lib.Option.some | _ -> None -let unwrap_module_ast (prog : Syntax.dec list): Syntax.exp_field list option = - match prog with - | ({it=Syntax.ExpD {it= Syntax.ObjE(_,fields) ;_} ;_} :: _) -> - Some fields +let unwrap_module_ast (lib : Syntax.lib): Syntax.exp_field list option = + match lib.it.it with + | Syntax.BlockE [] -> None + | Syntax.BlockE decs -> + (match Lib.List.last decs with + | {it=Syntax.ExpD {it= Syntax.ObjE(_,fields) ;_} ;_} -> Some fields + | _ -> None) | _ -> None let populate_definitions - (libraries : Syntax.libraries) + (libs : Syntax.lib list) (path : string) (decls : ide_decl list) : ide_decl list = @@ -131,9 +134,10 @@ let populate_definitions Some typ_id | _ -> None in let extract_binders env (pat : Syntax.pat) = gather_pat env pat in - let find_def (prog : Syntax.dec list) def = match def with + let find_def (lib : Syntax.lib) def = + match def with | ValueDecl value -> - let fields = Lib.Option.get (unwrap_module_ast prog) [] in + let fields = Lib.Option.get (unwrap_module_ast lib) [] in let positioned_binder = fields |> Lib.List.map_filter is_let_bound @@ -142,7 +146,7 @@ let populate_definitions in ValueDecl { value with definition = positioned_binder } | TypeDecl typ -> - let fields = Lib.Option.get (unwrap_module_ast prog) [] in + let fields = Lib.Option.get (unwrap_module_ast lib) [] in let type_definition = fields |> Lib.List.map_filter is_type_def @@ -154,12 +158,12 @@ let populate_definitions TypeDecl { typ with definition = type_definition } in let opt_lib = List.find_opt - (fun (path', _) -> String.equal path path') - libraries in + (fun lib -> String.equal path lib.note) + libs in match opt_lib with | None -> decls - | Some (_, prog) -> - List.map (find_def prog.it) decls + | Some lib -> + List.map (find_def lib) decls let make_index_inner vfs : declaration_index Diag.result = let entry_points = project_files () in @@ -167,7 +171,7 @@ let make_index_inner vfs : declaration_index Diag.result = (Vfs.parse_file vfs) Pipeline.initial_stat_env (Pipeline__.Resolve_import.S.of_list entry_points) - |> Diag.map (fun (libraries, scope) -> + |> Diag.map (fun (libs, scope) -> Type.Env.fold (fun path ty acc -> Index.add @@ -175,7 +179,7 @@ let make_index_inner vfs : declaration_index Diag.result = (ty |> read_single_module_lib |> Lib.Fun.flip Lib.Option.get [] - |> populate_definitions libraries path) + |> populate_definitions libs path) acc) scope.Scope.lib_env Index.empty) diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index e531167a4b2..9ac36149747 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -423,60 +423,18 @@ and prog (p : Syntax.prog) : Ir.prog = } -let declare_import imp_env (f, (prog:Syntax.prog)) = +let declare_import imp_env lib = let open Source in + let f = lib.note in let t = T.Env.find f imp_env in let typ_note = { Syntax.empty_typ_note with Syntax.note_typ = t } in - match prog.it with - | [{it = Syntax.ExpD e;_}] -> - { it = Syntax.LetD ( - { it = Syntax.VarP (id_of_full_path f) - ; at = no_region - ; note = t - } - , e - ) - ; at = no_region - ; note = typ_note - } - (* HACK: to be removed once we restrict programs to expressions *) - | ds -> - Diag.( - print_message - { sev = Warning - ; at = prog.at - ; cat = "import" - ; text = Printf.sprintf - "imported declarations `...` from file %s as a module; \ - please rewrite library %s as `module { ... }` instead." f f - } - ); - { it = - Syntax.LetD - ( - { it = Syntax.VarP (id_of_full_path f) - ; at = no_region - ; note = t - } - , { it = Syntax.ObjE - (T.Module @@ no_region, - List.map - (fun d -> - { Syntax.dec=d; vis=Syntax.Public @@ no_region } - @@ d.at) - prog.it) - ; at = no_region - ; note = typ_note - } - ) - ; at = no_region - ; note = typ_note - } - -let combine_files imp_env libraries progs : Syntax.prog = + let p = { it = Syntax.VarP (id_of_full_path f); at = lib.at; note = t } in + { it = Syntax.LetD (p, lib.it); at = lib.at; note = typ_note } + +let combine_files imp_env libs progs : Syntax.prog = (* This is a hack until the backend has explicit support for libraries *) let open Source in - { it = List.map (declare_import imp_env) libraries + { it = List.map (declare_import imp_env) libs @ List.concat (List.map (fun p -> p.it) progs) ; at = no_region ; note = match progs with diff --git a/src/lowering/desugar.mli b/src/lowering/desugar.mli index b3015fe89c2..cfe10d33ef9 100644 --- a/src/lowering/desugar.mli +++ b/src/lowering/desugar.mli @@ -3,4 +3,4 @@ open Mo_types open Ir_def val transform : Syntax.prog -> Ir.prog -val transform_graph : Scope.lib_env -> Syntax.libraries -> Syntax.prog list -> Ir.prog +val transform_graph : Scope.lib_env -> Syntax.lib list -> Syntax.prog list -> Ir.prog diff --git a/src/mo_def/syntax.ml b/src/mo_def/syntax.ml index 700694154b8..dff44ea575a 100644 --- a/src/mo_def/syntax.ml +++ b/src/mo_def/syntax.ml @@ -171,15 +171,17 @@ and dec' = | ClassD of (* class *) typ_id * typ_bind list * pat * typ option * obj_sort * id * exp_field list + (* Program *) type prog = (prog', string) Source.annotated_phrase and prog' = dec list + (* Libraries *) -type library = string * prog -type libraries = library list +type lib = (exp, string) Source.annotated_phrase + (* n-ary arguments/result sequences *) diff --git a/src/mo_frontend/definedness.ml b/src/mo_frontend/definedness.ml index f6f0ce8283d..3eb1b082db9 100644 --- a/src/mo_frontend/definedness.ml +++ b/src/mo_frontend/definedness.ml @@ -204,3 +204,9 @@ let check_prog prog = ignore (decs msgs prog.it); Some () ) + +let check_lib lib = + Diag.with_message_store (fun msgs -> + ignore (exp msgs lib.it); + Some () + ) diff --git a/src/mo_frontend/definedness.mli b/src/mo_frontend/definedness.mli index d2377acf3e3..5138b680944 100644 --- a/src/mo_frontend/definedness.mli +++ b/src/mo_frontend/definedness.mli @@ -1,3 +1,4 @@ open Mo_def val check_prog : Syntax.prog -> unit Diag.result +val check_lib : Syntax.lib -> unit Diag.result diff --git a/src/mo_frontend/parser.mly b/src/mo_frontend/parser.mly index b0a2c9a877c..9a4faf37c65 100644 --- a/src/mo_frontend/parser.mly +++ b/src/mo_frontend/parser.mly @@ -639,9 +639,6 @@ dec_nonvar : let efs' = if s.it = Type.Actor then List.map share_expfield efs else efs in ClassD(xf "class" $sloc, tps, p, t, s, x, efs') @? at $sloc } - | IMPORT xf=id_opt EQ? f=TEXT - { let named, x = xf "import" $sloc in - let_or_exp named x (ImportE (f, ref "")) (at $sloc) } dec : | d=dec_var @@ -677,12 +674,17 @@ class_body : (* Programs *) +imp : + | IMPORT xf=id_opt EQ? f=TEXT + { let _, x = xf "import" $sloc in + let_or_exp true x (ImportE (f, ref "")) (at $sloc) } + parse_prog : - | ds=seplist(dec, semicolon) EOF - { fun filename -> { it = ds; at = at $sloc ; note = filename} } + | is=seplist(imp, semicolon) ds=seplist(dec, semicolon) EOF + { fun filename -> { it = is @ ds; at = at $sloc ; note = filename} } parse_prog_interactive : - | ds=seplist(dec, SEMICOLON) SEMICOLON_EOL - { fun filename -> { it = ds; at = at $sloc ; note = filename} } + | is=seplist(imp, SEMICOLON) ds=seplist(dec, SEMICOLON) SEMICOLON_EOL + { fun filename -> { it = is @ ds; at = at $sloc ; note = filename} } %% diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index fe48dee2cab..c8ddd22ae23 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -1807,26 +1807,15 @@ let infer_prog scope prog : (T.typ * Scope.t) Diag.result = ) prog ) -let infer_library env prog at = - let typ,scope = infer_block env prog at in - match prog with - | [{it = Syntax.ExpD _;_}] -> - typ - (* HACK: to be removed once we insist on single expression imports *) - | ds -> - object_of_scope env T.Module - (List.map (fun d -> {vis = Public @@ no_region; dec = d} @@ no_region) ds) - scope at - -let check_library scope (filename, prog) : Scope.t Diag.result = +let check_lib scope lib : Scope.t Diag.result = Diag.with_message_store (fun msgs -> recover_opt - (fun prog -> + (fun lib -> let env = env_of_scope msgs scope in - let typ = infer_library env prog.it prog.at in - Scope.library filename typ - ) prog + let typ = infer_exp env lib.it in + Scope.lib lib.note typ + ) lib ) let is_actor_dec d = diff --git a/src/mo_frontend/typing.mli b/src/mo_frontend/typing.mli index 87ba3eaba81..43e93f2dcfe 100644 --- a/src/mo_frontend/typing.mli +++ b/src/mo_frontend/typing.mli @@ -5,5 +5,5 @@ open Type open Scope val infer_prog : scope -> Syntax.prog -> (typ * scope) Diag.result -val check_library : scope -> Syntax.library -> scope Diag.result +val check_lib : scope -> Syntax.lib -> scope Diag.result val check_actors : scope -> Syntax.prog list -> unit Diag.result diff --git a/src/mo_interpreter/interpret.ml b/src/mo_interpreter/interpret.ml index 0ae643c0e00..5da3190e8f0 100644 --- a/src/mo_interpreter/interpret.ml +++ b/src/mo_interpreter/interpret.ml @@ -46,7 +46,7 @@ let adjoin_vals env ve = { env with vals = V.Env.adjoin env.vals ve } let empty_scope = { val_env = V.Env.empty; lib_env = V.Env.empty } -let library_scope f v scope : scope = +let lib_scope f v scope : scope = { scope with lib_env = V.Env.add f v scope.lib_env } let env_of_scope flags scope = @@ -883,21 +883,12 @@ let interpret_prog flags scope p : (V.value * scope) option = (* Libraries *) -let interpret_library flags scope (filename, p) : scope = +let interpret_lib flags scope lib : scope = let env = env_of_scope flags scope in trace_depth := 0; let vo = ref None in - let ve = ref V.Env.empty in Scheduler.queue (fun () -> - interpret_block env p.it (Some ve) (fun v -> vo := Some v) + interpret_exp env lib.it (fun v -> vo := Some v) ); Scheduler.run (); - let v = match p.it with - | [ { it = ExpD _ ; _ } ] -> - Lib.Option.value !vo - (* HACK: to be removed once we restrict libraries to expressions *) - | ds -> - V.Obj (V.Env.map Lib.Promise.value (!ve)) - in - library_scope filename v scope - + lib_scope lib.note (Lib.Option.value !vo) scope diff --git a/src/mo_interpreter/interpret.mli b/src/mo_interpreter/interpret.mli index eef3336211e..b1da709986d 100644 --- a/src/mo_interpreter/interpret.mli +++ b/src/mo_interpreter/interpret.mli @@ -21,4 +21,4 @@ val adjoin_scope : scope -> scope -> scope exception Trap of Source.region * string val interpret_prog : flags -> scope -> Syntax.prog -> (V.value * scope) option -val interpret_library : flags -> scope -> Syntax.library -> scope +val interpret_lib : flags -> scope -> Syntax.lib -> scope diff --git a/src/mo_types/scope.ml b/src/mo_types/scope.ml index e0de17da283..b6ab6467ae0 100644 --- a/src/mo_types/scope.ml +++ b/src/mo_types/scope.ml @@ -37,5 +37,5 @@ let adjoin scope1 scope2 = let adjoin_val_env scope ve = {scope with val_env = T.Env.adjoin scope.val_env ve} -let library f t = +let lib f t = { empty with lib_env = T.Env.add f t empty.lib_env } diff --git a/src/mo_types/scope.mli b/src/mo_types/scope.mli index dad521e2342..9e8101b4044 100644 --- a/src/mo_types/scope.mli +++ b/src/mo_types/scope.mli @@ -20,4 +20,4 @@ val empty : scope val adjoin : scope -> scope -> scope val adjoin_val_env : scope -> val_env -> scope -val library : string -> typ -> scope +val lib : string -> typ -> scope diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index 63665ba706f..c02d0ada6b0 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -109,14 +109,14 @@ type resolve_result = (Syntax.prog * Resolve_import.S.t) Diag.result let resolve_prog (prog, base) : resolve_result = Diag.map - (fun libraries -> (prog, libraries)) + (fun libs -> (prog, libs)) (Resolve_import.resolve !Flags.package_urls prog base) let resolve_progs = Diag.traverse resolve_prog -(* Typechecking *) +(* Checking *) let infer_prog senv prog : (Type.typ * Scope.scope) Diag.result = @@ -130,29 +130,27 @@ let infer_prog senv prog dump_prog Flags.dump_tc prog; | Error _ -> () end; - r + phase "Definedness" prog.Source.note; + Diag.bind r (fun t_sscope -> + Diag.bind (Definedness.check_prog prog) (fun () -> Diag.return t_sscope) + ) -let rec typecheck_progs senv progs : Scope.scope Diag.result = +let rec check_progs senv progs : Scope.scope Diag.result = match progs with | [] -> Diag.return senv | p::ps -> Diag.bind (infer_prog senv p) (fun (_t, sscope) -> let senv' = Scope.adjoin senv sscope in - typecheck_progs senv' ps + check_progs senv' ps ) -let typecheck_library senv filename prog : Scope.scope Diag.result = - phase "Checking" prog.Source.note; - Typing.check_library senv (filename, prog) - -(* Definedness checking *) - -let defindeness_prog prog : unit Diag.result = - phase "Definedness" prog.Source.note; - Definedness.check_prog prog +let check_lib senv lib : Scope.scope Diag.result = + phase "Checking" (Filename.basename lib.Source.note); + Diag.bind (Typing.check_lib senv lib) (fun sscope -> + phase "Definedness" (Filename.basename lib.Source.note); + Diag.bind (Definedness.check_lib lib) (fun () -> Diag.return sscope) + ) -let defindeness_progs progs : unit Diag.result = - Diag.traverse_ defindeness_prog progs (* Imported file loading *) @@ -165,13 +163,42 @@ When we load a declaration (i.e from the REPL), we also care about the type and the newly added scopes, so these are returned separately. *) +let is_import dec = + let open Source in let open Syntax in + match dec.it with + | ExpD e | LetD (_, e) -> (match e.it with ImportE _ -> true | _ -> false) + | _ -> false + +let is_module dec = + let open Source in let open Syntax in + match dec.it with + | ExpD e | LetD (_, e) -> + (match e.it with ObjE (s, _) -> s.it = Type.Module | _ -> false) + | _ -> false + +let rec lib_of_prog' imps at = function + | [d] when is_module d -> imps, d + | d::ds when is_import d -> lib_of_prog' (d::imps) at ds + | ds -> + let open Source in let open Syntax in + let fs = List.map (fun d -> {vis = Public @@ at; dec = d} @@ d.at) ds in + let obj = {it = ObjE (Type.Module @@ at, fs); at; note = empty_typ_note} in + imps, {it = ExpD obj; at; note = empty_typ_note} + +let lib_of_prog f prog = + let open Source in let open Syntax in + let imps, dec = lib_of_prog' [] prog.at prog.it in + let exp = {it = BlockE (List.rev imps @ [dec]); at = prog.at; note = empty_typ_note} in + {it = exp; at = prog.at; note = f} + + type load_result = - (Syntax.libraries * Syntax.prog list * Scope.scope) Diag.result + (Syntax.lib list * Syntax.prog list * Scope.scope) Diag.result type load_decl_result = - (Syntax.libraries * Syntax.prog * Scope.scope * Type.typ * Scope.scope) Diag.result + (Syntax.lib list * Syntax.prog * Scope.scope * Type.typ * Scope.scope) Diag.result -let chase_imports parsefn senv0 imports : (Syntax.libraries * Scope.scope) Diag.result = +let chase_imports parsefn senv0 imports : (Syntax.lib list * Scope.scope) Diag.result = (* This function loads and type-checkes the files given in `imports`, including any further dependencies. @@ -188,7 +215,7 @@ let chase_imports parsefn senv0 imports : (Syntax.libraries * Scope.scope) Diag. let open Resolve_import.S in let pending = ref empty in let senv = ref senv0 in - let libraries = ref [] in + let libs = ref [] in let rec go f = if Type.Env.mem f !senv.Scope.lib_env then @@ -204,38 +231,37 @@ let chase_imports parsefn senv0 imports : (Syntax.libraries * Scope.scope) Diag. Diag.bind (Static.prog prog) (fun () -> Diag.bind (Resolve_import.resolve !Flags.package_urls prog base) (fun more_imports -> Diag.bind (go_set more_imports) (fun () -> - Diag.bind (typecheck_library !senv f prog) (fun sscope -> - Diag.bind (defindeness_prog prog) (fun () -> - libraries := (f, prog) :: !libraries; (* NB: Conceptually an append *) + let lib = lib_of_prog f prog in + Diag.bind (check_lib !senv lib) (fun sscope -> + libs := lib :: !libs; (* NB: Conceptually an append *) senv := Scope.adjoin !senv sscope; pending := remove f !pending; Diag.return () - )))))) + ))))) end and go_set todo = Diag.traverse_ go (elements todo) in - Diag.map (fun () -> (List.rev !libraries, !senv)) (go_set imports) + Diag.map (fun () -> (List.rev !libs, !senv)) (go_set imports) let load_progs parsefn files senv : load_result = Diag.bind (Diag.traverse parsefn files) (fun parsed -> Diag.bind (resolve_progs parsed) (fun rs -> let progs' = List.map fst rs in - let libraries = + let libs = List.fold_left Resolve_import.S.union Resolve_import.S.empty (List.map snd rs) in - Diag.bind (chase_imports parsefn senv libraries) (fun (libraries, senv') -> - Diag.bind (typecheck_progs senv' progs') (fun senv'' -> - Diag.bind (defindeness_progs progs') (fun _ -> - Diag.return (libraries, progs', senv'') - ))))) + Diag.bind (chase_imports parsefn senv libs) (fun (libs, senv') -> + Diag.bind (check_progs senv' progs') (fun senv'' -> + Diag.return (libs, progs', senv'') + )))) let load_decl parse_one senv : load_decl_result = Diag.bind parse_one (fun parsed -> - Diag.bind (resolve_prog parsed) (fun (prog, libraries) -> - Diag.bind (chase_imports parse_file senv libraries) (fun (libraries, senv') -> + Diag.bind (resolve_prog parsed) (fun (prog, libs) -> + Diag.bind (chase_imports parse_file senv libs) (fun (libs, senv') -> Diag.bind (infer_prog senv' prog) (fun (t, sscope) -> let senv'' = Scope.adjoin senv' sscope in - Diag.return (libraries, prog, senv'', t, sscope) + Diag.return (libs, prog, senv'', t, sscope) )))) @@ -249,16 +275,16 @@ let interpret_prog denv prog : (Value.value * Interpret.scope) option = Profiler.process_prog_result result ; result -let rec interpret_libraries denv libraries : Interpret.scope = +let rec interpret_libs denv libs : Interpret.scope = let open Interpret in - match libraries with + match libs with | [] -> denv - | (f, p)::libs -> - phase "Interpreting" p.Source.note; + | lib::libs' -> + phase "Interpreting" (Filename.basename lib.Source.note); let flags = { trace = !Flags.trace; print_depth = !Flags.print_depth } in - let dscope = interpret_library flags denv (f, p) in + let dscope = interpret_lib flags denv lib in let denv' = adjoin_scope denv dscope in - interpret_libraries denv' libs + interpret_libs denv' libs' let rec interpret_progs denv progs : Interpret.scope option = match progs with @@ -273,8 +299,8 @@ let rec interpret_progs denv progs : Interpret.scope option = let interpret_files (senv0, denv0) files : (Scope.scope * Interpret.scope) option = Lib.Option.bind (Diag.flush_messages (load_progs parse_file files senv0)) - (fun (libraries, progs, senv1) -> - let denv1 = interpret_libraries denv0 libraries in + (fun (libs, progs, senv1) -> + let denv1 = interpret_libs denv0 libs in match interpret_progs denv1 progs with | None -> None | Some denv2 -> Some (senv1, denv2) @@ -290,7 +316,7 @@ let prelude_error phase (msgs : Diag.messages) = Diag.print_messages msgs; exit 1 -let typecheck_prelude () : Syntax.prog * stat_env = +let check_prelude () : Syntax.prog * stat_env = let lexer = Lexing.from_string Prelude.prelude in let parse = Parser.parse_prog in match parse_with Lexer.Privileged lexer parse prelude_name with @@ -303,7 +329,7 @@ let typecheck_prelude () : Syntax.prog * stat_env = let senv1 = Scope.adjoin senv0 sscope in prog, senv1 -let prelude, initial_stat_env = typecheck_prelude () +let prelude, initial_stat_env = check_prelude () let run_prelude () : dyn_env = match interpret_prog Interpret.empty_scope prelude with @@ -333,7 +359,7 @@ let check_string s name : check_result = let generate_idl files : Idllib.Syntax.prog Diag.result = Diag.bind (load_progs parse_file files initial_stat_env) - (fun (libraries, progs, senv) -> + (fun (libs, progs, senv) -> Diag.return (Mo_idl.Mo_to_idl.prog (progs, senv))) (* Running *) @@ -379,9 +405,9 @@ let run_stdin lexer (senv, denv) : env option = Diag.print_messages msgs; if !Flags.verbose then printf "\n"; None - | Ok ((libraries, prog, senv', t, sscope), msgs) -> + | Ok ((libs, prog, senv', t, sscope), msgs) -> Diag.print_messages msgs; - let denv' = interpret_libraries denv libraries in + let denv' = interpret_libs denv libs in match interpret_prog denv' prog with | None -> if !Flags.verbose then printf "\n"; @@ -424,9 +450,9 @@ let transform_if transform_name trans flag env prog name = if flag then transform transform_name trans env prog name else prog -let desugar env lib_env libraries progs name = +let desugar env lib_env libs progs name = phase "Desugaring" name; - let prog_ir' : Ir.prog = Lowering.Desugar.transform_graph lib_env libraries progs in + let prog_ir' : Ir.prog = Lowering.Desugar.transform_graph lib_env libs progs in dump_ir Flags.dump_lowering prog_ir'; if !Flags.check_ir then Check_ir.check_prog !Flags.verbose env "Desugaring" prog_ir'; @@ -476,39 +502,40 @@ let name_progs progs = then "empty" else (Lib.List.last progs).Source.note -let lower_prog mode senv lib_env libraries progs name = - let prog_ir = desugar senv lib_env libraries progs name in +let lower_prog mode senv lib_env libs progs name = + let prog_ir = desugar senv lib_env libs progs name in let prog_ir = await_lowering !Flags.await_lowering initial_stat_env prog_ir name in let prog_ir = async_lowering mode !Flags.async_lowering initial_stat_env prog_ir name in let prog_ir = tailcall_optimization true initial_stat_env prog_ir name in let prog_ir = show_translation true initial_stat_env prog_ir name in prog_ir -let compile_prog mode do_link lib_env libraries progs : Wasm_exts.CustomModule.extended_module = +let compile_prog mode do_link lib_env libs progs : Wasm_exts.CustomModule.extended_module = let prelude_ir = Lowering.Desugar.transform prelude in let name = name_progs progs in - let prog_ir = lower_prog mode initial_stat_env lib_env libraries progs name in + let prog_ir = lower_prog mode initial_stat_env lib_env libs progs name in phase "Compiling" name; let rts = if do_link then Some (load_as_rts ()) else None in Codegen.Compile.compile mode name rts prelude_ir [prog_ir] let compile_files mode do_link files : compile_result = - Diag.bind (load_progs parse_file files initial_stat_env) (fun (libraries, progs, senv) -> - Diag.bind (Typing.check_actors senv progs) (fun () -> - Diag.return (compile_prog mode do_link senv.Scope.lib_env libraries progs))) + Diag.bind (load_progs parse_file files initial_stat_env) + (fun (libs, progs, senv) -> + Diag.bind (Typing.check_actors senv progs) (fun () -> + Diag.return (compile_prog mode do_link senv.Scope.lib_env libs progs))) let compile_string mode s name : compile_result = Diag.bind (load_decl (parse_string name s) initial_stat_env) - (fun (libraries, prog, senv, _t, _sscope) -> - Diag.return (compile_prog mode false senv.Scope.lib_env libraries [prog])) + (fun (libs, prog, senv, _t, _sscope) -> + Diag.return (compile_prog mode false senv.Scope.lib_env libs [prog])) (* Interpretation (IR) *) -let interpret_ir_prog inp_env libraries progs = +let interpret_ir_prog inp_env libs progs = let prelude_ir = Lowering.Desugar.transform prelude in let name = name_progs progs in Flags.compile_mode := Flags.WasmMode; (* REMOVE THIS HACK *) - let prog_ir = lower_prog Flags.WasmMode initial_stat_env inp_env libraries progs name in + let prog_ir = lower_prog Flags.WasmMode initial_stat_env inp_env libs progs name in phase "Interpreting" name; let open Interpret_ir in let flags = { trace = !Flags.trace; print_depth = !Flags.print_depth } in @@ -520,5 +547,5 @@ let interpret_ir_prog inp_env libraries progs = let interpret_ir_files files = Lib.Option.map - (fun (libraries, progs, senv) -> interpret_ir_prog senv.Scope.lib_env libraries progs) + (fun (libs, progs, senv) -> interpret_ir_prog senv.Scope.lib_env libs progs) (Diag.flush_messages (load_progs parse_file files initial_stat_env)) diff --git a/src/pipeline/pipeline.mli b/src/pipeline/pipeline.mli index 16b874c6c24..664d38bc30e 100644 --- a/src/pipeline/pipeline.mli +++ b/src/pipeline/pipeline.mli @@ -14,7 +14,7 @@ val generate_idl : string list -> Idllib.Syntax.prog Diag.result val initial_stat_env : Scope.scope val chase_imports : parse_fn -> Scope.scope -> Resolve_import.S.t -> - (Syntax.libraries * Scope.scope) Diag.result + (Syntax.lib list * Scope.scope) Diag.result val run_files : string list -> unit option val interpret_ir_files : string list -> unit option diff --git a/stdlib/assocList.mo b/stdlib/assocList.mo index 01a9fa10b61..693b595d124 100644 --- a/stdlib/assocList.mo +++ b/stdlib/assocList.mo @@ -1,3 +1,5 @@ +import List "list.mo"; + module { /** @@ -10,8 +12,6 @@ Implements the same interface as `Trie`, but as a linked-list of key-value pairs */ -import List "list.mo"; - // polymorphic association linked lists between keys and values public type AssocList = List.List<(K,V)>; diff --git a/stdlib/docTable.mo b/stdlib/docTable.mo index 2dc2201623f..4a04cc405b0 100644 --- a/stdlib/docTable.mo +++ b/stdlib/docTable.mo @@ -1,3 +1,8 @@ +import Hash "hash.mo"; + +//import Trie "trie.mo"; +import Trie "trie2.mo"; + module { /** @@ -43,11 +48,6 @@ type information. */ -import Hash "hash.mo"; - -//import Trie "trie.mo"; -import Trie "trie2.mo"; - public type Hash = Hash.Hash; public type Trie = Trie.Trie; public type Key = Trie.Key; diff --git a/stdlib/examples/actorspec/src/ActorSpec.mo b/stdlib/examples/actorspec/src/ActorSpec.mo index 3f8bed143c9..a3e4bf81668 100644 --- a/stdlib/examples/actorspec/src/ActorSpec.mo +++ b/stdlib/examples/actorspec/src/ActorSpec.mo @@ -1,8 +1,8 @@ -module { - import Array "../../../array.mo"; - import Int "../../../int.mo"; - import Text "../../../text.mo"; +import Array "../../../array.mo"; +import Int "../../../int.mo"; +import Text "../../../text.mo"; +module { public type Group = { name : Text; groups : [Group]; diff --git a/stdlib/examples/produce-exchange/profileActor.mo b/stdlib/examples/produce-exchange/profileActor.mo index 0c788d1610e..79d5f62486b 100644 --- a/stdlib/examples/produce-exchange/profileActor.mo +++ b/stdlib/examples/produce-exchange/profileActor.mo @@ -1,5 +1,5 @@ -let T = (import "serverTypes.mo"); -let Model = (import "serverModel.mo"); +import T = "serverTypes.mo"; +import Model = "serverModel.mo"; actor server { // morally: loadQuery (region_count:Nat, scale_factor:Nat) { diff --git a/stdlib/examples/produce-exchange/serverActor.mo b/stdlib/examples/produce-exchange/serverActor.mo index bd092a233bf..6f7e486bedd 100644 --- a/stdlib/examples/produce-exchange/serverActor.mo +++ b/stdlib/examples/produce-exchange/serverActor.mo @@ -11,9 +11,9 @@ import L = "serverLang.mo"; import Model = "serverModel.mo"; import Result = "../../result.mo"; -let Trie = (import "../../trie2.mo"); +import Trie = "../../trie2.mo"; +import List = "../../list.mo"; -let List = (import "../../list.mo"); type List = List.List; type Result = Result.Result; diff --git a/stdlib/examples/produce-exchange/serverLang.mo b/stdlib/examples/produce-exchange/serverLang.mo index bdd64ad2ae1..5ce8f33d1b3 100644 --- a/stdlib/examples/produce-exchange/serverLang.mo +++ b/stdlib/examples/produce-exchange/serverLang.mo @@ -1,3 +1,7 @@ +import Result = "../../result.mo"; +import T = "serverTypes.mo"; + + module { /** @@ -8,9 +12,6 @@ module { */ -import Result = "../../result.mo"; -import T = "serverTypes.mo"; - public type Result = Result.Result; /** diff --git a/stdlib/examples/produce-exchange/serverModel.mo b/stdlib/examples/produce-exchange/serverModel.mo index 4e5c8782ca4..889f0b44c61 100644 --- a/stdlib/examples/produce-exchange/serverModel.mo +++ b/stdlib/examples/produce-exchange/serverModel.mo @@ -1,3 +1,18 @@ +import P = "../../prelude.mo"; + +import T = "serverTypes.mo"; +import L = "serverLang.mo"; +import M = "serverModelTypes.mo"; + +import List = "../../list.mo"; +import Hash_ = "../../hash.mo"; +import Option = "../../option.mo"; +import Trie = "../../trie2.mo"; + +import DT = "../../docTable.mo"; +import Result = "../../result.mo"; + + module { /** @@ -22,21 +37,11 @@ uses are is not. */ -import P = "../../prelude.mo"; - -import T = "serverTypes.mo"; -import L = "serverLang.mo"; -import M = "serverModelTypes.mo"; - -public let List = (import "../../list.mo"); public type List = List.List; -public let Hash = (import "../../hash.mo").BitVec; +public let Hash = Hash_.BitVec; public type Hash = Hash.t; -import Option = "../../option.mo"; -import Trie = "../../trie2.mo"; - public type Trie = Trie.Trie; public type TrieBuild = Trie.Build.TrieBuild; public type Key = Trie.Key; @@ -47,11 +52,9 @@ public let Table = Trie; public type Map = Trie.Trie; public let Map = Trie; -import DT = "../../docTable.mo"; public let DocTable = DT.DocTable; public type DocTable = DT.DocTable; -import Result = "../../result.mo"; public type Result = Result.Result; public type RouteInventoryMap = Trie<(T.RouteId, T.InventoryId), (M.RouteDoc, M.InventoryDoc)>; diff --git a/stdlib/examples/produce-exchange/serverModelTypes.mo b/stdlib/examples/produce-exchange/serverModelTypes.mo index 6a499eb8fca..9771661ff3e 100644 --- a/stdlib/examples/produce-exchange/serverModelTypes.mo +++ b/stdlib/examples/produce-exchange/serverModelTypes.mo @@ -1,3 +1,8 @@ +import T = "serverTypes.mo"; +import Trie = "../../trie2.mo"; +import DocTable = "../../docTable.mo"; + + module { /** @@ -33,11 +38,7 @@ Representation */ -import T = "serverTypes.mo"; - -import Trie = "../../trie2.mo"; public type Trie = Trie.Trie; - public type Map = Trie; public let Map = Trie; @@ -97,7 +98,6 @@ internal sharing: */ -public let DocTable = (import "../../docTable.mo"); public type DocTable = DocTable.DocTable; /** diff --git a/stdlib/examples/produce-exchange/test/evalBulk.mo b/stdlib/examples/produce-exchange/test/evalBulk.mo index 8ddc4ea9da6..7c0d0005bb9 100644 --- a/stdlib/examples/produce-exchange/test/evalBulk.mo +++ b/stdlib/examples/produce-exchange/test/evalBulk.mo @@ -1,7 +1,7 @@ -let T = (import "../serverTypes.mo"); -let A = (import "../serverActor.mo"); -let Result = (import "../../../result.mo"); -let Option = (import "../../../option.mo"); +import T = "../serverTypes.mo"; +import A = "../serverActor.mo"; +import Result = "../../../result.mo"; +import Option = "../../../option.mo"; func printEntityCount(entname:Text, count:Nat) { print ("- " # entname # " count: "); diff --git a/stdlib/examples/produce-exchange/test/producerRemInventory.mo b/stdlib/examples/produce-exchange/test/producerRemInventory.mo index 8792d4545ef..f205e62d362 100644 --- a/stdlib/examples/produce-exchange/test/producerRemInventory.mo +++ b/stdlib/examples/produce-exchange/test/producerRemInventory.mo @@ -1,7 +1,7 @@ -let T = (import "../serverTypes.mo"); -let A = (import "../serverActor.mo"); -let Result = (import "../../../result.mo"); -let Option = (import "../../../option.mo"); +import T = "../serverTypes.mo"; +import A = "../serverActor.mo"; +import Result = "../../../result.mo"; +import Option = "../../../option.mo"; func printEntityCount(entname:Text, count:Nat) { print ("- " # entname # " count: "); diff --git a/stdlib/examples/produce-exchange/test/profileFastCounts.mo b/stdlib/examples/produce-exchange/test/profileFastCounts.mo index a194af18ae2..9ec1c21ad2f 100644 --- a/stdlib/examples/produce-exchange/test/profileFastCounts.mo +++ b/stdlib/examples/produce-exchange/test/profileFastCounts.mo @@ -2,8 +2,8 @@ // we correlate these numbers with times that we // measure elsewhere, where these numbers are not available. -let T = (import "../serverTypes.mo"); -let Model = (import "../serverModel.mo"); +import T = "../serverTypes.mo"; +import Model = "../serverModel.mo"; let m = Model.Model(); diff --git a/stdlib/examples/produce-exchange/test/retailerReserveMany.mo b/stdlib/examples/produce-exchange/test/retailerReserveMany.mo index dff476cbd6f..051c613ec47 100644 --- a/stdlib/examples/produce-exchange/test/retailerReserveMany.mo +++ b/stdlib/examples/produce-exchange/test/retailerReserveMany.mo @@ -1,7 +1,7 @@ -let T = (import "../serverTypes.mo"); -let A = (import "../serverActor.mo"); -let Result = (import "../../../result.mo"); -let Option = (import "../../../option.mo"); +import T = "../serverTypes.mo"; +import A = "../serverActor.mo"; +import Result = "../../../result.mo"; +import Option = "../../../option.mo"; func printEntityCount(entname:Text, count:Nat) { print ("- " # entname # " count: "); diff --git a/stdlib/examples/rx/src/Observable.mo b/stdlib/examples/rx/src/Observable.mo index bf8d830324a..19be16008f9 100644 --- a/stdlib/examples/rx/src/Observable.mo +++ b/stdlib/examples/rx/src/Observable.mo @@ -1,7 +1,7 @@ -module { - import Disposable "Disposable.mo"; - import Observer "Observer.mo"; +import Disposable "Disposable.mo"; +import Observer "Observer.mo"; +module { type Subscriber = Observer.Type -> Disposable.Type; public class Type(subscribe_ : Subscriber) { diff --git a/stdlib/examples/rx/src/Observer.mo b/stdlib/examples/rx/src/Observer.mo index 0812f3c273b..c7e32d8a0d3 100644 --- a/stdlib/examples/rx/src/Observer.mo +++ b/stdlib/examples/rx/src/Observer.mo @@ -1,6 +1,6 @@ -module { - import Event "Event.mo"; +import Event "Event.mo"; +module { public type EventHandler = Event.Type -> (); public class Type(handler_ : EventHandler) { diff --git a/stdlib/examples/rx/src/Rx.mo b/stdlib/examples/rx/src/Rx.mo index a0bb5ec6605..d5faf0ac9bd 100644 --- a/stdlib/examples/rx/src/Rx.mo +++ b/stdlib/examples/rx/src/Rx.mo @@ -1,4 +1,11 @@ -import Disposable = "Disposable.mo"; -import Event = "Event.mo"; -import Observable = "Observable.mo"; -import Observer = "Observer.mo"; +import DisposableLib = "Disposable.mo"; +import EventLib = "Event.mo"; +import ObservableLib = "Observable.mo"; +import ObserverLib = "Observer.mo"; + +module { + public let Disposable = DisposableLib; + public let Event = EventLib; + public let Observable = ObservableLib; + public let Observer = ObserverLib; +}; diff --git a/stdlib/int.mo b/stdlib/int.mo index cbb1fc2ab33..d7a6432c505 100644 --- a/stdlib/int.mo +++ b/stdlib/int.mo @@ -1,6 +1,6 @@ -module { - import Prelude "prelude.mo"; +import Prelude "prelude.mo"; +module { public func add(x : Int, y : Int) : Int { x + y; }; diff --git a/stdlib/listTest.mo b/stdlib/listTest.mo index 92e8091a648..d33beabb25e 100644 --- a/stdlib/listTest.mo +++ b/stdlib/listTest.mo @@ -1,6 +1,7 @@ -type X = Nat; import List "list.mo"; +type X = Nat; + func opnatEq(a : ?Nat, b : ?Nat) : Bool { switch (a, b) { case (null, null) { true }; diff --git a/stdlib/nat.mo b/stdlib/nat.mo index 365250d31fa..8e6068bd388 100644 --- a/stdlib/nat.mo +++ b/stdlib/nat.mo @@ -1,7 +1,7 @@ -module { - import Int "int.mo"; - import Prelude "prelude.mo"; +import Int "int.mo"; +import Prelude "prelude.mo"; +module { public func add(x : Nat, y : Nat) : Nat { x + y; }; diff --git a/stdlib/option.mo b/stdlib/option.mo index adb2b3d3209..a980e9caa76 100644 --- a/stdlib/option.mo +++ b/stdlib/option.mo @@ -1,3 +1,5 @@ +import P "prelude.mo"; + module { /** @@ -5,8 +7,6 @@ Functions for Option types. */ -import P "prelude.mo"; - public type t = ?A; /*** diff --git a/stdlib/result.mo b/stdlib/result.mo index 017e3cdadee..1d8b669ef25 100644 --- a/stdlib/result.mo +++ b/stdlib/result.mo @@ -1,6 +1,6 @@ -module { import P "prelude.mo"; +module { /** Result diff --git a/stdlib/set.mo b/stdlib/set.mo index 88003b68a71..24a308d5f42 100644 --- a/stdlib/set.mo +++ b/stdlib/set.mo @@ -17,10 +17,10 @@ in the future, we might avoid this via https://dfinity.atlassian.net/browse/AST-32 */ -module { import Trie "trie2.mo"; import Hash "hash.mo"; +module { public type Hash = Hash.Hash; public type Set = Trie.Trie; diff --git a/stdlib/trie.mo b/stdlib/trie.mo index a714ca7dbd9..4f2a56b0560 100644 --- a/stdlib/trie.mo +++ b/stdlib/trie.mo @@ -1,3 +1,8 @@ +import H "hash.mo"; +import List "list.mo"; +import AssocList "assocList.mo"; + + module { /** @@ -61,14 +66,10 @@ See the full details in the definitions below: */ -import H "hash.mo"; public let Hash = H.BitVec; public type Hash = Hash.t; -import List "list.mo"; public type List = List.List; - -import AssocList "assocList.mo"; public type AssocList = AssocList.AssocList; public let HASH_BITS = 4; diff --git a/stdlib/trie2.mo b/stdlib/trie2.mo index 9c73b6a14e9..ca4654ac6e5 100644 --- a/stdlib/trie2.mo +++ b/stdlib/trie2.mo @@ -1,4 +1,11 @@ -module{ +import P "prelude.mo"; +import Option "option.mo"; +import H "hash.mo"; + +import List "list.mo"; +import AssocList "assocList.mo"; + +module { /** Hash tries @@ -73,18 +80,10 @@ public let MAX_LEAF_COUNT = 8; // <-- beats both 4 and 16 for me, now //let MAX_LEAF_COUNT = 16; //let MAX_LEAF_COUNT = 32; -import P "prelude.mo"; - -import Option "option.mo"; - -import H "hash.mo"; public let Hash = H.BitVec; public type Hash = Hash.t; -import List "list.mo"; public type List = List.List; - -import AssocList "assocList.mo"; public type AssocList = AssocList.AssocList; /** A `Key` for the trie has an associated hash value */ diff --git a/test/lsp-int/Main.hs b/test/lsp-int/Main.hs index d39377ffaa6..809ede13197 100644 --- a/test/lsp-int/Main.hs +++ b/test/lsp-int/Main.hs @@ -73,6 +73,7 @@ main = handleHUnitFailure $ do runSession as_ide fullCaps "." $ do initRes <- initializeResponse doc <- openDoc "ListClient.mo" "motoko" +{- TODO(kritzcreek): Fix me and reactivate hoverTestCase doc (Position 13 11) @@ -94,6 +95,7 @@ main = handleHUnitFailure $ do -- 14 | List.pus| (Position 13 14) [("push",Just "(T, List) -> List")] +-} closeDoc doc doc <- openDoc "ListClient.mo" "motoko" -- 1 | module { diff --git a/test/lsp-int/test-project/ListClient.mo b/test/lsp-int/test-project/ListClient.mo index a749967a85e..baa04f1246d 100644 --- a/test/lsp-int/test-project/ListClient.mo +++ b/test/lsp-int/test-project/ListClient.mo @@ -1,8 +1,8 @@ -module { - import List "lib/list.mo"; - import Option "lib/option.mo"; - import P "lib/prelude.mo"; +import List "lib/list.mo"; +import Option "lib/option.mo"; +import P "lib/prelude.mo"; +module { public type Stack = List.List; let (a, b) = (1, 2); diff --git a/test/lsp-int/test-project/app.mo b/test/lsp-int/test-project/app.mo index e5e2a89a69b..b4d2104cd37 100644 --- a/test/lsp-int/test-project/app.mo +++ b/test/lsp-int/test-project/app.mo @@ -1,7 +1,6 @@ -actor { - - import Stack "ListClient.mo"; +import Stack "ListClient.mo"; +actor { func main(): () { let st = Stack.empty(); let newst = Stack.push(0, st); diff --git a/test/lsp-int/test-project/lib/ListFuncs.mo b/test/lsp-int/test-project/lib/ListFuncs.mo index dc430e44e93..e25064736d8 100644 --- a/test/lsp-int/test-project/lib/ListFuncs.mo +++ b/test/lsp-int/test-project/lib/ListFuncs.mo @@ -1,6 +1,6 @@ -module { - import List = "./ListLib.mo"; +import List = "./ListLib.mo"; +module { public func singleton(x: T): List.List = List.cons(x, List.nil()); diff --git a/test/lsp-int/test-project/lib/option.mo b/test/lsp-int/test-project/lib/option.mo index adb2b3d3209..a980e9caa76 100644 --- a/test/lsp-int/test-project/lib/option.mo +++ b/test/lsp-int/test-project/lib/option.mo @@ -1,3 +1,5 @@ +import P "prelude.mo"; + module { /** @@ -5,8 +7,6 @@ Functions for Option types. */ -import P "prelude.mo"; - public type t = ?A; /*** diff --git a/test/repl/lib/a.mo b/test/repl/lib/a.mo index 1927c9a60c6..7aa0183b2a5 100644 --- a/test/repl/lib/a.mo +++ b/test/repl/lib/a.mo @@ -1 +1,3 @@ -import "c.mo" +import C "c.mo"; + +let i = C.i; diff --git a/test/repl/lib/b.mo b/test/repl/lib/b.mo index 1927c9a60c6..b07786fc5c0 100644 --- a/test/repl/lib/b.mo +++ b/test/repl/lib/b.mo @@ -1 +1,2 @@ -import "c.mo" +import C "c.mo"; +let i = C.i; diff --git a/test/repl/lib/c.mo b/test/repl/lib/c.mo index d81cc0710eb..c561a109ca6 100644 --- a/test/repl/lib/c.mo +++ b/test/repl/lib/c.mo @@ -1 +1 @@ -42 +let i = 42 diff --git a/test/repl/lib/nested.mo b/test/repl/lib/nested.mo index 92801627663..16a66c3d2f6 100644 --- a/test/repl/lib/nested.mo +++ b/test/repl/lib/nested.mo @@ -1,2 +1,4 @@ import A "nested/a.mo"; -import "nested/b.mo" +import "nested/b.mo"; + +let i = A.i; diff --git a/test/repl/lib/nested/a.mo b/test/repl/lib/nested/a.mo index d81cc0710eb..c561a109ca6 100644 --- a/test/repl/lib/nested/a.mo +++ b/test/repl/lib/nested/a.mo @@ -1 +1 @@ -42 +let i = 42 diff --git a/test/repl/lib/nested/b.mo b/test/repl/lib/nested/b.mo index 0419dbf6552..81829339bc9 100644 --- a/test/repl/lib/nested/b.mo +++ b/test/repl/lib/nested/b.mo @@ -1,3 +1,4 @@ +import A "./a.mo"; module { - import "./a.mo"; + public let i = A.i } diff --git a/test/repl/ok/double-import.stdout.ok b/test/repl/ok/double-import.stdout.ok index f3cfb0ebca8..e4f8aebbd96 100644 --- a/test/repl/ok/double-import.stdout.ok +++ b/test/repl/ok/double-import.stdout.ok @@ -4,16 +4,18 @@ Motoko 0.1 interpreter -- Checking empty.mo: -- Definedness empty.mo: -- Checking stdin: +-- Definedness stdin: -- Interpreting empty.mo: -- Interpreting stdin: -- Finished stdin: -{} : module {} +let anon-import-1.1 : module {} = {} -- Parsing stdin: > -- Checking stdin: +-- Definedness stdin: -- Interpreting stdin: -- Finished stdin: -{} : module {} +let anon-import-2.1 : module {} = {} -- Parsing stdin: > diff --git a/test/repl/ok/file-and-repl.stdout.ok b/test/repl/ok/file-and-repl.stdout.ok index 9a7d8f3cb9f..38cec6e903d 100644 --- a/test/repl/ok/file-and-repl.stdout.ok +++ b/test/repl/ok/file-and-repl.stdout.ok @@ -5,6 +5,7 @@ Motoko 0.1 interpreter -- Interpreting 63: -- Parsing stdin: > -- Checking stdin: +-- Definedness stdin: -- Interpreting stdin: -- Finished stdin: diff --git a/test/repl/ok/triangle-import.stdout.ok b/test/repl/ok/triangle-import.stdout.ok index 4479154f8d5..7b65ff402b1 100644 --- a/test/repl/ok/triangle-import.stdout.ok +++ b/test/repl/ok/triangle-import.stdout.ok @@ -7,37 +7,41 @@ Motoko 0.1 interpreter -- Checking b.mo: -- Definedness b.mo: -- Checking stdin: +-- Definedness stdin: -- Interpreting c.mo: -- Interpreting b.mo: -- Interpreting stdin: -- Finished stdin: -42 : Nat +let anon-import-1.1 : module {i : Nat} = {i = 42} -- Parsing stdin: > -- Parsing a.mo: -- Checking a.mo: -- Definedness a.mo: -- Checking stdin: +-- Definedness stdin: -- Interpreting a.mo: -- Interpreting stdin: -- Finished stdin: -42 : Nat +let anon-import-2.1 : module {i : Nat} = {i = 42} -- Parsing stdin: > -- Checking stdin: +-- Definedness stdin: -- Interpreting stdin: -- Finished stdin: -42 : Nat +let anon-import-3.1 : module {i : Nat} = {i = 42} -- Parsing stdin: > -- Parsing triangle.mo: -- Checking triangle.mo: -- Definedness triangle.mo: -- Checking stdin: +-- Definedness stdin: -- Interpreting triangle.mo: -- Interpreting stdin: -- Finished stdin: -42 : Nat +let anon-import-4.1 : module {} = {} -- Parsing stdin: > diff --git a/test/run/import-module.mo b/test/run/import-module.mo index f8f438de04c..d6faf86caab 100644 --- a/test/run/import-module.mo +++ b/test/run/import-module.mo @@ -1,3 +1,3 @@ -let L = import "lib/ListM.mo"; +import L = "lib/ListM.mo"; type stack = L.List; let s = L.cons(1, L.nil()); diff --git a/test/run/import.mo b/test/run/import.mo index 2c15c064d2a..6967a661ef8 100644 --- a/test/run/import.mo +++ b/test/run/import.mo @@ -1,2 +1,5 @@ -assert ((import "lib/hello-string.mo") == "Hello!"); -assert ((import "lib/dir") == "Hello!"); +import A "lib/hello-string.mo"; +import B "lib/dir"; + +assert (A.hello == "Hello!"); +assert (B.hello == "Hello!"); diff --git a/test/run/lib/dir/lib.mo b/test/run/lib/dir/lib.mo index 5af1ebfc9f1..b93139c6937 100644 --- a/test/run/lib/dir/lib.mo +++ b/test/run/lib/dir/lib.mo @@ -1 +1 @@ -"Hello!" +let hello = "Hello!"; diff --git a/test/run/lib/hello-string.mo b/test/run/lib/hello-string.mo index 5af1ebfc9f1..b93139c6937 100644 --- a/test/run/lib/hello-string.mo +++ b/test/run/lib/hello-string.mo @@ -1 +1 @@ -"Hello!" +let hello = "Hello!"; From 3eb3dda521dfb6a60dc9b802c21e1aa6880db0ab Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 31 Oct 2019 18:25:41 +0100 Subject: [PATCH 0502/1176] ICCallPrim: Continuations are local functions this is more in line with the IC's interface, which wants a function pointer, not a (platform-level) `funcref`. --- src/codegen/compile.ml | 57 +++++++++++++++++++++--- src/ir_def/check_ir.ml | 4 +- src/ir_def/construct.ml | 7 --- src/ir_def/construct.mli | 1 - src/ir_passes/async.ml | 7 +-- test/run-drun/ok/ic-calls.wasm.stderr.ok | 2 +- 6 files changed, 58 insertions(+), 20 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index a9ee1b2979b..30a78b75980 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -232,6 +232,7 @@ module E = struct let add_dfinity_type (env : t) e = assert (mode env = Flags.AncientMode); + (* ignore duplicates? or use a map? but who cares, is for ancient system only *) ignore (reg env.dfinity_types e) let add_global (env : t) name g = @@ -4840,7 +4841,8 @@ module FuncDec = struct let call_ty env = E.func_type env (FuncType ([I32Type; I32Type; I32Type], [])) - (* Expects reply callback, databuf and elembuf on the stack, in serialized form. *) + + (* Expects reply callback funcref, databuf and elembuf on the stack, in serialized form. *) let call_await_funcref env get_ref = compile_unboxed_const tmp_table_slot ^^ (* slot number *) get_ref ^^ (* the unboxed funcref *) @@ -5155,6 +5157,47 @@ module FuncDec = struct ClosureTable.remember_closure env ^^ Dfinity.system_call env "func" "bind_i32" + (* Wraps a local closure in a shared function that does serialization and + takes care of the reply global *) + (* Need this function once per type, so we can share based on ts *) + let callback_to_funcref env ts get_closure = + assert (E.mode env = Flags.AncientMode); + let name = "@callback<" ^ Serialization.typ_id (Type.Tup ts) ^ ">" in + Func.define_built_in env name ["clos", I32Type; "reply", I32Type; "databuf", I32Type; "elembuf", I32Type] [] (fun env -> + let get_reply = G.i (LocalGet (nr 1l)) in + let get_databuf = G.i (LocalGet (nr 2l)) in + let get_elembuf = G.i (LocalGet (nr 3l)) in + + (* Restore memory *) + OrthogonalPersistence.restore_mem env ^^ + + (* Story reply contiuation *) + get_reply ^^ Dfinity.set_reply_cont env ^^ + + (* Look up closure *) + let (set_closure, get_closure) = new_local env "closure" in + G.i (LocalGet (nr 0l)) ^^ + ClosureTable.recall_closure env ^^ (* At this point we can remove the closure *) + set_closure ^^ + get_closure ^^ + + (* Deserialize arguments *) + get_databuf ^^ get_elembuf ^^ + Serialization.deserialize env ts ^^ + + get_closure ^^ + Closure.call_closure env (List.length ts) 0 ^^ + + message_cleanup env (Type.Shared Type.Write) + ); + declare_dfinity_type env true true (E.built_in env name); + compile_unboxed_const (E.built_in env name) ^^ + Dfinity.system_call env "func" "externalize" ^^ + get_closure ^^ ClosureTable.remember_closure env ^^ + Dfinity.system_call env "func" "bind_i32" ^^ + Dfinity.get_reply_cont env ^^ + Dfinity.system_call env "func" "bind_ref" + let lit env ae how name sort control free_vars args mk_body ret_tys at = let captured = List.filter (VarEnv.needs_capture ae) free_vars in @@ -6399,7 +6442,7 @@ and compile_exp (env : E.t) ae exp = | ICCallPrim, [f;e;k;r] -> SR.unit, begin match E.mode env with | Flags.ICMode -> - todo_trap env "compile_exp" (Arrange_ir.exp exp) + assert false (* not implemented yet *) | Flags.AncientMode -> let (set_funcref, get_funcref) = new_local env "funcref" in let (set_arg, get_arg) = new_local env "arg" in @@ -6409,15 +6452,17 @@ and compile_exp (env : E.t) ae exp = set_funcref ^^ compile_exp_as env ae SR.Vanilla e ^^ set_arg ^^ - compile_exp_as env ae SR.UnboxedReference k ^^ set_k ^^ + compile_exp_as env ae SR.Vanilla k ^^ set_k ^^ (* We drop the reject continuation on the ancient platform, but still need to evaluate it *) let (r_sr, code_r) = compile_exp env ae r in code_r ^^ StackRep.drop env r_sr ^^ - get_k ^^ Dfinity.get_reply_cont env ^^ Dfinity.system_call env "func" "bind_ref" ^^ - let _, _, _, ts, _ = Type.as_func f.note.note_typ in - get_arg ^^ Serialization.serialize env ts ^^ + (* TBR: Can we do better than using the notes? *) + let _, _, _, ts1, _ = Type.as_func f.note.note_typ in + let _, _, _, ts2, _ = Type.as_func k.note.note_typ in + FuncDec.callback_to_funcref env ts2 get_k ^^ + get_arg ^^ Serialization.serialize env ts1 ^^ FuncDec.call_await_funcref env get_funcref | _ -> assert false end diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 1ec3eea19b6..668f8dc20d5 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -385,13 +385,13 @@ let rec check_exp env (exp:Ir.exp) : unit = typ exp2 <: t_arg; check_concrete env exp.at t_arg; (match T.promote (typ k) with - | T.Func (T.Shared T.Write, T.Replies, [], t_rets, []) -> + | T.Func (T.Local, T.Returns, [], t_rets, []) -> check_concrete env exp.at (T.seq t_rets) | T.Non -> () (* dead code, not much to check here *) | t -> error env k.at "expected continuation type, but expression produces type\n %s" (T.string_of_typ_expand t)); - typ r <: T.Func (T.Shared T.Write, T.Replies, [], [T.text], []); + typ r <: T.Func (T.Local, T.Returns, [], [T.text], []); | T.Non -> () (* dead code, not much to check here *) | _ -> error env exp1.at "expected function type, but expression produces type\n %s" diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index 075b57e817a..25b7c211e6e 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -464,13 +464,6 @@ let (-->*) xs exp = let fun_ty = T.Func (T.Local, T.Returns, [], List.map typ xs, T.as_seq (typ exp)) in nary_funcE "$lambda" fun_ty xs exp - -(* n-ary shared lambda, used for callbacks in async *) -let (-@>*) xs exp = - let fun_ty = T.Func (T.Shared T.Write, T.Replies, [], List.map typ xs, T.as_seq (typ exp)) in - nary_funcE "$lambda" fun_ty xs exp - - (* Lambda application (monomorphic) *) let ( -*- ) exp1 exp2 = diff --git a/src/ir_def/construct.mli b/src/ir_def/construct.mli index b0afb8dab5f..cffd0af420f 100644 --- a/src/ir_def/construct.mli +++ b/src/ir_def/construct.mli @@ -104,5 +104,4 @@ val seqE : exp list -> exp val (-->) : var -> exp -> exp val (-->*) : var list -> exp -> exp (* n-ary local *) -val (-@>*) : var list -> exp -> exp (* n-ary shared *) val (-*-) : exp -> exp -> exp (* application *) diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index 1cd621b36fa..dd866f725a0 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -133,7 +133,7 @@ module Transform(Platform : sig val platform : platform end) = struct let seq_of_v' = tupE (List.mapi (fun i _ -> projE v' i) ts) in [k';r'] -->* (unary_async -*- (tupE[([v'] -->* (k' -*- seq_of_v'));r'])) in - (* construct the n-ary reply message that sends a sequence of values to fulfill the async *) + (* construct the n-ary reply callback that sends a sequence of values to fulfill the async *) let nary_reply = let vs,seq_of_vs = match ts1 with @@ -144,11 +144,12 @@ module Transform(Platform : sig val platform : platform end) = struct let vs = fresh_vars "rep" ts in vs, tupE vs in - vs -@>* (unary_fulfill -*- seq_of_vs) + vs -->* (unary_fulfill -*- seq_of_vs) in + (* construct the n-ary reject callback *) let nary_reject = let v = fresh_var "msg" T.text in - [v] -@>* (fail -*- (make_errorE (sys_error_codeE()) v)) + [v] -->* (fail -*- (make_errorE (sys_error_codeE()) v)) in let async,reply,reject = fresh_var "async" (typ nary_async), diff --git a/test/run-drun/ok/ic-calls.wasm.stderr.ok b/test/run-drun/ok/ic-calls.wasm.stderr.ok index 16bed23dc0f..85d6295d888 100644 --- a/test/run-drun/ok/ic-calls.wasm.stderr.ok +++ b/test/run-drun/ok/ic-calls.wasm.stderr.ok @@ -1 +1 @@ -Fatal error: exception "Assert_failure codegen/compile.ml:4920:4" +Fatal error: exception "Assert_failure codegen/compile.ml:6445:8" From 8977c86eedbe96131106d742e53663aaa1c0ca3f Mon Sep 17 00:00:00 2001 From: Paul Young Date: Thu, 31 Oct 2019 12:49:11 -0700 Subject: [PATCH 0503/1176] Remove printOpInt now that we have debug_show (#787) I propose that we discourage adding specialized functions like this and instead suggest that people use `print(debug_show(x))`. --- stdlib/option.mo | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/stdlib/option.mo b/stdlib/option.mo index a980e9caa76..da0db4424c8 100644 --- a/stdlib/option.mo +++ b/stdlib/option.mo @@ -125,20 +125,6 @@ public func assertNullAny(x: ?Any) = public func assertNull(x: ?A) = assertNullAny(x); -/*** - - `printOpInt` - -------------------- - - Print an optional integer. - -*/ -public func printOpInt(x : ?Int) = - switch x { - case null { print "null" }; - case (?x_) { print "?"; printInt x_ }; - }; - public func apply(f : ?(A -> B), x : ?A) : ?B { switch (f, x) { case (?f_, ?x_) { From 4c343a60a79f7ce9df54df00032edcd6b21026e7 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 31 Oct 2019 21:05:59 +0100 Subject: [PATCH 0504/1176] Set ret_tys of `post` function when implementing `async` look how nice `check_ir` now looks! --- src/ir_def/check_ir.ml | 10 ++-------- src/ir_passes/async.ml | 10 +++------- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 668f8dc20d5..8122cf276e2 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -379,18 +379,12 @@ let rec check_exp env (exp:Ir.exp) : unit = typ k <: T.Func (T.Local, T.Returns, [], t_rets, []); typ r <: T.Func (T.Local, T.Returns, [], [T.catch], []); *) - | T.Func (sort, T.Replies, [], arg_tys, _ret_tys) -> + | T.Func (sort, T.Replies, [], arg_tys, ret_tys) -> check_exp env exp2; let t_arg = T.seq arg_tys in typ exp2 <: t_arg; check_concrete env exp.at t_arg; - (match T.promote (typ k) with - | T.Func (T.Local, T.Returns, [], t_rets, []) -> - check_concrete env exp.at (T.seq t_rets) - | T.Non -> () (* dead code, not much to check here *) - | t -> - error env k.at "expected continuation type, but expression produces type\n %s" - (T.string_of_typ_expand t)); + typ k <: T.Func (T.Local, T.Returns, [], ret_tys, []); typ r <: T.Func (T.Local, T.Returns, [], [T.text], []); | T.Non -> () (* dead code, not much to check here *) | _ -> diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index dd866f725a0..1a41c4f5d4b 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -276,14 +276,10 @@ module Transform(Platform : sig val platform : platform end) = struct | PrimE (OtherPrim "@await", [a;kr]) -> ((t_exp a) -*- (t_exp kr)).it | PrimE (OtherPrim "@async", [exp2]) -> - let ts1, contT = match typ exp2 with - | Func(_,_, - [], - [Func(_, _, [], ts1, []) as contT; _], - []) -> - (List.map t_typ ts1, t_typ contT) + let ts1 = match typ exp2 with + | Func(_,_, [], [Func(_, _, [], ts1, []); _], []) -> List.map t_typ ts1 | t -> assert false in - let post = fresh_var "post" (T.Func(T.Shared T.Write, T.Replies, [], [], [])) in + let post = fresh_var "post" (T.Func(T.Shared T.Write, T.Replies, [], [], ts1)) in let u = fresh_var "u" T.unit in let ((nary_async, nary_reply, reject), def) = new_nary_async_reply ts1 in (blockE [letP (tupP [varP nary_async; varP nary_reply; varP reject]) def; From 3418c34709d219ea1afd95c65d7793f87b35bda7 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 1 Nov 2019 02:21:44 +0100 Subject: [PATCH 0505/1176] Reduce size of some more test cases (#810) * Make `large-array.mo` smaller Allocating a 1GB array was putting too much strain on CI, especially during interpretation. Let's do 50MB instead. * Reduce size of some more test cases * Off-by-one --- test/run-dfinity/async-loop-while.mo | 16 ++++++++-------- test/run-dfinity/async-loop.mo | 16 ++++++++-------- test/run-dfinity/async-while.mo | 16 ++++++++-------- test/run-dfinity/await.mo | 4 ++-- test/run-dfinity/ok/async-loop-while.dvm-run.ok | 2 +- test/run-dfinity/ok/async-loop-while.run-ir.ok | 2 +- test/run-dfinity/ok/async-loop-while.run-low.ok | 2 +- test/run-dfinity/ok/async-loop-while.run.ok | 2 +- test/run-dfinity/ok/async-loop.dvm-run.ok | 2 +- test/run-dfinity/ok/async-loop.run-ir.ok | 2 +- test/run-dfinity/ok/async-loop.run-low.ok | 2 +- test/run-dfinity/ok/async-loop.run.ok | 2 +- test/run-dfinity/ok/async-while.dvm-run.ok | 2 +- test/run-dfinity/ok/async-while.run-ir.ok | 2 +- test/run-dfinity/ok/async-while.run-low.ok | 2 +- test/run-dfinity/ok/async-while.run.ok | 2 +- test/run-dfinity/ok/await.dvm-run.ok | 10 +++------- test/run-dfinity/ok/await.run-ir.ok | 4 ---- test/run-dfinity/ok/await.run-low.ok | 4 ---- test/run-dfinity/ok/await.run.ok | 4 ---- 20 files changed, 41 insertions(+), 57 deletions(-) diff --git a/test/run-dfinity/async-loop-while.mo b/test/run-dfinity/async-loop-while.mo index c4bae925319..9677bc085e3 100644 --- a/test/run-dfinity/async-loop-while.mo +++ b/test/run-dfinity/async-loop-while.mo @@ -8,8 +8,8 @@ async { assert(j == i); i += 1; j += 1; - } while (i < 11); - assert(i == 11); + } while (i < 3); + assert(i == 3); }; @@ -21,8 +21,8 @@ async { assert(j == i); i += 1; j += 1; - } while (await async (i < 11)); - assert(i == 11); + } while (await async (i < 3)); + assert(i == 3); }; { @@ -33,8 +33,8 @@ async { assert(j == i); await (async (i += 1)); j += 1; - } while (i < 11); - assert(i == 11); + } while (i < 3); + assert(i == 3); }; { @@ -42,7 +42,7 @@ async { var j = 0; label l loop { - if (j > 10) { + if (j > 2) { break l; assert(false); }; @@ -53,7 +53,7 @@ async { continue l; assert(false); } while (true); - assert(i == 11); + assert(i == 3); }; }; diff --git a/test/run-dfinity/async-loop.mo b/test/run-dfinity/async-loop.mo index 0cc9252d180..35453921383 100644 --- a/test/run-dfinity/async-loop.mo +++ b/test/run-dfinity/async-loop.mo @@ -9,9 +9,9 @@ async { assert(j == i); i += 1; j += 1; - if (j == 11) break l else continue l; + if (j == 3) break l else continue l; } ; - assert(i == 11); + assert(i == 3); }; @@ -24,10 +24,10 @@ async { assert(j == i); i += 1; j += 1; - if (await async (j == 11)) break l else continue l; + if (await async (j == 3)) break l else continue l; assert(false); }; - assert(i == 11); + assert(i == 3); }; { @@ -39,10 +39,10 @@ async { assert(j == i); await (async (i += 1)); j += 1; - if (j == 11) break l else continue l; + if (j == 3) break l else continue l; assert(false); }; - assert(i == 11); + assert(i == 3); }; { @@ -50,7 +50,7 @@ async { var j = 0; label l loop { - if (j > 10) { + if (j > 2) { break l; assert(false); }; @@ -61,7 +61,7 @@ async { continue l; assert(false); }; - assert(i == 11); + assert(i == 3); }; }; diff --git a/test/run-dfinity/async-while.mo b/test/run-dfinity/async-while.mo index 63ec7b22e87..969fe18c1d8 100644 --- a/test/run-dfinity/async-while.mo +++ b/test/run-dfinity/async-while.mo @@ -3,38 +3,38 @@ async { { var i = 0; var j = 0; - while (j <= 10) { + while (j <= 2) { printNat(j); assert(j == i); i += 1; j += 1; }; - assert(i == 11); + assert(i == 3); }; { var i = 0; var j = 0; - while (await async (j <= 10)) { + while (await async (j <= 2)) { printNat(j); assert(j == i); i += 1; j += 1; }; - assert(i == 11); + assert(i == 3); }; { var i = 0; var j = 0; - while (j <= 10) { + while (j <= 2) { printNat(j); assert(j == i); await (async (i += 1)); j += 1; }; - assert(i == 11); + assert(i == 3); }; { @@ -42,7 +42,7 @@ async { var j = 0; label l while (true) { - if (j > 10) { + if (j > 2) { break l; assert(false); }; @@ -53,7 +53,7 @@ async { continue l; assert(false); }; - assert(i == 11); + assert(i == 3); }; }; diff --git a/test/run-dfinity/await.mo b/test/run-dfinity/await.mo index c0788bdf348..887044ac310 100644 --- a/test/run-dfinity/await.mo +++ b/test/run-dfinity/await.mo @@ -34,7 +34,7 @@ print "e"; let e = async { var i = 5; print "e-while"; - while (i < 10) { + while (i < 8) { let _ = await f(i); i += 1; }; @@ -48,7 +48,7 @@ let g = async { print "g-label"; label lp while (true) { - if (i < 15) { + if (i < 13) { print "."; let _ = await f(i); i += 1; diff --git a/test/run-dfinity/ok/async-loop-while.dvm-run.ok b/test/run-dfinity/ok/async-loop-while.dvm-run.ok index ac6ac408923..f97e06e398a 100644 --- a/test/run-dfinity/ok/async-loop-while.dvm-run.ok +++ b/test/run-dfinity/ok/async-loop-while.dvm-run.ok @@ -1 +1 @@ -012345678910012345678910012345678910012345678910 +012012012012 diff --git a/test/run-dfinity/ok/async-loop-while.run-ir.ok b/test/run-dfinity/ok/async-loop-while.run-ir.ok index ac6ac408923..f97e06e398a 100644 --- a/test/run-dfinity/ok/async-loop-while.run-ir.ok +++ b/test/run-dfinity/ok/async-loop-while.run-ir.ok @@ -1 +1 @@ -012345678910012345678910012345678910012345678910 +012012012012 diff --git a/test/run-dfinity/ok/async-loop-while.run-low.ok b/test/run-dfinity/ok/async-loop-while.run-low.ok index ac6ac408923..f97e06e398a 100644 --- a/test/run-dfinity/ok/async-loop-while.run-low.ok +++ b/test/run-dfinity/ok/async-loop-while.run-low.ok @@ -1 +1 @@ -012345678910012345678910012345678910012345678910 +012012012012 diff --git a/test/run-dfinity/ok/async-loop-while.run.ok b/test/run-dfinity/ok/async-loop-while.run.ok index ac6ac408923..f97e06e398a 100644 --- a/test/run-dfinity/ok/async-loop-while.run.ok +++ b/test/run-dfinity/ok/async-loop-while.run.ok @@ -1 +1 @@ -012345678910012345678910012345678910012345678910 +012012012012 diff --git a/test/run-dfinity/ok/async-loop.dvm-run.ok b/test/run-dfinity/ok/async-loop.dvm-run.ok index ac6ac408923..f97e06e398a 100644 --- a/test/run-dfinity/ok/async-loop.dvm-run.ok +++ b/test/run-dfinity/ok/async-loop.dvm-run.ok @@ -1 +1 @@ -012345678910012345678910012345678910012345678910 +012012012012 diff --git a/test/run-dfinity/ok/async-loop.run-ir.ok b/test/run-dfinity/ok/async-loop.run-ir.ok index ac6ac408923..f97e06e398a 100644 --- a/test/run-dfinity/ok/async-loop.run-ir.ok +++ b/test/run-dfinity/ok/async-loop.run-ir.ok @@ -1 +1 @@ -012345678910012345678910012345678910012345678910 +012012012012 diff --git a/test/run-dfinity/ok/async-loop.run-low.ok b/test/run-dfinity/ok/async-loop.run-low.ok index ac6ac408923..f97e06e398a 100644 --- a/test/run-dfinity/ok/async-loop.run-low.ok +++ b/test/run-dfinity/ok/async-loop.run-low.ok @@ -1 +1 @@ -012345678910012345678910012345678910012345678910 +012012012012 diff --git a/test/run-dfinity/ok/async-loop.run.ok b/test/run-dfinity/ok/async-loop.run.ok index ac6ac408923..f97e06e398a 100644 --- a/test/run-dfinity/ok/async-loop.run.ok +++ b/test/run-dfinity/ok/async-loop.run.ok @@ -1 +1 @@ -012345678910012345678910012345678910012345678910 +012012012012 diff --git a/test/run-dfinity/ok/async-while.dvm-run.ok b/test/run-dfinity/ok/async-while.dvm-run.ok index ac6ac408923..f97e06e398a 100644 --- a/test/run-dfinity/ok/async-while.dvm-run.ok +++ b/test/run-dfinity/ok/async-while.dvm-run.ok @@ -1 +1 @@ -012345678910012345678910012345678910012345678910 +012012012012 diff --git a/test/run-dfinity/ok/async-while.run-ir.ok b/test/run-dfinity/ok/async-while.run-ir.ok index ac6ac408923..f97e06e398a 100644 --- a/test/run-dfinity/ok/async-while.run-ir.ok +++ b/test/run-dfinity/ok/async-while.run-ir.ok @@ -1 +1 @@ -012345678910012345678910012345678910012345678910 +012012012012 diff --git a/test/run-dfinity/ok/async-while.run-low.ok b/test/run-dfinity/ok/async-while.run-low.ok index ac6ac408923..f97e06e398a 100644 --- a/test/run-dfinity/ok/async-while.run-low.ok +++ b/test/run-dfinity/ok/async-while.run-low.ok @@ -1 +1 @@ -012345678910012345678910012345678910012345678910 +012012012012 diff --git a/test/run-dfinity/ok/async-while.run.ok b/test/run-dfinity/ok/async-while.run.ok index ac6ac408923..f97e06e398a 100644 --- a/test/run-dfinity/ok/async-while.run.ok +++ b/test/run-dfinity/ok/async-while.run.ok @@ -1 +1 @@ -012345678910012345678910012345678910012345678910 +012012012012 diff --git a/test/run-dfinity/ok/await.dvm-run.ok b/test/run-dfinity/ok/await.dvm-run.ok index 7569eb9e6fe..963fc9b25f1 100644 --- a/test/run-dfinity/ok/await.dvm-run.ok +++ b/test/run-dfinity/ok/await.dvm-run.ok @@ -6,11 +6,7 @@ cnt: 4 i: 4 e-whilecnt: 5 i: 5 cnt: 6 i: 6 cnt: 7 i: 7 -cnt: 8 i: 8 -cnt: 9 i: 9 -e-exitg-label.cnt: 10 i: 10 -.cnt: 11 i: 11 -.cnt: 12 i: 12 -.cnt: 13 i: 13 -.cnt: 14 i: 14 +e-exitg-label.cnt: 8 i: 10 +.cnt: 9 i: 11 +.cnt: 10 i: 12 g-exitab diff --git a/test/run-dfinity/ok/await.run-ir.ok b/test/run-dfinity/ok/await.run-ir.ok index 08e3e459bc4..731730721c0 100644 --- a/test/run-dfinity/ok/await.run-ir.ok +++ b/test/run-dfinity/ok/await.run-ir.ok @@ -9,8 +9,4 @@ cnt: 7 i: 6 cnt: 8 i: 11 .cnt: 9 i: 7 cnt: 10 i: 12 -.cnt: 11 i: 8 -cnt: 12 i: 13 -.cnt: 13 i: 9 -cnt: 14 i: 14 e-exitg-exit diff --git a/test/run-dfinity/ok/await.run-low.ok b/test/run-dfinity/ok/await.run-low.ok index 08e3e459bc4..731730721c0 100644 --- a/test/run-dfinity/ok/await.run-low.ok +++ b/test/run-dfinity/ok/await.run-low.ok @@ -9,8 +9,4 @@ cnt: 7 i: 6 cnt: 8 i: 11 .cnt: 9 i: 7 cnt: 10 i: 12 -.cnt: 11 i: 8 -cnt: 12 i: 13 -.cnt: 13 i: 9 -cnt: 14 i: 14 e-exitg-exit diff --git a/test/run-dfinity/ok/await.run.ok b/test/run-dfinity/ok/await.run.ok index 08e3e459bc4..731730721c0 100644 --- a/test/run-dfinity/ok/await.run.ok +++ b/test/run-dfinity/ok/await.run.ok @@ -9,8 +9,4 @@ cnt: 7 i: 6 cnt: 8 i: 11 .cnt: 9 i: 7 cnt: 10 i: 12 -.cnt: 11 i: 8 -cnt: 12 i: 13 -.cnt: 13 i: 9 -cnt: 14 i: 14 e-exitg-exit From 62c9042f821eeab3884c015ee8170d867e304dc2 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 1 Nov 2019 12:52:15 +0100 Subject: [PATCH 0506/1176] Add reversei test case (#817) this is a test case based on https://github.com/dfinity-lab/dapps/blob/75ead35363574f3697e37cd3a0592e51d3253a36/examples/reversi/src/reversi/main.mo resp. https://github.com/dfinity-lab/dapps/pull/4 @ninegua reports in https://dfinity.slack.com/archives/CPKAD5BJN/p1572573329177100 that there is an out-of-memory-condition, so I tried to reproduce it, but I could not easily. Maybe it needs more calls or other code. But its still a nice example. @ninegua, if you remeber how to trigger the out-of-memory condition (if it even was a Wasm/Motoko out of memory), maybe you can tell us or amend the test case. --- test/run-drun/ok/reversi.drun-run.ok | 9 + test/run-drun/reversi.mo | 274 +++++++++++++++++++++++++++ 2 files changed, 283 insertions(+) create mode 100644 test/run-drun/ok/reversi.drun-run.ok create mode 100644 test/run-drun/reversi.mo diff --git a/test/run-drun/ok/reversi.drun-run.ok b/test/run-drun/ok/reversi.drun-run.ok new file mode 100644 index 00000000000..0c49bd69fb7 --- /dev/null +++ b/test/run-drun/ok/reversi.drun-run.ok @@ -0,0 +1,9 @@ +ingress(0) System +ingress(1) Completed: Canister: Empty +ingress(2) Completed: Canister: Payload: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e4f2a2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a +ingress(3) Completed: Canister: Payload: 0x4449444c000171024f4b +ingress(4) Completed: Canister: Payload: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e4f2e2e2e0a2e2e2e4f4f2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a +ingress(5) Completed: Canister: Payload: 0x4449444c000171024f4b +ingress(6) Completed: Canister: Payload: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a +ingress(7) Completed: Canister: Payload: 0x4449444c000171024f4b +ingress(8) Completed: Canister: Payload: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e4f4f2e2e2e0a2e2e4f4f4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a diff --git a/test/run-drun/reversi.mo b/test/run-drun/reversi.mo new file mode 100644 index 00000000000..95f7038f341 --- /dev/null +++ b/test/run-drun/reversi.mo @@ -0,0 +1,274 @@ +actor { + // based on https://github.com/dfinity-lab/dapps/blob/75ead35363574f3697e37cd3a0592e51d3253a36/examples/reversi/src/reversi/main.mo + // with stdlib inlined and board size changed to 8 + + + // inline parts of stdlib + func unreachable() : None = { assert false ; loop { } }; + + func toText(x : Int) : Text { + if (x == 0) { + return "0"; + }; + + let isNegative = x < 0; + var int = if isNegative (-x) else x; + + var text = ""; + let base = 10; + + while (int > 0) { + let rem = int % base; + text := (switch (rem) { + case 0 "0"; + case 1 "1"; + case 2 "2"; + case 3 "3"; + case 4 "4"; + case 5 "5"; + case 6 "6"; + case 7 "7"; + case 8 "8"; + case 9 "9"; + case _ unreachable(); + }) # text; + int := int / base; + }; + + return if isNegative ("-" # text) else text; + }; + + + + // Color related type and constants + type Color = Nat; + let empty : Color = 0; + let white : Color = 1; + let black : Color = 2; + + // Dimension of the board + let N : Nat = 8; + + // Board is NxN array + type Board = [var Color]; + let Board : Board = Array_init(N * N, empty); + + // Which color should move next + var next_color : Color = white; + + // Reset the board to initial state + func init() { + // Reset to empty board + for (i in range(0, N * N - 1)) { + Board[i] := empty; + }; + + // initialize center 4 pieces + let M = N / 2; + Board[(M - 1) * N + M - 1] := white; + Board[ M * N + M ] := white; + Board[(M - 1) * N + M ] := black; + Board[ M * N + M - 1] := black; + + // White moves first + next_color := white; + }; + + // External interface to reset the board + public func reset() { + init() + }; + + public func dimension() : async Nat { + return N; + }; + + // Render the board into a string + func render(board: Board) : Text { + var str = ""; + for (i in range(0, N-1)) { + for (j in range(0, N-1)) { + if (board[i * N + j] == white) { + str := str # "O"; + } else if (board[i * N + j] == black) { + str := str # "*"; + } + else { + str := str # "."; + }; + }; + str := str # "\n"; + }; + + return str; + }; + + // External interface to render the board + public func board() : async Text { + return render(Board); + }; + + // Given a color, return its opponent color + func opponent(color: Color): Color { + return (3 - color); + }; + + // Check if a piece of the given color exists on the board using + // coordinate (i, j) and offset (p, q). + func exists(board: Board, color: Color, i: Nat, j: Nat, p:Int, q:Int) : Bool { + let s = i + p; + let t = j + q; + if (s < 0 or s >= N or t < 0 or t >= N) { + return false; + }; + return (board[abs (s * N + t)] == color); + }; + + // Check if a piece of the given color eventually exits on the board + // using coordinate (i, j) and direction (p, q), ignoring opponent colors + // in between. Return false if the given color is not found before reaching + // empty cell or board boundary. + func eventually(board: Board, color: Color, i: Nat, j: Nat, p:Int, q:Int) : Bool { + if (exists(board, opponent(color), i, j, p, q)) { + // the abs below is save because its precondition is already checked + return eventually(board, color, abs(i + p), abs(j + q), p, q); + } else { + return exists(board, color, i, j, p, q); + } + }; + + // Flip pieces of opponent color into the given color starting from + // coordinate (i, j) and along direction (p, q). + func flip(board: Board, color: Color, i: Nat, j: Nat, p:Int, q:Int) { + if (exists(board, opponent(color), i, j, p, q)) { + // the abs below is save because its precondition is already checked + let s = abs(i + p); + let t = abs(j + q); + board[s * N + t] := color; + flip(board, color, s, t, p, q); + } + }; + + // Calculate all validate positions for a given color by returning + // a board that has the cells colored. + func valid_moves(board: Board, color: Color) : Board { + let next : Board = Array_init(N * N, empty); + for (i in range(0, N-1)) { + for (j in range(0, N-1)) { + if (board[i * N + j] == empty) { + for (p in [-1, 0, 1].vals()) { + for (q in [-1, 0, 1].vals()) { + if (not(p == 0 and q == 0)) { + if (exists(board, opponent(color), i, j, p, q) and + eventually(board, color, i, j, p, q)) { + next[i * N + j] := color; + } + } + } + } + } + } + }; + return next; + }; + + // Set a piece on the board at a given position, and flip all + // affected opponent pieces accordingly. It requires that the + // given position is a valid move before this call. + func set_and_flip(board: Board, color: Color, i: Nat, j: Nat) { + board[i * N + j] := color; + for (p in [-1, 0, 1].vals()) { + for (q in [-1, 0, 1].vals()) { + if (not(p == 0 and q == 0)) { + if (exists(board, opponent(color), i, j, p, q) and + eventually(board, color, i, j, p, q)) { + flip(board, color, i, j, p, q); + } + } + } + } + }; + + // Check if the given board is empty. + func is_empty(board: Board) : Bool { + for (c in board.vals()) { + if (c != empty){ + return false; + } + }; + return true; + }; + + + // Return the white and black counts. + func score(board: Board) : (Nat, Nat) { + var wc = 0; + var bc = 0; + for (c in board.vals()) { + if (c == white) { + wc += 1; + } + else if (c == black) { + bc += 1; + } + }; + return (wc, bc); + }; + + // External interface that places a piece of given color at a coordinate. + // It returns "OK" when the move is valid. + public func place(color_: Int, row_: Int, col_: Int) : async Text { + // The casting is necessary because dfx has yet to support Nat on commandline + let color : Color = abs(color_); + let row : Nat = abs(row_); + let col : Nat = abs(col_); + + // Check input validity + if (row >= N or col >= N) { + return "Invalid coordinate"; + }; + if (not (color == 1 or color == 2)) { + return "Invalid piece color, must be either 1 or 2"; + }; + + var possible = valid_moves(Board, next_color); + + // If no move is possible, either pass or end game. + if (is_empty(possible)) { + next_color := opponent(next_color); + possible := valid_moves(Board, next_color); + // If no possible move again, end game + if (is_empty(possible)) { + let (wc, bc) = score(Board); + return ("End Game! Whites = " # toText(wc) # ", Blacks = " # toText(bc)) + } + else { + return "PASS" + } + }; + + if (next_color != color) { + return "Wrong color for this move"; + }; + + if (possible[row * N + col] != empty) { + set_and_flip(Board, color, row, col); + next_color := opponent(color); + return "OK"; + } else { + return "Illegal move"; + }; + + }; + + init(); +}; + +//CALL ingress reset 0x4449444C0000 +//CALL ingress board 0x4449444C0000 +//CALL ingress place 0x4449444C00037c7c7c010204 +//CALL ingress board 0x4449444C0000 +//CALL ingress place 0x4449444C00037c7c7c020203 +//CALL ingress board 0x4449444C0000 +//CALL ingress place 0x4449444C00037c7c7c010402 +//CALL ingress board 0x4449444C0000 From 69012148caa4fa194afc0f7d9bb653ad3fe11176 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 1 Nov 2019 15:44:23 +0100 Subject: [PATCH 0507/1176] Introduce named prims for post-await pre-async Await and Asyn (#814) so that we can do some proper checking in `Check_IR` --- src/ir_def/arrange_ir.ml | 2 + src/ir_def/check_ir.ml | 10 +++- src/ir_def/construct.ml | 4 +- src/ir_def/ir.ml | 2 + src/ir_interpreter/interpret_ir.ml | 73 ++++++++++++++---------------- src/ir_passes/async.ml | 6 +-- 6 files changed, 51 insertions(+), 46 deletions(-) diff --git a/src/ir_def/arrange_ir.ml b/src/ir_def/arrange_ir.ml index 4cf0bb0473d..37fcfd5c515 100644 --- a/src/ir_def/arrange_ir.ml +++ b/src/ir_def/arrange_ir.ml @@ -60,6 +60,8 @@ and prim = function | ShowPrim t -> "ShowPrim" $$ [typ t] | NumConvPrim (t1, t2) -> "NumConvPrim" $$ [prim_ty t1; prim_ty t2] | OtherPrim s -> Atom s + | CPSAwait -> Atom "CPSAwait" + | CPSAsync -> Atom "CPSAsync" | ICReplyPrim ts -> "ICReplyPrim" $$ List.map typ ts | ICRejectPrim -> Atom "ICRejectPrim" | ICErrorCodePrim -> Atom "ICErrorCodePrim" diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index e8ccac85c3d..4bb6c12f5a9 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -289,7 +289,7 @@ let type_lit env lit at : T.prim = let isAsyncE exp = match exp.it with | AsyncE _ (* pre await transformation *) - | PrimE(OtherPrim "@async", [_]) (* post await transformation *) + | PrimE (CPSAsync, [_]) (* post await transformation *) -> true | _ -> false @@ -340,6 +340,14 @@ let rec check_exp env (exp:Ir.exp) : unit = check_exp env exp1; typ exp1 <: ot; T.Prim T.Text <: t + | CPSAwait, [a; kr] -> + check (not (env.flavor.has_await)) "CPSAwait await flavor"; + check (env.flavor.has_async_typ) "CPSAwait in post-async flavor"; + (* TODO: We can check more here, can we *) + | CPSAsync, [exp] -> + check (not (env.flavor.has_await)) "CPSAsync await flavor"; + check (env.flavor.has_async_typ) "CPSAsync in post-async flavor"; + (* TODO: We can check more here, can we *) | ICReplyPrim ts, [exp1] -> check (not (env.flavor.has_async_typ)) "ICReplyPrim in async flavor"; check (T.shared t) "ICReplyPrim is not defined for non-shared operand type"; diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index 1ea5e7d99f8..29a17f07c59 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -91,7 +91,7 @@ let primE prim es = } let asyncE typ e = - { it = PrimE (OtherPrim "@async", [e]); + { it = PrimE (CPSAsync, [e]); at = no_region; note = { note_typ = T.Async typ; note_eff = eff e } } @@ -103,7 +103,7 @@ let assertE e = } let awaitE typ e1 e2 = - { it = PrimE (OtherPrim "@await", [e1; e2]); + { it = PrimE (CPSAwait, [e1; e2]); at = no_region; note = { note_typ = T.unit; note_eff = max_eff (eff e1) (eff e2) } } diff --git a/src/ir_def/ir.ml b/src/ir_def/ir.ml index 418ff4d2298..cf3e3d673cf 100644 --- a/src/ir_def/ir.ml +++ b/src/ir_def/ir.ml @@ -106,6 +106,8 @@ and prim = | ShowPrim of Type.typ (* debug show *) | NumConvPrim of Type.prim * Type.prim | OtherPrim of string (* Other primitive operation, no custom typing rule *) + | CPSAwait + | CPSAsync | ICReplyPrim of Type.typ list | ICRejectPrim | ICErrorCodePrim diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index 415adf7b543..76412ea2217 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -218,43 +218,6 @@ let make_message env x cc v : V.value = | T.Returns -> make_unit_message env x v | T.Promises-> make_async_message env x v - -let extended_prim env s typ at = - match s with - | "@async" -> - assert (not env.flavor.has_await && env.flavor.has_async_typ); - (fun v k -> - let (_, f) = V.as_func v in - match typ with - | T.Func(_, _, _, [T.Func(_, _, _, [f_dom], _);T.Func(_, _, _, [r_dom], _)], _) -> - let call_conv_f = CC.call_conv_of_typ f_dom in - let call_conv_r = CC.call_conv_of_typ r_dom in - async env at - (fun k' r -> - let vk' = Value.Func (call_conv_f, fun v _ -> k' v) in - let vr = Value.Func (call_conv_r, fun v _ -> r v) in - f (V.Tup [vk';vr]) V.as_unit - ) - k - | _ -> assert false - ) - | "@await" -> - assert (not env.flavor.has_await && env.flavor.has_async_typ); - (fun v k -> - match V.as_tup v with - | [async; v1] -> - (match V.as_tup v1 with - | [vf; vr] -> - let (_, f) = V.as_func vf in - let (_, r) = V.as_func vr in - await env at (V.as_async async) - (fun v -> f v k) - (fun e -> r e k) (* TBR *) - | _ -> assert false) - | _ -> assert false) - | _ -> Prim.prim s - - (* Literals *) let interpret_lit env lit : V.value = @@ -345,12 +308,42 @@ and interpret_exp_mut env exp (k : V.value V.cont) = if Show.can_show ot then k (Value.Text (Show.show_val ot v)) else raise (Invalid_argument "debug_show")) + | CPSAsync, [exp1] -> + interpret_exp env exp1 (fun v -> + assert (not env.flavor.has_await && env.flavor.has_async_typ); + let (_, f) = V.as_func v in + let typ = exp.note.note_typ in + match typ with + | T.Func(_, _, _, [T.Func(_, _, _, [f_dom], _);T.Func(_, _, _, [r_dom], _)], _) -> + let call_conv_f = CC.call_conv_of_typ f_dom in + let call_conv_r = CC.call_conv_of_typ r_dom in + async env exp.at + (fun k' r -> + let vk' = Value.Func (call_conv_f, fun v _ -> k' v) in + let vr = Value.Func (call_conv_r, fun v _ -> r v) in + f (V.Tup [vk';vr]) V.as_unit + ) + k + | _ -> assert false + ) + | CPSAwait, [exp1;exp2] -> + interpret_exp env exp1 (fun v1 -> + interpret_exp env exp2 (fun v2 -> + assert (not env.flavor.has_await && env.flavor.has_async_typ); + match V.as_tup v2 with + | [vf; vr] -> + let (_, f) = V.as_func vf in + let (_, r) = V.as_func vr in + await env exp.at (V.as_async v1) + (fun v -> f v k) + (fun e -> r e k) (* TBR *) + | _ -> assert false + ) + ) | OtherPrim s, exps -> interpret_exps env exps [] (fun vs -> - let at = exp.at in - let t = exp.note.note_typ in let arg = match vs with [v] -> v | _ -> V.Tup vs in - extended_prim env s t at arg k + Prim.prim s arg k ) | NumConvPrim (t1, t2), exps -> interpret_exps env exps [] (fun vs -> diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index 7bc3fcef9e3..32d237ff477 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -319,9 +319,9 @@ module Transform(Platform : sig val platform : platform end) = struct ArrayE (mut, t_typ t, List.map t_exp exps) | IdxE (exp1, exp2) -> IdxE (t_exp exp1, t_exp exp2) - | PrimE (OtherPrim "@await", [a;kr]) -> + | PrimE (CPSAwait, [a;kr]) -> ((t_exp a) -*- (t_exp kr)).it - | PrimE (OtherPrim "@async", [exp2]) -> + | PrimE (CPSAsync, [exp2]) -> let ts1, contT = match typ exp2 with | Func(_,_, [], @@ -419,7 +419,7 @@ module Transform(Platform : sig val platform : platform end) = struct in let typbinds' = t_typ_binds typbinds in let cps = match exp.it with - | PrimE (OtherPrim "@async", [cps]) -> cps + | PrimE (CPSAsync, [cps]) -> cps | _ -> assert false in let t1, contT = match typ cps with | Func(_,_, From a45835fb97d6f445b180bde467abd7d9cc47ca4e Mon Sep 17 00:00:00 2001 From: Paul Young Date: Fri, 1 Nov 2019 11:39:10 -0700 Subject: [PATCH 0508/1176] Standard library additions (#808) * Add Array.enumerate, Array.mapWithIndex, Iter.for * "for" is apparently reserved * Actually run the tests * Add Function.curry, Function.uncurry * Add compose, const, const2 for functions * Add None.absurd * Add Array.filter * Use built-in Iter type * Use lift/lower * User lift/lower in tests --- stdlib/Makefile | 24 +++++++++++++++ stdlib/array.mo | 22 ++++++++++++++ stdlib/arrayTest.mo | 68 ++++++++++++++++++++++++++++++++++++++++++ stdlib/function.mo | 31 +++++++++++++++++++ stdlib/functionTest.mo | 51 +++++++++++++++++++++++++++++++ stdlib/iter.mo | 20 +++++++++++++ stdlib/iterTest.mo | 21 +++++++++++++ stdlib/none.mo | 5 ++++ stdlib/noneTest.mo | 13 ++++++++ 9 files changed, 255 insertions(+) create mode 100644 stdlib/function.mo create mode 100644 stdlib/functionTest.mo create mode 100644 stdlib/iter.mo create mode 100644 stdlib/iterTest.mo create mode 100644 stdlib/none.mo create mode 100644 stdlib/noneTest.mo diff --git a/stdlib/Makefile b/stdlib/Makefile index 4e5eff22988..8620467fa9d 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -19,13 +19,19 @@ TESTS=\ ArrayTest \ AssocList \ DocTable \ + Function \ + FunctionTest \ Hash \ Int \ IntTest \ + Iter \ + IterTest \ List \ ListTest \ Nat \ NatTest \ + None \ + NoneTest \ Option \ OptionTest \ Result \ @@ -68,12 +74,24 @@ $(OUTDIR)/Array.out: array.mo | $(OUTDIR) $(OUTDIR)/ArrayTest.out: arrayTest.mo | $(OUTDIR) $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ +$(OUTDIR)/Function.out: function.mo | $(OUTDIR) + $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ + +$(OUTDIR)/FunctionTest.out: functionTest.mo | $(OUTDIR) + $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ + $(OUTDIR)/Int.out: int.mo | $(OUTDIR) $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ $(OUTDIR)/IntTest.out: intTest.mo | $(OUTDIR) $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ +$(OUTDIR)/Iter.out: iter.mo | $(OUTDIR) + $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ + +$(OUTDIR)/IterTest.out: iterTest.mo | $(OUTDIR) + $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ + $(OUTDIR)/Nat.out: nat.mo | $(OUTDIR) $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ @@ -83,6 +101,12 @@ $(OUTDIR)/NatTest.out: natTest.mo | $(OUTDIR) $(OUTDIR)/Hash.out: hash.mo | $(OUTDIR) $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ +$(OUTDIR)/None.out: none.mo | $(OUTDIR) + $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ + +$(OUTDIR)/NoneTest.out: noneTest.mo | $(OUTDIR) + $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ + $(OUTDIR)/Option.out: option.mo | $(OUTDIR) $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ diff --git a/stdlib/array.mo b/stdlib/array.mo index db7b39ed615..a56cf187909 100644 --- a/stdlib/array.mo +++ b/stdlib/array.mo @@ -32,6 +32,22 @@ module { ys; }; + public func enumerate(xs : [A]) : [(A, Nat)] { + Array_tabulate<(A, Nat)>(xs.len(), func (i : Nat) : (A, Nat) { + (xs[i], i); + }); + }; + + public func filter(f : A -> Bool, xs : [A]) : [A] { + var ys : [A] = []; + for (x in xs.vals()) { + if (f(x)) { + ys := append(ys, [x]); + }; + }; + ys; + }; + public func foldl(f : (B, A) -> B, initial : B, xs : [A]) : B { var acc = initial; let len = xs.len(); @@ -81,6 +97,12 @@ module { }); }; + public func mapWithIndex(f : (A, Nat) -> B, xs : [A]) : [B] { + Array_tabulate(xs.len(), func (i : Nat) : B { + f(xs[i], i); + }); + }; + public func pure(x: A) : [A] { [x]; }; diff --git a/stdlib/arrayTest.mo b/stdlib/arrayTest.mo index 02e77e5cc77..a8775d562fd 100644 --- a/stdlib/arrayTest.mo +++ b/stdlib/arrayTest.mo @@ -55,6 +55,41 @@ Prelude.printLn("Array"); }; }; +{ + Prelude.printLn(" enumerate"); + + let xs = [ "a", "b", "c" ]; + let ys = Array.enumerate(xs); + + assert(xs.len() == ys.len()); + + assert(ys[0].0 == xs[0]); + assert(ys[0].1 == 0); + + assert(ys[1].0 == xs[1]); + assert(ys[1].1 == 1); + + assert(ys[2].0 == xs[2]); + assert(ys[2].1 == 2); +}; + +{ + Prelude.printLn(" filter"); + + let isEven = func (x : Int) : Bool { + x % 2 == 0; + }; + + let actual = Array.filter(isEven, [ 1, 2, 3, 4, 5, 6 ]); + let expected = [ 2, 4, 6 ]; + + assert(actual.len() == expected.len()); + + for (i in actual.keys()) { + assert(actual[i] == expected[i]); + }; +}; + { Prelude.printLn(" find"); @@ -152,6 +187,39 @@ Prelude.printLn("Array"); }; }; +{ + Prelude.printLn(" mapWithIndex"); + + let isEven = func (x : Int) : Bool { + x % 2 == 0; + }; + + let xs = [ 1, 2, 3, 4, 5, 6 ]; + + let actual = Array.mapWithIndex( + func (value : Int, index : Nat) : (Bool, Bool) { + (isEven value, isEven index) + }, + xs + ); + + let expected = [ + (false, true), + (true, false), + (false, true), + (true, false), + (false, true), + (true, false), + ]; + + assert(actual.len() == expected.len()); + + for (i in actual.keys()) { + assert(actual[i].0 == expected[i].0); + assert(actual[i].1 == expected[i].1); + }; +}; + { Prelude.printLn(" pure"); diff --git a/stdlib/function.mo b/stdlib/function.mo new file mode 100644 index 00000000000..6ebc39088b3 --- /dev/null +++ b/stdlib/function.mo @@ -0,0 +1,31 @@ +module { + public func compose(f : B -> C, g : A -> B) : A -> C { + func (x : A) : C { + f(g(x)); + }; + }; + + public func const(x : A) : (B) -> A { + func (_ : B) : A { + x; + }; + }; + + public func const2(x : A) : (B, C) -> A { + func (_ : B, _ : C) : A { + x; + }; + }; + + public func lift(f: (A, B) -> C) : ((A, B)) -> C { + func (p : (A, B)) : C { + f(p.0, p.1); + } + }; + + public func lower(f: ((A, B)) -> C) : (A, B) -> C { + func (fst : A, snd: B) : C { + f((fst, snd)); + } + }; +} diff --git a/stdlib/functionTest.mo b/stdlib/functionTest.mo new file mode 100644 index 00000000000..37c82fa5918 --- /dev/null +++ b/stdlib/functionTest.mo @@ -0,0 +1,51 @@ +import Function "function.mo"; +import Prelude "prelude.mo"; +import Text "text.mo"; + +Prelude.printLn("Function"); + +{ + Prelude.printLn(" compose"); + + func isEven(x : Int) : Bool { x % 2 == 0; }; + func not_(x : Bool) : Bool { not x; }; + let isOdd = Function.compose(not_, isEven); + + assert(isOdd(0) == false); + assert(isOdd(1)); +}; + +{ + Prelude.printLn(" const"); + + assert(Function.const(true)("abc")); + assert(Function.const(false)("abc") == false); +}; + +{ + Prelude.printLn(" const2"); + + assert(Function.const2(true)(0, "abc")); + assert(Function.const2(false)(0, "abc") == false); +}; + +{ + Prelude.printLn(" lift"); + + let appendPair = Function.lift(Text.append); + let pair = ("Hello, ", "World!"); + + assert(appendPair(pair) == "Hello, World!"); +}; + +{ + Prelude.printLn(" lower"); + + func appendPair(pair : (Text, Text)) : Text { + pair.0 # pair.1; + }; + + let append = Function.lower(appendPair); + + assert(append("Hello, ", "World!") == "Hello, World!"); +}; diff --git a/stdlib/iter.mo b/stdlib/iter.mo new file mode 100644 index 00000000000..07f6ae33373 --- /dev/null +++ b/stdlib/iter.mo @@ -0,0 +1,20 @@ +module { + public func forIn( + f : (A, Nat) -> (), + xs : Iter + ) { + var i = 0; + label l loop { + switch (xs.next()) { + case (?next) { + f(next, i); + }; + case (null) { + break l; + }; + }; + i += 1; + continue l; + }; + }; +} diff --git a/stdlib/iterTest.mo b/stdlib/iterTest.mo new file mode 100644 index 00000000000..d8eefb6c310 --- /dev/null +++ b/stdlib/iterTest.mo @@ -0,0 +1,21 @@ +import Iter "iter.mo"; +import Prelude "prelude.mo"; + +Prelude.printLn("Iter"); + +{ + Prelude.printLn(" forIn"); + + let xs = [ "a", "b", "c", "d", "e", "f" ]; + + var y = ""; + var z = 0; + + Iter.forIn(func (x : Text, i : Nat) { + y := y # x; + z += i; + }, xs.vals()); + + assert(y == "abcdef"); + assert(z == 15); +} diff --git a/stdlib/none.mo b/stdlib/none.mo new file mode 100644 index 00000000000..1588c5ab8c7 --- /dev/null +++ b/stdlib/none.mo @@ -0,0 +1,5 @@ +module { + public func absurd(x : None) : A { + switch (x) {}; + }; +} diff --git a/stdlib/noneTest.mo b/stdlib/noneTest.mo new file mode 100644 index 00000000000..389d878a5b4 --- /dev/null +++ b/stdlib/noneTest.mo @@ -0,0 +1,13 @@ +import Array "array.mo"; +import None "none.mo"; +import Prelude "prelude.mo"; + +Prelude.printLn("None"); + +{ + Prelude.printLn(" absurd"); + + func showNone(x : None) : Text { + None.absurd(x); + }; +}; From bdda5a0da2e3fc360c747de4fd87daa995c7cf9f Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Fri, 1 Nov 2019 23:36:13 +0000 Subject: [PATCH 0509/1176] Fix grow_memory after GC (#820) signed comparisons are healthier than unsigned here... Thanks to @crusso for some initial narrowing down the test case. --- src/codegen/compile.ml | 7 +++---- test/run-drun/ok/oom.drun-run.ok | 3 +++ test/run-drun/oom.mo | 13 +++++++++++++ 3 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 test/run-drun/ok/oom.drun-run.ok create mode 100644 test/run-drun/oom.mo diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 7d508fc667b..f7c03b1a919 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -731,7 +731,7 @@ module Heap = struct (* Check that the new heap pointer is within the memory *) get_pages_needed ^^ compile_unboxed_zero ^^ - G.i (Compare (Wasm.Values.I32 I32Op.GtU)) ^^ + G.i (Compare (Wasm.Values.I32 I32Op.GtS)) ^^ G.if_ (ValBlockType None) ( get_pages_needed ^^ G.i MemoryGrow ^^ @@ -4954,7 +4954,7 @@ module FuncDec = struct G.i (Call (nr (E.built_in env "collect"))) | Type.Shared Type.Query -> (* Don't collect *) - G.i Nop + G.nop | _ -> assert false )) | Flags.WasmMode -> assert false @@ -6928,8 +6928,7 @@ and conclude_module env module_name start_fi_o = (* Wrap the start function with the RTS initialization *) let rts_start_fi = E.add_fun env "rts_start" (Func.of_body env [] [] (fun env1 -> - G.i (GlobalGet (nr (E.get_global env "__heap_base"))) ^^ - Heap.set_heap_ptr env ^^ + Heap.get_heap_base env ^^ Heap.set_heap_ptr env ^^ match start_fi_o with | Some fi -> G.i (Call fi) | None -> G.nop diff --git a/test/run-drun/ok/oom.drun-run.ok b/test/run-drun/ok/oom.drun-run.ok new file mode 100644 index 00000000000..d1d6ed87e8b --- /dev/null +++ b/test/run-drun/ok/oom.drun-run.ok @@ -0,0 +1,3 @@ +ingress(0) System +ingress(1) Completed: Canister: Empty +ingress(2) Completed: Canister: Empty diff --git a/test/run-drun/oom.mo b/test/run-drun/oom.mo new file mode 100644 index 00000000000..f9a9b135f21 --- /dev/null +++ b/test/run-drun/oom.mo @@ -0,0 +1,13 @@ +actor Oom { + public func doloop() { + ignore(Array_init<()>(1200*1024/4, ())); + }; +} + +// on dvm: +// CALL doloop 0x4449444C0000 [] +// CALL doloop 0x4449444C0000 [] + +// on drun: +//CALL ingress doloop 0x4449444C0000 +//CALL ingress doloop 0x4449444C0000 From 71ce0535bf2149c98c664308f5f977d449ab5126 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 4 Nov 2019 17:16:28 +0100 Subject: [PATCH 0510/1176] Motoko Prelude: s/print/debug_print (#825) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Motoko Prelude: s/print/debug_print we should be clear that the `print` functionality accessed using `print` is only a debugging aid, it is _not_ the “real” way to return a result to the user. * camelCase * Test output --- README.md | 2 +- guide/as-slides.md | 4 +- guide/chat.mo | 2 +- guide/schat.mo | 2 +- samples/app/client.mo | 2 +- samples/app/server.mo | 2 +- src/prelude/prelude.ml | 8 +- stdlib/examples/actorspec/src/ActorSpec.mo | 10 +- .../examples/produce-exchange/serverActor.mo | 2 +- .../examples/produce-exchange/serverModel.mo | 8 +- .../produce-exchange/test/evalBulk.mo | 106 +++++------ .../test/loadWorkloadAndQuery.mo | 6 +- .../test/loadWorkloadAndQueryBig.mo | 122 ++++++------- .../test/producerRemInventory.mo | 108 +++++------ .../test/profileFastCounts.mo | 26 +-- .../test/retailerReserveMany.mo | 170 +++++++++--------- .../test/simpleSetupAndQuery.mo | 122 ++++++------- stdlib/hash.mo | 20 +-- stdlib/prelude.mo | 2 +- stdlib/trie2.mo | 18 +- test/bugs/aritybug.mo | 2 +- test/fail/actor-reexport.mo | 2 +- test/fail/branch-before-define.mo | 4 +- test/fail/objpat-infer.mo | 2 +- test/fail/objpat-mutable.mo | 8 +- test/fail/return-before-define.mo | 4 +- test/fail/use-before-define.mo | 2 +- test/lsp-int/test-project/lib/option.mo | 4 +- test/lsp-int/test-project/lib/prelude.mo | 2 +- test/run-dfinity/array-out-of-bounds.mo | 4 +- test/run-dfinity/async-loop-while.mo | 8 +- test/run-dfinity/async-loop.mo | 8 +- test/run-dfinity/async-new-obj.mo | 30 ++-- test/run-dfinity/async-obj-mut.mo | 16 +- test/run-dfinity/async-while.mo | 8 +- test/run-dfinity/await.mo | 38 ++-- test/run-dfinity/block.mo | 18 +- test/run-dfinity/chat.mo | 2 +- test/run-dfinity/chatpp.mo | 4 +- test/run-dfinity/closure-params.mo | 14 +- test/run-dfinity/counter.mo | 4 +- test/run-dfinity/counter2.mo | 4 +- test/run-dfinity/data-params.mo | 60 +++---- test/run-dfinity/fac.mo | 2 +- test/run-dfinity/flatten-awaitables.mo | 4 +- test/run-dfinity/for-await.mo | 2 +- test/run-dfinity/generic-tail-rec.mo | 8 +- test/run-dfinity/hello-concat-world.mo | 2 +- test/run-dfinity/hello-world-async.mo | 4 +- test/run-dfinity/hello-world-await.mo | 2 +- test/run-dfinity/hello-world-message.mo | 2 +- test/run-dfinity/hello-world-message2.mo | 2 +- test/run-dfinity/hello-world.mo | 2 +- test/run-dfinity/hello-world2.mo | 2 +- test/run-dfinity/hello-world3.mo | 4 +- test/run-dfinity/indirect-counter.mo | 10 +- test/run-dfinity/local-throw.mo | 4 +- test/run-dfinity/nary-async.mo | 20 +-- test/run-dfinity/ok/text-iter.dvm-run.ok | 10 +- test/run-dfinity/ok/text-iter.run-ir.ok | 10 +- test/run-dfinity/ok/text-iter.run-low.ok | 10 +- test/run-dfinity/ok/text-iter.run.ok | 10 +- test/run-dfinity/overflow.mo | 14 +- test/run-dfinity/query.mo | 6 +- test/run-dfinity/reference-params.mo | 6 +- test/run-dfinity/selftail.mo | 6 +- test/run-dfinity/show.mo | 2 +- test/run-dfinity/simple-throw.mo | 10 +- test/run-dfinity/tailpositions.mo | 14 +- test/run-dfinity/text-iter.mo | 66 +++---- test/run-dfinity/the-answer.mo | 2 +- test/run-drun/counter.mo | 4 +- test/run-drun/idl-any.mo | 2 +- test/run-drun/idl-option.mo | 4 +- test/run-drun/idl-record.mo | 8 +- test/run-drun/print-from-init.mo | 2 +- test/run-drun/query.mo | 6 +- test/run-drun/reject.mo | 14 +- test/run-release/debug.mo | 6 +- test/run/conversions.mo | 2 +- test/run/debug.mo | 2 +- test/run/for.mo | 2 +- test/run/idlHash.mo | 6 +- test/run/numeric-ops.mo | 4 +- test/run/variants.mo | 4 +- test/run/words.mo | 10 +- 86 files changed, 651 insertions(+), 651 deletions(-) diff --git a/README.md b/README.md index 280094425ea..6db21f37507 100644 --- a/README.md +++ b/README.md @@ -241,7 +241,7 @@ actor class Client(name : Text, server : Server) = this { }; public func send(msg : Text) { - print(name # " received " # msg # "\n"); + debugPrint(name # " received " # msg # "\n"); }; }; diff --git a/guide/as-slides.md b/guide/as-slides.md index 437b31bf576..8e5ebd39f18 100644 --- a/guide/as-slides.md +++ b/guide/as-slides.md @@ -545,7 +545,7 @@ alice.start("Alice", Server); // async send as function call * connects internal primitives with surface syntax (types, operations) * conversions like `intToWord32` -* side-effecting operations `printInt` +* side-effecting operations `debugPrintInt` (tie into execution environment) * utilities like `hashInt`, `clzWord32` @@ -608,7 +608,7 @@ actor class Client() = this { ``` ``` public func send(msg : Text) { - print(name # " received " # msg # "\n"); + debugPrint(name # " received " # msg # "\n"); }; }; ``` diff --git a/guide/chat.mo b/guide/chat.mo index bcef183c8d9..252d8f5af57 100644 --- a/guide/chat.mo +++ b/guide/chat.mo @@ -40,7 +40,7 @@ actor class Client() = this { }; public func send(msg : Text) { - print(name # " received " # msg # "\n"); + debugPrint(name # " received " # msg # "\n"); }; }; diff --git a/guide/schat.mo b/guide/schat.mo index 65c503f2d0f..2c2cbe6a3d6 100644 --- a/guide/schat.mo +++ b/guide/schat.mo @@ -42,7 +42,7 @@ actor class Client() = this { } }; send(msg : Text) { - print(name # " received " # msg # "\n"); + debugPrint(name # " received " # msg # "\n"); }; }; diff --git a/samples/app/client.mo b/samples/app/client.mo index 9c911992130..07ae7b5d0b1 100644 --- a/samples/app/client.mo +++ b/samples/app/client.mo @@ -17,7 +17,7 @@ actor class Client() = this { }; public func send(msg : Text) { - print(name # " received " # msg # "\n"); + debugPrint(name # " received " # msg # "\n"); }; }; diff --git a/samples/app/server.mo b/samples/app/server.mo index b8c6c7de039..afcccab76c6 100644 --- a/samples/app/server.mo +++ b/samples/app/server.mo @@ -49,7 +49,7 @@ actor class Server() = { case null { clients := n.tail }; case (?p) { p.tail := n.tail }; }; - print "(unsubscribe "; printInt id; print ")\n"; + debugPrint "(unsubscribe "; debugPrintInt id; debugPrint ")\n"; return; }; prev := next; diff --git a/src/prelude/prelude.ml b/src/prelude/prelude.ml index 2530744fab4..18d85330978 100644 --- a/src/prelude/prelude.ml +++ b/src/prelude/prelude.ml @@ -85,10 +85,10 @@ func @text_chars(xs : Text) : (() -> Iter) = // for testing func idlHash(x : Text) : Word32 { (prim "idlHash" : Text -> Word32) x }; -func printNat(x : Nat) { print (@text_of_Nat x) }; -func printInt(x : Int) { print (@text_of_Int x) }; -func printChar(x : Char) { print (charToText x) }; -func print(x : Text) { (prim "print" : Text -> ()) x }; +func debugPrint(x : Text) { (prim "print" : Text -> ()) x }; +func debugPrintNat(x : Nat) { debugPrint (@text_of_Nat x) }; +func debugPrintInt(x : Int) { debugPrint (@text_of_Int x) }; +func debugPrintChar(x : Char) { debugPrint (charToText x) }; func rts_version() : Text { (prim "rts_version" : () -> Text) () }; // Hashing diff --git a/stdlib/examples/actorspec/src/ActorSpec.mo b/stdlib/examples/actorspec/src/ActorSpec.mo index a3e4bf81668..a64cac3c92f 100644 --- a/stdlib/examples/actorspec/src/ActorSpec.mo +++ b/stdlib/examples/actorspec/src/ActorSpec.mo @@ -42,10 +42,10 @@ module { public func run(groups_ : [Group]) : Bool { let (groups, status) = getGroups(groups_); printGroups(groups, ""); - print("\n"); - print(printStatus(status)); - print("\n"); - print("\n"); + debugPrint("\n"); + debugPrint(printStatus(status)); + debugPrint("\n"); + debugPrint("\n"); status.failed == 0; }; @@ -86,7 +86,7 @@ module { case (_, _, _) { ":" # printStatus(status); }; }; }; - print(newline # indent # group.name # statusText # "\n"); + debugPrint(newline # indent # group.name # statusText # "\n"); printGroups(group.groups, indent # " "); }; }; diff --git a/stdlib/examples/produce-exchange/serverActor.mo b/stdlib/examples/produce-exchange/serverActor.mo index 6f7e486bedd..2ecb50a0275 100644 --- a/stdlib/examples/produce-exchange/serverActor.mo +++ b/stdlib/examples/produce-exchange/serverActor.mo @@ -1048,7 +1048,7 @@ been processed public func loadWorkload(params:T.WorkloadParams) : () { - func db(s:Text) = if false {print "Model::loadWorkload: "; print s; print "\n"}; + func db(s:Text) = if false {debugPrint "Model::loadWorkload: "; debugPrint s; debugPrint "\n"}; getModel().loadWorkload(params) }; diff --git a/stdlib/examples/produce-exchange/serverModel.mo b/stdlib/examples/produce-exchange/serverModel.mo index 889f0b44c61..2999da9e489 100644 --- a/stdlib/examples/produce-exchange/serverModel.mo +++ b/stdlib/examples/produce-exchange/serverModel.mo @@ -82,7 +82,7 @@ public class Model() { */ public func loadWorkload(params:T.WorkloadParams) : () { - func db(s:Text) = if false {print "Model::loadWorkload: "; print s; print "\n"}; + func db(s:Text) = if false {debugPrint "Model::loadWorkload: "; debugPrint s; debugPrint "\n"}; /**- generate add requests for these params: */ db "generate requests for workload..."; @@ -130,7 +130,7 @@ public class Model() { */ public func evalReq(req:L.Req) : Result { - if false {print "Model::evalReq: "; print (debug_show req); print "\n"; }; + if false {debugPrint "Model::evalReq: "; debugPrint (debug_show req); debugPrint "\n"; }; switch req { case (#reset) { /**- 1. reset each entity table: */ @@ -604,8 +604,8 @@ public class Model() { ================== */ - func debugOut (t:Text) { debug { print t } }; - func debugInt (i:Int) { debug { printInt i } }; + func debugOut (t:Text) { debug { debugPrint t } }; + func debugInt (i:Int) { debug { debugPrintInt i } }; func debugOff (t:Text) { debug { } }; func debugIntOff (i:Int) { debug { } }; diff --git a/stdlib/examples/produce-exchange/test/evalBulk.mo b/stdlib/examples/produce-exchange/test/evalBulk.mo index 7c0d0005bb9..580e14b632f 100644 --- a/stdlib/examples/produce-exchange/test/evalBulk.mo +++ b/stdlib/examples/produce-exchange/test/evalBulk.mo @@ -4,15 +4,15 @@ import Result = "../../../result.mo"; import Option = "../../../option.mo"; func printEntityCount(entname:Text, count:Nat) { - print ("- " # entname # " count: "); - printInt count; - print "\n"; + debugPrint ("- " # entname # " count: "); + debugPrintInt count; + debugPrint "\n"; }; func printLabeledCost(lab:Text, cost:Nat) { - print ("- " # lab # " cost: "); - printInt cost; - print "\n"; + debugPrint ("- " # lab # " cost: "); + debugPrintInt cost; + debugPrint "\n"; }; actor class Test() = this { @@ -21,7 +21,7 @@ actor class Test() = this { { let s = A.Server(); - print "\nExchange setup: Begin...\n====================================\n"; + debugPrint "\nExchange setup: Begin...\n====================================\n"; let pka = "beef"; let pkb = "dead"; @@ -123,7 +123,7 @@ actor class Test() = this { ////////////////////////////////////////////////////////////////// - print "\nRetailer queries\n====================================\n"; + debugPrint "\nRetailer queries\n====================================\n"; // do some queries await retailerQueryAll(s, pka, ? Result.assertUnwrapAny(uida)); @@ -132,7 +132,7 @@ actor class Test() = this { await retailerQueryAll(s, pkd, ? Result.assertUnwrapAny(uidd)); await retailerQueryAll(s, pke, ? Result.assertUnwrapAny(uide)); - print "\nQuery counts\n----------------\n"; + debugPrint "\nQuery counts\n----------------\n"; let counts = await s.getCounts(); printEntityCount("Retailer join", counts.retailer_join_count); @@ -146,84 +146,84 @@ actor class Test() = this { func retailerQueryAll(server:A.Server, pk:Text, r:?T.UserId) : async () { - print "\nRetailer "; + debugPrint "\nRetailer "; let retailerId: T.UserId = Option.unwrap(r); - printInt retailerId; - print " sends `retailerQueryAll`\n"; - print "------------------------------------\n"; + debugPrintInt retailerId; + debugPrint " sends `retailerQueryAll`\n"; + debugPrint "------------------------------------\n"; - print "\n## Query begin:\n"; + debugPrint "\n## Query begin:\n"; let res = Result.assertUnwrapAny( await server.retailerQueryAll(pk, retailerId, null, null) ); - print "\n## Query end."; + debugPrint "\n## Query end."; - print "\n## Query results ("; - printInt (res.len()); - print ")\n"; + debugPrint "\n## Query results ("; + debugPrintInt (res.len()); + debugPrint ")\n"; for (info in res.vals()) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; } }; func debugDumpAll(server:A.Server) : async () { - print "\nTruck type info\n----------------\n"; + debugPrint "\nTruck type info\n----------------\n"; for ( info in ((await server.allTruckTypeInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; - print "\nRegion info\n----------------\n"; + debugPrint "\nRegion info\n----------------\n"; for ( info in ((await server.allRegionInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; - print "\nProduce info\n----------------\n"; + debugPrint "\nProduce info\n----------------\n"; for ( info in ((await server.allProduceInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; - print "\nProducer info\n----------------\n"; + debugPrint "\nProducer info\n----------------\n"; for ( info in ((await server.allProducerInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; - print "\nTransporter info\n----------------\n"; + debugPrint "\nTransporter info\n----------------\n"; for ( info in ((await server.allTransporterInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; - print "\nRetailer info\n----------------\n"; + debugPrint "\nRetailer info\n----------------\n"; for ( info in ((await server.allRetailerInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; - print "\nInventory info\n----------------\n"; + debugPrint "\nInventory info\n----------------\n"; for ( info in ((await server.allInventoryInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; - print "\nRoute info\n----------------\n"; + debugPrint "\nRoute info\n----------------\n"; for ( info in ((await server.allRouteInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; }; diff --git a/stdlib/examples/produce-exchange/test/loadWorkloadAndQuery.mo b/stdlib/examples/produce-exchange/test/loadWorkloadAndQuery.mo index 388c8f33a5c..af8658b8f41 100644 --- a/stdlib/examples/produce-exchange/test/loadWorkloadAndQuery.mo +++ b/stdlib/examples/produce-exchange/test/loadWorkloadAndQuery.mo @@ -1,7 +1,7 @@ func scaledParams(region_count_:Nat, factor:Nat) : T.WorkloadParams = { - print "## region_count = "; printInt region_count_; print "\n"; - print "## factor = "; printInt factor; print "\n"; - print "## data format: source-region, evaluation-count:\n"; + debugPrint "## region_count = "; debugPrintInt region_count_; debugPrint "\n"; + debugPrint "## factor = "; debugPrintInt factor; debugPrint "\n"; + debugPrint "## data format: source-region, evaluation-count:\n"; shared { region_count = region_count_:Nat; day_count = 3:Nat; diff --git a/stdlib/examples/produce-exchange/test/loadWorkloadAndQueryBig.mo b/stdlib/examples/produce-exchange/test/loadWorkloadAndQueryBig.mo index cdf4772de9b..6a5cd73fc3c 100644 --- a/stdlib/examples/produce-exchange/test/loadWorkloadAndQueryBig.mo +++ b/stdlib/examples/produce-exchange/test/loadWorkloadAndQueryBig.mo @@ -30,26 +30,26 @@ actor class Test() = this { ///////////////////////////////////////////////////////////////////////////////////// let s = server; - print "\nExchange setup: Begin...\n====================================\n"; + debugPrint "\nExchange setup: Begin...\n====================================\n"; await s.loadWorkload(params); if false { - print "\nRetailer queries\n====================================\n"; + debugPrint "\nRetailer queries\n====================================\n"; // do a query for each retailer: for (r in range(0, params.retailer_count)) { await retailerQueryAll("", r) }; }; - print "\nQuery counts\n----------------\n"; + debugPrint "\nQuery counts\n----------------\n"; let counts = await s.getCounts(); printEntityCount("Retailer join", counts.retailer_join_count); printEntityCount("Retailer query", counts.retailer_query_count); printLabeledCost("Retailer query", counts.retailer_query_cost); - print "\nDump all\n====================================\n"; - print (debug_show (await s.getCounts())); + debugPrint "\nDump all\n====================================\n"; + debugPrint (debug_show (await s.getCounts())); if false { await debugDumpAll() } @@ -61,107 +61,107 @@ actor class Test() = this { //func retailerQueryAll(server:A.Server, pk:Text, r:?T.UserId) : async () { func retailerQueryAll(pk:Text, retailerId:T.RetailerId) : async () { - print "\nRetailer "; - printInt retailerId; - print " sends `retailerQueryAll`\n"; - print "------------------------------------\n"; + debugPrint "\nRetailer "; + debugPrintInt retailerId; + debugPrint " sends `retailerQueryAll`\n"; + debugPrint "------------------------------------\n"; - print "\n## Query begin:\n"; + debugPrint "\n## Query begin:\n"; let res = Result.assertUnwrapAny( await server.retailerQueryAll(pk, retailerId, null, null) ); - print "\n## Query end."; + debugPrint "\n## Query end."; - print "\n## Query results ("; - printInt (res.len()); - print ")\n"; + debugPrint "\n## Query results ("; + debugPrintInt (res.len()); + debugPrint ")\n"; for (info in res.vals()) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; } }; //func debugDumpAll(server:A.Server) : async () { func debugDumpAll() : async () { - print "\nTruck type info\n----------------\n"; + debugPrint "\nTruck type info\n----------------\n"; for ( info in ((await server.allTruckTypeInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; - print "\nRegion info\n----------------\n"; + debugPrint "\nRegion info\n----------------\n"; for ( info in ((await server.allRegionInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; - print "\nProduce info\n----------------\n"; + debugPrint "\nProduce info\n----------------\n"; for ( info in ((await server.allProduceInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; - print "\nProducer info\n----------------\n"; + debugPrint "\nProducer info\n----------------\n"; for ( info in ((await server.allProducerInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; - print "\nTransporter info\n----------------\n"; + debugPrint "\nTransporter info\n----------------\n"; for ( info in ((await server.allTransporterInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; - print "\nRetailer info\n----------------\n"; + debugPrint "\nRetailer info\n----------------\n"; for ( info in ((await server.allRetailerInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; - { print "\nInventory info\n----------------\n"; + { debugPrint "\nInventory info\n----------------\n"; let items = await server.allInventoryInfo(); - print "total count of "; - printInt (items.len()); - print ":\n"; + debugPrint "total count of "; + debugPrintInt (items.len()); + debugPrint ":\n"; for ( info in items.vals() ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; }; - { print "\nRoute info\n----------------\n"; + { debugPrint "\nRoute info\n----------------\n"; let routes = await server.allRouteInfo(); - print "total count of "; - printInt (routes.len()); - print ":\n"; + debugPrint "total count of "; + debugPrintInt (routes.len()); + debugPrint ":\n"; for ( info in (routes.vals()) ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; }; }; func printEntityCount(entname:Text, count:Nat) { - print ("- " # entname # " count: "); - printInt count; - print "\n"; + debugPrint ("- " # entname # " count: "); + debugPrintInt count; + debugPrint "\n"; }; func printLabeledCost(lab:Text, cost:Nat) { - print ("- " # lab # " cost: "); - printInt cost; - print "\n"; + debugPrint ("- " # lab # " cost: "); + debugPrintInt cost; + debugPrint "\n"; }; let test = Test(); diff --git a/stdlib/examples/produce-exchange/test/producerRemInventory.mo b/stdlib/examples/produce-exchange/test/producerRemInventory.mo index f205e62d362..47626266f72 100644 --- a/stdlib/examples/produce-exchange/test/producerRemInventory.mo +++ b/stdlib/examples/produce-exchange/test/producerRemInventory.mo @@ -4,15 +4,15 @@ import Result = "../../../result.mo"; import Option = "../../../option.mo"; func printEntityCount(entname:Text, count:Nat) { - print ("- " # entname # " count: "); - printInt count; - print "\n"; + debugPrint ("- " # entname # " count: "); + debugPrintInt count; + debugPrint "\n"; }; func printLabeledCost(lab:Text, cost:Nat) { - print ("- " # lab # " cost: "); - printInt cost; - print "\n"; + debugPrint ("- " # lab # " cost: "); + debugPrintInt cost; + debugPrint "\n"; }; actor class Test() = this { @@ -21,7 +21,7 @@ actor class Test() = this { { let s = A.Server(); - print "\nExchange setup: Begin...\n====================================\n"; + debugPrint "\nExchange setup: Begin...\n====================================\n"; let pka = "beef"; let pkb = "dead"; @@ -124,22 +124,22 @@ actor class Test() = this { await debugDumpInventory(s, pka, 0); await debugDumpAll(s); - print "\n First time: Producer remove query\n====================================\n"; + debugPrint "\n First time: Producer remove query\n====================================\n"; let rem0 = await s.producerRemInventory(pka, 0); - print "- first producerRemInventory(pka, 0) result:"; - print (debug_show rem0); - print "\n"; + debugPrint "- first producerRemInventory(pka, 0) result:"; + debugPrint (debug_show rem0); + debugPrint "\n"; await debugDumpInventory(s, pka, 0); await debugDumpAll(s); - print "\n Second time: Producer remove query\n====================================\n"; + debugPrint "\n Second time: Producer remove query\n====================================\n"; let rem0b = await s.producerRemInventory(pka, 0); - print "- second producerRemInventory(pka, 0) result:"; - print (debug_show rem0b); - print "\n"; + debugPrint "- second producerRemInventory(pka, 0) result:"; + debugPrint (debug_show rem0b); + debugPrint "\n"; await debugDumpInventory(s, pka, 0); await debugDumpAll(s); @@ -148,75 +148,75 @@ actor class Test() = this { }; func debugDumpInventory(server:A.Server, pk:T.PublicKey, p:T.ProducerId) : async () { - print "\nProducer "; - printInt p; - print "'s inventory:\n--------------------------------\n"; + debugPrint "\nProducer "; + debugPrintInt p; + debugPrint "'s inventory:\n--------------------------------\n"; let res = await server.producerAllInventoryInfo(pk, p); let items = Result.assertUnwrapAny<[T.InventoryInfo]>(res); for (i in items.keys()) { - printInt i; - print ". "; - print (debug_show (items[i])); - print "\n"; + debugPrintInt i; + debugPrint ". "; + debugPrint (debug_show (items[i])); + debugPrint "\n"; } }; func debugDumpAll(server:A.Server) : async () { - print "\nTruck type info\n----------------\n"; + debugPrint "\nTruck type info\n----------------\n"; for ( info in ((await server.allTruckTypeInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; - print "\nRegion info\n----------------\n"; + debugPrint "\nRegion info\n----------------\n"; for ( info in ((await server.allRegionInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; - print "\nProduce info\n----------------\n"; + debugPrint "\nProduce info\n----------------\n"; for ( info in ((await server.allProduceInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; - print "\nProducer info\n----------------\n"; + debugPrint "\nProducer info\n----------------\n"; for ( info in ((await server.allProducerInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; - print "\nTransporter info\n----------------\n"; + debugPrint "\nTransporter info\n----------------\n"; for ( info in ((await server.allTransporterInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; - print "\nRetailer info\n----------------\n"; + debugPrint "\nRetailer info\n----------------\n"; for ( info in ((await server.allRetailerInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; - print "\nInventory info\n----------------\n"; + debugPrint "\nInventory info\n----------------\n"; for ( info in ((await server.allInventoryInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; - print "\nRoute info\n----------------\n"; + debugPrint "\nRoute info\n----------------\n"; for ( info in ((await server.allRouteInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; }; diff --git a/stdlib/examples/produce-exchange/test/profileFastCounts.mo b/stdlib/examples/produce-exchange/test/profileFastCounts.mo index 9ec1c21ad2f..b9cc55987a2 100644 --- a/stdlib/examples/produce-exchange/test/profileFastCounts.mo +++ b/stdlib/examples/produce-exchange/test/profileFastCounts.mo @@ -1,4 +1,4 @@ -// print a table of numbers (somewhat) quickly. +// debugPrint a table of numbers (somewhat) quickly. // we correlate these numbers with times that we // measure elsewhere, where these numbers are not available. @@ -10,10 +10,10 @@ let m = Model.Model(); let scales = [1,2,3,4,5,6,7,8,9,10, 20,50,100]; -print "# column: region count\n"; -print "# column: workload scale\n"; -print "# column: inventory count\n"; -print "# column: route count\n"; +debugPrint "# column: region count\n"; +debugPrint "# column: workload scale\n"; +debugPrint "# column: inventory count\n"; +debugPrint "# column: route count\n"; for (scale in scales.vals()) { let (ic, rc) = m.countAddReqs(3, 1, @@ -22,12 +22,12 @@ for (scale in scales.vals()) { 5 * scale, 5); - printInt 5; - print ", "; - printInt scale; - print ", "; - printInt ic; - print ", "; - printInt rc; - print "\n"; + debugPrintInt 5; + debugPrint ", "; + debugPrintInt scale; + debugPrint ", "; + debugPrintInt ic; + debugPrint ", "; + debugPrintInt rc; + debugPrint "\n"; }; diff --git a/stdlib/examples/produce-exchange/test/retailerReserveMany.mo b/stdlib/examples/produce-exchange/test/retailerReserveMany.mo index 051c613ec47..949e50d94e0 100644 --- a/stdlib/examples/produce-exchange/test/retailerReserveMany.mo +++ b/stdlib/examples/produce-exchange/test/retailerReserveMany.mo @@ -4,15 +4,15 @@ import Result = "../../../result.mo"; import Option = "../../../option.mo"; func printEntityCount(entname:Text, count:Nat) { - print ("- " # entname # " count: "); - printInt count; - print "\n"; + debugPrint ("- " # entname # " count: "); + debugPrintInt count; + debugPrint "\n"; }; func printLabeledCost(lab:Text, cost:Nat) { - print ("- " # lab # " cost: "); - printInt cost; - print "\n"; + debugPrint ("- " # lab # " cost: "); + debugPrintInt cost; + debugPrint "\n"; }; actor class Test() = this { @@ -21,7 +21,7 @@ actor class Test() = this { { let s = A.Server(); - print "\nExchange setup: Begin...\n====================================\n"; + debugPrint "\nExchange setup: Begin...\n====================================\n"; let pka = "beef"; let pkb = "dead"; @@ -97,7 +97,7 @@ actor class Test() = this { ////////////////////////////////////////////////////////////////// - print "\nExchange setup: Done.\n====================================\n"; + debugPrint "\nExchange setup: Done.\n====================================\n"; let inventoryCount1 = await debugDumpInventory(s, pka, 0); let routeCount1 = await debugDumpRoutes(s, pka, 0); @@ -105,7 +105,7 @@ actor class Test() = this { ////////////////////////////////////////////////////////////////// - print "\nRetailer queries\n====================================\n"; + debugPrint "\nRetailer queries\n====================================\n"; // do some queries await retailerQueryAll(s, pka, ? Result.assertUnwrapAny(uida)); @@ -114,17 +114,17 @@ actor class Test() = this { await retailerQueryAll(s, pkd, ? Result.assertUnwrapAny(uidd)); await retailerQueryAll(s, pke, ? Result.assertUnwrapAny(uide)); - print "\nQuery counts\n----------------\n"; + debugPrint "\nQuery counts\n----------------\n"; let counts = await s.getCounts(); printEntityCount("Retailer join", counts.retailer_join_count); printEntityCount("Retailer query", counts.retailer_query_count); printLabeledCost("Retailer query", counts.retailer_query_cost); - print "\nRetailer reservations\n====================================\n"; + debugPrint "\nRetailer reservations\n====================================\n"; - print "\nRetailer reservations: begin...\n------------------------\n"; + debugPrint "\nRetailer reservations: begin...\n------------------------\n"; let rrm = await s.retailerReserveMany(pka, @@ -135,24 +135,24 @@ actor class Test() = this { let urrm = Result.assertUnwrapAny<[Result.Result<(T.ReservedInventoryId, T.ReservedRouteId), T.ServerErr>]>(rrm); - print "\nRetailer reservations: results:\n---------------------------------\n"; + debugPrint "\nRetailer reservations: results:\n---------------------------------\n"; for (i in urrm.keys()) { - printInt i; - print ". "; - print (debug_show urrm[i]); - print "\n"; + debugPrintInt i; + debugPrint ". "; + debugPrint (debug_show urrm[i]); + debugPrint "\n"; }; - print "\nRetailer reservations: results[0]: expect success.\n---------------------------------\n"; + debugPrint "\nRetailer reservations: results[0]: expect success.\n---------------------------------\n"; let (ri0, rr0) = Result.assertUnwrapAny<(T.ReservedInventoryId, T.ReservedRouteId)>(urrm[0]); - print "- "; - print (debug_show (ri0, rr0)); - print "\n"; + debugPrint "- "; + debugPrint (debug_show (ri0, rr0)); + debugPrint "\n"; - print "\nRetailer reservations: results[1]: expect error: already reserved by us!\n---------------------------------\n"; + debugPrint "\nRetailer reservations: results[1]: expect error: already reserved by us!\n---------------------------------\n"; Result.assertErrAs (urrm[1], @@ -160,7 +160,7 @@ actor class Test() = this { switch err { case (#idErr entid) { switch entid { - case (?(#inventory 0)) print "- error is `#idErr(?(#inventory 0))`\n"; + case (?(#inventory 0)) debugPrint "- error is `#idErr(?(#inventory 0))`\n"; case _ assert false; } }; @@ -168,9 +168,9 @@ actor class Test() = this { } }); - print "\nRetailer reservations: done.\n---------------------------------\n"; + debugPrint "\nRetailer reservations: done.\n---------------------------------\n"; - print "\nExchange interactions: Done.\n====================================\n"; + debugPrint "\nExchange interactions: Done.\n====================================\n"; let inventoryCount2 = await debugDumpInventory(s, pka, 0); let routeCount2 = await debugDumpRoutes(s, pka, 0); @@ -183,117 +183,117 @@ actor class Test() = this { }; func debugDumpInventory(server:A.Server, pk:T.PublicKey, p:T.ProducerId) : async Nat { - print "\nProducer "; - printInt p; - print "'s inventory:\n--------------------------------\n"; + debugPrint "\nProducer "; + debugPrintInt p; + debugPrint "'s inventory:\n--------------------------------\n"; let res = await server.producerAllInventoryInfo(pk, p); let items = Result.assertUnwrapAny<[T.InventoryInfo]>(res); for (i in items.keys()) { - printInt i; - print ". "; - print (debug_show (items[i])); - print "\n"; + debugPrintInt i; + debugPrint ". "; + debugPrint (debug_show (items[i])); + debugPrint "\n"; }; - print "(list end)\n"; + debugPrint "(list end)\n"; items.len() }; func debugDumpRoutes(server:A.Server, pk:T.PublicKey, t:T.TransporterId) : async Nat { - print "\nTransporter "; - printInt t; - print "'s routes:\n--------------------------------\n"; + debugPrint "\nTransporter "; + debugPrintInt t; + debugPrint "'s routes:\n--------------------------------\n"; let res = await server.transporterAllRouteInfo(pk, t); let items = Result.assertUnwrapAny<[T.RouteInfo]>(res); for (i in items.keys()) { - printInt i; - print ". "; - print (debug_show (items[i])); - print "\n"; + debugPrintInt i; + debugPrint ". "; + debugPrint (debug_show (items[i])); + debugPrint "\n"; }; - print "(list end)\n"; + debugPrint "(list end)\n"; items.len() }; func retailerQueryAll(server:A.Server, pk:Text, r:?T.UserId) : async () { - print "\nRetailer "; + debugPrint "\nRetailer "; let retailerId: T.UserId = Option.unwrap(r); - printInt retailerId; - print " sends `retailerQueryAll`\n"; - print "------------------------------------\n"; + debugPrintInt retailerId; + debugPrint " sends `retailerQueryAll`\n"; + debugPrint "------------------------------------\n"; - print "\n## Query begin:\n"; + debugPrint "\n## Query begin:\n"; let res = Result.assertUnwrapAny( await server.retailerQueryAll(pk, retailerId, null, null) ); - print "\n## Query end."; + debugPrint "\n## Query end."; - print "\n## Query results ("; - printInt (res.len()); - print ")\n"; + debugPrint "\n## Query results ("; + debugPrintInt (res.len()); + debugPrint ")\n"; for (info in res.vals()) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; } }; func debugDumpAll(server:A.Server) : async () { - print "\nTruck type info\n----------------\n"; + debugPrint "\nTruck type info\n----------------\n"; for ( info in ((await server.allTruckTypeInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; - print "\nRegion info\n----------------\n"; + debugPrint "\nRegion info\n----------------\n"; for ( info in ((await server.allRegionInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; - print "\nProduce info\n----------------\n"; + debugPrint "\nProduce info\n----------------\n"; for ( info in ((await server.allProduceInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; - print "\nProducer info\n----------------\n"; + debugPrint "\nProducer info\n----------------\n"; for ( info in ((await server.allProducerInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; - print "\nTransporter info\n----------------\n"; + debugPrint "\nTransporter info\n----------------\n"; for ( info in ((await server.allTransporterInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; - print "\nRetailer info\n----------------\n"; + debugPrint "\nRetailer info\n----------------\n"; for ( info in ((await server.allRetailerInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; - print "\nInventory info\n----------------\n"; + debugPrint "\nInventory info\n----------------\n"; for ( info in ((await server.allInventoryInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; - print "\nRoute info\n----------------\n"; + debugPrint "\nRoute info\n----------------\n"; for ( info in ((await server.allRouteInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; }; diff --git a/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.mo b/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.mo index 080b47f906f..089237e312a 100644 --- a/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.mo +++ b/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.mo @@ -4,15 +4,15 @@ import Result = "../../../result.mo"; import Option = "../../../option.mo"; func printEntityCount(entname:Text, count:Nat) { - print ("- " # entname # " count: "); - printInt count; - print "\n"; + debugPrint ("- " # entname # " count: "); + debugPrintInt count; + debugPrint "\n"; }; func printLabeledCost(lab:Text, cost:Nat) { - print ("- " # lab # " cost: "); - printInt cost; - print "\n"; + debugPrint ("- " # lab # " cost: "); + debugPrintInt cost; + debugPrint "\n"; }; actor class Test() = this { @@ -21,7 +21,7 @@ actor class Test() = this { { let s = A.Server(); - print "\nExchange setup: Begin...\n====================================\n"; + debugPrint "\nExchange setup: Begin...\n====================================\n"; let pka = "beef"; let pkb = "dead"; @@ -289,13 +289,13 @@ actor class Test() = this { ////////////////////////////////////////////////////////////////// - print "\nExchange setup: Done.\n====================================\n"; + debugPrint "\nExchange setup: Done.\n====================================\n"; await debugDumpAll(s); ////////////////////////////////////////////////////////////////// - print "\nRetailer queries\n====================================\n"; + debugPrint "\nRetailer queries\n====================================\n"; // do some queries await retailerQueryAll(s, pka, ? Result.assertUnwrapAny(uida)); @@ -304,32 +304,32 @@ actor class Test() = this { await retailerQueryAll(s, pkd, ? Result.assertUnwrapAny(uidd)); await retailerQueryAll(s, pke, ? Result.assertUnwrapAny(uide)); - print "\nQuery counts\n----------------\n"; + debugPrint "\nQuery counts\n----------------\n"; let counts = await s.getCounts(); printEntityCount("Retailer join", counts.retailer_join_count); printEntityCount("Retailer query", counts.retailer_query_count); printLabeledCost("Retailer query", counts.retailer_query_cost); - print "\nAuthentication test:\n====================================\n"; + debugPrint "\nAuthentication test:\n====================================\n"; - print "\npk a == uid a"; + debugPrint "\npk a == uid a"; assert(await s.validateUser(pka, Result.assertUnwrapAny(uida))); - print "\npk b == uid b"; + debugPrint "\npk b == uid b"; assert(await s.validateUser(pkb, Result.assertUnwrapAny(uidb))); - print "\npk a != uid b"; + debugPrint "\npk a != uid b"; assert(not(await s.validateUser(pka, Result.assertUnwrapAny(uidb)))); - print "\npk b != uid a"; + debugPrint "\npk b != uid a"; assert(not(await s.validateUser(pkb, Result.assertUnwrapAny(uida)))); ////////////////////////////////////////////////////////////////// // xxx --- todo: separate test(s) for expected failures // User c should not be able to remove user a's route if false { - print "\nAuthentication test, expect Result.assertion failure:\n"; + debugPrint "\nAuthentication test, expect Result.assertion failure:\n"; ignore(await s.transporterRemRoute(pkc, Result.assertUnwrapAny(rta_a_c_tta))) }; - print "\n"; + debugPrint "\n"; }) }; }; @@ -337,84 +337,84 @@ actor class Test() = this { func retailerQueryAll(server:A.Server, pk:Text, r:?T.UserId) : async () { - print "\nRetailer "; + debugPrint "\nRetailer "; let retailerId: T.UserId = Option.unwrap(r); - printInt retailerId; - print " sends `retailerQueryAll`\n"; - print "------------------------------------\n"; + debugPrintInt retailerId; + debugPrint " sends `retailerQueryAll`\n"; + debugPrint "------------------------------------\n"; - print "\n## Query begin:\n"; + debugPrint "\n## Query begin:\n"; let res = Result.assertUnwrapAny( await server.retailerQueryAll(pk, retailerId, null, null) ); - print "\n## Query end."; + debugPrint "\n## Query end."; - print "\n## Query results ("; - printInt (res.len()); - print ")\n"; + debugPrint "\n## Query results ("; + debugPrintInt (res.len()); + debugPrint ")\n"; for (info in res.vals()) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; } }; func debugDumpAll(server:A.Server) : async () { - print "\nTruck type info\n----------------\n"; + debugPrint "\nTruck type info\n----------------\n"; for ( info in ((await server.allTruckTypeInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; - print "\nRegion info\n----------------\n"; + debugPrint "\nRegion info\n----------------\n"; for ( info in ((await server.allRegionInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; - print "\nProduce info\n----------------\n"; + debugPrint "\nProduce info\n----------------\n"; for ( info in ((await server.allProduceInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; - print "\nProducer info\n----------------\n"; + debugPrint "\nProducer info\n----------------\n"; for ( info in ((await server.allProducerInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; - print "\nTransporter info\n----------------\n"; + debugPrint "\nTransporter info\n----------------\n"; for ( info in ((await server.allTransporterInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; - print "\nRetailer info\n----------------\n"; + debugPrint "\nRetailer info\n----------------\n"; for ( info in ((await server.allRetailerInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; - print "\nInventory info\n----------------\n"; + debugPrint "\nInventory info\n----------------\n"; for ( info in ((await server.allInventoryInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; - print "\nRoute info\n----------------\n"; + debugPrint "\nRoute info\n----------------\n"; for ( info in ((await server.allRouteInfo()).vals()) ) { - print "- "; - print (debug_show info); - print "\n"; + debugPrint "- "; + debugPrint (debug_show info); + debugPrint "\n"; }; }; diff --git a/stdlib/hash.mo b/stdlib/hash.mo index e772bdb9219..0bf6bd19fa7 100644 --- a/stdlib/hash.mo +++ b/stdlib/hash.mo @@ -123,9 +123,9 @@ public module BitVec { public func bitsPrintRev(bits:BitVec) { for (j in range(0, length() - 1)) { if (getHashBit(bits, j)) { - print "1" + debugPrint "1" } else { - print "0" + debugPrint "0" } } }; @@ -133,9 +133,9 @@ public module BitVec { public func hashPrintRev(bits:BitVec) { for (j in range(length() - 1, 0)) { if (getHashBit(bits, j)) { - print "1" + debugPrint "1" } else { - print "0" + debugPrint "0" } } }; @@ -200,22 +200,22 @@ public module BitList { public func bitsPrintRev(bits:BitList) { switch bits { - case null { print "" }; + case null { debugPrint "" }; case (?(bit,bits_)) { bitsPrintRev(bits_); - if bit { print "1R." } - else { print "0L." } + if bit { debugPrint "1R." } + else { debugPrint "0L." } } } }; public func hashPrintRev(bits:BitList) { switch bits { - case null { print "" }; + case null { debugPrint "" }; case (?(bit,bits_)) { hashPrintRev(bits_); - if bit { print "1" } - else { print "0" } + if bit { debugPrint "1" } + else { debugPrint "0" } } } }; diff --git a/stdlib/prelude.mo b/stdlib/prelude.mo index 6199cf0d996..0405bef8f6f 100644 --- a/stdlib/prelude.mo +++ b/stdlib/prelude.mo @@ -19,7 +19,7 @@ some further experience and discussion. Until then, they live here. */ public func printLn(x : Text) { - print(x # "\n"); + debugPrint(x # "\n"); }; /*** diff --git a/stdlib/trie2.mo b/stdlib/trie2.mo index ca4654ac6e5..44181962b7b 100644 --- a/stdlib/trie2.mo +++ b/stdlib/trie2.mo @@ -142,20 +142,20 @@ public func isValid (t:Trie, enforceNormal:Bool) : Bool { ( List.all<(Key,V)>( l.keyvals, func ((k:Key,v:V)):Bool{ - //{ print "testing hash..."; true } + //{ debugPrint "testing hash..."; true } //and ((k.hash & mask) == bits) or - { print "\nmalformed hash!:\n"; - printInt (word32ToNat(k.hash)); - print "\n (key hash) != (path bits): \n"; - printInt (word32ToNat(bits)); - print "\nmask : "; printInt (word32ToNat(mask)); - print "\n"; + { debugPrint "\nmalformed hash!:\n"; + debugPrintInt (word32ToNat(k.hash)); + debugPrint "\n (key hash) != (path bits): \n"; + debugPrintInt (word32ToNat(bits)); + debugPrint "\nmask : "; debugPrintInt (word32ToNat(mask)); + debugPrint "\n"; false } } ) or - { print "one or more hashes are malformed"; false } + { debugPrint "one or more hashes are malformed"; false } ) }; case (#branch b) { @@ -166,7 +166,7 @@ public func isValid (t:Trie, enforceNormal:Bool) : Bool { let mask1 = mask | (natToWord32(1) << bitpos1); let bits1 = bits | (natToWord32(1) << bitpos1); let sum = count(b.left) + count(b.right); - (b.count == sum or { print "malformed count"; false }) + (b.count == sum or { debugPrint "malformed count"; false }) and rec(b.left, ?bitpos1, bits, mask1) and diff --git a/test/bugs/aritybug.mo b/test/bugs/aritybug.mo index caf9bb00324..f2d116f3816 100644 --- a/test/bugs/aritybug.mo +++ b/test/bugs/aritybug.mo @@ -16,7 +16,7 @@ shared func fu_u(a:Int,) : async (Int,) { let _ : async (Int,) = async { let (x,) = await fu_u(1); // * assert(x==2); - print t; + debugPrint t; return (x,); }; }; diff --git a/test/fail/actor-reexport.mo b/test/fail/actor-reexport.mo index 27cd31e0176..a8de5e653b3 100644 --- a/test/fail/actor-reexport.mo +++ b/test/fail/actor-reexport.mo @@ -1,6 +1,6 @@ actor test { public func exported() { - print("exported()\n"); + debugPrint("exported()\n"); }; public let exported_too = exported; }; diff --git a/test/fail/branch-before-define.mo b/test/fail/branch-before-define.mo index 1c8938e942b..8f4013aefc7 100644 --- a/test/fail/branch-before-define.mo +++ b/test/fail/branch-before-define.mo @@ -8,8 +8,8 @@ func f():() -> Int { }; }; -print "1\n"; +debugPrint "1\n"; let h = f(); -print "2\n"; +debugPrint "2\n"; let wrong = h(); diff --git a/test/fail/objpat-infer.mo b/test/fail/objpat-infer.mo index e087588fa58..53815989d5d 100644 --- a/test/fail/objpat-infer.mo +++ b/test/fail/objpat-infer.mo @@ -4,7 +4,7 @@ ignore (switch (object {}) { case {a} 42 }); // checks -for ({} in [object {}].vals()) { print "hey" }; +for ({} in [object {}].vals()) { debugPrint "hey" }; // infers diff --git a/test/fail/objpat-mutable.mo b/test/fail/objpat-mutable.mo index 0b708aa7b93..4547e41a22b 100644 --- a/test/fail/objpat-mutable.mo +++ b/test/fail/objpat-mutable.mo @@ -2,8 +2,8 @@ type WithMut = { var x : Int; y : Text }; func reject (o : WithMut) = switch o { - case { y = "good" } { print "good" }; - //case { x = -42 } { print "bad" }; // backend: Invalid_argument("unop") - //case { x = (42 : Int) } { print "bad" }; // tc: cannot consume expected - case { x } { printInt x } + case { y = "good" } { debugPrint "good" }; + //case { x = -42 } { debugPrint "bad" }; // backend: Invalid_argument("unop") + //case { x = (42 : Int) } { debugPrint "bad" }; // tc: cannot consume expected + case { x } { debugPrintInt x } }; diff --git a/test/fail/return-before-define.mo b/test/fail/return-before-define.mo index b9fcdf53efc..b40307b33aa 100644 --- a/test/fail/return-before-define.mo +++ b/test/fail/return-before-define.mo @@ -6,8 +6,8 @@ func f():() -> Int { }; }; -print "1\n"; +debugPrint "1\n"; let h = f(); -print "2\n"; +debugPrint "2\n"; let wrong = h(); diff --git a/test/fail/use-before-define.mo b/test/fail/use-before-define.mo index 99d43b94c1e..442a59688e3 100644 --- a/test/fail/use-before-define.mo +++ b/test/fail/use-before-define.mo @@ -1,4 +1,4 @@ func f():Int = x; let y = f(); let x = 1; -printInt(x); +debugPrintInt(x); diff --git a/test/lsp-int/test-project/lib/option.mo b/test/lsp-int/test-project/lib/option.mo index a980e9caa76..7fd53890a47 100644 --- a/test/lsp-int/test-project/lib/option.mo +++ b/test/lsp-int/test-project/lib/option.mo @@ -135,8 +135,8 @@ public func assertNull(x: ?A) = assertNullAny(x); */ public func printOpInt(x : ?Int) = switch x { - case null { print "null" }; - case (?x_) { print "?"; printInt x_ }; + case null { debugPrint "null" }; + case (?x_) { debugPrint "?"; debugPrintInt x_ }; }; public func apply(f : ?(A -> B), x : ?A) : ?B { diff --git a/test/lsp-int/test-project/lib/prelude.mo b/test/lsp-int/test-project/lib/prelude.mo index 6199cf0d996..0405bef8f6f 100644 --- a/test/lsp-int/test-project/lib/prelude.mo +++ b/test/lsp-int/test-project/lib/prelude.mo @@ -19,7 +19,7 @@ some further experience and discussion. Until then, they live here. */ public func printLn(x : Text) { - print(x # "\n"); + debugPrint(x # "\n"); }; /*** diff --git a/test/run-dfinity/array-out-of-bounds.mo b/test/run-dfinity/array-out-of-bounds.mo index e1502a20faf..38ec4293133 100644 --- a/test/run-dfinity/array-out-of-bounds.mo +++ b/test/run-dfinity/array-out-of-bounds.mo @@ -3,9 +3,9 @@ let b = []; ignore(async { ignore(a[5]); - print("Unreachable code reached\n"); + debugPrint("Unreachable code reached\n"); }); ignore(async { ignore(b[0]); - print("Unreachable code reached\n"); + debugPrint("Unreachable code reached\n"); }); diff --git a/test/run-dfinity/async-loop-while.mo b/test/run-dfinity/async-loop-while.mo index 9677bc085e3..9e38145413b 100644 --- a/test/run-dfinity/async-loop-while.mo +++ b/test/run-dfinity/async-loop-while.mo @@ -4,7 +4,7 @@ async { { var i = 0; var j = 0; loop { - printNat(j); + debugPrintNat(j); assert(j == i); i += 1; j += 1; @@ -17,7 +17,7 @@ async { var i = 0; var j = 0; loop { - printNat(j); + debugPrintNat(j); assert(j == i); i += 1; j += 1; @@ -29,7 +29,7 @@ async { var i = 0; var j = 0; loop { - printNat(j); + debugPrintNat(j); assert(j == i); await (async (i += 1)); j += 1; @@ -46,7 +46,7 @@ async { break l; assert(false); }; - printNat(j); + debugPrintNat(j); assert(j == i); await (async (i += 1)); j += 1; diff --git a/test/run-dfinity/async-loop.mo b/test/run-dfinity/async-loop.mo index 35453921383..bb0d06a971d 100644 --- a/test/run-dfinity/async-loop.mo +++ b/test/run-dfinity/async-loop.mo @@ -5,7 +5,7 @@ async { var j = 0; label l loop { - printNat(j); + debugPrintNat(j); assert(j == i); i += 1; j += 1; @@ -20,7 +20,7 @@ async { var j = 0; label l loop { - printNat(j); + debugPrintNat(j); assert(j == i); i += 1; j += 1; @@ -35,7 +35,7 @@ async { var j = 0; label l loop { - printNat(j); + debugPrintNat(j); assert(j == i); await (async (i += 1)); j += 1; @@ -54,7 +54,7 @@ async { break l; assert(false); }; - printNat(j); + debugPrintNat(j); assert(j == i); await (async (i += 1)); j += 1; diff --git a/test/run-dfinity/async-new-obj.mo b/test/run-dfinity/async-new-obj.mo index 339009c0a7f..8fc5b63e46c 100644 --- a/test/run-dfinity/async-new-obj.mo +++ b/test/run-dfinity/async-new-obj.mo @@ -8,9 +8,9 @@ let a = async { public func get_b() : Text { b }; }; let (a, b) = (o.get_a(), o.get_b()); - print a; - print b; - print "\n"; + debugPrint a; + debugPrint b; + debugPrint "\n"; }; let b = async { @@ -21,9 +21,9 @@ let b = async { public func get_b() : Text { b }; }; let (a, b) = (o.get_a(), o.get_b()); - print a; - print b; - print "\n"; + debugPrint a; + debugPrint b; + debugPrint "\n"; }; let c = async { @@ -34,9 +34,9 @@ let c = async { public func get_b() : Text { b }; }; let (a, b) = (o.get_a(), o.get_b()); - print a; - print b; - print "\n"; + debugPrint a; + debugPrint b; + debugPrint "\n"; }; let d = async { @@ -47,9 +47,9 @@ let d = async { public func get_b() : Text { b }; }; let (a, b) = (o.get_a(), o.get_b()); - print a; - print b; - print "\n"; + debugPrint a; + debugPrint b; + debugPrint "\n"; }; let e = async { @@ -63,7 +63,7 @@ let e = async { }; }; let (a, b) = o.get_ab(); - print a; - print b; - print "\n"; + debugPrint a; + debugPrint b; + debugPrint "\n"; }; diff --git a/test/run-dfinity/async-obj-mut.mo b/test/run-dfinity/async-obj-mut.mo index 7628ba5bb25..c12dbe176ff 100644 --- a/test/run-dfinity/async-obj-mut.mo +++ b/test/run-dfinity/async-obj-mut.mo @@ -1,19 +1,19 @@ let _ = async { let o = object { public var x = await { async { 1 } }; - let a = printNat(x); + let a = debugPrintNat(x); // private b = (x := await { async (x + 1) }); let b = (x := x + 1); - let c = printNat(x); + let c = debugPrintNat(x); public func foo() = { x := x + 1 }; let e = foo(); - let f = printNat(x); + let f = debugPrintNat(x); }; - print("\ndone creating\n"); - printNat(o.x); + debugPrint("\ndone creating\n"); + debugPrintNat(o.x); o.x := o.x + 1; - printNat(o.x); + debugPrintNat(o.x); o.foo(); - printNat(o.x); - print("\n"); + debugPrintNat(o.x); + debugPrint("\n"); } diff --git a/test/run-dfinity/async-while.mo b/test/run-dfinity/async-while.mo index 969fe18c1d8..816a85a723d 100644 --- a/test/run-dfinity/async-while.mo +++ b/test/run-dfinity/async-while.mo @@ -4,7 +4,7 @@ async { { var i = 0; var j = 0; while (j <= 2) { - printNat(j); + debugPrintNat(j); assert(j == i); i += 1; j += 1; @@ -17,7 +17,7 @@ async { var i = 0; var j = 0; while (await async (j <= 2)) { - printNat(j); + debugPrintNat(j); assert(j == i); i += 1; j += 1; @@ -29,7 +29,7 @@ async { var i = 0; var j = 0; while (j <= 2) { - printNat(j); + debugPrintNat(j); assert(j == i); await (async (i += 1)); j += 1; @@ -46,7 +46,7 @@ async { break l; assert(false); }; - printNat(j); + debugPrintNat(j); assert(j == i); await (async (i += 1)); j += 1; diff --git a/test/run-dfinity/await.mo b/test/run-dfinity/await.mo index 887044ac310..e0ef91846fd 100644 --- a/test/run-dfinity/await.mo +++ b/test/run-dfinity/await.mo @@ -1,70 +1,70 @@ var cnt : Nat = 0; func f(i:Nat) : async Nat { - print "cnt: "; - printNat cnt; - print " i: "; - printNat i; - print "\n"; + debugPrint "cnt: "; + debugPrintNat cnt; + debugPrint " i: "; + debugPrintNat i; + debugPrint "\n"; cnt += 1; cnt; }; -print "a"; +debugPrint "a"; let a = async await f(0); -print "b"; +debugPrint "b"; let b = async { await f(1); }; -print "c"; +debugPrint "c"; let c = async { let _ = await f(2); await f(3); }; -print "d"; +debugPrint "d"; let d = (async { return await f(4); }) : async Int; -print "e"; +debugPrint "e"; let e = async { var i = 5; - print "e-while"; + debugPrint "e-while"; while (i < 8) { let _ = await f(i); i += 1; }; - print "e-exit"; + debugPrint "e-exit"; }; -print "g"; +debugPrint "g"; let g = async { var i = 10; - print "g-label"; + debugPrint "g-label"; label lp while (true) { if (i < 13) { - print "."; + debugPrint "."; let _ = await f(i); i += 1; continue lp; } else {}; break lp; }; - print "g-exit"; + debugPrint "g-exit"; }; -print "holy"; +debugPrint "holy"; func p():async (Text,Text) { ("fst","snd"); }; let h = async { let (a,b) = ("a","b"); /* await p(a,b);*/ - print a; - print b; + debugPrint a; + debugPrint b; }; diff --git a/test/run-dfinity/block.mo b/test/run-dfinity/block.mo index c5bd3f1b17a..6015320cfa0 100644 --- a/test/run-dfinity/block.mo +++ b/test/run-dfinity/block.mo @@ -1,35 +1,35 @@ let a = async { let (a,b) = ("a1","b1"); - print a; - print b; + debugPrint a; + debugPrint b; }; let b = async { let (a,b) = await (async ("a2","b2")); - print a; - print b; + debugPrint a; + debugPrint b; }; let c = async { - func f(a:Text,b:Text):(){ print a; print b;}; + func f(a:Text,b:Text):(){ debugPrint a; debugPrint b;}; let (a,b) = await (async ("a3","b3")); let _ = f(a,b); }; let d = async { var f = 1; - printNat (f); + debugPrintNat (f); let (a,b) = await (async ("a4","b4")); f += 2; - printNat (f); + debugPrintNat (f); }; let e = async { var f = await (async 5); - printNat (f); + debugPrintNat (f); let (a,b) = await (async ("a5","b5")); f += 1; - printNat (f); + debugPrintNat (f); }; diff --git a/test/run-dfinity/chat.mo b/test/run-dfinity/chat.mo index d42f97793fb..404e9f91764 100644 --- a/test/run-dfinity/chat.mo +++ b/test/run-dfinity/chat.mo @@ -42,7 +42,7 @@ actor class Client() = this { }; public func send(msg : Text) { - print(name # " received " # msg # "\n"); + debugPrint(name # " received " # msg # "\n"); }; }; diff --git a/test/run-dfinity/chatpp.mo b/test/run-dfinity/chatpp.mo index 3898bb67678..a60cc39a671 100644 --- a/test/run-dfinity/chatpp.mo +++ b/test/run-dfinity/chatpp.mo @@ -53,7 +53,7 @@ actor class Server() = { case null { clients := n.tail }; case (?p) { p.tail := n.tail }; }; - print "(unsubscribe "; printNat id; print ")\n"; + debugPrint "(unsubscribe "; debugPrintNat id; debugPrint ")\n"; return; }; prev := next; @@ -81,7 +81,7 @@ actor class Client() = this { }; public func send(msg : Text) { - print(name # " received " # msg # "\n"); + debugPrint(name # " received " # msg # "\n"); }; }; diff --git a/test/run-dfinity/closure-params.mo b/test/run-dfinity/closure-params.mo index 12c4c1239c4..41610aed90c 100644 --- a/test/run-dfinity/closure-params.mo +++ b/test/run-dfinity/closure-params.mo @@ -2,8 +2,8 @@ let a = actor { var c = 0; public func incn(n : Nat) : () { c += n; - printNat(c); - print("\n"); + debugPrintNat(c); + debugPrint("\n"); }; public func readCounter(f : shared Nat -> ()) : () { f(c); @@ -11,12 +11,12 @@ let a = actor { }; a.incn(1); -a.readCounter(shared func (n : Nat) = { printNat n; print("\n") }); +a.readCounter(shared func (n : Nat) = { debugPrintNat n; debugPrint("\n") }); a.incn(2); -a.readCounter(shared func (n : Nat) = { printNat n; print("\n") }); +a.readCounter(shared func (n : Nat) = { debugPrintNat n; debugPrint("\n") }); a.incn(3); -a.readCounter(shared func (n : Nat) = { printNat n; print("\n") }); +a.readCounter(shared func (n : Nat) = { debugPrintNat n; debugPrint("\n") }); a.incn(4); -a.readCounter(shared func (n : Nat) = { printNat n; print("\n") }); +a.readCounter(shared func (n : Nat) = { debugPrintNat n; debugPrint("\n") }); a.incn(5); -a.readCounter(shared func (n : Nat) = { printNat n; print("\n") }); +a.readCounter(shared func (n : Nat) = { debugPrintNat n; debugPrint("\n") }); diff --git a/test/run-dfinity/counter.mo b/test/run-dfinity/counter.mo index e91575f9043..dbc84f4e52b 100644 --- a/test/run-dfinity/counter.mo +++ b/test/run-dfinity/counter.mo @@ -2,10 +2,10 @@ let a = actor { var c = 1; public func inc() { c += 1; - printNat c; print "\n"; + debugPrintNat c; debugPrint "\n"; }; public func printCounter () { - printNat c; print "\n"; + debugPrintNat c; debugPrint "\n"; } }; diff --git a/test/run-dfinity/counter2.mo b/test/run-dfinity/counter2.mo index fed194e2ba2..94eb1545c01 100644 --- a/test/run-dfinity/counter2.mo +++ b/test/run-dfinity/counter2.mo @@ -2,10 +2,10 @@ actor { var c = 1; public func inc() { c += 1; - printNat c; print "\n"; + debugPrintNat c; debugPrint "\n"; }; public func printCounter () { - printNat c; print "\n"; + debugPrintNat c; debugPrint "\n"; } } //CALL inc 0x4449444C0000 [] diff --git a/test/run-dfinity/data-params.mo b/test/run-dfinity/data-params.mo index 4427bcdd8f3..744195fd89e 100644 --- a/test/run-dfinity/data-params.mo +++ b/test/run-dfinity/data-params.mo @@ -2,88 +2,88 @@ let a = actor { var c : Int = 0; public func inci(n : Int) : () { c += n; - printInt(c); - print("\n"); + debugPrintInt(c); + debugPrint("\n"); }; public func incn(n : Nat) : () { c += n; - printInt(c); - print("\n"); + debugPrintInt(c); + debugPrint("\n"); }; public func incnn(n1 : Nat, n2 : Nat) : () { c += n1 + n2; - printInt(c); - print("\n"); + debugPrintInt(c); + debugPrint("\n"); }; public func incnested(n1 : Nat, (n2 : Nat, n3 : Nat)) : () { c += n1 + n2 + n3; - printInt(c); - print("\n"); + debugPrintInt(c); + debugPrint("\n"); }; public func incarray(a : [Nat]) : () { for (i in a.vals()) { c += i }; - printInt(c); - print("\n"); + debugPrintInt(c); + debugPrint("\n"); }; public func incopt(a : ?Nat) : () { switch a { case null { c += 1000000 }; case (?a) { c += a }; }; - printInt(c); - print("\n"); + debugPrintInt(c); + debugPrint("\n"); }; public func increcord(a : { x : Nat; y : Nat }) : () { c += a.x; c += a.y; - printInt(c); - print("\n"); + debugPrintInt(c); + debugPrint("\n"); }; public func incVariant(v : { #foo : Nat; #bar : Nat }) { c += (switch v { case (#foo n) n; case (#bar n) n; }); - printInt(c); - print("\n"); + debugPrintInt(c); + debugPrint("\n"); }; public func printCounter() { - printInt(c); - print("\n"); + debugPrintInt(c); + debugPrint("\n"); }; public func printLabeled(l:Text) { - print l; - printInt(c); - print("\n"); + debugPrint l; + debugPrintInt(c); + debugPrint("\n"); }; public func printLabeledOpt(?l:?Text) { - print l; - printInt(c); - print("\n"); + debugPrint l; + debugPrintInt(c); + debugPrint("\n"); }; public func incwords(w8 : Word8, w16 : Word16, w32 : Word32, w64 : Word64) : () { c += word8ToInt(w8); c += word16ToInt(w16); c += word32ToInt(w32); c += word64ToInt(w64); - printInt(c); - print("\n"); + debugPrintInt(c); + debugPrint("\n"); }; public func incnats(n8 : Nat8, n16 : Nat16, n32 : Nat32, n64 : Nat64) : () { c += nat8ToNat(n8); c += nat16ToNat(n16); c += nat32ToNat(n32); c += nat64ToNat(n64); - printInt(c); - print("\n"); + debugPrintInt(c); + debugPrint("\n"); }; public func incints(i8 : Int8, i16 : Int16, i32 : Int32, i64 : Int64) : () { c += int8ToInt(i8); c += int16ToInt(i16); c += int32ToInt(i32); c += int64ToInt(i64); - printInt(c); - print("\n"); + debugPrintInt(c); + debugPrint("\n"); }; }; diff --git a/test/run-dfinity/fac.mo b/test/run-dfinity/fac.mo index 4f546b8d70e..71a68ac3876 100644 --- a/test/run-dfinity/fac.mo +++ b/test/run-dfinity/fac.mo @@ -3,4 +3,4 @@ func fac(n : Nat) : Nat { n * fac (n-1); }; -printNat(fac 5); +debugPrintNat(fac 5); diff --git a/test/run-dfinity/flatten-awaitables.mo b/test/run-dfinity/flatten-awaitables.mo index 72184de029b..f8c4c87a756 100644 --- a/test/run-dfinity/flatten-awaitables.mo +++ b/test/run-dfinity/flatten-awaitables.mo @@ -32,7 +32,7 @@ let a = actor { }; -func println(s:Text) {print s;print ",";}; +func println(s:Text) {debugPrint s;debugPrint ",";}; let _ = async { @@ -116,6 +116,6 @@ let _ = async { let (3,false,"text") = await a.g3(a.n3,xyz); println "15"; - print "\n"; + debugPrint "\n"; }; diff --git a/test/run-dfinity/for-await.mo b/test/run-dfinity/for-await.mo index 88e296a3f45..c0a7a08c835 100644 --- a/test/run-dfinity/for-await.mo +++ b/test/run-dfinity/for-await.mo @@ -5,7 +5,7 @@ async { var i = 0; i := 0; for (j in range(0, 10)) { - printNat(j); + debugPrintNat(j); assert(j == i); await (async (i += 1)); }; diff --git a/test/run-dfinity/generic-tail-rec.mo b/test/run-dfinity/generic-tail-rec.mo index 1f0688ce1f8..20cc023222a 100644 --- a/test/run-dfinity/generic-tail-rec.mo +++ b/test/run-dfinity/generic-tail-rec.mo @@ -5,7 +5,7 @@ let bound:Int = 100000; { func Loop(n:Int){ if (n >= bound) { - print "done 1\n"; + debugPrint "done 1\n"; return; }; Loop(n+1); @@ -17,7 +17,7 @@ Loop(0); { func Loop(n:Int){ if (n >= bound) { - print "done 2\n"; + debugPrint "done 2\n"; return; }; return Loop(n+1); @@ -30,7 +30,7 @@ Loop(0); { func Loop(n:Int){ if (n >= bound) { - print "done 3\n"; + debugPrint "done 3\n"; return; }; Loop(n+1); @@ -42,7 +42,7 @@ Loop(0); { func Loop(n:Int){ if (n >= bound) { - print "done 4\n"; + debugPrint "done 4\n"; return; }; Loop(n+1); diff --git a/test/run-dfinity/hello-concat-world.mo b/test/run-dfinity/hello-concat-world.mo index 95e1893c5b5..7109163143b 100644 --- a/test/run-dfinity/hello-concat-world.mo +++ b/test/run-dfinity/hello-concat-world.mo @@ -1 +1 @@ -print("Hello " # "World!\n"); +debugPrint("Hello " # "World!\n"); diff --git a/test/run-dfinity/hello-world-async.mo b/test/run-dfinity/hello-world-async.mo index 2b7bab40032..feeb880ff48 100644 --- a/test/run-dfinity/hello-world-async.mo +++ b/test/run-dfinity/hello-world-async.mo @@ -1,10 +1,10 @@ let a = actor { public func world() { - print("World!\n"); + debugPrint("World!\n"); }; public func go() { world(); - print("Hello "); + debugPrint("Hello "); }; }; diff --git a/test/run-dfinity/hello-world-await.mo b/test/run-dfinity/hello-world-await.mo index d8b73e3bdc2..b5549411073 100644 --- a/test/run-dfinity/hello-world-await.mo +++ b/test/run-dfinity/hello-world-await.mo @@ -6,7 +6,7 @@ let a = actor { "World!\n" }; public func go() : async () { - print((await hello()) # (await world())); + debugPrint((await hello()) # (await world())); }; }; diff --git a/test/run-dfinity/hello-world-message.mo b/test/run-dfinity/hello-world-message.mo index 9fc8fef1623..7e54cde56b6 100644 --- a/test/run-dfinity/hello-world-message.mo +++ b/test/run-dfinity/hello-world-message.mo @@ -1,6 +1,6 @@ actor { public func hello() { - print("Hello World!\n"); + debugPrint("Hello World!\n"); } } diff --git a/test/run-dfinity/hello-world-message2.mo b/test/run-dfinity/hello-world-message2.mo index 25fa661eb50..9274933cc3a 100644 --- a/test/run-dfinity/hello-world-message2.mo +++ b/test/run-dfinity/hello-world-message2.mo @@ -1,6 +1,6 @@ actor hello_world { public func hello() { - print("Hello World!\n"); + debugPrint("Hello World!\n"); } } diff --git a/test/run-dfinity/hello-world.mo b/test/run-dfinity/hello-world.mo index 3b66c900d9c..bc9c37d31e8 100644 --- a/test/run-dfinity/hello-world.mo +++ b/test/run-dfinity/hello-world.mo @@ -1 +1 @@ -print("Hello World!\n"); +debugPrint("Hello World!\n"); diff --git a/test/run-dfinity/hello-world2.mo b/test/run-dfinity/hello-world2.mo index c797af62b2c..46218e8ead3 100644 --- a/test/run-dfinity/hello-world2.mo +++ b/test/run-dfinity/hello-world2.mo @@ -1,6 +1,6 @@ let a = actor { public func hello() { - print("Hello World!\n"); + debugPrint("Hello World!\n"); } }; diff --git a/test/run-dfinity/hello-world3.mo b/test/run-dfinity/hello-world3.mo index 5354a951b08..d5cc98a1d53 100644 --- a/test/run-dfinity/hello-world3.mo +++ b/test/run-dfinity/hello-world3.mo @@ -1,13 +1,13 @@ let a = actor { public func hello() { - print("Hello "); + debugPrint("Hello "); }; public func go() { hello(); world(); }; public func world() { - print("World!\n"); + debugPrint("World!\n"); }; }; diff --git a/test/run-dfinity/indirect-counter.mo b/test/run-dfinity/indirect-counter.mo index 3d3e76955f4..85e045f959c 100644 --- a/test/run-dfinity/indirect-counter.mo +++ b/test/run-dfinity/indirect-counter.mo @@ -3,17 +3,17 @@ let a = actor { var c = 1; public func inc() { c += 1; - printNat(c) + debugPrintNat(c) }; - public func print() { - printNat(c) + public func debugPrint() { + debugPrintNat(c) }; }; public func inc() { aa.inc() }; - public func print() { aa.print() }; + public func debugPrint() { aa.debugPrint() }; }; a.inc(); a.inc(); a.inc(); -a.print() +a.debugPrint() diff --git a/test/run-dfinity/local-throw.mo b/test/run-dfinity/local-throw.mo index d49a7c37d96..de25bb8c696 100644 --- a/test/run-dfinity/local-throw.mo +++ b/test/run-dfinity/local-throw.mo @@ -51,14 +51,14 @@ async { try { await t2(); - print ("\n t2 ok"); + debugPrint ("\n t2 ok"); } catch _ { assert false; }; try { await t3(); - print ("\n t3 ok"); + debugPrint ("\n t3 ok"); } catch _ { assert false; }; diff --git a/test/run-dfinity/nary-async.mo b/test/run-dfinity/nary-async.mo index 5f2ae4c65c4..3875884af34 100644 --- a/test/run-dfinity/nary-async.mo +++ b/test/run-dfinity/nary-async.mo @@ -6,7 +6,7 @@ let t = "0_0\n"; shared func f0_0() : async () {}; let _ : async () = async { await f0_0(); - print t; + debugPrint t; }; }; @@ -17,7 +17,7 @@ shared func f1_0(x:Int) : async () { }; let _ : async () = async { await f1_0(1); - print t; + debugPrint t; }; }; @@ -29,7 +29,7 @@ shared func f2_0(x:Int,y:Bool) : async () { }; let _ : async () = async { await f2_0(1,true); - print t; + debugPrint t; }; }; @@ -42,7 +42,7 @@ shared func f3_0(x:Int,y:Bool,z:Text) : async () { }; let _ : async () = async { await f3_0(1,true,"a"); - print t; + debugPrint t; }; }; @@ -53,7 +53,7 @@ let t = "0_0\n"; shared func f0_0() : async () {}; let _ : async () = async { await f0_0(); - print t; + debugPrint t; }; }; @@ -66,7 +66,7 @@ shared func f0_1() : async Int { let _ : async Int = async { let x = await f0_1(); assert(x == 1); - print t; + debugPrint t; x; }; }; @@ -80,7 +80,7 @@ let _ : async (Int,Bool) = async { let (x,y) = await f0_2(); assert(x==1); assert(y==true); - print t; + debugPrint t; (x,y); }; }; @@ -96,7 +96,7 @@ let _ : async (Int,Bool,Text) = async { assert(x==1); assert(y==true); assert(z=="a"); - print t; + debugPrint t; (x,y,z); }; }; @@ -114,7 +114,7 @@ shared func fu_u(a:Int,) : async (Int,) { let _ : async (Int,) = async { let (x,) = await fu_u(1); assert(x==2); - print t; + debugPrint t; return (x,); }; }; @@ -131,7 +131,7 @@ shared func fu_u(x:T) : async T { let _ : async T = async { let y = await fu_u(x); assert(eq(x,y)); - print t; + debugPrint t; return y; }; }; diff --git a/test/run-dfinity/ok/text-iter.dvm-run.ok b/test/run-dfinity/ok/text-iter.dvm-run.ok index 1a0889b1e4f..cdfd71bd534 100644 --- a/test/run-dfinity/ok/text-iter.dvm-run.ok +++ b/test/run-dfinity/ok/text-iter.dvm-run.ok @@ -1,16 +1,16 @@ -via `print`: +via `debugPrint`: hello world! -via iteration and `printChar`: #1 +via iteration and `debugPrintChar`: #1 hello world! -via iteration and `printChar`: #2 +via iteration and `debugPrintChar`: #2 1:'h' 2:'e' 3:'l' 4:'l' 5:'o' 6:' ' 7:'w' 8:'o' 9:'r' 10:'l' 11:'d' 12:'!' 13:' ' -via iteration and `printChar` (Unicode): #3 +via iteration and `debugPrintChar` (Unicode): #3 1:'П' 2:'р' 3:'и' 4:'в' 5:'е' 6:'т' 7:'с' 8:'т' 9:'в' 10:'у' 11:'ю' 12:',' 13:' ' 14:'м' 15:'и' 16:'р' 17:'!' 18:' ' -via iteration and `printChar` (Unicode): #4 +via iteration and `debugPrintChar` (Unicode): #4 1:'🙈' 2:'🎸' 3:'😋' Приветствую, мир! diff --git a/test/run-dfinity/ok/text-iter.run-ir.ok b/test/run-dfinity/ok/text-iter.run-ir.ok index 1a0889b1e4f..cdfd71bd534 100644 --- a/test/run-dfinity/ok/text-iter.run-ir.ok +++ b/test/run-dfinity/ok/text-iter.run-ir.ok @@ -1,16 +1,16 @@ -via `print`: +via `debugPrint`: hello world! -via iteration and `printChar`: #1 +via iteration and `debugPrintChar`: #1 hello world! -via iteration and `printChar`: #2 +via iteration and `debugPrintChar`: #2 1:'h' 2:'e' 3:'l' 4:'l' 5:'o' 6:' ' 7:'w' 8:'o' 9:'r' 10:'l' 11:'d' 12:'!' 13:' ' -via iteration and `printChar` (Unicode): #3 +via iteration and `debugPrintChar` (Unicode): #3 1:'П' 2:'р' 3:'и' 4:'в' 5:'е' 6:'т' 7:'с' 8:'т' 9:'в' 10:'у' 11:'ю' 12:',' 13:' ' 14:'м' 15:'и' 16:'р' 17:'!' 18:' ' -via iteration and `printChar` (Unicode): #4 +via iteration and `debugPrintChar` (Unicode): #4 1:'🙈' 2:'🎸' 3:'😋' Приветствую, мир! diff --git a/test/run-dfinity/ok/text-iter.run-low.ok b/test/run-dfinity/ok/text-iter.run-low.ok index 1a0889b1e4f..cdfd71bd534 100644 --- a/test/run-dfinity/ok/text-iter.run-low.ok +++ b/test/run-dfinity/ok/text-iter.run-low.ok @@ -1,16 +1,16 @@ -via `print`: +via `debugPrint`: hello world! -via iteration and `printChar`: #1 +via iteration and `debugPrintChar`: #1 hello world! -via iteration and `printChar`: #2 +via iteration and `debugPrintChar`: #2 1:'h' 2:'e' 3:'l' 4:'l' 5:'o' 6:' ' 7:'w' 8:'o' 9:'r' 10:'l' 11:'d' 12:'!' 13:' ' -via iteration and `printChar` (Unicode): #3 +via iteration and `debugPrintChar` (Unicode): #3 1:'П' 2:'р' 3:'и' 4:'в' 5:'е' 6:'т' 7:'с' 8:'т' 9:'в' 10:'у' 11:'ю' 12:',' 13:' ' 14:'м' 15:'и' 16:'р' 17:'!' 18:' ' -via iteration and `printChar` (Unicode): #4 +via iteration and `debugPrintChar` (Unicode): #4 1:'🙈' 2:'🎸' 3:'😋' Приветствую, мир! diff --git a/test/run-dfinity/ok/text-iter.run.ok b/test/run-dfinity/ok/text-iter.run.ok index 1a0889b1e4f..cdfd71bd534 100644 --- a/test/run-dfinity/ok/text-iter.run.ok +++ b/test/run-dfinity/ok/text-iter.run.ok @@ -1,16 +1,16 @@ -via `print`: +via `debugPrint`: hello world! -via iteration and `printChar`: #1 +via iteration and `debugPrintChar`: #1 hello world! -via iteration and `printChar`: #2 +via iteration and `debugPrintChar`: #2 1:'h' 2:'e' 3:'l' 4:'l' 5:'o' 6:' ' 7:'w' 8:'o' 9:'r' 10:'l' 11:'d' 12:'!' 13:' ' -via iteration and `printChar` (Unicode): #3 +via iteration and `debugPrintChar` (Unicode): #3 1:'П' 2:'р' 3:'и' 4:'в' 5:'е' 6:'т' 7:'с' 8:'т' 9:'в' 10:'у' 11:'ю' 12:',' 13:' ' 14:'м' 15:'и' 16:'р' 17:'!' 18:' ' -via iteration and `printChar` (Unicode): #4 +via iteration and `debugPrintChar` (Unicode): #4 1:'🙈' 2:'🎸' 3:'😋' Приветствую, мир! diff --git a/test/run-dfinity/overflow.mo b/test/run-dfinity/overflow.mo index 49b0222c865..3bf1689d5d4 100644 --- a/test/run-dfinity/overflow.mo +++ b/test/run-dfinity/overflow.mo @@ -4,31 +4,31 @@ ignore(async { ignore ((0-1):Int); - print("This is reachable.\n"); + debugPrint("This is reachable.\n"); }); ignore(async { ignore ((1-1):Nat); - print("This is reachable.\n"); + debugPrint("This is reachable.\n"); }); ignore(async { ignore ((0-1):Nat); - print("This should be unreachable.\n"); + debugPrint("This should be unreachable.\n"); }); ignore(async { ignore ((0-1):Nat); - print("This should be unreachable.\n"); + debugPrint("This should be unreachable.\n"); }); /* ignore(async { ignore ((18446744073709551615 + 0):Nat); - print("This is reachable.\n"); + debugPrint("This is reachable.\n"); }); */ ignore(async { ignore ((9223372036854775806 + 9223372036854775806 + 1):Nat); - print("This is reachable.\n"); + debugPrint("This is reachable.\n"); }); ignore(async { ignore ((9223372036854775806 + 9223372036854775806 + 2):Nat); - print("This is reachable.\n"); + debugPrint("This is reachable.\n"); }); diff --git a/test/run-dfinity/query.mo b/test/run-dfinity/query.mo index 8f34ec56b64..a6d7e3b63f2 100644 --- a/test/run-dfinity/query.mo +++ b/test/run-dfinity/query.mo @@ -2,10 +2,10 @@ actor counter = { var c = 1; public func inc() { c += 1; - printNat c; print "\n"; + debugPrintNat c; debugPrint "\n"; }; public func printCounter () { - printNat c; print "\n"; + debugPrintNat c; debugPrint "\n"; }; public func get() : async Nat { return c @@ -13,7 +13,7 @@ actor counter = { public query func read() : async Nat { let tmp = c; c += 1; - printNat c; print "(read)\n"; + debugPrintNat c; debugPrint "(read)\n"; return tmp; }; diff --git a/test/run-dfinity/reference-params.mo b/test/run-dfinity/reference-params.mo index 98e51252b68..6324345b96c 100644 --- a/test/run-dfinity/reference-params.mo +++ b/test/run-dfinity/reference-params.mo @@ -1,6 +1,6 @@ let a = actor { public func hello() { - print("Hello World!\n"); + debugPrint("Hello World!\n"); }; }; a.hello(); @@ -27,7 +27,7 @@ let d = actor { f(); }; public func hello() { - print("Hello Universe!\n"); + debugPrint("Hello Universe!\n"); }; public func go() { say_hi(hello); @@ -38,7 +38,7 @@ d.go(); // test passing a self to an actor let e = actor this { public func hello() { - print("Hello Galaxy!\n"); + debugPrint("Hello Galaxy!\n"); }; public func send_to(f : shared (actor { hello : () -> () }) -> ()) { f(this); diff --git a/test/run-dfinity/selftail.mo b/test/run-dfinity/selftail.mo index 1e2264cf5b8..f12f6d22741 100644 --- a/test/run-dfinity/selftail.mo +++ b/test/run-dfinity/selftail.mo @@ -11,13 +11,13 @@ func f (tailCall:Bool, n:Int, acc:Int) : Int { // check we get same results for small n assert (f(false, 100, 0) == f(true, 100, 0)); -print "ok1 \n"; +debugPrint "ok1 \n"; // check tail recursion works for large n assert(10000 == f (true, 10000, 0)); -print "ok2 \n"; +debugPrint "ok2 \n"; // check recursion overflows for large n (on dvm only) // disabled as overflowing or not appears to be non-deterministic on V8 //assert(10000 == f (false, 10000, 0)); -//print "unreachable on dvm \n"; +//debugPrint "unreachable on dvm \n"; diff --git a/test/run-dfinity/show.mo b/test/run-dfinity/show.mo index b0948366ca9..d896dcc6e4d 100644 --- a/test/run-dfinity/show.mo +++ b/test/run-dfinity/show.mo @@ -1,4 +1,4 @@ -func printLn(x : Text) { print(x # "\n"); }; +func printLn(x : Text) { debugPrint(x # "\n"); }; printLn(debug_show (true)); printLn(debug_show (false)); printLn(debug_show (-42000000000000)); diff --git a/test/run-dfinity/simple-throw.mo b/test/run-dfinity/simple-throw.mo index 7e1b7b04cc5..b600d63e075 100644 --- a/test/run-dfinity/simple-throw.mo +++ b/test/run-dfinity/simple-throw.mo @@ -2,20 +2,20 @@ // In principle, it should run on all targets. async { - print "1"; + debugPrint "1"; try { - print "2"; + debugPrint "2"; throw error("t2"); assert(false); } catch e { switch (errorCode(e), errorMessage(e)) { case (#error, "t1") { assert false; }; case (#system, _ ) { assert false; }; - case (#error, _) { print "3"; }; + case (#error, _) { debugPrint "3"; }; } }; - print "4"; - print "done"; + debugPrint "4"; + debugPrint "done"; }; diff --git a/test/run-dfinity/tailpositions.mo b/test/run-dfinity/tailpositions.mo index 16f5c787c5c..06d66fe44c5 100644 --- a/test/run-dfinity/tailpositions.mo +++ b/test/run-dfinity/tailpositions.mo @@ -5,7 +5,7 @@ let bound:Int = 100000; { func Loop(n:Int){ if (n >= bound) { - print "done 1\n"; + debugPrint "done 1\n"; return; }; Loop(n+1); @@ -16,7 +16,7 @@ let bound:Int = 100000; { func Loop(n:Int){ if (n >= bound) { - print "done 2\n"; + debugPrint "done 2\n"; return; }; if (true) @@ -31,7 +31,7 @@ let bound:Int = 100000; { func Loop(n:Int){ if (n >= bound) { - print "done 3\n"; + debugPrint "done 3\n"; return; }; switch (n % 2) { @@ -47,7 +47,7 @@ let bound:Int = 100000; { func Loop(n:Int){ if (n >= bound) { - print "done 4\n"; + debugPrint "done 4\n"; return; }; { let m = n; @@ -61,7 +61,7 @@ let bound:Int = 100000; { func Loop(n:Int){ if (n >= bound) { - print "done 5\n"; + debugPrint "done 5\n"; return; }; let _ = (return Loop(n+1)) + 1; @@ -73,7 +73,7 @@ let bound:Int = 100000; { func Loop(n:Int):Bool{ if (n >= bound) { - print "done 6\n"; + debugPrint "done 6\n"; return true; }; true and Loop(n+1); @@ -84,7 +84,7 @@ let bound:Int = 100000; { func Loop(n:Int):Bool { if (n >= bound) { - print "done 7\n"; + debugPrint "done 7\n"; return true; }; false or Loop(n+1); diff --git a/test/run-dfinity/text-iter.mo b/test/run-dfinity/text-iter.mo index 84693bb89d6..0b160c06688 100644 --- a/test/run-dfinity/text-iter.mo +++ b/test/run-dfinity/text-iter.mo @@ -1,69 +1,69 @@ let s = "hello world!\n"; -print "via `print`:\n"; -print s; -print "\n"; +debugPrint "via `debugPrint`:\n"; +debugPrint s; +debugPrint "\n"; -print "via iteration and `printChar`: #1\n"; +debugPrint "via iteration and `debugPrintChar`: #1\n"; for (a in s.chars()) { - printChar a; + debugPrintChar a; }; -print "\n"; +debugPrint "\n"; -print "via iteration and `printChar`: #2\n"; +debugPrint "via iteration and `debugPrintChar`: #2\n"; var x = 0; for (a in s.chars()) { x += 1; - printNat x; - print ":"; - printChar '\''; - printChar a; - printChar '\''; - print " "; + debugPrintNat x; + debugPrint ":"; + debugPrintChar '\''; + debugPrintChar a; + debugPrintChar '\''; + debugPrint " "; }; -print "\n"; +debugPrint "\n"; let russian = "Приветствую, мир!\n"; assert(russian.len() == 18); -print "via iteration and `printChar` (Unicode): #3\n"; +debugPrint "via iteration and `debugPrintChar` (Unicode): #3\n"; x := 0; for (a in russian.chars()) { x += 1; - printNat x; - print ":"; - printChar '\''; - printChar a; - printChar '\''; - print " "; + debugPrintNat x; + debugPrint ":"; + debugPrintChar '\''; + debugPrintChar a; + debugPrintChar '\''; + debugPrint " "; }; -print "\n"; +debugPrint "\n"; assert(x == 18); let emojis = "🙈🎸😋"; assert(emojis.len() == 3); -print "via iteration and `printChar` (Unicode): #4\n"; +debugPrint "via iteration and `debugPrintChar` (Unicode): #4\n"; x := 0; for (a in emojis.chars()) { x += 1; - printNat x; - print ":"; - printChar '\''; - printChar a; - printChar '\''; - print " "; + debugPrintNat x; + debugPrint ":"; + debugPrintChar '\''; + debugPrintChar a; + debugPrintChar '\''; + debugPrint " "; }; -print "\n"; +debugPrint "\n"; assert(x == 3); -print russian; print "\n"; +debugPrint russian; debugPrint "\n"; switch (russian.chars().next()) { - case (?c) { printChar c; print "\n" }; + case (?c) { debugPrintChar c; debugPrint "\n" }; case _ {}; }; switch (emojis.chars().next()) { - case (?c) { assert (c == '\u{1f648}'); printChar c; print "\n" }; + case (?c) { assert (c == '\u{1f648}'); debugPrintChar c; debugPrint "\n" }; case _ {}; }; diff --git a/test/run-dfinity/the-answer.mo b/test/run-dfinity/the-answer.mo index 43657e60ede..3f4e1e6c14c 100644 --- a/test/run-dfinity/the-answer.mo +++ b/test/run-dfinity/the-answer.mo @@ -1 +1 @@ -printNat(42); +debugPrintNat(42); diff --git a/test/run-drun/counter.mo b/test/run-drun/counter.mo index 7f086642a3d..0e40920fb6f 100644 --- a/test/run-drun/counter.mo +++ b/test/run-drun/counter.mo @@ -2,10 +2,10 @@ actor { var c = 1; public func inc() { c += 1; - printNat c; print "\n"; + debugPrintNat c; debugPrint "\n"; }; public func printCounter () { - printNat c; print "\n"; + debugPrintNat c; debugPrint "\n"; }; public func get() : async Nat { return c diff --git a/test/run-drun/idl-any.mo b/test/run-drun/idl-any.mo index eb0a5e82044..b2c5713be24 100644 --- a/test/run-drun/idl-any.mo +++ b/test/run-drun/idl-any.mo @@ -2,7 +2,7 @@ // zooms past the any argument and finds the beginning of the string actor { public func any(_ : Any, x : Text) : async () { - print ("ok: " # x); + debugPrint ("ok: " # x); }; } diff --git a/test/run-drun/idl-option.mo b/test/run-drun/idl-option.mo index 3fbe8f0a620..887644e7584 100644 --- a/test/run-drun/idl-option.mo +++ b/test/run-drun/idl-option.mo @@ -3,8 +3,8 @@ actor { public func any(o : ?Text) : async () { switch o { - case null print ("ok: null"); - case (?x) print ("ok: " # x); + case null debugPrint ("ok: null"); + case (?x) debugPrint ("ok: " # x); } }; } diff --git a/test/run-drun/idl-record.mo b/test/run-drun/idl-record.mo index d1f23c1d553..576609b3aa0 100644 --- a/test/run-drun/idl-record.mo +++ b/test/run-drun/idl-record.mo @@ -4,22 +4,22 @@ actor { public func pair(o : (Text, Int)) : async () { switch o { - case (content, num) print ("ok: " # debug_show num); + case (content, num) debugPrint ("ok: " # debug_show num); } }; public func record(o : {content: Text; value : Int}) : async () { switch o { - case {content} print ("ok: " # content); + case {content} debugPrint ("ok: " # content); } }; public func record1(o : {value : Int; byte : Int8}) : async () { switch o { - case {byte} print ("ok: " # debug_show byte); + case {byte} debugPrint ("ok: " # debug_show byte); } }; public func record2(o : {content: Text; value : Int}, follower : Int8) : async Int8 { switch o { - case {content} { print ("ok: " # " " # content # " " # debug_show follower); follower }; + case {content} { debugPrint ("ok: " # " " # content # " " # debug_show follower); follower }; } }; } diff --git a/test/run-drun/print-from-init.mo b/test/run-drun/print-from-init.mo index 15b4e8c6731..e65298d1a21 100644 --- a/test/run-drun/print-from-init.mo +++ b/test/run-drun/print-from-init.mo @@ -1,3 +1,3 @@ actor { - print("Debug out"); + debugPrint("Debug out"); } diff --git a/test/run-drun/query.mo b/test/run-drun/query.mo index 3c97f7a3357..3e494c1154e 100644 --- a/test/run-drun/query.mo +++ b/test/run-drun/query.mo @@ -2,10 +2,10 @@ actor { var c = 1; public func inc() { c += 1; - printNat c; print "\n"; + debugPrintNat c; debugPrint "\n"; }; public func printCounter () { - printNat c; print "\n"; + debugPrintNat c; debugPrint "\n"; }; public func get() : async Nat { return c @@ -13,7 +13,7 @@ actor { public query func read() : async Nat { let tmp = c; c += 1; - printNat c; print "\n"; + debugPrintNat c; debugPrint "\n"; return tmp; }; diff --git a/test/run-drun/reject.mo b/test/run-drun/reject.mo index 788c0273c3a..a2a7e7bdff9 100644 --- a/test/run-drun/reject.mo +++ b/test/run-drun/reject.mo @@ -1,25 +1,25 @@ actor { public func reject1() : async () { - print "1"; + debugPrint "1"; throw (error("Error")); - print "wrong"; + debugPrint "wrong"; }; public func reject2() : async () { - print "1"; + debugPrint "1"; try { throw (error("Error")) } catch e {}; - print "ok"; + debugPrint "ok"; }; public func reject3() : async () { - print "1"; + debugPrint "1"; try { throw (error("Error")) } catch e { - print "ok"; + debugPrint "ok"; throw e; }; - print "wrong"; + debugPrint "wrong"; }; } diff --git a/test/run-release/debug.mo b/test/run-release/debug.mo index f52dc765b48..5e8005c6e9c 100644 --- a/test/run-release/debug.mo +++ b/test/run-release/debug.mo @@ -1,4 +1,4 @@ -print "This should appear\n"; -debug { print "This shouldn't appear\n" }; -print "This should appear too\n"; +debugPrint "This should appear\n"; +debug { debugPrint "This shouldn't appear\n" }; +debugPrint "This should appear too\n"; diff --git a/test/run/conversions.mo b/test/run/conversions.mo index 9316ba04756..e4406164507 100644 --- a/test/run/conversions.mo +++ b/test/run/conversions.mo @@ -112,7 +112,7 @@ assert(intToWord32 2147483648 == (2147483648 : Word32)); // 2**31 assert(intToWord32 2147483649 == (2147483649 : Word32)); // 2**31 + 1 assert(intToWord32 4294967295 == (4294967295 : Word32)); // 2**32 - 1 -func println(i : Int) { printInt(i); print "\n"; }; +func println(i : Int) { debugPrintInt(i); debugPrint "\n"; }; println(word32ToInt (-2147483648)); // -2**31 println(word32ToInt (-2147483647)); // -2**31 + 1 diff --git a/test/run/debug.mo b/test/run/debug.mo index b0b3281f042..0c881ad1776 100644 --- a/test/run/debug.mo +++ b/test/run/debug.mo @@ -1 +1 @@ -debug { print "This is for debugging only" }; // okay: result () +debug { debugPrint "This is for debugging only" }; // okay: result () diff --git a/test/run/for.mo b/test/run/for.mo index 15a83cf5266..93468a301c4 100644 --- a/test/run/for.mo +++ b/test/run/for.mo @@ -1,6 +1,6 @@ var i = 0; for (j in range(0, 10)) { - printNat(j); + debugPrintNat(j); assert(j == i); i += 1; }; diff --git a/test/run/idlHash.mo b/test/run/idlHash.mo index 3d2546dbbcf..7ae1af984d9 100644 --- a/test/run/idlHash.mo +++ b/test/run/idlHash.mo @@ -1,7 +1,7 @@ func testHash(s : Text, h : Word32) { - print("Hash for " # s # ":\n"); - print("Expected: " # debug_show (word32ToNat(h)) # "\n"); - print("Actual: " # debug_show (word32ToNat(idlHash s)) # "\n"); + debugPrint("Hash for " # s # ":\n"); + debugPrint("Expected: " # debug_show (word32ToNat(h)) # "\n"); + debugPrint("Actual: " # debug_show (word32ToNat(idlHash s)) # "\n"); }; // The lines below can be copied verbatim out of the corresponding JS unit test diff --git a/test/run/numeric-ops.mo b/test/run/numeric-ops.mo index 240df731f9c..3ba0aaf7155 100644 --- a/test/run/numeric-ops.mo +++ b/test/run/numeric-ops.mo @@ -4,9 +4,9 @@ // asserts that those compare equal func verify(etalon : [T], results : [T], cmp : (T, T) -> Bool) { - //print "\n"; + //debugPrint "\n"; for (i in etalon.keys()) - { //printInt i; print "\n"; + { //debugPrintInt i; debugPrint "\n"; assert cmp(etalon[i], results[i * 2]); assert cmp(etalon[i], results[i * 2 + 1]); } diff --git a/test/run/variants.mo b/test/run/variants.mo index f8693c653be..43f54088c1b 100644 --- a/test/run/variants.mo +++ b/test/run/variants.mo @@ -10,8 +10,8 @@ func size(t : Tree) : Nat { let tt1 : Tree = #branch(#leaf 1, #leaf (-1)); let tt2 = #leaf ""; // infers type {#leaf : Text} which is a subtype of Tree -printNat(size(tt1)); print "\n"; -printNat(size(tt2)); print "\n"; +debugPrintNat(size(tt1)); debugPrint "\n"; +debugPrintNat(size(tt2)); debugPrint "\n"; // subtyping diff --git a/test/run/words.mo b/test/run/words.mo index 099fcb2cd78..0a9f82071a6 100644 --- a/test/run/words.mo +++ b/test/run/words.mo @@ -1,6 +1,6 @@ // CHECK: func $start -func printBit(a : Bool) { print(if a "set" else "clear"); print "\n" }; +func printBit(a : Bool) { debugPrint(if a "set" else "clear"); debugPrint "\n" }; func checkpointAlpha() {}; @@ -16,7 +16,7 @@ func checkpointJuliett() {}; // Word64 operations { - func printW64ln(w : Word64) { printNat(word64ToNat w); print " "; printInt(word64ToInt w); print "\n" }; + func printW64ln(w : Word64) { debugPrintNat(word64ToNat w); debugPrint " "; debugPrintInt(word64ToInt w); debugPrint "\n" }; let a : Word64 = 4567; let b : Word64 = 7; @@ -71,7 +71,7 @@ func checkpointJuliett() {}; // Word32 operations { - func printW32ln(w : Word32) { printNat(word32ToNat w); print " "; printInt(word32ToInt w); print "\n" }; + func printW32ln(w : Word32) { debugPrintNat(word32ToNat w); debugPrint " "; debugPrintInt(word32ToInt w); debugPrint "\n" }; let a : Word32 = 4567; let b : Word32 = 7; @@ -125,7 +125,7 @@ func checkpointJuliett() {}; // Word16 operations { - func printW16ln(w : Word16) { printNat(word16ToNat w); print " "; printInt(word16ToInt w); print "\n" }; + func printW16ln(w : Word16) { debugPrintNat(word16ToNat w); debugPrint " "; debugPrintInt(word16ToInt w); debugPrint "\n" }; let a : Word16 = 4567; let b : Word16 = 7; @@ -205,7 +205,7 @@ func checkpointJuliett() {}; // Word8 operations { - func printW8ln(w : Word8) { printNat(word8ToNat w); print " "; printInt(word8ToInt w); print "\n" }; + func printW8ln(w : Word8) { debugPrintNat(word8ToNat w); debugPrint " "; debugPrintInt(word8ToInt w); debugPrint "\n" }; let a : Word8 = 67; let b : Word8 = 7; From c0fef5d2ac78a5a9aa59f534950fb6d2affb8067 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 5 Nov 2019 08:44:49 +0100 Subject: [PATCH 0511/1176] Test suite: check return code (#811) * Test suite: check return code as @basvandijk pointed out, the test suite would not necessarily fail if a process would exit abnormally. This fixes tihs (adding `$base.$ext.ret`) to the files to be checked. Some refactoring of `run.sh` included. Required some renaming. * Fix quick.mk so that it doesn't use `_out/foo.done` which would now be cleaned by `run.sh` * Depend on chronic * Erronous test output --- default.nix | 1 + test/Makefile | 1 - .../{fields.idl.stderr.ok => fields.idl.ok} | 0 test/as-idl/ok/fields.idl.ret.ok | 1 + test/fail/ok/AST-60.tc.ret.ok | 1 + test/fail/ok/abstract-msgs.tc.ret.ok | 1 + test/fail/ok/actor-match.tc.ret.ok | 1 + test/fail/ok/actor-reexport.tc.ret.ok | 1 + test/fail/ok/argument-subtyping.tc.ret.ok | 1 + test/fail/ok/ast81-clash.tc.ret.ok | 1 + test/fail/ok/asyncret1.tc.ret.ok | 1 + test/fail/ok/asyncret2.tc.ret.ok | 1 + test/fail/ok/asyncret3.tc.ret.ok | 1 + test/fail/ok/await-in-actor.tc.ret.ok | 1 + test/fail/ok/bad-unops.tc.ret.ok | 1 + test/fail/ok/branch-before-define.tc.ret.ok | 1 + .../ok/char-high-surrogate-trap.run.ret.ok | 1 + .../char-high-surrogate-trap.wasm-run.ret.ok | 1 + test/fail/ok/char-high-surrogate.tc.ret.ok | 1 + .../ok/char-low-surrogate-trap.run.ret.ok | 1 + .../char-low-surrogate-trap.wasm-run.ret.ok | 1 + test/fail/ok/char-low-surrogate.tc.ret.ok | 1 + test/fail/ok/char-trap.run.ret.ok | 1 + test/fail/ok/char-trap.wasm-run.ret.ok | 1 + test/fail/ok/class.tc.ret.ok | 1 + test/fail/ok/const-var-array.tc.ret.ok | 1 + test/fail/ok/const-var-field.tc.ret.ok | 1 + test/fail/ok/cyclic-bound1.tc.ret.ok | 1 + test/fail/ok/cyclic-bound2.tc.ret.ok | 1 + test/fail/ok/cyclic-bound3.tc.ret.ok | 1 + test/fail/ok/cyclic-bound4.tc.ret.ok | 1 + test/fail/ok/cyclic-bound5.tc.ret.ok | 1 + test/fail/ok/debug.tc.ret.ok | 1 + test/fail/ok/decl-clash.tc.ret.ok | 1 + test/fail/ok/duplicate-field.tc.ret.ok | 1 + test/fail/ok/f-bounds-fail.tc.ret.ok | 1 + test/fail/ok/issue103.tc.ret.ok | 1 + test/fail/ok/issue167.tc.ret.ok | 1 + ...issue36.wasm.stderr.ok => issue36.comp.ok} | 0 test/fail/ok/issue36.wasm-run.ret.ok | 1 + test/fail/ok/modexp1.tc.ret.ok | 1 + test/fail/ok/modexp2.tc.ret.ok | 1 + test/fail/ok/modexp3.tc.ret.ok | 1 + test/fail/ok/modexp4.tc.ret.ok | 1 + test/fail/ok/modexp5.tc.ret.ok | 1 + test/fail/ok/modules-fwd.tc.ret.ok | 1 + test/fail/ok/modules-shadow.tc.ret.ok | 1 + test/fail/ok/nested-class-rec-fail.tc.ret.ok | 1 + test/fail/ok/non_static_module.tc.ret.ok | 1 + test/fail/ok/nonlinear-pat.tc.ret.ok | 1 + test/fail/ok/not-static.tc.ret.ok | 1 + test/fail/ok/object-patterns.tc.ret.ok | 1 + test/fail/ok/objpat-duplicate.tc.ret.ok | 1 + test/fail/ok/objpat-infer.tc.ret.ok | 1 + test/fail/ok/objpat-mutable.tc.ret.ok | 1 + test/fail/ok/one-tuple-ambiguity.tc.ret.ok | 1 + test/fail/ok/pat-inconsistent.tc.ret.ok | 1 + test/fail/ok/pat-subtyping-fail.tc.ret.ok | 1 + test/fail/ok/prim-in-source.tc.ret.ok | 1 + test/fail/ok/return-before-define.tc.ret.ok | 1 + test/fail/ok/self-import.tc.ret.ok | 1 + test/fail/ok/switch-type.tc.ret.ok | 1 + test/fail/ok/text-high-surrogate.tc.ret.ok | 1 + test/fail/ok/text-low-surrogate.tc.ret.ok | 1 + test/fail/ok/typ-field-lub-glb-fail.tc.ret.ok | 1 + test/fail/ok/use-before-define.tc.ret.ok | 1 + test/fail/ok/use-before-define2.tc.ret.ok | 1 + test/fail/ok/use-before-define4.tc.ret.ok | 1 + ...m.stderr.ok => use-before-define5.comp.ok} | 0 .../ok/use-before-define5.wasm-run.ret.ok | 1 + test/fail/ok/use-before-define6.tc.ret.ok | 1 + test/fail/ok/var-const-array.tc.ret.ok | 1 + test/fail/ok/var-const-field.tc.ret.ok | 1 + test/fail/ok/word-range.tc.ret.ok | 1 + test/quick.mk | 31 +++-- test/run-deser/Makefile | 3 +- ....dvm-run.ok => array-out-of-bounds.dvm.ok} | 0 ...ile.dvm-run.ok => async-loop-while.dvm.ok} | 0 ...sync-loop.dvm-run.ok => async-loop.dvm.ok} | 0 ...ew-obj.dvm-run.ok => async-new-obj.dvm.ok} | 0 ...bj-mut.dvm-run.ok => async-obj-mut.dvm.ok} | 0 ...nc-while.dvm-run.ok => async-while.dvm.ok} | 0 .../ok/{await.dvm-run.ok => await.dvm.ok} | 0 .../ok/{block.dvm-run.ok => block.dvm.ok} | 0 .../ok/{chat.dvm-run.ok => chat.dvm.ok} | 0 .../ok/{chatpp.dvm-run.ok => chatpp.dvm.ok} | 0 ...arams.dvm-run.ok => closure-params.dvm.ok} | 0 ...s.wasm.stderr.ok => counter-class.comp.ok} | 0 ...-class.dvm-run.ok => counter-class.dvm.ok} | 0 .../ok/{counter.dvm-run.ok => counter.dvm.ok} | 0 .../{counter2.dvm-run.ok => counter2.dvm.ok} | 0 ...rams.idl.stderr.ok => data-params.comp.ok} | 0 ...a-params.dvm-run.ok => data-params.dvm.ok} | 0 .../run-dfinity/ok/data-params.wasm.stderr.ok | 4 - .../ok/{fac.dvm-run.ok => fac.dvm.ok} | 0 ...l.stderr.ok => flatten-awaitables.comp.ok} | 0 ...s.dvm-run.ok => flatten-awaitables.dvm.ok} | 0 .../ok/flatten-awaitables.wasm.stderr.ok | 120 ------------------ ...{for-await.dvm-run.ok => for-await.dvm.ok} | 0 ...rec.dvm-run.ok => generic-tail-rec.dvm.ok} | 0 ...d.dvm-run.ok => hello-concat-world.dvm.ok} | 0 ...nc.dvm-run.ok => hello-world-async.dvm.ok} | 0 ...it.dvm-run.ok => hello-world-await.dvm.ok} | 0 ....dvm-run.ok => hello-world-message.dvm.ok} | 0 ...dvm-run.ok => hello-world-message2.dvm.ok} | 0 ...lo-world.dvm-run.ok => hello-world.dvm.ok} | 0 ...-world2.dvm-run.ok => hello-world2.dvm.ok} | 0 ...-world3.dvm-run.ok => hello-world3.dvm.ok} | 0 ...ter.dvm-run.ok => indirect-counter.dvm.ok} | 0 ...al-throw.dvm-run.ok => local-throw.dvm.ok} | 0 ...ary-async.dvm-run.ok => nary-async.dvm.ok} | 0 .../{overflow.dvm-run.ok => overflow.dvm.ok} | 0 .../ok/{query.dvm-run.ok => query.dvm.ok} | 0 ...ams.dvm-run.ok => reference-params.dvm.ok} | 0 .../{selftail.dvm-run.ok => selftail.dvm.ok} | 0 .../ok/{show.dvm-run.ok => show.dvm.ok} | 0 ...e-throw.dvm-run.ok => simple-throw.dvm.ok} | 0 ...itions.dvm-run.ok => tailpositions.dvm.ok} | 0 ...{text-iter.dvm-run.ok => text-iter.dvm.ok} | 0 ...he-answer.dvm-run.ok => the-answer.dvm.ok} | 0 test/run-drun/ok/idl-func.tc.ret.ok | 1 + ...wasm.stderr.ok => multiple-actors.comp.ok} | 0 test/run-drun/ok/multiple-actors.comp.ret.ok | 1 + test/run-drun/ok/unsupported.tc.ret.ok | 1 + test/run.sh | 84 ++++++------ test/run/ok/TRAP-write-before-init.tc.ret.ok | 1 + test/run/ok/array-bounds.run.ret.ok | 1 + test/run/ok/array-bounds.wasm-run.ret.ok | 1 + test/run/ok/assertFalse.run.ret.ok | 1 + test/run/ok/assertFalse.wasm-run.ret.ok | 1 + test/run/ok/conversions.wasm-run.ret.ok | 1 + ...overage.idl.stderr.ok => coverage.comp.ok} | 0 test/run/ok/coverage.wasm.stderr.ok | 101 --------------- test/run/ok/idlHash.wasm-run.ret.ok | 1 + ...ssue442.idl.stderr.ok => issue442.comp.ok} | 0 test/run/ok/issue442.wasm.stderr.ok | 6 - ...uple.idl.stderr.ok => large-tuple.comp.ok} | 0 test/run/ok/large-tuple.wasm.stderr.ok | 23 ---- ...ops.wasm.stderr.ok => numeric-ops.comp.ok} | 0 ...bjects1.idl.stderr.ok => objects1.comp.ok} | 0 test/run/ok/objects1.wasm.stderr.ok | 10 -- test/run/ok/overflow.run.ret.ok | 1 + test/run/ok/overflow.wasm-run.ret.ok | 1 + ...g.wasm.stderr.ok => pat-subtyping.comp.ok} | 0 test/run/ok/pat-subtyping.idl.stderr.ok | 41 ------ ....wasm.stderr.ok => relational-ops.comp.ok} | 0 .../{switch.idl.stderr.ok => switch.comp.ok} | 0 test/run/ok/switch.wasm.stderr.ok | 17 --- ....wasm.stderr.ok => type-inference.comp.ok} | 0 test/run/ok/type-inference.idl.stderr.ok | 37 ------ test/trap/ok/addInt16-lower.run.ret.ok | 1 + test/trap/ok/addInt16-lower.wasm-run.ret.ok | 1 + test/trap/ok/addInt16-upper.run.ret.ok | 1 + test/trap/ok/addInt16-upper.wasm-run.ret.ok | 1 + test/trap/ok/addInt32-lower.run.ret.ok | 1 + test/trap/ok/addInt32-lower.wasm-run.ret.ok | 1 + test/trap/ok/addInt32-upper.run.ret.ok | 1 + test/trap/ok/addInt32-upper.wasm-run.ret.ok | 1 + test/trap/ok/addInt64-lower.run.ret.ok | 1 + test/trap/ok/addInt64-lower.wasm-run.ret.ok | 1 + test/trap/ok/addInt64-upper.run.ret.ok | 1 + test/trap/ok/addInt64-upper.wasm-run.ret.ok | 1 + test/trap/ok/addInt8-lower.run.ret.ok | 1 + test/trap/ok/addInt8-lower.wasm-run.ret.ok | 1 + test/trap/ok/addInt8-upper.run.ret.ok | 1 + test/trap/ok/addInt8-upper.wasm-run.ret.ok | 1 + test/trap/ok/addNat16.run.ret.ok | 1 + test/trap/ok/addNat16.wasm-run.ret.ok | 1 + test/trap/ok/addNat32.run.ret.ok | 1 + test/trap/ok/addNat32.wasm-run.ret.ok | 1 + test/trap/ok/addNat64.run.ret.ok | 1 + test/trap/ok/addNat64.wasm-run.ret.ok | 1 + test/trap/ok/addNat8.run.ret.ok | 1 + test/trap/ok/addNat8.wasm-run.ret.ok | 1 + test/trap/ok/divInt16.run.ret.ok | 1 + test/trap/ok/divInt16.wasm-run.ret.ok | 1 + test/trap/ok/divInt32.run.ret.ok | 1 + test/trap/ok/divInt32.wasm-run.ret.ok | 1 + test/trap/ok/divInt64.run.ret.ok | 1 + test/trap/ok/divInt64.wasm-run.ret.ok | 1 + test/trap/ok/divInt8.run.ret.ok | 1 + test/trap/ok/divInt8.wasm-run.ret.ok | 1 + test/trap/ok/mulInt16-lower.run.ret.ok | 1 + test/trap/ok/mulInt16-lower.wasm-run.ret.ok | 1 + test/trap/ok/mulInt16-upper.run.ret.ok | 1 + test/trap/ok/mulInt16-upper.wasm-run.ret.ok | 1 + test/trap/ok/mulInt32-lower.run.ret.ok | 1 + test/trap/ok/mulInt32-lower.wasm-run.ret.ok | 1 + test/trap/ok/mulInt32-upper.run.ret.ok | 1 + test/trap/ok/mulInt32-upper.wasm-run.ret.ok | 1 + test/trap/ok/mulInt64-lower.run.ret.ok | 1 + test/trap/ok/mulInt64-lower.wasm-run.ret.ok | 1 + test/trap/ok/mulInt64-upper.run.ret.ok | 1 + test/trap/ok/mulInt64-upper.wasm-run.ret.ok | 1 + test/trap/ok/mulInt8-lower.run.ret.ok | 1 + test/trap/ok/mulInt8-lower.wasm-run.ret.ok | 1 + test/trap/ok/mulInt8-upper.run.ret.ok | 1 + test/trap/ok/mulInt8-upper.wasm-run.ret.ok | 1 + test/trap/ok/mulNat16.run.ret.ok | 1 + test/trap/ok/mulNat16.wasm-run.ret.ok | 1 + test/trap/ok/mulNat32.run.ret.ok | 1 + test/trap/ok/mulNat32.wasm-run.ret.ok | 1 + test/trap/ok/mulNat64.run.ret.ok | 1 + test/trap/ok/mulNat64.wasm-run.ret.ok | 1 + test/trap/ok/mulNat8.run.ret.ok | 1 + test/trap/ok/mulNat8.wasm-run.ret.ok | 1 + test/trap/ok/outrange-int16-lower.run.ret.ok | 1 + .../ok/outrange-int16-lower.wasm-run.ret.ok | 1 + .../ok/outrange-int16-negation.run.ret.ok | 1 + .../outrange-int16-negation.wasm-run.ret.ok | 1 + test/trap/ok/outrange-int16-upper.run.ret.ok | 1 + .../ok/outrange-int16-upper.wasm-run.ret.ok | 1 + test/trap/ok/outrange-int32-lower.run.ret.ok | 1 + .../ok/outrange-int32-lower.wasm-run.ret.ok | 1 + .../ok/outrange-int32-negation.run.ret.ok | 1 + .../outrange-int32-negation.wasm-run.ret.ok | 1 + test/trap/ok/outrange-int32-upper.run.ret.ok | 1 + .../ok/outrange-int32-upper.wasm-run.ret.ok | 1 + test/trap/ok/outrange-int64-lower.run.ret.ok | 1 + .../ok/outrange-int64-lower.wasm-run.ret.ok | 1 + .../ok/outrange-int64-negation.run.ret.ok | 1 + .../outrange-int64-negation.wasm-run.ret.ok | 1 + test/trap/ok/outrange-int64-upper.run.ret.ok | 1 + .../ok/outrange-int64-upper.wasm-run.ret.ok | 1 + test/trap/ok/outrange-int8-lower.run.ret.ok | 1 + .../ok/outrange-int8-lower.wasm-run.ret.ok | 1 + .../trap/ok/outrange-int8-negation.run.ret.ok | 1 + .../ok/outrange-int8-negation.wasm-run.ret.ok | 1 + test/trap/ok/outrange-int8-upper.run.ret.ok | 1 + .../ok/outrange-int8-upper.wasm-run.ret.ok | 1 + test/trap/ok/outrange-nat16.run.ret.ok | 1 + test/trap/ok/outrange-nat16.wasm-run.ret.ok | 1 + test/trap/ok/outrange-nat32.run.ret.ok | 1 + test/trap/ok/outrange-nat32.wasm-run.ret.ok | 1 + test/trap/ok/outrange-nat64.run.ret.ok | 1 + test/trap/ok/outrange-nat64.wasm-run.ret.ok | 1 + test/trap/ok/outrange-nat8.run.ret.ok | 1 + test/trap/ok/outrange-nat8.wasm-run.ret.ok | 1 + test/trap/ok/powInt32-lower.run.ret.ok | 1 + test/trap/ok/powInt32-lower.wasm-run.ret.ok | 1 + test/trap/ok/powInt32-raise-neg.run.ret.ok | 1 + .../ok/powInt32-raise-neg.wasm-run.ret.ok | 1 + test/trap/ok/powInt32-upper.run.ret.ok | 1 + test/trap/ok/powInt32-upper.wasm-run.ret.ok | 1 + test/trap/ok/powInt64-lower-fast.run.ret.ok | 1 + .../ok/powInt64-lower-fast.wasm-run.ret.ok | 1 + test/trap/ok/powInt64-lower-slow.run.ret.ok | 1 + .../ok/powInt64-lower-slow.wasm-run.ret.ok | 1 + test/trap/ok/powInt64-raise-neg.run.ret.ok | 1 + .../ok/powInt64-raise-neg.wasm-run.ret.ok | 1 + test/trap/ok/powInt64-upper-fast.run.ret.ok | 1 + .../ok/powInt64-upper-fast.wasm-run.ret.ok | 1 + test/trap/ok/powInt64-upper-slow.run.ret.ok | 1 + .../ok/powInt64-upper-slow.wasm-run.ret.ok | 1 + test/trap/ok/powInt8-lower.run.ret.ok | 1 + test/trap/ok/powInt8-lower.wasm-run.ret.ok | 1 + test/trap/ok/powInt8-raise-neg.run.ret.ok | 1 + .../trap/ok/powInt8-raise-neg.wasm-run.ret.ok | 1 + test/trap/ok/powInt8-upper.run.ret.ok | 1 + test/trap/ok/powInt8-upper.wasm-run.ret.ok | 1 + test/trap/ok/powNat16.run.ret.ok | 1 + test/trap/ok/powNat16.wasm-run.ret.ok | 1 + test/trap/ok/powNat32.run.ret.ok | 1 + test/trap/ok/powNat32.wasm-run.ret.ok | 1 + test/trap/ok/powNat64.run.ret.ok | 1 + test/trap/ok/powNat64.wasm-run.ret.ok | 1 + test/trap/ok/powNat8.run.ret.ok | 1 + test/trap/ok/powNat8.wasm-run.ret.ok | 1 + test/trap/ok/subInt16-lower.run.ret.ok | 1 + test/trap/ok/subInt16-lower.wasm-run.ret.ok | 1 + test/trap/ok/subInt16-upper.run.ret.ok | 1 + test/trap/ok/subInt16-upper.wasm-run.ret.ok | 1 + test/trap/ok/subInt32-lower.run.ret.ok | 1 + test/trap/ok/subInt32-lower.wasm-run.ret.ok | 1 + test/trap/ok/subInt32-upper.run.ret.ok | 1 + test/trap/ok/subInt32-upper.wasm-run.ret.ok | 1 + test/trap/ok/subInt64-lower.run.ret.ok | 1 + test/trap/ok/subInt64-lower.wasm-run.ret.ok | 1 + test/trap/ok/subInt64-upper.run.ret.ok | 1 + test/trap/ok/subInt64-upper.wasm-run.ret.ok | 1 + test/trap/ok/subInt8-lower.run.ret.ok | 1 + test/trap/ok/subInt8-lower.wasm-run.ret.ok | 1 + test/trap/ok/subInt8-upper.run.ret.ok | 1 + test/trap/ok/subInt8-upper.wasm-run.ret.ok | 1 + test/trap/ok/subNat16.run.ret.ok | 1 + test/trap/ok/subNat16.wasm-run.ret.ok | 1 + test/trap/ok/subNat32.run.ret.ok | 1 + test/trap/ok/subNat32.wasm-run.ret.ok | 1 + test/trap/ok/subNat64-slow.run.ret.ok | 1 + test/trap/ok/subNat64-slow.wasm-run.ret.ok | 1 + test/trap/ok/subNat64.run.ret.ok | 1 + test/trap/ok/subNat64.wasm-run.ret.ok | 1 + test/trap/ok/subNat8.run.ret.ok | 1 + test/trap/ok/subNat8.wasm-run.ret.ok | 1 + 294 files changed, 286 insertions(+), 418 deletions(-) rename test/as-idl/ok/{fields.idl.stderr.ok => fields.idl.ok} (100%) create mode 100644 test/as-idl/ok/fields.idl.ret.ok create mode 100644 test/fail/ok/AST-60.tc.ret.ok create mode 100644 test/fail/ok/abstract-msgs.tc.ret.ok create mode 100644 test/fail/ok/actor-match.tc.ret.ok create mode 100644 test/fail/ok/actor-reexport.tc.ret.ok create mode 100644 test/fail/ok/argument-subtyping.tc.ret.ok create mode 100644 test/fail/ok/ast81-clash.tc.ret.ok create mode 100644 test/fail/ok/asyncret1.tc.ret.ok create mode 100644 test/fail/ok/asyncret2.tc.ret.ok create mode 100644 test/fail/ok/asyncret3.tc.ret.ok create mode 100644 test/fail/ok/await-in-actor.tc.ret.ok create mode 100644 test/fail/ok/bad-unops.tc.ret.ok create mode 100644 test/fail/ok/branch-before-define.tc.ret.ok create mode 100644 test/fail/ok/char-high-surrogate-trap.run.ret.ok create mode 100644 test/fail/ok/char-high-surrogate-trap.wasm-run.ret.ok create mode 100644 test/fail/ok/char-high-surrogate.tc.ret.ok create mode 100644 test/fail/ok/char-low-surrogate-trap.run.ret.ok create mode 100644 test/fail/ok/char-low-surrogate-trap.wasm-run.ret.ok create mode 100644 test/fail/ok/char-low-surrogate.tc.ret.ok create mode 100644 test/fail/ok/char-trap.run.ret.ok create mode 100644 test/fail/ok/char-trap.wasm-run.ret.ok create mode 100644 test/fail/ok/class.tc.ret.ok create mode 100644 test/fail/ok/const-var-array.tc.ret.ok create mode 100644 test/fail/ok/const-var-field.tc.ret.ok create mode 100644 test/fail/ok/cyclic-bound1.tc.ret.ok create mode 100644 test/fail/ok/cyclic-bound2.tc.ret.ok create mode 100644 test/fail/ok/cyclic-bound3.tc.ret.ok create mode 100644 test/fail/ok/cyclic-bound4.tc.ret.ok create mode 100644 test/fail/ok/cyclic-bound5.tc.ret.ok create mode 100644 test/fail/ok/debug.tc.ret.ok create mode 100644 test/fail/ok/decl-clash.tc.ret.ok create mode 100644 test/fail/ok/duplicate-field.tc.ret.ok create mode 100644 test/fail/ok/f-bounds-fail.tc.ret.ok create mode 100644 test/fail/ok/issue103.tc.ret.ok create mode 100644 test/fail/ok/issue167.tc.ret.ok rename test/fail/ok/{issue36.wasm.stderr.ok => issue36.comp.ok} (100%) create mode 100644 test/fail/ok/issue36.wasm-run.ret.ok create mode 100644 test/fail/ok/modexp1.tc.ret.ok create mode 100644 test/fail/ok/modexp2.tc.ret.ok create mode 100644 test/fail/ok/modexp3.tc.ret.ok create mode 100644 test/fail/ok/modexp4.tc.ret.ok create mode 100644 test/fail/ok/modexp5.tc.ret.ok create mode 100644 test/fail/ok/modules-fwd.tc.ret.ok create mode 100644 test/fail/ok/modules-shadow.tc.ret.ok create mode 100644 test/fail/ok/nested-class-rec-fail.tc.ret.ok create mode 100644 test/fail/ok/non_static_module.tc.ret.ok create mode 100644 test/fail/ok/nonlinear-pat.tc.ret.ok create mode 100644 test/fail/ok/not-static.tc.ret.ok create mode 100644 test/fail/ok/object-patterns.tc.ret.ok create mode 100644 test/fail/ok/objpat-duplicate.tc.ret.ok create mode 100644 test/fail/ok/objpat-infer.tc.ret.ok create mode 100644 test/fail/ok/objpat-mutable.tc.ret.ok create mode 100644 test/fail/ok/one-tuple-ambiguity.tc.ret.ok create mode 100644 test/fail/ok/pat-inconsistent.tc.ret.ok create mode 100644 test/fail/ok/pat-subtyping-fail.tc.ret.ok create mode 100644 test/fail/ok/prim-in-source.tc.ret.ok create mode 100644 test/fail/ok/return-before-define.tc.ret.ok create mode 100644 test/fail/ok/self-import.tc.ret.ok create mode 100644 test/fail/ok/switch-type.tc.ret.ok create mode 100644 test/fail/ok/text-high-surrogate.tc.ret.ok create mode 100644 test/fail/ok/text-low-surrogate.tc.ret.ok create mode 100644 test/fail/ok/typ-field-lub-glb-fail.tc.ret.ok create mode 100644 test/fail/ok/use-before-define.tc.ret.ok create mode 100644 test/fail/ok/use-before-define2.tc.ret.ok create mode 100644 test/fail/ok/use-before-define4.tc.ret.ok rename test/fail/ok/{use-before-define5.wasm.stderr.ok => use-before-define5.comp.ok} (100%) create mode 100644 test/fail/ok/use-before-define5.wasm-run.ret.ok create mode 100644 test/fail/ok/use-before-define6.tc.ret.ok create mode 100644 test/fail/ok/var-const-array.tc.ret.ok create mode 100644 test/fail/ok/var-const-field.tc.ret.ok create mode 100644 test/fail/ok/word-range.tc.ret.ok rename test/run-dfinity/ok/{array-out-of-bounds.dvm-run.ok => array-out-of-bounds.dvm.ok} (100%) rename test/run-dfinity/ok/{async-loop-while.dvm-run.ok => async-loop-while.dvm.ok} (100%) rename test/run-dfinity/ok/{async-loop.dvm-run.ok => async-loop.dvm.ok} (100%) rename test/run-dfinity/ok/{async-new-obj.dvm-run.ok => async-new-obj.dvm.ok} (100%) rename test/run-dfinity/ok/{async-obj-mut.dvm-run.ok => async-obj-mut.dvm.ok} (100%) rename test/run-dfinity/ok/{async-while.dvm-run.ok => async-while.dvm.ok} (100%) rename test/run-dfinity/ok/{await.dvm-run.ok => await.dvm.ok} (100%) rename test/run-dfinity/ok/{block.dvm-run.ok => block.dvm.ok} (100%) rename test/run-dfinity/ok/{chat.dvm-run.ok => chat.dvm.ok} (100%) rename test/run-dfinity/ok/{chatpp.dvm-run.ok => chatpp.dvm.ok} (100%) rename test/run-dfinity/ok/{closure-params.dvm-run.ok => closure-params.dvm.ok} (100%) rename test/run-dfinity/ok/{counter-class.wasm.stderr.ok => counter-class.comp.ok} (100%) rename test/run-dfinity/ok/{counter-class.dvm-run.ok => counter-class.dvm.ok} (100%) rename test/run-dfinity/ok/{counter.dvm-run.ok => counter.dvm.ok} (100%) rename test/run-dfinity/ok/{counter2.dvm-run.ok => counter2.dvm.ok} (100%) rename test/run-dfinity/ok/{data-params.idl.stderr.ok => data-params.comp.ok} (100%) rename test/run-dfinity/ok/{data-params.dvm-run.ok => data-params.dvm.ok} (100%) delete mode 100644 test/run-dfinity/ok/data-params.wasm.stderr.ok rename test/run-dfinity/ok/{fac.dvm-run.ok => fac.dvm.ok} (100%) rename test/run-dfinity/ok/{flatten-awaitables.idl.stderr.ok => flatten-awaitables.comp.ok} (100%) rename test/run-dfinity/ok/{flatten-awaitables.dvm-run.ok => flatten-awaitables.dvm.ok} (100%) delete mode 100644 test/run-dfinity/ok/flatten-awaitables.wasm.stderr.ok rename test/run-dfinity/ok/{for-await.dvm-run.ok => for-await.dvm.ok} (100%) rename test/run-dfinity/ok/{generic-tail-rec.dvm-run.ok => generic-tail-rec.dvm.ok} (100%) rename test/run-dfinity/ok/{hello-concat-world.dvm-run.ok => hello-concat-world.dvm.ok} (100%) rename test/run-dfinity/ok/{hello-world-async.dvm-run.ok => hello-world-async.dvm.ok} (100%) rename test/run-dfinity/ok/{hello-world-await.dvm-run.ok => hello-world-await.dvm.ok} (100%) rename test/run-dfinity/ok/{hello-world-message.dvm-run.ok => hello-world-message.dvm.ok} (100%) rename test/run-dfinity/ok/{hello-world-message2.dvm-run.ok => hello-world-message2.dvm.ok} (100%) rename test/run-dfinity/ok/{hello-world.dvm-run.ok => hello-world.dvm.ok} (100%) rename test/run-dfinity/ok/{hello-world2.dvm-run.ok => hello-world2.dvm.ok} (100%) rename test/run-dfinity/ok/{hello-world3.dvm-run.ok => hello-world3.dvm.ok} (100%) rename test/run-dfinity/ok/{indirect-counter.dvm-run.ok => indirect-counter.dvm.ok} (100%) rename test/run-dfinity/ok/{local-throw.dvm-run.ok => local-throw.dvm.ok} (100%) rename test/run-dfinity/ok/{nary-async.dvm-run.ok => nary-async.dvm.ok} (100%) rename test/run-dfinity/ok/{overflow.dvm-run.ok => overflow.dvm.ok} (100%) rename test/run-dfinity/ok/{query.dvm-run.ok => query.dvm.ok} (100%) rename test/run-dfinity/ok/{reference-params.dvm-run.ok => reference-params.dvm.ok} (100%) rename test/run-dfinity/ok/{selftail.dvm-run.ok => selftail.dvm.ok} (100%) rename test/run-dfinity/ok/{show.dvm-run.ok => show.dvm.ok} (100%) rename test/run-dfinity/ok/{simple-throw.dvm-run.ok => simple-throw.dvm.ok} (100%) rename test/run-dfinity/ok/{tailpositions.dvm-run.ok => tailpositions.dvm.ok} (100%) rename test/run-dfinity/ok/{text-iter.dvm-run.ok => text-iter.dvm.ok} (100%) rename test/run-dfinity/ok/{the-answer.dvm-run.ok => the-answer.dvm.ok} (100%) create mode 100644 test/run-drun/ok/idl-func.tc.ret.ok rename test/run-drun/ok/{multiple-actors.wasm.stderr.ok => multiple-actors.comp.ok} (100%) create mode 100644 test/run-drun/ok/multiple-actors.comp.ret.ok create mode 100644 test/run-drun/ok/unsupported.tc.ret.ok create mode 100644 test/run/ok/TRAP-write-before-init.tc.ret.ok create mode 100644 test/run/ok/array-bounds.run.ret.ok create mode 100644 test/run/ok/array-bounds.wasm-run.ret.ok create mode 100644 test/run/ok/assertFalse.run.ret.ok create mode 100644 test/run/ok/assertFalse.wasm-run.ret.ok create mode 100644 test/run/ok/conversions.wasm-run.ret.ok rename test/run/ok/{coverage.idl.stderr.ok => coverage.comp.ok} (100%) delete mode 100644 test/run/ok/coverage.wasm.stderr.ok create mode 100644 test/run/ok/idlHash.wasm-run.ret.ok rename test/run/ok/{issue442.idl.stderr.ok => issue442.comp.ok} (100%) delete mode 100644 test/run/ok/issue442.wasm.stderr.ok rename test/run/ok/{large-tuple.idl.stderr.ok => large-tuple.comp.ok} (100%) delete mode 100644 test/run/ok/large-tuple.wasm.stderr.ok rename test/run/ok/{numeric-ops.wasm.stderr.ok => numeric-ops.comp.ok} (100%) rename test/run/ok/{objects1.idl.stderr.ok => objects1.comp.ok} (100%) delete mode 100644 test/run/ok/objects1.wasm.stderr.ok create mode 100644 test/run/ok/overflow.run.ret.ok create mode 100644 test/run/ok/overflow.wasm-run.ret.ok rename test/run/ok/{pat-subtyping.wasm.stderr.ok => pat-subtyping.comp.ok} (100%) delete mode 100644 test/run/ok/pat-subtyping.idl.stderr.ok rename test/run/ok/{relational-ops.wasm.stderr.ok => relational-ops.comp.ok} (100%) rename test/run/ok/{switch.idl.stderr.ok => switch.comp.ok} (100%) delete mode 100644 test/run/ok/switch.wasm.stderr.ok rename test/run/ok/{type-inference.wasm.stderr.ok => type-inference.comp.ok} (100%) delete mode 100644 test/run/ok/type-inference.idl.stderr.ok create mode 100644 test/trap/ok/addInt16-lower.run.ret.ok create mode 100644 test/trap/ok/addInt16-lower.wasm-run.ret.ok create mode 100644 test/trap/ok/addInt16-upper.run.ret.ok create mode 100644 test/trap/ok/addInt16-upper.wasm-run.ret.ok create mode 100644 test/trap/ok/addInt32-lower.run.ret.ok create mode 100644 test/trap/ok/addInt32-lower.wasm-run.ret.ok create mode 100644 test/trap/ok/addInt32-upper.run.ret.ok create mode 100644 test/trap/ok/addInt32-upper.wasm-run.ret.ok create mode 100644 test/trap/ok/addInt64-lower.run.ret.ok create mode 100644 test/trap/ok/addInt64-lower.wasm-run.ret.ok create mode 100644 test/trap/ok/addInt64-upper.run.ret.ok create mode 100644 test/trap/ok/addInt64-upper.wasm-run.ret.ok create mode 100644 test/trap/ok/addInt8-lower.run.ret.ok create mode 100644 test/trap/ok/addInt8-lower.wasm-run.ret.ok create mode 100644 test/trap/ok/addInt8-upper.run.ret.ok create mode 100644 test/trap/ok/addInt8-upper.wasm-run.ret.ok create mode 100644 test/trap/ok/addNat16.run.ret.ok create mode 100644 test/trap/ok/addNat16.wasm-run.ret.ok create mode 100644 test/trap/ok/addNat32.run.ret.ok create mode 100644 test/trap/ok/addNat32.wasm-run.ret.ok create mode 100644 test/trap/ok/addNat64.run.ret.ok create mode 100644 test/trap/ok/addNat64.wasm-run.ret.ok create mode 100644 test/trap/ok/addNat8.run.ret.ok create mode 100644 test/trap/ok/addNat8.wasm-run.ret.ok create mode 100644 test/trap/ok/divInt16.run.ret.ok create mode 100644 test/trap/ok/divInt16.wasm-run.ret.ok create mode 100644 test/trap/ok/divInt32.run.ret.ok create mode 100644 test/trap/ok/divInt32.wasm-run.ret.ok create mode 100644 test/trap/ok/divInt64.run.ret.ok create mode 100644 test/trap/ok/divInt64.wasm-run.ret.ok create mode 100644 test/trap/ok/divInt8.run.ret.ok create mode 100644 test/trap/ok/divInt8.wasm-run.ret.ok create mode 100644 test/trap/ok/mulInt16-lower.run.ret.ok create mode 100644 test/trap/ok/mulInt16-lower.wasm-run.ret.ok create mode 100644 test/trap/ok/mulInt16-upper.run.ret.ok create mode 100644 test/trap/ok/mulInt16-upper.wasm-run.ret.ok create mode 100644 test/trap/ok/mulInt32-lower.run.ret.ok create mode 100644 test/trap/ok/mulInt32-lower.wasm-run.ret.ok create mode 100644 test/trap/ok/mulInt32-upper.run.ret.ok create mode 100644 test/trap/ok/mulInt32-upper.wasm-run.ret.ok create mode 100644 test/trap/ok/mulInt64-lower.run.ret.ok create mode 100644 test/trap/ok/mulInt64-lower.wasm-run.ret.ok create mode 100644 test/trap/ok/mulInt64-upper.run.ret.ok create mode 100644 test/trap/ok/mulInt64-upper.wasm-run.ret.ok create mode 100644 test/trap/ok/mulInt8-lower.run.ret.ok create mode 100644 test/trap/ok/mulInt8-lower.wasm-run.ret.ok create mode 100644 test/trap/ok/mulInt8-upper.run.ret.ok create mode 100644 test/trap/ok/mulInt8-upper.wasm-run.ret.ok create mode 100644 test/trap/ok/mulNat16.run.ret.ok create mode 100644 test/trap/ok/mulNat16.wasm-run.ret.ok create mode 100644 test/trap/ok/mulNat32.run.ret.ok create mode 100644 test/trap/ok/mulNat32.wasm-run.ret.ok create mode 100644 test/trap/ok/mulNat64.run.ret.ok create mode 100644 test/trap/ok/mulNat64.wasm-run.ret.ok create mode 100644 test/trap/ok/mulNat8.run.ret.ok create mode 100644 test/trap/ok/mulNat8.wasm-run.ret.ok create mode 100644 test/trap/ok/outrange-int16-lower.run.ret.ok create mode 100644 test/trap/ok/outrange-int16-lower.wasm-run.ret.ok create mode 100644 test/trap/ok/outrange-int16-negation.run.ret.ok create mode 100644 test/trap/ok/outrange-int16-negation.wasm-run.ret.ok create mode 100644 test/trap/ok/outrange-int16-upper.run.ret.ok create mode 100644 test/trap/ok/outrange-int16-upper.wasm-run.ret.ok create mode 100644 test/trap/ok/outrange-int32-lower.run.ret.ok create mode 100644 test/trap/ok/outrange-int32-lower.wasm-run.ret.ok create mode 100644 test/trap/ok/outrange-int32-negation.run.ret.ok create mode 100644 test/trap/ok/outrange-int32-negation.wasm-run.ret.ok create mode 100644 test/trap/ok/outrange-int32-upper.run.ret.ok create mode 100644 test/trap/ok/outrange-int32-upper.wasm-run.ret.ok create mode 100644 test/trap/ok/outrange-int64-lower.run.ret.ok create mode 100644 test/trap/ok/outrange-int64-lower.wasm-run.ret.ok create mode 100644 test/trap/ok/outrange-int64-negation.run.ret.ok create mode 100644 test/trap/ok/outrange-int64-negation.wasm-run.ret.ok create mode 100644 test/trap/ok/outrange-int64-upper.run.ret.ok create mode 100644 test/trap/ok/outrange-int64-upper.wasm-run.ret.ok create mode 100644 test/trap/ok/outrange-int8-lower.run.ret.ok create mode 100644 test/trap/ok/outrange-int8-lower.wasm-run.ret.ok create mode 100644 test/trap/ok/outrange-int8-negation.run.ret.ok create mode 100644 test/trap/ok/outrange-int8-negation.wasm-run.ret.ok create mode 100644 test/trap/ok/outrange-int8-upper.run.ret.ok create mode 100644 test/trap/ok/outrange-int8-upper.wasm-run.ret.ok create mode 100644 test/trap/ok/outrange-nat16.run.ret.ok create mode 100644 test/trap/ok/outrange-nat16.wasm-run.ret.ok create mode 100644 test/trap/ok/outrange-nat32.run.ret.ok create mode 100644 test/trap/ok/outrange-nat32.wasm-run.ret.ok create mode 100644 test/trap/ok/outrange-nat64.run.ret.ok create mode 100644 test/trap/ok/outrange-nat64.wasm-run.ret.ok create mode 100644 test/trap/ok/outrange-nat8.run.ret.ok create mode 100644 test/trap/ok/outrange-nat8.wasm-run.ret.ok create mode 100644 test/trap/ok/powInt32-lower.run.ret.ok create mode 100644 test/trap/ok/powInt32-lower.wasm-run.ret.ok create mode 100644 test/trap/ok/powInt32-raise-neg.run.ret.ok create mode 100644 test/trap/ok/powInt32-raise-neg.wasm-run.ret.ok create mode 100644 test/trap/ok/powInt32-upper.run.ret.ok create mode 100644 test/trap/ok/powInt32-upper.wasm-run.ret.ok create mode 100644 test/trap/ok/powInt64-lower-fast.run.ret.ok create mode 100644 test/trap/ok/powInt64-lower-fast.wasm-run.ret.ok create mode 100644 test/trap/ok/powInt64-lower-slow.run.ret.ok create mode 100644 test/trap/ok/powInt64-lower-slow.wasm-run.ret.ok create mode 100644 test/trap/ok/powInt64-raise-neg.run.ret.ok create mode 100644 test/trap/ok/powInt64-raise-neg.wasm-run.ret.ok create mode 100644 test/trap/ok/powInt64-upper-fast.run.ret.ok create mode 100644 test/trap/ok/powInt64-upper-fast.wasm-run.ret.ok create mode 100644 test/trap/ok/powInt64-upper-slow.run.ret.ok create mode 100644 test/trap/ok/powInt64-upper-slow.wasm-run.ret.ok create mode 100644 test/trap/ok/powInt8-lower.run.ret.ok create mode 100644 test/trap/ok/powInt8-lower.wasm-run.ret.ok create mode 100644 test/trap/ok/powInt8-raise-neg.run.ret.ok create mode 100644 test/trap/ok/powInt8-raise-neg.wasm-run.ret.ok create mode 100644 test/trap/ok/powInt8-upper.run.ret.ok create mode 100644 test/trap/ok/powInt8-upper.wasm-run.ret.ok create mode 100644 test/trap/ok/powNat16.run.ret.ok create mode 100644 test/trap/ok/powNat16.wasm-run.ret.ok create mode 100644 test/trap/ok/powNat32.run.ret.ok create mode 100644 test/trap/ok/powNat32.wasm-run.ret.ok create mode 100644 test/trap/ok/powNat64.run.ret.ok create mode 100644 test/trap/ok/powNat64.wasm-run.ret.ok create mode 100644 test/trap/ok/powNat8.run.ret.ok create mode 100644 test/trap/ok/powNat8.wasm-run.ret.ok create mode 100644 test/trap/ok/subInt16-lower.run.ret.ok create mode 100644 test/trap/ok/subInt16-lower.wasm-run.ret.ok create mode 100644 test/trap/ok/subInt16-upper.run.ret.ok create mode 100644 test/trap/ok/subInt16-upper.wasm-run.ret.ok create mode 100644 test/trap/ok/subInt32-lower.run.ret.ok create mode 100644 test/trap/ok/subInt32-lower.wasm-run.ret.ok create mode 100644 test/trap/ok/subInt32-upper.run.ret.ok create mode 100644 test/trap/ok/subInt32-upper.wasm-run.ret.ok create mode 100644 test/trap/ok/subInt64-lower.run.ret.ok create mode 100644 test/trap/ok/subInt64-lower.wasm-run.ret.ok create mode 100644 test/trap/ok/subInt64-upper.run.ret.ok create mode 100644 test/trap/ok/subInt64-upper.wasm-run.ret.ok create mode 100644 test/trap/ok/subInt8-lower.run.ret.ok create mode 100644 test/trap/ok/subInt8-lower.wasm-run.ret.ok create mode 100644 test/trap/ok/subInt8-upper.run.ret.ok create mode 100644 test/trap/ok/subInt8-upper.wasm-run.ret.ok create mode 100644 test/trap/ok/subNat16.run.ret.ok create mode 100644 test/trap/ok/subNat16.wasm-run.ret.ok create mode 100644 test/trap/ok/subNat32.run.ret.ok create mode 100644 test/trap/ok/subNat32.wasm-run.ret.ok create mode 100644 test/trap/ok/subNat64-slow.run.ret.ok create mode 100644 test/trap/ok/subNat64-slow.wasm-run.ret.ok create mode 100644 test/trap/ok/subNat64.run.ret.ok create mode 100644 test/trap/ok/subNat64.wasm-run.ret.ok create mode 100644 test/trap/ok/subNat8.run.ret.ok create mode 100644 test/trap/ok/subNat8.wasm-run.ret.ok diff --git a/default.nix b/default.nix index 59e038a3f18..eaeda694329 100644 --- a/default.nix +++ b/default.nix @@ -278,6 +278,7 @@ rec { nixpkgs.bash nixpkgs.perl nixpkgs.getconf + nixpkgs.moreutils nixpkgs.nodejs-10_x filecheck js-user-library diff --git a/test/Makefile b/test/Makefile index 44b38a1604e..bd75943b4d7 100644 --- a/test/Makefile +++ b/test/Makefile @@ -53,7 +53,6 @@ accept: $(MAKE) -C idl accept $(MAKE) -C as-idl accept $(MAKE) -C trap accept - $(MAKE) -C trap check $(MAKE) -C run-deser accept clean: diff --git a/test/as-idl/ok/fields.idl.stderr.ok b/test/as-idl/ok/fields.idl.ok similarity index 100% rename from test/as-idl/ok/fields.idl.stderr.ok rename to test/as-idl/ok/fields.idl.ok diff --git a/test/as-idl/ok/fields.idl.ret.ok b/test/as-idl/ok/fields.idl.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/as-idl/ok/fields.idl.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/AST-60.tc.ret.ok b/test/fail/ok/AST-60.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/AST-60.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/abstract-msgs.tc.ret.ok b/test/fail/ok/abstract-msgs.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/abstract-msgs.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/actor-match.tc.ret.ok b/test/fail/ok/actor-match.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/actor-match.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/actor-reexport.tc.ret.ok b/test/fail/ok/actor-reexport.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/actor-reexport.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/argument-subtyping.tc.ret.ok b/test/fail/ok/argument-subtyping.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/argument-subtyping.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/ast81-clash.tc.ret.ok b/test/fail/ok/ast81-clash.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/ast81-clash.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/asyncret1.tc.ret.ok b/test/fail/ok/asyncret1.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/asyncret1.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/asyncret2.tc.ret.ok b/test/fail/ok/asyncret2.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/asyncret2.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/asyncret3.tc.ret.ok b/test/fail/ok/asyncret3.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/asyncret3.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/await-in-actor.tc.ret.ok b/test/fail/ok/await-in-actor.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/await-in-actor.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/bad-unops.tc.ret.ok b/test/fail/ok/bad-unops.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/bad-unops.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/branch-before-define.tc.ret.ok b/test/fail/ok/branch-before-define.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/branch-before-define.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/char-high-surrogate-trap.run.ret.ok b/test/fail/ok/char-high-surrogate-trap.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/char-high-surrogate-trap.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/char-high-surrogate-trap.wasm-run.ret.ok b/test/fail/ok/char-high-surrogate-trap.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/char-high-surrogate-trap.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/char-high-surrogate.tc.ret.ok b/test/fail/ok/char-high-surrogate.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/char-high-surrogate.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/char-low-surrogate-trap.run.ret.ok b/test/fail/ok/char-low-surrogate-trap.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/char-low-surrogate-trap.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/char-low-surrogate-trap.wasm-run.ret.ok b/test/fail/ok/char-low-surrogate-trap.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/char-low-surrogate-trap.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/char-low-surrogate.tc.ret.ok b/test/fail/ok/char-low-surrogate.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/char-low-surrogate.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/char-trap.run.ret.ok b/test/fail/ok/char-trap.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/char-trap.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/char-trap.wasm-run.ret.ok b/test/fail/ok/char-trap.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/char-trap.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/class.tc.ret.ok b/test/fail/ok/class.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/class.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/const-var-array.tc.ret.ok b/test/fail/ok/const-var-array.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/const-var-array.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/const-var-field.tc.ret.ok b/test/fail/ok/const-var-field.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/const-var-field.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/cyclic-bound1.tc.ret.ok b/test/fail/ok/cyclic-bound1.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/cyclic-bound1.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/cyclic-bound2.tc.ret.ok b/test/fail/ok/cyclic-bound2.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/cyclic-bound2.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/cyclic-bound3.tc.ret.ok b/test/fail/ok/cyclic-bound3.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/cyclic-bound3.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/cyclic-bound4.tc.ret.ok b/test/fail/ok/cyclic-bound4.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/cyclic-bound4.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/cyclic-bound5.tc.ret.ok b/test/fail/ok/cyclic-bound5.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/cyclic-bound5.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/debug.tc.ret.ok b/test/fail/ok/debug.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/debug.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/decl-clash.tc.ret.ok b/test/fail/ok/decl-clash.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/decl-clash.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/duplicate-field.tc.ret.ok b/test/fail/ok/duplicate-field.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/duplicate-field.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/f-bounds-fail.tc.ret.ok b/test/fail/ok/f-bounds-fail.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/f-bounds-fail.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/issue103.tc.ret.ok b/test/fail/ok/issue103.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/issue103.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/issue167.tc.ret.ok b/test/fail/ok/issue167.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/issue167.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/issue36.wasm.stderr.ok b/test/fail/ok/issue36.comp.ok similarity index 100% rename from test/fail/ok/issue36.wasm.stderr.ok rename to test/fail/ok/issue36.comp.ok diff --git a/test/fail/ok/issue36.wasm-run.ret.ok b/test/fail/ok/issue36.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/issue36.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/modexp1.tc.ret.ok b/test/fail/ok/modexp1.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/modexp1.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/modexp2.tc.ret.ok b/test/fail/ok/modexp2.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/modexp2.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/modexp3.tc.ret.ok b/test/fail/ok/modexp3.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/modexp3.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/modexp4.tc.ret.ok b/test/fail/ok/modexp4.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/modexp4.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/modexp5.tc.ret.ok b/test/fail/ok/modexp5.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/modexp5.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/modules-fwd.tc.ret.ok b/test/fail/ok/modules-fwd.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/modules-fwd.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/modules-shadow.tc.ret.ok b/test/fail/ok/modules-shadow.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/modules-shadow.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/nested-class-rec-fail.tc.ret.ok b/test/fail/ok/nested-class-rec-fail.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/nested-class-rec-fail.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/non_static_module.tc.ret.ok b/test/fail/ok/non_static_module.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/non_static_module.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/nonlinear-pat.tc.ret.ok b/test/fail/ok/nonlinear-pat.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/nonlinear-pat.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/not-static.tc.ret.ok b/test/fail/ok/not-static.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/not-static.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/object-patterns.tc.ret.ok b/test/fail/ok/object-patterns.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/object-patterns.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/objpat-duplicate.tc.ret.ok b/test/fail/ok/objpat-duplicate.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/objpat-duplicate.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/objpat-infer.tc.ret.ok b/test/fail/ok/objpat-infer.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/objpat-infer.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/objpat-mutable.tc.ret.ok b/test/fail/ok/objpat-mutable.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/objpat-mutable.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/one-tuple-ambiguity.tc.ret.ok b/test/fail/ok/one-tuple-ambiguity.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/one-tuple-ambiguity.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/pat-inconsistent.tc.ret.ok b/test/fail/ok/pat-inconsistent.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/pat-inconsistent.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/pat-subtyping-fail.tc.ret.ok b/test/fail/ok/pat-subtyping-fail.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/pat-subtyping-fail.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/prim-in-source.tc.ret.ok b/test/fail/ok/prim-in-source.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/prim-in-source.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/return-before-define.tc.ret.ok b/test/fail/ok/return-before-define.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/return-before-define.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/self-import.tc.ret.ok b/test/fail/ok/self-import.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/self-import.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/switch-type.tc.ret.ok b/test/fail/ok/switch-type.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/switch-type.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/text-high-surrogate.tc.ret.ok b/test/fail/ok/text-high-surrogate.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/text-high-surrogate.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/text-low-surrogate.tc.ret.ok b/test/fail/ok/text-low-surrogate.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/text-low-surrogate.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/typ-field-lub-glb-fail.tc.ret.ok b/test/fail/ok/typ-field-lub-glb-fail.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/typ-field-lub-glb-fail.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/use-before-define.tc.ret.ok b/test/fail/ok/use-before-define.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/use-before-define.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/use-before-define2.tc.ret.ok b/test/fail/ok/use-before-define2.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/use-before-define2.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/use-before-define4.tc.ret.ok b/test/fail/ok/use-before-define4.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/use-before-define4.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/use-before-define5.wasm.stderr.ok b/test/fail/ok/use-before-define5.comp.ok similarity index 100% rename from test/fail/ok/use-before-define5.wasm.stderr.ok rename to test/fail/ok/use-before-define5.comp.ok diff --git a/test/fail/ok/use-before-define5.wasm-run.ret.ok b/test/fail/ok/use-before-define5.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/use-before-define5.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/use-before-define6.tc.ret.ok b/test/fail/ok/use-before-define6.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/use-before-define6.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/var-const-array.tc.ret.ok b/test/fail/ok/var-const-array.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/var-const-array.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/var-const-field.tc.ret.ok b/test/fail/ok/var-const-field.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/var-const-field.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/word-range.tc.ret.ok b/test/fail/ok/word-range.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/word-range.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/quick.mk b/test/quick.mk index d603610aea0..9ac7155ebdb 100644 --- a/test/quick.mk +++ b/test/quick.mk @@ -1,10 +1,10 @@ # Note: this rule collection is included from one level deeper TO-TEST = \ - $(patsubst %.mo,_out/%.done,$(wildcard *.mo)) \ - $(patsubst %.sh,_out/%.done,$(wildcard *.sh)) \ - $(patsubst %.wat,_out/%.done,$(wildcard *.wat)) \ - $(patsubst %.did,_out/%.done,$(wildcard *.did)) \ + $(patsubst %.mo,_out/%_done,$(wildcard *.mo)) \ + $(patsubst %.sh,_out/%_done,$(wildcard *.sh)) \ + $(patsubst %.wat,_out/%_done,$(wildcard *.wat)) \ + $(patsubst %.did,_out/%_done,$(wildcard *.did)) \ .PHONY: quick @@ -14,12 +14,17 @@ quick: $(TO-TEST) _out: @ mkdir -p $@ -# run single test, e.g. make _out/AST-56.done -_out/%.done: %.mo $(wildcard ../../src/moc) ../run.sh | _out - @+ (../run.sh $(RUNFLAGS) $< > $@.tmp && mv $@.tmp $@) || (cat $@.tmp; rm -f $@.tmp; false) -_out/%.done: %.sh $(wildcard ../../src/moc) ../run.sh | _out - @+ (../run.sh $(RUNFLAGS) $< > $@.tmp && mv $@.tmp $@) || (cat $@.tmp; rm -f $@.tmp; false) -_out/%.done: %.wat $(wildcard ../../src/moc) ../run.sh | _out - @+ (../run.sh $(RUNFLAGS) $< > $@.tmp && mv $@.tmp $@) || (cat $@.tmp; rm -f $@.tmp; false) -_out/%.done: %.did $(wildcard ../../src/didc) ../run.sh | _out - @+ (../run.sh $(RUNFLAGS) $< > $@.tmp && mv $@.tmp $@) || (cat $@.tmp; rm -f $@.tmp; false) +# run single test, e.g. make _out/AST-56_done +# _done, not .done, because run.sh likes to clean $base.* +_out/%_done: %.mo $(wildcard ../../src/moc) ../run.sh | _out + @+ chronic ../run.sh $(RUNFLAGS) $< + @+ touch $@ +_out/%_done: %.sh $(wildcard ../../src/moc) ../run.sh | _out + @+ chronic ../run.sh $(RUNFLAGS) $< + @+ touch $@ +_out/%_done: %.wat $(wildcard ../../src/moc) ../run.sh | _out + @+ chronic ../run.sh $(RUNFLAGS) $< + @+ touch $@ +_out/%_done: %.did $(wildcard ../../src/didc) ../run.sh | _out + @+ chronic ../run.sh $(RUNFLAGS) $< + @+ touch $@ diff --git a/test/run-deser/Makefile b/test/run-deser/Makefile index 2a0f93b1193..6e73fe2b147 100644 --- a/test/run-deser/Makefile +++ b/test/run-deser/Makefile @@ -9,7 +9,8 @@ all: quick quick: $(patsubst %.bin, _out/%.done, $(wildcard *.bin)) accept: $(wildcard *.bin) - rm $(wildcard ok/*.ok) + mkdir -p ok + rm -f $(wildcard ok/*.ok) echo $(foreach FILE,$^,"$(DESER) < $(FILE) > $(patsubst %.bin, ok/%.ok, $(FILE)) ;") \ | sh diff --git a/test/run-dfinity/ok/array-out-of-bounds.dvm-run.ok b/test/run-dfinity/ok/array-out-of-bounds.dvm.ok similarity index 100% rename from test/run-dfinity/ok/array-out-of-bounds.dvm-run.ok rename to test/run-dfinity/ok/array-out-of-bounds.dvm.ok diff --git a/test/run-dfinity/ok/async-loop-while.dvm-run.ok b/test/run-dfinity/ok/async-loop-while.dvm.ok similarity index 100% rename from test/run-dfinity/ok/async-loop-while.dvm-run.ok rename to test/run-dfinity/ok/async-loop-while.dvm.ok diff --git a/test/run-dfinity/ok/async-loop.dvm-run.ok b/test/run-dfinity/ok/async-loop.dvm.ok similarity index 100% rename from test/run-dfinity/ok/async-loop.dvm-run.ok rename to test/run-dfinity/ok/async-loop.dvm.ok diff --git a/test/run-dfinity/ok/async-new-obj.dvm-run.ok b/test/run-dfinity/ok/async-new-obj.dvm.ok similarity index 100% rename from test/run-dfinity/ok/async-new-obj.dvm-run.ok rename to test/run-dfinity/ok/async-new-obj.dvm.ok diff --git a/test/run-dfinity/ok/async-obj-mut.dvm-run.ok b/test/run-dfinity/ok/async-obj-mut.dvm.ok similarity index 100% rename from test/run-dfinity/ok/async-obj-mut.dvm-run.ok rename to test/run-dfinity/ok/async-obj-mut.dvm.ok diff --git a/test/run-dfinity/ok/async-while.dvm-run.ok b/test/run-dfinity/ok/async-while.dvm.ok similarity index 100% rename from test/run-dfinity/ok/async-while.dvm-run.ok rename to test/run-dfinity/ok/async-while.dvm.ok diff --git a/test/run-dfinity/ok/await.dvm-run.ok b/test/run-dfinity/ok/await.dvm.ok similarity index 100% rename from test/run-dfinity/ok/await.dvm-run.ok rename to test/run-dfinity/ok/await.dvm.ok diff --git a/test/run-dfinity/ok/block.dvm-run.ok b/test/run-dfinity/ok/block.dvm.ok similarity index 100% rename from test/run-dfinity/ok/block.dvm-run.ok rename to test/run-dfinity/ok/block.dvm.ok diff --git a/test/run-dfinity/ok/chat.dvm-run.ok b/test/run-dfinity/ok/chat.dvm.ok similarity index 100% rename from test/run-dfinity/ok/chat.dvm-run.ok rename to test/run-dfinity/ok/chat.dvm.ok diff --git a/test/run-dfinity/ok/chatpp.dvm-run.ok b/test/run-dfinity/ok/chatpp.dvm.ok similarity index 100% rename from test/run-dfinity/ok/chatpp.dvm-run.ok rename to test/run-dfinity/ok/chatpp.dvm.ok diff --git a/test/run-dfinity/ok/closure-params.dvm-run.ok b/test/run-dfinity/ok/closure-params.dvm.ok similarity index 100% rename from test/run-dfinity/ok/closure-params.dvm-run.ok rename to test/run-dfinity/ok/closure-params.dvm.ok diff --git a/test/run-dfinity/ok/counter-class.wasm.stderr.ok b/test/run-dfinity/ok/counter-class.comp.ok similarity index 100% rename from test/run-dfinity/ok/counter-class.wasm.stderr.ok rename to test/run-dfinity/ok/counter-class.comp.ok diff --git a/test/run-dfinity/ok/counter-class.dvm-run.ok b/test/run-dfinity/ok/counter-class.dvm.ok similarity index 100% rename from test/run-dfinity/ok/counter-class.dvm-run.ok rename to test/run-dfinity/ok/counter-class.dvm.ok diff --git a/test/run-dfinity/ok/counter.dvm-run.ok b/test/run-dfinity/ok/counter.dvm.ok similarity index 100% rename from test/run-dfinity/ok/counter.dvm-run.ok rename to test/run-dfinity/ok/counter.dvm.ok diff --git a/test/run-dfinity/ok/counter2.dvm-run.ok b/test/run-dfinity/ok/counter2.dvm.ok similarity index 100% rename from test/run-dfinity/ok/counter2.dvm-run.ok rename to test/run-dfinity/ok/counter2.dvm.ok diff --git a/test/run-dfinity/ok/data-params.idl.stderr.ok b/test/run-dfinity/ok/data-params.comp.ok similarity index 100% rename from test/run-dfinity/ok/data-params.idl.stderr.ok rename to test/run-dfinity/ok/data-params.comp.ok diff --git a/test/run-dfinity/ok/data-params.dvm-run.ok b/test/run-dfinity/ok/data-params.dvm.ok similarity index 100% rename from test/run-dfinity/ok/data-params.dvm-run.ok rename to test/run-dfinity/ok/data-params.dvm.ok diff --git a/test/run-dfinity/ok/data-params.wasm.stderr.ok b/test/run-dfinity/ok/data-params.wasm.stderr.ok deleted file mode 100644 index 4f513b4d81a..00000000000 --- a/test/run-dfinity/ok/data-params.wasm.stderr.ok +++ /dev/null @@ -1,4 +0,0 @@ -data-params.mo:59.30-59.40: warning, this pattern consuming type - ?Text -does not cover value - null diff --git a/test/run-dfinity/ok/fac.dvm-run.ok b/test/run-dfinity/ok/fac.dvm.ok similarity index 100% rename from test/run-dfinity/ok/fac.dvm-run.ok rename to test/run-dfinity/ok/fac.dvm.ok diff --git a/test/run-dfinity/ok/flatten-awaitables.idl.stderr.ok b/test/run-dfinity/ok/flatten-awaitables.comp.ok similarity index 100% rename from test/run-dfinity/ok/flatten-awaitables.idl.stderr.ok rename to test/run-dfinity/ok/flatten-awaitables.comp.ok diff --git a/test/run-dfinity/ok/flatten-awaitables.dvm-run.ok b/test/run-dfinity/ok/flatten-awaitables.dvm.ok similarity index 100% rename from test/run-dfinity/ok/flatten-awaitables.dvm-run.ok rename to test/run-dfinity/ok/flatten-awaitables.dvm.ok diff --git a/test/run-dfinity/ok/flatten-awaitables.wasm.stderr.ok b/test/run-dfinity/ok/flatten-awaitables.wasm.stderr.ok deleted file mode 100644 index 4734a23a649..00000000000 --- a/test/run-dfinity/ok/flatten-awaitables.wasm.stderr.ok +++ /dev/null @@ -1,120 +0,0 @@ -flatten-awaitables.mo:43.9-43.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:45.9-45.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:47.9-47.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) -flatten-awaitables.mo:52.9-52.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:54.9-54.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:56.9-56.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) -flatten-awaitables.mo:66.9-66.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:68.9-68.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:70.9-70.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) -flatten-awaitables.mo:75.9-75.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:77.9-77.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:79.9-79.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) -flatten-awaitables.mo:85.9-85.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:87.9-87.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:89.9-89.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) -flatten-awaitables.mo:94.9-94.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:96.9-96.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:98.9-98.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) -flatten-awaitables.mo:103.9-103.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:105.9-105.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:107.9-107.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) -flatten-awaitables.mo:112.9-112.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:114.9-114.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:116.9-116.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) diff --git a/test/run-dfinity/ok/for-await.dvm-run.ok b/test/run-dfinity/ok/for-await.dvm.ok similarity index 100% rename from test/run-dfinity/ok/for-await.dvm-run.ok rename to test/run-dfinity/ok/for-await.dvm.ok diff --git a/test/run-dfinity/ok/generic-tail-rec.dvm-run.ok b/test/run-dfinity/ok/generic-tail-rec.dvm.ok similarity index 100% rename from test/run-dfinity/ok/generic-tail-rec.dvm-run.ok rename to test/run-dfinity/ok/generic-tail-rec.dvm.ok diff --git a/test/run-dfinity/ok/hello-concat-world.dvm-run.ok b/test/run-dfinity/ok/hello-concat-world.dvm.ok similarity index 100% rename from test/run-dfinity/ok/hello-concat-world.dvm-run.ok rename to test/run-dfinity/ok/hello-concat-world.dvm.ok diff --git a/test/run-dfinity/ok/hello-world-async.dvm-run.ok b/test/run-dfinity/ok/hello-world-async.dvm.ok similarity index 100% rename from test/run-dfinity/ok/hello-world-async.dvm-run.ok rename to test/run-dfinity/ok/hello-world-async.dvm.ok diff --git a/test/run-dfinity/ok/hello-world-await.dvm-run.ok b/test/run-dfinity/ok/hello-world-await.dvm.ok similarity index 100% rename from test/run-dfinity/ok/hello-world-await.dvm-run.ok rename to test/run-dfinity/ok/hello-world-await.dvm.ok diff --git a/test/run-dfinity/ok/hello-world-message.dvm-run.ok b/test/run-dfinity/ok/hello-world-message.dvm.ok similarity index 100% rename from test/run-dfinity/ok/hello-world-message.dvm-run.ok rename to test/run-dfinity/ok/hello-world-message.dvm.ok diff --git a/test/run-dfinity/ok/hello-world-message2.dvm-run.ok b/test/run-dfinity/ok/hello-world-message2.dvm.ok similarity index 100% rename from test/run-dfinity/ok/hello-world-message2.dvm-run.ok rename to test/run-dfinity/ok/hello-world-message2.dvm.ok diff --git a/test/run-dfinity/ok/hello-world.dvm-run.ok b/test/run-dfinity/ok/hello-world.dvm.ok similarity index 100% rename from test/run-dfinity/ok/hello-world.dvm-run.ok rename to test/run-dfinity/ok/hello-world.dvm.ok diff --git a/test/run-dfinity/ok/hello-world2.dvm-run.ok b/test/run-dfinity/ok/hello-world2.dvm.ok similarity index 100% rename from test/run-dfinity/ok/hello-world2.dvm-run.ok rename to test/run-dfinity/ok/hello-world2.dvm.ok diff --git a/test/run-dfinity/ok/hello-world3.dvm-run.ok b/test/run-dfinity/ok/hello-world3.dvm.ok similarity index 100% rename from test/run-dfinity/ok/hello-world3.dvm-run.ok rename to test/run-dfinity/ok/hello-world3.dvm.ok diff --git a/test/run-dfinity/ok/indirect-counter.dvm-run.ok b/test/run-dfinity/ok/indirect-counter.dvm.ok similarity index 100% rename from test/run-dfinity/ok/indirect-counter.dvm-run.ok rename to test/run-dfinity/ok/indirect-counter.dvm.ok diff --git a/test/run-dfinity/ok/local-throw.dvm-run.ok b/test/run-dfinity/ok/local-throw.dvm.ok similarity index 100% rename from test/run-dfinity/ok/local-throw.dvm-run.ok rename to test/run-dfinity/ok/local-throw.dvm.ok diff --git a/test/run-dfinity/ok/nary-async.dvm-run.ok b/test/run-dfinity/ok/nary-async.dvm.ok similarity index 100% rename from test/run-dfinity/ok/nary-async.dvm-run.ok rename to test/run-dfinity/ok/nary-async.dvm.ok diff --git a/test/run-dfinity/ok/overflow.dvm-run.ok b/test/run-dfinity/ok/overflow.dvm.ok similarity index 100% rename from test/run-dfinity/ok/overflow.dvm-run.ok rename to test/run-dfinity/ok/overflow.dvm.ok diff --git a/test/run-dfinity/ok/query.dvm-run.ok b/test/run-dfinity/ok/query.dvm.ok similarity index 100% rename from test/run-dfinity/ok/query.dvm-run.ok rename to test/run-dfinity/ok/query.dvm.ok diff --git a/test/run-dfinity/ok/reference-params.dvm-run.ok b/test/run-dfinity/ok/reference-params.dvm.ok similarity index 100% rename from test/run-dfinity/ok/reference-params.dvm-run.ok rename to test/run-dfinity/ok/reference-params.dvm.ok diff --git a/test/run-dfinity/ok/selftail.dvm-run.ok b/test/run-dfinity/ok/selftail.dvm.ok similarity index 100% rename from test/run-dfinity/ok/selftail.dvm-run.ok rename to test/run-dfinity/ok/selftail.dvm.ok diff --git a/test/run-dfinity/ok/show.dvm-run.ok b/test/run-dfinity/ok/show.dvm.ok similarity index 100% rename from test/run-dfinity/ok/show.dvm-run.ok rename to test/run-dfinity/ok/show.dvm.ok diff --git a/test/run-dfinity/ok/simple-throw.dvm-run.ok b/test/run-dfinity/ok/simple-throw.dvm.ok similarity index 100% rename from test/run-dfinity/ok/simple-throw.dvm-run.ok rename to test/run-dfinity/ok/simple-throw.dvm.ok diff --git a/test/run-dfinity/ok/tailpositions.dvm-run.ok b/test/run-dfinity/ok/tailpositions.dvm.ok similarity index 100% rename from test/run-dfinity/ok/tailpositions.dvm-run.ok rename to test/run-dfinity/ok/tailpositions.dvm.ok diff --git a/test/run-dfinity/ok/text-iter.dvm-run.ok b/test/run-dfinity/ok/text-iter.dvm.ok similarity index 100% rename from test/run-dfinity/ok/text-iter.dvm-run.ok rename to test/run-dfinity/ok/text-iter.dvm.ok diff --git a/test/run-dfinity/ok/the-answer.dvm-run.ok b/test/run-dfinity/ok/the-answer.dvm.ok similarity index 100% rename from test/run-dfinity/ok/the-answer.dvm-run.ok rename to test/run-dfinity/ok/the-answer.dvm.ok diff --git a/test/run-drun/ok/idl-func.tc.ret.ok b/test/run-drun/ok/idl-func.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/idl-func.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-drun/ok/multiple-actors.wasm.stderr.ok b/test/run-drun/ok/multiple-actors.comp.ok similarity index 100% rename from test/run-drun/ok/multiple-actors.wasm.stderr.ok rename to test/run-drun/ok/multiple-actors.comp.ok diff --git a/test/run-drun/ok/multiple-actors.comp.ret.ok b/test/run-drun/ok/multiple-actors.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/multiple-actors.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-drun/ok/unsupported.tc.ret.ok b/test/run-drun/ok/unsupported.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/unsupported.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run.sh b/test/run.sh index 9cd4c6eff14..8f9945469b6 100755 --- a/test/run.sh +++ b/test/run.sh @@ -86,6 +86,29 @@ function normalize () { fi } +function run () { + # first argument: extension of the output file + # remaining argument: command line + # uses from scope: $out, $base, $diff_files + + local ext="$1" + shift + $ECHO -n " [$ext]" + "$@" >& $out/$base.$ext + local ret=$? + + if [ $ret != 0 ] + then echo "Return code $ret" >> $out/$base.$ext.ret + else rm -f $out/$base.$ext.ret + fi + diff_files="$diff_files $base.$ext.ret" + + normalize $out/$base.$ext + diff_files="$diff_files $base.$ext" + + return $ret +} + for file in "$@"; do if ! [ -r $file ] @@ -120,10 +143,10 @@ do [ -d $out ] || mkdir $out [ -d $ok ] || mkdir $ok - rm -f $out/$base.{tc,wasm,wasm.map,wasm-run,wasm.stderr,drun-run,filecheck,diff-ir,diff-low,stdout,stderr,linked.wat,did,did.tc,js.out} + rm -f $out/$base.* if [ $ACCEPT = yes ] then - rm -f $ok/$base.{tc,wasm,wasm.map,wasm-run,wasm.stderr,drun-run,filecheck,diff-ir,diff-low,stdout,stderr,linked.wat,did,did.tc,js.out}.ok + rm -f $ok/$base.* fi # First run all the steps, and remember what to diff @@ -132,52 +155,38 @@ do if [ ${file: -3} == ".mo" ] then # Typecheck - $ECHO -n " [tc]" - $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS --check $base.mo > $out/$base.tc 2>&1 + run tc $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS --check $base.mo tc_succeeded=$? - normalize $out/$base.tc - diff_files="$diff_files $base.tc" if [ "$tc_succeeded" -eq 0 ] then if [ $IDL = 'yes' ] then - $ECHO -n " [idl]" - $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS --idl $base.mo -o $out/$base.did 2> $out/$base.idl.stderr + run idl $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS --idl $base.mo -o $out/$base.did idl_succeeded=$? + normalize $out/$base.did - normalize $out/$base.idl.stderr - diff_files="$diff_files $base.did $base.idl.stderr" + diff_files="$diff_files $base.did" + if [ "$idl_succeeded" -eq 0 ] then - $ECHO -n " [didc]" - $DIDC --check $out/$base.did > $out/$base.did.tc 2>&1 - diff_files="$diff_files $base.did.tc" + run didc $DIDC --check $out/$base.did fi else if [ "$SKIP_RUNNING" != yes ] then # Interpret - $ECHO -n " [run]" - $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS -r $base.mo > $out/$base.run 2>&1 - normalize $out/$base.run - diff_files="$diff_files $base.run" + run run $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS -r $base.mo # Interpret IR without lowering - $ECHO -n " [run-ir]" - $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS -r -iR -no-async -no-await $base.mo > $out/$base.run-ir 2>&1 - normalize $out/$base.run-ir - diff_files="$diff_files $base.run-ir" + run run-ir $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS -r -iR -no-async -no-await $base.mo # Diff interpretations without/with lowering diff -u -N --label "$base.run" $out/$base.run --label "$base.run-ir" $out/$base.run-ir > $out/$base.diff-ir diff_files="$diff_files $base.diff-ir" # Interpret IR with lowering - $ECHO -n " [run-low]" - $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS -r -iR $base.mo > $out/$base.run-low 2>&1 - normalize $out/$base.run-low - diff_files="$diff_files $base.run-low" + run run-low $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS -r -iR $base.mo # Diff interpretations without/with lowering diff -u -N --label "$base.run" $out/$base.run --label "$base.run-low" $out/$base.run-low > $out/$base.diff-low @@ -186,10 +195,7 @@ do fi # Compile - $ECHO -n " [wasm]" - $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS --map -c $base.mo -o $out/$base.wasm 2> $out/$base.wasm.stderr - normalize $out/$base.wasm.stderr - diff_files="$diff_files $base.wasm.stderr" + run comp $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS --map -c $base.mo -o $out/$base.wasm # Check filecheck if [ "$SKIP_RUNNING" != yes ] @@ -210,21 +216,12 @@ do then if [ $API = ancient ] then - $ECHO -n " [dvm]" - $DVM_WRAPPER $out/$base.wasm $base.mo > $out/$base.dvm-run 2>&1 - normalize $out/$base.dvm-run - diff_files="$diff_files $base.dvm-run" + run dvm $DVM_WRAPPER $out/$base.wasm $base.mo elif [ $API = ic ] then - $ECHO -n " [drun]" - $DRUN_WRAPPER $out/$base.wasm $base.mo > $out/$base.drun-run 2>&1 - normalize $out/$base.drun-run - diff_files="$diff_files $base.drun-run" + run drun-run $DRUN_WRAPPER $out/$base.wasm $base.mo else - $ECHO -n " [wasm-run]" - $WASM $out/$base.wasm > $out/$base.wasm-run 2>&1 - normalize $out/$base.wasm-run - diff_files="$diff_files $base.wasm-run" + run wasm-run $WASM $out/$base.wasm fi fi fi @@ -249,9 +246,8 @@ do if [ -e $out/$base.linked.wasm ] then - $ECHO -n " [wat]" - wasm2wat $out/$base.linked.wasm -o $out/$base.linked.wat 2> $out/$base.linked.wat.stderr - diff_files="$diff_files $base.linked.wat $base.linked.wat.stderr" + run wasm2wat wasm2wat $out/$base.linked.wasm -o $out/$base.linked.wat + diff_files="$diff_files $base.linked.wat" fi else diff --git a/test/run/ok/TRAP-write-before-init.tc.ret.ok b/test/run/ok/TRAP-write-before-init.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run/ok/TRAP-write-before-init.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run/ok/array-bounds.run.ret.ok b/test/run/ok/array-bounds.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run/ok/array-bounds.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run/ok/array-bounds.wasm-run.ret.ok b/test/run/ok/array-bounds.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run/ok/array-bounds.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run/ok/assertFalse.run.ret.ok b/test/run/ok/assertFalse.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run/ok/assertFalse.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run/ok/assertFalse.wasm-run.ret.ok b/test/run/ok/assertFalse.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run/ok/assertFalse.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run/ok/conversions.wasm-run.ret.ok b/test/run/ok/conversions.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run/ok/conversions.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run/ok/coverage.idl.stderr.ok b/test/run/ok/coverage.comp.ok similarity index 100% rename from test/run/ok/coverage.idl.stderr.ok rename to test/run/ok/coverage.comp.ok diff --git a/test/run/ok/coverage.wasm.stderr.ok b/test/run/ok/coverage.wasm.stderr.ok deleted file mode 100644 index 6cd2a586f70..00000000000 --- a/test/run/ok/coverage.wasm.stderr.ok +++ /dev/null @@ -1,101 +0,0 @@ -coverage.mo:5.13-5.14: warning, this pattern is never matched -coverage.mo:7.13-7.14: warning, this pattern is never matched -coverage.mo:8.13-8.14: warning, this pattern is never matched -coverage.mo:16.16-16.17: warning, this pattern is never matched -coverage.mo:18.16-18.17: warning, this pattern is never matched -coverage.mo:19.17-19.18: warning, this pattern is never matched -coverage.mo:24.25-24.34: warning, this case is never reached -coverage.mo:27.25-27.34: warning, this case is never reached -coverage.mo:28.25-28.34: warning, this case is never reached -coverage.mo:29.25-29.34: warning, this case is never reached -coverage.mo:30.25-30.34: warning, this case is never reached -coverage.mo:31.25-31.34: warning, this case is never reached -coverage.mo:32.43-32.44: warning, this pattern is never matched -coverage.mo:33.35-33.49: warning, this case is never reached -coverage.mo:34.42-34.51: warning, this case is never reached -coverage.mo:37.51-37.73: warning, this case is never reached -coverage.mo:38.39-38.54: warning, this case is never reached -coverage.mo:39.56-39.65: warning, this case is never reached -coverage.mo:40.49-40.58: warning, this case is never reached -coverage.mo:46.58-46.72: warning, this case is never reached -coverage.mo:61.22-61.31: warning, this case is never reached -coverage.mo:62.28-62.37: warning, this case is never reached -coverage.mo:63.49-63.50: warning, this pattern is never matched -coverage.mo:64.48-64.49: warning, this pattern is never matched -coverage.mo:65.41-65.42: warning, this pattern is never matched -coverage.mo:66.40-66.41: warning, this pattern is never matched -coverage.mo:77.5-77.55: warning, this case is never reached -coverage.mo:109.3-109.52: warning, this case is never reached -coverage.mo:4.7-4.8: warning, this pattern consuming type - Nat -does not cover value - 0 or 1 or _ -coverage.mo:5.7-5.15: warning, this pattern consuming type - Nat -does not cover value - 0 or 1 or _ -coverage.mo:9.7-9.9: warning, this pattern consuming type - ?Nat -does not cover value - null -coverage.mo:10.7-10.9: warning, this pattern consuming type - ?Nat -does not cover value - null -coverage.mo:11.7-11.9: warning, this pattern consuming type - ?Nat -does not cover value - ?(0 or 1 or _) or - null -coverage.mo:15.10-15.13: warning, this pattern consuming type - Nat -does not cover value - 0 or 1 or _ -coverage.mo:16.10-16.18: warning, this pattern consuming type - Nat -does not cover value - 0 or 1 or _ -coverage.mo:23.3-23.25: warning, the cases in this switch over type - Nat -do not cover value - 0 or 1 or _ -coverage.mo:24.3-24.36: warning, the cases in this switch over type - Nat -do not cover value - 0 or 1 or _ -coverage.mo:32.3-32.50: warning, the cases in this switch over type - Nat -do not cover value - 0 or 1 or _ -coverage.mo:35.3-35.51: warning, the cases in this switch over type - (Nat, Nat) -do not cover value - (1 or 2 or _, 1 or 2 or _) -coverage.mo:41.3-41.61: warning, the cases in this switch over type - {a : Nat; b : Nat} -do not cover value - {a = 1 or 2 or _; b = 1 or 2 or _) -coverage.mo:45.3-45.74: warning, the cases in this switch over type - {#a : Nat; #b : Nat} -do not cover value - #b(0 or 1 or _) -coverage.mo:47.3-47.58: warning, the cases in this switch over type - {#a : Nat; #b : Nat} -do not cover value - #b(_) -coverage.mo:48.3-48.58: warning, the cases in this switch over type - {#a : Nat; #b : Nat} -do not cover value - #a(_) -coverage.mo:49.3-49.62: warning, the cases in this switch over type - {#a : Nat; #b : Nat; #c} -do not cover value - #a(_) or #c -coverage.mo:50.3-50.42: warning, the cases in this switch over type - {#a : Nat; #b : Nat} -do not cover value - _ -coverage.mo:74.3-78.4: warning, the cases in this switch over type - {#branch : (Tree, Tree); #leaf : Int} -do not cover value - #leaf(0 or 1 or _) diff --git a/test/run/ok/idlHash.wasm-run.ret.ok b/test/run/ok/idlHash.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run/ok/idlHash.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run/ok/issue442.idl.stderr.ok b/test/run/ok/issue442.comp.ok similarity index 100% rename from test/run/ok/issue442.idl.stderr.ok rename to test/run/ok/issue442.comp.ok diff --git a/test/run/ok/issue442.wasm.stderr.ok b/test/run/ok/issue442.wasm.stderr.ok deleted file mode 100644 index 2ec06928058..00000000000 --- a/test/run/ok/issue442.wasm.stderr.ok +++ /dev/null @@ -1,6 +0,0 @@ -issue442.mo:1.11-1.24: warning, this array has type [Any] because elements have inconsistent types -issue442.mo:2.11-2.29: warning, this if has type Any because branches have inconsistent types, -true produces - Nat -false produces - Text diff --git a/test/run/ok/large-tuple.idl.stderr.ok b/test/run/ok/large-tuple.comp.ok similarity index 100% rename from test/run/ok/large-tuple.idl.stderr.ok rename to test/run/ok/large-tuple.comp.ok diff --git a/test/run/ok/large-tuple.wasm.stderr.ok b/test/run/ok/large-tuple.wasm.stderr.ok deleted file mode 100644 index c20cc4ea334..00000000000 --- a/test/run/ok/large-tuple.wasm.stderr.ok +++ /dev/null @@ -1,23 +0,0 @@ -large-tuple.mo:4.21-4.73: warning, this pattern consuming type - (Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat) -does not cover value - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0 or 1 or _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 0 or 1 or _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 0 or 1 or _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0 or 1 or _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0 or 1 or _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0 or 1 or _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0 or 1 or _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0 or 1 or _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0 or 1 or _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0 or 1 or _, _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or - (1, 2, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or - (1, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or - (0 or 2 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) diff --git a/test/run/ok/numeric-ops.wasm.stderr.ok b/test/run/ok/numeric-ops.comp.ok similarity index 100% rename from test/run/ok/numeric-ops.wasm.stderr.ok rename to test/run/ok/numeric-ops.comp.ok diff --git a/test/run/ok/objects1.idl.stderr.ok b/test/run/ok/objects1.comp.ok similarity index 100% rename from test/run/ok/objects1.idl.stderr.ok rename to test/run/ok/objects1.comp.ok diff --git a/test/run/ok/objects1.wasm.stderr.ok b/test/run/ok/objects1.wasm.stderr.ok deleted file mode 100644 index 53be7fa8068..00000000000 --- a/test/run/ok/objects1.wasm.stderr.ok +++ /dev/null @@ -1,10 +0,0 @@ -objects1.mo:22.3-22.26: warning, this case is never reached -objects1.mo:23.3-23.14: warning, this case is never reached -objects1.mo:32.23-35.2: warning, the cases in this switch over type - {a : Int; b : Nat} -do not cover value - {a = 0 or 1 or _; b = 0 or 1 or _) -objects1.mo:43.21-45.2: warning, the cases in this switch over type - (Nat, Int, {c : Char; d : Text}) -do not cover value - (_, 0 or 1 or _, _) diff --git a/test/run/ok/overflow.run.ret.ok b/test/run/ok/overflow.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run/ok/overflow.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run/ok/overflow.wasm-run.ret.ok b/test/run/ok/overflow.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run/ok/overflow.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run/ok/pat-subtyping.wasm.stderr.ok b/test/run/ok/pat-subtyping.comp.ok similarity index 100% rename from test/run/ok/pat-subtyping.wasm.stderr.ok rename to test/run/ok/pat-subtyping.comp.ok diff --git a/test/run/ok/pat-subtyping.idl.stderr.ok b/test/run/ok/pat-subtyping.idl.stderr.ok deleted file mode 100644 index 76a04dc98af..00000000000 --- a/test/run/ok/pat-subtyping.idl.stderr.ok +++ /dev/null @@ -1,41 +0,0 @@ -pat-subtyping.mo:6.3-6.12: warning, this case is never reached -pat-subtyping.mo:7.3-7.15: warning, this case is never reached -pat-subtyping.mo:10.3-10.20: warning, this case is never reached -pat-subtyping.mo:11.3-11.20: warning, this case is never reached -pat-subtyping.mo:18.3-18.28: warning, this case is never reached -pat-subtyping.mo:25.3-25.28: warning, this case is never reached -pat-subtyping.mo:32.3-32.42: warning, this case is never reached -pat-subtyping.mo:38.3-38.47: warning, this case is never reached -pat-subtyping.mo:44.3-44.44: warning, this case is never reached -pat-subtyping.mo:51.3-51.47: warning, this case is never reached -pat-subtyping.mo:58.3-58.44: warning, this case is never reached -pat-subtyping.mo:65.3-65.58: warning, this case is never reached -pat-subtyping.mo:71.3-71.63: warning, this case is never reached -pat-subtyping.mo:77.3-77.60: warning, this case is never reached -pat-subtyping.mo:84.3-84.71: warning, this case is never reached -pat-subtyping.mo:91.3-91.60: warning, this case is never reached -pat-subtyping.mo:97.3-97.49: warning, this case is never reached -pat-subtyping.mo:103.3-103.51: warning, this case is never reached -pat-subtyping.mo:109.3-109.42: warning, this case is never reached -pat-subtyping.mo:115.3-115.36: warning, this case is never reached -pat-subtyping.mo:119.3-119.17: warning, this case is never reached -pat-subtyping.mo:120.3-120.16: warning, this case is never reached -pat-subtyping.mo:130.3-130.33: warning, this case is never reached -pat-subtyping.mo:137.3-137.31: warning, this case is never reached -pat-subtyping.mo:138.3-138.15: warning, this case is never reached -pat-subtyping.mo:145.3-145.30: warning, this case is never reached -pat-subtyping.mo:156.3-156.31: warning, this case is never reached -pat-subtyping.mo:163.3-163.30: warning, this case is never reached -pat-subtyping.mo:171.3-171.34: warning, this case is never reached -pat-subtyping.mo:172.3-172.32: warning, this case is never reached -pat-subtyping.mo:182.3-182.49: warning, this case is never reached -pat-subtyping.mo:185.3-185.31: warning, this case is never reached -pat-subtyping.mo:188.3-188.39: warning, this case is never reached -pat-subtyping.mo:208.3-208.15: warning, this case is never reached -pat-subtyping.mo:209.3-209.12: warning, this case is never reached -pat-subtyping.mo:210.3-210.14: warning, this case is never reached -pat-subtyping.mo:211.3-211.13: warning, this case is never reached -pat-subtyping.mo:212.3-212.13: warning, this case is never reached -pat-subtyping.mo:213.3-213.13: warning, this case is never reached -pat-subtyping.mo:214.3-214.15: warning, this case is never reached -pat-subtyping.mo:215.3-215.15: warning, this case is never reached diff --git a/test/run/ok/relational-ops.wasm.stderr.ok b/test/run/ok/relational-ops.comp.ok similarity index 100% rename from test/run/ok/relational-ops.wasm.stderr.ok rename to test/run/ok/relational-ops.comp.ok diff --git a/test/run/ok/switch.idl.stderr.ok b/test/run/ok/switch.comp.ok similarity index 100% rename from test/run/ok/switch.idl.stderr.ok rename to test/run/ok/switch.comp.ok diff --git a/test/run/ok/switch.wasm.stderr.ok b/test/run/ok/switch.wasm.stderr.ok deleted file mode 100644 index d8896858554..00000000000 --- a/test/run/ok/switch.wasm.stderr.ok +++ /dev/null @@ -1,17 +0,0 @@ -switch.mo:86.29-86.30: warning, this pattern is never matched -switch.mo:75.11-77.2: warning, the cases in this switch over type - ?Int -do not cover value - ?(_) -switch.mo:81.3-81.14: warning, the cases in this switch over type - Nat -do not cover value - _ -switch.mo:92.11-94.2: warning, the cases in this switch over type - ?Nat -do not cover value - null -switch.mo:97.11-99.2: warning, the cases in this switch over type - ?Nat -do not cover value - ?(_) diff --git a/test/run/ok/type-inference.wasm.stderr.ok b/test/run/ok/type-inference.comp.ok similarity index 100% rename from test/run/ok/type-inference.wasm.stderr.ok rename to test/run/ok/type-inference.comp.ok diff --git a/test/run/ok/type-inference.idl.stderr.ok b/test/run/ok/type-inference.idl.stderr.ok deleted file mode 100644 index a1077f043f0..00000000000 --- a/test/run/ok/type-inference.idl.stderr.ok +++ /dev/null @@ -1,37 +0,0 @@ -type-inference.mo:3.9-3.28: warning, this if has type Any because branches have inconsistent types, -true produces - Bool -false produces - Nat -type-inference.mo:4.9-4.34: warning, this if has type Any because branches have inconsistent types, -true produces - Bool -false produces - [var Nat] -type-inference.mo:5.9-5.27: warning, this if has type Any because branches have inconsistent types, -true produces - Nat -false produces - Float -type-inference.mo:6.9-6.29: warning, this if has type Any because branches have inconsistent types, -true produces - () -false produces - {} -type-inference.mo:11.33-11.41: warning, the switch has type Any because branches have inconsistent types, -this case produces type - Bool -the previous produce type - Nat -type-inference.mo:12.33-12.47: warning, the switch has type Any because branches have inconsistent types, -this case produces type - Bool -the previous produce type - [var Nat] -type-inference.mo:13.43-13.56: warning, the switch has type Any because branches have inconsistent types, -this case produces type - Int -the previous produce type - Text -type-inference.mo:19.9-19.18: warning, this array has type [Any] because elements have inconsistent types -type-inference.mo:20.9-20.24: warning, this array has type [Any] because elements have inconsistent types diff --git a/test/trap/ok/addInt16-lower.run.ret.ok b/test/trap/ok/addInt16-lower.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/addInt16-lower.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/addInt16-lower.wasm-run.ret.ok b/test/trap/ok/addInt16-lower.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/addInt16-lower.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/addInt16-upper.run.ret.ok b/test/trap/ok/addInt16-upper.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/addInt16-upper.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/addInt16-upper.wasm-run.ret.ok b/test/trap/ok/addInt16-upper.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/addInt16-upper.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/addInt32-lower.run.ret.ok b/test/trap/ok/addInt32-lower.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/addInt32-lower.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/addInt32-lower.wasm-run.ret.ok b/test/trap/ok/addInt32-lower.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/addInt32-lower.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/addInt32-upper.run.ret.ok b/test/trap/ok/addInt32-upper.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/addInt32-upper.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/addInt32-upper.wasm-run.ret.ok b/test/trap/ok/addInt32-upper.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/addInt32-upper.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/addInt64-lower.run.ret.ok b/test/trap/ok/addInt64-lower.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/addInt64-lower.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/addInt64-lower.wasm-run.ret.ok b/test/trap/ok/addInt64-lower.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/addInt64-lower.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/addInt64-upper.run.ret.ok b/test/trap/ok/addInt64-upper.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/addInt64-upper.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/addInt64-upper.wasm-run.ret.ok b/test/trap/ok/addInt64-upper.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/addInt64-upper.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/addInt8-lower.run.ret.ok b/test/trap/ok/addInt8-lower.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/addInt8-lower.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/addInt8-lower.wasm-run.ret.ok b/test/trap/ok/addInt8-lower.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/addInt8-lower.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/addInt8-upper.run.ret.ok b/test/trap/ok/addInt8-upper.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/addInt8-upper.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/addInt8-upper.wasm-run.ret.ok b/test/trap/ok/addInt8-upper.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/addInt8-upper.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/addNat16.run.ret.ok b/test/trap/ok/addNat16.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/addNat16.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/addNat16.wasm-run.ret.ok b/test/trap/ok/addNat16.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/addNat16.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/addNat32.run.ret.ok b/test/trap/ok/addNat32.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/addNat32.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/addNat32.wasm-run.ret.ok b/test/trap/ok/addNat32.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/addNat32.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/addNat64.run.ret.ok b/test/trap/ok/addNat64.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/addNat64.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/addNat64.wasm-run.ret.ok b/test/trap/ok/addNat64.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/addNat64.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/addNat8.run.ret.ok b/test/trap/ok/addNat8.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/addNat8.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/addNat8.wasm-run.ret.ok b/test/trap/ok/addNat8.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/addNat8.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/divInt16.run.ret.ok b/test/trap/ok/divInt16.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/divInt16.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/divInt16.wasm-run.ret.ok b/test/trap/ok/divInt16.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/divInt16.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/divInt32.run.ret.ok b/test/trap/ok/divInt32.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/divInt32.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/divInt32.wasm-run.ret.ok b/test/trap/ok/divInt32.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/divInt32.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/divInt64.run.ret.ok b/test/trap/ok/divInt64.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/divInt64.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/divInt64.wasm-run.ret.ok b/test/trap/ok/divInt64.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/divInt64.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/divInt8.run.ret.ok b/test/trap/ok/divInt8.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/divInt8.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/divInt8.wasm-run.ret.ok b/test/trap/ok/divInt8.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/divInt8.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/mulInt16-lower.run.ret.ok b/test/trap/ok/mulInt16-lower.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/mulInt16-lower.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/mulInt16-lower.wasm-run.ret.ok b/test/trap/ok/mulInt16-lower.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/mulInt16-lower.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/mulInt16-upper.run.ret.ok b/test/trap/ok/mulInt16-upper.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/mulInt16-upper.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/mulInt16-upper.wasm-run.ret.ok b/test/trap/ok/mulInt16-upper.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/mulInt16-upper.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/mulInt32-lower.run.ret.ok b/test/trap/ok/mulInt32-lower.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/mulInt32-lower.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/mulInt32-lower.wasm-run.ret.ok b/test/trap/ok/mulInt32-lower.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/mulInt32-lower.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/mulInt32-upper.run.ret.ok b/test/trap/ok/mulInt32-upper.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/mulInt32-upper.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/mulInt32-upper.wasm-run.ret.ok b/test/trap/ok/mulInt32-upper.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/mulInt32-upper.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/mulInt64-lower.run.ret.ok b/test/trap/ok/mulInt64-lower.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/mulInt64-lower.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/mulInt64-lower.wasm-run.ret.ok b/test/trap/ok/mulInt64-lower.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/mulInt64-lower.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/mulInt64-upper.run.ret.ok b/test/trap/ok/mulInt64-upper.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/mulInt64-upper.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/mulInt64-upper.wasm-run.ret.ok b/test/trap/ok/mulInt64-upper.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/mulInt64-upper.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/mulInt8-lower.run.ret.ok b/test/trap/ok/mulInt8-lower.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/mulInt8-lower.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/mulInt8-lower.wasm-run.ret.ok b/test/trap/ok/mulInt8-lower.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/mulInt8-lower.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/mulInt8-upper.run.ret.ok b/test/trap/ok/mulInt8-upper.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/mulInt8-upper.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/mulInt8-upper.wasm-run.ret.ok b/test/trap/ok/mulInt8-upper.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/mulInt8-upper.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/mulNat16.run.ret.ok b/test/trap/ok/mulNat16.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/mulNat16.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/mulNat16.wasm-run.ret.ok b/test/trap/ok/mulNat16.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/mulNat16.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/mulNat32.run.ret.ok b/test/trap/ok/mulNat32.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/mulNat32.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/mulNat32.wasm-run.ret.ok b/test/trap/ok/mulNat32.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/mulNat32.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/mulNat64.run.ret.ok b/test/trap/ok/mulNat64.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/mulNat64.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/mulNat64.wasm-run.ret.ok b/test/trap/ok/mulNat64.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/mulNat64.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/mulNat8.run.ret.ok b/test/trap/ok/mulNat8.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/mulNat8.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/mulNat8.wasm-run.ret.ok b/test/trap/ok/mulNat8.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/mulNat8.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/outrange-int16-lower.run.ret.ok b/test/trap/ok/outrange-int16-lower.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/outrange-int16-lower.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/outrange-int16-lower.wasm-run.ret.ok b/test/trap/ok/outrange-int16-lower.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/outrange-int16-lower.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/outrange-int16-negation.run.ret.ok b/test/trap/ok/outrange-int16-negation.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/outrange-int16-negation.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/outrange-int16-negation.wasm-run.ret.ok b/test/trap/ok/outrange-int16-negation.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/outrange-int16-negation.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/outrange-int16-upper.run.ret.ok b/test/trap/ok/outrange-int16-upper.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/outrange-int16-upper.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/outrange-int16-upper.wasm-run.ret.ok b/test/trap/ok/outrange-int16-upper.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/outrange-int16-upper.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/outrange-int32-lower.run.ret.ok b/test/trap/ok/outrange-int32-lower.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/outrange-int32-lower.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/outrange-int32-lower.wasm-run.ret.ok b/test/trap/ok/outrange-int32-lower.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/outrange-int32-lower.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/outrange-int32-negation.run.ret.ok b/test/trap/ok/outrange-int32-negation.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/outrange-int32-negation.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/outrange-int32-negation.wasm-run.ret.ok b/test/trap/ok/outrange-int32-negation.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/outrange-int32-negation.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/outrange-int32-upper.run.ret.ok b/test/trap/ok/outrange-int32-upper.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/outrange-int32-upper.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/outrange-int32-upper.wasm-run.ret.ok b/test/trap/ok/outrange-int32-upper.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/outrange-int32-upper.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/outrange-int64-lower.run.ret.ok b/test/trap/ok/outrange-int64-lower.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/outrange-int64-lower.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/outrange-int64-lower.wasm-run.ret.ok b/test/trap/ok/outrange-int64-lower.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/outrange-int64-lower.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/outrange-int64-negation.run.ret.ok b/test/trap/ok/outrange-int64-negation.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/outrange-int64-negation.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/outrange-int64-negation.wasm-run.ret.ok b/test/trap/ok/outrange-int64-negation.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/outrange-int64-negation.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/outrange-int64-upper.run.ret.ok b/test/trap/ok/outrange-int64-upper.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/outrange-int64-upper.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/outrange-int64-upper.wasm-run.ret.ok b/test/trap/ok/outrange-int64-upper.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/outrange-int64-upper.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/outrange-int8-lower.run.ret.ok b/test/trap/ok/outrange-int8-lower.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/outrange-int8-lower.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/outrange-int8-lower.wasm-run.ret.ok b/test/trap/ok/outrange-int8-lower.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/outrange-int8-lower.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/outrange-int8-negation.run.ret.ok b/test/trap/ok/outrange-int8-negation.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/outrange-int8-negation.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/outrange-int8-negation.wasm-run.ret.ok b/test/trap/ok/outrange-int8-negation.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/outrange-int8-negation.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/outrange-int8-upper.run.ret.ok b/test/trap/ok/outrange-int8-upper.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/outrange-int8-upper.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/outrange-int8-upper.wasm-run.ret.ok b/test/trap/ok/outrange-int8-upper.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/outrange-int8-upper.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/outrange-nat16.run.ret.ok b/test/trap/ok/outrange-nat16.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/outrange-nat16.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/outrange-nat16.wasm-run.ret.ok b/test/trap/ok/outrange-nat16.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/outrange-nat16.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/outrange-nat32.run.ret.ok b/test/trap/ok/outrange-nat32.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/outrange-nat32.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/outrange-nat32.wasm-run.ret.ok b/test/trap/ok/outrange-nat32.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/outrange-nat32.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/outrange-nat64.run.ret.ok b/test/trap/ok/outrange-nat64.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/outrange-nat64.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/outrange-nat64.wasm-run.ret.ok b/test/trap/ok/outrange-nat64.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/outrange-nat64.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/outrange-nat8.run.ret.ok b/test/trap/ok/outrange-nat8.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/outrange-nat8.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/outrange-nat8.wasm-run.ret.ok b/test/trap/ok/outrange-nat8.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/outrange-nat8.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/powInt32-lower.run.ret.ok b/test/trap/ok/powInt32-lower.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/powInt32-lower.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/powInt32-lower.wasm-run.ret.ok b/test/trap/ok/powInt32-lower.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/powInt32-lower.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/powInt32-raise-neg.run.ret.ok b/test/trap/ok/powInt32-raise-neg.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/powInt32-raise-neg.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/powInt32-raise-neg.wasm-run.ret.ok b/test/trap/ok/powInt32-raise-neg.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/powInt32-raise-neg.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/powInt32-upper.run.ret.ok b/test/trap/ok/powInt32-upper.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/powInt32-upper.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/powInt32-upper.wasm-run.ret.ok b/test/trap/ok/powInt32-upper.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/powInt32-upper.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/powInt64-lower-fast.run.ret.ok b/test/trap/ok/powInt64-lower-fast.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/powInt64-lower-fast.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/powInt64-lower-fast.wasm-run.ret.ok b/test/trap/ok/powInt64-lower-fast.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/powInt64-lower-fast.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/powInt64-lower-slow.run.ret.ok b/test/trap/ok/powInt64-lower-slow.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/powInt64-lower-slow.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/powInt64-lower-slow.wasm-run.ret.ok b/test/trap/ok/powInt64-lower-slow.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/powInt64-lower-slow.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/powInt64-raise-neg.run.ret.ok b/test/trap/ok/powInt64-raise-neg.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/powInt64-raise-neg.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/powInt64-raise-neg.wasm-run.ret.ok b/test/trap/ok/powInt64-raise-neg.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/powInt64-raise-neg.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/powInt64-upper-fast.run.ret.ok b/test/trap/ok/powInt64-upper-fast.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/powInt64-upper-fast.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/powInt64-upper-fast.wasm-run.ret.ok b/test/trap/ok/powInt64-upper-fast.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/powInt64-upper-fast.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/powInt64-upper-slow.run.ret.ok b/test/trap/ok/powInt64-upper-slow.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/powInt64-upper-slow.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/powInt64-upper-slow.wasm-run.ret.ok b/test/trap/ok/powInt64-upper-slow.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/powInt64-upper-slow.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/powInt8-lower.run.ret.ok b/test/trap/ok/powInt8-lower.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/powInt8-lower.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/powInt8-lower.wasm-run.ret.ok b/test/trap/ok/powInt8-lower.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/powInt8-lower.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/powInt8-raise-neg.run.ret.ok b/test/trap/ok/powInt8-raise-neg.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/powInt8-raise-neg.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/powInt8-raise-neg.wasm-run.ret.ok b/test/trap/ok/powInt8-raise-neg.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/powInt8-raise-neg.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/powInt8-upper.run.ret.ok b/test/trap/ok/powInt8-upper.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/powInt8-upper.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/powInt8-upper.wasm-run.ret.ok b/test/trap/ok/powInt8-upper.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/powInt8-upper.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/powNat16.run.ret.ok b/test/trap/ok/powNat16.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/powNat16.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/powNat16.wasm-run.ret.ok b/test/trap/ok/powNat16.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/powNat16.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/powNat32.run.ret.ok b/test/trap/ok/powNat32.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/powNat32.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/powNat32.wasm-run.ret.ok b/test/trap/ok/powNat32.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/powNat32.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/powNat64.run.ret.ok b/test/trap/ok/powNat64.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/powNat64.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/powNat64.wasm-run.ret.ok b/test/trap/ok/powNat64.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/powNat64.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/powNat8.run.ret.ok b/test/trap/ok/powNat8.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/powNat8.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/powNat8.wasm-run.ret.ok b/test/trap/ok/powNat8.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/powNat8.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/subInt16-lower.run.ret.ok b/test/trap/ok/subInt16-lower.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/subInt16-lower.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/subInt16-lower.wasm-run.ret.ok b/test/trap/ok/subInt16-lower.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/subInt16-lower.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/subInt16-upper.run.ret.ok b/test/trap/ok/subInt16-upper.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/subInt16-upper.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/subInt16-upper.wasm-run.ret.ok b/test/trap/ok/subInt16-upper.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/subInt16-upper.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/subInt32-lower.run.ret.ok b/test/trap/ok/subInt32-lower.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/subInt32-lower.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/subInt32-lower.wasm-run.ret.ok b/test/trap/ok/subInt32-lower.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/subInt32-lower.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/subInt32-upper.run.ret.ok b/test/trap/ok/subInt32-upper.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/subInt32-upper.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/subInt32-upper.wasm-run.ret.ok b/test/trap/ok/subInt32-upper.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/subInt32-upper.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/subInt64-lower.run.ret.ok b/test/trap/ok/subInt64-lower.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/subInt64-lower.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/subInt64-lower.wasm-run.ret.ok b/test/trap/ok/subInt64-lower.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/subInt64-lower.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/subInt64-upper.run.ret.ok b/test/trap/ok/subInt64-upper.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/subInt64-upper.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/subInt64-upper.wasm-run.ret.ok b/test/trap/ok/subInt64-upper.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/subInt64-upper.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/subInt8-lower.run.ret.ok b/test/trap/ok/subInt8-lower.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/subInt8-lower.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/subInt8-lower.wasm-run.ret.ok b/test/trap/ok/subInt8-lower.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/subInt8-lower.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/subInt8-upper.run.ret.ok b/test/trap/ok/subInt8-upper.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/subInt8-upper.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/subInt8-upper.wasm-run.ret.ok b/test/trap/ok/subInt8-upper.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/subInt8-upper.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/subNat16.run.ret.ok b/test/trap/ok/subNat16.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/subNat16.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/subNat16.wasm-run.ret.ok b/test/trap/ok/subNat16.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/subNat16.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/subNat32.run.ret.ok b/test/trap/ok/subNat32.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/subNat32.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/subNat32.wasm-run.ret.ok b/test/trap/ok/subNat32.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/subNat32.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/subNat64-slow.run.ret.ok b/test/trap/ok/subNat64-slow.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/subNat64-slow.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/subNat64-slow.wasm-run.ret.ok b/test/trap/ok/subNat64-slow.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/subNat64-slow.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/subNat64.run.ret.ok b/test/trap/ok/subNat64.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/subNat64.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/subNat64.wasm-run.ret.ok b/test/trap/ok/subNat64.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/subNat64.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/subNat8.run.ret.ok b/test/trap/ok/subNat8.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/subNat8.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/trap/ok/subNat8.wasm-run.ret.ok b/test/trap/ok/subNat8.wasm-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/trap/ok/subNat8.wasm-run.ret.ok @@ -0,0 +1 @@ +Return code 1 From a9eaa4e72a8279544e0ab813688b5ad677983bdd Mon Sep 17 00:00:00 2001 From: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> Date: Tue, 5 Nov 2019 12:37:11 +0100 Subject: [PATCH 0512/1176] Allows specifying an entry-point for the lsp server (#818) * crude hacks, wip * annotates parsed modules with their filepath over just basename * removes commented code * adds cli arg parser for the lsp server Only creates and writes to the log file if --debug is set * removes dead code, comments out a test for now * adds LOCALE_ARCHIVE to nix-shell environment this stops Perl from outputting warnings into the test output * accept that motoko outputs relative file paths for source files Rather than just using the file basename * pass the current_directory as the filename for the js compiler It seems odd that we stat the file system when compiling a string, I think it happens somewhere when resolving imports --- default.nix | 1 + src/exes/mo_ide.ml | 25 +++++++++++- src/js/mo_js.ml | 4 +- src/languageServer/declaration_index.ml | 25 +++--------- src/languageServer/languageServer.ml | 53 ++++++++++++++++--------- src/lib/lib.ml | 8 ++++ src/lib/lib.mli | 1 + src/pipeline/pipeline.ml | 5 +-- src/pipeline/pipeline.mli | 5 +++ test/fail/ok/not-static.tc.ok | 2 +- test/lsp-int/Main.hs | 15 +++---- test/repl/ok/double-import.stdout.ok | 2 +- test/repl/ok/file-and-repl.stderr.ok | 2 +- test/repl/ok/file-and-repl.stdout.ok | 8 ++-- test/repl/ok/nested-import.stdout.ok | 6 +-- test/repl/ok/triangle-import.stdout.ok | 8 ++-- 16 files changed, 105 insertions(+), 65 deletions(-) diff --git a/default.nix b/default.nix index eaeda694329..324cbcfbe95 100644 --- a/default.nix +++ b/default.nix @@ -589,6 +589,7 @@ rec { JS_USER_LIBRARY=js-user-library; TOMMATHSRC = libtommath; NIX_FONTCONFIG_FILE = users-guide.NIX_FONTCONFIG_FILE; + LOCALE_ARCHIVE="${nixpkgs.glibcLocales}/lib/locale/locale-archive"; } else null; } diff --git a/src/exes/mo_ide.ml b/src/exes/mo_ide.ml index 6919193ee44..c40aba7858c 100644 --- a/src/exes/mo_ide.ml +++ b/src/exes/mo_ide.ml @@ -1,2 +1,25 @@ +let entry_point : string option ref = ref None +let debug = ref false + +let set_debug () = debug := true +let set_entry_point ep = entry_point := Some ep +let usage = "LSP server for motoko" + +let argspec = + Arg.align + [ "--debug", + Arg.Unit set_debug, + " outputs logging information to a lsp.log file" + ; "--canister-main", + Arg.String set_entry_point, + " specifies the entry point for the current project" + ] + let () = - LanguageServer.start () + Arg.parse argspec ignore usage; + match !entry_point with + | None -> + Printf.eprintf "--canister-main needs to be specified"; + exit 1 + | Some ep -> + LanguageServer.start ep !debug diff --git a/src/js/mo_js.ml b/src/js/mo_js.ml index 30d0cb8e938..7603fc3ac25 100644 --- a/src/js/mo_js.ml +++ b/src/js/mo_js.ml @@ -30,7 +30,7 @@ let diagnostics_of_msgs (msgs : Diag.message list) = let js_check source = let msgs = match - Pipeline.check_string (Js.to_string source) "js-input" with + Pipeline.check_string (Js.to_string source) Filename.current_dir_name with | Error msgs -> msgs | Ok (_, msgs) -> msgs in object%js @@ -44,7 +44,7 @@ let js_compile_with mode_string source convert = | "dfinity" -> Flags.AncientMode | _ -> Flags.WasmMode in - match Pipeline.compile_string mode (Js.to_string source) "js-input" with + match Pipeline.compile_string mode (Js.to_string source) Filename.current_dir_name with | Ok (module_, msgs) -> let (code, map) = convert module_ in object%js diff --git a/src/languageServer/declaration_index.ml b/src/languageServer/declaration_index.ml index 0ceb0a6b953..f1342bded64 100644 --- a/src/languageServer/declaration_index.ml +++ b/src/languageServer/declaration_index.ml @@ -83,18 +83,6 @@ let string_of_index index = ^ string_of_list string_of_ide_decl decls ^ "\n") -let project_files () : string list = - let rec read_dir d = - if Sys.is_directory d - then - let entries = - Array.to_list (Sys.readdir d) - |> List.map (fun file -> Filename.concat d file) in - flat_map read_dir entries - else [d] in - read_dir "." - |> List.filter (fun file -> String.equal (Filename.extension file) ".mo") - let read_single_module_lib (ty: Type.typ): ide_decl list option = match ty with | Type.Obj (Type.Module, fields) -> @@ -165,13 +153,12 @@ let populate_definitions | Some lib -> List.map (find_def lib) decls -let make_index_inner vfs : declaration_index Diag.result = - let entry_points = project_files () in - Pipeline.chase_imports +let make_index_inner vfs entry_points : declaration_index Diag.result = + Pipeline.load_progs (Vfs.parse_file vfs) + entry_points Pipeline.initial_stat_env - (Pipeline__.Resolve_import.S.of_list entry_points) - |> Diag.map (fun (libs, scope) -> + |> Diag.map (fun (libs, _, scope) -> Type.Env.fold (fun path ty acc -> Index.add @@ -184,6 +171,6 @@ let make_index_inner vfs : declaration_index Diag.result = scope.Scope.lib_env Index.empty) -let make_index vfs : declaration_index Diag.result = +let make_index vfs entry_points : declaration_index Diag.result = (* TODO(Christoph): Actually handle errors here *) - try make_index_inner vfs with _ -> Diag.return Index.empty + try make_index_inner vfs entry_points with _ -> Diag.return Index.empty diff --git a/src/languageServer/languageServer.ml b/src/languageServer/languageServer.ml index 85e4a4b2a27..851193ac969 100644 --- a/src/languageServer/languageServer.ml +++ b/src/languageServer/languageServer.ml @@ -60,6 +60,9 @@ module Channel = struct }) in let notification = notification params in send_notification oc (Lsp_j.string_of_notification_message notification) + + let clear_diagnostics (oc : out_channel) (uri : Lsp_t.document_uri): unit = + publish_diagnostics oc uri [] end let position_of_pos (pos : Source.pos) : Lsp_t.position = Lsp_t. @@ -77,29 +80,35 @@ let severity_of_sev : Diag.severity -> Lsp.DiagnosticSeverity.t = function | Diag.Error -> Lsp.DiagnosticSeverity.Error | Diag.Warning -> Lsp.DiagnosticSeverity.Warning -let diagnostics_of_message (msg : Diag.message) : Lsp_t.diagnostic = Lsp_t. +let diagnostics_of_message (msg : Diag.message) : (Lsp_t.diagnostic * string) = (Lsp_t. { diagnostic_range = range_of_region msg.Diag.at; diagnostic_severity = Some (severity_of_sev msg.Diag.sev); diagnostic_code = None; diagnostic_source = Some "Motoko"; diagnostic_message = msg.Diag.text; diagnostic_relatedInformation = None; - } - -let start () = - let oc: out_channel = open_out_gen [Open_append; Open_creat] 0o666 "ls.log"; in + }, msg.Diag.at.Source.left.Source.file) +let start entry_point debug = + let oc: out_channel = + if debug then + open_out_gen [Open_append; Open_creat] 0o666 "ls.log" + else + open_out "/dev/null" in let log_to_file = Channel.log_to_file oc in + let _ = log_to_file "entry_point" entry_point in let publish_diagnostics = Channel.publish_diagnostics oc in + let clear_diagnostics = Channel.clear_diagnostics oc in let send_response = Channel.send_response oc in let show_message = Channel.show_message oc in let shutdown = ref false in let client_capabilities = ref None in let project_root = Sys.getcwd () in + let files_with_diags = ref [] in let vfs = ref Vfs.empty in let decl_index = - let ix = match Declaration_index.make_index !vfs with + let ix = match Declaration_index.make_index !vfs [entry_point] with | Error(err) -> List.iter (fun e -> log_to_file "Error" (Diag.string_of_message e)) err; Declaration_index.Index.empty @@ -211,19 +220,25 @@ let start () = vfs := Vfs.update_file params !vfs | (_, `TextDocumentDidClose params) -> vfs := Vfs.close_file params !vfs - | (_, `TextDocumentDidSave params) -> - let textDocumentIdent = params.Lsp_t.text_document_did_save_params_textDocument in - let uri = textDocumentIdent.Lsp_t.text_document_identifier_uri in - let file_name = Vfs.file_from_uri log_to_file uri in - let result = Pipeline.check_files' (Vfs.parse_file !vfs) [file_name] in - let msgs = match result with - | Error msgs' -> msgs' - | Ok (_, msgs') -> msgs' in - (match Declaration_index.make_index !vfs with - | Error(err) -> () - | Ok((ix, _)) -> decl_index := ix); - let diags = List.map diagnostics_of_message msgs in - publish_diagnostics uri diags; + | (_, `TextDocumentDidSave _) -> + let msgs = match Declaration_index.make_index !vfs [entry_point] with + | Error msgs' -> msgs' + | Ok((ix, msgs')) -> + decl_index := ix; + msgs' in + let diags_by_file = + msgs + |> List.map diagnostics_of_message + |> Lib.List.group (fun (_, f1) (_, f2) -> f1 = f2) + |> List.map (fun diags -> + let (_, file) = List.hd diags in + (List.map fst diags, Vfs.uri_from_file file)) in + + List.iter clear_diagnostics !files_with_diags; + files_with_diags := List.map snd diags_by_file; + List.iter (fun (diags, uri) -> + let _ = log_to_file "diag_uri" uri in + publish_diagnostics uri diags) diags_by_file; (* Notification messages *) diff --git a/src/lib/lib.ml b/src/lib/lib.ml index 92508667946..4fc9c150042 100644 --- a/src/lib/lib.ml +++ b/src/lib/lib.ml @@ -144,6 +144,14 @@ struct and table' n f xs = if n = 0 then xs else table' (n - 1) f (f (n - 1) :: xs) + let group f l = + let rec grouping acc = function + | [] -> acc + | hd::tl -> + let l1,l2 = List.partition (f hd) tl in + grouping ((hd::l1)::acc) l2 + in grouping [] l + let rec take n xs = match n, xs with | _ when n <= 0 -> [] diff --git a/src/lib/lib.mli b/src/lib/lib.mli index f2b673aacc2..0f0503a6b1b 100644 --- a/src/lib/lib.mli +++ b/src/lib/lib.mli @@ -16,6 +16,7 @@ sig val equal : ('a -> 'a -> bool) -> 'a list -> 'a list -> bool val make : int -> 'a -> 'a list val table : int -> (int -> 'a) -> 'a list + val group : ('a -> 'a -> bool) -> 'a list -> 'a list list val take : int -> 'a list -> 'a list (* raises Failure *) val drop : int -> 'a list -> 'a list (* raises Failure *) val split_at : int -> 'a list -> ('a list * 'a list) diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index c02d0ada6b0..dd4b09bba83 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -89,15 +89,14 @@ let parse_string name s : parse_result = let lexer = Lexing.from_string s in let parse = Parser.parse_prog in match parse_with Lexer.Normal lexer parse name with - | Ok prog -> Diag.return (prog, Filename.current_dir_name) + | Ok prog -> Diag.return (prog, name) | Error e -> Error [e] let parse_file filename : parse_result = let ic = open_in filename in let lexer = Lexing.from_channel ic in let parse = Parser.parse_prog in - let name = Filename.basename filename in - let result = parse_with Lexer.Normal lexer parse name in + let result = parse_with Lexer.Normal lexer parse filename in close_in ic; match result with | Ok prog -> Diag.return (prog, filename) diff --git a/src/pipeline/pipeline.mli b/src/pipeline/pipeline.mli index 664d38bc30e..b2a1b0c47e7 100644 --- a/src/pipeline/pipeline.mli +++ b/src/pipeline/pipeline.mli @@ -24,3 +24,8 @@ type compile_result = Wasm_exts.CustomModule.extended_module Diag.result val compile_string : Flags.compile_mode -> string -> string -> compile_result val compile_files : Flags.compile_mode -> bool -> string list -> compile_result + +(* For use in the IDE server *) +type load_result = + (Syntax.lib list * Syntax.prog list * Scope.scope) Diag.result +val load_progs : parse_fn -> string list -> Scope.scope -> load_result diff --git a/test/fail/ok/not-static.tc.ok b/test/fail/ok/not-static.tc.ok index 71bab0557a2..032a0232e30 100644 --- a/test/fail/ok/not-static.tc.ok +++ b/test/fail/ok/not-static.tc.ok @@ -1 +1 @@ -not-static.mo:1.1-1.36: type error, non-static expression in library or module +lib/not-static.mo:1.1-1.36: type error, non-static expression in library or module diff --git a/test/lsp-int/Main.hs b/test/lsp-int/Main.hs index 809ede13197..d03aaafb47e 100644 --- a/test/lsp-int/Main.hs +++ b/test/lsp-int/Main.hs @@ -66,14 +66,13 @@ main = handleHUnitFailure $ do unless (length args == 2) (putStrLn "This test expects two command line arguments,\ - \the path to the as-ide binary and the path to\ + \the path to the mo-ide binary and the path to\ \the test project it's supposed to run in") - let [as_ide, project] = args + let [mo_ide, project] = args setCurrentDirectory project - runSession as_ide fullCaps "." $ do + runSession (mo_ide <> " --canister-main app.mo --debug") fullCaps "." $ do initRes <- initializeResponse doc <- openDoc "ListClient.mo" "motoko" -{- TODO(kritzcreek): Fix me and reactivate hoverTestCase doc (Position 13 11) @@ -95,11 +94,10 @@ main = handleHUnitFailure $ do -- 14 | List.pus| (Position 13 14) [("push",Just "(T, List) -> List")] --} closeDoc doc doc <- openDoc "ListClient.mo" "motoko" - -- 1 | module { - -- ==> 1 | ule { + -- 1 | import List + -- ==> 1 | ort List let edit = TextEdit (Range (Position 0 1) (Position 0 3)) "" _ <- applyEdit doc edit sendNotification TextDocumentDidSave (DidSaveTextDocumentParams doc) @@ -109,10 +107,13 @@ main = handleHUnitFailure $ do -- It finds errors in transitive modules that have been changed in -- the vfs but not yet stored to disc + {- TODO(Christoph): Figure out why this isn't working right now doc <- openDoc "ListClient.mo" "motoko" let edit = TextEdit (Range (Position 0 1) (Position 0 3)) "" _ <- applyEdit doc edit appDoc <- openDoc "app.mo" "motoko" sendNotification TextDocumentDidSave (DidSaveTextDocumentParams appDoc) + diags <- waitForDiagnostics (diagnostic:_) <- waitForDiagnostics liftIO (diagnostic^.message `shouldBe` "unexpected token") + -} diff --git a/test/repl/ok/double-import.stdout.ok b/test/repl/ok/double-import.stdout.ok index e4f8aebbd96..ae051459fc0 100644 --- a/test/repl/ok/double-import.stdout.ok +++ b/test/repl/ok/double-import.stdout.ok @@ -1,6 +1,6 @@ Motoko 0.1 interpreter -- Parsing stdin: -> -- Parsing empty.mo: +> -- Parsing lib/empty.mo: -- Checking empty.mo: -- Definedness empty.mo: -- Checking stdin: diff --git a/test/repl/ok/file-and-repl.stderr.ok b/test/repl/ok/file-and-repl.stderr.ok index 7e572ed4d4d..4e594fbfc86 100644 --- a/test/repl/ok/file-and-repl.stderr.ok +++ b/test/repl/ok/file-and-repl.stderr.ok @@ -1,4 +1,4 @@ -63:1.12-1.40: warning, the cases in this switch over type +/dev/fd/63:1.12-1.40: warning, the cases in this switch over type Bool do not cover value false diff --git a/test/repl/ok/file-and-repl.stdout.ok b/test/repl/ok/file-and-repl.stdout.ok index 38cec6e903d..52b8ed87e51 100644 --- a/test/repl/ok/file-and-repl.stdout.ok +++ b/test/repl/ok/file-and-repl.stdout.ok @@ -1,8 +1,8 @@ Motoko 0.1 interpreter --- Parsing 63: --- Checking 63: --- Definedness 63: --- Interpreting 63: +-- Parsing /dev/fd/63: +-- Checking /dev/fd/63: +-- Definedness /dev/fd/63: +-- Interpreting /dev/fd/63: -- Parsing stdin: > -- Checking stdin: -- Definedness stdin: diff --git a/test/repl/ok/nested-import.stdout.ok b/test/repl/ok/nested-import.stdout.ok index f4819100728..b04d696a65b 100644 --- a/test/repl/ok/nested-import.stdout.ok +++ b/test/repl/ok/nested-import.stdout.ok @@ -1,5 +1,5 @@ -- Parsing stdin: -> -- Parsing nested.mo: --- Parsing a.mo: --- Parsing b.mo: +> -- Parsing lib/nested.mo: +-- Parsing lib/nested/a.mo: +-- Parsing lib/nested/b.mo: -- Parsing stdin: diff --git a/test/repl/ok/triangle-import.stdout.ok b/test/repl/ok/triangle-import.stdout.ok index 7b65ff402b1..e12a3548380 100644 --- a/test/repl/ok/triangle-import.stdout.ok +++ b/test/repl/ok/triangle-import.stdout.ok @@ -1,7 +1,7 @@ Motoko 0.1 interpreter -- Parsing stdin: -> -- Parsing b.mo: --- Parsing c.mo: +> -- Parsing lib/b.mo: +-- Parsing lib/c.mo: -- Checking c.mo: -- Definedness c.mo: -- Checking b.mo: @@ -15,7 +15,7 @@ Motoko 0.1 interpreter let anon-import-1.1 : module {i : Nat} = {i = 42} -- Parsing stdin: -> -- Parsing a.mo: +> -- Parsing lib/a.mo: -- Checking a.mo: -- Definedness a.mo: -- Checking stdin: @@ -33,7 +33,7 @@ let anon-import-2.1 : module {i : Nat} = {i = 42} let anon-import-3.1 : module {i : Nat} = {i = 42} -- Parsing stdin: -> -- Parsing triangle.mo: +> -- Parsing lib/triangle.mo: -- Checking triangle.mo: -- Definedness triangle.mo: -- Checking stdin: From 4df602f3bf9263e35bfad0682ed260a6c1925db2 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity <48968912+chenyan-dfinity@users.noreply.github.com> Date: Tue, 5 Nov 2019 10:56:54 -0800 Subject: [PATCH 0513/1176] Cleanup for AS to IDL conversion (#770) * remove prelude from idl * update doc and null for () * allow names to use most IDL keywords * fix * address comments * fix * remove identifier rename to another PR * fix * fix * fix * fix --- design/IDL-Motoko.md | 14 ++++---- src/mo_idl/mo_to_idl.ml | 15 ++++++-- test/Makefile | 8 ++--- test/as-idl/fields.mo | 12 ------- test/as-idl/ok/inline_result.did.ok | 16 --------- test/as-idl/ok/pa_cars.did.ok | 40 --------------------- test/idl/fieldnat.did | 3 ++ test/idl/keywords.did | 5 +++ test/idl/ok/fieldnat.js.ok | 6 +++- test/idl/ok/keywords.js.ok | 13 +++++++ test/{as-idl => mo-idl}/Makefile | 0 test/{as-idl => mo-idl}/counter.mo | 0 test/mo-idl/dup_fields.mo | 13 +++++++ test/mo-idl/fields.mo | 15 ++++++++ test/mo-idl/func_mode.mo | 4 +++ test/{as-idl => mo-idl}/inline_result.mo | 0 test/mo-idl/keyword.mo | 4 +++ test/{as-idl => mo-idl}/ok/counter.did.ok | 3 +- test/mo-idl/ok/dup_fields.idl.ok | 1 + test/mo-idl/ok/dup_fields.idl.ret.ok | 1 + test/mo-idl/ok/fields.did.ok | 20 +++++++++++ test/mo-idl/ok/func_mode.did.ok | 4 +++ test/mo-idl/ok/inline_result.did.ok | 13 +++++++ test/mo-idl/ok/keyword.did.ok | 4 +++ test/mo-idl/ok/pa_cars.did.ok | 35 ++++++++++++++++++ test/mo-idl/ok/prelude.did.ok | 6 ++++ test/{as-idl => mo-idl}/ok/recursion.did.ok | 10 +++--- test/{as-idl => mo-idl}/ok/result.did.ok | 18 +++++----- test/{as-idl => mo-idl}/pa_cars.mo | 0 test/mo-idl/prelude.mo | 6 ++++ test/{as-idl => mo-idl}/recursion.mo | 0 test/{as-idl => mo-idl}/result.mo | 0 32 files changed, 187 insertions(+), 102 deletions(-) delete mode 100644 test/as-idl/fields.mo delete mode 100644 test/as-idl/ok/inline_result.did.ok delete mode 100644 test/as-idl/ok/pa_cars.did.ok create mode 100644 test/idl/keywords.did create mode 100644 test/idl/ok/keywords.js.ok rename test/{as-idl => mo-idl}/Makefile (100%) rename test/{as-idl => mo-idl}/counter.mo (100%) create mode 100644 test/mo-idl/dup_fields.mo create mode 100644 test/mo-idl/fields.mo create mode 100644 test/mo-idl/func_mode.mo rename test/{as-idl => mo-idl}/inline_result.mo (100%) create mode 100644 test/mo-idl/keyword.mo rename test/{as-idl => mo-idl}/ok/counter.did.ok (66%) create mode 100644 test/mo-idl/ok/dup_fields.idl.ok create mode 100644 test/mo-idl/ok/dup_fields.idl.ret.ok create mode 100644 test/mo-idl/ok/fields.did.ok create mode 100644 test/mo-idl/ok/func_mode.did.ok create mode 100644 test/mo-idl/ok/inline_result.did.ok create mode 100644 test/mo-idl/ok/keyword.did.ok create mode 100644 test/mo-idl/ok/pa_cars.did.ok create mode 100644 test/mo-idl/ok/prelude.did.ok rename test/{as-idl => mo-idl}/ok/recursion.did.ok (53%) rename test/{as-idl => mo-idl}/ok/result.did.ok (60%) rename test/{as-idl => mo-idl}/pa_cars.mo (100%) create mode 100644 test/mo-idl/prelude.mo rename test/{as-idl => mo-idl}/recursion.mo (100%) rename test/{as-idl => mo-idl}/result.mo (100%) diff --git a/design/IDL-Motoko.md b/design/IDL-Motoko.md index fd6fd77f0e1..ede21b917c6 100644 --- a/design/IDL-Motoko.md +++ b/design/IDL-Motoko.md @@ -101,7 +101,7 @@ ef ( : ) = unescape() : e() efn : -> efn(shared -> ()) = ea() -> () oneway -efn(shared -> async ) = ea() -> ea() +efn(shared query? -> async ) = ea() -> ea() query? ea : -> ,* ea( ( ,* ) ) = e();* @@ -144,8 +144,8 @@ if( : ) = escape() : i() if( : ) = "_" "_": i() // also for implicit labels ifn : -> -ifn((,*) -> () oneway query?) = shared ia() -> () -ifn((,*) -> (,*) query?) = shared ia(,*) -> ia(,*) +ifn((,*) -> () oneway) = shared ia() -> () +ifn((,*) -> (,*) query?) = shared query? ia(,*) -> async ia(,*) ia : ,* -> ia(,) = i() @@ -168,11 +168,9 @@ escape = "_" hash() "_" otherwise Formally: For all IDL types `t ∈ dom i`, we have that `e(i(t))` is equivalent to `t`, i.e. either they are the same types, or short-hands of each other. - * Tuples are exported using the unnamed field short-hand, which is how tuples + * Non-empty tuples are exported using the unnamed field short-hand, which is how tuples are idiomatically expressed in the IDL: ``` - e(()) = record {} - e((Int, )) = record {int} e((Int, Nat)) = record {int;nat} e({i:Int, n:Nat)) = record {i:int; n:nat} e({_0_:Int, _1_:Nat)) = record {0:int; 1:nat} @@ -243,7 +241,7 @@ These mappings should be straight-forward, given the following clarifications: * Characters (of type `Char`) are mapped to their Unicode scalar as a `nat32`. Decoding a `nat32` that is not a valid Unicode scalar fails. -## Works flows +## Work flows The mapping specified here can be used to support the following use-cases. The user interfaces (e.g. flag names, or whether `moc`, `didc`, `dfx` is used) are @@ -253,7 +251,7 @@ just suggestions. If `foo.mo` is an Motoko `actor` compilation unit, then - moc --generate-idl foo.mo -o foo.did + moc --idl foo.mo -o foo.did will type-check `foo.mo` as `t = actor { … }`, map the Motoko type `t` to an IDL type `e(t)` of the form `service `, and produce a diff --git a/src/mo_idl/mo_to_idl.ml b/src/mo_idl/mo_to_idl.ml index 9915cce9eb1..9c1964e7782 100644 --- a/src/mo_idl/mo_to_idl.ml +++ b/src/mo_idl/mo_to_idl.ml @@ -66,8 +66,14 @@ let rec typ vs t = | Prim p -> I.PrimT (prim p) | Var (s, i) -> (typ vs (List.nth vs i)).it | Con (c, []) -> - chase_con vs c; - I.VarT (string_of_con vs c @@ no_region) + (match Con.kind c with + | Def ([], Prim p) -> I.PrimT (prim p) + | Def ([], Any) -> I.PrimT I.Reserved + | Def ([], Non) -> I.PrimT I.Empty + | _ -> + chase_con vs c; + I.VarT (string_of_con vs c @@ no_region) + ) | Con (c, ts) -> let ts = List.map (fun t -> @@ -85,7 +91,10 @@ let rec typ vs t = | _ -> assert false) | Typ c -> assert false | Tup ts -> - I.RecordT (tuple vs ts) + if ts = [] then + I.PrimT I.Null + else + I.RecordT (tuple vs ts) | Array t -> I.VecT (typ vs t) | Opt t -> I.OptT (typ vs t) | Obj (Object, fs) -> diff --git a/test/Makefile b/test/Makefile index bd75943b4d7..052150efede 100644 --- a/test/Makefile +++ b/test/Makefile @@ -7,7 +7,7 @@ all: $(MAKE) -C repl $(MAKE) -C ld $(MAKE) -C idl - $(MAKE) -C as-idl + $(MAKE) -C mo-idl $(MAKE) -C trap MAKE_PAR := $(MAKE) --no-print-directory --load-average -j $(shell getconf _NPROCESSORS_ONLN) --keep-going @@ -19,7 +19,7 @@ quick: $(MAKE_PAR) -C repl quick $(MAKE_PAR) -C ld quick $(MAKE_PAR) -C idl quick - $(MAKE_PAR) -C as-idl quick + $(MAKE_PAR) -C mo-idl quick parallel: quick $(MAKE_PAR) -C run-dfinity quick @@ -51,7 +51,7 @@ accept: $(MAKE) -C repl accept $(MAKE) -C ld accept $(MAKE) -C idl accept - $(MAKE) -C as-idl accept + $(MAKE) -C mo-idl accept $(MAKE) -C trap accept $(MAKE) -C run-deser accept @@ -63,7 +63,7 @@ clean: $(MAKE) -C run-drun clean $(MAKE) -C repl clean $(MAKE) -C ld clean - $(MAKE) -C as-idl clean + $(MAKE) -C mo-idl clean $(MAKE) -C idl clean $(MAKE) -C trap clean diff --git a/test/as-idl/fields.mo b/test/as-idl/fields.mo deleted file mode 100644 index 51dd1fb4146..00000000000 --- a/test/as-idl/fields.mo +++ /dev/null @@ -1,12 +0,0 @@ -type Info = { - name : Text; - // TODO not accepted by parser - //_1_ : Info; - //_34_5_ : Text; - name_ : Nat; -}; -type Tup = (Text, Info, Text, Nat); -actor Server { - public func f_(user1 : Info, user2 : Tup) : async () { - }; -} diff --git a/test/as-idl/ok/inline_result.did.ok b/test/as-idl/ok/inline_result.did.ok deleted file mode 100644 index af2f7ed6969..00000000000 --- a/test/as-idl/ok/inline_result.did.ok +++ /dev/null @@ -1,16 +0,0 @@ -type Text = text; -type Nat = nat; -type Int = int; -service anon_inline_result { - "f": (opt Nat) -> (variant { - "err": Text; - "ok": Nat; - }); - "g": (variant { - "err": Text; - "ok": Nat; - }) -> (variant { - "err": record {}; - "ok": Int; - }); -} diff --git a/test/as-idl/ok/pa_cars.did.ok b/test/as-idl/ok/pa_cars.did.ok deleted file mode 100644 index e5c23a58e4c..00000000000 --- a/test/as-idl/ok/pa_cars.did.ok +++ /dev/null @@ -1,40 +0,0 @@ -type User = record {"name": Text;}; -type TimeSpan = - record { - "end": Int; - "start": Int; - }; -type Text = text; -type Result_1 = opt record {"reservationId": Text;}; -type PACars = - service { - "verifyCarInformation": (User, Car) -> - (opt func (Location, TimeSpan) -> (Result_1)); - }; -type Nat = nat; -type Location = - record { - "lat": Float; - "long": Float; - }; -type Int = int; -type Float = float64; -type DMV = - service { - "check": (Car) -> (CarInfo); - }; -type CarInfo = - record { - "expires": Nat; - "isValid": Bool; - "model": Text; - "plate": Text; - "wasStolen": Bool; - }; -type Car = - record { - "model": Text; - "plate": Text; - }; -type Bool = bool; - diff --git a/test/idl/fieldnat.did b/test/idl/fieldnat.did index 12af354c150..cdc412a14ea 100644 --- a/test/idl/fieldnat.did +++ b/test/idl/fieldnat.did @@ -1,5 +1,8 @@ service Foo { foo : (record {2 : int}) -> (); bar : (record {"2" : int}) -> (); + // TODO: JS binding treats all field names as string + baz : (record {2: int; "2": nat}) -> (); + bab : (2: int, "2": nat) -> (); } diff --git a/test/idl/keywords.did b/test/idl/keywords.did new file mode 100644 index 00000000000..16cfb66696a --- /dev/null +++ b/test/idl/keywords.did @@ -0,0 +1,5 @@ +type const_ = record { type_:nat; service_:nat; vec_:nat }; +service s { + "blob": (const_) -> (blob); + "record": (opt_:nat, import_:nat, variant_:variant {}) -> (record_:nat, record {}); +} diff --git a/test/idl/ok/fieldnat.js.ok b/test/idl/ok/fieldnat.js.ok index 2dd0d31471b..41edca0128b 100644 --- a/test/idl/ok/fieldnat.js.ok +++ b/test/idl/ok/fieldnat.js.ok @@ -1,6 +1,10 @@ export default ({ IDL }) => { const actor_Foo = new IDL.ActorInterface({ 'foo': IDL.Func(IDL.Obj({'0': IDL.Obj({'2': IDL.Int})}), IDL.Obj({})), - 'bar': IDL.Func(IDL.Obj({'0': IDL.Obj({'2': IDL.Int})}), IDL.Obj({}))}); + 'bar': IDL.Func(IDL.Obj({'0': IDL.Obj({'2': IDL.Int})}), IDL.Obj({})), + 'baz': + IDL.Func(IDL.Obj({'0': IDL.Obj({'2': IDL.Int, '2': IDL.Nat})}), + IDL.Obj({})), + 'bab': IDL.Func(IDL.Obj({'2': IDL.Int, '2': IDL.Nat}), IDL.Obj({}))}); return actor_Foo; }; diff --git a/test/idl/ok/keywords.js.ok b/test/idl/ok/keywords.js.ok new file mode 100644 index 00000000000..b13d803e6c6 --- /dev/null +++ b/test/idl/ok/keywords.js.ok @@ -0,0 +1,13 @@ +export default ({ IDL }) => { + const const_ = + IDL.Obj({'type_': IDL.Nat, 'vec_': IDL.Nat, 'service_': IDL.Nat}) + const actor_s = new IDL.ActorInterface({ + 'blob': IDL.Func(IDL.Obj({'0': const_}), IDL.Obj({'0': IDL.Arr(IDL.Nat8)})), + + 'record': + IDL.Func( + IDL.Obj({'opt_': IDL.Nat, 'import_': IDL.Nat, 'variant_': IDL.Variant({}) + }), + IDL.Obj({'record_': IDL.Nat, '821774511': IDL.Obj({})}))}); + return actor_s; +}; diff --git a/test/as-idl/Makefile b/test/mo-idl/Makefile similarity index 100% rename from test/as-idl/Makefile rename to test/mo-idl/Makefile diff --git a/test/as-idl/counter.mo b/test/mo-idl/counter.mo similarity index 100% rename from test/as-idl/counter.mo rename to test/mo-idl/counter.mo diff --git a/test/mo-idl/dup_fields.mo b/test/mo-idl/dup_fields.mo new file mode 100644 index 00000000000..1a834bea6d6 --- /dev/null +++ b/test/mo-idl/dup_fields.mo @@ -0,0 +1,13 @@ +type Info = { + name : Text; + _1_ : Info; + _345_ : Text; + name_: Int; +}; +type Tup = (Text, Info, Text, Nat); +actor Server { + public query func f_(user : Tup) : async () { + }; + public func f__(user : ?Tup) : () { }; +} + diff --git a/test/mo-idl/fields.mo b/test/mo-idl/fields.mo new file mode 100644 index 00000000000..1c213cfbc59 --- /dev/null +++ b/test/mo-idl/fields.mo @@ -0,0 +1,15 @@ +type Info = { + name : Text; + _1_ : Info; + _345_ : Text; + _34_5_: Bool; + _name_: Int; + name__ : Nat; +}; +type Tup = (Text, Info, Text, Nat); +actor Server { + public func f_(user : Tup) : async () { + }; + public func f__(user : ?Tup) : () { }; +} + diff --git a/test/mo-idl/func_mode.mo b/test/mo-idl/func_mode.mo new file mode 100644 index 00000000000..9d918f0169f --- /dev/null +++ b/test/mo-idl/func_mode.mo @@ -0,0 +1,4 @@ +actor s { + public query func f() : async () {}; + public func g() : () {}; +} diff --git a/test/as-idl/inline_result.mo b/test/mo-idl/inline_result.mo similarity index 100% rename from test/as-idl/inline_result.mo rename to test/mo-idl/inline_result.mo diff --git a/test/mo-idl/keyword.mo b/test/mo-idl/keyword.mo new file mode 100644 index 00000000000..85e944d7f64 --- /dev/null +++ b/test/mo-idl/keyword.mo @@ -0,0 +1,4 @@ +type record_ = Nat; +actor record_ { + public func record(record: record_) : async () {}; +} diff --git a/test/as-idl/ok/counter.did.ok b/test/mo-idl/ok/counter.did.ok similarity index 66% rename from test/as-idl/ok/counter.did.ok rename to test/mo-idl/ok/counter.did.ok index 4274e7fac69..6d278fcfcce 100644 --- a/test/as-idl/ok/counter.did.ok +++ b/test/mo-idl/ok/counter.did.ok @@ -1,7 +1,6 @@ -type Int = int; type Counter = service { "dec": () -> () oneway; - "read": () -> (Int); + "read": () -> (int); }; service c : Counter diff --git a/test/mo-idl/ok/dup_fields.idl.ok b/test/mo-idl/ok/dup_fields.idl.ok new file mode 100644 index 00000000000..63274d81be3 --- /dev/null +++ b/test/mo-idl/ok/dup_fields.idl.ok @@ -0,0 +1 @@ +(unknown location): type error, field name name hash collision with field name diff --git a/test/mo-idl/ok/dup_fields.idl.ret.ok b/test/mo-idl/ok/dup_fields.idl.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/mo-idl/ok/dup_fields.idl.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/mo-idl/ok/fields.did.ok b/test/mo-idl/ok/fields.did.ok new file mode 100644 index 00000000000..cf85958da08 --- /dev/null +++ b/test/mo-idl/ok/fields.did.ok @@ -0,0 +1,20 @@ +type Tup = + record { + text; + Info; + text; + nat; + }; +type Info = + record { + 1: Info; + 345: text; + "_34_5": bool; + "_name": int; + "name": text; + "name_": nat; + }; +service Server { + "f": (Tup) -> (); + "f_": (opt Tup) -> () oneway; +} diff --git a/test/mo-idl/ok/func_mode.did.ok b/test/mo-idl/ok/func_mode.did.ok new file mode 100644 index 00000000000..c3867b8d58f --- /dev/null +++ b/test/mo-idl/ok/func_mode.did.ok @@ -0,0 +1,4 @@ +service s { + "f": () -> () query; + "g": () -> () oneway; +} diff --git a/test/mo-idl/ok/inline_result.did.ok b/test/mo-idl/ok/inline_result.did.ok new file mode 100644 index 00000000000..9975fbd985c --- /dev/null +++ b/test/mo-idl/ok/inline_result.did.ok @@ -0,0 +1,13 @@ +service anon_inline_result { + "f": (opt nat) -> (variant { + "err": text; + "ok": nat; + }); + "g": (variant { + "err": text; + "ok": nat; + }) -> (variant { + "err": null; + "ok": int; + }); +} diff --git a/test/mo-idl/ok/keyword.did.ok b/test/mo-idl/ok/keyword.did.ok new file mode 100644 index 00000000000..378323b0b63 --- /dev/null +++ b/test/mo-idl/ok/keyword.did.ok @@ -0,0 +1,4 @@ +type record_ = nat; +service record_ { + "record": (record_) -> (); +} diff --git a/test/mo-idl/ok/pa_cars.did.ok b/test/mo-idl/ok/pa_cars.did.ok new file mode 100644 index 00000000000..7d82ad5c81c --- /dev/null +++ b/test/mo-idl/ok/pa_cars.did.ok @@ -0,0 +1,35 @@ +type User = record {"name": text;}; +type TimeSpan = + record { + "end": int; + "start": int; + }; +type Result_1 = opt record {"reservationId": text;}; +type PACars = + service { + "verifyCarInformation": (User, Car) -> + (opt func (Location, TimeSpan) -> (Result_1)); + }; +type Location = + record { + "lat": float64; + "long": float64; + }; +type DMV = + service { + "check": (Car) -> (CarInfo); + }; +type CarInfo = + record { + "expires": nat; + "isValid": bool; + "model": text; + "plate": text; + "wasStolen": bool; + }; +type Car = + record { + "model": text; + "plate": text; + }; + diff --git a/test/mo-idl/ok/prelude.did.ok b/test/mo-idl/ok/prelude.did.ok new file mode 100644 index 00000000000..3f065033fc4 --- /dev/null +++ b/test/mo-idl/ok/prelude.did.ok @@ -0,0 +1,6 @@ +type Text_1 = Nat_1; +type Nat_1 = null; +type Id = int; +service A { + "f": (Nat_1, Text_1) -> (Id); +} diff --git a/test/as-idl/ok/recursion.did.ok b/test/mo-idl/ok/recursion.did.ok similarity index 53% rename from test/as-idl/ok/recursion.did.ok rename to test/mo-idl/ok/recursion.did.ok index 267c0171831..60a9d06ac88 100644 --- a/test/as-idl/ok/recursion.did.ok +++ b/test/mo-idl/ok/recursion.did.ok @@ -1,16 +1,14 @@ -type Nat = nat; type List_2 = record { - "head": Nat; + "head": nat; "tail": opt List_2; }; type List_1 = record { - "head": Int; + "head": int; "tail": opt List_1; }; -type Int = int; service anon_recursion { - "f": (Nat) -> (List_2); - "g": (Int) -> (List_1); + "f": (nat) -> (List_2); + "g": (int) -> (List_1); } diff --git a/test/as-idl/ok/result.did.ok b/test/mo-idl/ok/result.did.ok similarity index 60% rename from test/as-idl/ok/result.did.ok rename to test/mo-idl/ok/result.did.ok index 154062fb5c7..8bb8b28d4e1 100644 --- a/test/as-idl/ok/result.did.ok +++ b/test/mo-idl/ok/result.did.ok @@ -1,31 +1,29 @@ -type Text = text; type Result_1_2 = variant { - "err": Text; - "ok": Nat; + "err": text; + "ok": nat; }; type Result_1_1 = variant { - "err": Text; - "ok": record {}; + "err": text; + "ok": null; }; type Result3_1 = variant { "err": Result2_1; - "ok": record {}; + "ok": null; }; type Result2_2 = variant { "err": Result_1_2; - "ok": Nat; + "ok": nat; }; type Result2_1 = variant { "err": Result_1_1; - "ok": record {}; + "ok": null; }; -type Nat = nat; service anon_result { - "f": (opt Nat) -> (Result_1_2); + "f": (opt nat) -> (Result_1_2); "g": (Result3_1) -> (Result2_2); } diff --git a/test/as-idl/pa_cars.mo b/test/mo-idl/pa_cars.mo similarity index 100% rename from test/as-idl/pa_cars.mo rename to test/mo-idl/pa_cars.mo diff --git a/test/mo-idl/prelude.mo b/test/mo-idl/prelude.mo new file mode 100644 index 00000000000..2e77d6f15f3 --- /dev/null +++ b/test/mo-idl/prelude.mo @@ -0,0 +1,6 @@ +type Nat = (); +type Id = Int; +type Text = Nat; +actor A { + public func f (x:Nat, y:Text):async Id {0}; +}; diff --git a/test/as-idl/recursion.mo b/test/mo-idl/recursion.mo similarity index 100% rename from test/as-idl/recursion.mo rename to test/mo-idl/recursion.mo diff --git a/test/as-idl/result.mo b/test/mo-idl/result.mo similarity index 100% rename from test/as-idl/result.mo rename to test/mo-idl/result.mo From e726dba7a5d32e15915b1f3977ae2161da057f80 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 30 Oct 2019 23:40:58 +0000 Subject: [PATCH 0514/1176] Interpret ICCallPrim in the IR interpreter by passing callbacks via different calling convention for T.Replies functions. Still needs better names for replying functions.... --- guide/guide.md | 5 +- src/ir_interpreter/interpret_ir.ml | 83 +++++++++++++++++++++++++-- src/mo_frontend/typing.ml | 3 +- src/mo_values/call_conv.ml | 3 +- src/mo_values/call_conv.mli | 1 + src/mo_values/value.ml | 3 +- src/mo_values/value.mli | 1 + src/pipeline/pipeline.ml | 3 +- test/run-dfinity/ok/await.diff-low.ok | 10 ++++ test/run-dfinity/ok/await.run-low.ok | 4 +- test/run-drun/ic-calls.mo | 2 +- test/run.sh | 2 - 12 files changed, 104 insertions(+), 16 deletions(-) create mode 100644 test/run-dfinity/ok/await.diff-low.ok diff --git a/guide/guide.md b/guide/guide.md index 13c13b305de..df7cdcf283d 100644 --- a/guide/guide.md +++ b/guide/guide.md @@ -26,6 +26,7 @@ TODO: * [ ] Platform changes: remove async expressions (and perhaps types); restrict await to shared calls. * [ ] Queries * [ ] Remove Shared type +* [ ] Document .vals and .key for arrays. Iter type. --> # Introduction @@ -1041,7 +1042,7 @@ Otherwise, `r2` is false and the result is `()`. The for expression `for ( in ) ` has type `()` provided: * `` has type `{ next : () -> ?T; }`; -* pattern `` has type `U`; and, +* pattern `` has type `T`; and, * expression `` has type `()` (in the environment extended with ``'s bindings). The `for`-expression is syntactic sugar for @@ -1059,7 +1060,7 @@ for ( in ) := } ``` -where `x` is fresh identifier. +where `x` is a fresh identifier. In particular, the `for` loops will trap if evaluation of `` traps; as soon as some value of `x.next()` traps or the value of `x.next()` does not match pattern ``. diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index a07f26b0394..00f1bcaa109 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -15,6 +15,8 @@ type val_env = V.def V.Env.t type lab_env = V.value V.cont V.Env.t type ret_env = V.value V.cont option type throw_env = V.value V.cont option +type reply_env = V.value V.cont option +type reject_env = V.value V.cont option type scope = val_env @@ -30,6 +32,8 @@ type env = labs : lab_env; rets : ret_env; throws : throw_env; + replies : reply_env; + rejects : reject_env; async : bool } @@ -45,6 +49,8 @@ let env_of_scope flags flavor ve = labs = V.Env.empty; rets = None; throws = None; + replies = None; + rejects = None; async = false; } @@ -65,7 +71,7 @@ let find id env = let trace_depth = ref 0 let trace fmt = - Printf.ksprintf (fun s -> + Printf.ksprintf (fun s -> Printf.printf "%s%s\n%!" (String.make (2 * !trace_depth) ' ') s ) fmt @@ -109,7 +115,6 @@ struct if not (Queue.is_empty q) then (yield (); run ()) end - (* Async auxiliary functions *) (* Are these just duplicates of the corresponding functions in interpret.ml? If so, refactor *) @@ -212,12 +217,26 @@ let make_async_message env id v = failwith ("unexpected call_conv " ^ string_of_call_conv call_conv) (* assert (false) *) +let make_replying_message env id v = + assert (not env.flavor.has_async_typ); + let open CC in + let call_conv, f = V.as_func v in + match call_conv with + | {sort = T.Shared s; control = T.Replies; _} -> + Value.replies_func s call_conv.n_args call_conv.n_res (fun v k -> + actor_msg env id f v (fun v -> ()); + k (V.unit) + ) + | _ -> + failwith ("unexpected call_conv " ^ string_of_call_conv call_conv) + (* assert (false) *) + let make_message env x cc v : V.value = match cc.CC.control with | T.Returns -> make_unit_message env x v | T.Promises-> make_async_message env x v - | T.Replies -> make_async_message env x v (* TBR *) + | T.Replies -> make_replying_message env x v (* TBR *) let extended_prim env s typ at = @@ -357,7 +376,26 @@ and interpret_exp_mut env exp (k : V.value V.cont) = interpret_exps env exps [] (fun vs -> let arg = match vs with [v] -> v | _ -> V.Tup vs in Prim.num_conv_prim t1 t2 arg k - ) + ) + | ICReplyPrim ts, [exp1] -> + assert (not env.flavor.has_async_typ); + let reply = Lib.Option.value env.replies in + interpret_exp env exp1 reply + | ICRejectPrim, [exp1] -> + assert (not env.flavor.has_async_typ); + let reject = Lib.Option.value env.rejects in + interpret_exp env exp1 reject + | ICCallPrim, [exp1; exp2; expk ; expr] -> + assert (not env.flavor.has_async_typ); + interpret_exp env exp1 (fun v1 -> + interpret_exp env exp2 (fun v2 -> + interpret_exp env expk (fun kv -> + interpret_exp env expr (fun rv -> + let call_conv, f = V.as_func v1 in + check_call_conv exp1 call_conv; + check_call_conv_arg env exp2 v2 call_conv; + last_region := exp.at; (* in case the following throws *) + f (V.Tup[kv;rv;v2]) k)))) | _ -> trap exp.at "Unknown prim or wrong number of arguments (%d given):\n %s" (List.length es) (Wasm.Sexpr.to_string 80 (Arrange_ir.prim p)) @@ -466,6 +504,18 @@ and interpret_exp_mut env exp (k : V.value V.cont) = define_id env id v'; k V.unit ) + | FuncE (x, (T.Shared _ as sort), (T.Replies as control), _typbinds, args, ret_typs, e) -> + assert (not env.flavor.has_async_typ); + let cc = { sort; control; n_args = List.length args; n_res = List.length ret_typs } in + + let f = interpret_message env exp.at x args + (fun env' -> + interpret_exp env' e) in + + let v = V.Func (cc, f) in + let v = make_message env x cc v in + k v + | FuncE (x, sort, control, _typbinds, args, ret_typs, e) -> let cc = { sort; control; n_args = List.length args; n_res = List.length ret_typs } in @@ -729,6 +779,31 @@ and interpret_func env at x args f v (k : V.value V.cont) = } in f env' k' +and interpret_message env at x args f v (k : V.value V.cont) = + let v_reply, v_reject, v = match V.as_tup v with + | [v_reply ; v_reject; v] -> v_reply, v_reject, v + | _ -> assert false + in + if env.flags.trace then trace "%s%s" x (string_of_arg env v); + let _, reply = V.as_func v_reply in + let _, reject = V.as_func v_reject in + let ve = match_args at args v in + incr trace_depth; + let k' = fun v' -> + if env.flags.trace then trace "<= %s" (string_of_val env v'); + decr trace_depth; + k v' + in + let env' = + { env with + vals = V.Env.adjoin env.vals ve; + labs = V.Env.empty; + rets = Some k'; + replies = Some (fun v -> reply v V.as_unit); + rejects = Some (fun v -> reject v V.as_unit); + async = false + } + in f env' k' (* Programs *) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 41c404c8333..2b050892baf 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -92,7 +92,8 @@ let compile_mode_error mode env at fmt = let error_in modes env at fmt = let mode = !Flags.compile_mode in if List.mem mode modes then - compile_mode_error mode env at fmt + compile_mode_error mode env at fmt + (* Context extension *) diff --git a/src/mo_values/call_conv.ml b/src/mo_values/call_conv.ml index 33750ca4df5..9e334c1d5c6 100644 --- a/src/mo_values/call_conv.ml +++ b/src/mo_values/call_conv.ml @@ -19,6 +19,7 @@ type t = call_conv let local_cc n m = { sort = Local; control = Returns; n_args = n; n_res = m} let message_cc s n = { sort = Shared s; control = Returns; n_args = n; n_res = 0} let async_cc s n m = { sort = Shared s; control = Promises; n_args = n; n_res = m} +let replies_cc s n m = { sort = Shared s; control = Replies; n_args = n; n_res = m} let call_conv_of_typ typ = match typ with @@ -32,6 +33,6 @@ let string_of_call_conv {sort;control;n_args;n_res} = Printf.sprintf "(%s%i %s %i)" (string_of_func_sort sort) n_args - (match control with Returns -> "->" | Promises -> "@>" | Replies -> "@>") + (match control with Returns -> "->" | Promises -> "@>" | Replies -> "#>") n_res diff --git a/src/mo_values/call_conv.mli b/src/mo_values/call_conv.mli index 0b013a8526e..24fd4b318a1 100644 --- a/src/mo_values/call_conv.mli +++ b/src/mo_values/call_conv.mli @@ -12,6 +12,7 @@ type t = call_conv val local_cc : int -> int -> call_conv val message_cc : Type.shared_sort -> int -> call_conv val async_cc : Type.shared_sort -> int -> int -> call_conv +val replies_cc : Type.shared_sort -> int -> int -> call_conv val call_conv_of_typ : Type.typ -> call_conv diff --git a/src/mo_values/value.ml b/src/mo_values/value.ml index 054361acf82..582fed3ec31 100644 --- a/src/mo_values/value.ml +++ b/src/mo_values/value.ml @@ -302,7 +302,8 @@ let unit = Tup [] let local_func n m f = Func (Call_conv.local_cc n m, f) let message_func s n f = Func (Call_conv.message_cc s n, f) -let async_func s n p f = Func ( Call_conv.async_cc s n p, f) +let async_func s n m f = Func (Call_conv.async_cc s n m, f) +let replies_func s n m f = Func (Call_conv.replies_cc s n m, f) (* Projections *) diff --git a/src/mo_values/value.mli b/src/mo_values/value.mli index cf62e3e99c7..8c1b2581427 100644 --- a/src/mo_values/value.mli +++ b/src/mo_values/value.mli @@ -117,6 +117,7 @@ val unit : value val local_func : int -> int -> func -> value val message_func : Type.shared_sort -> int -> func -> value val async_func : Type.shared_sort -> int -> int -> func -> value +val replies_func : Type.shared_sort -> int -> int -> func -> value (* Projections *) diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index 63665ba706f..c058e85aba1 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -507,8 +507,7 @@ let compile_string mode s name : compile_result = let interpret_ir_prog inp_env libraries progs = let prelude_ir = Lowering.Desugar.transform prelude in let name = name_progs progs in - Flags.compile_mode := Flags.WasmMode; (* REMOVE THIS HACK *) - let prog_ir = lower_prog Flags.WasmMode initial_stat_env inp_env libraries progs name in + let prog_ir = lower_prog (!Flags.compile_mode) initial_stat_env inp_env libraries progs name in phase "Interpreting" name; let open Interpret_ir in let flags = { trace = !Flags.trace; print_depth = !Flags.print_depth } in diff --git a/test/run-dfinity/ok/await.diff-low.ok b/test/run-dfinity/ok/await.diff-low.ok new file mode 100644 index 00000000000..fd756b219f9 --- /dev/null +++ b/test/run-dfinity/ok/await.diff-low.ok @@ -0,0 +1,10 @@ +--- await.run ++++ await.run-low +@@ -12,5 +12,5 @@ + .cnt: 11 i: 8 + cnt: 12 i: 13 + .cnt: 13 i: 9 +-cnt: 14 i: 14 +-e-exitg-exit ++e-exitcnt: 14 i: 14 ++g-exit diff --git a/test/run-dfinity/ok/await.run-low.ok b/test/run-dfinity/ok/await.run-low.ok index 08e3e459bc4..1358fdeb953 100644 --- a/test/run-dfinity/ok/await.run-low.ok +++ b/test/run-dfinity/ok/await.run-low.ok @@ -12,5 +12,5 @@ cnt: 10 i: 12 .cnt: 11 i: 8 cnt: 12 i: 13 .cnt: 13 i: 9 -cnt: 14 i: 14 -e-exitg-exit +e-exitcnt: 14 i: 14 +g-exit diff --git a/test/run-drun/ic-calls.mo b/test/run-drun/ic-calls.mo index 01dc01475dd..3c5a81cd1ec 100644 --- a/test/run-drun/ic-calls.mo +++ b/test/run-drun/ic-calls.mo @@ -1,4 +1,4 @@ -actor { +actor X { public func A() : async () { diff --git a/test/run.sh b/test/run.sh index 6b8fbab2733..9cd4c6eff14 100755 --- a/test/run.sh +++ b/test/run.sh @@ -173,7 +173,6 @@ do diff -u -N --label "$base.run" $out/$base.run --label "$base.run-ir" $out/$base.run-ir > $out/$base.diff-ir diff_files="$diff_files $base.diff-ir" - if false; then # Interpret IR with lowering $ECHO -n " [run-low]" $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS -r -iR $base.mo > $out/$base.run-low 2>&1 @@ -183,7 +182,6 @@ do # Diff interpretations without/with lowering diff -u -N --label "$base.run" $out/$base.run --label "$base.run-low" $out/$base.run-low > $out/$base.diff-low diff_files="$diff_files $base.diff-low" - fi fi From b097ed6117a4bcfc4ffe660362161998a1f3101a Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 6 Nov 2019 12:18:59 +0000 Subject: [PATCH 0515/1176] relax restrictions in interpreter --- src/exes/moc.ml | 12 ++++++++---- src/mo_config/flags.ml | 3 ++- src/mo_frontend/typing.ml | 8 +++++--- src/mo_types/type.ml | 8 ++++---- src/pipeline/pipeline.ml | 2 +- 5 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/exes/moc.ml b/src/exes/moc.ml index aa866b1420e..af8ff43e5a8 100644 --- a/src/exes/moc.ml +++ b/src/exes/moc.ml @@ -67,10 +67,10 @@ let argspec = Arg.align "-no-link", Arg.Clear link, " do not statically link-in runtime"; "-no-system-api", - Arg.Unit (fun () -> Flags.(compile_mode := WasmMode)), + Arg.Unit (fun () -> Flags.(compile_mode := Some WasmMode)), " do not import any system API"; "-ancient-system-api", - Arg.Unit (fun () -> Flags.(compile_mode := AncientMode)), + Arg.Unit (fun () -> Flags.(compile_mode := Some AncientMode)), " use the ancient DFINITY system API (dvm)"; "-multi-value", Arg.Set Flags.multi_value, " use multi-value extension"; "-no-multi-value", Arg.Clear Flags.multi_value, " avoid multi-value extension"; @@ -121,11 +121,11 @@ let process_files files : unit = let prog = Diag.run (Pipeline.generate_idl files) in ignore (Diag.run (Idllib.Pipeline.check_prog prog)); let oc = open_out !out_file in - let idl_code = Idllib.Arrange_idl.string_of_prog prog in + let idl_code = Idllib.Arrange_idl.string_of_prog prog in output_string oc idl_code; close_out oc | Compile -> set_out_file files ".wasm"; - let module_ = Diag.run Pipeline.(compile_files !Flags.compile_mode !link files) in + let module_ = Diag.run Pipeline.(compile_files (Lib.Option.value (!Flags.compile_mode)) !link files) in let oc = open_out !out_file in let (source_map, wasm) = CustomModuleEncode.encode module_ in output_string oc wasm; close_out oc; @@ -157,5 +157,9 @@ let () = Printexc.record_backtrace true; Arg.parse argspec add_arg usage; if !mode = Default then mode := (if !args = [] then Interact else Compile); + match !mode with + | Run | Interact -> + Flags.compile_mode := None + | _ -> (); process_profiler_flags () ; process_files !args diff --git a/src/mo_config/flags.ml b/src/mo_config/flags.ml index 1da5cdd1474..cea19a37aa7 100644 --- a/src/mo_config/flags.ml +++ b/src/mo_config/flags.ml @@ -6,7 +6,7 @@ let trace = ref false let verbose = ref false let print_depth = ref 2 let release_mode = ref false -let compile_mode = ref ICMode +let compile_mode = ref (None : compile_mode option) let multi_value = ref false let await_lowering = ref true let async_lowering = ref true @@ -20,3 +20,4 @@ let profile_verbose = ref false let profile_file = ref "profiling-counters.csv" let profile_line_prefix = ref "" let profile_field_names : string list ref = ref [] +let interpreted = ref false diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index c8ddd22ae23..01a8c97d59d 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -75,7 +75,7 @@ let warn env at fmt = let flag_of_compile_mode mode = match mode with - | Flags.ICMode -> "" + | Flags.ICMode -> "compiled" | Flags.WasmMode -> " and flag -no-system-api" | Flags.AncientMode -> " and flag -ancient-system-api" @@ -90,8 +90,10 @@ let compile_mode_error mode env at fmt = Diag.add_msg env.msgs (type_error at s); raise Recover) fmt let error_in modes env at fmt = - let mode = !Flags.compile_mode in - if List.mem mode modes then + match !Flags.compile_mode with + | None -> () + | Some mode -> + if List.mem mode modes then compile_mode_error mode env at fmt (* Context extension *) diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index 6da2971e63e..c9ec6c62ee2 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -568,8 +568,8 @@ let concrete t = let shared t = (* TBR: Hack to restrict sharing in ICMode *) - let allow_actor = not (!Flags.compile_mode = Flags.ICMode) in - let allow_shared = not (!Flags.compile_mode = Flags.ICMode) in + let allow_actor = not (!Flags.compile_mode = Some Flags.ICMode) in + let allow_shared = not (!Flags.compile_mode = Some Flags.ICMode) in let seen = ref S.empty in let rec go t = S.mem t !seen || @@ -598,8 +598,8 @@ let shared t = (* Find the first unshared subexpression in a type *) let find_unshared t = (* TBR: Hack to restrict sharing in ICMode *) - let allow_actor = not (!Flags.compile_mode = Flags.ICMode) in - let allow_shared = not (!Flags.compile_mode = Flags.ICMode) in + let allow_actor = not (!Flags.compile_mode = Some Flags.ICMode) in + let allow_shared = not (!Flags.compile_mode = Some Flags.ICMode) in let seen = ref S.empty in let rec go t = if S.mem t !seen then None else diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index dd4b09bba83..40b9389f1e3 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -533,7 +533,7 @@ let compile_string mode s name : compile_result = let interpret_ir_prog inp_env libs progs = let prelude_ir = Lowering.Desugar.transform prelude in let name = name_progs progs in - Flags.compile_mode := Flags.WasmMode; (* REMOVE THIS HACK *) + Flags.compile_mode := Some Flags.WasmMode; (* REMOVE THIS HACK *) let prog_ir = lower_prog Flags.WasmMode initial_stat_env inp_env libs progs name in phase "Interpreting" name; let open Interpret_ir in From ddbba65608f91736addab5cb7f2ad3020f30d49e Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 6 Nov 2019 13:27:08 +0000 Subject: [PATCH 0516/1176] just use a Flags.compiled global instead --- src/exes/moc.ml | 11 ++++------- src/mo_config/flags.ml | 4 ++-- src/mo_frontend/typing.ml | 8 +++----- src/mo_types/type.ml | 8 ++++---- src/pipeline/pipeline.ml | 2 +- test/run-drun/ok/{idl-func.tc.ok => idl-func.comp.ok} | 0 .../ok/{idl-func.tc.ret.ok => idl-func.comp.ret.ok} | 0 .../ok/{unsupported.tc.ok => unsupported.comp.ok} | 2 +- ...{unsupported.tc.ret.ok => unsupported.comp.ret.ok} | 0 test/run-drun/unsupported.mo | 4 ++-- 10 files changed, 17 insertions(+), 22 deletions(-) rename test/run-drun/ok/{idl-func.tc.ok => idl-func.comp.ok} (100%) rename test/run-drun/ok/{idl-func.tc.ret.ok => idl-func.comp.ret.ok} (100%) rename test/run-drun/ok/{unsupported.tc.ok => unsupported.comp.ok} (97%) rename test/run-drun/ok/{unsupported.tc.ret.ok => unsupported.comp.ret.ok} (100%) diff --git a/src/exes/moc.ml b/src/exes/moc.ml index af8ff43e5a8..31b6c27edf0 100644 --- a/src/exes/moc.ml +++ b/src/exes/moc.ml @@ -67,10 +67,10 @@ let argspec = Arg.align "-no-link", Arg.Clear link, " do not statically link-in runtime"; "-no-system-api", - Arg.Unit (fun () -> Flags.(compile_mode := Some WasmMode)), + Arg.Unit (fun () -> Flags.(compile_mode := WasmMode)), " do not import any system API"; "-ancient-system-api", - Arg.Unit (fun () -> Flags.(compile_mode := Some AncientMode)), + Arg.Unit (fun () -> Flags.(compile_mode := AncientMode)), " use the ancient DFINITY system API (dvm)"; "-multi-value", Arg.Set Flags.multi_value, " use multi-value extension"; "-no-multi-value", Arg.Clear Flags.multi_value, " avoid multi-value extension"; @@ -125,7 +125,7 @@ let process_files files : unit = output_string oc idl_code; close_out oc | Compile -> set_out_file files ".wasm"; - let module_ = Diag.run Pipeline.(compile_files (Lib.Option.value (!Flags.compile_mode)) !link files) in + let module_ = Diag.run Pipeline.(compile_files !Flags.compile_mode !link files) in let oc = open_out !out_file in let (source_map, wasm) = CustomModuleEncode.encode module_ in output_string oc wasm; close_out oc; @@ -157,9 +157,6 @@ let () = Printexc.record_backtrace true; Arg.parse argspec add_arg usage; if !mode = Default then mode := (if !args = [] then Interact else Compile); - match !mode with - | Run | Interact -> - Flags.compile_mode := None - | _ -> (); + Flags.compiled := (!mode = Compile); process_profiler_flags () ; process_files !args diff --git a/src/mo_config/flags.ml b/src/mo_config/flags.ml index cea19a37aa7..0c8fcd1294f 100644 --- a/src/mo_config/flags.ml +++ b/src/mo_config/flags.ml @@ -6,7 +6,7 @@ let trace = ref false let verbose = ref false let print_depth = ref 2 let release_mode = ref false -let compile_mode = ref (None : compile_mode option) +let compile_mode = ref ICMode let multi_value = ref false let await_lowering = ref true let async_lowering = ref true @@ -20,4 +20,4 @@ let profile_verbose = ref false let profile_file = ref "profiling-counters.csv" let profile_line_prefix = ref "" let profile_field_names : string list ref = ref [] -let interpreted = ref false +let compiled = ref false diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 01a8c97d59d..8371b57d44f 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -75,7 +75,7 @@ let warn env at fmt = let flag_of_compile_mode mode = match mode with - | Flags.ICMode -> "compiled" + | Flags.ICMode -> "" | Flags.WasmMode -> " and flag -no-system-api" | Flags.AncientMode -> " and flag -ancient-system-api" @@ -90,10 +90,8 @@ let compile_mode_error mode env at fmt = Diag.add_msg env.msgs (type_error at s); raise Recover) fmt let error_in modes env at fmt = - match !Flags.compile_mode with - | None -> () - | Some mode -> - if List.mem mode modes then + let mode = !Flags.compile_mode in + if !Flags.compiled && List.mem mode modes then compile_mode_error mode env at fmt (* Context extension *) diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index c9ec6c62ee2..2656077dde3 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -568,8 +568,8 @@ let concrete t = let shared t = (* TBR: Hack to restrict sharing in ICMode *) - let allow_actor = not (!Flags.compile_mode = Some Flags.ICMode) in - let allow_shared = not (!Flags.compile_mode = Some Flags.ICMode) in + let allow_actor as allow_shared = + not (!Flags.compiled && !Flags.compile_mode = Flags.ICMode) in let seen = ref S.empty in let rec go t = S.mem t !seen || @@ -598,8 +598,8 @@ let shared t = (* Find the first unshared subexpression in a type *) let find_unshared t = (* TBR: Hack to restrict sharing in ICMode *) - let allow_actor = not (!Flags.compile_mode = Some Flags.ICMode) in - let allow_shared = not (!Flags.compile_mode = Some Flags.ICMode) in + let allow_actor as allow_shared = + not (!Flags.compiled && !Flags.compile_mode = Flags.ICMode) in let seen = ref S.empty in let rec go t = if S.mem t !seen then None else diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index 40b9389f1e3..dd4b09bba83 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -533,7 +533,7 @@ let compile_string mode s name : compile_result = let interpret_ir_prog inp_env libs progs = let prelude_ir = Lowering.Desugar.transform prelude in let name = name_progs progs in - Flags.compile_mode := Some Flags.WasmMode; (* REMOVE THIS HACK *) + Flags.compile_mode := Flags.WasmMode; (* REMOVE THIS HACK *) let prog_ir = lower_prog Flags.WasmMode initial_stat_env inp_env libs progs name in phase "Interpreting" name; let open Interpret_ir in diff --git a/test/run-drun/ok/idl-func.tc.ok b/test/run-drun/ok/idl-func.comp.ok similarity index 100% rename from test/run-drun/ok/idl-func.tc.ok rename to test/run-drun/ok/idl-func.comp.ok diff --git a/test/run-drun/ok/idl-func.tc.ret.ok b/test/run-drun/ok/idl-func.comp.ret.ok similarity index 100% rename from test/run-drun/ok/idl-func.tc.ret.ok rename to test/run-drun/ok/idl-func.comp.ret.ok diff --git a/test/run-drun/ok/unsupported.tc.ok b/test/run-drun/ok/unsupported.comp.ok similarity index 97% rename from test/run-drun/ok/unsupported.tc.ok rename to test/run-drun/ok/unsupported.comp.ok index 15fb6b8cfa8..fa8f5d395b1 100644 --- a/test/run-drun/ok/unsupported.tc.ok +++ b/test/run-drun/ok/unsupported.comp.ok @@ -48,7 +48,7 @@ unsupported.mo:62.3-62.35: type error, actor classes are not supported; use an a (This is a limitation of the current version.) unsupported.mo:66.45-66.53: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program (This is a limitation of the current version.) -unsupported.mo:70.29-70.37: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program +unsupported.mo:70.37-70.45: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program (This is a limitation of the current version.) unsupported.mo:76.34-76.37: type error, freestanding async expression not yet supported (This is a limitation of the current version.) diff --git a/test/run-drun/ok/unsupported.tc.ret.ok b/test/run-drun/ok/unsupported.comp.ret.ok similarity index 100% rename from test/run-drun/ok/unsupported.tc.ret.ok rename to test/run-drun/ok/unsupported.comp.ret.ok diff --git a/test/run-drun/unsupported.mo b/test/run-drun/unsupported.mo index bc1d44419b2..b31f825c639 100644 --- a/test/run-drun/unsupported.mo +++ b/test/run-drun/unsupported.mo @@ -24,7 +24,7 @@ actor Counter { }; public func bad_await() : async () { - let t : async Int = loop {}; + let t : async () = loop {}; await t; // unsupported general await }; @@ -67,7 +67,7 @@ func local_spawn() { }; { - let bad_nested_actor = { actor {}; ()}; + let bad_nested_actor = { let _ = actor {}; ()}; }; From 2ee194b449a2567f3406dc316b2943a1eb17e7d2 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 6 Nov 2019 17:53:18 +0000 Subject: [PATCH 0517/1176] fix ICReply/Reject prims to go through scheduler (#833) --- src/ir_interpreter/interpret_ir.ml | 4 ++-- test/run-dfinity/ok/await.diff-low.ok | 10 ---------- test/run-dfinity/ok/await.run-low.ok | 4 ++-- 3 files changed, 4 insertions(+), 14 deletions(-) delete mode 100644 test/run-dfinity/ok/await.diff-low.ok diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index 3062f6b5b86..ca04765ba2f 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -373,11 +373,11 @@ and interpret_exp_mut env exp (k : V.value V.cont) = | ICReplyPrim ts, [exp1] -> assert (not env.flavor.has_async_typ); let reply = Lib.Option.value env.replies in - interpret_exp env exp1 reply + interpret_exp env exp1 (fun v -> Scheduler.queue (fun () -> reply v)) | ICRejectPrim, [exp1] -> assert (not env.flavor.has_async_typ); let reject = Lib.Option.value env.rejects in - interpret_exp env exp1 reject + interpret_exp env exp1 (fun v -> Scheduler.queue (fun () -> reject v)) | ICCallPrim, [exp1; exp2; expk ; expr] -> assert (not env.flavor.has_async_typ); interpret_exp env exp1 (fun v1 -> diff --git a/test/run-dfinity/ok/await.diff-low.ok b/test/run-dfinity/ok/await.diff-low.ok deleted file mode 100644 index a0aeb94fab4..00000000000 --- a/test/run-dfinity/ok/await.diff-low.ok +++ /dev/null @@ -1,10 +0,0 @@ ---- await.run -+++ await.run-low -@@ -8,5 +8,5 @@ - cnt: 7 i: 6 - cnt: 8 i: 11 - .cnt: 9 i: 7 --cnt: 10 i: 12 --e-exitg-exit -+e-exitcnt: 10 i: 12 -+g-exit diff --git a/test/run-dfinity/ok/await.run-low.ok b/test/run-dfinity/ok/await.run-low.ok index 4ec00e441ce..731730721c0 100644 --- a/test/run-dfinity/ok/await.run-low.ok +++ b/test/run-dfinity/ok/await.run-low.ok @@ -8,5 +8,5 @@ cnt: 5 i: 10 cnt: 7 i: 6 cnt: 8 i: 11 .cnt: 9 i: 7 -e-exitcnt: 10 i: 12 -g-exit +cnt: 10 i: 12 +e-exitg-exit From b5573dfceaf963256d244eb1e9f5468415f1678b Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 6 Nov 2019 20:20:16 +0100 Subject: [PATCH 0518/1176] =?UTF-8?q?Build=20ocaml=20programs=20(moc,?= =?UTF-8?q?=E2=80=A6)=20statically=20(#823)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Linux, we can build ocaml binaries statically, so that the resulting binary works on all linux distributions, without any complex or fragile bundling into self-extracting binaries. So let’s do that for release builds. Building in `nix-shell` is unaffected (this also means that running `make` in `src` in a “normal” opam environment will work as before). On Darwin, we use `nix/standalone-darwin.nix` to make sure we fetch system libraries from, well, the system. This is copied from https://github.com/dfinity-lab/common/blob/master/nix/overlays/standalone/darwin.nix It is copied verbatin, so easy to update, but does not couple the repositories (important for eventual open sourcing) --- default.nix | 208 ++++++++++++++-------------- nix/ocaml-bisect_ppx-ocamlbuild.nix | 32 ----- nix/ocaml-bisect_ppx.nix | 33 ----- nix/standalone-darwin.nix | 102 ++++++++++++++ src/dune | 1 + 5 files changed, 205 insertions(+), 171 deletions(-) delete mode 100644 nix/ocaml-bisect_ppx-ocamlbuild.nix delete mode 100644 nix/ocaml-bisect_ppx.nix create mode 100644 nix/standalone-darwin.nix diff --git a/default.nix b/default.nix index 324cbcfbe95..1d1cff5abac 100644 --- a/default.nix +++ b/default.nix @@ -11,19 +11,6 @@ let stdenv = nixpkgs.stdenv; in let subpath = p: import ./nix/gitSource.nix p; in -let ocaml_wasm = import ./nix/ocaml-wasm.nix { - inherit (nixpkgs) stdenv fetchFromGitHub ocaml; - inherit (nixpkgs.ocamlPackages) findlib ocamlbuild; -}; in - -let ocaml_vlq = import ./nix/ocaml-vlq.nix { - inherit (nixpkgs) stdenv fetchFromGitHub ocaml dune; - inherit (nixpkgs.ocamlPackages) findlib; -}; in - -let ocaml_bisect_ppx = import ./nix/ocaml-bisect_ppx.nix nixpkgs; in -let ocaml_bisect_ppx-ocamlbuild = import ./nix/ocaml-bisect_ppx-ocamlbuild.nix nixpkgs; in - let dev = import (builtins.fetchGit { url = "ssh://git@github.com/dfinity-lab/dev"; # ref = "master"; @@ -153,27 +140,6 @@ let haskellPackages = nixpkgs.haskellPackages.override { }) {}; }; }; in - -let commonBuildInputs = [ - nixpkgs.ocaml - nixpkgs.dune - nixpkgs.ocamlPackages.atdgen - nixpkgs.ocamlPackages.findlib - nixpkgs.ocamlPackages.menhir - nixpkgs.ocamlPackages.num - nixpkgs.ocamlPackages.stdint - ocaml_wasm - ocaml_vlq - nixpkgs.ocamlPackages.zarith - nixpkgs.ocamlPackages.yojson - nixpkgs.ocamlPackages.ppxlib - nixpkgs.ocamlPackages.ppx_inline_test - ocaml_bisect_ppx - ocaml_bisect_ppx-ocamlbuild - nixpkgs.ocamlPackages.ocaml-migrate-parsetree - nixpkgs.ocamlPackages.ppx_tools_versioned -]; in - let libtommath = nixpkgs.fetchFromGitHub { owner = "libtom"; @@ -199,6 +165,91 @@ let ''; in +# When building for linux (but not in nix-shell) we build statically +# (We should probably just figure out how to use nix overlays to add this to nixpkgs) +let ocamlpkgs = + if nixpkgs.stdenv.isDarwin + then nixpkgs + else nixpkgs.pkgsMusl; in + +let ocaml_wasm_static = + import ./nix/ocaml-wasm.nix { + inherit (ocamlpkgs) stdenv fetchFromGitHub ocaml; + inherit (ocamlpkgs.ocamlPackages) findlib ocamlbuild; + }; in + +# This branches on the pkgs, which is either +# normal nixpkgs (nix-shell, darwin) +# nixpkgs.pkgsMusl for static building (release builds) +let commonBuildInputs = pkgs: + let ocaml_wasm = import ./nix/ocaml-wasm.nix { + inherit (pkgs) stdenv fetchFromGitHub ocaml; + inherit (pkgs.ocamlPackages) findlib ocamlbuild; + }; in + + let ocaml_vlq = import ./nix/ocaml-vlq.nix { + inherit (pkgs) stdenv fetchFromGitHub ocaml dune; + inherit (pkgs.ocamlPackages) findlib; + }; in + + [ + pkgs.ocaml + pkgs.dune + pkgs.ocamlPackages.atdgen + pkgs.ocamlPackages.findlib + pkgs.ocamlPackages.menhir + pkgs.ocamlPackages.num + pkgs.ocamlPackages.stdint + ocaml_wasm + ocaml_vlq + pkgs.ocamlPackages.zarith + pkgs.ocamlPackages.yojson + pkgs.ocamlPackages.ppxlib + pkgs.ocamlPackages.ppx_inline_test + pkgs.ocamlPackages.bisect_ppx + pkgs.ocamlPackages.bisect_ppx-ocamlbuild + pkgs.ocamlPackages.ocaml-migrate-parsetree + pkgs.ocamlPackages.ppx_tools_versioned + ]; in + +let darwin_standalone = + import nix/standalone-darwin.nix { + inherit (nixpkgs) runCommandNoCC stdenv removeReferencesTo lib; + grep = nixpkgs.gnugrep; + }; in + +let ocaml_exe = name: bin: + let + profile = + if nixpkgs.stdenv.isDarwin + then "release" + else "release-static"; + + drv = ocamlpkgs.stdenv.mkDerivation { + inherit name; + + ${if nixpkgs.stdenv.isDarwin then null else "allowedRequisites"} = []; + + src = subpath ./src; + + buildInputs = commonBuildInputs ocamlpkgs; + + buildPhase = '' + make DUNE_OPTS="--display=short --profile ${profile}" ${bin} + ''; + + installPhase = '' + mkdir -p $out/bin + cp --verbose --dereference ${bin} $out/bin + ''; + }; + in + # Make standalone on darwin (nothing to do on linux, is static) + if nixpkgs.stdenv.isDarwin + then darwin_standalone { inherit drv; exename = bin; } + else drv; +in + rec { rts = stdenv.mkDerivation { name = "moc-rts"; @@ -225,22 +276,11 @@ rec { ''; }; - moc-bin = stdenv.mkDerivation { - name = "moc-bin"; - - src = subpath ./src; - - buildInputs = commonBuildInputs; - - buildPhase = '' - make DUNE_OPTS="--display=short --profile release" moc mo-ld - ''; - - installPhase = '' - mkdir -p $out/bin - cp --verbose --dereference moc mo-ld $out/bin - ''; - }; + moc-bin = ocaml_exe "moc-bin" "moc"; + mo-ld = ocaml_exe "mo-ld" "mo-ld"; + mo-ide = ocaml_exe "mo-ide" "mo-ide"; + didc = ocaml_exe "didc" "didc"; + deser = ocaml_exe "deser" "deser"; moc = nixpkgs.symlinkJoin { name = "moc"; @@ -271,9 +311,10 @@ rec { src = subpath ./test; buildInputs = [ moc + mo-ld didc deser - ocaml_wasm + ocaml_wasm_static nixpkgs.wabt nixpkgs.bash nixpkgs.perl @@ -314,12 +355,12 @@ rec { ''; }; - unit-tests = stdenv.mkDerivation { + unit-tests = ocamlpkgs.stdenv.mkDerivation { name = "unit-tests"; src = subpath ./src; - buildInputs = commonBuildInputs; + buildInputs = commonBuildInputs ocamlpkgs; buildPhase = '' make DUNE_OPTS="--display=short" unit-tests @@ -330,30 +371,13 @@ rec { ''; }; - mo-ide = stdenv.mkDerivation { - name = "mo-ide"; - - src = subpath ./src; - - buildInputs = commonBuildInputs; - - buildPhase = '' - make DUNE_OPTS="--display=short --profile release" mo-ide - ''; - - installPhase = '' - mkdir -p $out/bin - cp --verbose --dereference mo-ide $out/bin - ''; - }; - samples = stdenv.mkDerivation { name = "samples"; src = subpath ./samples; buildInputs = [ moc didc - ocaml_wasm + ocaml_wasm_static nixpkgs.wabt nixpkgs.bash nixpkgs.perl @@ -372,10 +396,12 @@ rec { ''; }; - js = moc-bin.overrideAttrs (oldAttrs: { + js = stdenv.mkDerivation { name = "moc.js"; - buildInputs = commonBuildInputs ++ [ + src = subpath ./src; + + buildInputs = commonBuildInputs nixpkgs ++ [ nixpkgs.ocamlPackages.js_of_ocaml nixpkgs.ocamlPackages.js_of_ocaml-ocamlbuild nixpkgs.ocamlPackages.js_of_ocaml-ppx @@ -397,36 +423,9 @@ rec { installCheckPhase = '' NODE_PATH=$out node --experimental-wasm-mut-global --experimental-wasm-mv ${./test/node-test.js} ''; - - }); - - didc = stdenv.mkDerivation { - name = "didc"; - src = subpath ./src; - buildInputs = commonBuildInputs; - buildPhase = '' - make DUNE_OPTS="--display=short --profile release" didc - ''; - installPhase = '' - mkdir -p $out/bin - cp --verbose --dereference didc $out/bin - ''; - }; - - deser = stdenv.mkDerivation { - name = "deser"; - src = subpath ./src; - buildInputs = commonBuildInputs; - buildPhase = '' - make DUNE_OPTS="--display=short --profile release" deser - ''; - installPhase = '' - mkdir -p $out/bin - cp --verbose --dereference deser $out/bin - ''; }; - wasm = ocaml_wasm; + wasm = ocaml_wasm_static; dvm = real-dvm; drun = real-drun; filecheck = nixpkgs.linkFarm "FileCheck" @@ -574,12 +573,9 @@ rec { buildInputs = let dont_build = [ moc didc deser ]; in nixpkgs.lib.lists.unique (builtins.filter (i: !(builtins.elem i dont_build)) ( - moc-bin.buildInputs ++ - js.buildInputs ++ + commonBuildInputs nixpkgs ++ rts.buildInputs ++ - didc.buildInputs ++ - deser.buildInputs ++ - tests.buildInputs ++ + js.buildInputs ++ users-guide.buildInputs ++ [ nixpkgs.ncurses nixpkgs.ocamlPackages.merlin nixpkgs.ocamlPackages.utop ] )); diff --git a/nix/ocaml-bisect_ppx-ocamlbuild.nix b/nix/ocaml-bisect_ppx-ocamlbuild.nix deleted file mode 100644 index 9dd8315981d..00000000000 --- a/nix/ocaml-bisect_ppx-ocamlbuild.nix +++ /dev/null @@ -1,32 +0,0 @@ -pkgs: - -let version = "1.4.0"; in - -pkgs.stdenv.mkDerivation { - name = "ocaml${pkgs.ocaml.version}-bisect_ppx-ocamlbuild-${version}"; - - src = pkgs.fetchFromGitHub { - owner = "aantron"; - repo = "bisect_ppx"; - rev = version; - sha256 = "1plhm4pvrhpapz5zaks194ji1fgzmp13y942g10pbn9m7kgkqg4h"; - }; - - buildInputs = [ - pkgs.ocaml - pkgs.dune - pkgs.ocamlPackages.findlib - pkgs.ocamlPackages.ocamlbuild - ]; - - buildPhase = "dune build -p bisect_ppx-ocamlbuild"; - - inherit (pkgs.dune) installPhase; - - meta = { - homepage = https://github.com/aantron/bisect_ppx; - platforms = pkgs.ocaml.meta.platforms or []; - description = "Code coverage for OCaml"; - license = pkgs.stdenv.lib.licenses.mpl20; - }; -} diff --git a/nix/ocaml-bisect_ppx.nix b/nix/ocaml-bisect_ppx.nix deleted file mode 100644 index c1a3030a92f..00000000000 --- a/nix/ocaml-bisect_ppx.nix +++ /dev/null @@ -1,33 +0,0 @@ -pkgs: - -let version = "1.4.0"; in - -pkgs.stdenv.mkDerivation { - name = "ocaml${pkgs.ocaml.version}-bisect_ppx-${version}"; - - src = pkgs.fetchFromGitHub { - owner = "aantron"; - repo = "bisect_ppx"; - rev = version; - sha256 = "1plhm4pvrhpapz5zaks194ji1fgzmp13y942g10pbn9m7kgkqg4h"; - }; - - buildInputs = [ - pkgs.ocaml - pkgs.dune - pkgs.ocamlPackages.findlib - pkgs.ocamlPackages.ocaml-migrate-parsetree - pkgs.ocamlPackages.ppx_tools_versioned - ]; - - buildPhase = "dune build -p bisect_ppx"; - - inherit (pkgs.dune) installPhase; - - meta = { - homepage = https://github.com/aantron/bisect_ppx; - platforms = pkgs.ocaml.meta.platforms or []; - description = "Code coverage for OCaml"; - license = pkgs.stdenv.lib.licenses.mpl20; - }; -} diff --git a/nix/standalone-darwin.nix b/nix/standalone-darwin.nix new file mode 100644 index 00000000000..bda5bcc0be2 --- /dev/null +++ b/nix/standalone-darwin.nix @@ -0,0 +1,102 @@ +{ runCommandNoCC +, stdenv +, grep +, removeReferencesTo +, lib +}: + +{ drv +, exename +, extraBins ? [] +}: + +# on darwin we don't support shipping extra binaries +assert extraBins == []; + +# these are (1) the references we're okay with getting rid of and the dynamic +# libs that we're fine with pulling from /usr/lib. These should be passed as +# arguments, but they're very generic and for now it's simpler to have them +# here. +let + allowStrippedRefs = [ "*-crates-io" "*-swift-corefoundation" ]; + allowBundledDeps = [ "libSystem*.dylib" "libresolv*.dylib" "libc++*.dylib" ]; +in + +# For simplicity we assume those aren't empty. Empty lists would be the case +# analysis. +assert allowStrippedRefs != []; +assert allowBundledDeps != []; + + # Create a standalone executable from the given rust executable. + # * drv: the base derivation + # * name: the executable name, e.g. /bin/ + # The output is placed in $out/bin/. + # This works in two steps: + # 1. Strip out dynamic libraries + # 2. Strip out other nix store references +runCommandNoCC "${exename}-mkstandalone" + { buildInputs = [ grep stdenv.cc removeReferencesTo ]; + inherit exename; + allowedRequisites = []; + } + '' + dir=$(mktemp -d) + exe=$dir/$exename + + cp ${drv}/bin/$exename $exe + + # Make sure we can patch the exe + chmod +w $exe + + # For all dynamic dependencies... + otool -L $exe \ + | grep --only-match '${builtins.storeDir}/\S*' > libs + while read lib; do + libname=$(basename $lib) + + case $libname in + # ... strip out the widespread ones by making the RPATH entries + # point to /usr/lib. + # XXX: We should be able to statically link libc++ although we've + # wasted ~ 2 eng/days already, so this is good enough for now. + # See: https://github.com/rust-lang/rust/issues/64612 + ${lib.concatStringsSep "|" allowBundledDeps}) + newlibname=/usr/lib/''${libname%%\.*}.''${libname##*\.} + echo "Found $libname:" + echo " $lib -> $newlibname" + install_name_tool -change "$lib" "$newlibname" $exe + ;; + *) + echo "Found unknown library: $libname ($lib)" + echo "Please handle this case." + exit 1 + ;; + esac + done deps + + while read dep; do + depname=$(basename $dep) + + case "$depname" in + ${lib.concatStringsSep "|" allowStrippedRefs}) + remove-references-to -t /nix/store/$depname $exe + ;; + *) + echo "Unknown dependency: $dep" + exit 1 + ;; + esac + done Date: Wed, 6 Nov 2019 21:30:25 +0100 Subject: [PATCH 0519/1176] Avoid IFD on hydra (#834) --- nix/gitSource.nix | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/nix/gitSource.nix b/nix/gitSource.nix index fea7f6cb544..2a652673a27 100644 --- a/nix/gitSource.nix +++ b/nix/gitSource.nix @@ -38,6 +38,9 @@ let has_prefix = prefix: s: prefix == builtins.substring 0 (builtins.stringLength prefix) s; + has_suffix = suffix: s: + let x1 = builtins.stringLength suffix - builtins.stringLength s; in + x1 >= 0 && suffix == builtins.substring x1 (builtins.stringLength s) s; remove_prefix = prefix: s: builtins.substring (builtins.stringLength prefix) @@ -45,9 +48,13 @@ let s; lines = s: filter (x : x != [] && x != "") (split "\n" s); + +# On hydra, checkouts are always clean, and we don't want to do IFD + isHydra = (builtins.tryEval ).success; + not_dot_git = p: t: !(has_suffix ".git" p); in -if builtins.pathExists ../.git +if !isHydra && builtins.pathExists ../.git then let nixpkgs = (import ./nixpkgs.nix).nixpkgs {}; @@ -91,9 +98,10 @@ else # `builtins.fetchGit` then the source is extracted to /nix/store without a # .git directory, but in this case we know that it is clean, so do not warn warn_unless - (has_prefix "/nix/store" (toString ../.)) + (isHydra || has_prefix "/nix/store" (toString ../.)) "gitSource.nix: ${toString ../.} does not seem to be a git repository,\nassuming it is a clean checkout." (subdir: path { name = baseNameOf (toString subdir); path = if isString subdir then (../. + "/${subdir}") else subdir; + filter = not_dot_git; }) From cf0bcd55ad9fc7cdd451bdeb9a7606c6b3615173 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity <48968912+chenyan-dfinity@users.noreply.github.com> Date: Thu, 7 Nov 2019 02:24:58 -0800 Subject: [PATCH 0520/1176] Identifier escape (#829) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * identifier escape * Rewrite section “Identifier escape” (#830) --- design/IDL-Motoko.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/design/IDL-Motoko.md b/design/IDL-Motoko.md index ede21b917c6..140d53e63dd 100644 --- a/design/IDL-Motoko.md +++ b/design/IDL-Motoko.md @@ -241,6 +241,20 @@ These mappings should be straight-forward, given the following clarifications: * Characters (of type `Char`) are mapped to their Unicode scalar as a `nat32`. Decoding a `nat32` that is not a valid Unicode scalar fails. +## Type name mangling + +The name of type definition or services are irrelevant with regard to whether +the resulting imported/exported types are correct, as both Motoko and IDL +employ structural typing. Nevertheless, when the type export or import has to +produce such identifiers, it tries to preserve the original name. This is a +best effort approach. + +If it happens that such a name is invalid (e.g. reserved) in the target +language, a `"_"` is appended during translation. + +Conversely, a name of the form ` "_"` is translated to ``, if the +latter is legal in the target language. + ## Work flows The mapping specified here can be used to support the following use-cases. The From ef5fd079c280b5a314f78ee1ef2706d7defae1e6 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 7 Nov 2019 13:05:19 +0100 Subject: [PATCH 0521/1176] Use custom field hash and check for collisions (#759) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Use custom field hash and check for collisions this fixes the “implements” portion of #733. Because type fields are erased, we ignore those. * Ir: Also check for hash collisions * Check_IR NewObjE: Check type validity of inferred type --- src/codegen/compile.ml | 14 ++++----- src/ir_def/check_ir.ml | 20 ++++++++++++- src/lib/lib.ml | 4 +++ src/lib/lib.mli | 2 ++ src/mo_frontend/typing.ml | 24 ++++++++++----- src/mo_types/hash.ml | 15 ++++++++++ src/mo_types/hash.mli | 1 + test/fail/duplicate-field.mo | 48 +++++++++++++++++++++++++++++- test/fail/ok/duplicate-field.tc.ok | 8 +++++ 9 files changed, 117 insertions(+), 19 deletions(-) create mode 100644 src/mo_types/hash.ml create mode 100644 src/mo_types/hash.mli diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index f7c03b1a919..be70614ffa1 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -1260,8 +1260,8 @@ module Variant = struct let tag_field = Tagged.header_size let payload_field = Int32.add Tagged.header_size 1l - let hash_variant_label : Mo_types.Type.lab -> int32 = fun l -> - Int32.of_int (Hashtbl.hash l) + let hash_variant_label : Mo_types.Type.lab -> int32 = + Mo_types.Hash.hash let inject env l e = Tagged.obj env Tagged.Variant [compile_unboxed_const (hash_variant_label l); e] @@ -2424,10 +2424,6 @@ module Object = struct (* Number of object fields *) let size_field = Int32.add Tagged.header_size 0l - (* We use the same hashing function as Ocaml would *) - let hash_field_name s = - Int32.of_int (Hashtbl.hash s) - module FieldEnv = Env.Make(String) (* This is for non-recursive objects, i.e. ObjNewE *) @@ -2439,7 +2435,7 @@ module Object = struct then we need to allocate separate boxes for the non-public ones: List.filter (fun (_, vis, f) -> vis.it = Public) |> *) - List.map (fun (n,_) -> (hash_field_name n, n)) |> + List.map (fun (n,_) -> (Mo_types.Hash.hash n, n)) |> List.sort compare |> List.mapi (fun i (_h,n) -> (n,Int32.of_int i)) |> List.fold_left (fun m (n,i) -> FieldEnv.add n i m) FieldEnv.empty in @@ -2471,7 +2467,7 @@ module Object = struct let init_field (name, mk_is) : G.t = (* Write the hash *) get_ri ^^ - compile_unboxed_const (hash_field_name name) ^^ + compile_unboxed_const (Mo_types.Hash.hash name) ^^ Heap.store_field (hash_position env name) ^^ (* Write the pointer to the indirection *) get_ri ^^ @@ -2533,7 +2529,7 @@ module Object = struct with Invalid_argument _ -> false let idx env obj_type name = - compile_unboxed_const (hash_field_name name) ^^ + compile_unboxed_const (Mo_types.Hash.hash name) ^^ idx_hash env (is_mut_field env obj_type name) let load_idx env obj_type f = diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 4bb6c12f5a9..b9da5dfed8c 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -119,6 +119,16 @@ let check_concrete env at t = check env at (T.concrete t) "message argument is not concrete:\n %s" (T.string_of_typ_expand t) +let check_field_hashes env what at = + Lib.List.iter_pairs + (fun x y -> + if not (T.is_typ x.T.typ) && not (T.is_typ y.T.typ) && + Hash.hash x.T.lab = Hash.hash y.T.lab + then error env at "field names %s and %s in %s type have colliding hashes" + x.T.lab y.T.lab what; + ) + + let rec check_typ env typ : unit = match typ with | T.Pre -> @@ -181,11 +191,13 @@ let rec check_typ env typ : unit = check_shared env no_region t' | T.Obj (sort, fields) -> List.iter (check_typ_field env (Some sort)) fields; + check_field_hashes env "object" no_region fields; (* fields strictly sorted (and) distinct *) if not (Lib.List.is_strictly_ordered T.compare_field fields) then error env no_region "object type's fields are not distinct and sorted %s" (T.string_of_typ typ) | T.Variant fields -> List.iter (check_typ_field env None) fields; + check_field_hashes env "variant" no_region fields; if not (Lib.List.is_strictly_ordered T.compare_field fields) then error env no_region "variant type's fields are not distinct and sorted %s" (T.string_of_typ typ) | T.Mut typ -> @@ -593,10 +605,16 @@ let rec check_exp env (exp:Ir.exp) : unit = (type_obj env'' T.Actor fs) <: (T.Obj (s0, val_tfs0)); t0 <: t; | NewObjE (s, fs, t0) -> + (* check object *) + let t1 = type_obj env s fs in + check_typ env t1; + + (* check annotation *) check (T.is_obj t0) "bad annotation (object type expected)"; let (s0, tfs0) = T.as_obj t0 in let val_tfs0 = List.filter (fun tf -> not (T.is_typ tf.T.typ)) tfs0 in - (type_obj env s fs) <: (T.Obj (s0, val_tfs0)); + t1 <: T.Obj (s0, val_tfs0); + t0 <: t (* Cases *) diff --git a/src/lib/lib.ml b/src/lib/lib.ml index 4fc9c150042..94404402787 100644 --- a/src/lib/lib.ml +++ b/src/lib/lib.ml @@ -231,6 +231,10 @@ struct match f x1 x2 with | -1 -> is_strictly_ordered f (x2::xs') | _ -> false + + let rec iter_pairs f = function + | [] -> () + | x::ys -> List.iter (fun y -> f x y) ys; iter_pairs f ys end module List32 = diff --git a/src/lib/lib.mli b/src/lib/lib.mli index 0f0503a6b1b..9cd858f1893 100644 --- a/src/lib/lib.mli +++ b/src/lib/lib.mli @@ -33,6 +33,8 @@ sig val compare : ('a -> 'a -> int) -> 'a list -> 'a list -> int val is_ordered : ('a -> 'a -> int) -> 'a list -> bool val is_strictly_ordered : ('a -> 'a -> int) -> 'a list -> bool + + val iter_pairs : ('a -> 'a -> unit) -> 'a list -> unit end module List32 : diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 8371b57d44f..5d59b005854 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -128,14 +128,13 @@ let disjoint_union env at fmt env1 env2 = (* Types *) -let check_ids env kind member ids = ignore - (List.fold_left - (fun dom id -> - if List.mem id.it dom - then error env id.at "duplicate %s name %s in %s type" member id.it kind - else id.it::dom - ) [] ids - ) +let check_ids env kind member ids = Lib.List.iter_pairs + (fun x y -> + if x.it = y.it + then error env y.at "duplicate %s name %s in %s type" member y.it kind; + if Hash.hash x.it = Hash.hash y.it + then error env y.at "%s names %s and %s in %s type have colliding hashes" member x.it y.it kind; + ) ids let infer_mut mut : T.typ -> T.typ = match mut.it with @@ -1408,6 +1407,15 @@ and object_of_scope env sort fields scope at = else tfs ) scope.Scope.val_env tfs in + + Lib.List.iter_pairs + (fun x y -> + if not (T.is_typ x.T.typ) && not (T.is_typ y.T.typ) && + Hash.hash x.T.lab = Hash.hash y.T.lab + then error env at "field names %s and %s in %sobject type have colliding hashes" + x.T.lab y.T.lab (T.string_of_obj_sort sort); + ) tfs'; + let t = T.Obj (sort, List.sort T.compare_field tfs') in let accessible_cons = gather_typ T.ConSet.empty t in let inaccessible_cons = T.ConSet.diff scope.Scope.con_env accessible_cons in diff --git a/src/mo_types/hash.ml b/src/mo_types/hash.ml new file mode 100644 index 00000000000..b389539a13d --- /dev/null +++ b/src/mo_types/hash.ml @@ -0,0 +1,15 @@ +(* +We hash field names using the following hash function, +which results in values [0..2^31-1] +*) + +let hash : string -> int32 = fun s -> + let open Int32 in + + logand (shift_right_logical minus_one 1) ( + List.fold_left + (fun s c -> add (mul s (of_int 223)) (of_int (Char.code c))) + zero + (Lib.String.explode s) + ) + diff --git a/src/mo_types/hash.mli b/src/mo_types/hash.mli new file mode 100644 index 00000000000..7471ca443af --- /dev/null +++ b/src/mo_types/hash.mli @@ -0,0 +1 @@ +val hash : string -> int32 diff --git a/test/fail/duplicate-field.mo b/test/fail/duplicate-field.mo index 66db44941ee..0dbd8e705f1 100644 --- a/test/fail/duplicate-field.mo +++ b/test/fail/duplicate-field.mo @@ -1,5 +1,51 @@ -actor class C() { +{ actor class C() { public func m() {}; public func n() {}; public func m() {}; // Illegal! +}; }; + +{ +type T = {foo : Int; foo: Bool} +}; + +{ +type T = {foo : Int; nxnnbkddcv: Bool} +}; + +{ +type T = {#foo : Int; #nxnnbkddcv: Bool} +}; + +{ +ignore({foo = 5; foo = true}); +}; + +{ +ignore({foo = 5; nxnnbkddcv = true}); +}; + +{ +ignore(object {public func foo() = (); public func nxnnbkddcv() = ()}); +}; + +{ +ignore(actor {public func foo() = (); public func nxnnbkddcv() = ()}); +}; + +{ +ignore(module {public func foo() = (); public func nxnnbkddcv() = ()}); +}; + +{ +// not a clash +ignore(module { + public let foo = 1; + public type foo = Int; + public type nxnnbkddcv = Nat +});}; + +{ +// not a clash +// syntax not supported yet +// type T = {type foo = Int; nxnnbkddcv: Bool} }; diff --git a/test/fail/ok/duplicate-field.tc.ok b/test/fail/ok/duplicate-field.tc.ok index 65b3f73815e..cf88c6968a6 100644 --- a/test/fail/ok/duplicate-field.tc.ok +++ b/test/fail/ok/duplicate-field.tc.ok @@ -1 +1,9 @@ duplicate-field.mo:4.15-4.16: type error, duplicate definition for m in block +duplicate-field.mo:8.22-8.25: type error, duplicate field name foo in object type +duplicate-field.mo:12.22-12.32: type error, field names foo and nxnnbkddcv in object type have colliding hashes +duplicate-field.mo:16.23-16.34: type error, tag names foo and nxnnbkddcv in variant type have colliding hashes +duplicate-field.mo:20.18-20.21: type error, duplicate definition for foo in block +duplicate-field.mo:24.8-24.36: type error, field names nxnnbkddcv and foo in object type have colliding hashes +duplicate-field.mo:28.8-28.70: type error, field names nxnnbkddcv and foo in object type have colliding hashes +duplicate-field.mo:32.8-32.69: type error, field names nxnnbkddcv and foo in actor object type have colliding hashes +duplicate-field.mo:36.8-36.70: type error, field names nxnnbkddcv and foo in module object type have colliding hashes From aa7a407daf20f4615eec59ad161bff92a4212cba Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 7 Nov 2019 13:08:57 +0100 Subject: [PATCH 0522/1176] Set LOCALE_ARCHIVE only when `glibcLocales` is present (#836) * Set LOCALE_ARCHIVE only when `glibcLocales` is present it seems that #818 (which @kritzcreek needed) broke the nix-shell for darwin users. * Also add test dependencies back to nix-shell --- default.nix | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/default.nix b/default.nix index 1d1cff5abac..aefedbc889c 100644 --- a/default.nix +++ b/default.nix @@ -571,10 +571,11 @@ rec { # buildInputs = - let dont_build = [ moc didc deser ]; in + let dont_build = [ moc mo-ld didc deser ]; in nixpkgs.lib.lists.unique (builtins.filter (i: !(builtins.elem i dont_build)) ( commonBuildInputs nixpkgs ++ rts.buildInputs ++ + tests.buildInputs ++ js.buildInputs ++ users-guide.buildInputs ++ [ nixpkgs.ncurses nixpkgs.ocamlPackages.merlin nixpkgs.ocamlPackages.utop ] @@ -585,7 +586,7 @@ rec { JS_USER_LIBRARY=js-user-library; TOMMATHSRC = libtommath; NIX_FONTCONFIG_FILE = users-guide.NIX_FONTCONFIG_FILE; - LOCALE_ARCHIVE="${nixpkgs.glibcLocales}/lib/locale/locale-archive"; + ${if nixpkgs ? glibcLocales then "LOCALE_ARCHIVE" else null} ="${nixpkgs.glibcLocales}/lib/locale/locale-archive"; } else null; } From 3277b5769f7575fb61fdad40baebf3324d632f99 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Thu, 7 Nov 2019 22:02:36 +0000 Subject: [PATCH 0523/1176] Type ICReply/Reject as Non & refactor async translation (#835) ttype ICReject/Reply as exiting with Non, and cleanup async translation removing Platform type and other indirections, using mode parameter, not global flag. --- src/ir_def/check_ir.ml | 18 +- src/ir_def/construct.ml | 4 +- src/ir_interpreter/interpret_ir.ml | 8 +- src/ir_passes/async.ml | 345 ++++++++++++++--------------- src/ir_passes/async.mli | 7 +- src/ir_passes/dune | 2 +- src/pipeline/pipeline.ml | 3 +- 7 files changed, 175 insertions(+), 212 deletions(-) diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index aebcf035a8f..28bb37fbb96 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -358,12 +358,12 @@ let rec check_exp env (exp:Ir.exp) : unit = (* TODO: check against expected reply typ; note this may not be env.ret_tys. *) check_exp env exp1; typ exp1 <: (T.seq ts); - T.unit <: t + T.Non <: t | ICRejectPrim, [exp1] -> check (not (env.flavor.has_async_typ)) "ICRejectPrim in async flavor"; check_exp env exp1; typ exp1 <: T.text; - T.unit <: t + T.Non <: t | ICErrorCodePrim, [] -> T.Prim (T.Int32) <: t | ICCallPrim, [exp1; exp2; k; r] -> @@ -373,20 +373,6 @@ let rec check_exp env (exp:Ir.exp) : unit = check_exp env r; let t1 = T.promote (typ exp1) in begin match t1 with - (* TODO: oneways *) -(* - | T.Func (sort, T.Promises p, [], arg_tys, [T.Async ret_ty]) -> - check_exp env exp2; - let t_arg = T.seq arg_tys in - let t_rets = if (p = 1) then [ret_ty] else T.as_seq ret_ty in - if T.is_shared_sort sort then begin - check_concrete env exp.at t_arg; - check_concrete env exp.at ret_ty; - end; - typ exp2 <: t_arg; - typ k <: T.Func (T.Local, T.Returns, [], t_rets, []); - typ r <: T.Func (T.Local, T.Returns, [], [T.catch], []); -*) | T.Func (sort, T.Replies, [], arg_tys, ret_tys) -> check_exp env exp2; let t_arg = T.seq arg_tys in diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index 34afcf32d11..1b58e0c46f9 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -78,8 +78,8 @@ let seqP ps = let primE prim es = let ty = match prim with | ShowPrim _ -> T.text - | ICReplyPrim _ -> T.unit - | ICRejectPrim -> T.unit + | ICReplyPrim _ -> T.Non + | ICRejectPrim -> T.Non | ICErrorCodePrim -> T.Prim T.Int32 | _ -> assert false (* implement more as needed *) in diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index ca04765ba2f..0b0ff98bd93 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -236,7 +236,7 @@ let make_message env x cc v : V.value = match cc.CC.control with | T.Returns -> make_unit_message env x v | T.Promises-> make_async_message env x v - | T.Replies -> make_replying_message env x v (* TBR *) + | T.Replies -> make_replying_message env x v (* Literals *) @@ -373,11 +373,13 @@ and interpret_exp_mut env exp (k : V.value V.cont) = | ICReplyPrim ts, [exp1] -> assert (not env.flavor.has_async_typ); let reply = Lib.Option.value env.replies in - interpret_exp env exp1 (fun v -> Scheduler.queue (fun () -> reply v)) + interpret_exp env exp1 + (fun v -> Scheduler.queue (fun () -> reply v)) | ICRejectPrim, [exp1] -> assert (not env.flavor.has_async_typ); let reject = Lib.Option.value env.rejects in - interpret_exp env exp1 (fun v -> Scheduler.queue (fun () -> reject v)) + interpret_exp env exp1 + (fun v -> Scheduler.queue (fun () -> reject v)) | ICCallPrim, [exp1; exp2; expk ; expr] -> assert (not env.flavor.has_async_typ); interpret_exp env exp1 (fun v1 -> diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index 3ce3f2bb279..6759307f210 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -1,3 +1,4 @@ +open Mo_config open Mo_types open Ir_def @@ -20,20 +21,149 @@ open Construct a manifest tuple argument extended with a final reply continuation. *) -(* written as a functor so we can allocate some temporary shared state without making it global *) - -type platform = - V1 (* legacy, Haskell *) - | V2 (* new, Rust *) - -module Transform(Platform : sig val platform : platform end) = struct - - let platform = Platform.platform - - module ConRenaming = E.Make(struct type t = T.con let compare = Con.compare end) - - (* the state *) +module ConRenaming = E.Make(struct type t = T.con let compare = Con.compare end) + +(* Helpers *) + +let error_codeE mode = + match mode with + | Flags.ICMode -> callE + (idE "@int32ToErrorCode" + (T.Func(T.Local,T.Returns,[],[T.Prim T.Int32],[T.Variant T.catchErrorCodes]))) + [] + (ic_error_codeE()) + | _ -> { it = TagE ("error", tupE []); + at = no_region; + note = { + note_typ = T.Variant (T.catchErrorCodes); + note_eff = T.Triv } + } + +let errorMessageE e = +{ it = PrimE (OtherPrim "errorMessage", [e]); + at = no_region; + note = { note_typ = T.text; note_eff = eff e } +} + +let make_errorE e_code e_msg = +{ it = PrimE (OtherPrim "make_error", [e_code; e_msg]); + at = no_region; + note = { note_typ = T.Prim T.Error; note_eff = max (eff e_code) (eff e_msg) } +} + +let unary typ = [typ] + +let nary typ = T.as_seq typ + +let fulfillT as_seq typ = T.Func(T.Local, T.Returns, [], as_seq typ, []) + +let failT = T.Func(T.Local, T.Returns, [], [T.catch], []) + +let t_async as_seq t = + T.Func (T.Local, T.Returns, [], [fulfillT as_seq t; failT], []) + +let new_async_ret as_seq t = [t_async as_seq t; fulfillT as_seq t; failT] + +let new_asyncT = + T.Func ( + T.Local, + T.Returns, + [ { var = "T"; bound = T.Any } ], + [], + new_async_ret unary (T.Var ("T", 0)) + ) + +let new_asyncE = + idE "@new_async" new_asyncT + +let new_async t1 = + let call_new_async = callE new_asyncE [t1] (tupE []) in + let async = fresh_var "async" (typ (projE call_new_async 0)) in + let fulfill = fresh_var "fulfill" (typ (projE call_new_async 1)) in + let fail = fresh_var "fail" (typ (projE call_new_async 2)) in + (async, fulfill, fail), call_new_async + +let new_nary_async_reply mode ts1 = + (* The async implementation isn't n-ary *) + let t1 = T.seq ts1 in + let (unary_async, unary_fulfill, fail), call_new_async = new_async t1 in + let v' = fresh_var "v" t1 in + (* construct the n-ary async value, coercing the continuation, if necessary *) + let nary_async = + match ts1 with + | [t] -> + unary_async + | ts -> + let k' = fresh_var "k" (contT t1) in + let r' = fresh_var "r" err_contT in + let seq_of_v' = tupE (List.mapi (fun i _ -> projE v' i) ts) in + [k';r'] -->* (unary_async -*- (tupE[([v'] -->* (k' -*- seq_of_v'));r'])) + in + (* construct the n-ary reply callback that sends a sequence of values to fulfill the async *) + let nary_reply = + let vs,seq_of_vs = + match ts1 with + | [t] -> + let v = fresh_var "rep" t in + [v],v + | ts -> + let vs = fresh_vars "rep" ts in + vs, tupE vs + in + vs -->* (unary_fulfill -*- seq_of_vs) + in + (* construct the n-ary reject callback *) + let nary_reject = + let v = fresh_var "msg" T.text in + [v] -->* (fail -*- (make_errorE (error_codeE mode) v)) + in + let async,reply,reject = + fresh_var "async" (typ nary_async), + fresh_var "reply" (typ nary_reply), + fresh_var "reject" (typ nary_reject) + in + (async, reply, reject), + blockE [letP (tupP [varP unary_async; varP unary_fulfill; varP fail]) call_new_async] + (tupE [nary_async; nary_reply; nary_reject]) + +let letEta e scope = + match e.it with + | VarE _ -> scope e (* pure, so reduce *) + | _ -> let f = fresh_var "x" (typ e) in + letD f e :: (scope f) (* maybe impure; sequence *) + +let isAwaitableFunc exp = + match typ exp with + | T.Func (T.Shared _,T.Promises,_,_,_) -> true + | _ -> false + +(* Given sequence type ts, bind e of type (seq ts) to a + sequence of expressions supplied to decs d_of_es, + preserving effects of e when the sequence type is empty. + d_of_es must not duplicate or discard the evaluation of es. + *) +let letSeq ts e d_of_vs = + match ts with + | [] -> + (expD e)::d_of_vs [] + | [t] -> + let x = fresh_var "x" t in + let p = varP x in + (letP p e)::d_of_vs [x] + | ts -> + let xs = fresh_vars "x" ts in + let p = tupP (List.map varP xs) in + (letP p e)::d_of_vs (xs) + +(* The actual transformation *) + +let transform mode env prog = + + (* the state *) + let con_renaming = ref + (Type.ConSet.fold (fun c env -> ConRenaming.add c c env) + env.Scope.con_env ConRenaming.empty) (* maps constructors to new constructors (name name, new stamp, new kind) it is initialized with the type constructors defined outside here, which are not rewritten. @@ -41,154 +171,12 @@ module Transform(Platform : sig val platform : platform end) = struct If we run this translation on two program fragments (e.g. prelude and program) we would have to pass down the `con_renaming`. But this is simply the right thing to do for a pass that changes the context. - *) - - let con_renaming = ref ConRenaming.empty - - (* Explicit invocation of reply, reject and call System API functions; - implemented (as far as possible) for V1; - TBC for V2 *) - - let sys_replyE ts v = ic_replyE ts v - - let sys_rejectE e = ic_rejectE e - - let sys_callE v1 typs vs reply reject = - assert (typs = []); - ic_callE v1 (seqE vs) reply reject - - let sys_error_codeE () = - match platform with - | V1 -> { it = TagE ("error", tupE []); - at = no_region; - note = { - note_typ = T.Variant (T.catchErrorCodes); - note_eff = T.Triv } - } - | V2 -> callE - (idE "@int32ToErrorCode" - (T.Func(T.Local,T.Returns,[],[T.Prim T.Int32],[T.Variant T.catchErrorCodes]))) - [] - (ic_error_codeE()) - - let errorMessageE e = - { it = PrimE (OtherPrim "errorMessage", [e]); - at = no_region; - note = { note_typ = T.text; note_eff = eff e } - } - - let make_errorE e_code e_msg = - { it = PrimE (OtherPrim "make_error", [e_code; e_msg]); - at = no_region; - note = { note_typ = T.Prim T.Error; note_eff = max (eff e_code) (eff e_msg) } - } - - (* End of configuration *) - - let unary typ = [typ] - - let nary typ = T.as_seq typ - - let fulfillT as_seq typ = T.Func(T.Local, T.Returns, [], as_seq typ, []) - - let failT = T.Func(T.Local, T.Returns, [], [T.catch], []) - - let t_async as_seq t = - T.Func (T.Local, T.Returns, [], [fulfillT as_seq t; failT], []) - - let new_async_ret as_seq t = [t_async as_seq t; fulfillT as_seq t; failT] - - let new_asyncT = - T.Func ( - T.Local, - T.Returns, - [ { var = "T"; bound = T.Any } ], - [], - new_async_ret unary (T.Var ("T", 0)) - ) - - let new_asyncE = - idE "@new_async" new_asyncT - - let new_async t1 = - let call_new_async = callE new_asyncE [t1] (tupE []) in - let async = fresh_var "async" (typ (projE call_new_async 0)) in - let fulfill = fresh_var "fulfill" (typ (projE call_new_async 1)) in - let fail = fresh_var "fail" (typ (projE call_new_async 2)) in - (async, fulfill, fail), call_new_async - - let new_nary_async_reply ts1 = - (* The async implementation isn't n-ary *) - let t1 = T.seq ts1 in - let (unary_async, unary_fulfill, fail), call_new_async = new_async t1 in - let v' = fresh_var "v" t1 in - (* construct the n-ary async value, coercing the continuation, if necessary *) - let nary_async = - match ts1 with - | [t] -> - unary_async - | ts -> - let k' = fresh_var "k" (contT t1) in - let r' = fresh_var "r" err_contT in - let seq_of_v' = tupE (List.mapi (fun i _ -> projE v' i) ts) in - [k';r'] -->* (unary_async -*- (tupE[([v'] -->* (k' -*- seq_of_v'));r'])) - in - (* construct the n-ary reply callback that sends a sequence of values to fulfill the async *) - let nary_reply = - let vs,seq_of_vs = - match ts1 with - | [t] -> - let v = fresh_var "rep" t in - [v],v - | ts -> - let vs = fresh_vars "rep" ts in - vs, tupE vs - in - vs -->* (unary_fulfill -*- seq_of_vs) - in - (* construct the n-ary reject callback *) - let nary_reject = - let v = fresh_var "msg" T.text in - [v] -->* (fail -*- (make_errorE (sys_error_codeE()) v)) - in - let async,reply,reject = - fresh_var "async" (typ nary_async), - fresh_var "reply" (typ nary_reply), - fresh_var "reject" (typ nary_reject) - in - (async, reply, reject), - blockE [letP (tupP [varP unary_async; varP unary_fulfill; varP fail]) call_new_async] - (tupE [nary_async; nary_reply; nary_reject]) - - let letEta e scope = - match e.it with - | VarE _ -> scope e (* pure, so reduce *) - | _ -> let f = fresh_var "x" (typ e) in - letD f e :: (scope f) (* maybe impure; sequence *) - - let isAwaitableFunc exp = - match typ exp with - | T.Func (T.Shared _,T.Promises,_,_,_) -> true - | _ -> false - - (* Given sequence type ts, bind e of type (seq ts) to a - sequence of expressions supplied to decs d_of_es, - preserving effects of e when the sequence type is empty. - d_of_es must not duplicate or discard the evaluation of es. - *) - let letSeq ts e d_of_vs = - match ts with - | [] -> - (expD e)::d_of_vs [] - | [t] -> - let x = fresh_var "x" t in - let p = varP x in - (letP p e)::d_of_vs [x] - | ts -> - let xs = fresh_vars "x" ts in - let p = tupP (List.map varP xs) in - (letP p e)::d_of_vs (xs) + Eventually, pipeline will allow us to pass the con_renaming to downstream program + fragments, then we would simply start with an empty con_renaming and the prelude. + *) + in + let rec t_typ (t:T.typ) = match t with | T.Prim _ @@ -197,9 +185,9 @@ module Transform(Platform : sig val platform : platform end) = struct Con (t_con c, List.map t_typ ts) | Array t -> Array (t_typ t) | Tup ts -> Tup (List.map t_typ ts) - | Func (s, c, tbs, t1, t2) -> + | Func (s, c, tbs, ts1, ts2) -> let c' = if c = T.Promises then T.Replies else c in - Func (s, c', List.map t_bind tbs, List.map t_typ t1, List.map t_typ t2) + Func (s, c', List.map t_bind tbs, List.map t_typ ts1, List.map t_typ ts2) | Opt t -> Opt (t_typ t) | Variant fs -> Variant (List.map t_field fs) | Async t -> t_async nary (t_typ t) @@ -243,6 +231,7 @@ module Transform(Platform : sig val platform : platform end) = struct and t_field {lab; typ} = { lab; typ = t_typ typ } + in let rec t_exp (exp: exp) = { it = t_exp' exp; @@ -281,20 +270,21 @@ module Transform(Platform : sig val platform : platform end) = struct | t -> assert false in let post = fresh_var "post" (T.Func(T.Shared T.Write, T.Replies, [], [], ts1)) in let u = fresh_var "u" T.unit in - let ((nary_async, nary_reply, reject), def) = new_nary_async_reply ts1 in + let ((nary_async, nary_reply, reject), def) = new_nary_async_reply mode ts1 in (blockE [letP (tupP [varP nary_async; varP nary_reply; varP reject]) def; funcD post u ( let vs = fresh_vars "v" ts1 in - let k = vs -->* (sys_replyE ts1 (seqE vs)) in + let k = vs -->* (ic_replyE ts1 (seqE vs)) in let e = fresh_var "e" T.catch in - let r = [e] -->* (sys_rejectE (errorMessageE e)) in + let r = [e] -->* (ic_rejectE (errorMessageE e)) in (t_exp exp2) -*- tupE [k;r]); - expD (sys_callE post [] [] nary_reply reject); + expD (ic_callE post (seqE []) nary_reply reject); ] nary_async ).it | CallE (exp1, typs, exp2) when isAwaitableFunc exp1 -> + assert (typs = []); let ts1,ts2 = match typ exp1 with | T.Func (T.Shared _, T.Promises,tbs,ts1,ts2) -> @@ -303,13 +293,12 @@ module Transform(Platform : sig val platform : platform end) = struct in let exp1' = t_exp exp1 in let exp2' = t_exp exp2 in - let typs = List.map t_typ typs in - let ((nary_async, nary_reply, reject), def) = new_nary_async_reply ts2 in + let ((nary_async, nary_reply, reject), def) = new_nary_async_reply mode ts2 in let _ = letEta in (blockE ( letP (tupP [varP nary_async; varP nary_reply; varP reject]) def :: letEta exp1' (fun v1 -> letSeq ts1 exp2' (fun vs -> - [ expD (sys_callE v1 typs vs nary_reply reject) ] + [ expD (ic_callE v1 (seqE vs) nary_reply reject) ] ) ) ) @@ -374,9 +363,9 @@ module Transform(Platform : sig val platform : platform end) = struct (t_typ (T.seq ts1),t_typ contT) | t -> assert false in let v = fresh_var "v" t1 in - let k = v --> (sys_replyE ret_tys v) in + let k = v --> (ic_replyE ret_tys v) in let e = fresh_var "e" T.catch in - let r = [e] -->* (sys_rejectE (errorMessageE e)) in + let r = [e] -->* (ic_rejectE (errorMessageE e)) in let exp' = (t_exp cps) -*- tupE [k;r] in FuncE (x, T.Shared s', Replies, typbinds', args', ret_tys, exp') | Replies -> assert false @@ -437,16 +426,6 @@ module Transform(Platform : sig val platform : platform end) = struct and t_typ_binds typbinds = List.map t_typ_bind typbinds and t_prog (prog, flavor) = (t_block prog, { flavor with has_async_typ = false } ) +in + t_prog prog -end - -let transform platform = - let module T = Transform(struct let platform = platform end) in - fun env prog -> - (* - Initialized the con_renaming with those type constructors already in scope. - Eventually, pipeline will allow us to pass the con_renaming to downstream program - fragments, then we would simply start with an empty con_renaming and the prelude. - *) - Type.ConSet.iter (fun c -> T.con_renaming := T.ConRenaming.add c c (!T.con_renaming)) env.Scope.con_env; - T.t_prog prog diff --git a/src/ir_passes/async.mli b/src/ir_passes/async.mli index 40b6fa4e956..ff87eae2dd5 100644 --- a/src/ir_passes/async.mli +++ b/src/ir_passes/async.mli @@ -1,8 +1,5 @@ (* lower uses of async type appropriately *) open Ir_def -type platform = - V1 (* legacy, Haskell *) - | V2 (* new, Rust *) - -val transform : platform -> Mo_types.Scope.scope -> Ir.prog -> Ir.prog +val transform : + Mo_config.Flags.compile_mode -> Mo_types.Scope.scope -> Ir.prog -> Ir.prog diff --git a/src/ir_passes/dune b/src/ir_passes/dune index f21c8932d3f..e3a0a8ce05a 100644 --- a/src/ir_passes/dune +++ b/src/ir_passes/dune @@ -1,4 +1,4 @@ (library (name ir_passes) - (libraries lib ir_def) + (libraries lib mo_config ir_def) ) diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index 6b19dd65185..9a3f16e90c7 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -461,8 +461,7 @@ let await_lowering = transform_if "Await Lowering" (fun _ -> Await.transform) let async_lowering mode = - let platform = if mode = Flags.ICMode then Async.V2 else Async.V1 in - transform_if "Async Lowering" (Async.transform platform) + transform_if "Async Lowering" (Async.transform mode) let tailcall_optimization = transform_if "Tailcall optimization" (fun _ -> Tailcall.transform) From 1e20e88ab02dd5ecd6c498fadfe011ea3feec7da Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 8 Nov 2019 09:31:33 +0100 Subject: [PATCH 0524/1176] Pass name to fetchGit (#838) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit inspired by @hansl’s https://github.com/dfinity-lab/sdk/pull/149 --- default.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/default.nix b/default.nix index aefedbc889c..0595bc75c7f 100644 --- a/default.nix +++ b/default.nix @@ -12,18 +12,21 @@ let stdenv = nixpkgs.stdenv; in let subpath = p: import ./nix/gitSource.nix p; in let dev = import (builtins.fetchGit { + name = "dev-sources"; url = "ssh://git@github.com/dfinity-lab/dev"; # ref = "master"; rev = "6fca1936fcd027aaeaccab0beb51defeee38a0ff"; }) { system = nixpkgs.system; }; in let dfinity-repo = import (builtins.fetchGit { + name = "dfinity-sources"; url = "ssh://git@github.com/dfinity-lab/dfinity"; # ref = "master"; rev = "3c82c6400b0eb8c5785669996f5b8007623cd9fc"; }) { system = nixpkgs.system; }; in let sdk = import (builtins.fetchGit { + name = "sdk-sources"; url = "ssh://git@github.com/dfinity-lab/sdk"; ref = "paulyoung/js-user-library"; rev = "42f15621bc5b228c7fd349cb52f265917d33a3a0"; From 97b42665c6b81d331c51da35719455daa5f0062b Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 8 Nov 2019 13:44:40 +0100 Subject: [PATCH 0525/1176] Test runner: Allow skipping of certain steps useful if we have test cases that are very slow in the interpreter, and we only really care about the test with `drun`. --- test/run-drun/large-array.mo | 3 +++ test/run.sh | 19 ++++++++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/test/run-drun/large-array.mo b/test/run-drun/large-array.mo index 9c78a314ce4..b4c880c8860 100644 --- a/test/run-drun/large-array.mo +++ b/test/run-drun/large-array.mo @@ -4,3 +4,6 @@ // Should allocate 50MB (easier on CI) ignore(Array_init<()>(50*1024*1024/4, ())); +//SKIP run +//SKIP run-ir +//SKIP run-low diff --git a/test/run.sh b/test/run.sh index 8f9945469b6..bff1d5a1696 100755 --- a/test/run.sh +++ b/test/run.sh @@ -89,10 +89,13 @@ function normalize () { function run () { # first argument: extension of the output file # remaining argument: command line - # uses from scope: $out, $base, $diff_files + # uses from scope: $out, $file, $base, $diff_files local ext="$1" shift + + if grep -q "^//SKIP $ext" $file; then return; fi + $ECHO -n " [$ext]" "$@" >& $out/$base.$ext local ret=$? @@ -182,15 +185,21 @@ do run run-ir $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS -r -iR -no-async -no-await $base.mo # Diff interpretations without/with lowering - diff -u -N --label "$base.run" $out/$base.run --label "$base.run-ir" $out/$base.run-ir > $out/$base.diff-ir - diff_files="$diff_files $base.diff-ir" + if [ -e $out/$base.run -a -e $out/$base.run-ir ] + then + diff -u -N --label "$base.run" $out/$base.run --label "$base.run-ir" $out/$base.run-ir > $out/$base.diff-ir + diff_files="$diff_files $base.diff-ir" + fi # Interpret IR with lowering run run-low $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS -r -iR $base.mo # Diff interpretations without/with lowering - diff -u -N --label "$base.run" $out/$base.run --label "$base.run-low" $out/$base.run-low > $out/$base.diff-low - diff_files="$diff_files $base.diff-low" + if [ -e $out/$base.run -a -e $out/$base.run-low ] + then + diff -u -N --label "$base.run" $out/$base.run --label "$base.run-low" $out/$base.run-low > $out/$base.diff-low + diff_files="$diff_files $base.diff-low" + fi fi From b5519c9c0bf4dcd063f4891ee66aedfb59a2d583 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 8 Nov 2019 13:46:02 +0100 Subject: [PATCH 0526/1176] Actually test 1G allocation it is reasonably fast on `drun`. --- test/run-drun/large-array.mo | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/test/run-drun/large-array.mo b/test/run-drun/large-array.mo index b4c880c8860..f47f4924763 100644 --- a/test/run-drun/large-array.mo +++ b/test/run-drun/large-array.mo @@ -1,8 +1,5 @@ // Should allocate 1G -// ignore(Array_init<()>(1024*1024*1024/4, ())); - -// Should allocate 50MB (easier on CI) -ignore(Array_init<()>(50*1024*1024/4, ())); +ignore(Array_init<()>(1024*1024*1024/4, ())); //SKIP run //SKIP run-ir From b632da4af54f4452d8909d49b183f81db7554d1d Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 8 Nov 2019 14:17:31 +0100 Subject: [PATCH 0527/1176] Move haskellPackages into its own nix file just to keep `default.nix` a bit smaller --- default.nix | 93 +--------------------------------------- nix/haskell-packages.nix | 92 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+), 92 deletions(-) create mode 100644 nix/haskell-packages.nix diff --git a/default.nix b/default.nix index 0595bc75c7f..cd3382ac498 100644 --- a/default.nix +++ b/default.nix @@ -50,98 +50,7 @@ let real-drun = let js-user-library = sdk.js-user-library; in let haskellPackages = nixpkgs.haskellPackages.override { - overrides = self: super: { - haskell-lsp-types = self.callPackage - ({ mkDerivation, aeson, base, bytestring, data-default, deepseq - , filepath, hashable, lens, network-uri, scientific, text - , unordered-containers - }: - mkDerivation { - pname = "haskell-lsp-types"; - version = "0.16.0.0"; - sha256 = "14wlv54ydbddpw6cwgykcas3rb55w7m78q0s1wdbi594wg1bscqg"; - libraryHaskellDepends = [ - aeson base bytestring data-default deepseq filepath hashable lens - network-uri scientific text unordered-containers - ]; - description = "Haskell library for the Microsoft Language Server Protocol, data types"; - license = stdenv.lib.licenses.mit; - hydraPlatforms = stdenv.lib.platforms.none; - }) {}; - - rope-utf16-splay = self.callPackage - ({ mkDerivation, base, QuickCheck, tasty, tasty-hunit - , tasty-quickcheck, text - }: - mkDerivation { - pname = "rope-utf16-splay"; - version = "0.3.1.0"; - sha256 = "1ilcgwmdwqnp95vb7652fc03ji9dnzy6cm24pvbiwi2mhc4piy6b"; - libraryHaskellDepends = [ base text ]; - testHaskellDepends = [ - base QuickCheck tasty tasty-hunit tasty-quickcheck text - ]; - description = "Ropes optimised for updating using UTF-16 code units and row/column pairs"; - license = stdenv.lib.licenses.bsd3; - }) {}; - - haskell-lsp = self.callPackage - ({ mkDerivation, aeson, async, attoparsec, base, bytestring - , containers, data-default, directory, filepath, hashable - , haskell-lsp-types, hslogger, hspec, hspec-discover, lens, mtl - , network-uri, QuickCheck, quickcheck-instances, rope-utf16-splay - , sorted-list, stm, temporary, text, time, unordered-containers - }: - mkDerivation { - pname = "haskell-lsp"; - version = "0.16.0.0"; - sha256 = "1s04lfnb3c0g9bkwp4j7j59yw8ypps63dq27ayybynrfci4bpj95"; - isLibrary = true; - isExecutable = true; - libraryHaskellDepends = [ - aeson async attoparsec base bytestring containers data-default - directory filepath hashable haskell-lsp-types hslogger lens mtl - network-uri rope-utf16-splay sorted-list stm temporary text time - unordered-containers - ]; - testHaskellDepends = [ - aeson base bytestring containers data-default directory filepath - hashable hspec lens network-uri QuickCheck quickcheck-instances - rope-utf16-splay sorted-list stm text - ]; - testToolDepends = [ hspec-discover ]; - description = "Haskell library for the Microsoft Language Server Protocol"; - license = stdenv.lib.licenses.mit; - hydraPlatforms = stdenv.lib.platforms.none; - }) {}; - - lsp-test = self.callPackage - ({ mkDerivation, aeson, aeson-pretty, ansi-terminal, async, base - , bytestring, conduit, conduit-parse, containers, data-default - , Diff, directory, filepath, hspec, haskell-lsp, lens, mtl - , parser-combinators, process, rope-utf16-splay, text, transformers - , unix, unordered-containers - }: - mkDerivation { - pname = "lsp-test"; - version = "0.7.0.0"; - sha256 = "1lm299gbahrnwfrprhhpzxrmjljj33pps1gzz2wzmp3m9gzl1dx5"; - libraryHaskellDepends = [ - aeson aeson-pretty ansi-terminal async base bytestring conduit - conduit-parse containers data-default Diff directory filepath - haskell-lsp lens mtl parser-combinators process rope-utf16-splay - text transformers unix unordered-containers - ]; - doCheck = false; - testHaskellDepends = [ - aeson base data-default haskell-lsp hspec lens text - unordered-containers - ]; - description = "Functional test framework for LSP servers"; - license = stdenv.lib.licenses.bsd3; - hydraPlatforms = stdenv.lib.platforms.none; - }) {}; - }; + overrides = import nix/haskell-packages.nix stdenv; }; in let libtommath = nixpkgs.fetchFromGitHub { diff --git a/nix/haskell-packages.nix b/nix/haskell-packages.nix new file mode 100644 index 00000000000..854c84c650c --- /dev/null +++ b/nix/haskell-packages.nix @@ -0,0 +1,92 @@ +stdenv: self: super: { + haskell-lsp-types = self.callPackage + ({ mkDerivation, aeson, base, bytestring, data-default, deepseq + , filepath, hashable, lens, network-uri, scientific, text + , unordered-containers + }: + mkDerivation { + pname = "haskell-lsp-types"; + version = "0.16.0.0"; + sha256 = "14wlv54ydbddpw6cwgykcas3rb55w7m78q0s1wdbi594wg1bscqg"; + libraryHaskellDepends = [ + aeson base bytestring data-default deepseq filepath hashable lens + network-uri scientific text unordered-containers + ]; + description = "Haskell library for the Microsoft Language Server Protocol, data types"; + license = stdenv.lib.licenses.mit; + hydraPlatforms = stdenv.lib.platforms.none; + }) {}; + + rope-utf16-splay = self.callPackage + ({ mkDerivation, base, QuickCheck, tasty, tasty-hunit + , tasty-quickcheck, text + }: + mkDerivation { + pname = "rope-utf16-splay"; + version = "0.3.1.0"; + sha256 = "1ilcgwmdwqnp95vb7652fc03ji9dnzy6cm24pvbiwi2mhc4piy6b"; + libraryHaskellDepends = [ base text ]; + testHaskellDepends = [ + base QuickCheck tasty tasty-hunit tasty-quickcheck text + ]; + description = "Ropes optimised for updating using UTF-16 code units and row/column pairs"; + license = stdenv.lib.licenses.bsd3; + }) {}; + + haskell-lsp = self.callPackage + ({ mkDerivation, aeson, async, attoparsec, base, bytestring + , containers, data-default, directory, filepath, hashable + , haskell-lsp-types, hslogger, hspec, hspec-discover, lens, mtl + , network-uri, QuickCheck, quickcheck-instances, rope-utf16-splay + , sorted-list, stm, temporary, text, time, unordered-containers + }: + mkDerivation { + pname = "haskell-lsp"; + version = "0.16.0.0"; + sha256 = "1s04lfnb3c0g9bkwp4j7j59yw8ypps63dq27ayybynrfci4bpj95"; + isLibrary = true; + isExecutable = true; + libraryHaskellDepends = [ + aeson async attoparsec base bytestring containers data-default + directory filepath hashable haskell-lsp-types hslogger lens mtl + network-uri rope-utf16-splay sorted-list stm temporary text time + unordered-containers + ]; + testHaskellDepends = [ + aeson base bytestring containers data-default directory filepath + hashable hspec lens network-uri QuickCheck quickcheck-instances + rope-utf16-splay sorted-list stm text + ]; + testToolDepends = [ hspec-discover ]; + description = "Haskell library for the Microsoft Language Server Protocol"; + license = stdenv.lib.licenses.mit; + hydraPlatforms = stdenv.lib.platforms.none; + }) {}; + + lsp-test = self.callPackage + ({ mkDerivation, aeson, aeson-pretty, ansi-terminal, async, base + , bytestring, conduit, conduit-parse, containers, data-default + , Diff, directory, filepath, hspec, haskell-lsp, lens, mtl + , parser-combinators, process, rope-utf16-splay, text, transformers + , unix, unordered-containers + }: + mkDerivation { + pname = "lsp-test"; + version = "0.7.0.0"; + sha256 = "1lm299gbahrnwfrprhhpzxrmjljj33pps1gzz2wzmp3m9gzl1dx5"; + libraryHaskellDepends = [ + aeson aeson-pretty ansi-terminal async base bytestring conduit + conduit-parse containers data-default Diff directory filepath + haskell-lsp lens mtl parser-combinators process rope-utf16-splay + text transformers unix unordered-containers + ]; + doCheck = false; + testHaskellDepends = [ + aeson base data-default haskell-lsp hspec lens text + unordered-containers + ]; + description = "Functional test framework for LSP servers"; + license = stdenv.lib.licenses.bsd3; + hydraPlatforms = stdenv.lib.platforms.none; + }) {}; +} From eb73cf40fe19d3dbf84cf4fb7b36ffe307731e6b Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 8 Nov 2019 14:23:37 +0100 Subject: [PATCH 0528/1176] More shuffling around --- default.nix | 9 ++++----- nix/haskell-packages.nix | 4 ++++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/default.nix b/default.nix index cd3382ac498..6687f43508c 100644 --- a/default.nix +++ b/default.nix @@ -214,9 +214,8 @@ rec { ''; }; - lsp-int = haskellPackages.callCabal2nix "lsp-int" test/lsp-int { }; - - qc-motoko = haskellPackages.callCabal2nix "qc-motoko" test/random { }; + # “our” Haskell packages + inherit (haskellPackages) lsp-int qc-motoko; tests = stdenv.mkDerivation { name = "tests"; @@ -237,8 +236,8 @@ rec { js-user-library dvm drun - qc-motoko - lsp-int + haskellPackages.qc-motoko + haskellPackages.lsp-int esm ] ++ llvmBuildInputs; diff --git a/nix/haskell-packages.nix b/nix/haskell-packages.nix index 854c84c650c..1c9cd1287a5 100644 --- a/nix/haskell-packages.nix +++ b/nix/haskell-packages.nix @@ -89,4 +89,8 @@ stdenv: self: super: { license = stdenv.lib.licenses.bsd3; hydraPlatforms = stdenv.lib.platforms.none; }) {}; + + lsp-int = self.callCabal2nix "lsp-int" ../test/lsp-int { }; + + qc-motoko = self.callCabal2nix "qc-motoko" ../test/random { }; } From 34c4e129272b81651742e0d094c02d3ec662915e Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 8 Nov 2019 14:55:16 +0100 Subject: [PATCH 0529/1176] Update src/codegen/compile.ml Co-Authored-By: Claudio Russo --- src/codegen/compile.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 9cab12e58a0..a71a3a1d5ee 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -5015,7 +5015,7 @@ module FuncDec = struct message_cleanup env sort )) | Flags.AncientMode, Type.Promises -> assert false - | Flags.AncientMode, Type.Replies -> (* with callback *) + | Flags.AncientMode, Type.Replies -> (* with callbacks *) let ae0 = VarEnv.mk_fun_ae outer_ae in Func.of_body outer_env ["reply", I32Type; "databuf", I32Type; "elembuf", I32Type] [] (fun env -> G.with_region at ( let get_reply = G.i (LocalGet (nr 0l)) in From 2c6241849965fd7a30ba5885ac2ba735f8cb49d5 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 8 Nov 2019 14:57:52 +0100 Subject: [PATCH 0530/1176] Update src/ir_interpreter/interpret_ir.ml --- src/ir_interpreter/interpret_ir.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index 0b0ff98bd93..a95476f32ef 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -71,7 +71,7 @@ let find id env = let trace_depth = ref 0 let trace fmt = - Printf.ksprintf (fun s -> + Printf.ksprintf (fun s -> Printf.printf "%s%s\n%!" (String.make (2 * !trace_depth) ' ') s ) fmt From 752db9fd8bdad5b453747d87f02b3898f39b2530 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 8 Nov 2019 14:59:56 +0100 Subject: [PATCH 0531/1176] =?UTF-8?q?Add=20an=20=E2=80=9CIC=20stub?= =?UTF-8?q?=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit a pure implementation of the System API, with an interface compatible with `drun`. The purpose of this is * to have a way to run the test suite without depending on stuff we cannot open source together with motoko * to speed up development by allowing us to develop against a new System API while the client is working on implementing it * to isolate bugs better --- default.nix | 5 +- ic-stub/.gitignore | 23 ++ ic-stub/.hlint.yaml | 4 + ic-stub/cabal.project | 0 ic-stub/ic-stub.cabal | 28 ++ ic-stub/src/IC/DRun/Parse.hs | 42 +++ ic-stub/src/IC/Stub.hs | 518 +++++++++++++++++++++++++++++++++++ ic-stub/src/ic-stub-run.hs | 65 +++++ nix/haskell-packages.nix | 18 +- 9 files changed, 698 insertions(+), 5 deletions(-) create mode 100644 ic-stub/.gitignore create mode 100644 ic-stub/.hlint.yaml create mode 100644 ic-stub/cabal.project create mode 100644 ic-stub/ic-stub.cabal create mode 100644 ic-stub/src/IC/DRun/Parse.hs create mode 100644 ic-stub/src/IC/Stub.hs create mode 100644 ic-stub/src/ic-stub-run.hs diff --git a/default.nix b/default.nix index 6687f43508c..de05f1698c2 100644 --- a/default.nix +++ b/default.nix @@ -50,7 +50,7 @@ let real-drun = let js-user-library = sdk.js-user-library; in let haskellPackages = nixpkgs.haskellPackages.override { - overrides = import nix/haskell-packages.nix stdenv; + overrides = import nix/haskell-packages.nix nixpkgs subpath; }; in let libtommath = nixpkgs.fetchFromGitHub { @@ -215,7 +215,7 @@ rec { }; # “our” Haskell packages - inherit (haskellPackages) lsp-int qc-motoko; + inherit (haskellPackages) lsp-int qc-motoko ic-stub; tests = stdenv.mkDerivation { name = "tests"; @@ -470,6 +470,7 @@ rec { stdlib-doc-live produce-exchange users-guide + ic-stub ]; }; diff --git a/ic-stub/.gitignore b/ic-stub/.gitignore new file mode 100644 index 00000000000..4c9e245b5d8 --- /dev/null +++ b/ic-stub/.gitignore @@ -0,0 +1,23 @@ +dist +dist-* +cabal-dev +*.o +*.hi +*.hie +*.chi +*.chs.h +*.dyn_o +*.dyn_hi +.hpc +.hsenv +.cabal-sandbox/ +cabal.sandbox.config +*.prof +*.aux +*.hp +*.eventlog +.stack-work/ +cabal.project.local +cabal.project.local~ +.HTF/ +.ghc.environment.* diff --git a/ic-stub/.hlint.yaml b/ic-stub/.hlint.yaml new file mode 100644 index 00000000000..8323a007046 --- /dev/null +++ b/ic-stub/.hlint.yaml @@ -0,0 +1,4 @@ +# Warnings currently triggered by your code +- ignore: {name: "Use uncurry"} +- ignore: {name: "Avoid lambda"} +- ignore: {name: "Use camelCase"} diff --git a/ic-stub/cabal.project b/ic-stub/cabal.project new file mode 100644 index 00000000000..e69de29bb2d diff --git a/ic-stub/ic-stub.cabal b/ic-stub/ic-stub.cabal new file mode 100644 index 00000000000..70daf2cdb3a --- /dev/null +++ b/ic-stub/ic-stub.cabal @@ -0,0 +1,28 @@ +cabal-version: >=1.10 +name: ic-stub +version: 0.1.0.0 +author: Joachim Breitner +maintainer: mail@joachim-breitner.de +build-type: Simple + +executable ic-stub-run + main-is: ic-stub-run.hs + hs-source-dirs: src + other-modules: IC.Stub + other-modules: IC.DRun.Parse + build-depends: base >=4.11 && <5 + build-depends: optparse-applicative + build-depends: filepath + build-depends: hex-text + build-depends: text + build-depends: bytestring + build-depends: containers + build-depends: winter + build-depends: mtl + build-depends: transformers + build-depends: binary + build-depends: data-default-class + build-depends: vector + build-depends: primitive + default-language: Haskell2010 + ghc-options: -rtsopts diff --git a/ic-stub/src/IC/DRun/Parse.hs b/ic-stub/src/IC/DRun/Parse.hs new file mode 100644 index 00000000000..d8c44a2759f --- /dev/null +++ b/ic-stub/src/IC/DRun/Parse.hs @@ -0,0 +1,42 @@ +module IC.DRun.Parse where + +import qualified Data.ByteString.Lazy as B +import qualified Text.Hex as H +import qualified Data.Text as T +import Data.Char +import Control.Exception + +data Type = Query | Update deriving Show +type MethodName = String + +type Ingress = (Type, String, B.ByteString) + +parseFile :: FilePath -> IO [Ingress] +parseFile input = do + x <- parse <$> readFile input + evaluate (show x) -- hack to evaluate until we have a proper parser + return x + +parse = map parseLine . lines + +parseLine l = case words l of + [t,m,a] -> (parseType t, m, parseArg a) + +parseType "ingress" = Update +parseType "query" = Query +parseType x = error $ "Invalid ingress type " ++ x + +parseArg ('0':'x':xs) + | Just x <- B.fromStrict <$> H.decodeHex (T.pack xs) = x +parseArg ('"':xs) + = B.pack $ go xs + where + go "" = error "Missing terminating \"" + go "\"" = [] + go ('\\':'x':a:b:xs) + | Just h <- H.decodeHex (T.pack [a,b]) + = B.unpack (B.fromStrict h) ++ go xs + go (c:xs) = fromIntegral (ord c) : go xs +parseArg x = error $ "Invalid argument " ++ x + + diff --git a/ic-stub/src/IC/Stub.hs b/ic-stub/src/IC/Stub.hs new file mode 100644 index 00000000000..41a9933d223 --- /dev/null +++ b/ic-stub/src/IC/Stub.hs @@ -0,0 +1,518 @@ +{-# LANGUAGE TypeOperators #-} +{-# LANGUAGE ConstraintKinds #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE TupleSections #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE RankNTypes #-} + +{-# OPTIONS_GHC -Wmissing-signatures #-} +module IC.Stub where + +import qualified Data.ByteString.Lazy as BS +import qualified Data.ByteString.Lazy.Char8 as BSC +import qualified Data.Vector as V +import qualified Data.Map as M +import qualified Data.IntMap as IM +import qualified Data.Text.Lazy as T +import Data.List +import Data.Monoid +import Data.Maybe +import Control.Monad.State.Class +import Control.Monad.Trans.State.Strict (StateT(..), evalStateT) +import Control.Monad.Identity +import Control.Monad.Primitive +import Control.Monad.Except +import Control.Monad.ST +import Data.STRef +import Data.Binary.Get (runGetOrFail) +import Data.Default.Class (Default (..)) + +import qualified Wasm.Binary.Decode as W +import qualified Wasm.Exec.Eval as W +import qualified Wasm.Runtime.Func as W +import qualified Wasm.Runtime.Instance as W +import qualified Wasm.Runtime.Memory as W +import qualified Wasm.Syntax.AST as W +import qualified Wasm.Syntax.Types as W +import qualified Wasm.Syntax.Values as W +import qualified Wasm.Syntax.Memory as W +import Wasm.Runtime.Mutable + + +type (↦) = M.Map + +-- Basic types + +type Blob = BS.ByteString +type EntityId = Blob +type CanisterId = EntityId +type MethodName = String +type RequestID = Blob +type RejectCode = Integer + +-- Abstract HTTP Interface + +data AsyncRequest + = InstallRequest Blob Blob + | UpdateRequest MethodName Blob + deriving (Eq, Ord, Show) + +data SyncRequest + = QueryRequest MethodName Blob + | StatusRequest Blob + +data RequestStatus + = Unknown -- never inside IC, only as ReqResponse + | Received + | Processing + | Rejected (RejectCode, String) + | Completed CompletionValue + deriving Show + +type ReqResponse = RequestStatus + + +data CompletionValue -- we need to be more typed than the public spec here + = CompleteUnit + | CompleteCanisterId CanisterId + | CompleteArg Blob + deriving Show + +-- Abstract canisters + +data TrapOr a = Trap String | Return a + +data Arg = Arg + { dat :: Blob + , caller :: EntityId + } + deriving Show + +type InitFunc = (CanisterId, Blob) -> TrapOr WasmState +type UpdateFunc = WasmState -> TrapOr (WasmState, {- List MethodCall, -} Maybe Response) +type QueryFunc = WasmState -> TrapOr Response +data Response = Reply Blob | Reject (RejectCode, String) + +data CanisterModule = CanisterModule + { init_method :: InitFunc + , update_methods :: MethodName ↦ (Arg -> UpdateFunc) + , query_methods :: MethodName ↦ (Arg -> QueryFunc) + } + +-- IC state + +data CanState = CanState + { wasm_state :: WasmState + , can_mod :: CanisterModule + } + +type ICT = MonadState IC + +data IC = IC + { canisters :: CanisterId ↦ Maybe CanState + , requests :: AsyncRequest ↦ RequestStatus + } + +initialIC :: IC +initialIC = IC mempty mempty + +submitRequest :: ICT m => AsyncRequest -> m () +submitRequest r = + -- lensify? + modify (\ic -> ic { requests = M.insert r Received (requests ic) }) + +requestId :: AsyncRequest -> Blob +requestId r = BSC.pack (show r) -- TODO: Implement request hashing + +findRequest :: RequestID -> IC -> Maybe (AsyncRequest, RequestStatus) +findRequest rid ic = find (\(r,s) -> requestId r == rid) (M.toList (requests ic)) + +readRequest :: ICT m => SyncRequest -> m ReqResponse + +readRequest (StatusRequest rid) = + gets (findRequest rid) >>= \case + Just (r,status) -> return status + Nothing -> return Unknown + +readRequest (QueryRequest method arg) = + gets (M.lookup dummyCanisterId . canisters) >>= \case + Nothing -> return $ Rejected (0, "canister does not exist") + Just Nothing -> return $ Rejected (0, "canister is empty") + Just (Just (CanState wasm_state can_mod)) -> + case M.lookup method (query_methods can_mod) of + Nothing -> return $ Rejected (0, "query method does not exist") + Just f -> + case f (Arg arg dummyUserId) wasm_state of + Trap msg -> return $ Rejected (0, "canister trapped: " ++ msg) + Return (Reply res) -> return $ Completed (CompleteArg res) + Return (Reject (rc,rm)) -> return $ Rejected (rc, rm) + +nextRecieved :: ICT m => m (Maybe AsyncRequest) +nextRecieved = gets $ \ic -> listToMaybe + [ r | (r, Received) <- M.toList (requests ic) ] + +nextStarved :: ICT m => m (Maybe AsyncRequest) +nextStarved = gets $ \ic -> listToMaybe + -- TODO: This should return a starved calling context. + -- Until we have them, we treat requests in Processing state as starved + [ r | (r, Processing) <- M.toList (requests ic) ] + +setReqStatus :: ICT m => AsyncRequest -> RequestStatus -> m () +setReqStatus r s = + modify (\ic -> ic { requests = M.insert r s (requests ic) }) + +createCanister :: ICT m => CanisterId -> CanisterModule -> WasmState -> m () +createCanister cid can_mod wasm_state = + modify (\ic -> ic { canisters = + M.insert cid (Just (CanState {can_mod, wasm_state})) (canisters ic) + }) + +setCanisterState :: ICT m => CanisterId -> WasmState -> m () +setCanisterState cid wasm_state = + modify (\ic -> ic { canisters = + M.adjust (fmap (\cs -> cs { wasm_state })) cid (canisters ic) + }) + +dummyCanisterId :: CanisterId +dummyCanisterId = BS.pack [0xDE, 0xAD, 0xBE, 0xEF] + +dummyUserId :: CanisterId +dummyUserId = BS.pack [0xCA, 0xFF, 0xEE] + +processRequest :: ICT m => AsyncRequest -> m () +processRequest r@(InstallRequest can_mod arg) = + case parseCanister can_mod of + Left err -> + setReqStatus r (Rejected (0, "Parsing failed: " ++ err)) + Right can_mod -> + case init_method can_mod (dummyCanisterId, arg) of + Trap msg -> + setReqStatus r (Rejected (0, "Initialization trapped: " ++ msg)) + Return wasm_state -> do + createCanister dummyCanisterId can_mod wasm_state + setReqStatus r (Completed CompleteUnit) + +processRequest r@(UpdateRequest method arg) = do + setReqStatus r Processing + gets (M.lookup dummyCanisterId . canisters) >>= \case + Nothing -> setReqStatus r $ Rejected (0, "canister does not exist") + Just Nothing -> setReqStatus r $ Rejected (0, "canister is empty") + Just (Just (CanState wasm_state can_mod)) -> + case M.lookup method (update_methods can_mod) of + Nothing -> setReqStatus r $ Rejected (0, "update method does not exist") + Just f -> + case f (Arg arg dummyUserId) wasm_state of + Trap msg -> setReqStatus r $ Rejected (0, "canister trapped: " ++ msg) + Return (new_state, mb_response) -> do + setCanisterState dummyCanisterId new_state + case mb_response of + Just (Reply res) -> setReqStatus r $ Completed (CompleteArg res) + Just (Reject (rc,rm)) -> setReqStatus r $ Rejected (rc, rm) + Nothing -> return () + +-- processRequest r = setReqStatus r (Rejected (0, "Unknown request type")) + +starvedRequest :: ICT m => AsyncRequest -> m () +starvedRequest r@(UpdateRequest method arg) = + setReqStatus r $ Rejected (0, "canister did not respond") + +runToCompletion :: ICT m => m () +runToCompletion = + nextRecieved >>= \case + Just r -> processRequest r >> runToCompletion + Nothing -> nextStarved >>= \case + Just r -> starvedRequest r >> runToCompletion + Nothing -> return () + +-- Concrete canister + +-- We model a WasmState as the history of the canister. This is slow, +-- but allows us a correct implementation of persistence based on any +-- WebAssembly engine. + +data WasmState + = WSInit (W.Module Identity) CanisterId Blob + | WSUpdate MethodName Arg WasmState + +parseCanister :: Blob -> Either String CanisterModule +parseCanister bytes = + case runGetOrFail W.getModule bytes of + Left (_,_,err) -> Left err + Right (_,_,wasm_mod) -> Right $ concreteToAbstractModule wasm_mod + +concreteToAbstractModule :: W.Module Identity -> CanisterModule +concreteToAbstractModule wasm_mod = CanisterModule + { init_method = \(cid, arg) -> initializeMethod wasm_mod cid arg + , update_methods = M.fromList + [ (m, \arg wasm_state -> updateMethod m arg wasm_state) + | Identity e <- W._moduleExports wasm_mod + , W.FuncExport {} <- return $ W._exportDesc e + , Just m <- return $ stripPrefix "canister_update " (T.unpack (W._exportName e)) + ] + , query_methods = M.fromList + [ (m, \arg wasm_state -> queryMethod m arg wasm_state) + | Identity e <- W._moduleExports wasm_mod + , W.FuncExport {} <- return $ W._exportDesc e + , Just m <- return $ stripPrefix "canister_query " (T.unpack (W._exportName e)) + ] + } + +data Params = Params + { param_dat :: Maybe Blob + , param_caller :: Maybe EntityId + , reject_code :: Int + , reject_message :: String + } + +data ExecutionState s = ExecutionState + { memory :: Memory s + , self_id :: CanisterId + , params :: Params + , response :: Maybe Response + , reply_data :: Blob + } + + + +initalExecutionState :: CanisterId -> Memory s -> ExecutionState s +initalExecutionState self_id memory = ExecutionState + { memory + , self_id + , params = Params Nothing Nothing 0 "" + , response = Nothing + , reply_data = mempty + } + +type HostFunc s = ExceptT String (ST s) [W.Value] +type Memory s = W.MemoryInst (ST s) + +getBytes :: Memory s -> W.Address -> W.Size -> ExceptT String (ST s) Blob +getBytes mem ptr len = do + vec <- withExceptT show $ W.loadBytes mem ptr len + return $ BS.pack $ V.toList vec + +setBytes :: Memory s -> W.Address -> Blob -> ExceptT String (ST s) () +setBytes mem ptr blob = + withExceptT show $ + W.storeBytes mem (fromIntegral ptr) (V.fromList (BS.unpack blob)) + +type ESRef s = (STRef s Bool, STRef s (Maybe (ExecutionState s))) + +newESRef :: ST s (ESRef s) +newESRef = (,) <$> newSTRef True <*> newSTRef Nothing + +runESST :: (forall s. ESRef s -> ST s a) -> a +runESST f = runST $ newESRef >>= f + +withES :: PrimMonad m => ESRef (PrimState m) -> ExecutionState (PrimState m) -> m a -> m (a, ExecutionState (PrimState m)) +withES (pref, esref) es f = do + before <- stToPrim $ readSTRef esref + unless (isNothing before) $ fail "withES with non-empty es" + stToPrim $ writeSTRef esref $ Just es + x <- f + es' <- stToPrim $ readSTRef esref + case es' of + Nothing -> fail "withES: ExecutionState lost" + Just es' -> do + stToPrim $ writeSTRef esref Nothing + return (x, es') + +silently :: PrimMonad m => ESRef (PrimState m) -> m x -> m x +silently (pref, esref) f = do + before <- stToPrim $ readSTRef pref + stToPrim $ writeSTRef pref False + x <- f + stToPrim $ writeSTRef pref before + return x + +getsES :: ESRef s -> (ExecutionState s -> b) -> ExceptT String (ST s) b +getsES (_, esref) f = lift (readSTRef esref) >>= \case + Nothing -> throwError "System API not available yet" + Just es -> return (f es) + +modES :: ESRef s -> (ExecutionState s -> ExecutionState s) -> ExceptT String (ST s) () +modES (_, esref) f = lift $ modifySTRef esref (fmap f) + + +putBytes :: PrimMonad m => ESRef (PrimState m) -> BS.ByteString -> m () +putBytes (pref, _esref) bytes = + stToPrim (readSTRef pref) >>= \case + True -> unsafeIOToPrim (BS.putStr bytes) + False -> return () + + +systemAPI :: forall s. + ESRef s -> + [(String, [(String, W.StackType, W.StackType, [W.Value] -> HostFunc s)])] +systemAPI esref = + [ (,) "ic" + [ (,,,) "trap" [i32, i32] [] $ \case + [v1,v2] -> throwError "explicit trap" + _ -> fail "ic.trap: invalid argument" + ] + , (,) "msg" + [ unimplemented "reject" [i64, i32, i32] [] + , (,,,) "reply" [i64, i32, i32] [] msg_reply + , unimplemented "error_code" [i64] [i32] + , (,,,) "arg_data_copy" [i64, i32, i32, i32] [] arg_data_copy + , (,,,) "arg_data_size" [i64] [i32] arg_data_size + ] + , (,) "debug" + [ (,,,) "print" [i32, i32] [] debug_print + ] + ] + where + unimplemented name arg ret = (,,,) name arg ret $ + \_ -> throwError $ "unimplemented: " ++ name + + i32 = W.I32Type + i64 = W.I64Type + + debug_print :: [W.Value] -> HostFunc s + debug_print [W.I32 ptr, W.I32 len] = do + mem <- getsES esref memory + bytes <- getBytes mem (fromIntegral ptr) len + putBytes esref bytes + return [] + debug_print _ = fail "debug_print: invalid argument" + + arg_data_size :: [W.Value] -> HostFunc s + arg_data_size [W.I64 _nonce] = do + blob <- getsES esref (param_dat . params) + >>= maybe (throwError "arg_data_size: No argument") return + return [W.I32 (fromIntegral (BS.length blob))] + arg_data_size _ = fail "arg_data_size: invalid argument" + + arg_data_copy :: [W.Value] -> HostFunc s + arg_data_copy [W.I64 _nonce, W.I32 dst, W.I32 len, W.I32 offset] = do + blob <- getsES esref (param_dat . params) + >>= maybe (throwError "arg_data_size: No argument") return + unless (offset == 0) $ throwError "arg_data_copy: offset /= 0 not suppoted" + unless (len == fromIntegral (BS.length blob)) $ throwError "arg_data_copy: len not full blob not suppoted" + mem <- getsES esref memory + -- TODO Bounds checking + setBytes mem (fromIntegral dst) blob + return [] + arg_data_copy _ = fail "arg_data_copy: invalid argument" + + msg_reply :: [W.Value] -> HostFunc s + msg_reply [W.I64 _nonce, W.I32 ptr, W.I32 len] = do + mem <- getsES esref memory + bytes <- getBytes mem (fromIntegral ptr) len + modES esref (\es -> es { response = Just (Reply bytes) }) + return [] + msg_reply _ = fail "msg_reply: invalid argument" + + + +ifStateIsPresent :: Monad m => m x -> StateT s m x -> StateT (Maybe s) m x +ifStateIsPresent err (StateT f) = StateT $ \case + Nothing -> (, Nothing) <$> err + Just es -> do + (r, es') <- f es + return (r, Just es') + +initializeMethod :: W.Module Identity -> CanisterId -> Blob -> TrapOr WasmState +initializeMethod wasm_mod cid arg = runESST $ \esref -> do + result <- rawInitializeMethod esref wasm_mod cid arg + case result of + Trap err -> return $ Trap err + Return _raw_state -> return $ Return $ WSInit wasm_mod cid arg + +updateMethod :: MethodName -> Arg -> WasmState -> TrapOr (WasmState, Maybe Response) +updateMethod m arg s = runESST $ \esref -> do + rs <- replay esref s + tor <- rawUpdateMethod rs m arg + case tor of + Trap msg -> return $ Trap msg + Return r -> return $ Return (WSUpdate m arg s, r) + +queryMethod :: MethodName -> Arg -> WasmState -> TrapOr Response +queryMethod m arg s = runESST $ \esref -> do + rs <- replay esref s + rawQueryMethod rs m arg + +replay :: ESRef s -> WasmState -> ST s (RawState s) +replay esref s = silently esref $ go s + where + trapToFail (Trap err) = fail "replay failed" + trapToFail (Return x) = return x + + go (WSInit wasm_mod cid arg) = + rawInitializeMethod esref wasm_mod cid arg >>= trapToFail + go (WSUpdate m arg s) = do + rs <- go s + _ <- rawUpdateMethod rs m arg >>= trapToFail + return rs + +type RawState s = (ESRef s, CanisterId, IM.IntMap (W.ModuleInst Identity (ST s)), W.ModuleInst Identity (ST s)) + +rawInitializeMethod :: ESRef s -> W.Module Identity -> CanisterId -> Blob -> ST s (TrapOr (RawState s)) +rawInitializeMethod esref wasm_mod cid arg = do + result <- runExceptT $ do + let names = M.fromList (zip (map (T.pack . fst) (systemAPI esref)) [1..]) + mods = IM.fromList $ zip [1..] + [ (W.emptyModuleInst def) + { W._miGlobals = [ ] + , W._miTables = [ ] + , W._miMemories = [ ] + , W._miFuncs = [ ] + , W._miExports = M.fromList + [ (,) (T.pack fname) $ W.ExternFunc $ + W.allocHostEff (W.FuncType arg_ty ret_ty) + (\ args -> runExceptT $ f args) + | (fname, arg_ty, ret_ty, f) <- funcs + ] + } + | (_name, funcs) <- systemAPI esref + ] + (ref, inst) <- W.initialize (Identity wasm_mod) names mods + let mods' = IM.insert ref inst mods + + -- invoke canister_init + when (M.member (T.pack "canister_init") $ W._miExports inst) $ + void $ withES esref (initalExecutionState cid (head (W._miMemories inst))) $ + W.invokeByName mods' inst (T.pack "canister_init") [W.I64 0] + + return (esref, cid, mods', inst) + case result of + Left err -> return $ Trap $ show err + Right _raw_state -> return $ Return _raw_state + +rawQueryMethod :: RawState s -> MethodName -> Arg -> ST s (TrapOr Response) +rawQueryMethod (esref, cid, mods', inst) method arg = do + let es = (initalExecutionState cid (head (W._miMemories inst))) + { params = Params + { param_dat = Just $ dat arg + , param_caller = Just $ caller arg + , reject_code = 0 + , reject_message = "" + } + } + result <- runExceptT $ withES esref es $ + W.invokeByName mods' inst (T.pack $ "canister_query " ++ method) [W.I64 0] + case result of + Left err -> return $ Trap $ show err + Right (_, es') + | Just r <- response es' -> return $ Return r + | otherwise -> return $ Trap "No response" + +rawUpdateMethod :: RawState s -> MethodName -> Arg -> ST s (TrapOr ({- List MethodCall, -} Maybe Response)) +rawUpdateMethod (esref, cid, mods', inst) method arg = do + let es = (initalExecutionState cid (head (W._miMemories inst))) + { params = Params + { param_dat = Just $ dat arg + , param_caller = Just $ caller arg + , reject_code = 0 + , reject_message = "" + } + } + + result <- runExceptT $ withES esref es $ + W.invokeByName mods' inst (T.pack $ "canister_update " ++ method) [W.I64 0] + case result of + Left err -> return $ Trap $ show err + Right (_, es') -> return $ Return (response es') diff --git a/ic-stub/src/ic-stub-run.hs b/ic-stub/src/ic-stub-run.hs new file mode 100644 index 00000000000..b111bcc2d7f --- /dev/null +++ b/ic-stub/src/ic-stub-run.hs @@ -0,0 +1,65 @@ +{-# LANGUAGE ConstraintKinds #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE LambdaCase #-} +module Main where + +import Options.Applicative +import Control.Monad (join, foldM_, forM_) +import Data.Monoid ((<>)) +import System.FilePath +import qualified Data.ByteString.Lazy as B +import Control.Monad.Trans.State +import Control.Monad.IO.Class + +import IC.DRun.Parse (Type(..), parseFile) +import IC.Stub + (ICT, IC, AsyncRequest(..), SyncRequest(..), requestId, ReqResponse(..), + initialIC, submitRequest, readRequest, runToCompletion) + +type DRun = StateT IC IO + +submitAndRun :: AsyncRequest -> DRun ReqResponse +submitAndRun r = do + submitRequest r + runToCompletion + readRequest (StatusRequest (requestId r)) + +work :: FilePath -> FilePath -> IO () +work wasm_file msg_file = do + wasm <- B.readFile wasm_file + msgs <- parseFile msg_file + + flip evalStateT initialIC $ do + req_res <- submitAndRun (InstallRequest wasm B.empty) + liftIO $ print req_res -- assert completed + forM_ msgs $ \case + (Query, method, arg) -> + readRequest (QueryRequest method arg) >>= liftIO . print + (Update, method, arg) -> + submitAndRun (UpdateRequest method arg) >>= liftIO . print + +main :: IO () +main = join . customExecParser (prefs showHelpOnError) $ + info (helper <*> parser) + ( fullDesc + <> header "Internet Computer Canister runner" + <> progDesc "This runs an IC canister against a list of messages." + ) + where + parser :: Parser (IO ()) + parser = + work + <$ strOption + ( long "config" + <> short 'c' + <> metavar "CONFIG" + <> value "" + ) + <*> strArgument + ( metavar "*.wasm" + <> help "Wasm module" + ) + <*> strArgument + ( metavar "script" + <> help "messags to execute" + ) diff --git a/nix/haskell-packages.nix b/nix/haskell-packages.nix index 1c9cd1287a5..18771d4c46b 100644 --- a/nix/haskell-packages.nix +++ b/nix/haskell-packages.nix @@ -1,4 +1,6 @@ -stdenv: self: super: { +nix: subpath: + let stdenv = nix.stdenv; in + self: super: { haskell-lsp-types = self.callPackage ({ mkDerivation, aeson, base, bytestring, data-default, deepseq , filepath, hashable, lens, network-uri, scientific, text @@ -90,7 +92,17 @@ stdenv: self: super: { hydraPlatforms = stdenv.lib.platforms.none; }) {}; - lsp-int = self.callCabal2nix "lsp-int" ../test/lsp-int { }; + lsp-int = self.callCabal2nix "lsp-int" (subpath "test/lsp-int") { }; - qc-motoko = self.callCabal2nix "qc-motoko" ../test/random { }; + qc-motoko = self.callCabal2nix "qc-motoko" (subpath "test/random") { }; + + winter = self.callCabal2nixWithOptions "winter" + (nix.fetchFromGitHub { + owner = "nomeata"; + repo = "winter"; + rev = "eca9fb8dd8ec4d02962db104721f855040f33720"; + sha256 = "1gk5597fpw14y6pg1hklb1nv1psqf6wwaph8v2vx8fxlk41lyrv8"; + }) "--no-check" {}; + + ic-stub = self.callCabal2nix "ic-stub" (subpath "ic-stub") { }; } From 6ad9194a5d9e72506ee2b79aea73b9044ce4e885 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 8 Nov 2019 15:13:53 +0100 Subject: [PATCH 0532/1176] Update src/ir_interpreter/interpret_ir.ml Co-Authored-By: Claudio Russo --- src/ir_interpreter/interpret_ir.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index a95476f32ef..3bae24aac21 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -504,7 +504,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = let cc = { sort; control; n_args = List.length args; n_res = List.length ret_typs } in let f = interpret_message env exp.at x args - (fun env' -> + (fun env' -> interpret_exp env' e) in let v = V.Func (cc, f) in From 4fc4ada1ebf07e09294b84d20f94a8a7731d5ac2 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 8 Nov 2019 15:08:41 +0100 Subject: [PATCH 0533/1176] Run ic-stub-run in the test suite --- default.nix | 1 + test/run-drun/large-array.mo | 1 + test/run-drun/ok/counter.ic-stub-run.ok | 10 +++++++ .../ok/hello-world-return.ic-stub-run.ok | 3 ++ test/run-drun/ok/idl-any.ic-stub-run.ok | 29 +++++++++++++++++++ test/run-drun/ok/idl-bad.ic-stub-run.ok | 2 ++ .../ok/idl-field-escape.ic-stub-run.ok | 5 ++++ test/run-drun/ok/idl-nary.ic-stub-run.ok | 12 ++++++++ test/run-drun/ok/idl-nat-int.ic-stub-run.ok | 5 ++++ test/run-drun/ok/idl-option.ic-stub-run.ok | 4 +++ test/run-drun/ok/idl-pair.ic-stub-run.ok | 2 ++ test/run-drun/ok/idl-record.ic-stub-run.ok | 5 ++++ test/run-drun/ok/idl-tuple.ic-stub-run.ok | 5 ++++ test/run-drun/ok/idl-unit.ic-stub-run.ok | 2 ++ test/run-drun/ok/idl-variant.ic-stub-run.ok | 2 ++ test/run-drun/ok/idl-vector.ic-stub-run.ok | 2 ++ test/run-drun/ok/oom.ic-stub-run.ok | 3 ++ .../ok/print-from-init.ic-stub-run.ok | 1 + test/run-drun/ok/query.ic-stub-run.ok | 18 ++++++++++++ test/run-drun/ok/reject.ic-stub-run.ok | 4 +++ test/run-drun/ok/reversi.ic-stub-run.ok | 9 ++++++ test/run.sh | 2 ++ 22 files changed, 127 insertions(+) create mode 100644 test/run-drun/ok/counter.ic-stub-run.ok create mode 100644 test/run-drun/ok/hello-world-return.ic-stub-run.ok create mode 100644 test/run-drun/ok/idl-any.ic-stub-run.ok create mode 100644 test/run-drun/ok/idl-bad.ic-stub-run.ok create mode 100644 test/run-drun/ok/idl-field-escape.ic-stub-run.ok create mode 100644 test/run-drun/ok/idl-nary.ic-stub-run.ok create mode 100644 test/run-drun/ok/idl-nat-int.ic-stub-run.ok create mode 100644 test/run-drun/ok/idl-option.ic-stub-run.ok create mode 100644 test/run-drun/ok/idl-pair.ic-stub-run.ok create mode 100644 test/run-drun/ok/idl-record.ic-stub-run.ok create mode 100644 test/run-drun/ok/idl-tuple.ic-stub-run.ok create mode 100644 test/run-drun/ok/idl-unit.ic-stub-run.ok create mode 100644 test/run-drun/ok/idl-variant.ic-stub-run.ok create mode 100644 test/run-drun/ok/idl-vector.ic-stub-run.ok create mode 100644 test/run-drun/ok/oom.ic-stub-run.ok create mode 100644 test/run-drun/ok/print-from-init.ic-stub-run.ok create mode 100644 test/run-drun/ok/query.ic-stub-run.ok create mode 100644 test/run-drun/ok/reject.ic-stub-run.ok create mode 100644 test/run-drun/ok/reversi.ic-stub-run.ok diff --git a/default.nix b/default.nix index de05f1698c2..48afa7b9432 100644 --- a/default.nix +++ b/default.nix @@ -238,6 +238,7 @@ rec { drun haskellPackages.qc-motoko haskellPackages.lsp-int + ic-stub esm ] ++ llvmBuildInputs; diff --git a/test/run-drun/large-array.mo b/test/run-drun/large-array.mo index f47f4924763..5a8b76c762b 100644 --- a/test/run-drun/large-array.mo +++ b/test/run-drun/large-array.mo @@ -4,3 +4,4 @@ ignore(Array_init<()>(1024*1024*1024/4, ())); //SKIP run //SKIP run-ir //SKIP run-low +//SKIP ic-stub-run diff --git a/test/run-drun/ok/counter.ic-stub-run.ok b/test/run-drun/ok/counter.ic-stub-run.ok new file mode 100644 index 00000000000..8089c7a7d99 --- /dev/null +++ b/test/run-drun/ok/counter.ic-stub-run.ok @@ -0,0 +1,10 @@ +Completed CompleteUnit +2 +Rejected (0,"canister did not respond") +3 +Rejected (0,"canister did not respond") +4 +Rejected (0,"canister did not respond") +4 +Rejected (0,"canister did not respond") +Completed (CompleteArg "DIDL\NUL\SOH}\EOT") diff --git a/test/run-drun/ok/hello-world-return.ic-stub-run.ok b/test/run-drun/ok/hello-world-return.ic-stub-run.ok new file mode 100644 index 00000000000..336b95741ee --- /dev/null +++ b/test/run-drun/ok/hello-world-return.ic-stub-run.ok @@ -0,0 +1,3 @@ +Completed CompleteUnit +Completed (CompleteArg "DIDL\NUL\SOHq\fHello World!") +Completed (CompleteArg "DIDL\NUL\SOHq\fHello World!") diff --git a/test/run-drun/ok/idl-any.ic-stub-run.ok b/test/run-drun/ok/idl-any.ic-stub-run.ok new file mode 100644 index 00000000000..4fc6a8f2e7e --- /dev/null +++ b/test/run-drun/ok/idl-any.ic-stub-run.ok @@ -0,0 +1,29 @@ +Completed CompleteUnit +ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") +ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") +ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") +ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") +ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") +ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") +ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") +ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") +ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") +ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") +ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") +ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") +ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") +ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") +ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") +ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") +ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") +ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") +ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") +ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") +ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") +ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") +ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") +ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") +ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") +ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") +ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") +ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") diff --git a/test/run-drun/ok/idl-bad.ic-stub-run.ok b/test/run-drun/ok/idl-bad.ic-stub-run.ok new file mode 100644 index 00000000000..41e9c36d7b5 --- /dev/null +++ b/test/run-drun/ok/idl-bad.ic-stub-run.ok @@ -0,0 +1,2 @@ +Completed CompleteUnit +Rejected (0,"canister trapped: EvalTrapError :0.1 \"explicit trap\"") diff --git a/test/run-drun/ok/idl-field-escape.ic-stub-run.ok b/test/run-drun/ok/idl-field-escape.ic-stub-run.ok new file mode 100644 index 00000000000..74e03a71ffe --- /dev/null +++ b/test/run-drun/ok/idl-field-escape.ic-stub-run.ok @@ -0,0 +1,5 @@ +Completed CompleteUnit +Completed (CompleteArg "DIDL\STXl\SOH\134\142\183\STX\SOHl\NUL\SOH\NUL") +Completed (CompleteArg "DIDL\STXl\SOH\134\142\183\STX\SOHl\NUL\SOH\NUL") +Completed (CompleteArg "DIDL\SOHl\ETX\NUL|\SOH}\188\254\247\177\STXq\SOH\NUL\255\255\ETX\128 \ETXXXX") +Completed (CompleteArg "DIDL\NUL\NUL") diff --git a/test/run-drun/ok/idl-nary.ic-stub-run.ok b/test/run-drun/ok/idl-nary.ic-stub-run.ok new file mode 100644 index 00000000000..40f8313bdb1 --- /dev/null +++ b/test/run-drun/ok/idl-nary.ic-stub-run.ok @@ -0,0 +1,12 @@ +Completed CompleteUnit +Completed (CompleteArg "DIDL\NUL\STXqq\ETXOne\ETXTwo") +Completed (CompleteArg "DIDL\NUL\ETXqqq\ETXOne\ETXTwo\ENQThree") +Completed (CompleteArg "DIDL\NUL\EOTqqqq\ETXOne\ETXTwo\ENQThree\EOTFour") +Completed (CompleteArg "DIDL\SOHl\EOT\NULq\SOHq\STXq\ETXq\SOH\NUL\ETXOne\ETXTwo\ENQThree\EOTFour") +Completed (CompleteArg "DIDL\SOHl\EOT\NULq\SOHq\STXq\ETXq\SOH\NUL\ETXOne\ETXTwo\ENQThree\EOTFour") +Completed (CompleteArg "DIDL\SOHl\EOT\NULq\SOHq\STXq\ETXq\SOH\NUL\ETXOne\ETXTwo\ENQThree\EOTFour") +Completed (CompleteArg "DIDL\SOHl\EOT\NULq\SOHq\STXq\ETXq\SOH\NUL\ETXOne\ETXTwo\ENQThree\EOTFour") +Completed (CompleteArg "DIDL\SOHl\EOT\NULq\SOHq\STXq\ETXq\SOH\NUL\ETXOne\ETXTwo\ENQThree\EOTFour") +Rejected (0,"canister trapped: EvalTrapError :0.1 \"explicit trap\"") +Rejected (0,"canister trapped: EvalTrapError :0.1 \"explicit trap\"") +Completed (CompleteArg "DIDL\NUL\EOTqqqq\ETXOne\ETXTwo\ENQThree\EOTFour") diff --git a/test/run-drun/ok/idl-nat-int.ic-stub-run.ok b/test/run-drun/ok/idl-nat-int.ic-stub-run.ok new file mode 100644 index 00000000000..6e785d7eab2 --- /dev/null +++ b/test/run-drun/ok/idl-nat-int.ic-stub-run.ok @@ -0,0 +1,5 @@ +Completed CompleteUnit +Completed (CompleteArg "DIDL\NUL\SOH}*") +Completed (CompleteArg "DIDL\NUL\SOH}*") +Completed (CompleteArg "DIDL\SOHm}\SOH\NUL\STX*\EM") +Completed (CompleteArg "DIDL\SOHm}\SOH\NUL\STX*\EM") diff --git a/test/run-drun/ok/idl-option.ic-stub-run.ok b/test/run-drun/ok/idl-option.ic-stub-run.ok new file mode 100644 index 00000000000..6576da2108b --- /dev/null +++ b/test/run-drun/ok/idl-option.ic-stub-run.ok @@ -0,0 +1,4 @@ +Completed CompleteUnit +ok: nullCompleted (CompleteArg "DIDL\NUL\NUL") +ok: nullCompleted (CompleteArg "DIDL\NUL\NUL") +ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") diff --git a/test/run-drun/ok/idl-pair.ic-stub-run.ok b/test/run-drun/ok/idl-pair.ic-stub-run.ok new file mode 100644 index 00000000000..b422faf3acd --- /dev/null +++ b/test/run-drun/ok/idl-pair.ic-stub-run.ok @@ -0,0 +1,2 @@ +Completed CompleteUnit +Completed (CompleteArg "DIDL\SOHl\STX\NUL|\SOH|\SOH\NUL\STX\ENQ") diff --git a/test/run-drun/ok/idl-record.ic-stub-run.ok b/test/run-drun/ok/idl-record.ic-stub-run.ok new file mode 100644 index 00000000000..91cd95622a0 --- /dev/null +++ b/test/run-drun/ok/idl-record.ic-stub-run.ok @@ -0,0 +1,5 @@ +Completed CompleteUnit +ok: +42Completed (CompleteArg "DIDL\NUL\NUL") +ok: Hey!Completed (CompleteArg "DIDL\NUL\NUL") +ok: +25Completed (CompleteArg "DIDL\NUL\NUL") +ok: Hey! +25Completed (CompleteArg "DIDL\NUL\SOHw\EM") diff --git a/test/run-drun/ok/idl-tuple.ic-stub-run.ok b/test/run-drun/ok/idl-tuple.ic-stub-run.ok new file mode 100644 index 00000000000..1ae4c051cbe --- /dev/null +++ b/test/run-drun/ok/idl-tuple.ic-stub-run.ok @@ -0,0 +1,5 @@ +Completed CompleteUnit +Completed (CompleteArg "DIDL\NUL\STX||\STX\ENQ") +Completed (CompleteArg "DIDL\NUL\ETX|||\ENQ\ENQ\129\132\140 ") +Completed (CompleteArg "DIDL\NUL\ETX|||\ENQ\ENQ\129\132\140 ") +Completed (CompleteArg "DIDL\NUL\ETX|||\ENQ\ENQ\129\132\140 ") diff --git a/test/run-drun/ok/idl-unit.ic-stub-run.ok b/test/run-drun/ok/idl-unit.ic-stub-run.ok new file mode 100644 index 00000000000..97dececaebe --- /dev/null +++ b/test/run-drun/ok/idl-unit.ic-stub-run.ok @@ -0,0 +1,2 @@ +Completed CompleteUnit +Completed (CompleteArg "DIDL\NUL\NUL") diff --git a/test/run-drun/ok/idl-variant.ic-stub-run.ok b/test/run-drun/ok/idl-variant.ic-stub-run.ok new file mode 100644 index 00000000000..c0f575a70ae --- /dev/null +++ b/test/run-drun/ok/idl-variant.ic-stub-run.ok @@ -0,0 +1,2 @@ +Completed CompleteUnit +Completed (CompleteArg "DIDL\SOHk\ETX\213\131\183\STX\NUL\135\144\192\189\EOTy\220\151\144\203\SOy\SOH\NUL\NUL\SOH \NUL\NUL\NUL") diff --git a/test/run-drun/ok/idl-vector.ic-stub-run.ok b/test/run-drun/ok/idl-vector.ic-stub-run.ok new file mode 100644 index 00000000000..8187ff9d804 --- /dev/null +++ b/test/run-drun/ok/idl-vector.ic-stub-run.ok @@ -0,0 +1,2 @@ +Completed CompleteUnit +Completed (CompleteArg "DIDL\STXn\SOHm\NUL\SOH\NUL\SOH\ETX\SOH\NUL\SOH\EOT\SOH\NUL\SOH\STX\SOH\NUL\SOH\NUL\SOH\NUL\SOH\NUL\SOH\NUL") diff --git a/test/run-drun/ok/oom.ic-stub-run.ok b/test/run-drun/ok/oom.ic-stub-run.ok new file mode 100644 index 00000000000..3e1fe57f769 --- /dev/null +++ b/test/run-drun/ok/oom.ic-stub-run.ok @@ -0,0 +1,3 @@ +Completed CompleteUnit +Rejected (0,"canister did not respond") +Rejected (0,"canister did not respond") diff --git a/test/run-drun/ok/print-from-init.ic-stub-run.ok b/test/run-drun/ok/print-from-init.ic-stub-run.ok new file mode 100644 index 00000000000..3694857207b --- /dev/null +++ b/test/run-drun/ok/print-from-init.ic-stub-run.ok @@ -0,0 +1 @@ +Debug outCompleted CompleteUnit diff --git a/test/run-drun/ok/query.ic-stub-run.ok b/test/run-drun/ok/query.ic-stub-run.ok new file mode 100644 index 00000000000..2564ce843e0 --- /dev/null +++ b/test/run-drun/ok/query.ic-stub-run.ok @@ -0,0 +1,18 @@ +Completed CompleteUnit +2 +Rejected (0,"canister did not respond") +3 +Rejected (0,"canister did not respond") +4 +Rejected (0,"canister did not respond") +4 +Rejected (0,"canister did not respond") +Completed (CompleteArg "DIDL\NUL\SOH}\EOT") +5 +Completed (CompleteArg "DIDL\NUL\SOH}\EOT") +4 +Rejected (0,"canister did not respond") +5 +Completed (CompleteArg "DIDL\NUL\SOH}\EOT") +4 +Rejected (0,"canister did not respond") diff --git a/test/run-drun/ok/reject.ic-stub-run.ok b/test/run-drun/ok/reject.ic-stub-run.ok new file mode 100644 index 00000000000..557b22fc81c --- /dev/null +++ b/test/run-drun/ok/reject.ic-stub-run.ok @@ -0,0 +1,4 @@ +Completed CompleteUnit +1Rejected (0,"canister trapped: EvalTrapError :0.1 \"unimplemented: reject\"") +1okCompleted (CompleteArg "DIDL\NUL\NUL") +1okRejected (0,"canister trapped: EvalTrapError :0.1 \"unimplemented: reject\"") diff --git a/test/run-drun/ok/reversi.ic-stub-run.ok b/test/run-drun/ok/reversi.ic-stub-run.ok new file mode 100644 index 00000000000..66e2cccdbc4 --- /dev/null +++ b/test/run-drun/ok/reversi.ic-stub-run.ok @@ -0,0 +1,9 @@ +Completed CompleteUnit +Rejected (0,"canister did not respond") +Completed (CompleteArg "DIDL\NUL\SOHqH........\n........\n........\n...O*...\n...*O...\n........\n........\n........\n") +Completed (CompleteArg "DIDL\NUL\SOHq\STXOK") +Completed (CompleteArg "DIDL\NUL\SOHqH........\n........\n....O...\n...OO...\n...*O...\n........\n........\n........\n") +Completed (CompleteArg "DIDL\NUL\SOHq\STXOK") +Completed (CompleteArg "DIDL\NUL\SOHqH........\n........\n...*O...\n...*O...\n...*O...\n........\n........\n........\n") +Completed (CompleteArg "DIDL\NUL\SOHq\STXOK") +Completed (CompleteArg "DIDL\NUL\SOHqH........\n........\n...*O...\n...OO...\n..OOO...\n........\n........\n........\n") diff --git a/test/run.sh b/test/run.sh index bff1d5a1696..4444391b816 100755 --- a/test/run.sh +++ b/test/run.sh @@ -31,6 +31,7 @@ export MO_LD WASM=${WASM:-wasm} DVM_WRAPPER=$(realpath $(dirname $0)/dvm.sh) DRUN_WRAPPER=$(realpath $(dirname $0)/drun-wrapper.sh) +IC_STUB_RUN=${IC_STUB:-ic-stub-run} ECHO=echo while getopts "a12sir" o; do @@ -229,6 +230,7 @@ do elif [ $API = ic ] then run drun-run $DRUN_WRAPPER $out/$base.wasm $base.mo + DRUN=$IC_STUB_RUN run ic-stub-run $DRUN_WRAPPER $out/$base.wasm $base.mo else run wasm-run $WASM $out/$base.wasm fi From 8907d6251ff04ecf2477235bcce75a2e59620f9c Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 8 Nov 2019 15:23:24 +0100 Subject: [PATCH 0534/1176] Update test output --- test/run-drun/ok/ic-calls.comp.ok | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/run-drun/ok/ic-calls.comp.ok b/test/run-drun/ok/ic-calls.comp.ok index 85d6295d888..3c98a1fe547 100644 --- a/test/run-drun/ok/ic-calls.comp.ok +++ b/test/run-drun/ok/ic-calls.comp.ok @@ -1 +1 @@ -Fatal error: exception "Assert_failure codegen/compile.ml:6445:8" +Fatal error: exception "Assert_failure codegen/compile.ml:6441:8" From 289b62d9dd669ece2b94a53eec1c963285e99606 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 8 Nov 2019 16:50:33 +0100 Subject: [PATCH 0535/1176] Move haskellPackages into its own nix file (#840) * Move haskellPackages into its own nix file just to keep `default.nix` a bit smaller * More shuffling around --- default.nix | 102 ++------------------------------------- nix/haskell-packages.nix | 96 ++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+), 97 deletions(-) create mode 100644 nix/haskell-packages.nix diff --git a/default.nix b/default.nix index 0595bc75c7f..6687f43508c 100644 --- a/default.nix +++ b/default.nix @@ -50,98 +50,7 @@ let real-drun = let js-user-library = sdk.js-user-library; in let haskellPackages = nixpkgs.haskellPackages.override { - overrides = self: super: { - haskell-lsp-types = self.callPackage - ({ mkDerivation, aeson, base, bytestring, data-default, deepseq - , filepath, hashable, lens, network-uri, scientific, text - , unordered-containers - }: - mkDerivation { - pname = "haskell-lsp-types"; - version = "0.16.0.0"; - sha256 = "14wlv54ydbddpw6cwgykcas3rb55w7m78q0s1wdbi594wg1bscqg"; - libraryHaskellDepends = [ - aeson base bytestring data-default deepseq filepath hashable lens - network-uri scientific text unordered-containers - ]; - description = "Haskell library for the Microsoft Language Server Protocol, data types"; - license = stdenv.lib.licenses.mit; - hydraPlatforms = stdenv.lib.platforms.none; - }) {}; - - rope-utf16-splay = self.callPackage - ({ mkDerivation, base, QuickCheck, tasty, tasty-hunit - , tasty-quickcheck, text - }: - mkDerivation { - pname = "rope-utf16-splay"; - version = "0.3.1.0"; - sha256 = "1ilcgwmdwqnp95vb7652fc03ji9dnzy6cm24pvbiwi2mhc4piy6b"; - libraryHaskellDepends = [ base text ]; - testHaskellDepends = [ - base QuickCheck tasty tasty-hunit tasty-quickcheck text - ]; - description = "Ropes optimised for updating using UTF-16 code units and row/column pairs"; - license = stdenv.lib.licenses.bsd3; - }) {}; - - haskell-lsp = self.callPackage - ({ mkDerivation, aeson, async, attoparsec, base, bytestring - , containers, data-default, directory, filepath, hashable - , haskell-lsp-types, hslogger, hspec, hspec-discover, lens, mtl - , network-uri, QuickCheck, quickcheck-instances, rope-utf16-splay - , sorted-list, stm, temporary, text, time, unordered-containers - }: - mkDerivation { - pname = "haskell-lsp"; - version = "0.16.0.0"; - sha256 = "1s04lfnb3c0g9bkwp4j7j59yw8ypps63dq27ayybynrfci4bpj95"; - isLibrary = true; - isExecutable = true; - libraryHaskellDepends = [ - aeson async attoparsec base bytestring containers data-default - directory filepath hashable haskell-lsp-types hslogger lens mtl - network-uri rope-utf16-splay sorted-list stm temporary text time - unordered-containers - ]; - testHaskellDepends = [ - aeson base bytestring containers data-default directory filepath - hashable hspec lens network-uri QuickCheck quickcheck-instances - rope-utf16-splay sorted-list stm text - ]; - testToolDepends = [ hspec-discover ]; - description = "Haskell library for the Microsoft Language Server Protocol"; - license = stdenv.lib.licenses.mit; - hydraPlatforms = stdenv.lib.platforms.none; - }) {}; - - lsp-test = self.callPackage - ({ mkDerivation, aeson, aeson-pretty, ansi-terminal, async, base - , bytestring, conduit, conduit-parse, containers, data-default - , Diff, directory, filepath, hspec, haskell-lsp, lens, mtl - , parser-combinators, process, rope-utf16-splay, text, transformers - , unix, unordered-containers - }: - mkDerivation { - pname = "lsp-test"; - version = "0.7.0.0"; - sha256 = "1lm299gbahrnwfrprhhpzxrmjljj33pps1gzz2wzmp3m9gzl1dx5"; - libraryHaskellDepends = [ - aeson aeson-pretty ansi-terminal async base bytestring conduit - conduit-parse containers data-default Diff directory filepath - haskell-lsp lens mtl parser-combinators process rope-utf16-splay - text transformers unix unordered-containers - ]; - doCheck = false; - testHaskellDepends = [ - aeson base data-default haskell-lsp hspec lens text - unordered-containers - ]; - description = "Functional test framework for LSP servers"; - license = stdenv.lib.licenses.bsd3; - hydraPlatforms = stdenv.lib.platforms.none; - }) {}; - }; + overrides = import nix/haskell-packages.nix stdenv; }; in let libtommath = nixpkgs.fetchFromGitHub { @@ -305,9 +214,8 @@ rec { ''; }; - lsp-int = haskellPackages.callCabal2nix "lsp-int" test/lsp-int { }; - - qc-motoko = haskellPackages.callCabal2nix "qc-motoko" test/random { }; + # “our” Haskell packages + inherit (haskellPackages) lsp-int qc-motoko; tests = stdenv.mkDerivation { name = "tests"; @@ -328,8 +236,8 @@ rec { js-user-library dvm drun - qc-motoko - lsp-int + haskellPackages.qc-motoko + haskellPackages.lsp-int esm ] ++ llvmBuildInputs; diff --git a/nix/haskell-packages.nix b/nix/haskell-packages.nix new file mode 100644 index 00000000000..1c9cd1287a5 --- /dev/null +++ b/nix/haskell-packages.nix @@ -0,0 +1,96 @@ +stdenv: self: super: { + haskell-lsp-types = self.callPackage + ({ mkDerivation, aeson, base, bytestring, data-default, deepseq + , filepath, hashable, lens, network-uri, scientific, text + , unordered-containers + }: + mkDerivation { + pname = "haskell-lsp-types"; + version = "0.16.0.0"; + sha256 = "14wlv54ydbddpw6cwgykcas3rb55w7m78q0s1wdbi594wg1bscqg"; + libraryHaskellDepends = [ + aeson base bytestring data-default deepseq filepath hashable lens + network-uri scientific text unordered-containers + ]; + description = "Haskell library for the Microsoft Language Server Protocol, data types"; + license = stdenv.lib.licenses.mit; + hydraPlatforms = stdenv.lib.platforms.none; + }) {}; + + rope-utf16-splay = self.callPackage + ({ mkDerivation, base, QuickCheck, tasty, tasty-hunit + , tasty-quickcheck, text + }: + mkDerivation { + pname = "rope-utf16-splay"; + version = "0.3.1.0"; + sha256 = "1ilcgwmdwqnp95vb7652fc03ji9dnzy6cm24pvbiwi2mhc4piy6b"; + libraryHaskellDepends = [ base text ]; + testHaskellDepends = [ + base QuickCheck tasty tasty-hunit tasty-quickcheck text + ]; + description = "Ropes optimised for updating using UTF-16 code units and row/column pairs"; + license = stdenv.lib.licenses.bsd3; + }) {}; + + haskell-lsp = self.callPackage + ({ mkDerivation, aeson, async, attoparsec, base, bytestring + , containers, data-default, directory, filepath, hashable + , haskell-lsp-types, hslogger, hspec, hspec-discover, lens, mtl + , network-uri, QuickCheck, quickcheck-instances, rope-utf16-splay + , sorted-list, stm, temporary, text, time, unordered-containers + }: + mkDerivation { + pname = "haskell-lsp"; + version = "0.16.0.0"; + sha256 = "1s04lfnb3c0g9bkwp4j7j59yw8ypps63dq27ayybynrfci4bpj95"; + isLibrary = true; + isExecutable = true; + libraryHaskellDepends = [ + aeson async attoparsec base bytestring containers data-default + directory filepath hashable haskell-lsp-types hslogger lens mtl + network-uri rope-utf16-splay sorted-list stm temporary text time + unordered-containers + ]; + testHaskellDepends = [ + aeson base bytestring containers data-default directory filepath + hashable hspec lens network-uri QuickCheck quickcheck-instances + rope-utf16-splay sorted-list stm text + ]; + testToolDepends = [ hspec-discover ]; + description = "Haskell library for the Microsoft Language Server Protocol"; + license = stdenv.lib.licenses.mit; + hydraPlatforms = stdenv.lib.platforms.none; + }) {}; + + lsp-test = self.callPackage + ({ mkDerivation, aeson, aeson-pretty, ansi-terminal, async, base + , bytestring, conduit, conduit-parse, containers, data-default + , Diff, directory, filepath, hspec, haskell-lsp, lens, mtl + , parser-combinators, process, rope-utf16-splay, text, transformers + , unix, unordered-containers + }: + mkDerivation { + pname = "lsp-test"; + version = "0.7.0.0"; + sha256 = "1lm299gbahrnwfrprhhpzxrmjljj33pps1gzz2wzmp3m9gzl1dx5"; + libraryHaskellDepends = [ + aeson aeson-pretty ansi-terminal async base bytestring conduit + conduit-parse containers data-default Diff directory filepath + haskell-lsp lens mtl parser-combinators process rope-utf16-splay + text transformers unix unordered-containers + ]; + doCheck = false; + testHaskellDepends = [ + aeson base data-default haskell-lsp hspec lens text + unordered-containers + ]; + description = "Functional test framework for LSP servers"; + license = stdenv.lib.licenses.bsd3; + hydraPlatforms = stdenv.lib.platforms.none; + }) {}; + + lsp-int = self.callCabal2nix "lsp-int" ../test/lsp-int { }; + + qc-motoko = self.callCabal2nix "qc-motoko" ../test/random { }; +} From 91dbde827b2676b0a558267e6532a860a7170135 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 8 Nov 2019 17:51:28 +0100 Subject: [PATCH 0536/1176] run.sh: Allow using a different ic-stub-run --- test/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/run.sh b/test/run.sh index 4444391b816..5b0b4769325 100755 --- a/test/run.sh +++ b/test/run.sh @@ -31,7 +31,7 @@ export MO_LD WASM=${WASM:-wasm} DVM_WRAPPER=$(realpath $(dirname $0)/dvm.sh) DRUN_WRAPPER=$(realpath $(dirname $0)/drun-wrapper.sh) -IC_STUB_RUN=${IC_STUB:-ic-stub-run} +IC_STUB_RUN=${IC_STUB_RUN:-ic-stub-run} ECHO=echo while getopts "a12sir" o; do From e464ddc3effb4812d0a837c3c0d5dc8efb292f61 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 8 Nov 2019 17:52:56 +0100 Subject: [PATCH 0537/1176] Implement msg.reject and make reject codes symbolic --- ic-stub/ic-stub.cabal | 1 + ic-stub/src/IC/Stub.hs | 52 ++++++++++++++++++------ test/run-drun/ok/counter.ic-stub-run.ok | 8 ++-- test/run-drun/ok/idl-bad.ic-stub-run.ok | 2 +- test/run-drun/ok/idl-nary.ic-stub-run.ok | 4 +- test/run-drun/ok/oom.ic-stub-run.ok | 4 +- test/run-drun/ok/query.ic-stub-run.ok | 12 +++--- test/run-drun/ok/reject.ic-stub-run.ok | 4 +- test/run-drun/ok/reversi.ic-stub-run.ok | 2 +- 9 files changed, 58 insertions(+), 31 deletions(-) diff --git a/ic-stub/ic-stub.cabal b/ic-stub/ic-stub.cabal index 70daf2cdb3a..5fc71bf20c4 100644 --- a/ic-stub/ic-stub.cabal +++ b/ic-stub/ic-stub.cabal @@ -24,5 +24,6 @@ executable ic-stub-run build-depends: data-default-class build-depends: vector build-depends: primitive + build-depends: utf8-string default-language: Haskell2010 ghc-options: -rtsopts diff --git a/ic-stub/src/IC/Stub.hs b/ic-stub/src/IC/Stub.hs index 41a9933d223..d04aa310b38 100644 --- a/ic-stub/src/IC/Stub.hs +++ b/ic-stub/src/IC/Stub.hs @@ -13,6 +13,7 @@ module IC.Stub where import qualified Data.ByteString.Lazy as BS import qualified Data.ByteString.Lazy.Char8 as BSC +import qualified Data.ByteString.Lazy.UTF8 as BSU import qualified Data.Vector as V import qualified Data.Map as M import qualified Data.IntMap as IM @@ -51,7 +52,23 @@ type EntityId = Blob type CanisterId = EntityId type MethodName = String type RequestID = Blob -type RejectCode = Integer + +-- Reject code + +data RejectCode + = RC_SYS_FATAL + | RC_SYS_TRANSIENT + | RC_DESTINATION_INVALID + | RC_CANISTER_REJECT + | RC_CANISTER_ERROR + deriving Show + +rejectCode :: RejectCode -> Int +rejectCode RC_SYS_FATAL = 1 +rejectCode RC_SYS_TRANSIENT = 2 +rejectCode RC_DESTINATION_INVALID = 3 +rejectCode RC_CANISTER_REJECT = 4 +rejectCode RC_CANISTER_ERROR = 5 -- Abstract HTTP Interface @@ -139,14 +156,14 @@ readRequest (StatusRequest rid) = readRequest (QueryRequest method arg) = gets (M.lookup dummyCanisterId . canisters) >>= \case - Nothing -> return $ Rejected (0, "canister does not exist") - Just Nothing -> return $ Rejected (0, "canister is empty") + Nothing -> return $ Rejected (RC_DESTINATION_INVALID, "canister does not exist") + Just Nothing -> return $ Rejected (RC_DESTINATION_INVALID, "canister is empty") Just (Just (CanState wasm_state can_mod)) -> case M.lookup method (query_methods can_mod) of - Nothing -> return $ Rejected (0, "query method does not exist") + Nothing -> return $ Rejected (RC_DESTINATION_INVALID, "query method does not exist") Just f -> case f (Arg arg dummyUserId) wasm_state of - Trap msg -> return $ Rejected (0, "canister trapped: " ++ msg) + Trap msg -> return $ Rejected (RC_CANISTER_ERROR, "canister trapped: " ++ msg) Return (Reply res) -> return $ Completed (CompleteArg res) Return (Reject (rc,rm)) -> return $ Rejected (rc, rm) @@ -186,11 +203,11 @@ processRequest :: ICT m => AsyncRequest -> m () processRequest r@(InstallRequest can_mod arg) = case parseCanister can_mod of Left err -> - setReqStatus r (Rejected (0, "Parsing failed: " ++ err)) + setReqStatus r (Rejected (RC_SYS_FATAL, "Parsing failed: " ++ err)) Right can_mod -> case init_method can_mod (dummyCanisterId, arg) of Trap msg -> - setReqStatus r (Rejected (0, "Initialization trapped: " ++ msg)) + setReqStatus r (Rejected (RC_CANISTER_ERROR, "Initialization trapped: " ++ msg)) Return wasm_state -> do createCanister dummyCanisterId can_mod wasm_state setReqStatus r (Completed CompleteUnit) @@ -198,14 +215,14 @@ processRequest r@(InstallRequest can_mod arg) = processRequest r@(UpdateRequest method arg) = do setReqStatus r Processing gets (M.lookup dummyCanisterId . canisters) >>= \case - Nothing -> setReqStatus r $ Rejected (0, "canister does not exist") - Just Nothing -> setReqStatus r $ Rejected (0, "canister is empty") + Nothing -> setReqStatus r $ Rejected (RC_DESTINATION_INVALID, "canister does not exist") + Just Nothing -> setReqStatus r $ Rejected (RC_DESTINATION_INVALID, "canister is empty") Just (Just (CanState wasm_state can_mod)) -> case M.lookup method (update_methods can_mod) of - Nothing -> setReqStatus r $ Rejected (0, "update method does not exist") + Nothing -> setReqStatus r $ Rejected (RC_DESTINATION_INVALID, "update method does not exist") Just f -> case f (Arg arg dummyUserId) wasm_state of - Trap msg -> setReqStatus r $ Rejected (0, "canister trapped: " ++ msg) + Trap msg -> setReqStatus r $ Rejected (RC_CANISTER_ERROR, "canister trapped: " ++ msg) Return (new_state, mb_response) -> do setCanisterState dummyCanisterId new_state case mb_response of @@ -217,7 +234,7 @@ processRequest r@(UpdateRequest method arg) = do starvedRequest :: ICT m => AsyncRequest -> m () starvedRequest r@(UpdateRequest method arg) = - setReqStatus r $ Rejected (0, "canister did not respond") + setReqStatus r $ Rejected (RC_CANISTER_ERROR, "canister did not respond") runToCompletion :: ICT m => m () runToCompletion = @@ -354,7 +371,7 @@ systemAPI esref = _ -> fail "ic.trap: invalid argument" ] , (,) "msg" - [ unimplemented "reject" [i64, i32, i32] [] + [ (,,,) "reject" [i64, i32, i32] [] msg_reject , (,,,) "reply" [i64, i32, i32] [] msg_reply , unimplemented "error_code" [i64] [i32] , (,,,) "arg_data_copy" [i64, i32, i32, i32] [] arg_data_copy @@ -406,6 +423,15 @@ systemAPI esref = return [] msg_reply _ = fail "msg_reply: invalid argument" + msg_reject :: [W.Value] -> HostFunc s + msg_reject [W.I64 _nonce, W.I32 ptr, W.I32 len] = do + mem <- getsES esref memory + bytes <- getBytes mem (fromIntegral ptr) len + let msg = BSU.toString bytes + modES esref (\es -> es { response = Just (Reject (RC_CANISTER_REJECT, msg)) }) + return [] + msg_reject _ = fail "msg_reply: invalid argument" + ifStateIsPresent :: Monad m => m x -> StateT s m x -> StateT (Maybe s) m x diff --git a/test/run-drun/ok/counter.ic-stub-run.ok b/test/run-drun/ok/counter.ic-stub-run.ok index 8089c7a7d99..19d189c14e3 100644 --- a/test/run-drun/ok/counter.ic-stub-run.ok +++ b/test/run-drun/ok/counter.ic-stub-run.ok @@ -1,10 +1,10 @@ Completed CompleteUnit 2 -Rejected (0,"canister did not respond") +Rejected (RC_CANISTER_ERROR,"canister did not respond") 3 -Rejected (0,"canister did not respond") +Rejected (RC_CANISTER_ERROR,"canister did not respond") 4 -Rejected (0,"canister did not respond") +Rejected (RC_CANISTER_ERROR,"canister did not respond") 4 -Rejected (0,"canister did not respond") +Rejected (RC_CANISTER_ERROR,"canister did not respond") Completed (CompleteArg "DIDL\NUL\SOH}\EOT") diff --git a/test/run-drun/ok/idl-bad.ic-stub-run.ok b/test/run-drun/ok/idl-bad.ic-stub-run.ok index 41e9c36d7b5..fbf26698058 100644 --- a/test/run-drun/ok/idl-bad.ic-stub-run.ok +++ b/test/run-drun/ok/idl-bad.ic-stub-run.ok @@ -1,2 +1,2 @@ Completed CompleteUnit -Rejected (0,"canister trapped: EvalTrapError :0.1 \"explicit trap\"") +Rejected (RC_CANISTER_ERROR,"canister trapped: EvalTrapError :0.1 \"explicit trap\"") diff --git a/test/run-drun/ok/idl-nary.ic-stub-run.ok b/test/run-drun/ok/idl-nary.ic-stub-run.ok index 40f8313bdb1..b43c326c422 100644 --- a/test/run-drun/ok/idl-nary.ic-stub-run.ok +++ b/test/run-drun/ok/idl-nary.ic-stub-run.ok @@ -7,6 +7,6 @@ Completed (CompleteArg "DIDL\SOHl\EOT\NULq\SOHq\STXq\ETXq\SOH\NUL\ETXOne\ETXTwo\ Completed (CompleteArg "DIDL\SOHl\EOT\NULq\SOHq\STXq\ETXq\SOH\NUL\ETXOne\ETXTwo\ENQThree\EOTFour") Completed (CompleteArg "DIDL\SOHl\EOT\NULq\SOHq\STXq\ETXq\SOH\NUL\ETXOne\ETXTwo\ENQThree\EOTFour") Completed (CompleteArg "DIDL\SOHl\EOT\NULq\SOHq\STXq\ETXq\SOH\NUL\ETXOne\ETXTwo\ENQThree\EOTFour") -Rejected (0,"canister trapped: EvalTrapError :0.1 \"explicit trap\"") -Rejected (0,"canister trapped: EvalTrapError :0.1 \"explicit trap\"") +Rejected (RC_CANISTER_ERROR,"canister trapped: EvalTrapError :0.1 \"explicit trap\"") +Rejected (RC_CANISTER_ERROR,"canister trapped: EvalTrapError :0.1 \"explicit trap\"") Completed (CompleteArg "DIDL\NUL\EOTqqqq\ETXOne\ETXTwo\ENQThree\EOTFour") diff --git a/test/run-drun/ok/oom.ic-stub-run.ok b/test/run-drun/ok/oom.ic-stub-run.ok index 3e1fe57f769..72e8d4a465d 100644 --- a/test/run-drun/ok/oom.ic-stub-run.ok +++ b/test/run-drun/ok/oom.ic-stub-run.ok @@ -1,3 +1,3 @@ Completed CompleteUnit -Rejected (0,"canister did not respond") -Rejected (0,"canister did not respond") +Rejected (RC_CANISTER_ERROR,"canister did not respond") +Rejected (RC_CANISTER_ERROR,"canister did not respond") diff --git a/test/run-drun/ok/query.ic-stub-run.ok b/test/run-drun/ok/query.ic-stub-run.ok index 2564ce843e0..0baa5f670d2 100644 --- a/test/run-drun/ok/query.ic-stub-run.ok +++ b/test/run-drun/ok/query.ic-stub-run.ok @@ -1,18 +1,18 @@ Completed CompleteUnit 2 -Rejected (0,"canister did not respond") +Rejected (RC_CANISTER_ERROR,"canister did not respond") 3 -Rejected (0,"canister did not respond") +Rejected (RC_CANISTER_ERROR,"canister did not respond") 4 -Rejected (0,"canister did not respond") +Rejected (RC_CANISTER_ERROR,"canister did not respond") 4 -Rejected (0,"canister did not respond") +Rejected (RC_CANISTER_ERROR,"canister did not respond") Completed (CompleteArg "DIDL\NUL\SOH}\EOT") 5 Completed (CompleteArg "DIDL\NUL\SOH}\EOT") 4 -Rejected (0,"canister did not respond") +Rejected (RC_CANISTER_ERROR,"canister did not respond") 5 Completed (CompleteArg "DIDL\NUL\SOH}\EOT") 4 -Rejected (0,"canister did not respond") +Rejected (RC_CANISTER_ERROR,"canister did not respond") diff --git a/test/run-drun/ok/reject.ic-stub-run.ok b/test/run-drun/ok/reject.ic-stub-run.ok index 557b22fc81c..d25795f150d 100644 --- a/test/run-drun/ok/reject.ic-stub-run.ok +++ b/test/run-drun/ok/reject.ic-stub-run.ok @@ -1,4 +1,4 @@ Completed CompleteUnit -1Rejected (0,"canister trapped: EvalTrapError :0.1 \"unimplemented: reject\"") +1Rejected (RC_CANISTER_REJECT,"Error") 1okCompleted (CompleteArg "DIDL\NUL\NUL") -1okRejected (0,"canister trapped: EvalTrapError :0.1 \"unimplemented: reject\"") +1okRejected (RC_CANISTER_REJECT,"Error") diff --git a/test/run-drun/ok/reversi.ic-stub-run.ok b/test/run-drun/ok/reversi.ic-stub-run.ok index 66e2cccdbc4..820e9b16754 100644 --- a/test/run-drun/ok/reversi.ic-stub-run.ok +++ b/test/run-drun/ok/reversi.ic-stub-run.ok @@ -1,5 +1,5 @@ Completed CompleteUnit -Rejected (0,"canister did not respond") +Rejected (RC_CANISTER_ERROR,"canister did not respond") Completed (CompleteArg "DIDL\NUL\SOHqH........\n........\n........\n...O*...\n...*O...\n........\n........\n........\n") Completed (CompleteArg "DIDL\NUL\SOHq\STXOK") Completed (CompleteArg "DIDL\NUL\SOHqH........\n........\n....O...\n...OO...\n...*O...\n........\n........\n........\n") From c7000463cc33cef9e42e1303b75bb755aafb8861 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 8 Nov 2019 18:19:06 +0100 Subject: [PATCH 0538/1176] ic-stub-run: More prettily print requests and responses --- ic-stub/ic-stub.cabal | 1 + ic-stub/src/IC/Stub.hs | 2 +- ic-stub/src/ic-stub-run.hs | 63 ++++++++-- test/drun-wrapper.sh | 2 +- test/run-drun/ok/counter.ic-stub-run.ok | 26 +++- .../ok/hello-world-return.ic-stub-run.ok | 9 +- test/run-drun/ok/idl-any.ic-stub-run.ok | 115 +++++++++++++----- test/run-drun/ok/idl-bad.ic-stub-run.ok | 6 +- .../ok/idl-field-escape.ic-stub-run.ok | 15 ++- test/run-drun/ok/idl-nary.ic-stub-run.ok | 36 ++++-- test/run-drun/ok/idl-nat-int.ic-stub-run.ok | 15 ++- test/run-drun/ok/idl-option.ic-stub-run.ok | 15 ++- test/run-drun/ok/idl-pair.ic-stub-run.ok | 6 +- test/run-drun/ok/idl-record.ic-stub-run.ok | 19 ++- test/run-drun/ok/idl-tuple.ic-stub-run.ok | 15 ++- test/run-drun/ok/idl-unit.ic-stub-run.ok | 6 +- test/run-drun/ok/idl-variant.ic-stub-run.ok | 6 +- test/run-drun/ok/idl-vector.ic-stub-run.ok | 6 +- test/run-drun/ok/oom.ic-stub-run.ok | 9 +- .../ok/print-from-init.ic-stub-run.ok | 4 +- test/run-drun/ok/query.ic-stub-run.ok | 46 +++++-- test/run-drun/ok/reject.ic-stub-run.ok | 17 ++- test/run-drun/ok/reversi.ic-stub-run.ok | 27 ++-- 23 files changed, 346 insertions(+), 120 deletions(-) diff --git a/ic-stub/ic-stub.cabal b/ic-stub/ic-stub.cabal index 5fc71bf20c4..dc344acbd95 100644 --- a/ic-stub/ic-stub.cabal +++ b/ic-stub/ic-stub.cabal @@ -25,5 +25,6 @@ executable ic-stub-run build-depends: vector build-depends: primitive build-depends: utf8-string + build-depends: hex-text default-language: Haskell2010 ghc-options: -rtsopts diff --git a/ic-stub/src/IC/Stub.hs b/ic-stub/src/IC/Stub.hs index d04aa310b38..a335c6f002e 100644 --- a/ic-stub/src/IC/Stub.hs +++ b/ic-stub/src/IC/Stub.hs @@ -357,7 +357,7 @@ modES (_, esref) f = lift $ modifySTRef esref (fmap f) putBytes :: PrimMonad m => ESRef (PrimState m) -> BS.ByteString -> m () putBytes (pref, _esref) bytes = stToPrim (readSTRef pref) >>= \case - True -> unsafeIOToPrim (BS.putStr bytes) + True -> unsafeIOToPrim (BSC.putStrLn bytes) False -> return () diff --git a/ic-stub/src/ic-stub-run.hs b/ic-stub/src/ic-stub-run.hs index b111bcc2d7f..3f809b7da29 100644 --- a/ic-stub/src/ic-stub-run.hs +++ b/ic-stub/src/ic-stub-run.hs @@ -8,21 +8,73 @@ import Control.Monad (join, foldM_, forM_) import Data.Monoid ((<>)) import System.FilePath import qualified Data.ByteString.Lazy as B +import Control.Monad.Trans import Control.Monad.Trans.State import Control.Monad.IO.Class +import qualified Data.Text as T +import qualified Text.Hex as T +import Text.Printf import IC.DRun.Parse (Type(..), parseFile) import IC.Stub - (ICT, IC, AsyncRequest(..), SyncRequest(..), requestId, ReqResponse(..), + (Blob, EntityId, + IC, AsyncRequest(..), SyncRequest(..), requestId, ReqResponse(..), + RequestStatus(..), CompletionValue(..), initialIC, submitRequest, readRequest, runToCompletion) type DRun = StateT IC IO +-- Pretty printing + +prettyBlob :: Blob -> String +prettyBlob b = "0x" ++ T.unpack (T.encodeHex (B.toStrict b)) + +prettyID :: EntityId -> String +prettyID = prettyBlob -- implement the "ic:…" stuff + +printAsyncRequest :: AsyncRequest -> IO () +printAsyncRequest (InstallRequest _ _) = + printf "→ install\n" +printAsyncRequest (UpdateRequest method arg) = + printf "→ update %s(%s)\n" method (prettyBlob arg) + +printSyncRequest :: SyncRequest -> IO () +printSyncRequest (StatusRequest rid) = + printf "→ status? %s\n" (prettyBlob rid) +printSyncRequest (QueryRequest method arg) = + printf "→ query %s(%s)\n" method (prettyBlob arg) + +printReqStatus :: RequestStatus -> IO () +printReqStatus Unknown = + printf "← unknown\n" +printReqStatus Received = + printf "← received\n" +printReqStatus Processing = + printf "← processing\n" +printReqStatus (Rejected (c, s)) = + printf "← rejected (%s): %s\n" (show c) s +printReqStatus (Completed CompleteUnit) = + printf "← completed\n" +printReqStatus (Completed (CompleteCanisterId id)) = + printf "← completed: canister-id = %s\n" (prettyID id) +printReqStatus (Completed (CompleteArg blob)) = + printf "← completed: %s\n" (prettyBlob blob) + submitAndRun :: AsyncRequest -> DRun ReqResponse submitAndRun r = do + lift $ printAsyncRequest r submitRequest r runToCompletion - readRequest (StatusRequest (requestId r)) + r <- readRequest (StatusRequest (requestId r)) + lift $ printReqStatus r + return r + +submitRead :: SyncRequest -> DRun ReqResponse +submitRead r = do + lift $ printSyncRequest r + r <- readRequest r + lift $ printReqStatus r + return r work :: FilePath -> FilePath -> IO () work wasm_file msg_file = do @@ -31,12 +83,9 @@ work wasm_file msg_file = do flip evalStateT initialIC $ do req_res <- submitAndRun (InstallRequest wasm B.empty) - liftIO $ print req_res -- assert completed forM_ msgs $ \case - (Query, method, arg) -> - readRequest (QueryRequest method arg) >>= liftIO . print - (Update, method, arg) -> - submitAndRun (UpdateRequest method arg) >>= liftIO . print + (Query, method, arg) -> submitRead (QueryRequest method arg) + (Update, method, arg) -> submitAndRun (UpdateRequest method arg) main :: IO () main = join . customExecParser (prefs showHelpOnError) $ diff --git a/test/drun-wrapper.sh b/test/drun-wrapper.sh index 167723a32d9..d5b0bbcd61f 100755 --- a/test/drun-wrapper.sh +++ b/test/drun-wrapper.sh @@ -11,7 +11,7 @@ then exit 1 fi -export LANG=C +export LANG=C.UTF-8 ( if [ -n "$2" ]; then grep '^//CALL ' $2 | cut -c8-; fi;) | $DRUN -c "$CONFIG" $1 /dev/stdin diff --git a/test/run-drun/ok/counter.ic-stub-run.ok b/test/run-drun/ok/counter.ic-stub-run.ok index 19d189c14e3..21a9c0406fa 100644 --- a/test/run-drun/ok/counter.ic-stub-run.ok +++ b/test/run-drun/ok/counter.ic-stub-run.ok @@ -1,10 +1,24 @@ -Completed CompleteUnit +→ install +← completed +→ update inc(0x4449444c0000) 2 -Rejected (RC_CANISTER_ERROR,"canister did not respond") + + +← rejected (RC_CANISTER_ERROR): canister did not respond +→ update inc(0x4449444c0000) 3 -Rejected (RC_CANISTER_ERROR,"canister did not respond") + + +← rejected (RC_CANISTER_ERROR): canister did not respond +→ update inc(0x4449444c0000) 4 -Rejected (RC_CANISTER_ERROR,"canister did not respond") + + +← rejected (RC_CANISTER_ERROR): canister did not respond +→ update printCounter(0x4449444c0000) 4 -Rejected (RC_CANISTER_ERROR,"canister did not respond") -Completed (CompleteArg "DIDL\NUL\SOH}\EOT") + + +← rejected (RC_CANISTER_ERROR): canister did not respond +→ update get(0x4449444c0000) +← completed: 0x4449444c00017d04 diff --git a/test/run-drun/ok/hello-world-return.ic-stub-run.ok b/test/run-drun/ok/hello-world-return.ic-stub-run.ok index 336b95741ee..1cee502a7a2 100644 --- a/test/run-drun/ok/hello-world-return.ic-stub-run.ok +++ b/test/run-drun/ok/hello-world-return.ic-stub-run.ok @@ -1,3 +1,6 @@ -Completed CompleteUnit -Completed (CompleteArg "DIDL\NUL\SOHq\fHello World!") -Completed (CompleteArg "DIDL\NUL\SOHq\fHello World!") +→ install +← completed +→ query hello(0x4449444c00017105576f726c64) +← completed: 0x4449444c0001710c48656c6c6f20576f726c6421 +→ query hello2(0x4449444c00017105576f726c64) +← completed: 0x4449444c0001710c48656c6c6f20576f726c6421 diff --git a/test/run-drun/ok/idl-any.ic-stub-run.ok b/test/run-drun/ok/idl-any.ic-stub-run.ok index 4fc6a8f2e7e..d655b4a2ed2 100644 --- a/test/run-drun/ok/idl-any.ic-stub-run.ok +++ b/test/run-drun/ok/idl-any.ic-stub-run.ok @@ -1,29 +1,86 @@ -Completed CompleteUnit -ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") -ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") -ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") -ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") -ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") -ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") -ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") -ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") -ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") -ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") -ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") -ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") -ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") -ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") -ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") -ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") -ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") -ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") -ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") -ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") -ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") -ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") -ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") -ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") -ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") -ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") -ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") -ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") +→ install +← completed +→ update any(0x4449444c00027f7103466f6f) +ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c00027e710103466f6f) +ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c00027d718080800803466f6f) +ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c00027c718080800803466f6f) +ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c00027b71ab03466f6f) +ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c00027a71abcd03466f6f) +ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c00027971deadbeef03466f6f) +ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c00027871deadbeefcaffee6603466f6f) +ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c00027771ab03466f6f) +ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c00027671abcd03466f6f) +ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c00027571deadbeef03466f6f) +ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c00027471deadbeefcaffee6603466f6f) +ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c00027371deadbeef03466f6f) +ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c00027271deadbeefcaffee6603466f6f) +ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c0002717103466f6f03466f6f) +ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c0002707103466f6f) +ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c016e710200710003466f6f) +ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c016e710200710103466f6f03466f6f) +ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c016d710200710003466f6f) +ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c016d710200710103466f6f03466f6f) +ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c016d71020071020003466f6f03466f6f) +ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c016c0002007103466f6f) +ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c016c01800175020071deadbeef03466f6f) +ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c016c02007180017502007101a0deadbeef03466f6f) +ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c016b0180017502007100deadbeef03466f6f) +ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c016b0200718001750200710001a003466f6f) +ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c016b02007180017502007101deadbeef03466f6f) +ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c016602abcd0200710400deadbeef03466f6f) +ok: Foo +← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-bad.ic-stub-run.ok b/test/run-drun/ok/idl-bad.ic-stub-run.ok index fbf26698058..d05cb778cd4 100644 --- a/test/run-drun/ok/idl-bad.ic-stub-run.ok +++ b/test/run-drun/ok/idl-bad.ic-stub-run.ok @@ -1,2 +1,4 @@ -Completed CompleteUnit -Rejected (RC_CANISTER_ERROR,"canister trapped: EvalTrapError :0.1 \"explicit trap\"") +→ install +← completed +→ query foo(0x4e4f544449444c) +← rejected (RC_CANISTER_ERROR): canister trapped: EvalTrapError :0.1 "explicit trap" diff --git a/test/run-drun/ok/idl-field-escape.ic-stub-run.ok b/test/run-drun/ok/idl-field-escape.ic-stub-run.ok index 74e03a71ffe..315382546b0 100644 --- a/test/run-drun/ok/idl-field-escape.ic-stub-run.ok +++ b/test/run-drun/ok/idl-field-escape.ic-stub-run.ok @@ -1,5 +1,10 @@ -Completed CompleteUnit -Completed (CompleteArg "DIDL\STXl\SOH\134\142\183\STX\SOHl\NUL\SOH\NUL") -Completed (CompleteArg "DIDL\STXl\SOH\134\142\183\STX\SOHl\NUL\SOH\NUL") -Completed (CompleteArg "DIDL\SOHl\ETX\NUL|\SOH}\188\254\247\177\STXq\SOH\NUL\255\255\ETX\128 \ETXXXX") -Completed (CompleteArg "DIDL\NUL\NUL") +→ install +← completed +→ update foo1(0x4449444c0000) +← completed: 0x4449444c026c01868eb702016c000100 +→ update foo2(0x4449444c0000) +← completed: 0x4449444c026c01868eb702016c000100 +→ update out(0x4449444c0000) +← completed: 0x4449444c016c03007c017dbcfef7b102710100ffff03802003585858 +→ update input(0x4449444c016c03007c017dbcfef7b102710100ffff03802003585858) +← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-nary.ic-stub-run.ok b/test/run-drun/ok/idl-nary.ic-stub-run.ok index b43c326c422..9b62b925bcd 100644 --- a/test/run-drun/ok/idl-nary.ic-stub-run.ok +++ b/test/run-drun/ok/idl-nary.ic-stub-run.ok @@ -1,12 +1,24 @@ -Completed CompleteUnit -Completed (CompleteArg "DIDL\NUL\STXqq\ETXOne\ETXTwo") -Completed (CompleteArg "DIDL\NUL\ETXqqq\ETXOne\ETXTwo\ENQThree") -Completed (CompleteArg "DIDL\NUL\EOTqqqq\ETXOne\ETXTwo\ENQThree\EOTFour") -Completed (CompleteArg "DIDL\SOHl\EOT\NULq\SOHq\STXq\ETXq\SOH\NUL\ETXOne\ETXTwo\ENQThree\EOTFour") -Completed (CompleteArg "DIDL\SOHl\EOT\NULq\SOHq\STXq\ETXq\SOH\NUL\ETXOne\ETXTwo\ENQThree\EOTFour") -Completed (CompleteArg "DIDL\SOHl\EOT\NULq\SOHq\STXq\ETXq\SOH\NUL\ETXOne\ETXTwo\ENQThree\EOTFour") -Completed (CompleteArg "DIDL\SOHl\EOT\NULq\SOHq\STXq\ETXq\SOH\NUL\ETXOne\ETXTwo\ENQThree\EOTFour") -Completed (CompleteArg "DIDL\SOHl\EOT\NULq\SOHq\STXq\ETXq\SOH\NUL\ETXOne\ETXTwo\ENQThree\EOTFour") -Rejected (RC_CANISTER_ERROR,"canister trapped: EvalTrapError :0.1 \"explicit trap\"") -Rejected (RC_CANISTER_ERROR,"canister trapped: EvalTrapError :0.1 \"explicit trap\"") -Completed (CompleteArg "DIDL\NUL\EOTqqqq\ETXOne\ETXTwo\ENQThree\EOTFour") +→ install +← completed +→ update two(0x4449444c00027171034f6e650354776f) +← completed: 0x4449444c00027171034f6e650354776f +→ update three(0x4449444c0003717171034f6e650354776f055468726565) +← completed: 0x4449444c0003717171034f6e650354776f055468726565 +→ update four(0x4449444c000471717171034f6e650354776f05546872656504466f7572) +← completed: 0x4449444c000471717171034f6e650354776f05546872656504466f7572 +→ update mkRecord(0x4449444c0000) +← completed: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 +→ update unary1(0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572) +← completed: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 +→ update unary2(0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572) +← completed: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 +→ update unary3(0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572) +← completed: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 +→ update unary4(0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572) +← completed: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 +→ update three(0x4449444c00027171034f6e650354776f) +← rejected (RC_CANISTER_ERROR): canister trapped: EvalTrapError :0.1 "explicit trap" +→ update three(0x4449444c0003717171034f6e650354776f05546872656545585452414259544553) +← rejected (RC_CANISTER_ERROR): canister trapped: EvalTrapError :0.1 "explicit trap" +→ update four(0x4449444c00057171717171034f6e650354776f05546872656504466f75720446697665) +← completed: 0x4449444c000471717171034f6e650354776f05546872656504466f7572 diff --git a/test/run-drun/ok/idl-nat-int.ic-stub-run.ok b/test/run-drun/ok/idl-nat-int.ic-stub-run.ok index 6e785d7eab2..0a8265cff65 100644 --- a/test/run-drun/ok/idl-nat-int.ic-stub-run.ok +++ b/test/run-drun/ok/idl-nat-int.ic-stub-run.ok @@ -1,5 +1,10 @@ -Completed CompleteUnit -Completed (CompleteArg "DIDL\NUL\SOH}*") -Completed (CompleteArg "DIDL\NUL\SOH}*") -Completed (CompleteArg "DIDL\SOHm}\SOH\NUL\STX*\EM") -Completed (CompleteArg "DIDL\SOHm}\SOH\NUL\STX*\EM") +→ install +← completed +→ query absolute(0x4449444c00017d2a) +← completed: 0x4449444c00017d2a +→ query absolute(0x4449444c00017c56) +← completed: 0x4449444c00017d2a +→ query absolutes(0x4449444c016d7d0100022a19) +← completed: 0x4449444c016d7d0100022a19 +→ query absolutes(0x4449444c016d7c0100025619) +← completed: 0x4449444c016d7d0100022a19 diff --git a/test/run-drun/ok/idl-option.ic-stub-run.ok b/test/run-drun/ok/idl-option.ic-stub-run.ok index 6576da2108b..bc846d92318 100644 --- a/test/run-drun/ok/idl-option.ic-stub-run.ok +++ b/test/run-drun/ok/idl-option.ic-stub-run.ok @@ -1,4 +1,11 @@ -Completed CompleteUnit -ok: nullCompleted (CompleteArg "DIDL\NUL\NUL") -ok: nullCompleted (CompleteArg "DIDL\NUL\NUL") -ok: FooCompleted (CompleteArg "DIDL\NUL\NUL") +→ install +← completed +→ update any(0x4449444c00017f) +ok: null +← completed: 0x4449444c0000 +→ update any(0x4449444c016e71010000) +ok: null +← completed: 0x4449444c0000 +→ update any(0x4449444c016e7101000103466f6f) +ok: Foo +← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-pair.ic-stub-run.ok b/test/run-drun/ok/idl-pair.ic-stub-run.ok index b422faf3acd..e4895464782 100644 --- a/test/run-drun/ok/idl-pair.ic-stub-run.ok +++ b/test/run-drun/ok/idl-pair.ic-stub-run.ok @@ -1,2 +1,4 @@ -Completed CompleteUnit -Completed (CompleteArg "DIDL\SOHl\STX\NUL|\SOH|\SOH\NUL\STX\ENQ") +→ install +← completed +→ update len2(0x4449444c0002717102486905576f726c64) +← completed: 0x4449444c016c02007c017c01000205 diff --git a/test/run-drun/ok/idl-record.ic-stub-run.ok b/test/run-drun/ok/idl-record.ic-stub-run.ok index 91cd95622a0..b4dc531fddd 100644 --- a/test/run-drun/ok/idl-record.ic-stub-run.ok +++ b/test/run-drun/ok/idl-record.ic-stub-run.ok @@ -1,5 +1,14 @@ -Completed CompleteUnit -ok: +42Completed (CompleteArg "DIDL\NUL\NUL") -ok: Hey!Completed (CompleteArg "DIDL\NUL\NUL") -ok: +25Completed (CompleteArg "DIDL\NUL\NUL") -ok: Hey! +25Completed (CompleteArg "DIDL\NUL\SOHw\EM") +→ install +← completed +→ update pair(0x4449444c016c020071017c010004486579212a) +ok: +42 +← completed: 0x4449444c0000 +→ update record(0x4449444c016c02b99adecb0171f1fee18d037c010004486579212a) +ok: Hey! +← completed: 0x4449444c0000 +→ update record1(0x4449444c016c03b99adecb0171f1fee18d037c88be8c890477010004486579212a19) +ok: +25 +← completed: 0x4449444c0000 +→ update record2(0x4449444c016c03b99adecb0171f1fee18d037c88be8c89047702007704486579212a1819) +ok: Hey! +25 +← completed: 0x4449444c00017719 diff --git a/test/run-drun/ok/idl-tuple.ic-stub-run.ok b/test/run-drun/ok/idl-tuple.ic-stub-run.ok index 1ae4c051cbe..a556a084e35 100644 --- a/test/run-drun/ok/idl-tuple.ic-stub-run.ok +++ b/test/run-drun/ok/idl-tuple.ic-stub-run.ok @@ -1,5 +1,10 @@ -Completed CompleteUnit -Completed (CompleteArg "DIDL\NUL\STX||\STX\ENQ") -Completed (CompleteArg "DIDL\NUL\ETX|||\ENQ\ENQ\129\132\140 ") -Completed (CompleteArg "DIDL\NUL\ETX|||\ENQ\ENQ\129\132\140 ") -Completed (CompleteArg "DIDL\NUL\ETX|||\ENQ\ENQ\129\132\140 ") +→ install +← completed +→ query len2(0x4449444c0002717102486905576f726c64) +← completed: 0x4449444c00027c7c0205 +→ query len3(0x4449444c016c02007101750200710548656c6c6f0102030405576f726c64) +← completed: 0x4449444c00037c7c7c050581848c20 +→ query len3(0x4449444c016c030071007601750200710548656c6c6fdead0102030405576f726c64) +← completed: 0x4449444c00037c7c7c050581848c20 +→ query len3(0x4449444c016c030071017502760200710548656c6c6f01020304dead05576f726c64) +← completed: 0x4449444c00037c7c7c050581848c20 diff --git a/test/run-drun/ok/idl-unit.ic-stub-run.ok b/test/run-drun/ok/idl-unit.ic-stub-run.ok index 97dececaebe..e552c46999b 100644 --- a/test/run-drun/ok/idl-unit.ic-stub-run.ok +++ b/test/run-drun/ok/idl-unit.ic-stub-run.ok @@ -1,2 +1,4 @@ -Completed CompleteUnit -Completed (CompleteArg "DIDL\NUL\NUL") +→ install +← completed +→ query unit_id(0x4449444c0000) +← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-variant.ic-stub-run.ok b/test/run-drun/ok/idl-variant.ic-stub-run.ok index c0f575a70ae..0aa8f35ad28 100644 --- a/test/run-drun/ok/idl-variant.ic-stub-run.ok +++ b/test/run-drun/ok/idl-variant.ic-stub-run.ok @@ -1,2 +1,4 @@ -Completed CompleteUnit -Completed (CompleteArg "DIDL\SOHk\ETX\213\131\183\STX\NUL\135\144\192\189\EOTy\220\151\144\203\SOy\SOH\NUL\NUL\SOH \NUL\NUL\NUL") +→ install +← completed +→ query numify(0x4449444c016b03d583b702008790c0bd0479dc9790cb0e790100000220000000) +← completed: 0x4449444c016b03d583b702008790c0bd0479dc9790cb0e790100000120000000 diff --git a/test/run-drun/ok/idl-vector.ic-stub-run.ok b/test/run-drun/ok/idl-vector.ic-stub-run.ok index 8187ff9d804..c6f75bb92ab 100644 --- a/test/run-drun/ok/idl-vector.ic-stub-run.ok +++ b/test/run-drun/ok/idl-vector.ic-stub-run.ok @@ -1,2 +1,4 @@ -Completed CompleteUnit -Completed (CompleteArg "DIDL\STXn\SOHm\NUL\SOH\NUL\SOH\ETX\SOH\NUL\SOH\EOT\SOH\NUL\SOH\STX\SOH\NUL\SOH\NUL\SOH\NUL\SOH\NUL\SOH\NUL") +→ install +← completed +→ query rose(0x4449444c016d00010003000400020000000000) +← completed: 0x4449444c026e016d0001000103010001040100010201000100010001000100 diff --git a/test/run-drun/ok/oom.ic-stub-run.ok b/test/run-drun/ok/oom.ic-stub-run.ok index 72e8d4a465d..267aee6dadb 100644 --- a/test/run-drun/ok/oom.ic-stub-run.ok +++ b/test/run-drun/ok/oom.ic-stub-run.ok @@ -1,3 +1,6 @@ -Completed CompleteUnit -Rejected (RC_CANISTER_ERROR,"canister did not respond") -Rejected (RC_CANISTER_ERROR,"canister did not respond") +→ install +← completed +→ update doloop(0x4449444c0000) +← rejected (RC_CANISTER_ERROR): canister did not respond +→ update doloop(0x4449444c0000) +← rejected (RC_CANISTER_ERROR): canister did not respond diff --git a/test/run-drun/ok/print-from-init.ic-stub-run.ok b/test/run-drun/ok/print-from-init.ic-stub-run.ok index 3694857207b..6daaa454e15 100644 --- a/test/run-drun/ok/print-from-init.ic-stub-run.ok +++ b/test/run-drun/ok/print-from-init.ic-stub-run.ok @@ -1 +1,3 @@ -Debug outCompleted CompleteUnit +→ install +Debug out +← completed diff --git a/test/run-drun/ok/query.ic-stub-run.ok b/test/run-drun/ok/query.ic-stub-run.ok index 0baa5f670d2..eabf7fa916c 100644 --- a/test/run-drun/ok/query.ic-stub-run.ok +++ b/test/run-drun/ok/query.ic-stub-run.ok @@ -1,18 +1,44 @@ -Completed CompleteUnit +→ install +← completed +→ update inc(0x4449444c0000) 2 -Rejected (RC_CANISTER_ERROR,"canister did not respond") + + +← rejected (RC_CANISTER_ERROR): canister did not respond +→ update inc(0x4449444c0000) 3 -Rejected (RC_CANISTER_ERROR,"canister did not respond") + + +← rejected (RC_CANISTER_ERROR): canister did not respond +→ update inc(0x4449444c0000) 4 -Rejected (RC_CANISTER_ERROR,"canister did not respond") + + +← rejected (RC_CANISTER_ERROR): canister did not respond +→ update printCounter(0x4449444c0000) 4 -Rejected (RC_CANISTER_ERROR,"canister did not respond") -Completed (CompleteArg "DIDL\NUL\SOH}\EOT") + + +← rejected (RC_CANISTER_ERROR): canister did not respond +→ update get(0x4449444c0000) +← completed: 0x4449444c00017d04 +→ query read(0x4449444c0000) 5 -Completed (CompleteArg "DIDL\NUL\SOH}\EOT") + + +← completed: 0x4449444c00017d04 +→ update printCounter(0x4449444c0000) 4 -Rejected (RC_CANISTER_ERROR,"canister did not respond") + + +← rejected (RC_CANISTER_ERROR): canister did not respond +→ query read(0x4449444c0000) 5 -Completed (CompleteArg "DIDL\NUL\SOH}\EOT") + + +← completed: 0x4449444c00017d04 +→ update printCounter(0x4449444c0000) 4 -Rejected (RC_CANISTER_ERROR,"canister did not respond") + + +← rejected (RC_CANISTER_ERROR): canister did not respond diff --git a/test/run-drun/ok/reject.ic-stub-run.ok b/test/run-drun/ok/reject.ic-stub-run.ok index d25795f150d..1b0f835527b 100644 --- a/test/run-drun/ok/reject.ic-stub-run.ok +++ b/test/run-drun/ok/reject.ic-stub-run.ok @@ -1,4 +1,13 @@ -Completed CompleteUnit -1Rejected (RC_CANISTER_REJECT,"Error") -1okCompleted (CompleteArg "DIDL\NUL\NUL") -1okRejected (RC_CANISTER_REJECT,"Error") +→ install +← completed +→ update reject1(0x4449444c0000) +1 +← rejected (RC_CANISTER_REJECT): Error +→ update reject2(0x4449444c0000) +1 +ok +← completed: 0x4449444c0000 +→ update reject3(0x4449444c0000) +1 +ok +← rejected (RC_CANISTER_REJECT): Error diff --git a/test/run-drun/ok/reversi.ic-stub-run.ok b/test/run-drun/ok/reversi.ic-stub-run.ok index 820e9b16754..71270e26ac3 100644 --- a/test/run-drun/ok/reversi.ic-stub-run.ok +++ b/test/run-drun/ok/reversi.ic-stub-run.ok @@ -1,9 +1,18 @@ -Completed CompleteUnit -Rejected (RC_CANISTER_ERROR,"canister did not respond") -Completed (CompleteArg "DIDL\NUL\SOHqH........\n........\n........\n...O*...\n...*O...\n........\n........\n........\n") -Completed (CompleteArg "DIDL\NUL\SOHq\STXOK") -Completed (CompleteArg "DIDL\NUL\SOHqH........\n........\n....O...\n...OO...\n...*O...\n........\n........\n........\n") -Completed (CompleteArg "DIDL\NUL\SOHq\STXOK") -Completed (CompleteArg "DIDL\NUL\SOHqH........\n........\n...*O...\n...*O...\n...*O...\n........\n........\n........\n") -Completed (CompleteArg "DIDL\NUL\SOHq\STXOK") -Completed (CompleteArg "DIDL\NUL\SOHqH........\n........\n...*O...\n...OO...\n..OOO...\n........\n........\n........\n") +→ install +← completed +→ update reset(0x4449444c0000) +← rejected (RC_CANISTER_ERROR): canister did not respond +→ update board(0x4449444c0000) +← completed: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e4f2a2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a +→ update place(0x4449444c00037c7c7c010204) +← completed: 0x4449444c000171024f4b +→ update board(0x4449444c0000) +← completed: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e4f2e2e2e0a2e2e2e4f4f2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a +→ update place(0x4449444c00037c7c7c020203) +← completed: 0x4449444c000171024f4b +→ update board(0x4449444c0000) +← completed: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a +→ update place(0x4449444c00037c7c7c010402) +← completed: 0x4449444c000171024f4b +→ update board(0x4449444c0000) +← completed: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e4f4f2e2e2e0a2e2e4f4f4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a From bc112b8ecdb73914fa7d65083fb711abf0974380 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 8 Nov 2019 18:52:25 +0100 Subject: [PATCH 0539/1176] =?UTF-8?q?Resurrect=20=E2=80=9Ccalling=20a=20sh?= =?UTF-8?q?ared=20function=20not=20yet=20supported=E2=80=9D=20error=20(#84?= =?UTF-8?q?2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This got removed in #804, but that was premature: That PR merely makes the _old_ platform use an IR interface that is closer to the new platform, but the _new_ platform did not gain any new features. (But soon...) --- src/mo_frontend/typing.ml | 3 +-- test/run-drun/ok/ic-calls.comp.ok | 16 +++++++++++++++- test/run-drun/ok/ic-calls.comp.ret.ok | 2 +- test/run-drun/ok/unsupported.comp.ok | 2 ++ 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 92b0841b324..5d59b005854 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -753,8 +753,7 @@ and infer_exp'' env exp : T.typ = if T.is_async t_ret && not in_await then error_in [Flags.ICMode] env exp2.at "shared, async function must be called within an await expression"; - if t_ret = T.unit then - error_in [Flags.ICMode] env exp1.at "calling a oneway shared function not yet supported"; + error_in [Flags.ICMode] env exp1.at "calling a shared function not yet supported"; if not (T.concrete t_arg) then error env exp1.at "shared function argument contains abstract type\n %s" diff --git a/test/run-drun/ok/ic-calls.comp.ok b/test/run-drun/ok/ic-calls.comp.ok index 3c98a1fe547..e753cbd283c 100644 --- a/test/run-drun/ok/ic-calls.comp.ok +++ b/test/run-drun/ok/ic-calls.comp.ok @@ -1 +1,15 @@ -Fatal error: exception "Assert_failure codegen/compile.ml:6441:8" +ic-calls.mo:18.9-18.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +ic-calls.mo:19.9-19.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (1, false) or + (0 or -1 or _, _) +ic-calls.mo:17.20-17.21: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +ic-calls.mo:18.19-18.20: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +ic-calls.mo:19.26-19.27: type error, calling a shared function not yet supported + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/ic-calls.comp.ret.ok b/test/run-drun/ok/ic-calls.comp.ret.ok index 63e15a4d3fa..69becfa16f9 100644 --- a/test/run-drun/ok/ic-calls.comp.ret.ok +++ b/test/run-drun/ok/ic-calls.comp.ret.ok @@ -1 +1 @@ -Return code 2 +Return code 1 diff --git a/test/run-drun/ok/unsupported.comp.ok b/test/run-drun/ok/unsupported.comp.ok index 9b4b2c70f19..fa8f5d395b1 100644 --- a/test/run-drun/ok/unsupported.comp.ok +++ b/test/run-drun/ok/unsupported.comp.ok @@ -16,6 +16,8 @@ unsupported.mo:8.31-8.53: type error, shared function types are non-shared. (This is a limitation of the current version.) unsupported.mo:19.19-19.21: type error, shared, async function must be called within an await expression (This is a limitation of the current version.) +unsupported.mo:23.16-23.18: type error, calling a shared function not yet supported + (This is a limitation of the current version.) unsupported.mo:28.8-28.9: type error, argument to await must be a call expression (This is a limitation of the current version.) unsupported.mo:32.17-32.29: type error, unsupported async block From 53317f4e619ca2cb9fb870632fcf36296ab6e651 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Fri, 8 Nov 2019 18:40:21 +0000 Subject: [PATCH 0540/1176] Fix for GIT-843 --- src/ir_def/check_ir.ml | 5 ++--- src/ir_interpreter/interpret_ir.ml | 8 +++++--- test/run-dfinity/GIT-843.mo | 6 ++++++ test/run-dfinity/ok/GIT-843.dvm.ok | 1 + test/run-dfinity/ok/GIT-843.run-ir.ok | 1 + test/run-dfinity/ok/GIT-843.run-low.ok | 1 + test/run-dfinity/ok/GIT-843.run.ok | 1 + 7 files changed, 17 insertions(+), 6 deletions(-) create mode 100644 test/run-dfinity/GIT-843.mo create mode 100644 test/run-dfinity/ok/GIT-843.dvm.ok create mode 100644 test/run-dfinity/ok/GIT-843.run-ir.ok create mode 100644 test/run-dfinity/ok/GIT-843.run-low.ok create mode 100644 test/run-dfinity/ok/GIT-843.run.ok diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 48929c9f67c..5ceca78703a 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -618,9 +618,8 @@ let rec check_exp env (exp:Ir.exp) : unit = | ActorE (id, ds, fs, t0) -> let env' = { env with async = false } in let ve0 = T.Env.singleton id t0 in - let scope0 = { empty_scope with val_env = ve0 } in - let scope1 = List.fold_left (gather_dec env') scope0 ds in - let env'' = adjoin env' scope1 in + let scope1 = List.fold_left (gather_dec env') empty_scope ds in + let env'' = adjoin (adjoin_vals env' ve0) scope1 in check_decs env'' ds; check (T.is_obj t0) "bad annotation (object type expected)"; let (s0, tfs0) = T.as_obj t0 in diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index 3bae24aac21..76b6f828e8c 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -524,11 +524,13 @@ and interpret_exp_mut env exp (k : V.value V.cont) = in k v | ActorE (id, ds, fs, _) -> - let ve = declare_decs ds (declare_id id) in - let env' = adjoin_vals env ve in + let ve0 = declare_id id in + let ve = declare_decs ds ve0 in + let env0 = adjoin_vals env ve0 in + let env' = adjoin_vals env0 ve in interpret_decs env' ds (fun _ -> let obj = interpret_fields env' fs in - define_id env' id obj; + define_id env0 id obj; k obj) | NewObjE (sort, fs, _) -> k (interpret_fields env fs) diff --git a/test/run-dfinity/GIT-843.mo b/test/run-dfinity/GIT-843.mo new file mode 100644 index 00000000000..efdd79019a6 --- /dev/null +++ b/test/run-dfinity/GIT-843.mo @@ -0,0 +1,6 @@ +// the check_ir and ir_interpreter +// failed if an actor field name (legally) shadowed the actor name +actor Bad { + public func Bad (){ debugPrint "ok"}; +}; +Bad.Bad(); \ No newline at end of file diff --git a/test/run-dfinity/ok/GIT-843.dvm.ok b/test/run-dfinity/ok/GIT-843.dvm.ok new file mode 100644 index 00000000000..9766475a418 --- /dev/null +++ b/test/run-dfinity/ok/GIT-843.dvm.ok @@ -0,0 +1 @@ +ok diff --git a/test/run-dfinity/ok/GIT-843.run-ir.ok b/test/run-dfinity/ok/GIT-843.run-ir.ok new file mode 100644 index 00000000000..9766475a418 --- /dev/null +++ b/test/run-dfinity/ok/GIT-843.run-ir.ok @@ -0,0 +1 @@ +ok diff --git a/test/run-dfinity/ok/GIT-843.run-low.ok b/test/run-dfinity/ok/GIT-843.run-low.ok new file mode 100644 index 00000000000..9766475a418 --- /dev/null +++ b/test/run-dfinity/ok/GIT-843.run-low.ok @@ -0,0 +1 @@ +ok diff --git a/test/run-dfinity/ok/GIT-843.run.ok b/test/run-dfinity/ok/GIT-843.run.ok new file mode 100644 index 00000000000..9766475a418 --- /dev/null +++ b/test/run-dfinity/ok/GIT-843.run.ok @@ -0,0 +1 @@ +ok From a749cb954f95121a0cc4e75386e220d7d4f478cf Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Fri, 8 Nov 2019 18:44:41 +0000 Subject: [PATCH 0541/1176] avoid binding id twice --- src/ir_interpreter/interpret_ir.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index 76b6f828e8c..e9bc4e99401 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -525,8 +525,8 @@ and interpret_exp_mut env exp (k : V.value V.cont) = k v | ActorE (id, ds, fs, _) -> let ve0 = declare_id id in - let ve = declare_decs ds ve0 in let env0 = adjoin_vals env ve0 in + let ve = declare_decs ds V.Env.empty in let env' = adjoin_vals env0 ve in interpret_decs env' ds (fun _ -> let obj = interpret_fields env' fs in From bbecba792eb1d8c6ba079bf592e66fcfe98a4a0e Mon Sep 17 00:00:00 2001 From: Timo Hanke Date: Fri, 8 Nov 2019 10:46:28 -0800 Subject: [PATCH 0542/1176] Add a function isEq for immutable arrays --- stdlib/array.mo | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/stdlib/array.mo b/stdlib/array.mo index a56cf187909..433c308a7f6 100644 --- a/stdlib/array.mo +++ b/stdlib/array.mo @@ -1,4 +1,16 @@ module { + public func isEq(a : [A], b : [A], eq : (A,A) -> Bool) : Bool { + if (a.len() != b.len()) { + return false + }; + for (i in range(1,a.len())) { + if (not eq(a[i-1],b[i-1])) { + return false + } + }; + return true; + }; + public func append(xs : [A], ys : [A]) : [A] { switch(xs.len(), ys.len()) { case (0, 0) { []; }; @@ -118,4 +130,4 @@ module { }; ys; }; -} +} \ No newline at end of file From 563570febbb7a6eba07a90851f02dfe972679229 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Fri, 8 Nov 2019 18:54:37 +0000 Subject: [PATCH 0543/1176] add newline --- test/run-dfinity/GIT-843.mo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/run-dfinity/GIT-843.mo b/test/run-dfinity/GIT-843.mo index efdd79019a6..031609eca8f 100644 --- a/test/run-dfinity/GIT-843.mo +++ b/test/run-dfinity/GIT-843.mo @@ -3,4 +3,4 @@ actor Bad { public func Bad (){ debugPrint "ok"}; }; -Bad.Bad(); \ No newline at end of file +Bad.Bad(); From df1d796f394e30ad030f0631511c8bde21e70245 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Fri, 8 Nov 2019 18:56:39 +0000 Subject: [PATCH 0544/1176] fix comment --- test/run-dfinity/GIT-843.mo | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/run-dfinity/GIT-843.mo b/test/run-dfinity/GIT-843.mo index 031609eca8f..5f02db7e1c1 100644 --- a/test/run-dfinity/GIT-843.mo +++ b/test/run-dfinity/GIT-843.mo @@ -1,5 +1,5 @@ -// the check_ir and ir_interpreter -// failed if an actor field name (legally) shadowed the actor name +// Both check_ir and ir_interpreter would failed +// if an actor field name (legally) shadowed the actor name actor Bad { public func Bad (){ debugPrint "ok"}; }; From c1d1a41c52437fe2fce2d4ce8a9ebe19c83a39e5 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity <48968912+chenyan-dfinity@users.noreply.github.com> Date: Fri, 8 Nov 2019 10:58:23 -0800 Subject: [PATCH 0545/1176] Remove filename from anonymous actor name (#845) --- src/mo_idl/mo_to_idl.ml | 2 +- test/mo-idl/ok/inline_result.did.ok | 2 +- test/mo-idl/ok/recursion.did.ok | 2 +- test/mo-idl/ok/result.did.ok | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mo_idl/mo_to_idl.ml b/src/mo_idl/mo_to_idl.ml index 9c1964e7782..dac21c4f9eb 100644 --- a/src/mo_idl/mo_to_idl.ml +++ b/src/mo_idl/mo_to_idl.ml @@ -178,7 +178,7 @@ let gather_decs () = let actor progs = let open E in let find_last_actor (prog : prog) = - let anon = normalize ("anon_" ^ (Filename.remove_extension prog.note)) in + let anon = "anon" in let check_dec d t def = let rec check_pat p = match p.it with diff --git a/test/mo-idl/ok/inline_result.did.ok b/test/mo-idl/ok/inline_result.did.ok index 9975fbd985c..35a34389ce7 100644 --- a/test/mo-idl/ok/inline_result.did.ok +++ b/test/mo-idl/ok/inline_result.did.ok @@ -1,4 +1,4 @@ -service anon_inline_result { +service anon { "f": (opt nat) -> (variant { "err": text; "ok": nat; diff --git a/test/mo-idl/ok/recursion.did.ok b/test/mo-idl/ok/recursion.did.ok index 60a9d06ac88..e4bc02bb91a 100644 --- a/test/mo-idl/ok/recursion.did.ok +++ b/test/mo-idl/ok/recursion.did.ok @@ -8,7 +8,7 @@ type List_1 = "head": int; "tail": opt List_1; }; -service anon_recursion { +service anon { "f": (nat) -> (List_2); "g": (int) -> (List_1); } diff --git a/test/mo-idl/ok/result.did.ok b/test/mo-idl/ok/result.did.ok index 8bb8b28d4e1..463a16fd59a 100644 --- a/test/mo-idl/ok/result.did.ok +++ b/test/mo-idl/ok/result.did.ok @@ -23,7 +23,7 @@ type Result2_1 = "err": Result_1_1; "ok": null; }; -service anon_result { +service anon { "f": (opt nat) -> (Result_1_2); "g": (Result3_1) -> (Result2_2); } From eb2af69fcae0273507ac00cad54c59eaa402136b Mon Sep 17 00:00:00 2001 From: Timo Hanke Date: Fri, 8 Nov 2019 16:46:45 -0800 Subject: [PATCH 0546/1176] Replaced for loop with while loop As per crusso's suggestion. --- stdlib/array.mo | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/stdlib/array.mo b/stdlib/array.mo index 433c308a7f6..5e9c92cf707 100644 --- a/stdlib/array.mo +++ b/stdlib/array.mo @@ -3,10 +3,12 @@ module { if (a.len() != b.len()) { return false }; - for (i in range(1,a.len())) { - if (not eq(a[i-1],b[i-1])) { - return false - } + var i = 0; + while (i < a.len()) { + if (not eq(a[i],b[i])) { + return false + }; + i += 1 }; return true; }; @@ -130,4 +132,4 @@ module { }; ys; }; -} \ No newline at end of file +} From 4d977f299676e0906813e95192f829accf47b687 Mon Sep 17 00:00:00 2001 From: Timo Hanke Date: Sun, 10 Nov 2019 17:13:23 -0800 Subject: [PATCH 0547/1176] Change function name isEq to equals --- stdlib/array.mo | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stdlib/array.mo b/stdlib/array.mo index 5e9c92cf707..abf99b42485 100644 --- a/stdlib/array.mo +++ b/stdlib/array.mo @@ -1,14 +1,14 @@ module { - public func isEq(a : [A], b : [A], eq : (A,A) -> Bool) : Bool { + public func equals(a : [A], b : [A], eq : (A,A) -> Bool) : Bool { if (a.len() != b.len()) { - return false + return false; }; var i = 0; while (i < a.len()) { if (not eq(a[i],b[i])) { - return false + return false; }; - i += 1 + i += 1; }; return true; }; From 74a7c6ae7f022c09794c310dc2cfe87d8123050c Mon Sep 17 00:00:00 2001 From: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> Date: Mon, 11 Nov 2019 11:26:50 +0100 Subject: [PATCH 0548/1176] parses package paths passed to the LSP server just like the compiler (#850) --- src/exes/mo_ide.ml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/exes/mo_ide.ml b/src/exes/mo_ide.ml index c40aba7858c..ab498bf33bb 100644 --- a/src/exes/mo_ide.ml +++ b/src/exes/mo_ide.ml @@ -13,6 +13,18 @@ let argspec = ; "--canister-main", Arg.String set_entry_point, " specifies the entry point for the current project" + ; "--package", + (let package_name_ref = ref "DEADBEEF" in + Arg.Tuple [ + Arg.Set_string package_name_ref ; + Arg.String begin fun package_url -> + (* push (package_name, package_url) onto the list. *) + Mo_config.Flags.package_urls := ( + !package_name_ref, + package_url + ) :: ! Mo_config.Flags.package_urls + end + ]), " Specify a package-name-package-URL pair, separated by a space" ; ] let () = From a41ae6e9c1fa02e2903a737bd0f2a8403826a934 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 11 Nov 2019 12:10:48 +0100 Subject: [PATCH 0549/1176] Test runner: Allow skipping of certain steps (#839) * Test runner: Allow skipping of certain steps useful if we have test cases that are very slow in the interpreter, and we only really care about the test with `drun`. * Actually test 1G allocation it is reasonably fast on `drun`. --- test/run-drun/large-array.mo | 8 ++++---- test/run.sh | 19 ++++++++++++++----- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/test/run-drun/large-array.mo b/test/run-drun/large-array.mo index 9c78a314ce4..f47f4924763 100644 --- a/test/run-drun/large-array.mo +++ b/test/run-drun/large-array.mo @@ -1,6 +1,6 @@ // Should allocate 1G -// ignore(Array_init<()>(1024*1024*1024/4, ())); - -// Should allocate 50MB (easier on CI) -ignore(Array_init<()>(50*1024*1024/4, ())); +ignore(Array_init<()>(1024*1024*1024/4, ())); +//SKIP run +//SKIP run-ir +//SKIP run-low diff --git a/test/run.sh b/test/run.sh index 8f9945469b6..bff1d5a1696 100755 --- a/test/run.sh +++ b/test/run.sh @@ -89,10 +89,13 @@ function normalize () { function run () { # first argument: extension of the output file # remaining argument: command line - # uses from scope: $out, $base, $diff_files + # uses from scope: $out, $file, $base, $diff_files local ext="$1" shift + + if grep -q "^//SKIP $ext" $file; then return; fi + $ECHO -n " [$ext]" "$@" >& $out/$base.$ext local ret=$? @@ -182,15 +185,21 @@ do run run-ir $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS -r -iR -no-async -no-await $base.mo # Diff interpretations without/with lowering - diff -u -N --label "$base.run" $out/$base.run --label "$base.run-ir" $out/$base.run-ir > $out/$base.diff-ir - diff_files="$diff_files $base.diff-ir" + if [ -e $out/$base.run -a -e $out/$base.run-ir ] + then + diff -u -N --label "$base.run" $out/$base.run --label "$base.run-ir" $out/$base.run-ir > $out/$base.diff-ir + diff_files="$diff_files $base.diff-ir" + fi # Interpret IR with lowering run run-low $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS -r -iR $base.mo # Diff interpretations without/with lowering - diff -u -N --label "$base.run" $out/$base.run --label "$base.run-low" $out/$base.run-low > $out/$base.diff-low - diff_files="$diff_files $base.diff-low" + if [ -e $out/$base.run -a -e $out/$base.run-low ] + then + diff -u -N --label "$base.run" $out/$base.run --label "$base.run-low" $out/$base.run-low > $out/$base.diff-low + diff_files="$diff_files $base.diff-low" + fi fi From 0ad1b543bc74b078d592f31a1960397ebcd7a3be Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 11 Nov 2019 12:39:06 +0100 Subject: [PATCH 0550/1176] Make IDL decoder errors less Germanic (#848) --- src/codegen/compile.ml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index d7f281719a4..9df62a4baba 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -3916,7 +3916,7 @@ module Serialization = struct let assert_prim_typ () = check_prim_typ t ^^ - E.else_trap_with env ("IDL error: unexpected IDL typ when parsing " ^ string_of_typ t) + E.else_trap_with env ("IDL error: unexpected IDL type when parsing " ^ string_of_typ t) in @@ -3927,7 +3927,7 @@ module Serialization = struct (* make sure index is not negative *) get_idltyp ^^ compile_unboxed_const 0l ^^ G.i (Compare (Wasm.Values.I32 I32Op.GeS)) ^^ - E.else_trap_with env ("IDL error: expected composite typ when parsing " ^ string_of_typ t) ^^ + E.else_trap_with env ("IDL error: expected composite type when parsing " ^ string_of_typ t) ^^ ReadBuf.alloc env (fun get_typ_buf -> (* Update typ_buf *) ReadBuf.set_ptr get_typ_buf ( @@ -3941,7 +3941,7 @@ module Serialization = struct ReadBuf.read_sleb128 env get_typ_buf ^^ (* Check it is the expected value *) compile_eq_const idl_tycon_id ^^ - E.else_trap_with env ("IDL error: wrong composite typ when parsing " ^ string_of_typ t) ^^ + E.else_trap_with env ("IDL error: wrong composite type when parsing " ^ string_of_typ t) ^^ (* to the work *) f get_typ_buf ) in From 596fe3d108c4d8697f1191d8d0d5b3aaf4d6f444 Mon Sep 17 00:00:00 2001 From: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> Date: Mon, 11 Nov 2019 21:21:17 +0100 Subject: [PATCH 0551/1176] Catches lexer exceptions in the LSP server (#856) * removes duplicated code * catches lexer exceptions when completing or hovering in the ide --- src/languageServer/completion.ml | 32 +-------------- src/languageServer/completion_test.ml | 52 ------------------------- src/languageServer/source_file.ml | 4 +- src/languageServer/source_file_tests.ml | 52 +++++++++++++++++++++++++ test/lsp-int/Main.hs | 9 +++++ 5 files changed, 65 insertions(+), 84 deletions(-) diff --git a/src/languageServer/completion.ml b/src/languageServer/completion.ml index 874d9884e56..3a40ceaa56e 100644 --- a/src/languageServer/completion.ml +++ b/src/languageServer/completion.ml @@ -68,34 +68,6 @@ let import_relative_to_project_root root module_path dependency = |> Pipeline__.File_path.normalise |> Lib.Option.some -(* Given the source of a module, figure out under what names what - modules have been imported. Normalizes the imported modules - filepaths relative to the project root *) -let parse_module_header project_root current_file_path file = - let lexbuf = Lexing.from_string file in - let next () = Lexer.token Lexer.Normal lexbuf in - let res = ref [] in - let rec loop = function - | Parser.IMPORT -> - (match next () with - | Parser.ID alias -> - (match next () with - | Parser.TEXT path -> - let path = - import_relative_to_project_root - project_root - current_file_path - path in - (match path with - | Some path -> res := (alias, path) :: !res - | None -> ()); - loop (next ()) - | tkn -> loop tkn) - | tkn -> loop tkn) - | Parser.EOF -> List.rev !res - | tkn -> loop (next ()) in - loop (next ()) - (* Given a source file and a cursor position in that file, figure out the prefix relevant to searching completions. For example, given: @@ -130,10 +102,10 @@ let find_completion_prefix logger file line column: (string * string) option = | tkn -> loop tkn) | Parser.EOF -> None | _ -> loop (next ()) in - loop (next ()) + try loop (next ()) with _ -> None let completions index logger project_root file_path file_contents line column = - let imported = parse_module_header project_root file_path file_contents in + let imported = Source_file.parse_module_header project_root file_path file_contents in let module_alias_completion_item alias = Lsp_t.{ completion_item_label = alias; diff --git a/src/languageServer/completion_test.ml b/src/languageServer/completion_test.ml index cf7d644ae7b..e4dd4adc154 100644 --- a/src/languageServer/completion_test.ml +++ b/src/languageServer/completion_test.ml @@ -43,25 +43,6 @@ let import_relative_test_case root module_path import expected = (show actual); false) -let parse_module_header_test_case project_root current_file file expected = - let actual = - Completion.parse_module_header - project_root - current_file file in - let display_result (alias, path) = Printf.sprintf "%s => \"%s\"" alias path in - let result = Lib.List.equal - (fun (x, y) (x', y') -> - String.equal x x' && String.equal y y') - actual - expected in - if not result then - Printf.printf - "\nExpected: %s\nActual: %s" - (Completion.string_of_list display_result expected) - (Completion.string_of_list display_result actual) else (); - result - - let%test "it finds a simple prefix" = prefix_test_case "List.|" (Some ("List", "")) @@ -128,36 +109,3 @@ let%test "it can handle parent directory relationships" = "/home/project/src/main.mo" "../lib/List.mo" (Some "lib/List.mo") - -let%test "it parses a simple module header" = - parse_module_header_test_case - "/project" - "/project/src/Main.mo" - "import P \"lib/prelude.mo\"" - ["P", "src/lib/prelude.mo"] - -let%test "it parses a simple module header" = - parse_module_header_test_case - "/project" - "/project/Main.mo" - {| -module { - -private import List "lib/ListLib.mo"; -private import ListFuncs "lib/ListFuncs.mo"; - -type Stack = List.List; - -func push(x: Int, s: Stack): Stack = - List.cons(x, s); - -func empty(): Stack = - List.nil(); - -func singleton(x: Int): Stack = - ListFuncs.doubleton(x, x); -} -|} - [ ("List", "lib/ListLib.mo") - ; ("ListFuncs", "lib/ListFuncs.mo") - ] diff --git a/src/languageServer/source_file.ml b/src/languageServer/source_file.ml index 6315210b9c6..597736b6f7b 100644 --- a/src/languageServer/source_file.ml +++ b/src/languageServer/source_file.ml @@ -37,7 +37,7 @@ let cursor_target_at_pos | tkn -> loop tkn) | Parser.EOF -> None | _ -> loop (next ()) in - loop (next ()) + try loop (next ()) with _ -> None let import_relative_to_project_root root module_path dependency = match Pipeline__.File_path.relative_to root module_path with @@ -75,7 +75,7 @@ let parse_module_header project_root current_file_path file = | tkn -> loop tkn) | Parser.EOF -> List.rev !res | tkn -> loop (next ()) in - loop (next ()) + try loop (next ()) with _ -> List.rev !res type unresolved_target = { qualifier : string; ident : string } diff --git a/src/languageServer/source_file_tests.ml b/src/languageServer/source_file_tests.ml index 189f9f37108..a5eeae5f79f 100644 --- a/src/languageServer/source_file_tests.ml +++ b/src/languageServer/source_file_tests.ml @@ -31,6 +31,24 @@ let hovered_identifier_test_case file expected = (show actual); false) +let parse_module_header_test_case project_root current_file file expected = + let actual = + Source_file.parse_module_header + project_root + current_file file in + let display_result (alias, path) = Printf.sprintf "%s => \"%s\"" alias path in + let result = Lib.List.equal + (fun (x, y) (x', y') -> + String.equal x x' && String.equal y y') + actual + expected in + if not result then + Printf.printf + "\nExpected: %s\nActual: %s" + (Completion.string_of_list display_result expected) + (Completion.string_of_list display_result actual) else (); + result + let%test "it finds an identifier" = hovered_identifier_test_case "f|ilter" @@ -43,3 +61,37 @@ let%test "it finds a qualified identifier" = hovered_identifier_test_case "List.f|ilter" (Some (Source_file.CQualified ("List", "filter"))) + + +let%test "it parses a simple module header" = + parse_module_header_test_case + "/project" + "/project/src/Main.mo" + "import P \"lib/prelude.mo\"" + ["P", "src/lib/prelude.mo"] + +let%test "it parses a simple module header" = + parse_module_header_test_case + "/project" + "/project/Main.mo" + {| +module { + +private import List "lib/ListLib.mo"; +private import ListFuncs "lib/ListFuncs.mo"; + +type Stack = List.List; + +func push(x: Int, s: Stack): Stack = + List.cons(x, s); + +func empty(): Stack = + List.nil(); + +func singleton(x: Int): Stack = + ListFuncs.doubleton(x, x); +} +|} + [ ("List", "lib/ListLib.mo") + ; ("ListFuncs", "lib/ListFuncs.mo") + ] diff --git a/test/lsp-int/Main.hs b/test/lsp-int/Main.hs index d03aaafb47e..d41dc60c371 100644 --- a/test/lsp-int/Main.hs +++ b/test/lsp-int/Main.hs @@ -105,6 +105,15 @@ main = handleHUnitFailure $ do liftIO (diagnostic^.message `shouldBe` "unexpected token") closeDoc doc + doc <- openDoc "ListClient.mo" "motoko" + -- Creates an unclosed text literal, which triggers a lexer error + let edit = TextEdit (Range (Position 0 1) (Position 0 3)) "\"hello" + _ <- applyEdit doc edit + -- We're just testing that the server doesn't crash here + getCompletions doc (Position 0 0) + getHover doc (Position 0 0) + closeDoc doc + -- It finds errors in transitive modules that have been changed in -- the vfs but not yet stored to disc {- TODO(Christoph): Figure out why this isn't working right now From a8e32bed5d80a2d8ed5838b639dad72a94541ec6 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 12 Nov 2019 11:59:58 +0100 Subject: [PATCH 0552/1176] Fix nix-shell on darwin (#859) --- default.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/default.nix b/default.nix index 6687f43508c..9f7680a2650 100644 --- a/default.nix +++ b/default.nix @@ -497,7 +497,8 @@ rec { JS_USER_LIBRARY=js-user-library; TOMMATHSRC = libtommath; NIX_FONTCONFIG_FILE = users-guide.NIX_FONTCONFIG_FILE; - ${if nixpkgs ? glibcLocales then "LOCALE_ARCHIVE" else null} ="${nixpkgs.glibcLocales}/lib/locale/locale-archive"; + LOCALE_ARCHIVE = stdenv.lib.optionalString stdenv.isLinux "${nixpkgs.glibcLocales}/lib/locale/locale-archive"; + } else null; } From 1ec044c782f5ea9a2bd35a5a4bb7123595e73372 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Tue, 12 Nov 2019 12:16:45 +0100 Subject: [PATCH 0553/1176] deser: silent/verbose mode (#785) * introduce --verbose option (with default of suppressing commentary) * update expectations --- src/exes/deser.ml | 45 +++++++++++++++++++++++-------------- test/run-deser/ok/five.ok | 18 ++------------- test/run-deser/ok/future.ok | 16 ++----------- 3 files changed, 32 insertions(+), 47 deletions(-) diff --git a/src/exes/deser.ml b/src/exes/deser.ml index aa5f4de7563..2497e5b5e70 100644 --- a/src/exes/deser.ml +++ b/src/exes/deser.ml @@ -9,6 +9,10 @@ open Lazy type outputter = unit -> unit +(* noise reduction *) + +let chatty = ref false + (* read nothing *) let epsilon : outputter = ignore @@ -137,7 +141,7 @@ let read_type_index () = let ty = read_sleb128 () in assert (ty > -18); ty let read_assoc () = let hash = read_leb128 () in let tynum = read_type_index () in - Printf.printf "hash: %d, tynum: %d\n" hash tynum; hash, tynum + if !chatty then Printf.printf "hash: %d, tynum: %d\n" hash tynum; hash, tynum module type Dump = sig @@ -199,9 +203,9 @@ let output_text bytes from tostream = let buf = Buffer.create 0 in ignore (input_buffer from buf ~len:bytes); Printf.printf "%sText: %d bytes follow on next line\n" (fill ()) bytes; - Printf.printf "%s---->" (fill ()); (* TODO: puts? *) + Printf.printf "%s---->" (fill ()); Stdio.Out_channel.output_buffer tostream buf; - Printf.printf "\n" + print_string "\n" let output_arguments args : outputter * (unit -> int -> outputter -> outputter) = let herald_arguments = function @@ -234,7 +238,8 @@ end module OutputIdl : Dump = struct let output_string (s : string) = print_string s -let output_string_space (s : string) = Printf.printf "%s " s +let chat_string s = if !chatty then output_string s +let output_string_space (s : string) = output_string s; output_string " " let output_decimal (i : int) = Printf.printf "%d" i let output_bignum (i : int) = output_decimal i (* for now *) @@ -257,15 +262,15 @@ let output_text n froms tos = let output_arguments args : outputter * (unit -> int -> outputter -> outputter) = let last i = i + 1 = args in let herald_arguments = function - | () when args = 0 -> output_string "// No arguments...\n()" - | _ when args = 1 -> output_string "// 1 argument follows\n(\n" - | _ -> Printf.printf "// %d arguments follow\n(\n" args in + | () when args = 0 -> chat_string "// No arguments...\n"; output_string "()" + | _ when args = 1 -> chat_string "// 1 argument follows\n" + | _ -> if !chatty then Printf.printf "// %d arguments follow\n" args in let herald_member () i f () = - Printf.printf "// Argument #%d%s:\n" i (if last i then " (last)" else ""); - if i = 0 then print_string " " else print_string ", "; + if !chatty then Printf.printf "// Argument #%d%s:\n" i (if last i then " (last)" else ""); + output_string (if i = 0 then "( " else ", "); f (); - if last i then print_string "\n)" else print_string "\n" in - herald_arguments, (*bracket args*) herald_member + output_string (if last i then "\n)" else "\n") in + herald_arguments, herald_member let start i = if i = 0 then output_string_space "{" let stop max i = if i + 1 = max then output_string " }" @@ -420,6 +425,7 @@ let read_type lookup : (typ * outputter) Lazy.t = (* T(service {*}) = sleb128(-23) T*(* ) *) + | -23 -> failwith "service types not supported yet" | t -> (* future type *) let bytes = read_leb128 () in @@ -436,19 +442,23 @@ T(service {*}) = sleb128(-23) T*(* ) let read_type_table (t : unit -> (typ * outputter) Lazy.t) : (typ * outputter) Lazy.t array = let rep = read_leb128 () in - Array.init rep (fun i -> Printf.printf "read_type_table: %d\n" i;t ()) + Array.init rep (fun i -> if !chatty then Printf.printf "read_type_table: %d\n" i; t ()) + +(* Utilities *) + +let chat_string = if !chatty then print_string else ignore (* Top-level *) let top_level md : unit = - Printf.printf "\nDESER, to your service!\n"; + chat_string "\nDESER, to your service!\n"; read_magic (); - Printf.printf "\n========================== Type section\n"; + chat_string "\n========================== Type section\n"; let tab = let rec tab = lazy (read_type_table (fun () -> read_type lookup)) and lookup = fun indx -> (*Printf.printf "{indx: %d}" indx; *)Array.get (force tab) indx in Array.map force (force tab) in - Printf.printf "\n========================== Value section\n"; + chat_string "\n========================== Value section\n"; let open F in begin match md with | Nary -> @@ -462,10 +472,10 @@ let top_level md : unit = Array.iteri (fun i f -> herald_member () i f ()) consumers | Unary -> let argty = read_type_index () in - Printf.printf "ARGTY: %d\n" argty; + if !chatty then Printf.printf "# ARGTY: %d\n" argty; snd (Array.get tab argty) () end; - Printf.printf "\n-------- DESER DONE\n" + chat_string "\n-------- DESER DONE\n" end @@ -500,6 +510,7 @@ let argspec = Arg.align "--prose", Arg.Unit (set_format Prose), " output indented prose"; "--json", Arg.Unit (set_format Json), " output JSON values"; "--idl", Arg.Unit (set_format Idl), " output IDL values (default)"; + "--verbose", Arg.Unit (fun () -> chatty := true), " amend commentary"; "--version", Arg.Unit (fun () -> Printf.printf "%s\n" banner; exit 0), " show version"; ] diff --git a/test/run-deser/ok/five.ok b/test/run-deser/ok/five.ok index 92e67e390dc..c7a4adeb3ad 100644 --- a/test/run-deser/ok/five.ok +++ b/test/run-deser/ok/five.ok @@ -1,20 +1,6 @@ - -DESER, to your service! - -========================== Type section - -========================== Value section -// 5 arguments follow -( -// Argument #0: - "One" -// Argument #1: +( "One" , "Two" -// Argument #2: , "Three" -// Argument #3: , "Four" -// Argument #4 (last): , "Five" -) --------- DESER DONE +) \ No newline at end of file diff --git a/test/run-deser/ok/future.ok b/test/run-deser/ok/future.ok index 77610c4fd4b..02a9b865a87 100644 --- a/test/run-deser/ok/future.ok +++ b/test/run-deser/ok/future.ok @@ -1,15 +1,3 @@ - -DESER, to your service! - -========================== Type section -read_type_table: 0 - -========================== Value section -// 2 arguments follow -( -// Argument #0: - -// Argument #1 (last): +( , "Foo" -) --------- DESER DONE +) \ No newline at end of file From ef8d4ca3ece8586800558fabaea806d51a6c1811 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 12 Nov 2019 14:03:46 +0100 Subject: [PATCH 0554/1176] Upgrade to llvm9 as released (#677) based on https://github.com/NixOS/nixpkgs/pull/69115 The trick is to use `--target=wasm32-unknown-emscripten-wasm`, the LLVM works just fine. --- nix/llvm.nix | 13 - nix/llvm/bintools.nix | 19 - nix/llvm/clang/clang-xpc.patch | 41 -- nix/llvm/clang/default.nix | 127 ------ nix/llvm/clang/purity.patch | 30 -- nix/llvm/clang/static-pie.patch | 157 -------- nix/llvm/clang/unwindlib.patch | 372 ----------------- nix/llvm/compiler-rt-codesign.patch | 33 -- nix/llvm/compiler-rt.nix | 67 ---- nix/llvm/crtbegin-and-end.patch | 595 ---------------------------- nix/llvm/default.nix | 198 --------- nix/llvm/libc++/default.nix | 58 --- nix/llvm/libc++/setup-hook.sh | 6 - nix/llvm/libc++abi.nix | 66 --- nix/llvm/libcxxabi-no-threads.patch | 12 - nix/llvm/libcxxabi-wasm.patch | 16 - nix/llvm/libunwind.nix | 22 - nix/llvm/lld.nix | 32 -- nix/llvm/lldb.nix | 60 --- nix/llvm/llvm-outputs.patch | 26 -- nix/llvm/llvm.nix | 175 -------- nix/llvm/openmp.nix | 25 -- nix/llvm/sanitizers-nongnu.patch | 412 ------------------- nix/nixpkgs-newer.nix | 4 +- rts/Makefile | 2 +- 25 files changed, 3 insertions(+), 2565 deletions(-) delete mode 100644 nix/llvm/bintools.nix delete mode 100644 nix/llvm/clang/clang-xpc.patch delete mode 100644 nix/llvm/clang/default.nix delete mode 100644 nix/llvm/clang/purity.patch delete mode 100644 nix/llvm/clang/static-pie.patch delete mode 100644 nix/llvm/clang/unwindlib.patch delete mode 100644 nix/llvm/compiler-rt-codesign.patch delete mode 100644 nix/llvm/compiler-rt.nix delete mode 100644 nix/llvm/crtbegin-and-end.patch delete mode 100644 nix/llvm/default.nix delete mode 100644 nix/llvm/libc++/default.nix delete mode 100644 nix/llvm/libc++/setup-hook.sh delete mode 100644 nix/llvm/libc++abi.nix delete mode 100644 nix/llvm/libcxxabi-no-threads.patch delete mode 100644 nix/llvm/libcxxabi-wasm.patch delete mode 100644 nix/llvm/libunwind.nix delete mode 100644 nix/llvm/lld.nix delete mode 100644 nix/llvm/lldb.nix delete mode 100644 nix/llvm/llvm-outputs.patch delete mode 100644 nix/llvm/llvm.nix delete mode 100644 nix/llvm/openmp.nix delete mode 100644 nix/llvm/sanitizers-nongnu.patch diff --git a/nix/llvm.nix b/nix/llvm.nix index fd9ff283625..fcf0aca1cb3 100644 --- a/nix/llvm.nix +++ b/nix/llvm.nix @@ -1,20 +1,7 @@ { system } : -let overlay = self: super: - with super; - { - llvmPackages_9 = callPackage ./llvm ({ - inherit (stdenvAdapters) overrideCC; - buildLlvmTools = buildPackages.llvmPackages_9.tools; - targetLlvmLibraries = targetPackages.llvmPackages_9.libraries; - } // stdenv.lib.optionalAttrs (buildPackages.stdenv.cc.isGNU && stdenv.hostPlatform.isi686) { - stdenv = overrideCC stdenv buildPackages.gcc6; - } - ); - }; in let pkgs = (import ./nixpkgs-newer.nix) { system = system; - overlays = [overlay]; }; in { diff --git a/nix/llvm/bintools.nix b/nix/llvm/bintools.nix deleted file mode 100644 index 72a2a733193..00000000000 --- a/nix/llvm/bintools.nix +++ /dev/null @@ -1,19 +0,0 @@ -{ runCommand, stdenv, llvm, lld, version }: - -let - prefix = - if stdenv.hostPlatform != stdenv.targetPlatform - then "${stdenv.targetPlatform.config}-" - else ""; -in runCommand "llvm-binutils-${version}" { preferLocalBuild = true; } '' - mkdir -p $out/bin - for prog in ${lld}/bin/*; do - ln -s $prog $out/bin/${prefix}$(basename $prog) - done - for prog in ${llvm}/bin/*; do - ln -s $prog $out/bin/${prefix}$(echo $(basename $prog) | sed -e "s|llvm-||") - ln -sf $prog $out/bin/${prefix}$(basename $prog) - done - rm -f $out/bin/${prefix}cat - ln -s ${lld}/bin/lld $out/bin/${prefix}ld -'' diff --git a/nix/llvm/clang/clang-xpc.patch b/nix/llvm/clang/clang-xpc.patch deleted file mode 100644 index eb57d345822..00000000000 --- a/nix/llvm/clang/clang-xpc.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 61c9b97d7b81cc2c013b423bf1763a92b14fcae3 Mon Sep 17 00:00:00 2001 -From: Jan Korous -Date: Tue, 26 Mar 2019 03:48:25 +0000 -Subject: [PATCH] [clangd][xpc][cmake] Respect explicit value of - CLANGD_BUILD_XPC - -We shouldn't prevent user from disabling XPC framework build on Darwin. -However, by keeping it on by default our CI systems also test -it by default on macOS. - -Based on user request: -http://lists.llvm.org/pipermail/cfe-dev/2019-March/061778.html - -Differential Revision: https://reviews.llvm.org/D59808 - -git-svn-id: https://llvm.org/svn/llvm-project/clang-tools-extra/trunk@356974 91177308-0d34-0410-b5e6-96231b3b80d8 ---- - CMakeLists.txt | 13 ++++++++++--- - 1 file changed, 10 insertions(+), 3 deletions(-) - -diff --git a/CMakeLists.txt b/CMakeLists.txt -index 66ebeaeeaa..514b17fb3c 100644 ---- a/tools/extra/CMakeLists.txt -+++ b/tools/extra/CMakeLists.txt -@@ -1,6 +1,13 @@ --option(CLANGD_BUILD_XPC "Build XPC Support For Clangd." OFF) --if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") -- set(CLANGD_BUILD_XPC ON CACHE BOOL "" FORCE) -+if (NOT DEFINED CLANGD_BUILD_XPC) -+ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") -+ set(CLANGD_BUILD_XPC_DEFAULT ON) -+ else () -+ set(CLANGD_BUILD_XPC_DEFAULT OFF) -+ endif () -+ -+ set(CLANGD_BUILD_XPC ${CLANGD_BUILD_XPC_DEFAULT} CACHE BOOL "Build XPC Support For Clangd." FORCE) -+ -+ unset(CLANGD_BUILD_XPC_DEFAULT) - endif () - - add_subdirectory(clang-apply-replacements) \ No newline at end of file diff --git a/nix/llvm/clang/default.nix b/nix/llvm/clang/default.nix deleted file mode 100644 index ff8f007a660..00000000000 --- a/nix/llvm/clang/default.nix +++ /dev/null @@ -1,127 +0,0 @@ -{ stdenv, fetch, fetchpatch, cmake, libxml2, llvm, version, clang-tools-extra_src, python -, fixDarwinDylibNames -, enableManpages ? false -, enablePolly ? false # TODO: get this info from llvm (passthru?) -}: - -let - self = stdenv.mkDerivation ({ - name = "clang-${version}"; - - unpackPhase = '' - unpackFile ${fetch "cfe" "1ifvdcjs1dpwm61xk7wlqwmmq0afxj9g7lknpcxsb1w239aza36z"} - chmod -R u+w cfe-* - mv cfe-* clang - sourceRoot=$PWD/clang - unpackFile ${clang-tools-extra_src} - chmod -R u+w $sourceRoot/tools - chmod -R u+w clang-tools-extra-* - mv clang-tools-extra-* $sourceRoot/tools/extra - ''; - - nativeBuildInputs = [ cmake python ] - ++ stdenv.lib.optional enableManpages python.pkgs.sphinx; - - buildInputs = [ libxml2 llvm ] - ++ stdenv.lib.optional stdenv.isDarwin fixDarwinDylibNames; - - cmakeFlags = [ - "-DCMAKE_CXX_FLAGS=-std=c++11" - "-DCLANGD_BUILD_XPC=OFF" - ] ++ stdenv.lib.optionals enableManpages [ - "-DCLANG_INCLUDE_DOCS=ON" - "-DLLVM_ENABLE_SPHINX=ON" - "-DSPHINX_OUTPUT_MAN=ON" - "-DSPHINX_OUTPUT_HTML=OFF" - "-DSPHINX_WARNINGS_AS_ERRORS=OFF" - ] ++ stdenv.lib.optionals enablePolly [ - "-DWITH_POLLY=ON" - "-DLINK_POLLY_INTO_TOOLS=ON" - ]; - - patches = [ - #./purity.patch - # already applied upstream it seems: - # ./clang-xpc.patch - # Backport for -static-pie, which the latter touches, and which is nice in - # its own right. - #./static-pie.patch - # Backport for the `--unwindlib=[libgcc|complier-rt]` flag, which is - # needed for our bootstrapping to not interfere with C. - #./unwindlib.patch - ]; - - - postPatch = '' - sed -i -e 's/DriverArgs.hasArg(options::OPT_nostdlibinc)/true/' \ - -e 's/Args.hasArg(options::OPT_nostdlibinc)/true/' \ - lib/Driver/ToolChains/*.cpp - - # Patch for standalone doc building - sed -i '1s,^,find_package(Sphinx REQUIRED)\n,' docs/CMakeLists.txt - '' + stdenv.lib.optionalString stdenv.hostPlatform.isMusl '' - sed -i -e 's/lgcc_s/lgcc_eh/' lib/Driver/ToolChains/*.cpp - '' + stdenv.lib.optionalString stdenv.hostPlatform.isDarwin '' - substituteInPlace tools/extra/clangd/CMakeLists.txt \ - --replace "NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB" FALSE - ''; - - outputs = [ "out" "lib" "python" ]; - - # Clang expects to find LLVMgold in its own prefix - postInstall = '' - if [ -e ${llvm}/lib/LLVMgold.so ]; then - ln -sv ${llvm}/lib/LLVMgold.so $out/lib - fi - - ln -sv $out/bin/clang $out/bin/cpp - - # Move libclang to 'lib' output - moveToOutput "lib/libclang.*" "$lib" - substituteInPlace $out/lib/cmake/clang/ClangTargets-release.cmake \ - --replace "\''${_IMPORT_PREFIX}/lib/libclang." "$lib/lib/libclang." - - mkdir -p $python/bin $python/share/clang/ - mv $out/bin/{git-clang-format,scan-view} $python/bin - if [ -e $out/bin/set-xcode-analyzer ]; then - mv $out/bin/set-xcode-analyzer $python/bin - fi - mv $out/share/clang/*.py $python/share/clang - rm $out/bin/c-index-test - ''; - - enableParallelBuilding = true; - - passthru = { - isClang = true; - inherit llvm; - } // stdenv.lib.optionalAttrs (stdenv.targetPlatform.isLinux || (stdenv.cc.isGNU && stdenv.cc.cc ? gcc)) { - gcc = if stdenv.cc.isGNU then stdenv.cc.cc else stdenv.cc.cc.gcc; - }; - - meta = { - description = "A c, c++, objective-c, and objective-c++ frontend for the llvm compiler"; - homepage = http://llvm.org/; - license = stdenv.lib.licenses.ncsa; - platforms = stdenv.lib.platforms.all; - }; - } // stdenv.lib.optionalAttrs enableManpages { - name = "clang-manpages-${version}"; - - buildPhase = '' - make docs-clang-man - ''; - - installPhase = '' - mkdir -p $out/share/man/man1 - # Manually install clang manpage - cp docs/man/*.1 $out/share/man/man1/ - ''; - - outputs = [ "out" ]; - - doCheck = false; - - meta.description = "man page for Clang ${version}"; - }); -in self diff --git a/nix/llvm/clang/purity.patch b/nix/llvm/clang/purity.patch deleted file mode 100644 index b30d0d0b5d5..00000000000 --- a/nix/llvm/clang/purity.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 4add81bba40dcec62c4ea4481be8e35ac53e89d8 Mon Sep 17 00:00:00 2001 -From: Will Dietz -Date: Thu, 18 May 2017 11:56:12 -0500 -Subject: [PATCH] "purity" patch for 5.0 - ---- - lib/Driver/ToolChains/Gnu.cpp | 7 ------- - 1 file changed, 7 deletions(-) - -diff --git a/lib/Driver/ToolChains/Gnu.cpp b/lib/Driver/ToolChains/Gnu.cpp -index fe3c0191bb..c6a482bece 100644 ---- a/lib/Driver/ToolChains/Gnu.cpp -+++ b/lib/Driver/ToolChains/Gnu.cpp -@@ -494,13 +494,6 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, - if (!Args.hasArg(options::OPT_static)) { - if (Args.hasArg(options::OPT_rdynamic)) - CmdArgs.push_back("-export-dynamic"); -- -- if (!Args.hasArg(options::OPT_shared)) { -- const std::string Loader = -- D.DyldPrefix + ToolChain.getDynamicLinker(Args); -- CmdArgs.push_back("-dynamic-linker"); -- CmdArgs.push_back(Args.MakeArgString(Loader)); -- } - } - - CmdArgs.push_back("-o"); --- -2.11.0 - diff --git a/nix/llvm/clang/static-pie.patch b/nix/llvm/clang/static-pie.patch deleted file mode 100644 index d1f86a16232..00000000000 --- a/nix/llvm/clang/static-pie.patch +++ /dev/null @@ -1,157 +0,0 @@ -commit 7a9842bc92921e79b84630045276861be90b2d47 -Author: Siva Chandra -Date: Wed Feb 20 19:07:04 2019 +0000 - - [Clang Driver] Add support for "-static-pie" argument to the Clang driver. - - Summary: This change mimics GCC's support for the "-static-pie" argument. - - Subscribers: cfe-commits - - Tags: #clang - - Differential Revision: https://reviews.llvm.org/D58307 - - git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@354502 91177308-0d34-0410-b5e6-96231b3b80d8 - (cherry picked from commit 7d6cd7825e6883f8650e32b07f3750824c2cef62) - -diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td -index d02d9744d7..75a21e66c7 100644 ---- a/include/clang/Driver/Options.td -+++ b/include/clang/Driver/Options.td -@@ -2502,6 +2502,7 @@ def pthread : Flag<["-"], "pthread">, Flags<[CC1Option]>, - def no_pthread : Flag<["-"], "no-pthread">, Flags<[CC1Option]>; - def p : Flag<["-"], "p">; - def pie : Flag<["-"], "pie">; -+def static_pie : Flag<["-"], "static-pie">; - def read__only__relocs : Separate<["-"], "read_only_relocs">; - def remap : Flag<["-"], "remap">; - def rewrite_objc : Flag<["-"], "rewrite-objc">, Flags<[DriverOption,CC1Option]>, -diff --git a/lib/Driver/ToolChains/CommonArgs.cpp b/lib/Driver/ToolChains/CommonArgs.cpp -index d7e316befa..85ffc1618d 100644 ---- a/lib/Driver/ToolChains/CommonArgs.cpp -+++ b/lib/Driver/ToolChains/CommonArgs.cpp -@@ -1138,19 +1138,22 @@ static void AddLibgcc(const llvm::Triple &Triple, const Driver &D, - bool isCygMing = Triple.isOSCygMing(); - bool IsIAMCU = Triple.isOSIAMCU(); - bool StaticLibgcc = Args.hasArg(options::OPT_static_libgcc) || -- Args.hasArg(options::OPT_static); -+ Args.hasArg(options::OPT_static) || -+ Args.hasArg(options::OPT_static_pie); - - bool SharedLibgcc = Args.hasArg(options::OPT_shared_libgcc); - bool UnspecifiedLibgcc = !StaticLibgcc && !SharedLibgcc; - - // Gcc adds libgcc arguments in various ways: - // -- // gcc : -lgcc --as-needed -lgcc_s --no-as-needed -- // g++ : -lgcc_s -lgcc -- // gcc shared: -lgcc_s -lgcc -- // g++ shared: -lgcc_s -lgcc -- // gcc static: -lgcc -lgcc_eh -- // g++ static: -lgcc -lgcc_eh -+ // gcc : -lgcc --as-needed -lgcc_s --no-as-needed -+ // g++ : -lgcc_s -lgcc -+ // gcc shared: -lgcc_s -lgcc -+ // g++ shared: -lgcc_s -lgcc -+ // gcc static: -lgcc -lgcc_eh -+ // g++ static: -lgcc -lgcc_eh -+ // gcc static-pie: -lgcc -lgcc_eh -+ // g++ static-pie: -lgcc -lgcc_eh - // - // Also, certain targets need additional adjustments. - -diff --git a/lib/Driver/ToolChains/Gnu.cpp b/lib/Driver/ToolChains/Gnu.cpp -index 69dba8fec8..0faa0bb473 100644 ---- a/lib/Driver/ToolChains/Gnu.cpp -+++ b/lib/Driver/ToolChains/Gnu.cpp -@@ -334,6 +334,7 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, - const bool isAndroid = ToolChain.getTriple().isAndroid(); - const bool IsIAMCU = ToolChain.getTriple().isOSIAMCU(); - const bool IsPIE = getPIE(Args, ToolChain); -+ const bool IsStaticPIE = Args.hasArg(options::OPT_static_pie); - const bool HasCRTBeginEndFiles = - ToolChain.getTriple().hasEnvironment() || - (ToolChain.getTriple().getVendor() != llvm::Triple::MipsTechnologies); -@@ -354,6 +355,12 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, - if (IsPIE) - CmdArgs.push_back("-pie"); - -+ if (IsStaticPIE) { -+ CmdArgs.push_back("-static"); -+ CmdArgs.push_back("-pie"); -+ CmdArgs.push_back("--no-dynamic-linker"); -+ } -+ - if (Args.hasArg(options::OPT_rdynamic)) - CmdArgs.push_back("-export-dynamic"); - -@@ -415,6 +422,8 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, - crt1 = "gcrt1.o"; - else if (IsPIE) - crt1 = "Scrt1.o"; -+ else if (IsStaticPIE) -+ crt1 = "rcrt1.o"; - else - crt1 = "crt1.o"; - } -@@ -432,7 +441,7 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, - crtbegin = isAndroid ? "crtbegin_static.o" : "crtbeginT.o"; - else if (Args.hasArg(options::OPT_shared)) - crtbegin = isAndroid ? "crtbegin_so.o" : "crtbeginS.o"; -- else if (IsPIE) -+ else if (IsPIE || IsStaticPIE) - crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbeginS.o"; - else - crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbegin.o"; -@@ -483,7 +492,7 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, - - if (!Args.hasArg(options::OPT_nostdlib)) { - if (!Args.hasArg(options::OPT_nodefaultlibs)) { -- if (Args.hasArg(options::OPT_static)) -+ if (Args.hasArg(options::OPT_static) || IsStaticPIE) - CmdArgs.push_back("--start-group"); - - if (NeedsSanitizerDeps) -@@ -518,7 +527,7 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, - if (IsIAMCU) - CmdArgs.push_back("-lgloss"); - -- if (Args.hasArg(options::OPT_static)) -+ if (Args.hasArg(options::OPT_static) || IsStaticPIE) - CmdArgs.push_back("--end-group"); - else - AddRunTimeLibs(ToolChain, D, CmdArgs, Args); -@@ -535,7 +544,7 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, - const char *crtend; - if (Args.hasArg(options::OPT_shared)) - crtend = isAndroid ? "crtend_so.o" : "crtendS.o"; -- else if (IsPIE) -+ else if (IsPIE || IsStaticPIE) - crtend = isAndroid ? "crtend_android.o" : "crtendS.o"; - else - crtend = isAndroid ? "crtend_android.o" : "crtend.o"; -diff --git a/test/Driver/linux-ld.c b/test/Driver/linux-ld.c -index 3ab81be490..800f782523 100644 ---- a/test/Driver/linux-ld.c -+++ b/test/Driver/linux-ld.c -@@ -176,6 +176,19 @@ - // CHECK-CLANG-NO-LIBGCC-STATIC: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" - // CHECK-CLANG-NO-LIBGCC-STATIC: "--start-group" "-lgcc" "-lgcc_eh" "-lc" "--end-group" - // -+// RUN: %clang -static-pie -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -+// RUN: --target=x86_64-unknown-linux -rtlib=platform \ -+// RUN: --gcc-toolchain="" \ -+// RUN: --sysroot=%S/Inputs/basic_linux_tree \ -+// RUN: | FileCheck --check-prefix=CHECK-CLANG-LD-STATIC-PIE %s -+// CHECK-CLANG-LD-STATIC-PIE: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" -+// CHECK-CLANG-LD-STATIC-PIE: "-static" -+// CHECK-CLANG-LD-STATIC-PIE: "-pie" -+// CHECK-CLANG-LD-STATIC-PIE: "--no-dynamic-linker" -+// CHECK-CLANG-LD-STATIC-PIE: "-m" "elf_x86_64" -+// CHECK-CLANG-LD-STATIC-PIE: "{{.*}}rcrt1.o" -+// CHECK-CLANG-LD-STATIC-PIE: "--start-group" "-lgcc" "-lgcc_eh" "-lc" "--end-group" -+// - // RUN: %clang -dynamic -no-canonical-prefixes %s -### -o %t.o 2>&1 \ - // RUN: --target=x86_64-unknown-linux -rtlib=platform \ - // RUN: --gcc-toolchain="" \ diff --git a/nix/llvm/clang/unwindlib.patch b/nix/llvm/clang/unwindlib.patch deleted file mode 100644 index 6958fce60ce..00000000000 --- a/nix/llvm/clang/unwindlib.patch +++ /dev/null @@ -1,372 +0,0 @@ -commit cd5603a4767277a29d3e67a9c3f2a5d2129cd973 -Author: Sterling Augustine -Date: Tue Mar 19 20:01:59 2019 +0000 - - Add --unwindlib=[libgcc|compiler-rt] to parallel --rtlib= [take 2] - - "clang++ hello.cc --rtlib=compiler-rt" - - now can works without specifying additional unwind or exception - handling libraries. - - This reworked version of the feature no longer modifies today's default - unwind library for compiler-rt: which is nothing. Rather, a user - can specify -DCLANG_DEFAULT_UNWINDLIB=libunwind when configuring - the compiler. - - This should address the issues from the previous version. - - Update tests for new --unwindlib semantics. - - Differential Revision: https://reviews.llvm.org/D59109 - - git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@356508 91177308-0d34-0410-b5e6-96231b3b80d8 - (cherry picked from commit 344aa82a52f2fae527f58284567ae305a314f7a8) - -diff --git a/CMakeLists.txt b/CMakeLists.txt -index c2016a45ca..edeb2b66a1 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -261,6 +261,24 @@ if (NOT(CLANG_DEFAULT_RTLIB STREQUAL "" OR - "Default runtime library to use (\"libgcc\" or \"compiler-rt\", empty for platform default)" FORCE) - endif() - -+set(CLANG_DEFAULT_UNWINDLIB "" CACHE STRING -+ "Default unwind library to use (\"none\" \"libgcc\" or \"libunwind\", empty to match runtime library.)") -+if (CLANG_DEFAULT_UNWINDLIB STREQUAL "") -+ if (CLANG_DEFAULT_RTLIB STREQUAL "libgcc") -+ set (CLANG_DEFAULT_UNWINDLIB "libgcc" CACHE STRING "" FORCE) -+ elseif (CLANG_DEFAULT_RTLIBS STREQUAL "libunwind") -+ set (CLANG_DEFAULT_UNWINDLIB "none" CACHE STRING "" FORCE) -+ endif() -+endif() -+ -+if (NOT(CLANG_DEFAULT_UNWINDLIB STREQUAL "none" OR -+ CLANG_DEFAULT_UNWINDLIB STREQUAL "libgcc" OR -+ CLANG_DEFAULT_UNWINDLIB STREQUAL "libunwind")) -+ message(WARNING "Resetting default unwindlib to use platform default") -+ set(CLANG_DEFAULT_UNWINDLIB "" CACHE STRING -+ "Default unwind library to use (\"none\" \"libgcc\" or \"libunwind\", empty for none)" FORCE) -+endif() -+ - set(CLANG_DEFAULT_OBJCOPY "objcopy" CACHE STRING - "Default objcopy executable to use.") - -diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td -index 5475e28ed7..15971210e4 100644 ---- a/include/clang/Basic/DiagnosticDriverKinds.td -+++ b/include/clang/Basic/DiagnosticDriverKinds.td -@@ -52,6 +52,10 @@ def err_drv_invalid_rtlib_name : Error< - "invalid runtime library name in argument '%0'">; - def err_drv_unsupported_rtlib_for_platform : Error< - "unsupported runtime library '%0' for platform '%1'">; -+def err_drv_invalid_unwindlib_name : Error< -+ "invalid unwind library name in argument '%0'">; -+def err_drv_incompatible_unwindlib : Error< -+ "--rtlib=libgcc requires --unwindlib=libgcc">; - def err_drv_invalid_stdlib_name : Error< - "invalid library name in argument '%0'">; - def err_drv_invalid_output_with_multiple_archs : Error< -diff --git a/include/clang/Config/config.h.cmake b/include/clang/Config/config.h.cmake -index 1d624450b9..2d4cb747e8 100644 ---- a/include/clang/Config/config.h.cmake -+++ b/include/clang/Config/config.h.cmake -@@ -23,6 +23,9 @@ - /* Default runtime library to use. */ - #define CLANG_DEFAULT_RTLIB "${CLANG_DEFAULT_RTLIB}" - -+/* Default unwind library to use. */ -+#define CLANG_DEFAULT_UNWINDLIB "${CLANG_DEFAULT_UNWINDLIB}" -+ - /* Default objcopy to use */ - #define CLANG_DEFAULT_OBJCOPY "${CLANG_DEFAULT_OBJCOPY}" - -diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td -index 75a21e66c7..4da0e54965 100644 ---- a/include/clang/Driver/Options.td -+++ b/include/clang/Driver/Options.td -@@ -2570,6 +2570,8 @@ def std_EQ : Joined<["-", "--"], "std=">, Flags<[CC1Option]>, - }]>; - def stdlib_EQ : Joined<["-", "--"], "stdlib=">, Flags<[CC1Option]>, - HelpText<"C++ standard library to use">, Values<"libc++,libstdc++,platform">; -+def unwindlib_EQ : Joined<["-", "--"], "unwindlib=">, Flags<[CC1Option]>, -+ HelpText<"Unwind library to use">, Values<"libgcc,unwindlib,platform">; - def sub__library : JoinedOrSeparate<["-"], "sub_library">; - def sub__umbrella : JoinedOrSeparate<["-"], "sub_umbrella">; - def system_header_prefix : Joined<["--"], "system-header-prefix=">, -diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h -index d5f75b8271..4bedf760eb 100644 ---- a/include/clang/Driver/ToolChain.h -+++ b/include/clang/Driver/ToolChain.h -@@ -100,6 +100,12 @@ public: - RLT_Libgcc - }; - -+ enum UnwindLibType { -+ UNW_None, -+ UNW_CompilerRT, -+ UNW_Libgcc -+ }; -+ - enum RTTIMode { - RM_Enabled, - RM_Disabled, -@@ -368,6 +374,10 @@ public: - return ToolChain::CST_Libstdcxx; - } - -+ virtual UnwindLibType GetDefaultUnwindLibType() const { -+ return ToolChain::UNW_None; -+ } -+ - virtual std::string getCompilerRTPath() const; - - virtual std::string getCompilerRT(const llvm::opt::ArgList &Args, -@@ -512,6 +522,10 @@ public: - // given compilation arguments. - virtual CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const; - -+ // GetUnwindLibType - Determine the unwind library type to use with the -+ // given compilation arguments. -+ virtual UnwindLibType GetUnwindLibType(const llvm::opt::ArgList &Args) const; -+ - /// AddClangCXXStdlibIncludeArgs - Add the clang -cc1 level arguments to set - /// the include paths to use for the given C++ standard library type. - virtual void -diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp -index 88a627eab6..d82423f4a8 100644 ---- a/lib/Driver/ToolChain.cpp -+++ b/lib/Driver/ToolChain.cpp -@@ -680,6 +680,33 @@ ToolChain::RuntimeLibType ToolChain::GetRuntimeLibType( - return GetDefaultRuntimeLibType(); - } - -+ToolChain::UnwindLibType ToolChain::GetUnwindLibType( -+ const ArgList &Args) const { -+ const Arg *A = Args.getLastArg(options::OPT_unwindlib_EQ); -+ StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_UNWINDLIB; -+ -+ if (LibName == "none") -+ return ToolChain::UNW_None; -+ else if (LibName == "platform" || LibName == "") { -+ ToolChain::RuntimeLibType RtLibType = GetRuntimeLibType(Args); -+ if (RtLibType == ToolChain::RLT_CompilerRT) -+ return ToolChain::UNW_None; -+ else if (RtLibType == ToolChain::RLT_Libgcc) -+ return ToolChain::UNW_Libgcc; -+ } else if (LibName == "libunwind") { -+ if (GetRuntimeLibType(Args) == RLT_Libgcc) -+ getDriver().Diag(diag::err_drv_incompatible_unwindlib); -+ return ToolChain::UNW_CompilerRT; -+ } else if (LibName == "libgcc") -+ return ToolChain::UNW_Libgcc; -+ -+ if (A) -+ getDriver().Diag(diag::err_drv_invalid_unwindlib_name) -+ << A->getAsString(Args); -+ -+ return GetDefaultUnwindLibType(); -+} -+ - ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{ - const Arg *A = Args.getLastArg(options::OPT_stdlib_EQ); - StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_CXX_STDLIB; -diff --git a/lib/Driver/ToolChains/CommonArgs.cpp b/lib/Driver/ToolChains/CommonArgs.cpp -index 85ffc1618d..9fd29726a4 100644 ---- a/lib/Driver/ToolChains/CommonArgs.cpp -+++ b/lib/Driver/ToolChains/CommonArgs.cpp -@@ -1132,47 +1132,80 @@ bool tools::isObjCAutoRefCount(const ArgList &Args) { - return Args.hasFlag(options::OPT_fobjc_arc, options::OPT_fno_objc_arc, false); - } - --static void AddLibgcc(const llvm::Triple &Triple, const Driver &D, -- ArgStringList &CmdArgs, const ArgList &Args) { -- bool isAndroid = Triple.isAndroid(); -- bool isCygMing = Triple.isOSCygMing(); -- bool IsIAMCU = Triple.isOSIAMCU(); -- bool StaticLibgcc = Args.hasArg(options::OPT_static_libgcc) || -- Args.hasArg(options::OPT_static) || -- Args.hasArg(options::OPT_static_pie); -- -- bool SharedLibgcc = Args.hasArg(options::OPT_shared_libgcc); -- bool UnspecifiedLibgcc = !StaticLibgcc && !SharedLibgcc; -- -- // Gcc adds libgcc arguments in various ways: -- // -- // gcc : -lgcc --as-needed -lgcc_s --no-as-needed -- // g++ : -lgcc_s -lgcc -- // gcc shared: -lgcc_s -lgcc -- // g++ shared: -lgcc_s -lgcc -- // gcc static: -lgcc -lgcc_eh -- // g++ static: -lgcc -lgcc_eh -- // gcc static-pie: -lgcc -lgcc_eh -- // g++ static-pie: -lgcc -lgcc_eh -- // -- // Also, certain targets need additional adjustments. -+enum class LibGccType { UnspecifiedLibGcc, StaticLibGcc, SharedLibGcc }; -+ -+static LibGccType getLibGccType(const ArgList &Args) { -+ bool Static = Args.hasArg(options::OPT_static_libgcc) || -+ Args.hasArg(options::OPT_static) || -+ Args.hasArg(options::OPT_static_pie); -+ -+ bool Shared = Args.hasArg(options::OPT_shared_libgcc); -+ if (Shared) -+ return LibGccType::SharedLibGcc; -+ if (Static) -+ return LibGccType::StaticLibGcc; -+ return LibGccType::UnspecifiedLibGcc; -+} - -- bool LibGccFirst = (D.CCCIsCC() && UnspecifiedLibgcc) || StaticLibgcc; -- if (LibGccFirst) -- CmdArgs.push_back("-lgcc"); -+// Gcc adds libgcc arguments in various ways: -+// -+// gcc : -lgcc --as-needed -lgcc_s --no-as-needed -+// g++ : -lgcc_s -lgcc -+// gcc shared: -lgcc_s -lgcc -+// g++ shared: -lgcc_s -lgcc -+// gcc static: -lgcc -lgcc_eh -+// g++ static: -lgcc -lgcc_eh -+// gcc static-pie: -lgcc -lgcc_eh -+// g++ static-pie: -lgcc -lgcc_eh -+// -+// Also, certain targets need additional adjustments. -+ -+static void AddUnwindLibrary(const ToolChain &TC, const Driver &D, -+ ArgStringList &CmdArgs, const ArgList &Args) { -+ ToolChain::UnwindLibType UNW = TC.GetUnwindLibType(Args); -+ // Targets that don't use unwind libraries. -+ if (TC.getTriple().isAndroid() || TC.getTriple().isOSIAMCU() || -+ TC.getTriple().isOSBinFormatWasm() || -+ UNW == ToolChain::UNW_None) -+ return; - -- bool AsNeeded = D.CCCIsCC() && UnspecifiedLibgcc && !isAndroid && !isCygMing; -+ LibGccType LGT = getLibGccType(Args); -+ bool AsNeeded = D.CCCIsCC() && LGT == LibGccType::UnspecifiedLibGcc && -+ !TC.getTriple().isAndroid() && !TC.getTriple().isOSCygMing(); - if (AsNeeded) - CmdArgs.push_back("--as-needed"); - -- if ((UnspecifiedLibgcc || SharedLibgcc) && !isAndroid) -- CmdArgs.push_back("-lgcc_s"); -- -- else if (StaticLibgcc && !isAndroid && !IsIAMCU) -- CmdArgs.push_back("-lgcc_eh"); -+ switch (UNW) { -+ case ToolChain::UNW_None: -+ return; -+ case ToolChain::UNW_Libgcc: { -+ LibGccType LGT = getLibGccType(Args); -+ if (LGT == LibGccType::UnspecifiedLibGcc || LGT == LibGccType::SharedLibGcc) -+ CmdArgs.push_back("-lgcc_s"); -+ else if (LGT == LibGccType::StaticLibGcc) -+ CmdArgs.push_back("-lgcc_eh"); -+ break; -+ } -+ case ToolChain::UNW_CompilerRT: -+ CmdArgs.push_back("-lunwind"); -+ break; -+ } - - if (AsNeeded) - CmdArgs.push_back("--no-as-needed"); -+} -+ -+static void AddLibgcc(const ToolChain &TC, const Driver &D, -+ ArgStringList &CmdArgs, const ArgList &Args) { -+ bool isAndroid = TC.getTriple().isAndroid(); -+ -+ LibGccType LGT = getLibGccType(Args); -+ bool LibGccFirst = (D.CCCIsCC() && LGT == LibGccType::UnspecifiedLibGcc) || -+ LGT == LibGccType::StaticLibGcc; -+ if (LibGccFirst) -+ CmdArgs.push_back("-lgcc"); -+ -+ AddUnwindLibrary(TC, D, CmdArgs, Args); - - if (!LibGccFirst) - CmdArgs.push_back("-lgcc"); -@@ -1182,7 +1215,7 @@ static void AddLibgcc(const llvm::Triple &Triple, const Driver &D, - // - // NOTE: This fixes a link error on Android MIPS as well. The non-static - // libgcc for MIPS relies on _Unwind_Find_FDE and dl_iterate_phdr from libdl. -- if (isAndroid && !StaticLibgcc) -+ if (isAndroid && getLibGccType(Args) != LibGccType::StaticLibGcc) - CmdArgs.push_back("-ldl"); - } - -@@ -1194,6 +1227,7 @@ void tools::AddRunTimeLibs(const ToolChain &TC, const Driver &D, - switch (RLT) { - case ToolChain::RLT_CompilerRT: - CmdArgs.push_back(TC.getCompilerRTArgString(Args, "builtins")); -+ AddUnwindLibrary(TC, D, CmdArgs, Args); - break; - case ToolChain::RLT_Libgcc: - // Make sure libgcc is not used under MSVC environment by default -@@ -1205,7 +1239,7 @@ void tools::AddRunTimeLibs(const ToolChain &TC, const Driver &D, - << Args.getLastArg(options::OPT_rtlib_EQ)->getValue() << "MSVC"; - } - } else -- AddLibgcc(TC.getTriple(), D, CmdArgs, Args); -+ AddLibgcc(TC, D, CmdArgs, Args); - break; - } - } -diff --git a/test/Driver/compiler-rt-unwind.c b/test/Driver/compiler-rt-unwind.c -new file mode 100644 -index 0000000000..00024dfa7e ---- /dev/null -+++ b/test/Driver/compiler-rt-unwind.c -@@ -0,0 +1,49 @@ -+// General tests that the driver handles combinations of --rtlib=XXX and -+// --unwindlib=XXX properly. -+// -+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -+// RUN: --target=x86_64-unknown-linux \ -+// RUN: --gcc-toolchain="" \ -+// RUN: | FileCheck --check-prefix=RTLIB-EMPTY %s -+// RTLIB-EMPTY: "{{.*}}lgcc" -+// RTLIB-EMPTY: "{{.*}}-lgcc_s" -+// -+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -+// RUN: --target=x86_64-unknown-linux -rtlib=libgcc \ -+// RUN: --gcc-toolchain="" \ -+// RUN: | FileCheck --check-prefix=RTLIB-GCC %s -+// RTLIB-GCC: "{{.*}}lgcc" -+// RTLIB-GCC: "{{.*}}lgcc_s" -+// -+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -+// RUN: --target=x86_64-unknown-linux -rtlib=libgcc --unwindlib=libunwind \ -+// RUN: --gcc-toolchain="" \ -+// RUN: | FileCheck --check-prefix=RTLIB-GCC-UNWINDLIB-COMPILER-RT %s -+// RTLIB-GCC-UNWINDLIB-COMPILER-RT: "{{.*}}lgcc" -+// RTLIB-GCC-UNWINDLIB-COMPILER-RT: "{{.*}}lunwind" -+// -+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -+// RUN: --target=x86_64-unknown-linux -rtlib=compiler-rt \ -+// RUN: --gcc-toolchain="" \ -+// RUN: | FileCheck --check-prefix=RTLIB-COMPILER-RT %s -+// RTLIB-COMPILER-RT: "{{.*}}libclang_rt.builtins-x86_64.a" -+// -+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -+// RUN: --target=x86_64-unknown-linux -rtlib=compiler-rt --unwindlib=libgcc \ -+// RUN: --gcc-toolchain="" \ -+// RUN: | FileCheck --check-prefix=RTLIB-COMPILER-RT-UNWINDLIB-GCC %s -+// RTLIB-COMPILER-RT-UNWINDLIB-GCC: "{{.*}}libclang_rt.builtins-x86_64.a" -+// RTLIB-COMPILER-RT-UNWINDLIB-GCC: "{{.*}}lgcc_s" -+// -+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -+// RUN: --target=x86_64-unknown-linux -rtlib=compiler-rt --unwindlib=libgcc \ -+// RUN: -static --gcc-toolchain="" \ -+// RUN: | FileCheck --check-prefix=RTLIB-COMPILER-RT-UNWINDLIB-GCC-STATIC %s -+// RTLIB-COMPILER-RT-UNWINDLIB-GCC-STATIC: "{{.*}}libclang_rt.builtins-x86_64.a" -+// RTLIB-COMPILER-RT-UNWINDLIB-GCC-STATIC: "{{.*}}lgcc_eh" -+// -+// RUN: not %clang -no-canonical-prefixes %s -o %t.o 2> %t.err \ -+// RUN: --target=x86_64-unknown-linux -rtlib=libgcc --unwindlib=libunwind \ -+// RUN: --gcc-toolchain="" \ -+// RUN: FileCheck --input-file=%t.err --check-prefix=RTLIB-GCC-UNWINDLIB-COMPILER_RT %s -+// RTLIB-GCC-UNWINDLIB-COMPILER_RT: "{{[.|\\\n]*}}--rtlib=libgcc requires --unwindlib=libgcc" diff --git a/nix/llvm/compiler-rt-codesign.patch b/nix/llvm/compiler-rt-codesign.patch deleted file mode 100644 index 3cc12b94b20..00000000000 --- a/nix/llvm/compiler-rt-codesign.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 3dec5f3475a26aeb4678627795c4b67c6b7b4785 Mon Sep 17 00:00:00 2001 -From: Will Dietz -Date: Tue, 19 Sep 2017 13:13:06 -0500 -Subject: [PATCH] remove codesign use on Apple, disable ios sim testing that - needs it - ---- - cmake/Modules/AddCompilerRT.cmake | 8 ------ - test/asan/CMakeLists.txt | 52 --------------------------------------- - test/tsan/CMakeLists.txt | 47 ----------------------------------- - 3 files changed, 107 deletions(-) - -diff --git a/cmake/Modules/AddCompilerRT.cmake b/cmake/Modules/AddCompilerRT.cmake -index bc5fb9ff7..b64eb4246 100644 ---- a/cmake/Modules/AddCompilerRT.cmake -+++ b/cmake/Modules/AddCompilerRT.cmake -@@ -210,14 +210,6 @@ function(add_compiler_rt_runtime name type) - set_target_properties(${libname} PROPERTIES IMPORT_PREFIX "") - set_target_properties(${libname} PROPERTIES IMPORT_SUFFIX ".lib") - endif() -- if(APPLE) -- # Ad-hoc sign the dylibs -- add_custom_command(TARGET ${libname} -- POST_BUILD -- COMMAND codesign --sign - $ -- WORKING_DIRECTORY ${COMPILER_RT_LIBRARY_OUTPUT_DIR} -- ) -- endif() - endif() - install(TARGETS ${libname} - ARCHIVE DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR} -2.14.1 - diff --git a/nix/llvm/compiler-rt.nix b/nix/llvm/compiler-rt.nix deleted file mode 100644 index 39c26f4a06f..00000000000 --- a/nix/llvm/compiler-rt.nix +++ /dev/null @@ -1,67 +0,0 @@ -{ stdenv, version, fetch, cmake, python, llvm, libcxxabi }: -stdenv.mkDerivation rec { - name = "compiler-rt-${version}"; - inherit version; - src = fetch "compiler-rt" "0v03h0979v7adw6vixabc21i4v5yf3mnxh7w5v4kg32cwr0xi6zz"; - - nativeBuildInputs = [ cmake python llvm ]; - buildInputs = stdenv.lib.optional stdenv.hostPlatform.isDarwin libcxxabi; - - cmakeFlags = [ - "-DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON" - "-DCMAKE_C_COMPILER_TARGET=${stdenv.hostPlatform.config}" - "-DCMAKE_ASM_COMPILER_TARGET=${stdenv.hostPlatform.config}" - ] ++ stdenv.lib.optionals (stdenv.hostPlatform != stdenv.buildPlatform) [ - "-DCMAKE_C_FLAGS=-nodefaultlibs" - "-DCMAKE_CXX_COMPILER_WORKS=ON" - "-DCOMPILER_RT_BUILD_SANITIZERS=OFF" - "-DCOMPILER_RT_BUILD_XRAY=OFF" - "-DCOMPILER_RT_BUILD_LIBFUZZER=OFF" - "-DCOMPILER_RT_BUILD_PROFILE=OFF" - "-DCOMPILER_RT_BAREMETAL_BUILD=ON" - #https://stackoverflow.com/questions/53633705/cmake-the-c-compiler-is-not-able-to-compile-a-simple-test-program - "-DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY" - "-DCMAKE_SIZEOF_VOID_P=${toString (stdenv.hostPlatform.parsed.cpu.bits / 8)}" - ] ++ stdenv.lib.optionals stdenv.hostPlatform.isMusl [ - "-DCOMPILER_RT_BUILD_SANITIZERS=OFF" - "-DCOMPILER_RT_BUILD_XRAY=OFF" - "-DCOMPILER_RT_BUILD_LIBFUZZER=OFF" - "-DCOMPILER_RT_BUILD_PROFILE=OFF" - ]; - - outputs = [ "out" "dev" ]; - - patches = [ - ./compiler-rt-codesign.patch # Revert compiler-rt commit that makes codesign mandatory - ]# ++ stdenv.lib.optional stdenv.hostPlatform.isMusl ./sanitizers-nongnu.patch - ++ stdenv.lib.optional (stdenv.hostPlatform != stdenv.buildPlatform) ./crtbegin-and-end.patch; - - # TSAN requires XPC on Darwin, which we have no public/free source files for. We can depend on the Apple frameworks - # to get it, but they're unfree. Since LLVM is rather central to the stdenv, we patch out TSAN support so that Hydra - # can build this. If we didn't do it, basically the entire nixpkgs on Darwin would have an unfree dependency and we'd - # get no binary cache for the entire platform. If you really find yourself wanting the TSAN, make this controllable by - # a flag and turn the flag off during the stdenv build. - postPatch = stdenv.lib.optionalString stdenv.isDarwin '' - substituteInPlace cmake/config-ix.cmake \ - --replace 'set(COMPILER_RT_HAS_TSAN TRUE)' 'set(COMPILER_RT_HAS_TSAN FALSE)' - '' + stdenv.lib.optionalString (stdenv.hostPlatform != stdenv.buildPlatform) '' - substituteInPlace lib/builtins/int_util.c \ - --replace "#include " "" - substituteInPlace lib/builtins/clear_cache.c \ - --replace "#include " "" - substituteInPlace lib/builtins/cpu_model.c \ - --replace "#include " "" - ''; - - # Hack around weird upsream RPATH bug - postInstall = stdenv.lib.optionalString (stdenv.hostPlatform.isDarwin || stdenv.hostPlatform.isWasm) '' - ln -s "$out/lib"/*/* "$out/lib" - '' + stdenv.lib.optionalString (stdenv.hostPlatform.useLLVM or false) '' - ln -s $out/lib/*/clang_rt.crtbegin-*.o $out/lib/crtbegin.o - ln -s $out/lib/*/clang_rt.crtend-*.o $out/lib/crtend.o - ln -s $out/lib/*/clang_rt.crtbegin_shared-*.o $out/lib/crtbeginS.o - ln -s $out/lib/*/clang_rt.crtend_shared-*.o $out/lib/crtendS.o - ''; - - enableParallelBuilding = true; -} diff --git a/nix/llvm/crtbegin-and-end.patch b/nix/llvm/crtbegin-and-end.patch deleted file mode 100644 index e63be181f95..00000000000 --- a/nix/llvm/crtbegin-and-end.patch +++ /dev/null @@ -1,595 +0,0 @@ -Get crtbegin and crtend without compiler GCC! PR is at https://reviews.llvm.org/D28791 - -Index: compiler-rt/CMakeLists.txt -=================================================================== ---- compiler-rt/CMakeLists.txt -+++ compiler-rt/CMakeLists.txt -@@ -29,6 +29,8 @@ - - option(COMPILER_RT_BUILD_BUILTINS "Build builtins" ON) - mark_as_advanced(COMPILER_RT_BUILD_BUILTINS) -+option(COMPILER_RT_BUILD_CRT "Build crtbegin.o/crtend.o" ON) -+mark_as_advanced(COMPILER_RT_BUILD_CRT) - option(COMPILER_RT_BUILD_SANITIZERS "Build sanitizers" ON) - mark_as_advanced(COMPILER_RT_BUILD_SANITIZERS) - option(COMPILER_RT_BUILD_XRAY "Build xray" ON) -Index: compiler-rt/cmake/Modules/AddCompilerRT.cmake -=================================================================== ---- compiler-rt/cmake/Modules/AddCompilerRT.cmake -+++ compiler-rt/cmake/Modules/AddCompilerRT.cmake -@@ -132,7 +132,7 @@ - # Adds static or shared runtime for a list of architectures and operating - # systems and puts it in the proper directory in the build and install trees. - # add_compiler_rt_runtime( --# {STATIC|SHARED} -+# {OBJECT|STATIC|SHARED} - # ARCHS - # OS - # SOURCES -@@ -144,8 +144,8 @@ - # PARENT_TARGET - # ADDITIONAL_HEADERS
) - function(add_compiler_rt_runtime name type) -- if(NOT type MATCHES "^(STATIC|SHARED)$") -- message(FATAL_ERROR "type argument must be STATIC or SHARED") -+ if(NOT type MATCHES "^(OBJECT|STATIC|SHARED)$") -+ message(FATAL_ERROR "type argument must be OBJECT, STATIC or SHARED") - return() - endif() - cmake_parse_arguments(LIB -@@ -204,7 +204,10 @@ - message(FATAL_ERROR "Architecture ${arch} can't be targeted") - return() - endif() -- if(type STREQUAL "STATIC") -+ if(type STREQUAL "OBJECT") -+ set(libname "${name}-${arch}") -+ set(output_name_${libname} ${libname}${COMPILER_RT_OS_SUFFIX}) -+ elseif(type STREQUAL "STATIC") - set(libname "${name}-${arch}") - set_output_name(output_name_${libname} ${name} ${arch}) - else() -@@ -270,12 +273,34 @@ - set(COMPONENT_OPTION COMPONENT ${libname}) - endif() - -- add_library(${libname} ${type} ${sources_${libname}}) -- set_target_compile_flags(${libname} ${extra_cflags_${libname}}) -- set_target_link_flags(${libname} ${extra_link_flags_${libname}}) -- set_property(TARGET ${libname} APPEND PROPERTY -- COMPILE_DEFINITIONS ${LIB_DEFS}) -- set_target_output_directories(${libname} ${output_dir_${libname}}) -+ if(type STREQUAL "OBJECT") -+ string(TOUPPER ${CMAKE_BUILD_TYPE} config) -+ get_property(cflags SOURCE ${sources_${libname}} PROPERTY COMPILE_FLAGS) -+ separate_arguments(cflags) -+ add_custom_command( -+ OUTPUT ${output_dir_${libname}}/${libname}.o -+ COMMAND ${CMAKE_C_COMPILER} ${sources_${libname}} ${cflags} ${extra_cflags_${libname}} -c -o ${output_dir_${libname}}/${libname}.o -+ DEPENDS ${sources_${libname}} -+ COMMENT "Building C object ${libname}.o") -+ add_custom_target(${libname} DEPENDS ${output_dir_${libname}}/${libname}.o) -+ install(FILES ${output_dir_${libname}}/${libname}.o -+ DESTINATION ${install_dir_${libname}} -+ ${COMPONENT_OPTION}) -+ else() -+ add_library(${libname} ${type} ${sources_${libname}}) -+ set_target_compile_flags(${libname} ${extra_cflags_${libname}}) -+ set_target_link_flags(${libname} ${extra_link_flags_${libname}}) -+ set_property(TARGET ${libname} APPEND PROPERTY -+ COMPILE_DEFINITIONS ${LIB_DEFS}) -+ set_target_output_directories(${libname} ${output_dir_${libname}}) -+ install(TARGETS ${libname} -+ ARCHIVE DESTINATION ${install_dir_${libname}} -+ ${COMPONENT_OPTION} -+ LIBRARY DESTINATION ${install_dir_${libname}} -+ ${COMPONENT_OPTION} -+ RUNTIME DESTINATION ${install_dir_${libname}} -+ ${COMPONENT_OPTION}) -+ endif() - set_target_properties(${libname} PROPERTIES - OUTPUT_NAME ${output_name_${libname}}) - set_target_properties(${libname} PROPERTIES FOLDER "Compiler-RT Runtime") -@@ -299,13 +324,6 @@ - ) - endif() - endif() -- install(TARGETS ${libname} -- ARCHIVE DESTINATION ${install_dir_${libname}} -- ${COMPONENT_OPTION} -- LIBRARY DESTINATION ${install_dir_${libname}} -- ${COMPONENT_OPTION} -- RUNTIME DESTINATION ${install_dir_${libname}} -- ${COMPONENT_OPTION}) - - # We only want to generate per-library install targets if you aren't using - # an IDE because the extra targets get cluttered in IDEs. -Index: compiler-rt/cmake/config-ix.cmake -=================================================================== ---- compiler-rt/cmake/config-ix.cmake -+++ compiler-rt/cmake/config-ix.cmake -@@ -227,6 +227,7 @@ - ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} ${S390X}) - set(ALL_ASAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} - ${MIPS32} ${MIPS64} ${PPC64} ${S390X}) -+set(ALL_CRT_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64}) - set(ALL_DFSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64}) - set(ALL_FUZZER_SUPPORTED_ARCH ${X86_64} ${ARM64}) - -@@ -474,6 +475,7 @@ - SANITIZER_COMMON_SUPPORTED_ARCH) - - else() -+ filter_available_targets(CRT_SUPPORTED_ARCH ${ALL_CRT_SUPPORTED_ARCH}) - # Architectures supported by compiler-rt libraries. - filter_available_targets(SANITIZER_COMMON_SUPPORTED_ARCH - ${ALL_SANITIZER_COMMON_SUPPORTED_ARCH}) -@@ -563,6 +565,12 @@ - - # TODO: Add builtins support. - -+if (CRT_SUPPORTED_ARCH AND OS_NAME MATCHES "Linux") -+ set(COMPILER_RT_HAS_CRT TRUE) -+else() -+ set(COMPILER_RT_HAS_CRT FALSE) -+endif() -+ - if (COMPILER_RT_HAS_SANITIZER_COMMON AND DFSAN_SUPPORTED_ARCH AND - OS_NAME MATCHES "Linux") - set(COMPILER_RT_HAS_DFSAN TRUE) -Index: compiler-rt/lib/CMakeLists.txt -=================================================================== ---- compiler-rt/lib/CMakeLists.txt -+++ compiler-rt/lib/CMakeLists.txt -@@ -17,6 +17,10 @@ - add_subdirectory(builtins) - endif() - -+if(COMPILER_RT_BUILD_CRT) -+ add_subdirectory(crt) -+endif() -+ - function(compiler_rt_build_runtime runtime) - string(TOUPPER ${runtime} runtime_uppercase) - if(COMPILER_RT_HAS_${runtime_uppercase}) -Index: compiler-rt/lib/crt/CMakeLists.txt -=================================================================== ---- /dev/null -+++ compiler-rt/lib/crt/CMakeLists.txt -@@ -0,0 +1,102 @@ -+add_compiler_rt_component(crt) -+ -+function(check_cxx_section_exists section output) -+ cmake_parse_arguments(ARG "" "" "SOURCE;FLAGS" ${ARGN}) -+ if(NOT ARG_SOURCE) -+ set(ARG_SOURCE "int main() { return 0; }\n") -+ endif() -+ -+ string(RANDOM TARGET_NAME) -+ set(TARGET_NAME "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cmTC_${TARGET_NAME}.dir") -+ file(MAKE_DIRECTORY ${TARGET_NAME}) -+ -+ file(WRITE "${TARGET_NAME}/CheckSectionExists.c" "${ARG_SOURCE}\n") -+ -+ string(REGEX MATCHALL "<[A-Za-z0-9_]*>" substitutions -+ ${CMAKE_C_COMPILE_OBJECT}) -+ -+ set(try_compile_flags "${ARG_FLAGS}") -+ if(CMAKE_C_COMPILER_ID MATCHES Clang AND CMAKE_C_COMPILER_TARGET) -+ list(APPEND try_compile_flags "-target ${CMAKE_C_COMPILER_TARGET}") -+ endif() -+ -+ string(REPLACE ";" " " extra_flags "${try_compile_flags}") -+ -+ set(test_compile_command "${CMAKE_C_COMPILE_OBJECT}") -+ foreach(substitution ${substitutions}) -+ if(substitution STREQUAL "") -+ string(REPLACE "" -+ "${CMAKE_C_COMPILER}" test_compile_command ${test_compile_command}) -+ elseif(substitution STREQUAL "") -+ string(REPLACE "" "${TARGET_NAME}/CheckSectionExists.o" -+ test_compile_command ${test_compile_command}) -+ elseif(substitution STREQUAL "") -+ string(REPLACE "" "${TARGET_NAME}/CheckSectionExists.c" -+ test_compile_command ${test_compile_command}) -+ elseif(substitution STREQUAL "") -+ string(REPLACE "" "${CMAKE_C_FLAGS} ${extra_flags}" -+ test_compile_command ${test_compile_command}) -+ else() -+ string(REPLACE "${substitution}" "" test_compile_command -+ ${test_compile_command}) -+ endif() -+ endforeach() -+ -+ string(REPLACE " " ";" test_compile_command "${test_compile_command}") -+ -+ execute_process( -+ COMMAND ${test_compile_command} -+ RESULT_VARIABLE TEST_RESULT -+ OUTPUT_VARIABLE TEST_OUTPUT -+ ERROR_VARIABLE TEST_ERROR -+ ) -+ -+ execute_process( -+ COMMAND ${CMAKE_OBJDUMP} -h "${TARGET_NAME}/CheckSectionExists.o" -+ RESULT_VARIABLE CHECK_RESULT -+ OUTPUT_VARIABLE CHECK_OUTPUT -+ ERROR_VARIABLE CHECK_ERROR -+ ) -+ string(FIND "${CHECK_OUTPUT}" "${section}" SECTION_FOUND) -+ -+ if(NOT SECTION_FOUND EQUAL -1) -+ set(${output} TRUE PARENT_SCOPE) -+ else() -+ set(${output} FALSE PARENT_SCOPE) -+ endif() -+ -+ file(REMOVE_RECURSE ${TARGET_NAME}) -+endfunction() -+ -+check_cxx_section_exists(".init_array" COMPILER_RT_HAS_INITFINI_ARRAY -+ SOURCE "__attribute__((constructor)) void f() {}\nint main() { return 0; }\n") -+ -+append_list_if(COMPILER_RT_HAS_INITFINI_ARRAY -DCRT_HAS_INITFINI_ARRAY CRT_CFLAGS) -+append_list_if(COMPILER_RT_HAS_FPIC_FLAG -fPIC CRT_CFLAGS) -+ -+foreach(arch ${CRT_SUPPORTED_ARCH}) -+ add_compiler_rt_runtime(clang_rt.crtbegin -+ OBJECT -+ ARCHS ${arch} -+ SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/crtbegin.c -+ CFLAGS ${CRT_CFLAGS} -+ PARENT_TARGET crt) -+ add_compiler_rt_runtime(clang_rt.crtbegin_shared -+ OBJECT -+ ARCHS ${arch} -+ SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/crtbegin.c -+ CFLAGS ${CRT_CFLAGS} -DCRT_SHARED -+ PARENT_TARGET crt) -+ add_compiler_rt_runtime(clang_rt.crtend -+ OBJECT -+ ARCHS ${arch} -+ SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/crtend.c -+ CFLAGS ${CRT_CFLAGS} -+ PARENT_TARGET crt) -+ add_compiler_rt_runtime(clang_rt.crtend_shared -+ OBJECT -+ ARCHS ${arch} -+ SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/crtend.c -+ CFLAGS ${CRT_CFLAGS} -DCRT_SHARED -+ PARENT_TARGET crt) -+endforeach() -Index: compiler-rt/lib/crt/crtbegin.c -=================================================================== ---- /dev/null -+++ compiler-rt/lib/crt/crtbegin.c -@@ -0,0 +1,108 @@ -+/* ===-- crtbegin.c - Start of constructors and destructors ----------------=== -+ * -+ * The LLVM Compiler Infrastructure -+ * -+ * This file is dual licensed under the MIT and the University of Illinois Open -+ * Source Licenses. See LICENSE.TXT for details. -+ * -+ * ===----------------------------------------------------------------------=== -+ */ -+ -+#include -+ -+__attribute__((visibility("hidden"))) -+#ifdef CRT_SHARED -+void *__dso_handle = &__dso_handle; -+#else -+void *__dso_handle = (void *)0; -+#endif -+ -+static long __EH_FRAME_LIST__[] -+ __attribute__((section(".eh_frame"), aligned(sizeof(void *)))) = {}; -+ -+extern void __register_frame_info(const void *, void *) __attribute__((weak)); -+extern void *__deregister_frame_info(const void *) __attribute__((weak)); -+ -+#ifndef CRT_HAS_INITFINI_ARRAY -+typedef void (*fp)(void); -+ -+static fp __CTOR_LIST__[] -+ __attribute__((section(".ctors"), aligned(sizeof(fp)), used)) = {(fp)-1}; -+extern fp __CTOR_LIST_END__[]; -+#endif -+ -+#ifdef CRT_SHARED -+extern void __cxa_finalize(void *) __attribute__((weak)); -+#endif -+ -+static void __attribute__((used)) __do_init() { -+ static _Bool __initialized; -+ if (__builtin_expect(__initialized, 0)) -+ return; -+ __initialized = 1; -+ -+ static struct { void *p[8]; } __object; -+ if (__register_frame_info) -+ __register_frame_info(__EH_FRAME_LIST__, &__object); -+ -+#ifndef CRT_HAS_INITFINI_ARRAY -+ const size_t n = __CTOR_LIST_END__ - __CTOR_LIST__ - 1; -+ for (size_t i = n; i >= 1; i--) __CTOR_LIST__[i](); -+#endif -+} -+ -+#ifdef CRT_HAS_INITFINI_ARRAY -+__attribute__((section(".init_array"), -+ used)) static void (*__init)(void) = __do_init; -+#else // CRT_HAS_INITFINI_ARRAY -+#if defined(__i386__) || defined(__x86_64__) -+asm(".pushsection .init,\"ax\",@progbits\n\t" -+ "call " __USER_LABEL_PREFIX__ "__do_init\n\t" -+ ".popsection"); -+#elif defined(__arm__) -+asm(".pushsection .init,\"ax\",%progbits\n\t" -+ "bl " __USER_LABEL_PREFIX__ "__do_init\n\t" -+ ".popsection"); -+#endif // CRT_HAS_INITFINI_ARRAY -+#endif -+ -+#ifndef CRT_HAS_INITFINI_ARRAY -+static fp __DTOR_LIST__[] -+ __attribute__((section(".dtors"), aligned(sizeof(fp)), used)) = {(fp)-1}; -+extern fp __DTOR_LIST_END__[]; -+#endif -+ -+static void __attribute__((used)) __do_fini() { -+ static _Bool __finalized; -+ if (__builtin_expect(__finalized, 0)) -+ return; -+ __finalized = 1; -+ -+#ifdef CRT_SHARED -+ if (__cxa_finalize) -+ __cxa_finalize(__dso_handle); -+#endif -+ -+#ifndef CRT_HAS_INITFINI_ARRAY -+ if (__deregister_frame_info) -+ __deregister_frame_info(__EH_FRAME_LIST__); -+ -+ const size_t n = __DTOR_LIST_END__ - __DTOR_LIST__ - 1; -+ for (size_t i = 1; i < n; i++) __DTOR_LIST__[i](); -+#endif -+} -+ -+#ifdef CRT_HAS_INITFINI_ARRAY -+__attribute__((section(".fini_array"), -+ used)) static void (*__fini)(void) = __do_fini; -+#else // CRT_HAS_INITFINI_ARRAY -+#if defined(__i386__) || defined(__x86_64__) -+asm(".pushsection .fini,\"ax\",@progbits\n\t" -+ "call " __USER_LABEL_PREFIX__ "__do_fini\n\t" -+ ".popsection"); -+#elif defined(__arm__) -+asm(".pushsection .fini,\"ax\",%progbits\n\t" -+ "bl " __USER_LABEL_PREFIX__ "__do_fini\n\t" -+ ".popsection"); -+#endif -+#endif // CRT_HAS_INIT_FINI_ARRAY -Index: compiler-rt/lib/crt/crtend.c -=================================================================== ---- /dev/null -+++ compiler-rt/lib/crt/crtend.c -@@ -0,0 +1,24 @@ -+/* ===-- crtend.c - End of constructors and destructors --------------------=== -+ * -+ * The LLVM Compiler Infrastructure -+ * -+ * This file is dual licensed under the MIT and the University of Illinois Open -+ * Source Licenses. See LICENSE.TXT for details. -+ * -+ * ===----------------------------------------------------------------------=== -+ */ -+ -+#include -+ -+// Put 4-byte zero which is the length field in FDE at the end as a terminator. -+const int32_t __EH_FRAME_LIST_END__[] -+ __attribute__((section(".eh_frame"), aligned(sizeof(int32_t)), -+ visibility("hidden"), used)) = {0}; -+ -+#ifndef CRT_HAS_INITFINI_ARRAY -+typedef void (*fp)(void); -+fp __CTOR_LIST_END__[] -+ __attribute__((section(".ctors"), visibility("hidden"), used)) = {0}; -+fp __DTOR_LIST_END__[] -+ __attribute__((section(".dtors"), visibility("hidden"), used)) = {0}; -+#endif -Index: compiler-rt/test/CMakeLists.txt -=================================================================== ---- compiler-rt/test/CMakeLists.txt -+++ compiler-rt/test/CMakeLists.txt -@@ -73,6 +73,9 @@ - if(COMPILER_RT_BUILD_XRAY) - compiler_rt_test_runtime(xray) - endif() -+ if(COMPILER_RT_HAS_CRT) -+ add_subdirectory(crt) -+ endif() - # ShadowCallStack does not yet provide a runtime with compiler-rt, the tests - # include their own minimal runtime - add_subdirectory(shadowcallstack) -Index: compiler-rt/test/crt/CMakeLists.txt -=================================================================== ---- /dev/null -+++ compiler-rt/test/crt/CMakeLists.txt -@@ -0,0 +1,31 @@ -+set(CRT_LIT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) -+ -+set(CRT_TESTSUITES) -+ -+set(CRT_TEST_DEPS "") -+ -+if(NOT COMPILER_RT_STANDALONE_BUILD AND COMPILER_RT_BUILD_CRT AND -+ COMPILER_RT_HAS_CRT) -+ list(APPEND CRT_TEST_DEPS crt) -+endif() -+ -+set(CRT_TEST_ARCH ${CRT_SUPPORTED_ARCH}) -+if (COMPILER_RT_BUILD_CRT AND COMPILER_RT_HAS_CRT) -+ foreach(arch ${CRT_TEST_ARCH}) -+ set(CRT_TEST_TARGET_ARCH ${arch}) -+ string(TOLOWER "-${arch}-${OS_NAME}" CRT_TEST_CONFIG_SUFFIX) -+ get_test_cc_for_arch(${arch} CRT_TEST_TARGET_CC CRT_TEST_TARGET_CFLAGS) -+ string(TOUPPER ${arch} ARCH_UPPER_CASE) -+ set(CONFIG_NAME ${ARCH_UPPER_CASE}${OS_NAME}Config) -+ -+ configure_lit_site_cfg( -+ ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in -+ ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg) -+ list(APPEND CRT_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}) -+ endforeach() -+endif() -+ -+add_lit_testsuite(check-crt "Running the CRT tests" -+ ${CRT_TESTSUITES} -+ DEPENDS ${CRT_TEST_DEPS}) -+set_target_properties(check-crt PROPERTIES FOLDER "Compiler-RT Misc") -Index: compiler-rt/test/crt/dso_handle.cpp -=================================================================== ---- /dev/null -+++ compiler-rt/test/crt/dso_handle.cpp -@@ -0,0 +1,33 @@ -+// RUN: %clangxx -g -DCRT_SHARED -c %s -fPIC -o %tshared.o -+// RUN: %clangxx -g -c %s -fPIC -o %t.o -+// RUN: %clangxx -g -shared -o %t.so -nostdlib %crti %shared_crtbegin %tshared.o %libstdcxx -lc -lm -lgcc_s %shared_crtend %crtn -+// RUN: %clangxx -g -o %t -nostdlib %crt1 %crti %crtbegin %t.o %libstdcxx -lc -lm %libgcc %t.so %crtend %crtn -+// RUN: %run %t 2>&1 | FileCheck %s -+ -+#include -+ -+// CHECK: 1 -+// CHECK-NEXT: ~A() -+ -+#ifdef CRT_SHARED -+bool G; -+void C() { -+ printf("%d\n", G); -+} -+ -+struct A { -+ A() { G = true; } -+ ~A() { -+ printf("~A()\n"); -+ } -+}; -+ -+A a; -+#else -+void C(); -+ -+int main() { -+ C(); -+ return 0; -+} -+#endif -Index: compiler-rt/test/crt/lit.cfg -=================================================================== ---- /dev/null -+++ compiler-rt/test/crt/lit.cfg -@@ -0,0 +1,80 @@ -+# -*- Python -*- -+ -+import os -+import subprocess -+ -+# Setup config name. -+config.name = 'CRT' + config.name_suffix -+ -+# Setup source root. -+config.test_source_root = os.path.dirname(__file__) -+ -+ -+def get_library_path(file): -+ cmd = subprocess.Popen([config.clang.strip(), -+ config.target_cflags.strip(), -+ '-print-file-name=%s' % file], -+ stdout=subprocess.PIPE, -+ env=config.environment) -+ if not cmd.stdout: -+ lit_config.fatal("Couldn't find the library path for '%s'" % file) -+ dir = cmd.stdout.read().strip() -+ if sys.platform in ['win32'] and execute_external: -+ # Don't pass dosish path separator to msys bash.exe. -+ dir = dir.replace('\\', '/') -+ # Ensure the result is an ascii string, across Python2.5+ - Python3. -+ return str(dir.decode('ascii')) -+ -+ -+def get_libgcc_file_name(): -+ cmd = subprocess.Popen([config.clang.strip(), -+ config.target_cflags.strip(), -+ '-print-libgcc-file-name'], -+ stdout=subprocess.PIPE, -+ env=config.environment) -+ if not cmd.stdout: -+ lit_config.fatal("Couldn't find the library path for '%s'" % file) -+ dir = cmd.stdout.read().strip() -+ if sys.platform in ['win32'] and execute_external: -+ # Don't pass dosish path separator to msys bash.exe. -+ dir = dir.replace('\\', '/') -+ # Ensure the result is an ascii string, across Python2.5+ - Python3. -+ return str(dir.decode('ascii')) -+ -+ -+def build_invocation(compile_flags): -+ return ' ' + ' '.join([config.clang] + compile_flags) + ' ' -+ -+ -+# Setup substitutions. -+config.substitutions.append( -+ ('%clang ', build_invocation([config.target_cflags]))) -+config.substitutions.append( -+ ('%clangxx ', -+ build_invocation(config.cxx_mode_flags + [config.target_cflags]))) -+ -+base_lib = os.path.join( -+ config.compiler_rt_libdir, "clang_rt.%%s-%s.o" % config.target_arch) -+config.substitutions.append(('%crtbegin', base_lib % "crtbegin")) -+config.substitutions.append(('%shared_crtbegin', base_lib % "crtbegin_shared")) -+config.substitutions.append(('%crtend', base_lib % "crtend")) -+config.substitutions.append(('%shared_crtend', base_lib % "crtend_shared")) -+ -+config.substitutions.append( -+ ('%crt1', get_library_path('crt1.o'))) -+config.substitutions.append( -+ ('%crti', get_library_path('crti.o'))) -+config.substitutions.append( -+ ('%crtn', get_library_path('crtn.o'))) -+ -+config.substitutions.append( -+ ('%libgcc', get_libgcc_file_name())) -+ -+config.substitutions.append( -+ ('%libstdcxx', '-l' + config.sanitizer_cxx_lib.lstrip('lib'))) -+ -+# Default test suffixes. -+config.suffixes = ['.c', '.cc', '.cpp'] -+ -+if config.host_os not in ['Linux']: -+ config.unsupported = True -Index: compiler-rt/test/crt/lit.site.cfg.in -=================================================================== ---- /dev/null -+++ compiler-rt/test/crt/lit.site.cfg.in -@@ -0,0 +1,14 @@ -+@LIT_SITE_CFG_IN_HEADER@ -+ -+# Tool-specific config options. -+config.name_suffix = "@CRT_TEST_CONFIG_SUFFIX@" -+config.crt_lit_source_dir = "@CRT_LIT_SOURCE_DIR@" -+config.target_cflags = "@CRT_TEST_TARGET_CFLAGS@" -+config.target_arch = "@CRT_TEST_TARGET_ARCH@" -+config.sanitizer_cxx_lib = "@SANITIZER_TEST_CXX_LIBNAME@" -+ -+# Load common config for all compiler-rt lit tests -+lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured") -+ -+# Load tool-specific config that would do the real work. -+lit_config.load_config(config, "@CRT_LIT_SOURCE_DIR@/lit.cfg") diff --git a/nix/llvm/default.nix b/nix/llvm/default.nix deleted file mode 100644 index b310c3937b5..00000000000 --- a/nix/llvm/default.nix +++ /dev/null @@ -1,198 +0,0 @@ -{ lowPrio, newScope, pkgs, stdenv, cmake, libstdcxxHook -, libxml2, python, isl, fetchsvn, overrideCC, wrapCCWith, wrapBintoolsWith -, buildLlvmTools # tools, but from the previous stage, for cross -, targetLlvmLibraries # libraries, but from the next stage, for cross -}: - -let - release_version = "9.0.0"; - version = release_version; # differentiating these is important for rc's - - fetch = name: sha256: fetchsvn { - url = "http://llvm.org/svn/llvm-project/${name}/trunk/"; - rev = "358327"; - inherit sha256; - }; - - clang-tools-extra_src = fetch "clang-tools-extra" "0gx7dbgjfnx3k06ggil782d6xbmj088yqd25sv05qri2d5j58k0x"; - - tools = stdenv.lib.makeExtensible (tools: let - callPackage = newScope (tools // { inherit stdenv cmake libxml2 python isl release_version version fetch; }); - mkExtraBuildCommands = cc: '' - rsrc="$out/resource-root" - mkdir "$rsrc" - ln -s "${cc}/lib/clang/${release_version}/include" "$rsrc" - ln -s "${targetLlvmLibraries.compiler-rt.out}/lib" "$rsrc/lib" - echo "-resource-dir=$rsrc" >> $out/nix-support/cc-cflags - '' + stdenv.lib.optionalString (stdenv.targetPlatform.isLinux && tools.clang-unwrapped ? gcc && !(stdenv.targetPlatform.useLLVM or false)) '' - echo "--gcc-toolchain=${tools.clang-unwrapped.gcc}" >> $out/nix-support/cc-cflags - ''; - in { - - llvm = callPackage ./llvm.nix { }; - llvm-polly = callPackage ./llvm.nix { enablePolly = true; }; - - clang-unwrapped = callPackage ./clang { - inherit clang-tools-extra_src; - }; - clang-polly-unwrapped = callPackage ./clang { - inherit clang-tools-extra_src; - llvm = tools.llvm-polly; - enablePolly = true; - }; - - llvm-manpages = lowPrio (tools.llvm.override { - enableManpages = true; - python = pkgs.python; # don't use python-boot - }); - - clang-manpages = lowPrio (tools.clang-unwrapped.override { - enableManpages = true; - python = pkgs.python; # don't use python-boot - }); - - libclang = tools.clang-unwrapped.lib; - - clang = if stdenv.cc.isGNU then tools.libstdcxxClang else tools.libcxxClang; - - libstdcxxClang = wrapCCWith rec { - cc = tools.clang-unwrapped; - extraPackages = [ - libstdcxxHook - targetLlvmLibraries.compiler-rt - ]; - extraBuildCommands = mkExtraBuildCommands cc; - }; - - libcxxClang = wrapCCWith rec { - cc = tools.clang-unwrapped; - libcxx = targetLlvmLibraries.libcxx; - extraPackages = [ - targetLlvmLibraries.libcxx - targetLlvmLibraries.libcxxabi - targetLlvmLibraries.compiler-rt - ]; - extraBuildCommands = mkExtraBuildCommands cc; - }; - - lld = callPackage ./lld.nix {}; - - lldb = callPackage ./lldb.nix {}; - - # Below, is the LLVM bootstrapping logic. It handles building a - # fully LLVM toolchain from scratch. No GCC toolchain should be - # pulled in. As a consequence, it is very quick to build different - # targets provided by LLVM and we can also build for what GCC - # doesn’t support like LLVM. Probably we should move to some other - # file. - - bintools = callPackage ./bintools.nix {}; - - lldClang = wrapCCWith rec { - cc = tools.clang-unwrapped; - libcxx = targetLlvmLibraries.libcxx; - bintools = wrapBintoolsWith { - inherit (tools) bintools; - }; - extraPackages = [ - targetLlvmLibraries.libcxx - targetLlvmLibraries.libcxxabi - targetLlvmLibraries.compiler-rt - ] ++ stdenv.lib.optionals (!stdenv.targetPlatform.isWasm) [ - targetLlvmLibraries.libunwind - ]; - extraBuildCommands = '' - echo "-target ${stdenv.targetPlatform.config}" >> $out/nix-support/cc-cflags - echo "-rtlib=compiler-rt -Wno-unused-command-line-argument" >> $out/nix-support/cc-cflags - echo "-B${targetLlvmLibraries.compiler-rt}/lib" >> $out/nix-support/cc-cflags - '' + stdenv.lib.optionalString (!stdenv.targetPlatform.isWasm) '' - echo "--unwindlib=libunwind" >> $out/nix-support/cc-cflags - '' + stdenv.lib.optionalString stdenv.targetPlatform.isWasm '' - echo "-fno-exceptions" >> $out/nix-support/cc-cflags - '' + mkExtraBuildCommands cc; - }; - - lldClangNoLibcxx = wrapCCWith rec { - cc = tools.clang-unwrapped; - libcxx = null; - bintools = wrapBintoolsWith { - inherit (tools) bintools; - }; - extraPackages = [ - targetLlvmLibraries.compiler-rt - ]; - extraBuildCommands = '' - echo "-target ${stdenv.targetPlatform.config}" >> $out/nix-support/cc-cflags - echo "-rtlib=compiler-rt" >> $out/nix-support/cc-cflags - echo "-B${targetLlvmLibraries.compiler-rt}/lib" >> $out/nix-support/cc-cflags - echo "-nostdlib++" >> $out/nix-support/cc-cflags - '' + mkExtraBuildCommands cc; - }; - - lldClangNoLibc = wrapCCWith rec { - cc = tools.clang-unwrapped; - libcxx = null; - bintools = wrapBintoolsWith { - inherit (tools) bintools; - libc = null; - }; - extraPackages = [ - targetLlvmLibraries.compiler-rt - ]; - extraBuildCommands = '' - echo "-target ${stdenv.targetPlatform.config}" >> $out/nix-support/cc-cflags - echo "-rtlib=compiler-rt" >> $out/nix-support/cc-cflags - echo "-B${targetLlvmLibraries.compiler-rt}/lib" >> $out/nix-support/cc-cflags - '' + mkExtraBuildCommands cc; - }; - - lldClangNoCompilerRt = wrapCCWith rec { - cc = tools.clang-unwrapped; - libcxx = null; - bintools = wrapBintoolsWith { - inherit (tools) bintools; - libc = null; - }; - extraPackages = [ ]; - extraBuildCommands = '' - echo "-nostartfiles" >> $out/nix-support/cc-cflags - echo "-target ${stdenv.targetPlatform.config}" >> $out/nix-support/cc-cflags - ''; - }; - - }); - - libraries = stdenv.lib.makeExtensible (libraries: let - callPackage = newScope (libraries // buildLlvmTools // { inherit stdenv cmake libxml2 python isl release_version version fetch; }); - in { - - compiler-rt = callPackage ./compiler-rt.nix ({} // - (stdenv.lib.optionalAttrs (stdenv.hostPlatform.useLLVM or false) { - stdenv = overrideCC stdenv buildLlvmTools.lldClangNoCompilerRt; - })); - - stdenv = overrideCC stdenv buildLlvmTools.clang; - - libcxxStdenv = overrideCC stdenv buildLlvmTools.libcxxClang; - - libcxx = callPackage ./libc++ ({} // - (stdenv.lib.optionalAttrs (stdenv.hostPlatform.useLLVM or false) { - stdenv = overrideCC stdenv buildLlvmTools.lldClangNoLibcxx; - })); - - libcxxabi = callPackage ./libc++abi.nix ({} // - (stdenv.lib.optionalAttrs (stdenv.hostPlatform.useLLVM or false) { - stdenv = overrideCC stdenv buildLlvmTools.lldClangNoLibcxx; - libunwind = libraries.libunwind; - })); - - openmp = callPackage ./openmp.nix {}; - - libunwind = callPackage ./libunwind.nix ({} // - (stdenv.lib.optionalAttrs (stdenv.hostPlatform.useLLVM or false) { - stdenv = overrideCC stdenv buildLlvmTools.lldClangNoLibcxx; - })); - - }); - -in { inherit tools libraries; } // libraries // tools diff --git a/nix/llvm/libc++/default.nix b/nix/llvm/libc++/default.nix deleted file mode 100644 index 77a7d62eefe..00000000000 --- a/nix/llvm/libc++/default.nix +++ /dev/null @@ -1,58 +0,0 @@ -{ lib, stdenv, fetch, cmake, python, libcxxabi, fixDarwinDylibNames, version -, enableShared ? true }: - -stdenv.mkDerivation rec { - name = "libc++-${version}"; - - src = fetch "libcxx" "1qlx3wlxrnc5cwc1fcfc2vhfsl7j4294hi8y5kxj8hy8wxsjd460"; - - postUnpack = '' - unpackFile ${libcxxabi.src} - export LIBCXXABI_INCLUDE_DIR="$PWD/$(ls -d libcxxabi-${version}*)/include" - ''; - - patches = stdenv.lib.optional stdenv.hostPlatform.isMusl ../../libcxx-0001-musl-hacks.patch; - - prePatch = '' - substituteInPlace lib/CMakeLists.txt --replace "/usr/lib/libc++" "\''${LIBCXX_LIBCXXABI_LIB_PATH}/libc++" - ''; - - preConfigure = '' - # Get headers from the cxxabi source so we can see private headers not installed by the cxxabi package - cmakeFlagsArray=($cmakeFlagsArray -DLIBCXX_CXX_ABI_INCLUDE_PATHS="$LIBCXXABI_INCLUDE_DIR") - '' + lib.optionalString stdenv.hostPlatform.isMusl '' - patchShebangs utils/cat_files.py - ''; - nativeBuildInputs = [ cmake ] - ++ stdenv.lib.optional (stdenv.hostPlatform.isMusl || stdenv.hostPlatform.isWasi) python; - - buildInputs = [ libcxxabi ] ++ lib.optional stdenv.isDarwin fixDarwinDylibNames; - - cmakeFlags = [ - "-DLIBCXX_LIBCXXABI_LIB_PATH=${libcxxabi}/lib" - "-DLIBCXX_LIBCPPABI_VERSION=2" - "-DLIBCXX_CXX_ABI=libcxxabi" - ] ++ stdenv.lib.optional (stdenv.hostPlatform.isMusl || stdenv.hostPlatform.isWasi) "-DLIBCXX_HAS_MUSL_LIBC=1" - ++ stdenv.lib.optional (stdenv.hostPlatform.useLLVM or false) "-DLIBCXX_USE_COMPILER_RT=ON" - ++ stdenv.lib.optional stdenv.hostPlatform.isWasm [ - "-DLIBCXX_ENABLE_THREADS=OFF" - "-DLIBCXX_ENABLE_FILESYSTEM=OFF" - "-DLIBCXX_ENABLE_EXCEPTIONS=OFF" - ] ++ stdenv.lib.optional (!enableShared) "-DLIBCXX_ENABLE_SHARED=OFF"; - - enableParallelBuilding = true; - - linkCxxAbi = stdenv.isLinux; - - setupHooks = [ - ../../../../../build-support/setup-hooks/role.bash - ./setup-hook.sh - ]; - - meta = { - homepage = http://libcxx.llvm.org/; - description = "A new implementation of the C++ standard library, targeting C++11"; - license = with stdenv.lib.licenses; [ ncsa mit ]; - platforms = stdenv.lib.platforms.all; - }; -} diff --git a/nix/llvm/libc++/setup-hook.sh b/nix/llvm/libc++/setup-hook.sh deleted file mode 100644 index 6611259165a..00000000000 --- a/nix/llvm/libc++/setup-hook.sh +++ /dev/null @@ -1,6 +0,0 @@ -# See pkgs/build-support/setup-hooks/role.bash -getHostRole - -linkCxxAbi="@linkCxxAbi@" -export NIX_${role_pre}CXXSTDLIB_COMPILE+=" -isystem @out@/include/c++/v1" -export NIX_${role_pre}CXXSTDLIB_LINK=" -stdlib=libc++${linkCxxAbi:+" -lc++abi"}" diff --git a/nix/llvm/libc++abi.nix b/nix/llvm/libc++abi.nix deleted file mode 100644 index 4ac739a1fb6..00000000000 --- a/nix/llvm/libc++abi.nix +++ /dev/null @@ -1,66 +0,0 @@ -{ stdenv, cmake, fetch, libcxx, libunwind, llvm, version -, enableShared ? true }: - -stdenv.mkDerivation { - name = "libc++abi-${version}"; - - src = fetch "libcxxabi" "1k875f977ybdkpdnr9105wa6hccy9qvpd9xd42n75h7p56bdxmn0"; - - nativeBuildInputs = [ cmake ]; - buildInputs = stdenv.lib.optional (!stdenv.isDarwin && !stdenv.isFreeBSD && !stdenv.hostPlatform.isWasm) libunwind; - - cmakeFlags = stdenv.lib.optionals (stdenv.hostPlatform.useLLVM or false) [ - "-DLLVM_ENABLE_LIBCXX=ON" - "-DLIBCXXABI_USE_LLVM_UNWINDER=ON" - ] ++ stdenv.lib.optionals stdenv.hostPlatform.isWasm [ - "-DLIBCXXABI_ENABLE_THREADS=OFF" - "-DLIBCXXABI_ENABLE_EXCEPTIONS=OFF" - ] ++ stdenv.lib.optionals (!enableShared) [ - "-DLIBCXXABI_ENABLE_SHARED=OFF" - ]; - - patches = [ ./libcxxabi-no-threads.patch ]; - - postUnpack = '' - unpackFile ${libcxx.src} - unpackFile ${llvm.src} - cmakeFlags+=" -DLLVM_PATH=$PWD/$(ls -d llvm-*) -DLIBCXXABI_LIBCXX_PATH=$PWD/$(ls -d libcxx-*)" - '' + stdenv.lib.optionalString stdenv.isDarwin '' - export TRIPLE=x86_64-apple-darwin - '' + stdenv.lib.optionalString stdenv.hostPlatform.isMusl '' - patch -p1 -d $(ls -d libcxx-*) -i ${../libcxx-0001-musl-hacks.patch} - '' + stdenv.lib.optionalString stdenv.hostPlatform.isWasm '' - patch -p1 -d $(ls -d llvm-*) -i ${./libcxxabi-wasm.patch} - ''; - - installPhase = if stdenv.isDarwin - then '' - for file in lib/*.dylib; do - # this should be done in CMake, but having trouble figuring out - # the magic combination of necessary CMake variables - # if you fancy a try, take a look at - # http://www.cmake.org/Wiki/CMake_RPATH_handling - install_name_tool -id $out/$file $file - done - make install - install -d 755 $out/include - install -m 644 ../include/*.h $out/include - '' - else '' - install -d -m 755 $out/include $out/lib - install -m 644 lib/libc++abi.a $out/lib - install -m 644 ../include/cxxabi.h $out/include - '' + stdenv.lib.optionalString enableShared '' - install -m 644 lib/libc++abi.so.1.0 $out/lib - ln -s libc++abi.so.1.0 $out/lib/libc++abi.so - ln -s libc++abi.so.1.0 $out/lib/libc++abi.so.1 - ''; - - meta = { - homepage = http://libcxxabi.llvm.org/; - description = "A new implementation of low level support for a standard C++ library"; - license = with stdenv.lib.licenses; [ ncsa mit ]; - maintainers = with stdenv.lib.maintainers; [ vlstill ]; - platforms = stdenv.lib.platforms.all; - }; -} diff --git a/nix/llvm/libcxxabi-no-threads.patch b/nix/llvm/libcxxabi-no-threads.patch deleted file mode 100644 index 787f3e16500..00000000000 --- a/nix/llvm/libcxxabi-no-threads.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/CMakeLists.txt b/CMakeLists.txt -index 4138acf..41b4763 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -362,6 +362,7 @@ if (NOT LIBCXXABI_ENABLE_THREADS) - " is also set to ON.") - endif() - add_definitions(-D_LIBCXXABI_HAS_NO_THREADS) -+ add_definitions(-D_LIBCPP_HAS_NO_THREADS) - endif() - - if (LIBCXXABI_HAS_EXTERNAL_THREAD_API) diff --git a/nix/llvm/libcxxabi-wasm.patch b/nix/llvm/libcxxabi-wasm.patch deleted file mode 100644 index 4ebfe46aa81..00000000000 --- a/nix/llvm/libcxxabi-wasm.patch +++ /dev/null @@ -1,16 +0,0 @@ -diff --git a/cmake/modules/HandleLLVMOptions.cmake b/cmake/modules/HandleLLVMOptions.cmake -index 15497d405e0..33f7f18193a 100644 ---- a/cmake/modules/HandleLLVMOptions.cmake -+++ b/cmake/modules/HandleLLVMOptions.cmake -@@ -127,7 +127,10 @@ else(WIN32) - set(LLVM_HAVE_LINK_VERSION_SCRIPT 1) - endif() - else(FUCHSIA OR UNIX) -- MESSAGE(SEND_ERROR "Unable to determine platform") -+ if(${CMAKE_SYSTEM_NAME} MATCHES "Wasi") -+ else() -+ MESSAGE(SEND_ERROR "Unable to determine platform") -+ endif() - endif(FUCHSIA OR UNIX) - endif(WIN32) - diff --git a/nix/llvm/libunwind.nix b/nix/llvm/libunwind.nix deleted file mode 100644 index a187d0adc99..00000000000 --- a/nix/llvm/libunwind.nix +++ /dev/null @@ -1,22 +0,0 @@ -{ stdenv, version, fetch, cmake, libcxx, fetchpatch }: - -stdenv.mkDerivation { - name = "libunwind-${version}"; - - src = fetch "libunwind" "0q7ndlldid9wchnny0a936llwxj7zgb9gxp46wjjxvwwkik3l97z"; - - nativeBuildInputs = [ cmake ]; - - patches = [ - (fetchpatch { - url = "https://github.com/llvm-mirror/libunwind/commit/34a45c630d4c79af403661d267db42fbe7de1178.patch"; - sha256 = "0n0pv6jvcky8pn3srhrf9x5kbnd0d2kia9xlx2g590f5q0bgwfhv"; - }) - (fetchpatch { - url = "https://github.com/llvm-mirror/libunwind/commit/e050272d2eb57eb4e56a37b429a61df2ebb8aa3e.patch"; - sha256 = "1sxyx5xnax8k713jjcxgq3jq3cpnxygs2rcdf5vfja0f2k9jzldl"; - }) - ]; - - enableParallelBuilding = true; -} diff --git a/nix/llvm/lld.nix b/nix/llvm/lld.nix deleted file mode 100644 index 31921266fd7..00000000000 --- a/nix/llvm/lld.nix +++ /dev/null @@ -1,32 +0,0 @@ -{ stdenv -, fetch -, cmake -, libxml2 -, llvm -, version -}: - -stdenv.mkDerivation { - name = "lld-${version}"; - - src = fetch "lld" "0ajal35y7kdrwccb4ynrfhdp32rfcsd3nlaf22iz8r2yr83jl0wg"; - - nativeBuildInputs = [ cmake ]; - buildInputs = [ llvm libxml2 ]; - - outputs = [ "out" "dev" ]; - - enableParallelBuilding = true; - - postInstall = '' - moveToOutput include "$dev" - moveToOutput lib "$dev" - ''; - - meta = { - description = "The LLVM Linker"; - homepage = http://lld.llvm.org/; - license = stdenv.lib.licenses.ncsa; - platforms = stdenv.lib.platforms.all; - }; -} diff --git a/nix/llvm/lldb.nix b/nix/llvm/lldb.nix deleted file mode 100644 index d95d902743b..00000000000 --- a/nix/llvm/lldb.nix +++ /dev/null @@ -1,60 +0,0 @@ -{ stdenv -, fetch -, cmake -, zlib -, ncurses -, swig -, which -, libedit -, libxml2 -, llvm -, clang-unwrapped -, python -, version -, darwin -}: - -stdenv.mkDerivation { - name = "lldb-${version}"; - - src = fetch "lldb" "0wq3mi76fk86g2g2bcsr0yhagh1dlf2myk641ai58rc116gqp4a0"; - - postPatch = '' - # Fix up various paths that assume llvm and clang are installed in the same place - sed -i 's,".*ClangConfig.cmake","${clang-unwrapped}/lib/cmake/clang/ClangConfig.cmake",' \ - cmake/modules/LLDBStandalone.cmake - sed -i 's,".*tools/clang/include","${clang-unwrapped}/include",' \ - cmake/modules/LLDBStandalone.cmake - sed -i 's,"$.LLVM_LIBRARY_DIR.",${llvm}/lib ${clang-unwrapped}/lib,' \ - cmake/modules/LLDBStandalone.cmake - ''; - - nativeBuildInputs = [ cmake python which swig ]; - buildInputs = [ ncurses zlib libedit libxml2 llvm ] - ++ stdenv.lib.optionals stdenv.isDarwin [ darwin.libobjc darwin.apple_sdk.libs.xpc darwin.apple_sdk.frameworks.Foundation darwin.bootstrap_cmds darwin.apple_sdk.frameworks.Carbon darwin.apple_sdk.frameworks.Cocoa darwin.cf-private ]; - - CXXFLAGS = "-fno-rtti"; - hardeningDisable = [ "format" ]; - - cmakeFlags = [ - "-DLLDB_CODESIGN_IDENTITY=" # codesigning makes nondeterministic - ]; - - enableParallelBuilding = true; - - postInstall = '' - mkdir -p $out/share/man/man1 - cp ../docs/lldb.1 $out/share/man/man1/ - - install -D ../tools/lldb-vscode/package.json $out/share/vscode/extensions/llvm-org.lldb-vscode-0.1.0/package.json - mkdir $out/share/vscode/extensions/llvm-org.lldb-vscode-0.1.0/bin - ln -s $out/bin/lldb-vscode $out/share/vscode/extensions/llvm-org.lldb-vscode-0.1.0/bin - ''; - - meta = with stdenv.lib; { - description = "A next-generation high-performance debugger"; - homepage = http://llvm.org/; - license = licenses.ncsa; - platforms = platforms.all; - }; -} diff --git a/nix/llvm/llvm-outputs.patch b/nix/llvm/llvm-outputs.patch deleted file mode 100644 index 40096fa3497..00000000000 --- a/nix/llvm/llvm-outputs.patch +++ /dev/null @@ -1,26 +0,0 @@ -diff --git a/tools/llvm-config/llvm-config.cpp b/tools/llvm-config/llvm-config.cpp -index 94d426b..37f7794 100644 ---- a/tools/llvm-config/llvm-config.cpp -+++ b/tools/llvm-config/llvm-config.cpp -@@ -333,6 +333,21 @@ int main(int argc, char **argv) { - ActiveIncludeOption = "-I" + ActiveIncludeDir; - } - -+ /// Nix-specific multiple-output handling: override ActiveLibDir if --link-shared -+ if (!IsInDevelopmentTree) { -+ bool WantShared = true; -+ for (int i = 1; i < argc; ++i) { -+ StringRef Arg = argv[i]; -+ if (Arg == "--link-shared") -+ WantShared = true; -+ else if (Arg == "--link-static") -+ WantShared = false; // the last one wins -+ } -+ -+ if (WantShared) -+ ActiveLibDir = std::string("@lib@") + "/lib" + LLVM_LIBDIR_SUFFIX; -+ } -+ - /// We only use `shared library` mode in cases where the static library form - /// of the components provided are not available; note however that this is - /// skipped if we're run from within the build dir. However, once installed, diff --git a/nix/llvm/llvm.nix b/nix/llvm/llvm.nix deleted file mode 100644 index 584cf9b5eb8..00000000000 --- a/nix/llvm/llvm.nix +++ /dev/null @@ -1,175 +0,0 @@ -{ stdenv -, fetch -, fetchpatch -, cmake -, python -, libffi -, libbfd -, libpfm -, libxml2 -, ncurses -, version -, release_version -, zlib -, buildPackages -, debugVersion ? false -, enableManpages ? false -, enableSharedLibraries ? true -, enablePFM ? !stdenv.isDarwin -, enablePolly ? false -}: - -let - inherit (stdenv.lib) optional optionals optionalString; - - src = fetch "llvm" "180msa40issz6cljrclg7c2934az450gbsar72j174jc55l8h77i"; - polly_src = fetch "polly" "1x4xv3j226rqdddp7b61d71wsx2b8vmmri02ycx27y2fg7ba7xg0"; - - # Used when creating a version-suffixed symlink of libLLVM.dylib - shortVersion = with stdenv.lib; - concatStringsSep "." (take 1 (splitString "." release_version)); - -in stdenv.mkDerivation (rec { - name = "llvm-${version}"; - - unpackPhase = '' - unpackFile ${src} - chmod -R u+w llvm-r* - mv llvm-r* llvm - sourceRoot=$PWD/llvm - '' + optionalString enablePolly '' - unpackFile ${polly_src} - mv polly-* $sourceRoot/tools/polly - ''; - - outputs = [ "out" "python" ] - ++ optional enableSharedLibraries "lib"; - - nativeBuildInputs = [ cmake python ] - ++ optionals enableManpages [ python.pkgs.sphinx python.pkgs.recommonmark ]; - - buildInputs = [ libxml2 libffi ] - ++ optional enablePFM libpfm; # exegesis - - propagatedBuildInputs = [ ncurses zlib ]; - - postPatch = optionalString stdenv.isDarwin '' - substituteInPlace cmake/modules/AddLLVM.cmake \ - --replace 'set(_install_name_dir INSTALL_NAME_DIR "@rpath")' "set(_install_name_dir)" \ - --replace 'set(_install_rpath "@loader_path/../lib" ''${extra_libdir})' "" - '' - # Patch llvm-config to return correct library path based on --link-{shared,static}. - + optionalString (enableSharedLibraries) '' - substitute '${./llvm-outputs.patch}' ./llvm-outputs.patch --subst-var lib - patch -p1 < ./llvm-outputs.patch - '' + '' - # FileSystem permissions tests fail with various special bits - substituteInPlace unittests/Support/CMakeLists.txt \ - --replace "Path.cpp" "" - rm unittests/Support/Path.cpp - '' + optionalString stdenv.hostPlatform.isMusl '' - patch -p1 -i ${../TLI-musl.patch} - substituteInPlace unittests/Support/CMakeLists.txt \ - --replace "add_subdirectory(DynamicLibrary)" "" - rm unittests/Support/DynamicLibrary/DynamicLibraryTest.cpp - # valgrind unhappy with musl or glibc, but fails w/musl only - rm test/CodeGen/AArch64/wineh4.mir - '' + '' - patchShebangs test/BugPoint/compile-custom.ll.py - ''; - - # hacky fix: created binaries need to be run before installation - preBuild = '' - mkdir -p $out/ - ln -sv $PWD/lib $out - ''; - - cmakeFlags = with stdenv; [ - "-DCMAKE_BUILD_TYPE=${if debugVersion then "Debug" else "Release"}" - "-DLLVM_INSTALL_UTILS=ON" # Needed by rustc - "-DLLVM_BUILD_TESTS=ON" - "-DLLVM_ENABLE_FFI=ON" - "-DLLVM_ENABLE_RTTI=ON" - "-DLLVM_HOST_TRIPLE=${stdenv.hostPlatform.config}" - "-DLLVM_DEFAULT_TARGET_TRIPLE=${stdenv.hostPlatform.config}" - "-DLLVM_ENABLE_DUMP=ON" - ] ++ optionals enableSharedLibraries [ - "-DLLVM_LINK_LLVM_DYLIB=ON" - ] ++ optionals enableManpages [ - "-DLLVM_BUILD_DOCS=ON" - "-DLLVM_ENABLE_SPHINX=ON" - "-DSPHINX_OUTPUT_MAN=ON" - "-DSPHINX_OUTPUT_HTML=OFF" - "-DSPHINX_WARNINGS_AS_ERRORS=OFF" - ] ++ optionals (!isDarwin) [ - "-DLLVM_BINUTILS_INCDIR=${libbfd.dev}/include" - ] ++ optionals (isDarwin) [ - "-DLLVM_ENABLE_LIBCXX=ON" - "-DCAN_TARGET_i386=false" - ] ++ optionals (stdenv.hostPlatform != stdenv.buildPlatform) [ - "-DCMAKE_CROSSCOMPILING=True" - "-DLLVM_TABLEGEN=${buildPackages.llvm_7}/bin/llvm-tblgen" - ]; - - postBuild = '' - rm -fR $out - ''; - - preCheck = '' - export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/lib - ''; - - postInstall = '' - mkdir -p $python/share - mv $out/share/opt-viewer $python/share/opt-viewer - '' - + optionalString enableSharedLibraries '' - moveToOutput "lib/libLLVM-*" "$lib" - moveToOutput "lib/libLLVM${stdenv.hostPlatform.extensions.sharedLibrary}" "$lib" - substituteInPlace "$out/lib/cmake/llvm/LLVMExports-${if debugVersion then "debug" else "release"}.cmake" \ - --replace "\''${_IMPORT_PREFIX}/lib/libLLVM-" "$lib/lib/libLLVM-" - '' - + optionalString (stdenv.isDarwin && enableSharedLibraries) '' - substituteInPlace "$out/lib/cmake/llvm/LLVMExports-${if debugVersion then "debug" else "release"}.cmake" \ - --replace "\''${_IMPORT_PREFIX}/lib/libLLVM.dylib" "$lib/lib/libLLVM.dylib" - ln -s $lib/lib/libLLVM.dylib $lib/lib/libLLVM-${shortVersion}.dylib - ln -s $lib/lib/libLLVM.dylib $lib/lib/libLLVM-${release_version}.dylib - ''; - - doCheck = stdenv.isLinux && (!stdenv.isx86_32); - - checkTarget = "check-all"; - - enableParallelBuilding = true; - - passthru.src = src; - - meta = { - description = "Collection of modular and reusable compiler and toolchain technologies"; - homepage = http://llvm.org/; - license = stdenv.lib.licenses.ncsa; - maintainers = with stdenv.lib.maintainers; [ lovek323 raskin dtzWill ]; - platforms = stdenv.lib.platforms.all; - }; -} // stdenv.lib.optionalAttrs enableManpages { - name = "llvm-manpages-${version}"; - - buildPhase = '' - make docs-llvm-man - ''; - - propagatedBuildInputs = []; - - installPhase = '' - make -C docs install - ''; - - postPatch = null; - postInstall = null; - - outputs = [ "out" ]; - - doCheck = false; - - meta.description = "man pages for LLVM ${version}"; -}) diff --git a/nix/llvm/openmp.nix b/nix/llvm/openmp.nix deleted file mode 100644 index b7f242e43a3..00000000000 --- a/nix/llvm/openmp.nix +++ /dev/null @@ -1,25 +0,0 @@ -{ stdenv -, fetch -, cmake -, llvm -, perl -, version -}: - -stdenv.mkDerivation { - name = "openmp-${version}"; - - src = fetch "openmp" "1mf9cpgvix34xlpv0inkgl3qmdvgvp96f7sksqizri0n5xfp1cg0"; - - nativeBuildInputs = [ cmake perl ]; - buildInputs = [ llvm ]; - - enableParallelBuilding = true; - - meta = { - description = "Components required to build an executable OpenMP program"; - homepage = http://openmp.llvm.org/; - license = stdenv.lib.licenses.mit; - platforms = stdenv.lib.platforms.all; - }; -} diff --git a/nix/llvm/sanitizers-nongnu.patch b/nix/llvm/sanitizers-nongnu.patch deleted file mode 100644 index 1f2ac97818e..00000000000 --- a/nix/llvm/sanitizers-nongnu.patch +++ /dev/null @@ -1,412 +0,0 @@ -From f7a253f8f85d0f49df6b73996737a3e84ac64236 Mon Sep 17 00:00:00 2001 -From: Will Dietz -Date: Mon, 24 Sep 2018 11:17:25 -0500 -Subject: [PATCH] Ported to 7.0, taken from gentoo-musl project. - ------- -Ported to compiler-rt-sanitizers-5.0.0. Taken from - -https://gist.githubusercontent.com/pwaller/2337f3290f12634cad3e3730cff0a6c1/raw/83c87a8585e2f9662494db5662e5361beb093c26/nongnu.patch -Signed-off-by: Jory A. Pratt - -Taken from gentoo-musl project, with a few additional minor fixes. ---- - lib/asan/asan_linux.cc | 4 +- - lib/interception/interception_linux.cc | 2 +- - lib/interception/interception_linux.h | 2 +- - lib/msan/msan_linux.cc | 2 +- - lib/sanitizer_common/sanitizer_allocator.cc | 2 +- - .../sanitizer_common_interceptors_ioctl.inc | 4 +- - .../sanitizer_common_syscalls.inc | 2 +- - lib/sanitizer_common/sanitizer_linux.cc | 8 +++- - .../sanitizer_linux_libcdep.cc | 10 ++--- - lib/sanitizer_common/sanitizer_platform.h | 6 +++ - .../sanitizer_platform_interceptors.h | 4 +- - .../sanitizer_platform_limits_posix.cc | 37 +++++++++++-------- - lib/tsan/rtl/tsan_platform_linux.cc | 2 +- - 13 files changed, 51 insertions(+), 34 deletions(-) - -diff --git a/lib/asan/asan_linux.cc b/lib/asan/asan_linux.cc -index 625f32d40..73cf77aca 100644 ---- a/lib/asan/asan_linux.cc -+++ b/lib/asan/asan_linux.cc -@@ -46,7 +46,7 @@ - #include - #endif - --#if SANITIZER_ANDROID || SANITIZER_FREEBSD || SANITIZER_SOLARIS -+#if SANITIZER_ANDROID || SANITIZER_FREEBSD || SANITIZER_SOLARIS || SANITIZER_NONGNU - #include - extern "C" void* _DYNAMIC; - #elif SANITIZER_NETBSD -@@ -139,7 +139,7 @@ void AsanApplyToGlobals(globals_op_fptr op, const void *needle) { - UNIMPLEMENTED(); - } - --#if SANITIZER_ANDROID -+#if SANITIZER_ANDROID || SANITIZER_NONGNU - // FIXME: should we do anything for Android? - void AsanCheckDynamicRTPrereqs() {} - void AsanCheckIncompatibleRT() {} -diff --git a/lib/interception/interception_linux.cc b/lib/interception/interception_linux.cc -index 26bfcd8f6..529b234f7 100644 ---- a/lib/interception/interception_linux.cc -+++ b/lib/interception/interception_linux.cc -@@ -43,7 +43,7 @@ bool GetRealFunctionAddress(const char *func_name, uptr *func_addr, - } - - // Android and Solaris do not have dlvsym --#if !SANITIZER_ANDROID && !SANITIZER_SOLARIS && !SANITIZER_OPENBSD -+#if !SANITIZER_ANDROID && !SANITIZER_SOLARIS && !SANITIZER_OPENBSD && !SANITIZER_NONGNU - void *GetFuncAddrVer(const char *func_name, const char *ver) { - return dlvsym(RTLD_NEXT, func_name, ver); - } -diff --git a/lib/interception/interception_linux.h b/lib/interception/interception_linux.h -index 942c25609..24a4d5080 100644 ---- a/lib/interception/interception_linux.h -+++ b/lib/interception/interception_linux.h -@@ -36,7 +36,7 @@ void *GetFuncAddrVer(const char *func_name, const char *ver); - (::__interception::uptr) & WRAP(func)) - - // Android, Solaris and OpenBSD do not have dlvsym --#if !SANITIZER_ANDROID && !SANITIZER_SOLARIS && !SANITIZER_OPENBSD -+#if !SANITIZER_ANDROID && !SANITIZER_SOLARIS && !SANITIZER_OPENBSD && !SANITIZER_NONGNU - #define INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver) \ - (::__interception::real_##func = (func##_f)( \ - unsigned long)::__interception::GetFuncAddrVer(#func, symver)) -diff --git a/lib/msan/msan_linux.cc b/lib/msan/msan_linux.cc -index 385a650c4..6e30a8ce9 100644 ---- a/lib/msan/msan_linux.cc -+++ b/lib/msan/msan_linux.cc -@@ -13,7 +13,7 @@ - //===----------------------------------------------------------------------===// - - #include "sanitizer_common/sanitizer_platform.h" --#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD -+#if SANITIZER_FREEBSD || (SANITIZER_LINUX && !SANITIZER_NONGNU) || SANITIZER_NETBSD - - #include "msan.h" - #include "msan_report.h" -diff --git a/lib/sanitizer_common/sanitizer_allocator.cc b/lib/sanitizer_common/sanitizer_allocator.cc -index 6bfd5e5ee..048f6154f 100644 ---- a/lib/sanitizer_common/sanitizer_allocator.cc -+++ b/lib/sanitizer_common/sanitizer_allocator.cc -@@ -27,7 +27,7 @@ const char *SecondaryAllocatorName = "LargeMmapAllocator"; - - // ThreadSanitizer for Go uses libc malloc/free. - #if SANITIZER_GO || defined(SANITIZER_USE_MALLOC) --# if SANITIZER_LINUX && !SANITIZER_ANDROID -+# if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_NONGNU - extern "C" void *__libc_malloc(uptr size); - # if !SANITIZER_GO - extern "C" void *__libc_memalign(uptr alignment, uptr size); -diff --git a/lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc b/lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc -index 2d633c173..b6eb23116 100644 ---- a/lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc -+++ b/lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc -@@ -104,7 +104,7 @@ static void ioctl_table_fill() { - _(SIOCGETVIFCNT, WRITE, struct_sioc_vif_req_sz); - #endif - --#if SANITIZER_LINUX -+#if SANITIZER_LINUX && !SANITIZER_NONGNU - // Conflicting request ids. - // _(CDROMAUDIOBUFSIZ, NONE, 0); - // _(SNDCTL_TMR_CONTINUE, NONE, 0); -@@ -365,7 +365,7 @@ static void ioctl_table_fill() { - _(VT_WAITACTIVE, NONE, 0); - #endif - --#if SANITIZER_LINUX && !SANITIZER_ANDROID -+#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_NONGNU - // _(SIOCDEVPLIP, WRITE, struct_ifreq_sz); // the same as EQL_ENSLAVE - _(CYGETDEFTHRESH, WRITE, sizeof(int)); - _(CYGETDEFTIMEOUT, WRITE, sizeof(int)); -diff --git a/lib/sanitizer_common/sanitizer_common_syscalls.inc b/lib/sanitizer_common/sanitizer_common_syscalls.inc -index 469c8eb7e..24f87867d 100644 ---- a/lib/sanitizer_common/sanitizer_common_syscalls.inc -+++ b/lib/sanitizer_common/sanitizer_common_syscalls.inc -@@ -2038,7 +2038,7 @@ POST_SYSCALL(setrlimit)(long res, long resource, void *rlim) { - } - } - --#if !SANITIZER_ANDROID -+#if !SANITIZER_ANDROID && !SANITIZER_NONGNU - PRE_SYSCALL(prlimit64)(long pid, long resource, const void *new_rlim, - void *old_rlim) { - if (new_rlim) PRE_READ(new_rlim, struct_rlimit64_sz); -diff --git a/lib/sanitizer_common/sanitizer_linux.cc b/lib/sanitizer_common/sanitizer_linux.cc -index 96d6c1eff..9e2b7fb9d 100644 ---- a/lib/sanitizer_common/sanitizer_linux.cc -+++ b/lib/sanitizer_common/sanitizer_linux.cc -@@ -541,13 +541,13 @@ const char *GetEnv(const char *name) { - #endif - } - --#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD && !SANITIZER_OPENBSD -+#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD && !SANITIZER_OPENBSD && !SANITIZER_NONGNU - extern "C" { - SANITIZER_WEAK_ATTRIBUTE extern void *__libc_stack_end; - } - #endif - --#if !SANITIZER_GO && !SANITIZER_FREEBSD && !SANITIZER_NETBSD && \ -+#if (!SANITIZER_GO || SANITIZER_NONGNU) && !SANITIZER_FREEBSD && !SANITIZER_NETBSD && \ - !SANITIZER_OPENBSD - static void ReadNullSepFileToArray(const char *path, char ***arr, - int arr_size) { -@@ -590,6 +590,10 @@ static void GetArgsAndEnv(char ***argv, char ***envp) { - #elif SANITIZER_NETBSD - *argv = __ps_strings->ps_argvstr; - *envp = __ps_strings->ps_envstr; -+#elif SANITIZER_NONGNU -+ static const int kMaxArgv = 2000, kMaxEnvp = 2000; -+ ReadNullSepFileToArray("/proc/self/cmdline", argv, kMaxArgv); -+ ReadNullSepFileToArray("/proc/self/environ", envp, kMaxEnvp); - #else // SANITIZER_FREEBSD - #if !SANITIZER_GO - if (&__libc_stack_end) { -diff --git a/lib/sanitizer_common/sanitizer_linux_libcdep.cc b/lib/sanitizer_common/sanitizer_linux_libcdep.cc -index 4962ff832..438f94dbe 100644 ---- a/lib/sanitizer_common/sanitizer_linux_libcdep.cc -+++ b/lib/sanitizer_common/sanitizer_linux_libcdep.cc -@@ -179,7 +179,7 @@ __attribute__((unused)) static bool GetLibcVersion(int *major, int *minor, - } - - #if !SANITIZER_FREEBSD && !SANITIZER_ANDROID && !SANITIZER_GO && \ -- !SANITIZER_NETBSD && !SANITIZER_OPENBSD && !SANITIZER_SOLARIS -+ !SANITIZER_NETBSD && !SANITIZER_OPENBSD && !SANITIZER_SOLARIS && !SANITIZER_NONGNU - static uptr g_tls_size; - - #ifdef __i386__ -@@ -261,7 +261,7 @@ void InitTlsSize() { } - #if (defined(__x86_64__) || defined(__i386__) || defined(__mips__) || \ - defined(__aarch64__) || defined(__powerpc64__) || defined(__s390__) || \ - defined(__arm__)) && \ -- SANITIZER_LINUX && !SANITIZER_ANDROID -+ SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_NONGNU - // sizeof(struct pthread) from glibc. - static atomic_uintptr_t thread_descriptor_size; - -@@ -426,7 +426,7 @@ int GetSizeFromHdr(struct dl_phdr_info *info, size_t size, void *data) { - - #if !SANITIZER_GO - static void GetTls(uptr *addr, uptr *size) { --#if SANITIZER_LINUX && !SANITIZER_ANDROID -+#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_NONGNU - # if defined(__x86_64__) || defined(__i386__) || defined(__s390__) - *addr = ThreadSelf(); - *size = GetTlsSize(); -@@ -470,7 +470,7 @@ static void GetTls(uptr *addr, uptr *size) { - #elif SANITIZER_OPENBSD - *addr = 0; - *size = 0; --#elif SANITIZER_ANDROID -+#elif SANITIZER_ANDROID || SANITIZER_NONGNU - *addr = 0; - *size = 0; - #elif SANITIZER_SOLARIS -@@ -486,7 +486,7 @@ static void GetTls(uptr *addr, uptr *size) { - #if !SANITIZER_GO - uptr GetTlsSize() { - #if SANITIZER_FREEBSD || SANITIZER_ANDROID || SANITIZER_NETBSD || \ -- SANITIZER_OPENBSD || SANITIZER_SOLARIS -+ SANITIZER_OPENBSD || SANITIZER_SOLARIS || SANITIZER_NONGNU - uptr addr, size; - GetTls(&addr, &size); - return size; -diff --git a/lib/sanitizer_common/sanitizer_platform.h b/lib/sanitizer_common/sanitizer_platform.h -index d81e25580..e10680ac8 100644 ---- a/lib/sanitizer_common/sanitizer_platform.h -+++ b/lib/sanitizer_common/sanitizer_platform.h -@@ -208,6 +208,12 @@ - # define SANITIZER_SOLARIS32 0 - #endif - -+#if defined(__linux__) && !defined(__GLIBC__) -+# define SANITIZER_NONGNU 1 -+#else -+# define SANITIZER_NONGNU 0 -+#endif -+ - #if defined(__myriad2__) - # define SANITIZER_MYRIAD2 1 - #else -diff --git a/lib/sanitizer_common/sanitizer_platform_interceptors.h b/lib/sanitizer_common/sanitizer_platform_interceptors.h -index f95539a73..6c53b3415 100644 ---- a/lib/sanitizer_common/sanitizer_platform_interceptors.h -+++ b/lib/sanitizer_common/sanitizer_platform_interceptors.h -@@ -39,7 +39,7 @@ - # include "sanitizer_platform_limits_solaris.h" - #endif - --#if SANITIZER_LINUX && !SANITIZER_ANDROID -+#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_NONGNU - # define SI_LINUX_NOT_ANDROID 1 - #else - # define SI_LINUX_NOT_ANDROID 0 -@@ -322,7 +322,7 @@ - #define SANITIZER_INTERCEPT_ETHER_R (SI_FREEBSD || SI_LINUX_NOT_ANDROID) - #define SANITIZER_INTERCEPT_SHMCTL \ - (SI_NETBSD || SI_OPENBSD || SI_SOLARIS || \ -- ((SI_FREEBSD || SI_LINUX_NOT_ANDROID) && \ -+ ((SI_FREEBSD || SI_LINUX_NOT_ANDROID || SANITIZER_NONGNU) && \ - SANITIZER_WORDSIZE == 64)) // NOLINT - #define SANITIZER_INTERCEPT_RANDOM_R SI_LINUX_NOT_ANDROID - #define SANITIZER_INTERCEPT_PTHREAD_ATTR_GET SI_POSIX -diff --git a/lib/sanitizer_common/sanitizer_platform_limits_posix.cc b/lib/sanitizer_common/sanitizer_platform_limits_posix.cc -index 54da635d7..2f6ff69c3 100644 ---- a/lib/sanitizer_common/sanitizer_platform_limits_posix.cc -+++ b/lib/sanitizer_common/sanitizer_platform_limits_posix.cc -@@ -14,6 +14,9 @@ - - #include "sanitizer_platform.h" - -+// Workaround musl <--> linux conflicting definition of 'struct sysinfo' -+#define _LINUX_SYSINFO_H -+ - #if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_MAC - // Tests in this file assume that off_t-dependent data structures match the - // libc ABI. For example, struct dirent here is what readdir() function (as -@@ -138,12 +141,14 @@ typedef struct user_fpregs elf_fpregset_t; - - #if SANITIZER_LINUX && !SANITIZER_ANDROID - #include --#include -+# if !SANITIZER_NONGNU -+# include -+# endif - #include --#include --#include --#include --#include -+#include -+#include -+#include -+#include - #if HAVE_RPC_XDR_H - # include - #elif HAVE_TIRPC_RPC_XDR_H -@@ -251,7 +256,7 @@ namespace __sanitizer { - unsigned struct_itimerspec_sz = sizeof(struct itimerspec); - #endif // SANITIZER_LINUX || SANITIZER_FREEBSD - --#if SANITIZER_LINUX && !SANITIZER_ANDROID -+#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_NONGNU - // Use pre-computed size of struct ustat to avoid which - // has been removed from glibc 2.28. - #if defined(__aarch64__) || defined(__s390x__) || defined (__mips64) \ -@@ -322,7 +327,7 @@ unsigned struct_ElfW_Phdr_sz = sizeof(ElfW(Phdr)); - unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); - #endif - --#if (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID -+#if (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID && !SANITIZER_NONGNU - int glob_nomatch = GLOB_NOMATCH; - int glob_altdirfunc = GLOB_ALTDIRFUNC; - #endif -@@ -416,7 +421,7 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); - unsigned struct_termios_sz = sizeof(struct termios); - unsigned struct_winsize_sz = sizeof(struct winsize); - --#if SANITIZER_LINUX -+#if SANITIZER_LINUX && !SANITIZER_NONGNU - unsigned struct_arpreq_sz = sizeof(struct arpreq); - unsigned struct_cdrom_msf_sz = sizeof(struct cdrom_msf); - unsigned struct_cdrom_multisession_sz = sizeof(struct cdrom_multisession); -@@ -466,7 +471,7 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); - unsigned struct_vt_mode_sz = sizeof(struct vt_mode); - #endif // SANITIZER_LINUX || SANITIZER_FREEBSD - --#if SANITIZER_LINUX && !SANITIZER_ANDROID -+#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_NONGNU - unsigned struct_ax25_parms_struct_sz = sizeof(struct ax25_parms_struct); - unsigned struct_cyclades_monitor_sz = sizeof(struct cyclades_monitor); - #if EV_VERSION > (0x010000) -@@ -834,7 +839,7 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); - unsigned IOCTL_VT_WAITACTIVE = VT_WAITACTIVE; - #endif // SANITIZER_LINUX || SANITIZER_FREEBSD - --#if SANITIZER_LINUX && !SANITIZER_ANDROID -+#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_NONGNU - unsigned IOCTL_CYGETDEFTHRESH = CYGETDEFTHRESH; - unsigned IOCTL_CYGETDEFTIMEOUT = CYGETDEFTIMEOUT; - unsigned IOCTL_CYGETMON = CYGETMON; -@@ -989,7 +994,7 @@ CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_phdr); - CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_phnum); - #endif // SANITIZER_LINUX || SANITIZER_FREEBSD - --#if (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID -+#if (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID && !SANITIZER_NONGNU - CHECK_TYPE_SIZE(glob_t); - CHECK_SIZE_AND_OFFSET(glob_t, gl_pathc); - CHECK_SIZE_AND_OFFSET(glob_t, gl_pathv); -@@ -1023,6 +1028,7 @@ CHECK_TYPE_SIZE(iovec); - CHECK_SIZE_AND_OFFSET(iovec, iov_base); - CHECK_SIZE_AND_OFFSET(iovec, iov_len); - -+#if !SANITIZER_NONGNU - CHECK_TYPE_SIZE(msghdr); - CHECK_SIZE_AND_OFFSET(msghdr, msg_name); - CHECK_SIZE_AND_OFFSET(msghdr, msg_namelen); -@@ -1036,6 +1042,7 @@ CHECK_TYPE_SIZE(cmsghdr); - CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_len); - CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_level); - CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_type); -+#endif - - #ifndef __GLIBC_PREREQ - #define __GLIBC_PREREQ(x, y) 0 -@@ -1145,7 +1152,7 @@ CHECK_SIZE_AND_OFFSET(mntent, mnt_passno); - - CHECK_TYPE_SIZE(ether_addr); - --#if (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID -+#if (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID && !SANITIZER_NONGNU - CHECK_TYPE_SIZE(ipc_perm); - # if SANITIZER_FREEBSD - CHECK_SIZE_AND_OFFSET(ipc_perm, key); -@@ -1206,7 +1213,7 @@ CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_dstaddr); - CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_data); - #endif - --#if SANITIZER_LINUX -+#if SANITIZER_LINUX && !SANITIZER_NONGNU - COMPILER_CHECK(sizeof(__sanitizer_mallinfo) == sizeof(struct mallinfo)); - #endif - -@@ -1256,7 +1263,7 @@ COMPILER_CHECK(__sanitizer_XDR_DECODE == XDR_DECODE); - COMPILER_CHECK(__sanitizer_XDR_FREE == XDR_FREE); - #endif - --#if SANITIZER_LINUX && !SANITIZER_ANDROID -+#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_NONGNU - COMPILER_CHECK(sizeof(__sanitizer_FILE) <= sizeof(FILE)); - CHECK_SIZE_AND_OFFSET(FILE, _flags); - CHECK_SIZE_AND_OFFSET(FILE, _IO_read_ptr); -@@ -1275,7 +1282,7 @@ CHECK_SIZE_AND_OFFSET(FILE, _chain); - CHECK_SIZE_AND_OFFSET(FILE, _fileno); - #endif - --#if SANITIZER_LINUX && !SANITIZER_ANDROID -+#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_NONGNU - COMPILER_CHECK(sizeof(__sanitizer__obstack_chunk) <= sizeof(_obstack_chunk)); - CHECK_SIZE_AND_OFFSET(_obstack_chunk, limit); - CHECK_SIZE_AND_OFFSET(_obstack_chunk, prev); -diff --git a/lib/tsan/rtl/tsan_platform_linux.cc b/lib/tsan/rtl/tsan_platform_linux.cc -index de989b780..51a97b554 100644 ---- a/lib/tsan/rtl/tsan_platform_linux.cc -+++ b/lib/tsan/rtl/tsan_platform_linux.cc -@@ -294,7 +294,7 @@ void InitializePlatform() { - // This is required to properly "close" the fds, because we do not see internal - // closes within glibc. The code is a pure hack. - int ExtractResolvFDs(void *state, int *fds, int nfd) { --#if SANITIZER_LINUX && !SANITIZER_ANDROID -+#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_NONGNU - int cnt = 0; - struct __res_state *statp = (struct __res_state*)state; - for (int i = 0; i < MAXNS && cnt < nfd; i++) { --- -2.19.0 - diff --git a/nix/nixpkgs-newer.nix b/nix/nixpkgs-newer.nix index 44578bdaa33..3c74a0151b5 100644 --- a/nix/nixpkgs-newer.nix +++ b/nix/nixpkgs-newer.nix @@ -1,6 +1,6 @@ -with { rev = "b63c99659e6b18771c734be0d320008d4b548929"; }; +with { rev = "42710203b04738b8f19ae51f0fd21d22fddf3f39"; }; import (builtins.fetchTarball { - sha256 = "19yvp0i9dw26ijddwjkahrgj2zhb4qnflvmnjqwavf24i6m0p4ki"; + sha256 = "1fqfi0rrlhmssp2cfz07f9sg3mvck28mxnmd39w2ir8670xfixvq"; url = "https://github.com/NixOS/nixpkgs/archive/${rev}.tar.gz"; }) diff --git a/rts/Makefile b/rts/Makefile index a4f5dd47994..9aa92964fc6 100644 --- a/rts/Makefile +++ b/rts/Makefile @@ -47,7 +47,7 @@ CLANG_FLAGS = \ # WASM_FLAGS = \ - --target=wasm32-unknown-unknown-wasm -fvisibility=hidden \ + --target=wasm32-unknown-emscripten-wasm -fvisibility=hidden \ -fno-builtin -ffreestanding \ --optimize=3 \ From 10e877f718763687b0a0c87a5c6aba2c0b9cdccc Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 12 Nov 2019 15:24:26 +0100 Subject: [PATCH 0555/1176] Bump dfinity (#857) * Bump dfinity in particular, to import `drun` instead of `dfinity.rs.drun` (https://github.com/dfinity-lab/dfinity/pull/1833) * Try https://github.com/dfinity-lab/dfinity/pull/1841 * Update test output * drun.toml: Section got renamed * Track dfinity master --- default.nix | 6 +++--- test/drun.toml | 2 +- test/run-drun/ok/idl-bad.drun-run.ok | 2 +- test/run-drun/ok/idl-nary.drun-run.ok | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/default.nix b/default.nix index 9f7680a2650..1ffefc79b6c 100644 --- a/default.nix +++ b/default.nix @@ -21,8 +21,8 @@ let dev = import (builtins.fetchGit { let dfinity-repo = import (builtins.fetchGit { name = "dfinity-sources"; url = "ssh://git@github.com/dfinity-lab/dfinity"; - # ref = "master"; - rev = "3c82c6400b0eb8c5785669996f5b8007623cd9fc"; + ref = "master"; + rev = "907aaadd6272d81ab9d9b02d9858fa8423192bfe"; }) { system = nixpkgs.system; }; in let sdk = import (builtins.fetchGit { @@ -44,7 +44,7 @@ let real-dvm = let real-drun = if drun == null - then dfinity-repo.dfinity.drun + then dfinity-repo.drun or dfinity-repo.dfinity.drun else drun; in let js-user-library = sdk.js-user-library; in diff --git a/test/drun.toml b/test/drun.toml index ba938f471e8..37e4b23227c 100644 --- a/test/drun.toml +++ b/test/drun.toml @@ -1,4 +1,4 @@ -[application] +[scheduler] scheduler_cores = 1 round_gas_max = 10_000_000_000_000 exec_gas = 1_000_000_000_000 diff --git a/test/run-drun/ok/idl-bad.drun-run.ok b/test/run-drun/ok/idl-bad.drun-run.ok index d5e839da5d6..401133f7f50 100644 --- a/test/run-drun/ok/idl-bad.drun-run.ok +++ b/test/run-drun/ok/idl-bad.drun-run.ok @@ -1,2 +1,2 @@ ingress(0) System -Err: IC0503: Canister 42 called 'ic.trap' with message 'explicit canister trap: IDL error: missing magic bytes' +Err: IC0503: Canister 42 trapped explicitly: IDL error: missing magic bytes diff --git a/test/run-drun/ok/idl-nary.drun-run.ok b/test/run-drun/ok/idl-nary.drun-run.ok index 3ceb8691eaa..e6f3a393455 100644 --- a/test/run-drun/ok/idl-nary.drun-run.ok +++ b/test/run-drun/ok/idl-nary.drun-run.ok @@ -7,6 +7,6 @@ ingress(5) Completed: Canister: Payload: 0x4449444c016c0400710171027103710100034 ingress(6) Completed: Canister: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 ingress(7) Completed: Canister: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 ingress(8) Completed: Canister: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 -ingress(9) Err: IC0503: Canister 42 called 'ic.trap' with message 'explicit canister trap: IDL error: too few arguments Text,Text,Text' -ingress(10) Err: IC0503: Canister 42 called 'ic.trap' with message 'explicit canister trap: IDL error: left-over bytes Text,Text,Text' +ingress(9) Err: IC0503: Canister 42 trapped explicitly: IDL error: too few arguments Text,Text,Text +ingress(10) Err: IC0503: Canister 42 trapped explicitly: IDL error: left-over bytes Text,Text,Text ingress(11) Completed: Canister: Payload: 0x4449444c000471717171034f6e650354776f05546872656504466f7572 From d74ddefb68f837570471213e98134b5752948212 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 12 Nov 2019 19:15:41 +0000 Subject: [PATCH 0556/1176] sketch type indexed awaits --- design/scoped-await.md | 161 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 design/scoped-await.md diff --git a/design/scoped-await.md b/design/scoped-await.md new file mode 100644 index 00000000000..1cb17d92f44 --- /dev/null +++ b/design/scoped-await.md @@ -0,0 +1,161 @@ +# Structured awaits using indexed async types and parametric polymorphism + + +# Abstract Syntax + +```bnf + := ... + | async[T]U // T is an index, typically a type parameter + + := + | async e // index abstraction plus application in one + | shared f(x:T) : async[X]U = async e ; // requests + | shared f(x:T) : async[X]U { e; } // sugar (for the above) + | f e // (indexed) application +``` + +### Parameterized async expressions + +``` +E,X; async[X] |- e : T +-------------------------------------- +E; async[U] |- async e : async[U]T +``` +An `async` expression at index `X` provides the scoped ability to await asyncs with index `X`. + +The body 'e' of an async must be parametric in the index but the index parameter is immediately eliminated at any index `U`. + +### (restricted) await expressions +``` +E; async[T] |- e : async[T]U +------------------------------ +E; async[T] |- await e : U +``` + +We can only await things of the current index `T`, recorded in the context as `_ ; async[T]`. + +### Application + +``` +E; _ |- f : shared U -> async[X] V +E; _ |- e': [T/X] U +------------------------------------- +E; _ |- f e' : async[T]([T/X]V) +``` + +Application must provide an index, typically the nearest enclosing index parameter if want to await the result, but I guess +it could be any enclosing index parameter. + + +### Abstraction + +Rule for (desugared) shared functions: + +``` +E, X, x : T, Y; async |- e : U +---------------------------------------------------- +E; _ |- shared f(x:T) : async[X]U = async e ; +``` +Every shared function introduce a new index parameter, immediately supplied to the inner async expression. + +Derived rule for sugar: + +``` +E, X, x : T; async |- e : U +-------------------------------------------- +E; _ |- shared f(x:T) : async[X] U { e; } +``` + +## Examples: + +Assuming the following requests: + +``` +shared Request() : async[X](){ +} + +shared Echo(i : Int) : async[X] Int { return i; } +``` + + +### Static parralel waiting: +``` +async { + let a1 = Request(); + let a2 = Request() + await(a1); + await(a2); +}; +``` + +### Dynamic parallel waiting for acknowledgements + +``` +async { + let as = Array_tabulate()>(func _ { Request(); }); + for (a in as.key) { + await(a2); + }; +}; +``` + +### Dynamic parallel waiting (with results) + +``` +async { + let as = Array_tabulate()>(func _ { Request(); }); + let res = Array_init<>(as.len,-1); + rs = for (i in as.keys()) { + res[i] := await(a2); + }; + res; +}; +``` + +### Recursive parallel waiting + +``` +shared func waitN(n:Nat) : async[X]() { + if (n = 0) + () + else { + let a = Request(); + await waitN(n-1); + await(a); + }; +}; +``` +### Recursive parallel waiting (with results) + +``` +shared func waitN(n:Nat) : async[X](List) { + if (n = 0) + List.null + else { + let a = Echo(n); + let tl = await waitN(n-1); + List.cons(await(a),tl); + }; +}; +``` +### Deadlock Prevention: + +### Immediate deadlock + +``` +let t:async[T]U = async{ await t;}; // bad await since t : Async[Any]U { + let a1 = async{ await a2; }; // bad await since a1 : Async[X]() () + let a2 = async{ await a1; }; // bad await since a2 : Async[X]() () + await(a1); +}; +``` +Ruled out by index scoping (`X != Y,Z`, any `Y,Z`) From d7c5495dd5d848837ed52d25420bb5f44c26864a Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 12 Nov 2019 19:52:35 +0000 Subject: [PATCH 0557/1176] fixes --- design/scoped-await.md | 91 +++++++++++++++++++++++++++++++----------- 1 file changed, 68 insertions(+), 23 deletions(-) diff --git a/design/scoped-await.md b/design/scoped-await.md index 1cb17d92f44..b9a875b316f 100644 --- a/design/scoped-await.md +++ b/design/scoped-await.md @@ -1,5 +1,35 @@ # Structured awaits using indexed async types and parametric polymorphism +Inspired by Launchbury's RunST trick and Rust's lifetimes. + +*Basic idea:* + +Use type indexing and parametricity to ensure +that a function can only await async +values it has created, hopefully ruling out: + +* deadlock, and +* reply to wrong sender + +while still allowing local uses of first-class async values. + +Deadlock is (hopefully) prevented because an async can't await itself, since +it can only await async it has created. Similarly a sequence of +async can only be awaited by the async that created them, not by each other. +That's the hope anyway. + +The idea behind ruling out reply-to-wrong-sender is that an async +value cannot be stored in a non-local var or other mutable +datastructure, due to the fresh index, so it is only accessible from +the currentmessage and thus can only receive continuation from the +current message. It can't receive continuations from an inner +function by escaping into that function, since the inner function can at +most await asyncs with its inner index, not the outer ne. Thus the only +contination that are stored (including the ultimate reply +continuation), are from the current function. + +_Please break it_ + # Abstract Syntax @@ -8,24 +38,37 @@ | async[T]U // T is an index, typically a type parameter := - | async e // index abstraction plus application in one - | shared f(x:T) : async[X]U = async e ; // requests - | shared f(x:T) : async[X]U { e; } // sugar (for the above) - | f e // (indexed) application + | async e // index abstraction plus application in one (parameter X free in e, but not in instantiation U) + | shared f(x:T) : async[X]U = async e ; // requests + | shared f(x:T) : async[X]U { e; } // sugar (for the above) + | f e // (indexed) application + +Ctxt := E; async[T] // async context with index U + | E; - // non-async context + +Env := // the usual suspect + | E, x : T + | E, X + | ``` +# Concrete Syntax + +TBD, but hopefully the explicit parameterization/instantiaton can be surpressed, much as Rust *lifetimes* are largely implicit. + ### Parameterized async expressions ``` -E,X; async[X] |- e : T --------------------------------------- -E; async[U] |- async e : async[U]T +E, X; async[X] |- e : T E |- U :: * (X fresh) +------------------------------------------------- +E; async[U] |- async e : async[U]T ``` An `async` expression at index `X` provides the scoped ability to await asyncs with index `X`. -The body 'e' of an async must be parametric in the index but the index parameter is immediately eliminated at any index `U`. +The body 'e' of an async must be parametric in the index but the index parameteris immediately eliminated at any index `U` (not mentioning `X`). ### (restricted) await expressions + ``` E; async[T] |- e : async[T]U ------------------------------ @@ -49,16 +92,16 @@ it could be any enclosing index parameter. ### Abstraction -Rule for (desugared) shared functions: +Rule for (desugared) shared functions (ignoring recursion). ``` -E, X, x : T, Y; async |- e : U +E, X, x : T, Y; async |- e : U (X, Y fresh) ---------------------------------------------------- E; _ |- shared f(x:T) : async[X]U = async e ; ``` Every shared function introduce a new index parameter, immediately supplied to the inner async expression. -Derived rule for sugar: +Derived rule for sugar (ignoring recursion): ``` E, X, x : T; async |- e : U @@ -71,18 +114,16 @@ E; _ |- shared f(x:T) : async[X] U { e; } Assuming the following requests: ``` -shared Request() : async[X](){ -} +shared Ack() : async[X](){ }; -shared Echo(i : Int) : async[X] Int { return i; } +shared Request(i : Int) : async[X] Int { return i; } ``` - ### Static parralel waiting: ``` async { - let a1 = Request(); - let a2 = Request() + let a1 = Ack(); + let a2 = Ack() await(a1); await(a2); }; @@ -92,7 +133,7 @@ async { ``` async { - let as = Array_tabulate()>(func _ { Request(); }); + let as = Array_tabulate()>(func _ { Ack(); }); for (a in as.key) { await(a2); }; @@ -103,7 +144,7 @@ async { ``` async { - let as = Array_tabulate()>(func _ { Request(); }); + let as = Array_tabulate()>(func _ { Ack(); }); let res = Array_init<>(as.len,-1); rs = for (i in as.keys()) { res[i] := await(a2); @@ -119,12 +160,13 @@ shared func waitN(n:Nat) : async[X]() { if (n = 0) () else { - let a = Request(); + let a = Ack(); await waitN(n-1); - await(a); + await(a); }; }; ``` + ### Recursive parallel waiting (with results) ``` @@ -132,19 +174,22 @@ shared func waitN(n:Nat) : async[X](List) { if (n = 0) List.null else { - let a = Echo(n); + let a = Request(n); let tl = await waitN(n-1); - List.cons(await(a),tl); + List.cons(await(a),tl); }; }; ``` + ### Deadlock Prevention: ### Immediate deadlock + ``` let t:async[T]U = async{ await t;}; // bad await since t : Async[Any]U Date: Tue, 12 Nov 2019 19:55:38 +0000 Subject: [PATCH 0558/1176] fixes --- design/scoped-await.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/design/scoped-await.md b/design/scoped-await.md index b9a875b316f..6f0ed8740c9 100644 --- a/design/scoped-await.md +++ b/design/scoped-await.md @@ -46,7 +46,7 @@ _Please break it_ Ctxt := E; async[T] // async context with index U | E; - // non-async context -Env := // the usual suspect +Env := // the usual suspects | E, x : T | E, X | @@ -65,7 +65,8 @@ E; async[U] |- async e : async[U]T ``` An `async` expression at index `X` provides the scoped ability to await asyncs with index `X`. -The body 'e' of an async must be parametric in the index but the index parameteris immediately eliminated at any index `U` (not mentioning `X`). +The body `e` of an async must be parametric in the index but the index +parameter is immediately eliminated at some index `U` (not mentioning `X`). ### (restricted) await expressions From 287fedd3cbcb399d9af6559c7e2f7c6ed0c53fd6 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 12 Nov 2019 19:59:18 +0000 Subject: [PATCH 0559/1176] fixes --- design/scoped-await.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/design/scoped-await.md b/design/scoped-await.md index 6f0ed8740c9..26ed121a18b 100644 --- a/design/scoped-await.md +++ b/design/scoped-await.md @@ -136,7 +136,7 @@ async { async { let as = Array_tabulate()>(func _ { Ack(); }); for (a in as.key) { - await(a2); + await(a2); }; }; ``` @@ -162,8 +162,8 @@ shared func waitN(n:Nat) : async[X]() { () else { let a = Ack(); - await waitN(n-1); - await(a); + await waitN(n-1); // recurse + await(a); }; }; ``` @@ -173,7 +173,7 @@ shared func waitN(n:Nat) : async[X]() { ``` shared func waitN(n:Nat) : async[X](List) { if (n = 0) - List.null + List.null(); else { let a = Request(n); let tl = await waitN(n-1); @@ -184,7 +184,7 @@ shared func waitN(n:Nat) : async[X](List) { ### Deadlock Prevention: -### Immediate deadlock +#### Immediate deadlock ``` @@ -193,9 +193,7 @@ let t:async[T]U = async{ await t;}; // bad await since t : Async[Any]U { @@ -204,4 +202,5 @@ async { await(a1); }; ``` + Ruled out by index scoping (`X != Y,Z`, any `Y,Z`) From 0a4238f5d4fb766ec212ac2182a8cdd9c7ba0d47 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 12 Nov 2019 20:05:47 +0000 Subject: [PATCH 0560/1176] Update scoped-await.md --- design/scoped-await.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/design/scoped-await.md b/design/scoped-await.md index 26ed121a18b..843ab07b28b 100644 --- a/design/scoped-await.md +++ b/design/scoped-await.md @@ -14,19 +14,19 @@ values it has created, hopefully ruling out: while still allowing local uses of first-class async values. Deadlock is (hopefully) prevented because an async can't await itself, since -it can only await async it has created. Similarly a sequence of -async can only be awaited by the async that created them, not by each other. +it can only await asyncs it has created. Similarly a sequence of +asyncs can only be awaited by the async that created them, not by each other. That's the hope anyway. The idea behind ruling out reply-to-wrong-sender is that an async value cannot be stored in a non-local var or other mutable datastructure, due to the fresh index, so it is only accessible from -the currentmessage and thus can only receive continuation from the -current message. It can't receive continuations from an inner +the current message and thus can only receive continuations from the +current message. It can't receive continuations from an inner function by escaping into that function, since the inner function can at -most await asyncs with its inner index, not the outer ne. Thus the only +most await asyncs with its inner index, not the outer one. Thus the only contination that are stored (including the ultimate reply -continuation), are from the current function. +continuation), must be from the current function. _Please break it_ @@ -55,6 +55,8 @@ Env := // the usual suspects # Concrete Syntax TBD, but hopefully the explicit parameterization/instantiaton can be surpressed, much as Rust *lifetimes* are largely implicit. +Here, the simplist might be to use the function name itself for the implicit index parameter +(although not all motoko functions are named) and always instantiate with the ambient index (or `Any` if none). ### Parameterized async expressions From d1b64ccfcd0ab943b352a2cb83e5828bb58e7b56 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 12 Nov 2019 20:07:03 +0000 Subject: [PATCH 0561/1176] Update scoped-await.md --- design/scoped-await.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/design/scoped-await.md b/design/scoped-await.md index 843ab07b28b..b3963548775 100644 --- a/design/scoped-await.md +++ b/design/scoped-await.md @@ -14,18 +14,18 @@ values it has created, hopefully ruling out: while still allowing local uses of first-class async values. Deadlock is (hopefully) prevented because an async can't await itself, since -it can only await asyncs it has created. Similarly a sequence of +it can only await asyncs it has created. Similarly, a sequence of asyncs can only be awaited by the async that created them, not by each other. That's the hope anyway. -The idea behind ruling out reply-to-wrong-sender is that an async +The idea behind ruling out *reply-to-wrong-sender* is that an async value cannot be stored in a non-local var or other mutable datastructure, due to the fresh index, so it is only accessible from -the current message and thus can only receive continuations from the +the current message and thus can only receive continuations (via `await`) from the current message. It can't receive continuations from an inner function by escaping into that function, since the inner function can at most await asyncs with its inner index, not the outer one. Thus the only -contination that are stored (including the ultimate reply +continations that are stored (including the ultimate reply continuation), must be from the current function. _Please break it_ From fadc0343bc4ef2209d5cf05822e6203c58c098ce Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 13 Nov 2019 10:56:32 +0100 Subject: [PATCH 0562/1176] Add a README and a `shell.nix` --- Building.md | 2 ++ ic-stub/README.md | 33 +++++++++++++++++++++++++++++++++ ic-stub/cabal.project | 1 + ic-stub/shell.nix | 13 +++++++++++++ 4 files changed, 49 insertions(+) create mode 100644 ic-stub/README.md create mode 100644 ic-stub/shell.nix diff --git a/Building.md b/Building.md index 6db0d3d9ca2..2c32036eaab 100644 --- a/Building.md +++ b/Building.md @@ -53,6 +53,8 @@ installing all required tools without nix is out of scope). nix-env -i -f . -A filecheck nix-env -i -f . -A wabt nix-env -i -f . -A dvm + nix-env -i -f . -A drun + nix-env -i -f . -A ic-stub ``` * Building the Motoko runtime without nix is tricky. But you can run ``` diff --git a/ic-stub/README.md b/ic-stub/README.md new file mode 100644 index 00000000000..1a13ee11470 --- /dev/null +++ b/ic-stub/README.md @@ -0,0 +1,33 @@ +The IC Stub +=========== + +The IC stub is a partial implementation of the public interface of the DFINITY +Internet Computer, as specified in +https://docs.dfinity.systems/spec/public/ +with the primary goal of providing a mock environment to test the output of the +Motoko compiler. + +It currently provides one binary, `ic-stub-run`, that allows you to script the +execution of a single canister. + +Status +------ + +This is neither complete nor authorative. Since this is primarily meant for +testing the output of Motoko, code paths not exercised by Motoko may not be +present; in particular, error handling and input validation is incomplete. + +Installation of `ic-stub-run` +----------------------------- + +From the top-level repository directory, run + + + nix-env -i -f . -A ic-stub + + +Developing on ic-stub +--------------------- + +Running `nix-shell` in the `ic-stub/` directory should give you an environment +that allows you to build the project using `cabal new-build`. diff --git a/ic-stub/cabal.project b/ic-stub/cabal.project index e69de29bb2d..e6fdbadb439 100644 --- a/ic-stub/cabal.project +++ b/ic-stub/cabal.project @@ -0,0 +1 @@ +packages: . diff --git a/ic-stub/shell.nix b/ic-stub/shell.nix new file mode 100644 index 00000000000..9e1ba03df1f --- /dev/null +++ b/ic-stub/shell.nix @@ -0,0 +1,13 @@ +{ nixpkgs ? (import ../nix/nixpkgs.nix).nixpkgs {} }: + +let + ic-stub = (import ../default.nix {inherit nixpkgs;}).ic-stub; + + extra-pkgs = [ + nixpkgs.haskellPackages.cabal-install + nixpkgs.haskellPackages.ghcid + ]; +in + ic-stub.env.overrideAttrs (old: { + nativeBuildInputs = (old.nativeBuildInputs or []) ++ extra-pkgs ; + }) From dac7108fef492bdc47a36227ad1f6e53ba677649 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 13 Nov 2019 10:33:50 +0000 Subject: [PATCH 0563/1176] Update scoped-await.md removed unnessary restriction on async introduction (need not be in an async context). --- design/scoped-await.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/design/scoped-await.md b/design/scoped-await.md index b3963548775..efd71a3144b 100644 --- a/design/scoped-await.md +++ b/design/scoped-await.md @@ -63,7 +63,7 @@ Here, the simplist might be to use the function name itself for the implicit ind ``` E, X; async[X] |- e : T E |- U :: * (X fresh) ------------------------------------------------- -E; async[U] |- async e : async[U]T +E; - |- async e : async[U]T ``` An `async` expression at index `X` provides the scoped ability to await asyncs with index `X`. From 1531171ec711e7b473b6501a750dd3de2e7737b7 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 13 Nov 2019 10:44:09 +0000 Subject: [PATCH 0564/1176] Update scoped-await.md --- design/scoped-await.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/design/scoped-await.md b/design/scoped-await.md index efd71a3144b..c0c47f33ef7 100644 --- a/design/scoped-await.md +++ b/design/scoped-await.md @@ -206,3 +206,28 @@ async { ``` Ruled out by index scoping (`X != Y,Z`, any `Y,Z`) + +### Imperative deadlock + +The informal example: +``` +shared func f() : async () { + var x : async Nat = async 0; + x := async { + await x + }; +} +``` + +is rejected by this system: + +Explicitly, the shared function and nested async would have distinct indices,so the await for type `asyncNat` on `x` (of type asyncNat (with the outer parameter) would actually be illegal: + +``` +shared func f() : async () { + var x : async Nat = async<_> 0 ; + x := async{ + await x // illegal: await _ : asyncT -> T (not async T -> T) (any T) + } ; +} +``` From deb282ad533af93dc537db1bc30e40acfdcc097c Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 13 Nov 2019 14:15:12 +0100 Subject: [PATCH 0565/1176] Test suite: validate wasm output (#863) --- test/run.sh | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/test/run.sh b/test/run.sh index bff1d5a1696..058996d2e2e 100755 --- a/test/run.sh +++ b/test/run.sh @@ -206,21 +206,24 @@ do # Compile run comp $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS --map -c $base.mo -o $out/$base.wasm - # Check filecheck - if [ "$SKIP_RUNNING" != yes ] + if [ -e $out/$base.wasm ] then - if grep -F -q CHECK $base.mo + # Validate wasm + run valid wasm-validate $out/$base.wasm + + # Check filecheck + if [ "$SKIP_RUNNING" != yes ] then - $ECHO -n " [FileCheck]" - wasm2wat --no-check --enable-multi-value $out/$base.wasm > $out/$base.wat - cat $out/$base.wat | FileCheck $base.mo > $out/$base.filecheck 2>&1 - diff_files="$diff_files $base.filecheck" + if grep -F -q CHECK $base.mo + then + $ECHO -n " [FileCheck]" + wasm2wat --no-check --enable-multi-value $out/$base.wasm > $out/$base.wat + cat $out/$base.wat | FileCheck $base.mo > $out/$base.filecheck 2>&1 + diff_files="$diff_files $base.filecheck" + fi fi - fi - # Run compiled program - if [ -e $out/$base.wasm ] - then + # Run compiled program if [ "$SKIP_RUNNING" != yes ] then if [ $API = ancient ] From 82641372871f52e50bd72436dcf596630a6e2976 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 13 Nov 2019 14:09:34 +0000 Subject: [PATCH 0566/1176] Update design/scoped-await.md Co-Authored-By: Andreas Rossberg --- design/scoped-await.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/design/scoped-await.md b/design/scoped-await.md index c0c47f33ef7..3c153c32ab4 100644 --- a/design/scoped-await.md +++ b/design/scoped-await.md @@ -54,7 +54,7 @@ Env := // the usual suspects # Concrete Syntax -TBD, but hopefully the explicit parameterization/instantiaton can be surpressed, much as Rust *lifetimes* are largely implicit. +TBD, but hopefully the explicit parameterization/instantiation can be supressed, much as Rust *lifetimes* are largely implicit. Here, the simplist might be to use the function name itself for the implicit index parameter (although not all motoko functions are named) and always instantiate with the ambient index (or `Any` if none). From c11afbd368d5141e98b2f28113f54a1749001d6a Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 13 Nov 2019 14:09:44 +0000 Subject: [PATCH 0567/1176] Update design/scoped-await.md Co-Authored-By: Andreas Rossberg --- design/scoped-await.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/design/scoped-await.md b/design/scoped-await.md index 3c153c32ab4..ca0e6596618 100644 --- a/design/scoped-await.md +++ b/design/scoped-await.md @@ -48,7 +48,7 @@ Ctxt := E; async[T] // async context with index U Env := // the usual suspects | E, x : T - | E, X + | E, X <: T | ``` From a523aa3d454cbe2c9ff83abf4c4f5ba0c60ad008 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Wed, 13 Nov 2019 15:43:19 +0100 Subject: [PATCH 0568/1176] Deser: annotate numeric literals (#862) * annotate fixed-size literals when outputting * perform 64-bit as bigint * test literal annotations Caveat: `opt ` still not parenthesised. --- src/exes/deser.ml | 49 +++++++++++++++++++-------------- src/exes/dune | 2 +- test/run-deser/annot-lit.bin | Bin 0 -> 82 bytes test/run-deser/ok/annot-lit.ok | 17 ++++++++++++ 4 files changed, 47 insertions(+), 21 deletions(-) create mode 100644 test/run-deser/annot-lit.bin create mode 100644 test/run-deser/ok/annot-lit.ok diff --git a/src/exes/deser.ml b/src/exes/deser.ml index 2497e5b5e70..90c807a0410 100644 --- a/src/exes/deser.ml +++ b/src/exes/deser.ml @@ -28,17 +28,17 @@ let read_byte () : int = let read_2byte () : int = let lsb = read_byte () in let msb = read_byte () in - msb * 256 + lsb + msb lsl 8 + lsb let read_4byte () : int = let lsb = read_2byte () in let msb = read_2byte () in - msb * 65536 + lsb + msb lsl 16 + lsb -let read_8byte () : int = (* TODO: should be bigint *) +let read_8byte () : Big_int.big_int = let lsb = read_4byte () in let msb = read_4byte () in - msb * 4294967296 + lsb + Big_int.(add_int_big_int lsb (mult_int_big_int 4294967296 (big_int_of_int msb))) let read_signed_byte () : bool * int = let b = read_byte () in @@ -73,19 +73,18 @@ let read_int8 () : int = let read_int16 () : int = let lsb = read_byte () in let msb = read_int8 () in - msb * 256 + lsb + msb lsl 8 lor lsb let read_int32 () : int = let lsb = read_2byte () in let msb = read_int16 () in - msb * 65536 + lsb + msb lsl 16 lor lsb -let read_int64 () : int = (* TODO: should be bigint *) +let read_int64 () : Big_int.big_int = let lsb = read_4byte () in let msb = read_int32 () in - msb * 4294967296 + lsb + Big_int.(add_int_big_int lsb (mult_int_big_int 4294967296 (big_int_of_int msb))) -(* bool: M(b : bool) = i8(if b then 1 else 0) *) let read_bool () : bool = match read_byte () with | 0 -> false @@ -152,11 +151,11 @@ val output_nil : outputter val output_byte : int -> unit val output_2byte : int -> unit val output_4byte : int -> unit -val output_8byte : int -> unit +val output_8byte : Big_int.big_int -> unit val output_int8 : int -> unit val output_int16 : int -> unit val output_int32 : int -> unit -val output_int64 : int -> unit +val output_int64 : Big_int.big_int -> unit val output_text : int -> Stdio.In_channel.t -> Stdio.Out_channel.t -> unit val output_some : outputter -> unit val output_arguments : int -> outputter * (unit -> int -> outputter -> outputter) @@ -184,6 +183,7 @@ let fill () = if !continue_line then (continue_line := false; "") else String.ma let output_string what (s : string) = Printf.printf "%s%s: %s\n" (fill ()) what s let output_decimal what (i : int) = Printf.printf "%s%s: %d\n" (fill ()) what i +let output_big_decimal what (i : Big_int.big_int) = Printf.printf "%s%s: %s\n" (fill ()) what (Big_int.string_of_big_int i) (* outputters *) let output_nat nat = output_decimal "output_nat" nat @@ -194,11 +194,11 @@ let output_some consumer = Printf.printf "%sSome: value follows on the next line let output_byte b = output_decimal "output_byte" b let output_2byte b = output_decimal "output_2byte" b let output_4byte b = output_decimal "output_4byte" b -let output_8byte b = output_decimal "output_8byte" b +let output_8byte b = output_big_decimal "output_8byte" b let output_int8 i = output_decimal "output_int8" i let output_int16 i = output_decimal "output_int16" i let output_int32 i = output_decimal "output_int32" i -let output_int64 i = output_decimal "output_int64" i +let output_int64 i = output_big_decimal "output_int64" i let output_text bytes from tostream = let buf = Buffer.create 0 in ignore (input_buffer from buf ~len:bytes); @@ -241,16 +241,24 @@ let output_string (s : string) = print_string s let chat_string s = if !chatty then output_string s let output_string_space (s : string) = output_string s; output_string " " let output_decimal (i : int) = Printf.printf "%d" i -let output_bignum (i : int) = output_decimal i (* for now *) +let output_big_decimal (i : Big_int.big_int) = output_string (Big_int.string_of_big_int i) +(* let output_bignum (i : Big_int.big_int) = Printf.printf "%s" (Big_int.string_of_big_int i) *) +let output_bignum (i : int) = output_decimal i (* for now, later: output_big_decimal *) +let casted ty f v = match ty with + | IntN n -> f v; Printf.printf " : int%d" n + | NatN n -> f v; Printf.printf " : nat%d" n + | _ -> assert false let output_bool b = output_string (if b then "true" else "false") let output_nil () = output_string "null" let output_some consumer = output_string_space "opt"; consumer () -let output_byte, output_2byte, output_4byte = output_decimal, output_decimal, output_decimal -let output_8byte = output_bignum +let output_byte, output_2byte, output_4byte = + casted (NatN 8) output_decimal, casted (NatN 16) output_decimal, casted (NatN 32) output_decimal +let output_8byte = casted (NatN 64) output_big_decimal let output_nat, output_int = output_bignum, output_bignum -let output_int8, output_int16, output_int32 = output_decimal, output_decimal, output_decimal -let output_int64 = output_bignum +let output_int8, output_int16, output_int32 = + casted (IntN 8) output_decimal, casted (IntN 16) output_decimal, casted (IntN 32) output_decimal +let output_int64 = casted (IntN 64) output_big_decimal let output_text n froms tos = output_string "\""; let buf = Buffer.create 0 in @@ -301,16 +309,17 @@ module OutputJson : Dump = struct let output_string (s : string) = print_string s let output_string_space (s : string) = Printf.printf "%s " s let output_decimal (i : int) = Printf.printf "%d" i +let output_big_decimal (i : Big_int.big_int) = output_string (Big_int.string_of_big_int i) let output_bignum (i : int) = output_decimal i (* for now *) let output_bool b = output_string (if b then "true" else "false") let output_nil () = output_string "null" let output_some consumer = output_string "["; consumer (); output_string "]" let output_byte, output_2byte, output_4byte = output_decimal, output_decimal, output_decimal -let output_8byte = output_bignum +let output_8byte = output_big_decimal let output_nat, output_int = output_bignum, output_bignum let output_int8, output_int16, output_int32 = output_decimal, output_decimal, output_decimal -let output_int64 = output_bignum +let output_int64 = output_big_decimal let output_text n froms tos = output_string "\""; let buf = Buffer.create 0 in diff --git a/src/exes/dune b/src/exes/dune index 82c5d3e6046..ca14688d5d4 100644 --- a/src/exes/dune +++ b/src/exes/dune @@ -21,5 +21,5 @@ (executable (name deser) (modules deser) - (libraries stdio) + (libraries stdio num) ) diff --git a/test/run-deser/annot-lit.bin b/test/run-deser/annot-lit.bin new file mode 100644 index 0000000000000000000000000000000000000000..320ee32f20c0ee1ff9aa2af3a692f3e86fe901a4 GIT binary patch literal 82 zcmZ?qbn#&jsID$Auc|65tE?<7t*9s|Vff!r&%p5iKSRTRAPr&x*$hD5e+VBY1{DW! JL2@8a4*;Q1CWrt4 literal 0 HcmV?d00001 diff --git a/test/run-deser/ok/annot-lit.ok b/test/run-deser/ok/annot-lit.ok new file mode 100644 index 00000000000..5ecf863f392 --- /dev/null +++ b/test/run-deser/ok/annot-lit.ok @@ -0,0 +1,17 @@ +( 0 : nat8 +, 255 : nat8 +, -128 : int8 +, 127 : int8 +, 0 : nat16 +, 65535 : nat16 +, -32768 : int16 +, 32767 : int16 +, 0 : nat32 +, 4294967295 : nat32 +, -2147483648 : int32 +, 2147483647 : int32 +, 0 : nat64 +, 18446744073709551615 : nat64 +, -9223372036854775808 : int64 +, 9223372036854775807 : int64 +) \ No newline at end of file From bcfc6cd27ad3c5c626e333d19e964ab7f16101b4 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 13 Nov 2019 16:22:09 +0100 Subject: [PATCH 0569/1176] Factor out a wrapper around Winter --- ic-stub/.hlint.yaml | 1 + ic-stub/ic-stub.cabal | 1 + ic-stub/src/IC/Stub.hs | 158 ++++++++++++---------------------- ic-stub/src/IC/Wasm/Winter.hs | 103 ++++++++++++++++++++++ 4 files changed, 162 insertions(+), 101 deletions(-) create mode 100644 ic-stub/src/IC/Wasm/Winter.hs diff --git a/ic-stub/.hlint.yaml b/ic-stub/.hlint.yaml index 8323a007046..f62b394038b 100644 --- a/ic-stub/.hlint.yaml +++ b/ic-stub/.hlint.yaml @@ -2,3 +2,4 @@ - ignore: {name: "Use uncurry"} - ignore: {name: "Avoid lambda"} - ignore: {name: "Use camelCase"} +- ignore: {name: "Eta reduce"} diff --git a/ic-stub/ic-stub.cabal b/ic-stub/ic-stub.cabal index dc344acbd95..252bdba109d 100644 --- a/ic-stub/ic-stub.cabal +++ b/ic-stub/ic-stub.cabal @@ -9,6 +9,7 @@ executable ic-stub-run main-is: ic-stub-run.hs hs-source-dirs: src other-modules: IC.Stub + other-modules: IC.Wasm.Winter other-modules: IC.DRun.Parse build-depends: base >=4.11 && <5 build-depends: optparse-applicative diff --git a/ic-stub/src/IC/Stub.hs b/ic-stub/src/IC/Stub.hs index a335c6f002e..50ce942c418 100644 --- a/ic-stub/src/IC/Stub.hs +++ b/ic-stub/src/IC/Stub.hs @@ -31,17 +31,7 @@ import Data.STRef import Data.Binary.Get (runGetOrFail) import Data.Default.Class (Default (..)) -import qualified Wasm.Binary.Decode as W -import qualified Wasm.Exec.Eval as W -import qualified Wasm.Runtime.Func as W -import qualified Wasm.Runtime.Instance as W -import qualified Wasm.Runtime.Memory as W -import qualified Wasm.Syntax.AST as W -import qualified Wasm.Syntax.Types as W -import qualified Wasm.Syntax.Values as W -import qualified Wasm.Syntax.Memory as W -import Wasm.Runtime.Mutable - +import IC.Wasm.Winter type (↦) = M.Map @@ -251,29 +241,27 @@ runToCompletion = -- WebAssembly engine. data WasmState - = WSInit (W.Module Identity) CanisterId Blob + = WSInit Module CanisterId Blob | WSUpdate MethodName Arg WasmState parseCanister :: Blob -> Either String CanisterModule parseCanister bytes = - case runGetOrFail W.getModule bytes of - Left (_,_,err) -> Left err - Right (_,_,wasm_mod) -> Right $ concreteToAbstractModule wasm_mod + case parseModule bytes of + Left err -> Left err + Right wasm_mod -> Right $ concreteToAbstractModule wasm_mod -concreteToAbstractModule :: W.Module Identity -> CanisterModule +concreteToAbstractModule :: Module -> CanisterModule concreteToAbstractModule wasm_mod = CanisterModule { init_method = \(cid, arg) -> initializeMethod wasm_mod cid arg , update_methods = M.fromList [ (m, \arg wasm_state -> updateMethod m arg wasm_state) - | Identity e <- W._moduleExports wasm_mod - , W.FuncExport {} <- return $ W._exportDesc e - , Just m <- return $ stripPrefix "canister_update " (T.unpack (W._exportName e)) + | n <- exportedFunctions wasm_mod + , Just m <- return $ stripPrefix "canister_update " n ] , query_methods = M.fromList [ (m, \arg wasm_state -> queryMethod m arg wasm_state) - | Identity e <- W._moduleExports wasm_mod - , W.FuncExport {} <- return $ W._exportDesc e - , Just m <- return $ stripPrefix "canister_query " (T.unpack (W._exportName e)) + | n <- exportedFunctions wasm_mod + , Just m <- return $ stripPrefix "canister_query " n ] } @@ -285,7 +273,7 @@ data Params = Params } data ExecutionState s = ExecutionState - { memory :: Memory s + { inst :: Instance s , self_id :: CanisterId , params :: Params , response :: Maybe Response @@ -294,28 +282,15 @@ data ExecutionState s = ExecutionState -initalExecutionState :: CanisterId -> Memory s -> ExecutionState s -initalExecutionState self_id memory = ExecutionState - { memory +initalExecutionState :: CanisterId -> Instance s -> ExecutionState s +initalExecutionState self_id inst = ExecutionState + { inst , self_id , params = Params Nothing Nothing 0 "" , response = Nothing , reply_data = mempty } -type HostFunc s = ExceptT String (ST s) [W.Value] -type Memory s = W.MemoryInst (ST s) - -getBytes :: Memory s -> W.Address -> W.Size -> ExceptT String (ST s) Blob -getBytes mem ptr len = do - vec <- withExceptT show $ W.loadBytes mem ptr len - return $ BS.pack $ V.toList vec - -setBytes :: Memory s -> W.Address -> Blob -> ExceptT String (ST s) () -setBytes mem ptr blob = - withExceptT show $ - W.storeBytes mem (fromIntegral ptr) (V.fromList (BS.unpack blob)) - type ESRef s = (STRef s Bool, STRef s (Maybe (ExecutionState s))) newESRef :: ST s (ESRef s) @@ -361,9 +336,7 @@ putBytes (pref, _esref) bytes = False -> return () -systemAPI :: forall s. - ESRef s -> - [(String, [(String, W.StackType, W.StackType, [W.Value] -> HostFunc s)])] +systemAPI :: forall s. ESRef s -> Imports s systemAPI esref = [ (,) "ic" [ (,,,) "trap" [i32, i32] [] $ \case @@ -385,48 +358,48 @@ systemAPI esref = unimplemented name arg ret = (,,,) name arg ret $ \_ -> throwError $ "unimplemented: " ++ name - i32 = W.I32Type - i64 = W.I64Type + i32 = I32Type + i64 = I64Type - debug_print :: [W.Value] -> HostFunc s - debug_print [W.I32 ptr, W.I32 len] = do - mem <- getsES esref memory - bytes <- getBytes mem (fromIntegral ptr) len + debug_print :: [Value] -> HostFunc s + debug_print [I32 ptr, I32 len] = do + i <- getsES esref inst + bytes <- getBytes i (fromIntegral ptr) len putBytes esref bytes return [] debug_print _ = fail "debug_print: invalid argument" - arg_data_size :: [W.Value] -> HostFunc s - arg_data_size [W.I64 _nonce] = do + arg_data_size :: [Value] -> HostFunc s + arg_data_size [I64 _nonce] = do blob <- getsES esref (param_dat . params) >>= maybe (throwError "arg_data_size: No argument") return - return [W.I32 (fromIntegral (BS.length blob))] + return [I32 (fromIntegral (BS.length blob))] arg_data_size _ = fail "arg_data_size: invalid argument" - arg_data_copy :: [W.Value] -> HostFunc s - arg_data_copy [W.I64 _nonce, W.I32 dst, W.I32 len, W.I32 offset] = do + arg_data_copy :: [Value] -> HostFunc s + arg_data_copy [I64 _nonce, I32 dst, I32 len, I32 offset] = do blob <- getsES esref (param_dat . params) >>= maybe (throwError "arg_data_size: No argument") return unless (offset == 0) $ throwError "arg_data_copy: offset /= 0 not suppoted" unless (len == fromIntegral (BS.length blob)) $ throwError "arg_data_copy: len not full blob not suppoted" - mem <- getsES esref memory + i <- getsES esref inst -- TODO Bounds checking - setBytes mem (fromIntegral dst) blob + setBytes i (fromIntegral dst) blob return [] arg_data_copy _ = fail "arg_data_copy: invalid argument" - msg_reply :: [W.Value] -> HostFunc s - msg_reply [W.I64 _nonce, W.I32 ptr, W.I32 len] = do - mem <- getsES esref memory - bytes <- getBytes mem (fromIntegral ptr) len + msg_reply :: [Value] -> HostFunc s + msg_reply [I64 _nonce, I32 ptr, I32 len] = do + i <- getsES esref inst + bytes <- getBytes i (fromIntegral ptr) len modES esref (\es -> es { response = Just (Reply bytes) }) return [] msg_reply _ = fail "msg_reply: invalid argument" - msg_reject :: [W.Value] -> HostFunc s - msg_reject [W.I64 _nonce, W.I32 ptr, W.I32 len] = do - mem <- getsES esref memory - bytes <- getBytes mem (fromIntegral ptr) len + msg_reject :: [Value] -> HostFunc s + msg_reject [I64 _nonce, I32 ptr, I32 len] = do + i <- getsES esref inst + bytes <- getBytes i (fromIntegral ptr) len let msg = BSU.toString bytes modES esref (\es -> es { response = Just (Reject (RC_CANISTER_REJECT, msg)) }) return [] @@ -441,7 +414,7 @@ ifStateIsPresent err (StateT f) = StateT $ \case (r, es') <- f es return (r, Just es') -initializeMethod :: W.Module Identity -> CanisterId -> Blob -> TrapOr WasmState +initializeMethod :: Module -> CanisterId -> Blob -> TrapOr WasmState initializeMethod wasm_mod cid arg = runESST $ \esref -> do result <- rawInitializeMethod esref wasm_mod cid arg case result of @@ -474,43 +447,26 @@ replay esref s = silently esref $ go s _ <- rawUpdateMethod rs m arg >>= trapToFail return rs -type RawState s = (ESRef s, CanisterId, IM.IntMap (W.ModuleInst Identity (ST s)), W.ModuleInst Identity (ST s)) +type RawState s = (ESRef s, CanisterId, Instance s) -rawInitializeMethod :: ESRef s -> W.Module Identity -> CanisterId -> Blob -> ST s (TrapOr (RawState s)) +rawInitializeMethod :: ESRef s -> Module -> CanisterId -> Blob -> ST s (TrapOr (RawState s)) rawInitializeMethod esref wasm_mod cid arg = do result <- runExceptT $ do - let names = M.fromList (zip (map (T.pack . fst) (systemAPI esref)) [1..]) - mods = IM.fromList $ zip [1..] - [ (W.emptyModuleInst def) - { W._miGlobals = [ ] - , W._miTables = [ ] - , W._miMemories = [ ] - , W._miFuncs = [ ] - , W._miExports = M.fromList - [ (,) (T.pack fname) $ W.ExternFunc $ - W.allocHostEff (W.FuncType arg_ty ret_ty) - (\ args -> runExceptT $ f args) - | (fname, arg_ty, ret_ty, f) <- funcs - ] - } - | (_name, funcs) <- systemAPI esref - ] - (ref, inst) <- W.initialize (Identity wasm_mod) names mods - let mods' = IM.insert ref inst mods - - -- invoke canister_init - when (M.member (T.pack "canister_init") $ W._miExports inst) $ - void $ withES esref (initalExecutionState cid (head (W._miMemories inst))) $ - W.invokeByName mods' inst (T.pack "canister_init") [W.I64 0] - - return (esref, cid, mods', inst) + inst <- initialize wasm_mod (systemAPI esref) + + -- invoke canister_init + when ("canister_init" `elem` exportedFunctions wasm_mod) $ + void $ withES esref (initalExecutionState cid inst) $ + invokeExport inst "canister_init" [I64 0] + + return (esref, cid, inst) case result of - Left err -> return $ Trap $ show err - Right _raw_state -> return $ Return _raw_state + Left err -> return $ Trap err + Right raw_state -> return $ Return raw_state rawQueryMethod :: RawState s -> MethodName -> Arg -> ST s (TrapOr Response) -rawQueryMethod (esref, cid, mods', inst) method arg = do - let es = (initalExecutionState cid (head (W._miMemories inst))) +rawQueryMethod (esref, cid, inst) method arg = do + let es = (initalExecutionState cid inst) { params = Params { param_dat = Just $ dat arg , param_caller = Just $ caller arg @@ -519,16 +475,16 @@ rawQueryMethod (esref, cid, mods', inst) method arg = do } } result <- runExceptT $ withES esref es $ - W.invokeByName mods' inst (T.pack $ "canister_query " ++ method) [W.I64 0] + invokeExport inst ("canister_query " ++ method) [I64 0] case result of - Left err -> return $ Trap $ show err + Left err -> return $ Trap err Right (_, es') | Just r <- response es' -> return $ Return r | otherwise -> return $ Trap "No response" rawUpdateMethod :: RawState s -> MethodName -> Arg -> ST s (TrapOr ({- List MethodCall, -} Maybe Response)) -rawUpdateMethod (esref, cid, mods', inst) method arg = do - let es = (initalExecutionState cid (head (W._miMemories inst))) +rawUpdateMethod (esref, cid, inst) method arg = do + let es = (initalExecutionState cid inst) { params = Params { param_dat = Just $ dat arg , param_caller = Just $ caller arg @@ -538,7 +494,7 @@ rawUpdateMethod (esref, cid, mods', inst) method arg = do } result <- runExceptT $ withES esref es $ - W.invokeByName mods' inst (T.pack $ "canister_update " ++ method) [W.I64 0] + invokeExport inst ("canister_update " ++ method) [I64 0] case result of - Left err -> return $ Trap $ show err + Left err -> return $ Trap err Right (_, es') -> return $ Return (response es') diff --git a/ic-stub/src/IC/Wasm/Winter.hs b/ic-stub/src/IC/Wasm/Winter.hs new file mode 100644 index 00000000000..44b86fd4ea9 --- /dev/null +++ b/ic-stub/src/IC/Wasm/Winter.hs @@ -0,0 +1,103 @@ +module IC.Wasm.Winter + ( Module + , parseModule + , exportedFunctions + , Imports + , HostFunc + , W.Value(..) + , W.StackType + , W.ValueType(..) + , W.Address + , W.Size + , getBytes + , setBytes + , initialize + , Instance + , invokeExport + ) +where + +import qualified Data.ByteString.Lazy as BS +import Control.Monad.Identity +import Control.Monad.Except +import qualified Data.Map as M +import qualified Data.IntMap as IM +import qualified Data.Text.Lazy as T +import Control.Monad.ST +import Data.Binary.Get (runGetOrFail) +import Data.Default.Class (Default (..)) +import qualified Data.Vector as V + +import qualified Wasm.Binary.Decode as W +import qualified Wasm.Exec.Eval as W +import qualified Wasm.Runtime.Func as W +import qualified Wasm.Runtime.Instance as W +import qualified Wasm.Runtime.Memory as W +import qualified Wasm.Syntax.AST as W +import qualified Wasm.Syntax.Types as W +import qualified Wasm.Syntax.Values as W +import qualified Wasm.Syntax.Memory as W + +type Instance s = (IM.IntMap (W.ModuleInst Identity (ST s)), W.ModuleInst Identity (ST s)) + +type HostFunc s = ExceptT String (ST s) [W.Value] + +type Imports s = [(String, [(String, W.StackType, W.StackType, [W.Value] -> HostFunc s)])] + +type Module = W.Module Identity + +parseModule :: BS.ByteString -> Either String Module +parseModule bytes = case runGetOrFail W.getModule bytes of + Left (_,_,err) -> Left err + Right (_,_,wasm_mod) -> Right wasm_mod + + +initialize :: Module -> Imports s -> ExceptT String (ST s) (Instance s) +initialize mod imps = withExceptT show $ do + let names = M.fromList (zip (map (T.pack . fst) imps) [1..]) + mods = IM.fromList $ zip [1..] + [ (W.emptyModuleInst def) + { W._miGlobals = [ ] + , W._miTables = [ ] + , W._miMemories = [ ] + , W._miFuncs = [ ] + , W._miExports = M.fromList + [ (,) (T.pack fname) $ W.ExternFunc $ + W.allocHostEff (W.FuncType arg_ty ret_ty) + (\ args -> runExceptT $ f args) + | (fname, arg_ty, ret_ty, f) <- funcs + ] + } + | (_name, funcs) <- imps + ] + (ref, inst) <- W.initialize (Identity mod) names mods + let mods' = IM.insert ref inst mods + return (mods', inst) + + +exportedFunctions :: Module -> [String] +exportedFunctions wasm_mod = + [ T.unpack (W._exportName e) + | Identity e <- W._moduleExports wasm_mod + , W.FuncExport {} <- return $ W._exportDesc e + ] + + +invokeExport :: Instance s -> String -> [W.Value] -> ExceptT String (ST s) [W.Value] +invokeExport (mods', inst) method args = + withExceptT show $ + W.invokeByName mods' inst (T.pack method) args + + +getBytes :: Instance s -> W.Address -> W.Size -> ExceptT String (ST s) BS.ByteString +getBytes (_, inst) ptr len = do + let mem = head (W._miMemories inst) + vec <- withExceptT show $ W.loadBytes mem ptr len + return $ BS.pack $ V.toList vec + +setBytes :: Instance s -> W.Address -> BS.ByteString -> ExceptT String (ST s) () +setBytes (_, inst) ptr blob = do + let mem = head (W._miMemories inst) + withExceptT show $ + W.storeBytes mem (fromIntegral ptr) (V.fromList (BS.unpack blob)) + From 87749b6b8fe212bf16c491cabc987fff5749f632 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 13 Nov 2019 16:51:52 +0100 Subject: [PATCH 0570/1176] Split out canister code in own modules --- ic-stub/ic-stub.cabal | 3 + ic-stub/src/IC/Canister/Imp.hs | 235 ++++++++++++++++++++++++ ic-stub/src/IC/Canister/Pure.hs | 117 ++++++++++++ ic-stub/src/IC/Stub.hs | 308 +------------------------------- ic-stub/src/IC/Types.hs | 35 ++++ ic-stub/src/IC/Wasm/Winter.hs | 7 + ic-stub/src/ic-stub-run.hs | 7 +- 7 files changed, 401 insertions(+), 311 deletions(-) create mode 100644 ic-stub/src/IC/Canister/Imp.hs create mode 100644 ic-stub/src/IC/Canister/Pure.hs create mode 100644 ic-stub/src/IC/Types.hs diff --git a/ic-stub/ic-stub.cabal b/ic-stub/ic-stub.cabal index 252bdba109d..389eca3a0bb 100644 --- a/ic-stub/ic-stub.cabal +++ b/ic-stub/ic-stub.cabal @@ -9,6 +9,9 @@ executable ic-stub-run main-is: ic-stub-run.hs hs-source-dirs: src other-modules: IC.Stub + other-modules: IC.Types + other-modules: IC.Canister.Imp + other-modules: IC.Canister.Pure other-modules: IC.Wasm.Winter other-modules: IC.DRun.Parse build-depends: base >=4.11 && <5 diff --git a/ic-stub/src/IC/Canister/Imp.hs b/ic-stub/src/IC/Canister/Imp.hs new file mode 100644 index 00000000000..f14e4768b69 --- /dev/null +++ b/ic-stub/src/IC/Canister/Imp.hs @@ -0,0 +1,235 @@ +{-# LANGUAGE RankNTypes #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE TupleSections #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE FlexibleContexts #-} + +{-| +The canister interface, presented imperatively (or impurely), i.e. without rollback +-} +module IC.Canister.Imp + ( ESRef + , RawState + , runESST + , rawInitializeMethod + , rawUpdateMethod + , rawQueryMethod + , silently + ) +where + +import qualified Data.ByteString.Lazy as BS +import qualified Data.ByteString.Lazy.Char8 as BSC +import qualified Data.ByteString.Lazy.UTF8 as BSU +import Control.Monad.Primitive +import Control.Monad.ST +import Control.Monad.Except +import Control.Monad.Trans.State.Strict (StateT(..), evalStateT) +import Data.STRef +import Data.Maybe + +import IC.Types +import IC.Wasm.Winter + +data Params = Params + { param_dat :: Maybe Blob + , param_caller :: Maybe EntityId + , reject_code :: Int + , reject_message :: String + } + +data ExecutionState s = ExecutionState + { inst :: Instance s + , self_id :: CanisterId + , params :: Params + , response :: Maybe Response + , reply_data :: Blob + } + + + +initalExecutionState :: CanisterId -> Instance s -> ExecutionState s +initalExecutionState self_id inst = ExecutionState + { inst + , self_id + , params = Params Nothing Nothing 0 "" + , response = Nothing + , reply_data = mempty + } + +type ESRef s = (STRef s Bool, STRef s (Maybe (ExecutionState s))) + +newESRef :: ST s (ESRef s) +newESRef = (,) <$> newSTRef True <*> newSTRef Nothing + +runESST :: (forall s. ESRef s -> ST s a) -> a +runESST f = runST $ newESRef >>= f + +withES :: PrimMonad m => ESRef (PrimState m) -> ExecutionState (PrimState m) -> m a -> m (a, ExecutionState (PrimState m)) +withES (pref, esref) es f = do + before <- stToPrim $ readSTRef esref + unless (isNothing before) $ fail "withES with non-empty es" + stToPrim $ writeSTRef esref $ Just es + x <- f + es' <- stToPrim $ readSTRef esref + case es' of + Nothing -> fail "withES: ExecutionState lost" + Just es' -> do + stToPrim $ writeSTRef esref Nothing + return (x, es') + +silently :: PrimMonad m => ESRef (PrimState m) -> m x -> m x +silently (pref, esref) f = do + before <- stToPrim $ readSTRef pref + stToPrim $ writeSTRef pref False + x <- f + stToPrim $ writeSTRef pref before + return x + +getsES :: ESRef s -> (ExecutionState s -> b) -> ExceptT String (ST s) b +getsES (_, esref) f = lift (readSTRef esref) >>= \case + Nothing -> throwError "System API not available yet" + Just es -> return (f es) + +modES :: ESRef s -> (ExecutionState s -> ExecutionState s) -> ExceptT String (ST s) () +modES (_, esref) f = lift $ modifySTRef esref (fmap f) + + +putBytes :: PrimMonad m => ESRef (PrimState m) -> BS.ByteString -> m () +putBytes (pref, _esref) bytes = + stToPrim (readSTRef pref) >>= \case + True -> unsafeIOToPrim (BSC.putStrLn bytes) + False -> return () + + +systemAPI :: forall s. ESRef s -> Imports s +systemAPI esref = + [ (,) "ic" + [ (,,,) "trap" [i32, i32] [] $ \case + [v1,v2] -> throwError "explicit trap" + _ -> fail "ic.trap: invalid argument" + ] + , (,) "msg" + [ (,,,) "reject" [i64, i32, i32] [] msg_reject + , (,,,) "reply" [i64, i32, i32] [] msg_reply + , unimplemented "error_code" [i64] [i32] + , (,,,) "arg_data_copy" [i64, i32, i32, i32] [] arg_data_copy + , (,,,) "arg_data_size" [i64] [i32] arg_data_size + ] + , (,) "debug" + [ (,,,) "print" [i32, i32] [] debug_print + ] + ] + where + unimplemented name arg ret = (,,,) name arg ret $ + \_ -> throwError $ "unimplemented: " ++ name + + i32 = I32Type + i64 = I64Type + + debug_print :: [Value] -> HostFunc s + debug_print [I32 ptr, I32 len] = do + i <- getsES esref inst + bytes <- getBytes i (fromIntegral ptr) len + putBytes esref bytes + return [] + debug_print _ = fail "debug_print: invalid argument" + + arg_data_size :: [Value] -> HostFunc s + arg_data_size [I64 _nonce] = do + blob <- getsES esref (param_dat . params) + >>= maybe (throwError "arg_data_size: No argument") return + return [I32 (fromIntegral (BS.length blob))] + arg_data_size _ = fail "arg_data_size: invalid argument" + + arg_data_copy :: [Value] -> HostFunc s + arg_data_copy [I64 _nonce, I32 dst, I32 len, I32 offset] = do + blob <- getsES esref (param_dat . params) + >>= maybe (throwError "arg_data_size: No argument") return + unless (offset == 0) $ throwError "arg_data_copy: offset /= 0 not suppoted" + unless (len == fromIntegral (BS.length blob)) $ throwError "arg_data_copy: len not full blob not suppoted" + i <- getsES esref inst + -- TODO Bounds checking + setBytes i (fromIntegral dst) blob + return [] + arg_data_copy _ = fail "arg_data_copy: invalid argument" + + msg_reply :: [Value] -> HostFunc s + msg_reply [I64 _nonce, I32 ptr, I32 len] = do + i <- getsES esref inst + bytes <- getBytes i (fromIntegral ptr) len + modES esref (\es -> es { response = Just (Reply bytes) }) + return [] + msg_reply _ = fail "msg_reply: invalid argument" + + msg_reject :: [Value] -> HostFunc s + msg_reject [I64 _nonce, I32 ptr, I32 len] = do + i <- getsES esref inst + bytes <- getBytes i (fromIntegral ptr) len + let msg = BSU.toString bytes + modES esref (\es -> es { response = Just (Reject (RC_CANISTER_REJECT, msg)) }) + return [] + msg_reject _ = fail "msg_reply: invalid argument" + + + +ifStateIsPresent :: Monad m => m x -> StateT s m x -> StateT (Maybe s) m x +ifStateIsPresent err (StateT f) = StateT $ \case + Nothing -> (, Nothing) <$> err + Just es -> do + (r, es') <- f es + return (r, Just es') + +type RawState s = (ESRef s, CanisterId, Instance s) + +rawInitializeMethod :: ESRef s -> Module -> CanisterId -> Blob -> ST s (TrapOr (RawState s)) +rawInitializeMethod esref wasm_mod cid arg = do + result <- runExceptT $ do + inst <- initialize wasm_mod (systemAPI esref) + + -- invoke canister_init + when ("canister_init" `elem` exportedFunctions wasm_mod) $ + void $ withES esref (initalExecutionState cid inst) $ + invokeExport inst "canister_init" [I64 0] + + return (esref, cid, inst) + case result of + Left err -> return $ Trap err + Right raw_state -> return $ Return raw_state + +rawQueryMethod :: RawState s -> MethodName -> Arg -> ST s (TrapOr Response) +rawQueryMethod (esref, cid, inst) method arg = do + let es = (initalExecutionState cid inst) + { params = Params + { param_dat = Just $ dat arg + , param_caller = Just $ caller arg + , reject_code = 0 + , reject_message = "" + } + } + result <- runExceptT $ withES esref es $ + invokeExport inst ("canister_query " ++ method) [I64 0] + case result of + Left err -> return $ Trap err + Right (_, es') + | Just r <- response es' -> return $ Return r + | otherwise -> return $ Trap "No response" + +rawUpdateMethod :: RawState s -> MethodName -> Arg -> ST s (TrapOr ({- List MethodCall, -} Maybe Response)) +rawUpdateMethod (esref, cid, inst) method arg = do + let es = (initalExecutionState cid inst) + { params = Params + { param_dat = Just $ dat arg + , param_caller = Just $ caller arg + , reject_code = 0 + , reject_message = "" + } + } + + result <- runExceptT $ withES esref es $ + invokeExport inst ("canister_update " ++ method) [I64 0] + case result of + Left err -> return $ Trap err + Right (_, es') -> return $ Return (response es') + diff --git a/ic-stub/src/IC/Canister/Pure.hs b/ic-stub/src/IC/Canister/Pure.hs new file mode 100644 index 00000000000..8f3d8f8c032 --- /dev/null +++ b/ic-stub/src/IC/Canister/Pure.hs @@ -0,0 +1,117 @@ +{-# LANGUAGE TypeOperators #-} +{-# LANGUAGE ConstraintKinds #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE RankNTypes #-} + +{-# OPTIONS_GHC -Wmissing-signatures #-} +{-| +A “pure” implementation of canisters, using "IC.Canister.Imp", but just replaying when needed. +Note that this is quadratic in the number of update calls, so do not run such canisters for long. + +We could do some hacking caching of state using stable names, so that as long as no trap occurs, 'replay' is fast. +-} + +module IC.Canister.Pure + ( WasmState + , parseCanister + , CanisterModule(..) + , InitFunc, UpdateFunc, QueryFunc + ) + where + +import qualified Data.ByteString.Lazy as BS +import qualified Data.ByteString.Lazy.Char8 as BSC +import qualified Data.ByteString.Lazy.UTF8 as BSU +import qualified Data.Vector as V +import qualified Data.Map as M +import qualified Data.IntMap as IM +import qualified Data.Text.Lazy as T +import Data.List +import Data.Monoid +import Data.Maybe +import Control.Monad.State.Class +import Control.Monad.Trans.State.Strict (StateT(..), evalStateT) +import Control.Monad.Identity +import Control.Monad.Primitive +import Control.Monad.Except +import Control.Monad.ST +import Data.STRef +import Data.Binary.Get (runGetOrFail) +import Data.Default.Class (Default (..)) + +import IC.Types +import IC.Wasm.Winter (parseModule, exportedFunctions, Module) +import IC.Canister.Imp + +data WasmState + = WSInit Module CanisterId Blob + | WSUpdate MethodName Arg WasmState + +type InitFunc = (CanisterId, Blob) -> TrapOr WasmState +type UpdateFunc = WasmState -> TrapOr (WasmState, {- List MethodCall, -} Maybe Response) +type QueryFunc = WasmState -> TrapOr Response + +data CanisterModule = CanisterModule + { init_method :: InitFunc + , update_methods :: MethodName ↦ (Arg -> UpdateFunc) + , query_methods :: MethodName ↦ (Arg -> QueryFunc) + } + +parseCanister :: Blob -> Either String CanisterModule +parseCanister bytes = + case parseModule bytes of + Left err -> Left err + Right wasm_mod -> Right $ concreteToAbstractModule wasm_mod + +concreteToAbstractModule :: Module -> CanisterModule +concreteToAbstractModule wasm_mod = CanisterModule + { init_method = \(cid, arg) -> initializeMethod wasm_mod cid arg + , update_methods = M.fromList + [ (m, \arg wasm_state -> updateMethod m arg wasm_state) + | n <- exportedFunctions wasm_mod + , Just m <- return $ stripPrefix "canister_update " n + ] + , query_methods = M.fromList + [ (m, \arg wasm_state -> queryMethod m arg wasm_state) + | n <- exportedFunctions wasm_mod + , Just m <- return $ stripPrefix "canister_query " n + ] + } + +initializeMethod :: Module -> CanisterId -> Blob -> TrapOr WasmState +initializeMethod wasm_mod cid arg = runESST $ \esref -> do + result <- rawInitializeMethod esref wasm_mod cid arg + case result of + Trap err -> return $ Trap err + Return _raw_state -> return $ Return $ WSInit wasm_mod cid arg + +updateMethod :: MethodName -> Arg -> WasmState -> TrapOr (WasmState, Maybe Response) +updateMethod m arg s = runESST $ \esref -> do + rs <- replay esref s + tor <- rawUpdateMethod rs m arg + case tor of + Trap msg -> return $ Trap msg + Return r -> return $ Return (WSUpdate m arg s, r) + +queryMethod :: MethodName -> Arg -> WasmState -> TrapOr Response +queryMethod m arg s = runESST $ \esref -> do + rs <- replay esref s + rawQueryMethod rs m arg + + +replay :: ESRef s -> WasmState -> ST s (RawState s) +replay esref s = silently esref $ go s + where + trapToFail (Trap err) = fail "replay failed" + trapToFail (Return x) = return x + + go (WSInit wasm_mod cid arg) = + rawInitializeMethod esref wasm_mod cid arg >>= trapToFail + go (WSUpdate m arg s) = do + rs <- go s + _ <- rawUpdateMethod rs m arg >>= trapToFail + return rs + diff --git a/ic-stub/src/IC/Stub.hs b/ic-stub/src/IC/Stub.hs index 50ce942c418..bc87fc51cf1 100644 --- a/ic-stub/src/IC/Stub.hs +++ b/ic-stub/src/IC/Stub.hs @@ -4,7 +4,6 @@ {-# LANGUAGE LambdaCase #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE TypeFamilies #-} -{-# LANGUAGE TupleSections #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE RankNTypes #-} @@ -31,27 +30,8 @@ import Data.STRef import Data.Binary.Get (runGetOrFail) import Data.Default.Class (Default (..)) -import IC.Wasm.Winter - -type (↦) = M.Map - --- Basic types - -type Blob = BS.ByteString -type EntityId = Blob -type CanisterId = EntityId -type MethodName = String -type RequestID = Blob - --- Reject code - -data RejectCode - = RC_SYS_FATAL - | RC_SYS_TRANSIENT - | RC_DESTINATION_INVALID - | RC_CANISTER_REJECT - | RC_CANISTER_ERROR - deriving Show +import IC.Types +import IC.Canister.Pure rejectCode :: RejectCode -> Int rejectCode RC_SYS_FATAL = 1 @@ -90,25 +70,6 @@ data CompletionValue -- we need to be more typed than the public spec here -- Abstract canisters -data TrapOr a = Trap String | Return a - -data Arg = Arg - { dat :: Blob - , caller :: EntityId - } - deriving Show - -type InitFunc = (CanisterId, Blob) -> TrapOr WasmState -type UpdateFunc = WasmState -> TrapOr (WasmState, {- List MethodCall, -} Maybe Response) -type QueryFunc = WasmState -> TrapOr Response -data Response = Reply Blob | Reject (RejectCode, String) - -data CanisterModule = CanisterModule - { init_method :: InitFunc - , update_methods :: MethodName ↦ (Arg -> UpdateFunc) - , query_methods :: MethodName ↦ (Arg -> QueryFunc) - } - -- IC state data CanState = CanState @@ -233,268 +194,3 @@ runToCompletion = Nothing -> nextStarved >>= \case Just r -> starvedRequest r >> runToCompletion Nothing -> return () - --- Concrete canister - --- We model a WasmState as the history of the canister. This is slow, --- but allows us a correct implementation of persistence based on any --- WebAssembly engine. - -data WasmState - = WSInit Module CanisterId Blob - | WSUpdate MethodName Arg WasmState - -parseCanister :: Blob -> Either String CanisterModule -parseCanister bytes = - case parseModule bytes of - Left err -> Left err - Right wasm_mod -> Right $ concreteToAbstractModule wasm_mod - -concreteToAbstractModule :: Module -> CanisterModule -concreteToAbstractModule wasm_mod = CanisterModule - { init_method = \(cid, arg) -> initializeMethod wasm_mod cid arg - , update_methods = M.fromList - [ (m, \arg wasm_state -> updateMethod m arg wasm_state) - | n <- exportedFunctions wasm_mod - , Just m <- return $ stripPrefix "canister_update " n - ] - , query_methods = M.fromList - [ (m, \arg wasm_state -> queryMethod m arg wasm_state) - | n <- exportedFunctions wasm_mod - , Just m <- return $ stripPrefix "canister_query " n - ] - } - -data Params = Params - { param_dat :: Maybe Blob - , param_caller :: Maybe EntityId - , reject_code :: Int - , reject_message :: String - } - -data ExecutionState s = ExecutionState - { inst :: Instance s - , self_id :: CanisterId - , params :: Params - , response :: Maybe Response - , reply_data :: Blob - } - - - -initalExecutionState :: CanisterId -> Instance s -> ExecutionState s -initalExecutionState self_id inst = ExecutionState - { inst - , self_id - , params = Params Nothing Nothing 0 "" - , response = Nothing - , reply_data = mempty - } - -type ESRef s = (STRef s Bool, STRef s (Maybe (ExecutionState s))) - -newESRef :: ST s (ESRef s) -newESRef = (,) <$> newSTRef True <*> newSTRef Nothing - -runESST :: (forall s. ESRef s -> ST s a) -> a -runESST f = runST $ newESRef >>= f - -withES :: PrimMonad m => ESRef (PrimState m) -> ExecutionState (PrimState m) -> m a -> m (a, ExecutionState (PrimState m)) -withES (pref, esref) es f = do - before <- stToPrim $ readSTRef esref - unless (isNothing before) $ fail "withES with non-empty es" - stToPrim $ writeSTRef esref $ Just es - x <- f - es' <- stToPrim $ readSTRef esref - case es' of - Nothing -> fail "withES: ExecutionState lost" - Just es' -> do - stToPrim $ writeSTRef esref Nothing - return (x, es') - -silently :: PrimMonad m => ESRef (PrimState m) -> m x -> m x -silently (pref, esref) f = do - before <- stToPrim $ readSTRef pref - stToPrim $ writeSTRef pref False - x <- f - stToPrim $ writeSTRef pref before - return x - -getsES :: ESRef s -> (ExecutionState s -> b) -> ExceptT String (ST s) b -getsES (_, esref) f = lift (readSTRef esref) >>= \case - Nothing -> throwError "System API not available yet" - Just es -> return (f es) - -modES :: ESRef s -> (ExecutionState s -> ExecutionState s) -> ExceptT String (ST s) () -modES (_, esref) f = lift $ modifySTRef esref (fmap f) - - -putBytes :: PrimMonad m => ESRef (PrimState m) -> BS.ByteString -> m () -putBytes (pref, _esref) bytes = - stToPrim (readSTRef pref) >>= \case - True -> unsafeIOToPrim (BSC.putStrLn bytes) - False -> return () - - -systemAPI :: forall s. ESRef s -> Imports s -systemAPI esref = - [ (,) "ic" - [ (,,,) "trap" [i32, i32] [] $ \case - [v1,v2] -> throwError "explicit trap" - _ -> fail "ic.trap: invalid argument" - ] - , (,) "msg" - [ (,,,) "reject" [i64, i32, i32] [] msg_reject - , (,,,) "reply" [i64, i32, i32] [] msg_reply - , unimplemented "error_code" [i64] [i32] - , (,,,) "arg_data_copy" [i64, i32, i32, i32] [] arg_data_copy - , (,,,) "arg_data_size" [i64] [i32] arg_data_size - ] - , (,) "debug" - [ (,,,) "print" [i32, i32] [] debug_print - ] - ] - where - unimplemented name arg ret = (,,,) name arg ret $ - \_ -> throwError $ "unimplemented: " ++ name - - i32 = I32Type - i64 = I64Type - - debug_print :: [Value] -> HostFunc s - debug_print [I32 ptr, I32 len] = do - i <- getsES esref inst - bytes <- getBytes i (fromIntegral ptr) len - putBytes esref bytes - return [] - debug_print _ = fail "debug_print: invalid argument" - - arg_data_size :: [Value] -> HostFunc s - arg_data_size [I64 _nonce] = do - blob <- getsES esref (param_dat . params) - >>= maybe (throwError "arg_data_size: No argument") return - return [I32 (fromIntegral (BS.length blob))] - arg_data_size _ = fail "arg_data_size: invalid argument" - - arg_data_copy :: [Value] -> HostFunc s - arg_data_copy [I64 _nonce, I32 dst, I32 len, I32 offset] = do - blob <- getsES esref (param_dat . params) - >>= maybe (throwError "arg_data_size: No argument") return - unless (offset == 0) $ throwError "arg_data_copy: offset /= 0 not suppoted" - unless (len == fromIntegral (BS.length blob)) $ throwError "arg_data_copy: len not full blob not suppoted" - i <- getsES esref inst - -- TODO Bounds checking - setBytes i (fromIntegral dst) blob - return [] - arg_data_copy _ = fail "arg_data_copy: invalid argument" - - msg_reply :: [Value] -> HostFunc s - msg_reply [I64 _nonce, I32 ptr, I32 len] = do - i <- getsES esref inst - bytes <- getBytes i (fromIntegral ptr) len - modES esref (\es -> es { response = Just (Reply bytes) }) - return [] - msg_reply _ = fail "msg_reply: invalid argument" - - msg_reject :: [Value] -> HostFunc s - msg_reject [I64 _nonce, I32 ptr, I32 len] = do - i <- getsES esref inst - bytes <- getBytes i (fromIntegral ptr) len - let msg = BSU.toString bytes - modES esref (\es -> es { response = Just (Reject (RC_CANISTER_REJECT, msg)) }) - return [] - msg_reject _ = fail "msg_reply: invalid argument" - - - -ifStateIsPresent :: Monad m => m x -> StateT s m x -> StateT (Maybe s) m x -ifStateIsPresent err (StateT f) = StateT $ \case - Nothing -> (, Nothing) <$> err - Just es -> do - (r, es') <- f es - return (r, Just es') - -initializeMethod :: Module -> CanisterId -> Blob -> TrapOr WasmState -initializeMethod wasm_mod cid arg = runESST $ \esref -> do - result <- rawInitializeMethod esref wasm_mod cid arg - case result of - Trap err -> return $ Trap err - Return _raw_state -> return $ Return $ WSInit wasm_mod cid arg - -updateMethod :: MethodName -> Arg -> WasmState -> TrapOr (WasmState, Maybe Response) -updateMethod m arg s = runESST $ \esref -> do - rs <- replay esref s - tor <- rawUpdateMethod rs m arg - case tor of - Trap msg -> return $ Trap msg - Return r -> return $ Return (WSUpdate m arg s, r) - -queryMethod :: MethodName -> Arg -> WasmState -> TrapOr Response -queryMethod m arg s = runESST $ \esref -> do - rs <- replay esref s - rawQueryMethod rs m arg - -replay :: ESRef s -> WasmState -> ST s (RawState s) -replay esref s = silently esref $ go s - where - trapToFail (Trap err) = fail "replay failed" - trapToFail (Return x) = return x - - go (WSInit wasm_mod cid arg) = - rawInitializeMethod esref wasm_mod cid arg >>= trapToFail - go (WSUpdate m arg s) = do - rs <- go s - _ <- rawUpdateMethod rs m arg >>= trapToFail - return rs - -type RawState s = (ESRef s, CanisterId, Instance s) - -rawInitializeMethod :: ESRef s -> Module -> CanisterId -> Blob -> ST s (TrapOr (RawState s)) -rawInitializeMethod esref wasm_mod cid arg = do - result <- runExceptT $ do - inst <- initialize wasm_mod (systemAPI esref) - - -- invoke canister_init - when ("canister_init" `elem` exportedFunctions wasm_mod) $ - void $ withES esref (initalExecutionState cid inst) $ - invokeExport inst "canister_init" [I64 0] - - return (esref, cid, inst) - case result of - Left err -> return $ Trap err - Right raw_state -> return $ Return raw_state - -rawQueryMethod :: RawState s -> MethodName -> Arg -> ST s (TrapOr Response) -rawQueryMethod (esref, cid, inst) method arg = do - let es = (initalExecutionState cid inst) - { params = Params - { param_dat = Just $ dat arg - , param_caller = Just $ caller arg - , reject_code = 0 - , reject_message = "" - } - } - result <- runExceptT $ withES esref es $ - invokeExport inst ("canister_query " ++ method) [I64 0] - case result of - Left err -> return $ Trap err - Right (_, es') - | Just r <- response es' -> return $ Return r - | otherwise -> return $ Trap "No response" - -rawUpdateMethod :: RawState s -> MethodName -> Arg -> ST s (TrapOr ({- List MethodCall, -} Maybe Response)) -rawUpdateMethod (esref, cid, inst) method arg = do - let es = (initalExecutionState cid inst) - { params = Params - { param_dat = Just $ dat arg - , param_caller = Just $ caller arg - , reject_code = 0 - , reject_message = "" - } - } - - result <- runExceptT $ withES esref es $ - invokeExport inst ("canister_update " ++ method) [I64 0] - case result of - Left err -> return $ Trap err - Right (_, es') -> return $ Return (response es') diff --git a/ic-stub/src/IC/Types.hs b/ic-stub/src/IC/Types.hs new file mode 100644 index 00000000000..7034ce0f1d5 --- /dev/null +++ b/ic-stub/src/IC/Types.hs @@ -0,0 +1,35 @@ +{-# LANGUAGE TypeOperators #-} +module IC.Types where + +import qualified Data.ByteString.Lazy as BS +import qualified Data.Map as M + +type (↦) = M.Map + +-- Basic types + +type Blob = BS.ByteString +type EntityId = Blob +type CanisterId = EntityId +type MethodName = String +type RequestID = Blob + +data RejectCode + = RC_SYS_FATAL + | RC_SYS_TRANSIENT + | RC_DESTINATION_INVALID + | RC_CANISTER_REJECT + | RC_CANISTER_ERROR + deriving Show + +data Response = Reply Blob | Reject (RejectCode, String) + +-- Abstract canisters + +data TrapOr a = Trap String | Return a + +data Arg = Arg + { dat :: Blob + , caller :: EntityId + } + deriving Show diff --git a/ic-stub/src/IC/Wasm/Winter.hs b/ic-stub/src/IC/Wasm/Winter.hs index 44b86fd4ea9..93911204d02 100644 --- a/ic-stub/src/IC/Wasm/Winter.hs +++ b/ic-stub/src/IC/Wasm/Winter.hs @@ -1,3 +1,10 @@ +{-| + +This module provides a thin wrapper around the winter Wasm engine, exposing just +the bits needed by the IC stub. + +This is the interface at which one might plug in a different Wasm engine. +-} module IC.Wasm.Winter ( Module , parseModule diff --git a/ic-stub/src/ic-stub-run.hs b/ic-stub/src/ic-stub-run.hs index 3f809b7da29..577f4d8f09f 100644 --- a/ic-stub/src/ic-stub-run.hs +++ b/ic-stub/src/ic-stub-run.hs @@ -15,12 +15,9 @@ import qualified Data.Text as T import qualified Text.Hex as T import Text.Printf -import IC.DRun.Parse (Type(..), parseFile) +import IC.Types import IC.Stub - (Blob, EntityId, - IC, AsyncRequest(..), SyncRequest(..), requestId, ReqResponse(..), - RequestStatus(..), CompletionValue(..), - initialIC, submitRequest, readRequest, runToCompletion) +import IC.DRun.Parse (Type(..), parseFile) type DRun = StateT IC IO From f2717de24f6d6731e8e633044c031d9c77118b9c Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 13 Nov 2019 17:11:12 +0100 Subject: [PATCH 0571/1176] Make code -Wall safe and make sure nix complains if there are warnings --- ic-stub/ic-stub.cabal | 9 ++++++++- ic-stub/src/IC/Canister/Imp.hs | 29 ++++++++++++++--------------- ic-stub/src/IC/Canister/Pure.hs | 24 ++++-------------------- ic-stub/src/IC/DRun/Parse.hs | 16 +++++++++++----- ic-stub/src/IC/Stub.hs | 23 ++++++----------------- ic-stub/src/ic-stub-run.hs | 6 ++---- nix/haskell-packages.nix | 2 +- 7 files changed, 46 insertions(+), 63 deletions(-) diff --git a/ic-stub/ic-stub.cabal b/ic-stub/ic-stub.cabal index 389eca3a0bb..cda30427b5d 100644 --- a/ic-stub/ic-stub.cabal +++ b/ic-stub/ic-stub.cabal @@ -5,6 +5,10 @@ author: Joachim Breitner maintainer: mail@joachim-breitner.de build-type: Simple +flag release + default: False + description: Release build, warnings are errors + executable ic-stub-run main-is: ic-stub-run.hs hs-source-dirs: src @@ -31,4 +35,7 @@ executable ic-stub-run build-depends: utf8-string build-depends: hex-text default-language: Haskell2010 - ghc-options: -rtsopts + ghc-options: -rtsopts + ghc-options: -Wall -Wno-name-shadowing + if flag(release) + ghc-options: -Werror diff --git a/ic-stub/src/IC/Canister/Imp.hs b/ic-stub/src/IC/Canister/Imp.hs index f14e4768b69..4f807d8c745 100644 --- a/ic-stub/src/IC/Canister/Imp.hs +++ b/ic-stub/src/IC/Canister/Imp.hs @@ -25,7 +25,6 @@ import qualified Data.ByteString.Lazy.UTF8 as BSU import Control.Monad.Primitive import Control.Monad.ST import Control.Monad.Except -import Control.Monad.Trans.State.Strict (StateT(..), evalStateT) import Data.STRef import Data.Maybe @@ -67,7 +66,7 @@ runESST :: (forall s. ESRef s -> ST s a) -> a runESST f = runST $ newESRef >>= f withES :: PrimMonad m => ESRef (PrimState m) -> ExecutionState (PrimState m) -> m a -> m (a, ExecutionState (PrimState m)) -withES (pref, esref) es f = do +withES (_pref, esref) es f = do before <- stToPrim $ readSTRef esref unless (isNothing before) $ fail "withES with non-empty es" stToPrim $ writeSTRef esref $ Just es @@ -80,7 +79,7 @@ withES (pref, esref) es f = do return (x, es') silently :: PrimMonad m => ESRef (PrimState m) -> m x -> m x -silently (pref, esref) f = do +silently (pref, _esref) f = do before <- stToPrim $ readSTRef pref stToPrim $ writeSTRef pref False x <- f @@ -107,7 +106,7 @@ systemAPI :: forall s. ESRef s -> Imports s systemAPI esref = [ (,) "ic" [ (,,,) "trap" [i32, i32] [] $ \case - [v1,v2] -> throwError "explicit trap" + [_v1, _v2] -> throwError "explicit trap" _ -> fail "ic.trap: invalid argument" ] , (,) "msg" @@ -172,25 +171,25 @@ systemAPI esref = return [] msg_reject _ = fail "msg_reply: invalid argument" - - -ifStateIsPresent :: Monad m => m x -> StateT s m x -> StateT (Maybe s) m x -ifStateIsPresent err (StateT f) = StateT $ \case - Nothing -> (, Nothing) <$> err - Just es -> do - (r, es') <- f es - return (r, Just es') - type RawState s = (ESRef s, CanisterId, Instance s) -rawInitializeMethod :: ESRef s -> Module -> CanisterId -> Blob -> ST s (TrapOr (RawState s)) +rawInitializeMethod :: ESRef s -> Module -> CanisterId -> Arg -> ST s (TrapOr (RawState s)) rawInitializeMethod esref wasm_mod cid arg = do result <- runExceptT $ do inst <- initialize wasm_mod (systemAPI esref) + let es = (initalExecutionState cid inst) + { params = Params + { param_dat = Just $ dat arg + , param_caller = Just $ caller arg + , reject_code = 0 + , reject_message = "" + } + } + -- invoke canister_init when ("canister_init" `elem` exportedFunctions wasm_mod) $ - void $ withES esref (initalExecutionState cid inst) $ + void $ withES esref es $ invokeExport inst "canister_init" [I64 0] return (esref, cid, inst) diff --git a/ic-stub/src/IC/Canister/Pure.hs b/ic-stub/src/IC/Canister/Pure.hs index 8f3d8f8c032..b80fe1c24ea 100644 --- a/ic-stub/src/IC/Canister/Pure.hs +++ b/ic-stub/src/IC/Canister/Pure.hs @@ -22,35 +22,19 @@ module IC.Canister.Pure ) where -import qualified Data.ByteString.Lazy as BS -import qualified Data.ByteString.Lazy.Char8 as BSC -import qualified Data.ByteString.Lazy.UTF8 as BSU -import qualified Data.Vector as V import qualified Data.Map as M -import qualified Data.IntMap as IM -import qualified Data.Text.Lazy as T import Data.List -import Data.Monoid -import Data.Maybe -import Control.Monad.State.Class -import Control.Monad.Trans.State.Strict (StateT(..), evalStateT) -import Control.Monad.Identity -import Control.Monad.Primitive -import Control.Monad.Except import Control.Monad.ST -import Data.STRef -import Data.Binary.Get (runGetOrFail) -import Data.Default.Class (Default (..)) import IC.Types import IC.Wasm.Winter (parseModule, exportedFunctions, Module) import IC.Canister.Imp data WasmState - = WSInit Module CanisterId Blob + = WSInit Module CanisterId Arg | WSUpdate MethodName Arg WasmState -type InitFunc = (CanisterId, Blob) -> TrapOr WasmState +type InitFunc = (CanisterId, Arg) -> TrapOr WasmState type UpdateFunc = WasmState -> TrapOr (WasmState, {- List MethodCall, -} Maybe Response) type QueryFunc = WasmState -> TrapOr Response @@ -81,7 +65,7 @@ concreteToAbstractModule wasm_mod = CanisterModule ] } -initializeMethod :: Module -> CanisterId -> Blob -> TrapOr WasmState +initializeMethod :: Module -> CanisterId -> Arg -> TrapOr WasmState initializeMethod wasm_mod cid arg = runESST $ \esref -> do result <- rawInitializeMethod esref wasm_mod cid arg case result of @@ -105,7 +89,7 @@ queryMethod m arg s = runESST $ \esref -> do replay :: ESRef s -> WasmState -> ST s (RawState s) replay esref s = silently esref $ go s where - trapToFail (Trap err) = fail "replay failed" + trapToFail (Trap _err) = fail "replay failed" trapToFail (Return x) = return x go (WSInit wasm_mod cid arg) = diff --git a/ic-stub/src/IC/DRun/Parse.hs b/ic-stub/src/IC/DRun/Parse.hs index d8c44a2759f..ddf6f2c9efb 100644 --- a/ic-stub/src/IC/DRun/Parse.hs +++ b/ic-stub/src/IC/DRun/Parse.hs @@ -8,24 +8,30 @@ import Control.Exception data Type = Query | Update deriving Show type MethodName = String +type Payload = B.ByteString -type Ingress = (Type, String, B.ByteString) +type Ingress = (Type, String, Payload) parseFile :: FilePath -> IO [Ingress] parseFile input = do x <- parse <$> readFile input - evaluate (show x) -- hack to evaluate until we have a proper parser + _ <- evaluate (show x) -- hack to evaluate until we have a proper parser return x +parse :: String -> [Ingress] parse = map parseLine . lines +parseLine :: String -> Ingress parseLine l = case words l of [t,m,a] -> (parseType t, m, parseArg a) + _ -> error $ "Cannot parse: " ++ show l +parseType :: String -> Type parseType "ingress" = Update parseType "query" = Query parseType x = error $ "Invalid ingress type " ++ x +parseArg :: String -> Payload parseArg ('0':'x':xs) | Just x <- B.fromStrict <$> H.decodeHex (T.pack xs) = x parseArg ('"':xs) @@ -33,10 +39,10 @@ parseArg ('"':xs) where go "" = error "Missing terminating \"" go "\"" = [] - go ('\\':'x':a:b:xs) + go ('\\':'x':a:b:ys) | Just h <- H.decodeHex (T.pack [a,b]) - = B.unpack (B.fromStrict h) ++ go xs - go (c:xs) = fromIntegral (ord c) : go xs + = B.unpack (B.fromStrict h) ++ go ys + go (c:ys) = fromIntegral (ord c) : go ys parseArg x = error $ "Invalid argument " ++ x diff --git a/ic-stub/src/IC/Stub.hs b/ic-stub/src/IC/Stub.hs index bc87fc51cf1..29cea974a5c 100644 --- a/ic-stub/src/IC/Stub.hs +++ b/ic-stub/src/IC/Stub.hs @@ -12,23 +12,10 @@ module IC.Stub where import qualified Data.ByteString.Lazy as BS import qualified Data.ByteString.Lazy.Char8 as BSC -import qualified Data.ByteString.Lazy.UTF8 as BSU -import qualified Data.Vector as V import qualified Data.Map as M -import qualified Data.IntMap as IM -import qualified Data.Text.Lazy as T import Data.List -import Data.Monoid import Data.Maybe import Control.Monad.State.Class -import Control.Monad.Trans.State.Strict (StateT(..), evalStateT) -import Control.Monad.Identity -import Control.Monad.Primitive -import Control.Monad.Except -import Control.Monad.ST -import Data.STRef -import Data.Binary.Get (runGetOrFail) -import Data.Default.Class (Default (..)) import IC.Types import IC.Canister.Pure @@ -96,13 +83,13 @@ requestId :: AsyncRequest -> Blob requestId r = BSC.pack (show r) -- TODO: Implement request hashing findRequest :: RequestID -> IC -> Maybe (AsyncRequest, RequestStatus) -findRequest rid ic = find (\(r,s) -> requestId r == rid) (M.toList (requests ic)) +findRequest rid ic = find (\(r,_s) -> requestId r == rid) (M.toList (requests ic)) readRequest :: ICT m => SyncRequest -> m ReqResponse readRequest (StatusRequest rid) = gets (findRequest rid) >>= \case - Just (r,status) -> return status + Just (_r,status) -> return status Nothing -> return Unknown readRequest (QueryRequest method arg) = @@ -156,7 +143,7 @@ processRequest r@(InstallRequest can_mod arg) = Left err -> setReqStatus r (Rejected (RC_SYS_FATAL, "Parsing failed: " ++ err)) Right can_mod -> - case init_method can_mod (dummyCanisterId, arg) of + case init_method can_mod (dummyCanisterId, Arg arg dummyUserId) of Trap msg -> setReqStatus r (Rejected (RC_CANISTER_ERROR, "Initialization trapped: " ++ msg)) Return wasm_state -> do @@ -184,8 +171,10 @@ processRequest r@(UpdateRequest method arg) = do -- processRequest r = setReqStatus r (Rejected (0, "Unknown request type")) starvedRequest :: ICT m => AsyncRequest -> m () -starvedRequest r@(UpdateRequest method arg) = +starvedRequest r@(UpdateRequest _method _arg) = setReqStatus r $ Rejected (RC_CANISTER_ERROR, "canister did not respond") +starvedRequest r = + fail $ "Did not expect request " ++ show r ++ " to starve" runToCompletion :: ICT m => m () runToCompletion = diff --git a/ic-stub/src/ic-stub-run.hs b/ic-stub/src/ic-stub-run.hs index 577f4d8f09f..48146090d2d 100644 --- a/ic-stub/src/ic-stub-run.hs +++ b/ic-stub/src/ic-stub-run.hs @@ -4,13 +4,11 @@ module Main where import Options.Applicative -import Control.Monad (join, foldM_, forM_) +import Control.Monad (join, forM_) import Data.Monoid ((<>)) -import System.FilePath import qualified Data.ByteString.Lazy as B import Control.Monad.Trans import Control.Monad.Trans.State -import Control.Monad.IO.Class import qualified Data.Text as T import qualified Text.Hex as T import Text.Printf @@ -79,7 +77,7 @@ work wasm_file msg_file = do msgs <- parseFile msg_file flip evalStateT initialIC $ do - req_res <- submitAndRun (InstallRequest wasm B.empty) + _req_res <- submitAndRun (InstallRequest wasm B.empty) forM_ msgs $ \case (Query, method, arg) -> submitRead (QueryRequest method arg) (Update, method, arg) -> submitAndRun (UpdateRequest method arg) diff --git a/nix/haskell-packages.nix b/nix/haskell-packages.nix index 18771d4c46b..a4f63701836 100644 --- a/nix/haskell-packages.nix +++ b/nix/haskell-packages.nix @@ -104,5 +104,5 @@ nix: subpath: sha256 = "1gk5597fpw14y6pg1hklb1nv1psqf6wwaph8v2vx8fxlk41lyrv8"; }) "--no-check" {}; - ic-stub = self.callCabal2nix "ic-stub" (subpath "ic-stub") { }; + ic-stub = self.callCabal2nixWithOptions "ic-stub" (subpath "ic-stub") "-frelease" { }; } From cf9a6ebfa785ab552c890053dd9d4b9a45b95811 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 13 Nov 2019 17:12:16 +0100 Subject: [PATCH 0572/1176] More README --- ic-stub/README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ic-stub/README.md b/ic-stub/README.md index 1a13ee11470..2e5ae0936ae 100644 --- a/ic-stub/README.md +++ b/ic-stub/README.md @@ -20,7 +20,11 @@ present; in particular, error handling and input validation is incomplete. Installation of `ic-stub-run` ----------------------------- -From the top-level repository directory, run +If you use the top-level `nix-shell`, you should already have `ic-stub-run` in +your `PATH`. + +To install it into your normal environment, run from the top-level repository +directory. nix-env -i -f . -A ic-stub From ac37679ab643764eb6ed6a048091f527f0bbd5c5 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 13 Nov 2019 23:54:05 +0000 Subject: [PATCH 0573/1176] WIP, need to switch branch --- src/ir_def/arrange_ir.ml | 2 +- src/ir_def/check_ir.ml | 28 +++++++---- src/ir_def/construct.ml | 4 +- src/ir_def/construct.mli | 2 +- src/ir_def/freevars.ml | 2 +- src/ir_def/ir.ml | 4 +- src/ir_def/ir_effect.ml | 2 +- src/ir_interpreter/interpret_ir.ml | 9 ++-- src/ir_passes/async.ml | 11 +++-- src/ir_passes/await.ml | 12 +++-- src/ir_passes/rename.ml | 2 +- src/ir_passes/show.ml | 2 +- src/ir_passes/tailcall.ml | 2 +- src/lowering/desugar.ml | 6 +-- src/mo_def/arrange.ml | 4 +- src/mo_def/syntax.ml | 4 +- src/mo_frontend/definedness.ml | 2 +- src/mo_frontend/effect.ml | 2 +- src/mo_frontend/typing.ml | 31 +++++++----- src/mo_idl/mo_to_idl.ml | 4 +- src/mo_interpreter/interpret.ml | 6 +-- src/mo_types/arrange_type.ml | 18 +++---- src/mo_types/type.ml | 76 +++++++++++++++++++----------- src/mo_types/type.mli | 16 ++++--- src/mo_values/call_conv.ml | 11 +++-- src/mo_values/call_conv.mli | 2 +- 26 files changed, 157 insertions(+), 107 deletions(-) diff --git a/src/ir_def/arrange_ir.ml b/src/ir_def/arrange_ir.ml index ad4e25b7c30..8ffaf7d2d67 100644 --- a/src/ir_def/arrange_ir.ml +++ b/src/ir_def/arrange_ir.ml @@ -31,7 +31,7 @@ let rec exp e = match e.it with | LabelE (i, t, e) -> "LabelE" $$ [id i; typ t; exp e] | BreakE (i, e) -> "BreakE" $$ [id i; exp e] | RetE e -> "RetE" $$ [exp e] - | AsyncE e -> "AsyncE" $$ [exp e] + | AsyncE (tb, e, t) -> "AsyncE" $$ [typ_bind tb; exp e; typ t] | AwaitE e -> "AwaitE" $$ [exp e] | AssertE e -> "AssertE" $$ [exp e] | OptE e -> "OptE" $$ [exp e] diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 5ceca78703a..84ee8667b3b 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -170,7 +170,7 @@ let rec check_typ env typ : unit = | T.Returns -> check env' no_region (sort = T.Shared T.Write) "one-shot query function pointless" - | T.Promises -> + | T.Promises _ -> check env no_region env.flavor.Ir.has_async_typ "promising function in post-async flavor"; check env' no_region (sort <> T.Local) @@ -189,9 +189,9 @@ let rec check_typ env typ : unit = "promising function cannot be local:\n %s" (T.string_of_typ_expand typ); | T.Opt typ -> check_typ env typ - | T.Async typ -> + | T.Async (typ1, typ2) -> check env no_region env.flavor.Ir.has_async_typ "async in non-async flavor"; - let t' = T.promote typ in + let t' = T.promote typ2 in check_shared env no_region t' | T.Obj (sort, fields) -> List.iter (check_typ_field env (Some sort)) fields; @@ -549,24 +549,29 @@ let rec check_exp env (exp:Ir.exp) : unit = check_exp env exp1; typ exp1 <: T.throw; T.Non <: t (* vacuously true *) - | AsyncE exp1 -> + | AsyncE (tb, exp1, t0) -> check env.flavor.has_await "async expression in non-await flavor"; + check_typ env t0; + let c, tb, ce = check_open_typ_bind env tb in let t1 = typ exp1 in let env' = - {env with labs = T.Env.empty; rets = Some t1; async = true} in + {(adjoin_cons env ce) + with labs = T.Env.empty; rets = Some t1; async = true} in check_exp env' exp1; - t1 <: T.Any; - T.Async t1 <: t + let t1' = T.open_ [t0] (T.close [c] t1) in + t1' <: T.Any; (* vacuous *) + T.Async (t0,t1') <: t | AwaitE exp1 -> check env.flavor.has_await "await in non-await flavor"; check env.async "misplaced await"; check_exp env exp1; let t1 = T.promote (typ exp1) in - let t2 = try T.as_async_sub t1 + let (t0, t2) = try T.as_async_sub t1 with Invalid_argument _ -> error env exp1.at "expected async type, but expression has type\n %s" (T.string_of_typ_expand t1) in + (* TODO check t0 is in async context *) t2 <: t | AssertE exp1 -> check_exp env exp1; @@ -599,7 +604,7 @@ let rec check_exp env (exp:Ir.exp) : unit = let env' = adjoin_cons env ce in let ve = check_args env' args in List.iter (check_typ env') ret_tys; - check ((T.is_shared_sort sort && control = T.Promises) ==> isAsyncE exp) + check ((T.is_shared_sort sort && T.is_promising control) ==> isAsyncE exp) "shared function with async type has non-async body"; if T.is_shared_sort sort then List.iter (check_concrete env exp.at) ret_tys; let codom = T.codom control ret_tys in @@ -785,6 +790,11 @@ and check_open_typ_binds env typ_binds = let _ = check_typ_binds env tbs in cs, tbs, ce +and check_open_typ_bind env typ_bind = + match check_open_typ_binds env [typ_bind] with + | [c], [tb], ce -> c, tb, ce + | _ -> assert false + and close_typ_binds cs tbs = List.map (fun {con; bound} -> {Type.var = Con.name con; bound = Type.close cs bound}) tbs diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index 1b58e0c46f9..d018cafc45d 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -90,10 +90,10 @@ let primE prim es = note = { note_typ = ty; note_eff = e } } -let asyncE typ e = +let asyncE typ1 typ2 e = { it = PrimE (CPSAsync, [e]); at = no_region; - note = { note_typ = T.Async typ; note_eff = eff e } + note = { note_typ = T.Async (typ1, typ2); note_eff = eff e } } let assertE e = diff --git a/src/ir_def/construct.mli b/src/ir_def/construct.mli index cffd0af420f..712f5917e86 100644 --- a/src/ir_def/construct.mli +++ b/src/ir_def/construct.mli @@ -39,7 +39,7 @@ val seqP : pat list -> pat (* Expressions *) val primE : Ir.prim -> exp list -> exp -val asyncE : typ -> exp -> exp +val asyncE : typ -> typ -> exp -> exp val assertE : exp -> exp val awaitE : typ -> exp -> exp -> exp val ic_replyE : typ list -> exp -> exp diff --git a/src/ir_def/freevars.ml b/src/ir_def/freevars.ml index 9e158801167..1a2b520dd08 100644 --- a/src/ir_def/freevars.ml +++ b/src/ir_def/freevars.ml @@ -75,7 +75,7 @@ let rec exp e : f = match e.it with | LabelE (i, t, e) -> exp e | BreakE (i, e) -> exp e | RetE e -> exp e - | AsyncE e -> exp e + | AsyncE (_, e, _) -> exp e | AwaitE e -> exp e | AssertE e -> exp e | OptE e -> exp e diff --git a/src/ir_def/ir.ml b/src/ir_def/ir.ml index df1513673f8..0ce61378f7a 100644 --- a/src/ir_def/ir.ml +++ b/src/ir_def/ir.ml @@ -81,13 +81,13 @@ and exp' = | LabelE of id * Type.typ * exp (* label *) | BreakE of id * exp (* break *) | RetE of exp (* return *) - | AsyncE of exp (* async *) + | AsyncE of typ_bind * exp * Type.typ (* async *) | AwaitE of exp (* await *) | AssertE of exp (* assertion *) | DeclareE of id * Type.typ * exp (* local promise *) | DefineE of id * mut * exp (* promise fulfillment *) | FuncE of (* function *) - string * Type.func_sort * Type.control * typ_bind list * arg list * Type.typ list * exp + string * Type.func_sort * Type.typ Type.control * typ_bind list * arg list * Type.typ list * exp | ActorE of id * dec list * field list * Type.typ (* actor *) | NewObjE of Type.obj_sort * field list * Type.typ (* make an object *) | ThrowE of exp (* throw *) diff --git a/src/ir_def/ir_effect.ml b/src/ir_def/ir_effect.ml index e818cd03a66..6362a84e761 100644 --- a/src/ir_def/ir_effect.ml +++ b/src/ir_def/ir_effect.ml @@ -62,7 +62,7 @@ let rec infer_effect_exp (exp: exp) : T.eff = let e1 = effect_exp exp1 in let e2 = effect_cases cases in max_eff e1 e2 - | AsyncE exp1 -> + | AsyncE _ -> T.Triv | ThrowE _ | TryE _ diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index e9bc4e99401..8c6420be478 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -205,7 +205,7 @@ let make_async_message env id v = let open CC in let call_conv, f = V.as_func v in match call_conv with - | {sort = T.Shared s; control = T.Promises; _} -> + | {sort = T.Shared s; control = T.Promises _; _} -> Value.async_func s call_conv.n_args call_conv.n_res (fun v k -> let async = make_async () in actor_msg env id f v (fun v_async -> @@ -235,7 +235,7 @@ let make_replying_message env id v = let make_message env x cc v : V.value = match cc.CC.control with | T.Returns -> make_unit_message env x v - | T.Promises-> make_async_message env x v + | T.Promises _ -> make_async_message env x v | T.Replies -> make_replying_message env x v (* Literals *) @@ -467,7 +467,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = interpret_exp env exp1 (Lib.Option.value env.rets) | ThrowE exp1 -> interpret_exp env exp1 (Lib.Option.value env.throws) - | AsyncE exp1 -> + | AsyncE (_, exp1, _) -> assert env.flavor.has_await; async env exp.at @@ -511,7 +511,8 @@ and interpret_exp_mut env exp (k : V.value V.cont) = let v = make_message env x cc v in k v - | FuncE (x, sort, control, _typbinds, args, ret_typs, e) -> + | FuncE (x, sort, controlT, _typbinds, args, ret_typs, e) -> + let control = Type.map_control (fun _ -> ()) controlT in let cc = { sort; control; n_args = List.length args; n_res = List.length ret_typs } in let f = interpret_func env exp.at x args diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index 6759307f210..6e405adb2a8 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -134,7 +134,7 @@ let letEta e scope = let isAwaitableFunc exp = match typ exp with - | T.Func (T.Shared _,T.Promises,_,_,_) -> true + | T.Func (T.Shared _,T.Promises _,_,_,_) -> true | _ -> false (* Given sequence type ts, bind e of type (seq ts) to a @@ -186,11 +186,11 @@ let transform mode env prog = | Array t -> Array (t_typ t) | Tup ts -> Tup (List.map t_typ ts) | Func (s, c, tbs, ts1, ts2) -> - let c' = if c = T.Promises then T.Replies else c in + let c' = match c with T.Promises _ -> T.Replies | _ -> c in Func (s, c', List.map t_bind tbs, List.map t_typ ts1, List.map t_typ ts2) | Opt t -> Opt (t_typ t) | Variant fs -> Variant (List.map t_field fs) - | Async t -> t_async nary (t_typ t) + | Async (_, t) -> t_async nary (t_typ t) (* TBR exploit the index _ *) | Obj (s, fs) -> Obj (s, List.map t_field fs) | Mut t -> Mut (t_typ t) | Any -> Any @@ -287,7 +287,7 @@ let transform mode env prog = assert (typs = []); let ts1,ts2 = match typ exp1 with - | T.Func (T.Shared _, T.Promises,tbs,ts1,ts2) -> + | T.Func (T.Shared _, T.Promises _,tbs,ts1,ts2) -> List.map t_typ ts1, List.map t_typ ts2 | _ -> assert(false) in @@ -348,7 +348,8 @@ let transform mode env prog = match c with | Returns -> FuncE (x, s, c, t_typ_binds typbinds, t_args args, List.map t_typ ret_tys, t_exp exp) - | Promises -> + | Promises _ -> + (* TODO: deal with _ ^^^*) let ret_tys = List.map t_typ ret_tys in let args' = t_args args in let typbinds' = t_typ_binds typbinds in diff --git a/src/ir_passes/await.ml b/src/ir_passes/await.ml index b26ce5b3000..afeebe4f3f5 100644 --- a/src/ir_passes/await.ml +++ b/src/ir_passes/await.ml @@ -116,7 +116,8 @@ and t_exp' context exp' = | Some Label -> RetE (t_exp context exp1) | None -> assert false end - | AsyncE exp1 -> + | AsyncE (_tb, exp1, typ1) -> + (* TODO: this needs more work to account for _tb and _ty *) let exp1 = R.exp R.Renaming.empty exp1 in (* rename all bound vars apart *) (* add the implicit return/throw label *) let k_ret = fresh_cont (typ exp1) in @@ -126,8 +127,8 @@ and t_exp' context exp' = (LabelEnv.add Throw (Cont (ContVar k_fail)) LabelEnv.empty) in (* TODO: bind k_fail *) - (asyncE (typ exp1) ([k_ret; k_fail] -->* - c_exp context' exp1 (ContVar k_ret))).it + (asyncE typ1 (typ exp1) ([k_ret; k_fail] -->* + c_exp context' exp1 (ContVar k_ret))).it | TryE _ | ThrowE _ | AwaitE _ -> assert false (* these never have effect T.Triv *) @@ -352,7 +353,8 @@ and c_exp' context exp k = | Some Label | None -> assert false end - | AsyncE exp1 -> + | AsyncE (_, exp1, typ1) -> + (* TODO: this needs more thought *) (* add the implicit return label *) let k_ret = fresh_cont (typ exp1) in let k_fail = fresh_err_cont () in @@ -360,7 +362,7 @@ and c_exp' context exp k = LabelEnv.add Return (Cont (ContVar k_ret)) (LabelEnv.add Throw (Cont (ContVar k_fail)) LabelEnv.empty) in - k -@- (asyncE (typ exp1) ([k_ret; k_fail] -->* + k -@- (asyncE typ1 (typ exp1) ([k_ret; k_fail] -->* (c_exp context' exp1 (ContVar k_ret)))) | AwaitE exp1 -> let r = match LabelEnv.find_opt Throw context with diff --git a/src/ir_passes/rename.ml b/src/ir_passes/rename.ml index e60d6993711..c4e3e200bcb 100644 --- a/src/ir_passes/rename.ml +++ b/src/ir_passes/rename.ml @@ -54,7 +54,7 @@ and exp' rho e = match e with LabelE(i', t, exp rho' e) | BreakE (i, e) -> BreakE(id rho i,exp rho e) | RetE e -> RetE (exp rho e) - | AsyncE e -> AsyncE (exp rho e) + | AsyncE (tb, e, t) -> AsyncE (tb, exp rho e, t) | AwaitE e -> AwaitE (exp rho e) | AssertE e -> AssertE (exp rho e) | OptE e -> OptE (exp rho e) diff --git a/src/ir_passes/show.ml b/src/ir_passes/show.ml index 5348d8d2723..75ef4fe9061 100644 --- a/src/ir_passes/show.ml +++ b/src/ir_passes/show.ml @@ -124,7 +124,7 @@ and t_exp' env = function RetE (t_exp env exp1) | ThrowE exp1 -> ThrowE (t_exp env exp1) - | AsyncE e -> AsyncE (t_exp env e) + | AsyncE (tb, e, typ) -> AsyncE (tb, t_exp env e, typ) (* TBR *) | AwaitE e -> AwaitE (t_exp env e) | AssertE exp1 -> AssertE (t_exp env exp1) diff --git a/src/ir_passes/tailcall.ml b/src/ir_passes/tailcall.ml index dc5ca3ca8b7..a4088147a43 100644 --- a/src/ir_passes/tailcall.ml +++ b/src/ir_passes/tailcall.ml @@ -123,7 +123,7 @@ and exp' env e : exp' = match e.it with | RetE e -> RetE (tailexp { env with tail_pos = true } e) (* NB:^ e is always in tailposition, regardless of fst env *) | ThrowE e -> ThrowE (exp env e) (* TODO: make me a tail call *) - | AsyncE e -> AsyncE (exp { tail_pos = true; info = None } e) + | AsyncE (tb, e, typ) -> AsyncE (tb, exp { tail_pos = true; info = None } e, typ) | AwaitE e -> AwaitE (exp env e) | AssertE e -> AssertE (exp env e) | OptE e -> OptE (exp env e) diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 9ac36149747..3a373b4ab82 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -131,7 +131,7 @@ and exp' at note = function | S.BreakE (l, e) -> I.BreakE (l.it, exp e) | S.RetE e -> I.RetE (exp e) | S.ThrowE e -> I.ThrowE (exp e) - | S.AsyncE e -> I.AsyncE (exp e) + | S.AsyncE (tb, e, t) -> I.AsyncE (typ_bind tb, exp e, t.Source.note) | S.AwaitE e -> I.AwaitE (exp e) | S.AssertE e -> I.AssertE (exp e) | S.AnnotE (e, _) -> assert false @@ -367,7 +367,7 @@ and to_arg p : (Ir.arg * (Ir.exp -> Ir.exp)) = (fun e -> blockE [letP (pat p) v] e) -and to_args typ p : Ir.arg list * (Ir.exp -> Ir.exp) * T.control * T.typ list = +and to_args typ p : Ir.arg list * (Ir.exp -> Ir.exp) * T.typ T.control * T.typ list = let sort, control, n_args, res_tys = match typ with | Type.Func (sort, control, tbds, dom, res) -> @@ -405,7 +405,7 @@ and to_args typ p : Ir.arg list * (Ir.exp -> Ir.exp) * T.control * T.typ list = let wrap_under_async e = if T.is_shared_sort sort && control <> T.Returns then match e.it with - | Ir.AsyncE e' -> { e with it = Ir.AsyncE (wrap e') } + | Ir.AsyncE (tb, e',t) -> { e with it = Ir.AsyncE (tb, wrap e', t) } | _ -> assert false else wrap e in diff --git a/src/mo_def/arrange.ml b/src/mo_def/arrange.ml index 7a3377c9f2e..a7667805467 100644 --- a/src/mo_def/arrange.ml +++ b/src/mo_def/arrange.ml @@ -49,7 +49,7 @@ let rec exp e = match e.it with | DebugE e -> "DebugE" $$ [exp e] | BreakE (i, e) -> "BreakE" $$ [id i; exp e] | RetE e -> "RetE" $$ [exp e] - | AsyncE e -> "AsyncE" $$ [exp e] + | AsyncE (tb, e, t) -> "AsyncE" $$ [typ_bind tb; exp e; typ t] | AwaitE e -> "AwaitE" $$ [exp e] | AssertE e -> "AssertE" $$ [exp e] | AnnotE (e, t) -> "AnnotE" $$ [exp e; typ t] @@ -147,7 +147,7 @@ and typ t = match t.it with | VariantT cts -> "VariantT" $$ List.map typ_tag cts | TupT ts -> "TupT" $$ List.map typ ts | FuncT (s, tbs, at, rt) -> "FuncT" $$ [func_sort s] @ List.map typ_bind tbs @ [ typ at; typ rt] - | AsyncT t -> "AsyncT" $$ [typ t] + | AsyncT (t1, t2) -> "AsyncT" $$ [typ t1; typ t2] | ParT t -> "ParT" $$ [typ t] and dec d = match d.it with diff --git a/src/mo_def/syntax.ml b/src/mo_def/syntax.ml index dff44ea575a..aeb2495ce67 100644 --- a/src/mo_def/syntax.ml +++ b/src/mo_def/syntax.ml @@ -40,7 +40,7 @@ and typ' = | VariantT of typ_tag list (* variant *) | TupT of typ list (* tuple *) | FuncT of func_sort * typ_bind list * typ * typ (* function *) - | AsyncT of typ (* future *) + | AsyncT of typ * typ (* future *) | ParT of typ (* parentheses, used to control function arity only *) and typ_field = typ_field' Source.phrase @@ -141,7 +141,7 @@ and exp' = | BreakE of id * exp (* break *) | RetE of exp (* return *) | DebugE of exp (* debugging *) - | AsyncE of exp (* async *) + | AsyncE of typ_bind * exp * typ (* async *) | AwaitE of exp (* await *) | AssertE of exp (* assertion *) | AnnotE of exp * typ (* type annotation *) diff --git a/src/mo_frontend/definedness.ml b/src/mo_frontend/definedness.ml index 3eb1b082db9..364e8db8514 100644 --- a/src/mo_frontend/definedness.ml +++ b/src/mo_frontend/definedness.ml @@ -119,7 +119,7 @@ let rec exp msgs e : f = match e.it with | ForE (p, e1, e2) -> exp msgs e1 ++ (exp msgs e2 /// pat msgs p) | LabelE (i, t, e) -> exp msgs e | DebugE e -> exp msgs e - | AsyncE e -> exp msgs e + | AsyncE (_, e, _) -> exp msgs e | AwaitE e -> exp msgs e | AssertE e -> exp msgs e | AnnotE (e, t) -> exp msgs e diff --git a/src/mo_frontend/effect.ml b/src/mo_frontend/effect.ml index 5f89c72e0fd..a9501dbe954 100644 --- a/src/mo_frontend/effect.ml +++ b/src/mo_frontend/effect.ml @@ -82,7 +82,7 @@ let rec infer_effect_exp (exp:Syntax.exp) : T.eff = let e1 = effect_exp exp1 in let e2 = effect_cases cases in max_eff e1 e2 - | AsyncE exp1 -> + | AsyncE _ -> T.Triv | ThrowE _ | TryE _ diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 5d59b005854..2b2d574b0e8 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -215,12 +215,12 @@ let as_domT t = let as_codomT sort t = match sort, t.Source.it with - | T.Shared _, AsyncT t -> T.Promises, as_domT t + | T.Shared _, AsyncT (t1,t2) -> T.Promises t1 , as_domT t2 | _ -> T.Returns, as_domT t let check_shared_return env at sort c ts = match sort, c, ts with - | T.Shared _, T.Promises, _ -> () + | T.Shared _, T.Promises _, _ -> () | T.Shared T.Write, T.Returns, [] -> () | T.Shared T.Write, _, _ -> error env at "shared function must have syntactic return type `()` or `async `" | T.Shared T.Query, _, _ -> error env at "shared query function must have syntactic return type `async `" @@ -258,6 +258,7 @@ and check_typ' env typ : T.typ = let c, typs2 = as_codomT sort.it typ2 in let ts1 = List.map (check_typ env') typs1 in let ts2 = List.map (check_typ env') typs2 in + let c' = T.map_control (check_typ env') c in check_shared_return env typ2.at sort.it c ts2; if Type.is_shared_sort sort.it then @@ -273,14 +274,15 @@ and check_typ' env typ : T.typ = ) ts2; match c, ts2 with | T.Returns, [] when sort.it = T.Shared T.Write -> () - | T.Promises, _ -> () + | T.Promises _, _ -> () | _ -> error env typ2.at "shared function has non-async result type\n %s" (T.string_of_typ_expand (T.seq ts2)) - end; + end; + let tbs = List.map2 (fun c t -> {T.var = Con.name c; bound = t}) cs ts in - T.Func (sort.it, c, T.close_binds cs tbs, List.map (T.close cs) ts1, List.map (T.close cs) ts2) + T.Func (sort.it, c', T.close_binds cs tbs, List.map (T.close cs) ts1, List.map (T.close cs) ts2) | OptT typ -> T.Opt (check_typ env typ) | VariantT tags -> @@ -288,12 +290,13 @@ and check_typ' env typ : T.typ = (List.map (fun (tag : typ_tag) -> tag.it.tag) tags); let fs = List.map (check_typ_tag env) tags in T.Variant (List.sort T.compare_field fs) - | AsyncT typ -> + | AsyncT (typ0, typ) -> + let t0 = check_typ env typ0 in let t = check_typ env typ in if not env.pre && not (T.shared t) then error_shared env t typ.at "async has non-shared content type\n %s" (T.string_of_typ_expand t); - T.Async t + T.Async (t0,t) | ObjT (sort, fields) -> check_ids env "object" "field" (List.map (fun (field : typ_field) -> field.it.id) fields); @@ -694,13 +697,13 @@ and infer_exp'' env exp : T.typ = | Some typ -> typ | None -> {it = TupT []; at = no_region; note = T.Pre} in - let c, ts2 = as_codomT sort.it typ in - check_shared_return env typ.at sort.it c ts2; - + let cT, ts2 = as_codomT sort.it typ in + check_shared_return env typ.at sort.it cT ts2; let cs, ts, te, ce = check_typ_binds env typ_binds in let env' = adjoin_typs env te ce in let t1, ve = infer_pat_exhaustive env' pat in let ts2 = List.map (check_typ env') ts2 in + let c = T.map_control (check_typ env') cT in let codom = T.codom c ts2 in if not env.pre then begin let env'' = @@ -723,7 +726,7 @@ and infer_exp'' env exp : T.typ = ) ts2; match c, ts2 with | T.Returns, [] when sort.it = T.Shared T.Write -> () - | T.Promises, _ -> + | T.Promises _, _ -> if not (isAsyncE exp) then error env exp.at "shared function with async result type has non-async body" @@ -897,7 +900,7 @@ and infer_exp'' env exp : T.typ = error env exp.at "misplaced throw"; if not env.pre then check_exp env T.throw exp1; T.Non - | AsyncE exp1 -> + | AsyncE (_, exp1, _) -> if not in_shared then error_in [Flags.ICMode] env exp.at "unsupported async block"; let env' = @@ -907,9 +910,11 @@ and infer_exp'' env exp : T.typ = error_shared env t exp1.at "async type has non-shared content type\n %s" (T.string_of_typ_expand t); T.Async t - | AwaitE (exp1) -> + | AwaitE (typ_bind, exp1, typ0) -> if not env.async then error env exp.at "misplaced await"; + let t0 = check_typ env typ0 in + let t1 = infer_exp_promote {env with in_await = true} exp1 in (match exp1.it with | CallE (f, _, _) -> diff --git a/src/mo_idl/mo_to_idl.ml b/src/mo_idl/mo_to_idl.ml index dac21c4f9eb..8d9833d094a 100644 --- a/src/mo_idl/mo_to_idl.ml +++ b/src/mo_idl/mo_to_idl.ml @@ -107,7 +107,7 @@ let rec typ vs t = let fs1 = tuple vs ts1 in (match ts2, c with | [], Returns -> I.FuncT ([I.Oneway @@ no_region], fs1, []) - | ts, Promises -> + | ts, Promises _ -> I.FuncT ( (match s with | Query -> [I.Query @@ no_region] @@ -115,7 +115,7 @@ let rec typ vs t = fs1, tuple vs ts) | _ -> assert false) | Func _ -> assert false - | Async t -> assert false + | Async _ -> assert false | Mut t -> assert false | Pre -> assert false ) @@ no_region diff --git a/src/mo_interpreter/interpret.ml b/src/mo_interpreter/interpret.ml index 5da3190e8f0..a6ce385e0a3 100644 --- a/src/mo_interpreter/interpret.ml +++ b/src/mo_interpreter/interpret.ml @@ -213,7 +213,7 @@ let make_async_message env id v = let open CC in let call_conv, f = V.as_func v in match call_conv with - | {sort = T.Shared s; control = T.Promises; _} -> + | {sort = T.Shared s; control = T.Promises _; _} -> Value.async_func s call_conv.n_args call_conv.n_res (fun v k -> let async = make_async () in actor_msg env id f v (fun v_async -> @@ -228,7 +228,7 @@ let make_async_message env id v = let make_message env name t v : V.value = match t with | T.Func (_, T.Returns, _, _, _) -> make_unit_message env name v - | T.Func (_, T.Promises, _, _, _) -> make_async_message env name v + | T.Func (_, T.Promises _, _, _, _) -> make_async_message env name v | _ -> (* assert false *) failwith (Printf.sprintf "actorfield: %s %s" name (T.string_of_typ t)) @@ -556,7 +556,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = interpret_exp env exp1 (Lib.Option.value env.rets) | ThrowE exp1 -> interpret_exp env exp1 (Lib.Option.value env.throws) - | AsyncE exp1 -> + | AsyncE (_ ,exp1, _) -> async env exp.at (fun k' r -> diff --git a/src/mo_types/arrange_type.ml b/src/mo_types/arrange_type.ml index 51fb22d106a..0f03e7dba26 100644 --- a/src/mo_types/arrange_type.ml +++ b/src/mo_types/arrange_type.ml @@ -5,7 +5,7 @@ let ($$) head inner = Node (head, inner) let control c = match c with | Returns -> "Returns" - | Promises -> "Promises" + | Promises t -> "Promises ?" | Replies -> "Replies" let obj_sort s = match s with @@ -51,13 +51,15 @@ let rec typ (t:Type.typ) = match t with | Opt t -> "Opt" $$ [typ t] | Variant tfs -> "Variant" $$ List.map typ_field tfs | Tup ts -> "Tup" $$ List.map typ ts - | Func (s, c, tbs, at, rt) -> "Func" $$ [Atom (func_sort s); Atom (control c)] @ List.map typ_bind tbs @ [ "" $$ (List.map typ at); "" $$ (List.map typ rt)] - | Async t -> "Async" $$ [typ t] - | Mut t -> "Mut" $$ [typ t] - | Any -> Atom "Any" - | Non -> Atom "Non" - | Pre -> Atom "Pre" - | Typ c -> "Typ" $$ [con c] + | Func (s, c, tbs, at, rt) -> + "Func" $$ [Atom (func_sort s); Atom (control c)] @ + List.map typ_bind tbs @ [ "" $$ (List.map typ at); "" $$ (List.map typ rt)] + | Async (t1, t2) -> "Async" $$ [typ t1; typ t2] + | Mut t -> "Mut" $$ [typ t] + | Any -> Atom "Any" + | Non -> Atom "Non" + | Pre -> Atom "Pre" + | Typ c -> "Typ" $$ [con c] and typ_bind (tb : Type.bind) = tb.var $$ [typ tb.bound] diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index 1a277d0b5f1..56a945ada09 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -4,10 +4,11 @@ open Mo_config type lab = string type var = string -type control = - | Returns (* regular local function or one-shot shared function *) - | Promises (* shared function producing a future value upon call *) - | Replies (* (IR only): responds asynchronously using `reply` *) +type 'a control = + | Returns (* regular local function or one-shot shared function *) + | Promises of 'a (* shared function producing a future value upon call *) + | Replies (* (IR only): responds asynchronously using `reply` *) + type obj_sort = Object | Actor | Module type shared_sort = Query | Write type func_sort = Local | Shared of shared_sort @@ -45,8 +46,8 @@ and typ = | Array of typ (* array *) | Opt of typ (* option *) | Tup of typ list (* tuple *) - | Func of func_sort * control * bind list * typ list * typ list (* function *) - | Async of typ (* future *) + | Func of func_sort * (typ control) * bind list * typ list * typ list (* function *) + | Async of typ * typ (* future *) | Mut of typ (* mutable type *) | Any (* top *) | Non (* bottom *) @@ -61,9 +62,21 @@ and kind = | Def of bind list * typ | Abs of bind list * typ + (* Function sorts *) let is_shared_sort sort = sort <> Local +let is_promising c = + match c with + | Promises _ -> true + | _ -> false + +let map_control f c = + match c with + | Promises x -> Promises (f x) + | Replies -> Replies + | Returns -> Returns + (* Constructors *) @@ -134,7 +147,7 @@ let prim = function let seq = function [t] -> t | ts -> Tup ts let codom c ts = match c with - | Promises -> Async (seq ts) + | Promises t -> Async (t, (seq ts)) | Returns -> seq ts | Replies -> Tup [] @@ -158,7 +171,7 @@ let rec shift i n t = let i' = i + List.length tbs in Func (s, c, List.map (shift_bind i' n) tbs, List.map (shift i' n) ts1, List.map (shift i' n) ts2) | Opt t -> Opt (shift i n t) - | Async t -> Async (shift i n t) + | Async (t1,t2) -> Async (shift i n t1, shift i n t2) | Obj (s, fs) -> Obj (s, List.map (shift_field n i) fs) | Variant fs -> Variant (List.map (shift_field n i) fs) | Mut t -> Mut (shift i n t) @@ -204,7 +217,7 @@ let rec subst sigma t = Func (s, c, List.map (subst_bind sigma') tbs, List.map (subst sigma') ts1, List.map (subst sigma') ts2) | Opt t -> Opt (subst sigma t) - | Async t -> Async (subst sigma t) + | Async (t1, t2) -> Async (subst sigma t1, subst sigma t2) | Obj (s, fs) -> Obj (s, List.map (subst_field sigma) fs) | Variant fs -> Variant (List.map (subst_field sigma) fs) | Mut t -> Mut (subst sigma t) @@ -259,7 +272,7 @@ let rec open' i ts t = let i' = i + List.length tbs in Func (s, c, List.map (open_bind i' ts) tbs, List.map (open' i' ts) ts1, List.map (open' i' ts) ts2) | Opt t -> Opt (open' i ts t) - | Async t -> Async (open' i ts t) + | Async (t1, t2) -> Async (open' i ts t1, open' i ts t2) | Obj (s, fs) -> Obj (s, List.map (open_field i ts) fs) | Variant fs -> Variant (List.map (open_field i ts) fs) | Mut t -> Mut (open' i ts t) @@ -347,7 +360,7 @@ let as_tup = function Tup ts -> ts | _ -> invalid "as_tup" let as_unit = function Tup [] -> () | _ -> invalid "as_unit" let as_pair = function Tup [t1; t2] -> t1, t2 | _ -> invalid "as_pair" let as_func = function Func (s, c, tbs, ts1, ts2) -> s, c, tbs, ts1, ts2 | _ -> invalid "as_func" -let as_async = function Async t -> t | _ -> invalid "as_async" +let as_async = function Async (t1, t2) -> (t1, t2) | _ -> invalid "as_async" let as_mut = function Mut t -> t | _ -> invalid "as_mut" let as_immut = function Mut t -> t | t -> t let as_typ = function Typ c -> c | _ -> invalid "as_typ" @@ -408,8 +421,8 @@ let as_mono_func_sub t = match promote t with | Non -> Any, Non | _ -> invalid "as_func_sub" let as_async_sub t = match promote t with - | Async t -> t - | Non -> Non + | Async (t1, t2) -> (t1, t2) + | Non -> Any, Non (* TBR *) | _ -> invalid "as_async_sub" @@ -474,7 +487,7 @@ let rec avoid' cons seen = function List.map (avoid' cons seen) ts2 ) | Opt t -> Opt (avoid' cons seen t) - | Async t -> Async (avoid' cons seen t) + | Async (t1, t2) -> Async (avoid' cons seen t1, avoid' cons seen t2) | Obj (s, fs) -> Obj (s, List.map (avoid_field cons seen) fs) | Variant fs -> Variant (List.map (avoid_field cons seen) fs) | Mut t -> Mut (avoid' cons seen t) @@ -512,8 +525,10 @@ let rec cons t cs = | (Prim _ | Any | Non | Pre) -> cs | Con (c, ts) -> List.fold_right cons ts (ConSet.add c cs) - | (Opt t | Async t | Mut t | Array t) -> + | (Opt t | Mut t | Array t) -> cons t cs + | Async (t1, t2) -> + cons t2 (cons t1 cs) | Tup ts -> List.fold_right cons ts cs | Func (s, c, tbs, ts1, ts2) -> let cs = List.fold_right cons_bind tbs cs in @@ -559,7 +574,8 @@ let concrete t = | Abs _ -> false | Def (_, t) -> go (open_ ts t) (* TBR this may fail to terminate *) ) - | Array t | Opt t | Async t | Mut t -> go t + | Array t | Opt t | Mut t -> go t + | Async (t1, t2) -> go t1 && go t2 | Tup ts -> List.for_all go ts | Obj (_, fs) | Variant fs -> List.for_all (fun f -> go f.typ) fs | Func (s, c, tbs, ts1, ts2) -> @@ -713,8 +729,9 @@ let rec rel_typ rel eq t1 t2 = rel_list rel_typ rel eq (List.map (open_ ts) t12) (List.map (open_ ts) t22) | None -> false ) - | Async t1', Async t2' -> - rel_typ rel eq t1' t2' + | Async (t11, t12), Async (t21,t22) -> + eq_typ rel eq t11 t21 && + rel_typ rel eq t12 t22 | Mut t1', Mut t2' -> eq_typ rel eq t1' t2' | Typ c1, Typ c2 -> @@ -834,8 +851,9 @@ let rec compatible_typ co t1 t2 = true | Variant tfs1, Variant tfs2 -> compatible_tags co tfs1 tfs2 - | Async t1', Async t2' -> - compatible_typ co t1' t2' + | Async (t11, t12), Async (t21, t22) -> + compatible_typ co t11 t21 && (* TBR *) + compatible_typ co t12 t22 | Func _, Func _ -> true | Typ _, Typ _ -> @@ -937,8 +955,9 @@ let rec lub' lubs glbs t1 t2 = s1 = s2 && c1 = c2 && List.(length bs1 = length bs2) && List.(length args1 = length args2 && length res1 = length res2) -> combine_func_parts s1 c1 bs1 args1 res1 bs2 args2 res2 lubs glbs glb' lub' - | Async t1', Async t2' -> - Async (lub' lubs glbs t1' t2') + | Async (t11, t12), Async (t21, t22) when eq t11 t21 -> + Async (t11, lub' lubs glbs t12 t22) + | Async _, Async _ -> Any | Con _, _ | _, Con _ -> (* TODO(rossberg): fix handling of bounds *) @@ -1009,8 +1028,9 @@ and glb' lubs glbs t1 t2 = s1 = s2 && c1 = c2 && List.(length bs1 = length bs2) && List.(length args1 = length args2 && length res1 = length res2) -> combine_func_parts s1 c1 bs1 args1 res1 bs2 args2 res2 lubs glbs lub' glb' - | Async t1', Async t2' -> - Async (glb' lubs glbs t1' t2') + | Async (t11, t12), Async (t21, t22) when eq t11 t21 -> + Async (t11, glb' lubs glbs t12 t22) + | Async _, Async _ -> Non | Con _, _ | _, Con _ -> (* TODO(rossberg): fix handling of bounds *) @@ -1181,7 +1201,8 @@ and string_of_control_cod c vs ts = let cod = string_of_cod vs ts in match c with | Returns -> cod - | Promises -> sprintf "async %s" cod + + | Promises t -> sprintf "async<%s> %s" (string_of_typ' vs t) cod | Replies -> sprintf "replies %s" cod and string_of_typ' vs t = @@ -1197,8 +1218,8 @@ and string_of_typ' vs t = (string_of_dom (vs' @ vs) ts1) (string_of_control_cod c (vs' @ vs) ts2) | Opt t -> sprintf "?%s" (string_of_typ_nullary vs t) - | Async t -> - sprintf "async %s" (string_of_typ_nullary vs t) + | Async (t1, t2) -> + sprintf "async<%s> %s" (string_of_typ' vs t1) (string_of_typ_nullary vs t2) | Obj (s, fs) -> sprintf "%s%s" (string_of_obj_sort s) (string_of_typ_nullary vs (Obj (Object, fs))) | Typ c -> @@ -1270,3 +1291,4 @@ let rec string_of_typ_expand t = | _ -> s let is_shared_sort sort = sort <> Local + diff --git a/src/mo_types/type.mli b/src/mo_types/type.mli index e980366e0f6..1f2497ba19b 100644 --- a/src/mo_types/type.mli +++ b/src/mo_types/type.mli @@ -3,7 +3,7 @@ type lab = string type var = string -type control = Returns | Promises | Replies +type 'a control = Returns | Promises of 'a | Replies type obj_sort = Object | Actor | Module type shared_sort = Query | Write type func_sort = Local | Shared of shared_sort @@ -41,8 +41,8 @@ and typ = | Array of typ (* array *) | Opt of typ (* option *) | Tup of typ list (* tuple *) - | Func of func_sort * control * bind list * typ list * typ list (* function *) - | Async of typ (* future *) + | Func of func_sort * (typ control) * bind list * typ list * typ list (* function *) + | Async of typ * typ (* future *) | Mut of typ (* mutable type *) | Any (* top *) | Non (* bottom *) @@ -60,6 +60,8 @@ and kind = (* Function sorts *) val is_shared_sort : func_sort -> bool +val is_promising : 'a control -> bool +val map_control : ('a -> 'b) -> 'a control -> 'b control (* Short-hands *) @@ -105,8 +107,8 @@ val as_opt : typ -> typ val as_tup : typ -> typ list val as_unit : typ -> unit val as_pair : typ -> typ * typ -val as_func : typ -> func_sort * control * bind list * typ list * typ list -val as_async : typ -> typ +val as_func : typ -> func_sort * (typ control) * bind list * typ list * typ list +val as_async : typ -> typ * typ val as_mut : typ -> typ val as_immut : typ -> typ val as_typ : typ -> con @@ -121,13 +123,13 @@ val as_unit_sub : typ -> unit val as_pair_sub : typ -> typ * typ val as_func_sub : func_sort -> int -> typ -> func_sort * bind list * typ * typ val as_mono_func_sub : typ -> typ * typ -val as_async_sub : typ -> typ +val as_async_sub : typ -> typ * typ (* Argument/result sequences *) val seq : typ list -> typ -val codom : control -> typ list -> typ +val codom : typ control -> typ list -> typ val as_seq : typ -> typ list (* This needs to go away *) val seq_of_tup : typ -> typ list val arity : typ -> int diff --git a/src/mo_values/call_conv.ml b/src/mo_values/call_conv.ml index 9e334c1d5c6..bd289db48ce 100644 --- a/src/mo_values/call_conv.ml +++ b/src/mo_values/call_conv.ml @@ -10,7 +10,7 @@ with their “calling convention”, and check them in calls. type call_conv = { sort: func_sort; - control : control; + control : unit control; n_args : int; n_res : int; } @@ -18,12 +18,17 @@ type t = call_conv let local_cc n m = { sort = Local; control = Returns; n_args = n; n_res = m} let message_cc s n = { sort = Shared s; control = Returns; n_args = n; n_res = 0} -let async_cc s n m = { sort = Shared s; control = Promises; n_args = n; n_res = m} +let async_cc s n m = { sort = Shared s; control = Promises (); n_args = n; n_res = m} let replies_cc s n m = { sort = Shared s; control = Replies; n_args = n; n_res = m} let call_conv_of_typ typ = match typ with | Func (sort, control, tbds, dom, res) -> + let control = match control with + | Promises t -> Promises () + | Returns -> Returns + | Replies -> Replies + in { sort; control; n_args = List.length dom; n_res = List.length res } | Non -> { sort = Local; control = Returns; n_args = 1; n_res = 1 } @@ -33,6 +38,6 @@ let string_of_call_conv {sort;control;n_args;n_res} = Printf.sprintf "(%s%i %s %i)" (string_of_func_sort sort) n_args - (match control with Returns -> "->" | Promises -> "@>" | Replies -> "#>") + (match control with Returns -> "->" | Promises _ -> "@>" | Replies -> "#>") n_res diff --git a/src/mo_values/call_conv.mli b/src/mo_values/call_conv.mli index 24fd4b318a1..0bfeb2e61a9 100644 --- a/src/mo_values/call_conv.mli +++ b/src/mo_values/call_conv.mli @@ -3,7 +3,7 @@ open Mo_types type call_conv = { sort: Type.func_sort; - control : Type.control; + control : unit Type.control; n_args : int; n_res : int; } From 9af980b214adbdc88c57b842c983cb1975d5be79 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Wed, 13 Nov 2019 14:48:11 +0100 Subject: [PATCH 0574/1176] Shorthand fields can have annvals too --- design/IDL.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/design/IDL.md b/design/IDL.md index 534736c4717..b13f9e44c6d 100644 --- a/design/IDL.md +++ b/design/IDL.md @@ -1122,8 +1122,8 @@ Analoguous to types, a few syntactic shorthands are supported that can be reduce | blob := vec { N;* } where N* are of bytes in the string, interpreted [as in the WebAssembly textual format](https://webassembly.github.io/spec/core/text/values.html#strings) ::= ... - | = := = - | := N = where N is either 0 or previous + 1 (only in records) + | = := = + | := N = where N is either 0 or previous + 1 (only in records) | := = null (only in variants) | := = null (only in variants) ``` From 2059045cb410cd2aa09335890f94a27e8dfe48f2 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 14 Nov 2019 09:19:28 +0100 Subject: [PATCH 0575/1176] Track winter master --- nix/haskell-packages.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nix/haskell-packages.nix b/nix/haskell-packages.nix index a4f63701836..46854d21277 100644 --- a/nix/haskell-packages.nix +++ b/nix/haskell-packages.nix @@ -98,10 +98,10 @@ nix: subpath: winter = self.callCabal2nixWithOptions "winter" (nix.fetchFromGitHub { - owner = "nomeata"; + owner = "dfinity"; repo = "winter"; - rev = "eca9fb8dd8ec4d02962db104721f855040f33720"; - sha256 = "1gk5597fpw14y6pg1hklb1nv1psqf6wwaph8v2vx8fxlk41lyrv8"; + rev = "2c9cfc593ab3c670858bc9773a70b35b6c3d89e1"; + sha256 = "092149z54yxi6kzwpm87ipnzf16x7qcyw4506ki48ivkmykycycl"; }) "--no-check" {}; ic-stub = self.callCabal2nixWithOptions "ic-stub" (subpath "ic-stub") "-frelease" { }; From 54766783c57a60a43d1040a664ab02e46dfe0b8c Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Thu, 14 Nov 2019 10:31:22 +0000 Subject: [PATCH 0576/1176] WIP --- src/mo_frontend/typing.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 2b2d574b0e8..91438a5965f 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -914,7 +914,7 @@ and infer_exp'' env exp : T.typ = if not env.async then error env exp.at "misplaced await"; let t0 = check_typ env typ0 in - + let c, tb, ce = check_open_typ_bind env tb in let t1 = infer_exp_promote {env with in_await = true} exp1 in (match exp1.it with | CallE (f, _, _) -> From 7b04b89e6e3b1f37fcf66727cdfed04cefb75452 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Thu, 14 Nov 2019 10:50:29 +0000 Subject: [PATCH 0577/1176] rename msg_error_code to msg_reject_code --- default.nix | 2 +- src/codegen/compile.ml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/default.nix b/default.nix index 1ffefc79b6c..13abda3ef1d 100644 --- a/default.nix +++ b/default.nix @@ -22,7 +22,7 @@ let dfinity-repo = import (builtins.fetchGit { name = "dfinity-sources"; url = "ssh://git@github.com/dfinity-lab/dfinity"; ref = "master"; - rev = "907aaadd6272d81ab9d9b02d9858fa8423192bfe"; + rev = "8f017216245d57fb7173f27cb395f6c0e35d2c47"; }) { system = nixpkgs.system; }; in let sdk = import (builtins.fetchGit { diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 9df62a4baba..c0fb8f7d98e 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -3047,7 +3047,7 @@ module Dfinity = struct E.add_func_import env "msg" "arg_data_copy" [I64Type; I32Type; I32Type; I32Type] []; E.add_func_import env "msg" "reply" [I64Type; I32Type; I32Type] []; E.add_func_import env "msg" "reject" [I64Type; I32Type; I32Type] []; - E.add_func_import env "msg" "error_code" [I64Type] [I32Type]; + E.add_func_import env "msg" "reject_code" [I64Type] [I32Type]; E.add_func_import env "ic" "trap" [I32Type; I32Type] [] | Flags.AncientMode -> E.add_func_import env "test" "print" [I32Type] []; @@ -3222,7 +3222,7 @@ module Dfinity = struct let error_code env = SR.UnboxedWord32, get_api_nonce env ^^ - system_call env "msg" "error_code" + system_call env "msg" "reject_code" end (* Dfinity *) From f239801666ab7023446cbb3a090366b464d56f12 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 14 Nov 2019 05:30:01 -0700 Subject: [PATCH 0578/1176] remove original (pre-variants) Trie module; rename Trie2 to Trie throughout; update README --- stdlib/Makefile | 16 +- stdlib/README.md | 327 +-- stdlib/docTable.mo | 3 +- .../examples/produce-exchange/serverActor.mo | 2 +- .../examples/produce-exchange/serverModel.mo | 2 +- .../produce-exchange/serverModelTypes.mo | 2 +- stdlib/trie.mo | 1981 +++++++++-------- stdlib/trie2.mo | 1468 ------------ stdlib/{set.mo => trieSet.mo} | 6 +- 9 files changed, 1114 insertions(+), 2693 deletions(-) delete mode 100644 stdlib/trie2.mo rename stdlib/{set.mo => trieSet.mo} (97%) diff --git a/stdlib/Makefile b/stdlib/Makefile index 8620467fa9d..8febddc6c11 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -35,11 +35,10 @@ TESTS=\ Option \ OptionTest \ Result \ - Set \ Text \ TextTest \ Trie \ - Trie2 \ + TrieSet \ ProduceExchange \ producerRemInventory \ retailerReserveMany \ @@ -135,10 +134,7 @@ $(OUTDIR)/TextTest.out: textTest.mo | $(OUTDIR) $(OUTDIR)/Trie.out: trie.mo | $(OUTDIR) $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ -$(OUTDIR)/Trie2.out:trie2.mo | $(OUTDIR) - $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/Set.out: set.mo | $(OUTDIR) +$(OUTDIR)/TrieSet.out: trieSet.mo | $(OUTDIR) $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ $(OUTDIR)/DocTable.out: docTable.mo | $(OUTDIR) @@ -164,8 +160,7 @@ docMd: \ $(DOCDIR)/list.md \ $(DOCDIR)/assocList.md \ $(DOCDIR)/trie.md \ - $(DOCDIR)/trie2.md \ - $(DOCDIR)/set.md \ + $(DOCDIR)/trieSet.md \ $(DOCDIR)/docTable.md \ $(DOCDIR)/examples/produce-exchange/README.md \ $(DOCDIR)/examples/produce-exchange/serverTypes.md \ @@ -188,9 +183,8 @@ docHtml: \ $(DOCDIR)/list.html \ $(DOCDIR)/assocList.html \ $(DOCDIR)/trie.html \ - $(DOCDIR)/trie2.html \ $(DOCDIR)/docTable.html \ - $(DOCDIR)/set.html \ + $(DOCDIR)/trieSet.html \ $(DOCDIR)/examples/produce-exchange/README.html \ $(DOCDIR)/examples/produce-exchange/serverTypes.html \ $(DOCDIR)/examples/produce-exchange/serverLang.html \ @@ -224,7 +218,7 @@ $(DOCDIR)/examples/produce-exchange/README.md: examples/produce-exchange/README. ## PRODUCE_EXCHANGE_SRC=\ - prelude.mo option.mo hash.mo list.mo assocList.mo trie2.mo docTable.mo result.mo \ + prelude.mo option.mo hash.mo list.mo assocList.mo trie.mo docTable.mo result.mo \ examples/produce-exchange/serverTypes.mo \ examples/produce-exchange/serverLang.mo \ examples/produce-exchange/serverModelTypes.mo \ diff --git a/stdlib/README.md b/stdlib/README.md index 77fd7573f59..80e9e33d79a 100644 --- a/stdlib/README.md +++ b/stdlib/README.md @@ -1,321 +1,30 @@ Motoko Standard Library ============================== -Prior Documentation -------------------------- +The standard library of Motoko. -- [(Jira Story)](https://dfinity.atlassian.net/browse/AST-31): -- Older [See #127](https://github.com/dfinity-lab/motoko/issues/127) +See [The Appendix Chapter](https://sdk.dfinity.org/language-guide/index.html#appendix-stdlib) +of [the Motoko Book](https://sdk.dfinity.org/language-guide/) for documentation with examples. --------------------------------------------------------------- +## Overview of modules -Produce Exchange -================= +We group the modules conceptually, and indicate the status of each as planned +(`[ ]`) or implemented and tested, at least partially (`[x]`). -We focus on explaining the role of these collections from perspective -of the [produce exchange example](https://github.com/dfinity-lab/motoko/tree/stdlib-examples/stdlib/examples/produce-exchange). +### Collections: -See also, the [library modules by priority](#library-modules-by-priority). +- [x] `Array` module +- [x] `List` module +- [x] `AssocList` module +- [ ] `Map` interface (e.g., implemented by `Trie` below, via a class) +- [ ] `Set` interface (e.g., implemented by `TrieSet` below, via a class) -[`DocTable`]($DOCURL/docTable.html) ----------- +### Low-level collections (wrappers provide above interfaces): -A _document table_ abstracts over a **mutable collection of _documents_**, -each _assigned a unique id_ when added to the table. +- [x] `TrieSet` module -- can implement `Set` above +- [x] `Trie` module -- can implement `Map` above -The table is essentially a mutable mapping, augmented with: +### Misc utilities -- a mechanism to generate distinct ids and assign them to new documents, and -- an associated shallow projection, from each document to its -associated shallower _information_ type, for use in server-to-client -messages. - -See also - [`Index`](#index), - [`Map`](#map), - [`Trie`](#trie) -and [`AssocList`](#assoclist). - -[`Trie`]($DOCURL/trie.html) ----------- - -Represent a finite map with a _canonical binary tree_, based on hashing each key. - -[`AssocList`]($DOCURL/assocList.html) ------------- - -Represent a finite map with an _association list_ a list of key-value pairs. - -[`List`]($DOCURL/list.html) ------------ - -Linked lists. - -------------------------------------------------------------------------------------- - -To do -========= - -`Trie2D` ----------- - -A Trie2D is a trie that maps each key to a _secondary trie_, representing a _second dimension_. - -A Trie2D represents a 2D mapping, but in a kind of _curried form_, -that permits efficient, eagerly-applied partial application of the -first dimension's keys. - -To do --- separate from existing `Trie` module - - -`Index` ----------- - -An _index_ abstracts over a **mutable finite map**_ with fixed key and -value types, perhaps implemented by a purely-functional data -structure. - -To do --- create as a simplified form of existing `DocTable` class - -See also - [`DocTable`](#doctable), - [`Map`](#index), - [`Trie`](#trie) -and [`AssocList`](#assoclist). - -`Map` -------- - -An abstraction for functional finite maps with fixed key and value -types. - - -To do --- create as a simplified form of existing `DocTable` class - -See also - [`Trie`](#trie) - [`AssocList`](#assoclist), - [`Index`](#index), -and [`DocTable`](#doctable). - - -`Hash` ------------ - -To do - -Convert iterable bit strings into compact hashes. - -Convert each compact hash into its canonical iterable bit string (but -not reversing the hash, of course!). - - -`Array` ------------ - -To do - -Concatenate arrays; query outputs are arrays of records, represented -either directly, or with a cursor. - - -`TrieCursor` ---------------- - -Provide navigational controls for a trie, e.g., holding query results. - -To do - - -`Bits` ---------- - -Bit strings - -Convert "everything", e.g., each kind of entity in a DFINITY canister -application, into its canonical iterable bit string, for the purposes of: - - - hashing it, e.g., for use as complex keys in databases or caches - - serializing it and de-serializing it - - representing in IDL / system messages / wire format - -To do - -**Open questions** - -- If, how and when will the compiler/language just support this stuff "for free"? -- versus, how much should we write as Motoko-based abstractions? - - ---------------------------------------------------------------- - -Library Modules, by priority -============================== - -Primary modules ------------------------ - -See also, the [produce exchange](#produce-exchange) use case. - - - [x] **List**: See [`List` module from SML Basis library](http://sml-family.org/Basis/list.html). - - [x] **Hashtrie**: Persistent maps, as functional hash tries. - - [x] **Set**: Persistent sets, based directly on persistent maps. - - [ ] **Hashtable**: Mutable maps, as imperative hash tables. - -Secondary modules ------------------------- - -These modules _may_ be useful in the collections library: - - [ ] **Stream**: Type def done; most operations are pending... - -Other modules ------------------ - -These modules are merely exercises (toys/examples), and _not_ essential to the collections library: - - [ ] **Thunk**: Type def and some operations are done. - - ----------------------------------------------------------------- - - -Performance considerations -==================================================================== - -After having a functioning specification, we will employ the thoughts -below toward getting better performance. - -The main thrust of the work on this canister is currently focused on -creating an executable prototype. - -At some point (near the end of our test suite components), we will -want to consider botj the **asymptotic** and **constant-factor** performance -properties of our implementation. - -In particular, this performance is phrased in terms of **workloads**, -executing update & query behavior over the PESS server definition -implementation. - -We shall vary workloads in kind and size, and measure space and time -usage of the Wasm VM running this implementation, in terms of the -standard library of collections implemented here. - -We shall compare the performance on fixed workloads across varying -representations of the `Map` data structure that we use. - -Notably, the one and only collection type used in this implementation -is the `Map` type. With two implementations: - - - [Association lists]() - - [Hash tries]() - -We use purely-functional data structures for `Map` since their design -permits `O(1)`-time/space for sharing, and their immutability makes -them suitable for mathematical reasoning. - -As explained below, the hash trie representation is asymptotically -efficient for large sizes; while association lists are not, they are -suitable for small sub-cases, including those where hash collisions -occur in the trie structure. - -These mathematical properties are practically important for affording -a reasonably-efficient executable specification, but they also suggest -even more optimized representations, with the same mathematical -properties. First, - -Hash tries ---------------------------------- - -Before considering other variations, we review the basic properties of -the hash trie representation. - -Crucially, the hash trie implementation of `Map` uses a _functional -representation_, with expected times as follows (expected time -analysis, because of hashing): - -``` - Trie.copy : O(1) - Trie.find : O(log n) - Trie.replace, .insert, .remove : O(log n) - Trie.merge, .split : O(log n) - Trie.union : O(n) - Trie.intersect : O(n) -``` - -Alternative representations ----------------------------- - -We consider variations of how to represent a `Map`, both as variations -of the hash trie, and as other representations as well (see below). - -First, we might consider validating the followin claim: - -> **Claim:** The asymptotic properties of the hash trie are ideal -> for a practical (infinitely-scalable) implementation of PESS. - -Before considering other representations, we should evaluate this -claim on randomly-generated use-cases of varying size, to simulate -realistic (but synthetic) workloads, and measure time and space usage -by the Wasm VM. - -Once we can generate performance plots, we should consider comparing -different representations for `Map` that still use a hash trie. - -Chunks -------- - -A simple variation of the hash trie uses **"chunks"** at the leaves, -to represent sub-maps of the threshhold size where the pointers -involved in the per-hash-bit branching no longer pays off. - -So, we may first consider additional implementations by varying the -details of these chunks: - - - when the basecase of the hash trie occurs, and - - how the basecase of the hash trie is represented - -We consider several simple, but practical representations of chunks below. - - -Association array representation: ---------------------------------------- - -Association arrays are optimized for cache locality. They each store -a key-value mapping as two arrays: one of keys, and one of values. To -find a key-value pair, do a linear-scan in the array of keys to -find the corresponding position of the value, in that array. Regrow -the two arrays by doubling, or some other scheme. - -``` - Aa.copy : O(n) - Aa.find : O(n) - Aa.replace, .insert, .remove : O(n) - Aa.merge, .split : O(n) -?? Aa.union : O(n) -?? Aa.intersect : O(n) -``` - -Hashtable representation: ---------------------------------------- - -A traditional hash table uses an array as a table, indexed by hashes. -It handles hash collisions somehow, perhaps by doing a simple linear -scan. It regrows the table by doubling, or some other scheme. It may -or may not shrink the table. - -``` - Htbl.copy : O(n) - Htbl.find : O(1) - Htbl.replace, .insert, .remove : O(1) - Htbl.merge, .split : O(n) -?? Htbl.union : O(n) -?? Htbl.intersect : O(n) -``` - -### Swiss tables - -Swiss tables are special implementations of imperative hash tables that try to be extra efficient, compared to other options: - - - [Swiss tables blog post](https://abseil.io/blog/20180927-swisstables) - - [Swiss tables in Rust](https://github.com/Amanieu/hashbrown) - - +- [x] `Prelude` module +- [x] `Hash` module diff --git a/stdlib/docTable.mo b/stdlib/docTable.mo index 4a04cc405b0..99d7e0844f1 100644 --- a/stdlib/docTable.mo +++ b/stdlib/docTable.mo @@ -1,7 +1,6 @@ import Hash "hash.mo"; -//import Trie "trie.mo"; -import Trie "trie2.mo"; +import Trie "trie.mo"; module { /** diff --git a/stdlib/examples/produce-exchange/serverActor.mo b/stdlib/examples/produce-exchange/serverActor.mo index 2ecb50a0275..abff3bddd30 100644 --- a/stdlib/examples/produce-exchange/serverActor.mo +++ b/stdlib/examples/produce-exchange/serverActor.mo @@ -11,7 +11,7 @@ import L = "serverLang.mo"; import Model = "serverModel.mo"; import Result = "../../result.mo"; -import Trie = "../../trie2.mo"; +import Trie = "../../trie.mo"; import List = "../../list.mo"; type List = List.List; diff --git a/stdlib/examples/produce-exchange/serverModel.mo b/stdlib/examples/produce-exchange/serverModel.mo index 2999da9e489..9ed579e0459 100644 --- a/stdlib/examples/produce-exchange/serverModel.mo +++ b/stdlib/examples/produce-exchange/serverModel.mo @@ -7,7 +7,7 @@ import M = "serverModelTypes.mo"; import List = "../../list.mo"; import Hash_ = "../../hash.mo"; import Option = "../../option.mo"; -import Trie = "../../trie2.mo"; +import Trie = "../../trie.mo"; import DT = "../../docTable.mo"; import Result = "../../result.mo"; diff --git a/stdlib/examples/produce-exchange/serverModelTypes.mo b/stdlib/examples/produce-exchange/serverModelTypes.mo index 9771661ff3e..6352769d368 100644 --- a/stdlib/examples/produce-exchange/serverModelTypes.mo +++ b/stdlib/examples/produce-exchange/serverModelTypes.mo @@ -1,5 +1,5 @@ import T = "serverTypes.mo"; -import Trie = "../../trie2.mo"; +import Trie = "../../trie.mo"; import DocTable = "../../docTable.mo"; diff --git a/stdlib/trie.mo b/stdlib/trie.mo index 4f2a56b0560..44181962b7b 100644 --- a/stdlib/trie.mo +++ b/stdlib/trie.mo @@ -1,8 +1,10 @@ +import P "prelude.mo"; +import Option "option.mo"; import H "hash.mo"; + import List "list.mo"; import AssocList "assocList.mo"; - module { /** @@ -25,91 +27,156 @@ Trees, Red-Black Trees) do not enjoy history independence, and are each more complex to implement (e.g., each requires "rebalancing"; these trees never do). -Assumptions -============= +*/ -Uniform depth assumption: ------------------------------- +/** +Representation +===================== -We make a simplifying assumption, for now: All defined paths in the -trie have a uniform length, the same as the number of bits of a -hash, starting at the LSB, that we use for indexing. +A hash trie is a binary trie, where each (internal) branch node +represents having distinguished its key-value pairs on a single bit of +the keys. -- If the number is too low, our expected O(log n) bounds become - expected O(n). +By following paths in the trie, we determine an increasingly smaller +and smaller subset of the keys. -- If the number is too high, we waste constant factors for - representing small sets/maps. +Each leaf node consists of an association list of key-value pairs. -In [future work](#adaptive-path-lengths), we can make this more robust -by making this number adaptive for each path, and based on the content -of the trie along that path. +We say that a leaf is valid if it contains no more than MAX_LEAF_COUNT +key-value pairs. -See [Future work](#future-work) below --------------------------------------- -*/ +Each non-empty trie node stores a count; we discuss that more below. -/** -Representation -===================== +### Adaptive depth -Below, we define the types used in the representation: +For small mappings, this "trie" structure just consists of a single +leaf, which contains up to MAX_LEAF_COUNT key-value pairs. + +By construction, the algorithms below enforce the invariant that no +leaf ever contains more than MAX_LEAF_COUNT key-value pairs: the +function `leaf` accepts a list, but subdivides it with branches until +it can actually construct valid leaves. Ongce distinguished, subsets +of keys tend to remain distinguished by the presence of these branches. + +### Cached counts - - **`Key`**, parameterized by a hashable type `K` - - **`Branch`**, for binary nodes with two tries. - - **`Leaf`**, for leaf nodes with no sub-tries. We use [association lists](#association-lists) there. - - We use **`null`** for the empty trie, and - - **`?Node`** represents all three possibilities until we have variants. +At each branch and leaf, we use a stored count to support a +memory-efficient `toArray` function, which itself relies on +per-element projection via `nth`; in turn, `nth` directly uses the +O(1)-time function `count` for achieving an acceptable level of +algorithmic efficiently. Notably, leaves are generally lists of +key-value pairs, and we do not store a count for each Cons cell in the +list. -See the full details in the definitions below: +### Details + +Below, we define the types used in the representation: */ +//let MAX_LEAF_COUNT = 4; // worse than 8, slightly +public let MAX_LEAF_COUNT = 8; // <-- beats both 4 and 16 for me, now +//let MAX_LEAF_COUNT = 16; +//let MAX_LEAF_COUNT = 32; + public let Hash = H.BitVec; public type Hash = Hash.t; public type List = List.List; public type AssocList = AssocList.AssocList; -public let HASH_BITS = 4; -//let HASH_BITS = 16; - +/** A `Key` for the trie has an associated hash value */ public type Key = { - // hash field: permits fast inequality checks, permits collisions; - // (eventually: permits incremental growth of deeper trie paths) + /** `hash` permits fast inequality checks, and permits collisions */ hash: Hash; - // key field: for conservative equality checks, after equal hashes. + /** `key` permits percise equality checks, but only used after equal hashes. */ key: K; }; -// Binary branch nodes -public type Branch = { - left:Trie; - right:Trie; +/** Equality function for two `Key`s, in terms of equality of `K`'s. */ +public func keyEq(keq:(K,K) -> Bool) : ((Key,Key) -> Bool) = { + func (key1:Key, key2:Key) : Bool = + label profile_trie_keyEq : Bool + (Hash.hashEq(key1.hash, key2.hash) and keq(key1.key, key2.key)) }; -// Leaf nodes are association lists of `Key`s where every key -// shares a common hash prefix, its (common) trie path. + +/** leaf nodes of trie consist of key-value pairs as a list. */ public type Leaf = { - keyvals:AssocList,V>; + count : Nat ; + keyvals : AssocList,V> ; }; -// XXX: See AST-42 -public type Node = { - left:Trie; - right:Trie; - keyvals:AssocList,V>; +/** branch nodes of the trie discriminate on a bit position of the keys' hashes. + we never store this bitpos; rather, + we enforce a style where this position is always known from context. +*/ +public type Branch = { + count : Nat ; + left : Trie ; + right : Trie ; }; -public type Trie = ?Node; +/** binary hash tries: either empty, a leaf node, or a branch node */ +public type Trie = { + #empty ; + #leaf : Leaf ; + #branch : Branch ; +}; -/** - Association lists - ----------------- - Notice above that the `Leaf` case uses a list of key-value pairs. +public func isValid (t:Trie, enforceNormal:Bool) : Bool { + func rec(t:Trie, bitpos:?Hash, bits:Hash, mask:Hash) : Bool { + switch t { + case (#empty) { + switch bitpos { + case null true; + case (?_) not enforceNormal; + } + }; + case (#leaf l) { + let len = List.len<(Key,V)>(l.keyvals); + ((len <= MAX_LEAF_COUNT) or (not enforceNormal)) + and + len == l.count + and + ( List.all<(Key,V)>( + l.keyvals, + func ((k:Key,v:V)):Bool{ + //{ debugPrint "testing hash..."; true } + //and + ((k.hash & mask) == bits) + or + { debugPrint "\nmalformed hash!:\n"; + debugPrintInt (word32ToNat(k.hash)); + debugPrint "\n (key hash) != (path bits): \n"; + debugPrintInt (word32ToNat(bits)); + debugPrint "\nmask : "; debugPrintInt (word32ToNat(mask)); + debugPrint "\n"; + false } + } + ) or + { debugPrint "one or more hashes are malformed"; false } + ) + }; + case (#branch b) { + let bitpos1 = switch bitpos { + case null (natToWord32(0)); + case (?bp) (natToWord32(word32ToNat(bp) + 1)) + }; + let mask1 = mask | (natToWord32(1) << bitpos1); + let bits1 = bits | (natToWord32(1) << bitpos1); + let sum = count(b.left) + count(b.right); + (b.count == sum or { debugPrint "malformed count"; false }) + and + rec(b.left, ?bitpos1, bits, mask1) + and + rec(b.right, ?bitpos1, bits1, mask1) + }; + } + }; + rec(t, null, 0, 0) +}; - See [this document]($DOCURL/assocList.html) for more details. -*/ /** Two-dimensional trie @@ -130,295 +197,253 @@ public type Trie3D = Trie >; /** Module interface =================== - - For non-public helpers used in these definitions, see below: - - - [Helpers 1](#helpers-for-hashing) - - [Helpers 2](#helpers-for-missing-variants) - */ -//let Trie = new { - - /** - `empty` - -------- - An empty trie. - */ - public func empty() : Trie = makeEmpty(); - - /** - `copy` - --------- - Purely-functional representation permits _O(1)_-time copy, via persistent sharing. - - */ - - public func copy(t : Trie) : Trie = t; - - /** - `replace` - --------- - replace the given key's value option with the given one, returning the previous one - */ - public func replace(t : Trie, k:Key, k_eq:(K,K)->Bool, v:?V) : (Trie, ?V) { - let key_eq = keyEq(k_eq); - // For `bitpos` in 0..HASH_BITS, walk the given trie and locate the given value `x`, if it exists. - func rec(t : Trie, bitpos:Nat) : (Trie, ?V) { - if ( bitpos < HASH_BITS ) { - switch t { - case null { (buildNewPath(bitpos, k, v), null) }; - case (?n) { - assertIsBin(t); - let bit = Hash.getHashBit(k.hash, bitpos); - // rebuild either the left or right path with the inserted (k,v) pair - if (not bit) { - let (l, v_) = rec(n.left, bitpos+1); - (?{left=l; right=n.right; keyvals=null; }, v_) - } - else { - let (r, v_) = rec(n.right, bitpos+1); - (?{left=n.left; right=r; keyvals=null; }, v_) - } - }; - } - } else { - // No more walking; we should be at a leaf now, by construction invariants. - switch t { - case null { (buildNewPath(bitpos, k, v), null) }; - case (?l) { - // Permit hash collisions by walking - // a list/array of KV pairs in each leaf: - let (kvs2, old_val) = - AssocList.replace,V>(l.keyvals, k, key_eq, v); - (?{left=null; right=null; keyvals=kvs2}, old_val) - }; - } - } - }; - rec(t, 0) - }; - - /** - `replaceThen` - ------------ - replace the given key's value in the trie, - and only if successful, do the success continuation, - otherwise, return the failure value - */ - public func replaceThen(t : Trie, k:Key, k_eq:(K,K)->Bool, v2:V, - success: (Trie, V) -> X, - fail: () -> X) - : X - { - let (t2, ov) = replace(t, k, k_eq, ?v2); - switch ov { - case (null) { /* no prior value; failure to remove */ fail() }; - case (?v1) { success(t2, v1) }; - } - }; - - /** - `insert` - ------------ - insert the given key's value in the trie; return the new trie, and the previous value associated with the key, if any - */ - public func insert(t : Trie, k:Key, k_eq:(K,K)->Bool, v:V) : (Trie, ?V) { - replace(t, k, k_eq, ?v) - }; - - /** - `insertFresh` - ---------------- - insert the given key's value in the trie; return the new trie; assert that no prior value is associated with the key - */ - public func insertFresh(t : Trie, k:Key, k_eq:(K,K)->Bool, v:V) : Trie { - let (t2, none) = replace(t, k, k_eq, ?v); - switch none { - case (null) (); - case (?_) assert false; - }; - t2 - }; - - /** - `insert2D` - --------------- - insert the given key's value in the 2D trie; return the new 2D trie. - */ - public func insert2D(t : Trie2D, - k1:Key, k1_eq:(K1,K1)->Bool, - k2:Key, k2_eq:(K2,K2)->Bool, - v:V) - : Trie2D - { - let inner = find>(t, k1, k1_eq); - let (updated_inner, _) = switch inner { - case (null) { insert(null, k2, k2_eq, v) }; - case (?inner) { insert(inner, k2, k2_eq, v) }; - }; - let (updated_outer, _) = { insert>(t, k1, k1_eq, updated_inner) }; - updated_outer; - }; - - /** - `insert3D` - --------------- - insert the given key's value in the trie; return the new trie; - */ - public func insert3D - (t : Trie3D, - k1:Key, k1_eq:(K1,K1)->Bool, - k2:Key, k2_eq:(K2,K2)->Bool, - k3:Key, k3_eq:(K3,K3)->Bool, - v:V - ) - : Trie3D - { - let inner1 = find>(t, k1, k1_eq); - let (updated_inner1, _) = switch inner1 { - case (null) { - insert>( - null, k2, k2_eq, - (insert(null, k3, k3_eq, v)).0 - ) - }; - case (?inner1) { - let inner2 = find>(inner1, k2, k2_eq); - let (updated_inner2, _) = switch inner2 { - case (null) { insert(null, k3, k3_eq, v) }; - case (?inner2) { insert(inner2, k3, k3_eq, v) }; - }; - insert>( inner1, k2, k2_eq, updated_inner2 ) - }; - }; - let (updated_outer, _) = { insert>(t, k1, k1_eq, updated_inner1) }; - updated_outer; - }; - - /** - `remove` - ------------- - remove the given key's value in the trie; return the new trie - */ - public func remove(t : Trie, k:Key, k_eq:(K,K)->Bool) : (Trie, ?V) { - replace(t, k, k_eq, null) - }; - - /** - `removeThen` - ------------ - remove the given key's value in the trie, - and only if successful, do the success continuation, - otherwise, return the failure value - */ - public func removeThen(t : Trie, k:Key, k_eq:(K,K)->Bool, - success: (Trie, V) -> X, - fail: () -> X) - : X - { - let (t2, ov) = replace(t, k, k_eq, null); - switch ov { - case (null) { /* no prior value; failure to remove */ fail() }; - case (?v) { success(t2, v) }; - } - }; - - - /** - `remove2D` - -------------- - remove the given key-key pair's value in the 2D trie; return the - new trie, and the prior value, if any. - */ - public func remove2D(t : Trie2D, - k1:Key, k1_eq:(K1,K1)->Bool, - k2:Key, k2_eq:(K2,K2)->Bool) - : (Trie2D, ?V) - { - switch (find>(t, k1, k1_eq)) { - case (null) { - (t, null) - }; - case (?inner) { - let (updated_inner, ov) = remove(inner, k2, k2_eq); - let (updated_outer, _) = { - insert>(t, k1, k1_eq, updated_inner) - }; - (updated_outer, ov) - }; - } - }; - - /** - `remove3D` - --------------- - remove the given key-key pair's value in the 3D trie; return the - new trie, and the prior value, if any. - */ - public func remove3D - (t : Trie3D, - k1:Key, k1_eq:(K1,K1)->Bool, - k2:Key, k2_eq:(K2,K2)->Bool, - k3:Key, k3_eq:(K3,K3)->Bool, - ) - : (Trie3D, ?V) - { - switch (find>(t, k1, k1_eq)) { - case (null) { - (t, null) - }; - case (?inner) { - let (updated_inner, ov) = remove2D(inner, k2, k2_eq, k3, k3_eq); - let (updated_outer, _) = { - insert>(t, k1, k1_eq, updated_inner) - }; - (updated_outer, ov) - }; - } - }; - + /** + `empty` + -------- + An empty trie. + */ +public func empty() : Trie = + #empty; + + /** + `count` + -------- + Get the number of key-value pairs in the trie, in constant time. + + ### Implementation notes + + `nth` directly uses this function `count` for achieving an + acceptable level of algorithmic efficiently. + + */ +public func count(t: Trie) : Nat = label profile_trie_count : Nat { + switch t { + case (#empty) 0; + case (#leaf l) l.count; + case (#branch b) b.count; + } + }; + + /** + `branch` + -------- + Construct a branch node, computing the count stored there. + */ +public func branch(l:Trie, r:Trie) : Trie = label profile_trie_branch : Trie { + let sum = count(l) + count(r); + #branch( + { + count=sum; + left=l; + right=r + } + ); + }; + + /** + `leaf` + -------- + Construct a leaf node, computing the count stored there. + + This helper function automatically enforces the MAX_LEAF_COUNT + by constructing branches as necessary; to do so, it also needs the bitpos + of the leaf. + + */ +public func leaf(kvs:AssocList,V>, bitpos:Nat) : Trie = label trie_leaf : Trie { + fromSizedList(null, kvs, bitpos) + }; + +public func fromList(kvs:AssocList,V>, bitpos:Nat) : Trie = + label profile_trie_fromList_begin : (Trie) { + func rec(kvs:AssocList,V>, bitpos:Nat) : Trie { + if ( List.isNil<(Key,V)>(kvs) ) + label profile_trie_fromList_end_empty : (Trie) { + #empty + } + else if ( List.lenIsEqLessThan<(Key,V)>(kvs, MAX_LEAF_COUNT - 1) ) + label profile_trie_fromList_end_validleaf : (Trie) { + let len = List.len<(Key,V)>(kvs); + #leaf{count=len;keyvals=kvs} + } + else if ( bitpos >= 31 ) + label profile_trie_fromList_end_bitposIs31 : (Trie) { + let len = List.len<(Key,V)>(kvs); + #leaf{count=len;keyvals=kvs} + } + else /* too many keys for a leaf, so introduce a branch */ + label profile_trie_fromList_branch : (Trie) { + let (l, r) = splitAssocList(kvs, bitpos); + branch(rec(l, bitpos + 1), rec(r, bitpos + 1)) + } + }; + rec(kvs, bitpos) + }; + + +public func fromSizedList(kvc:?Nat, kvs:AssocList,V>, bitpos:Nat) : Trie = + label profile_trie_fromList_begin : (Trie) { + func rec(kvc:?Nat, kvs:AssocList,V>, bitpos:Nat) : Trie { + switch kvc { + case null { + switch (List.lenClamp<(Key,V)>(kvs, MAX_LEAF_COUNT)) { + case null () /* fall through to branch case. */; + case (?len) { + return #leaf{count=len; keyvals=kvs} + }; + } + }; + case (?c) { + if ( c == 0 ) { + return #empty + } else if ( c <= MAX_LEAF_COUNT ) { + return #leaf{count=c; keyvals=kvs} + } else { + /* fall through to branch case */ + } + }; + }; + let (ls, l, rs, r) = splitSizedList(kvs, bitpos); + if ( ls == 0 and rs == 0 ) { + #empty + } else if (rs == 0 and ls <= MAX_LEAF_COUNT) { + #leaf{count=ls; keyvals=l} + } else if (ls == 0 and rs <= MAX_LEAF_COUNT) { + #leaf{count=rs; keyvals=r} + } else { + branch(rec(?ls, l, bitpos + 1), rec(?rs, r, bitpos + 1)) + } + }; + rec(kvc, kvs, bitpos) + }; + + /** + `copy` + --------- + Purely-functional representation permits _O(1)_-time copy, via persistent sharing. + */ +public func copy(t : Trie) : Trie = t; + + /** + `replace` + --------- + replace the given key's value option with the given one, returning the previous one + */ +public func replace(t : Trie, k:Key, k_eq:(K,K)->Bool, v:?V) : (Trie, ?V) = + label profile_trie_replace : (Trie, ?V) { + let key_eq = keyEq(k_eq); + + func rec(t : Trie, bitpos:Nat) : (Trie, ?V) = + label profile_trie_replace_rec : (Trie, ?V) { + switch t { + case (#empty) label profile_trie_replace_rec_empty : (Trie, ?V) { + let (kvs, _) = AssocList.replace,V>(null, k, key_eq, v); + (leaf(kvs, bitpos), null) + }; + case (#branch b) label profile_trie_replace_rec_branch : (Trie, ?V) { + let bit = Hash.getHashBit(k.hash, bitpos); + // rebuild either the left or right path with the inserted (k,v) pair + if (not bit) { + let (l, v_) = rec(b.left, bitpos+1); + (branch(l, b.right), v_) + } + else { + let (r, v_) = rec(b.right, bitpos+1); + (branch(b.left, r), v_) + } + }; + case (#leaf l) label profile_trie_replace_rec_leaf : (Trie, ?V) { + let (kvs2, old_val) = + AssocList.replace,V>(l.keyvals, k, key_eq, v); + (leaf(kvs2, bitpos), old_val) + }; + } + }; + let (to, vo) = rec(t, 0); + //assert(isValid(to, false)); + (to, vo) + }; + + /** + `insert` + ------------ + insert the given key's value in the trie; return the new trie, and the previous value associated with the key, if any + */ +public func insert(t : Trie, k:Key, k_eq:(K,K)->Bool, v:V) : (Trie, ?V) = + label profile_trie_insert : (Trie, ?V) { + replace(t, k, k_eq, ?v) + }; - /** - `find` - --------- - find the given key's value in the trie, or return null if nonexistent - */ - public func find(t : Trie, k:Key, k_eq:(K,K) -> Bool) : ?V { - let key_eq = keyEq(k_eq); - // For `bitpos` in 0..HASH_BITS, walk the given trie and locate the given value `x`, if it exists. - func rec(t : Trie, bitpos:Nat) : ?V { label profile_trie_find_rec : (?V) - if ( bitpos < HASH_BITS ) { - label profile_trie_find_bitpos_lt_hash_bits : (?V) - switch t { - case null { - label profile_trie_find_end_null : (?V) - // the trie may be "sparse" along paths leading to no keys, and may end early. - null - }; - case (?n) { - assertIsBin(t); - let bit = Hash.getHashBit(k.hash, bitpos); - if (not bit) { rec(n.left, bitpos+1) } - else { rec(n.right, bitpos+1) } - }; - } - } else { - label profile_trie_find_bitpos_gte_hash_bits : (?V) - // No more walking; we should be at a leaf now, by construction invariants. - switch t { - case null { null }; - case (?l) { - label profile_trie_find_end_assocList_find : (?V) - // Permit hash collisions by walking a list/array of KV pairs in each leaf: - AssocList.find,V>(l.keyvals, k, key_eq) - }; - } - } - }; - label profile_trie_find_begin : (?V) - rec(t, 0) - }; +/** + `find` + --------- + find the given key's value in the trie, or return null if nonexistent + */ +public func find(t : Trie, k:Key, k_eq:(K,K) -> Bool) : ?V = label profile_trie_find : (?V) { + let key_eq = keyEq(k_eq); + func rec(t : Trie, bitpos:Nat) : ?V = label profile_trie_find_rec : (?V) { + switch t { + case (#empty) { + label profile_trie_find_end_null : (?V) + null + }; + case (#leaf l) { + label profile_trie_find_end_assocList_find : (?V) + AssocList.find,V>(l.keyvals, k, key_eq) + }; + case (#branch b) { + let bit = Hash.getHashBit(k.hash, bitpos); + if (not bit) { + label profile_trie_find_branch_left : (?V) + rec(b.left, bitpos+1) + } + else { + label profile_trie_find_branch_right : (?V) + rec(b.right, bitpos+1) + } + }; + } + }; + rec(t, 0) + }; + + + + +public func splitAssocList(al:AssocList,V>, bitpos:Nat) + : (AssocList,V>, AssocList,V>) = + label profile_trie_splitAssocList : (AssocList,V>, AssocList,V>) + { + List.split<(Key,V)>( + al, + func ((k : Key, v : V)) : Bool { + not Hash.getHashBit(k.hash, bitpos) + } + ) + }; + +public func splitSizedList(l:AssocList,V>, bitpos:Nat) + : (Nat, AssocList,V>, Nat, AssocList,V>) = + label profile_trie_splitSizedList : (Nat, AssocList,V>, Nat, AssocList,V>) + { + func rec(l : AssocList,V>) : (Nat, AssocList,V>, Nat, AssocList,V>) = + label profile_trie_sized_split_rec : (Nat, AssocList,V>, Nat, AssocList,V>) { + switch l { + case null { (0, null, 0, null) }; + case (?((k,v),t)) { + let (cl, l, cr, r) = rec(t) ; + if (not Hash.getHashBit(k.hash, bitpos)){ + (cl + 1, ?((k,v),l), cr, r) + } else { + (cl, l, cr + 1, ?((k,v),r)) + } + }; + } + }; + rec(l) + }; /** `merge` @@ -435,49 +460,43 @@ public type Trie3D = Trie >; - [`prod`](#prod) */ - public func merge(tl:Trie, tr:Trie, k_eq:(K,K)->Bool): Trie { +public func merge(tl:Trie, tr:Trie, k_eq:(K,K)->Bool) : Trie = label profile_trie_merge : Trie { let key_eq = keyEq(k_eq); - func rec(tl:Trie, tr:Trie) : Trie { + func br(l:Trie, r:Trie) : Trie = branch(l,r); + func rec(bitpos:Nat, tl:Trie, tr:Trie) : Trie { + func lf(kvs:AssocList,V>) : Trie = leaf(kvs, bitpos); switch (tl, tr) { - case (null, _) { return tr }; - case (_, null) { return tl }; - case (?nl,?nr) { - switch (isBin(tl), - isBin(tr)) { - case (true, true) { - let t0 = rec(nl.left, nr.left); - let t1 = rec(nl.right, nr.right); - makeBin(t0, t1) - }; - case (false, true) { - assert false; - // XXX impossible, until we lift uniform depth assumption - tr - }; - case (true, false) { - assert false; - // XXX impossible, until we lift uniform depth assumption - tr - }; - case (false, false) { - /// handle hash collisions by using the association list: - makeLeaf( - AssocList.disj,V,V,V>( - nl.keyvals, nr.keyvals, - key_eq, - func (x:?V, y:?V):V = { - switch (x, y) { - case (null, null) {/* IMPOSSIBLE case: diverge. */ func x():V=x(); x()}; - case (null, ?v) v; - case (?v, _) v; - }} - )) - }; - } - }; + case (#empty, _) { return tr }; + case (_, #empty) { return tl }; + case (#leaf l1, #leaf l2) { + lf( + AssocList.disj,V,V,V>( + l1.keyvals, l2.keyvals, + key_eq, + func (x:?V, y:?V):V = { + switch (x, y) { + case (null, null) { P.unreachable() }; + case (null, ?v) v; + case (?v, _) v; + }} + ) + ) + }; + case (#leaf l, _) { + let (ll, lr) = splitAssocList(l.keyvals, bitpos); + rec(bitpos, br(lf ll, lf lr), tr) + }; + case (_, #leaf l) { + let (ll, lr) = splitAssocList(l.keyvals, bitpos); + rec(bitpos, tl, br(lf ll, lf lr)) + }; + case (#branch b1, #branch b2) { + br(rec(bitpos + 1, b1.left, b2.left), + rec(bitpos + 1, b1.right, b2.right)) + }; } }; - rec(tl, tr) + rec(0, tl, tr) }; /** @@ -487,76 +506,47 @@ public type Trie3D = Trie >; dynamic error if there are collisions in common keys between the left and right inputs. */ - public func mergeDisjoint(tl:Trie, tr:Trie, k_eq:(K,K)->Bool): Trie { +public func mergeDisjoint(tl:Trie, tr:Trie, k_eq:(K,K)->Bool): Trie = + label profile_trie_mergeDisjoint : Trie { let key_eq = keyEq(k_eq); - func rec(tl:Trie, tr:Trie) : Trie { + func br(l:Trie, r:Trie) : Trie = branch(l,r); + func rec(bitpos:Nat, tl:Trie, tr:Trie) : Trie = label profile_trie_mergeDisjoint_rec : Trie { + func lf(kvs:AssocList,V>) : Trie = leaf(kvs, bitpos); switch (tl, tr) { - case (null, _) { return tr }; - case (_, null) { return tl }; - case (?nl,?nr) { - switch (isBin(tl), - isBin(tr)) { - case (true, true) { - let t0 = rec(nl.left, nr.left); - let t1 = rec(nl.right, nr.right); - makeBin(t0, t1) - }; - case (false, true) { - assert(false); - // XXX impossible, until we lift uniform depth assumption - tr - }; - case (true, false) { - assert(false); - // XXX impossible, until we lift uniform depth assumption - tr - }; - case (false, false) { - /// handle hash collisions by using the association list: - makeLeaf( - AssocList.disj,V,V,V>( - nl.keyvals, nr.keyvals, - key_eq, - func (x:?V, y:?V):V = { - switch (x, y) { - case (null, null) { - /* IMPOSSIBLE case. */ - assert false; func x():V=x(); x() - }; - case (?_, ?_) { - /* INVALID case: left and right defined for the same key */ - assert false; func x():V=x(); x() - }; - case (null, ?v) v; - case (?v, null) v; - }} - )) - }; - } - }; + case (#empty, _) label profile_trie_mergeDisjoint_rec_emptyL : Trie { return tr }; + case (_, #empty) label profile_trie_mergeDisjoint_rec_emptyR : Trie { return tl }; + case (#leaf l1, #leaf l2) label profile_trie_mergeDisjoint_rec_leafPair : Trie { + lf( + AssocList.disjDisjoint,V,V,V>( + l1.keyvals, l2.keyvals, + func (x:?V, y:?V):V = { + switch (x, y) { + case (null, ?v) v; + case (?v, null) v; + case (_, _) P.unreachable(); + } + } + ) + ) + }; + case (#leaf l, _) label profile_trie_mergeDisjoint_rec_splitLeafL : Trie { + let (ll, lr) = splitAssocList(l.keyvals, bitpos); + rec(bitpos, br(lf ll, lf lr), tr) + }; + case (_, #leaf l) label profile_trie_mergeDisjoint_rec_splitLeafR : Trie { + let (ll, lr) = splitAssocList(l.keyvals, bitpos); + rec(bitpos, tl, br(lf ll, lf lr)) + }; + case (#branch b1, #branch b2) label profile_trie_mergeDisjoint_rec_branchPair : Trie { + branch( + rec(bitpos + 1, b1.left, b2.left), + rec(bitpos + 1, b1.right, b2.right) + ) + }; + } }; - rec(tl, tr) - }; - - - /** - `mergeDisjoint2D` - -------------- - - Like [`mergeDisjoint`](#mergedisjoint), except instead of merging a - pair, it merges the collection of dimension-2 sub-trees of a 2D - trie. - - */ - public func mergeDisjoint2D(t : Trie2D, k1_eq:(K1,K1)->Bool, k2_eq:(K2,K2)->Bool) - : Trie - { - foldUp, Trie> - ( t, - func (t1:Trie, t2:Trie):Trie { mergeDisjoint(t1, t2, k2_eq) }, - func (_:K1, t:Trie): Trie { t }, - null ) + rec(0, tl, tr) }; /** @@ -566,41 +556,42 @@ public type Trie3D = Trie >; the left trie whose keys are not present in the right trie; the values of the right trie are irrelevant. */ - public func diff(tl:Trie, tr:Trie, k_eq:(K,K)->Bool) : Trie { +public func diff(tl:Trie, tr:Trie, k_eq:(K,K)->Bool): Trie { let key_eq = keyEq(k_eq); - func rec(tl:Trie, tr:Trie) : Trie { + + func br1(l:Trie, r:Trie) : Trie = branch(l,r); + func br2(l:Trie, r:Trie) : Trie = branch(l,r); + + func rec(bitpos:Nat, tl:Trie, tr:Trie) : Trie { + func lf1(kvs:AssocList,V>) : Trie = leaf(kvs, bitpos); + func lf2(kvs:AssocList,W>) : Trie = leaf(kvs, bitpos); + switch (tl, tr) { - case (null, _) { return makeEmpty() }; - case (_, null) { return tl }; - case (?nl,?nr) { - switch (isBin(tl), - isBin(tr)) { - case (true, true) { - let t0 = rec(nl.left, nr.left); - let t1 = rec(nl.right, nr.right); - makeBin(t0, t1) - }; - case (false, true) { - assert false; - // XXX impossible, until we lift uniform depth assumption - tl - }; - case (true, false) { - assert false; - // XXX impossible, until we lift uniform depth assumption - tl - }; - case (false, false) { - assert(isLeaf(tl)); - assert(isLeaf(tr)); - makeLeaf( - AssocList.diff,V,W>(nl.keyvals, nr.keyvals, key_eq) - ) - }; - } - }; - }}; - rec(tl, tr) + case (#empty, _) { return #empty }; + case (_, #empty) { return tl }; + case (#leaf l1, #leaf l2) { + lf1( + AssocList.diff,V,W>( + l1.keyvals, l2.keyvals, + key_eq, + ) + ) + }; + case (#leaf l, _) { + let (ll, lr) = splitAssocList(l.keyvals, bitpos); + rec(bitpos, br1(lf1 ll, lf1 lr), tr) + }; + case (_, #leaf l) { + let (ll, lr) = splitAssocList(l.keyvals, bitpos); + rec(bitpos, tl, br2(lf2 ll, lf2 lr)) + }; + case (#branch b1, #branch b2) { + br1(rec(bitpos + 1, b1.left, b2.left), + rec(bitpos + 1, b1.right, b2.right)) + }; + } + }; + rec(0, tl, tr) }; /** @@ -626,66 +617,71 @@ public type Trie3D = Trie >; - [`prod`](#prod) */ - public func disj(tl:Trie, tr:Trie, - k_eq:(K,K)->Bool, vbin:(?V,?W)->X) +public func disj( + tl : Trie, + tr : Trie, + k_eq : (K,K)->Bool, + vbin : (?V,?W)->X + ) : Trie { let key_eq = keyEq(k_eq); - func recL(t:Trie) : Trie { + + func br1(l:Trie, r:Trie) : Trie = branch(l,r); + func br2(l:Trie, r:Trie) : Trie = branch(l,r); + + func br3(l:Trie, r:Trie) : Trie = branch(l,r); + func lf3(kvs:AssocList,X>, bitpos:Nat) : Trie = leaf(kvs, bitpos); + + /** empty right case; build from left only: */ + func recL(t:Trie, bitpos:Nat) : Trie { switch t { - case (null) null; - case (? n) { - switch (matchLeaf(t)) { - case (?_) { makeLeaf(AssocList.disj,V,W,X>(n.keyvals, null, key_eq, vbin)) }; - case _ { makeBin(recL(n.left), recL(n.right)) } - } + case (#empty) #empty; + case (#leaf l) { + lf3(AssocList.disj,V,W,X>(l.keyvals, null, key_eq, vbin), bitpos) }; - }}; - func recR(t:Trie) : Trie { + case (#branch(b)) { br3(recL(b.left,bitpos+1),recL(b.right,bitpos+1)) }; + } + }; + /** empty left case; build from right only: */ + func recR(t:Trie, bitpos:Nat) : Trie { switch t { - case (null) null; - case (? n) { - switch (matchLeaf(t)) { - case (?_) { makeLeaf(AssocList.disj,V,W,X>(null, n.keyvals, key_eq, vbin)) }; - case _ { makeBin(recR(n.left), recR(n.right)) } - } + case (#empty) #empty; + case (#leaf l) { + lf3(AssocList.disj,V,W,X>(null, l.keyvals, key_eq, vbin), bitpos) }; - }}; - func rec(tl:Trie, tr:Trie) : Trie { + case (#branch(b)) { br3(recR(b.left,bitpos+1),recR(b.right,bitpos+1)) }; + } + }; + + /** main recursion */ + func rec(bitpos:Nat, tl:Trie, tr:Trie) : Trie { + func lf1(kvs:AssocList,V>) : Trie = leaf(kvs, bitpos); + func lf2(kvs:AssocList,W>) : Trie = leaf(kvs, bitpos); switch (tl, tr) { - // empty-empty terminates early, all other cases do not. - case (null, null) { makeEmpty() }; - case (null, _ ) { recR(tr) }; - case (_, null) { recL(tl) }; - case (? nl, ? nr) { - switch (isBin(tl), - isBin(tr)) { - case (true, true) { - let t0 = rec(nl.left, nr.left); - let t1 = rec(nl.right, nr.right); - makeBin(t0, t1) - }; - case (false, true) { - assert false; - // XXX impossible, until we lift uniform depth assumption - makeEmpty() - }; - case (true, false) { - assert false; - // XXX impossible, until we lift uniform depth assumption - makeEmpty() - }; - case (false, false) { - assert(isLeaf(tl)); - assert(isLeaf(tr)); - makeLeaf( - AssocList.disj,V,W,X>(nl.keyvals, nr.keyvals, key_eq, vbin) - ) - }; - } + case (#empty, #empty) { #empty }; + case (#empty, _ ) { recR(tr, bitpos) }; + case (_, #empty) { recL(tl, bitpos) }; + case (#leaf l1, #leaf l2) { + lf3(AssocList.disj,V,W,X>(l1.keyvals, l2.keyvals, key_eq, vbin), bitpos) }; - }}; - rec(tl, tr) + case (#leaf l, _) { + let (ll, lr) = splitAssocList(l.keyvals, bitpos); + rec(bitpos, br1(lf1 ll, lf1 lr), tr) + }; + case (_, #leaf l) { + let (ll, lr) = splitAssocList(l.keyvals, bitpos); + rec(bitpos, tl, br2(lf2 ll, lf2 lr)) + }; + case (#branch b1, #branch b2) { + br3(rec(bitpos + 1, b1.left, b2.left), + rec(bitpos + 1, b1.right, b2.right)) + }; + + } + }; + + rec(0, tl, tr) }; /** @@ -707,48 +703,70 @@ public type Trie3D = Trie >; */ public func join(tl:Trie, tr:Trie, k_eq:(K,K)->Bool, vbin:(V,W)->X) - : Trie + : Trie = label profile_trie_join : Trie { let key_eq = keyEq(k_eq); - func rec(tl:Trie, tr:Trie) : Trie { + + func br1(l:Trie, r:Trie) : Trie = branch(l,r); + func br2(l:Trie, r:Trie) : Trie = branch(l,r); + func br3(l:Trie, r:Trie) : Trie = branch(l,r); + + func rec(bitpos:Nat, tl:Trie, tr:Trie) : Trie = label profile_trie_join_rec : Trie { + func lf1(kvs:AssocList,V>) : Trie = leaf(kvs, bitpos); + func lf2(kvs:AssocList,W>) : Trie = leaf(kvs, bitpos); + func lf3(kvs:AssocList,X>) : Trie = leaf(kvs, bitpos); + switch (tl, tr) { - case (null, null) { return makeEmpty() }; - case (null, ? nr) { return makeEmpty() }; - case (? nl, null) { return makeEmpty() }; - case (? nl, ? nr) { - switch (isBin(tl), - isBin(tr)) { - case (true, true) { - let t0 = rec(nl.left, nr.left); - let t1 = rec(nl.right, nr.right); - makeBin(t0, t1) - }; - case (false, true) { - assert false; - // XXX impossible, until we lift uniform depth assumption - makeEmpty() - }; - case (true, false) { - assert false; - // XXX impossible, until we lift uniform depth assumption - makeEmpty() - }; - case (false, false) { - assert(isLeaf(tl)); - assert(isLeaf(tr)); - makeLeaf( - AssocList.join,V,W,X>(nl.keyvals, nr.keyvals, key_eq, vbin) - ) - }; - } - } - }}; - rec(tl, tr) - }; + case (#empty, _) { #empty }; + case (_, #empty) { #empty }; + case (#leaf l1, #leaf l2) { + lf3(AssocList.join,V,W,X>(l1.keyvals, l2.keyvals, key_eq, vbin)) + }; + case (#leaf l, _) { + let (ll, lr) = splitAssocList(l.keyvals, bitpos); + rec(bitpos, br1(lf1 ll, lf1 lr), tr) + }; + case (_, #leaf l) { + let (ll, lr) = splitAssocList(l.keyvals, bitpos); + rec(bitpos, tl, br2(lf2 ll, lf2 lr)) + }; + case (#branch b1, #branch b2) { + br3(rec(bitpos + 1, b1.left, b2.left), + rec(bitpos + 1, b1.right, b2.right)) + }; + } + }; + rec(0, tl, tr) + }; /** + `foldUp` + ------------ + This operation gives a recursor for the internal structure of + tries. Many common operations are instantiations of this function, + either as clients, or as hand-specialized versions (e.g., see map, + mapFilter, exists and forAll below). + */ + public func foldUp(t:Trie, bin:(X,X)->X, leaf:(K,V)->X, empty:X) : X { + func rec(t:Trie) : X { + switch t { + case (#empty) { empty }; + case (#leaf l) { + AssocList.fold,V,X>( + l.keyvals, empty, + func (k:Key, v:V, x:X):X = + bin(leaf(k.key,v),x) + ) + }; + case (#branch(b)) { bin(rec(b.left), rec(b.right)) }; + } + }; + rec(t) + }; + + /** `prod` --------- @@ -780,7 +798,7 @@ public type Trie3D = Trie >; func merge (a:Trie, b:Trie) : Trie = mergeDisjoint(a, b, k3_eq); - /**- `foldUp` "squared"; something like "`foldUp^2((tl, tr), merge, (insert null >( tl, merge, func (k1:K1, v1:V1) : Trie { @@ -788,43 +806,209 @@ public type Trie3D = Trie >; tr, merge, func (k2:K2, v2:V2) : Trie { switch (op(k1, v1, k2, v2)) { - case null null; - case (?(k3, v3)) { (insert(null, k3, k3_eq, v3)).0 }; + case null #empty; + case (?(k3, v3)) { (insert(#empty, k3, k3_eq, v3)).0 }; } }, - null + #empty ) }, - null + #empty + ) + }; + + + /** + Build: An ADT for "Trie Builds" + ======================================== + + This module provides optimized variants of normal tries, for + (much!) more efficient PX retailer queries. + + The central insight is that for (unmaterialized) query results, we + do not need to actually build any resulting trie of the resulting + data, but rather, just need a collection of what would be in that + trie. Since query results can be large (quadratic in the DB size!), + avoiding the construction of this trie provides a considerable savings. + + To get this savings, we use an ADT for the operations that _would_ build this trie, + if evaluated. This structure specializes a rope: a balanced tree representing a + sequence. It is only as balanced as the tries from which we generate + these build ASTs. They have no intrinsic balance properties of their + own. + + */ + public module Build { + + /** Commands for building tries. + + For PL academics: Imagine commands for the IMP imperative language, + but where global memory consists of a single (anonymous) global trie */ + public type TrieBuild = { + #skip ; + #insert : (K, ?Hash, V) ; + #seq : { + count : Nat ; + left : TrieBuild ; + right : TrieBuild ; + } ; + }; + + public func buildCount(tb:TrieBuild) : Nat = + label profile_trie_buildCount : Nat { + switch tb { + case (#skip) 0; + case (#insert(_, _, _)) 1; + case (#seq(seq)) seq.count; + } + }; + + public func buildSeq(l:TrieBuild, r:TrieBuild) : TrieBuild = + label profile_trie_buildSeq : TrieBuild { + let sum = buildCount(l) + buildCount(r); + #seq { count = sum; left = l; right = r } + }; + + /** + `prodBuild` + --------------- + + Like `prod`, except do not actually do the insert calls, just + record them, as a (binary tree) data structure, isomorphic to the + recursion of this function (which is balanced, in expectation). + + See also: + + - [`prod`](#prod) + + */ + public func prodBuild( + tl :Trie, + tr :Trie, + op :(K1,V1,K2,V2) -> ?(K3,V3), + k3_eq :(K3,K3) -> Bool ) - }; + : TrieBuild + { + func outer_bin (a:TrieBuild, + b:TrieBuild) + : TrieBuild = + label profile_trie_prodBuild_outer_seqOfBranch : TrieBuild { + buildSeq(a, b) + }; + + func inner_bin (a:TrieBuild, + b:TrieBuild) + : TrieBuild = + label profile_trie_prodBuild_inner_seqOfBranch : TrieBuild { + buildSeq(a, b) + }; + + /**- "`foldUp` squared" (imagine two nested loops): */ + foldUp>( + tl, outer_bin, + func (k1:K1, v1:V1) : TrieBuild { + foldUp>( + tr, inner_bin, + func (k2:K2, v2:V2) : TrieBuild { + switch (op(k1, v1, k2, v2)) { + case null #skip; + case (?(k3, v3)) { #insert(k3, null, v3) }; + } + }, + #skip + ) + }, + #skip + ) + }; + + /** + `buildNth` + -------- + Project the nth key-value pair from the trie build. + + This position is meaningful only when the build contains multiple uses of one or more keys, otherwise it is not. + */ + public func buildNth(tb:TrieBuild, i:Nat) : ?(K, ?Hash, V) = label profile_triebuild_nth : (?(K, ?Hash, V)) { + func rec(tb:TrieBuild, i:Nat) : ?(K, ?Hash, V) = label profile_triebuild_nth_rec : (?(K, ?Hash, V)) { + switch tb { + case (#skip) P.unreachable(); + case (#insert (k,h,v)) label profile_trie_buildNth_rec_end : (?(K, ?Hash, V)) { + assert(i == 0); + ?(k,h,v) + }; + case (#seq s) label profile_trie_buildNth_rec_seq : (?(K, ?Hash, V)) { + let count_left = buildCount(s.left); + if (i < count_left) { rec(s.left, i) } + else { rec(s.right, i - count_left) } + }; + } + }; + if (i >= buildCount(tb)) { + return null + }; + rec(tb, i) + }; + + /** + `projectInnerBuild` + -------------- + + Like [`mergeDisjoint`](#mergedisjoint), except that it avoids the + work of actually merging any tries; rather, just record the work for + latter (if ever). + */ + public func projectInnerBuild(t : Trie>) + : TrieBuild + { + foldUp, TrieBuild> + ( t, + func (t1:TrieBuild, t2:TrieBuild):TrieBuild { buildSeq(t1, t2) }, + func (_:K1, t:TrieBuild): TrieBuild { t }, + #skip ) + }; + + /** + `buildToArray` + -------- + Gather the collection of key-value pairs into an array of a (possibly-distinct) type. + */ + public func buildToArray(tb:TrieBuild,f:(K,V)->W):[W] = + label profile_triebuild_toArray_begin : [W] { + let a = Array_tabulate ( + buildCount(tb), + func (i:Nat) : W = label profile_triebuild_toArray_nth : W { + let (k,_,v) = Option.unwrap<(K,?Hash,V)>(buildNth(tb, i)); + f(k, v) + } + ); + label profile_triebuild_toArray_end : [W] + a + }; + + /** + `buildToArray2` + -------- + Gather the collection of key-value pairs into an array of a (possibly-distinct) type. + + (Same semantics as `buildToArray`, but faster in practice.) + */ + public func buildToArray2(tb:TrieBuild,f:(K,V)->W):[W] { + let c = buildCount(tb); + let a = Array_init(c, null); + var i = 0; + func rec(tb:TrieBuild) = label profile_triebuild_toArray2_rec { + switch tb { + case (#skip) (); + case (#insert(k,_,v)) { a[i] := ?f(k,v); i := i + 1 }; + case (#seq(s)) { rec(s.left); rec(s.right) }; + } + }; + rec(tb); + Array_tabulate(c, func(i:Nat) : W = Option.unwrap(a[i])) + }; - /** - `foldUp` - ------------ - This operation gives a recursor for the internal structure of - tries. Many common operations are instantiations of this function, - either as clients, or as hand-specialized versions (e.g., see map, - mapFilter, exists and forAll below). - */ - public func foldUp(t:Trie, bin:(X,X)->X, leaf:(K,V)->X, empty:X) : X { - func rec(t:Trie) : X { - switch t { - case (null) { empty }; - case (?n) { - switch (matchLeaf(t)) { - case (?kvs) { - AssocList.fold,V,X>( - kvs, empty, - func (k:Key, v:V, x:X):X = - bin(leaf(k.key,v),x) - ) - }; - case null { bin(rec(n.left), rec(n.right)) }; - } - }; - }}; - rec(t) }; /** @@ -836,22 +1020,20 @@ public type Trie3D = Trie >; public func fold(t:Trie, f:(K,V,X)->X, x:X) : X { func rec(t:Trie, x:X) : X { switch t { - case (null) x; - case (?n) { - switch (matchLeaf(t)) { - case (?kvs) { - AssocList.fold,V,X>( - kvs, x, - func (k:Key, v:V, x:X):X = f(k.key,v,x) - ) - }; - case null { rec(n.left,rec(n.right,x)) }; - } + case (#empty) x; + case (#leaf l) { + AssocList.fold,V,X>( + l.keyvals, x, + func (k:Key, v:V, x:X):X = f(k.key,v,x) + ) }; - }}; + case (#branch(b)) { rec(b.left,rec(b.right,x)) }; + }; + }; rec(t, x) }; + /** `exists` -------- @@ -860,22 +1042,18 @@ public type Trie3D = Trie >; public func exists(t:Trie, f:(K,V)->Bool) : Bool { func rec(t:Trie) : Bool { switch t { - case (null) { false }; - case (?n) { - switch (matchLeaf(t)) { - case (?kvs) { - List.exists<(Key,V)>( - kvs, func ((k:Key,v:V)):Bool=f(k.key,v) - ) - }; - case null { rec(n.left) or rec(n.right) }; - } + case (#empty) { false }; + case (#leaf l) { + List.exists<(Key,V)>( + l.keyvals, func ((k:Key,v:V)):Bool=f(k.key,v) + ) }; - }}; + case (#branch(b)) { rec(b.left) or rec(b.right) }; + }; + }; rec(t) }; - /** `forAll` --------- @@ -884,60 +1062,84 @@ public type Trie3D = Trie >; public func forAll(t:Trie, f:(K,V)->Bool) : Bool { func rec(t:Trie) : Bool { switch t { - case (null) { true }; - case (?n) { - switch (matchLeaf(t)) { - case (?kvs) { - List.all<(Key,V)>( - kvs, func ((k:Key,v:V)):Bool=f(k.key,v) - ) - }; - case null { rec(n.left) and rec(n.right) }; - } + case (#empty) { true }; + case (#leaf l) { + List.all<(Key,V)>( + l.keyvals, func ((k:Key,v:V)):Bool=f(k.key,v) + ) }; - }}; + case (#branch(b)) { rec(b.left) and rec(b.right) }; + }; + }; rec(t) }; /** - `count` + `nth` -------- - Count the number of entries in the trie. + Project the nth key-value pair from the trie. + + Note: This position is not meaningful; it's only here so that we + can inject tries into arrays given the Array_tabulate interface for + doing so. */ - public func count(t:Trie):Nat{ - foldUp - (t, - func(n:Nat,m:Nat):Nat{n+m}, - func(_:K,_:V):Nat{1}, - 0) + public func nth(t:Trie, i:Nat) : ?(Key, V) = label profile_trie_nth : (?(Key, V)) { + func rec(t:Trie, i:Nat) : ?(Key, V) = label profile_trie_nth_rec : (?(Key, V)) { + switch t { + case (#empty) P.unreachable(); + case (#leaf l) List.nth<(Key,V)>(l.keyvals, i); + case (#branch b) { + let count_left = count(b.left); + if (i < count_left) { rec(b.left, i) } + else { rec(b.right, i - count_left) } + } + } + }; + if (i >= count(t)) { + return null + }; + rec(t, i) }; + /** `toArray` -------- - Gather the collection of key-value pairs into an array. + Gather the collection of key-value pairs into an array of a (possibly-distinct) type. + + ### Implementation notes: + + we use this function repeatedly in the Produce Exchange example + application, often on very large tries. + + Performance Profiling shows that it is important that this be + memory efficient, and reasonably time efficient, at large scales. + + To do so, we use a single array allocation (for the returned array) and we + sacrifice some efficiency in reading the input trie, and instead use function `nth` to + project each element with an independent trie traversal. + + This approach is somewhat forced on us by the type signature of + Array_tabulate, and the desire to only allocate one array; that requirement rules + out iterative mutation of an optionally-null array, since an imperative + approach which would give us the wrong return type. + + Since we want to statically rule out null output elements, and since the AS type system + cannot do that for an imperative approach unless we assume more about + the type W (e.g., the existence of "default values"), we settle for using `nth`. - To do: make this more efficient, using a single array allocation. */ - public func toArray(t:Trie,f:(K,V)->[W]):[W] = + public func toArray(t:Trie,f:(K,V)->W):[W] = label profile_trie_toArray_begin : [W] { - func arrayAppend(x:[W],y:[W]):[W] { - label profile_trie_toArray_arrayAppend : [W] - Array_tabulate ( - x.len() + y.len(), - func (i:Nat) : W = label profile_trie_toArray_arrayAppend_projelm : W { - if (i >= x.len()) { y[i - x.len()] } - else { x[i] } - } - ) - }; - let result = foldUp - (t, - arrayAppend, - func(k:K, v:V):[W]{f(k,v)}, - []); + let a = Array_tabulate ( + count(t), + func (i:Nat) : W = label profile_trie_toArray_nth : W { + let (k,v) = Option.unwrap<(Key,V)>(nth(t, i)); + f(k.key, v) + } + ); label profile_trie_toArray_end : [W] - result + a }; /** @@ -948,20 +1150,8 @@ public type Trie3D = Trie >; but no leaves. These can result from naive filtering operations; filter uses this function to avoid creating such subtrees. */ - public func isEmpty(t:Trie) : Bool { - func rec(t:Trie) : Bool { - switch t { - case (null) { true }; - case (?n) { - switch (matchLeaf(t)) { - case (?kvs) { List.isNil<(Key,V)>(kvs) }; - case null { rec(n.left) and rec(n.right) }; - } - }; - } - }; - rec(t) - }; + public func isEmpty(t:Trie) : Bool = + count(t) == 0; /** `filter` @@ -969,73 +1159,71 @@ public type Trie3D = Trie >; filter the key-value pairs by a given predicate. */ public func filter(t:Trie, f:(K,V)->Bool) : Trie { - func rec(t:Trie) : Trie { + func rec(t:Trie, bitpos:Nat) : Trie { switch t { - case (null) { null }; - case (?n) { - switch (matchLeaf(t)) { - case (?kvs) { - makeLeaf( - List.filter<(Key,V)>(kvs, func ((k:Key,v:V)):Bool = f(k.key,v)) - ) - }; - case null { - let l = rec(n.left); - let r = rec(n.right); - switch (isEmpty(l), - isEmpty(r)) { - case (true, true) null; - case (false, true) r; - case (true, false) l; - case (false, false) makeBin(l, r); - } - }; - } - }; + case (#empty) { #empty }; + case (#leaf l) { + leaf( + List.filter<(Key,V)>( + l.keyvals, + func ((k:Key,v:V)):Bool = f(k.key,v) + ), + bitpos + ) + }; + case (#branch(b)) { + let fl = rec(b.left, bitpos+1); + let fr = rec(b.right, bitpos+1); + switch (isEmpty(fl), + isEmpty(fr)) { + case (true, true) #empty; + case (false, true) fr; + case (true, false) fl; + case (false, false) branch(fl, fr); + }; + } } }; - rec(t) + rec(t, 0) }; /** `mapFilter` ----------- - map and filter the key-value pairs by a given partial mapping function. + map and filter the key-value pairs by a given predicate. */ public func mapFilter(t:Trie, f:(K,V)->?W) : Trie { - func rec(t:Trie) : Trie { + func rec(t:Trie, bitpos:Nat) : Trie { switch t { - case (null) { null }; - case (?n) { - switch (matchLeaf(t)) { - case (?kvs) { - makeLeaf( - List.mapFilter<(Key,V),(Key,W)> - (kvs, - // retain key and hash, but update key's value using f: - func ((k:Key,v:V)):?(Key,W) = { - switch (f(k.key,v)) { - case (null) null; - case (?w) (?({key=k.key; hash=k.hash}, w)); - }} - )) - }; - case null { - let l = rec(n.left); - let r = rec(n.right); - switch (isEmpty(l), - isEmpty(r)) { - case (true, true) null; - case (false, true) r; - case (true, false) l; - case (false, false) makeBin(l, r); - } - }; - } - }; + case (#empty) { #empty }; + case (#leaf l) { + leaf( + List.mapFilter<(Key,V),(Key,W)>( + l.keyvals, + // retain key and hash, but update key's value using f: + func ((k:Key,v:V)):?(Key,W) = { + switch (f(k.key,v)) { + case (null) null; + case (?w) (?({key=k.key; hash=k.hash}, w)); + }} + ), + bitpos + ) + }; + case (#branch(b)) { + let fl = rec(b.left, bitpos + 1); + let fr = rec(b.right, bitpos + 1); + switch (isEmpty(fl), + isEmpty(fr)) { + case (true, true) #empty; + case (false, true) fr; + case (true, false) fl; + case (false, false) branch(fl, fr); + }; + } } }; - rec(t) + rec(t, 0) }; /** @@ -1058,221 +1246,220 @@ public type Trie3D = Trie >; ) : Bool { func rec(tl:Trie, tr:Trie) : Bool { switch (tl, tr) { - case (null, null) { true }; - case (_, null) { false }; - case (null, _) { false }; - case (?nl, ?nr) { - switch (matchLeaf(tl), - matchLeaf(tr)) { - case (null, null) { - rec(nl.left, nr.left) - and rec(nl.right, nr.right) - }; - case (null, _) { false }; - case (_, null) { false }; - case (?kvs1, ?kvs2) { - List.isEq<(Key,V)> - (kvs1, kvs2, - func ((k1:Key, v1:V), (k2:Key, v2:V)) : Bool = - keq(k1.key, k2.key) and veq(v1,v2) - ) - }; - } + case (#empty, #empty) { true }; + case (#leaf l1, #leaf l2) { + List.isEq<(Key,V)> + (l1.keyvals, l2.keyvals, + func ((k1:Key, v1:V), (k2:Key, v2:V)) : Bool = + keq(k1.key, k2.key) and veq(v1,v2) + ) }; - }}; - rec(tl, tr) + case (#branch(b1),#branch(b2)) { + rec(b1.left, b2.left) and rec(b2.right, b2.right) + }; + case _ { false }; + } + }; + rec(tl,tr) }; - // Equality function for two `Key`s, in terms of equality of `K`'s. - public func keyEq(keq:(K,K) -> Bool) : ((Key,Key) -> Bool) = { - func (key1:Key, key2:Key) : Bool = - label profile_trie_keyEq : Bool - (Hash.hashEq(key1.hash, key2.hash) and keq(key1.key, key2.key)) + /** + `replaceThen` + ------------ + replace the given key's value in the trie, + and only if successful, do the success continuation, + otherwise, return the failure value + */ + public func replaceThen(t : Trie, k:Key, k_eq:(K,K)->Bool, v2:V, + success: (Trie, V) -> X, + fail: () -> X) + : X + { + let (t2, ov) = replace(t, k, k_eq, ?v2); + switch ov { + case (null) { /* no prior value; failure to remove */ fail() }; + case (?v1) { success(t2, v1) }; + } }; /** - Helpers for missing variants - ============================== - Until Motoko has variant types, we need various helper functions here. They are uninteresting. + `insertFresh` + ---------------- + insert the given key's value in the trie; return the new trie; assert that no prior value is associated with the key */ - // @Omit: - - // XXX: until AST-42: - public func isNull(x : ?X) : Bool { - switch x { - case null { true }; - case (?_) { false }; + public func insertFresh(t : Trie, k:Key, k_eq:(K,K)->Bool, v:V) : Trie { + let (t2, none) = replace(t, k, k_eq, ?v); + switch none { + case (null) (); + case (?_) assert false; }; + t2 }; - // XXX: until AST-42: - public func assertIsNull(x : ?X) { - label profile_trie_assertIsNull - switch x { - case null { assert(true) }; - case (?_) { assert(false) }; + /** + `insert2D` + --------------- + insert the given key's value in the 2D trie; return the new 2D trie. + */ + public func insert2D(t : Trie2D, + k1:Key, k1_eq:(K1,K1)->Bool, + k2:Key, k2_eq:(K2,K2)->Bool, + v:V) + : Trie2D + { + let inner = find>(t, k1, k1_eq); + let (updated_inner, _) = switch inner { + case (null) { insert(#empty, k2, k2_eq, v) }; + case (?inner) { insert(inner, k2, k2_eq, v) }; }; + let (updated_outer, _) = { insert>(t, k1, k1_eq, updated_inner) }; + updated_outer; }; - // XXX: until AST-42: - public func makeEmpty() : Trie - = null; - - // XXX: until AST-42: - public func assertIsEmpty(t : Trie) { - switch t { - case null { assert(true) }; - case (?_) { assert(false) }; + /** + `insert3D` + --------------- + insert the given key's value in the trie; return the new trie; + */ + public func insert3D + (t : Trie3D, + k1:Key, k1_eq:(K1,K1)->Bool, + k2:Key, k2_eq:(K2,K2)->Bool, + k3:Key, k3_eq:(K3,K3)->Bool, + v:V + ) + : Trie3D + { + let inner1 = find>(t, k1, k1_eq); + let (updated_inner1, _) = switch inner1 { + case (null) { + insert>( + #empty, k2, k2_eq, + (insert(#empty, k3, k3_eq, v)).0 + ) + }; + case (?inner1) { + let inner2 = find>(inner1, k2, k2_eq); + let (updated_inner2, _) = switch inner2 { + case (null) { insert(#empty, k3, k3_eq, v) }; + case (?inner2) { insert(inner2, k3, k3_eq, v) }; + }; + insert>( inner1, k2, k2_eq, updated_inner2 ) + }; }; + let (updated_outer, _) = { insert>(t, k1, k1_eq, updated_inner1) }; + updated_outer; }; - // XXX: until AST-42: - public func makeBin(l:Trie, r:Trie) : Trie { - ?{left=l; right=r; keyvals=null; } + /** + `remove` + ------------- + remove the given key's value in the trie; return the new trie + */ + public func remove(t : Trie, k:Key, k_eq:(K,K)->Bool) : (Trie, ?V) { + replace(t, k, k_eq, null) }; - // XXX: until AST-42: - public func isBin(t:Trie) : Bool { - switch t { - case null { false }; - case (?t_) { - switch (t_.keyvals) { - case null { true }; - case _ { false }; - }; - }; + /** + `removeThen` + ------------ + remove the given key's value in the trie, + and only if successful, do the success continuation, + otherwise, return the failure value + */ + public func removeThen(t : Trie, k:Key, k_eq:(K,K)->Bool, + success: (Trie, V) -> X, + fail: () -> X) + : X + { + let (t2, ov) = replace(t, k, k_eq, null); + switch ov { + case (null) { /* no prior value; failure to remove */ fail() }; + case (?v) { success(t2, v) }; } }; - // XXX: until AST-42: - public func makeLeaf(kvs:AssocList,V>) : Trie { - ?{left=null; right=null; keyvals=kvs } - }; - - // XXX: until AST-42: - public func matchLeaf(t:Trie) : ?AssocList,V> { - switch t { - case null { null }; - case (?t_) { - switch (t_.keyvals) { - case (?keyvals) ?(?(keyvals)); - case (_) null; - } - }; - } - }; - // XXX: until AST-42: - public func isLeaf(t:Trie) : Bool { - switch t { - case null { false }; - case (?t_) { - switch (t_.keyvals) { - case null { false }; - case _ { true }; - } - }; - } - }; - // XXX: until AST-42: - public func assertIsBin(t : Trie) { - switch t { - case null { assert(false) }; - case (?n) { - assertIsNull<((Key,V),AssocList,V>)>(n.keyvals); + /** + `remove2D` + -------------- + remove the given key-key pair's value in the 2D trie; return the + new trie, and the prior value, if any. + */ + public func remove2D(t : Trie2D, + k1:Key, k1_eq:(K1,K1)->Bool, + k2:Key, k2_eq:(K2,K2)->Bool) + : (Trie2D, ?V) + { + switch (find>(t, k1, k1_eq)) { + case (null) { + (t, null) + }; + case (?inner) { + let (updated_inner, ov) = remove(inner, k2, k2_eq); + let (updated_outer, _) = { + insert>(t, k1, k1_eq, updated_inner) + }; + (updated_outer, ov) }; } }; - // XXX: until AST-42: - public func getLeafKey(t : Node) : Key { - assertIsNull>(t.left); - assertIsNull>(t.right); - switch (t.keyvals) { - case (?((k,v),_)) { k }; - case (null) { /* ERROR */ getLeafKey(t) }; + /** + `remove3D` + --------------- + remove the given key-key pair's value in the 3D trie; return the + new trie, and the prior value, if any. + */ + public func remove3D + (t : Trie3D, + k1:Key, k1_eq:(K1,K1)->Bool, + k2:Key, k2_eq:(K2,K2)->Bool, + k3:Key, k3_eq:(K3,K3)->Bool, + ) + : (Trie3D, ?V) + { + switch (find>(t, k1, k1_eq)) { + case (null) { + (t, null) + }; + case (?inner) { + let (updated_inner, ov) = remove2D(inner, k2, k2_eq, k3, k3_eq); + let (updated_outer, _) = { + insert>(t, k1, k1_eq, updated_inner) + }; + (updated_outer, ov) + }; } }; - // XXX: this helper is an ugly hack; we need real sum types to avoid it, I think: - public func getLeafVal(t : Node) : V { - assertIsNull>(t.left); - assertIsNull>(t.right); - switch (t.keyvals) { - case (?((k,v),_)) { v }; - case null { /* ERROR */ getLeafVal(t) }; - } - }; /** - More helpers - ============================== - */ + `mergeDisjoint2D` + -------------- + Like [`mergeDisjoint`](#mergedisjoint), except instead of merging a + pair, it merges the collection of dimension-2 sub-trees of a 2D + trie. - /** - `buildNewPath` - --------------- - helper function for constructing new paths of uniform length */ - - public func buildNewPath(bitpos:Nat, k:Key, ov:?V) : Trie { - func rec(bitpos:Nat) : Trie { - if ( bitpos < HASH_BITS ) { - // create new bin node for this bit of the hash - let path = rec(bitpos+1); - let bit = Hash.getHashBit(k.hash, bitpos); - if (not bit) { - ?{left=path; right=null; keyvals=null} - } - else { - ?{left=null; right=path; keyvals=null} - } - } else { - // create new leaf for (k,v) pair, if the value is non-null: - switch ov { - case null { ?{left=null; right=null; keyvals=null } }; - case (?v) { ?{left=null; right=null; keyvals=?((k,v),null) } }; - } - } - }; - rec(bitpos) + public func mergeDisjoint2D(t : Trie2D, k1_eq:(K1,K1)->Bool, k2_eq:(K2,K2)->Bool) + : Trie + { + foldUp, Trie> + ( t, + func (t1:Trie, t2:Trie):Trie { mergeDisjoint(t1, t2, k2_eq) }, + func (_:K1, t:Trie): Trie { t }, + #empty ) }; -//}; - /** Future work ============= -Tests ---------- -more regression tests for everything documented in the [module interface](#module-interface). - - -Variant types ------------------------- -See [AST-42]() (sum types); we want this type definition instead: - - ``` - // Use a sum type (AST-42) - type Trie = { #leaf : LeafNode; #bin : BinNode; #empty }; - type BinNode = { left:Trie; right:Trie }; - type LeafNode = { key:K; val:V }; - ``` - -Adaptive path lengths ----------------------- - -Currently we assume a uniform path length. This can be inefficient, -and requires careful tuning. In the future, we could adapt the path -length of each subtree to its cardinality; this wouild avoid -needlessly long paths, or paths that are too short for their subtree's -size. - Iterator objects ------------------- for use in 'for ... in ...' patterns diff --git a/stdlib/trie2.mo b/stdlib/trie2.mo deleted file mode 100644 index 44181962b7b..00000000000 --- a/stdlib/trie2.mo +++ /dev/null @@ -1,1468 +0,0 @@ -import P "prelude.mo"; -import Option "option.mo"; -import H "hash.mo"; - -import List "list.mo"; -import AssocList "assocList.mo"; - -module { -/** - -Hash tries -====================== - -Functional maps (and sets) whose representation is "canonical", and -history independent. - -Background ------------------- - -See this POPL 1989 paper (Section 6): - - - ["Incremental computation via function caching", Pugh & Teitelbaum](https://dl.acm.org/citation.cfm?id=75305). - - [Public copy here](http://matthewhammer.org/courses/csci7000-s17/readings/Pugh89.pdf). - -By contrast, other usual functional representations of maps (AVL -Trees, Red-Black Trees) do not enjoy history independence, and are -each more complex to implement (e.g., each requires "rebalancing"; -these trees never do). - -*/ - -/** -Representation -===================== - -A hash trie is a binary trie, where each (internal) branch node -represents having distinguished its key-value pairs on a single bit of -the keys. - -By following paths in the trie, we determine an increasingly smaller -and smaller subset of the keys. - -Each leaf node consists of an association list of key-value pairs. - -We say that a leaf is valid if it contains no more than MAX_LEAF_COUNT -key-value pairs. - -Each non-empty trie node stores a count; we discuss that more below. - -### Adaptive depth - -For small mappings, this "trie" structure just consists of a single -leaf, which contains up to MAX_LEAF_COUNT key-value pairs. - -By construction, the algorithms below enforce the invariant that no -leaf ever contains more than MAX_LEAF_COUNT key-value pairs: the -function `leaf` accepts a list, but subdivides it with branches until -it can actually construct valid leaves. Ongce distinguished, subsets -of keys tend to remain distinguished by the presence of these branches. - -### Cached counts - -At each branch and leaf, we use a stored count to support a -memory-efficient `toArray` function, which itself relies on -per-element projection via `nth`; in turn, `nth` directly uses the -O(1)-time function `count` for achieving an acceptable level of -algorithmic efficiently. Notably, leaves are generally lists of -key-value pairs, and we do not store a count for each Cons cell in the -list. - - -### Details - -Below, we define the types used in the representation: - -*/ - -//let MAX_LEAF_COUNT = 4; // worse than 8, slightly -public let MAX_LEAF_COUNT = 8; // <-- beats both 4 and 16 for me, now -//let MAX_LEAF_COUNT = 16; -//let MAX_LEAF_COUNT = 32; - -public let Hash = H.BitVec; -public type Hash = Hash.t; - -public type List = List.List; -public type AssocList = AssocList.AssocList; - -/** A `Key` for the trie has an associated hash value */ -public type Key = { - /** `hash` permits fast inequality checks, and permits collisions */ - hash: Hash; - /** `key` permits percise equality checks, but only used after equal hashes. */ - key: K; -}; - -/** Equality function for two `Key`s, in terms of equality of `K`'s. */ -public func keyEq(keq:(K,K) -> Bool) : ((Key,Key) -> Bool) = { - func (key1:Key, key2:Key) : Bool = - label profile_trie_keyEq : Bool - (Hash.hashEq(key1.hash, key2.hash) and keq(key1.key, key2.key)) -}; - -/** leaf nodes of trie consist of key-value pairs as a list. */ -public type Leaf = { - count : Nat ; - keyvals : AssocList,V> ; -}; - -/** branch nodes of the trie discriminate on a bit position of the keys' hashes. - we never store this bitpos; rather, - we enforce a style where this position is always known from context. -*/ -public type Branch = { - count : Nat ; - left : Trie ; - right : Trie ; -}; - -/** binary hash tries: either empty, a leaf node, or a branch node */ -public type Trie = { - #empty ; - #leaf : Leaf ; - #branch : Branch ; -}; - -public func isValid (t:Trie, enforceNormal:Bool) : Bool { - func rec(t:Trie, bitpos:?Hash, bits:Hash, mask:Hash) : Bool { - switch t { - case (#empty) { - switch bitpos { - case null true; - case (?_) not enforceNormal; - } - }; - case (#leaf l) { - let len = List.len<(Key,V)>(l.keyvals); - ((len <= MAX_LEAF_COUNT) or (not enforceNormal)) - and - len == l.count - and - ( List.all<(Key,V)>( - l.keyvals, - func ((k:Key,v:V)):Bool{ - //{ debugPrint "testing hash..."; true } - //and - ((k.hash & mask) == bits) - or - { debugPrint "\nmalformed hash!:\n"; - debugPrintInt (word32ToNat(k.hash)); - debugPrint "\n (key hash) != (path bits): \n"; - debugPrintInt (word32ToNat(bits)); - debugPrint "\nmask : "; debugPrintInt (word32ToNat(mask)); - debugPrint "\n"; - false } - } - ) or - { debugPrint "one or more hashes are malformed"; false } - ) - }; - case (#branch b) { - let bitpos1 = switch bitpos { - case null (natToWord32(0)); - case (?bp) (natToWord32(word32ToNat(bp) + 1)) - }; - let mask1 = mask | (natToWord32(1) << bitpos1); - let bits1 = bits | (natToWord32(1) << bitpos1); - let sum = count(b.left) + count(b.right); - (b.count == sum or { debugPrint "malformed count"; false }) - and - rec(b.left, ?bitpos1, bits, mask1) - and - rec(b.right, ?bitpos1, bits1, mask1) - }; - } - }; - rec(t, null, 0, 0) -}; - - -/** - Two-dimensional trie - --------------------- - A 2D trie is just a trie that maps dimension-1 keys to another - layer of tries, each keyed on the dimension-2 keys. -*/ -public type Trie2D = Trie >; - -/** - Three-dimensional trie - --------------------- - A 3D trie is just a trie that maps dimension-1 keys to another - layer of 2D tries, each keyed on the dimension-2 and dimension-3 keys. -*/ -public type Trie3D = Trie >; - -/** - Module interface - =================== - */ - - /** - `empty` - -------- - An empty trie. - */ -public func empty() : Trie = - #empty; - - /** - `count` - -------- - Get the number of key-value pairs in the trie, in constant time. - - ### Implementation notes - - `nth` directly uses this function `count` for achieving an - acceptable level of algorithmic efficiently. - - */ -public func count(t: Trie) : Nat = label profile_trie_count : Nat { - switch t { - case (#empty) 0; - case (#leaf l) l.count; - case (#branch b) b.count; - } - }; - - /** - `branch` - -------- - Construct a branch node, computing the count stored there. - */ -public func branch(l:Trie, r:Trie) : Trie = label profile_trie_branch : Trie { - let sum = count(l) + count(r); - #branch( - { - count=sum; - left=l; - right=r - } - ); - }; - - /** - `leaf` - -------- - Construct a leaf node, computing the count stored there. - - This helper function automatically enforces the MAX_LEAF_COUNT - by constructing branches as necessary; to do so, it also needs the bitpos - of the leaf. - - */ -public func leaf(kvs:AssocList,V>, bitpos:Nat) : Trie = label trie_leaf : Trie { - fromSizedList(null, kvs, bitpos) - }; - -public func fromList(kvs:AssocList,V>, bitpos:Nat) : Trie = - label profile_trie_fromList_begin : (Trie) { - func rec(kvs:AssocList,V>, bitpos:Nat) : Trie { - if ( List.isNil<(Key,V)>(kvs) ) - label profile_trie_fromList_end_empty : (Trie) { - #empty - } - else if ( List.lenIsEqLessThan<(Key,V)>(kvs, MAX_LEAF_COUNT - 1) ) - label profile_trie_fromList_end_validleaf : (Trie) { - let len = List.len<(Key,V)>(kvs); - #leaf{count=len;keyvals=kvs} - } - else if ( bitpos >= 31 ) - label profile_trie_fromList_end_bitposIs31 : (Trie) { - let len = List.len<(Key,V)>(kvs); - #leaf{count=len;keyvals=kvs} - } - else /* too many keys for a leaf, so introduce a branch */ - label profile_trie_fromList_branch : (Trie) { - let (l, r) = splitAssocList(kvs, bitpos); - branch(rec(l, bitpos + 1), rec(r, bitpos + 1)) - } - }; - rec(kvs, bitpos) - }; - - -public func fromSizedList(kvc:?Nat, kvs:AssocList,V>, bitpos:Nat) : Trie = - label profile_trie_fromList_begin : (Trie) { - func rec(kvc:?Nat, kvs:AssocList,V>, bitpos:Nat) : Trie { - switch kvc { - case null { - switch (List.lenClamp<(Key,V)>(kvs, MAX_LEAF_COUNT)) { - case null () /* fall through to branch case. */; - case (?len) { - return #leaf{count=len; keyvals=kvs} - }; - } - }; - case (?c) { - if ( c == 0 ) { - return #empty - } else if ( c <= MAX_LEAF_COUNT ) { - return #leaf{count=c; keyvals=kvs} - } else { - /* fall through to branch case */ - } - }; - }; - let (ls, l, rs, r) = splitSizedList(kvs, bitpos); - if ( ls == 0 and rs == 0 ) { - #empty - } else if (rs == 0 and ls <= MAX_LEAF_COUNT) { - #leaf{count=ls; keyvals=l} - } else if (ls == 0 and rs <= MAX_LEAF_COUNT) { - #leaf{count=rs; keyvals=r} - } else { - branch(rec(?ls, l, bitpos + 1), rec(?rs, r, bitpos + 1)) - } - }; - rec(kvc, kvs, bitpos) - }; - - /** - `copy` - --------- - Purely-functional representation permits _O(1)_-time copy, via persistent sharing. - */ -public func copy(t : Trie) : Trie = t; - - /** - `replace` - --------- - replace the given key's value option with the given one, returning the previous one - */ -public func replace(t : Trie, k:Key, k_eq:(K,K)->Bool, v:?V) : (Trie, ?V) = - label profile_trie_replace : (Trie, ?V) { - let key_eq = keyEq(k_eq); - - func rec(t : Trie, bitpos:Nat) : (Trie, ?V) = - label profile_trie_replace_rec : (Trie, ?V) { - switch t { - case (#empty) label profile_trie_replace_rec_empty : (Trie, ?V) { - let (kvs, _) = AssocList.replace,V>(null, k, key_eq, v); - (leaf(kvs, bitpos), null) - }; - case (#branch b) label profile_trie_replace_rec_branch : (Trie, ?V) { - let bit = Hash.getHashBit(k.hash, bitpos); - // rebuild either the left or right path with the inserted (k,v) pair - if (not bit) { - let (l, v_) = rec(b.left, bitpos+1); - (branch(l, b.right), v_) - } - else { - let (r, v_) = rec(b.right, bitpos+1); - (branch(b.left, r), v_) - } - }; - case (#leaf l) label profile_trie_replace_rec_leaf : (Trie, ?V) { - let (kvs2, old_val) = - AssocList.replace,V>(l.keyvals, k, key_eq, v); - (leaf(kvs2, bitpos), old_val) - }; - } - }; - let (to, vo) = rec(t, 0); - //assert(isValid(to, false)); - (to, vo) - }; - - /** - `insert` - ------------ - insert the given key's value in the trie; return the new trie, and the previous value associated with the key, if any - */ -public func insert(t : Trie, k:Key, k_eq:(K,K)->Bool, v:V) : (Trie, ?V) = - label profile_trie_insert : (Trie, ?V) { - replace(t, k, k_eq, ?v) - }; - -/** - `find` - --------- - find the given key's value in the trie, or return null if nonexistent - */ -public func find(t : Trie, k:Key, k_eq:(K,K) -> Bool) : ?V = label profile_trie_find : (?V) { - let key_eq = keyEq(k_eq); - func rec(t : Trie, bitpos:Nat) : ?V = label profile_trie_find_rec : (?V) { - switch t { - case (#empty) { - label profile_trie_find_end_null : (?V) - null - }; - case (#leaf l) { - label profile_trie_find_end_assocList_find : (?V) - AssocList.find,V>(l.keyvals, k, key_eq) - }; - case (#branch b) { - let bit = Hash.getHashBit(k.hash, bitpos); - if (not bit) { - label profile_trie_find_branch_left : (?V) - rec(b.left, bitpos+1) - } - else { - label profile_trie_find_branch_right : (?V) - rec(b.right, bitpos+1) - } - }; - } - }; - rec(t, 0) - }; - - - - -public func splitAssocList(al:AssocList,V>, bitpos:Nat) - : (AssocList,V>, AssocList,V>) = - label profile_trie_splitAssocList : (AssocList,V>, AssocList,V>) - { - List.split<(Key,V)>( - al, - func ((k : Key, v : V)) : Bool { - not Hash.getHashBit(k.hash, bitpos) - } - ) - }; - -public func splitSizedList(l:AssocList,V>, bitpos:Nat) - : (Nat, AssocList,V>, Nat, AssocList,V>) = - label profile_trie_splitSizedList : (Nat, AssocList,V>, Nat, AssocList,V>) - { - func rec(l : AssocList,V>) : (Nat, AssocList,V>, Nat, AssocList,V>) = - label profile_trie_sized_split_rec : (Nat, AssocList,V>, Nat, AssocList,V>) { - switch l { - case null { (0, null, 0, null) }; - case (?((k,v),t)) { - let (cl, l, cr, r) = rec(t) ; - if (not Hash.getHashBit(k.hash, bitpos)){ - (cl + 1, ?((k,v),l), cr, r) - } else { - (cl, l, cr + 1, ?((k,v),r)) - } - }; - } - }; - rec(l) - }; - - /** - `merge` - --------- - merge tries, preferring the right trie where there are collisions - in common keys. note: the `disj` operation generalizes this `merge` - operation in various ways, and does not (in general) lose - information; this operation is a simpler, special case. - - See also: - - - [`disj`](#disj) - - [`join`](#join) - - [`prod`](#prod) - - */ -public func merge(tl:Trie, tr:Trie, k_eq:(K,K)->Bool) : Trie = label profile_trie_merge : Trie { - let key_eq = keyEq(k_eq); - func br(l:Trie, r:Trie) : Trie = branch(l,r); - func rec(bitpos:Nat, tl:Trie, tr:Trie) : Trie { - func lf(kvs:AssocList,V>) : Trie = leaf(kvs, bitpos); - switch (tl, tr) { - case (#empty, _) { return tr }; - case (_, #empty) { return tl }; - case (#leaf l1, #leaf l2) { - lf( - AssocList.disj,V,V,V>( - l1.keyvals, l2.keyvals, - key_eq, - func (x:?V, y:?V):V = { - switch (x, y) { - case (null, null) { P.unreachable() }; - case (null, ?v) v; - case (?v, _) v; - }} - ) - ) - }; - case (#leaf l, _) { - let (ll, lr) = splitAssocList(l.keyvals, bitpos); - rec(bitpos, br(lf ll, lf lr), tr) - }; - case (_, #leaf l) { - let (ll, lr) = splitAssocList(l.keyvals, bitpos); - rec(bitpos, tl, br(lf ll, lf lr)) - }; - case (#branch b1, #branch b2) { - br(rec(bitpos + 1, b1.left, b2.left), - rec(bitpos + 1, b1.right, b2.right)) - }; - } - }; - rec(0, tl, tr) - }; - - /** - `mergeDisjoint` - ---------------- - like `merge`, it merges tries, but unlike `merge`, it signals a - dynamic error if there are collisions in common keys between the - left and right inputs. - */ -public func mergeDisjoint(tl:Trie, tr:Trie, k_eq:(K,K)->Bool): Trie = - label profile_trie_mergeDisjoint : Trie { - let key_eq = keyEq(k_eq); - func br(l:Trie, r:Trie) : Trie = branch(l,r); - func rec(bitpos:Nat, tl:Trie, tr:Trie) : Trie = label profile_trie_mergeDisjoint_rec : Trie { - func lf(kvs:AssocList,V>) : Trie = leaf(kvs, bitpos); - switch (tl, tr) { - case (#empty, _) label profile_trie_mergeDisjoint_rec_emptyL : Trie { return tr }; - case (_, #empty) label profile_trie_mergeDisjoint_rec_emptyR : Trie { return tl }; - case (#leaf l1, #leaf l2) label profile_trie_mergeDisjoint_rec_leafPair : Trie { - lf( - AssocList.disjDisjoint,V,V,V>( - l1.keyvals, l2.keyvals, - func (x:?V, y:?V):V = { - switch (x, y) { - case (null, ?v) v; - case (?v, null) v; - case (_, _) P.unreachable(); - } - } - ) - ) - }; - case (#leaf l, _) label profile_trie_mergeDisjoint_rec_splitLeafL : Trie { - let (ll, lr) = splitAssocList(l.keyvals, bitpos); - rec(bitpos, br(lf ll, lf lr), tr) - }; - case (_, #leaf l) label profile_trie_mergeDisjoint_rec_splitLeafR : Trie { - let (ll, lr) = splitAssocList(l.keyvals, bitpos); - rec(bitpos, tl, br(lf ll, lf lr)) - }; - case (#branch b1, #branch b2) label profile_trie_mergeDisjoint_rec_branchPair : Trie { - branch( - rec(bitpos + 1, b1.left, b2.left), - rec(bitpos + 1, b1.right, b2.right) - ) - }; - - } - }; - rec(0, tl, tr) - }; - - /** - `diff` - ------ - The key-value pairs of the final trie consists of those pairs of - the left trie whose keys are not present in the right trie; the - values of the right trie are irrelevant. - */ -public func diff(tl:Trie, tr:Trie, k_eq:(K,K)->Bool): Trie { - let key_eq = keyEq(k_eq); - - func br1(l:Trie, r:Trie) : Trie = branch(l,r); - func br2(l:Trie, r:Trie) : Trie = branch(l,r); - - func rec(bitpos:Nat, tl:Trie, tr:Trie) : Trie { - func lf1(kvs:AssocList,V>) : Trie = leaf(kvs, bitpos); - func lf2(kvs:AssocList,W>) : Trie = leaf(kvs, bitpos); - - switch (tl, tr) { - case (#empty, _) { return #empty }; - case (_, #empty) { return tl }; - case (#leaf l1, #leaf l2) { - lf1( - AssocList.diff,V,W>( - l1.keyvals, l2.keyvals, - key_eq, - ) - ) - }; - case (#leaf l, _) { - let (ll, lr) = splitAssocList(l.keyvals, bitpos); - rec(bitpos, br1(lf1 ll, lf1 lr), tr) - }; - case (_, #leaf l) { - let (ll, lr) = splitAssocList(l.keyvals, bitpos); - rec(bitpos, tl, br2(lf2 ll, lf2 lr)) - }; - case (#branch b1, #branch b2) { - br1(rec(bitpos + 1, b1.left, b2.left), - rec(bitpos + 1, b1.right, b2.right)) - }; - } - }; - rec(0, tl, tr) - }; - - /** - `disj` - -------- - - This operation generalizes the notion of "set union" to finite maps. - - Produces a "disjunctive image" of the two tries, where the values of - matching keys are combined with the given binary operator. - - For unmatched key-value pairs, the operator is still applied to - create the value in the image. To accomodate these various - situations, the operator accepts optional values, but is never - applied to (null, null). - - Implements the database idea of an ["outer join"](https://stackoverflow.com/questions/38549/what-is-the-difference-between-inner-join-and-outer-join). - - See also: - - - [`join`](#join) - - [`merge`](#merge) - - [`prod`](#prod) - - */ -public func disj( - tl : Trie, - tr : Trie, - k_eq : (K,K)->Bool, - vbin : (?V,?W)->X - ) - : Trie - { - let key_eq = keyEq(k_eq); - - func br1(l:Trie, r:Trie) : Trie = branch(l,r); - func br2(l:Trie, r:Trie) : Trie = branch(l,r); - - func br3(l:Trie, r:Trie) : Trie = branch(l,r); - func lf3(kvs:AssocList,X>, bitpos:Nat) : Trie = leaf(kvs, bitpos); - - /** empty right case; build from left only: */ - func recL(t:Trie, bitpos:Nat) : Trie { - switch t { - case (#empty) #empty; - case (#leaf l) { - lf3(AssocList.disj,V,W,X>(l.keyvals, null, key_eq, vbin), bitpos) - }; - case (#branch(b)) { br3(recL(b.left,bitpos+1),recL(b.right,bitpos+1)) }; - } - }; - /** empty left case; build from right only: */ - func recR(t:Trie, bitpos:Nat) : Trie { - switch t { - case (#empty) #empty; - case (#leaf l) { - lf3(AssocList.disj,V,W,X>(null, l.keyvals, key_eq, vbin), bitpos) - }; - case (#branch(b)) { br3(recR(b.left,bitpos+1),recR(b.right,bitpos+1)) }; - } - }; - - /** main recursion */ - func rec(bitpos:Nat, tl:Trie, tr:Trie) : Trie { - func lf1(kvs:AssocList,V>) : Trie = leaf(kvs, bitpos); - func lf2(kvs:AssocList,W>) : Trie = leaf(kvs, bitpos); - switch (tl, tr) { - case (#empty, #empty) { #empty }; - case (#empty, _ ) { recR(tr, bitpos) }; - case (_, #empty) { recL(tl, bitpos) }; - case (#leaf l1, #leaf l2) { - lf3(AssocList.disj,V,W,X>(l1.keyvals, l2.keyvals, key_eq, vbin), bitpos) - }; - case (#leaf l, _) { - let (ll, lr) = splitAssocList(l.keyvals, bitpos); - rec(bitpos, br1(lf1 ll, lf1 lr), tr) - }; - case (_, #leaf l) { - let (ll, lr) = splitAssocList(l.keyvals, bitpos); - rec(bitpos, tl, br2(lf2 ll, lf2 lr)) - }; - case (#branch b1, #branch b2) { - br3(rec(bitpos + 1, b1.left, b2.left), - rec(bitpos + 1, b1.right, b2.right)) - }; - - } - }; - - rec(0, tl, tr) - }; - - /** - `join` - --------- - This operation generalizes the notion of "set intersection" to - finite maps. Produces a "conjuctive image" of the two tries, where - the values of matching keys are combined with the given binary - operator, and unmatched key-value pairs are not present in the output. - - Implements the database idea of an ["inner join"](https://stackoverflow.com/questions/38549/what-is-the-difference-between-inner-join-and-outer-join). - - See also: - - - [`disj`](#disj) - - [`merge`](#merge) - - [`prod`](#prod) - - */ - public func join(tl:Trie, tr:Trie, - k_eq:(K,K)->Bool, vbin:(V,W)->X) - : Trie = label profile_trie_join : Trie - { - let key_eq = keyEq(k_eq); - - func br1(l:Trie, r:Trie) : Trie = branch(l,r); - func br2(l:Trie, r:Trie) : Trie = branch(l,r); - func br3(l:Trie, r:Trie) : Trie = branch(l,r); - - func rec(bitpos:Nat, tl:Trie, tr:Trie) : Trie = label profile_trie_join_rec : Trie { - func lf1(kvs:AssocList,V>) : Trie = leaf(kvs, bitpos); - func lf2(kvs:AssocList,W>) : Trie = leaf(kvs, bitpos); - func lf3(kvs:AssocList,X>) : Trie = leaf(kvs, bitpos); - - switch (tl, tr) { - case (#empty, _) { #empty }; - case (_, #empty) { #empty }; - case (#leaf l1, #leaf l2) { - lf3(AssocList.join,V,W,X>(l1.keyvals, l2.keyvals, key_eq, vbin)) - }; - case (#leaf l, _) { - let (ll, lr) = splitAssocList(l.keyvals, bitpos); - rec(bitpos, br1(lf1 ll, lf1 lr), tr) - }; - case (_, #leaf l) { - let (ll, lr) = splitAssocList(l.keyvals, bitpos); - rec(bitpos, tl, br2(lf2 ll, lf2 lr)) - }; - case (#branch b1, #branch b2) { - br3(rec(bitpos + 1, b1.left, b2.left), - rec(bitpos + 1, b1.right, b2.right)) - }; - - } - }; - rec(0, tl, tr) - }; - - /** - `foldUp` - ------------ - This operation gives a recursor for the internal structure of - tries. Many common operations are instantiations of this function, - either as clients, or as hand-specialized versions (e.g., see map, - mapFilter, exists and forAll below). - */ - public func foldUp(t:Trie, bin:(X,X)->X, leaf:(K,V)->X, empty:X) : X { - func rec(t:Trie) : X { - switch t { - case (#empty) { empty }; - case (#leaf l) { - AssocList.fold,V,X>( - l.keyvals, empty, - func (k:Key, v:V, x:X):X = - bin(leaf(k.key,v),x) - ) - }; - case (#branch(b)) { bin(rec(b.left), rec(b.right)) }; - } - }; - rec(t) - }; - - - /** - `prod` - --------- - - Conditional _catesian product_, where the given - operation `op` _conditionally_ creates output elements in the - resulting trie. - - The keyed structure of the input tries are not relevant for this - operation: all pairs are considered, regardless of keys matching or - not. Moreover, the resulting trie may use keys that are unrelated to - these input keys. - - See also: - - - [`disj`](#disj) - - [`join`](#join) - - [`merge`](#merge) - - */ - public func prod( - tl :Trie, - tr :Trie, - op :(K1,V1,K2,V2) -> ?(Key,V3), - k3_eq :(K3,K3) -> Bool - ) - : Trie - { - /**- binary case: merge disjoint results: */ - func merge (a:Trie, b:Trie) : Trie = - mergeDisjoint(a, b, k3_eq); - - /**- "`foldUp` squared" (imagine two nested loops): */ - foldUp>( - tl, merge, - func (k1:K1, v1:V1) : Trie { - foldUp>( - tr, merge, - func (k2:K2, v2:V2) : Trie { - switch (op(k1, v1, k2, v2)) { - case null #empty; - case (?(k3, v3)) { (insert(#empty, k3, k3_eq, v3)).0 }; - } - }, - #empty - ) - }, - #empty - ) - }; - - - /** - Build: An ADT for "Trie Builds" - ======================================== - - This module provides optimized variants of normal tries, for - (much!) more efficient PX retailer queries. - - The central insight is that for (unmaterialized) query results, we - do not need to actually build any resulting trie of the resulting - data, but rather, just need a collection of what would be in that - trie. Since query results can be large (quadratic in the DB size!), - avoiding the construction of this trie provides a considerable savings. - - To get this savings, we use an ADT for the operations that _would_ build this trie, - if evaluated. This structure specializes a rope: a balanced tree representing a - sequence. It is only as balanced as the tries from which we generate - these build ASTs. They have no intrinsic balance properties of their - own. - - */ - public module Build { - - /** Commands for building tries. - - For PL academics: Imagine commands for the IMP imperative language, - but where global memory consists of a single (anonymous) global trie */ - public type TrieBuild = { - #skip ; - #insert : (K, ?Hash, V) ; - #seq : { - count : Nat ; - left : TrieBuild ; - right : TrieBuild ; - } ; - }; - - public func buildCount(tb:TrieBuild) : Nat = - label profile_trie_buildCount : Nat { - switch tb { - case (#skip) 0; - case (#insert(_, _, _)) 1; - case (#seq(seq)) seq.count; - } - }; - - public func buildSeq(l:TrieBuild, r:TrieBuild) : TrieBuild = - label profile_trie_buildSeq : TrieBuild { - let sum = buildCount(l) + buildCount(r); - #seq { count = sum; left = l; right = r } - }; - - /** - `prodBuild` - --------------- - - Like `prod`, except do not actually do the insert calls, just - record them, as a (binary tree) data structure, isomorphic to the - recursion of this function (which is balanced, in expectation). - - See also: - - - [`prod`](#prod) - - */ - public func prodBuild( - tl :Trie, - tr :Trie, - op :(K1,V1,K2,V2) -> ?(K3,V3), - k3_eq :(K3,K3) -> Bool - ) - : TrieBuild - { - func outer_bin (a:TrieBuild, - b:TrieBuild) - : TrieBuild = - label profile_trie_prodBuild_outer_seqOfBranch : TrieBuild { - buildSeq(a, b) - }; - - func inner_bin (a:TrieBuild, - b:TrieBuild) - : TrieBuild = - label profile_trie_prodBuild_inner_seqOfBranch : TrieBuild { - buildSeq(a, b) - }; - - /**- "`foldUp` squared" (imagine two nested loops): */ - foldUp>( - tl, outer_bin, - func (k1:K1, v1:V1) : TrieBuild { - foldUp>( - tr, inner_bin, - func (k2:K2, v2:V2) : TrieBuild { - switch (op(k1, v1, k2, v2)) { - case null #skip; - case (?(k3, v3)) { #insert(k3, null, v3) }; - } - }, - #skip - ) - }, - #skip - ) - }; - - /** - `buildNth` - -------- - Project the nth key-value pair from the trie build. - - This position is meaningful only when the build contains multiple uses of one or more keys, otherwise it is not. - */ - public func buildNth(tb:TrieBuild, i:Nat) : ?(K, ?Hash, V) = label profile_triebuild_nth : (?(K, ?Hash, V)) { - func rec(tb:TrieBuild, i:Nat) : ?(K, ?Hash, V) = label profile_triebuild_nth_rec : (?(K, ?Hash, V)) { - switch tb { - case (#skip) P.unreachable(); - case (#insert (k,h,v)) label profile_trie_buildNth_rec_end : (?(K, ?Hash, V)) { - assert(i == 0); - ?(k,h,v) - }; - case (#seq s) label profile_trie_buildNth_rec_seq : (?(K, ?Hash, V)) { - let count_left = buildCount(s.left); - if (i < count_left) { rec(s.left, i) } - else { rec(s.right, i - count_left) } - }; - } - }; - if (i >= buildCount(tb)) { - return null - }; - rec(tb, i) - }; - - /** - `projectInnerBuild` - -------------- - - Like [`mergeDisjoint`](#mergedisjoint), except that it avoids the - work of actually merging any tries; rather, just record the work for - latter (if ever). - */ - public func projectInnerBuild(t : Trie>) - : TrieBuild - { - foldUp, TrieBuild> - ( t, - func (t1:TrieBuild, t2:TrieBuild):TrieBuild { buildSeq(t1, t2) }, - func (_:K1, t:TrieBuild): TrieBuild { t }, - #skip ) - }; - - /** - `buildToArray` - -------- - Gather the collection of key-value pairs into an array of a (possibly-distinct) type. - */ - public func buildToArray(tb:TrieBuild,f:(K,V)->W):[W] = - label profile_triebuild_toArray_begin : [W] { - let a = Array_tabulate ( - buildCount(tb), - func (i:Nat) : W = label profile_triebuild_toArray_nth : W { - let (k,_,v) = Option.unwrap<(K,?Hash,V)>(buildNth(tb, i)); - f(k, v) - } - ); - label profile_triebuild_toArray_end : [W] - a - }; - - /** - `buildToArray2` - -------- - Gather the collection of key-value pairs into an array of a (possibly-distinct) type. - - (Same semantics as `buildToArray`, but faster in practice.) - */ - public func buildToArray2(tb:TrieBuild,f:(K,V)->W):[W] { - let c = buildCount(tb); - let a = Array_init(c, null); - var i = 0; - func rec(tb:TrieBuild) = label profile_triebuild_toArray2_rec { - switch tb { - case (#skip) (); - case (#insert(k,_,v)) { a[i] := ?f(k,v); i := i + 1 }; - case (#seq(s)) { rec(s.left); rec(s.right) }; - } - }; - rec(tb); - Array_tabulate(c, func(i:Nat) : W = Option.unwrap(a[i])) - }; - - }; - - /** - `fold` - --------- - Fold over the key-value pairs of the trie, using an accumulator. - The key-value pairs have no reliable or meaningful ordering. - */ - public func fold(t:Trie, f:(K,V,X)->X, x:X) : X { - func rec(t:Trie, x:X) : X { - switch t { - case (#empty) x; - case (#leaf l) { - AssocList.fold,V,X>( - l.keyvals, x, - func (k:Key, v:V, x:X):X = f(k.key,v,x) - ) - }; - case (#branch(b)) { rec(b.left,rec(b.right,x)) }; - }; - }; - rec(t, x) - }; - - - /** - `exists` - -------- - Test whether a given key-value pair is present, or not. - */ - public func exists(t:Trie, f:(K,V)->Bool) : Bool { - func rec(t:Trie) : Bool { - switch t { - case (#empty) { false }; - case (#leaf l) { - List.exists<(Key,V)>( - l.keyvals, func ((k:Key,v:V)):Bool=f(k.key,v) - ) - }; - case (#branch(b)) { rec(b.left) or rec(b.right) }; - }; - }; - rec(t) - }; - - /** - `forAll` - --------- - Test whether all key-value pairs have a given property. - */ - public func forAll(t:Trie, f:(K,V)->Bool) : Bool { - func rec(t:Trie) : Bool { - switch t { - case (#empty) { true }; - case (#leaf l) { - List.all<(Key,V)>( - l.keyvals, func ((k:Key,v:V)):Bool=f(k.key,v) - ) - }; - case (#branch(b)) { rec(b.left) and rec(b.right) }; - }; - }; - rec(t) - }; - - /** - `nth` - -------- - Project the nth key-value pair from the trie. - - Note: This position is not meaningful; it's only here so that we - can inject tries into arrays given the Array_tabulate interface for - doing so. - */ - public func nth(t:Trie, i:Nat) : ?(Key, V) = label profile_trie_nth : (?(Key, V)) { - func rec(t:Trie, i:Nat) : ?(Key, V) = label profile_trie_nth_rec : (?(Key, V)) { - switch t { - case (#empty) P.unreachable(); - case (#leaf l) List.nth<(Key,V)>(l.keyvals, i); - case (#branch b) { - let count_left = count(b.left); - if (i < count_left) { rec(b.left, i) } - else { rec(b.right, i - count_left) } - } - } - }; - if (i >= count(t)) { - return null - }; - rec(t, i) - }; - - - /** - `toArray` - -------- - Gather the collection of key-value pairs into an array of a (possibly-distinct) type. - - ### Implementation notes: - - we use this function repeatedly in the Produce Exchange example - application, often on very large tries. - - Performance Profiling shows that it is important that this be - memory efficient, and reasonably time efficient, at large scales. - - To do so, we use a single array allocation (for the returned array) and we - sacrifice some efficiency in reading the input trie, and instead use function `nth` to - project each element with an independent trie traversal. - - This approach is somewhat forced on us by the type signature of - Array_tabulate, and the desire to only allocate one array; that requirement rules - out iterative mutation of an optionally-null array, since an imperative - approach which would give us the wrong return type. - - Since we want to statically rule out null output elements, and since the AS type system - cannot do that for an imperative approach unless we assume more about - the type W (e.g., the existence of "default values"), we settle for using `nth`. - - */ - public func toArray(t:Trie,f:(K,V)->W):[W] = - label profile_trie_toArray_begin : [W] { - let a = Array_tabulate ( - count(t), - func (i:Nat) : W = label profile_trie_toArray_nth : W { - let (k,v) = Option.unwrap<(Key,V)>(nth(t, i)); - f(k.key, v) - } - ); - label profile_trie_toArray_end : [W] - a - }; - - /** - `isEmpty` - ----------- - specialized foldUp operation. - Test for "deep emptiness": subtrees that have branching structure, - but no leaves. These can result from naive filtering operations; - filter uses this function to avoid creating such subtrees. - */ - public func isEmpty(t:Trie) : Bool = - count(t) == 0; - - /** - `filter` - ----------- - filter the key-value pairs by a given predicate. - */ - public func filter(t:Trie, f:(K,V)->Bool) : Trie { - func rec(t:Trie, bitpos:Nat) : Trie { - switch t { - case (#empty) { #empty }; - case (#leaf l) { - leaf( - List.filter<(Key,V)>( - l.keyvals, - func ((k:Key,v:V)):Bool = f(k.key,v) - ), - bitpos - ) - }; - case (#branch(b)) { - let fl = rec(b.left, bitpos+1); - let fr = rec(b.right, bitpos+1); - switch (isEmpty(fl), - isEmpty(fr)) { - case (true, true) #empty; - case (false, true) fr; - case (true, false) fl; - case (false, false) branch(fl, fr); - }; - } - } - }; - rec(t, 0) - }; - - /** - `mapFilter` - ----------- - map and filter the key-value pairs by a given predicate. - */ - public func mapFilter(t:Trie, f:(K,V)->?W) : Trie { - func rec(t:Trie, bitpos:Nat) : Trie { - switch t { - case (#empty) { #empty }; - case (#leaf l) { - leaf( - List.mapFilter<(Key,V),(Key,W)>( - l.keyvals, - // retain key and hash, but update key's value using f: - func ((k:Key,v:V)):?(Key,W) = { - switch (f(k.key,v)) { - case (null) null; - case (?w) (?({key=k.key; hash=k.hash}, w)); - }} - ), - bitpos - ) - }; - case (#branch(b)) { - let fl = rec(b.left, bitpos + 1); - let fr = rec(b.right, bitpos + 1); - switch (isEmpty(fl), - isEmpty(fr)) { - case (true, true) #empty; - case (false, true) fr; - case (true, false) fl; - case (false, false) branch(fl, fr); - }; - } - } - }; - rec(t, 0) - }; - - /** - `equalStructure` - ------------------ - - Test for equality, but naively, based on structure. - Does not attempt to remove "junk" in the tree; - For instance, a "smarter" approach would equate - `#bin{left=#empty;right=#empty}` - with - `#empty`. - We do not observe that equality here. - */ - public func equalStructure( - tl:Trie, - tr:Trie, - keq:(K,K)->Bool, - veq:(V,V)->Bool - ) : Bool { - func rec(tl:Trie, tr:Trie) : Bool { - switch (tl, tr) { - case (#empty, #empty) { true }; - case (#leaf l1, #leaf l2) { - List.isEq<(Key,V)> - (l1.keyvals, l2.keyvals, - func ((k1:Key, v1:V), (k2:Key, v2:V)) : Bool = - keq(k1.key, k2.key) and veq(v1,v2) - ) - }; - case (#branch(b1),#branch(b2)) { - rec(b1.left, b2.left) and rec(b2.right, b2.right) - }; - case _ { false }; - } - }; - rec(tl,tr) - }; - - /** - `replaceThen` - ------------ - replace the given key's value in the trie, - and only if successful, do the success continuation, - otherwise, return the failure value - */ - public func replaceThen(t : Trie, k:Key, k_eq:(K,K)->Bool, v2:V, - success: (Trie, V) -> X, - fail: () -> X) - : X - { - let (t2, ov) = replace(t, k, k_eq, ?v2); - switch ov { - case (null) { /* no prior value; failure to remove */ fail() }; - case (?v1) { success(t2, v1) }; - } - }; - - /** - `insertFresh` - ---------------- - insert the given key's value in the trie; return the new trie; assert that no prior value is associated with the key - */ - public func insertFresh(t : Trie, k:Key, k_eq:(K,K)->Bool, v:V) : Trie { - let (t2, none) = replace(t, k, k_eq, ?v); - switch none { - case (null) (); - case (?_) assert false; - }; - t2 - }; - - /** - `insert2D` - --------------- - insert the given key's value in the 2D trie; return the new 2D trie. - */ - public func insert2D(t : Trie2D, - k1:Key, k1_eq:(K1,K1)->Bool, - k2:Key, k2_eq:(K2,K2)->Bool, - v:V) - : Trie2D - { - let inner = find>(t, k1, k1_eq); - let (updated_inner, _) = switch inner { - case (null) { insert(#empty, k2, k2_eq, v) }; - case (?inner) { insert(inner, k2, k2_eq, v) }; - }; - let (updated_outer, _) = { insert>(t, k1, k1_eq, updated_inner) }; - updated_outer; - }; - - /** - `insert3D` - --------------- - insert the given key's value in the trie; return the new trie; - */ - public func insert3D - (t : Trie3D, - k1:Key, k1_eq:(K1,K1)->Bool, - k2:Key, k2_eq:(K2,K2)->Bool, - k3:Key, k3_eq:(K3,K3)->Bool, - v:V - ) - : Trie3D - { - let inner1 = find>(t, k1, k1_eq); - let (updated_inner1, _) = switch inner1 { - case (null) { - insert>( - #empty, k2, k2_eq, - (insert(#empty, k3, k3_eq, v)).0 - ) - }; - case (?inner1) { - let inner2 = find>(inner1, k2, k2_eq); - let (updated_inner2, _) = switch inner2 { - case (null) { insert(#empty, k3, k3_eq, v) }; - case (?inner2) { insert(inner2, k3, k3_eq, v) }; - }; - insert>( inner1, k2, k2_eq, updated_inner2 ) - }; - }; - let (updated_outer, _) = { insert>(t, k1, k1_eq, updated_inner1) }; - updated_outer; - }; - - /** - `remove` - ------------- - remove the given key's value in the trie; return the new trie - */ - public func remove(t : Trie, k:Key, k_eq:(K,K)->Bool) : (Trie, ?V) { - replace(t, k, k_eq, null) - }; - - /** - `removeThen` - ------------ - remove the given key's value in the trie, - and only if successful, do the success continuation, - otherwise, return the failure value - */ - public func removeThen(t : Trie, k:Key, k_eq:(K,K)->Bool, - success: (Trie, V) -> X, - fail: () -> X) - : X - { - let (t2, ov) = replace(t, k, k_eq, null); - switch ov { - case (null) { /* no prior value; failure to remove */ fail() }; - case (?v) { success(t2, v) }; - } - }; - - - /** - `remove2D` - -------------- - remove the given key-key pair's value in the 2D trie; return the - new trie, and the prior value, if any. - */ - public func remove2D(t : Trie2D, - k1:Key, k1_eq:(K1,K1)->Bool, - k2:Key, k2_eq:(K2,K2)->Bool) - : (Trie2D, ?V) - { - switch (find>(t, k1, k1_eq)) { - case (null) { - (t, null) - }; - case (?inner) { - let (updated_inner, ov) = remove(inner, k2, k2_eq); - let (updated_outer, _) = { - insert>(t, k1, k1_eq, updated_inner) - }; - (updated_outer, ov) - }; - } - }; - - /** - `remove3D` - --------------- - remove the given key-key pair's value in the 3D trie; return the - new trie, and the prior value, if any. - */ - public func remove3D - (t : Trie3D, - k1:Key, k1_eq:(K1,K1)->Bool, - k2:Key, k2_eq:(K2,K2)->Bool, - k3:Key, k3_eq:(K3,K3)->Bool, - ) - : (Trie3D, ?V) - { - switch (find>(t, k1, k1_eq)) { - case (null) { - (t, null) - }; - case (?inner) { - let (updated_inner, ov) = remove2D(inner, k2, k2_eq, k3, k3_eq); - let (updated_outer, _) = { - insert>(t, k1, k1_eq, updated_inner) - }; - (updated_outer, ov) - }; - } - }; - - - - /** - `mergeDisjoint2D` - -------------- - - Like [`mergeDisjoint`](#mergedisjoint), except instead of merging a - pair, it merges the collection of dimension-2 sub-trees of a 2D - trie. - - */ - public func mergeDisjoint2D(t : Trie2D, k1_eq:(K1,K1)->Bool, k2_eq:(K2,K2)->Bool) - : Trie - { - foldUp, Trie> - ( t, - func (t1:Trie, t2:Trie):Trie { mergeDisjoint(t1, t2, k2_eq) }, - func (_:K1, t:Trie): Trie { t }, - #empty ) - }; - - -/** - -Future work -============= - -Iterator objects -------------------- -for use in 'for ... in ...' patterns - -*/ -} diff --git a/stdlib/set.mo b/stdlib/trieSet.mo similarity index 97% rename from stdlib/set.mo rename to stdlib/trieSet.mo index 24a308d5f42..249c0e3800f 100644 --- a/stdlib/set.mo +++ b/stdlib/trieSet.mo @@ -1,7 +1,7 @@ /** - Sets - ======== + Trie-based Sets + ================ Sets are partial maps from element type to unit type, i.e., the partial map represents the set with its domain. @@ -17,7 +17,7 @@ in the future, we might avoid this via https://dfinity.atlassian.net/browse/AST-32 */ -import Trie "trie2.mo"; +import Trie "trie.mo"; import Hash "hash.mo"; module { From 44f35eaa520f8139b42135839a1fc8472ad7ee83 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 14 Nov 2019 16:33:24 +0100 Subject: [PATCH 0579/1176] Implement inter-canister messaging MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit both in the backend and in ic-stub You can only call `a.foo` when in `actor a { … }`, i.e. self-calls that go _through_ your own actor id. Issuing or handling rejects untested so far. --- ic-stub/src/IC/Canister/Imp.hs | 191 +++++++++++---- ic-stub/src/IC/Canister/Pure.hs | 68 ++++-- ic-stub/src/IC/Stub.hs | 231 ++++++++++++++---- ic-stub/src/IC/Types.hs | 32 ++- ic-stub/src/IC/Wasm/Winter.hs | 20 +- ic-stub/src/ic-stub-run.hs | 2 +- nix/haskell-packages.nix | 6 +- rts/idl.c | 2 + src/codegen/compile.ml | 205 ++++++++++++---- src/mo_frontend/typing.ml | 1 - test/run-drun/ic-calls.mo | 2 +- test/run-drun/ok/counter.drun-run.ok | 18 -- .../ok/hello-world-return.drun-run.ok | 3 - test/run-drun/ok/ic-calls.comp.ok | 6 - test/run-drun/ok/ic-calls.comp.ret.ok | 1 - test/run-drun/ok/idl-any.drun-run.ok | 57 ----- test/run-drun/ok/idl-bad.drun-run.ok | 2 - test/run-drun/ok/idl-bad.ic-stub-run.ok | 2 +- test/run-drun/ok/idl-field-escape.drun-run.ok | 5 - test/run-drun/ok/idl-nary.drun-run.ok | 12 - test/run-drun/ok/idl-nary.ic-stub-run.ok | 4 +- test/run-drun/ok/idl-nat-int.drun-run.ok | 5 - test/run-drun/ok/idl-option.drun-run.ok | 7 - test/run-drun/ok/idl-pair.drun-run.ok | 2 - test/run-drun/ok/idl-record.drun-run.ok | 9 - test/run-drun/ok/idl-tuple.drun-run.ok | 5 - test/run-drun/ok/idl-unit.drun-run.ok | 2 - test/run-drun/ok/idl-variant.drun-run.ok | 2 - test/run-drun/ok/idl-vector.drun-run.ok | 2 - test/run-drun/ok/large-array.drun-run.ok | 1 - test/run-drun/ok/oom.drun-run.ok | 3 - test/run-drun/ok/print-from-init.drun-run.ok | 2 - test/run-drun/ok/query.drun-run.ok | 34 --- test/run-drun/ok/reject.drun-run.ok | 9 - test/run-drun/ok/reversi.drun-run.ok | 9 - test/run-drun/ok/unsupported.comp.ok | 2 - test/run.sh | 2 +- 37 files changed, 596 insertions(+), 370 deletions(-) delete mode 100644 test/run-drun/ok/counter.drun-run.ok delete mode 100644 test/run-drun/ok/hello-world-return.drun-run.ok delete mode 100644 test/run-drun/ok/ic-calls.comp.ret.ok delete mode 100644 test/run-drun/ok/idl-any.drun-run.ok delete mode 100644 test/run-drun/ok/idl-bad.drun-run.ok delete mode 100644 test/run-drun/ok/idl-field-escape.drun-run.ok delete mode 100644 test/run-drun/ok/idl-nary.drun-run.ok delete mode 100644 test/run-drun/ok/idl-nat-int.drun-run.ok delete mode 100644 test/run-drun/ok/idl-option.drun-run.ok delete mode 100644 test/run-drun/ok/idl-pair.drun-run.ok delete mode 100644 test/run-drun/ok/idl-record.drun-run.ok delete mode 100644 test/run-drun/ok/idl-tuple.drun-run.ok delete mode 100644 test/run-drun/ok/idl-unit.drun-run.ok delete mode 100644 test/run-drun/ok/idl-variant.drun-run.ok delete mode 100644 test/run-drun/ok/idl-vector.drun-run.ok delete mode 100644 test/run-drun/ok/large-array.drun-run.ok delete mode 100644 test/run-drun/ok/oom.drun-run.ok delete mode 100644 test/run-drun/ok/print-from-init.drun-run.ok delete mode 100644 test/run-drun/ok/query.drun-run.ok delete mode 100644 test/run-drun/ok/reject.drun-run.ok delete mode 100644 test/run-drun/ok/reversi.drun-run.ok diff --git a/ic-stub/src/IC/Canister/Imp.hs b/ic-stub/src/IC/Canister/Imp.hs index 4f807d8c745..2bae97fc5ac 100644 --- a/ic-stub/src/IC/Canister/Imp.hs +++ b/ic-stub/src/IC/Canister/Imp.hs @@ -14,6 +14,7 @@ module IC.Canister.Imp , runESST , rawInitializeMethod , rawUpdateMethod + , rawCallbackMethod , rawQueryMethod , silently ) @@ -27,6 +28,7 @@ import Control.Monad.ST import Control.Monad.Except import Data.STRef import Data.Maybe +import Data.Int import IC.Types import IC.Wasm.Winter @@ -43,18 +45,17 @@ data ExecutionState s = ExecutionState , self_id :: CanisterId , params :: Params , response :: Maybe Response - , reply_data :: Blob + , calls :: [MethodCall] } - initalExecutionState :: CanisterId -> Instance s -> ExecutionState s initalExecutionState self_id inst = ExecutionState { inst , self_id , params = Params Nothing Nothing 0 "" , response = Nothing - , reply_data = mempty + , calls = mempty } type ESRef s = (STRef s Bool, STRef s (Maybe (ExecutionState s))) @@ -86,14 +87,21 @@ silently (pref, _esref) f = do stToPrim $ writeSTRef pref before return x -getsES :: ESRef s -> (ExecutionState s -> b) -> ExceptT String (ST s) b +getsES :: ESRef s -> (ExecutionState s -> b) -> HostM s b getsES (_, esref) f = lift (readSTRef esref) >>= \case Nothing -> throwError "System API not available yet" Just es -> return (f es) -modES :: ESRef s -> (ExecutionState s -> ExecutionState s) -> ExceptT String (ST s) () +modES :: ESRef s -> (ExecutionState s -> ExecutionState s) -> HostM s () modES (_, esref) f = lift $ modifySTRef esref (fmap f) +setResponse :: ESRef s -> Response -> HostM s () +setResponse esref r = modES esref $ \es -> + es { response = Just r } + +appendCall :: ESRef s -> MethodCall -> HostM s () +appendCall esref c = modES esref $ \es -> + es { calls = calls es ++ [c] } putBytes :: PrimMonad m => ESRef (PrimState m) -> BS.ByteString -> m () putBytes (pref, _esref) bytes = @@ -105,83 +113,157 @@ putBytes (pref, _esref) bytes = systemAPI :: forall s. ESRef s -> Imports s systemAPI esref = [ (,) "ic" - [ (,,,) "trap" [i32, i32] [] $ \case - [_v1, _v2] -> throwError "explicit trap" - _ -> fail "ic.trap: invalid argument" + [ (,,,) "trap" [i32, i32] [] explicit_trap ] , (,) "msg" - [ (,,,) "reject" [i64, i32, i32] [] msg_reject - , (,,,) "reply" [i64, i32, i32] [] msg_reply + [ (,,,) "reject" [i64, i32, i32] [] $ with_nonce msg_reject + , (,,,) "reply" [i64, i32, i32] [] $ with_nonce msg_reply , unimplemented "error_code" [i64] [i32] - , (,,,) "arg_data_copy" [i64, i32, i32, i32] [] arg_data_copy - , (,,,) "arg_data_size" [i64] [i32] arg_data_size + , (,,,) "arg_data_copy" [i64, i32, i32, i32] [] $ with_nonce arg_data_copy + , (,,,) "arg_data_size" [i64] [i32] $ with_nonce arg_data_size ] , (,) "debug" [ (,,,) "print" [i32, i32] [] debug_print ] + , (,) "ic0" + [ (,,,) "call_simple" (replicate 10 i32) [i32] call_simple + , (,,,) "canister_self_len" [] [i32] canister_self_len + , (,,,) "canister_self_copy" (replicate 3 i32) [] canister_self_copy + ] ] where + -- Utilities + unimplemented name arg ret = (,,,) name arg ret $ \_ -> throwError $ "unimplemented: " ++ name i32 = I32Type i64 = I64Type - debug_print :: [Value] -> HostFunc s - debug_print [I32 ptr, I32 len] = do + with_nonce :: ([Value] -> HostFunc s) -> ([Value] -> HostFunc s) + with_nonce f (I64 _nonce : args) = f args + with_nonce _ _ = fail "with_nonce: missing or wrongly typed nonce argument" + + copy_to_canister :: String -> Int32 -> Int32 -> Int32 -> Blob -> HostM s () + copy_to_canister name dst offset len blob = do + unless (offset == 0) $ + throwError $ name ++ ": offset /= 0 not suppoted" + unless (len == fromIntegral (BS.length blob)) $ + throwError $ name ++ ": len not full blob not suppoted" + i <- getsES esref inst + -- TODO Bounds checking + setBytes i (fromIntegral dst) blob + + copy_from_canister :: String -> Int32 -> Int32 -> HostM s Blob + copy_from_canister _name src len = do i <- getsES esref inst - bytes <- getBytes i (fromIntegral ptr) len + getBytes i (fromIntegral src) len + + -- The system calls + + -- (TODO: Give them proper Haskell types and write generic code that takes + -- apart the values) + + debug_print :: [Value] -> HostFunc s + debug_print [I32 src, I32 len] = do + -- TODO: This should be a non-trapping copy + bytes <- copy_from_canister "debug_print" src len putBytes esref bytes return [] debug_print _ = fail "debug_print: invalid argument" + explicit_trap :: [Value] -> HostFunc s + explicit_trap [I32 src, I32 len] = do + -- TODO: This should be a non-trapping copy + bytes <- copy_from_canister "ic.trap" src len + let msg = BSU.toString bytes + throwError $ "canister trapped explicitly: " ++ msg + explicit_trap _ = fail "explicit_trap: invalid argument" + + canister_self_len :: [Value] -> HostFunc s + canister_self_len [] = do + id <- getsES esref self_id + return [I32 (fromIntegral (BS.length (rawEntityId id)))] + canister_self_len _ = fail "arg_data_size: invalid argument" + + canister_self_copy :: [Value] -> HostFunc s + canister_self_copy [I32 dst, I32 offset, I32 len] = do + id <- getsES esref self_id + copy_to_canister "canister_self_copy" dst offset len (rawEntityId id) + return [] + canister_self_copy _ = fail "arg_data_size: invalid argument" + arg_data_size :: [Value] -> HostFunc s - arg_data_size [I64 _nonce] = do + arg_data_size [] = do blob <- getsES esref (param_dat . params) >>= maybe (throwError "arg_data_size: No argument") return return [I32 (fromIntegral (BS.length blob))] arg_data_size _ = fail "arg_data_size: invalid argument" arg_data_copy :: [Value] -> HostFunc s - arg_data_copy [I64 _nonce, I32 dst, I32 len, I32 offset] = do + arg_data_copy [I32 dst, I32 len, I32 offset] = do blob <- getsES esref (param_dat . params) >>= maybe (throwError "arg_data_size: No argument") return - unless (offset == 0) $ throwError "arg_data_copy: offset /= 0 not suppoted" - unless (len == fromIntegral (BS.length blob)) $ throwError "arg_data_copy: len not full blob not suppoted" - i <- getsES esref inst - -- TODO Bounds checking - setBytes i (fromIntegral dst) blob + copy_to_canister "arg_data_copy" dst offset len blob return [] arg_data_copy _ = fail "arg_data_copy: invalid argument" msg_reply :: [Value] -> HostFunc s - msg_reply [I64 _nonce, I32 ptr, I32 len] = do - i <- getsES esref inst - bytes <- getBytes i (fromIntegral ptr) len - modES esref (\es -> es { response = Just (Reply bytes) }) + msg_reply [I32 src, I32 len] = do + bytes <- copy_from_canister "debug_print" src len + setResponse esref (Reply bytes) return [] msg_reply _ = fail "msg_reply: invalid argument" msg_reject :: [Value] -> HostFunc s - msg_reject [I64 _nonce, I32 ptr, I32 len] = do - i <- getsES esref inst - bytes <- getBytes i (fromIntegral ptr) len + msg_reject [I32 src, I32 len] = do + bytes <- copy_from_canister "debug_print" src len let msg = BSU.toString bytes modES esref (\es -> es { response = Just (Reject (RC_CANISTER_REJECT, msg)) }) return [] msg_reject _ = fail "msg_reply: invalid argument" + call_simple :: [Value] -> HostFunc s + call_simple + [ I32 callee_src + , I32 callee_len + , I32 name_src + , I32 name_len + , I32 reply_fun + , I32 reply_env + , I32 reject_fun + , I32 reject_env + , I32 data_src + , I32 data_len + ] = do + callee <- copy_from_canister "call_simple" callee_src callee_len + method_name <- copy_from_canister "call_simple" name_src name_len + arg <- copy_from_canister "call_simple" data_src data_len + + appendCall esref $ MethodCall + { call_callee = EntityId callee + , call_method_name = BSU.toString method_name -- TODO: check for valid UTF8 + , call_arg = arg + , call_callback = Callback + { reply_callback = WasmClosure reply_fun reply_env + , reject_callback = WasmClosure reject_fun reject_env + } + } + + return [I32 0] + call_simple _ = fail "call_simple: invalid argument" + type RawState s = (ESRef s, CanisterId, Instance s) -rawInitializeMethod :: ESRef s -> Module -> CanisterId -> Arg -> ST s (TrapOr (RawState s)) -rawInitializeMethod esref wasm_mod cid arg = do +rawInitializeMethod :: ESRef s -> Module -> CanisterId -> EntityId -> Blob -> ST s (TrapOr (RawState s)) +rawInitializeMethod esref wasm_mod cid caller dat = do result <- runExceptT $ do inst <- initialize wasm_mod (systemAPI esref) let es = (initalExecutionState cid inst) { params = Params - { param_dat = Just $ dat arg - , param_caller = Just $ caller arg + { param_dat = Just dat + , param_caller = Just caller , reject_code = 0 , reject_message = "" } @@ -191,36 +273,39 @@ rawInitializeMethod esref wasm_mod cid arg = do when ("canister_init" `elem` exportedFunctions wasm_mod) $ void $ withES esref es $ invokeExport inst "canister_init" [I64 0] + -- TODO: Check no calls are made return (esref, cid, inst) case result of - Left err -> return $ Trap err + Left err -> return $ Trap err Right raw_state -> return $ Return raw_state -rawQueryMethod :: RawState s -> MethodName -> Arg -> ST s (TrapOr Response) -rawQueryMethod (esref, cid, inst) method arg = do +rawQueryMethod :: RawState s -> MethodName -> EntityId -> Blob -> ST s (TrapOr Response) +rawQueryMethod (esref, cid, inst) method caller dat = do let es = (initalExecutionState cid inst) { params = Params - { param_dat = Just $ dat arg - , param_caller = Just $ caller arg + { param_dat = Just dat + , param_caller = Just caller , reject_code = 0 , reject_message = "" } } result <- runExceptT $ withES esref es $ invokeExport inst ("canister_query " ++ method) [I64 0] + -- TODO: Check no calls are made + case result of Left err -> return $ Trap err Right (_, es') | Just r <- response es' -> return $ Return r | otherwise -> return $ Trap "No response" -rawUpdateMethod :: RawState s -> MethodName -> Arg -> ST s (TrapOr ({- List MethodCall, -} Maybe Response)) -rawUpdateMethod (esref, cid, inst) method arg = do +rawUpdateMethod :: RawState s -> MethodName -> EntityId -> Blob -> ST s (TrapOr ([MethodCall], Maybe Response)) +rawUpdateMethod (esref, cid, inst) method caller dat = do let es = (initalExecutionState cid inst) { params = Params - { param_dat = Just $ dat arg - , param_caller = Just $ caller arg + { param_dat = Just dat + , param_caller = Just caller , reject_code = 0 , reject_message = "" } @@ -230,5 +315,25 @@ rawUpdateMethod (esref, cid, inst) method arg = do invokeExport inst ("canister_update " ++ method) [I64 0] case result of Left err -> return $ Trap err - Right (_, es') -> return $ Return (response es') + Right (_, es') -> return $ Return (calls es', response es') + +rawCallbackMethod :: RawState s -> Callback -> EntityId -> Response -> ST s (TrapOr ([MethodCall], Maybe Response)) +rawCallbackMethod (esref, cid, inst) callback caller res = do + let param_caller = Just caller + let params = case res of + Reply dat -> + Params { param_dat = Just dat, param_caller, reject_code = 0, reject_message = "" } + Reject (rc, reject_message) -> + Params { param_dat = Nothing, param_caller, reject_code = rejectCode rc, reject_message } + let es = (initalExecutionState cid inst) { params } + + let WasmClosure fun_idx env = case res of + Reply {} -> reply_callback callback + Reject {} -> reject_callback callback + + result <- runExceptT $ withES esref es $ + invokeTable inst fun_idx [I64 0, I32 env] + case result of + Left err -> return $ Trap err + Right (_, es') -> return $ Return (calls es', response es') diff --git a/ic-stub/src/IC/Canister/Pure.hs b/ic-stub/src/IC/Canister/Pure.hs index b80fe1c24ea..12a1db29da2 100644 --- a/ic-stub/src/IC/Canister/Pure.hs +++ b/ic-stub/src/IC/Canister/Pure.hs @@ -31,17 +31,19 @@ import IC.Wasm.Winter (parseModule, exportedFunctions, Module) import IC.Canister.Imp data WasmState - = WSInit Module CanisterId Arg - | WSUpdate MethodName Arg WasmState + = WSInit Module CanisterId EntityId Blob + | WSUpdate MethodName EntityId Blob WasmState + | WSCallback Callback EntityId Response WasmState -type InitFunc = (CanisterId, Arg) -> TrapOr WasmState -type UpdateFunc = WasmState -> TrapOr (WasmState, {- List MethodCall, -} Maybe Response) +type InitFunc = CanisterId -> EntityId -> Blob -> TrapOr WasmState +type UpdateFunc = WasmState -> TrapOr (WasmState, [MethodCall], Maybe Response) type QueryFunc = WasmState -> TrapOr Response data CanisterModule = CanisterModule { init_method :: InitFunc - , update_methods :: MethodName ↦ (Arg -> UpdateFunc) - , query_methods :: MethodName ↦ (Arg -> QueryFunc) + , update_methods :: MethodName ↦ (EntityId -> Blob -> UpdateFunc) + , query_methods :: MethodName ↦ (EntityId -> Blob -> QueryFunc) + , callbacks :: Callback -> EntityId -> Response -> UpdateFunc } parseCanister :: Blob -> Either String CanisterModule @@ -52,9 +54,9 @@ parseCanister bytes = concreteToAbstractModule :: Module -> CanisterModule concreteToAbstractModule wasm_mod = CanisterModule - { init_method = \(cid, arg) -> initializeMethod wasm_mod cid arg + { init_method = \cid caller dat -> initializeMethod wasm_mod cid caller dat , update_methods = M.fromList - [ (m, \arg wasm_state -> updateMethod m arg wasm_state) + [ (m, \caller dat wasm_state -> updateMethod m caller dat wasm_state) | n <- exportedFunctions wasm_mod , Just m <- return $ stripPrefix "canister_update " n ] @@ -63,27 +65,43 @@ concreteToAbstractModule wasm_mod = CanisterModule | n <- exportedFunctions wasm_mod , Just m <- return $ stripPrefix "canister_query " n ] + , callbacks = callbackMethod } -initializeMethod :: Module -> CanisterId -> Arg -> TrapOr WasmState -initializeMethod wasm_mod cid arg = runESST $ \esref -> do - result <- rawInitializeMethod esref wasm_mod cid arg +initializeMethod :: Module -> CanisterId -> EntityId -> Blob -> TrapOr WasmState +initializeMethod wasm_mod cid caller dat = runESST $ \esref -> do + result <- rawInitializeMethod esref wasm_mod cid caller dat + let state' = WSInit wasm_mod cid caller dat case result of Trap err -> return $ Trap err - Return _raw_state -> return $ Return $ WSInit wasm_mod cid arg + Return _raw_state -> return $ Return state' -updateMethod :: MethodName -> Arg -> WasmState -> TrapOr (WasmState, Maybe Response) -updateMethod m arg s = runESST $ \esref -> do +updateMethod :: + MethodName -> EntityId -> Blob -> + WasmState -> TrapOr (WasmState, [MethodCall], Maybe Response) +updateMethod m caller dat s = runESST $ \esref -> do rs <- replay esref s - tor <- rawUpdateMethod rs m arg + tor <- rawUpdateMethod rs m caller dat + let state' = WSUpdate m caller dat s case tor of Trap msg -> return $ Trap msg - Return r -> return $ Return (WSUpdate m arg s, r) + Return (calls, r) -> return $ Return (state', calls, r) -queryMethod :: MethodName -> Arg -> WasmState -> TrapOr Response -queryMethod m arg s = runESST $ \esref -> do +callbackMethod :: + Callback -> EntityId -> Response -> + WasmState -> TrapOr (WasmState, [MethodCall], Maybe Response) +callbackMethod cb caller r s = runESST $ \esref -> do rs <- replay esref s - rawQueryMethod rs m arg + tor <- rawCallbackMethod rs cb caller r + let state' = WSCallback cb caller r s + case tor of + Trap msg -> return $ Trap msg + Return (calls, r) -> return $ Return (state', calls, r) + +queryMethod :: MethodName -> EntityId -> Blob -> WasmState -> TrapOr Response +queryMethod m caller dat s = runESST $ \esref -> do + rs <- replay esref s + rawQueryMethod rs m caller dat replay :: ESRef s -> WasmState -> ST s (RawState s) @@ -92,10 +110,14 @@ replay esref s = silently esref $ go s trapToFail (Trap _err) = fail "replay failed" trapToFail (Return x) = return x - go (WSInit wasm_mod cid arg) = - rawInitializeMethod esref wasm_mod cid arg >>= trapToFail - go (WSUpdate m arg s) = do + go (WSInit wasm_mod cid caller dat) = + rawInitializeMethod esref wasm_mod cid caller dat >>= trapToFail + go (WSUpdate m caller dat s) = do + rs <- go s + _ <- rawUpdateMethod rs m caller dat >>= trapToFail + return rs + go (WSCallback cb caller r s) = do rs <- go s - _ <- rawUpdateMethod rs m arg >>= trapToFail + _ <- rawCallbackMethod rs cb caller r >>= trapToFail return rs diff --git a/ic-stub/src/IC/Stub.hs b/ic-stub/src/IC/Stub.hs index 29cea974a5c..4d10470e0ef 100644 --- a/ic-stub/src/IC/Stub.hs +++ b/ic-stub/src/IC/Stub.hs @@ -8,25 +8,33 @@ {-# LANGUAGE RankNTypes #-} {-# OPTIONS_GHC -Wmissing-signatures #-} -module IC.Stub where +module IC.Stub + ( IC + , AsyncRequest(..) + , SyncRequest(..) + , RequestStatus(..) + , CompletionValue(..) + , ReqResponse + , initialIC + , submitRequest, readRequest + , runToCompletion + , requestId + ) +where import qualified Data.ByteString.Lazy as BS import qualified Data.ByteString.Lazy.Char8 as BSC import qualified Data.Map as M import Data.List import Data.Maybe +import Control.Monad import Control.Monad.State.Class +-- import Debug.Trace + import IC.Types import IC.Canister.Pure -rejectCode :: RejectCode -> Int -rejectCode RC_SYS_FATAL = 1 -rejectCode RC_SYS_TRANSIENT = 2 -rejectCode RC_DESTINATION_INVALID = 3 -rejectCode RC_CANISTER_REJECT = 4 -rejectCode RC_CANISTER_ERROR = 5 - -- Abstract HTTP Interface data AsyncRequest @@ -66,13 +74,46 @@ data CanState = CanState type ICT = MonadState IC +data EntryPoint + = Public MethodName Blob + | Closure Callback Response + deriving Show + +type CallId = Int + +data CallContext = CallContext + { canister :: CanisterId + , origin :: CallOrigin + , responded :: Bool + , last_trap :: Maybe String + } + deriving Show + +data CallOrigin + = FromUser AsyncRequest + | FromCanister CallId Callback + deriving Show + +data Message = + CallMessage + { call_context :: CallId + , entry :: EntryPoint + } + | ResponseMessage + { call_context :: CallId + , response :: Response + } + deriving Show + data IC = IC { canisters :: CanisterId ↦ Maybe CanState , requests :: AsyncRequest ↦ RequestStatus + , messages :: [Message] + , call_contexts :: CallId ↦ CallContext } initialIC :: IC -initialIC = IC mempty mempty +initialIC = IC mempty mempty mempty mempty submitRequest :: ICT m => AsyncRequest -> m () submitRequest r = @@ -100,7 +141,7 @@ readRequest (QueryRequest method arg) = case M.lookup method (query_methods can_mod) of Nothing -> return $ Rejected (RC_DESTINATION_INVALID, "query method does not exist") Just f -> - case f (Arg arg dummyUserId) wasm_state of + case f dummyUserId arg wasm_state of Trap msg -> return $ Rejected (RC_CANISTER_ERROR, "canister trapped: " ++ msg) Return (Reply res) -> return $ Completed (CompleteArg res) Return (Reject (rc,rm)) -> return $ Rejected (rc, rm) @@ -109,11 +150,27 @@ nextRecieved :: ICT m => m (Maybe AsyncRequest) nextRecieved = gets $ \ic -> listToMaybe [ r | (r, Received) <- M.toList (requests ic) ] -nextStarved :: ICT m => m (Maybe AsyncRequest) +nextStarved :: ICT m => m (Maybe CallId) nextStarved = gets $ \ic -> listToMaybe -- TODO: This should return a starved calling context. -- Until we have them, we treat requests in Processing state as starved - [ r | (r, Processing) <- M.toList (requests ic) ] + [ c + | (c, ctxt) <- M.toList (call_contexts ic) + , not $ responded ctxt + , null [ () | ResponseMessage { call_context = c' } <- messages ic, c' == c ] + , null + [ () + | CallContext { responded = False, origin = FromCanister c' _} + <- M.elems (call_contexts ic) + , c' == c + ] + ] + +nextMessage :: ICT m => m (Maybe Message) +nextMessage = state $ \ic -> + case messages ic of + [] -> (Nothing, ic) + (m:ms) -> (Just m, ic { messages = ms }) setReqStatus :: ICT m => AsyncRequest -> RequestStatus -> m () setReqStatus r s = @@ -132,54 +189,144 @@ setCanisterState cid wasm_state = }) dummyCanisterId :: CanisterId -dummyCanisterId = BS.pack [0xDE, 0xAD, 0xBE, 0xEF] +dummyCanisterId = EntityId $ BS.pack [0xDE, 0xAD, 0xBE, 0xEF] dummyUserId :: CanisterId -dummyUserId = BS.pack [0xCA, 0xFF, 0xEE] +dummyUserId = EntityId $ BS.pack [0xCA, 0xFF, 0xEE] processRequest :: ICT m => AsyncRequest -> m () -processRequest r@(InstallRequest can_mod arg) = +processRequest r@(InstallRequest can_mod dat) = case parseCanister can_mod of Left err -> - setReqStatus r (Rejected (RC_SYS_FATAL, "Parsing failed: " ++ err)) + setReqStatus r $ Rejected (RC_SYS_FATAL, "Parsing failed: " ++ err) Right can_mod -> - case init_method can_mod (dummyCanisterId, Arg arg dummyUserId) of + case init_method can_mod dummyCanisterId dummyUserId dat of Trap msg -> - setReqStatus r (Rejected (RC_CANISTER_ERROR, "Initialization trapped: " ++ msg)) + setReqStatus r $ Rejected (RC_CANISTER_ERROR, "Initialization trapped: " ++ msg) Return wasm_state -> do createCanister dummyCanisterId can_mod wasm_state - setReqStatus r (Completed CompleteUnit) + setReqStatus r $ Completed CompleteUnit processRequest r@(UpdateRequest method arg) = do + + let canister = dummyCanisterId + + ctxt_id <- newCallContext $ CallContext + { canister = canister + , origin = FromUser r + , responded = False + , last_trap = Nothing + } + enqueueMessage $ CallMessage + { call_context = ctxt_id + , entry = Public method arg + } setReqStatus r Processing - gets (M.lookup dummyCanisterId . canisters) >>= \case - Nothing -> setReqStatus r $ Rejected (RC_DESTINATION_INVALID, "canister does not exist") - Just Nothing -> setReqStatus r $ Rejected (RC_DESTINATION_INVALID, "canister is empty") - Just (Just (CanState wasm_state can_mod)) -> - case M.lookup method (update_methods can_mod) of - Nothing -> setReqStatus r $ Rejected (RC_DESTINATION_INVALID, "update method does not exist") - Just f -> - case f (Arg arg dummyUserId) wasm_state of - Trap msg -> setReqStatus r $ Rejected (RC_CANISTER_ERROR, "canister trapped: " ++ msg) - Return (new_state, mb_response) -> do - setCanisterState dummyCanisterId new_state - case mb_response of - Just (Reply res) -> setReqStatus r $ Completed (CompleteArg res) - Just (Reject (rc,rm)) -> setReqStatus r $ Rejected (rc, rm) - Nothing -> return () -- processRequest r = setReqStatus r (Rejected (0, "Unknown request type")) -starvedRequest :: ICT m => AsyncRequest -> m () -starvedRequest r@(UpdateRequest _method _arg) = - setReqStatus r $ Rejected (RC_CANISTER_ERROR, "canister did not respond") -starvedRequest r = - fail $ "Did not expect request " ++ show r ++ " to starve" +enqueueMessage :: ICT m => Message -> m () +enqueueMessage m = modify $ \ic -> ic { messages = messages ic ++ [m] } + +newCallContext :: ICT m => CallContext -> m CallId +newCallContext cc = state go + where + go ic = (i, ic { call_contexts = M.insert i cc (call_contexts ic)}) + where + i | M.null (call_contexts ic) = 0 + | otherwise = fst (M.findMax (call_contexts ic)) + 1 + +modifyContext :: ICT m => CallId -> (CallContext -> CallContext) -> m () +modifyContext ctxt_id f = + modify $ \ic -> ic { call_contexts = M.adjust f ctxt_id (call_contexts ic) } + +respondContext :: ICT m => CallId -> Response -> m () +respondContext ctxt_id response = do + -- TODO: check no prior response + modifyContext ctxt_id $ \ctxt -> ctxt { responded = True } + enqueueMessage $ ResponseMessage { call_context = ctxt_id, response } + +rememberTrap :: ICT m => CallId -> String -> m () +rememberTrap ctxt_id msg = + modifyContext ctxt_id $ \ctxt -> ctxt { last_trap = Just msg } + +callerOfCallID :: ICT m => CallId -> m EntityId +callerOfCallID ctxt_id = do + ctxt <- gets ((M.! ctxt_id) . call_contexts) + case origin ctxt of + FromUser _request -> return dummyUserId + FromCanister other_ctxt_id _callback -> calleeOfCallID other_ctxt_id + +calleeOfCallID :: ICT m => CallId -> m EntityId +calleeOfCallID ctxt_id = do + ctxt <- gets ((M.! ctxt_id) . call_contexts) + return $ canister ctxt + +invokeEntry :: ICT m => + CallId -> CanState -> EntryPoint -> + m (TrapOr (WasmState, [MethodCall], Maybe Response)) +invokeEntry ctxt_id (CanState wasm_state can_mod) entry = do + caller <- callerOfCallID ctxt_id + case entry of + Public method dat -> + case M.lookup method (update_methods can_mod) of + Just f -> return $ f caller dat wasm_state + Nothing -> return $ Return (wasm_state, [], Just $ Reject (RC_DESTINATION_INVALID, "update method does not exist: " ++ method)) + Closure cb r -> + return $ callbacks can_mod cb caller r wasm_state + +processMessage :: ICT m => Message -> m () +processMessage (CallMessage ctxt_id entry) = do + callee <- calleeOfCallID ctxt_id + let res r = respondContext ctxt_id r + gets (M.lookup callee . canisters) >>= \case + Nothing -> res $ Reject (RC_DESTINATION_INVALID, "canister does not exist: " ++ show callee) + Just Nothing -> res $ Reject (RC_DESTINATION_INVALID, "canister is empty") + Just (Just cs) -> + invokeEntry ctxt_id cs entry >>= \case + Trap msg -> + rememberTrap ctxt_id msg + Return (new_state, calls, mb_response) -> do + setCanisterState dummyCanisterId new_state + forM_ calls $ \call -> do + new_ctxt_id <- newCallContext $ CallContext + { canister = call_callee call + , origin = FromCanister ctxt_id (call_callback call) + , responded = False + , last_trap = Nothing + } + enqueueMessage $ CallMessage + { call_context = new_ctxt_id + , entry = Public (call_method_name call) (call_arg call) + } + mapM_ res mb_response + +processMessage (ResponseMessage ctxt_id response) = do + ctxt <- gets ((M.! ctxt_id) . call_contexts) + case origin ctxt of + FromUser request -> setReqStatus request $ + case response of + Reject (rc, msg) -> Rejected (rc, msg) + Reply blob -> Completed (CompleteArg blob) + FromCanister other_ctxt_id callback -> + enqueueMessage $ CallMessage + { call_context = other_ctxt_id + , entry = Closure callback response + } + +starveContext :: ICT m => CallId -> m () +starveContext ctxt_id = do + ctxt <- gets ((M.! ctxt_id) . call_contexts) + let msg | Just t <- last_trap ctxt = "canister trapped: " ++ t + | otherwise = "canister did not respond" + respondContext ctxt_id $ Reject (RC_CANISTER_ERROR, msg) runToCompletion :: ICT m => m () runToCompletion = nextRecieved >>= \case Just r -> processRequest r >> runToCompletion - Nothing -> nextStarved >>= \case - Just r -> starvedRequest r >> runToCompletion - Nothing -> return () + Nothing -> nextMessage >>= \case + Just m -> processMessage m >> runToCompletion + Nothing -> nextStarved >>= \case + Just c -> starveContext c >> runToCompletion + Nothing -> return () diff --git a/ic-stub/src/IC/Types.hs b/ic-stub/src/IC/Types.hs index 7034ce0f1d5..46c7ca41416 100644 --- a/ic-stub/src/IC/Types.hs +++ b/ic-stub/src/IC/Types.hs @@ -3,13 +3,14 @@ module IC.Types where import qualified Data.ByteString.Lazy as BS import qualified Data.Map as M +import Data.Int type (↦) = M.Map -- Basic types type Blob = BS.ByteString -type EntityId = Blob +newtype EntityId = EntityId { rawEntityId :: Blob } deriving (Show, Eq, Ord) type CanisterId = EntityId type MethodName = String type RequestID = Blob @@ -22,14 +23,37 @@ data RejectCode | RC_CANISTER_ERROR deriving Show +rejectCode :: RejectCode -> Int +rejectCode RC_SYS_FATAL = 1 +rejectCode RC_SYS_TRANSIENT = 2 +rejectCode RC_DESTINATION_INVALID = 3 +rejectCode RC_CANISTER_REJECT = 4 +rejectCode RC_CANISTER_ERROR = 5 + + data Response = Reply Blob | Reject (RejectCode, String) + deriving Show -- Abstract canisters data TrapOr a = Trap String | Return a -data Arg = Arg - { dat :: Blob - , caller :: EntityId +data WasmClosure = WasmClosure + { closure_idx :: Int32 + , closure_env :: Int32 + } + deriving Show + +data Callback = Callback + { reply_callback :: WasmClosure + , reject_callback :: WasmClosure + } + deriving Show + +data MethodCall = MethodCall + { call_callee :: CanisterId + , call_method_name :: MethodName + , call_arg :: Blob + , call_callback :: Callback } deriving Show diff --git a/ic-stub/src/IC/Wasm/Winter.hs b/ic-stub/src/IC/Wasm/Winter.hs index 93911204d02..45c88d42a3c 100644 --- a/ic-stub/src/IC/Wasm/Winter.hs +++ b/ic-stub/src/IC/Wasm/Winter.hs @@ -10,6 +10,7 @@ module IC.Wasm.Winter , parseModule , exportedFunctions , Imports + , HostM , HostFunc , W.Value(..) , W.StackType @@ -21,6 +22,7 @@ module IC.Wasm.Winter , initialize , Instance , invokeExport + , invokeTable ) where @@ -33,6 +35,7 @@ import qualified Data.Text.Lazy as T import Control.Monad.ST import Data.Binary.Get (runGetOrFail) import Data.Default.Class (Default (..)) +import Data.Int import qualified Data.Vector as V import qualified Wasm.Binary.Decode as W @@ -47,7 +50,9 @@ import qualified Wasm.Syntax.Memory as W type Instance s = (IM.IntMap (W.ModuleInst Identity (ST s)), W.ModuleInst Identity (ST s)) -type HostFunc s = ExceptT String (ST s) [W.Value] +type HostM s = ExceptT String (ST s) + +type HostFunc s = HostM s [W.Value] type Imports s = [(String, [(String, W.StackType, W.StackType, [W.Value] -> HostFunc s)])] @@ -59,7 +64,7 @@ parseModule bytes = case runGetOrFail W.getModule bytes of Right (_,_,wasm_mod) -> Right wasm_mod -initialize :: Module -> Imports s -> ExceptT String (ST s) (Instance s) +initialize :: Module -> Imports s -> HostM s (Instance s) initialize mod imps = withExceptT show $ do let names = M.fromList (zip (map (T.pack . fst) imps) [1..]) mods = IM.fromList $ zip [1..] @@ -90,19 +95,24 @@ exportedFunctions wasm_mod = ] -invokeExport :: Instance s -> String -> [W.Value] -> ExceptT String (ST s) [W.Value] +invokeExport :: Instance s -> String -> [W.Value] -> HostM s [W.Value] invokeExport (mods', inst) method args = withExceptT show $ W.invokeByName mods' inst (T.pack method) args +invokeTable :: Instance s -> Int32 -> [W.Value] -> HostM s [W.Value] +invokeTable (mods', inst) idx args = + withExceptT show $ do + func <- W.elem inst 0 idx def + W.invoke mods' inst func args -getBytes :: Instance s -> W.Address -> W.Size -> ExceptT String (ST s) BS.ByteString +getBytes :: Instance s -> W.Address -> W.Size -> HostM s BS.ByteString getBytes (_, inst) ptr len = do let mem = head (W._miMemories inst) vec <- withExceptT show $ W.loadBytes mem ptr len return $ BS.pack $ V.toList vec -setBytes :: Instance s -> W.Address -> BS.ByteString -> ExceptT String (ST s) () +setBytes :: Instance s -> W.Address -> BS.ByteString -> HostM s () setBytes (_, inst) ptr blob = do let mem = head (W._miMemories inst) withExceptT show $ diff --git a/ic-stub/src/ic-stub-run.hs b/ic-stub/src/ic-stub-run.hs index 48146090d2d..94a53af3ecc 100644 --- a/ic-stub/src/ic-stub-run.hs +++ b/ic-stub/src/ic-stub-run.hs @@ -25,7 +25,7 @@ prettyBlob :: Blob -> String prettyBlob b = "0x" ++ T.unpack (T.encodeHex (B.toStrict b)) prettyID :: EntityId -> String -prettyID = prettyBlob -- implement the "ic:…" stuff +prettyID = prettyBlob . rawEntityId -- implement the "ic:…" stuff printAsyncRequest :: AsyncRequest -> IO () printAsyncRequest (InstallRequest _ _) = diff --git a/nix/haskell-packages.nix b/nix/haskell-packages.nix index 46854d21277..6a7df7dbba9 100644 --- a/nix/haskell-packages.nix +++ b/nix/haskell-packages.nix @@ -98,10 +98,10 @@ nix: subpath: winter = self.callCabal2nixWithOptions "winter" (nix.fetchFromGitHub { - owner = "dfinity"; + owner = "nomeata"; repo = "winter"; - rev = "2c9cfc593ab3c670858bc9773a70b35b6c3d89e1"; - sha256 = "092149z54yxi6kzwpm87ipnzf16x7qcyw4506ki48ivkmykycycl"; + rev = "0c1f8e0e473b904c341fca320d648139ee084c72"; + sha256 = "09gmzcbwck15l6461w9mg9glm7mimx5mwrpb8qzg0pwmd9gdji3z"; }) "--no-check" {}; ic-stub = self.callCabal2nixWithOptions "ic-stub" (subpath "ic-stub") "-frelease" { }; diff --git a/rts/idl.c b/rts/idl.c index 4349ae08a3f..4a95126c157 100644 --- a/rts/idl.c +++ b/rts/idl.c @@ -94,6 +94,8 @@ export int32_t read_i32_of_sleb128(buf *buf) { * (again via pointer argument, for lack of multi-value returns in C) */ export void parse_idl_header(buf *buf, uint8_t ***typtbl_out, uint8_t **main_types_out) { + if (buf->p == buf->e) idl_trap_with("empty input"); + // Magic bytes (DIDL) if (read_word(buf) != 0x4C444944) idl_trap_with("missing magic bytes"); diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 9df62a4baba..1fd5e8bab35 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -586,7 +586,7 @@ module Func = struct (* Shorthands for various arities *) - let _share_code0 env name retty mk_body = + let share_code0 env name retty mk_body = share_code env name [] retty (fun env -> mk_body env) let share_code1 env name p1 retty mk_body = share_code env name [p1] retty (fun env -> mk_body env @@ -2650,6 +2650,12 @@ module Blob = struct let unskewed_payload_offset = Int32.(add ptr_unskew (mul Heap.word_size header_size)) let payload_ptr_unskewed = compile_add_const unskewed_payload_offset + let as_ptr_len env = Func.share_code1 env "as_ptr_len" ("x", I32Type) [I32Type; I32Type] ( + fun env get_x -> + get_x ^^ payload_ptr_unskewed ^^ + get_x ^^ Heap.load_field len_field + ) + (* Blob concatenation. Expects two strings on stack *) let concat env = Func.share_code2 env "concat" (("x", I32Type), ("y", I32Type)) [I32Type] (fun env get_x get_y -> let (set_z, get_z) = new_local env "z" in @@ -2879,6 +2885,9 @@ module Arr = struct let element_size = 4l let len_field = Int32.add Tagged.header_size 0l + (* Static array access. No checking *) + let load_field n = Heap.load_field Int32.(add n header_size) + (* Dynamic array access. Returns the address (not the value) of the field. Does bounds checking *) let idx env = @@ -3048,7 +3057,11 @@ module Dfinity = struct E.add_func_import env "msg" "reply" [I64Type; I32Type; I32Type] []; E.add_func_import env "msg" "reject" [I64Type; I32Type; I32Type] []; E.add_func_import env "msg" "error_code" [I64Type] [I32Type]; - E.add_func_import env "ic" "trap" [I32Type; I32Type] [] + E.add_func_import env "ic" "trap" [I32Type; I32Type] []; + E.add_func_import env "ic0" "canister_self_len" [] [I32Type]; + E.add_func_import env "ic0" "canister_self_copy" [I32Type; I32Type; I32Type] []; + E.add_func_import env "ic0" "call_simple" (Lib.List.make 10 I32Type) [I32Type]; + () | Flags.AncientMode -> E.add_func_import env "test" "print" [I32Type] []; E.add_func_import env "test" "show_i32" [I32Type] [I32Type]; @@ -3197,8 +3210,27 @@ module Dfinity = struct ElemHeap.recall_reference env let get_self_reference env = - system_call env "actor" "self" ^^ - box_reference env + match E.mode env with + | Flags.ICMode -> + Func.share_code0 env "canister_self" [I32Type] (fun env -> + let (set_len, get_len) = new_local env "len" in + let (set_blob, get_blob) = new_local env "blob" in + system_call env "ic0" "canister_self_len" ^^ + set_len ^^ + + get_len ^^ Blob.alloc env ^^ set_blob ^^ + get_blob ^^ Blob.payload_ptr_unskewed ^^ + compile_unboxed_const 0l ^^ + get_len ^^ + system_call env "ic0" "canister_self_copy" ^^ + + get_blob + ) + | Flags.AncientMode -> + system_call env "actor" "self" ^^ + box_reference env + | _ -> + assert false let static_message_funcref env fi = compile_unboxed_const fi ^^ @@ -3224,6 +3256,14 @@ module Dfinity = struct get_api_nonce env ^^ system_call env "msg" "error_code" + let reply_with_data env = + Func.share_code2 env "reply_with_data" (("start", I32Type), ("size", I32Type)) [] ( + fun env get_data_start get_data_size -> + get_api_nonce env ^^ + get_data_start ^^ + get_data_size ^^ + system_call env "msg" "reply" + ) end (* Dfinity *) module OrthogonalPersistence = struct @@ -4134,12 +4174,6 @@ module Serialization = struct end ) - let reply_with_data env get_data_start get_data_size = - Dfinity.get_api_nonce env ^^ - get_data_start ^^ - get_data_size ^^ - Dfinity.system_call env "msg" "reply" - let argument_data_size env = Dfinity.get_api_nonce env ^^ Dfinity.system_call env "msg" "arg_data_size" @@ -4154,9 +4188,10 @@ module Serialization = struct let serialize env ts : G.t = let ts_name = String.concat "," (List.map typ_id ts) in let name = "@serialize<" ^ ts_name ^ ">" in - (* On ancient API returns databuf/elembuf, on new API returns nothing *) - let ret_tys = if E.mode env = Flags.ICMode then [] else [I32Type; I32Type] in - Func.share_code1 env name ("x", I32Type) ret_tys (fun env get_x -> + (* On ancient API returns databuf/elembuf, + On IC API returns data/length poitners (will be GC next time!) + *) + Func.share_code1 env name ("x", I32Type) [I32Type; I32Type] (fun env get_x -> let (set_data_size, get_data_size) = new_local env "data_size" in let (set_refs_size, get_refs_size) = new_local env "refs_size" in @@ -4213,9 +4248,8 @@ module Serialization = struct G.i (Compare (Wasm.Values.I32 I32Op.Eq)) ^^ E.else_trap_with env "cannot send references on IC System API" ^^ - (* Copy out the bytes *) - reply_with_data env get_data_start get_data_size - + get_data_start ^^ + get_data_size | Flags.WasmMode -> assert false ) @@ -4607,7 +4641,11 @@ module StackRep = struct | StaticFun fi -> assert false | StaticMessage fi -> - Dfinity.static_message_funcref env fi + match E.mode env with + | Flags.AncientMode -> + Dfinity.static_message_funcref env fi + | _ -> + E.trap_with env "cannot call anonymous shared function" let materialize env = function | StaticFun fi -> @@ -4618,8 +4656,12 @@ module StackRep = struct compile_unboxed_zero (* number of parameters: none *) ] | StaticMessage fi -> - Dfinity.static_message_funcref env fi ^^ - Dfinity.box_reference env + match E.mode env with + | Flags.AncientMode -> + Dfinity.static_message_funcref env fi ^^ + Dfinity.box_reference env + | _ -> + E.trap_with env "cannot call anonymous shared function" let adjust env (sr_in : t) sr_out = if sr_in = sr_out @@ -4847,21 +4889,6 @@ module FuncDec = struct compile_unboxed_const tmp_table_slot ^^ G.i (CallIndirect (nr (call_ty env))) - let export_self_message env = - Func.share_code1 env "export_self_message" ("name", I32Type) [I32Type] (fun env get_name -> - Tagged.obj env Tagged.Reference [ - (* Create a funcref for the message *) - Dfinity.system_call env "actor" "self" ^^ - get_name ^^ (* the databuf with the message name *) - Dfinity.system_call env "actor" "export" ^^ - ElemHeap.remember_reference env - ] - ) - - let _static_self_message_pointer env name = - Dfinity.compile_databuf_of_bytes env name ^^ - export_self_message env - let bind_args ae0 first_arg as_ bind_arg = let rec go i ae = function | [] -> ae @@ -5194,6 +5221,57 @@ module FuncDec = struct Dfinity.get_reply_cont env ^^ Dfinity.system_call env "func" "bind_ref" + (* Wraps a local closure in a local function that does serialization and + takes care of the environment *) + (* Need this function once per type, so we can share based on ts *) + let closure_to_reply_callback env ts get_closure = + assert (E.mode env = Flags.ICMode); + let name = "@callback<" ^ Serialization.typ_id (Type.Tup ts) ^ ">" in + Func.define_built_in env name ["api_nonce",I64Type; "env", I32Type] [] (fun env -> + G.i (LocalGet (nr 0l)) ^^ Dfinity.set_api_nonce env ^^ + + (* Look up closure *) + let (set_closure, get_closure) = new_local env "closure" in + G.i (LocalGet (nr 1l)) ^^ + ClosureTable.recall_closure env ^^ (* At this point we can remove the closure *) + set_closure ^^ + get_closure ^^ + + (* Deserialize arguments *) + Serialization.deserialize env ts ^^ + + get_closure ^^ + Closure.call_closure env (List.length ts) 0 ^^ + + message_cleanup env (Type.Shared Type.Write) + ); + compile_unboxed_const (E.built_in env name) ^^ + get_closure ^^ ClosureTable.remember_closure env + + let closure_to_reject_callback env get_closure = + assert (E.mode env = Flags.ICMode); + let name = "@reject_callback" in + Func.define_built_in env name ["api_nonce",I64Type; "env", I32Type] [] (fun env -> + G.i (LocalGet (nr 0l)) ^^ Dfinity.set_api_nonce env ^^ + + (* Look up closure *) + let (set_closure, get_closure) = new_local env "closure" in + G.i (LocalGet (nr 1l)) ^^ + ClosureTable.recall_closure env ^^ (* At this point we can remove the closure *) + set_closure ^^ + get_closure ^^ + + (* Synthesize reject *) + E.trap_with env "reject_callback" ^^ + + get_closure ^^ + Closure.call_closure env 1 0 ^^ + + message_cleanup env (Type.Shared Type.Write) + ); + compile_unboxed_const (E.built_in env name) ^^ + get_closure ^^ ClosureTable.remember_closure env + let lit env ae how name sort control free_vars args mk_body ret_tys at = let captured = List.filter (VarEnv.needs_capture ae) free_vars in @@ -6147,10 +6225,14 @@ and compile_exp (env : E.t) ae exp = SR.Vanilla, compile_exp_vanilla env ae e ^^ Object.load_idx env e.note.note_typ name - | ActorDotE (e, name) -> + | ActorDotE (e, name) when E.mode env = Flags.AncientMode -> SR.UnboxedReference, compile_exp_as env ae SR.UnboxedReference e ^^ actor_fake_object_idx env name + | ActorDotE (e, name) -> + SR.Vanilla, + compile_exp_as env ae SR.Vanilla e ^^ + actor_fake_object_idx env name | PrimE (p, es) -> (* for more concise code when all arguments and result use the same sr *) @@ -6415,7 +6497,8 @@ and compile_exp (env : E.t) ae exp = compile_exp_as env ae SR.Vanilla e ^^ (* TODO: We can try to avoid the boxing and pass the arguments to serialize individually *) - Serialization.serialize env ts + Serialization.serialize env ts ^^ + Dfinity.reply_with_data env | Flags.AncientMode -> let (set_funcref, get_funcref) = new_local env "funcref" in Dfinity.get_reply_cont env ^^ @@ -6436,27 +6519,50 @@ and compile_exp (env : E.t) ae exp = Dfinity.error_code env | ICCallPrim, [f;e;k;r] -> - SR.unit, begin match E.mode env with + SR.unit, begin + (* TBR: Can we do better than using the notes? *) + let _, _, _, ts1, _ = Type.as_func f.note.note_typ in + let _, _, _, ts2, _ = Type.as_func k.note.note_typ in + + match E.mode env with | Flags.ICMode -> - assert false (* not implemented yet *) + + let (set_funcref, get_funcref) = new_local env "funcref" in + let (set_arg, get_arg) = new_local env "arg" in + let (set_k, get_k) = new_local env "k" in + let (set_r, get_r) = new_local env "r" in + compile_exp_as env ae SR.Vanilla f ^^ set_funcref ^^ + compile_exp_as env ae SR.Vanilla e ^^ set_arg ^^ + compile_exp_as env ae SR.Vanilla k ^^ set_k ^^ + compile_exp_as env ae SR.Vanilla r ^^ set_r ^^ + + (* The callee *) + get_funcref ^^ Arr.load_field 0l ^^ Blob.as_ptr_len env ^^ + (* The method name *) + get_funcref ^^ Arr.load_field 1l ^^ Blob.as_ptr_len env ^^ + (* The reply callback *) + FuncDec.closure_to_reply_callback env ts1 get_k ^^ + (* The reject callback *) + FuncDec.closure_to_reject_callback env get_r ^^ + (* the data *) + get_arg ^^ Serialization.serialize env ts1 ^^ + (* done! *) + Dfinity.system_call env "ic0" "call_simple" ^^ + (* TODO: Check error code *) + G.i Drop | Flags.AncientMode -> let (set_funcref, get_funcref) = new_local env "funcref" in let (set_arg, get_arg) = new_local env "arg" in let (set_k, get_k) = new_local env "k" in - let fun_sr, code1 = compile_exp env ae f in - code1 ^^ StackRep.adjust env fun_sr SR.UnboxedReference ^^ - set_funcref ^^ - + compile_exp_as env ae SR.UnboxedReference f ^^ set_funcref ^^ compile_exp_as env ae SR.Vanilla e ^^ set_arg ^^ compile_exp_as env ae SR.Vanilla k ^^ set_k ^^ + (* We drop the reject continuation on the ancient platform, but still need to evaluate it *) let (r_sr, code_r) = compile_exp env ae r in code_r ^^ StackRep.drop env r_sr ^^ - (* TBR: Can we do better than using the notes? *) - let _, _, _, ts1, _ = Type.as_func f.note.note_typ in - let _, _, _, ts2, _ = Type.as_func k.note.note_typ in FuncDec.callback_to_funcref env ts2 get_k ^^ get_arg ^^ Serialization.serialize env ts1 ^^ FuncDec.call_await_funcref env get_funcref @@ -7109,9 +7215,18 @@ and main_actor env ae1 this ds fs = decls_code +(* Actor reference on the stack *) and actor_fake_object_idx env name = + match E.mode env with + | Flags.AncientMode -> Dfinity.compile_databuf_of_bytes env name ^^ Dfinity.system_call env "actor" "export" + | Flags.ICMode -> + (* simply tuple canister name and function name *) + Blob.lit env name ^^ + Tuple.from_stack env 2 + | Flags.WasmMode -> assert false + and conclude_module env module_name start_fi_o = diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 5d59b005854..0f574f55214 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -753,7 +753,6 @@ and infer_exp'' env exp : T.typ = if T.is_async t_ret && not in_await then error_in [Flags.ICMode] env exp2.at "shared, async function must be called within an await expression"; - error_in [Flags.ICMode] env exp1.at "calling a shared function not yet supported"; if not (T.concrete t_arg) then error env exp1.at "shared function argument contains abstract type\n %s" diff --git a/test/run-drun/ic-calls.mo b/test/run-drun/ic-calls.mo index 3c5a81cd1ec..32d4a947f77 100644 --- a/test/run-drun/ic-calls.mo +++ b/test/run-drun/ic-calls.mo @@ -20,5 +20,5 @@ actor X { }; } -//CALL ingress inc 0x4449444C0000 +//CALL ingress test 0x4449444C0000 diff --git a/test/run-drun/ok/counter.drun-run.ok b/test/run-drun/ok/counter.drun-run.ok deleted file mode 100644 index 7d9bd915a92..00000000000 --- a/test/run-drun/ok/counter.drun-run.ok +++ /dev/null @@ -1,18 +0,0 @@ -ingress(0) System -debug.print: 2 -debug.print: - -ingress(1) Completed: Canister: Empty -debug.print: 3 -debug.print: - -ingress(2) Completed: Canister: Empty -debug.print: 4 -debug.print: - -ingress(3) Completed: Canister: Empty -debug.print: 4 -debug.print: - -ingress(4) Completed: Canister: Empty -ingress(5) Completed: Canister: Payload: 0x4449444c00017d04 diff --git a/test/run-drun/ok/hello-world-return.drun-run.ok b/test/run-drun/ok/hello-world-return.drun-run.ok deleted file mode 100644 index c1f0a27528b..00000000000 --- a/test/run-drun/ok/hello-world-return.drun-run.ok +++ /dev/null @@ -1,3 +0,0 @@ -ingress(0) System -Ok: Payload: 0x4449444c0001710c48656c6c6f20576f726c6421 -Ok: Payload: 0x4449444c0001710c48656c6c6f20576f726c6421 diff --git a/test/run-drun/ok/ic-calls.comp.ok b/test/run-drun/ok/ic-calls.comp.ok index e753cbd283c..dec54dfc5ac 100644 --- a/test/run-drun/ok/ic-calls.comp.ok +++ b/test/run-drun/ok/ic-calls.comp.ok @@ -7,9 +7,3 @@ ic-calls.mo:19.9-19.17: warning, this pattern consuming type does not cover value (1, false) or (0 or -1 or _, _) -ic-calls.mo:17.20-17.21: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -ic-calls.mo:18.19-18.20: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -ic-calls.mo:19.26-19.27: type error, calling a shared function not yet supported - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/ic-calls.comp.ret.ok b/test/run-drun/ok/ic-calls.comp.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/ic-calls.comp.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/idl-any.drun-run.ok b/test/run-drun/ok/idl-any.drun-run.ok deleted file mode 100644 index 4f76ce5ac28..00000000000 --- a/test/run-drun/ok/idl-any.drun-run.ok +++ /dev/null @@ -1,57 +0,0 @@ -ingress(0) System -debug.print: ok: Foo -ingress(1) Completed: Canister: Payload: 0x4449444c0000 -debug.print: ok: Foo -ingress(2) Completed: Canister: Payload: 0x4449444c0000 -debug.print: ok: Foo -ingress(3) Completed: Canister: Payload: 0x4449444c0000 -debug.print: ok: Foo -ingress(4) Completed: Canister: Payload: 0x4449444c0000 -debug.print: ok: Foo -ingress(5) Completed: Canister: Payload: 0x4449444c0000 -debug.print: ok: Foo -ingress(6) Completed: Canister: Payload: 0x4449444c0000 -debug.print: ok: Foo -ingress(7) Completed: Canister: Payload: 0x4449444c0000 -debug.print: ok: Foo -ingress(8) Completed: Canister: Payload: 0x4449444c0000 -debug.print: ok: Foo -ingress(9) Completed: Canister: Payload: 0x4449444c0000 -debug.print: ok: Foo -ingress(10) Completed: Canister: Payload: 0x4449444c0000 -debug.print: ok: Foo -ingress(11) Completed: Canister: Payload: 0x4449444c0000 -debug.print: ok: Foo -ingress(12) Completed: Canister: Payload: 0x4449444c0000 -debug.print: ok: Foo -ingress(13) Completed: Canister: Payload: 0x4449444c0000 -debug.print: ok: Foo -ingress(14) Completed: Canister: Payload: 0x4449444c0000 -debug.print: ok: Foo -ingress(15) Completed: Canister: Payload: 0x4449444c0000 -debug.print: ok: Foo -ingress(16) Completed: Canister: Payload: 0x4449444c0000 -debug.print: ok: Foo -ingress(17) Completed: Canister: Payload: 0x4449444c0000 -debug.print: ok: Foo -ingress(18) Completed: Canister: Payload: 0x4449444c0000 -debug.print: ok: Foo -ingress(19) Completed: Canister: Payload: 0x4449444c0000 -debug.print: ok: Foo -ingress(20) Completed: Canister: Payload: 0x4449444c0000 -debug.print: ok: Foo -ingress(21) Completed: Canister: Payload: 0x4449444c0000 -debug.print: ok: Foo -ingress(22) Completed: Canister: Payload: 0x4449444c0000 -debug.print: ok: Foo -ingress(23) Completed: Canister: Payload: 0x4449444c0000 -debug.print: ok: Foo -ingress(24) Completed: Canister: Payload: 0x4449444c0000 -debug.print: ok: Foo -ingress(25) Completed: Canister: Payload: 0x4449444c0000 -debug.print: ok: Foo -ingress(26) Completed: Canister: Payload: 0x4449444c0000 -debug.print: ok: Foo -ingress(27) Completed: Canister: Payload: 0x4449444c0000 -debug.print: ok: Foo -ingress(28) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-bad.drun-run.ok b/test/run-drun/ok/idl-bad.drun-run.ok deleted file mode 100644 index 401133f7f50..00000000000 --- a/test/run-drun/ok/idl-bad.drun-run.ok +++ /dev/null @@ -1,2 +0,0 @@ -ingress(0) System -Err: IC0503: Canister 42 trapped explicitly: IDL error: missing magic bytes diff --git a/test/run-drun/ok/idl-bad.ic-stub-run.ok b/test/run-drun/ok/idl-bad.ic-stub-run.ok index d05cb778cd4..d0fad626584 100644 --- a/test/run-drun/ok/idl-bad.ic-stub-run.ok +++ b/test/run-drun/ok/idl-bad.ic-stub-run.ok @@ -1,4 +1,4 @@ → install ← completed → query foo(0x4e4f544449444c) -← rejected (RC_CANISTER_ERROR): canister trapped: EvalTrapError :0.1 "explicit trap" +← rejected (RC_CANISTER_ERROR): canister trapped: EvalTrapError :0.1 "canister trapped explicitly: IDL error: missing magic bytes" diff --git a/test/run-drun/ok/idl-field-escape.drun-run.ok b/test/run-drun/ok/idl-field-escape.drun-run.ok deleted file mode 100644 index 2d425b83ef4..00000000000 --- a/test/run-drun/ok/idl-field-escape.drun-run.ok +++ /dev/null @@ -1,5 +0,0 @@ -ingress(0) System -ingress(1) Completed: Canister: Payload: 0x4449444c026c01868eb702016c000100 -ingress(2) Completed: Canister: Payload: 0x4449444c026c01868eb702016c000100 -ingress(3) Completed: Canister: Payload: 0x4449444c016c03007c017dbcfef7b102710100ffff03802003585858 -ingress(4) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-nary.drun-run.ok b/test/run-drun/ok/idl-nary.drun-run.ok deleted file mode 100644 index e6f3a393455..00000000000 --- a/test/run-drun/ok/idl-nary.drun-run.ok +++ /dev/null @@ -1,12 +0,0 @@ -ingress(0) System -ingress(1) Completed: Canister: Payload: 0x4449444c00027171034f6e650354776f -ingress(2) Completed: Canister: Payload: 0x4449444c0003717171034f6e650354776f055468726565 -ingress(3) Completed: Canister: Payload: 0x4449444c000471717171034f6e650354776f05546872656504466f7572 -ingress(4) Completed: Canister: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 -ingress(5) Completed: Canister: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 -ingress(6) Completed: Canister: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 -ingress(7) Completed: Canister: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 -ingress(8) Completed: Canister: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 -ingress(9) Err: IC0503: Canister 42 trapped explicitly: IDL error: too few arguments Text,Text,Text -ingress(10) Err: IC0503: Canister 42 trapped explicitly: IDL error: left-over bytes Text,Text,Text -ingress(11) Completed: Canister: Payload: 0x4449444c000471717171034f6e650354776f05546872656504466f7572 diff --git a/test/run-drun/ok/idl-nary.ic-stub-run.ok b/test/run-drun/ok/idl-nary.ic-stub-run.ok index 9b62b925bcd..6acee11407e 100644 --- a/test/run-drun/ok/idl-nary.ic-stub-run.ok +++ b/test/run-drun/ok/idl-nary.ic-stub-run.ok @@ -17,8 +17,8 @@ → update unary4(0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572) ← completed: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 → update three(0x4449444c00027171034f6e650354776f) -← rejected (RC_CANISTER_ERROR): canister trapped: EvalTrapError :0.1 "explicit trap" +← rejected (RC_CANISTER_ERROR): canister trapped: EvalTrapError :0.1 "canister trapped explicitly: IDL error: too few arguments Text,Text,Text" → update three(0x4449444c0003717171034f6e650354776f05546872656545585452414259544553) -← rejected (RC_CANISTER_ERROR): canister trapped: EvalTrapError :0.1 "explicit trap" +← rejected (RC_CANISTER_ERROR): canister trapped: EvalTrapError :0.1 "canister trapped explicitly: IDL error: left-over bytes Text,Text,Text" → update four(0x4449444c00057171717171034f6e650354776f05546872656504466f75720446697665) ← completed: 0x4449444c000471717171034f6e650354776f05546872656504466f7572 diff --git a/test/run-drun/ok/idl-nat-int.drun-run.ok b/test/run-drun/ok/idl-nat-int.drun-run.ok deleted file mode 100644 index f450261cb17..00000000000 --- a/test/run-drun/ok/idl-nat-int.drun-run.ok +++ /dev/null @@ -1,5 +0,0 @@ -ingress(0) System -Ok: Payload: 0x4449444c00017d2a -Ok: Payload: 0x4449444c00017d2a -Ok: Payload: 0x4449444c016d7d0100022a19 -Ok: Payload: 0x4449444c016d7d0100022a19 diff --git a/test/run-drun/ok/idl-option.drun-run.ok b/test/run-drun/ok/idl-option.drun-run.ok deleted file mode 100644 index 028b1b4aa2e..00000000000 --- a/test/run-drun/ok/idl-option.drun-run.ok +++ /dev/null @@ -1,7 +0,0 @@ -ingress(0) System -debug.print: ok: null -ingress(1) Completed: Canister: Payload: 0x4449444c0000 -debug.print: ok: null -ingress(2) Completed: Canister: Payload: 0x4449444c0000 -debug.print: ok: Foo -ingress(3) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-pair.drun-run.ok b/test/run-drun/ok/idl-pair.drun-run.ok deleted file mode 100644 index fd1ef07bac7..00000000000 --- a/test/run-drun/ok/idl-pair.drun-run.ok +++ /dev/null @@ -1,2 +0,0 @@ -ingress(0) System -ingress(1) Completed: Canister: Payload: 0x4449444c016c02007c017c01000205 diff --git a/test/run-drun/ok/idl-record.drun-run.ok b/test/run-drun/ok/idl-record.drun-run.ok deleted file mode 100644 index 933c43b7393..00000000000 --- a/test/run-drun/ok/idl-record.drun-run.ok +++ /dev/null @@ -1,9 +0,0 @@ -ingress(0) System -debug.print: ok: +42 -ingress(1) Completed: Canister: Payload: 0x4449444c0000 -debug.print: ok: Hey! -ingress(2) Completed: Canister: Payload: 0x4449444c0000 -debug.print: ok: +25 -ingress(3) Completed: Canister: Payload: 0x4449444c0000 -debug.print: ok: Hey! +25 -ingress(4) Completed: Canister: Payload: 0x4449444c00017719 diff --git a/test/run-drun/ok/idl-tuple.drun-run.ok b/test/run-drun/ok/idl-tuple.drun-run.ok deleted file mode 100644 index 6789a1dbd26..00000000000 --- a/test/run-drun/ok/idl-tuple.drun-run.ok +++ /dev/null @@ -1,5 +0,0 @@ -ingress(0) System -Ok: Payload: 0x4449444c00027c7c0205 -Ok: Payload: 0x4449444c00037c7c7c050581848c20 -Ok: Payload: 0x4449444c00037c7c7c050581848c20 -Ok: Payload: 0x4449444c00037c7c7c050581848c20 diff --git a/test/run-drun/ok/idl-unit.drun-run.ok b/test/run-drun/ok/idl-unit.drun-run.ok deleted file mode 100644 index 139fbf3fc92..00000000000 --- a/test/run-drun/ok/idl-unit.drun-run.ok +++ /dev/null @@ -1,2 +0,0 @@ -ingress(0) System -Ok: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-variant.drun-run.ok b/test/run-drun/ok/idl-variant.drun-run.ok deleted file mode 100644 index 2e39e7bfc87..00000000000 --- a/test/run-drun/ok/idl-variant.drun-run.ok +++ /dev/null @@ -1,2 +0,0 @@ -ingress(0) System -Ok: Payload: 0x4449444c016b03d583b702008790c0bd0479dc9790cb0e790100000120000000 diff --git a/test/run-drun/ok/idl-vector.drun-run.ok b/test/run-drun/ok/idl-vector.drun-run.ok deleted file mode 100644 index a8c227d6d03..00000000000 --- a/test/run-drun/ok/idl-vector.drun-run.ok +++ /dev/null @@ -1,2 +0,0 @@ -ingress(0) System -Ok: Payload: 0x4449444c026e016d0001000103010001040100010201000100010001000100 diff --git a/test/run-drun/ok/large-array.drun-run.ok b/test/run-drun/ok/large-array.drun-run.ok deleted file mode 100644 index 43d7af40394..00000000000 --- a/test/run-drun/ok/large-array.drun-run.ok +++ /dev/null @@ -1 +0,0 @@ -ingress(0) System diff --git a/test/run-drun/ok/oom.drun-run.ok b/test/run-drun/ok/oom.drun-run.ok deleted file mode 100644 index d1d6ed87e8b..00000000000 --- a/test/run-drun/ok/oom.drun-run.ok +++ /dev/null @@ -1,3 +0,0 @@ -ingress(0) System -ingress(1) Completed: Canister: Empty -ingress(2) Completed: Canister: Empty diff --git a/test/run-drun/ok/print-from-init.drun-run.ok b/test/run-drun/ok/print-from-init.drun-run.ok deleted file mode 100644 index 4d57fad6ec2..00000000000 --- a/test/run-drun/ok/print-from-init.drun-run.ok +++ /dev/null @@ -1,2 +0,0 @@ -debug.print: Debug out -ingress(0) System diff --git a/test/run-drun/ok/query.drun-run.ok b/test/run-drun/ok/query.drun-run.ok deleted file mode 100644 index 5137d9c8055..00000000000 --- a/test/run-drun/ok/query.drun-run.ok +++ /dev/null @@ -1,34 +0,0 @@ -ingress(0) System -debug.print: 2 -debug.print: - -ingress(1) Completed: Canister: Empty -debug.print: 3 -debug.print: - -ingress(2) Completed: Canister: Empty -debug.print: 4 -debug.print: - -ingress(3) Completed: Canister: Empty -debug.print: 4 -debug.print: - -ingress(4) Completed: Canister: Empty -ingress(5) Completed: Canister: Payload: 0x4449444c00017d04 -debug.print: 5 -debug.print: - -Ok: Payload: 0x4449444c00017d04 -debug.print: 4 -debug.print: - -ingress(6) Completed: Canister: Empty -debug.print: 5 -debug.print: - -Ok: Payload: 0x4449444c00017d04 -debug.print: 4 -debug.print: - -ingress(7) Completed: Canister: Empty diff --git a/test/run-drun/ok/reject.drun-run.ok b/test/run-drun/ok/reject.drun-run.ok deleted file mode 100644 index 8ea07ed3242..00000000000 --- a/test/run-drun/ok/reject.drun-run.ok +++ /dev/null @@ -1,9 +0,0 @@ -ingress(0) System -debug.print: 1 -ingress(1) Completed: Canister: Reject: Error -debug.print: 1 -debug.print: ok -ingress(2) Completed: Canister: Payload: 0x4449444c0000 -debug.print: 1 -debug.print: ok -ingress(3) Completed: Canister: Reject: Error diff --git a/test/run-drun/ok/reversi.drun-run.ok b/test/run-drun/ok/reversi.drun-run.ok deleted file mode 100644 index 0c49bd69fb7..00000000000 --- a/test/run-drun/ok/reversi.drun-run.ok +++ /dev/null @@ -1,9 +0,0 @@ -ingress(0) System -ingress(1) Completed: Canister: Empty -ingress(2) Completed: Canister: Payload: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e4f2a2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a -ingress(3) Completed: Canister: Payload: 0x4449444c000171024f4b -ingress(4) Completed: Canister: Payload: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e4f2e2e2e0a2e2e2e4f4f2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a -ingress(5) Completed: Canister: Payload: 0x4449444c000171024f4b -ingress(6) Completed: Canister: Payload: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a -ingress(7) Completed: Canister: Payload: 0x4449444c000171024f4b -ingress(8) Completed: Canister: Payload: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e4f4f2e2e2e0a2e2e4f4f4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a diff --git a/test/run-drun/ok/unsupported.comp.ok b/test/run-drun/ok/unsupported.comp.ok index fa8f5d395b1..9b4b2c70f19 100644 --- a/test/run-drun/ok/unsupported.comp.ok +++ b/test/run-drun/ok/unsupported.comp.ok @@ -16,8 +16,6 @@ unsupported.mo:8.31-8.53: type error, shared function types are non-shared. (This is a limitation of the current version.) unsupported.mo:19.19-19.21: type error, shared, async function must be called within an await expression (This is a limitation of the current version.) -unsupported.mo:23.16-23.18: type error, calling a shared function not yet supported - (This is a limitation of the current version.) unsupported.mo:28.8-28.9: type error, argument to await must be a call expression (This is a limitation of the current version.) unsupported.mo:32.17-32.29: type error, unsupported async block diff --git a/test/run.sh b/test/run.sh index 5b0b4769325..dad50585ebc 100755 --- a/test/run.sh +++ b/test/run.sh @@ -229,7 +229,7 @@ do run dvm $DVM_WRAPPER $out/$base.wasm $base.mo elif [ $API = ic ] then - run drun-run $DRUN_WRAPPER $out/$base.wasm $base.mo + # run drun-run $DRUN_WRAPPER $out/$base.wasm $base.mo DRUN=$IC_STUB_RUN run ic-stub-run $DRUN_WRAPPER $out/$base.wasm $base.mo else run wasm-run $WASM $out/$base.wasm From 95ca7484fbdb3e005f17e2f39b47c5bd303fff84 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 14 Nov 2019 19:02:02 +0100 Subject: [PATCH 0580/1176] Define a StubMode --- src/codegen/compile.ml | 48 +++++++++++++++++++++++++-------------- src/exes/moc.ml | 3 +++ src/mo_config/flags.ml | 2 +- src/mo_frontend/typing.ml | 26 +++++++++++---------- 4 files changed, 49 insertions(+), 30 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 1fd5e8bab35..a09ec923d3e 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -686,7 +686,7 @@ module RTS = struct E.call_import env "data" "externalize" ^^ E.call_import env "test" "print" ^^ G.i Unreachable - | Flags.ICMode -> + | Flags.ICMode | Flags.StubMode -> E.call_import env "ic" "trap" ^^ G.i Unreachable | Flags.WasmMode -> G.i Unreachable @@ -3051,6 +3051,15 @@ module Dfinity = struct let system_imports env = match E.mode env with | Flags.ICMode -> + E.add_func_import env "debug" "print" [I32Type; I32Type] []; + E.add_func_import env "msg" "arg_data_size" [I64Type] [I32Type]; + E.add_func_import env "msg" "arg_data_copy" [I64Type; I32Type; I32Type; I32Type] []; + E.add_func_import env "msg" "reply" [I64Type; I32Type; I32Type] []; + E.add_func_import env "msg" "reject" [I64Type; I32Type; I32Type] []; + E.add_func_import env "msg" "error_code" [I64Type] [I32Type]; + E.add_func_import env "ic" "trap" [I32Type; I32Type] []; + () + | Flags.StubMode -> E.add_func_import env "debug" "print" [I32Type; I32Type] []; E.add_func_import env "msg" "arg_data_size" [I64Type] [I32Type]; E.add_func_import env "msg" "arg_data_copy" [I64Type; I32Type; I32Type; I32Type] []; @@ -3103,7 +3112,7 @@ module Dfinity = struct let prim_print env = match E.mode env with | Flags.WasmMode -> G.i Drop - | Flags.ICMode -> + | Flags.ICMode | Flags.StubMode -> Func.share_code1 env "print_text" ("str", I32Type) [] (fun env get_str -> get_str ^^ Blob.payload_ptr_unskewed ^^ get_str ^^ Heap.load_field (Blob.len_field) ^^ @@ -3133,7 +3142,7 @@ module Dfinity = struct match E.mode env with | Flags.WasmMode -> G.i Unreachable | Flags.AncientMode -> compile_static_print env (s ^ "\n") ^^ G.i Unreachable - | Flags.ICMode -> Blob.lit env s ^^ ic_trap env ^^ G.i Unreachable + | Flags.ICMode | Flags.StubMode -> Blob.lit env s ^^ ic_trap env ^^ G.i Unreachable let default_exports env = (* these exports seem to be wanted by the hypervisor/v8 *) @@ -3184,7 +3193,7 @@ module Dfinity = struct E.add_dfinity_type env (fi, []) let export_start env start_fi = - assert (E.mode env = Flags.ICMode); + assert (E.mode env = Flags.ICMode || E.mode env = Flags.StubMode); (* Create an empty message *) let empty_f = Func.of_body env ["api_nonce",I64Type] [] (fun env1 -> G.i (Call (nr start_fi)) ^^ @@ -3212,6 +3221,8 @@ module Dfinity = struct let get_self_reference env = match E.mode env with | Flags.ICMode -> + assert false + | Flags.StubMode -> Func.share_code0 env "canister_self" [I32Type] (fun env -> let (set_len, get_len) = new_local env "len" in let (set_blob, get_blob) = new_local env "blob" in @@ -3238,7 +3249,7 @@ module Dfinity = struct let reject env arg_instrs = match E.mode env with - | Flags.ICMode -> + | Flags.ICMode | Flags.StubMode -> get_api_nonce env ^^ let (set_text, get_text) = new_local env "text" in arg_instrs ^^ @@ -4242,7 +4253,7 @@ module Serialization = struct get_refs_start ^^ get_refs_size ^^ Dfinity.system_call env "elem" "externalize" - | Flags.ICMode -> + | Flags.ICMode | Flags.StubMode -> get_refs_size ^^ compile_unboxed_const 0l ^^ G.i (Compare (Wasm.Values.I32 I32Op.Eq)) ^^ @@ -4256,7 +4267,9 @@ module Serialization = struct let deserialize env ts = let ts_name = String.concat "," (List.map typ_id ts) in let name = "@deserialize<" ^ ts_name ^ ">" in - let args = if E.mode env = Flags.ICMode then [] else [("databuf",I32Type);("elembuf", I32Type)] in + let args = match E.mode env with + | Flags.ICMode | Flags.StubMode -> [] + | _ -> [("databuf",I32Type);("elembuf", I32Type)] in Func.share_code env name args (List.map (fun _ -> I32Type) ts) (fun env -> let (set_data_size, get_data_size) = new_local env "data_size" in let (set_refs_size, get_refs_size) = new_local env "refs_size" in @@ -4280,7 +4293,7 @@ module Serialization = struct get_refs_size ^^ compile_mul_const Heap.word_size ^^ Blob.dyn_alloc_scratch env ^^ set_refs_start ^^ get_refs_start ^^ get_refs_size ^^ get_elembuf ^^ compile_unboxed_const 0l ^^ Dfinity.system_call env "elem" "internalize" - | Flags.ICMode -> + | Flags.ICMode | Flags.StubMode -> (* Allocate space for the data buffer and copy it *) argument_data_size env ^^ set_data_size ^^ get_data_size ^^ Blob.dyn_alloc_scratch env ^^ set_data_start ^^ @@ -5062,7 +5075,7 @@ module FuncDec = struct mk_body env ae1 ^^ message_cleanup env sort )) - | Flags.ICMode, _ -> + | (Flags.ICMode | Flags.StubMode), _ -> let ae0 = VarEnv.mk_fun_ae outer_ae in Func.of_body outer_env ["api_nonce", I64Type] [] (fun env -> G.with_region at ( G.i (LocalGet (nr 0l)) ^^ Dfinity.set_api_nonce env ^^ @@ -5225,7 +5238,7 @@ module FuncDec = struct takes care of the environment *) (* Need this function once per type, so we can share based on ts *) let closure_to_reply_callback env ts get_closure = - assert (E.mode env = Flags.ICMode); + assert (E.mode env = Flags.ICMode || E.mode env = Flags.StubMode); let name = "@callback<" ^ Serialization.typ_id (Type.Tup ts) ^ ">" in Func.define_built_in env name ["api_nonce",I64Type; "env", I32Type] [] (fun env -> G.i (LocalGet (nr 0l)) ^^ Dfinity.set_api_nonce env ^^ @@ -5249,7 +5262,7 @@ module FuncDec = struct get_closure ^^ ClosureTable.remember_closure env let closure_to_reject_callback env get_closure = - assert (E.mode env = Flags.ICMode); + assert (E.mode env = Flags.ICMode || E.mode env = Flags.StubMode); let name = "@reject_callback" in Func.define_built_in env name ["api_nonce",I64Type; "env", I32Type] [] (fun env -> G.i (LocalGet (nr 0l)) ^^ Dfinity.set_api_nonce env ^^ @@ -6493,7 +6506,7 @@ and compile_exp (env : E.t) ae exp = | ICReplyPrim ts, [e] -> SR.unit, begin match E.mode env with - | Flags.ICMode -> + | Flags.ICMode | Flags.StubMode -> compile_exp_as env ae SR.Vanilla e ^^ (* TODO: We can try to avoid the boxing and pass the arguments to serialize individually *) @@ -6515,7 +6528,7 @@ and compile_exp (env : E.t) ae exp = SR.unit, Dfinity.reject env (compile_exp_vanilla env ae e) | ICErrorCodePrim, [] -> - assert (E.mode env = Flags.ICMode); + assert (E.mode env = Flags.ICMode || E.mode env = Flags.StubMode); Dfinity.error_code env | ICCallPrim, [f;e;k;r] -> @@ -6525,7 +6538,7 @@ and compile_exp (env : E.t) ae exp = let _, _, _, ts2, _ = Type.as_func k.note.note_typ in match E.mode env with - | Flags.ICMode -> + | Flags.ICMode | Flags.StubMode -> let (set_funcref, get_funcref) = new_local env "funcref" in let (set_arg, get_arg) = new_local env "arg" in @@ -7137,7 +7150,7 @@ and export_actor_field env ae (f : Ir.field) = E.add_export env (nr { name = Wasm.Utf8.decode (match E.mode env with | Flags.AncientMode -> f.it.name - | Flags.ICMode -> + | Flags.ICMode | Flags.StubMode -> Mo_types.Type.( match normalize f.note with | Func(Shared sort,_,_,_,_) -> @@ -7191,6 +7204,7 @@ and actor_lit outer_env this ds fs at = let start_fi = E.add_fun mod_env "start" start_fun in if E.mode mod_env = Flags.ICMode then Dfinity.export_start mod_env start_fi; + if E.mode mod_env = Flags.StubMode then Dfinity.export_start mod_env start_fi; if E.mode mod_env = Flags.AncientMode then OrthogonalPersistence.register mod_env start_fi; let m = conclude_module mod_env this None in @@ -7221,7 +7235,7 @@ and actor_fake_object_idx env name = | Flags.AncientMode -> Dfinity.compile_databuf_of_bytes env name ^^ Dfinity.system_call env "actor" "export" - | Flags.ICMode -> + | Flags.ICMode | Flags.StubMode -> (* simply tuple canister name and function name *) Blob.lit env name ^^ Tuple.from_stack env 2 @@ -7324,7 +7338,7 @@ let compile mode module_name rts (prelude : Ir.prog) (progs : Ir.prog list) : Wa OrthogonalPersistence.register env start_fi; Dfinity.export_start_stub env; None - | Flags.ICMode -> Dfinity.export_start env start_fi; None + | Flags.ICMode | Flags.StubMode -> Dfinity.export_start env start_fi; None | Flags.WasmMode -> Some (nr start_fi) in conclude_module env module_name start_fi_o diff --git a/src/exes/moc.ml b/src/exes/moc.ml index 31b6c27edf0..860e01f9522 100644 --- a/src/exes/moc.ml +++ b/src/exes/moc.ml @@ -72,6 +72,9 @@ let argspec = Arg.align "-ancient-system-api", Arg.Unit (fun () -> Flags.(compile_mode := AncientMode)), " use the ancient DFINITY system API (dvm)"; + "-stub-system-api", + Arg.Unit (fun () -> Flags.(compile_mode := StubMode)), + " use the future DFINITY system API (ic-stub-run)"; "-multi-value", Arg.Set Flags.multi_value, " use multi-value extension"; "-no-multi-value", Arg.Clear Flags.multi_value, " avoid multi-value extension"; diff --git a/src/mo_config/flags.ml b/src/mo_config/flags.ml index 0c8fcd1294f..f75dbc426b0 100644 --- a/src/mo_config/flags.ml +++ b/src/mo_config/flags.ml @@ -1,6 +1,6 @@ (* common flags for the moc compiler *) -type compile_mode = WasmMode | AncientMode | ICMode +type compile_mode = WasmMode | AncientMode | ICMode | StubMode let trace = ref false let verbose = ref false diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 0f574f55214..f97f1fa2e32 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -78,6 +78,7 @@ let flag_of_compile_mode mode = | Flags.ICMode -> "" | Flags.WasmMode -> " and flag -no-system-api" | Flags.AncientMode -> " and flag -ancient-system-api" + | Flags.StubMode -> " and flag -stub-system-api" let compile_mode_error mode env at fmt = Printf.ksprintf @@ -202,9 +203,9 @@ let error_shared env t at fmt = Diag.add_msg env.msgs (type_error at (s1^s)); match t1 with | T.Obj (T.Actor, _) -> - error_in [Flags.ICMode] env at "actor types are non-shared." + error_in [Flags.ICMode; Flags.StubMode] env at "actor types are non-shared." | T.Func (T.Shared _, _, _, _, _) -> - error_in [Flags.ICMode] env at "shared function types are non-shared." + error_in [Flags.ICMode; Flags.StubMode] env at "shared function types are non-shared." | _ -> raise Recover) fmt @@ -635,7 +636,7 @@ and infer_exp'' env exp : T.typ = ) | ObjE (sort, fields) -> if not in_prog && sort.it = T.Actor then - error_in [Flags.ICMode] env exp.at "non-toplevel actor; an actor can only be declared at the toplevel of a program"; + error_in [Flags.ICMode; Flags.StubMode] env exp.at "non-toplevel actor; an actor can only be declared at the toplevel of a program"; let env' = if sort.it = T.Actor then {env with async = false; in_actor = true} else env in infer_obj env' sort.it fields exp.at | DotE (exp1, id) -> @@ -688,7 +689,7 @@ and infer_exp'' env exp : T.typ = ) | FuncE (_, sort, typ_binds, pat, typ_opt, exp) -> if not env.pre && not in_actor && T.is_shared_sort sort.it then - error_in [Flags.ICMode] env exp.at "a shared function is only allowed as a public field of an actor"; + error_in [Flags.ICMode; Flags.StubMode] env exp.at "a shared function is only allowed as a public field of an actor"; let typ = match typ_opt with | Some typ -> typ @@ -751,8 +752,9 @@ and infer_exp'' env exp : T.typ = check_exp env t_arg exp2; if Type.is_shared_sort sort then begin if T.is_async t_ret && not in_await then - error_in [Flags.ICMode] env exp2.at + error_in [Flags.ICMode; Flags.StubMode] env exp2.at "shared, async function must be called within an await expression"; + error_in [Flags.ICMode] env exp1.at "calling a shared function not yet supported"; if not (T.concrete t_arg) then error env exp1.at "shared function argument contains abstract type\n %s" @@ -898,7 +900,7 @@ and infer_exp'' env exp : T.typ = T.Non | AsyncE exp1 -> if not in_shared then - error_in [Flags.ICMode] env exp.at "unsupported async block"; + error_in [Flags.ICMode; Flags.StubMode] env exp.at "unsupported async block"; let env' = {env with labs = T.Env.empty; rets = Some T.Pre; async = true} in let t = infer_exp env' exp1 in @@ -913,8 +915,8 @@ and infer_exp'' env exp : T.typ = (match exp1.it with | CallE (f, _, _) -> if not env.pre && (Call_conv.call_conv_of_typ f.note.note_typ).Call_conv.control = T.Returns then - error_in [Flags.ICMode] env f.at "expecting call to shared async function in await"; - | _ -> error_in [Flags.ICMode] env exp1.at "argument to await must be a call expression"); + error_in [Flags.ICMode; Flags.StubMode] env f.at "expecting call to shared async function in await"; + | _ -> error_in [Flags.ICMode; Flags.StubMode] env exp1.at "argument to await must be a call expression"); (try T.as_async_sub t1 with Invalid_argument _ -> @@ -979,7 +981,7 @@ and check_exp' env0 t exp : T.typ = t | AsyncE exp1, T.Async t' -> if not in_shared then - error_in [Flags.ICMode] env exp.at "freestanding async expression not yet supported"; + error_in [Flags.ICMode; Flags.StubMode] env exp.at "freestanding async expression not yet supported"; let env' = {env with labs = T.Env.empty; rets = Some t'; async = true} in check_exp env' t' exp1; t @@ -1458,7 +1460,7 @@ and infer_obj env s fields at : T.typ = ) fields; List.iter (fun ef -> if ef.it.vis.it = Syntax.Private && is_actor_method ef.it.dec then - error_in [Flags.ICMode] env ef.it.dec.at + error_in [Flags.ICMode; Flags.StubMode] env ef.it.dec.at "a shared function cannot be private" ) fields; end; @@ -1785,7 +1787,7 @@ and infer_dec_valdecs env dec : Scope.t = } | ClassD (id, typ_binds, pat, _, sort, _, _) -> if sort.it = T.Actor then - error_in [Flags.ICMode] env dec.at + error_in [Flags.ICMode; Flags.StubMode] env dec.at "actor classes are not supported; use an actor declaration instead"; let cs, ts, te, ce = check_typ_binds env typ_binds in let env' = adjoin_typs env te ce in @@ -1842,7 +1844,7 @@ let check_actors scope progs : unit Diag.result = | ds -> List.iter (fun d -> recover - (error_in [Flags.ICMode] env d.at) + (error_in [Flags.ICMode; Flags.StubMode] env d.at) "multiple actors in program; there must be at most one actor declaration in a program") ds ) From 4147ca8e27a8b72967ab876a14c89d40e7c1c010 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 14 Nov 2019 19:05:51 +0100 Subject: [PATCH 0581/1176] Let test.sh understand -3 --- test/run.sh | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/test/run.sh b/test/run.sh index dad50585ebc..0509d937bf1 100755 --- a/test/run.sh +++ b/test/run.sh @@ -34,7 +34,7 @@ DRUN_WRAPPER=$(realpath $(dirname $0)/drun-wrapper.sh) IC_STUB_RUN=${IC_STUB_RUN:-ic-stub-run} ECHO=echo -while getopts "a12sir" o; do +while getopts "a123sir" o; do case "${o}" in a) ACCEPT=yes @@ -45,6 +45,9 @@ while getopts "a12sir" o; do 2) API=ic ;; + 3) + API=stub + ;; s) ECHO=true ;; @@ -59,6 +62,7 @@ done if [ $API = "wasm" ]; then EXTRA_MOC_FLAGS=-no-system-api; fi if [ $API = "ancient" ]; then EXTRA_MOC_FLAGS=-ancient-system-api; fi +if [ $API = "stub" ]; then EXTRA_MOC_FLAGS=-stub-system-api; fi if [ $RELEASE = "yes" ]; then MOC_FLAGS=--release; fi shift $((OPTIND-1)) @@ -229,7 +233,9 @@ do run dvm $DVM_WRAPPER $out/$base.wasm $base.mo elif [ $API = ic ] then - # run drun-run $DRUN_WRAPPER $out/$base.wasm $base.mo + run drun-run $DRUN_WRAPPER $out/$base.wasm $base.mo + elif [ $API = stub ] + then DRUN=$IC_STUB_RUN run ic-stub-run $DRUN_WRAPPER $out/$base.wasm $base.mo else run wasm-run $WASM $out/$base.wasm From 66d2b952288f8114f3df5d5e450e41b13dae2647 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Thu, 14 Nov 2019 18:07:40 +0000 Subject: [PATCH 0582/1176] WIP --- src/codegen/compile.ml | 10 ++++----- src/mo_frontend/parser.mly | 7 ++++-- src/mo_frontend/typing.ml | 39 +++++++++++++++++++++++----------- src/pipeline/resolve_import.ml | 2 +- 4 files changed, 38 insertions(+), 20 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 9df62a4baba..4f9df323741 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -4950,7 +4950,7 @@ module FuncDec = struct mk_body env ae2 ^^ message_cleanup env sort )) - | Type.Promises -> assert false + | Type.Promises _ -> assert false | Type.Replies -> Func.of_body outer_env ["clos", I32Type; "reply", I32Type; "databuf", I32Type; "elembuf", I32Type] [] (fun env -> G.with_region at ( let get_reply = G.i (LocalGet (nr 1l)) in @@ -5010,7 +5010,7 @@ module FuncDec = struct mk_body env ae1 ^^ message_cleanup env sort )) - | Flags.AncientMode, Type.Promises -> assert false + | Flags.AncientMode, Type.Promises _ -> assert false | Flags.AncientMode, Type.Replies -> (* with callbacks *) let ae0 = VarEnv.mk_fun_ae outer_ae in Func.of_body outer_env ["reply", I32Type; "databuf", I32Type; "elembuf", I32Type] [] (fun env -> G.with_region at ( @@ -6544,7 +6544,7 @@ and compile_exp (env : E.t) ae exp = let return_arity = match control with | Type.Returns -> List.length ret_tys | Type.Replies -> 0 - | Type.Promises -> assert false in + | Type.Promises _ -> assert false in StackRep.of_arity return_arity, let fun_sr, code1 = compile_exp env ae e1 in @@ -6609,7 +6609,7 @@ and compile_exp (env : E.t) ae exp = let return_tys = match control with | Type.Returns -> res_tys | Type.Replies -> [] - | Type.Promises -> assert false in + | Type.Promises _ -> assert false in let return_arity = List.length return_tys in let mk_body env1 ae1 = compile_exp_as env1 ae1 (StackRep.of_arity return_arity) e in FuncDec.lit env ae typ_binds x sort control captured args mk_body return_tys exp.at @@ -6942,7 +6942,7 @@ and compile_static_exp env pre_ae how exp = match exp.it with let return_tys = match control with | Type.Returns -> res_tys | Type.Replies -> [] - | Type.Promises -> assert false in + | Type.Promises _ -> assert false in let mk_body env ae = assert begin (* Is this really closed? *) List.for_all (fun v -> VarEnv.NameEnv.mem v ae.VarEnv.vars) diff --git a/src/mo_frontend/parser.mly b/src/mo_frontend/parser.mly index 9a4faf37c65..0c6d2e1daa5 100644 --- a/src/mo_frontend/parser.mly +++ b/src/mo_frontend/parser.mly @@ -89,6 +89,9 @@ let share_expfield (ef : exp_field) = then ef else {ef with it = {ef.it with dec = share_dec ef.it.dec}} +let scope_bind = [{var = "@" @@ no_region; bound = PrimT "Any" @! no_region} @=no_region] +let scope_typ = VarT "@" @! no_region + %} %token EOF @@ -247,7 +250,7 @@ typ_pre : | PRIM s=TEXT { PrimT(s) @! at $sloc } | ASYNC t=typ_pre - { AsyncT(t) @! at $sloc } + { AsyncT(scope_typ,t) @! at $sloc } | s=obj_sort tfs=typ_obj { let tfs' = if s.it = Type.Actor then List.map share_typfield tfs else tfs @@ -442,7 +445,7 @@ exp_nondec(B) : | RETURN e=exp(ob) { RetE(e) @? at $sloc } | ASYNC e=exp(bl) - { AsyncE(e) @? at $sloc } + { AsyncE(scope_bind,e,scope_typ) @? at $sloc } | AWAIT e=exp(bl) { AwaitE(e) @? at $sloc } | ASSERT e=exp(bl) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 91438a5965f..ac4da833d78 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -367,6 +367,11 @@ and check_typ_binds env typ_binds : T.con list * T.typ list * Scope.typ_env * Sc List.iter2 (fun typ_bind c -> typ_bind.note <- Some c) typ_binds cs; cs, ts, te, T.ConSet.of_list cs +and check_typ_bind env typ_bind : T.con * T.typ * Scope.typ_env * Scope.con_env = + match check_typ_binds env [typ_bind] with + | [c], [t], te, cs -> c, t, te, cs + | _ -> assert false + and check_typ_bounds env (tbs : T.bind list) (ts : T.typ list) typs at = let pars = List.length tbs in let args = List.length ts in @@ -900,21 +905,22 @@ and infer_exp'' env exp : T.typ = error env exp.at "misplaced throw"; if not env.pre then check_exp env T.throw exp1; T.Non - | AsyncE (_, exp1, _) -> + | AsyncE (tb, exp1, typ0) -> if not in_shared then error_in [Flags.ICMode] env exp.at "unsupported async block"; + let t0 = check_typ env typ0 in + let c, tb, ce, cs = check_typ_bind env tb in let env' = - {env with labs = T.Env.empty; rets = Some T.Pre; async = true} in + {(adjoin_typs env ce cs) with labs = T.Env.empty; rets = Some T.Pre; async = true} in let t = infer_exp env' exp1 in - if not (T.shared t) then - error_shared env t exp1.at "async type has non-shared content type\n %s" - (T.string_of_typ_expand t); - T.Async t - | AwaitE (typ_bind, exp1, typ0) -> + let t1 = T.open_ [t0] (T.close [c] t) in + if not (T.shared t1) then + error_shared env t1 exp1.at "async type has non-shared content type\n %s" + (T.string_of_typ_expand t1); + T.Async (t0,t1) + | AwaitE exp1 -> if not env.async then error env exp.at "misplaced await"; - let t0 = check_typ env typ0 in - let c, tb, ce = check_open_typ_bind env tb in let t1 = infer_exp_promote {env with in_await = true} exp1 in (match exp1.it with | CallE (f, _, _) -> @@ -922,7 +928,9 @@ and infer_exp'' env exp : T.typ = error_in [Flags.ICMode] env f.at "expecting call to shared async function in await"; | _ -> error_in [Flags.ICMode] env exp1.at "argument to await must be a call expression"); (try - T.as_async_sub t1 + let (t2,t3) = T.as_async_sub t1 in + (* TODO: check the index *) + t3 with Invalid_argument _ -> error env exp1.at "expected async type, but expression has type\n %s" (T.string_of_typ_expand t1) @@ -983,10 +991,17 @@ and check_exp' env0 t exp : T.typ = (T.string_of_typ_expand (T.Array t')); List.iter (check_exp env (T.as_immut t')) exps; t - | AsyncE exp1, T.Async t' -> + | AsyncE (tb, exp1, typ0), T.Async (t0',t') -> if not in_shared then error_in [Flags.ICMode] env exp.at "freestanding async expression not yet supported"; - let env' = {env with labs = T.Env.empty; rets = Some t'; async = true} in + let t0 = check_typ env typ0 in + if not (T.eq t0 t0') then + error env exp.at "async at scope\n %s\ncannot produce expected scope\n %s" + (T.string_of_typ_expand t0) + (T.string_of_typ_expand t0'); + let c, tb, ce, cs = check_typ_bind env tb in + let env' = + {(adjoin_typs env ce cs) with labs = T.Env.empty; rets = Some t'; async = true} in check_exp env' t' exp1; t | BlockE decs, _ -> diff --git a/src/pipeline/resolve_import.ml b/src/pipeline/resolve_import.ml index 5fd5dde93eb..379cc819dd5 100644 --- a/src/pipeline/resolve_import.ml +++ b/src/pipeline/resolve_import.ml @@ -155,7 +155,7 @@ let rec | BreakE (_, exp1) | RetE exp1 | AnnotE (exp1, _) - | AsyncE exp1 + | AsyncE (_, exp1, _) | AwaitE exp1 | ThrowE exp1 | LoopE (exp1, None) -> From 5f4057f4fab0fb23e671cf2d176055452562c9b2 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 14 Nov 2019 19:09:23 +0100 Subject: [PATCH 0583/1176] Create `test-stub` and update test output --- test/Makefile | 5 + test/run-drun/ok/counter.drun-run.ok | 18 ++ .../ok/hello-world-return.drun-run.ok | 3 + test/run-drun/ok/ic-calls.comp.ok | 6 + test/run-drun/ok/ic-calls.comp.ret.ok | 1 + test/run-drun/ok/idl-any.drun-run.ok | 57 ++++ test/run-drun/ok/idl-bad.drun-run.ok | 2 + test/run-drun/ok/idl-field-escape.drun-run.ok | 5 + test/run-drun/ok/idl-nary.drun-run.ok | 12 + test/run-drun/ok/idl-nat-int.drun-run.ok | 5 + test/run-drun/ok/idl-option.drun-run.ok | 7 + test/run-drun/ok/idl-pair.drun-run.ok | 2 + test/run-drun/ok/idl-record.drun-run.ok | 9 + test/run-drun/ok/idl-tuple.drun-run.ok | 5 + test/run-drun/ok/idl-unit.drun-run.ok | 2 + test/run-drun/ok/idl-variant.drun-run.ok | 2 + test/run-drun/ok/idl-vector.drun-run.ok | 2 + test/run-drun/ok/large-array.drun-run.ok | 1 + test/run-drun/ok/oom.drun-run.ok | 3 + test/run-drun/ok/print-from-init.drun-run.ok | 2 + test/run-drun/ok/query.drun-run.ok | 34 +++ test/run-drun/ok/reject.drun-run.ok | 9 + test/run-drun/ok/reversi.drun-run.ok | 9 + test/run-drun/ok/self-calls.comp.ok | 15 + test/run-drun/ok/self-calls.comp.ret.ok | 1 + test/run-drun/ok/self-calls.run-ir.ok | 9 + test/run-drun/ok/self-calls.run-low.ok | 9 + test/run-drun/ok/self-calls.run.ok | 9 + test/run-drun/ok/self-calls.tc.ok | 9 + test/run-drun/ok/unsupported.comp.ok | 2 + test/run-drun/self-calls.mo | 27 ++ test/run-stub/Makefile | 12 + test/run-stub/counter.mo | 18 ++ test/run-stub/hello-world-return.mo | 11 + test/run-stub/ic-calls.mo | 24 ++ test/run-stub/idl-any.mo | 39 +++ test/run-stub/idl-bad.mo | 7 + test/run-stub/idl-field-escape.mo | 27 ++ test/run-stub/idl-func.mo | 13 + test/run-stub/idl-nary.mo | 53 ++++ test/run-stub/idl-nat-int.mo | 18 ++ test/run-stub/idl-option.mo | 14 + test/run-stub/idl-pair.mo | 8 + test/run-stub/idl-record.mo | 34 +++ test/run-stub/idl-tuple.mo | 17 ++ test/run-stub/idl-unit.mo | 7 + test/run-stub/idl-variant.mo | 16 + test/run-stub/idl-vector.mo | 13 + test/run-stub/large-array.mo | 7 + test/run-stub/multiple-actors.mo | 7 + .../ok/counter.ic-stub-run.ok | 0 .../ok/hello-world-return.ic-stub-run.ok | 0 test/run-stub/ok/ic-calls.comp.ok | 9 + test/run-stub/ok/ic-calls.ic-stub-run.ok | 4 + test/run-stub/ok/ic-calls.run-ir.ok | 9 + test/run-stub/ok/ic-calls.run-low.ok | 9 + test/run-stub/ok/ic-calls.run.ok | 9 + test/run-stub/ok/ic-calls.tc.ok | 9 + .../ok/idl-any.ic-stub-run.ok | 0 .../ok/idl-bad.ic-stub-run.ok | 0 .../ok/idl-field-escape.ic-stub-run.ok | 0 test/run-stub/ok/idl-func.ic-stub-run.ok | 6 + .../ok/idl-nary.ic-stub-run.ok | 0 .../ok/idl-nat-int.ic-stub-run.ok | 0 .../ok/idl-option.ic-stub-run.ok | 0 .../ok/idl-pair.ic-stub-run.ok | 0 .../ok/idl-record.ic-stub-run.ok | 0 .../ok/idl-tuple.ic-stub-run.ok | 0 .../ok/idl-unit.ic-stub-run.ok | 0 .../ok/idl-variant.ic-stub-run.ok | 0 .../ok/idl-vector.ic-stub-run.ok | 0 test/run-stub/ok/multiple-actors.comp.ok | 4 + test/run-stub/ok/multiple-actors.comp.ret.ok | 1 + .../ok/oom.ic-stub-run.ok | 0 .../ok/print-from-init.ic-stub-run.ok | 0 test/run-stub/ok/print-from-init.run-ir.ok | 1 + test/run-stub/ok/print-from-init.run-low.ok | 1 + test/run-stub/ok/print-from-init.run.ok | 1 + .../ok/query.ic-stub-run.ok | 0 .../ok/reject.ic-stub-run.ok | 0 .../ok/reversi.ic-stub-run.ok | 0 test/run-stub/ok/self-calls.comp.ok | 9 + test/run-stub/ok/self-calls.ic-stub-run.ok | 11 + test/run-stub/ok/self-calls.run-ir.ok | 9 + test/run-stub/ok/self-calls.run-low.ok | 9 + test/run-stub/ok/self-calls.run.ok | 9 + test/run-stub/ok/self-calls.tc.ok | 9 + test/run-stub/ok/unsupported.comp.ok | 20 ++ test/run-stub/ok/unsupported.comp.ret.ok | 1 + test/run-stub/oom.mo | 13 + test/run-stub/print-from-init.mo | 3 + test/run-stub/query.mo | 29 ++ test/run-stub/reject.mo | 29 ++ test/run-stub/reversi.mo | 274 ++++++++++++++++++ test/run-stub/self-calls.mo | 27 ++ test/run-stub/unsupported.mo | 76 +++++ 96 files changed, 1218 insertions(+) create mode 100644 test/run-drun/ok/counter.drun-run.ok create mode 100644 test/run-drun/ok/hello-world-return.drun-run.ok create mode 100644 test/run-drun/ok/ic-calls.comp.ret.ok create mode 100644 test/run-drun/ok/idl-any.drun-run.ok create mode 100644 test/run-drun/ok/idl-bad.drun-run.ok create mode 100644 test/run-drun/ok/idl-field-escape.drun-run.ok create mode 100644 test/run-drun/ok/idl-nary.drun-run.ok create mode 100644 test/run-drun/ok/idl-nat-int.drun-run.ok create mode 100644 test/run-drun/ok/idl-option.drun-run.ok create mode 100644 test/run-drun/ok/idl-pair.drun-run.ok create mode 100644 test/run-drun/ok/idl-record.drun-run.ok create mode 100644 test/run-drun/ok/idl-tuple.drun-run.ok create mode 100644 test/run-drun/ok/idl-unit.drun-run.ok create mode 100644 test/run-drun/ok/idl-variant.drun-run.ok create mode 100644 test/run-drun/ok/idl-vector.drun-run.ok create mode 100644 test/run-drun/ok/large-array.drun-run.ok create mode 100644 test/run-drun/ok/oom.drun-run.ok create mode 100644 test/run-drun/ok/print-from-init.drun-run.ok create mode 100644 test/run-drun/ok/query.drun-run.ok create mode 100644 test/run-drun/ok/reject.drun-run.ok create mode 100644 test/run-drun/ok/reversi.drun-run.ok create mode 100644 test/run-drun/ok/self-calls.comp.ok create mode 100644 test/run-drun/ok/self-calls.comp.ret.ok create mode 100644 test/run-drun/ok/self-calls.run-ir.ok create mode 100644 test/run-drun/ok/self-calls.run-low.ok create mode 100644 test/run-drun/ok/self-calls.run.ok create mode 100644 test/run-drun/ok/self-calls.tc.ok create mode 100644 test/run-drun/self-calls.mo create mode 100644 test/run-stub/Makefile create mode 100644 test/run-stub/counter.mo create mode 100644 test/run-stub/hello-world-return.mo create mode 100644 test/run-stub/ic-calls.mo create mode 100644 test/run-stub/idl-any.mo create mode 100644 test/run-stub/idl-bad.mo create mode 100644 test/run-stub/idl-field-escape.mo create mode 100644 test/run-stub/idl-func.mo create mode 100644 test/run-stub/idl-nary.mo create mode 100644 test/run-stub/idl-nat-int.mo create mode 100644 test/run-stub/idl-option.mo create mode 100644 test/run-stub/idl-pair.mo create mode 100644 test/run-stub/idl-record.mo create mode 100644 test/run-stub/idl-tuple.mo create mode 100644 test/run-stub/idl-unit.mo create mode 100644 test/run-stub/idl-variant.mo create mode 100644 test/run-stub/idl-vector.mo create mode 100644 test/run-stub/large-array.mo create mode 100644 test/run-stub/multiple-actors.mo rename test/{run-drun => run-stub}/ok/counter.ic-stub-run.ok (100%) rename test/{run-drun => run-stub}/ok/hello-world-return.ic-stub-run.ok (100%) create mode 100644 test/run-stub/ok/ic-calls.comp.ok create mode 100644 test/run-stub/ok/ic-calls.ic-stub-run.ok create mode 100644 test/run-stub/ok/ic-calls.run-ir.ok create mode 100644 test/run-stub/ok/ic-calls.run-low.ok create mode 100644 test/run-stub/ok/ic-calls.run.ok create mode 100644 test/run-stub/ok/ic-calls.tc.ok rename test/{run-drun => run-stub}/ok/idl-any.ic-stub-run.ok (100%) rename test/{run-drun => run-stub}/ok/idl-bad.ic-stub-run.ok (100%) rename test/{run-drun => run-stub}/ok/idl-field-escape.ic-stub-run.ok (100%) create mode 100644 test/run-stub/ok/idl-func.ic-stub-run.ok rename test/{run-drun => run-stub}/ok/idl-nary.ic-stub-run.ok (100%) rename test/{run-drun => run-stub}/ok/idl-nat-int.ic-stub-run.ok (100%) rename test/{run-drun => run-stub}/ok/idl-option.ic-stub-run.ok (100%) rename test/{run-drun => run-stub}/ok/idl-pair.ic-stub-run.ok (100%) rename test/{run-drun => run-stub}/ok/idl-record.ic-stub-run.ok (100%) rename test/{run-drun => run-stub}/ok/idl-tuple.ic-stub-run.ok (100%) rename test/{run-drun => run-stub}/ok/idl-unit.ic-stub-run.ok (100%) rename test/{run-drun => run-stub}/ok/idl-variant.ic-stub-run.ok (100%) rename test/{run-drun => run-stub}/ok/idl-vector.ic-stub-run.ok (100%) create mode 100644 test/run-stub/ok/multiple-actors.comp.ok create mode 100644 test/run-stub/ok/multiple-actors.comp.ret.ok rename test/{run-drun => run-stub}/ok/oom.ic-stub-run.ok (100%) rename test/{run-drun => run-stub}/ok/print-from-init.ic-stub-run.ok (100%) create mode 100644 test/run-stub/ok/print-from-init.run-ir.ok create mode 100644 test/run-stub/ok/print-from-init.run-low.ok create mode 100644 test/run-stub/ok/print-from-init.run.ok rename test/{run-drun => run-stub}/ok/query.ic-stub-run.ok (100%) rename test/{run-drun => run-stub}/ok/reject.ic-stub-run.ok (100%) rename test/{run-drun => run-stub}/ok/reversi.ic-stub-run.ok (100%) create mode 100644 test/run-stub/ok/self-calls.comp.ok create mode 100644 test/run-stub/ok/self-calls.ic-stub-run.ok create mode 100644 test/run-stub/ok/self-calls.run-ir.ok create mode 100644 test/run-stub/ok/self-calls.run-low.ok create mode 100644 test/run-stub/ok/self-calls.run.ok create mode 100644 test/run-stub/ok/self-calls.tc.ok create mode 100644 test/run-stub/ok/unsupported.comp.ok create mode 100644 test/run-stub/ok/unsupported.comp.ret.ok create mode 100644 test/run-stub/oom.mo create mode 100644 test/run-stub/print-from-init.mo create mode 100644 test/run-stub/query.mo create mode 100644 test/run-stub/reject.mo create mode 100644 test/run-stub/reversi.mo create mode 100644 test/run-stub/self-calls.mo create mode 100644 test/run-stub/unsupported.mo diff --git a/test/Makefile b/test/Makefile index 052150efede..8502938468f 100644 --- a/test/Makefile +++ b/test/Makefile @@ -4,6 +4,7 @@ all: $(MAKE) -C run-release $(MAKE) -C run-dfinity $(MAKE) -C run-drun + $(MAKE) -C run-stub $(MAKE) -C repl $(MAKE) -C ld $(MAKE) -C idl @@ -24,6 +25,7 @@ quick: parallel: quick $(MAKE_PAR) -C run-dfinity quick $(MAKE_PAR) -C run-drun quick + $(MAKE_PAR) -C run-stub quick $(MAKE_PAR) -C trap quick $(MAKE_PAR) -C run-deser quick @@ -37,6 +39,7 @@ coverage: $(MAKE) -C run-release; \ $(MAKE) -C run-dfinity; \ $(MAKE) -C run-drun; \ + $(MAKE) -C run-stub; \ $(MAKE) -C repl; $(MAKE) -C ld || true bisect-ppx-report -I ../src/_build/ -html coverage/ _coverage/bisect*.out @@ -48,6 +51,7 @@ accept: $(MAKE) -C run-release accept $(MAKE) -C run-dfinity accept $(MAKE) -C run-drun accept + $(MAKE) -C run-stub accept $(MAKE) -C repl accept $(MAKE) -C ld accept $(MAKE) -C idl accept @@ -61,6 +65,7 @@ clean: $(MAKE) -C run-release clean $(MAKE) -C run-dfinity clean $(MAKE) -C run-drun clean + $(MAKE) -C run-stub clean $(MAKE) -C repl clean $(MAKE) -C ld clean $(MAKE) -C mo-idl clean diff --git a/test/run-drun/ok/counter.drun-run.ok b/test/run-drun/ok/counter.drun-run.ok new file mode 100644 index 00000000000..7d9bd915a92 --- /dev/null +++ b/test/run-drun/ok/counter.drun-run.ok @@ -0,0 +1,18 @@ +ingress(0) System +debug.print: 2 +debug.print: + +ingress(1) Completed: Canister: Empty +debug.print: 3 +debug.print: + +ingress(2) Completed: Canister: Empty +debug.print: 4 +debug.print: + +ingress(3) Completed: Canister: Empty +debug.print: 4 +debug.print: + +ingress(4) Completed: Canister: Empty +ingress(5) Completed: Canister: Payload: 0x4449444c00017d04 diff --git a/test/run-drun/ok/hello-world-return.drun-run.ok b/test/run-drun/ok/hello-world-return.drun-run.ok new file mode 100644 index 00000000000..c1f0a27528b --- /dev/null +++ b/test/run-drun/ok/hello-world-return.drun-run.ok @@ -0,0 +1,3 @@ +ingress(0) System +Ok: Payload: 0x4449444c0001710c48656c6c6f20576f726c6421 +Ok: Payload: 0x4449444c0001710c48656c6c6f20576f726c6421 diff --git a/test/run-drun/ok/ic-calls.comp.ok b/test/run-drun/ok/ic-calls.comp.ok index dec54dfc5ac..e753cbd283c 100644 --- a/test/run-drun/ok/ic-calls.comp.ok +++ b/test/run-drun/ok/ic-calls.comp.ok @@ -7,3 +7,9 @@ ic-calls.mo:19.9-19.17: warning, this pattern consuming type does not cover value (1, false) or (0 or -1 or _, _) +ic-calls.mo:17.20-17.21: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +ic-calls.mo:18.19-18.20: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +ic-calls.mo:19.26-19.27: type error, calling a shared function not yet supported + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/ic-calls.comp.ret.ok b/test/run-drun/ok/ic-calls.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/ic-calls.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-drun/ok/idl-any.drun-run.ok b/test/run-drun/ok/idl-any.drun-run.ok new file mode 100644 index 00000000000..4f76ce5ac28 --- /dev/null +++ b/test/run-drun/ok/idl-any.drun-run.ok @@ -0,0 +1,57 @@ +ingress(0) System +debug.print: ok: Foo +ingress(1) Completed: Canister: Payload: 0x4449444c0000 +debug.print: ok: Foo +ingress(2) Completed: Canister: Payload: 0x4449444c0000 +debug.print: ok: Foo +ingress(3) Completed: Canister: Payload: 0x4449444c0000 +debug.print: ok: Foo +ingress(4) Completed: Canister: Payload: 0x4449444c0000 +debug.print: ok: Foo +ingress(5) Completed: Canister: Payload: 0x4449444c0000 +debug.print: ok: Foo +ingress(6) Completed: Canister: Payload: 0x4449444c0000 +debug.print: ok: Foo +ingress(7) Completed: Canister: Payload: 0x4449444c0000 +debug.print: ok: Foo +ingress(8) Completed: Canister: Payload: 0x4449444c0000 +debug.print: ok: Foo +ingress(9) Completed: Canister: Payload: 0x4449444c0000 +debug.print: ok: Foo +ingress(10) Completed: Canister: Payload: 0x4449444c0000 +debug.print: ok: Foo +ingress(11) Completed: Canister: Payload: 0x4449444c0000 +debug.print: ok: Foo +ingress(12) Completed: Canister: Payload: 0x4449444c0000 +debug.print: ok: Foo +ingress(13) Completed: Canister: Payload: 0x4449444c0000 +debug.print: ok: Foo +ingress(14) Completed: Canister: Payload: 0x4449444c0000 +debug.print: ok: Foo +ingress(15) Completed: Canister: Payload: 0x4449444c0000 +debug.print: ok: Foo +ingress(16) Completed: Canister: Payload: 0x4449444c0000 +debug.print: ok: Foo +ingress(17) Completed: Canister: Payload: 0x4449444c0000 +debug.print: ok: Foo +ingress(18) Completed: Canister: Payload: 0x4449444c0000 +debug.print: ok: Foo +ingress(19) Completed: Canister: Payload: 0x4449444c0000 +debug.print: ok: Foo +ingress(20) Completed: Canister: Payload: 0x4449444c0000 +debug.print: ok: Foo +ingress(21) Completed: Canister: Payload: 0x4449444c0000 +debug.print: ok: Foo +ingress(22) Completed: Canister: Payload: 0x4449444c0000 +debug.print: ok: Foo +ingress(23) Completed: Canister: Payload: 0x4449444c0000 +debug.print: ok: Foo +ingress(24) Completed: Canister: Payload: 0x4449444c0000 +debug.print: ok: Foo +ingress(25) Completed: Canister: Payload: 0x4449444c0000 +debug.print: ok: Foo +ingress(26) Completed: Canister: Payload: 0x4449444c0000 +debug.print: ok: Foo +ingress(27) Completed: Canister: Payload: 0x4449444c0000 +debug.print: ok: Foo +ingress(28) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-bad.drun-run.ok b/test/run-drun/ok/idl-bad.drun-run.ok new file mode 100644 index 00000000000..401133f7f50 --- /dev/null +++ b/test/run-drun/ok/idl-bad.drun-run.ok @@ -0,0 +1,2 @@ +ingress(0) System +Err: IC0503: Canister 42 trapped explicitly: IDL error: missing magic bytes diff --git a/test/run-drun/ok/idl-field-escape.drun-run.ok b/test/run-drun/ok/idl-field-escape.drun-run.ok new file mode 100644 index 00000000000..2d425b83ef4 --- /dev/null +++ b/test/run-drun/ok/idl-field-escape.drun-run.ok @@ -0,0 +1,5 @@ +ingress(0) System +ingress(1) Completed: Canister: Payload: 0x4449444c026c01868eb702016c000100 +ingress(2) Completed: Canister: Payload: 0x4449444c026c01868eb702016c000100 +ingress(3) Completed: Canister: Payload: 0x4449444c016c03007c017dbcfef7b102710100ffff03802003585858 +ingress(4) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-nary.drun-run.ok b/test/run-drun/ok/idl-nary.drun-run.ok new file mode 100644 index 00000000000..e6f3a393455 --- /dev/null +++ b/test/run-drun/ok/idl-nary.drun-run.ok @@ -0,0 +1,12 @@ +ingress(0) System +ingress(1) Completed: Canister: Payload: 0x4449444c00027171034f6e650354776f +ingress(2) Completed: Canister: Payload: 0x4449444c0003717171034f6e650354776f055468726565 +ingress(3) Completed: Canister: Payload: 0x4449444c000471717171034f6e650354776f05546872656504466f7572 +ingress(4) Completed: Canister: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 +ingress(5) Completed: Canister: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 +ingress(6) Completed: Canister: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 +ingress(7) Completed: Canister: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 +ingress(8) Completed: Canister: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 +ingress(9) Err: IC0503: Canister 42 trapped explicitly: IDL error: too few arguments Text,Text,Text +ingress(10) Err: IC0503: Canister 42 trapped explicitly: IDL error: left-over bytes Text,Text,Text +ingress(11) Completed: Canister: Payload: 0x4449444c000471717171034f6e650354776f05546872656504466f7572 diff --git a/test/run-drun/ok/idl-nat-int.drun-run.ok b/test/run-drun/ok/idl-nat-int.drun-run.ok new file mode 100644 index 00000000000..f450261cb17 --- /dev/null +++ b/test/run-drun/ok/idl-nat-int.drun-run.ok @@ -0,0 +1,5 @@ +ingress(0) System +Ok: Payload: 0x4449444c00017d2a +Ok: Payload: 0x4449444c00017d2a +Ok: Payload: 0x4449444c016d7d0100022a19 +Ok: Payload: 0x4449444c016d7d0100022a19 diff --git a/test/run-drun/ok/idl-option.drun-run.ok b/test/run-drun/ok/idl-option.drun-run.ok new file mode 100644 index 00000000000..028b1b4aa2e --- /dev/null +++ b/test/run-drun/ok/idl-option.drun-run.ok @@ -0,0 +1,7 @@ +ingress(0) System +debug.print: ok: null +ingress(1) Completed: Canister: Payload: 0x4449444c0000 +debug.print: ok: null +ingress(2) Completed: Canister: Payload: 0x4449444c0000 +debug.print: ok: Foo +ingress(3) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-pair.drun-run.ok b/test/run-drun/ok/idl-pair.drun-run.ok new file mode 100644 index 00000000000..fd1ef07bac7 --- /dev/null +++ b/test/run-drun/ok/idl-pair.drun-run.ok @@ -0,0 +1,2 @@ +ingress(0) System +ingress(1) Completed: Canister: Payload: 0x4449444c016c02007c017c01000205 diff --git a/test/run-drun/ok/idl-record.drun-run.ok b/test/run-drun/ok/idl-record.drun-run.ok new file mode 100644 index 00000000000..933c43b7393 --- /dev/null +++ b/test/run-drun/ok/idl-record.drun-run.ok @@ -0,0 +1,9 @@ +ingress(0) System +debug.print: ok: +42 +ingress(1) Completed: Canister: Payload: 0x4449444c0000 +debug.print: ok: Hey! +ingress(2) Completed: Canister: Payload: 0x4449444c0000 +debug.print: ok: +25 +ingress(3) Completed: Canister: Payload: 0x4449444c0000 +debug.print: ok: Hey! +25 +ingress(4) Completed: Canister: Payload: 0x4449444c00017719 diff --git a/test/run-drun/ok/idl-tuple.drun-run.ok b/test/run-drun/ok/idl-tuple.drun-run.ok new file mode 100644 index 00000000000..6789a1dbd26 --- /dev/null +++ b/test/run-drun/ok/idl-tuple.drun-run.ok @@ -0,0 +1,5 @@ +ingress(0) System +Ok: Payload: 0x4449444c00027c7c0205 +Ok: Payload: 0x4449444c00037c7c7c050581848c20 +Ok: Payload: 0x4449444c00037c7c7c050581848c20 +Ok: Payload: 0x4449444c00037c7c7c050581848c20 diff --git a/test/run-drun/ok/idl-unit.drun-run.ok b/test/run-drun/ok/idl-unit.drun-run.ok new file mode 100644 index 00000000000..139fbf3fc92 --- /dev/null +++ b/test/run-drun/ok/idl-unit.drun-run.ok @@ -0,0 +1,2 @@ +ingress(0) System +Ok: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-variant.drun-run.ok b/test/run-drun/ok/idl-variant.drun-run.ok new file mode 100644 index 00000000000..2e39e7bfc87 --- /dev/null +++ b/test/run-drun/ok/idl-variant.drun-run.ok @@ -0,0 +1,2 @@ +ingress(0) System +Ok: Payload: 0x4449444c016b03d583b702008790c0bd0479dc9790cb0e790100000120000000 diff --git a/test/run-drun/ok/idl-vector.drun-run.ok b/test/run-drun/ok/idl-vector.drun-run.ok new file mode 100644 index 00000000000..a8c227d6d03 --- /dev/null +++ b/test/run-drun/ok/idl-vector.drun-run.ok @@ -0,0 +1,2 @@ +ingress(0) System +Ok: Payload: 0x4449444c026e016d0001000103010001040100010201000100010001000100 diff --git a/test/run-drun/ok/large-array.drun-run.ok b/test/run-drun/ok/large-array.drun-run.ok new file mode 100644 index 00000000000..43d7af40394 --- /dev/null +++ b/test/run-drun/ok/large-array.drun-run.ok @@ -0,0 +1 @@ +ingress(0) System diff --git a/test/run-drun/ok/oom.drun-run.ok b/test/run-drun/ok/oom.drun-run.ok new file mode 100644 index 00000000000..d1d6ed87e8b --- /dev/null +++ b/test/run-drun/ok/oom.drun-run.ok @@ -0,0 +1,3 @@ +ingress(0) System +ingress(1) Completed: Canister: Empty +ingress(2) Completed: Canister: Empty diff --git a/test/run-drun/ok/print-from-init.drun-run.ok b/test/run-drun/ok/print-from-init.drun-run.ok new file mode 100644 index 00000000000..4d57fad6ec2 --- /dev/null +++ b/test/run-drun/ok/print-from-init.drun-run.ok @@ -0,0 +1,2 @@ +debug.print: Debug out +ingress(0) System diff --git a/test/run-drun/ok/query.drun-run.ok b/test/run-drun/ok/query.drun-run.ok new file mode 100644 index 00000000000..5137d9c8055 --- /dev/null +++ b/test/run-drun/ok/query.drun-run.ok @@ -0,0 +1,34 @@ +ingress(0) System +debug.print: 2 +debug.print: + +ingress(1) Completed: Canister: Empty +debug.print: 3 +debug.print: + +ingress(2) Completed: Canister: Empty +debug.print: 4 +debug.print: + +ingress(3) Completed: Canister: Empty +debug.print: 4 +debug.print: + +ingress(4) Completed: Canister: Empty +ingress(5) Completed: Canister: Payload: 0x4449444c00017d04 +debug.print: 5 +debug.print: + +Ok: Payload: 0x4449444c00017d04 +debug.print: 4 +debug.print: + +ingress(6) Completed: Canister: Empty +debug.print: 5 +debug.print: + +Ok: Payload: 0x4449444c00017d04 +debug.print: 4 +debug.print: + +ingress(7) Completed: Canister: Empty diff --git a/test/run-drun/ok/reject.drun-run.ok b/test/run-drun/ok/reject.drun-run.ok new file mode 100644 index 00000000000..8ea07ed3242 --- /dev/null +++ b/test/run-drun/ok/reject.drun-run.ok @@ -0,0 +1,9 @@ +ingress(0) System +debug.print: 1 +ingress(1) Completed: Canister: Reject: Error +debug.print: 1 +debug.print: ok +ingress(2) Completed: Canister: Payload: 0x4449444c0000 +debug.print: 1 +debug.print: ok +ingress(3) Completed: Canister: Reject: Error diff --git a/test/run-drun/ok/reversi.drun-run.ok b/test/run-drun/ok/reversi.drun-run.ok new file mode 100644 index 00000000000..0c49bd69fb7 --- /dev/null +++ b/test/run-drun/ok/reversi.drun-run.ok @@ -0,0 +1,9 @@ +ingress(0) System +ingress(1) Completed: Canister: Empty +ingress(2) Completed: Canister: Payload: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e4f2a2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a +ingress(3) Completed: Canister: Payload: 0x4449444c000171024f4b +ingress(4) Completed: Canister: Payload: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e4f2e2e2e0a2e2e2e4f4f2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a +ingress(5) Completed: Canister: Payload: 0x4449444c000171024f4b +ingress(6) Completed: Canister: Payload: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a +ingress(7) Completed: Canister: Payload: 0x4449444c000171024f4b +ingress(8) Completed: Canister: Payload: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e4f4f2e2e2e0a2e2e4f4f4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a diff --git a/test/run-drun/ok/self-calls.comp.ok b/test/run-drun/ok/self-calls.comp.ok new file mode 100644 index 00000000000..7320705bb9f --- /dev/null +++ b/test/run-drun/ok/self-calls.comp.ok @@ -0,0 +1,15 @@ +self-calls.mo:21.9-21.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +self-calls.mo:23.9-23.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (1, false) or + (0 or -1 or _, _) +self-calls.mo:19.20-19.23: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +self-calls.mo:21.19-21.22: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +self-calls.mo:23.26-23.29: type error, calling a shared function not yet supported + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/self-calls.comp.ret.ok b/test/run-drun/ok/self-calls.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/self-calls.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-drun/ok/self-calls.run-ir.ok b/test/run-drun/ok/self-calls.run-ir.ok new file mode 100644 index 00000000000..0dc2420ebed --- /dev/null +++ b/test/run-drun/ok/self-calls.run-ir.ok @@ -0,0 +1,9 @@ +self-calls.mo:21.9-21.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +self-calls.mo:23.9-23.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (1, false) or + (0 or -1 or _, _) diff --git a/test/run-drun/ok/self-calls.run-low.ok b/test/run-drun/ok/self-calls.run-low.ok new file mode 100644 index 00000000000..0dc2420ebed --- /dev/null +++ b/test/run-drun/ok/self-calls.run-low.ok @@ -0,0 +1,9 @@ +self-calls.mo:21.9-21.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +self-calls.mo:23.9-23.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (1, false) or + (0 or -1 or _, _) diff --git a/test/run-drun/ok/self-calls.run.ok b/test/run-drun/ok/self-calls.run.ok new file mode 100644 index 00000000000..0dc2420ebed --- /dev/null +++ b/test/run-drun/ok/self-calls.run.ok @@ -0,0 +1,9 @@ +self-calls.mo:21.9-21.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +self-calls.mo:23.9-23.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (1, false) or + (0 or -1 or _, _) diff --git a/test/run-drun/ok/self-calls.tc.ok b/test/run-drun/ok/self-calls.tc.ok new file mode 100644 index 00000000000..0dc2420ebed --- /dev/null +++ b/test/run-drun/ok/self-calls.tc.ok @@ -0,0 +1,9 @@ +self-calls.mo:21.9-21.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +self-calls.mo:23.9-23.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (1, false) or + (0 or -1 or _, _) diff --git a/test/run-drun/ok/unsupported.comp.ok b/test/run-drun/ok/unsupported.comp.ok index 9b4b2c70f19..fa8f5d395b1 100644 --- a/test/run-drun/ok/unsupported.comp.ok +++ b/test/run-drun/ok/unsupported.comp.ok @@ -16,6 +16,8 @@ unsupported.mo:8.31-8.53: type error, shared function types are non-shared. (This is a limitation of the current version.) unsupported.mo:19.19-19.21: type error, shared, async function must be called within an await expression (This is a limitation of the current version.) +unsupported.mo:23.16-23.18: type error, calling a shared function not yet supported + (This is a limitation of the current version.) unsupported.mo:28.8-28.9: type error, argument to await must be a call expression (This is a limitation of the current version.) unsupported.mo:32.17-32.29: type error, unsupported async block diff --git a/test/run-drun/self-calls.mo b/test/run-drun/self-calls.mo new file mode 100644 index 00000000000..0f139b5c157 --- /dev/null +++ b/test/run-drun/self-calls.mo @@ -0,0 +1,27 @@ +actor X { + public func A() : async () { + debugPrint("A called"); + }; + + + public func B(x : Int) : async Int { + debugPrint("B called"); + x + }; + + public func C(x : Int, y: Bool) : async (Int,Bool) { + debugPrint("C called"); + (x,y); + }; + + public func test() : async () { + debugPrint("test1"); + let () = await X.A(); + debugPrint("test2"); + let 1 = await X.B(1); + debugPrint("test3"); + let (1,true) = await X.C(1,true); + debugPrint("test4"); + }; +} +//CALL ingress test 0x4449444C0000 diff --git a/test/run-stub/Makefile b/test/run-stub/Makefile new file mode 100644 index 00000000000..72bda5cb77b --- /dev/null +++ b/test/run-stub/Makefile @@ -0,0 +1,12 @@ +RUNFLAGS = -3 + +all: + ../run.sh $(RUNFLAGS) *.mo + +accept: + ../run.sh $(RUNFLAGS) -a *.mo + +clean: + rm -rf _out + +include ../*.mk diff --git a/test/run-stub/counter.mo b/test/run-stub/counter.mo new file mode 100644 index 00000000000..0e40920fb6f --- /dev/null +++ b/test/run-stub/counter.mo @@ -0,0 +1,18 @@ +actor { + var c = 1; + public func inc() { + c += 1; + debugPrintNat c; debugPrint "\n"; + }; + public func printCounter () { + debugPrintNat c; debugPrint "\n"; + }; + public func get() : async Nat { + return c + }; +} +//CALL ingress inc 0x4449444C0000 +//CALL ingress inc 0x4449444C0000 +//CALL ingress inc 0x4449444C0000 +//CALL ingress printCounter 0x4449444C0000 +//CALL ingress get 0x4449444C0000 diff --git a/test/run-stub/hello-world-return.mo b/test/run-stub/hello-world-return.mo new file mode 100644 index 00000000000..e1a4ca1644d --- /dev/null +++ b/test/run-stub/hello-world-return.mo @@ -0,0 +1,11 @@ +actor { + public query func hello(who : Text) : async Text { + "Hello " # who # "!"; + }; + public query func hello2(who : Text) : async Text { + return ("Hello " # who # "!"); + } +} + +//CALL query hello "DIDL\x00\x01\x71\x05World" +//CALL query hello2 "DIDL\x00\x01\x71\x05World" diff --git a/test/run-stub/ic-calls.mo b/test/run-stub/ic-calls.mo new file mode 100644 index 00000000000..32d4a947f77 --- /dev/null +++ b/test/run-stub/ic-calls.mo @@ -0,0 +1,24 @@ +actor X { + + + public func A() : async () { + }; + + + public func B(x : Int) : async Int { + x + }; + + public func C(x : Int, y: Bool) : async (Int,Bool) { + (x,y); + }; + + public func test() : async () { + let () = await A(); + let 1 = await B(1); + let (1,true) = await C(1,true); + }; + +} +//CALL ingress test 0x4449444C0000 + diff --git a/test/run-stub/idl-any.mo b/test/run-stub/idl-any.mo new file mode 100644 index 00000000000..b2c5713be24 --- /dev/null +++ b/test/run-stub/idl-any.mo @@ -0,0 +1,39 @@ +// This tests checks that the IDL decoder properly +// zooms past the any argument and finds the beginning of the string +actor { + public func any(_ : Any, x : Text) : async () { + debugPrint ("ok: " # x); + }; +} + +// Primitive values: +//CALL ingress any 0x4449444C00027f7103466F6F +//CALL ingress any 0x4449444C00027e710103466F6F +//CALL ingress any 0x4449444C00027d718080800803466F6F +//CALL ingress any 0x4449444C00027c718080800803466F6F +//CALL ingress any 0x4449444C00027b71AB03466F6F +//CALL ingress any 0x4449444C00027a71ABCD03466F6F +//CALL ingress any 0x4449444C00027971DEADBEEF03466F6F +//CALL ingress any 0x4449444C00027871DEADBEEFCAFFEE6603466F6F +//CALL ingress any 0x4449444C00027771AB03466F6F +//CALL ingress any 0x4449444C00027671ABCD03466F6F +//CALL ingress any 0x4449444C00027571DEADBEEF03466F6F +//CALL ingress any 0x4449444C00027471DEADBEEFCAFFEE6603466F6F +//CALL ingress any 0x4449444C00027371DEADBEEF03466F6F +//CALL ingress any 0x4449444C00027271DEADBEEFCAFFEE6603466F6F +//CALL ingress any 0x4449444C0002717103466F6F03466F6F +//CALL ingress any 0x4449444C0002707103466F6F + +// Composite values: +//CALL ingress any 0x4449444C016e710200710003466F6F +//CALL ingress any 0x4449444C016e710200710103466F6F03466F6F +//CALL ingress any 0x4449444C016d710200710003466F6F +//CALL ingress any 0x4449444C016d710200710103466F6F03466F6F +//CALL ingress any 0x4449444C016d71020071020003466F6F03466F6F +//CALL ingress any 0x4449444C016c0002007103466F6F +//CALL ingress any 0x4449444C016c01800175020071DEADBEEF03466F6F +//CALL ingress any 0x4449444C016c02007180017502007101A0DEADBEEF03466F6F +//CALL ingress any 0x4449444C016b0180017502007100DEADBEEF03466F6F +//CALL ingress any 0x4449444C016b0200718001750200710001A003466F6F +//CALL ingress any 0x4449444C016b02007180017502007101DEADBEEF03466F6F +//CALL ingress any 0x4449444C016602ABCD0200710400DEADBEEF03466F6F diff --git a/test/run-stub/idl-bad.mo b/test/run-stub/idl-bad.mo new file mode 100644 index 00000000000..2b5b04be855 --- /dev/null +++ b/test/run-stub/idl-bad.mo @@ -0,0 +1,7 @@ +actor { + public query func foo() : async () { + }; +} + +//CALL query foo "NOTDIDL" + diff --git a/test/run-stub/idl-field-escape.mo b/test/run-stub/idl-field-escape.mo new file mode 100644 index 00000000000..f84ca1556ec --- /dev/null +++ b/test/run-stub/idl-field-escape.mo @@ -0,0 +1,27 @@ +// This test checks that the IDL encoder/decode implements +// the field escape logic +actor { + type R = { + _0_ : Int; + _1_ : Nat; + async_ : Text + }; + + public func out() : async R { + { _0_ = 0xFFFF; + _1_ = 0x1000; + async_ = "XXX" + } + }; + + public func foo1() : async {foo_ : ()} { { foo_ = () } }; + public func foo2() : async {foo : ()} { { foo = () } }; + + public func input(r : R) : async () { + }; +} + +//CALL ingress foo1 0x4449444C0000 +//CALL ingress foo2 0x4449444C0000 +//CALL ingress out 0x4449444C0000 +//CALL ingress input 0x4449444c016c03007c017dbcfef7b102710100ffff03802003585858 diff --git a/test/run-stub/idl-func.mo b/test/run-stub/idl-func.mo new file mode 100644 index 00000000000..592c306ddf1 --- /dev/null +++ b/test/run-stub/idl-func.mo @@ -0,0 +1,13 @@ +type Func = shared Int -> async Func; + +actor { + public query func fun() : async ?Func { + null + }; + public query func fun2(arg : ?Func) : async () { + }; +} + + +//CALL query fun 0x4449444C0000 +//CALL query fun2 0x4449444c026e016a017c0000010000 diff --git a/test/run-stub/idl-nary.mo b/test/run-stub/idl-nary.mo new file mode 100644 index 00000000000..25284781203 --- /dev/null +++ b/test/run-stub/idl-nary.mo @@ -0,0 +1,53 @@ +actor { + public func two(x:Text, y:Text) : async (Text, Text) { + (x, y) + }; + + public func three(x:Text, y:Text, z: Text) : async (Text, Text, Text) { + (x, y, z) + }; + + public func four(x:Text, y:Text, z: Text, w: Text) : async (Text, Text, Text, Text) { + (x, y, z, w) + }; + + public func mkRecord() : async ((Text, Text, Text, Text)) { + ("One", "Two", "Three", "Four") + }; + + public func unary1((x:Text, y:Text, z: Text, w: Text)) : async ((Text, Text, Text, Text)) { + (x, y, z, w) + }; + + public func unary2(xyzw : (Text, Text, Text, Text)) : async ((Text, Text, Text, Text)) { + xyzw + }; + + public func unary3(xyzw : (Text, Text, Text, Text)) : async ((Text, Text, Text, Text)) { + xyzw + }; + + type T = (Text, Text, Text, Text); + public func unary4(xyzw : (Text, Text, Text, Text)) : async T { + xyzw + } + + +} + +//CALL ingress two "DIDL\x00\x02\x71\x71\x03One\x03Two" +//CALL ingress three "DIDL\x00\x03\x71\x71\x71\x03One\x03Two\x05Three" +//CALL ingress four "DIDL\x00\x04\x71\x71\x71\x71\x03One\x03Two\x05Three\x04Four" +//CALL ingress mkRecord "DIDL\x00\x00" +//CALL ingress unary1 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 +//CALL ingress unary2 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 +//CALL ingress unary3 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 +//CALL ingress unary4 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 + + +// too few arguments +//CALL ingress three "DIDL\x00\x02\x71\x71\x03One\x03Two" +// extra bytes (bad) +//CALL ingress three "DIDL\x00\x03\x71\x71\x71\x03One\x03Two\x05ThreeEXTRABYTES" +// extra arguments (ok) +//CALL ingress four "DIDL\x00\x05\x71\x71\x71\x71\x71\x03One\x03Two\x05Three\x04Four\x04Five" diff --git a/test/run-stub/idl-nat-int.mo b/test/run-stub/idl-nat-int.mo new file mode 100644 index 00000000000..7c971b93ff7 --- /dev/null +++ b/test/run-stub/idl-nat-int.mo @@ -0,0 +1,18 @@ +actor { + public query func absolute(x:Int) : async Nat { + abs x + }; + public query func absolutes(xs:[Int]) : async [Nat] { + Array_tabulate(xs.len(), func (i:Int) : Nat = abs(xs[i])) + }; +} + +// with Nat +//CALL query absolute "DIDL\x00\x01\x7d\x2a" +// with Int +//CALL query absolute "DIDL\x00\x01\x7c\x56" + +// with Nats +//CALL query absolutes "DIDL\x01\x6d\x7d\x01\x00\x02\x2a\x19" +// with Ints +//CALL query absolutes "DIDL\x01\x6d\x7c\x01\x00\x02\x56\x19" diff --git a/test/run-stub/idl-option.mo b/test/run-stub/idl-option.mo new file mode 100644 index 00000000000..887644e7584 --- /dev/null +++ b/test/run-stub/idl-option.mo @@ -0,0 +1,14 @@ +// This test checks that the IDL decoder can +// do the subtyping from null to option +actor { + public func any(o : ?Text) : async () { + switch o { + case null debugPrint ("ok: null"); + case (?x) debugPrint ("ok: " # x); + } + }; +} + +//CALL ingress any 0x4449444C00017f +//CALL ingress any 0x4449444C016e71010000 +//CALL ingress any 0x4449444C016e7101000103466F6F diff --git a/test/run-stub/idl-pair.mo b/test/run-stub/idl-pair.mo new file mode 100644 index 00000000000..57a487bcd64 --- /dev/null +++ b/test/run-stub/idl-pair.mo @@ -0,0 +1,8 @@ +type Pair = (Int,Int); +actor { + public func len2(x:Text, y:Text) : async Pair { + (x.len(), y.len()) + } +} + +//CALL ingress len2 "DIDL\x00\x02\x71\x71\x02Hi\x05World" diff --git a/test/run-stub/idl-record.mo b/test/run-stub/idl-record.mo new file mode 100644 index 00000000000..576609b3aa0 --- /dev/null +++ b/test/run-stub/idl-record.mo @@ -0,0 +1,34 @@ +// This test checks that the IDL decoder can +// do the subtyping from received many-field record +// to a double-field one (field names are in hash order) +actor { + public func pair(o : (Text, Int)) : async () { + switch o { + case (content, num) debugPrint ("ok: " # debug_show num); + } + }; + public func record(o : {content: Text; value : Int}) : async () { + switch o { + case {content} debugPrint ("ok: " # content); + } + }; + public func record1(o : {value : Int; byte : Int8}) : async () { + switch o { + case {byte} debugPrint ("ok: " # debug_show byte); + } + }; + public func record2(o : {content: Text; value : Int}, follower : Int8) : async Int8 { + switch o { + case {content} { debugPrint ("ok: " # " " # content # " " # debug_show follower); follower }; + } + }; +} + +//CALL ingress pair 0x4449444C016C020071017C010004486579212A +//CALL ingress record 0x4449444C016C02b99adecb0171f1fee18d037C010004486579212A +// SKIPPED +// CALL ingress record1 0x4449444C016C0388be8c890477b99adecb0171f1fee18d037C010004486579212A19 +// needs to jump over redundant `content` field +//CALL ingress record1 0x4449444C016C03b99adecb0171f1fee18d037C88be8c890477010004486579212A19 +// needs to jump over redundant trailing `byte` field +//CALL ingress record2 0x4449444C016C03b99adecb0171f1fee18d037C88be8c89047702007704486579212A1819 diff --git a/test/run-stub/idl-tuple.mo b/test/run-stub/idl-tuple.mo new file mode 100644 index 00000000000..0f86f4a9a06 --- /dev/null +++ b/test/run-stub/idl-tuple.mo @@ -0,0 +1,17 @@ +actor { + // top-level tuple + public query func len2(x:Text, y:Text) : async (Int,Int) { + (x.len(), y.len()) + }; + // a pair embedded in top-level tuple + public query func len3((x:Text, i:Int32), y:Text) : async (Int,Int,Int) { + (x.len(), y.len(), int32ToInt i) + } +} + +//CALL query len2 "DIDL\x00\x02\x71\x71\x02Hi\x05World" +//CALL query len3 0x4449444c016c02007101750200710548656c6c6f0102030405576f726c64 +// testing redundant first tuple member (repeated hash with different type), currently ignored, it is although invalid IDL data +//CALL query len3 0x4449444c016c030071007601750200710548656c6c6fdead0102030405576f726c64 +// testing redundant third tuple member, gets ignored +//CALL query len3 0x4449444c016c030071017502760200710548656c6c6f01020304dead05576f726c64 diff --git a/test/run-stub/idl-unit.mo b/test/run-stub/idl-unit.mo new file mode 100644 index 00000000000..09e6f9b85ec --- /dev/null +++ b/test/run-stub/idl-unit.mo @@ -0,0 +1,7 @@ +actor { + public query func unit_id() : async () { + () + } +} + +//CALL query unit_id "DIDL\x00\x00" diff --git a/test/run-stub/idl-variant.mo b/test/run-stub/idl-variant.mo new file mode 100644 index 00000000000..594cf29f99f --- /dev/null +++ b/test/run-stub/idl-variant.mo @@ -0,0 +1,16 @@ +type Either = { #left: Word32; #right: Char; #fix: Either }; + +func to_left(e : Either) : Either + = switch e { + case (#right n) #left (charToWord32 n); + case (#fix t) #fix (to_left t); + case other other + }; + +actor { + public query func numify(t: Either) : async Either { + to_left t + } +} + +//CALL query numify 0x4449444c016b03d583b702008790c0bd0479dc9790cb0e790100000220000000 diff --git a/test/run-stub/idl-vector.mo b/test/run-stub/idl-vector.mo new file mode 100644 index 00000000000..48391f2a241 --- /dev/null +++ b/test/run-stub/idl-vector.mo @@ -0,0 +1,13 @@ +type Rose = [Rose]; +type MayRose = ?[MayRose]; + +func may(r : Rose) : MayRose = ?Array_tabulate(r.len(), func (i : Nat) = may(r[i])); + +actor { + public query func rose(r : Rose) : async MayRose { + may r + } +} + +// [[], [[], [[], [],], [], []], []] +//CALL query rose 0x4449444c016d00010003000400020000000000 diff --git a/test/run-stub/large-array.mo b/test/run-stub/large-array.mo new file mode 100644 index 00000000000..5a8b76c762b --- /dev/null +++ b/test/run-stub/large-array.mo @@ -0,0 +1,7 @@ +// Should allocate 1G +ignore(Array_init<()>(1024*1024*1024/4, ())); + +//SKIP run +//SKIP run-ir +//SKIP run-low +//SKIP ic-stub-run diff --git a/test/run-stub/multiple-actors.mo b/test/run-stub/multiple-actors.mo new file mode 100644 index 00000000000..33e4b920714 --- /dev/null +++ b/test/run-stub/multiple-actors.mo @@ -0,0 +1,7 @@ +actor a { }; + +actor b { }; + + + + diff --git a/test/run-drun/ok/counter.ic-stub-run.ok b/test/run-stub/ok/counter.ic-stub-run.ok similarity index 100% rename from test/run-drun/ok/counter.ic-stub-run.ok rename to test/run-stub/ok/counter.ic-stub-run.ok diff --git a/test/run-drun/ok/hello-world-return.ic-stub-run.ok b/test/run-stub/ok/hello-world-return.ic-stub-run.ok similarity index 100% rename from test/run-drun/ok/hello-world-return.ic-stub-run.ok rename to test/run-stub/ok/hello-world-return.ic-stub-run.ok diff --git a/test/run-stub/ok/ic-calls.comp.ok b/test/run-stub/ok/ic-calls.comp.ok new file mode 100644 index 00000000000..dec54dfc5ac --- /dev/null +++ b/test/run-stub/ok/ic-calls.comp.ok @@ -0,0 +1,9 @@ +ic-calls.mo:18.9-18.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +ic-calls.mo:19.9-19.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (1, false) or + (0 or -1 or _, _) diff --git a/test/run-stub/ok/ic-calls.ic-stub-run.ok b/test/run-stub/ok/ic-calls.ic-stub-run.ok new file mode 100644 index 00000000000..d73ca90a1ac --- /dev/null +++ b/test/run-stub/ok/ic-calls.ic-stub-run.ok @@ -0,0 +1,4 @@ +→ install +← completed +→ update test(0x4449444c0000) +← rejected (RC_CANISTER_ERROR): canister trapped: EvalTrapError :0.1 "canister trapped explicitly: cannot call anonymous shared function" diff --git a/test/run-stub/ok/ic-calls.run-ir.ok b/test/run-stub/ok/ic-calls.run-ir.ok new file mode 100644 index 00000000000..dec54dfc5ac --- /dev/null +++ b/test/run-stub/ok/ic-calls.run-ir.ok @@ -0,0 +1,9 @@ +ic-calls.mo:18.9-18.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +ic-calls.mo:19.9-19.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (1, false) or + (0 or -1 or _, _) diff --git a/test/run-stub/ok/ic-calls.run-low.ok b/test/run-stub/ok/ic-calls.run-low.ok new file mode 100644 index 00000000000..dec54dfc5ac --- /dev/null +++ b/test/run-stub/ok/ic-calls.run-low.ok @@ -0,0 +1,9 @@ +ic-calls.mo:18.9-18.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +ic-calls.mo:19.9-19.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (1, false) or + (0 or -1 or _, _) diff --git a/test/run-stub/ok/ic-calls.run.ok b/test/run-stub/ok/ic-calls.run.ok new file mode 100644 index 00000000000..dec54dfc5ac --- /dev/null +++ b/test/run-stub/ok/ic-calls.run.ok @@ -0,0 +1,9 @@ +ic-calls.mo:18.9-18.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +ic-calls.mo:19.9-19.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (1, false) or + (0 or -1 or _, _) diff --git a/test/run-stub/ok/ic-calls.tc.ok b/test/run-stub/ok/ic-calls.tc.ok new file mode 100644 index 00000000000..dec54dfc5ac --- /dev/null +++ b/test/run-stub/ok/ic-calls.tc.ok @@ -0,0 +1,9 @@ +ic-calls.mo:18.9-18.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +ic-calls.mo:19.9-19.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (1, false) or + (0 or -1 or _, _) diff --git a/test/run-drun/ok/idl-any.ic-stub-run.ok b/test/run-stub/ok/idl-any.ic-stub-run.ok similarity index 100% rename from test/run-drun/ok/idl-any.ic-stub-run.ok rename to test/run-stub/ok/idl-any.ic-stub-run.ok diff --git a/test/run-drun/ok/idl-bad.ic-stub-run.ok b/test/run-stub/ok/idl-bad.ic-stub-run.ok similarity index 100% rename from test/run-drun/ok/idl-bad.ic-stub-run.ok rename to test/run-stub/ok/idl-bad.ic-stub-run.ok diff --git a/test/run-drun/ok/idl-field-escape.ic-stub-run.ok b/test/run-stub/ok/idl-field-escape.ic-stub-run.ok similarity index 100% rename from test/run-drun/ok/idl-field-escape.ic-stub-run.ok rename to test/run-stub/ok/idl-field-escape.ic-stub-run.ok diff --git a/test/run-stub/ok/idl-func.ic-stub-run.ok b/test/run-stub/ok/idl-func.ic-stub-run.ok new file mode 100644 index 00000000000..b9b5b7e1146 --- /dev/null +++ b/test/run-stub/ok/idl-func.ic-stub-run.ok @@ -0,0 +1,6 @@ +→ install +← completed +→ query fun(0x4449444c0000) +← completed: 0x4449444c026e016a017c010100010000 +→ query fun2(0x4449444c026e016a017c0000010000) +← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-nary.ic-stub-run.ok b/test/run-stub/ok/idl-nary.ic-stub-run.ok similarity index 100% rename from test/run-drun/ok/idl-nary.ic-stub-run.ok rename to test/run-stub/ok/idl-nary.ic-stub-run.ok diff --git a/test/run-drun/ok/idl-nat-int.ic-stub-run.ok b/test/run-stub/ok/idl-nat-int.ic-stub-run.ok similarity index 100% rename from test/run-drun/ok/idl-nat-int.ic-stub-run.ok rename to test/run-stub/ok/idl-nat-int.ic-stub-run.ok diff --git a/test/run-drun/ok/idl-option.ic-stub-run.ok b/test/run-stub/ok/idl-option.ic-stub-run.ok similarity index 100% rename from test/run-drun/ok/idl-option.ic-stub-run.ok rename to test/run-stub/ok/idl-option.ic-stub-run.ok diff --git a/test/run-drun/ok/idl-pair.ic-stub-run.ok b/test/run-stub/ok/idl-pair.ic-stub-run.ok similarity index 100% rename from test/run-drun/ok/idl-pair.ic-stub-run.ok rename to test/run-stub/ok/idl-pair.ic-stub-run.ok diff --git a/test/run-drun/ok/idl-record.ic-stub-run.ok b/test/run-stub/ok/idl-record.ic-stub-run.ok similarity index 100% rename from test/run-drun/ok/idl-record.ic-stub-run.ok rename to test/run-stub/ok/idl-record.ic-stub-run.ok diff --git a/test/run-drun/ok/idl-tuple.ic-stub-run.ok b/test/run-stub/ok/idl-tuple.ic-stub-run.ok similarity index 100% rename from test/run-drun/ok/idl-tuple.ic-stub-run.ok rename to test/run-stub/ok/idl-tuple.ic-stub-run.ok diff --git a/test/run-drun/ok/idl-unit.ic-stub-run.ok b/test/run-stub/ok/idl-unit.ic-stub-run.ok similarity index 100% rename from test/run-drun/ok/idl-unit.ic-stub-run.ok rename to test/run-stub/ok/idl-unit.ic-stub-run.ok diff --git a/test/run-drun/ok/idl-variant.ic-stub-run.ok b/test/run-stub/ok/idl-variant.ic-stub-run.ok similarity index 100% rename from test/run-drun/ok/idl-variant.ic-stub-run.ok rename to test/run-stub/ok/idl-variant.ic-stub-run.ok diff --git a/test/run-drun/ok/idl-vector.ic-stub-run.ok b/test/run-stub/ok/idl-vector.ic-stub-run.ok similarity index 100% rename from test/run-drun/ok/idl-vector.ic-stub-run.ok rename to test/run-stub/ok/idl-vector.ic-stub-run.ok diff --git a/test/run-stub/ok/multiple-actors.comp.ok b/test/run-stub/ok/multiple-actors.comp.ok new file mode 100644 index 00000000000..839f6dcaeab --- /dev/null +++ b/test/run-stub/ok/multiple-actors.comp.ok @@ -0,0 +1,4 @@ +multiple-actors.mo:1.1-1.12: type error, multiple actors in program; there must be at most one actor declaration in a program + (This is a limitation of the current version and flag -stub-system-api.) +multiple-actors.mo:3.1-3.12: type error, multiple actors in program; there must be at most one actor declaration in a program + (This is a limitation of the current version and flag -stub-system-api.) diff --git a/test/run-stub/ok/multiple-actors.comp.ret.ok b/test/run-stub/ok/multiple-actors.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-stub/ok/multiple-actors.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-drun/ok/oom.ic-stub-run.ok b/test/run-stub/ok/oom.ic-stub-run.ok similarity index 100% rename from test/run-drun/ok/oom.ic-stub-run.ok rename to test/run-stub/ok/oom.ic-stub-run.ok diff --git a/test/run-drun/ok/print-from-init.ic-stub-run.ok b/test/run-stub/ok/print-from-init.ic-stub-run.ok similarity index 100% rename from test/run-drun/ok/print-from-init.ic-stub-run.ok rename to test/run-stub/ok/print-from-init.ic-stub-run.ok diff --git a/test/run-stub/ok/print-from-init.run-ir.ok b/test/run-stub/ok/print-from-init.run-ir.ok new file mode 100644 index 00000000000..2c5e67992ab --- /dev/null +++ b/test/run-stub/ok/print-from-init.run-ir.ok @@ -0,0 +1 @@ +Debug out diff --git a/test/run-stub/ok/print-from-init.run-low.ok b/test/run-stub/ok/print-from-init.run-low.ok new file mode 100644 index 00000000000..2c5e67992ab --- /dev/null +++ b/test/run-stub/ok/print-from-init.run-low.ok @@ -0,0 +1 @@ +Debug out diff --git a/test/run-stub/ok/print-from-init.run.ok b/test/run-stub/ok/print-from-init.run.ok new file mode 100644 index 00000000000..2c5e67992ab --- /dev/null +++ b/test/run-stub/ok/print-from-init.run.ok @@ -0,0 +1 @@ +Debug out diff --git a/test/run-drun/ok/query.ic-stub-run.ok b/test/run-stub/ok/query.ic-stub-run.ok similarity index 100% rename from test/run-drun/ok/query.ic-stub-run.ok rename to test/run-stub/ok/query.ic-stub-run.ok diff --git a/test/run-drun/ok/reject.ic-stub-run.ok b/test/run-stub/ok/reject.ic-stub-run.ok similarity index 100% rename from test/run-drun/ok/reject.ic-stub-run.ok rename to test/run-stub/ok/reject.ic-stub-run.ok diff --git a/test/run-drun/ok/reversi.ic-stub-run.ok b/test/run-stub/ok/reversi.ic-stub-run.ok similarity index 100% rename from test/run-drun/ok/reversi.ic-stub-run.ok rename to test/run-stub/ok/reversi.ic-stub-run.ok diff --git a/test/run-stub/ok/self-calls.comp.ok b/test/run-stub/ok/self-calls.comp.ok new file mode 100644 index 00000000000..0dc2420ebed --- /dev/null +++ b/test/run-stub/ok/self-calls.comp.ok @@ -0,0 +1,9 @@ +self-calls.mo:21.9-21.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +self-calls.mo:23.9-23.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (1, false) or + (0 or -1 or _, _) diff --git a/test/run-stub/ok/self-calls.ic-stub-run.ok b/test/run-stub/ok/self-calls.ic-stub-run.ok new file mode 100644 index 00000000000..4bdbaaf3e09 --- /dev/null +++ b/test/run-stub/ok/self-calls.ic-stub-run.ok @@ -0,0 +1,11 @@ +→ install +← completed +→ update test(0x4449444c0000) +test1 +A called +test2 +B called +test3 +C called +test4 +← completed: 0x4449444c0000 diff --git a/test/run-stub/ok/self-calls.run-ir.ok b/test/run-stub/ok/self-calls.run-ir.ok new file mode 100644 index 00000000000..0dc2420ebed --- /dev/null +++ b/test/run-stub/ok/self-calls.run-ir.ok @@ -0,0 +1,9 @@ +self-calls.mo:21.9-21.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +self-calls.mo:23.9-23.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (1, false) or + (0 or -1 or _, _) diff --git a/test/run-stub/ok/self-calls.run-low.ok b/test/run-stub/ok/self-calls.run-low.ok new file mode 100644 index 00000000000..0dc2420ebed --- /dev/null +++ b/test/run-stub/ok/self-calls.run-low.ok @@ -0,0 +1,9 @@ +self-calls.mo:21.9-21.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +self-calls.mo:23.9-23.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (1, false) or + (0 or -1 or _, _) diff --git a/test/run-stub/ok/self-calls.run.ok b/test/run-stub/ok/self-calls.run.ok new file mode 100644 index 00000000000..0dc2420ebed --- /dev/null +++ b/test/run-stub/ok/self-calls.run.ok @@ -0,0 +1,9 @@ +self-calls.mo:21.9-21.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +self-calls.mo:23.9-23.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (1, false) or + (0 or -1 or _, _) diff --git a/test/run-stub/ok/self-calls.tc.ok b/test/run-stub/ok/self-calls.tc.ok new file mode 100644 index 00000000000..0dc2420ebed --- /dev/null +++ b/test/run-stub/ok/self-calls.tc.ok @@ -0,0 +1,9 @@ +self-calls.mo:21.9-21.10: warning, this pattern consuming type + Int +does not cover value + 0 or -1 or _ +self-calls.mo:23.9-23.17: warning, this pattern consuming type + (Int, Bool) +does not cover value + (1, false) or + (0 or -1 or _, _) diff --git a/test/run-stub/ok/unsupported.comp.ok b/test/run-stub/ok/unsupported.comp.ok new file mode 100644 index 00000000000..e78cfc51c54 --- /dev/null +++ b/test/run-stub/ok/unsupported.comp.ok @@ -0,0 +1,20 @@ +unsupported.mo:19.19-19.21: type error, shared, async function must be called within an await expression + (This is a limitation of the current version and flag -stub-system-api.) +unsupported.mo:28.8-28.9: type error, argument to await must be a call expression + (This is a limitation of the current version and flag -stub-system-api.) +unsupported.mo:32.17-32.29: type error, unsupported async block + (This is a limitation of the current version and flag -stub-system-api.) +unsupported.mo:4.5-4.41: type error, a shared function cannot be private + (This is a limitation of the current version and flag -stub-system-api.) +unsupported.mo:38.26-38.29: type error, a shared function is only allowed as a public field of an actor + (This is a limitation of the current version and flag -stub-system-api.) +unsupported.mo:41.10-41.18: type error, unsupported async block + (This is a limitation of the current version and flag -stub-system-api.) +unsupported.mo:62.3-62.35: type error, actor classes are not supported; use an actor declaration instead + (This is a limitation of the current version and flag -stub-system-api.) +unsupported.mo:66.45-66.53: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program + (This is a limitation of the current version and flag -stub-system-api.) +unsupported.mo:70.37-70.45: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program + (This is a limitation of the current version and flag -stub-system-api.) +unsupported.mo:76.34-76.37: type error, freestanding async expression not yet supported + (This is a limitation of the current version and flag -stub-system-api.) diff --git a/test/run-stub/ok/unsupported.comp.ret.ok b/test/run-stub/ok/unsupported.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-stub/ok/unsupported.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-stub/oom.mo b/test/run-stub/oom.mo new file mode 100644 index 00000000000..f9a9b135f21 --- /dev/null +++ b/test/run-stub/oom.mo @@ -0,0 +1,13 @@ +actor Oom { + public func doloop() { + ignore(Array_init<()>(1200*1024/4, ())); + }; +} + +// on dvm: +// CALL doloop 0x4449444C0000 [] +// CALL doloop 0x4449444C0000 [] + +// on drun: +//CALL ingress doloop 0x4449444C0000 +//CALL ingress doloop 0x4449444C0000 diff --git a/test/run-stub/print-from-init.mo b/test/run-stub/print-from-init.mo new file mode 100644 index 00000000000..e65298d1a21 --- /dev/null +++ b/test/run-stub/print-from-init.mo @@ -0,0 +1,3 @@ +actor { + debugPrint("Debug out"); +} diff --git a/test/run-stub/query.mo b/test/run-stub/query.mo new file mode 100644 index 00000000000..3e494c1154e --- /dev/null +++ b/test/run-stub/query.mo @@ -0,0 +1,29 @@ +actor { + var c = 1; + public func inc() { + c += 1; + debugPrintNat c; debugPrint "\n"; + }; + public func printCounter () { + debugPrintNat c; debugPrint "\n"; + }; + public func get() : async Nat { + return c + }; + public query func read() : async Nat { + let tmp = c; + c += 1; + debugPrintNat c; debugPrint "\n"; + return tmp; + }; + +} +//CALL ingress inc 0x4449444C0000 +//CALL ingress inc 0x4449444C0000 +//CALL ingress inc 0x4449444C0000 +//CALL ingress printCounter 0x4449444C0000 +//CALL ingress get 0x4449444C0000 +//CALL query read 0x4449444C0000 +//CALL ingress printCounter 0x4449444C0000 +//CALL query read 0x4449444C0000 +//CALL ingress printCounter 0x4449444C0000 diff --git a/test/run-stub/reject.mo b/test/run-stub/reject.mo new file mode 100644 index 00000000000..a2a7e7bdff9 --- /dev/null +++ b/test/run-stub/reject.mo @@ -0,0 +1,29 @@ +actor { + public func reject1() : async () { + debugPrint "1"; + throw (error("Error")); + debugPrint "wrong"; + }; + + public func reject2() : async () { + debugPrint "1"; + try { throw (error("Error")) } + catch e {}; + debugPrint "ok"; + }; + + public func reject3() : async () { + debugPrint "1"; + try { throw (error("Error")) } + catch e { + debugPrint "ok"; + throw e; + }; + debugPrint "wrong"; + }; + +} + +//CALL ingress reject1 0x4449444C0000 +//CALL ingress reject2 0x4449444C0000 +//CALL ingress reject3 0x4449444C0000 diff --git a/test/run-stub/reversi.mo b/test/run-stub/reversi.mo new file mode 100644 index 00000000000..95f7038f341 --- /dev/null +++ b/test/run-stub/reversi.mo @@ -0,0 +1,274 @@ +actor { + // based on https://github.com/dfinity-lab/dapps/blob/75ead35363574f3697e37cd3a0592e51d3253a36/examples/reversi/src/reversi/main.mo + // with stdlib inlined and board size changed to 8 + + + // inline parts of stdlib + func unreachable() : None = { assert false ; loop { } }; + + func toText(x : Int) : Text { + if (x == 0) { + return "0"; + }; + + let isNegative = x < 0; + var int = if isNegative (-x) else x; + + var text = ""; + let base = 10; + + while (int > 0) { + let rem = int % base; + text := (switch (rem) { + case 0 "0"; + case 1 "1"; + case 2 "2"; + case 3 "3"; + case 4 "4"; + case 5 "5"; + case 6 "6"; + case 7 "7"; + case 8 "8"; + case 9 "9"; + case _ unreachable(); + }) # text; + int := int / base; + }; + + return if isNegative ("-" # text) else text; + }; + + + + // Color related type and constants + type Color = Nat; + let empty : Color = 0; + let white : Color = 1; + let black : Color = 2; + + // Dimension of the board + let N : Nat = 8; + + // Board is NxN array + type Board = [var Color]; + let Board : Board = Array_init(N * N, empty); + + // Which color should move next + var next_color : Color = white; + + // Reset the board to initial state + func init() { + // Reset to empty board + for (i in range(0, N * N - 1)) { + Board[i] := empty; + }; + + // initialize center 4 pieces + let M = N / 2; + Board[(M - 1) * N + M - 1] := white; + Board[ M * N + M ] := white; + Board[(M - 1) * N + M ] := black; + Board[ M * N + M - 1] := black; + + // White moves first + next_color := white; + }; + + // External interface to reset the board + public func reset() { + init() + }; + + public func dimension() : async Nat { + return N; + }; + + // Render the board into a string + func render(board: Board) : Text { + var str = ""; + for (i in range(0, N-1)) { + for (j in range(0, N-1)) { + if (board[i * N + j] == white) { + str := str # "O"; + } else if (board[i * N + j] == black) { + str := str # "*"; + } + else { + str := str # "."; + }; + }; + str := str # "\n"; + }; + + return str; + }; + + // External interface to render the board + public func board() : async Text { + return render(Board); + }; + + // Given a color, return its opponent color + func opponent(color: Color): Color { + return (3 - color); + }; + + // Check if a piece of the given color exists on the board using + // coordinate (i, j) and offset (p, q). + func exists(board: Board, color: Color, i: Nat, j: Nat, p:Int, q:Int) : Bool { + let s = i + p; + let t = j + q; + if (s < 0 or s >= N or t < 0 or t >= N) { + return false; + }; + return (board[abs (s * N + t)] == color); + }; + + // Check if a piece of the given color eventually exits on the board + // using coordinate (i, j) and direction (p, q), ignoring opponent colors + // in between. Return false if the given color is not found before reaching + // empty cell or board boundary. + func eventually(board: Board, color: Color, i: Nat, j: Nat, p:Int, q:Int) : Bool { + if (exists(board, opponent(color), i, j, p, q)) { + // the abs below is save because its precondition is already checked + return eventually(board, color, abs(i + p), abs(j + q), p, q); + } else { + return exists(board, color, i, j, p, q); + } + }; + + // Flip pieces of opponent color into the given color starting from + // coordinate (i, j) and along direction (p, q). + func flip(board: Board, color: Color, i: Nat, j: Nat, p:Int, q:Int) { + if (exists(board, opponent(color), i, j, p, q)) { + // the abs below is save because its precondition is already checked + let s = abs(i + p); + let t = abs(j + q); + board[s * N + t] := color; + flip(board, color, s, t, p, q); + } + }; + + // Calculate all validate positions for a given color by returning + // a board that has the cells colored. + func valid_moves(board: Board, color: Color) : Board { + let next : Board = Array_init(N * N, empty); + for (i in range(0, N-1)) { + for (j in range(0, N-1)) { + if (board[i * N + j] == empty) { + for (p in [-1, 0, 1].vals()) { + for (q in [-1, 0, 1].vals()) { + if (not(p == 0 and q == 0)) { + if (exists(board, opponent(color), i, j, p, q) and + eventually(board, color, i, j, p, q)) { + next[i * N + j] := color; + } + } + } + } + } + } + }; + return next; + }; + + // Set a piece on the board at a given position, and flip all + // affected opponent pieces accordingly. It requires that the + // given position is a valid move before this call. + func set_and_flip(board: Board, color: Color, i: Nat, j: Nat) { + board[i * N + j] := color; + for (p in [-1, 0, 1].vals()) { + for (q in [-1, 0, 1].vals()) { + if (not(p == 0 and q == 0)) { + if (exists(board, opponent(color), i, j, p, q) and + eventually(board, color, i, j, p, q)) { + flip(board, color, i, j, p, q); + } + } + } + } + }; + + // Check if the given board is empty. + func is_empty(board: Board) : Bool { + for (c in board.vals()) { + if (c != empty){ + return false; + } + }; + return true; + }; + + + // Return the white and black counts. + func score(board: Board) : (Nat, Nat) { + var wc = 0; + var bc = 0; + for (c in board.vals()) { + if (c == white) { + wc += 1; + } + else if (c == black) { + bc += 1; + } + }; + return (wc, bc); + }; + + // External interface that places a piece of given color at a coordinate. + // It returns "OK" when the move is valid. + public func place(color_: Int, row_: Int, col_: Int) : async Text { + // The casting is necessary because dfx has yet to support Nat on commandline + let color : Color = abs(color_); + let row : Nat = abs(row_); + let col : Nat = abs(col_); + + // Check input validity + if (row >= N or col >= N) { + return "Invalid coordinate"; + }; + if (not (color == 1 or color == 2)) { + return "Invalid piece color, must be either 1 or 2"; + }; + + var possible = valid_moves(Board, next_color); + + // If no move is possible, either pass or end game. + if (is_empty(possible)) { + next_color := opponent(next_color); + possible := valid_moves(Board, next_color); + // If no possible move again, end game + if (is_empty(possible)) { + let (wc, bc) = score(Board); + return ("End Game! Whites = " # toText(wc) # ", Blacks = " # toText(bc)) + } + else { + return "PASS" + } + }; + + if (next_color != color) { + return "Wrong color for this move"; + }; + + if (possible[row * N + col] != empty) { + set_and_flip(Board, color, row, col); + next_color := opponent(color); + return "OK"; + } else { + return "Illegal move"; + }; + + }; + + init(); +}; + +//CALL ingress reset 0x4449444C0000 +//CALL ingress board 0x4449444C0000 +//CALL ingress place 0x4449444C00037c7c7c010204 +//CALL ingress board 0x4449444C0000 +//CALL ingress place 0x4449444C00037c7c7c020203 +//CALL ingress board 0x4449444C0000 +//CALL ingress place 0x4449444C00037c7c7c010402 +//CALL ingress board 0x4449444C0000 diff --git a/test/run-stub/self-calls.mo b/test/run-stub/self-calls.mo new file mode 100644 index 00000000000..0f139b5c157 --- /dev/null +++ b/test/run-stub/self-calls.mo @@ -0,0 +1,27 @@ +actor X { + public func A() : async () { + debugPrint("A called"); + }; + + + public func B(x : Int) : async Int { + debugPrint("B called"); + x + }; + + public func C(x : Int, y: Bool) : async (Int,Bool) { + debugPrint("C called"); + (x,y); + }; + + public func test() : async () { + debugPrint("test1"); + let () = await X.A(); + debugPrint("test2"); + let 1 = await X.B(1); + debugPrint("test3"); + let (1,true) = await X.C(1,true); + debugPrint("test4"); + }; +} +//CALL ingress test 0x4449444C0000 diff --git a/test/run-stub/unsupported.mo b/test/run-stub/unsupported.mo new file mode 100644 index 00000000000..b31f825c639 --- /dev/null +++ b/test/run-stub/unsupported.mo @@ -0,0 +1,76 @@ +// top-level actor objects are supported +actor Counter { + + shared func bad_private_shared() { }; // not public + + public func badactorarg(a:actor{}) : async () {}; + + public func badfunctionarg(f:shared()->async ()) : async () {}; + + /* TODO + public func badoneway(){}; // unsupported oneway + */ + + public func ok() : async () {}; + + public func ok_explicit() : async () = async {}; + + public func bad_call() : async () { + ignore (ok()); // unsupported intercanister messaging + }; + + public func bad_await_call() : async () { + await (ok()); // unsupported intercanister messaging + }; + + public func bad_await() : async () { + let t : async () = loop {}; + await t; // unsupported general await + }; + + public func badasync() : async () { + let a = async { 1; }; // unsupported async + }; + +} +; + +shared func bad_shared() { }; // not actor enclosed + +func local_spawn() { + ignore(async ()); // not yet supported +}; + +{ + // shared function types aren't sharable + type illformed_1 = shared (shared () -> ()) -> async (); +}; + +{ + // actors aren't shareable + type illformed_2 = shared (actor {}) -> async (); +}; + +/* TODO +{ + // oneway functions aren't supported + type illformed_3 = shared () -> (); +}; +*/ + +{ + actor class BadActorClass () { }; // no actor classes +}; + +{ + let bad_non_top_actor : actor {} = if true actor {} else actor {}; +}; + +{ + let bad_nested_actor = { let _ = actor {}; ()}; +}; + + +actor BadSecondActor { }; + +func implicit_async() : async () { }; // async functions not supported From 2ef440e46b27c3934716263c7084c0848720aeba Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 14 Nov 2019 19:24:05 +0100 Subject: [PATCH 0584/1176] Recover proper reporting of unsupported features in stub mode --- src/mo_types/type.ml | 8 +++--- test/run-stub/ok/idl-func.comp.ok | 8 ++++++ test/run-stub/ok/idl-func.comp.ret.ok | 1 + test/run-stub/ok/idl-func.ic-stub-run.ok | 6 ----- test/run-stub/ok/unsupported.comp.ok | 32 ++++++++++++++++++++++++ 5 files changed, 45 insertions(+), 10 deletions(-) create mode 100644 test/run-stub/ok/idl-func.comp.ok create mode 100644 test/run-stub/ok/idl-func.comp.ret.ok delete mode 100644 test/run-stub/ok/idl-func.ic-stub-run.ok diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index 1a277d0b5f1..65cfb4f3b93 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -571,9 +571,9 @@ let concrete t = in go t let shared t = - (* TBR: Hack to restrict sharing in ICMode *) + (* TBR: Hack to restrict sharing in Wasm and ICMode *) let allow_actor as allow_shared = - not (!Flags.compiled && !Flags.compile_mode = Flags.ICMode) in + not !Flags.compiled || !Flags.compile_mode = Flags.AncientMode in let seen = ref S.empty in let rec go t = S.mem t !seen || @@ -601,9 +601,9 @@ let shared t = (* Find the first unshared subexpression in a type *) let find_unshared t = - (* TBR: Hack to restrict sharing in ICMode *) + (* TBR: Hack to restrict sharing in Wasm and ICMode *) let allow_actor as allow_shared = - not (!Flags.compiled && !Flags.compile_mode = Flags.ICMode) in + not !Flags.compiled || !Flags.compile_mode = Flags.AncientMode in let seen = ref S.empty in let rec go t = if S.mem t !seen then None else diff --git a/test/run-stub/ok/idl-func.comp.ok b/test/run-stub/ok/idl-func.comp.ok new file mode 100644 index 00000000000..2ab3746d8ec --- /dev/null +++ b/test/run-stub/ok/idl-func.comp.ok @@ -0,0 +1,8 @@ +idl-func.mo:1.13-1.37: type error, shared function has non-shared return type + Func = shared Int -> async Func +type + Func = shared Int -> async Func +is or contains non-shared type + shared Int -> async Func +idl-func.mo:1.13-1.37: type error, shared function types are non-shared. + (This is a limitation of the current version and flag -stub-system-api.) diff --git a/test/run-stub/ok/idl-func.comp.ret.ok b/test/run-stub/ok/idl-func.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-stub/ok/idl-func.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-stub/ok/idl-func.ic-stub-run.ok b/test/run-stub/ok/idl-func.ic-stub-run.ok deleted file mode 100644 index b9b5b7e1146..00000000000 --- a/test/run-stub/ok/idl-func.ic-stub-run.ok +++ /dev/null @@ -1,6 +0,0 @@ -→ install -← completed -→ query fun(0x4449444c0000) -← completed: 0x4449444c026e016a017c010100010000 -→ query fun2(0x4449444c026e016a017c0000010000) -← completed: 0x4449444c0000 diff --git a/test/run-stub/ok/unsupported.comp.ok b/test/run-stub/ok/unsupported.comp.ok index e78cfc51c54..1eb7bdd6fba 100644 --- a/test/run-stub/ok/unsupported.comp.ok +++ b/test/run-stub/ok/unsupported.comp.ok @@ -1,3 +1,19 @@ +unsupported.mo:6.28-6.39: type error, shared function has non-shared parameter type + actor {} +type + actor {} +is or contains non-shared type + actor {} +unsupported.mo:6.28-6.39: type error, actor types are non-shared. + (This is a limitation of the current version and flag -stub-system-api.) +unsupported.mo:8.31-8.53: type error, shared function has non-shared parameter type + shared () -> async () +type + shared () -> async () +is or contains non-shared type + shared () -> async () +unsupported.mo:8.31-8.53: type error, shared function types are non-shared. + (This is a limitation of the current version and flag -stub-system-api.) unsupported.mo:19.19-19.21: type error, shared, async function must be called within an await expression (This is a limitation of the current version and flag -stub-system-api.) unsupported.mo:28.8-28.9: type error, argument to await must be a call expression @@ -10,6 +26,22 @@ unsupported.mo:38.26-38.29: type error, a shared function is only allowed as a p (This is a limitation of the current version and flag -stub-system-api.) unsupported.mo:41.10-41.18: type error, unsupported async block (This is a limitation of the current version and flag -stub-system-api.) +unsupported.mo:46.31-46.48: type error, shared function has non-shared parameter type + shared () -> () +type + shared () -> () +is or contains non-shared type + shared () -> () +unsupported.mo:46.31-46.48: type error, shared function types are non-shared. + (This is a limitation of the current version and flag -stub-system-api.) +unsupported.mo:51.31-51.41: type error, shared function has non-shared parameter type + actor {} +type + actor {} +is or contains non-shared type + actor {} +unsupported.mo:51.31-51.41: type error, actor types are non-shared. + (This is a limitation of the current version and flag -stub-system-api.) unsupported.mo:62.3-62.35: type error, actor classes are not supported; use an actor declaration instead (This is a limitation of the current version and flag -stub-system-api.) unsupported.mo:66.45-66.53: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program From 6897c966131766ecbecf82ba6562dfbf86017d8b Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 14 Nov 2019 19:34:50 +0100 Subject: [PATCH 0585/1176] Do not change semantics of allow_actor on WasmMode this is wrong, but fixing this should be a separate change (maybe with the introduction of a typecheck-only test directory) --- src/mo_types/type.ml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index 65cfb4f3b93..f6526fc6ed1 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -571,9 +571,11 @@ let concrete t = in go t let shared t = - (* TBR: Hack to restrict sharing in Wasm and ICMode *) + (* TBR: Hack to restrict sharing in ICMode *) let allow_actor as allow_shared = - not !Flags.compiled || !Flags.compile_mode = Flags.AncientMode in + not !Flags.compiled || + !Flags.compile_mode = Flags.WasmMode || + !Flags.compile_mode = Flags.AncientMode in let seen = ref S.empty in let rec go t = S.mem t !seen || @@ -601,9 +603,11 @@ let shared t = (* Find the first unshared subexpression in a type *) let find_unshared t = - (* TBR: Hack to restrict sharing in Wasm and ICMode *) + (* TBR: Hack to restrict sharing in ICMode *) let allow_actor as allow_shared = - not !Flags.compiled || !Flags.compile_mode = Flags.AncientMode in + not !Flags.compiled || + !Flags.compile_mode = Flags.WasmMode || + !Flags.compile_mode = Flags.AncientMode in let seen = ref S.empty in let rec go t = if S.mem t !seen then None else From 729a432b80d8031846247032a55500e5b147ee6f Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 14 Nov 2019 20:49:00 +0100 Subject: [PATCH 0586/1176] Make the IC stub export the specified `ic0` calls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit and adjust the backend accordingly. Also, the test case should actually store data in the callback’s environment. --- ic-stub/src/IC/Canister/Imp.hs | 39 +++---- src/codegen/compile.ml | 134 ++++++++++++++++++------- test/run-stub/ok/self-calls.comp.ok | 9 -- test/run-stub/ok/self-calls.run-ir.ok | 9 -- test/run-stub/ok/self-calls.run-low.ok | 9 -- test/run-stub/ok/self-calls.run.ok | 9 -- test/run-stub/ok/self-calls.tc.ok | 9 -- test/run-stub/self-calls.mo | 9 +- 8 files changed, 115 insertions(+), 112 deletions(-) delete mode 100644 test/run-stub/ok/self-calls.comp.ok delete mode 100644 test/run-stub/ok/self-calls.run-ir.ok delete mode 100644 test/run-stub/ok/self-calls.run-low.ok delete mode 100644 test/run-stub/ok/self-calls.run.ok delete mode 100644 test/run-stub/ok/self-calls.tc.ok diff --git a/ic-stub/src/IC/Canister/Imp.hs b/ic-stub/src/IC/Canister/Imp.hs index 2bae97fc5ac..fac1e226a0f 100644 --- a/ic-stub/src/IC/Canister/Imp.hs +++ b/ic-stub/src/IC/Canister/Imp.hs @@ -112,23 +112,17 @@ putBytes (pref, _esref) bytes = systemAPI :: forall s. ESRef s -> Imports s systemAPI esref = - [ (,) "ic" - [ (,,,) "trap" [i32, i32] [] explicit_trap - ] - , (,) "msg" - [ (,,,) "reject" [i64, i32, i32] [] $ with_nonce msg_reject - , (,,,) "reply" [i64, i32, i32] [] $ with_nonce msg_reply - , unimplemented "error_code" [i64] [i32] - , (,,,) "arg_data_copy" [i64, i32, i32, i32] [] $ with_nonce arg_data_copy - , (,,,) "arg_data_size" [i64] [i32] $ with_nonce arg_data_size - ] - , (,) "debug" - [ (,,,) "print" [i32, i32] [] debug_print - ] - , (,) "ic0" + [ (,) "ic0" [ (,,,) "call_simple" (replicate 10 i32) [i32] call_simple - , (,,,) "canister_self_len" [] [i32] canister_self_len , (,,,) "canister_self_copy" (replicate 3 i32) [] canister_self_copy + , (,,,) "canister_self_len" [] [i32] canister_self_len + , (,,,) "debug_print" [i32, i32] [] debug_print + , (,,,) "msg_arg_data_copy" [i32, i32, i32] [] arg_data_copy + , (,,,) "msg_arg_data_size" [] [i32] arg_data_size + , (,,,) "msg_reject" [i32, i32] [] msg_reject + , (,,,) "msg_reply" [i32, i32] [] msg_reply + , (,,,) "trap" [i32, i32] [] explicit_trap + , unimplemented "msg_error_code" [] [i32] ] ] where @@ -138,11 +132,6 @@ systemAPI esref = \_ -> throwError $ "unimplemented: " ++ name i32 = I32Type - i64 = I64Type - - with_nonce :: ([Value] -> HostFunc s) -> ([Value] -> HostFunc s) - with_nonce f (I64 _nonce : args) = f args - with_nonce _ _ = fail "with_nonce: missing or wrongly typed nonce argument" copy_to_canister :: String -> Int32 -> Int32 -> Int32 -> Blob -> HostM s () copy_to_canister name dst offset len blob = do @@ -201,7 +190,7 @@ systemAPI esref = arg_data_size _ = fail "arg_data_size: invalid argument" arg_data_copy :: [Value] -> HostFunc s - arg_data_copy [I32 dst, I32 len, I32 offset] = do + arg_data_copy [I32 dst, I32 offset, I32 len] = do blob <- getsES esref (param_dat . params) >>= maybe (throwError "arg_data_size: No argument") return copy_to_canister "arg_data_copy" dst offset len blob @@ -272,7 +261,7 @@ rawInitializeMethod esref wasm_mod cid caller dat = do -- invoke canister_init when ("canister_init" `elem` exportedFunctions wasm_mod) $ void $ withES esref es $ - invokeExport inst "canister_init" [I64 0] + invokeExport inst "canister_init" [] -- TODO: Check no calls are made return (esref, cid, inst) @@ -291,7 +280,7 @@ rawQueryMethod (esref, cid, inst) method caller dat = do } } result <- runExceptT $ withES esref es $ - invokeExport inst ("canister_query " ++ method) [I64 0] + invokeExport inst ("canister_query " ++ method) [] -- TODO: Check no calls are made case result of @@ -312,7 +301,7 @@ rawUpdateMethod (esref, cid, inst) method caller dat = do } result <- runExceptT $ withES esref es $ - invokeExport inst ("canister_update " ++ method) [I64 0] + invokeExport inst ("canister_update " ++ method) [] case result of Left err -> return $ Trap err Right (_, es') -> return $ Return (calls es', response es') @@ -332,7 +321,7 @@ rawCallbackMethod (esref, cid, inst) callback caller res = do Reject {} -> reject_callback callback result <- runExceptT $ withES esref es $ - invokeTable inst fun_idx [I64 0, I32 env] + invokeTable inst fun_idx [I32 env] case result of Left err -> return $ Trap err Right (_, es') -> return $ Return (calls es', response es') diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index a09ec923d3e..bc19b0f0515 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -686,9 +686,12 @@ module RTS = struct E.call_import env "data" "externalize" ^^ E.call_import env "test" "print" ^^ G.i Unreachable - | Flags.ICMode | Flags.StubMode -> + | Flags.ICMode -> E.call_import env "ic" "trap" ^^ G.i Unreachable + | Flags.StubMode -> + E.call_import env "ic0" "trap" ^^ + G.i Unreachable | Flags.WasmMode -> G.i Unreachable ) ) in @@ -3038,15 +3041,22 @@ end (* Tuple *) module Dfinity = struct (* Dfinity-specific stuff: System imports, databufs etc. *) - let set_api_nonce env = G.i (GlobalSet (nr (E.get_global env "api_nonce"))) - let get_api_nonce env = G.i (GlobalGet (nr (E.get_global env "api_nonce"))) + let set_api_nonce env = + assert (E.mode env = Flags.ICMode); + G.i (GlobalSet (nr (E.get_global env "api_nonce"))) + + let get_api_nonce env = + if E.mode env = Flags.ICMode + then G.i (GlobalGet (nr (E.get_global env "api_nonce"))) + else G.nop let set_reply_cont env = G.i (GlobalSet (nr (E.get_global env "reply_cont"))) let get_reply_cont env = G.i (GlobalGet (nr (E.get_global env "reply_cont"))) let register_globals env = (* current api_nonce *) - E.add_global64 env "api_nonce" Mutable 0L + if E.mode env = Flags.ICMode + then E.add_global64 env "api_nonce" Mutable 0L let system_imports env = match E.mode env with @@ -3060,16 +3070,16 @@ module Dfinity = struct E.add_func_import env "ic" "trap" [I32Type; I32Type] []; () | Flags.StubMode -> - E.add_func_import env "debug" "print" [I32Type; I32Type] []; - E.add_func_import env "msg" "arg_data_size" [I64Type] [I32Type]; - E.add_func_import env "msg" "arg_data_copy" [I64Type; I32Type; I32Type; I32Type] []; - E.add_func_import env "msg" "reply" [I64Type; I32Type; I32Type] []; - E.add_func_import env "msg" "reject" [I64Type; I32Type; I32Type] []; - E.add_func_import env "msg" "error_code" [I64Type] [I32Type]; - E.add_func_import env "ic" "trap" [I32Type; I32Type] []; - E.add_func_import env "ic0" "canister_self_len" [] [I32Type]; - E.add_func_import env "ic0" "canister_self_copy" [I32Type; I32Type; I32Type] []; E.add_func_import env "ic0" "call_simple" (Lib.List.make 10 I32Type) [I32Type]; + E.add_func_import env "ic0" "canister_self_copy" [I32Type; I32Type; I32Type] []; + E.add_func_import env "ic0" "canister_self_len" [] [I32Type]; + E.add_func_import env "ic0" "debug_print" [I32Type; I32Type] []; + E.add_func_import env "ic0" "msg_arg_data_copy" [I32Type; I32Type; I32Type] []; + E.add_func_import env "ic0" "msg_arg_data_size" [] [I32Type]; + E.add_func_import env "ic0" "msg_error_code" [] [I32Type]; + E.add_func_import env "ic0" "msg_reject" [I32Type; I32Type] []; + E.add_func_import env "ic0" "msg_reply" [I32Type; I32Type] []; + E.add_func_import env "ic0" "trap" [I32Type; I32Type] []; () | Flags.AncientMode -> E.add_func_import env "test" "print" [I32Type] []; @@ -3112,12 +3122,18 @@ module Dfinity = struct let prim_print env = match E.mode env with | Flags.WasmMode -> G.i Drop - | Flags.ICMode | Flags.StubMode -> + | Flags.ICMode -> Func.share_code1 env "print_text" ("str", I32Type) [] (fun env get_str -> get_str ^^ Blob.payload_ptr_unskewed ^^ get_str ^^ Heap.load_field (Blob.len_field) ^^ system_call env "debug" "print" ) + | Flags.StubMode -> + Func.share_code1 env "print_text" ("str", I32Type) [] (fun env get_str -> + get_str ^^ Blob.payload_ptr_unskewed ^^ + get_str ^^ Heap.load_field (Blob.len_field) ^^ + system_call env "ic0" "debug_print" + ) | Flags.AncientMode -> compile_databuf_of_text env ^^ system_call env "test" "print" @@ -3132,17 +3148,23 @@ module Dfinity = struct compile_static_print env "\n" let ic_trap env = + match E.mode env with + | Flags.ICMode -> system_call env "ic" "trap" + | Flags.StubMode -> system_call env "ic0" "trap" + | _ -> assert false + + let ic_trap_str env = Func.share_code1 env "ic_trap" ("str", I32Type) [] (fun env get_str -> get_str ^^ Blob.payload_ptr_unskewed ^^ get_str ^^ Heap.load_field (Blob.len_field) ^^ - system_call env "ic" "trap" + ic_trap env ) let trap_with env s = match E.mode env with | Flags.WasmMode -> G.i Unreachable | Flags.AncientMode -> compile_static_print env (s ^ "\n") ^^ G.i Unreachable - | Flags.ICMode | Flags.StubMode -> Blob.lit env s ^^ ic_trap env ^^ G.i Unreachable + | Flags.ICMode | Flags.StubMode -> Blob.lit env s ^^ ic_trap_str env ^^ G.i Unreachable let default_exports env = (* these exports seem to be wanted by the hypervisor/v8 *) @@ -3194,8 +3216,9 @@ module Dfinity = struct let export_start env start_fi = assert (E.mode env = Flags.ICMode || E.mode env = Flags.StubMode); + let args = if E.mode env = Flags.ICMode then ["api_nonce",I64Type] else [] in (* Create an empty message *) - let empty_f = Func.of_body env ["api_nonce",I64Type] [] (fun env1 -> + let empty_f = Func.of_body env args [] (fun env1 -> G.i (Call (nr start_fi)) ^^ (* Collect garbage *) G.i (Call (nr (E.built_in env1 "collect"))) @@ -3256,7 +3279,11 @@ module Dfinity = struct set_text ^^ get_text ^^ Blob.payload_ptr_unskewed ^^ get_text ^^ Heap.load_field (Blob.len_field) ^^ - system_call env "msg" "reject" + begin match E.mode env with + | Flags.ICMode -> system_call env "msg" "reject" + | Flags.StubMode -> system_call env "ic0" "msg_reject" + | _ -> assert false + end | Flags.AncientMode -> trap_with env "Explicit reject on ancient system" | _ -> @@ -3264,8 +3291,13 @@ module Dfinity = struct let error_code env = SR.UnboxedWord32, - get_api_nonce env ^^ - system_call env "msg" "error_code" + match E.mode env with + | Flags.ICMode -> + get_api_nonce env ^^ + system_call env "msg" "error_code" + | Flags.StubMode -> + system_call env "ic" "msg_error_code" + | _ -> assert false let reply_with_data env = Func.share_code2 env "reply_with_data" (("start", I32Type), ("size", I32Type)) [] ( @@ -3273,7 +3305,10 @@ module Dfinity = struct get_api_nonce env ^^ get_data_start ^^ get_data_size ^^ - system_call env "msg" "reply" + match E.mode env with + | Flags.ICMode -> system_call env "msg" "reply" + | Flags.StubMode -> system_call env "ic0" "msg_reply" + | _ -> assert false ) end (* Dfinity *) @@ -4186,15 +4221,28 @@ module Serialization = struct ) let argument_data_size env = - Dfinity.get_api_nonce env ^^ - Dfinity.system_call env "msg" "arg_data_size" + match E.mode env with + | Flags.ICMode -> + Dfinity.get_api_nonce env ^^ + Dfinity.system_call env "msg" "arg_data_size" + | Flags.StubMode -> + Dfinity.system_call env "ic0" "msg_arg_data_size" + | _ -> assert false let argument_data_copy env get_dest get_length = - Dfinity.get_api_nonce env ^^ - get_dest ^^ - get_length ^^ - (compile_unboxed_const 0l) ^^ - Dfinity.system_call env "msg" "arg_data_copy" + match E.mode env with + | Flags.ICMode -> + Dfinity.get_api_nonce env ^^ + get_dest ^^ + get_length ^^ + (compile_unboxed_const 0l) ^^ + Dfinity.system_call env "msg" "arg_data_copy" + | Flags.StubMode -> + get_dest ^^ + (compile_unboxed_const 0l) ^^ + get_length ^^ + Dfinity.system_call env "ic0" "msg_arg_data_copy" + | _ -> assert false let serialize env ts : G.t = let ts_name = String.concat "," (List.map typ_id ts) in @@ -5075,11 +5123,23 @@ module FuncDec = struct mk_body env ae1 ^^ message_cleanup env sort )) - | (Flags.ICMode | Flags.StubMode), _ -> + | Flags.ICMode, _ -> let ae0 = VarEnv.mk_fun_ae outer_ae in Func.of_body outer_env ["api_nonce", I64Type] [] (fun env -> G.with_region at ( G.i (LocalGet (nr 0l)) ^^ Dfinity.set_api_nonce env ^^ + (* Deserialize argument and add params to the environment *) + let arg_names = List.map (fun a -> a.it) args in + let arg_tys = List.map (fun a -> a.note) args in + let (ae1, setters) = VarEnv.add_argument_locals env ae0 arg_names in + Serialization.deserialize env arg_tys ^^ + G.concat (List.rev setters) ^^ + mk_body env ae1 ^^ + message_cleanup env sort + )) + | Flags.StubMode, _ -> + let ae0 = VarEnv.mk_fun_ae outer_ae in + Func.of_body outer_env [] [] (fun env -> G.with_region at ( (* Deserialize argument and add params to the environment *) let arg_names = List.map (fun a -> a.it) args in let arg_tys = List.map (fun a -> a.note) args in @@ -5238,14 +5298,12 @@ module FuncDec = struct takes care of the environment *) (* Need this function once per type, so we can share based on ts *) let closure_to_reply_callback env ts get_closure = - assert (E.mode env = Flags.ICMode || E.mode env = Flags.StubMode); + assert (E.mode env = Flags.StubMode); let name = "@callback<" ^ Serialization.typ_id (Type.Tup ts) ^ ">" in - Func.define_built_in env name ["api_nonce",I64Type; "env", I32Type] [] (fun env -> - G.i (LocalGet (nr 0l)) ^^ Dfinity.set_api_nonce env ^^ - + Func.define_built_in env name ["env", I32Type] [] (fun env -> (* Look up closure *) let (set_closure, get_closure) = new_local env "closure" in - G.i (LocalGet (nr 1l)) ^^ + G.i (LocalGet (nr 0l)) ^^ ClosureTable.recall_closure env ^^ (* At this point we can remove the closure *) set_closure ^^ get_closure ^^ @@ -5262,14 +5320,12 @@ module FuncDec = struct get_closure ^^ ClosureTable.remember_closure env let closure_to_reject_callback env get_closure = - assert (E.mode env = Flags.ICMode || E.mode env = Flags.StubMode); + assert (E.mode env = Flags.StubMode); let name = "@reject_callback" in - Func.define_built_in env name ["api_nonce",I64Type; "env", I32Type] [] (fun env -> - G.i (LocalGet (nr 0l)) ^^ Dfinity.set_api_nonce env ^^ - + Func.define_built_in env name ["env", I32Type] [] (fun env -> (* Look up closure *) let (set_closure, get_closure) = new_local env "closure" in - G.i (LocalGet (nr 1l)) ^^ + G.i (LocalGet (nr 0l)) ^^ ClosureTable.recall_closure env ^^ (* At this point we can remove the closure *) set_closure ^^ get_closure ^^ diff --git a/test/run-stub/ok/self-calls.comp.ok b/test/run-stub/ok/self-calls.comp.ok deleted file mode 100644 index 0dc2420ebed..00000000000 --- a/test/run-stub/ok/self-calls.comp.ok +++ /dev/null @@ -1,9 +0,0 @@ -self-calls.mo:21.9-21.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -self-calls.mo:23.9-23.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (1, false) or - (0 or -1 or _, _) diff --git a/test/run-stub/ok/self-calls.run-ir.ok b/test/run-stub/ok/self-calls.run-ir.ok deleted file mode 100644 index 0dc2420ebed..00000000000 --- a/test/run-stub/ok/self-calls.run-ir.ok +++ /dev/null @@ -1,9 +0,0 @@ -self-calls.mo:21.9-21.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -self-calls.mo:23.9-23.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (1, false) or - (0 or -1 or _, _) diff --git a/test/run-stub/ok/self-calls.run-low.ok b/test/run-stub/ok/self-calls.run-low.ok deleted file mode 100644 index 0dc2420ebed..00000000000 --- a/test/run-stub/ok/self-calls.run-low.ok +++ /dev/null @@ -1,9 +0,0 @@ -self-calls.mo:21.9-21.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -self-calls.mo:23.9-23.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (1, false) or - (0 or -1 or _, _) diff --git a/test/run-stub/ok/self-calls.run.ok b/test/run-stub/ok/self-calls.run.ok deleted file mode 100644 index 0dc2420ebed..00000000000 --- a/test/run-stub/ok/self-calls.run.ok +++ /dev/null @@ -1,9 +0,0 @@ -self-calls.mo:21.9-21.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -self-calls.mo:23.9-23.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (1, false) or - (0 or -1 or _, _) diff --git a/test/run-stub/ok/self-calls.tc.ok b/test/run-stub/ok/self-calls.tc.ok deleted file mode 100644 index 0dc2420ebed..00000000000 --- a/test/run-stub/ok/self-calls.tc.ok +++ /dev/null @@ -1,9 +0,0 @@ -self-calls.mo:21.9-21.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -self-calls.mo:23.9-23.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (1, false) or - (0 or -1 or _, _) diff --git a/test/run-stub/self-calls.mo b/test/run-stub/self-calls.mo index 0f139b5c157..0d1716a5587 100644 --- a/test/run-stub/self-calls.mo +++ b/test/run-stub/self-calls.mo @@ -16,12 +16,15 @@ actor X { public func test() : async () { debugPrint("test1"); - let () = await X.A(); + let x = await X.A(); debugPrint("test2"); - let 1 = await X.B(1); + let y = await X.B(1); debugPrint("test3"); - let (1,true) = await X.C(1,true); + let z = await X.C(2,true); debugPrint("test4"); + assert (y == 1); + assert (z.0 == 2); + assert (z.1); }; } //CALL ingress test 0x4449444C0000 From 470a80987c56dd3729a3bc1b7d8586fa6ea0d690 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 14 Nov 2019 20:52:57 +0100 Subject: [PATCH 0587/1176] Remove large-array.mo from run-stub not run anyways here --- test/run-stub/large-array.mo | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 test/run-stub/large-array.mo diff --git a/test/run-stub/large-array.mo b/test/run-stub/large-array.mo deleted file mode 100644 index 5a8b76c762b..00000000000 --- a/test/run-stub/large-array.mo +++ /dev/null @@ -1,7 +0,0 @@ -// Should allocate 1G -ignore(Array_init<()>(1024*1024*1024/4, ())); - -//SKIP run -//SKIP run-ir -//SKIP run-low -//SKIP ic-stub-run From 9cb44fc4dd673feb9289ea6ef753dd3c869d23a7 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 14 Nov 2019 20:55:09 +0100 Subject: [PATCH 0588/1176] ElemHeap only used on AncientMode put in some `assert` to more clearly signal which code we would be able to get rid of --- src/codegen/compile.ml | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index bc19b0f0515..7112a98675f 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -887,12 +887,13 @@ module ElemHeap = struct ElemRef). This way, the fake orthogonal persistence code can easily store all references an elembuf. - This could be done differently (e.g. traversing the heap and looking for tagged references), but - it predates the heap traversal code, and the whole thing goes away once we - target orthogonal persistence anyways. + This could be done differently (e.g. traversing the heap and looking for + tagged references), but it predates the heap traversal code, and the whole + thing goes away once we target orthogonal persistence anyways. *) let register_globals env = + assert (E.mode env = Flags.AncientMode); (* reference counter *) E.add_global32 env "refcounter" Mutable 0l let get_ref_ctr env = @@ -910,6 +911,7 @@ module ElemHeap = struct (* Assumes a reference on the stack, and replaces it with an index into the reference table *) let remember_reference env : G.t = + assert (E.mode env = Flags.AncientMode); Func.share_code1 env "remember_reference" ("ref", I32Type) [I32Type] (fun env get_ref -> (* Check table space *) get_ref_ctr env ^^ @@ -935,6 +937,7 @@ module ElemHeap = struct (* Assumes a index into the table on the stack, and replaces it with the reference *) let recall_reference env : G.t = + assert (E.mode env = Flags.AncientMode); Func.share_code1 env "recall_reference" ("ref_idx", I32Type) [I32Type] (fun env get_ref_idx -> get_ref_idx ^^ compile_mul_const Heap.word_size ^^ @@ -3230,6 +3233,7 @@ module Dfinity = struct }) let box_reference env = + assert (E.mode env = Flags.AncientMode); Func.share_code1 env "box_reference" ("ref", I32Type) [I32Type] (fun env get_ref -> Tagged.obj env Tagged.Reference [ get_ref ^^ @@ -3238,6 +3242,7 @@ module Dfinity = struct ) let unbox_reference env = + assert (E.mode env = Flags.AncientMode); Heap.load_field 1l ^^ ElemHeap.recall_reference env @@ -7230,7 +7235,7 @@ and actor_lit outer_env this ds fs at = if E.mode mod_env = Flags.AncientMode then OrthogonalPersistence.register_globals mod_env; Heap.register_globals mod_env; - ElemHeap.register_globals mod_env; + if E.mode mod_env = Flags.AncientMode then ElemHeap.register_globals mod_env; Stack.register_globals mod_env; Dfinity.register_globals mod_env; @@ -7377,7 +7382,7 @@ let compile mode module_name rts (prelude : Ir.prog) (progs : Ir.prog list) : Wa if E.mode env = Flags.AncientMode then OrthogonalPersistence.register_globals env; Heap.register_globals env; - ElemHeap.register_globals env; + if E.mode env = Flags.AncientMode then ElemHeap.register_globals env; Stack.register_globals env; Dfinity.register_globals env; From 7bfa71dc11c6eeb1558c479ab8608b0b4ab73e65 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 14 Nov 2019 21:06:12 +0100 Subject: [PATCH 0589/1176] In test-fail/, only run the typechecker MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit these are tests for certain type checker errors, so do not try to compile, so that we don’t have to find out which target this can compile on. --- test/fail/Makefile | 2 +- test/fail/ok/use-before-define5.comp.ok | 15 --------------- test/fail/ok/use-before-define5.wasm-run.ok | 1 - test/fail/ok/use-before-define5.wasm-run.ret.ok | 1 - test/run.sh | 11 +++++++++-- test/{fail => run}/char-high-surrogate-trap.mo | 0 test/{fail => run}/char-low-surrogate-trap.mo | 0 test/{fail => run}/char-trap.mo | 0 test/{fail => run}/issue36.mo | 0 .../ok/char-high-surrogate-trap.run-ir.ok | 0 .../ok/char-high-surrogate-trap.run-low.ok | 0 .../ok/char-high-surrogate-trap.run.ok | 0 .../ok/char-high-surrogate-trap.run.ret.ok | 0 .../ok/char-high-surrogate-trap.wasm-run.ok | 0 .../ok/char-high-surrogate-trap.wasm-run.ret.ok | 0 .../ok/char-low-surrogate-trap.run-ir.ok | 0 .../ok/char-low-surrogate-trap.run-low.ok | 0 .../ok/char-low-surrogate-trap.run.ok | 0 .../ok/char-low-surrogate-trap.run.ret.ok | 0 .../ok/char-low-surrogate-trap.wasm-run.ok | 0 .../ok/char-low-surrogate-trap.wasm-run.ret.ok | 0 test/{fail => run}/ok/char-trap.run-ir.ok | 0 test/{fail => run}/ok/char-trap.run-low.ok | 0 test/{fail => run}/ok/char-trap.run.ok | 0 test/{fail => run}/ok/char-trap.run.ret.ok | 0 test/{fail => run}/ok/char-trap.wasm-run.ok | 0 test/{fail => run}/ok/char-trap.wasm-run.ret.ok | 0 test/{fail => run}/ok/issue36.comp.ok | 0 test/{fail => run}/ok/issue36.wasm-run.ok | 0 test/{fail => run}/ok/issue36.wasm-run.ret.ok | 0 30 files changed, 10 insertions(+), 20 deletions(-) delete mode 100644 test/fail/ok/use-before-define5.comp.ok delete mode 100644 test/fail/ok/use-before-define5.wasm-run.ok delete mode 100644 test/fail/ok/use-before-define5.wasm-run.ret.ok rename test/{fail => run}/char-high-surrogate-trap.mo (100%) rename test/{fail => run}/char-low-surrogate-trap.mo (100%) rename test/{fail => run}/char-trap.mo (100%) rename test/{fail => run}/issue36.mo (100%) rename test/{fail => run}/ok/char-high-surrogate-trap.run-ir.ok (100%) rename test/{fail => run}/ok/char-high-surrogate-trap.run-low.ok (100%) rename test/{fail => run}/ok/char-high-surrogate-trap.run.ok (100%) rename test/{fail => run}/ok/char-high-surrogate-trap.run.ret.ok (100%) rename test/{fail => run}/ok/char-high-surrogate-trap.wasm-run.ok (100%) rename test/{fail => run}/ok/char-high-surrogate-trap.wasm-run.ret.ok (100%) rename test/{fail => run}/ok/char-low-surrogate-trap.run-ir.ok (100%) rename test/{fail => run}/ok/char-low-surrogate-trap.run-low.ok (100%) rename test/{fail => run}/ok/char-low-surrogate-trap.run.ok (100%) rename test/{fail => run}/ok/char-low-surrogate-trap.run.ret.ok (100%) rename test/{fail => run}/ok/char-low-surrogate-trap.wasm-run.ok (100%) rename test/{fail => run}/ok/char-low-surrogate-trap.wasm-run.ret.ok (100%) rename test/{fail => run}/ok/char-trap.run-ir.ok (100%) rename test/{fail => run}/ok/char-trap.run-low.ok (100%) rename test/{fail => run}/ok/char-trap.run.ok (100%) rename test/{fail => run}/ok/char-trap.run.ret.ok (100%) rename test/{fail => run}/ok/char-trap.wasm-run.ok (100%) rename test/{fail => run}/ok/char-trap.wasm-run.ret.ok (100%) rename test/{fail => run}/ok/issue36.comp.ok (100%) rename test/{fail => run}/ok/issue36.wasm-run.ok (100%) rename test/{fail => run}/ok/issue36.wasm-run.ret.ok (100%) diff --git a/test/fail/Makefile b/test/fail/Makefile index 733076dc3a2..e1a9fcb3e06 100644 --- a/test/fail/Makefile +++ b/test/fail/Makefile @@ -1,4 +1,4 @@ -RUNFLAGS = +RUNFLAGS = -t all: ../run.sh $(RUNFLAGS) *.mo diff --git a/test/fail/ok/use-before-define5.comp.ok b/test/fail/ok/use-before-define5.comp.ok deleted file mode 100644 index 328a44f1679..00000000000 --- a/test/fail/ok/use-before-define5.comp.ok +++ /dev/null @@ -1,15 +0,0 @@ -non-closed actor: (ActorE - a - (LetD - (VarP foo) - (FuncE - foo - Shared - Returns - () - (AssertE (PrimE (RelPrim Nat EqOp) (VarE x) (LitE (NatLit 1)))) - ) - ) - (foo foo) - actor {foo : shared () -> ()} -) diff --git a/test/fail/ok/use-before-define5.wasm-run.ok b/test/fail/ok/use-before-define5.wasm-run.ok deleted file mode 100644 index f1fd5a677e9..00000000000 --- a/test/fail/ok/use-before-define5.wasm-run.ok +++ /dev/null @@ -1 +0,0 @@ -_out/use-before-define5.wasm:0x___: runtime trap: unreachable executed diff --git a/test/fail/ok/use-before-define5.wasm-run.ret.ok b/test/fail/ok/use-before-define5.wasm-run.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/fail/ok/use-before-define5.wasm-run.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run.sh b/test/run.sh index 0509d937bf1..1edc48b3e74 100755 --- a/test/run.sh +++ b/test/run.sh @@ -9,6 +9,8 @@ # -a: Update the files in ok/ # -1: Use Ancient API # -2: Use IC API +# -3: Use Stub API +# -t: Only typecheck # -s: Be silent in sunny-day execution # -i: Only check mo to idl generation # -r: Activate release mode (eliminate `debug` blocks) @@ -32,9 +34,11 @@ WASM=${WASM:-wasm} DVM_WRAPPER=$(realpath $(dirname $0)/dvm.sh) DRUN_WRAPPER=$(realpath $(dirname $0)/drun-wrapper.sh) IC_STUB_RUN=${IC_STUB_RUN:-ic-stub-run} +SKIP_RUNNING=${SKIP_RUNNING:-no} +ONLY_TYPECHECK=no ECHO=echo -while getopts "a123sir" o; do +while getopts "a123stir" o; do case "${o}" in a) ACCEPT=yes @@ -51,6 +55,9 @@ while getopts "a123sir" o; do s) ECHO=true ;; + t) + ONLY_TYPECHECK=true + ;; i) IDL=yes ;; @@ -166,7 +173,7 @@ do run tc $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS --check $base.mo tc_succeeded=$? - if [ "$tc_succeeded" -eq 0 ] + if [ "$tc_succeeded" -eq 0 -a "$ONLY_TYPECHECK" = "no" ] then if [ $IDL = 'yes' ] then diff --git a/test/fail/char-high-surrogate-trap.mo b/test/run/char-high-surrogate-trap.mo similarity index 100% rename from test/fail/char-high-surrogate-trap.mo rename to test/run/char-high-surrogate-trap.mo diff --git a/test/fail/char-low-surrogate-trap.mo b/test/run/char-low-surrogate-trap.mo similarity index 100% rename from test/fail/char-low-surrogate-trap.mo rename to test/run/char-low-surrogate-trap.mo diff --git a/test/fail/char-trap.mo b/test/run/char-trap.mo similarity index 100% rename from test/fail/char-trap.mo rename to test/run/char-trap.mo diff --git a/test/fail/issue36.mo b/test/run/issue36.mo similarity index 100% rename from test/fail/issue36.mo rename to test/run/issue36.mo diff --git a/test/fail/ok/char-high-surrogate-trap.run-ir.ok b/test/run/ok/char-high-surrogate-trap.run-ir.ok similarity index 100% rename from test/fail/ok/char-high-surrogate-trap.run-ir.ok rename to test/run/ok/char-high-surrogate-trap.run-ir.ok diff --git a/test/fail/ok/char-high-surrogate-trap.run-low.ok b/test/run/ok/char-high-surrogate-trap.run-low.ok similarity index 100% rename from test/fail/ok/char-high-surrogate-trap.run-low.ok rename to test/run/ok/char-high-surrogate-trap.run-low.ok diff --git a/test/fail/ok/char-high-surrogate-trap.run.ok b/test/run/ok/char-high-surrogate-trap.run.ok similarity index 100% rename from test/fail/ok/char-high-surrogate-trap.run.ok rename to test/run/ok/char-high-surrogate-trap.run.ok diff --git a/test/fail/ok/char-high-surrogate-trap.run.ret.ok b/test/run/ok/char-high-surrogate-trap.run.ret.ok similarity index 100% rename from test/fail/ok/char-high-surrogate-trap.run.ret.ok rename to test/run/ok/char-high-surrogate-trap.run.ret.ok diff --git a/test/fail/ok/char-high-surrogate-trap.wasm-run.ok b/test/run/ok/char-high-surrogate-trap.wasm-run.ok similarity index 100% rename from test/fail/ok/char-high-surrogate-trap.wasm-run.ok rename to test/run/ok/char-high-surrogate-trap.wasm-run.ok diff --git a/test/fail/ok/char-high-surrogate-trap.wasm-run.ret.ok b/test/run/ok/char-high-surrogate-trap.wasm-run.ret.ok similarity index 100% rename from test/fail/ok/char-high-surrogate-trap.wasm-run.ret.ok rename to test/run/ok/char-high-surrogate-trap.wasm-run.ret.ok diff --git a/test/fail/ok/char-low-surrogate-trap.run-ir.ok b/test/run/ok/char-low-surrogate-trap.run-ir.ok similarity index 100% rename from test/fail/ok/char-low-surrogate-trap.run-ir.ok rename to test/run/ok/char-low-surrogate-trap.run-ir.ok diff --git a/test/fail/ok/char-low-surrogate-trap.run-low.ok b/test/run/ok/char-low-surrogate-trap.run-low.ok similarity index 100% rename from test/fail/ok/char-low-surrogate-trap.run-low.ok rename to test/run/ok/char-low-surrogate-trap.run-low.ok diff --git a/test/fail/ok/char-low-surrogate-trap.run.ok b/test/run/ok/char-low-surrogate-trap.run.ok similarity index 100% rename from test/fail/ok/char-low-surrogate-trap.run.ok rename to test/run/ok/char-low-surrogate-trap.run.ok diff --git a/test/fail/ok/char-low-surrogate-trap.run.ret.ok b/test/run/ok/char-low-surrogate-trap.run.ret.ok similarity index 100% rename from test/fail/ok/char-low-surrogate-trap.run.ret.ok rename to test/run/ok/char-low-surrogate-trap.run.ret.ok diff --git a/test/fail/ok/char-low-surrogate-trap.wasm-run.ok b/test/run/ok/char-low-surrogate-trap.wasm-run.ok similarity index 100% rename from test/fail/ok/char-low-surrogate-trap.wasm-run.ok rename to test/run/ok/char-low-surrogate-trap.wasm-run.ok diff --git a/test/fail/ok/char-low-surrogate-trap.wasm-run.ret.ok b/test/run/ok/char-low-surrogate-trap.wasm-run.ret.ok similarity index 100% rename from test/fail/ok/char-low-surrogate-trap.wasm-run.ret.ok rename to test/run/ok/char-low-surrogate-trap.wasm-run.ret.ok diff --git a/test/fail/ok/char-trap.run-ir.ok b/test/run/ok/char-trap.run-ir.ok similarity index 100% rename from test/fail/ok/char-trap.run-ir.ok rename to test/run/ok/char-trap.run-ir.ok diff --git a/test/fail/ok/char-trap.run-low.ok b/test/run/ok/char-trap.run-low.ok similarity index 100% rename from test/fail/ok/char-trap.run-low.ok rename to test/run/ok/char-trap.run-low.ok diff --git a/test/fail/ok/char-trap.run.ok b/test/run/ok/char-trap.run.ok similarity index 100% rename from test/fail/ok/char-trap.run.ok rename to test/run/ok/char-trap.run.ok diff --git a/test/fail/ok/char-trap.run.ret.ok b/test/run/ok/char-trap.run.ret.ok similarity index 100% rename from test/fail/ok/char-trap.run.ret.ok rename to test/run/ok/char-trap.run.ret.ok diff --git a/test/fail/ok/char-trap.wasm-run.ok b/test/run/ok/char-trap.wasm-run.ok similarity index 100% rename from test/fail/ok/char-trap.wasm-run.ok rename to test/run/ok/char-trap.wasm-run.ok diff --git a/test/fail/ok/char-trap.wasm-run.ret.ok b/test/run/ok/char-trap.wasm-run.ret.ok similarity index 100% rename from test/fail/ok/char-trap.wasm-run.ret.ok rename to test/run/ok/char-trap.wasm-run.ret.ok diff --git a/test/fail/ok/issue36.comp.ok b/test/run/ok/issue36.comp.ok similarity index 100% rename from test/fail/ok/issue36.comp.ok rename to test/run/ok/issue36.comp.ok diff --git a/test/fail/ok/issue36.wasm-run.ok b/test/run/ok/issue36.wasm-run.ok similarity index 100% rename from test/fail/ok/issue36.wasm-run.ok rename to test/run/ok/issue36.wasm-run.ok diff --git a/test/fail/ok/issue36.wasm-run.ret.ok b/test/run/ok/issue36.wasm-run.ret.ok similarity index 100% rename from test/fail/ok/issue36.wasm-run.ret.ok rename to test/run/ok/issue36.wasm-run.ret.ok From a0bb37f35623af78031c70adbc1c5513c4508911 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Thu, 14 Nov 2019 20:25:39 +0000 Subject: [PATCH 0590/1176] add implicit scope indices (but no t parameters --- src/mo_frontend/parser.mly | 7 ++++--- src/prelude/prelude.ml | 3 +++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/mo_frontend/parser.mly b/src/mo_frontend/parser.mly index 0c6d2e1daa5..c91009a5e36 100644 --- a/src/mo_frontend/parser.mly +++ b/src/mo_frontend/parser.mly @@ -89,8 +89,9 @@ let share_expfield (ef : exp_field) = then ef else {ef with it = {ef.it with dec = share_dec ef.it.dec}} -let scope_bind = [{var = "@" @@ no_region; bound = PrimT "Any" @! no_region} @=no_region] -let scope_typ = VarT "@" @! no_region +let scope_id = "@_" +let scope_bind = {var = scope_id @@ no_region; bound = PrimT "Any" @! no_region} @= no_region +let scope_typ = PathT ((IdH (scope_id @@ no_region)) @! no_region, []) @! no_region %} @@ -631,7 +632,7 @@ dec_nonvar : | (false, e) -> e (* body declared as EQ e *) | (true, e) -> (* body declared as immediate block *) match t with - | Some {it = AsyncT _; _} -> AsyncE(e) @? e.at + | Some {it = AsyncT _; _} -> AsyncE(scope_bind,e,scope_typ) @? e.at | _ -> e in let named, x = xf "func" $sloc in diff --git a/src/prelude/prelude.ml b/src/prelude/prelude.ml index 18d85330978..38ee7c0cad5 100644 --- a/src/prelude/prelude.ml +++ b/src/prelude/prelude.ml @@ -23,6 +23,9 @@ type Char = prim "Char"; type Text = prim "Text"; type Error = prim "Error"; +// top level scope +type @_ = Any; + type Iter = {next : () -> ?T_}; func abs(x : Int) : Nat { (prim "abs" : Int -> Nat) x }; From 30ca1cb3b768e76be37012e3130d56c9fd6f87f7 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 14 Nov 2019 21:48:57 +0100 Subject: [PATCH 0591/1176] Use the Haskell types of the System API --- ic-stub/ic-stub.cabal | 1 + ic-stub/src/IC/Canister/Imp.hs | 102 +++++++---------- ic-stub/src/IC/Wasm/Imports.hs | 204 +++++++++++++++++++++++++++++++++ ic-stub/src/IC/Wasm/Winter.hs | 5 +- 4 files changed, 252 insertions(+), 60 deletions(-) create mode 100644 ic-stub/src/IC/Wasm/Imports.hs diff --git a/ic-stub/ic-stub.cabal b/ic-stub/ic-stub.cabal index cda30427b5d..11db148afd0 100644 --- a/ic-stub/ic-stub.cabal +++ b/ic-stub/ic-stub.cabal @@ -17,6 +17,7 @@ executable ic-stub-run other-modules: IC.Canister.Imp other-modules: IC.Canister.Pure other-modules: IC.Wasm.Winter + other-modules: IC.Wasm.Imports other-modules: IC.DRun.Parse build-depends: base >=4.11 && <5 build-depends: optparse-applicative diff --git a/ic-stub/src/IC/Canister/Imp.hs b/ic-stub/src/IC/Canister/Imp.hs index fac1e226a0f..395824fd31b 100644 --- a/ic-stub/src/IC/Canister/Imp.hs +++ b/ic-stub/src/IC/Canister/Imp.hs @@ -1,7 +1,6 @@ {-# LANGUAGE RankNTypes #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE NamedFieldPuns #-} -{-# LANGUAGE TupleSections #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE FlexibleContexts #-} @@ -32,6 +31,7 @@ import Data.Int import IC.Types import IC.Wasm.Winter +import IC.Wasm.Imports data Params = Params { param_dat :: Maybe Blob @@ -109,19 +109,18 @@ putBytes (pref, _esref) bytes = True -> unsafeIOToPrim (BSC.putStrLn bytes) False -> return () - systemAPI :: forall s. ESRef s -> Imports s systemAPI esref = [ (,) "ic0" - [ (,,,) "call_simple" (replicate 10 i32) [i32] call_simple - , (,,,) "canister_self_copy" (replicate 3 i32) [] canister_self_copy - , (,,,) "canister_self_len" [] [i32] canister_self_len - , (,,,) "debug_print" [i32, i32] [] debug_print - , (,,,) "msg_arg_data_copy" [i32, i32, i32] [] arg_data_copy - , (,,,) "msg_arg_data_size" [] [i32] arg_data_size - , (,,,) "msg_reject" [i32, i32] [] msg_reject - , (,,,) "msg_reply" [i32, i32] [] msg_reply - , (,,,) "trap" [i32, i32] [] explicit_trap + [ toImport "call_simple" call_simple + , toImport "canister_self_copy" canister_self_copy + , toImport "canister_self_len" canister_self_len + , toImport "debug_print" debug_print + , toImport "msg_arg_data_copy" arg_data_copy + , toImport "msg_arg_data_size" arg_data_size + , toImport "msg_reject" msg_reject + , toImport "msg_reply" msg_reply + , toImport "trap" explicit_trap , unimplemented "msg_error_code" [] [i32] ] ] @@ -150,81 +149,67 @@ systemAPI esref = -- The system calls - -- (TODO: Give them proper Haskell types and write generic code that takes - -- apart the values) - - debug_print :: [Value] -> HostFunc s - debug_print [I32 src, I32 len] = do + debug_print :: (Int32, Int32) -> HostM s () + debug_print (src, len) = do -- TODO: This should be a non-trapping copy bytes <- copy_from_canister "debug_print" src len putBytes esref bytes - return [] - debug_print _ = fail "debug_print: invalid argument" - explicit_trap :: [Value] -> HostFunc s - explicit_trap [I32 src, I32 len] = do + explicit_trap :: (Int32, Int32) -> HostM s () + explicit_trap (src, len) = do -- TODO: This should be a non-trapping copy bytes <- copy_from_canister "ic.trap" src len let msg = BSU.toString bytes throwError $ "canister trapped explicitly: " ++ msg - explicit_trap _ = fail "explicit_trap: invalid argument" - canister_self_len :: [Value] -> HostFunc s - canister_self_len [] = do + canister_self_len :: () -> HostM s Int32 + canister_self_len () = do id <- getsES esref self_id - return [I32 (fromIntegral (BS.length (rawEntityId id)))] - canister_self_len _ = fail "arg_data_size: invalid argument" + return $ fromIntegral (BS.length (rawEntityId id)) - canister_self_copy :: [Value] -> HostFunc s - canister_self_copy [I32 dst, I32 offset, I32 len] = do + canister_self_copy :: (Int32, Int32, Int32) -> HostM s () + canister_self_copy (dst, offset, len) = do id <- getsES esref self_id copy_to_canister "canister_self_copy" dst offset len (rawEntityId id) - return [] - canister_self_copy _ = fail "arg_data_size: invalid argument" - arg_data_size :: [Value] -> HostFunc s - arg_data_size [] = do + arg_data_size :: () -> HostM s Int32 + arg_data_size () = do blob <- getsES esref (param_dat . params) >>= maybe (throwError "arg_data_size: No argument") return - return [I32 (fromIntegral (BS.length blob))] - arg_data_size _ = fail "arg_data_size: invalid argument" + return $ fromIntegral (BS.length blob) - arg_data_copy :: [Value] -> HostFunc s - arg_data_copy [I32 dst, I32 offset, I32 len] = do + arg_data_copy :: (Int32, Int32, Int32) -> HostM s () + arg_data_copy (dst, offset, len) = do blob <- getsES esref (param_dat . params) >>= maybe (throwError "arg_data_size: No argument") return copy_to_canister "arg_data_copy" dst offset len blob - return [] - arg_data_copy _ = fail "arg_data_copy: invalid argument" - msg_reply :: [Value] -> HostFunc s - msg_reply [I32 src, I32 len] = do + msg_reply :: (Int32, Int32) -> HostM s () + msg_reply (src, len) = do bytes <- copy_from_canister "debug_print" src len setResponse esref (Reply bytes) - return [] - msg_reply _ = fail "msg_reply: invalid argument" - msg_reject :: [Value] -> HostFunc s - msg_reject [I32 src, I32 len] = do + msg_reject :: (Int32, Int32) -> HostM s () + msg_reject (src, len) = do bytes <- copy_from_canister "debug_print" src len let msg = BSU.toString bytes modES esref (\es -> es { response = Just (Reject (RC_CANISTER_REJECT, msg)) }) - return [] - msg_reject _ = fail "msg_reply: invalid argument" - call_simple :: [Value] -> HostFunc s + call_simple :: + ( Int32, Int32, Int32, Int32, Int32 + , Int32, Int32, Int32, Int32, Int32) -> HostM s Int32 call_simple - [ I32 callee_src - , I32 callee_len - , I32 name_src - , I32 name_len - , I32 reply_fun - , I32 reply_env - , I32 reject_fun - , I32 reject_env - , I32 data_src - , I32 data_len - ] = do + ( callee_src + , callee_len + , name_src + , name_len + , reply_fun + , reply_env + , reject_fun + , reject_env + , data_src + , data_len + ) = do callee <- copy_from_canister "call_simple" callee_src callee_len method_name <- copy_from_canister "call_simple" name_src name_len arg <- copy_from_canister "call_simple" data_src data_len @@ -239,8 +224,7 @@ systemAPI esref = } } - return [I32 0] - call_simple _ = fail "call_simple: invalid argument" + return 0 type RawState s = (ESRef s, CanisterId, Instance s) diff --git a/ic-stub/src/IC/Wasm/Imports.hs b/ic-stub/src/IC/Wasm/Imports.hs new file mode 100644 index 00000000000..714053f1527 --- /dev/null +++ b/ic-stub/src/IC/Wasm/Imports.hs @@ -0,0 +1,204 @@ +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TypeApplications #-} +{-# LANGUAGE AllowAmbiguousTypes #-} +{-# LANGUAGE DefaultSignatures #-} + +module IC.Wasm.Imports where + +import Data.Int +import IC.Wasm.Winter +import Text.Printf +import Control.Monad.Except + + +class WasmArg a where + valueType :: ValueType + fromValue :: Value -> Either String a + toValue :: a -> Value + +class WasmArgs a where + stackType :: StackType + fromValues :: [Value] -> Either String a + toValues :: a -> [Value] + + default stackType :: WasmArg a => StackType + stackType = [valueType @a] + default fromValues :: WasmArg a => [Value] -> Either String a + fromValues [x] = fromValue x + fromValues xs = argError 1 xs + default toValues :: WasmArg a => a -> [Value] + toValues x = [toValue x] + +argError :: Int -> [a] -> Either String b +argError n xs = Left $ + printf "expected %d arguments, got %d arguments" n (length xs) + +instance WasmArg Int32 where + valueType = I32Type + fromValue (I32 i) = Right i + fromValue v = Left $ "expected i32, got " ++ show v + toValue = I32 +instance WasmArgs Int32 where + +instance WasmArgs () where + stackType = [] + fromValues [] = Right () + fromValues xs = argError 0 xs + toValues () = [] + +-- The formatting is a bit odd, but allows it easier to create new instances by copy and paste and adding lines +instance + ( WasmArg a1 + , WasmArg a2 + ) => WasmArgs + ( a1 + , a2 + ) where + stackType = + [ valueType @a1 + , valueType @a2 + ] + fromValues + [ x1 + , x2 + ] = (,) + <$> fromValue x1 + <*> fromValue x2 + fromValues xs = argError 2 xs + toValues + ( x1 + , x2 + ) = + [ toValue x1 + , toValue x2 + ] + +instance + ( WasmArg a1 + , WasmArg a2 + , WasmArg a3 + ) => WasmArgs + ( a1 + , a2 + , a3 + ) where + stackType = + [ valueType @a1 + , valueType @a2 + , valueType @a3 + ] + fromValues + [ x1 + , x2 + , x3 + ] = (,,) + <$> fromValue x1 + <*> fromValue x2 + <*> fromValue x3 + fromValues xs = argError 3 xs + toValues + ( x1 + , x2 + , x3 + ) = + [ toValue x1 + , toValue x2 + , toValue x3 + ] + +instance + ( WasmArg a1 + , WasmArg a2 + , WasmArg a3 + , WasmArg a4 + , WasmArg a5 + , WasmArg a6 + , WasmArg a7 + , WasmArg a8 + , WasmArg a9 + , WasmArg a10 + ) => WasmArgs + ( a1 + , a2 + , a3 + , a4 + , a5 + , a6 + , a7 + , a8 + , a9 + , a10 + ) where + stackType = + [ valueType @a1 + , valueType @a2 + , valueType @a3 + , valueType @a4 + , valueType @a5 + , valueType @a6 + , valueType @a7 + , valueType @a8 + , valueType @a9 + , valueType @a10 + ] + fromValues + [ x1 + , x2 + , x3 + , x4 + , x5 + , x6 + , x7 + , x8 + , x9 + , x10 + ] = (,,,,,,,,,) + <$> fromValue x1 + <*> fromValue x2 + <*> fromValue x3 + <*> fromValue x4 + <*> fromValue x5 + <*> fromValue x6 + <*> fromValue x7 + <*> fromValue x8 + <*> fromValue x9 + <*> fromValue x10 + fromValues xs = argError 10 xs + toValues + ( x1 + , x2 + , x3 + , x4 + , x5 + , x6 + , x7 + , x8 + , x9 + , x10 + ) = + [ toValue x1 + , toValue x2 + , toValue x3 + , toValue x4 + , toValue x5 + , toValue x6 + , toValue x7 + , toValue x8 + , toValue x9 + , toValue x10 + ] + + +toImport :: + forall a b s. + (WasmArgs a, WasmArgs b) => + String -> (a -> HostM s b) -> Import s +toImport name f = (name, stackType @a, stackType @b, f') + where + f' :: [Value] -> HostFunc s + f' xs = do + a <- withExceptT ((name ++ ": ") ++) $ + ExceptT $ return (fromValues xs) + b <- f a + return $ toValues b + diff --git a/ic-stub/src/IC/Wasm/Winter.hs b/ic-stub/src/IC/Wasm/Winter.hs index 45c88d42a3c..4704faa3150 100644 --- a/ic-stub/src/IC/Wasm/Winter.hs +++ b/ic-stub/src/IC/Wasm/Winter.hs @@ -9,6 +9,7 @@ module IC.Wasm.Winter ( Module , parseModule , exportedFunctions + , Import , Imports , HostM , HostFunc @@ -54,7 +55,9 @@ type HostM s = ExceptT String (ST s) type HostFunc s = HostM s [W.Value] -type Imports s = [(String, [(String, W.StackType, W.StackType, [W.Value] -> HostFunc s)])] +type Import s = (String, W.StackType, W.StackType, [W.Value] -> HostFunc s) + +type Imports s = [(String, [Import s])] type Module = W.Module Identity From 35b5294a1b2274de9846251be90e24376472de79 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 14 Nov 2019 22:00:13 +0100 Subject: [PATCH 0592/1176] More comments in ic-stub --- ic-stub/src/IC/Canister/Imp.hs | 55 +++++++++++++++++++++++++-------- ic-stub/src/IC/Canister/Pure.hs | 14 ++++----- ic-stub/src/IC/Stub.hs | 14 ++++----- 3 files changed, 56 insertions(+), 27 deletions(-) diff --git a/ic-stub/src/IC/Canister/Imp.hs b/ic-stub/src/IC/Canister/Imp.hs index 395824fd31b..9d744b2e782 100644 --- a/ic-stub/src/IC/Canister/Imp.hs +++ b/ic-stub/src/IC/Canister/Imp.hs @@ -9,7 +9,7 @@ The canister interface, presented imperatively (or impurely), i.e. without rollb -} module IC.Canister.Imp ( ESRef - , RawState + , ImpState , runESST , rawInitializeMethod , rawUpdateMethod @@ -33,6 +33,8 @@ import IC.Types import IC.Wasm.Winter import IC.Wasm.Imports +-- Parameters are the data that come from the caller + data Params = Params { param_dat :: Maybe Blob , param_caller :: Maybe EntityId @@ -40,10 +42,14 @@ data Params = Params , reject_message :: String } +-- The execution state is all information available to the +-- canister. Some of it is immutable (could be separated here) + data ExecutionState s = ExecutionState { inst :: Instance s , self_id :: CanisterId , params :: Params + -- now the mutable parts , response :: Maybe Response , calls :: [MethodCall] } @@ -58,6 +64,14 @@ initalExecutionState self_id inst = ExecutionState , calls = mempty } +-- Some bookkeeping to access the ExecutionState +-- +-- We “always” have the 'STRef', but only within 'withES' is it actually +-- present. +-- +-- Also: A flag to check whether we are running in silent mode or not +-- (a bit of a hack) + type ESRef s = (STRef s Bool, STRef s (Maybe (ExecutionState s))) newESRef :: ST s (ESRef s) @@ -66,7 +80,12 @@ newESRef = (,) <$> newSTRef True <*> newSTRef Nothing runESST :: (forall s. ESRef s -> ST s a) -> a runESST f = runST $ newESRef >>= f -withES :: PrimMonad m => ESRef (PrimState m) -> ExecutionState (PrimState m) -> m a -> m (a, ExecutionState (PrimState m)) +-- | runs a computation with the given initial execution state +-- and returns the final execution state with it. +withES :: PrimMonad m => + ESRef (PrimState m) -> + ExecutionState (PrimState m) -> + m a -> m (a, ExecutionState (PrimState m)) withES (_pref, esref) es f = do before <- stToPrim $ readSTRef esref unless (isNothing before) $ fail "withES with non-empty es" @@ -95,6 +114,7 @@ getsES (_, esref) f = lift (readSTRef esref) >>= \case modES :: ESRef s -> (ExecutionState s -> ExecutionState s) -> HostM s () modES (_, esref) f = lift $ modifySTRef esref (fmap f) + setResponse :: ESRef s -> Response -> HostM s () setResponse esref r = modES esref $ \es -> es { response = Just r } @@ -103,11 +123,9 @@ appendCall :: ESRef s -> MethodCall -> HostM s () appendCall esref c = modES esref $ \es -> es { calls = calls es ++ [c] } -putBytes :: PrimMonad m => ESRef (PrimState m) -> BS.ByteString -> m () -putBytes (pref, _esref) bytes = - stToPrim (readSTRef pref) >>= \case - True -> unsafeIOToPrim (BSC.putStrLn bytes) - False -> return () +-- The System API, with all imports + +-- The code is defined in the where clause to scope over the 'ESRef' systemAPI :: forall s. ESRef s -> Imports s systemAPI esref = @@ -147,13 +165,20 @@ systemAPI esref = i <- getsES esref inst getBytes i (fromIntegral src) len + -- Unsafely print (if not in silent mode) + putBytes :: BS.ByteString -> HostM s () + putBytes bytes = + stToPrim (readSTRef (fst esref)) >>= \case + True -> unsafeIOToPrim (BSC.putStrLn bytes) + False -> return () + -- The system calls debug_print :: (Int32, Int32) -> HostM s () debug_print (src, len) = do -- TODO: This should be a non-trapping copy bytes <- copy_from_canister "debug_print" src len - putBytes esref bytes + putBytes bytes explicit_trap :: (Int32, Int32) -> HostM s () explicit_trap (src, len) = do @@ -226,9 +251,13 @@ systemAPI esref = return 0 -type RawState s = (ESRef s, CanisterId, Instance s) +-- The state of an instance, consistig of the underlying Wasm state, +-- additional remembered information like the CanisterId +-- and the 'ESRef' that the system api functions are accessing + +type ImpState s = (ESRef s, CanisterId, Instance s) -rawInitializeMethod :: ESRef s -> Module -> CanisterId -> EntityId -> Blob -> ST s (TrapOr (RawState s)) +rawInitializeMethod :: ESRef s -> Module -> CanisterId -> EntityId -> Blob -> ST s (TrapOr (ImpState s)) rawInitializeMethod esref wasm_mod cid caller dat = do result <- runExceptT $ do inst <- initialize wasm_mod (systemAPI esref) @@ -253,7 +282,7 @@ rawInitializeMethod esref wasm_mod cid caller dat = do Left err -> return $ Trap err Right raw_state -> return $ Return raw_state -rawQueryMethod :: RawState s -> MethodName -> EntityId -> Blob -> ST s (TrapOr Response) +rawQueryMethod :: ImpState s -> MethodName -> EntityId -> Blob -> ST s (TrapOr Response) rawQueryMethod (esref, cid, inst) method caller dat = do let es = (initalExecutionState cid inst) { params = Params @@ -273,7 +302,7 @@ rawQueryMethod (esref, cid, inst) method caller dat = do | Just r <- response es' -> return $ Return r | otherwise -> return $ Trap "No response" -rawUpdateMethod :: RawState s -> MethodName -> EntityId -> Blob -> ST s (TrapOr ([MethodCall], Maybe Response)) +rawUpdateMethod :: ImpState s -> MethodName -> EntityId -> Blob -> ST s (TrapOr ([MethodCall], Maybe Response)) rawUpdateMethod (esref, cid, inst) method caller dat = do let es = (initalExecutionState cid inst) { params = Params @@ -290,7 +319,7 @@ rawUpdateMethod (esref, cid, inst) method caller dat = do Left err -> return $ Trap err Right (_, es') -> return $ Return (calls es', response es') -rawCallbackMethod :: RawState s -> Callback -> EntityId -> Response -> ST s (TrapOr ([MethodCall], Maybe Response)) +rawCallbackMethod :: ImpState s -> Callback -> EntityId -> Response -> ST s (TrapOr ([MethodCall], Maybe Response)) rawCallbackMethod (esref, cid, inst) callback caller res = do let param_caller = Just caller let params = case res of diff --git a/ic-stub/src/IC/Canister/Pure.hs b/ic-stub/src/IC/Canister/Pure.hs index 12a1db29da2..01af4ddb5f7 100644 --- a/ic-stub/src/IC/Canister/Pure.hs +++ b/ic-stub/src/IC/Canister/Pure.hs @@ -104,7 +104,7 @@ queryMethod m caller dat s = runESST $ \esref -> do rawQueryMethod rs m caller dat -replay :: ESRef s -> WasmState -> ST s (RawState s) +replay :: ESRef s -> WasmState -> ST s (ImpState s) replay esref s = silently esref $ go s where trapToFail (Trap _err) = fail "replay failed" @@ -113,11 +113,11 @@ replay esref s = silently esref $ go s go (WSInit wasm_mod cid caller dat) = rawInitializeMethod esref wasm_mod cid caller dat >>= trapToFail go (WSUpdate m caller dat s) = do - rs <- go s - _ <- rawUpdateMethod rs m caller dat >>= trapToFail - return rs + is <- go s + _ <- rawUpdateMethod is m caller dat >>= trapToFail + return is go (WSCallback cb caller r s) = do - rs <- go s - _ <- rawCallbackMethod rs cb caller r >>= trapToFail - return rs + is <- go s + _ <- rawCallbackMethod is cb caller r >>= trapToFail + return is diff --git a/ic-stub/src/IC/Stub.hs b/ic-stub/src/IC/Stub.hs index 4d10470e0ef..5361cb346a8 100644 --- a/ic-stub/src/IC/Stub.hs +++ b/ic-stub/src/IC/Stub.hs @@ -195,24 +195,24 @@ dummyUserId :: CanisterId dummyUserId = EntityId $ BS.pack [0xCA, 0xFF, 0xEE] processRequest :: ICT m => AsyncRequest -> m () -processRequest r@(InstallRequest can_mod dat) = +processRequest r@(InstallRequest can_mod dat) = do + let canister_id = dummyCanisterId case parseCanister can_mod of Left err -> setReqStatus r $ Rejected (RC_SYS_FATAL, "Parsing failed: " ++ err) Right can_mod -> - case init_method can_mod dummyCanisterId dummyUserId dat of + case init_method can_mod canister_id dummyUserId dat of Trap msg -> setReqStatus r $ Rejected (RC_CANISTER_ERROR, "Initialization trapped: " ++ msg) Return wasm_state -> do - createCanister dummyCanisterId can_mod wasm_state + createCanister canister_id can_mod wasm_state setReqStatus r $ Completed CompleteUnit processRequest r@(UpdateRequest method arg) = do - - let canister = dummyCanisterId + let canister_id = dummyCanisterId ctxt_id <- newCallContext $ CallContext - { canister = canister + { canister = canister_id , origin = FromUser r , responded = False , last_trap = Nothing @@ -287,7 +287,7 @@ processMessage (CallMessage ctxt_id entry) = do Trap msg -> rememberTrap ctxt_id msg Return (new_state, calls, mb_response) -> do - setCanisterState dummyCanisterId new_state + setCanisterState callee new_state forM_ calls $ \call -> do new_ctxt_id <- newCallContext $ CallContext { canister = call_callee call From 8b11c4280bf1ffb30df83dfcb9ba1ad35684482e Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 14 Nov 2019 14:58:22 -0700 Subject: [PATCH 0593/1176] growable buffer abstraction in Motoko stdlib --- stdlib/buf.mo | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 stdlib/buf.mo diff --git a/stdlib/buf.mo b/stdlib/buf.mo new file mode 100644 index 00000000000..f786caf4a33 --- /dev/null +++ b/stdlib/buf.mo @@ -0,0 +1,92 @@ +module { +/** +Buffers +=================== + +Define common types for buffers that grow, with a general element type. + +Implementations of these types are/will be defined elsewhere. + +### Why? + +Motoko applications expose interfaces that use arrays of non-`Char` +elements to represent sets, sequences and maps of application-specific +elements. + +To create these arrays, and to consume them with ergonomic (imperative) code, and +low API friction, developers need _buffers that grow_. + +The `Array` module focuses on Motoko's builtin arrays, whose size is +each fixed. They do not permit general growth/appending, which is the +focus here. + +### Define `Buf` object type + +A "buffer" is a mutable sequence that grows, either one element at a time, or one (second) buffer at time. + +The only way to access elements is with iteration, or by producing an array (either mutable or immutable). + +We capture the most basic buffer abstraction with the following `Buf` object type: +*/ + +type Buf = { + // intro forms: addElm and addBuf + addElm: X -> (); + addBuf: Buf -> (); + + // utilities: + len: () -> Nat; + clear: () -> (); + copy: () -> Buf; // copies do not interfere across future mutations + + // elim forms for accessing elements: + iter: () -> Iter; + array: () -> [X]; + mutArray: () -> [var X]; // bikeshed decision: `varArray` instead? +}; + +/** + +Based on this type, we define subtypes with more features below. + +### Define `RamBuf` object type + +In its subtypes, a more general version of the buffer abstraction permits some **random access** of its elements, independent of iteration or producing an auxiliary array. + +##### Addressing accesses and updates + +By default, to _address_ an element for access, we use an offset from +the start of the buffer, beginning at zero. Additionally, the +abstraction provides access by a (zero-based) offset from the end. + +*/ + +type RamBuf = { + // intro forms: add and addBuf + add: X -> (); + addBuf: Buf -> (); + + // utilities: + len: () -> Nat; + clear: () -> (); + copy: () -> Buf; // copies do not interfere across future mutations + + // elim forms for accessing elements: + iter: () -> Iter; + array: () -> [X]; + mutArray: () -> [var X]; // bikeshed decision: `varArray` instead? + + // get/set via an offset from the start, beginning at zero. + get : Nat -> ?X; + set : (Nat, X) -> ?X; // returns old elem, if any + + // get/set via an offset from the end, beginning at zero. + getEnd : Nat -> ?X; + setEnd : (Nat, X) -> ?X; +}; + +// missing language feature? +// assert that two types are related by subtyping, without having instances?: +// e.g., use a compiler meta-function `assertIsSubTypeOf(RamBuf, Buf);` here? + +} From 2fc0151a41cbef839fe3829695d255d805600827 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 14 Nov 2019 17:08:58 -0700 Subject: [PATCH 0594/1176] first draft of an array-based buffer --- stdlib/arrayBuf.mo | 124 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 stdlib/arrayBuf.mo diff --git a/stdlib/arrayBuf.mo b/stdlib/arrayBuf.mo new file mode 100644 index 00000000000..3542eb7336d --- /dev/null +++ b/stdlib/arrayBuf.mo @@ -0,0 +1,124 @@ +import P "prelude.mo"; +import Buf "buf.mo"; +import Option "option.mo"; + +module { +/** +Array Buffers +=================== + +Growable buffers, implemented as arrays. + +See [buffer documentation](buf.mo) for more. + +*/ + +public type ArrayBuf = { + array: [var ?X]; + var count: Nat; +}; + +/** +#### Terminology: + +Note, above we say `count` rather than `len`, the term used by the +buffer abstaction. + +Here, we use `count ` and not `len` to distinguish from `array.len()`. + +`array.len()` gives the _capacity_ of the buffer's current array, but +not its current (growable) "length" within that array (which again, we +call "count" to avoid further confusion here). + +*/ + +public type InitArg = { + // no initial info + #none; + // take ownership of an existing representation + #arrayBuf: ArrayBuf; + // initially-empty, with specified capacity + #capacity: Nat; + // initialize with given elements, and additional capacity + #array: [X]; +}; + +// Create a Buf instance, represented as an ArrayBuf instance +public class Make (init:InitArg) : Buf.Buf { + var buf : ArrayBuf = switch init + { + case (#arrayBuf(buf)) buf; + case (#none) + { // 0 is "most conservative" on initial size: + array = Array_init(0, null); + var count = 0; + }; + case (#capacity(initCapacity)) + { + array = Array_init(initCapacity, null); + var count = 0; + }; + case (#array(array_)) + { + // allocate new buffer, + let newBuf = { + array = Array_init(array_.len() * 2, null); + var count = array_.len() + }; + // initialize via immutable array arg + for (i in array_.keys()) { + newBuf.array[i] := ?(array_[i]) + }; + newBuf + }; + }; + + public func add(x:X) { + if (buf.count < buf.array.len()) { + Option.assertNullAny(buf.array[buf.count]); + buf.array[buf.count] := ?x; + buf.count += 1; + } else { + // todo: grow + P.nyi() + } + }; + + public func addBuf(b:Buf.Buf) { + for (x in b.iter()) { add(x) } + }; + + public func len() : Nat = + buf.count; + + public func clear() { + // clear away elements, but do not reallocate + for (x in buf.array.keys()) { + buf.array[x] := null + }; + buf.count := 0 + }; + + public func clone() : Buf.Buf { + /** Blocked: See issue 871 */ + P.nyi() + }; + + public func iter() : Iter = + P.nyi(); + + public func array() : [X] = + // immutable clone of array + Array_tabulate( + buf.array.len(), + func(x: Nat): X { + Option.unwrap(buf.array[x]) + }); + + public func mutArray() : [var X] = { + /** Blocked: See issue 871 */ + P.nyi() + }; +}; + +} From 5a5fb92a083ef82088c6d915c609d3976da44423 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 14 Nov 2019 17:19:48 -0700 Subject: [PATCH 0595/1176] minor nits --- stdlib/arrayBuf.mo | 3 ++- stdlib/buf.mo | 14 ++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/stdlib/arrayBuf.mo b/stdlib/arrayBuf.mo index 3542eb7336d..88e05b6582b 100644 --- a/stdlib/arrayBuf.mo +++ b/stdlib/arrayBuf.mo @@ -22,7 +22,7 @@ public type ArrayBuf = { #### Terminology: Note, above we say `count` rather than `len`, the term used by the -buffer abstaction. +buffer abstraction. Here, we use `count ` and not `len` to distinguish from `array.len()`. @@ -105,6 +105,7 @@ public class Make (init:InitArg) : Buf.Buf { }; public func iter() : Iter = + // todo P.nyi(); public func array() : [X] = diff --git a/stdlib/buf.mo b/stdlib/buf.mo index f786caf4a33..991751ab126 100644 --- a/stdlib/buf.mo +++ b/stdlib/buf.mo @@ -3,13 +3,13 @@ module { Buffers =================== -Define common types for buffers that grow, with a general element type. +This module defines common types for buffers that grow, with a general element type. Implementations of these types are/will be defined elsewhere. ### Why? -Motoko applications expose interfaces that use arrays of non-`Char` +Motoko applications expose interfaces that use arrays of general (user-defined) elements to represent sets, sequences and maps of application-specific elements. @@ -29,15 +29,15 @@ The only way to access elements is with iteration, or by producing an array (eit We capture the most basic buffer abstraction with the following `Buf` object type: */ -type Buf = { +public type Buf = { // intro forms: addElm and addBuf - addElm: X -> (); + add: X -> (); addBuf: Buf -> (); // utilities: len: () -> Nat; clear: () -> (); - copy: () -> Buf; // copies do not interfere across future mutations + clone: () -> Buf; // copies do not interfere across future mutations // elim forms for accessing elements: iter: () -> Iter; @@ -69,7 +69,7 @@ type RamBuf = { // utilities: len: () -> Nat; clear: () -> (); - copy: () -> Buf; // copies do not interfere across future mutations + clone: () -> Buf; // copies do not interfere across future mutations // elim forms for accessing elements: iter: () -> Iter; @@ -89,4 +89,6 @@ type RamBuf = { // assert that two types are related by subtyping, without having instances?: // e.g., use a compiler meta-function `assertIsSubTypeOf(RamBuf, Buf);` here? +// alternatively, we could have a way to "append" object types, as with `+` on Rust traits + } From f71f8f288e9593953ec692484ef4a6f5693ae13c Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 14 Nov 2019 17:21:22 -0700 Subject: [PATCH 0596/1176] nit --- stdlib/arrayBuf.mo | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/stdlib/arrayBuf.mo b/stdlib/arrayBuf.mo index 88e05b6582b..69e53aa17a4 100644 --- a/stdlib/arrayBuf.mo +++ b/stdlib/arrayBuf.mo @@ -21,14 +21,11 @@ public type ArrayBuf = { /** #### Terminology: -Note, above we say `count` rather than `len`, the term used by the -buffer abstraction. +The buffer abstraction says `len` for what we call `count` here internally. -Here, we use `count ` and not `len` to distinguish from `array.len()`. - -`array.len()` gives the _capacity_ of the buffer's current array, but -not its current (growable) "length" within that array (which again, we -call "count" to avoid further confusion here). +We do this because `array.len()` gives the _capacity_ of the buffer's +current array, but not its current (growable) "length" within that +array (which again, we call "count" to avoid further confusion here). */ From 7fa8ac1c5a8c366f47a515c3aeb5a336c8aa8a34 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 14 Nov 2019 17:23:53 -0700 Subject: [PATCH 0597/1176] more nits --- stdlib/arrayBuf.mo | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/stdlib/arrayBuf.mo b/stdlib/arrayBuf.mo index 69e53aa17a4..a3790571660 100644 --- a/stdlib/arrayBuf.mo +++ b/stdlib/arrayBuf.mo @@ -21,11 +21,13 @@ public type ArrayBuf = { /** #### Terminology: -The buffer abstraction says `len` for what we call `count` here internally. +The buffer abstraction `Buf.Buf` says `len()` for the value tracked +(interrnally) by the `count` field of `ArrayBuf`. -We do this because `array.len()` gives the _capacity_ of the buffer's +We say `count`, and not `len`, to avoid confusion with the `len()` +method of field `array`, which gives the _capacity_ of the buffer's current array, but not its current (growable) "length" within that -array (which again, we call "count" to avoid further confusion here). +array. */ From 636b4f2705eeca5a547ef61269c3efcd04e1f24b Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 14 Nov 2019 17:40:38 -0700 Subject: [PATCH 0598/1176] placeholder for eventual unit tests --- stdlib/Makefile | 3 +++ stdlib/arrayBuf.mo | 24 +++++++++++++----------- stdlib/arrayBufTest.mo | 10 ++++++++++ stdlib/buf.mo | 8 ++++++++ 4 files changed, 34 insertions(+), 11 deletions(-) create mode 100644 stdlib/arrayBufTest.mo diff --git a/stdlib/Makefile b/stdlib/Makefile index 8febddc6c11..15cf2981565 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -17,6 +17,9 @@ WASM=\ TESTS=\ Array \ ArrayTest \ + ArrayBuf \ + ArrayBufTest \ + Buf \ AssocList \ DocTable \ Function \ diff --git a/stdlib/arrayBuf.mo b/stdlib/arrayBuf.mo index a3790571660..49451728fe7 100644 --- a/stdlib/arrayBuf.mo +++ b/stdlib/arrayBuf.mo @@ -13,11 +13,6 @@ See [buffer documentation](buf.mo) for more. */ -public type ArrayBuf = { - array: [var ?X]; - var count: Nat; -}; - /** #### Terminology: @@ -31,9 +26,13 @@ array. */ +// re-export types and use them below. +public type ArrayBuf = Buf.ArrayBuf; +public type Buf = Buf.Buf; + public type InitArg = { - // no initial info - #none; + // requests an empty buffer without asking for a capacity + #empty; // take ownership of an existing representation #arrayBuf: ArrayBuf; // initially-empty, with specified capacity @@ -43,11 +42,11 @@ public type InitArg = { }; // Create a Buf instance, represented as an ArrayBuf instance -public class Make (init:InitArg) : Buf.Buf { +public class Make (init:InitArg) : Buf { var buf : ArrayBuf = switch init { case (#arrayBuf(buf)) buf; - case (#none) + case (#empty) { // 0 is "most conservative" on initial size: array = Array_init(0, null); var count = 0; @@ -83,7 +82,7 @@ public class Make (init:InitArg) : Buf.Buf { } }; - public func addBuf(b:Buf.Buf) { + public func addBuf(b:Buf) { for (x in b.iter()) { add(x) } }; @@ -98,7 +97,7 @@ public class Make (init:InitArg) : Buf.Buf { buf.count := 0 }; - public func clone() : Buf.Buf { + public func clone() : Buf { /** Blocked: See issue 871 */ P.nyi() }; @@ -119,6 +118,9 @@ public class Make (init:InitArg) : Buf.Buf { /** Blocked: See issue 871 */ P.nyi() }; + + public func arrayBuf() : ArrayBuf + = buf; }; } diff --git a/stdlib/arrayBufTest.mo b/stdlib/arrayBufTest.mo new file mode 100644 index 00000000000..0906b9d55db --- /dev/null +++ b/stdlib/arrayBufTest.mo @@ -0,0 +1,10 @@ +import ArrayBuf "arrayBuf.mo"; + +let a = ArrayBuf.Make(#empty); +let b = ArrayBuf.Make(#capacity(1000)); +let c1 = ArrayBuf.Make(#arrayBuf(a.arrayBuf())); +let c2 = ArrayBuf.Make(#arrayBuf(b.arrayBuf())); +let d1 = ArrayBuf.Make(#array([1,2,3])); +let d2 = ArrayBuf.Make(#array(a.array())); + +// todo: assert stuff here about the variables defined above diff --git a/stdlib/buf.mo b/stdlib/buf.mo index 991751ab126..0246301646f 100644 --- a/stdlib/buf.mo +++ b/stdlib/buf.mo @@ -43,6 +43,13 @@ public type Buf = { iter: () -> Iter; array: () -> [X]; mutArray: () -> [var X]; // bikeshed decision: `varArray` instead? + arrayBuf: () -> ArrayBuf; // can expose _spare capacity_, if any +}; + +// A type that can represent and implement Buf; See [`ArrayBuf`](arrayBuf.mo) for details. +public type ArrayBuf = { + array: [var ?X]; + var count: Nat; }; /** @@ -75,6 +82,7 @@ type RamBuf = { iter: () -> Iter; array: () -> [X]; mutArray: () -> [var X]; // bikeshed decision: `varArray` instead? + arrayBuf: () -> ArrayBuf; // can expose _spare capacity_, if any // get/set via an offset from the start, beginning at zero. get : Nat -> ?X; From 1c2681df15b9b05483eb1d69ebf865cb47748cd0 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 14 Nov 2019 17:45:38 -0700 Subject: [PATCH 0599/1176] Makefile lines for new modules --- stdlib/Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/stdlib/Makefile b/stdlib/Makefile index 15cf2981565..a6375162c98 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -157,6 +157,8 @@ docMd: \ $(DOCDIR)/README.md \ $(DOCDIR)/prelude.md \ $(DOCDIR)/array.md \ + $(DOCDIR)/arrayBuf.md \ + $(DOCDIR)/buf.md \ $(DOCDIR)/option.md \ $(DOCDIR)/result.md \ $(DOCDIR)/hash.md \ @@ -180,6 +182,8 @@ docHtml: \ $(DOCDIR)/README.html \ $(DOCDIR)/prelude.html \ $(DOCDIR)/array.html \ + $(DOCDIR)/arrayBuf.html \ + $(DOCDIR)/buf.html \ $(DOCDIR)/option.html \ $(DOCDIR)/result.html \ $(DOCDIR)/hash.html \ From 86ad0cde3d1c54037a17398df5a50581e0be0540 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 14 Nov 2019 17:48:53 -0700 Subject: [PATCH 0600/1176] Makefile lines for new modules --- stdlib/Makefile | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/stdlib/Makefile b/stdlib/Makefile index a6375162c98..23f1c68f023 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -76,6 +76,12 @@ $(OUTDIR)/Array.out: array.mo | $(OUTDIR) $(OUTDIR)/ArrayTest.out: arrayTest.mo | $(OUTDIR) $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ +$(OUTDIR)/ArrayBuf.out: arrayBuf.mo | $(OUTDIR) + $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ + +$(OUTDIR)/ArrayBufTest.out: arrayBufTest.mo | $(OUTDIR) + $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ + $(OUTDIR)/Function.out: function.mo | $(OUTDIR) $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ From a2cc4885dcdbbded3a2f79949061feab031a3a48 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 14 Nov 2019 17:50:27 -0700 Subject: [PATCH 0601/1176] Makefile lines for new modules --- stdlib/Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/stdlib/Makefile b/stdlib/Makefile index 23f1c68f023..025001be4ba 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -82,6 +82,9 @@ $(OUTDIR)/ArrayBuf.out: arrayBuf.mo | $(OUTDIR) $(OUTDIR)/ArrayBufTest.out: arrayBufTest.mo | $(OUTDIR) $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ +$(OUTDIR)/Buf.out: buf.mo | $(OUTDIR) + $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ + $(OUTDIR)/Function.out: function.mo | $(OUTDIR) $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ From 5ee41f69d7ef9510f2a91e70cbff1bc7ad96a184 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 14 Nov 2019 17:53:04 -0700 Subject: [PATCH 0602/1176] nit: move comment --- stdlib/arrayBuf.mo | 13 ------------- stdlib/buf.mo | 13 +++++++++++++ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/stdlib/arrayBuf.mo b/stdlib/arrayBuf.mo index 49451728fe7..cee3d86b1b2 100644 --- a/stdlib/arrayBuf.mo +++ b/stdlib/arrayBuf.mo @@ -13,19 +13,6 @@ See [buffer documentation](buf.mo) for more. */ -/** -#### Terminology: - -The buffer abstraction `Buf.Buf` says `len()` for the value tracked -(interrnally) by the `count` field of `ArrayBuf`. - -We say `count`, and not `len`, to avoid confusion with the `len()` -method of field `array`, which gives the _capacity_ of the buffer's -current array, but not its current (growable) "length" within that -array. - -*/ - // re-export types and use them below. public type ArrayBuf = Buf.ArrayBuf; public type Buf = Buf.Buf; diff --git a/stdlib/buf.mo b/stdlib/buf.mo index 0246301646f..bb913ce1b4e 100644 --- a/stdlib/buf.mo +++ b/stdlib/buf.mo @@ -52,6 +52,19 @@ public type ArrayBuf = { var count: Nat; }; +/** +#### Terminology: + +The buffer abstraction `Buf.Buf` says `len()` for the value tracked +(interrnally) by the `count` field of `ArrayBuf`. + +We say `count`, and not `len`, to avoid confusion with the `len()` +method of field `array`, which gives the _capacity_ of the buffer's +current array, but not its current (growable) "length" within that +array. + +*/ + /** Based on this type, we define subtypes with more features below. From 257d19d3f1bc2122515cc62435315e3dad99c936 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 14 Nov 2019 18:55:07 -0700 Subject: [PATCH 0603/1176] encode subtyping assertion --- stdlib/buf.mo | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/stdlib/buf.mo b/stdlib/buf.mo index bb913ce1b4e..357bff94aba 100644 --- a/stdlib/buf.mo +++ b/stdlib/buf.mo @@ -106,10 +106,8 @@ type RamBuf = { setEnd : (Nat, X) -> ?X; }; -// missing language feature? -// assert that two types are related by subtyping, without having instances?: -// e.g., use a compiler meta-function `assertIsSubTypeOf(RamBuf, Buf);` here? - -// alternatively, we could have a way to "append" object types, as with `+` on Rust traits +// assert that two types are related by subtyping, without having instances: +func _assertSubtypes(ramBuf:RamBuf) : Buf = ramBuf; +// (alternatively, we could have a way to "append" object types, as with `+` on Rust traits.) } From ea1a20f818e8bbf0d3815034ad7fd05ef06454f4 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 15 Nov 2019 08:41:30 +0100 Subject: [PATCH 0604/1176] IC.Stub: Implement `ic0.msg_reply_data_append` --- ic-stub/src/IC/Canister/Imp.hs | 143 +++++++++++++++++++--------- src/codegen/compile.ml | 7 +- test/run-stub/ok/oom.ic-stub-run.ok | 6 -- test/run-stub/oom.mo | 13 --- 4 files changed, 102 insertions(+), 67 deletions(-) delete mode 100644 test/run-stub/ok/oom.ic-stub-run.ok delete mode 100644 test/run-stub/oom.mo diff --git a/ic-stub/src/IC/Canister/Imp.hs b/ic-stub/src/IC/Canister/Imp.hs index afd4ebb8ca7..56ab171f36d 100644 --- a/ic-stub/src/IC/Canister/Imp.hs +++ b/ic-stub/src/IC/Canister/Imp.hs @@ -51,6 +51,7 @@ data ExecutionState s = ExecutionState , params :: Params -- now the mutable parts , response :: Maybe Response + , reply_data :: Blob , calls :: [MethodCall] } @@ -61,6 +62,7 @@ initalExecutionState self_id inst = ExecutionState , self_id , params = Params Nothing Nothing 0 "" , response = Nothing + , reply_data = mempty , calls = mempty } @@ -114,6 +116,9 @@ getsES (_, esref) f = lift (readSTRef esref) >>= \case modES :: ESRef s -> (ExecutionState s -> ExecutionState s) -> HostM s () modES (_, esref) f = lift $ modifySTRef esref (fmap f) +appendReplyData :: ESRef s -> Blob -> HostM s () +appendReplyData esref dat = modES esref $ \es -> + es { reply_data = reply_data es <> dat } setResponse :: ESRef s -> Response -> HostM s () setResponse esref r = modES esref $ \es -> @@ -130,25 +135,27 @@ appendCall esref c = modES esref $ \es -> systemAPI :: forall s. ESRef s -> Imports s systemAPI esref = [ (,) "ic0" - [ toImport "call_simple" call_simple + [ toImport "msg_arg_data_size" msg_arg_data_size + , toImport "msg_arg_data_copy" msg_arg_data_copy + , toImport "msg_caller_size" msg_caller_size + , toImport "msg_caller_copy" msg_caller_copy + , toImport "msg_reject_code" msg_reject_code + , toImport "msg_reject_msg_len" msg_reject_msg_len + , toImport "msg_reject_msg_copy" msg_reject_msg_copy + , toImport "msg_reply_data_append" msg_reply_data_append + , toImport "msg_reply" msg_reply + , toImport "msg_reject" msg_reject , toImport "canister_self_copy" canister_self_copy , toImport "canister_self_len" canister_self_len + , toImport "call_simple" call_simple , toImport "debug_print" debug_print - , toImport "msg_arg_data_copy" arg_data_copy - , toImport "msg_arg_data_size" arg_data_size - , toImport "msg_reject" msg_reject - , toImport "msg_reply" msg_reply , toImport "trap" explicit_trap - , unimplemented "msg_reject_code" [] [i32] ] ] where -- Utilities - - unimplemented name arg ret = (,,,) name arg ret $ - \_ -> throwError $ "unimplemented: " ++ name - - i32 = I32Type + gets :: (ExecutionState s -> b) -> HostM s b + gets = getsES esref copy_to_canister :: String -> Int32 -> Int32 -> Int32 -> Blob -> HostM s () copy_to_canister name dst offset len blob = do @@ -162,7 +169,7 @@ systemAPI esref = copy_from_canister :: String -> Int32 -> Int32 -> HostM s Blob copy_from_canister _name src len = do - i <- getsES esref inst + i <- gets inst getBytes i (fromIntegral src) len -- Unsafely print (if not in silent mode) @@ -172,53 +179,85 @@ systemAPI esref = True -> unsafeIOToPrim (BSC.putStrLn bytes) False -> return () - -- The system calls - - debug_print :: (Int32, Int32) -> HostM s () - debug_print (src, len) = do - -- TODO: This should be a non-trapping copy - bytes <- copy_from_canister "debug_print" src len - putBytes bytes - - explicit_trap :: (Int32, Int32) -> HostM s () - explicit_trap (src, len) = do - -- TODO: This should be a non-trapping copy - bytes <- copy_from_canister "ic.trap" src len - let msg = BSU.toString bytes - throwError $ "canister trapped explicitly: " ++ msg - - canister_self_len :: () -> HostM s Int32 - canister_self_len () = do - id <- getsES esref self_id - return $ fromIntegral (BS.length (rawEntityId id)) - - canister_self_copy :: (Int32, Int32, Int32) -> HostM s () - canister_self_copy (dst, offset, len) = do - id <- getsES esref self_id - copy_to_canister "canister_self_copy" dst offset len (rawEntityId id) + -- The system calls (in the order of the public spec) + -- https://docs.dfinity.systems/spec/public/#_system_imports - arg_data_size :: () -> HostM s Int32 - arg_data_size () = do - blob <- getsES esref (param_dat . params) + msg_arg_data_size :: () -> HostM s Int32 + msg_arg_data_size () = do + blob <- gets (param_dat . params) >>= maybe (throwError "arg_data_size: No argument") return return $ fromIntegral (BS.length blob) - arg_data_copy :: (Int32, Int32, Int32) -> HostM s () - arg_data_copy (dst, offset, len) = do - blob <- getsES esref (param_dat . params) + msg_arg_data_copy :: (Int32, Int32, Int32) -> HostM s () + msg_arg_data_copy (dst, offset, len) = do + blob <- gets (param_dat . params) >>= maybe (throwError "arg_data_size: No argument") return copy_to_canister "arg_data_copy" dst offset len blob - msg_reply :: (Int32, Int32) -> HostM s () - msg_reply (src, len) = do + msg_caller_size :: () -> HostM s Int32 + msg_caller_size () = do + blob <- gets (param_caller . params) + >>= maybe (throwError "arg_data_size: No argument") return + return $ fromIntegral (BS.length (rawEntityId blob)) + + msg_caller_copy :: (Int32, Int32, Int32) -> HostM s () + msg_caller_copy (dst, offset, len) = do + blob <- gets (param_caller . params) + >>= maybe (throwError "arg_data_size: No argument") return + copy_to_canister "msg_caller_copy" dst offset len (rawEntityId blob) + + msg_reject_code :: () -> HostM s Int32 + msg_reject_code () = + fromIntegral <$> gets (reject_code . params) + + msg_reject_msg_len :: () -> HostM s Int32 + msg_reject_msg_len () = do + c <- gets (reject_code . params) + when (c == 0) $ throwError "msg_reject_msg_len: No reject message" + msg <- gets (reject_message . params) + return $ fromIntegral (BS.length (BSU.fromString msg)) + + msg_reject_msg_copy :: (Int32, Int32, Int32) -> HostM s () + msg_reject_msg_copy (dst, offset, len) = do + c <- gets (reject_code . params) + when (c == 0) $ throwError "msg_reject_msg_len: No reject message" + msg <- gets (reject_message . params) + copy_to_canister "msg_reject_msg_copy" dst offset len (BSU.fromString msg) + + assert_not_responded :: HostM s () + assert_not_responded = + gets response >>= \case + Nothing -> return () + Just _ -> throwError "This has already be responded to" + + msg_reply_data_append :: (Int32, Int32) -> HostM s () + msg_reply_data_append (src, len) = do + assert_not_responded bytes <- copy_from_canister "debug_print" src len + appendReplyData esref bytes + + msg_reply :: () -> HostM s () + msg_reply () = do + assert_not_responded + bytes <- gets reply_data setResponse esref (Reply bytes) msg_reject :: (Int32, Int32) -> HostM s () msg_reject (src, len) = do + assert_not_responded bytes <- copy_from_canister "debug_print" src len let msg = BSU.toString bytes - modES esref (\es -> es { response = Just (Reject (RC_CANISTER_REJECT, msg)) }) + setResponse esref $ Reject (RC_CANISTER_REJECT, msg) + + canister_self_len :: () -> HostM s Int32 + canister_self_len () = do + id <- gets self_id + return $ fromIntegral (BS.length (rawEntityId id)) + + canister_self_copy :: (Int32, Int32, Int32) -> HostM s () + canister_self_copy (dst, offset, len) = do + id <- gets self_id + copy_to_canister "canister_self_copy" dst offset len (rawEntityId id) call_simple :: ( Int32, Int32, Int32, Int32, Int32 @@ -248,9 +287,21 @@ systemAPI esref = , reject_callback = WasmClosure reject_fun reject_env } } - return 0 + debug_print :: (Int32, Int32) -> HostM s () + debug_print (src, len) = do + -- TODO: This should be a non-trapping copy + bytes <- copy_from_canister "debug_print" src len + putBytes bytes + + explicit_trap :: (Int32, Int32) -> HostM s () + explicit_trap (src, len) = do + -- TODO: This should be a non-trapping copy + bytes <- copy_from_canister "trap" src len + let msg = BSU.toString bytes + throwError $ "canister trapped explicitly: " ++ msg + -- The state of an instance, consistig of the underlying Wasm state, -- additional remembered information like the CanisterId -- and the 'ESRef' that the system api functions are accessing diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 9093645d9d4..37a2b62e1a0 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -3081,7 +3081,8 @@ module Dfinity = struct E.add_func_import env "ic0" "msg_arg_data_size" [] [I32Type]; E.add_func_import env "ic0" "msg_reject_code" [] [I32Type]; E.add_func_import env "ic0" "msg_reject" [I32Type; I32Type] []; - E.add_func_import env "ic0" "msg_reply" [I32Type; I32Type] []; + E.add_func_import env "ic0" "msg_reply_data_append" [I32Type; I32Type] []; + E.add_func_import env "ic0" "msg_reply" [] []; E.add_func_import env "ic0" "trap" [I32Type; I32Type] []; () | Flags.AncientMode -> @@ -3312,7 +3313,9 @@ module Dfinity = struct get_data_size ^^ match E.mode env with | Flags.ICMode -> system_call env "msg" "reply" - | Flags.StubMode -> system_call env "ic0" "msg_reply" + | Flags.StubMode -> + system_call env "ic0" "msg_reply_data_append" ^^ + system_call env "ic0" "msg_reply" | _ -> assert false ) end (* Dfinity *) diff --git a/test/run-stub/ok/oom.ic-stub-run.ok b/test/run-stub/ok/oom.ic-stub-run.ok deleted file mode 100644 index 267aee6dadb..00000000000 --- a/test/run-stub/ok/oom.ic-stub-run.ok +++ /dev/null @@ -1,6 +0,0 @@ -→ install -← completed -→ update doloop(0x4449444c0000) -← rejected (RC_CANISTER_ERROR): canister did not respond -→ update doloop(0x4449444c0000) -← rejected (RC_CANISTER_ERROR): canister did not respond diff --git a/test/run-stub/oom.mo b/test/run-stub/oom.mo deleted file mode 100644 index f9a9b135f21..00000000000 --- a/test/run-stub/oom.mo +++ /dev/null @@ -1,13 +0,0 @@ -actor Oom { - public func doloop() { - ignore(Array_init<()>(1200*1024/4, ())); - }; -} - -// on dvm: -// CALL doloop 0x4449444C0000 [] -// CALL doloop 0x4449444C0000 [] - -// on drun: -//CALL ingress doloop 0x4449444C0000 -//CALL ingress doloop 0x4449444C0000 From 77e74c8a96c41694e24fc02ff7187ca4fea861d3 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 15 Nov 2019 09:06:05 +0100 Subject: [PATCH 0605/1176] Stub System API: Use `size` in anticipation of https://github.com/dfinity-lab/dfinity/pull/1889 --- ic-stub/src/IC/Canister/Imp.hs | 112 +++++++++++++++------------------ src/codegen/compile.ml | 6 +- 2 files changed, 52 insertions(+), 66 deletions(-) diff --git a/ic-stub/src/IC/Canister/Imp.hs b/ic-stub/src/IC/Canister/Imp.hs index 56ab171f36d..0c0e4ae4a1d 100644 --- a/ic-stub/src/IC/Canister/Imp.hs +++ b/ic-stub/src/IC/Canister/Imp.hs @@ -140,13 +140,13 @@ systemAPI esref = , toImport "msg_caller_size" msg_caller_size , toImport "msg_caller_copy" msg_caller_copy , toImport "msg_reject_code" msg_reject_code - , toImport "msg_reject_msg_len" msg_reject_msg_len + , toImport "msg_reject_msg_size" msg_reject_msg_size , toImport "msg_reject_msg_copy" msg_reject_msg_copy , toImport "msg_reply_data_append" msg_reply_data_append , toImport "msg_reply" msg_reply , toImport "msg_reject" msg_reject , toImport "canister_self_copy" canister_self_copy - , toImport "canister_self_len" canister_self_len + , toImport "canister_self_size" canister_self_size , toImport "call_simple" call_simple , toImport "debug_print" debug_print , toImport "trap" explicit_trap @@ -157,20 +157,31 @@ systemAPI esref = gets :: (ExecutionState s -> b) -> HostM s b gets = getsES esref - copy_to_canister :: String -> Int32 -> Int32 -> Int32 -> Blob -> HostM s () - copy_to_canister name dst offset len blob = do + copy_to_canister :: Int32 -> Int32 -> Int32 -> Blob -> HostM s () + copy_to_canister dst offset size blob = do unless (offset == 0) $ - throwError $ name ++ ": offset /= 0 not suppoted" - unless (len == fromIntegral (BS.length blob)) $ - throwError $ name ++ ": len not full blob not suppoted" + throwError "offset /= 0 not suppoted" + unless (size == fromIntegral (BS.length blob)) $ + throwError "copying less than the full blob is not supported" i <- getsES esref inst -- TODO Bounds checking setBytes i (fromIntegral dst) blob copy_from_canister :: String -> Int32 -> Int32 -> HostM s Blob - copy_from_canister _name src len = do + copy_from_canister _name src size = do i <- gets inst - getBytes i (fromIntegral src) len + getBytes i (fromIntegral src) size + + size_and_copy :: HostM s Blob -> + ( () -> HostM s Int32 + , (Int32, Int32, Int32) -> HostM s () + ) + size_and_copy get_blob = + ( \() -> + get_blob >>= \blob -> return $ fromIntegral (BS.length blob) + , \(dst, offset, size) -> + get_blob >>= \blob -> copy_to_canister dst offset size blob + ) -- Unsafely print (if not in silent mode) putBytes :: BS.ByteString -> HostM s () @@ -183,57 +194,37 @@ systemAPI esref = -- https://docs.dfinity.systems/spec/public/#_system_imports msg_arg_data_size :: () -> HostM s Int32 - msg_arg_data_size () = do - blob <- gets (param_dat . params) - >>= maybe (throwError "arg_data_size: No argument") return - return $ fromIntegral (BS.length blob) - - msg_arg_data_copy :: (Int32, Int32, Int32) -> HostM s () - msg_arg_data_copy (dst, offset, len) = do - blob <- gets (param_dat . params) - >>= maybe (throwError "arg_data_size: No argument") return - copy_to_canister "arg_data_copy" dst offset len blob + msg_arg_data_copy :: (Int32, Int32, Int32) -> HostM s () + (msg_arg_data_size, msg_arg_data_copy) = size_and_copy $ + gets (param_dat . params) >>= maybe (throwError "arg_data_size: No argument") return msg_caller_size :: () -> HostM s Int32 - msg_caller_size () = do - blob <- gets (param_caller . params) - >>= maybe (throwError "arg_data_size: No argument") return - return $ fromIntegral (BS.length (rawEntityId blob)) - - msg_caller_copy :: (Int32, Int32, Int32) -> HostM s () - msg_caller_copy (dst, offset, len) = do - blob <- gets (param_caller . params) - >>= maybe (throwError "arg_data_size: No argument") return - copy_to_canister "msg_caller_copy" dst offset len (rawEntityId blob) + msg_caller_copy :: (Int32, Int32, Int32) -> HostM s () + (msg_caller_size, msg_caller_copy) = size_and_copy $ + fmap rawEntityId $ gets (param_caller . params) >>= maybe (throwError "arg_data_size: No argument") return msg_reject_code :: () -> HostM s Int32 msg_reject_code () = fromIntegral <$> gets (reject_code . params) - msg_reject_msg_len :: () -> HostM s Int32 - msg_reject_msg_len () = do - c <- gets (reject_code . params) - when (c == 0) $ throwError "msg_reject_msg_len: No reject message" - msg <- gets (reject_message . params) - return $ fromIntegral (BS.length (BSU.fromString msg)) - - msg_reject_msg_copy :: (Int32, Int32, Int32) -> HostM s () - msg_reject_msg_copy (dst, offset, len) = do + msg_reject_msg_size :: () -> HostM s Int32 + msg_reject_msg_copy :: (Int32, Int32, Int32) -> HostM s () + (msg_reject_msg_size, msg_reject_msg_copy) = size_and_copy $ do c <- gets (reject_code . params) - when (c == 0) $ throwError "msg_reject_msg_len: No reject message" + when (c == 0) $ throwError "msg_reject_msg: No reject message" msg <- gets (reject_message . params) - copy_to_canister "msg_reject_msg_copy" dst offset len (BSU.fromString msg) + return $ BSU.fromString msg assert_not_responded :: HostM s () assert_not_responded = gets response >>= \case Nothing -> return () - Just _ -> throwError "This has already be responded to" + Just _ -> throwError "This call has already be responded to" msg_reply_data_append :: (Int32, Int32) -> HostM s () - msg_reply_data_append (src, len) = do + msg_reply_data_append (src, size) = do assert_not_responded - bytes <- copy_from_canister "debug_print" src len + bytes <- copy_from_canister "debug_print" src size appendReplyData esref bytes msg_reply :: () -> HostM s () @@ -243,40 +234,35 @@ systemAPI esref = setResponse esref (Reply bytes) msg_reject :: (Int32, Int32) -> HostM s () - msg_reject (src, len) = do + msg_reject (src, size) = do assert_not_responded - bytes <- copy_from_canister "debug_print" src len + bytes <- copy_from_canister "debug_print" src size let msg = BSU.toString bytes setResponse esref $ Reject (RC_CANISTER_REJECT, msg) - canister_self_len :: () -> HostM s Int32 - canister_self_len () = do - id <- gets self_id - return $ fromIntegral (BS.length (rawEntityId id)) - + canister_self_size :: () -> HostM s Int32 canister_self_copy :: (Int32, Int32, Int32) -> HostM s () - canister_self_copy (dst, offset, len) = do - id <- gets self_id - copy_to_canister "canister_self_copy" dst offset len (rawEntityId id) + (canister_self_size, canister_self_copy) = size_and_copy $ + rawEntityId <$> gets self_id call_simple :: ( Int32, Int32, Int32, Int32, Int32 , Int32, Int32, Int32, Int32, Int32) -> HostM s Int32 call_simple ( callee_src - , callee_len + , callee_size , name_src - , name_len + , name_size , reply_fun , reply_env , reject_fun , reject_env , data_src - , data_len + , data_size ) = do - callee <- copy_from_canister "call_simple" callee_src callee_len - method_name <- copy_from_canister "call_simple" name_src name_len - arg <- copy_from_canister "call_simple" data_src data_len + callee <- copy_from_canister "call_simple" callee_src callee_size + method_name <- copy_from_canister "call_simple" name_src name_size + arg <- copy_from_canister "call_simple" data_src data_size appendCall esref $ MethodCall { call_callee = EntityId callee @@ -290,15 +276,15 @@ systemAPI esref = return 0 debug_print :: (Int32, Int32) -> HostM s () - debug_print (src, len) = do + debug_print (src, size) = do -- TODO: This should be a non-trapping copy - bytes <- copy_from_canister "debug_print" src len + bytes <- copy_from_canister "debug_print" src size putBytes bytes explicit_trap :: (Int32, Int32) -> HostM s () - explicit_trap (src, len) = do + explicit_trap (src, size) = do -- TODO: This should be a non-trapping copy - bytes <- copy_from_canister "trap" src len + bytes <- copy_from_canister "trap" src size let msg = BSU.toString bytes throwError $ "canister trapped explicitly: " ++ msg diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 37a2b62e1a0..687244d71d5 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -2656,7 +2656,7 @@ module Blob = struct let unskewed_payload_offset = Int32.(add ptr_unskew (mul Heap.word_size header_size)) let payload_ptr_unskewed = compile_add_const unskewed_payload_offset - let as_ptr_len env = Func.share_code1 env "as_ptr_len" ("x", I32Type) [I32Type; I32Type] ( + let as_ptr_len env = Func.share_code1 env "as_ptr_size" ("x", I32Type) [I32Type; I32Type] ( fun env get_x -> get_x ^^ payload_ptr_unskewed ^^ get_x ^^ Heap.load_field len_field @@ -3075,7 +3075,7 @@ module Dfinity = struct | Flags.StubMode -> E.add_func_import env "ic0" "call_simple" (Lib.List.make 10 I32Type) [I32Type]; E.add_func_import env "ic0" "canister_self_copy" [I32Type; I32Type; I32Type] []; - E.add_func_import env "ic0" "canister_self_len" [] [I32Type]; + E.add_func_import env "ic0" "canister_self_size" [] [I32Type]; E.add_func_import env "ic0" "debug_print" [I32Type; I32Type] []; E.add_func_import env "ic0" "msg_arg_data_copy" [I32Type; I32Type; I32Type] []; E.add_func_import env "ic0" "msg_arg_data_size" [] [I32Type]; @@ -3255,7 +3255,7 @@ module Dfinity = struct Func.share_code0 env "canister_self" [I32Type] (fun env -> let (set_len, get_len) = new_local env "len" in let (set_blob, get_blob) = new_local env "blob" in - system_call env "ic0" "canister_self_len" ^^ + system_call env "ic0" "canister_self_size" ^^ set_len ^^ get_len ^^ Blob.alloc env ^^ set_blob ^^ From a4998121c6a6124991bba1d58c3a9f3bea4a410d Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 15 Nov 2019 09:27:11 +0100 Subject: [PATCH 0606/1176] Move `dummyUserId` into ic-stub-run --- ic-stub/src/IC/Canister/Imp.hs | 2 +- ic-stub/src/IC/Stub.hs | 25 +++++++++++++------------ ic-stub/src/IC/Types.hs | 1 + ic-stub/src/ic-stub-run.hs | 15 +++++++++------ 4 files changed, 24 insertions(+), 19 deletions(-) diff --git a/ic-stub/src/IC/Canister/Imp.hs b/ic-stub/src/IC/Canister/Imp.hs index 0c0e4ae4a1d..bbc54897d29 100644 --- a/ic-stub/src/IC/Canister/Imp.hs +++ b/ic-stub/src/IC/Canister/Imp.hs @@ -69,7 +69,7 @@ initalExecutionState self_id inst = ExecutionState -- Some bookkeeping to access the ExecutionState -- -- We “always” have the 'STRef', but only within 'withES' is it actually --- present. +-- present. -- -- Also: A flag to check whether we are running in silent mode or not -- (a bit of a hack) diff --git a/ic-stub/src/IC/Stub.hs b/ic-stub/src/IC/Stub.hs index 5361cb346a8..06302fb63e6 100644 --- a/ic-stub/src/IC/Stub.hs +++ b/ic-stub/src/IC/Stub.hs @@ -38,12 +38,12 @@ import IC.Canister.Pure -- Abstract HTTP Interface data AsyncRequest - = InstallRequest Blob Blob - | UpdateRequest MethodName Blob + = InstallRequest UserId Blob Blob + | UpdateRequest UserId MethodName Blob deriving (Eq, Ord, Show) data SyncRequest - = QueryRequest MethodName Blob + = QueryRequest UserId MethodName Blob | StatusRequest Blob data RequestStatus @@ -133,7 +133,7 @@ readRequest (StatusRequest rid) = Just (_r,status) -> return status Nothing -> return Unknown -readRequest (QueryRequest method arg) = +readRequest (QueryRequest user_id method arg) = gets (M.lookup dummyCanisterId . canisters) >>= \case Nothing -> return $ Rejected (RC_DESTINATION_INVALID, "canister does not exist") Just Nothing -> return $ Rejected (RC_DESTINATION_INVALID, "canister is empty") @@ -141,7 +141,7 @@ readRequest (QueryRequest method arg) = case M.lookup method (query_methods can_mod) of Nothing -> return $ Rejected (RC_DESTINATION_INVALID, "query method does not exist") Just f -> - case f dummyUserId arg wasm_state of + case f user_id arg wasm_state of Trap msg -> return $ Rejected (RC_CANISTER_ERROR, "canister trapped: " ++ msg) Return (Reply res) -> return $ Completed (CompleteArg res) Return (Reject (rc,rm)) -> return $ Rejected (rc, rm) @@ -191,24 +191,21 @@ setCanisterState cid wasm_state = dummyCanisterId :: CanisterId dummyCanisterId = EntityId $ BS.pack [0xDE, 0xAD, 0xBE, 0xEF] -dummyUserId :: CanisterId -dummyUserId = EntityId $ BS.pack [0xCA, 0xFF, 0xEE] - processRequest :: ICT m => AsyncRequest -> m () -processRequest r@(InstallRequest can_mod dat) = do +processRequest r@(InstallRequest user_id can_mod dat) = do let canister_id = dummyCanisterId case parseCanister can_mod of Left err -> setReqStatus r $ Rejected (RC_SYS_FATAL, "Parsing failed: " ++ err) Right can_mod -> - case init_method can_mod canister_id dummyUserId dat of + case init_method can_mod canister_id user_id dat of Trap msg -> setReqStatus r $ Rejected (RC_CANISTER_ERROR, "Initialization trapped: " ++ msg) Return wasm_state -> do createCanister canister_id can_mod wasm_state setReqStatus r $ Completed CompleteUnit -processRequest r@(UpdateRequest method arg) = do +processRequest r@(UpdateRequest _user_id method arg) = do let canister_id = dummyCanisterId ctxt_id <- newCallContext $ CallContext @@ -250,11 +247,15 @@ rememberTrap :: ICT m => CallId -> String -> m () rememberTrap ctxt_id msg = modifyContext ctxt_id $ \ctxt -> ctxt { last_trap = Just msg } +callerOfRequest :: AsyncRequest -> EntityId +callerOfRequest (InstallRequest user_id _ _) = user_id +callerOfRequest (UpdateRequest user_id _ _) = user_id + callerOfCallID :: ICT m => CallId -> m EntityId callerOfCallID ctxt_id = do ctxt <- gets ((M.! ctxt_id) . call_contexts) case origin ctxt of - FromUser _request -> return dummyUserId + FromUser request -> return $ callerOfRequest request FromCanister other_ctxt_id _callback -> calleeOfCallID other_ctxt_id calleeOfCallID :: ICT m => CallId -> m EntityId diff --git a/ic-stub/src/IC/Types.hs b/ic-stub/src/IC/Types.hs index 46c7ca41416..267c70d808f 100644 --- a/ic-stub/src/IC/Types.hs +++ b/ic-stub/src/IC/Types.hs @@ -12,6 +12,7 @@ type (↦) = M.Map type Blob = BS.ByteString newtype EntityId = EntityId { rawEntityId :: Blob } deriving (Show, Eq, Ord) type CanisterId = EntityId +type UserId = EntityId type MethodName = String type RequestID = Blob diff --git a/ic-stub/src/ic-stub-run.hs b/ic-stub/src/ic-stub-run.hs index 94a53af3ecc..186540a72d4 100644 --- a/ic-stub/src/ic-stub-run.hs +++ b/ic-stub/src/ic-stub-run.hs @@ -27,16 +27,19 @@ prettyBlob b = "0x" ++ T.unpack (T.encodeHex (B.toStrict b)) prettyID :: EntityId -> String prettyID = prettyBlob . rawEntityId -- implement the "ic:…" stuff +dummyUserId :: CanisterId +dummyUserId = EntityId $ B.pack [0xCA, 0xFF, 0xEE] + printAsyncRequest :: AsyncRequest -> IO () -printAsyncRequest (InstallRequest _ _) = +printAsyncRequest InstallRequest{} = printf "→ install\n" -printAsyncRequest (UpdateRequest method arg) = +printAsyncRequest (UpdateRequest _ method arg) = printf "→ update %s(%s)\n" method (prettyBlob arg) printSyncRequest :: SyncRequest -> IO () printSyncRequest (StatusRequest rid) = printf "→ status? %s\n" (prettyBlob rid) -printSyncRequest (QueryRequest method arg) = +printSyncRequest (QueryRequest _ method arg) = printf "→ query %s(%s)\n" method (prettyBlob arg) printReqStatus :: RequestStatus -> IO () @@ -77,10 +80,10 @@ work wasm_file msg_file = do msgs <- parseFile msg_file flip evalStateT initialIC $ do - _req_res <- submitAndRun (InstallRequest wasm B.empty) + _req_res <- submitAndRun (InstallRequest dummyUserId wasm B.empty) forM_ msgs $ \case - (Query, method, arg) -> submitRead (QueryRequest method arg) - (Update, method, arg) -> submitAndRun (UpdateRequest method arg) + (Query, method, arg) -> submitRead (QueryRequest dummyUserId method arg) + (Update, method, arg) -> submitAndRun (UpdateRequest dummyUserId method arg) main :: IO () main = join . customExecParser (prefs showHelpOnError) $ From a996ed60087d8ab05e0041a08bbe52e2fdb8b30b Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 15 Nov 2019 09:34:07 +0100 Subject: [PATCH 0607/1176] Move `generic-tail-rec.mo` to `run-drun` no actor features needed, but a tad too slow for the interpreter --- test/run-dfinity/ok/generic-tail-rec.dvm.ok | 4 ---- test/run-dfinity/ok/generic-tail-rec.run-ir.ok | 4 ---- test/run-dfinity/ok/generic-tail-rec.run-low.ok | 4 ---- test/run-dfinity/ok/generic-tail-rec.run.ok | 4 ---- test/{run-dfinity => run-drun}/generic-tail-rec.mo | 8 ++++---- test/run-drun/ok/generic-tail-rec.drun-run.ok | 5 +++++ test/run-drun/ok/generic-tail-rec.run-ir.ok | 1 + test/run-drun/ok/generic-tail-rec.run-low.ok | 1 + test/run-drun/ok/generic-tail-rec.run.ok | 1 + 9 files changed, 12 insertions(+), 20 deletions(-) delete mode 100644 test/run-dfinity/ok/generic-tail-rec.dvm.ok delete mode 100644 test/run-dfinity/ok/generic-tail-rec.run-ir.ok delete mode 100644 test/run-dfinity/ok/generic-tail-rec.run-low.ok delete mode 100644 test/run-dfinity/ok/generic-tail-rec.run.ok rename test/{run-dfinity => run-drun}/generic-tail-rec.mo (80%) create mode 100644 test/run-drun/ok/generic-tail-rec.drun-run.ok create mode 100644 test/run-drun/ok/generic-tail-rec.run-ir.ok create mode 100644 test/run-drun/ok/generic-tail-rec.run-low.ok create mode 100644 test/run-drun/ok/generic-tail-rec.run.ok diff --git a/test/run-dfinity/ok/generic-tail-rec.dvm.ok b/test/run-dfinity/ok/generic-tail-rec.dvm.ok deleted file mode 100644 index 6d96c93ceef..00000000000 --- a/test/run-dfinity/ok/generic-tail-rec.dvm.ok +++ /dev/null @@ -1,4 +0,0 @@ -done 1 -done 2 -done 3 -done 4 diff --git a/test/run-dfinity/ok/generic-tail-rec.run-ir.ok b/test/run-dfinity/ok/generic-tail-rec.run-ir.ok deleted file mode 100644 index 6d96c93ceef..00000000000 --- a/test/run-dfinity/ok/generic-tail-rec.run-ir.ok +++ /dev/null @@ -1,4 +0,0 @@ -done 1 -done 2 -done 3 -done 4 diff --git a/test/run-dfinity/ok/generic-tail-rec.run-low.ok b/test/run-dfinity/ok/generic-tail-rec.run-low.ok deleted file mode 100644 index 6d96c93ceef..00000000000 --- a/test/run-dfinity/ok/generic-tail-rec.run-low.ok +++ /dev/null @@ -1,4 +0,0 @@ -done 1 -done 2 -done 3 -done 4 diff --git a/test/run-dfinity/ok/generic-tail-rec.run.ok b/test/run-dfinity/ok/generic-tail-rec.run.ok deleted file mode 100644 index 6d96c93ceef..00000000000 --- a/test/run-dfinity/ok/generic-tail-rec.run.ok +++ /dev/null @@ -1,4 +0,0 @@ -done 1 -done 2 -done 3 -done 4 diff --git a/test/run-dfinity/generic-tail-rec.mo b/test/run-drun/generic-tail-rec.mo similarity index 80% rename from test/run-dfinity/generic-tail-rec.mo rename to test/run-drun/generic-tail-rec.mo index 20cc023222a..855b9110977 100644 --- a/test/run-dfinity/generic-tail-rec.mo +++ b/test/run-drun/generic-tail-rec.mo @@ -5,7 +5,7 @@ let bound:Int = 100000; { func Loop(n:Int){ if (n >= bound) { - debugPrint "done 1\n"; + debugPrint "done 1"; return; }; Loop(n+1); @@ -17,7 +17,7 @@ Loop(0); { func Loop(n:Int){ if (n >= bound) { - debugPrint "done 2\n"; + debugPrint "done 2"; return; }; return Loop(n+1); @@ -30,7 +30,7 @@ Loop(0); { func Loop(n:Int){ if (n >= bound) { - debugPrint "done 3\n"; + debugPrint "done 3"; return; }; Loop(n+1); @@ -42,7 +42,7 @@ Loop(0); { func Loop(n:Int){ if (n >= bound) { - debugPrint "done 4\n"; + debugPrint "done 4"; return; }; Loop(n+1); diff --git a/test/run-drun/ok/generic-tail-rec.drun-run.ok b/test/run-drun/ok/generic-tail-rec.drun-run.ok new file mode 100644 index 00000000000..86dfd61b593 --- /dev/null +++ b/test/run-drun/ok/generic-tail-rec.drun-run.ok @@ -0,0 +1,5 @@ +debug.print: done 1 +debug.print: done 2 +debug.print: done 3 +debug.print: done 4 +ingress(0) System diff --git a/test/run-drun/ok/generic-tail-rec.run-ir.ok b/test/run-drun/ok/generic-tail-rec.run-ir.ok new file mode 100644 index 00000000000..37779966f28 --- /dev/null +++ b/test/run-drun/ok/generic-tail-rec.run-ir.ok @@ -0,0 +1 @@ +done 1done 2done 3done 4 diff --git a/test/run-drun/ok/generic-tail-rec.run-low.ok b/test/run-drun/ok/generic-tail-rec.run-low.ok new file mode 100644 index 00000000000..37779966f28 --- /dev/null +++ b/test/run-drun/ok/generic-tail-rec.run-low.ok @@ -0,0 +1 @@ +done 1done 2done 3done 4 diff --git a/test/run-drun/ok/generic-tail-rec.run.ok b/test/run-drun/ok/generic-tail-rec.run.ok new file mode 100644 index 00000000000..37779966f28 --- /dev/null +++ b/test/run-drun/ok/generic-tail-rec.run.ok @@ -0,0 +1 @@ +done 1done 2done 3done 4 From da7d3589eadd948a44848ba3e4aedb9670ce5fbd Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 15 Nov 2019 09:41:57 +0100 Subject: [PATCH 0608/1176] Move a bunch of test cases from `drun-dfinity` to `run-drun` they use features we have there already --- test/run-dfinity/ok/counter2.dvm.ok | 8 - .../run-dfinity/ok/hello-world-message.dvm.ok | 2 - .../ok/hello-world-message2.dvm.ok | 2 - test/run-dfinity/ok/hello-world.dvm.ok | 1 - test/run-dfinity/ok/selftail.dvm.ok | 2 - test/run-dfinity/ok/show.dvm.ok | 35 --- test/run-dfinity/ok/tailpositions.dvm.ok | 7 - test/run-dfinity/ok/text-iter.dvm.ok | 18 -- test/run-dfinity/ok/the-answer.dvm.ok | 1 - test/{run-dfinity => run-drun}/arity_bug.mo | 0 test/{run-dfinity => run-drun}/counter2.mo | 0 .../hello-world-message.mo | 0 .../hello-world-message2.mo | 0 test/{run-dfinity => run-drun}/hello-world.mo | 0 test/{run-dfinity => run-drun}/large-mem.mo | 0 test/{run-dfinity => run-drun}/log-slow.mo | 0 test/{run-dfinity => run-drun}/modexp1.mo | 0 test/{run-dfinity => run-drun}/modexp2.mo | 0 test/{run-dfinity => run-drun}/modexp3.mo | 0 test/{run-dfinity => run-drun}/modexp4.mo | 0 test/{run-dfinity => run-drun}/modules-bwd.mo | 0 test/run-drun/ok/arity_bug.drun-run.ok | 1 + test/run-drun/ok/counter2.drun-run.ok | 2 + test/run-drun/ok/counter2.drun-run.ret.ok | 1 + .../ok/hello-world-message.drun-run.ok | 2 + .../ok/hello-world-message.drun-run.ret.ok | 1 + .../ok/hello-world-message2.drun-run.ok | 2 + .../ok/hello-world-message2.drun-run.ret.ok | 1 + test/run-drun/ok/hello-world.drun-run.ok | 3 + .../ok/hello-world.run-ir.ok | 0 .../ok/hello-world.run-low.ok | 0 .../ok/hello-world.run.ok | 0 test/run-drun/ok/large-mem.drun-run.ok | 1 + test/run-drun/ok/log-slow.drun-run.ok | 1 + test/run-drun/ok/modexp1.drun-run.ok | 1 + test/run-drun/ok/modexp2.drun-run.ok | 1 + test/run-drun/ok/modexp3.drun-run.ok | 1 + test/run-drun/ok/modexp4.drun-run.ok | 1 + test/run-drun/ok/modules-bwd.drun-run.ok | 1 + test/run-drun/ok/selftail.drun-run.ok | 5 + .../ok/selftail.run-ir.ok | 0 .../ok/selftail.run-low.ok | 0 .../ok/selftail.run.ok | 0 test/run-drun/ok/show.drun-run.ok | 71 +++++ .../ok/show.run-ir.ok | 0 .../ok/show.run-low.ok | 0 test/{run-dfinity => run-drun}/ok/show.run.ok | 0 test/run-drun/ok/tailpositions.drun-run.ok | 15 ++ .../ok/tailpositions.run-ir.ok | 0 .../ok/tailpositions.run-low.ok | 0 .../ok/tailpositions.run.ok | 0 test/run-drun/ok/text-iter.drun-run.ok | 253 ++++++++++++++++++ .../ok/text-iter.run-ir.ok | 0 .../ok/text-iter.run-low.ok | 0 .../ok/text-iter.run.ok | 0 test/run-drun/ok/the-answer.drun-run.ok | 2 + .../ok/the-answer.run-ir.ok | 0 .../ok/the-answer.run-low.ok | 0 .../ok/the-answer.run.ok | 0 test/{run-dfinity => run-drun}/selftail.mo | 0 test/{run-dfinity => run-drun}/show.mo | 0 .../tailpositions.mo | 0 test/{run-dfinity => run-drun}/text-iter.mo | 0 test/{run-dfinity => run-drun}/the-answer.mo | 0 64 files changed, 366 insertions(+), 76 deletions(-) delete mode 100644 test/run-dfinity/ok/counter2.dvm.ok delete mode 100644 test/run-dfinity/ok/hello-world-message.dvm.ok delete mode 100644 test/run-dfinity/ok/hello-world-message2.dvm.ok delete mode 100644 test/run-dfinity/ok/hello-world.dvm.ok delete mode 100644 test/run-dfinity/ok/selftail.dvm.ok delete mode 100644 test/run-dfinity/ok/show.dvm.ok delete mode 100644 test/run-dfinity/ok/tailpositions.dvm.ok delete mode 100644 test/run-dfinity/ok/text-iter.dvm.ok delete mode 100644 test/run-dfinity/ok/the-answer.dvm.ok rename test/{run-dfinity => run-drun}/arity_bug.mo (100%) rename test/{run-dfinity => run-drun}/counter2.mo (100%) rename test/{run-dfinity => run-drun}/hello-world-message.mo (100%) rename test/{run-dfinity => run-drun}/hello-world-message2.mo (100%) rename test/{run-dfinity => run-drun}/hello-world.mo (100%) rename test/{run-dfinity => run-drun}/large-mem.mo (100%) rename test/{run-dfinity => run-drun}/log-slow.mo (100%) rename test/{run-dfinity => run-drun}/modexp1.mo (100%) rename test/{run-dfinity => run-drun}/modexp2.mo (100%) rename test/{run-dfinity => run-drun}/modexp3.mo (100%) rename test/{run-dfinity => run-drun}/modexp4.mo (100%) rename test/{run-dfinity => run-drun}/modules-bwd.mo (100%) create mode 100644 test/run-drun/ok/arity_bug.drun-run.ok create mode 100644 test/run-drun/ok/counter2.drun-run.ok create mode 100644 test/run-drun/ok/counter2.drun-run.ret.ok create mode 100644 test/run-drun/ok/hello-world-message.drun-run.ok create mode 100644 test/run-drun/ok/hello-world-message.drun-run.ret.ok create mode 100644 test/run-drun/ok/hello-world-message2.drun-run.ok create mode 100644 test/run-drun/ok/hello-world-message2.drun-run.ret.ok create mode 100644 test/run-drun/ok/hello-world.drun-run.ok rename test/{run-dfinity => run-drun}/ok/hello-world.run-ir.ok (100%) rename test/{run-dfinity => run-drun}/ok/hello-world.run-low.ok (100%) rename test/{run-dfinity => run-drun}/ok/hello-world.run.ok (100%) create mode 100644 test/run-drun/ok/large-mem.drun-run.ok create mode 100644 test/run-drun/ok/log-slow.drun-run.ok create mode 100644 test/run-drun/ok/modexp1.drun-run.ok create mode 100644 test/run-drun/ok/modexp2.drun-run.ok create mode 100644 test/run-drun/ok/modexp3.drun-run.ok create mode 100644 test/run-drun/ok/modexp4.drun-run.ok create mode 100644 test/run-drun/ok/modules-bwd.drun-run.ok create mode 100644 test/run-drun/ok/selftail.drun-run.ok rename test/{run-dfinity => run-drun}/ok/selftail.run-ir.ok (100%) rename test/{run-dfinity => run-drun}/ok/selftail.run-low.ok (100%) rename test/{run-dfinity => run-drun}/ok/selftail.run.ok (100%) create mode 100644 test/run-drun/ok/show.drun-run.ok rename test/{run-dfinity => run-drun}/ok/show.run-ir.ok (100%) rename test/{run-dfinity => run-drun}/ok/show.run-low.ok (100%) rename test/{run-dfinity => run-drun}/ok/show.run.ok (100%) create mode 100644 test/run-drun/ok/tailpositions.drun-run.ok rename test/{run-dfinity => run-drun}/ok/tailpositions.run-ir.ok (100%) rename test/{run-dfinity => run-drun}/ok/tailpositions.run-low.ok (100%) rename test/{run-dfinity => run-drun}/ok/tailpositions.run.ok (100%) create mode 100644 test/run-drun/ok/text-iter.drun-run.ok rename test/{run-dfinity => run-drun}/ok/text-iter.run-ir.ok (100%) rename test/{run-dfinity => run-drun}/ok/text-iter.run-low.ok (100%) rename test/{run-dfinity => run-drun}/ok/text-iter.run.ok (100%) create mode 100644 test/run-drun/ok/the-answer.drun-run.ok rename test/{run-dfinity => run-drun}/ok/the-answer.run-ir.ok (100%) rename test/{run-dfinity => run-drun}/ok/the-answer.run-low.ok (100%) rename test/{run-dfinity => run-drun}/ok/the-answer.run.ok (100%) rename test/{run-dfinity => run-drun}/selftail.mo (100%) rename test/{run-dfinity => run-drun}/show.mo (100%) rename test/{run-dfinity => run-drun}/tailpositions.mo (100%) rename test/{run-dfinity => run-drun}/text-iter.mo (100%) rename test/{run-dfinity => run-drun}/the-answer.mo (100%) diff --git a/test/run-dfinity/ok/counter2.dvm.ok b/test/run-dfinity/ok/counter2.dvm.ok deleted file mode 100644 index ec8e4cf0a6f..00000000000 --- a/test/run-dfinity/ok/counter2.dvm.ok +++ /dev/null @@ -1,8 +0,0 @@ -DVM: Calling method inc 0x4449444C0000 [] -2 -DVM: Calling method inc 0x4449444C0000 [] -3 -DVM: Calling method inc 0x4449444C0000 [] -4 -DVM: Calling method printCounter 0x4449444C0000 [] -4 diff --git a/test/run-dfinity/ok/hello-world-message.dvm.ok b/test/run-dfinity/ok/hello-world-message.dvm.ok deleted file mode 100644 index 9d1c9e2b129..00000000000 --- a/test/run-dfinity/ok/hello-world-message.dvm.ok +++ /dev/null @@ -1,2 +0,0 @@ -DVM: Calling method hello 0x4449444C0000 [] -Hello World! diff --git a/test/run-dfinity/ok/hello-world-message2.dvm.ok b/test/run-dfinity/ok/hello-world-message2.dvm.ok deleted file mode 100644 index 9d1c9e2b129..00000000000 --- a/test/run-dfinity/ok/hello-world-message2.dvm.ok +++ /dev/null @@ -1,2 +0,0 @@ -DVM: Calling method hello 0x4449444C0000 [] -Hello World! diff --git a/test/run-dfinity/ok/hello-world.dvm.ok b/test/run-dfinity/ok/hello-world.dvm.ok deleted file mode 100644 index 980a0d5f19a..00000000000 --- a/test/run-dfinity/ok/hello-world.dvm.ok +++ /dev/null @@ -1 +0,0 @@ -Hello World! diff --git a/test/run-dfinity/ok/selftail.dvm.ok b/test/run-dfinity/ok/selftail.dvm.ok deleted file mode 100644 index acb397e19f2..00000000000 --- a/test/run-dfinity/ok/selftail.dvm.ok +++ /dev/null @@ -1,2 +0,0 @@ -ok1 -ok2 diff --git a/test/run-dfinity/ok/show.dvm.ok b/test/run-dfinity/ok/show.dvm.ok deleted file mode 100644 index 7f4f28dc1ee..00000000000 --- a/test/run-dfinity/ok/show.dvm.ok +++ /dev/null @@ -1,35 +0,0 @@ -true -false --42_000_000_000_000 --42_000_000 --42_000 --42 -0 -0 -+42 -+42_000 -+42_000_000 -+420_000_000_000_000 -0 -42 -42_000 -42_000_000 -420_000_000_000_000 -(42, -42, ()) -("Foobar", null, null, ?23) -[] -[1, 2, 3] -[var] -[var 1, 2, 3] -{bar = true; foo = +42} -#foo -#bar(1, 2) -#bar({}) -#bar([]) -#bar(42) -#bar(-42) -#foo(+42) -0x2A -42 -+42 --42 diff --git a/test/run-dfinity/ok/tailpositions.dvm.ok b/test/run-dfinity/ok/tailpositions.dvm.ok deleted file mode 100644 index 025c12b0e9a..00000000000 --- a/test/run-dfinity/ok/tailpositions.dvm.ok +++ /dev/null @@ -1,7 +0,0 @@ -done 1 -done 2 -done 3 -done 4 -done 5 -done 6 -done 7 diff --git a/test/run-dfinity/ok/text-iter.dvm.ok b/test/run-dfinity/ok/text-iter.dvm.ok deleted file mode 100644 index cdfd71bd534..00000000000 --- a/test/run-dfinity/ok/text-iter.dvm.ok +++ /dev/null @@ -1,18 +0,0 @@ -via `debugPrint`: -hello world! - -via iteration and `debugPrintChar`: #1 -hello world! - -via iteration and `debugPrintChar`: #2 -1:'h' 2:'e' 3:'l' 4:'l' 5:'o' 6:' ' 7:'w' 8:'o' 9:'r' 10:'l' 11:'d' 12:'!' 13:' -' -via iteration and `debugPrintChar` (Unicode): #3 -1:'П' 2:'р' 3:'и' 4:'в' 5:'е' 6:'т' 7:'с' 8:'т' 9:'в' 10:'у' 11:'ю' 12:',' 13:' ' 14:'м' 15:'и' 16:'р' 17:'!' 18:' -' -via iteration and `debugPrintChar` (Unicode): #4 -1:'🙈' 2:'🎸' 3:'😋' -Приветствую, мир! - -П -🙈 diff --git a/test/run-dfinity/ok/the-answer.dvm.ok b/test/run-dfinity/ok/the-answer.dvm.ok deleted file mode 100644 index d81cc0710eb..00000000000 --- a/test/run-dfinity/ok/the-answer.dvm.ok +++ /dev/null @@ -1 +0,0 @@ -42 diff --git a/test/run-dfinity/arity_bug.mo b/test/run-drun/arity_bug.mo similarity index 100% rename from test/run-dfinity/arity_bug.mo rename to test/run-drun/arity_bug.mo diff --git a/test/run-dfinity/counter2.mo b/test/run-drun/counter2.mo similarity index 100% rename from test/run-dfinity/counter2.mo rename to test/run-drun/counter2.mo diff --git a/test/run-dfinity/hello-world-message.mo b/test/run-drun/hello-world-message.mo similarity index 100% rename from test/run-dfinity/hello-world-message.mo rename to test/run-drun/hello-world-message.mo diff --git a/test/run-dfinity/hello-world-message2.mo b/test/run-drun/hello-world-message2.mo similarity index 100% rename from test/run-dfinity/hello-world-message2.mo rename to test/run-drun/hello-world-message2.mo diff --git a/test/run-dfinity/hello-world.mo b/test/run-drun/hello-world.mo similarity index 100% rename from test/run-dfinity/hello-world.mo rename to test/run-drun/hello-world.mo diff --git a/test/run-dfinity/large-mem.mo b/test/run-drun/large-mem.mo similarity index 100% rename from test/run-dfinity/large-mem.mo rename to test/run-drun/large-mem.mo diff --git a/test/run-dfinity/log-slow.mo b/test/run-drun/log-slow.mo similarity index 100% rename from test/run-dfinity/log-slow.mo rename to test/run-drun/log-slow.mo diff --git a/test/run-dfinity/modexp1.mo b/test/run-drun/modexp1.mo similarity index 100% rename from test/run-dfinity/modexp1.mo rename to test/run-drun/modexp1.mo diff --git a/test/run-dfinity/modexp2.mo b/test/run-drun/modexp2.mo similarity index 100% rename from test/run-dfinity/modexp2.mo rename to test/run-drun/modexp2.mo diff --git a/test/run-dfinity/modexp3.mo b/test/run-drun/modexp3.mo similarity index 100% rename from test/run-dfinity/modexp3.mo rename to test/run-drun/modexp3.mo diff --git a/test/run-dfinity/modexp4.mo b/test/run-drun/modexp4.mo similarity index 100% rename from test/run-dfinity/modexp4.mo rename to test/run-drun/modexp4.mo diff --git a/test/run-dfinity/modules-bwd.mo b/test/run-drun/modules-bwd.mo similarity index 100% rename from test/run-dfinity/modules-bwd.mo rename to test/run-drun/modules-bwd.mo diff --git a/test/run-drun/ok/arity_bug.drun-run.ok b/test/run-drun/ok/arity_bug.drun-run.ok new file mode 100644 index 00000000000..43d7af40394 --- /dev/null +++ b/test/run-drun/ok/arity_bug.drun-run.ok @@ -0,0 +1 @@ +ingress(0) System diff --git a/test/run-drun/ok/counter2.drun-run.ok b/test/run-drun/ok/counter2.drun-run.ok new file mode 100644 index 00000000000..ae5f39f9b7f --- /dev/null +++ b/test/run-drun/ok/counter2.drun-run.ok @@ -0,0 +1,2 @@ +ingress(0) System +Error: "Line 1: Illegal method name: 0x4449444C0000." diff --git a/test/run-drun/ok/counter2.drun-run.ret.ok b/test/run-drun/ok/counter2.drun-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/counter2.drun-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-drun/ok/hello-world-message.drun-run.ok b/test/run-drun/ok/hello-world-message.drun-run.ok new file mode 100644 index 00000000000..ae5f39f9b7f --- /dev/null +++ b/test/run-drun/ok/hello-world-message.drun-run.ok @@ -0,0 +1,2 @@ +ingress(0) System +Error: "Line 1: Illegal method name: 0x4449444C0000." diff --git a/test/run-drun/ok/hello-world-message.drun-run.ret.ok b/test/run-drun/ok/hello-world-message.drun-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/hello-world-message.drun-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-drun/ok/hello-world-message2.drun-run.ok b/test/run-drun/ok/hello-world-message2.drun-run.ok new file mode 100644 index 00000000000..ae5f39f9b7f --- /dev/null +++ b/test/run-drun/ok/hello-world-message2.drun-run.ok @@ -0,0 +1,2 @@ +ingress(0) System +Error: "Line 1: Illegal method name: 0x4449444C0000." diff --git a/test/run-drun/ok/hello-world-message2.drun-run.ret.ok b/test/run-drun/ok/hello-world-message2.drun-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/hello-world-message2.drun-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-drun/ok/hello-world.drun-run.ok b/test/run-drun/ok/hello-world.drun-run.ok new file mode 100644 index 00000000000..4c3030d0fee --- /dev/null +++ b/test/run-drun/ok/hello-world.drun-run.ok @@ -0,0 +1,3 @@ +debug.print: Hello World! + +ingress(0) System diff --git a/test/run-dfinity/ok/hello-world.run-ir.ok b/test/run-drun/ok/hello-world.run-ir.ok similarity index 100% rename from test/run-dfinity/ok/hello-world.run-ir.ok rename to test/run-drun/ok/hello-world.run-ir.ok diff --git a/test/run-dfinity/ok/hello-world.run-low.ok b/test/run-drun/ok/hello-world.run-low.ok similarity index 100% rename from test/run-dfinity/ok/hello-world.run-low.ok rename to test/run-drun/ok/hello-world.run-low.ok diff --git a/test/run-dfinity/ok/hello-world.run.ok b/test/run-drun/ok/hello-world.run.ok similarity index 100% rename from test/run-dfinity/ok/hello-world.run.ok rename to test/run-drun/ok/hello-world.run.ok diff --git a/test/run-drun/ok/large-mem.drun-run.ok b/test/run-drun/ok/large-mem.drun-run.ok new file mode 100644 index 00000000000..43d7af40394 --- /dev/null +++ b/test/run-drun/ok/large-mem.drun-run.ok @@ -0,0 +1 @@ +ingress(0) System diff --git a/test/run-drun/ok/log-slow.drun-run.ok b/test/run-drun/ok/log-slow.drun-run.ok new file mode 100644 index 00000000000..43d7af40394 --- /dev/null +++ b/test/run-drun/ok/log-slow.drun-run.ok @@ -0,0 +1 @@ +ingress(0) System diff --git a/test/run-drun/ok/modexp1.drun-run.ok b/test/run-drun/ok/modexp1.drun-run.ok new file mode 100644 index 00000000000..43d7af40394 --- /dev/null +++ b/test/run-drun/ok/modexp1.drun-run.ok @@ -0,0 +1 @@ +ingress(0) System diff --git a/test/run-drun/ok/modexp2.drun-run.ok b/test/run-drun/ok/modexp2.drun-run.ok new file mode 100644 index 00000000000..43d7af40394 --- /dev/null +++ b/test/run-drun/ok/modexp2.drun-run.ok @@ -0,0 +1 @@ +ingress(0) System diff --git a/test/run-drun/ok/modexp3.drun-run.ok b/test/run-drun/ok/modexp3.drun-run.ok new file mode 100644 index 00000000000..43d7af40394 --- /dev/null +++ b/test/run-drun/ok/modexp3.drun-run.ok @@ -0,0 +1 @@ +ingress(0) System diff --git a/test/run-drun/ok/modexp4.drun-run.ok b/test/run-drun/ok/modexp4.drun-run.ok new file mode 100644 index 00000000000..43d7af40394 --- /dev/null +++ b/test/run-drun/ok/modexp4.drun-run.ok @@ -0,0 +1 @@ +ingress(0) System diff --git a/test/run-drun/ok/modules-bwd.drun-run.ok b/test/run-drun/ok/modules-bwd.drun-run.ok new file mode 100644 index 00000000000..43d7af40394 --- /dev/null +++ b/test/run-drun/ok/modules-bwd.drun-run.ok @@ -0,0 +1 @@ +ingress(0) System diff --git a/test/run-drun/ok/selftail.drun-run.ok b/test/run-drun/ok/selftail.drun-run.ok new file mode 100644 index 00000000000..7c9d2a30e8b --- /dev/null +++ b/test/run-drun/ok/selftail.drun-run.ok @@ -0,0 +1,5 @@ +debug.print: ok1 + +debug.print: ok2 + +ingress(0) System diff --git a/test/run-dfinity/ok/selftail.run-ir.ok b/test/run-drun/ok/selftail.run-ir.ok similarity index 100% rename from test/run-dfinity/ok/selftail.run-ir.ok rename to test/run-drun/ok/selftail.run-ir.ok diff --git a/test/run-dfinity/ok/selftail.run-low.ok b/test/run-drun/ok/selftail.run-low.ok similarity index 100% rename from test/run-dfinity/ok/selftail.run-low.ok rename to test/run-drun/ok/selftail.run-low.ok diff --git a/test/run-dfinity/ok/selftail.run.ok b/test/run-drun/ok/selftail.run.ok similarity index 100% rename from test/run-dfinity/ok/selftail.run.ok rename to test/run-drun/ok/selftail.run.ok diff --git a/test/run-drun/ok/show.drun-run.ok b/test/run-drun/ok/show.drun-run.ok new file mode 100644 index 00000000000..a7ab5d6aa08 --- /dev/null +++ b/test/run-drun/ok/show.drun-run.ok @@ -0,0 +1,71 @@ +debug.print: true + +debug.print: false + +debug.print: -42_000_000_000_000 + +debug.print: -42_000_000 + +debug.print: -42_000 + +debug.print: -42 + +debug.print: 0 + +debug.print: 0 + +debug.print: +42 + +debug.print: +42_000 + +debug.print: +42_000_000 + +debug.print: +420_000_000_000_000 + +debug.print: 0 + +debug.print: 42 + +debug.print: 42_000 + +debug.print: 42_000_000 + +debug.print: 420_000_000_000_000 + +debug.print: (42, -42, ()) + +debug.print: ("Foobar", null, null, ?23) + +debug.print: [] + +debug.print: [1, 2, 3] + +debug.print: [var] + +debug.print: [var 1, 2, 3] + +debug.print: {bar = true; foo = +42} + +debug.print: #foo + +debug.print: #bar(1, 2) + +debug.print: #bar({}) + +debug.print: #bar([]) + +debug.print: #bar(42) + +debug.print: #bar(-42) + +debug.print: #foo(+42) + +debug.print: 0x2A + +debug.print: 42 + +debug.print: +42 + +debug.print: -42 + +ingress(0) System diff --git a/test/run-dfinity/ok/show.run-ir.ok b/test/run-drun/ok/show.run-ir.ok similarity index 100% rename from test/run-dfinity/ok/show.run-ir.ok rename to test/run-drun/ok/show.run-ir.ok diff --git a/test/run-dfinity/ok/show.run-low.ok b/test/run-drun/ok/show.run-low.ok similarity index 100% rename from test/run-dfinity/ok/show.run-low.ok rename to test/run-drun/ok/show.run-low.ok diff --git a/test/run-dfinity/ok/show.run.ok b/test/run-drun/ok/show.run.ok similarity index 100% rename from test/run-dfinity/ok/show.run.ok rename to test/run-drun/ok/show.run.ok diff --git a/test/run-drun/ok/tailpositions.drun-run.ok b/test/run-drun/ok/tailpositions.drun-run.ok new file mode 100644 index 00000000000..f4ea4aa55fd --- /dev/null +++ b/test/run-drun/ok/tailpositions.drun-run.ok @@ -0,0 +1,15 @@ +debug.print: done 1 + +debug.print: done 2 + +debug.print: done 3 + +debug.print: done 4 + +debug.print: done 5 + +debug.print: done 6 + +debug.print: done 7 + +ingress(0) System diff --git a/test/run-dfinity/ok/tailpositions.run-ir.ok b/test/run-drun/ok/tailpositions.run-ir.ok similarity index 100% rename from test/run-dfinity/ok/tailpositions.run-ir.ok rename to test/run-drun/ok/tailpositions.run-ir.ok diff --git a/test/run-dfinity/ok/tailpositions.run-low.ok b/test/run-drun/ok/tailpositions.run-low.ok similarity index 100% rename from test/run-dfinity/ok/tailpositions.run-low.ok rename to test/run-drun/ok/tailpositions.run-low.ok diff --git a/test/run-dfinity/ok/tailpositions.run.ok b/test/run-drun/ok/tailpositions.run.ok similarity index 100% rename from test/run-dfinity/ok/tailpositions.run.ok rename to test/run-drun/ok/tailpositions.run.ok diff --git a/test/run-drun/ok/text-iter.drun-run.ok b/test/run-drun/ok/text-iter.drun-run.ok new file mode 100644 index 00000000000..d7516f24c11 --- /dev/null +++ b/test/run-drun/ok/text-iter.drun-run.ok @@ -0,0 +1,253 @@ +debug.print: via `debugPrint`: + +debug.print: hello world! + +debug.print: + +debug.print: via iteration and `debugPrintChar`: #1 + +debug.print: h +debug.print: e +debug.print: l +debug.print: l +debug.print: o +debug.print: +debug.print: w +debug.print: o +debug.print: r +debug.print: l +debug.print: d +debug.print: ! +debug.print: + +debug.print: + +debug.print: via iteration and `debugPrintChar`: #2 + +debug.print: 1 +debug.print: : +debug.print: ' +debug.print: h +debug.print: ' +debug.print: +debug.print: 2 +debug.print: : +debug.print: ' +debug.print: e +debug.print: ' +debug.print: +debug.print: 3 +debug.print: : +debug.print: ' +debug.print: l +debug.print: ' +debug.print: +debug.print: 4 +debug.print: : +debug.print: ' +debug.print: l +debug.print: ' +debug.print: +debug.print: 5 +debug.print: : +debug.print: ' +debug.print: o +debug.print: ' +debug.print: +debug.print: 6 +debug.print: : +debug.print: ' +debug.print: +debug.print: ' +debug.print: +debug.print: 7 +debug.print: : +debug.print: ' +debug.print: w +debug.print: ' +debug.print: +debug.print: 8 +debug.print: : +debug.print: ' +debug.print: o +debug.print: ' +debug.print: +debug.print: 9 +debug.print: : +debug.print: ' +debug.print: r +debug.print: ' +debug.print: +debug.print: 10 +debug.print: : +debug.print: ' +debug.print: l +debug.print: ' +debug.print: +debug.print: 11 +debug.print: : +debug.print: ' +debug.print: d +debug.print: ' +debug.print: +debug.print: 12 +debug.print: : +debug.print: ' +debug.print: ! +debug.print: ' +debug.print: +debug.print: 13 +debug.print: : +debug.print: ' +debug.print: + +debug.print: ' +debug.print: +debug.print: + +debug.print: via iteration and `debugPrintChar` (Unicode): #3 + +debug.print: 1 +debug.print: : +debug.print: ' +debug.print: П +debug.print: ' +debug.print: +debug.print: 2 +debug.print: : +debug.print: ' +debug.print: р +debug.print: ' +debug.print: +debug.print: 3 +debug.print: : +debug.print: ' +debug.print: и +debug.print: ' +debug.print: +debug.print: 4 +debug.print: : +debug.print: ' +debug.print: в +debug.print: ' +debug.print: +debug.print: 5 +debug.print: : +debug.print: ' +debug.print: е +debug.print: ' +debug.print: +debug.print: 6 +debug.print: : +debug.print: ' +debug.print: т +debug.print: ' +debug.print: +debug.print: 7 +debug.print: : +debug.print: ' +debug.print: с +debug.print: ' +debug.print: +debug.print: 8 +debug.print: : +debug.print: ' +debug.print: т +debug.print: ' +debug.print: +debug.print: 9 +debug.print: : +debug.print: ' +debug.print: в +debug.print: ' +debug.print: +debug.print: 10 +debug.print: : +debug.print: ' +debug.print: у +debug.print: ' +debug.print: +debug.print: 11 +debug.print: : +debug.print: ' +debug.print: ю +debug.print: ' +debug.print: +debug.print: 12 +debug.print: : +debug.print: ' +debug.print: , +debug.print: ' +debug.print: +debug.print: 13 +debug.print: : +debug.print: ' +debug.print: +debug.print: ' +debug.print: +debug.print: 14 +debug.print: : +debug.print: ' +debug.print: м +debug.print: ' +debug.print: +debug.print: 15 +debug.print: : +debug.print: ' +debug.print: и +debug.print: ' +debug.print: +debug.print: 16 +debug.print: : +debug.print: ' +debug.print: р +debug.print: ' +debug.print: +debug.print: 17 +debug.print: : +debug.print: ' +debug.print: ! +debug.print: ' +debug.print: +debug.print: 18 +debug.print: : +debug.print: ' +debug.print: + +debug.print: ' +debug.print: +debug.print: + +debug.print: via iteration and `debugPrintChar` (Unicode): #4 + +debug.print: 1 +debug.print: : +debug.print: ' +debug.print: 🙈 +debug.print: ' +debug.print: +debug.print: 2 +debug.print: : +debug.print: ' +debug.print: 🎸 +debug.print: ' +debug.print: +debug.print: 3 +debug.print: : +debug.print: ' +debug.print: 😋 +debug.print: ' +debug.print: +debug.print: + +debug.print: Приветствую, мир! + +debug.print: + +debug.print: П +debug.print: + +debug.print: 🙈 +debug.print: + +ingress(0) System diff --git a/test/run-dfinity/ok/text-iter.run-ir.ok b/test/run-drun/ok/text-iter.run-ir.ok similarity index 100% rename from test/run-dfinity/ok/text-iter.run-ir.ok rename to test/run-drun/ok/text-iter.run-ir.ok diff --git a/test/run-dfinity/ok/text-iter.run-low.ok b/test/run-drun/ok/text-iter.run-low.ok similarity index 100% rename from test/run-dfinity/ok/text-iter.run-low.ok rename to test/run-drun/ok/text-iter.run-low.ok diff --git a/test/run-dfinity/ok/text-iter.run.ok b/test/run-drun/ok/text-iter.run.ok similarity index 100% rename from test/run-dfinity/ok/text-iter.run.ok rename to test/run-drun/ok/text-iter.run.ok diff --git a/test/run-drun/ok/the-answer.drun-run.ok b/test/run-drun/ok/the-answer.drun-run.ok new file mode 100644 index 00000000000..3a0919de67b --- /dev/null +++ b/test/run-drun/ok/the-answer.drun-run.ok @@ -0,0 +1,2 @@ +debug.print: 42 +ingress(0) System diff --git a/test/run-dfinity/ok/the-answer.run-ir.ok b/test/run-drun/ok/the-answer.run-ir.ok similarity index 100% rename from test/run-dfinity/ok/the-answer.run-ir.ok rename to test/run-drun/ok/the-answer.run-ir.ok diff --git a/test/run-dfinity/ok/the-answer.run-low.ok b/test/run-drun/ok/the-answer.run-low.ok similarity index 100% rename from test/run-dfinity/ok/the-answer.run-low.ok rename to test/run-drun/ok/the-answer.run-low.ok diff --git a/test/run-dfinity/ok/the-answer.run.ok b/test/run-drun/ok/the-answer.run.ok similarity index 100% rename from test/run-dfinity/ok/the-answer.run.ok rename to test/run-drun/ok/the-answer.run.ok diff --git a/test/run-dfinity/selftail.mo b/test/run-drun/selftail.mo similarity index 100% rename from test/run-dfinity/selftail.mo rename to test/run-drun/selftail.mo diff --git a/test/run-dfinity/show.mo b/test/run-drun/show.mo similarity index 100% rename from test/run-dfinity/show.mo rename to test/run-drun/show.mo diff --git a/test/run-dfinity/tailpositions.mo b/test/run-drun/tailpositions.mo similarity index 100% rename from test/run-dfinity/tailpositions.mo rename to test/run-drun/tailpositions.mo diff --git a/test/run-dfinity/text-iter.mo b/test/run-drun/text-iter.mo similarity index 100% rename from test/run-dfinity/text-iter.mo rename to test/run-drun/text-iter.mo diff --git a/test/run-dfinity/the-answer.mo b/test/run-drun/the-answer.mo similarity index 100% rename from test/run-dfinity/the-answer.mo rename to test/run-drun/the-answer.mo From 16dfd6a364f0f894296a687e713fe52e9015ee58 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 15 Nov 2019 09:35:13 +0100 Subject: [PATCH 0609/1176] =?UTF-8?q?In=20`run-dfinity`,=20delete=20`fac`,?= =?UTF-8?q?=20`hello-concat-world`,=20`idl-tuple`,=20=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit and some others. These test cases don’t add much value. foo --- test/run-dfinity/fac.mo | 6 ------ test/run-dfinity/hello-concat-world.mo | 1 - test/run-dfinity/idl-tuple.mo | 9 --------- test/run-dfinity/ok/fac.dvm.ok | 1 - test/run-dfinity/ok/fac.run-ir.ok | 1 - test/run-dfinity/ok/fac.run-low.ok | 1 - test/run-dfinity/ok/fac.run.ok | 1 - test/run-dfinity/ok/hello-concat-world.dvm.ok | 1 - test/run-dfinity/ok/hello-concat-world.run-ir.ok | 1 - test/run-dfinity/ok/hello-concat-world.run-low.ok | 1 - test/run-dfinity/ok/hello-concat-world.run.ok | 1 - test/run-dfinity/tiny.mo | 8 -------- 12 files changed, 32 deletions(-) delete mode 100644 test/run-dfinity/fac.mo delete mode 100644 test/run-dfinity/hello-concat-world.mo delete mode 100644 test/run-dfinity/idl-tuple.mo delete mode 100644 test/run-dfinity/ok/fac.dvm.ok delete mode 100644 test/run-dfinity/ok/fac.run-ir.ok delete mode 100644 test/run-dfinity/ok/fac.run-low.ok delete mode 100644 test/run-dfinity/ok/fac.run.ok delete mode 100644 test/run-dfinity/ok/hello-concat-world.dvm.ok delete mode 100644 test/run-dfinity/ok/hello-concat-world.run-ir.ok delete mode 100644 test/run-dfinity/ok/hello-concat-world.run-low.ok delete mode 100644 test/run-dfinity/ok/hello-concat-world.run.ok delete mode 100644 test/run-dfinity/tiny.mo diff --git a/test/run-dfinity/fac.mo b/test/run-dfinity/fac.mo deleted file mode 100644 index 71a68ac3876..00000000000 --- a/test/run-dfinity/fac.mo +++ /dev/null @@ -1,6 +0,0 @@ -func fac(n : Nat) : Nat { - if (n == 0) return(1); - n * fac (n-1); -}; - -debugPrintNat(fac 5); diff --git a/test/run-dfinity/hello-concat-world.mo b/test/run-dfinity/hello-concat-world.mo deleted file mode 100644 index 7109163143b..00000000000 --- a/test/run-dfinity/hello-concat-world.mo +++ /dev/null @@ -1 +0,0 @@ -debugPrint("Hello " # "World!\n"); diff --git a/test/run-dfinity/idl-tuple.mo b/test/run-dfinity/idl-tuple.mo deleted file mode 100644 index b78782d33a9..00000000000 --- a/test/run-dfinity/idl-tuple.mo +++ /dev/null @@ -1,9 +0,0 @@ -let a = actor { - public func len2() : async (Int,Int) { - (23, 42) - } -}; - -a.len2(); - -// CALL len2 0x4449444c016a027c7c00000100 [console:logAny] diff --git a/test/run-dfinity/ok/fac.dvm.ok b/test/run-dfinity/ok/fac.dvm.ok deleted file mode 100644 index 52bd8e43afb..00000000000 --- a/test/run-dfinity/ok/fac.dvm.ok +++ /dev/null @@ -1 +0,0 @@ -120 diff --git a/test/run-dfinity/ok/fac.run-ir.ok b/test/run-dfinity/ok/fac.run-ir.ok deleted file mode 100644 index 52bd8e43afb..00000000000 --- a/test/run-dfinity/ok/fac.run-ir.ok +++ /dev/null @@ -1 +0,0 @@ -120 diff --git a/test/run-dfinity/ok/fac.run-low.ok b/test/run-dfinity/ok/fac.run-low.ok deleted file mode 100644 index 52bd8e43afb..00000000000 --- a/test/run-dfinity/ok/fac.run-low.ok +++ /dev/null @@ -1 +0,0 @@ -120 diff --git a/test/run-dfinity/ok/fac.run.ok b/test/run-dfinity/ok/fac.run.ok deleted file mode 100644 index 52bd8e43afb..00000000000 --- a/test/run-dfinity/ok/fac.run.ok +++ /dev/null @@ -1 +0,0 @@ -120 diff --git a/test/run-dfinity/ok/hello-concat-world.dvm.ok b/test/run-dfinity/ok/hello-concat-world.dvm.ok deleted file mode 100644 index 980a0d5f19a..00000000000 --- a/test/run-dfinity/ok/hello-concat-world.dvm.ok +++ /dev/null @@ -1 +0,0 @@ -Hello World! diff --git a/test/run-dfinity/ok/hello-concat-world.run-ir.ok b/test/run-dfinity/ok/hello-concat-world.run-ir.ok deleted file mode 100644 index 980a0d5f19a..00000000000 --- a/test/run-dfinity/ok/hello-concat-world.run-ir.ok +++ /dev/null @@ -1 +0,0 @@ -Hello World! diff --git a/test/run-dfinity/ok/hello-concat-world.run-low.ok b/test/run-dfinity/ok/hello-concat-world.run-low.ok deleted file mode 100644 index 980a0d5f19a..00000000000 --- a/test/run-dfinity/ok/hello-concat-world.run-low.ok +++ /dev/null @@ -1 +0,0 @@ -Hello World! diff --git a/test/run-dfinity/ok/hello-concat-world.run.ok b/test/run-dfinity/ok/hello-concat-world.run.ok deleted file mode 100644 index 980a0d5f19a..00000000000 --- a/test/run-dfinity/ok/hello-concat-world.run.ok +++ /dev/null @@ -1 +0,0 @@ -Hello World! diff --git a/test/run-dfinity/tiny.mo b/test/run-dfinity/tiny.mo deleted file mode 100644 index 847802eec64..00000000000 --- a/test/run-dfinity/tiny.mo +++ /dev/null @@ -1,8 +0,0 @@ -// This file only exercises local throws that don't cross function boundaries. -// In principle, it should run on all targets. - -async { -}; - - - From e602d617079f31c67eee24ac29864b86d3c730af Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 15 Nov 2019 11:09:17 +0100 Subject: [PATCH 0610/1176] New flag -hide-warnings (#873) The main purpose of this is to make our test suite less nosiy. Every test case is first type-checked and then run in various modes. If there are type checker warnings, but no errors (usually due to partial patterns, I am looking at you, @crusso ;-)), we get these warnings in the test suite output many times. This flags allows us to make sure that running/compiling files is actually silent. This is in particularly useful as empty output file are not even stored by the test runner, so we have less files. Which is good. --- src/exes/moc.ml | 4 +- src/lang_utils/diag.ml | 6 +- src/lang_utils/dune | 2 +- src/mo_config/flags.ml | 1 + test/run-dfinity/ok/data-params.comp.ok | 4 - test/run-dfinity/ok/data-params.run-ir.ok | 4 - test/run-dfinity/ok/data-params.run-low.ok | 4 - test/run-dfinity/ok/data-params.run.ok | 4 - .../run-dfinity/ok/flatten-awaitables.comp.ok | 120 ------------------ .../ok/flatten-awaitables.run-ir.ok | 120 ------------------ .../ok/flatten-awaitables.run-low.ok | 120 ------------------ test/run-dfinity/ok/flatten-awaitables.run.ok | 120 ------------------ test/run-drun/ok/ic-calls.comp.ok | 9 -- test/run-drun/ok/ic-calls.run-ir.ok | 9 -- test/run-drun/ok/ic-calls.run-low.ok | 9 -- test/run-drun/ok/ic-calls.run.ok | 9 -- test/run.sh | 8 +- test/run/ok/coverage.comp.ok | 73 ----------- test/run/ok/coverage.run-ir.ok | 73 ----------- test/run/ok/coverage.run-low.ok | 73 ----------- test/run/ok/coverage.run.ok | 73 ----------- test/run/ok/issue442.comp.ok | 6 - test/run/ok/issue442.run-ir.ok | 6 - test/run/ok/issue442.run-low.ok | 6 - test/run/ok/issue442.run.ok | 6 - test/run/ok/large-tuple.comp.ok | 23 ---- test/run/ok/large-tuple.run-ir.ok | 23 ---- test/run/ok/large-tuple.run-low.ok | 23 ---- test/run/ok/large-tuple.run.ok | 23 ---- test/run/ok/objects1.comp.ok | 8 -- test/run/ok/objects1.run-ir.ok | 8 -- test/run/ok/objects1.run-low.ok | 8 -- test/run/ok/objects1.run.ok | 8 -- test/run/ok/switch.comp.ok | 16 --- test/run/ok/switch.run-ir.ok | 16 --- test/run/ok/switch.run-low.ok | 16 --- test/run/ok/switch.run.ok | 16 --- test/run/ok/type-inference.comp.ok | 37 ------ test/run/ok/type-inference.run-ir.ok | 37 ------ test/run/ok/type-inference.run-low.ok | 37 ------ test/run/ok/type-inference.run.ok | 37 ------ 41 files changed, 14 insertions(+), 1191 deletions(-) delete mode 100644 test/run-dfinity/ok/data-params.comp.ok delete mode 100644 test/run-dfinity/ok/flatten-awaitables.comp.ok delete mode 100644 test/run-drun/ok/ic-calls.run-ir.ok delete mode 100644 test/run-drun/ok/ic-calls.run-low.ok delete mode 100644 test/run-drun/ok/ic-calls.run.ok delete mode 100644 test/run/ok/issue442.comp.ok delete mode 100644 test/run/ok/issue442.run-ir.ok delete mode 100644 test/run/ok/issue442.run-low.ok delete mode 100644 test/run/ok/issue442.run.ok delete mode 100644 test/run/ok/large-tuple.comp.ok delete mode 100644 test/run/ok/large-tuple.run-ir.ok delete mode 100644 test/run/ok/large-tuple.run-low.ok delete mode 100644 test/run/ok/large-tuple.run.ok delete mode 100644 test/run/ok/type-inference.run-ir.ok delete mode 100644 test/run/ok/type-inference.run-low.ok delete mode 100644 test/run/ok/type-inference.run.ok diff --git a/src/exes/moc.ml b/src/exes/moc.ml index 31b6c27edf0..f2fb40a9261 100644 --- a/src/exes/moc.ml +++ b/src/exes/moc.ml @@ -35,9 +35,11 @@ let argspec = Arg.align "-i", Arg.Unit (set_mode Interact), " run interactive REPL (implies -r)"; "--check", Arg.Unit (set_mode Check), " type-check only"; "--idl", Arg.Unit (set_mode Idl), " generate IDL spec"; + "-o", Arg.Set_string out_file, " output file"; + "-v", Arg.Set Flags.verbose, " verbose output"; "-p", Arg.Set_int Flags.print_depth, " set print depth"; - "-o", Arg.Set_string out_file, " output file"; + "--hide-warnings", Arg.Clear Flags.print_warnings, " hide warnings"; "--version", Arg.Unit (fun () -> printf "%s\n%!" banner; exit 0), " show version"; diff --git a/src/lang_utils/diag.ml b/src/lang_utils/diag.ml index d4dd3cd1f4c..7ba7e8bb5e3 100644 --- a/src/lang_utils/diag.ml +++ b/src/lang_utils/diag.ml @@ -1,3 +1,5 @@ +open Mo_config + type severity = Warning | Error type message = { sev : severity; @@ -50,7 +52,9 @@ let string_of_message msg = Printf.sprintf "%s: %s, %s\n" (Source.string_of_region msg.at) label msg.text let print_message msg = - Printf.eprintf "%s%!" (string_of_message msg) + if msg.sev = Warning && not !Flags.print_warnings + then () + else Printf.eprintf "%s%!" (string_of_message msg) let print_messages = List.iter print_message diff --git a/src/lang_utils/dune b/src/lang_utils/dune index 00d153bb761..1a6e872e19d 100644 --- a/src/lang_utils/dune +++ b/src/lang_utils/dune @@ -1,5 +1,5 @@ (library (name lang_utils) - (libraries lib) + (libraries lib mo_config) (wrapped false) ) diff --git a/src/mo_config/flags.ml b/src/mo_config/flags.ml index 0c8fcd1294f..89e549a704b 100644 --- a/src/mo_config/flags.ml +++ b/src/mo_config/flags.ml @@ -4,6 +4,7 @@ type compile_mode = WasmMode | AncientMode | ICMode let trace = ref false let verbose = ref false +let print_warnings = ref true let print_depth = ref 2 let release_mode = ref false let compile_mode = ref ICMode diff --git a/test/run-dfinity/ok/data-params.comp.ok b/test/run-dfinity/ok/data-params.comp.ok deleted file mode 100644 index 4f513b4d81a..00000000000 --- a/test/run-dfinity/ok/data-params.comp.ok +++ /dev/null @@ -1,4 +0,0 @@ -data-params.mo:59.30-59.40: warning, this pattern consuming type - ?Text -does not cover value - null diff --git a/test/run-dfinity/ok/data-params.run-ir.ok b/test/run-dfinity/ok/data-params.run-ir.ok index 78262242d6f..732e96d5e47 100644 --- a/test/run-dfinity/ok/data-params.run-ir.ok +++ b/test/run-dfinity/ok/data-params.run-ir.ok @@ -1,7 +1,3 @@ -data-params.mo:59.30-59.40: warning, this pattern consuming type - ?Text -does not cover value - null 0 +1 +3 diff --git a/test/run-dfinity/ok/data-params.run-low.ok b/test/run-dfinity/ok/data-params.run-low.ok index 78262242d6f..732e96d5e47 100644 --- a/test/run-dfinity/ok/data-params.run-low.ok +++ b/test/run-dfinity/ok/data-params.run-low.ok @@ -1,7 +1,3 @@ -data-params.mo:59.30-59.40: warning, this pattern consuming type - ?Text -does not cover value - null 0 +1 +3 diff --git a/test/run-dfinity/ok/data-params.run.ok b/test/run-dfinity/ok/data-params.run.ok index 78262242d6f..732e96d5e47 100644 --- a/test/run-dfinity/ok/data-params.run.ok +++ b/test/run-dfinity/ok/data-params.run.ok @@ -1,7 +1,3 @@ -data-params.mo:59.30-59.40: warning, this pattern consuming type - ?Text -does not cover value - null 0 +1 +3 diff --git a/test/run-dfinity/ok/flatten-awaitables.comp.ok b/test/run-dfinity/ok/flatten-awaitables.comp.ok deleted file mode 100644 index 4734a23a649..00000000000 --- a/test/run-dfinity/ok/flatten-awaitables.comp.ok +++ /dev/null @@ -1,120 +0,0 @@ -flatten-awaitables.mo:43.9-43.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:45.9-45.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:47.9-47.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) -flatten-awaitables.mo:52.9-52.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:54.9-54.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:56.9-56.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) -flatten-awaitables.mo:66.9-66.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:68.9-68.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:70.9-70.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) -flatten-awaitables.mo:75.9-75.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:77.9-77.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:79.9-79.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) -flatten-awaitables.mo:85.9-85.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:87.9-87.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:89.9-89.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) -flatten-awaitables.mo:94.9-94.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:96.9-96.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:98.9-98.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) -flatten-awaitables.mo:103.9-103.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:105.9-105.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:107.9-107.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) -flatten-awaitables.mo:112.9-112.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:114.9-114.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:116.9-116.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) diff --git a/test/run-dfinity/ok/flatten-awaitables.run-ir.ok b/test/run-dfinity/ok/flatten-awaitables.run-ir.ok index 71bc01633c6..4c1b1bd6651 100644 --- a/test/run-dfinity/ok/flatten-awaitables.run-ir.ok +++ b/test/run-dfinity/ok/flatten-awaitables.run-ir.ok @@ -1,123 +1,3 @@ -flatten-awaitables.mo:43.9-43.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:45.9-45.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:47.9-47.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) -flatten-awaitables.mo:52.9-52.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:54.9-54.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:56.9-56.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) -flatten-awaitables.mo:66.9-66.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:68.9-68.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:70.9-70.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) -flatten-awaitables.mo:75.9-75.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:77.9-77.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:79.9-79.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) -flatten-awaitables.mo:85.9-85.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:87.9-87.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:89.9-89.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) -flatten-awaitables.mo:94.9-94.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:96.9-96.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:98.9-98.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) -flatten-awaitables.mo:103.9-103.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:105.9-105.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:107.9-107.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) -flatten-awaitables.mo:112.9-112.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:114.9-114.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:116.9-116.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) first-order ,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, diff --git a/test/run-dfinity/ok/flatten-awaitables.run-low.ok b/test/run-dfinity/ok/flatten-awaitables.run-low.ok index 71bc01633c6..4c1b1bd6651 100644 --- a/test/run-dfinity/ok/flatten-awaitables.run-low.ok +++ b/test/run-dfinity/ok/flatten-awaitables.run-low.ok @@ -1,123 +1,3 @@ -flatten-awaitables.mo:43.9-43.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:45.9-45.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:47.9-47.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) -flatten-awaitables.mo:52.9-52.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:54.9-54.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:56.9-56.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) -flatten-awaitables.mo:66.9-66.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:68.9-68.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:70.9-70.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) -flatten-awaitables.mo:75.9-75.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:77.9-77.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:79.9-79.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) -flatten-awaitables.mo:85.9-85.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:87.9-87.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:89.9-89.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) -flatten-awaitables.mo:94.9-94.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:96.9-96.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:98.9-98.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) -flatten-awaitables.mo:103.9-103.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:105.9-105.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:107.9-107.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) -flatten-awaitables.mo:112.9-112.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:114.9-114.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:116.9-116.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) first-order ,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, diff --git a/test/run-dfinity/ok/flatten-awaitables.run.ok b/test/run-dfinity/ok/flatten-awaitables.run.ok index 71bc01633c6..4c1b1bd6651 100644 --- a/test/run-dfinity/ok/flatten-awaitables.run.ok +++ b/test/run-dfinity/ok/flatten-awaitables.run.ok @@ -1,123 +1,3 @@ -flatten-awaitables.mo:43.9-43.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:45.9-45.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:47.9-47.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) -flatten-awaitables.mo:52.9-52.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:54.9-54.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:56.9-56.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) -flatten-awaitables.mo:66.9-66.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:68.9-68.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:70.9-70.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) -flatten-awaitables.mo:75.9-75.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:77.9-77.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:79.9-79.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) -flatten-awaitables.mo:85.9-85.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:87.9-87.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:89.9-89.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) -flatten-awaitables.mo:94.9-94.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:96.9-96.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:98.9-98.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) -flatten-awaitables.mo:103.9-103.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:105.9-105.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:107.9-107.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) -flatten-awaitables.mo:112.9-112.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -flatten-awaitables.mo:114.9-114.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (2, false) or - (0 or 1 or _, _) -flatten-awaitables.mo:116.9-116.25: warning, this pattern consuming type - (Int, Bool, Text) -does not cover value - (3, false, _) or - (3, true, _) or - (0 or 1 or _, _, _) first-order ,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, diff --git a/test/run-drun/ok/ic-calls.comp.ok b/test/run-drun/ok/ic-calls.comp.ok index e753cbd283c..7010e97b311 100644 --- a/test/run-drun/ok/ic-calls.comp.ok +++ b/test/run-drun/ok/ic-calls.comp.ok @@ -1,12 +1,3 @@ -ic-calls.mo:18.9-18.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -ic-calls.mo:19.9-19.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (1, false) or - (0 or -1 or _, _) ic-calls.mo:17.20-17.21: type error, calling a shared function not yet supported (This is a limitation of the current version.) ic-calls.mo:18.19-18.20: type error, calling a shared function not yet supported diff --git a/test/run-drun/ok/ic-calls.run-ir.ok b/test/run-drun/ok/ic-calls.run-ir.ok deleted file mode 100644 index dec54dfc5ac..00000000000 --- a/test/run-drun/ok/ic-calls.run-ir.ok +++ /dev/null @@ -1,9 +0,0 @@ -ic-calls.mo:18.9-18.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -ic-calls.mo:19.9-19.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (1, false) or - (0 or -1 or _, _) diff --git a/test/run-drun/ok/ic-calls.run-low.ok b/test/run-drun/ok/ic-calls.run-low.ok deleted file mode 100644 index dec54dfc5ac..00000000000 --- a/test/run-drun/ok/ic-calls.run-low.ok +++ /dev/null @@ -1,9 +0,0 @@ -ic-calls.mo:18.9-18.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -ic-calls.mo:19.9-19.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (1, false) or - (0 or -1 or _, _) diff --git a/test/run-drun/ok/ic-calls.run.ok b/test/run-drun/ok/ic-calls.run.ok deleted file mode 100644 index dec54dfc5ac..00000000000 --- a/test/run-drun/ok/ic-calls.run.ok +++ /dev/null @@ -1,9 +0,0 @@ -ic-calls.mo:18.9-18.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -ic-calls.mo:19.9-19.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (1, false) or - (0 or -1 or _, _) diff --git a/test/run.sh b/test/run.sh index 058996d2e2e..e8c4b96ee23 100755 --- a/test/run.sh +++ b/test/run.sh @@ -179,10 +179,10 @@ do if [ "$SKIP_RUNNING" != yes ] then # Interpret - run run $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS -r $base.mo + run run $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS --hide-warnings -r $base.mo # Interpret IR without lowering - run run-ir $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS -r -iR -no-async -no-await $base.mo + run run-ir $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS --hide-warnings -r -iR -no-async -no-await $base.mo # Diff interpretations without/with lowering if [ -e $out/$base.run -a -e $out/$base.run-ir ] @@ -192,7 +192,7 @@ do fi # Interpret IR with lowering - run run-low $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS -r -iR $base.mo + run run-low $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS --hide-warnings -r -iR $base.mo # Diff interpretations without/with lowering if [ -e $out/$base.run -a -e $out/$base.run-low ] @@ -204,7 +204,7 @@ do fi # Compile - run comp $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS --map -c $base.mo -o $out/$base.wasm + run comp $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS --hide-warnings --map -c $base.mo -o $out/$base.wasm if [ -e $out/$base.wasm ] then diff --git a/test/run/ok/coverage.comp.ok b/test/run/ok/coverage.comp.ok index 6cd2a586f70..e3455fac13d 100644 --- a/test/run/ok/coverage.comp.ok +++ b/test/run/ok/coverage.comp.ok @@ -26,76 +26,3 @@ coverage.mo:65.41-65.42: warning, this pattern is never matched coverage.mo:66.40-66.41: warning, this pattern is never matched coverage.mo:77.5-77.55: warning, this case is never reached coverage.mo:109.3-109.52: warning, this case is never reached -coverage.mo:4.7-4.8: warning, this pattern consuming type - Nat -does not cover value - 0 or 1 or _ -coverage.mo:5.7-5.15: warning, this pattern consuming type - Nat -does not cover value - 0 or 1 or _ -coverage.mo:9.7-9.9: warning, this pattern consuming type - ?Nat -does not cover value - null -coverage.mo:10.7-10.9: warning, this pattern consuming type - ?Nat -does not cover value - null -coverage.mo:11.7-11.9: warning, this pattern consuming type - ?Nat -does not cover value - ?(0 or 1 or _) or - null -coverage.mo:15.10-15.13: warning, this pattern consuming type - Nat -does not cover value - 0 or 1 or _ -coverage.mo:16.10-16.18: warning, this pattern consuming type - Nat -does not cover value - 0 or 1 or _ -coverage.mo:23.3-23.25: warning, the cases in this switch over type - Nat -do not cover value - 0 or 1 or _ -coverage.mo:24.3-24.36: warning, the cases in this switch over type - Nat -do not cover value - 0 or 1 or _ -coverage.mo:32.3-32.50: warning, the cases in this switch over type - Nat -do not cover value - 0 or 1 or _ -coverage.mo:35.3-35.51: warning, the cases in this switch over type - (Nat, Nat) -do not cover value - (1 or 2 or _, 1 or 2 or _) -coverage.mo:41.3-41.61: warning, the cases in this switch over type - {a : Nat; b : Nat} -do not cover value - {a = 1 or 2 or _; b = 1 or 2 or _) -coverage.mo:45.3-45.74: warning, the cases in this switch over type - {#a : Nat; #b : Nat} -do not cover value - #b(0 or 1 or _) -coverage.mo:47.3-47.58: warning, the cases in this switch over type - {#a : Nat; #b : Nat} -do not cover value - #b(_) -coverage.mo:48.3-48.58: warning, the cases in this switch over type - {#a : Nat; #b : Nat} -do not cover value - #a(_) -coverage.mo:49.3-49.62: warning, the cases in this switch over type - {#a : Nat; #b : Nat; #c} -do not cover value - #a(_) or #c -coverage.mo:50.3-50.42: warning, the cases in this switch over type - {#a : Nat; #b : Nat} -do not cover value - _ -coverage.mo:74.3-78.4: warning, the cases in this switch over type - {#branch : (Tree, Tree); #leaf : Int} -do not cover value - #leaf(0 or 1 or _) diff --git a/test/run/ok/coverage.run-ir.ok b/test/run/ok/coverage.run-ir.ok index 6cd2a586f70..e3455fac13d 100644 --- a/test/run/ok/coverage.run-ir.ok +++ b/test/run/ok/coverage.run-ir.ok @@ -26,76 +26,3 @@ coverage.mo:65.41-65.42: warning, this pattern is never matched coverage.mo:66.40-66.41: warning, this pattern is never matched coverage.mo:77.5-77.55: warning, this case is never reached coverage.mo:109.3-109.52: warning, this case is never reached -coverage.mo:4.7-4.8: warning, this pattern consuming type - Nat -does not cover value - 0 or 1 or _ -coverage.mo:5.7-5.15: warning, this pattern consuming type - Nat -does not cover value - 0 or 1 or _ -coverage.mo:9.7-9.9: warning, this pattern consuming type - ?Nat -does not cover value - null -coverage.mo:10.7-10.9: warning, this pattern consuming type - ?Nat -does not cover value - null -coverage.mo:11.7-11.9: warning, this pattern consuming type - ?Nat -does not cover value - ?(0 or 1 or _) or - null -coverage.mo:15.10-15.13: warning, this pattern consuming type - Nat -does not cover value - 0 or 1 or _ -coverage.mo:16.10-16.18: warning, this pattern consuming type - Nat -does not cover value - 0 or 1 or _ -coverage.mo:23.3-23.25: warning, the cases in this switch over type - Nat -do not cover value - 0 or 1 or _ -coverage.mo:24.3-24.36: warning, the cases in this switch over type - Nat -do not cover value - 0 or 1 or _ -coverage.mo:32.3-32.50: warning, the cases in this switch over type - Nat -do not cover value - 0 or 1 or _ -coverage.mo:35.3-35.51: warning, the cases in this switch over type - (Nat, Nat) -do not cover value - (1 or 2 or _, 1 or 2 or _) -coverage.mo:41.3-41.61: warning, the cases in this switch over type - {a : Nat; b : Nat} -do not cover value - {a = 1 or 2 or _; b = 1 or 2 or _) -coverage.mo:45.3-45.74: warning, the cases in this switch over type - {#a : Nat; #b : Nat} -do not cover value - #b(0 or 1 or _) -coverage.mo:47.3-47.58: warning, the cases in this switch over type - {#a : Nat; #b : Nat} -do not cover value - #b(_) -coverage.mo:48.3-48.58: warning, the cases in this switch over type - {#a : Nat; #b : Nat} -do not cover value - #a(_) -coverage.mo:49.3-49.62: warning, the cases in this switch over type - {#a : Nat; #b : Nat; #c} -do not cover value - #a(_) or #c -coverage.mo:50.3-50.42: warning, the cases in this switch over type - {#a : Nat; #b : Nat} -do not cover value - _ -coverage.mo:74.3-78.4: warning, the cases in this switch over type - {#branch : (Tree, Tree); #leaf : Int} -do not cover value - #leaf(0 or 1 or _) diff --git a/test/run/ok/coverage.run-low.ok b/test/run/ok/coverage.run-low.ok index 6cd2a586f70..e3455fac13d 100644 --- a/test/run/ok/coverage.run-low.ok +++ b/test/run/ok/coverage.run-low.ok @@ -26,76 +26,3 @@ coverage.mo:65.41-65.42: warning, this pattern is never matched coverage.mo:66.40-66.41: warning, this pattern is never matched coverage.mo:77.5-77.55: warning, this case is never reached coverage.mo:109.3-109.52: warning, this case is never reached -coverage.mo:4.7-4.8: warning, this pattern consuming type - Nat -does not cover value - 0 or 1 or _ -coverage.mo:5.7-5.15: warning, this pattern consuming type - Nat -does not cover value - 0 or 1 or _ -coverage.mo:9.7-9.9: warning, this pattern consuming type - ?Nat -does not cover value - null -coverage.mo:10.7-10.9: warning, this pattern consuming type - ?Nat -does not cover value - null -coverage.mo:11.7-11.9: warning, this pattern consuming type - ?Nat -does not cover value - ?(0 or 1 or _) or - null -coverage.mo:15.10-15.13: warning, this pattern consuming type - Nat -does not cover value - 0 or 1 or _ -coverage.mo:16.10-16.18: warning, this pattern consuming type - Nat -does not cover value - 0 or 1 or _ -coverage.mo:23.3-23.25: warning, the cases in this switch over type - Nat -do not cover value - 0 or 1 or _ -coverage.mo:24.3-24.36: warning, the cases in this switch over type - Nat -do not cover value - 0 or 1 or _ -coverage.mo:32.3-32.50: warning, the cases in this switch over type - Nat -do not cover value - 0 or 1 or _ -coverage.mo:35.3-35.51: warning, the cases in this switch over type - (Nat, Nat) -do not cover value - (1 or 2 or _, 1 or 2 or _) -coverage.mo:41.3-41.61: warning, the cases in this switch over type - {a : Nat; b : Nat} -do not cover value - {a = 1 or 2 or _; b = 1 or 2 or _) -coverage.mo:45.3-45.74: warning, the cases in this switch over type - {#a : Nat; #b : Nat} -do not cover value - #b(0 or 1 or _) -coverage.mo:47.3-47.58: warning, the cases in this switch over type - {#a : Nat; #b : Nat} -do not cover value - #b(_) -coverage.mo:48.3-48.58: warning, the cases in this switch over type - {#a : Nat; #b : Nat} -do not cover value - #a(_) -coverage.mo:49.3-49.62: warning, the cases in this switch over type - {#a : Nat; #b : Nat; #c} -do not cover value - #a(_) or #c -coverage.mo:50.3-50.42: warning, the cases in this switch over type - {#a : Nat; #b : Nat} -do not cover value - _ -coverage.mo:74.3-78.4: warning, the cases in this switch over type - {#branch : (Tree, Tree); #leaf : Int} -do not cover value - #leaf(0 or 1 or _) diff --git a/test/run/ok/coverage.run.ok b/test/run/ok/coverage.run.ok index 6cd2a586f70..e3455fac13d 100644 --- a/test/run/ok/coverage.run.ok +++ b/test/run/ok/coverage.run.ok @@ -26,76 +26,3 @@ coverage.mo:65.41-65.42: warning, this pattern is never matched coverage.mo:66.40-66.41: warning, this pattern is never matched coverage.mo:77.5-77.55: warning, this case is never reached coverage.mo:109.3-109.52: warning, this case is never reached -coverage.mo:4.7-4.8: warning, this pattern consuming type - Nat -does not cover value - 0 or 1 or _ -coverage.mo:5.7-5.15: warning, this pattern consuming type - Nat -does not cover value - 0 or 1 or _ -coverage.mo:9.7-9.9: warning, this pattern consuming type - ?Nat -does not cover value - null -coverage.mo:10.7-10.9: warning, this pattern consuming type - ?Nat -does not cover value - null -coverage.mo:11.7-11.9: warning, this pattern consuming type - ?Nat -does not cover value - ?(0 or 1 or _) or - null -coverage.mo:15.10-15.13: warning, this pattern consuming type - Nat -does not cover value - 0 or 1 or _ -coverage.mo:16.10-16.18: warning, this pattern consuming type - Nat -does not cover value - 0 or 1 or _ -coverage.mo:23.3-23.25: warning, the cases in this switch over type - Nat -do not cover value - 0 or 1 or _ -coverage.mo:24.3-24.36: warning, the cases in this switch over type - Nat -do not cover value - 0 or 1 or _ -coverage.mo:32.3-32.50: warning, the cases in this switch over type - Nat -do not cover value - 0 or 1 or _ -coverage.mo:35.3-35.51: warning, the cases in this switch over type - (Nat, Nat) -do not cover value - (1 or 2 or _, 1 or 2 or _) -coverage.mo:41.3-41.61: warning, the cases in this switch over type - {a : Nat; b : Nat} -do not cover value - {a = 1 or 2 or _; b = 1 or 2 or _) -coverage.mo:45.3-45.74: warning, the cases in this switch over type - {#a : Nat; #b : Nat} -do not cover value - #b(0 or 1 or _) -coverage.mo:47.3-47.58: warning, the cases in this switch over type - {#a : Nat; #b : Nat} -do not cover value - #b(_) -coverage.mo:48.3-48.58: warning, the cases in this switch over type - {#a : Nat; #b : Nat} -do not cover value - #a(_) -coverage.mo:49.3-49.62: warning, the cases in this switch over type - {#a : Nat; #b : Nat; #c} -do not cover value - #a(_) or #c -coverage.mo:50.3-50.42: warning, the cases in this switch over type - {#a : Nat; #b : Nat} -do not cover value - _ -coverage.mo:74.3-78.4: warning, the cases in this switch over type - {#branch : (Tree, Tree); #leaf : Int} -do not cover value - #leaf(0 or 1 or _) diff --git a/test/run/ok/issue442.comp.ok b/test/run/ok/issue442.comp.ok deleted file mode 100644 index 2ec06928058..00000000000 --- a/test/run/ok/issue442.comp.ok +++ /dev/null @@ -1,6 +0,0 @@ -issue442.mo:1.11-1.24: warning, this array has type [Any] because elements have inconsistent types -issue442.mo:2.11-2.29: warning, this if has type Any because branches have inconsistent types, -true produces - Nat -false produces - Text diff --git a/test/run/ok/issue442.run-ir.ok b/test/run/ok/issue442.run-ir.ok deleted file mode 100644 index 2ec06928058..00000000000 --- a/test/run/ok/issue442.run-ir.ok +++ /dev/null @@ -1,6 +0,0 @@ -issue442.mo:1.11-1.24: warning, this array has type [Any] because elements have inconsistent types -issue442.mo:2.11-2.29: warning, this if has type Any because branches have inconsistent types, -true produces - Nat -false produces - Text diff --git a/test/run/ok/issue442.run-low.ok b/test/run/ok/issue442.run-low.ok deleted file mode 100644 index 2ec06928058..00000000000 --- a/test/run/ok/issue442.run-low.ok +++ /dev/null @@ -1,6 +0,0 @@ -issue442.mo:1.11-1.24: warning, this array has type [Any] because elements have inconsistent types -issue442.mo:2.11-2.29: warning, this if has type Any because branches have inconsistent types, -true produces - Nat -false produces - Text diff --git a/test/run/ok/issue442.run.ok b/test/run/ok/issue442.run.ok deleted file mode 100644 index 2ec06928058..00000000000 --- a/test/run/ok/issue442.run.ok +++ /dev/null @@ -1,6 +0,0 @@ -issue442.mo:1.11-1.24: warning, this array has type [Any] because elements have inconsistent types -issue442.mo:2.11-2.29: warning, this if has type Any because branches have inconsistent types, -true produces - Nat -false produces - Text diff --git a/test/run/ok/large-tuple.comp.ok b/test/run/ok/large-tuple.comp.ok deleted file mode 100644 index c20cc4ea334..00000000000 --- a/test/run/ok/large-tuple.comp.ok +++ /dev/null @@ -1,23 +0,0 @@ -large-tuple.mo:4.21-4.73: warning, this pattern consuming type - (Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat) -does not cover value - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0 or 1 or _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 0 or 1 or _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 0 or 1 or _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0 or 1 or _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0 or 1 or _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0 or 1 or _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0 or 1 or _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0 or 1 or _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0 or 1 or _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0 or 1 or _, _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or - (1, 2, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or - (1, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or - (0 or 2 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) diff --git a/test/run/ok/large-tuple.run-ir.ok b/test/run/ok/large-tuple.run-ir.ok deleted file mode 100644 index c20cc4ea334..00000000000 --- a/test/run/ok/large-tuple.run-ir.ok +++ /dev/null @@ -1,23 +0,0 @@ -large-tuple.mo:4.21-4.73: warning, this pattern consuming type - (Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat) -does not cover value - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0 or 1 or _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 0 or 1 or _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 0 or 1 or _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0 or 1 or _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0 or 1 or _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0 or 1 or _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0 or 1 or _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0 or 1 or _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0 or 1 or _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0 or 1 or _, _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or - (1, 2, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or - (1, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or - (0 or 2 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) diff --git a/test/run/ok/large-tuple.run-low.ok b/test/run/ok/large-tuple.run-low.ok deleted file mode 100644 index c20cc4ea334..00000000000 --- a/test/run/ok/large-tuple.run-low.ok +++ /dev/null @@ -1,23 +0,0 @@ -large-tuple.mo:4.21-4.73: warning, this pattern consuming type - (Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat) -does not cover value - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0 or 1 or _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 0 or 1 or _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 0 or 1 or _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0 or 1 or _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0 or 1 or _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0 or 1 or _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0 or 1 or _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0 or 1 or _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0 or 1 or _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0 or 1 or _, _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or - (1, 2, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or - (1, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or - (0 or 2 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) diff --git a/test/run/ok/large-tuple.run.ok b/test/run/ok/large-tuple.run.ok deleted file mode 100644 index c20cc4ea334..00000000000 --- a/test/run/ok/large-tuple.run.ok +++ /dev/null @@ -1,23 +0,0 @@ -large-tuple.mo:4.21-4.73: warning, this pattern consuming type - (Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat, Nat) -does not cover value - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0 or 1 or _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 0 or 1 or _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 0 or 1 or _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0 or 1 or _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0 or 1 or _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0 or 1 or _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0 or 1 or _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0 or 1 or _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0 or 1 or _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0 or 1 or _, _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 9, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 8, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 7, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 6, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 5, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 4, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or - (1, 2, 3, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or - (1, 2, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or - (1, 0 or 1 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) or - (0 or 2 or _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) diff --git a/test/run/ok/objects1.comp.ok b/test/run/ok/objects1.comp.ok index 53be7fa8068..8a83a4aca71 100644 --- a/test/run/ok/objects1.comp.ok +++ b/test/run/ok/objects1.comp.ok @@ -1,10 +1,2 @@ objects1.mo:22.3-22.26: warning, this case is never reached objects1.mo:23.3-23.14: warning, this case is never reached -objects1.mo:32.23-35.2: warning, the cases in this switch over type - {a : Int; b : Nat} -do not cover value - {a = 0 or 1 or _; b = 0 or 1 or _) -objects1.mo:43.21-45.2: warning, the cases in this switch over type - (Nat, Int, {c : Char; d : Text}) -do not cover value - (_, 0 or 1 or _, _) diff --git a/test/run/ok/objects1.run-ir.ok b/test/run/ok/objects1.run-ir.ok index 53be7fa8068..8a83a4aca71 100644 --- a/test/run/ok/objects1.run-ir.ok +++ b/test/run/ok/objects1.run-ir.ok @@ -1,10 +1,2 @@ objects1.mo:22.3-22.26: warning, this case is never reached objects1.mo:23.3-23.14: warning, this case is never reached -objects1.mo:32.23-35.2: warning, the cases in this switch over type - {a : Int; b : Nat} -do not cover value - {a = 0 or 1 or _; b = 0 or 1 or _) -objects1.mo:43.21-45.2: warning, the cases in this switch over type - (Nat, Int, {c : Char; d : Text}) -do not cover value - (_, 0 or 1 or _, _) diff --git a/test/run/ok/objects1.run-low.ok b/test/run/ok/objects1.run-low.ok index 53be7fa8068..8a83a4aca71 100644 --- a/test/run/ok/objects1.run-low.ok +++ b/test/run/ok/objects1.run-low.ok @@ -1,10 +1,2 @@ objects1.mo:22.3-22.26: warning, this case is never reached objects1.mo:23.3-23.14: warning, this case is never reached -objects1.mo:32.23-35.2: warning, the cases in this switch over type - {a : Int; b : Nat} -do not cover value - {a = 0 or 1 or _; b = 0 or 1 or _) -objects1.mo:43.21-45.2: warning, the cases in this switch over type - (Nat, Int, {c : Char; d : Text}) -do not cover value - (_, 0 or 1 or _, _) diff --git a/test/run/ok/objects1.run.ok b/test/run/ok/objects1.run.ok index 53be7fa8068..8a83a4aca71 100644 --- a/test/run/ok/objects1.run.ok +++ b/test/run/ok/objects1.run.ok @@ -1,10 +1,2 @@ objects1.mo:22.3-22.26: warning, this case is never reached objects1.mo:23.3-23.14: warning, this case is never reached -objects1.mo:32.23-35.2: warning, the cases in this switch over type - {a : Int; b : Nat} -do not cover value - {a = 0 or 1 or _; b = 0 or 1 or _) -objects1.mo:43.21-45.2: warning, the cases in this switch over type - (Nat, Int, {c : Char; d : Text}) -do not cover value - (_, 0 or 1 or _, _) diff --git a/test/run/ok/switch.comp.ok b/test/run/ok/switch.comp.ok index d8896858554..a2be30fb719 100644 --- a/test/run/ok/switch.comp.ok +++ b/test/run/ok/switch.comp.ok @@ -1,17 +1 @@ switch.mo:86.29-86.30: warning, this pattern is never matched -switch.mo:75.11-77.2: warning, the cases in this switch over type - ?Int -do not cover value - ?(_) -switch.mo:81.3-81.14: warning, the cases in this switch over type - Nat -do not cover value - _ -switch.mo:92.11-94.2: warning, the cases in this switch over type - ?Nat -do not cover value - null -switch.mo:97.11-99.2: warning, the cases in this switch over type - ?Nat -do not cover value - ?(_) diff --git a/test/run/ok/switch.run-ir.ok b/test/run/ok/switch.run-ir.ok index d8896858554..a2be30fb719 100644 --- a/test/run/ok/switch.run-ir.ok +++ b/test/run/ok/switch.run-ir.ok @@ -1,17 +1 @@ switch.mo:86.29-86.30: warning, this pattern is never matched -switch.mo:75.11-77.2: warning, the cases in this switch over type - ?Int -do not cover value - ?(_) -switch.mo:81.3-81.14: warning, the cases in this switch over type - Nat -do not cover value - _ -switch.mo:92.11-94.2: warning, the cases in this switch over type - ?Nat -do not cover value - null -switch.mo:97.11-99.2: warning, the cases in this switch over type - ?Nat -do not cover value - ?(_) diff --git a/test/run/ok/switch.run-low.ok b/test/run/ok/switch.run-low.ok index d8896858554..a2be30fb719 100644 --- a/test/run/ok/switch.run-low.ok +++ b/test/run/ok/switch.run-low.ok @@ -1,17 +1 @@ switch.mo:86.29-86.30: warning, this pattern is never matched -switch.mo:75.11-77.2: warning, the cases in this switch over type - ?Int -do not cover value - ?(_) -switch.mo:81.3-81.14: warning, the cases in this switch over type - Nat -do not cover value - _ -switch.mo:92.11-94.2: warning, the cases in this switch over type - ?Nat -do not cover value - null -switch.mo:97.11-99.2: warning, the cases in this switch over type - ?Nat -do not cover value - ?(_) diff --git a/test/run/ok/switch.run.ok b/test/run/ok/switch.run.ok index d8896858554..a2be30fb719 100644 --- a/test/run/ok/switch.run.ok +++ b/test/run/ok/switch.run.ok @@ -1,17 +1 @@ switch.mo:86.29-86.30: warning, this pattern is never matched -switch.mo:75.11-77.2: warning, the cases in this switch over type - ?Int -do not cover value - ?(_) -switch.mo:81.3-81.14: warning, the cases in this switch over type - Nat -do not cover value - _ -switch.mo:92.11-94.2: warning, the cases in this switch over type - ?Nat -do not cover value - null -switch.mo:97.11-99.2: warning, the cases in this switch over type - ?Nat -do not cover value - ?(_) diff --git a/test/run/ok/type-inference.comp.ok b/test/run/ok/type-inference.comp.ok index b8e76a3ed94..b3d258e7112 100644 --- a/test/run/ok/type-inference.comp.ok +++ b/test/run/ok/type-inference.comp.ok @@ -1,38 +1 @@ compile_lit: (FloatLit 5.1) -type-inference.mo:3.9-3.28: warning, this if has type Any because branches have inconsistent types, -true produces - Bool -false produces - Nat -type-inference.mo:4.9-4.34: warning, this if has type Any because branches have inconsistent types, -true produces - Bool -false produces - [var Nat] -type-inference.mo:5.9-5.27: warning, this if has type Any because branches have inconsistent types, -true produces - Nat -false produces - Float -type-inference.mo:6.9-6.29: warning, this if has type Any because branches have inconsistent types, -true produces - () -false produces - {} -type-inference.mo:11.33-11.41: warning, the switch has type Any because branches have inconsistent types, -this case produces type - Bool -the previous produce type - Nat -type-inference.mo:12.33-12.47: warning, the switch has type Any because branches have inconsistent types, -this case produces type - Bool -the previous produce type - [var Nat] -type-inference.mo:13.43-13.56: warning, the switch has type Any because branches have inconsistent types, -this case produces type - Int -the previous produce type - Text -type-inference.mo:19.9-19.18: warning, this array has type [Any] because elements have inconsistent types -type-inference.mo:20.9-20.24: warning, this array has type [Any] because elements have inconsistent types diff --git a/test/run/ok/type-inference.run-ir.ok b/test/run/ok/type-inference.run-ir.ok deleted file mode 100644 index a1077f043f0..00000000000 --- a/test/run/ok/type-inference.run-ir.ok +++ /dev/null @@ -1,37 +0,0 @@ -type-inference.mo:3.9-3.28: warning, this if has type Any because branches have inconsistent types, -true produces - Bool -false produces - Nat -type-inference.mo:4.9-4.34: warning, this if has type Any because branches have inconsistent types, -true produces - Bool -false produces - [var Nat] -type-inference.mo:5.9-5.27: warning, this if has type Any because branches have inconsistent types, -true produces - Nat -false produces - Float -type-inference.mo:6.9-6.29: warning, this if has type Any because branches have inconsistent types, -true produces - () -false produces - {} -type-inference.mo:11.33-11.41: warning, the switch has type Any because branches have inconsistent types, -this case produces type - Bool -the previous produce type - Nat -type-inference.mo:12.33-12.47: warning, the switch has type Any because branches have inconsistent types, -this case produces type - Bool -the previous produce type - [var Nat] -type-inference.mo:13.43-13.56: warning, the switch has type Any because branches have inconsistent types, -this case produces type - Int -the previous produce type - Text -type-inference.mo:19.9-19.18: warning, this array has type [Any] because elements have inconsistent types -type-inference.mo:20.9-20.24: warning, this array has type [Any] because elements have inconsistent types diff --git a/test/run/ok/type-inference.run-low.ok b/test/run/ok/type-inference.run-low.ok deleted file mode 100644 index a1077f043f0..00000000000 --- a/test/run/ok/type-inference.run-low.ok +++ /dev/null @@ -1,37 +0,0 @@ -type-inference.mo:3.9-3.28: warning, this if has type Any because branches have inconsistent types, -true produces - Bool -false produces - Nat -type-inference.mo:4.9-4.34: warning, this if has type Any because branches have inconsistent types, -true produces - Bool -false produces - [var Nat] -type-inference.mo:5.9-5.27: warning, this if has type Any because branches have inconsistent types, -true produces - Nat -false produces - Float -type-inference.mo:6.9-6.29: warning, this if has type Any because branches have inconsistent types, -true produces - () -false produces - {} -type-inference.mo:11.33-11.41: warning, the switch has type Any because branches have inconsistent types, -this case produces type - Bool -the previous produce type - Nat -type-inference.mo:12.33-12.47: warning, the switch has type Any because branches have inconsistent types, -this case produces type - Bool -the previous produce type - [var Nat] -type-inference.mo:13.43-13.56: warning, the switch has type Any because branches have inconsistent types, -this case produces type - Int -the previous produce type - Text -type-inference.mo:19.9-19.18: warning, this array has type [Any] because elements have inconsistent types -type-inference.mo:20.9-20.24: warning, this array has type [Any] because elements have inconsistent types diff --git a/test/run/ok/type-inference.run.ok b/test/run/ok/type-inference.run.ok deleted file mode 100644 index a1077f043f0..00000000000 --- a/test/run/ok/type-inference.run.ok +++ /dev/null @@ -1,37 +0,0 @@ -type-inference.mo:3.9-3.28: warning, this if has type Any because branches have inconsistent types, -true produces - Bool -false produces - Nat -type-inference.mo:4.9-4.34: warning, this if has type Any because branches have inconsistent types, -true produces - Bool -false produces - [var Nat] -type-inference.mo:5.9-5.27: warning, this if has type Any because branches have inconsistent types, -true produces - Nat -false produces - Float -type-inference.mo:6.9-6.29: warning, this if has type Any because branches have inconsistent types, -true produces - () -false produces - {} -type-inference.mo:11.33-11.41: warning, the switch has type Any because branches have inconsistent types, -this case produces type - Bool -the previous produce type - Nat -type-inference.mo:12.33-12.47: warning, the switch has type Any because branches have inconsistent types, -this case produces type - Bool -the previous produce type - [var Nat] -type-inference.mo:13.43-13.56: warning, the switch has type Any because branches have inconsistent types, -this case produces type - Int -the previous produce type - Text -type-inference.mo:19.9-19.18: warning, this array has type [Any] because elements have inconsistent types -type-inference.mo:20.9-20.24: warning, this array has type [Any] because elements have inconsistent types From a96082d3f573a11341bed67f54548042464d9d5d Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 15 Nov 2019 09:50:32 +0100 Subject: [PATCH 0611/1176] Decode callback at the right type exposed by a test case, yay! --- ic-stub/src/IC/Types.hs | 9 +++++++++ ic-stub/src/ic-stub-run.hs | 8 -------- src/codegen/compile.ml | 2 +- test/run-stub/ok/transpose.ic-stub-run.ok | 4 ++++ test/{run-dfinity => run-stub}/transpose.mo | 18 ++++++++++-------- 5 files changed, 24 insertions(+), 17 deletions(-) create mode 100644 test/run-stub/ok/transpose.ic-stub-run.ok rename test/{run-dfinity => run-stub}/transpose.mo (53%) diff --git a/ic-stub/src/IC/Types.hs b/ic-stub/src/IC/Types.hs index 267c70d808f..2005907070b 100644 --- a/ic-stub/src/IC/Types.hs +++ b/ic-stub/src/IC/Types.hs @@ -3,6 +3,8 @@ module IC.Types where import qualified Data.ByteString.Lazy as BS import qualified Data.Map as M +import qualified Data.Text as T +import qualified Text.Hex as T import Data.Int type (↦) = M.Map @@ -16,6 +18,13 @@ type UserId = EntityId type MethodName = String type RequestID = Blob +prettyBlob :: Blob -> String +prettyBlob b = "0x" ++ T.unpack (T.encodeHex (BS.toStrict b)) + +prettyID :: EntityId -> String +prettyID = prettyBlob . rawEntityId -- implement the "ic:…" stuff + + data RejectCode = RC_SYS_FATAL | RC_SYS_TRANSIENT diff --git a/ic-stub/src/ic-stub-run.hs b/ic-stub/src/ic-stub-run.hs index 186540a72d4..1d7a5e28ae6 100644 --- a/ic-stub/src/ic-stub-run.hs +++ b/ic-stub/src/ic-stub-run.hs @@ -9,8 +9,6 @@ import Data.Monoid ((<>)) import qualified Data.ByteString.Lazy as B import Control.Monad.Trans import Control.Monad.Trans.State -import qualified Data.Text as T -import qualified Text.Hex as T import Text.Printf import IC.Types @@ -21,12 +19,6 @@ type DRun = StateT IC IO -- Pretty printing -prettyBlob :: Blob -> String -prettyBlob b = "0x" ++ T.unpack (T.encodeHex (B.toStrict b)) - -prettyID :: EntityId -> String -prettyID = prettyBlob . rawEntityId -- implement the "ic:…" stuff - dummyUserId :: CanisterId dummyUserId = EntityId $ B.pack [0xCA, 0xFF, 0xEE] diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 687244d71d5..a580aa30edf 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -6618,7 +6618,7 @@ and compile_exp (env : E.t) ae exp = (* The method name *) get_funcref ^^ Arr.load_field 1l ^^ Blob.as_ptr_len env ^^ (* The reply callback *) - FuncDec.closure_to_reply_callback env ts1 get_k ^^ + FuncDec.closure_to_reply_callback env ts2 get_k ^^ (* The reject callback *) FuncDec.closure_to_reject_callback env get_r ^^ (* the data *) diff --git a/test/run-stub/ok/transpose.ic-stub-run.ok b/test/run-stub/ok/transpose.ic-stub-run.ok new file mode 100644 index 00000000000..6486f68e99f --- /dev/null +++ b/test/run-stub/ok/transpose.ic-stub-run.ok @@ -0,0 +1,4 @@ +→ install +← completed +→ update go(0x4449444c0000) +← completed: 0x4449444c0000 diff --git a/test/run-dfinity/transpose.mo b/test/run-stub/transpose.mo similarity index 53% rename from test/run-dfinity/transpose.mo rename to test/run-stub/transpose.mo index 38c224426f0..2f4821bddd4 100644 --- a/test/run-dfinity/transpose.mo +++ b/test/run-stub/transpose.mo @@ -4,13 +4,15 @@ actor foo { ints = Array_tabulate(data.len(), func (i:Nat) : Int = (data[i].0)); txts = Array_tabulate(data.len(), func (i:Nat) : Text = (data[i].1)) } - } -}; + }; -async { - let x = await foo.transpose([(1,"Hi"), (2, "Ho")]); - assert (x.ints[0] == 1); - assert (x.ints[1] == 2); - assert (x.txts[0] == "Hi"); - assert (x.txts[1] == "Ho"); + public func go() : async () { + let x = await foo.transpose([(1,"Hi"), (2, "Ho")]); + assert (x.ints[0] == 1); + assert (x.ints[1] == 2); + assert (x.txts[0] == "Hi"); + assert (x.txts[1] == "Ho"); + } } + +//CALL ingress go 0x4449444C0000 From 8d6cfa18be91f3c0332bc9e17515c1e425337b2c Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 15 Nov 2019 10:13:15 +0100 Subject: [PATCH 0612/1176] Test case for issue #874 --- test/fail/issue874.mo | 4 ++++ test/fail/ok/issue874.tc.ok | 2 ++ test/fail/ok/issue874.tc.ret.ok | 1 + 3 files changed, 7 insertions(+) create mode 100644 test/fail/issue874.mo create mode 100644 test/fail/ok/issue874.tc.ok create mode 100644 test/fail/ok/issue874.tc.ret.ok diff --git a/test/fail/issue874.mo b/test/fail/issue874.mo new file mode 100644 index 00000000000..1f54f9a1d5d --- /dev/null +++ b/test/fail/issue874.mo @@ -0,0 +1,4 @@ +actor a { + public func foo() {}; + let _ = a.foo(); +} diff --git a/test/fail/ok/issue874.tc.ok b/test/fail/ok/issue874.tc.ok new file mode 100644 index 00000000000..9b5b57c2af2 --- /dev/null +++ b/test/fail/ok/issue874.tc.ok @@ -0,0 +1,2 @@ +issue874.mo:3.11-3.12: type error, field foo does not exist in type + actor {} diff --git a/test/fail/ok/issue874.tc.ret.ok b/test/fail/ok/issue874.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/issue874.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 From 81e4e62733c41045291d45aa38b898f40dce5b36 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 15 Nov 2019 10:38:58 +0100 Subject: [PATCH 0613/1176] Backend: Implement calling one-shot functions in stub mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit a bit of a hack (passing out invalid callbacks), probably subsumed by https://github.com/dfinity-lab/motoko/pull/773 Also, `data-params.mo` runs far too slow on the stub ic. The “orthogonal persitence by replaying” does’t quite work out. Need to rethink that. --- src/codegen/compile.ml | 46 +++++++-- test/run-dfinity/ok/data-params.comp.ok | 4 - test/run-dfinity/ok/data-params.run-ir.ok | 42 -------- test/run-dfinity/ok/data-params.run-low.ok | 42 -------- test/run-dfinity/ok/data-params.run.ok | 42 -------- test/run-dfinity/ok/data-params.tc.ok | 4 - test/{run-dfinity => run-stub}/data-params.mo | 96 ++++++++----------- test/run-stub/ok/data-params.comp.ok | 4 + .../ok/data-params.ic-stub-run.ok} | 13 ++- test/run-stub/ok/data-params.run-ir.ok | 4 + test/run-stub/ok/data-params.run-low.ok | 4 + test/run-stub/ok/data-params.run.ok | 4 + test/run-stub/ok/data-params.tc.ok | 4 + 13 files changed, 109 insertions(+), 200 deletions(-) delete mode 100644 test/run-dfinity/ok/data-params.comp.ok delete mode 100644 test/run-dfinity/ok/data-params.run-ir.ok delete mode 100644 test/run-dfinity/ok/data-params.run-low.ok delete mode 100644 test/run-dfinity/ok/data-params.run.ok delete mode 100644 test/run-dfinity/ok/data-params.tc.ok rename test/{run-dfinity => run-stub}/data-params.mo (61%) create mode 100644 test/run-stub/ok/data-params.comp.ok rename test/{run-dfinity/ok/data-params.dvm.ok => run-stub/ok/data-params.ic-stub-run.ok} (73%) create mode 100644 test/run-stub/ok/data-params.run-ir.ok create mode 100644 test/run-stub/ok/data-params.run-low.ok create mode 100644 test/run-stub/ok/data-params.run.ok create mode 100644 test/run-stub/ok/data-params.tc.ok diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index a580aa30edf..763a1a9e0b5 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -6749,15 +6749,43 @@ and compile_exp (env : E.t) ae exp = | _, Type.Shared _ -> (* Non-one-shot functions have been rewritten in async.ml *) assert (control = Type.Returns); - let (set_funcref, get_funcref) = new_local env "funcref" in - code1 ^^ StackRep.adjust env fun_sr SR.UnboxedReference ^^ - set_funcref ^^ - compile_exp_as env ae SR.Vanilla e2 ^^ - (* We can try to avoid the boxing and pass the arguments to - serialize individually *) - let _, _, _, ts, _ = Type.as_func e1.note.note_typ in - Serialization.serialize env ts ^^ - FuncDec.call_message_funcref env get_funcref + match E.mode env with + | Flags.AncientMode -> + let (set_funcref, get_funcref) = new_local env "funcref" in + code1 ^^ StackRep.adjust env fun_sr SR.UnboxedReference ^^ + set_funcref ^^ + compile_exp_as env ae SR.Vanilla e2 ^^ + (* We can try to avoid the boxing and pass the arguments to + serialize individually *) + let _, _, _, ts, _ = Type.as_func e1.note.note_typ in + Serialization.serialize env ts ^^ + FuncDec.call_message_funcref env get_funcref + | Flags.StubMode -> + let (set_funcref, get_funcref) = new_local env "funcref" in + let (set_arg, get_arg) = new_local env "arg" in + let _, _, _, ts, _ = Type.as_func e1.note.note_typ in + code1 ^^ StackRep.adjust env fun_sr SR.Vanilla ^^ + set_funcref ^^ + compile_exp_as env ae SR.Vanilla e2 ^^ set_arg ^^ + + (* The callee *) + get_funcref ^^ Arr.load_field 0l ^^ Blob.as_ptr_len env ^^ + (* The method name *) + get_funcref ^^ Arr.load_field 1l ^^ Blob.as_ptr_len env ^^ + (* The reply callback *) + compile_unboxed_const 0l ^^ + compile_unboxed_const 0l ^^ + (* The reject callback *) + compile_unboxed_const 0l ^^ + compile_unboxed_const 0l ^^ + (* the data *) + get_arg ^^ Serialization.serialize env ts ^^ + (* done! *) + Dfinity.system_call env "ic0" "call_simple" ^^ + (* TODO: Check error code *) + G.i Drop + + | _ -> assert false end | SwitchE (e, cs) -> SR.Vanilla, diff --git a/test/run-dfinity/ok/data-params.comp.ok b/test/run-dfinity/ok/data-params.comp.ok deleted file mode 100644 index 4f513b4d81a..00000000000 --- a/test/run-dfinity/ok/data-params.comp.ok +++ /dev/null @@ -1,4 +0,0 @@ -data-params.mo:59.30-59.40: warning, this pattern consuming type - ?Text -does not cover value - null diff --git a/test/run-dfinity/ok/data-params.run-ir.ok b/test/run-dfinity/ok/data-params.run-ir.ok deleted file mode 100644 index 78262242d6f..00000000000 --- a/test/run-dfinity/ok/data-params.run-ir.ok +++ /dev/null @@ -1,42 +0,0 @@ -data-params.mo:59.30-59.40: warning, this pattern consuming type - ?Text -does not cover value - null -0 -+1 -+3 -+6 -+10 -+1_010 -+1_021 -+6_021 -+6_045 -+6_091 -+1_006_091 -+1_006_105 -+1_006_136 -+1_006_171 -+1_006_191 -+1_006_211 -+1_006_211 -Foo1: +1_006_211 -μεταγράψτε: +1_006_211 -Foo2: +1_006_211 -+10_000_001_006_211 -+20_000_001_006_211 -+1_006_211 -+1_006_221 -+1_006_211 -+1_006_221 -+1_006_231 -+1_006_221 -+1_267_650_600_228_229_401_496_704_211_597 -+2_535_301_200_456_458_802_993_407_416_973 -+1_006_221 -+1_074_748_045 -+2_148_489_868 -+2_148_489_868 -+2_148_489_869 -+2_148_489_911 -+2_148_489_869 -+4_295_973_516 diff --git a/test/run-dfinity/ok/data-params.run-low.ok b/test/run-dfinity/ok/data-params.run-low.ok deleted file mode 100644 index 78262242d6f..00000000000 --- a/test/run-dfinity/ok/data-params.run-low.ok +++ /dev/null @@ -1,42 +0,0 @@ -data-params.mo:59.30-59.40: warning, this pattern consuming type - ?Text -does not cover value - null -0 -+1 -+3 -+6 -+10 -+1_010 -+1_021 -+6_021 -+6_045 -+6_091 -+1_006_091 -+1_006_105 -+1_006_136 -+1_006_171 -+1_006_191 -+1_006_211 -+1_006_211 -Foo1: +1_006_211 -μεταγράψτε: +1_006_211 -Foo2: +1_006_211 -+10_000_001_006_211 -+20_000_001_006_211 -+1_006_211 -+1_006_221 -+1_006_211 -+1_006_221 -+1_006_231 -+1_006_221 -+1_267_650_600_228_229_401_496_704_211_597 -+2_535_301_200_456_458_802_993_407_416_973 -+1_006_221 -+1_074_748_045 -+2_148_489_868 -+2_148_489_868 -+2_148_489_869 -+2_148_489_911 -+2_148_489_869 -+4_295_973_516 diff --git a/test/run-dfinity/ok/data-params.run.ok b/test/run-dfinity/ok/data-params.run.ok deleted file mode 100644 index 78262242d6f..00000000000 --- a/test/run-dfinity/ok/data-params.run.ok +++ /dev/null @@ -1,42 +0,0 @@ -data-params.mo:59.30-59.40: warning, this pattern consuming type - ?Text -does not cover value - null -0 -+1 -+3 -+6 -+10 -+1_010 -+1_021 -+6_021 -+6_045 -+6_091 -+1_006_091 -+1_006_105 -+1_006_136 -+1_006_171 -+1_006_191 -+1_006_211 -+1_006_211 -Foo1: +1_006_211 -μεταγράψτε: +1_006_211 -Foo2: +1_006_211 -+10_000_001_006_211 -+20_000_001_006_211 -+1_006_211 -+1_006_221 -+1_006_211 -+1_006_221 -+1_006_231 -+1_006_221 -+1_267_650_600_228_229_401_496_704_211_597 -+2_535_301_200_456_458_802_993_407_416_973 -+1_006_221 -+1_074_748_045 -+2_148_489_868 -+2_148_489_868 -+2_148_489_869 -+2_148_489_911 -+2_148_489_869 -+4_295_973_516 diff --git a/test/run-dfinity/ok/data-params.tc.ok b/test/run-dfinity/ok/data-params.tc.ok deleted file mode 100644 index 4f513b4d81a..00000000000 --- a/test/run-dfinity/ok/data-params.tc.ok +++ /dev/null @@ -1,4 +0,0 @@ -data-params.mo:59.30-59.40: warning, this pattern consuming type - ?Text -does not cover value - null diff --git a/test/run-dfinity/data-params.mo b/test/run-stub/data-params.mo similarity index 61% rename from test/run-dfinity/data-params.mo rename to test/run-stub/data-params.mo index 744195fd89e..0244de558c3 100644 --- a/test/run-dfinity/data-params.mo +++ b/test/run-stub/data-params.mo @@ -3,27 +3,22 @@ let a = actor { public func inci(n : Int) : () { c += n; debugPrintInt(c); - debugPrint("\n"); }; public func incn(n : Nat) : () { c += n; debugPrintInt(c); - debugPrint("\n"); }; public func incnn(n1 : Nat, n2 : Nat) : () { c += n1 + n2; debugPrintInt(c); - debugPrint("\n"); }; public func incnested(n1 : Nat, (n2 : Nat, n3 : Nat)) : () { c += n1 + n2 + n3; debugPrintInt(c); - debugPrint("\n"); }; public func incarray(a : [Nat]) : () { for (i in a.vals()) { c += i }; debugPrintInt(c); - debugPrint("\n"); }; public func incopt(a : ?Nat) : () { switch a { @@ -31,13 +26,11 @@ let a = actor { case (?a) { c += a }; }; debugPrintInt(c); - debugPrint("\n"); }; public func increcord(a : { x : Nat; y : Nat }) : () { c += a.x; c += a.y; debugPrintInt(c); - debugPrint("\n"); }; public func incVariant(v : { #foo : Nat; #bar : Nat }) { c += (switch v { @@ -45,21 +38,17 @@ let a = actor { case (#bar n) n; }); debugPrintInt(c); - debugPrint("\n"); }; public func printCounter() { debugPrintInt(c); - debugPrint("\n"); }; public func printLabeled(l:Text) { debugPrint l; debugPrintInt(c); - debugPrint("\n"); }; public func printLabeledOpt(?l:?Text) { debugPrint l; debugPrintInt(c); - debugPrint("\n"); }; public func incwords(w8 : Word8, w16 : Word16, w32 : Word32, w64 : Word64) : () { c += word8ToInt(w8); @@ -67,7 +56,6 @@ let a = actor { c += word32ToInt(w32); c += word64ToInt(w64); debugPrintInt(c); - debugPrint("\n"); }; public func incnats(n8 : Nat8, n16 : Nat16, n32 : Nat32, n64 : Nat64) : () { c += nat8ToNat(n8); @@ -75,7 +63,6 @@ let a = actor { c += nat32ToNat(n32); c += nat64ToNat(n64); debugPrintInt(c); - debugPrint("\n"); }; public func incints(i8 : Int8, i16 : Int16, i32 : Int32, i64 : Int64) : () { c += int8ToInt(i8); @@ -83,46 +70,47 @@ let a = actor { c += int32ToInt(i32); c += int64ToInt(i64); debugPrintInt(c); - debugPrint("\n"); }; -}; - -a.incn(0); -a.incn(1); -a.incn(2); -a.incn(3); -a.incn(4); -a.incn(1000); -a.incnn(5,6); -a.incnn(2000,3000); -a.incnested(7,(8,9)); -a.incarray([10,11,12,13]); -a.incopt(null); -a.incopt(?14); -a.increcord({x = 15; y = 16}); -a.increcord({x = 17; y = 18; z = 19}); -a.incVariant(#foo 20); -a.incVariant(#bar 20); -a.printCounter(); -a.printLabeled("Foo1: "); -a.printLabeled("μεταγράψτε: "); -a.printLabeledOpt(?"Foo2: "); -a.incn(10000000000000); -a.inci(10000000000000); -a.inci(-20000000000000); -a.incwords(1,2,3,4); -a.incwords(-1,-2,-3,-4); -a.incnats(1,2,3,4); -a.incints(1,2,3,4); -a.incints(-1,-2,-3,-4); -a.incn(2**100); -a.inci(2**100); -a.inci(-(2**101)); -a.inci(-2**30); // lowest compact -a.inci(2**30 - 1); // highest compact -a.inci(0); -a.inci(1); -a.inci(42); -a.inci(-42); -a.incn(2**31 - 1); // highest compact + public func go() : async () { + a.incn(0); + a.incn(1); + a.incn(2); + a.incn(3); + a.incn(4); + a.incn(1000); + a.incnn(5,6); + a.incnn(2000,3000); + a.incnested(7,(8,9)); + a.incarray([10,11,12,13]); + a.incopt(null); + a.incopt(?14); + a.increcord({x = 15; y = 16}); + a.increcord({x = 17; y = 18; z = 19}); + a.incVariant(#foo 20); + a.incVariant(#bar 20); + a.printCounter(); + a.printLabeled("Foo1: "); + a.printLabeled("μεταγράψτε: "); + a.printLabeledOpt(?"Foo2: "); + a.incn(10000000000000); + a.inci(10000000000000); + a.inci(-20000000000000); + a.incwords(1,2,3,4); + a.incwords(-1,-2,-3,-4); + a.incnats(1,2,3,4); + a.incints(1,2,3,4); + a.incints(-1,-2,-3,-4); + a.incn(2**100); + a.inci(2**100); + a.inci(-(2**101)); + a.inci(-2**30); // lowest compact + a.inci(2**30 - 1); // highest compact + a.inci(0); + a.inci(1); + a.inci(42); + a.inci(-42); + a.incn(2**31 - 1); // highest compact + }; +} +//CALL ingress go 0x4449444C0000 diff --git a/test/run-stub/ok/data-params.comp.ok b/test/run-stub/ok/data-params.comp.ok new file mode 100644 index 00000000000..8121106181c --- /dev/null +++ b/test/run-stub/ok/data-params.comp.ok @@ -0,0 +1,4 @@ +data-params.mo:49.30-49.40: warning, this pattern consuming type + ?Text +does not cover value + null diff --git a/test/run-dfinity/ok/data-params.dvm.ok b/test/run-stub/ok/data-params.ic-stub-run.ok similarity index 73% rename from test/run-dfinity/ok/data-params.dvm.ok rename to test/run-stub/ok/data-params.ic-stub-run.ok index 732e96d5e47..8f2de813c9d 100644 --- a/test/run-dfinity/ok/data-params.dvm.ok +++ b/test/run-stub/ok/data-params.ic-stub-run.ok @@ -1,3 +1,6 @@ +→ install +← completed +→ update go(0x4449444c0000) 0 +1 +3 @@ -15,9 +18,12 @@ +1_006_191 +1_006_211 +1_006_211 -Foo1: +1_006_211 -μεταγράψτε: +1_006_211 -Foo2: +1_006_211 +Foo1: ++1_006_211 +μεταγράψτε: ++1_006_211 +Foo2: ++1_006_211 +10_000_001_006_211 +20_000_001_006_211 +1_006_211 @@ -36,3 +42,4 @@ Foo2: +1_006_211 +2_148_489_911 +2_148_489_869 +4_295_973_516 +← completed: 0x4449444c0000 diff --git a/test/run-stub/ok/data-params.run-ir.ok b/test/run-stub/ok/data-params.run-ir.ok new file mode 100644 index 00000000000..8121106181c --- /dev/null +++ b/test/run-stub/ok/data-params.run-ir.ok @@ -0,0 +1,4 @@ +data-params.mo:49.30-49.40: warning, this pattern consuming type + ?Text +does not cover value + null diff --git a/test/run-stub/ok/data-params.run-low.ok b/test/run-stub/ok/data-params.run-low.ok new file mode 100644 index 00000000000..8121106181c --- /dev/null +++ b/test/run-stub/ok/data-params.run-low.ok @@ -0,0 +1,4 @@ +data-params.mo:49.30-49.40: warning, this pattern consuming type + ?Text +does not cover value + null diff --git a/test/run-stub/ok/data-params.run.ok b/test/run-stub/ok/data-params.run.ok new file mode 100644 index 00000000000..8121106181c --- /dev/null +++ b/test/run-stub/ok/data-params.run.ok @@ -0,0 +1,4 @@ +data-params.mo:49.30-49.40: warning, this pattern consuming type + ?Text +does not cover value + null diff --git a/test/run-stub/ok/data-params.tc.ok b/test/run-stub/ok/data-params.tc.ok new file mode 100644 index 00000000000..8121106181c --- /dev/null +++ b/test/run-stub/ok/data-params.tc.ok @@ -0,0 +1,4 @@ +data-params.mo:49.30-49.40: warning, this pattern consuming type + ?Text +does not cover value + null From b358e09fcfceffc4b12e05c0cd170e4f531b2de9 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 15 Nov 2019 11:53:32 +0100 Subject: [PATCH 0614/1176] A Persistence story for Winter --- ic-stub/ic-stub.cabal | 1 + ic-stub/src/IC/Canister/Pure.hs | 1 - ic-stub/src/IC/Wasm/Winter.hs | 16 ++-- ic-stub/src/IC/Wasm/Winter/Persist.hs | 112 ++++++++++++++++++++++++++ nix/haskell-packages.nix | 4 +- 5 files changed, 125 insertions(+), 9 deletions(-) create mode 100644 ic-stub/src/IC/Wasm/Winter/Persist.hs diff --git a/ic-stub/ic-stub.cabal b/ic-stub/ic-stub.cabal index 11db148afd0..694fe60bb24 100644 --- a/ic-stub/ic-stub.cabal +++ b/ic-stub/ic-stub.cabal @@ -17,6 +17,7 @@ executable ic-stub-run other-modules: IC.Canister.Imp other-modules: IC.Canister.Pure other-modules: IC.Wasm.Winter + other-modules: IC.Wasm.Winter.Persist other-modules: IC.Wasm.Imports other-modules: IC.DRun.Parse build-depends: base >=4.11 && <5 diff --git a/ic-stub/src/IC/Canister/Pure.hs b/ic-stub/src/IC/Canister/Pure.hs index 01af4ddb5f7..d44039739a9 100644 --- a/ic-stub/src/IC/Canister/Pure.hs +++ b/ic-stub/src/IC/Canister/Pure.hs @@ -120,4 +120,3 @@ replay esref s = silently esref $ go s is <- go s _ <- rawCallbackMethod is cb caller r >>= trapToFail return is - diff --git a/ic-stub/src/IC/Wasm/Winter.hs b/ic-stub/src/IC/Wasm/Winter.hs index 4704faa3150..2fe17e1aa79 100644 --- a/ic-stub/src/IC/Wasm/Winter.hs +++ b/ic-stub/src/IC/Wasm/Winter.hs @@ -49,7 +49,7 @@ import qualified Wasm.Syntax.Types as W import qualified Wasm.Syntax.Values as W import qualified Wasm.Syntax.Memory as W -type Instance s = (IM.IntMap (W.ModuleInst Identity (ST s)), W.ModuleInst Identity (ST s)) +type Instance s = (IM.IntMap (W.ModuleInst Identity (ST s)), Int) type HostM s = ExceptT String (ST s) @@ -87,7 +87,7 @@ initialize mod imps = withExceptT show $ do ] (ref, inst) <- W.initialize (Identity mod) names mods let mods' = IM.insert ref inst mods - return (mods', inst) + return (mods', ref) exportedFunctions :: Module -> [String] @@ -99,24 +99,28 @@ exportedFunctions wasm_mod = invokeExport :: Instance s -> String -> [W.Value] -> HostM s [W.Value] -invokeExport (mods', inst) method args = +invokeExport (mods', ref) method args = do + let inst = mods' IM.! ref withExceptT show $ W.invokeByName mods' inst (T.pack method) args invokeTable :: Instance s -> Int32 -> [W.Value] -> HostM s [W.Value] -invokeTable (mods', inst) idx args = +invokeTable (mods', ref) idx args = do + let inst = mods' IM.! ref withExceptT show $ do func <- W.elem inst 0 idx def W.invoke mods' inst func args getBytes :: Instance s -> W.Address -> W.Size -> HostM s BS.ByteString -getBytes (_, inst) ptr len = do +getBytes (mods', ref) ptr len = do + let inst = mods' IM.! ref let mem = head (W._miMemories inst) vec <- withExceptT show $ W.loadBytes mem ptr len return $ BS.pack $ V.toList vec setBytes :: Instance s -> W.Address -> BS.ByteString -> HostM s () -setBytes (_, inst) ptr blob = do +setBytes (mods', ref) ptr blob = do + let inst = mods' IM.! ref let mem = head (W._miMemories inst) withExceptT show $ W.storeBytes mem (fromIntegral ptr) (V.fromList (BS.unpack blob)) diff --git a/ic-stub/src/IC/Wasm/Winter/Persist.hs b/ic-stub/src/IC/Wasm/Winter/Persist.hs new file mode 100644 index 00000000000..90276fa0cce --- /dev/null +++ b/ic-stub/src/IC/Wasm/Winter/Persist.hs @@ -0,0 +1,112 @@ +{-# LANGUAGE ExplicitForAll #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE FlexibleInstances #-} +{- | +This module provides a way to persist the state of a Winter Wasm instance, and +to recover it. + +It is tailored to the use by ic-stub. For example it assumes that the +table of a wasm instance is immutable. +-} +module IC.Wasm.Winter.Persist where + +import Control.Monad.Identity +import Control.Monad.ST +import Data.Primitive.MutVar +import qualified Data.IntMap as IM +import qualified Data.Map.Lazy as M +import qualified Data.Text.Lazy as T +import Data.Word +import qualified Data.Vector.Unboxed as V + +import qualified Wasm.Runtime.Global as W +import qualified Wasm.Runtime.Instance as W +import qualified Wasm.Runtime.Memory as W +import qualified Wasm.Syntax.Values as W + +type Instance s = (IM.IntMap (W.ModuleInst Identity (ST s)), Int) + +-- | +-- This stores data read from an instance. +-- +-- Note that an 'Instance' has aliasing, the same global may appear in various +-- spots. We don’t worry about that for now and just de-alias on reading, at the +-- expense of writing the corresponding mutable values more than once. +newtype PInstance = PInstance (IM.IntMap PModuleInst) + +persistInstance :: Instance s -> ST s PInstance +persistInstance (i,_) = PInstance <$> persist1 i + + +class Persistable f where + type Persisted f :: * + persist :: f (ST s) -> ST s (Persisted f) + resume :: f (ST s) -> Persisted f -> ST s () + +instance Persistable W.MemoryInst where + type Persisted W.MemoryInst = V.Vector Word8 + persist m = readMutVar (W._miContent m) >>= V.freeze + resume m v = V.thaw v >>= writeMutVar (W._miContent m) + +instance Persistable W.GlobalInst where + type Persisted W.GlobalInst = W.Value + persist m = readMutVar (W._giContent m) + resume m = writeMutVar (W._giContent m) + + +data PExtern + = PExternMemory (Persisted W.MemoryInst) + | PExternGlobal (Persisted W.GlobalInst) + | PExternOther + +instance Persistable (W.Extern f) where + type Persisted (W.Extern f) = PExtern + + persist (W.ExternGlobal g) = PExternGlobal <$> persist g + persist (W.ExternMemory m) = PExternMemory <$> persist m + persist _ = return PExternOther + + resume (W.ExternGlobal g) (PExternGlobal pg) = resume g pg + resume (W.ExternMemory m) (PExternMemory pm) = resume m pm + resume _ _ = return () + +data PModuleInst = PModuleInst + { memories :: [Persisted W.MemoryInst] + , globals :: [Persisted W.GlobalInst] + , exports :: M.Map T.Text (Persisted (W.Extern Identity)) + } + +instance Persistable (W.ModuleInst Identity) where + type Persisted (W.ModuleInst Identity) = PModuleInst + persist inst = PModuleInst + <$> persist1 (W._miMemories inst) + <*> persist1 (W._miGlobals inst) + <*> persist1 (W._miExports inst) + resume inst pinst = do + resume1 (W._miMemories inst) (memories pinst) + resume1 (W._miGlobals inst) (globals pinst) + resume1 (W._miExports inst) (exports pinst) + + +class Persistable1 c f where + persist1 :: c (f (ST s)) -> ST s (c (Persisted f)) + resume1 :: c (f (ST s)) -> c (Persisted f) -> ST s () + +instance Persistable f => Persistable1 [] f where + persist1 = mapM persist + resume1 xs ys = do + unless (length xs == length ys) $ fail "Lengths don’t match" + zipWithM_ resume xs ys + +instance (Eq k, Persistable f) => Persistable1 (M.Map k) f where + persist1 = mapM persist + resume1 xs ys = do + unless (M.keys xs == M.keys ys) $ fail "Map keys don’t match" + zipWithM_ resume (M.elems xs) (M.elems ys) + +instance Persistable f => Persistable1 IM.IntMap f where + persist1 = mapM persist + resume1 xs ys = do + unless (IM.keys xs == IM.keys ys) $ fail "Map keys don’t match" + zipWithM_ resume (IM.elems xs) (IM.elems ys) diff --git a/nix/haskell-packages.nix b/nix/haskell-packages.nix index 6a7df7dbba9..0061c9e5876 100644 --- a/nix/haskell-packages.nix +++ b/nix/haskell-packages.nix @@ -100,8 +100,8 @@ nix: subpath: (nix.fetchFromGitHub { owner = "nomeata"; repo = "winter"; - rev = "0c1f8e0e473b904c341fca320d648139ee084c72"; - sha256 = "09gmzcbwck15l6461w9mg9glm7mimx5mwrpb8qzg0pwmd9gdji3z"; + rev = "eb8add32c7de95ccdaf1c896f894814833633bbc"; + sha256 = "05pa6fwvs7galf0gnjngampfdfrki8zjd92f4hzr9yv75jxzv10v"; }) "--no-check" {}; ic-stub = self.callCabal2nixWithOptions "ic-stub" (subpath "ic-stub") "-frelease" { }; From c236c62da4944a47d152e3051810903fb5d9202f Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 15 Nov 2019 12:07:07 +0100 Subject: [PATCH 0615/1176] Simplify Persistable type class setup a bit --- ic-stub/src/IC/Wasm/Winter/Persist.hs | 102 +++++++++++++++----------- 1 file changed, 61 insertions(+), 41 deletions(-) diff --git a/ic-stub/src/IC/Wasm/Winter/Persist.hs b/ic-stub/src/IC/Wasm/Winter/Persist.hs index 90276fa0cce..66c637538d6 100644 --- a/ic-stub/src/IC/Wasm/Winter/Persist.hs +++ b/ic-stub/src/IC/Wasm/Winter/Persist.hs @@ -2,6 +2,7 @@ {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE FlexibleContexts #-} {- | This module provides a way to persist the state of a Winter Wasm instance, and to recover it. @@ -9,7 +10,12 @@ to recover it. It is tailored to the use by ic-stub. For example it assumes that the table of a wasm instance is immutable. -} -module IC.Wasm.Winter.Persist where +module IC.Wasm.Winter.Persist + ( PInstance + , persistInstance + , resumeInstance + ) + where import Control.Monad.Identity import Control.Monad.ST @@ -25,7 +31,7 @@ import qualified Wasm.Runtime.Instance as W import qualified Wasm.Runtime.Memory as W import qualified Wasm.Syntax.Values as W -type Instance s = (IM.IntMap (W.ModuleInst Identity (ST s)), Int) +import IC.Wasm.Winter (Instance) -- | -- This stores data read from an instance. @@ -33,35 +39,40 @@ type Instance s = (IM.IntMap (W.ModuleInst Identity (ST s)), Int) -- Note that an 'Instance' has aliasing, the same global may appear in various -- spots. We don’t worry about that for now and just de-alias on reading, at the -- expense of writing the corresponding mutable values more than once. -newtype PInstance = PInstance (IM.IntMap PModuleInst) +newtype PInstance = PInstance (Persisted (Instance ())) persistInstance :: Instance s -> ST s PInstance -persistInstance (i,_) = PInstance <$> persist1 i +persistInstance i = PInstance <$> persist i +resumeInstance :: Instance s -> PInstance -> ST s () +resumeInstance i (PInstance p) = resume i p -class Persistable f where - type Persisted f :: * - persist :: f (ST s) -> ST s (Persisted f) - resume :: f (ST s) -> Persisted f -> ST s () +class Monad (M a) => Persistable a where + type Persisted a :: * + type M a :: * -> * + persist :: a -> M a (Persisted a) + resume :: a -> Persisted a -> M a () -instance Persistable W.MemoryInst where - type Persisted W.MemoryInst = V.Vector Word8 +instance Persistable (W.MemoryInst (ST s)) where + type Persisted (W.MemoryInst (ST s)) = V.Vector Word8 + type M (W.MemoryInst (ST s)) = ST s persist m = readMutVar (W._miContent m) >>= V.freeze resume m v = V.thaw v >>= writeMutVar (W._miContent m) -instance Persistable W.GlobalInst where - type Persisted W.GlobalInst = W.Value +instance Persistable (W.GlobalInst (ST s)) where + type Persisted (W.GlobalInst (ST s)) = W.Value + type M (W.GlobalInst (ST s)) = ST s persist m = readMutVar (W._giContent m) resume m = writeMutVar (W._giContent m) - data PExtern - = PExternMemory (Persisted W.MemoryInst) - | PExternGlobal (Persisted W.GlobalInst) + = PExternMemory (Persisted (W.MemoryInst (ST ()))) + | PExternGlobal (Persisted (W.GlobalInst (ST ()))) | PExternOther -instance Persistable (W.Extern f) where - type Persisted (W.Extern f) = PExtern +instance Persistable (W.Extern f (ST s)) where + type Persisted (W.Extern f (ST s)) = PExtern + type M (W.Extern f (ST s)) = ST s persist (W.ExternGlobal g) = PExternGlobal <$> persist g persist (W.ExternMemory m) = PExternMemory <$> persist m @@ -72,41 +83,50 @@ instance Persistable (W.Extern f) where resume _ _ = return () data PModuleInst = PModuleInst - { memories :: [Persisted W.MemoryInst] - , globals :: [Persisted W.GlobalInst] - , exports :: M.Map T.Text (Persisted (W.Extern Identity)) + { memories :: [Persisted (W.MemoryInst (ST ()))] + , globals :: [Persisted (W.GlobalInst (ST ()))] + , exports :: M.Map T.Text (Persisted (W.Extern Identity (ST ()))) } -instance Persistable (W.ModuleInst Identity) where - type Persisted (W.ModuleInst Identity) = PModuleInst +instance Persistable (W.ModuleInst Identity (ST s)) where + type Persisted (W.ModuleInst Identity (ST s)) = PModuleInst + type M (W.ModuleInst Identity (ST s)) = ST s persist inst = PModuleInst - <$> persist1 (W._miMemories inst) - <*> persist1 (W._miGlobals inst) - <*> persist1 (W._miExports inst) + <$> persist (W._miMemories inst) + <*> persist (W._miGlobals inst) + <*> persist (W._miExports inst) resume inst pinst = do - resume1 (W._miMemories inst) (memories pinst) - resume1 (W._miGlobals inst) (globals pinst) - resume1 (W._miExports inst) (exports pinst) - + resume (W._miMemories inst) (memories pinst) + resume (W._miGlobals inst) (globals pinst) + resume (W._miExports inst) (exports pinst) -class Persistable1 c f where - persist1 :: c (f (ST s)) -> ST s (c (Persisted f)) - resume1 :: c (f (ST s)) -> c (Persisted f) -> ST s () -instance Persistable f => Persistable1 [] f where - persist1 = mapM persist - resume1 xs ys = do +instance Persistable a => Persistable [a] where + type Persisted [a] = [Persisted a] + type M [a] = M a + persist = mapM persist + resume xs ys = do unless (length xs == length ys) $ fail "Lengths don’t match" zipWithM_ resume xs ys -instance (Eq k, Persistable f) => Persistable1 (M.Map k) f where - persist1 = mapM persist - resume1 xs ys = do +instance (Eq k, Persistable a) => Persistable (M.Map k a) where + type Persisted (M.Map k a) = M.Map k (Persisted a) + type M (M.Map k a) = M a + persist = mapM persist + resume xs ys = do unless (M.keys xs == M.keys ys) $ fail "Map keys don’t match" zipWithM_ resume (M.elems xs) (M.elems ys) -instance Persistable f => Persistable1 IM.IntMap f where - persist1 = mapM persist - resume1 xs ys = do +instance Persistable a => Persistable (IM.IntMap a) where + type Persisted (IM.IntMap a) = IM.IntMap (Persisted a) + type M (IM.IntMap a) = M a + persist = mapM persist + resume xs ys = do unless (IM.keys xs == IM.keys ys) $ fail "Map keys don’t match" zipWithM_ resume (IM.elems xs) (IM.elems ys) + +instance Persistable a => Persistable (a, Int) where + type Persisted (a, Int) = Persisted a + type M (a, Int) = M a + persist (a, _i) = persist a + resume (a, _i) p = resume a p From aa7aef3e78f2499558674a78372122d0426e6baf Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 15 Nov 2019 12:46:24 +0100 Subject: [PATCH 0616/1176] =?UTF-8?q?Use=20=E2=80=9Cpersistence=E2=80=9D?= =?UTF-8?q?=20in=20the=20IC=20Stub?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We keep the `IC.Canister.Pure` around, may come in handy to debug stuff. --- ic-stub/ic-stub.cabal | 1 + ic-stub/src/IC/Canister/Imp.hs | 18 +++-- ic-stub/src/IC/Canister/Persisted.hs | 117 +++++++++++++++++++++++++++ ic-stub/src/IC/Canister/Pure.hs | 25 +++--- ic-stub/src/IC/Stub.hs | 2 +- 5 files changed, 146 insertions(+), 17 deletions(-) create mode 100644 ic-stub/src/IC/Canister/Persisted.hs diff --git a/ic-stub/ic-stub.cabal b/ic-stub/ic-stub.cabal index 694fe60bb24..346156c5d13 100644 --- a/ic-stub/ic-stub.cabal +++ b/ic-stub/ic-stub.cabal @@ -16,6 +16,7 @@ executable ic-stub-run other-modules: IC.Types other-modules: IC.Canister.Imp other-modules: IC.Canister.Pure + other-modules: IC.Canister.Persisted other-modules: IC.Wasm.Winter other-modules: IC.Wasm.Winter.Persist other-modules: IC.Wasm.Imports diff --git a/ic-stub/src/IC/Canister/Imp.hs b/ic-stub/src/IC/Canister/Imp.hs index bbc54897d29..26e1bbdbb69 100644 --- a/ic-stub/src/IC/Canister/Imp.hs +++ b/ic-stub/src/IC/Canister/Imp.hs @@ -11,6 +11,7 @@ module IC.Canister.Imp ( ESRef , ImpState , runESST + , rawInitializeModule , rawInitializeMethod , rawUpdateMethod , rawCallbackMethod @@ -294,11 +295,16 @@ systemAPI esref = type ImpState s = (ESRef s, CanisterId, Instance s) -rawInitializeMethod :: ESRef s -> Module -> CanisterId -> EntityId -> Blob -> ST s (TrapOr (ImpState s)) -rawInitializeMethod esref wasm_mod cid caller dat = do - result <- runExceptT $ do - inst <- initialize wasm_mod (systemAPI esref) +rawInitializeModule :: ESRef s -> Module -> ST s (TrapOr (Instance s)) +rawInitializeModule esref wasm_mod = do + result <- runExceptT $ initialize wasm_mod (systemAPI esref) + case result of + Left err -> return $ Trap err + Right inst -> return $ Return inst +rawInitializeMethod :: ESRef s -> Module -> Instance s -> CanisterId -> EntityId -> Blob -> ST s (TrapOr ()) +rawInitializeMethod esref wasm_mod inst cid caller dat = do + result <- runExceptT $ do let es = (initalExecutionState cid inst) { params = Params { param_dat = Just dat @@ -313,11 +319,9 @@ rawInitializeMethod esref wasm_mod cid caller dat = do void $ withES esref es $ invokeExport inst "canister_init" [] -- TODO: Check no calls are made - - return (esref, cid, inst) case result of Left err -> return $ Trap err - Right raw_state -> return $ Return raw_state + Right () -> return $ Return () rawQueryMethod :: ImpState s -> MethodName -> EntityId -> Blob -> ST s (TrapOr Response) rawQueryMethod (esref, cid, inst) method caller dat = do diff --git a/ic-stub/src/IC/Canister/Persisted.hs b/ic-stub/src/IC/Canister/Persisted.hs new file mode 100644 index 00000000000..64c88842220 --- /dev/null +++ b/ic-stub/src/IC/Canister/Persisted.hs @@ -0,0 +1,117 @@ +{-# LANGUAGE TypeOperators #-} +{-# LANGUAGE ConstraintKinds #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE RankNTypes #-} +{-# LANGUAGE LambdaCase #-} + +{-# OPTIONS_GHC -Wmissing-signatures #-} +{-| +An implementation of canisters based on persistence, using "IC.Canister.Imp". It has the same interface as "IC.Canister.Pure". +-} + +module IC.Canister.Persisted + ( WasmState + , parseCanister + , CanisterModule(..) + , InitFunc, UpdateFunc, QueryFunc + ) + where + +import qualified Data.Map as M +import Data.List +import Control.Monad.ST + +import IC.Types +import IC.Wasm.Winter (parseModule, exportedFunctions, Module) +import IC.Wasm.Winter.Persist +import IC.Canister.Imp + +data WasmState = WasmState Module CanisterId PInstance + +type InitFunc = CanisterId -> EntityId -> Blob -> TrapOr WasmState +type UpdateFunc = WasmState -> TrapOr (WasmState, [MethodCall], Maybe Response) +type QueryFunc = WasmState -> TrapOr Response + +data CanisterModule = CanisterModule + { init_method :: InitFunc + , update_methods :: MethodName ↦ (EntityId -> Blob -> UpdateFunc) + , query_methods :: MethodName ↦ (EntityId -> Blob -> QueryFunc) + , callbacks :: Callback -> EntityId -> Response -> UpdateFunc + } + +parseCanister :: Blob -> Either String CanisterModule +parseCanister bytes = + case parseModule bytes of + Left err -> Left err + Right wasm_mod -> Right $ concreteToAbstractModule wasm_mod + +concreteToAbstractModule :: Module -> CanisterModule +concreteToAbstractModule wasm_mod = CanisterModule + { init_method = \cid caller dat -> initializeMethod wasm_mod cid caller dat + , update_methods = M.fromList + [ (m, \caller dat wasm_state -> updateMethod m caller dat wasm_state) + | n <- exportedFunctions wasm_mod + , Just m <- return $ stripPrefix "canister_update " n + ] + , query_methods = M.fromList + [ (m, \arg wasm_state -> queryMethod m arg wasm_state) + | n <- exportedFunctions wasm_mod + , Just m <- return $ stripPrefix "canister_query " n + ] + , callbacks = callbackMethod + } + +initializeMethod :: Module -> CanisterId -> EntityId -> Blob -> TrapOr WasmState +initializeMethod wasm_mod cid caller dat = runESST $ \esref -> + rawInitializeModule esref wasm_mod >>= \case + Trap err -> return $ Trap err + Return inst -> + rawInitializeMethod esref wasm_mod inst cid caller dat >>= \case + Trap err -> return $ Trap err + Return () -> Return . WasmState wasm_mod cid <$> persistInstance inst + +updateMethod :: + MethodName -> EntityId -> Blob -> + WasmState -> TrapOr (WasmState, [MethodCall], Maybe Response) +updateMethod m caller dat s = runESST $ \esref -> do + rs <- replay esref s + tor <- rawUpdateMethod rs m caller dat + case tor of + Trap msg -> return $ Trap msg + Return (calls, r) -> do + state' <- persist s rs + return $ Return (state', calls, r) + +callbackMethod :: + Callback -> EntityId -> Response -> + WasmState -> TrapOr (WasmState, [MethodCall], Maybe Response) +callbackMethod cb caller r s = runESST $ \esref -> do + rs <- replay esref s + tor <- rawCallbackMethod rs cb caller r + case tor of + Trap msg -> return $ Trap msg + Return (calls, r) -> do + state' <- persist s rs + return $ Return (state', calls, r) + +queryMethod :: MethodName -> EntityId -> Blob -> WasmState -> TrapOr Response +queryMethod m caller dat s = runESST $ \esref -> do + rs <- replay esref s + rawQueryMethod rs m caller dat + + +replay :: ESRef s -> WasmState -> ST s (ImpState s) +replay esref (WasmState wasm_mod cid pinst) = do + is <- rawInitializeModule esref wasm_mod >>= trapToFail + resumeInstance is pinst + return (esref, cid, is) + where + trapToFail (Trap _err) = fail "replay failed" + trapToFail (Return x) = return x + +persist :: WasmState -> ImpState s -> ST s WasmState +persist (WasmState wasm_mod cid _) (_, _, inst) = + WasmState wasm_mod cid <$> persistInstance inst diff --git a/ic-stub/src/IC/Canister/Pure.hs b/ic-stub/src/IC/Canister/Pure.hs index d44039739a9..354570305e2 100644 --- a/ic-stub/src/IC/Canister/Pure.hs +++ b/ic-stub/src/IC/Canister/Pure.hs @@ -5,6 +5,7 @@ {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE RankNTypes #-} +{-# LANGUAGE LambdaCase #-} {-# OPTIONS_GHC -Wmissing-signatures #-} {-| @@ -69,12 +70,15 @@ concreteToAbstractModule wasm_mod = CanisterModule } initializeMethod :: Module -> CanisterId -> EntityId -> Blob -> TrapOr WasmState -initializeMethod wasm_mod cid caller dat = runESST $ \esref -> do - result <- rawInitializeMethod esref wasm_mod cid caller dat - let state' = WSInit wasm_mod cid caller dat - case result of - Trap err -> return $ Trap err - Return _raw_state -> return $ Return state' +initializeMethod wasm_mod cid caller dat = runESST $ \esref -> + rawInitializeModule esref wasm_mod >>= \case + Trap err -> return $ Trap err + Return inst -> do + result <- rawInitializeMethod esref wasm_mod inst cid caller dat + let state' = WSInit wasm_mod cid caller dat + case result of + Trap err -> return $ Trap err + Return _raw_state -> return $ Return state' updateMethod :: MethodName -> EntityId -> Blob -> @@ -104,14 +108,17 @@ queryMethod m caller dat s = runESST $ \esref -> do rawQueryMethod rs m caller dat -replay :: ESRef s -> WasmState -> ST s (ImpState s) +replay :: forall s. ESRef s -> WasmState -> ST s (ImpState s) replay esref s = silently esref $ go s where trapToFail (Trap _err) = fail "replay failed" trapToFail (Return x) = return x - go (WSInit wasm_mod cid caller dat) = - rawInitializeMethod esref wasm_mod cid caller dat >>= trapToFail + go :: WasmState -> ST s (ImpState s) + go (WSInit wasm_mod cid caller dat) = do + inst <- rawInitializeModule esref wasm_mod >>= trapToFail + rawInitializeMethod esref wasm_mod inst cid caller dat >>= trapToFail + return (esref, cid, inst) go (WSUpdate m caller dat s) = do is <- go s _ <- rawUpdateMethod is m caller dat >>= trapToFail diff --git a/ic-stub/src/IC/Stub.hs b/ic-stub/src/IC/Stub.hs index 06302fb63e6..c60492d75b2 100644 --- a/ic-stub/src/IC/Stub.hs +++ b/ic-stub/src/IC/Stub.hs @@ -33,7 +33,7 @@ import Control.Monad.State.Class -- import Debug.Trace import IC.Types -import IC.Canister.Pure +import IC.Canister.Persisted -- Abstract HTTP Interface From bef114da0b8dc9864c03b92d65ec6f15ce9bd48e Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 15 Nov 2019 13:11:37 +0100 Subject: [PATCH 0617/1176] Remove some code duplication --- ic-stub/ic-stub.cabal | 1 + ic-stub/src/IC/Canister.hs | 60 ++++++++++++++++++++++++++++ ic-stub/src/IC/Canister/Persisted.hs | 51 +++-------------------- ic-stub/src/IC/Canister/Pure.hs | 49 +++-------------------- ic-stub/src/IC/Stub.hs | 2 +- 5 files changed, 72 insertions(+), 91 deletions(-) create mode 100644 ic-stub/src/IC/Canister.hs diff --git a/ic-stub/ic-stub.cabal b/ic-stub/ic-stub.cabal index 346156c5d13..49a6ac555e0 100644 --- a/ic-stub/ic-stub.cabal +++ b/ic-stub/ic-stub.cabal @@ -14,6 +14,7 @@ executable ic-stub-run hs-source-dirs: src other-modules: IC.Stub other-modules: IC.Types + other-modules: IC.Canister other-modules: IC.Canister.Imp other-modules: IC.Canister.Pure other-modules: IC.Canister.Persisted diff --git a/ic-stub/src/IC/Canister.hs b/ic-stub/src/IC/Canister.hs new file mode 100644 index 00000000000..39b1ae8afb4 --- /dev/null +++ b/ic-stub/src/IC/Canister.hs @@ -0,0 +1,60 @@ +{-# LANGUAGE TypeOperators #-} + +{-| +A “pure” implementation of canisters, using "IC.Canister.Imp", but just replaying when needed. +Note that this is quadratic in the number of update calls, so do not run such canisters for long. + +We could do some hacking caching of state using stable names, so that as long as no trap occurs, 'replay' is fast. +-} + +module IC.Canister + ( WasmState + , parseCanister + , CanisterModule(..) + , InitFunc, UpdateFunc, QueryFunc + ) + where + +import qualified Data.Map as M +import Data.List +import Control.Monad.ST + +import IC.Types +import IC.Wasm.Winter (parseModule, exportedFunctions, Module) +import IC.Canister.Imp + +-- Here we can swap out the persistence implementation +import IC.Canister.Pure + +type InitFunc = CanisterId -> EntityId -> Blob -> TrapOr WasmState +type UpdateFunc = WasmState -> TrapOr (WasmState, [MethodCall], Maybe Response) +type QueryFunc = WasmState -> TrapOr Response + +data CanisterModule = CanisterModule + { init_method :: InitFunc + , update_methods :: MethodName ↦ (EntityId -> Blob -> UpdateFunc) + , query_methods :: MethodName ↦ (EntityId -> Blob -> QueryFunc) + , callbacks :: Callback -> EntityId -> Response -> UpdateFunc + } + +parseCanister :: Blob -> Either String CanisterModule +parseCanister bytes = + case parseModule bytes of + Left err -> Left err + Right wasm_mod -> Right $ concreteToAbstractModule wasm_mod + +concreteToAbstractModule :: Module -> CanisterModule +concreteToAbstractModule wasm_mod = CanisterModule + { init_method = \cid caller dat -> initializeMethod wasm_mod cid caller dat + , update_methods = M.fromList + [ (m, \caller dat wasm_state -> updateMethod m caller dat wasm_state) + | n <- exportedFunctions wasm_mod + , Just m <- return $ stripPrefix "canister_update " n + ] + , query_methods = M.fromList + [ (m, \arg wasm_state -> queryMethod m arg wasm_state) + | n <- exportedFunctions wasm_mod + , Just m <- return $ stripPrefix "canister_query " n + ] + , callbacks = callbackMethod + } diff --git a/ic-stub/src/IC/Canister/Persisted.hs b/ic-stub/src/IC/Canister/Persisted.hs index 64c88842220..eb26530869b 100644 --- a/ic-stub/src/IC/Canister/Persisted.hs +++ b/ic-stub/src/IC/Canister/Persisted.hs @@ -1,10 +1,3 @@ -{-# LANGUAGE TypeOperators #-} -{-# LANGUAGE ConstraintKinds #-} -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE NamedFieldPuns #-} -{-# LANGUAGE TypeFamilies #-} -{-# LANGUAGE ScopedTypeVariables #-} -{-# LANGUAGE RankNTypes #-} {-# LANGUAGE LambdaCase #-} {-# OPTIONS_GHC -Wmissing-signatures #-} @@ -14,56 +7,22 @@ An implementation of canisters based on persistence, using "IC.Canister.Imp". It module IC.Canister.Persisted ( WasmState - , parseCanister - , CanisterModule(..) - , InitFunc, UpdateFunc, QueryFunc + , initializeMethod + , updateMethod + , callbackMethod + , queryMethod ) where -import qualified Data.Map as M -import Data.List import Control.Monad.ST import IC.Types -import IC.Wasm.Winter (parseModule, exportedFunctions, Module) +import IC.Wasm.Winter (Module) import IC.Wasm.Winter.Persist import IC.Canister.Imp data WasmState = WasmState Module CanisterId PInstance -type InitFunc = CanisterId -> EntityId -> Blob -> TrapOr WasmState -type UpdateFunc = WasmState -> TrapOr (WasmState, [MethodCall], Maybe Response) -type QueryFunc = WasmState -> TrapOr Response - -data CanisterModule = CanisterModule - { init_method :: InitFunc - , update_methods :: MethodName ↦ (EntityId -> Blob -> UpdateFunc) - , query_methods :: MethodName ↦ (EntityId -> Blob -> QueryFunc) - , callbacks :: Callback -> EntityId -> Response -> UpdateFunc - } - -parseCanister :: Blob -> Either String CanisterModule -parseCanister bytes = - case parseModule bytes of - Left err -> Left err - Right wasm_mod -> Right $ concreteToAbstractModule wasm_mod - -concreteToAbstractModule :: Module -> CanisterModule -concreteToAbstractModule wasm_mod = CanisterModule - { init_method = \cid caller dat -> initializeMethod wasm_mod cid caller dat - , update_methods = M.fromList - [ (m, \caller dat wasm_state -> updateMethod m caller dat wasm_state) - | n <- exportedFunctions wasm_mod - , Just m <- return $ stripPrefix "canister_update " n - ] - , query_methods = M.fromList - [ (m, \arg wasm_state -> queryMethod m arg wasm_state) - | n <- exportedFunctions wasm_mod - , Just m <- return $ stripPrefix "canister_query " n - ] - , callbacks = callbackMethod - } - initializeMethod :: Module -> CanisterId -> EntityId -> Blob -> TrapOr WasmState initializeMethod wasm_mod cid caller dat = runESST $ \esref -> rawInitializeModule esref wasm_mod >>= \case diff --git a/ic-stub/src/IC/Canister/Pure.hs b/ic-stub/src/IC/Canister/Pure.hs index 354570305e2..c6e2aa57b42 100644 --- a/ic-stub/src/IC/Canister/Pure.hs +++ b/ic-stub/src/IC/Canister/Pure.hs @@ -1,8 +1,3 @@ -{-# LANGUAGE TypeOperators #-} -{-# LANGUAGE ConstraintKinds #-} -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE NamedFieldPuns #-} -{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE LambdaCase #-} @@ -17,18 +12,17 @@ We could do some hacking caching of state using stable names, so that as long as module IC.Canister.Pure ( WasmState - , parseCanister - , CanisterModule(..) - , InitFunc, UpdateFunc, QueryFunc + , initializeMethod + , updateMethod + , callbackMethod + , queryMethod ) where -import qualified Data.Map as M -import Data.List import Control.Monad.ST import IC.Types -import IC.Wasm.Winter (parseModule, exportedFunctions, Module) +import IC.Wasm.Winter (Module) import IC.Canister.Imp data WasmState @@ -36,39 +30,6 @@ data WasmState | WSUpdate MethodName EntityId Blob WasmState | WSCallback Callback EntityId Response WasmState -type InitFunc = CanisterId -> EntityId -> Blob -> TrapOr WasmState -type UpdateFunc = WasmState -> TrapOr (WasmState, [MethodCall], Maybe Response) -type QueryFunc = WasmState -> TrapOr Response - -data CanisterModule = CanisterModule - { init_method :: InitFunc - , update_methods :: MethodName ↦ (EntityId -> Blob -> UpdateFunc) - , query_methods :: MethodName ↦ (EntityId -> Blob -> QueryFunc) - , callbacks :: Callback -> EntityId -> Response -> UpdateFunc - } - -parseCanister :: Blob -> Either String CanisterModule -parseCanister bytes = - case parseModule bytes of - Left err -> Left err - Right wasm_mod -> Right $ concreteToAbstractModule wasm_mod - -concreteToAbstractModule :: Module -> CanisterModule -concreteToAbstractModule wasm_mod = CanisterModule - { init_method = \cid caller dat -> initializeMethod wasm_mod cid caller dat - , update_methods = M.fromList - [ (m, \caller dat wasm_state -> updateMethod m caller dat wasm_state) - | n <- exportedFunctions wasm_mod - , Just m <- return $ stripPrefix "canister_update " n - ] - , query_methods = M.fromList - [ (m, \arg wasm_state -> queryMethod m arg wasm_state) - | n <- exportedFunctions wasm_mod - , Just m <- return $ stripPrefix "canister_query " n - ] - , callbacks = callbackMethod - } - initializeMethod :: Module -> CanisterId -> EntityId -> Blob -> TrapOr WasmState initializeMethod wasm_mod cid caller dat = runESST $ \esref -> rawInitializeModule esref wasm_mod >>= \case diff --git a/ic-stub/src/IC/Stub.hs b/ic-stub/src/IC/Stub.hs index c60492d75b2..3597991934e 100644 --- a/ic-stub/src/IC/Stub.hs +++ b/ic-stub/src/IC/Stub.hs @@ -33,7 +33,7 @@ import Control.Monad.State.Class -- import Debug.Trace import IC.Types -import IC.Canister.Persisted +import IC.Canister -- Abstract HTTP Interface From f2954ac2417c44ef8cc707d37872f550a8b3ee86 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 15 Nov 2019 13:23:06 +0100 Subject: [PATCH 0618/1176] Fix warnings --- ic-stub/src/IC/Canister.hs | 2 -- 1 file changed, 2 deletions(-) diff --git a/ic-stub/src/IC/Canister.hs b/ic-stub/src/IC/Canister.hs index a80e20e7dbd..8d4707b051b 100644 --- a/ic-stub/src/IC/Canister.hs +++ b/ic-stub/src/IC/Canister.hs @@ -17,11 +17,9 @@ module IC.Canister import qualified Data.Map as M import Data.List -import Control.Monad.ST import IC.Types import IC.Wasm.Winter (parseModule, exportedFunctions, Module) -import IC.Canister.Imp -- Here we can swap out the persistence implementation import IC.Canister.Persisted From f2f6e5e188f101e3752655973ae3f5057ab17d72 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 15 Nov 2019 13:42:55 +0100 Subject: [PATCH 0619/1176] update test output --- test/run-drun/ok/self-calls.comp.ok | 9 --------- test/run-drun/ok/self-calls.run-ir.ok | 9 --------- test/run-drun/ok/self-calls.run-low.ok | 9 --------- test/run-drun/ok/self-calls.run.ok | 9 --------- 4 files changed, 36 deletions(-) delete mode 100644 test/run-drun/ok/self-calls.run-ir.ok delete mode 100644 test/run-drun/ok/self-calls.run-low.ok delete mode 100644 test/run-drun/ok/self-calls.run.ok diff --git a/test/run-drun/ok/self-calls.comp.ok b/test/run-drun/ok/self-calls.comp.ok index 7320705bb9f..736889609df 100644 --- a/test/run-drun/ok/self-calls.comp.ok +++ b/test/run-drun/ok/self-calls.comp.ok @@ -1,12 +1,3 @@ -self-calls.mo:21.9-21.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -self-calls.mo:23.9-23.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (1, false) or - (0 or -1 or _, _) self-calls.mo:19.20-19.23: type error, calling a shared function not yet supported (This is a limitation of the current version.) self-calls.mo:21.19-21.22: type error, calling a shared function not yet supported diff --git a/test/run-drun/ok/self-calls.run-ir.ok b/test/run-drun/ok/self-calls.run-ir.ok deleted file mode 100644 index 0dc2420ebed..00000000000 --- a/test/run-drun/ok/self-calls.run-ir.ok +++ /dev/null @@ -1,9 +0,0 @@ -self-calls.mo:21.9-21.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -self-calls.mo:23.9-23.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (1, false) or - (0 or -1 or _, _) diff --git a/test/run-drun/ok/self-calls.run-low.ok b/test/run-drun/ok/self-calls.run-low.ok deleted file mode 100644 index 0dc2420ebed..00000000000 --- a/test/run-drun/ok/self-calls.run-low.ok +++ /dev/null @@ -1,9 +0,0 @@ -self-calls.mo:21.9-21.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -self-calls.mo:23.9-23.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (1, false) or - (0 or -1 or _, _) diff --git a/test/run-drun/ok/self-calls.run.ok b/test/run-drun/ok/self-calls.run.ok deleted file mode 100644 index 0dc2420ebed..00000000000 --- a/test/run-drun/ok/self-calls.run.ok +++ /dev/null @@ -1,9 +0,0 @@ -self-calls.mo:21.9-21.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -self-calls.mo:23.9-23.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (1, false) or - (0 or -1 or _, _) From 5f825c174feaa7070b4fe9c0e389f494beeab7fc Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 15 Nov 2019 14:34:10 +0100 Subject: [PATCH 0620/1176] More cleaning out of test/run-dfinity --- test/run-dfinity/array-out-of-bounds.mo | 11 ----------- test/run-dfinity/hello-world2.mo | 7 ------- test/run-dfinity/hello-world3.mo | 14 -------------- test/run-dfinity/ok/array-out-of-bounds.dvm.ok | 4 ---- .../ok/array-out-of-bounds.run-ir.ok | 2 -- .../ok/array-out-of-bounds.run-low.ok | 2 -- test/run-dfinity/ok/array-out-of-bounds.run.ok | 2 -- test/run-dfinity/ok/hello-world2.dvm.ok | 1 - test/run-dfinity/ok/hello-world2.run-ir.ok | 1 - test/run-dfinity/ok/hello-world2.run-low.ok | 1 - test/run-dfinity/ok/hello-world2.run.ok | 1 - test/run-dfinity/ok/hello-world3.dvm.ok | 1 - test/run-dfinity/ok/hello-world3.run-ir.ok | 1 - test/run-dfinity/ok/hello-world3.run-low.ok | 1 - test/run-dfinity/ok/hello-world3.run.ok | 1 - test/run-drun/array-out-of-bounds.mo | 17 +++++++++++++++++ .../run-drun/ok/array-out-of-bounds.drun-run.ok | 3 +++ 17 files changed, 20 insertions(+), 50 deletions(-) delete mode 100644 test/run-dfinity/array-out-of-bounds.mo delete mode 100644 test/run-dfinity/hello-world2.mo delete mode 100644 test/run-dfinity/hello-world3.mo delete mode 100644 test/run-dfinity/ok/array-out-of-bounds.dvm.ok delete mode 100644 test/run-dfinity/ok/array-out-of-bounds.run-ir.ok delete mode 100644 test/run-dfinity/ok/array-out-of-bounds.run-low.ok delete mode 100644 test/run-dfinity/ok/array-out-of-bounds.run.ok delete mode 100644 test/run-dfinity/ok/hello-world2.dvm.ok delete mode 100644 test/run-dfinity/ok/hello-world2.run-ir.ok delete mode 100644 test/run-dfinity/ok/hello-world2.run-low.ok delete mode 100644 test/run-dfinity/ok/hello-world2.run.ok delete mode 100644 test/run-dfinity/ok/hello-world3.dvm.ok delete mode 100644 test/run-dfinity/ok/hello-world3.run-ir.ok delete mode 100644 test/run-dfinity/ok/hello-world3.run-low.ok delete mode 100644 test/run-dfinity/ok/hello-world3.run.ok create mode 100644 test/run-drun/array-out-of-bounds.mo create mode 100644 test/run-drun/ok/array-out-of-bounds.drun-run.ok diff --git a/test/run-dfinity/array-out-of-bounds.mo b/test/run-dfinity/array-out-of-bounds.mo deleted file mode 100644 index 38ec4293133..00000000000 --- a/test/run-dfinity/array-out-of-bounds.mo +++ /dev/null @@ -1,11 +0,0 @@ -let a = [0, 1, 2, 3, 4]; -let b = []; - -ignore(async { - ignore(a[5]); - debugPrint("Unreachable code reached\n"); -}); -ignore(async { - ignore(b[0]); - debugPrint("Unreachable code reached\n"); -}); diff --git a/test/run-dfinity/hello-world2.mo b/test/run-dfinity/hello-world2.mo deleted file mode 100644 index 46218e8ead3..00000000000 --- a/test/run-dfinity/hello-world2.mo +++ /dev/null @@ -1,7 +0,0 @@ -let a = actor { - public func hello() { - debugPrint("Hello World!\n"); - } -}; - -a.hello() diff --git a/test/run-dfinity/hello-world3.mo b/test/run-dfinity/hello-world3.mo deleted file mode 100644 index d5cc98a1d53..00000000000 --- a/test/run-dfinity/hello-world3.mo +++ /dev/null @@ -1,14 +0,0 @@ -let a = actor { - public func hello() { - debugPrint("Hello "); - }; - public func go() { - hello(); - world(); - }; - public func world() { - debugPrint("World!\n"); - }; -}; - -a.go() diff --git a/test/run-dfinity/ok/array-out-of-bounds.dvm.ok b/test/run-dfinity/ok/array-out-of-bounds.dvm.ok deleted file mode 100644 index 559bc83aa09..00000000000 --- a/test/run-dfinity/ok/array-out-of-bounds.dvm.ok +++ /dev/null @@ -1,4 +0,0 @@ -hypervisor: calling func$NNN failed with trap message: Uncaught RuntimeError: unreachable -hypervisor: calling func$NNN failed with trap message: Uncaught RuntimeError: unreachable -Array index out of bounds -Array index out of bounds diff --git a/test/run-dfinity/ok/array-out-of-bounds.run-ir.ok b/test/run-dfinity/ok/array-out-of-bounds.run-ir.ok deleted file mode 100644 index 130db1c6b7f..00000000000 --- a/test/run-dfinity/ok/array-out-of-bounds.run-ir.ok +++ /dev/null @@ -1,2 +0,0 @@ -array-out-of-bounds.mo:5.10-5.14: execution error, index out of bounds -array-out-of-bounds.mo:9.10-9.14: execution error, index out of bounds diff --git a/test/run-dfinity/ok/array-out-of-bounds.run-low.ok b/test/run-dfinity/ok/array-out-of-bounds.run-low.ok deleted file mode 100644 index 130db1c6b7f..00000000000 --- a/test/run-dfinity/ok/array-out-of-bounds.run-low.ok +++ /dev/null @@ -1,2 +0,0 @@ -array-out-of-bounds.mo:5.10-5.14: execution error, index out of bounds -array-out-of-bounds.mo:9.10-9.14: execution error, index out of bounds diff --git a/test/run-dfinity/ok/array-out-of-bounds.run.ok b/test/run-dfinity/ok/array-out-of-bounds.run.ok deleted file mode 100644 index 130db1c6b7f..00000000000 --- a/test/run-dfinity/ok/array-out-of-bounds.run.ok +++ /dev/null @@ -1,2 +0,0 @@ -array-out-of-bounds.mo:5.10-5.14: execution error, index out of bounds -array-out-of-bounds.mo:9.10-9.14: execution error, index out of bounds diff --git a/test/run-dfinity/ok/hello-world2.dvm.ok b/test/run-dfinity/ok/hello-world2.dvm.ok deleted file mode 100644 index 980a0d5f19a..00000000000 --- a/test/run-dfinity/ok/hello-world2.dvm.ok +++ /dev/null @@ -1 +0,0 @@ -Hello World! diff --git a/test/run-dfinity/ok/hello-world2.run-ir.ok b/test/run-dfinity/ok/hello-world2.run-ir.ok deleted file mode 100644 index 980a0d5f19a..00000000000 --- a/test/run-dfinity/ok/hello-world2.run-ir.ok +++ /dev/null @@ -1 +0,0 @@ -Hello World! diff --git a/test/run-dfinity/ok/hello-world2.run-low.ok b/test/run-dfinity/ok/hello-world2.run-low.ok deleted file mode 100644 index 980a0d5f19a..00000000000 --- a/test/run-dfinity/ok/hello-world2.run-low.ok +++ /dev/null @@ -1 +0,0 @@ -Hello World! diff --git a/test/run-dfinity/ok/hello-world2.run.ok b/test/run-dfinity/ok/hello-world2.run.ok deleted file mode 100644 index 980a0d5f19a..00000000000 --- a/test/run-dfinity/ok/hello-world2.run.ok +++ /dev/null @@ -1 +0,0 @@ -Hello World! diff --git a/test/run-dfinity/ok/hello-world3.dvm.ok b/test/run-dfinity/ok/hello-world3.dvm.ok deleted file mode 100644 index 980a0d5f19a..00000000000 --- a/test/run-dfinity/ok/hello-world3.dvm.ok +++ /dev/null @@ -1 +0,0 @@ -Hello World! diff --git a/test/run-dfinity/ok/hello-world3.run-ir.ok b/test/run-dfinity/ok/hello-world3.run-ir.ok deleted file mode 100644 index 980a0d5f19a..00000000000 --- a/test/run-dfinity/ok/hello-world3.run-ir.ok +++ /dev/null @@ -1 +0,0 @@ -Hello World! diff --git a/test/run-dfinity/ok/hello-world3.run-low.ok b/test/run-dfinity/ok/hello-world3.run-low.ok deleted file mode 100644 index 980a0d5f19a..00000000000 --- a/test/run-dfinity/ok/hello-world3.run-low.ok +++ /dev/null @@ -1 +0,0 @@ -Hello World! diff --git a/test/run-dfinity/ok/hello-world3.run.ok b/test/run-dfinity/ok/hello-world3.run.ok deleted file mode 100644 index 980a0d5f19a..00000000000 --- a/test/run-dfinity/ok/hello-world3.run.ok +++ /dev/null @@ -1 +0,0 @@ -Hello World! diff --git a/test/run-drun/array-out-of-bounds.mo b/test/run-drun/array-out-of-bounds.mo new file mode 100644 index 00000000000..c521aea9f3a --- /dev/null +++ b/test/run-drun/array-out-of-bounds.mo @@ -0,0 +1,17 @@ +actor a { + let xs = [0, 1, 2, 3, 4]; + let ys = []; + + public func foo1() : async () { + ignore(xs[5]); + debugPrint("Unreachable code reached\n"); + }; + public func foo2() : async () { + ignore(ys[0]); + debugPrint("Unreachable code reached\n"); + }; +}; + +//CALL ingress foo1 0x4449444C0000 +//CALL ingress foo2 0x4449444C0000 + diff --git a/test/run-drun/ok/array-out-of-bounds.drun-run.ok b/test/run-drun/ok/array-out-of-bounds.drun-run.ok new file mode 100644 index 00000000000..b006eea0561 --- /dev/null +++ b/test/run-drun/ok/array-out-of-bounds.drun-run.ok @@ -0,0 +1,3 @@ +ingress(0) System +ingress(1) Err: IC0503: Canister 42 trapped explicitly: Array index out of bounds +ingress(2) Err: IC0503: Canister 42 trapped explicitly: Array index out of bounds From cd3143b7a585ff82b29c0bc4f03811f4945af4ec Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 15 Nov 2019 14:35:52 +0100 Subject: [PATCH 0621/1176] Slightly improve the hack to support one-way calls --- src/codegen/compile.ml | 10 ++++++++-- test/run-dfinity/hello-world-async.mo | 11 ----------- test/run-dfinity/ok/hello-world-async.dvm.ok | 1 - test/run-dfinity/ok/hello-world-async.run-ir.ok | 1 - test/run-dfinity/ok/hello-world-async.run-low.ok | 1 - test/run-dfinity/ok/hello-world-async.run.ok | 1 - 6 files changed, 8 insertions(+), 17 deletions(-) delete mode 100644 test/run-dfinity/hello-world-async.mo delete mode 100644 test/run-dfinity/ok/hello-world-async.dvm.ok delete mode 100644 test/run-dfinity/ok/hello-world-async.run-ir.ok delete mode 100644 test/run-dfinity/ok/hello-world-async.run-low.ok delete mode 100644 test/run-dfinity/ok/hello-world-async.run.ok diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 763a1a9e0b5..54ff1a46c46 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -5349,6 +5349,12 @@ module FuncDec = struct compile_unboxed_const (E.built_in env name) ^^ get_closure ^^ ClosureTable.remember_closure env + let ignoring_callback env = + assert (E.mode env = Flags.StubMode); + let name = "@ignore_callback" in + Func.define_built_in env name ["env", I32Type] [] (fun env -> G.nop); + compile_unboxed_const (E.built_in env name) + let lit env ae how name sort control free_vars args mk_body ret_tys at = let captured = List.filter (VarEnv.needs_capture ae) free_vars in @@ -6773,10 +6779,10 @@ and compile_exp (env : E.t) ae exp = (* The method name *) get_funcref ^^ Arr.load_field 1l ^^ Blob.as_ptr_len env ^^ (* The reply callback *) - compile_unboxed_const 0l ^^ + FuncDec.ignoring_callback env ^^ compile_unboxed_const 0l ^^ (* The reject callback *) - compile_unboxed_const 0l ^^ + FuncDec.ignoring_callback env ^^ compile_unboxed_const 0l ^^ (* the data *) get_arg ^^ Serialization.serialize env ts ^^ diff --git a/test/run-dfinity/hello-world-async.mo b/test/run-dfinity/hello-world-async.mo deleted file mode 100644 index feeb880ff48..00000000000 --- a/test/run-dfinity/hello-world-async.mo +++ /dev/null @@ -1,11 +0,0 @@ -let a = actor { - public func world() { - debugPrint("World!\n"); - }; - public func go() { - world(); - debugPrint("Hello "); - }; -}; - -a.go() diff --git a/test/run-dfinity/ok/hello-world-async.dvm.ok b/test/run-dfinity/ok/hello-world-async.dvm.ok deleted file mode 100644 index 980a0d5f19a..00000000000 --- a/test/run-dfinity/ok/hello-world-async.dvm.ok +++ /dev/null @@ -1 +0,0 @@ -Hello World! diff --git a/test/run-dfinity/ok/hello-world-async.run-ir.ok b/test/run-dfinity/ok/hello-world-async.run-ir.ok deleted file mode 100644 index 980a0d5f19a..00000000000 --- a/test/run-dfinity/ok/hello-world-async.run-ir.ok +++ /dev/null @@ -1 +0,0 @@ -Hello World! diff --git a/test/run-dfinity/ok/hello-world-async.run-low.ok b/test/run-dfinity/ok/hello-world-async.run-low.ok deleted file mode 100644 index 980a0d5f19a..00000000000 --- a/test/run-dfinity/ok/hello-world-async.run-low.ok +++ /dev/null @@ -1 +0,0 @@ -Hello World! diff --git a/test/run-dfinity/ok/hello-world-async.run.ok b/test/run-dfinity/ok/hello-world-async.run.ok deleted file mode 100644 index 980a0d5f19a..00000000000 --- a/test/run-dfinity/ok/hello-world-async.run.ok +++ /dev/null @@ -1 +0,0 @@ -Hello World! From 98b52c088afe27ea22e43f432631e8360dae5d87 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Fri, 15 Nov 2019 10:29:12 -0800 Subject: [PATCH 0622/1176] Operations on iterables (#822) * Add Iter.pure * Add Iter.map * [WIP] Iter.toArray, Iter.toArrayMut * Add Iter to Array/List conversion functions * Add fromArray, fromArrayMut, fromList functions --- stdlib/iter.mo | 73 ++++++++++++++++++++++++++ stdlib/iterTest.mo | 127 ++++++++++++++++++++++++++++++++++++++++++++- stdlib/list.mo | 27 ++++++++++ stdlib/listTest.mo | 49 +++++++++++++++++ 4 files changed, 275 insertions(+), 1 deletion(-) diff --git a/stdlib/iter.mo b/stdlib/iter.mo index 07f6ae33373..c5caa6da6b0 100644 --- a/stdlib/iter.mo +++ b/stdlib/iter.mo @@ -1,3 +1,6 @@ +import Array "array.mo"; +import List "list.mo"; + module { public func forIn( f : (A, Nat) -> (), @@ -17,4 +20,74 @@ module { continue l; }; }; + + func length(xs : Iter) : Nat { + var len = 0; + forIn(func (x, i) { len += 1; }, xs); + len; + }; + + public func map(f : A -> B, xs : Iter) : Iter = object { + var i = 0; + public func next() : ?B { + label l loop { + switch (xs.next()) { + case (?next) { + return ?f(next); + }; + case (null) { + break l; + }; + }; + i += 1; + continue l; + }; + null; + }; + }; + + public func pure(x : A) : Iter = object { + public func next() : ?A { + ?x; + }; + }; + + public func fromArray(xs : [A]) : Iter { + fromList(List.fromArray(xs)); + }; + + public func fromArrayMut(xs : [var A]) : Iter { + fromArray(Array.freeze(xs)); + }; + + public func fromList(xs : List.List) : Iter { + List.toArray(xs).vals(); + }; + + public func toArray(xs : Iter) : [A] { + List.toArray(toList(xs)); + }; + + public func toArrayMut(xs : Iter) : [var A] { + Array.thaw(toArray(xs)); + }; + + public func toList(xs : Iter) : List.List { + toListWithLength(xs).list; + }; + + public func toListWithLength( + xs : Iter, + ) : ({ + length : Nat; + list : List.List; + }) { + var _length = 0; + var _list = List.nil(); + forIn(func (x, i) { + _length += 1; + _list := List.push(x, _list); + }, xs); + { length = _length; list = List.rev(_list); }; + }; } diff --git a/stdlib/iterTest.mo b/stdlib/iterTest.mo index d8eefb6c310..14f6f20c731 100644 --- a/stdlib/iterTest.mo +++ b/stdlib/iterTest.mo @@ -1,4 +1,5 @@ import Iter "iter.mo"; +import List "list.mo"; import Prelude "prelude.mo"; Prelude.printLn("Iter"); @@ -18,4 +19,128 @@ Prelude.printLn("Iter"); assert(y == "abcdef"); assert(z == 15); -} +}; + +{ + Prelude.printLn(" map"); + + let isEven = func (x : Int) : Bool { + x % 2 == 0; + }; + + let _actual = Iter.map(isEven, [ 1, 2, 3 ].vals()); + let actual = [var true, false, true]; + Iter.forIn(func (x, i) { actual[i] := x; }, _actual); + + let expected = [false, true, false]; + + for (i in actual.keys()) { + assert(actual[i] == expected[i]); + }; +}; + +{ + Prelude.printLn(" pure"); + + let x = 1; + let y = Iter.pure(x); + + switch (y.next()) { + case null { assert false; }; + case (?z) { assert (x == z); }; + }; +}; + +{ + Prelude.printLn(" fromArray"); + + let expected = [1, 2, 3]; + let _actual = Iter.fromArray(expected); + let actual = [var 0, 0, 0]; + + Iter.forIn(func (x, i) { actual[i] := x; }, _actual); + + for (i in actual.keys()) { + assert(actual[i] == expected[i]); + }; +}; + +{ + Prelude.printLn(" fromArrayMut"); + + let expected = [var 1, 2, 3]; + let _actual = Iter.fromArrayMut(expected); + let actual = [var 0, 0, 0]; + + Iter.forIn(func (x, i) { actual[i] := x; }, _actual); + + for (i in actual.keys()) { + assert(actual[i] == expected[i]); + }; +}; + +{ + Prelude.printLn(" fromList"); + + let list : List.List = ?(1, ?(2, ?(3, List.nil()))); + let _actual = Iter.fromList(list); + let actual = [var 0, 0, 0]; + let expected = [1, 2, 3]; + + Iter.forIn(func (x, i) { actual[i] := x; }, _actual); + + for (i in actual.keys()) { + assert(actual[i] == expected[i]); + }; +}; + +{ + Prelude.printLn(" toArray"); + + let expected = [1, 2, 3]; + let actual = Iter.toArray(expected.vals()); + + assert (actual.len() == expected.len()); + + for (i in actual.keys()) { + assert(actual[i] == expected[i]); + }; +}; + +{ + Prelude.printLn(" toArrayMut"); + + let expected = [var 1, 2, 3]; + let actual = Iter.toArrayMut(expected.vals()); + + assert (actual.len() == expected.len()); + + for (i in actual.keys()) { + assert(actual[i] == expected[i]); + }; +}; + +{ + Prelude.printLn(" toList"); + + let expected : List.List = ?(1, ?(2, ?(3, List.nil()))); + let actual = Iter.toList([1, 2, 3].vals()); + assert List.isEq(expected, actual, func (x1, x2) { x1 == x2 }); +}; + +{ + Prelude.printLn(" toListWithLength"); + + let expected : { + length : Nat; + list : List.List; + } = { + length = 3; + list = ?(1, ?(2, ?(3, List.nil()))); + }; + + let actual = Iter.toListWithLength([1, 2, 3].vals()); + + assert (expected.length == actual.length); + assert List.isEq(expected.list, actual.list, func (x1, x2) { x1 == x2 }); +}; diff --git a/stdlib/list.mo b/stdlib/list.mo index 8fe677571e9..6ffc4b113fc 100644 --- a/stdlib/list.mo +++ b/stdlib/list.mo @@ -1,3 +1,6 @@ +import Array "array.mo"; +import Option "option.mo"; + module { /** @@ -554,6 +557,30 @@ public type List = ?(T, List); } }; + public func fromArray(xs : [A]) : List { + Array.foldr>(func (x : A, ys : List) : List { + push(x, ys); + }, nil(), xs); + }; + + public func fromArrayMut(xs : [var A]) : List { + fromArray(Array.freeze(xs)); + }; + + public func toArray(xs : List) : [A] { + let length = len(xs); + var list = xs; + Array_tabulate(length, func (i) { + let popped = pop(list); + list := popped.1; + Option.unwrap(popped.0); + }); + }; + + public func toArrayMut(xs : List) : [var A] { + Array.thaw(toArray(xs)); + }; + /** To do: diff --git a/stdlib/listTest.mo b/stdlib/listTest.mo index d33beabb25e..e6e1e21aa11 100644 --- a/stdlib/listTest.mo +++ b/stdlib/listTest.mo @@ -1,4 +1,5 @@ import List "list.mo"; +import Prelude "prelude.mo"; type X = Nat; @@ -57,3 +58,51 @@ type X = Nat; assert (List.len(l1) == 0); assert (List.len(l2) == 1); assert (List.len(l3) == 2); + + { + Prelude.printLn(" fromArray"); + + let expected : List.List = ?(1, ?(2, ?(3, List.nil()))); + let array = [1, 2, 3]; + let actual = List.fromArray(array); + + assert List.isEq(expected, actual, func (x1, x2) { x1 == x2 }); + }; + + { + Prelude.printLn(" fromArrayMut"); + + let expected : List.List = ?(1, ?(2, ?(3, List.nil()))); + let array = [var 1, 2, 3]; + let actual = List.fromArrayMut(array); + + assert List.isEq(expected, actual, func (x1, x2) { x1 == x2 }); + }; + + { + Prelude.printLn(" toArray"); + + let expected = [1, 2, 3]; + let list : List.List = ?(1, ?(2, ?(3, List.nil()))); + let actual = List.toArray(list); + + assert (actual.len() == expected.len()); + + for (i in actual.keys()) { + assert(actual[i] == expected[i]); + }; + }; + + { + Prelude.printLn(" toArrayMut"); + + let expected = [var 1, 2, 3]; + let list : List.List = ?(1, ?(2, ?(3, List.nil()))); + let actual = List.toArrayMut(list); + + assert (actual.len() == expected.len()); + + for (i in actual.keys()) { + assert(actual[i] == expected[i]); + }; + }; From 896878954fe125adc4130c202ab32b2221a4e791 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Fri, 15 Nov 2019 20:31:15 +0000 Subject: [PATCH 0623/1176] add index checking to typing.ml; generate fresh annotatons for each use of scope type in parser (state sucks) --- src/mo_frontend/parser.mly | 10 +++++----- src/mo_frontend/typing.ml | 28 +++++++++++++++------------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/mo_frontend/parser.mly b/src/mo_frontend/parser.mly index c91009a5e36..825b958be7c 100644 --- a/src/mo_frontend/parser.mly +++ b/src/mo_frontend/parser.mly @@ -90,8 +90,8 @@ let share_expfield (ef : exp_field) = else {ef with it = {ef.it with dec = share_dec ef.it.dec}} let scope_id = "@_" -let scope_bind = {var = scope_id @@ no_region; bound = PrimT "Any" @! no_region} @= no_region -let scope_typ = PathT ((IdH (scope_id @@ no_region)) @! no_region, []) @! no_region +let scope_bind() = {var = scope_id @@ no_region; bound = PrimT "Any" @! no_region} @= no_region +let scope_typ() = PathT ((IdH (scope_id @@ no_region)) @! no_region, []) @! no_region %} @@ -251,7 +251,7 @@ typ_pre : | PRIM s=TEXT { PrimT(s) @! at $sloc } | ASYNC t=typ_pre - { AsyncT(scope_typ,t) @! at $sloc } + { AsyncT(scope_typ(),t) @! at $sloc } | s=obj_sort tfs=typ_obj { let tfs' = if s.it = Type.Actor then List.map share_typfield tfs else tfs @@ -446,7 +446,7 @@ exp_nondec(B) : | RETURN e=exp(ob) { RetE(e) @? at $sloc } | ASYNC e=exp(bl) - { AsyncE(scope_bind,e,scope_typ) @? at $sloc } + { AsyncE(scope_bind(),e,scope_typ()) @? at $sloc } | AWAIT e=exp(bl) { AwaitE(e) @? at $sloc } | ASSERT e=exp(bl) @@ -632,7 +632,7 @@ dec_nonvar : | (false, e) -> e (* body declared as EQ e *) | (true, e) -> (* body declared as immediate block *) match t with - | Some {it = AsyncT _; _} -> AsyncE(scope_bind,e,scope_typ) @? e.at + | Some {it = AsyncT _; _} -> AsyncE(scope_bind(),e,scope_typ()) @? e.at | _ -> e in let named, x = xf "func" $sloc in diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index ac4da833d78..8b38d98c52a 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -23,7 +23,7 @@ type env = objs : Scope.obj_env; labs : lab_env; rets : ret_env; - async : bool; + async : Type.con option; in_actor : bool; in_await : bool; in_shared : bool; @@ -40,7 +40,7 @@ let env_of_scope msgs scope = objs = T.Env.empty; labs = T.Env.empty; rets = None; - async = false; + async = None; in_await = false; in_shared = false; in_actor = false; @@ -644,7 +644,7 @@ and infer_exp'' env exp : T.typ = | ObjE (sort, fields) -> if not in_prog && sort.it = T.Actor then error_in [Flags.ICMode] env exp.at "non-toplevel actor; an actor can only be declared at the toplevel of a program"; - let env' = if sort.it = T.Actor then {env with async = false; in_actor = true} else env in + let env' = if sort.it = T.Actor then {env with async = None; in_actor = true} else env in infer_obj env' sort.it fields exp.at | DotE (exp1, id) -> let t1 = infer_exp_promote env exp1 in @@ -715,7 +715,7 @@ and infer_exp'' env exp : T.typ = { env' with labs = T.Env.empty; rets = Some codom; - async = false; + async = None; in_shared = T.is_shared_sort sort.it} in check_exp (adjoin_vals env'' ve) codom exp; if Type.is_shared_sort sort.it then begin @@ -822,7 +822,7 @@ and infer_exp'' env exp : T.typ = end; t | TryE (exp1, cases) -> - if not env.async then + if env.async = None then error env exp.at "misplaced try"; let t1 = infer_exp env exp1 in let t2 = infer_cases env T.catch T.Non cases in @@ -901,7 +901,7 @@ and infer_exp'' env exp : T.typ = end; T.Non | ThrowE exp1 -> - if not env.async then + if env.async = None then error env exp.at "misplaced throw"; if not env.pre then check_exp env T.throw exp1; T.Non @@ -911,7 +911,7 @@ and infer_exp'' env exp : T.typ = let t0 = check_typ env typ0 in let c, tb, ce, cs = check_typ_bind env tb in let env' = - {(adjoin_typs env ce cs) with labs = T.Env.empty; rets = Some T.Pre; async = true} in + {(adjoin_typs env ce cs) with labs = T.Env.empty; rets = Some T.Pre; async = Some c} in let t = infer_exp env' exp1 in let t1 = T.open_ [t0] (T.close [c] t) in if not (T.shared t1) then @@ -919,7 +919,7 @@ and infer_exp'' env exp : T.typ = (T.string_of_typ_expand t1); T.Async (t0,t1) | AwaitE exp1 -> - if not env.async then + if env.async = None then error env exp.at "misplaced await"; let t1 = infer_exp_promote {env with in_await = true} exp1 in (match exp1.it with @@ -929,7 +929,9 @@ and infer_exp'' env exp : T.typ = | _ -> error_in [Flags.ICMode] env exp1.at "argument to await must be a call expression"); (try let (t2,t3) = T.as_async_sub t1 in - (* TODO: check the index *) + let t0 = T.Con(Lib.Option.value env.async, []) in + if not (T.eq t0 t2) then + error env exp.at "ill-scoped await"; t3 with Invalid_argument _ -> error env exp1.at "expected async type, but expression has type\n %s" @@ -1001,7 +1003,7 @@ and check_exp' env0 t exp : T.typ = (T.string_of_typ_expand t0'); let c, tb, ce, cs = check_typ_bind env tb in let env' = - {(adjoin_typs env ce cs) with labs = T.Env.empty; rets = Some t'; async = true} in + {(adjoin_typs env ce cs) with labs = T.Env.empty; rets = Some t'; async = Some c} in check_exp env' t' exp1; t | BlockE decs, _ -> @@ -1025,7 +1027,7 @@ and check_exp' env0 t exp : T.typ = ); t | TryE (exp1, cases), _ -> - if not env.async then + if env.async = None then error env exp.at "misplaced try"; check_exp env t exp1; check_cases env T.catch t cases; @@ -1058,7 +1060,7 @@ and check_exp' env0 t exp : T.typ = { env with labs = T.Env.empty; rets = Some t2; - async = false; + async = None; in_shared = T.is_shared_sort s'.it; } in check_exp (adjoin_vals env' ve) t2 exp; @@ -1534,7 +1536,7 @@ and infer_dec env dec : T.typ = { (add_val env'' self_id.it self_typ) with labs = T.Env.empty; rets = None; - async = false; + async = None; in_actor = sort.it = T.Actor; } in From fdc083a020b33dff40483943cf2764addb877568 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Fri, 15 Nov 2019 20:43:21 +0000 Subject: [PATCH 0624/1176] check scopes in check_ir.ml --- src/ir_def/check_ir.ml | 23 ++++++++++++----------- src/mo_frontend/typing.ml | 2 +- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 84ee8667b3b..8c93836a6cd 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -52,7 +52,7 @@ type env = cons : con_env; labs : lab_env; rets : ret_env; - async : bool; + async : T.con option; } let env_of_scope scope flavor : env = @@ -61,7 +61,7 @@ let env_of_scope scope flavor : env = cons = scope.Scope.con_env; labs = T.Env.empty; rets = None; - async = false; + async = None; } @@ -508,7 +508,7 @@ let rec check_exp env (exp:Ir.exp) : unit = check_cases env t1 t cases | TryE (exp1, cases) -> check env.flavor.has_await "try in non-await flavor"; - check env.async "misplaced try"; + check (env.async <> None) "misplaced try"; check_exp env exp1; typ exp1 <: t; check_cases env T.catch t cases; @@ -545,7 +545,7 @@ let rec check_exp env (exp:Ir.exp) : unit = T.Non <: t (* vacuously true *) | ThrowE exp1 -> check env.flavor.has_await "throw in non-await flavor"; - check env.async "misplaced throw"; + check (env.async <> None) "misplaced throw"; check_exp env exp1; typ exp1 <: T.throw; T.Non <: t (* vacuously true *) @@ -556,23 +556,24 @@ let rec check_exp env (exp:Ir.exp) : unit = let t1 = typ exp1 in let env' = {(adjoin_cons env ce) - with labs = T.Env.empty; rets = Some t1; async = true} in + with labs = T.Env.empty; rets = Some t1; async = Some c} in check_exp env' exp1; let t1' = T.open_ [t0] (T.close [c] t1) in t1' <: T.Any; (* vacuous *) T.Async (t0,t1') <: t | AwaitE exp1 -> check env.flavor.has_await "await in non-await flavor"; - check env.async "misplaced await"; + check (env.async <> None) "misplaced await"; + let t0 = T.Con(Lib.Option.value env.async, []) in check_exp env exp1; let t1 = T.promote (typ exp1) in - let (t0, t2) = try T.as_async_sub t1 + let (t2, t3) = try T.as_async_sub t1 with Invalid_argument _ -> error env exp1.at "expected async type, but expression has type\n %s" (T.string_of_typ_expand t1) in - (* TODO check t0 is in async context *) - t2 <: t + check (T.eq t0 t2) "ill-scoped async"; + t3 <: t | AssertE exp1 -> check_exp env exp1; typ exp1 <: T.bool; @@ -609,7 +610,7 @@ let rec check_exp env (exp:Ir.exp) : unit = if T.is_shared_sort sort then List.iter (check_concrete env exp.at) ret_tys; let codom = T.codom control ret_tys in let env'' = - {env' with labs = T.Env.empty; rets = Some codom; async = false} in + {env' with labs = T.Env.empty; rets = Some codom; async = None} in check_exp (adjoin_vals env'' ve) exp; check_sub env' exp.at (typ exp) codom; (* Now construct the function type and compare with the annotation *) @@ -621,7 +622,7 @@ let rec check_exp env (exp:Ir.exp) : unit = ) in fun_ty <: t | ActorE (id, ds, fs, t0) -> - let env' = { env with async = false } in + let env' = { env with async = None } in let ve0 = T.Env.singleton id t0 in let scope1 = List.fold_left (gather_dec env') empty_scope ds in let env'' = adjoin (adjoin_vals env' ve0) scope1 in diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 8b38d98c52a..ee81826a611 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -23,7 +23,7 @@ type env = objs : Scope.obj_env; labs : lab_env; rets : ret_env; - async : Type.con option; + async : T.con option; in_actor : bool; in_await : bool; in_shared : bool; From bdcd2dd878273e7de3cb8d4ab5f8f08627f3f0bc Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Fri, 15 Nov 2019 20:46:58 +0000 Subject: [PATCH 0625/1176] Update src/lowering/desugar.ml --- src/lowering/desugar.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 3a373b4ab82..227b4f32933 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -405,7 +405,7 @@ and to_args typ p : Ir.arg list * (Ir.exp -> Ir.exp) * T.typ T.control * T.typ l let wrap_under_async e = if T.is_shared_sort sort && control <> T.Returns then match e.it with - | Ir.AsyncE (tb, e',t) -> { e with it = Ir.AsyncE (tb, wrap e', t) } + | Ir.AsyncE (tb, e', t) -> { e with it = Ir.AsyncE (tb, wrap e', t) } | _ -> assert false else wrap e in From 2f039f13f79505ee5b7c9e6451fc45a937fe617c Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Sat, 16 Nov 2019 13:07:06 +0100 Subject: [PATCH 0626/1176] Forgot to commit test case --- test/run-stub/hello-world-async.mo | 12 ++++++++++++ test/run-stub/ok/hello-world-async.ic-stub-run.ok | 7 +++++++ 2 files changed, 19 insertions(+) create mode 100644 test/run-stub/hello-world-async.mo create mode 100644 test/run-stub/ok/hello-world-async.ic-stub-run.ok diff --git a/test/run-stub/hello-world-async.mo b/test/run-stub/hello-world-async.mo new file mode 100644 index 00000000000..e12d76d55d4 --- /dev/null +++ b/test/run-stub/hello-world-async.mo @@ -0,0 +1,12 @@ +let a = actor { + public func world() { + debugPrint("World!\n"); + }; + public func go() { + a.world(); + debugPrint("Hello "); + }; +}; + +//CALL ingress go 0x4449444C0000 + diff --git a/test/run-stub/ok/hello-world-async.ic-stub-run.ok b/test/run-stub/ok/hello-world-async.ic-stub-run.ok new file mode 100644 index 00000000000..ac0776f7a8d --- /dev/null +++ b/test/run-stub/ok/hello-world-async.ic-stub-run.ok @@ -0,0 +1,7 @@ +→ install +← completed +→ update go(0x4449444c0000) +Hello +World! + +← rejected (RC_CANISTER_ERROR): canister did not respond From 86bfb67c676bc27bed46226cfbf3c45c58ef9c19 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Sat, 16 Nov 2019 13:14:43 +0100 Subject: [PATCH 0627/1176] README: A note on profiling results, and where the bottle necks are. --- ic-stub/README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ic-stub/README.md b/ic-stub/README.md index 2e5ae0936ae..17ab89f1889 100644 --- a/ic-stub/README.md +++ b/ic-stub/README.md @@ -35,3 +35,13 @@ Developing on ic-stub Running `nix-shell` in the `ic-stub/` directory should give you an environment that allows you to build the project using `cabal new-build`. + +The interpreter is too slow +--------------------------- + +The obvious performance issue with `winter`, according to profiling, is +evaluation under lambdas, the cost centres `step_Label7_k`, `step_Label7`, +`step_Label2` and `step_Framed4` are responsible for most allocation. Switching +to an interpreter form with a control stack would likely help a lot, but would +move `winter` away from being a straight-forward port of the Ocaml reference +interpreter `wasm`. From b8f1cd4f4a12236423903cc1b52ba0ee2dced1de Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Sun, 17 Nov 2019 20:59:52 +0000 Subject: [PATCH 0628/1176] adapt operations on types to support Promise typ argument --- src/mo_types/type.ml | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index 56a945ada09..0aa601a472c 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -214,7 +214,7 @@ let rec subst sigma t = | Tup ts -> Tup (List.map (subst sigma) ts) | Func (s, c, tbs, ts1, ts2) -> let sigma' = ConEnv.map (shift 0 (List.length tbs)) sigma in - Func (s, c, List.map (subst_bind sigma') tbs, + Func (s, map_control (subst sigma') c, List.map (subst_bind sigma') tbs, List.map (subst sigma') ts1, List.map (subst sigma') ts2) | Opt t -> Opt (subst sigma t) | Async (t1, t2) -> Async (subst sigma t1, subst sigma t2) @@ -270,7 +270,7 @@ let rec open' i ts t = | Tup ts' -> Tup (List.map (open' i ts) ts') | Func (s, c, tbs, ts1, ts2) -> let i' = i + List.length tbs in - Func (s, c, List.map (open_bind i' ts) tbs, List.map (open' i' ts) ts1, List.map (open' i' ts) ts2) + Func (s, map_control (open' i' ts) c, List.map (open_bind i' ts) tbs, List.map (open' i' ts) ts1, List.map (open' i' ts) ts2) | Opt t -> Opt (open' i ts t) | Async (t1, t2) -> Async (open' i ts t1, open' i ts t2) | Obj (s, fs) -> Obj (s, List.map (open_field i ts) fs) @@ -575,7 +575,7 @@ let concrete t = | Def (_, t) -> go (open_ ts t) (* TBR this may fail to terminate *) ) | Array t | Opt t | Mut t -> go t - | Async (t1, t2) -> go t1 && go t2 + | Async (t1, t2) -> go t2 (* t1 is a phantom type *) | Tup ts -> List.for_all go ts | Obj (_, fs) | Variant fs -> List.for_all (fun f -> go f.typ) fs | Func (s, c, tbs, ts1, ts2) -> @@ -722,9 +722,10 @@ let rec rel_typ rel eq t1 t2 = | Tup ts1, Tup ts2 -> rel_list rel_typ rel eq ts1 ts2 | Func (s1, c1, tbs1, t11, t12), Func (s2, c2, tbs2, t21, t22) -> - c1 = c2 && s1 = s2 && + s1 = s2 && (match rel_binds rel eq tbs1 tbs2 with | Some ts -> + eq_control' rel eq (map_control (open_ ts) c1) (map_control (open_ ts) c2) && rel_list rel_typ rel eq (List.map (open_ ts) t21) (List.map (open_ ts) t11) && rel_list rel_typ rel eq (List.map (open_ ts) t12) (List.map (open_ ts) t22) | None -> false @@ -739,6 +740,13 @@ let rec rel_typ rel eq t1 t2 = | _, _ -> false end +and eq_control' rel eq c1 c2 = + match c1, c2 with + | Promises t1, Promises t2 -> eq_typ rel eq t1 t2 + | Returns, Returns -> true + | Replies, Replies -> true + | _ -> false + and rel_fields rel eq tfs1 tfs2 = (* Assume that tfs1 and tfs2 are sorted. *) match tfs1, tfs2 with @@ -817,6 +825,9 @@ and eq_con eq c1 c2 = let eq_kind k1 k2 : bool = eq_kind' (ref SS.empty) k1 k2 +let eq_control c1 c2 : bool = + let eq = ref SS.empty in eq_control' eq eq c1 c2 + (* Compatibility *) let compatible_list p co xs1 xs2 = @@ -952,7 +963,7 @@ let rec lub' lubs glbs t1 t2 = | Obj (s1, tf1), Obj (s2, tf2) when s1 = s2 -> Obj (s1, lub_fields lubs glbs tf1 tf2) | Func (s1, c1, bs1, args1, res1), Func (s2, c2, bs2, args2, res2) when - s1 = s2 && c1 = c2 && List.(length bs1 = length bs2) && + s1 = s2 && eq_control c1 c2 && List.(length bs1 = length bs2) && List.(length args1 = length args2 && length res1 = length res2) -> combine_func_parts s1 c1 bs1 args1 res1 bs2 args2 res2 lubs glbs glb' lub' | Async (t11, t12), Async (t21, t22) when eq t11 t21 -> @@ -1025,7 +1036,7 @@ and glb' lubs glbs t1 t2 = | Some fs -> Obj (s1, fs) ) | Func (s1, c1, bs1, args1, res1), Func (s2, c2, bs2, args2, res2) when - s1 = s2 && c1 = c2 && List.(length bs1 = length bs2) && + s1 = s2 && eq_control c1 c2 && List.(length bs1 = length bs2) && List.(length args1 = length args2 && length res1 = length res2) -> combine_func_parts s1 c1 bs1 args1 res1 bs2 args2 res2 lubs glbs lub' glb' | Async (t11, t12), Async (t21, t22) when eq t11 t21 -> From e8a77233984fa75a134e1c89e49108c1bc8d37d6 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Sun, 17 Nov 2019 21:26:28 +0000 Subject: [PATCH 0629/1176] open and close controls too --- src/ir_def/check_ir.ml | 6 ++++-- src/mo_frontend/typing.ml | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 8c93836a6cd..d394748759c 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -160,6 +160,7 @@ let rec check_typ env typ : unit = let cs, ce = check_typ_binds env binds in let env' = adjoin_cons env ce in let ts = List.map (fun c -> T.Con (c, [])) cs in + let control = T.map_control (T.open_ ts) control in let ts1 = List.map (T.open_ ts) ts1 in let ts2 = List.map (T.open_ ts) ts2 in List.iter (check_typ env') ts1; @@ -170,7 +171,8 @@ let rec check_typ env typ : unit = | T.Returns -> check env' no_region (sort = T.Shared T.Write) "one-shot query function pointless" - | T.Promises _ -> + | T.Promises t -> + check_typ env' typ; check env no_region env.flavor.Ir.has_async_typ "promising function in post-async flavor"; check env' no_region (sort <> T.Local) @@ -617,7 +619,7 @@ let rec check_exp env (exp:Ir.exp) : unit = let ts1 = List.map (fun a -> a.note) args in if T.is_shared_sort sort then List.iter (check_concrete env exp.at) ts1; let fun_ty = T.Func - ( sort, control + ( sort, T.map_control (T.close cs) control , tbs, List.map (T.close cs) ts1, List.map (T.close cs) ret_tys ) in fun_ty <: t diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index ee81826a611..49458689c0c 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -742,7 +742,7 @@ and infer_exp'' env exp : T.typ = end; let ts1 = match pat.it with TupP _ -> T.seq_of_tup t1 | _ -> [t1] in let tbs = List.map2 (fun c t -> {T.var = Con.name c; bound = T.close cs t}) cs ts in - T.Func (sort.it, c, tbs, List.map (T.close cs) ts1, List.map (T.close cs) ts2) + T.Func (sort.it, T.map_control (T.close cs) c, tbs, List.map (T.close cs) ts1, List.map (T.close cs) ts2) | CallE (exp1, insts, exp2) -> let t1 = infer_exp_promote env exp1 in let sort, tbs, t_arg, t_ret = From bb94d7d957ae029f917fa4b47ca1e33c1a7803bd Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Sun, 17 Nov 2019 21:37:02 +0000 Subject: [PATCH 0630/1176] fixed typo causing stack overflow --- src/ir_def/check_ir.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index d394748759c..26516104a3c 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -171,8 +171,8 @@ let rec check_typ env typ : unit = | T.Returns -> check env' no_region (sort = T.Shared T.Write) "one-shot query function pointless" - | T.Promises t -> - check_typ env' typ; + | T.Promises t' -> + check_typ env' t'; check env no_region env.flavor.Ir.has_async_typ "promising function in post-async flavor"; check env' no_region (sort <> T.Local) From 39edf40d9e2209847f22ec92335d7492bcb11e49 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Sun, 17 Nov 2019 21:52:12 +0000 Subject: [PATCH 0631/1176] fix bogus ir checks --- src/ir_def/check_ir.ml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 26516104a3c..985983dea76 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -175,17 +175,13 @@ let rec check_typ env typ : unit = check_typ env' t'; check env no_region env.flavor.Ir.has_async_typ "promising function in post-async flavor"; - check env' no_region (sort <> T.Local) - "promising function cannot be local:\n %s" (T.string_of_typ_expand (T.seq ts)); - check env' no_region (List.for_all T.shared ts) - "message result is not sharable:\n %s" (T.string_of_typ_expand (T.seq ts)) + check env' no_region (List.for_all T.shared ts2) + "message result is not sharable:\n %s" (T.string_of_typ_expand (T.seq ts2)) | T.Replies -> check env no_region (not env.flavor.Ir.has_async_typ) "replying function in pre-async flavor"; - check env' no_region (sort <> T.Local) - "replying function cannot be local:\n %s" (T.string_of_typ_expand (T.seq ts)); - check env' no_region (List.for_all T.shared ts) - "message result is not sharable:\n %s" (T.string_of_typ_expand (T.seq ts)) + check env' no_region (List.for_all T.shared ts2) + "message result is not sharable:\n %s" (T.string_of_typ_expand (T.seq ts2)) end else check env' no_region (control = T.Returns) "promising function cannot be local:\n %s" (T.string_of_typ_expand typ); From 4a6be7496ff0e776b79a984c98f7905fc61a648e Mon Sep 17 00:00:00 2001 From: Enzo Haussecker Date: Sun, 17 Nov 2019 23:32:39 -0800 Subject: [PATCH 0632/1176] Add function to split list at given index --- stdlib/list.mo | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/stdlib/list.mo b/stdlib/list.mo index 6ffc4b113fc..527c565b404 100644 --- a/stdlib/list.mo +++ b/stdlib/list.mo @@ -520,7 +520,7 @@ public type List = ?(T, List); `zip` ------------- Creates a list of pairs from a pair of lists. If the given lists have - inconsistent lengths, then the list created will have a length equal to the + inconsistent lengths, then the list created will have a length equal to their minimum. */ public func zip(xs : List, ys : List) : List<(X, Y)> { @@ -533,7 +533,7 @@ public type List = ?(T, List); Creates a list whose elements are calculated from the given function and elements occuring at the same position in the given lists. If the given lists have inconsistent lengths, then the list created will have a length equal to - the minimum. + their minimum. */ public func zipWith( xs : List, @@ -557,6 +557,34 @@ public type List = ?(T, List); } }; + /** + `splitAt` + ----------- + Creates a pair of lists by splitting the given list at the given index. + */ + public func splitAt(n : Nat, xs : List) : (List, List) { + if (n == 0) { + (null, xs) + } else { + func rec(n : Nat, xs : List) : (List, List) { + switch (pop(xs)) { + case (null, _) { + (null, null) + }; + case (?h, t) { + if (n == 1) { + (singleton(h), t) + } else { + let (l, r) = rec(n - 1, t); + (push(h, l), r) + } + } + } + }; + rec(n, xs) + } + }; + public func fromArray(xs : [A]) : List { Array.foldr>(func (x : A, ys : List) : List { push(x, ys); From 08e1153a7ce0a58c11e47bd996e75e98325fe335 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Mon, 18 Nov 2019 13:27:36 +0000 Subject: [PATCH 0633/1176] Desugar control properly --- src/lowering/desugar.ml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 227b4f32933..167200a15a4 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -91,7 +91,8 @@ and exp' at note = function let tbs' = typ_binds tbs in let vars = List.map (fun (tb : I.typ_bind) -> T.Con (tb.it.I.con, [])) tbs' in let tys = List.map (T.open_ vars) res_tys in - I.FuncE (name, s.it, control, tbs', args, tys, wrap (exp e)) + let control' = T.map_control (T.open_ vars) control in + I.FuncE (name, s.it, control', tbs', args, tys, wrap (exp e)) (* Primitive functions in the prelude have particular shapes *) | S.CallE ({it=S.AnnotE ({it=S.PrimE p;_}, _);note;_}, _, e) when Lib.String.chop_prefix "num_conv" p <> None -> @@ -291,8 +292,9 @@ and dec' at n d = match d with in let varPat = {it = I.VarP id'.it; at = at; note = fun_typ } in let args, wrap, control, _n_res = to_args n.S.note_typ p in + let control' = T.map_control (T.open_ inst) control in let fn = { - it = I.FuncE (id.it, sort, control, typ_binds tbs, args, [obj_typ], wrap + it = I.FuncE (id.it, sort, control', typ_binds tbs, args, [obj_typ], wrap { it = obj at s (Some self_id) es obj_typ; at = at; note = { I.note_typ = obj_typ; I.note_eff = T.Triv } }); From 91f7a78aa4f16c86c490a39f0d909b668200e56b Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Mon, 18 Nov 2019 15:17:32 +0000 Subject: [PATCH 0634/1176] check subterms of CPSAwait and CPSAsync --- src/ir_def/check_ir.ml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 985983dea76..72dc24aa99d 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -357,10 +357,13 @@ let rec check_exp env (exp:Ir.exp) : unit = | CPSAwait, [a; kr] -> check (not (env.flavor.has_await)) "CPSAwait await flavor"; check (env.flavor.has_async_typ) "CPSAwait in post-async flavor"; + check_exp env a; + check_exp env kr (* TODO: We can check more here, can we *) | CPSAsync, [exp] -> check (not (env.flavor.has_await)) "CPSAsync await flavor"; check (env.flavor.has_async_typ) "CPSAsync in post-async flavor"; + check_exp env exp; (* TODO: We can check more here, can we *) | ICReplyPrim ts, [exp1] -> check (not (env.flavor.has_async_typ)) "ICReplyPrim in async flavor"; From 417e26000dceef2fe9bb35093ccc884af5221443 Mon Sep 17 00:00:00 2001 From: Enzo Haussecker Date: Mon, 18 Nov 2019 19:08:29 +0200 Subject: [PATCH 0635/1176] Update stdlib/list.mo Co-Authored-By: Gabor Greif --- stdlib/list.mo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/list.mo b/stdlib/list.mo index 527c565b404..0357ad54045 100644 --- a/stdlib/list.mo +++ b/stdlib/list.mo @@ -560,7 +560,7 @@ public type List = ?(T, List); /** `splitAt` ----------- - Creates a pair of lists by splitting the given list at the given index. + Creates a pair of lists by splitting the given list at the given (zero-based) index. */ public func splitAt(n : Nat, xs : List) : (List, List) { if (n == 0) { From d19af3845c329c639c1b8b52c0f5c2a67fe3ff14 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Mon, 18 Nov 2019 18:37:06 +0000 Subject: [PATCH 0636/1176] make async t interpretion polymorphic (but keeping answer type at unit for now --- src/ir_def/arrange_ir.ml | 2 +- src/ir_def/check_ir.ml | 8 +++++--- src/ir_def/construct.ml | 22 ++++++++++++++++++++-- src/ir_def/construct.mli | 1 + src/ir_def/ir.ml | 2 +- src/ir_interpreter/interpret_ir.ml | 2 +- src/ir_passes/async.ml | 24 +++++++++++++----------- src/ir_passes/await.ml | 15 ++++++++------- 8 files changed, 50 insertions(+), 26 deletions(-) diff --git a/src/ir_def/arrange_ir.ml b/src/ir_def/arrange_ir.ml index 8ffaf7d2d67..68769208b83 100644 --- a/src/ir_def/arrange_ir.ml +++ b/src/ir_def/arrange_ir.ml @@ -61,7 +61,7 @@ and prim = function | NumConvPrim (t1, t2) -> "NumConvPrim" $$ [prim_ty t1; prim_ty t2] | OtherPrim s -> Atom s | CPSAwait -> Atom "CPSAwait" - | CPSAsync -> Atom "CPSAsync" + | CPSAsync t -> "CPSAsync" $$ [typ t] | ICReplyPrim ts -> "ICReplyPrim" $$ List.map typ ts | ICRejectPrim -> Atom "ICRejectPrim" | ICErrorCodePrim -> Atom "ICErrorCodePrim" diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 72dc24aa99d..ced29261de2 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -146,7 +146,8 @@ let rec check_typ env typ : unit = check_con {env with cons = T.ConSet.add c env.cons} c; check_typ_bounds env tbs typs no_region | T.Abs (tbs, _) -> - check env no_region (T.ConSet.mem c env.cons) "free type constructor"; + check env no_region (T.ConSet.mem c env.cons) "free type constructor %s " + (T.string_of_typ typ); check_typ_bounds env tbs typs no_region end | T.Any -> () @@ -303,7 +304,7 @@ let type_lit env lit at : T.prim = let isAsyncE exp = match exp.it with | AsyncE _ (* pre await transformation *) - | PrimE (CPSAsync, [_]) (* post await transformation *) + | PrimE (CPSAsync _, [_]) (* post await transformation *) -> true | _ -> false @@ -360,9 +361,10 @@ let rec check_exp env (exp:Ir.exp) : unit = check_exp env a; check_exp env kr (* TODO: We can check more here, can we *) - | CPSAsync, [exp] -> + | CPSAsync t, [exp] -> check (not (env.flavor.has_await)) "CPSAsync await flavor"; check (env.flavor.has_async_typ) "CPSAsync in post-async flavor"; + check_typ env t; check_exp env exp; (* TODO: We can check more here, can we *) | ICReplyPrim ts, [exp1] -> diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index d018cafc45d..71149ca606f 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -2,7 +2,7 @@ open Source open Ir open Ir_effect - +module Con = Mo_types.Con module T = Mo_types.Type type var = exp @@ -91,7 +91,7 @@ let primE prim es = } let asyncE typ1 typ2 e = - { it = PrimE (CPSAsync, [e]); + { it = PrimE (CPSAsync typ1, [e]); at = no_region; note = { note_typ = T.Async (typ1, typ2); note_eff = eff e } } @@ -464,6 +464,24 @@ let (-->*) xs exp = let fun_ty = T.Func (T.Local, T.Returns, [], List.map typ xs, T.as_seq (typ exp)) in nary_funcE "$lambda" fun_ty xs exp +let close_typ_binds cs tbs = + List.map (fun {it = {con; bound}; _} -> {T.var = Con.name con; bound = T.close cs bound}) tbs + +(* polymorphic, n-ary local lambda *) +let forall tbs e = + let cs = List.map (fun tb -> tb.it.con) tbs in + match e.it, e.note.note_typ with + | FuncE (n, s, c1, [], xs, ts, exp), + T.Func ( _, c2, [], ts1, ts2) -> + { e with + it = FuncE(n, s, c1, tbs, xs, ts, exp); + note = { e.note with + note_typ = T.Func(s, T.map_control (T.close cs) c2, close_typ_binds cs tbs, + List.map (T.close cs) ts1, + List.map (T.close cs) ts2) + }} + | _ -> assert false + (* Lambda application (monomorphic) *) let ( -*- ) exp1 exp2 = diff --git a/src/ir_def/construct.mli b/src/ir_def/construct.mli index 712f5917e86..019fa0ebc9b 100644 --- a/src/ir_def/construct.mli +++ b/src/ir_def/construct.mli @@ -104,4 +104,5 @@ val seqE : exp list -> exp val (-->) : var -> exp -> exp val (-->*) : var list -> exp -> exp (* n-ary local *) +val forall : typ_bind list -> exp -> exp (* generalization *) val (-*-) : exp -> exp -> exp (* application *) diff --git a/src/ir_def/ir.ml b/src/ir_def/ir.ml index 0ce61378f7a..9017914d2e6 100644 --- a/src/ir_def/ir.ml +++ b/src/ir_def/ir.ml @@ -107,7 +107,7 @@ and prim = | NumConvPrim of Type.prim * Type.prim | OtherPrim of string (* Other primitive operation, no custom typing rule *) | CPSAwait - | CPSAsync + | CPSAsync of Type.typ | ICReplyPrim of Type.typ list | ICRejectPrim | ICErrorCodePrim diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index 8c6420be478..63b612a9c2c 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -328,7 +328,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = if Show.can_show ot then k (Value.Text (Show.show_val ot v)) else raise (Invalid_argument "debug_show")) - | CPSAsync, [exp1] -> + | CPSAsync _, [exp1] -> interpret_exp env exp1 (fun v -> assert (not env.flavor.has_await && env.flavor.has_async_typ); let (_, f) = V.as_func v in diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index 6e405adb2a8..a938fca1c2a 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -227,6 +227,7 @@ let transform mode env prog = | ShowPrim ot -> ShowPrim (t_typ ot) | NumConvPrim (t1,t2) -> NumConvPrim (t1,t2) | ICReplyPrim ts -> ICReplyPrim (List.map t_typ ts) + | CPSAsync t -> CPSAsync (t_typ t) | p -> p and t_field {lab; typ} = @@ -262,11 +263,13 @@ let transform mode env prog = ArrayE (mut, t_typ t, List.map t_exp exps) | IdxE (exp1, exp2) -> IdxE (t_exp exp1, t_exp exp2) - | PrimE (CPSAwait, [a;kr]) -> + | PrimE (CPSAwait, [a; kr]) -> ((t_exp a) -*- (t_exp kr)).it - | PrimE (CPSAsync, [exp2]) -> - let ts1 = match typ exp2 with - | Func(_,_, [], [Func(_, _, [], ts1, []); _], []) -> List.map t_typ ts1 + | PrimE (CPSAsync t0, [exp2]) -> + let t0 = t_typ t0 in + let tb, ts1 = match typ exp2 with + | Func(_,_, [tb], [Func(_, _, [], ts1, []); _], []) -> + tb, List.map t_typ (List.map (T.open_ [t0]) ts1) | t -> assert false in let post = fresh_var "post" (T.Func(T.Shared T.Write, T.Replies, [], [], ts1)) in let u = fresh_var "u" T.unit in @@ -277,8 +280,7 @@ let transform mode env prog = let k = vs -->* (ic_replyE ts1 (seqE vs)) in let e = fresh_var "e" T.catch in let r = [e] -->* (ic_rejectE (errorMessageE e)) in - (t_exp exp2) -*- tupE [k;r]); - + callE (t_exp exp2) [t0] (tupE [k;r])); expD (ic_callE post (seqE []) nary_reply reject); ] nary_async @@ -353,21 +355,21 @@ let transform mode env prog = let ret_tys = List.map t_typ ret_tys in let args' = t_args args in let typbinds' = t_typ_binds typbinds in - let cps = match exp.it with - | PrimE (CPSAsync, [cps]) -> cps + let t0, cps = match exp.it with + | PrimE (CPSAsync t0, [cps]) -> t_typ t0, cps | _ -> assert false in let t1, contT = match typ cps with | Func(_,_, - [], + [tb], [Func(_, _, [], ts1, []) as contT; _], []) -> - (t_typ (T.seq ts1),t_typ contT) + (t_typ (T.seq (List.map (T.open_ [t0]) ts1)),t_typ (T.open_ [t0] contT)) | t -> assert false in let v = fresh_var "v" t1 in let k = v --> (ic_replyE ret_tys v) in let e = fresh_var "e" T.catch in let r = [e] -->* (ic_rejectE (errorMessageE e)) in - let exp' = (t_exp cps) -*- tupE [k;r] in + let exp' = callE (t_exp cps) [t0] (tupE [k;r]) in FuncE (x, T.Shared s', Replies, typbinds', args', ret_tys, exp') | Replies -> assert false end diff --git a/src/ir_passes/await.ml b/src/ir_passes/await.ml index afeebe4f3f5..2db995bb76b 100644 --- a/src/ir_passes/await.ml +++ b/src/ir_passes/await.ml @@ -116,7 +116,7 @@ and t_exp' context exp' = | Some Label -> RetE (t_exp context exp1) | None -> assert false end - | AsyncE (_tb, exp1, typ1) -> + | AsyncE (tb, exp1, typ1) -> (* TODO: this needs more work to account for _tb and _ty *) let exp1 = R.exp R.Renaming.empty exp1 in (* rename all bound vars apart *) (* add the implicit return/throw label *) @@ -126,9 +126,9 @@ and t_exp' context exp' = LabelEnv.add Return (Cont (ContVar k_ret)) (LabelEnv.add Throw (Cont (ContVar k_fail)) LabelEnv.empty) in - (* TODO: bind k_fail *) - (asyncE typ1 (typ exp1) ([k_ret; k_fail] -->* - c_exp context' exp1 (ContVar k_ret))).it + (asyncE typ1 (typ exp1) + (forall [tb] ([k_ret; k_fail] -->* + c_exp context' exp1 (ContVar k_ret)))).it | TryE _ | ThrowE _ | AwaitE _ -> assert false (* these never have effect T.Triv *) @@ -353,7 +353,7 @@ and c_exp' context exp k = | Some Label | None -> assert false end - | AsyncE (_, exp1, typ1) -> + | AsyncE (tb, exp1, typ1) -> (* TODO: this needs more thought *) (* add the implicit return label *) let k_ret = fresh_cont (typ exp1) in @@ -362,8 +362,9 @@ and c_exp' context exp k = LabelEnv.add Return (Cont (ContVar k_ret)) (LabelEnv.add Throw (Cont (ContVar k_fail)) LabelEnv.empty) in - k -@- (asyncE typ1 (typ exp1) ([k_ret; k_fail] -->* - (c_exp context' exp1 (ContVar k_ret)))) + k -@- (asyncE typ1 (typ exp1) + (forall [tb] ([k_ret; k_fail] -->* + (c_exp context' exp1 (ContVar k_ret))))) | AwaitE exp1 -> let r = match LabelEnv.find_opt Throw context with | Some (Cont r) -> r From 77f5493fc1f8f7e75e0e7ec8b95fb1e9fd9a755d Mon Sep 17 00:00:00 2001 From: Enzo Haussecker Date: Mon, 18 Nov 2019 12:57:45 -0800 Subject: [PATCH 0637/1176] Add function to split a list into length-n chunks --- stdlib/list.mo | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/stdlib/list.mo b/stdlib/list.mo index 0357ad54045..49e01e9ca60 100644 --- a/stdlib/list.mo +++ b/stdlib/list.mo @@ -560,7 +560,7 @@ public type List = ?(T, List); /** `splitAt` ----------- - Creates a pair of lists by splitting the given list at the given (zero-based) index. + Split the given list at the given zero-based index. */ public func splitAt(n : Nat, xs : List) : (List, List) { if (n == 0) { @@ -585,6 +585,21 @@ public type List = ?(T, List); } }; + /** + `chunksOf` + ----------- + Split the given list into length-n chunks. The last chunk will be shorter if + n does not evenly divide the length of the given list. + */ + public func chunksOf(n : Nat, xs : List) : List> { + let (l, r) = splitAt(n, xs); + if (isNil(l)) { + null + } else { + push>(l, chunksOf(n, r)) + } + }; + public func fromArray(xs : [A]) : List { Array.foldr>(func (x : A, ys : List) : List { push(x, ys); From 7dfe883851f76b32d31a138332a979cd257aa2fb Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Mon, 18 Nov 2019 21:29:57 +0000 Subject: [PATCH 0638/1176] make @ an (unpriviledged) identifier for naming scope indices; support scope polymorphic shared function in async.ml --- src/ir_def/check_ir.ml | 2 +- src/ir_passes/async.ml | 5 +++-- src/mo_frontend/lexer.mll | 2 +- src/mo_frontend/parser.mly | 2 +- src/prelude/prelude.ml | 2 +- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index ced29261de2..beb5d86d332 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -388,7 +388,7 @@ let rec check_exp env (exp:Ir.exp) : unit = check_exp env r; let t1 = T.promote (typ exp1) in begin match t1 with - | T.Func (sort, T.Replies, [], arg_tys, ret_tys) -> + | T.Func (sort, T.Replies, _ (*TBR*), arg_tys, ret_tys) -> check_exp env exp2; let t_arg = T.seq arg_tys in typ exp2 <: t_arg; diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index a938fca1c2a..80ee6c9acca 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -286,11 +286,12 @@ let transform mode env prog = nary_async ).it | CallE (exp1, typs, exp2) when isAwaitableFunc exp1 -> - assert (typs = []); + (* assert (typs = []); *) let ts1,ts2 = match typ exp1 with | T.Func (T.Shared _, T.Promises _,tbs,ts1,ts2) -> - List.map t_typ ts1, List.map t_typ ts2 + List.map (fun t -> t_typ (T.open_ typs t)) ts1, + List.map (fun t -> t_typ (T.open_ typs t)) ts2 | _ -> assert(false) in let exp1' = t_exp exp1 in diff --git a/src/mo_frontend/lexer.mll b/src/mo_frontend/lexer.mll index 675268d8984..8e633a6fae4 100644 --- a/src/mo_frontend/lexer.mll +++ b/src/mo_frontend/lexer.mll @@ -107,7 +107,7 @@ let float = | "0x" hexnum ('.' hexfrac?)? ('p' | 'P') sign? num let char = '\'' character '\'' let text = '"' character* '"' -let id = (letter | '_') ((letter | digit | '_')*) +let id = '@' | ((letter | '_') ((letter | digit | '_')*)) let privileged_id = "@" id let reserved = ([^'\"''('')'';'] # space)+ (* hack for table size *) diff --git a/src/mo_frontend/parser.mly b/src/mo_frontend/parser.mly index 825b958be7c..c60611deae6 100644 --- a/src/mo_frontend/parser.mly +++ b/src/mo_frontend/parser.mly @@ -89,7 +89,7 @@ let share_expfield (ef : exp_field) = then ef else {ef with it = {ef.it with dec = share_dec ef.it.dec}} -let scope_id = "@_" +let scope_id = "@" let scope_bind() = {var = scope_id @@ no_region; bound = PrimT "Any" @! no_region} @= no_region let scope_typ() = PathT ((IdH (scope_id @@ no_region)) @! no_region, []) @! no_region diff --git a/src/prelude/prelude.ml b/src/prelude/prelude.ml index 38ee7c0cad5..f0216625cf9 100644 --- a/src/prelude/prelude.ml +++ b/src/prelude/prelude.ml @@ -24,7 +24,7 @@ type Text = prim "Text"; type Error = prim "Error"; // top level scope -type @_ = Any; +type @ = Any; type Iter = {next : () -> ?T_}; From 02a4c47ae0d47b64674a37601441c67ed0b22ede Mon Sep 17 00:00:00 2001 From: Enzo Haussecker Date: Mon, 18 Nov 2019 15:40:53 -0800 Subject: [PATCH 0639/1176] Add function to convert text to list of characters --- stdlib/text.mo | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/stdlib/text.mo b/stdlib/text.mo index 8d74ff17cb3..2068814bf18 100644 --- a/stdlib/text.mo +++ b/stdlib/text.mo @@ -1,5 +1,19 @@ +import List "mo:stdlib/list.mo"; +import Option "mo:stdlib/option.mo"; + +type List = List.List; + module { + public func append(x : Text, y : Text) : Text { x # y; }; + + public func toList(text : Text) : List { + let get = text.chars().next; + List.tabulate(text.len(), func _ { + Option.unwrap(get()) + }) + }; + } From f2c77f5c7d8838e149da4d2c60d143f955b83e62 Mon Sep 17 00:00:00 2001 From: Enzo Haussecker Date: Mon, 18 Nov 2019 16:13:00 -0800 Subject: [PATCH 0640/1176] Fix up imports --- stdlib/text.mo | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/text.mo b/stdlib/text.mo index 2068814bf18..c6a113f1e2c 100644 --- a/stdlib/text.mo +++ b/stdlib/text.mo @@ -1,5 +1,5 @@ -import List "mo:stdlib/list.mo"; -import Option "mo:stdlib/option.mo"; +import List "list.mo"; +import Option "option.mo"; type List = List.List; From abf221534a269006e692df1b248c90c73b425b69 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity <48968912+chenyan-dfinity@users.noreply.github.com> Date: Mon, 18 Nov 2019 16:24:21 -0800 Subject: [PATCH 0641/1176] Update IDL func type (#881) * update IDL func type * Update src/mo_idl/mo_to_idl.ml Co-Authored-By: Joachim Breitner --- src/idllib/arrange_idl.ml | 6 +++--- src/idllib/compile_js.ml | 17 ++++++++++++----- src/idllib/parser.mly | 8 ++++++-- src/idllib/syntax.ml | 2 +- src/idllib/typing.ml | 6 +++--- src/mo_idl/mo_to_idl.ml | 8 +++++--- test/idl/fieldnat.did | 2 +- test/idl/ok/actor.js.ok | 9 ++++----- test/idl/ok/cyclic.js.ok | 4 +--- test/idl/ok/diamond.js.ok | 3 +-- test/idl/ok/escape.js.ok | 2 +- test/idl/ok/fieldnat.js.ok | 10 ++++------ test/idl/ok/fields.js.ok | 4 +--- test/idl/ok/import.js.ok | 7 ++----- test/idl/ok/import1.js.ok | 3 +-- test/idl/ok/import3.js.ok | 18 ++++++------------ test/idl/ok/integer.js.ok | 6 +++--- test/idl/ok/keywords.js.ok | 8 ++------ test/idl/ok/px.js.ok | 4 +--- test/idl/ok/recursion.js.ok | 18 ++++++------------ test/idl/ok/test.js.ok | 23 ++++++++++------------- test/idl/ok/unicode.js.ok | 8 +++----- 22 files changed, 77 insertions(+), 99 deletions(-) diff --git a/src/idllib/arrange_idl.ml b/src/idllib/arrange_idl.ml index 6bb4d2628fc..378d193f270 100644 --- a/src/idllib/arrange_idl.ml +++ b/src/idllib/arrange_idl.ml @@ -26,7 +26,7 @@ let string_of_mode m = match m.it with | Oneway -> " oneway" | Query -> " query" - + let ($$) head inner = Node (head, inner) and id i = Atom i.it @@ -53,7 +53,7 @@ and typ t = match t.it with | VecT t -> "VecT" $$ [typ t] | OptT t -> "OptT" $$ [typ t] | VariantT cts -> "VariantT" $$ List.map typ_field cts - | FuncT (ms, s, t) -> "FuncT" $$ List.map typ_field s @ List.map typ_field t @ List.map mode ms + | FuncT (ms, s, t) -> "FuncT" $$ List.map typ s @ List.map typ t @ List.map mode ms | ServT ts -> "ServT" $$ List.map typ_meth ts | PreT -> Atom "PreT" @@ -133,7 +133,7 @@ and pp_args ppf fs = let n = List.length fs in str ppf "("; List.iteri (fun i f -> - pp_field ppf f; + pp_typ ppf f; if i < n-1 then kwd ppf ","; ) fs; diff --git a/src/idllib/compile_js.ml b/src/idllib/compile_js.ml index f31c8c1ded4..983cb104083 100644 --- a/src/idllib/compile_js.ml +++ b/src/idllib/compile_js.ml @@ -11,7 +11,7 @@ type typ_info = { typ : typ; is_rec : bool; } - + (* Gather type definitions from actor and sort the definitions in topological order *) let chase_env env actor = let new_env = ref [] in @@ -31,7 +31,7 @@ let chase_env env actor = | VecT t -> chase t | RecordT fs -> chase_fields fs | VariantT fs -> chase_fields fs - | FuncT (ms, fs1, fs2) -> chase_fields fs1; chase_fields fs2 + | FuncT (ms, fs1, fs2) -> List.iter chase fs1; List.iter chase fs2 | PreT -> assert false and chase_fields fs = List.iter (fun (f : typ_field) -> chase f.it.typ) fs @@ -58,7 +58,7 @@ let infer_rec env_list = | VecT t -> go t | RecordT fs -> go_fields fs | VariantT fs -> go_fields fs - | FuncT (_, fs1, fs2) -> go_fields fs1; go_fields fs2 + | FuncT (_, fs1, fs2) -> List.iter go fs1; List.iter go fs2 | preT -> assert false and go_fields fs = List.iter (fun (f:typ_field) -> go f.it.typ) fs @@ -109,9 +109,9 @@ let rec pp_typ ppf t = | VariantT ts -> str ppf "IDL.Variant({"; concat ppf pp_field "," ts; str ppf "})"; | FuncT (ms, t1, t2) -> str ppf "IDL.Func("; - pp_fields ppf t1; + pp_args ppf t1; kwd ppf ","; - pp_fields ppf t2; + pp_args ppf t2; str ppf ")"; | ServT ts -> pp_open_hovbox ppf 1; @@ -124,6 +124,13 @@ let rec pp_typ ppf t = ); pp_close_box ppf () +and pp_args ppf args = + pp_open_box ppf 1; + str ppf "["; + concat ppf pp_typ "," args; + str ppf "]"; + pp_close_box ppf () + and pp_fields ppf fs = pp_open_box ppf 1; str ppf "IDL.Obj({"; diff --git a/src/idllib/parser.mly b/src/idllib/parser.mly index e6701f4ed38..def2c37de69 100644 --- a/src/idllib/parser.mly +++ b/src/idllib/parser.mly @@ -131,8 +131,12 @@ data_typ : | t=prim_typ { t } param_typs : - | LPAR fs=seplist(record_typ, COMMA) RPAR - { record_fields fs } + | LPAR fs=seplist(param_typ, COMMA) RPAR + { fs } + +param_typ : + | t=data_typ { t } + | name COLON t=data_typ { t } func_mode : | m=id diff --git a/src/idllib/syntax.ml b/src/idllib/syntax.ml index 6cec88d7f08..94dee6f5162 100644 --- a/src/idllib/syntax.ml +++ b/src/idllib/syntax.ml @@ -34,7 +34,7 @@ type typ = typ' Source.phrase and typ' = | PrimT of prim (* primitive *) | VarT of id (* type name *) - | FuncT of func_mode list * typ_field list * typ_field list (* function *) + | FuncT of func_mode list * typ list * typ list (* function *) | OptT of typ (* option *) | VecT of typ (* vector *) | RecordT of typ_field list (* record *) diff --git a/src/idllib/typing.ml b/src/idllib/typing.ml index fca453ed9d3..883a4209fe6 100644 --- a/src/idllib/typing.ml +++ b/src/idllib/typing.ml @@ -73,7 +73,7 @@ let field_name (f: typ_field) = | Id n -> Lib.Uint32.to_string n | Named name -> name | Unnamed n -> "Unnamed " ^ (Lib.Uint32.to_string n) - + let compare_field (f1: typ_field) (f2: typ_field) = Lib.Uint32.compare (field_id f1) (field_id f2) let compare_meth (m1: typ_meth) (m2: typ_meth) = compare m1.it.var m2.it.var let find_type env id = @@ -113,8 +113,8 @@ let rec check_typ env t = | PrimT prim -> t | VarT id -> ignore (find_type env id); t | FuncT (ms, t1, t2) -> - let t1' = check_fields env t1 in - let t2' = check_fields env t2 in + let t1' = List.map (fun t -> check_typ env t) t1 in + let t2' = List.map (fun t -> check_typ env t) t2 in if List.exists (fun m -> m.it == Oneway) ms && List.length t2 > 0 then error env t.at "oneway function has non-unit return type"; FuncT (ms, t1', t2') @@ t.at diff --git a/src/mo_idl/mo_to_idl.ml b/src/mo_idl/mo_to_idl.ml index dac21c4f9eb..4556ac6d443 100644 --- a/src/mo_idl/mo_to_idl.ml +++ b/src/mo_idl/mo_to_idl.ml @@ -104,15 +104,15 @@ let rec typ vs t = | Variant fs -> I.VariantT (List.map (field vs) fs) | Func (Shared s, c, [], ts1, ts2) -> - let fs1 = tuple vs ts1 in + let t1 = args vs ts1 in (match ts2, c with - | [], Returns -> I.FuncT ([I.Oneway @@ no_region], fs1, []) + | [], Returns -> I.FuncT ([I.Oneway @@ no_region], t1, []) | ts, Promises -> I.FuncT ( (match s with | Query -> [I.Query @@ no_region] | Write -> []), - fs1, tuple vs ts) + t1, args vs ts) | _ -> assert false) | Func _ -> assert false | Async t -> assert false @@ -131,6 +131,8 @@ and tuple vs ts = let id = Lib.Uint32.of_int i in I.{label = I.Unnamed id @@ no_region; typ = typ vs x} @@ no_region ) ts +and args vs ts = + List.map (typ vs) ts and meths vs fs = List.fold_right (fun f list -> match f.typ with diff --git a/test/idl/fieldnat.did b/test/idl/fieldnat.did index cdc412a14ea..7f1ebd2d3d6 100644 --- a/test/idl/fieldnat.did +++ b/test/idl/fieldnat.did @@ -3,6 +3,6 @@ service Foo { bar : (record {"2" : int}) -> (); // TODO: JS binding treats all field names as string baz : (record {2: int; "2": nat}) -> (); - bab : (2: int, "2": nat) -> (); + bab : (two: int, "2": nat) -> (); } diff --git a/test/idl/ok/actor.js.ok b/test/idl/ok/actor.js.ok index 875bc47239b..2370c62aa8c 100644 --- a/test/idl/ok/actor.js.ok +++ b/test/idl/ok/actor.js.ok @@ -1,11 +1,10 @@ export default ({ IDL }) => { const o = IDL.Rec() - const f = IDL.Func(IDL.Obj({'0': IDL.Int8}), IDL.Obj({'0': IDL.Int8})) - const h = IDL.Func(IDL.Obj({'0': f}), IDL.Obj({'0': f})) + const f = IDL.Func([IDL.Int8], [IDL.Int8]) + const h = IDL.Func([f], [f]) const g = f o.fill(IDL.Opt(o)) - const actor_g = new IDL.ActorInterface({ - 'f': IDL.Func(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': h})), 'g': f, - 'h': g, 'o': IDL.Func(IDL.Obj({'0': o}), IDL.Obj({'0': o}))}); + const actor_g = new IDL.ActorInterface({'f': IDL.Func([IDL.Nat], [h]), + 'g': f, 'h': g, 'o': IDL.Func([o], [o])}); return actor_g; }; diff --git a/test/idl/ok/cyclic.js.ok b/test/idl/ok/cyclic.js.ok index 119fbfd9030..4aba8bf66cd 100644 --- a/test/idl/ok/cyclic.js.ok +++ b/test/idl/ok/cyclic.js.ok @@ -7,8 +7,6 @@ export default ({ IDL }) => { const Y = Z const X = Y const actor_S = new IDL.ActorInterface({ - 'f': - IDL.Func(IDL.Obj({'0': A, '1': B, '2': C, '3': X, '4': Y, '5': Z}), - IDL.Obj({}))}); + 'f': IDL.Func([A, B, C, X, Y, Z], [])}); return actor_S; }; diff --git a/test/idl/ok/diamond.js.ok b/test/idl/ok/diamond.js.ok index 4dbe0a2d635..2e957b9362b 100644 --- a/test/idl/ok/diamond.js.ok +++ b/test/idl/ok/diamond.js.ok @@ -3,7 +3,6 @@ export default ({ IDL }) => { const t2 = IDL.Arr(t) const t3 = IDL.Opt(t) const t1 = IDL.Obj({'0': t2, '1': t3, '2': t}) - const actor_S = new IDL.ActorInterface({ - 'f': IDL.Func(IDL.Obj({'0': t, '1': t2, '2': t3}), IDL.Obj({'0': t1}))}); + const actor_S = new IDL.ActorInterface({'f': IDL.Func([t, t2, t3], [t1])}); return actor_S; }; diff --git a/test/idl/ok/escape.js.ok b/test/idl/ok/escape.js.ok index 334209fb0e0..c39ee2a7772 100644 --- a/test/idl/ok/escape.js.ok +++ b/test/idl/ok/escape.js.ok @@ -3,6 +3,6 @@ export default ({ IDL }) => { IDL.Obj({'\"': IDL.Nat, '\'': IDL.Nat, '\"\'': IDL.Nat, '\\\n\'\"': IDL.Nat }) const actor_E = new IDL.ActorInterface({ - '\n\'\"\'\'\"\"\r\t': IDL.Func(IDL.Obj({'0': t}), IDL.Obj({}))}); + '\n\'\"\'\'\"\"\r\t': IDL.Func([t], [])}); return actor_E; }; diff --git a/test/idl/ok/fieldnat.js.ok b/test/idl/ok/fieldnat.js.ok index 41edca0128b..60b621faf12 100644 --- a/test/idl/ok/fieldnat.js.ok +++ b/test/idl/ok/fieldnat.js.ok @@ -1,10 +1,8 @@ export default ({ IDL }) => { const actor_Foo = new IDL.ActorInterface({ - 'foo': IDL.Func(IDL.Obj({'0': IDL.Obj({'2': IDL.Int})}), IDL.Obj({})), - 'bar': IDL.Func(IDL.Obj({'0': IDL.Obj({'2': IDL.Int})}), IDL.Obj({})), - 'baz': - IDL.Func(IDL.Obj({'0': IDL.Obj({'2': IDL.Int, '2': IDL.Nat})}), - IDL.Obj({})), - 'bab': IDL.Func(IDL.Obj({'2': IDL.Int, '2': IDL.Nat}), IDL.Obj({}))}); + 'foo': IDL.Func([IDL.Obj({'2': IDL.Int})], []), + 'bar': IDL.Func([IDL.Obj({'2': IDL.Int})], []), + 'baz': IDL.Func([IDL.Obj({'2': IDL.Int, '2': IDL.Nat})], []), + 'bab': IDL.Func([IDL.Int, IDL.Nat], [])}); return actor_Foo; }; diff --git a/test/idl/ok/fields.js.ok b/test/idl/ok/fields.js.ok index 3f7599fe745..71e1f4e4ad7 100644 --- a/test/idl/ok/fields.js.ok +++ b/test/idl/ok/fields.js.ok @@ -14,8 +14,6 @@ export default ({ IDL }) => { '3': IDL.Obj({'0': IDL.Nat, '1': IDL.Nat, '2': IDL.Nat}), '4': IDL.Nat, '5': IDL.Nat, '6': IDL.Nat, '7': A, '8': B, '9': C, '10': IDL.Nat}) const actor_S = new IDL.ActorInterface({ - 'f': - IDL.Func(IDL.Obj({'0': A, '1': B, '2': C, '3': nest_record}), IDL.Obj({})) - }); + 'f': IDL.Func([A, B, C, nest_record], [])}); return actor_S; }; diff --git a/test/idl/ok/import.js.ok b/test/idl/ok/import.js.ok index 0f4e9f52bf3..1a56ff8bf8f 100644 --- a/test/idl/ok/import.js.ok +++ b/test/idl/ok/import.js.ok @@ -12,10 +12,7 @@ export default ({ IDL }) => { const IdErr = IDL.Obj({'idErr': OpEntId}) const Inventory = IDL.Obj({'produce_id': IDL.Nat, 'quantity': IDL.Nat}) const actor_S = new IDL.ActorInterface({ - 'f': - IDL.Func(IDL.Obj({'0': t, '1': t1, '2': t2}), - IDL.Obj({'0': list, '1': IdErr})), - 'getInventory': - IDL.Func(IDL.Obj({'producer_id': IDL.Nat}), IDL.Obj({'0': Inventory}))}); + 'f': IDL.Func([t, t1, t2], [list, IdErr]), + 'getInventory': IDL.Func([IDL.Nat], [Inventory])}); return actor_S; }; diff --git a/test/idl/ok/import1.js.ok b/test/idl/ok/import1.js.ok index 2bee6bffe15..f9f378b390b 100644 --- a/test/idl/ok/import1.js.ok +++ b/test/idl/ok/import1.js.ok @@ -3,7 +3,6 @@ export default ({ IDL }) => { const t1 = t const UserId = IDL.Nat const t2 = UserId - const actor_S = new IDL.ActorInterface({ - 'f': IDL.Func(IDL.Obj({'0': t, '1': t1, '2': t2}), IDL.Obj({}))}); + const actor_S = new IDL.ActorInterface({'f': IDL.Func([t, t1, t2], [])}); return actor_S; }; diff --git a/test/idl/ok/import3.js.ok b/test/idl/ok/import3.js.ok index 16299826063..d6beb90cb66 100644 --- a/test/idl/ok/import3.js.ok +++ b/test/idl/ok/import3.js.ok @@ -4,25 +4,19 @@ export default ({ IDL }) => { const s = IDL.Rec() const stream = IDL.Rec() const tree = IDL.Rec() - const t = IDL.Func(IDL.Obj({'server': s}), IDL.Obj({})) + const t = IDL.Func([s], []) const node = IDL.Obj({'head': IDL.Nat, 'tail': list}) list.fill(IDL.Opt(node)) - stream.fill( - IDL.Opt( - IDL.Obj({'head': IDL.Nat, - 'next': IDL.Func(IDL.Obj({}), IDL.Obj({'0': stream}))})) - ) + const A = B + B.fill(IDL.Opt(A)) tree.fill( IDL.Variant({ 'branch': IDL.Obj({'val': IDL.Int, 'left': tree, 'right': tree}), 'leaf': IDL.Int})) - const A = B - B.fill(IDL.Opt(A)) + stream.fill( + IDL.Opt(IDL.Obj({'head': IDL.Nat, 'next': IDL.Func([], [stream])}))) s.fill( - new IDL.ActorInterface({'f': t, - 'g': - IDL.Func(IDL.Obj({'0': list}), IDL.Obj({'2': stream, '1': tree, '0': B})) - })) + new IDL.ActorInterface({'f': t, 'g': IDL.Func([list], [B, tree, stream])})) const actor_S = s.__typ; return actor_S; }; diff --git a/test/idl/ok/integer.js.ok b/test/idl/ok/integer.js.ok index 87da2b1e380..c0dc38ae2e4 100644 --- a/test/idl/ok/integer.js.ok +++ b/test/idl/ok/integer.js.ok @@ -1,7 +1,7 @@ export default ({ IDL }) => { const actor_num = new IDL.ActorInterface({ - 'f': IDL.Func(IDL.Obj({'0': IDL.Nat8}), IDL.Obj({'0': IDL.Int16})), - 'g': IDL.Func(IDL.Obj({'0': IDL.Nat64}), IDL.Obj({'0': IDL.Int64})), - 'h': IDL.Func(IDL.Obj({'0': IDL.Int8}), IDL.Obj({'0': IDL.Nat}))}); + 'f': IDL.Func([IDL.Nat8], [IDL.Int16]), + 'g': IDL.Func([IDL.Nat64], [IDL.Int64]), + 'h': IDL.Func([IDL.Int8], [IDL.Nat])}); return actor_num; }; diff --git a/test/idl/ok/keywords.js.ok b/test/idl/ok/keywords.js.ok index b13d803e6c6..338022c9e51 100644 --- a/test/idl/ok/keywords.js.ok +++ b/test/idl/ok/keywords.js.ok @@ -2,12 +2,8 @@ export default ({ IDL }) => { const const_ = IDL.Obj({'type_': IDL.Nat, 'vec_': IDL.Nat, 'service_': IDL.Nat}) const actor_s = new IDL.ActorInterface({ - 'blob': IDL.Func(IDL.Obj({'0': const_}), IDL.Obj({'0': IDL.Arr(IDL.Nat8)})), - + 'blob': IDL.Func([const_], [IDL.Arr(IDL.Nat8)]), 'record': - IDL.Func( - IDL.Obj({'opt_': IDL.Nat, 'import_': IDL.Nat, 'variant_': IDL.Variant({}) - }), - IDL.Obj({'record_': IDL.Nat, '821774511': IDL.Obj({})}))}); + IDL.Func([IDL.Nat, IDL.Nat, IDL.Variant({})], [IDL.Nat, IDL.Obj({})])}); return actor_s; }; diff --git a/test/idl/ok/px.js.ok b/test/idl/ok/px.js.ok index bec47c4fb9b..1ae4b25bbf0 100644 --- a/test/idl/ok/px.js.ok +++ b/test/idl/ok/px.js.ok @@ -13,8 +13,6 @@ export default ({ IDL }) => { const OpEntId = IDL.Opt(EntId) const IdErr = IDL.Obj({'idErr': OpEntId}) const actor_ProduceExchange = new IDL.ActorInterface({ - 'getInventory': - IDL.Func(IDL.Obj({'producer_id': IDL.Nat, '3667444713': UserInfo}), - IDL.Obj({'0': Inventory, '1': IdErr}))}); + 'getInventory': IDL.Func([IDL.Nat, UserInfo], [Inventory, IdErr])}); return actor_ProduceExchange; }; diff --git a/test/idl/ok/recursion.js.ok b/test/idl/ok/recursion.js.ok index 9c0f918d693..747b82cfdec 100644 --- a/test/idl/ok/recursion.js.ok +++ b/test/idl/ok/recursion.js.ok @@ -4,25 +4,19 @@ export default ({ IDL }) => { const s = IDL.Rec() const stream = IDL.Rec() const tree = IDL.Rec() - const t = IDL.Func(IDL.Obj({'server': s}), IDL.Obj({})) + const t = IDL.Func([s], []) const node = IDL.Obj({'head': IDL.Nat, 'tail': list}) list.fill(IDL.Opt(node)) - stream.fill( - IDL.Opt( - IDL.Obj({'head': IDL.Nat, - 'next': IDL.Func(IDL.Obj({}), IDL.Obj({'0': stream}))})) - ) + const A = B + B.fill(IDL.Opt(A)) tree.fill( IDL.Variant({ 'branch': IDL.Obj({'val': IDL.Int, 'left': tree, 'right': tree}), 'leaf': IDL.Int})) - const A = B - B.fill(IDL.Opt(A)) + stream.fill( + IDL.Opt(IDL.Obj({'head': IDL.Nat, 'next': IDL.Func([], [stream])}))) s.fill( - new IDL.ActorInterface({'f': t, - 'g': - IDL.Func(IDL.Obj({'0': list}), IDL.Obj({'2': stream, '1': tree, '0': B})) - })) + new IDL.ActorInterface({'f': t, 'g': IDL.Func([list], [B, tree, stream])})) const actor_A = s.__typ; return actor_A; }; diff --git a/test/idl/ok/test.js.ok b/test/idl/ok/test.js.ok index 37feb3c96ad..1ea953ff2a5 100644 --- a/test/idl/ok/test.js.ok +++ b/test/idl/ok/test.js.ok @@ -5,20 +5,17 @@ export default ({ IDL }) => { const broker = new IDL.ActorInterface({ 'find': - IDL.Func(IDL.Obj({'name': IDL.Text}), - IDL.Obj({ - '0': - new IDL.ActorInterface({'up': IDL.Func(IDL.Obj({}), IDL.Obj({})), - 'current': IDL.Func(IDL.Obj({}), IDL.Obj({'0': IDL.Nat}))}) - })) + IDL.Func([IDL.Text], + [ + new IDL.ActorInterface({'up': IDL.Func([], []), + 'current': IDL.Func([], [IDL.Nat])}) + ]) }) const actor_server = new IDL.ActorInterface({ - 'addUser': - IDL.Func(IDL.Obj({'name': IDL.Text, 'age': IDL.Nat8}), - IDL.Obj({'id': IDL.Nat64})), - 'userName': IDL.Func(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({'0': IDL.Text})), - 'userAge': IDL.Func(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({'0': IDL.Nat8})), - 'deleteUser': IDL.Func(IDL.Obj({'id': IDL.Nat64}), IDL.Obj({})), - 'f': IDL.Func(IDL.Obj({'0': message}), IDL.Obj({'0': broker}))}); + 'addUser': IDL.Func([IDL.Text, IDL.Nat8], [IDL.Nat64]), + 'userName': IDL.Func([IDL.Nat64], [IDL.Text]), + 'userAge': IDL.Func([IDL.Nat64], [IDL.Nat8]), + 'deleteUser': IDL.Func([IDL.Nat64], []), 'f': IDL.Func([message], [broker]) + }); return actor_server; }; diff --git a/test/idl/ok/unicode.js.ok b/test/idl/ok/unicode.js.ok index 55a1fa71b81..9fa4d61d285 100644 --- a/test/idl/ok/unicode.js.ok +++ b/test/idl/ok/unicode.js.ok @@ -5,10 +5,8 @@ export default ({ IDL }) => { const B = IDL.Variant({'': IDL.Unit, '空的': IDL.Unit, ' 空的 ': IDL.Unit, '1⃣️2⃣️3⃣️': IDL.Unit}) - const actor_C = new IDL.ActorInterface({ - '函数名': IDL.Func(IDL.Obj({'0': A}), IDL.Obj({'0': B})), - '': IDL.Func(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': IDL.Nat})), - '👀': IDL.Func(IDL.Obj({'0': IDL.Nat}), IDL.Obj({'0': IDL.Nat})), - '✈️ 🚗 ⛱️ ': IDL.Func(IDL.Obj({}), IDL.Obj({}))}); + const actor_C = new IDL.ActorInterface({'函数名': IDL.Func([A], [B]), + '': IDL.Func([IDL.Nat], [IDL.Nat]), '👀': IDL.Func([IDL.Nat], [IDL.Nat]), + '✈️ 🚗 ⛱️ ': IDL.Func([], [])}); return actor_C; }; From b4d35bf4896781003501843c51024e62a18a1e46 Mon Sep 17 00:00:00 2001 From: Enzo Haussecker Date: Mon, 18 Nov 2019 16:37:18 -0800 Subject: [PATCH 0642/1176] Add character is digit test --- stdlib/char.mo | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 stdlib/char.mo diff --git a/stdlib/char.mo b/stdlib/char.mo new file mode 100644 index 00000000000..62f5849546a --- /dev/null +++ b/stdlib/char.mo @@ -0,0 +1,7 @@ +module { + + public func isDigit(char : Char) : Bool { + charToWord32(char) - charToWord32('0') <= (9 : Word32) + }; + +} From 9f138a73de792faaf0e7cc3cedc19ccdc46cb101 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 19 Nov 2019 10:19:48 +0100 Subject: [PATCH 0643/1176] Streamline signature of rawInitializeMethod --- ic-stub/src/IC/Canister/Imp.hs | 4 ++-- ic-stub/src/IC/Canister/Persisted.hs | 5 +++-- ic-stub/src/IC/Canister/Pure.hs | 8 +++++--- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/ic-stub/src/IC/Canister/Imp.hs b/ic-stub/src/IC/Canister/Imp.hs index 26e1bbdbb69..2ebff7898a0 100644 --- a/ic-stub/src/IC/Canister/Imp.hs +++ b/ic-stub/src/IC/Canister/Imp.hs @@ -302,8 +302,8 @@ rawInitializeModule esref wasm_mod = do Left err -> return $ Trap err Right inst -> return $ Return inst -rawInitializeMethod :: ESRef s -> Module -> Instance s -> CanisterId -> EntityId -> Blob -> ST s (TrapOr ()) -rawInitializeMethod esref wasm_mod inst cid caller dat = do +rawInitializeMethod :: ImpState s -> Module -> EntityId -> Blob -> ST s (TrapOr ()) +rawInitializeMethod (esref, cid, inst) wasm_mod caller dat = do result <- runExceptT $ do let es = (initalExecutionState cid inst) { params = Params diff --git a/ic-stub/src/IC/Canister/Persisted.hs b/ic-stub/src/IC/Canister/Persisted.hs index eb26530869b..a6b31020cdf 100644 --- a/ic-stub/src/IC/Canister/Persisted.hs +++ b/ic-stub/src/IC/Canister/Persisted.hs @@ -27,8 +27,9 @@ initializeMethod :: Module -> CanisterId -> EntityId -> Blob -> TrapOr WasmState initializeMethod wasm_mod cid caller dat = runESST $ \esref -> rawInitializeModule esref wasm_mod >>= \case Trap err -> return $ Trap err - Return inst -> - rawInitializeMethod esref wasm_mod inst cid caller dat >>= \case + Return inst -> do + let rs = (esref, cid, inst) + rawInitializeMethod rs wasm_mod caller dat >>= \case Trap err -> return $ Trap err Return () -> Return . WasmState wasm_mod cid <$> persistInstance inst diff --git a/ic-stub/src/IC/Canister/Pure.hs b/ic-stub/src/IC/Canister/Pure.hs index c6e2aa57b42..41144128866 100644 --- a/ic-stub/src/IC/Canister/Pure.hs +++ b/ic-stub/src/IC/Canister/Pure.hs @@ -35,7 +35,8 @@ initializeMethod wasm_mod cid caller dat = runESST $ \esref -> rawInitializeModule esref wasm_mod >>= \case Trap err -> return $ Trap err Return inst -> do - result <- rawInitializeMethod esref wasm_mod inst cid caller dat + let rs = (esref, cid, inst) + result <- rawInitializeMethod rs wasm_mod caller dat let state' = WSInit wasm_mod cid caller dat case result of Trap err -> return $ Trap err @@ -78,8 +79,9 @@ replay esref s = silently esref $ go s go :: WasmState -> ST s (ImpState s) go (WSInit wasm_mod cid caller dat) = do inst <- rawInitializeModule esref wasm_mod >>= trapToFail - rawInitializeMethod esref wasm_mod inst cid caller dat >>= trapToFail - return (esref, cid, inst) + let rs = (esref, cid, inst) + rawInitializeMethod rs wasm_mod caller dat >>= trapToFail + return rs go (WSUpdate m caller dat s) = do is <- go s _ <- rawUpdateMethod is m caller dat >>= trapToFail From a3cbfc6330c990c350838453b9785be8d35ba7cb Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 19 Nov 2019 10:58:32 +0100 Subject: [PATCH 0644/1176] Make persistence/replay code agnostic in data flowing in an out --- ic-stub/ic-stub.cabal | 1 + ic-stub/src/IC/Canister.hs | 12 +++-- ic-stub/src/IC/Canister/Imp.hs | 17 ++++-- ic-stub/src/IC/Canister/Interface.hs | 19 +++++++ ic-stub/src/IC/Canister/Persisted.hs | 43 ++++----------- ic-stub/src/IC/Canister/Pure.hs | 80 +++++++++++----------------- ic-stub/src/IC/Stub.hs | 6 +-- ic-stub/src/IC/Types.hs | 3 +- 8 files changed, 86 insertions(+), 95 deletions(-) create mode 100644 ic-stub/src/IC/Canister/Interface.hs diff --git a/ic-stub/ic-stub.cabal b/ic-stub/ic-stub.cabal index 49a6ac555e0..81e96705bb0 100644 --- a/ic-stub/ic-stub.cabal +++ b/ic-stub/ic-stub.cabal @@ -16,6 +16,7 @@ executable ic-stub-run other-modules: IC.Types other-modules: IC.Canister other-modules: IC.Canister.Imp + other-modules: IC.Canister.Interface other-modules: IC.Canister.Pure other-modules: IC.Canister.Persisted other-modules: IC.Wasm.Winter diff --git a/ic-stub/src/IC/Canister.hs b/ic-stub/src/IC/Canister.hs index 8d4707b051b..8b9d116b5aa 100644 --- a/ic-stub/src/IC/Canister.hs +++ b/ic-stub/src/IC/Canister.hs @@ -21,11 +21,12 @@ import Data.List import IC.Types import IC.Wasm.Winter (parseModule, exportedFunctions, Module) +import qualified IC.Canister.Interface as CI -- Here we can swap out the persistence implementation import IC.Canister.Persisted type InitFunc = CanisterId -> EntityId -> Blob -> TrapOr WasmState -type UpdateFunc = WasmState -> TrapOr (WasmState, [MethodCall], Maybe Response) +type UpdateFunc = WasmState -> TrapOr (WasmState, ([MethodCall], Maybe Response)) type QueryFunc = WasmState -> TrapOr Response data CanisterModule = CanisterModule @@ -43,16 +44,17 @@ parseCanister bytes = concreteToAbstractModule :: Module -> CanisterModule concreteToAbstractModule wasm_mod = CanisterModule - { init_method = \cid caller dat -> initializeMethod wasm_mod cid caller dat + { init_method = \cid caller dat -> initialize wasm_mod cid caller dat , update_methods = M.fromList - [ (m, \caller dat wasm_state -> updateMethod m caller dat wasm_state) + [ (m, \caller dat wasm_state -> invoke wasm_state (CI.Update m caller dat)) | n <- exportedFunctions wasm_mod , Just m <- return $ stripPrefix "canister_update " n ] , query_methods = M.fromList - [ (m, \arg wasm_state -> queryMethod m arg wasm_state) + [ (m, \caller arg wasm_state -> + snd <$> invoke wasm_state (CI.Query m caller arg)) | n <- exportedFunctions wasm_mod , Just m <- return $ stripPrefix "canister_query " n ] - , callbacks = callbackMethod + , callbacks = \cb cid res wasm_state -> invoke wasm_state (CI.Callback cb cid res) } diff --git a/ic-stub/src/IC/Canister/Imp.hs b/ic-stub/src/IC/Canister/Imp.hs index 2ebff7898a0..4a35f9f429f 100644 --- a/ic-stub/src/IC/Canister/Imp.hs +++ b/ic-stub/src/IC/Canister/Imp.hs @@ -2,6 +2,7 @@ {-# LANGUAGE LambdaCase #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE GADTs #-} {-# LANGUAGE FlexibleContexts #-} {-| @@ -12,10 +13,7 @@ module IC.Canister.Imp , ImpState , runESST , rawInitializeModule - , rawInitializeMethod - , rawUpdateMethod - , rawCallbackMethod - , rawQueryMethod + , rawInvoke , silently ) where @@ -33,6 +31,7 @@ import Data.Int import IC.Types import IC.Wasm.Winter import IC.Wasm.Imports +import qualified IC.Canister.Interface as CI -- Parameters are the data that come from the caller @@ -302,6 +301,16 @@ rawInitializeModule esref wasm_mod = do Left err -> return $ Trap err Right inst -> return $ Return inst +rawInvoke :: ImpState s -> CI.CanisterMethod r -> ST s (TrapOr r) +rawInvoke esref (CI.Initialize wasm_mod caller dat) = + rawInitializeMethod esref wasm_mod caller dat +rawInvoke esref (CI.Query name caller dat) = + rawQueryMethod esref name caller dat +rawInvoke esref (CI.Update name caller dat) = + rawUpdateMethod esref name caller dat +rawInvoke esref (CI.Callback cb caller res) = + rawCallbackMethod esref cb caller res + rawInitializeMethod :: ImpState s -> Module -> EntityId -> Blob -> ST s (TrapOr ()) rawInitializeMethod (esref, cid, inst) wasm_mod caller dat = do result <- runExceptT $ do diff --git a/ic-stub/src/IC/Canister/Interface.hs b/ic-stub/src/IC/Canister/Interface.hs new file mode 100644 index 00000000000..eb1d5d9dd93 --- /dev/null +++ b/ic-stub/src/IC/Canister/Interface.hs @@ -0,0 +1,19 @@ +{-# LANGUAGE GADTs #-} + +{-| +This module defines the various entry points provided by "IC.Canister.Imp" as a data type describing the arguments and results. + +The point of this abstraction is to to allow adding new entry points, or changing the arguments or result values, without changing the modules "IC.Canister.Pure" or "IC.Canister.Persisted", that sit between "IC.Canister.Imp" and "IC.Canister". +-} +module IC.Canister.Interface where + +import IC.Types +import IC.Wasm.Winter (Module) + +type UpdateResult = ([MethodCall], Maybe Response) + +data CanisterMethod r where + Initialize :: Module -> EntityId -> Blob -> CanisterMethod () + Query :: MethodName -> EntityId -> Blob -> CanisterMethod Response + Update :: MethodName -> EntityId -> Blob -> CanisterMethod UpdateResult + Callback :: Callback -> EntityId -> Response -> CanisterMethod UpdateResult diff --git a/ic-stub/src/IC/Canister/Persisted.hs b/ic-stub/src/IC/Canister/Persisted.hs index a6b31020cdf..96e1fb3f192 100644 --- a/ic-stub/src/IC/Canister/Persisted.hs +++ b/ic-stub/src/IC/Canister/Persisted.hs @@ -7,10 +7,8 @@ An implementation of canisters based on persistence, using "IC.Canister.Imp". It module IC.Canister.Persisted ( WasmState - , initializeMethod - , updateMethod - , callbackMethod - , queryMethod + , initialize + , invoke ) where @@ -19,49 +17,30 @@ import Control.Monad.ST import IC.Types import IC.Wasm.Winter (Module) import IC.Wasm.Winter.Persist +import qualified IC.Canister.Interface as CI import IC.Canister.Imp data WasmState = WasmState Module CanisterId PInstance -initializeMethod :: Module -> CanisterId -> EntityId -> Blob -> TrapOr WasmState -initializeMethod wasm_mod cid caller dat = runESST $ \esref -> +initialize :: Module -> CanisterId -> EntityId -> Blob -> TrapOr WasmState +initialize wasm_mod cid caller dat = runESST $ \esref -> rawInitializeModule esref wasm_mod >>= \case Trap err -> return $ Trap err Return inst -> do let rs = (esref, cid, inst) - rawInitializeMethod rs wasm_mod caller dat >>= \case + rawInvoke rs (CI.Initialize wasm_mod caller dat) >>= \case Trap err -> return $ Trap err Return () -> Return . WasmState wasm_mod cid <$> persistInstance inst -updateMethod :: - MethodName -> EntityId -> Blob -> - WasmState -> TrapOr (WasmState, [MethodCall], Maybe Response) -updateMethod m caller dat s = runESST $ \esref -> do +invoke :: WasmState -> CI.CanisterMethod r -> TrapOr (WasmState, r) +invoke s m = runESST $ \esref -> do rs <- replay esref s - tor <- rawUpdateMethod rs m caller dat + tor <- rawInvoke rs m case tor of Trap msg -> return $ Trap msg - Return (calls, r) -> do + Return r -> do state' <- persist s rs - return $ Return (state', calls, r) - -callbackMethod :: - Callback -> EntityId -> Response -> - WasmState -> TrapOr (WasmState, [MethodCall], Maybe Response) -callbackMethod cb caller r s = runESST $ \esref -> do - rs <- replay esref s - tor <- rawCallbackMethod rs cb caller r - case tor of - Trap msg -> return $ Trap msg - Return (calls, r) -> do - state' <- persist s rs - return $ Return (state', calls, r) - -queryMethod :: MethodName -> EntityId -> Blob -> WasmState -> TrapOr Response -queryMethod m caller dat s = runESST $ \esref -> do - rs <- replay esref s - rawQueryMethod rs m caller dat - + return $ Return (state', r) replay :: ESRef s -> WasmState -> ST s (ImpState s) replay esref (WasmState wasm_mod cid pinst) = do diff --git a/ic-stub/src/IC/Canister/Pure.hs b/ic-stub/src/IC/Canister/Pure.hs index 41144128866..5edc61f126a 100644 --- a/ic-stub/src/IC/Canister/Pure.hs +++ b/ic-stub/src/IC/Canister/Pure.hs @@ -1,6 +1,8 @@ {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE LambdaCase #-} +{-# LANGUAGE GADTs #-} +{-# LANGUAGE NamedFieldPuns #-} {-# OPTIONS_GHC -Wmissing-signatures #-} {-| @@ -12,10 +14,8 @@ We could do some hacking caching of state using stable names, so that as long as module IC.Canister.Pure ( WasmState - , initializeMethod - , updateMethod - , callbackMethod - , queryMethod + , initialize + , invoke ) where @@ -23,70 +23,50 @@ import Control.Monad.ST import IC.Types import IC.Wasm.Winter (Module) +import qualified IC.Canister.Interface as CI import IC.Canister.Imp -data WasmState - = WSInit Module CanisterId EntityId Blob - | WSUpdate MethodName EntityId Blob WasmState - | WSCallback Callback EntityId Response WasmState +data ACall = forall r. ACall (CI.CanisterMethod r) -initializeMethod :: Module -> CanisterId -> EntityId -> Blob -> TrapOr WasmState -initializeMethod wasm_mod cid caller dat = runESST $ \esref -> +data WasmState = WasmState + { ws_mod :: Module + , ws_self_id :: CanisterId + , ws_calls :: [ACall] -- in reverse order + } + +initialize :: Module -> CanisterId -> EntityId -> Blob -> TrapOr WasmState +initialize wasm_mod cid caller dat = runESST $ \esref -> rawInitializeModule esref wasm_mod >>= \case Trap err -> return $ Trap err Return inst -> do let rs = (esref, cid, inst) - result <- rawInitializeMethod rs wasm_mod caller dat - let state' = WSInit wasm_mod cid caller dat + let m = CI.Initialize wasm_mod caller dat + result <- rawInvoke rs m + let state' = WasmState wasm_mod cid [ACall m] case result of Trap err -> return $ Trap err Return _raw_state -> return $ Return state' -updateMethod :: - MethodName -> EntityId -> Blob -> - WasmState -> TrapOr (WasmState, [MethodCall], Maybe Response) -updateMethod m caller dat s = runESST $ \esref -> do - rs <- replay esref s - tor <- rawUpdateMethod rs m caller dat - let state' = WSUpdate m caller dat s - case tor of - Trap msg -> return $ Trap msg - Return (calls, r) -> return $ Return (state', calls, r) - -callbackMethod :: - Callback -> EntityId -> Response -> - WasmState -> TrapOr (WasmState, [MethodCall], Maybe Response) -callbackMethod cb caller r s = runESST $ \esref -> do +invoke :: WasmState -> CI.CanisterMethod r -> TrapOr (WasmState, r) +invoke s m = runESST $ \esref -> do rs <- replay esref s - tor <- rawCallbackMethod rs cb caller r - let state' = WSCallback cb caller r s + tor <- rawInvoke rs m + let state' = s { ws_calls = ACall m : ws_calls s } case tor of Trap msg -> return $ Trap msg - Return (calls, r) -> return $ Return (state', calls, r) - -queryMethod :: MethodName -> EntityId -> Blob -> WasmState -> TrapOr Response -queryMethod m caller dat s = runESST $ \esref -> do - rs <- replay esref s - rawQueryMethod rs m caller dat - + Return r -> return $ Return (state', r) replay :: forall s. ESRef s -> WasmState -> ST s (ImpState s) -replay esref s = silently esref $ go s +replay esref WasmState{ ws_mod, ws_self_id, ws_calls } = silently esref $ go ws_calls where trapToFail (Trap _err) = fail "replay failed" trapToFail (Return x) = return x - go :: WasmState -> ST s (ImpState s) - go (WSInit wasm_mod cid caller dat) = do - inst <- rawInitializeModule esref wasm_mod >>= trapToFail - let rs = (esref, cid, inst) - rawInitializeMethod rs wasm_mod caller dat >>= trapToFail - return rs - go (WSUpdate m caller dat s) = do - is <- go s - _ <- rawUpdateMethod is m caller dat >>= trapToFail - return is - go (WSCallback cb caller r s) = do - is <- go s - _ <- rawCallbackMethod is cb caller r >>= trapToFail + go :: [ACall] -> ST s (ImpState s) + go [] = do + inst <- rawInitializeModule esref ws_mod >>= trapToFail + return (esref, ws_self_id, inst) + go (ACall m:ms) = do + is <- go ms + _ <- rawInvoke is m >>= trapToFail return is diff --git a/ic-stub/src/IC/Stub.hs b/ic-stub/src/IC/Stub.hs index 3597991934e..17030715c1b 100644 --- a/ic-stub/src/IC/Stub.hs +++ b/ic-stub/src/IC/Stub.hs @@ -265,14 +265,14 @@ calleeOfCallID ctxt_id = do invokeEntry :: ICT m => CallId -> CanState -> EntryPoint -> - m (TrapOr (WasmState, [MethodCall], Maybe Response)) + m (TrapOr (WasmState, ([MethodCall], Maybe Response))) invokeEntry ctxt_id (CanState wasm_state can_mod) entry = do caller <- callerOfCallID ctxt_id case entry of Public method dat -> case M.lookup method (update_methods can_mod) of Just f -> return $ f caller dat wasm_state - Nothing -> return $ Return (wasm_state, [], Just $ Reject (RC_DESTINATION_INVALID, "update method does not exist: " ++ method)) + Nothing -> return $ Return (wasm_state, ([], Just $ Reject (RC_DESTINATION_INVALID, "update method does not exist: " ++ method))) Closure cb r -> return $ callbacks can_mod cb caller r wasm_state @@ -287,7 +287,7 @@ processMessage (CallMessage ctxt_id entry) = do invokeEntry ctxt_id cs entry >>= \case Trap msg -> rememberTrap ctxt_id msg - Return (new_state, calls, mb_response) -> do + Return (new_state, (calls, mb_response)) -> do setCanisterState callee new_state forM_ calls $ \call -> do new_ctxt_id <- newCallContext $ CallContext diff --git a/ic-stub/src/IC/Types.hs b/ic-stub/src/IC/Types.hs index 2005907070b..09970933117 100644 --- a/ic-stub/src/IC/Types.hs +++ b/ic-stub/src/IC/Types.hs @@ -1,4 +1,5 @@ {-# LANGUAGE TypeOperators #-} +{-# LANGUAGE DeriveFunctor #-} module IC.Types where import qualified Data.ByteString.Lazy as BS @@ -46,7 +47,7 @@ data Response = Reply Blob | Reject (RejectCode, String) -- Abstract canisters -data TrapOr a = Trap String | Return a +data TrapOr a = Trap String | Return a deriving Functor data WasmClosure = WasmClosure { closure_idx :: Int32 From 14793c258c50f24920ebd5726810c18b6b603966 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 19 Nov 2019 11:10:30 +0100 Subject: [PATCH 0645/1176] IDL-Motoko: Pass actor and func references as data (#883) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The status quo is: * Motoko assumes that we can pass around references to actors (public, anonymous, and non-closed) and functions (also public, anonymous and non-closed). * The IDL type system has service and function references, and assumes the transport supports a “sequence of platform-specific references” * The system has _no_ such concept, but obviously _public_ canister ids and id/method name pairs can be used to reference public canister and their public entry points. This eventually needs consolidation. But as a scaffolding measure, let’s at least support the lowest common denominator, i.e. passing around public actors and public functions. There are two points where we can implement that: * In the IDL (the “big” solution): We extend the IDL wire format so that a value of type `serivce {…}` is tagged (in `M`). One tag indicates “reference” and means there is a reference in `R` (as specified now). Another tag indicates “id” and means that in the _data_ section a public id follows. Nice side effect: This is future-proof with adding refernces, and we can add more tags later. * In the IDL-Motoko mapping (the “small” solution): We (temporarily) change `e(actor {…}) = blob` and do not use the IDL types that require system support for the reference sequence. This does not affect other IDL implementations. This PR proposes the “small” solution, as it seems the easiest first step. --- design/IDL-Motoko.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/design/IDL-Motoko.md b/design/IDL-Motoko.md index 140d53e63dd..f8f98bb996c 100644 --- a/design/IDL-Motoko.md +++ b/design/IDL-Motoko.md @@ -307,3 +307,15 @@ just suggestions. is treated by `moc` by reading `foo.did` as if the developer had run `didc path/to/foo.did -o path/to/foo.mo`. + +## Provisional Scaffolding adjustments + +At the time of writing, the underlying transport mechanism on the Internet Computer has no notion of a “sequence of references”, as expected by the IDL spec. This means that the IDL types `service …` and `func …` are not usable. + +To work around this and at least support passing references to _public_ canister and to _public_ canister methods, and until this mismatch is resolved, we implement `e` as follows: + +``` +e(actor { ;* }) = blob +e(shared -> ) = (blob, text) +``` +where the `blob` is an actor id, and the `text` a method name. From 3bd541de4d26c74c89d6d05005ff85d8109d6318 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 19 Nov 2019 10:24:55 +0000 Subject: [PATCH 0646/1176] Update src/mo_frontend/parser.mly Co-Authored-By: Andreas Rossberg --- src/mo_frontend/parser.mly | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mo_frontend/parser.mly b/src/mo_frontend/parser.mly index c60611deae6..361f0b906d8 100644 --- a/src/mo_frontend/parser.mly +++ b/src/mo_frontend/parser.mly @@ -446,7 +446,7 @@ exp_nondec(B) : | RETURN e=exp(ob) { RetE(e) @? at $sloc } | ASYNC e=exp(bl) - { AsyncE(scope_bind(),e,scope_typ()) @? at $sloc } + { AsyncE(scope_bind(), e, scope_typ()) @? at $sloc } | AWAIT e=exp(bl) { AwaitE(e) @? at $sloc } | ASSERT e=exp(bl) From f99561262ed425a729aac1c1dadeacf5bc317221 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 19 Nov 2019 10:38:17 +0000 Subject: [PATCH 0647/1176] Apply suggestions from code review Co-Authored-By: Andreas Rossberg --- src/ir_def/check_ir.ml | 2 +- src/mo_frontend/parser.mly | 2 +- src/mo_frontend/typing.ml | 14 +++++++------- src/mo_interpreter/interpret.ml | 2 +- src/mo_types/type.ml | 6 +++--- src/mo_types/type.mli | 4 ++-- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index beb5d86d332..631703caaf3 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -563,7 +563,7 @@ let rec check_exp env (exp:Ir.exp) : unit = check_exp env' exp1; let t1' = T.open_ [t0] (T.close [c] t1) in t1' <: T.Any; (* vacuous *) - T.Async (t0,t1') <: t + T.Async (t0, t1') <: t | AwaitE exp1 -> check env.flavor.has_await "await in non-await flavor"; check (env.async <> None) "misplaced await"; diff --git a/src/mo_frontend/parser.mly b/src/mo_frontend/parser.mly index 361f0b906d8..20e58be75fe 100644 --- a/src/mo_frontend/parser.mly +++ b/src/mo_frontend/parser.mly @@ -632,7 +632,7 @@ dec_nonvar : | (false, e) -> e (* body declared as EQ e *) | (true, e) -> (* body declared as immediate block *) match t with - | Some {it = AsyncT _; _} -> AsyncE(scope_bind(),e,scope_typ()) @? e.at + | Some {it = AsyncT _; _} -> AsyncE(scope_bind(), e, scope_typ()) @? e.at | _ -> e in let named, x = xf "func" $sloc in diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 49458689c0c..926994f6877 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -215,7 +215,7 @@ let as_domT t = let as_codomT sort t = match sort, t.Source.it with - | T.Shared _, AsyncT (t1,t2) -> T.Promises t1 , as_domT t2 + | T.Shared _, AsyncT (t1, t2) -> T.Promises t1 , as_domT t2 | _ -> T.Returns, as_domT t let check_shared_return env at sort c ts = @@ -296,7 +296,7 @@ and check_typ' env typ : T.typ = if not env.pre && not (T.shared t) then error_shared env t typ.at "async has non-shared content type\n %s" (T.string_of_typ_expand t); - T.Async (t0,t) + T.Async (t0, t) | ObjT (sort, fields) -> check_ids env "object" "field" (List.map (fun (field : typ_field) -> field.it.id) fields); @@ -742,7 +742,7 @@ and infer_exp'' env exp : T.typ = end; let ts1 = match pat.it with TupP _ -> T.seq_of_tup t1 | _ -> [t1] in let tbs = List.map2 (fun c t -> {T.var = Con.name c; bound = T.close cs t}) cs ts in - T.Func (sort.it, T.map_control (T.close cs) c, tbs, List.map (T.close cs) ts1, List.map (T.close cs) ts2) + T.Func (sort.it, T.map_control (T.close cs) c, tbs, List.map (T.close cs) ts1, List.map (T.close cs) ts2) | CallE (exp1, insts, exp2) -> let t1 = infer_exp_promote env exp1 in let sort, tbs, t_arg, t_ret = @@ -905,7 +905,7 @@ and infer_exp'' env exp : T.typ = error env exp.at "misplaced throw"; if not env.pre then check_exp env T.throw exp1; T.Non - | AsyncE (tb, exp1, typ0) -> + | AsyncE (typbind, exp1, typ1) -> if not in_shared then error_in [Flags.ICMode] env exp.at "unsupported async block"; let t0 = check_typ env typ0 in @@ -917,8 +917,8 @@ and infer_exp'' env exp : T.typ = if not (T.shared t1) then error_shared env t1 exp1.at "async type has non-shared content type\n %s" (T.string_of_typ_expand t1); - T.Async (t0,t1) - | AwaitE exp1 -> + T.Async (t0, t1) + | AwaitE exp1 -> if env.async = None then error env exp.at "misplaced await"; let t1 = infer_exp_promote {env with in_await = true} exp1 in @@ -929,7 +929,7 @@ and infer_exp'' env exp : T.typ = | _ -> error_in [Flags.ICMode] env exp1.at "argument to await must be a call expression"); (try let (t2,t3) = T.as_async_sub t1 in - let t0 = T.Con(Lib.Option.value env.async, []) in + let t0 = T.Con (Lib.Option.value env.async, []) in if not (T.eq t0 t2) then error env exp.at "ill-scoped await"; t3 diff --git a/src/mo_interpreter/interpret.ml b/src/mo_interpreter/interpret.ml index a6ce385e0a3..b0cffda44f3 100644 --- a/src/mo_interpreter/interpret.ml +++ b/src/mo_interpreter/interpret.ml @@ -556,7 +556,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = interpret_exp env exp1 (Lib.Option.value env.rets) | ThrowE exp1 -> interpret_exp env exp1 (Lib.Option.value env.throws) - | AsyncE (_ ,exp1, _) -> + | AsyncE (_, exp1, _) -> async env exp.at (fun k' r -> diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index 0aa601a472c..a1793c9f497 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -46,7 +46,7 @@ and typ = | Array of typ (* array *) | Opt of typ (* option *) | Tup of typ list (* tuple *) - | Func of func_sort * (typ control) * bind list * typ list * typ list (* function *) + | Func of func_sort * typ control * bind list * typ list * typ list (* function *) | Async of typ * typ (* future *) | Mut of typ (* mutable type *) | Any (* top *) @@ -147,7 +147,7 @@ let prim = function let seq = function [t] -> t | ts -> Tup ts let codom c ts = match c with - | Promises t -> Async (t, (seq ts)) + | Promises t -> Async (t, seq ts) | Returns -> seq ts | Replies -> Tup [] @@ -730,7 +730,7 @@ let rec rel_typ rel eq t1 t2 = rel_list rel_typ rel eq (List.map (open_ ts) t12) (List.map (open_ ts) t22) | None -> false ) - | Async (t11, t12), Async (t21,t22) -> + | Async (t11, t12), Async (t21, t22) -> eq_typ rel eq t11 t21 && rel_typ rel eq t12 t22 | Mut t1', Mut t2' -> diff --git a/src/mo_types/type.mli b/src/mo_types/type.mli index 1f2497ba19b..c4f3f642a98 100644 --- a/src/mo_types/type.mli +++ b/src/mo_types/type.mli @@ -41,7 +41,7 @@ and typ = | Array of typ (* array *) | Opt of typ (* option *) | Tup of typ list (* tuple *) - | Func of func_sort * (typ control) * bind list * typ list * typ list (* function *) + | Func of func_sort * typ control * bind list * typ list * typ list (* function *) | Async of typ * typ (* future *) | Mut of typ (* mutable type *) | Any (* top *) @@ -107,7 +107,7 @@ val as_opt : typ -> typ val as_tup : typ -> typ list val as_unit : typ -> unit val as_pair : typ -> typ * typ -val as_func : typ -> func_sort * (typ control) * bind list * typ list * typ list +val as_func : typ -> func_sort * typ control * bind list * typ list * typ list val as_async : typ -> typ * typ val as_mut : typ -> typ val as_immut : typ -> typ From fb20b1e747d27433cea618880c93b1809393ffdf Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 19 Nov 2019 10:44:50 +0000 Subject: [PATCH 0648/1176] fix broken suggestions --- src/mo_frontend/typing.ml | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 926994f6877..ebd01efe6df 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -905,19 +905,19 @@ and infer_exp'' env exp : T.typ = error env exp.at "misplaced throw"; if not env.pre then check_exp env T.throw exp1; T.Non - | AsyncE (typbind, exp1, typ1) -> + | AsyncE (typ_bind, exp1, typ1) -> if not in_shared then error_in [Flags.ICMode] env exp.at "unsupported async block"; - let t0 = check_typ env typ0 in - let c, tb, ce, cs = check_typ_bind env tb in + let t1 = check_typ env typ1 in + let c, tb, ce, cs = check_typ_bind env typ_bind in let env' = {(adjoin_typs env ce cs) with labs = T.Env.empty; rets = Some T.Pre; async = Some c} in let t = infer_exp env' exp1 in - let t1 = T.open_ [t0] (T.close [c] t) in - if not (T.shared t1) then - error_shared env t1 exp1.at "async type has non-shared content type\n %s" - (T.string_of_typ_expand t1); - T.Async (t0, t1) + let t' = T.open_ [t1] (T.close [c] t) in + if not (T.shared t') then + error_shared env t' exp1.at "async type has non-shared content type\n %s" + (T.string_of_typ_expand t'); + T.Async (t1, t') | AwaitE exp1 -> if env.async = None then error env exp.at "misplaced await"; @@ -993,14 +993,14 @@ and check_exp' env0 t exp : T.typ = (T.string_of_typ_expand (T.Array t')); List.iter (check_exp env (T.as_immut t')) exps; t - | AsyncE (tb, exp1, typ0), T.Async (t0',t') -> + | AsyncE (tb, exp1, typ1), T.Async (t1',t') -> if not in_shared then error_in [Flags.ICMode] env exp.at "freestanding async expression not yet supported"; - let t0 = check_typ env typ0 in - if not (T.eq t0 t0') then + let t1 = check_typ env typ1 in + if not (T.eq t1 t1') then error env exp.at "async at scope\n %s\ncannot produce expected scope\n %s" - (T.string_of_typ_expand t0) - (T.string_of_typ_expand t0'); + (T.string_of_typ_expand t1) + (T.string_of_typ_expand t1'); let c, tb, ce, cs = check_typ_bind env tb in let env' = {(adjoin_typs env ce cs) with labs = T.Env.empty; rets = Some t'; async = Some c} in From e2ecf3578ab46230bcf85bec3c583e8b3323981b Mon Sep 17 00:00:00 2001 From: Enzo Haussecker Date: Tue, 19 Nov 2019 03:00:05 -0800 Subject: [PATCH 0649/1176] Move list alias into module --- stdlib/text.mo | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/text.mo b/stdlib/text.mo index c6a113f1e2c..734b81c86be 100644 --- a/stdlib/text.mo +++ b/stdlib/text.mo @@ -1,10 +1,10 @@ import List "list.mo"; import Option "option.mo"; -type List = List.List; - module { + type List = List.List; + public func append(x : Text, y : Text) : Text { x # y; }; From 98185c8674eaa3c8174104ea80a3dccce8d6c09a Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 19 Nov 2019 11:09:17 +0000 Subject: [PATCH 0650/1176] Apply suggestions from code review Co-Authored-By: Andreas Rossberg --- src/mo_frontend/parser.mly | 2 +- src/mo_frontend/typing.ml | 2 +- src/mo_types/type.ml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mo_frontend/parser.mly b/src/mo_frontend/parser.mly index 20e58be75fe..daac415c232 100644 --- a/src/mo_frontend/parser.mly +++ b/src/mo_frontend/parser.mly @@ -251,7 +251,7 @@ typ_pre : | PRIM s=TEXT { PrimT(s) @! at $sloc } | ASYNC t=typ_pre - { AsyncT(scope_typ(),t) @! at $sloc } + { AsyncT(scope_typ(), t) @! at $sloc } | s=obj_sort tfs=typ_obj { let tfs' = if s.it = Type.Actor then List.map share_typfield tfs else tfs diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index ebd01efe6df..3302726309a 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -928,7 +928,7 @@ and infer_exp'' env exp : T.typ = error_in [Flags.ICMode] env f.at "expecting call to shared async function in await"; | _ -> error_in [Flags.ICMode] env exp1.at "argument to await must be a call expression"); (try - let (t2,t3) = T.as_async_sub t1 in + let (t2, t3) = T.as_async_sub t1 in let t0 = T.Con (Lib.Option.value env.async, []) in if not (T.eq t0 t2) then error env exp.at "ill-scoped await"; diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index a1793c9f497..5c55e54b521 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -171,7 +171,7 @@ let rec shift i n t = let i' = i + List.length tbs in Func (s, c, List.map (shift_bind i' n) tbs, List.map (shift i' n) ts1, List.map (shift i' n) ts2) | Opt t -> Opt (shift i n t) - | Async (t1,t2) -> Async (shift i n t1, shift i n t2) + | Async (t1, t2) -> Async (shift i n t1, shift i n t2) | Obj (s, fs) -> Obj (s, List.map (shift_field n i) fs) | Variant fs -> Variant (List.map (shift_field n i) fs) | Mut t -> Mut (shift i n t) From 563127321fd8d0aeec0180d9d347276c5ca80d46 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 19 Nov 2019 11:12:31 +0000 Subject: [PATCH 0651/1176] Apply suggestions from code review --- src/mo_types/type.ml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index 5c55e54b521..36f57cc646d 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -1212,7 +1212,6 @@ and string_of_control_cod c vs ts = let cod = string_of_cod vs ts in match c with | Returns -> cod - | Promises t -> sprintf "async<%s> %s" (string_of_typ' vs t) cod | Replies -> sprintf "replies %s" cod From 82ae0adf680687baddb7c1851f726f24d8687b66 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 19 Nov 2019 12:16:00 +0100 Subject: [PATCH 0652/1176] Apply suggestions from code review Co-Authored-By: Gabor Greif --- ic-stub/.gitignore | 2 +- ic-stub/README.md | 2 +- ic-stub/src/IC/Canister.hs | 2 +- ic-stub/src/IC/Canister/Imp.hs | 2 +- ic-stub/src/IC/Stub.hs | 6 +++--- ic-stub/src/IC/Wasm/Imports.hs | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ic-stub/.gitignore b/ic-stub/.gitignore index 4c9e245b5d8..fdf15c75487 100644 --- a/ic-stub/.gitignore +++ b/ic-stub/.gitignore @@ -18,6 +18,6 @@ cabal.sandbox.config *.eventlog .stack-work/ cabal.project.local -cabal.project.local~ +*~ .HTF/ .ghc.environment.* diff --git a/ic-stub/README.md b/ic-stub/README.md index 17ab89f1889..c970cd85885 100644 --- a/ic-stub/README.md +++ b/ic-stub/README.md @@ -13,7 +13,7 @@ execution of a single canister. Status ------ -This is neither complete nor authorative. Since this is primarily meant for +This is neither complete nor authoritative. Since this is primarily meant for testing the output of Motoko, code paths not exercised by Motoko may not be present; in particular, error handling and input validation is incomplete. diff --git a/ic-stub/src/IC/Canister.hs b/ic-stub/src/IC/Canister.hs index 8b9d116b5aa..bded2eb11f5 100644 --- a/ic-stub/src/IC/Canister.hs +++ b/ic-stub/src/IC/Canister.hs @@ -4,7 +4,7 @@ A “pure” implementation of canisters, using "IC.Canister.Imp", but just replaying when needed. Note that this is quadratic in the number of update calls, so do not run such canisters for long. -We could do some hacking caching of state using stable names, so that as long as no trap occurs, 'replay' is fast. +We could do some hacking caching of state using stable names, so that, as long as no trap occurs, 'replay' is fast. -} module IC.Canister diff --git a/ic-stub/src/IC/Canister/Imp.hs b/ic-stub/src/IC/Canister/Imp.hs index 4a35f9f429f..53343cbcd27 100644 --- a/ic-stub/src/IC/Canister/Imp.hs +++ b/ic-stub/src/IC/Canister/Imp.hs @@ -219,7 +219,7 @@ systemAPI esref = assert_not_responded = gets response >>= \case Nothing -> return () - Just _ -> throwError "This call has already be responded to" + Just _ -> throwError "This call has already been responded to" msg_reply_data_append :: (Int32, Int32) -> HostM s () msg_reply_data_append (src, size) = do diff --git a/ic-stub/src/IC/Stub.hs b/ic-stub/src/IC/Stub.hs index 17030715c1b..c939d56a651 100644 --- a/ic-stub/src/IC/Stub.hs +++ b/ic-stub/src/IC/Stub.hs @@ -146,8 +146,8 @@ readRequest (QueryRequest user_id method arg) = Return (Reply res) -> return $ Completed (CompleteArg res) Return (Reject (rc,rm)) -> return $ Rejected (rc, rm) -nextRecieved :: ICT m => m (Maybe AsyncRequest) -nextRecieved = gets $ \ic -> listToMaybe +nextReceived :: ICT m => m (Maybe AsyncRequest) +nextReceived = gets $ \ic -> listToMaybe [ r | (r, Received) <- M.toList (requests ic) ] nextStarved :: ICT m => m (Maybe CallId) @@ -324,7 +324,7 @@ starveContext ctxt_id = do runToCompletion :: ICT m => m () runToCompletion = - nextRecieved >>= \case + nextReceived >>= \case Just r -> processRequest r >> runToCompletion Nothing -> nextMessage >>= \case Just m -> processMessage m >> runToCompletion diff --git a/ic-stub/src/IC/Wasm/Imports.hs b/ic-stub/src/IC/Wasm/Imports.hs index 714053f1527..87b3df952fa 100644 --- a/ic-stub/src/IC/Wasm/Imports.hs +++ b/ic-stub/src/IC/Wasm/Imports.hs @@ -46,7 +46,7 @@ instance WasmArgs () where fromValues xs = argError 0 xs toValues () = [] --- The formatting is a bit odd, but allows it easier to create new instances by copy and paste and adding lines +-- The formatting is a bit odd, but it allows to create new instances easily by copy and paste and adding lines instance ( WasmArg a1 , WasmArg a2 From cbe634ed7b44b25bf041e8d956e036a4e4f57da7 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 19 Nov 2019 11:17:10 +0000 Subject: [PATCH 0653/1176] Claudio/oneway awaits (#773) * support await/try-catch in oneway functions * adapt IR checker; add test * indentation, preempting rossberg * updates drun test output. Note that some calls previously returning payload Empty and now return () were wrong (I think) * update test output * rationalize contextual errors * special case ignore async expressions in oneway functions; add test * cleanup * reorg typing.ml * desugar to ignore e to let _ = e : Any * remove @ignore from prelude --- src/codegen/compile.ml | 5 ++- src/ir_def/check_ir.ml | 3 +- src/ir_passes/async.ml | 42 +++++++++++++++--- src/ir_passes/await.ml | 1 - src/mo_frontend/lexer.mll | 1 + src/mo_frontend/parser.mly | 4 +- src/mo_frontend/typing.ml | 59 +++++++++++++++++-------- src/prelude/prelude.ml | 2 - test/run-drun/ok/counter.drun-run.ok | 8 ++-- test/run-drun/ok/oneway.drun-run.ok | 11 +++++ test/run-drun/ok/oom.drun-run.ok | 4 +- test/run-drun/ok/query.drun-run.ok | 12 ++--- test/run-drun/ok/reversi.drun-run.ok | 2 +- test/run-drun/ok/test_oneway.run-ir.ok | 1 + test/run-drun/ok/test_oneway.run-low.ok | 1 + test/run-drun/ok/test_oneway.run.ok | 1 + test/run-drun/oneway.mo | 59 +++++++++++++++++++++++++ test/run-drun/test_oneway.mo | 16 +++++++ 18 files changed, 189 insertions(+), 43 deletions(-) create mode 100644 test/run-drun/ok/oneway.drun-run.ok create mode 100644 test/run-drun/ok/test_oneway.run-ir.ok create mode 100644 test/run-drun/ok/test_oneway.run-low.ok create mode 100644 test/run-drun/ok/test_oneway.run.ok create mode 100644 test/run-drun/oneway.mo create mode 100644 test/run-drun/test_oneway.mo diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index c0fb8f7d98e..b2308eff70f 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -5039,7 +5039,10 @@ module FuncDec = struct let ae0 = VarEnv.mk_fun_ae outer_ae in Func.of_body outer_env ["api_nonce", I64Type] [] (fun env -> G.with_region at ( G.i (LocalGet (nr 0l)) ^^ Dfinity.set_api_nonce env ^^ - + (* reply early for a oneway *) + (if control = Type.Returns + then Tuple.compile_unit ^^ Serialization.serialize env [] + else G.nop) ^^ (* Deserialize argument and add params to the environment *) let arg_names = List.map (fun a -> a.it) args in let arg_tys = List.map (fun a -> a.note) args in diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 5ceca78703a..17b283905d1 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -603,8 +603,9 @@ let rec check_exp env (exp:Ir.exp) : unit = "shared function with async type has non-async body"; if T.is_shared_sort sort then List.iter (check_concrete env exp.at) ret_tys; let codom = T.codom control ret_tys in + let is_oneway = T.is_shared_sort sort && control = T.Returns in let env'' = - {env' with labs = T.Env.empty; rets = Some codom; async = false} in + {env' with labs = T.Env.empty; rets = Some codom; async = is_oneway} in check_exp (adjoin_vals env'' ve) exp; check_sub env' exp.at (typ exp) codom; (* Now construct the function type and compare with the annotation *) diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index 6759307f210..bea00ebce5d 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -176,7 +176,7 @@ let transform mode env prog = fragments, then we would simply start with an empty con_renaming and the prelude. *) in - + let rec t_typ (t:T.typ) = match t with | T.Prim _ @@ -345,10 +345,8 @@ let transform mode env prog = FuncE (x, s, c, t_typ_binds typbinds, t_args args, List.map t_typ ret_tys, t_exp exp) | T.Shared s' -> begin - match c with - | Returns -> - FuncE (x, s, c, t_typ_binds typbinds, t_args args, List.map t_typ ret_tys, t_exp exp) - | Promises -> + match c, exp with + | Promises, exp -> let ret_tys = List.map t_typ ret_tys in let args' = t_args args in let typbinds' = t_typ_binds typbinds in @@ -368,7 +366,39 @@ let transform mode env prog = let r = [e] -->* (ic_rejectE (errorMessageE e)) in let exp' = (t_exp cps) -*- tupE [k;r] in FuncE (x, T.Shared s', Replies, typbinds', args', ret_tys, exp') - | Replies -> assert false + (* oneway with an `ignore(async _)` body + TODO: remove this special casing once async fully supported + *) + | Returns, + { it = BlockE ( + [{ it = LetD ( + { it = WildP; _}, + ({ it = PrimE (CPSAsync, _); _} as exp)); _ }], + { it = TupE []; _}); + _ } -> + let ret_tys = List.map t_typ ret_tys in + let args' = t_args args in + let typbinds' = t_typ_binds typbinds in + let cps = match exp.it with + | PrimE (CPSAsync, [cps]) -> cps + | _ -> assert false in + let t1, contT = match typ cps with + | Func(_,_, + [], + [Func(_, _, [], ts1, []) as contT; _], + []) -> + (t_typ (T.seq ts1),t_typ contT) + | t -> assert false in + let v = fresh_var "v" t1 in + let k = v --> tupE [] in (* discard return *) + let e = fresh_var "e" T.catch in + let r = [e] -->* tupE [] in (* discard error *) + let exp' = (t_exp cps) -*- tupE [k;r] in + FuncE (x, T.Shared s', Returns, typbinds', args', ret_tys, exp') + (* sequential oneway *) + | Returns, _ -> + FuncE (x, s, c, t_typ_binds typbinds, t_args args, List.map t_typ ret_tys, t_exp exp) + | Replies,_ -> assert false end end | ActorE (id, ds, fs, typ) -> diff --git a/src/ir_passes/await.ml b/src/ir_passes/await.ml index b26ce5b3000..c9b8d89a475 100644 --- a/src/ir_passes/await.ml +++ b/src/ir_passes/await.ml @@ -125,7 +125,6 @@ and t_exp' context exp' = LabelEnv.add Return (Cont (ContVar k_ret)) (LabelEnv.add Throw (Cont (ContVar k_fail)) LabelEnv.empty) in - (* TODO: bind k_fail *) (asyncE (typ exp1) ([k_ret; k_fail] -->* c_exp context' exp1 (ContVar k_ret))).it | TryE _ diff --git a/src/mo_frontend/lexer.mll b/src/mo_frontend/lexer.mll index 675268d8984..7c94f952e8c 100644 --- a/src/mo_frontend/lexer.mll +++ b/src/mo_frontend/lexer.mll @@ -205,6 +205,7 @@ rule token mode = parse | "for" { FOR } | "func" { FUNC } | "if" { IF } + | "ignore" { IGNORE } | "in" { IN } | "import" { IMPORT } | "module" { MODULE } diff --git a/src/mo_frontend/parser.mly b/src/mo_frontend/parser.mly index 9a4faf37c65..13850a20192 100644 --- a/src/mo_frontend/parser.mly +++ b/src/mo_frontend/parser.mly @@ -96,7 +96,7 @@ let share_expfield (ef : exp_field) = %token LET VAR %token LPAR RPAR LBRACKET RBRACKET LCURLY RCURLY %token AWAIT ASYNC BREAK CASE CATCH CONTINUE LABEL DEBUG -%token IF IN ELSE SWITCH LOOP WHILE FOR RETURN TRY THROW +%token IF IGNORE IN ELSE SWITCH LOOP WHILE FOR RETURN TRY THROW %token ARROW ASSIGN %token FUNC TYPE OBJECT ACTOR CLASS PUBLIC PRIVATE SHARED QUERY %token SEMICOLON SEMICOLON_EOL COMMA COLON SUB DOT QUEST @@ -639,6 +639,8 @@ dec_nonvar : let efs' = if s.it = Type.Actor then List.map share_expfield efs else efs in ClassD(xf "class" $sloc, tps, p, t, s, x, efs') @? at $sloc } + | IGNORE e=exp(ob) + { LetD(WildP @! no_region, AnnotE (e, PrimT "Any" @! no_region) @? no_region) @? at $sloc } dec : | d=dec_var diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 5d59b005854..64fa94e2858 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -25,9 +25,8 @@ type env = rets : ret_env; async : bool; in_actor : bool; - in_await : bool; - in_shared : bool; in_prog : bool; + context : exp' list; pre : bool; msgs : Diag.msg_store; } @@ -41,10 +40,9 @@ let env_of_scope msgs scope = labs = T.Env.empty; rets = None; async = false; - in_await = false; - in_shared = false; in_actor = false; in_prog = true; + context = []; pre = false; msgs; } @@ -126,6 +124,35 @@ let disjoint_union env at fmt env1 env2 = with T.Env.Clash k -> error env at fmt k +(* Syntactic predicates for context dependent restrictions *) + +let in_await env = + match env.context with + | _ :: AwaitE _ :: _ -> true + | _ -> false + +let in_shared_async env = + match env.context with + | _ :: FuncE (_, {it = T.Shared _; _}, _, _, typ_opt, _) :: _ -> + (match typ_opt with + | Some {it = AsyncT _; _} -> true + | _ -> false) + | _ -> false + +let in_oneway_ignore env = + match env.context with + | _ :: + AnnotE _ :: + BlockE [ {it = LetD ({ it = WildP;_}, _); _} ] :: + FuncE (_, {it = T.Shared _; _} , _, _, typ_opt, _) :: + _ -> + (match typ_opt with + | Some { it = TupT []; _} + | None -> true + | _ -> false) + | _ -> false + + (* Types *) let check_ids env kind member ids = Lib.List.iter_pairs @@ -547,9 +574,7 @@ and infer_exp' f env exp : T.typ = and infer_exp'' env exp : T.typ = let in_prog = env.in_prog in let in_actor = env.in_actor in - let in_await = env.in_await in - let in_shared = env.in_shared in - let env = {env with in_actor = false; in_await = false; in_prog = false; in_shared = false} in + let env = {env with in_actor = false; in_prog = false; context = exp.it::env.context} in match exp.it with | PrimE _ -> error env exp.at "cannot infer type of primitive" @@ -707,8 +732,8 @@ and infer_exp'' env exp : T.typ = { env' with labs = T.Env.empty; rets = Some codom; - async = false; - in_shared = T.is_shared_sort sort.it} in + async = false } + in check_exp (adjoin_vals env'' ve) codom exp; if Type.is_shared_sort sort.it then begin if not (T.shared t1) then @@ -750,7 +775,7 @@ and infer_exp'' env exp : T.typ = if not env.pre then begin check_exp env t_arg exp2; if Type.is_shared_sort sort then begin - if T.is_async t_ret && not in_await then + if T.is_async t_ret && not (in_await env) then error_in [Flags.ICMode] env exp2.at "shared, async function must be called within an await expression"; error_in [Flags.ICMode] env exp1.at "calling a shared function not yet supported"; @@ -898,7 +923,7 @@ and infer_exp'' env exp : T.typ = if not env.pre then check_exp env T.throw exp1; T.Non | AsyncE exp1 -> - if not in_shared then + if not (in_shared_async env || in_oneway_ignore env) then error_in [Flags.ICMode] env exp.at "unsupported async block"; let env' = {env with labs = T.Env.empty; rets = Some T.Pre; async = true} in @@ -910,7 +935,7 @@ and infer_exp'' env exp : T.typ = | AwaitE (exp1) -> if not env.async then error env exp.at "misplaced await"; - let t1 = infer_exp_promote {env with in_await = true} exp1 in + let t1 = infer_exp_promote env exp1 in (match exp1.it with | CallE (f, _, _) -> if not env.pre && (Call_conv.call_conv_of_typ f.note.note_typ).Call_conv.control = T.Returns then @@ -947,8 +972,7 @@ and check_exp env t exp = exp.note <- {note_typ = t'; note_eff = e} and check_exp' env0 t exp : T.typ = - let in_shared = env0.in_shared in - let env = {env0 with in_await = false; in_shared = false; in_prog = false} in + let env = {env0 with in_prog = false; context = exp.it :: env0.context } in match exp.it, t with | PrimE s, T.Func _ -> t @@ -979,7 +1003,7 @@ and check_exp' env0 t exp : T.typ = List.iter (check_exp env (T.as_immut t')) exps; t | AsyncE exp1, T.Async t' -> - if not in_shared then + if not (in_shared_async env || in_oneway_ignore env) then error_in [Flags.ICMode] env exp.at "freestanding async expression not yet supported"; let env' = {env with labs = T.Env.empty; rets = Some t'; async = true} in check_exp env' t' exp1; @@ -1038,9 +1062,8 @@ and check_exp' env0 t exp : T.typ = { env with labs = T.Env.empty; rets = Some t2; - async = false; - in_shared = T.is_shared_sort s'.it; - } in + async = false } + in check_exp (adjoin_vals env' ve) t2 exp; t | _ -> diff --git a/src/prelude/prelude.ml b/src/prelude/prelude.ml index 18d85330978..dd9337e2635 100644 --- a/src/prelude/prelude.ml +++ b/src/prelude/prelude.ml @@ -27,8 +27,6 @@ type Iter = {next : () -> ?T_}; func abs(x : Int) : Nat { (prim "abs" : Int -> Nat) x }; -func ignore(_ : Any) {}; - class range(x : Nat, y : Nat) { var i = x; public func next() : ?Nat { if (i > y) null else {let j = i; i += 1; ?j} }; diff --git a/test/run-drun/ok/counter.drun-run.ok b/test/run-drun/ok/counter.drun-run.ok index 7d9bd915a92..c389f84ac9c 100644 --- a/test/run-drun/ok/counter.drun-run.ok +++ b/test/run-drun/ok/counter.drun-run.ok @@ -2,17 +2,17 @@ ingress(0) System debug.print: 2 debug.print: -ingress(1) Completed: Canister: Empty +ingress(1) Completed: Canister: Payload: 0x4449444c0000 debug.print: 3 debug.print: -ingress(2) Completed: Canister: Empty +ingress(2) Completed: Canister: Payload: 0x4449444c0000 debug.print: 4 debug.print: -ingress(3) Completed: Canister: Empty +ingress(3) Completed: Canister: Payload: 0x4449444c0000 debug.print: 4 debug.print: -ingress(4) Completed: Canister: Empty +ingress(4) Completed: Canister: Payload: 0x4449444c0000 ingress(5) Completed: Canister: Payload: 0x4449444c00017d04 diff --git a/test/run-drun/ok/oneway.drun-run.ok b/test/run-drun/ok/oneway.drun-run.ok new file mode 100644 index 00000000000..8ce9c90d9f3 --- /dev/null +++ b/test/run-drun/ok/oneway.drun-run.ok @@ -0,0 +1,11 @@ +ingress(0) System +debug.print: 1 +debug.print: 2 +ingress(1) Completed: Canister: Payload: 0x4449444c0000 +debug.print: 3 +debug.print: 4 +ingress(2) Completed: Canister: Payload: 0x4449444c0000 +debug.print: 5 +ingress(3) Completed: Canister: Payload: 0x4449444c0000 +debug.print: 6 +ingress(4) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/oom.drun-run.ok b/test/run-drun/ok/oom.drun-run.ok index d1d6ed87e8b..57687c597aa 100644 --- a/test/run-drun/ok/oom.drun-run.ok +++ b/test/run-drun/ok/oom.drun-run.ok @@ -1,3 +1,3 @@ ingress(0) System -ingress(1) Completed: Canister: Empty -ingress(2) Completed: Canister: Empty +ingress(1) Completed: Canister: Payload: 0x4449444c0000 +ingress(2) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/query.drun-run.ok b/test/run-drun/ok/query.drun-run.ok index 5137d9c8055..2130635fc01 100644 --- a/test/run-drun/ok/query.drun-run.ok +++ b/test/run-drun/ok/query.drun-run.ok @@ -2,19 +2,19 @@ ingress(0) System debug.print: 2 debug.print: -ingress(1) Completed: Canister: Empty +ingress(1) Completed: Canister: Payload: 0x4449444c0000 debug.print: 3 debug.print: -ingress(2) Completed: Canister: Empty +ingress(2) Completed: Canister: Payload: 0x4449444c0000 debug.print: 4 debug.print: -ingress(3) Completed: Canister: Empty +ingress(3) Completed: Canister: Payload: 0x4449444c0000 debug.print: 4 debug.print: -ingress(4) Completed: Canister: Empty +ingress(4) Completed: Canister: Payload: 0x4449444c0000 ingress(5) Completed: Canister: Payload: 0x4449444c00017d04 debug.print: 5 debug.print: @@ -23,7 +23,7 @@ Ok: Payload: 0x4449444c00017d04 debug.print: 4 debug.print: -ingress(6) Completed: Canister: Empty +ingress(6) Completed: Canister: Payload: 0x4449444c0000 debug.print: 5 debug.print: @@ -31,4 +31,4 @@ Ok: Payload: 0x4449444c00017d04 debug.print: 4 debug.print: -ingress(7) Completed: Canister: Empty +ingress(7) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/reversi.drun-run.ok b/test/run-drun/ok/reversi.drun-run.ok index 0c49bd69fb7..fa534586835 100644 --- a/test/run-drun/ok/reversi.drun-run.ok +++ b/test/run-drun/ok/reversi.drun-run.ok @@ -1,5 +1,5 @@ ingress(0) System -ingress(1) Completed: Canister: Empty +ingress(1) Completed: Canister: Payload: 0x4449444c0000 ingress(2) Completed: Canister: Payload: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e4f2a2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a ingress(3) Completed: Canister: Payload: 0x4449444c000171024f4b ingress(4) Completed: Canister: Payload: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e4f2e2e2e0a2e2e2e4f4f2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a diff --git a/test/run-drun/ok/test_oneway.run-ir.ok b/test/run-drun/ok/test_oneway.run-ir.ok new file mode 100644 index 00000000000..550167191f0 --- /dev/null +++ b/test/run-drun/ok/test_oneway.run-ir.ok @@ -0,0 +1 @@ +ABCDE123456 diff --git a/test/run-drun/ok/test_oneway.run-low.ok b/test/run-drun/ok/test_oneway.run-low.ok new file mode 100644 index 00000000000..550167191f0 --- /dev/null +++ b/test/run-drun/ok/test_oneway.run-low.ok @@ -0,0 +1 @@ +ABCDE123456 diff --git a/test/run-drun/ok/test_oneway.run.ok b/test/run-drun/ok/test_oneway.run.ok new file mode 100644 index 00000000000..550167191f0 --- /dev/null +++ b/test/run-drun/ok/test_oneway.run.ok @@ -0,0 +1 @@ +ABCDE123456 diff --git a/test/run-drun/oneway.mo b/test/run-drun/oneway.mo new file mode 100644 index 00000000000..acf67ab3a05 --- /dev/null +++ b/test/run-drun/oneway.mo @@ -0,0 +1,59 @@ +actor Oneway { + // test that oneways can locally try/throw + public func oneway() : () { + ignore ( + async { + debugPrint "1"; + try { + throw (error("Error")); + debugPrint "unreachable"; + } + catch e { debugPrint "2"}; + } + ) + }; + + // test that oneways can locally try/throw + // using `=` syntax + public func onewayAlt() : () = + ignore ( + async { + debugPrint "3"; + try { + throw (error("Error")); + debugPrint "unreachable"; + } + catch e { debugPrint "4"}; + } + ); + + + // test that throws from oneways are silently discarded (because replies are eager) + public func discard() : () { + ignore ( + async { + debugPrint "5"; + throw (error("ignored")); + debugPrint "unreachable"; + } + ) + }; + + // test that throws from oneways are silently discarded (because replies are eager) + // using `=` syntax + public func discardAlt() : () = + ignore ( + async { + debugPrint "6"; + throw (error("ignored")); + debugPrint "unreachable"; + } + ); + + + // TODO test await and calls to shared functions +} +//CALL ingress oneway 0x4449444C0000 +//CALL ingress onewayAlt 0x4449444C0000 +//CALL ingress discard 0x4449444C0000 +//CALL ingress discardAlt 0x4449444C0000 diff --git a/test/run-drun/test_oneway.mo b/test/run-drun/test_oneway.mo new file mode 100644 index 00000000000..cd2aacd6ae7 --- /dev/null +++ b/test/run-drun/test_oneway.mo @@ -0,0 +1,16 @@ +import M "oneway.mo"; + +ignore (async { + debugPrint("A"); + M.Oneway.oneway(); + debugPrint("B"); + M.Oneway.onewayAlt(); + debugPrint("C"); + M.Oneway.discard(); + debugPrint("D"); + M.Oneway.discardAlt(); + debugPrint("E"); +} +); + +//SKIP comp \ No newline at end of file From 678dc640bd9495f8997e3e61f9ad2964fb8fd052 Mon Sep 17 00:00:00 2001 From: Enzo Haussecker Date: Tue, 19 Nov 2019 03:17:22 -0800 Subject: [PATCH 0654/1176] Trivial syntax abstractions --- stdlib/list.mo | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/stdlib/list.mo b/stdlib/list.mo index 49e01e9ca60..702c0426f2c 100644 --- a/stdlib/list.mo +++ b/stdlib/list.mo @@ -513,7 +513,7 @@ public type List = ?(T, List); Creates a list of the given length with the same value in each position. */ public func replicate(n : Nat, x : X) : List { - tabulate(n, func (_) { x }) + tabulate(n, func _ x) }; /** @@ -524,7 +524,7 @@ public type List = ?(T, List); minimum. */ public func zip(xs : List, ys : List) : List<(X, Y)> { - zipWith(xs, ys, func (x, y) { (x, y) }) + zipWith(xs, ys, func (x, y) (x, y)) }; /** @@ -541,14 +541,10 @@ public type List = ?(T, List); f : (X, Y) -> Z ) : List { switch (pop(xs)) { - case (null, _) { - nil() - }; + case (null, _) null; case (?x, xt) { switch (pop(ys)) { - case (null, _) { - nil() - }; + case (null, _) null; case (?y, yt) { push(f(x, y), zipWith(xt, yt, f)) } @@ -594,7 +590,7 @@ public type List = ?(T, List); public func chunksOf(n : Nat, xs : List) : List> { let (l, r) = splitAt(n, xs); if (isNil(l)) { - null + l } else { push>(l, chunksOf(n, r)) } From 4d7bd186b58b361e2c4fc972f2160b6fd964fcc2 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 19 Nov 2019 11:22:03 +0000 Subject: [PATCH 0655/1176] fix broken merge --- src/mo_idl/mo_to_idl.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mo_idl/mo_to_idl.ml b/src/mo_idl/mo_to_idl.ml index df057218568..2eeebfaf47a 100644 --- a/src/mo_idl/mo_to_idl.ml +++ b/src/mo_idl/mo_to_idl.ml @@ -106,7 +106,7 @@ let rec typ vs t = | Func (Shared s, c, [], ts1, ts2) -> let t1 = args vs ts1 in (match ts2, c with - | [], Returns -> I.FuncT ([I.Oneway @@ no_region], fs1, []) + | [], Returns -> I.FuncT ([I.Oneway @@ no_region], t1, []) | ts, Promises _ -> I.FuncT ( (match s with From e382f60ea858de69abda8b3c808e986109123715 Mon Sep 17 00:00:00 2001 From: Enzo Haussecker Date: Tue, 19 Nov 2019 03:22:53 -0800 Subject: [PATCH 0656/1176] Use curly braces for function result --- stdlib/list.mo | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/list.mo b/stdlib/list.mo index 702c0426f2c..f9eca6eb901 100644 --- a/stdlib/list.mo +++ b/stdlib/list.mo @@ -513,7 +513,7 @@ public type List = ?(T, List); Creates a list of the given length with the same value in each position. */ public func replicate(n : Nat, x : X) : List { - tabulate(n, func _ x) + tabulate(n, func _ { x }) }; /** @@ -524,7 +524,7 @@ public type List = ?(T, List); minimum. */ public func zip(xs : List, ys : List) : List<(X, Y)> { - zipWith(xs, ys, func (x, y) (x, y)) + zipWith(xs, ys, func (x, y) { (x, y) }) }; /** From cbb3ef08bb5cb81789260f136245bf29fc8c2e4f Mon Sep 17 00:00:00 2001 From: Enzo Haussecker Date: Tue, 19 Nov 2019 03:26:41 -0800 Subject: [PATCH 0657/1176] Revert syntax abstractions --- stdlib/list.mo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/list.mo b/stdlib/list.mo index f9eca6eb901..e60dca9a758 100644 --- a/stdlib/list.mo +++ b/stdlib/list.mo @@ -513,7 +513,7 @@ public type List = ?(T, List); Creates a list of the given length with the same value in each position. */ public func replicate(n : Nat, x : X) : List { - tabulate(n, func _ { x }) + tabulate(n, func (_) { x }) }; /** From 3ec5db820c6aebfb8a377124b058bae908c6dc80 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 19 Nov 2019 12:32:33 +0100 Subject: [PATCH 0658/1176] Remove test case large-mem (we have large-array already) --- test/run-drun/large-mem.mo | 1 - test/run-drun/ok/large-mem.drun-run.ok | 1 - test/run/large-mem.mo | 1 - 3 files changed, 3 deletions(-) delete mode 100644 test/run-drun/large-mem.mo delete mode 100644 test/run-drun/ok/large-mem.drun-run.ok delete mode 100644 test/run/large-mem.mo diff --git a/test/run-drun/large-mem.mo b/test/run-drun/large-mem.mo deleted file mode 100644 index dc0a4c63996..00000000000 --- a/test/run-drun/large-mem.mo +++ /dev/null @@ -1 +0,0 @@ -ignore(Array_init<()>(64*1024, ())); diff --git a/test/run-drun/ok/large-mem.drun-run.ok b/test/run-drun/ok/large-mem.drun-run.ok deleted file mode 100644 index 43d7af40394..00000000000 --- a/test/run-drun/ok/large-mem.drun-run.ok +++ /dev/null @@ -1 +0,0 @@ -ingress(0) System diff --git a/test/run/large-mem.mo b/test/run/large-mem.mo deleted file mode 100644 index dc0a4c63996..00000000000 --- a/test/run/large-mem.mo +++ /dev/null @@ -1 +0,0 @@ -ignore(Array_init<()>(64*1024, ())); From 6952d214e26d4c8a59a56ab70c6c25ff13bec60f Mon Sep 17 00:00:00 2001 From: Enzo Haussecker Date: Tue, 19 Nov 2019 03:34:47 -0800 Subject: [PATCH 0659/1176] Fix type error --- stdlib/list.mo | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/list.mo b/stdlib/list.mo index e60dca9a758..15580fcefab 100644 --- a/stdlib/list.mo +++ b/stdlib/list.mo @@ -513,7 +513,7 @@ public type List = ?(T, List); Creates a list of the given length with the same value in each position. */ public func replicate(n : Nat, x : X) : List { - tabulate(n, func (_) { x }) + tabulate(n, func _ { x }) }; /** @@ -590,7 +590,7 @@ public type List = ?(T, List); public func chunksOf(n : Nat, xs : List) : List> { let (l, r) = splitAt(n, xs); if (isNil(l)) { - l + null } else { push>(l, chunksOf(n, r)) } From 646a75a6d29f476742f10a9b30683440d6ac1985 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 19 Nov 2019 13:03:25 +0100 Subject: [PATCH 0660/1176] Let `rawInitialize` assemble the `ImpState` The abstraction is not perfect, because `IC.Canister.Persisted` needs to look inside. --- ic-stub/src/IC/Canister/Imp.hs | 8 ++++---- ic-stub/src/IC/Canister/Persisted.hs | 21 ++++++++++++++------- ic-stub/src/IC/Canister/Pure.hs | 9 +++------ 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/ic-stub/src/IC/Canister/Imp.hs b/ic-stub/src/IC/Canister/Imp.hs index 53343cbcd27..9ad156afa75 100644 --- a/ic-stub/src/IC/Canister/Imp.hs +++ b/ic-stub/src/IC/Canister/Imp.hs @@ -12,7 +12,7 @@ module IC.Canister.Imp ( ESRef , ImpState , runESST - , rawInitializeModule + , rawInitialize , rawInvoke , silently ) @@ -294,12 +294,12 @@ systemAPI esref = type ImpState s = (ESRef s, CanisterId, Instance s) -rawInitializeModule :: ESRef s -> Module -> ST s (TrapOr (Instance s)) -rawInitializeModule esref wasm_mod = do +rawInitialize :: ESRef s -> CanisterId -> Module -> ST s (TrapOr (ImpState s)) +rawInitialize esref cid wasm_mod = do result <- runExceptT $ initialize wasm_mod (systemAPI esref) case result of Left err -> return $ Trap err - Right inst -> return $ Return inst + Right inst -> return $ Return (esref, cid, inst) rawInvoke :: ImpState s -> CI.CanisterMethod r -> ST s (TrapOr r) rawInvoke esref (CI.Initialize wasm_mod caller dat) = diff --git a/ic-stub/src/IC/Canister/Persisted.hs b/ic-stub/src/IC/Canister/Persisted.hs index 96e1fb3f192..8026be43bf8 100644 --- a/ic-stub/src/IC/Canister/Persisted.hs +++ b/ic-stub/src/IC/Canister/Persisted.hs @@ -24,13 +24,12 @@ data WasmState = WasmState Module CanisterId PInstance initialize :: Module -> CanisterId -> EntityId -> Blob -> TrapOr WasmState initialize wasm_mod cid caller dat = runESST $ \esref -> - rawInitializeModule esref wasm_mod >>= \case + rawInitialize esref cid wasm_mod >>= \case Trap err -> return $ Trap err - Return inst -> do - let rs = (esref, cid, inst) + Return rs -> rawInvoke rs (CI.Initialize wasm_mod caller dat) >>= \case Trap err -> return $ Trap err - Return () -> Return . WasmState wasm_mod cid <$> persistInstance inst + Return () -> Return <$> newWasmState wasm_mod rs invoke :: WasmState -> CI.CanisterMethod r -> TrapOr (WasmState, r) invoke s m = runESST $ \esref -> do @@ -44,13 +43,21 @@ invoke s m = runESST $ \esref -> do replay :: ESRef s -> WasmState -> ST s (ImpState s) replay esref (WasmState wasm_mod cid pinst) = do - is <- rawInitializeModule esref wasm_mod >>= trapToFail - resumeInstance is pinst - return (esref, cid, is) + rs <- rawInitialize esref cid wasm_mod >>= trapToFail + resume rs pinst + return rs where trapToFail (Trap _err) = fail "replay failed" trapToFail (Return x) = return x +newWasmState :: Module -> ImpState s -> ST s WasmState +newWasmState wasm_mod (_esref, cid, inst) = + WasmState wasm_mod cid <$> persistInstance inst + +resume :: ImpState s -> PInstance -> ST s () +resume (_, _, inst) pinst = + resumeInstance inst pinst + persist :: WasmState -> ImpState s -> ST s WasmState persist (WasmState wasm_mod cid _) (_, _, inst) = WasmState wasm_mod cid <$> persistInstance inst diff --git a/ic-stub/src/IC/Canister/Pure.hs b/ic-stub/src/IC/Canister/Pure.hs index 5edc61f126a..84573c722f8 100644 --- a/ic-stub/src/IC/Canister/Pure.hs +++ b/ic-stub/src/IC/Canister/Pure.hs @@ -36,10 +36,9 @@ data WasmState = WasmState initialize :: Module -> CanisterId -> EntityId -> Blob -> TrapOr WasmState initialize wasm_mod cid caller dat = runESST $ \esref -> - rawInitializeModule esref wasm_mod >>= \case + rawInitialize esref cid wasm_mod >>= \case Trap err -> return $ Trap err - Return inst -> do - let rs = (esref, cid, inst) + Return rs -> do let m = CI.Initialize wasm_mod caller dat result <- rawInvoke rs m let state' = WasmState wasm_mod cid [ACall m] @@ -63,9 +62,7 @@ replay esref WasmState{ ws_mod, ws_self_id, ws_calls } = silently esref $ go ws_ trapToFail (Return x) = return x go :: [ACall] -> ST s (ImpState s) - go [] = do - inst <- rawInitializeModule esref ws_mod >>= trapToFail - return (esref, ws_self_id, inst) + go [] = rawInitialize esref ws_self_id ws_mod >>= trapToFail go (ACall m:ms) = do is <- go ms _ <- rawInvoke is m >>= trapToFail From c532e4c8f42b19a837b7e7b912b9e9c07880f8a9 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 19 Nov 2019 15:55:03 +0100 Subject: [PATCH 0661/1176] Use Data.Sequence --- ic-stub/src/IC/Stub.hs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ic-stub/src/IC/Stub.hs b/ic-stub/src/IC/Stub.hs index c939d56a651..aeffeb9b612 100644 --- a/ic-stub/src/IC/Stub.hs +++ b/ic-stub/src/IC/Stub.hs @@ -29,6 +29,8 @@ import Data.List import Data.Maybe import Control.Monad import Control.Monad.State.Class +import Data.Sequence (Seq(..)) +import Data.Foldable (toList) -- import Debug.Trace @@ -108,7 +110,7 @@ data Message = data IC = IC { canisters :: CanisterId ↦ Maybe CanState , requests :: AsyncRequest ↦ RequestStatus - , messages :: [Message] + , messages :: Seq Message , call_contexts :: CallId ↦ CallContext } @@ -157,7 +159,7 @@ nextStarved = gets $ \ic -> listToMaybe [ c | (c, ctxt) <- M.toList (call_contexts ic) , not $ responded ctxt - , null [ () | ResponseMessage { call_context = c' } <- messages ic, c' == c ] + , null [ () | ResponseMessage { call_context = c' } <- toList (messages ic), c' == c ] , null [ () | CallContext { responded = False, origin = FromCanister c' _} @@ -169,8 +171,8 @@ nextStarved = gets $ \ic -> listToMaybe nextMessage :: ICT m => m (Maybe Message) nextMessage = state $ \ic -> case messages ic of - [] -> (Nothing, ic) - (m:ms) -> (Just m, ic { messages = ms }) + Empty -> (Nothing, ic) + m :<| ms -> (Just m, ic { messages = ms }) setReqStatus :: ICT m => AsyncRequest -> RequestStatus -> m () setReqStatus r s = @@ -220,10 +222,8 @@ processRequest r@(UpdateRequest _user_id method arg) = do } setReqStatus r Processing --- processRequest r = setReqStatus r (Rejected (0, "Unknown request type")) - enqueueMessage :: ICT m => Message -> m () -enqueueMessage m = modify $ \ic -> ic { messages = messages ic ++ [m] } +enqueueMessage m = modify $ \ic -> ic { messages = messages ic :|> m } newCallContext :: ICT m => CallContext -> m CallId newCallContext cc = state go From 83758d9b70d8a5583c7295825598a836c485b86e Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 19 Nov 2019 15:56:35 +0100 Subject: [PATCH 0662/1176] getCallContext --- ic-stub/src/IC/Stub.hs | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/ic-stub/src/IC/Stub.hs b/ic-stub/src/IC/Stub.hs index aeffeb9b612..ee7682da811 100644 --- a/ic-stub/src/IC/Stub.hs +++ b/ic-stub/src/IC/Stub.hs @@ -233,19 +233,23 @@ newCallContext cc = state go i | M.null (call_contexts ic) = 0 | otherwise = fst (M.findMax (call_contexts ic)) + 1 -modifyContext :: ICT m => CallId -> (CallContext -> CallContext) -> m () -modifyContext ctxt_id f = +getCallContext :: ICT m => CallId -> m CallContext +getCallContext ctxt_id = + gets ((M.! ctxt_id) . call_contexts) + +modifyCallContext :: ICT m => CallId -> (CallContext -> CallContext) -> m () +modifyCallContext ctxt_id f = modify $ \ic -> ic { call_contexts = M.adjust f ctxt_id (call_contexts ic) } -respondContext :: ICT m => CallId -> Response -> m () -respondContext ctxt_id response = do +respondCallContext :: ICT m => CallId -> Response -> m () +respondCallContext ctxt_id response = do -- TODO: check no prior response - modifyContext ctxt_id $ \ctxt -> ctxt { responded = True } + modifyCallContext ctxt_id $ \ctxt -> ctxt { responded = True } enqueueMessage $ ResponseMessage { call_context = ctxt_id, response } rememberTrap :: ICT m => CallId -> String -> m () rememberTrap ctxt_id msg = - modifyContext ctxt_id $ \ctxt -> ctxt { last_trap = Just msg } + modifyCallContext ctxt_id $ \ctxt -> ctxt { last_trap = Just msg } callerOfRequest :: AsyncRequest -> EntityId callerOfRequest (InstallRequest user_id _ _) = user_id @@ -253,14 +257,14 @@ callerOfRequest (UpdateRequest user_id _ _) = user_id callerOfCallID :: ICT m => CallId -> m EntityId callerOfCallID ctxt_id = do - ctxt <- gets ((M.! ctxt_id) . call_contexts) + ctxt <- getCallContext ctxt_id case origin ctxt of FromUser request -> return $ callerOfRequest request FromCanister other_ctxt_id _callback -> calleeOfCallID other_ctxt_id calleeOfCallID :: ICT m => CallId -> m EntityId calleeOfCallID ctxt_id = do - ctxt <- gets ((M.! ctxt_id) . call_contexts) + ctxt <- getCallContext ctxt_id return $ canister ctxt invokeEntry :: ICT m => @@ -279,7 +283,7 @@ invokeEntry ctxt_id (CanState wasm_state can_mod) entry = do processMessage :: ICT m => Message -> m () processMessage (CallMessage ctxt_id entry) = do callee <- calleeOfCallID ctxt_id - let res r = respondContext ctxt_id r + let res r = respondCallContext ctxt_id r gets (M.lookup callee . canisters) >>= \case Nothing -> res $ Reject (RC_DESTINATION_INVALID, "canister does not exist: " ++ show callee) Just Nothing -> res $ Reject (RC_DESTINATION_INVALID, "canister is empty") @@ -303,7 +307,7 @@ processMessage (CallMessage ctxt_id entry) = do mapM_ res mb_response processMessage (ResponseMessage ctxt_id response) = do - ctxt <- gets ((M.! ctxt_id) . call_contexts) + ctxt <- getCallContext ctxt_id case origin ctxt of FromUser request -> setReqStatus request $ case response of @@ -315,12 +319,12 @@ processMessage (ResponseMessage ctxt_id response) = do , entry = Closure callback response } -starveContext :: ICT m => CallId -> m () -starveContext ctxt_id = do - ctxt <- gets ((M.! ctxt_id) . call_contexts) +starveCallContext :: ICT m => CallId -> m () +starveCallContext ctxt_id = do + ctxt <- getCallContext ctxt_id let msg | Just t <- last_trap ctxt = "canister trapped: " ++ t | otherwise = "canister did not respond" - respondContext ctxt_id $ Reject (RC_CANISTER_ERROR, msg) + respondCallContext ctxt_id $ Reject (RC_CANISTER_ERROR, msg) runToCompletion :: ICT m => m () runToCompletion = @@ -329,5 +333,5 @@ runToCompletion = Nothing -> nextMessage >>= \case Just m -> processMessage m >> runToCompletion Nothing -> nextStarved >>= \case - Just c -> starveContext c >> runToCompletion + Just c -> starveCallContext c >> runToCompletion Nothing -> return () From 620e1a734f06c2558344c4e98aaece1c4510d300 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 19 Nov 2019 16:00:35 +0100 Subject: [PATCH 0663/1176] =?UTF-8?q?Christoph=E2=80=99s=20nits?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ic-stub/src/IC/Canister/Imp.hs | 6 +++--- ic-stub/src/IC/Canister/Persisted.hs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ic-stub/src/IC/Canister/Imp.hs b/ic-stub/src/IC/Canister/Imp.hs index 9ad156afa75..57cb928aa4e 100644 --- a/ic-stub/src/IC/Canister/Imp.hs +++ b/ic-stub/src/IC/Canister/Imp.hs @@ -110,8 +110,8 @@ silently (pref, _esref) f = do getsES :: ESRef s -> (ExecutionState s -> b) -> HostM s b getsES (_, esref) f = lift (readSTRef esref) >>= \case - Nothing -> throwError "System API not available yet" - Just es -> return (f es) + Nothing -> throwError "System API not available yet" + Just es -> return (f es) modES :: ESRef s -> (ExecutionState s -> ExecutionState s) -> HostM s () modES (_, esref) f = lift $ modifySTRef esref (fmap f) @@ -160,7 +160,7 @@ systemAPI esref = copy_to_canister :: Int32 -> Int32 -> Int32 -> Blob -> HostM s () copy_to_canister dst offset size blob = do unless (offset == 0) $ - throwError "offset /= 0 not suppoted" + throwError "offset /= 0 not supported" unless (size == fromIntegral (BS.length blob)) $ throwError "copying less than the full blob is not supported" i <- getsES esref inst diff --git a/ic-stub/src/IC/Canister/Persisted.hs b/ic-stub/src/IC/Canister/Persisted.hs index 8026be43bf8..229ed69aa49 100644 --- a/ic-stub/src/IC/Canister/Persisted.hs +++ b/ic-stub/src/IC/Canister/Persisted.hs @@ -52,11 +52,11 @@ replay esref (WasmState wasm_mod cid pinst) = do newWasmState :: Module -> ImpState s -> ST s WasmState newWasmState wasm_mod (_esref, cid, inst) = - WasmState wasm_mod cid <$> persistInstance inst + WasmState wasm_mod cid <$> persistInstance inst resume :: ImpState s -> PInstance -> ST s () resume (_, _, inst) pinst = - resumeInstance inst pinst + resumeInstance inst pinst persist :: WasmState -> ImpState s -> ST s WasmState persist (WasmState wasm_mod cid _) (_, _, inst) = From 12aa9bd820d8a9dbb4ce4ddaa1d3c819d1f68733 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 19 Nov 2019 15:13:14 +0000 Subject: [PATCH 0664/1176] Update src/mo_frontend/typing.ml Co-Authored-By: Andreas Rossberg --- src/mo_frontend/typing.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 3302726309a..9519cbecb11 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -993,7 +993,7 @@ and check_exp' env0 t exp : T.typ = (T.string_of_typ_expand (T.Array t')); List.iter (check_exp env (T.as_immut t')) exps; t - | AsyncE (tb, exp1, typ1), T.Async (t1',t') -> + | AsyncE (tb, exp1, typ1), T.Async (t1', t') -> if not in_shared then error_in [Flags.ICMode] env exp.at "freestanding async expression not yet supported"; let t1 = check_typ env typ1 in From ac64dc21df839259d17dcb73e57f0df056029bac Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 19 Nov 2019 15:22:55 +0000 Subject: [PATCH 0665/1176] fix as_async_sub to take default_scope --- src/ir_def/check_ir.ml | 2 +- src/mo_frontend/typing.ml | 2 +- src/mo_types/type.ml | 4 ++-- src/mo_types/type.mli | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 631703caaf3..17acad63cc5 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -570,7 +570,7 @@ let rec check_exp env (exp:Ir.exp) : unit = let t0 = T.Con(Lib.Option.value env.async, []) in check_exp env exp1; let t1 = T.promote (typ exp1) in - let (t2, t3) = try T.as_async_sub t1 + let (t2, t3) = try T.as_async_sub t0 t1 with Invalid_argument _ -> error env exp1.at "expected async type, but expression has type\n %s" (T.string_of_typ_expand t1) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 9519cbecb11..9edb3bd2099 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -928,8 +928,8 @@ and infer_exp'' env exp : T.typ = error_in [Flags.ICMode] env f.at "expecting call to shared async function in await"; | _ -> error_in [Flags.ICMode] env exp1.at "argument to await must be a call expression"); (try - let (t2, t3) = T.as_async_sub t1 in let t0 = T.Con (Lib.Option.value env.async, []) in + let (t2, t3) = T.as_async_sub t0 t1 in if not (T.eq t0 t2) then error env exp.at "ill-scoped await"; t3 diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index 36f57cc646d..29c57c034ce 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -420,9 +420,9 @@ let as_mono_func_sub t = match promote t with | Func (_, _, [], ts1, ts2) -> seq ts1, seq ts2 | Non -> Any, Non | _ -> invalid "as_func_sub" -let as_async_sub t = match promote t with +let as_async_sub default_scope t = match promote t with | Async (t1, t2) -> (t1, t2) - | Non -> Any, Non (* TBR *) + | Non -> default_scope, Non (* TBR *) | _ -> invalid "as_async_sub" diff --git a/src/mo_types/type.mli b/src/mo_types/type.mli index c4f3f642a98..4dea0ab5f49 100644 --- a/src/mo_types/type.mli +++ b/src/mo_types/type.mli @@ -123,7 +123,7 @@ val as_unit_sub : typ -> unit val as_pair_sub : typ -> typ * typ val as_func_sub : func_sort -> int -> typ -> func_sort * bind list * typ * typ val as_mono_func_sub : typ -> typ * typ -val as_async_sub : typ -> typ * typ +val as_async_sub : typ -> typ -> typ * typ (* Argument/result sequences *) From b5a74f083b85d895f8f9e5e436d0fbc1f33d0b5f Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 19 Nov 2019 17:50:53 +0000 Subject: [PATCH 0666/1176] Fix for #874 (#877) * update don't replace obj environment entries * added test for nested access * remove duplicate test --- src/mo_frontend/typing.ml | 5 +++-- test/fail/issue-874-b.mo | 8 ++++++++ test/fail/issue-874.mo | 5 +++++ test/fail/issue874.mo | 4 ---- test/fail/ok/issue-874-b.tc.ok | 1 + .../fail/ok/{issue874.tc.ret.ok => issue-874-b.tc.ret.ok} | 0 test/fail/ok/issue-874.tc.ok | 1 + test/fail/ok/issue-874.tc.ret.ok | 1 + test/fail/ok/issue874.tc.ok | 2 -- test/fail/ok/modexp2.tc.ok | 2 +- test/fail/ok/modexp3.tc.ok | 2 +- test/fail/ok/modexp4.tc.ok | 2 +- test/fail/ok/modules-fwd.tc.ok | 3 +-- 13 files changed, 23 insertions(+), 13 deletions(-) create mode 100644 test/fail/issue-874-b.mo create mode 100644 test/fail/issue-874.mo delete mode 100644 test/fail/issue874.mo create mode 100644 test/fail/ok/issue-874-b.tc.ok rename test/fail/ok/{issue874.tc.ret.ok => issue-874-b.tc.ret.ok} (100%) create mode 100644 test/fail/ok/issue-874.tc.ok create mode 100644 test/fail/ok/issue-874.tc.ret.ok delete mode 100644 test/fail/ok/issue874.tc.ok diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 610d3afc24c..44b2e251962 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -1699,7 +1699,8 @@ and infer_dec_typdecs env dec : Scope.t = let decs = List.map (fun {it = {vis;dec}; _} -> dec) fields in let scope = T.Env.find id.it env.objs in let env' = adjoin env scope in - let obj_scope = infer_block_typdecs env' decs in + let obj_scope_typs = infer_block_typdecs env' decs in + let obj_scope = Scope.adjoin scope obj_scope_typs in Scope.{ empty with con_env = obj_scope.con_env; val_env = T.Env.singleton id.it (object_of_scope env sort fields obj_scope at); @@ -1790,7 +1791,7 @@ and infer_dec_valdecs env dec : Scope.t = let obj_scope' = infer_block_valdecs (adjoin {env with pre = true} obj_scope) - decs Scope.empty + decs obj_scope in let obj_typ = object_of_scope env sort fields obj_scope' at in let _ve = check_pat env obj_typ pat in diff --git a/test/fail/issue-874-b.mo b/test/fail/issue-874-b.mo new file mode 100644 index 00000000000..eb227956c50 --- /dev/null +++ b/test/fail/issue-874-b.mo @@ -0,0 +1,8 @@ +let m = object { + public module X { + public type T = Int; + public func bar() { m.X.bar(); }; + let _ = m.X.bar(); + } +}; + diff --git a/test/fail/issue-874.mo b/test/fail/issue-874.mo new file mode 100644 index 00000000000..42ebb333b63 --- /dev/null +++ b/test/fail/issue-874.mo @@ -0,0 +1,5 @@ +let a = actor { + public type T = Int; + public func foo() { a.foo(); }; + let _ = a.foo(); +}; diff --git a/test/fail/issue874.mo b/test/fail/issue874.mo deleted file mode 100644 index 1f54f9a1d5d..00000000000 --- a/test/fail/issue874.mo +++ /dev/null @@ -1,4 +0,0 @@ -actor a { - public func foo() {}; - let _ = a.foo(); -} diff --git a/test/fail/ok/issue-874-b.tc.ok b/test/fail/ok/issue-874-b.tc.ok new file mode 100644 index 00000000000..a22770ea50c --- /dev/null +++ b/test/fail/ok/issue-874-b.tc.ok @@ -0,0 +1 @@ +issue-874-b.mo:5.14-5.21: type error, cannot infer type of forward field reference bar diff --git a/test/fail/ok/issue874.tc.ret.ok b/test/fail/ok/issue-874-b.tc.ret.ok similarity index 100% rename from test/fail/ok/issue874.tc.ret.ok rename to test/fail/ok/issue-874-b.tc.ret.ok diff --git a/test/fail/ok/issue-874.tc.ok b/test/fail/ok/issue-874.tc.ok new file mode 100644 index 00000000000..340f61c5fb9 --- /dev/null +++ b/test/fail/ok/issue-874.tc.ok @@ -0,0 +1 @@ +issue-874.mo:4.11-4.16: type error, cannot infer type of forward field reference foo diff --git a/test/fail/ok/issue-874.tc.ret.ok b/test/fail/ok/issue-874.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/issue-874.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/issue874.tc.ok b/test/fail/ok/issue874.tc.ok deleted file mode 100644 index 9b5b57c2af2..00000000000 --- a/test/fail/ok/issue874.tc.ok +++ /dev/null @@ -1,2 +0,0 @@ -issue874.mo:3.11-3.12: type error, field foo does not exist in type - actor {} diff --git a/test/fail/ok/modexp2.tc.ok b/test/fail/ok/modexp2.tc.ok index c36ba16ab97..913cad8d38b 100644 --- a/test/fail/ok/modexp2.tc.ok +++ b/test/fail/ok/modexp2.tc.ok @@ -1,2 +1,2 @@ modexp2.mo:11.16-11.17: type error, type field U does not exist in type - module {type T = Int} + module {type T = Int; f : ???} diff --git a/test/fail/ok/modexp3.tc.ok b/test/fail/ok/modexp3.tc.ok index 2b37e312262..fb581d91d9e 100644 --- a/test/fail/ok/modexp3.tc.ok +++ b/test/fail/ok/modexp3.tc.ok @@ -1,2 +1,2 @@ modexp3.mo:1.1-7.2: type error, local class type U is contained in object or actor type - module {type T = U} + module {type T = U; f : ???; h : ???} diff --git a/test/fail/ok/modexp4.tc.ok b/test/fail/ok/modexp4.tc.ok index dc7f20d07ac..0ff59d1658f 100644 --- a/test/fail/ok/modexp4.tc.ok +++ b/test/fail/ok/modexp4.tc.ok @@ -1,2 +1,2 @@ modexp4.mo:2.1-10.2: type error, local class type U is contained in object or actor type - module {type T = U} + module {type T = U; f : ???; h : ???} diff --git a/test/fail/ok/modules-fwd.tc.ok b/test/fail/ok/modules-fwd.tc.ok index c653a0a2c7b..563341165c3 100644 --- a/test/fail/ok/modules-fwd.tc.ok +++ b/test/fail/ok/modules-fwd.tc.ok @@ -1,2 +1 @@ -modules-fwd.mo:5.9-5.10: type error, field v does not exist in type - module {type T = ()} +modules-fwd.mo:5.9-5.12: type error, cannot infer type of forward field reference v From 789ac54bbed48a744f7911a43b8c76bfca33456c Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 19 Nov 2019 18:05:03 +0000 Subject: [PATCH 0667/1176] address nit --- src/ir_def/check_ir.ml | 5 +++-- src/mo_frontend/typing.ml | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 17acad63cc5..9ca06e0f0ba 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -566,8 +566,9 @@ let rec check_exp env (exp:Ir.exp) : unit = T.Async (t0, t1') <: t | AwaitE exp1 -> check env.flavor.has_await "await in non-await flavor"; - check (env.async <> None) "misplaced await"; - let t0 = T.Con(Lib.Option.value env.async, []) in + let t0 = match env.async with + | Some c -> T.Con(c, []) + | None -> error env exp.at "misplaced await" in check_exp env exp1; let t1 = T.promote (typ exp1) in let (t2, t3) = try T.as_async_sub t0 t1 diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 9edb3bd2099..ff0c290c3b3 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -919,8 +919,9 @@ and infer_exp'' env exp : T.typ = (T.string_of_typ_expand t'); T.Async (t1, t') | AwaitE exp1 -> - if env.async = None then - error env exp.at "misplaced await"; + let t0 = match env.async with + | Some c -> T.Con(c, []) + | None -> error env exp.at "misplaced await" in let t1 = infer_exp_promote {env with in_await = true} exp1 in (match exp1.it with | CallE (f, _, _) -> @@ -928,7 +929,6 @@ and infer_exp'' env exp : T.typ = error_in [Flags.ICMode] env f.at "expecting call to shared async function in await"; | _ -> error_in [Flags.ICMode] env exp1.at "argument to await must be a call expression"); (try - let t0 = T.Con (Lib.Option.value env.async, []) in let (t2, t3) = T.as_async_sub t0 t1 in if not (T.eq t0 t2) then error env exp.at "ill-scoped await"; From d8230d69c6171ac0d238ffc5210a38f8e6f93293 Mon Sep 17 00:00:00 2001 From: Enzo Haussecker Date: Tue, 19 Nov 2019 11:14:50 -0800 Subject: [PATCH 0668/1176] Text to list conversion is now redundant --- stdlib/text.mo | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/stdlib/text.mo b/stdlib/text.mo index 734b81c86be..34805fc947d 100644 --- a/stdlib/text.mo +++ b/stdlib/text.mo @@ -1,19 +1,7 @@ -import List "list.mo"; -import Option "option.mo"; - module { - type List = List.List; - public func append(x : Text, y : Text) : Text { x # y; }; - public func toList(text : Text) : List { - let get = text.chars().next; - List.tabulate(text.len(), func _ { - Option.unwrap(get()) - }) - }; - } From 2f9bbe895fa67814da751f27a5210b0c94164b17 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 19 Nov 2019 19:23:22 +0000 Subject: [PATCH 0669/1176] add test for general_await; WIP --- test/run-drun/general_await.mo | 101 +++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 test/run-drun/general_await.mo diff --git a/test/run-drun/general_await.mo b/test/run-drun/general_await.mo new file mode 100644 index 00000000000..727caaa67c0 --- /dev/null +++ b/test/run-drun/general_await.mo @@ -0,0 +1,101 @@ +actor Await { + + public shared func Ack<@>() : async(){ }; + + public shared func Request<@>(i : Int) : async Int { return i; }; + + // Static parallel waiting: + + public shared func PA<@>() : async () { + let a1 = Ack<@>(); + let a2 = Ack<@>(); + await a1; + await a2; + }; + + public shared func PR<@>() : async (Int,Int) { + let a1 = Request<@>(1); + let a2 = Request<@>(2); + (await a1, await a2) + }; + + // Dynamic parallel waiting for acknowledgements + + public shared func DPA<@>() : async () { + let as: [async()] = Array_tabulate(10, func (_) { Ack<@>(); }); + for (a in as.vals()) { + await a; + }; + }; + + // Dynamic parallel waiting (with results) + + public shared func DPR<@>() : async [Int] { + func f (i:Nat) : async Int = Request<@>(i); + let as = Array_tabulate(10, f); + let res = Array_init(as.len(),-1); + for (i in as.keys()) { + res[i] := (await as[i]); + }; + Array_tabulate(as.len(),func i = res[i]) + }; + + // Recursive parallel waiting + + public shared func RPA<@>(n:Nat) : async () { + if (n == 0) () + else { + let a = Ack<@>(); + await RPA<@>(n-1); // recurse + await a; + }; + }; + + // Recursive parallel waiting (with results) + + public type List = ?(Int,List); + + public shared func RPR<@>(n:Nat) : async List { + if (n == 0) null + else { + let a = Request<@>(n); + let tl = await RPR<@>(n-1); // recurse + ?(await a,tl) + } + }; + + + public shared func Test<@>() : async () { + + await PA<@>(); + + switch (await PR<@>()) { + case (1,2) (); + case _ (assert false); + }; + + await DPA<@>(); + + let rs = await DPR<@>(); + for (i in rs.keys()) { + assert rs[i] == i; + }; + + await RPA<@>(10); + + var l = await RPR<@>(10); + for (i in range(0, 9)) { + switch (l) { + case (?(h, t)) { + assert (h == i); + l := t; + }; + case null (assert false); + } + } + } +}; + +Await.test(); + +//SKIP run-drun From a9739c7da02436631511737159bb2e3b58960c12 Mon Sep 17 00:00:00 2001 From: Enzo Haussecker Date: Tue, 19 Nov 2019 11:30:30 -0800 Subject: [PATCH 0670/1176] Create iterator from text --- stdlib/text.mo | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/stdlib/text.mo b/stdlib/text.mo index 34805fc947d..bc46bb3d4cd 100644 --- a/stdlib/text.mo +++ b/stdlib/text.mo @@ -4,4 +4,8 @@ module { x # y; }; + public func toIter(text : Text) : Iter { + { next = text.chars().next } + } + } From 6901c536deff066671aa96c6e765d96a7415bb40 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 19 Nov 2019 22:59:06 +0100 Subject: [PATCH 0671/1176] default.nix: Remove packaging code (#887) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Judging from how the SDK imports Motoko, all this stuff is not actually used, so remove it. Also, they override the `buildPhase` of `stdlib` in https://github.com/dfinity-lab/sdk/blob/master/nix/overlays/motoko.nix let’s just do this properly here. --- default.nix | 38 ++++---------------------------------- 1 file changed, 4 insertions(+), 34 deletions(-) diff --git a/default.nix b/default.nix index 627690ffcdb..4c85cc6d1d5 100644 --- a/default.nix +++ b/default.nix @@ -204,16 +204,6 @@ rec { ''; }; - moc-tar = nixpkgs.symlinkJoin { - name = "moc-tar"; - paths = [ moc-bin rts didc ]; - postBuild = '' - tar -chf $out/moc.tar -C $out bin/moc rts/mo-rts.wasm bin/didc - mkdir -p $out/nix-support - echo "file bin $out/moc.tar" >> $out/nix-support/hydra-build-products - ''; - }; - # “our” Haskell packages inherit (haskellPackages) lsp-int qc-motoko ic-stub; @@ -391,27 +381,8 @@ rec { ''; installPhase = '' mkdir -p $out - tar -rf $out/stdlib.tar -C $src *.mo - mkdir -p $out/nix-support - echo "report stdlib $out/stdlib.tar" >> $out/nix-support/hydra-build-products - ''; - forceShare = ["man"]; - }; - - stdlib-doc-live = stdenv.mkDerivation { - name = "stdlib-doc-live"; - src = subpath ./stdlib; - buildInputs = with nixpkgs; - [ pandoc bash python ]; - buildPhase = '' - patchShebangs . - make alldoc - ''; - installPhase = '' - mkdir -p $out - mv doc $out/ - mkdir -p $out/nix-support - echo "report docs $out/doc README.html" >> $out/nix-support/hydra-build-products + cp ./*.mo $out + rm $out/*Test.mo ''; forceShare = ["man"]; }; @@ -427,9 +398,9 @@ rec { ''; installPhase = '' mkdir -p $out - tar -rf $out/stdlib-doc.tar -C doc . + mv doc $out/ mkdir -p $out/nix-support - echo "report stdlib-doc $out/stdlib-doc.tar" >> $out/nix-support/hydra-build-products + echo "report docs $out/doc README.html" >> $out/nix-support/hydra-build-products ''; forceShare = ["man"]; }; @@ -468,7 +439,6 @@ rec { rts stdlib stdlib-doc - stdlib-doc-live produce-exchange users-guide ic-stub From def84bfcc9cee2c05e6ee5b80eefad053afa9e16 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 20 Nov 2019 15:22:24 +0000 Subject: [PATCH 0672/1176] add test --- test/run-drun/general_await.mo | 22 +++++++---- test/run-drun/ok/general_await.run-ir.ok | 45 +++++++++++++++++++++++ test/run-drun/ok/general_await.run-low.ok | 45 +++++++++++++++++++++++ 3 files changed, 105 insertions(+), 7 deletions(-) create mode 100644 test/run-drun/ok/general_await.run-ir.ok create mode 100644 test/run-drun/ok/general_await.run-low.ok diff --git a/test/run-drun/general_await.mo b/test/run-drun/general_await.mo index 727caaa67c0..528ebb2ccf7 100644 --- a/test/run-drun/general_await.mo +++ b/test/run-drun/general_await.mo @@ -1,8 +1,13 @@ actor Await { - public shared func Ack<@>() : async(){ }; + public shared func Ack<@>() : async(){ + debugPrint "\nAck" + }; - public shared func Request<@>(i : Int) : async Int { return i; }; + public shared func Request<@>(i : Int) : async Int { + debugPrint("\nRequest(");debugPrintInt(i);debugPrint(")"); + return i; + }; // Static parallel waiting: @@ -35,7 +40,9 @@ actor Await { let as = Array_tabulate(10, f); let res = Array_init(as.len(),-1); for (i in as.keys()) { - res[i] := (await as[i]); +// res[i] := (await as[i]); <-- compiler bug (generates incorrect code) + let a = await as[i]; + res[i] := a; }; Array_tabulate(as.len(),func i = res[i]) }; @@ -65,7 +72,7 @@ actor Await { }; - public shared func Test<@>() : async () { + public shared func Test() : async () { await PA<@>(); @@ -84,7 +91,7 @@ actor Await { await RPA<@>(10); var l = await RPR<@>(10); - for (i in range(0, 9)) { + for (i in revrange(10, 1)) { switch (l) { case (?(h, t)) { assert (h == i); @@ -92,10 +99,11 @@ actor Await { }; case null (assert false); } - } + }; } }; -Await.test(); +Await.Test(); //SKIP run-drun +//SKIP comp diff --git a/test/run-drun/ok/general_await.run-ir.ok b/test/run-drun/ok/general_await.run-ir.ok new file mode 100644 index 00000000000..0e38f4617ac --- /dev/null +++ b/test/run-drun/ok/general_await.run-ir.ok @@ -0,0 +1,45 @@ + +Ack +Ack +Request(+1) +Request(+2) +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Request(0) +Request(+1) +Request(+2) +Request(+3) +Request(+4) +Request(+5) +Request(+6) +Request(+7) +Request(+8) +Request(+9) +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Request(+10) +Request(+9) +Request(+8) +Request(+7) +Request(+6) +Request(+5) +Request(+4) +Request(+3) +Request(+2) +Request(+1) diff --git a/test/run-drun/ok/general_await.run-low.ok b/test/run-drun/ok/general_await.run-low.ok new file mode 100644 index 00000000000..0e38f4617ac --- /dev/null +++ b/test/run-drun/ok/general_await.run-low.ok @@ -0,0 +1,45 @@ + +Ack +Ack +Request(+1) +Request(+2) +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Request(0) +Request(+1) +Request(+2) +Request(+3) +Request(+4) +Request(+5) +Request(+6) +Request(+7) +Request(+8) +Request(+9) +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Request(+10) +Request(+9) +Request(+8) +Request(+7) +Request(+6) +Request(+5) +Request(+4) +Request(+3) +Request(+2) +Request(+1) From 7a0ec93e8839df2c8ae524de4af846a31cab40f4 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 20 Nov 2019 19:23:08 +0100 Subject: [PATCH 0673/1176] Bump `dfinity` (#893) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit main reason: entering `nix-shell` only uses stuff that is built on hydra ``` git log --first-parent --oneline 8f017216245d57fb7173f27cb395f6c0e35d2c47..5c7efff0524adbf97d85b27adb180e6137a3428f ``` * dfinity-lab/dfinity@5c7efff05 Merge pull request dfinity-lab/dfinity#1919 from dfinity-lab/david/doc/msg-routing/remove-routing-scheduling-boundary * dfinity-lab/dfinity@841a6a906 Bump common (dfinity-lab/dfinity#1928) * dfinity-lab/dfinity@f8ff2b7c0 Log and record time it took to make/recover a checkpoint. (dfinity-lab/dfinity#1920) * dfinity-lab/dfinity@0c7cbba45 Merge pull request dfinity-lab/dfinity#1918 from dfinity-lab/david/doc/msg-routing/drop-pass-through-functions * dfinity-lab/dfinity@e82efa286 Merge pull request dfinity-lab/dfinity#1925 from dfinity-lab/dfn-1014 * dfinity-lab/dfinity@d65c0d6d4 Merge pull request dfinity-lab/dfinity#1922 from dfinity-lab/kw/test-wasmtime-op-cleanup * dfinity-lab/dfinity@0420f29f3 DFN-1146: s/StateLabel/Height/g (dfinity-lab/dfinity#1916) * dfinity-lab/dfinity@abd30f49b Merge pull request dfinity-lab/dfinity#1914 from dfinity-lab/allen/cleanup-owners * dfinity-lab/dfinity@c27eabd16 Merge pull request dfinity-lab/dfinity#1917 from dfinity-lab/david/doc/msg-routing/drop-link-to-scheduler-google-doc * dfinity-lab/dfinity@e143b053f Merge pull request dfinity-lab/dfinity#1913 from dfinity-lab/manu/DFN-1051 * dfinity-lab/dfinity@5507d438f DFN-1129: Consensus team can hash according to revised crypto hashing API (dfinity-lab/dfinity#1901) * dfinity-lab/dfinity@3c93ad1e6 Merge pull request dfinity-lab/dfinity#1906 from dfinity-lab/DFN-183/response-handler * dfinity-lab/dfinity@3b3f0a832 Client can print sample config (dfinity-lab/dfinity#1897) * dfinity-lab/dfinity@2be31246e Merge pull request dfinity-lab/dfinity#1912 from dfinity-lab/allen/messages * dfinity-lab/dfinity@7918e55a8 Merge pull request dfinity-lab/dfinity#1905 from dfinity-lab/mw/fix-nix-experimental * dfinity-lab/dfinity@c11031c96 Merge pull request dfinity-lab/dfinity#1898 from dfinity-lab/DFN-1096 * dfinity-lab/dfinity@ea4e5efcc Merge pull request dfinity-lab/dfinity#1910 from dfinity-lab/cleanupShareAggregatorTest * dfinity-lab/dfinity@7c6fc6bc0 Merge pull request dfinity-lab/dfinity#1900 from dfinity-lab/blockMakerDocs * dfinity-lab/dfinity@64fefa569 Merge pull request dfinity-lab/dfinity#1856 from dfinity-lab/DFN-1064_doc_beacon * dfinity-lab/dfinity@ca7203097 Merge pull request dfinity-lab/dfinity#1907 from dfinity-lab/fix-lock * dfinity-lab/dfinity@9e2b54765 Merge pull request dfinity-lab/dfinity#1890 from dfinity-lab/david/doc/msg-routing/cleanup * dfinity-lab/dfinity@cae5e1ab2 Merge pull request dfinity-lab/dfinity#1908 from dfinity-lab/akhi3030/improve-api * dfinity-lab/dfinity@2e54a427c Merge pull request dfinity-lab/dfinity#1894 from dfinity-lab/david/doc/msg-routing/minor-fixes * dfinity-lab/dfinity@83ebb2334 Merge pull request dfinity-lab/dfinity#1904 from dfinity-lab/akhi3030/mv-mmap-to-ph * dfinity-lab/dfinity@7dc5cf9eb Merge pull request dfinity-lab/dfinity#1760 from dfinity-lab/mw/wasmtime-no-libsigsegv * dfinity-lab/dfinity@53530603d Merge pull request dfinity-lab/dfinity#1902 from dfinity-lab/kw/move-persistent-heap * dfinity-lab/dfinity@ec6d55054 Merge pull request dfinity-lab/dfinity#1892 from dfinity-lab/DFN-183/extends-funcref * dfinity-lab/dfinity@a844428e2 Merge pull request dfinity-lab/dfinity#1826 from dfinity-lab/akhi3030/more-hypervisor-update * dfinity-lab/dfinity@400f232bf Merge pull request dfinity-lab/dfinity#1868 from dfinity-lab/drun-lib * dfinity-lab/dfinity@d8171de1f Transferring several CODEOWNER duties from jwiegley to others (dfinity-lab/dfinity#1899) * dfinity-lab/dfinity@cff61077e Merge pull request dfinity-lab/dfinity#1885 from dfinity-lab/paulliu/consensus-spec-index * dfinity-lab/dfinity@f1335c2f1 Merge pull request dfinity-lab/dfinity#1887 from dfinity-lab/removeDeprecatedConsensus * dfinity-lab/dfinity@24b1fb057 Merge pull request dfinity-lab/dfinity#1881 from dfinity-lab/paulliu/document-orchestrator * dfinity-lab/dfinity@e9be9ea36 Merge pull request dfinity-lab/dfinity#1888 from dfinity-lab/DFN-1063 * dfinity-lab/dfinity@67f1ff678 Merge pull request dfinity-lab/dfinity#1883 from dfinity-lab/paulliu/purger-spec * dfinity-lab/dfinity@1b23b9d06 Merge pull request dfinity-lab/dfinity#1569 from dfinity-lab/on_wasm * dfinity-lab/dfinity@1e2ab1219 Merge pull request dfinity-lab/dfinity#1830 from dfinity-lab/INF-479-integration-tests-with-iso * dfinity-lab/dfinity@09c5a3073 Merge pull request dfinity-lab/dfinity#1891 from dfinity-lab/DFN-183/extend-callcontext * dfinity-lab/dfinity@e44ce1ad5 Implement ic.canister_self (dfinity-lab/dfinity#1880) * dfinity-lab/dfinity@03e9d7125 Public Spec: Use “size” consistently (dfinity-lab/dfinity#1889) * dfinity-lab/dfinity@2c8f64033 Merge pull request dfinity-lab/dfinity#1886 from dfinity-lab/useTraitObjectForConsensusConfig * dfinity-lab/dfinity@cb5937b93 Merge pull request dfinity-lab/dfinity#1837 from dfinity-lab/removeDeprecatedConsensus * dfinity-lab/dfinity@614fd8ae3 Merge pull request dfinity-lab/dfinity#1882 from dfinity-lab/DFN-1059_test_each_stage * dfinity-lab/dfinity@d1e989119 Merge pull request dfinity-lab/dfinity#1884 from dfinity-lab/removeExtraBoxFromPayloadBuilder * dfinity-lab/dfinity@33d4988c8 Moar ways to pass config to ic-client. (dfinity-lab/dfinity#1867) * dfinity-lab/dfinity@eac1bfcb5 Merge pull request dfinity-lab/dfinity#1858 from dfinity-lab/paulliu/consensus-multi-node * dfinity-lab/dfinity@56210e494 Merge pull request dfinity-lab/dfinity#1878 from dfinity-lab/nm-update-common * dfinity-lab/dfinity@44bb00dae Merge pull request dfinity-lab/dfinity#660 from dfinity-lab/johnw/remove-example * dfinity-lab/dfinity@2694d6163 Merge pull request dfinity-lab/dfinity#1875 from dfinity-lab/nm-dont-override-cargo-home * dfinity-lab/dfinity@03cb15b82 Merge pull request dfinity-lab/dfinity#1853 from dfinity-lab/eftychis-move-persistence * dfinity-lab/dfinity@c79f1031c Merge pull request dfinity-lab/dfinity#1871 from dfinity-lab/david/doc/msg-routing/align-scheduling-routing-boundary * dfinity-lab/dfinity@a4ef887e7 Merge pull request dfinity-lab/dfinity#1874 from dfinity-lab/dimitris/remove-error-code * dfinity-lab/dfinity@3cf7db1ef Merge pull request dfinity-lab/dfinity#1873 from dfinity-lab/dimitris/remove-function * dfinity-lab/dfinity@a35818365 Scenario3 - update Initialize Account (dfinity-lab/dfinity#1840) --- default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/default.nix b/default.nix index 4c85cc6d1d5..d4acd1fe019 100644 --- a/default.nix +++ b/default.nix @@ -22,7 +22,7 @@ let dfinity-repo = import (builtins.fetchGit { name = "dfinity-sources"; url = "ssh://git@github.com/dfinity-lab/dfinity"; ref = "master"; - rev = "8f017216245d57fb7173f27cb395f6c0e35d2c47"; + rev = "5c7efff0524adbf97d85b27adb180e6137a3428f"; }) { system = nixpkgs.system; }; in let sdk = import (builtins.fetchGit { From 42aad7ad12cc05c4c09235f6a16ae88fd8707324 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Wed, 20 Nov 2019 14:52:36 -0700 Subject: [PATCH 0674/1176] discussion and feedback; Andreas and Joachim --- stdlib/array.mo | 9 +++ stdlib/arrayBuf.mo | 164 +++++++++++++++++++++++++-------------------- stdlib/buf.mo | 65 +++++++++--------- 3 files changed, 131 insertions(+), 107 deletions(-) diff --git a/stdlib/array.mo b/stdlib/array.mo index a56cf187909..11df7eef039 100644 --- a/stdlib/array.mo +++ b/stdlib/array.mo @@ -118,4 +118,13 @@ module { }; ys; }; + + public func Array_tabulate_mut(len : Nat, gen : Nat -> T) : [var T] { + if (len == 0) { return [] }; + let xs = Array_init(len, gen 0); + for (i in range(1,len)) { + xs[i] := gen i; + }; + return xs; + }; } diff --git a/stdlib/arrayBuf.mo b/stdlib/arrayBuf.mo index cee3d86b1b2..1a2b431f795 100644 --- a/stdlib/arrayBuf.mo +++ b/stdlib/arrayBuf.mo @@ -15,99 +15,117 @@ See [buffer documentation](buf.mo) for more. // re-export types and use them below. public type ArrayBuf = Buf.ArrayBuf; -public type Buf = Buf.Buf; - -public type InitArg = { - // requests an empty buffer without asking for a capacity - #empty; - // take ownership of an existing representation - #arrayBuf: ArrayBuf; - // initially-empty, with specified capacity - #capacity: Nat; - // initialize with given elements, and additional capacity - #array: [X]; -}; +public type IndexedBuf = Buf.IndexedBuf; -// Create a Buf instance, represented as an ArrayBuf instance -public class Make (init:InitArg) : Buf { - var buf : ArrayBuf = switch init - { - case (#arrayBuf(buf)) buf; - case (#empty) - { // 0 is "most conservative" on initial size: - array = Array_init(0, null); - var count = 0; - }; - case (#capacity(initCapacity)) - { - array = Array_init(initCapacity, null); - var count = 0; - }; - case (#array(array_)) - { - // allocate new buffer, - let newBuf = { - array = Array_init(array_.len() * 2, null); - var count = array_.len() - }; - // initialize via immutable array arg - for (i in array_.keys()) { - newBuf.array[i] := ?(array_[i]) - }; - newBuf - }; - }; +/* +Create an IndexedBuf, represented internally by an mutable array. - public func add(x:X) { - if (buf.count < buf.array.len()) { - Option.assertNullAny(buf.array[buf.count]); - buf.array[buf.count] := ?x; - buf.count += 1; - } else { - // todo: grow - P.nyi() - } +The argument `initCapacity` gives the initial capacity. Under the +interface, the mutable array grows by doubling when this initial +capacity is exhausted. +*/ +public class ArrayBufObj (initCapacity : Nat) : IndexedBuf { + var count : Nat = 0; + var elems : [var X] = [var]; // initially empty; allocated upon first `add` + + public func add(elem : X) { + if (count == elems.len()) { + let size = + if (count == 0) + initCapacity + else + 2 * elems.len(); + let elems2 = Array_init(size, elem); + for (i in elems.keys()) { + elems2[i] := elems[i]; + }; + elems := elems2; + }; + elems[count] := elem; + count += 1; }; - public func addBuf(b:Buf) { + public func addBuf(b:Buf.Buf) { for (x in b.iter()) { add(x) } }; public func len() : Nat = - buf.count; + count; - public func clear() { - // clear away elements, but do not reallocate - for (x in buf.array.keys()) { - buf.array[x] := null - }; - buf.count := 0 - }; + public func clear() = + count := 0; - public func clone() : Buf { - /** Blocked: See issue 871 */ - P.nyi() + public func clone() : IndexedBuf { + let c = ArrayBufObj(initCapacity); + for (elem in iter()) { c.add(elem) }; + c }; - public func iter() : Iter = - // todo - P.nyi(); + public func iter() : Iter = object { + var pos = 0; + public func next() : ?X { + if (pos == count) { null } else { + let elem = ?elems[pos]; + pos += 1; + elem + } + } + }; public func array() : [X] = // immutable clone of array Array_tabulate( - buf.array.len(), - func(x: Nat): X { - Option.unwrap(buf.array[x]) - }); + elems.len(), + func(x: Nat): X { elems[x] } + ); public func mutArray() : [var X] = { - /** Blocked: See issue 871 */ - P.nyi() + if (count == 0) { [var] } else { + let a = Array_init(count, elems[0]); + for (i in elems.keys()) { + a[i] := elems[i] + }; + a + } }; - public func arrayBuf() : ArrayBuf - = buf; + public func arrayBuf() : ArrayBuf { + // overcome common field names between source/target objects: + let e = elems; + let c = count; + { var elems = e; + var count = c } + }; + + public func get(offset : Nat) : X { + elems[offset] + }; + + public func getOpt(offset : Nat) : ?X { + if (offset < count) { + ?elems[offset] + } + else { + null + } + }; + + public func set(offset : Nat, elem : X) { + elems[offset] := elem; + }; + + public func getEnd(offset : Nat) : X { + elems[count - offset] + }; + + public func getEndOpt(offset : Nat) : ?X { + if (count > offset) { ?elems[count - offset] } + else { null } + }; + + public func setEnd(offset : Nat, elem : X) { + elems[count - offset] := elem; + }; }; } diff --git a/stdlib/buf.mo b/stdlib/buf.mo index 357bff94aba..e85ba9ad756 100644 --- a/stdlib/buf.mo +++ b/stdlib/buf.mo @@ -7,7 +7,7 @@ This module defines common types for buffers that grow, with a general element t Implementations of these types are/will be defined elsewhere. -### Why? +### Why? Motoko applications expose interfaces that use arrays of general (user-defined) elements to represent sets, sequences and maps of application-specific @@ -22,7 +22,7 @@ focus here. ### Define `Buf` object type -A "buffer" is a mutable sequence that grows, either one element at a time, or one (second) buffer at time. +A "buffer" is a mutable sequence that grows, either one element at a time, or one (second) buffer at time. The only way to access elements is with iteration, or by producing an array (either mutable or immutable). @@ -38,7 +38,7 @@ public type Buf = { len: () -> Nat; clear: () -> (); clone: () -> Buf; // copies do not interfere across future mutations - + // elim forms for accessing elements: iter: () -> Iter; array: () -> [X]; @@ -46,42 +46,37 @@ public type Buf = { arrayBuf: () -> ArrayBuf; // can expose _spare capacity_, if any }; -// A type that can represent and implement Buf; See [`ArrayBuf`](arrayBuf.mo) for details. +/* + A type that can represent and implement Buf; See [`ArrayBuf`](arrayBuf.mo) for details. + + invariants: + 1. the first `count` elements are "filled" in the `elems` array; + 2. any remaining slots in `elems` contain a default value of type `X`. +*/ public type ArrayBuf = { - array: [var ?X]; + var elems: [var X]; var count: Nat; }; /** -#### Terminology: - -The buffer abstraction `Buf.Buf` says `len()` for the value tracked -(interrnally) by the `count` field of `ArrayBuf`. -We say `count`, and not `len`, to avoid confusion with the `len()` -method of field `array`, which gives the _capacity_ of the buffer's -current array, but not its current (growable) "length" within that -array. - -*/ - -/** +### Define `IndexedBuf` object type -Based on this type, we define subtypes with more features below. - -### Define `RamBuf` object type - -In its subtypes, a more general version of the buffer abstraction permits some **random access** of its elements, independent of iteration or producing an auxiliary array. +A more general version of `Buf` that permits **indexed-based random +access** of its elements, independent of iteration or producing an +auxiliary array. ##### Addressing accesses and updates By default, to _address_ an element for access, we use an offset from -the start of the buffer, beginning at zero. Additionally, the -abstraction provides access by a (zero-based) offset from the end. +the start of the buffer, beginning at zero. + +Additionally, the abstraction provides access by a (zero-based) offset +from the end (via `getEnd` and `setEnd`). */ -type RamBuf = { +public type IndexedBuf = { // intro forms: add and addBuf add: X -> (); addBuf: Buf -> (); @@ -89,25 +84,27 @@ type RamBuf = { // utilities: len: () -> Nat; clear: () -> (); - clone: () -> Buf; // copies do not interfere across future mutations - + clone: () -> IndexedBuf; // copies do not interfere across future mutations + // elim forms for accessing elements: iter: () -> Iter; array: () -> [X]; - mutArray: () -> [var X]; // bikeshed decision: `varArray` instead? - arrayBuf: () -> ArrayBuf; // can expose _spare capacity_, if any + mutArray: () -> [var X]; + arrayBuf: () -> ArrayBuf; // get/set via an offset from the start, beginning at zero. - get : Nat -> ?X; - set : (Nat, X) -> ?X; // returns old elem, if any + get : Nat -> X; // out-of-bounds access traps (as with ordinary arrays) + getOpt : Nat -> ?X; // `null` means "out of bounds" + set : (Nat, X) -> (); // get/set via an offset from the end, beginning at zero. - getEnd : Nat -> ?X; - setEnd : (Nat, X) -> ?X; + getEnd : Nat -> X; // out-of-bounds access traps (as with ordinary arrays) + getEndOpt : Nat -> ?X; // `null` means "out of bounds" + setEnd : (Nat, X) -> (); }; // assert that two types are related by subtyping, without having instances: -func _assertSubtypes(ramBuf:RamBuf) : Buf = ramBuf; +func _assertSubtypes(ramBuf:IndexedBuf) : Buf = ramBuf; // (alternatively, we could have a way to "append" object types, as with `+` on Rust traits.) } From 7e5416741c9c9b593587d63343a4612844d34e51 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Wed, 20 Nov 2019 15:00:11 -0700 Subject: [PATCH 0675/1176] fix type errors --- stdlib/array.mo | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stdlib/array.mo b/stdlib/array.mo index 11df7eef039..dc7c0aafd25 100644 --- a/stdlib/array.mo +++ b/stdlib/array.mo @@ -119,9 +119,9 @@ module { ys; }; - public func Array_tabulate_mut(len : Nat, gen : Nat -> T) : [var T] { - if (len == 0) { return [] }; - let xs = Array_init(len, gen 0); + public func Array_tabulate_mut(len : Nat, gen : Nat -> A) : [var A] { + if (len == 0) { return [var] }; + let xs = Array_init(len, gen 0); for (i in range(1,len)) { xs[i] := gen i; }; From f9093293d02eaba4c779b7509bc4e0ed33f937d2 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Wed, 20 Nov 2019 15:07:03 -0700 Subject: [PATCH 0676/1176] fix test --- stdlib/arrayBuf.mo | 12 ++++++------ stdlib/arrayBufTest.mo | 14 +++++++------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/stdlib/arrayBuf.mo b/stdlib/arrayBuf.mo index 1a2b431f795..ba37c499c6b 100644 --- a/stdlib/arrayBuf.mo +++ b/stdlib/arrayBuf.mo @@ -1,5 +1,5 @@ import P "prelude.mo"; -import Buf "buf.mo"; +import B "buf.mo"; import Option "option.mo"; module { @@ -14,8 +14,8 @@ See [buffer documentation](buf.mo) for more. */ // re-export types and use them below. -public type ArrayBuf = Buf.ArrayBuf; -public type IndexedBuf = Buf.IndexedBuf; +public type ArrayBuf = B.ArrayBuf; +public type IndexedBuf = B.IndexedBuf; /* Create an IndexedBuf, represented internally by an mutable array. @@ -24,7 +24,7 @@ The argument `initCapacity` gives the initial capacity. Under the interface, the mutable array grows by doubling when this initial capacity is exhausted. */ -public class ArrayBufObj (initCapacity : Nat) : IndexedBuf { +public class Buf (initCapacity : Nat) : IndexedBuf { var count : Nat = 0; var elems : [var X] = [var]; // initially empty; allocated upon first `add` @@ -45,7 +45,7 @@ public class ArrayBufObj (initCapacity : Nat) : IndexedBuf { count += 1; }; - public func addBuf(b:Buf.Buf) { + public func addBuf(b:B.Buf) { for (x in b.iter()) { add(x) } }; @@ -56,7 +56,7 @@ public class ArrayBufObj (initCapacity : Nat) : IndexedBuf { count := 0; public func clone() : IndexedBuf { - let c = ArrayBufObj(initCapacity); + let c = Buf(initCapacity); for (elem in iter()) { c.add(elem) }; c }; diff --git a/stdlib/arrayBufTest.mo b/stdlib/arrayBufTest.mo index 0906b9d55db..7c1b7e600e7 100644 --- a/stdlib/arrayBufTest.mo +++ b/stdlib/arrayBufTest.mo @@ -1,10 +1,10 @@ import ArrayBuf "arrayBuf.mo"; -let a = ArrayBuf.Make(#empty); -let b = ArrayBuf.Make(#capacity(1000)); -let c1 = ArrayBuf.Make(#arrayBuf(a.arrayBuf())); -let c2 = ArrayBuf.Make(#arrayBuf(b.arrayBuf())); -let d1 = ArrayBuf.Make(#array([1,2,3])); -let d2 = ArrayBuf.Make(#array(a.array())); +let a = ArrayBuf.Buf(3); +for (i in range(0, 123)) { + a.add(i); +}; +for (i in range(0, 123)) { + assert (a.get(i) == i); +} -// todo: assert stuff here about the variables defined above From 542e296209b04b227c03acd5217ec321613d07df Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Wed, 20 Nov 2019 15:10:10 -0700 Subject: [PATCH 0677/1176] nit --- stdlib/buf.mo | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/stdlib/buf.mo b/stdlib/buf.mo index e85ba9ad756..041b8b6109a 100644 --- a/stdlib/buf.mo +++ b/stdlib/buf.mo @@ -104,7 +104,6 @@ public type IndexedBuf = { }; // assert that two types are related by subtyping, without having instances: -func _assertSubtypes(ramBuf:IndexedBuf) : Buf = ramBuf; -// (alternatively, we could have a way to "append" object types, as with `+` on Rust traits.) +func _assertSubtypes(b:IndexedBuf) : Buf = b; } From 9405cb1ee59b27cbeedaf8d2f8028a591e5d945c Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Wed, 20 Nov 2019 15:14:26 -0700 Subject: [PATCH 0678/1176] nits --- stdlib/buf.mo | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/stdlib/buf.mo b/stdlib/buf.mo index 041b8b6109a..b6437aa03df 100644 --- a/stdlib/buf.mo +++ b/stdlib/buf.mo @@ -42,12 +42,14 @@ public type Buf = { // elim forms for accessing elements: iter: () -> Iter; array: () -> [X]; - mutArray: () -> [var X]; // bikeshed decision: `varArray` instead? - arrayBuf: () -> ArrayBuf; // can expose _spare capacity_, if any + mutArray: () -> [var X]; + arrayBuf: () -> ArrayBuf; }; /* - A type that can represent and implement Buf; See [`ArrayBuf`](arrayBuf.mo) for details. + A concrete representation of a growable buffer. + + See [`ArrayBuf`](arrayBuf.mo) for details. invariants: 1. the first `count` elements are "filled" in the `elems` array; From 57142bd6c0363600f6033bf904e83becdc23dc3a Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Wed, 20 Nov 2019 17:12:30 -0700 Subject: [PATCH 0679/1176] unused import --- stdlib/arrayBuf.mo | 1 - 1 file changed, 1 deletion(-) diff --git a/stdlib/arrayBuf.mo b/stdlib/arrayBuf.mo index ba37c499c6b..ada76ed668a 100644 --- a/stdlib/arrayBuf.mo +++ b/stdlib/arrayBuf.mo @@ -1,6 +1,5 @@ import P "prelude.mo"; import B "buf.mo"; -import Option "option.mo"; module { /** From dece039f2277e139a9116f8af848f86ed71c8ea9 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 20 Nov 2019 14:48:02 +0100 Subject: [PATCH 0680/1176] IC Stub/Backend: Create canister MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to support patterns useful for and used in the Motoko test suite, the IC stub gains some extra features that are not spec’ed or implemented in the official client. These are: * The ability to create calls from `canister_init`. * The ability to create additional canisters, in a way where the creating canisters learns the id of the created canister synchronously, and can send messages to it right away. The interface for that is ic.create_canister : (mod_src : i32, mod_size : i32, arg_src : i32, arg_size : i32) -> (idx : i32) ic.created_canister_id_size : (idx : i32) -> (size : i32) ic.created_canister_id_copy : (idx : i32, dst : i32, offset : i32, size : i32) -> () where the `idx` is only valid within the same function invokation. --- ic-stub/.hlint.yaml | 1 + ic-stub/README.md | 21 ++++ ic-stub/ic-stub.cabal | 1 + ic-stub/loop.c | 5 + ic-stub/loop.wasm | Bin 0 -> 295 bytes ic-stub/print.mo | 1 + ic-stub/print.wasm | Bin 0 -> 51147 bytes ic-stub/src/IC/Canister.hs | 15 +-- ic-stub/src/IC/Canister/Imp.hs | 101 +++++++++++---- ic-stub/src/IC/Canister/Interface.hs | 13 +- ic-stub/src/IC/Canister/Persisted.hs | 9 +- ic-stub/src/IC/Canister/Pure.hs | 6 +- ic-stub/src/IC/Id.hs | 14 +++ ic-stub/src/IC/Stub.hs | 117 ++++++++++++------ ic-stub/src/IC/Types.hs | 6 + ic-stub/src/IC/Wasm/Imports.hs | 40 ++++++ ic-stub/src/ic-stub-run.hs | 15 ++- src/codegen/compile.ml | 81 +++++++++--- src/mo_frontend/typing.ml | 2 +- test/run-stub/actor-creation.mo | 21 ++++ .../run-stub/ok/actor-creation.ic-stub-run.ok | 22 ++++ test/run-stub/ok/actor-creation.run-ir.ok | 9 ++ test/run-stub/ok/actor-creation.run-low.ok | 9 ++ test/run-stub/ok/actor-creation.run.ok | 9 ++ test/run-stub/ok/counter.ic-stub-run.ok | 2 + test/run-stub/ok/data-params.ic-stub-run.ok | 2 + .../ok/hello-world-async.ic-stub-run.ok | 2 + .../ok/hello-world-return.ic-stub-run.ok | 2 + test/run-stub/ok/ic-calls.ic-stub-run.ok | 2 + test/run-stub/ok/idl-any.ic-stub-run.ok | 2 + test/run-stub/ok/idl-bad.ic-stub-run.ok | 2 + .../ok/idl-field-escape.ic-stub-run.ok | 2 + test/run-stub/ok/idl-nary.ic-stub-run.ok | 2 + test/run-stub/ok/idl-nat-int.ic-stub-run.ok | 2 + test/run-stub/ok/idl-option.ic-stub-run.ok | 2 + test/run-stub/ok/idl-pair.ic-stub-run.ok | 2 + test/run-stub/ok/idl-record.ic-stub-run.ok | 2 + test/run-stub/ok/idl-tuple.ic-stub-run.ok | 2 + test/run-stub/ok/idl-unit.ic-stub-run.ok | 2 + test/run-stub/ok/idl-variant.ic-stub-run.ok | 2 + test/run-stub/ok/idl-vector.ic-stub-run.ok | 2 + .../ok/print-from-init.ic-stub-run.ok | 2 + test/run-stub/ok/query.ic-stub-run.ok | 2 + test/run-stub/ok/reject.ic-stub-run.ok | 2 + test/run-stub/ok/reversi.ic-stub-run.ok | 2 + test/run-stub/ok/self-calls.ic-stub-run.ok | 2 + test/run-stub/ok/transpose.ic-stub-run.ok | 2 + test/run-stub/ok/unsupported.comp.ok | 4 - 48 files changed, 456 insertions(+), 112 deletions(-) create mode 100644 ic-stub/loop.c create mode 100755 ic-stub/loop.wasm create mode 100644 ic-stub/print.mo create mode 100644 ic-stub/print.wasm create mode 100644 ic-stub/src/IC/Id.hs create mode 100644 test/run-stub/actor-creation.mo create mode 100644 test/run-stub/ok/actor-creation.ic-stub-run.ok create mode 100644 test/run-stub/ok/actor-creation.run-ir.ok create mode 100644 test/run-stub/ok/actor-creation.run-low.ok create mode 100644 test/run-stub/ok/actor-creation.run.ok diff --git a/ic-stub/.hlint.yaml b/ic-stub/.hlint.yaml index f62b394038b..7486ac8efa3 100644 --- a/ic-stub/.hlint.yaml +++ b/ic-stub/.hlint.yaml @@ -3,3 +3,4 @@ - ignore: {name: "Avoid lambda"} - ignore: {name: "Use camelCase"} - ignore: {name: "Eta reduce"} +- ignore: {name: "Use >=>"} diff --git a/ic-stub/README.md b/ic-stub/README.md index c970cd85885..6b7c12eaacd 100644 --- a/ic-stub/README.md +++ b/ic-stub/README.md @@ -17,6 +17,27 @@ This is neither complete nor authoritative. Since this is primarily meant for testing the output of Motoko, code paths not exercised by Motoko may not be present; in particular, error handling and input validation is incomplete. +Extra features +-------------- + +In order to support patterns useful for and used in the Motoko test suite, the +IC stub has some extra features that are not spec’ed or implemented in the +official client. These are: + + * The ability to create calls from `canister_init`. + + * The ability to create additional canisters, in a way where the creating + canisters learns the id of the created canister synchronously, and can send + messages to it right away. + + The interface for that is + + ic.create_canister : (mod_src : i32, mod_size : i32, arg_src : i32, arg_size : i32) -> (idx : i32) + ic.created_canister_id_size : (idx : i32) -> (size : i32) + ic.created_canister_id_copy : (idx : i32, dst : i32, offset : i32, size : i32) -> () + + where the `idx` is only valid within the same function invokation. + Installation of `ic-stub-run` ----------------------------- diff --git a/ic-stub/ic-stub.cabal b/ic-stub/ic-stub.cabal index 81e96705bb0..f5e2ed427f7 100644 --- a/ic-stub/ic-stub.cabal +++ b/ic-stub/ic-stub.cabal @@ -15,6 +15,7 @@ executable ic-stub-run other-modules: IC.Stub other-modules: IC.Types other-modules: IC.Canister + other-modules: IC.Id other-modules: IC.Canister.Imp other-modules: IC.Canister.Interface other-modules: IC.Canister.Pure diff --git a/ic-stub/loop.c b/ic-stub/loop.c new file mode 100644 index 00000000000..2a0c8f36876 --- /dev/null +++ b/ic-stub/loop.c @@ -0,0 +1,5 @@ +unsigned int i; +void canister_init () { +i = 1024*1024; +while (i--) {}; +} diff --git a/ic-stub/loop.wasm b/ic-stub/loop.wasm new file mode 100755 index 0000000000000000000000000000000000000000..9fb34a22b3abbd13c7086c9c21ea6546ae180542 GIT binary patch literal 295 zcmZ9Fy-ve09K`>Bf25^u1q)(B_Ev^eEmiqgP(APfhzBrkVnKkoQJf;W5DyF;c_bc< zAYkE^JN@pY0~<;N0AzRvKnVilSRo>(2qZbAE$WXQ6D|DNdtdYxEGb>NuD1k)F%QmG zW@Uq;I4~x+jWy2al#DX#i_o~*6uxKx2Df;Fy;jHg2?{hQlqlhh#9fR)mUP)6BFXp% zD5_h> literal 0 HcmV?d00001 diff --git a/ic-stub/print.mo b/ic-stub/print.mo new file mode 100644 index 00000000000..66a86a75b0b --- /dev/null +++ b/ic-stub/print.mo @@ -0,0 +1 @@ +debugPrint "Hi\n"; diff --git a/ic-stub/print.wasm b/ic-stub/print.wasm new file mode 100644 index 0000000000000000000000000000000000000000..23e892104e49577ea9fe6d11149c0d908e63a1b6 GIT binary patch literal 51147 zcmdUY37jNVeSf{GzN>quW|v)HcY*2#lQjY|v%|0$#H}&Qse%z>5>1BQnciitp4sl6 z-C45i3^&LjmlukFpdg2U$|>q{dnK9}^Utj@cQoqXBWf=G-|z3es;)j}*wH1Q{1;}r z>ecW4-tT_D_j|8;ta5!yS(c?fb>YH-<)3TM&s*oJy=wm4#NK&cJNUqFxwg=(=Jl_= z1eHtc+ytHiD9I1DS-JzR?7e%{Uj3Y~d#!UL95RxD#E|IUjz$l_p=BH(62k0xpb=OZ z%Kr8OC{HIxD_du`CueG7)rMs`Q}ykIa&7zYXt_}yu8*Bxu~ci@$n?x^%Vt}$R+*XH zZ8^M7)hgqak%qp>Rcf{A+VIHqD0JOkX1UxWc4wNu%=m9YwiOza;dX{BQK z%ef??=*R8Sv(Qt(KR(E&QrS!f1Ep4Qv{WjApO$}kydslHrxjY$^28t{g_f1b=e>NY zC((1zK`U3UTGQLRYSqe>tJfTS$iauM#TEXoTeoig`a_%l&~)g^m3StP0ls$a+BJu= z+hK>TTX#4C*RDErE&fC6nnPEvUA6XbfJpn{hab8MkI{ea+9MK|Q(tOE{X70kUMx43 zoqC8DnRyj_@4p`T@dYj}EdE+pNVt2|kX*O?vVwhIOt|UW*v%=7l&fR)Mx{19Rvl|t z&qLRhDcedm%3CKZ%E~}t3)W}s>}}MXZ3P4Fb1I$5=G=T?MUU6Ja@9fP{m`}R)*p8G z5q`0Bf`$QHx3*>c*3R=U-PRcz4qkSZ4QQB|7%-LIrX&D z&p7i9Z+z2PXTSN^-*V1df8%Yx`CGsJ_ILcw?+%|^-a0Z`*|z<>vGIw?sp|C1j#|Aj zyK~pv?(=_d&jowu7u1F7B6YF4L|v*bQMC`$x<*~A-leWn*Q*=Ujp`=# zZuK7ZUiCipes#0@fcl`iMSV!!s%}%as}HL?)Sc=h>Z9r|b+`JMx<}os?o;=xkE;jN zgX$sm3H3?!DfO^=L_Mk=Q;(}B)Th;x>ND!I>T_zJdP+U5o>9-L=hXA+1@(FL1@%Ss zC1nLaQ?B|WmHX_+E~0&3L!nu|6*%KTqUv3u+-t*@?6_}ju#;ZOy;7Qj7eANqGM2gX zEnj&l%l!H&j&WB0D{z@tpINg+5j#(zAC1D$4}!nND?9w;9B{a;9*6OOkfY%SwG`D zgLVNQxa;*Z#bl5ma5eyt^5r9mkAJ@Br#}E-*3bG$!e>h<_d*6owFCh`b@`%HJaK@i zxKG4jL!L!j)9z?So#06s!XYbJhyolIe8*j)!)KP;;j_!_@VVu7*tgsc&n&mYbIa}U z!g4!&VYwZ?wA>C~?b_j8Vj4=D#(SR8B^OkG5YyCuz`v3>Gk&Eo*@ZLSD>ZN&M2-TXgyH{YHJra#2696zY$53SGp#M~nNe zz!q8mQ@b=Cd ze^GvNDU`Rzc#r1DK+OeemUjCs(!(p^H50vO@*YOI<~y&kvfwOO@YraZ#^7~309JdAmGe1m zq;>}Tc&8y35(IVHLER9vwQqiB@J-zpX^|c>!k%yMqH&;0D~^>rgYOFt*9C-owP;Dt z3}bY`=ImLrgBM?XF7baQaX+sBQ5PA*!4PP@sl7GuFajR5jNowuPmjl4xAs+jWACZTW1JCZ%_`y-(+hk{}^1o`0BeF-jxM%{;_ zr_i5}JWrC7fRn6fKDg?cL^62qGYK%k?w*Sj>@m!j+J#O2_U&h|wn3kLR^SD98RP)# zi5X#(!oAk3bZb7bd-L(#oBO&qALDK7hWnM>n_tnrx!ApV$lKlx_bJ_*&*6^R7aFLT!_c{6 z7QeH_41Obx{*!QM4$1-9_~&7x?S`${VBxVNF2*Jm#&nCi0 z!B@};6$QrPzZ6{o*e+oj@soNa)B*kxFrP+MA^0IMD+~pSu<+O!Yr!p>LxA8#p+#B^ zU5NKjijHz{&*xB1fDXm~yfvkiPfpuR!Yp233StE`4Xu+HCtR&)1~VmB%gm+BazDevd}yk<~ZK@0+x7*r?`vkG#8JEUjH>2Y5O8F-+DfrDRm z20;I(4gCj-mwy*+XW%ffx)l!k^v37x_e z55I!7VwAJ!ua>mG-&(HyeHZq(w42-%)7x^~XB|G$$=tFg37=JN+qGJh7Nd*C0SI+ ztPxz9Sz7^ihwbrF@)*lPy2wi4e1PmAg&G|$@p;6KAl2~kT%iV6TN}V4Qb>FB!=9Fh z2GG`k4gu4P0vKRN17n78K?m&FVSevOe$VaaW>ii{R8F*QE-)mOly{4Azb*d3M1YxK zLT6}+;430ebY>=q51oRy#4hf?CVa%PUTjb+_zU{mdZSrBkYY49njtvC+wR>mo=(v+ z6bF*JhVd^I+tGs%n5FWF94}17?41bj(1q*%ov6sTHCkA@lUY*o8{bCLS(4po z(j(6$i7?8$Mmn8R+Y$1q5rD&tFTe}=l zu$G(>-?H2(@!OF6Hz{9avd-T2^cZE#ecZ-GHS_XIcVD2hJ3XYGo?nt%PzRmz5ZEwKUg9yTP`n4;c_3-wul<-*`Oc(3yP7G z3(G_53UE-eeS0s)q!3~)d*OF4mFr)4;B);SEg=~9TB9*+7lYW&1RAX)Se zmm(=lmFd2qDzJCn4_UsF{`*-GJ#$vGBgpXSa3QnLdZUzrUU*6uJS@a1>CXihwhZrs zn!LYND zYgo;FBeXdLWA_6xteOupSY&x=lo3#U5u4Jp(^A!gH!n9%{R>R&r6S5j2i|>`j409B zHcq)FS?2KPG1vyd{ubp>)bDE2*G8_nnalMv?A(|8msR6}})C?ZLTq(=ERHs*{ zIl{!lLxmSf3DOg03wqVltJB%lP$YH^Wjm;tf|p{~LywL@bqSe=yA3-x>n!%_KB7b#=qM_ZR41u7~f>LR75iP- z8cN_yC7aeDN7_p80KMyk0BK`SC84*4U`sz|w=aq9tumuI9JCikhmX~;I}uO2-DzuF zp_d|2vG}`^5BKV&h*XISey_iR>yF+c3eLVq8{v*wu}61ZrB^Ylg6~P!Rl4gcePnbM zZK~H_Ra^<1T8XYri=i8ovU)2k3w)*3_@xaVzTx8zTaz@ka4Qt0DlWha0PD2O*q&JF zAVEZvAtKym^)^|A$Zqb6#ZA0v!|o#@PfX=`z0fjIK>HlG;3W;o>iNQN+bR^5PY^_#rP|iHjF`ag1*lE$;oxiY!>ESAjAz4q{O3 z*pDF~4&;U-JK@MqII*fLy!Uxj8Yah!c|Pz_=>{syxkQDN z4GJ64B6^3Sht-Pc6Grr|7CkIC{!EJ=$975LBK<`4P5{w&;uO&@(oaOs6Bn2XtYQwd zV#8Eu^>Y+`D>fe+z~jZ7mKi28A&8yZQV0})W1@H3iNY2!&`9!-^xZ&24;rvV3>s3P z0jUOQNEy+0B0x=ZyqIbcJr<6k=yjC|^DuKg{6g+A!E{erc!TXYvt#EytGwrw3-?>V zj$InPGKI1&OE)Ix$b7fq9lyu919*=W{#;%OT z+Q}Pku^8xNFFVoXkTBp5lL-=RGm7E!Qn4KG_mz8xTm?UU4s4CfhXr~pxyp>=wVpuk z&Cyq>FJ|&-t5eB3HZ9-P)Kq31Wc2o0?sFm#*sJo{2birOy|ZLQ4~kx6DLz9f z9p_^yOHhnvh}9+_Hp+ZQL@Rr&008WZ){YR@K5Lv+cu`~=4TqU68BmO%(c-;2fj>(y zeqU&FSnY=q6>WR7y_x#*F64=@&7y4I*;24w-URExC*859F!tmeQ8GjMar1hx-$l#;MKc**yzQ#pJB z!=K_OkoMq(vvt&!H14x@AR?u3T2>%h2`phJ1I?O5q)0gM*9a^>wGL>HICGtE*9_H$ z(l`fSz^PVC<>pB#1ay%dJbT0S-%3Ctq#r*ZyU9ZmK#&{g-2%FJqlK5G@NBN8DLkiv zdIAC@jS&Rn#Gwce;IQ#G6fBMeD*_Nd6VMqR*bVOwc!rfvgiCc=fzw+WisQ*vy8(-4 zc)%(fKNR6 z99vmQo+pmvu-|-~T7W-y5-*MWPrSWZjI0~^r$Jya(bEdA(7tgMc0a^Xem-jR-Kdqu z1552u9n?CIFP8xlGva2SZ#Vlw%rd^t#?Iopo1f==%c;`#U#6u~rmrF9m zWl83ccFBOY{ge!Cm(|{;=b8y{T|3V8F`N?i+arOc=e>-ixj&E0Pc0nY%>qQCP(WKG=tYE*@h-OWhwGpbPprO+O`7&BE1tW=r{s?IIHE3jPeatJ2Jb)g0lUxg%KRRe)+^I{6@l5j#Z#Tu;;Siry2(fpuTw_poBNaN zxX#L;eh_#QrNmLPCT(W+%`0&K_ZAW=-Ga69{28(^v4dV5ZwkEjB|&mUZ!(WH0agVr zf3UriPr98XAq z8L3YCP-bJWKuOr&pv7JDh8^ z!zkH^o#nBD)j%gJE7(YH*gsYzbJJ0Sh5@Hsp2WM@cM1Fbrxb7q0U|>EmLhT~A{QcB z9f_#jE8}94!caU`pf(bTDJqA=VujW`UXO-DQ8{$;lx>0!G!{pgGL@!O7<>?Q=(Q4j zcy5RsBr-=2Pb8ALX1uN@~2# zDGNnr;~=n{gki30m|c>&ZjwU5)}6PKBff7+<|<$%AJZqkV@$ECM~-J zvP#HEdSg_A=>>G*UiUrZ+5@GrdXRg#~71cnM&8O3y<1WSHJ$QGJ&5 zCRx*yqHN48p5}f{_E)eYr+jM?dofFH%W?a~x0s#TMFm+P2Z`+mK}X{y?wVn5#r>|? zQ(}i;j=5lv!%l?U?i$CQRtX!BRta0L+%vHCxU$!UlXKie2)6?X=41Pc+ag))_4&Ay zy)|s$qBr+@ki~o1=vbX>9pdfe;2=2`3Osn1mILG1G5UL#a$k$^SUOqWRoEcYyN&zZ zr;T5y8@XdRUFRp?zDpemDG@W0Fiv}>N2?MS-*m>>-de_=T z;v=y@Wxb&QVf)quxQ3ju^Ad6$C**qb2FGHAJjK-rD7oHHB8Oyceu)`I5_*Le17?V! zyl=2$svol6R=^ix`t}7N#vYn~8*mzg%ai@PmM{D3*ahpaQ1+r!@16D*{Z$@d4pI*r zgCll!ZMM$n+N@5CUTKLV!Iwe;kA54$Sd~rdG*)F(%?_+e^kfD{vUM37j98Z4`SM?+ z^A)kqUvJtP4sjUE6h~-Uoq}Z+?N)cu&Jt$}bq4Q!#Efr&q4$Jmvv6P zpd#_WI@NqJ&wiN?!6$(3W)~;$&dlO=gDQPq}IsISc6J! z0b$`$4$Ts>Oj3*`JdIS~b_jR81B1jK^2jE`W-4HQhcDjP$+a^W4wt(=EDGY#(Gp*~ zLNnktJOy+)asfx2Y;ieYMCuU<*h3}=(AnV4B_#zq9Kw;#e-Y-&@IRO?Q!a%QLv9%H zqFy-9#heSZy*HY!KWuiDR1IG>V3}_$P*|4;tRB*y@D;K<8SpB+mck7n9}a@kNf^+* zOLUfOhABMb8K~d_nt-T+)+QE*j1Z&)z&S;{#TvBoP-Y%Z1L;_D#F4i}oTgAkm>HPC zDI3%f5XJ;U3U3X`E59`yY~1&hgYW*k5X%IVQ30L`4&PB=@z~xBd1M-p7BJW~pxAfe zGkD>5;lhj3Of~U+;QLO(`JF9D#~kUnux|j14TdX@P(t#l{-x>nyg@wckJYD1d87?j4wSa>LGk8M@%F2{@BuMWYpaV?H_C5dyBM>a_ zgD6w$=cwjp@D!llEqLDAhFN*ljp{Wbp+boHXT?=J+0zpS8Z@z5hA} zac=|>V%0q#jM~w29L|GM{)-MO`x-O8$?qWz5#4_R_Y@zFQJpGNYhazRgWM+F=R`wT zenDMyLis>Nj!Y(Cs6sog^F@n+DFniqED*!>7FGoq8pj`>Fqm}T44jsdV}T3r7s9^O zDeFYXxDrD~nEoKOs&%ek1~Xq%f&~a7p#w}jO36##Hm6t>zhV;0QPRq@o^VtLA^-%= z-tE)}EDaOD%$+G`S-kO99Z8jXBi z`hqjpl^`NgL$L>YeS1Qvr5tSP0A>equ5Z+$Lz{?llmoj2d#D-KBoKmc5F6HC{SuSu z+3hmDYjL3tt-qp#wbrl8sv0EFYC7Z!A<(cxxypHCZ7D`YdS%`w*S%Vgr?>)s(WVHH?XkWo{v@+B4cUOxU+4CsWSff#8E4rMzOlkFZf?pai} zL$EQ())`uVnQt9$TbGDI!L^_#%9b%YE?dXF8DA-8*&c>I(uUJV`*0E#Am9r^_lEI= zF-_(H)I*?2`aT8e-JyLG@f>09N}J6IOwO2Bzzoizd$-{`{~!?A-(tg{U}2dLlQbWJ zaV~Pg%iuWlMfMln`&f^fdklmpuxWX^M zw3+2V_C%~vy%RG4XIb=ogO7|9&PQ43EFl7u4#-L5&@0}#GD8=hM1ywro!Z$;19Eb`0Yr9s6|duivXNy~mXcGQJE0?)mER2btRa6qkm>V&0@x{7La62g)N*MEQg(4-M;ro-ZEa01& z8K!!2^jkR5F-6w?CaQov2hg&Is@>ZAu5lRA%|G+TyULFdsnKWN7i7-?Q|Y5}nbl`1g{y+D+>5E_7>O;D-`eY66kO6Y*WkbI#j zvVx>mG>F&aYb$`=$yar0^>fn`;YCgj3p}P$%9P1i+`aJKochR=SV816N9;uJ3_T}9 z+BuFdq|xW(eHeqZJGxdp%p*!^g9ogTjuM0iu|TO|CZP#w$@oL1ViB4&e@RMSsFJA1 zbtaq&%!4|kJ-Y#!+YRrp@y(vlh}0KoRL~>9Vc2j}W)YZ3DF(4FFvj>;1TBym!jU$z zh=o}6fcBdE5_(jw8w8C|z`@5w_h5{C>O(9Nfkb_wT^OUqT&TyxN>G0<3Rl$N0gMF> zssQ+kkR@s+{OSSlBm|>s@;t++ZDUP?rG+=K*2kA32}i!d1u825&7e@rRs?zsfxCox zq@`haiJDuQiN3XE;j;ekmls<*(0yf}zC=W0x@ox;_ zeM6ztqiNv>`2LzqLtNu>0GU5=0p~N0X450s6&~SGo^%L!l0-R7s{ppcNGRnjYC_&i z;(8L167ZD0yiCnE!NlN6Xz0qUorsMCB_uF`pitxi4m7N%61dnnrDovp6pSL0I7|q`M#u#@K}ky9L?WyQ>mdfn z5Pxj0ff9opf`lxJPy^^KrRgl7f~r9H#tuK{MEukB72`T66Ycanrle3`oi#SPhD0Sn>fB^6e=kvmcB+2T2I1$aH=nUz@EDBV@PqFgzQ+xfi ztowQ{-cw44D?ZYnMg@lJ%y2@7)ibEbghWEL8mL_S{lB}SES&O%<8oq^u%`QSKrNOC zAH)Jl(G?6smeHlr9!@eP+^-nzL1MI6QwPONMdcxrhiS-)5;{cEO7Y6Rer;8(O4|m^HaP)fm6uP!88-RoUd#X`#Dj;TCBnm^hbaLJ6f$ho zD6j-$GsNnrcNFPLEpcBb7sAsg;ufhr4LpczYXt*k$Sl;kep1&9z#m2zT_ZZ#Vk+XX zRnB4ph%yNhTqLXE>_{^c!WD>?yplbjNrgxb`hZa@02(7)Niizo5qN@TrPxVzP!<1q zDGXH~{{ALYD<<9)f~1Q`XPCvDv5vp_gOYS=O16<46sfpBq$^4p>W!9wBc-_TQC0H5 ziz6#F=JVbsk-f^Yfc>~Mpb7y3qzvQ^R-Tx4WG3Rw|~7;;TM;JSkh#$BG%mC zZ%c%?SYU@7qGE-GFQJgJ%XSaUz65upKLI_5Ujii*vu~3YS(QVo& ztDK)UlxDd=yE->R&<4BEmI@L#*n1$&v`NYtgCfn(h~{TP&6_MG z%D~x)%wTZ%v(N^lP;l0bS>fCor1KgTIJ zS133)Opu}lA#4xD*t3dU0VaGL!FGLoUzL$;NDOU~LczdslGsFoVw8v&-XSE4O>y5^ zs)$Wlw0S`!3s3^P1xorFja6GuCj zk)k;og-j|S?U>LxZd~XmEh+TlgoNXoV}lZ|!X>6a=sBNrMlL3Fl(LKgz)vI#26-_n z-~>Q&VswZUj$TsazR=-!h(bh8lueQA@I&i!=qe0{FnE1~-*gWrfIBrGfKUmtJPjhS zVYCtl3mZdkLsx*q^B9ifnDxM2hGf&jt+1Mk7_140F%t0C^jfKjo(W&flZB0lia6t7 zpY>Bso|c6kk`E$@gp8B>CU`jAh)|lq8jCz6lD1(Ds%EnmlkP-mN7U#C_#If@qale9 zCx+9|#2!I6n;r>aH6!~(kGO6QsgdZ%xNaiRL+Z!fY4IZLaY|Z{=m)}oOS`lz#8s?^ zLzB@^8#DTG3zxvbZ|~sDs8vRobl}Kbsas?i-4)7;R7k3_&3++yU37;(*cDUZ4nxd6^Sw@Q|*yNZlAspxn*tEXbC%K>F zK5z+bKh4~aiyt2P-78x%+=7oxUd@WhW2q26M1RpYmX$F2*aMJ3JAhrbwu9WR?cgyH z?8W)37Vr>vh=%uY8rVFlY;YKOk1S!aUO<+#n8R>87yFjUaEeX}+ET_?_#4FI(l3pG zgqJdc1*(R}pN$VBi70fy#VIHldn6jlO=N#Fd_cECXvQ}L2r@CA z5q}N|3eYW49~uig;ALKYAr?bR5I~++5B3J6flXo_>-OJ1jHQq}Z8P6AHuJNKVKa%W zoDq@38Vh)7Iy{q%lqjt8Fg8hP97W}@YOli{#D)OKQU^0As8WT-!6?lHO?I1%y0D-} zuo4T%4OvC5BJt%vxGDfoo@+2akBYD?22;F&W=b$-{4GVU-0_LnG=VRTM~uR?94eC% zP7Z55ElgN5`#Q-o2uz4^6!BKaJXzhkegR*s?Yn>? zMc51kXZV|o5J0eJ2M;2YT;J7bSQFyWhjG6UFG>|ylycbxr#fTSBj1Faj zR-Axgxlkrei2Zi>KfErKy%GJ3%|zwALplMvy;H?;;(7-O^wk59r(W3gMqhJig6 zyY&M`D&{Z}&UF(42k~`)A{eC@wz=qwfg^IYwwPO#4-hub)gLehITn2^#OQ9nO1z4?P z1pIYOnhMaq1K5*os9RB(eOVfN=uTSV2E$3PGM&Z2_6$kJf=n`J0tcn4XB1g|Q1K3@ z3O$oFl`4&Rgt=Va0*cp*T3cuWPJm=ZCJk9vhMn;!Y=z=vKn-e8LT#+?5KLZjBAPgu zOgYkMrX19Q^^`-x1eL}YO*tBaq%Z3vp_e&C*x+O$bm|L}l4$02Q#j>ligereW%5b5 zcX9HuIr$*`aN;rF*1_x)d4Npq$ndeb!%bp1P)e$w+Qcvw=((I#LsWh+Ib;J}sfIeB zI-7rA6(5pq@Zf;Fxt-IIS8OI<%yWJKV$0bK<6)o&Rx|&=5a}x=meFYJXokL_XT%s? z=ET{7aISG+dI(RlU(q_pM0quWjou-ILo70B;0v#5)+jKESu;s*XM|E*p93 zq#5Hh(J2}cr~oULDcr@U3P(>B2DWvoFq<2gD)3#GCSLuQOcic4RfMX-DGPnN8Z5x^m$bJx&pIHTZF&nTivqH}<49A%b?9ZYy zjVS`0$)E)Y0>=z3A3{W0up(X}=l3x~w<%8F_@aBA7kH@fS&(1S_gbeAP9T2I-aRER zJ~?@uobXp!8Ge%C6l(&&3Q-qoYIPYO6r8aRiu3N$YcU+Lgk#a1QQro`oHMZVnE@M6 z5e!q$7zqXrEc-ZPB%&FEr`xc!O}hHahxx_0W~zo%v6YC|45(bpMc@m;nA0K}c<2>v z8io}^ZaRTm9_T_NObc%sfETGRlMEE4&*G%0ZH|8jGs$_3sW1*c=`MNGB~K;E3Y1!x zDU^dVwGd(*b9^g2c7=p8B34LkAtYa7R5j-pEbQ6J^eLF!8)$Y|(}a4K$ppulB;Ukv zsF)x;*w|yE37H*p$^kY)mr4uPfT1oht_jnd~q_3;tX7dGReY z5<;kRF8)OInP8oM?;AqXF-WwZ;yD&tVo{DMgESdmnkZkA!x;)2wqeFbWit}U$#qcC zGFD6OM(((m3QD;Mbblb*bDd(Lje&E@#A%la4}>&j0?(oN=y3QR5>SDRm>wn5d0xJ& z$A|?78;n?XB80Bf`-lz`XguKu@^qxhMZRnZqQM806N-WygG+Au#l}Kc$lGZNLAoNM zJEM2VF%l@rTjjLD9khmoBdZn1!AzwpsbI63+Q~o-aQQBY*u@U{3;zkdooBh=c>{aDwaD&7F3k>!Tqc2c^a|B->b}6em%q4L@;$|&23wQ=V z4rEbIMRs$H`*7)Q&Hx3lINacn48%n@cf#`s=6sk=vwhA5(5nf{J??%TM7mHI315*y zWZ(pe1Do844qY0?hxmyH@E=Us-V=BaqM$U7=%M$l<%J2|OSH~E!OK&T;^+9LFBlxW zfrZ5o9+*CD>(eQhEJ6i|5vN?7n8%kxj2tW_A@gm7JZT7df(etZ@E}_f%Lkv5EkQ+y z#0-m=JitkqHBn0ZPrQI$2w54~1bTXgZqZlX1q4HUNl)iYQh-Ec#M=YVdj^(*$I%Y8 zIVl0}YHnF0@PJZ=6N-hiMmKysClyiz0m2;vrB8M;{NiAPlC(zthz`i&vDW6Pn<(){ zC{DqeaDo$Cy<`rrFW}F|gY!}bB(M~Uj6u%YKq7pu)yti045w*qN`e*yL;%D86U~Dn z%sR=C*cJ}(M1f2b0+Tm_hzMhv7f1-yYd{Lm%-}zj$t-1N@RwAdIT!+pjEV2J7GSuX zTBrr+K?(*tPE z8BXO-F~flbM0=yi9g_?jDJ(&aV@2JRYEHc3T{0>aq%eJ@J~+QJ?jd_ZB}hV0hv4<` z%ede%r0hP3@Dt%*)%ddVUcmPzf9Ps>QlEwQMHB8}Im@zE<7eyG_OWWi-!@wvX^c%* z{YtGiU9*DQ0Fz1Kx%><6ZoPdFx9f;u6@Fe{u2!cT{`T7RE`O>rHC@|%tQCA25U(J_ zVfcAdxiMQSPx|%Qt&Lh)k26~xt<<(nPVcgU9|5*V*hBFX)N1A3{urLl`O~uve|nq0 zbsE5RD|p{i3HLa{ZNSgi=;UeT`g#6zbrRrHGn196O0`iLMOXaasMKa^75s)bejeQp zVK)yylhgIF>UJLwN5<;l*9yLg$A|Or8vKk*k5*=;DG)Putz6w+fykbQI0z*Ff-7*F z<*mZcaaM3s{C*hHi{C@y_r>q~t>Cfv{YEQzHhw=~1z(NdA8!SJ8NVO2f`5wNp8yHQ z?>B+mXJYi7Xa!ft?~j2bA2L*;<`Mbzp`TR{5^ zqe!i?4K!6pAd|}6Ol71=yuWR%GCArK=?v_u`%@!#tGkNITkEs6QAkDTGfJ?i9gJHZ z4FlBH*=-=g+69SqYcG%PEQ7!{=(nD8$}yY#o#n}~QEgPT|Jho_vcC9-m?IL^@>IpT zlE<7gkZZMZ?9{Y+`gYttYNuVX#bGg%OnPi&7$JQo>*{$#ZgLp}XSs46aFI`qZLdz( zDutw|enqBM*(p~&-sZ8XsoBPGnK6HOd!^y6*xYj8+X^vRsjiGe;C@y7zFuh@)Z2n{ zqO!Zbx+jK|4QpCqAcp$EaTqonlHJ^>%r%BF#G$Uf967ICtFKL)iDzAIw6b+}``HxF z`a<&>bKPOF+taI!!&fw)z8*M^aBGeFF#L=2kDopdvlyU?IUpJwIAmx0^Z|4Ksk4N9+HiF)-7 zzKXrr&R%_kM@ugQ*Ee`f7Ed=xr(=03SDRk#>Q;8ybev1-G|Z;HT(vA5K_vaWK4%(N zg9952rkz~|2L>XJZHhPo+{XSB2}w$E_nN3z-{7yZSCgZY zB8~vpH~88to`PE3oXktP+VnbCw+cs_LyiEmDbSeZ!BEbyiU+UPGL-gT3)@exHntE` zD9uv@lcDicN-cbHTJ!{cPH*mvljqCTZ)8Rq`s!`j zt&O^V{G0hEY~SE-WesrO;BRLQbl>3Hb0K)&;5%aQ8~cAJgx}czyCM9>{^1CIWB<7^ z_`!j42tPQmHH04=7>VEq2S)SSbEmfrV-Bk{?;x3N%{xeAdm(}(d*?N80lH~yMf4Q6 zeS_mI_Z#~sTJ8r2CY#-Xd(%|&F>dAt8G@29)O;1nGHgBoZot{RB&@((!#tc^9wNkfKE0xi(ZLW!QdWNaTZqp6oG;`?r zO-dz(|DHhu2p!WA&G+Oag&7{Jjx{b=p|6n}%ubdYmAy$>Zp>%pF z%iAj#D#U6X$+mD|LXeA8ZgaJ=Yq(tBT^+et<;Lp6v(>HBbCuCcl$o4%K}_{amCH5B zuwIi~rV>NL+Z&gwzMEx!`10(wX*$cm9CZ> zd~%J3zgA_1gJZ`==ia4OlmT`O^Mzvu29F)MuBBnqu>;q~8;(Ej*nt~b8v2hNxUr>S z;Mjqigv`pj^>FWLd5j_6tJ~ifZyyAn_v`kXTiQXv2Xy-fe^{;QfE=b+?`XjZ`tDRYNhF2|{}B;- zmGA5ehm&hr1Ele5`LrOCt|ng_(|nPPdA{2oW-GImXH~M^DAyX#sr1P7 zW+DxrS1w2g#BhD={K^+prn0jY^sOjfq`^=}%Ml}_dBYDK-J;ZM{`CeOpO zm{<^`^t1n?R!Ji)nvJH%pDGWks#l=C$>Ho@>$QhQb z|1S-c+|>U{Wv6CD0@EXZt#Y`=SX|A0L#1)EtyZagQ+XzP#^{vl#{R!i2e&st5!1OMAD?aa*oPOa~N*O(+j|NHiCg9C!@AG)*?-9NUY1AGkKKee+m zIPlNytVBKjMP&_Xl^x%Xt|uGciLSRd{x!Outb8}R-d_10{7@=a4CddDZV;*eZ*(&? zJNbj?1|jB$(G7g_N6`&D_s7u1et`hVH|vWXwGY@C#3W(*gEBf8BcZpLcF5pE!a9?UTLtgPWO-`lwk8c!-t7WY znHxFp!v>~OuH7MxB=JtW0JKdz`iRZ20kIDEkA763YW4F*?~<-;9lcusz$*Ygrh%tN zaea^N3AtO#lU(={#l3bxnowz(;{AQ``}&UB{q{JRC9D|A<@)gO5g+ z8y^!{!1+cWm#eYrNbL!^f^pYAEr2l3;n64M65I@re#XvCj#Vf0#Ag4~1E^zQ22_@+ zW|ZaB8?~&Jv*kiLSns<@D=~sPvC15U37|an>f>xR=csZ*mGgGnqdrtDHL#kq)ow?P zC0xuEGsAlFOiGfO>Xpe|HyyLF@7Rrf=`=G~_*W*&d})~DWgS4QSU$eNV>b>gimxZp zMsdGw&()n(&2)pAtBmipgAR0nBBK=0-geNzc2H)!0=lvt^n?yjN9#tk9@Wu0fYw)Zpa$1O{YxF-V7&Uv z9j#!zx}l>Lj8|XTff|ex^{=#pZv@ZPS9P?K$)h`3$>A~Ws5g>Bpgy((oJ_vDqm@h^ z*U?H2`#MmQL!j>O04I|hJ6g%)Kzr)|IXu1{^?*_1U-Kwga_MH8F{lOp^Mvv1w9vH=*(eZ$6qsN&Y z4-DsT=y+f_e`Ci3!}*&!9vIHg>Udx{KfB|B;rz|*S{elBBfs9>dIH$q^_FmE53TbA z@I2zEkwk*|?l~Qu!1=DXcC>=+UBA)M3Z8epEu>QIvQyu+|zLJYfptD_Y% z*!9~Ttq{Pjw|B++jt*GJWY_O>v_c@eez(1K69qEd74Nwnun^O(az`trv$dm@(i!QB zcQlsU$QMAeSd?W|xzd3hQl8t^(F%FaZSQD>Jm=2q zXoWoI#yVOdxw-L0OaM{2W;U2X>w2xFN@GTHK^!Iy1b=9-stSu={-1}>c@Rf!l?NwquGBrI)j z+no_6c87_KnzYq6N6jVdZF5O^bbg_UmkF~NXCk?6tX6L%Q%6J4^-kJ+_!O<3pw5 zHy5du22rY3sbhg@$Dca(M7?!&X4mR1{nKH6H6!KKY*;tVg{w6;yvWB97sA#R@z$Qa zDb`9>?`2uAmCN3|DaXp)#R?12xl8!Fda1%Pbf!^L`5Eke)KN;Wj8;Z3L#rw)we@n9 z&=)qsW8F#O*WkbvDl+0RS%HoxLUNLEa;^-qyt5mYt7QDE0b^JDlwIw=Mul^w60{-C z76D!h_@r#~C`UF#!am{3S+8;wOt5@igfM(~yexs_;q{Saz}IY5zM<{@#;CIrvj!AU z-W0O*?iLwLI%*LayhnvIkPI`{Vzdc0X_o6Duc2qRuF&7RpM$;cKn(VN6^3G}VbT%C z$CDw2DOFC#m3;Go81nwI4p>X4I4bMF(+RWIOe^4R8^`B-#{jQ zUn^7G32S-&@z&c1T5liJ#0av7V%MLDU4Jrm{V5^gVT?(&C^h#;$n~Q{%*YfENRMgd zsNJ?Y-$|fHUxL5;AMXbI1my-zvTh(#a4n&#Nj3Iqm1R4S2nNB^pWygORZgj`Y1Zz> zo&=Q%9ECeh@poTKwEql<)CSX>u1@%Dm&Q$>i)M``B+5w>b;ryi3Ct5o)krm`_;hTF z&ot-vtTRy`ZcY|)JKUcMBlK!7-mzDh*w;xT%UJC+R`!QRZ0f!&G(OcijrSqrn{X(V zglg!-N@q4tcY#HUS#umvmr#{B>@#YO(WIIn2&ZwQnIvcMMbx4i*`{W4s?w2%6-2Tt zNL>$y^+Nggu5MOGH_EQ6%+xEx=c`(tbBk4;AC$$3LY@1rZeBhMvkyDsG=Z-AwpeOQ z@On-iYM9a)9M zZOnB*RbI^%LXZ`z+M~uiRqa({D^+!s8as#}t5tQ48hakTo-NOe@%+O` EntityId -> Blob -> TrapOr WasmState -type UpdateFunc = WasmState -> TrapOr (WasmState, ([MethodCall], Maybe Response)) +type InitFunc = ExistingCanisters -> CanisterId -> EntityId -> Blob -> TrapOr (InitResult, WasmState) +type UpdateFunc = WasmState -> TrapOr (WasmState, UpdateResult) type QueryFunc = WasmState -> TrapOr Response data CanisterModule = CanisterModule { init_method :: InitFunc - , update_methods :: MethodName ↦ (EntityId -> Blob -> UpdateFunc) + , update_methods :: MethodName ↦ (ExistingCanisters -> EntityId -> Blob -> UpdateFunc) , query_methods :: MethodName ↦ (EntityId -> Blob -> QueryFunc) - , callbacks :: Callback -> EntityId -> Response -> UpdateFunc + , callbacks :: Callback -> ExistingCanisters -> EntityId -> Response -> UpdateFunc } parseCanister :: Blob -> Either String CanisterModule @@ -44,9 +44,9 @@ parseCanister bytes = concreteToAbstractModule :: Module -> CanisterModule concreteToAbstractModule wasm_mod = CanisterModule - { init_method = \cid caller dat -> initialize wasm_mod cid caller dat + { init_method = \ex cid caller dat -> initialize ex wasm_mod cid caller dat , update_methods = M.fromList - [ (m, \caller dat wasm_state -> invoke wasm_state (CI.Update m caller dat)) + [ (m, \ex caller dat wasm_state -> invoke wasm_state (CI.Update m ex caller dat)) | n <- exportedFunctions wasm_mod , Just m <- return $ stripPrefix "canister_update " n ] @@ -56,5 +56,6 @@ concreteToAbstractModule wasm_mod = CanisterModule | n <- exportedFunctions wasm_mod , Just m <- return $ stripPrefix "canister_query " n ] - , callbacks = \cb cid res wasm_state -> invoke wasm_state (CI.Callback cb cid res) + , callbacks = \cb ex cid res wasm_state -> + invoke wasm_state (CI.Callback cb ex cid res) } diff --git a/ic-stub/src/IC/Canister/Imp.hs b/ic-stub/src/IC/Canister/Imp.hs index 57cb928aa4e..bd7f65987b4 100644 --- a/ic-stub/src/IC/Canister/Imp.hs +++ b/ic-stub/src/IC/Canister/Imp.hs @@ -27,7 +27,9 @@ import Control.Monad.Except import Data.STRef import Data.Maybe import Data.Int +import Text.Printf +import IC.Id import IC.Types import IC.Wasm.Winter import IC.Wasm.Imports @@ -49,21 +51,25 @@ data ExecutionState s = ExecutionState { inst :: Instance s , self_id :: CanisterId , params :: Params + , existing_canisters :: ExistingCanisters -- now the mutable parts , response :: Maybe Response , reply_data :: Blob , calls :: [MethodCall] + , new_canisters :: NewCanisters } -initalExecutionState :: CanisterId -> Instance s -> ExecutionState s -initalExecutionState self_id inst = ExecutionState +initalExecutionState :: CanisterId -> Instance s -> ExistingCanisters -> ExecutionState s +initalExecutionState self_id inst ex = ExecutionState { inst , self_id + , existing_canisters = ex , params = Params Nothing Nothing 0 "" , response = Nothing , reply_data = mempty , calls = mempty + , new_canisters = mempty } -- Some bookkeeping to access the ExecutionState @@ -128,6 +134,10 @@ appendCall :: ESRef s -> MethodCall -> HostM s () appendCall esref c = modES esref $ \es -> es { calls = calls es ++ [c] } +appendNewCanister :: ESRef s -> (CanisterId, Blob, Blob) -> HostM s () +appendNewCanister esref c = modES esref $ \es -> + es { new_canisters = new_canisters es ++ [c] } + -- The System API, with all imports -- The code is defined in the where clause to scope over the 'ESRef' @@ -151,6 +161,11 @@ systemAPI esref = , toImport "debug_print" debug_print , toImport "trap" explicit_trap ] + , (,) "stub" + [ toImport "create_canister" create_canister + , toImport "created_canister_id_size" created_canister_id_size + , toImport "created_canister_id_copy" created_canister_id_copy + ] ] where -- Utilities @@ -182,6 +197,16 @@ systemAPI esref = , \(dst, offset, size) -> get_blob >>= \blob -> copy_to_canister dst offset size blob ) + size_and_copy1 :: (a -> HostM s Blob) -> + ( a -> HostM s Int32 + , (a, Int32, Int32, Int32) -> HostM s () + ) + size_and_copy1 get_blob = + ( \x -> + get_blob x >>= \blob -> return $ fromIntegral (BS.length blob) + , \(x, dst, offset, size) -> + get_blob x >>= \blob -> copy_to_canister dst offset size blob + ) -- Unsafely print (if not in silent mode) putBytes :: BS.ByteString -> HostM s () @@ -288,6 +313,30 @@ systemAPI esref = let msg = BSU.toString bytes throwError $ "canister trapped explicitly: " ++ msg + -- These system calls are not specified, and are backdoors for use + -- by the Motoko test suite + + create_canister :: (Int32, Int32, Int32, Int32) -> HostM s Int32 + create_canister (mod_src, mod_size, arg_src, arg_size) = do + ex <- gets existing_canisters + new <- gets new_canisters + let can_id = freshId (map (\(i,_,_) -> i) new ++ ex) + let idx = fromIntegral $ length new + mod <- copy_from_canister "create_canister" mod_src mod_size + arg <- copy_from_canister "create_canister" arg_src arg_size + appendNewCanister esref (can_id, mod, arg) + return idx + + created_canister_id_size :: Int32 -> HostM s Int32 + created_canister_id_copy :: (Int32, Int32, Int32, Int32) -> HostM s () + (created_canister_id_size, created_canister_id_copy) = size_and_copy1 $ \idx' -> do + let idx = fromIntegral idx' + new <- gets new_canisters + unless (idx >= 0 && idx < length new) $ + throwError $ printf "created_canister_id index (%d) out of bounds (%d)" idx (length new) + let (i,_,_) = new !! idx + return (rawEntityId i) + -- The state of an instance, consistig of the underlying Wasm state, -- additional remembered information like the CanisterId -- and the 'ESRef' that the system api functions are accessing @@ -302,19 +351,19 @@ rawInitialize esref cid wasm_mod = do Right inst -> return $ Return (esref, cid, inst) rawInvoke :: ImpState s -> CI.CanisterMethod r -> ST s (TrapOr r) -rawInvoke esref (CI.Initialize wasm_mod caller dat) = - rawInitializeMethod esref wasm_mod caller dat +rawInvoke esref (CI.Initialize ex wasm_mod caller dat) = + rawInitializeMethod esref ex wasm_mod caller dat rawInvoke esref (CI.Query name caller dat) = rawQueryMethod esref name caller dat -rawInvoke esref (CI.Update name caller dat) = - rawUpdateMethod esref name caller dat -rawInvoke esref (CI.Callback cb caller res) = - rawCallbackMethod esref cb caller res +rawInvoke esref (CI.Update name ex caller dat) = + rawUpdateMethod esref name ex caller dat +rawInvoke esref (CI.Callback cb ex caller res) = + rawCallbackMethod esref cb ex caller res -rawInitializeMethod :: ImpState s -> Module -> EntityId -> Blob -> ST s (TrapOr ()) -rawInitializeMethod (esref, cid, inst) wasm_mod caller dat = do +rawInitializeMethod :: ImpState s -> ExistingCanisters -> Module -> EntityId -> Blob -> ST s (TrapOr InitResult) +rawInitializeMethod (esref, cid, inst) ex wasm_mod caller dat = do result <- runExceptT $ do - let es = (initalExecutionState cid inst) + let es = (initalExecutionState cid inst ex) { params = Params { param_dat = Just dat , param_caller = Just caller @@ -324,17 +373,20 @@ rawInitializeMethod (esref, cid, inst) wasm_mod caller dat = do } -- invoke canister_init - when ("canister_init" `elem` exportedFunctions wasm_mod) $ - void $ withES esref es $ - invokeExport inst "canister_init" [] + if "canister_init" `elem` exportedFunctions wasm_mod + then withES esref es $ void $ invokeExport inst "canister_init" [] + else return ((), es) -- TODO: Check no calls are made + case result of Left err -> return $ Trap err - Right () -> return $ Return () + Right (_, es') -> return $ + -- TODO: extract canisters and calls here + Return (new_canisters es', calls es') rawQueryMethod :: ImpState s -> MethodName -> EntityId -> Blob -> ST s (TrapOr Response) rawQueryMethod (esref, cid, inst) method caller dat = do - let es = (initalExecutionState cid inst) + let es = (initalExecutionState cid inst []) { params = Params { param_dat = Just dat , param_caller = Just caller @@ -352,9 +404,9 @@ rawQueryMethod (esref, cid, inst) method caller dat = do | Just r <- response es' -> return $ Return r | otherwise -> return $ Trap "No response" -rawUpdateMethod :: ImpState s -> MethodName -> EntityId -> Blob -> ST s (TrapOr ([MethodCall], Maybe Response)) -rawUpdateMethod (esref, cid, inst) method caller dat = do - let es = (initalExecutionState cid inst) +rawUpdateMethod :: ImpState s -> MethodName -> ExistingCanisters -> EntityId -> Blob -> ST s (TrapOr UpdateResult) +rawUpdateMethod (esref, cid, inst) method ex caller dat = do + let es = (initalExecutionState cid inst ex) { params = Params { param_dat = Just dat , param_caller = Just caller @@ -367,17 +419,17 @@ rawUpdateMethod (esref, cid, inst) method caller dat = do invokeExport inst ("canister_update " ++ method) [] case result of Left err -> return $ Trap err - Right (_, es') -> return $ Return (calls es', response es') + Right (_, es') -> return $ Return (new_canisters es', calls es', response es') -rawCallbackMethod :: ImpState s -> Callback -> EntityId -> Response -> ST s (TrapOr ([MethodCall], Maybe Response)) -rawCallbackMethod (esref, cid, inst) callback caller res = do +rawCallbackMethod :: ImpState s -> Callback -> ExistingCanisters -> EntityId -> Response -> ST s (TrapOr UpdateResult) +rawCallbackMethod (esref, cid, inst) callback ex caller res = do let param_caller = Just caller let params = case res of Reply dat -> Params { param_dat = Just dat, param_caller, reject_code = 0, reject_message = "" } Reject (rc, reject_message) -> Params { param_dat = Nothing, param_caller, reject_code = rejectCode rc, reject_message } - let es = (initalExecutionState cid inst) { params } + let es = (initalExecutionState cid inst ex) { params } let WasmClosure fun_idx env = case res of Reply {} -> reply_callback callback @@ -387,5 +439,6 @@ rawCallbackMethod (esref, cid, inst) callback caller res = do invokeTable inst fun_idx [I32 env] case result of Left err -> return $ Trap err - Right (_, es') -> return $ Return (calls es', response es') + Right (_, es') -> return $ + Return (new_canisters es', calls es', response es') diff --git a/ic-stub/src/IC/Canister/Interface.hs b/ic-stub/src/IC/Canister/Interface.hs index eb1d5d9dd93..93a8755023e 100644 --- a/ic-stub/src/IC/Canister/Interface.hs +++ b/ic-stub/src/IC/Canister/Interface.hs @@ -4,16 +4,21 @@ This module defines the various entry points provided by "IC.Canister.Imp" as a data type describing the arguments and results. The point of this abstraction is to to allow adding new entry points, or changing the arguments or result values, without changing the modules "IC.Canister.Pure" or "IC.Canister.Persisted", that sit between "IC.Canister.Imp" and "IC.Canister". + +Certain features here are beyond the specified abilities, in order to support the Motoko test suite. In particular: + + * Creating canisters + * Issuing calls from canister_init + -} module IC.Canister.Interface where import IC.Types import IC.Wasm.Winter (Module) -type UpdateResult = ([MethodCall], Maybe Response) data CanisterMethod r where - Initialize :: Module -> EntityId -> Blob -> CanisterMethod () + Initialize :: ExistingCanisters -> Module -> EntityId -> Blob -> CanisterMethod InitResult Query :: MethodName -> EntityId -> Blob -> CanisterMethod Response - Update :: MethodName -> EntityId -> Blob -> CanisterMethod UpdateResult - Callback :: Callback -> EntityId -> Response -> CanisterMethod UpdateResult + Update :: MethodName -> ExistingCanisters -> EntityId -> Blob -> CanisterMethod UpdateResult + Callback :: Callback -> ExistingCanisters -> EntityId -> Response -> CanisterMethod UpdateResult diff --git a/ic-stub/src/IC/Canister/Persisted.hs b/ic-stub/src/IC/Canister/Persisted.hs index 229ed69aa49..ffb3ebbfbdd 100644 --- a/ic-stub/src/IC/Canister/Persisted.hs +++ b/ic-stub/src/IC/Canister/Persisted.hs @@ -1,4 +1,5 @@ {-# LANGUAGE LambdaCase #-} +{-# LANGUAGE TupleSections #-} {-# OPTIONS_GHC -Wmissing-signatures #-} {-| @@ -22,14 +23,14 @@ import IC.Canister.Imp data WasmState = WasmState Module CanisterId PInstance -initialize :: Module -> CanisterId -> EntityId -> Blob -> TrapOr WasmState -initialize wasm_mod cid caller dat = runESST $ \esref -> +initialize :: ExistingCanisters -> Module -> CanisterId -> EntityId -> Blob -> TrapOr (InitResult, WasmState) +initialize ex wasm_mod cid caller dat = runESST $ \esref -> rawInitialize esref cid wasm_mod >>= \case Trap err -> return $ Trap err Return rs -> - rawInvoke rs (CI.Initialize wasm_mod caller dat) >>= \case + rawInvoke rs (CI.Initialize ex wasm_mod caller dat) >>= \case Trap err -> return $ Trap err - Return () -> Return <$> newWasmState wasm_mod rs + Return ir -> Return . (ir,) <$> newWasmState wasm_mod rs invoke :: WasmState -> CI.CanisterMethod r -> TrapOr (WasmState, r) invoke s m = runESST $ \esref -> do diff --git a/ic-stub/src/IC/Canister/Pure.hs b/ic-stub/src/IC/Canister/Pure.hs index 84573c722f8..dc03767347b 100644 --- a/ic-stub/src/IC/Canister/Pure.hs +++ b/ic-stub/src/IC/Canister/Pure.hs @@ -34,12 +34,12 @@ data WasmState = WasmState , ws_calls :: [ACall] -- in reverse order } -initialize :: Module -> CanisterId -> EntityId -> Blob -> TrapOr WasmState -initialize wasm_mod cid caller dat = runESST $ \esref -> +initialize :: Module -> ExistingCanisters -> CanisterId -> EntityId -> Blob -> TrapOr WasmState +initialize wasm_mod ex cid caller dat = runESST $ \esref -> rawInitialize esref cid wasm_mod >>= \case Trap err -> return $ Trap err Return rs -> do - let m = CI.Initialize wasm_mod caller dat + let m = CI.Initialize ex wasm_mod caller dat result <- rawInvoke rs m let state' = WasmState wasm_mod cid [ACall m] case result of diff --git a/ic-stub/src/IC/Id.hs b/ic-stub/src/IC/Id.hs new file mode 100644 index 00000000000..b3e2323198e --- /dev/null +++ b/ic-stub/src/IC/Id.hs @@ -0,0 +1,14 @@ +module IC.Id where + +import IC.Types + +import Data.Binary (encode) +import Data.Word + +-- Not particulary efficent, but this is a reference implementation, right? +freshId :: [EntityId] -> EntityId +freshId ids = + head $ + filter (`notElem` ids) $ + map (EntityId . encode) + [1024::Word64 ..] diff --git a/ic-stub/src/IC/Stub.hs b/ic-stub/src/IC/Stub.hs index ee7682da811..0dcf61e2978 100644 --- a/ic-stub/src/IC/Stub.hs +++ b/ic-stub/src/IC/Stub.hs @@ -22,12 +22,10 @@ module IC.Stub ) where -import qualified Data.ByteString.Lazy as BS import qualified Data.ByteString.Lazy.Char8 as BSC import qualified Data.Map as M import Data.List import Data.Maybe -import Control.Monad import Control.Monad.State.Class import Data.Sequence (Seq(..)) import Data.Foldable (toList) @@ -36,16 +34,18 @@ import Data.Foldable (toList) import IC.Types import IC.Canister +import IC.Id -- Abstract HTTP Interface data AsyncRequest - = InstallRequest UserId Blob Blob - | UpdateRequest UserId MethodName Blob + = CreateRequest UserId + | InstallRequest CanisterId UserId Blob Blob + | UpdateRequest CanisterId UserId MethodName Blob deriving (Eq, Ord, Show) data SyncRequest - = QueryRequest UserId MethodName Blob + = QueryRequest CanisterId UserId MethodName Blob | StatusRequest Blob data RequestStatus @@ -94,6 +94,7 @@ data CallContext = CallContext data CallOrigin = FromUser AsyncRequest | FromCanister CallId Callback + | FromInit EntityId deriving Show data Message = @@ -135,8 +136,8 @@ readRequest (StatusRequest rid) = Just (_r,status) -> return status Nothing -> return Unknown -readRequest (QueryRequest user_id method arg) = - gets (M.lookup dummyCanisterId . canisters) >>= \case +readRequest (QueryRequest canister_id user_id method arg) = + gets (M.lookup canister_id . canisters) >>= \case Nothing -> return $ Rejected (RC_DESTINATION_INVALID, "canister does not exist") Just Nothing -> return $ Rejected (RC_DESTINATION_INVALID, "canister is empty") Just (Just (CanState wasm_state can_mod)) -> @@ -154,8 +155,6 @@ nextReceived = gets $ \ic -> listToMaybe nextStarved :: ICT m => m (Maybe CallId) nextStarved = gets $ \ic -> listToMaybe - -- TODO: This should return a starved calling context. - -- Until we have them, we treat requests in Processing state as starved [ c | (c, ctxt) <- M.toList (call_contexts ic) , not $ responded ctxt @@ -178,8 +177,16 @@ setReqStatus :: ICT m => AsyncRequest -> RequestStatus -> m () setReqStatus r s = modify (\ic -> ic { requests = M.insert r s (requests ic) }) -createCanister :: ICT m => CanisterId -> CanisterModule -> WasmState -> m () -createCanister cid can_mod wasm_state = +createEmptyCanister :: ICT m => CanisterId -> m () +createEmptyCanister cid = + modify (\ic -> ic { canisters = + M.insert cid Nothing (canisters ic) + }) + + +installCanister :: ICT m => CanisterId -> CanisterModule -> WasmState -> m () +installCanister cid can_mod wasm_state = + -- Check that canister exists but is empty before? modify (\ic -> ic { canisters = M.insert cid (Just (CanState {can_mod, wasm_state})) (canisters ic) }) @@ -190,26 +197,42 @@ setCanisterState cid wasm_state = M.adjust (fmap (\cs -> cs { wasm_state })) cid (canisters ic) }) -dummyCanisterId :: CanisterId -dummyCanisterId = EntityId $ BS.pack [0xDE, 0xAD, 0xBE, 0xEF] - processRequest :: ICT m => AsyncRequest -> m () -processRequest r@(InstallRequest user_id can_mod dat) = do - let canister_id = dummyCanisterId + +processRequest r@(CreateRequest _user_id) = do + existing_canisters <- gets (M.keys . canisters) + let new_id = freshId existing_canisters + createEmptyCanister new_id + setReqStatus r $ Completed $ CompleteCanisterId new_id + +processRequest r@(InstallRequest canister_id user_id can_mod dat) = case parseCanister can_mod of Left err -> setReqStatus r $ Rejected (RC_SYS_FATAL, "Parsing failed: " ++ err) - Right can_mod -> - case init_method can_mod canister_id user_id dat of + Right can_mod -> do + -- We only need a call context to be able to do inter-canister calls + -- from init, which is useful for Motoko testing, but not currently + -- allowed by the spec. + ctxt_id <- newCallContext $ CallContext + { canister = canister_id + , origin = FromInit user_id + , responded = True + , last_trap = Nothing + } + + existing_canisters <- gets (M.keys . canisters) + + case init_method can_mod existing_canisters canister_id user_id dat of Trap msg -> setReqStatus r $ Rejected (RC_CANISTER_ERROR, "Initialization trapped: " ++ msg) - Return wasm_state -> do - createCanister canister_id can_mod wasm_state + Return ((new_canisters, new_calls), wasm_state) -> do + installCanister canister_id can_mod wasm_state + mapM_ (\(i,_,_) -> createEmptyCanister i) new_canisters + mapM_ (\(i,mod,dat) -> submitRequest (InstallRequest i canister_id mod dat)) new_canisters + mapM_ (newCall ctxt_id) new_calls setReqStatus r $ Completed CompleteUnit -processRequest r@(UpdateRequest _user_id method arg) = do - let canister_id = dummyCanisterId - +processRequest r@(UpdateRequest canister_id _user_id method arg) = do ctxt_id <- newCallContext $ CallContext { canister = canister_id , origin = FromUser r @@ -252,8 +275,9 @@ rememberTrap ctxt_id msg = modifyCallContext ctxt_id $ \ctxt -> ctxt { last_trap = Just msg } callerOfRequest :: AsyncRequest -> EntityId -callerOfRequest (InstallRequest user_id _ _) = user_id -callerOfRequest (UpdateRequest user_id _ _) = user_id +callerOfRequest (CreateRequest user_id) = user_id +callerOfRequest (InstallRequest _ user_id _ _) = user_id +callerOfRequest (UpdateRequest _ user_id _ _) = user_id callerOfCallID :: ICT m => CallId -> m EntityId callerOfCallID ctxt_id = do @@ -261,6 +285,7 @@ callerOfCallID ctxt_id = do case origin ctxt of FromUser request -> return $ callerOfRequest request FromCanister other_ctxt_id _callback -> calleeOfCallID other_ctxt_id + FromInit entity_id -> return entity_id calleeOfCallID :: ICT m => CallId -> m EntityId calleeOfCallID ctxt_id = do @@ -269,16 +294,33 @@ calleeOfCallID ctxt_id = do invokeEntry :: ICT m => CallId -> CanState -> EntryPoint -> - m (TrapOr (WasmState, ([MethodCall], Maybe Response))) + m (TrapOr (WasmState, UpdateResult)) invokeEntry ctxt_id (CanState wasm_state can_mod) entry = do + existing_canisters <- gets (M.keys . canisters) caller <- callerOfCallID ctxt_id case entry of Public method dat -> case M.lookup method (update_methods can_mod) of - Just f -> return $ f caller dat wasm_state - Nothing -> return $ Return (wasm_state, ([], Just $ Reject (RC_DESTINATION_INVALID, "update method does not exist: " ++ method))) + Just f -> + return $ f existing_canisters caller dat wasm_state + Nothing -> do + let reject = Reject (RC_DESTINATION_INVALID, "update method does not exist: " ++ method) + return $ Return (wasm_state, ([], [], Just reject)) Closure cb r -> - return $ callbacks can_mod cb caller r wasm_state + return $ callbacks can_mod cb existing_canisters caller r wasm_state + +newCall :: ICT m => CallId -> MethodCall -> m () +newCall from_ctxt_id call = do + new_ctxt_id <- newCallContext $ CallContext + { canister = call_callee call + , origin = FromCanister from_ctxt_id (call_callback call) + , responded = False + , last_trap = Nothing + } + enqueueMessage $ CallMessage + { call_context = new_ctxt_id + , entry = Public (call_method_name call) (call_arg call) + } processMessage :: ICT m => Message -> m () processMessage (CallMessage ctxt_id entry) = do @@ -291,19 +333,11 @@ processMessage (CallMessage ctxt_id entry) = do invokeEntry ctxt_id cs entry >>= \case Trap msg -> rememberTrap ctxt_id msg - Return (new_state, (calls, mb_response)) -> do + Return (new_state, (new_canisters, new_calls, mb_response)) -> do setCanisterState callee new_state - forM_ calls $ \call -> do - new_ctxt_id <- newCallContext $ CallContext - { canister = call_callee call - , origin = FromCanister ctxt_id (call_callback call) - , responded = False - , last_trap = Nothing - } - enqueueMessage $ CallMessage - { call_context = new_ctxt_id - , entry = Public (call_method_name call) (call_arg call) - } + mapM_ (\(i,_,_) -> createEmptyCanister i) new_canisters + mapM_ (\(i,mod,dat) -> submitRequest (InstallRequest i callee mod dat)) new_canisters + mapM_ (newCall ctxt_id) new_calls mapM_ res mb_response processMessage (ResponseMessage ctxt_id response) = do @@ -318,6 +352,7 @@ processMessage (ResponseMessage ctxt_id response) = do { call_context = other_ctxt_id , entry = Closure callback response } + FromInit _ -> fail "unexpected Response in Init" starveCallContext :: ICT m => CallId -> m () starveCallContext ctxt_id = do diff --git a/ic-stub/src/IC/Types.hs b/ic-stub/src/IC/Types.hs index 09970933117..a76fb8238d9 100644 --- a/ic-stub/src/IC/Types.hs +++ b/ic-stub/src/IC/Types.hs @@ -68,3 +68,9 @@ data MethodCall = MethodCall , call_callback :: Callback } deriving Show + +type ExistingCanisters = [CanisterId] +type NewCanisters = [(CanisterId, Blob, Blob)] + +type InitResult = (NewCanisters, [MethodCall]) +type UpdateResult = (NewCanisters, [MethodCall], Maybe Response) diff --git a/ic-stub/src/IC/Wasm/Imports.hs b/ic-stub/src/IC/Wasm/Imports.hs index 87b3df952fa..dacd814d173 100644 --- a/ic-stub/src/IC/Wasm/Imports.hs +++ b/ic-stub/src/IC/Wasm/Imports.hs @@ -73,6 +73,46 @@ instance , toValue x2 ] +instance + ( WasmArg a1 + , WasmArg a2 + , WasmArg a3 + , WasmArg a4 + ) => WasmArgs + ( a1 + , a2 + , a3 + , a4 + ) where + stackType = + [ valueType @a1 + , valueType @a2 + , valueType @a3 + , valueType @a4 + ] + fromValues + [ x1 + , x2 + , x3 + , x4 + ] = (,,,) + <$> fromValue x1 + <*> fromValue x2 + <*> fromValue x3 + <*> fromValue x4 + fromValues xs = argError 3 xs + toValues + ( x1 + , x2 + , x3 + , x4 + ) = + [ toValue x1 + , toValue x2 + , toValue x3 + , toValue x4 + ] + instance ( WasmArg a1 , WasmArg a2 diff --git a/ic-stub/src/ic-stub-run.hs b/ic-stub/src/ic-stub-run.hs index 1d7a5e28ae6..f450ba95346 100644 --- a/ic-stub/src/ic-stub-run.hs +++ b/ic-stub/src/ic-stub-run.hs @@ -23,15 +23,17 @@ dummyUserId :: CanisterId dummyUserId = EntityId $ B.pack [0xCA, 0xFF, 0xEE] printAsyncRequest :: AsyncRequest -> IO () +printAsyncRequest CreateRequest{} = + printf "→ create\n" printAsyncRequest InstallRequest{} = printf "→ install\n" -printAsyncRequest (UpdateRequest _ method arg) = +printAsyncRequest (UpdateRequest _ _ method arg) = printf "→ update %s(%s)\n" method (prettyBlob arg) printSyncRequest :: SyncRequest -> IO () printSyncRequest (StatusRequest rid) = printf "→ status? %s\n" (prettyBlob rid) -printSyncRequest (QueryRequest _ method arg) = +printSyncRequest (QueryRequest _ _ method arg) = printf "→ query %s(%s)\n" method (prettyBlob arg) printReqStatus :: RequestStatus -> IO () @@ -71,11 +73,14 @@ work wasm_file msg_file = do wasm <- B.readFile wasm_file msgs <- parseFile msg_file + let user_id = dummyUserId + flip evalStateT initialIC $ do - _req_res <- submitAndRun (InstallRequest dummyUserId wasm B.empty) + Completed (CompleteCanisterId cid) <- submitAndRun (CreateRequest user_id) + _ <- submitAndRun (InstallRequest cid user_id wasm B.empty) forM_ msgs $ \case - (Query, method, arg) -> submitRead (QueryRequest dummyUserId method arg) - (Update, method, arg) -> submitAndRun (UpdateRequest dummyUserId method arg) + (Query, method, arg) -> submitRead (QueryRequest cid user_id method arg) + (Update, method, arg) -> submitAndRun (UpdateRequest cid user_id method arg) main :: IO () main = join . customExecParser (prefs showHelpOnError) $ diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index c7d97119a39..d4959b06244 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -3062,6 +3062,7 @@ module Dfinity = struct then E.add_global64 env "api_nonce" Mutable 0L let system_imports env = + let i32s n = Lib.List.make n I32Type in match E.mode env with | Flags.ICMode -> E.add_func_import env "debug" "print" [I32Type; I32Type] []; @@ -3073,17 +3074,20 @@ module Dfinity = struct E.add_func_import env "ic" "trap" [I32Type; I32Type] []; () | Flags.StubMode -> - E.add_func_import env "ic0" "call_simple" (Lib.List.make 10 I32Type) [I32Type]; - E.add_func_import env "ic0" "canister_self_copy" [I32Type; I32Type; I32Type] []; + E.add_func_import env "ic0" "call_simple" (i32s 10) [I32Type]; + E.add_func_import env "ic0" "canister_self_copy" (i32s 3) []; E.add_func_import env "ic0" "canister_self_size" [] [I32Type]; - E.add_func_import env "ic0" "debug_print" [I32Type; I32Type] []; - E.add_func_import env "ic0" "msg_arg_data_copy" [I32Type; I32Type; I32Type] []; + E.add_func_import env "ic0" "debug_print" (i32s 2) []; + E.add_func_import env "ic0" "msg_arg_data_copy" (i32s 3) []; E.add_func_import env "ic0" "msg_arg_data_size" [] [I32Type]; E.add_func_import env "ic0" "msg_reject_code" [] [I32Type]; - E.add_func_import env "ic0" "msg_reject" [I32Type; I32Type] []; - E.add_func_import env "ic0" "msg_reply_data_append" [I32Type; I32Type] []; + E.add_func_import env "ic0" "msg_reject" (i32s 2) []; + E.add_func_import env "ic0" "msg_reply_data_append" (i32s 2) []; E.add_func_import env "ic0" "msg_reply" [] []; - E.add_func_import env "ic0" "trap" [I32Type; I32Type] []; + E.add_func_import env "ic0" "trap" (i32s 2) []; + E.add_func_import env "stub" "create_canister" (i32s 4) [I32Type]; + E.add_func_import env "stub" "created_canister_id_size" (i32s 1) [I32Type]; + E.add_func_import env "stub" "created_canister_id_copy" (i32s 4) []; () | Flags.AncientMode -> E.add_func_import env "test" "print" [I32Type] []; @@ -3318,6 +3322,17 @@ module Dfinity = struct system_call env "ic0" "msg_reply" | _ -> assert false ) + + + (* References have special stack representation on the ancient platform, + but are just vanilla Blobs on the IC platform. *) + let reference_sr env = match E.mode env with + | Flags.AncientMode -> SR.UnboxedReference + | Flags.ICMode -> SR.Vanilla + | Flags.StubMode -> SR.Vanilla + | _ -> assert false + + end (* Dfinity *) module OrthogonalPersistence = struct @@ -5258,7 +5273,8 @@ module FuncDec = struct SR.Vanilla, code ^^ get_clos - else + else begin + assert (E.mode env = Flags.AncientMode); SR.UnboxedReference, code ^^ compile_unboxed_const fi ^^ @@ -5266,6 +5282,7 @@ module FuncDec = struct get_clos ^^ ClosureTable.remember_closure env ^^ Dfinity.system_call env "func" "bind_i32" + end (* Wraps a local closure in a shared function that does serialization and takes care of the reply global *) @@ -6314,13 +6331,9 @@ and compile_exp (env : E.t) ae exp = SR.Vanilla, compile_exp_vanilla env ae e ^^ Object.load_idx env e.note.note_typ name - | ActorDotE (e, name) when E.mode env = Flags.AncientMode -> - SR.UnboxedReference, - compile_exp_as env ae SR.UnboxedReference e ^^ - actor_fake_object_idx env name | ActorDotE (e, name) -> - SR.Vanilla, - compile_exp_as env ae SR.Vanilla e ^^ + Dfinity.reference_sr env, + compile_exp_as env ae (Dfinity.reference_sr env) e ^^ actor_fake_object_idx env name | PrimE (p, es) -> @@ -6837,7 +6850,7 @@ and compile_exp (env : E.t) ae exp = let mk_body env1 ae1 = compile_exp_as env1 ae1 (StackRep.of_arity return_arity) e in FuncDec.lit env ae typ_binds x sort control captured args mk_body return_tys exp.at | ActorE (i, ds, fs, _) -> - SR.UnboxedReference, + Dfinity.reference_sr env, let captured = Freevars.exp exp in let prelude_names = find_prelude_names env in if Freevars.M.is_empty (Freevars.diff captured prelude_names) @@ -7315,10 +7328,40 @@ and actor_lit outer_env this ds fs at = let (_map, wasm_binary) = Wasm_exts.CustomModuleEncode.encode m in wasm_binary in - Dfinity.compile_databuf_of_bytes outer_env wasm_binary ^^ - (* Create actorref *) - Dfinity.system_call outer_env "module" "new" ^^ - Dfinity.system_call outer_env "actor" "new" + match E.mode outer_env with + | Flags.AncientMode -> + Dfinity.compile_databuf_of_bytes outer_env wasm_binary ^^ + (* Create actorref *) + Dfinity.system_call outer_env "module" "new" ^^ + Dfinity.system_call outer_env "actor" "new" + | Flags.StubMode -> + let (set_idx, get_idx) = new_local outer_env "idx" in + let (set_len, get_len) = new_local outer_env "len" in + let (set_id, get_id) = new_local outer_env "id" in + (* the module *) + Blob.lit outer_env wasm_binary ^^ + Blob.as_ptr_len outer_env ^^ + (* the arg (not used in motoko yet) *) + compile_unboxed_const 0l ^^ + compile_unboxed_const 0l ^^ + Dfinity.system_call outer_env "stub" "create_canister" ^^ + set_idx ^^ + + get_idx ^^ + Dfinity.system_call outer_env "stub" "created_canister_id_size" ^^ + set_len ^^ + + get_len ^^ Blob.alloc outer_env ^^ set_id ^^ + + get_idx ^^ + get_id ^^ Blob.payload_ptr_unskewed ^^ + compile_unboxed_const 0l ^^ + get_len ^^ + Dfinity.system_call outer_env "stub" "created_canister_id_copy" ^^ + + get_id + | _ -> assert false + (* Main actor: Just return the initialization code, and export functions as needed *) and main_actor env ae1 this ds fs = diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 44b2e251962..aef7f27b567 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -661,7 +661,7 @@ and infer_exp'' env exp : T.typ = ) | ObjE (sort, fields) -> if not in_prog && sort.it = T.Actor then - error_in [Flags.ICMode; Flags.StubMode] env exp.at "non-toplevel actor; an actor can only be declared at the toplevel of a program"; + error_in [Flags.ICMode] env exp.at "non-toplevel actor; an actor can only be declared at the toplevel of a program"; let env' = if sort.it = T.Actor then {env with async = false; in_actor = true} else env in infer_obj env' sort.it fields exp.at | DotE (exp1, id) -> diff --git a/test/run-stub/actor-creation.mo b/test/run-stub/actor-creation.mo new file mode 100644 index 00000000000..0d8dddbe137 --- /dev/null +++ b/test/run-stub/actor-creation.mo @@ -0,0 +1,21 @@ +debugPrint ("main actor creating a\n"); +actor a { + public func foo() { + debugPrint ("a.foo() called\n"); + + debugPrint ("a creating b\n"); + actor b { + public func foo() { + debugPrint ("b.foo() called\n"); + }; + debugPrint ("b created\n"); + }; + + debugPrint ("a calling b.foo()\n"); + b.foo(); + debugPrint ("a.foo() done\n"); + }; + debugPrint ("a created\n"); +}; +debugPrint ("main actor calling a.foo()\n"); +a.foo(); diff --git a/test/run-stub/ok/actor-creation.ic-stub-run.ok b/test/run-stub/ok/actor-creation.ic-stub-run.ok new file mode 100644 index 00000000000..586cb2a776e --- /dev/null +++ b/test/run-stub/ok/actor-creation.ic-stub-run.ok @@ -0,0 +1,22 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +main actor creating a + +main actor calling a.foo() + +a created + +a.foo() called + +a creating b + +a calling b.foo() + +a.foo() done + +b created + +b.foo() called + +← completed diff --git a/test/run-stub/ok/actor-creation.run-ir.ok b/test/run-stub/ok/actor-creation.run-ir.ok new file mode 100644 index 00000000000..8605c4121d3 --- /dev/null +++ b/test/run-stub/ok/actor-creation.run-ir.ok @@ -0,0 +1,9 @@ +main actor creating a +a created +main actor calling a.foo() +a.foo() called +a creating b +b created +a calling b.foo() +a.foo() done +b.foo() called diff --git a/test/run-stub/ok/actor-creation.run-low.ok b/test/run-stub/ok/actor-creation.run-low.ok new file mode 100644 index 00000000000..8605c4121d3 --- /dev/null +++ b/test/run-stub/ok/actor-creation.run-low.ok @@ -0,0 +1,9 @@ +main actor creating a +a created +main actor calling a.foo() +a.foo() called +a creating b +b created +a calling b.foo() +a.foo() done +b.foo() called diff --git a/test/run-stub/ok/actor-creation.run.ok b/test/run-stub/ok/actor-creation.run.ok new file mode 100644 index 00000000000..8605c4121d3 --- /dev/null +++ b/test/run-stub/ok/actor-creation.run.ok @@ -0,0 +1,9 @@ +main actor creating a +a created +main actor calling a.foo() +a.foo() called +a creating b +b created +a calling b.foo() +a.foo() done +b.foo() called diff --git a/test/run-stub/ok/counter.ic-stub-run.ok b/test/run-stub/ok/counter.ic-stub-run.ok index 21a9c0406fa..4782a51c086 100644 --- a/test/run-stub/ok/counter.ic-stub-run.ok +++ b/test/run-stub/ok/counter.ic-stub-run.ok @@ -1,3 +1,5 @@ +→ create +← completed: canister-id = 0x0000000000000400 → install ← completed → update inc(0x4449444c0000) diff --git a/test/run-stub/ok/data-params.ic-stub-run.ok b/test/run-stub/ok/data-params.ic-stub-run.ok index 8f2de813c9d..f91829e5655 100644 --- a/test/run-stub/ok/data-params.ic-stub-run.ok +++ b/test/run-stub/ok/data-params.ic-stub-run.ok @@ -1,3 +1,5 @@ +→ create +← completed: canister-id = 0x0000000000000400 → install ← completed → update go(0x4449444c0000) diff --git a/test/run-stub/ok/hello-world-async.ic-stub-run.ok b/test/run-stub/ok/hello-world-async.ic-stub-run.ok index ac0776f7a8d..54b0b5b88ee 100644 --- a/test/run-stub/ok/hello-world-async.ic-stub-run.ok +++ b/test/run-stub/ok/hello-world-async.ic-stub-run.ok @@ -1,3 +1,5 @@ +→ create +← completed: canister-id = 0x0000000000000400 → install ← completed → update go(0x4449444c0000) diff --git a/test/run-stub/ok/hello-world-return.ic-stub-run.ok b/test/run-stub/ok/hello-world-return.ic-stub-run.ok index 1cee502a7a2..ced690a2811 100644 --- a/test/run-stub/ok/hello-world-return.ic-stub-run.ok +++ b/test/run-stub/ok/hello-world-return.ic-stub-run.ok @@ -1,3 +1,5 @@ +→ create +← completed: canister-id = 0x0000000000000400 → install ← completed → query hello(0x4449444c00017105576f726c64) diff --git a/test/run-stub/ok/ic-calls.ic-stub-run.ok b/test/run-stub/ok/ic-calls.ic-stub-run.ok index d73ca90a1ac..0a14e248fd2 100644 --- a/test/run-stub/ok/ic-calls.ic-stub-run.ok +++ b/test/run-stub/ok/ic-calls.ic-stub-run.ok @@ -1,3 +1,5 @@ +→ create +← completed: canister-id = 0x0000000000000400 → install ← completed → update test(0x4449444c0000) diff --git a/test/run-stub/ok/idl-any.ic-stub-run.ok b/test/run-stub/ok/idl-any.ic-stub-run.ok index d655b4a2ed2..cad8ed39a4c 100644 --- a/test/run-stub/ok/idl-any.ic-stub-run.ok +++ b/test/run-stub/ok/idl-any.ic-stub-run.ok @@ -1,3 +1,5 @@ +→ create +← completed: canister-id = 0x0000000000000400 → install ← completed → update any(0x4449444c00027f7103466f6f) diff --git a/test/run-stub/ok/idl-bad.ic-stub-run.ok b/test/run-stub/ok/idl-bad.ic-stub-run.ok index d0fad626584..d6c66bd8bf5 100644 --- a/test/run-stub/ok/idl-bad.ic-stub-run.ok +++ b/test/run-stub/ok/idl-bad.ic-stub-run.ok @@ -1,3 +1,5 @@ +→ create +← completed: canister-id = 0x0000000000000400 → install ← completed → query foo(0x4e4f544449444c) diff --git a/test/run-stub/ok/idl-field-escape.ic-stub-run.ok b/test/run-stub/ok/idl-field-escape.ic-stub-run.ok index 315382546b0..c56fd5f64d1 100644 --- a/test/run-stub/ok/idl-field-escape.ic-stub-run.ok +++ b/test/run-stub/ok/idl-field-escape.ic-stub-run.ok @@ -1,3 +1,5 @@ +→ create +← completed: canister-id = 0x0000000000000400 → install ← completed → update foo1(0x4449444c0000) diff --git a/test/run-stub/ok/idl-nary.ic-stub-run.ok b/test/run-stub/ok/idl-nary.ic-stub-run.ok index 6acee11407e..6a9444f8d0c 100644 --- a/test/run-stub/ok/idl-nary.ic-stub-run.ok +++ b/test/run-stub/ok/idl-nary.ic-stub-run.ok @@ -1,3 +1,5 @@ +→ create +← completed: canister-id = 0x0000000000000400 → install ← completed → update two(0x4449444c00027171034f6e650354776f) diff --git a/test/run-stub/ok/idl-nat-int.ic-stub-run.ok b/test/run-stub/ok/idl-nat-int.ic-stub-run.ok index 0a8265cff65..e2cfca32cb4 100644 --- a/test/run-stub/ok/idl-nat-int.ic-stub-run.ok +++ b/test/run-stub/ok/idl-nat-int.ic-stub-run.ok @@ -1,3 +1,5 @@ +→ create +← completed: canister-id = 0x0000000000000400 → install ← completed → query absolute(0x4449444c00017d2a) diff --git a/test/run-stub/ok/idl-option.ic-stub-run.ok b/test/run-stub/ok/idl-option.ic-stub-run.ok index bc846d92318..7268e34088a 100644 --- a/test/run-stub/ok/idl-option.ic-stub-run.ok +++ b/test/run-stub/ok/idl-option.ic-stub-run.ok @@ -1,3 +1,5 @@ +→ create +← completed: canister-id = 0x0000000000000400 → install ← completed → update any(0x4449444c00017f) diff --git a/test/run-stub/ok/idl-pair.ic-stub-run.ok b/test/run-stub/ok/idl-pair.ic-stub-run.ok index e4895464782..5fc5fed734d 100644 --- a/test/run-stub/ok/idl-pair.ic-stub-run.ok +++ b/test/run-stub/ok/idl-pair.ic-stub-run.ok @@ -1,3 +1,5 @@ +→ create +← completed: canister-id = 0x0000000000000400 → install ← completed → update len2(0x4449444c0002717102486905576f726c64) diff --git a/test/run-stub/ok/idl-record.ic-stub-run.ok b/test/run-stub/ok/idl-record.ic-stub-run.ok index b4dc531fddd..df552d2b0f9 100644 --- a/test/run-stub/ok/idl-record.ic-stub-run.ok +++ b/test/run-stub/ok/idl-record.ic-stub-run.ok @@ -1,3 +1,5 @@ +→ create +← completed: canister-id = 0x0000000000000400 → install ← completed → update pair(0x4449444c016c020071017c010004486579212a) diff --git a/test/run-stub/ok/idl-tuple.ic-stub-run.ok b/test/run-stub/ok/idl-tuple.ic-stub-run.ok index a556a084e35..c8f4900d5fb 100644 --- a/test/run-stub/ok/idl-tuple.ic-stub-run.ok +++ b/test/run-stub/ok/idl-tuple.ic-stub-run.ok @@ -1,3 +1,5 @@ +→ create +← completed: canister-id = 0x0000000000000400 → install ← completed → query len2(0x4449444c0002717102486905576f726c64) diff --git a/test/run-stub/ok/idl-unit.ic-stub-run.ok b/test/run-stub/ok/idl-unit.ic-stub-run.ok index e552c46999b..e7d4b9a40ab 100644 --- a/test/run-stub/ok/idl-unit.ic-stub-run.ok +++ b/test/run-stub/ok/idl-unit.ic-stub-run.ok @@ -1,3 +1,5 @@ +→ create +← completed: canister-id = 0x0000000000000400 → install ← completed → query unit_id(0x4449444c0000) diff --git a/test/run-stub/ok/idl-variant.ic-stub-run.ok b/test/run-stub/ok/idl-variant.ic-stub-run.ok index 0aa8f35ad28..75074f6bd69 100644 --- a/test/run-stub/ok/idl-variant.ic-stub-run.ok +++ b/test/run-stub/ok/idl-variant.ic-stub-run.ok @@ -1,3 +1,5 @@ +→ create +← completed: canister-id = 0x0000000000000400 → install ← completed → query numify(0x4449444c016b03d583b702008790c0bd0479dc9790cb0e790100000220000000) diff --git a/test/run-stub/ok/idl-vector.ic-stub-run.ok b/test/run-stub/ok/idl-vector.ic-stub-run.ok index c6f75bb92ab..352cb7766e8 100644 --- a/test/run-stub/ok/idl-vector.ic-stub-run.ok +++ b/test/run-stub/ok/idl-vector.ic-stub-run.ok @@ -1,3 +1,5 @@ +→ create +← completed: canister-id = 0x0000000000000400 → install ← completed → query rose(0x4449444c016d00010003000400020000000000) diff --git a/test/run-stub/ok/print-from-init.ic-stub-run.ok b/test/run-stub/ok/print-from-init.ic-stub-run.ok index 6daaa454e15..69d944607df 100644 --- a/test/run-stub/ok/print-from-init.ic-stub-run.ok +++ b/test/run-stub/ok/print-from-init.ic-stub-run.ok @@ -1,3 +1,5 @@ +→ create +← completed: canister-id = 0x0000000000000400 → install Debug out ← completed diff --git a/test/run-stub/ok/query.ic-stub-run.ok b/test/run-stub/ok/query.ic-stub-run.ok index eabf7fa916c..8f558b44b5e 100644 --- a/test/run-stub/ok/query.ic-stub-run.ok +++ b/test/run-stub/ok/query.ic-stub-run.ok @@ -1,3 +1,5 @@ +→ create +← completed: canister-id = 0x0000000000000400 → install ← completed → update inc(0x4449444c0000) diff --git a/test/run-stub/ok/reject.ic-stub-run.ok b/test/run-stub/ok/reject.ic-stub-run.ok index 1b0f835527b..cca556750dd 100644 --- a/test/run-stub/ok/reject.ic-stub-run.ok +++ b/test/run-stub/ok/reject.ic-stub-run.ok @@ -1,3 +1,5 @@ +→ create +← completed: canister-id = 0x0000000000000400 → install ← completed → update reject1(0x4449444c0000) diff --git a/test/run-stub/ok/reversi.ic-stub-run.ok b/test/run-stub/ok/reversi.ic-stub-run.ok index 71270e26ac3..be8989be6d7 100644 --- a/test/run-stub/ok/reversi.ic-stub-run.ok +++ b/test/run-stub/ok/reversi.ic-stub-run.ok @@ -1,3 +1,5 @@ +→ create +← completed: canister-id = 0x0000000000000400 → install ← completed → update reset(0x4449444c0000) diff --git a/test/run-stub/ok/self-calls.ic-stub-run.ok b/test/run-stub/ok/self-calls.ic-stub-run.ok index 4bdbaaf3e09..11ec18b545d 100644 --- a/test/run-stub/ok/self-calls.ic-stub-run.ok +++ b/test/run-stub/ok/self-calls.ic-stub-run.ok @@ -1,3 +1,5 @@ +→ create +← completed: canister-id = 0x0000000000000400 → install ← completed → update test(0x4449444c0000) diff --git a/test/run-stub/ok/transpose.ic-stub-run.ok b/test/run-stub/ok/transpose.ic-stub-run.ok index 6486f68e99f..be9fb5d62c0 100644 --- a/test/run-stub/ok/transpose.ic-stub-run.ok +++ b/test/run-stub/ok/transpose.ic-stub-run.ok @@ -1,3 +1,5 @@ +→ create +← completed: canister-id = 0x0000000000000400 → install ← completed → update go(0x4449444c0000) diff --git a/test/run-stub/ok/unsupported.comp.ok b/test/run-stub/ok/unsupported.comp.ok index 1eb7bdd6fba..4f6b017c8a7 100644 --- a/test/run-stub/ok/unsupported.comp.ok +++ b/test/run-stub/ok/unsupported.comp.ok @@ -44,9 +44,5 @@ unsupported.mo:51.31-51.41: type error, actor types are non-shared. (This is a limitation of the current version and flag -stub-system-api.) unsupported.mo:62.3-62.35: type error, actor classes are not supported; use an actor declaration instead (This is a limitation of the current version and flag -stub-system-api.) -unsupported.mo:66.45-66.53: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program - (This is a limitation of the current version and flag -stub-system-api.) -unsupported.mo:70.37-70.45: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program - (This is a limitation of the current version and flag -stub-system-api.) unsupported.mo:76.34-76.37: type error, freestanding async expression not yet supported (This is a limitation of the current version and flag -stub-system-api.) From bd215cc960eed34002b347869f7f2db16001277f Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Thu, 21 Nov 2019 15:25:52 +0000 Subject: [PATCH 0681/1176] add general_await.mo to run-stub tests; relax some StubMode restrictions to match --- src/mo_frontend/typing.ml | 6 +- test/run-stub/general_await.mo | 112 ++++++++++++++++++ test/run-stub/ok/general_await.ic-stub-run.ok | 52 ++++++++ 3 files changed, 167 insertions(+), 3 deletions(-) create mode 100644 test/run-stub/general_await.mo create mode 100644 test/run-stub/ok/general_await.ic-stub-run.ok diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index e8a29f7f053..7f023d6d21b 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -785,7 +785,7 @@ and infer_exp'' env exp : T.typ = check_exp env t_arg exp2; if Type.is_shared_sort sort then begin if T.is_async t_ret && not (in_await env) then - error_in [Flags.ICMode; Flags.StubMode] env exp2.at + error_in [Flags.ICMode] env exp2.at "shared, async function must be called within an await expression"; error_in [Flags.ICMode] env exp1.at "calling a shared function not yet supported"; if not (T.concrete t_arg) then @@ -952,8 +952,8 @@ and infer_exp'' env exp : T.typ = (match exp1.it with | CallE (f, _, _) -> if not env.pre && (Call_conv.call_conv_of_typ f.note.note_typ).Call_conv.control = T.Returns then - error_in [Flags.ICMode; Flags.StubMode] env f.at "expecting call to shared async function in await"; - | _ -> error_in [Flags.ICMode; Flags.StubMode] env exp1.at "argument to await must be a call expression"); + error_in [Flags.ICMode] env f.at "expecting call to shared async function in await"; + | _ -> error_in [Flags.ICMode] env exp1.at "argument to await must be a call expression"); (try let (t2, t3) = T.as_async_sub t0 t1 in if not (T.eq t0 t2) then diff --git a/test/run-stub/general_await.mo b/test/run-stub/general_await.mo new file mode 100644 index 00000000000..b01c7942950 --- /dev/null +++ b/test/run-stub/general_await.mo @@ -0,0 +1,112 @@ +// TODO: Remove Await. prefix from calls once supported +// Remove bug workaround +// Increase N (once perf improves) +actor Await { + + let N = 3; // number of dynamic waits (low coz slow) + + public shared func Ack<@>() : async(){ + debugPrint "\nAck" + }; + + public shared func Request<@>(i : Int) : async Int { + debugPrint("\nRequest(");debugPrintInt(i);debugPrint(")"); + return i; + }; + + // Static parallel waiting: + + public shared func PA<@>() : async () { + let a1 = Await.Ack<@>(); + let a2 = Await.Ack<@>(); + await a1; + await a2; + }; + + public shared func PR<@>() : async (Int,Int) { + let a1 = Await.Request<@>(1); + let a2 = Await.Request<@>(2); + (await a1, await a2) + }; + + // Dynamic parallel waiting for acknowledgements + + public shared func DPA<@>() : async () { + let as: [async()] = Array_tabulate(N, func (_) { Await.Ack<@>(); }); + for (a in as.vals()) { + await a; + }; + }; + + // Dynamic parallel waiting (with results) + + public shared func DPR<@>() : async [Int] { + func f (i:Nat) : async Int = Await.Request<@>(i); + let as = Array_tabulate(N, f); + let res = Array_init(as.len(),-1); + for (i in as.keys()) { +// res[i] := (await as[i]); <-- compiler bug (generates incorrect code) + let a = await as[i]; + res[i] := a; + }; + Array_tabulate(as.len(),func i = res[i]) + }; + + // Recursive parallel waiting + + public shared func RPA<@>(n:Nat) : async () { + if (n == 0) () + else { + let a = Await.Ack<@>(); + await Await.RPA<@>(n-1); // recurse + await a; + }; + }; + + // Recursive parallel waiting (with results) + + public type List = ?(Int,List); + + public shared func RPR<@>(n:Nat) : async List { + if (n == 0) null + else { + let a = Await.Request<@>(n); + let tl = await Await.RPR<@>(n-1); // recurse + ?(await a,tl) + } + }; + + + public shared func Test() : async () { + + await Await.PA<@>(); + + switch (await Await.PR<@>()) { + case (1,2) (); + case _ (assert false); + }; + + await Await.DPA<@>(); + + let rs = await Await.DPR<@>(); + for (i in rs.keys()) { + assert rs[i] == i; + }; + + await Await.RPA<@>(N); + + var l = await Await.RPR<@>(N); + for (i in revrange(N, 1)) { + switch (l) { + case (?(h, t)) { + assert (h == i); + l := t; + }; + case null (assert false); + } + }; + } +}; + +//CALL ingress Test 0x4449444C0000 + diff --git a/test/run-stub/ok/general_await.ic-stub-run.ok b/test/run-stub/ok/general_await.ic-stub-run.ok new file mode 100644 index 00000000000..0fc4527b321 --- /dev/null +++ b/test/run-stub/ok/general_await.ic-stub-run.ok @@ -0,0 +1,52 @@ +→ install +← completed +→ update Test(0x4449444c0000) + +Ack + +Ack + +Request( ++1 +) + +Request( ++2 +) + +Ack + +Ack + +Ack + +Request( +0 +) + +Request( ++1 +) + +Request( ++2 +) + +Ack + +Ack + +Ack + +Request( ++3 +) + +Request( ++2 +) + +Request( ++1 +) +← completed: 0x4449444c0000 From d152843ce4d51153265df62a60fb52d2263c7c16 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 21 Nov 2019 08:27:24 -0700 Subject: [PATCH 0682/1176] review feedback; Andreas --- stdlib/arrayBuf.mo | 130 ------------------------------ stdlib/buf.mo | 196 +++++++++++++++++++++++++-------------------- 2 files changed, 110 insertions(+), 216 deletions(-) delete mode 100644 stdlib/arrayBuf.mo diff --git a/stdlib/arrayBuf.mo b/stdlib/arrayBuf.mo deleted file mode 100644 index ada76ed668a..00000000000 --- a/stdlib/arrayBuf.mo +++ /dev/null @@ -1,130 +0,0 @@ -import P "prelude.mo"; -import B "buf.mo"; - -module { -/** -Array Buffers -=================== - -Growable buffers, implemented as arrays. - -See [buffer documentation](buf.mo) for more. - -*/ - -// re-export types and use them below. -public type ArrayBuf = B.ArrayBuf; -public type IndexedBuf = B.IndexedBuf; - -/* -Create an IndexedBuf, represented internally by an mutable array. - -The argument `initCapacity` gives the initial capacity. Under the -interface, the mutable array grows by doubling when this initial -capacity is exhausted. -*/ -public class Buf (initCapacity : Nat) : IndexedBuf { - var count : Nat = 0; - var elems : [var X] = [var]; // initially empty; allocated upon first `add` - - public func add(elem : X) { - if (count == elems.len()) { - let size = - if (count == 0) - initCapacity - else - 2 * elems.len(); - let elems2 = Array_init(size, elem); - for (i in elems.keys()) { - elems2[i] := elems[i]; - }; - elems := elems2; - }; - elems[count] := elem; - count += 1; - }; - - public func addBuf(b:B.Buf) { - for (x in b.iter()) { add(x) } - }; - - public func len() : Nat = - count; - - public func clear() = - count := 0; - - public func clone() : IndexedBuf { - let c = Buf(initCapacity); - for (elem in iter()) { c.add(elem) }; - c - }; - - public func iter() : Iter = object { - var pos = 0; - public func next() : ?X { - if (pos == count) { null } else { - let elem = ?elems[pos]; - pos += 1; - elem - } - } - }; - - public func array() : [X] = - // immutable clone of array - Array_tabulate( - elems.len(), - func(x: Nat): X { elems[x] } - ); - - public func mutArray() : [var X] = { - if (count == 0) { [var] } else { - let a = Array_init(count, elems[0]); - for (i in elems.keys()) { - a[i] := elems[i] - }; - a - } - }; - - public func arrayBuf() : ArrayBuf { - // overcome common field names between source/target objects: - let e = elems; - let c = count; - { var elems = e; - var count = c } - }; - - public func get(offset : Nat) : X { - elems[offset] - }; - - public func getOpt(offset : Nat) : ?X { - if (offset < count) { - ?elems[offset] - } - else { - null - } - }; - - public func set(offset : Nat, elem : X) { - elems[offset] := elem; - }; - - public func getEnd(offset : Nat) : X { - elems[count - offset] - }; - - public func getEndOpt(offset : Nat) : ?X { - if (count > offset) { ?elems[count - offset] } - else { null } - }; - - public func setEnd(offset : Nat, elem : X) { - elems[count - offset] := elem; - }; -}; - -} diff --git a/stdlib/buf.mo b/stdlib/buf.mo index b6437aa03df..7543955fe5e 100644 --- a/stdlib/buf.mo +++ b/stdlib/buf.mo @@ -1,111 +1,135 @@ +import P "prelude.mo"; +import B "buf.mo"; + module { + /** + Buffers =================== -This module defines common types for buffers that grow, with a general element type. - -Implementations of these types are/will be defined elsewhere. +This module defines buffers that grow, with a general element type. ### Why? -Motoko applications expose interfaces that use arrays of general (user-defined) -elements to represent sets, sequences and maps of application-specific -elements. - -To create these arrays, and to consume them with ergonomic (imperative) code, and -low API friction, developers need _buffers that grow_. +Motoko applications expose interfaces that use fixed-size arrays of +general (user-defined) elements to represent sets, sequences and maps +of application-specific elements. The `Array` module focuses on Motoko's builtin arrays, whose size is each fixed. They do not permit general growth/appending, which is the focus here. -### Define `Buf` object type +To create these arrays, and to consume them with ergonomic (imperative) code, and +low API friction, developers need _buffers that grow_. -A "buffer" is a mutable sequence that grows, either one element at a time, or one (second) buffer at time. +### Define `Buf` object type -The only way to access elements is with iteration, or by producing an array (either mutable or immutable). +A "buffer" is a mutable sequence that grows, either one element at a +time, or one (second) buffer at time. -We capture the most basic buffer abstraction with the following `Buf` object type: */ -public type Buf = { - // intro forms: addElm and addBuf - add: X -> (); - addBuf: Buf -> (); - - // utilities: - len: () -> Nat; - clear: () -> (); - clone: () -> Buf; // copies do not interfere across future mutations - - // elim forms for accessing elements: - iter: () -> Iter; - array: () -> [X]; - mutArray: () -> [var X]; - arrayBuf: () -> ArrayBuf; -}; /* - A concrete representation of a growable buffer. - - See [`ArrayBuf`](arrayBuf.mo) for details. +Create a buffer represented internally by an mutable array. - invariants: - 1. the first `count` elements are "filled" in the `elems` array; - 2. any remaining slots in `elems` contain a default value of type `X`. +The argument `initCapacity` gives the initial capacity. Under the +interface, the mutable array grows by doubling when this initial +capacity is exhausted. */ -public type ArrayBuf = { - var elems: [var X]; - var count: Nat; +public class Buf (initCapacity : Nat) { + var count : Nat = 0; + var elems : [var X] = [var]; // initially empty; allocated upon first `add` + + public func add(elem : X) { + if (count == elems.len()) { + let size = + if (count == 0) + initCapacity + else + 2 * elems.len(); + let elems2 = Array_init(size, elem); + for (i in elems.keys()) { + elems2[i] := elems[i]; + }; + elems := elems2; + }; + elems[count] := elem; + count += 1; + }; + + public func append(b:Buf) { + if (count + b.count >= b.len()) { + let size = 2 * count * b.count; + let elems2 = Array_init(size, elems[0]); + for (i in elems.keys()) { + elems2[i] := elems[i]; + }; + elems := elems; + }; + for (i in b.elems.keys()) { + elems[count + i] := b.elems[i]; + }; + count += b.count; + }; + + public func len() : Nat = + count; + + public func clear() = + count := 0; + + public func clone() : Buf { + let c = Buf(initCapacity); + for (elem in iter()) { c.add(elem) }; + c + }; + + public func iter() : Iter = object { + var pos = 0; + public func next() : ?X { + if (pos == count) { null } else { + let elem = ?elems[pos]; + pos += 1; + elem + } + } + }; + + public func toArray() : [X] = + // immutable clone of array + Array_tabulate( + elems.len(), + func(x: Nat): X { elems[x] } + ); + + public func toVarArray() : [var X] = { + if (count == 0) { [var] } else { + let a = Array_init(count, elems[0]); + for (i in elems.keys()) { + a[i] := elems[i] + }; + a + } + }; + + public func get(offset : Nat) : X { + elems[offset] + }; + + public func getOpt(offset : Nat) : ?X { + if (offset < count) { + ?elems[offset] + } + else { + null + } + }; + + public func set(offset : Nat, elem : X) { + elems[offset] := elem; + }; }; -/** - -### Define `IndexedBuf` object type - -A more general version of `Buf` that permits **indexed-based random -access** of its elements, independent of iteration or producing an -auxiliary array. - -##### Addressing accesses and updates - -By default, to _address_ an element for access, we use an offset from -the start of the buffer, beginning at zero. - -Additionally, the abstraction provides access by a (zero-based) offset -from the end (via `getEnd` and `setEnd`). - -*/ - -public type IndexedBuf = { - // intro forms: add and addBuf - add: X -> (); - addBuf: Buf -> (); - - // utilities: - len: () -> Nat; - clear: () -> (); - clone: () -> IndexedBuf; // copies do not interfere across future mutations - - // elim forms for accessing elements: - iter: () -> Iter; - array: () -> [X]; - mutArray: () -> [var X]; - arrayBuf: () -> ArrayBuf; - - // get/set via an offset from the start, beginning at zero. - get : Nat -> X; // out-of-bounds access traps (as with ordinary arrays) - getOpt : Nat -> ?X; // `null` means "out of bounds" - set : (Nat, X) -> (); - - // get/set via an offset from the end, beginning at zero. - getEnd : Nat -> X; // out-of-bounds access traps (as with ordinary arrays) - getEndOpt : Nat -> ?X; // `null` means "out of bounds" - setEnd : (Nat, X) -> (); -}; - -// assert that two types are related by subtyping, without having instances: -func _assertSubtypes(b:IndexedBuf) : Buf = b; - } From e9f7b0de5b96719ad8896d02d8f673756bf3e30a Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 21 Nov 2019 08:30:41 -0700 Subject: [PATCH 0683/1176] oops --- stdlib/buf.mo | 1 - 1 file changed, 1 deletion(-) diff --git a/stdlib/buf.mo b/stdlib/buf.mo index 7543955fe5e..1df577a1301 100644 --- a/stdlib/buf.mo +++ b/stdlib/buf.mo @@ -1,5 +1,4 @@ import P "prelude.mo"; -import B "buf.mo"; module { From b19f69adb18b59b45e838ffb684718e0e4e3b8c2 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 21 Nov 2019 08:35:09 -0700 Subject: [PATCH 0684/1176] fix build --- stdlib/Makefile | 3 +-- stdlib/buf.mo | 5 +++-- stdlib/{arrayBufTest.mo => bufTest.mo} | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) rename stdlib/{arrayBufTest.mo => bufTest.mo} (61%) diff --git a/stdlib/Makefile b/stdlib/Makefile index 025001be4ba..861e3688087 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -17,8 +17,7 @@ WASM=\ TESTS=\ Array \ ArrayTest \ - ArrayBuf \ - ArrayBufTest \ + BufTest \ Buf \ AssocList \ DocTable \ diff --git a/stdlib/buf.mo b/stdlib/buf.mo index 1df577a1301..1081a104446 100644 --- a/stdlib/buf.mo +++ b/stdlib/buf.mo @@ -38,8 +38,9 @@ interface, the mutable array grows by doubling when this initial capacity is exhausted. */ public class Buf (initCapacity : Nat) { - var count : Nat = 0; - var elems : [var X] = [var]; // initially empty; allocated upon first `add` + // TODO: These should be private, but then `append` is not implementable as is. + public var count : Nat = 0; + public var elems : [var X] = [var]; // initially empty; allocated upon first `add` public func add(elem : X) { if (count == elems.len()) { diff --git a/stdlib/arrayBufTest.mo b/stdlib/bufTest.mo similarity index 61% rename from stdlib/arrayBufTest.mo rename to stdlib/bufTest.mo index 7c1b7e600e7..1f972d6d2c3 100644 --- a/stdlib/arrayBufTest.mo +++ b/stdlib/bufTest.mo @@ -1,6 +1,6 @@ -import ArrayBuf "arrayBuf.mo"; +import B "Buf.mo"; -let a = ArrayBuf.Buf(3); +let a = B.Buf(3); for (i in range(0, 123)) { a.add(i); }; From 58277588df418dd264870235cdd7c5c691acc91a Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 21 Nov 2019 08:36:28 -0700 Subject: [PATCH 0685/1176] rename; as per Andreas's comment --- stdlib/array.mo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/array.mo b/stdlib/array.mo index dc7c0aafd25..79227690250 100644 --- a/stdlib/array.mo +++ b/stdlib/array.mo @@ -119,7 +119,7 @@ module { ys; }; - public func Array_tabulate_mut(len : Nat, gen : Nat -> A) : [var A] { + public func TabulateVar(len : Nat, gen : Nat -> A) : [var A] { if (len == 0) { return [var] }; let xs = Array_init(len, gen 0); for (i in range(1,len)) { From f45e3acb05f10df2dbe99b47c3c308da08a1c985 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 21 Nov 2019 08:42:19 -0700 Subject: [PATCH 0686/1176] build fixes --- stdlib/Makefile | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/stdlib/Makefile b/stdlib/Makefile index 861e3688087..287d55f8c82 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -75,13 +75,10 @@ $(OUTDIR)/Array.out: array.mo | $(OUTDIR) $(OUTDIR)/ArrayTest.out: arrayTest.mo | $(OUTDIR) $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ -$(OUTDIR)/ArrayBuf.out: arrayBuf.mo | $(OUTDIR) - $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/ArrayBufTest.out: arrayBufTest.mo | $(OUTDIR) +$(OUTDIR)/Buf.out: buf.mo | $(OUTDIR) $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ -$(OUTDIR)/Buf.out: buf.mo | $(OUTDIR) +$(OUTDIR)/BufTest.out: bufTest.mo | $(OUTDIR) $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ $(OUTDIR)/Function.out: function.mo | $(OUTDIR) @@ -165,7 +162,6 @@ docMd: \ $(DOCDIR)/README.md \ $(DOCDIR)/prelude.md \ $(DOCDIR)/array.md \ - $(DOCDIR)/arrayBuf.md \ $(DOCDIR)/buf.md \ $(DOCDIR)/option.md \ $(DOCDIR)/result.md \ @@ -190,7 +186,6 @@ docHtml: \ $(DOCDIR)/README.html \ $(DOCDIR)/prelude.html \ $(DOCDIR)/array.html \ - $(DOCDIR)/arrayBuf.html \ $(DOCDIR)/buf.html \ $(DOCDIR)/option.html \ $(DOCDIR)/result.html \ From 0377b2740e29d4f02b1e4cee4b8d475daf366690 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 21 Nov 2019 08:44:05 -0700 Subject: [PATCH 0687/1176] typo --- stdlib/bufTest.mo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/bufTest.mo b/stdlib/bufTest.mo index 1f972d6d2c3..04699a3be93 100644 --- a/stdlib/bufTest.mo +++ b/stdlib/bufTest.mo @@ -1,4 +1,4 @@ -import B "Buf.mo"; +import B "buf.mo"; let a = B.Buf(3); for (i in range(0, 123)) { From d834f38a49a813232ff75663db39329dbef3ea21 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Thu, 21 Nov 2019 18:21:28 +0000 Subject: [PATCH 0688/1176] illegal await tests --- test/fail/illegal-await.mo | 46 ++++++++++++++++++++++++++++ test/fail/ok/illegal-await.tc.ok | 5 +++ test/fail/ok/illegal-await.tc.ret.ok | 1 + 3 files changed, 52 insertions(+) create mode 100644 test/fail/illegal-await.mo create mode 100644 test/fail/ok/illegal-await.tc.ok create mode 100644 test/fail/ok/illegal-await.tc.ret.ok diff --git a/test/fail/illegal-await.mo b/test/fail/illegal-await.mo new file mode 100644 index 00000000000..2c8ad87628f --- /dev/null +++ b/test/fail/illegal-await.mo @@ -0,0 +1,46 @@ +// immediate deadlock +{ + let t : async () = async { await t}; +}; + + + +// circular deadlock + +{ + ignore async { + let a1 : async () = async{ await a2; }; // illegal await since a1 : Async() () + let a2 : async () = async{ await a1; }; // illegal await since a2 : Async() () + }; +}; + + +// Imperative deadlock + +{ + ignore async { + var x = async { 0 }; + x := (async { + await x // illegal: await _ : asyncT -> T (not async T -> T) (any T)) + }); + } +}; + +// Recursive deadlock + +shared func Rec<@>(n : Int, a : async ()) : async () { + if (n == 0) { + await a // <- illegal await since async<@>() () + } + else { + await Rec<@>(n-1, a) + } +}; + + +{ + ignore async { + let t : async () = Rec<@>(10,t); + await t; + } +}; \ No newline at end of file diff --git a/test/fail/ok/illegal-await.tc.ok b/test/fail/ok/illegal-await.tc.ok new file mode 100644 index 00000000000..3d5e328ee7b --- /dev/null +++ b/test/fail/ok/illegal-await.tc.ok @@ -0,0 +1,5 @@ +illegal-await.mo:3.30-3.37: type error, ill-scoped await +illegal-await.mo:12.32-12.40: type error, ill-scoped await +illegal-await.mo:13.32-13.40: type error, ill-scoped await +illegal-await.mo:24.7-24.14: type error, ill-scoped await +illegal-await.mo:33.5-33.12: type error, ill-scoped await diff --git a/test/fail/ok/illegal-await.tc.ret.ok b/test/fail/ok/illegal-await.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/illegal-await.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 From f25528bff11279182ba6bfd43f41ae8b8c8d7959 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Thu, 21 Nov 2019 14:14:14 -0800 Subject: [PATCH 0689/1176] Allow passing `system` separately from nixpkgs --- default.nix | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/default.nix b/default.nix index d4acd1fe019..3af81ce96ce 100644 --- a/default.nix +++ b/default.nix @@ -2,10 +2,11 @@ dvm ? null, drun ? null, export-shell ? false, - replay ? 0 + replay ? 0, + system ? nixpkgs.system }: -let llvm = import ./nix/llvm.nix { system = nixpkgs.system; }; in +let llvm = import ./nix/llvm.nix { inherit system; }; in let stdenv = nixpkgs.stdenv; in @@ -16,21 +17,21 @@ let dev = import (builtins.fetchGit { url = "ssh://git@github.com/dfinity-lab/dev"; # ref = "master"; rev = "6fca1936fcd027aaeaccab0beb51defeee38a0ff"; -}) { system = nixpkgs.system; }; in +}) { inherit system; }; in let dfinity-repo = import (builtins.fetchGit { name = "dfinity-sources"; url = "ssh://git@github.com/dfinity-lab/dfinity"; ref = "master"; rev = "5c7efff0524adbf97d85b27adb180e6137a3428f"; -}) { system = nixpkgs.system; }; in +}) { inherit system; }; in let sdk = import (builtins.fetchGit { name = "sdk-sources"; url = "ssh://git@github.com/dfinity-lab/sdk"; ref = "paulyoung/js-user-library"; rev = "42f15621bc5b228c7fd349cb52f265917d33a3a0"; -}) { system = nixpkgs.system; }; in +}) { inherit system; }; in let esm = builtins.fetchTarball { sha256 = "116k10q9v0yzpng9bgdx3xrjm2kppma2db62mnbilbi66dvrvz9q"; From 87162afc46ca6edae4ac558d8372ce7cfb734fa3 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Fri, 22 Nov 2019 11:39:29 +0100 Subject: [PATCH 0690/1176] Lower precedence of assignment ops (#909) Previously, one had to write x := (await ...); now one can write x := await ...; This fixes issue #904. --- src/mo_frontend/parser.mly | 9 ++++----- test/run/issue904.mo | 2 ++ 2 files changed, 6 insertions(+), 5 deletions(-) create mode 100644 test/run/issue904.mo diff --git a/src/mo_frontend/parser.mly b/src/mo_frontend/parser.mly index 13850a20192..e0e726e1650 100644 --- a/src/mo_frontend/parser.mly +++ b/src/mo_frontend/parser.mly @@ -125,7 +125,6 @@ let share_expfield (ef : exp_field) = %nonassoc RETURN_NO_ARG IF_NO_ELSE LOOP_NO_WHILE %nonassoc ELSE WHILE -%right ASSIGN PLUSASSIGN MINUSASSIGN MULASSIGN DIVASSIGN MODASSIGN POWASSIGN CATASSIGN ANDASSIGN ORASSIGN XORASSIGN SHLASSIGN USHRASSIGN SSHRASSIGN ROTLASSIGN ROTRASSIGN %left COLON %left OR %left AND @@ -423,10 +422,6 @@ exp_bin(B) : { BinE(ref Type.Pre, e1, op, e2) @? at $sloc } | e1=exp_bin(ob) op=relop e2=exp_bin(ob) { RelE(ref Type.Pre, e1, op, e2) @? at $sloc } - | e1=exp_bin(ob) ASSIGN e2=exp_bin(ob) - { AssignE(e1, e2) @? at $sloc} - | e1=exp_bin(ob) op=binassign e2=exp_bin(ob) - { assign_op e1 (fun e1' -> BinE(ref Type.Pre, e1', op, e2) @? at $sloc) (at $sloc) } | e1=exp_bin(ob) AND e2=exp_bin(ob) { AndE(e1, e2) @? at $sloc } | e1=exp_bin(ob) OR e2=exp_bin(ob) @@ -437,6 +432,10 @@ exp_bin(B) : exp_nondec(B) : | e=exp_bin(B) { e } + | e1=exp_bin(ob) ASSIGN e2=exp(ob) + { AssignE(e1, e2) @? at $sloc} + | e1=exp_bin(ob) op=binassign e2=exp(ob) + { assign_op e1 (fun e1' -> BinE(ref Type.Pre, e1', op, e2) @? at $sloc) (at $sloc) } | RETURN %prec RETURN_NO_ARG { RetE(TupE([]) @? at $sloc) @? at $sloc } | RETURN e=exp(ob) diff --git a/test/run/issue904.mo b/test/run/issue904.mo new file mode 100644 index 00000000000..92b38febad2 --- /dev/null +++ b/test/run/issue904.mo @@ -0,0 +1,2 @@ +var x = (); +x := ignore (); From 7e8921a3e4b147791f791089f7f3c894b842e094 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 22 Nov 2019 12:01:37 +0100 Subject: [PATCH 0691/1176] Backend: Allow direct self calls (#903) * Allow direct self calls Put in some extra bookkeeping in the compiler to allow ``` actor a { public foo() {}; foo() } ``` and not just, as before, ``` actor a { public foo() {}; a.foo() } ``` * Fix stuff on dvm * Update src/codegen/compile.ml --- src/codegen/compile.ml | 86 ++++++++++++++---------- test/run-stub/ic-calls.mo | 5 +- test/run-stub/ok/ic-calls.ic-stub-run.ok | 6 +- test/run-stub/ok/ic-calls.tc.ok | 4 +- 4 files changed, 63 insertions(+), 38 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index d4959b06244..6e4e4c43119 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -47,7 +47,8 @@ module SR = struct *) type static_thing = | StaticFun of int32 - | StaticMessage of int32 + | StaticMessage of int32 (* anonymous message, only on ancient *) + | PublicMethod of int32 * string (* Value representation on the stack: @@ -3332,6 +3333,17 @@ module Dfinity = struct | Flags.StubMode -> SR.Vanilla | _ -> assert false + (* Actor reference on the stack *) + and actor_public_field env name = + match E.mode env with + | Flags.AncientMode -> + compile_databuf_of_bytes env name ^^ + system_call env "actor" "export" + | Flags.ICMode | Flags.StubMode -> + (* simply tuple canister name and function name *) + Blob.lit env name ^^ + Tuple.from_stack env 2 + | Flags.WasmMode -> assert false end (* Dfinity *) @@ -4724,12 +4736,9 @@ module StackRep = struct let materialize_unboxed_ref env = function | StaticFun fi -> assert false - | StaticMessage fi -> - match E.mode env with - | Flags.AncientMode -> - Dfinity.static_message_funcref env fi - | _ -> - E.trap_with env "cannot call anonymous shared function" + | StaticMessage fi | PublicMethod (fi, _) -> + assert (E.mode env = Flags.AncientMode); + Dfinity.static_message_funcref env fi let materialize env = function | StaticFun fi -> @@ -4739,13 +4748,14 @@ module StackRep = struct compile_unboxed_const fi; compile_unboxed_zero (* number of parameters: none *) ] + | (StaticMessage fi | PublicMethod (fi, _)) when E.mode env = Flags.AncientMode -> + Dfinity.static_message_funcref env fi ^^ + Dfinity.box_reference env | StaticMessage fi -> - match E.mode env with - | Flags.AncientMode -> - Dfinity.static_message_funcref env fi ^^ - Dfinity.box_reference env - | _ -> - E.trap_with env "cannot call anonymous shared function" + assert false + | PublicMethod (_, name) -> + Dfinity.get_self_reference env ^^ + Dfinity.actor_public_field env name let adjust env (sr_in : t) sr_out = if sr_in = sr_out @@ -6334,7 +6344,7 @@ and compile_exp (env : E.t) ae exp = | ActorDotE (e, name) -> Dfinity.reference_sr env, compile_exp_as env ae (Dfinity.reference_sr env) e ^^ - actor_fake_object_idx env name + Dfinity.actor_public_field env name | PrimE (p, es) -> (* for more concise code when all arguments and result use the same sr *) @@ -7109,13 +7119,25 @@ and compile_n_ary_pat env ae how pat = orTrap env (fill_pat env ae1 pat) in (ae1, alloc_code, arity, fill_code) -and compile_dec env pre_ae how dec : VarEnv.t * G.t * (VarEnv.t -> G.t) = +and compile_dec env pre_ae how v2en dec : VarEnv.t * G.t * (VarEnv.t -> G.t) = (fun (pre_ae,alloc_code,mk_code) -> (pre_ae, G.with_region dec.at alloc_code, fun ae -> G.with_region dec.at (mk_code ae))) @@ match dec.it with | TypD _ -> (pre_ae, G.nop, fun _ -> G.nop) + (* A special case for public methods *) + (* This relies on the fact that in the top-level mutually recursive group, no shadowing happens. *) + | LetD ({it = VarP v; _}, e) when E.NameEnv.mem v v2en -> + let (static_thing, fill) = compile_static_exp env pre_ae how e in + let fi = match static_thing with + | SR.StaticMessage fi -> fi + | _ -> assert false in + let pre_ae1 = VarEnv.add_local_deferred pre_ae v + (SR.StaticThing (SR.PublicMethod (fi, (E.NameEnv.find v v2en)))) + (fun _ -> G.nop) false in + ( pre_ae1, G.nop, fun ae -> fill env ae; G.nop) + (* A special case for static expressions *) | LetD ({it = VarP v; _}, e) when not (AllocHow.M.mem v how) -> let (static_thing, fill) = compile_static_exp env pre_ae how e in @@ -7140,12 +7162,15 @@ and compile_dec env pre_ae how dec : VarEnv.t * G.t * (VarEnv.t -> G.t) = ) and compile_decs env ae lvl decs captured_in_body : VarEnv.t * G.t = + compile_decs_public env ae lvl decs E.NameEnv.empty captured_in_body + +and compile_decs_public env ae lvl decs v2en captured_in_body : VarEnv.t * G.t = let how = AllocHow.decs ae lvl decs captured_in_body in let rec go pre_ae decs = match decs with | [] -> (pre_ae, G.nop, fun _ -> G.nop) - | [dec] -> compile_dec env pre_ae how dec + | [dec] -> compile_dec env pre_ae how v2en dec | (dec::decs) -> - let (pre_ae1, alloc_code1, mk_code1) = compile_dec env pre_ae how dec in + let (pre_ae1, alloc_code1, mk_code1) = compile_dec env pre_ae how v2en dec in let (pre_ae2, alloc_code2, mk_code2) = go pre_ae1 decs in ( pre_ae2, alloc_code1 ^^ alloc_code2, @@ -7252,9 +7277,9 @@ and compile_start_func mod_env (progs : Ir.prog list) : E.func_with_names = and export_actor_field env ae (f : Ir.field) = let sr, code = Var.get_val env ae f.it.var in - (* A public actor field is guaranteed to be compiled as a StaticMessage *) + (* A public actor field is guaranteed to be compiled as a PublicMethod *) let fi = match sr with - | SR.StaticThing (SR.StaticMessage fi) -> fi + | SR.StaticThing (SR.PublicMethod (fi, _)) -> fi | _ -> assert false in (* There should be no code associated with this *) assert (G.is_nop code); @@ -7311,8 +7336,11 @@ and actor_lit outer_env this ds fs at = (* Add this pointer *) let ae2 = VarEnv.add_local_deferred ae1 this SR.Vanilla Dfinity.get_self_reference false in + (* Reverse the fs, to a map from variable to exported name *) + let v2en = E.NameEnv.from_list (List.map (fun f -> (f.it.var, f.it.name)) fs) in + (* Compile the declarations *) - let (ae3, decls_code) = compile_decs env ae2 AllocHow.TopLvl ds Freevars.S.empty in + let (ae3, decls_code) = compile_decs_public env ae2 AllocHow.TopLvl ds v2en Freevars.S.empty in (* Export the public functions *) List.iter (export_actor_field env ae3) fs; @@ -7368,27 +7396,17 @@ and main_actor env ae1 this ds fs = (* Add this pointer *) let ae2 = VarEnv.add_local_deferred ae1 this SR.Vanilla Dfinity.get_self_reference false in + (* Reverse the fs, to a map from variable to exported name *) + let v2en = E.NameEnv.from_list (List.map (fun f -> (f.it.var, f.it.name)) fs) in + (* Compile the declarations *) - let (ae3, decls_code) = compile_decs env ae2 AllocHow.TopLvl ds Freevars.S.empty in + let (ae3, decls_code) = compile_decs_public env ae2 AllocHow.TopLvl ds v2en Freevars.S.empty in (* Export the public functions *) List.iter (export_actor_field env ae3) fs; decls_code -(* Actor reference on the stack *) -and actor_fake_object_idx env name = - match E.mode env with - | Flags.AncientMode -> - Dfinity.compile_databuf_of_bytes env name ^^ - Dfinity.system_call env "actor" "export" - | Flags.ICMode | Flags.StubMode -> - (* simply tuple canister name and function name *) - Blob.lit env name ^^ - Tuple.from_stack env 2 - | Flags.WasmMode -> assert false - - and conclude_module env module_name start_fi_o = (* add beginning-of-heap pointer, may be changed by linker *) diff --git a/test/run-stub/ic-calls.mo b/test/run-stub/ic-calls.mo index 32d4a947f77..80333ac8c9f 100644 --- a/test/run-stub/ic-calls.mo +++ b/test/run-stub/ic-calls.mo @@ -1,15 +1,17 @@ actor X { - public func A() : async () { + debugPrint("A"); }; public func B(x : Int) : async Int { + debugPrint("B"); x }; public func C(x : Int, y: Bool) : async (Int,Bool) { + debugPrint("C"); (x,y); }; @@ -17,6 +19,7 @@ actor X { let () = await A(); let 1 = await B(1); let (1,true) = await C(1,true); + debugPrint("test"); }; } diff --git a/test/run-stub/ok/ic-calls.ic-stub-run.ok b/test/run-stub/ok/ic-calls.ic-stub-run.ok index 0a14e248fd2..baf78b4a60a 100644 --- a/test/run-stub/ok/ic-calls.ic-stub-run.ok +++ b/test/run-stub/ok/ic-calls.ic-stub-run.ok @@ -3,4 +3,8 @@ → install ← completed → update test(0x4449444c0000) -← rejected (RC_CANISTER_ERROR): canister trapped: EvalTrapError :0.1 "canister trapped explicitly: cannot call anonymous shared function" +A +B +C +test +← completed: 0x4449444c0000 diff --git a/test/run-stub/ok/ic-calls.tc.ok b/test/run-stub/ok/ic-calls.tc.ok index dec54dfc5ac..226f38933fc 100644 --- a/test/run-stub/ok/ic-calls.tc.ok +++ b/test/run-stub/ok/ic-calls.tc.ok @@ -1,8 +1,8 @@ -ic-calls.mo:18.9-18.10: warning, this pattern consuming type +ic-calls.mo:20.9-20.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -ic-calls.mo:19.9-19.17: warning, this pattern consuming type +ic-calls.mo:21.9-21.17: warning, this pattern consuming type (Int, Bool) does not cover value (1, false) or From 5230bb18be10ed472233315f40ae8dfbb7247264 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 22 Nov 2019 12:32:11 +0100 Subject: [PATCH 0692/1176] debugPrint should not be passed a newline (#902) this updates the interpreter, the compilation on `dvm` and the test suite. Some test suite output is less pretty now. --- src/codegen/compile.ml | 9 +- src/mo_values/prim.ml | 2 +- test/bugs/aritybug.mo | 2 +- test/fail/actor-reexport.mo | 2 +- test/fail/branch-before-define.mo | 4 +- test/fail/return-before-define.mo | 4 +- test/run-dfinity/async-new-obj.mo | 20 +- test/run-dfinity/async-obj-mut.mo | 3 +- test/run-dfinity/await.mo | 6 +- test/run-dfinity/chat.mo | 2 +- test/run-dfinity/chatpp.mo | 5 +- test/run-dfinity/closure-params.mo | 11 +- test/run-dfinity/counter.mo | 4 +- test/run-dfinity/flatten-awaitables.mo | 74 ++-- test/run-dfinity/hello-world-await.mo | 2 +- test/run-dfinity/local-throw.mo | 4 +- test/run-dfinity/nary-async.mo | 24 +- test/run-dfinity/ok/async-loop-while.dvm.ok | 13 +- .../run-dfinity/ok/async-loop-while.run-ir.ok | 13 +- .../ok/async-loop-while.run-low.ok | 13 +- test/run-dfinity/ok/async-loop-while.run.ok | 13 +- test/run-dfinity/ok/async-loop.dvm.ok | 13 +- test/run-dfinity/ok/async-loop.run-ir.ok | 13 +- test/run-dfinity/ok/async-loop.run-low.ok | 13 +- test/run-dfinity/ok/async-loop.run.ok | 13 +- test/run-dfinity/ok/async-obj-mut.dvm.ok | 9 +- test/run-dfinity/ok/async-obj-mut.run-ir.ok | 9 +- test/run-dfinity/ok/async-obj-mut.run-low.ok | 9 +- test/run-dfinity/ok/async-obj-mut.run.ok | 9 +- test/run-dfinity/ok/async-while.dvm.ok | 13 +- test/run-dfinity/ok/async-while.run-ir.ok | 13 +- test/run-dfinity/ok/async-while.run-low.ok | 13 +- test/run-dfinity/ok/async-while.run.ok | 13 +- test/run-dfinity/ok/await.dvm.ok | 27 +- test/run-dfinity/ok/await.run-ir.ok | 23 +- test/run-dfinity/ok/await.run-low.ok | 23 +- test/run-dfinity/ok/await.run.ok | 23 +- test/run-dfinity/ok/block.dvm.ok | 11 +- test/run-dfinity/ok/block.run-ir.ok | 11 +- test/run-dfinity/ok/block.run-low.ok | 11 +- test/run-dfinity/ok/block.run.ok | 11 +- test/run-dfinity/ok/chatpp.dvm.ok | 9 +- test/run-dfinity/ok/chatpp.run-ir.ok | 9 +- test/run-dfinity/ok/chatpp.run-low.ok | 9 +- test/run-dfinity/ok/chatpp.run.ok | 9 +- test/run-dfinity/ok/counter-class.dvm.ok | 1 + test/run-dfinity/ok/flatten-awaitables.dvm.ok | 35 +- .../ok/flatten-awaitables.run-ir.ok | 35 +- .../ok/flatten-awaitables.run-low.ok | 35 +- test/run-dfinity/ok/flatten-awaitables.run.ok | 35 +- test/run-dfinity/ok/flatten-awaitables.tc.ok | 48 +-- test/run-dfinity/ok/for-await.dvm.ok | 12 +- test/run-dfinity/ok/for-await.run-ir.ok | 12 +- test/run-dfinity/ok/for-await.run-low.ok | 12 +- test/run-dfinity/ok/for-await.run.ok | 12 +- test/run-dfinity/ok/indirect-counter.dvm.ok | 5 +- .../run-dfinity/ok/indirect-counter.run-ir.ok | 5 +- .../ok/indirect-counter.run-low.ok | 5 +- test/run-dfinity/ok/indirect-counter.run.ok | 5 +- test/run-dfinity/ok/local-throw.dvm.ok | 5 +- test/run-dfinity/ok/local-throw.run-ir.ok | 5 +- test/run-dfinity/ok/local-throw.run-low.ok | 5 +- test/run-dfinity/ok/local-throw.run.ok | 5 +- test/run-dfinity/ok/nary-async.dvm.ok | 3 +- test/run-dfinity/ok/nary-async.run-ir.ok | 3 +- test/run-dfinity/ok/nary-async.run-low.ok | 3 +- test/run-dfinity/ok/nary-async.run.ok | 3 +- test/run-dfinity/ok/overflow.dvm.ok | 2 + test/run-dfinity/ok/query.dvm.ok | 6 +- test/run-dfinity/ok/query.run-ir.ok | 6 +- test/run-dfinity/ok/query.run-low.ok | 6 +- test/run-dfinity/ok/query.run.ok | 6 +- test/run-dfinity/ok/simple-throw.dvm.ok | 6 +- test/run-dfinity/ok/simple-throw.run-ir.ok | 6 +- test/run-dfinity/ok/simple-throw.run-low.ok | 6 +- test/run-dfinity/ok/simple-throw.run.ok | 6 +- test/run-dfinity/overflow.mo | 14 +- test/run-dfinity/query.mo | 6 +- test/run-dfinity/reference-params.mo | 6 +- test/run-drun/array-out-of-bounds.mo | 4 +- test/run-drun/counter.mo | 4 +- test/run-drun/counter2.mo | 4 +- test/run-drun/hello-world-message.mo | 2 +- test/run-drun/hello-world-message2.mo | 2 +- test/run-drun/hello-world.mo | 2 +- test/run-drun/ok/counter.drun-run.ok | 8 - test/run-drun/ok/generic-tail-rec.run-ir.ok | 5 +- test/run-drun/ok/generic-tail-rec.run-low.ok | 5 +- test/run-drun/ok/generic-tail-rec.run.ok | 5 +- test/run-drun/ok/hello-world.drun-run.ok | 1 - test/run-drun/ok/query.drun-run.ok | 16 - test/run-drun/ok/selftail.drun-run.ok | 6 +- test/run-drun/ok/selftail.run-ir.ok | 4 +- test/run-drun/ok/selftail.run-low.ok | 4 +- test/run-drun/ok/selftail.run.ok | 4 +- test/run-drun/ok/show.drun-run.ok | 35 -- test/run-drun/ok/tailpositions.drun-run.ok | 7 - test/run-drun/ok/test_oneway.run-ir.ok | 12 +- test/run-drun/ok/test_oneway.run-low.ok | 12 +- test/run-drun/ok/test_oneway.run.ok | 12 +- test/run-drun/ok/text-iter.drun-run.ok | 23 -- test/run-drun/ok/text-iter.run-ir.ok | 223 +++++++++++- test/run-drun/ok/text-iter.run-low.ok | 223 +++++++++++- test/run-drun/ok/text-iter.run.ok | 223 +++++++++++- test/run-drun/query.mo | 6 +- test/run-drun/selftail.mo | 6 +- test/run-drun/show.mo | 71 ++-- test/run-drun/tailpositions.mo | 14 +- test/run-drun/text-iter.mo | 28 +- test/run-release/debug.mo | 6 +- test/run-stub/actor-creation.mo | 18 +- test/run-stub/counter.mo | 4 +- test/run-stub/hello-world-async.mo | 2 +- .../run-stub/ok/actor-creation.ic-stub-run.ok | 9 - test/run-stub/ok/counter.ic-stub-run.ok | 8 - .../ok/hello-world-async.ic-stub-run.ok | 1 - test/run-stub/ok/query.ic-stub-run.ok | 16 - test/run-stub/query.mo | 6 +- test/run/conversions.mo | 2 +- test/run/idlHash.mo | 6 +- test/run/numeric-ops.mo | 4 +- test/run/ok/for.run-ir.ok | 12 +- test/run/ok/for.run-low.ok | 12 +- test/run/ok/for.run.ok | 12 +- test/run/ok/idlHash.run-ir.ok | 10 +- test/run/ok/idlHash.run-low.ok | 10 +- test/run/ok/idlHash.run.ok | 10 +- test/run/ok/words.run-ir.ok | 344 +++++++++++++----- test/run/ok/words.run-low.ok | 344 +++++++++++++----- test/run/ok/words.run.ok | 344 +++++++++++++----- test/run/variants.mo | 4 +- test/run/words.mo | 10 +- 132 files changed, 2299 insertions(+), 777 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 6e4e4c43119..26d214c5996 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -3144,8 +3144,13 @@ module Dfinity = struct system_call env "ic0" "debug_print" ) | Flags.AncientMode -> - compile_databuf_of_text env ^^ - system_call env "test" "print" + Func.share_code1 env "print_text" ("str", I32Type) [] (fun env get_str -> + get_str ^^ + Blob.lit env "\n" ^^ + Blob.concat env ^^ + compile_databuf_of_text env ^^ + system_call env "test" "print" + ) (* For debugging *) let compile_static_print env s = diff --git a/src/mo_values/prim.ml b/src/mo_values/prim.ml index d05f2bbea8b..e4c0fb5084a 100644 --- a/src/mo_values/prim.ml +++ b/src/mo_values/prim.ml @@ -240,7 +240,7 @@ let prim = function | c when c <= 0o177 -> String.make 1 (Char.chr c) | code -> Wasm.Utf8.encode [code] in k (Text str) - | "print" -> fun v k -> Printf.printf "%s%!" (as_text v); k unit + | "print" -> fun v k -> Printf.printf "%s\n%!" (as_text v); k unit | "rts_version" -> fun v k -> as_unit v; k (Text "0.1") | "idlHash" -> fun v k -> let s = as_text v in k (Word32 (Lib.Uint32.to_int32 (Idllib.IdlHash.idl_hash s))) | "decodeUTF8" -> fun v k -> diff --git a/test/bugs/aritybug.mo b/test/bugs/aritybug.mo index f2d116f3816..aafd6353565 100644 --- a/test/bugs/aritybug.mo +++ b/test/bugs/aritybug.mo @@ -8,7 +8,7 @@ // eventhough Int != Tup[Int] { -let t = "u_u\n"; +let t = "u_u"; shared func fu_u(a:Int,) : async (Int,) { return (2*a,); }; diff --git a/test/fail/actor-reexport.mo b/test/fail/actor-reexport.mo index a8de5e653b3..51b75c6162d 100644 --- a/test/fail/actor-reexport.mo +++ b/test/fail/actor-reexport.mo @@ -1,6 +1,6 @@ actor test { public func exported() { - debugPrint("exported()\n"); + debugPrint("exported()"); }; public let exported_too = exported; }; diff --git a/test/fail/branch-before-define.mo b/test/fail/branch-before-define.mo index 8f4013aefc7..88877861117 100644 --- a/test/fail/branch-before-define.mo +++ b/test/fail/branch-before-define.mo @@ -8,8 +8,8 @@ func f():() -> Int { }; }; -debugPrint "1\n"; +debugPrint "1"; let h = f(); -debugPrint "2\n"; +debugPrint "2"; let wrong = h(); diff --git a/test/fail/return-before-define.mo b/test/fail/return-before-define.mo index b40307b33aa..d6aaf72b8e8 100644 --- a/test/fail/return-before-define.mo +++ b/test/fail/return-before-define.mo @@ -6,8 +6,8 @@ func f():() -> Int { }; }; -debugPrint "1\n"; +debugPrint "1"; let h = f(); -debugPrint "2\n"; +debugPrint "2"; let wrong = h(); diff --git a/test/run-dfinity/async-new-obj.mo b/test/run-dfinity/async-new-obj.mo index 8fc5b63e46c..68015a6f376 100644 --- a/test/run-dfinity/async-new-obj.mo +++ b/test/run-dfinity/async-new-obj.mo @@ -8,9 +8,7 @@ let a = async { public func get_b() : Text { b }; }; let (a, b) = (o.get_a(), o.get_b()); - debugPrint a; - debugPrint b; - debugPrint "\n"; + debugPrint (a#b); }; let b = async { @@ -21,9 +19,7 @@ let b = async { public func get_b() : Text { b }; }; let (a, b) = (o.get_a(), o.get_b()); - debugPrint a; - debugPrint b; - debugPrint "\n"; + debugPrint (a#b); }; let c = async { @@ -34,9 +30,7 @@ let c = async { public func get_b() : Text { b }; }; let (a, b) = (o.get_a(), o.get_b()); - debugPrint a; - debugPrint b; - debugPrint "\n"; + debugPrint (a#b); }; let d = async { @@ -47,9 +41,7 @@ let d = async { public func get_b() : Text { b }; }; let (a, b) = (o.get_a(), o.get_b()); - debugPrint a; - debugPrint b; - debugPrint "\n"; + debugPrint (a#b); }; let e = async { @@ -63,7 +55,5 @@ let e = async { }; }; let (a, b) = o.get_ab(); - debugPrint a; - debugPrint b; - debugPrint "\n"; + debugPrint (a#b); }; diff --git a/test/run-dfinity/async-obj-mut.mo b/test/run-dfinity/async-obj-mut.mo index c12dbe176ff..eeca3235c2d 100644 --- a/test/run-dfinity/async-obj-mut.mo +++ b/test/run-dfinity/async-obj-mut.mo @@ -9,11 +9,10 @@ let _ = async { let e = foo(); let f = debugPrintNat(x); }; - debugPrint("\ndone creating\n"); + debugPrint("done creating\n"); debugPrintNat(o.x); o.x := o.x + 1; debugPrintNat(o.x); o.foo(); debugPrintNat(o.x); - debugPrint("\n"); } diff --git a/test/run-dfinity/await.mo b/test/run-dfinity/await.mo index e0ef91846fd..e0d76b87158 100644 --- a/test/run-dfinity/await.mo +++ b/test/run-dfinity/await.mo @@ -1,11 +1,7 @@ var cnt : Nat = 0; func f(i:Nat) : async Nat { - debugPrint "cnt: "; - debugPrintNat cnt; - debugPrint " i: "; - debugPrintNat i; - debugPrint "\n"; + debugPrint ("cnt: " # debug_show cnt # " i: " # debug_show i); cnt += 1; cnt; }; diff --git a/test/run-dfinity/chat.mo b/test/run-dfinity/chat.mo index 404e9f91764..520aeaf38fe 100644 --- a/test/run-dfinity/chat.mo +++ b/test/run-dfinity/chat.mo @@ -42,7 +42,7 @@ actor class Client() = this { }; public func send(msg : Text) { - debugPrint(name # " received " # msg # "\n"); + debugPrint(name # " received " # msg); }; }; diff --git a/test/run-dfinity/chatpp.mo b/test/run-dfinity/chatpp.mo index a60cc39a671..6da6492d316 100644 --- a/test/run-dfinity/chatpp.mo +++ b/test/run-dfinity/chatpp.mo @@ -53,7 +53,8 @@ actor class Server() = { case null { clients := n.tail }; case (?p) { p.tail := n.tail }; }; - debugPrint "(unsubscribe "; debugPrintNat id; debugPrint ")\n"; + debugPrint "unsubscribe "; + debugPrintInt id; return; }; prev := next; @@ -81,7 +82,7 @@ actor class Client() = this { }; public func send(msg : Text) { - debugPrint(name # " received " # msg # "\n"); + debugPrint(name # " received " # msg); }; }; diff --git a/test/run-dfinity/closure-params.mo b/test/run-dfinity/closure-params.mo index 41610aed90c..984b5b7c452 100644 --- a/test/run-dfinity/closure-params.mo +++ b/test/run-dfinity/closure-params.mo @@ -3,7 +3,6 @@ let a = actor { public func incn(n : Nat) : () { c += n; debugPrintNat(c); - debugPrint("\n"); }; public func readCounter(f : shared Nat -> ()) : () { f(c); @@ -11,12 +10,12 @@ let a = actor { }; a.incn(1); -a.readCounter(shared func (n : Nat) = { debugPrintNat n; debugPrint("\n") }); +a.readCounter(shared func (n : Nat) = { debugPrintNat n }); a.incn(2); -a.readCounter(shared func (n : Nat) = { debugPrintNat n; debugPrint("\n") }); +a.readCounter(shared func (n : Nat) = { debugPrintNat n }); a.incn(3); -a.readCounter(shared func (n : Nat) = { debugPrintNat n; debugPrint("\n") }); +a.readCounter(shared func (n : Nat) = { debugPrintNat n }); a.incn(4); -a.readCounter(shared func (n : Nat) = { debugPrintNat n; debugPrint("\n") }); +a.readCounter(shared func (n : Nat) = { debugPrintNat n }); a.incn(5); -a.readCounter(shared func (n : Nat) = { debugPrintNat n; debugPrint("\n") }); +a.readCounter(shared func (n : Nat) = { debugPrintNat n }); diff --git a/test/run-dfinity/counter.mo b/test/run-dfinity/counter.mo index dbc84f4e52b..3692a2279fc 100644 --- a/test/run-dfinity/counter.mo +++ b/test/run-dfinity/counter.mo @@ -2,10 +2,10 @@ let a = actor { var c = 1; public func inc() { c += 1; - debugPrintNat c; debugPrint "\n"; + debugPrintNat c; }; public func printCounter () { - debugPrintNat c; debugPrint "\n"; + debugPrintNat c; } }; diff --git a/test/run-dfinity/flatten-awaitables.mo b/test/run-dfinity/flatten-awaitables.mo index f8c4c87a756..2e2082e4529 100644 --- a/test/run-dfinity/flatten-awaitables.mo +++ b/test/run-dfinity/flatten-awaitables.mo @@ -32,29 +32,27 @@ let a = actor { }; -func println(s:Text) {debugPrint s;debugPrint ",";}; - let _ = async { - println "\nfirst-order\n"; + debugPrint "first-order"; let () = await a.m0(); - println "0"; + debugPrint "0"; let 1 = await a.m1(1); - println "1"; + debugPrint "1"; let (2,true) = await a.m2(2,true); - println "2"; + debugPrint "2"; let (3,false,"text") = await a.m3(3,false,"text"); - println "3"; + debugPrint "3"; let () = await a.n0(); - println "4"; + debugPrint "4"; let 1 = await a.n1(1); - println "5"; + debugPrint "5"; let (2,true) = await a.n2(2,true); - println "6"; + debugPrint "6"; let (3,false,"text") = await a.n3(3,false,"text"); - println "7"; + debugPrint "7"; let u = (); let x:Int = 1; @@ -62,60 +60,58 @@ let _ = async { let xyz:(Int,Bool,Text) = (3,false,"text"); let () = await a.m0 u; - println "8"; + debugPrint "8"; let 1 = await a.m1 x; - println "9"; + debugPrint "9"; let (2,true) = await a.m2 xy; - println "10"; + debugPrint "10"; let (3,false,"text") = await a.m3 xyz; - println "11"; + debugPrint "11"; let () = await a.n0 u; - println "12"; + debugPrint "12"; let 1 = await a.n1 x; - println "13"; + debugPrint "13"; let (2,true) = await a.n2 xy; - println "14"; + debugPrint "14"; let (3,false,"text") = await a.n3 xyz; - println "15"; - - println "\nhigher-order\n"; + debugPrint "15"; + + debugPrint "higher-order"; let () = await a.h0(a.m0,()); - println "0"; + debugPrint "0"; let 1 = await a.h1(a.m1,1); - println "1"; + debugPrint "1"; let (2,true) = await a.h2(a.m2,(2,true)); - println "2"; + debugPrint "2"; let (3,false,"text") = await a.h3(a.m3,(3,false,"text")); - println "3"; + debugPrint "3"; let () = await a.g0(a.n0,()); - println "4"; + debugPrint "4"; let 1 = await a.g1(a.n1,1); - println "5"; + debugPrint "5"; let (2,true) = await a.g2(a.n2,(2,true)); - println "6"; + debugPrint "6"; let (3,false,"text") = await a.g3(a.n3,(3,false,"text")); - println "7"; + debugPrint "7"; let () = await a.h0(a.m0,u); - println "8"; + debugPrint "8"; let 1 = await a.h1(a.m1,x); - println "9"; + debugPrint "9"; let (2,true) = await a.h2(a.m2,xy); - println "10"; + debugPrint "10"; let (3,false,"text") = await a.h3(a.m3,xyz); - println "11"; + debugPrint "11"; let () = await a.g0(a.n0,u); - println "12"; + debugPrint "12"; let 1 = await a.g1(a.n1,x); - println "13"; + debugPrint "13"; let (2,true) = await a.g2(a.n2,xy); - println "14"; + debugPrint "14"; let (3,false,"text") = await a.g3(a.n3,xyz); - println "15"; - - debugPrint "\n"; + debugPrint "15"; }; diff --git a/test/run-dfinity/hello-world-await.mo b/test/run-dfinity/hello-world-await.mo index b5549411073..1d3eb8d9261 100644 --- a/test/run-dfinity/hello-world-await.mo +++ b/test/run-dfinity/hello-world-await.mo @@ -3,7 +3,7 @@ let a = actor { "Hello "; }; public func world() : async Text { - "World!\n" + "World!" }; public func go() : async () { debugPrint((await hello()) # (await world())); diff --git a/test/run-dfinity/local-throw.mo b/test/run-dfinity/local-throw.mo index de25bb8c696..742a038e177 100644 --- a/test/run-dfinity/local-throw.mo +++ b/test/run-dfinity/local-throw.mo @@ -51,14 +51,14 @@ async { try { await t2(); - debugPrint ("\n t2 ok"); + debugPrint ("t2 ok"); } catch _ { assert false; }; try { await t3(); - debugPrint ("\n t3 ok"); + debugPrint ("t3 ok"); } catch _ { assert false; }; diff --git a/test/run-dfinity/nary-async.mo b/test/run-dfinity/nary-async.mo index 3875884af34..7ad1a042c03 100644 --- a/test/run-dfinity/nary-async.mo +++ b/test/run-dfinity/nary-async.mo @@ -2,7 +2,7 @@ /* n-ary args */ { -let t = "0_0\n"; +let t = "0_0"; shared func f0_0() : async () {}; let _ : async () = async { await f0_0(); @@ -11,7 +11,7 @@ let _ : async () = async { }; { -let t = "1_0\n"; +let t = "1_0"; shared func f1_0(x:Int) : async () { assert(x == 1); }; @@ -22,7 +22,7 @@ let _ : async () = async { }; { -let t = "2_0\n"; +let t = "2_0"; shared func f2_0(x:Int,y:Bool) : async () { assert(x==1); assert(y==true); @@ -34,7 +34,7 @@ let _ : async () = async { }; { -let t = "3_0\n"; +let t = "3_0"; shared func f3_0(x:Int,y:Bool,z:Text) : async () { assert(x == 1); assert(y == true); @@ -49,7 +49,7 @@ let _ : async () = async { /* n-ary returns */ { -let t = "0_0\n"; +let t = "0_0"; shared func f0_0() : async () {}; let _ : async () = async { await f0_0(); @@ -58,7 +58,7 @@ let _ : async () = async { }; { -let t = "0_1\n"; +let t = "0_1"; shared func f0_1() : async Int { 1; }; @@ -72,7 +72,7 @@ let _ : async Int = async { }; { -let t = "0_2\n"; +let t = "0_2"; shared func f0_2() : async (Int,Bool) { (1,true); }; @@ -87,7 +87,7 @@ let _ : async (Int,Bool) = async { { -let t = "0_3\n!!"; +let t = "0_3!!"; shared func f0_3() : async (Int,Bool,Text) { (1,true,"a"); }; @@ -106,7 +106,7 @@ let _ : async (Int,Bool,Text) = async { /* special case: unary tuples */ /* { -let t = "(1)-(1)\n"; +let t = "(1)-(1)"; shared func fu_u(a:Int,) : async (Int,) { return (2*a,); }; @@ -137,11 +137,11 @@ let _ : async T = async { }; -Generic("\n", 1, func eq(i:Int,j:Int) : Bool = i == j); +Generic("", 1, func eq(i:Int,j:Int) : Bool = i == j); -Generic<()>("<()>\n", (), func eq(i:(),j:()) : Bool = true); +Generic<()>("<()>", (), func eq(i:(),j:()) : Bool = true); -Generic<(Int,Bool)>("<(Int,Bool)>\n", (1,true), +Generic<(Int,Bool)>("<(Int,Bool)>", (1,true), func eq((i,b):(Int,Bool), (j,c):(Int,Bool)) : Bool = i == j and b == c); */ diff --git a/test/run-dfinity/ok/async-loop-while.dvm.ok b/test/run-dfinity/ok/async-loop-while.dvm.ok index f97e06e398a..4e57a41a93e 100644 --- a/test/run-dfinity/ok/async-loop-while.dvm.ok +++ b/test/run-dfinity/ok/async-loop-while.dvm.ok @@ -1 +1,12 @@ -012012012012 +0 +1 +2 +0 +1 +2 +0 +1 +2 +0 +1 +2 diff --git a/test/run-dfinity/ok/async-loop-while.run-ir.ok b/test/run-dfinity/ok/async-loop-while.run-ir.ok index f97e06e398a..4e57a41a93e 100644 --- a/test/run-dfinity/ok/async-loop-while.run-ir.ok +++ b/test/run-dfinity/ok/async-loop-while.run-ir.ok @@ -1 +1,12 @@ -012012012012 +0 +1 +2 +0 +1 +2 +0 +1 +2 +0 +1 +2 diff --git a/test/run-dfinity/ok/async-loop-while.run-low.ok b/test/run-dfinity/ok/async-loop-while.run-low.ok index f97e06e398a..4e57a41a93e 100644 --- a/test/run-dfinity/ok/async-loop-while.run-low.ok +++ b/test/run-dfinity/ok/async-loop-while.run-low.ok @@ -1 +1,12 @@ -012012012012 +0 +1 +2 +0 +1 +2 +0 +1 +2 +0 +1 +2 diff --git a/test/run-dfinity/ok/async-loop-while.run.ok b/test/run-dfinity/ok/async-loop-while.run.ok index f97e06e398a..4e57a41a93e 100644 --- a/test/run-dfinity/ok/async-loop-while.run.ok +++ b/test/run-dfinity/ok/async-loop-while.run.ok @@ -1 +1,12 @@ -012012012012 +0 +1 +2 +0 +1 +2 +0 +1 +2 +0 +1 +2 diff --git a/test/run-dfinity/ok/async-loop.dvm.ok b/test/run-dfinity/ok/async-loop.dvm.ok index f97e06e398a..4e57a41a93e 100644 --- a/test/run-dfinity/ok/async-loop.dvm.ok +++ b/test/run-dfinity/ok/async-loop.dvm.ok @@ -1 +1,12 @@ -012012012012 +0 +1 +2 +0 +1 +2 +0 +1 +2 +0 +1 +2 diff --git a/test/run-dfinity/ok/async-loop.run-ir.ok b/test/run-dfinity/ok/async-loop.run-ir.ok index f97e06e398a..4e57a41a93e 100644 --- a/test/run-dfinity/ok/async-loop.run-ir.ok +++ b/test/run-dfinity/ok/async-loop.run-ir.ok @@ -1 +1,12 @@ -012012012012 +0 +1 +2 +0 +1 +2 +0 +1 +2 +0 +1 +2 diff --git a/test/run-dfinity/ok/async-loop.run-low.ok b/test/run-dfinity/ok/async-loop.run-low.ok index f97e06e398a..4e57a41a93e 100644 --- a/test/run-dfinity/ok/async-loop.run-low.ok +++ b/test/run-dfinity/ok/async-loop.run-low.ok @@ -1 +1,12 @@ -012012012012 +0 +1 +2 +0 +1 +2 +0 +1 +2 +0 +1 +2 diff --git a/test/run-dfinity/ok/async-loop.run.ok b/test/run-dfinity/ok/async-loop.run.ok index f97e06e398a..4e57a41a93e 100644 --- a/test/run-dfinity/ok/async-loop.run.ok +++ b/test/run-dfinity/ok/async-loop.run.ok @@ -1 +1,12 @@ -012012012012 +0 +1 +2 +0 +1 +2 +0 +1 +2 +0 +1 +2 diff --git a/test/run-dfinity/ok/async-obj-mut.dvm.ok b/test/run-dfinity/ok/async-obj-mut.dvm.ok index 98f29c526f9..a346eeafc00 100644 --- a/test/run-dfinity/ok/async-obj-mut.dvm.ok +++ b/test/run-dfinity/ok/async-obj-mut.dvm.ok @@ -1,3 +1,8 @@ -123 +1 +2 +3 done creating -345 + +3 +4 +5 diff --git a/test/run-dfinity/ok/async-obj-mut.run-ir.ok b/test/run-dfinity/ok/async-obj-mut.run-ir.ok index 98f29c526f9..a346eeafc00 100644 --- a/test/run-dfinity/ok/async-obj-mut.run-ir.ok +++ b/test/run-dfinity/ok/async-obj-mut.run-ir.ok @@ -1,3 +1,8 @@ -123 +1 +2 +3 done creating -345 + +3 +4 +5 diff --git a/test/run-dfinity/ok/async-obj-mut.run-low.ok b/test/run-dfinity/ok/async-obj-mut.run-low.ok index 98f29c526f9..a346eeafc00 100644 --- a/test/run-dfinity/ok/async-obj-mut.run-low.ok +++ b/test/run-dfinity/ok/async-obj-mut.run-low.ok @@ -1,3 +1,8 @@ -123 +1 +2 +3 done creating -345 + +3 +4 +5 diff --git a/test/run-dfinity/ok/async-obj-mut.run.ok b/test/run-dfinity/ok/async-obj-mut.run.ok index 98f29c526f9..a346eeafc00 100644 --- a/test/run-dfinity/ok/async-obj-mut.run.ok +++ b/test/run-dfinity/ok/async-obj-mut.run.ok @@ -1,3 +1,8 @@ -123 +1 +2 +3 done creating -345 + +3 +4 +5 diff --git a/test/run-dfinity/ok/async-while.dvm.ok b/test/run-dfinity/ok/async-while.dvm.ok index f97e06e398a..4e57a41a93e 100644 --- a/test/run-dfinity/ok/async-while.dvm.ok +++ b/test/run-dfinity/ok/async-while.dvm.ok @@ -1 +1,12 @@ -012012012012 +0 +1 +2 +0 +1 +2 +0 +1 +2 +0 +1 +2 diff --git a/test/run-dfinity/ok/async-while.run-ir.ok b/test/run-dfinity/ok/async-while.run-ir.ok index f97e06e398a..4e57a41a93e 100644 --- a/test/run-dfinity/ok/async-while.run-ir.ok +++ b/test/run-dfinity/ok/async-while.run-ir.ok @@ -1 +1,12 @@ -012012012012 +0 +1 +2 +0 +1 +2 +0 +1 +2 +0 +1 +2 diff --git a/test/run-dfinity/ok/async-while.run-low.ok b/test/run-dfinity/ok/async-while.run-low.ok index f97e06e398a..4e57a41a93e 100644 --- a/test/run-dfinity/ok/async-while.run-low.ok +++ b/test/run-dfinity/ok/async-while.run-low.ok @@ -1 +1,12 @@ -012012012012 +0 +1 +2 +0 +1 +2 +0 +1 +2 +0 +1 +2 diff --git a/test/run-dfinity/ok/async-while.run.ok b/test/run-dfinity/ok/async-while.run.ok index f97e06e398a..4e57a41a93e 100644 --- a/test/run-dfinity/ok/async-while.run.ok +++ b/test/run-dfinity/ok/async-while.run.ok @@ -1 +1,12 @@ -012012012012 +0 +1 +2 +0 +1 +2 +0 +1 +2 +0 +1 +2 diff --git a/test/run-dfinity/ok/await.dvm.ok b/test/run-dfinity/ok/await.dvm.ok index 963fc9b25f1..2075f5ae300 100644 --- a/test/run-dfinity/ok/await.dvm.ok +++ b/test/run-dfinity/ok/await.dvm.ok @@ -1,12 +1,27 @@ -abcdegholycnt: 0 i: 0 +a +b +c +d +e +g +holy +cnt: 0 i: 0 cnt: 1 i: 1 cnt: 2 i: 2 cnt: 3 i: 3 cnt: 4 i: 4 -e-whilecnt: 5 i: 5 +e-while +cnt: 5 i: 5 cnt: 6 i: 6 cnt: 7 i: 7 -e-exitg-label.cnt: 8 i: 10 -.cnt: 9 i: 11 -.cnt: 10 i: 12 -g-exitab +e-exit +g-label +. +cnt: 8 i: 10 +. +cnt: 9 i: 11 +. +cnt: 10 i: 12 +g-exit +a +b diff --git a/test/run-dfinity/ok/await.run-ir.ok b/test/run-dfinity/ok/await.run-ir.ok index 731730721c0..6c5b990f341 100644 --- a/test/run-dfinity/ok/await.run-ir.ok +++ b/test/run-dfinity/ok/await.run-ir.ok @@ -1,12 +1,27 @@ -abcdegholye-whileg-label.abcnt: 0 i: 0 +a +b +c +d +e +g +holy +e-while +g-label +. +a +b +cnt: 0 i: 0 cnt: 1 i: 1 cnt: 2 i: 2 cnt: 3 i: 4 cnt: 4 i: 5 cnt: 5 i: 10 -.cnt: 6 i: 3 +. +cnt: 6 i: 3 cnt: 7 i: 6 cnt: 8 i: 11 -.cnt: 9 i: 7 +. +cnt: 9 i: 7 cnt: 10 i: 12 -e-exitg-exit +e-exit +g-exit diff --git a/test/run-dfinity/ok/await.run-low.ok b/test/run-dfinity/ok/await.run-low.ok index 731730721c0..6c5b990f341 100644 --- a/test/run-dfinity/ok/await.run-low.ok +++ b/test/run-dfinity/ok/await.run-low.ok @@ -1,12 +1,27 @@ -abcdegholye-whileg-label.abcnt: 0 i: 0 +a +b +c +d +e +g +holy +e-while +g-label +. +a +b +cnt: 0 i: 0 cnt: 1 i: 1 cnt: 2 i: 2 cnt: 3 i: 4 cnt: 4 i: 5 cnt: 5 i: 10 -.cnt: 6 i: 3 +. +cnt: 6 i: 3 cnt: 7 i: 6 cnt: 8 i: 11 -.cnt: 9 i: 7 +. +cnt: 9 i: 7 cnt: 10 i: 12 -e-exitg-exit +e-exit +g-exit diff --git a/test/run-dfinity/ok/await.run.ok b/test/run-dfinity/ok/await.run.ok index 731730721c0..6c5b990f341 100644 --- a/test/run-dfinity/ok/await.run.ok +++ b/test/run-dfinity/ok/await.run.ok @@ -1,12 +1,27 @@ -abcdegholye-whileg-label.abcnt: 0 i: 0 +a +b +c +d +e +g +holy +e-while +g-label +. +a +b +cnt: 0 i: 0 cnt: 1 i: 1 cnt: 2 i: 2 cnt: 3 i: 4 cnt: 4 i: 5 cnt: 5 i: 10 -.cnt: 6 i: 3 +. +cnt: 6 i: 3 cnt: 7 i: 6 cnt: 8 i: 11 -.cnt: 9 i: 7 +. +cnt: 9 i: 7 cnt: 10 i: 12 -e-exitg-exit +e-exit +g-exit diff --git a/test/run-dfinity/ok/block.dvm.ok b/test/run-dfinity/ok/block.dvm.ok index c70e9fe9d72..4a400a89e81 100644 --- a/test/run-dfinity/ok/block.dvm.ok +++ b/test/run-dfinity/ok/block.dvm.ok @@ -1 +1,10 @@ -a1b1a2b2a3b31356 +a1 +b1 +a2 +b2 +a3 +b3 +1 +3 +5 +6 diff --git a/test/run-dfinity/ok/block.run-ir.ok b/test/run-dfinity/ok/block.run-ir.ok index 456ed210645..64059f8c509 100644 --- a/test/run-dfinity/ok/block.run-ir.ok +++ b/test/run-dfinity/ok/block.run-ir.ok @@ -1 +1,10 @@ -a1b11a2b2a3b3356 +a1 +b1 +1 +a2 +b2 +a3 +b3 +3 +5 +6 diff --git a/test/run-dfinity/ok/block.run-low.ok b/test/run-dfinity/ok/block.run-low.ok index 456ed210645..64059f8c509 100644 --- a/test/run-dfinity/ok/block.run-low.ok +++ b/test/run-dfinity/ok/block.run-low.ok @@ -1 +1,10 @@ -a1b11a2b2a3b3356 +a1 +b1 +1 +a2 +b2 +a3 +b3 +3 +5 +6 diff --git a/test/run-dfinity/ok/block.run.ok b/test/run-dfinity/ok/block.run.ok index 456ed210645..64059f8c509 100644 --- a/test/run-dfinity/ok/block.run.ok +++ b/test/run-dfinity/ok/block.run.ok @@ -1 +1,10 @@ -a1b11a2b2a3b3356 +a1 +b1 +1 +a2 +b2 +a3 +b3 +3 +5 +6 diff --git a/test/run-dfinity/ok/chatpp.dvm.ok b/test/run-dfinity/ok/chatpp.dvm.ok index 42e2059e8d8..1384c6db136 100644 --- a/test/run-dfinity/ok/chatpp.dvm.ok +++ b/test/run-dfinity/ok/chatpp.dvm.ok @@ -1,3 +1,6 @@ -(unsubscribe 0) -(unsubscribe 1) -(unsubscribe 2) +unsubscribe +0 +unsubscribe ++1 +unsubscribe ++2 diff --git a/test/run-dfinity/ok/chatpp.run-ir.ok b/test/run-dfinity/ok/chatpp.run-ir.ok index 953e0dc688e..83b6fd429f2 100644 --- a/test/run-dfinity/ok/chatpp.run-ir.ok +++ b/test/run-dfinity/ok/chatpp.run-ir.ok @@ -1,6 +1,9 @@ -(unsubscribe 0) -(unsubscribe 1) -(unsubscribe 2) +unsubscribe +0 +unsubscribe ++1 +unsubscribe ++2 charlie received hello from bob alice received hello from bob charlie received goodbye from bob diff --git a/test/run-dfinity/ok/chatpp.run-low.ok b/test/run-dfinity/ok/chatpp.run-low.ok index 953e0dc688e..83b6fd429f2 100644 --- a/test/run-dfinity/ok/chatpp.run-low.ok +++ b/test/run-dfinity/ok/chatpp.run-low.ok @@ -1,6 +1,9 @@ -(unsubscribe 0) -(unsubscribe 1) -(unsubscribe 2) +unsubscribe +0 +unsubscribe ++1 +unsubscribe ++2 charlie received hello from bob alice received hello from bob charlie received goodbye from bob diff --git a/test/run-dfinity/ok/chatpp.run.ok b/test/run-dfinity/ok/chatpp.run.ok index 953e0dc688e..83b6fd429f2 100644 --- a/test/run-dfinity/ok/chatpp.run.ok +++ b/test/run-dfinity/ok/chatpp.run.ok @@ -1,6 +1,9 @@ -(unsubscribe 0) -(unsubscribe 1) -(unsubscribe 2) +unsubscribe +0 +unsubscribe ++1 +unsubscribe ++2 charlie received hello from bob alice received hello from bob charlie received goodbye from bob diff --git a/test/run-dfinity/ok/counter-class.dvm.ok b/test/run-dfinity/ok/counter-class.dvm.ok index c17544bddef..3f704155b23 100644 --- a/test/run-dfinity/ok/counter-class.dvm.ok +++ b/test/run-dfinity/ok/counter-class.dvm.ok @@ -1,2 +1,3 @@ hypervisor: calling start failed with trap message: Uncaught RuntimeError: unreachable TODO: non-closed actor + diff --git a/test/run-dfinity/ok/flatten-awaitables.dvm.ok b/test/run-dfinity/ok/flatten-awaitables.dvm.ok index 4c1b1bd6651..86dad5a61f1 100644 --- a/test/run-dfinity/ok/flatten-awaitables.dvm.ok +++ b/test/run-dfinity/ok/flatten-awaitables.dvm.ok @@ -1,5 +1,34 @@ - first-order -,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 higher-order -,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 diff --git a/test/run-dfinity/ok/flatten-awaitables.run-ir.ok b/test/run-dfinity/ok/flatten-awaitables.run-ir.ok index 4c1b1bd6651..86dad5a61f1 100644 --- a/test/run-dfinity/ok/flatten-awaitables.run-ir.ok +++ b/test/run-dfinity/ok/flatten-awaitables.run-ir.ok @@ -1,5 +1,34 @@ - first-order -,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 higher-order -,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 diff --git a/test/run-dfinity/ok/flatten-awaitables.run-low.ok b/test/run-dfinity/ok/flatten-awaitables.run-low.ok index 4c1b1bd6651..86dad5a61f1 100644 --- a/test/run-dfinity/ok/flatten-awaitables.run-low.ok +++ b/test/run-dfinity/ok/flatten-awaitables.run-low.ok @@ -1,5 +1,34 @@ - first-order -,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 higher-order -,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 diff --git a/test/run-dfinity/ok/flatten-awaitables.run.ok b/test/run-dfinity/ok/flatten-awaitables.run.ok index 4c1b1bd6651..86dad5a61f1 100644 --- a/test/run-dfinity/ok/flatten-awaitables.run.ok +++ b/test/run-dfinity/ok/flatten-awaitables.run.ok @@ -1,5 +1,34 @@ - first-order -,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 higher-order -,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 diff --git a/test/run-dfinity/ok/flatten-awaitables.tc.ok b/test/run-dfinity/ok/flatten-awaitables.tc.ok index 4734a23a649..a172866abd7 100644 --- a/test/run-dfinity/ok/flatten-awaitables.tc.ok +++ b/test/run-dfinity/ok/flatten-awaitables.tc.ok @@ -1,118 +1,118 @@ -flatten-awaitables.mo:43.9-43.10: warning, this pattern consuming type +flatten-awaitables.mo:41.9-41.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.mo:45.9-45.17: warning, this pattern consuming type +flatten-awaitables.mo:43.9-43.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.mo:47.9-47.25: warning, this pattern consuming type +flatten-awaitables.mo:45.9-45.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.mo:52.9-52.10: warning, this pattern consuming type +flatten-awaitables.mo:50.9-50.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.mo:54.9-54.17: warning, this pattern consuming type +flatten-awaitables.mo:52.9-52.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.mo:56.9-56.25: warning, this pattern consuming type +flatten-awaitables.mo:54.9-54.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.mo:66.9-66.10: warning, this pattern consuming type +flatten-awaitables.mo:64.9-64.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.mo:68.9-68.17: warning, this pattern consuming type +flatten-awaitables.mo:66.9-66.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.mo:70.9-70.25: warning, this pattern consuming type +flatten-awaitables.mo:68.9-68.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.mo:75.9-75.10: warning, this pattern consuming type +flatten-awaitables.mo:73.9-73.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.mo:77.9-77.17: warning, this pattern consuming type +flatten-awaitables.mo:75.9-75.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.mo:79.9-79.25: warning, this pattern consuming type +flatten-awaitables.mo:77.9-77.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.mo:85.9-85.10: warning, this pattern consuming type +flatten-awaitables.mo:83.9-83.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.mo:87.9-87.17: warning, this pattern consuming type +flatten-awaitables.mo:85.9-85.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.mo:89.9-89.25: warning, this pattern consuming type +flatten-awaitables.mo:87.9-87.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.mo:94.9-94.10: warning, this pattern consuming type +flatten-awaitables.mo:92.9-92.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.mo:96.9-96.17: warning, this pattern consuming type +flatten-awaitables.mo:94.9-94.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.mo:98.9-98.25: warning, this pattern consuming type +flatten-awaitables.mo:96.9-96.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.mo:103.9-103.10: warning, this pattern consuming type +flatten-awaitables.mo:101.9-101.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.mo:105.9-105.17: warning, this pattern consuming type +flatten-awaitables.mo:103.9-103.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.mo:107.9-107.25: warning, this pattern consuming type +flatten-awaitables.mo:105.9-105.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.mo:112.9-112.10: warning, this pattern consuming type +flatten-awaitables.mo:110.9-110.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.mo:114.9-114.17: warning, this pattern consuming type +flatten-awaitables.mo:112.9-112.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.mo:116.9-116.25: warning, this pattern consuming type +flatten-awaitables.mo:114.9-114.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or diff --git a/test/run-dfinity/ok/for-await.dvm.ok b/test/run-dfinity/ok/for-await.dvm.ok index 718ae076949..b033488efab 100644 --- a/test/run-dfinity/ok/for-await.dvm.ok +++ b/test/run-dfinity/ok/for-await.dvm.ok @@ -1 +1,11 @@ -012345678910 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 diff --git a/test/run-dfinity/ok/for-await.run-ir.ok b/test/run-dfinity/ok/for-await.run-ir.ok index 718ae076949..b033488efab 100644 --- a/test/run-dfinity/ok/for-await.run-ir.ok +++ b/test/run-dfinity/ok/for-await.run-ir.ok @@ -1 +1,11 @@ -012345678910 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 diff --git a/test/run-dfinity/ok/for-await.run-low.ok b/test/run-dfinity/ok/for-await.run-low.ok index 718ae076949..b033488efab 100644 --- a/test/run-dfinity/ok/for-await.run-low.ok +++ b/test/run-dfinity/ok/for-await.run-low.ok @@ -1 +1,11 @@ -012345678910 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 diff --git a/test/run-dfinity/ok/for-await.run.ok b/test/run-dfinity/ok/for-await.run.ok index 718ae076949..b033488efab 100644 --- a/test/run-dfinity/ok/for-await.run.ok +++ b/test/run-dfinity/ok/for-await.run.ok @@ -1 +1,11 @@ -012345678910 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 diff --git a/test/run-dfinity/ok/indirect-counter.dvm.ok b/test/run-dfinity/ok/indirect-counter.dvm.ok index dc01807c8fe..95c45d6da51 100644 --- a/test/run-dfinity/ok/indirect-counter.dvm.ok +++ b/test/run-dfinity/ok/indirect-counter.dvm.ok @@ -1 +1,4 @@ -2344 +2 +3 +4 +4 diff --git a/test/run-dfinity/ok/indirect-counter.run-ir.ok b/test/run-dfinity/ok/indirect-counter.run-ir.ok index dc01807c8fe..95c45d6da51 100644 --- a/test/run-dfinity/ok/indirect-counter.run-ir.ok +++ b/test/run-dfinity/ok/indirect-counter.run-ir.ok @@ -1 +1,4 @@ -2344 +2 +3 +4 +4 diff --git a/test/run-dfinity/ok/indirect-counter.run-low.ok b/test/run-dfinity/ok/indirect-counter.run-low.ok index dc01807c8fe..95c45d6da51 100644 --- a/test/run-dfinity/ok/indirect-counter.run-low.ok +++ b/test/run-dfinity/ok/indirect-counter.run-low.ok @@ -1 +1,4 @@ -2344 +2 +3 +4 +4 diff --git a/test/run-dfinity/ok/indirect-counter.run.ok b/test/run-dfinity/ok/indirect-counter.run.ok index dc01807c8fe..95c45d6da51 100644 --- a/test/run-dfinity/ok/indirect-counter.run.ok +++ b/test/run-dfinity/ok/indirect-counter.run.ok @@ -1 +1,4 @@ -2344 +2 +3 +4 +4 diff --git a/test/run-dfinity/ok/local-throw.dvm.ok b/test/run-dfinity/ok/local-throw.dvm.ok index 1633cd29053..33bffc9666e 100644 --- a/test/run-dfinity/ok/local-throw.dvm.ok +++ b/test/run-dfinity/ok/local-throw.dvm.ok @@ -1,3 +1,2 @@ - - t2 ok - t3 ok +t2 ok +t3 ok diff --git a/test/run-dfinity/ok/local-throw.run-ir.ok b/test/run-dfinity/ok/local-throw.run-ir.ok index 1633cd29053..33bffc9666e 100644 --- a/test/run-dfinity/ok/local-throw.run-ir.ok +++ b/test/run-dfinity/ok/local-throw.run-ir.ok @@ -1,3 +1,2 @@ - - t2 ok - t3 ok +t2 ok +t3 ok diff --git a/test/run-dfinity/ok/local-throw.run-low.ok b/test/run-dfinity/ok/local-throw.run-low.ok index 1633cd29053..33bffc9666e 100644 --- a/test/run-dfinity/ok/local-throw.run-low.ok +++ b/test/run-dfinity/ok/local-throw.run-low.ok @@ -1,3 +1,2 @@ - - t2 ok - t3 ok +t2 ok +t3 ok diff --git a/test/run-dfinity/ok/local-throw.run.ok b/test/run-dfinity/ok/local-throw.run.ok index 1633cd29053..33bffc9666e 100644 --- a/test/run-dfinity/ok/local-throw.run.ok +++ b/test/run-dfinity/ok/local-throw.run.ok @@ -1,3 +1,2 @@ - - t2 ok - t3 ok +t2 ok +t3 ok diff --git a/test/run-dfinity/ok/nary-async.dvm.ok b/test/run-dfinity/ok/nary-async.dvm.ok index 3df16532e56..c49facc630f 100644 --- a/test/run-dfinity/ok/nary-async.dvm.ok +++ b/test/run-dfinity/ok/nary-async.dvm.ok @@ -5,5 +5,4 @@ 0_0 0_1 0_2 -0_3 -!! +0_3!! diff --git a/test/run-dfinity/ok/nary-async.run-ir.ok b/test/run-dfinity/ok/nary-async.run-ir.ok index 3df16532e56..c49facc630f 100644 --- a/test/run-dfinity/ok/nary-async.run-ir.ok +++ b/test/run-dfinity/ok/nary-async.run-ir.ok @@ -5,5 +5,4 @@ 0_0 0_1 0_2 -0_3 -!! +0_3!! diff --git a/test/run-dfinity/ok/nary-async.run-low.ok b/test/run-dfinity/ok/nary-async.run-low.ok index 3df16532e56..c49facc630f 100644 --- a/test/run-dfinity/ok/nary-async.run-low.ok +++ b/test/run-dfinity/ok/nary-async.run-low.ok @@ -5,5 +5,4 @@ 0_0 0_1 0_2 -0_3 -!! +0_3!! diff --git a/test/run-dfinity/ok/nary-async.run.ok b/test/run-dfinity/ok/nary-async.run.ok index 3df16532e56..c49facc630f 100644 --- a/test/run-dfinity/ok/nary-async.run.ok +++ b/test/run-dfinity/ok/nary-async.run.ok @@ -5,5 +5,4 @@ 0_0 0_1 0_2 -0_3 -!! +0_3!! diff --git a/test/run-dfinity/ok/overflow.dvm.ok b/test/run-dfinity/ok/overflow.dvm.ok index a9f55b265cc..29962e83f4e 100644 --- a/test/run-dfinity/ok/overflow.dvm.ok +++ b/test/run-dfinity/ok/overflow.dvm.ok @@ -3,6 +3,8 @@ hypervisor: calling func$NNN failed with trap message: Uncaught RuntimeError: un This is reachable. This is reachable. Natural subtraction underflow + Natural subtraction underflow + This is reachable. This is reachable. diff --git a/test/run-dfinity/ok/query.dvm.ok b/test/run-dfinity/ok/query.dvm.ok index c10e912b5d0..66717210b53 100644 --- a/test/run-dfinity/ok/query.dvm.ok +++ b/test/run-dfinity/ok/query.dvm.ok @@ -2,7 +2,9 @@ 3 4 4 -5(read) +5 +(read) 4 -5(read) +5 +(read) 4 diff --git a/test/run-dfinity/ok/query.run-ir.ok b/test/run-dfinity/ok/query.run-ir.ok index 5a78e7ebee9..17740cbca04 100644 --- a/test/run-dfinity/ok/query.run-ir.ok +++ b/test/run-dfinity/ok/query.run-ir.ok @@ -2,8 +2,10 @@ 3 4 4 -5(read) 5 -6(read) +(read) +5 +6 +(read) query.mo:61.2-61.16: execution error, assertion failure 6 diff --git a/test/run-dfinity/ok/query.run-low.ok b/test/run-dfinity/ok/query.run-low.ok index 5a78e7ebee9..17740cbca04 100644 --- a/test/run-dfinity/ok/query.run-low.ok +++ b/test/run-dfinity/ok/query.run-low.ok @@ -2,8 +2,10 @@ 3 4 4 -5(read) 5 -6(read) +(read) +5 +6 +(read) query.mo:61.2-61.16: execution error, assertion failure 6 diff --git a/test/run-dfinity/ok/query.run.ok b/test/run-dfinity/ok/query.run.ok index 5a78e7ebee9..17740cbca04 100644 --- a/test/run-dfinity/ok/query.run.ok +++ b/test/run-dfinity/ok/query.run.ok @@ -2,8 +2,10 @@ 3 4 4 -5(read) 5 -6(read) +(read) +5 +6 +(read) query.mo:61.2-61.16: execution error, assertion failure 6 diff --git a/test/run-dfinity/ok/simple-throw.dvm.ok b/test/run-dfinity/ok/simple-throw.dvm.ok index e357299a076..f3e51c00a71 100644 --- a/test/run-dfinity/ok/simple-throw.dvm.ok +++ b/test/run-dfinity/ok/simple-throw.dvm.ok @@ -1 +1,5 @@ -1234done +1 +2 +3 +4 +done diff --git a/test/run-dfinity/ok/simple-throw.run-ir.ok b/test/run-dfinity/ok/simple-throw.run-ir.ok index e357299a076..f3e51c00a71 100644 --- a/test/run-dfinity/ok/simple-throw.run-ir.ok +++ b/test/run-dfinity/ok/simple-throw.run-ir.ok @@ -1 +1,5 @@ -1234done +1 +2 +3 +4 +done diff --git a/test/run-dfinity/ok/simple-throw.run-low.ok b/test/run-dfinity/ok/simple-throw.run-low.ok index e357299a076..f3e51c00a71 100644 --- a/test/run-dfinity/ok/simple-throw.run-low.ok +++ b/test/run-dfinity/ok/simple-throw.run-low.ok @@ -1 +1,5 @@ -1234done +1 +2 +3 +4 +done diff --git a/test/run-dfinity/ok/simple-throw.run.ok b/test/run-dfinity/ok/simple-throw.run.ok index e357299a076..f3e51c00a71 100644 --- a/test/run-dfinity/ok/simple-throw.run.ok +++ b/test/run-dfinity/ok/simple-throw.run.ok @@ -1 +1,5 @@ -1234done +1 +2 +3 +4 +done diff --git a/test/run-dfinity/overflow.mo b/test/run-dfinity/overflow.mo index 3bf1689d5d4..d0b6e27d722 100644 --- a/test/run-dfinity/overflow.mo +++ b/test/run-dfinity/overflow.mo @@ -4,31 +4,31 @@ ignore(async { ignore ((0-1):Int); - debugPrint("This is reachable.\n"); + debugPrint("This is reachable."); }); ignore(async { ignore ((1-1):Nat); - debugPrint("This is reachable.\n"); + debugPrint("This is reachable."); }); ignore(async { ignore ((0-1):Nat); - debugPrint("This should be unreachable.\n"); + debugPrint("This should be unreachable."); }); ignore(async { ignore ((0-1):Nat); - debugPrint("This should be unreachable.\n"); + debugPrint("This should be unreachable."); }); /* ignore(async { ignore ((18446744073709551615 + 0):Nat); - debugPrint("This is reachable.\n"); + debugPrint("This is reachable."); }); */ ignore(async { ignore ((9223372036854775806 + 9223372036854775806 + 1):Nat); - debugPrint("This is reachable.\n"); + debugPrint("This is reachable."); }); ignore(async { ignore ((9223372036854775806 + 9223372036854775806 + 2):Nat); - debugPrint("This is reachable.\n"); + debugPrint("This is reachable."); }); diff --git a/test/run-dfinity/query.mo b/test/run-dfinity/query.mo index a6d7e3b63f2..271830eb031 100644 --- a/test/run-dfinity/query.mo +++ b/test/run-dfinity/query.mo @@ -2,10 +2,10 @@ actor counter = { var c = 1; public func inc() { c += 1; - debugPrintNat c; debugPrint "\n"; + debugPrintNat c; }; public func printCounter () { - debugPrintNat c; debugPrint "\n"; + debugPrintNat c; }; public func get() : async Nat { return c @@ -13,7 +13,7 @@ actor counter = { public query func read() : async Nat { let tmp = c; c += 1; - debugPrintNat c; debugPrint "(read)\n"; + debugPrintNat c; debugPrint "(read)"; return tmp; }; diff --git a/test/run-dfinity/reference-params.mo b/test/run-dfinity/reference-params.mo index 6324345b96c..cc575f9f954 100644 --- a/test/run-dfinity/reference-params.mo +++ b/test/run-dfinity/reference-params.mo @@ -1,6 +1,6 @@ let a = actor { public func hello() { - debugPrint("Hello World!\n"); + debugPrint("Hello World!"); }; }; a.hello(); @@ -27,7 +27,7 @@ let d = actor { f(); }; public func hello() { - debugPrint("Hello Universe!\n"); + debugPrint("Hello Universe!"); }; public func go() { say_hi(hello); @@ -38,7 +38,7 @@ d.go(); // test passing a self to an actor let e = actor this { public func hello() { - debugPrint("Hello Galaxy!\n"); + debugPrint("Hello Galaxy!"); }; public func send_to(f : shared (actor { hello : () -> () }) -> ()) { f(this); diff --git a/test/run-drun/array-out-of-bounds.mo b/test/run-drun/array-out-of-bounds.mo index c521aea9f3a..a55586ebfd0 100644 --- a/test/run-drun/array-out-of-bounds.mo +++ b/test/run-drun/array-out-of-bounds.mo @@ -4,11 +4,11 @@ actor a { public func foo1() : async () { ignore(xs[5]); - debugPrint("Unreachable code reached\n"); + debugPrint("Unreachable code reached"); }; public func foo2() : async () { ignore(ys[0]); - debugPrint("Unreachable code reached\n"); + debugPrint("Unreachable code reached"); }; }; diff --git a/test/run-drun/counter.mo b/test/run-drun/counter.mo index 0e40920fb6f..0f4e4ba26ce 100644 --- a/test/run-drun/counter.mo +++ b/test/run-drun/counter.mo @@ -2,10 +2,10 @@ actor { var c = 1; public func inc() { c += 1; - debugPrintNat c; debugPrint "\n"; + debugPrintNat c }; public func printCounter () { - debugPrintNat c; debugPrint "\n"; + debugPrintNat c }; public func get() : async Nat { return c diff --git a/test/run-drun/counter2.mo b/test/run-drun/counter2.mo index 94eb1545c01..8bdeeab46a5 100644 --- a/test/run-drun/counter2.mo +++ b/test/run-drun/counter2.mo @@ -2,10 +2,10 @@ actor { var c = 1; public func inc() { c += 1; - debugPrintNat c; debugPrint "\n"; + debugPrintNat c }; public func printCounter () { - debugPrintNat c; debugPrint "\n"; + debugPrintNat c } } //CALL inc 0x4449444C0000 [] diff --git a/test/run-drun/hello-world-message.mo b/test/run-drun/hello-world-message.mo index 7e54cde56b6..cd14b3d32b4 100644 --- a/test/run-drun/hello-world-message.mo +++ b/test/run-drun/hello-world-message.mo @@ -1,6 +1,6 @@ actor { public func hello() { - debugPrint("Hello World!\n"); + debugPrint("Hello World!"); } } diff --git a/test/run-drun/hello-world-message2.mo b/test/run-drun/hello-world-message2.mo index 9274933cc3a..28d9d49fddb 100644 --- a/test/run-drun/hello-world-message2.mo +++ b/test/run-drun/hello-world-message2.mo @@ -1,6 +1,6 @@ actor hello_world { public func hello() { - debugPrint("Hello World!\n"); + debugPrint("Hello World!"); } } diff --git a/test/run-drun/hello-world.mo b/test/run-drun/hello-world.mo index bc9c37d31e8..84266d49e9c 100644 --- a/test/run-drun/hello-world.mo +++ b/test/run-drun/hello-world.mo @@ -1 +1 @@ -debugPrint("Hello World!\n"); +debugPrint("Hello World!"); diff --git a/test/run-drun/ok/counter.drun-run.ok b/test/run-drun/ok/counter.drun-run.ok index c389f84ac9c..52942b3d790 100644 --- a/test/run-drun/ok/counter.drun-run.ok +++ b/test/run-drun/ok/counter.drun-run.ok @@ -1,18 +1,10 @@ ingress(0) System debug.print: 2 -debug.print: - ingress(1) Completed: Canister: Payload: 0x4449444c0000 debug.print: 3 -debug.print: - ingress(2) Completed: Canister: Payload: 0x4449444c0000 debug.print: 4 -debug.print: - ingress(3) Completed: Canister: Payload: 0x4449444c0000 debug.print: 4 -debug.print: - ingress(4) Completed: Canister: Payload: 0x4449444c0000 ingress(5) Completed: Canister: Payload: 0x4449444c00017d04 diff --git a/test/run-drun/ok/generic-tail-rec.run-ir.ok b/test/run-drun/ok/generic-tail-rec.run-ir.ok index 37779966f28..6d96c93ceef 100644 --- a/test/run-drun/ok/generic-tail-rec.run-ir.ok +++ b/test/run-drun/ok/generic-tail-rec.run-ir.ok @@ -1 +1,4 @@ -done 1done 2done 3done 4 +done 1 +done 2 +done 3 +done 4 diff --git a/test/run-drun/ok/generic-tail-rec.run-low.ok b/test/run-drun/ok/generic-tail-rec.run-low.ok index 37779966f28..6d96c93ceef 100644 --- a/test/run-drun/ok/generic-tail-rec.run-low.ok +++ b/test/run-drun/ok/generic-tail-rec.run-low.ok @@ -1 +1,4 @@ -done 1done 2done 3done 4 +done 1 +done 2 +done 3 +done 4 diff --git a/test/run-drun/ok/generic-tail-rec.run.ok b/test/run-drun/ok/generic-tail-rec.run.ok index 37779966f28..6d96c93ceef 100644 --- a/test/run-drun/ok/generic-tail-rec.run.ok +++ b/test/run-drun/ok/generic-tail-rec.run.ok @@ -1 +1,4 @@ -done 1done 2done 3done 4 +done 1 +done 2 +done 3 +done 4 diff --git a/test/run-drun/ok/hello-world.drun-run.ok b/test/run-drun/ok/hello-world.drun-run.ok index 4c3030d0fee..e019e1158f8 100644 --- a/test/run-drun/ok/hello-world.drun-run.ok +++ b/test/run-drun/ok/hello-world.drun-run.ok @@ -1,3 +1,2 @@ debug.print: Hello World! - ingress(0) System diff --git a/test/run-drun/ok/query.drun-run.ok b/test/run-drun/ok/query.drun-run.ok index 2130635fc01..aab5adff8d1 100644 --- a/test/run-drun/ok/query.drun-run.ok +++ b/test/run-drun/ok/query.drun-run.ok @@ -1,34 +1,18 @@ ingress(0) System debug.print: 2 -debug.print: - ingress(1) Completed: Canister: Payload: 0x4449444c0000 debug.print: 3 -debug.print: - ingress(2) Completed: Canister: Payload: 0x4449444c0000 debug.print: 4 -debug.print: - ingress(3) Completed: Canister: Payload: 0x4449444c0000 debug.print: 4 -debug.print: - ingress(4) Completed: Canister: Payload: 0x4449444c0000 ingress(5) Completed: Canister: Payload: 0x4449444c00017d04 debug.print: 5 -debug.print: - Ok: Payload: 0x4449444c00017d04 debug.print: 4 -debug.print: - ingress(6) Completed: Canister: Payload: 0x4449444c0000 debug.print: 5 -debug.print: - Ok: Payload: 0x4449444c00017d04 debug.print: 4 -debug.print: - ingress(7) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/selftail.drun-run.ok b/test/run-drun/ok/selftail.drun-run.ok index 7c9d2a30e8b..922e74685f0 100644 --- a/test/run-drun/ok/selftail.drun-run.ok +++ b/test/run-drun/ok/selftail.drun-run.ok @@ -1,5 +1,3 @@ -debug.print: ok1 - -debug.print: ok2 - +debug.print: ok1 +debug.print: ok2 ingress(0) System diff --git a/test/run-drun/ok/selftail.run-ir.ok b/test/run-drun/ok/selftail.run-ir.ok index acb397e19f2..58223a7b0e6 100644 --- a/test/run-drun/ok/selftail.run-ir.ok +++ b/test/run-drun/ok/selftail.run-ir.ok @@ -1,2 +1,2 @@ -ok1 -ok2 +ok1 +ok2 diff --git a/test/run-drun/ok/selftail.run-low.ok b/test/run-drun/ok/selftail.run-low.ok index acb397e19f2..58223a7b0e6 100644 --- a/test/run-drun/ok/selftail.run-low.ok +++ b/test/run-drun/ok/selftail.run-low.ok @@ -1,2 +1,2 @@ -ok1 -ok2 +ok1 +ok2 diff --git a/test/run-drun/ok/selftail.run.ok b/test/run-drun/ok/selftail.run.ok index acb397e19f2..58223a7b0e6 100644 --- a/test/run-drun/ok/selftail.run.ok +++ b/test/run-drun/ok/selftail.run.ok @@ -1,2 +1,2 @@ -ok1 -ok2 +ok1 +ok2 diff --git a/test/run-drun/ok/show.drun-run.ok b/test/run-drun/ok/show.drun-run.ok index a7ab5d6aa08..e422f408f34 100644 --- a/test/run-drun/ok/show.drun-run.ok +++ b/test/run-drun/ok/show.drun-run.ok @@ -1,71 +1,36 @@ debug.print: true - debug.print: false - debug.print: -42_000_000_000_000 - debug.print: -42_000_000 - debug.print: -42_000 - debug.print: -42 - debug.print: 0 - debug.print: 0 - debug.print: +42 - debug.print: +42_000 - debug.print: +42_000_000 - debug.print: +420_000_000_000_000 - debug.print: 0 - debug.print: 42 - debug.print: 42_000 - debug.print: 42_000_000 - debug.print: 420_000_000_000_000 - debug.print: (42, -42, ()) - debug.print: ("Foobar", null, null, ?23) - debug.print: [] - debug.print: [1, 2, 3] - debug.print: [var] - debug.print: [var 1, 2, 3] - debug.print: {bar = true; foo = +42} - debug.print: #foo - debug.print: #bar(1, 2) - debug.print: #bar({}) - debug.print: #bar([]) - debug.print: #bar(42) - debug.print: #bar(-42) - debug.print: #foo(+42) - debug.print: 0x2A - debug.print: 42 - debug.print: +42 - debug.print: -42 - ingress(0) System diff --git a/test/run-drun/ok/tailpositions.drun-run.ok b/test/run-drun/ok/tailpositions.drun-run.ok index f4ea4aa55fd..2111364c1b2 100644 --- a/test/run-drun/ok/tailpositions.drun-run.ok +++ b/test/run-drun/ok/tailpositions.drun-run.ok @@ -1,15 +1,8 @@ debug.print: done 1 - debug.print: done 2 - debug.print: done 3 - debug.print: done 4 - debug.print: done 5 - debug.print: done 6 - debug.print: done 7 - ingress(0) System diff --git a/test/run-drun/ok/test_oneway.run-ir.ok b/test/run-drun/ok/test_oneway.run-ir.ok index 550167191f0..853eff0d5b4 100644 --- a/test/run-drun/ok/test_oneway.run-ir.ok +++ b/test/run-drun/ok/test_oneway.run-ir.ok @@ -1 +1,11 @@ -ABCDE123456 +A +B +C +D +E +1 +2 +3 +4 +5 +6 diff --git a/test/run-drun/ok/test_oneway.run-low.ok b/test/run-drun/ok/test_oneway.run-low.ok index 550167191f0..853eff0d5b4 100644 --- a/test/run-drun/ok/test_oneway.run-low.ok +++ b/test/run-drun/ok/test_oneway.run-low.ok @@ -1 +1,11 @@ -ABCDE123456 +A +B +C +D +E +1 +2 +3 +4 +5 +6 diff --git a/test/run-drun/ok/test_oneway.run.ok b/test/run-drun/ok/test_oneway.run.ok index 550167191f0..853eff0d5b4 100644 --- a/test/run-drun/ok/test_oneway.run.ok +++ b/test/run-drun/ok/test_oneway.run.ok @@ -1 +1,11 @@ -ABCDE123456 +A +B +C +D +E +1 +2 +3 +4 +5 +6 diff --git a/test/run-drun/ok/text-iter.drun-run.ok b/test/run-drun/ok/text-iter.drun-run.ok index d7516f24c11..2f4ecd9288b 100644 --- a/test/run-drun/ok/text-iter.drun-run.ok +++ b/test/run-drun/ok/text-iter.drun-run.ok @@ -1,11 +1,7 @@ debug.print: via `debugPrint`: - debug.print: hello world! - debug.print: - debug.print: via iteration and `debugPrintChar`: #1 - debug.print: h debug.print: e debug.print: l @@ -19,11 +15,7 @@ debug.print: l debug.print: d debug.print: ! debug.print: - -debug.print: - debug.print: via iteration and `debugPrintChar`: #2 - debug.print: 1 debug.print: : debug.print: ' @@ -96,17 +88,8 @@ debug.print: ' debug.print: ! debug.print: ' debug.print: -debug.print: 13 -debug.print: : -debug.print: ' debug.print: - -debug.print: ' -debug.print: -debug.print: - debug.print: via iteration and `debugPrintChar` (Unicode): #3 - debug.print: 1 debug.print: : debug.print: ' @@ -217,9 +200,7 @@ debug.print: debug.print: ' debug.print: debug.print: - debug.print: via iteration and `debugPrintChar` (Unicode): #4 - debug.print: 1 debug.print: : debug.print: ' @@ -239,15 +220,11 @@ debug.print: 😋 debug.print: ' debug.print: debug.print: - debug.print: Приветствую, мир! debug.print: - debug.print: П debug.print: - debug.print: 🙈 debug.print: - ingress(0) System diff --git a/test/run-drun/ok/text-iter.run-ir.ok b/test/run-drun/ok/text-iter.run-ir.ok index cdfd71bd534..a2ae9467155 100644 --- a/test/run-drun/ok/text-iter.run-ir.ok +++ b/test/run-drun/ok/text-iter.run-ir.ok @@ -2,17 +2,228 @@ via `debugPrint`: hello world! via iteration and `debugPrintChar`: #1 -hello world! +h +e +l +l +o + +w +o +r +l +d +! via iteration and `debugPrintChar`: #2 -1:'h' 2:'e' 3:'l' 4:'l' 5:'o' 6:' ' 7:'w' 8:'o' 9:'r' 10:'l' 11:'d' 12:'!' 13:' -' +1 +: +' +h +' + +2 +: +' +e +' + +3 +: +' +l +' + +4 +: +' +l +' + +5 +: +' +o +' + +6 +: +' + +' + +7 +: +' +w +' + +8 +: +' +o +' + +9 +: +' +r +' + +10 +: +' +l +' + +11 +: +' +d +' + +12 +: +' +! +' + + via iteration and `debugPrintChar` (Unicode): #3 -1:'П' 2:'р' 3:'и' 4:'в' 5:'е' 6:'т' 7:'с' 8:'т' 9:'в' 10:'у' 11:'ю' 12:',' 13:' ' 14:'м' 15:'и' 16:'р' 17:'!' 18:' -' +1 +: +' +П +' + +2 +: +' +р +' + +3 +: +' +и +' + +4 +: +' +в +' + +5 +: +' +е +' + +6 +: +' +т +' + +7 +: +' +с +' + +8 +: +' +т +' + +9 +: +' +в +' + +10 +: +' +у +' + +11 +: +' +ю +' + +12 +: +' +, +' + +13 +: +' + +' + +14 +: +' +м +' + +15 +: +' +и +' + +16 +: +' +р +' + +17 +: +' +! +' + +18 +: +' + + +' + + via iteration and `debugPrintChar` (Unicode): #4 -1:'🙈' 2:'🎸' 3:'😋' +1 +: +' +🙈 +' + +2 +: +' +🎸 +' + +3 +: +' +😋 +' + + Приветствую, мир! + П + 🙈 + diff --git a/test/run-drun/ok/text-iter.run-low.ok b/test/run-drun/ok/text-iter.run-low.ok index cdfd71bd534..a2ae9467155 100644 --- a/test/run-drun/ok/text-iter.run-low.ok +++ b/test/run-drun/ok/text-iter.run-low.ok @@ -2,17 +2,228 @@ via `debugPrint`: hello world! via iteration and `debugPrintChar`: #1 -hello world! +h +e +l +l +o + +w +o +r +l +d +! via iteration and `debugPrintChar`: #2 -1:'h' 2:'e' 3:'l' 4:'l' 5:'o' 6:' ' 7:'w' 8:'o' 9:'r' 10:'l' 11:'d' 12:'!' 13:' -' +1 +: +' +h +' + +2 +: +' +e +' + +3 +: +' +l +' + +4 +: +' +l +' + +5 +: +' +o +' + +6 +: +' + +' + +7 +: +' +w +' + +8 +: +' +o +' + +9 +: +' +r +' + +10 +: +' +l +' + +11 +: +' +d +' + +12 +: +' +! +' + + via iteration and `debugPrintChar` (Unicode): #3 -1:'П' 2:'р' 3:'и' 4:'в' 5:'е' 6:'т' 7:'с' 8:'т' 9:'в' 10:'у' 11:'ю' 12:',' 13:' ' 14:'м' 15:'и' 16:'р' 17:'!' 18:' -' +1 +: +' +П +' + +2 +: +' +р +' + +3 +: +' +и +' + +4 +: +' +в +' + +5 +: +' +е +' + +6 +: +' +т +' + +7 +: +' +с +' + +8 +: +' +т +' + +9 +: +' +в +' + +10 +: +' +у +' + +11 +: +' +ю +' + +12 +: +' +, +' + +13 +: +' + +' + +14 +: +' +м +' + +15 +: +' +и +' + +16 +: +' +р +' + +17 +: +' +! +' + +18 +: +' + + +' + + via iteration and `debugPrintChar` (Unicode): #4 -1:'🙈' 2:'🎸' 3:'😋' +1 +: +' +🙈 +' + +2 +: +' +🎸 +' + +3 +: +' +😋 +' + + Приветствую, мир! + П + 🙈 + diff --git a/test/run-drun/ok/text-iter.run.ok b/test/run-drun/ok/text-iter.run.ok index cdfd71bd534..a2ae9467155 100644 --- a/test/run-drun/ok/text-iter.run.ok +++ b/test/run-drun/ok/text-iter.run.ok @@ -2,17 +2,228 @@ via `debugPrint`: hello world! via iteration and `debugPrintChar`: #1 -hello world! +h +e +l +l +o + +w +o +r +l +d +! via iteration and `debugPrintChar`: #2 -1:'h' 2:'e' 3:'l' 4:'l' 5:'o' 6:' ' 7:'w' 8:'o' 9:'r' 10:'l' 11:'d' 12:'!' 13:' -' +1 +: +' +h +' + +2 +: +' +e +' + +3 +: +' +l +' + +4 +: +' +l +' + +5 +: +' +o +' + +6 +: +' + +' + +7 +: +' +w +' + +8 +: +' +o +' + +9 +: +' +r +' + +10 +: +' +l +' + +11 +: +' +d +' + +12 +: +' +! +' + + via iteration and `debugPrintChar` (Unicode): #3 -1:'П' 2:'р' 3:'и' 4:'в' 5:'е' 6:'т' 7:'с' 8:'т' 9:'в' 10:'у' 11:'ю' 12:',' 13:' ' 14:'м' 15:'и' 16:'р' 17:'!' 18:' -' +1 +: +' +П +' + +2 +: +' +р +' + +3 +: +' +и +' + +4 +: +' +в +' + +5 +: +' +е +' + +6 +: +' +т +' + +7 +: +' +с +' + +8 +: +' +т +' + +9 +: +' +в +' + +10 +: +' +у +' + +11 +: +' +ю +' + +12 +: +' +, +' + +13 +: +' + +' + +14 +: +' +м +' + +15 +: +' +и +' + +16 +: +' +р +' + +17 +: +' +! +' + +18 +: +' + + +' + + via iteration and `debugPrintChar` (Unicode): #4 -1:'🙈' 2:'🎸' 3:'😋' +1 +: +' +🙈 +' + +2 +: +' +🎸 +' + +3 +: +' +😋 +' + + Приветствую, мир! + П + 🙈 + diff --git a/test/run-drun/query.mo b/test/run-drun/query.mo index 3e494c1154e..8541b9f7f3d 100644 --- a/test/run-drun/query.mo +++ b/test/run-drun/query.mo @@ -2,10 +2,10 @@ actor { var c = 1; public func inc() { c += 1; - debugPrintNat c; debugPrint "\n"; + debugPrintNat c }; public func printCounter () { - debugPrintNat c; debugPrint "\n"; + debugPrintNat c }; public func get() : async Nat { return c @@ -13,7 +13,7 @@ actor { public query func read() : async Nat { let tmp = c; c += 1; - debugPrintNat c; debugPrint "\n"; + debugPrintNat c; return tmp; }; diff --git a/test/run-drun/selftail.mo b/test/run-drun/selftail.mo index f12f6d22741..084a449eb93 100644 --- a/test/run-drun/selftail.mo +++ b/test/run-drun/selftail.mo @@ -11,13 +11,13 @@ func f (tailCall:Bool, n:Int, acc:Int) : Int { // check we get same results for small n assert (f(false, 100, 0) == f(true, 100, 0)); -debugPrint "ok1 \n"; +debugPrint "ok1"; // check tail recursion works for large n assert(10000 == f (true, 10000, 0)); -debugPrint "ok2 \n"; +debugPrint "ok2"; // check recursion overflows for large n (on dvm only) // disabled as overflowing or not appears to be non-deterministic on V8 //assert(10000 == f (false, 10000, 0)); -//debugPrint "unreachable on dvm \n"; +//debugPrint "unreachable on dvm"; diff --git a/test/run-drun/show.mo b/test/run-drun/show.mo index d896dcc6e4d..88b0131995e 100644 --- a/test/run-drun/show.mo +++ b/test/run-drun/show.mo @@ -1,37 +1,36 @@ -func printLn(x : Text) { debugPrint(x # "\n"); }; -printLn(debug_show (true)); -printLn(debug_show (false)); -printLn(debug_show (-42000000000000)); -printLn(debug_show (-42000000)); -printLn(debug_show (-42000)); -printLn(debug_show (-42)); -printLn(debug_show (-0)); -printLn(debug_show (+0)); -printLn(debug_show (+42)); -printLn(debug_show (+42000)); -printLn(debug_show (+42000000)); -printLn(debug_show (+420000000000000)); -printLn(debug_show (0)); -printLn(debug_show (42)); -printLn(debug_show (42000)); -printLn(debug_show (42000000)); -printLn(debug_show (420000000000000)); -printLn(debug_show (42,-42,())); -printLn(debug_show ("Foobar", null, null, ?23)); -printLn(debug_show ([])); -printLn(debug_show ([1,2,3])); -printLn(debug_show ([var])); -printLn(debug_show ([var 1,2,3])); +debugPrint(debug_show (true)); +debugPrint(debug_show (false)); +debugPrint(debug_show (-42000000000000)); +debugPrint(debug_show (-42000000)); +debugPrint(debug_show (-42000)); +debugPrint(debug_show (-42)); +debugPrint(debug_show (-0)); +debugPrint(debug_show (+0)); +debugPrint(debug_show (+42)); +debugPrint(debug_show (+42000)); +debugPrint(debug_show (+42000000)); +debugPrint(debug_show (+420000000000000)); +debugPrint(debug_show (0)); +debugPrint(debug_show (42)); +debugPrint(debug_show (42000)); +debugPrint(debug_show (42000000)); +debugPrint(debug_show (420000000000000)); +debugPrint(debug_show (42,-42,())); +debugPrint(debug_show ("Foobar", null, null, ?23)); +debugPrint(debug_show ([])); +debugPrint(debug_show ([1,2,3])); +debugPrint(debug_show ([var])); +debugPrint(debug_show ([var 1,2,3])); class Foo() { public let foo : Int = 42; public var bar : Bool = true ; let hidden = [1,2] }; -printLn(debug_show (Foo())); -printLn(debug_show (#foo ())); -printLn(debug_show (#bar (1, 2))); -printLn(debug_show (#bar {})); -printLn(debug_show (#bar ([]))); -printLn(debug_show (#bar 42)); -printLn(debug_show (#bar (-42))); -printLn(debug_show (#foo 42 : {#foo : Int; #bar : Text})); -printLn(debug_show (42 : Word16)); -printLn(debug_show (42 : Nat8)); -printLn(debug_show (42 : Int32)); -printLn(debug_show (intToInt64 (-42))); +debugPrint(debug_show (Foo())); +debugPrint(debug_show (#foo ())); +debugPrint(debug_show (#bar (1, 2))); +debugPrint(debug_show (#bar {})); +debugPrint(debug_show (#bar ([]))); +debugPrint(debug_show (#bar 42)); +debugPrint(debug_show (#bar (-42))); +debugPrint(debug_show (#foo 42 : {#foo : Int; #bar : Text})); +debugPrint(debug_show (42 : Word16)); +debugPrint(debug_show (42 : Nat8)); +debugPrint(debug_show (42 : Int32)); +debugPrint(debug_show (intToInt64 (-42))); diff --git a/test/run-drun/tailpositions.mo b/test/run-drun/tailpositions.mo index 06d66fe44c5..b171023670a 100644 --- a/test/run-drun/tailpositions.mo +++ b/test/run-drun/tailpositions.mo @@ -5,7 +5,7 @@ let bound:Int = 100000; { func Loop(n:Int){ if (n >= bound) { - debugPrint "done 1\n"; + debugPrint "done 1"; return; }; Loop(n+1); @@ -16,7 +16,7 @@ let bound:Int = 100000; { func Loop(n:Int){ if (n >= bound) { - debugPrint "done 2\n"; + debugPrint "done 2"; return; }; if (true) @@ -31,7 +31,7 @@ let bound:Int = 100000; { func Loop(n:Int){ if (n >= bound) { - debugPrint "done 3\n"; + debugPrint "done 3"; return; }; switch (n % 2) { @@ -47,7 +47,7 @@ let bound:Int = 100000; { func Loop(n:Int){ if (n >= bound) { - debugPrint "done 4\n"; + debugPrint "done 4"; return; }; { let m = n; @@ -61,7 +61,7 @@ let bound:Int = 100000; { func Loop(n:Int){ if (n >= bound) { - debugPrint "done 5\n"; + debugPrint "done 5"; return; }; let _ = (return Loop(n+1)) + 1; @@ -73,7 +73,7 @@ let bound:Int = 100000; { func Loop(n:Int):Bool{ if (n >= bound) { - debugPrint "done 6\n"; + debugPrint "done 6"; return true; }; true and Loop(n+1); @@ -84,7 +84,7 @@ let bound:Int = 100000; { func Loop(n:Int):Bool { if (n >= bound) { - debugPrint "done 7\n"; + debugPrint "done 7"; return true; }; false or Loop(n+1); diff --git a/test/run-drun/text-iter.mo b/test/run-drun/text-iter.mo index 0b160c06688..e2ce9e9ce45 100644 --- a/test/run-drun/text-iter.mo +++ b/test/run-drun/text-iter.mo @@ -1,16 +1,16 @@ -let s = "hello world!\n"; +let s = "hello world!"; -debugPrint "via `debugPrint`:\n"; +debugPrint "via `debugPrint`:"; debugPrint s; -debugPrint "\n"; +debugPrint ""; -debugPrint "via iteration and `debugPrintChar`: #1\n"; +debugPrint "via iteration and `debugPrintChar`: #1"; for (a in s.chars()) { debugPrintChar a; }; -debugPrint "\n"; +debugPrint ""; -debugPrint "via iteration and `debugPrintChar`: #2\n"; +debugPrint "via iteration and `debugPrintChar`: #2"; var x = 0; for (a in s.chars()) { x += 1; @@ -21,12 +21,12 @@ for (a in s.chars()) { debugPrintChar '\''; debugPrint " "; }; -debugPrint "\n"; +debugPrint ""; let russian = "Приветствую, мир!\n"; assert(russian.len() == 18); -debugPrint "via iteration and `debugPrintChar` (Unicode): #3\n"; +debugPrint "via iteration and `debugPrintChar` (Unicode): #3"; x := 0; for (a in russian.chars()) { x += 1; @@ -37,13 +37,13 @@ for (a in russian.chars()) { debugPrintChar '\''; debugPrint " "; }; -debugPrint "\n"; +debugPrint ""; assert(x == 18); let emojis = "🙈🎸😋"; assert(emojis.len() == 3); -debugPrint "via iteration and `debugPrintChar` (Unicode): #4\n"; +debugPrint "via iteration and `debugPrintChar` (Unicode): #4"; x := 0; for (a in emojis.chars()) { x += 1; @@ -54,16 +54,16 @@ for (a in emojis.chars()) { debugPrintChar '\''; debugPrint " "; }; -debugPrint "\n"; +debugPrint ""; assert(x == 3); -debugPrint russian; debugPrint "\n"; +debugPrint russian; debugPrint ""; switch (russian.chars().next()) { - case (?c) { debugPrintChar c; debugPrint "\n" }; + case (?c) { debugPrintChar c; debugPrint "" }; case _ {}; }; switch (emojis.chars().next()) { - case (?c) { assert (c == '\u{1f648}'); debugPrintChar c; debugPrint "\n" }; + case (?c) { assert (c == '\u{1f648}'); debugPrintChar c; debugPrint "" }; case _ {}; }; diff --git a/test/run-release/debug.mo b/test/run-release/debug.mo index 5e8005c6e9c..7a4417f2e9c 100644 --- a/test/run-release/debug.mo +++ b/test/run-release/debug.mo @@ -1,4 +1,4 @@ -debugPrint "This should appear\n"; -debug { debugPrint "This shouldn't appear\n" }; -debugPrint "This should appear too\n"; +debugPrint "This should appear"; +debug { debugPrint "This shouldn't appear" }; +debugPrint "This should appear too"; diff --git a/test/run-stub/actor-creation.mo b/test/run-stub/actor-creation.mo index 0d8dddbe137..a4420eb1be5 100644 --- a/test/run-stub/actor-creation.mo +++ b/test/run-stub/actor-creation.mo @@ -1,21 +1,21 @@ -debugPrint ("main actor creating a\n"); +debugPrint ("main actor creating a"); actor a { public func foo() { - debugPrint ("a.foo() called\n"); + debugPrint ("a.foo() called"); - debugPrint ("a creating b\n"); + debugPrint ("a creating b"); actor b { public func foo() { - debugPrint ("b.foo() called\n"); + debugPrint ("b.foo() called"); }; - debugPrint ("b created\n"); + debugPrint ("b created"); }; - debugPrint ("a calling b.foo()\n"); + debugPrint ("a calling b.foo()"); b.foo(); - debugPrint ("a.foo() done\n"); + debugPrint ("a.foo() done"); }; - debugPrint ("a created\n"); + debugPrint ("a created"); }; -debugPrint ("main actor calling a.foo()\n"); +debugPrint ("main actor calling a.foo()"); a.foo(); diff --git a/test/run-stub/counter.mo b/test/run-stub/counter.mo index 0e40920fb6f..90410b64710 100644 --- a/test/run-stub/counter.mo +++ b/test/run-stub/counter.mo @@ -2,10 +2,10 @@ actor { var c = 1; public func inc() { c += 1; - debugPrintNat c; debugPrint "\n"; + debugPrintNat c; }; public func printCounter () { - debugPrintNat c; debugPrint "\n"; + debugPrintNat c; }; public func get() : async Nat { return c diff --git a/test/run-stub/hello-world-async.mo b/test/run-stub/hello-world-async.mo index e12d76d55d4..a50e970cd9b 100644 --- a/test/run-stub/hello-world-async.mo +++ b/test/run-stub/hello-world-async.mo @@ -1,6 +1,6 @@ let a = actor { public func world() { - debugPrint("World!\n"); + debugPrint("World!"); }; public func go() { a.world(); diff --git a/test/run-stub/ok/actor-creation.ic-stub-run.ok b/test/run-stub/ok/actor-creation.ic-stub-run.ok index 586cb2a776e..983be8d9fef 100644 --- a/test/run-stub/ok/actor-creation.ic-stub-run.ok +++ b/test/run-stub/ok/actor-creation.ic-stub-run.ok @@ -2,21 +2,12 @@ ← completed: canister-id = 0x0000000000000400 → install main actor creating a - main actor calling a.foo() - a created - a.foo() called - a creating b - a calling b.foo() - a.foo() done - b created - b.foo() called - ← completed diff --git a/test/run-stub/ok/counter.ic-stub-run.ok b/test/run-stub/ok/counter.ic-stub-run.ok index 4782a51c086..12512b1f71e 100644 --- a/test/run-stub/ok/counter.ic-stub-run.ok +++ b/test/run-stub/ok/counter.ic-stub-run.ok @@ -4,23 +4,15 @@ ← completed → update inc(0x4449444c0000) 2 - - ← rejected (RC_CANISTER_ERROR): canister did not respond → update inc(0x4449444c0000) 3 - - ← rejected (RC_CANISTER_ERROR): canister did not respond → update inc(0x4449444c0000) 4 - - ← rejected (RC_CANISTER_ERROR): canister did not respond → update printCounter(0x4449444c0000) 4 - - ← rejected (RC_CANISTER_ERROR): canister did not respond → update get(0x4449444c0000) ← completed: 0x4449444c00017d04 diff --git a/test/run-stub/ok/hello-world-async.ic-stub-run.ok b/test/run-stub/ok/hello-world-async.ic-stub-run.ok index 54b0b5b88ee..ddbeb950d79 100644 --- a/test/run-stub/ok/hello-world-async.ic-stub-run.ok +++ b/test/run-stub/ok/hello-world-async.ic-stub-run.ok @@ -5,5 +5,4 @@ → update go(0x4449444c0000) Hello World! - ← rejected (RC_CANISTER_ERROR): canister did not respond diff --git a/test/run-stub/ok/query.ic-stub-run.ok b/test/run-stub/ok/query.ic-stub-run.ok index 8f558b44b5e..fc74a981a76 100644 --- a/test/run-stub/ok/query.ic-stub-run.ok +++ b/test/run-stub/ok/query.ic-stub-run.ok @@ -4,43 +4,27 @@ ← completed → update inc(0x4449444c0000) 2 - - ← rejected (RC_CANISTER_ERROR): canister did not respond → update inc(0x4449444c0000) 3 - - ← rejected (RC_CANISTER_ERROR): canister did not respond → update inc(0x4449444c0000) 4 - - ← rejected (RC_CANISTER_ERROR): canister did not respond → update printCounter(0x4449444c0000) 4 - - ← rejected (RC_CANISTER_ERROR): canister did not respond → update get(0x4449444c0000) ← completed: 0x4449444c00017d04 → query read(0x4449444c0000) 5 - - ← completed: 0x4449444c00017d04 → update printCounter(0x4449444c0000) 4 - - ← rejected (RC_CANISTER_ERROR): canister did not respond → query read(0x4449444c0000) 5 - - ← completed: 0x4449444c00017d04 → update printCounter(0x4449444c0000) 4 - - ← rejected (RC_CANISTER_ERROR): canister did not respond diff --git a/test/run-stub/query.mo b/test/run-stub/query.mo index 3e494c1154e..99edfb122ec 100644 --- a/test/run-stub/query.mo +++ b/test/run-stub/query.mo @@ -2,10 +2,10 @@ actor { var c = 1; public func inc() { c += 1; - debugPrintNat c; debugPrint "\n"; + debugPrintNat c; }; public func printCounter () { - debugPrintNat c; debugPrint "\n"; + debugPrintNat c; }; public func get() : async Nat { return c @@ -13,7 +13,7 @@ actor { public query func read() : async Nat { let tmp = c; c += 1; - debugPrintNat c; debugPrint "\n"; + debugPrintNat c; return tmp; }; diff --git a/test/run/conversions.mo b/test/run/conversions.mo index e4406164507..a5183b996a0 100644 --- a/test/run/conversions.mo +++ b/test/run/conversions.mo @@ -112,7 +112,7 @@ assert(intToWord32 2147483648 == (2147483648 : Word32)); // 2**31 assert(intToWord32 2147483649 == (2147483649 : Word32)); // 2**31 + 1 assert(intToWord32 4294967295 == (4294967295 : Word32)); // 2**32 - 1 -func println(i : Int) { debugPrintInt(i); debugPrint "\n"; }; +func println(i : Int) { debugPrintInt(i) }; println(word32ToInt (-2147483648)); // -2**31 println(word32ToInt (-2147483647)); // -2**31 + 1 diff --git a/test/run/idlHash.mo b/test/run/idlHash.mo index 7ae1af984d9..e9582b817c5 100644 --- a/test/run/idlHash.mo +++ b/test/run/idlHash.mo @@ -1,7 +1,7 @@ func testHash(s : Text, h : Word32) { - debugPrint("Hash for " # s # ":\n"); - debugPrint("Expected: " # debug_show (word32ToNat(h)) # "\n"); - debugPrint("Actual: " # debug_show (word32ToNat(idlHash s)) # "\n"); + debugPrint("Hash for " # s); + debugPrint("Expected: " # debug_show (word32ToNat(h))); + debugPrint("Actual: " # debug_show (word32ToNat(idlHash s))); }; // The lines below can be copied verbatim out of the corresponding JS unit test diff --git a/test/run/numeric-ops.mo b/test/run/numeric-ops.mo index 3ba0aaf7155..f18a6505473 100644 --- a/test/run/numeric-ops.mo +++ b/test/run/numeric-ops.mo @@ -4,10 +4,8 @@ // asserts that those compare equal func verify(etalon : [T], results : [T], cmp : (T, T) -> Bool) { - //debugPrint "\n"; for (i in etalon.keys()) - { //debugPrintInt i; debugPrint "\n"; - assert cmp(etalon[i], results[i * 2]); + { assert cmp(etalon[i], results[i * 2]); assert cmp(etalon[i], results[i * 2 + 1]); } }; diff --git a/test/run/ok/for.run-ir.ok b/test/run/ok/for.run-ir.ok index 718ae076949..b033488efab 100644 --- a/test/run/ok/for.run-ir.ok +++ b/test/run/ok/for.run-ir.ok @@ -1 +1,11 @@ -012345678910 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 diff --git a/test/run/ok/for.run-low.ok b/test/run/ok/for.run-low.ok index 718ae076949..b033488efab 100644 --- a/test/run/ok/for.run-low.ok +++ b/test/run/ok/for.run-low.ok @@ -1 +1,11 @@ -012345678910 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 diff --git a/test/run/ok/for.run.ok b/test/run/ok/for.run.ok index 718ae076949..b033488efab 100644 --- a/test/run/ok/for.run.ok +++ b/test/run/ok/for.run.ok @@ -1 +1,11 @@ -012345678910 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 diff --git a/test/run/ok/idlHash.run-ir.ok b/test/run/ok/idlHash.run-ir.ok index c09174ebcb4..4eb46c64984 100644 --- a/test/run/ok/idlHash.run-ir.ok +++ b/test/run/ok/idlHash.run-ir.ok @@ -1,15 +1,15 @@ -Hash for : +Hash for Expected: 0 Actual: 0 -Hash for id: +Hash for id Expected: 23_515 Actual: 23_515 -Hash for description: +Hash for description Expected: 1_595_738_364 Actual: 1_595_738_364 -Hash for short_name: +Hash for short_name Expected: 3_261_810_734 Actual: 3_261_810_734 -Hash for Hi ☃: +Hash for Hi ☃ Expected: 1_419_229_646 Actual: 1_419_229_646 diff --git a/test/run/ok/idlHash.run-low.ok b/test/run/ok/idlHash.run-low.ok index c09174ebcb4..4eb46c64984 100644 --- a/test/run/ok/idlHash.run-low.ok +++ b/test/run/ok/idlHash.run-low.ok @@ -1,15 +1,15 @@ -Hash for : +Hash for Expected: 0 Actual: 0 -Hash for id: +Hash for id Expected: 23_515 Actual: 23_515 -Hash for description: +Hash for description Expected: 1_595_738_364 Actual: 1_595_738_364 -Hash for short_name: +Hash for short_name Expected: 3_261_810_734 Actual: 3_261_810_734 -Hash for Hi ☃: +Hash for Hi ☃ Expected: 1_419_229_646 Actual: 1_419_229_646 diff --git a/test/run/ok/idlHash.run.ok b/test/run/ok/idlHash.run.ok index c09174ebcb4..4eb46c64984 100644 --- a/test/run/ok/idlHash.run.ok +++ b/test/run/ok/idlHash.run.ok @@ -1,15 +1,15 @@ -Hash for : +Hash for Expected: 0 Actual: 0 -Hash for id: +Hash for id Expected: 23_515 Actual: 23_515 -Hash for description: +Hash for description Expected: 1_595_738_364 Actual: 1_595_738_364 -Hash for short_name: +Hash for short_name Expected: 3_261_810_734 Actual: 3_261_810_734 -Hash for Hi ☃: +Hash for Hi ☃ Expected: 1_419_229_646 Actual: 1_419_229_646 diff --git a/test/run/ok/words.run-ir.ok b/test/run/ok/words.run-ir.ok index dd9453afeb5..2e9de829814 100644 --- a/test/run/ok/words.run-ir.ok +++ b/test/run/ok/words.run-ir.ok @@ -1,98 +1,270 @@ -8_912_765 +8_912_765 -18_446_744_073_700_638_851 -8_912_765 -18_446_744_073_700_638_850 -8_912_766 -8_917_332 +8_917_332 -8_908_198 +8_908_198 -31_969 +31_969 -652 +652 -2_548 +2_548 -20_857_489 +20_857_489 -4_437 +4_437 -8_912_895 +8_912_895 -8_908_458 +8_908_458 -584_576 +584_576 -35 +35 -826_339_054_743_125_951 +826_339_054_743_125_951 -18_446_744_073_709_551_614 -2 -18_120_161_623_845_830_591 -326_582_449_863_721_025 -1_140_833_920 +1_140_833_920 -18_014_398_509_482_053_630 -432_345_564_227_497_986 -61 +61 -49 +49 -5 +5 +8_912_765 + ++8_912_765 +18_446_744_073_700_638_851 + +-8_912_765 +18_446_744_073_700_638_850 + +-8_912_766 +8_917_332 + ++8_917_332 +8_908_198 + ++8_908_198 +31_969 + ++31_969 +652 + ++652 +2_548 + ++2_548 +20_857_489 + ++20_857_489 +4_437 + ++4_437 +8_912_895 + ++8_912_895 +8_908_458 + ++8_908_458 +584_576 + ++584_576 +35 + ++35 +826_339_054_743_125_951 + ++826_339_054_743_125_951 +18_446_744_073_709_551_614 + +-2 +18_120_161_623_845_830_591 + +-326_582_449_863_721_025 +1_140_833_920 + ++1_140_833_920 +18_014_398_509_482_053_630 + +-432_345_564_227_497_986 +61 + ++61 +49 + ++49 +5 + ++5 set clear set -8_912_765 +8_912_765 -4_286_054_531 -8_912_765 -4_286_054_530 -8_912_766 -8_917_332 +8_917_332 -8_908_198 +8_908_198 -31_969 +31_969 -652 +652 -2_548 +2_548 -20_857_489 +20_857_489 -4_437 +4_437 -8_912_895 +8_912_895 -8_908_458 +8_908_458 -584_576 +584_576 -35 +35 -192_397_053 +192_397_053 -4_294_967_294 -2 -4_218_928_893 -76_038_403 -1_140_833_920 +1_140_833_920 -4_194_373_630 -100_593_666 -29 +29 -17 +17 -5 +5 +8_912_765 + ++8_912_765 +4_286_054_531 + +-8_912_765 +4_286_054_530 + +-8_912_766 +8_917_332 + ++8_917_332 +8_908_198 + ++8_908_198 +31_969 + ++31_969 +652 + ++652 +2_548 + ++2_548 +20_857_489 + ++20_857_489 +4_437 + ++4_437 +8_912_895 + ++8_912_895 +8_908_458 + ++8_908_458 +584_576 + ++584_576 +35 + ++35 +192_397_053 + ++192_397_053 +4_294_967_294 + +-2 +4_218_928_893 + +-76_038_403 +1_140_833_920 + ++1_140_833_920 +4_194_373_630 + +-100_593_666 +29 + ++29 +17 + ++17 +5 + ++5 set clear set -55_734 -9_802 -9_802 +9_802 -9_801 +9_801 -60_301 -5_235 -51_167 -14_369 -31_969 +31_969 -652 +652 -930 +930 -17_041 +17_041 -4_502 +4_502 -55_799 -9_737 -51_297 -14_239 -60_288 -5_248 -35 +35 -8_190 +8_190 -65_534 -2 -56_172 -9_364 -28_083 +28_083 -13 +13 -1 +1 -5 +5 +55_734 + +-9_802 +9_802 + ++9_802 +9_801 + ++9_801 +60_301 + +-5_235 +51_167 + +-14_369 +31_969 + ++31_969 +652 + ++652 +930 + ++930 +17_041 + ++17_041 +4_502 + ++4_502 +55_799 + +-9_737 +51_297 + +-14_239 +60_288 + +-5_248 +35 + ++35 +8_190 + ++8_190 +65_534 + +-2 +56_172 + +-9_364 +28_083 + ++28_083 +13 + ++13 +1 + ++1 +5 + ++5 set clear set -34 +34 -222 -34 -221 -35 -101 +101 -223 -33 -213 -43 -9 +9 -34 +34 -137 -119 -2 +2 -99 +99 -97 +97 -128 -128 -0 0 -30 +30 -254 -2 -17 +17 -68 +68 -5 +5 -0 0 -3 +3 +34 + ++34 +222 + +-34 +221 + +-35 +101 + ++101 +223 + +-33 +213 + +-43 +9 + ++9 +34 + ++34 +137 + +-119 +2 + ++2 +99 + ++99 +97 + ++97 +128 + +-128 +0 + +0 +30 + ++30 +254 + +-2 +17 + ++17 +68 + ++68 +5 + ++5 +0 + +0 +3 + ++3 set clear set diff --git a/test/run/ok/words.run-low.ok b/test/run/ok/words.run-low.ok index dd9453afeb5..2e9de829814 100644 --- a/test/run/ok/words.run-low.ok +++ b/test/run/ok/words.run-low.ok @@ -1,98 +1,270 @@ -8_912_765 +8_912_765 -18_446_744_073_700_638_851 -8_912_765 -18_446_744_073_700_638_850 -8_912_766 -8_917_332 +8_917_332 -8_908_198 +8_908_198 -31_969 +31_969 -652 +652 -2_548 +2_548 -20_857_489 +20_857_489 -4_437 +4_437 -8_912_895 +8_912_895 -8_908_458 +8_908_458 -584_576 +584_576 -35 +35 -826_339_054_743_125_951 +826_339_054_743_125_951 -18_446_744_073_709_551_614 -2 -18_120_161_623_845_830_591 -326_582_449_863_721_025 -1_140_833_920 +1_140_833_920 -18_014_398_509_482_053_630 -432_345_564_227_497_986 -61 +61 -49 +49 -5 +5 +8_912_765 + ++8_912_765 +18_446_744_073_700_638_851 + +-8_912_765 +18_446_744_073_700_638_850 + +-8_912_766 +8_917_332 + ++8_917_332 +8_908_198 + ++8_908_198 +31_969 + ++31_969 +652 + ++652 +2_548 + ++2_548 +20_857_489 + ++20_857_489 +4_437 + ++4_437 +8_912_895 + ++8_912_895 +8_908_458 + ++8_908_458 +584_576 + ++584_576 +35 + ++35 +826_339_054_743_125_951 + ++826_339_054_743_125_951 +18_446_744_073_709_551_614 + +-2 +18_120_161_623_845_830_591 + +-326_582_449_863_721_025 +1_140_833_920 + ++1_140_833_920 +18_014_398_509_482_053_630 + +-432_345_564_227_497_986 +61 + ++61 +49 + ++49 +5 + ++5 set clear set -8_912_765 +8_912_765 -4_286_054_531 -8_912_765 -4_286_054_530 -8_912_766 -8_917_332 +8_917_332 -8_908_198 +8_908_198 -31_969 +31_969 -652 +652 -2_548 +2_548 -20_857_489 +20_857_489 -4_437 +4_437 -8_912_895 +8_912_895 -8_908_458 +8_908_458 -584_576 +584_576 -35 +35 -192_397_053 +192_397_053 -4_294_967_294 -2 -4_218_928_893 -76_038_403 -1_140_833_920 +1_140_833_920 -4_194_373_630 -100_593_666 -29 +29 -17 +17 -5 +5 +8_912_765 + ++8_912_765 +4_286_054_531 + +-8_912_765 +4_286_054_530 + +-8_912_766 +8_917_332 + ++8_917_332 +8_908_198 + ++8_908_198 +31_969 + ++31_969 +652 + ++652 +2_548 + ++2_548 +20_857_489 + ++20_857_489 +4_437 + ++4_437 +8_912_895 + ++8_912_895 +8_908_458 + ++8_908_458 +584_576 + ++584_576 +35 + ++35 +192_397_053 + ++192_397_053 +4_294_967_294 + +-2 +4_218_928_893 + +-76_038_403 +1_140_833_920 + ++1_140_833_920 +4_194_373_630 + +-100_593_666 +29 + ++29 +17 + ++17 +5 + ++5 set clear set -55_734 -9_802 -9_802 +9_802 -9_801 +9_801 -60_301 -5_235 -51_167 -14_369 -31_969 +31_969 -652 +652 -930 +930 -17_041 +17_041 -4_502 +4_502 -55_799 -9_737 -51_297 -14_239 -60_288 -5_248 -35 +35 -8_190 +8_190 -65_534 -2 -56_172 -9_364 -28_083 +28_083 -13 +13 -1 +1 -5 +5 +55_734 + +-9_802 +9_802 + ++9_802 +9_801 + ++9_801 +60_301 + +-5_235 +51_167 + +-14_369 +31_969 + ++31_969 +652 + ++652 +930 + ++930 +17_041 + ++17_041 +4_502 + ++4_502 +55_799 + +-9_737 +51_297 + +-14_239 +60_288 + +-5_248 +35 + ++35 +8_190 + ++8_190 +65_534 + +-2 +56_172 + +-9_364 +28_083 + ++28_083 +13 + ++13 +1 + ++1 +5 + ++5 set clear set -34 +34 -222 -34 -221 -35 -101 +101 -223 -33 -213 -43 -9 +9 -34 +34 -137 -119 -2 +2 -99 +99 -97 +97 -128 -128 -0 0 -30 +30 -254 -2 -17 +17 -68 +68 -5 +5 -0 0 -3 +3 +34 + ++34 +222 + +-34 +221 + +-35 +101 + ++101 +223 + +-33 +213 + +-43 +9 + ++9 +34 + ++34 +137 + +-119 +2 + ++2 +99 + ++99 +97 + ++97 +128 + +-128 +0 + +0 +30 + ++30 +254 + +-2 +17 + ++17 +68 + ++68 +5 + ++5 +0 + +0 +3 + ++3 set clear set diff --git a/test/run/ok/words.run.ok b/test/run/ok/words.run.ok index dd9453afeb5..2e9de829814 100644 --- a/test/run/ok/words.run.ok +++ b/test/run/ok/words.run.ok @@ -1,98 +1,270 @@ -8_912_765 +8_912_765 -18_446_744_073_700_638_851 -8_912_765 -18_446_744_073_700_638_850 -8_912_766 -8_917_332 +8_917_332 -8_908_198 +8_908_198 -31_969 +31_969 -652 +652 -2_548 +2_548 -20_857_489 +20_857_489 -4_437 +4_437 -8_912_895 +8_912_895 -8_908_458 +8_908_458 -584_576 +584_576 -35 +35 -826_339_054_743_125_951 +826_339_054_743_125_951 -18_446_744_073_709_551_614 -2 -18_120_161_623_845_830_591 -326_582_449_863_721_025 -1_140_833_920 +1_140_833_920 -18_014_398_509_482_053_630 -432_345_564_227_497_986 -61 +61 -49 +49 -5 +5 +8_912_765 + ++8_912_765 +18_446_744_073_700_638_851 + +-8_912_765 +18_446_744_073_700_638_850 + +-8_912_766 +8_917_332 + ++8_917_332 +8_908_198 + ++8_908_198 +31_969 + ++31_969 +652 + ++652 +2_548 + ++2_548 +20_857_489 + ++20_857_489 +4_437 + ++4_437 +8_912_895 + ++8_912_895 +8_908_458 + ++8_908_458 +584_576 + ++584_576 +35 + ++35 +826_339_054_743_125_951 + ++826_339_054_743_125_951 +18_446_744_073_709_551_614 + +-2 +18_120_161_623_845_830_591 + +-326_582_449_863_721_025 +1_140_833_920 + ++1_140_833_920 +18_014_398_509_482_053_630 + +-432_345_564_227_497_986 +61 + ++61 +49 + ++49 +5 + ++5 set clear set -8_912_765 +8_912_765 -4_286_054_531 -8_912_765 -4_286_054_530 -8_912_766 -8_917_332 +8_917_332 -8_908_198 +8_908_198 -31_969 +31_969 -652 +652 -2_548 +2_548 -20_857_489 +20_857_489 -4_437 +4_437 -8_912_895 +8_912_895 -8_908_458 +8_908_458 -584_576 +584_576 -35 +35 -192_397_053 +192_397_053 -4_294_967_294 -2 -4_218_928_893 -76_038_403 -1_140_833_920 +1_140_833_920 -4_194_373_630 -100_593_666 -29 +29 -17 +17 -5 +5 +8_912_765 + ++8_912_765 +4_286_054_531 + +-8_912_765 +4_286_054_530 + +-8_912_766 +8_917_332 + ++8_917_332 +8_908_198 + ++8_908_198 +31_969 + ++31_969 +652 + ++652 +2_548 + ++2_548 +20_857_489 + ++20_857_489 +4_437 + ++4_437 +8_912_895 + ++8_912_895 +8_908_458 + ++8_908_458 +584_576 + ++584_576 +35 + ++35 +192_397_053 + ++192_397_053 +4_294_967_294 + +-2 +4_218_928_893 + +-76_038_403 +1_140_833_920 + ++1_140_833_920 +4_194_373_630 + +-100_593_666 +29 + ++29 +17 + ++17 +5 + ++5 set clear set -55_734 -9_802 -9_802 +9_802 -9_801 +9_801 -60_301 -5_235 -51_167 -14_369 -31_969 +31_969 -652 +652 -930 +930 -17_041 +17_041 -4_502 +4_502 -55_799 -9_737 -51_297 -14_239 -60_288 -5_248 -35 +35 -8_190 +8_190 -65_534 -2 -56_172 -9_364 -28_083 +28_083 -13 +13 -1 +1 -5 +5 +55_734 + +-9_802 +9_802 + ++9_802 +9_801 + ++9_801 +60_301 + +-5_235 +51_167 + +-14_369 +31_969 + ++31_969 +652 + ++652 +930 + ++930 +17_041 + ++17_041 +4_502 + ++4_502 +55_799 + +-9_737 +51_297 + +-14_239 +60_288 + +-5_248 +35 + ++35 +8_190 + ++8_190 +65_534 + +-2 +56_172 + +-9_364 +28_083 + ++28_083 +13 + ++13 +1 + ++1 +5 + ++5 set clear set -34 +34 -222 -34 -221 -35 -101 +101 -223 -33 -213 -43 -9 +9 -34 +34 -137 -119 -2 +2 -99 +99 -97 +97 -128 -128 -0 0 -30 +30 -254 -2 -17 +17 -68 +68 -5 +5 -0 0 -3 +3 +34 + ++34 +222 + +-34 +221 + +-35 +101 + ++101 +223 + +-33 +213 + +-43 +9 + ++9 +34 + ++34 +137 + +-119 +2 + ++2 +99 + ++99 +97 + ++97 +128 + +-128 +0 + +0 +30 + ++30 +254 + +-2 +17 + ++17 +68 + ++68 +5 + ++5 +0 + +0 +3 + ++3 set clear set diff --git a/test/run/variants.mo b/test/run/variants.mo index 43f54088c1b..f9181a06970 100644 --- a/test/run/variants.mo +++ b/test/run/variants.mo @@ -10,8 +10,8 @@ func size(t : Tree) : Nat { let tt1 : Tree = #branch(#leaf 1, #leaf (-1)); let tt2 = #leaf ""; // infers type {#leaf : Text} which is a subtype of Tree -debugPrintNat(size(tt1)); debugPrint "\n"; -debugPrintNat(size(tt2)); debugPrint "\n"; +debugPrintNat(size(tt1)); +debugPrintNat(size(tt2)); // subtyping diff --git a/test/run/words.mo b/test/run/words.mo index 0a9f82071a6..899742ec0b5 100644 --- a/test/run/words.mo +++ b/test/run/words.mo @@ -1,6 +1,6 @@ // CHECK: func $start -func printBit(a : Bool) { debugPrint(if a "set" else "clear"); debugPrint "\n" }; +func printBit(a : Bool) { debugPrint(if a "set" else "clear") }; func checkpointAlpha() {}; @@ -16,7 +16,7 @@ func checkpointJuliett() {}; // Word64 operations { - func printW64ln(w : Word64) { debugPrintNat(word64ToNat w); debugPrint " "; debugPrintInt(word64ToInt w); debugPrint "\n" }; + func printW64ln(w : Word64) { debugPrintNat(word64ToNat w); debugPrint " "; debugPrintInt(word64ToInt w) }; let a : Word64 = 4567; let b : Word64 = 7; @@ -71,7 +71,7 @@ func checkpointJuliett() {}; // Word32 operations { - func printW32ln(w : Word32) { debugPrintNat(word32ToNat w); debugPrint " "; debugPrintInt(word32ToInt w); debugPrint "\n" }; + func printW32ln(w : Word32) { debugPrintNat(word32ToNat w); debugPrint " "; debugPrintInt(word32ToInt w) }; let a : Word32 = 4567; let b : Word32 = 7; @@ -125,7 +125,7 @@ func checkpointJuliett() {}; // Word16 operations { - func printW16ln(w : Word16) { debugPrintNat(word16ToNat w); debugPrint " "; debugPrintInt(word16ToInt w); debugPrint "\n" }; + func printW16ln(w : Word16) { debugPrintNat(word16ToNat w); debugPrint " "; debugPrintInt(word16ToInt w) }; let a : Word16 = 4567; let b : Word16 = 7; @@ -205,7 +205,7 @@ func checkpointJuliett() {}; // Word8 operations { - func printW8ln(w : Word8) { debugPrintNat(word8ToNat w); debugPrint " "; debugPrintInt(word8ToInt w); debugPrint "\n" }; + func printW8ln(w : Word8) { debugPrintNat(word8ToNat w); debugPrint " "; debugPrintInt(word8ToInt w) }; let a : Word8 = 67; let b : Word8 = 7; From ecfa183016f164d1683e719975dd7a7933957c5e Mon Sep 17 00:00:00 2001 From: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> Date: Fri, 22 Nov 2019 12:43:34 +0100 Subject: [PATCH 0693/1176] updates the Emacs config to take advantage of `dfx ide` (#885) --- emacs/init.el | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/emacs/init.el b/emacs/init.el index dd620c666bb..0553b57c063 100644 --- a/emacs/init.el +++ b/emacs/init.el @@ -6,9 +6,11 @@ ;; your personal configuration. ;; ;; Requirements: -;; - Emacs 26 or newer -;; - `as-ide` binary (Can be generated with `make as-ide` in the -;; compiler repo) +;; 1. Emacs 26 or newer +;; 2. dfx +;; OR +;; 2. mo-ide binary (Can be generated with `make mo-ide` in the +;; compiler repo) ;; ;; How to use: ;; @@ -20,21 +22,24 @@ ;; ;; (adjust to match the path to this file) ;; -;; 3. Open an AS source file in an AS project and select the project -;; root from the menu +;; 3. Open a Motoko source file in a Motoko project and select the +;; project root from the menu ;;======== SETTINGS ========== -;; Change this to point to your `as-ide` binary, or leave it if the -;; binary can be found on your PATH -(setq as/ide-binary "as-ide") +;; Change this to the command that starts the language server on your +;; machine. In a dfx project with dfx on your path that is just `dfx +;; ide`. If you have a more complicated setup you have to pass the +;; proper entry point and library paths to the `mo-ide` binary +;; yourself. +(setq mo/lsp-command '("dfx" "ide")) ;; Change this to point to the directory where you cloned the ;; motoko repo -(setq as/installation-directory "~/code/motoko") +(setq mo/installation-directory "~/code/motoko") ;; Change nil to t if you want to use vim bindings for editing and ;; navigation -(setq as/use-evil nil) +(setq mo/use-evil nil) ;;============================ (require 'package) @@ -58,10 +63,10 @@ (use-package swift-mode :ensure t) (eval-and-compile - (defun as/as-mode-load-path () - (format "%s/emacs" as/installation-directory))) + (defun mo/mo-mode-load-path () + (format "%s/emacs" mo/installation-directory))) (use-package motoko-mode - :load-path (lambda () (list (as/as-mode-load-path))) + :load-path (lambda () (list (mo/mo-mode-load-path))) :config (add-hook 'motoko-mode-hook 'flycheck-mode) (add-hook 'motoko-mode-hook 'lsp) @@ -74,9 +79,9 @@ (add-to-list 'lsp-language-id-configuration '(motoko-mode . "motoko")) (lsp-register-client (make-lsp-client - :new-connection (lsp-stdio-connection as/ide-binary) + :new-connection (lsp-stdio-connection mo/lsp-command) :major-modes '(motoko-mode) - :server-id 'asls))) + :server-id 'mo-lsp))) (use-package lsp-ui :ensure t :commands lsp-ui-mode :config (setq lsp-ui-sideline-enable nil)) @@ -85,7 +90,7 @@ (use-package yasnippet :ensure t) (use-package flycheck :ensure t) -(when as/use-evil +(when mo/use-evil (use-package evil :ensure t :init From b7af8e82603bbbbd3bc6b1ddf47800c7d81d4693 Mon Sep 17 00:00:00 2001 From: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> Date: Fri, 22 Nov 2019 14:52:19 +0100 Subject: [PATCH 0694/1176] [LSP] Returns completions and locations for the current modules toplevel definitions (#896) * Adds completions and locations for toplevels in the current module Also fixes go-to-definition to return proper URIs * almost as good as do-syntax * inline single use definition * reenables test that started working again --- src/languageServer/completion.ml | 45 ++++++++++++++++++++----- src/languageServer/completion_test.ml | 12 +++++-- src/languageServer/definition.ml | 48 +++++++++++++++------------ test/lsp-int/Main.hs | 2 -- 4 files changed, 73 insertions(+), 34 deletions(-) diff --git a/src/languageServer/completion.ml b/src/languageServer/completion.ml index 3a40ceaa56e..3be02afb733 100644 --- a/src/languageServer/completion.ml +++ b/src/languageServer/completion.ml @@ -81,10 +81,14 @@ let find_completion_prefix logger file line column: (string * string) option = pos.Source.line = line && pos.Source.column = column in let pos_past_cursor pos = pos.Source.line > line - || (pos.Source.line = line && pos.Source.column >= column) in + || (pos.Source.line = line && pos.Source.column > column) in let rec loop = function | _ when (pos_past_cursor (Lexer.region lexbuf).Source.right) -> None | Parser.ID ident -> + let next_token_end = (Lexer.region lexbuf).Source.right in + if pos_eq_cursor next_token_end + then Some("", ident) + else (match next () with | Parser.DOT -> (match next () with @@ -96,7 +100,8 @@ let find_completion_prefix logger file line column: (string * string) option = else loop (Parser.ID prefix) | tkn -> let next_token_start = (Lexer.region lexbuf).Source.left in - if pos_past_cursor next_token_start + if pos_eq_cursor next_token_start + || pos_past_cursor next_token_start then Some (ident, "") else loop tkn) | tkn -> loop tkn) @@ -104,8 +109,19 @@ let find_completion_prefix logger file line column: (string * string) option = | _ -> loop (next ()) in try loop (next ()) with _ -> None +let has_prefix (prefix : string) (ide_decl : ide_decl): bool = + ide_decl + |> name_of_ide_decl + |> Lib.String.chop_prefix prefix + |> Lib.Option.is_some + +let opt_bind f = function + | None -> None + | Some x -> f x + let completions index logger project_root file_path file_contents line column = let imported = Source_file.parse_module_header project_root file_path file_contents in + let current_uri_opt = Pipeline__.File_path.relative_to project_root file_path in let module_alias_completion_item alias = Lsp_t.{ completion_item_label = alias; @@ -117,9 +133,26 @@ let completions index logger project_root file_path file_contents line column = match find_completion_prefix logger file_contents line column with | None -> (* If we don't have any prefix to work with, just suggest the - imported module aliases *) + imported module aliases, as well as top-level definitions in + the current file *) + let toplevel = + current_uri_opt + |> opt_bind (fun uri -> Index.find_opt uri index) + |> Lib.Option.map (List.map item_of_ide_decl) + |> Lib.Fun.flip Lib.Option.get [] in imported |> List.map (fun (alias, _) -> module_alias_completion_item alias) + |> List.append toplevel + | Some ("", prefix) -> + (* Without an alias but with a prefix we filter the toplevel + idenfiers of the current module *) + current_uri_opt + |> opt_bind (fun uri -> Index.find_opt uri index) + |> Lib.Option.map (fun decls -> + decls + |> List.filter (has_prefix prefix) + |> List.map item_of_ide_decl) + |> Lib.Fun.flip Lib.Option.get [] | Some (alias, prefix) -> let module_path = imported @@ -129,11 +162,7 @@ let completions index logger project_root file_path file_contents line column = (match Index.find_opt (snd mp) index with | Some decls -> decls - |> List.filter - (fun d -> d - |> name_of_ide_decl - |> Lib.String.chop_prefix prefix - |> Lib.Option.is_some) + |> List.filter (has_prefix prefix) |> List.map item_of_ide_decl | None -> (* The matching import references a module we haven't loaded *) diff --git a/src/languageServer/completion_test.ml b/src/languageServer/completion_test.ml index e4dd4adc154..078dbc4ac27 100644 --- a/src/languageServer/completion_test.ml +++ b/src/languageServer/completion_test.ml @@ -43,12 +43,18 @@ let import_relative_test_case root module_path import expected = (show actual); false) +let%test "it finds unqualified prefixes" = + prefix_test_case "filt|" (Some ("", "filt")) + +let%test "it understands whitespace" = + prefix_test_case "filt |" None + +let%test "it does find non-qualified idents after qualifiers" = + prefix_test_case "List.filter we|" (Some ("", "we")) + let%test "it finds a simple prefix" = prefix_test_case "List.|" (Some ("List", "")) -let%test "it doesn't find non-qualified idents" = - prefix_test_case "List.filter we|" None - let%test "it picks the qualified closest to the cursor" = prefix_test_case "Stack.some List.|" (Some ("List", "")) diff --git a/src/languageServer/definition.ml b/src/languageServer/definition.ml index f6cc1622d9a..718579df563 100644 --- a/src/languageServer/definition.ml +++ b/src/languageServer/definition.ml @@ -12,6 +12,21 @@ let range_of_region (at : Source.region) : Lsp.range = Lsp. range_end_ = position_of_pos at.Source.right; } +let find_named (name : string) : ide_decl list -> Source.region option = + Lib.List.first_opt (function + | ValueDecl value -> + if String.equal value.name name + then value.definition + else None + | TypeDecl typ -> + if String.equal typ.name name + then typ.definition + else None) + +let opt_bind f = function + | Some x -> f x + | None -> None + let definition_handler index position @@ -26,32 +41,23 @@ let definition_handler file_contents position) (function - | Source_file.Resolved resolved -> - Index.find_opt resolved.Source_file.path index - |> Lib.Fun.flip Lib.Option.bind (fun decls -> - decls - |> Lib.List.first_opt (function - | ValueDecl value -> - if String.equal value.name resolved.Source_file.ident - then - value.definition - |> Lib.Option.map (fun def -> - (resolved.Source_file.path, def)) - else None - | TypeDecl typ -> - if String.equal typ.name resolved.Source_file.ident - then - typ.definition - |> Lib.Option.map (fun def -> - (resolved.Source_file.path, def)) - else None)) | Source_file.Alias _ -> None | Source_file.Unresolved _ -> None - | Source_file.Ident _ -> None) in + | Source_file.Resolved resolved -> + Index.find_opt resolved.Source_file.path index + |> opt_bind (find_named resolved.Source_file.ident) + |> Lib.Option.map (fun loc -> (resolved.Source_file.path, loc)) + | Source_file.Ident ident -> + Pipeline__.File_path.relative_to project_root file_path + |> opt_bind (fun uri -> + Index.find_opt uri index + |> opt_bind (find_named ident) + |> Lib.Option.map (fun loc -> (uri, loc)) + )) in let location = Lib.Option.map (fun (path, region) -> Lsp. - { location_uri = path; + { location_uri = Vfs.uri_from_file path; location_range = range_of_region region }) result in `TextDocumentDefinitionResponse location diff --git a/test/lsp-int/Main.hs b/test/lsp-int/Main.hs index d41dc60c371..895d479a6f5 100644 --- a/test/lsp-int/Main.hs +++ b/test/lsp-int/Main.hs @@ -116,7 +116,6 @@ main = handleHUnitFailure $ do -- It finds errors in transitive modules that have been changed in -- the vfs but not yet stored to disc - {- TODO(Christoph): Figure out why this isn't working right now doc <- openDoc "ListClient.mo" "motoko" let edit = TextEdit (Range (Position 0 1) (Position 0 3)) "" _ <- applyEdit doc edit @@ -125,4 +124,3 @@ main = handleHUnitFailure $ do diags <- waitForDiagnostics (diagnostic:_) <- waitForDiagnostics liftIO (diagnostic^.message `shouldBe` "unexpected token") - -} From 14cc084640542c32e9168dce4fecb21ad11a0370 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 22 Nov 2019 16:45:06 +0100 Subject: [PATCH 0695/1176] Backend: When asserting false, use `ic.trap` with a helpful message (#911) this will greatly improve the lifes of our poor developers. Another very good reason to switch our non-IC tests to WASI, i.e. https://github.com/dfinity-lab/motoko/pull/675, so that we see these prints. --- src/codegen/compile.ml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 26d214c5996..a892caa5667 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -3339,7 +3339,7 @@ module Dfinity = struct | _ -> assert false (* Actor reference on the stack *) - and actor_public_field env name = + let actor_public_field env name = match E.mode env with | Flags.AncientMode -> compile_databuf_of_bytes env name ^^ @@ -3350,6 +3350,9 @@ module Dfinity = struct Tuple.from_stack env 2 | Flags.WasmMode -> assert false + let fail_assert env at = + E.trap_with env (Printf.sprintf "assertion failed at %s" (string_of_region at)) + end (* Dfinity *) module OrthogonalPersistence = struct @@ -6702,7 +6705,7 @@ and compile_exp (env : E.t) ae exp = | AssertE e1 -> SR.unit, compile_exp_as env ae SR.bool e1 ^^ - G.if_ (ValBlockType None) G.nop (G.i Unreachable) + G.if_ (ValBlockType None) G.nop (Dfinity.fail_assert env exp.at) | IfE (scrut, e1, e2) -> let code_scrut = compile_exp_as env ae SR.bool scrut in let sr1, code1 = compile_exp env ae e1 in From 4c3b5e1b377fd194bd1e180eb590e0fbe8878e36 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 22 Nov 2019 19:24:54 +0100 Subject: [PATCH 0696/1176] IC Stub: Always print traps (#912) even if the reject they produce are ignored (e.g. in one-way messages). Helpful for debugging. This goes well together with #911. --- ic-stub/ic-stub.cabal | 1 + ic-stub/src/IC/Logger.hs | 12 ++++++++++++ ic-stub/src/IC/Stub.hs | 6 ++++-- test/run-stub/ok/idl-nary.ic-stub-run.ok | 2 ++ 4 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 ic-stub/src/IC/Logger.hs diff --git a/ic-stub/ic-stub.cabal b/ic-stub/ic-stub.cabal index f5e2ed427f7..fc19d9e9c2b 100644 --- a/ic-stub/ic-stub.cabal +++ b/ic-stub/ic-stub.cabal @@ -16,6 +16,7 @@ executable ic-stub-run other-modules: IC.Types other-modules: IC.Canister other-modules: IC.Id + other-modules: IC.Logger other-modules: IC.Canister.Imp other-modules: IC.Canister.Interface other-modules: IC.Canister.Pure diff --git a/ic-stub/src/IC/Logger.hs b/ic-stub/src/IC/Logger.hs new file mode 100644 index 00000000000..10a4a24e4e8 --- /dev/null +++ b/ic-stub/src/IC/Logger.hs @@ -0,0 +1,12 @@ +module IC.Logger where + +import Control.Monad.State + +class Logger m where + logTrap :: String -> m () + +instance (Monad m, Logger m) => Logger (StateT s m) where + logTrap x = lift $ logTrap x + +instance Logger IO where + logTrap msg = putStrLn $ "Trap: " ++ msg diff --git a/ic-stub/src/IC/Stub.hs b/ic-stub/src/IC/Stub.hs index 0dcf61e2978..dea3114ec99 100644 --- a/ic-stub/src/IC/Stub.hs +++ b/ic-stub/src/IC/Stub.hs @@ -35,6 +35,7 @@ import Data.Foldable (toList) import IC.Types import IC.Canister import IC.Id +import IC.Logger -- Abstract HTTP Interface @@ -74,7 +75,7 @@ data CanState = CanState , can_mod :: CanisterModule } -type ICT = MonadState IC +type ICT m = (MonadState IC m, Logger m) data EntryPoint = Public MethodName Blob @@ -331,7 +332,8 @@ processMessage (CallMessage ctxt_id entry) = do Just Nothing -> res $ Reject (RC_DESTINATION_INVALID, "canister is empty") Just (Just cs) -> invokeEntry ctxt_id cs entry >>= \case - Trap msg -> + Trap msg -> do + logTrap msg rememberTrap ctxt_id msg Return (new_state, (new_canisters, new_calls, mb_response)) -> do setCanisterState callee new_state diff --git a/test/run-stub/ok/idl-nary.ic-stub-run.ok b/test/run-stub/ok/idl-nary.ic-stub-run.ok index 6a9444f8d0c..53330a2c4ac 100644 --- a/test/run-stub/ok/idl-nary.ic-stub-run.ok +++ b/test/run-stub/ok/idl-nary.ic-stub-run.ok @@ -19,8 +19,10 @@ → update unary4(0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572) ← completed: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 → update three(0x4449444c00027171034f6e650354776f) +Trap: EvalTrapError :0.1 "canister trapped explicitly: IDL error: too few arguments Text,Text,Text" ← rejected (RC_CANISTER_ERROR): canister trapped: EvalTrapError :0.1 "canister trapped explicitly: IDL error: too few arguments Text,Text,Text" → update three(0x4449444c0003717171034f6e650354776f05546872656545585452414259544553) +Trap: EvalTrapError :0.1 "canister trapped explicitly: IDL error: left-over bytes Text,Text,Text" ← rejected (RC_CANISTER_ERROR): canister trapped: EvalTrapError :0.1 "canister trapped explicitly: IDL error: left-over bytes Text,Text,Text" → update four(0x4449444c00057171717171034f6e650354776f05546872656504466f75720446697665) ← completed: 0x4449444c000471717171034f6e650354776f05546872656504466f7572 From 266518dea7439d8bbdf2e5969262eb18a2176cbb Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Fri, 22 Nov 2019 12:09:06 -0700 Subject: [PATCH 0697/1176] private fields; use while loop for append --- stdlib/array.mo | 2 +- stdlib/buf.mo | 20 +++++++------------- stdlib/bufTest.mo | 12 +++++++++++- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/stdlib/array.mo b/stdlib/array.mo index 79227690250..52a22b51b84 100644 --- a/stdlib/array.mo +++ b/stdlib/array.mo @@ -119,7 +119,7 @@ module { ys; }; - public func TabulateVar(len : Nat, gen : Nat -> A) : [var A] { + public func tabulateVar(len : Nat, gen : Nat -> A) : [var A] { if (len == 0) { return [var] }; let xs = Array_init(len, gen 0); for (i in range(1,len)) { diff --git a/stdlib/buf.mo b/stdlib/buf.mo index 1081a104446..d1fe831cfa6 100644 --- a/stdlib/buf.mo +++ b/stdlib/buf.mo @@ -38,9 +38,8 @@ interface, the mutable array grows by doubling when this initial capacity is exhausted. */ public class Buf (initCapacity : Nat) { - // TODO: These should be private, but then `append` is not implementable as is. - public var count : Nat = 0; - public var elems : [var X] = [var]; // initially empty; allocated upon first `add` + var count : Nat = 0; + var elems : [var X] = [var]; // initially empty; allocated upon first `add` public func add(elem : X) { if (count == elems.len()) { @@ -60,18 +59,13 @@ public class Buf (initCapacity : Nat) { }; public func append(b:Buf) { - if (count + b.count >= b.len()) { - let size = 2 * count * b.count; - let elems2 = Array_init(size, elems[0]); - for (i in elems.keys()) { - elems2[i] := elems[i]; + let i = b.iter(); + loop { + switch (i.next()) { + case null return; + case (?x) add(x); }; - elems := elems; - }; - for (i in b.elems.keys()) { - elems[count + i] := b.elems[i]; }; - count += b.count; }; public func len() : Nat = diff --git a/stdlib/bufTest.mo b/stdlib/bufTest.mo index 04699a3be93..d87bc3031bd 100644 --- a/stdlib/bufTest.mo +++ b/stdlib/bufTest.mo @@ -1,10 +1,20 @@ import B "buf.mo"; +// test repeated growing let a = B.Buf(3); for (i in range(0, 123)) { a.add(i); }; for (i in range(0, 123)) { assert (a.get(i) == i); -} +}; + + +// test repeated appending +let b = B.Buf(3); +for (i in range(0, 123)) { + b.append(a); +}; +debugPrint(debug_show(a.toArray())); +debugPrint(debug_show(b.toArray())); From 6e378a325050b1b65c4ef654f8eb7f715290c8fc Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Fri, 22 Nov 2019 12:19:34 -0700 Subject: [PATCH 0698/1176] remove an iterator --- stdlib/buf.mo | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/stdlib/buf.mo b/stdlib/buf.mo index d1fe831cfa6..910a56a99a3 100644 --- a/stdlib/buf.mo +++ b/stdlib/buf.mo @@ -76,7 +76,9 @@ public class Buf (initCapacity : Nat) { public func clone() : Buf { let c = Buf(initCapacity); - for (elem in iter()) { c.add(elem) }; + for (i in elems.keys()) { + c.add(elems[i]) + }; c }; From 65aadde92eba781ff8ab0770c44f99a32eec88cb Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Fri, 22 Nov 2019 19:35:14 +0000 Subject: [PATCH 0699/1176] fix for issue 875 (#908) * fix for issue 875 * add test * fix regression * Update issue-875.mo --- src/mo_frontend/typing.ml | 2 +- test/fail/issue-875.mo | 1 + test/fail/ok/issue-875.tc.ok | 1 + test/fail/ok/issue-875.tc.ret.ok | 1 + 4 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 test/fail/issue-875.mo create mode 100644 test/fail/ok/issue-875.tc.ok create mode 100644 test/fail/ok/issue-875.tc.ret.ok diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index aef7f27b567..f9fb360c6f9 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -1502,7 +1502,7 @@ and infer_block_decs env decs : Scope.t = let scope = gather_block_decs env decs in let env' = adjoin {env with pre = true} scope in let scope_ce = infer_block_typdecs env' decs in - let env'' = adjoin env scope_ce in + let env'' = adjoin {env' with pre = env.pre} scope_ce in let _scope_ce = infer_block_typdecs env'' decs in (* TBR: assertion does not work for types with binders, due to stamping *) (* assert (scope_ce = _scope_ce); *) diff --git a/test/fail/issue-875.mo b/test/fail/issue-875.mo new file mode 100644 index 00000000000..1924356a916 --- /dev/null +++ b/test/fail/issue-875.mo @@ -0,0 +1 @@ +let t = async t; diff --git a/test/fail/ok/issue-875.tc.ok b/test/fail/ok/issue-875.tc.ok new file mode 100644 index 00000000000..2dcd368ff69 --- /dev/null +++ b/test/fail/ok/issue-875.tc.ok @@ -0,0 +1 @@ +issue-875.mo:1.15-1.16: type error, cannot infer type of forward variable t diff --git a/test/fail/ok/issue-875.tc.ret.ok b/test/fail/ok/issue-875.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/issue-875.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 From 8669c4dddcc9db18f2bd1d1ffc4f7e2a821027fd Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Sun, 24 Nov 2019 15:51:36 +0100 Subject: [PATCH 0700/1176] run.sh -a: Delete ok files later (#919) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit so that during a run of `make accept`, `git status` doesn't always show some files as deleted. (It’s not completely atomic, just more ergonomical). --- test/run.sh | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test/run.sh b/test/run.sh index ae0fa8b505e..cd4c022e043 100755 --- a/test/run.sh +++ b/test/run.sh @@ -159,10 +159,6 @@ do [ -d $ok ] || mkdir $ok rm -f $out/$base.* - if [ $ACCEPT = yes ] - then - rm -f $ok/$base.* - fi # First run all the steps, and remember what to diff diff_files= @@ -322,6 +318,8 @@ do if [ $ACCEPT = yes ] then + rm -f $ok/$base.* + for outfile in $diff_files do if [ -s $out/$outfile ] From 8d9e71012a80e250a65482619685b1942cd19510 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 25 Nov 2019 10:20:53 +0100 Subject: [PATCH 0701/1176] Move some tests out of run-dfinity to run-stub (#899) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move some tests out of run-dfinity to run-stub so that we reduce the dependency on `dvm`. This moves tests that don’t use `async` or local shared functions, or can easily be adjusted to do so. Many more tests will be movable once we have `async {…}` there, and @crusso is on it in (#891) --- test/run-dfinity/local-throw.mo | 104 +++++++++--------- test/run-dfinity/shared-object.mo | 15 --- test/run-dfinity/simple-throw.mo | 35 +++--- test/{run-dfinity => run-stub}/AST-64.mo | 0 test/{run-dfinity => run-stub}/GIT-843.mo | 0 test/{run-dfinity => run-stub}/async-calls.mo | 0 test/{run-dfinity => run-stub}/control.mo | 2 +- test/run-stub/counter.mo | 2 +- .../counter.mo => run-stub/counter2.mo} | 0 test/run-stub/create-then-trap.mo | 12 ++ test/run-stub/data-params.mo | 8 +- test/run-stub/divide-by-zero.mo | 1 + test/{run-dfinity => run-stub}/empty-actor.mo | 0 .../general-type-components.mo | 0 test/run-stub/hello-world-async.mo | 2 +- .../hello-world-await.mo | 4 +- test/run-stub/ic-calls.mo | 12 +- .../indirect-counter.mo | 0 test/run-stub/ok/AST-64.ic-stub-run.ok | 4 + test/run-stub/ok/GIT-843.ic-stub-run.ok | 5 + test/run-stub/ok/GIT-843.run-ir.ok | 1 + test/run-stub/ok/GIT-843.run-low.ok | 1 + test/run-stub/ok/GIT-843.run.ok | 1 + test/run-stub/ok/async-calls.ic-stub-run.ok | 4 + test/run-stub/ok/control.ic-stub-run.ok | 4 + test/run-stub/ok/counter2.ic-stub-run.ok | 18 +++ test/run-stub/ok/counter2.run-ir.ok | 14 +++ test/run-stub/ok/counter2.run-low.ok | 14 +++ test/run-stub/ok/counter2.run.ok | 14 +++ .../ok/create-then-trap.ic-stub-run.ok | 5 + test/run-stub/ok/create-then-trap.run-ir.ok | 2 + test/run-stub/ok/create-then-trap.run-low.ok | 2 + test/run-stub/ok/create-then-trap.run.ok | 2 + test/run-stub/ok/data-params.ic-stub-run.ok | 4 +- test/run-stub/ok/data-params.run-ir.ok | 41 +++++++ test/run-stub/ok/data-params.run-low.ok | 41 +++++++ test/run-stub/ok/data-params.run.ok | 41 +++++++ .../run-stub/ok/divide-by-zero.ic-stub-run.ok | 4 + .../ok/divide-by-zero.ic-stub-run.ret.ok | 1 + test/run-stub/ok/divide-by-zero.run-ir.ok | 1 + test/run-stub/ok/divide-by-zero.run-low.ok | 1 + test/run-stub/ok/divide-by-zero.run.ok | 1 + test/run-stub/ok/divide-by-zero.run.ret.ok | 1 + test/run-stub/ok/empty-actor.ic-stub-run.ok | 4 + .../ok/general-type-components.ic-stub-run.ok | 4 + .../ok/hello-world-async.ic-stub-run.ok | 4 +- test/run-stub/ok/hello-world-async.run-ir.ok | 2 + test/run-stub/ok/hello-world-async.run-low.ok | 2 + test/run-stub/ok/hello-world-async.run.ok | 2 + .../ok/hello-world-await.ic-stub-run.ok | 5 + test/run-stub/ok/hello-world-await.run-ir.ok | 1 + test/run-stub/ok/hello-world-await.run-low.ok | 1 + test/run-stub/ok/hello-world-await.run.ok | 1 + test/run-stub/ok/ic-calls.ic-stub-run.ok | 4 +- test/run-stub/ok/ic-calls.run-ir.ok | 4 + test/run-stub/ok/ic-calls.run-low.ok | 4 + test/run-stub/ok/ic-calls.run.ok | 4 + .../ok/indirect-counter.ic-stub-run.ok | 8 ++ test/run-stub/ok/indirect-counter.run-ir.ok | 4 + test/run-stub/ok/indirect-counter.run-low.ok | 4 + test/run-stub/ok/indirect-counter.run.ok | 4 + test/run-stub/ok/self-calls.ic-stub-run.ok | 4 +- test/run-stub/ok/self-calls.run-ir.ok | 7 ++ test/run-stub/ok/self-calls.run-low.ok | 7 ++ test/run-stub/ok/self-calls.run.ok | 7 ++ test/run-stub/ok/shared-object.ic-stub-run.ok | 4 + test/run-stub/ok/transpose.ic-stub-run.ok | 3 +- test/run-stub/ok/transpose.run-ir.ok | 1 + test/run-stub/ok/transpose.run-low.ok | 1 + test/run-stub/ok/transpose.run.ok | 1 + test/run-stub/self-calls.mo | 14 +-- test/run-stub/shared-object.mo | 20 ++++ test/run-stub/transpose.mo | 12 +- 73 files changed, 441 insertions(+), 126 deletions(-) delete mode 100644 test/run-dfinity/shared-object.mo rename test/{run-dfinity => run-stub}/AST-64.mo (100%) rename test/{run-dfinity => run-stub}/GIT-843.mo (100%) rename test/{run-dfinity => run-stub}/async-calls.mo (100%) rename test/{run-dfinity => run-stub}/control.mo (97%) rename test/{run-dfinity/counter.mo => run-stub/counter2.mo} (100%) create mode 100644 test/run-stub/create-then-trap.mo create mode 100644 test/run-stub/divide-by-zero.mo rename test/{run-dfinity => run-stub}/empty-actor.mo (100%) rename test/{run-dfinity => run-stub}/general-type-components.mo (100%) rename test/{run-dfinity => run-stub}/hello-world-await.mo (79%) rename test/{run-dfinity => run-stub}/indirect-counter.mo (100%) create mode 100644 test/run-stub/ok/AST-64.ic-stub-run.ok create mode 100644 test/run-stub/ok/GIT-843.ic-stub-run.ok create mode 100644 test/run-stub/ok/GIT-843.run-ir.ok create mode 100644 test/run-stub/ok/GIT-843.run-low.ok create mode 100644 test/run-stub/ok/GIT-843.run.ok create mode 100644 test/run-stub/ok/async-calls.ic-stub-run.ok create mode 100644 test/run-stub/ok/control.ic-stub-run.ok create mode 100644 test/run-stub/ok/counter2.ic-stub-run.ok create mode 100644 test/run-stub/ok/counter2.run-ir.ok create mode 100644 test/run-stub/ok/counter2.run-low.ok create mode 100644 test/run-stub/ok/counter2.run.ok create mode 100644 test/run-stub/ok/create-then-trap.ic-stub-run.ok create mode 100644 test/run-stub/ok/create-then-trap.run-ir.ok create mode 100644 test/run-stub/ok/create-then-trap.run-low.ok create mode 100644 test/run-stub/ok/create-then-trap.run.ok create mode 100644 test/run-stub/ok/data-params.run-ir.ok create mode 100644 test/run-stub/ok/data-params.run-low.ok create mode 100644 test/run-stub/ok/data-params.run.ok create mode 100644 test/run-stub/ok/divide-by-zero.ic-stub-run.ok create mode 100644 test/run-stub/ok/divide-by-zero.ic-stub-run.ret.ok create mode 100644 test/run-stub/ok/divide-by-zero.run-ir.ok create mode 100644 test/run-stub/ok/divide-by-zero.run-low.ok create mode 100644 test/run-stub/ok/divide-by-zero.run.ok create mode 100644 test/run-stub/ok/divide-by-zero.run.ret.ok create mode 100644 test/run-stub/ok/empty-actor.ic-stub-run.ok create mode 100644 test/run-stub/ok/general-type-components.ic-stub-run.ok create mode 100644 test/run-stub/ok/hello-world-async.run-ir.ok create mode 100644 test/run-stub/ok/hello-world-async.run-low.ok create mode 100644 test/run-stub/ok/hello-world-async.run.ok create mode 100644 test/run-stub/ok/hello-world-await.ic-stub-run.ok create mode 100644 test/run-stub/ok/hello-world-await.run-ir.ok create mode 100644 test/run-stub/ok/hello-world-await.run-low.ok create mode 100644 test/run-stub/ok/hello-world-await.run.ok create mode 100644 test/run-stub/ok/ic-calls.run-ir.ok create mode 100644 test/run-stub/ok/ic-calls.run-low.ok create mode 100644 test/run-stub/ok/ic-calls.run.ok create mode 100644 test/run-stub/ok/indirect-counter.ic-stub-run.ok create mode 100644 test/run-stub/ok/indirect-counter.run-ir.ok create mode 100644 test/run-stub/ok/indirect-counter.run-low.ok create mode 100644 test/run-stub/ok/indirect-counter.run.ok create mode 100644 test/run-stub/ok/self-calls.run-ir.ok create mode 100644 test/run-stub/ok/self-calls.run-low.ok create mode 100644 test/run-stub/ok/self-calls.run.ok create mode 100644 test/run-stub/ok/shared-object.ic-stub-run.ok create mode 100644 test/run-stub/ok/transpose.run-ir.ok create mode 100644 test/run-stub/ok/transpose.run-low.ok create mode 100644 test/run-stub/ok/transpose.run.ok create mode 100644 test/run-stub/shared-object.mo diff --git a/test/run-dfinity/local-throw.mo b/test/run-dfinity/local-throw.mo index 742a038e177..5f6b75566f9 100644 --- a/test/run-dfinity/local-throw.mo +++ b/test/run-dfinity/local-throw.mo @@ -1,67 +1,67 @@ // This file only exercises local throws that don't cross function boundaries. // In principle, it should run on all targets. -shared func t2() : async () { - try { - throw error("t2"); - assert(false); - } catch e { - switch (errorCode(e),errorMessage(e)) { - case (#error, "t2") { }; - case (#system, _ ) { assert false;}; - case (#error, _) { assert false;}; +actor a { + shared func t2() : async () { + try { + throw error("t2"); + assert(false); + } catch e { + switch (errorCode(e),errorMessage(e)) { + case (#error, "t2") { }; + case (#system, _ ) { assert false;}; + case (#error, _) { assert false;}; + } } - } -}; + }; -shared func t3() : async () { - try { + shared func t3() : async () { try { - throw error("t3"); - assert(false); - } catch e1 { - switch (errorCode(e1), errorMessage(e1)) { - case (#error, "t3") { - throw error("t31"); - }; - case (#system, _) { - assert false; - }; - case (#error, _) { - assert false; - }; + try { + throw error("t3"); + assert(false); + } catch e1 { + switch (errorCode(e1), errorMessage(e1)) { + case (#error, "t3") { + throw error("t31"); + }; + case (#system, _) { + assert false; + }; + case (#error, _) { + assert false; + }; + } } } - } - catch e2 { - switch (errorCode(e2),errorMessage(e2)) { - case (#error, "t31") { }; - case (#system, _) { - assert false; - }; - case (#error, _) { - assert true; - }; + catch e2 { + switch (errorCode(e2),errorMessage(e2)) { + case (#error, "t31") { }; + case (#system, _) { + assert false; + }; + case (#error, _) { + assert true; + }; + } } - } -}; + }; -async { + async { + try { + await t2(); + debugPrint ("t2 ok"); + } catch _ { + assert false; + }; - try { - await t2(); - debugPrint ("t2 ok"); - } catch _ { - assert false; - }; + try { + await t3(); + debugPrint ("t3 ok"); + } catch _ { + assert false; + }; - try { - await t3(); - debugPrint ("t3 ok"); - } catch _ { - assert false; }; - }; - diff --git a/test/run-dfinity/shared-object.mo b/test/run-dfinity/shared-object.mo deleted file mode 100644 index b93c6b9a217..00000000000 --- a/test/run-dfinity/shared-object.mo +++ /dev/null @@ -1,15 +0,0 @@ -type Shob = { a : Int; b : { c : ?Nat } }; - -let foo : Shob = { a = 17; b = { c = ?25 } }; - -// check whether we can pattern match shared objects - -shared func baz(sh : Shob) : async Int = async (switch sh { - case {a; b = {c = null}} a; - case {a; b = {c = ?c}} (a + c) -}); - -async { - let b = await (baz foo); - assert (b == 42); -}; diff --git a/test/run-dfinity/simple-throw.mo b/test/run-dfinity/simple-throw.mo index b600d63e075..6b1cd576dab 100644 --- a/test/run-dfinity/simple-throw.mo +++ b/test/run-dfinity/simple-throw.mo @@ -1,21 +1,22 @@ // This file only exercises local throws that don't cross function boundaries. // In principle, it should run on all targets. -async { - debugPrint "1"; - try { - debugPrint "2"; - throw error("t2"); - assert(false); - } catch e { - switch (errorCode(e), errorMessage(e)) { - case (#error, "t1") { assert false; }; - case (#system, _ ) { assert false; }; - case (#error, _) { debugPrint "3"; }; - } - }; - debugPrint "4"; - debugPrint "done"; +actor a { + public func go() = ignore async { + debugPrint "1"; + try { + debugPrint "2"; + throw error("t2"); + assert(false); + } catch e { + switch (errorCode(e), errorMessage(e)) { + case (#error, "t1") { assert false; }; + case (#system, _ ) { assert false; }; + case (#error, _) { debugPrint "3"; }; + } + }; + debugPrint "4"; + debugPrint "done"; + }; + go(); }; - - diff --git a/test/run-dfinity/AST-64.mo b/test/run-stub/AST-64.mo similarity index 100% rename from test/run-dfinity/AST-64.mo rename to test/run-stub/AST-64.mo diff --git a/test/run-dfinity/GIT-843.mo b/test/run-stub/GIT-843.mo similarity index 100% rename from test/run-dfinity/GIT-843.mo rename to test/run-stub/GIT-843.mo diff --git a/test/run-dfinity/async-calls.mo b/test/run-stub/async-calls.mo similarity index 100% rename from test/run-dfinity/async-calls.mo rename to test/run-stub/async-calls.mo diff --git a/test/run-dfinity/control.mo b/test/run-stub/control.mo similarity index 97% rename from test/run-dfinity/control.mo rename to test/run-stub/control.mo index 887e1289431..a50123acf80 100644 --- a/test/run-dfinity/control.mo +++ b/test/run-stub/control.mo @@ -1,4 +1,4 @@ -actor class Control() { +actor control { func condition() : Bool = false; diff --git a/test/run-stub/counter.mo b/test/run-stub/counter.mo index 90410b64710..3796efe4bd2 100644 --- a/test/run-stub/counter.mo +++ b/test/run-stub/counter.mo @@ -1,4 +1,4 @@ -actor { +actor a { var c = 1; public func inc() { c += 1; diff --git a/test/run-dfinity/counter.mo b/test/run-stub/counter2.mo similarity index 100% rename from test/run-dfinity/counter.mo rename to test/run-stub/counter2.mo diff --git a/test/run-stub/create-then-trap.mo b/test/run-stub/create-then-trap.mo new file mode 100644 index 00000000000..6a23cd10b71 --- /dev/null +++ b/test/run-stub/create-then-trap.mo @@ -0,0 +1,12 @@ +actor a { + public func go() { + actor b { + public func bad() { + debugPrint ("b.bad() called (should not happen)"); + } + }; + b.bad(); + assert false; + } +}; +a.go(); diff --git a/test/run-stub/data-params.mo b/test/run-stub/data-params.mo index 0244de558c3..3f9011e314a 100644 --- a/test/run-stub/data-params.mo +++ b/test/run-stub/data-params.mo @@ -1,4 +1,4 @@ -let a = actor { +actor a { var c : Int = 0; public func inci(n : Int) : () { c += n; @@ -72,7 +72,7 @@ let a = actor { debugPrintInt(c); }; - public func go() : async () { + public func go() : () { a.incn(0); a.incn(1); a.incn(2); @@ -112,5 +112,5 @@ let a = actor { a.inci(-42); a.incn(2**31 - 1); // highest compact }; -} -//CALL ingress go 0x4449444C0000 +}; +a.go(); diff --git a/test/run-stub/divide-by-zero.mo b/test/run-stub/divide-by-zero.mo new file mode 100644 index 00000000000..88dc1085e67 --- /dev/null +++ b/test/run-stub/divide-by-zero.mo @@ -0,0 +1 @@ +let _ = 0/0; diff --git a/test/run-dfinity/empty-actor.mo b/test/run-stub/empty-actor.mo similarity index 100% rename from test/run-dfinity/empty-actor.mo rename to test/run-stub/empty-actor.mo diff --git a/test/run-dfinity/general-type-components.mo b/test/run-stub/general-type-components.mo similarity index 100% rename from test/run-dfinity/general-type-components.mo rename to test/run-stub/general-type-components.mo diff --git a/test/run-stub/hello-world-async.mo b/test/run-stub/hello-world-async.mo index a50e970cd9b..86dcb14837d 100644 --- a/test/run-stub/hello-world-async.mo +++ b/test/run-stub/hello-world-async.mo @@ -8,5 +8,5 @@ let a = actor { }; }; -//CALL ingress go 0x4449444C0000 +a.go() diff --git a/test/run-dfinity/hello-world-await.mo b/test/run-stub/hello-world-await.mo similarity index 79% rename from test/run-dfinity/hello-world-await.mo rename to test/run-stub/hello-world-await.mo index 1d3eb8d9261..4ea6fa264bf 100644 --- a/test/run-dfinity/hello-world-await.mo +++ b/test/run-stub/hello-world-await.mo @@ -5,9 +5,9 @@ let a = actor { public func world() : async Text { "World!" }; - public func go() : async () { + public func go() = ignore async { debugPrint((await hello()) # (await world())); }; }; -let _ = a.go() +a.go() diff --git a/test/run-stub/ic-calls.mo b/test/run-stub/ic-calls.mo index 80333ac8c9f..9f15511141e 100644 --- a/test/run-stub/ic-calls.mo +++ b/test/run-stub/ic-calls.mo @@ -1,13 +1,13 @@ actor X { - public func A() : async () { + public func A() : () { debugPrint("A"); }; public func B(x : Int) : async Int { debugPrint("B"); - x + x }; public func C(x : Int, y: Bool) : async (Int,Bool) { @@ -15,13 +15,13 @@ actor X { (x,y); }; - public func test() : async () { - let () = await A(); + public func test() = ignore async { + A(); let 1 = await B(1); let (1,true) = await C(1,true); debugPrint("test"); }; -} -//CALL ingress test 0x4449444C0000 +}; +X.test(); diff --git a/test/run-dfinity/indirect-counter.mo b/test/run-stub/indirect-counter.mo similarity index 100% rename from test/run-dfinity/indirect-counter.mo rename to test/run-stub/indirect-counter.mo diff --git a/test/run-stub/ok/AST-64.ic-stub-run.ok b/test/run-stub/ok/AST-64.ic-stub-run.ok new file mode 100644 index 00000000000..54225bc8555 --- /dev/null +++ b/test/run-stub/ok/AST-64.ic-stub-run.ok @@ -0,0 +1,4 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed diff --git a/test/run-stub/ok/GIT-843.ic-stub-run.ok b/test/run-stub/ok/GIT-843.ic-stub-run.ok new file mode 100644 index 00000000000..edc65f1e690 --- /dev/null +++ b/test/run-stub/ok/GIT-843.ic-stub-run.ok @@ -0,0 +1,5 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +ok +← completed diff --git a/test/run-stub/ok/GIT-843.run-ir.ok b/test/run-stub/ok/GIT-843.run-ir.ok new file mode 100644 index 00000000000..9766475a418 --- /dev/null +++ b/test/run-stub/ok/GIT-843.run-ir.ok @@ -0,0 +1 @@ +ok diff --git a/test/run-stub/ok/GIT-843.run-low.ok b/test/run-stub/ok/GIT-843.run-low.ok new file mode 100644 index 00000000000..9766475a418 --- /dev/null +++ b/test/run-stub/ok/GIT-843.run-low.ok @@ -0,0 +1 @@ +ok diff --git a/test/run-stub/ok/GIT-843.run.ok b/test/run-stub/ok/GIT-843.run.ok new file mode 100644 index 00000000000..9766475a418 --- /dev/null +++ b/test/run-stub/ok/GIT-843.run.ok @@ -0,0 +1 @@ +ok diff --git a/test/run-stub/ok/async-calls.ic-stub-run.ok b/test/run-stub/ok/async-calls.ic-stub-run.ok new file mode 100644 index 00000000000..54225bc8555 --- /dev/null +++ b/test/run-stub/ok/async-calls.ic-stub-run.ok @@ -0,0 +1,4 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed diff --git a/test/run-stub/ok/control.ic-stub-run.ok b/test/run-stub/ok/control.ic-stub-run.ok new file mode 100644 index 00000000000..54225bc8555 --- /dev/null +++ b/test/run-stub/ok/control.ic-stub-run.ok @@ -0,0 +1,4 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed diff --git a/test/run-stub/ok/counter2.ic-stub-run.ok b/test/run-stub/ok/counter2.ic-stub-run.ok new file mode 100644 index 00000000000..73250a9a72f --- /dev/null +++ b/test/run-stub/ok/counter2.ic-stub-run.ok @@ -0,0 +1,18 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +2 +3 +4 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +← completed diff --git a/test/run-stub/ok/counter2.run-ir.ok b/test/run-stub/ok/counter2.run-ir.ok new file mode 100644 index 00000000000..e9717fd149f --- /dev/null +++ b/test/run-stub/ok/counter2.run-ir.ok @@ -0,0 +1,14 @@ +2 +3 +4 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 diff --git a/test/run-stub/ok/counter2.run-low.ok b/test/run-stub/ok/counter2.run-low.ok new file mode 100644 index 00000000000..e9717fd149f --- /dev/null +++ b/test/run-stub/ok/counter2.run-low.ok @@ -0,0 +1,14 @@ +2 +3 +4 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 diff --git a/test/run-stub/ok/counter2.run.ok b/test/run-stub/ok/counter2.run.ok new file mode 100644 index 00000000000..e9717fd149f --- /dev/null +++ b/test/run-stub/ok/counter2.run.ok @@ -0,0 +1,14 @@ +2 +3 +4 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 diff --git a/test/run-stub/ok/create-then-trap.ic-stub-run.ok b/test/run-stub/ok/create-then-trap.ic-stub-run.ok new file mode 100644 index 00000000000..06e8c44dffb --- /dev/null +++ b/test/run-stub/ok/create-then-trap.ic-stub-run.ok @@ -0,0 +1,5 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +Trap: EvalTrapError :0.1 "canister trapped explicitly: assertion failed at create-then-trap.mo:9.5-9.17" +← completed diff --git a/test/run-stub/ok/create-then-trap.run-ir.ok b/test/run-stub/ok/create-then-trap.run-ir.ok new file mode 100644 index 00000000000..bbda0311c17 --- /dev/null +++ b/test/run-stub/ok/create-then-trap.run-ir.ok @@ -0,0 +1,2 @@ +create-then-trap.mo:9.5-9.17: execution error, assertion failure +b.bad() called (should not happen) diff --git a/test/run-stub/ok/create-then-trap.run-low.ok b/test/run-stub/ok/create-then-trap.run-low.ok new file mode 100644 index 00000000000..bbda0311c17 --- /dev/null +++ b/test/run-stub/ok/create-then-trap.run-low.ok @@ -0,0 +1,2 @@ +create-then-trap.mo:9.5-9.17: execution error, assertion failure +b.bad() called (should not happen) diff --git a/test/run-stub/ok/create-then-trap.run.ok b/test/run-stub/ok/create-then-trap.run.ok new file mode 100644 index 00000000000..bbda0311c17 --- /dev/null +++ b/test/run-stub/ok/create-then-trap.run.ok @@ -0,0 +1,2 @@ +create-then-trap.mo:9.5-9.17: execution error, assertion failure +b.bad() called (should not happen) diff --git a/test/run-stub/ok/data-params.ic-stub-run.ok b/test/run-stub/ok/data-params.ic-stub-run.ok index f91829e5655..7b5b4b7e2d5 100644 --- a/test/run-stub/ok/data-params.ic-stub-run.ok +++ b/test/run-stub/ok/data-params.ic-stub-run.ok @@ -1,8 +1,6 @@ → create ← completed: canister-id = 0x0000000000000400 → install -← completed -→ update go(0x4449444c0000) 0 +1 +3 @@ -44,4 +42,4 @@ Foo2: +2_148_489_911 +2_148_489_869 +4_295_973_516 -← completed: 0x4449444c0000 +← completed diff --git a/test/run-stub/ok/data-params.run-ir.ok b/test/run-stub/ok/data-params.run-ir.ok new file mode 100644 index 00000000000..2fd43916bee --- /dev/null +++ b/test/run-stub/ok/data-params.run-ir.ok @@ -0,0 +1,41 @@ +0 ++1 ++3 ++6 ++10 ++1_010 ++1_021 ++6_021 ++6_045 ++6_091 ++1_006_091 ++1_006_105 ++1_006_136 ++1_006_171 ++1_006_191 ++1_006_211 ++1_006_211 +Foo1: ++1_006_211 +μεταγράψτε: ++1_006_211 +Foo2: ++1_006_211 ++10_000_001_006_211 ++20_000_001_006_211 ++1_006_211 ++1_006_221 ++1_006_211 ++1_006_221 ++1_006_231 ++1_006_221 ++1_267_650_600_228_229_401_496_704_211_597 ++2_535_301_200_456_458_802_993_407_416_973 ++1_006_221 ++1_074_748_045 ++2_148_489_868 ++2_148_489_868 ++2_148_489_869 ++2_148_489_911 ++2_148_489_869 ++4_295_973_516 diff --git a/test/run-stub/ok/data-params.run-low.ok b/test/run-stub/ok/data-params.run-low.ok new file mode 100644 index 00000000000..2fd43916bee --- /dev/null +++ b/test/run-stub/ok/data-params.run-low.ok @@ -0,0 +1,41 @@ +0 ++1 ++3 ++6 ++10 ++1_010 ++1_021 ++6_021 ++6_045 ++6_091 ++1_006_091 ++1_006_105 ++1_006_136 ++1_006_171 ++1_006_191 ++1_006_211 ++1_006_211 +Foo1: ++1_006_211 +μεταγράψτε: ++1_006_211 +Foo2: ++1_006_211 ++10_000_001_006_211 ++20_000_001_006_211 ++1_006_211 ++1_006_221 ++1_006_211 ++1_006_221 ++1_006_231 ++1_006_221 ++1_267_650_600_228_229_401_496_704_211_597 ++2_535_301_200_456_458_802_993_407_416_973 ++1_006_221 ++1_074_748_045 ++2_148_489_868 ++2_148_489_868 ++2_148_489_869 ++2_148_489_911 ++2_148_489_869 ++4_295_973_516 diff --git a/test/run-stub/ok/data-params.run.ok b/test/run-stub/ok/data-params.run.ok new file mode 100644 index 00000000000..2fd43916bee --- /dev/null +++ b/test/run-stub/ok/data-params.run.ok @@ -0,0 +1,41 @@ +0 ++1 ++3 ++6 ++10 ++1_010 ++1_021 ++6_021 ++6_045 ++6_091 ++1_006_091 ++1_006_105 ++1_006_136 ++1_006_171 ++1_006_191 ++1_006_211 ++1_006_211 +Foo1: ++1_006_211 +μεταγράψτε: ++1_006_211 +Foo2: ++1_006_211 ++10_000_001_006_211 ++20_000_001_006_211 ++1_006_211 ++1_006_221 ++1_006_211 ++1_006_221 ++1_006_231 ++1_006_221 ++1_267_650_600_228_229_401_496_704_211_597 ++2_535_301_200_456_458_802_993_407_416_973 ++1_006_221 ++1_074_748_045 ++2_148_489_868 ++2_148_489_868 ++2_148_489_869 ++2_148_489_911 ++2_148_489_869 ++4_295_973_516 diff --git a/test/run-stub/ok/divide-by-zero.ic-stub-run.ok b/test/run-stub/ok/divide-by-zero.ic-stub-run.ok new file mode 100644 index 00000000000..59ec67eb613 --- /dev/null +++ b/test/run-stub/ok/divide-by-zero.ic-stub-run.ok @@ -0,0 +1,4 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +ic-stub-run: divide by zero diff --git a/test/run-stub/ok/divide-by-zero.ic-stub-run.ret.ok b/test/run-stub/ok/divide-by-zero.ic-stub-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-stub/ok/divide-by-zero.ic-stub-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-stub/ok/divide-by-zero.run-ir.ok b/test/run-stub/ok/divide-by-zero.run-ir.ok new file mode 100644 index 00000000000..fffe6018d94 --- /dev/null +++ b/test/run-stub/ok/divide-by-zero.run-ir.ok @@ -0,0 +1 @@ +divide-by-zero.mo:1.9-1.12: execution error, arithmetic overflow diff --git a/test/run-stub/ok/divide-by-zero.run-low.ok b/test/run-stub/ok/divide-by-zero.run-low.ok new file mode 100644 index 00000000000..fffe6018d94 --- /dev/null +++ b/test/run-stub/ok/divide-by-zero.run-low.ok @@ -0,0 +1 @@ +divide-by-zero.mo:1.9-1.12: execution error, arithmetic overflow diff --git a/test/run-stub/ok/divide-by-zero.run.ok b/test/run-stub/ok/divide-by-zero.run.ok new file mode 100644 index 00000000000..fffe6018d94 --- /dev/null +++ b/test/run-stub/ok/divide-by-zero.run.ok @@ -0,0 +1 @@ +divide-by-zero.mo:1.9-1.12: execution error, arithmetic overflow diff --git a/test/run-stub/ok/divide-by-zero.run.ret.ok b/test/run-stub/ok/divide-by-zero.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-stub/ok/divide-by-zero.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-stub/ok/empty-actor.ic-stub-run.ok b/test/run-stub/ok/empty-actor.ic-stub-run.ok new file mode 100644 index 00000000000..54225bc8555 --- /dev/null +++ b/test/run-stub/ok/empty-actor.ic-stub-run.ok @@ -0,0 +1,4 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed diff --git a/test/run-stub/ok/general-type-components.ic-stub-run.ok b/test/run-stub/ok/general-type-components.ic-stub-run.ok new file mode 100644 index 00000000000..54225bc8555 --- /dev/null +++ b/test/run-stub/ok/general-type-components.ic-stub-run.ok @@ -0,0 +1,4 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed diff --git a/test/run-stub/ok/hello-world-async.ic-stub-run.ok b/test/run-stub/ok/hello-world-async.ic-stub-run.ok index ddbeb950d79..952ef550629 100644 --- a/test/run-stub/ok/hello-world-async.ic-stub-run.ok +++ b/test/run-stub/ok/hello-world-async.ic-stub-run.ok @@ -1,8 +1,6 @@ → create ← completed: canister-id = 0x0000000000000400 → install -← completed -→ update go(0x4449444c0000) Hello World! -← rejected (RC_CANISTER_ERROR): canister did not respond +← completed diff --git a/test/run-stub/ok/hello-world-async.run-ir.ok b/test/run-stub/ok/hello-world-async.run-ir.ok new file mode 100644 index 00000000000..35df24c2f80 --- /dev/null +++ b/test/run-stub/ok/hello-world-async.run-ir.ok @@ -0,0 +1,2 @@ +Hello +World! diff --git a/test/run-stub/ok/hello-world-async.run-low.ok b/test/run-stub/ok/hello-world-async.run-low.ok new file mode 100644 index 00000000000..35df24c2f80 --- /dev/null +++ b/test/run-stub/ok/hello-world-async.run-low.ok @@ -0,0 +1,2 @@ +Hello +World! diff --git a/test/run-stub/ok/hello-world-async.run.ok b/test/run-stub/ok/hello-world-async.run.ok new file mode 100644 index 00000000000..35df24c2f80 --- /dev/null +++ b/test/run-stub/ok/hello-world-async.run.ok @@ -0,0 +1,2 @@ +Hello +World! diff --git a/test/run-stub/ok/hello-world-await.ic-stub-run.ok b/test/run-stub/ok/hello-world-await.ic-stub-run.ok new file mode 100644 index 00000000000..7f2eae552c1 --- /dev/null +++ b/test/run-stub/ok/hello-world-await.ic-stub-run.ok @@ -0,0 +1,5 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +Hello World! +← completed diff --git a/test/run-stub/ok/hello-world-await.run-ir.ok b/test/run-stub/ok/hello-world-await.run-ir.ok new file mode 100644 index 00000000000..980a0d5f19a --- /dev/null +++ b/test/run-stub/ok/hello-world-await.run-ir.ok @@ -0,0 +1 @@ +Hello World! diff --git a/test/run-stub/ok/hello-world-await.run-low.ok b/test/run-stub/ok/hello-world-await.run-low.ok new file mode 100644 index 00000000000..980a0d5f19a --- /dev/null +++ b/test/run-stub/ok/hello-world-await.run-low.ok @@ -0,0 +1 @@ +Hello World! diff --git a/test/run-stub/ok/hello-world-await.run.ok b/test/run-stub/ok/hello-world-await.run.ok new file mode 100644 index 00000000000..980a0d5f19a --- /dev/null +++ b/test/run-stub/ok/hello-world-await.run.ok @@ -0,0 +1 @@ +Hello World! diff --git a/test/run-stub/ok/ic-calls.ic-stub-run.ok b/test/run-stub/ok/ic-calls.ic-stub-run.ok index baf78b4a60a..c5d70ec6f0b 100644 --- a/test/run-stub/ok/ic-calls.ic-stub-run.ok +++ b/test/run-stub/ok/ic-calls.ic-stub-run.ok @@ -1,10 +1,8 @@ → create ← completed: canister-id = 0x0000000000000400 → install -← completed -→ update test(0x4449444c0000) A B C test -← completed: 0x4449444c0000 +← completed diff --git a/test/run-stub/ok/ic-calls.run-ir.ok b/test/run-stub/ok/ic-calls.run-ir.ok new file mode 100644 index 00000000000..d7c2f49f195 --- /dev/null +++ b/test/run-stub/ok/ic-calls.run-ir.ok @@ -0,0 +1,4 @@ +A +B +C +test diff --git a/test/run-stub/ok/ic-calls.run-low.ok b/test/run-stub/ok/ic-calls.run-low.ok new file mode 100644 index 00000000000..d7c2f49f195 --- /dev/null +++ b/test/run-stub/ok/ic-calls.run-low.ok @@ -0,0 +1,4 @@ +A +B +C +test diff --git a/test/run-stub/ok/ic-calls.run.ok b/test/run-stub/ok/ic-calls.run.ok new file mode 100644 index 00000000000..d7c2f49f195 --- /dev/null +++ b/test/run-stub/ok/ic-calls.run.ok @@ -0,0 +1,4 @@ +A +B +C +test diff --git a/test/run-stub/ok/indirect-counter.ic-stub-run.ok b/test/run-stub/ok/indirect-counter.ic-stub-run.ok new file mode 100644 index 00000000000..d5913df8b46 --- /dev/null +++ b/test/run-stub/ok/indirect-counter.ic-stub-run.ok @@ -0,0 +1,8 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +2 +3 +4 +4 +← completed diff --git a/test/run-stub/ok/indirect-counter.run-ir.ok b/test/run-stub/ok/indirect-counter.run-ir.ok new file mode 100644 index 00000000000..95c45d6da51 --- /dev/null +++ b/test/run-stub/ok/indirect-counter.run-ir.ok @@ -0,0 +1,4 @@ +2 +3 +4 +4 diff --git a/test/run-stub/ok/indirect-counter.run-low.ok b/test/run-stub/ok/indirect-counter.run-low.ok new file mode 100644 index 00000000000..95c45d6da51 --- /dev/null +++ b/test/run-stub/ok/indirect-counter.run-low.ok @@ -0,0 +1,4 @@ +2 +3 +4 +4 diff --git a/test/run-stub/ok/indirect-counter.run.ok b/test/run-stub/ok/indirect-counter.run.ok new file mode 100644 index 00000000000..95c45d6da51 --- /dev/null +++ b/test/run-stub/ok/indirect-counter.run.ok @@ -0,0 +1,4 @@ +2 +3 +4 +4 diff --git a/test/run-stub/ok/self-calls.ic-stub-run.ok b/test/run-stub/ok/self-calls.ic-stub-run.ok index 11ec18b545d..607268f5415 100644 --- a/test/run-stub/ok/self-calls.ic-stub-run.ok +++ b/test/run-stub/ok/self-calls.ic-stub-run.ok @@ -1,8 +1,6 @@ → create ← completed: canister-id = 0x0000000000000400 → install -← completed -→ update test(0x4449444c0000) test1 A called test2 @@ -10,4 +8,4 @@ B called test3 C called test4 -← completed: 0x4449444c0000 +← completed diff --git a/test/run-stub/ok/self-calls.run-ir.ok b/test/run-stub/ok/self-calls.run-ir.ok new file mode 100644 index 00000000000..f46b40f7334 --- /dev/null +++ b/test/run-stub/ok/self-calls.run-ir.ok @@ -0,0 +1,7 @@ +test1 +A called +test2 +B called +test3 +C called +test4 diff --git a/test/run-stub/ok/self-calls.run-low.ok b/test/run-stub/ok/self-calls.run-low.ok new file mode 100644 index 00000000000..f46b40f7334 --- /dev/null +++ b/test/run-stub/ok/self-calls.run-low.ok @@ -0,0 +1,7 @@ +test1 +A called +test2 +B called +test3 +C called +test4 diff --git a/test/run-stub/ok/self-calls.run.ok b/test/run-stub/ok/self-calls.run.ok new file mode 100644 index 00000000000..f46b40f7334 --- /dev/null +++ b/test/run-stub/ok/self-calls.run.ok @@ -0,0 +1,7 @@ +test1 +A called +test2 +B called +test3 +C called +test4 diff --git a/test/run-stub/ok/shared-object.ic-stub-run.ok b/test/run-stub/ok/shared-object.ic-stub-run.ok new file mode 100644 index 00000000000..54225bc8555 --- /dev/null +++ b/test/run-stub/ok/shared-object.ic-stub-run.ok @@ -0,0 +1,4 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed diff --git a/test/run-stub/ok/transpose.ic-stub-run.ok b/test/run-stub/ok/transpose.ic-stub-run.ok index be9fb5d62c0..c19a2a856f5 100644 --- a/test/run-stub/ok/transpose.ic-stub-run.ok +++ b/test/run-stub/ok/transpose.ic-stub-run.ok @@ -1,6 +1,5 @@ → create ← completed: canister-id = 0x0000000000000400 → install +All good ← completed -→ update go(0x4449444c0000) -← completed: 0x4449444c0000 diff --git a/test/run-stub/ok/transpose.run-ir.ok b/test/run-stub/ok/transpose.run-ir.ok new file mode 100644 index 00000000000..d6109db9233 --- /dev/null +++ b/test/run-stub/ok/transpose.run-ir.ok @@ -0,0 +1 @@ +All good diff --git a/test/run-stub/ok/transpose.run-low.ok b/test/run-stub/ok/transpose.run-low.ok new file mode 100644 index 00000000000..d6109db9233 --- /dev/null +++ b/test/run-stub/ok/transpose.run-low.ok @@ -0,0 +1 @@ +All good diff --git a/test/run-stub/ok/transpose.run.ok b/test/run-stub/ok/transpose.run.ok new file mode 100644 index 00000000000..d6109db9233 --- /dev/null +++ b/test/run-stub/ok/transpose.run.ok @@ -0,0 +1 @@ +All good diff --git a/test/run-stub/self-calls.mo b/test/run-stub/self-calls.mo index 0d1716a5587..e64643b7ec6 100644 --- a/test/run-stub/self-calls.mo +++ b/test/run-stub/self-calls.mo @@ -1,4 +1,4 @@ -actor X { +actor a { public func A() : async () { debugPrint("A called"); }; @@ -14,17 +14,17 @@ actor X { (x,y); }; - public func test() : async () { + public func test() = ignore async { debugPrint("test1"); - let x = await X.A(); + let x = await a.A(); debugPrint("test2"); - let y = await X.B(1); + let y = await a.B(1); debugPrint("test3"); - let z = await X.C(2,true); + let z = await a.C(2,true); debugPrint("test4"); assert (y == 1); assert (z.0 == 2); assert (z.1); }; -} -//CALL ingress test 0x4449444C0000 +}; +a.test(); diff --git a/test/run-stub/shared-object.mo b/test/run-stub/shared-object.mo new file mode 100644 index 00000000000..32a02daf507 --- /dev/null +++ b/test/run-stub/shared-object.mo @@ -0,0 +1,20 @@ +actor a { + + type Shob = { a : Int; b : { c : ?Nat } }; + + let foo : Shob = { a = 17; b = { c = ?25 } }; + + // check whether we can pattern match shared objects + + public func baz(sh : Shob) : async Int = async (switch sh { + case {a; b = {c = null}} a; + case {a; b = {c = ?c}} (a + c) + }); + + public func go() = ignore async { + let b = await (baz foo); + assert (b == 42); + }; + + go(); +} diff --git a/test/run-stub/transpose.mo b/test/run-stub/transpose.mo index 2f4821bddd4..c0335d9a275 100644 --- a/test/run-stub/transpose.mo +++ b/test/run-stub/transpose.mo @@ -1,4 +1,4 @@ -actor foo { +actor a { public func transpose (data : [(Int,Text)]) : async {ints: [Int]; txts: [Text]} { return { ints = Array_tabulate(data.len(), func (i:Nat) : Int = (data[i].0)); @@ -6,13 +6,13 @@ actor foo { } }; - public func go() : async () { - let x = await foo.transpose([(1,"Hi"), (2, "Ho")]); + public func go() = ignore async { + let x = await a.transpose([(1,"Hi"), (2, "Ho")]); assert (x.ints[0] == 1); assert (x.ints[1] == 2); assert (x.txts[0] == "Hi"); assert (x.txts[1] == "Ho"); + debugPrint("All good"); } -} - -//CALL ingress go 0x4449444C0000 +}; +a.go(); From 9a5ca015acee2931718c4ed06e579f5a184c4310 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Mon, 25 Nov 2019 11:35:12 +0100 Subject: [PATCH 0702/1176] fix trapping behaviour of intToWord64 (#924) (it should wrap, of course) --- src/codegen/compile.ml | 2 +- test/random/Main.hs | 1 + test/run/ok/conversions.wasm-run.ok | 1 - test/run/ok/conversions.wasm-run.ret.ok | 1 - 4 files changed, 2 insertions(+), 3 deletions(-) delete mode 100644 test/run/ok/conversions.wasm-run.ok delete mode 100644 test/run/ok/conversions.wasm-run.ret.ok diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index a892caa5667..354b4b77d1b 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -6398,7 +6398,7 @@ and compile_exp (env : E.t) ae exp = | (Nat|Int), Word64 -> SR.UnboxedWord64, compile_exp_vanilla env ae e ^^ - BigNum.to_word64 env + BigNum.truncate_to_word64 env | Nat64, Word64 | Int64, Word64 diff --git a/test/random/Main.hs b/test/random/Main.hs index 1a679631c8c..803f457c498 100644 --- a/test/random/Main.hs +++ b/test/random/Main.hs @@ -896,6 +896,7 @@ unparseWord p a = "(word" <> bitWidth p <> "ToNat(" <> unparseAS a <> "))" -- TO -- TODOs: -- - wordToInt +-- - natToNat64/intToWord64 (and round-trips) -- - bitwise ops (btst?) -- - pattern matches (over numeric, bool, structured) -- - trapping flavour-preserving conversions Nat -> NatN diff --git a/test/run/ok/conversions.wasm-run.ok b/test/run/ok/conversions.wasm-run.ok deleted file mode 100644 index 9cc370c17be..00000000000 --- a/test/run/ok/conversions.wasm-run.ok +++ /dev/null @@ -1 +0,0 @@ -_out/conversions.wasm:0x___: runtime trap: unreachable executed diff --git a/test/run/ok/conversions.wasm-run.ret.ok b/test/run/ok/conversions.wasm-run.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run/ok/conversions.wasm-run.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 From 2f71cfc9590741425db752a029e0758f94284e79 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 25 Nov 2019 12:39:37 +0100 Subject: [PATCH 0703/1176] Nix: Properly take the `system` parameter into account (#918) * Nix: Properly take the `system` parameter into account this refined upon f25528bff11279182ba6bfd43f41ae8b8c8d7959 (#907) in order to fix #917. * Pass `system` from `ci.nix` and `shell.nix` * ci.nix: Remove referenced to deleted derivations these were removed in 6901c536deff066671aa96c6e765d96a7415bb40 * Do not even allow a `nixpkgs` parameter following what I see in `sdk/default.nix`. * Simplify further --- ci.nix | 8 ++------ default.nix | 15 +++++++++------ shell.nix | 4 ++-- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/ci.nix b/ci.nix index 5bce20d368d..62d5c13bbff 100644 --- a/ci.nix +++ b/ci.nix @@ -1,17 +1,13 @@ { src ? { rev = null; } }: let nixpkgs = (import ./nix/nixpkgs.nix).nixpkgs { }; - nixpkgs-linux = (import ./nix/nixpkgs.nix).nixpkgs { system = "x86_64-linux"; }; - nixpkgs-darwin = (import ./nix/nixpkgs.nix).nixpkgs { system = "x86_64-darwin"; }; inject-rev = drv: drv.overrideAttrs (attrs: { rev = src.rev; }); - linux = import ./default.nix { nixpkgs = nixpkgs-linux; }; - darwin = import ./default.nix { nixpkgs = nixpkgs-darwin; }; + linux = import ./default.nix { system = "x86_64-linux"; }; + darwin = import ./default.nix { system = "x86_64-darwin"; }; in linux // { darwin = darwin.all-systems-go; - moc-tar-x86_64-darwin = darwin.moc-tar; - moc-tar-x86_64-linux = linux.moc-tar; all-systems-go = inject-rev (nixpkgs.releaseTools.aggregate { name = "all-systems-go"; constituents = [ diff --git a/default.nix b/default.nix index 3af81ce96ce..e80575dabf9 100644 --- a/default.nix +++ b/default.nix @@ -1,12 +1,15 @@ -{ nixpkgs ? (import ./nix/nixpkgs.nix).nixpkgs {}, +{ dvm ? null, drun ? null, export-shell ? false, replay ? 0, - system ? nixpkgs.system + system ? builtins.currentSystem, }: -let llvm = import ./nix/llvm.nix { inherit system; }; in + +let nixpkgs = (import ./nix/nixpkgs.nix).nixpkgs { inherit system; }; in + +let llvm = import ./nix/llvm.nix { inherit (nixpkgs) system; }; in let stdenv = nixpkgs.stdenv; in @@ -17,21 +20,21 @@ let dev = import (builtins.fetchGit { url = "ssh://git@github.com/dfinity-lab/dev"; # ref = "master"; rev = "6fca1936fcd027aaeaccab0beb51defeee38a0ff"; -}) { inherit system; }; in +}) { inherit (nixpkgs) system; }; in let dfinity-repo = import (builtins.fetchGit { name = "dfinity-sources"; url = "ssh://git@github.com/dfinity-lab/dfinity"; ref = "master"; rev = "5c7efff0524adbf97d85b27adb180e6137a3428f"; -}) { inherit system; }; in +}) { inherit (nixpkgs) system; }; in let sdk = import (builtins.fetchGit { name = "sdk-sources"; url = "ssh://git@github.com/dfinity-lab/sdk"; ref = "paulyoung/js-user-library"; rev = "42f15621bc5b228c7fd349cb52f265917d33a3a0"; -}) { inherit system; }; in +}) { inherit (nixpkgs) system; }; in let esm = builtins.fetchTarball { sha256 = "116k10q9v0yzpng9bgdx3xrjm2kppma2db62mnbilbi66dvrvz9q"; diff --git a/shell.nix b/shell.nix index 429f224b81f..a7c0a47d0fe 100644 --- a/shell.nix +++ b/shell.nix @@ -1,4 +1,4 @@ -{ nixpkgs ? (import ./nix/nixpkgs.nix).nixpkgs {}, +{ system ? builtins.currentSystem, }: -(import ./default.nix { inherit nixpkgs; export-shell = true; }).shell +(import ./default.nix { inherit system; export-shell = true; }).shell From e360c24284a99d4ac41ebe36e400a5a6651e88d3 Mon Sep 17 00:00:00 2001 From: Paul Young Date: Mon, 25 Nov 2019 05:09:26 -0800 Subject: [PATCH 0704/1176] Update SDK for changes to JS user library (#905) * Update SDK for changes to JS user library * nix consistency --- default.nix | 4 ++-- test/run.sh | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/default.nix b/default.nix index e80575dabf9..6c202ece0ef 100644 --- a/default.nix +++ b/default.nix @@ -32,8 +32,8 @@ let dfinity-repo = import (builtins.fetchGit { let sdk = import (builtins.fetchGit { name = "sdk-sources"; url = "ssh://git@github.com/dfinity-lab/sdk"; - ref = "paulyoung/js-user-library"; - rev = "42f15621bc5b228c7fd349cb52f265917d33a3a0"; + ref = "master"; + rev = "7ee8cc40abab5b33c68bc8a32412e5be33a9f410"; }) { inherit (nixpkgs) system; }; in let esm = builtins.fetchTarball { diff --git a/test/run.sh b/test/run.sh index cd4c022e043..5405dbfd43b 100755 --- a/test/run.sh +++ b/test/run.sh @@ -308,7 +308,7 @@ do node -r esm -e \ "import actorInterface from './$out/$base.js'; import { makeActor, makeHttpAgent } from '$JS_USER_LIBRARY'; - const httpAgent = makeHttpAgent({ canisterId: 1 }); + const httpAgent = makeHttpAgent({ canisterId: "ffffffffffffffff" }); const actor = makeActor(actorInterface)(httpAgent); assert(Object.entries(actor).length > 0);" fi From 634fced25387a4995359283fc682701e4f36a16a Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 25 Nov 2019 16:33:37 +0100 Subject: [PATCH 0705/1176] Bump nixpkgs (#886) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit matching https://github.com/dfinity-lab/common/pull/68 Also, build the shell’s dependencies on CI (to test the derivation and keep the dependencies in the cache), but do not build `shell` remotely, do not substitute it (it’s build is just `touch $out`). Also update test output (new `wabt` it seems). --- default.nix | 17 ++++++++++++----- nix/nixpkgs.nix | 4 ++-- shell.nix | 3 +-- test/ld/ok/representative.linked.wat.ok | 2 +- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/default.nix b/default.nix index 6c202ece0ef..947bd9246c5 100644 --- a/default.nix +++ b/default.nix @@ -1,7 +1,6 @@ { dvm ? null, drun ? null, - export-shell ? false, replay ? 0, system ? builtins.currentSystem, }: @@ -229,7 +228,7 @@ rec { filecheck js-user-library dvm - drun + real-drun haskellPackages.qc-motoko haskellPackages.lsp-int ic-stub @@ -446,10 +445,11 @@ rec { produce-exchange users-guide ic-stub + shell ]; }; - shell = if export-shell then nixpkgs.mkShell { + shell = nixpkgs.mkShell { # # Since building moc, and testing it, are two different derivations in we # have to create a fake derivation for `nix-shell` that commons up the @@ -475,6 +475,13 @@ rec { NIX_FONTCONFIG_FILE = users-guide.NIX_FONTCONFIG_FILE; LOCALE_ARCHIVE = stdenv.lib.optionalString stdenv.isLinux "${nixpkgs.glibcLocales}/lib/locale/locale-archive"; - } else null; - + # allow building this as a derivation, so that hydra builds and caches + # the dependencies of shell + phases = ["dummyBuildPhase"]; + dummyBuildPhase = '' + touch $out + ''; + preferLocalBuild = true; + allowSubstitutes = true; + }; } diff --git a/nix/nixpkgs.nix b/nix/nixpkgs.nix index b8a6502553d..18edb15f256 100644 --- a/nix/nixpkgs.nix +++ b/nix/nixpkgs.nix @@ -1,8 +1,8 @@ rec { - rev = "e0c7712eac67c6b820d9d1020f46bac96fd8cede"; + rev = "96c9578020133fe64feab90c00f3cb880d53ad0d"; src = builtins.fetchTarball { - sha256 = "08rcnqxkninl5a560ss39s4nbqf0a677q6qh1fh7i0lr9pxf6aan"; + sha256 = "03rn7gn8r129a8cj527nhs7k28ibzwqw083iirwvas2x4k9mir9z"; url = "https://github.com/NixOS/nixpkgs/archive/${rev}.tar.gz"; }; diff --git a/shell.nix b/shell.nix index a7c0a47d0fe..570469d1c5b 100644 --- a/shell.nix +++ b/shell.nix @@ -1,4 +1,3 @@ { system ? builtins.currentSystem, }: -(import ./default.nix { inherit system; export-shell = true; }).shell - +(import ./default.nix { inherit system; }).shell diff --git a/test/ld/ok/representative.linked.wat.ok b/test/ld/ok/representative.linked.wat.ok index 207c392a946..88a9a7a604a 100644 --- a/test/ld/ok/representative.linked.wat.ok +++ b/test/ld/ok/representative.linked.wat.ok @@ -25,7 +25,7 @@ i32.mul) (func $link_start (type 4) call $__wasm_call_ctors) - (table (;0;) 0 0 anyfunc) + (table (;0;) 0 0 funcref) (memory (;0;) 2) (global (;0;) i32 (i32.const 65536)) (start 8)) From 9f1bf7acea79ff3a5272b1c8086c26e88ba4da7a Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 25 Nov 2019 16:48:13 +0100 Subject: [PATCH 0706/1176] New target: WASI (#675) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Finally, upstream `wasmtime` resolved the build issues with `wasmtime` on Darwin, so we can land this. You can now compile with `-wasi-system-api` and enjoy a local wasm program that can print. This is used by the test suite. Pro: * Ability to use debugPrint in tests/run * much faster execution of large tests in tests/run (which we don’t have) * relevant testing of the engine that the client plans to use (important for profiling, see #921) Con: * Need to run `nix-env -iA wasmtime -f .` once to install the wasmtime binary (or use nix-shell) --- Building.md | 2 +- default.nix | 19 +- nix/llvm.nix | 2 +- nix/{nixpkgs-newer.nix => nixpkgs-llvm.nix} | 0 nix/wasmtime/cargo-lock.patch | 2278 +++++++++++++++++ nix/wasmtime/default.nix | 31 + src/codegen/compile.ml | 186 +- src/exes/moc.ml | 3 + src/mo_config/flags.ml | 2 +- src/mo_frontend/typing.ml | 1 + test/run-drun/ok/idl-bad.drun-run.ok | 3 +- test/run-release/ok/debug.wasm-run.ok | 2 + test/run-stub/ok/idl-bad.ic-stub-run.ok | 3 +- test/run.sh | 13 +- test/run/idlHash.mo | 2 + test/run/ok/array-bounds.wasm-run.ok | 9 +- test/run/ok/assertFalse.wasm-run.ok | 9 +- .../ok/char-high-surrogate-trap.wasm-run.ok | 9 +- .../ok/char-low-surrogate-trap.wasm-run.ok | 9 +- test/run/ok/char-trap.wasm-run.ok | 9 +- test/run/ok/conversions.wasm-run.ok | 10 + test/run/ok/debug.wasm-run.ok | 1 + test/run/ok/for.wasm-run.ok | 11 + test/run/ok/idlHash.wasm-run.ok | 1 - test/run/ok/issue120.comp.ok | 6 + ...h.wasm-run.ret.ok => issue120.comp.ret.ok} | 0 test/run/ok/issue36.wasm-run.ok | 9 +- test/run/ok/overflow.wasm-run.ok | 7 +- test/run/ok/print.run-ir.ok | 2 + test/run/ok/print.run-low.ok | 2 + test/run/ok/print.run.ok | 2 + test/run/ok/print.wasm-run.ok | 2 + test/run/ok/variants.wasm-run.ok | 2 + test/run/ok/words.wasm-run.ok | 270 ++ test/run/print.mo | 2 + test/trap/ok/addInt16-lower.wasm-run.ok | 9 +- test/trap/ok/addInt16-upper.wasm-run.ok | 9 +- test/trap/ok/addInt32-lower.wasm-run.ok | 9 +- test/trap/ok/addInt32-upper.wasm-run.ok | 9 +- test/trap/ok/addInt64-lower.wasm-run.ok | 9 +- test/trap/ok/addInt64-upper.wasm-run.ok | 9 +- test/trap/ok/addInt8-lower.wasm-run.ok | 9 +- test/trap/ok/addInt8-upper.wasm-run.ok | 9 +- test/trap/ok/addNat16.wasm-run.ok | 9 +- test/trap/ok/addNat32.wasm-run.ok | 9 +- test/trap/ok/addNat64.wasm-run.ok | 9 +- test/trap/ok/addNat8.wasm-run.ok | 9 +- test/trap/ok/divInt16.wasm-run.ok | 7 +- test/trap/ok/divInt32.wasm-run.ok | 7 +- test/trap/ok/divInt64.wasm-run.ok | 7 +- test/trap/ok/divInt8.wasm-run.ok | 7 +- test/trap/ok/mulInt16-lower.wasm-run.ok | 9 +- test/trap/ok/mulInt16-upper.wasm-run.ok | 9 +- test/trap/ok/mulInt32-lower.wasm-run.ok | 9 +- test/trap/ok/mulInt32-upper.wasm-run.ok | 9 +- test/trap/ok/mulInt64-lower.wasm-run.ok | 9 +- test/trap/ok/mulInt64-upper.wasm-run.ok | 9 +- test/trap/ok/mulInt8-lower.wasm-run.ok | 9 +- test/trap/ok/mulInt8-upper.wasm-run.ok | 9 +- test/trap/ok/mulNat16.wasm-run.ok | 9 +- test/trap/ok/mulNat32.wasm-run.ok | 9 +- test/trap/ok/mulNat64.wasm-run.ok | 9 +- test/trap/ok/mulNat8.wasm-run.ok | 9 +- test/trap/ok/outrange-int16-lower.wasm-run.ok | 9 +- .../ok/outrange-int16-negation.wasm-run.ok | 9 +- test/trap/ok/outrange-int16-upper.wasm-run.ok | 9 +- test/trap/ok/outrange-int32-lower.wasm-run.ok | 9 +- .../ok/outrange-int32-negation.wasm-run.ok | 9 +- test/trap/ok/outrange-int32-upper.wasm-run.ok | 9 +- test/trap/ok/outrange-int64-lower.wasm-run.ok | 9 +- .../ok/outrange-int64-negation.wasm-run.ok | 9 +- test/trap/ok/outrange-int64-upper.wasm-run.ok | 9 +- test/trap/ok/outrange-int8-lower.wasm-run.ok | 9 +- .../ok/outrange-int8-negation.wasm-run.ok | 9 +- test/trap/ok/outrange-int8-upper.wasm-run.ok | 9 +- test/trap/ok/outrange-nat16.wasm-run.ok | 9 +- test/trap/ok/outrange-nat32.wasm-run.ok | 9 +- test/trap/ok/outrange-nat64.wasm-run.ok | 9 +- test/trap/ok/outrange-nat8.wasm-run.ok | 9 +- test/trap/ok/powInt32-lower.wasm-run.ok | 9 +- test/trap/ok/powInt32-raise-neg.wasm-run.ok | 9 +- test/trap/ok/powInt32-upper.wasm-run.ok | 9 +- test/trap/ok/powInt64-lower-fast.wasm-run.ok | 9 +- test/trap/ok/powInt64-lower-slow.wasm-run.ok | 9 +- test/trap/ok/powInt64-raise-neg.wasm-run.ok | 9 +- test/trap/ok/powInt64-upper-fast.wasm-run.ok | 9 +- test/trap/ok/powInt64-upper-slow.wasm-run.ok | 9 +- test/trap/ok/powInt8-lower.wasm-run.ok | 9 +- test/trap/ok/powInt8-raise-neg.wasm-run.ok | 9 +- test/trap/ok/powInt8-upper.wasm-run.ok | 9 +- test/trap/ok/powNat16.wasm-run.ok | 9 +- test/trap/ok/powNat32.wasm-run.ok | 9 +- test/trap/ok/powNat64.wasm-run.ok | 9 +- test/trap/ok/powNat8.wasm-run.ok | 9 +- test/trap/ok/subInt16-lower.wasm-run.ok | 9 +- test/trap/ok/subInt16-upper.wasm-run.ok | 9 +- test/trap/ok/subInt32-lower.wasm-run.ok | 9 +- test/trap/ok/subInt32-upper.wasm-run.ok | 9 +- test/trap/ok/subInt64-lower.wasm-run.ok | 9 +- test/trap/ok/subInt64-upper.wasm-run.ok | 9 +- test/trap/ok/subInt8-lower.wasm-run.ok | 9 +- test/trap/ok/subInt8-upper.wasm-run.ok | 9 +- test/trap/ok/subNat16.wasm-run.ok | 9 +- test/trap/ok/subNat32.wasm-run.ok | 9 +- test/trap/ok/subNat64-slow.wasm-run.ok | 9 +- test/trap/ok/subNat64.wasm-run.ok | 9 +- test/trap/ok/subNat8.wasm-run.ok | 9 +- 107 files changed, 3396 insertions(+), 163 deletions(-) rename nix/{nixpkgs-newer.nix => nixpkgs-llvm.nix} (100%) create mode 100644 nix/wasmtime/cargo-lock.patch create mode 100644 nix/wasmtime/default.nix create mode 100644 test/run-release/ok/debug.wasm-run.ok create mode 100644 test/run/ok/conversions.wasm-run.ok create mode 100644 test/run/ok/debug.wasm-run.ok create mode 100644 test/run/ok/for.wasm-run.ok delete mode 100644 test/run/ok/idlHash.wasm-run.ok create mode 100644 test/run/ok/issue120.comp.ok rename test/run/ok/{idlHash.wasm-run.ret.ok => issue120.comp.ret.ok} (100%) create mode 100644 test/run/ok/print.run-ir.ok create mode 100644 test/run/ok/print.run-low.ok create mode 100644 test/run/ok/print.run.ok create mode 100644 test/run/ok/print.wasm-run.ok create mode 100644 test/run/ok/variants.wasm-run.ok create mode 100644 test/run/ok/words.wasm-run.ok create mode 100644 test/run/print.mo diff --git a/Building.md b/Building.md index 2c32036eaab..d2989684d0b 100644 --- a/Building.md +++ b/Building.md @@ -49,7 +49,7 @@ installing all required tools without nix is out of scope). ``` * Install various command line tools used by, in particuar, the test suite: ``` - nix-env -i -f . -A wasm + nix-env -i -f . -A wasmtime nix-env -i -f . -A filecheck nix-env -i -f . -A wabt nix-env -i -f . -A dvm diff --git a/default.nix b/default.nix index 947bd9246c5..7d1ffd56be4 100644 --- a/default.nix +++ b/default.nix @@ -5,8 +5,12 @@ system ? builtins.currentSystem, }: - -let nixpkgs = (import ./nix/nixpkgs.nix).nixpkgs { inherit system; }; in +let nixpkgs = (import ./nix/nixpkgs.nix).nixpkgs { + inherit system; + overlays = [ + (self: super: { wasmtime = self.callPackage ./nix/wasmtime {}; }) + ]; +}; in let llvm = import ./nix/llvm.nix { inherit (nixpkgs) system; }; in @@ -87,11 +91,6 @@ let ocamlpkgs = then nixpkgs else nixpkgs.pkgsMusl; in -let ocaml_wasm_static = - import ./nix/ocaml-wasm.nix { - inherit (ocamlpkgs) stdenv fetchFromGitHub ocaml; - inherit (ocamlpkgs.ocamlPackages) findlib ocamlbuild; - }; in # This branches on the pkgs, which is either # normal nixpkgs (nix-shell, darwin) @@ -218,7 +217,6 @@ rec { mo-ld didc deser - ocaml_wasm_static nixpkgs.wabt nixpkgs.bash nixpkgs.perl @@ -229,6 +227,7 @@ rec { js-user-library dvm real-drun + wasmtime haskellPackages.qc-motoko haskellPackages.lsp-int ic-stub @@ -282,7 +281,6 @@ rec { buildInputs = [ moc didc - ocaml_wasm_static nixpkgs.wabt nixpkgs.bash nixpkgs.perl @@ -330,13 +328,12 @@ rec { ''; }; - wasm = ocaml_wasm_static; dvm = real-dvm; drun = real-drun; filecheck = nixpkgs.linkFarm "FileCheck" [ { name = "bin/FileCheck"; path = "${nixpkgs.llvm}/bin/FileCheck";} ]; wabt = nixpkgs.wabt; - + wasmtime = nixpkgs.wasmtime; users-guide = stdenv.mkDerivation { name = "users-guide"; diff --git a/nix/llvm.nix b/nix/llvm.nix index fcf0aca1cb3..f7fdaa92a56 100644 --- a/nix/llvm.nix +++ b/nix/llvm.nix @@ -1,6 +1,6 @@ { system } : -let pkgs = (import ./nixpkgs-newer.nix) { +let pkgs = (import ./nixpkgs-llvm.nix) { system = system; }; in diff --git a/nix/nixpkgs-newer.nix b/nix/nixpkgs-llvm.nix similarity index 100% rename from nix/nixpkgs-newer.nix rename to nix/nixpkgs-llvm.nix diff --git a/nix/wasmtime/cargo-lock.patch b/nix/wasmtime/cargo-lock.patch new file mode 100644 index 00000000000..56c9879dd6e --- /dev/null +++ b/nix/wasmtime/cargo-lock.patch @@ -0,0 +1,2278 @@ +diff --git a/Cargo.lock b/Cargo.lock +new file mode 100644 +index 00000000..3b45d5eb +--- /dev/null ++++ b/Cargo.lock +@@ -0,0 +1,2272 @@ ++# This file is automatically @generated by Cargo. ++# It is not intended for manual editing. ++[[package]] ++name = "ahash" ++version = "0.2.16" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "const-random 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "aho-corasick" ++version = "0.7.6" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "ansi_term" ++version = "0.11.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "anyhow" ++version = "1.0.19" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "arrayref" ++version = "0.3.5" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "arrayvec" ++version = "0.4.12" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "atty" ++version = "0.2.13" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "autocfg" ++version = "0.1.6" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "backtrace" ++version = "0.3.40" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "backtrace-sys" ++version = "0.1.32" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "base64" ++version = "0.10.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "base64" ++version = "0.11.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "bincode" ++version = "1.2.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "bindgen" ++version = "0.51.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cexpr 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ++ "clang-sys 0.28.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ++ "peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "which 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "bitflags" ++version = "1.2.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "blake2b_simd" ++version = "0.5.8" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ++ "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", ++ "constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "block-buffer" ++version = "0.7.3" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ++ "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "block-padding" ++version = "0.1.4" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "byte-tools" ++version = "0.3.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "byteorder" ++version = "1.3.2" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "c2-chacha" ++version = "0.2.2" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "capstone" ++version = "0.6.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "capstone-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "capstone-sys" ++version = "0.10.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "cc" ++version = "1.0.46" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "jobserver 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", ++ "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "cexpr" ++version = "0.3.5" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "cfg-if" ++version = "0.1.10" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "chrono" ++version = "0.4.9" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", ++ "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ++ "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "clang-sys" ++version = "0.28.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libloading 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "clap" ++version = "2.33.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", ++ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "cloudabi" ++version = "0.0.3" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "cmake" ++version = "0.1.42" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "const-random" ++version = "0.1.6" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "const-random-macro 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "const-random-macro" ++version = "0.1.6" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", ++ "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "constant_time_eq" ++version = "0.1.4" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "cpu-time" ++version = "1.0.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "cranelift-bforest" ++version = "0.49.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "cranelift-entity 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "cranelift-codegen" ++version = "0.49.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-bforest 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-codegen-meta 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-codegen-shared 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-entity 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "hashbrown 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ++ "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ++ "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "thiserror 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "cranelift-codegen-meta" ++version = "0.49.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "cranelift-codegen-shared 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-entity 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "cranelift-codegen-shared" ++version = "0.49.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "cranelift-entity" ++version = "0.49.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "cranelift-frontend" ++version = "0.49.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "cranelift-codegen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "hashbrown 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ++ "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "cranelift-native" ++version = "0.49.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "cranelift-codegen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "raw-cpuid 7.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ++ "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "cranelift-wasm" ++version = "0.49.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "cranelift-codegen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-entity 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-frontend 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "hashbrown 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ++ "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ++ "thiserror 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasmparser 0.39.2 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "crossbeam-deque" ++version = "0.7.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "crossbeam-epoch" ++version = "0.7.2" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ++ "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", ++ "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "crossbeam-queue" ++version = "0.1.2" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "crossbeam-utils" ++version = "0.6.6" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ++ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "ctor" ++version = "0.1.12" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "cvt" ++version = "0.1.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "digest" ++version = "0.8.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "directories" ++version = "2.0.2" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ++ "dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "dirs-sys" ++version = "0.3.4" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "docopt" ++version = "1.1.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ++ "strsim 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "dynasm" ++version = "0.5.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "dynasmrt" ++version = "0.5.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "either" ++version = "1.5.3" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "env_logger" ++version = "0.6.2" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", ++ "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ++ "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "errno" ++version = "0.2.4" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "errno-dragonfly" ++version = "0.1.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "faerie" ++version = "0.12.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "goblin 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "indexmap 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ++ "scroll 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "string-interner 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "failure" ++version = "0.1.6" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", ++ "failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "failure_derive" ++version = "0.1.6" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++ "synstructure 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "fake-simd" ++version = "0.1.2" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "fallible-iterator" ++version = "0.2.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "file-per-thread-logger" ++version = "0.1.2" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "filetime" ++version = "0.2.7" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", ++ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "fuchsia-cprng" ++version = "0.1.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "gcc" ++version = "0.3.55" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "generic-array" ++version = "0.12.3" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "getrandom" ++version = "0.1.12" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "ghost" ++version = "0.1.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "gimli" ++version = "0.19.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", ++ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "fallible-iterator 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "indexmap 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "glob" ++version = "0.3.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "goblin" ++version = "0.1.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ++ "plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ++ "scroll 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "hashbrown" ++version = "0.5.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "hashbrown" ++version = "0.6.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "ahash 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", ++ "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "heck" ++version = "0.3.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "humantime" ++version = "1.3.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "id-arena" ++version = "2.2.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "indexmap" ++version = "1.2.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "indoc" ++version = "0.3.4" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "indoc-impl 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ++ "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "indoc-impl" ++version = "0.3.4" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", ++ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++ "unindent 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "inventory" ++version = "0.1.4" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "ctor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ++ "ghost 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "inventory-impl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "inventory-impl" ++version = "0.1.4" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "itertools" ++version = "0.8.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "itoa" ++version = "0.4.4" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "jobserver" ++version = "0.1.17" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "lazy_static" ++version = "1.4.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "leb128" ++version = "0.2.4" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "libc" ++version = "0.2.64" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "libloading" ++version = "0.5.2" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", ++ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "lightbeam" ++version = "0.0.0" ++dependencies = [ ++ "capstone 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-codegen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "dynasm 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "dynasmrt 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", ++ "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", ++ "more-asserts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "multi_mut 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ++ "quickcheck 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "thiserror 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++ "typemap 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasmparser 0.39.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wat 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "log" ++version = "0.4.8" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "mach" ++version = "0.2.3" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "memchr" ++version = "2.2.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "memmap" ++version = "0.7.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "memoffset" ++version = "0.5.3" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "more-asserts" ++version = "0.2.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "multi_mut" ++version = "0.1.3" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "nix" ++version = "0.15.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "nodrop" ++version = "0.1.14" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "nom" ++version = "4.2.3" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "num" ++version = "0.2.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "num-complex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ++ "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", ++ "num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", ++ "num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "num-complex" ++version = "0.2.3" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "num-integer" ++version = "0.1.41" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "num-iter" ++version = "0.1.39" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", ++ "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "num-rational" ++version = "0.2.2" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", ++ "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "num-traits" ++version = "0.2.8" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "num_cpus" ++version = "1.10.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "opaque-debug" ++version = "0.2.3" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "os_pipe" ++version = "0.9.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "owning_ref" ++version = "0.4.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "paste" ++version = "0.1.6" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "paste-impl 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "paste-impl" ++version = "0.1.6" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", ++ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "peeking_take_while" ++version = "0.1.2" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "plain" ++version = "0.2.3" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "ppv-lite86" ++version = "0.2.5" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "pretty_env_logger" ++version = "0.3.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", ++ "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "proc-macro-hack" ++version = "0.5.11" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "proc-macro2" ++version = "1.0.6" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "pyo3" ++version = "0.8.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "indoc 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ++ "inventory 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ++ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ++ "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "pyo3cls 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ++ "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", ++ "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "unindent 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ++ "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "pyo3-derive-backend" ++version = "0.8.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "pyo3cls" ++version = "0.8.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "pyo3-derive-backend 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "quick-error" ++version = "1.2.2" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "quickcheck" ++version = "0.9.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ++ "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "quote" ++version = "1.0.2" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "rand" ++version = "0.7.2" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "rand_pcg 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "rand_chacha" ++version = "0.2.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "rand_core" ++version = "0.3.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "rand_core" ++version = "0.4.2" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "rand_core" ++version = "0.5.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "rand_hc" ++version = "0.2.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "rand_os" ++version = "0.1.3" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ++ "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "rand_pcg" ++version = "0.2.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "raw-cpuid" ++version = "7.0.3" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", ++ "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "rayon" ++version = "1.2.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", ++ "rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "rayon-core" ++version = "1.6.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "rdrand" ++version = "0.4.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "redox_syscall" ++version = "0.1.56" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "redox_users" ++version = "0.3.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ++ "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", ++ "rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "regex" ++version = "1.3.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", ++ "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "regex-syntax" ++version = "0.6.12" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "region" ++version = "2.1.2" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "mach 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ++ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "remove_dir_all" ++version = "0.5.2" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "rust-argon2" ++version = "0.5.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "blake2b_simd 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", ++ "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "rustc-demangle" ++version = "0.1.16" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "rustc-hash" ++version = "1.0.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "rustc_version" ++version = "0.2.3" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "ryu" ++version = "1.0.2" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "scopeguard" ++version = "1.0.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "scroll" ++version = "0.10.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "scroll_derive 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "scroll_derive" ++version = "0.10.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "semver" ++version = "0.9.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "semver-parser" ++version = "0.7.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "serde" ++version = "1.0.101" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "serde_derive" ++version = "1.0.101" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "serde_json" ++version = "1.0.41" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", ++ "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "sha2" ++version = "0.8.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", ++ "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "shlex" ++version = "0.1.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "smallvec" ++version = "1.0.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "spin" ++version = "0.5.2" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "stable_deref_trait" ++version = "1.1.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "string-interner" ++version = "0.7.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "strsim" ++version = "0.8.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "strsim" ++version = "0.9.2" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "syn" ++version = "1.0.5" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "synstructure" ++version = "0.12.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "target-lexicon" ++version = "0.9.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "tempfile" ++version = "3.1.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", ++ "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "termcolor" ++version = "1.0.5" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "textwrap" ++version = "0.11.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "thiserror" ++version = "1.0.5" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "thiserror-impl 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "thiserror-impl" ++version = "1.0.5" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "thread_local" ++version = "0.3.6" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "time" ++version = "0.1.42" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", ++ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "toml" ++version = "0.5.5" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "traitobject" ++version = "0.1.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "trybuild" ++version = "1.0.17" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ++ "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", ++ "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++ "toml 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "typemap" ++version = "0.3.3" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "unsafe-any 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "typenum" ++version = "1.11.2" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "unicode-segmentation" ++version = "1.3.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "unicode-width" ++version = "0.1.6" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "unicode-xid" ++version = "0.2.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "unindent" ++version = "0.1.5" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "unsafe-any" ++version = "0.4.2" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "vec_map" ++version = "0.8.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "version_check" ++version = "0.1.5" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "version_check" ++version = "0.9.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "void" ++version = "1.0.2" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "walrus" ++version = "0.13.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "anyhow 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", ++ "id-arena 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "leb128 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", ++ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ++ "walrus-macro 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasmparser 0.39.2 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "walrus-macro" ++version = "0.13.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "wasi" ++version = "0.7.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "wasi-common" ++version = "0.5.0" ++dependencies = [ ++ "anyhow 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cpu-time 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-codegen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "filetime 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ++ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ++ "nix 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "os_pipe 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "pretty_env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "thiserror 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasi-common-cbindgen 0.5.0", ++ "wasmtime 0.1.0", ++ "wasmtime-environ 0.2.0", ++ "wasmtime-jit 0.2.0", ++ "wasmtime-runtime 0.2.0", ++ "wasmtime-wasi 0.2.0", ++ "wig 0.1.0", ++ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ++ "winx 0.5.0", ++] ++ ++[[package]] ++name = "wasi-common-cbindgen" ++version = "0.5.0" ++dependencies = [ ++ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++ "trybuild 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "wasm-webidl-bindings" ++version = "0.6.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "anyhow 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", ++ "id-arena 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "leb128 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", ++ "walrus 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "wasmparser" ++version = "0.39.2" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "hashbrown 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "wasmtime" ++version = "0.1.0" ++dependencies = [ ++ "anyhow 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-codegen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-entity 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-frontend 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-native 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-wasm 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "docopt 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "file-per-thread-logger 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "hashbrown 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "pretty_env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "region 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ++ "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "thiserror 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasi-common 0.5.0", ++ "wasmparser 0.39.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasmtime-environ 0.2.0", ++ "wasmtime-jit 0.2.0", ++ "wasmtime-runtime 0.2.0", ++ "wasmtime-wasi 0.2.0", ++ "wasmtime-wast 0.2.0", ++] ++ ++[[package]] ++name = "wasmtime-cli" ++version = "0.2.0" ++dependencies = [ ++ "anyhow 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-codegen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-entity 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-native 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-wasm 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "docopt 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "faerie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "file-per-thread-logger 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "more-asserts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "pretty_env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ++ "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasi-common 0.5.0", ++ "wasm-webidl-bindings 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasmtime 0.1.0", ++ "wasmtime-debug 0.2.0", ++ "wasmtime-environ 0.2.0", ++ "wasmtime-interface-types 0.2.0", ++ "wasmtime-jit 0.2.0", ++ "wasmtime-obj 0.2.0", ++ "wasmtime-runtime 0.2.0", ++ "wasmtime-wasi 0.2.0", ++ "wasmtime-wasi-c 0.2.0", ++ "wasmtime-wast 0.2.0", ++ "wat 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "wasmtime-debug" ++version = "0.2.0" ++dependencies = [ ++ "cranelift-codegen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-entity 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-wasm 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "faerie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "gimli 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "hashbrown 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "more-asserts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "thiserror 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasmparser 0.39.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasmtime-environ 0.2.0", ++] ++ ++[[package]] ++name = "wasmtime-environ" ++version = "0.2.0" ++dependencies = [ ++ "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-codegen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-entity 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-wasm 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "directories 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", ++ "file-per-thread-logger 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "filetime 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ++ "indexmap 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "lightbeam 0.0.0", ++ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ++ "more-asserts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "pretty_env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ++ "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "thiserror 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++ "toml 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", ++ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ++ "zstd 0.5.1+zstd.1.4.4 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "wasmtime-interface-types" ++version = "0.2.0" ++dependencies = [ ++ "anyhow 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-codegen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "walrus 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasm-webidl-bindings 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasmparser 0.39.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasmtime-jit 0.2.0", ++ "wasmtime-runtime 0.2.0", ++] ++ ++[[package]] ++name = "wasmtime-jit" ++version = "0.2.0" ++dependencies = [ ++ "cranelift-codegen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-entity 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-frontend 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-wasm 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "hashbrown 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "more-asserts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "region 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "thiserror 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasmparser 0.39.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasmtime-debug 0.2.0", ++ "wasmtime-environ 0.2.0", ++ "wasmtime-runtime 0.2.0", ++ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "wasmtime-obj" ++version = "0.2.0" ++dependencies = [ ++ "cranelift-codegen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-entity 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-wasm 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "faerie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "more-asserts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasmtime-environ 0.2.0", ++] ++ ++[[package]] ++name = "wasmtime-py" ++version = "0.2.0" ++dependencies = [ ++ "anyhow 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-codegen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-entity 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-frontend 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-native 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-wasm 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "pyo3 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "region 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasmparser 0.39.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasmtime-environ 0.2.0", ++ "wasmtime-interface-types 0.2.0", ++ "wasmtime-jit 0.2.0", ++ "wasmtime-runtime 0.2.0", ++] ++ ++[[package]] ++name = "wasmtime-runtime" ++version = "0.2.0" ++dependencies = [ ++ "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-codegen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-entity 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-wasm 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "hashbrown 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "indexmap 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", ++ "more-asserts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "region 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "thiserror 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasmtime-environ 0.2.0", ++ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "wasmtime-rust" ++version = "0.2.0" ++dependencies = [ ++ "anyhow 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-codegen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-native 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasmtime-interface-types 0.2.0", ++ "wasmtime-jit 0.2.0", ++ "wasmtime-rust-macro 0.2.0", ++ "wasmtime-wasi 0.2.0", ++] ++ ++[[package]] ++name = "wasmtime-rust-macro" ++version = "0.2.0" ++dependencies = [ ++ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "wasmtime-wasi" ++version = "0.2.0" ++dependencies = [ ++ "cranelift-codegen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-entity 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-wasm 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ++ "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasi-common 0.5.0", ++ "wasmtime-environ 0.2.0", ++ "wasmtime-jit 0.2.0", ++ "wasmtime-runtime 0.2.0", ++] ++ ++[[package]] ++name = "wasmtime-wasi-c" ++version = "0.2.0" ++dependencies = [ ++ "bindgen 0.51.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-codegen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-entity 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-wasm 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ++ "more-asserts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasmtime-environ 0.2.0", ++ "wasmtime-jit 0.2.0", ++ "wasmtime-runtime 0.2.0", ++] ++ ++[[package]] ++name = "wasmtime-wast" ++version = "0.2.0" ++dependencies = [ ++ "anyhow 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-codegen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-entity 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-wasm 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasmtime-environ 0.2.0", ++ "wasmtime-jit 0.2.0", ++ "wasmtime-runtime 0.2.0", ++ "wast 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "wast" ++version = "3.0.2" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "leb128 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "wat" ++version = "1.0.3" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "wast 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "which" ++version = "3.0.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "wig" ++version = "0.1.0" ++dependencies = [ ++ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "witx 0.4.0", ++] ++ ++[[package]] ++name = "winapi" ++version = "0.3.8" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "winapi-i686-pc-windows-gnu" ++version = "0.4.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "winapi-util" ++version = "0.1.2" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "winapi-x86_64-pc-windows-gnu" ++version = "0.4.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] ++name = "wincolor" ++version = "1.0.2" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ++ "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "winx" ++version = "0.5.0" ++dependencies = [ ++ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cvt 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "witx" ++version = "0.4.0" ++dependencies = [ ++ "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wast 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "zstd" ++version = "0.5.1+zstd.1.4.4" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "zstd-safe 2.0.3+zstd.1.4.4 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "zstd-safe" ++version = "2.0.3+zstd.1.4.4" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "zstd-sys 1.4.15+zstd.1.4.4 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "zstd-sys" ++version = "1.4.15+zstd.1.4.4" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", ++ "glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[metadata] ++"checksum ahash 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)" = "b35dfc96a657c1842b4eb73180b65e37152d4b94d0eb5cb51708aee7826950b4" ++"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" ++"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" ++"checksum anyhow 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "57114fc2a6cc374bce195d3482057c846e706d252ff3604363449695684d7a0d" ++"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" ++"checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" ++"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" ++"checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" ++"checksum backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea" ++"checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491" ++"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" ++"checksum base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" ++"checksum bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8ab639324e3ee8774d296864fbc0dbbb256cf1a41c490b94cba90c082915f92" ++"checksum bindgen 0.51.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ebd71393f1ec0509b553aa012b9b58e81dadbdff7130bd3b8cba576e69b32f75" ++"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" ++"checksum blake2b_simd 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "5850aeee1552f495dd0250014cf64b82b7c8879a89d83b33bbdace2cc4f63182" ++"checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" ++"checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09" ++"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" ++"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" ++"checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" ++"checksum capstone 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "031ba51c39151a1d6336ec859646153187204b0147c7b3f6fe2de636f1b8dbb3" ++"checksum capstone-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fae25eddcb80e24f98c35952c37a91ff7f8d0f60dbbdafb9763e8d5cc566b8d7" ++"checksum cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)" = "0213d356d3c4ea2c18c40b037c3be23cd639825c18f25ee670ac7813beeef99c" ++"checksum cexpr 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7fa24eb00d5ffab90eaeaf1092ac85c04c64aaf358ea6f84505b8116d24c6af" ++"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" ++"checksum chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e8493056968583b0193c1bb04d6f7684586f3726992d6c573261941a895dbd68" ++"checksum clang-sys 0.28.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81de550971c976f176130da4b2978d3b524eaa0fd9ac31f3ceb5ae1231fb4853" ++"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" ++"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" ++"checksum cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "81fb25b677f8bf1eb325017cb6bb8452f87969db0fedb4f757b297bee78a7c62" ++"checksum const-random 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7b641a8c9867e341f3295564203b1c250eb8ce6cb6126e007941f78c4d2ed7fe" ++"checksum const-random-macro 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c750ec12b83377637110d5a57f5ae08e895b06c4b16e2bdbf1a94ef717428c59" ++"checksum constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "995a44c877f9212528ccc74b21a232f66ad69001e40ede5bcee2ac9ef2657120" ++"checksum cpu-time 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e9e393a7668fe1fad3075085b86c781883000b4ede868f43627b34a87c8b7ded" ++"checksum cranelift-bforest 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba29e425110674c89fdc2f79479d767f31003dd9187c29ba2dad57fe4d321670" ++"checksum cranelift-codegen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8cb71c7ce1438c41f3d35383fa41eee26f5adf9815c7f5c2e7029a6c9356df2c" ++"checksum cranelift-codegen-meta 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4aa634fd60290d5047d40172028a0aa86458e32a72c76fcce0a317bbbbcca4e5" ++"checksum cranelift-codegen-shared 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6fa6cf5c2adc031be07cd5bc88145ebb93d9d2a05a28a93136782b2167eacb62" ++"checksum cranelift-entity 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)" = "932d5f9622b336e10e8cf843ded09a688ec49f32c32b3101d7c5a7b71cad3dc9" ++"checksum cranelift-frontend 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d1a3c105c657cd65c20d9183bbd4f2b16bf3548db4b865c065bf7028f3021de" ++"checksum cranelift-native 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba5e34645453b73a9e2def05561f957a9df17253996379dd59c4afe3cf7db0f1" ++"checksum cranelift-wasm 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23410ae1f5edf7d83e95bf8537e771345ecc2b11e5c7208cbee8151ea3b88e97" ++"checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" ++"checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" ++"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" ++"checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" ++"checksum ctor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd8ce37ad4184ab2ce004c33bf6379185d3b1c95801cab51026bd271bf68eedc" ++"checksum cvt 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "34ac344c7efccb80cd25bc61b2170aec26f2f693fd40e765a539a1243db48c71" ++"checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" ++"checksum directories 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "551a778172a450d7fc12e629ca3b0428d00f6afa9a43da1b630d54604e97371c" ++"checksum dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b" ++"checksum docopt 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f525a586d310c87df72ebcd98009e57f1cc030c8c268305287a476beb653969" ++"checksum dynasm 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8654f63488a94cd11feac2a609fdcdecd09e02fb582731f635783689fbb429f3" ++"checksum dynasmrt 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b0046b083139885c38990f2fb9822d06f6c5902068d93a6ed9e56b63011b9932" ++"checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" ++"checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" ++"checksum errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2a071601ed01b988f896ab14b95e67335d1eeb50190932a1320f7fe3cadc84e" ++"checksum errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "14ca354e36190500e1e1fb267c647932382b54053c50b14970856c0b00a35067" ++"checksum faerie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "01fed63609767c70e34203201032c249d60a24578a67ef0ce7cc13ff010e9cf2" ++"checksum failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9" ++"checksum failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0bc225b78e0391e4b8683440bf2e63c2deeeb2ce5189eab46e2b68c6d3725d08" ++"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" ++"checksum fallible-iterator 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" ++"checksum file-per-thread-logger 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8505b75b31ef7285168dd237c4a7db3c1f3e0927e7d314e670bc98e854272fe9" ++"checksum filetime 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6bd7380b54ced79dda72ecc35cc4fbbd1da6bba54afaa37e96fd1c2a308cd469" ++"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" ++"checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" ++"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" ++"checksum getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571" ++"checksum ghost 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2a36606a68532b5640dc86bb1f33c64b45c4682aad4c50f3937b317ea387f3d6" ++"checksum gimli 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "162d18ae5f2e3b90a993d202f1ba17a5633c2484426f8bcae201f86194bacd00" ++"checksum glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" ++"checksum goblin 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6040506480da04a63de51a478e8021892d65d8411f29b2a422c2648bdd8bcb" ++"checksum hashbrown 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e1de41fb8dba9714efd92241565cdff73f78508c95697dd56787d3cba27e2353" ++"checksum hashbrown 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6587d09be37fb98a11cb08b9000a3f592451c1b1b613ca69d949160e313a430a" ++"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" ++"checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" ++"checksum id-arena 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" ++"checksum indexmap 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a61202fbe46c4a951e9404a720a0180bcf3212c750d735cb5c4ba4dc551299f3" ++"checksum indoc 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3f9553c1e16c114b8b77ebeb329e5f2876eed62a8d51178c8bc6bff0d65f98f8" ++"checksum indoc-impl 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b714fc08d0961716390977cdff1536234415ac37b509e34e5a983def8340fb75" ++"checksum inventory 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f4cece20baea71d9f3435e7bbe9adf4765f091c5fe404975f844006964a71299" ++"checksum inventory-impl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2869bf972e998977b1cb87e60df70341d48e48dca0823f534feb91ea44adaf9" ++"checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" ++"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" ++"checksum jobserver 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "f2b1d42ef453b30b7387e113da1c83ab1605d90c5b4e0eb8e96d016ed3b8c160" ++"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" ++"checksum leb128 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3576a87f2ba00f6f106fdfcd16db1d698d648a26ad8e0573cad8537c3c362d2a" ++"checksum libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)" = "74dfca3d9957906e8d1e6a0b641dc9a59848e793f1da2165889fd4f62d10d79c" ++"checksum libloading 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753" ++"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" ++"checksum mach 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "86dd2487cdfea56def77b88438a2c915fb45113c5319bfe7e14306ca4cd0b0e1" ++"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" ++"checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" ++"checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" ++"checksum more-asserts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0debeb9fcf88823ea64d64e4a815ab1643f33127d995978e099942ce38f25238" ++"checksum multi_mut 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "816df386e5557ac1843a96f1ba8a7cbf4ab175d05ccc15c87a3cda27b4fbdece" ++"checksum nix 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3b2e0b4f3320ed72aaedb9a5ac838690a8047c7b275da22711fddff4f8a14229" ++"checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" ++"checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" ++"checksum num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf4825417e1e1406b3782a8ce92f4d53f26ec055e3622e1881ca8e9f5f9e08db" ++"checksum num-complex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fcb0cf31fb3ff77e6d2a6ebd6800df7fdcd106f2ad89113c9130bcd07f93dffc" ++"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" ++"checksum num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "76bd5272412d173d6bf9afdf98db8612bbabc9a7a830b7bfc9c188911716132e" ++"checksum num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2885278d5fe2adc2f75ced642d52d879bffaceb5a2e0b1d4309ffdfb239b454" ++"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" ++"checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" ++"checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" ++"checksum os_pipe 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "db4d06355a7090ce852965b2d08e11426c315438462638c6d721448d0b47aa22" ++"checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" ++"checksum paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "423a519e1c6e828f1e73b720f9d9ed2fa643dce8a7737fb43235ce0b41eeaa49" ++"checksum paste-impl 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4214c9e912ef61bf42b81ba9a47e8aad1b2ffaf739ab162bf96d1e011f54e6c5" ++"checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" ++"checksum plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" ++"checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" ++"checksum pretty_env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "717ee476b1690853d222af4634056d830b5197ffd747726a9a1eee6da9f49074" ++"checksum proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5" ++"checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" ++"checksum pyo3 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a00f96312ebe4082db7d93ad062df1818f597660002541c1bbae6752ec583244" ++"checksum pyo3-derive-backend 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1a7caa60cb986fca5b488e29d078fb25ae228e01dab080b855168ce061bbef0a" ++"checksum pyo3cls 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a5ccfa624ed9b5d805079f1ad64b3f1de5d551a946d4cf494f1f032b5572d39f" ++"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" ++"checksum quickcheck 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d5ca504a2fdaa08d3517f442fbbba91ac24d1ec4c51ea68688a038765e3b2662" ++"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" ++"checksum rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412" ++"checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" ++"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" ++"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" ++"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" ++"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" ++"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" ++"checksum rand_pcg 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e196346cbbc5c70c77e7b4926147ee8e383a38ee4d15d58a08098b169e492b6" ++"checksum raw-cpuid 7.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4a349ca83373cfa5d6dbb66fd76e58b2cca08da71a5f6400de0a0a6a9bceeaf" ++"checksum rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83a27732a533a1be0a0035a111fe76db89ad312f6f0347004c220c57f209a123" ++"checksum rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98dcf634205083b17d0861252431eb2acbfb698ab7478a2d20de07954f47ec7b" ++"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" ++"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" ++"checksum redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecedbca3bf205f8d8f5c2b44d83cd0690e39ee84b951ed649e9f1841132b66d" ++"checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" ++"checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" ++"checksum region 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "448e868c6e4cfddfa49b6a72c95906c04e8547465e9536575b95c70a4044f856" ++"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" ++"checksum rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf" ++"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" ++"checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" ++"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" ++"checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" ++"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" ++"checksum scroll 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "abb2332cb595d33f7edd5700f4cbf94892e680c7f0ae56adab58a35190b66cb1" ++"checksum scroll_derive 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8584eea9b9ff42825b46faf46a8c24d2cff13ec152fa2a50df788b87c07ee28" ++"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" ++"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" ++"checksum serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd" ++"checksum serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "4b133a43a1ecd55d4086bd5b4dc6c1751c68b1bfbeba7a5040442022c7e7c02e" ++"checksum serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "2f72eb2a68a7dc3f9a691bfda9305a1c017a6215e5a4545c258500d2099a37c2" ++"checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" ++"checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" ++"checksum smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecf3b85f68e8abaa7555aa5abdb1153079387e60b718283d732f03897fcfc86" ++"checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" ++"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" ++"checksum string-interner 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd710eadff449a1531351b0e43eb81ea404336fa2f56c777427ab0e32a4cf183" ++"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" ++"checksum strsim 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "032c03039aae92b350aad2e3779c352e104d919cb192ba2fabbd7b831ce4f0f6" ++"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" ++"checksum synstructure 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f085a5855930c0441ca1288cf044ea4aecf4f43a91668abdb870b4ba546a203" ++"checksum target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6f4c118a7a38378f305a9e111fcb2f7f838c0be324bfb31a77ea04f7f6e684b4" ++"checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" ++"checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" ++"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" ++"checksum thiserror 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f9fb62ff737e573b1e677459bea6fd023cd5d6e868c3242d3cdf3ef2f0554824" ++"checksum thiserror-impl 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "24069c0ba08aab54289d6a25f5036d94afc61e1538bbc42ae5501df141c9027d" ++"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" ++"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" ++"checksum toml 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "01d1404644c8b12b16bfcffa4322403a91a451584daaaa7c28d3152e6cbc98cf" ++"checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" ++"checksum trybuild 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "e6851bf8351876984fbab8a2391de6378947b898410d8714edd12164d2137127" ++"checksum typemap 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "653be63c80a3296da5551e1bfd2cca35227e13cdd08c6668903ae2f4f77aa1f6" ++"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" ++"checksum unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1967f4cdfc355b37fd76d2a954fb2ed3871034eb4f26d60537d88795cfc332a9" ++"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" ++"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" ++"checksum unindent 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "63f18aa3b0e35fed5a0048f029558b1518095ffe2a0a31fb87c93dece93a4993" ++"checksum unsafe-any 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f30360d7979f5e9c6e6cea48af192ea8fab4afb3cf72597154b8f08935bc9c7f" ++"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" ++"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" ++"checksum version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" ++"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" ++"checksum walrus 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85ce93ab0c27412ba41d509f2410fa575ecbfdb4a6aba0e02e79e12c09745485" ++"checksum walrus-macro 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8757b0da38353d55a9687f4dee68a8f441f980dd36e16ab07d6e6c673f505f76" ++"checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" ++"checksum wasm-webidl-bindings 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b5cae185868c6038a48f487b9af3766ee0c68d4a85fa3610c3a0522092b3cec1" ++"checksum wasmparser 0.39.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e5083b449454f7de0b15f131eee17de54b5a71dcb9adcf11df2b2f78fad0cd82" ++"checksum wast 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "86b52202bd73a756b216bbfea019991ff317b1e5f22677da5cef2964696a3245" ++"checksum wat 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "80db13d155bab63db0f19c24a0e12bf60c3fe346edba8da508ba6962e08c137b" ++"checksum which 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "240a31163872f7e8e49f35b42b58485e35355b07eb009d9f3686733541339a69" ++"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" ++"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" ++"checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" ++"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" ++"checksum wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "96f5016b18804d24db43cebf3c77269e7569b8954a8464501c216cc5e070eaa9" ++"checksum zstd 0.5.1+zstd.1.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5c5d978b793ae64375b80baf652919b148f6a496ac8802922d9999f5a553194f" ++"checksum zstd-safe 2.0.3+zstd.1.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bee25eac9753cfedd48133fa1736cbd23b774e253d89badbeac7d12b23848d3f" ++"checksum zstd-sys 1.4.15+zstd.1.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "89719b034dc22d240d5b407fb0a3fe6d29952c181cff9a9f95c0bd40b4f8f7d8" diff --git a/nix/wasmtime/default.nix b/nix/wasmtime/default.nix new file mode 100644 index 00000000000..7b263b5c9aa --- /dev/null +++ b/nix/wasmtime/default.nix @@ -0,0 +1,31 @@ +{ rustPlatform, fetchFromGitHub, lib, python, cmake, llvmPackages, clang, stdenv, darwin }: + +rustPlatform.buildRustPackage { + pname = "wasmtime"; + version = "20191111"; + + src = fetchFromGitHub { + owner = "CraneStation"; + repo = "wasmtime"; + rev = "0006a2af954eba74c79885cb1fe8cdeb68f531c1"; + sha256 = "0lf3pdkjxcrjmjic7xxyjl5dka3arxi809sp9hm4hih5p2fhf2gw"; + fetchSubmodules = true; + }; + + cargoSha256 = "0mnwaipa2az3vpgbz4m9siz6bfyhmzwz174k678cv158m7mxx12f"; + + cargoPatches = [ ./cargo-lock.patch ]; + + nativeBuildInputs = [ python cmake clang ]; + buildInputs = [ llvmPackages.libclang ] ++ + lib.optionals stdenv.isDarwin [ darwin.apple_sdk.frameworks.Security ]; + LIBCLANG_PATH = "${llvmPackages.libclang}/lib"; + + meta = with lib; { + description = "Standalone JIT-style runtime for WebAsssembly, using Cranelift"; + homepage = https://github.com/CraneStation/wasmtime; + license = licenses.asl20; + maintainers = [ maintainers.matthewbauer ]; + platforms = platforms.unix; + }; +} diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 354b4b77d1b..a9b4963aa38 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -663,44 +663,6 @@ module RTS = struct E.add_func_import env "rts" "find_field" [I32Type; I32Type; I32Type; I32Type; I32Type] [I32Type]; E.add_func_import env "rts" "skip_fields" [I32Type; I32Type; I32Type; I32Type] [] - let system_exports env = - E.add_export env (nr { - name = Wasm.Utf8.decode "alloc_bytes"; - edesc = nr (FuncExport (nr (E.built_in env "alloc_bytes"))) - }); - let bigint_trap_fi = E.add_fun env "bigint_trap" ( - Func.of_body env [] [] (fun env -> - E.trap_with env "bigint function error" - ) - ) in - E.add_export env (nr { - name = Wasm.Utf8.decode "bigint_trap"; - edesc = nr (FuncExport (nr bigint_trap_fi)) - }); - let idl_trap_fi = E.add_fun env "idl_trap" ( - Func.of_body env ["str", I32Type; "len", I32Type] [] (fun env -> - let get_str = G.i (LocalGet (nr 0l)) in - let get_len = G.i (LocalGet (nr 1l)) in - get_str ^^ get_len ^^ - match E.mode env with - | Flags.AncientMode -> - E.call_import env "data" "externalize" ^^ - E.call_import env "test" "print" ^^ - G.i Unreachable - | Flags.ICMode -> - E.call_import env "ic" "trap" ^^ - G.i Unreachable - | Flags.StubMode -> - E.call_import env "ic0" "trap" ^^ - G.i Unreachable - | Flags.WasmMode -> G.i Unreachable - ) - ) in - E.add_export env (nr { - name = Wasm.Utf8.decode "idl_trap"; - edesc = nr (FuncExport (nr idl_trap_fi)) - }) - end (* RTS *) module Heap = struct @@ -3107,7 +3069,9 @@ module Dfinity = struct E.add_func_import env "func" "externalize" [I32Type] [I32Type]; E.add_func_import env "func" "bind_i32" [I32Type; I32Type] [I32Type]; E.add_func_import env "func" "bind_ref" [I32Type; I32Type] [I32Type] - | _ -> () + | Flags.WASIMode -> + E.add_func_import env "wasi_unstable" "fd_write" [I32Type; I32Type; I32Type; I32Type] [I32Type]; + | Flags.WasmMode -> () let system_call env modname funcname = E.call_import env modname funcname @@ -3128,22 +3092,74 @@ module Dfinity = struct let compile_databuf_of_bytes env (bytes : string) = Blob.lit env bytes ^^ compile_databuf_of_text env - let prim_print env = + let rec print_ptr_len env = match E.mode env with - | Flags.WasmMode -> G.i Drop - | Flags.ICMode -> - Func.share_code1 env "print_text" ("str", I32Type) [] (fun env get_str -> - get_str ^^ Blob.payload_ptr_unskewed ^^ - get_str ^^ Heap.load_field (Blob.len_field) ^^ - system_call env "debug" "print" + | Flags.WasmMode -> G.i Drop ^^ G.i Drop + | Flags.ICMode -> system_call env "debug" "print" + | Flags.StubMode -> system_call env "ic0" "debug_print" + | Flags.WASIMode -> + Func.share_code2 env "print_ptr" (("ptr", I32Type), ("len", I32Type)) [] (fun env get_ptr get_len -> + Stack.with_words env "io_vec" 6l (fun get_iovec_ptr -> + (* We use the iovec functionality to append a newline *) + get_iovec_ptr ^^ + get_ptr ^^ + G.i (Store {ty = I32Type; align = 2; offset = 0l; sz = None}) ^^ + + get_iovec_ptr ^^ + get_len ^^ + G.i (Store {ty = I32Type; align = 2; offset = 4l; sz = None}) ^^ + + get_iovec_ptr ^^ + get_iovec_ptr ^^ compile_add_const 16l ^^ + G.i (Store {ty = I32Type; align = 2; offset = 8l; sz = None}) ^^ + + get_iovec_ptr ^^ + compile_unboxed_const 1l ^^ + G.i (Store {ty = I32Type; align = 2; offset = 12l; sz = None}) ^^ + + get_iovec_ptr ^^ + compile_unboxed_const (Int32.of_int (Char.code '\n')) ^^ + G.i (Store {ty = I32Type; align = 0; offset = 16l; sz = Some Wasm.Memory.Pack8}) ^^ + + (* Call fd_write twice to work around + https://github.com/bytecodealliance/wasmtime/issues/629 + *) + + compile_unboxed_const 1l (* stdout *) ^^ + get_iovec_ptr ^^ + compile_unboxed_const 1l (* one string segments (2 doesnt work) *) ^^ + get_iovec_ptr ^^ compile_add_const 20l ^^ (* out for bytes written, we ignore that *) + E.call_import env "wasi_unstable" "fd_write" ^^ + G.i Drop ^^ + + compile_unboxed_const 1l (* stdout *) ^^ + get_iovec_ptr ^^ compile_add_const 8l ^^ + compile_unboxed_const 1l (* one string segments *) ^^ + get_iovec_ptr ^^ compile_add_const 20l ^^ (* out for bytes written, we ignore that *) + E.call_import env "wasi_unstable" "fd_write" ^^ + G.i Drop + ) ) - | Flags.StubMode -> - Func.share_code1 env "print_text" ("str", I32Type) [] (fun env get_str -> - get_str ^^ Blob.payload_ptr_unskewed ^^ - get_str ^^ Heap.load_field (Blob.len_field) ^^ - system_call env "ic0" "debug_print" + | Flags.AncientMode -> + Func.share_code2 env "print_ptr" (("ptr", I32Type), ("len", I32Type)) [] (fun env get_ptr get_len -> + let (set_blob, get_blob) = new_local env "blob" in + get_len ^^ Blob.alloc env ^^ set_blob ^^ + + get_blob ^^ Blob.payload_ptr_unskewed ^^ + get_ptr ^^ + get_len ^^ + Heap.memcpy env ^^ + + get_blob ^^ + print_text env ) + + and print_text env = + match E.mode env with | Flags.AncientMode -> + (* The recursion goes the other wary in the AncientMode. + This can be removed once we get rid of the ancient mode + *) Func.share_code1 env "print_text" ("str", I32Type) [] (fun env get_str -> get_str ^^ Blob.lit env "\n" ^^ @@ -3151,15 +3167,21 @@ module Dfinity = struct compile_databuf_of_text env ^^ system_call env "test" "print" ) + | _ -> + Func.share_code1 env "print_text" ("str", I32Type) [] (fun env get_str -> + get_str ^^ Blob.payload_ptr_unskewed ^^ + get_str ^^ Heap.load_field (Blob.len_field) ^^ + print_ptr_len env + ) (* For debugging *) let compile_static_print env s = - Blob.lit env s ^^ prim_print env + Blob.lit env s ^^ print_text env let _compile_println_int env = - system_call env "test" "show_i32" ^^ - system_call env "test" "print" ^^ - compile_static_print env "\n" + system_call env "test" "show_i32" ^^ + system_call env "test" "print" ^^ + compile_static_print env "\n" let ic_trap env = match E.mode env with @@ -3177,13 +3199,17 @@ module Dfinity = struct let trap_with env s = match E.mode env with | Flags.WasmMode -> G.i Unreachable - | Flags.AncientMode -> compile_static_print env (s ^ "\n") ^^ G.i Unreachable + | Flags.AncientMode | Flags.WASIMode -> compile_static_print env (s ^ "\n") ^^ G.i Unreachable | Flags.ICMode | Flags.StubMode -> Blob.lit env s ^^ ic_trap_str env ^^ G.i Unreachable let default_exports env = (* these exports seem to be wanted by the hypervisor/v8 *) E.add_export env (nr { - name = Wasm.Utf8.decode "mem"; + name = Wasm.Utf8.decode ( + match E.mode env with + | Flags.WASIMode -> "memory" + | _ -> "mem" + ); edesc = nr (MemoryExport (nr 0l)) }); E.add_export env (nr { @@ -3348,13 +3374,44 @@ module Dfinity = struct (* simply tuple canister name and function name *) Blob.lit env name ^^ Tuple.from_stack env 2 - | Flags.WasmMode -> assert false + | Flags.WasmMode | Flags.WASIMode -> assert false let fail_assert env at = E.trap_with env (Printf.sprintf "assertion failed at %s" (string_of_region at)) end (* Dfinity *) +module RTS_Exports = struct + let system_exports env = + E.add_export env (nr { + name = Wasm.Utf8.decode "alloc_bytes"; + edesc = nr (FuncExport (nr (E.built_in env "alloc_bytes"))) + }); + let bigint_trap_fi = E.add_fun env "bigint_trap" ( + Func.of_body env [] [] (fun env -> + E.trap_with env "bigint function error" + ) + ) in + E.add_export env (nr { + name = Wasm.Utf8.decode "bigint_trap"; + edesc = nr (FuncExport (nr bigint_trap_fi)) + }); + let idl_trap_fi = E.add_fun env "idl_trap" ( + Func.of_body env ["str", I32Type; "len", I32Type] [] (fun env -> + let get_str = G.i (LocalGet (nr 0l)) in + let get_len = G.i (LocalGet (nr 1l)) in + get_str ^^ get_len ^^ Dfinity.print_ptr_len env ^^ + G.i Unreachable + ) + ) in + E.add_export env (nr { + name = Wasm.Utf8.decode "idl_trap"; + edesc = nr (FuncExport (nr idl_trap_fi)) + }) + +end (* RTS_Exports *) + + module OrthogonalPersistence = struct (* This module implements the code that fakes orthogonal persistence *) @@ -4352,7 +4409,7 @@ module Serialization = struct get_data_start ^^ get_data_size - | Flags.WasmMode -> assert false + | Flags.WasmMode | Flags.WASIMode -> assert false ) let deserialize env ts = @@ -5196,7 +5253,7 @@ module FuncDec = struct mk_body env ae1 ^^ message_cleanup env sort )) - | Flags.WasmMode, _ -> assert false + | (Flags.WasmMode | Flags.WASIMode), _ -> assert false let declare_dfinity_type env has_closure has_reply fi = if E.mode env = Flags.AncientMode then @@ -6577,7 +6634,7 @@ and compile_exp (env : E.t) ae exp = | OtherPrim "print", [e] -> SR.unit, compile_exp_vanilla env ae e ^^ - Dfinity.prim_print env + Dfinity.print_text env | OtherPrim "decodeUTF8", [e] -> SR.UnboxedTuple 2, compile_exp_vanilla env ae e ^^ @@ -7238,6 +7295,7 @@ and find_prelude_names env = (* Create a throw-away environment *) let env0 = E.mk_global (E.mode env) None (E.get_prelude env) (fun _ _ -> G.i Unreachable) 0l in Heap.register_globals env0; + Stack.register_globals env0; Dfinity.system_imports env0; RTS.system_imports env0; let env1 = E.mk_fun_env env0 0l 0 in @@ -7330,7 +7388,7 @@ and actor_lit outer_env this ds fs at = Dfinity.system_imports mod_env; RTS.system_imports mod_env; - RTS.system_exports mod_env; + RTS_Exports.system_exports mod_env; Dfinity.register_reply mod_env; @@ -7500,7 +7558,7 @@ let compile mode module_name rts (prelude : Ir.prog) (progs : Ir.prog list) : Wa Dfinity.system_imports env; RTS.system_imports env; - RTS.system_exports env; + RTS_Exports.system_exports env; Dfinity.register_reply env; @@ -7512,6 +7570,6 @@ let compile mode module_name rts (prelude : Ir.prog) (progs : Ir.prog list) : Wa Dfinity.export_start_stub env; None | Flags.ICMode | Flags.StubMode -> Dfinity.export_start env start_fi; None - | Flags.WasmMode -> Some (nr start_fi) in + | Flags.WasmMode | Flags.WASIMode-> Some (nr start_fi) in conclude_module env module_name start_fi_o diff --git a/src/exes/moc.ml b/src/exes/moc.ml index 9cdb4b1d719..d9ac5ac96f6 100644 --- a/src/exes/moc.ml +++ b/src/exes/moc.ml @@ -71,6 +71,9 @@ let argspec = Arg.align "-no-system-api", Arg.Unit (fun () -> Flags.(compile_mode := WasmMode)), " do not import any system API"; + "-wasi-system-api", + Arg.Unit (fun () -> Flags.(compile_mode := WASIMode)), + " use the WASI system API (wasmtime)"; "-ancient-system-api", Arg.Unit (fun () -> Flags.(compile_mode := AncientMode)), " use the ancient DFINITY system API (dvm)"; diff --git a/src/mo_config/flags.ml b/src/mo_config/flags.ml index 8d6c84da0f7..832e37a4ee5 100644 --- a/src/mo_config/flags.ml +++ b/src/mo_config/flags.ml @@ -1,6 +1,6 @@ (* common flags for the moc compiler *) -type compile_mode = WasmMode | AncientMode | ICMode | StubMode +type compile_mode = WasmMode | AncientMode | ICMode | StubMode | WASIMode let trace = ref false let verbose = ref false diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index f9fb360c6f9..9880ad95317 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -74,6 +74,7 @@ let warn env at fmt = let flag_of_compile_mode mode = match mode with | Flags.ICMode -> "" + | Flags.WASIMode -> " and flag -wasi-system-api" | Flags.WasmMode -> " and flag -no-system-api" | Flags.AncientMode -> " and flag -ancient-system-api" | Flags.StubMode -> " and flag -stub-system-api" diff --git a/test/run-drun/ok/idl-bad.drun-run.ok b/test/run-drun/ok/idl-bad.drun-run.ok index 401133f7f50..2bc34fb40a7 100644 --- a/test/run-drun/ok/idl-bad.drun-run.ok +++ b/test/run-drun/ok/idl-bad.drun-run.ok @@ -1,2 +1,3 @@ ingress(0) System -Err: IC0503: Canister 42 trapped explicitly: IDL error: missing magic bytes +debug.print: IDL error: missing magic bytes +Err: IC0502: Canister 42 trapped: unreachable diff --git a/test/run-release/ok/debug.wasm-run.ok b/test/run-release/ok/debug.wasm-run.ok new file mode 100644 index 00000000000..f5e5eab0d0a --- /dev/null +++ b/test/run-release/ok/debug.wasm-run.ok @@ -0,0 +1,2 @@ +This should appear +This should appear too diff --git a/test/run-stub/ok/idl-bad.ic-stub-run.ok b/test/run-stub/ok/idl-bad.ic-stub-run.ok index d6c66bd8bf5..55f13f8b448 100644 --- a/test/run-stub/ok/idl-bad.ic-stub-run.ok +++ b/test/run-stub/ok/idl-bad.ic-stub-run.ok @@ -3,4 +3,5 @@ → install ← completed → query foo(0x4e4f544449444c) -← rejected (RC_CANISTER_ERROR): canister trapped: EvalTrapError :0.1 "canister trapped explicitly: IDL error: missing magic bytes" +IDL error: missing magic bytes +← rejected (RC_CANISTER_ERROR): canister trapped: EvalTrapError :0.1 "unreachable executed" diff --git a/test/run.sh b/test/run.sh index 5405dbfd43b..269a7855fb4 100755 --- a/test/run.sh +++ b/test/run.sh @@ -22,7 +22,7 @@ function realpath() { ACCEPT=no -API=wasm +API=wasi IDL=no RELEASE=no EXTRA_MOC_FLAGS= @@ -30,7 +30,7 @@ MOC=${MOC:-$(realpath $(dirname $0)/../src/moc)} MO_LD=${MO_LD:-$(realpath $(dirname $0)/../src/mo-ld)} DIDC=${DIDC:-$(realpath $(dirname $0)/../src/didc)} export MO_LD -WASM=${WASM:-wasm} +WASMTIME=${WASMTIME:-wasmtime} DVM_WRAPPER=$(realpath $(dirname $0)/dvm.sh) DRUN_WRAPPER=$(realpath $(dirname $0)/drun-wrapper.sh) IC_STUB_RUN=${IC_STUB_RUN:-ic-stub-run} @@ -69,6 +69,7 @@ done if [ $API = "wasm" ]; then EXTRA_MOC_FLAGS=-no-system-api; fi if [ $API = "ancient" ]; then EXTRA_MOC_FLAGS=-ancient-system-api; fi +if [ $API = "wasi" ]; then EXTRA_MOC_FLAGS=-wasi-system-api; fi if [ $API = "stub" ]; then EXTRA_MOC_FLAGS=-stub-system-api; fi if [ $RELEASE = "yes" ]; then MOC_FLAGS=--release; fi @@ -93,6 +94,8 @@ function normalize () { sed 's,/tmp/.*ic.[^/]*,/tmp/ic.XXX,g' | sed 's,/build/.*ic.[^/]*,/tmp/ic.XXX,g' | sed 's/^.*run-dfinity\/\.\.\/drun.sh: line/drun.sh: line/g' | + sed 's/trap at 0x[a-f0-9]*/trap at 0x___:/g' | + sed 's/source location: @[a-f0-9]*/source location: @___:/g' | cat > $1.norm mv $1.norm $1 fi @@ -243,8 +246,12 @@ do elif [ $API = stub ] then DRUN=$IC_STUB_RUN run ic-stub-run $DRUN_WRAPPER $out/$base.wasm $base.mo + elif [ $API = wasi ] + then + run wasm-run $WASMTIME --disable-cache $out/$base.wasm else - run wasm-run $WASM $out/$base.wasm + echo "Unkonwn API $API" + exit 1 fi fi fi diff --git a/test/run/idlHash.mo b/test/run/idlHash.mo index e9582b817c5..756885df980 100644 --- a/test/run/idlHash.mo +++ b/test/run/idlHash.mo @@ -12,3 +12,5 @@ testHash("id", 23515); testHash("description", 1595738364); testHash("short_name", 3261810734); testHash("Hi ☃", 1419229646); + +//SKIP comp diff --git a/test/run/ok/array-bounds.wasm-run.ok b/test/run/ok/array-bounds.wasm-run.ok index 988f0569732..943ff8632a4 100644 --- a/test/run/ok/array-bounds.wasm-run.ok +++ b/test/run/ok/array-bounds.wasm-run.ok @@ -1 +1,8 @@ -_out/array-bounds.wasm:0x___: runtime trap: unreachable executed +Array index out of bounds + +Error: failed to process main module `_out/array-bounds.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/run/ok/assertFalse.wasm-run.ok b/test/run/ok/assertFalse.wasm-run.ok index e03ec0ea09e..6e98ff9615e 100644 --- a/test/run/ok/assertFalse.wasm-run.ok +++ b/test/run/ok/assertFalse.wasm-run.ok @@ -1 +1,8 @@ -_out/assertFalse.wasm:0x___: runtime trap: unreachable executed +assertion failed at assertFalse.mo:1.1-1.14 + +Error: failed to process main module `_out/assertFalse.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/run/ok/char-high-surrogate-trap.wasm-run.ok b/test/run/ok/char-high-surrogate-trap.wasm-run.ok index f8094194cdc..972c78476b8 100644 --- a/test/run/ok/char-high-surrogate-trap.wasm-run.ok +++ b/test/run/ok/char-high-surrogate-trap.wasm-run.ok @@ -1 +1,8 @@ -_out/char-high-surrogate-trap.wasm:0x___: runtime trap: unreachable executed +codepoint out of range + +Error: failed to process main module `_out/char-high-surrogate-trap.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/run/ok/char-low-surrogate-trap.wasm-run.ok b/test/run/ok/char-low-surrogate-trap.wasm-run.ok index af88b01be92..0d0f8a91520 100644 --- a/test/run/ok/char-low-surrogate-trap.wasm-run.ok +++ b/test/run/ok/char-low-surrogate-trap.wasm-run.ok @@ -1 +1,8 @@ -_out/char-low-surrogate-trap.wasm:0x___: runtime trap: unreachable executed +codepoint out of range + +Error: failed to process main module `_out/char-low-surrogate-trap.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/run/ok/char-trap.wasm-run.ok b/test/run/ok/char-trap.wasm-run.ok index 1aa5d820042..29f16842009 100644 --- a/test/run/ok/char-trap.wasm-run.ok +++ b/test/run/ok/char-trap.wasm-run.ok @@ -1 +1,8 @@ -_out/char-trap.wasm:0x___: runtime trap: unreachable executed +codepoint out of range + +Error: failed to process main module `_out/char-trap.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/run/ok/conversions.wasm-run.ok b/test/run/ok/conversions.wasm-run.ok new file mode 100644 index 00000000000..976fbb2ff3e --- /dev/null +++ b/test/run/ok/conversions.wasm-run.ok @@ -0,0 +1,10 @@ +-2_147_483_648 +-2_147_483_647 +-42 +-1 +0 ++42 ++2_147_483_647 +-2_147_483_648 +-2 +-1 diff --git a/test/run/ok/debug.wasm-run.ok b/test/run/ok/debug.wasm-run.ok new file mode 100644 index 00000000000..dfe5154ed76 --- /dev/null +++ b/test/run/ok/debug.wasm-run.ok @@ -0,0 +1 @@ +This is for debugging only diff --git a/test/run/ok/for.wasm-run.ok b/test/run/ok/for.wasm-run.ok new file mode 100644 index 00000000000..b033488efab --- /dev/null +++ b/test/run/ok/for.wasm-run.ok @@ -0,0 +1,11 @@ +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 diff --git a/test/run/ok/idlHash.wasm-run.ok b/test/run/ok/idlHash.wasm-run.ok deleted file mode 100644 index 4ba414f67c5..00000000000 --- a/test/run/ok/idlHash.wasm-run.ok +++ /dev/null @@ -1 +0,0 @@ -_out/idlHash.wasm:0x___: runtime trap: unreachable executed diff --git a/test/run/ok/issue120.comp.ok b/test/run/ok/issue120.comp.ok new file mode 100644 index 00000000000..d563599b0a1 --- /dev/null +++ b/test/run/ok/issue120.comp.ok @@ -0,0 +1,6 @@ +issue120.mo:2.8-2.11: type error, shared function has non-shared parameter type + Bar = actor {} +type + Bar = actor {} +is or contains non-shared type + actor {} diff --git a/test/run/ok/idlHash.wasm-run.ret.ok b/test/run/ok/issue120.comp.ret.ok similarity index 100% rename from test/run/ok/idlHash.wasm-run.ret.ok rename to test/run/ok/issue120.comp.ret.ok diff --git a/test/run/ok/issue36.wasm-run.ok b/test/run/ok/issue36.wasm-run.ok index 1f1f72b3800..445adce17bc 100644 --- a/test/run/ok/issue36.wasm-run.ok +++ b/test/run/ok/issue36.wasm-run.ok @@ -1 +1,8 @@ -_out/issue36.wasm:0x___: runtime trap: unreachable executed +TODO: compile_lit + +Error: failed to process main module `_out/issue36.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/run/ok/overflow.wasm-run.ok b/test/run/ok/overflow.wasm-run.ok index 7c22e438c43..8ef1d926e00 100644 --- a/test/run/ok/overflow.wasm-run.ok +++ b/test/run/ok/overflow.wasm-run.ok @@ -1 +1,6 @@ -_out/overflow.wasm:0x___: runtime trap: integer divide by zero +Error: failed to process main module `_out/overflow.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: integer divide by zero, source location: @___: + diff --git a/test/run/ok/print.run-ir.ok b/test/run/ok/print.run-ir.ok new file mode 100644 index 00000000000..e03a4526ac4 --- /dev/null +++ b/test/run/ok/print.run-ir.ok @@ -0,0 +1,2 @@ +Hello World! +How are you? diff --git a/test/run/ok/print.run-low.ok b/test/run/ok/print.run-low.ok new file mode 100644 index 00000000000..e03a4526ac4 --- /dev/null +++ b/test/run/ok/print.run-low.ok @@ -0,0 +1,2 @@ +Hello World! +How are you? diff --git a/test/run/ok/print.run.ok b/test/run/ok/print.run.ok new file mode 100644 index 00000000000..e03a4526ac4 --- /dev/null +++ b/test/run/ok/print.run.ok @@ -0,0 +1,2 @@ +Hello World! +How are you? diff --git a/test/run/ok/print.wasm-run.ok b/test/run/ok/print.wasm-run.ok new file mode 100644 index 00000000000..e03a4526ac4 --- /dev/null +++ b/test/run/ok/print.wasm-run.ok @@ -0,0 +1,2 @@ +Hello World! +How are you? diff --git a/test/run/ok/variants.wasm-run.ok b/test/run/ok/variants.wasm-run.ok new file mode 100644 index 00000000000..f00580c4060 --- /dev/null +++ b/test/run/ok/variants.wasm-run.ok @@ -0,0 +1,2 @@ +3 +1 diff --git a/test/run/ok/words.wasm-run.ok b/test/run/ok/words.wasm-run.ok new file mode 100644 index 00000000000..2e9de829814 --- /dev/null +++ b/test/run/ok/words.wasm-run.ok @@ -0,0 +1,270 @@ +8_912_765 + ++8_912_765 +18_446_744_073_700_638_851 + +-8_912_765 +18_446_744_073_700_638_850 + +-8_912_766 +8_917_332 + ++8_917_332 +8_908_198 + ++8_908_198 +31_969 + ++31_969 +652 + ++652 +2_548 + ++2_548 +20_857_489 + ++20_857_489 +4_437 + ++4_437 +8_912_895 + ++8_912_895 +8_908_458 + ++8_908_458 +584_576 + ++584_576 +35 + ++35 +826_339_054_743_125_951 + ++826_339_054_743_125_951 +18_446_744_073_709_551_614 + +-2 +18_120_161_623_845_830_591 + +-326_582_449_863_721_025 +1_140_833_920 + ++1_140_833_920 +18_014_398_509_482_053_630 + +-432_345_564_227_497_986 +61 + ++61 +49 + ++49 +5 + ++5 +set +clear +set +8_912_765 + ++8_912_765 +4_286_054_531 + +-8_912_765 +4_286_054_530 + +-8_912_766 +8_917_332 + ++8_917_332 +8_908_198 + ++8_908_198 +31_969 + ++31_969 +652 + ++652 +2_548 + ++2_548 +20_857_489 + ++20_857_489 +4_437 + ++4_437 +8_912_895 + ++8_912_895 +8_908_458 + ++8_908_458 +584_576 + ++584_576 +35 + ++35 +192_397_053 + ++192_397_053 +4_294_967_294 + +-2 +4_218_928_893 + +-76_038_403 +1_140_833_920 + ++1_140_833_920 +4_194_373_630 + +-100_593_666 +29 + ++29 +17 + ++17 +5 + ++5 +set +clear +set +55_734 + +-9_802 +9_802 + ++9_802 +9_801 + ++9_801 +60_301 + +-5_235 +51_167 + +-14_369 +31_969 + ++31_969 +652 + ++652 +930 + ++930 +17_041 + ++17_041 +4_502 + ++4_502 +55_799 + +-9_737 +51_297 + +-14_239 +60_288 + +-5_248 +35 + ++35 +8_190 + ++8_190 +65_534 + +-2 +56_172 + +-9_364 +28_083 + ++28_083 +13 + ++13 +1 + ++1 +5 + ++5 +set +clear +set +34 + ++34 +222 + +-34 +221 + +-35 +101 + ++101 +223 + +-33 +213 + +-43 +9 + ++9 +34 + ++34 +137 + +-119 +2 + ++2 +99 + ++99 +97 + ++97 +128 + +-128 +0 + +0 +30 + ++30 +254 + +-2 +17 + ++17 +68 + ++68 +5 + ++5 +0 + +0 +3 + ++3 +set +clear +set diff --git a/test/run/print.mo b/test/run/print.mo new file mode 100644 index 00000000000..f30cb8444ee --- /dev/null +++ b/test/run/print.mo @@ -0,0 +1,2 @@ +debugPrint("Hello World!"); +debugPrint("How are you?"); diff --git a/test/trap/ok/addInt16-lower.wasm-run.ok b/test/trap/ok/addInt16-lower.wasm-run.ok index a53f2af670e..66f5dd7070f 100644 --- a/test/trap/ok/addInt16-lower.wasm-run.ok +++ b/test/trap/ok/addInt16-lower.wasm-run.ok @@ -1 +1,8 @@ -_out/addInt16-lower.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/addInt16-lower.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/addInt16-upper.wasm-run.ok b/test/trap/ok/addInt16-upper.wasm-run.ok index 79ac5c6da61..81472dc98e6 100644 --- a/test/trap/ok/addInt16-upper.wasm-run.ok +++ b/test/trap/ok/addInt16-upper.wasm-run.ok @@ -1 +1,8 @@ -_out/addInt16-upper.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/addInt16-upper.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/addInt32-lower.wasm-run.ok b/test/trap/ok/addInt32-lower.wasm-run.ok index 7301a614e60..cd7e4fbd4f8 100644 --- a/test/trap/ok/addInt32-lower.wasm-run.ok +++ b/test/trap/ok/addInt32-lower.wasm-run.ok @@ -1 +1,8 @@ -_out/addInt32-lower.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/addInt32-lower.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/addInt32-upper.wasm-run.ok b/test/trap/ok/addInt32-upper.wasm-run.ok index e7274c12aea..a9762336fc4 100644 --- a/test/trap/ok/addInt32-upper.wasm-run.ok +++ b/test/trap/ok/addInt32-upper.wasm-run.ok @@ -1 +1,8 @@ -_out/addInt32-upper.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/addInt32-upper.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/addInt64-lower.wasm-run.ok b/test/trap/ok/addInt64-lower.wasm-run.ok index da9469b2efd..4f7d61c40c1 100644 --- a/test/trap/ok/addInt64-lower.wasm-run.ok +++ b/test/trap/ok/addInt64-lower.wasm-run.ok @@ -1 +1,8 @@ -_out/addInt64-lower.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/addInt64-lower.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/addInt64-upper.wasm-run.ok b/test/trap/ok/addInt64-upper.wasm-run.ok index 7d7fd9d5525..c7b874379e6 100644 --- a/test/trap/ok/addInt64-upper.wasm-run.ok +++ b/test/trap/ok/addInt64-upper.wasm-run.ok @@ -1 +1,8 @@ -_out/addInt64-upper.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/addInt64-upper.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/addInt8-lower.wasm-run.ok b/test/trap/ok/addInt8-lower.wasm-run.ok index 8a3153abe4d..5c7f24a3211 100644 --- a/test/trap/ok/addInt8-lower.wasm-run.ok +++ b/test/trap/ok/addInt8-lower.wasm-run.ok @@ -1 +1,8 @@ -_out/addInt8-lower.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/addInt8-lower.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/addInt8-upper.wasm-run.ok b/test/trap/ok/addInt8-upper.wasm-run.ok index 885fc9bb190..227c8e7e58e 100644 --- a/test/trap/ok/addInt8-upper.wasm-run.ok +++ b/test/trap/ok/addInt8-upper.wasm-run.ok @@ -1 +1,8 @@ -_out/addInt8-upper.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/addInt8-upper.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/addNat16.wasm-run.ok b/test/trap/ok/addNat16.wasm-run.ok index 211d569d615..3bf65cf51be 100644 --- a/test/trap/ok/addNat16.wasm-run.ok +++ b/test/trap/ok/addNat16.wasm-run.ok @@ -1 +1,8 @@ -_out/addNat16.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/addNat16.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/addNat32.wasm-run.ok b/test/trap/ok/addNat32.wasm-run.ok index a8bbc4d6459..5b0915d0018 100644 --- a/test/trap/ok/addNat32.wasm-run.ok +++ b/test/trap/ok/addNat32.wasm-run.ok @@ -1 +1,8 @@ -_out/addNat32.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/addNat32.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/addNat64.wasm-run.ok b/test/trap/ok/addNat64.wasm-run.ok index 83259226b95..314b6a5d3b7 100644 --- a/test/trap/ok/addNat64.wasm-run.ok +++ b/test/trap/ok/addNat64.wasm-run.ok @@ -1 +1,8 @@ -_out/addNat64.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/addNat64.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/addNat8.wasm-run.ok b/test/trap/ok/addNat8.wasm-run.ok index 6c45c588c69..ba41678f4e8 100644 --- a/test/trap/ok/addNat8.wasm-run.ok +++ b/test/trap/ok/addNat8.wasm-run.ok @@ -1 +1,8 @@ -_out/addNat8.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/addNat8.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/divInt16.wasm-run.ok b/test/trap/ok/divInt16.wasm-run.ok index 5c10a0140c7..5876e2b0c3d 100644 --- a/test/trap/ok/divInt16.wasm-run.ok +++ b/test/trap/ok/divInt16.wasm-run.ok @@ -1 +1,6 @@ -_out/divInt16.wasm:0x___: runtime trap: unreachable executed +Error: failed to process main module `_out/divInt16.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/divInt32.wasm-run.ok b/test/trap/ok/divInt32.wasm-run.ok index c590a95e715..00be4caef22 100644 --- a/test/trap/ok/divInt32.wasm-run.ok +++ b/test/trap/ok/divInt32.wasm-run.ok @@ -1 +1,6 @@ -_out/divInt32.wasm:0x___: runtime trap: integer overflow +Error: failed to process main module `_out/divInt32.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: integer overflow, source location: @___: + diff --git a/test/trap/ok/divInt64.wasm-run.ok b/test/trap/ok/divInt64.wasm-run.ok index a83505797dc..340edc6b0f4 100644 --- a/test/trap/ok/divInt64.wasm-run.ok +++ b/test/trap/ok/divInt64.wasm-run.ok @@ -1 +1,6 @@ -_out/divInt64.wasm:0x___: runtime trap: integer overflow +Error: failed to process main module `_out/divInt64.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: integer overflow, source location: @___: + diff --git a/test/trap/ok/divInt8.wasm-run.ok b/test/trap/ok/divInt8.wasm-run.ok index cc30751f738..6ea2a31d06a 100644 --- a/test/trap/ok/divInt8.wasm-run.ok +++ b/test/trap/ok/divInt8.wasm-run.ok @@ -1 +1,6 @@ -_out/divInt8.wasm:0x___: runtime trap: unreachable executed +Error: failed to process main module `_out/divInt8.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/mulInt16-lower.wasm-run.ok b/test/trap/ok/mulInt16-lower.wasm-run.ok index 8d58f77d6bf..6e55364e9ab 100644 --- a/test/trap/ok/mulInt16-lower.wasm-run.ok +++ b/test/trap/ok/mulInt16-lower.wasm-run.ok @@ -1 +1,8 @@ -_out/mulInt16-lower.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/mulInt16-lower.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/mulInt16-upper.wasm-run.ok b/test/trap/ok/mulInt16-upper.wasm-run.ok index eec850eeb1d..c02d0722720 100644 --- a/test/trap/ok/mulInt16-upper.wasm-run.ok +++ b/test/trap/ok/mulInt16-upper.wasm-run.ok @@ -1 +1,8 @@ -_out/mulInt16-upper.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/mulInt16-upper.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/mulInt32-lower.wasm-run.ok b/test/trap/ok/mulInt32-lower.wasm-run.ok index 67a3d477bdd..dbff0ee6f35 100644 --- a/test/trap/ok/mulInt32-lower.wasm-run.ok +++ b/test/trap/ok/mulInt32-lower.wasm-run.ok @@ -1 +1,8 @@ -_out/mulInt32-lower.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/mulInt32-lower.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/mulInt32-upper.wasm-run.ok b/test/trap/ok/mulInt32-upper.wasm-run.ok index c11c7fda881..8b8ba7b5a2f 100644 --- a/test/trap/ok/mulInt32-upper.wasm-run.ok +++ b/test/trap/ok/mulInt32-upper.wasm-run.ok @@ -1 +1,8 @@ -_out/mulInt32-upper.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/mulInt32-upper.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/mulInt64-lower.wasm-run.ok b/test/trap/ok/mulInt64-lower.wasm-run.ok index 57661b67d09..ab1ef3a5bb0 100644 --- a/test/trap/ok/mulInt64-lower.wasm-run.ok +++ b/test/trap/ok/mulInt64-lower.wasm-run.ok @@ -1 +1,8 @@ -_out/mulInt64-lower.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/mulInt64-lower.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/mulInt64-upper.wasm-run.ok b/test/trap/ok/mulInt64-upper.wasm-run.ok index 2dad24b7f71..872febf92eb 100644 --- a/test/trap/ok/mulInt64-upper.wasm-run.ok +++ b/test/trap/ok/mulInt64-upper.wasm-run.ok @@ -1 +1,8 @@ -_out/mulInt64-upper.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/mulInt64-upper.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/mulInt8-lower.wasm-run.ok b/test/trap/ok/mulInt8-lower.wasm-run.ok index ee3b90af24b..3ec6c499100 100644 --- a/test/trap/ok/mulInt8-lower.wasm-run.ok +++ b/test/trap/ok/mulInt8-lower.wasm-run.ok @@ -1 +1,8 @@ -_out/mulInt8-lower.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/mulInt8-lower.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/mulInt8-upper.wasm-run.ok b/test/trap/ok/mulInt8-upper.wasm-run.ok index 30c1be3a4eb..2b9d0f59008 100644 --- a/test/trap/ok/mulInt8-upper.wasm-run.ok +++ b/test/trap/ok/mulInt8-upper.wasm-run.ok @@ -1 +1,8 @@ -_out/mulInt8-upper.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/mulInt8-upper.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/mulNat16.wasm-run.ok b/test/trap/ok/mulNat16.wasm-run.ok index 9b4c3b7176e..c747f9ed52b 100644 --- a/test/trap/ok/mulNat16.wasm-run.ok +++ b/test/trap/ok/mulNat16.wasm-run.ok @@ -1 +1,8 @@ -_out/mulNat16.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/mulNat16.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/mulNat32.wasm-run.ok b/test/trap/ok/mulNat32.wasm-run.ok index 717a6e28d74..f1597b57be5 100644 --- a/test/trap/ok/mulNat32.wasm-run.ok +++ b/test/trap/ok/mulNat32.wasm-run.ok @@ -1 +1,8 @@ -_out/mulNat32.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/mulNat32.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/mulNat64.wasm-run.ok b/test/trap/ok/mulNat64.wasm-run.ok index bb34cc33252..321ddaac2a9 100644 --- a/test/trap/ok/mulNat64.wasm-run.ok +++ b/test/trap/ok/mulNat64.wasm-run.ok @@ -1 +1,8 @@ -_out/mulNat64.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/mulNat64.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/mulNat8.wasm-run.ok b/test/trap/ok/mulNat8.wasm-run.ok index 2b9666200cd..ec4a78110b2 100644 --- a/test/trap/ok/mulNat8.wasm-run.ok +++ b/test/trap/ok/mulNat8.wasm-run.ok @@ -1 +1,8 @@ -_out/mulNat8.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/mulNat8.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/outrange-int16-lower.wasm-run.ok b/test/trap/ok/outrange-int16-lower.wasm-run.ok index 9fd79b192f9..7d213d546ff 100644 --- a/test/trap/ok/outrange-int16-lower.wasm-run.ok +++ b/test/trap/ok/outrange-int16-lower.wasm-run.ok @@ -1 +1,8 @@ -_out/outrange-int16-lower.wasm:0x___: runtime trap: unreachable executed +losing precision + +Error: failed to process main module `_out/outrange-int16-lower.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/outrange-int16-negation.wasm-run.ok b/test/trap/ok/outrange-int16-negation.wasm-run.ok index b292eceb663..9b283bc29b3 100644 --- a/test/trap/ok/outrange-int16-negation.wasm-run.ok +++ b/test/trap/ok/outrange-int16-negation.wasm-run.ok @@ -1 +1,8 @@ -_out/outrange-int16-negation.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/outrange-int16-negation.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/outrange-int16-upper.wasm-run.ok b/test/trap/ok/outrange-int16-upper.wasm-run.ok index 03b9e36d669..faa0f23873e 100644 --- a/test/trap/ok/outrange-int16-upper.wasm-run.ok +++ b/test/trap/ok/outrange-int16-upper.wasm-run.ok @@ -1 +1,8 @@ -_out/outrange-int16-upper.wasm:0x___: runtime trap: unreachable executed +losing precision + +Error: failed to process main module `_out/outrange-int16-upper.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/outrange-int32-lower.wasm-run.ok b/test/trap/ok/outrange-int32-lower.wasm-run.ok index a630c1ce2a7..660d4c55346 100644 --- a/test/trap/ok/outrange-int32-lower.wasm-run.ok +++ b/test/trap/ok/outrange-int32-lower.wasm-run.ok @@ -1 +1,8 @@ -_out/outrange-int32-lower.wasm:0x___: runtime trap: unreachable executed +losing precision + +Error: failed to process main module `_out/outrange-int32-lower.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/outrange-int32-negation.wasm-run.ok b/test/trap/ok/outrange-int32-negation.wasm-run.ok index 82b07835bd3..172647b70c6 100644 --- a/test/trap/ok/outrange-int32-negation.wasm-run.ok +++ b/test/trap/ok/outrange-int32-negation.wasm-run.ok @@ -1 +1,8 @@ -_out/outrange-int32-negation.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/outrange-int32-negation.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/outrange-int32-upper.wasm-run.ok b/test/trap/ok/outrange-int32-upper.wasm-run.ok index ffc335345f7..db07dd973c3 100644 --- a/test/trap/ok/outrange-int32-upper.wasm-run.ok +++ b/test/trap/ok/outrange-int32-upper.wasm-run.ok @@ -1 +1,8 @@ -_out/outrange-int32-upper.wasm:0x___: runtime trap: unreachable executed +losing precision + +Error: failed to process main module `_out/outrange-int32-upper.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/outrange-int64-lower.wasm-run.ok b/test/trap/ok/outrange-int64-lower.wasm-run.ok index a485fbae838..d98ac51337c 100644 --- a/test/trap/ok/outrange-int64-lower.wasm-run.ok +++ b/test/trap/ok/outrange-int64-lower.wasm-run.ok @@ -1 +1,8 @@ -_out/outrange-int64-lower.wasm:0x___: runtime trap: unreachable executed +losing precision + +Error: failed to process main module `_out/outrange-int64-lower.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/outrange-int64-negation.wasm-run.ok b/test/trap/ok/outrange-int64-negation.wasm-run.ok index 1238f5ad4ec..efe18ad0a40 100644 --- a/test/trap/ok/outrange-int64-negation.wasm-run.ok +++ b/test/trap/ok/outrange-int64-negation.wasm-run.ok @@ -1 +1,8 @@ -_out/outrange-int64-negation.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/outrange-int64-negation.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/outrange-int64-upper.wasm-run.ok b/test/trap/ok/outrange-int64-upper.wasm-run.ok index 0dc740b1173..5829cc9b2ee 100644 --- a/test/trap/ok/outrange-int64-upper.wasm-run.ok +++ b/test/trap/ok/outrange-int64-upper.wasm-run.ok @@ -1 +1,8 @@ -_out/outrange-int64-upper.wasm:0x___: runtime trap: unreachable executed +losing precision + +Error: failed to process main module `_out/outrange-int64-upper.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/outrange-int8-lower.wasm-run.ok b/test/trap/ok/outrange-int8-lower.wasm-run.ok index a6754b244ca..797ec799d07 100644 --- a/test/trap/ok/outrange-int8-lower.wasm-run.ok +++ b/test/trap/ok/outrange-int8-lower.wasm-run.ok @@ -1 +1,8 @@ -_out/outrange-int8-lower.wasm:0x___: runtime trap: unreachable executed +losing precision + +Error: failed to process main module `_out/outrange-int8-lower.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/outrange-int8-negation.wasm-run.ok b/test/trap/ok/outrange-int8-negation.wasm-run.ok index d0518678619..05b412f4453 100644 --- a/test/trap/ok/outrange-int8-negation.wasm-run.ok +++ b/test/trap/ok/outrange-int8-negation.wasm-run.ok @@ -1 +1,8 @@ -_out/outrange-int8-negation.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/outrange-int8-negation.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/outrange-int8-upper.wasm-run.ok b/test/trap/ok/outrange-int8-upper.wasm-run.ok index 3366993f2a4..5c141ce09a6 100644 --- a/test/trap/ok/outrange-int8-upper.wasm-run.ok +++ b/test/trap/ok/outrange-int8-upper.wasm-run.ok @@ -1 +1,8 @@ -_out/outrange-int8-upper.wasm:0x___: runtime trap: unreachable executed +losing precision + +Error: failed to process main module `_out/outrange-int8-upper.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/outrange-nat16.wasm-run.ok b/test/trap/ok/outrange-nat16.wasm-run.ok index 3e31c22ece7..18dd920aed5 100644 --- a/test/trap/ok/outrange-nat16.wasm-run.ok +++ b/test/trap/ok/outrange-nat16.wasm-run.ok @@ -1 +1,8 @@ -_out/outrange-nat16.wasm:0x___: runtime trap: unreachable executed +losing precision + +Error: failed to process main module `_out/outrange-nat16.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/outrange-nat32.wasm-run.ok b/test/trap/ok/outrange-nat32.wasm-run.ok index e3d912613a5..4fd28c74b8c 100644 --- a/test/trap/ok/outrange-nat32.wasm-run.ok +++ b/test/trap/ok/outrange-nat32.wasm-run.ok @@ -1 +1,8 @@ -_out/outrange-nat32.wasm:0x___: runtime trap: unreachable executed +losing precision + +Error: failed to process main module `_out/outrange-nat32.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/outrange-nat64.wasm-run.ok b/test/trap/ok/outrange-nat64.wasm-run.ok index c2173dffda9..3722f18faf1 100644 --- a/test/trap/ok/outrange-nat64.wasm-run.ok +++ b/test/trap/ok/outrange-nat64.wasm-run.ok @@ -1 +1,8 @@ -_out/outrange-nat64.wasm:0x___: runtime trap: unreachable executed +losing precision + +Error: failed to process main module `_out/outrange-nat64.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/outrange-nat8.wasm-run.ok b/test/trap/ok/outrange-nat8.wasm-run.ok index e64bc25b4c7..cadbc4eef86 100644 --- a/test/trap/ok/outrange-nat8.wasm-run.ok +++ b/test/trap/ok/outrange-nat8.wasm-run.ok @@ -1 +1,8 @@ -_out/outrange-nat8.wasm:0x___: runtime trap: unreachable executed +losing precision + +Error: failed to process main module `_out/outrange-nat8.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/powInt32-lower.wasm-run.ok b/test/trap/ok/powInt32-lower.wasm-run.ok index 1686c95bc0c..226791f6cca 100644 --- a/test/trap/ok/powInt32-lower.wasm-run.ok +++ b/test/trap/ok/powInt32-lower.wasm-run.ok @@ -1 +1,8 @@ -_out/powInt32-lower.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/powInt32-lower.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/powInt32-raise-neg.wasm-run.ok b/test/trap/ok/powInt32-raise-neg.wasm-run.ok index 81aa3d12b63..afc323030d3 100644 --- a/test/trap/ok/powInt32-raise-neg.wasm-run.ok +++ b/test/trap/ok/powInt32-raise-neg.wasm-run.ok @@ -1 +1,8 @@ -_out/powInt32-raise-neg.wasm:0x___: runtime trap: unreachable executed +negative power + +Error: failed to process main module `_out/powInt32-raise-neg.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/powInt32-upper.wasm-run.ok b/test/trap/ok/powInt32-upper.wasm-run.ok index 6f29285d1d2..b9417bd905f 100644 --- a/test/trap/ok/powInt32-upper.wasm-run.ok +++ b/test/trap/ok/powInt32-upper.wasm-run.ok @@ -1 +1,8 @@ -_out/powInt32-upper.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/powInt32-upper.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/powInt64-lower-fast.wasm-run.ok b/test/trap/ok/powInt64-lower-fast.wasm-run.ok index 76a7f113984..fb1c13ee042 100644 --- a/test/trap/ok/powInt64-lower-fast.wasm-run.ok +++ b/test/trap/ok/powInt64-lower-fast.wasm-run.ok @@ -1 +1,8 @@ -_out/powInt64-lower-fast.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/powInt64-lower-fast.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/powInt64-lower-slow.wasm-run.ok b/test/trap/ok/powInt64-lower-slow.wasm-run.ok index 5a7fce1bb95..85490c02c8b 100644 --- a/test/trap/ok/powInt64-lower-slow.wasm-run.ok +++ b/test/trap/ok/powInt64-lower-slow.wasm-run.ok @@ -1 +1,8 @@ -_out/powInt64-lower-slow.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/powInt64-lower-slow.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/powInt64-raise-neg.wasm-run.ok b/test/trap/ok/powInt64-raise-neg.wasm-run.ok index c9999dacc32..e232f0211e7 100644 --- a/test/trap/ok/powInt64-raise-neg.wasm-run.ok +++ b/test/trap/ok/powInt64-raise-neg.wasm-run.ok @@ -1 +1,8 @@ -_out/powInt64-raise-neg.wasm:0x___: runtime trap: unreachable executed +negative power + +Error: failed to process main module `_out/powInt64-raise-neg.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/powInt64-upper-fast.wasm-run.ok b/test/trap/ok/powInt64-upper-fast.wasm-run.ok index 98fa7675e78..b8c1d2707f9 100644 --- a/test/trap/ok/powInt64-upper-fast.wasm-run.ok +++ b/test/trap/ok/powInt64-upper-fast.wasm-run.ok @@ -1 +1,8 @@ -_out/powInt64-upper-fast.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/powInt64-upper-fast.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/powInt64-upper-slow.wasm-run.ok b/test/trap/ok/powInt64-upper-slow.wasm-run.ok index 01093b45a72..edfd23fafb7 100644 --- a/test/trap/ok/powInt64-upper-slow.wasm-run.ok +++ b/test/trap/ok/powInt64-upper-slow.wasm-run.ok @@ -1 +1,8 @@ -_out/powInt64-upper-slow.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/powInt64-upper-slow.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/powInt8-lower.wasm-run.ok b/test/trap/ok/powInt8-lower.wasm-run.ok index 7385b83b26c..0d2d17b9853 100644 --- a/test/trap/ok/powInt8-lower.wasm-run.ok +++ b/test/trap/ok/powInt8-lower.wasm-run.ok @@ -1 +1,8 @@ -_out/powInt8-lower.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/powInt8-lower.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/powInt8-raise-neg.wasm-run.ok b/test/trap/ok/powInt8-raise-neg.wasm-run.ok index e6cd6aa2c71..00ac4b9efc9 100644 --- a/test/trap/ok/powInt8-raise-neg.wasm-run.ok +++ b/test/trap/ok/powInt8-raise-neg.wasm-run.ok @@ -1 +1,8 @@ -_out/powInt8-raise-neg.wasm:0x___: runtime trap: unreachable executed +negative power + +Error: failed to process main module `_out/powInt8-raise-neg.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/powInt8-upper.wasm-run.ok b/test/trap/ok/powInt8-upper.wasm-run.ok index a765c82a85c..90937a6e45b 100644 --- a/test/trap/ok/powInt8-upper.wasm-run.ok +++ b/test/trap/ok/powInt8-upper.wasm-run.ok @@ -1 +1,8 @@ -_out/powInt8-upper.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/powInt8-upper.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/powNat16.wasm-run.ok b/test/trap/ok/powNat16.wasm-run.ok index a1b622733f6..1125671217f 100644 --- a/test/trap/ok/powNat16.wasm-run.ok +++ b/test/trap/ok/powNat16.wasm-run.ok @@ -1 +1,8 @@ -_out/powNat16.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/powNat16.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/powNat32.wasm-run.ok b/test/trap/ok/powNat32.wasm-run.ok index b23b3b070ed..a0f41f7fa06 100644 --- a/test/trap/ok/powNat32.wasm-run.ok +++ b/test/trap/ok/powNat32.wasm-run.ok @@ -1 +1,8 @@ -_out/powNat32.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/powNat32.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/powNat64.wasm-run.ok b/test/trap/ok/powNat64.wasm-run.ok index 569b2f79dd0..2312bf471c7 100644 --- a/test/trap/ok/powNat64.wasm-run.ok +++ b/test/trap/ok/powNat64.wasm-run.ok @@ -1 +1,8 @@ -_out/powNat64.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/powNat64.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/powNat8.wasm-run.ok b/test/trap/ok/powNat8.wasm-run.ok index 8343057bb39..478841e9cd6 100644 --- a/test/trap/ok/powNat8.wasm-run.ok +++ b/test/trap/ok/powNat8.wasm-run.ok @@ -1 +1,8 @@ -_out/powNat8.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/powNat8.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/subInt16-lower.wasm-run.ok b/test/trap/ok/subInt16-lower.wasm-run.ok index a1b0d29f73e..10f94d0bb9f 100644 --- a/test/trap/ok/subInt16-lower.wasm-run.ok +++ b/test/trap/ok/subInt16-lower.wasm-run.ok @@ -1 +1,8 @@ -_out/subInt16-lower.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/subInt16-lower.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/subInt16-upper.wasm-run.ok b/test/trap/ok/subInt16-upper.wasm-run.ok index 2382e27d4e8..d6dee45676d 100644 --- a/test/trap/ok/subInt16-upper.wasm-run.ok +++ b/test/trap/ok/subInt16-upper.wasm-run.ok @@ -1 +1,8 @@ -_out/subInt16-upper.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/subInt16-upper.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/subInt32-lower.wasm-run.ok b/test/trap/ok/subInt32-lower.wasm-run.ok index c7aaeeb70fa..9745a378cda 100644 --- a/test/trap/ok/subInt32-lower.wasm-run.ok +++ b/test/trap/ok/subInt32-lower.wasm-run.ok @@ -1 +1,8 @@ -_out/subInt32-lower.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/subInt32-lower.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/subInt32-upper.wasm-run.ok b/test/trap/ok/subInt32-upper.wasm-run.ok index 7ef9e891064..367bb8caa3c 100644 --- a/test/trap/ok/subInt32-upper.wasm-run.ok +++ b/test/trap/ok/subInt32-upper.wasm-run.ok @@ -1 +1,8 @@ -_out/subInt32-upper.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/subInt32-upper.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/subInt64-lower.wasm-run.ok b/test/trap/ok/subInt64-lower.wasm-run.ok index e5e991412ee..e18a4ca4d22 100644 --- a/test/trap/ok/subInt64-lower.wasm-run.ok +++ b/test/trap/ok/subInt64-lower.wasm-run.ok @@ -1 +1,8 @@ -_out/subInt64-lower.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/subInt64-lower.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/subInt64-upper.wasm-run.ok b/test/trap/ok/subInt64-upper.wasm-run.ok index 0c8ea0c1929..49cf86c7fe0 100644 --- a/test/trap/ok/subInt64-upper.wasm-run.ok +++ b/test/trap/ok/subInt64-upper.wasm-run.ok @@ -1 +1,8 @@ -_out/subInt64-upper.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/subInt64-upper.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/subInt8-lower.wasm-run.ok b/test/trap/ok/subInt8-lower.wasm-run.ok index 9ca860506a2..d739b3a12b3 100644 --- a/test/trap/ok/subInt8-lower.wasm-run.ok +++ b/test/trap/ok/subInt8-lower.wasm-run.ok @@ -1 +1,8 @@ -_out/subInt8-lower.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/subInt8-lower.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/subInt8-upper.wasm-run.ok b/test/trap/ok/subInt8-upper.wasm-run.ok index 52d843336fb..001d37b54b2 100644 --- a/test/trap/ok/subInt8-upper.wasm-run.ok +++ b/test/trap/ok/subInt8-upper.wasm-run.ok @@ -1 +1,8 @@ -_out/subInt8-upper.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/subInt8-upper.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/subNat16.wasm-run.ok b/test/trap/ok/subNat16.wasm-run.ok index f7323ad6059..519021fd938 100644 --- a/test/trap/ok/subNat16.wasm-run.ok +++ b/test/trap/ok/subNat16.wasm-run.ok @@ -1 +1,8 @@ -_out/subNat16.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/subNat16.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/subNat32.wasm-run.ok b/test/trap/ok/subNat32.wasm-run.ok index 508878f6747..1a07c6b8b01 100644 --- a/test/trap/ok/subNat32.wasm-run.ok +++ b/test/trap/ok/subNat32.wasm-run.ok @@ -1 +1,8 @@ -_out/subNat32.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/subNat32.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/subNat64-slow.wasm-run.ok b/test/trap/ok/subNat64-slow.wasm-run.ok index b7e53fd8ac8..89836cdf57c 100644 --- a/test/trap/ok/subNat64-slow.wasm-run.ok +++ b/test/trap/ok/subNat64-slow.wasm-run.ok @@ -1 +1,8 @@ -_out/subNat64-slow.wasm:0x___: runtime trap: unreachable executed +Natural subtraction underflow + +Error: failed to process main module `_out/subNat64-slow.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/subNat64.wasm-run.ok b/test/trap/ok/subNat64.wasm-run.ok index 8cede90807f..5c30141a3cc 100644 --- a/test/trap/ok/subNat64.wasm-run.ok +++ b/test/trap/ok/subNat64.wasm-run.ok @@ -1 +1,8 @@ -_out/subNat64.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/subNat64.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + diff --git a/test/trap/ok/subNat8.wasm-run.ok b/test/trap/ok/subNat8.wasm-run.ok index 7fd00f66dcb..7f0bcec3b56 100644 --- a/test/trap/ok/subNat8.wasm-run.ok +++ b/test/trap/ok/subNat8.wasm-run.ok @@ -1 +1,8 @@ -_out/subNat8.wasm:0x___: runtime trap: unreachable executed +arithmetic overflow + +Error: failed to process main module `_out/subNat8.wasm` + +Caused by: + 0: Instantiation failed during setup + 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: + From f771b6bd02412bc4d759546f70610d96f33ad256 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 25 Nov 2019 18:23:06 +0100 Subject: [PATCH 0707/1176] Collect RTS stats (#925) * Collect RTS stats namely: * current size of the _dynamic_ heap * total number of bytes ever allocated * number of outstanding callbacks One testcase checks that allocating a 10000 byte array allocates 10008 bytes. The other checks that callbacks are freed as they are returned. Which currently is not happening yet, but I will work on that next (test driven development). To be able to test that I am allowing first-class asyncs on the stub API. It is not IR-type-safe yet until https://github.com/dfinity-lab/motoko/pull/860 lands. * Update test output * Update src/codegen/compile.ml Co-Authored-By: Claudio Russo --- src/codegen/compile.ml | 185 +++++++++++------- src/mo_frontend/typing.ml | 4 +- src/mo_values/prim.ml | 3 + src/prelude/prelude.ml | 3 + test/run-stub/count-callbacks.mo | 33 ++++ .../ok/count-callbacks.ic-stub-run.ok | 17 ++ test/run-stub/ok/rts-stats.ic-stub-run.ok | 5 + test/run-stub/ok/unsupported.comp.ok | 4 - test/run-stub/rts-stats.mo | 19 ++ 9 files changed, 198 insertions(+), 75 deletions(-) create mode 100644 test/run-stub/count-callbacks.mo create mode 100644 test/run-stub/ok/count-callbacks.ic-stub-run.ok create mode 100644 test/run-stub/ok/rts-stats.ic-stub-run.ok create mode 100644 test/run-stub/rts-stats.mo diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index a9b4963aa38..2e2be5e6f0b 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -671,20 +671,36 @@ module Heap = struct (* Memory addresses are 32 bit (I32Type). *) let word_size = 4l - let register_globals env = - (* end-of-heap pointer, we set this to __heap_base upon start *) - E.add_global32 env "end_of_heap" Mutable 0xDEADBEEFl + (* The heap base global can only be used late, see conclude_module + and GHC.register *) + let get_heap_base env = + G.i (GlobalGet (nr (E.get_global env "__heap_base"))) (* We keep track of the end of the used heap in this global, and bump it if we allocate stuff. This is the actual memory offset, not-skewed yet *) - let get_heap_base env = - G.i (GlobalGet (nr (E.get_global env "__heap_base"))) let get_heap_ptr env = G.i (GlobalGet (nr (E.get_global env "end_of_heap"))) let set_heap_ptr env = G.i (GlobalSet (nr (E.get_global env "end_of_heap"))) let get_skewed_heap_ptr env = get_heap_ptr env ^^ compile_add_const ptr_skew + let register_globals env = + (* end-of-heap pointer, we set this to __heap_base upon start *) + E.add_global32 env "end_of_heap" Mutable 0xDEADBEEFl; + + (* counter for total allocations *) + E.add_global64 env "allocations" Mutable 0L + + let count_allocations env = + (* assumes number of allocated bytes on the stack *) + G.i (Convert (Wasm.Values.I64 I64Op.ExtendUI32)) ^^ + G.i (GlobalGet (nr (E.get_global env "allocations"))) ^^ + G.i (Binary (Wasm.Values.I64 I64Op.Add)) ^^ + G.i (GlobalSet (nr (E.get_global env "allocations"))) + + let get_total_allocation env = + G.i (GlobalGet (nr (E.get_global env "allocations"))) + (* Page allocation. Ensures that the memory up to the given unskewed pointer is allocated. *) let grow_memory env = Func.share_code1 env "grow_memory" ("ptr", I32Type) [] (fun env get_ptr -> @@ -712,16 +728,22 @@ module Heap = struct (* Dynamic allocation *) let dyn_alloc_words env = Func.share_code1 env "alloc_words" ("n", I32Type) [I32Type] (fun env get_n -> - (* expects the size (in words), returns the pointer *) + (* expects the size (in words), returns the skewed pointer *) (* return the current pointer (skewed) *) get_skewed_heap_ptr env ^^ + (* Cound allocated bytes *) + get_n ^^ compile_mul_const word_size ^^ + count_allocations env ^^ + (* Update heap pointer *) get_heap_ptr env ^^ get_n ^^ compile_mul_const word_size ^^ G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ set_heap_ptr env ^^ + + (* grow memory if needed *) get_heap_ptr env ^^ grow_memory env ) @@ -800,7 +822,6 @@ module Heap = struct ) ) - end (* Heap *) module Stack = struct @@ -970,6 +991,9 @@ module ClosureTable = struct load_unskewed_ptr ) + let get_outstanding_callbacks env = + get_counter + end (* ClosureTable *) module Bool = struct @@ -4613,71 +4637,81 @@ module GC = struct get_begin_from_space get_begin_to_space get_end_to_space ) - let register env (end_of_static_space : int32) = Func.define_built_in env "collect" [] [] (fun env -> - if not gc_enabled then G.nop else - - (* Copy all roots. *) - let (set_begin_from_space, get_begin_from_space) = new_local env "begin_from_space" in - let (set_begin_to_space, get_begin_to_space) = new_local env "begin_to_space" in - let (set_end_to_space, get_end_to_space) = new_local env "end_to_space" in - - Heap.get_heap_base env ^^ compile_add_const ptr_skew ^^ set_begin_from_space ^^ - Heap.get_skewed_heap_ptr env ^^ set_begin_to_space ^^ - Heap.get_skewed_heap_ptr env ^^ set_end_to_space ^^ - - - (* Common arguments for evacuate *) - let evac get_ptr_loc = - get_begin_from_space ^^ - get_begin_to_space ^^ - get_end_to_space ^^ - get_ptr_loc ^^ - evacuate env ^^ - set_end_to_space in - - let evac_offset get_ptr_loc offset = - get_begin_from_space ^^ - get_begin_to_space ^^ - get_end_to_space ^^ - get_ptr_loc ^^ - evacuate_offset env offset ^^ - set_end_to_space in - - (* Go through the roots, and evacuate them *) - ClosureTable.get_counter ^^ - from_0_to_n env (fun get_i -> evac ( - get_i ^^ - compile_add_const 1l ^^ - compile_mul_const Heap.word_size ^^ - compile_add_const ClosureTable.loc ^^ - compile_add_const ptr_skew - )) ^^ - HeapTraversal.walk_heap_from_to env - (compile_unboxed_const Int32.(add ClosureTable.table_end ptr_skew)) - (compile_unboxed_const Int32.(add end_of_static_space ptr_skew)) - (fun get_x -> HeapTraversal.for_each_pointer env get_x evac evac_offset) ^^ - - (* Go through the to-space, and evacuate that. - Note that get_end_to_space changes as we go, but walk_heap_from_to can handle that. - *) - HeapTraversal.walk_heap_from_to env - get_begin_to_space - get_end_to_space - (fun get_x -> HeapTraversal.for_each_pointer env get_x evac evac_offset) ^^ - - (* Copy the to-space to the beginning of memory. *) - get_begin_from_space ^^ compile_add_const ptr_unskew ^^ - get_begin_to_space ^^ compile_add_const ptr_unskew ^^ - get_end_to_space ^^ get_begin_to_space ^^ G.i (Binary (Wasm.Values.I32 I32Op.Sub)) ^^ - Heap.memcpy env ^^ + let register env (end_of_static_space : int32) = + Func.define_built_in env "get_heap_size" [] [I32Type] (fun env -> + Heap.get_heap_ptr env ^^ + Heap.get_heap_base env ^^ + G.i (Binary (Wasm.Values.I32 I32Op.Sub)) + ); - (* Reset the heap pointer *) - get_begin_from_space ^^ compile_add_const ptr_unskew ^^ - get_end_to_space ^^ get_begin_to_space ^^ G.i (Binary (Wasm.Values.I32 I32Op.Sub)) ^^ - G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ - Heap.set_heap_ptr env + Func.define_built_in env "collect" [] [] (fun env -> + if not gc_enabled then G.nop else + + (* Copy all roots. *) + let (set_begin_from_space, get_begin_from_space) = new_local env "begin_from_space" in + let (set_begin_to_space, get_begin_to_space) = new_local env "begin_to_space" in + let (set_end_to_space, get_end_to_space) = new_local env "end_to_space" in + + Heap.get_heap_base env ^^ compile_add_const ptr_skew ^^ set_begin_from_space ^^ + Heap.get_skewed_heap_ptr env ^^ set_begin_to_space ^^ + Heap.get_skewed_heap_ptr env ^^ set_end_to_space ^^ + + + (* Common arguments for evacuate *) + let evac get_ptr_loc = + get_begin_from_space ^^ + get_begin_to_space ^^ + get_end_to_space ^^ + get_ptr_loc ^^ + evacuate env ^^ + set_end_to_space in + + let evac_offset get_ptr_loc offset = + get_begin_from_space ^^ + get_begin_to_space ^^ + get_end_to_space ^^ + get_ptr_loc ^^ + evacuate_offset env offset ^^ + set_end_to_space in + + (* Go through the roots, and evacuate them *) + ClosureTable.get_counter ^^ + from_0_to_n env (fun get_i -> evac ( + get_i ^^ + compile_add_const 1l ^^ + compile_mul_const Heap.word_size ^^ + compile_add_const ClosureTable.loc ^^ + compile_add_const ptr_skew + )) ^^ + HeapTraversal.walk_heap_from_to env + (compile_unboxed_const Int32.(add ClosureTable.table_end ptr_skew)) + (compile_unboxed_const Int32.(add end_of_static_space ptr_skew)) + (fun get_x -> HeapTraversal.for_each_pointer env get_x evac evac_offset) ^^ + + (* Go through the to-space, and evacuate that. + Note that get_end_to_space changes as we go, but walk_heap_from_to can handle that. + *) + HeapTraversal.walk_heap_from_to env + get_begin_to_space + get_end_to_space + (fun get_x -> HeapTraversal.for_each_pointer env get_x evac evac_offset) ^^ + + (* Copy the to-space to the beginning of memory. *) + get_begin_from_space ^^ compile_add_const ptr_unskew ^^ + get_begin_to_space ^^ compile_add_const ptr_unskew ^^ + get_end_to_space ^^ get_begin_to_space ^^ G.i (Binary (Wasm.Values.I32 I32Op.Sub)) ^^ + Heap.memcpy env ^^ + + (* Reset the heap pointer *) + get_begin_from_space ^^ compile_add_const ptr_unskew ^^ + get_end_to_space ^^ get_begin_to_space ^^ G.i (Binary (Wasm.Values.I32 I32Op.Sub)) ^^ + G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ + Heap.set_heap_ptr env ) + let get_heap_size env = + G.i (Call (nr (E.built_in env "get_heap_size"))) + end (* GC *) module VarLoc = struct @@ -6594,6 +6628,19 @@ and compile_exp (env : E.t) ae exp = SR.Vanilla, E.call_import env "rts" "version" + | OtherPrim "rts_heap_size", [] -> + SR.Vanilla, + GC.get_heap_size env ^^ Prim.prim_word32toNat env + + | OtherPrim "rts_total_allocation", [] -> + SR.Vanilla, + Heap.get_total_allocation env ^^ BigNum.from_word64 env + + | OtherPrim "rts_outstanding_callbacks", [] -> + SR.Vanilla, + ClosureTable.get_outstanding_callbacks env ^^ Prim.prim_word32toNat env + + | OtherPrim "idlHash", [e] -> SR.Vanilla, E.trap_with env "idlHash only implemented in interpreter " diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 9880ad95317..4816d139d19 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -778,7 +778,7 @@ and infer_exp'' env exp : T.typ = check_exp env t_arg exp2; if Type.is_shared_sort sort then begin if T.is_async t_ret && not (in_await env) then - error_in [Flags.ICMode; Flags.StubMode] env exp2.at + error_in [Flags.ICMode] env exp2.at "shared, async function must be called within an await expression"; error_in [Flags.ICMode] env exp1.at "calling a shared function not yet supported"; if not (T.concrete t_arg) then @@ -942,7 +942,7 @@ and infer_exp'' env exp : T.typ = | CallE (f, _, _) -> if not env.pre && (Call_conv.call_conv_of_typ f.note.note_typ).Call_conv.control = T.Returns then error_in [Flags.ICMode; Flags.StubMode] env f.at "expecting call to shared async function in await"; - | _ -> error_in [Flags.ICMode; Flags.StubMode] env exp1.at "argument to await must be a call expression"); + | _ -> error_in [Flags.ICMode] env exp1.at "argument to await must be a call expression"); (try T.as_async_sub t1 with Invalid_argument _ -> diff --git a/src/mo_values/prim.ml b/src/mo_values/prim.ml index e4c0fb5084a..4472a76aa7c 100644 --- a/src/mo_values/prim.ml +++ b/src/mo_values/prim.ml @@ -242,6 +242,9 @@ let prim = function in k (Text str) | "print" -> fun v k -> Printf.printf "%s\n%!" (as_text v); k unit | "rts_version" -> fun v k -> as_unit v; k (Text "0.1") + | "rts_heap_size" -> fun v k -> as_unit v; k (Int (Int.of_int 0)) + | "rts_total_allocation" -> fun v k -> as_unit v; k (Int (Int.of_int 0)) + | "rts_outstanding_callbacks" -> fun v k -> as_unit v; k (Int (Int.of_int 0)) | "idlHash" -> fun v k -> let s = as_text v in k (Word32 (Lib.Uint32.to_int32 (Idllib.IdlHash.idl_hash s))) | "decodeUTF8" -> fun v k -> let s = as_text v in diff --git a/src/prelude/prelude.ml b/src/prelude/prelude.ml index dd9337e2635..601b9792990 100644 --- a/src/prelude/prelude.ml +++ b/src/prelude/prelude.ml @@ -88,6 +88,9 @@ func debugPrintNat(x : Nat) { debugPrint (@text_of_Nat x) }; func debugPrintInt(x : Int) { debugPrint (@text_of_Int x) }; func debugPrintChar(x : Char) { debugPrint (charToText x) }; func rts_version() : Text { (prim "rts_version" : () -> Text) () }; +func rts_heap_size() : Nat { (prim "rts_heap_size" : () -> Nat) () }; +func rts_total_allocation() : Nat { (prim "rts_total_allocation" : () -> Nat) () }; +func rts_outstanding_callbacks() : Nat { (prim "rts_outstanding_callbacks" : () -> Nat) () }; // Hashing func hashInt(x : Int) : Word32 { diff --git a/test/run-stub/count-callbacks.mo b/test/run-stub/count-callbacks.mo new file mode 100644 index 00000000000..923c90c53a5 --- /dev/null +++ b/test/run-stub/count-callbacks.mo @@ -0,0 +1,33 @@ +actor a { + + public func ping() : async () { + debugPrint("ping! " # debug_show rts_outstanding_callbacks()); + }; + + public func go() = ignore async { + debugPrint("go 1: " # debug_show rts_outstanding_callbacks()); + let a1 = ping(); + debugPrint("go 1: " # debug_show rts_outstanding_callbacks()); + let a2 = ping(); + debugPrint("go 1: " # debug_show rts_outstanding_callbacks()); + let a3 = ping(); + debugPrint("go 1: " # debug_show rts_outstanding_callbacks()); + let a4 = ping(); + + debugPrint("go 1: " # debug_show rts_outstanding_callbacks()); + await a1; + debugPrint("go 2: " # debug_show rts_outstanding_callbacks()); + await a2; + debugPrint("go 3: " # debug_show rts_outstanding_callbacks()); + await a3; + debugPrint("go 4: " # debug_show rts_outstanding_callbacks()); + await a4; + debugPrint("go 5: " # debug_show rts_outstanding_callbacks()); + }; + + go(); +} + +//SKIP run +//SKIP run-low +//SKIP run-ir diff --git a/test/run-stub/ok/count-callbacks.ic-stub-run.ok b/test/run-stub/ok/count-callbacks.ic-stub-run.ok new file mode 100644 index 00000000000..8703025cdf0 --- /dev/null +++ b/test/run-stub/ok/count-callbacks.ic-stub-run.ok @@ -0,0 +1,17 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +go 1: 0 +go 1: 2 +go 1: 4 +go 1: 6 +go 1: 8 +ping! 8 +ping! 8 +ping! 8 +ping! 8 +go 2: 8 +go 3: 8 +go 4: 8 +go 5: 8 +← completed diff --git a/test/run-stub/ok/rts-stats.ic-stub-run.ok b/test/run-stub/ok/rts-stats.ic-stub-run.ok new file mode 100644 index 00000000000..a6f1dd30bd2 --- /dev/null +++ b/test/run-stub/ok/rts-stats.ic-stub-run.ok @@ -0,0 +1,5 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +Size and allocation delta: (10_008, 10_008) +← completed diff --git a/test/run-stub/ok/unsupported.comp.ok b/test/run-stub/ok/unsupported.comp.ok index 4f6b017c8a7..45c25dbe75d 100644 --- a/test/run-stub/ok/unsupported.comp.ok +++ b/test/run-stub/ok/unsupported.comp.ok @@ -14,10 +14,6 @@ is or contains non-shared type shared () -> async () unsupported.mo:8.31-8.53: type error, shared function types are non-shared. (This is a limitation of the current version and flag -stub-system-api.) -unsupported.mo:19.19-19.21: type error, shared, async function must be called within an await expression - (This is a limitation of the current version and flag -stub-system-api.) -unsupported.mo:28.8-28.9: type error, argument to await must be a call expression - (This is a limitation of the current version and flag -stub-system-api.) unsupported.mo:32.17-32.29: type error, unsupported async block (This is a limitation of the current version and flag -stub-system-api.) unsupported.mo:4.5-4.41: type error, a shared function cannot be private diff --git a/test/run-stub/rts-stats.mo b/test/run-stub/rts-stats.mo new file mode 100644 index 00000000000..a8a27f0c150 --- /dev/null +++ b/test/run-stub/rts-stats.mo @@ -0,0 +1,19 @@ +let s0 = rts_heap_size(); +let a0 = rts_total_allocation(); +ignore(Array_init<()>(2500, ())); +let s1 = rts_heap_size(); +let a1 = rts_total_allocation(); + +// the following are too likey to change to be included in the test output +// debugPrint("Size and allocation before: " # debug_show (s0, a0)); +// debugPrint("Size and allocation after: " # debug_show (s1, a1)); + +// this should be rather stable unless the array representation changes +debugPrint("Size and allocation delta: " # debug_show (s1-s0, a1-a0)); +assert (s1-s0 == 10008); +assert (a1-a0 == 10008); + +// no point running these in the interpreter +//SKIP run +//SKIP run-low +//SKIP run-ir From 1db35edd76648b8ab4bdbe9c54fe95331a505d6e Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 25 Nov 2019 22:17:44 +0100 Subject: [PATCH 0708/1176] Pass function and actor references as data (#913) this implements the design in https://github.com/dfinity-lab/motoko/pull/883 For the forseeable future, actor references are `Blob`s, and function references are `(blob, text)` tuples. So this uses these types in the IDL. This allows us to pass any kind of reference we have. An important step to get rid of the `dvm` dependency. This also introduces a type `Blob` for packed arrays of word8. This is, so far, only used in the backend, but it might come handy anyways (e.g. should we want to pull the IDL encoding/decoding into an IR pass). This does _not_ update the Motoko-to-IDL export, which is actually tricky; see discussion in #913. --- src/codegen/compile.ml | 94 ++++++++++++++----- src/mo_frontend/coverage.ml | 1 + src/mo_frontend/typing.ml | 4 +- src/mo_idl/mo_to_idl.ml | 43 ++++----- src/mo_types/arrange_type.ml | 1 + src/mo_types/type.ml | 25 ++--- src/mo_types/type.mli | 1 + test/idl/.gitignore | 1 + test/mo-idl/fun_self_arg.mo | 2 + test/mo-idl/ok/fun_self_arg.did.ok | 6 ++ test/run-drun/ok/idl-func.comp.ok | 8 -- test/run-drun/ok/idl-func.comp.ret.ok | 1 - test/run-drun/ok/idl-func.drun-run.ok | 3 + test/run-drun/ok/unsupported.comp.ok | 32 ------- test/run-stub/ok/idl-func.comp.ok | 8 -- test/run-stub/ok/idl-func.comp.ret.ok | 1 - test/run-stub/ok/idl-func.ic-stub-run.ok | 8 ++ .../ok/pass-references.ic-stub-run.ok | 7 ++ test/run-stub/ok/pass-references.run-ir.ok | 3 + test/run-stub/ok/pass-references.run-low.ok | 3 + test/run-stub/ok/pass-references.run.ok | 3 + test/run-stub/ok/unsupported.comp.ok | 32 ------- test/run-stub/pass-references.mo | 22 +++++ test/run/ok/issue120.comp.ok | 6 -- test/run/ok/issue120.comp.ret.ok | 1 - 25 files changed, 160 insertions(+), 156 deletions(-) create mode 100644 test/idl/.gitignore create mode 100644 test/mo-idl/fun_self_arg.mo create mode 100644 test/mo-idl/ok/fun_self_arg.did.ok delete mode 100644 test/run-drun/ok/idl-func.comp.ok delete mode 100644 test/run-drun/ok/idl-func.comp.ret.ok create mode 100644 test/run-drun/ok/idl-func.drun-run.ok delete mode 100644 test/run-stub/ok/idl-func.comp.ok delete mode 100644 test/run-stub/ok/idl-func.comp.ret.ok create mode 100644 test/run-stub/ok/idl-func.ic-stub-run.ok create mode 100644 test/run-stub/ok/pass-references.ic-stub-run.ok create mode 100644 test/run-stub/ok/pass-references.run-ir.ok create mode 100644 test/run-stub/ok/pass-references.run-low.ok create mode 100644 test/run-stub/ok/pass-references.run.ok create mode 100644 test/run-stub/pass-references.mo delete mode 100644 test/run/ok/issue120.comp.ok delete mode 100644 test/run/ok/issue120.comp.ret.ok diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 2e2be5e6f0b..c78f3a542cb 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -3716,6 +3716,19 @@ module Serialization = struct (fun (h1,_) (h2,_) -> Lib.Uint32.compare h1 h2) (List.map (fun f -> (Idllib.Escape.unescape_hash f.Type.lab, f)) fs) + (* The code below does not work on all Motoko types, but only certain “raw + types”. In particular, type definitions have to be removed (using Type.normalize). + But also, at least for now, actor and function references are represented + as data, https://github.com/dfinity-lab/motoko/pull/883 + *) + let raw_type env : Type.typ -> Type.typ = fun t -> + let open Type in + match normalize t with + | Obj (Actor, _) when E.mode env != Flags.AncientMode -> Prim Blob + | Func _ when E.mode env != Flags.AncientMode -> Tup [Prim Blob; Prim Text] + | t -> t + + (* The IDL serialization prefaces the data with a type description. We can statically create the type description in Ocaml code, store it in the program, and just copy it to the beginning of the message. @@ -3741,20 +3754,21 @@ module Serialization = struct | Prim Int64 -> Some 12 | Prim Float -> Some 14 | Prim Text -> Some 15 + (* NB: Prim Blob does not map to a primitive IDL type *) | Any -> Some 16 | Non -> Some 17 | _ -> None - let type_desc ts : string = + let type_desc env ts : string = let open Type in (* Type traversal *) - (* We do a first traversal to find out the indices of types *) + (* We do a first traversal to find out the indices of non-primitive types *) let (typs, idx) = let typs = ref [] in let idx = ref TM.empty in let rec go t = - let t = Type.normalize t in + let t = raw_type env t in if to_idl_prim t <> None then () else if TM.mem t !idx then () else begin idx := TM.add t (List.length !typs) !idx; @@ -3768,6 +3782,7 @@ module Serialization = struct | Variant vs -> List.iter (fun f -> go f.typ) vs | Func (s, c, tbs, ts1, ts2) -> List.iter go ts1; List.iter go ts2 + | Prim Blob -> () | _ -> Printf.eprintf "type_desc: unexpected type %s\n" (string_of_typ t); assert false @@ -3809,14 +3824,17 @@ module Serialization = struct (* Actual binary data *) let add_idx t = - let t = Type.normalize t in + let t = raw_type env t in match to_idl_prim t with | Some i -> add_sleb128 (-i) | None -> add_sleb128 (TM.find (normalize t) idx) in - let add_typ t = + let rec add_typ t = match t with - | Prim _ | Non -> assert false + | Non -> assert false + | Prim Blob -> + add_typ Type.(Array (Prim Word8)) + | Prim _ -> assert false | Tup ts -> add_sleb128 (-20); add_leb128 (List.length ts); @@ -3832,6 +3850,7 @@ module Serialization = struct add_idx f.typ ) (sort_by_hash fs) | Obj (Actor, fs) -> + assert (E.mode env = Flags.AncientMode); add_sleb128 (-23); add_leb128 (List.length fs); List.iter (fun f -> @@ -3851,6 +3870,8 @@ module Serialization = struct add_idx f.typ ) (sort_by_hash vs) | Func (s, c, tbs, ts1, ts2) -> + assert (Type.is_shared_sort s); + assert (E.mode env = Flags.AncientMode); add_sleb128 (-22); add_leb128 (List.length ts1); List.iter add_idx ts1; @@ -3869,7 +3890,7 @@ module Serialization = struct (* Returns data (in bytes) and reference buffer size (in entries) needed *) let rec buffer_size env t = let open Type in - let t = Type.normalize t in + let t = raw_type env t in let name = "@buffer_size<" ^ typ_id t ^ ">" in Func.share_code1 env name ("x", I32Type) [I32Type; I32Type] (fun env get_x -> @@ -3927,9 +3948,11 @@ module Serialization = struct get_x ^^ get_i ^^ Arr.idx env ^^ load_ptr ^^ size env t ) - | Prim Text -> - size_word env (get_x ^^ Heap.load_field Blob.len_field) ^^ - inc_data_size (get_x ^^ Heap.load_field Blob.len_field) + | Prim (Text | Blob) -> + let (set_len, get_len) = new_local env "len" in + get_x ^^ Heap.load_field Blob.len_field ^^ set_len ^^ + size_word env get_len ^^ + inc_data_size get_len | Prim Null -> G.nop | Any -> G.nop | Opt t -> @@ -3948,6 +3971,7 @@ module Serialization = struct ( List.mapi (fun i (_h, f) -> (i,f)) (sort_by_hash vs) ) ( E.trap_with env "buffer_size: unexpected variant" ) | (Func _ | Obj (Actor, _)) -> + assert (E.mode env = Flags.AncientMode); inc_ref_size 1l | Non -> E.trap_with env "buffer_size called on value of type None" @@ -3960,7 +3984,7 @@ module Serialization = struct (* Copies x to the data_buffer, storing references after ref_count entries in ref_base *) let rec serialize_go env t = let open Type in - let t = Type.normalize t in + let t = raw_type env t in let name = "@serialize_go<" ^ typ_id t ^ ">" in Func.share_code3 env name (("x", I32Type), ("data_buffer", I32Type), ("ref_buffer", I32Type)) [I32Type; I32Type] (fun env get_x get_data_buf get_ref_buf -> @@ -3995,6 +4019,7 @@ module Serialization = struct set_data_buf in + (* Now the actual serialization *) begin match t with @@ -4074,10 +4099,10 @@ module Serialization = struct ) ( List.mapi (fun i (_h, f) -> (i,f)) (sort_by_hash vs) ) ( E.trap_with env "serialize_go: unexpected variant" ) - | Prim Text -> + | Prim (Text | Blob )-> + (* Serializes to text or vec word8 respectively, but same data format *) let (set_len, get_len) = new_local env "len" in get_x ^^ Heap.load_field Blob.len_field ^^ set_len ^^ - write_word get_len ^^ get_data_buf ^^ get_x ^^ Blob.payload_ptr_unskewed ^^ @@ -4085,6 +4110,7 @@ module Serialization = struct Heap.memcpy env ^^ get_len ^^ advance_data_buf | (Func _ | Obj (Actor, _)) -> + assert (E.mode env = Flags.AncientMode); get_ref_buf ^^ get_x ^^ Dfinity.unbox_reference env ^^ store_unskewed_ptr ^^ @@ -4099,7 +4125,7 @@ module Serialization = struct let rec deserialize_go env t = let open Type in - let t = normalize t in + let t = raw_type env t in let name = "@deserialize_go<" ^ typ_id t ^ ">" in Func.share_code4 env name (("data_buffer", I32Type), @@ -4129,6 +4155,20 @@ module Serialization = struct E.else_trap_with env ("IDL error: unexpected IDL type when parsing " ^ string_of_typ t) in + let read_blob validate = + let (set_len, get_len) = new_local env "len" in + let (set_x, get_x) = new_local env "x" in + ReadBuf.read_leb128 env get_data_buf ^^ set_len ^^ + + get_len ^^ Blob.alloc env ^^ set_x ^^ + get_x ^^ Blob.payload_ptr_unskewed ^^ + ReadBuf.read_blob env get_data_buf get_len ^^ + begin if validate then + get_x ^^ Blob.payload_ptr_unskewed ^^ get_len ^^ + E.call_import env "rts" "utf8_validate" + else G.nop end ^^ + get_x + in (* checks that idltyp is positive, looks it up in the table, updates the typ_buf, reads the type constructor index and traps if it is the wrong one. @@ -4156,6 +4196,14 @@ module Serialization = struct f get_typ_buf ) in + let assert_blob_typ env = + with_composite_typ (-19l) (fun get_typ_buf -> + ReadBuf.read_sleb128 env get_typ_buf ^^ + compile_eq_const (-5l) (* Nat8 *) ^^ + E.else_trap_with env ("IDL error: blob not a vector of nat8") + ) + in + (* Now the actual deserialization *) begin match t with (* Primitive types *) @@ -4212,17 +4260,10 @@ module Serialization = struct Opt.null | Prim Text -> assert_prim_typ () ^^ - let (set_len, get_len) = new_local env "len" in - let (set_x, get_x) = new_local env "x" in - ReadBuf.read_leb128 env get_data_buf ^^ set_len ^^ - - get_len ^^ Blob.alloc env ^^ set_x ^^ - get_x ^^ Blob.payload_ptr_unskewed ^^ - ReadBuf.read_blob env get_data_buf get_len ^^ - get_x ^^ Blob.payload_ptr_unskewed ^^ get_len ^^ - E.call_import env "rts" "utf8_validate" ^^ - get_x - + read_blob true + | Prim Blob -> + assert_blob_typ env ^^ + read_blob false (* Composite types *) | Tup ts -> with_composite_typ (-20l) (fun get_typ_buf -> @@ -4336,6 +4377,7 @@ module Serialization = struct ( E.trap_with env "IDL error: unexpected variant tag" ) ) | (Func _ | Obj (Actor, _)) -> + assert (E.mode env = Flags.AncientMode); ReadBuf.read_word32 env get_ref_buf ^^ Dfinity.box_reference env | Non -> @@ -4378,7 +4420,7 @@ module Serialization = struct let (set_data_size, get_data_size) = new_local env "data_size" in let (set_refs_size, get_refs_size) = new_local env "refs_size" in - let tydesc = type_desc ts in + let tydesc = type_desc env ts in let tydesc_len = Int32.of_int (String.length tydesc) in (* Get object sizes *) diff --git a/src/mo_frontend/coverage.ml b/src/mo_frontend/coverage.ml index 5b641e4a3a0..211f70f65f7 100644 --- a/src/mo_frontend/coverage.ml +++ b/src/mo_frontend/coverage.ml @@ -102,6 +102,7 @@ let pick_val vs = function | T.Word64 -> pick_word (module V.Word64) (fun x -> V.Word64 x) vs | T.Char -> pick_char vs | T.Text + | T.Blob | T.Error | T.Float -> Any diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 4816d139d19..707db2411f1 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -231,9 +231,9 @@ let error_shared env t at fmt = Diag.add_msg env.msgs (type_error at (s1^s)); match t1 with | T.Obj (T.Actor, _) -> - error_in [Flags.ICMode; Flags.StubMode] env at "actor types are non-shared." + error_in [Flags.ICMode] env at "actor types are non-shared." | T.Func (T.Shared _, _, _, _, _) -> - error_in [Flags.ICMode; Flags.StubMode] env at "shared function types are non-shared." + error_in [Flags.ICMode] env at "shared function types are non-shared." | _ -> raise Recover) fmt diff --git a/src/mo_idl/mo_to_idl.ml b/src/mo_idl/mo_to_idl.ml index 4556ac6d443..cf0340c1190 100644 --- a/src/mo_idl/mo_to_idl.ml +++ b/src/mo_idl/mo_to_idl.ml @@ -38,36 +38,37 @@ let string_of_con vs c = let prim p = match p with - | Null -> I.Null - | Bool -> I.Bool - | Nat -> I.Nat - | Nat8 -> I.Nat8 - | Nat16 -> I.Nat16 - | Nat32 -> I.Nat32 - | Nat64 -> I.Nat64 - | Int -> I.Int - | Int8 -> I.Int8 - | Int16 -> I.Int16 - | Int32 -> I.Int32 - | Int64 -> I.Int64 - | Word8 -> I.Nat8 - | Word16 -> I.Nat16 - | Word32 -> I.Nat32 - | Word64 -> I.Nat64 - | Float -> I.Float64 - | Char -> I.Nat32 - | Text -> I.Text + | Null -> I.PrimT I.Null + | Bool -> I.PrimT I.Bool + | Nat -> I.PrimT I.Nat + | Nat8 -> I.PrimT I.Nat8 + | Nat16 -> I.PrimT I.Nat16 + | Nat32 -> I.PrimT I.Nat32 + | Nat64 -> I.PrimT I.Nat64 + | Int -> I.PrimT I.Int + | Int8 -> I.PrimT I.Int8 + | Int16 -> I.PrimT I.Int16 + | Int32 -> I.PrimT I.Int32 + | Int64 -> I.PrimT I.Int64 + | Word8 -> I.PrimT I.Nat8 + | Word16 -> I.PrimT I.Nat16 + | Word32 -> I.PrimT I.Nat32 + | Word64 -> I.PrimT I.Nat64 + | Float -> I.PrimT I.Float64 + | Char -> I.PrimT I.Nat32 + | Text -> I.PrimT I.Text + | Blob -> I.VecT (I.PrimT I.Nat8 @@ no_region) | Error -> assert false let rec typ vs t = (match t with | Any -> I.PrimT I.Reserved | Non -> I.PrimT I.Empty - | Prim p -> I.PrimT (prim p) + | Prim p -> prim p | Var (s, i) -> (typ vs (List.nth vs i)).it | Con (c, []) -> (match Con.kind c with - | Def ([], Prim p) -> I.PrimT (prim p) + | Def ([], Prim p) -> prim p | Def ([], Any) -> I.PrimT I.Reserved | Def ([], Non) -> I.PrimT I.Empty | _ -> diff --git a/src/mo_types/arrange_type.ml b/src/mo_types/arrange_type.ml index 51fb22d106a..fe9cb123f55 100644 --- a/src/mo_types/arrange_type.ml +++ b/src/mo_types/arrange_type.ml @@ -38,6 +38,7 @@ let prim p = match p with | Float -> Atom "Float" | Char -> Atom "Char" | Text -> Atom "Text" + | Blob -> Atom "Blob" | Error -> Atom "Error" let con c = Atom (Con.to_string c) diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index f6526fc6ed1..8707b236e28 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -1,6 +1,4 @@ (* Representation *) -open Mo_config - type lab = string type var = string @@ -33,6 +31,7 @@ type prim = | Float | Char | Text + | Blob (* IR use: Packed representation, vec u8 IDL type *) | Error type t = typ @@ -433,7 +432,7 @@ let rec span = function | Con _ as t -> span (promote t) | Prim Null -> Some 1 | Prim Bool -> Some 2 - | Prim (Nat | Int | Float | Text | Error) -> None + | Prim (Nat | Int | Float | Text | Blob | Error) -> None | Prim (Nat8 | Int8 | Word8) -> Some 0x100 | Prim (Nat16 | Int16 | Word16) -> Some 0x10000 | Prim (Nat32 | Int32 | Word32 | Nat64 | Int64 | Word64 | Char) -> None (* for all practical purposes *) @@ -571,11 +570,6 @@ let concrete t = in go t let shared t = - (* TBR: Hack to restrict sharing in ICMode *) - let allow_actor as allow_shared = - not !Flags.compiled || - !Flags.compile_mode = Flags.WasmMode || - !Flags.compile_mode = Flags.AncientMode in let seen = ref S.empty in let rec go t = S.mem t !seen || @@ -594,20 +588,15 @@ let shared t = | Array t | Opt t -> go t | Tup ts -> List.for_all go ts | Obj (s, fs) -> - (allow_actor && s = Actor) || + s = Actor || (not (s = Actor) && List.for_all (fun f -> go f.typ) fs) | Variant fs -> List.for_all (fun f -> go f.typ) fs - | Func (s, c, tbs, ts1, ts2) -> allow_shared && is_shared_sort s + | Func (s, c, tbs, ts1, ts2) -> is_shared_sort s end in go t (* Find the first unshared subexpression in a type *) let find_unshared t = - (* TBR: Hack to restrict sharing in ICMode *) - let allow_actor as allow_shared = - not !Flags.compiled || - !Flags.compile_mode = Flags.WasmMode || - !Flags.compile_mode = Flags.AncientMode in let seen = ref S.empty in let rec go t = if S.mem t !seen then None else @@ -627,12 +616,11 @@ let find_unshared t = | Tup ts -> Lib.List.first_opt go ts | Obj (s, fs) -> if s = Actor - then if allow_actor then None - else Some t + then None else Lib.List.first_opt (fun f -> go f.typ) fs | Variant fs -> Lib.List.first_opt (fun f -> go f.typ) fs | Func (s, c, tbs, ts1, ts2) -> - if allow_shared && is_shared_sort s + if is_shared_sort s then None else Some t end @@ -1122,6 +1110,7 @@ let string_of_prim = function | Word64 -> "Word64" | Char -> "Char" | Text -> "Text" + | Blob -> "Blob" | Error -> "Error" let string_of_var (x, i) = diff --git a/src/mo_types/type.mli b/src/mo_types/type.mli index e980366e0f6..f6dcb71302f 100644 --- a/src/mo_types/type.mli +++ b/src/mo_types/type.mli @@ -29,6 +29,7 @@ type prim = | Float | Char | Text + | Blob (* IR use: Packed representation, vec u8 IDL type *) | Error type t = typ diff --git a/test/idl/.gitignore b/test/idl/.gitignore new file mode 100644 index 00000000000..3c3629e647f --- /dev/null +++ b/test/idl/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/test/mo-idl/fun_self_arg.mo b/test/mo-idl/fun_self_arg.mo new file mode 100644 index 00000000000..32c29100ef9 --- /dev/null +++ b/test/mo-idl/fun_self_arg.mo @@ -0,0 +1,2 @@ +type F = shared () -> async F; +type A = actor { foo : F } diff --git a/test/mo-idl/ok/fun_self_arg.did.ok b/test/mo-idl/ok/fun_self_arg.did.ok new file mode 100644 index 00000000000..05996242017 --- /dev/null +++ b/test/mo-idl/ok/fun_self_arg.did.ok @@ -0,0 +1,6 @@ +type F = func () -> (F); +type A_9 = + service { + "foo": F; + }; + diff --git a/test/run-drun/ok/idl-func.comp.ok b/test/run-drun/ok/idl-func.comp.ok deleted file mode 100644 index b796bc5ed9d..00000000000 --- a/test/run-drun/ok/idl-func.comp.ok +++ /dev/null @@ -1,8 +0,0 @@ -idl-func.mo:1.13-1.37: type error, shared function has non-shared return type - Func = shared Int -> async Func -type - Func = shared Int -> async Func -is or contains non-shared type - shared Int -> async Func -idl-func.mo:1.13-1.37: type error, shared function types are non-shared. - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/idl-func.comp.ret.ok b/test/run-drun/ok/idl-func.comp.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/idl-func.comp.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/idl-func.drun-run.ok b/test/run-drun/ok/idl-func.drun-run.ok new file mode 100644 index 00000000000..a775313ab56 --- /dev/null +++ b/test/run-drun/ok/idl-func.drun-run.ok @@ -0,0 +1,3 @@ +ingress(0) System +Ok: Payload: 0x4449444c036e016c02000201716d7b010000 +Ok: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/unsupported.comp.ok b/test/run-drun/ok/unsupported.comp.ok index fa8f5d395b1..a131d209526 100644 --- a/test/run-drun/ok/unsupported.comp.ok +++ b/test/run-drun/ok/unsupported.comp.ok @@ -1,19 +1,3 @@ -unsupported.mo:6.28-6.39: type error, shared function has non-shared parameter type - actor {} -type - actor {} -is or contains non-shared type - actor {} -unsupported.mo:6.28-6.39: type error, actor types are non-shared. - (This is a limitation of the current version.) -unsupported.mo:8.31-8.53: type error, shared function has non-shared parameter type - shared () -> async () -type - shared () -> async () -is or contains non-shared type - shared () -> async () -unsupported.mo:8.31-8.53: type error, shared function types are non-shared. - (This is a limitation of the current version.) unsupported.mo:19.19-19.21: type error, shared, async function must be called within an await expression (This is a limitation of the current version.) unsupported.mo:23.16-23.18: type error, calling a shared function not yet supported @@ -28,22 +12,6 @@ unsupported.mo:38.26-38.29: type error, a shared function is only allowed as a p (This is a limitation of the current version.) unsupported.mo:41.10-41.18: type error, unsupported async block (This is a limitation of the current version.) -unsupported.mo:46.31-46.48: type error, shared function has non-shared parameter type - shared () -> () -type - shared () -> () -is or contains non-shared type - shared () -> () -unsupported.mo:46.31-46.48: type error, shared function types are non-shared. - (This is a limitation of the current version.) -unsupported.mo:51.31-51.41: type error, shared function has non-shared parameter type - actor {} -type - actor {} -is or contains non-shared type - actor {} -unsupported.mo:51.31-51.41: type error, actor types are non-shared. - (This is a limitation of the current version.) unsupported.mo:62.3-62.35: type error, actor classes are not supported; use an actor declaration instead (This is a limitation of the current version.) unsupported.mo:66.45-66.53: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program diff --git a/test/run-stub/ok/idl-func.comp.ok b/test/run-stub/ok/idl-func.comp.ok deleted file mode 100644 index 2ab3746d8ec..00000000000 --- a/test/run-stub/ok/idl-func.comp.ok +++ /dev/null @@ -1,8 +0,0 @@ -idl-func.mo:1.13-1.37: type error, shared function has non-shared return type - Func = shared Int -> async Func -type - Func = shared Int -> async Func -is or contains non-shared type - shared Int -> async Func -idl-func.mo:1.13-1.37: type error, shared function types are non-shared. - (This is a limitation of the current version and flag -stub-system-api.) diff --git a/test/run-stub/ok/idl-func.comp.ret.ok b/test/run-stub/ok/idl-func.comp.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-stub/ok/idl-func.comp.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-stub/ok/idl-func.ic-stub-run.ok b/test/run-stub/ok/idl-func.ic-stub-run.ok new file mode 100644 index 00000000000..a787304d4d8 --- /dev/null +++ b/test/run-stub/ok/idl-func.ic-stub-run.ok @@ -0,0 +1,8 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ query fun(0x4449444c0000) +← completed: 0x4449444c036e016c02000201716d7b010000 +→ query fun2(0x4449444c026e016a017c0000010000) +← completed: 0x4449444c0000 diff --git a/test/run-stub/ok/pass-references.ic-stub-run.ok b/test/run-stub/ok/pass-references.ic-stub-run.ok new file mode 100644 index 00000000000..a7476cb89cd --- /dev/null +++ b/test/run-stub/ok/pass-references.ic-stub-run.ok @@ -0,0 +1,7 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +a +b +b +← completed diff --git a/test/run-stub/ok/pass-references.run-ir.ok b/test/run-stub/ok/pass-references.run-ir.ok new file mode 100644 index 00000000000..ee12596769e --- /dev/null +++ b/test/run-stub/ok/pass-references.run-ir.ok @@ -0,0 +1,3 @@ +a +b +b diff --git a/test/run-stub/ok/pass-references.run-low.ok b/test/run-stub/ok/pass-references.run-low.ok new file mode 100644 index 00000000000..ee12596769e --- /dev/null +++ b/test/run-stub/ok/pass-references.run-low.ok @@ -0,0 +1,3 @@ +a +b +b diff --git a/test/run-stub/ok/pass-references.run.ok b/test/run-stub/ok/pass-references.run.ok new file mode 100644 index 00000000000..ee12596769e --- /dev/null +++ b/test/run-stub/ok/pass-references.run.ok @@ -0,0 +1,3 @@ +a +b +b diff --git a/test/run-stub/ok/unsupported.comp.ok b/test/run-stub/ok/unsupported.comp.ok index 45c25dbe75d..5ea780b32b5 100644 --- a/test/run-stub/ok/unsupported.comp.ok +++ b/test/run-stub/ok/unsupported.comp.ok @@ -1,19 +1,3 @@ -unsupported.mo:6.28-6.39: type error, shared function has non-shared parameter type - actor {} -type - actor {} -is or contains non-shared type - actor {} -unsupported.mo:6.28-6.39: type error, actor types are non-shared. - (This is a limitation of the current version and flag -stub-system-api.) -unsupported.mo:8.31-8.53: type error, shared function has non-shared parameter type - shared () -> async () -type - shared () -> async () -is or contains non-shared type - shared () -> async () -unsupported.mo:8.31-8.53: type error, shared function types are non-shared. - (This is a limitation of the current version and flag -stub-system-api.) unsupported.mo:32.17-32.29: type error, unsupported async block (This is a limitation of the current version and flag -stub-system-api.) unsupported.mo:4.5-4.41: type error, a shared function cannot be private @@ -22,22 +6,6 @@ unsupported.mo:38.26-38.29: type error, a shared function is only allowed as a p (This is a limitation of the current version and flag -stub-system-api.) unsupported.mo:41.10-41.18: type error, unsupported async block (This is a limitation of the current version and flag -stub-system-api.) -unsupported.mo:46.31-46.48: type error, shared function has non-shared parameter type - shared () -> () -type - shared () -> () -is or contains non-shared type - shared () -> () -unsupported.mo:46.31-46.48: type error, shared function types are non-shared. - (This is a limitation of the current version and flag -stub-system-api.) -unsupported.mo:51.31-51.41: type error, shared function has non-shared parameter type - actor {} -type - actor {} -is or contains non-shared type - actor {} -unsupported.mo:51.31-51.41: type error, actor types are non-shared. - (This is a limitation of the current version and flag -stub-system-api.) unsupported.mo:62.3-62.35: type error, actor classes are not supported; use an actor declaration instead (This is a limitation of the current version and flag -stub-system-api.) unsupported.mo:76.34-76.37: type error, freestanding async expression not yet supported diff --git a/test/run-stub/pass-references.mo b/test/run-stub/pass-references.mo new file mode 100644 index 00000000000..f58d3276d97 --- /dev/null +++ b/test/run-stub/pass-references.mo @@ -0,0 +1,22 @@ +actor a { + public func foo() { debugPrint("a"); }; + + public func pass_func(f : shared () -> ()) { + f(); + }; + + public func pass_actor(a : actor { foo : shared () -> () }) { + a.foo(); + }; + + public func go() { + actor b { + public func foo() { debugPrint("b"); }; + }; + pass_func(foo); + pass_func(b.foo); + pass_actor(b); + }; + + go(); +} diff --git a/test/run/ok/issue120.comp.ok b/test/run/ok/issue120.comp.ok deleted file mode 100644 index d563599b0a1..00000000000 --- a/test/run/ok/issue120.comp.ok +++ /dev/null @@ -1,6 +0,0 @@ -issue120.mo:2.8-2.11: type error, shared function has non-shared parameter type - Bar = actor {} -type - Bar = actor {} -is or contains non-shared type - actor {} diff --git a/test/run/ok/issue120.comp.ret.ok b/test/run/ok/issue120.comp.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run/ok/issue120.comp.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 From 2a05e51175e616f6ee96a671a8f708113c151b6a Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 25 Nov 2019 22:44:31 +0100 Subject: [PATCH 0709/1176] Add `console.profile()` call to `debug.html` (#923) so that profiling wraps the relevant lines. --- test/debug.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/debug.html b/test/debug.html index 10a97d51948..43057d85306 100644 --- a/test/debug.html +++ b/test/debug.html @@ -29,7 +29,9 @@ }; const importObject = {env}; + console.profile(); const wa = await createWebAssembly(file, importObject); + console.profileEnd(); exports = wa.instance.exports; console.info('got exports', exports); From 9ac0a97f0b72207eecdac15a63e2c9e453bfcad0 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 26 Nov 2019 12:03:06 +0100 Subject: [PATCH 0710/1176] Test suite profiler: Correctly use `drun` (#922) `/dev/null` != `/dev/zero` (Not that I would mind removing all that code there.) --- stdlib/Makefile | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/stdlib/Makefile b/stdlib/Makefile index 8febddc6c11..ecfdb3fc473 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -472,53 +472,53 @@ $(STOPWATCH): $(STOPWATCH_C) $(CC) $< -o $@ $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm $(STOPWATCH) - $(STOPWATCH) "$(DRUN) $< /dev/zero" "5, 1, " > $@ + $(STOPWATCH) "$(DRUN) $< /dev/null" "5, 1, " > $@ cat $@ $(OUTDIR)/ProduceExchangeLoadQuery_5_2.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_2.wasm $(STOPWATCH) - $(STOPWATCH) "$(DRUN) $< /dev/zero" "5, 2, " > $@ + $(STOPWATCH) "$(DRUN) $< /dev/null" "5, 2, " > $@ cat $@ $(OUTDIR)/ProduceExchangeLoadQuery_5_3.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_3.wasm $(STOPWATCH) - $(STOPWATCH) "$(DRUN) $< /dev/zero" "5, 3, " > $@ + $(STOPWATCH) "$(DRUN) $< /dev/null" "5, 3, " > $@ cat $@ $(OUTDIR)/ProduceExchangeLoadQuery_5_4.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_4.wasm $(STOPWATCH) - $(STOPWATCH) "$(DRUN) $< /dev/zero" "5, 4, " > $@ + $(STOPWATCH) "$(DRUN) $< /dev/null" "5, 4, " > $@ cat $@ $(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm $(STOPWATCH) - $(STOPWATCH) "$(DRUN) $< /dev/zero" "5, 5, " > $@ + $(STOPWATCH) "$(DRUN) $< /dev/null" "5, 5, " > $@ cat $@ $(OUTDIR)/ProduceExchangeLoadQuery_5_6.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_6.wasm $(STOPWATCH) - $(STOPWATCH) "$(DRUN) $< /dev/zero" "5, 6, " > $@ + $(STOPWATCH) "$(DRUN) $< /dev/null" "5, 6, " > $@ cat $@ $(OUTDIR)/ProduceExchangeLoadQuery_5_7.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_7.wasm $(STOPWATCH) - $(STOPWATCH) "$(DRUN) $< /dev/zero" "5, 7, " > $@ + $(STOPWATCH) "$(DRUN) $< /dev/null" "5, 7, " > $@ cat $@ $(OUTDIR)/ProduceExchangeLoadQuery_5_8.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_8.wasm $(STOPWATCH) - $(STOPWATCH) "$(DRUN) $< /dev/zero" "5, 8, " > $@ + $(STOPWATCH) "$(DRUN) $< /dev/null" "5, 8, " > $@ cat $@ $(OUTDIR)/ProduceExchangeLoadQuery_5_9.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_9.wasm $(STOPWATCH) - $(STOPWATCH) "$(DRUN) $< /dev/zero" "5, 9, " > $@ + $(STOPWATCH) "$(DRUN) $< /dev/null" "5, 9, " > $@ cat $@ $(OUTDIR)/ProduceExchangeLoadQuery_5_10.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_10.wasm $(STOPWATCH) - $(STOPWATCH) "$(DRUN) $< /dev/zero" "5, 10, " > $@ + $(STOPWATCH) "$(DRUN) $< /dev/null" "5, 10, " > $@ cat $@ $(OUTDIR)/ProduceExchangeLoadQuery_5_20.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_20.wasm $(STOPWATCH) - $(STOPWATCH) "$(DRUN) $< /dev/zero" "5, 20, " > $@ + $(STOPWATCH) "$(DRUN) $< /dev/null" "5, 20, " > $@ cat $@ $(OUTDIR)/ProduceExchangeLoadQuery_5_50.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_50.wasm $(STOPWATCH) - $(STOPWATCH) "$(DRUN) $< /dev/zero" "5, 50, " > $@ + $(STOPWATCH) "$(DRUN) $< /dev/null" "5, 50, " > $@ cat $@ $(OUTDIR)/ProduceExchangeLoadQuery_5_100.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_100.wasm $(STOPWATCH) - $(STOPWATCH) "$(DRUN) $< /dev/zero" "5, 100, " > $@ + $(STOPWATCH) "$(DRUN) $< /dev/null" "5, 100, " > $@ cat $@ From 77d7077cd3f9ff61e35c801457b4d3edf9e6bf9e Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 26 Nov 2019 12:40:33 +0100 Subject: [PATCH 0711/1176] Compile async expression to SelfCallE (#931) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit so that we can have `async {…}` on the new platform! Yay! Collaborative work with Claudio. Introduce SelfCallE (not a prim, because not call-by-value) is essentially a short-hand for a combination of `FuncE Shared` with immediate `CallE`. It has to be kept togehter for the backend, which can compile this combination, but not a general `FuncE Shared` expression. --- src/codegen/compile.ml | 282 ++++++++++++------ src/ir_def/arrange_ir.ml | 2 + src/ir_def/check_ir.ml | 11 +- src/ir_def/freevars.ml | 1 + src/ir_def/ir.ml | 1 + src/ir_def/ir_effect.ml | 4 + src/ir_interpreter/interpret_ir.ml | 50 ++-- src/ir_passes/async.ml | 34 ++- src/ir_passes/await.ml | 2 + src/ir_passes/rename.ml | 2 + src/ir_passes/show.ml | 2 + src/ir_passes/tailcall.ml | 6 + src/mo_frontend/typing.ml | 6 +- test/run-dfinity/async-free-var.mo | 15 + test/run-dfinity/interleave.mo | 37 +++ test/run-dfinity/ok/async-free-var.dvm.ok | 7 + test/run-dfinity/ok/async-free-var.run-ir.ok | 7 + test/run-dfinity/ok/async-free-var.run-low.ok | 7 + test/run-dfinity/ok/async-free-var.run.ok | 7 + test/run-dfinity/ok/interleave.dvm.ok | 19 ++ test/run-dfinity/ok/interleave.run-ir.ok | 19 ++ test/run-dfinity/ok/interleave.run-low.ok | 19 ++ test/run-dfinity/ok/interleave.run.ok | 19 ++ test/run-dfinity/ok/overflow.dvm.ok | 4 +- test/run-stub/ok/unsupported.comp.ok | 6 - 25 files changed, 422 insertions(+), 147 deletions(-) create mode 100644 test/run-dfinity/async-free-var.mo create mode 100644 test/run-dfinity/interleave.mo create mode 100644 test/run-dfinity/ok/async-free-var.dvm.ok create mode 100644 test/run-dfinity/ok/async-free-var.run-ir.ok create mode 100644 test/run-dfinity/ok/async-free-var.run-low.ok create mode 100644 test/run-dfinity/ok/async-free-var.run.ok create mode 100644 test/run-dfinity/ok/interleave.dvm.ok create mode 100644 test/run-dfinity/ok/interleave.run-ir.ok create mode 100644 test/run-dfinity/ok/interleave.run-low.ok create mode 100644 test/run-dfinity/ok/interleave.run.ok diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index c78f3a542cb..f2b9e3e89ec 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -3327,8 +3327,7 @@ module Dfinity = struct get_blob ) | Flags.AncientMode -> - system_call env "actor" "self" ^^ - box_reference env + system_call env "actor" "self" | _ -> assert false @@ -3403,6 +3402,8 @@ module Dfinity = struct let fail_assert env at = E.trap_with env (Printf.sprintf "assertion failed at %s" (string_of_region at)) + let async_method_name = "__motoko_async_helper" + end (* Dfinity *) module RTS_Exports = struct @@ -5110,7 +5111,7 @@ module FuncDec = struct compile_unboxed_const tmp_table_slot ^^ G.i (CallIndirect (nr (message_ty env))) - (* The type of messages (with return: expect a callback, first argument (for binding) *) + (* The type of messages (with return: expect a callback as the first argument *) let call_ty env = E.func_type env (FuncType ([I32Type; I32Type; I32Type], [])) @@ -5435,6 +5436,26 @@ module FuncDec = struct Dfinity.system_call env "func" "bind_i32" end + let lit env ae name sort control free_vars args mk_body ret_tys at = + + let captured = List.filter (VarEnv.needs_capture ae) free_vars in + + if captured = [] + then + let (st, fill) = closed env sort control name args mk_body ret_tys at in + fill env ae; + (SR.StaticThing st, G.nop) + else closure env ae sort control name captured args mk_body ret_tys at + + (* Returns the index of a saved closure *) + let async_body env ae ts free_vars mk_body at = + (* We compile this as a local, returning function, so set return type to [] *) + let sr, code = lit env ae "anon_async" Type.Local Type.Returns free_vars [] mk_body [] at in + code ^^ + StackRep.adjust env sr SR.Vanilla ^^ + ClosureTable.remember_closure env + + (* Wraps a local closure in a shared function that does serialization and takes care of the reply global *) (* Need this function once per type, so we can share based on ts *) @@ -5529,15 +5550,128 @@ module FuncDec = struct Func.define_built_in env name ["env", I32Type] [] (fun env -> G.nop); compile_unboxed_const (E.built_in env name) - let lit env ae how name sort control free_vars args mk_body ret_tys at = - let captured = List.filter (VarEnv.needs_capture ae) free_vars in + let ic_call env ts1 ts2 get_funcref get_arg get_k get_r = + match E.mode env with + | Flags.ICMode | Flags.StubMode -> - if captured = [] - then - let (st, fill) = closed env sort control name args mk_body ret_tys at in - fill env ae; - (SR.StaticThing st, G.nop) - else closure env ae sort control name captured args mk_body ret_tys at + (* The callee *) + get_funcref ^^ Arr.load_field 0l ^^ Blob.as_ptr_len env ^^ + (* The method name *) + get_funcref ^^ Arr.load_field 1l ^^ Blob.as_ptr_len env ^^ + (* The reply callback *) + closure_to_reply_callback env ts2 get_k ^^ + (* The reject callback *) + closure_to_reject_callback env get_r ^^ + (* the data *) + get_arg ^^ Serialization.serialize env ts1 ^^ + (* done! *) + Dfinity.system_call env "ic0" "call_simple" ^^ + (* TODO: Check error code *) + G.i Drop + | Flags.AncientMode -> + callback_to_funcref env ts2 get_k ^^ + get_arg ^^ Serialization.serialize env ts1 ^^ + call_await_funcref env get_funcref + | _ -> assert false + + let ic_call_one_shot env ts get_funcref get_arg = + match E.mode env with + | Flags.ICMode | Flags.StubMode -> + + (* The callee *) + get_funcref ^^ Arr.load_field 0l ^^ Blob.as_ptr_len env ^^ + (* The method name *) + get_funcref ^^ Arr.load_field 1l ^^ Blob.as_ptr_len env ^^ + (* The reply callback *) + ignoring_callback env ^^ + compile_unboxed_zero ^^ + (* The reject callback *) + ignoring_callback env ^^ + compile_unboxed_zero ^^ + (* the data *) + get_arg ^^ Serialization.serialize env ts ^^ + (* done! *) + Dfinity.system_call env "ic0" "call_simple" ^^ + (* TODO: Check error code *) + G.i Drop + | Flags.AncientMode -> + get_arg ^^ Serialization.serialize env ts ^^ + call_message_funcref env get_funcref + | _ -> assert false + + let export_async_method env = + let name = Dfinity.async_method_name in + begin match E.mode env with + | Flags.AncientMode -> + Func.define_built_in env name ["reply", I32Type; "databuf", I32Type; "elembuf", I32Type] [] (fun env -> + let (set_closure, get_closure) = new_local env "closure" in + let get_reply = G.i (LocalGet (nr 0l)) in + let get_databuf = G.i (LocalGet (nr 1l)) in + let get_elembuf = G.i (LocalGet (nr 2l)) in + + (* Restore memory *) + OrthogonalPersistence.restore_mem env ^^ + + (* Story reply contiuation *) + get_reply ^^ Dfinity.set_reply_cont env ^^ + + (* Look up closure *) + get_databuf ^^ get_elembuf ^^ + Serialization.deserialize env [Type.Prim Type.Word32] ^^ + BoxedSmallWord.unbox env ^^ + ClosureTable.recall_closure env ^^ (* At this point we can remove the closure *) + set_closure ^^ get_closure ^^ get_closure ^^ + Closure.call_closure env 0 0 ^^ + message_cleanup env (Type.Shared Type.Write) + ); + + let fi = E.built_in env name in + declare_dfinity_type env false true fi; + E.add_export env (nr { + name = Wasm.Utf8.decode name; + edesc = nr (FuncExport (nr fi)) + }) + + | Flags.ICMode -> + Func.define_built_in env name ["api_nonce", I64Type] [] (fun env -> + let (set_closure, get_closure) = new_local env "closure" in + + G.i (LocalGet (nr 0l)) ^^ Dfinity.set_api_nonce env ^^ + + (* TODO: Check that it is us that is calling this *) + + (* Deserialize and look up closure argument *) + Serialization.deserialize env [Type.Prim Type.Word32] ^^ + BoxedSmallWord.unbox env ^^ + ClosureTable.recall_closure env ^^ + set_closure ^^ get_closure ^^ get_closure ^^ + Closure.call_closure env 0 0 ^^ + message_cleanup env (Type.Shared Type.Write) + ); + | Flags.StubMode -> + Func.define_built_in env name [] [] (fun env -> + let (set_closure, get_closure) = new_local env "closure" in + + (* TODO: Check that it is us that is calling this *) + + (* Deserialize and look up closure argument *) + Serialization.deserialize env [Type.Prim Type.Word32] ^^ + BoxedSmallWord.unbox env ^^ + ClosureTable.recall_closure env ^^ + set_closure ^^ get_closure ^^ get_closure ^^ + Closure.call_closure env 0 0 ^^ + message_cleanup env (Type.Shared Type.Write) + ); + + + let fi = E.built_in env name in + declare_dfinity_type env false true fi; + E.add_export env (nr { + name = Wasm.Utf8.decode ("canister_update " ^ name); + edesc = nr (FuncExport (nr fi)) + }) + | _ -> () + end end (* FuncDec *) @@ -6789,52 +6923,16 @@ and compile_exp (env : E.t) ae exp = (* TBR: Can we do better than using the notes? *) let _, _, _, ts1, _ = Type.as_func f.note.note_typ in let _, _, _, ts2, _ = Type.as_func k.note.note_typ in - - match E.mode env with - | Flags.ICMode | Flags.StubMode -> - - let (set_funcref, get_funcref) = new_local env "funcref" in - let (set_arg, get_arg) = new_local env "arg" in - let (set_k, get_k) = new_local env "k" in - let (set_r, get_r) = new_local env "r" in - compile_exp_as env ae SR.Vanilla f ^^ set_funcref ^^ - compile_exp_as env ae SR.Vanilla e ^^ set_arg ^^ - compile_exp_as env ae SR.Vanilla k ^^ set_k ^^ - compile_exp_as env ae SR.Vanilla r ^^ set_r ^^ - - (* The callee *) - get_funcref ^^ Arr.load_field 0l ^^ Blob.as_ptr_len env ^^ - (* The method name *) - get_funcref ^^ Arr.load_field 1l ^^ Blob.as_ptr_len env ^^ - (* The reply callback *) - FuncDec.closure_to_reply_callback env ts2 get_k ^^ - (* The reject callback *) - FuncDec.closure_to_reject_callback env get_r ^^ - (* the data *) - get_arg ^^ Serialization.serialize env ts1 ^^ - (* done! *) - Dfinity.system_call env "ic0" "call_simple" ^^ - (* TODO: Check error code *) - G.i Drop - | Flags.AncientMode -> - let (set_funcref, get_funcref) = new_local env "funcref" in - let (set_arg, get_arg) = new_local env "arg" in - let (set_k, get_k) = new_local env "k" in - compile_exp_as env ae SR.UnboxedReference f ^^ set_funcref ^^ - compile_exp_as env ae SR.Vanilla e ^^ set_arg ^^ - compile_exp_as env ae SR.Vanilla k ^^ set_k ^^ - - (* We drop the reject continuation on the ancient platform, but still - need to evaluate it *) - let (r_sr, code_r) = compile_exp env ae r in - code_r ^^ StackRep.drop env r_sr ^^ - - FuncDec.callback_to_funcref env ts2 get_k ^^ - get_arg ^^ Serialization.serialize env ts1 ^^ - FuncDec.call_await_funcref env get_funcref - | _ -> assert false + let (set_funcref, get_funcref) = new_local env "funcref" in + let (set_arg, get_arg) = new_local env "arg" in + let (set_k, get_k) = new_local env "k" in + let (set_r, get_r) = new_local env "r" in + compile_exp_as env ae (Dfinity.reference_sr env) f ^^ set_funcref ^^ + compile_exp_as env ae SR.Vanilla e ^^ set_arg ^^ + compile_exp_as env ae SR.Vanilla k ^^ set_k ^^ + compile_exp_as env ae SR.Vanilla r ^^ set_r ^^ + FuncDec.ic_call env ts1 ts2 get_funcref get_arg get_k get_r end - (* Unknown prim *) | _ -> SR.Unreachable, todo_trap env "compile_exp" (Arrange_ir.exp exp) end @@ -6938,43 +7036,15 @@ and compile_exp (env : E.t) ae exp = | _, Type.Shared _ -> (* Non-one-shot functions have been rewritten in async.ml *) assert (control = Type.Returns); - match E.mode env with - | Flags.AncientMode -> - let (set_funcref, get_funcref) = new_local env "funcref" in - code1 ^^ StackRep.adjust env fun_sr SR.UnboxedReference ^^ - set_funcref ^^ - compile_exp_as env ae SR.Vanilla e2 ^^ - (* We can try to avoid the boxing and pass the arguments to - serialize individually *) - let _, _, _, ts, _ = Type.as_func e1.note.note_typ in - Serialization.serialize env ts ^^ - FuncDec.call_message_funcref env get_funcref - | Flags.StubMode -> - let (set_funcref, get_funcref) = new_local env "funcref" in - let (set_arg, get_arg) = new_local env "arg" in - let _, _, _, ts, _ = Type.as_func e1.note.note_typ in - code1 ^^ StackRep.adjust env fun_sr SR.Vanilla ^^ - set_funcref ^^ - compile_exp_as env ae SR.Vanilla e2 ^^ set_arg ^^ - - (* The callee *) - get_funcref ^^ Arr.load_field 0l ^^ Blob.as_ptr_len env ^^ - (* The method name *) - get_funcref ^^ Arr.load_field 1l ^^ Blob.as_ptr_len env ^^ - (* The reply callback *) - FuncDec.ignoring_callback env ^^ - compile_unboxed_const 0l ^^ - (* The reject callback *) - FuncDec.ignoring_callback env ^^ - compile_unboxed_const 0l ^^ - (* the data *) - get_arg ^^ Serialization.serialize env ts ^^ - (* done! *) - Dfinity.system_call env "ic0" "call_simple" ^^ - (* TODO: Check error code *) - G.i Drop - | _ -> assert false + let (set_funcref, get_funcref) = new_local env "funcref" in + let (set_arg, get_arg) = new_local env "arg" in + let _, _, _, ts, _ = Type.as_func e1.note.note_typ in + code1 ^^ StackRep.adjust env fun_sr (Dfinity.reference_sr env) ^^ + set_funcref ^^ + compile_exp_as env ae SR.Vanilla e2 ^^ set_arg ^^ + + FuncDec.ic_call_one_shot env ts get_funcref get_arg end | SwitchE (e, cs) -> SR.Vanilla, @@ -7012,7 +7082,26 @@ and compile_exp (env : E.t) ae exp = | Type.Promises -> assert false in let return_arity = List.length return_tys in let mk_body env1 ae1 = compile_exp_as env1 ae1 (StackRep.of_arity return_arity) e in - FuncDec.lit env ae typ_binds x sort control captured args mk_body return_tys exp.at + FuncDec.lit env ae x sort control captured args mk_body return_tys exp.at + | SelfCallE (ts, exp_f, exp_k, exp_r) -> + SR.unit, + let (set_closure_idx, get_closure_idx) = new_local env "closure_idx" in + let (set_k, get_k) = new_local env "k" in + let (set_r, get_r) = new_local env "r" in + let mk_body env1 ae1 = compile_exp_as env1 ae1 SR.unit exp_f in + let captured = Freevars.captured exp_f in + FuncDec.async_body env ae ts captured mk_body exp.at ^^ + set_closure_idx ^^ + + compile_exp_as env ae SR.Vanilla exp_k ^^ set_k ^^ + compile_exp_as env ae SR.Vanilla exp_r ^^ set_r ^^ + + FuncDec.ic_call env [Type.Prim Type.Word32] ts + ( Dfinity.get_self_reference env ^^ + Dfinity.actor_public_field env (Dfinity.async_method_name)) + (get_closure_idx ^^ BoxedSmallWord.box env) + get_k + get_r | ActorE (i, ds, fs, _) -> Dfinity.reference_sr env, let captured = Freevars.exp exp in @@ -7481,7 +7570,6 @@ and actor_lit outer_env this ds fs at = Dfinity.register_reply mod_env; - let start_fun = Func.of_body mod_env [] [] (fun env -> G.with_region at @@ let ae0 = VarEnv.empty_ae in @@ -7489,7 +7577,7 @@ and actor_lit outer_env this ds fs at = let (ae1, prelude_code) = compile_prelude env ae0 in (* Add this pointer *) - let ae2 = VarEnv.add_local_deferred ae1 this SR.Vanilla Dfinity.get_self_reference false in + let ae2 = VarEnv.add_local_deferred ae1 this (Dfinity.reference_sr env) Dfinity.get_self_reference false in (* Reverse the fs, to a map from variable to exported name *) let v2en = E.NameEnv.from_list (List.map (fun f -> (f.it.var, f.it.name)) fs) in @@ -7549,7 +7637,7 @@ and actor_lit outer_env this ds fs at = (* Main actor: Just return the initialization code, and export functions as needed *) and main_actor env ae1 this ds fs = (* Add this pointer *) - let ae2 = VarEnv.add_local_deferred ae1 this SR.Vanilla Dfinity.get_self_reference false in + let ae2 = VarEnv.add_local_deferred ae1 this (Dfinity.reference_sr env) Dfinity.get_self_reference false in (* Reverse the fs, to a map from variable to exported name *) let v2en = E.NameEnv.from_list (List.map (fun f -> (f.it.var, f.it.name)) fs) in @@ -7564,6 +7652,8 @@ and main_actor env ae1 this ds fs = and conclude_module env module_name start_fi_o = + FuncDec.export_async_method env; + (* add beginning-of-heap pointer, may be changed by linker *) (* needs to happen here now that we know the size of static memory *) E.add_global32 env "__heap_base" Immutable (E.get_end_of_static_memory env); diff --git a/src/ir_def/arrange_ir.ml b/src/ir_def/arrange_ir.ml index ad4e25b7c30..ca0ed7d53b3 100644 --- a/src/ir_def/arrange_ir.ml +++ b/src/ir_def/arrange_ir.ml @@ -40,6 +40,8 @@ let rec exp e = match e.it with | DefineE (i, m, e1) -> "DefineE" $$ [id i; mut m; exp e1] | FuncE (x, s, c, tp, as_, ts, e) -> "FuncE" $$ [Atom x; func_sort s; control c] @ List.map typ_bind tp @ args as_@ [ typ (Type.seq ts); exp e] + | SelfCallE (ts, exp_f, exp_k, exp_r) -> + "SelfCallE" $$ [typ (Type.seq ts); exp exp_f; exp exp_k; exp exp_r] | ActorE (i, ds, fs, t) -> "ActorE" $$ [id i] @ List.map dec ds @ fields fs @ [typ t] | NewObjE (s, fs, t) -> "NewObjE" $$ (Arrange_type.obj_sort s :: fields fs @ [typ t]) | ThrowE e -> "ThrowE" $$ [exp e] diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 17b283905d1..bddab65a3d6 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -396,7 +396,7 @@ let rec check_exp env (exp:Ir.exp) : unit = | _ -> error env exp1.at "expected function type, but expression produces type\n %s" (T.string_of_typ_expand t1) - end + end | OtherPrim _, _ -> () | _ -> error env exp.at "PrimE with wrong number of arguments" @@ -616,6 +616,15 @@ let rec check_exp env (exp:Ir.exp) : unit = , tbs, List.map (T.close cs) ts1, List.map (T.close cs) ret_tys ) in fun_ty <: t + | SelfCallE (ts, exp_f, exp_k, exp_r) -> + check (not env.flavor.Ir.has_async_typ) "SelfCallE in async flavor"; + List.iter (check_typ env) ts; + check_exp env exp_f; + check_exp env exp_k; + check_exp env exp_r; + typ exp_f <: T.unit; + typ exp_k <: T.Func (T.Local, T.Returns, [], ts, []); + typ exp_r <: T.Func (T.Local, T.Returns, [], [T.text], []); | ActorE (id, ds, fs, t0) -> let env' = { env with async = false } in let ve0 = T.Env.singleton id t0 in diff --git a/src/ir_def/freevars.ml b/src/ir_def/freevars.ml index 9e158801167..1ae023fc615 100644 --- a/src/ir_def/freevars.ml +++ b/src/ir_def/freevars.ml @@ -87,6 +87,7 @@ let rec exp e : f = match e.it with | NewObjE (_, fs, _) -> fields fs | ThrowE e -> exp e | TryE (e, cs) -> exp e ++ cases cs + | SelfCallE (_, e1, e2, e3) -> under_lambda (exp e1) ++ exp e2 ++ exp e3 and fields fs = unions (fun f -> id f.it.var) fs diff --git a/src/ir_def/ir.ml b/src/ir_def/ir.ml index df1513673f8..e610ba1d0ef 100644 --- a/src/ir_def/ir.ml +++ b/src/ir_def/ir.ml @@ -88,6 +88,7 @@ and exp' = | DefineE of id * mut * exp (* promise fulfillment *) | FuncE of (* function *) string * Type.func_sort * Type.control * typ_bind list * arg list * Type.typ list * exp + | SelfCallE of Type.typ list * exp * exp * exp (* essentially ICCallPrim (FuncE shared…) *) | ActorE of id * dec list * field list * Type.typ (* actor *) | NewObjE of Type.obj_sort * field list * Type.typ (* make an object *) | ThrowE of exp (* throw *) diff --git a/src/ir_def/ir_effect.ml b/src/ir_def/ir_effect.ml index e818cd03a66..731d98cc0ca 100644 --- a/src/ir_def/ir_effect.ml +++ b/src/ir_def/ir_effect.ml @@ -74,6 +74,10 @@ let rec infer_effect_exp (exp: exp) : T.eff = effect_exp exp1 | FuncE _ -> T.Triv + | SelfCallE (_, _, exp1, exp2) -> + let e1 = effect_exp exp1 in + let e2 = effect_exp exp2 in + max_eff e1 e2 | ActorE _ -> T.Triv | NewObjE _ -> diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index e9bc4e99401..0211d5940f6 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -187,9 +187,8 @@ let actor_msg env id f v (k : V.value V.cont) = f v k ) -let make_unit_message env id v = +let make_unit_message env id call_conv f = let open CC in - let call_conv, f = V.as_func v in match call_conv with | {sort = T.Shared s; n_res = 0; _} -> Value.message_func s call_conv.n_args (fun v k -> @@ -200,10 +199,9 @@ let make_unit_message env id v = failwith ("unexpected call_conv " ^ string_of_call_conv call_conv) (* assert (false) *) -let make_async_message env id v = +let make_async_message env id call_conv f = assert env.flavor.has_async_typ; let open CC in - let call_conv, f = V.as_func v in match call_conv with | {sort = T.Shared s; control = T.Promises; _} -> Value.async_func s call_conv.n_args call_conv.n_res (fun v k -> @@ -217,10 +215,9 @@ let make_async_message env id v = failwith ("unexpected call_conv " ^ string_of_call_conv call_conv) (* assert (false) *) -let make_replying_message env id v = +let make_replying_message env id call_conv f = assert (not env.flavor.has_async_typ); let open CC in - let call_conv, f = V.as_func v in match call_conv with | {sort = T.Shared s; control = T.Replies; _} -> Value.replies_func s call_conv.n_args call_conv.n_res (fun v k -> @@ -232,11 +229,11 @@ let make_replying_message env id v = (* assert (false) *) -let make_message env x cc v : V.value = +let make_message env x cc f : V.value = match cc.CC.control with - | T.Returns -> make_unit_message env x v - | T.Promises-> make_async_message env x v - | T.Replies -> make_replying_message env x v + | T.Returns -> make_unit_message env x cc f + | T.Promises-> make_async_message env x cc f + | T.Replies -> make_replying_message env x cc f (* Literals *) @@ -388,7 +385,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = interpret_exp env expr (fun rv -> let call_conv, f = V.as_func v1 in check_call_conv exp1 call_conv; - check_call_conv_arg env exp2 v2 call_conv; + check_call_conv_arg env exp v2 call_conv; last_region := exp.at; (* in case the following throws *) f (V.Tup[kv;rv;v2]) k)))) | _ -> @@ -499,28 +496,33 @@ and interpret_exp_mut env exp (k : V.value V.cont) = define_id env id v'; k V.unit ) + | SelfCallE (ts, exp_f, exp_k, exp_r) -> + assert (not env.flavor.has_async_typ); + (* see code for FuncE *) + let cc = { sort = T.Shared T.Write; control = T.Replies; n_args = 0; n_res = List.length ts } in + let f = interpret_message env exp.at "anon" [] + (fun env' -> interpret_exp env' exp_f) in + let v = make_message env "anon" cc f in + (* see code for ICCallPrim *) + interpret_exp env exp_k (fun kv -> + interpret_exp env exp_r (fun rv -> + let _call_conv, f = V.as_func v in + last_region := exp.at; (* in case the following throws *) + f (V.Tup[kv;rv;V.Tup []]) k)) | FuncE (x, (T.Shared _ as sort), (T.Replies as control), _typbinds, args, ret_typs, e) -> assert (not env.flavor.has_async_typ); let cc = { sort; control; n_args = List.length args; n_res = List.length ret_typs } in - let f = interpret_message env exp.at x args - (fun env' -> - interpret_exp env' e) in - - let v = V.Func (cc, f) in - let v = make_message env x cc v in + (fun env' -> interpret_exp env' e) in + let v = make_message env x cc f in k v - | FuncE (x, sort, control, _typbinds, args, ret_typs, e) -> let cc = { sort; control; n_args = List.length args; n_res = List.length ret_typs } in - let f = interpret_func env exp.at x args (fun env' -> interpret_exp env' e) in - let v = V.Func (cc, f) in - let v = - match cc.sort with - | T.Shared _ -> make_message env x cc v - | _-> v + let v = match cc.sort with + | T.Shared _ -> make_message env x cc f + | _ -> V.Func (cc, f) in k v | ActorE (id, ds, fs, _) -> diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index bea00ebce5d..7d0f4c72ba8 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -29,7 +29,7 @@ let error_codeE mode = match mode with | Flags.ICMode -> callE (idE "@int32ToErrorCode" - (T.Func(T.Local,T.Returns,[],[T.Prim T.Int32],[T.Variant T.catchErrorCodes]))) + (T.Func (T.Local, T.Returns, [], [T.Prim T.Int32], [T.Variant T.catchErrorCodes]))) [] (ic_error_codeE()) | _ -> { it = TagE ("error", tupE []); @@ -39,6 +39,13 @@ let error_codeE mode = note_eff = T.Triv } } +let selfcallE ts e1 e2 e3 = + { it = SelfCallE (ts, e1, e2, e3); + at = no_region; + note = { note_typ = T.unit; + note_eff = T.Triv } +} + let errorMessageE e = { it = PrimE (OtherPrim "errorMessage", [e]); at = no_region; @@ -264,22 +271,19 @@ let transform mode env prog = IdxE (t_exp exp1, t_exp exp2) | PrimE (CPSAwait, [a;kr]) -> ((t_exp a) -*- (t_exp kr)).it - | PrimE (CPSAsync, [exp2]) -> - let ts1 = match typ exp2 with + | PrimE (CPSAsync, [exp1]) -> + let ts1 = match typ exp1 with | Func(_,_, [], [Func(_, _, [], ts1, []); _], []) -> List.map t_typ ts1 | t -> assert false in - let post = fresh_var "post" (T.Func(T.Shared T.Write, T.Replies, [], [], ts1)) in - let u = fresh_var "u" T.unit in let ((nary_async, nary_reply, reject), def) = new_nary_async_reply mode ts1 in - (blockE [letP (tupP [varP nary_async; varP nary_reply; varP reject]) def; - funcD post u ( - let vs = fresh_vars "v" ts1 in - let k = vs -->* (ic_replyE ts1 (seqE vs)) in - let e = fresh_var "e" T.catch in - let r = [e] -->* (ic_rejectE (errorMessageE e)) in - (t_exp exp2) -*- tupE [k;r]); - - expD (ic_callE post (seqE []) nary_reply reject); + (blockE [ + letP (tupP [varP nary_async; varP nary_reply; varP reject]) def; + let v = fresh_var "v" (T.seq ts1) in + let ic_reply = v --> (ic_replyE ts1 v) in + let e = fresh_var "e" T.catch in + let ic_reject = [e] -->* (ic_rejectE (errorMessageE e)) in + let exp' = t_exp exp1 -*- tupE [ic_reply; ic_reject] in + expD (selfcallE ts1 exp' nary_reply reject) ] nary_async ).it @@ -405,6 +409,7 @@ let transform mode env prog = ActorE (id, t_decs ds, t_fields fs, t_typ typ) | NewObjE (sort, ids, t) -> NewObjE (sort, t_fields ids, t_typ t) + | SelfCallE _ -> assert false and t_dec dec = { dec with it = t_dec' dec.it } @@ -458,4 +463,3 @@ let transform mode env prog = and t_prog (prog, flavor) = (t_block prog, { flavor with has_async_typ = false } ) in t_prog prog - diff --git a/src/ir_passes/await.ml b/src/ir_passes/await.ml index c9b8d89a475..0c0d25cb030 100644 --- a/src/ir_passes/await.ml +++ b/src/ir_passes/await.ml @@ -142,6 +142,7 @@ and t_exp' context exp' = | ActorE (id, ds, ids, t) -> ActorE (id, t_decs context ds, ids, t) | NewObjE (sort, ids, typ) -> exp' + | SelfCallE _ -> assert false and t_dec context dec = {dec with it = t_dec' context dec.it} @@ -387,6 +388,7 @@ and c_exp' context exp k = | DefineE (id, mut, exp1) -> unary context k (fun v1 -> e (DefineE (id, mut, v1))) exp1 | NewObjE _ -> exp + | SelfCallE _ -> assert false and c_block context decs exp k = let is_typ dec = diff --git a/src/ir_passes/rename.ml b/src/ir_passes/rename.ml index e60d6993711..319d3d5c1b9 100644 --- a/src/ir_passes/rename.ml +++ b/src/ir_passes/rename.ml @@ -69,6 +69,8 @@ and exp' rho e = match e with | NewObjE (s, fs, t) -> NewObjE (s, fields rho fs, t) | ThrowE e -> ThrowE (exp rho e) | TryE (e, cs) -> TryE (exp rho e, cases rho cs) + | SelfCallE (ts, e1, e2, e3) -> + SelfCallE (ts, exp rho e1, exp rho e2, exp rho e3) and exps rho es = List.map (exp rho) es diff --git a/src/ir_passes/show.ml b/src/ir_passes/show.ml index 5348d8d2723..b0c0bef564d 100644 --- a/src/ir_passes/show.ml +++ b/src/ir_passes/show.ml @@ -134,6 +134,8 @@ and t_exp' env = function DefineE (id, mut, t_exp env exp1) | NewObjE (sort, ids, t) -> NewObjE (sort, ids, t) + | SelfCallE (ts, e1, e2, e3) -> + SelfCallE (ts, t_exp env e1, t_exp env e2, t_exp env e3) and t_dec env dec = { dec with it = t_dec' env dec.it } diff --git a/src/ir_passes/tailcall.ml b/src/ir_passes/tailcall.ml index dc5ca3ca8b7..612e11206db 100644 --- a/src/ir_passes/tailcall.ml +++ b/src/ir_passes/tailcall.ml @@ -136,6 +136,12 @@ and exp' env e : exp' = match e.it with let env2 = args env1 as_ in let exp0' = tailexp env2 exp0 in FuncE (x, s, c, tbs, as_, ret_tys, exp0') + | SelfCallE (ts, exp1, exp2, exp3) -> + let env1 = { tail_pos = true; info = None} in + let exp1' = tailexp env1 exp1 in + let exp2' = exp env exp2 in + let exp3' = exp env exp3 in + SelfCallE (ts, exp1', exp2', exp3') | ActorE (i, ds, fs, t) -> ActorE (i, ds, fs, t) (* TODO: descent into ds *) | NewObjE (s,is,t) -> NewObjE (s, is, t) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 707db2411f1..0217886d781 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -926,7 +926,7 @@ and infer_exp'' env exp : T.typ = T.Non | AsyncE exp1 -> if not (in_shared_async env || in_oneway_ignore env) then - error_in [Flags.ICMode; Flags.StubMode] env exp.at "unsupported async block"; + error_in [Flags.ICMode] env exp.at "unsupported async block"; let env' = {env with labs = T.Env.empty; rets = Some T.Pre; async = true} in let t = infer_exp env' exp1 in @@ -941,7 +941,7 @@ and infer_exp'' env exp : T.typ = (match exp1.it with | CallE (f, _, _) -> if not env.pre && (Call_conv.call_conv_of_typ f.note.note_typ).Call_conv.control = T.Returns then - error_in [Flags.ICMode; Flags.StubMode] env f.at "expecting call to shared async function in await"; + error_in [Flags.ICMode] env f.at "expecting call to shared async function in await"; | _ -> error_in [Flags.ICMode] env exp1.at "argument to await must be a call expression"); (try T.as_async_sub t1 @@ -1006,7 +1006,7 @@ and check_exp' env0 t exp : T.typ = t | AsyncE exp1, T.Async t' -> if not (in_shared_async env || in_oneway_ignore env) then - error_in [Flags.ICMode; Flags.StubMode] env exp.at "freestanding async expression not yet supported"; + error_in [Flags.ICMode] env exp.at "freestanding async expression not yet supported"; let env' = {env with labs = T.Env.empty; rets = Some t'; async = true} in check_exp env' t' exp1; t diff --git a/test/run-dfinity/async-free-var.mo b/test/run-dfinity/async-free-var.mo new file mode 100644 index 00000000000..7edddece50a --- /dev/null +++ b/test/run-dfinity/async-free-var.mo @@ -0,0 +1,15 @@ +ignore async { + var x = "A"; + debugPrint x; + let a = async { + debugPrint "Now in async"; + debugPrint x; + x := "B"; + debugPrint x; + }; + debugPrint x; + x := "C"; + debugPrint x; + await a; + debugPrint x; +}; diff --git a/test/run-dfinity/interleave.mo b/test/run-dfinity/interleave.mo new file mode 100644 index 00000000000..65627075f54 --- /dev/null +++ b/test/run-dfinity/interleave.mo @@ -0,0 +1,37 @@ +var cnt : Nat = 0; + +func f(m: Text, i:Nat) : async Nat { + debugPrint (m # " cnt: " # debug_show cnt # " i: " # debug_show i); + cnt += 1; + cnt; +}; + + + +let e = async { + var i = 5; + debugPrint " e-while\n"; + while (i < 10) { + let _ = await f(" e",i); + i += 1; + }; + debugPrint " e-exit\n"; +}; + +debugPrint "g"; + +let g = async { + var i = 10; + debugPrint "g-label\n"; + label lp + while (true) { + if (i < 15) { + let _ = await f("g",i); + i += 1; + continue lp; + } else {}; + break lp; + }; + debugPrint "g-exit\n"; +}; + diff --git a/test/run-dfinity/ok/async-free-var.dvm.ok b/test/run-dfinity/ok/async-free-var.dvm.ok new file mode 100644 index 00000000000..3bf15dcf814 --- /dev/null +++ b/test/run-dfinity/ok/async-free-var.dvm.ok @@ -0,0 +1,7 @@ +A +A +C +Now in async +C +B +B diff --git a/test/run-dfinity/ok/async-free-var.run-ir.ok b/test/run-dfinity/ok/async-free-var.run-ir.ok new file mode 100644 index 00000000000..3bf15dcf814 --- /dev/null +++ b/test/run-dfinity/ok/async-free-var.run-ir.ok @@ -0,0 +1,7 @@ +A +A +C +Now in async +C +B +B diff --git a/test/run-dfinity/ok/async-free-var.run-low.ok b/test/run-dfinity/ok/async-free-var.run-low.ok new file mode 100644 index 00000000000..3bf15dcf814 --- /dev/null +++ b/test/run-dfinity/ok/async-free-var.run-low.ok @@ -0,0 +1,7 @@ +A +A +C +Now in async +C +B +B diff --git a/test/run-dfinity/ok/async-free-var.run.ok b/test/run-dfinity/ok/async-free-var.run.ok new file mode 100644 index 00000000000..3bf15dcf814 --- /dev/null +++ b/test/run-dfinity/ok/async-free-var.run.ok @@ -0,0 +1,7 @@ +A +A +C +Now in async +C +B +B diff --git a/test/run-dfinity/ok/interleave.dvm.ok b/test/run-dfinity/ok/interleave.dvm.ok new file mode 100644 index 00000000000..9e55fa80c2d --- /dev/null +++ b/test/run-dfinity/ok/interleave.dvm.ok @@ -0,0 +1,19 @@ +g + e-while + + e cnt: 0 i: 5 + e cnt: 1 i: 6 + e cnt: 2 i: 7 + e cnt: 3 i: 8 + e cnt: 4 i: 9 + e-exit + +g-label + +g cnt: 5 i: 10 +g cnt: 6 i: 11 +g cnt: 7 i: 12 +g cnt: 8 i: 13 +g cnt: 9 i: 14 +g-exit + diff --git a/test/run-dfinity/ok/interleave.run-ir.ok b/test/run-dfinity/ok/interleave.run-ir.ok new file mode 100644 index 00000000000..84affc5daf2 --- /dev/null +++ b/test/run-dfinity/ok/interleave.run-ir.ok @@ -0,0 +1,19 @@ +g + e-while + +g-label + + e cnt: 0 i: 5 +g cnt: 1 i: 10 + e cnt: 2 i: 6 +g cnt: 3 i: 11 + e cnt: 4 i: 7 +g cnt: 5 i: 12 + e cnt: 6 i: 8 +g cnt: 7 i: 13 + e cnt: 8 i: 9 +g cnt: 9 i: 14 + e-exit + +g-exit + diff --git a/test/run-dfinity/ok/interleave.run-low.ok b/test/run-dfinity/ok/interleave.run-low.ok new file mode 100644 index 00000000000..84affc5daf2 --- /dev/null +++ b/test/run-dfinity/ok/interleave.run-low.ok @@ -0,0 +1,19 @@ +g + e-while + +g-label + + e cnt: 0 i: 5 +g cnt: 1 i: 10 + e cnt: 2 i: 6 +g cnt: 3 i: 11 + e cnt: 4 i: 7 +g cnt: 5 i: 12 + e cnt: 6 i: 8 +g cnt: 7 i: 13 + e cnt: 8 i: 9 +g cnt: 9 i: 14 + e-exit + +g-exit + diff --git a/test/run-dfinity/ok/interleave.run.ok b/test/run-dfinity/ok/interleave.run.ok new file mode 100644 index 00000000000..84affc5daf2 --- /dev/null +++ b/test/run-dfinity/ok/interleave.run.ok @@ -0,0 +1,19 @@ +g + e-while + +g-label + + e cnt: 0 i: 5 +g cnt: 1 i: 10 + e cnt: 2 i: 6 +g cnt: 3 i: 11 + e cnt: 4 i: 7 +g cnt: 5 i: 12 + e cnt: 6 i: 8 +g cnt: 7 i: 13 + e cnt: 8 i: 9 +g cnt: 9 i: 14 + e-exit + +g-exit + diff --git a/test/run-dfinity/ok/overflow.dvm.ok b/test/run-dfinity/ok/overflow.dvm.ok index 29962e83f4e..86d13f58ad8 100644 --- a/test/run-dfinity/ok/overflow.dvm.ok +++ b/test/run-dfinity/ok/overflow.dvm.ok @@ -1,5 +1,5 @@ -hypervisor: calling func$NNN failed with trap message: Uncaught RuntimeError: unreachable -hypervisor: calling func$NNN failed with trap message: Uncaught RuntimeError: unreachable +hypervisor: calling __motoko_async_helper failed with trap message: Uncaught RuntimeError: unreachable +hypervisor: calling __motoko_async_helper failed with trap message: Uncaught RuntimeError: unreachable This is reachable. This is reachable. Natural subtraction underflow diff --git a/test/run-stub/ok/unsupported.comp.ok b/test/run-stub/ok/unsupported.comp.ok index 5ea780b32b5..c443aedda7e 100644 --- a/test/run-stub/ok/unsupported.comp.ok +++ b/test/run-stub/ok/unsupported.comp.ok @@ -1,12 +1,6 @@ -unsupported.mo:32.17-32.29: type error, unsupported async block - (This is a limitation of the current version and flag -stub-system-api.) unsupported.mo:4.5-4.41: type error, a shared function cannot be private (This is a limitation of the current version and flag -stub-system-api.) unsupported.mo:38.26-38.29: type error, a shared function is only allowed as a public field of an actor (This is a limitation of the current version and flag -stub-system-api.) -unsupported.mo:41.10-41.18: type error, unsupported async block - (This is a limitation of the current version and flag -stub-system-api.) unsupported.mo:62.3-62.35: type error, actor classes are not supported; use an actor declaration instead (This is a limitation of the current version and flag -stub-system-api.) -unsupported.mo:76.34-76.37: type error, freestanding async expression not yet supported - (This is a limitation of the current version and flag -stub-system-api.) From a120a7d280619cc4a7590f9bd794d42925e6e7a1 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 26 Nov 2019 16:23:05 +0100 Subject: [PATCH 0712/1176] Typing: Check FuncE restrictions also in checking mode (#932) --- src/mo_frontend/typing.ml | 4 +++- test/run-stub/ok/unsupported.comp.ok | 4 ++++ test/run-stub/unsupported.mo | 7 ++++++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 0217886d781..a2a82dc92e5 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -974,7 +974,7 @@ and check_exp env t exp = exp.note <- {note_typ = t'; note_eff = e} and check_exp' env0 t exp : T.typ = - let env = {env0 with in_prog = false; context = exp.it :: env0.context } in + let env = {env0 with in_prog = false; in_actor = false; context = exp.it :: env0.context } in match exp.it, t with | PrimE s, T.Func _ -> t @@ -1044,6 +1044,8 @@ and check_exp' env0 t exp : T.typ = ); t | FuncE (_, s', [], pat, typ_opt, exp), T.Func (s, c, [], ts1, ts2) -> + if not env.pre && not env0.in_actor && T.is_shared_sort s'.it then + error_in [Flags.ICMode; Flags.StubMode] env exp.at "a shared function is only allowed as a public field of an actor"; let ve = check_pat_exhaustive env (T.seq ts1) pat in let codom = T.codom c ts2 in let t2 = diff --git a/test/run-stub/ok/unsupported.comp.ok b/test/run-stub/ok/unsupported.comp.ok index c443aedda7e..24c01e4cd61 100644 --- a/test/run-stub/ok/unsupported.comp.ok +++ b/test/run-stub/ok/unsupported.comp.ok @@ -4,3 +4,7 @@ unsupported.mo:38.26-38.29: type error, a shared function is only allowed as a p (This is a limitation of the current version and flag -stub-system-api.) unsupported.mo:62.3-62.35: type error, actor classes are not supported; use an actor declaration instead (This is a limitation of the current version and flag -stub-system-api.) +unsupported.mo:80.34-80.37: type error, a shared function is only allowed as a public field of an actor + (This is a limitation of the current version and flag -stub-system-api.) +unsupported.mo:81.27-81.30: type error, a shared function is only allowed as a public field of an actor + (This is a limitation of the current version and flag -stub-system-api.) diff --git a/test/run-stub/unsupported.mo b/test/run-stub/unsupported.mo index b31f825c639..7a043cde6df 100644 --- a/test/run-stub/unsupported.mo +++ b/test/run-stub/unsupported.mo @@ -73,4 +73,9 @@ func local_spawn() { actor BadSecondActor { }; -func implicit_async() : async () { }; // async functions not supported +// async functions not supported (inference mode) +func implicit_async() : async () { }; + +// anonymous shared functions not supported (inference and checking mode) +let _ = shared func() : async () { }; +(shared func() : async () { }) : shared () -> async (); From c0986af833ca218d1034bd71ba7f82953d786afe Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 26 Nov 2019 17:52:34 +0100 Subject: [PATCH 0713/1176] Follow System API changes in `drun` (#929) * Follow System API changes in `drun` as @chmllr is updating the `client` in steps to the `ic0` system api in https://github.com/dfinity-lab/dfinity/pull/1954 * bump drun * Actually update imports * Bump dfinity to master to get https://github.com/dfinity-lab/dfinity/pull/1954 (no more use of the API nonce). Also remove the `drun` parameter to `default.nix`, due to https://github.com/dfinity-lab/dfinity/pull/1958 --- default.nix | 26 ++++++-------------- src/codegen/compile.ml | 55 ++++++------------------------------------ 2 files changed, 16 insertions(+), 65 deletions(-) diff --git a/default.nix b/default.nix index 7d1ffd56be4..489e3f94097 100644 --- a/default.nix +++ b/default.nix @@ -1,6 +1,4 @@ { - dvm ? null, - drun ? null, replay ? 0, system ? builtins.currentSystem, }: @@ -28,8 +26,8 @@ let dev = import (builtins.fetchGit { let dfinity-repo = import (builtins.fetchGit { name = "dfinity-sources"; url = "ssh://git@github.com/dfinity-lab/dfinity"; - ref = "master"; - rev = "5c7efff0524adbf97d85b27adb180e6137a3428f"; + # ref = "master"; + rev = "a77f9b30fa5b1f35bef2913c2329e2c8e81c1af8"; }) { inherit (nixpkgs) system; }; in let sdk = import (builtins.fetchGit { @@ -44,16 +42,8 @@ let esm = builtins.fetchTarball { url = "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz"; }; in -let real-dvm = - if dvm == null - then dev.dvm - else dvm; in - -let real-drun = - if drun == null - then dfinity-repo.drun or dfinity-repo.dfinity.drun - else drun; in - +let dvm = dev.dvm; in +let drun = dfinity-repo.drun or dfinity-repo.dfinity.drun; in let js-user-library = sdk.js-user-library; in let haskellPackages = nixpkgs.haskellPackages.override { @@ -226,7 +216,7 @@ rec { filecheck js-user-library dvm - real-drun + drun wasmtime haskellPackages.qc-motoko haskellPackages.lsp-int @@ -285,7 +275,7 @@ rec { nixpkgs.bash nixpkgs.perl filecheck - real-drun + drun ] ++ llvmBuildInputs; @@ -328,8 +318,8 @@ rec { ''; }; - dvm = real-dvm; - drun = real-drun; + inherit dvm; + inherit drun; filecheck = nixpkgs.linkFarm "FileCheck" [ { name = "bin/FileCheck"; path = "${nixpkgs.llvm}/bin/FileCheck";} ]; wabt = nixpkgs.wabt; diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index f2b9e3e89ec..649a6d000b9 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -3031,33 +3031,19 @@ end (* Tuple *) module Dfinity = struct (* Dfinity-specific stuff: System imports, databufs etc. *) - let set_api_nonce env = - assert (E.mode env = Flags.ICMode); - G.i (GlobalSet (nr (E.get_global env "api_nonce"))) - - let get_api_nonce env = - if E.mode env = Flags.ICMode - then G.i (GlobalGet (nr (E.get_global env "api_nonce"))) - else G.nop - let set_reply_cont env = G.i (GlobalSet (nr (E.get_global env "reply_cont"))) let get_reply_cont env = G.i (GlobalGet (nr (E.get_global env "reply_cont"))) - let register_globals env = - (* current api_nonce *) - if E.mode env = Flags.ICMode - then E.add_global64 env "api_nonce" Mutable 0L - let system_imports env = let i32s n = Lib.List.make n I32Type in match E.mode env with | Flags.ICMode -> E.add_func_import env "debug" "print" [I32Type; I32Type] []; - E.add_func_import env "msg" "arg_data_size" [I64Type] [I32Type]; - E.add_func_import env "msg" "arg_data_copy" [I64Type; I32Type; I32Type; I32Type] []; - E.add_func_import env "msg" "reply" [I64Type; I32Type; I32Type] []; - E.add_func_import env "msg" "reject" [I64Type; I32Type; I32Type] []; - E.add_func_import env "msg" "reject_code" [I64Type] [I32Type]; + E.add_func_import env "msg" "arg_data_size" [] [I32Type]; + E.add_func_import env "msg" "arg_data_copy" [I32Type; I32Type; I32Type] []; + E.add_func_import env "msg" "reply" [I32Type; I32Type] []; + E.add_func_import env "msg" "reject" [I32Type; I32Type] []; + E.add_func_import env "msg" "reject_code" [] [I32Type]; E.add_func_import env "ic" "trap" [I32Type; I32Type] []; () | Flags.StubMode -> @@ -3280,9 +3266,8 @@ module Dfinity = struct let export_start env start_fi = assert (E.mode env = Flags.ICMode || E.mode env = Flags.StubMode); - let args = if E.mode env = Flags.ICMode then ["api_nonce",I64Type] else [] in (* Create an empty message *) - let empty_f = Func.of_body env args [] (fun env1 -> + let empty_f = Func.of_body env [] [] (fun env1 -> G.i (Call (nr start_fi)) ^^ (* Collect garbage *) G.i (Call (nr (E.built_in env1 "collect"))) @@ -3338,7 +3323,6 @@ module Dfinity = struct let reject env arg_instrs = match E.mode env with | Flags.ICMode | Flags.StubMode -> - get_api_nonce env ^^ let (set_text, get_text) = new_local env "text" in arg_instrs ^^ set_text ^^ @@ -3358,7 +3342,6 @@ module Dfinity = struct SR.UnboxedWord32, match E.mode env with | Flags.ICMode -> - get_api_nonce env ^^ system_call env "msg" "reject_code" | Flags.StubMode -> system_call env "ic" "msg_reject_code" @@ -3367,7 +3350,6 @@ module Dfinity = struct let reply_with_data env = Func.share_code2 env "reply_with_data" (("start", I32Type), ("size", I32Type)) [] ( fun env get_data_start get_data_size -> - get_api_nonce env ^^ get_data_start ^^ get_data_size ^^ match E.mode env with @@ -4390,7 +4372,6 @@ module Serialization = struct let argument_data_size env = match E.mode env with | Flags.ICMode -> - Dfinity.get_api_nonce env ^^ Dfinity.system_call env "msg" "arg_data_size" | Flags.StubMode -> Dfinity.system_call env "ic0" "msg_arg_data_size" @@ -4399,7 +4380,6 @@ module Serialization = struct let argument_data_copy env get_dest get_length = match E.mode env with | Flags.ICMode -> - Dfinity.get_api_nonce env ^^ get_dest ^^ get_length ^^ (compile_unboxed_const 0l) ^^ @@ -5300,8 +5280,7 @@ module FuncDec = struct )) | Flags.ICMode, _ -> let ae0 = VarEnv.mk_fun_ae outer_ae in - Func.of_body outer_env ["api_nonce", I64Type] [] (fun env -> G.with_region at ( - G.i (LocalGet (nr 0l)) ^^ Dfinity.set_api_nonce env ^^ + Func.of_body outer_env [] [] (fun env -> G.with_region at ( (* reply early for a oneway *) (if control = Type.Returns then @@ -5632,23 +5611,7 @@ module FuncDec = struct edesc = nr (FuncExport (nr fi)) }) - | Flags.ICMode -> - Func.define_built_in env name ["api_nonce", I64Type] [] (fun env -> - let (set_closure, get_closure) = new_local env "closure" in - - G.i (LocalGet (nr 0l)) ^^ Dfinity.set_api_nonce env ^^ - - (* TODO: Check that it is us that is calling this *) - - (* Deserialize and look up closure argument *) - Serialization.deserialize env [Type.Prim Type.Word32] ^^ - BoxedSmallWord.unbox env ^^ - ClosureTable.recall_closure env ^^ - set_closure ^^ get_closure ^^ get_closure ^^ - Closure.call_closure env 0 0 ^^ - message_cleanup env (Type.Shared Type.Write) - ); - | Flags.StubMode -> + | Flags.ICMode | Flags.StubMode -> Func.define_built_in env name [] [] (fun env -> let (set_closure, get_closure) = new_local env "closure" in @@ -7562,7 +7525,6 @@ and actor_lit outer_env this ds fs at = Heap.register_globals mod_env; if E.mode mod_env = Flags.AncientMode then ElemHeap.register_globals mod_env; Stack.register_globals mod_env; - Dfinity.register_globals mod_env; Dfinity.system_imports mod_env; RTS.system_imports mod_env; @@ -7733,7 +7695,6 @@ let compile mode module_name rts (prelude : Ir.prog) (progs : Ir.prog list) : Wa Heap.register_globals env; if E.mode env = Flags.AncientMode then ElemHeap.register_globals env; Stack.register_globals env; - Dfinity.register_globals env; Dfinity.system_imports env; RTS.system_imports env; From d03407b948dae089953ae6a8cdab82aa10ec2c49 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 26 Nov 2019 18:05:09 +0100 Subject: [PATCH 0714/1176] More emptying out of `run-dfinity` (#934) * More emptying out of `run-dfinity` with only three test cases left (these require allowing classes with no parameters, which we can easily allow) * Add more files * fix path, delete files * Move remaining test cases to run/ these will just be interpreted for now --- test/repl/type-lub-repl.sh | 2 +- test/run-dfinity/closure-params.mo | 21 --- test/run-dfinity/nary-async.mo | 147 ------------------ test/run-dfinity/ok/GIT-843.dvm.ok | 1 - test/run-dfinity/ok/GIT-843.run-ir.ok | 1 - test/run-dfinity/ok/GIT-843.run-low.ok | 1 - test/run-dfinity/ok/GIT-843.run.ok | 1 - test/run-dfinity/ok/async-free-var.dvm.ok | 7 - test/run-dfinity/ok/async-loop-while.dvm.ok | 12 -- test/run-dfinity/ok/async-loop.dvm.ok | 12 -- test/run-dfinity/ok/async-new-obj.dvm.ok | 5 - test/run-dfinity/ok/async-obj-mut.dvm.ok | 8 - test/run-dfinity/ok/async-while.dvm.ok | 12 -- test/run-dfinity/ok/await.dvm.ok | 27 ---- test/run-dfinity/ok/block.dvm.ok | 10 -- test/run-dfinity/ok/chatpp.dvm.ok | 6 - test/run-dfinity/ok/closure-params.dvm.ok | 10 -- test/run-dfinity/ok/counter-class.comp.ok | 60 ------- test/run-dfinity/ok/counter-class.dvm.ok | 3 - test/run-dfinity/ok/counter.dvm.ok | 14 -- test/run-dfinity/ok/counter.run-ir.ok | 14 -- test/run-dfinity/ok/counter.run-low.ok | 14 -- test/run-dfinity/ok/counter.run.ok | 14 -- test/run-dfinity/ok/for-await.dvm.ok | 11 -- test/run-dfinity/ok/hello-world-await.dvm.ok | 1 - .../ok/hello-world-await.run-ir.ok | 1 - .../ok/hello-world-await.run-low.ok | 1 - test/run-dfinity/ok/hello-world-await.run.ok | 1 - test/run-dfinity/ok/indirect-counter.dvm.ok | 4 - .../run-dfinity/ok/indirect-counter.run-ir.ok | 4 - .../ok/indirect-counter.run-low.ok | 4 - test/run-dfinity/ok/indirect-counter.run.ok | 4 - test/run-dfinity/ok/interleave.dvm.ok | 19 --- test/run-dfinity/ok/local-throw.dvm.ok | 2 - test/run-dfinity/ok/nary-async.dvm.ok | 8 - test/run-dfinity/ok/overflow.dvm.ok | 10 -- test/run-dfinity/ok/query.dvm.ok | 10 -- test/run-dfinity/ok/query.run-ir.ok | 11 -- test/run-dfinity/ok/query.run-low.ok | 11 -- test/run-dfinity/ok/query.run.ok | 11 -- test/run-dfinity/ok/reference-params.dvm.ok | 5 - test/run-dfinity/ok/simple-throw.dvm.ok | 5 - test/run-dfinity/query.mo | 62 -------- test/run-dfinity/reference-params.mo | 47 ------ test/{run-dfinity => run-stub}/AST-66.mo | 0 test/{run-dfinity => run-stub}/async-any.mo | 0 .../async-free-var.mo | 0 .../async-loop-while.mo | 0 test/{run-dfinity => run-stub}/async-loop.mo | 0 .../async-new-obj.mo | 0 .../async-obj-mut.mo | 0 test/{run-dfinity => run-stub}/async-while.mo | 0 test/{run-dfinity => run-stub}/await.mo | 0 test/{run-dfinity => run-stub}/block.mo | 0 test/run-stub/closure-params.mo | 24 +++ .../flatten-awaitables.mo | 0 test/{run-dfinity => run-stub}/for-await.mo | 0 test/{run-dfinity => run-stub}/interleave.mo | 0 test/{run-dfinity => run-stub}/local-throw.mo | 4 +- test/run-stub/nary-async.mo | 103 ++++++++++++ test/run-stub/ok/AST-66.ic-stub-run.ok | 4 + test/run-stub/ok/async-any.ic-stub-run.ok | 4 + .../run-stub/ok/async-free-var.ic-stub-run.ok | 11 ++ .../ok/async-free-var.run-ir.ok | 0 .../ok/async-free-var.run-low.ok | 0 .../ok/async-free-var.run.ok | 0 .../ok/async-loop-while.ic-stub-run.ok | 16 ++ .../ok/async-loop-while.run-ir.ok | 0 .../ok/async-loop-while.run-low.ok | 0 .../ok/async-loop-while.run.ok | 0 test/run-stub/ok/async-loop.ic-stub-run.ok | 16 ++ .../ok/async-loop.run-ir.ok | 0 .../ok/async-loop.run-low.ok | 0 .../ok/async-loop.run.ok | 0 test/run-stub/ok/async-new-obj.ic-stub-run.ok | 9 ++ .../ok/async-new-obj.run-ir.ok | 0 .../ok/async-new-obj.run-low.ok | 0 .../ok/async-new-obj.run.ok | 0 test/run-stub/ok/async-obj-mut.ic-stub-run.ok | 12 ++ .../ok/async-obj-mut.run-ir.ok | 0 .../ok/async-obj-mut.run-low.ok | 0 .../ok/async-obj-mut.run.ok | 0 test/run-stub/ok/async-while.ic-stub-run.ok | 16 ++ .../ok/async-while.run-ir.ok | 0 .../ok/async-while.run-low.ok | 0 .../ok/async-while.run.ok | 0 test/run-stub/ok/await.ic-stub-run.ok | 31 ++++ .../ok/await.run-ir.ok | 0 .../ok/await.run-low.ok | 0 .../{run-dfinity => run-stub}/ok/await.run.ok | 0 test/run-stub/ok/block.ic-stub-run.ok | 14 ++ .../ok/block.run-ir.ok | 0 .../ok/block.run-low.ok | 0 .../{run-dfinity => run-stub}/ok/block.run.ok | 0 .../run-stub/ok/closure-params.ic-stub-run.ok | 14 ++ .../ok/closure-params.run-ir.ok | 0 .../ok/closure-params.run-low.ok | 0 .../ok/closure-params.run.ok | 0 .../ok/flatten-awaitables.ic-stub-run.ok} | 4 + .../ok/flatten-awaitables.run-ir.ok | 0 .../ok/flatten-awaitables.run-low.ok | 0 .../ok/flatten-awaitables.run.ok | 0 .../ok/flatten-awaitables.tc.ok | 0 test/run-stub/ok/for-await.ic-stub-run.ok | 15 ++ .../ok/for-await.run-ir.ok | 0 .../ok/for-await.run-low.ok | 0 .../ok/for-await.run.ok | 0 test/run-stub/ok/interleave.ic-stub-run.ok | 23 +++ .../ok/interleave.run-ir.ok | 0 .../ok/interleave.run-low.ok | 0 .../ok/interleave.run.ok | 0 test/run-stub/ok/local-throw.ic-stub-run.ok | 6 + .../ok/local-throw.run-ir.ok | 0 .../ok/local-throw.run-low.ok | 0 .../ok/local-throw.run.ok | 0 test/run-stub/ok/nary-async.ic-stub-run.ok | 12 ++ .../ok/nary-async.run-ir.ok | 2 +- .../ok/nary-async.run-low.ok | 2 +- .../ok/nary-async.run.ok | 2 +- test/run-stub/ok/overflow.ic-stub-run.ok | 12 ++ .../ok/overflow.run-ir.ok | 0 .../ok/overflow.run-low.ok | 0 .../ok/overflow.run.ok | 0 test/run-stub/ok/query2.ic-stub-run.ok | 10 ++ test/run-stub/ok/query2.run-ir.ok | 12 ++ test/run-stub/ok/query2.run-low.ok | 12 ++ test/run-stub/ok/query2.run.ok | 12 ++ .../ok/reference-params.ic-stub-run.ok | 9 ++ .../ok/reference-params.run-ir.ok | 0 .../ok/reference-params.run-low.ok | 0 .../ok/reference-params.run.ok | 0 test/run-stub/ok/simple-throw.ic-stub-run.ok | 9 ++ .../ok/simple-throw.run-ir.ok | 0 .../ok/simple-throw.run-low.ok | 0 .../ok/simple-throw.run.ok | 0 test/run-stub/ok/type-lub.ic-stub-run.ok | 4 + test/{run-dfinity => run-stub}/overflow.mo | 0 test/run-stub/query2.mo | 66 ++++++++ test/run-stub/reference-params.mo | 49 ++++++ .../{run-dfinity => run-stub}/simple-throw.mo | 0 test/{run-dfinity => run-stub}/type-lub.mo | 0 test/{run-dfinity => run}/chatpp.mo | 3 + test/{run-dfinity => run}/counter-class.mo | 3 + test/{run-dfinity => run}/ok/chatpp.run-ir.ok | 0 .../{run-dfinity => run}/ok/chatpp.run-low.ok | 0 test/{run-dfinity => run}/ok/chatpp.run.ok | 0 146 files changed, 541 insertions(+), 638 deletions(-) delete mode 100644 test/run-dfinity/closure-params.mo delete mode 100644 test/run-dfinity/nary-async.mo delete mode 100644 test/run-dfinity/ok/GIT-843.dvm.ok delete mode 100644 test/run-dfinity/ok/GIT-843.run-ir.ok delete mode 100644 test/run-dfinity/ok/GIT-843.run-low.ok delete mode 100644 test/run-dfinity/ok/GIT-843.run.ok delete mode 100644 test/run-dfinity/ok/async-free-var.dvm.ok delete mode 100644 test/run-dfinity/ok/async-loop-while.dvm.ok delete mode 100644 test/run-dfinity/ok/async-loop.dvm.ok delete mode 100644 test/run-dfinity/ok/async-new-obj.dvm.ok delete mode 100644 test/run-dfinity/ok/async-obj-mut.dvm.ok delete mode 100644 test/run-dfinity/ok/async-while.dvm.ok delete mode 100644 test/run-dfinity/ok/await.dvm.ok delete mode 100644 test/run-dfinity/ok/block.dvm.ok delete mode 100644 test/run-dfinity/ok/chatpp.dvm.ok delete mode 100644 test/run-dfinity/ok/closure-params.dvm.ok delete mode 100644 test/run-dfinity/ok/counter-class.comp.ok delete mode 100644 test/run-dfinity/ok/counter-class.dvm.ok delete mode 100644 test/run-dfinity/ok/counter.dvm.ok delete mode 100644 test/run-dfinity/ok/counter.run-ir.ok delete mode 100644 test/run-dfinity/ok/counter.run-low.ok delete mode 100644 test/run-dfinity/ok/counter.run.ok delete mode 100644 test/run-dfinity/ok/for-await.dvm.ok delete mode 100644 test/run-dfinity/ok/hello-world-await.dvm.ok delete mode 100644 test/run-dfinity/ok/hello-world-await.run-ir.ok delete mode 100644 test/run-dfinity/ok/hello-world-await.run-low.ok delete mode 100644 test/run-dfinity/ok/hello-world-await.run.ok delete mode 100644 test/run-dfinity/ok/indirect-counter.dvm.ok delete mode 100644 test/run-dfinity/ok/indirect-counter.run-ir.ok delete mode 100644 test/run-dfinity/ok/indirect-counter.run-low.ok delete mode 100644 test/run-dfinity/ok/indirect-counter.run.ok delete mode 100644 test/run-dfinity/ok/interleave.dvm.ok delete mode 100644 test/run-dfinity/ok/local-throw.dvm.ok delete mode 100644 test/run-dfinity/ok/nary-async.dvm.ok delete mode 100644 test/run-dfinity/ok/overflow.dvm.ok delete mode 100644 test/run-dfinity/ok/query.dvm.ok delete mode 100644 test/run-dfinity/ok/query.run-ir.ok delete mode 100644 test/run-dfinity/ok/query.run-low.ok delete mode 100644 test/run-dfinity/ok/query.run.ok delete mode 100644 test/run-dfinity/ok/reference-params.dvm.ok delete mode 100644 test/run-dfinity/ok/simple-throw.dvm.ok delete mode 100644 test/run-dfinity/query.mo delete mode 100644 test/run-dfinity/reference-params.mo rename test/{run-dfinity => run-stub}/AST-66.mo (100%) rename test/{run-dfinity => run-stub}/async-any.mo (100%) rename test/{run-dfinity => run-stub}/async-free-var.mo (100%) rename test/{run-dfinity => run-stub}/async-loop-while.mo (100%) rename test/{run-dfinity => run-stub}/async-loop.mo (100%) rename test/{run-dfinity => run-stub}/async-new-obj.mo (100%) rename test/{run-dfinity => run-stub}/async-obj-mut.mo (100%) rename test/{run-dfinity => run-stub}/async-while.mo (100%) rename test/{run-dfinity => run-stub}/await.mo (100%) rename test/{run-dfinity => run-stub}/block.mo (100%) create mode 100644 test/run-stub/closure-params.mo rename test/{run-dfinity => run-stub}/flatten-awaitables.mo (100%) rename test/{run-dfinity => run-stub}/for-await.mo (100%) rename test/{run-dfinity => run-stub}/interleave.mo (100%) rename test/{run-dfinity => run-stub}/local-throw.mo (95%) create mode 100644 test/run-stub/nary-async.mo create mode 100644 test/run-stub/ok/AST-66.ic-stub-run.ok create mode 100644 test/run-stub/ok/async-any.ic-stub-run.ok create mode 100644 test/run-stub/ok/async-free-var.ic-stub-run.ok rename test/{run-dfinity => run-stub}/ok/async-free-var.run-ir.ok (100%) rename test/{run-dfinity => run-stub}/ok/async-free-var.run-low.ok (100%) rename test/{run-dfinity => run-stub}/ok/async-free-var.run.ok (100%) create mode 100644 test/run-stub/ok/async-loop-while.ic-stub-run.ok rename test/{run-dfinity => run-stub}/ok/async-loop-while.run-ir.ok (100%) rename test/{run-dfinity => run-stub}/ok/async-loop-while.run-low.ok (100%) rename test/{run-dfinity => run-stub}/ok/async-loop-while.run.ok (100%) create mode 100644 test/run-stub/ok/async-loop.ic-stub-run.ok rename test/{run-dfinity => run-stub}/ok/async-loop.run-ir.ok (100%) rename test/{run-dfinity => run-stub}/ok/async-loop.run-low.ok (100%) rename test/{run-dfinity => run-stub}/ok/async-loop.run.ok (100%) create mode 100644 test/run-stub/ok/async-new-obj.ic-stub-run.ok rename test/{run-dfinity => run-stub}/ok/async-new-obj.run-ir.ok (100%) rename test/{run-dfinity => run-stub}/ok/async-new-obj.run-low.ok (100%) rename test/{run-dfinity => run-stub}/ok/async-new-obj.run.ok (100%) create mode 100644 test/run-stub/ok/async-obj-mut.ic-stub-run.ok rename test/{run-dfinity => run-stub}/ok/async-obj-mut.run-ir.ok (100%) rename test/{run-dfinity => run-stub}/ok/async-obj-mut.run-low.ok (100%) rename test/{run-dfinity => run-stub}/ok/async-obj-mut.run.ok (100%) create mode 100644 test/run-stub/ok/async-while.ic-stub-run.ok rename test/{run-dfinity => run-stub}/ok/async-while.run-ir.ok (100%) rename test/{run-dfinity => run-stub}/ok/async-while.run-low.ok (100%) rename test/{run-dfinity => run-stub}/ok/async-while.run.ok (100%) create mode 100644 test/run-stub/ok/await.ic-stub-run.ok rename test/{run-dfinity => run-stub}/ok/await.run-ir.ok (100%) rename test/{run-dfinity => run-stub}/ok/await.run-low.ok (100%) rename test/{run-dfinity => run-stub}/ok/await.run.ok (100%) create mode 100644 test/run-stub/ok/block.ic-stub-run.ok rename test/{run-dfinity => run-stub}/ok/block.run-ir.ok (100%) rename test/{run-dfinity => run-stub}/ok/block.run-low.ok (100%) rename test/{run-dfinity => run-stub}/ok/block.run.ok (100%) create mode 100644 test/run-stub/ok/closure-params.ic-stub-run.ok rename test/{run-dfinity => run-stub}/ok/closure-params.run-ir.ok (100%) rename test/{run-dfinity => run-stub}/ok/closure-params.run-low.ok (100%) rename test/{run-dfinity => run-stub}/ok/closure-params.run.ok (100%) rename test/{run-dfinity/ok/flatten-awaitables.dvm.ok => run-stub/ok/flatten-awaitables.ic-stub-run.ok} (54%) rename test/{run-dfinity => run-stub}/ok/flatten-awaitables.run-ir.ok (100%) rename test/{run-dfinity => run-stub}/ok/flatten-awaitables.run-low.ok (100%) rename test/{run-dfinity => run-stub}/ok/flatten-awaitables.run.ok (100%) rename test/{run-dfinity => run-stub}/ok/flatten-awaitables.tc.ok (100%) create mode 100644 test/run-stub/ok/for-await.ic-stub-run.ok rename test/{run-dfinity => run-stub}/ok/for-await.run-ir.ok (100%) rename test/{run-dfinity => run-stub}/ok/for-await.run-low.ok (100%) rename test/{run-dfinity => run-stub}/ok/for-await.run.ok (100%) create mode 100644 test/run-stub/ok/interleave.ic-stub-run.ok rename test/{run-dfinity => run-stub}/ok/interleave.run-ir.ok (100%) rename test/{run-dfinity => run-stub}/ok/interleave.run-low.ok (100%) rename test/{run-dfinity => run-stub}/ok/interleave.run.ok (100%) create mode 100644 test/run-stub/ok/local-throw.ic-stub-run.ok rename test/{run-dfinity => run-stub}/ok/local-throw.run-ir.ok (100%) rename test/{run-dfinity => run-stub}/ok/local-throw.run-low.ok (100%) rename test/{run-dfinity => run-stub}/ok/local-throw.run.ok (100%) create mode 100644 test/run-stub/ok/nary-async.ic-stub-run.ok rename test/{run-dfinity => run-stub}/ok/nary-async.run-ir.ok (82%) rename test/{run-dfinity => run-stub}/ok/nary-async.run-low.ok (82%) rename test/{run-dfinity => run-stub}/ok/nary-async.run.ok (82%) create mode 100644 test/run-stub/ok/overflow.ic-stub-run.ok rename test/{run-dfinity => run-stub}/ok/overflow.run-ir.ok (100%) rename test/{run-dfinity => run-stub}/ok/overflow.run-low.ok (100%) rename test/{run-dfinity => run-stub}/ok/overflow.run.ok (100%) create mode 100644 test/run-stub/ok/query2.ic-stub-run.ok create mode 100644 test/run-stub/ok/query2.run-ir.ok create mode 100644 test/run-stub/ok/query2.run-low.ok create mode 100644 test/run-stub/ok/query2.run.ok create mode 100644 test/run-stub/ok/reference-params.ic-stub-run.ok rename test/{run-dfinity => run-stub}/ok/reference-params.run-ir.ok (100%) rename test/{run-dfinity => run-stub}/ok/reference-params.run-low.ok (100%) rename test/{run-dfinity => run-stub}/ok/reference-params.run.ok (100%) create mode 100644 test/run-stub/ok/simple-throw.ic-stub-run.ok rename test/{run-dfinity => run-stub}/ok/simple-throw.run-ir.ok (100%) rename test/{run-dfinity => run-stub}/ok/simple-throw.run-low.ok (100%) rename test/{run-dfinity => run-stub}/ok/simple-throw.run.ok (100%) create mode 100644 test/run-stub/ok/type-lub.ic-stub-run.ok rename test/{run-dfinity => run-stub}/overflow.mo (100%) create mode 100644 test/run-stub/query2.mo create mode 100644 test/run-stub/reference-params.mo rename test/{run-dfinity => run-stub}/simple-throw.mo (100%) rename test/{run-dfinity => run-stub}/type-lub.mo (100%) rename test/{run-dfinity => run}/chatpp.mo (96%) rename test/{run-dfinity => run}/counter-class.mo (80%) rename test/{run-dfinity => run}/ok/chatpp.run-ir.ok (100%) rename test/{run-dfinity => run}/ok/chatpp.run-low.ok (100%) rename test/{run-dfinity => run}/ok/chatpp.run.ok (100%) diff --git a/test/repl/type-lub-repl.sh b/test/repl/type-lub-repl.sh index 7d672c90b91..5e4327876b0 100755 --- a/test/repl/type-lub-repl.sh +++ b/test/repl/type-lub-repl.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # Tests that correct lub types are inferred when values appear in arrays -${MOC:-$(dirname "$BASH_SOURCE")/../../src/moc} -i -ancient-system-api ../run-dfinity/type-lub.mo <<__END__ +${MOC:-$(dirname "$BASH_SOURCE")/../../src/moc} -i -ancient-system-api ../run-stub/type-lub.mo <<__END__ opts; nulls; incompatible_objs; diff --git a/test/run-dfinity/closure-params.mo b/test/run-dfinity/closure-params.mo deleted file mode 100644 index 984b5b7c452..00000000000 --- a/test/run-dfinity/closure-params.mo +++ /dev/null @@ -1,21 +0,0 @@ -let a = actor { - var c = 0; - public func incn(n : Nat) : () { - c += n; - debugPrintNat(c); - }; - public func readCounter(f : shared Nat -> ()) : () { - f(c); - }; -}; - -a.incn(1); -a.readCounter(shared func (n : Nat) = { debugPrintNat n }); -a.incn(2); -a.readCounter(shared func (n : Nat) = { debugPrintNat n }); -a.incn(3); -a.readCounter(shared func (n : Nat) = { debugPrintNat n }); -a.incn(4); -a.readCounter(shared func (n : Nat) = { debugPrintNat n }); -a.incn(5); -a.readCounter(shared func (n : Nat) = { debugPrintNat n }); diff --git a/test/run-dfinity/nary-async.mo b/test/run-dfinity/nary-async.mo deleted file mode 100644 index 7ad1a042c03..00000000000 --- a/test/run-dfinity/nary-async.mo +++ /dev/null @@ -1,147 +0,0 @@ -/* test n-ary async/await */ - -/* n-ary args */ -{ -let t = "0_0"; -shared func f0_0() : async () {}; -let _ : async () = async { - await f0_0(); - debugPrint t; -}; -}; - -{ -let t = "1_0"; -shared func f1_0(x:Int) : async () { - assert(x == 1); -}; -let _ : async () = async { - await f1_0(1); - debugPrint t; -}; -}; - -{ -let t = "2_0"; -shared func f2_0(x:Int,y:Bool) : async () { - assert(x==1); - assert(y==true); -}; -let _ : async () = async { - await f2_0(1,true); - debugPrint t; -}; -}; - -{ -let t = "3_0"; -shared func f3_0(x:Int,y:Bool,z:Text) : async () { - assert(x == 1); - assert(y == true); - assert(z == "a"); -}; -let _ : async () = async { - await f3_0(1,true,"a"); - debugPrint t; -}; -}; - -/* n-ary returns */ - -{ -let t = "0_0"; -shared func f0_0() : async () {}; -let _ : async () = async { - await f0_0(); - debugPrint t; -}; -}; - -{ -let t = "0_1"; -shared func f0_1() : async Int { - 1; -}; - -let _ : async Int = async { - let x = await f0_1(); - assert(x == 1); - debugPrint t; - x; -}; -}; - -{ -let t = "0_2"; -shared func f0_2() : async (Int,Bool) { - (1,true); -}; -let _ : async (Int,Bool) = async { - let (x,y) = await f0_2(); - assert(x==1); - assert(y==true); - debugPrint t; - (x,y); -}; -}; - - -{ -let t = "0_3!!"; -shared func f0_3() : async (Int,Bool,Text) { - (1,true,"a"); -}; -let _ : async (Int,Bool,Text) = async { - let (x,y,z) = await f0_3(); - assert(x==1); - assert(y==true); - assert(z=="a"); - debugPrint t; - (x,y,z); -}; -}; - - - -/* special case: unary tuples */ -/* -{ -let t = "(1)-(1)"; -shared func fu_u(a:Int,) : async (Int,) { - return (2*a,); -}; - -let _ : async (Int,) = async { - let (x,) = await fu_u(1); - assert(x==2); - debugPrint t; - return (x,); -}; -}; -*/ - - -/* Disabled: No generic messages are supported -func Generic(t:Text, x:T,eq:(T,T)->Bool) { - -shared func fu_u(x:T) : async T { - return x; -}; - -let _ : async T = async { - let y = await fu_u(x); - assert(eq(x,y)); - debugPrint t; - return y; -}; -}; - - -Generic("", 1, func eq(i:Int,j:Int) : Bool = i == j); - -Generic<()>("<()>", (), func eq(i:(),j:()) : Bool = true); - -Generic<(Int,Bool)>("<(Int,Bool)>", (1,true), - func eq((i,b):(Int,Bool), - (j,c):(Int,Bool)) : Bool = i == j and b == c); -*/ diff --git a/test/run-dfinity/ok/GIT-843.dvm.ok b/test/run-dfinity/ok/GIT-843.dvm.ok deleted file mode 100644 index 9766475a418..00000000000 --- a/test/run-dfinity/ok/GIT-843.dvm.ok +++ /dev/null @@ -1 +0,0 @@ -ok diff --git a/test/run-dfinity/ok/GIT-843.run-ir.ok b/test/run-dfinity/ok/GIT-843.run-ir.ok deleted file mode 100644 index 9766475a418..00000000000 --- a/test/run-dfinity/ok/GIT-843.run-ir.ok +++ /dev/null @@ -1 +0,0 @@ -ok diff --git a/test/run-dfinity/ok/GIT-843.run-low.ok b/test/run-dfinity/ok/GIT-843.run-low.ok deleted file mode 100644 index 9766475a418..00000000000 --- a/test/run-dfinity/ok/GIT-843.run-low.ok +++ /dev/null @@ -1 +0,0 @@ -ok diff --git a/test/run-dfinity/ok/GIT-843.run.ok b/test/run-dfinity/ok/GIT-843.run.ok deleted file mode 100644 index 9766475a418..00000000000 --- a/test/run-dfinity/ok/GIT-843.run.ok +++ /dev/null @@ -1 +0,0 @@ -ok diff --git a/test/run-dfinity/ok/async-free-var.dvm.ok b/test/run-dfinity/ok/async-free-var.dvm.ok deleted file mode 100644 index 3bf15dcf814..00000000000 --- a/test/run-dfinity/ok/async-free-var.dvm.ok +++ /dev/null @@ -1,7 +0,0 @@ -A -A -C -Now in async -C -B -B diff --git a/test/run-dfinity/ok/async-loop-while.dvm.ok b/test/run-dfinity/ok/async-loop-while.dvm.ok deleted file mode 100644 index 4e57a41a93e..00000000000 --- a/test/run-dfinity/ok/async-loop-while.dvm.ok +++ /dev/null @@ -1,12 +0,0 @@ -0 -1 -2 -0 -1 -2 -0 -1 -2 -0 -1 -2 diff --git a/test/run-dfinity/ok/async-loop.dvm.ok b/test/run-dfinity/ok/async-loop.dvm.ok deleted file mode 100644 index 4e57a41a93e..00000000000 --- a/test/run-dfinity/ok/async-loop.dvm.ok +++ /dev/null @@ -1,12 +0,0 @@ -0 -1 -2 -0 -1 -2 -0 -1 -2 -0 -1 -2 diff --git a/test/run-dfinity/ok/async-new-obj.dvm.ok b/test/run-dfinity/ok/async-new-obj.dvm.ok deleted file mode 100644 index 9dfdfbb5120..00000000000 --- a/test/run-dfinity/ok/async-new-obj.dvm.ok +++ /dev/null @@ -1,5 +0,0 @@ -aaab -babb -cacb -dadb -eaeb diff --git a/test/run-dfinity/ok/async-obj-mut.dvm.ok b/test/run-dfinity/ok/async-obj-mut.dvm.ok deleted file mode 100644 index a346eeafc00..00000000000 --- a/test/run-dfinity/ok/async-obj-mut.dvm.ok +++ /dev/null @@ -1,8 +0,0 @@ -1 -2 -3 -done creating - -3 -4 -5 diff --git a/test/run-dfinity/ok/async-while.dvm.ok b/test/run-dfinity/ok/async-while.dvm.ok deleted file mode 100644 index 4e57a41a93e..00000000000 --- a/test/run-dfinity/ok/async-while.dvm.ok +++ /dev/null @@ -1,12 +0,0 @@ -0 -1 -2 -0 -1 -2 -0 -1 -2 -0 -1 -2 diff --git a/test/run-dfinity/ok/await.dvm.ok b/test/run-dfinity/ok/await.dvm.ok deleted file mode 100644 index 2075f5ae300..00000000000 --- a/test/run-dfinity/ok/await.dvm.ok +++ /dev/null @@ -1,27 +0,0 @@ -a -b -c -d -e -g -holy -cnt: 0 i: 0 -cnt: 1 i: 1 -cnt: 2 i: 2 -cnt: 3 i: 3 -cnt: 4 i: 4 -e-while -cnt: 5 i: 5 -cnt: 6 i: 6 -cnt: 7 i: 7 -e-exit -g-label -. -cnt: 8 i: 10 -. -cnt: 9 i: 11 -. -cnt: 10 i: 12 -g-exit -a -b diff --git a/test/run-dfinity/ok/block.dvm.ok b/test/run-dfinity/ok/block.dvm.ok deleted file mode 100644 index 4a400a89e81..00000000000 --- a/test/run-dfinity/ok/block.dvm.ok +++ /dev/null @@ -1,10 +0,0 @@ -a1 -b1 -a2 -b2 -a3 -b3 -1 -3 -5 -6 diff --git a/test/run-dfinity/ok/chatpp.dvm.ok b/test/run-dfinity/ok/chatpp.dvm.ok deleted file mode 100644 index 1384c6db136..00000000000 --- a/test/run-dfinity/ok/chatpp.dvm.ok +++ /dev/null @@ -1,6 +0,0 @@ -unsubscribe -0 -unsubscribe -+1 -unsubscribe -+2 diff --git a/test/run-dfinity/ok/closure-params.dvm.ok b/test/run-dfinity/ok/closure-params.dvm.ok deleted file mode 100644 index 17b4c77d5c9..00000000000 --- a/test/run-dfinity/ok/closure-params.dvm.ok +++ /dev/null @@ -1,10 +0,0 @@ -1 -1 -3 -3 -6 -6 -10 -10 -15 -15 diff --git a/test/run-dfinity/ok/counter-class.comp.ok b/test/run-dfinity/ok/counter-class.comp.ok deleted file mode 100644 index f59ec22908c..00000000000 --- a/test/run-dfinity/ok/counter-class.comp.ok +++ /dev/null @@ -1,60 +0,0 @@ -non-closed actor: (ActorE - anon-object-1.30 - (VarD j (VarE i)) - (LetD - (VarP dec) - (FuncE - dec - Shared - Returns - () - (BlockE - (LetD WildP (CallE (VarE showCounter) (VarE j))) - (AssignE - (VarE j) - (PrimE (BinPrim Int SubOp) (VarE j) (LitE (IntLit 1))) - ) - ) - ) - ) - (LetD - (VarP read) - (FuncE - read - Shared - Replies - Int - (CallE - (FuncE - $lambda - Local - Returns - (params $k/0 $r/0) - () - (CallE (VarE $k/0) (VarE j)) - ) - (TupE - (FuncE - $lambda - Local - Returns - (params $v/0) - () - (PrimE (ICReplyPrim Int) (VarE $v/0)) - ) - (FuncE - $lambda - Local - Returns - (params $e/0) - () - (PrimE ICRejectPrim (PrimE errorMessage (VarE $e/0))) - ) - ) - ) - ) - ) - (read read) - (dec dec) - actor {dec : shared () -> (); read : shared () -> replies Int} -) diff --git a/test/run-dfinity/ok/counter-class.dvm.ok b/test/run-dfinity/ok/counter-class.dvm.ok deleted file mode 100644 index 3f704155b23..00000000000 --- a/test/run-dfinity/ok/counter-class.dvm.ok +++ /dev/null @@ -1,3 +0,0 @@ -hypervisor: calling start failed with trap message: Uncaught RuntimeError: unreachable -TODO: non-closed actor - diff --git a/test/run-dfinity/ok/counter.dvm.ok b/test/run-dfinity/ok/counter.dvm.ok deleted file mode 100644 index e9717fd149f..00000000000 --- a/test/run-dfinity/ok/counter.dvm.ok +++ /dev/null @@ -1,14 +0,0 @@ -2 -3 -4 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 diff --git a/test/run-dfinity/ok/counter.run-ir.ok b/test/run-dfinity/ok/counter.run-ir.ok deleted file mode 100644 index e9717fd149f..00000000000 --- a/test/run-dfinity/ok/counter.run-ir.ok +++ /dev/null @@ -1,14 +0,0 @@ -2 -3 -4 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 diff --git a/test/run-dfinity/ok/counter.run-low.ok b/test/run-dfinity/ok/counter.run-low.ok deleted file mode 100644 index e9717fd149f..00000000000 --- a/test/run-dfinity/ok/counter.run-low.ok +++ /dev/null @@ -1,14 +0,0 @@ -2 -3 -4 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 diff --git a/test/run-dfinity/ok/counter.run.ok b/test/run-dfinity/ok/counter.run.ok deleted file mode 100644 index e9717fd149f..00000000000 --- a/test/run-dfinity/ok/counter.run.ok +++ /dev/null @@ -1,14 +0,0 @@ -2 -3 -4 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 diff --git a/test/run-dfinity/ok/for-await.dvm.ok b/test/run-dfinity/ok/for-await.dvm.ok deleted file mode 100644 index b033488efab..00000000000 --- a/test/run-dfinity/ok/for-await.dvm.ok +++ /dev/null @@ -1,11 +0,0 @@ -0 -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 diff --git a/test/run-dfinity/ok/hello-world-await.dvm.ok b/test/run-dfinity/ok/hello-world-await.dvm.ok deleted file mode 100644 index 980a0d5f19a..00000000000 --- a/test/run-dfinity/ok/hello-world-await.dvm.ok +++ /dev/null @@ -1 +0,0 @@ -Hello World! diff --git a/test/run-dfinity/ok/hello-world-await.run-ir.ok b/test/run-dfinity/ok/hello-world-await.run-ir.ok deleted file mode 100644 index 980a0d5f19a..00000000000 --- a/test/run-dfinity/ok/hello-world-await.run-ir.ok +++ /dev/null @@ -1 +0,0 @@ -Hello World! diff --git a/test/run-dfinity/ok/hello-world-await.run-low.ok b/test/run-dfinity/ok/hello-world-await.run-low.ok deleted file mode 100644 index 980a0d5f19a..00000000000 --- a/test/run-dfinity/ok/hello-world-await.run-low.ok +++ /dev/null @@ -1 +0,0 @@ -Hello World! diff --git a/test/run-dfinity/ok/hello-world-await.run.ok b/test/run-dfinity/ok/hello-world-await.run.ok deleted file mode 100644 index 980a0d5f19a..00000000000 --- a/test/run-dfinity/ok/hello-world-await.run.ok +++ /dev/null @@ -1 +0,0 @@ -Hello World! diff --git a/test/run-dfinity/ok/indirect-counter.dvm.ok b/test/run-dfinity/ok/indirect-counter.dvm.ok deleted file mode 100644 index 95c45d6da51..00000000000 --- a/test/run-dfinity/ok/indirect-counter.dvm.ok +++ /dev/null @@ -1,4 +0,0 @@ -2 -3 -4 -4 diff --git a/test/run-dfinity/ok/indirect-counter.run-ir.ok b/test/run-dfinity/ok/indirect-counter.run-ir.ok deleted file mode 100644 index 95c45d6da51..00000000000 --- a/test/run-dfinity/ok/indirect-counter.run-ir.ok +++ /dev/null @@ -1,4 +0,0 @@ -2 -3 -4 -4 diff --git a/test/run-dfinity/ok/indirect-counter.run-low.ok b/test/run-dfinity/ok/indirect-counter.run-low.ok deleted file mode 100644 index 95c45d6da51..00000000000 --- a/test/run-dfinity/ok/indirect-counter.run-low.ok +++ /dev/null @@ -1,4 +0,0 @@ -2 -3 -4 -4 diff --git a/test/run-dfinity/ok/indirect-counter.run.ok b/test/run-dfinity/ok/indirect-counter.run.ok deleted file mode 100644 index 95c45d6da51..00000000000 --- a/test/run-dfinity/ok/indirect-counter.run.ok +++ /dev/null @@ -1,4 +0,0 @@ -2 -3 -4 -4 diff --git a/test/run-dfinity/ok/interleave.dvm.ok b/test/run-dfinity/ok/interleave.dvm.ok deleted file mode 100644 index 9e55fa80c2d..00000000000 --- a/test/run-dfinity/ok/interleave.dvm.ok +++ /dev/null @@ -1,19 +0,0 @@ -g - e-while - - e cnt: 0 i: 5 - e cnt: 1 i: 6 - e cnt: 2 i: 7 - e cnt: 3 i: 8 - e cnt: 4 i: 9 - e-exit - -g-label - -g cnt: 5 i: 10 -g cnt: 6 i: 11 -g cnt: 7 i: 12 -g cnt: 8 i: 13 -g cnt: 9 i: 14 -g-exit - diff --git a/test/run-dfinity/ok/local-throw.dvm.ok b/test/run-dfinity/ok/local-throw.dvm.ok deleted file mode 100644 index 33bffc9666e..00000000000 --- a/test/run-dfinity/ok/local-throw.dvm.ok +++ /dev/null @@ -1,2 +0,0 @@ -t2 ok -t3 ok diff --git a/test/run-dfinity/ok/nary-async.dvm.ok b/test/run-dfinity/ok/nary-async.dvm.ok deleted file mode 100644 index c49facc630f..00000000000 --- a/test/run-dfinity/ok/nary-async.dvm.ok +++ /dev/null @@ -1,8 +0,0 @@ -0_0 -1_0 -2_0 -3_0 -0_0 -0_1 -0_2 -0_3!! diff --git a/test/run-dfinity/ok/overflow.dvm.ok b/test/run-dfinity/ok/overflow.dvm.ok deleted file mode 100644 index 86d13f58ad8..00000000000 --- a/test/run-dfinity/ok/overflow.dvm.ok +++ /dev/null @@ -1,10 +0,0 @@ -hypervisor: calling __motoko_async_helper failed with trap message: Uncaught RuntimeError: unreachable -hypervisor: calling __motoko_async_helper failed with trap message: Uncaught RuntimeError: unreachable -This is reachable. -This is reachable. -Natural subtraction underflow - -Natural subtraction underflow - -This is reachable. -This is reachable. diff --git a/test/run-dfinity/ok/query.dvm.ok b/test/run-dfinity/ok/query.dvm.ok deleted file mode 100644 index 66717210b53..00000000000 --- a/test/run-dfinity/ok/query.dvm.ok +++ /dev/null @@ -1,10 +0,0 @@ -2 -3 -4 -4 -5 -(read) -4 -5 -(read) -4 diff --git a/test/run-dfinity/ok/query.run-ir.ok b/test/run-dfinity/ok/query.run-ir.ok deleted file mode 100644 index 17740cbca04..00000000000 --- a/test/run-dfinity/ok/query.run-ir.ok +++ /dev/null @@ -1,11 +0,0 @@ -2 -3 -4 -4 -5 -(read) -5 -6 -(read) -query.mo:61.2-61.16: execution error, assertion failure -6 diff --git a/test/run-dfinity/ok/query.run-low.ok b/test/run-dfinity/ok/query.run-low.ok deleted file mode 100644 index 17740cbca04..00000000000 --- a/test/run-dfinity/ok/query.run-low.ok +++ /dev/null @@ -1,11 +0,0 @@ -2 -3 -4 -4 -5 -(read) -5 -6 -(read) -query.mo:61.2-61.16: execution error, assertion failure -6 diff --git a/test/run-dfinity/ok/query.run.ok b/test/run-dfinity/ok/query.run.ok deleted file mode 100644 index 17740cbca04..00000000000 --- a/test/run-dfinity/ok/query.run.ok +++ /dev/null @@ -1,11 +0,0 @@ -2 -3 -4 -4 -5 -(read) -5 -6 -(read) -query.mo:61.2-61.16: execution error, assertion failure -6 diff --git a/test/run-dfinity/ok/reference-params.dvm.ok b/test/run-dfinity/ok/reference-params.dvm.ok deleted file mode 100644 index 8650e0ef3bf..00000000000 --- a/test/run-dfinity/ok/reference-params.dvm.ok +++ /dev/null @@ -1,5 +0,0 @@ -Hello World! -Hello World! -Hello World! -Hello Universe! -Hello Galaxy! diff --git a/test/run-dfinity/ok/simple-throw.dvm.ok b/test/run-dfinity/ok/simple-throw.dvm.ok deleted file mode 100644 index f3e51c00a71..00000000000 --- a/test/run-dfinity/ok/simple-throw.dvm.ok +++ /dev/null @@ -1,5 +0,0 @@ -1 -2 -3 -4 -done diff --git a/test/run-dfinity/query.mo b/test/run-dfinity/query.mo deleted file mode 100644 index 271830eb031..00000000000 --- a/test/run-dfinity/query.mo +++ /dev/null @@ -1,62 +0,0 @@ -actor counter = { - var c = 1; - public func inc() { - c += 1; - debugPrintNat c; - }; - public func printCounter () { - debugPrintNat c; - }; - public func get() : async Nat { - return c - }; - public query func read() : async Nat { - let tmp = c; - c += 1; - debugPrintNat c; debugPrint "(read)"; - return tmp; - }; - -}; - - -{ // fully explicit syntax - -let _ : actor { read : shared query () -> async Nat } = counter; - -shared query func f () : async Nat { 666; }; - -type Query = shared query () -> async Nat; - -let _ : Query = counter.read; - -}; - -{ - -// sugar, surpressing shared - -let _ : actor { read: query () -> async Nat } = counter; - -query func f () : async Nat { 666; }; - -type Query = query () -> async Nat; - -let _ : Query = counter.read; - -}; - -async { - counter.inc(); - counter.inc(); - counter.inc(); - counter.printCounter(); - let c1 = await counter.get(); - assert c1 == 4; - let c2 = await counter.read(); - counter.printCounter(); - assert c2 == 4; - let c3 = await counter.read(); - counter.printCounter(); - assert c3 == 4; -}; diff --git a/test/run-dfinity/reference-params.mo b/test/run-dfinity/reference-params.mo deleted file mode 100644 index cc575f9f954..00000000000 --- a/test/run-dfinity/reference-params.mo +++ /dev/null @@ -1,47 +0,0 @@ -let a = actor { - public func hello() { - debugPrint("Hello World!"); - }; -}; -a.hello(); - -// test passing an actor to an actor -let b = actor this { - public func say_hi(a : actor { hello : () -> () } ) { - a.hello(); - }; -}; -b.say_hi(a); - -// test passing a funcref to an actor -let c = actor { - public func say_hi(f : shared () -> ()) { - f(); - }; -}; -c.say_hi(a.hello); - -// test passing a own funcref to an actor -let d = actor { - public func say_hi(f : shared () -> ()) { - f(); - }; - public func hello() { - debugPrint("Hello Universe!"); - }; - public func go() { - say_hi(hello); - } -}; -d.go(); - -// test passing a self to an actor -let e = actor this { - public func hello() { - debugPrint("Hello Galaxy!"); - }; - public func send_to(f : shared (actor { hello : () -> () }) -> ()) { - f(this); - } -}; -e.send_to(b.say_hi); diff --git a/test/run-dfinity/AST-66.mo b/test/run-stub/AST-66.mo similarity index 100% rename from test/run-dfinity/AST-66.mo rename to test/run-stub/AST-66.mo diff --git a/test/run-dfinity/async-any.mo b/test/run-stub/async-any.mo similarity index 100% rename from test/run-dfinity/async-any.mo rename to test/run-stub/async-any.mo diff --git a/test/run-dfinity/async-free-var.mo b/test/run-stub/async-free-var.mo similarity index 100% rename from test/run-dfinity/async-free-var.mo rename to test/run-stub/async-free-var.mo diff --git a/test/run-dfinity/async-loop-while.mo b/test/run-stub/async-loop-while.mo similarity index 100% rename from test/run-dfinity/async-loop-while.mo rename to test/run-stub/async-loop-while.mo diff --git a/test/run-dfinity/async-loop.mo b/test/run-stub/async-loop.mo similarity index 100% rename from test/run-dfinity/async-loop.mo rename to test/run-stub/async-loop.mo diff --git a/test/run-dfinity/async-new-obj.mo b/test/run-stub/async-new-obj.mo similarity index 100% rename from test/run-dfinity/async-new-obj.mo rename to test/run-stub/async-new-obj.mo diff --git a/test/run-dfinity/async-obj-mut.mo b/test/run-stub/async-obj-mut.mo similarity index 100% rename from test/run-dfinity/async-obj-mut.mo rename to test/run-stub/async-obj-mut.mo diff --git a/test/run-dfinity/async-while.mo b/test/run-stub/async-while.mo similarity index 100% rename from test/run-dfinity/async-while.mo rename to test/run-stub/async-while.mo diff --git a/test/run-dfinity/await.mo b/test/run-stub/await.mo similarity index 100% rename from test/run-dfinity/await.mo rename to test/run-stub/await.mo diff --git a/test/run-dfinity/block.mo b/test/run-stub/block.mo similarity index 100% rename from test/run-dfinity/block.mo rename to test/run-stub/block.mo diff --git a/test/run-stub/closure-params.mo b/test/run-stub/closure-params.mo new file mode 100644 index 00000000000..1048ea22ed5 --- /dev/null +++ b/test/run-stub/closure-params.mo @@ -0,0 +1,24 @@ +let a = actor { + var c = 0; + public func incn(n : Nat) : () { + c += n; + debugPrintNat(c); + }; + public func readCounter(f : shared Nat -> ()) : () { + f(c); + }; + + public func printNat(n: Nat) { debugPrintNat n }; + + incn(1); + readCounter(printNat); + incn(2); + readCounter(printNat); + incn(3); + readCounter(printNat); + incn(4); + readCounter(printNat); + incn(5); + readCounter(printNat); +}; + diff --git a/test/run-dfinity/flatten-awaitables.mo b/test/run-stub/flatten-awaitables.mo similarity index 100% rename from test/run-dfinity/flatten-awaitables.mo rename to test/run-stub/flatten-awaitables.mo diff --git a/test/run-dfinity/for-await.mo b/test/run-stub/for-await.mo similarity index 100% rename from test/run-dfinity/for-await.mo rename to test/run-stub/for-await.mo diff --git a/test/run-dfinity/interleave.mo b/test/run-stub/interleave.mo similarity index 100% rename from test/run-dfinity/interleave.mo rename to test/run-stub/interleave.mo diff --git a/test/run-dfinity/local-throw.mo b/test/run-stub/local-throw.mo similarity index 95% rename from test/run-dfinity/local-throw.mo rename to test/run-stub/local-throw.mo index 5f6b75566f9..9a1e8ce2cf1 100644 --- a/test/run-dfinity/local-throw.mo +++ b/test/run-stub/local-throw.mo @@ -2,7 +2,7 @@ // In principle, it should run on all targets. actor a { - shared func t2() : async () { + public func t2() : async () { try { throw error("t2"); assert(false); @@ -15,7 +15,7 @@ actor a { } }; - shared func t3() : async () { + public func t3() : async () { try { try { throw error("t3"); diff --git a/test/run-stub/nary-async.mo b/test/run-stub/nary-async.mo new file mode 100644 index 00000000000..649f7f8732d --- /dev/null +++ b/test/run-stub/nary-async.mo @@ -0,0 +1,103 @@ +/* test n-ary async/await */ + +/* n-ary args */ +actor { + public func f0_0() : async () {}; + { + let t = "0_0"; + ignore async { + await f0_0(); + debugPrint t; + }; + }; + + public func f1_0(x:Int) : async () { + assert(x == 1); + }; + { + let t = "1_0"; + ignore async { + await f1_0(1); + debugPrint t; + }; + }; + + public func f2_0(x:Int,y:Bool) : async () { + assert(x==1); + assert(y==true); + }; + { + let t = "2_0"; + ignore async { + await f2_0(1,true); + debugPrint t; + }; + }; + + public func f3_0(x:Int,y:Bool,z:Text) : async () { + assert(x == 1); + assert(y == true); + assert(z == "a"); + }; + { + let t = "3_0"; + ignore async { + await f3_0(1,true,"a"); + debugPrint t; + }; + }; + + /* n-ary returns */ + + public func g0_0() : async () {}; + { + let t = "0_0"; + ignore async { + await g0_0(); + debugPrint t; + }; + }; + + public func g0_1() : async Int { + 1; + }; + { + let t = "0_1"; + ignore async { + let x = await g0_1(); + assert(x == 1); + debugPrint t; + x; + }; + }; + + public func g0_2() : async (Int,Bool) { + (1,true); + }; + { + let t = "0_2"; + ignore async { + let (x,y) = await g0_2(); + assert(x==1); + assert(y==true); + debugPrint t; + (x,y); + }; + }; + + + public func g0_3() : async (Int,Bool,Text) { + (1,true,"a"); + }; + { + let t = "0_3"; + ignore async { + let (x,y,z) = await g0_3(); + assert(x==1); + assert(y==true); + assert(z=="a"); + debugPrint t; + (x,y,z); + }; + }; +} diff --git a/test/run-stub/ok/AST-66.ic-stub-run.ok b/test/run-stub/ok/AST-66.ic-stub-run.ok new file mode 100644 index 00000000000..54225bc8555 --- /dev/null +++ b/test/run-stub/ok/AST-66.ic-stub-run.ok @@ -0,0 +1,4 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed diff --git a/test/run-stub/ok/async-any.ic-stub-run.ok b/test/run-stub/ok/async-any.ic-stub-run.ok new file mode 100644 index 00000000000..54225bc8555 --- /dev/null +++ b/test/run-stub/ok/async-any.ic-stub-run.ok @@ -0,0 +1,4 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed diff --git a/test/run-stub/ok/async-free-var.ic-stub-run.ok b/test/run-stub/ok/async-free-var.ic-stub-run.ok new file mode 100644 index 00000000000..80905ede799 --- /dev/null +++ b/test/run-stub/ok/async-free-var.ic-stub-run.ok @@ -0,0 +1,11 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +A +A +C +Now in async +C +B +B +← completed diff --git a/test/run-dfinity/ok/async-free-var.run-ir.ok b/test/run-stub/ok/async-free-var.run-ir.ok similarity index 100% rename from test/run-dfinity/ok/async-free-var.run-ir.ok rename to test/run-stub/ok/async-free-var.run-ir.ok diff --git a/test/run-dfinity/ok/async-free-var.run-low.ok b/test/run-stub/ok/async-free-var.run-low.ok similarity index 100% rename from test/run-dfinity/ok/async-free-var.run-low.ok rename to test/run-stub/ok/async-free-var.run-low.ok diff --git a/test/run-dfinity/ok/async-free-var.run.ok b/test/run-stub/ok/async-free-var.run.ok similarity index 100% rename from test/run-dfinity/ok/async-free-var.run.ok rename to test/run-stub/ok/async-free-var.run.ok diff --git a/test/run-stub/ok/async-loop-while.ic-stub-run.ok b/test/run-stub/ok/async-loop-while.ic-stub-run.ok new file mode 100644 index 00000000000..ac17ed83399 --- /dev/null +++ b/test/run-stub/ok/async-loop-while.ic-stub-run.ok @@ -0,0 +1,16 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +0 +1 +2 +0 +1 +2 +0 +1 +2 +0 +1 +2 +← completed diff --git a/test/run-dfinity/ok/async-loop-while.run-ir.ok b/test/run-stub/ok/async-loop-while.run-ir.ok similarity index 100% rename from test/run-dfinity/ok/async-loop-while.run-ir.ok rename to test/run-stub/ok/async-loop-while.run-ir.ok diff --git a/test/run-dfinity/ok/async-loop-while.run-low.ok b/test/run-stub/ok/async-loop-while.run-low.ok similarity index 100% rename from test/run-dfinity/ok/async-loop-while.run-low.ok rename to test/run-stub/ok/async-loop-while.run-low.ok diff --git a/test/run-dfinity/ok/async-loop-while.run.ok b/test/run-stub/ok/async-loop-while.run.ok similarity index 100% rename from test/run-dfinity/ok/async-loop-while.run.ok rename to test/run-stub/ok/async-loop-while.run.ok diff --git a/test/run-stub/ok/async-loop.ic-stub-run.ok b/test/run-stub/ok/async-loop.ic-stub-run.ok new file mode 100644 index 00000000000..ac17ed83399 --- /dev/null +++ b/test/run-stub/ok/async-loop.ic-stub-run.ok @@ -0,0 +1,16 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +0 +1 +2 +0 +1 +2 +0 +1 +2 +0 +1 +2 +← completed diff --git a/test/run-dfinity/ok/async-loop.run-ir.ok b/test/run-stub/ok/async-loop.run-ir.ok similarity index 100% rename from test/run-dfinity/ok/async-loop.run-ir.ok rename to test/run-stub/ok/async-loop.run-ir.ok diff --git a/test/run-dfinity/ok/async-loop.run-low.ok b/test/run-stub/ok/async-loop.run-low.ok similarity index 100% rename from test/run-dfinity/ok/async-loop.run-low.ok rename to test/run-stub/ok/async-loop.run-low.ok diff --git a/test/run-dfinity/ok/async-loop.run.ok b/test/run-stub/ok/async-loop.run.ok similarity index 100% rename from test/run-dfinity/ok/async-loop.run.ok rename to test/run-stub/ok/async-loop.run.ok diff --git a/test/run-stub/ok/async-new-obj.ic-stub-run.ok b/test/run-stub/ok/async-new-obj.ic-stub-run.ok new file mode 100644 index 00000000000..6bb840f5518 --- /dev/null +++ b/test/run-stub/ok/async-new-obj.ic-stub-run.ok @@ -0,0 +1,9 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +aaab +babb +dadb +eaeb +cacb +← completed diff --git a/test/run-dfinity/ok/async-new-obj.run-ir.ok b/test/run-stub/ok/async-new-obj.run-ir.ok similarity index 100% rename from test/run-dfinity/ok/async-new-obj.run-ir.ok rename to test/run-stub/ok/async-new-obj.run-ir.ok diff --git a/test/run-dfinity/ok/async-new-obj.run-low.ok b/test/run-stub/ok/async-new-obj.run-low.ok similarity index 100% rename from test/run-dfinity/ok/async-new-obj.run-low.ok rename to test/run-stub/ok/async-new-obj.run-low.ok diff --git a/test/run-dfinity/ok/async-new-obj.run.ok b/test/run-stub/ok/async-new-obj.run.ok similarity index 100% rename from test/run-dfinity/ok/async-new-obj.run.ok rename to test/run-stub/ok/async-new-obj.run.ok diff --git a/test/run-stub/ok/async-obj-mut.ic-stub-run.ok b/test/run-stub/ok/async-obj-mut.ic-stub-run.ok new file mode 100644 index 00000000000..836b858c056 --- /dev/null +++ b/test/run-stub/ok/async-obj-mut.ic-stub-run.ok @@ -0,0 +1,12 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +1 +2 +3 +done creating + +3 +4 +5 +← completed diff --git a/test/run-dfinity/ok/async-obj-mut.run-ir.ok b/test/run-stub/ok/async-obj-mut.run-ir.ok similarity index 100% rename from test/run-dfinity/ok/async-obj-mut.run-ir.ok rename to test/run-stub/ok/async-obj-mut.run-ir.ok diff --git a/test/run-dfinity/ok/async-obj-mut.run-low.ok b/test/run-stub/ok/async-obj-mut.run-low.ok similarity index 100% rename from test/run-dfinity/ok/async-obj-mut.run-low.ok rename to test/run-stub/ok/async-obj-mut.run-low.ok diff --git a/test/run-dfinity/ok/async-obj-mut.run.ok b/test/run-stub/ok/async-obj-mut.run.ok similarity index 100% rename from test/run-dfinity/ok/async-obj-mut.run.ok rename to test/run-stub/ok/async-obj-mut.run.ok diff --git a/test/run-stub/ok/async-while.ic-stub-run.ok b/test/run-stub/ok/async-while.ic-stub-run.ok new file mode 100644 index 00000000000..ac17ed83399 --- /dev/null +++ b/test/run-stub/ok/async-while.ic-stub-run.ok @@ -0,0 +1,16 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +0 +1 +2 +0 +1 +2 +0 +1 +2 +0 +1 +2 +← completed diff --git a/test/run-dfinity/ok/async-while.run-ir.ok b/test/run-stub/ok/async-while.run-ir.ok similarity index 100% rename from test/run-dfinity/ok/async-while.run-ir.ok rename to test/run-stub/ok/async-while.run-ir.ok diff --git a/test/run-dfinity/ok/async-while.run-low.ok b/test/run-stub/ok/async-while.run-low.ok similarity index 100% rename from test/run-dfinity/ok/async-while.run-low.ok rename to test/run-stub/ok/async-while.run-low.ok diff --git a/test/run-dfinity/ok/async-while.run.ok b/test/run-stub/ok/async-while.run.ok similarity index 100% rename from test/run-dfinity/ok/async-while.run.ok rename to test/run-stub/ok/async-while.run.ok diff --git a/test/run-stub/ok/await.ic-stub-run.ok b/test/run-stub/ok/await.ic-stub-run.ok new file mode 100644 index 00000000000..ea903adf0c1 --- /dev/null +++ b/test/run-stub/ok/await.ic-stub-run.ok @@ -0,0 +1,31 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +a +b +c +d +e +g +holy +e-while +g-label +. +a +b +cnt: 0 i: 0 +cnt: 1 i: 1 +cnt: 2 i: 2 +cnt: 3 i: 4 +cnt: 4 i: 5 +cnt: 5 i: 10 +. +cnt: 6 i: 3 +cnt: 7 i: 6 +cnt: 8 i: 11 +. +cnt: 9 i: 7 +cnt: 10 i: 12 +e-exit +g-exit +← completed diff --git a/test/run-dfinity/ok/await.run-ir.ok b/test/run-stub/ok/await.run-ir.ok similarity index 100% rename from test/run-dfinity/ok/await.run-ir.ok rename to test/run-stub/ok/await.run-ir.ok diff --git a/test/run-dfinity/ok/await.run-low.ok b/test/run-stub/ok/await.run-low.ok similarity index 100% rename from test/run-dfinity/ok/await.run-low.ok rename to test/run-stub/ok/await.run-low.ok diff --git a/test/run-dfinity/ok/await.run.ok b/test/run-stub/ok/await.run.ok similarity index 100% rename from test/run-dfinity/ok/await.run.ok rename to test/run-stub/ok/await.run.ok diff --git a/test/run-stub/ok/block.ic-stub-run.ok b/test/run-stub/ok/block.ic-stub-run.ok new file mode 100644 index 00000000000..6d6336f2016 --- /dev/null +++ b/test/run-stub/ok/block.ic-stub-run.ok @@ -0,0 +1,14 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +a1 +b1 +1 +a2 +b2 +a3 +b3 +3 +5 +6 +← completed diff --git a/test/run-dfinity/ok/block.run-ir.ok b/test/run-stub/ok/block.run-ir.ok similarity index 100% rename from test/run-dfinity/ok/block.run-ir.ok rename to test/run-stub/ok/block.run-ir.ok diff --git a/test/run-dfinity/ok/block.run-low.ok b/test/run-stub/ok/block.run-low.ok similarity index 100% rename from test/run-dfinity/ok/block.run-low.ok rename to test/run-stub/ok/block.run-low.ok diff --git a/test/run-dfinity/ok/block.run.ok b/test/run-stub/ok/block.run.ok similarity index 100% rename from test/run-dfinity/ok/block.run.ok rename to test/run-stub/ok/block.run.ok diff --git a/test/run-stub/ok/closure-params.ic-stub-run.ok b/test/run-stub/ok/closure-params.ic-stub-run.ok new file mode 100644 index 00000000000..8288cb11e5d --- /dev/null +++ b/test/run-stub/ok/closure-params.ic-stub-run.ok @@ -0,0 +1,14 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +1 +3 +6 +10 +15 +1 +3 +6 +10 +15 +← completed diff --git a/test/run-dfinity/ok/closure-params.run-ir.ok b/test/run-stub/ok/closure-params.run-ir.ok similarity index 100% rename from test/run-dfinity/ok/closure-params.run-ir.ok rename to test/run-stub/ok/closure-params.run-ir.ok diff --git a/test/run-dfinity/ok/closure-params.run-low.ok b/test/run-stub/ok/closure-params.run-low.ok similarity index 100% rename from test/run-dfinity/ok/closure-params.run-low.ok rename to test/run-stub/ok/closure-params.run-low.ok diff --git a/test/run-dfinity/ok/closure-params.run.ok b/test/run-stub/ok/closure-params.run.ok similarity index 100% rename from test/run-dfinity/ok/closure-params.run.ok rename to test/run-stub/ok/closure-params.run.ok diff --git a/test/run-dfinity/ok/flatten-awaitables.dvm.ok b/test/run-stub/ok/flatten-awaitables.ic-stub-run.ok similarity index 54% rename from test/run-dfinity/ok/flatten-awaitables.dvm.ok rename to test/run-stub/ok/flatten-awaitables.ic-stub-run.ok index 86dad5a61f1..31491e54d1f 100644 --- a/test/run-dfinity/ok/flatten-awaitables.dvm.ok +++ b/test/run-stub/ok/flatten-awaitables.ic-stub-run.ok @@ -1,3 +1,6 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install first-order 0 1 @@ -32,3 +35,4 @@ higher-order 13 14 15 +← completed diff --git a/test/run-dfinity/ok/flatten-awaitables.run-ir.ok b/test/run-stub/ok/flatten-awaitables.run-ir.ok similarity index 100% rename from test/run-dfinity/ok/flatten-awaitables.run-ir.ok rename to test/run-stub/ok/flatten-awaitables.run-ir.ok diff --git a/test/run-dfinity/ok/flatten-awaitables.run-low.ok b/test/run-stub/ok/flatten-awaitables.run-low.ok similarity index 100% rename from test/run-dfinity/ok/flatten-awaitables.run-low.ok rename to test/run-stub/ok/flatten-awaitables.run-low.ok diff --git a/test/run-dfinity/ok/flatten-awaitables.run.ok b/test/run-stub/ok/flatten-awaitables.run.ok similarity index 100% rename from test/run-dfinity/ok/flatten-awaitables.run.ok rename to test/run-stub/ok/flatten-awaitables.run.ok diff --git a/test/run-dfinity/ok/flatten-awaitables.tc.ok b/test/run-stub/ok/flatten-awaitables.tc.ok similarity index 100% rename from test/run-dfinity/ok/flatten-awaitables.tc.ok rename to test/run-stub/ok/flatten-awaitables.tc.ok diff --git a/test/run-stub/ok/for-await.ic-stub-run.ok b/test/run-stub/ok/for-await.ic-stub-run.ok new file mode 100644 index 00000000000..5e7fbc6f075 --- /dev/null +++ b/test/run-stub/ok/for-await.ic-stub-run.ok @@ -0,0 +1,15 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +← completed diff --git a/test/run-dfinity/ok/for-await.run-ir.ok b/test/run-stub/ok/for-await.run-ir.ok similarity index 100% rename from test/run-dfinity/ok/for-await.run-ir.ok rename to test/run-stub/ok/for-await.run-ir.ok diff --git a/test/run-dfinity/ok/for-await.run-low.ok b/test/run-stub/ok/for-await.run-low.ok similarity index 100% rename from test/run-dfinity/ok/for-await.run-low.ok rename to test/run-stub/ok/for-await.run-low.ok diff --git a/test/run-dfinity/ok/for-await.run.ok b/test/run-stub/ok/for-await.run.ok similarity index 100% rename from test/run-dfinity/ok/for-await.run.ok rename to test/run-stub/ok/for-await.run.ok diff --git a/test/run-stub/ok/interleave.ic-stub-run.ok b/test/run-stub/ok/interleave.ic-stub-run.ok new file mode 100644 index 00000000000..7a32913cb52 --- /dev/null +++ b/test/run-stub/ok/interleave.ic-stub-run.ok @@ -0,0 +1,23 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +g + e-while + +g-label + + e cnt: 0 i: 5 +g cnt: 1 i: 10 + e cnt: 2 i: 6 +g cnt: 3 i: 11 + e cnt: 4 i: 7 +g cnt: 5 i: 12 + e cnt: 6 i: 8 +g cnt: 7 i: 13 + e cnt: 8 i: 9 +g cnt: 9 i: 14 + e-exit + +g-exit + +← completed diff --git a/test/run-dfinity/ok/interleave.run-ir.ok b/test/run-stub/ok/interleave.run-ir.ok similarity index 100% rename from test/run-dfinity/ok/interleave.run-ir.ok rename to test/run-stub/ok/interleave.run-ir.ok diff --git a/test/run-dfinity/ok/interleave.run-low.ok b/test/run-stub/ok/interleave.run-low.ok similarity index 100% rename from test/run-dfinity/ok/interleave.run-low.ok rename to test/run-stub/ok/interleave.run-low.ok diff --git a/test/run-dfinity/ok/interleave.run.ok b/test/run-stub/ok/interleave.run.ok similarity index 100% rename from test/run-dfinity/ok/interleave.run.ok rename to test/run-stub/ok/interleave.run.ok diff --git a/test/run-stub/ok/local-throw.ic-stub-run.ok b/test/run-stub/ok/local-throw.ic-stub-run.ok new file mode 100644 index 00000000000..49cd150c9d8 --- /dev/null +++ b/test/run-stub/ok/local-throw.ic-stub-run.ok @@ -0,0 +1,6 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +t2 ok +t3 ok +← completed diff --git a/test/run-dfinity/ok/local-throw.run-ir.ok b/test/run-stub/ok/local-throw.run-ir.ok similarity index 100% rename from test/run-dfinity/ok/local-throw.run-ir.ok rename to test/run-stub/ok/local-throw.run-ir.ok diff --git a/test/run-dfinity/ok/local-throw.run-low.ok b/test/run-stub/ok/local-throw.run-low.ok similarity index 100% rename from test/run-dfinity/ok/local-throw.run-low.ok rename to test/run-stub/ok/local-throw.run-low.ok diff --git a/test/run-dfinity/ok/local-throw.run.ok b/test/run-stub/ok/local-throw.run.ok similarity index 100% rename from test/run-dfinity/ok/local-throw.run.ok rename to test/run-stub/ok/local-throw.run.ok diff --git a/test/run-stub/ok/nary-async.ic-stub-run.ok b/test/run-stub/ok/nary-async.ic-stub-run.ok new file mode 100644 index 00000000000..5070e4ed2ea --- /dev/null +++ b/test/run-stub/ok/nary-async.ic-stub-run.ok @@ -0,0 +1,12 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +0_0 +1_0 +2_0 +3_0 +0_0 +0_1 +0_2 +0_3 +← completed diff --git a/test/run-dfinity/ok/nary-async.run-ir.ok b/test/run-stub/ok/nary-async.run-ir.ok similarity index 82% rename from test/run-dfinity/ok/nary-async.run-ir.ok rename to test/run-stub/ok/nary-async.run-ir.ok index c49facc630f..8921d750e55 100644 --- a/test/run-dfinity/ok/nary-async.run-ir.ok +++ b/test/run-stub/ok/nary-async.run-ir.ok @@ -5,4 +5,4 @@ 0_0 0_1 0_2 -0_3!! +0_3 diff --git a/test/run-dfinity/ok/nary-async.run-low.ok b/test/run-stub/ok/nary-async.run-low.ok similarity index 82% rename from test/run-dfinity/ok/nary-async.run-low.ok rename to test/run-stub/ok/nary-async.run-low.ok index c49facc630f..8921d750e55 100644 --- a/test/run-dfinity/ok/nary-async.run-low.ok +++ b/test/run-stub/ok/nary-async.run-low.ok @@ -5,4 +5,4 @@ 0_0 0_1 0_2 -0_3!! +0_3 diff --git a/test/run-dfinity/ok/nary-async.run.ok b/test/run-stub/ok/nary-async.run.ok similarity index 82% rename from test/run-dfinity/ok/nary-async.run.ok rename to test/run-stub/ok/nary-async.run.ok index c49facc630f..8921d750e55 100644 --- a/test/run-dfinity/ok/nary-async.run.ok +++ b/test/run-stub/ok/nary-async.run.ok @@ -5,4 +5,4 @@ 0_0 0_1 0_2 -0_3!! +0_3 diff --git a/test/run-stub/ok/overflow.ic-stub-run.ok b/test/run-stub/ok/overflow.ic-stub-run.ok new file mode 100644 index 00000000000..20223842232 --- /dev/null +++ b/test/run-stub/ok/overflow.ic-stub-run.ok @@ -0,0 +1,12 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +This is reachable. +This is reachable. +Trap: EvalTrapError :0.1 "canister trapped explicitly: Natural subtraction underflow" +Trap: EvalTrapError :0.1 "canister trapped explicitly: Natural subtraction underflow" +This is reachable. +This is reachable. +Trap: EvalTrapError :0.1 "canister trapped explicitly: reject_callback" +Trap: EvalTrapError :0.1 "canister trapped explicitly: reject_callback" +← completed diff --git a/test/run-dfinity/ok/overflow.run-ir.ok b/test/run-stub/ok/overflow.run-ir.ok similarity index 100% rename from test/run-dfinity/ok/overflow.run-ir.ok rename to test/run-stub/ok/overflow.run-ir.ok diff --git a/test/run-dfinity/ok/overflow.run-low.ok b/test/run-stub/ok/overflow.run-low.ok similarity index 100% rename from test/run-dfinity/ok/overflow.run-low.ok rename to test/run-stub/ok/overflow.run-low.ok diff --git a/test/run-dfinity/ok/overflow.run.ok b/test/run-stub/ok/overflow.run.ok similarity index 100% rename from test/run-dfinity/ok/overflow.run.ok rename to test/run-stub/ok/overflow.run.ok diff --git a/test/run-stub/ok/query2.ic-stub-run.ok b/test/run-stub/ok/query2.ic-stub-run.ok new file mode 100644 index 00000000000..d15550489c8 --- /dev/null +++ b/test/run-stub/ok/query2.ic-stub-run.ok @@ -0,0 +1,10 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +2 +3 +4 +4 +Trap: EvalTrapError :0.1 "canister trapped explicitly: reject_callback" +Trap: EvalTrapError :0.1 "canister trapped explicitly: reject_callback" +← completed diff --git a/test/run-stub/ok/query2.run-ir.ok b/test/run-stub/ok/query2.run-ir.ok new file mode 100644 index 00000000000..3c0e48a4d47 --- /dev/null +++ b/test/run-stub/ok/query2.run-ir.ok @@ -0,0 +1,12 @@ +2 +3 +4 +4 +In read: +5 +5 +In read: +6 +The following fails in the intepreter, for lack of query semantics +query2.mo:65.2-65.16: execution error, assertion failure +6 diff --git a/test/run-stub/ok/query2.run-low.ok b/test/run-stub/ok/query2.run-low.ok new file mode 100644 index 00000000000..3c0e48a4d47 --- /dev/null +++ b/test/run-stub/ok/query2.run-low.ok @@ -0,0 +1,12 @@ +2 +3 +4 +4 +In read: +5 +5 +In read: +6 +The following fails in the intepreter, for lack of query semantics +query2.mo:65.2-65.16: execution error, assertion failure +6 diff --git a/test/run-stub/ok/query2.run.ok b/test/run-stub/ok/query2.run.ok new file mode 100644 index 00000000000..3c0e48a4d47 --- /dev/null +++ b/test/run-stub/ok/query2.run.ok @@ -0,0 +1,12 @@ +2 +3 +4 +4 +In read: +5 +5 +In read: +6 +The following fails in the intepreter, for lack of query semantics +query2.mo:65.2-65.16: execution error, assertion failure +6 diff --git a/test/run-stub/ok/reference-params.ic-stub-run.ok b/test/run-stub/ok/reference-params.ic-stub-run.ok new file mode 100644 index 00000000000..bb1a279f272 --- /dev/null +++ b/test/run-stub/ok/reference-params.ic-stub-run.ok @@ -0,0 +1,9 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +Hello World! +Hello World! +Hello World! +Hello Universe! +Hello Galaxy! +← completed diff --git a/test/run-dfinity/ok/reference-params.run-ir.ok b/test/run-stub/ok/reference-params.run-ir.ok similarity index 100% rename from test/run-dfinity/ok/reference-params.run-ir.ok rename to test/run-stub/ok/reference-params.run-ir.ok diff --git a/test/run-dfinity/ok/reference-params.run-low.ok b/test/run-stub/ok/reference-params.run-low.ok similarity index 100% rename from test/run-dfinity/ok/reference-params.run-low.ok rename to test/run-stub/ok/reference-params.run-low.ok diff --git a/test/run-dfinity/ok/reference-params.run.ok b/test/run-stub/ok/reference-params.run.ok similarity index 100% rename from test/run-dfinity/ok/reference-params.run.ok rename to test/run-stub/ok/reference-params.run.ok diff --git a/test/run-stub/ok/simple-throw.ic-stub-run.ok b/test/run-stub/ok/simple-throw.ic-stub-run.ok new file mode 100644 index 00000000000..f97beec3dc8 --- /dev/null +++ b/test/run-stub/ok/simple-throw.ic-stub-run.ok @@ -0,0 +1,9 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +1 +2 +3 +4 +done +← completed diff --git a/test/run-dfinity/ok/simple-throw.run-ir.ok b/test/run-stub/ok/simple-throw.run-ir.ok similarity index 100% rename from test/run-dfinity/ok/simple-throw.run-ir.ok rename to test/run-stub/ok/simple-throw.run-ir.ok diff --git a/test/run-dfinity/ok/simple-throw.run-low.ok b/test/run-stub/ok/simple-throw.run-low.ok similarity index 100% rename from test/run-dfinity/ok/simple-throw.run-low.ok rename to test/run-stub/ok/simple-throw.run-low.ok diff --git a/test/run-dfinity/ok/simple-throw.run.ok b/test/run-stub/ok/simple-throw.run.ok similarity index 100% rename from test/run-dfinity/ok/simple-throw.run.ok rename to test/run-stub/ok/simple-throw.run.ok diff --git a/test/run-stub/ok/type-lub.ic-stub-run.ok b/test/run-stub/ok/type-lub.ic-stub-run.ok new file mode 100644 index 00000000000..54225bc8555 --- /dev/null +++ b/test/run-stub/ok/type-lub.ic-stub-run.ok @@ -0,0 +1,4 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed diff --git a/test/run-dfinity/overflow.mo b/test/run-stub/overflow.mo similarity index 100% rename from test/run-dfinity/overflow.mo rename to test/run-stub/overflow.mo diff --git a/test/run-stub/query2.mo b/test/run-stub/query2.mo new file mode 100644 index 00000000000..21a6de83b91 --- /dev/null +++ b/test/run-stub/query2.mo @@ -0,0 +1,66 @@ +actor counter = { + var c = 1; + public func inc() { + c += 1; + debugPrintNat c; + }; + public func printCounter () { + debugPrintNat c; + }; + public func get() : async Nat { + return c + }; + public query func read() : async Nat { + let tmp = c; + c += 1; + debugPrint "In read:"; + debugPrintNat c; + return tmp; + }; + +}; + +/* Disabled, while we don’t have first-class shared functions + + { // fully explicit syntax + + let _ : actor { read : shared query () -> async Nat } = counter; + + shared query func f () : async Nat { 666; }; + + type Query = shared query () -> async Nat; + + let _ : Query = counter.read; + + }; + + { + + // sugar, surpressing shared + + let _ : actor { read: query () -> async Nat } = counter; + + query func f () : async Nat { 666; }; + + type Query = query () -> async Nat; + + let _ : Query = counter.read; + + }; +*/ + +async { + counter.inc(); + counter.inc(); + counter.inc(); + counter.printCounter(); + let c1 = await counter.get(); + assert c1 == 4; + let c2 = await counter.read(); + counter.printCounter(); + assert c2 == 4; + let c3 = await counter.read(); + counter.printCounter(); + debugPrint("The following fails in the intepreter, for lack of query semantics"); + assert c3 == 4; +}; diff --git a/test/run-stub/reference-params.mo b/test/run-stub/reference-params.mo new file mode 100644 index 00000000000..b29fac1cab8 --- /dev/null +++ b/test/run-stub/reference-params.mo @@ -0,0 +1,49 @@ +actor { + let a = actor { + public func hello() { + debugPrint("Hello World!"); + }; + }; + a.hello(); + + // test passing an actor to an actor + let b = actor this { + public func say_hi(a : actor { hello : () -> () } ) { + a.hello(); + }; + }; + b.say_hi(a); + + // test passing a funcref to an actor + let c = actor { + public func say_hi(f : shared () -> ()) { + f(); + }; + }; + c.say_hi(a.hello); + + // test passing a own funcref to an actor + let d = actor { + public func say_hi(f : shared () -> ()) { + f(); + }; + public func hello() { + debugPrint("Hello Universe!"); + }; + public func go() { + say_hi(hello); + } + }; + d.go(); + + // test passing a self to an actor + let e = actor this { + public func hello() { + debugPrint("Hello Galaxy!"); + }; + public func send_to(f : shared (actor { hello : () -> () }) -> ()) { + f(this); + } + }; + e.send_to(b.say_hi); +} diff --git a/test/run-dfinity/simple-throw.mo b/test/run-stub/simple-throw.mo similarity index 100% rename from test/run-dfinity/simple-throw.mo rename to test/run-stub/simple-throw.mo diff --git a/test/run-dfinity/type-lub.mo b/test/run-stub/type-lub.mo similarity index 100% rename from test/run-dfinity/type-lub.mo rename to test/run-stub/type-lub.mo diff --git a/test/run-dfinity/chatpp.mo b/test/run/chatpp.mo similarity index 96% rename from test/run-dfinity/chatpp.mo rename to test/run/chatpp.mo index 6da6492d316..d96e11d9bba 100644 --- a/test/run-dfinity/chatpp.mo +++ b/test/run/chatpp.mo @@ -93,3 +93,6 @@ let charlie = Client(); bob.go("bob", server); alice.go("alice", server); charlie.go("charlie", server); + +// no support for first-class shared functions anywhere yet +//SKIP comp diff --git a/test/run-dfinity/counter-class.mo b/test/run/counter-class.mo similarity index 80% rename from test/run-dfinity/counter-class.mo rename to test/run/counter-class.mo index 711ec097d54..bfc4d6d2820 100644 --- a/test/run-dfinity/counter-class.mo +++ b/test/run/counter-class.mo @@ -22,3 +22,6 @@ func test() { }; let _ = test(); + +// no support for first-class shared functions anywhere yet +//SKIP comp diff --git a/test/run-dfinity/ok/chatpp.run-ir.ok b/test/run/ok/chatpp.run-ir.ok similarity index 100% rename from test/run-dfinity/ok/chatpp.run-ir.ok rename to test/run/ok/chatpp.run-ir.ok diff --git a/test/run-dfinity/ok/chatpp.run-low.ok b/test/run/ok/chatpp.run-low.ok similarity index 100% rename from test/run-dfinity/ok/chatpp.run-low.ok rename to test/run/ok/chatpp.run-low.ok diff --git a/test/run-dfinity/ok/chatpp.run.ok b/test/run/ok/chatpp.run.ok similarity index 100% rename from test/run-dfinity/ok/chatpp.run.ok rename to test/run/ok/chatpp.run.ok From 0be07fb64cc42fc2c04834cae3831e4b0014c36d Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 26 Nov 2019 18:48:38 +0100 Subject: [PATCH 0715/1176] Allow `actor class Foo()` (no parameter) on stub (#935) * Allow `actor class Foo()` (no parameter) on stub * Apply suggestions from code review Fix error message * Delete run-dfinity, nothing left here --- src/mo_frontend/typing.ml | 10 ++++++++-- test/Makefile | 5 ----- test/run-dfinity/Makefile | 12 ------------ test/{run-dfinity => run-stub}/chat.mo | 2 +- .../chat.dvm.ok => run-stub/ok/chat.ic-stub-run.ok} | 10 ++++++++++ test/{run-dfinity => run-stub}/ok/chat.run-ir.ok | 0 test/{run-dfinity => run-stub}/ok/chat.run-low.ok | 0 test/{run-dfinity => run-stub}/ok/chat.run.ok | 0 test/run-stub/ok/unsupported.comp.ok | 2 +- test/run-stub/unsupported.mo | 2 +- 10 files changed, 21 insertions(+), 22 deletions(-) delete mode 100644 test/run-dfinity/Makefile rename test/{run-dfinity => run-stub}/chat.mo (97%) rename test/{run-dfinity/ok/chat.dvm.ok => run-stub/ok/chat.ic-stub-run.ok} (58%) rename test/{run-dfinity => run-stub}/ok/chat.run-ir.ok (100%) rename test/{run-dfinity => run-stub}/ok/chat.run-low.ok (100%) rename test/{run-dfinity => run-stub}/ok/chat.run.ok (100%) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index a2a82dc92e5..488c1d242cd 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -1814,8 +1814,15 @@ and infer_dec_valdecs env dec : Scope.t = } | ClassD (id, typ_binds, pat, _, sort, _, _) -> if sort.it = T.Actor then - error_in [Flags.ICMode; Flags.StubMode] env dec.at + error_in [Flags.ICMode] env dec.at "actor classes are not supported; use an actor declaration instead"; + let rec is_unit_pat p = match p.it with + | ParP p -> is_unit_pat p + | TupP [] -> true + | _ -> false in + if sort.it = T.Actor && not (is_unit_pat pat) then + error_in [Flags.StubMode] env dec.at + "actor classes with parameters are not supported; use an actor declaration instead"; let cs, ts, te, ce = check_typ_binds env typ_binds in let env' = adjoin_typs env te ce in let c = T.Env.find id.it env.typs in @@ -1876,4 +1883,3 @@ let check_actors scope progs : unit Diag.result = ds ) progs) - diff --git a/test/Makefile b/test/Makefile index 8502938468f..f61bbeb9723 100644 --- a/test/Makefile +++ b/test/Makefile @@ -2,7 +2,6 @@ all: $(MAKE) -C fail $(MAKE) -C run $(MAKE) -C run-release - $(MAKE) -C run-dfinity $(MAKE) -C run-drun $(MAKE) -C run-stub $(MAKE) -C repl @@ -23,7 +22,6 @@ quick: $(MAKE_PAR) -C mo-idl quick parallel: quick - $(MAKE_PAR) -C run-dfinity quick $(MAKE_PAR) -C run-drun quick $(MAKE_PAR) -C run-stub quick $(MAKE_PAR) -C trap quick @@ -37,7 +35,6 @@ coverage: $(MAKE) -C fail; \ $(MAKE) -C run; \ $(MAKE) -C run-release; \ - $(MAKE) -C run-dfinity; \ $(MAKE) -C run-drun; \ $(MAKE) -C run-stub; \ $(MAKE) -C repl; @@ -49,7 +46,6 @@ accept: $(MAKE) -C fail accept $(MAKE) -C run accept $(MAKE) -C run-release accept - $(MAKE) -C run-dfinity accept $(MAKE) -C run-drun accept $(MAKE) -C run-stub accept $(MAKE) -C repl accept @@ -63,7 +59,6 @@ clean: $(MAKE) -C fail clean $(MAKE) -C run clean $(MAKE) -C run-release clean - $(MAKE) -C run-dfinity clean $(MAKE) -C run-drun clean $(MAKE) -C run-stub clean $(MAKE) -C repl clean diff --git a/test/run-dfinity/Makefile b/test/run-dfinity/Makefile deleted file mode 100644 index 97145fb5c64..00000000000 --- a/test/run-dfinity/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -RUNFLAGS = -1 - -all: - ../run.sh $(RUNFLAGS) *.mo - -accept: - ../run.sh $(RUNFLAGS) -a *.mo - -clean: - rm -rf _out - -include ../*.mk diff --git a/test/run-dfinity/chat.mo b/test/run-stub/chat.mo similarity index 97% rename from test/run-dfinity/chat.mo rename to test/run-stub/chat.mo index 520aeaf38fe..8cf6f40542c 100644 --- a/test/run-dfinity/chat.mo +++ b/test/run-stub/chat.mo @@ -5,7 +5,7 @@ type Post = shared Text -> (); actor class Server() = { var clients : List = null; - shared func broadcast(message : Text) { + public func broadcast(message : Text) { var next = clients; loop { switch next { diff --git a/test/run-dfinity/ok/chat.dvm.ok b/test/run-stub/ok/chat.ic-stub-run.ok similarity index 58% rename from test/run-dfinity/ok/chat.dvm.ok rename to test/run-stub/ok/chat.ic-stub-run.ok index 40f6822b967..ea692752113 100644 --- a/test/run-dfinity/ok/chat.dvm.ok +++ b/test/run-stub/ok/chat.ic-stub-run.ok @@ -1,7 +1,16 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +charlie received hello from bob +alice received hello from bob bob received hello from bob +charlie received goodbye from bob +alice received goodbye from bob bob received goodbye from bob +charlie received hello from alice alice received hello from alice bob received hello from alice +charlie received goodbye from alice alice received goodbye from alice bob received goodbye from alice charlie received hello from charlie @@ -10,3 +19,4 @@ bob received hello from charlie charlie received goodbye from charlie alice received goodbye from charlie bob received goodbye from charlie +← completed diff --git a/test/run-dfinity/ok/chat.run-ir.ok b/test/run-stub/ok/chat.run-ir.ok similarity index 100% rename from test/run-dfinity/ok/chat.run-ir.ok rename to test/run-stub/ok/chat.run-ir.ok diff --git a/test/run-dfinity/ok/chat.run-low.ok b/test/run-stub/ok/chat.run-low.ok similarity index 100% rename from test/run-dfinity/ok/chat.run-low.ok rename to test/run-stub/ok/chat.run-low.ok diff --git a/test/run-dfinity/ok/chat.run.ok b/test/run-stub/ok/chat.run.ok similarity index 100% rename from test/run-dfinity/ok/chat.run.ok rename to test/run-stub/ok/chat.run.ok diff --git a/test/run-stub/ok/unsupported.comp.ok b/test/run-stub/ok/unsupported.comp.ok index 24c01e4cd61..ad1bf6587e8 100644 --- a/test/run-stub/ok/unsupported.comp.ok +++ b/test/run-stub/ok/unsupported.comp.ok @@ -2,7 +2,7 @@ unsupported.mo:4.5-4.41: type error, a shared function cannot be private (This is a limitation of the current version and flag -stub-system-api.) unsupported.mo:38.26-38.29: type error, a shared function is only allowed as a public field of an actor (This is a limitation of the current version and flag -stub-system-api.) -unsupported.mo:62.3-62.35: type error, actor classes are not supported; use an actor declaration instead +unsupported.mo:62.3-62.42: type error, actor classes with parameters are not supported; use an actor declaration instead (This is a limitation of the current version and flag -stub-system-api.) unsupported.mo:80.34-80.37: type error, a shared function is only allowed as a public field of an actor (This is a limitation of the current version and flag -stub-system-api.) diff --git a/test/run-stub/unsupported.mo b/test/run-stub/unsupported.mo index 7a043cde6df..58f17ecb5b1 100644 --- a/test/run-stub/unsupported.mo +++ b/test/run-stub/unsupported.mo @@ -59,7 +59,7 @@ func local_spawn() { */ { - actor class BadActorClass () { }; // no actor classes + actor class BadActorClass (x : Int) { }; // no actor classes }; { From 5a15877bce47e05184d7295377548368fa5b2d2e Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 26 Nov 2019 20:27:04 +0000 Subject: [PATCH 0716/1176] don't flatten success arguments (for consistency with other cases --- src/ir_def/check_ir.ml | 1 - src/ir_passes/async.ml | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 8cd0335da55..84cb458cf1c 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -613,7 +613,6 @@ let rec check_exp env (exp:Ir.exp) : unit = "shared function with async type has non-async body"; if T.is_shared_sort sort then List.iter (check_concrete env exp.at) ret_tys; let codom = T.codom control ret_tys in - let is_oneway = T.is_shared_sort sort && control = T.Returns in let env'' = {env' with labs = T.Env.empty; rets = Some codom; async = None} in check_exp (adjoin_vals env'' ve) exp; diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index 4cbb4b538a9..d4f42405690 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -279,7 +279,7 @@ let transform mode env prog = tb, List.map t_typ (List.map (T.open_ [t0]) ts1) | t -> assert false in let ((nary_async, nary_reply, reject), def) = new_nary_async_reply mode ts1 in -(* +(* TBD (blockE [letP (tupP [varP nary_async; varP nary_reply; varP reject]) def; funcD post u ( let vs = fresh_vars "v" ts1 in @@ -291,11 +291,11 @@ let transform mode env prog = *) (blockE [ letP (tupP [varP nary_async; varP nary_reply; varP reject]) def; - let v = fresh_var "v" (T.seq ts1) in + let v = fresh_var "v" (T.seq ts1) in (* flatten v, here and below? *) let ic_reply = v --> (ic_replyE ts1 v) in let e = fresh_var "e" T.catch in let ic_reject = [e] -->* (ic_rejectE (errorMessageE e)) in - let exp' = callE (t_exp exp1 [t0] (tupE [ic_reply; ic_reject])) in + let exp' = callE (t_exp exp1) [t0] (tupE [ic_reply; ic_reject]) in expD (selfcallE ts1 exp' nary_reply reject) ] nary_async From 1eb31b1f431b09dab6ee25500d24fca79461d577 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 27 Nov 2019 00:02:57 +0000 Subject: [PATCH 0717/1176] new sugar; WIP --- design/scoped-await.md | 74 +++++++++++++++++++++++++------------- src/lowering/desugar.ml | 2 +- src/mo_def/arrange.ml | 2 +- src/mo_def/syntax.ml | 16 ++++++++- src/mo_frontend/parser.mly | 33 ++++++++++++++--- src/mo_frontend/typing.ml | 9 ++++- 6 files changed, 104 insertions(+), 32 deletions(-) diff --git a/design/scoped-await.md b/design/scoped-await.md index ca0e6596618..350a8fedc08 100644 --- a/design/scoped-await.md +++ b/design/scoped-await.md @@ -35,15 +35,15 @@ _Please break it_ ```bnf := ... - | async[T]U // T is an index, typically a type parameter + | asyncU // T is an index, typically a type parameter := | async e // index abstraction plus application in one (parameter X free in e, but not in instantiation U) - | shared f(x:T) : async[X]U = async e ; // requests - | shared f(x:T) : async[X]U { e; } // sugar (for the above) + | shared f(x:T) : asyncU = async e ; // requests + | shared f(x:T) : asyncU { e; } // sugar (for the above) | f e // (indexed) application -Ctxt := E; async[T] // async context with index U +Ctxt := E; async // async context with index U | E; - // non-async context Env := // the usual suspects @@ -61,7 +61,7 @@ Here, the simplist might be to use the function name itself for the implicit ind ### Parameterized async expressions ``` -E, X; async[X] |- e : T E |- U :: * (X fresh) +E, X; async |- e : T E |- U :: * (X fresh) ------------------------------------------------- E; - |- async e : async[U]T ``` @@ -73,20 +73,20 @@ parameter is immediately eliminated at some index `U` (not mentioning `X`). ### (restricted) await expressions ``` -E; async[T] |- e : async[T]U +E; async |- e : asyncU ------------------------------ -E; async[T] |- await e : U +E; async |- await e : U ``` -We can only await things of the current index `T`, recorded in the context as `_ ; async[T]`. +We can only await things of the current index `T`, recorded in the context as `_ ; async`. ### Application ``` -E; _ |- f : shared U -> async[X] V +E; _ |- f : shared U -> async V E; _ |- e': [T/X] U ------------------------------------- -E; _ |- f e' : async[T]([T/X]V) +E; _ |- f e' : async([T/X]V) ``` Application must provide an index, typically the nearest enclosing index parameter if want to await the result, but I guess @@ -100,7 +100,7 @@ Rule for (desugared) shared functions (ignoring recursion). ``` E, X, x : T, Y; async |- e : U (X, Y fresh) ---------------------------------------------------- -E; _ |- shared f(x:T) : async[X]U = async e ; +E; _ |- shared f(x:T) : asyncU = async e ; ``` Every shared function introduce a new index parameter, immediately supplied to the inner async expression. @@ -109,7 +109,7 @@ Derived rule for sugar (ignoring recursion): ``` E, X, x : T; async |- e : U -------------------------------------------- -E; _ |- shared f(x:T) : async[X] U { e; } +E; _ |- shared f(x:T) : async U { e; } ``` ## Examples: @@ -117,9 +117,9 @@ E; _ |- shared f(x:T) : async[X] U { e; } Assuming the following requests: ``` -shared Ack() : async[X](){ }; +shared Ack() : async(){ }; -shared Request(i : Int) : async[X] Int { return i; } +shared Request(i : Int) : async Int { return i; } ``` ### Static parralel waiting: @@ -159,7 +159,7 @@ async { ### Recursive parallel waiting ``` -shared func waitN(n:Nat) : async[X]() { +shared func waitN(n:Nat) : async() { if (n = 0) () else { @@ -173,7 +173,7 @@ shared func waitN(n:Nat) : async[X]() { ### Recursive parallel waiting (with results) ``` -shared func waitN(n:Nat) : async[X](List) { +shared func waitN(n:Nat) : async(List) { if (n = 0) List.null(); else { @@ -190,7 +190,7 @@ shared func waitN(n:Nat) : async[X](List) { ``` -let t:async[T]U = async{ await t;}; // bad await since t : Async[Any]U U = async{ await t;}; // bad await since t : Async[Any]U U ``` Ruled out by index scoping (`X != T`, any `T`) @@ -199,8 +199,8 @@ Ruled out by index scoping (`X != T`, any `T`) ``` async { - let a1 = async{ await a2; }; // bad await since a1 : Async[X]() () - let a2 = async{ await a1; }; // bad await since a2 : Async[X]() () + let a1 = async{ await a2; }; // bad await since a1 : Async() () + let a2 = async{ await a1; }; // bad await since a2 : Async() () await(a1); }; ``` @@ -213,9 +213,9 @@ The informal example: ``` shared func f() : async () { var x : async Nat = async 0; - x := async { - await x - }; + x := async { + await x + }; } ``` @@ -226,8 +226,34 @@ Explicitly, the shared function and nested async would have distinct indices,so ``` shared func f() : async () { var x : async Nat = async<_> 0 ; - x := async{ + x := async{ await x // illegal: await _ : asyncT -> T (not async T -> T) (any T) - } ; + } ; } ``` + + +syntactic sugar: + +``` +async typ := async<@> typ + +(typ,...) -> async<@> typ -> := +<@>(typ,...) -> async<@> typ + +func f() : async<@> t = e +func<@>f() : async<@>t = e + +func f() : async<@> t { e } :- +func<@>f() : async<@>t { e } :- + +x(pat) : async t {e} = x<@>(pat): async<@> t +x(pat) : async t = e = x<@>(pat): async<@> t + +async e := async<@> e <@> +``` + +static sugar +``` +f e = f<@>e when f: sort (typ,...) -> async t +``` diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 167200a15a4..5bb21716280 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -112,7 +112,7 @@ and exp' at note = function if T.is_non t then unreachableE.it else - let inst = List.map (fun t -> t.Source.note) inst in + let inst = List.map (fun t -> t.Source.note) (!inst) in I.CallE (exp e1, inst, exp e2) | S.BlockE [] -> I.TupE [] | S.BlockE [{it = S.ExpD e; _}] -> (exp e).it diff --git a/src/mo_def/arrange.ml b/src/mo_def/arrange.ml index a7667805467..cd19293b289 100644 --- a/src/mo_def/arrange.ml +++ b/src/mo_def/arrange.ml @@ -34,7 +34,7 @@ let rec exp e = match e.it with (match t with None -> Atom "_" | Some t -> typ t); exp e' ] - | CallE (e1, ts, e2) -> "CallE" $$ [exp e1] @ List.map typ ts @ [exp e2] + | CallE (e1, tsr, e2) -> "CallE" $$ [exp e1] @ List.map typ (!tsr) @ [exp e2] | BlockE ds -> "BlockE" $$ List.map dec ds | NotE e -> "NotE" $$ [exp e] | AndE (e1, e2) -> "AndE" $$ [exp e1; exp e2] diff --git a/src/mo_def/syntax.ml b/src/mo_def/syntax.ml index aeb2495ce67..bbc07407604 100644 --- a/src/mo_def/syntax.ml +++ b/src/mo_def/syntax.ml @@ -127,7 +127,7 @@ and exp' = | ArrayE of mut * exp list (* array *) | IdxE of exp * exp (* array indexing *) | FuncE of string * func_sort * typ_bind list * pat * typ option * exp (* function *) - | CallE of exp * typ list * exp (* function call *) + | CallE of exp * typ list ref * exp (* function call *) | BlockE of dec list (* block (with type after avoidance)*) | NotE of exp (* negation *) | AndE of exp * exp (* conjunction *) @@ -222,3 +222,17 @@ let string_of_lit = function | TextLit t -> t | FloatLit f -> Value.Float.to_pretty_string f | PreLit _ -> assert false + + +let scope_id = "@" + +let scope_typ region = + Source.( + { it = PathT ( + { it = IdH { it = scope_id; at = region; note = () }; + at = no_region; + note = Type.Pre }, + []); + at = region; + note = Type.Pre }); + diff --git a/src/mo_frontend/parser.mly b/src/mo_frontend/parser.mly index 573c2680e84..1545888fbbf 100644 --- a/src/mo_frontend/parser.mly +++ b/src/mo_frontend/parser.mly @@ -93,6 +93,31 @@ let scope_id = "@" let scope_bind() = {var = scope_id @@ no_region; bound = PrimT "Any" @! no_region} @= no_region let scope_typ() = PathT ((IdH (scope_id @@ no_region)) @! no_region, []) @! no_region +let rec is_scope_typ t = + match t.it with + | PathT (p, []) -> + (match p.it with + | IdH id -> + id.it = scope_id + | _ -> false) + | ParT t -> is_scope_typ t + | _ -> false + +let funcT(sort, tbs, t1, t2) = + match tbs, t2.it with + | [], (AsyncT (t21, _)) when is_scope_typ t21 -> + FuncT(sort, [scope_bind()], t1, t2) + | _ -> FuncT(sort, tbs, t1, t2) + +let funcE (f, s, tbs, p, t_opt, e) = + match tbs, t_opt with + | [], Some t -> + (match t.it with + | AsyncT (t1, _) when is_scope_typ t1 -> + FuncE(f, s, [scope_bind()], p, t_opt, e) + | _ -> FuncE(f, s, tbs, p, t_opt, e)) + | _ -> FuncE(f, s, tbs, p, t_opt, e) + %} %token EOF @@ -260,7 +285,7 @@ typ : | t=typ_pre { t } | s=func_sort_opt tps=typ_params_opt t1=typ_un ARROW t2=typ - { FuncT(s, tps, t1, t2) @! at $sloc } + { funcT(s, tps, t1, t2) @! at $sloc } typ_item : | id COLON t=typ { t } @@ -277,7 +302,7 @@ typ_field : | mut=var_opt x=id COLON t=typ { {id = x; typ = t; mut} @@ at $sloc } | x=id tps=typ_params_opt t1=typ_nullary t2=return_typ - { let t = FuncT(Type.Local @@ no_region, tps, t1, t2) + { let t = funcT(Type.Local @@ no_region, tps, t1, t2) @! span x.at t2.at in {id = x; typ = t; mut = Const @@ no_region} @@ at $sloc } @@ -394,7 +419,7 @@ exp_post(B) : { DotE(e, x) @? at $sloc } | e1=exp_post(ob) tso=typ_args? e2=exp_nullary(ob) { let typ_args = Lib.Option.get tso [] in - CallE(e1, typ_args, e2) @? at $sloc } + CallE(e1, ref typ_args, e2) @? at $sloc } exp_un(B) : | e=exp_post(B) @@ -635,7 +660,7 @@ dec_nonvar : | _ -> e in let named, x = xf "func" $sloc in - let_or_exp named x (FuncE(x.it, s, tps, p, t, e)) (at $sloc) } + let_or_exp named x (funcE(x.it, s, tps, p, t, e)) (at $sloc) } | s=obj_sort_opt CLASS xf=typ_id_opt tps=typ_params_opt p=pat_param t=return_typ? cb=class_body { let x, efs = cb in diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 3625c568d6a..436001d66ef 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -770,7 +770,8 @@ and infer_exp'' env exp : T.typ = let ts1 = match pat.it with TupP _ -> T.seq_of_tup t1 | _ -> [t1] in let tbs = List.map2 (fun c t -> {T.var = Con.name c; bound = T.close cs t}) cs ts in T.Func (sort.it, T.map_control (T.close cs) c, tbs, List.map (T.close cs) ts1, List.map (T.close cs) ts2) - | CallE (exp1, insts, exp2) -> + | CallE (exp1, insts_ref, exp2) -> + let insts = !insts_ref in let t1 = infer_exp_promote env exp1 in let sort, tbs, t_arg, t_ret = try T.as_func_sub T.Local (List.length insts) t1 @@ -779,6 +780,12 @@ and infer_exp'' env exp : T.typ = "expected function type, but expression produces type\n %s" (T.string_of_typ_expand t1) in + let insts = match insts, t1 with + | [], T.Func(_,T.Promises (T.Var (_,0)),[_],_,_) -> + [Syntax.scope_typ {left=exp1.at.right; right = exp2.at.left}] + | _ -> insts + in + insts_ref := insts; let ts = check_inst_bounds env tbs insts exp.at in let t_arg = T.open_ ts t_arg in let t_ret = T.open_ ts t_ret in From 1ef98e3d85935385bae2d1102480e197d03dbd5a Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 27 Nov 2019 11:06:47 +0100 Subject: [PATCH 0718/1176] Drop support for the M1 client (#936) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Drop support for the M1 client and no longer depend on `dvm` or the `dev` repo. so much work goes down the drain… fake orthogonal persistence… trying hard to avoid boxing and unboxing references… the `ElemTable`… support for the DFINITY-specific custom sections. 800 lines of dense code. But yay, finally nothing is using `dvm` any more, or importing stuff from https://github.com/dfinity-lab/dev! So we only need that repo to read about how the Nix cache works in the README… The main feature that we cannot test any more now are non-top-level shared functions. But most aspects of that code are still present in some form, and can be re-arranged later. * A bit more cleanup --- Building.md | 1 - default.nix | 10 - guide/as-slides.md | 2 +- samples/app/Makefile | 7 +- src/codegen/compile.ml | 800 ++-------------------------- src/exes/moc.ml | 3 - src/js/mo_js.ml | 1 - src/linking/linkModule.ml | 35 +- src/mo_config/flags.ml | 2 +- src/mo_frontend/typing.ml | 1 - src/wasm-exts/customModule.ml | 7 - src/wasm-exts/customModuleDecode.ml | 2 - src/wasm-exts/customModuleEncode.ml | 47 -- stdlib/Makefile | 10 +- test/dvm.sh | 37 -- test/repl/type-lub-repl.sh | 2 +- test/run-drun/oom.mo | 4 - test/run-drun/selftail.mo | 4 +- test/run-drun/tailpositions.mo | 2 +- test/run.sh | 13 +- 20 files changed, 77 insertions(+), 913 deletions(-) delete mode 100755 test/dvm.sh diff --git a/Building.md b/Building.md index d2989684d0b..62d7aad8b57 100644 --- a/Building.md +++ b/Building.md @@ -52,7 +52,6 @@ installing all required tools without nix is out of scope). nix-env -i -f . -A wasmtime nix-env -i -f . -A filecheck nix-env -i -f . -A wabt - nix-env -i -f . -A dvm nix-env -i -f . -A drun nix-env -i -f . -A ic-stub ``` diff --git a/default.nix b/default.nix index 489e3f94097..6343844a83e 100644 --- a/default.nix +++ b/default.nix @@ -16,13 +16,6 @@ let stdenv = nixpkgs.stdenv; in let subpath = p: import ./nix/gitSource.nix p; in -let dev = import (builtins.fetchGit { - name = "dev-sources"; - url = "ssh://git@github.com/dfinity-lab/dev"; - # ref = "master"; - rev = "6fca1936fcd027aaeaccab0beb51defeee38a0ff"; -}) { inherit (nixpkgs) system; }; in - let dfinity-repo = import (builtins.fetchGit { name = "dfinity-sources"; url = "ssh://git@github.com/dfinity-lab/dfinity"; @@ -42,7 +35,6 @@ let esm = builtins.fetchTarball { url = "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz"; }; in -let dvm = dev.dvm; in let drun = dfinity-repo.drun or dfinity-repo.dfinity.drun; in let js-user-library = sdk.js-user-library; in @@ -215,7 +207,6 @@ rec { nixpkgs.nodejs-10_x filecheck js-user-library - dvm drun wasmtime haskellPackages.qc-motoko @@ -318,7 +309,6 @@ rec { ''; }; - inherit dvm; inherit drun; filecheck = nixpkgs.linkFarm "FileCheck" [ { name = "bin/FileCheck"; path = "${nixpkgs.llvm}/bin/FileCheck";} ]; diff --git a/guide/as-slides.md b/guide/as-slides.md index 8e5ebd39f18..b1ba4d70921 100644 --- a/guide/as-slides.md +++ b/guide/as-slides.md @@ -56,7 +56,7 @@ Inspirations: Java(Script), C#, Swift, Pony, ML, Haskell ### Status * great team! -* interpreter/compiler up and running via `dvm`. +* interpreter/compiler up and running via `drun`. * compiles multiple files by concatenation (good enough for the Produce Exchange) * documentation (see [draft](motoko-guide.pdf), 30 pages) diff --git a/samples/app/Makefile b/samples/app/Makefile index dfbc817f364..9bdb3d25bc6 100644 --- a/samples/app/Makefile +++ b/samples/app/Makefile @@ -3,7 +3,6 @@ # This works with bash MOC?=../../src/moc -DVM?=../../test/dvm.sh # we need to specify the output if there is more than one .mo file OUT=main.wasm LIB=list.mo types.mo server.mo client.mo @@ -12,12 +11,8 @@ SAMPLES:= test all: rm -f main.txt - $(MOC) -ancient-system-api -r -t -v main.mo >main.txt 2>&1 + $(MOC) -stub-system-api -r -t -v main.mo >main.txt 2>&1 cat main.txt -dvm: - $(MOC) -ancient-system-api -o $(OUT) main.mo - $(DVM) $(OUT) - clean: rm -f $(OUT) main.txt diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 649a6d000b9..cbccabd280a 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -47,7 +47,7 @@ module SR = struct *) type static_thing = | StaticFun of int32 - | StaticMessage of int32 (* anonymous message, only on ancient *) + | StaticMessage of int32 (* anonymous message, only temporary *) | PublicMethod of int32 * string (* Value representation on the stack: @@ -61,7 +61,6 @@ module SR = struct | UnboxedTuple of int | UnboxedWord64 | UnboxedWord32 - | UnboxedReference | Unreachable | StaticThing of static_thing @@ -148,11 +147,9 @@ module E = struct func_imports : import list ref; other_imports : import list ref; exports : export list ref; - dfinity_types : (int32 * Wasm_exts.CustomModule.type_ list) list ref; (* Dfinity types of exports *) funcs : (func * string * local_names) Lib.Promise.t list ref; globals : (global * string) list ref; global_names : int32 NameEnv.t ref; - persist : (int32 * Wasm_exts.CustomModule.type_) list ref; built_in_funcs : lazy_built_in NameEnv.t ref; static_strings : int32 StringEnv.t ref; end_of_static_memory : int32 ref; (* End of statically allocated memory *) @@ -183,11 +180,9 @@ module E = struct func_imports = ref []; other_imports = ref []; exports = ref []; - dfinity_types = ref []; funcs = ref []; globals = ref []; global_names = ref NameEnv.empty; - persist = ref []; built_in_funcs = ref NameEnv.empty; static_strings = ref StringEnv.empty; end_of_static_memory = ref dyn_mem; @@ -231,11 +226,6 @@ module E = struct let add_export (env : t) e = ignore (reg env.exports e) - let add_dfinity_type (env : t) e = - assert (mode env = Flags.AncientMode); - (* ignore duplicates? or use a map? but who cares, is for ancient system only *) - ignore (reg env.dfinity_types e) - let add_global (env : t) name g = assert (not (NameEnv.mem name !(env.global_names))); let gi = reg env.globals (g, name) in @@ -271,11 +261,6 @@ module E = struct let get_globals (env : t) = List.map (fun (g,n) -> g) !(env.globals) - let persist (env : t) i t = - env.persist := !(env.persist) @ [(i, t)] - - let get_persist (env : t) = !(env.persist) - let reserve_fun (env : t) name = let (j, fill) = reserve_promise env.funcs name in let n = Int32.of_int (List.length !(env.func_imports)) in @@ -317,7 +302,6 @@ module E = struct let get_func_imports (env : t) = !(env.func_imports) let get_other_imports (env : t) = !(env.other_imports) let get_exports (env : t) = !(env.exports) - let get_dfinity_types (env : t) = !(env.dfinity_types) let get_funcs (env : t) = List.map Lib.Promise.value !(env.funcs) let func_type (env : t) ty = @@ -866,75 +850,10 @@ module Stack = struct end (* Stack *) -module ElemHeap = struct - (* The ElemHeap adds a level of indirection for references (elements, as in - ElemRef). This way, the fake orthogonal persistence code can easily - store all references an elembuf. - - This could be done differently (e.g. traversing the heap and looking for - tagged references), but it predates the heap traversal code, and the whole - thing goes away once we target orthogonal persistence anyways. - *) - - let register_globals env = - assert (E.mode env = Flags.AncientMode); - (* reference counter *) - E.add_global32 env "refcounter" Mutable 0l - let get_ref_ctr env = - G.i (GlobalGet (nr (E.get_global env "refcounter"))) - let set_ref_ctr env = - G.i (GlobalSet (nr (E.get_global env "refcounter"))) - - (* For now, we allocate a fixed size range. This obviously cannot stay. *) - let max_references = 1024l - - let ref_location = Stack.end_of_stack - - let table_end : int32 = Int32.(add ref_location (mul max_references Heap.word_size)) - - (* Assumes a reference on the stack, and replaces it with an index into the - reference table *) - let remember_reference env : G.t = - assert (E.mode env = Flags.AncientMode); - Func.share_code1 env "remember_reference" ("ref", I32Type) [I32Type] (fun env get_ref -> - (* Check table space *) - get_ref_ctr env ^^ - compile_unboxed_const max_references ^^ - G.i (Compare (Wasm.Values.I32 I64Op.LtU)) ^^ - E.else_trap_with env "Reference table full" ^^ - - (* Return index *) - get_ref_ctr env ^^ - - (* Store reference *) - get_ref_ctr env ^^ - compile_mul_const Heap.word_size ^^ - compile_add_const ref_location ^^ - get_ref ^^ - store_unskewed_ptr ^^ - - (* Bump counter *) - get_ref_ctr env ^^ - compile_add_const 1l ^^ - set_ref_ctr env - ) - - (* Assumes a index into the table on the stack, and replaces it with the reference *) - let recall_reference env : G.t = - assert (E.mode env = Flags.AncientMode); - Func.share_code1 env "recall_reference" ("ref_idx", I32Type) [I32Type] (fun env get_ref_idx -> - get_ref_idx ^^ - compile_mul_const Heap.word_size ^^ - compile_add_const ref_location ^^ - load_unskewed_ptr - ) - -end (* ElemHeap *) - module ClosureTable = struct (* Another fixed-size table at the beginning of memory: When we create a closure - that is bound to a funcref that we pass out, we need this level of indirection for + that is bound to a callback that we pass out, we need this level of indirection for two reasons: - we cannot just bind the address via i32.bind, because that is not stable, due to our moving GC, and @@ -945,7 +864,7 @@ module ClosureTable = struct *) let max_entries = 1024l - let loc = ElemHeap.table_end + let loc = Stack.end_of_stack let table_end = Int32.(add loc (mul max_entries Heap.word_size)) (* For reasons I do not recall, we use the first word of the table as the counter, @@ -1088,7 +1007,6 @@ module Tagged = struct | Object | ObjInd (* The indirection used for object fields *) | Array (* Also a tuple *) - | Reference (* Either arrayref or funcref, no need to distinguish here *) | Int (* Contains a 64 bit number *) | MutBox (* used for mutable heap-allocated variables *) | Closure @@ -1104,7 +1022,6 @@ module Tagged = struct | Object -> 1l | ObjInd -> 2l | Array -> 3l - | Reference -> 4l | Int -> 5l | MutBox -> 6l | Closure -> 7l @@ -3031,9 +2948,6 @@ end (* Tuple *) module Dfinity = struct (* Dfinity-specific stuff: System imports, databufs etc. *) - let set_reply_cont env = G.i (GlobalSet (nr (E.get_global env "reply_cont"))) - let get_reply_cont env = G.i (GlobalGet (nr (E.get_global env "reply_cont"))) - let system_imports env = let i32s n = Lib.List.make n I32Type in match E.mode env with @@ -3062,47 +2976,13 @@ module Dfinity = struct E.add_func_import env "stub" "created_canister_id_size" (i32s 1) [I32Type]; E.add_func_import env "stub" "created_canister_id_copy" (i32s 4) []; () - | Flags.AncientMode -> - E.add_func_import env "test" "print" [I32Type] []; - E.add_func_import env "test" "show_i32" [I32Type] [I32Type]; - E.add_func_import env "data" "externalize" [I32Type; I32Type] [I32Type]; - E.add_func_import env "data" "internalize" [I32Type; I32Type; I32Type; I32Type] []; - E.add_func_import env "data" "length" [I32Type] [I32Type]; - E.add_func_import env "elem" "externalize" [I32Type; I32Type] [I32Type]; - E.add_func_import env "elem" "internalize" [I32Type; I32Type; I32Type; I32Type] []; - E.add_func_import env "elem" "length" [I32Type] [I32Type]; - E.add_func_import env "module" "new" [I32Type] [I32Type]; - E.add_func_import env "actor" "new" [I32Type] [I32Type]; - E.add_func_import env "actor" "self" [] [I32Type]; - E.add_func_import env "actor" "export" [I32Type; I32Type] [I32Type]; - E.add_func_import env "func" "internalize" [I32Type; I32Type] []; - E.add_func_import env "func" "externalize" [I32Type] [I32Type]; - E.add_func_import env "func" "bind_i32" [I32Type; I32Type] [I32Type]; - E.add_func_import env "func" "bind_ref" [I32Type; I32Type] [I32Type] | Flags.WASIMode -> E.add_func_import env "wasi_unstable" "fd_write" [I32Type; I32Type; I32Type; I32Type] [I32Type]; | Flags.WasmMode -> () let system_call env modname funcname = E.call_import env modname funcname - let compile_databuf_of_text env = - Func.share_code1 env "databuf_of_text" ("string", I32Type) [I32Type] (fun env get_string -> - (* Calculate the offset *) - get_string ^^ - compile_add_const Int32.(add (mul Heap.word_size Blob.header_size) ptr_unskew) ^^ - - (* Calculate the length *) - get_string ^^ - Heap.load_field (Blob.len_field) ^^ - - (* Externalize *) - system_call env "data" "externalize" - ) - - let compile_databuf_of_bytes env (bytes : string) = - Blob.lit env bytes ^^ compile_databuf_of_text env - - let rec print_ptr_len env = + let print_ptr_len env = match E.mode env with | Flags.WasmMode -> G.i Drop ^^ G.i Drop | Flags.ICMode -> system_call env "debug" "print" @@ -3150,39 +3030,13 @@ module Dfinity = struct G.i Drop ) ) - | Flags.AncientMode -> - Func.share_code2 env "print_ptr" (("ptr", I32Type), ("len", I32Type)) [] (fun env get_ptr get_len -> - let (set_blob, get_blob) = new_local env "blob" in - get_len ^^ Blob.alloc env ^^ set_blob ^^ - - get_blob ^^ Blob.payload_ptr_unskewed ^^ - get_ptr ^^ - get_len ^^ - Heap.memcpy env ^^ - - get_blob ^^ - print_text env - ) - and print_text env = - match E.mode env with - | Flags.AncientMode -> - (* The recursion goes the other wary in the AncientMode. - This can be removed once we get rid of the ancient mode - *) - Func.share_code1 env "print_text" ("str", I32Type) [] (fun env get_str -> - get_str ^^ - Blob.lit env "\n" ^^ - Blob.concat env ^^ - compile_databuf_of_text env ^^ - system_call env "test" "print" - ) - | _ -> - Func.share_code1 env "print_text" ("str", I32Type) [] (fun env get_str -> - get_str ^^ Blob.payload_ptr_unskewed ^^ - get_str ^^ Heap.load_field (Blob.len_field) ^^ - print_ptr_len env - ) + let print_text env = + Func.share_code1 env "print_text" ("str", I32Type) [] (fun env get_str -> + get_str ^^ Blob.payload_ptr_unskewed ^^ + get_str ^^ Heap.load_field (Blob.len_field) ^^ + print_ptr_len env + ) (* For debugging *) let compile_static_print env s = @@ -3209,7 +3063,7 @@ module Dfinity = struct let trap_with env s = match E.mode env with | Flags.WasmMode -> G.i Unreachable - | Flags.AncientMode | Flags.WASIMode -> compile_static_print env (s ^ "\n") ^^ G.i Unreachable + | Flags.WASIMode -> compile_static_print env (s ^ "\n") ^^ G.i Unreachable | Flags.ICMode | Flags.StubMode -> Blob.lit env s ^^ ic_trap_str env ^^ G.i Unreachable let default_exports env = @@ -3227,43 +3081,6 @@ module Dfinity = struct edesc = nr (TableExport (nr 0l)) }) - let register_reply env = - if E.mode env = Flags.AncientMode - then begin - (* in-canister emulation of the call context, in particular the “current reply” *) - Func.define_built_in env "empty_reply" ["databuf", I32Type; "elembuf", I32Type] [] - (fun env -> trap_with env "dummy_reply called"); - let fi = E.built_in env "empty_reply" in - E.add_dfinity_type env (fi, [ Wasm_exts.CustomModule.DataBuf; Wasm_exts.CustomModule.ElemBuf ]); - E.add_global32 env "reply_cont" Mutable 0l - end - - let set_dummy_reply env = - if E.mode env = Flags.AncientMode then - compile_unboxed_const (E.built_in env "empty_reply") ^^ - system_call env "func" "externalize" ^^ - set_reply_cont env - else G.nop - - let export_start_stub env = - assert (E.mode env = Flags.AncientMode); - let empty_f = Func.of_body env [] [] (fun env1 -> - (* Set initial reply continuation *) - set_dummy_reply env ^^ - (* Set up memory *) - G.i (Call (nr (E.built_in env1 "restore_mem"))) ^^ - (* Collect garbage *) - G.i (Call (nr (E.built_in env1 "collect"))) ^^ - (* Save memory *) - G.i (Call (nr (E.built_in env1 "save_mem"))) - ) in - let fi = E.add_fun env "start_stub" empty_f in - E.add_export env (nr { - name = Wasm.Utf8.decode "start"; - edesc = nr (FuncExport (nr fi)) - }); - E.add_dfinity_type env (fi, []) - let export_start env start_fi = assert (E.mode env = Flags.ICMode || E.mode env = Flags.StubMode); (* Create an empty message *) @@ -3278,24 +3095,8 @@ module Dfinity = struct edesc = nr (FuncExport (nr fi)) }) - let box_reference env = - assert (E.mode env = Flags.AncientMode); - Func.share_code1 env "box_reference" ("ref", I32Type) [I32Type] (fun env get_ref -> - Tagged.obj env Tagged.Reference [ - get_ref ^^ - ElemHeap.remember_reference env - ] - ) - - let unbox_reference env = - assert (E.mode env = Flags.AncientMode); - Heap.load_field 1l ^^ - ElemHeap.recall_reference env - let get_self_reference env = match E.mode env with - | Flags.ICMode -> - assert false | Flags.StubMode -> Func.share_code0 env "canister_self" [I32Type] (fun env -> let (set_len, get_len) = new_local env "len" in @@ -3311,15 +3112,9 @@ module Dfinity = struct get_blob ) - | Flags.AncientMode -> - system_call env "actor" "self" | _ -> assert false - let static_message_funcref env fi = - compile_unboxed_const fi ^^ - system_call env "func" "externalize" - let reject env arg_instrs = match E.mode env with | Flags.ICMode | Flags.StubMode -> @@ -3333,8 +3128,6 @@ module Dfinity = struct | Flags.StubMode -> system_call env "ic0" "msg_reject" | _ -> assert false end - | Flags.AncientMode -> - trap_with env "Explicit reject on ancient system" | _ -> assert false @@ -3360,21 +3153,9 @@ module Dfinity = struct | _ -> assert false ) - - (* References have special stack representation on the ancient platform, - but are just vanilla Blobs on the IC platform. *) - let reference_sr env = match E.mode env with - | Flags.AncientMode -> SR.UnboxedReference - | Flags.ICMode -> SR.Vanilla - | Flags.StubMode -> SR.Vanilla - | _ -> assert false - (* Actor reference on the stack *) let actor_public_field env name = match E.mode env with - | Flags.AncientMode -> - compile_databuf_of_bytes env name ^^ - system_call env "actor" "export" | Flags.ICMode | Flags.StubMode -> (* simply tuple canister name and function name *) Blob.lit env name ^^ @@ -3419,105 +3200,6 @@ module RTS_Exports = struct end (* RTS_Exports *) -module OrthogonalPersistence = struct - (* This module implements the code that fakes orthogonal persistence *) - - (* Strategy: - * There is a persistent global databuf called `datastore` - * Two helper functions are installed in each actor: restore_mem and save_mem. - (The don’t actually have names, just numbers, of course). - * Upon each message entry, call restore_mem. At the end, call save_mem. - * restore_mem checks if datastore is defined. - - If it is 0, then this is the first message ever received. - Run the actor’s start function (e.g. to initialize globals). - - If it is not 0, then load the databuf into memory, and set - the global with the end-of-memory pointer to the length. - * save_mem simply copies the whole dynamic memory (up to the end-of-memory - pointer) to a new databuf and stores that in datastore. - *) - - let register_globals env = - assert (E.mode env = Flags.AncientMode); - (* We want to put all persistent globals first: - The index in the persist annotation refers to the index in the - list of *exported* globals, not all globals (at least with v8/dvm) *) - E.add_global32 env "datastore" Mutable 0l; - E.add_global32 env "elemstore" Mutable 0l; - E.export_global env "datastore"; - E.export_global env "elemstore"; - E.persist env (E.get_global env "datastore") Wasm_exts.CustomModule.DataBuf; - E.persist env (E.get_global env "elemstore") Wasm_exts.CustomModule.ElemBuf - - let register env start_funid = - assert (E.mode env = Flags.AncientMode); - let mem_global = E.get_global env "datastore" in - let elem_global = E.get_global env "elemstore" in - - Func.define_built_in env "restore_mem" [] [] (fun env1 -> - let (set_i, get_i) = new_local env1 "len" in - G.i (GlobalGet (nr mem_global)) ^^ - Dfinity.system_call env1 "data" "length" ^^ - set_i ^^ - - get_i ^^ - compile_eq_const 0l ^^ - G.if_ (ValBlockType None) - (* First run, call the start function *) - ( G.i (Call (nr start_funid)) ) - - (* Subsequent run *) - ( (* Set heap pointer based on databuf length *) - get_i ^^ - compile_add_const ElemHeap.table_end ^^ - Heap.set_heap_ptr env ^^ - Heap.get_heap_ptr env ^^ Heap.grow_memory env ^^ - - (* Load memory *) - compile_unboxed_const ElemHeap.table_end ^^ - get_i ^^ - G.i (GlobalGet (nr mem_global)) ^^ - compile_unboxed_zero ^^ - Dfinity.system_call env1 "data" "internalize" ^^ - - (* Load reference counter *) - G.i (GlobalGet (nr elem_global)) ^^ - Dfinity.system_call env1 "elem" "length" ^^ - ElemHeap.set_ref_ctr env ^^ - - (* Load references *) - compile_unboxed_const ElemHeap.ref_location ^^ - ElemHeap.get_ref_ctr env ^^ - G.i (GlobalGet (nr elem_global)) ^^ - compile_unboxed_zero ^^ - Dfinity.system_call env1 "elem" "internalize" - ) - ); - Func.define_built_in env "save_mem" [] [] (fun env1 -> - (* Store memory *) - compile_unboxed_const ElemHeap.table_end ^^ - Heap.get_heap_ptr env ^^ - compile_unboxed_const ElemHeap.table_end ^^ - G.i (Binary (Wasm.Values.I32 I32Op.Sub)) ^^ - Dfinity.system_call env "data" "externalize" ^^ - G.i (GlobalSet (nr mem_global)) ^^ - - (* Store references *) - compile_unboxed_const ElemHeap.ref_location ^^ - ElemHeap.get_ref_ctr env ^^ - Dfinity.system_call env "elem" "externalize" ^^ - G.i (GlobalSet (nr elem_global)) - ) - - let save_mem env = - assert (E.mode env = Flags.AncientMode); - G.i (Call (nr (E.built_in env "save_mem"))) - - let restore_mem env = - assert (E.mode env = Flags.AncientMode); - G.i (Call (nr (E.built_in env "restore_mem"))) - -end (* OrthogonalPersistence *) - module HeapTraversal = struct (* Returns the object size (in words) *) let object_size env = @@ -3530,8 +3212,6 @@ module HeapTraversal = struct compile_unboxed_const 2l ; Tagged.BigInt, compile_unboxed_const 5l (* HeapTag + sizeof(mp_int) *) - ; Tagged.Reference, - compile_unboxed_const 2l ; Tagged.Some, compile_unboxed_const 2l ; Tagged.Variant, @@ -3707,8 +3387,8 @@ module Serialization = struct let raw_type env : Type.typ -> Type.typ = fun t -> let open Type in match normalize t with - | Obj (Actor, _) when E.mode env != Flags.AncientMode -> Prim Blob - | Func _ when E.mode env != Flags.AncientMode -> Tup [Prim Blob; Prim Text] + | Obj (Actor, _) -> Prim Blob + | Func _ -> Tup [Prim Blob; Prim Text] | t -> t @@ -3833,14 +3513,7 @@ module Serialization = struct add_idx f.typ ) (sort_by_hash fs) | Obj (Actor, fs) -> - assert (E.mode env = Flags.AncientMode); - add_sleb128 (-23); - add_leb128 (List.length fs); - List.iter (fun f -> - add_leb128 (String.length f.lab); - Buffer.add_string buf f.lab; - add_idx f.typ - ) fs + assert false; | Array t -> add_sleb128 (-19); add_idx t | Opt t -> @@ -3852,15 +3525,8 @@ module Serialization = struct add_leb128_32 h; add_idx f.typ ) (sort_by_hash vs) - | Func (s, c, tbs, ts1, ts2) -> - assert (Type.is_shared_sort s); - assert (E.mode env = Flags.AncientMode); - add_sleb128 (-22); - add_leb128 (List.length ts1); - List.iter add_idx ts1; - add_leb128 (List.length ts2); - List.iter add_idx ts2; - add_leb128 0 (* no annotations *) + | Func _ -> + assert false | _ -> assert false in Buffer.add_string buf "DIDL"; @@ -3889,9 +3555,6 @@ module Serialization = struct G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ set_data_size in - let inc_ref_size i = - get_ref_size ^^ compile_add_const i ^^ set_ref_size - in let size_word env code = let (set_word, get_word) = new_local env "word" in @@ -3954,8 +3617,7 @@ module Serialization = struct ( List.mapi (fun i (_h, f) -> (i,f)) (sort_by_hash vs) ) ( E.trap_with env "buffer_size: unexpected variant" ) | (Func _ | Obj (Actor, _)) -> - assert (E.mode env = Flags.AncientMode); - inc_ref_size 1l + assert false | Non -> E.trap_with env "buffer_size called on value of type None" | _ -> todo "buffer_size" (Arrange_ir.typ t) G.nop @@ -3978,8 +3640,6 @@ module Serialization = struct let advance_data_buf = get_data_buf ^^ G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ set_data_buf in - let advance_ref_buf = - get_ref_buf ^^ compile_add_const Heap.word_size ^^ set_ref_buf in let write_word code = let (set_word, get_word) = new_local env "word" in @@ -4093,11 +3753,7 @@ module Serialization = struct Heap.memcpy env ^^ get_len ^^ advance_data_buf | (Func _ | Obj (Actor, _)) -> - assert (E.mode env = Flags.AncientMode); - get_ref_buf ^^ - get_x ^^ Dfinity.unbox_reference env ^^ - store_unskewed_ptr ^^ - advance_ref_buf + assert false | Non -> E.trap_with env "serializing value of type None" | _ -> todo "serialize" (Arrange_ir.typ t) G.nop @@ -4360,9 +4016,7 @@ module Serialization = struct ( E.trap_with env "IDL error: unexpected variant tag" ) ) | (Func _ | Obj (Actor, _)) -> - assert (E.mode env = Flags.AncientMode); - ReadBuf.read_word32 env get_ref_buf ^^ - Dfinity.box_reference env + assert false; | Non -> E.trap_with env "IDL error: deserializing value of type None" | _ -> todo_trap env "deserialize" (Arrange_ir.typ t) @@ -4394,9 +4048,7 @@ module Serialization = struct let serialize env ts : G.t = let ts_name = String.concat "," (List.map typ_id ts) in let name = "@serialize<" ^ ts_name ^ ">" in - (* On ancient API returns databuf/elembuf, - On IC API returns data/length pointers (will be GC next time!) - *) + (* returns data/length pointers (will be GC’ed next time!) *) Func.share_code1 env name ("x", I32Type) [I32Type; I32Type] (fun env get_x -> let (set_data_size, get_data_size) = new_local env "data_size" in let (set_refs_size, get_refs_size) = new_local env "refs_size" in @@ -4440,14 +4092,6 @@ module Serialization = struct E.else_trap_with env "data buffer not filled " ^^ match E.mode env with - | Flags.AncientMode -> - (* Store it all in a databuf and an elembuf *) - get_data_start ^^ get_data_size ^^ - Dfinity.system_call env "data" "externalize" ^^ - - get_refs_start ^^ get_refs_size ^^ - Dfinity.system_call env "elem" "externalize" - | Flags.ICMode | Flags.StubMode -> get_refs_size ^^ compile_unboxed_const 0l ^^ @@ -4462,42 +4106,20 @@ module Serialization = struct let deserialize env ts = let ts_name = String.concat "," (List.map typ_id ts) in let name = "@deserialize<" ^ ts_name ^ ">" in - let args = match E.mode env with - | Flags.ICMode | Flags.StubMode -> [] - | _ -> [("databuf",I32Type);("elembuf", I32Type)] in - Func.share_code env name args (List.map (fun _ -> I32Type) ts) (fun env -> + Func.share_code env name [] (List.map (fun _ -> I32Type) ts) (fun env -> let (set_data_size, get_data_size) = new_local env "data_size" in let (set_refs_size, get_refs_size) = new_local env "refs_size" in let (set_data_start, get_data_start) = new_local env "data_start" in let (set_refs_start, get_refs_start) = new_local env "refs_start" in let (set_arg_count, get_arg_count) = new_local env "arg_count" in - begin match E.mode env with - | Flags.AncientMode -> - let get_databuf = G.i (LocalGet (nr 0l)) in - let get_elembuf = G.i (LocalGet (nr 1l)) in - - (* Allocate space for the data buffer and copy it *) - get_databuf ^^ Dfinity.system_call env "data" "length" ^^ set_data_size ^^ - get_data_size ^^ Blob.dyn_alloc_scratch env ^^ set_data_start ^^ - get_data_start ^^ get_data_size ^^ get_databuf ^^ compile_unboxed_const 0l ^^ - Dfinity.system_call env "data" "internalize" ^^ - - (* Allocate space for the reference buffer and copy it *) - get_elembuf ^^ Dfinity.system_call env "elem" "length" ^^ set_refs_size ^^ - get_refs_size ^^ compile_mul_const Heap.word_size ^^ Blob.dyn_alloc_scratch env ^^ set_refs_start ^^ - get_refs_start ^^ get_refs_size ^^ get_elembuf ^^ compile_unboxed_const 0l ^^ - Dfinity.system_call env "elem" "internalize" - | Flags.ICMode | Flags.StubMode -> - (* Allocate space for the data buffer and copy it *) - argument_data_size env ^^ set_data_size ^^ - get_data_size ^^ Blob.dyn_alloc_scratch env ^^ set_data_start ^^ - argument_data_copy env get_data_start get_data_size ^^ + (* Allocate space for the data buffer and copy it *) + argument_data_size env ^^ set_data_size ^^ + get_data_size ^^ Blob.dyn_alloc_scratch env ^^ set_data_start ^^ + argument_data_copy env get_data_start get_data_size ^^ - (* Allocate space for the reference buffer and copy it *) - compile_unboxed_const 0l ^^ set_refs_size (* none yet *) - | _ -> assert false - end ^^ + (* Allocate space for the reference buffer and copy it *) + compile_unboxed_const 0l ^^ set_refs_size (* none yet *) ^^ (* Allocate space for out parameters of parse_idl_header *) Stack.with_words env "get_typtbl_ptr" 1l (fun get_typtbl_ptr -> @@ -4554,7 +4176,7 @@ module GC = struct Roots are: * All objects in the static part of the memory. - * all closures ever bound to a `funcref`. + * all closures ever passed out as callback or to async_method These therefore need to live in a separate area of memory (could be mutable array of pointers, similar to the reference table) *) @@ -4805,7 +4427,6 @@ module StackRep = struct | Vanilla -> ValBlockType (Some I32Type) | UnboxedWord64 -> ValBlockType (Some I64Type) | UnboxedWord32 -> ValBlockType (Some I32Type) - | UnboxedReference -> ValBlockType (Some I32Type) | UnboxedTuple 0 -> ValBlockType None | UnboxedTuple 1 -> ValBlockType (Some I32Type) | UnboxedTuple n when not !Flags.multi_value -> assert false @@ -4817,7 +4438,6 @@ module StackRep = struct | Vanilla -> "Vanilla" | UnboxedWord64 -> "UnboxedWord64" | UnboxedWord32 -> "UnboxedWord32" - | UnboxedReference -> "UnboxedReference" | UnboxedTuple n -> Printf.sprintf "UnboxedTuple %d" n | Unreachable -> "Unreachable" | StaticThing _ -> "StaticThing" @@ -4827,7 +4447,6 @@ module StackRep = struct | Unreachable, sr2 -> sr2 | sr1, Unreachable -> sr1 | UnboxedWord64, UnboxedWord64 -> UnboxedWord64 - | UnboxedReference, UnboxedReference -> UnboxedReference | UnboxedTuple n, UnboxedTuple m when n = m -> sr1 | _, Vanilla -> Vanilla | Vanilla, _ -> Vanilla @@ -4850,18 +4469,10 @@ module StackRep = struct | Vanilla -> G.i Drop | UnboxedWord64 -> G.i Drop | UnboxedWord32 -> G.i Drop - | UnboxedReference -> G.i Drop | UnboxedTuple n -> G.table n (fun _ -> G.i Drop) | StaticThing _ -> G.nop | Unreachable -> G.nop - let materialize_unboxed_ref env = function - | StaticFun fi -> - assert false - | StaticMessage fi | PublicMethod (fi, _) -> - assert (E.mode env = Flags.AncientMode); - Dfinity.static_message_funcref env fi - let materialize env = function | StaticFun fi -> (* When accessing a variable that is a static function, then we need to @@ -4870,9 +4481,6 @@ module StackRep = struct compile_unboxed_const fi; compile_unboxed_zero (* number of parameters: none *) ] - | (StaticMessage fi | PublicMethod (fi, _)) when E.mode env = Flags.AncientMode -> - Dfinity.static_message_funcref env fi ^^ - Dfinity.box_reference env | StaticMessage fi -> assert false | PublicMethod (_, name) -> @@ -4895,11 +4503,7 @@ module StackRep = struct | UnboxedWord32, Vanilla -> BoxedSmallWord.box env | Vanilla, UnboxedWord32 -> BoxedSmallWord.unbox env - | UnboxedReference, Vanilla -> Dfinity.box_reference env - | Vanilla, UnboxedReference -> Dfinity.unbox_reference env - | StaticThing s, Vanilla -> materialize env s - | StaticThing s, UnboxedReference -> materialize_unboxed_ref env s | StaticThing s, UnboxedTuple 0 -> G.nop | _, _ -> @@ -5073,38 +4677,6 @@ end (* Var *) (* This comes late because it also deals with messages *) module FuncDec = struct - (* We use the first table slot for calls to funcrefs *) - (* This does not clash with slots for our functions as long as there - is at least one imported function (which we do not add to the table) *) - let tmp_table_slot = 0l - - (* The type of messages (no return: one-shot, callbacks) *) - let message_ty env = - E.func_type env (FuncType ([I32Type; I32Type], [])) - - (* Expects databuf and elembuf on the stack, in serialized form. *) - let call_message_funcref env get_ref = - compile_unboxed_const tmp_table_slot ^^ (* slot number *) - get_ref ^^ (* the unboxed funcref *) - Dfinity.system_call env "func" "internalize" ^^ - - compile_unboxed_const tmp_table_slot ^^ - G.i (CallIndirect (nr (message_ty env))) - - (* The type of messages (with return: expect a callback as the first argument *) - let call_ty env = - E.func_type env (FuncType ([I32Type; I32Type; I32Type], [])) - - - (* Expects reply callback funcref, databuf and elembuf on the stack, in serialized form. *) - let call_await_funcref env get_ref = - compile_unboxed_const tmp_table_slot ^^ (* slot number *) - get_ref ^^ (* the unboxed funcref *) - Dfinity.system_call env "func" "internalize" ^^ - - compile_unboxed_const tmp_table_slot ^^ - G.i (CallIndirect (nr (call_ty env))) - let bind_args ae0 first_arg as_ bind_arg = let rec go i ae = function | [] -> ae @@ -5137,147 +4709,12 @@ module FuncDec = struct )) let message_cleanup env sort = match sort with - | Type.Shared Type.Write -> - (* Collect garbage *) - G.i (Call (nr (E.built_in env "collect"))) ^^ - (* Save memory *) - if E.mode env = Flags.AncientMode - then OrthogonalPersistence.save_mem env - else G.nop - | Type.Shared Type.Query -> - (* Don't collect or persist *) - G.i Nop + | Type.Shared Type.Write -> G.i (Call (nr (E.built_in env "collect"))) + | Type.Shared Type.Query -> G.i Nop | _ -> assert false - (* Similar, but for shared functions aka messages. Differences are: - - The closure is actually an index into the closure table - - The arguments need to be deserialized. - - The return value ought to be discarded - - We need to register the type in the custom types section - - Do GC at the end - - Fake orthogonal persistence - *) - let compile_message outer_env outer_ae sort control restore_env args mk_body ret_tys at = - assert (E.mode outer_env = Flags.AncientMode); - assert (List.length ret_tys = 0); - let ae0 = VarEnv.mk_fun_ae outer_ae in - match control with - | Type.Returns -> - Func.of_body outer_env ["clos", I32Type; "databuf", I32Type; "elembuf", I32Type] [] (fun env -> G.with_region at ( - let get_databuf = G.i (LocalGet (nr 1l)) in - let get_elembuf = G.i (LocalGet (nr 2l)) in - - (* Restore memory *) - OrthogonalPersistence.restore_mem env ^^ - - (* Set initial dummy continuation *) - Dfinity.set_dummy_reply env ^^ - - (* Look up closure *) - let (set_closure, get_closure) = new_local env "closure" in - G.i (LocalGet (nr 0l)) ^^ - ClosureTable.recall_closure env ^^ - set_closure ^^ - - let (ae1, closure_code) = restore_env env ae0 get_closure in - - (* Deserialize argument and add params to the environment *) - let arg_names = List.map (fun a -> a.it) args in - let arg_tys = List.map (fun a -> a.note) args in - let (ae2, setters) = VarEnv.add_argument_locals env ae1 arg_names in - get_databuf ^^ get_elembuf ^^ - Serialization.deserialize env arg_tys ^^ - G.concat (List.rev setters) ^^ - - closure_code ^^ - mk_body env ae2 ^^ - message_cleanup env sort - )) - | Type.Promises -> assert false - | Type.Replies -> - Func.of_body outer_env ["clos", I32Type; "reply", I32Type; "databuf", I32Type; "elembuf", I32Type] [] (fun env -> G.with_region at ( - let get_reply = G.i (LocalGet (nr 1l)) in - let get_databuf = G.i (LocalGet (nr 2l)) in - let get_elembuf = G.i (LocalGet (nr 3l)) in - - (* Restore memory *) - OrthogonalPersistence.restore_mem env ^^ - - (* Story reply contiuation *) - get_reply ^^ Dfinity.set_reply_cont env ^^ - - (* Look up closure *) - let (set_closure, get_closure) = new_local env "closure" in - G.i (LocalGet (nr 0l)) ^^ - ClosureTable.recall_closure env ^^ - set_closure ^^ - - let (ae1, closure_code) = restore_env env ae0 get_closure in - - (* Deserialize argument and add params to the environment *) - let arg_names = List.map (fun a -> a.it) args in - let arg_tys = List.map (fun a -> a.note) args in - let (ae2, setters) = VarEnv.add_argument_locals env ae1 arg_names in - get_databuf ^^ get_elembuf ^^ - Serialization.deserialize env arg_tys ^^ - G.concat (List.rev setters) ^^ - - closure_code ^^ - mk_body env ae2 ^^ - message_cleanup env sort - )) - let compile_static_message outer_env outer_ae sort control args mk_body ret_tys at : E.func_with_names = match E.mode outer_env, control with - | Flags.AncientMode, Type.Returns -> (* no callback *) - assert (List.length ret_tys = 0); - let ae0 = VarEnv.mk_fun_ae outer_ae in - Func.of_body outer_env ["databuf", I32Type; "elembuf", I32Type] [] (fun env -> G.with_region at ( - let get_databuf = G.i (LocalGet (nr 0l)) in - let get_elembuf = G.i (LocalGet (nr 1l)) in - - (* Set up memory *) - OrthogonalPersistence.restore_mem env ^^ - - (* Set initial dummy continuation *) - Dfinity.set_dummy_reply env ^^ - - (* Deserialize argument and add params to the environment *) - let arg_names = List.map (fun a -> a.it) args in - let arg_tys = List.map (fun a -> a.note) args in - let (ae1, setters) = VarEnv.add_argument_locals env ae0 arg_names in - get_databuf ^^ get_elembuf ^^ - Serialization.deserialize env arg_tys ^^ - G.concat (List.rev setters) ^^ - - mk_body env ae1 ^^ - message_cleanup env sort - )) - | Flags.AncientMode, Type.Promises -> assert false - | Flags.AncientMode, Type.Replies -> (* with callbacks *) - let ae0 = VarEnv.mk_fun_ae outer_ae in - Func.of_body outer_env ["reply", I32Type; "databuf", I32Type; "elembuf", I32Type] [] (fun env -> G.with_region at ( - let get_reply = G.i (LocalGet (nr 0l)) in - let get_databuf = G.i (LocalGet (nr 1l)) in - let get_elembuf = G.i (LocalGet (nr 2l)) in - - (* Set up memory *) - OrthogonalPersistence.restore_mem env ^^ - - (* Story reply contiuation *) - get_reply ^^ Dfinity.set_reply_cont env ^^ - - (* Deserialize argument and add params to the environment *) - let arg_names = List.map (fun a -> a.it) args in - let arg_tys = List.map (fun a -> a.note) args in - let (ae1, setters) = VarEnv.add_argument_locals env ae0 arg_names in - get_databuf ^^ get_elembuf ^^ - Serialization.deserialize env arg_tys ^^ - G.concat (List.rev setters) ^^ - - mk_body env ae1 ^^ - message_cleanup env sort - )) | Flags.ICMode, _ -> let ae0 = VarEnv.mk_fun_ae outer_ae in Func.of_body outer_env [] [] (fun env -> G.with_region at ( @@ -5311,20 +4748,11 @@ module FuncDec = struct )) | (Flags.WasmMode | Flags.WASIMode), _ -> assert false - let declare_dfinity_type env has_closure has_reply fi = - if E.mode env = Flags.AncientMode then - E.add_dfinity_type env (fi, - (if has_closure then [ Wasm_exts.CustomModule.I32 ] else []) @ - (if has_reply then [ Wasm_exts.CustomModule.FuncRef ] else []) @ - [ Wasm_exts.CustomModule.DataBuf; Wasm_exts.CustomModule.ElemBuf ] - ) - (* Compile a closed function declaration (captures no local variables) *) let closed pre_env sort control name args mk_body ret_tys at = let (fi, fill) = E.reserve_fun pre_env name in if Type.is_shared_sort sort then begin - declare_dfinity_type pre_env false (control <> Type.Returns) fi ; ( SR.StaticMessage fi, fun env ae -> fill (compile_static_message env ae sort control args mk_body ret_tys at) ) @@ -5369,12 +4797,10 @@ module FuncDec = struct let f = if is_local then compile_local_function env ae restore_env args mk_body ret_tys at - else compile_message env ae sort control restore_env args mk_body ret_tys at in + else assert false (* no first class shared functions yet *) in let fi = E.add_fun env name f in - if not is_local then declare_dfinity_type env true (control <> Type.Returns) fi; - let code = (* Allocate a heap object for the closure *) Heap.alloc env (Int32.add Closure.header_size len) ^^ @@ -5398,22 +4824,12 @@ module FuncDec = struct store_env in - (* Possibly turn into a funcref *) if is_local then SR.Vanilla, code ^^ get_clos - else begin - assert (E.mode env = Flags.AncientMode); - SR.UnboxedReference, - code ^^ - compile_unboxed_const fi ^^ - Dfinity.system_call env "func" "externalize" ^^ - get_clos ^^ - ClosureTable.remember_closure env ^^ - Dfinity.system_call env "func" "bind_i32" - end + else assert false (* no first class shared functions *) let lit env ae name sort control free_vars args mk_body ret_tys at = @@ -5434,48 +4850,6 @@ module FuncDec = struct StackRep.adjust env sr SR.Vanilla ^^ ClosureTable.remember_closure env - - (* Wraps a local closure in a shared function that does serialization and - takes care of the reply global *) - (* Need this function once per type, so we can share based on ts *) - let callback_to_funcref env ts get_closure = - assert (E.mode env = Flags.AncientMode); - let name = "@callback<" ^ Serialization.typ_id (Type.Tup ts) ^ ">" in - Func.define_built_in env name ["clos", I32Type; "reply", I32Type; "databuf", I32Type; "elembuf", I32Type] [] (fun env -> - let get_reply = G.i (LocalGet (nr 1l)) in - let get_databuf = G.i (LocalGet (nr 2l)) in - let get_elembuf = G.i (LocalGet (nr 3l)) in - - (* Restore memory *) - OrthogonalPersistence.restore_mem env ^^ - - (* Story reply contiuation *) - get_reply ^^ Dfinity.set_reply_cont env ^^ - - (* Look up closure *) - let (set_closure, get_closure) = new_local env "closure" in - G.i (LocalGet (nr 0l)) ^^ - ClosureTable.recall_closure env ^^ (* At this point we can remove the closure *) - set_closure ^^ - get_closure ^^ - - (* Deserialize arguments *) - get_databuf ^^ get_elembuf ^^ - Serialization.deserialize env ts ^^ - - get_closure ^^ - Closure.call_closure env (List.length ts) 0 ^^ - - message_cleanup env (Type.Shared Type.Write) - ); - declare_dfinity_type env true true (E.built_in env name); - compile_unboxed_const (E.built_in env name) ^^ - Dfinity.system_call env "func" "externalize" ^^ - get_closure ^^ ClosureTable.remember_closure env ^^ - Dfinity.system_call env "func" "bind_i32" ^^ - Dfinity.get_reply_cont env ^^ - Dfinity.system_call env "func" "bind_ref" - (* Wraps a local closure in a local function that does serialization and takes care of the environment *) (* Need this function once per type, so we can share based on ts *) @@ -5529,14 +4903,14 @@ module FuncDec = struct Func.define_built_in env name ["env", I32Type] [] (fun env -> G.nop); compile_unboxed_const (E.built_in env name) - let ic_call env ts1 ts2 get_funcref get_arg get_k get_r = + let ic_call env ts1 ts2 get_meth_pair get_arg get_k get_r = match E.mode env with | Flags.ICMode | Flags.StubMode -> (* The callee *) - get_funcref ^^ Arr.load_field 0l ^^ Blob.as_ptr_len env ^^ + get_meth_pair ^^ Arr.load_field 0l ^^ Blob.as_ptr_len env ^^ (* The method name *) - get_funcref ^^ Arr.load_field 1l ^^ Blob.as_ptr_len env ^^ + get_meth_pair ^^ Arr.load_field 1l ^^ Blob.as_ptr_len env ^^ (* The reply callback *) closure_to_reply_callback env ts2 get_k ^^ (* The reject callback *) @@ -5547,20 +4921,16 @@ module FuncDec = struct Dfinity.system_call env "ic0" "call_simple" ^^ (* TODO: Check error code *) G.i Drop - | Flags.AncientMode -> - callback_to_funcref env ts2 get_k ^^ - get_arg ^^ Serialization.serialize env ts1 ^^ - call_await_funcref env get_funcref | _ -> assert false - let ic_call_one_shot env ts get_funcref get_arg = + let ic_call_one_shot env ts get_meth_pair get_arg = match E.mode env with | Flags.ICMode | Flags.StubMode -> (* The callee *) - get_funcref ^^ Arr.load_field 0l ^^ Blob.as_ptr_len env ^^ + get_meth_pair ^^ Arr.load_field 0l ^^ Blob.as_ptr_len env ^^ (* The method name *) - get_funcref ^^ Arr.load_field 1l ^^ Blob.as_ptr_len env ^^ + get_meth_pair ^^ Arr.load_field 1l ^^ Blob.as_ptr_len env ^^ (* The reply callback *) ignoring_callback env ^^ compile_unboxed_zero ^^ @@ -5573,44 +4943,11 @@ module FuncDec = struct Dfinity.system_call env "ic0" "call_simple" ^^ (* TODO: Check error code *) G.i Drop - | Flags.AncientMode -> - get_arg ^^ Serialization.serialize env ts ^^ - call_message_funcref env get_funcref | _ -> assert false let export_async_method env = let name = Dfinity.async_method_name in begin match E.mode env with - | Flags.AncientMode -> - Func.define_built_in env name ["reply", I32Type; "databuf", I32Type; "elembuf", I32Type] [] (fun env -> - let (set_closure, get_closure) = new_local env "closure" in - let get_reply = G.i (LocalGet (nr 0l)) in - let get_databuf = G.i (LocalGet (nr 1l)) in - let get_elembuf = G.i (LocalGet (nr 2l)) in - - (* Restore memory *) - OrthogonalPersistence.restore_mem env ^^ - - (* Story reply contiuation *) - get_reply ^^ Dfinity.set_reply_cont env ^^ - - (* Look up closure *) - get_databuf ^^ get_elembuf ^^ - Serialization.deserialize env [Type.Prim Type.Word32] ^^ - BoxedSmallWord.unbox env ^^ - ClosureTable.recall_closure env ^^ (* At this point we can remove the closure *) - set_closure ^^ get_closure ^^ get_closure ^^ - Closure.call_closure env 0 0 ^^ - message_cleanup env (Type.Shared Type.Write) - ); - - let fi = E.built_in env name in - declare_dfinity_type env false true fi; - E.add_export env (nr { - name = Wasm.Utf8.decode name; - edesc = nr (FuncExport (nr fi)) - }) - | Flags.ICMode | Flags.StubMode -> Func.define_built_in env name [] [] (fun env -> let (set_closure, get_closure) = new_local env "closure" in @@ -5626,9 +4963,7 @@ module FuncDec = struct message_cleanup env (Type.Shared Type.Write) ); - let fi = E.built_in env name in - declare_dfinity_type env false true fi; E.add_export env (nr { name = Wasm.Utf8.decode ("canister_update " ^ name); edesc = nr (FuncExport (nr fi)) @@ -6580,8 +5915,8 @@ and compile_exp (env : E.t) ae exp = compile_exp_vanilla env ae e ^^ Object.load_idx env e.note.note_typ name | ActorDotE (e, name) -> - Dfinity.reference_sr env, - compile_exp_as env ae (Dfinity.reference_sr env) e ^^ + SR.Vanilla, + compile_exp_as env ae SR.Vanilla e ^^ Dfinity.actor_public_field env name | PrimE (p, es) -> @@ -6862,15 +6197,6 @@ and compile_exp (env : E.t) ae exp = serialize individually *) Serialization.serialize env ts ^^ Dfinity.reply_with_data env - | Flags.AncientMode -> - let (set_funcref, get_funcref) = new_local env "funcref" in - Dfinity.get_reply_cont env ^^ - set_funcref ^^ - compile_exp_as env ae SR.Vanilla e ^^ - (* TODO: We can try to avoid the boxing and pass the arguments to - serialize individually *) - Serialization.serialize env ts ^^ - FuncDec.call_message_funcref env get_funcref | _ -> assert false end @@ -6886,15 +6212,15 @@ and compile_exp (env : E.t) ae exp = (* TBR: Can we do better than using the notes? *) let _, _, _, ts1, _ = Type.as_func f.note.note_typ in let _, _, _, ts2, _ = Type.as_func k.note.note_typ in - let (set_funcref, get_funcref) = new_local env "funcref" in + let (set_meth_pair, get_meth_pair) = new_local env "meth_pair" in let (set_arg, get_arg) = new_local env "arg" in let (set_k, get_k) = new_local env "k" in let (set_r, get_r) = new_local env "r" in - compile_exp_as env ae (Dfinity.reference_sr env) f ^^ set_funcref ^^ + compile_exp_as env ae SR.Vanilla f ^^ set_meth_pair ^^ compile_exp_as env ae SR.Vanilla e ^^ set_arg ^^ compile_exp_as env ae SR.Vanilla k ^^ set_k ^^ compile_exp_as env ae SR.Vanilla r ^^ set_r ^^ - FuncDec.ic_call env ts1 ts2 get_funcref get_arg get_k get_r + FuncDec.ic_call env ts1 ts2 get_meth_pair get_arg get_k get_r end (* Unknown prim *) | _ -> SR.Unreachable, todo_trap env "compile_exp" (Arrange_ir.exp exp) @@ -7000,14 +6326,14 @@ and compile_exp (env : E.t) ae exp = (* Non-one-shot functions have been rewritten in async.ml *) assert (control = Type.Returns); - let (set_funcref, get_funcref) = new_local env "funcref" in + let (set_meth_pair, get_meth_pair) = new_local env "meth_pair" in let (set_arg, get_arg) = new_local env "arg" in let _, _, _, ts, _ = Type.as_func e1.note.note_typ in - code1 ^^ StackRep.adjust env fun_sr (Dfinity.reference_sr env) ^^ - set_funcref ^^ + code1 ^^ StackRep.adjust env fun_sr SR.Vanilla ^^ + set_meth_pair ^^ compile_exp_as env ae SR.Vanilla e2 ^^ set_arg ^^ - FuncDec.ic_call_one_shot env ts get_funcref get_arg + FuncDec.ic_call_one_shot env ts get_meth_pair get_arg end | SwitchE (e, cs) -> SR.Vanilla, @@ -7066,7 +6392,7 @@ and compile_exp (env : E.t) ae exp = get_k get_r | ActorE (i, ds, fs, _) -> - Dfinity.reference_sr env, + SR.Vanilla, let captured = Freevars.exp exp in let prelude_names = find_prelude_names env in if Freevars.M.is_empty (Freevars.diff captured prelude_names) @@ -7491,14 +6817,8 @@ and export_actor_field env ae (f : Ir.field) = (* There should be no code associated with this *) assert (G.is_nop code); - let is_await = match Type.normalize f.note with - | Type.Func(_,Type.Replies,_,_,_) -> true - | _ -> false in - - FuncDec.declare_dfinity_type env false is_await fi; E.add_export env (nr { name = Wasm.Utf8.decode (match E.mode env with - | Flags.AncientMode -> f.it.name | Flags.ICMode | Flags.StubMode -> Mo_types.Type.( match normalize f.note with @@ -7521,17 +6841,13 @@ and actor_lit outer_env this ds fs at = (E.get_trap_with outer_env) ClosureTable.table_end in - if E.mode mod_env = Flags.AncientMode then OrthogonalPersistence.register_globals mod_env; Heap.register_globals mod_env; - if E.mode mod_env = Flags.AncientMode then ElemHeap.register_globals mod_env; Stack.register_globals mod_env; Dfinity.system_imports mod_env; RTS.system_imports mod_env; RTS_Exports.system_exports mod_env; - Dfinity.register_reply mod_env; - let start_fun = Func.of_body mod_env [] [] (fun env -> G.with_region at @@ let ae0 = VarEnv.empty_ae in @@ -7539,7 +6855,7 @@ and actor_lit outer_env this ds fs at = let (ae1, prelude_code) = compile_prelude env ae0 in (* Add this pointer *) - let ae2 = VarEnv.add_local_deferred ae1 this (Dfinity.reference_sr env) Dfinity.get_self_reference false in + let ae2 = VarEnv.add_local_deferred ae1 this SR.Vanilla Dfinity.get_self_reference false in (* Reverse the fs, to a map from variable to exported name *) let v2en = E.NameEnv.from_list (List.map (fun f -> (f.it.var, f.it.name)) fs) in @@ -7555,18 +6871,12 @@ and actor_lit outer_env this ds fs at = if E.mode mod_env = Flags.ICMode then Dfinity.export_start mod_env start_fi; if E.mode mod_env = Flags.StubMode then Dfinity.export_start mod_env start_fi; - if E.mode mod_env = Flags.AncientMode then OrthogonalPersistence.register mod_env start_fi; let m = conclude_module mod_env this None in let (_map, wasm_binary) = Wasm_exts.CustomModuleEncode.encode m in wasm_binary in match E.mode outer_env with - | Flags.AncientMode -> - Dfinity.compile_databuf_of_bytes outer_env wasm_binary ^^ - (* Create actorref *) - Dfinity.system_call outer_env "module" "new" ^^ - Dfinity.system_call outer_env "actor" "new" | Flags.StubMode -> let (set_idx, get_idx) = new_local outer_env "idx" in let (set_len, get_len) = new_local outer_env "len" in @@ -7599,7 +6909,7 @@ and actor_lit outer_env this ds fs at = (* Main actor: Just return the initialization code, and export functions as needed *) and main_actor env ae1 this ds fs = (* Add this pointer *) - let ae2 = VarEnv.add_local_deferred ae1 this (Dfinity.reference_sr env) Dfinity.get_self_reference false in + let ae2 = VarEnv.add_local_deferred ae1 this SR.Vanilla Dfinity.get_self_reference false in (* Reverse the fs, to a map from variable to exported name *) let v2en = E.NameEnv.from_list (List.map (fun f -> (f.it.var, f.it.name)) fs) in @@ -7680,8 +6990,6 @@ and conclude_module env module_name start_fi_o = locals_names = List.mapi (fun i (f,_,ln) -> Int32.(add ni' (of_int i), ln)) funcs; }; - types = E.get_dfinity_types env; - persist = E.get_persist env } in match E.get_rts env with @@ -7691,24 +6999,16 @@ and conclude_module env module_name start_fi_o = let compile mode module_name rts (prelude : Ir.prog) (progs : Ir.prog list) : Wasm_exts.CustomModule.extended_module = let env = E.mk_global mode rts prelude Dfinity.trap_with ClosureTable.table_end in - if E.mode env = Flags.AncientMode then OrthogonalPersistence.register_globals env; Heap.register_globals env; - if E.mode env = Flags.AncientMode then ElemHeap.register_globals env; Stack.register_globals env; Dfinity.system_imports env; RTS.system_imports env; RTS_Exports.system_exports env; - Dfinity.register_reply env; - let start_fun = compile_start_func env (prelude :: progs) in let start_fi = E.add_fun env "start" start_fun in let start_fi_o = match E.mode env with - | Flags.AncientMode -> - OrthogonalPersistence.register env start_fi; - Dfinity.export_start_stub env; - None | Flags.ICMode | Flags.StubMode -> Dfinity.export_start env start_fi; None | Flags.WasmMode | Flags.WASIMode-> Some (nr start_fi) in diff --git a/src/exes/moc.ml b/src/exes/moc.ml index d9ac5ac96f6..d4bc64915c6 100644 --- a/src/exes/moc.ml +++ b/src/exes/moc.ml @@ -74,9 +74,6 @@ let argspec = Arg.align "-wasi-system-api", Arg.Unit (fun () -> Flags.(compile_mode := WASIMode)), " use the WASI system API (wasmtime)"; - "-ancient-system-api", - Arg.Unit (fun () -> Flags.(compile_mode := AncientMode)), - " use the ancient DFINITY system API (dvm)"; "-stub-system-api", Arg.Unit (fun () -> Flags.(compile_mode := StubMode)), " use the future DFINITY system API (ic-stub-run)"; diff --git a/src/js/mo_js.ml b/src/js/mo_js.ml index 7603fc3ac25..d6a300658b9 100644 --- a/src/js/mo_js.ml +++ b/src/js/mo_js.ml @@ -41,7 +41,6 @@ let js_check source = let js_compile_with mode_string source convert = let mode = match Js.to_string mode_string with - | "dfinity" -> Flags.AncientMode | _ -> Flags.WasmMode in match Pipeline.compile_string mode (Js.to_string source) Filename.current_dir_name with diff --git a/src/linking/linkModule.ml b/src/linking/linkModule.ml index 6ec76768dbb..cc9ece17047 100644 --- a/src/linking/linkModule.ml +++ b/src/linking/linkModule.ml @@ -181,31 +181,23 @@ let _remove_non_canister_exports (em : extended_module) : extended_module = let is_canister_export (exp : export) = Lib.String.chop_prefix "canister_" (Wasm.Utf8.encode exp.it.name) <> None in map_module (fun m -> { m with exports = List.filter is_canister_export m.exports }) em -module VarMap = Map.Make(Int32) - -let remove_non_dfinity_exports (em : extended_module) : extended_module = +let remove_non_ic_exports (em : extended_module) : extended_module = (* We assume that every exported function that does not have an entry in the custom types section was only exported for linking, and should not be exported in the final module *) - let dfinity_exports = List.fold_left - (fun map (fi, _) -> VarMap.add fi () map) - VarMap.empty em.types in - - let is_canister_export (exp : export) = - Lib.String.chop_prefix "canister_" (Wasm.Utf8.encode exp.it.name) <> None in - - let is_interesting_global (exp : export) = - (* For the ancient system API *) - Wasm.Utf8.encode exp.it.name = "datastore" || - Wasm.Utf8.encode exp.it.name = "elemstore" in + let is_ic_export (exp : export) = + Lib.String.chop_prefix "canister_" (Wasm.Utf8.encode exp.it.name) <> None + in - let is_dfinity_export exp = - is_canister_export exp || + let keep_export exp = + is_ic_export exp || match exp.it.edesc.it with - | FuncExport var -> VarMap.mem var.it dfinity_exports - | GlobalExport _ -> is_interesting_global exp - | _ -> true in - map_module (fun m -> { m with exports = List.filter is_dfinity_export m.exports }) em + | FuncExport var -> false + | GlobalExport _ -> false + | MemoryExport _ -> true + | TableExport _ -> true in + + map_module (fun m -> { m with exports = List.filter keep_export m.exports }) em (* Generic linking logic *) @@ -389,7 +381,6 @@ let rename_funcs_name_section rn (ns : name_section) = let rename_funcs_extended rn (em : extended_module) = { em with module_ = rename_funcs rn em.module_; - types = List.map (fun (fi, ty) -> (rn fi, ty)) em.types; name = rename_funcs_name_section rn em.name; } @@ -694,4 +685,4 @@ let link (em1 : extended_module) libname (em2 : extended_module) = |> rename_funcs_name_section funs2 ) |> add_call_ctors - |> remove_non_dfinity_exports (* only sane if no additional files get linked in *) + |> remove_non_ic_exports (* only sane if no additional files get linked in *) diff --git a/src/mo_config/flags.ml b/src/mo_config/flags.ml index 832e37a4ee5..ea22cc2ed37 100644 --- a/src/mo_config/flags.ml +++ b/src/mo_config/flags.ml @@ -1,6 +1,6 @@ (* common flags for the moc compiler *) -type compile_mode = WasmMode | AncientMode | ICMode | StubMode | WASIMode +type compile_mode = WasmMode | ICMode | StubMode | WASIMode let trace = ref false let verbose = ref false diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 488c1d242cd..eb4170984c5 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -76,7 +76,6 @@ let flag_of_compile_mode mode = | Flags.ICMode -> "" | Flags.WASIMode -> " and flag -wasi-system-api" | Flags.WasmMode -> " and flag -no-system-api" - | Flags.AncientMode -> " and flag -ancient-system-api" | Flags.StubMode -> " and flag -stub-system-api" let compile_mode_error mode env at fmt = diff --git a/src/wasm-exts/customModule.ml b/src/wasm-exts/customModule.ml index 89ac52cb9e8..8be4300c57e 100644 --- a/src/wasm-exts/customModule.ml +++ b/src/wasm-exts/customModule.ml @@ -4,8 +4,6 @@ open Wasm.Ast -type type_ = I32 | DataBuf | ElemBuf | ActorRef | FuncRef - type name_section = { module_ : string option; function_names : (int32 * string) list; @@ -33,9 +31,4 @@ type extended_module = { name : name_section; (* dylib section *) dylink : dylink_section option; - (* DFINITY Types: *) - (* function index, and number of arguments (simplified type system) *) - types : (int32 * type_ list) list; - (* index of persisted global, and its type *) - persist : (int32 * type_) list; } diff --git a/src/wasm-exts/customModuleDecode.ml b/src/wasm-exts/customModuleDecode.ml index 858d2785258..d404edd64c1 100644 --- a/src/wasm-exts/customModuleDecode.ml +++ b/src/wasm-exts/customModuleDecode.ml @@ -764,8 +764,6 @@ let module_ s = {types; tables; memories; globals; funcs; imports; exports; elems; data; start}; dylink; name; - persist = []; (* no use case for parsing these yet *) - types = [] (* no use case for parsing these yet *) } diff --git a/src/wasm-exts/customModuleEncode.ml b/src/wasm-exts/customModuleEncode.ml index ecb2182d199..7850e44bba8 100644 --- a/src/wasm-exts/customModuleEncode.ml +++ b/src/wasm-exts/customModuleEncode.ml @@ -124,7 +124,6 @@ let encode (em : extended_module) = let list f xs = List.iter f xs let opt f xo = Lib.Option.iter f xo let vec f xs = len (List.length xs); list f xs - let veci f xs = len (List.length xs); List.iteri f xs let gap32 () = let p = pos s in u32 0l; u8 0; p let patch_gap32 p n = @@ -543,50 +542,6 @@ let encode (em : extended_module) = let data_section data = section 11 (vec memory_segment) data (data <> []) - (* DFINITY Types section *) - - (* - The dfinity types are specified in terms of function ids excluding - imports, which is unidiomatic. We use real function ids internally, - so we have to work around it here. - *) - let count_fun_imports (em : extended_module) = - let is_fun_import imp = match imp.it.idesc.it with - | FuncImport _ -> true - | _ -> false in - Lib.List32.length (List.filter is_fun_import em.module_.imports) - - let dfinity_type = function - | CustomModule.I32 -> vu32 0x7fl - | CustomModule.DataBuf -> vu32 0x6cl - | CustomModule.ElemBuf -> vu32 0x6bl - | CustomModule.ActorRef -> vu32 0x6fl - | CustomModule.FuncRef -> vu32 0x6dl - - let dfinity_fun_type (_fi, param_types) = - vu32 0x60l; (* function type op code *) - vec dfinity_type param_types; - vu32 0l - - let dfinity_fun_type_map ni i (fi, _param_types) = - vu32 (Int32.sub fi ni); - vu32 (Int32.of_int i) - - let dfinity_types_section ni tys = - (* We could deduplicate the types here *) - custom_section "types" (vec dfinity_fun_type) tys (tys <> []); - custom_section "typeMap" (veci (dfinity_fun_type_map ni)) tys (tys <> []) - - (* DFINITY Persist section *) - - let dfinity_persist_global (i, sort) = - vu32 0x03l; (* a global *) - vu32 i; (* the index *) - dfinity_type sort - - let dfinity_persist_section pgs = - custom_section "persist" (vec dfinity_persist_global) pgs (pgs <> []) - (* Name section *) let assoc_list : 'a. ('a -> unit) -> (int32 * 'a) list -> unit = fun f xs -> @@ -626,8 +581,6 @@ let encode (em : extended_module) = code_section m.funcs; data_section m.data; (* other optional sections *) - dfinity_types_section (count_fun_imports em) em.types; - dfinity_persist_section em.persist; name_section em.name; end in E.module_ em; diff --git a/stdlib/Makefile b/stdlib/Makefile index ecfdb3fc473..9ba19774765 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -227,22 +227,22 @@ PRODUCE_EXCHANGE_SRC=\ $(OUTDIR)/ProduceExchange.out: $(PRODUCE_EXCHANGE_SRC) \ examples/produce-exchange/test/simpleSetupAndQuery.mo | $(OUTDIR) - $(MOC) -ancient-system-api -r examples/produce-exchange/test/simpleSetupAndQuery.mo > $@ + $(MOC) -stub-system-api -r examples/produce-exchange/test/simpleSetupAndQuery.mo > $@ $(OUTDIR)/retailerReserveMany.out: $(PRODUCE_EXCHANGE_SRC) \ examples/produce-exchange/test/retailerReserveMany.mo | $(OUTDIR) - $(MOC) -ancient-system-api -r examples/produce-exchange/test/retailerReserveMany.mo > $@ + $(MOC) -stub-system-api -r examples/produce-exchange/test/retailerReserveMany.mo > $@ $(OUTDIR)/producerRemInventory.out: $(PRODUCE_EXCHANGE_SRC) \ examples/produce-exchange/test/producerRemInventory.mo | $(OUTDIR) - $(MOC) -ancient-system-api -r examples/produce-exchange/test/producerRemInventory.mo > $@ + $(MOC) -stub-system-api -r examples/produce-exchange/test/producerRemInventory.mo > $@ $(OUTDIR)/evalBulk.out: $(PRODUCE_EXCHANGE_SRC) \ examples/produce-exchange/test/evalBulk.mo | $(OUTDIR) - $(MOC) -ancient-system-api -r examples/produce-exchange/test/evalBulk.mo > $@ + $(MOC) -stub-system-api -r examples/produce-exchange/test/evalBulk.mo > $@ $(OUTDIR)/ProduceExchange.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(MOC) -ancient-system-api -c -o $@ examples/produce-exchange/serverActor.mo + $(MOC) -stub-system-api -c -o $@ examples/produce-exchange/serverActor.mo $(DOCDIR)/%.md: %.mo $(MDofMO) | $(DOCDIR) @echo "" > $@ diff --git a/test/dvm.sh b/test/dvm.sh deleted file mode 100755 index 55b7ccfcbda..00000000000 --- a/test/dvm.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env bash - -if [ -z "$1" ] -then - echo "Usage: $0 .wasm [call-script]" - exit 1 -fi - -name="$(basename $1 .wasm)" -DVM_TMP=$(mktemp --directory --tmpdir dvm-XXXXXX) -trap 'rm -rf $DVM_TMP' EXIT - -export LANG=C -function dvm_ () { - # echo "\$ dvm $@" - - # hide the segmentation fault message - # hide leaked debug log - { dvm $@; } 2>&1 \ - | perl -pe 's,.*egmentation.*,Segmentation Fault,' \ - | perl -pe 's/Leaked.*!\n//m' \ - -} - -dvm_ -q --db $DVM_TMP reset -dvm_ -q --db $DVM_TMP new $1 -a $name -dvm_ -q --db $DVM_TMP run $name start - -if [ -n "$2" ] -then - grep '^//CALL ' $2 | cut -c7- | - while read call - do - echo "DVM: Calling method $call" - dvm_ -q --db $DVM_TMP run $name $call - done -fi diff --git a/test/repl/type-lub-repl.sh b/test/repl/type-lub-repl.sh index 5e4327876b0..b94f5bf9759 100755 --- a/test/repl/type-lub-repl.sh +++ b/test/repl/type-lub-repl.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # Tests that correct lub types are inferred when values appear in arrays -${MOC:-$(dirname "$BASH_SOURCE")/../../src/moc} -i -ancient-system-api ../run-stub/type-lub.mo <<__END__ +${MOC:-$(dirname "$BASH_SOURCE")/../../src/moc} -i ../run-stub/type-lub.mo <<__END__ opts; nulls; incompatible_objs; diff --git a/test/run-drun/oom.mo b/test/run-drun/oom.mo index f9a9b135f21..9689b0a9337 100644 --- a/test/run-drun/oom.mo +++ b/test/run-drun/oom.mo @@ -4,10 +4,6 @@ actor Oom { }; } -// on dvm: -// CALL doloop 0x4449444C0000 [] -// CALL doloop 0x4449444C0000 [] - // on drun: //CALL ingress doloop 0x4449444C0000 //CALL ingress doloop 0x4449444C0000 diff --git a/test/run-drun/selftail.mo b/test/run-drun/selftail.mo index 084a449eb93..f732b3f9ec2 100644 --- a/test/run-drun/selftail.mo +++ b/test/run-drun/selftail.mo @@ -17,7 +17,7 @@ debugPrint "ok1"; assert(10000 == f (true, 10000, 0)); debugPrint "ok2"; -// check recursion overflows for large n (on dvm only) +// check recursion overflows for large n (on drun only) // disabled as overflowing or not appears to be non-deterministic on V8 //assert(10000 == f (false, 10000, 0)); -//debugPrint "unreachable on dvm"; +//debugPrint "unreachable on drun"; diff --git a/test/run-drun/tailpositions.mo b/test/run-drun/tailpositions.mo index b171023670a..ed9e5f9f44f 100644 --- a/test/run-drun/tailpositions.mo +++ b/test/run-drun/tailpositions.mo @@ -1,4 +1,4 @@ -/* test tail-position calculation; error would stack overflow in dvm*/ +/* test tail-position calculation; error would stack overflow in drun*/ let bound:Int = 100000; diff --git a/test/run.sh b/test/run.sh index 269a7855fb4..f50e9ecf7bc 100755 --- a/test/run.sh +++ b/test/run.sh @@ -7,7 +7,6 @@ # Options: # # -a: Update the files in ok/ -# -1: Use Ancient API # -2: Use IC API # -3: Use Stub API # -t: Only typecheck @@ -31,21 +30,17 @@ MO_LD=${MO_LD:-$(realpath $(dirname $0)/../src/mo-ld)} DIDC=${DIDC:-$(realpath $(dirname $0)/../src/didc)} export MO_LD WASMTIME=${WASMTIME:-wasmtime} -DVM_WRAPPER=$(realpath $(dirname $0)/dvm.sh) DRUN_WRAPPER=$(realpath $(dirname $0)/drun-wrapper.sh) IC_STUB_RUN=${IC_STUB_RUN:-ic-stub-run} SKIP_RUNNING=${SKIP_RUNNING:-no} ONLY_TYPECHECK=no ECHO=echo -while getopts "a123stir" o; do +while getopts "a23stir" o; do case "${o}" in a) ACCEPT=yes ;; - 1) - API=ancient - ;; 2) API=ic ;; @@ -68,7 +63,6 @@ while getopts "a123stir" o; do done if [ $API = "wasm" ]; then EXTRA_MOC_FLAGS=-no-system-api; fi -if [ $API = "ancient" ]; then EXTRA_MOC_FLAGS=-ancient-system-api; fi if [ $API = "wasi" ]; then EXTRA_MOC_FLAGS=-wasi-system-api; fi if [ $API = "stub" ]; then EXTRA_MOC_FLAGS=-stub-system-api; fi if [ $RELEASE = "yes" ]; then MOC_FLAGS=--release; fi @@ -237,10 +231,7 @@ do # Run compiled program if [ "$SKIP_RUNNING" != yes ] then - if [ $API = ancient ] - then - run dvm $DVM_WRAPPER $out/$base.wasm $base.mo - elif [ $API = ic ] + if [ $API = ic ] then run drun-run $DRUN_WRAPPER $out/$base.wasm $base.mo elif [ $API = stub ] From d848c732eaa5162f481a459ff853b62457712b7e Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 27 Nov 2019 11:09:03 +0000 Subject: [PATCH 0719/1176] Fix for #894 (bad cps conversion of :=) (#937) * fix for issue-894 (bad cps-conversion of :=) * indentation * end with newlines * end with newlines * stray bullet * refactor per nomeata --- src/ir_def/check_ir.ml | 5 +++ src/ir_passes/await.ml | 19 ++++++++- test/fail/issue-894-fail.mo | 19 +++++++++ test/fail/ok/issue-894-fail.tc.ok | 12 ++++++ test/fail/ok/issue-894-fail.tc.ret.ok | 1 + test/run-stub/issue-894.mo | 48 +++++++++++++++++++++++ test/run-stub/ok/issue-894.ic-stub-run.ok | 13 ++++++ test/run-stub/ok/issue-894.run-ir.ok | 9 +++++ test/run-stub/ok/issue-894.run-low.ok | 9 +++++ test/run-stub/ok/issue-894.run.ok | 9 +++++ 10 files changed, 142 insertions(+), 2 deletions(-) create mode 100644 test/fail/issue-894-fail.mo create mode 100644 test/fail/ok/issue-894-fail.tc.ok create mode 100644 test/fail/ok/issue-894-fail.tc.ret.ok create mode 100644 test/run-stub/issue-894.mo create mode 100644 test/run-stub/ok/issue-894.ic-stub-run.ok create mode 100644 test/run-stub/ok/issue-894.run-ir.ok create mode 100644 test/run-stub/ok/issue-894.run-low.ok create mode 100644 test/run-stub/ok/issue-894.run.ok diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index bddab65a3d6..41d7c7a30fc 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -441,6 +441,11 @@ let rec check_exp env (exp:Ir.exp) : unit = n (T.string_of_typ_expand t1) end | AssignE (exp1, exp2) -> + begin + match exp1.it with + | (VarE _ | DotE _ | IdxE _) -> () + | _ -> error env exp.at "unexpected assignment target" + end; check_exp env exp1; check_exp env exp2; let t2 = try T.as_mut (typ exp1) with diff --git a/src/ir_passes/await.ml b/src/ir_passes/await.ml index 0c0d25cb030..92ba33c389d 100644 --- a/src/ir_passes/await.ml +++ b/src/ir_passes/await.ml @@ -228,11 +228,26 @@ and c_loop context k e1 = (c_exp context e1 (ContVar loop))] (loop -*- unitE) +and c_assign context k e exp1 exp2 = + match exp1.it with + | VarE _ -> + unary context k (fun v2 -> e (AssignE(exp1, v2))) exp2 + | DotE (exp11, id) -> + binary context k (fun v11 v2 -> + e (AssignE ({exp1 with it = DotE (v11, id)}, v2))) exp11 exp2 + | IdxE (exp11, exp12) -> + nary context k (fun vs -> match vs with + | [v11; v12; v2] -> + e (AssignE ({exp1 with it = IdxE (v11, v12)}, v2)) + | _ -> assert false) + [exp11; exp12; exp2] + | _ -> assert false + and c_exp context exp = c_exp' context exp and c_exp' context exp k = - let e exp' = {it=exp'; at = exp.at; note = exp.note} in + let e exp' = {exp with it = exp'} in match exp.it with | _ when is_triv exp -> k -@- (t_exp context exp) @@ -257,7 +272,7 @@ and c_exp' context exp k = | ActorDotE (exp1, id) -> unary context k (fun v1 -> e (DotE (v1, id))) exp1 | AssignE (exp1, exp2) -> - binary context k (fun v1 v2 -> e (AssignE (v1, v2))) exp1 exp2 + c_assign context k e exp1 exp2 | ArrayE (mut, typ, exps) -> nary context k (fun vs -> e (ArrayE (mut, typ, vs))) exps | IdxE (exp1, exp2) -> diff --git a/test/fail/issue-894-fail.mo b/test/fail/issue-894-fail.mo new file mode 100644 index 00000000000..32c14cc99c6 --- /dev/null +++ b/test/fail/issue-894-fail.mo @@ -0,0 +1,19 @@ +actor a { + public shared func test() : async () { + { + let o = {var l = 0}; + (await async o).l := await async 1; // type error (o mutable, not shared) + debugPrintNat(o.l); + assert o.l == 1; + }; + + { + let a = [var 0]; + (await async a)[0] := await async 1; // type error (a mutable, not shared) + debugPrintNat(a[0]); + assert a[0] == 1; + }; + } +}; + +a.test(); diff --git a/test/fail/ok/issue-894-fail.tc.ok b/test/fail/ok/issue-894-fail.tc.ok new file mode 100644 index 00000000000..c9ebafcca33 --- /dev/null +++ b/test/fail/ok/issue-894-fail.tc.ok @@ -0,0 +1,12 @@ +issue-894-fail.mo:5.20-5.21: type error, async type has non-shared content type + {var l : Nat} +type + {var l : Nat} +is or contains non-shared type + var Nat +issue-894-fail.mo:12.20-12.21: type error, async type has non-shared content type + [var Nat] +type + [var Nat] +is or contains non-shared type + var Nat diff --git a/test/fail/ok/issue-894-fail.tc.ret.ok b/test/fail/ok/issue-894-fail.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/issue-894-fail.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-stub/issue-894.mo b/test/run-stub/issue-894.mo new file mode 100644 index 00000000000..64d2a6f7b1e --- /dev/null +++ b/test/run-stub/issue-894.mo @@ -0,0 +1,48 @@ +actor a { + public shared func id(i : Nat) : async Nat { i }; + + public shared func test() : async () { + + { + let o = {var l = 0}; + o.l := 1; + debugPrintNat(o.l); + assert o.l == 1; + }; + + { + let o = {var l = 0}; + o.l := await async 1; + debugPrintNat(o.l); + assert o.l == 1; + }; + + { + let a = [var 0]; + a[await async 0] := 1; + debugPrintNat(a[0]); + assert a[0] == 1; + }; + + { + let a = [var 0]; + a[await async 0] := await async 1; + debugPrintNat(a[0]); + assert a[0] == 1; + }; + + { + let a = Array_init(5, 0); + for (i in a.keys()) { + a[await id(i)] := await id(i); + debugPrintNat(a[i]); + assert a[i] == i; + }; + }; + + + }; + +}; + +a.test(); diff --git a/test/run-stub/ok/issue-894.ic-stub-run.ok b/test/run-stub/ok/issue-894.ic-stub-run.ok new file mode 100644 index 00000000000..b43fa49a755 --- /dev/null +++ b/test/run-stub/ok/issue-894.ic-stub-run.ok @@ -0,0 +1,13 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +1 +1 +1 +1 +0 +1 +2 +3 +4 +← completed diff --git a/test/run-stub/ok/issue-894.run-ir.ok b/test/run-stub/ok/issue-894.run-ir.ok new file mode 100644 index 00000000000..f3500a67ec4 --- /dev/null +++ b/test/run-stub/ok/issue-894.run-ir.ok @@ -0,0 +1,9 @@ +1 +1 +1 +1 +0 +1 +2 +3 +4 diff --git a/test/run-stub/ok/issue-894.run-low.ok b/test/run-stub/ok/issue-894.run-low.ok new file mode 100644 index 00000000000..f3500a67ec4 --- /dev/null +++ b/test/run-stub/ok/issue-894.run-low.ok @@ -0,0 +1,9 @@ +1 +1 +1 +1 +0 +1 +2 +3 +4 diff --git a/test/run-stub/ok/issue-894.run.ok b/test/run-stub/ok/issue-894.run.ok new file mode 100644 index 00000000000..f3500a67ec4 --- /dev/null +++ b/test/run-stub/ok/issue-894.run.ok @@ -0,0 +1,9 @@ +1 +1 +1 +1 +0 +1 +2 +3 +4 From ee9712c6d354f61d069158ce85487ef781f3db1b Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 27 Nov 2019 11:29:58 +0000 Subject: [PATCH 0720/1176] Update src/mo_types/type.ml bug fix --- src/mo_types/type.ml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index 475d66a7745..3f7bbd16d71 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -168,7 +168,7 @@ let rec shift i n t = | Tup ts -> Tup (List.map (shift i n) ts) | Func (s, c, tbs, ts1, ts2) -> let i' = i + List.length tbs in - Func (s, c, List.map (shift_bind i' n) tbs, List.map (shift i' n) ts1, List.map (shift i' n) ts2) + Func (s, map_control (shift i' n) c, List.map (shift_bind i' n) tbs, List.map (shift i' n) ts1, List.map (shift i' n) ts2) | Opt t -> Opt (shift i n t) | Async (t1, t2) -> Async (shift i n t1, shift i n t2) | Obj (s, fs) -> Obj (s, List.map (shift_field n i) fs) @@ -1294,4 +1294,3 @@ let rec string_of_typ_expand t = | _ -> s let is_shared_sort sort = sort <> Local - From 20ac584172d567aa84aa8db32b367f7366206676 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 27 Nov 2019 11:30:47 +0000 Subject: [PATCH 0721/1176] Update src/mo_types/type.ml formatting --- src/mo_types/type.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index 3f7bbd16d71..526ac02c16b 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -168,7 +168,7 @@ let rec shift i n t = | Tup ts -> Tup (List.map (shift i n) ts) | Func (s, c, tbs, ts1, ts2) -> let i' = i + List.length tbs in - Func (s, map_control (shift i' n) c, List.map (shift_bind i' n) tbs, List.map (shift i' n) ts1, List.map (shift i' n) ts2) + Func (s, map_control (shift i' n) c, List.map (shift_bind i' n) tbs, List.map (shift i' n) ts1, List.map (shift i' n) ts2) | Opt t -> Opt (shift i n t) | Async (t1, t2) -> Async (shift i n t1, shift i n t2) | Obj (s, fs) -> Obj (s, List.map (shift_field n i) fs) From 339b90d4c5f37648568f5ba43f8598f949ddb453 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 27 Nov 2019 12:28:52 +0000 Subject: [PATCH 0722/1176] Update src/mo_frontend/typing.ml Bug fix (found on claudio/scoped-await-sweet) --- src/mo_frontend/typing.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 3625c568d6a..a1c4c70084c 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -311,7 +311,7 @@ and check_typ' env typ : T.typ = end; let tbs = List.map2 (fun c t -> {T.var = Con.name c; bound = t}) cs ts in - T.Func (sort.it, c', T.close_binds cs tbs, List.map (T.close cs) ts1, List.map (T.close cs) ts2) + T.Func (sort.it, T.map_control (T.close cs) c', T.close_binds cs tbs, List.map (T.close cs) ts1, List.map (T.close cs) ts2) | OptT typ -> T.Opt (check_typ env typ) | VariantT tags -> From f3227731ab15dfc05fddb375bf45bcff3a3f497c Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 27 Nov 2019 12:31:23 +0000 Subject: [PATCH 0723/1176] only introduce bindes when <> not present; bug fix in shift and elab of FuncT --- src/mo_frontend/parser.mly | 37 +++++++++++++++++++++++-------------- src/mo_frontend/typing.ml | 2 +- src/mo_types/type.ml | 2 +- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/src/mo_frontend/parser.mly b/src/mo_frontend/parser.mly index 1545888fbbf..13c930700c1 100644 --- a/src/mo_frontend/parser.mly +++ b/src/mo_frontend/parser.mly @@ -103,20 +103,25 @@ let rec is_scope_typ t = | ParT t -> is_scope_typ t | _ -> false -let funcT(sort, tbs, t1, t2) = - match tbs, t2.it with - | [], (AsyncT (t21, _)) when is_scope_typ t21 -> - FuncT(sort, [scope_bind()], t1, t2) - | _ -> FuncT(sort, tbs, t1, t2) - -let funcE (f, s, tbs, p, t_opt, e) = - match tbs, t_opt with - | [], Some t -> +let funcT(sort, tbs_opt, t1, t2) = + match tbs_opt with + | None -> + (match t2.it with + | AsyncT (t21, _) when is_scope_typ t21 -> + FuncT(sort, [scope_bind()], t1, t2) + | _ -> + FuncT(sort, [], t1, t2)) + | Some tbs -> FuncT(sort, tbs, t1, t2) + +let funcE (f, s, tbs_opt, p, t_opt, e) = + match tbs_opt, t_opt with + | None, None -> FuncE(f, s, [], p, t_opt, e) + | None, Some t -> (match t.it with | AsyncT (t1, _) when is_scope_typ t1 -> FuncE(f, s, [scope_bind()], p, t_opt, e) - | _ -> FuncE(f, s, tbs, p, t_opt, e)) - | _ -> FuncE(f, s, tbs, p, t_opt, e) + | _ -> FuncE(f, s, [], p, t_opt, e)) + | Some tbs, _ -> FuncE(f, s, tbs, p, t_opt, e) %} @@ -294,10 +299,14 @@ typ_item : typ_args : | LT ts=seplist(typ, COMMA) GT { ts } -%inline typ_params_opt : +%inline typ_params : | (* empty *) { [] } | LT ts=seplist(typ_bind, COMMA) GT { ts } +%inline typ_params_opt : + | (* empty *) { None } + | LT ts=seplist(typ_bind, COMMA) GT { Some ts } + typ_field : | mut=var_opt x=id COLON t=typ { {id = x; typ = t; mut} @@ at $sloc } @@ -640,7 +649,7 @@ dec_nonvar : | AnnotP (p', t) -> p', AnnotE (e, t) @? p.at | _ -> p, e in LetD (p', e') @? at $sloc } - | TYPE x=typ_id tps=typ_params_opt EQ t=typ + | TYPE x=typ_id tps=typ_params EQ t=typ { TypD(x, tps, t) @? at $sloc } | s=obj_sort xf=id_opt EQ? efs=obj_body { let named, x = xf "object" $sloc in @@ -662,7 +671,7 @@ dec_nonvar : let named, x = xf "func" $sloc in let_or_exp named x (funcE(x.it, s, tps, p, t, e)) (at $sloc) } | s=obj_sort_opt CLASS xf=typ_id_opt - tps=typ_params_opt p=pat_param t=return_typ? cb=class_body + tps=typ_params p=pat_param t=return_typ? cb=class_body { let x, efs = cb in let efs' = if s.it = Type.Actor then List.map share_expfield efs else efs diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 436001d66ef..24fbb9b2100 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -311,7 +311,7 @@ and check_typ' env typ : T.typ = end; let tbs = List.map2 (fun c t -> {T.var = Con.name c; bound = t}) cs ts in - T.Func (sort.it, c', T.close_binds cs tbs, List.map (T.close cs) ts1, List.map (T.close cs) ts2) + T.Func (sort.it, T.map_control (T.close cs) c', T.close_binds cs tbs, List.map (T.close cs) ts1, List.map (T.close cs) ts2) | OptT typ -> T.Opt (check_typ env typ) | VariantT tags -> diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index 475d66a7745..75197c01dc6 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -168,7 +168,7 @@ let rec shift i n t = | Tup ts -> Tup (List.map (shift i n) ts) | Func (s, c, tbs, ts1, ts2) -> let i' = i + List.length tbs in - Func (s, c, List.map (shift_bind i' n) tbs, List.map (shift i' n) ts1, List.map (shift i' n) ts2) + Func (s, map_control (shift i' n) c, List.map (shift_bind i' n) tbs, List.map (shift i' n) ts1, List.map (shift i' n) ts2) | Opt t -> Opt (shift i n t) | Async (t1, t2) -> Async (shift i n t1, shift i n t2) | Obj (s, fs) -> Obj (s, List.map (shift_field n i) fs) From 8428270808244ca937bd8e45878973832c29e3b2 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 27 Nov 2019 12:41:36 +0000 Subject: [PATCH 0724/1176] new test exploiting scope sugar: --- test/run-drun/general_await_implicit.mo | 110 +++++++++++++++ .../ok/general_await_implicit.run-ir.ok | 132 ++++++++++++++++++ .../ok/general_await_implicit.run-low.ok | 132 ++++++++++++++++++ 3 files changed, 374 insertions(+) create mode 100644 test/run-drun/general_await_implicit.mo create mode 100644 test/run-drun/ok/general_await_implicit.run-ir.ok create mode 100644 test/run-drun/ok/general_await_implicit.run-low.ok diff --git a/test/run-drun/general_await_implicit.mo b/test/run-drun/general_await_implicit.mo new file mode 100644 index 00000000000..610cc4314da --- /dev/null +++ b/test/run-drun/general_await_implicit.mo @@ -0,0 +1,110 @@ +actor Await { + + public shared func Ack/*<@>*/() : async(){ + debugPrint "\nAck" + }; + + public shared func Request/*<@>*/(i : Int) : async Int { + debugPrint("\nRequest(");debugPrintInt(i);debugPrint(")"); + return i; + }; + + // Static parallel waiting: + + public shared func PA/*<@>*/() : async () { + let a1 = Ack/*<@>*/(); + let a2 = Ack/*<@>*/(); + await a1; + await a2; + }; + + public shared func PR/*<@>*/() : async (Int,Int) { + let a1 = Request/*<@>*/(1); + let a2 = Request/*<@>*/(2); + (await a1, await a2) + }; + + // Dynamic parallel waiting for acknowledgements + + public shared func DPA/*<@>*/() : async () { + let as: [async()] = Array_tabulate(10, func (_) { Ack/*<@>*/(); }); + for (a in as.vals()) { + await a; + }; + }; + + // Dynamic parallel waiting (with results) + + public shared func DPR/*<@>*/() : async [Int] { + func f<>(i:Nat) : async Int = Request/*<@>*/(i); + //NB: <> necesary to suppress implicit @-quantification + let as = Array_tabulate(10, f); + let res = Array_init(as.len(),-1); + for (i in as.keys()) { +// res[i] := (await as[i]); <-- compiler bug (generates incorrect code) + let a = await as[i]; + res[i] := a; + }; + Array_tabulate(as.len(),func i = res[i]) + }; + + // Recursive parallel waiting + + public shared func RPA/*<@>*/(n:Nat) : async () { + if (n == 0) () + else { + let a = Ack/*<@>*/(); + await RPA/*<@>*/(n-1); // recurse + await a; + }; + }; + + // Recursive parallel waiting (with results) + + public type List = ?(Int,List); + + public shared func RPR/*<@>*/(n:Nat) : async List { + if (n == 0) null + else { + let a = Request/*<@>*/(n); + let tl = await RPR/*<@>*/(n-1); // recurse + ?(await a,tl) + } + }; + + + public shared func Test() : async () { + + await PA/*<@>*/(); + + switch (await PR/*<@>*/()) { + case (1,2) (); + case _ (assert false); + }; + + await DPA/*<@>*/(); + + let rs = await DPR/*<@>*/(); + for (i in rs.keys()) { + assert rs[i] == i; + }; + + await RPA/*<@>*/(10); + + var l = await RPR/*<@>*/(10); + for (i in revrange(10, 1)) { + switch (l) { + case (?(h, t)) { + assert (h == i); + l := t; + }; + case null (assert false); + } + }; + } +}; + +Await.Test(); + +//SKIP run-drun +//SKIP comp diff --git a/test/run-drun/ok/general_await_implicit.run-ir.ok b/test/run-drun/ok/general_await_implicit.run-ir.ok new file mode 100644 index 00000000000..e956f326cfb --- /dev/null +++ b/test/run-drun/ok/general_await_implicit.run-ir.ok @@ -0,0 +1,132 @@ + +Ack + +Ack + +Request( ++1 +) + +Request( ++2 +) + +Ack + +Ack + +Ack + +Ack + +Ack + +Ack + +Ack + +Ack + +Ack + +Ack + +Request( +0 +) + +Request( ++1 +) + +Request( ++2 +) + +Request( ++3 +) + +Request( ++4 +) + +Request( ++5 +) + +Request( ++6 +) + +Request( ++7 +) + +Request( ++8 +) + +Request( ++9 +) + +Ack + +Ack + +Ack + +Ack + +Ack + +Ack + +Ack + +Ack + +Ack + +Ack + +Request( ++10 +) + +Request( ++9 +) + +Request( ++8 +) + +Request( ++7 +) + +Request( ++6 +) + +Request( ++5 +) + +Request( ++4 +) + +Request( ++3 +) + +Request( ++2 +) + +Request( ++1 +) diff --git a/test/run-drun/ok/general_await_implicit.run-low.ok b/test/run-drun/ok/general_await_implicit.run-low.ok new file mode 100644 index 00000000000..e956f326cfb --- /dev/null +++ b/test/run-drun/ok/general_await_implicit.run-low.ok @@ -0,0 +1,132 @@ + +Ack + +Ack + +Request( ++1 +) + +Request( ++2 +) + +Ack + +Ack + +Ack + +Ack + +Ack + +Ack + +Ack + +Ack + +Ack + +Ack + +Request( +0 +) + +Request( ++1 +) + +Request( ++2 +) + +Request( ++3 +) + +Request( ++4 +) + +Request( ++5 +) + +Request( ++6 +) + +Request( ++7 +) + +Request( ++8 +) + +Request( ++9 +) + +Ack + +Ack + +Ack + +Ack + +Ack + +Ack + +Ack + +Ack + +Ack + +Ack + +Request( ++10 +) + +Request( ++9 +) + +Request( ++8 +) + +Request( ++7 +) + +Request( ++6 +) + +Request( ++5 +) + +Request( ++4 +) + +Request( ++3 +) + +Request( ++2 +) + +Request( ++1 +) From 5580f102c407864f59c80ab09cdc487a69e11e8d Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 27 Nov 2019 14:22:26 +0000 Subject: [PATCH 0725/1176] infer scope parameter for local functions too --- src/mo_frontend/typing.ml | 3 ++- test/run-drun/general_await.mo | 2 +- test/run-stub/general_await.mo | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 24fbb9b2100..5d640c440a8 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -781,7 +781,8 @@ and infer_exp'' env exp : T.typ = (T.string_of_typ_expand t1) in let insts = match insts, t1 with - | [], T.Func(_,T.Promises (T.Var (_,0)),[_],_,_) -> + | [], T.Func(_,T.Promises (T.Var (_,0)),[_],_,_) + | [], T.Func(_,T.Returns,[_],_,[T.Async (T.Var (_,0),_)]) -> [Syntax.scope_typ {left=exp1.at.right; right = exp2.at.left}] | _ -> insts in diff --git a/test/run-drun/general_await.mo b/test/run-drun/general_await.mo index 528ebb2ccf7..ffefcfd53ed 100644 --- a/test/run-drun/general_await.mo +++ b/test/run-drun/general_await.mo @@ -36,7 +36,7 @@ actor Await { // Dynamic parallel waiting (with results) public shared func DPR<@>() : async [Int] { - func f (i:Nat) : async Int = Request<@>(i); + func f<>(i:Nat) : async Int = Request<@>(i); let as = Array_tabulate(10, f); let res = Array_init(as.len(),-1); for (i in as.keys()) { diff --git a/test/run-stub/general_await.mo b/test/run-stub/general_await.mo index b01c7942950..ee57adc35ba 100644 --- a/test/run-stub/general_await.mo +++ b/test/run-stub/general_await.mo @@ -41,7 +41,7 @@ actor Await { // Dynamic parallel waiting (with results) public shared func DPR<@>() : async [Int] { - func f (i:Nat) : async Int = Await.Request<@>(i); + func f<>(i:Nat) : async Int = Await.Request<@>(i); let as = Array_tabulate(N, f); let res = Array_init(as.len(),-1); for (i in as.keys()) { From 2fa5ec6c0c97a5558d8188a1f4de3bade01d71ea Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 27 Nov 2019 17:47:50 +0000 Subject: [PATCH 0726/1176] add explicit async syntax, ascync { ... } ? --- src/mo_frontend/parser.mly | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/mo_frontend/parser.mly b/src/mo_frontend/parser.mly index 573c2680e84..e0b19afe914 100644 --- a/src/mo_frontend/parser.mly +++ b/src/mo_frontend/parser.mly @@ -249,8 +249,8 @@ typ_pre : { t } | PRIM s=TEXT { PrimT(s) @! at $sloc } - | ASYNC t=typ_pre - { AsyncT(scope_typ(), t) @! at $sloc } + | ASYNC t1 = scope_inst_opt t2=typ_pre + { AsyncT(t1, t2) @! at $sloc } | s=obj_sort tfs=typ_obj { let tfs' = if s.it = Type.Actor then List.map share_typfield tfs else tfs @@ -291,7 +291,15 @@ typ_bind : | x=id { {var = x; bound = PrimT "Any" @! at $sloc} @= at $sloc } +%inline scope_bind : + | LT tb=typ_bind GT + { tb } +%inline scope_inst_opt : + | LT t=typ GT + { t } + | (* empty *) + { scope_typ () } (* Expressions *) @@ -446,6 +454,8 @@ exp_nondec(B) : { RetE(e) @? at $sloc } | ASYNC e=exp(bl) { AsyncE(scope_bind(), e, scope_typ()) @? at $sloc } + | ASYNC tb = scope_bind e=exp_block t=scope_inst_opt + { AsyncE(tb, e, t) @? at $sloc } | AWAIT e=exp(bl) { AwaitE(e) @? at $sloc } | ASSERT e=exp(bl) From 2bc200344ebab481faba9e92c8ea0cc6c8d39250 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Thu, 28 Nov 2019 11:36:52 +0100 Subject: [PATCH 0727/1176] Conversion random testing (#943) * test roundtrip WordN -> Nat -> WordN * test modulo roundtrip Nat -> WordN -> Nat I.e. the conversion `natToWordN` restricted to `WordN` is the identity, and elsewhere defined by modulus. --- test/random/Main.hs | 59 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 5 deletions(-) diff --git a/test/random/Main.hs b/test/random/Main.hs index 803f457c498..ce42b1d46cb 100644 --- a/test/random/Main.hs +++ b/test/random/Main.hs @@ -17,6 +17,7 @@ import qualified Data.Text (null, unpack) import Data.Maybe import Data.Bool (bool) import Data.Proxy +import Data.Type.Equality import GHC.Natural import GHC.TypeLits import qualified Data.Word @@ -29,13 +30,23 @@ import Turtle main = defaultMain tests where tests :: TestTree - tests = testGroup "Motoko tests" [arithProps, utf8Props, matchingProps] + tests = testGroup "Motoko tests" [arithProps, conversionProps, utf8Props, matchingProps] arithProps = testGroup "Arithmetic/logic" [ QC.testProperty "expected failures" $ prop_rejects , QC.testProperty "expected successes" $ prop_verifies ] +conversionProps = testGroup "Numeric conversions" + [ QC.testProperty "roundtrip Word64 Nat Word64 " $ prop_roundtripWNW @64 + , QC.testProperty "roundtrip Word32 Nat Word32 " $ prop_roundtripWNW @32 + , QC.testProperty "roundtrip Word16 Nat Word16 " $ prop_roundtripWNW @16 + , QC.testProperty "roundtrip Word8 Nat Word8 " $ prop_roundtripWNW @8 + , QC.testProperty "modulo Nat Word64 Nat" $ prop_moduloNWN @64 + , QC.testProperty "modulo Nat Word32 Nat" $ prop_moduloNWN @32 + , QC.testProperty "modulo Nat Word16 Nat" $ prop_moduloNWN @16 + , QC.testProperty "modulo Nat Word8 Nat" $ prop_moduloNWN @8 + ] utf8Props = testGroup "UTF-8 coding" [ QC.testProperty "explode >>> concat roundtrips" $ prop_explodeConcat @@ -43,7 +54,7 @@ utf8Props = testGroup "UTF-8 coding" , QC.testProperty "length computation" $ prop_textLength ] -matchingProps = testGroup "pattern matching" +matchingProps = testGroup "Pattern matching" [ QC.testProperty "intra-actor" $ prop_matchStructured , QC.testProperty "inter-actor" $ prop_matchInActor ] @@ -113,7 +124,7 @@ newtype Failing a = Failing a deriving Show instance Arbitrary (Failing String) where arbitrary = do let failed as = "let _ = " ++ unparseAS as ++ ";" - Failing . failed <$> suchThat (resize 5 arbitrary) (\(evaluate @ Integer -> res) -> null res) + Failing . failed <$> suchThat (resize 5 arbitrary) (\(evaluate @Integer -> res) -> null res) prop_rejects (Failing testCase) = monadicIO $ runScriptWantFuzz "fails" testCase @@ -125,7 +136,7 @@ newtype TestCase = TestCase [String] deriving Show instance Arbitrary TestCase where arbitrary = do tests <- infiniteListOf arbitrary - let expected = evaluate @ Integer <$> tests + let expected = evaluate @Integer <$> tests let paired as = fmap (\res -> "assert (" ++ unparseAS as ++ " == " ++ show res ++ ");") pure . TestCase . take 100 . catMaybes $ zipWith paired tests expected @@ -155,6 +166,33 @@ prop_verifies (TestCase (map fromString -> testCase)) = monadicIO $ do assertSuccessNoFuzz id res +newtype ConversionTest n = ConversionTest (ASTerm (BitLimited n Word)) deriving Show + +instance WordLike n => Arbitrary (ConversionTest n) where + arbitrary = ConversionTest . ConvertNatToWord . ConvertWordToNat . Neuralgic <$> (arbitrary :: Gen (Neuralgic (BitLimited n Word))) + +prop_roundtripWNW :: ConversionTest n -> Property +prop_roundtripWNW (ConversionTest term) = + case term of + ConvertNatToWord (ConvertWordToNat n) -> + case sameNat (bitsIn term) (bitsIn n) of + Just Refl -> let testCase = "assert(" <> unparseAS (term `Equals` n) <> ")" in + monadicIO $ runScriptNoFuzz "roundtripWNW" testCase + where bitsIn :: KnownNat n => ASTerm (BitLimited n Word) -> Proxy n + bitsIn _ = Proxy + + +newtype ModuloTest (n :: Nat) = ModuloTest (ASTerm (BitLimited n Word)) deriving Show + +instance WordLike n => Arbitrary (ModuloTest n) where + arbitrary = ModuloTest . ConvertNatToWord @n . Neuralgic <$> (arbitrary :: Gen (Neuralgic Natural)) + +prop_moduloNWN :: forall n . KnownNat n => ModuloTest n -> Property +prop_moduloNWN (ModuloTest term@(ConvertNatToWord (Neuralgic m))) = monadicIO $ runScriptNoFuzz "moduloNWN" testCase + where m' = evalN m .&. maskFor term + testCase = "assert(" <> unparseAS (ConvertWordToNat term) + <> " == " <> show m' <> ")" + data Matching where Matching :: (AnnotLit t, ASValue t, Show t) => (ASTerm t, t) -> Matching @@ -282,7 +320,7 @@ infix 1 `guardedFrom` instance Arbitrary (Neuralgic Natural) where arbitrary = (\n -> if n >= 0 then pure (fromIntegral n) else Nothing) - `guardedFrom` [Around0, AroundPos 30, AroundPos 63, LargePos] + `guardedFrom` [Around0, AroundPos 30, AroundPos 63, LargePos, AroundPos 77] instance KnownNat n => Arbitrary (Neuralgic (BitLimited n Natural)) where arbitrary = fmap NatN <$> trapNat bits `guardedFrom` menu bits @@ -339,6 +377,8 @@ data ASTerm :: * -> * where ConvertNat :: KnownNat n => ASTerm (BitLimited n Natural) -> ASTerm Integer ConvertInt :: KnownNat n => ASTerm (BitLimited n Integer) -> ASTerm Integer ConvertWord :: WordLike n => ASTerm (BitLimited n Word) -> ASTerm Integer + ConvertNatToWord :: WordLike n => ASTerm Natural -> ASTerm (BitLimited n Word) + ConvertWordToNat :: WordLike n => ASTerm (BitLimited n Word) -> ASTerm Natural -- Constructors (intro forms) Pair :: (AnnotLit a, AnnotLit b, Evaluatable a, Evaluatable b) => ASTerm a -> ASTerm b -> ASTerm (a, b) Triple :: (AnnotLit a, AnnotLit b, AnnotLit c, Evaluatable a, Evaluatable b, Evaluatable c) @@ -739,6 +779,10 @@ instance Evaluatable a => Evaluatable (Maybe a) where evaluate Null = pure Nothing evaluate (Some a) = Just <$> evaluate a +maskFor :: forall n . KnownNat n => ASTerm (BitLimited n Word) -> Natural +maskFor _ = fromIntegral $ 2 ^ natVal (Proxy @n) - 1 + + eval :: (Restricted a, Integral a) => ASTerm a -> Maybe a eval Five = pure 5 eval (Neuralgic n) = evalN n @@ -755,6 +799,8 @@ eval (ConvertNatural t) = fromIntegral <$> evaluate t eval (ConvertNat t) = fromIntegral <$> evaluate t eval (ConvertInt t) = fromIntegral <$> evaluate t eval (ConvertWord t) = fromIntegral <$> evaluate t +eval c@(ConvertNatToWord t) = fromIntegral . (.&. maskFor c) <$> evaluate t +eval (ConvertWordToNat t) = fromIntegral <$> evaluate t eval (IfThenElse a b c) = do c <- evaluate c eval $ if c then a else b --eval _ = Nothing @@ -868,6 +914,8 @@ unparseAS (ConvertNatural a) = "(++++(" <> unparseAS a <> "))" unparseAS (ConvertNat a) = unparseNat Proxy a unparseAS (ConvertInt a) = unparseInt Proxy a unparseAS (ConvertWord a) = unparseWord Proxy a +unparseAS (ConvertWordToNat a) = sizeSuffix a "(word" <> "ToNat " <> unparseAS a <> ")" +unparseAS t@(ConvertNatToWord a) = sizeSuffix t "(natToWord" <> " " <> unparseAS a <> ")" unparseAS (IfThenElse a b c) = "(if (" <> unparseAS c <> ") " <> unparseAS a <> " else " <> unparseAS b <> ")" unparseAS (a `NotEqual` b) = inParens unparseAS "!=" a b unparseAS (a `Equals` b) = inParens unparseAS "==" a b @@ -897,6 +945,7 @@ unparseWord p a = "(word" <> bitWidth p <> "ToNat(" <> unparseAS a <> "))" -- TO -- TODOs: -- - wordToInt -- - natToNat64/intToWord64 (and round-trips) +-- Done: natToWordN/wordNToNat -- - bitwise ops (btst?) -- - pattern matches (over numeric, bool, structured) -- - trapping flavour-preserving conversions Nat -> NatN From 261e26d52049a3846ffccae35724a69b0c6ce37e Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 28 Nov 2019 11:46:49 +0100 Subject: [PATCH 0728/1176] Garbage collect closures (#944) This defines a suitable data stucture in the C code (a packed array with integrated free list). It is compatible with the RTS's idea of an array, so it can be copied and traversed by the GC. There is a test case that checks that that closed-over values (a large array in this case) are indeed freed. We can add such test cases for other GC-related things now. There is also a unit test of the C data structure in test_rts.c. --- rts/Makefile | 2 +- rts/closure-table.c | 109 ++++++++++++++++ rts/rts.c | 22 ++-- rts/rts.h | 19 ++- rts/test_leb128.c | 7 +- rts/test_rts.c | 80 ++++++++++-- src/codegen/compile.ml | 123 ++++++------------ src/prelude/prelude.ml | 3 +- test/run-stub/count-callbacks.mo | 20 +-- test/run-stub/free-callbacks.mo | 38 ++++++ .../ok/count-callbacks.ic-stub-run.ok | 8 +- .../run-stub/ok/free-callbacks.ic-stub-run.ok | 5 + test/run.sh | 1 + 13 files changed, 309 insertions(+), 128 deletions(-) create mode 100644 rts/closure-table.c create mode 100644 test/run-stub/free-callbacks.mo create mode 100644 test/run-stub/ok/free-callbacks.ic-stub-run.ok diff --git a/rts/Makefile b/rts/Makefile index 9aa92964fc6..3a8ebaec451 100644 --- a/rts/Makefile +++ b/rts/Makefile @@ -81,7 +81,7 @@ TOMMATH_NATIVE_O=$(TOMMATHFILES:%=_build/native/tommath_%.o) # Our part of the RTS, Wasm and native # -RTSFILES=rts idl bigint buf utf8_valid +RTSFILES=rts idl bigint buf utf8_valid closure-table _build/wasm/%.o: %.c rts.h buf.h | _build/wasm $(WASM_CLANG) -c $(CLANG_FLAGS) $(WASM_FLAGS) $(TOMMATH_FLAGS) -I$(TOMMATHSRC) --std=c11 $< --output $@ diff --git a/rts/closure-table.c b/rts/closure-table.c new file mode 100644 index 00000000000..cadd3fe7f93 --- /dev/null +++ b/rts/closure-table.c @@ -0,0 +1,109 @@ +#include "rts.h" + +/* +This file implements the data structure the Motoko runtime uses to keep track of outstanding closures. It needs to support the following operations + + 1. Adding a closure (any heap pointer) and getting an index (i32) + 2. Looking up a closure by index, which also frees it + 3. GC must traverse all closures, and possibly move the table + 4. Obtain number of closures registered + 5. Obtain size of table + +This stores the closures in a normal, heap-allocated, Motoko array. This means +3. is simple: just traverse this array in GC as normal. + +To efficiently look up the next free things, we use an implicit free list: +`free_slot` is the index (shifted 2 bit to the left) into the array payload of +the next free item. Each free item contains the index of another free item. +The last free slot is marked as (-1 << 2). + +We shift these 2 bit to the left so that GC treats them as scalars, not as +pointers. It also means they can be used as a byte offset, but that is more +cute than actually important. + +When the table is full, we double the size, copy the existing table, and add the +second half to the free list. Since all indices are relative to the payload +begin, they stay valid. We never shrink the table. +*/ + +#define FULL ((uint32_t)(-1) << 2) +#define INITIAL_SIZE 256 + +// Skewed pointer to the Array object +static as_ptr table = 0; +// counter of allocated things +static uint32_t n_closures = 0; +// next free +static uint32_t free_slot = FULL; + +static as_ptr alloc_array(uint32_t len) { + as_ptr a = alloc_words(ARRAY_HEADER_SIZE + len); + TAG(a) = TAG_ARRAY; + ARRAY_LEN(a) = len; + return a; +} + +static void create_closure_table() { + table = alloc_array(INITIAL_SIZE); + free_slot = 0; + for (uint32_t i = 0; i+1 < INITIAL_SIZE; i++) { + ARRAY_FIELD(table, i) = (i+1) << 2; + } + ARRAY_FIELD(table, INITIAL_SIZE - 1) = FULL; +} + +static void double_closure_table() { + uint32_t old_size = ARRAY_LEN(table); + as_ptr old = table; + as_ptr new = alloc_array(2*old_size); + for (uint32_t i = 0; i < old_size; i++) { + ARRAY_FIELD(new, i) = ARRAY_FIELD(old, i); + } + for (uint32_t i = old_size; i+1 < 2*old_size; i++) { + ARRAY_FIELD(new, i) = (i+1)<<2; + } + ARRAY_FIELD(new, 2*old_size - 1) = free_slot; + free_slot = old_size << 2; + table = new; +} + +export uint32_t remember_closure(as_ptr cls) { + if (table == 0) + create_closure_table(); + else if (free_slot == FULL) + double_closure_table(); + + uint32_t idx = free_slot >> 2; + free_slot = ARRAY_FIELD(table, idx); + ARRAY_FIELD(table, idx) = cls; + n_closures++; + return idx; +} + +export as_ptr recall_closure(uint32_t idx) { + if (table == 0) + rts_trap_with("recall_closure: No closure table allocated"); + if (idx >= ARRAY_LEN(table)) + rts_trap_with("recall_closure: Closure index out of range"); + + as_ptr cls = ARRAY_FIELD(table, idx); + ARRAY_FIELD(table, idx) = free_slot; + free_slot = idx << 2; + n_closures--; + return cls; +} + +export uint32_t closure_count() { + return n_closures; +} + +export as_ptr closure_table_loc() { + return SKEW(&table); +} + +export as_ptr closure_table_size() { + if (table == 0) + return 0; + else + return ARRAY_LEN(table); +} diff --git a/rts/rts.c b/rts/rts.c index 2f2ba743ab2..15ea2ffe724 100644 --- a/rts/rts.c +++ b/rts/rts.c @@ -29,15 +29,22 @@ as_ptr as_str_of_cstr(const char * const s) { return r; } -void idl_trap_with(const char *str) { - const char prefix[] = "IDL error: "; - int len = as_strlen(str); - char msg[sizeof prefix + len]; - as_memcpy(msg, prefix, sizeof prefix - 1); - as_memcpy(msg + sizeof prefix - 1, str, len); - idl_trap(msg, sizeof prefix - 1 + len); +void __attribute__ ((noreturn)) trap_with_prefix(const char* prefix, const char *str) { + int len1 = as_strlen(prefix); + int len2 = as_strlen(str); + char msg[len1 + len2]; + as_memcpy(msg, prefix, len1); + as_memcpy(msg + len1, str, len2); + rts_trap(msg, len1 + len2); } +void __attribute__ ((noreturn)) idl_trap_with(const char *str) { + trap_with_prefix("IDL error: ", str); +} + +void __attribute__ ((noreturn)) rts_trap_with(const char *str) { + trap_with_prefix("RTS error: ", str); +} // This is mostly to test static strings and access to the AS heap const char* RTS_VERSION = "0.1"; @@ -77,4 +84,3 @@ export void sleb128_encode(int32_t n, unsigned char *buf) { } } } - diff --git a/rts/rts.h b/rts/rts.h index 8f19b419577..632b05092c5 100644 --- a/rts/rts.h +++ b/rts/rts.h @@ -13,12 +13,21 @@ /* Motoko pointers are offset by one. So let us represent them as a typedef, and access the fields using the payload macro. + +Note that for the purpose of ./test_rts, this needs to be 64 bit safe. So do +_not_ encode that a word is 4 bytes! */ typedef intptr_t as_ptr; -#define FIELD(p,n) (((size_t *)(p+1))[n]) +#define SKEW(p) ((as_ptr)p-1) +#define UNSKEW(p) ((size_t *)((as_ptr)p+1)) +#define FIELD(p,n) (UNSKEW(p)[n]) #define TAG(p) FIELD(p,0) -#define TEXT_LEN(p) ((char *)(&FIELD(p,1))) -#define TEXT_PAYLOAD(p) ((char *)(&FIELD(p,2))) +#define TEXT_LEN(p) (FIELD(p,1)) +#define TEXT_PAYLOAD(p) ((uint8_t *)(&FIELD(p,2))) + +#define ARRAY_LEN(p) (FIELD(p,1)) +#define ARRAY_HEADER_SIZE 2 +#define ARRAY_FIELD(p,n) (FIELD(p,ARRAY_HEADER_SIZE+n)) /* Heap tags. Needs to stay in sync with compile.ml */ enum as_heap_tag { @@ -57,16 +66,18 @@ So in order to allocate on the Motoko heap from C, we import alloc_bytes from the Motoko RTS: */ from_rts as_ptr alloc_bytes(size_t n); +from_rts as_ptr alloc_words(size_t n); char *alloc(size_t n); /* IDL code */ /*@ assigns \nothing; ensures \false ; */ -from_rts __attribute__ ((noreturn)) void idl_trap(const char* str, size_t n); +from_rts __attribute__ ((noreturn)) void rts_trap(const char* str, size_t n); from_rts __attribute__ ((noreturn)) void bigint_trap(); /** Functions used in multiple modules of the RTS */ export void as_memcpy(char *str1, const char *str2, size_t n); export __attribute__ ((noreturn)) void idl_trap_with(const char *str1); +export __attribute__ ((noreturn)) void rts_trap_with(const char *str1); #endif /* RTS_H */ diff --git a/rts/test_leb128.c b/rts/test_leb128.c index 9f1e65c19cc..770f3dbcfe7 100644 --- a/rts/test_leb128.c +++ b/rts/test_leb128.c @@ -14,9 +14,12 @@ as_ptr alloc_bytes(size_t n) { if (ptr == NULL) { printf("OOM\n"); exit(1); }; return ((as_ptr)ptr) - 1; }; +as_ptr alloc_words(size_t n) { + return alloc_bytes(sizeof(uint32_t) * n); +}; -void idl_trap() { - printf("IDL trap\n"); +void rts_trap() { + printf("RTS trap\n"); abort(); } void bigint_trap() { diff --git a/rts/test_rts.c b/rts/test_rts.c index 41cd39c9e47..2ee59b9b5de 100644 --- a/rts/test_rts.c +++ b/rts/test_rts.c @@ -3,34 +3,54 @@ #include #include #include +#include typedef intptr_t as_ptr; + as_ptr alloc_bytes(size_t n) { void *ptr = malloc(n); if (ptr == NULL) { printf("OOM\n"); exit(1); }; return ((as_ptr)ptr) - 1; }; +as_ptr alloc_words(size_t n) { + return alloc_bytes(sizeof(size_t) * n); +}; -void idl_trap() { - printf("IDL trap\n"); - exit(1); +void rts_trap() { + printf("RTS trap\n"); + abort(); } void bigint_trap() { printf("Bigint trap\n"); exit(1); } -extern as_ptr bigint_of_word32(uint32_t b); -extern as_ptr bigint_mul(as_ptr a, as_ptr b); -extern as_ptr bigint_pow(as_ptr a, as_ptr b); -extern bool bigint_eq(as_ptr a, as_ptr b); +int ret = EXIT_SUCCESS; +void assert(bool check, const char *fmt, ...) { + if (!check) { + ret = EXIT_FAILURE; + va_list args; + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); + } +} int main () { printf("Motoko RTS test suite\n"); - int ret = EXIT_SUCCESS; + + /* + * Testing BigInt + */ + printf("Testing BigInt...\n"); + + extern as_ptr bigint_of_word32(uint32_t b); + extern as_ptr bigint_mul(as_ptr a, as_ptr b); + extern as_ptr bigint_pow(as_ptr a, as_ptr b); + extern bool bigint_eq(as_ptr a, as_ptr b); printf("70**32 = 70**31 * 70: %s\n", bigint_eq( @@ -40,6 +60,10 @@ int main () { bigint_of_word32(70) )) ? "ok" : (ret = EXIT_FAILURE, "not ok")); + /* + * Testing UTF8 + */ + printf("Testing UTF8...\n"); extern bool utf8_valid(const char*, size_t); const int cases = 33; @@ -95,10 +119,42 @@ int main () { for (int i = 0; i < cases; ++i) { bool invalid = i > 0; - printf("%svalid UTF-8 test #%d: %s\n", - invalid ? "in" : "", - i + 1, - invalid != utf8_valid(utf8_inputs[i], strlen(utf8_inputs[i])) ? "ok" : (ret = EXIT_FAILURE, "not ok")); + assert( invalid != utf8_valid(utf8_inputs[i], strlen(utf8_inputs[i])), + "%svalid UTF-8 test #%d failed\n", invalid ? "in" : "", i + 1); + } + + /* + * Testing the closure table + */ + printf("Testing Closuretable ...\n"); + + extern uint32_t remember_closure(as_ptr cls); + extern uint32_t recall_closure(as_ptr cls); + extern uint32_t closure_count(); + + static int N = 2000; // >256, to exercise double_closure_table() + // We remember and recall a bunch of closures, + // and compare against a reference array. + uint32_t reference[N]; + if (closure_count() != 0) { + printf("Initial count wrong\n"); + ret = EXIT_FAILURE; + } + for (int i = 0; i=0; i--) { + assert(reference[i] == recall_closure(i),"Recall went wrong\n"); + assert(closure_count() == i, "Closure count wrong\n"); } return ret; diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index cbccabd280a..673e84e569c 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -499,7 +499,7 @@ let from_0_to_n env mk_body = let load_unskewed_ptr : G.t = G.i (Load {ty = I32Type; align = 2; offset = 0l; sz = None}) -let store_unskewed_ptr : G.t = +let _store_unskewed_ptr : G.t = G.i (Store {ty = I32Type; align = 2; offset = 0l; sz = None}) let load_ptr : G.t = @@ -645,7 +645,13 @@ module RTS = struct E.add_func_import env "rts" "skip_leb128" [I32Type] []; E.add_func_import env "rts" "skip_any" [I32Type; I32Type; I32Type; I32Type] []; E.add_func_import env "rts" "find_field" [I32Type; I32Type; I32Type; I32Type; I32Type] [I32Type]; - E.add_func_import env "rts" "skip_fields" [I32Type; I32Type; I32Type; I32Type] [] + E.add_func_import env "rts" "skip_fields" [I32Type; I32Type; I32Type; I32Type] []; + E.add_func_import env "rts" "remember_closure" [I32Type] [I32Type]; + E.add_func_import env "rts" "recall_closure" [I32Type] [I32Type]; + E.add_func_import env "rts" "closure_count" [] [I32Type]; + E.add_func_import env "rts" "closure_table_loc" [] [I32Type]; + E.add_func_import env "rts" "closure_table_size" [] [I32Type]; + () end (* RTS *) @@ -851,68 +857,12 @@ module Stack = struct end (* Stack *) module ClosureTable = struct - (* - Another fixed-size table at the beginning of memory: When we create a closure - that is bound to a callback that we pass out, we need this level of indirection for - two reasons: - - we cannot just bind the address via i32.bind, because that is not stable, due - to our moving GC, and - - we need to remember that these closures are roots (and currently never freed!) - - Therefore we maintain a static table from closure index to address of the closure - on the heap. - *) - - let max_entries = 1024l - let loc = Stack.end_of_stack - let table_end = Int32.(add loc (mul max_entries Heap.word_size)) - - (* For reasons I do not recall, we use the first word of the table as the counter, - and not a global. - *) - let get_counter = compile_unboxed_const loc ^^ load_unskewed_ptr - - (* Assumes a reference on the stack, and replaces it with an index into the - reference table *) - let remember_closure env : G.t = - Func.share_code1 env "remember_closure" ("ptr", I32Type) [I32Type] (fun env get_ptr -> - (* Check table space *) - get_counter ^^ - compile_unboxed_const (Int32.sub max_entries 1l) ^^ - G.i (Compare (Wasm.Values.I32 I64Op.LtU)) ^^ - E.else_trap_with env "Closure table full" ^^ - - (* Return index *) - get_counter ^^ - compile_add_const 1l ^^ - - (* Store reference *) - get_counter ^^ - compile_add_const 1l ^^ - compile_mul_const Heap.word_size ^^ - compile_add_const loc ^^ - get_ptr ^^ - store_unskewed_ptr ^^ - - (* Bump counter *) - compile_unboxed_const loc ^^ - get_counter ^^ - compile_add_const 1l ^^ - store_unskewed_ptr - ) - - (* Assumes a index into the table on the stack, and replaces it with a ptr to the closure *) - let recall_closure env : G.t = - Func.share_code1 env "recall_closure" ("closure_idx", I32Type) [I32Type] (fun env get_closure_idx -> - get_closure_idx ^^ - compile_mul_const Heap.word_size ^^ - compile_add_const loc ^^ - load_unskewed_ptr - ) - - let get_outstanding_callbacks env = - get_counter - + (* See rts/closure-table.c *) + let remember env : G.t = E.call_import env "rts" "remember_closure" + let recall env : G.t = E.call_import env "rts" "recall_closure" + let count env : G.t = E.call_import env "rts" "closure_count" + let size env : G.t = E.call_import env "rts" "closure_table_size" + let root env : G.t = E.call_import env "rts" "closure_table_loc" end (* ClosureTable *) module Bool = struct @@ -3175,6 +3125,10 @@ module RTS_Exports = struct name = Wasm.Utf8.decode "alloc_bytes"; edesc = nr (FuncExport (nr (E.built_in env "alloc_bytes"))) }); + E.add_export env (nr { + name = Wasm.Utf8.decode "alloc_words"; + edesc = nr (FuncExport (nr (E.built_in env "alloc_words"))) + }); let bigint_trap_fi = E.add_fun env "bigint_trap" ( Func.of_body env [] [] (fun env -> E.trap_with env "bigint function error" @@ -3184,7 +3138,7 @@ module RTS_Exports = struct name = Wasm.Utf8.decode "bigint_trap"; edesc = nr (FuncExport (nr bigint_trap_fi)) }); - let idl_trap_fi = E.add_fun env "idl_trap" ( + let rts_trap_fi = E.add_fun env "rts_trap" ( Func.of_body env ["str", I32Type; "len", I32Type] [] (fun env -> let get_str = G.i (LocalGet (nr 0l)) in let get_len = G.i (LocalGet (nr 1l)) in @@ -3193,8 +3147,8 @@ module RTS_Exports = struct ) ) in E.add_export env (nr { - name = Wasm.Utf8.decode "idl_trap"; - edesc = nr (FuncExport (nr idl_trap_fi)) + name = Wasm.Utf8.decode "rts_trap"; + edesc = nr (FuncExport (nr rts_trap_fi)) }) end (* RTS_Exports *) @@ -4320,16 +4274,9 @@ module GC = struct set_end_to_space in (* Go through the roots, and evacuate them *) - ClosureTable.get_counter ^^ - from_0_to_n env (fun get_i -> evac ( - get_i ^^ - compile_add_const 1l ^^ - compile_mul_const Heap.word_size ^^ - compile_add_const ClosureTable.loc ^^ - compile_add_const ptr_skew - )) ^^ + evac (ClosureTable.root env) ^^ HeapTraversal.walk_heap_from_to env - (compile_unboxed_const Int32.(add ClosureTable.table_end ptr_skew)) + (compile_unboxed_const Int32.(add Stack.end_of_stack ptr_skew)) (compile_unboxed_const Int32.(add end_of_static_space ptr_skew)) (fun get_x -> HeapTraversal.for_each_pointer env get_x evac evac_offset) ^^ @@ -4848,7 +4795,7 @@ module FuncDec = struct let sr, code = lit env ae "anon_async" Type.Local Type.Returns free_vars [] mk_body [] at in code ^^ StackRep.adjust env sr SR.Vanilla ^^ - ClosureTable.remember_closure env + ClosureTable.remember env (* Wraps a local closure in a local function that does serialization and takes care of the environment *) @@ -4860,7 +4807,7 @@ module FuncDec = struct (* Look up closure *) let (set_closure, get_closure) = new_local env "closure" in G.i (LocalGet (nr 0l)) ^^ - ClosureTable.recall_closure env ^^ (* At this point we can remove the closure *) + ClosureTable.recall env ^^ (* At this point we can remove the closure *) set_closure ^^ get_closure ^^ @@ -4873,7 +4820,7 @@ module FuncDec = struct message_cleanup env (Type.Shared Type.Write) ); compile_unboxed_const (E.built_in env name) ^^ - get_closure ^^ ClosureTable.remember_closure env + get_closure ^^ ClosureTable.remember env let closure_to_reject_callback env get_closure = assert (E.mode env = Flags.StubMode); @@ -4882,7 +4829,7 @@ module FuncDec = struct (* Look up closure *) let (set_closure, get_closure) = new_local env "closure" in G.i (LocalGet (nr 0l)) ^^ - ClosureTable.recall_closure env ^^ (* At this point we can remove the closure *) + ClosureTable.recall env ^^ (* At this point we can remove the closure *) set_closure ^^ get_closure ^^ @@ -4895,7 +4842,7 @@ module FuncDec = struct message_cleanup env (Type.Shared Type.Write) ); compile_unboxed_const (E.built_in env name) ^^ - get_closure ^^ ClosureTable.remember_closure env + get_closure ^^ ClosureTable.remember env let ignoring_callback env = assert (E.mode env = Flags.StubMode); @@ -4957,7 +4904,7 @@ module FuncDec = struct (* Deserialize and look up closure argument *) Serialization.deserialize env [Type.Prim Type.Word32] ^^ BoxedSmallWord.unbox env ^^ - ClosureTable.recall_closure env ^^ + ClosureTable.recall env ^^ set_closure ^^ get_closure ^^ get_closure ^^ Closure.call_closure env 0 0 ^^ message_cleanup env (Type.Shared Type.Write) @@ -6110,9 +6057,13 @@ and compile_exp (env : E.t) ae exp = SR.Vanilla, Heap.get_total_allocation env ^^ BigNum.from_word64 env - | OtherPrim "rts_outstanding_callbacks", [] -> + | OtherPrim "rts_callback_table_count", [] -> + SR.Vanilla, + ClosureTable.count env ^^ Prim.prim_word32toNat env + + | OtherPrim "rts_callback_table_size", [] -> SR.Vanilla, - ClosureTable.get_outstanding_callbacks env ^^ Prim.prim_word32toNat env + ClosureTable.size env ^^ Prim.prim_word32toNat env | OtherPrim "idlHash", [e] -> @@ -6839,7 +6790,7 @@ and actor_lit outer_env this ds fs at = (E.get_rts outer_env) (E.get_prelude outer_env) (E.get_trap_with outer_env) - ClosureTable.table_end in + Stack.end_of_stack in Heap.register_globals mod_env; Stack.register_globals mod_env; @@ -6997,7 +6948,7 @@ and conclude_module env module_name start_fi_o = | Some rts -> Linking.LinkModule.link emodule "rts" rts let compile mode module_name rts (prelude : Ir.prog) (progs : Ir.prog list) : Wasm_exts.CustomModule.extended_module = - let env = E.mk_global mode rts prelude Dfinity.trap_with ClosureTable.table_end in + let env = E.mk_global mode rts prelude Dfinity.trap_with Stack.end_of_stack in Heap.register_globals env; Stack.register_globals env; diff --git a/src/prelude/prelude.ml b/src/prelude/prelude.ml index 601b9792990..d8f8e8170be 100644 --- a/src/prelude/prelude.ml +++ b/src/prelude/prelude.ml @@ -90,7 +90,8 @@ func debugPrintChar(x : Char) { debugPrint (charToText x) }; func rts_version() : Text { (prim "rts_version" : () -> Text) () }; func rts_heap_size() : Nat { (prim "rts_heap_size" : () -> Nat) () }; func rts_total_allocation() : Nat { (prim "rts_total_allocation" : () -> Nat) () }; -func rts_outstanding_callbacks() : Nat { (prim "rts_outstanding_callbacks" : () -> Nat) () }; +func rts_callback_table_count() : Nat { (prim "rts_callback_table_count" : () -> Nat) () }; +func rts_callback_table_size() : Nat { (prim "rts_callback_table_size" : () -> Nat) () }; // Hashing func hashInt(x : Int) : Word32 { diff --git a/test/run-stub/count-callbacks.mo b/test/run-stub/count-callbacks.mo index 923c90c53a5..7773954c306 100644 --- a/test/run-stub/count-callbacks.mo +++ b/test/run-stub/count-callbacks.mo @@ -1,28 +1,28 @@ actor a { public func ping() : async () { - debugPrint("ping! " # debug_show rts_outstanding_callbacks()); + debugPrint("ping! " # debug_show rts_callback_table_count()); }; public func go() = ignore async { - debugPrint("go 1: " # debug_show rts_outstanding_callbacks()); + debugPrint("go 1: " # debug_show rts_callback_table_count()); let a1 = ping(); - debugPrint("go 1: " # debug_show rts_outstanding_callbacks()); + debugPrint("go 1: " # debug_show rts_callback_table_count()); let a2 = ping(); - debugPrint("go 1: " # debug_show rts_outstanding_callbacks()); + debugPrint("go 1: " # debug_show rts_callback_table_count()); let a3 = ping(); - debugPrint("go 1: " # debug_show rts_outstanding_callbacks()); + debugPrint("go 1: " # debug_show rts_callback_table_count()); let a4 = ping(); - debugPrint("go 1: " # debug_show rts_outstanding_callbacks()); + debugPrint("go 1: " # debug_show rts_callback_table_count()); await a1; - debugPrint("go 2: " # debug_show rts_outstanding_callbacks()); + debugPrint("go 2: " # debug_show rts_callback_table_count()); await a2; - debugPrint("go 3: " # debug_show rts_outstanding_callbacks()); + debugPrint("go 3: " # debug_show rts_callback_table_count()); await a3; - debugPrint("go 4: " # debug_show rts_outstanding_callbacks()); + debugPrint("go 4: " # debug_show rts_callback_table_count()); await a4; - debugPrint("go 5: " # debug_show rts_outstanding_callbacks()); + debugPrint("go 5: " # debug_show rts_callback_table_count()); }; go(); diff --git a/test/run-stub/free-callbacks.mo b/test/run-stub/free-callbacks.mo new file mode 100644 index 00000000000..0858e54c352 --- /dev/null +++ b/test/run-stub/free-callbacks.mo @@ -0,0 +1,38 @@ +actor a { + + public func ping() : async () { + }; + + public func go() = ignore async { + let s0 = rts_heap_size(); + let a = Array_init<()>(2500, ()); + await ping(); + let s1 = rts_heap_size(); + await ping(); + let s2 = rts_heap_size(); + // last use of a + ignore(a); + await ping(); + // now a should be freed + let s3 = rts_heap_size(); + + debugPrint( + "Ignore Diff: " # + debug_show s0 # " " # + debug_show s1 # " " # + debug_show s2 # " " # + debug_show s3 # " " + ); + // This checks that the array (10_000 bytes) has been allocated, but then + // freed. It allows for some wiggle room + assert (s1-s0 > 5_000); + assert (s2-s0 > 5_000); + assert (s3-s0 < 5_000); + }; + + go(); +} + +//SKIP run +//SKIP run-low +//SKIP run-ir diff --git a/test/run-stub/ok/count-callbacks.ic-stub-run.ok b/test/run-stub/ok/count-callbacks.ic-stub-run.ok index 8703025cdf0..27667f29e5c 100644 --- a/test/run-stub/ok/count-callbacks.ic-stub-run.ok +++ b/test/run-stub/ok/count-callbacks.ic-stub-run.ok @@ -10,8 +10,8 @@ ping! 8 ping! 8 ping! 8 ping! 8 -go 2: 8 -go 3: 8 -go 4: 8 -go 5: 8 +go 2: 7 +go 3: 6 +go 4: 5 +go 5: 4 ← completed diff --git a/test/run-stub/ok/free-callbacks.ic-stub-run.ok b/test/run-stub/ok/free-callbacks.ic-stub-run.ok new file mode 100644 index 00000000000..606daecf164 --- /dev/null +++ b/test/run-stub/ok/free-callbacks.ic-stub-run.ok @@ -0,0 +1,5 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +Ignore Diff: (ignored) +← completed diff --git a/test/run.sh b/test/run.sh index f50e9ecf7bc..79b15a90705 100755 --- a/test/run.sh +++ b/test/run.sh @@ -90,6 +90,7 @@ function normalize () { sed 's/^.*run-dfinity\/\.\.\/drun.sh: line/drun.sh: line/g' | sed 's/trap at 0x[a-f0-9]*/trap at 0x___:/g' | sed 's/source location: @[a-f0-9]*/source location: @___:/g' | + sed 's/Ignore Diff:.*/Ignore Diff: (ignored)/ig' | cat > $1.norm mv $1.norm $1 fi From 1cef148d932a8abee6be98b1f4aa9586cbcf94cc Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Thu, 28 Nov 2019 11:24:51 +0000 Subject: [PATCH 0729/1176] sugar types when pretty printing --- src/lowering/desugar.ml | 16 ++++++---- src/mo_def/arrange.ml | 6 +++- src/mo_def/syntax.ml | 4 ++- src/mo_frontend/parser.mly | 3 +- src/mo_frontend/typing.ml | 23 ++++++++------ src/mo_types/type.ml | 65 ++++++++++++++++++++++++++++++++------ 6 files changed, 89 insertions(+), 28 deletions(-) diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 5bb21716280..1de65c695a7 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -108,12 +108,16 @@ and exp' at note = function | S.CallE ({it=S.AnnotE ({it=S.PrimE p;_},_);_}, _, e) -> I.PrimE (I.OtherPrim p, [exp e]) | S.CallE (e1, inst, e2) -> - let t = e1.Source.note.S.note_typ in - if T.is_non t - then unreachableE.it - else - let inst = List.map (fun t -> t.Source.note) (!inst) in - I.CallE (exp e1, inst, exp e2) + begin + match !inst with + | None -> assert false + | Some typs -> + let t = e1.Source.note.S.note_typ in + let ts = List.map (fun t -> t.Source.note) typs in + if T.is_non t + then unreachableE.it (* BUG?, why should we discard the code for e1 just because e1 has type non (Issue #945) *) + else I.CallE (exp e1, ts, exp e2) + end | S.BlockE [] -> I.TupE [] | S.BlockE [{it = S.ExpD e; _}] -> (exp e).it | S.BlockE ds -> I.BlockE (block (T.is_unit note.I.note_typ) ds) diff --git a/src/mo_def/arrange.ml b/src/mo_def/arrange.ml index cd19293b289..037f1c0a043 100644 --- a/src/mo_def/arrange.ml +++ b/src/mo_def/arrange.ml @@ -34,7 +34,7 @@ let rec exp e = match e.it with (match t with None -> Atom "_" | Some t -> typ t); exp e' ] - | CallE (e1, tsr, e2) -> "CallE" $$ [exp e1] @ List.map typ (!tsr) @ [exp e2] + | CallE (e1, ts_opt_ref, e2) -> "CallE" $$ [exp e1] @ inst ts_opt_ref @ [exp e2] | BlockE ds -> "BlockE" $$ List.map dec ds | NotE e -> "NotE" $$ [exp e] | AndE (e1, e2) -> "AndE" $$ [exp e1; exp e2] @@ -60,6 +60,10 @@ let rec exp e = match e.it with | ThrowE e -> "ThrowE" $$ [exp e] | TryE (e, cs) -> "TryE" $$ [exp e] @ List.map catch cs +and inst ts_opt_ref = match !ts_opt_ref with + | None -> [Atom ("?")] + | Some ts -> List.map typ ts + and pat p = match p.it with | WildP -> Atom "WildP" | VarP x -> "VarP" $$ [id x] diff --git a/src/mo_def/syntax.ml b/src/mo_def/syntax.ml index bbc07407604..e41bf418661 100644 --- a/src/mo_def/syntax.ml +++ b/src/mo_def/syntax.ml @@ -108,6 +108,8 @@ and vis' = Public | Private type op_typ = Type.typ ref (* For overloaded resolution; initially Type.Pre. *) +type inst = typ list option ref (* For implicit scope instantiation *) + type exp = (exp', typ_note) Source.annotated_phrase and exp' = | PrimE of string (* primitive *) @@ -127,7 +129,7 @@ and exp' = | ArrayE of mut * exp list (* array *) | IdxE of exp * exp (* array indexing *) | FuncE of string * func_sort * typ_bind list * pat * typ option * exp (* function *) - | CallE of exp * typ list ref * exp (* function call *) + | CallE of exp * inst * exp (* function call *) | BlockE of dec list (* block (with type after avoidance)*) | NotE of exp (* negation *) | AndE of exp * exp (* conjunction *) diff --git a/src/mo_frontend/parser.mly b/src/mo_frontend/parser.mly index ce683dfe2a9..7067e2192d7 100644 --- a/src/mo_frontend/parser.mly +++ b/src/mo_frontend/parser.mly @@ -435,8 +435,7 @@ exp_post(B) : | e=exp_post(ob) DOT x=id { DotE(e, x) @? at $sloc } | e1=exp_post(ob) tso=typ_args? e2=exp_nullary(ob) - { let typ_args = Lib.Option.get tso [] in - CallE(e1, ref typ_args, e2) @? at $sloc } + { CallE(e1, ref tso, e2) @? at $sloc } exp_un(B) : | e=exp_post(B) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 5d640c440a8..fd89b63da5c 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -770,24 +770,29 @@ and infer_exp'' env exp : T.typ = let ts1 = match pat.it with TupP _ -> T.seq_of_tup t1 | _ -> [t1] in let tbs = List.map2 (fun c t -> {T.var = Con.name c; bound = T.close cs t}) cs ts in T.Func (sort.it, T.map_control (T.close cs) c, tbs, List.map (T.close cs) ts1, List.map (T.close cs) ts2) - | CallE (exp1, insts_ref, exp2) -> - let insts = !insts_ref in + | CallE (exp1, insts, exp2) -> + let n_insts = match !insts with + | Some ts -> List.length ts + | None -> 0 + in let t1 = infer_exp_promote env exp1 in let sort, tbs, t_arg, t_ret = - try T.as_func_sub T.Local (List.length insts) t1 + try T.as_func_sub T.Local n_insts t1 with Invalid_argument _ -> error env exp1.at "expected function type, but expression produces type\n %s" (T.string_of_typ_expand t1) in - let insts = match insts, t1 with - | [], T.Func(_,T.Promises (T.Var (_,0)),[_],_,_) - | [], T.Func(_,T.Returns,[_],_,[T.Async (T.Var (_,0),_)]) -> + (* only attempt scope inference when no inst, not empty inst (`<>`), provided *) + let typs = match !insts, t1 with + | None, T.Func(_,T.Promises (T.Var (_,0)),[_],_,_) + | None, T.Func(_,T.Returns,[_],_,[T.Async (T.Var (_,0),_)]) -> [Syntax.scope_typ {left=exp1.at.right; right = exp2.at.left}] - | _ -> insts + | None, _ -> [] + | Some typs, _ -> typs in - insts_ref := insts; - let ts = check_inst_bounds env tbs insts exp.at in + insts := Some typs; + let ts = check_inst_bounds env tbs typs exp.at in let t_arg = T.open_ ts t_arg in let t_ret = T.open_ ts t_ret in if not env.pre then begin diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index 526ac02c16b..934f89a04f6 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -1201,28 +1201,75 @@ and string_of_cod vs ts = | [Tup _] -> sprintf "(%s)" cod | _ -> cod -and string_of_control_cod c vs ts = - let cod = string_of_cod vs ts in - match c with - | Returns -> cod - | Promises t -> sprintf "async<%s> %s" (string_of_typ' vs t) cod - | Replies -> sprintf "replies %s" cod +and string_of_control_cod sugar c vs ts = + match c,ts with + (* sugar *) + | Returns, [Async (_,t)] when sugar -> + sprintf "async %s" (string_of_typ' vs t) + | Promises _, ts when sugar -> + sprintf "async %s" (string_of_cod vs ts) + (* explicit *) + | Returns, _ -> string_of_cod vs ts + | Promises t, _ -> + sprintf "async<%s> %s" (string_of_typ' vs t) + (string_of_cod vs ts) + | Replies, _ -> sprintf "replies %s" (string_of_cod vs ts) + +and can_sugar t = match t with + | Func(s,Promises (Var(_,0)),[tb],ts1,ts2) -> + can_omit 0 tb.bound && + List.for_all (can_omit 0) ts1 && + List.for_all (can_omit 0) ts2 + | Func(s,Returns,[tb],ts1,([Async (Var(_,0),_)] as ts2)) -> + can_omit 0 tb.bound && + List.for_all (can_omit 0) ts1 && + List.for_all (can_omit 0) ts2 + | _ -> false + +and can_omit i t = + let rec go i t = + begin + match t with + | Var (_,j) -> i <> j + | Pre -> assert false + | Prim _ | Any | Non -> true + | Con (c, ts) -> List.for_all (go i ) ts + | Array t | Opt t | Mut t -> go i t + | Async (Var (_,0), t2) when i = 0 -> go i t2 (* t1 is a phantom type *) + | Async (t1, t2) -> go i t1 && go i t2 + | Tup ts -> List.for_all (go i ) ts + | Obj (_, fs) | Variant fs -> List.for_all (fun f -> go i f.typ) fs + | Func (s, c, tbs, ts1, ts2) -> + let i' = i+List.length tbs in + List.for_all (fun {var;bound} -> (go i' bound)) tbs && + List.for_all (go i') ts1 && + List.for_all (go i') ts2 + | Typ c -> assert false (* TBR *) + end + in go i t and string_of_typ' vs t = match t with + | Func (s, c, [tb], ts1, ts2) when can_sugar t -> + let vs' = ("",0)::vs in + sprintf "%s%s -> %s" (string_of_func_sort s) + (string_of_dom vs' ts1) + (string_of_control_cod true c vs' ts2) | Func (s, c, [], ts1, ts2) -> sprintf "%s%s -> %s" (string_of_func_sort s) (string_of_dom vs ts1) - (string_of_control_cod c vs ts2) + (string_of_control_cod false c vs ts2) | Func (s, c, tbs, ts1, ts2) -> let vs' = vars_of_binds vs tbs in sprintf "%s%s%s -> %s" (string_of_func_sort s) (string_of_binds (vs' @ vs) vs' tbs) - (string_of_dom (vs' @ vs) ts1) (string_of_control_cod c (vs' @ vs) ts2) + (string_of_dom (vs' @ vs) ts1) (string_of_control_cod false c (vs' @ vs) ts2) | Opt t -> sprintf "?%s" (string_of_typ_nullary vs t) | Async (t1, t2) -> - sprintf "async<%s> %s" (string_of_typ' vs t1) (string_of_typ_nullary vs t2) + (match t1, vs with + | Var(_,0), ("",_)::vs -> sprintf "async %s" (string_of_typ_nullary vs t2) + | _ -> sprintf "async<%s> %s" (string_of_typ' vs t1) (string_of_typ_nullary vs t2)) | Obj (s, fs) -> sprintf "%s%s" (string_of_obj_sort s) (string_of_typ_nullary vs (Obj (Object, fs))) | Typ c -> From fb93020b3d21419c386f109f4a1f97a76002089b Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 28 Nov 2019 16:05:25 +0100 Subject: [PATCH 0730/1176] Store reply and reject callbacks together in the table (#946) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit because when one is called, we want to free both. Note how now the count goes down to zero in the text: ```diff diff --git a/test/run-stub/ok/count-callbacks.ic-stub-run.ok b/test/run-stub/ok/count-callbacks.ic-stub-run.ok index 27667f29..2fbc3c6f 100644 --- a/test/run-stub/ok/count-callbacks.ic-stub-run.ok +++ b/test/run-stub/ok/count-callbacks.ic-stub-run.ok @@ -2,16 +2,16 @@ ← completed: canister-id = 0x0000000000000400 → install go 1: 0 +go 1: 1 go 1: 2 +go 1: 3 go 1: 4 -go 1: 6 -go 1: 8 -ping! 8 -ping! 8 -ping! 8 -ping! 8 -go 2: 7 -go 3: 6 -go 4: 5 -go 5: 4 +ping! 4 +ping! 4 +ping! 4 +ping! 4 +go 2: 3 +go 3: 2 +go 4: 1 +go 5: 0 ← completed ``` --- src/codegen/compile.ml | 64 ++++++++++++------- .../ok/count-callbacks.ic-stub-run.ok | 20 +++--- 2 files changed, 50 insertions(+), 34 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 673e84e569c..dd9306881df 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -2893,6 +2893,7 @@ module Tuple = struct G.table n (fun i -> get_tup ^^ load_n (Int32.of_int i)) ) end + end (* Tuple *) module Dfinity = struct @@ -4130,9 +4131,7 @@ module GC = struct Roots are: * All objects in the static part of the memory. - * all closures ever passed out as callback or to async_method - These therefore need to live in a separate area of memory - (could be mutable array of pointers, similar to the reference table) + * the closure_table (see module ClosureTable) *) let gc_enabled = true @@ -4797,17 +4796,26 @@ module FuncDec = struct StackRep.adjust env sr SR.Vanilla ^^ ClosureTable.remember env - (* Wraps a local closure in a local function that does serialization and - takes care of the environment *) - (* Need this function once per type, so we can share based on ts *) - let closure_to_reply_callback env ts get_closure = + (* Takes the reply and reject callbacks, tuples them up, + add them to the closure table, and returns the two callbacks expected by + call_simple. + + The tupling is necesary because we want to free _both_ closures when + one is called. + + The reply callback function exists once per type (it has to do + serialization); the reject callback function is unique. + *) + + let closures_to_reply_reject_callbacks env ts = assert (E.mode env = Flags.StubMode); - let name = "@callback<" ^ Serialization.typ_id (Type.Tup ts) ^ ">" in - Func.define_built_in env name ["env", I32Type] [] (fun env -> + let reply_name = "@callback<" ^ Serialization.typ_id (Type.Tup ts) ^ ">" in + Func.define_built_in env reply_name ["env", I32Type] [] (fun env -> (* Look up closure *) let (set_closure, get_closure) = new_local env "closure" in G.i (LocalGet (nr 0l)) ^^ - ClosureTable.recall env ^^ (* At this point we can remove the closure *) + ClosureTable.recall env ^^ + Arr.load_field 0l ^^ (* get the reply closure *) set_closure ^^ get_closure ^^ @@ -4819,21 +4827,18 @@ module FuncDec = struct message_cleanup env (Type.Shared Type.Write) ); - compile_unboxed_const (E.built_in env name) ^^ - get_closure ^^ ClosureTable.remember env - let closure_to_reject_callback env get_closure = - assert (E.mode env = Flags.StubMode); - let name = "@reject_callback" in - Func.define_built_in env name ["env", I32Type] [] (fun env -> + let reject_name = "@reject_callback" in + Func.define_built_in env reject_name ["env", I32Type] [] (fun env -> (* Look up closure *) let (set_closure, get_closure) = new_local env "closure" in G.i (LocalGet (nr 0l)) ^^ - ClosureTable.recall env ^^ (* At this point we can remove the closure *) + ClosureTable.recall env ^^ + Arr.load_field 1l ^^ (* get the reject closure *) set_closure ^^ get_closure ^^ - (* Synthesize reject *) + (* Synthesize value of type `Error` *) E.trap_with env "reject_callback" ^^ get_closure ^^ @@ -4841,8 +4846,21 @@ module FuncDec = struct message_cleanup env (Type.Shared Type.Write) ); - compile_unboxed_const (E.built_in env name) ^^ - get_closure ^^ ClosureTable.remember env + + (* The upper half of this function must not depend on the get_k and get_r + parameters, so hide them from above (cute trick) *) + fun get_k get_r -> + let (set_cb_index, get_cb_index) = new_local env "cb_index" in + (* store the tuple away *) + Arr.lit env [get_k; get_r] ^^ + ClosureTable.remember env ^^ + set_cb_index ^^ + + (* return arguments for the ic.call *) + compile_unboxed_const (E.built_in env reply_name) ^^ + get_cb_index ^^ + compile_unboxed_const (E.built_in env reject_name) ^^ + get_cb_index let ignoring_callback env = assert (E.mode env = Flags.StubMode); @@ -4858,10 +4876,8 @@ module FuncDec = struct get_meth_pair ^^ Arr.load_field 0l ^^ Blob.as_ptr_len env ^^ (* The method name *) get_meth_pair ^^ Arr.load_field 1l ^^ Blob.as_ptr_len env ^^ - (* The reply callback *) - closure_to_reply_callback env ts2 get_k ^^ - (* The reject callback *) - closure_to_reject_callback env get_r ^^ + (* The reply and reject callback *) + closures_to_reply_reject_callbacks env ts2 get_k get_r ^^ (* the data *) get_arg ^^ Serialization.serialize env ts1 ^^ (* done! *) diff --git a/test/run-stub/ok/count-callbacks.ic-stub-run.ok b/test/run-stub/ok/count-callbacks.ic-stub-run.ok index 27667f29e5c..2fbc3c6f057 100644 --- a/test/run-stub/ok/count-callbacks.ic-stub-run.ok +++ b/test/run-stub/ok/count-callbacks.ic-stub-run.ok @@ -2,16 +2,16 @@ ← completed: canister-id = 0x0000000000000400 → install go 1: 0 +go 1: 1 go 1: 2 +go 1: 3 go 1: 4 -go 1: 6 -go 1: 8 -ping! 8 -ping! 8 -ping! 8 -ping! 8 -go 2: 7 -go 3: 6 -go 4: 5 -go 5: 4 +ping! 4 +ping! 4 +ping! 4 +ping! 4 +go 2: 3 +go 3: 2 +go 4: 1 +go 5: 0 ← completed From 24b459bb7497fdff42e836e6a06e3d28f0425f55 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 28 Nov 2019 22:18:27 +0100 Subject: [PATCH 0731/1176] IDL Backend: Implement e(()) = null (#940) * IDL Backend: Implement e(()) = null this fixes #938 * Update test output --- src/codegen/compile.ml | 34 +++++++++++-------- test/run-drun/idl-shorthand.mo | 9 +++++ test/run-drun/ok/idl-field-escape.drun-run.ok | 4 +-- test/run-drun/ok/idl-shorthand.drun-run.ok | 2 ++ .../ok/idl-field-escape.ic-stub-run.ok | 4 +-- 5 files changed, 35 insertions(+), 18 deletions(-) create mode 100644 test/run-drun/idl-shorthand.mo create mode 100644 test/run-drun/ok/idl-shorthand.drun-run.ok diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index dd9306881df..77b0d17dfda 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -3358,7 +3358,7 @@ module Serialization = struct module TM = Map.Make (struct type t = Type.typ let compare = compare end) let to_idl_prim = let open Type in function - | Prim Null -> Some 1 + | Prim Null | Tup [] -> Some 1 | Prim Bool -> Some 2 | Prim Nat -> Some 3 | Prim Int -> Some 4 @@ -3532,6 +3532,9 @@ module Serialization = struct | Prim (Int32|Nat32|Word32|Char) -> inc_data_size (compile_unboxed_const 4l) | Prim (Int64|Nat64|Word64) -> inc_data_size (compile_unboxed_const 8l) | Prim Bool -> inc_data_size (compile_unboxed_const 1l) + | Prim Null -> G.nop + | Any -> G.nop + | Tup [] -> G.nop (* e(()) = null *) | Tup ts -> G.concat_mapi (fun i t -> get_x ^^ Tuple.load_n (Int32.of_int i) ^^ @@ -3554,8 +3557,6 @@ module Serialization = struct get_x ^^ Heap.load_field Blob.len_field ^^ set_len ^^ size_word env get_len ^^ inc_data_size get_len - | Prim Null -> G.nop - | Any -> G.nop | Opt t -> inc_data_size (compile_unboxed_const 1l) ^^ (* one byte tag *) get_x ^^ Opt.is_some env ^^ @@ -3661,6 +3662,8 @@ module Serialization = struct get_x ^^ G.i (Store {ty = I32Type; align = 0; offset = 0l; sz = Some Wasm.Memory.Pack8}) ^^ compile_unboxed_const 1l ^^ advance_data_buf + | Tup [] -> (* e(()) = null *) + G.nop | Tup ts -> G.concat_mapi (fun i t -> get_x ^^ Tuple.load_n (Int32.of_int i) ^^ @@ -3744,7 +3747,7 @@ module Serialization = struct compile_eq_const (Int32.of_int (- (Lib.Option.value (to_idl_prim t)))) in - let assert_prim_typ () = + let assert_prim_typ t = check_prim_typ t ^^ E.else_trap_with env ("IDL error: unexpected IDL type when parsing " ^ string_of_typ t) in @@ -3802,7 +3805,7 @@ module Serialization = struct begin match t with (* Primitive types *) | Prim Nat -> - assert_prim_typ () ^^ + assert_prim_typ t ^^ get_data_buf ^^ BigNum.compile_load_from_data_buf env false | Prim Int -> @@ -3814,36 +3817,36 @@ module Serialization = struct BigNum.compile_load_from_data_buf env false end begin - assert_prim_typ () ^^ + assert_prim_typ t ^^ get_data_buf ^^ BigNum.compile_load_from_data_buf env true end | Prim (Int64|Nat64|Word64) -> - assert_prim_typ () ^^ + assert_prim_typ t ^^ ReadBuf.read_word64 env get_data_buf ^^ BoxedWord64.box env | Prim (Int32|Nat32|Word32) -> - assert_prim_typ () ^^ + assert_prim_typ t ^^ ReadBuf.read_word32 env get_data_buf ^^ BoxedSmallWord.box env | Prim Char -> let set_n, get_n = new_local env "len" in - assert_prim_typ () ^^ + assert_prim_typ t ^^ ReadBuf.read_word32 env get_data_buf ^^ set_n ^^ UnboxedSmallWord.check_and_box_codepoint env get_n | Prim (Int16|Nat16|Word16) -> - assert_prim_typ () ^^ + assert_prim_typ t ^^ ReadBuf.read_word16 env get_data_buf ^^ UnboxedSmallWord.msb_adjust Word16 | Prim (Int8|Nat8|Word8) -> - assert_prim_typ () ^^ + assert_prim_typ t ^^ ReadBuf.read_byte env get_data_buf ^^ UnboxedSmallWord.msb_adjust Word8 | Prim Bool -> - assert_prim_typ () ^^ + assert_prim_typ t ^^ ReadBuf.read_byte env get_data_buf | Prim Null -> - assert_prim_typ () ^^ + assert_prim_typ t ^^ Opt.null | Any -> (* Skip values of any possible type *) @@ -3853,11 +3856,14 @@ module Serialization = struct (* Any vanilla value works here *) Opt.null | Prim Text -> - assert_prim_typ () ^^ + assert_prim_typ t ^^ read_blob true | Prim Blob -> assert_blob_typ env ^^ read_blob false + | Tup [] -> (* e(()) = null *) + assert_prim_typ t ^^ + Tuple.from_stack env 0 (* Composite types *) | Tup ts -> with_composite_typ (-20l) (fun get_typ_buf -> diff --git a/test/run-drun/idl-shorthand.mo b/test/run-drun/idl-shorthand.mo new file mode 100644 index 00000000000..23b4f5962b5 --- /dev/null +++ b/test/run-drun/idl-shorthand.mo @@ -0,0 +1,9 @@ +type Foo = { #nil; }; + +actor { + public query func foo(#nil) : async Foo { + #nil; + } +} + +//CALL query foo 0x4449444c016b01d1a7cf027f010000 diff --git a/test/run-drun/ok/idl-field-escape.drun-run.ok b/test/run-drun/ok/idl-field-escape.drun-run.ok index 2d425b83ef4..81c657b619a 100644 --- a/test/run-drun/ok/idl-field-escape.drun-run.ok +++ b/test/run-drun/ok/idl-field-escape.drun-run.ok @@ -1,5 +1,5 @@ ingress(0) System -ingress(1) Completed: Canister: Payload: 0x4449444c026c01868eb702016c000100 -ingress(2) Completed: Canister: Payload: 0x4449444c026c01868eb702016c000100 +ingress(1) Completed: Canister: Payload: 0x4449444c016c01868eb7027f0100 +ingress(2) Completed: Canister: Payload: 0x4449444c016c01868eb7027f0100 ingress(3) Completed: Canister: Payload: 0x4449444c016c03007c017dbcfef7b102710100ffff03802003585858 ingress(4) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-shorthand.drun-run.ok b/test/run-drun/ok/idl-shorthand.drun-run.ok new file mode 100644 index 00000000000..42c68e92e5e --- /dev/null +++ b/test/run-drun/ok/idl-shorthand.drun-run.ok @@ -0,0 +1,2 @@ +ingress(0) System +Ok: Payload: 0x4449444c016b01d1a7cf027f010000 diff --git a/test/run-stub/ok/idl-field-escape.ic-stub-run.ok b/test/run-stub/ok/idl-field-escape.ic-stub-run.ok index c56fd5f64d1..fa73a9cfd53 100644 --- a/test/run-stub/ok/idl-field-escape.ic-stub-run.ok +++ b/test/run-stub/ok/idl-field-escape.ic-stub-run.ok @@ -3,9 +3,9 @@ → install ← completed → update foo1(0x4449444c0000) -← completed: 0x4449444c026c01868eb702016c000100 +← completed: 0x4449444c016c01868eb7027f0100 → update foo2(0x4449444c0000) -← completed: 0x4449444c026c01868eb702016c000100 +← completed: 0x4449444c016c01868eb7027f0100 → update out(0x4449444c0000) ← completed: 0x4449444c016c03007c017dbcfef7b102710100ffff03802003585858 → update input(0x4449444c016c03007c017dbcfef7b102710100ffff03802003585858) From a1c18bb77c45703d6fb2d25127dfb89f11f109b5 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Thu, 28 Nov 2019 23:59:47 +0000 Subject: [PATCH 0732/1176] document design --- design/scoped-await.md | 81 ++++++-- src/mo_def/syntax.ml | 49 ++++- src/mo_frontend/parser.mly | 47 +---- src/mo_frontend/typing.ml | 11 +- test/fail/illegal-await.mo | 6 +- test/fail/ok/asyncret2.tc.ok | 2 +- test/run-drun/general_await.mo | 8 +- test/run-drun/general_await_implicit.mo | 54 +++--- test/run-drun/ok/general_await.run-ir.ok | 1 - test/run-drun/ok/general_await.run-low.ok | 1 - .../ok/general_await_implicit.run-ir.ok | 176 +++++------------- .../ok/general_await_implicit.run-low.ok | 176 +++++------------- test/run-stub/ok/general_await.ic-stub-run.ok | 2 + .../ok/scope-inference.ic-stub-run.ok | 4 + 14 files changed, 261 insertions(+), 357 deletions(-) create mode 100644 test/run-stub/ok/scope-inference.ic-stub-run.ok diff --git a/design/scoped-await.md b/design/scoped-await.md index 350a8fedc08..794d2747c3c 100644 --- a/design/scoped-await.md +++ b/design/scoped-await.md @@ -25,7 +25,7 @@ the current message and thus can only receive continuations (via `await`) from t current message. It can't receive continuations from an inner function by escaping into that function, since the inner function can at most await asyncs with its inner index, not the outer one. Thus the only -continations that are stored (including the ultimate reply +continuations that are stored (including the ultimate reply continuation), must be from the current function. _Please break it_ @@ -114,6 +114,9 @@ E; _ |- shared f(x:T) : async U { e; } ## Examples: +(These need fixing below but are all coded in [general_await.mo](../test/run-drun/general_await.mo) +[general_await_implicit.mo](../test/run-drun/general_await_implicit.mo) + Assuming the following requests: ``` @@ -186,8 +189,9 @@ shared func waitN(n:Nat) : async(List) { ### Deadlock Prevention: -#### Immediate deadlock +(These need fixing but are all correctly coded in [illegal-await.mo](../test/fail/illegal-await.mo) +#### Immediate deadlock ``` let t:asyncU = async{ await t;}; // bad await since t : Async[Any]U U @@ -232,28 +236,77 @@ shared func f() : async () { } ``` +## Sugar + +Principle: Desugaring should be: +* simple and unambiguous +* expressible in the syntax (as explicit binders and instantiations). +* avoidable (by supplying explicit binders and instantations). + +Basic idea: + +Prelude: +defines default scope (non-awaitable) and instantiation: +` +type @ = Any +` + +(`@` is a newly legal scope identifier) + +Parsing: + +* inserts `<@>` type instantations and binders for missing `async` binders and instantiations (in types and terms) and `async` binders (in terms) +* adds missing `<@>` bindings to async returning functions with absent quantifiers (note we distinguish missing type parameters from empty parameters `<>`) + +Elaboration: + +* Elaboration ensures `@` is bound to appropriate constructor, +shadowing any previous `@`-binding to ensure structured scoping. +* Elaboration adds missing instantiations to function applications that require them, guided by the synthesized function type. + +syntactic sugar (during parse, applied bottom up as we construct types and terms) -syntactic sugar: ``` -async typ := async<@> typ +async T := async<@> T +T1 -> async<@> T2 := <@>T1 -> async<@> T1 -(typ,...) -> async<@> typ -> := -<@>(typ,...) -> async<@> typ +func f() : async<@> T = e +func<@>f() : async<@> T = e -func f() : async<@> t = e -func<@>f() : async<@>t = e +func f() : async<@> T { e } := +func<@>f() : async<@> T = async<@> e <@> -func f() : async<@> t { e } :- -func<@>f() : async<@>t { e } :- +func f() : async<@> T { e } := +funcf() : async<@> T = async e <@> -x(pat) : async t {e} = x<@>(pat): async<@> t -x(pat) : async t = e = x<@>(pat): async<@> t +x(pat) : async<@> T {e} := x<@>(pat): async<@> T = async <@> e <@> +x(pat) : async<@> T := e = x<@>(pat): async<@> T = e async e := async<@> e <@> + ``` -static sugar +static sugar (during elaboration) + ``` -f e = f<@>e when f: sort (typ,...) -> async t +T1 -> async<@> T2 ~~> T1[X/@] -> async T[X/@] +T1 -> async T2 ~~> LHS (|tbs| <> 1) + + +async e ~~> async e[X/@] +f e = f<@>e when f: sort (typ,...) ~~> async t + +funcf() : async<@> T = async e <@> ~~> +funcf() : async<@> T[X/@] = (async e <@>) [X/@] ``` +(basically, we rebind `@` to the current scope during elaboration, so references inserted during parsing elaborate to the nearest appropiate binding, and default missing scope instantiations to the current meaning of `@`). + +Note that in a function type or definition with n>1 type parameters, `<@>` either shadows one of those eponymous type parameters or it retains its outer meaning. In the latter case (outer binding), we might either warn appropriately or reject as ambiguous, requiring the user to +give the missing instantiation of the `async T` return type. + +(The implementation is currently silent and defaults `@` to the enclosing interpretation.) + +### Sugaring types (for pretty printing) + +During pretty printing of types, we suppress a unary type binding in a function type if it only occurs as an `async` type instantiation at DeBruijn level 0, in which case we elide all those `async` type instantiations too. Binders with async instantiations at DeBruijn levels higher than 0 must be shown to avoid ambiguity. diff --git a/src/mo_def/syntax.ml b/src/mo_def/syntax.ml index e41bf418661..2da689160a7 100644 --- a/src/mo_def/syntax.ml +++ b/src/mo_def/syntax.ml @@ -226,6 +226,12 @@ let string_of_lit = function | PreLit _ -> assert false +open Source +let (@@) = Source.(@@) +let (@?) it at = Source.({it; at; note = empty_typ_note}) +let (@!) it at = Source.({it; at; note = Type.Pre}) +let (@=) it at = Source.({it; at; note = None}) + let scope_id = "@" let scope_typ region = @@ -236,5 +242,46 @@ let scope_typ region = note = Type.Pre }, []); at = region; - note = Type.Pre }); + note = Type.Pre }) + +let scope_id = "@" +let scope_bind() = + { var = scope_id @@ no_region; + bound = PrimT "Any" @! no_region} + @= no_region + +let pun_bind typ_bind = + { var = typ_bind.it.var.it @@ no_region; + bound = PrimT "Any" @! no_region + } @= no_region + +let rec is_scope_typ t = + match t.it with + | PathT (p, []) -> + (match p.it with + | IdH id -> + id.it = scope_id + | _ -> false) + | ParT t -> is_scope_typ t + | _ -> false + +let funcT(sort, tbs_opt, t1, t2) = + match tbs_opt with + | None -> + (match t2.it with + | AsyncT (t21, _) when is_scope_typ t21 -> + FuncT(sort, [scope_bind ()], t1, t2) + | _ -> + FuncT(sort, [], t1, t2)) + | Some tbs -> FuncT(sort, tbs, t1, t2) + +let funcE (f, s, tbs_opt, p, t_opt, e) = + match tbs_opt, t_opt with + | None, None -> FuncE(f, s, [], p, t_opt, e) + | None, Some t -> + (match t.it with + | AsyncT (t1, _) when is_scope_typ t1 -> + FuncE(f, s, [scope_bind()], p, t_opt, e) + | _ -> FuncE(f, s, [], p, t_opt, e)) + | Some tbs, _ -> FuncE(f, s, tbs, p, t_opt, e) diff --git a/src/mo_frontend/parser.mly b/src/mo_frontend/parser.mly index 7067e2192d7..95c186f32ed 100644 --- a/src/mo_frontend/parser.mly +++ b/src/mo_frontend/parser.mly @@ -25,10 +25,6 @@ let positions_to_region position1 position2 = let at (startpos, endpos) = positions_to_region startpos endpos -let (@?) it at = {it; at; note = empty_typ_note} -let (@!) it at = {it; at; note = Type.Pre} -let (@=) it at = {it; at; note = None} - let dup_var x = VarE (x.it @@ x.at) @? x.at let anon sort at = "anon-" ^ sort ^ "-" ^ string_of_pos at.left @@ -89,41 +85,9 @@ let share_expfield (ef : exp_field) = then ef else {ef with it = {ef.it with dec = share_dec ef.it.dec}} -let scope_id = "@" -let scope_bind() = {var = scope_id @@ no_region; bound = PrimT "Any" @! no_region} @= no_region -let scope_typ() = PathT ((IdH (scope_id @@ no_region)) @! no_region, []) @! no_region +let scope_typ() = scope_typ no_region -let rec is_scope_typ t = - match t.it with - | PathT (p, []) -> - (match p.it with - | IdH id -> - id.it = scope_id - | _ -> false) - | ParT t -> is_scope_typ t - | _ -> false - -let funcT(sort, tbs_opt, t1, t2) = - match tbs_opt with - | None -> - (match t2.it with - | AsyncT (t21, _) when is_scope_typ t21 -> - FuncT(sort, [scope_bind()], t1, t2) - | _ -> - FuncT(sort, [], t1, t2)) - | Some tbs -> FuncT(sort, tbs, t1, t2) - -let funcE (f, s, tbs_opt, p, t_opt, e) = - match tbs_opt, t_opt with - | None, None -> FuncE(f, s, [], p, t_opt, e) - | None, Some t -> - (match t.it with - | AsyncT (t1, _) when is_scope_typ t1 -> - FuncE(f, s, [scope_bind()], p, t_opt, e) - | _ -> FuncE(f, s, [], p, t_opt, e)) - | Some tbs, _ -> FuncE(f, s, tbs, p, t_opt, e) - -%} + %} %token EOF @@ -487,7 +451,7 @@ exp_nondec(B) : { RetE(e) @? at $sloc } | ASYNC e=exp(bl) { AsyncE(scope_bind(), e, scope_typ()) @? at $sloc } - | ASYNC tb = scope_bind e=exp_block t=scope_inst_opt + | ASYNC tb = scope_bind e=exp_nullary(bl) t=scope_inst_opt { AsyncE(tb, e, t) @? at $sloc } | AWAIT e=exp(bl) { AwaitE(e) @? at $sloc } @@ -674,7 +638,10 @@ dec_nonvar : | (false, e) -> e (* body declared as EQ e *) | (true, e) -> (* body declared as immediate block *) match t with - | Some {it = AsyncT _; _} -> AsyncE(scope_bind(), e, scope_typ()) @? e.at + | Some {it = AsyncT _; _} -> + (match tps with + | Some [tb] -> AsyncE(pun_bind tb, e, scope_typ()) @? e.at + | _ -> AsyncE(scope_bind(), e, scope_typ()) @? e.at) | _ -> e in let named, x = xf "func" $sloc in diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index fd89b63da5c..85690c3efa8 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -255,6 +255,12 @@ let check_shared_return env at sort c ts = | T.Shared T.Query, _, _ -> error env at "shared query function must have syntactic return type `async `" | _ -> () +let infer_scope env cs cod = + match cs, cod.it with + | [c], AsyncT(typ0,_) when is_scope_typ typ0 -> + { env with typs = T.Env.add scope_id c env.typs } + | _ -> env + let rec check_typ env typ : T.typ = let t = check_typ' env typ in typ.note <- t; @@ -283,6 +289,7 @@ and check_typ' env typ : T.typ = | FuncT (sort, binds, typ1, typ2) -> let cs, ts, te, ce = check_typ_binds env binds in let env' = adjoin_typs env te ce in + let env' = infer_scope env' cs typ2 in let typs1 = as_domT typ1 in let c, typs2 = as_codomT sort.it typ2 in let ts1 = List.map (check_typ env') typs1 in @@ -733,6 +740,7 @@ and infer_exp'' env exp : T.typ = check_shared_return env typ.at sort.it cT ts2; let cs, ts, te, ce = check_typ_binds env typ_binds in let env' = adjoin_typs env te ce in + let env' = infer_scope env' cs typ in let t1, ve = infer_pat_exhaustive env' pat in let ts2 = List.map (check_typ env') ts2 in let c = T.map_control (check_typ env') cT in @@ -950,8 +958,9 @@ and infer_exp'' env exp : T.typ = error_in [Flags.ICMode] env exp.at "unsupported async block"; let t1 = check_typ env typ1 in let c, tb, ce, cs = check_typ_bind env typ_bind in + let ce_scope = T.Env.add "@" c ce in (* pun scope identifier @ with c *) let env' = - {(adjoin_typs env ce cs) with labs = T.Env.empty; rets = Some T.Pre; async = Some c} in + {(adjoin_typs env ce_scope cs) with labs = T.Env.empty; rets = Some T.Pre; async = Some c} in let t = infer_exp env' exp1 in let t' = T.open_ [t1] (T.close [c] t) in if not (T.shared t') then diff --git a/test/fail/illegal-await.mo b/test/fail/illegal-await.mo index 2c8ad87628f..f387af761c3 100644 --- a/test/fail/illegal-await.mo +++ b/test/fail/illegal-await.mo @@ -28,19 +28,19 @@ // Recursive deadlock -shared func Rec<@>(n : Int, a : async ()) : async () { +shared func Rec(n : Int, a : async ()) : async () { if (n == 0) { await a // <- illegal await since async<@>() () } else { - await Rec<@>(n-1, a) + await Rec(n-1, a) } }; { ignore async { - let t : async () = Rec<@>(10,t); + let t : async () = Rec(10,t); await t; } }; \ No newline at end of file diff --git a/test/fail/ok/asyncret2.tc.ok b/test/fail/ok/asyncret2.tc.ok index e8b9e5ae132..65fa3575b43 100644 --- a/test/fail/ok/asyncret2.tc.ok +++ b/test/fail/ok/asyncret2.tc.ok @@ -1,4 +1,4 @@ asyncret2.mo:1.54-1.57: type error, expression of type - async Int + async<@/3> Int cannot produce expected type Int diff --git a/test/run-drun/general_await.mo b/test/run-drun/general_await.mo index ffefcfd53ed..5308800c424 100644 --- a/test/run-drun/general_await.mo +++ b/test/run-drun/general_await.mo @@ -1,11 +1,11 @@ actor Await { - public shared func Ack<@>() : async(){ - debugPrint "\nAck" + public shared func Ack/*<@>*/() : async(){ + debugPrint "Ack" }; - public shared func Request<@>(i : Int) : async Int { - debugPrint("\nRequest(");debugPrintInt(i);debugPrint(")"); + public shared func Request/*<@>*/(i : Int) : async Int { + debugPrint("Request(" # debug_show i # ")"); return i; }; diff --git a/test/run-drun/general_await_implicit.mo b/test/run-drun/general_await_implicit.mo index 610cc4314da..6b5e045f2e4 100644 --- a/test/run-drun/general_await_implicit.mo +++ b/test/run-drun/general_await_implicit.mo @@ -1,33 +1,33 @@ actor Await { - public shared func Ack/*<@>*/() : async(){ - debugPrint "\nAck" + public shared func Ack() : async(){ + debugPrint "Ack" }; - public shared func Request/*<@>*/(i : Int) : async Int { - debugPrint("\nRequest(");debugPrintInt(i);debugPrint(")"); - return i; + public shared func Request(i : Int) : async Int { + debugPrint("Request(" # debug_show i # ")"); + return i }; // Static parallel waiting: - public shared func PA/*<@>*/() : async () { - let a1 = Ack/*<@>*/(); - let a2 = Ack/*<@>*/(); + public shared func PA() : async () { + let a1 = Ack(); + let a2 = Ack(); await a1; await a2; }; - public shared func PR/*<@>*/() : async (Int,Int) { - let a1 = Request/*<@>*/(1); - let a2 = Request/*<@>*/(2); + public shared func PR() : async (Int,Int) { + let a1 = Request(1); + let a2 = Request(2); (await a1, await a2) }; // Dynamic parallel waiting for acknowledgements - public shared func DPA/*<@>*/() : async () { - let as: [async()] = Array_tabulate(10, func (_) { Ack/*<@>*/(); }); + public shared func DPA() : async () { + let as: [async()] = Array_tabulate(10, func (_) { Ack(); }); for (a in as.vals()) { await a; }; @@ -35,8 +35,8 @@ actor Await { // Dynamic parallel waiting (with results) - public shared func DPR/*<@>*/() : async [Int] { - func f<>(i:Nat) : async Int = Request/*<@>*/(i); + public shared func DPR() : async [Int] { + func f<>(i:Nat) : async Int = Request(i); //NB: <> necesary to suppress implicit @-quantification let as = Array_tabulate(10, f); let res = Array_init(as.len(),-1); @@ -50,11 +50,11 @@ actor Await { // Recursive parallel waiting - public shared func RPA/*<@>*/(n:Nat) : async () { + public shared func RPA(n:Nat) : async () { if (n == 0) () else { - let a = Ack/*<@>*/(); - await RPA/*<@>*/(n-1); // recurse + let a = Ack(); + await RPA(n-1); // recurse await a; }; }; @@ -63,11 +63,11 @@ actor Await { public type List = ?(Int,List); - public shared func RPR/*<@>*/(n:Nat) : async List { + public shared func RPR(n:Nat) : async List { if (n == 0) null else { - let a = Request/*<@>*/(n); - let tl = await RPR/*<@>*/(n-1); // recurse + let a = Request(n); + let tl = await RPR(n-1); // recurse ?(await a,tl) } }; @@ -75,23 +75,23 @@ actor Await { public shared func Test() : async () { - await PA/*<@>*/(); + await PA(); - switch (await PR/*<@>*/()) { + switch (await PR()) { case (1,2) (); case _ (assert false); }; - await DPA/*<@>*/(); + await DPA(); - let rs = await DPR/*<@>*/(); + let rs = await DPR(); for (i in rs.keys()) { assert rs[i] == i; }; - await RPA/*<@>*/(10); + await RPA(10); - var l = await RPR/*<@>*/(10); + var l = await RPR(10); for (i in revrange(10, 1)) { switch (l) { case (?(h, t)) { diff --git a/test/run-drun/ok/general_await.run-ir.ok b/test/run-drun/ok/general_await.run-ir.ok index 0e38f4617ac..3e8ef58ba9f 100644 --- a/test/run-drun/ok/general_await.run-ir.ok +++ b/test/run-drun/ok/general_await.run-ir.ok @@ -1,4 +1,3 @@ - Ack Ack Request(+1) diff --git a/test/run-drun/ok/general_await.run-low.ok b/test/run-drun/ok/general_await.run-low.ok index 0e38f4617ac..3e8ef58ba9f 100644 --- a/test/run-drun/ok/general_await.run-low.ok +++ b/test/run-drun/ok/general_await.run-low.ok @@ -1,4 +1,3 @@ - Ack Ack Request(+1) diff --git a/test/run-drun/ok/general_await_implicit.run-ir.ok b/test/run-drun/ok/general_await_implicit.run-ir.ok index e956f326cfb..3e8ef58ba9f 100644 --- a/test/run-drun/ok/general_await_implicit.run-ir.ok +++ b/test/run-drun/ok/general_await_implicit.run-ir.ok @@ -1,132 +1,44 @@ - -Ack - -Ack - -Request( -+1 -) - -Request( -+2 -) - -Ack - -Ack - -Ack - -Ack - -Ack - -Ack - -Ack - -Ack - -Ack - -Ack - -Request( -0 -) - -Request( -+1 -) - -Request( -+2 -) - -Request( -+3 -) - -Request( -+4 -) - -Request( -+5 -) - -Request( -+6 -) - -Request( -+7 -) - -Request( -+8 -) - -Request( -+9 -) - -Ack - -Ack - -Ack - -Ack - -Ack - -Ack - -Ack - -Ack - -Ack - -Ack - -Request( -+10 -) - -Request( -+9 -) - -Request( -+8 -) - -Request( -+7 -) - -Request( -+6 -) - -Request( -+5 -) - -Request( -+4 -) - -Request( -+3 -) - -Request( -+2 -) - -Request( -+1 -) +Ack +Ack +Request(+1) +Request(+2) +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Request(0) +Request(+1) +Request(+2) +Request(+3) +Request(+4) +Request(+5) +Request(+6) +Request(+7) +Request(+8) +Request(+9) +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Request(+10) +Request(+9) +Request(+8) +Request(+7) +Request(+6) +Request(+5) +Request(+4) +Request(+3) +Request(+2) +Request(+1) diff --git a/test/run-drun/ok/general_await_implicit.run-low.ok b/test/run-drun/ok/general_await_implicit.run-low.ok index e956f326cfb..3e8ef58ba9f 100644 --- a/test/run-drun/ok/general_await_implicit.run-low.ok +++ b/test/run-drun/ok/general_await_implicit.run-low.ok @@ -1,132 +1,44 @@ - -Ack - -Ack - -Request( -+1 -) - -Request( -+2 -) - -Ack - -Ack - -Ack - -Ack - -Ack - -Ack - -Ack - -Ack - -Ack - -Ack - -Request( -0 -) - -Request( -+1 -) - -Request( -+2 -) - -Request( -+3 -) - -Request( -+4 -) - -Request( -+5 -) - -Request( -+6 -) - -Request( -+7 -) - -Request( -+8 -) - -Request( -+9 -) - -Ack - -Ack - -Ack - -Ack - -Ack - -Ack - -Ack - -Ack - -Ack - -Ack - -Request( -+10 -) - -Request( -+9 -) - -Request( -+8 -) - -Request( -+7 -) - -Request( -+6 -) - -Request( -+5 -) - -Request( -+4 -) - -Request( -+3 -) - -Request( -+2 -) - -Request( -+1 -) +Ack +Ack +Request(+1) +Request(+2) +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Request(0) +Request(+1) +Request(+2) +Request(+3) +Request(+4) +Request(+5) +Request(+6) +Request(+7) +Request(+8) +Request(+9) +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Request(+10) +Request(+9) +Request(+8) +Request(+7) +Request(+6) +Request(+5) +Request(+4) +Request(+3) +Request(+2) +Request(+1) diff --git a/test/run-stub/ok/general_await.ic-stub-run.ok b/test/run-stub/ok/general_await.ic-stub-run.ok index 0fc4527b321..ec18482a4a7 100644 --- a/test/run-stub/ok/general_await.ic-stub-run.ok +++ b/test/run-stub/ok/general_await.ic-stub-run.ok @@ -1,3 +1,5 @@ +→ create +← completed: canister-id = 0x0000000000000400 → install ← completed → update Test(0x4449444c0000) diff --git a/test/run-stub/ok/scope-inference.ic-stub-run.ok b/test/run-stub/ok/scope-inference.ic-stub-run.ok new file mode 100644 index 00000000000..54225bc8555 --- /dev/null +++ b/test/run-stub/ok/scope-inference.ic-stub-run.ok @@ -0,0 +1,4 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed From 69266686aa36346ba9222364820f40349836a2aa Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Fri, 29 Nov 2019 00:29:23 +0000 Subject: [PATCH 0733/1176] update design --- design/scoped-await.md | 24 ++-- test/run-drun/general_await.mo | 20 ++-- test/run-stub/general_await.mo | 62 +++++----- test/run-stub/general_await_implicit.mo | 111 ++++++++++++++++++ test/run-stub/ok/general_await.ic-stub-run.ok | 68 ++++------- .../ok/general_await_implicit.ic-stub-run.ok | 26 ++++ 6 files changed, 211 insertions(+), 100 deletions(-) create mode 100644 test/run-stub/general_await_implicit.mo create mode 100644 test/run-stub/ok/general_await_implicit.ic-stub-run.ok diff --git a/design/scoped-await.md b/design/scoped-await.md index 794d2747c3c..b69409f73f5 100644 --- a/design/scoped-await.md +++ b/design/scoped-await.md @@ -114,8 +114,11 @@ E; _ |- shared f(x:T) : async U { e; } ## Examples: -(These need fixing below but are all coded in [general_await.mo](../test/run-drun/general_await.mo) -[general_await_implicit.mo](../test/run-drun/general_await_implicit.mo) +(These need fixing for typos below but are all coded in + +* [general_await.mo](../test/run-stub/general_await.mo) (no-sugar) +* [general_await_implicit.mo](../test/run-stub/general_await_implicit.mo) (with sugar) +) Assuming the following requests: @@ -239,30 +242,33 @@ shared func f() : async () { ## Sugar Principle: Desugaring should be: + * simple and unambiguous * expressible in the syntax (as explicit binders and instantiations). * avoidable (by supplying explicit binders and instantations). -Basic idea: +### Basic idea: + +Prelude: -Prelude: -defines default scope (non-awaitable) and instantiation: -` +Defines default scope @ = Any (non-awaitable in any async context) and instantiation: + +``` type @ = Any -` +``` (`@` is a newly legal scope identifier) Parsing: -* inserts `<@>` type instantations and binders for missing `async` binders and instantiations (in types and terms) and `async` binders (in terms) +* inserts `<@>` type instantiations and binders for missing `async` binders and instantiations (in types and terms) and `async` binders (in terms) * adds missing `<@>` bindings to async returning functions with absent quantifiers (note we distinguish missing type parameters from empty parameters `<>`) Elaboration: * Elaboration ensures `@` is bound to appropriate constructor, shadowing any previous `@`-binding to ensure structured scoping. -* Elaboration adds missing instantiations to function applications that require them, guided by the synthesized function type. +* Elaboration adds missing unary instantiations to function applications that require them, guided by the synthesized function type. syntactic sugar (during parse, applied bottom up as we construct types and terms) diff --git a/test/run-drun/general_await.mo b/test/run-drun/general_await.mo index 5308800c424..461d1c78df6 100644 --- a/test/run-drun/general_await.mo +++ b/test/run-drun/general_await.mo @@ -1,24 +1,24 @@ actor Await { - public shared func Ack/*<@>*/() : async(){ + public shared func Ack<@>() : async<@> (){ debugPrint "Ack" }; - public shared func Request/*<@>*/(i : Int) : async Int { + public shared func Request<@>(i : Int) : async<@> Int { debugPrint("Request(" # debug_show i # ")"); return i; }; // Static parallel waiting: - public shared func PA<@>() : async () { + public shared func PA<@>() : async<@> () { let a1 = Ack<@>(); let a2 = Ack<@>(); await a1; await a2; }; - public shared func PR<@>() : async (Int,Int) { + public shared func PR<@>() : async<@>(Int,Int) { let a1 = Request<@>(1); let a2 = Request<@>(2); (await a1, await a2) @@ -26,7 +26,7 @@ actor Await { // Dynamic parallel waiting for acknowledgements - public shared func DPA<@>() : async () { + public shared func DPA<@>() : async<@>() { let as: [async()] = Array_tabulate(10, func (_) { Ack<@>(); }); for (a in as.vals()) { await a; @@ -35,7 +35,7 @@ actor Await { // Dynamic parallel waiting (with results) - public shared func DPR<@>() : async [Int] { + public shared func DPR<@>() : async<@>[Int] { func f<>(i:Nat) : async Int = Request<@>(i); let as = Array_tabulate(10, f); let res = Array_init(as.len(),-1); @@ -49,7 +49,7 @@ actor Await { // Recursive parallel waiting - public shared func RPA<@>(n:Nat) : async () { + public shared func RPA<@>(n:Nat) : async<@>() { if (n == 0) () else { let a = Ack<@>(); @@ -62,7 +62,7 @@ actor Await { public type List = ?(Int,List); - public shared func RPR<@>(n:Nat) : async List { + public shared func RPR<@>(n:Nat) : async<@> List { if (n == 0) null else { let a = Request<@>(n); @@ -72,7 +72,7 @@ actor Await { }; - public shared func Test() : async () { + public shared func Test<@>() : async<@>() { await PA<@>(); @@ -103,7 +103,7 @@ actor Await { } }; -Await.Test(); +Await.Test<@>(); //SKIP run-drun //SKIP comp diff --git a/test/run-stub/general_await.mo b/test/run-stub/general_await.mo index ee57adc35ba..74f77a7b926 100644 --- a/test/run-stub/general_await.mo +++ b/test/run-stub/general_await.mo @@ -1,38 +1,35 @@ -// TODO: Remove Await. prefix from calls once supported -// Remove bug workaround -// Increase N (once perf improves) actor Await { - let N = 3; // number of dynamic waits (low coz slow) - - public shared func Ack<@>() : async(){ - debugPrint "\nAck" + let N = 4; + + public shared func Ack<@>() : async<@> (){ + debugPrint "Ack" }; - public shared func Request<@>(i : Int) : async Int { - debugPrint("\nRequest(");debugPrintInt(i);debugPrint(")"); + public shared func Request<@>(i : Int) : async<@> Int { + debugPrint("Request(" # debug_show i # ")"); return i; }; // Static parallel waiting: - public shared func PA<@>() : async () { - let a1 = Await.Ack<@>(); - let a2 = Await.Ack<@>(); + public shared func PA<@>() : async<@> () { + let a1 = Ack<@>(); + let a2 = Ack<@>(); await a1; await a2; }; - public shared func PR<@>() : async (Int,Int) { - let a1 = Await.Request<@>(1); - let a2 = Await.Request<@>(2); + public shared func PR<@>() : async<@>(Int,Int) { + let a1 = Request<@>(1); + let a2 = Request<@>(2); (await a1, await a2) }; // Dynamic parallel waiting for acknowledgements - public shared func DPA<@>() : async () { - let as: [async()] = Array_tabulate(N, func (_) { Await.Ack<@>(); }); + public shared func DPA<@>() : async<@>() { + let as: [async()] = Array_tabulate(N, func (_) { Ack<@>(); }); for (a in as.vals()) { await a; }; @@ -40,8 +37,8 @@ actor Await { // Dynamic parallel waiting (with results) - public shared func DPR<@>() : async [Int] { - func f<>(i:Nat) : async Int = Await.Request<@>(i); + public shared func DPR<@>() : async<@>[Int] { + func f<>(i:Nat) : async Int = Request<@>(i); let as = Array_tabulate(N, f); let res = Array_init(as.len(),-1); for (i in as.keys()) { @@ -54,11 +51,11 @@ actor Await { // Recursive parallel waiting - public shared func RPA<@>(n:Nat) : async () { + public shared func RPA<@>(n:Nat) : async<@>() { if (n == 0) () else { - let a = Await.Ack<@>(); - await Await.RPA<@>(n-1); // recurse + let a = Ack<@>(); + await RPA<@>(n-1); // recurse await a; }; }; @@ -67,35 +64,35 @@ actor Await { public type List = ?(Int,List); - public shared func RPR<@>(n:Nat) : async List { + public shared func RPR<@>(n:Nat) : async<@> List { if (n == 0) null else { - let a = Await.Request<@>(n); - let tl = await Await.RPR<@>(n-1); // recurse + let a = Request<@>(n); + let tl = await RPR<@>(n-1); // recurse ?(await a,tl) } }; - public shared func Test() : async () { + public shared func Test<@>() : async<@>() { - await Await.PA<@>(); + await PA<@>(); - switch (await Await.PR<@>()) { + switch (await PR<@>()) { case (1,2) (); case _ (assert false); }; - await Await.DPA<@>(); + await DPA<@>(); - let rs = await Await.DPR<@>(); + let rs = await DPR<@>(); for (i in rs.keys()) { assert rs[i] == i; }; - await Await.RPA<@>(N); + await RPA<@>(N); - var l = await Await.RPR<@>(N); + var l = await RPR<@>(N); for (i in revrange(N, 1)) { switch (l) { case (?(h, t)) { @@ -109,4 +106,3 @@ actor Await { }; //CALL ingress Test 0x4449444C0000 - diff --git a/test/run-stub/general_await_implicit.mo b/test/run-stub/general_await_implicit.mo new file mode 100644 index 00000000000..b1a25606d56 --- /dev/null +++ b/test/run-stub/general_await_implicit.mo @@ -0,0 +1,111 @@ +actor Await { + + let N = 4; + + public shared func Ack() : async(){ + debugPrint "Ack" + }; + + public shared func Request(i : Int) : async Int { + debugPrint("Request(" # debug_show i # ")"); + return i + }; + + // Static parallel waiting: + + public shared func PA() : async () { + let a1 = Ack(); + let a2 = Ack(); + await a1; + await a2; + }; + + public shared func PR() : async (Int,Int) { + let a1 = Request(1); + let a2 = Request(2); + (await a1, await a2) + }; + + // Dynamic parallel waiting for acknowledgements + + public shared func DPA() : async () { + let as: [async()] = Array_tabulate(N, func (_) { Ack(); }); + for (a in as.vals()) { + await a; + }; + }; + + // Dynamic parallel waiting (with results) + + public shared func DPR() : async [Int] { + func f<>(i:Nat) : async Int = Request(i); + //NB: <> necesary to suppress implicit @-quantification + let as = Array_tabulate(N, f); + let res = Array_init(as.len(),-1); + for (i in as.keys()) { +// res[i] := (await as[i]); <-- compiler bug (generates incorrect code) + let a = await as[i]; + res[i] := a; + }; + Array_tabulate(as.len(),func i = res[i]) + }; + + // Recursive parallel waiting + + public shared func RPA(n:Nat) : async () { + if (n == 0) () + else { + let a = Ack(); + await RPA(n-1); // recurse + await a; + }; + }; + + // Recursive parallel waiting (with results) + + public type List = ?(Int,List); + + public shared func RPR(n:Nat) : async List { + if (n == 0) null + else { + let a = Request(n); + let tl = await RPR(n-1); // recurse + ?(await a,tl) + } + }; + + + public shared func Test() : async () { + + await PA(); + + switch (await PR()) { + case (1,2) (); + case _ (assert false); + }; + + await DPA(); + + let rs = await DPR(); + for (i in rs.keys()) { + assert rs[i] == i; + }; + + await RPA(N); + + var l = await RPR(N); + for (i in revrange(N, 1)) { + switch (l) { + case (?(h, t)) { + assert (h == i); + l := t; + }; + case null (assert false); + } + }; + } +}; + + +//CALL ingress Test 0x4449444C0000 + diff --git a/test/run-stub/ok/general_await.ic-stub-run.ok b/test/run-stub/ok/general_await.ic-stub-run.ok index ec18482a4a7..e679f36413e 100644 --- a/test/run-stub/ok/general_await.ic-stub-run.ok +++ b/test/run-stub/ok/general_await.ic-stub-run.ok @@ -3,52 +3,24 @@ → install ← completed → update Test(0x4449444c0000) - -Ack - -Ack - -Request( -+1 -) - -Request( -+2 -) - -Ack - -Ack - -Ack - -Request( -0 -) - -Request( -+1 -) - -Request( -+2 -) - -Ack - -Ack - -Ack - -Request( -+3 -) - -Request( -+2 -) - -Request( -+1 -) +Ack +Ack +Request(+1) +Request(+2) +Ack +Ack +Ack +Ack +Request(0) +Request(+1) +Request(+2) +Request(+3) +Ack +Ack +Ack +Ack +Request(+4) +Request(+3) +Request(+2) +Request(+1) ← completed: 0x4449444c0000 diff --git a/test/run-stub/ok/general_await_implicit.ic-stub-run.ok b/test/run-stub/ok/general_await_implicit.ic-stub-run.ok new file mode 100644 index 00000000000..e679f36413e --- /dev/null +++ b/test/run-stub/ok/general_await_implicit.ic-stub-run.ok @@ -0,0 +1,26 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ update Test(0x4449444c0000) +Ack +Ack +Request(+1) +Request(+2) +Ack +Ack +Ack +Ack +Request(0) +Request(+1) +Request(+2) +Request(+3) +Ack +Ack +Ack +Ack +Request(+4) +Request(+3) +Request(+2) +Request(+1) +← completed: 0x4449444c0000 From 28fd0a80a172f1ac2a8d6396c762e927bcd3fd1d Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 29 Nov 2019 10:58:50 +0100 Subject: [PATCH 0734/1176] IDL: Transparent data forms for `service` and `func` (#920) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit this proposes the “big” solution described in https://github.com/dfinity-lab/motoko/pull/883; the “small” solution is just too much of a hack (see https://github.com/dfinity-lab/motoko/pull/913#issuecomment-557780787) I think the idea is clear from this PR: We have two intro forms for these types, one for references and one for the transparent public actrors/methods, and serialize them differently, with a byte tag to distinguish. I am not sure if this is the best way of spec’ing this. Since this is Andreas’s document, if we agree on the idea of this, I invite @rossberg to take over the branch and reformulate as desired needed. --- design/IDL-Motoko.md | 12 ------------ design/IDL.md | 45 ++++++++++++++++++++++++++++---------------- 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/design/IDL-Motoko.md b/design/IDL-Motoko.md index f8f98bb996c..140d53e63dd 100644 --- a/design/IDL-Motoko.md +++ b/design/IDL-Motoko.md @@ -307,15 +307,3 @@ just suggestions. is treated by `moc` by reading `foo.did` as if the developer had run `didc path/to/foo.did -o path/to/foo.mo`. - -## Provisional Scaffolding adjustments - -At the time of writing, the underlying transport mechanism on the Internet Computer has no notion of a “sequence of references”, as expected by the IDL spec. This means that the IDL types `service …` and `func …` are not usable. - -To work around this and at least support passing references to _public_ canister and to _public_ canister methods, and until this mismatch is resolved, we implement `e` as follows: - -``` -e(actor { ;* }) = blob -e(shared -> ) = (blob, text) -``` -where the `blob` is an actor id, and the `text` a method name. diff --git a/design/IDL.md b/design/IDL.md index b13f9e44c6d..14644f1aa23 100644 --- a/design/IDL.md +++ b/design/IDL.md @@ -426,41 +426,49 @@ type tree = variant { A third form of value are *references*. They represent first-class handles to (possibly remote) *functions* or *services*. -#### Function References +#### Actor References -A *function reference* is described by its function type. For example, they allow passing callbacks to other functions. +An *actor reference* points to a service and is described by an actor type. Through this, services can communicate connections to other services. ``` - ::= func | ... + ::= ... | service ``` +There are two forms of values for actor references: + +* `Ref(r)` indicates an opaque reference, understood only by the underlying system. +* `Id(b)`, where `b : blob`, indicates a transparent reference to a service addressed by the blob `b`. + ##### Example ``` -type engine = service { - search : (query : text, callback : func (vec result) -> ()); +type broker = service { + findCounterService : (name : text) -> + (service {up : () -> (); current : () -> nat}); } ``` -#### Actor References +#### Function References -An *actor reference* points to a service and is described by an actor type. Through this, services can communicate connections to other services. +A *function reference* is described by its function type. For example, they allow passing callbacks to other functions. ``` - ::= ... | service + ::= func | ... ``` +There are two forms of values for actor references: + +* `Ref(r)` indicates an opaque reference, understood only by the underlying system. +* `Public(s,n)`, where `s : service ` and `n : text`, indicates the public method `n` of the service referenced by `s`. ##### Example ``` -type broker = service { - findCounterService : (name : text) -> - (service {up : () -> (); current : () -> nat}); +type engine = service { + search : (query : text, callback : func (vec result) -> ()); } ``` - ### Type Definitions Types can be named via *type definitions*. @@ -1009,8 +1017,11 @@ M : (, ) -> -> i8* M((k,v) : k:) = M(v : ) M : -> -> i8* -M(r : service ) = . -M(r : func ) = . +M(Ref(r) : service ) = i8(0) +M(Id(blob) : service ) = i8(1) M(blob) + +M(Ref(r) : func ) = i8(0) +M(Public(service, name) : func ) = i8(1) M(service) M(name) ``` @@ -1034,8 +1045,10 @@ R : (, ) -> -> * R((k,v) : k:) = R(v : ) R : -> -> * -R(r : service ) = r -R(r : func ) = r +R(Ref(r) : service ) = r +R(Id(blob) : service ) = . +R(Ref(r) : func ) = r +R(Public(service, name) : func ) = . ``` Note: From 73c6ca2f4438e13639f742f2cb4a0171d58fc02a Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 29 Nov 2019 11:49:14 +0100 Subject: [PATCH 0735/1176] Unify compile_static_message for IC and Stub mode (#947) * Unify compile_static_message for IC and Stub mode The only difference was the early reply for one-way methods, and we actually want that in both cases. * Update test output --- src/codegen/compile.ml | 51 +++++++++---------------- test/run-stub/ok/counter.ic-stub-run.ok | 8 ++-- test/run-stub/ok/query.ic-stub-run.ok | 12 +++--- test/run-stub/ok/reversi.ic-stub-run.ok | 2 +- 4 files changed, 29 insertions(+), 44 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 77b0d17dfda..5edb036c736 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -4666,39 +4666,24 @@ module FuncDec = struct | _ -> assert false let compile_static_message outer_env outer_ae sort control args mk_body ret_tys at : E.func_with_names = - match E.mode outer_env, control with - | Flags.ICMode, _ -> - let ae0 = VarEnv.mk_fun_ae outer_ae in - Func.of_body outer_env [] [] (fun env -> G.with_region at ( - (* reply early for a oneway *) - (if control = Type.Returns - then - Tuple.compile_unit ^^ - Serialization.serialize env [] ^^ - Dfinity.reply_with_data env - else G.nop) ^^ - (* Deserialize argument and add params to the environment *) - let arg_names = List.map (fun a -> a.it) args in - let arg_tys = List.map (fun a -> a.note) args in - let (ae1, setters) = VarEnv.add_argument_locals env ae0 arg_names in - Serialization.deserialize env arg_tys ^^ - G.concat (List.rev setters) ^^ - mk_body env ae1 ^^ - message_cleanup env sort - )) - | Flags.StubMode, _ -> - let ae0 = VarEnv.mk_fun_ae outer_ae in - Func.of_body outer_env [] [] (fun env -> G.with_region at ( - (* Deserialize argument and add params to the environment *) - let arg_names = List.map (fun a -> a.it) args in - let arg_tys = List.map (fun a -> a.note) args in - let (ae1, setters) = VarEnv.add_argument_locals env ae0 arg_names in - Serialization.deserialize env arg_tys ^^ - G.concat (List.rev setters) ^^ - mk_body env ae1 ^^ - message_cleanup env sort - )) - | (Flags.WasmMode | Flags.WASIMode), _ -> assert false + let ae0 = VarEnv.mk_fun_ae outer_ae in + Func.of_body outer_env [] [] (fun env -> G.with_region at ( + (* reply early for a oneway *) + (if control = Type.Returns + then + Tuple.compile_unit ^^ + Serialization.serialize env [] ^^ + Dfinity.reply_with_data env + else G.nop) ^^ + (* Deserialize argument and add params to the environment *) + let arg_names = List.map (fun a -> a.it) args in + let arg_tys = List.map (fun a -> a.note) args in + let (ae1, setters) = VarEnv.add_argument_locals env ae0 arg_names in + Serialization.deserialize env arg_tys ^^ + G.concat (List.rev setters) ^^ + mk_body env ae1 ^^ + message_cleanup env sort + )) (* Compile a closed function declaration (captures no local variables) *) let closed pre_env sort control name args mk_body ret_tys at = diff --git a/test/run-stub/ok/counter.ic-stub-run.ok b/test/run-stub/ok/counter.ic-stub-run.ok index 12512b1f71e..d5ebf47c862 100644 --- a/test/run-stub/ok/counter.ic-stub-run.ok +++ b/test/run-stub/ok/counter.ic-stub-run.ok @@ -4,15 +4,15 @@ ← completed → update inc(0x4449444c0000) 2 -← rejected (RC_CANISTER_ERROR): canister did not respond +← completed: 0x4449444c0000 → update inc(0x4449444c0000) 3 -← rejected (RC_CANISTER_ERROR): canister did not respond +← completed: 0x4449444c0000 → update inc(0x4449444c0000) 4 -← rejected (RC_CANISTER_ERROR): canister did not respond +← completed: 0x4449444c0000 → update printCounter(0x4449444c0000) 4 -← rejected (RC_CANISTER_ERROR): canister did not respond +← completed: 0x4449444c0000 → update get(0x4449444c0000) ← completed: 0x4449444c00017d04 diff --git a/test/run-stub/ok/query.ic-stub-run.ok b/test/run-stub/ok/query.ic-stub-run.ok index fc74a981a76..fb708e299fd 100644 --- a/test/run-stub/ok/query.ic-stub-run.ok +++ b/test/run-stub/ok/query.ic-stub-run.ok @@ -4,16 +4,16 @@ ← completed → update inc(0x4449444c0000) 2 -← rejected (RC_CANISTER_ERROR): canister did not respond +← completed: 0x4449444c0000 → update inc(0x4449444c0000) 3 -← rejected (RC_CANISTER_ERROR): canister did not respond +← completed: 0x4449444c0000 → update inc(0x4449444c0000) 4 -← rejected (RC_CANISTER_ERROR): canister did not respond +← completed: 0x4449444c0000 → update printCounter(0x4449444c0000) 4 -← rejected (RC_CANISTER_ERROR): canister did not respond +← completed: 0x4449444c0000 → update get(0x4449444c0000) ← completed: 0x4449444c00017d04 → query read(0x4449444c0000) @@ -21,10 +21,10 @@ ← completed: 0x4449444c00017d04 → update printCounter(0x4449444c0000) 4 -← rejected (RC_CANISTER_ERROR): canister did not respond +← completed: 0x4449444c0000 → query read(0x4449444c0000) 5 ← completed: 0x4449444c00017d04 → update printCounter(0x4449444c0000) 4 -← rejected (RC_CANISTER_ERROR): canister did not respond +← completed: 0x4449444c0000 diff --git a/test/run-stub/ok/reversi.ic-stub-run.ok b/test/run-stub/ok/reversi.ic-stub-run.ok index be8989be6d7..2bddbf68bb6 100644 --- a/test/run-stub/ok/reversi.ic-stub-run.ok +++ b/test/run-stub/ok/reversi.ic-stub-run.ok @@ -3,7 +3,7 @@ → install ← completed → update reset(0x4449444c0000) -← rejected (RC_CANISTER_ERROR): canister did not respond +← completed: 0x4449444c0000 → update board(0x4449444c0000) ← completed: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e4f2a2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a → update place(0x4449444c00037c7c7c010204) From d3692952db89f76f668dbdf7e6a5fdbbdf90442b Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Fri, 29 Nov 2019 11:46:22 +0000 Subject: [PATCH 0736/1176] Update design/scoped-await.md Co-Authored-By: Joachim Breitner --- design/scoped-await.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/design/scoped-await.md b/design/scoped-await.md index b69409f73f5..10e01f9e2fc 100644 --- a/design/scoped-await.md +++ b/design/scoped-await.md @@ -63,7 +63,7 @@ Here, the simplist might be to use the function name itself for the implicit ind ``` E, X; async |- e : T E |- U :: * (X fresh) ------------------------------------------------- -E; - |- async e : async[U]T +E; - |- async e : asyncT ``` An `async` expression at index `X` provides the scoped ability to await asyncs with index `X`. From ace832dc3e483c2cb926c1417b0e163015d1e600 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Fri, 29 Nov 2019 11:58:44 +0000 Subject: [PATCH 0737/1176] Apply suggestions from code review Co-Authored-By: Joachim Breitner --- design/scoped-await.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/design/scoped-await.md b/design/scoped-await.md index 10e01f9e2fc..01181cb63bd 100644 --- a/design/scoped-await.md +++ b/design/scoped-await.md @@ -132,7 +132,7 @@ shared Request(i : Int) : async Int { return i; } ``` async { let a1 = Ack(); - let a2 = Ack() + let a2 = Ack(); await(a1); await(a2); }; @@ -197,7 +197,7 @@ shared func waitN(n:Nat) : async(List) { #### Immediate deadlock ``` -let t:asyncU = async{ await t;}; // bad await since t : Async[Any]U U +let t:asyncU = async{ await t;}; // bad await since t : AsyncU U ``` Ruled out by index scoping (`X != T`, any `T`) @@ -277,11 +277,11 @@ syntactic sugar (during parse, applied bottom up as we construct types and terms async T := async<@> T T1 -> async<@> T2 := <@>T1 -> async<@> T1 -func f() : async<@> T = e -func<@>f() : async<@> T = e +func f() : async<@> T = e := +func<@>f() : async<@> T = e func f() : async<@> T { e } := -func<@>f() : async<@> T = async<@> e <@> +func<@>f() : async<@> T = async<@> e <@> func f() : async<@> T { e } := funcf() : async<@> T = async e <@> From 54ee63e977d9f53da4d62e3d624f4c7087a23d9e Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Fri, 29 Nov 2019 13:09:10 +0000 Subject: [PATCH 0738/1176] clarify design --- design/scoped-await.md | 86 ++++++++++++++++++++++++++++++------------ 1 file changed, 62 insertions(+), 24 deletions(-) diff --git a/design/scoped-await.md b/design/scoped-await.md index 01181cb63bd..f9882fafa13 100644 --- a/design/scoped-await.md +++ b/design/scoped-await.md @@ -63,8 +63,9 @@ Here, the simplist might be to use the function name itself for the implicit ind ``` E, X; async |- e : T E |- U :: * (X fresh) ------------------------------------------------- -E; - |- async e : asyncT +E; - |- async e : async T[U/X] ``` + An `async` expression at index `X` provides the scoped ability to await asyncs with index `X`. The body `e` of an async must be parametric in the index but the index @@ -73,43 +74,79 @@ parameter is immediately eliminated at some index `U` (not mentioning `X`). ### (restricted) await expressions ``` -E; async |- e : asyncU +E; async |- e : async T ------------------------------ -E; async |- await e : U +E; async |- await e : T ``` -We can only await things of the current index `T`, recorded in the context as `_ ; async`. +We can only await things of the current index `U`, recorded in the context as `_ ; async`. + +(For *closure under type substitution* of contexts, note that we need the annotation in the context to be a type, not just a type parameter). + + +### Application (Derived Rule) + +In the explicit system, the rules for function abstraction and application are *unchanged*. But +to illustrate how this works, we consider the derived rules: -### Application ``` -E; _ |- f : shared U -> async V +E; _ |- f : shared U -> async V E; _ |- e': [T/X] U ------------------------------------- E; _ |- f e' : async([T/X]V) ``` -Application must provide an index, typically the nearest enclosing index parameter if want to await the result, but I guess -it could be any enclosing index parameter. +Application must provide an instantiation, typically the nearest enclosing index parameter if want to await the result, but it +could be any type. + +In the implicit system, we change the rule for application to (if necessary) insert a single missing scope parameter (`@`) +amongst the remaining explicit type parameters, driven by the expected async returning function type +and the 1-deficit of type arguments. This is a simple check to see if the index of the return type is a type parameter and the number of arguments is 1 less than the number of parameters, +and then inserting '@' at the correct index in the type arguments (otherwise the arguments are as given). + + +### Abstraction (Derived Rule) + +Derivation for (desugared) shared functions (ignoring recursion). + +Consider the desugared async function: -### Abstraction +```shared f(x:T) : asyncU = async e ;``` -Rule for (desugared) shared functions (ignoring recursion). +For reusability in different async contexts, +every shared function should introduce a new index parameter, immediately supplied to the inner async expression. +Using non-generic shared functions is ok, but less useful (typically only locally useful): the result type needs to +be generic if we want to await it from other async contexts. + +Using the above rules and ordinary lambda abstraction we get: + +``` +E, X, x : T, Y; async |- e : U[Y] Y fresh +------------------------------------------------------------- +E, X, x : T |- async e : U[Y] : (U[Y])[X/Y] X fresh +------------------------------------------------------------- +E; _ |- shared f(x:T) : asyncU[X] = async e ; + shared (x:T) : asyncU[X] +``` + + +If we explicitly pun `X` and `Y` in our *implicit* syntax desugaring we get: ``` -E, X, x : T, Y; async |- e : U (X, Y fresh) ----------------------------------------------------- -E; _ |- shared f(x:T) : asyncU = async e ; +shared f(x:T) : async U := + shared f(x:T) : asyncU = async e ; + ``` -Every shared function introduce a new index parameter, immediately supplied to the inner async expression. -Derived rule for sugar (ignoring recursion): +Then we get the derived rule: ``` -E, X, x : T; async |- e : U --------------------------------------------- -E; _ |- shared f(x:T) : async U { e; } +E, X, x : T; async |- e : U (X fresh) +---------------------------------------------------------------------- +---------------------------------------------------------------------- +E; _ |- shared f(x:T) : async U { e; } : shared T -> async U ``` ## Examples: @@ -129,6 +166,7 @@ shared Request(i : Int) : async Int { return i; } ``` ### Static parralel waiting: + ``` async { let a1 = Ack(); @@ -266,8 +304,7 @@ Parsing: Elaboration: -* Elaboration ensures `@` is bound to appropriate constructor, -shadowing any previous `@`-binding to ensure structured scoping. +* Elaboration ensures `@` is bound to appropriate constructor, shadowing any previous `@`-binding to ensure structured scoping. * Elaboration adds missing unary instantiations to function applications that require them, guided by the synthesized function type. syntactic sugar (during parse, applied bottom up as we construct types and terms) @@ -284,10 +321,10 @@ func f() : async<@> T { e } := func<@>f() : async<@> T = async<@> e <@> func f() : async<@> T { e } := -funcf() : async<@> T = async e <@> +funcf() : async<@> T = async e <@> -x(pat) : async<@> T {e} := x<@>(pat): async<@> T = async <@> e <@> -x(pat) : async<@> T := e = x<@>(pat): async<@> T = e +f() : async<@> T {e} := f<@>(): async<@> T = async <@> e <@> +f() : async<@> T := e = f<@>(): async<@> T = e async e := async<@> e <@> @@ -305,7 +342,8 @@ f e = f<@>e when f: sort (typ,...) ~~> async t funcf() : async<@> T = async e <@> ~~> funcf() : async<@> T[X/@] = (async e <@>) [X/@] -``` +```` + (basically, we rebind `@` to the current scope during elaboration, so references inserted during parsing elaborate to the nearest appropiate binding, and default missing scope instantiations to the current meaning of `@`). Note that in a function type or definition with n>1 type parameters, `<@>` either shadows one of those eponymous type parameters or it retains its outer meaning. In the latter case (outer binding), we might either warn appropriately or reject as ambiguous, requiring the user to From 4156435980ce538a4209b7f124fddbf02da7e3a1 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Fri, 29 Nov 2019 13:24:54 +0000 Subject: [PATCH 0739/1176] add update --- design/scoped-await.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/design/scoped-await.md b/design/scoped-await.md index f9882fafa13..62f7d481275 100644 --- a/design/scoped-await.md +++ b/design/scoped-await.md @@ -285,6 +285,11 @@ Principle: Desugaring should be: * expressible in the syntax (as explicit binders and instantiations). * avoidable (by supplying explicit binders and instantations). + +*UPDATE*: The scheme below selectively adds a `@`-parameter to a (sugared) function with 0 or 1 type parameters and an omitted return index. +I now think it might be better to just always add to `@` to non-`@` declaring type parameters when the return type is `async<@> U`, regardless of the arity, n, of the original type parameters. We can then just insert @ at the correct position in a call with n-1 type arguments by inspecting the index of the async return type. Pretty printing can detect and elide the parameter in a slight generalization of what I do now. + + ### Basic idea: Prelude: @@ -346,11 +351,14 @@ funcf() : async<@> T[X/@] = (async e <@>) [X/@] (basically, we rebind `@` to the current scope during elaboration, so references inserted during parsing elaborate to the nearest appropiate binding, and default missing scope instantiations to the current meaning of `@`). -Note that in a function type or definition with n>1 type parameters, `<@>` either shadows one of those eponymous type parameters or it retains its outer meaning. In the latter case (outer binding), we might either warn appropriately or reject as ambiguous, requiring the user to +Note that in a function type or definition with n>1 type parameters, `@` either shadows one of those eponymous type parameters or it retains its outer meaning. In the latter case (outer binding), we might either warn appropriately or reject as ambiguous, requiring the user to give the missing instantiation of the `async T` return type. (The implementation is currently silent and defaults `@` to the enclosing interpretation.) + + + ### Sugaring types (for pretty printing) During pretty printing of types, we suppress a unary type binding in a function type if it only occurs as an `async` type instantiation at DeBruijn level 0, in which case we elide all those `async` type instantiations too. Binders with async instantiations at DeBruijn levels higher than 0 must be shown to avoid ambiguity. From 460b00f478ee6c6a492ad436d4aebc7a10fe8080 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Fri, 29 Nov 2019 13:57:39 +0000 Subject: [PATCH 0740/1176] update test output --- test/repl/ok/type-lub-repl.stdout.ok | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/repl/ok/type-lub-repl.stdout.ok b/test/repl/ok/type-lub-repl.stdout.ok index b3f4ed53aa5..d7fa1c338e4 100644 --- a/test/repl/ok/type-lub-repl.stdout.ok +++ b/test/repl/ok/type-lub-repl.stdout.ok @@ -28,5 +28,5 @@ Motoko 0.1 interpreter > 25 : Int > 42 : Int > func : (C, D) -> [C] -> [async (?4), async (?(-42))] : [(async (?Int))] +> [async (?4), async (?(-42))] : [(async<@> (?Int))] > From af6e0ff1d6a475285d3cdf1958ecee503e08feaa Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 29 Nov 2019 15:16:16 +0100 Subject: [PATCH 0741/1176] Test suite reorganization: Use actor-go pattern, merge drun and stub directories (#948) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit this consolidates the following * we want to run tests including actors on drun/stub * drun only supports a single top-level actor * we want to run something during tests, including remote calls and await. * the language does not allow await from the the program or actor top-level * the system does not even allow function calls from actor initialization (which also rules out `ignore async { … }`) * the interpreter runs programs which may create an actor and then use it. * the compiled targets can invoke public methods by using the following idiom: Tests take the following form: ``` actor a { … some exports … public func go() = ignore async { … the test driving code … }; }; a.go(); //OR-CALL ingress go "DIDL\x00\x00" ``` The interpreter can run such a thing directly. Before compilation, `run.sh` rewrite the last line to ``` //CALL ingress go "DIDL\x00\x00" ``` Now the test is a single top-level actor, thus it can be compiled to a canister, and the `//CALL` comment is picked up by `drun-wrapper.sh` to invoke `go()`. The rewriting is simply ``` sed 's,^.*//OR-CALL,//CALL,g' ``` so there can be more than one such call, and they can have proper arguments. I went through every test case in `run-drun`, and did some other reorganization along the way. Also, `test.sh` compiles for drun first. If that fails to compile (which should only happen due to platform restrictions), it compiles for the stub. It only runs one of them. All tests are now in tests into `test/run-drun`. Use `../test.sh -d`. --- test/.gitignore | 1 + test/Makefile | 5 - test/repl/type-lub-repl.sh | 2 +- test/{run-stub => run-drun}/AST-64.mo | 3 +- test/run-drun/AST-66.mo | 18 ++ test/{run-stub => run-drun}/GIT-843.mo | 3 +- test/run-drun/Makefile | 2 +- test/{run-stub => run-drun}/actor-creation.mo | 3 + test/run-drun/array-out-of-bounds.mo | 8 +- test/run-drun/async-any.mo | 6 + test/run-drun/async-calls1.mo | 12 + test/run-drun/async-calls2.mo | 14 + test/run-drun/async-calls3.mo | 19 ++ test/run-drun/async-free-var.mo | 18 ++ test/run-drun/async-loop-while.mo | 59 ++++ test/run-drun/async-loop.mo | 71 +++++ test/run-drun/async-new-obj.mo | 66 +++++ test/run-drun/async-obj-mut.mo | 21 ++ test/run-drun/async-while.mo | 59 ++++ test/run-drun/await.mo | 70 +++++ test/run-drun/block.mo | 39 +++ test/{run-stub => run-drun}/chat.mo | 3 +- test/run-drun/closure-params.mo | 26 ++ test/{run-stub => run-drun}/control.mo | 5 + .../{run-stub => run-drun}/count-callbacks.mo | 5 +- test/run-drun/counter2.mo | 28 +- .../create-then-trap.mo | 2 +- test/{run-stub => run-drun}/data-params.mo | 2 +- test/{run-stub => run-drun}/divide-by-zero.mo | 0 test/run-drun/empty-actor.mo | 1 + .../flatten-awaitables.mo | 7 +- test/run-drun/for-await.mo | 15 + test/{run-stub => run-drun}/free-callbacks.mo | 5 +- .../general-type-components.mo | 2 + test/run-drun/generic-tail-rec.mo | 8 +- .../hello-world-async.mo | 6 +- .../hello-world-await.mo | 3 +- test/run-drun/hello-world-message2.mo | 7 - test/run-drun/ic-calls.mo | 12 +- test/run-drun/idl-any.mo | 4 + test/run-drun/idl-bad.mo | 3 + test/run-drun/idl-field-escape.mo | 4 + test/run-drun/idl-func.mo | 4 + test/run-drun/idl-nary.mo | 4 + test/run-drun/idl-nat-int.mo | 4 + test/run-drun/idl-option.mo | 4 + test/run-drun/idl-pair.mo | 4 + test/run-drun/idl-record.mo | 4 + test/run-drun/idl-shorthand.mo | 4 + test/run-drun/idl-tuple.mo | 4 + test/run-drun/idl-unit.mo | 4 + test/run-drun/idl-variant.mo | 4 + test/run-drun/idl-vector.mo | 4 + .../indirect-counter.mo | 2 + test/run-drun/interleave.mo | 42 +++ test/{run-stub => run-drun}/issue-894.mo | 5 +- test/{run-stub => run-drun}/local-throw.mo | 4 +- test/run-drun/multiple-actors.mo | 7 - test/run-drun/nary-async.mo | 111 +++++++ .../ok/AST-64.ic-stub-run.ok | 0 test/run-drun/ok/AST-66.comp.ok | 4 + ...er2.drun-run.ret.ok => AST-66.comp.ret.ok} | 0 .../ok/AST-66.ic-stub-run.ok} | 2 +- test/run-drun/ok/GIT-843.drun-run.ok | 3 + .../ok/GIT-843.run-ir.ok | 0 .../ok/GIT-843.run-low.ok | 0 test/{run-stub => run-drun}/ok/GIT-843.run.ok | 0 .../ok/actor-creation.ic-stub-run.ok | 0 .../ok/actor-creation.run-ir.ok | 0 .../ok/actor-creation.run-low.ok | 0 .../ok/actor-creation.run.ok | 0 .../run-drun/ok/array-out-of-bounds.run-ir.ok | 2 + .../ok/array-out-of-bounds.run-low.ok | 2 + test/run-drun/ok/array-out-of-bounds.run.ok | 2 + test/run-drun/ok/async-any.comp.ok | 2 + ....drun-run.ret.ok => async-any.comp.ret.ok} | 0 .../ok/async-any.ic-stub-run.ok | 2 + test/run-drun/ok/async-calls1.comp.ok | 2 + ...s.comp.ret.ok => async-calls1.comp.ret.ok} | 0 .../ok/async-calls1.ic-stub-run.ok} | 3 +- test/run-drun/ok/async-calls2.comp.ok | 4 + ...s.comp.ret.ok => async-calls2.comp.ret.ok} | 0 .../ok/async-calls2.ic-stub-run.ok} | 2 + test/run-drun/ok/async-calls3.comp.ok | 6 + .../ok/async-calls3.comp.ret.ok} | 0 test/run-drun/ok/async-calls3.ic-stub-run.ok | 6 + test/run-drun/ok/async-free-var.comp.ok | 2 + .../ok/async-free-var.comp.ret.ok} | 0 .../ok/async-free-var.ic-stub-run.ok | 4 +- .../ok/async-free-var.run-ir.ok | 0 .../ok/async-free-var.run-low.ok | 0 .../ok/async-free-var.run.ok | 0 test/run-drun/ok/async-loop-while.comp.ok | 6 + .../ok/async-loop-while.comp.ret.ok} | 0 .../ok/async-loop-while.ic-stub-run.ok | 4 +- .../ok/async-loop-while.run-ir.ok | 0 .../ok/async-loop-while.run-low.ok | 0 .../ok/async-loop-while.run.ok | 0 test/run-drun/ok/async-loop.tc.ok | 1 + .../ok/async-loop.tc.ret.ok} | 0 test/run-drun/ok/async-new-obj.comp.ok | 2 + test/run-drun/ok/async-new-obj.comp.ret.ok | 1 + .../ok/async-new-obj.ic-stub-run.ok | 4 +- .../ok/async-new-obj.run-ir.ok | 0 .../ok/async-new-obj.run-low.ok | 0 .../ok/async-new-obj.run.ok | 0 test/run-drun/ok/async-obj-mut.comp.ok | 2 + test/run-drun/ok/async-obj-mut.comp.ret.ok | 1 + .../ok/async-obj-mut.ic-stub-run.ok | 4 +- .../ok/async-obj-mut.run-ir.ok | 0 .../ok/async-obj-mut.run-low.ok | 0 .../ok/async-obj-mut.run.ok | 0 test/run-drun/ok/async-while.comp.ok | 6 + test/run-drun/ok/async-while.comp.ret.ok | 1 + .../ok/async-while.ic-stub-run.ok | 4 +- .../ok/async-while.run-ir.ok | 0 .../ok/async-while.run-low.ok | 0 .../ok/async-while.run.ok | 0 test/run-drun/ok/await.comp.ok | 2 + test/run-drun/ok/await.comp.ret.ok | 1 + .../ok/await.ic-stub-run.ok | 4 +- .../{run-stub => run-drun}/ok/await.run-ir.ok | 0 .../ok/await.run-low.ok | 0 test/{run-stub => run-drun}/ok/await.run.ok | 0 test/run-drun/ok/block.comp.ok | 2 + test/run-drun/ok/block.comp.ret.ok | 1 + .../ok/block.ic-stub-run.ok | 4 +- .../{run-stub => run-drun}/ok/block.run-ir.ok | 0 .../ok/block.run-low.ok | 0 test/{run-stub => run-drun}/ok/block.run.ok | 0 .../ok/chat.ic-stub-run.ok | 0 test/{run-stub => run-drun}/ok/chat.run-ir.ok | 0 .../{run-stub => run-drun}/ok/chat.run-low.ok | 0 test/{run-stub => run-drun}/ok/chat.run.ok | 0 test/run-drun/ok/closure-params.comp.ok | 22 ++ test/run-drun/ok/closure-params.comp.ret.ok | 1 + .../ok/closure-params.ic-stub-run.ok | 4 +- .../ok/closure-params.run-ir.ok | 0 .../ok/closure-params.run-low.ok | 0 .../ok/closure-params.run.ok | 0 test/run-drun/ok/count-callbacks.comp.ok | 16 + test/run-drun/ok/count-callbacks.comp.ret.ok | 1 + .../ok/count-callbacks.ic-stub-run.ok | 4 +- test/run-drun/ok/counter2.comp.ok | 10 + test/run-drun/ok/counter2.comp.ret.ok | 1 + test/run-drun/ok/counter2.drun-run.ok | 2 - .../ok/counter2.ic-stub-run.ok | 4 +- .../ok/counter2.run-ir.ok | 0 .../ok/counter2.run-low.ok | 0 .../{run-stub => run-drun}/ok/counter2.run.ok | 0 test/run-drun/ok/create-then-trap.comp.ok | 4 + test/run-drun/ok/create-then-trap.comp.ret.ok | 1 + .../ok/create-then-trap.ic-stub-run.ok | 4 +- .../ok/create-then-trap.run-ir.ok | 0 .../ok/create-then-trap.run-low.ok | 0 .../ok/create-then-trap.run.ok | 0 test/run-drun/ok/data-params.comp.ok | 76 +++++ test/run-drun/ok/data-params.comp.ret.ok | 1 + .../ok/data-params.ic-stub-run.ok | 4 +- .../ok/data-params.run-ir.ok | 0 .../ok/data-params.run-low.ok | 0 .../ok/data-params.run.ok | 0 .../ok/data-params.tc.ok | 0 test/run-drun/ok/divide-by-zero.drun-run.ok | 1 + .../ok/divide-by-zero.run-ir.ok | 0 .../ok/divide-by-zero.run-low.ok | 0 .../ok/divide-by-zero.run.ok | 0 test/run-drun/ok/divide-by-zero.run.ret.ok | 1 + ...ug.drun-run.ok => empty-actor.drun-run.ok} | 0 test/run-drun/ok/flatten-awaitables.comp.ok | 80 +++++ .../ok/flatten-awaitables.comp.ret.ok | 1 + .../ok/flatten-awaitables.ic-stub-run.ok | 4 +- .../ok/flatten-awaitables.run-ir.ok | 0 .../ok/flatten-awaitables.run-low.ok | 0 .../ok/flatten-awaitables.run.ok | 0 .../ok/flatten-awaitables.tc.ok | 48 +-- test/run-drun/ok/for-await.comp.ok | 2 + test/run-drun/ok/for-await.comp.ret.ok | 1 + .../ok/for-await.ic-stub-run.ok | 4 +- .../ok/for-await.run-ir.ok | 0 .../ok/for-await.run-low.ok | 0 .../ok/for-await.run.ok | 0 test/run-drun/ok/free-callbacks.comp.ok | 6 + test/run-drun/ok/free-callbacks.comp.ret.ok | 1 + .../ok/free-callbacks.ic-stub-run.ok | 4 +- test/run-drun/ok/hello-world-async.comp.ok | 2 + .../run-drun/ok/hello-world-async.comp.ret.ok | 1 + .../ok/hello-world-async.ic-stub-run.ok | 4 +- .../ok/hello-world-async.run-ir.ok | 0 .../ok/hello-world-async.run-low.ok | 0 .../ok/hello-world-async.run.ok | 0 test/run-drun/ok/hello-world-await.comp.ok | 2 + .../run-drun/ok/hello-world-await.comp.ret.ok | 1 + .../ok/hello-world-await.ic-stub-run.ok | 4 +- .../ok/hello-world-await.run-ir.ok | 0 .../ok/hello-world-await.run-low.ok | 0 .../ok/hello-world-await.run.ok | 0 .../ok/hello-world-message2.drun-run.ok | 2 - test/run-drun/ok/ic-calls.comp.ok | 6 +- .../ok/ic-calls.ic-stub-run.ok | 6 +- test/run-drun/ok/ic-calls.tc.ok | 4 +- .../ok/indirect-counter.ic-stub-run.ok | 0 .../ok/indirect-counter.run-ir.ok | 0 .../ok/indirect-counter.run-low.ok | 0 .../ok/indirect-counter.run.ok | 0 test/run-drun/ok/interleave.comp.ok | 2 + test/run-drun/ok/interleave.comp.ret.ok | 1 + .../ok/interleave.ic-stub-run.ok | 4 +- .../ok/interleave.run-ir.ok | 0 .../ok/interleave.run-low.ok | 0 .../ok/interleave.run.ok | 0 test/run-drun/ok/issue-894.comp.ok | 8 + test/run-drun/ok/issue-894.comp.ret.ok | 1 + .../ok/issue-894.ic-stub-run.ok | 4 +- .../ok/issue-894.run-ir.ok | 0 .../ok/issue-894.run-low.ok | 0 .../ok/issue-894.run.ok | 0 test/run-drun/ok/local-throw.comp.ok | 4 + test/run-drun/ok/local-throw.comp.ret.ok | 1 + .../ok/local-throw.ic-stub-run.ok | 4 +- .../ok/local-throw.run-ir.ok | 0 .../ok/local-throw.run-low.ok | 0 .../ok/local-throw.run.ok | 0 test/run-drun/ok/modexp1.drun-run.ok | 1 - test/run-drun/ok/modexp2.drun-run.ok | 1 - test/run-drun/ok/modexp3.drun-run.ok | 1 - test/run-drun/ok/modexp4.drun-run.ok | 1 - test/run-drun/ok/modules-bwd.drun-run.ok | 1 - test/run-drun/ok/multiple-actors.comp.ok | 4 - test/run-drun/ok/nary-async.comp.ok | 16 + test/run-drun/ok/nary-async.comp.ret.ok | 1 + test/run-drun/ok/nary-async.ic-stub-run.ok | 16 + .../ok/nary-async.run-ir.ok | 0 .../ok/nary-async.run-low.ok | 0 .../ok/nary-async.run.ok | 0 test/run-drun/ok/oneway.comp.ok | 8 + test/run-drun/ok/oneway.comp.ret.ok | 1 + test/run-drun/ok/oneway.drun-run.ok | 11 - test/run-drun/ok/oneway.ic-stub-run.ok | 17 ++ ...test_oneway.run-ir.ok => oneway.run-ir.ok} | 0 ...st_oneway.run-low.ok => oneway.run-low.ok} | 0 .../ok/{test_oneway.run.ok => oneway.run.ok} | 0 test/run-drun/ok/overflow.comp.ok | 12 + test/run-drun/ok/overflow.comp.ret.ok | 1 + .../ok/overflow.ic-stub-run.ok | 7 +- test/run-drun/ok/overflow.run-ir.ok | 6 + test/run-drun/ok/overflow.run-low.ok | 6 + test/run-drun/ok/overflow.run.ok | 6 + test/run-drun/ok/pass-references.comp.ok | 12 + test/run-drun/ok/pass-references.comp.ret.ok | 1 + .../ok/pass-references.ic-stub-run.ok | 4 +- .../ok/pass-references.run-ir.ok | 0 .../ok/pass-references.run-low.ok | 0 .../ok/pass-references.run.ok | 0 test/run-drun/ok/query2.comp.ok | 18 ++ test/run-drun/ok/query2.comp.ret.ok | 1 + .../ok/query2.ic-stub-run.ok | 5 +- .../ok/query2.run-ir.ok | 2 +- .../ok/query2.run-low.ok | 2 +- test/{run-stub => run-drun}/ok/query2.run.ok | 2 +- .../ok/reference-params.ic-stub-run.ok | 0 .../ok/reference-params.run-ir.ok | 0 .../ok/reference-params.run-low.ok | 0 .../ok/reference-params.run.ok | 0 test/run-drun/ok/rts-stats.drun-run.ok | 2 + test/run-drun/ok/self-calls.comp.ok | 6 - test/run-drun/ok/self-calls.tc.ok | 9 - test/run-drun/ok/selftail.drun-run.ok | 2 +- test/run-drun/ok/selftail.run-ir.ok | 1 + test/run-drun/ok/selftail.run-low.ok | 1 + test/run-drun/ok/selftail.run.ok | 1 + test/run-drun/ok/shared-object.comp.ok | 2 + test/run-drun/ok/shared-object.comp.ret.ok | 1 + .../ok/shared-object.ic-stub-run.ok | 2 + test/run-drun/ok/simple-throw.drun-run.ok | 7 + .../ok/simple-throw.run-ir.ok | 0 .../ok/simple-throw.run-low.ok | 0 .../ok/simple-throw.run.ok | 0 test/run-drun/ok/test_oneway.tc.ok | 1 + test/run-drun/ok/test_oneway.tc.ret.ok | 1 + test/run-drun/ok/the-answer.drun-run.ok | 2 - test/run-drun/ok/the-answer.run-ir.ok | 1 - test/run-drun/ok/the-answer.run-low.ok | 1 - test/run-drun/ok/the-answer.run.ok | 1 - test/run-drun/ok/transpose.comp.ok | 2 + test/run-drun/ok/transpose.comp.ret.ok | 1 + .../ok/transpose.ic-stub-run.ok | 4 +- .../ok/transpose.run-ir.ok | 0 .../ok/transpose.run-low.ok | 0 .../ok/transpose.run.ok | 0 test/run-drun/ok/type-lub.comp.ok | 2 + test/run-drun/ok/type-lub.comp.ret.ok | 1 + .../ok/type-lub.ic-stub-run.ok | 0 .../ok/unsupported.comp-stub.ok} | 6 +- test/run-drun/ok/unsupported.comp-stub.ret.ok | 1 + test/run-drun/ok/unsupported.comp.ok | 12 +- test/run-drun/oneway.mo | 22 +- test/run-drun/oom.mo | 11 +- test/run-drun/overflow.mo | 33 +++ .../{run-stub => run-drun}/pass-references.mo | 5 +- test/run-drun/query.mo | 4 + test/{run-stub => run-drun}/query2.mo | 32 +- .../reference-params.mo | 1 + test/run-drun/reject.mo | 4 + test/run-drun/reversi.mo | 4 + test/{run-stub => run-drun}/rts-stats.mo | 0 test/run-drun/self-calls.mo | 27 -- test/run-drun/selftail.mo | 7 +- test/{run-stub => run-drun}/shared-object.mo | 5 +- test/{run-stub => run-drun}/simple-throw.mo | 4 +- test/run-drun/test_oneway.mo | 15 +- test/run-drun/the-answer.mo | 1 - test/{run-stub => run-drun}/transpose.mo | 2 +- test/{run-stub => run-drun}/type-lub.mo | 0 test/run-drun/unsupported.mo | 11 +- test/run-stub/AST-66.mo | 13 - test/run-stub/Makefile | 12 - test/run-stub/async-any.mo | 1 - test/run-stub/async-calls.mo | 47 --- test/run-stub/async-free-var.mo | 15 - test/run-stub/async-loop-while.mo | 59 ---- test/run-stub/async-loop.mo | 72 ----- test/run-stub/async-new-obj.mo | 59 ---- test/run-stub/async-obj-mut.mo | 18 -- test/run-stub/async-while.mo | 59 ---- test/run-stub/await.mo | 66 ----- test/run-stub/block.mo | 35 --- test/run-stub/closure-params.mo | 24 -- test/run-stub/counter.mo | 18 -- test/run-stub/counter2.mo | 25 -- test/run-stub/empty-actor.mo | 1 - test/run-stub/for-await.mo | 15 - test/run-stub/hello-world-return.mo | 11 - test/run-stub/ic-calls.mo | 27 -- test/run-stub/idl-any.mo | 39 --- test/run-stub/idl-bad.mo | 7 - test/run-stub/idl-field-escape.mo | 27 -- test/run-stub/idl-func.mo | 13 - test/run-stub/idl-nary.mo | 53 ---- test/run-stub/idl-nat-int.mo | 18 -- test/run-stub/idl-option.mo | 14 - test/run-stub/idl-pair.mo | 8 - test/run-stub/idl-record.mo | 34 --- test/run-stub/idl-tuple.mo | 17 -- test/run-stub/idl-unit.mo | 7 - test/run-stub/idl-variant.mo | 16 - test/run-stub/idl-vector.mo | 13 - test/run-stub/interleave.mo | 37 --- test/run-stub/multiple-actors.mo | 7 - test/run-stub/nary-async.mo | 103 ------- test/run-stub/ok/AST-66.ic-stub-run.ok | 4 - test/run-stub/ok/async-loop.ic-stub-run.ok | 16 - test/run-stub/ok/async-loop.run-ir.ok | 12 - test/run-stub/ok/async-loop.run-low.ok | 12 - test/run-stub/ok/async-loop.run.ok | 12 - test/run-stub/ok/control.ic-stub-run.ok | 4 - test/run-stub/ok/counter.ic-stub-run.ok | 18 -- .../run-stub/ok/divide-by-zero.ic-stub-run.ok | 4 - test/run-stub/ok/empty-actor.ic-stub-run.ok | 4 - .../ok/general-type-components.ic-stub-run.ok | 4 - .../ok/hello-world-return.ic-stub-run.ok | 8 - test/run-stub/ok/ic-calls.run-ir.ok | 4 - test/run-stub/ok/ic-calls.run-low.ok | 4 - test/run-stub/ok/ic-calls.run.ok | 4 - test/run-stub/ok/ic-calls.tc.ok | 9 - test/run-stub/ok/idl-any.ic-stub-run.ok | 88 ------ test/run-stub/ok/idl-bad.ic-stub-run.ok | 7 - .../ok/idl-field-escape.ic-stub-run.ok | 12 - test/run-stub/ok/idl-func.ic-stub-run.ok | 8 - test/run-stub/ok/idl-nary.ic-stub-run.ok | 28 -- test/run-stub/ok/idl-nat-int.ic-stub-run.ok | 12 - test/run-stub/ok/idl-option.ic-stub-run.ok | 13 - test/run-stub/ok/idl-pair.ic-stub-run.ok | 6 - test/run-stub/ok/idl-record.ic-stub-run.ok | 16 - test/run-stub/ok/idl-tuple.ic-stub-run.ok | 12 - test/run-stub/ok/idl-variant.ic-stub-run.ok | 6 - test/run-stub/ok/idl-vector.ic-stub-run.ok | 6 - test/run-stub/ok/multiple-actors.comp.ok | 4 - test/run-stub/ok/nary-async.ic-stub-run.ok | 12 - test/run-stub/ok/overflow.run-ir.ok | 6 - test/run-stub/ok/overflow.run-low.ok | 6 - test/run-stub/ok/overflow.run.ok | 6 - .../ok/print-from-init.ic-stub-run.ok | 5 - test/run-stub/ok/print-from-init.run-ir.ok | 1 - test/run-stub/ok/print-from-init.run-low.ok | 1 - test/run-stub/ok/print-from-init.run.ok | 1 - test/run-stub/ok/query.ic-stub-run.ok | 30 -- test/run-stub/ok/reject.ic-stub-run.ok | 15 - test/run-stub/ok/reversi.ic-stub-run.ok | 20 -- test/run-stub/ok/rts-stats.ic-stub-run.ok | 5 - test/run-stub/ok/self-calls.ic-stub-run.ok | 11 - test/run-stub/ok/self-calls.run-ir.ok | 7 - test/run-stub/ok/self-calls.run-low.ok | 7 - test/run-stub/ok/self-calls.run.ok | 7 - test/run-stub/ok/simple-throw.ic-stub-run.ok | 9 - test/run-stub/overflow.mo | 34 --- test/run-stub/print-from-init.mo | 3 - test/run-stub/query.mo | 29 -- test/run-stub/reject.mo | 29 -- test/run-stub/reversi.mo | 274 ------------------ test/run-stub/self-calls.mo | 30 -- test/run-stub/unsupported.mo | 81 ------ test/run.sh | 83 ++++-- test/{run-drun => run}/arity_bug.mo | 0 test/{run-drun => run}/modexp1.mo | 0 test/{run-drun => run}/modexp2.mo | 0 test/{run-drun => run}/modexp3.mo | 0 test/{run-drun => run}/modexp4.mo | 0 test/{run-drun => run}/modules-bwd.mo | 0 test/run/ok/show.run-ir.ok | 35 +++ test/run/ok/show.run-low.ok | 35 +++ test/run/ok/show.run.ok | 35 +++ test/run/ok/show.wasm-run.ok | 35 +++ test/run/ok/text-iter.run-ir.ok | 229 +++++++++++++++ test/run/ok/text-iter.run-low.ok | 229 +++++++++++++++ test/run/ok/text-iter.run.ok | 229 +++++++++++++++ test/run/ok/text-iter.wasm-run.ok | 229 +++++++++++++++ test/run/show.mo | 36 +++ test/run/text-iter.mo | 69 +++++ 419 files changed, 2691 insertions(+), 2260 deletions(-) rename test/{run-stub => run-drun}/AST-64.mo (88%) create mode 100644 test/run-drun/AST-66.mo rename test/{run-stub => run-drun}/GIT-843.mo (76%) rename test/{run-stub => run-drun}/actor-creation.mo (90%) create mode 100644 test/run-drun/async-any.mo create mode 100644 test/run-drun/async-calls1.mo create mode 100644 test/run-drun/async-calls2.mo create mode 100644 test/run-drun/async-calls3.mo create mode 100644 test/run-drun/async-free-var.mo create mode 100644 test/run-drun/async-loop-while.mo create mode 100644 test/run-drun/async-loop.mo create mode 100644 test/run-drun/async-new-obj.mo create mode 100644 test/run-drun/async-obj-mut.mo create mode 100644 test/run-drun/async-while.mo create mode 100644 test/run-drun/await.mo create mode 100644 test/run-drun/block.mo rename test/{run-stub => run-drun}/chat.mo (99%) create mode 100644 test/run-drun/closure-params.mo rename test/{run-stub => run-drun}/control.mo (92%) rename test/{run-stub => run-drun}/count-callbacks.mo (95%) rename test/{run-stub => run-drun}/create-then-trap.mo (80%) rename test/{run-stub => run-drun}/data-params.mo (98%) rename test/{run-stub => run-drun}/divide-by-zero.mo (100%) create mode 100644 test/run-drun/empty-actor.mo rename test/{run-stub => run-drun}/flatten-awaitables.mo (97%) create mode 100644 test/run-drun/for-await.mo rename test/{run-stub => run-drun}/free-callbacks.mo (94%) rename test/{run-stub => run-drun}/general-type-components.mo (94%) rename test/{run-stub => run-drun}/hello-world-async.mo (69%) rename test/{run-stub => run-drun}/hello-world-await.mo (83%) delete mode 100644 test/run-drun/hello-world-message2.mo rename test/{run-stub => run-drun}/indirect-counter.mo (96%) create mode 100644 test/run-drun/interleave.mo rename test/{run-stub => run-drun}/issue-894.mo (89%) rename test/{run-stub => run-drun}/local-throw.mo (94%) delete mode 100644 test/run-drun/multiple-actors.mo create mode 100644 test/run-drun/nary-async.mo rename test/{run-stub => run-drun}/ok/AST-64.ic-stub-run.ok (100%) create mode 100644 test/run-drun/ok/AST-66.comp.ok rename test/run-drun/ok/{counter2.drun-run.ret.ok => AST-66.comp.ret.ok} (100%) rename test/{run-stub/ok/idl-unit.ic-stub-run.ok => run-drun/ok/AST-66.ic-stub-run.ok} (77%) create mode 100644 test/run-drun/ok/GIT-843.drun-run.ok rename test/{run-stub => run-drun}/ok/GIT-843.run-ir.ok (100%) rename test/{run-stub => run-drun}/ok/GIT-843.run-low.ok (100%) rename test/{run-stub => run-drun}/ok/GIT-843.run.ok (100%) rename test/{run-stub => run-drun}/ok/actor-creation.ic-stub-run.ok (100%) rename test/{run-stub => run-drun}/ok/actor-creation.run-ir.ok (100%) rename test/{run-stub => run-drun}/ok/actor-creation.run-low.ok (100%) rename test/{run-stub => run-drun}/ok/actor-creation.run.ok (100%) create mode 100644 test/run-drun/ok/array-out-of-bounds.run-ir.ok create mode 100644 test/run-drun/ok/array-out-of-bounds.run-low.ok create mode 100644 test/run-drun/ok/array-out-of-bounds.run.ok create mode 100644 test/run-drun/ok/async-any.comp.ok rename test/run-drun/ok/{hello-world-message2.drun-run.ret.ok => async-any.comp.ret.ok} (100%) rename test/{run-stub => run-drun}/ok/async-any.ic-stub-run.ok (58%) create mode 100644 test/run-drun/ok/async-calls1.comp.ok rename test/run-drun/ok/{multiple-actors.comp.ret.ok => async-calls1.comp.ret.ok} (100%) rename test/{run-stub/ok/GIT-843.ic-stub-run.ok => run-drun/ok/async-calls1.ic-stub-run.ok} (58%) create mode 100644 test/run-drun/ok/async-calls2.comp.ok rename test/run-drun/ok/{self-calls.comp.ret.ok => async-calls2.comp.ret.ok} (100%) rename test/{run-stub/ok/async-calls.ic-stub-run.ok => run-drun/ok/async-calls2.ic-stub-run.ok} (58%) create mode 100644 test/run-drun/ok/async-calls3.comp.ok rename test/{run-stub/ok/divide-by-zero.ic-stub-run.ret.ok => run-drun/ok/async-calls3.comp.ret.ok} (100%) create mode 100644 test/run-drun/ok/async-calls3.ic-stub-run.ok create mode 100644 test/run-drun/ok/async-free-var.comp.ok rename test/{run-stub/ok/divide-by-zero.run.ret.ok => run-drun/ok/async-free-var.comp.ret.ok} (100%) rename test/{run-stub => run-drun}/ok/async-free-var.ic-stub-run.ok (64%) rename test/{run-stub => run-drun}/ok/async-free-var.run-ir.ok (100%) rename test/{run-stub => run-drun}/ok/async-free-var.run-low.ok (100%) rename test/{run-stub => run-drun}/ok/async-free-var.run.ok (100%) create mode 100644 test/run-drun/ok/async-loop-while.comp.ok rename test/{run-stub/ok/multiple-actors.comp.ret.ok => run-drun/ok/async-loop-while.comp.ret.ok} (100%) rename test/{run-stub => run-drun}/ok/async-loop-while.ic-stub-run.ok (64%) rename test/{run-stub => run-drun}/ok/async-loop-while.run-ir.ok (100%) rename test/{run-stub => run-drun}/ok/async-loop-while.run-low.ok (100%) rename test/{run-stub => run-drun}/ok/async-loop-while.run.ok (100%) create mode 100644 test/run-drun/ok/async-loop.tc.ok rename test/{run-stub/ok/unsupported.comp.ret.ok => run-drun/ok/async-loop.tc.ret.ok} (100%) create mode 100644 test/run-drun/ok/async-new-obj.comp.ok create mode 100644 test/run-drun/ok/async-new-obj.comp.ret.ok rename test/{run-stub => run-drun}/ok/async-new-obj.ic-stub-run.ok (64%) rename test/{run-stub => run-drun}/ok/async-new-obj.run-ir.ok (100%) rename test/{run-stub => run-drun}/ok/async-new-obj.run-low.ok (100%) rename test/{run-stub => run-drun}/ok/async-new-obj.run.ok (100%) create mode 100644 test/run-drun/ok/async-obj-mut.comp.ok create mode 100644 test/run-drun/ok/async-obj-mut.comp.ret.ok rename test/{run-stub => run-drun}/ok/async-obj-mut.ic-stub-run.ok (65%) rename test/{run-stub => run-drun}/ok/async-obj-mut.run-ir.ok (100%) rename test/{run-stub => run-drun}/ok/async-obj-mut.run-low.ok (100%) rename test/{run-stub => run-drun}/ok/async-obj-mut.run.ok (100%) create mode 100644 test/run-drun/ok/async-while.comp.ok create mode 100644 test/run-drun/ok/async-while.comp.ret.ok rename test/{run-stub => run-drun}/ok/async-while.ic-stub-run.ok (64%) rename test/{run-stub => run-drun}/ok/async-while.run-ir.ok (100%) rename test/{run-stub => run-drun}/ok/async-while.run-low.ok (100%) rename test/{run-stub => run-drun}/ok/async-while.run.ok (100%) create mode 100644 test/run-drun/ok/await.comp.ok create mode 100644 test/run-drun/ok/await.comp.ret.ok rename test/{run-stub => run-drun}/ok/await.ic-stub-run.ok (82%) rename test/{run-stub => run-drun}/ok/await.run-ir.ok (100%) rename test/{run-stub => run-drun}/ok/await.run-low.ok (100%) rename test/{run-stub => run-drun}/ok/await.run.ok (100%) create mode 100644 test/run-drun/ok/block.comp.ok create mode 100644 test/run-drun/ok/block.comp.ret.ok rename test/{run-stub => run-drun}/ok/block.ic-stub-run.ok (64%) rename test/{run-stub => run-drun}/ok/block.run-ir.ok (100%) rename test/{run-stub => run-drun}/ok/block.run-low.ok (100%) rename test/{run-stub => run-drun}/ok/block.run.ok (100%) rename test/{run-stub => run-drun}/ok/chat.ic-stub-run.ok (100%) rename test/{run-stub => run-drun}/ok/chat.run-ir.ok (100%) rename test/{run-stub => run-drun}/ok/chat.run-low.ok (100%) rename test/{run-stub => run-drun}/ok/chat.run.ok (100%) create mode 100644 test/run-drun/ok/closure-params.comp.ok create mode 100644 test/run-drun/ok/closure-params.comp.ret.ok rename test/{run-stub => run-drun}/ok/closure-params.ic-stub-run.ok (64%) rename test/{run-stub => run-drun}/ok/closure-params.run-ir.ok (100%) rename test/{run-stub => run-drun}/ok/closure-params.run-low.ok (100%) rename test/{run-stub => run-drun}/ok/closure-params.run.ok (100%) create mode 100644 test/run-drun/ok/count-callbacks.comp.ok create mode 100644 test/run-drun/ok/count-callbacks.comp.ret.ok rename test/{run-stub => run-drun}/ok/count-callbacks.ic-stub-run.ok (75%) create mode 100644 test/run-drun/ok/counter2.comp.ok create mode 100644 test/run-drun/ok/counter2.comp.ret.ok delete mode 100644 test/run-drun/ok/counter2.drun-run.ok rename test/{run-stub => run-drun}/ok/counter2.ic-stub-run.ok (66%) rename test/{run-stub => run-drun}/ok/counter2.run-ir.ok (100%) rename test/{run-stub => run-drun}/ok/counter2.run-low.ok (100%) rename test/{run-stub => run-drun}/ok/counter2.run.ok (100%) create mode 100644 test/run-drun/ok/create-then-trap.comp.ok create mode 100644 test/run-drun/ok/create-then-trap.comp.ret.ok rename test/{run-stub => run-drun}/ok/create-then-trap.ic-stub-run.ok (51%) rename test/{run-stub => run-drun}/ok/create-then-trap.run-ir.ok (100%) rename test/{run-stub => run-drun}/ok/create-then-trap.run-low.ok (100%) rename test/{run-stub => run-drun}/ok/create-then-trap.run.ok (100%) create mode 100644 test/run-drun/ok/data-params.comp.ok create mode 100644 test/run-drun/ok/data-params.comp.ret.ok rename test/{run-stub => run-drun}/ok/data-params.ic-stub-run.ok (90%) rename test/{run-stub => run-drun}/ok/data-params.run-ir.ok (100%) rename test/{run-stub => run-drun}/ok/data-params.run-low.ok (100%) rename test/{run-stub => run-drun}/ok/data-params.run.ok (100%) rename test/{run-stub => run-drun}/ok/data-params.tc.ok (100%) create mode 100644 test/run-drun/ok/divide-by-zero.drun-run.ok rename test/{run-stub => run-drun}/ok/divide-by-zero.run-ir.ok (100%) rename test/{run-stub => run-drun}/ok/divide-by-zero.run-low.ok (100%) rename test/{run-stub => run-drun}/ok/divide-by-zero.run.ok (100%) create mode 100644 test/run-drun/ok/divide-by-zero.run.ret.ok rename test/run-drun/ok/{arity_bug.drun-run.ok => empty-actor.drun-run.ok} (100%) create mode 100644 test/run-drun/ok/flatten-awaitables.comp.ok create mode 100644 test/run-drun/ok/flatten-awaitables.comp.ret.ok rename test/{run-stub => run-drun}/ok/flatten-awaitables.ic-stub-run.ok (75%) rename test/{run-stub => run-drun}/ok/flatten-awaitables.run-ir.ok (100%) rename test/{run-stub => run-drun}/ok/flatten-awaitables.run-low.ok (100%) rename test/{run-stub => run-drun}/ok/flatten-awaitables.run.ok (100%) rename test/{run-stub => run-drun}/ok/flatten-awaitables.tc.ok (54%) create mode 100644 test/run-drun/ok/for-await.comp.ok create mode 100644 test/run-drun/ok/for-await.comp.ret.ok rename test/{run-stub => run-drun}/ok/for-await.ic-stub-run.ok (64%) rename test/{run-stub => run-drun}/ok/for-await.run-ir.ok (100%) rename test/{run-stub => run-drun}/ok/for-await.run-low.ok (100%) rename test/{run-stub => run-drun}/ok/for-await.run.ok (100%) create mode 100644 test/run-drun/ok/free-callbacks.comp.ok create mode 100644 test/run-drun/ok/free-callbacks.comp.ret.ok rename test/{run-stub => run-drun}/ok/free-callbacks.ic-stub-run.ok (64%) create mode 100644 test/run-drun/ok/hello-world-async.comp.ok create mode 100644 test/run-drun/ok/hello-world-async.comp.ret.ok rename test/{run-stub => run-drun}/ok/hello-world-async.ic-stub-run.ok (62%) rename test/{run-stub => run-drun}/ok/hello-world-async.run-ir.ok (100%) rename test/{run-stub => run-drun}/ok/hello-world-async.run-low.ok (100%) rename test/{run-stub => run-drun}/ok/hello-world-async.run.ok (100%) create mode 100644 test/run-drun/ok/hello-world-await.comp.ok create mode 100644 test/run-drun/ok/hello-world-await.comp.ret.ok rename test/{run-stub => run-drun}/ok/hello-world-await.ic-stub-run.ok (62%) rename test/{run-stub => run-drun}/ok/hello-world-await.run-ir.ok (100%) rename test/{run-stub => run-drun}/ok/hello-world-await.run-low.ok (100%) rename test/{run-stub => run-drun}/ok/hello-world-await.run.ok (100%) delete mode 100644 test/run-drun/ok/hello-world-message2.drun-run.ok rename test/{run-stub => run-drun}/ok/ic-calls.ic-stub-run.ok (58%) rename test/{run-stub => run-drun}/ok/indirect-counter.ic-stub-run.ok (100%) rename test/{run-stub => run-drun}/ok/indirect-counter.run-ir.ok (100%) rename test/{run-stub => run-drun}/ok/indirect-counter.run-low.ok (100%) rename test/{run-stub => run-drun}/ok/indirect-counter.run.ok (100%) create mode 100644 test/run-drun/ok/interleave.comp.ok create mode 100644 test/run-drun/ok/interleave.comp.ret.ok rename test/{run-stub => run-drun}/ok/interleave.ic-stub-run.ok (82%) rename test/{run-stub => run-drun}/ok/interleave.run-ir.ok (100%) rename test/{run-stub => run-drun}/ok/interleave.run-low.ok (100%) rename test/{run-stub => run-drun}/ok/interleave.run.ok (100%) create mode 100644 test/run-drun/ok/issue-894.comp.ok create mode 100644 test/run-drun/ok/issue-894.comp.ret.ok rename test/{run-stub => run-drun}/ok/issue-894.ic-stub-run.ok (63%) rename test/{run-stub => run-drun}/ok/issue-894.run-ir.ok (100%) rename test/{run-stub => run-drun}/ok/issue-894.run-low.ok (100%) rename test/{run-stub => run-drun}/ok/issue-894.run.ok (100%) create mode 100644 test/run-drun/ok/local-throw.comp.ok create mode 100644 test/run-drun/ok/local-throw.comp.ret.ok rename test/{run-stub => run-drun}/ok/local-throw.ic-stub-run.ok (61%) rename test/{run-stub => run-drun}/ok/local-throw.run-ir.ok (100%) rename test/{run-stub => run-drun}/ok/local-throw.run-low.ok (100%) rename test/{run-stub => run-drun}/ok/local-throw.run.ok (100%) delete mode 100644 test/run-drun/ok/modexp1.drun-run.ok delete mode 100644 test/run-drun/ok/modexp2.drun-run.ok delete mode 100644 test/run-drun/ok/modexp3.drun-run.ok delete mode 100644 test/run-drun/ok/modexp4.drun-run.ok delete mode 100644 test/run-drun/ok/modules-bwd.drun-run.ok delete mode 100644 test/run-drun/ok/multiple-actors.comp.ok create mode 100644 test/run-drun/ok/nary-async.comp.ok create mode 100644 test/run-drun/ok/nary-async.comp.ret.ok create mode 100644 test/run-drun/ok/nary-async.ic-stub-run.ok rename test/{run-stub => run-drun}/ok/nary-async.run-ir.ok (100%) rename test/{run-stub => run-drun}/ok/nary-async.run-low.ok (100%) rename test/{run-stub => run-drun}/ok/nary-async.run.ok (100%) create mode 100644 test/run-drun/ok/oneway.comp.ok create mode 100644 test/run-drun/ok/oneway.comp.ret.ok delete mode 100644 test/run-drun/ok/oneway.drun-run.ok create mode 100644 test/run-drun/ok/oneway.ic-stub-run.ok rename test/run-drun/ok/{test_oneway.run-ir.ok => oneway.run-ir.ok} (100%) rename test/run-drun/ok/{test_oneway.run-low.ok => oneway.run-low.ok} (100%) rename test/run-drun/ok/{test_oneway.run.ok => oneway.run.ok} (100%) create mode 100644 test/run-drun/ok/overflow.comp.ok create mode 100644 test/run-drun/ok/overflow.comp.ret.ok rename test/{run-stub => run-drun}/ok/overflow.ic-stub-run.ok (66%) create mode 100644 test/run-drun/ok/overflow.run-ir.ok create mode 100644 test/run-drun/ok/overflow.run-low.ok create mode 100644 test/run-drun/ok/overflow.run.ok create mode 100644 test/run-drun/ok/pass-references.comp.ok create mode 100644 test/run-drun/ok/pass-references.comp.ret.ok rename test/{run-stub => run-drun}/ok/pass-references.ic-stub-run.ok (60%) rename test/{run-stub => run-drun}/ok/pass-references.run-ir.ok (100%) rename test/{run-stub => run-drun}/ok/pass-references.run-low.ok (100%) rename test/{run-stub => run-drun}/ok/pass-references.run.ok (100%) create mode 100644 test/run-drun/ok/query2.comp.ok create mode 100644 test/run-drun/ok/query2.comp.ret.ok rename test/{run-stub => run-drun}/ok/query2.ic-stub-run.ok (69%) rename test/{run-stub => run-drun}/ok/query2.run-ir.ok (63%) rename test/{run-stub => run-drun}/ok/query2.run-low.ok (63%) rename test/{run-stub => run-drun}/ok/query2.run.ok (63%) rename test/{run-stub => run-drun}/ok/reference-params.ic-stub-run.ok (100%) rename test/{run-stub => run-drun}/ok/reference-params.run-ir.ok (100%) rename test/{run-stub => run-drun}/ok/reference-params.run-low.ok (100%) rename test/{run-stub => run-drun}/ok/reference-params.run.ok (100%) create mode 100644 test/run-drun/ok/rts-stats.drun-run.ok delete mode 100644 test/run-drun/ok/self-calls.comp.ok delete mode 100644 test/run-drun/ok/self-calls.tc.ok create mode 100644 test/run-drun/ok/shared-object.comp.ok create mode 100644 test/run-drun/ok/shared-object.comp.ret.ok rename test/{run-stub => run-drun}/ok/shared-object.ic-stub-run.ok (58%) create mode 100644 test/run-drun/ok/simple-throw.drun-run.ok rename test/{run-stub => run-drun}/ok/simple-throw.run-ir.ok (100%) rename test/{run-stub => run-drun}/ok/simple-throw.run-low.ok (100%) rename test/{run-stub => run-drun}/ok/simple-throw.run.ok (100%) create mode 100644 test/run-drun/ok/test_oneway.tc.ok create mode 100644 test/run-drun/ok/test_oneway.tc.ret.ok delete mode 100644 test/run-drun/ok/the-answer.drun-run.ok delete mode 100644 test/run-drun/ok/the-answer.run-ir.ok delete mode 100644 test/run-drun/ok/the-answer.run-low.ok delete mode 100644 test/run-drun/ok/the-answer.run.ok create mode 100644 test/run-drun/ok/transpose.comp.ok create mode 100644 test/run-drun/ok/transpose.comp.ret.ok rename test/{run-stub => run-drun}/ok/transpose.ic-stub-run.ok (61%) rename test/{run-stub => run-drun}/ok/transpose.run-ir.ok (100%) rename test/{run-stub => run-drun}/ok/transpose.run-low.ok (100%) rename test/{run-stub => run-drun}/ok/transpose.run.ok (100%) create mode 100644 test/run-drun/ok/type-lub.comp.ok create mode 100644 test/run-drun/ok/type-lub.comp.ret.ok rename test/{run-stub => run-drun}/ok/type-lub.ic-stub-run.ok (100%) rename test/{run-stub/ok/unsupported.comp.ok => run-drun/ok/unsupported.comp-stub.ok} (78%) create mode 100644 test/run-drun/ok/unsupported.comp-stub.ret.ok create mode 100644 test/run-drun/overflow.mo rename test/{run-stub => run-drun}/pass-references.mo (88%) rename test/{run-stub => run-drun}/query2.mo (64%) rename test/{run-stub => run-drun}/reference-params.mo (98%) rename test/{run-stub => run-drun}/rts-stats.mo (100%) delete mode 100644 test/run-drun/self-calls.mo rename test/{run-stub => run-drun}/shared-object.mo (89%) rename test/{run-stub => run-drun}/simple-throw.mo (90%) delete mode 100644 test/run-drun/the-answer.mo rename test/{run-stub => run-drun}/transpose.mo (92%) rename test/{run-stub => run-drun}/type-lub.mo (100%) delete mode 100644 test/run-stub/AST-66.mo delete mode 100644 test/run-stub/Makefile delete mode 100644 test/run-stub/async-any.mo delete mode 100644 test/run-stub/async-calls.mo delete mode 100644 test/run-stub/async-free-var.mo delete mode 100644 test/run-stub/async-loop-while.mo delete mode 100644 test/run-stub/async-loop.mo delete mode 100644 test/run-stub/async-new-obj.mo delete mode 100644 test/run-stub/async-obj-mut.mo delete mode 100644 test/run-stub/async-while.mo delete mode 100644 test/run-stub/await.mo delete mode 100644 test/run-stub/block.mo delete mode 100644 test/run-stub/closure-params.mo delete mode 100644 test/run-stub/counter.mo delete mode 100644 test/run-stub/counter2.mo delete mode 100644 test/run-stub/empty-actor.mo delete mode 100644 test/run-stub/for-await.mo delete mode 100644 test/run-stub/hello-world-return.mo delete mode 100644 test/run-stub/ic-calls.mo delete mode 100644 test/run-stub/idl-any.mo delete mode 100644 test/run-stub/idl-bad.mo delete mode 100644 test/run-stub/idl-field-escape.mo delete mode 100644 test/run-stub/idl-func.mo delete mode 100644 test/run-stub/idl-nary.mo delete mode 100644 test/run-stub/idl-nat-int.mo delete mode 100644 test/run-stub/idl-option.mo delete mode 100644 test/run-stub/idl-pair.mo delete mode 100644 test/run-stub/idl-record.mo delete mode 100644 test/run-stub/idl-tuple.mo delete mode 100644 test/run-stub/idl-unit.mo delete mode 100644 test/run-stub/idl-variant.mo delete mode 100644 test/run-stub/idl-vector.mo delete mode 100644 test/run-stub/interleave.mo delete mode 100644 test/run-stub/multiple-actors.mo delete mode 100644 test/run-stub/nary-async.mo delete mode 100644 test/run-stub/ok/AST-66.ic-stub-run.ok delete mode 100644 test/run-stub/ok/async-loop.ic-stub-run.ok delete mode 100644 test/run-stub/ok/async-loop.run-ir.ok delete mode 100644 test/run-stub/ok/async-loop.run-low.ok delete mode 100644 test/run-stub/ok/async-loop.run.ok delete mode 100644 test/run-stub/ok/control.ic-stub-run.ok delete mode 100644 test/run-stub/ok/counter.ic-stub-run.ok delete mode 100644 test/run-stub/ok/divide-by-zero.ic-stub-run.ok delete mode 100644 test/run-stub/ok/empty-actor.ic-stub-run.ok delete mode 100644 test/run-stub/ok/general-type-components.ic-stub-run.ok delete mode 100644 test/run-stub/ok/hello-world-return.ic-stub-run.ok delete mode 100644 test/run-stub/ok/ic-calls.run-ir.ok delete mode 100644 test/run-stub/ok/ic-calls.run-low.ok delete mode 100644 test/run-stub/ok/ic-calls.run.ok delete mode 100644 test/run-stub/ok/ic-calls.tc.ok delete mode 100644 test/run-stub/ok/idl-any.ic-stub-run.ok delete mode 100644 test/run-stub/ok/idl-bad.ic-stub-run.ok delete mode 100644 test/run-stub/ok/idl-field-escape.ic-stub-run.ok delete mode 100644 test/run-stub/ok/idl-func.ic-stub-run.ok delete mode 100644 test/run-stub/ok/idl-nary.ic-stub-run.ok delete mode 100644 test/run-stub/ok/idl-nat-int.ic-stub-run.ok delete mode 100644 test/run-stub/ok/idl-option.ic-stub-run.ok delete mode 100644 test/run-stub/ok/idl-pair.ic-stub-run.ok delete mode 100644 test/run-stub/ok/idl-record.ic-stub-run.ok delete mode 100644 test/run-stub/ok/idl-tuple.ic-stub-run.ok delete mode 100644 test/run-stub/ok/idl-variant.ic-stub-run.ok delete mode 100644 test/run-stub/ok/idl-vector.ic-stub-run.ok delete mode 100644 test/run-stub/ok/multiple-actors.comp.ok delete mode 100644 test/run-stub/ok/nary-async.ic-stub-run.ok delete mode 100644 test/run-stub/ok/overflow.run-ir.ok delete mode 100644 test/run-stub/ok/overflow.run-low.ok delete mode 100644 test/run-stub/ok/overflow.run.ok delete mode 100644 test/run-stub/ok/print-from-init.ic-stub-run.ok delete mode 100644 test/run-stub/ok/print-from-init.run-ir.ok delete mode 100644 test/run-stub/ok/print-from-init.run-low.ok delete mode 100644 test/run-stub/ok/print-from-init.run.ok delete mode 100644 test/run-stub/ok/query.ic-stub-run.ok delete mode 100644 test/run-stub/ok/reject.ic-stub-run.ok delete mode 100644 test/run-stub/ok/reversi.ic-stub-run.ok delete mode 100644 test/run-stub/ok/rts-stats.ic-stub-run.ok delete mode 100644 test/run-stub/ok/self-calls.ic-stub-run.ok delete mode 100644 test/run-stub/ok/self-calls.run-ir.ok delete mode 100644 test/run-stub/ok/self-calls.run-low.ok delete mode 100644 test/run-stub/ok/self-calls.run.ok delete mode 100644 test/run-stub/ok/simple-throw.ic-stub-run.ok delete mode 100644 test/run-stub/overflow.mo delete mode 100644 test/run-stub/print-from-init.mo delete mode 100644 test/run-stub/query.mo delete mode 100644 test/run-stub/reject.mo delete mode 100644 test/run-stub/reversi.mo delete mode 100644 test/run-stub/self-calls.mo delete mode 100644 test/run-stub/unsupported.mo rename test/{run-drun => run}/arity_bug.mo (100%) rename test/{run-drun => run}/modexp1.mo (100%) rename test/{run-drun => run}/modexp2.mo (100%) rename test/{run-drun => run}/modexp3.mo (100%) rename test/{run-drun => run}/modexp4.mo (100%) rename test/{run-drun => run}/modules-bwd.mo (100%) create mode 100644 test/run/ok/show.run-ir.ok create mode 100644 test/run/ok/show.run-low.ok create mode 100644 test/run/ok/show.run.ok create mode 100644 test/run/ok/show.wasm-run.ok create mode 100644 test/run/ok/text-iter.run-ir.ok create mode 100644 test/run/ok/text-iter.run-low.ok create mode 100644 test/run/ok/text-iter.run.ok create mode 100644 test/run/ok/text-iter.wasm-run.ok create mode 100644 test/run/show.mo create mode 100644 test/run/text-iter.mo diff --git a/test/.gitignore b/test/.gitignore index 7acb84c198f..6b38fe97b53 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -16,3 +16,4 @@ _coverage *.wat-run *.tc *.wasm.map +*.mo.mangled diff --git a/test/Makefile b/test/Makefile index f61bbeb9723..558a137a001 100644 --- a/test/Makefile +++ b/test/Makefile @@ -3,7 +3,6 @@ all: $(MAKE) -C run $(MAKE) -C run-release $(MAKE) -C run-drun - $(MAKE) -C run-stub $(MAKE) -C repl $(MAKE) -C ld $(MAKE) -C idl @@ -23,7 +22,6 @@ quick: parallel: quick $(MAKE_PAR) -C run-drun quick - $(MAKE_PAR) -C run-stub quick $(MAKE_PAR) -C trap quick $(MAKE_PAR) -C run-deser quick @@ -36,7 +34,6 @@ coverage: $(MAKE) -C run; \ $(MAKE) -C run-release; \ $(MAKE) -C run-drun; \ - $(MAKE) -C run-stub; \ $(MAKE) -C repl; $(MAKE) -C ld || true bisect-ppx-report -I ../src/_build/ -html coverage/ _coverage/bisect*.out @@ -47,7 +44,6 @@ accept: $(MAKE) -C run accept $(MAKE) -C run-release accept $(MAKE) -C run-drun accept - $(MAKE) -C run-stub accept $(MAKE) -C repl accept $(MAKE) -C ld accept $(MAKE) -C idl accept @@ -60,7 +56,6 @@ clean: $(MAKE) -C run clean $(MAKE) -C run-release clean $(MAKE) -C run-drun clean - $(MAKE) -C run-stub clean $(MAKE) -C repl clean $(MAKE) -C ld clean $(MAKE) -C mo-idl clean diff --git a/test/repl/type-lub-repl.sh b/test/repl/type-lub-repl.sh index b94f5bf9759..2d5167ef991 100755 --- a/test/repl/type-lub-repl.sh +++ b/test/repl/type-lub-repl.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # Tests that correct lub types are inferred when values appear in arrays -${MOC:-$(dirname "$BASH_SOURCE")/../../src/moc} -i ../run-stub/type-lub.mo <<__END__ +${MOC:-$(dirname "$BASH_SOURCE")/../../src/moc} -i ../run-drun/type-lub.mo <<__END__ opts; nulls; incompatible_objs; diff --git a/test/run-stub/AST-64.mo b/test/run-drun/AST-64.mo similarity index 88% rename from test/run-stub/AST-64.mo rename to test/run-drun/AST-64.mo index cf83b84b2c7..1d758f74748 100644 --- a/test/run-stub/AST-64.mo +++ b/test/run-drun/AST-64.mo @@ -13,4 +13,5 @@ let _ = (actor { public func x() { x() } }) : Any; let _ = (object this { public func x() { this.x() } }) : Any; let _ = (object { public func x() { x() } }) : Any; - +// certainly won’t work on drun +//SKIP comp diff --git a/test/run-drun/AST-66.mo b/test/run-drun/AST-66.mo new file mode 100644 index 00000000000..ac7d172429f --- /dev/null +++ b/test/run-drun/AST-66.mo @@ -0,0 +1,18 @@ +// test cps conversion of async blocks with type decs +actor a { + public func go(){ + ignore async{ + type T = Null; + await { async (null:T) }; + }; + + ignore async{ + type T = U; + let _ = await { async (null:T) }; + type U = Null; + await { async (null:T) }; + }; + }; +}; +a.go(); //OR-CALL ingress go "DIDL\x00\x00" + diff --git a/test/run-stub/GIT-843.mo b/test/run-drun/GIT-843.mo similarity index 76% rename from test/run-stub/GIT-843.mo rename to test/run-drun/GIT-843.mo index 5f02db7e1c1..b9bdf431d1a 100644 --- a/test/run-stub/GIT-843.mo +++ b/test/run-drun/GIT-843.mo @@ -3,4 +3,5 @@ actor Bad { public func Bad (){ debugPrint "ok"}; }; -Bad.Bad(); +Bad.Bad(); //OR-CALL ingress Bad "DIDL\x00\x00" + diff --git a/test/run-drun/Makefile b/test/run-drun/Makefile index 5193a683b31..1522515fcef 100644 --- a/test/run-drun/Makefile +++ b/test/run-drun/Makefile @@ -1,4 +1,4 @@ -RUNFLAGS = -2 +RUNFLAGS = -d all: ../run.sh $(RUNFLAGS) *.mo diff --git a/test/run-stub/actor-creation.mo b/test/run-drun/actor-creation.mo similarity index 90% rename from test/run-stub/actor-creation.mo rename to test/run-drun/actor-creation.mo index a4420eb1be5..96c82eaeb02 100644 --- a/test/run-stub/actor-creation.mo +++ b/test/run-drun/actor-creation.mo @@ -19,3 +19,6 @@ actor a { }; debugPrint ("main actor calling a.foo()"); a.foo(); + +// certainly won’t work on drun +//SKIP comp diff --git a/test/run-drun/array-out-of-bounds.mo b/test/run-drun/array-out-of-bounds.mo index a55586ebfd0..6cb386c27c4 100644 --- a/test/run-drun/array-out-of-bounds.mo +++ b/test/run-drun/array-out-of-bounds.mo @@ -2,16 +2,16 @@ actor a { let xs = [0, 1, 2, 3, 4]; let ys = []; - public func foo1() : async () { + public func foo1() { ignore(xs[5]); debugPrint("Unreachable code reached"); }; - public func foo2() : async () { + public func foo2() { ignore(ys[0]); debugPrint("Unreachable code reached"); }; }; -//CALL ingress foo1 0x4449444C0000 -//CALL ingress foo2 0x4449444C0000 +a.foo1(); //OR-CALL ingress foo1 0x4449444C0000 +a.foo2(); //OR-CALL ingress foo2 0x4449444C0000 diff --git a/test/run-drun/async-any.mo b/test/run-drun/async-any.mo new file mode 100644 index 00000000000..d01734001eb --- /dev/null +++ b/test/run-drun/async-any.mo @@ -0,0 +1,6 @@ +actor a { + public func go() { + let _ = async { ():Any }; + } +}; +a.go(); //OR-CALL ingress go "DIDL\x00\x00" diff --git a/test/run-drun/async-calls1.mo b/test/run-drun/async-calls1.mo new file mode 100644 index 00000000000..aedcde1e228 --- /dev/null +++ b/test/run-drun/async-calls1.mo @@ -0,0 +1,12 @@ +/* This tests checks if messages to actors are really asynchronous, and complete + before delivery. +*/ + +actor a { + var x : Bool = false; + + public func bump() { assert (x == false); x := true; assert (x == true); }; + + public func go() { assert (x == false); bump(); assert (x == false); }; +}; +a.go(); //OR-CALL ingress go "DIDL\x00\x00" diff --git a/test/run-drun/async-calls2.mo b/test/run-drun/async-calls2.mo new file mode 100644 index 00000000000..cd4a8bbdf89 --- /dev/null +++ b/test/run-drun/async-calls2.mo @@ -0,0 +1,14 @@ +/* This tests checks if messages to actors are really asynchronous, and complete + before delivery. +*/ + +actor a { + var x : Bool = false; + + public func bump() { assert (x == false); x := true; assert (x == true); }; + + public func is_true() { assert (x == true); }; + + public func go() { assert (x == false); bump(); assert (x == false); is_true(); }; +}; +a.go(); //OR-CALL ingress go "DIDL\x00\x00" diff --git a/test/run-drun/async-calls3.mo b/test/run-drun/async-calls3.mo new file mode 100644 index 00000000000..1adaa455d7a --- /dev/null +++ b/test/run-drun/async-calls3.mo @@ -0,0 +1,19 @@ +/* This tests checks if messages to actors are really asynchronous, and complete + before delivery. +*/ + +actor a { + var x : Bool = false; + + public func test(b : Bool) { + if (b) { assert (x == false); x := true; assert (x == true); } + else { assert (x == false); test(false); assert (x == false); is_true(); } + }; + + public func is_true() { assert (x == true); }; + + public func go() { + test(true); + } +}; +a.go(); //OR-CALL ingress go "DIDL\x00\x00" diff --git a/test/run-drun/async-free-var.mo b/test/run-drun/async-free-var.mo new file mode 100644 index 00000000000..f8fecce961d --- /dev/null +++ b/test/run-drun/async-free-var.mo @@ -0,0 +1,18 @@ +actor a { + public func go() = ignore async { + var x = "A"; + debugPrint x; + let a = async { + debugPrint "Now in async"; + debugPrint x; + x := "B"; + debugPrint x; + }; + debugPrint x; + x := "C"; + debugPrint x; + await a; + debugPrint x; + }; +}; +a.go(); //OR-CALL ingress go "DIDL\x00\x00" diff --git a/test/run-drun/async-loop-while.mo b/test/run-drun/async-loop-while.mo new file mode 100644 index 00000000000..b99c622a8ac --- /dev/null +++ b/test/run-drun/async-loop-while.mo @@ -0,0 +1,59 @@ +actor a { + public func go() = ignore async { + { var i = 0; + var j = 0; + loop { + debugPrintNat(j); + assert(j == i); + i += 1; + j += 1; + } while (i < 3); + assert(i == 3); + }; + + + { + var i = 0; + var j = 0; + loop { + debugPrintNat(j); + assert(j == i); + i += 1; + j += 1; + } while (await async (i < 3)); + assert(i == 3); + }; + + { + var i = 0; + var j = 0; + loop { + debugPrintNat(j); + assert(j == i); + await (async (i += 1)); + j += 1; + } while (i < 3); + assert(i == 3); + }; + + { + var i = 0; + var j = 0; + label l + loop { + if (j > 2) { + break l; + assert(false); + }; + debugPrintNat(j); + assert(j == i); + await (async (i += 1)); + j += 1; + continue l; + assert(false); + } while (true); + assert(i == 3); + }; + }; +}; +a.go(); //OR-CALL ingress go "DIDL\x00\x00" diff --git a/test/run-drun/async-loop.mo b/test/run-drun/async-loop.mo new file mode 100644 index 00000000000..4a8375753f8 --- /dev/null +++ b/test/run-drun/async-loop.mo @@ -0,0 +1,71 @@ +actor a { + public func go() = ignore async { + { var i = 0; + var j = 0; + label l + loop { + debugPrintNat(j); + assert(j == i); + i += 1; + j += 1; + if (j == 3) break l else continue l; + } ; + assert(i == 3); + }; + + + { + var i = 0; + var j = 0; + label l + loop { + debugPrintNat(j); + assert(j == i); + i += 1; + j += 1; + if (await async (j == 3)) break l else continue l; + assert(false); + }; + assert(i == 3); + }; + + { + var i = 0; + var j = 0; + label l + loop { + debugPrintNat(j); + assert(j == i); + await (async (i += 1)); + j += 1; + if (j == 3) break l else continue l; + assert(false); + }; + assert(i == 3); + }; + + { + var i = 0; + var j = 0; + label l + loop { + if (j > 2) { + break l; + assert(false); + }; + debugPrintNat(j); + assert(j == i); + await (async (i += 1)); + j += 1; + continue l; + assert(false); + }; + assert(i == 3); + }; + + }; + + + + + diff --git a/test/run-drun/async-new-obj.mo b/test/run-drun/async-new-obj.mo new file mode 100644 index 00000000000..1865b45a247 --- /dev/null +++ b/test/run-drun/async-new-obj.mo @@ -0,0 +1,66 @@ +actor a { + public func go() = ignore async { + /* Test asynchronous construction of an object */ + + let a = async { + let o = object { + let a = "aa"; + let b = "ab"; + public func get_a() : Text { a }; + public func get_b() : Text { b }; + }; + let (a, b) = (o.get_a(), o.get_b()); + debugPrint (a#b); + }; + + let b = async { + let o = object { + let a = await (async "ba") ; + let b = "bb"; + public func get_a() : Text { a }; + public func get_b() : Text { b }; + }; + let (a, b) = (o.get_a(), o.get_b()); + debugPrint (a#b); + }; + + let c = async { + let o = object { + let a = await (async "ca") ; + let b = await (async "cb"); + public func get_a() : Text { a }; + public func get_b() : Text { b }; + }; + let (a, b) = (o.get_a(), o.get_b()); + debugPrint (a#b); + }; + + let d = async { + let o = object { + let a = "da"; + let b = await (async "db"); + public func get_a() : Text { a }; + public func get_b() : Text { b }; + }; + let (a, b) = (o.get_a(), o.get_b()); + debugPrint (a#b); + }; + + let e = async { + let o = object this { + let a = "ea"; + let b = await (async "eb"); + public func get_a() : Text { a }; + public func get_b() : Text { b }; + public func get_ab() : (Text, Text) { + (this.get_a(), this.get_b()); + }; + }; + let (a, b) = o.get_ab(); + debugPrint (a#b); + }; + + () + }; +}; +a.go(); //OR-CALL ingress go "DIDL\x00\x00" diff --git a/test/run-drun/async-obj-mut.mo b/test/run-drun/async-obj-mut.mo new file mode 100644 index 00000000000..d94e2a13e29 --- /dev/null +++ b/test/run-drun/async-obj-mut.mo @@ -0,0 +1,21 @@ +actor a { + public func go() = ignore async { + let o = object { + public var x = await { async { 1 } }; + let a = debugPrintNat(x); + // private b = (x := await { async (x + 1) }); + let b = (x := x + 1); + let c = debugPrintNat(x); + public func foo() = { x := x + 1 }; + let e = foo(); + let f = debugPrintNat(x); + }; + debugPrint("done creating\n"); + debugPrintNat(o.x); + o.x := o.x + 1; + debugPrintNat(o.x); + o.foo(); + debugPrintNat(o.x); + } +}; +a.go(); //OR-CALL ingress go "DIDL\x00\x00" diff --git a/test/run-drun/async-while.mo b/test/run-drun/async-while.mo new file mode 100644 index 00000000000..91b43fd5fde --- /dev/null +++ b/test/run-drun/async-while.mo @@ -0,0 +1,59 @@ +actor a { + public func go() = ignore async { + { var i = 0; + var j = 0; + while (j <= 2) { + debugPrintNat(j); + assert(j == i); + i += 1; + j += 1; + }; + assert(i == 3); + }; + + + { + var i = 0; + var j = 0; + while (await async (j <= 2)) { + debugPrintNat(j); + assert(j == i); + i += 1; + j += 1; + }; + assert(i == 3); + }; + + { + var i = 0; + var j = 0; + while (j <= 2) { + debugPrintNat(j); + assert(j == i); + await (async (i += 1)); + j += 1; + }; + assert(i == 3); + }; + + { + var i = 0; + var j = 0; + label l + while (true) { + if (j > 2) { + break l; + assert(false); + }; + debugPrintNat(j); + assert(j == i); + await (async (i += 1)); + j += 1; + continue l; + assert(false); + }; + assert(i == 3); + }; + } +}; +a.go(); //OR-CALL ingress go "DIDL\x00\x00" diff --git a/test/run-drun/await.mo b/test/run-drun/await.mo new file mode 100644 index 00000000000..1f0cd0d5eb1 --- /dev/null +++ b/test/run-drun/await.mo @@ -0,0 +1,70 @@ +actor a { + public func go() { + var cnt : Nat = 0; + + func f(i:Nat) : async Nat { + debugPrint ("cnt: " # debug_show cnt # " i: " # debug_show i); + cnt += 1; + cnt; + }; + + debugPrint "a"; + + let a = async await f(0); + + debugPrint "b"; + + let b = async { await f(1); }; + + debugPrint "c"; + + let c = async { + let _ = await f(2); + await f(3); + }; + + debugPrint "d"; + + let d = (async { return await f(4); }) : async Int; + + debugPrint "e"; + + let e = async { + var i = 5; + debugPrint "e-while"; + while (i < 8) { + let _ = await f(i); + i += 1; + }; + debugPrint "e-exit"; + }; + + debugPrint "g"; + + let g = async { + var i = 10; + debugPrint "g-label"; + label lp + while (true) { + if (i < 13) { + debugPrint "."; + let _ = await f(i); + i += 1; + continue lp; + } else {}; + break lp; + }; + debugPrint "g-exit"; + }; + + debugPrint "holy"; + + func p():async (Text,Text) { ("fst","snd"); }; + let h = async { + let (a,b) = ("a","b"); /* await p(a,b);*/ + debugPrint a; + debugPrint b; + }; + } +}; +a.go(); //OR-CALL ingress go "DIDL\x00\x00" diff --git a/test/run-drun/block.mo b/test/run-drun/block.mo new file mode 100644 index 00000000000..665170fbf8d --- /dev/null +++ b/test/run-drun/block.mo @@ -0,0 +1,39 @@ +actor a { + public func go() = ignore { + let a = async { + let (a,b) = ("a1","b1"); + debugPrint a; + debugPrint b; + }; + + let b = async { + let (a,b) = await (async ("a2","b2")); + debugPrint a; + debugPrint b; + }; + + let c = async { + func f(a:Text,b:Text):(){ debugPrint a; debugPrint b;}; + let (a,b) = await (async ("a3","b3")); + let _ = f(a,b); + }; + + let d = async { + var f = 1; + debugPrintNat (f); + let (a,b) = await (async ("a4","b4")); + f += 2; + debugPrintNat (f); + }; + + + let e = async { + var f = await (async 5); + debugPrintNat (f); + let (a,b) = await (async ("a5","b5")); + f += 1; + debugPrintNat (f); + }; + } +}; +a.go(); //OR-CALL ingress go "DIDL\x00\x00" diff --git a/test/run-stub/chat.mo b/test/run-drun/chat.mo similarity index 99% rename from test/run-stub/chat.mo rename to test/run-drun/chat.mo index 8cf6f40542c..1b21856a93c 100644 --- a/test/run-stub/chat.mo +++ b/test/run-drun/chat.mo @@ -62,4 +62,5 @@ charlie.go("charlie", server); compiler: - parameterising Client on s:IServer argument complains about non-closed actor (expected acc. to Joachim, pending system changes) */ - + +//SKIP comp diff --git a/test/run-drun/closure-params.mo b/test/run-drun/closure-params.mo new file mode 100644 index 00000000000..0e529f6e6ae --- /dev/null +++ b/test/run-drun/closure-params.mo @@ -0,0 +1,26 @@ +let a = actor { + var c = 0; + public func incn(n : Nat) : () { + c += n; + debugPrintNat(c); + }; + public func readCounter(f : shared Nat -> ()) : () { + f(c); + }; + + public func printNat(n: Nat) { debugPrintNat n }; + + public func go() { + incn(1); + readCounter(printNat); + incn(2); + readCounter(printNat); + incn(3); + readCounter(printNat); + incn(4); + readCounter(printNat); + incn(5); + readCounter(printNat); + }; +}; +a.go(); //OR-CALL ingress go "DIDL\x00\x00" diff --git a/test/run-stub/control.mo b/test/run-drun/control.mo similarity index 92% rename from test/run-stub/control.mo rename to test/run-drun/control.mo index a50123acf80..0872f79af80 100644 --- a/test/run-stub/control.mo +++ b/test/run-drun/control.mo @@ -1,3 +1,8 @@ +// Nothing to run here (but do compile and validate) + +//SKIP drun-run +//SKIP ic-stub-run + actor control { func condition() : Bool = false; diff --git a/test/run-stub/count-callbacks.mo b/test/run-drun/count-callbacks.mo similarity index 95% rename from test/run-stub/count-callbacks.mo rename to test/run-drun/count-callbacks.mo index 7773954c306..639ce158e79 100644 --- a/test/run-stub/count-callbacks.mo +++ b/test/run-drun/count-callbacks.mo @@ -24,9 +24,8 @@ actor a { await a4; debugPrint("go 5: " # debug_show rts_callback_table_count()); }; - - go(); -} +}; +a.go(); //OR-CALL ingress go "DIDL\x00\x00" //SKIP run //SKIP run-low diff --git a/test/run-drun/counter2.mo b/test/run-drun/counter2.mo index 8bdeeab46a5..7ff9a17359b 100644 --- a/test/run-drun/counter2.mo +++ b/test/run-drun/counter2.mo @@ -1,14 +1,24 @@ -actor { +let a = actor { var c = 1; public func inc() { c += 1; - debugPrintNat c + debugPrintNat c; }; public func printCounter () { - debugPrintNat c - } -} -//CALL inc 0x4449444C0000 [] -//CALL inc 0x4449444C0000 [] -//CALL inc 0x4449444C0000 [] -//CALL printCounter 0x4449444C0000 [] + debugPrintNat c; + }; + + public func go() { + a.inc(); + a.inc(); + a.inc(); + a.printCounter(); + + var i : Int = 10; + while (i > 0) { + a.inc(); + i -= 1; + }; + }; +}; +a.go(); //OR-CALL ingress go "DIDL\x00\x00" diff --git a/test/run-stub/create-then-trap.mo b/test/run-drun/create-then-trap.mo similarity index 80% rename from test/run-stub/create-then-trap.mo rename to test/run-drun/create-then-trap.mo index 6a23cd10b71..4150b084c84 100644 --- a/test/run-stub/create-then-trap.mo +++ b/test/run-drun/create-then-trap.mo @@ -9,4 +9,4 @@ actor a { assert false; } }; -a.go(); +a.go(); //OR-CALL ingress go "DIDL\x00\x00" diff --git a/test/run-stub/data-params.mo b/test/run-drun/data-params.mo similarity index 98% rename from test/run-stub/data-params.mo rename to test/run-drun/data-params.mo index 3f9011e314a..aa83f24286b 100644 --- a/test/run-stub/data-params.mo +++ b/test/run-drun/data-params.mo @@ -113,4 +113,4 @@ actor a { a.incn(2**31 - 1); // highest compact }; }; -a.go(); +a.go(); //OR-CALL ingress go "DIDL\x00\x00" diff --git a/test/run-stub/divide-by-zero.mo b/test/run-drun/divide-by-zero.mo similarity index 100% rename from test/run-stub/divide-by-zero.mo rename to test/run-drun/divide-by-zero.mo diff --git a/test/run-drun/empty-actor.mo b/test/run-drun/empty-actor.mo new file mode 100644 index 00000000000..a0b4cbb51ad --- /dev/null +++ b/test/run-drun/empty-actor.mo @@ -0,0 +1 @@ +actor {}; diff --git a/test/run-stub/flatten-awaitables.mo b/test/run-drun/flatten-awaitables.mo similarity index 97% rename from test/run-stub/flatten-awaitables.mo rename to test/run-drun/flatten-awaitables.mo index 2e2082e4529..1111f312180 100644 --- a/test/run-stub/flatten-awaitables.mo +++ b/test/run-drun/flatten-awaitables.mo @@ -30,9 +30,7 @@ let a = actor { public func g3 (f3:shared ((Int,Bool,Text)) -> async (Int,Bool,Text), xyz:(Int,Bool,Text)) : async (Int,Bool,Text) { await f3 xyz; }; -}; - -let _ = async { + public func go() = ignore async { debugPrint "first-order"; @@ -113,5 +111,6 @@ let _ = async { debugPrint "14"; let (3,false,"text") = await a.g3(a.n3,xyz); debugPrint "15"; + }; }; - +a.go(); //OR-CALL ingress go "DIDL\x00\x00" diff --git a/test/run-drun/for-await.mo b/test/run-drun/for-await.mo new file mode 100644 index 00000000000..d6139b230f1 --- /dev/null +++ b/test/run-drun/for-await.mo @@ -0,0 +1,15 @@ +actor a { + public func go() = ignore async { + { + var i = 0; + i := 0; + for (j in range(0, 10)) { + debugPrintNat(j); + assert(j == i); + await (async (i += 1)); + }; + assert(i == 11); + }; + } +}; +a.go(); //OR-CALL ingress go "DIDL\x00\x00" diff --git a/test/run-stub/free-callbacks.mo b/test/run-drun/free-callbacks.mo similarity index 94% rename from test/run-stub/free-callbacks.mo rename to test/run-drun/free-callbacks.mo index 0858e54c352..7fbe09ba40a 100644 --- a/test/run-stub/free-callbacks.mo +++ b/test/run-drun/free-callbacks.mo @@ -1,5 +1,4 @@ actor a { - public func ping() : async () { }; @@ -29,9 +28,9 @@ actor a { assert (s2-s0 > 5_000); assert (s3-s0 < 5_000); }; +}; +a.go(); //OR-CALL ingress go "DIDL\x00\x00" - go(); -} //SKIP run //SKIP run-low diff --git a/test/run-stub/general-type-components.mo b/test/run-drun/general-type-components.mo similarity index 94% rename from test/run-stub/general-type-components.mo rename to test/run-drun/general-type-components.mo index 5c88383c539..788fb16c49b 100644 --- a/test/run-stub/general-type-components.mo +++ b/test/run-drun/general-type-components.mo @@ -26,3 +26,5 @@ actor A = { type AT = A.T; +//SKIP comp +//SKIP comp-stub diff --git a/test/run-drun/generic-tail-rec.mo b/test/run-drun/generic-tail-rec.mo index 855b9110977..87cde02b7b4 100644 --- a/test/run-drun/generic-tail-rec.mo +++ b/test/run-drun/generic-tail-rec.mo @@ -10,7 +10,7 @@ func Loop(n:Int){ }; Loop(n+1); }; -Loop(0); +Loop(0); }; @@ -24,7 +24,7 @@ func Loop(n:Int){ assert(false); }; -Loop(0); +Loop(0); }; { @@ -34,7 +34,7 @@ func Loop(n:Int){ return; }; Loop(n+1); - }; + }; Loop(0); }; @@ -46,7 +46,7 @@ func Loop(n:Int){ return; }; Loop(n+1); - }; + }; Loop(0); }; diff --git a/test/run-stub/hello-world-async.mo b/test/run-drun/hello-world-async.mo similarity index 69% rename from test/run-stub/hello-world-async.mo rename to test/run-drun/hello-world-async.mo index 86dcb14837d..ff441afb7e2 100644 --- a/test/run-stub/hello-world-async.mo +++ b/test/run-drun/hello-world-async.mo @@ -1,4 +1,4 @@ -let a = actor { +actor a { public func world() { debugPrint("World!"); }; @@ -7,6 +7,4 @@ let a = actor { debugPrint("Hello "); }; }; - -a.go() - +a.go(); //OR-CALL ingress go "DIDL\x00\x00" diff --git a/test/run-stub/hello-world-await.mo b/test/run-drun/hello-world-await.mo similarity index 83% rename from test/run-stub/hello-world-await.mo rename to test/run-drun/hello-world-await.mo index 4ea6fa264bf..b1f47ee503f 100644 --- a/test/run-stub/hello-world-await.mo +++ b/test/run-drun/hello-world-await.mo @@ -9,5 +9,4 @@ let a = actor { debugPrint((await hello()) # (await world())); }; }; - -a.go() +a.go(); //OR-CALL ingress go "DIDL\x00\x00" diff --git a/test/run-drun/hello-world-message2.mo b/test/run-drun/hello-world-message2.mo deleted file mode 100644 index 28d9d49fddb..00000000000 --- a/test/run-drun/hello-world-message2.mo +++ /dev/null @@ -1,7 +0,0 @@ -actor hello_world { - public func hello() { - debugPrint("Hello World!"); - } -} - -//CALL hello 0x4449444C0000 [] diff --git a/test/run-drun/ic-calls.mo b/test/run-drun/ic-calls.mo index 32d4a947f77..770d9422710 100644 --- a/test/run-drun/ic-calls.mo +++ b/test/run-drun/ic-calls.mo @@ -1,10 +1,7 @@ -actor X { - - +actor a { public func A() : async () { }; - public func B(x : Int) : async Int { x }; @@ -13,12 +10,11 @@ actor X { (x,y); }; - public func test() : async () { + public func go() = ignore async { let () = await A(); let 1 = await B(1); let (1,true) = await C(1,true); }; -} -//CALL ingress test 0x4449444C0000 - +}; +a.go(); //OR-CALL ingress go "DIDL\x00\x00" diff --git a/test/run-drun/idl-any.mo b/test/run-drun/idl-any.mo index b2c5713be24..f05a21c217c 100644 --- a/test/run-drun/idl-any.mo +++ b/test/run-drun/idl-any.mo @@ -37,3 +37,7 @@ actor { //CALL ingress any 0x4449444C016b0200718001750200710001A003466F6F //CALL ingress any 0x4449444C016b02007180017502007101DEADBEEF03466F6F //CALL ingress any 0x4449444C016602ABCD0200710400DEADBEEF03466F6F + +//SKIP run +//SKIP run-ir +//SKIP run-low diff --git a/test/run-drun/idl-bad.mo b/test/run-drun/idl-bad.mo index 2b5b04be855..c5776204ea6 100644 --- a/test/run-drun/idl-bad.mo +++ b/test/run-drun/idl-bad.mo @@ -5,3 +5,6 @@ actor { //CALL query foo "NOTDIDL" +//SKIP run +//SKIP run-ir +//SKIP run-low diff --git a/test/run-drun/idl-field-escape.mo b/test/run-drun/idl-field-escape.mo index f84ca1556ec..0ad9549a16b 100644 --- a/test/run-drun/idl-field-escape.mo +++ b/test/run-drun/idl-field-escape.mo @@ -25,3 +25,7 @@ actor { //CALL ingress foo2 0x4449444C0000 //CALL ingress out 0x4449444C0000 //CALL ingress input 0x4449444c016c03007c017dbcfef7b102710100ffff03802003585858 + +//SKIP run +//SKIP run-ir +//SKIP run-low diff --git a/test/run-drun/idl-func.mo b/test/run-drun/idl-func.mo index 592c306ddf1..1d90a7c72cf 100644 --- a/test/run-drun/idl-func.mo +++ b/test/run-drun/idl-func.mo @@ -11,3 +11,7 @@ actor { //CALL query fun 0x4449444C0000 //CALL query fun2 0x4449444c026e016a017c0000010000 + +//SKIP run +//SKIP run-ir +//SKIP run-low diff --git a/test/run-drun/idl-nary.mo b/test/run-drun/idl-nary.mo index 25284781203..e441147eac4 100644 --- a/test/run-drun/idl-nary.mo +++ b/test/run-drun/idl-nary.mo @@ -51,3 +51,7 @@ actor { //CALL ingress three "DIDL\x00\x03\x71\x71\x71\x03One\x03Two\x05ThreeEXTRABYTES" // extra arguments (ok) //CALL ingress four "DIDL\x00\x05\x71\x71\x71\x71\x71\x03One\x03Two\x05Three\x04Four\x04Five" + +//SKIP run +//SKIP run-ir +//SKIP run-low diff --git a/test/run-drun/idl-nat-int.mo b/test/run-drun/idl-nat-int.mo index 7c971b93ff7..2e5b3c1bd47 100644 --- a/test/run-drun/idl-nat-int.mo +++ b/test/run-drun/idl-nat-int.mo @@ -16,3 +16,7 @@ actor { //CALL query absolutes "DIDL\x01\x6d\x7d\x01\x00\x02\x2a\x19" // with Ints //CALL query absolutes "DIDL\x01\x6d\x7c\x01\x00\x02\x56\x19" + +//SKIP run +//SKIP run-ir +//SKIP run-low diff --git a/test/run-drun/idl-option.mo b/test/run-drun/idl-option.mo index 887644e7584..e620332618f 100644 --- a/test/run-drun/idl-option.mo +++ b/test/run-drun/idl-option.mo @@ -12,3 +12,7 @@ actor { //CALL ingress any 0x4449444C00017f //CALL ingress any 0x4449444C016e71010000 //CALL ingress any 0x4449444C016e7101000103466F6F + +//SKIP run +//SKIP run-ir +//SKIP run-low diff --git a/test/run-drun/idl-pair.mo b/test/run-drun/idl-pair.mo index 57a487bcd64..78ffddf8bb9 100644 --- a/test/run-drun/idl-pair.mo +++ b/test/run-drun/idl-pair.mo @@ -6,3 +6,7 @@ actor { } //CALL ingress len2 "DIDL\x00\x02\x71\x71\x02Hi\x05World" + +//SKIP run +//SKIP run-ir +//SKIP run-low diff --git a/test/run-drun/idl-record.mo b/test/run-drun/idl-record.mo index 576609b3aa0..4194e64299e 100644 --- a/test/run-drun/idl-record.mo +++ b/test/run-drun/idl-record.mo @@ -32,3 +32,7 @@ actor { //CALL ingress record1 0x4449444C016C03b99adecb0171f1fee18d037C88be8c890477010004486579212A19 // needs to jump over redundant trailing `byte` field //CALL ingress record2 0x4449444C016C03b99adecb0171f1fee18d037C88be8c89047702007704486579212A1819 + +//SKIP run +//SKIP run-ir +//SKIP run-low diff --git a/test/run-drun/idl-shorthand.mo b/test/run-drun/idl-shorthand.mo index 23b4f5962b5..90557576561 100644 --- a/test/run-drun/idl-shorthand.mo +++ b/test/run-drun/idl-shorthand.mo @@ -7,3 +7,7 @@ actor { } //CALL query foo 0x4449444c016b01d1a7cf027f010000 + +//SKIP run +//SKIP run-ir +//SKIP run-low diff --git a/test/run-drun/idl-tuple.mo b/test/run-drun/idl-tuple.mo index 0f86f4a9a06..20456305b3f 100644 --- a/test/run-drun/idl-tuple.mo +++ b/test/run-drun/idl-tuple.mo @@ -15,3 +15,7 @@ actor { //CALL query len3 0x4449444c016c030071007601750200710548656c6c6fdead0102030405576f726c64 // testing redundant third tuple member, gets ignored //CALL query len3 0x4449444c016c030071017502760200710548656c6c6f01020304dead05576f726c64 + +//SKIP run +//SKIP run-ir +//SKIP run-low diff --git a/test/run-drun/idl-unit.mo b/test/run-drun/idl-unit.mo index 09e6f9b85ec..2cf2a1078c7 100644 --- a/test/run-drun/idl-unit.mo +++ b/test/run-drun/idl-unit.mo @@ -5,3 +5,7 @@ actor { } //CALL query unit_id "DIDL\x00\x00" + +//SKIP run +//SKIP run-ir +//SKIP run-low diff --git a/test/run-drun/idl-variant.mo b/test/run-drun/idl-variant.mo index 594cf29f99f..e9c4207bd38 100644 --- a/test/run-drun/idl-variant.mo +++ b/test/run-drun/idl-variant.mo @@ -14,3 +14,7 @@ actor { } //CALL query numify 0x4449444c016b03d583b702008790c0bd0479dc9790cb0e790100000220000000 + +//SKIP run +//SKIP run-ir +//SKIP run-low diff --git a/test/run-drun/idl-vector.mo b/test/run-drun/idl-vector.mo index 48391f2a241..dbecbcd2c11 100644 --- a/test/run-drun/idl-vector.mo +++ b/test/run-drun/idl-vector.mo @@ -11,3 +11,7 @@ actor { // [[], [[], [[], [],], [], []], []] //CALL query rose 0x4449444c016d00010003000400020000000000 + +//SKIP run +//SKIP run-ir +//SKIP run-low diff --git a/test/run-stub/indirect-counter.mo b/test/run-drun/indirect-counter.mo similarity index 96% rename from test/run-stub/indirect-counter.mo rename to test/run-drun/indirect-counter.mo index 85e045f959c..8d9bc3f5a89 100644 --- a/test/run-stub/indirect-counter.mo +++ b/test/run-drun/indirect-counter.mo @@ -17,3 +17,5 @@ a.inc(); a.inc(); a.inc(); a.debugPrint() + +//SKIP comp diff --git a/test/run-drun/interleave.mo b/test/run-drun/interleave.mo new file mode 100644 index 00000000000..d5c78eb8d56 --- /dev/null +++ b/test/run-drun/interleave.mo @@ -0,0 +1,42 @@ +actor a { + public func go() { + + var cnt : Nat = 0; + func f(m: Text, i:Nat) : async Nat { + debugPrint (m # " cnt: " # debug_show cnt # " i: " # debug_show i); + cnt += 1; + cnt; + }; + + + + let e = async { + var i = 5; + debugPrint " e-while\n"; + while (i < 10) { + let _ = await f(" e",i); + i += 1; + }; + debugPrint " e-exit\n"; + }; + + debugPrint "g"; + + let g = async { + var i = 10; + debugPrint "g-label\n"; + label lp + while (true) { + if (i < 15) { + let _ = await f("g",i); + i += 1; + continue lp; + } else {}; + break lp; + }; + debugPrint "g-exit\n"; + }; + + } +}; +a.go(); //OR-CALL ingress go "DIDL\x00\x00" diff --git a/test/run-stub/issue-894.mo b/test/run-drun/issue-894.mo similarity index 89% rename from test/run-stub/issue-894.mo rename to test/run-drun/issue-894.mo index 64d2a6f7b1e..591e969ec2e 100644 --- a/test/run-stub/issue-894.mo +++ b/test/run-drun/issue-894.mo @@ -1,7 +1,7 @@ actor a { public shared func id(i : Nat) : async Nat { i }; - public shared func test() : async () { + public shared func go() : async () { { let o = {var l = 0}; @@ -44,5 +44,4 @@ actor a { }; }; - -a.test(); +a.go(); //OR-CALL ingress go "DIDL\x00\x00" diff --git a/test/run-stub/local-throw.mo b/test/run-drun/local-throw.mo similarity index 94% rename from test/run-stub/local-throw.mo rename to test/run-drun/local-throw.mo index 9a1e8ce2cf1..edb93b96f1e 100644 --- a/test/run-stub/local-throw.mo +++ b/test/run-drun/local-throw.mo @@ -48,7 +48,7 @@ actor a { }; - async { + public func go() = ignore async { try { await t2(); debugPrint ("t2 ok"); @@ -62,6 +62,6 @@ actor a { } catch _ { assert false; }; - }; }; +a.go(); //OR-CALL ingress go "DIDL\x00\x00" diff --git a/test/run-drun/multiple-actors.mo b/test/run-drun/multiple-actors.mo deleted file mode 100644 index 33e4b920714..00000000000 --- a/test/run-drun/multiple-actors.mo +++ /dev/null @@ -1,7 +0,0 @@ -actor a { }; - -actor b { }; - - - - diff --git a/test/run-drun/nary-async.mo b/test/run-drun/nary-async.mo new file mode 100644 index 00000000000..0243a91e766 --- /dev/null +++ b/test/run-drun/nary-async.mo @@ -0,0 +1,111 @@ +/* test n-ary async/await */ + +actor a { + /* n-ary args */ + public func f0_0() : async () {}; + public func f1_0(x:Int) : async () { + assert(x == 1); + }; + public func f2_0(x:Int,y:Bool) : async () { + assert(x==1); + assert(y==true); + }; + public func f3_0(x:Int,y:Bool,z:Text) : async () { + assert(x == 1); + assert(y == true); + assert(z == "a"); + }; + + public func go1() { + { + let t = "0_0"; + ignore async { + await f0_0(); + debugPrint t; + }; + }; + + { + let t = "1_0"; + ignore async { + await f1_0(1); + debugPrint t; + }; + }; + + { + let t = "2_0"; + ignore async { + await f2_0(1,true); + debugPrint t; + }; + }; + + { + let t = "3_0"; + ignore async { + await f3_0(1,true,"a"); + debugPrint t; + }; + }; + }; + + /* n-ary returns */ + public func g0_0() : async () {}; + public func g0_1() : async Int { + 1; + }; + public func g0_2() : async (Int,Bool) { + (1,true); + }; + public func g0_3() : async (Int,Bool,Text) { + (1,true,"a"); + }; + + public func go2() { + { + let t = "0_0"; + ignore async { + await g0_0(); + debugPrint t; + }; + }; + + { + let t = "0_1"; + ignore async { + let x = await g0_1(); + assert(x == 1); + debugPrint t; + x; + }; + }; + + { + let t = "0_2"; + ignore async { + let (x,y) = await g0_2(); + assert(x==1); + assert(y==true); + debugPrint t; + (x,y); + }; + }; + + + { + let t = "0_3"; + ignore async { + let (x,y,z) = await g0_3(); + assert(x==1); + assert(y==true); + assert(z=="a"); + debugPrint t; + (x,y,z); + }; + }; + }; +}; + +a.go1(); //OR-CALL ingress go1 "DIDL\x00\x00" +a.go2(); //OR-CALL ingress go2 "DIDL\x00\x00" diff --git a/test/run-stub/ok/AST-64.ic-stub-run.ok b/test/run-drun/ok/AST-64.ic-stub-run.ok similarity index 100% rename from test/run-stub/ok/AST-64.ic-stub-run.ok rename to test/run-drun/ok/AST-64.ic-stub-run.ok diff --git a/test/run-drun/ok/AST-66.comp.ok b/test/run-drun/ok/AST-66.comp.ok new file mode 100644 index 00000000000..648f0ea3cff --- /dev/null +++ b/test/run-drun/ok/AST-66.comp.ok @@ -0,0 +1,4 @@ +AST-66.mo:4.12-7.6: type error, unsupported async block + (This is a limitation of the current version.) +AST-66.mo:9.12-14.6: type error, unsupported async block + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/counter2.drun-run.ret.ok b/test/run-drun/ok/AST-66.comp.ret.ok similarity index 100% rename from test/run-drun/ok/counter2.drun-run.ret.ok rename to test/run-drun/ok/AST-66.comp.ret.ok diff --git a/test/run-stub/ok/idl-unit.ic-stub-run.ok b/test/run-drun/ok/AST-66.ic-stub-run.ok similarity index 77% rename from test/run-stub/ok/idl-unit.ic-stub-run.ok rename to test/run-drun/ok/AST-66.ic-stub-run.ok index e7d4b9a40ab..be9fb5d62c0 100644 --- a/test/run-stub/ok/idl-unit.ic-stub-run.ok +++ b/test/run-drun/ok/AST-66.ic-stub-run.ok @@ -2,5 +2,5 @@ ← completed: canister-id = 0x0000000000000400 → install ← completed -→ query unit_id(0x4449444c0000) +→ update go(0x4449444c0000) ← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/GIT-843.drun-run.ok b/test/run-drun/ok/GIT-843.drun-run.ok new file mode 100644 index 00000000000..e51631cf793 --- /dev/null +++ b/test/run-drun/ok/GIT-843.drun-run.ok @@ -0,0 +1,3 @@ +ingress(0) System +debug.print: ok +ingress(1) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-stub/ok/GIT-843.run-ir.ok b/test/run-drun/ok/GIT-843.run-ir.ok similarity index 100% rename from test/run-stub/ok/GIT-843.run-ir.ok rename to test/run-drun/ok/GIT-843.run-ir.ok diff --git a/test/run-stub/ok/GIT-843.run-low.ok b/test/run-drun/ok/GIT-843.run-low.ok similarity index 100% rename from test/run-stub/ok/GIT-843.run-low.ok rename to test/run-drun/ok/GIT-843.run-low.ok diff --git a/test/run-stub/ok/GIT-843.run.ok b/test/run-drun/ok/GIT-843.run.ok similarity index 100% rename from test/run-stub/ok/GIT-843.run.ok rename to test/run-drun/ok/GIT-843.run.ok diff --git a/test/run-stub/ok/actor-creation.ic-stub-run.ok b/test/run-drun/ok/actor-creation.ic-stub-run.ok similarity index 100% rename from test/run-stub/ok/actor-creation.ic-stub-run.ok rename to test/run-drun/ok/actor-creation.ic-stub-run.ok diff --git a/test/run-stub/ok/actor-creation.run-ir.ok b/test/run-drun/ok/actor-creation.run-ir.ok similarity index 100% rename from test/run-stub/ok/actor-creation.run-ir.ok rename to test/run-drun/ok/actor-creation.run-ir.ok diff --git a/test/run-stub/ok/actor-creation.run-low.ok b/test/run-drun/ok/actor-creation.run-low.ok similarity index 100% rename from test/run-stub/ok/actor-creation.run-low.ok rename to test/run-drun/ok/actor-creation.run-low.ok diff --git a/test/run-stub/ok/actor-creation.run.ok b/test/run-drun/ok/actor-creation.run.ok similarity index 100% rename from test/run-stub/ok/actor-creation.run.ok rename to test/run-drun/ok/actor-creation.run.ok diff --git a/test/run-drun/ok/array-out-of-bounds.run-ir.ok b/test/run-drun/ok/array-out-of-bounds.run-ir.ok new file mode 100644 index 00000000000..2c3843087e9 --- /dev/null +++ b/test/run-drun/ok/array-out-of-bounds.run-ir.ok @@ -0,0 +1,2 @@ +array-out-of-bounds.mo:6.12-6.17: execution error, index out of bounds +array-out-of-bounds.mo:10.12-10.17: execution error, index out of bounds diff --git a/test/run-drun/ok/array-out-of-bounds.run-low.ok b/test/run-drun/ok/array-out-of-bounds.run-low.ok new file mode 100644 index 00000000000..2c3843087e9 --- /dev/null +++ b/test/run-drun/ok/array-out-of-bounds.run-low.ok @@ -0,0 +1,2 @@ +array-out-of-bounds.mo:6.12-6.17: execution error, index out of bounds +array-out-of-bounds.mo:10.12-10.17: execution error, index out of bounds diff --git a/test/run-drun/ok/array-out-of-bounds.run.ok b/test/run-drun/ok/array-out-of-bounds.run.ok new file mode 100644 index 00000000000..2c3843087e9 --- /dev/null +++ b/test/run-drun/ok/array-out-of-bounds.run.ok @@ -0,0 +1,2 @@ +array-out-of-bounds.mo:6.12-6.17: execution error, index out of bounds +array-out-of-bounds.mo:10.12-10.17: execution error, index out of bounds diff --git a/test/run-drun/ok/async-any.comp.ok b/test/run-drun/ok/async-any.comp.ok new file mode 100644 index 00000000000..8cc6dffc4c0 --- /dev/null +++ b/test/run-drun/ok/async-any.comp.ok @@ -0,0 +1,2 @@ +async-any.mo:3.13-3.29: type error, unsupported async block + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/hello-world-message2.drun-run.ret.ok b/test/run-drun/ok/async-any.comp.ret.ok similarity index 100% rename from test/run-drun/ok/hello-world-message2.drun-run.ret.ok rename to test/run-drun/ok/async-any.comp.ret.ok diff --git a/test/run-stub/ok/async-any.ic-stub-run.ok b/test/run-drun/ok/async-any.ic-stub-run.ok similarity index 58% rename from test/run-stub/ok/async-any.ic-stub-run.ok rename to test/run-drun/ok/async-any.ic-stub-run.ok index 54225bc8555..be9fb5d62c0 100644 --- a/test/run-stub/ok/async-any.ic-stub-run.ok +++ b/test/run-drun/ok/async-any.ic-stub-run.ok @@ -2,3 +2,5 @@ ← completed: canister-id = 0x0000000000000400 → install ← completed +→ update go(0x4449444c0000) +← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/async-calls1.comp.ok b/test/run-drun/ok/async-calls1.comp.ok new file mode 100644 index 00000000000..f1562045834 --- /dev/null +++ b/test/run-drun/ok/async-calls1.comp.ok @@ -0,0 +1,2 @@ +async-calls1.mo:10.43-10.47: type error, calling a shared function not yet supported + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/multiple-actors.comp.ret.ok b/test/run-drun/ok/async-calls1.comp.ret.ok similarity index 100% rename from test/run-drun/ok/multiple-actors.comp.ret.ok rename to test/run-drun/ok/async-calls1.comp.ret.ok diff --git a/test/run-stub/ok/GIT-843.ic-stub-run.ok b/test/run-drun/ok/async-calls1.ic-stub-run.ok similarity index 58% rename from test/run-stub/ok/GIT-843.ic-stub-run.ok rename to test/run-drun/ok/async-calls1.ic-stub-run.ok index edc65f1e690..be9fb5d62c0 100644 --- a/test/run-stub/ok/GIT-843.ic-stub-run.ok +++ b/test/run-drun/ok/async-calls1.ic-stub-run.ok @@ -1,5 +1,6 @@ → create ← completed: canister-id = 0x0000000000000400 → install -ok ← completed +→ update go(0x4449444c0000) +← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/async-calls2.comp.ok b/test/run-drun/ok/async-calls2.comp.ok new file mode 100644 index 00000000000..6d2e7554b87 --- /dev/null +++ b/test/run-drun/ok/async-calls2.comp.ok @@ -0,0 +1,4 @@ +async-calls2.mo:12.43-12.47: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +async-calls2.mo:12.72-12.79: type error, calling a shared function not yet supported + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/self-calls.comp.ret.ok b/test/run-drun/ok/async-calls2.comp.ret.ok similarity index 100% rename from test/run-drun/ok/self-calls.comp.ret.ok rename to test/run-drun/ok/async-calls2.comp.ret.ok diff --git a/test/run-stub/ok/async-calls.ic-stub-run.ok b/test/run-drun/ok/async-calls2.ic-stub-run.ok similarity index 58% rename from test/run-stub/ok/async-calls.ic-stub-run.ok rename to test/run-drun/ok/async-calls2.ic-stub-run.ok index 54225bc8555..be9fb5d62c0 100644 --- a/test/run-stub/ok/async-calls.ic-stub-run.ok +++ b/test/run-drun/ok/async-calls2.ic-stub-run.ok @@ -2,3 +2,5 @@ ← completed: canister-id = 0x0000000000000400 → install ← completed +→ update go(0x4449444c0000) +← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/async-calls3.comp.ok b/test/run-drun/ok/async-calls3.comp.ok new file mode 100644 index 00000000000..cf63d7526aa --- /dev/null +++ b/test/run-drun/ok/async-calls3.comp.ok @@ -0,0 +1,6 @@ +async-calls3.mo:10.35-10.39: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +async-calls3.mo:10.69-10.76: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +async-calls3.mo:16.5-16.9: type error, calling a shared function not yet supported + (This is a limitation of the current version.) diff --git a/test/run-stub/ok/divide-by-zero.ic-stub-run.ret.ok b/test/run-drun/ok/async-calls3.comp.ret.ok similarity index 100% rename from test/run-stub/ok/divide-by-zero.ic-stub-run.ret.ok rename to test/run-drun/ok/async-calls3.comp.ret.ok diff --git a/test/run-drun/ok/async-calls3.ic-stub-run.ok b/test/run-drun/ok/async-calls3.ic-stub-run.ok new file mode 100644 index 00000000000..be9fb5d62c0 --- /dev/null +++ b/test/run-drun/ok/async-calls3.ic-stub-run.ok @@ -0,0 +1,6 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ update go(0x4449444c0000) +← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/async-free-var.comp.ok b/test/run-drun/ok/async-free-var.comp.ok new file mode 100644 index 00000000000..6908efc9d22 --- /dev/null +++ b/test/run-drun/ok/async-free-var.comp.ok @@ -0,0 +1,2 @@ +async-free-var.mo:5.13-10.6: type error, unsupported async block + (This is a limitation of the current version.) diff --git a/test/run-stub/ok/divide-by-zero.run.ret.ok b/test/run-drun/ok/async-free-var.comp.ret.ok similarity index 100% rename from test/run-stub/ok/divide-by-zero.run.ret.ok rename to test/run-drun/ok/async-free-var.comp.ret.ok diff --git a/test/run-stub/ok/async-free-var.ic-stub-run.ok b/test/run-drun/ok/async-free-var.ic-stub-run.ok similarity index 64% rename from test/run-stub/ok/async-free-var.ic-stub-run.ok rename to test/run-drun/ok/async-free-var.ic-stub-run.ok index 80905ede799..dd58dcb8c5e 100644 --- a/test/run-stub/ok/async-free-var.ic-stub-run.ok +++ b/test/run-drun/ok/async-free-var.ic-stub-run.ok @@ -1,6 +1,8 @@ → create ← completed: canister-id = 0x0000000000000400 → install +← completed +→ update go(0x4449444c0000) A A C @@ -8,4 +10,4 @@ Now in async C B B -← completed +← completed: 0x4449444c0000 diff --git a/test/run-stub/ok/async-free-var.run-ir.ok b/test/run-drun/ok/async-free-var.run-ir.ok similarity index 100% rename from test/run-stub/ok/async-free-var.run-ir.ok rename to test/run-drun/ok/async-free-var.run-ir.ok diff --git a/test/run-stub/ok/async-free-var.run-low.ok b/test/run-drun/ok/async-free-var.run-low.ok similarity index 100% rename from test/run-stub/ok/async-free-var.run-low.ok rename to test/run-drun/ok/async-free-var.run-low.ok diff --git a/test/run-stub/ok/async-free-var.run.ok b/test/run-drun/ok/async-free-var.run.ok similarity index 100% rename from test/run-stub/ok/async-free-var.run.ok rename to test/run-drun/ok/async-free-var.run.ok diff --git a/test/run-drun/ok/async-loop-while.comp.ok b/test/run-drun/ok/async-loop-while.comp.ok new file mode 100644 index 00000000000..d977d56c237 --- /dev/null +++ b/test/run-drun/ok/async-loop-while.comp.ok @@ -0,0 +1,6 @@ +async-loop-while.mo:23.22-23.35: type error, unsupported async block + (This is a limitation of the current version.) +async-loop-while.mo:33.15-33.29: type error, unsupported async block + (This is a limitation of the current version.) +async-loop-while.mo:50.15-50.29: type error, unsupported async block + (This is a limitation of the current version.) diff --git a/test/run-stub/ok/multiple-actors.comp.ret.ok b/test/run-drun/ok/async-loop-while.comp.ret.ok similarity index 100% rename from test/run-stub/ok/multiple-actors.comp.ret.ok rename to test/run-drun/ok/async-loop-while.comp.ret.ok diff --git a/test/run-stub/ok/async-loop-while.ic-stub-run.ok b/test/run-drun/ok/async-loop-while.ic-stub-run.ok similarity index 64% rename from test/run-stub/ok/async-loop-while.ic-stub-run.ok rename to test/run-drun/ok/async-loop-while.ic-stub-run.ok index ac17ed83399..975b7da4a42 100644 --- a/test/run-stub/ok/async-loop-while.ic-stub-run.ok +++ b/test/run-drun/ok/async-loop-while.ic-stub-run.ok @@ -1,6 +1,8 @@ → create ← completed: canister-id = 0x0000000000000400 → install +← completed +→ update go(0x4449444c0000) 0 1 2 @@ -13,4 +15,4 @@ 0 1 2 -← completed +← completed: 0x4449444c0000 diff --git a/test/run-stub/ok/async-loop-while.run-ir.ok b/test/run-drun/ok/async-loop-while.run-ir.ok similarity index 100% rename from test/run-stub/ok/async-loop-while.run-ir.ok rename to test/run-drun/ok/async-loop-while.run-ir.ok diff --git a/test/run-stub/ok/async-loop-while.run-low.ok b/test/run-drun/ok/async-loop-while.run-low.ok similarity index 100% rename from test/run-stub/ok/async-loop-while.run-low.ok rename to test/run-drun/ok/async-loop-while.run-low.ok diff --git a/test/run-stub/ok/async-loop-while.run.ok b/test/run-drun/ok/async-loop-while.run.ok similarity index 100% rename from test/run-stub/ok/async-loop-while.run.ok rename to test/run-drun/ok/async-loop-while.run.ok diff --git a/test/run-drun/ok/async-loop.tc.ok b/test/run-drun/ok/async-loop.tc.ok new file mode 100644 index 00000000000..c7c2f07b4ce --- /dev/null +++ b/test/run-drun/ok/async-loop.tc.ok @@ -0,0 +1 @@ +async-loop.mo:72.1: syntax error, unexpected token diff --git a/test/run-stub/ok/unsupported.comp.ret.ok b/test/run-drun/ok/async-loop.tc.ret.ok similarity index 100% rename from test/run-stub/ok/unsupported.comp.ret.ok rename to test/run-drun/ok/async-loop.tc.ret.ok diff --git a/test/run-drun/ok/async-new-obj.comp.ok b/test/run-drun/ok/async-new-obj.comp.ok new file mode 100644 index 00000000000..2e4d9158230 --- /dev/null +++ b/test/run-drun/ok/async-new-obj.comp.ok @@ -0,0 +1,2 @@ +async-new-obj.mo:5.13-14.6: type error, unsupported async block + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/async-new-obj.comp.ret.ok b/test/run-drun/ok/async-new-obj.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/async-new-obj.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-stub/ok/async-new-obj.ic-stub-run.ok b/test/run-drun/ok/async-new-obj.ic-stub-run.ok similarity index 64% rename from test/run-stub/ok/async-new-obj.ic-stub-run.ok rename to test/run-drun/ok/async-new-obj.ic-stub-run.ok index 6bb840f5518..bc679bfb508 100644 --- a/test/run-stub/ok/async-new-obj.ic-stub-run.ok +++ b/test/run-drun/ok/async-new-obj.ic-stub-run.ok @@ -1,9 +1,11 @@ → create ← completed: canister-id = 0x0000000000000400 → install +← completed +→ update go(0x4449444c0000) aaab babb dadb eaeb cacb -← completed +← completed: 0x4449444c0000 diff --git a/test/run-stub/ok/async-new-obj.run-ir.ok b/test/run-drun/ok/async-new-obj.run-ir.ok similarity index 100% rename from test/run-stub/ok/async-new-obj.run-ir.ok rename to test/run-drun/ok/async-new-obj.run-ir.ok diff --git a/test/run-stub/ok/async-new-obj.run-low.ok b/test/run-drun/ok/async-new-obj.run-low.ok similarity index 100% rename from test/run-stub/ok/async-new-obj.run-low.ok rename to test/run-drun/ok/async-new-obj.run-low.ok diff --git a/test/run-stub/ok/async-new-obj.run.ok b/test/run-drun/ok/async-new-obj.run.ok similarity index 100% rename from test/run-stub/ok/async-new-obj.run.ok rename to test/run-drun/ok/async-new-obj.run.ok diff --git a/test/run-drun/ok/async-obj-mut.comp.ok b/test/run-drun/ok/async-obj-mut.comp.ok new file mode 100644 index 00000000000..8f859721af3 --- /dev/null +++ b/test/run-drun/ok/async-obj-mut.comp.ok @@ -0,0 +1,2 @@ +async-obj-mut.mo:4.30-4.41: type error, unsupported async block + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/async-obj-mut.comp.ret.ok b/test/run-drun/ok/async-obj-mut.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/async-obj-mut.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-stub/ok/async-obj-mut.ic-stub-run.ok b/test/run-drun/ok/async-obj-mut.ic-stub-run.ok similarity index 65% rename from test/run-stub/ok/async-obj-mut.ic-stub-run.ok rename to test/run-drun/ok/async-obj-mut.ic-stub-run.ok index 836b858c056..67a77baa02f 100644 --- a/test/run-stub/ok/async-obj-mut.ic-stub-run.ok +++ b/test/run-drun/ok/async-obj-mut.ic-stub-run.ok @@ -1,6 +1,8 @@ → create ← completed: canister-id = 0x0000000000000400 → install +← completed +→ update go(0x4449444c0000) 1 2 3 @@ -9,4 +11,4 @@ done creating 3 4 5 -← completed +← completed: 0x4449444c0000 diff --git a/test/run-stub/ok/async-obj-mut.run-ir.ok b/test/run-drun/ok/async-obj-mut.run-ir.ok similarity index 100% rename from test/run-stub/ok/async-obj-mut.run-ir.ok rename to test/run-drun/ok/async-obj-mut.run-ir.ok diff --git a/test/run-stub/ok/async-obj-mut.run-low.ok b/test/run-drun/ok/async-obj-mut.run-low.ok similarity index 100% rename from test/run-stub/ok/async-obj-mut.run-low.ok rename to test/run-drun/ok/async-obj-mut.run-low.ok diff --git a/test/run-stub/ok/async-obj-mut.run.ok b/test/run-drun/ok/async-obj-mut.run.ok similarity index 100% rename from test/run-stub/ok/async-obj-mut.run.ok rename to test/run-drun/ok/async-obj-mut.run.ok diff --git a/test/run-drun/ok/async-while.comp.ok b/test/run-drun/ok/async-while.comp.ok new file mode 100644 index 00000000000..6f612fb7993 --- /dev/null +++ b/test/run-drun/ok/async-while.comp.ok @@ -0,0 +1,6 @@ +async-while.mo:18.20-18.34: type error, unsupported async block + (This is a limitation of the current version.) +async-while.mo:33.15-33.29: type error, unsupported async block + (This is a limitation of the current version.) +async-while.mo:50.15-50.29: type error, unsupported async block + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/async-while.comp.ret.ok b/test/run-drun/ok/async-while.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/async-while.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-stub/ok/async-while.ic-stub-run.ok b/test/run-drun/ok/async-while.ic-stub-run.ok similarity index 64% rename from test/run-stub/ok/async-while.ic-stub-run.ok rename to test/run-drun/ok/async-while.ic-stub-run.ok index ac17ed83399..975b7da4a42 100644 --- a/test/run-stub/ok/async-while.ic-stub-run.ok +++ b/test/run-drun/ok/async-while.ic-stub-run.ok @@ -1,6 +1,8 @@ → create ← completed: canister-id = 0x0000000000000400 → install +← completed +→ update go(0x4449444c0000) 0 1 2 @@ -13,4 +15,4 @@ 0 1 2 -← completed +← completed: 0x4449444c0000 diff --git a/test/run-stub/ok/async-while.run-ir.ok b/test/run-drun/ok/async-while.run-ir.ok similarity index 100% rename from test/run-stub/ok/async-while.run-ir.ok rename to test/run-drun/ok/async-while.run-ir.ok diff --git a/test/run-stub/ok/async-while.run-low.ok b/test/run-drun/ok/async-while.run-low.ok similarity index 100% rename from test/run-stub/ok/async-while.run-low.ok rename to test/run-drun/ok/async-while.run-low.ok diff --git a/test/run-stub/ok/async-while.run.ok b/test/run-drun/ok/async-while.run.ok similarity index 100% rename from test/run-stub/ok/async-while.run.ok rename to test/run-drun/ok/async-while.run.ok diff --git a/test/run-drun/ok/await.comp.ok b/test/run-drun/ok/await.comp.ok new file mode 100644 index 00000000000..463f2a585c1 --- /dev/null +++ b/test/run-drun/ok/await.comp.ok @@ -0,0 +1,2 @@ +await.mo:13.13-13.29: type error, unsupported async block + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/await.comp.ret.ok b/test/run-drun/ok/await.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/await.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-stub/ok/await.ic-stub-run.ok b/test/run-drun/ok/await.ic-stub-run.ok similarity index 82% rename from test/run-stub/ok/await.ic-stub-run.ok rename to test/run-drun/ok/await.ic-stub-run.ok index ea903adf0c1..3ea1de6ccaf 100644 --- a/test/run-stub/ok/await.ic-stub-run.ok +++ b/test/run-drun/ok/await.ic-stub-run.ok @@ -1,6 +1,8 @@ → create ← completed: canister-id = 0x0000000000000400 → install +← completed +→ update go(0x4449444c0000) a b c @@ -28,4 +30,4 @@ cnt: 9 i: 7 cnt: 10 i: 12 e-exit g-exit -← completed +← completed: 0x4449444c0000 diff --git a/test/run-stub/ok/await.run-ir.ok b/test/run-drun/ok/await.run-ir.ok similarity index 100% rename from test/run-stub/ok/await.run-ir.ok rename to test/run-drun/ok/await.run-ir.ok diff --git a/test/run-stub/ok/await.run-low.ok b/test/run-drun/ok/await.run-low.ok similarity index 100% rename from test/run-stub/ok/await.run-low.ok rename to test/run-drun/ok/await.run-low.ok diff --git a/test/run-stub/ok/await.run.ok b/test/run-drun/ok/await.run.ok similarity index 100% rename from test/run-stub/ok/await.run.ok rename to test/run-drun/ok/await.run.ok diff --git a/test/run-drun/ok/block.comp.ok b/test/run-drun/ok/block.comp.ok new file mode 100644 index 00000000000..b2d8a0da451 --- /dev/null +++ b/test/run-drun/ok/block.comp.ok @@ -0,0 +1,2 @@ +block.mo:3.13-7.6: type error, unsupported async block + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/block.comp.ret.ok b/test/run-drun/ok/block.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/block.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-stub/ok/block.ic-stub-run.ok b/test/run-drun/ok/block.ic-stub-run.ok similarity index 64% rename from test/run-stub/ok/block.ic-stub-run.ok rename to test/run-drun/ok/block.ic-stub-run.ok index 6d6336f2016..5b07d035c27 100644 --- a/test/run-stub/ok/block.ic-stub-run.ok +++ b/test/run-drun/ok/block.ic-stub-run.ok @@ -1,6 +1,8 @@ → create ← completed: canister-id = 0x0000000000000400 → install +← completed +→ update go(0x4449444c0000) a1 b1 1 @@ -11,4 +13,4 @@ b3 3 5 6 -← completed +← completed: 0x4449444c0000 diff --git a/test/run-stub/ok/block.run-ir.ok b/test/run-drun/ok/block.run-ir.ok similarity index 100% rename from test/run-stub/ok/block.run-ir.ok rename to test/run-drun/ok/block.run-ir.ok diff --git a/test/run-stub/ok/block.run-low.ok b/test/run-drun/ok/block.run-low.ok similarity index 100% rename from test/run-stub/ok/block.run-low.ok rename to test/run-drun/ok/block.run-low.ok diff --git a/test/run-stub/ok/block.run.ok b/test/run-drun/ok/block.run.ok similarity index 100% rename from test/run-stub/ok/block.run.ok rename to test/run-drun/ok/block.run.ok diff --git a/test/run-stub/ok/chat.ic-stub-run.ok b/test/run-drun/ok/chat.ic-stub-run.ok similarity index 100% rename from test/run-stub/ok/chat.ic-stub-run.ok rename to test/run-drun/ok/chat.ic-stub-run.ok diff --git a/test/run-stub/ok/chat.run-ir.ok b/test/run-drun/ok/chat.run-ir.ok similarity index 100% rename from test/run-stub/ok/chat.run-ir.ok rename to test/run-drun/ok/chat.run-ir.ok diff --git a/test/run-stub/ok/chat.run-low.ok b/test/run-drun/ok/chat.run-low.ok similarity index 100% rename from test/run-stub/ok/chat.run-low.ok rename to test/run-drun/ok/chat.run-low.ok diff --git a/test/run-stub/ok/chat.run.ok b/test/run-drun/ok/chat.run.ok similarity index 100% rename from test/run-stub/ok/chat.run.ok rename to test/run-drun/ok/chat.run.ok diff --git a/test/run-drun/ok/closure-params.comp.ok b/test/run-drun/ok/closure-params.comp.ok new file mode 100644 index 00000000000..791ed4ed180 --- /dev/null +++ b/test/run-drun/ok/closure-params.comp.ok @@ -0,0 +1,22 @@ +closure-params.mo:8.5-8.6: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +closure-params.mo:14.5-14.9: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +closure-params.mo:15.5-15.16: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +closure-params.mo:16.5-16.9: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +closure-params.mo:17.5-17.16: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +closure-params.mo:18.5-18.9: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +closure-params.mo:19.5-19.16: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +closure-params.mo:20.5-20.9: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +closure-params.mo:21.5-21.16: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +closure-params.mo:22.5-22.9: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +closure-params.mo:23.5-23.16: type error, calling a shared function not yet supported + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/closure-params.comp.ret.ok b/test/run-drun/ok/closure-params.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/closure-params.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-stub/ok/closure-params.ic-stub-run.ok b/test/run-drun/ok/closure-params.ic-stub-run.ok similarity index 64% rename from test/run-stub/ok/closure-params.ic-stub-run.ok rename to test/run-drun/ok/closure-params.ic-stub-run.ok index 8288cb11e5d..83872c169e0 100644 --- a/test/run-stub/ok/closure-params.ic-stub-run.ok +++ b/test/run-drun/ok/closure-params.ic-stub-run.ok @@ -1,6 +1,8 @@ → create ← completed: canister-id = 0x0000000000000400 → install +← completed +→ update go(0x4449444c0000) 1 3 6 @@ -11,4 +13,4 @@ 6 10 15 -← completed +← completed: 0x4449444c0000 diff --git a/test/run-stub/ok/closure-params.run-ir.ok b/test/run-drun/ok/closure-params.run-ir.ok similarity index 100% rename from test/run-stub/ok/closure-params.run-ir.ok rename to test/run-drun/ok/closure-params.run-ir.ok diff --git a/test/run-stub/ok/closure-params.run-low.ok b/test/run-drun/ok/closure-params.run-low.ok similarity index 100% rename from test/run-stub/ok/closure-params.run-low.ok rename to test/run-drun/ok/closure-params.run-low.ok diff --git a/test/run-stub/ok/closure-params.run.ok b/test/run-drun/ok/closure-params.run.ok similarity index 100% rename from test/run-stub/ok/closure-params.run.ok rename to test/run-drun/ok/closure-params.run.ok diff --git a/test/run-drun/ok/count-callbacks.comp.ok b/test/run-drun/ok/count-callbacks.comp.ok new file mode 100644 index 00000000000..4645af5d7de --- /dev/null +++ b/test/run-drun/ok/count-callbacks.comp.ok @@ -0,0 +1,16 @@ +count-callbacks.mo:9.18-9.20: type error, shared, async function must be called within an await expression + (This is a limitation of the current version.) +count-callbacks.mo:11.18-11.20: type error, shared, async function must be called within an await expression + (This is a limitation of the current version.) +count-callbacks.mo:13.18-13.20: type error, shared, async function must be called within an await expression + (This is a limitation of the current version.) +count-callbacks.mo:15.18-15.20: type error, shared, async function must be called within an await expression + (This is a limitation of the current version.) +count-callbacks.mo:18.11-18.13: type error, argument to await must be a call expression + (This is a limitation of the current version.) +count-callbacks.mo:20.11-20.13: type error, argument to await must be a call expression + (This is a limitation of the current version.) +count-callbacks.mo:22.11-22.13: type error, argument to await must be a call expression + (This is a limitation of the current version.) +count-callbacks.mo:24.11-24.13: type error, argument to await must be a call expression + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/count-callbacks.comp.ret.ok b/test/run-drun/ok/count-callbacks.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/count-callbacks.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-stub/ok/count-callbacks.ic-stub-run.ok b/test/run-drun/ok/count-callbacks.ic-stub-run.ok similarity index 75% rename from test/run-stub/ok/count-callbacks.ic-stub-run.ok rename to test/run-drun/ok/count-callbacks.ic-stub-run.ok index 2fbc3c6f057..b8bcc69c966 100644 --- a/test/run-stub/ok/count-callbacks.ic-stub-run.ok +++ b/test/run-drun/ok/count-callbacks.ic-stub-run.ok @@ -1,6 +1,8 @@ → create ← completed: canister-id = 0x0000000000000400 → install +← completed +→ update go(0x4449444c0000) go 1: 0 go 1: 1 go 1: 2 @@ -14,4 +16,4 @@ go 2: 3 go 3: 2 go 4: 1 go 5: 0 -← completed +← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/counter2.comp.ok b/test/run-drun/ok/counter2.comp.ok new file mode 100644 index 00000000000..5e48f60d71f --- /dev/null +++ b/test/run-drun/ok/counter2.comp.ok @@ -0,0 +1,10 @@ +counter2.mo:12.5-12.10: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +counter2.mo:13.5-13.10: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +counter2.mo:14.5-14.10: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +counter2.mo:15.5-15.19: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +counter2.mo:19.7-19.12: type error, calling a shared function not yet supported + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/counter2.comp.ret.ok b/test/run-drun/ok/counter2.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/counter2.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-drun/ok/counter2.drun-run.ok b/test/run-drun/ok/counter2.drun-run.ok deleted file mode 100644 index ae5f39f9b7f..00000000000 --- a/test/run-drun/ok/counter2.drun-run.ok +++ /dev/null @@ -1,2 +0,0 @@ -ingress(0) System -Error: "Line 1: Illegal method name: 0x4449444C0000." diff --git a/test/run-stub/ok/counter2.ic-stub-run.ok b/test/run-drun/ok/counter2.ic-stub-run.ok similarity index 66% rename from test/run-stub/ok/counter2.ic-stub-run.ok rename to test/run-drun/ok/counter2.ic-stub-run.ok index 73250a9a72f..084e444ee29 100644 --- a/test/run-stub/ok/counter2.ic-stub-run.ok +++ b/test/run-drun/ok/counter2.ic-stub-run.ok @@ -1,6 +1,8 @@ → create ← completed: canister-id = 0x0000000000000400 → install +← completed +→ update go(0x4449444c0000) 2 3 4 @@ -15,4 +17,4 @@ 12 13 14 -← completed +← completed: 0x4449444c0000 diff --git a/test/run-stub/ok/counter2.run-ir.ok b/test/run-drun/ok/counter2.run-ir.ok similarity index 100% rename from test/run-stub/ok/counter2.run-ir.ok rename to test/run-drun/ok/counter2.run-ir.ok diff --git a/test/run-stub/ok/counter2.run-low.ok b/test/run-drun/ok/counter2.run-low.ok similarity index 100% rename from test/run-stub/ok/counter2.run-low.ok rename to test/run-drun/ok/counter2.run-low.ok diff --git a/test/run-stub/ok/counter2.run.ok b/test/run-drun/ok/counter2.run.ok similarity index 100% rename from test/run-stub/ok/counter2.run.ok rename to test/run-drun/ok/counter2.run.ok diff --git a/test/run-drun/ok/create-then-trap.comp.ok b/test/run-drun/ok/create-then-trap.comp.ok new file mode 100644 index 00000000000..06f08486cd5 --- /dev/null +++ b/test/run-drun/ok/create-then-trap.comp.ok @@ -0,0 +1,4 @@ +create-then-trap.mo:3.5-7.6: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program + (This is a limitation of the current version.) +create-then-trap.mo:8.5-8.10: type error, calling a shared function not yet supported + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/create-then-trap.comp.ret.ok b/test/run-drun/ok/create-then-trap.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/create-then-trap.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-stub/ok/create-then-trap.ic-stub-run.ok b/test/run-drun/ok/create-then-trap.ic-stub-run.ok similarity index 51% rename from test/run-stub/ok/create-then-trap.ic-stub-run.ok rename to test/run-drun/ok/create-then-trap.ic-stub-run.ok index 06e8c44dffb..92afdf91f16 100644 --- a/test/run-stub/ok/create-then-trap.ic-stub-run.ok +++ b/test/run-drun/ok/create-then-trap.ic-stub-run.ok @@ -1,5 +1,7 @@ → create ← completed: canister-id = 0x0000000000000400 → install -Trap: EvalTrapError :0.1 "canister trapped explicitly: assertion failed at create-then-trap.mo:9.5-9.17" ← completed +→ update go(0x4449444c0000) +Trap: EvalTrapError :0.1 "canister trapped explicitly: assertion failed at create-then-trap.mo:9.5-9.17" +← rejected (RC_CANISTER_ERROR): canister trapped: EvalTrapError :0.1 "canister trapped explicitly: assertion failed at create-then-trap.mo:9.5-9.17" diff --git a/test/run-stub/ok/create-then-trap.run-ir.ok b/test/run-drun/ok/create-then-trap.run-ir.ok similarity index 100% rename from test/run-stub/ok/create-then-trap.run-ir.ok rename to test/run-drun/ok/create-then-trap.run-ir.ok diff --git a/test/run-stub/ok/create-then-trap.run-low.ok b/test/run-drun/ok/create-then-trap.run-low.ok similarity index 100% rename from test/run-stub/ok/create-then-trap.run-low.ok rename to test/run-drun/ok/create-then-trap.run-low.ok diff --git a/test/run-stub/ok/create-then-trap.run.ok b/test/run-drun/ok/create-then-trap.run.ok similarity index 100% rename from test/run-stub/ok/create-then-trap.run.ok rename to test/run-drun/ok/create-then-trap.run.ok diff --git a/test/run-drun/ok/data-params.comp.ok b/test/run-drun/ok/data-params.comp.ok new file mode 100644 index 00000000000..fcde506cb9a --- /dev/null +++ b/test/run-drun/ok/data-params.comp.ok @@ -0,0 +1,76 @@ +data-params.mo:76.5-76.11: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +data-params.mo:77.5-77.11: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +data-params.mo:78.5-78.11: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +data-params.mo:79.5-79.11: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +data-params.mo:80.5-80.11: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +data-params.mo:81.5-81.11: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +data-params.mo:82.5-82.12: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +data-params.mo:83.5-83.12: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +data-params.mo:84.5-84.16: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +data-params.mo:85.5-85.15: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +data-params.mo:86.5-86.13: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +data-params.mo:87.5-87.13: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +data-params.mo:88.5-88.16: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +data-params.mo:89.5-89.16: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +data-params.mo:90.5-90.17: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +data-params.mo:91.5-91.17: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +data-params.mo:92.5-92.19: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +data-params.mo:93.5-93.19: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +data-params.mo:94.5-94.19: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +data-params.mo:95.5-95.22: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +data-params.mo:96.5-96.11: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +data-params.mo:97.5-97.11: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +data-params.mo:98.5-98.11: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +data-params.mo:99.5-99.15: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +data-params.mo:100.5-100.15: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +data-params.mo:101.5-101.14: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +data-params.mo:102.5-102.14: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +data-params.mo:103.5-103.14: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +data-params.mo:104.5-104.11: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +data-params.mo:105.5-105.11: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +data-params.mo:106.5-106.11: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +data-params.mo:107.5-107.11: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +data-params.mo:108.5-108.11: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +data-params.mo:109.5-109.11: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +data-params.mo:110.5-110.11: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +data-params.mo:111.5-111.11: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +data-params.mo:112.5-112.11: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +data-params.mo:113.5-113.11: type error, calling a shared function not yet supported + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/data-params.comp.ret.ok b/test/run-drun/ok/data-params.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/data-params.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-stub/ok/data-params.ic-stub-run.ok b/test/run-drun/ok/data-params.ic-stub-run.ok similarity index 90% rename from test/run-stub/ok/data-params.ic-stub-run.ok rename to test/run-drun/ok/data-params.ic-stub-run.ok index 7b5b4b7e2d5..f91829e5655 100644 --- a/test/run-stub/ok/data-params.ic-stub-run.ok +++ b/test/run-drun/ok/data-params.ic-stub-run.ok @@ -1,6 +1,8 @@ → create ← completed: canister-id = 0x0000000000000400 → install +← completed +→ update go(0x4449444c0000) 0 +1 +3 @@ -42,4 +44,4 @@ Foo2: +2_148_489_911 +2_148_489_869 +4_295_973_516 -← completed +← completed: 0x4449444c0000 diff --git a/test/run-stub/ok/data-params.run-ir.ok b/test/run-drun/ok/data-params.run-ir.ok similarity index 100% rename from test/run-stub/ok/data-params.run-ir.ok rename to test/run-drun/ok/data-params.run-ir.ok diff --git a/test/run-stub/ok/data-params.run-low.ok b/test/run-drun/ok/data-params.run-low.ok similarity index 100% rename from test/run-stub/ok/data-params.run-low.ok rename to test/run-drun/ok/data-params.run-low.ok diff --git a/test/run-stub/ok/data-params.run.ok b/test/run-drun/ok/data-params.run.ok similarity index 100% rename from test/run-stub/ok/data-params.run.ok rename to test/run-drun/ok/data-params.run.ok diff --git a/test/run-stub/ok/data-params.tc.ok b/test/run-drun/ok/data-params.tc.ok similarity index 100% rename from test/run-stub/ok/data-params.tc.ok rename to test/run-drun/ok/data-params.tc.ok diff --git a/test/run-drun/ok/divide-by-zero.drun-run.ok b/test/run-drun/ok/divide-by-zero.drun-run.ok new file mode 100644 index 00000000000..5da68903a6c --- /dev/null +++ b/test/run-drun/ok/divide-by-zero.drun-run.ok @@ -0,0 +1 @@ +ingress(0) Err: IC0502: Canister 42 trapped: integer division by 0 diff --git a/test/run-stub/ok/divide-by-zero.run-ir.ok b/test/run-drun/ok/divide-by-zero.run-ir.ok similarity index 100% rename from test/run-stub/ok/divide-by-zero.run-ir.ok rename to test/run-drun/ok/divide-by-zero.run-ir.ok diff --git a/test/run-stub/ok/divide-by-zero.run-low.ok b/test/run-drun/ok/divide-by-zero.run-low.ok similarity index 100% rename from test/run-stub/ok/divide-by-zero.run-low.ok rename to test/run-drun/ok/divide-by-zero.run-low.ok diff --git a/test/run-stub/ok/divide-by-zero.run.ok b/test/run-drun/ok/divide-by-zero.run.ok similarity index 100% rename from test/run-stub/ok/divide-by-zero.run.ok rename to test/run-drun/ok/divide-by-zero.run.ok diff --git a/test/run-drun/ok/divide-by-zero.run.ret.ok b/test/run-drun/ok/divide-by-zero.run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/divide-by-zero.run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-drun/ok/arity_bug.drun-run.ok b/test/run-drun/ok/empty-actor.drun-run.ok similarity index 100% rename from test/run-drun/ok/arity_bug.drun-run.ok rename to test/run-drun/ok/empty-actor.drun-run.ok diff --git a/test/run-drun/ok/flatten-awaitables.comp.ok b/test/run-drun/ok/flatten-awaitables.comp.ok new file mode 100644 index 00000000000..454b23a70f0 --- /dev/null +++ b/test/run-drun/ok/flatten-awaitables.comp.ok @@ -0,0 +1,80 @@ +flatten-awaitables.mo:16.16-16.18: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +flatten-awaitables.mo:18.16-18.18: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +flatten-awaitables.mo:20.16-20.18: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +flatten-awaitables.mo:22.16-22.18: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +flatten-awaitables.mo:25.16-25.18: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +flatten-awaitables.mo:27.16-27.18: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +flatten-awaitables.mo:29.16-29.18: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +flatten-awaitables.mo:31.16-31.18: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +flatten-awaitables.mo:37.20-37.24: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +flatten-awaitables.mo:39.19-39.23: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +flatten-awaitables.mo:41.26-41.30: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +flatten-awaitables.mo:43.34-43.38: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +flatten-awaitables.mo:46.20-46.24: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +flatten-awaitables.mo:48.19-48.23: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +flatten-awaitables.mo:50.26-50.30: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +flatten-awaitables.mo:52.34-52.38: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +flatten-awaitables.mo:60.20-60.24: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +flatten-awaitables.mo:62.19-62.23: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +flatten-awaitables.mo:64.26-64.30: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +flatten-awaitables.mo:66.34-66.38: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +flatten-awaitables.mo:69.20-69.24: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +flatten-awaitables.mo:71.19-71.23: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +flatten-awaitables.mo:73.26-73.30: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +flatten-awaitables.mo:75.34-75.38: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +flatten-awaitables.mo:79.20-79.24: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +flatten-awaitables.mo:81.19-81.23: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +flatten-awaitables.mo:83.26-83.30: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +flatten-awaitables.mo:85.34-85.38: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +flatten-awaitables.mo:88.20-88.24: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +flatten-awaitables.mo:90.19-90.23: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +flatten-awaitables.mo:92.26-92.30: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +flatten-awaitables.mo:94.34-94.38: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +flatten-awaitables.mo:97.20-97.24: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +flatten-awaitables.mo:99.19-99.23: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +flatten-awaitables.mo:101.26-101.30: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +flatten-awaitables.mo:103.34-103.38: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +flatten-awaitables.mo:106.20-106.24: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +flatten-awaitables.mo:108.19-108.23: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +flatten-awaitables.mo:110.26-110.30: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +flatten-awaitables.mo:112.34-112.38: type error, calling a shared function not yet supported + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/flatten-awaitables.comp.ret.ok b/test/run-drun/ok/flatten-awaitables.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/flatten-awaitables.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-stub/ok/flatten-awaitables.ic-stub-run.ok b/test/run-drun/ok/flatten-awaitables.ic-stub-run.ok similarity index 75% rename from test/run-stub/ok/flatten-awaitables.ic-stub-run.ok rename to test/run-drun/ok/flatten-awaitables.ic-stub-run.ok index 31491e54d1f..68cd8a896b3 100644 --- a/test/run-stub/ok/flatten-awaitables.ic-stub-run.ok +++ b/test/run-drun/ok/flatten-awaitables.ic-stub-run.ok @@ -1,6 +1,8 @@ → create ← completed: canister-id = 0x0000000000000400 → install +← completed +→ update go(0x4449444c0000) first-order 0 1 @@ -35,4 +37,4 @@ higher-order 13 14 15 -← completed +← completed: 0x4449444c0000 diff --git a/test/run-stub/ok/flatten-awaitables.run-ir.ok b/test/run-drun/ok/flatten-awaitables.run-ir.ok similarity index 100% rename from test/run-stub/ok/flatten-awaitables.run-ir.ok rename to test/run-drun/ok/flatten-awaitables.run-ir.ok diff --git a/test/run-stub/ok/flatten-awaitables.run-low.ok b/test/run-drun/ok/flatten-awaitables.run-low.ok similarity index 100% rename from test/run-stub/ok/flatten-awaitables.run-low.ok rename to test/run-drun/ok/flatten-awaitables.run-low.ok diff --git a/test/run-stub/ok/flatten-awaitables.run.ok b/test/run-drun/ok/flatten-awaitables.run.ok similarity index 100% rename from test/run-stub/ok/flatten-awaitables.run.ok rename to test/run-drun/ok/flatten-awaitables.run.ok diff --git a/test/run-stub/ok/flatten-awaitables.tc.ok b/test/run-drun/ok/flatten-awaitables.tc.ok similarity index 54% rename from test/run-stub/ok/flatten-awaitables.tc.ok rename to test/run-drun/ok/flatten-awaitables.tc.ok index a172866abd7..96cd1962c42 100644 --- a/test/run-stub/ok/flatten-awaitables.tc.ok +++ b/test/run-drun/ok/flatten-awaitables.tc.ok @@ -1,118 +1,118 @@ -flatten-awaitables.mo:41.9-41.10: warning, this pattern consuming type +flatten-awaitables.mo:39.9-39.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.mo:43.9-43.17: warning, this pattern consuming type +flatten-awaitables.mo:41.9-41.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.mo:45.9-45.25: warning, this pattern consuming type +flatten-awaitables.mo:43.9-43.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.mo:50.9-50.10: warning, this pattern consuming type +flatten-awaitables.mo:48.9-48.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.mo:52.9-52.17: warning, this pattern consuming type +flatten-awaitables.mo:50.9-50.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.mo:54.9-54.25: warning, this pattern consuming type +flatten-awaitables.mo:52.9-52.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.mo:64.9-64.10: warning, this pattern consuming type +flatten-awaitables.mo:62.9-62.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.mo:66.9-66.17: warning, this pattern consuming type +flatten-awaitables.mo:64.9-64.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.mo:68.9-68.25: warning, this pattern consuming type +flatten-awaitables.mo:66.9-66.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.mo:73.9-73.10: warning, this pattern consuming type +flatten-awaitables.mo:71.9-71.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.mo:75.9-75.17: warning, this pattern consuming type +flatten-awaitables.mo:73.9-73.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.mo:77.9-77.25: warning, this pattern consuming type +flatten-awaitables.mo:75.9-75.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.mo:83.9-83.10: warning, this pattern consuming type +flatten-awaitables.mo:81.9-81.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.mo:85.9-85.17: warning, this pattern consuming type +flatten-awaitables.mo:83.9-83.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.mo:87.9-87.25: warning, this pattern consuming type +flatten-awaitables.mo:85.9-85.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.mo:92.9-92.10: warning, this pattern consuming type +flatten-awaitables.mo:90.9-90.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.mo:94.9-94.17: warning, this pattern consuming type +flatten-awaitables.mo:92.9-92.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.mo:96.9-96.25: warning, this pattern consuming type +flatten-awaitables.mo:94.9-94.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.mo:101.9-101.10: warning, this pattern consuming type +flatten-awaitables.mo:99.9-99.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.mo:103.9-103.17: warning, this pattern consuming type +flatten-awaitables.mo:101.9-101.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.mo:105.9-105.25: warning, this pattern consuming type +flatten-awaitables.mo:103.9-103.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.mo:110.9-110.10: warning, this pattern consuming type +flatten-awaitables.mo:108.9-108.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.mo:112.9-112.17: warning, this pattern consuming type +flatten-awaitables.mo:110.9-110.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.mo:114.9-114.25: warning, this pattern consuming type +flatten-awaitables.mo:112.9-112.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or diff --git a/test/run-drun/ok/for-await.comp.ok b/test/run-drun/ok/for-await.comp.ok new file mode 100644 index 00000000000..96103de3721 --- /dev/null +++ b/test/run-drun/ok/for-await.comp.ok @@ -0,0 +1,2 @@ +for-await.mo:9.15-9.29: type error, unsupported async block + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/for-await.comp.ret.ok b/test/run-drun/ok/for-await.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/for-await.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-stub/ok/for-await.ic-stub-run.ok b/test/run-drun/ok/for-await.ic-stub-run.ok similarity index 64% rename from test/run-stub/ok/for-await.ic-stub-run.ok rename to test/run-drun/ok/for-await.ic-stub-run.ok index 5e7fbc6f075..f87d851ae57 100644 --- a/test/run-stub/ok/for-await.ic-stub-run.ok +++ b/test/run-drun/ok/for-await.ic-stub-run.ok @@ -1,6 +1,8 @@ → create ← completed: canister-id = 0x0000000000000400 → install +← completed +→ update go(0x4449444c0000) 0 1 2 @@ -12,4 +14,4 @@ 8 9 10 -← completed +← completed: 0x4449444c0000 diff --git a/test/run-stub/ok/for-await.run-ir.ok b/test/run-drun/ok/for-await.run-ir.ok similarity index 100% rename from test/run-stub/ok/for-await.run-ir.ok rename to test/run-drun/ok/for-await.run-ir.ok diff --git a/test/run-stub/ok/for-await.run-low.ok b/test/run-drun/ok/for-await.run-low.ok similarity index 100% rename from test/run-stub/ok/for-await.run-low.ok rename to test/run-drun/ok/for-await.run-low.ok diff --git a/test/run-stub/ok/for-await.run.ok b/test/run-drun/ok/for-await.run.ok similarity index 100% rename from test/run-stub/ok/for-await.run.ok rename to test/run-drun/ok/for-await.run.ok diff --git a/test/run-drun/ok/free-callbacks.comp.ok b/test/run-drun/ok/free-callbacks.comp.ok new file mode 100644 index 00000000000..ba466e2a62a --- /dev/null +++ b/test/run-drun/ok/free-callbacks.comp.ok @@ -0,0 +1,6 @@ +free-callbacks.mo:8.11-8.15: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +free-callbacks.mo:10.11-10.15: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +free-callbacks.mo:14.11-14.15: type error, calling a shared function not yet supported + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/free-callbacks.comp.ret.ok b/test/run-drun/ok/free-callbacks.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/free-callbacks.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-stub/ok/free-callbacks.ic-stub-run.ok b/test/run-drun/ok/free-callbacks.ic-stub-run.ok similarity index 64% rename from test/run-stub/ok/free-callbacks.ic-stub-run.ok rename to test/run-drun/ok/free-callbacks.ic-stub-run.ok index 606daecf164..c0dd9fe3c55 100644 --- a/test/run-stub/ok/free-callbacks.ic-stub-run.ok +++ b/test/run-drun/ok/free-callbacks.ic-stub-run.ok @@ -1,5 +1,7 @@ → create ← completed: canister-id = 0x0000000000000400 → install -Ignore Diff: (ignored) ← completed +→ update go(0x4449444c0000) +Ignore Diff: (ignored) +← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/hello-world-async.comp.ok b/test/run-drun/ok/hello-world-async.comp.ok new file mode 100644 index 00000000000..daff32bfed8 --- /dev/null +++ b/test/run-drun/ok/hello-world-async.comp.ok @@ -0,0 +1,2 @@ +hello-world-async.mo:6.5-6.12: type error, calling a shared function not yet supported + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/hello-world-async.comp.ret.ok b/test/run-drun/ok/hello-world-async.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/hello-world-async.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-stub/ok/hello-world-async.ic-stub-run.ok b/test/run-drun/ok/hello-world-async.ic-stub-run.ok similarity index 62% rename from test/run-stub/ok/hello-world-async.ic-stub-run.ok rename to test/run-drun/ok/hello-world-async.ic-stub-run.ok index 952ef550629..6e0af8d4f09 100644 --- a/test/run-stub/ok/hello-world-async.ic-stub-run.ok +++ b/test/run-drun/ok/hello-world-async.ic-stub-run.ok @@ -1,6 +1,8 @@ → create ← completed: canister-id = 0x0000000000000400 → install +← completed +→ update go(0x4449444c0000) Hello World! -← completed +← completed: 0x4449444c0000 diff --git a/test/run-stub/ok/hello-world-async.run-ir.ok b/test/run-drun/ok/hello-world-async.run-ir.ok similarity index 100% rename from test/run-stub/ok/hello-world-async.run-ir.ok rename to test/run-drun/ok/hello-world-async.run-ir.ok diff --git a/test/run-stub/ok/hello-world-async.run-low.ok b/test/run-drun/ok/hello-world-async.run-low.ok similarity index 100% rename from test/run-stub/ok/hello-world-async.run-low.ok rename to test/run-drun/ok/hello-world-async.run-low.ok diff --git a/test/run-stub/ok/hello-world-async.run.ok b/test/run-drun/ok/hello-world-async.run.ok similarity index 100% rename from test/run-stub/ok/hello-world-async.run.ok rename to test/run-drun/ok/hello-world-async.run.ok diff --git a/test/run-drun/ok/hello-world-await.comp.ok b/test/run-drun/ok/hello-world-await.comp.ok new file mode 100644 index 00000000000..3a0f615f7b1 --- /dev/null +++ b/test/run-drun/ok/hello-world-await.comp.ok @@ -0,0 +1,2 @@ +hello-world-await.mo:9.23-9.28: type error, calling a shared function not yet supported + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/hello-world-await.comp.ret.ok b/test/run-drun/ok/hello-world-await.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/hello-world-await.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-stub/ok/hello-world-await.ic-stub-run.ok b/test/run-drun/ok/hello-world-await.ic-stub-run.ok similarity index 62% rename from test/run-stub/ok/hello-world-await.ic-stub-run.ok rename to test/run-drun/ok/hello-world-await.ic-stub-run.ok index 7f2eae552c1..4b03e43e0df 100644 --- a/test/run-stub/ok/hello-world-await.ic-stub-run.ok +++ b/test/run-drun/ok/hello-world-await.ic-stub-run.ok @@ -1,5 +1,7 @@ → create ← completed: canister-id = 0x0000000000000400 → install -Hello World! ← completed +→ update go(0x4449444c0000) +Hello World! +← completed: 0x4449444c0000 diff --git a/test/run-stub/ok/hello-world-await.run-ir.ok b/test/run-drun/ok/hello-world-await.run-ir.ok similarity index 100% rename from test/run-stub/ok/hello-world-await.run-ir.ok rename to test/run-drun/ok/hello-world-await.run-ir.ok diff --git a/test/run-stub/ok/hello-world-await.run-low.ok b/test/run-drun/ok/hello-world-await.run-low.ok similarity index 100% rename from test/run-stub/ok/hello-world-await.run-low.ok rename to test/run-drun/ok/hello-world-await.run-low.ok diff --git a/test/run-stub/ok/hello-world-await.run.ok b/test/run-drun/ok/hello-world-await.run.ok similarity index 100% rename from test/run-stub/ok/hello-world-await.run.ok rename to test/run-drun/ok/hello-world-await.run.ok diff --git a/test/run-drun/ok/hello-world-message2.drun-run.ok b/test/run-drun/ok/hello-world-message2.drun-run.ok deleted file mode 100644 index ae5f39f9b7f..00000000000 --- a/test/run-drun/ok/hello-world-message2.drun-run.ok +++ /dev/null @@ -1,2 +0,0 @@ -ingress(0) System -Error: "Line 1: Illegal method name: 0x4449444C0000." diff --git a/test/run-drun/ok/ic-calls.comp.ok b/test/run-drun/ok/ic-calls.comp.ok index 7010e97b311..14732db46bd 100644 --- a/test/run-drun/ok/ic-calls.comp.ok +++ b/test/run-drun/ok/ic-calls.comp.ok @@ -1,6 +1,6 @@ -ic-calls.mo:17.20-17.21: type error, calling a shared function not yet supported +ic-calls.mo:14.20-14.21: type error, calling a shared function not yet supported (This is a limitation of the current version.) -ic-calls.mo:18.19-18.20: type error, calling a shared function not yet supported +ic-calls.mo:15.19-15.20: type error, calling a shared function not yet supported (This is a limitation of the current version.) -ic-calls.mo:19.26-19.27: type error, calling a shared function not yet supported +ic-calls.mo:16.26-16.27: type error, calling a shared function not yet supported (This is a limitation of the current version.) diff --git a/test/run-stub/ok/ic-calls.ic-stub-run.ok b/test/run-drun/ok/ic-calls.ic-stub-run.ok similarity index 58% rename from test/run-stub/ok/ic-calls.ic-stub-run.ok rename to test/run-drun/ok/ic-calls.ic-stub-run.ok index c5d70ec6f0b..be9fb5d62c0 100644 --- a/test/run-stub/ok/ic-calls.ic-stub-run.ok +++ b/test/run-drun/ok/ic-calls.ic-stub-run.ok @@ -1,8 +1,6 @@ → create ← completed: canister-id = 0x0000000000000400 → install -A -B -C -test ← completed +→ update go(0x4449444c0000) +← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/ic-calls.tc.ok b/test/run-drun/ok/ic-calls.tc.ok index dec54dfc5ac..a34dae4db67 100644 --- a/test/run-drun/ok/ic-calls.tc.ok +++ b/test/run-drun/ok/ic-calls.tc.ok @@ -1,8 +1,8 @@ -ic-calls.mo:18.9-18.10: warning, this pattern consuming type +ic-calls.mo:15.9-15.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -ic-calls.mo:19.9-19.17: warning, this pattern consuming type +ic-calls.mo:16.9-16.17: warning, this pattern consuming type (Int, Bool) does not cover value (1, false) or diff --git a/test/run-stub/ok/indirect-counter.ic-stub-run.ok b/test/run-drun/ok/indirect-counter.ic-stub-run.ok similarity index 100% rename from test/run-stub/ok/indirect-counter.ic-stub-run.ok rename to test/run-drun/ok/indirect-counter.ic-stub-run.ok diff --git a/test/run-stub/ok/indirect-counter.run-ir.ok b/test/run-drun/ok/indirect-counter.run-ir.ok similarity index 100% rename from test/run-stub/ok/indirect-counter.run-ir.ok rename to test/run-drun/ok/indirect-counter.run-ir.ok diff --git a/test/run-stub/ok/indirect-counter.run-low.ok b/test/run-drun/ok/indirect-counter.run-low.ok similarity index 100% rename from test/run-stub/ok/indirect-counter.run-low.ok rename to test/run-drun/ok/indirect-counter.run-low.ok diff --git a/test/run-stub/ok/indirect-counter.run.ok b/test/run-drun/ok/indirect-counter.run.ok similarity index 100% rename from test/run-stub/ok/indirect-counter.run.ok rename to test/run-drun/ok/indirect-counter.run.ok diff --git a/test/run-drun/ok/interleave.comp.ok b/test/run-drun/ok/interleave.comp.ok new file mode 100644 index 00000000000..de4aa60175f --- /dev/null +++ b/test/run-drun/ok/interleave.comp.ok @@ -0,0 +1,2 @@ +interleave.mo:13.13-21.6: type error, unsupported async block + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/interleave.comp.ret.ok b/test/run-drun/ok/interleave.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/interleave.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-stub/ok/interleave.ic-stub-run.ok b/test/run-drun/ok/interleave.ic-stub-run.ok similarity index 82% rename from test/run-stub/ok/interleave.ic-stub-run.ok rename to test/run-drun/ok/interleave.ic-stub-run.ok index 7a32913cb52..ef7d5a7b558 100644 --- a/test/run-stub/ok/interleave.ic-stub-run.ok +++ b/test/run-drun/ok/interleave.ic-stub-run.ok @@ -1,6 +1,8 @@ → create ← completed: canister-id = 0x0000000000000400 → install +← completed +→ update go(0x4449444c0000) g e-while @@ -20,4 +22,4 @@ g cnt: 9 i: 14 g-exit -← completed +← completed: 0x4449444c0000 diff --git a/test/run-stub/ok/interleave.run-ir.ok b/test/run-drun/ok/interleave.run-ir.ok similarity index 100% rename from test/run-stub/ok/interleave.run-ir.ok rename to test/run-drun/ok/interleave.run-ir.ok diff --git a/test/run-stub/ok/interleave.run-low.ok b/test/run-drun/ok/interleave.run-low.ok similarity index 100% rename from test/run-stub/ok/interleave.run-low.ok rename to test/run-drun/ok/interleave.run-low.ok diff --git a/test/run-stub/ok/interleave.run.ok b/test/run-drun/ok/interleave.run.ok similarity index 100% rename from test/run-stub/ok/interleave.run.ok rename to test/run-drun/ok/interleave.run.ok diff --git a/test/run-drun/ok/issue-894.comp.ok b/test/run-drun/ok/issue-894.comp.ok new file mode 100644 index 00000000000..5499821b6d7 --- /dev/null +++ b/test/run-drun/ok/issue-894.comp.ok @@ -0,0 +1,8 @@ +issue-894.mo:15.20-15.27: type error, unsupported async block + (This is a limitation of the current version.) +issue-894.mo:22.15-22.22: type error, unsupported async block + (This is a limitation of the current version.) +issue-894.mo:29.15-29.22: type error, unsupported async block + (This is a limitation of the current version.) +issue-894.mo:37.17-37.19: type error, calling a shared function not yet supported + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/issue-894.comp.ret.ok b/test/run-drun/ok/issue-894.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/issue-894.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-stub/ok/issue-894.ic-stub-run.ok b/test/run-drun/ok/issue-894.ic-stub-run.ok similarity index 63% rename from test/run-stub/ok/issue-894.ic-stub-run.ok rename to test/run-drun/ok/issue-894.ic-stub-run.ok index b43fa49a755..00808d3be96 100644 --- a/test/run-stub/ok/issue-894.ic-stub-run.ok +++ b/test/run-drun/ok/issue-894.ic-stub-run.ok @@ -1,6 +1,8 @@ → create ← completed: canister-id = 0x0000000000000400 → install +← completed +→ update go(0x4449444c0000) 1 1 1 @@ -10,4 +12,4 @@ 2 3 4 -← completed +← completed: 0x4449444c0000 diff --git a/test/run-stub/ok/issue-894.run-ir.ok b/test/run-drun/ok/issue-894.run-ir.ok similarity index 100% rename from test/run-stub/ok/issue-894.run-ir.ok rename to test/run-drun/ok/issue-894.run-ir.ok diff --git a/test/run-stub/ok/issue-894.run-low.ok b/test/run-drun/ok/issue-894.run-low.ok similarity index 100% rename from test/run-stub/ok/issue-894.run-low.ok rename to test/run-drun/ok/issue-894.run-low.ok diff --git a/test/run-stub/ok/issue-894.run.ok b/test/run-drun/ok/issue-894.run.ok similarity index 100% rename from test/run-stub/ok/issue-894.run.ok rename to test/run-drun/ok/issue-894.run.ok diff --git a/test/run-drun/ok/local-throw.comp.ok b/test/run-drun/ok/local-throw.comp.ok new file mode 100644 index 00000000000..2d6bffe44eb --- /dev/null +++ b/test/run-drun/ok/local-throw.comp.ok @@ -0,0 +1,4 @@ +local-throw.mo:53.13-53.15: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +local-throw.mo:60.13-60.15: type error, calling a shared function not yet supported + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/local-throw.comp.ret.ok b/test/run-drun/ok/local-throw.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/local-throw.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-stub/ok/local-throw.ic-stub-run.ok b/test/run-drun/ok/local-throw.ic-stub-run.ok similarity index 61% rename from test/run-stub/ok/local-throw.ic-stub-run.ok rename to test/run-drun/ok/local-throw.ic-stub-run.ok index 49cd150c9d8..4421ebdca21 100644 --- a/test/run-stub/ok/local-throw.ic-stub-run.ok +++ b/test/run-drun/ok/local-throw.ic-stub-run.ok @@ -1,6 +1,8 @@ → create ← completed: canister-id = 0x0000000000000400 → install +← completed +→ update go(0x4449444c0000) t2 ok t3 ok -← completed +← completed: 0x4449444c0000 diff --git a/test/run-stub/ok/local-throw.run-ir.ok b/test/run-drun/ok/local-throw.run-ir.ok similarity index 100% rename from test/run-stub/ok/local-throw.run-ir.ok rename to test/run-drun/ok/local-throw.run-ir.ok diff --git a/test/run-stub/ok/local-throw.run-low.ok b/test/run-drun/ok/local-throw.run-low.ok similarity index 100% rename from test/run-stub/ok/local-throw.run-low.ok rename to test/run-drun/ok/local-throw.run-low.ok diff --git a/test/run-stub/ok/local-throw.run.ok b/test/run-drun/ok/local-throw.run.ok similarity index 100% rename from test/run-stub/ok/local-throw.run.ok rename to test/run-drun/ok/local-throw.run.ok diff --git a/test/run-drun/ok/modexp1.drun-run.ok b/test/run-drun/ok/modexp1.drun-run.ok deleted file mode 100644 index 43d7af40394..00000000000 --- a/test/run-drun/ok/modexp1.drun-run.ok +++ /dev/null @@ -1 +0,0 @@ -ingress(0) System diff --git a/test/run-drun/ok/modexp2.drun-run.ok b/test/run-drun/ok/modexp2.drun-run.ok deleted file mode 100644 index 43d7af40394..00000000000 --- a/test/run-drun/ok/modexp2.drun-run.ok +++ /dev/null @@ -1 +0,0 @@ -ingress(0) System diff --git a/test/run-drun/ok/modexp3.drun-run.ok b/test/run-drun/ok/modexp3.drun-run.ok deleted file mode 100644 index 43d7af40394..00000000000 --- a/test/run-drun/ok/modexp3.drun-run.ok +++ /dev/null @@ -1 +0,0 @@ -ingress(0) System diff --git a/test/run-drun/ok/modexp4.drun-run.ok b/test/run-drun/ok/modexp4.drun-run.ok deleted file mode 100644 index 43d7af40394..00000000000 --- a/test/run-drun/ok/modexp4.drun-run.ok +++ /dev/null @@ -1 +0,0 @@ -ingress(0) System diff --git a/test/run-drun/ok/modules-bwd.drun-run.ok b/test/run-drun/ok/modules-bwd.drun-run.ok deleted file mode 100644 index 43d7af40394..00000000000 --- a/test/run-drun/ok/modules-bwd.drun-run.ok +++ /dev/null @@ -1 +0,0 @@ -ingress(0) System diff --git a/test/run-drun/ok/multiple-actors.comp.ok b/test/run-drun/ok/multiple-actors.comp.ok deleted file mode 100644 index 1e157831f17..00000000000 --- a/test/run-drun/ok/multiple-actors.comp.ok +++ /dev/null @@ -1,4 +0,0 @@ -multiple-actors.mo:1.1-1.12: type error, multiple actors in program; there must be at most one actor declaration in a program - (This is a limitation of the current version.) -multiple-actors.mo:3.1-3.12: type error, multiple actors in program; there must be at most one actor declaration in a program - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/nary-async.comp.ok b/test/run-drun/ok/nary-async.comp.ok new file mode 100644 index 00000000000..df59247982e --- /dev/null +++ b/test/run-drun/ok/nary-async.comp.ok @@ -0,0 +1,16 @@ +nary-async.mo:22.14-25.8: type error, unsupported async block + (This is a limitation of the current version.) +nary-async.mo:30.14-33.8: type error, unsupported async block + (This is a limitation of the current version.) +nary-async.mo:38.14-41.8: type error, unsupported async block + (This is a limitation of the current version.) +nary-async.mo:46.14-49.8: type error, unsupported async block + (This is a limitation of the current version.) +nary-async.mo:68.14-71.8: type error, unsupported async block + (This is a limitation of the current version.) +nary-async.mo:76.14-81.8: type error, unsupported async block + (This is a limitation of the current version.) +nary-async.mo:86.14-92.8: type error, unsupported async block + (This is a limitation of the current version.) +nary-async.mo:98.14-105.8: type error, unsupported async block + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/nary-async.comp.ret.ok b/test/run-drun/ok/nary-async.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/nary-async.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-drun/ok/nary-async.ic-stub-run.ok b/test/run-drun/ok/nary-async.ic-stub-run.ok new file mode 100644 index 00000000000..2a1bd71f3fc --- /dev/null +++ b/test/run-drun/ok/nary-async.ic-stub-run.ok @@ -0,0 +1,16 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ update go1(0x4449444c0000) +0_0 +1_0 +2_0 +3_0 +← completed: 0x4449444c0000 +→ update go2(0x4449444c0000) +0_0 +0_1 +0_2 +0_3 +← completed: 0x4449444c0000 diff --git a/test/run-stub/ok/nary-async.run-ir.ok b/test/run-drun/ok/nary-async.run-ir.ok similarity index 100% rename from test/run-stub/ok/nary-async.run-ir.ok rename to test/run-drun/ok/nary-async.run-ir.ok diff --git a/test/run-stub/ok/nary-async.run-low.ok b/test/run-drun/ok/nary-async.run-low.ok similarity index 100% rename from test/run-stub/ok/nary-async.run-low.ok rename to test/run-drun/ok/nary-async.run-low.ok diff --git a/test/run-stub/ok/nary-async.run.ok b/test/run-drun/ok/nary-async.run.ok similarity index 100% rename from test/run-stub/ok/nary-async.run.ok rename to test/run-drun/ok/nary-async.run.ok diff --git a/test/run-drun/ok/oneway.comp.ok b/test/run-drun/ok/oneway.comp.ok new file mode 100644 index 00000000000..8142047c85a --- /dev/null +++ b/test/run-drun/ok/oneway.comp.ok @@ -0,0 +1,8 @@ +oneway.mo:57.5-57.11: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +oneway.mo:59.5-59.14: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +oneway.mo:61.5-61.12: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +oneway.mo:63.5-63.15: type error, calling a shared function not yet supported + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/oneway.comp.ret.ok b/test/run-drun/ok/oneway.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/oneway.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-drun/ok/oneway.drun-run.ok b/test/run-drun/ok/oneway.drun-run.ok deleted file mode 100644 index 8ce9c90d9f3..00000000000 --- a/test/run-drun/ok/oneway.drun-run.ok +++ /dev/null @@ -1,11 +0,0 @@ -ingress(0) System -debug.print: 1 -debug.print: 2 -ingress(1) Completed: Canister: Payload: 0x4449444c0000 -debug.print: 3 -debug.print: 4 -ingress(2) Completed: Canister: Payload: 0x4449444c0000 -debug.print: 5 -ingress(3) Completed: Canister: Payload: 0x4449444c0000 -debug.print: 6 -ingress(4) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/oneway.ic-stub-run.ok b/test/run-drun/ok/oneway.ic-stub-run.ok new file mode 100644 index 00000000000..77ae2960ad1 --- /dev/null +++ b/test/run-drun/ok/oneway.ic-stub-run.ok @@ -0,0 +1,17 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ update go(0x4449444c0000) +A +B +C +D +E +1 +2 +3 +4 +5 +6 +← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/test_oneway.run-ir.ok b/test/run-drun/ok/oneway.run-ir.ok similarity index 100% rename from test/run-drun/ok/test_oneway.run-ir.ok rename to test/run-drun/ok/oneway.run-ir.ok diff --git a/test/run-drun/ok/test_oneway.run-low.ok b/test/run-drun/ok/oneway.run-low.ok similarity index 100% rename from test/run-drun/ok/test_oneway.run-low.ok rename to test/run-drun/ok/oneway.run-low.ok diff --git a/test/run-drun/ok/test_oneway.run.ok b/test/run-drun/ok/oneway.run.ok similarity index 100% rename from test/run-drun/ok/test_oneway.run.ok rename to test/run-drun/ok/oneway.run.ok diff --git a/test/run-drun/ok/overflow.comp.ok b/test/run-drun/ok/overflow.comp.ok new file mode 100644 index 00000000000..03d8fa71e12 --- /dev/null +++ b/test/run-drun/ok/overflow.comp.ok @@ -0,0 +1,12 @@ +overflow.mo:7.12-10.6: type error, unsupported async block + (This is a limitation of the current version.) +overflow.mo:11.12-14.6: type error, unsupported async block + (This is a limitation of the current version.) +overflow.mo:15.12-18.6: type error, unsupported async block + (This is a limitation of the current version.) +overflow.mo:19.12-22.6: type error, unsupported async block + (This is a limitation of the current version.) +overflow.mo:23.12-26.6: type error, unsupported async block + (This is a limitation of the current version.) +overflow.mo:27.12-30.6: type error, unsupported async block + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/overflow.comp.ret.ok b/test/run-drun/ok/overflow.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/overflow.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-stub/ok/overflow.ic-stub-run.ok b/test/run-drun/ok/overflow.ic-stub-run.ok similarity index 66% rename from test/run-stub/ok/overflow.ic-stub-run.ok rename to test/run-drun/ok/overflow.ic-stub-run.ok index 20223842232..75dbec3a4ea 100644 --- a/test/run-stub/ok/overflow.ic-stub-run.ok +++ b/test/run-drun/ok/overflow.ic-stub-run.ok @@ -1,12 +1,13 @@ → create ← completed: canister-id = 0x0000000000000400 → install +← completed +→ update go(0x4449444c0000) This is reachable. This is reachable. Trap: EvalTrapError :0.1 "canister trapped explicitly: Natural subtraction underflow" -Trap: EvalTrapError :0.1 "canister trapped explicitly: Natural subtraction underflow" +This is reachable. This is reachable. This is reachable. Trap: EvalTrapError :0.1 "canister trapped explicitly: reject_callback" -Trap: EvalTrapError :0.1 "canister trapped explicitly: reject_callback" -← completed +← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/overflow.run-ir.ok b/test/run-drun/ok/overflow.run-ir.ok new file mode 100644 index 00000000000..87b51c66e67 --- /dev/null +++ b/test/run-drun/ok/overflow.run-ir.ok @@ -0,0 +1,6 @@ +This is reachable. +This is reachable. +overflow.mo:16.18-16.21: execution error, arithmetic overflow +This is reachable. +This is reachable. +This is reachable. diff --git a/test/run-drun/ok/overflow.run-low.ok b/test/run-drun/ok/overflow.run-low.ok new file mode 100644 index 00000000000..87b51c66e67 --- /dev/null +++ b/test/run-drun/ok/overflow.run-low.ok @@ -0,0 +1,6 @@ +This is reachable. +This is reachable. +overflow.mo:16.18-16.21: execution error, arithmetic overflow +This is reachable. +This is reachable. +This is reachable. diff --git a/test/run-drun/ok/overflow.run.ok b/test/run-drun/ok/overflow.run.ok new file mode 100644 index 00000000000..87b51c66e67 --- /dev/null +++ b/test/run-drun/ok/overflow.run.ok @@ -0,0 +1,6 @@ +This is reachable. +This is reachable. +overflow.mo:16.18-16.21: execution error, arithmetic overflow +This is reachable. +This is reachable. +This is reachable. diff --git a/test/run-drun/ok/pass-references.comp.ok b/test/run-drun/ok/pass-references.comp.ok new file mode 100644 index 00000000000..77c0fedbdf0 --- /dev/null +++ b/test/run-drun/ok/pass-references.comp.ok @@ -0,0 +1,12 @@ +pass-references.mo:5.5-5.6: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +pass-references.mo:9.5-9.10: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +pass-references.mo:13.5-15.6: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program + (This is a limitation of the current version.) +pass-references.mo:16.5-16.14: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +pass-references.mo:17.5-17.14: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +pass-references.mo:18.5-18.15: type error, calling a shared function not yet supported + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/pass-references.comp.ret.ok b/test/run-drun/ok/pass-references.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/pass-references.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-stub/ok/pass-references.ic-stub-run.ok b/test/run-drun/ok/pass-references.ic-stub-run.ok similarity index 60% rename from test/run-stub/ok/pass-references.ic-stub-run.ok rename to test/run-drun/ok/pass-references.ic-stub-run.ok index a7476cb89cd..da7d6668992 100644 --- a/test/run-stub/ok/pass-references.ic-stub-run.ok +++ b/test/run-drun/ok/pass-references.ic-stub-run.ok @@ -1,7 +1,9 @@ → create ← completed: canister-id = 0x0000000000000400 → install +← completed +→ update go(0x4449444c0000) a b b -← completed +← completed: 0x4449444c0000 diff --git a/test/run-stub/ok/pass-references.run-ir.ok b/test/run-drun/ok/pass-references.run-ir.ok similarity index 100% rename from test/run-stub/ok/pass-references.run-ir.ok rename to test/run-drun/ok/pass-references.run-ir.ok diff --git a/test/run-stub/ok/pass-references.run-low.ok b/test/run-drun/ok/pass-references.run-low.ok similarity index 100% rename from test/run-stub/ok/pass-references.run-low.ok rename to test/run-drun/ok/pass-references.run-low.ok diff --git a/test/run-stub/ok/pass-references.run.ok b/test/run-drun/ok/pass-references.run.ok similarity index 100% rename from test/run-stub/ok/pass-references.run.ok rename to test/run-drun/ok/pass-references.run.ok diff --git a/test/run-drun/ok/query2.comp.ok b/test/run-drun/ok/query2.comp.ok new file mode 100644 index 00000000000..b97f086058d --- /dev/null +++ b/test/run-drun/ok/query2.comp.ok @@ -0,0 +1,18 @@ +query2.mo:22.4-22.15: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +query2.mo:23.4-23.15: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +query2.mo:24.4-24.15: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +query2.mo:25.4-25.24: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +query2.mo:26.19-26.30: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +query2.mo:28.19-28.31: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +query2.mo:29.4-29.24: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +query2.mo:31.19-31.31: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +query2.mo:32.4-32.24: type error, calling a shared function not yet supported + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/query2.comp.ret.ok b/test/run-drun/ok/query2.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/query2.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-stub/ok/query2.ic-stub-run.ok b/test/run-drun/ok/query2.ic-stub-run.ok similarity index 69% rename from test/run-stub/ok/query2.ic-stub-run.ok rename to test/run-drun/ok/query2.ic-stub-run.ok index d15550489c8..85d7fc58931 100644 --- a/test/run-stub/ok/query2.ic-stub-run.ok +++ b/test/run-drun/ok/query2.ic-stub-run.ok @@ -1,10 +1,11 @@ → create ← completed: canister-id = 0x0000000000000400 → install +← completed +→ update go(0x4449444c0000) 2 3 4 4 Trap: EvalTrapError :0.1 "canister trapped explicitly: reject_callback" -Trap: EvalTrapError :0.1 "canister trapped explicitly: reject_callback" -← completed +← completed: 0x4449444c0000 diff --git a/test/run-stub/ok/query2.run-ir.ok b/test/run-drun/ok/query2.run-ir.ok similarity index 63% rename from test/run-stub/ok/query2.run-ir.ok rename to test/run-drun/ok/query2.run-ir.ok index 3c0e48a4d47..2fe69e6672e 100644 --- a/test/run-stub/ok/query2.run-ir.ok +++ b/test/run-drun/ok/query2.run-ir.ok @@ -8,5 +8,5 @@ In read: In read: 6 The following fails in the intepreter, for lack of query semantics -query2.mo:65.2-65.16: execution error, assertion failure +query2.mo:34.4-34.18: execution error, assertion failure 6 diff --git a/test/run-stub/ok/query2.run-low.ok b/test/run-drun/ok/query2.run-low.ok similarity index 63% rename from test/run-stub/ok/query2.run-low.ok rename to test/run-drun/ok/query2.run-low.ok index 3c0e48a4d47..2fe69e6672e 100644 --- a/test/run-stub/ok/query2.run-low.ok +++ b/test/run-drun/ok/query2.run-low.ok @@ -8,5 +8,5 @@ In read: In read: 6 The following fails in the intepreter, for lack of query semantics -query2.mo:65.2-65.16: execution error, assertion failure +query2.mo:34.4-34.18: execution error, assertion failure 6 diff --git a/test/run-stub/ok/query2.run.ok b/test/run-drun/ok/query2.run.ok similarity index 63% rename from test/run-stub/ok/query2.run.ok rename to test/run-drun/ok/query2.run.ok index 3c0e48a4d47..2fe69e6672e 100644 --- a/test/run-stub/ok/query2.run.ok +++ b/test/run-drun/ok/query2.run.ok @@ -8,5 +8,5 @@ In read: In read: 6 The following fails in the intepreter, for lack of query semantics -query2.mo:65.2-65.16: execution error, assertion failure +query2.mo:34.4-34.18: execution error, assertion failure 6 diff --git a/test/run-stub/ok/reference-params.ic-stub-run.ok b/test/run-drun/ok/reference-params.ic-stub-run.ok similarity index 100% rename from test/run-stub/ok/reference-params.ic-stub-run.ok rename to test/run-drun/ok/reference-params.ic-stub-run.ok diff --git a/test/run-stub/ok/reference-params.run-ir.ok b/test/run-drun/ok/reference-params.run-ir.ok similarity index 100% rename from test/run-stub/ok/reference-params.run-ir.ok rename to test/run-drun/ok/reference-params.run-ir.ok diff --git a/test/run-stub/ok/reference-params.run-low.ok b/test/run-drun/ok/reference-params.run-low.ok similarity index 100% rename from test/run-stub/ok/reference-params.run-low.ok rename to test/run-drun/ok/reference-params.run-low.ok diff --git a/test/run-stub/ok/reference-params.run.ok b/test/run-drun/ok/reference-params.run.ok similarity index 100% rename from test/run-stub/ok/reference-params.run.ok rename to test/run-drun/ok/reference-params.run.ok diff --git a/test/run-drun/ok/rts-stats.drun-run.ok b/test/run-drun/ok/rts-stats.drun-run.ok new file mode 100644 index 00000000000..ebe75965c6a --- /dev/null +++ b/test/run-drun/ok/rts-stats.drun-run.ok @@ -0,0 +1,2 @@ +debug.print: Size and allocation delta: (10_008, 10_008) +ingress(0) System diff --git a/test/run-drun/ok/self-calls.comp.ok b/test/run-drun/ok/self-calls.comp.ok deleted file mode 100644 index 736889609df..00000000000 --- a/test/run-drun/ok/self-calls.comp.ok +++ /dev/null @@ -1,6 +0,0 @@ -self-calls.mo:19.20-19.23: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -self-calls.mo:21.19-21.22: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -self-calls.mo:23.26-23.29: type error, calling a shared function not yet supported - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/self-calls.tc.ok b/test/run-drun/ok/self-calls.tc.ok deleted file mode 100644 index 0dc2420ebed..00000000000 --- a/test/run-drun/ok/self-calls.tc.ok +++ /dev/null @@ -1,9 +0,0 @@ -self-calls.mo:21.9-21.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -self-calls.mo:23.9-23.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (1, false) or - (0 or -1 or _, _) diff --git a/test/run-drun/ok/selftail.drun-run.ok b/test/run-drun/ok/selftail.drun-run.ok index 922e74685f0..2bed2f23c23 100644 --- a/test/run-drun/ok/selftail.drun-run.ok +++ b/test/run-drun/ok/selftail.drun-run.ok @@ -1,3 +1,3 @@ debug.print: ok1 debug.print: ok2 -ingress(0) System +ingress(0) Err: IC0502: Canister 42 trapped: stack overflow diff --git a/test/run-drun/ok/selftail.run-ir.ok b/test/run-drun/ok/selftail.run-ir.ok index 58223a7b0e6..dc15cc2f553 100644 --- a/test/run-drun/ok/selftail.run-ir.ok +++ b/test/run-drun/ok/selftail.run-ir.ok @@ -1,2 +1,3 @@ ok1 ok2 +ok3 (unreachable on drun) diff --git a/test/run-drun/ok/selftail.run-low.ok b/test/run-drun/ok/selftail.run-low.ok index 58223a7b0e6..dc15cc2f553 100644 --- a/test/run-drun/ok/selftail.run-low.ok +++ b/test/run-drun/ok/selftail.run-low.ok @@ -1,2 +1,3 @@ ok1 ok2 +ok3 (unreachable on drun) diff --git a/test/run-drun/ok/selftail.run.ok b/test/run-drun/ok/selftail.run.ok index 58223a7b0e6..dc15cc2f553 100644 --- a/test/run-drun/ok/selftail.run.ok +++ b/test/run-drun/ok/selftail.run.ok @@ -1,2 +1,3 @@ ok1 ok2 +ok3 (unreachable on drun) diff --git a/test/run-drun/ok/shared-object.comp.ok b/test/run-drun/ok/shared-object.comp.ok new file mode 100644 index 00000000000..ee047cbf1b6 --- /dev/null +++ b/test/run-drun/ok/shared-object.comp.ok @@ -0,0 +1,2 @@ +shared-object.mo:15.20-15.23: type error, calling a shared function not yet supported + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/shared-object.comp.ret.ok b/test/run-drun/ok/shared-object.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/shared-object.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-stub/ok/shared-object.ic-stub-run.ok b/test/run-drun/ok/shared-object.ic-stub-run.ok similarity index 58% rename from test/run-stub/ok/shared-object.ic-stub-run.ok rename to test/run-drun/ok/shared-object.ic-stub-run.ok index 54225bc8555..be9fb5d62c0 100644 --- a/test/run-stub/ok/shared-object.ic-stub-run.ok +++ b/test/run-drun/ok/shared-object.ic-stub-run.ok @@ -2,3 +2,5 @@ ← completed: canister-id = 0x0000000000000400 → install ← completed +→ update go(0x4449444c0000) +← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/simple-throw.drun-run.ok b/test/run-drun/ok/simple-throw.drun-run.ok new file mode 100644 index 00000000000..fc761d02e54 --- /dev/null +++ b/test/run-drun/ok/simple-throw.drun-run.ok @@ -0,0 +1,7 @@ +ingress(0) System +debug.print: 1 +debug.print: 2 +debug.print: 3 +debug.print: 4 +debug.print: done +ingress(1) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-stub/ok/simple-throw.run-ir.ok b/test/run-drun/ok/simple-throw.run-ir.ok similarity index 100% rename from test/run-stub/ok/simple-throw.run-ir.ok rename to test/run-drun/ok/simple-throw.run-ir.ok diff --git a/test/run-stub/ok/simple-throw.run-low.ok b/test/run-drun/ok/simple-throw.run-low.ok similarity index 100% rename from test/run-stub/ok/simple-throw.run-low.ok rename to test/run-drun/ok/simple-throw.run-low.ok diff --git a/test/run-stub/ok/simple-throw.run.ok b/test/run-drun/ok/simple-throw.run.ok similarity index 100% rename from test/run-stub/ok/simple-throw.run.ok rename to test/run-drun/ok/simple-throw.run.ok diff --git a/test/run-drun/ok/test_oneway.tc.ok b/test/run-drun/ok/test_oneway.tc.ok new file mode 100644 index 00000000000..447e9090f16 --- /dev/null +++ b/test/run-drun/ok/test_oneway.tc.ok @@ -0,0 +1 @@ +oneway.mo:67.1-67.7: type error, non-static expression in library or module diff --git a/test/run-drun/ok/test_oneway.tc.ret.ok b/test/run-drun/ok/test_oneway.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/test_oneway.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-drun/ok/the-answer.drun-run.ok b/test/run-drun/ok/the-answer.drun-run.ok deleted file mode 100644 index 3a0919de67b..00000000000 --- a/test/run-drun/ok/the-answer.drun-run.ok +++ /dev/null @@ -1,2 +0,0 @@ -debug.print: 42 -ingress(0) System diff --git a/test/run-drun/ok/the-answer.run-ir.ok b/test/run-drun/ok/the-answer.run-ir.ok deleted file mode 100644 index d81cc0710eb..00000000000 --- a/test/run-drun/ok/the-answer.run-ir.ok +++ /dev/null @@ -1 +0,0 @@ -42 diff --git a/test/run-drun/ok/the-answer.run-low.ok b/test/run-drun/ok/the-answer.run-low.ok deleted file mode 100644 index d81cc0710eb..00000000000 --- a/test/run-drun/ok/the-answer.run-low.ok +++ /dev/null @@ -1 +0,0 @@ -42 diff --git a/test/run-drun/ok/the-answer.run.ok b/test/run-drun/ok/the-answer.run.ok deleted file mode 100644 index d81cc0710eb..00000000000 --- a/test/run-drun/ok/the-answer.run.ok +++ /dev/null @@ -1 +0,0 @@ -42 diff --git a/test/run-drun/ok/transpose.comp.ok b/test/run-drun/ok/transpose.comp.ok new file mode 100644 index 00000000000..2c654224f3c --- /dev/null +++ b/test/run-drun/ok/transpose.comp.ok @@ -0,0 +1,2 @@ +transpose.mo:10.19-10.30: type error, calling a shared function not yet supported + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/transpose.comp.ret.ok b/test/run-drun/ok/transpose.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/transpose.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-stub/ok/transpose.ic-stub-run.ok b/test/run-drun/ok/transpose.ic-stub-run.ok similarity index 61% rename from test/run-stub/ok/transpose.ic-stub-run.ok rename to test/run-drun/ok/transpose.ic-stub-run.ok index c19a2a856f5..42f71fbb799 100644 --- a/test/run-stub/ok/transpose.ic-stub-run.ok +++ b/test/run-drun/ok/transpose.ic-stub-run.ok @@ -1,5 +1,7 @@ → create ← completed: canister-id = 0x0000000000000400 → install -All good ← completed +→ update go(0x4449444c0000) +All good +← completed: 0x4449444c0000 diff --git a/test/run-stub/ok/transpose.run-ir.ok b/test/run-drun/ok/transpose.run-ir.ok similarity index 100% rename from test/run-stub/ok/transpose.run-ir.ok rename to test/run-drun/ok/transpose.run-ir.ok diff --git a/test/run-stub/ok/transpose.run-low.ok b/test/run-drun/ok/transpose.run-low.ok similarity index 100% rename from test/run-stub/ok/transpose.run-low.ok rename to test/run-drun/ok/transpose.run-low.ok diff --git a/test/run-stub/ok/transpose.run.ok b/test/run-drun/ok/transpose.run.ok similarity index 100% rename from test/run-stub/ok/transpose.run.ok rename to test/run-drun/ok/transpose.run.ok diff --git a/test/run-drun/ok/type-lub.comp.ok b/test/run-drun/ok/type-lub.comp.ok new file mode 100644 index 00000000000..9f592a9df67 --- /dev/null +++ b/test/run-drun/ok/type-lub.comp.ok @@ -0,0 +1,2 @@ +type-lub.mo:57.12-57.20: type error, unsupported async block + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/type-lub.comp.ret.ok b/test/run-drun/ok/type-lub.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/type-lub.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-stub/ok/type-lub.ic-stub-run.ok b/test/run-drun/ok/type-lub.ic-stub-run.ok similarity index 100% rename from test/run-stub/ok/type-lub.ic-stub-run.ok rename to test/run-drun/ok/type-lub.ic-stub-run.ok diff --git a/test/run-stub/ok/unsupported.comp.ok b/test/run-drun/ok/unsupported.comp-stub.ok similarity index 78% rename from test/run-stub/ok/unsupported.comp.ok rename to test/run-drun/ok/unsupported.comp-stub.ok index ad1bf6587e8..9b69d1cae08 100644 --- a/test/run-stub/ok/unsupported.comp.ok +++ b/test/run-drun/ok/unsupported.comp-stub.ok @@ -2,9 +2,9 @@ unsupported.mo:4.5-4.41: type error, a shared function cannot be private (This is a limitation of the current version and flag -stub-system-api.) unsupported.mo:38.26-38.29: type error, a shared function is only allowed as a public field of an actor (This is a limitation of the current version and flag -stub-system-api.) -unsupported.mo:62.3-62.42: type error, actor classes with parameters are not supported; use an actor declaration instead +unsupported.mo:66.3-66.42: type error, actor classes with parameters are not supported; use an actor declaration instead (This is a limitation of the current version and flag -stub-system-api.) -unsupported.mo:80.34-80.37: type error, a shared function is only allowed as a public field of an actor +unsupported.mo:84.34-84.37: type error, a shared function is only allowed as a public field of an actor (This is a limitation of the current version and flag -stub-system-api.) -unsupported.mo:81.27-81.30: type error, a shared function is only allowed as a public field of an actor +unsupported.mo:85.27-85.30: type error, a shared function is only allowed as a public field of an actor (This is a limitation of the current version and flag -stub-system-api.) diff --git a/test/run-drun/ok/unsupported.comp-stub.ret.ok b/test/run-drun/ok/unsupported.comp-stub.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/unsupported.comp-stub.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-drun/ok/unsupported.comp.ok b/test/run-drun/ok/unsupported.comp.ok index a131d209526..a2844d732ce 100644 --- a/test/run-drun/ok/unsupported.comp.ok +++ b/test/run-drun/ok/unsupported.comp.ok @@ -14,9 +14,15 @@ unsupported.mo:41.10-41.18: type error, unsupported async block (This is a limitation of the current version.) unsupported.mo:62.3-62.35: type error, actor classes are not supported; use an actor declaration instead (This is a limitation of the current version.) -unsupported.mo:66.45-66.53: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program +unsupported.mo:66.3-66.42: type error, actor classes are not supported; use an actor declaration instead (This is a limitation of the current version.) -unsupported.mo:70.37-70.45: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program +unsupported.mo:70.45-70.53: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program (This is a limitation of the current version.) -unsupported.mo:76.34-76.37: type error, freestanding async expression not yet supported +unsupported.mo:74.37-74.45: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program + (This is a limitation of the current version.) +unsupported.mo:81.34-81.37: type error, freestanding async expression not yet supported + (This is a limitation of the current version.) +unsupported.mo:84.34-84.37: type error, a shared function is only allowed as a public field of an actor + (This is a limitation of the current version.) +unsupported.mo:85.27-85.30: type error, a shared function is only allowed as a public field of an actor (This is a limitation of the current version.) diff --git a/test/run-drun/oneway.mo b/test/run-drun/oneway.mo index acf67ab3a05..3aa615b9962 100644 --- a/test/run-drun/oneway.mo +++ b/test/run-drun/oneway.mo @@ -1,4 +1,4 @@ -actor Oneway { +actor a { // test that oneways can locally try/throw public func oneway() : () { ignore ( @@ -50,10 +50,18 @@ actor Oneway { } ); - // TODO test await and calls to shared functions -} -//CALL ingress oneway 0x4449444C0000 -//CALL ingress onewayAlt 0x4449444C0000 -//CALL ingress discard 0x4449444C0000 -//CALL ingress discardAlt 0x4449444C0000 + + public func go() = ignore async { + debugPrint("A"); + oneway(); + debugPrint("B"); + onewayAlt(); + debugPrint("C"); + discard(); + debugPrint("D"); + discardAlt(); + debugPrint("E"); + }; +}; +a.go(); //OR-CALL ingress go 0x4449444C0000 diff --git a/test/run-drun/oom.mo b/test/run-drun/oom.mo index 9689b0a9337..88e8197fc7d 100644 --- a/test/run-drun/oom.mo +++ b/test/run-drun/oom.mo @@ -1,9 +1,8 @@ -actor Oom { - public func doloop() { +actor a { + public func go() { ignore(Array_init<()>(1200*1024/4, ())); }; -} +}; -// on drun: -//CALL ingress doloop 0x4449444C0000 -//CALL ingress doloop 0x4449444C0000 +a.go(); //OR-CALL ingress go 0x4449444C0000 +a.go(); //OR-CALL ingress go 0x4449444C0000 diff --git a/test/run-drun/overflow.mo b/test/run-drun/overflow.mo new file mode 100644 index 00000000000..1f37251088f --- /dev/null +++ b/test/run-drun/overflow.mo @@ -0,0 +1,33 @@ +// We have theses tests in run-drun because we want to check that certain +// traps are happening, and a good way to test this is if a message gets +// aborted. + +actor a { + public func go() { + ignore(async { + ignore ((0-1):Int); + debugPrint("This is reachable."); + }); + ignore(async { + ignore ((1-1):Nat); + debugPrint("This is reachable."); + }); + ignore(async { + ignore ((0-1):Nat); + debugPrint("This should be unreachable."); + }); + ignore(async { + ignore ((18446744073709551615 + 0):Nat); + debugPrint("This is reachable."); + }); + ignore(async { + ignore ((9223372036854775806 + 9223372036854775806 + 1):Nat); + debugPrint("This is reachable."); + }); + ignore(async { + ignore ((9223372036854775806 + 9223372036854775806 + 2):Nat); + debugPrint("This is reachable."); + }); + } +}; +a.go(); //OR-CALL ingress go "DIDL\x00\x00" diff --git a/test/run-stub/pass-references.mo b/test/run-drun/pass-references.mo similarity index 88% rename from test/run-stub/pass-references.mo rename to test/run-drun/pass-references.mo index f58d3276d97..316e268fcac 100644 --- a/test/run-stub/pass-references.mo +++ b/test/run-drun/pass-references.mo @@ -17,6 +17,5 @@ actor a { pass_func(b.foo); pass_actor(b); }; - - go(); -} +}; +a.go(); //OR-CALL ingress go "DIDL\x00\x00" diff --git a/test/run-drun/query.mo b/test/run-drun/query.mo index 8541b9f7f3d..e6639a1ddce 100644 --- a/test/run-drun/query.mo +++ b/test/run-drun/query.mo @@ -27,3 +27,7 @@ actor { //CALL ingress printCounter 0x4449444C0000 //CALL query read 0x4449444C0000 //CALL ingress printCounter 0x4449444C0000 + +//SKIP run +//SKIP run-ir +//SKIP run-low diff --git a/test/run-stub/query2.mo b/test/run-drun/query2.mo similarity index 64% rename from test/run-stub/query2.mo rename to test/run-drun/query2.mo index 21a6de83b91..b0eead49084 100644 --- a/test/run-stub/query2.mo +++ b/test/run-drun/query2.mo @@ -18,7 +18,24 @@ actor counter = { return tmp; }; + public func go() = ignore async { + counter.inc(); + counter.inc(); + counter.inc(); + counter.printCounter(); + let c1 = await counter.get(); + assert c1 == 4; + let c2 = await counter.read(); + counter.printCounter(); + assert c2 == 4; + let c3 = await counter.read(); + counter.printCounter(); + debugPrint("The following fails in the intepreter, for lack of query semantics"); + assert c3 == 4; + }; }; +counter.go(); //OR-CALL ingress go "DIDL\x00\x00" + /* Disabled, while we don’t have first-class shared functions @@ -49,18 +66,3 @@ actor counter = { }; */ -async { - counter.inc(); - counter.inc(); - counter.inc(); - counter.printCounter(); - let c1 = await counter.get(); - assert c1 == 4; - let c2 = await counter.read(); - counter.printCounter(); - assert c2 == 4; - let c3 = await counter.read(); - counter.printCounter(); - debugPrint("The following fails in the intepreter, for lack of query semantics"); - assert c3 == 4; -}; diff --git a/test/run-stub/reference-params.mo b/test/run-drun/reference-params.mo similarity index 98% rename from test/run-stub/reference-params.mo rename to test/run-drun/reference-params.mo index b29fac1cab8..df186f35eb6 100644 --- a/test/run-stub/reference-params.mo +++ b/test/run-drun/reference-params.mo @@ -47,3 +47,4 @@ actor { }; e.send_to(b.say_hi); } +//SKIP comp diff --git a/test/run-drun/reject.mo b/test/run-drun/reject.mo index a2a7e7bdff9..3b353eddae7 100644 --- a/test/run-drun/reject.mo +++ b/test/run-drun/reject.mo @@ -27,3 +27,7 @@ actor { //CALL ingress reject1 0x4449444C0000 //CALL ingress reject2 0x4449444C0000 //CALL ingress reject3 0x4449444C0000 + +//SKIP run +//SKIP run-ir +//SKIP run-low diff --git a/test/run-drun/reversi.mo b/test/run-drun/reversi.mo index 95f7038f341..95704d2ef1d 100644 --- a/test/run-drun/reversi.mo +++ b/test/run-drun/reversi.mo @@ -272,3 +272,7 @@ actor { //CALL ingress board 0x4449444C0000 //CALL ingress place 0x4449444C00037c7c7c010402 //CALL ingress board 0x4449444C0000 + +//SKIP run +//SKIP run-ir +//SKIP run-low diff --git a/test/run-stub/rts-stats.mo b/test/run-drun/rts-stats.mo similarity index 100% rename from test/run-stub/rts-stats.mo rename to test/run-drun/rts-stats.mo diff --git a/test/run-drun/self-calls.mo b/test/run-drun/self-calls.mo deleted file mode 100644 index 0f139b5c157..00000000000 --- a/test/run-drun/self-calls.mo +++ /dev/null @@ -1,27 +0,0 @@ -actor X { - public func A() : async () { - debugPrint("A called"); - }; - - - public func B(x : Int) : async Int { - debugPrint("B called"); - x - }; - - public func C(x : Int, y: Bool) : async (Int,Bool) { - debugPrint("C called"); - (x,y); - }; - - public func test() : async () { - debugPrint("test1"); - let () = await X.A(); - debugPrint("test2"); - let 1 = await X.B(1); - debugPrint("test3"); - let (1,true) = await X.C(1,true); - debugPrint("test4"); - }; -} -//CALL ingress test 0x4449444C0000 diff --git a/test/run-drun/selftail.mo b/test/run-drun/selftail.mo index f732b3f9ec2..040ed7fa744 100644 --- a/test/run-drun/selftail.mo +++ b/test/run-drun/selftail.mo @@ -17,7 +17,6 @@ debugPrint "ok1"; assert(10000 == f (true, 10000, 0)); debugPrint "ok2"; -// check recursion overflows for large n (on drun only) -// disabled as overflowing or not appears to be non-deterministic on V8 -//assert(10000 == f (false, 10000, 0)); -//debugPrint "unreachable on drun"; +// check recursion overflows for large n (overflows on drun only) +assert(10000 == f (false, 10000, 0)); +debugPrint "ok3 (unreachable on drun)"; diff --git a/test/run-stub/shared-object.mo b/test/run-drun/shared-object.mo similarity index 89% rename from test/run-stub/shared-object.mo rename to test/run-drun/shared-object.mo index 32a02daf507..db4e1722e68 100644 --- a/test/run-stub/shared-object.mo +++ b/test/run-drun/shared-object.mo @@ -15,6 +15,5 @@ actor a { let b = await (baz foo); assert (b == 42); }; - - go(); -} +}; +a.go(); //OR-CALL ingress go "DIDL\x00\x00" diff --git a/test/run-stub/simple-throw.mo b/test/run-drun/simple-throw.mo similarity index 90% rename from test/run-stub/simple-throw.mo rename to test/run-drun/simple-throw.mo index 6b1cd576dab..740bcc16beb 100644 --- a/test/run-stub/simple-throw.mo +++ b/test/run-drun/simple-throw.mo @@ -1,6 +1,4 @@ // This file only exercises local throws that don't cross function boundaries. -// In principle, it should run on all targets. - actor a { public func go() = ignore async { debugPrint "1"; @@ -18,5 +16,5 @@ actor a { debugPrint "4"; debugPrint "done"; }; - go(); }; +a.go(); //OR-CALL ingress go "DIDL\x00\x00" diff --git a/test/run-drun/test_oneway.mo b/test/run-drun/test_oneway.mo index cd2aacd6ae7..0ff6ddfc072 100644 --- a/test/run-drun/test_oneway.mo +++ b/test/run-drun/test_oneway.mo @@ -1,16 +1,3 @@ import M "oneway.mo"; -ignore (async { - debugPrint("A"); - M.Oneway.oneway(); - debugPrint("B"); - M.Oneway.onewayAlt(); - debugPrint("C"); - M.Oneway.discard(); - debugPrint("D"); - M.Oneway.discardAlt(); - debugPrint("E"); -} -); - -//SKIP comp \ No newline at end of file +//SKIP comp diff --git a/test/run-drun/the-answer.mo b/test/run-drun/the-answer.mo deleted file mode 100644 index 3f4e1e6c14c..00000000000 --- a/test/run-drun/the-answer.mo +++ /dev/null @@ -1 +0,0 @@ -debugPrintNat(42); diff --git a/test/run-stub/transpose.mo b/test/run-drun/transpose.mo similarity index 92% rename from test/run-stub/transpose.mo rename to test/run-drun/transpose.mo index c0335d9a275..9fed4a2aa21 100644 --- a/test/run-stub/transpose.mo +++ b/test/run-drun/transpose.mo @@ -15,4 +15,4 @@ actor a { debugPrint("All good"); } }; -a.go(); +a.go(); //OR-CALL ingress go "DIDL\x00\x00" diff --git a/test/run-stub/type-lub.mo b/test/run-drun/type-lub.mo similarity index 100% rename from test/run-stub/type-lub.mo rename to test/run-drun/type-lub.mo diff --git a/test/run-drun/unsupported.mo b/test/run-drun/unsupported.mo index b31f825c639..3a402421999 100644 --- a/test/run-drun/unsupported.mo +++ b/test/run-drun/unsupported.mo @@ -62,6 +62,10 @@ func local_spawn() { actor class BadActorClass () { }; // no actor classes }; +{ + actor class BadActorClass (x : Int) { }; // no actor classes +}; + { let bad_non_top_actor : actor {} = if true actor {} else actor {}; }; @@ -73,4 +77,9 @@ func local_spawn() { actor BadSecondActor { }; -func implicit_async() : async () { }; // async functions not supported +// async functions not supported (inference mode) +func implicit_async() : async () { }; + +// anonymous shared functions not supported (inference and checking mode) +let _ = shared func() : async () { }; +(shared func() : async () { }) : shared () -> async (); diff --git a/test/run-stub/AST-66.mo b/test/run-stub/AST-66.mo deleted file mode 100644 index f54ae2fb10e..00000000000 --- a/test/run-stub/AST-66.mo +++ /dev/null @@ -1,13 +0,0 @@ -// test cps conversion of async blocks with type decs - -let _ = async{ - type T = Null; - await { async (null:T) }; -}; - -let _ = async{ - type T = U; - let _ = await { async (null:T) }; - type U = Null; - await { async (null:T) }; -}; diff --git a/test/run-stub/Makefile b/test/run-stub/Makefile deleted file mode 100644 index 72bda5cb77b..00000000000 --- a/test/run-stub/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -RUNFLAGS = -3 - -all: - ../run.sh $(RUNFLAGS) *.mo - -accept: - ../run.sh $(RUNFLAGS) -a *.mo - -clean: - rm -rf _out - -include ../*.mk diff --git a/test/run-stub/async-any.mo b/test/run-stub/async-any.mo deleted file mode 100644 index 7e405dd4ecf..00000000000 --- a/test/run-stub/async-any.mo +++ /dev/null @@ -1 +0,0 @@ -async { ():Any }; diff --git a/test/run-stub/async-calls.mo b/test/run-stub/async-calls.mo deleted file mode 100644 index 208cd0964d2..00000000000 --- a/test/run-stub/async-calls.mo +++ /dev/null @@ -1,47 +0,0 @@ -/* This tests checks if messages to actors are really asynchronous, and complete - before delivery. -*/ - -let sync_object = object self { - var x : Bool = false; - - public func bump() { assert (x == false); x := true; assert (x == true); }; - - public func test() { assert (x == false); self.bump(); assert (x == true); }; -}; - -sync_object.test(); - -let async_actor = actor self { - var x : Bool = false; - - public func bump() { assert (x == false); x := true; assert (x == true); }; - - public func test() { assert (x == false); self.bump(); assert (x == false); }; -}; - -async_actor.test(); - -let async2_actor = actor self { - var x : Bool = false; - - public func bump() { assert (x == false); x := true; assert (x == true); }; - - public func test() { assert (x == false); bump(); assert (x == false); is_true(); }; - - public func is_true() { assert (x == true); }; -}; - -async2_actor.test(); - -let async_rec_actor = actor self { - var x : Bool = false; - - public func test(b : Bool) { - if (b) { assert (x == false); x := true; assert (x == true); } - else { assert (x == false); test(false); assert (x == false); is_true(); } - }; - public func is_true() { assert (x == true); }; -}; - -async_rec_actor.test(true); diff --git a/test/run-stub/async-free-var.mo b/test/run-stub/async-free-var.mo deleted file mode 100644 index 7edddece50a..00000000000 --- a/test/run-stub/async-free-var.mo +++ /dev/null @@ -1,15 +0,0 @@ -ignore async { - var x = "A"; - debugPrint x; - let a = async { - debugPrint "Now in async"; - debugPrint x; - x := "B"; - debugPrint x; - }; - debugPrint x; - x := "C"; - debugPrint x; - await a; - debugPrint x; -}; diff --git a/test/run-stub/async-loop-while.mo b/test/run-stub/async-loop-while.mo deleted file mode 100644 index 9e38145413b..00000000000 --- a/test/run-stub/async-loop-while.mo +++ /dev/null @@ -1,59 +0,0 @@ -let _ = -async { - -{ var i = 0; - var j = 0; - loop { - debugPrintNat(j); - assert(j == i); - i += 1; - j += 1; - } while (i < 3); - assert(i == 3); -}; - - -{ - var i = 0; - var j = 0; - loop { - debugPrintNat(j); - assert(j == i); - i += 1; - j += 1; - } while (await async (i < 3)); - assert(i == 3); -}; - -{ - var i = 0; - var j = 0; - loop { - debugPrintNat(j); - assert(j == i); - await (async (i += 1)); - j += 1; - } while (i < 3); - assert(i == 3); -}; - -{ - var i = 0; - var j = 0; - label l - loop { - if (j > 2) { - break l; - assert(false); - }; - debugPrintNat(j); - assert(j == i); - await (async (i += 1)); - j += 1; - continue l; - assert(false); - } while (true); - assert(i == 3); -}; - -}; diff --git a/test/run-stub/async-loop.mo b/test/run-stub/async-loop.mo deleted file mode 100644 index bb0d06a971d..00000000000 --- a/test/run-stub/async-loop.mo +++ /dev/null @@ -1,72 +0,0 @@ -let _ = -async { - -{ var i = 0; - var j = 0; - label l - loop { - debugPrintNat(j); - assert(j == i); - i += 1; - j += 1; - if (j == 3) break l else continue l; - } ; - assert(i == 3); -}; - - -{ - var i = 0; - var j = 0; - label l - loop { - debugPrintNat(j); - assert(j == i); - i += 1; - j += 1; - if (await async (j == 3)) break l else continue l; - assert(false); - }; - assert(i == 3); -}; - -{ - var i = 0; - var j = 0; - label l - loop { - debugPrintNat(j); - assert(j == i); - await (async (i += 1)); - j += 1; - if (j == 3) break l else continue l; - assert(false); - }; - assert(i == 3); -}; - -{ - var i = 0; - var j = 0; - label l - loop { - if (j > 2) { - break l; - assert(false); - }; - debugPrintNat(j); - assert(j == i); - await (async (i += 1)); - j += 1; - continue l; - assert(false); - }; - assert(i == 3); -}; - -}; - - - - - diff --git a/test/run-stub/async-new-obj.mo b/test/run-stub/async-new-obj.mo deleted file mode 100644 index 68015a6f376..00000000000 --- a/test/run-stub/async-new-obj.mo +++ /dev/null @@ -1,59 +0,0 @@ -/* Test asynchronous construction of an object */ - -let a = async { - let o = object { - let a = "aa"; - let b = "ab"; - public func get_a() : Text { a }; - public func get_b() : Text { b }; - }; - let (a, b) = (o.get_a(), o.get_b()); - debugPrint (a#b); -}; - -let b = async { - let o = object { - let a = await (async "ba") ; - let b = "bb"; - public func get_a() : Text { a }; - public func get_b() : Text { b }; - }; - let (a, b) = (o.get_a(), o.get_b()); - debugPrint (a#b); -}; - -let c = async { - let o = object { - let a = await (async "ca") ; - let b = await (async "cb"); - public func get_a() : Text { a }; - public func get_b() : Text { b }; - }; - let (a, b) = (o.get_a(), o.get_b()); - debugPrint (a#b); -}; - -let d = async { - let o = object { - let a = "da"; - let b = await (async "db"); - public func get_a() : Text { a }; - public func get_b() : Text { b }; - }; - let (a, b) = (o.get_a(), o.get_b()); - debugPrint (a#b); -}; - -let e = async { - let o = object this { - let a = "ea"; - let b = await (async "eb"); - public func get_a() : Text { a }; - public func get_b() : Text { b }; - public func get_ab() : (Text, Text) { - (this.get_a(), this.get_b()); - }; - }; - let (a, b) = o.get_ab(); - debugPrint (a#b); -}; diff --git a/test/run-stub/async-obj-mut.mo b/test/run-stub/async-obj-mut.mo deleted file mode 100644 index eeca3235c2d..00000000000 --- a/test/run-stub/async-obj-mut.mo +++ /dev/null @@ -1,18 +0,0 @@ -let _ = async { - let o = object { - public var x = await { async { 1 } }; - let a = debugPrintNat(x); - // private b = (x := await { async (x + 1) }); - let b = (x := x + 1); - let c = debugPrintNat(x); - public func foo() = { x := x + 1 }; - let e = foo(); - let f = debugPrintNat(x); - }; - debugPrint("done creating\n"); - debugPrintNat(o.x); - o.x := o.x + 1; - debugPrintNat(o.x); - o.foo(); - debugPrintNat(o.x); -} diff --git a/test/run-stub/async-while.mo b/test/run-stub/async-while.mo deleted file mode 100644 index 816a85a723d..00000000000 --- a/test/run-stub/async-while.mo +++ /dev/null @@ -1,59 +0,0 @@ -let _ = -async { - -{ var i = 0; - var j = 0; - while (j <= 2) { - debugPrintNat(j); - assert(j == i); - i += 1; - j += 1; - }; - assert(i == 3); -}; - - -{ - var i = 0; - var j = 0; - while (await async (j <= 2)) { - debugPrintNat(j); - assert(j == i); - i += 1; - j += 1; - }; - assert(i == 3); -}; - -{ - var i = 0; - var j = 0; - while (j <= 2) { - debugPrintNat(j); - assert(j == i); - await (async (i += 1)); - j += 1; - }; - assert(i == 3); -}; - -{ - var i = 0; - var j = 0; - label l - while (true) { - if (j > 2) { - break l; - assert(false); - }; - debugPrintNat(j); - assert(j == i); - await (async (i += 1)); - j += 1; - continue l; - assert(false); - }; - assert(i == 3); -}; - -}; diff --git a/test/run-stub/await.mo b/test/run-stub/await.mo deleted file mode 100644 index e0d76b87158..00000000000 --- a/test/run-stub/await.mo +++ /dev/null @@ -1,66 +0,0 @@ -var cnt : Nat = 0; - -func f(i:Nat) : async Nat { - debugPrint ("cnt: " # debug_show cnt # " i: " # debug_show i); - cnt += 1; - cnt; -}; - -debugPrint "a"; - -let a = async await f(0); - -debugPrint "b"; - -let b = async { await f(1); }; - -debugPrint "c"; - -let c = async { - let _ = await f(2); - await f(3); -}; - -debugPrint "d"; - -let d = (async { return await f(4); }) : async Int; - -debugPrint "e"; - -let e = async { - var i = 5; - debugPrint "e-while"; - while (i < 8) { - let _ = await f(i); - i += 1; - }; - debugPrint "e-exit"; -}; - -debugPrint "g"; - -let g = async { - var i = 10; - debugPrint "g-label"; - label lp - while (true) { - if (i < 13) { - debugPrint "."; - let _ = await f(i); - i += 1; - continue lp; - } else {}; - break lp; - }; - debugPrint "g-exit"; -}; - -debugPrint "holy"; - -func p():async (Text,Text) { ("fst","snd"); }; -let h = async { - let (a,b) = ("a","b"); /* await p(a,b);*/ - debugPrint a; - debugPrint b; -}; - diff --git a/test/run-stub/block.mo b/test/run-stub/block.mo deleted file mode 100644 index 6015320cfa0..00000000000 --- a/test/run-stub/block.mo +++ /dev/null @@ -1,35 +0,0 @@ -let a = async { - let (a,b) = ("a1","b1"); - debugPrint a; - debugPrint b; -}; - -let b = async { - let (a,b) = await (async ("a2","b2")); - debugPrint a; - debugPrint b; -}; - -let c = async { - func f(a:Text,b:Text):(){ debugPrint a; debugPrint b;}; - let (a,b) = await (async ("a3","b3")); - let _ = f(a,b); -}; - -let d = async { - var f = 1; - debugPrintNat (f); - let (a,b) = await (async ("a4","b4")); - f += 2; - debugPrintNat (f); -}; - - -let e = async { - var f = await (async 5); - debugPrintNat (f); - let (a,b) = await (async ("a5","b5")); - f += 1; - debugPrintNat (f); -}; - diff --git a/test/run-stub/closure-params.mo b/test/run-stub/closure-params.mo deleted file mode 100644 index 1048ea22ed5..00000000000 --- a/test/run-stub/closure-params.mo +++ /dev/null @@ -1,24 +0,0 @@ -let a = actor { - var c = 0; - public func incn(n : Nat) : () { - c += n; - debugPrintNat(c); - }; - public func readCounter(f : shared Nat -> ()) : () { - f(c); - }; - - public func printNat(n: Nat) { debugPrintNat n }; - - incn(1); - readCounter(printNat); - incn(2); - readCounter(printNat); - incn(3); - readCounter(printNat); - incn(4); - readCounter(printNat); - incn(5); - readCounter(printNat); -}; - diff --git a/test/run-stub/counter.mo b/test/run-stub/counter.mo deleted file mode 100644 index 3796efe4bd2..00000000000 --- a/test/run-stub/counter.mo +++ /dev/null @@ -1,18 +0,0 @@ -actor a { - var c = 1; - public func inc() { - c += 1; - debugPrintNat c; - }; - public func printCounter () { - debugPrintNat c; - }; - public func get() : async Nat { - return c - }; -} -//CALL ingress inc 0x4449444C0000 -//CALL ingress inc 0x4449444C0000 -//CALL ingress inc 0x4449444C0000 -//CALL ingress printCounter 0x4449444C0000 -//CALL ingress get 0x4449444C0000 diff --git a/test/run-stub/counter2.mo b/test/run-stub/counter2.mo deleted file mode 100644 index 3692a2279fc..00000000000 --- a/test/run-stub/counter2.mo +++ /dev/null @@ -1,25 +0,0 @@ -let a = actor { - var c = 1; - public func inc() { - c += 1; - debugPrintNat c; - }; - public func printCounter () { - debugPrintNat c; - } -}; - -a.inc(); -a.inc(); -a.inc(); -a.printCounter(); - -func test() { - var i : Int = 10; - while (i > 0) { - a.inc(); - i -= 1; - } -}; - -let _ = test(); diff --git a/test/run-stub/empty-actor.mo b/test/run-stub/empty-actor.mo deleted file mode 100644 index e059e8d76a7..00000000000 --- a/test/run-stub/empty-actor.mo +++ /dev/null @@ -1 +0,0 @@ -let _ = actor {}; diff --git a/test/run-stub/for-await.mo b/test/run-stub/for-await.mo deleted file mode 100644 index c0a7a08c835..00000000000 --- a/test/run-stub/for-await.mo +++ /dev/null @@ -1,15 +0,0 @@ -let _ = -async { - -{ - var i = 0; - i := 0; - for (j in range(0, 10)) { - debugPrintNat(j); - assert(j == i); - await (async (i += 1)); - }; - assert(i == 11); -}; - -}; diff --git a/test/run-stub/hello-world-return.mo b/test/run-stub/hello-world-return.mo deleted file mode 100644 index e1a4ca1644d..00000000000 --- a/test/run-stub/hello-world-return.mo +++ /dev/null @@ -1,11 +0,0 @@ -actor { - public query func hello(who : Text) : async Text { - "Hello " # who # "!"; - }; - public query func hello2(who : Text) : async Text { - return ("Hello " # who # "!"); - } -} - -//CALL query hello "DIDL\x00\x01\x71\x05World" -//CALL query hello2 "DIDL\x00\x01\x71\x05World" diff --git a/test/run-stub/ic-calls.mo b/test/run-stub/ic-calls.mo deleted file mode 100644 index 9f15511141e..00000000000 --- a/test/run-stub/ic-calls.mo +++ /dev/null @@ -1,27 +0,0 @@ -actor X { - - public func A() : () { - debugPrint("A"); - }; - - - public func B(x : Int) : async Int { - debugPrint("B"); - x - }; - - public func C(x : Int, y: Bool) : async (Int,Bool) { - debugPrint("C"); - (x,y); - }; - - public func test() = ignore async { - A(); - let 1 = await B(1); - let (1,true) = await C(1,true); - debugPrint("test"); - }; - -}; -X.test(); - diff --git a/test/run-stub/idl-any.mo b/test/run-stub/idl-any.mo deleted file mode 100644 index b2c5713be24..00000000000 --- a/test/run-stub/idl-any.mo +++ /dev/null @@ -1,39 +0,0 @@ -// This tests checks that the IDL decoder properly -// zooms past the any argument and finds the beginning of the string -actor { - public func any(_ : Any, x : Text) : async () { - debugPrint ("ok: " # x); - }; -} - -// Primitive values: -//CALL ingress any 0x4449444C00027f7103466F6F -//CALL ingress any 0x4449444C00027e710103466F6F -//CALL ingress any 0x4449444C00027d718080800803466F6F -//CALL ingress any 0x4449444C00027c718080800803466F6F -//CALL ingress any 0x4449444C00027b71AB03466F6F -//CALL ingress any 0x4449444C00027a71ABCD03466F6F -//CALL ingress any 0x4449444C00027971DEADBEEF03466F6F -//CALL ingress any 0x4449444C00027871DEADBEEFCAFFEE6603466F6F -//CALL ingress any 0x4449444C00027771AB03466F6F -//CALL ingress any 0x4449444C00027671ABCD03466F6F -//CALL ingress any 0x4449444C00027571DEADBEEF03466F6F -//CALL ingress any 0x4449444C00027471DEADBEEFCAFFEE6603466F6F -//CALL ingress any 0x4449444C00027371DEADBEEF03466F6F -//CALL ingress any 0x4449444C00027271DEADBEEFCAFFEE6603466F6F -//CALL ingress any 0x4449444C0002717103466F6F03466F6F -//CALL ingress any 0x4449444C0002707103466F6F - -// Composite values: -//CALL ingress any 0x4449444C016e710200710003466F6F -//CALL ingress any 0x4449444C016e710200710103466F6F03466F6F -//CALL ingress any 0x4449444C016d710200710003466F6F -//CALL ingress any 0x4449444C016d710200710103466F6F03466F6F -//CALL ingress any 0x4449444C016d71020071020003466F6F03466F6F -//CALL ingress any 0x4449444C016c0002007103466F6F -//CALL ingress any 0x4449444C016c01800175020071DEADBEEF03466F6F -//CALL ingress any 0x4449444C016c02007180017502007101A0DEADBEEF03466F6F -//CALL ingress any 0x4449444C016b0180017502007100DEADBEEF03466F6F -//CALL ingress any 0x4449444C016b0200718001750200710001A003466F6F -//CALL ingress any 0x4449444C016b02007180017502007101DEADBEEF03466F6F -//CALL ingress any 0x4449444C016602ABCD0200710400DEADBEEF03466F6F diff --git a/test/run-stub/idl-bad.mo b/test/run-stub/idl-bad.mo deleted file mode 100644 index 2b5b04be855..00000000000 --- a/test/run-stub/idl-bad.mo +++ /dev/null @@ -1,7 +0,0 @@ -actor { - public query func foo() : async () { - }; -} - -//CALL query foo "NOTDIDL" - diff --git a/test/run-stub/idl-field-escape.mo b/test/run-stub/idl-field-escape.mo deleted file mode 100644 index f84ca1556ec..00000000000 --- a/test/run-stub/idl-field-escape.mo +++ /dev/null @@ -1,27 +0,0 @@ -// This test checks that the IDL encoder/decode implements -// the field escape logic -actor { - type R = { - _0_ : Int; - _1_ : Nat; - async_ : Text - }; - - public func out() : async R { - { _0_ = 0xFFFF; - _1_ = 0x1000; - async_ = "XXX" - } - }; - - public func foo1() : async {foo_ : ()} { { foo_ = () } }; - public func foo2() : async {foo : ()} { { foo = () } }; - - public func input(r : R) : async () { - }; -} - -//CALL ingress foo1 0x4449444C0000 -//CALL ingress foo2 0x4449444C0000 -//CALL ingress out 0x4449444C0000 -//CALL ingress input 0x4449444c016c03007c017dbcfef7b102710100ffff03802003585858 diff --git a/test/run-stub/idl-func.mo b/test/run-stub/idl-func.mo deleted file mode 100644 index 592c306ddf1..00000000000 --- a/test/run-stub/idl-func.mo +++ /dev/null @@ -1,13 +0,0 @@ -type Func = shared Int -> async Func; - -actor { - public query func fun() : async ?Func { - null - }; - public query func fun2(arg : ?Func) : async () { - }; -} - - -//CALL query fun 0x4449444C0000 -//CALL query fun2 0x4449444c026e016a017c0000010000 diff --git a/test/run-stub/idl-nary.mo b/test/run-stub/idl-nary.mo deleted file mode 100644 index 25284781203..00000000000 --- a/test/run-stub/idl-nary.mo +++ /dev/null @@ -1,53 +0,0 @@ -actor { - public func two(x:Text, y:Text) : async (Text, Text) { - (x, y) - }; - - public func three(x:Text, y:Text, z: Text) : async (Text, Text, Text) { - (x, y, z) - }; - - public func four(x:Text, y:Text, z: Text, w: Text) : async (Text, Text, Text, Text) { - (x, y, z, w) - }; - - public func mkRecord() : async ((Text, Text, Text, Text)) { - ("One", "Two", "Three", "Four") - }; - - public func unary1((x:Text, y:Text, z: Text, w: Text)) : async ((Text, Text, Text, Text)) { - (x, y, z, w) - }; - - public func unary2(xyzw : (Text, Text, Text, Text)) : async ((Text, Text, Text, Text)) { - xyzw - }; - - public func unary3(xyzw : (Text, Text, Text, Text)) : async ((Text, Text, Text, Text)) { - xyzw - }; - - type T = (Text, Text, Text, Text); - public func unary4(xyzw : (Text, Text, Text, Text)) : async T { - xyzw - } - - -} - -//CALL ingress two "DIDL\x00\x02\x71\x71\x03One\x03Two" -//CALL ingress three "DIDL\x00\x03\x71\x71\x71\x03One\x03Two\x05Three" -//CALL ingress four "DIDL\x00\x04\x71\x71\x71\x71\x03One\x03Two\x05Three\x04Four" -//CALL ingress mkRecord "DIDL\x00\x00" -//CALL ingress unary1 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 -//CALL ingress unary2 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 -//CALL ingress unary3 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 -//CALL ingress unary4 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 - - -// too few arguments -//CALL ingress three "DIDL\x00\x02\x71\x71\x03One\x03Two" -// extra bytes (bad) -//CALL ingress three "DIDL\x00\x03\x71\x71\x71\x03One\x03Two\x05ThreeEXTRABYTES" -// extra arguments (ok) -//CALL ingress four "DIDL\x00\x05\x71\x71\x71\x71\x71\x03One\x03Two\x05Three\x04Four\x04Five" diff --git a/test/run-stub/idl-nat-int.mo b/test/run-stub/idl-nat-int.mo deleted file mode 100644 index 7c971b93ff7..00000000000 --- a/test/run-stub/idl-nat-int.mo +++ /dev/null @@ -1,18 +0,0 @@ -actor { - public query func absolute(x:Int) : async Nat { - abs x - }; - public query func absolutes(xs:[Int]) : async [Nat] { - Array_tabulate(xs.len(), func (i:Int) : Nat = abs(xs[i])) - }; -} - -// with Nat -//CALL query absolute "DIDL\x00\x01\x7d\x2a" -// with Int -//CALL query absolute "DIDL\x00\x01\x7c\x56" - -// with Nats -//CALL query absolutes "DIDL\x01\x6d\x7d\x01\x00\x02\x2a\x19" -// with Ints -//CALL query absolutes "DIDL\x01\x6d\x7c\x01\x00\x02\x56\x19" diff --git a/test/run-stub/idl-option.mo b/test/run-stub/idl-option.mo deleted file mode 100644 index 887644e7584..00000000000 --- a/test/run-stub/idl-option.mo +++ /dev/null @@ -1,14 +0,0 @@ -// This test checks that the IDL decoder can -// do the subtyping from null to option -actor { - public func any(o : ?Text) : async () { - switch o { - case null debugPrint ("ok: null"); - case (?x) debugPrint ("ok: " # x); - } - }; -} - -//CALL ingress any 0x4449444C00017f -//CALL ingress any 0x4449444C016e71010000 -//CALL ingress any 0x4449444C016e7101000103466F6F diff --git a/test/run-stub/idl-pair.mo b/test/run-stub/idl-pair.mo deleted file mode 100644 index 57a487bcd64..00000000000 --- a/test/run-stub/idl-pair.mo +++ /dev/null @@ -1,8 +0,0 @@ -type Pair = (Int,Int); -actor { - public func len2(x:Text, y:Text) : async Pair { - (x.len(), y.len()) - } -} - -//CALL ingress len2 "DIDL\x00\x02\x71\x71\x02Hi\x05World" diff --git a/test/run-stub/idl-record.mo b/test/run-stub/idl-record.mo deleted file mode 100644 index 576609b3aa0..00000000000 --- a/test/run-stub/idl-record.mo +++ /dev/null @@ -1,34 +0,0 @@ -// This test checks that the IDL decoder can -// do the subtyping from received many-field record -// to a double-field one (field names are in hash order) -actor { - public func pair(o : (Text, Int)) : async () { - switch o { - case (content, num) debugPrint ("ok: " # debug_show num); - } - }; - public func record(o : {content: Text; value : Int}) : async () { - switch o { - case {content} debugPrint ("ok: " # content); - } - }; - public func record1(o : {value : Int; byte : Int8}) : async () { - switch o { - case {byte} debugPrint ("ok: " # debug_show byte); - } - }; - public func record2(o : {content: Text; value : Int}, follower : Int8) : async Int8 { - switch o { - case {content} { debugPrint ("ok: " # " " # content # " " # debug_show follower); follower }; - } - }; -} - -//CALL ingress pair 0x4449444C016C020071017C010004486579212A -//CALL ingress record 0x4449444C016C02b99adecb0171f1fee18d037C010004486579212A -// SKIPPED -// CALL ingress record1 0x4449444C016C0388be8c890477b99adecb0171f1fee18d037C010004486579212A19 -// needs to jump over redundant `content` field -//CALL ingress record1 0x4449444C016C03b99adecb0171f1fee18d037C88be8c890477010004486579212A19 -// needs to jump over redundant trailing `byte` field -//CALL ingress record2 0x4449444C016C03b99adecb0171f1fee18d037C88be8c89047702007704486579212A1819 diff --git a/test/run-stub/idl-tuple.mo b/test/run-stub/idl-tuple.mo deleted file mode 100644 index 0f86f4a9a06..00000000000 --- a/test/run-stub/idl-tuple.mo +++ /dev/null @@ -1,17 +0,0 @@ -actor { - // top-level tuple - public query func len2(x:Text, y:Text) : async (Int,Int) { - (x.len(), y.len()) - }; - // a pair embedded in top-level tuple - public query func len3((x:Text, i:Int32), y:Text) : async (Int,Int,Int) { - (x.len(), y.len(), int32ToInt i) - } -} - -//CALL query len2 "DIDL\x00\x02\x71\x71\x02Hi\x05World" -//CALL query len3 0x4449444c016c02007101750200710548656c6c6f0102030405576f726c64 -// testing redundant first tuple member (repeated hash with different type), currently ignored, it is although invalid IDL data -//CALL query len3 0x4449444c016c030071007601750200710548656c6c6fdead0102030405576f726c64 -// testing redundant third tuple member, gets ignored -//CALL query len3 0x4449444c016c030071017502760200710548656c6c6f01020304dead05576f726c64 diff --git a/test/run-stub/idl-unit.mo b/test/run-stub/idl-unit.mo deleted file mode 100644 index 09e6f9b85ec..00000000000 --- a/test/run-stub/idl-unit.mo +++ /dev/null @@ -1,7 +0,0 @@ -actor { - public query func unit_id() : async () { - () - } -} - -//CALL query unit_id "DIDL\x00\x00" diff --git a/test/run-stub/idl-variant.mo b/test/run-stub/idl-variant.mo deleted file mode 100644 index 594cf29f99f..00000000000 --- a/test/run-stub/idl-variant.mo +++ /dev/null @@ -1,16 +0,0 @@ -type Either = { #left: Word32; #right: Char; #fix: Either }; - -func to_left(e : Either) : Either - = switch e { - case (#right n) #left (charToWord32 n); - case (#fix t) #fix (to_left t); - case other other - }; - -actor { - public query func numify(t: Either) : async Either { - to_left t - } -} - -//CALL query numify 0x4449444c016b03d583b702008790c0bd0479dc9790cb0e790100000220000000 diff --git a/test/run-stub/idl-vector.mo b/test/run-stub/idl-vector.mo deleted file mode 100644 index 48391f2a241..00000000000 --- a/test/run-stub/idl-vector.mo +++ /dev/null @@ -1,13 +0,0 @@ -type Rose = [Rose]; -type MayRose = ?[MayRose]; - -func may(r : Rose) : MayRose = ?Array_tabulate(r.len(), func (i : Nat) = may(r[i])); - -actor { - public query func rose(r : Rose) : async MayRose { - may r - } -} - -// [[], [[], [[], [],], [], []], []] -//CALL query rose 0x4449444c016d00010003000400020000000000 diff --git a/test/run-stub/interleave.mo b/test/run-stub/interleave.mo deleted file mode 100644 index 65627075f54..00000000000 --- a/test/run-stub/interleave.mo +++ /dev/null @@ -1,37 +0,0 @@ -var cnt : Nat = 0; - -func f(m: Text, i:Nat) : async Nat { - debugPrint (m # " cnt: " # debug_show cnt # " i: " # debug_show i); - cnt += 1; - cnt; -}; - - - -let e = async { - var i = 5; - debugPrint " e-while\n"; - while (i < 10) { - let _ = await f(" e",i); - i += 1; - }; - debugPrint " e-exit\n"; -}; - -debugPrint "g"; - -let g = async { - var i = 10; - debugPrint "g-label\n"; - label lp - while (true) { - if (i < 15) { - let _ = await f("g",i); - i += 1; - continue lp; - } else {}; - break lp; - }; - debugPrint "g-exit\n"; -}; - diff --git a/test/run-stub/multiple-actors.mo b/test/run-stub/multiple-actors.mo deleted file mode 100644 index 33e4b920714..00000000000 --- a/test/run-stub/multiple-actors.mo +++ /dev/null @@ -1,7 +0,0 @@ -actor a { }; - -actor b { }; - - - - diff --git a/test/run-stub/nary-async.mo b/test/run-stub/nary-async.mo deleted file mode 100644 index 649f7f8732d..00000000000 --- a/test/run-stub/nary-async.mo +++ /dev/null @@ -1,103 +0,0 @@ -/* test n-ary async/await */ - -/* n-ary args */ -actor { - public func f0_0() : async () {}; - { - let t = "0_0"; - ignore async { - await f0_0(); - debugPrint t; - }; - }; - - public func f1_0(x:Int) : async () { - assert(x == 1); - }; - { - let t = "1_0"; - ignore async { - await f1_0(1); - debugPrint t; - }; - }; - - public func f2_0(x:Int,y:Bool) : async () { - assert(x==1); - assert(y==true); - }; - { - let t = "2_0"; - ignore async { - await f2_0(1,true); - debugPrint t; - }; - }; - - public func f3_0(x:Int,y:Bool,z:Text) : async () { - assert(x == 1); - assert(y == true); - assert(z == "a"); - }; - { - let t = "3_0"; - ignore async { - await f3_0(1,true,"a"); - debugPrint t; - }; - }; - - /* n-ary returns */ - - public func g0_0() : async () {}; - { - let t = "0_0"; - ignore async { - await g0_0(); - debugPrint t; - }; - }; - - public func g0_1() : async Int { - 1; - }; - { - let t = "0_1"; - ignore async { - let x = await g0_1(); - assert(x == 1); - debugPrint t; - x; - }; - }; - - public func g0_2() : async (Int,Bool) { - (1,true); - }; - { - let t = "0_2"; - ignore async { - let (x,y) = await g0_2(); - assert(x==1); - assert(y==true); - debugPrint t; - (x,y); - }; - }; - - - public func g0_3() : async (Int,Bool,Text) { - (1,true,"a"); - }; - { - let t = "0_3"; - ignore async { - let (x,y,z) = await g0_3(); - assert(x==1); - assert(y==true); - assert(z=="a"); - debugPrint t; - (x,y,z); - }; - }; -} diff --git a/test/run-stub/ok/AST-66.ic-stub-run.ok b/test/run-stub/ok/AST-66.ic-stub-run.ok deleted file mode 100644 index 54225bc8555..00000000000 --- a/test/run-stub/ok/AST-66.ic-stub-run.ok +++ /dev/null @@ -1,4 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -← completed diff --git a/test/run-stub/ok/async-loop.ic-stub-run.ok b/test/run-stub/ok/async-loop.ic-stub-run.ok deleted file mode 100644 index ac17ed83399..00000000000 --- a/test/run-stub/ok/async-loop.ic-stub-run.ok +++ /dev/null @@ -1,16 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -0 -1 -2 -0 -1 -2 -0 -1 -2 -0 -1 -2 -← completed diff --git a/test/run-stub/ok/async-loop.run-ir.ok b/test/run-stub/ok/async-loop.run-ir.ok deleted file mode 100644 index 4e57a41a93e..00000000000 --- a/test/run-stub/ok/async-loop.run-ir.ok +++ /dev/null @@ -1,12 +0,0 @@ -0 -1 -2 -0 -1 -2 -0 -1 -2 -0 -1 -2 diff --git a/test/run-stub/ok/async-loop.run-low.ok b/test/run-stub/ok/async-loop.run-low.ok deleted file mode 100644 index 4e57a41a93e..00000000000 --- a/test/run-stub/ok/async-loop.run-low.ok +++ /dev/null @@ -1,12 +0,0 @@ -0 -1 -2 -0 -1 -2 -0 -1 -2 -0 -1 -2 diff --git a/test/run-stub/ok/async-loop.run.ok b/test/run-stub/ok/async-loop.run.ok deleted file mode 100644 index 4e57a41a93e..00000000000 --- a/test/run-stub/ok/async-loop.run.ok +++ /dev/null @@ -1,12 +0,0 @@ -0 -1 -2 -0 -1 -2 -0 -1 -2 -0 -1 -2 diff --git a/test/run-stub/ok/control.ic-stub-run.ok b/test/run-stub/ok/control.ic-stub-run.ok deleted file mode 100644 index 54225bc8555..00000000000 --- a/test/run-stub/ok/control.ic-stub-run.ok +++ /dev/null @@ -1,4 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -← completed diff --git a/test/run-stub/ok/counter.ic-stub-run.ok b/test/run-stub/ok/counter.ic-stub-run.ok deleted file mode 100644 index d5ebf47c862..00000000000 --- a/test/run-stub/ok/counter.ic-stub-run.ok +++ /dev/null @@ -1,18 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -← completed -→ update inc(0x4449444c0000) -2 -← completed: 0x4449444c0000 -→ update inc(0x4449444c0000) -3 -← completed: 0x4449444c0000 -→ update inc(0x4449444c0000) -4 -← completed: 0x4449444c0000 -→ update printCounter(0x4449444c0000) -4 -← completed: 0x4449444c0000 -→ update get(0x4449444c0000) -← completed: 0x4449444c00017d04 diff --git a/test/run-stub/ok/divide-by-zero.ic-stub-run.ok b/test/run-stub/ok/divide-by-zero.ic-stub-run.ok deleted file mode 100644 index 59ec67eb613..00000000000 --- a/test/run-stub/ok/divide-by-zero.ic-stub-run.ok +++ /dev/null @@ -1,4 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -ic-stub-run: divide by zero diff --git a/test/run-stub/ok/empty-actor.ic-stub-run.ok b/test/run-stub/ok/empty-actor.ic-stub-run.ok deleted file mode 100644 index 54225bc8555..00000000000 --- a/test/run-stub/ok/empty-actor.ic-stub-run.ok +++ /dev/null @@ -1,4 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -← completed diff --git a/test/run-stub/ok/general-type-components.ic-stub-run.ok b/test/run-stub/ok/general-type-components.ic-stub-run.ok deleted file mode 100644 index 54225bc8555..00000000000 --- a/test/run-stub/ok/general-type-components.ic-stub-run.ok +++ /dev/null @@ -1,4 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -← completed diff --git a/test/run-stub/ok/hello-world-return.ic-stub-run.ok b/test/run-stub/ok/hello-world-return.ic-stub-run.ok deleted file mode 100644 index ced690a2811..00000000000 --- a/test/run-stub/ok/hello-world-return.ic-stub-run.ok +++ /dev/null @@ -1,8 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -← completed -→ query hello(0x4449444c00017105576f726c64) -← completed: 0x4449444c0001710c48656c6c6f20576f726c6421 -→ query hello2(0x4449444c00017105576f726c64) -← completed: 0x4449444c0001710c48656c6c6f20576f726c6421 diff --git a/test/run-stub/ok/ic-calls.run-ir.ok b/test/run-stub/ok/ic-calls.run-ir.ok deleted file mode 100644 index d7c2f49f195..00000000000 --- a/test/run-stub/ok/ic-calls.run-ir.ok +++ /dev/null @@ -1,4 +0,0 @@ -A -B -C -test diff --git a/test/run-stub/ok/ic-calls.run-low.ok b/test/run-stub/ok/ic-calls.run-low.ok deleted file mode 100644 index d7c2f49f195..00000000000 --- a/test/run-stub/ok/ic-calls.run-low.ok +++ /dev/null @@ -1,4 +0,0 @@ -A -B -C -test diff --git a/test/run-stub/ok/ic-calls.run.ok b/test/run-stub/ok/ic-calls.run.ok deleted file mode 100644 index d7c2f49f195..00000000000 --- a/test/run-stub/ok/ic-calls.run.ok +++ /dev/null @@ -1,4 +0,0 @@ -A -B -C -test diff --git a/test/run-stub/ok/ic-calls.tc.ok b/test/run-stub/ok/ic-calls.tc.ok deleted file mode 100644 index 226f38933fc..00000000000 --- a/test/run-stub/ok/ic-calls.tc.ok +++ /dev/null @@ -1,9 +0,0 @@ -ic-calls.mo:20.9-20.10: warning, this pattern consuming type - Int -does not cover value - 0 or -1 or _ -ic-calls.mo:21.9-21.17: warning, this pattern consuming type - (Int, Bool) -does not cover value - (1, false) or - (0 or -1 or _, _) diff --git a/test/run-stub/ok/idl-any.ic-stub-run.ok b/test/run-stub/ok/idl-any.ic-stub-run.ok deleted file mode 100644 index cad8ed39a4c..00000000000 --- a/test/run-stub/ok/idl-any.ic-stub-run.ok +++ /dev/null @@ -1,88 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -← completed -→ update any(0x4449444c00027f7103466f6f) -ok: Foo -← completed: 0x4449444c0000 -→ update any(0x4449444c00027e710103466f6f) -ok: Foo -← completed: 0x4449444c0000 -→ update any(0x4449444c00027d718080800803466f6f) -ok: Foo -← completed: 0x4449444c0000 -→ update any(0x4449444c00027c718080800803466f6f) -ok: Foo -← completed: 0x4449444c0000 -→ update any(0x4449444c00027b71ab03466f6f) -ok: Foo -← completed: 0x4449444c0000 -→ update any(0x4449444c00027a71abcd03466f6f) -ok: Foo -← completed: 0x4449444c0000 -→ update any(0x4449444c00027971deadbeef03466f6f) -ok: Foo -← completed: 0x4449444c0000 -→ update any(0x4449444c00027871deadbeefcaffee6603466f6f) -ok: Foo -← completed: 0x4449444c0000 -→ update any(0x4449444c00027771ab03466f6f) -ok: Foo -← completed: 0x4449444c0000 -→ update any(0x4449444c00027671abcd03466f6f) -ok: Foo -← completed: 0x4449444c0000 -→ update any(0x4449444c00027571deadbeef03466f6f) -ok: Foo -← completed: 0x4449444c0000 -→ update any(0x4449444c00027471deadbeefcaffee6603466f6f) -ok: Foo -← completed: 0x4449444c0000 -→ update any(0x4449444c00027371deadbeef03466f6f) -ok: Foo -← completed: 0x4449444c0000 -→ update any(0x4449444c00027271deadbeefcaffee6603466f6f) -ok: Foo -← completed: 0x4449444c0000 -→ update any(0x4449444c0002717103466f6f03466f6f) -ok: Foo -← completed: 0x4449444c0000 -→ update any(0x4449444c0002707103466f6f) -ok: Foo -← completed: 0x4449444c0000 -→ update any(0x4449444c016e710200710003466f6f) -ok: Foo -← completed: 0x4449444c0000 -→ update any(0x4449444c016e710200710103466f6f03466f6f) -ok: Foo -← completed: 0x4449444c0000 -→ update any(0x4449444c016d710200710003466f6f) -ok: Foo -← completed: 0x4449444c0000 -→ update any(0x4449444c016d710200710103466f6f03466f6f) -ok: Foo -← completed: 0x4449444c0000 -→ update any(0x4449444c016d71020071020003466f6f03466f6f) -ok: Foo -← completed: 0x4449444c0000 -→ update any(0x4449444c016c0002007103466f6f) -ok: Foo -← completed: 0x4449444c0000 -→ update any(0x4449444c016c01800175020071deadbeef03466f6f) -ok: Foo -← completed: 0x4449444c0000 -→ update any(0x4449444c016c02007180017502007101a0deadbeef03466f6f) -ok: Foo -← completed: 0x4449444c0000 -→ update any(0x4449444c016b0180017502007100deadbeef03466f6f) -ok: Foo -← completed: 0x4449444c0000 -→ update any(0x4449444c016b0200718001750200710001a003466f6f) -ok: Foo -← completed: 0x4449444c0000 -→ update any(0x4449444c016b02007180017502007101deadbeef03466f6f) -ok: Foo -← completed: 0x4449444c0000 -→ update any(0x4449444c016602abcd0200710400deadbeef03466f6f) -ok: Foo -← completed: 0x4449444c0000 diff --git a/test/run-stub/ok/idl-bad.ic-stub-run.ok b/test/run-stub/ok/idl-bad.ic-stub-run.ok deleted file mode 100644 index 55f13f8b448..00000000000 --- a/test/run-stub/ok/idl-bad.ic-stub-run.ok +++ /dev/null @@ -1,7 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -← completed -→ query foo(0x4e4f544449444c) -IDL error: missing magic bytes -← rejected (RC_CANISTER_ERROR): canister trapped: EvalTrapError :0.1 "unreachable executed" diff --git a/test/run-stub/ok/idl-field-escape.ic-stub-run.ok b/test/run-stub/ok/idl-field-escape.ic-stub-run.ok deleted file mode 100644 index fa73a9cfd53..00000000000 --- a/test/run-stub/ok/idl-field-escape.ic-stub-run.ok +++ /dev/null @@ -1,12 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -← completed -→ update foo1(0x4449444c0000) -← completed: 0x4449444c016c01868eb7027f0100 -→ update foo2(0x4449444c0000) -← completed: 0x4449444c016c01868eb7027f0100 -→ update out(0x4449444c0000) -← completed: 0x4449444c016c03007c017dbcfef7b102710100ffff03802003585858 -→ update input(0x4449444c016c03007c017dbcfef7b102710100ffff03802003585858) -← completed: 0x4449444c0000 diff --git a/test/run-stub/ok/idl-func.ic-stub-run.ok b/test/run-stub/ok/idl-func.ic-stub-run.ok deleted file mode 100644 index a787304d4d8..00000000000 --- a/test/run-stub/ok/idl-func.ic-stub-run.ok +++ /dev/null @@ -1,8 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -← completed -→ query fun(0x4449444c0000) -← completed: 0x4449444c036e016c02000201716d7b010000 -→ query fun2(0x4449444c026e016a017c0000010000) -← completed: 0x4449444c0000 diff --git a/test/run-stub/ok/idl-nary.ic-stub-run.ok b/test/run-stub/ok/idl-nary.ic-stub-run.ok deleted file mode 100644 index 53330a2c4ac..00000000000 --- a/test/run-stub/ok/idl-nary.ic-stub-run.ok +++ /dev/null @@ -1,28 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -← completed -→ update two(0x4449444c00027171034f6e650354776f) -← completed: 0x4449444c00027171034f6e650354776f -→ update three(0x4449444c0003717171034f6e650354776f055468726565) -← completed: 0x4449444c0003717171034f6e650354776f055468726565 -→ update four(0x4449444c000471717171034f6e650354776f05546872656504466f7572) -← completed: 0x4449444c000471717171034f6e650354776f05546872656504466f7572 -→ update mkRecord(0x4449444c0000) -← completed: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 -→ update unary1(0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572) -← completed: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 -→ update unary2(0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572) -← completed: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 -→ update unary3(0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572) -← completed: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 -→ update unary4(0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572) -← completed: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 -→ update three(0x4449444c00027171034f6e650354776f) -Trap: EvalTrapError :0.1 "canister trapped explicitly: IDL error: too few arguments Text,Text,Text" -← rejected (RC_CANISTER_ERROR): canister trapped: EvalTrapError :0.1 "canister trapped explicitly: IDL error: too few arguments Text,Text,Text" -→ update three(0x4449444c0003717171034f6e650354776f05546872656545585452414259544553) -Trap: EvalTrapError :0.1 "canister trapped explicitly: IDL error: left-over bytes Text,Text,Text" -← rejected (RC_CANISTER_ERROR): canister trapped: EvalTrapError :0.1 "canister trapped explicitly: IDL error: left-over bytes Text,Text,Text" -→ update four(0x4449444c00057171717171034f6e650354776f05546872656504466f75720446697665) -← completed: 0x4449444c000471717171034f6e650354776f05546872656504466f7572 diff --git a/test/run-stub/ok/idl-nat-int.ic-stub-run.ok b/test/run-stub/ok/idl-nat-int.ic-stub-run.ok deleted file mode 100644 index e2cfca32cb4..00000000000 --- a/test/run-stub/ok/idl-nat-int.ic-stub-run.ok +++ /dev/null @@ -1,12 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -← completed -→ query absolute(0x4449444c00017d2a) -← completed: 0x4449444c00017d2a -→ query absolute(0x4449444c00017c56) -← completed: 0x4449444c00017d2a -→ query absolutes(0x4449444c016d7d0100022a19) -← completed: 0x4449444c016d7d0100022a19 -→ query absolutes(0x4449444c016d7c0100025619) -← completed: 0x4449444c016d7d0100022a19 diff --git a/test/run-stub/ok/idl-option.ic-stub-run.ok b/test/run-stub/ok/idl-option.ic-stub-run.ok deleted file mode 100644 index 7268e34088a..00000000000 --- a/test/run-stub/ok/idl-option.ic-stub-run.ok +++ /dev/null @@ -1,13 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -← completed -→ update any(0x4449444c00017f) -ok: null -← completed: 0x4449444c0000 -→ update any(0x4449444c016e71010000) -ok: null -← completed: 0x4449444c0000 -→ update any(0x4449444c016e7101000103466f6f) -ok: Foo -← completed: 0x4449444c0000 diff --git a/test/run-stub/ok/idl-pair.ic-stub-run.ok b/test/run-stub/ok/idl-pair.ic-stub-run.ok deleted file mode 100644 index 5fc5fed734d..00000000000 --- a/test/run-stub/ok/idl-pair.ic-stub-run.ok +++ /dev/null @@ -1,6 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -← completed -→ update len2(0x4449444c0002717102486905576f726c64) -← completed: 0x4449444c016c02007c017c01000205 diff --git a/test/run-stub/ok/idl-record.ic-stub-run.ok b/test/run-stub/ok/idl-record.ic-stub-run.ok deleted file mode 100644 index df552d2b0f9..00000000000 --- a/test/run-stub/ok/idl-record.ic-stub-run.ok +++ /dev/null @@ -1,16 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -← completed -→ update pair(0x4449444c016c020071017c010004486579212a) -ok: +42 -← completed: 0x4449444c0000 -→ update record(0x4449444c016c02b99adecb0171f1fee18d037c010004486579212a) -ok: Hey! -← completed: 0x4449444c0000 -→ update record1(0x4449444c016c03b99adecb0171f1fee18d037c88be8c890477010004486579212a19) -ok: +25 -← completed: 0x4449444c0000 -→ update record2(0x4449444c016c03b99adecb0171f1fee18d037c88be8c89047702007704486579212a1819) -ok: Hey! +25 -← completed: 0x4449444c00017719 diff --git a/test/run-stub/ok/idl-tuple.ic-stub-run.ok b/test/run-stub/ok/idl-tuple.ic-stub-run.ok deleted file mode 100644 index c8f4900d5fb..00000000000 --- a/test/run-stub/ok/idl-tuple.ic-stub-run.ok +++ /dev/null @@ -1,12 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -← completed -→ query len2(0x4449444c0002717102486905576f726c64) -← completed: 0x4449444c00027c7c0205 -→ query len3(0x4449444c016c02007101750200710548656c6c6f0102030405576f726c64) -← completed: 0x4449444c00037c7c7c050581848c20 -→ query len3(0x4449444c016c030071007601750200710548656c6c6fdead0102030405576f726c64) -← completed: 0x4449444c00037c7c7c050581848c20 -→ query len3(0x4449444c016c030071017502760200710548656c6c6f01020304dead05576f726c64) -← completed: 0x4449444c00037c7c7c050581848c20 diff --git a/test/run-stub/ok/idl-variant.ic-stub-run.ok b/test/run-stub/ok/idl-variant.ic-stub-run.ok deleted file mode 100644 index 75074f6bd69..00000000000 --- a/test/run-stub/ok/idl-variant.ic-stub-run.ok +++ /dev/null @@ -1,6 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -← completed -→ query numify(0x4449444c016b03d583b702008790c0bd0479dc9790cb0e790100000220000000) -← completed: 0x4449444c016b03d583b702008790c0bd0479dc9790cb0e790100000120000000 diff --git a/test/run-stub/ok/idl-vector.ic-stub-run.ok b/test/run-stub/ok/idl-vector.ic-stub-run.ok deleted file mode 100644 index 352cb7766e8..00000000000 --- a/test/run-stub/ok/idl-vector.ic-stub-run.ok +++ /dev/null @@ -1,6 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -← completed -→ query rose(0x4449444c016d00010003000400020000000000) -← completed: 0x4449444c026e016d0001000103010001040100010201000100010001000100 diff --git a/test/run-stub/ok/multiple-actors.comp.ok b/test/run-stub/ok/multiple-actors.comp.ok deleted file mode 100644 index 839f6dcaeab..00000000000 --- a/test/run-stub/ok/multiple-actors.comp.ok +++ /dev/null @@ -1,4 +0,0 @@ -multiple-actors.mo:1.1-1.12: type error, multiple actors in program; there must be at most one actor declaration in a program - (This is a limitation of the current version and flag -stub-system-api.) -multiple-actors.mo:3.1-3.12: type error, multiple actors in program; there must be at most one actor declaration in a program - (This is a limitation of the current version and flag -stub-system-api.) diff --git a/test/run-stub/ok/nary-async.ic-stub-run.ok b/test/run-stub/ok/nary-async.ic-stub-run.ok deleted file mode 100644 index 5070e4ed2ea..00000000000 --- a/test/run-stub/ok/nary-async.ic-stub-run.ok +++ /dev/null @@ -1,12 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -0_0 -1_0 -2_0 -3_0 -0_0 -0_1 -0_2 -0_3 -← completed diff --git a/test/run-stub/ok/overflow.run-ir.ok b/test/run-stub/ok/overflow.run-ir.ok deleted file mode 100644 index 481b58663c2..00000000000 --- a/test/run-stub/ok/overflow.run-ir.ok +++ /dev/null @@ -1,6 +0,0 @@ -This is reachable. -This is reachable. -overflow.mo:14.14-14.17: execution error, arithmetic overflow -overflow.mo:18.14-18.17: execution error, arithmetic overflow -This is reachable. -This is reachable. diff --git a/test/run-stub/ok/overflow.run-low.ok b/test/run-stub/ok/overflow.run-low.ok deleted file mode 100644 index 481b58663c2..00000000000 --- a/test/run-stub/ok/overflow.run-low.ok +++ /dev/null @@ -1,6 +0,0 @@ -This is reachable. -This is reachable. -overflow.mo:14.14-14.17: execution error, arithmetic overflow -overflow.mo:18.14-18.17: execution error, arithmetic overflow -This is reachable. -This is reachable. diff --git a/test/run-stub/ok/overflow.run.ok b/test/run-stub/ok/overflow.run.ok deleted file mode 100644 index 481b58663c2..00000000000 --- a/test/run-stub/ok/overflow.run.ok +++ /dev/null @@ -1,6 +0,0 @@ -This is reachable. -This is reachable. -overflow.mo:14.14-14.17: execution error, arithmetic overflow -overflow.mo:18.14-18.17: execution error, arithmetic overflow -This is reachable. -This is reachable. diff --git a/test/run-stub/ok/print-from-init.ic-stub-run.ok b/test/run-stub/ok/print-from-init.ic-stub-run.ok deleted file mode 100644 index 69d944607df..00000000000 --- a/test/run-stub/ok/print-from-init.ic-stub-run.ok +++ /dev/null @@ -1,5 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -Debug out -← completed diff --git a/test/run-stub/ok/print-from-init.run-ir.ok b/test/run-stub/ok/print-from-init.run-ir.ok deleted file mode 100644 index 2c5e67992ab..00000000000 --- a/test/run-stub/ok/print-from-init.run-ir.ok +++ /dev/null @@ -1 +0,0 @@ -Debug out diff --git a/test/run-stub/ok/print-from-init.run-low.ok b/test/run-stub/ok/print-from-init.run-low.ok deleted file mode 100644 index 2c5e67992ab..00000000000 --- a/test/run-stub/ok/print-from-init.run-low.ok +++ /dev/null @@ -1 +0,0 @@ -Debug out diff --git a/test/run-stub/ok/print-from-init.run.ok b/test/run-stub/ok/print-from-init.run.ok deleted file mode 100644 index 2c5e67992ab..00000000000 --- a/test/run-stub/ok/print-from-init.run.ok +++ /dev/null @@ -1 +0,0 @@ -Debug out diff --git a/test/run-stub/ok/query.ic-stub-run.ok b/test/run-stub/ok/query.ic-stub-run.ok deleted file mode 100644 index fb708e299fd..00000000000 --- a/test/run-stub/ok/query.ic-stub-run.ok +++ /dev/null @@ -1,30 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -← completed -→ update inc(0x4449444c0000) -2 -← completed: 0x4449444c0000 -→ update inc(0x4449444c0000) -3 -← completed: 0x4449444c0000 -→ update inc(0x4449444c0000) -4 -← completed: 0x4449444c0000 -→ update printCounter(0x4449444c0000) -4 -← completed: 0x4449444c0000 -→ update get(0x4449444c0000) -← completed: 0x4449444c00017d04 -→ query read(0x4449444c0000) -5 -← completed: 0x4449444c00017d04 -→ update printCounter(0x4449444c0000) -4 -← completed: 0x4449444c0000 -→ query read(0x4449444c0000) -5 -← completed: 0x4449444c00017d04 -→ update printCounter(0x4449444c0000) -4 -← completed: 0x4449444c0000 diff --git a/test/run-stub/ok/reject.ic-stub-run.ok b/test/run-stub/ok/reject.ic-stub-run.ok deleted file mode 100644 index cca556750dd..00000000000 --- a/test/run-stub/ok/reject.ic-stub-run.ok +++ /dev/null @@ -1,15 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -← completed -→ update reject1(0x4449444c0000) -1 -← rejected (RC_CANISTER_REJECT): Error -→ update reject2(0x4449444c0000) -1 -ok -← completed: 0x4449444c0000 -→ update reject3(0x4449444c0000) -1 -ok -← rejected (RC_CANISTER_REJECT): Error diff --git a/test/run-stub/ok/reversi.ic-stub-run.ok b/test/run-stub/ok/reversi.ic-stub-run.ok deleted file mode 100644 index 2bddbf68bb6..00000000000 --- a/test/run-stub/ok/reversi.ic-stub-run.ok +++ /dev/null @@ -1,20 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -← completed -→ update reset(0x4449444c0000) -← completed: 0x4449444c0000 -→ update board(0x4449444c0000) -← completed: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e4f2a2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a -→ update place(0x4449444c00037c7c7c010204) -← completed: 0x4449444c000171024f4b -→ update board(0x4449444c0000) -← completed: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e4f2e2e2e0a2e2e2e4f4f2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a -→ update place(0x4449444c00037c7c7c020203) -← completed: 0x4449444c000171024f4b -→ update board(0x4449444c0000) -← completed: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a -→ update place(0x4449444c00037c7c7c010402) -← completed: 0x4449444c000171024f4b -→ update board(0x4449444c0000) -← completed: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e4f4f2e2e2e0a2e2e4f4f4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a diff --git a/test/run-stub/ok/rts-stats.ic-stub-run.ok b/test/run-stub/ok/rts-stats.ic-stub-run.ok deleted file mode 100644 index a6f1dd30bd2..00000000000 --- a/test/run-stub/ok/rts-stats.ic-stub-run.ok +++ /dev/null @@ -1,5 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -Size and allocation delta: (10_008, 10_008) -← completed diff --git a/test/run-stub/ok/self-calls.ic-stub-run.ok b/test/run-stub/ok/self-calls.ic-stub-run.ok deleted file mode 100644 index 607268f5415..00000000000 --- a/test/run-stub/ok/self-calls.ic-stub-run.ok +++ /dev/null @@ -1,11 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -test1 -A called -test2 -B called -test3 -C called -test4 -← completed diff --git a/test/run-stub/ok/self-calls.run-ir.ok b/test/run-stub/ok/self-calls.run-ir.ok deleted file mode 100644 index f46b40f7334..00000000000 --- a/test/run-stub/ok/self-calls.run-ir.ok +++ /dev/null @@ -1,7 +0,0 @@ -test1 -A called -test2 -B called -test3 -C called -test4 diff --git a/test/run-stub/ok/self-calls.run-low.ok b/test/run-stub/ok/self-calls.run-low.ok deleted file mode 100644 index f46b40f7334..00000000000 --- a/test/run-stub/ok/self-calls.run-low.ok +++ /dev/null @@ -1,7 +0,0 @@ -test1 -A called -test2 -B called -test3 -C called -test4 diff --git a/test/run-stub/ok/self-calls.run.ok b/test/run-stub/ok/self-calls.run.ok deleted file mode 100644 index f46b40f7334..00000000000 --- a/test/run-stub/ok/self-calls.run.ok +++ /dev/null @@ -1,7 +0,0 @@ -test1 -A called -test2 -B called -test3 -C called -test4 diff --git a/test/run-stub/ok/simple-throw.ic-stub-run.ok b/test/run-stub/ok/simple-throw.ic-stub-run.ok deleted file mode 100644 index f97beec3dc8..00000000000 --- a/test/run-stub/ok/simple-throw.ic-stub-run.ok +++ /dev/null @@ -1,9 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -1 -2 -3 -4 -done -← completed diff --git a/test/run-stub/overflow.mo b/test/run-stub/overflow.mo deleted file mode 100644 index d0b6e27d722..00000000000 --- a/test/run-stub/overflow.mo +++ /dev/null @@ -1,34 +0,0 @@ -// We have theses tests in run-dfinity because we want to check that certain -// traps are happening, and a good way to test this is if a message gets -// aborted. - -ignore(async { - ignore ((0-1):Int); - debugPrint("This is reachable."); -}); -ignore(async { - ignore ((1-1):Nat); - debugPrint("This is reachable."); -}); -ignore(async { - ignore ((0-1):Nat); - debugPrint("This should be unreachable."); -}); -ignore(async { - ignore ((0-1):Nat); - debugPrint("This should be unreachable."); -}); -/* -ignore(async { - ignore ((18446744073709551615 + 0):Nat); - debugPrint("This is reachable."); -}); -*/ -ignore(async { - ignore ((9223372036854775806 + 9223372036854775806 + 1):Nat); - debugPrint("This is reachable."); -}); -ignore(async { - ignore ((9223372036854775806 + 9223372036854775806 + 2):Nat); - debugPrint("This is reachable."); -}); diff --git a/test/run-stub/print-from-init.mo b/test/run-stub/print-from-init.mo deleted file mode 100644 index e65298d1a21..00000000000 --- a/test/run-stub/print-from-init.mo +++ /dev/null @@ -1,3 +0,0 @@ -actor { - debugPrint("Debug out"); -} diff --git a/test/run-stub/query.mo b/test/run-stub/query.mo deleted file mode 100644 index 99edfb122ec..00000000000 --- a/test/run-stub/query.mo +++ /dev/null @@ -1,29 +0,0 @@ -actor { - var c = 1; - public func inc() { - c += 1; - debugPrintNat c; - }; - public func printCounter () { - debugPrintNat c; - }; - public func get() : async Nat { - return c - }; - public query func read() : async Nat { - let tmp = c; - c += 1; - debugPrintNat c; - return tmp; - }; - -} -//CALL ingress inc 0x4449444C0000 -//CALL ingress inc 0x4449444C0000 -//CALL ingress inc 0x4449444C0000 -//CALL ingress printCounter 0x4449444C0000 -//CALL ingress get 0x4449444C0000 -//CALL query read 0x4449444C0000 -//CALL ingress printCounter 0x4449444C0000 -//CALL query read 0x4449444C0000 -//CALL ingress printCounter 0x4449444C0000 diff --git a/test/run-stub/reject.mo b/test/run-stub/reject.mo deleted file mode 100644 index a2a7e7bdff9..00000000000 --- a/test/run-stub/reject.mo +++ /dev/null @@ -1,29 +0,0 @@ -actor { - public func reject1() : async () { - debugPrint "1"; - throw (error("Error")); - debugPrint "wrong"; - }; - - public func reject2() : async () { - debugPrint "1"; - try { throw (error("Error")) } - catch e {}; - debugPrint "ok"; - }; - - public func reject3() : async () { - debugPrint "1"; - try { throw (error("Error")) } - catch e { - debugPrint "ok"; - throw e; - }; - debugPrint "wrong"; - }; - -} - -//CALL ingress reject1 0x4449444C0000 -//CALL ingress reject2 0x4449444C0000 -//CALL ingress reject3 0x4449444C0000 diff --git a/test/run-stub/reversi.mo b/test/run-stub/reversi.mo deleted file mode 100644 index 95f7038f341..00000000000 --- a/test/run-stub/reversi.mo +++ /dev/null @@ -1,274 +0,0 @@ -actor { - // based on https://github.com/dfinity-lab/dapps/blob/75ead35363574f3697e37cd3a0592e51d3253a36/examples/reversi/src/reversi/main.mo - // with stdlib inlined and board size changed to 8 - - - // inline parts of stdlib - func unreachable() : None = { assert false ; loop { } }; - - func toText(x : Int) : Text { - if (x == 0) { - return "0"; - }; - - let isNegative = x < 0; - var int = if isNegative (-x) else x; - - var text = ""; - let base = 10; - - while (int > 0) { - let rem = int % base; - text := (switch (rem) { - case 0 "0"; - case 1 "1"; - case 2 "2"; - case 3 "3"; - case 4 "4"; - case 5 "5"; - case 6 "6"; - case 7 "7"; - case 8 "8"; - case 9 "9"; - case _ unreachable(); - }) # text; - int := int / base; - }; - - return if isNegative ("-" # text) else text; - }; - - - - // Color related type and constants - type Color = Nat; - let empty : Color = 0; - let white : Color = 1; - let black : Color = 2; - - // Dimension of the board - let N : Nat = 8; - - // Board is NxN array - type Board = [var Color]; - let Board : Board = Array_init(N * N, empty); - - // Which color should move next - var next_color : Color = white; - - // Reset the board to initial state - func init() { - // Reset to empty board - for (i in range(0, N * N - 1)) { - Board[i] := empty; - }; - - // initialize center 4 pieces - let M = N / 2; - Board[(M - 1) * N + M - 1] := white; - Board[ M * N + M ] := white; - Board[(M - 1) * N + M ] := black; - Board[ M * N + M - 1] := black; - - // White moves first - next_color := white; - }; - - // External interface to reset the board - public func reset() { - init() - }; - - public func dimension() : async Nat { - return N; - }; - - // Render the board into a string - func render(board: Board) : Text { - var str = ""; - for (i in range(0, N-1)) { - for (j in range(0, N-1)) { - if (board[i * N + j] == white) { - str := str # "O"; - } else if (board[i * N + j] == black) { - str := str # "*"; - } - else { - str := str # "."; - }; - }; - str := str # "\n"; - }; - - return str; - }; - - // External interface to render the board - public func board() : async Text { - return render(Board); - }; - - // Given a color, return its opponent color - func opponent(color: Color): Color { - return (3 - color); - }; - - // Check if a piece of the given color exists on the board using - // coordinate (i, j) and offset (p, q). - func exists(board: Board, color: Color, i: Nat, j: Nat, p:Int, q:Int) : Bool { - let s = i + p; - let t = j + q; - if (s < 0 or s >= N or t < 0 or t >= N) { - return false; - }; - return (board[abs (s * N + t)] == color); - }; - - // Check if a piece of the given color eventually exits on the board - // using coordinate (i, j) and direction (p, q), ignoring opponent colors - // in between. Return false if the given color is not found before reaching - // empty cell or board boundary. - func eventually(board: Board, color: Color, i: Nat, j: Nat, p:Int, q:Int) : Bool { - if (exists(board, opponent(color), i, j, p, q)) { - // the abs below is save because its precondition is already checked - return eventually(board, color, abs(i + p), abs(j + q), p, q); - } else { - return exists(board, color, i, j, p, q); - } - }; - - // Flip pieces of opponent color into the given color starting from - // coordinate (i, j) and along direction (p, q). - func flip(board: Board, color: Color, i: Nat, j: Nat, p:Int, q:Int) { - if (exists(board, opponent(color), i, j, p, q)) { - // the abs below is save because its precondition is already checked - let s = abs(i + p); - let t = abs(j + q); - board[s * N + t] := color; - flip(board, color, s, t, p, q); - } - }; - - // Calculate all validate positions for a given color by returning - // a board that has the cells colored. - func valid_moves(board: Board, color: Color) : Board { - let next : Board = Array_init(N * N, empty); - for (i in range(0, N-1)) { - for (j in range(0, N-1)) { - if (board[i * N + j] == empty) { - for (p in [-1, 0, 1].vals()) { - for (q in [-1, 0, 1].vals()) { - if (not(p == 0 and q == 0)) { - if (exists(board, opponent(color), i, j, p, q) and - eventually(board, color, i, j, p, q)) { - next[i * N + j] := color; - } - } - } - } - } - } - }; - return next; - }; - - // Set a piece on the board at a given position, and flip all - // affected opponent pieces accordingly. It requires that the - // given position is a valid move before this call. - func set_and_flip(board: Board, color: Color, i: Nat, j: Nat) { - board[i * N + j] := color; - for (p in [-1, 0, 1].vals()) { - for (q in [-1, 0, 1].vals()) { - if (not(p == 0 and q == 0)) { - if (exists(board, opponent(color), i, j, p, q) and - eventually(board, color, i, j, p, q)) { - flip(board, color, i, j, p, q); - } - } - } - } - }; - - // Check if the given board is empty. - func is_empty(board: Board) : Bool { - for (c in board.vals()) { - if (c != empty){ - return false; - } - }; - return true; - }; - - - // Return the white and black counts. - func score(board: Board) : (Nat, Nat) { - var wc = 0; - var bc = 0; - for (c in board.vals()) { - if (c == white) { - wc += 1; - } - else if (c == black) { - bc += 1; - } - }; - return (wc, bc); - }; - - // External interface that places a piece of given color at a coordinate. - // It returns "OK" when the move is valid. - public func place(color_: Int, row_: Int, col_: Int) : async Text { - // The casting is necessary because dfx has yet to support Nat on commandline - let color : Color = abs(color_); - let row : Nat = abs(row_); - let col : Nat = abs(col_); - - // Check input validity - if (row >= N or col >= N) { - return "Invalid coordinate"; - }; - if (not (color == 1 or color == 2)) { - return "Invalid piece color, must be either 1 or 2"; - }; - - var possible = valid_moves(Board, next_color); - - // If no move is possible, either pass or end game. - if (is_empty(possible)) { - next_color := opponent(next_color); - possible := valid_moves(Board, next_color); - // If no possible move again, end game - if (is_empty(possible)) { - let (wc, bc) = score(Board); - return ("End Game! Whites = " # toText(wc) # ", Blacks = " # toText(bc)) - } - else { - return "PASS" - } - }; - - if (next_color != color) { - return "Wrong color for this move"; - }; - - if (possible[row * N + col] != empty) { - set_and_flip(Board, color, row, col); - next_color := opponent(color); - return "OK"; - } else { - return "Illegal move"; - }; - - }; - - init(); -}; - -//CALL ingress reset 0x4449444C0000 -//CALL ingress board 0x4449444C0000 -//CALL ingress place 0x4449444C00037c7c7c010204 -//CALL ingress board 0x4449444C0000 -//CALL ingress place 0x4449444C00037c7c7c020203 -//CALL ingress board 0x4449444C0000 -//CALL ingress place 0x4449444C00037c7c7c010402 -//CALL ingress board 0x4449444C0000 diff --git a/test/run-stub/self-calls.mo b/test/run-stub/self-calls.mo deleted file mode 100644 index e64643b7ec6..00000000000 --- a/test/run-stub/self-calls.mo +++ /dev/null @@ -1,30 +0,0 @@ -actor a { - public func A() : async () { - debugPrint("A called"); - }; - - - public func B(x : Int) : async Int { - debugPrint("B called"); - x - }; - - public func C(x : Int, y: Bool) : async (Int,Bool) { - debugPrint("C called"); - (x,y); - }; - - public func test() = ignore async { - debugPrint("test1"); - let x = await a.A(); - debugPrint("test2"); - let y = await a.B(1); - debugPrint("test3"); - let z = await a.C(2,true); - debugPrint("test4"); - assert (y == 1); - assert (z.0 == 2); - assert (z.1); - }; -}; -a.test(); diff --git a/test/run-stub/unsupported.mo b/test/run-stub/unsupported.mo deleted file mode 100644 index 58f17ecb5b1..00000000000 --- a/test/run-stub/unsupported.mo +++ /dev/null @@ -1,81 +0,0 @@ -// top-level actor objects are supported -actor Counter { - - shared func bad_private_shared() { }; // not public - - public func badactorarg(a:actor{}) : async () {}; - - public func badfunctionarg(f:shared()->async ()) : async () {}; - - /* TODO - public func badoneway(){}; // unsupported oneway - */ - - public func ok() : async () {}; - - public func ok_explicit() : async () = async {}; - - public func bad_call() : async () { - ignore (ok()); // unsupported intercanister messaging - }; - - public func bad_await_call() : async () { - await (ok()); // unsupported intercanister messaging - }; - - public func bad_await() : async () { - let t : async () = loop {}; - await t; // unsupported general await - }; - - public func badasync() : async () { - let a = async { 1; }; // unsupported async - }; - -} -; - -shared func bad_shared() { }; // not actor enclosed - -func local_spawn() { - ignore(async ()); // not yet supported -}; - -{ - // shared function types aren't sharable - type illformed_1 = shared (shared () -> ()) -> async (); -}; - -{ - // actors aren't shareable - type illformed_2 = shared (actor {}) -> async (); -}; - -/* TODO -{ - // oneway functions aren't supported - type illformed_3 = shared () -> (); -}; -*/ - -{ - actor class BadActorClass (x : Int) { }; // no actor classes -}; - -{ - let bad_non_top_actor : actor {} = if true actor {} else actor {}; -}; - -{ - let bad_nested_actor = { let _ = actor {}; ()}; -}; - - -actor BadSecondActor { }; - -// async functions not supported (inference mode) -func implicit_async() : async () { }; - -// anonymous shared functions not supported (inference and checking mode) -let _ = shared func() : async () { }; -(shared func() : async () { }) : shared () -> async (); diff --git a/test/run.sh b/test/run.sh index 79b15a90705..1dc04b44057 100755 --- a/test/run.sh +++ b/test/run.sh @@ -7,8 +7,7 @@ # Options: # # -a: Update the files in ok/ -# -2: Use IC API -# -3: Use Stub API +# -d: Run on in drun (or, if not possible, in stub) # -t: Only typecheck # -s: Be silent in sunny-day execution # -i: Only check mo to idl generation @@ -21,10 +20,9 @@ function realpath() { ACCEPT=no -API=wasi +DRUN=no IDL=no RELEASE=no -EXTRA_MOC_FLAGS= MOC=${MOC:-$(realpath $(dirname $0)/../src/moc)} MO_LD=${MO_LD:-$(realpath $(dirname $0)/../src/mo-ld)} DIDC=${DIDC:-$(realpath $(dirname $0)/../src/didc)} @@ -36,16 +34,13 @@ SKIP_RUNNING=${SKIP_RUNNING:-no} ONLY_TYPECHECK=no ECHO=echo -while getopts "a23stir" o; do +while getopts "adstir" o; do case "${o}" in a) ACCEPT=yes ;; - 2) - API=ic - ;; - 3) - API=stub + d) + DRUN=yes ;; s) ECHO=true @@ -62,9 +57,6 @@ while getopts "a23stir" o; do esac done -if [ $API = "wasm" ]; then EXTRA_MOC_FLAGS=-no-system-api; fi -if [ $API = "wasi" ]; then EXTRA_MOC_FLAGS=-wasi-system-api; fi -if [ $API = "stub" ]; then EXTRA_MOC_FLAGS=-stub-system-api; fi if [ $RELEASE = "yes" ]; then MOC_FLAGS=--release; fi shift $((OPTIND-1)) @@ -88,6 +80,7 @@ function normalize () { sed 's,/tmp/.*ic.[^/]*,/tmp/ic.XXX,g' | sed 's,/build/.*ic.[^/]*,/tmp/ic.XXX,g' | sed 's/^.*run-dfinity\/\.\.\/drun.sh: line/drun.sh: line/g' | + sed 's,\([a-zA-Z0-9.-]*\).mo.mangled,\1.mo,g' | sed 's/trap at 0x[a-f0-9]*/trap at 0x___:/g' | sed 's/source location: @[a-f0-9]*/source location: @___:/g' | sed 's/Ignore Diff:.*/Ignore Diff: (ignored)/ig' | @@ -104,7 +97,7 @@ function run () { local ext="$1" shift - if grep -q "^//SKIP $ext" $file; then return; fi + if grep -q "^//SKIP $ext" $file; then return 1; fi $ECHO -n " [$ext]" "$@" >& $out/$base.$ext @@ -164,14 +157,14 @@ do if [ ${file: -3} == ".mo" ] then # Typecheck - run tc $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS --check $base.mo + run tc $MOC $MOC_FLAGS --check $base.mo tc_succeeded=$? if [ "$tc_succeeded" -eq 0 -a "$ONLY_TYPECHECK" = "no" ] then if [ $IDL = 'yes' ] then - run idl $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS --idl $base.mo -o $out/$base.did + run idl $MOC $MOC_FLAGS --idl $base.mo -o $out/$base.did idl_succeeded=$? normalize $out/$base.did @@ -185,10 +178,10 @@ do if [ "$SKIP_RUNNING" != yes ] then # Interpret - run run $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS --hide-warnings -r $base.mo + run run $MOC $MOC_FLAGS --hide-warnings -r $base.mo # Interpret IR without lowering - run run-ir $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS --hide-warnings -r -iR -no-async -no-await $base.mo + run run-ir $MOC $MOC_FLAGS --hide-warnings -r -iR -no-async -no-await $base.mo # Diff interpretations without/with lowering if [ -e $out/$base.run -a -e $out/$base.run-ir ] @@ -198,7 +191,7 @@ do fi # Interpret IR with lowering - run run-low $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS --hide-warnings -r -iR $base.mo + run run-low $MOC $MOC_FLAGS --hide-warnings -r -iR $base.mo # Diff interpretations without/with lowering if [ -e $out/$base.run -a -e $out/$base.run-low ] @@ -209,8 +202,38 @@ do fi + # Mangle for compilation: + # The compilation targets do not support self-calls during canister + # installation, so this replaces + # + # actor a { … } + # a.go(); //CALL … + # + # with + # + # actor a { … } + # //CALL … + # + # which actually works on the IC platform + + # needs to be in the same directory to preserve relative paths :-( + mangled=$base.mo.mangled + sed 's,^.*//OR-CALL,//CALL,g' $base.mo > $mangled + + # Compile - run comp $MOC $MOC_FLAGS $EXTRA_MOC_FLAGS --hide-warnings --map -c $base.mo -o $out/$base.wasm + if [ $DRUN = no ] + then + run comp $MOC $MOC_FLAGS -wasi-system-api --hide-warnings --map -c $mangled -o $out/$base.wasm + else + run comp $MOC $MOC_FLAGS --hide-warnings --map -c $mangled -o $out/$base.wasm + can_use_drun=$? + + if [ "$can_use_drun" -ne 0 ]; + then + run comp-stub $MOC $MOC_FLAGS -stub-system-api --hide-warnings --map -c $mangled -o $out/$base.wasm + fi + fi if [ -e $out/$base.wasm ] then @@ -220,11 +243,11 @@ do # Check filecheck if [ "$SKIP_RUNNING" != yes ] then - if grep -F -q CHECK $base.mo + if grep -F -q CHECK $mangled then $ECHO -n " [FileCheck]" wasm2wat --no-check --enable-multi-value $out/$base.wasm > $out/$base.wat - cat $out/$base.wat | FileCheck $base.mo > $out/$base.filecheck 2>&1 + cat $out/$base.wat | FileCheck $mangled > $out/$base.filecheck 2>&1 diff_files="$diff_files $base.filecheck" fi fi @@ -232,21 +255,19 @@ do # Run compiled program if [ "$SKIP_RUNNING" != yes ] then - if [ $API = ic ] - then - run drun-run $DRUN_WRAPPER $out/$base.wasm $base.mo - elif [ $API = stub ] - then - DRUN=$IC_STUB_RUN run ic-stub-run $DRUN_WRAPPER $out/$base.wasm $base.mo - elif [ $API = wasi ] + if [ $DRUN = no ] then run wasm-run $WASMTIME --disable-cache $out/$base.wasm + elif [ "$can_use_drun" -eq 0 ] + then + run drun-run $DRUN_WRAPPER $out/$base.wasm $mangled else - echo "Unkonwn API $API" - exit 1 + DRUN=$IC_STUB_RUN \ + run ic-stub-run $DRUN_WRAPPER $out/$base.wasm $mangled fi fi fi + rm -f $mangled fi fi elif [ ${file: -3} == ".sh" ] diff --git a/test/run-drun/arity_bug.mo b/test/run/arity_bug.mo similarity index 100% rename from test/run-drun/arity_bug.mo rename to test/run/arity_bug.mo diff --git a/test/run-drun/modexp1.mo b/test/run/modexp1.mo similarity index 100% rename from test/run-drun/modexp1.mo rename to test/run/modexp1.mo diff --git a/test/run-drun/modexp2.mo b/test/run/modexp2.mo similarity index 100% rename from test/run-drun/modexp2.mo rename to test/run/modexp2.mo diff --git a/test/run-drun/modexp3.mo b/test/run/modexp3.mo similarity index 100% rename from test/run-drun/modexp3.mo rename to test/run/modexp3.mo diff --git a/test/run-drun/modexp4.mo b/test/run/modexp4.mo similarity index 100% rename from test/run-drun/modexp4.mo rename to test/run/modexp4.mo diff --git a/test/run-drun/modules-bwd.mo b/test/run/modules-bwd.mo similarity index 100% rename from test/run-drun/modules-bwd.mo rename to test/run/modules-bwd.mo diff --git a/test/run/ok/show.run-ir.ok b/test/run/ok/show.run-ir.ok new file mode 100644 index 00000000000..7f4f28dc1ee --- /dev/null +++ b/test/run/ok/show.run-ir.ok @@ -0,0 +1,35 @@ +true +false +-42_000_000_000_000 +-42_000_000 +-42_000 +-42 +0 +0 ++42 ++42_000 ++42_000_000 ++420_000_000_000_000 +0 +42 +42_000 +42_000_000 +420_000_000_000_000 +(42, -42, ()) +("Foobar", null, null, ?23) +[] +[1, 2, 3] +[var] +[var 1, 2, 3] +{bar = true; foo = +42} +#foo +#bar(1, 2) +#bar({}) +#bar([]) +#bar(42) +#bar(-42) +#foo(+42) +0x2A +42 ++42 +-42 diff --git a/test/run/ok/show.run-low.ok b/test/run/ok/show.run-low.ok new file mode 100644 index 00000000000..7f4f28dc1ee --- /dev/null +++ b/test/run/ok/show.run-low.ok @@ -0,0 +1,35 @@ +true +false +-42_000_000_000_000 +-42_000_000 +-42_000 +-42 +0 +0 ++42 ++42_000 ++42_000_000 ++420_000_000_000_000 +0 +42 +42_000 +42_000_000 +420_000_000_000_000 +(42, -42, ()) +("Foobar", null, null, ?23) +[] +[1, 2, 3] +[var] +[var 1, 2, 3] +{bar = true; foo = +42} +#foo +#bar(1, 2) +#bar({}) +#bar([]) +#bar(42) +#bar(-42) +#foo(+42) +0x2A +42 ++42 +-42 diff --git a/test/run/ok/show.run.ok b/test/run/ok/show.run.ok new file mode 100644 index 00000000000..7f4f28dc1ee --- /dev/null +++ b/test/run/ok/show.run.ok @@ -0,0 +1,35 @@ +true +false +-42_000_000_000_000 +-42_000_000 +-42_000 +-42 +0 +0 ++42 ++42_000 ++42_000_000 ++420_000_000_000_000 +0 +42 +42_000 +42_000_000 +420_000_000_000_000 +(42, -42, ()) +("Foobar", null, null, ?23) +[] +[1, 2, 3] +[var] +[var 1, 2, 3] +{bar = true; foo = +42} +#foo +#bar(1, 2) +#bar({}) +#bar([]) +#bar(42) +#bar(-42) +#foo(+42) +0x2A +42 ++42 +-42 diff --git a/test/run/ok/show.wasm-run.ok b/test/run/ok/show.wasm-run.ok new file mode 100644 index 00000000000..7f4f28dc1ee --- /dev/null +++ b/test/run/ok/show.wasm-run.ok @@ -0,0 +1,35 @@ +true +false +-42_000_000_000_000 +-42_000_000 +-42_000 +-42 +0 +0 ++42 ++42_000 ++42_000_000 ++420_000_000_000_000 +0 +42 +42_000 +42_000_000 +420_000_000_000_000 +(42, -42, ()) +("Foobar", null, null, ?23) +[] +[1, 2, 3] +[var] +[var 1, 2, 3] +{bar = true; foo = +42} +#foo +#bar(1, 2) +#bar({}) +#bar([]) +#bar(42) +#bar(-42) +#foo(+42) +0x2A +42 ++42 +-42 diff --git a/test/run/ok/text-iter.run-ir.ok b/test/run/ok/text-iter.run-ir.ok new file mode 100644 index 00000000000..a2ae9467155 --- /dev/null +++ b/test/run/ok/text-iter.run-ir.ok @@ -0,0 +1,229 @@ +via `debugPrint`: +hello world! + +via iteration and `debugPrintChar`: #1 +h +e +l +l +o + +w +o +r +l +d +! + +via iteration and `debugPrintChar`: #2 +1 +: +' +h +' + +2 +: +' +e +' + +3 +: +' +l +' + +4 +: +' +l +' + +5 +: +' +o +' + +6 +: +' + +' + +7 +: +' +w +' + +8 +: +' +o +' + +9 +: +' +r +' + +10 +: +' +l +' + +11 +: +' +d +' + +12 +: +' +! +' + + +via iteration and `debugPrintChar` (Unicode): #3 +1 +: +' +П +' + +2 +: +' +р +' + +3 +: +' +и +' + +4 +: +' +в +' + +5 +: +' +е +' + +6 +: +' +т +' + +7 +: +' +с +' + +8 +: +' +т +' + +9 +: +' +в +' + +10 +: +' +у +' + +11 +: +' +ю +' + +12 +: +' +, +' + +13 +: +' + +' + +14 +: +' +м +' + +15 +: +' +и +' + +16 +: +' +р +' + +17 +: +' +! +' + +18 +: +' + + +' + + +via iteration and `debugPrintChar` (Unicode): #4 +1 +: +' +🙈 +' + +2 +: +' +🎸 +' + +3 +: +' +😋 +' + + +Приветствую, мир! + + +П + +🙈 + diff --git a/test/run/ok/text-iter.run-low.ok b/test/run/ok/text-iter.run-low.ok new file mode 100644 index 00000000000..a2ae9467155 --- /dev/null +++ b/test/run/ok/text-iter.run-low.ok @@ -0,0 +1,229 @@ +via `debugPrint`: +hello world! + +via iteration and `debugPrintChar`: #1 +h +e +l +l +o + +w +o +r +l +d +! + +via iteration and `debugPrintChar`: #2 +1 +: +' +h +' + +2 +: +' +e +' + +3 +: +' +l +' + +4 +: +' +l +' + +5 +: +' +o +' + +6 +: +' + +' + +7 +: +' +w +' + +8 +: +' +o +' + +9 +: +' +r +' + +10 +: +' +l +' + +11 +: +' +d +' + +12 +: +' +! +' + + +via iteration and `debugPrintChar` (Unicode): #3 +1 +: +' +П +' + +2 +: +' +р +' + +3 +: +' +и +' + +4 +: +' +в +' + +5 +: +' +е +' + +6 +: +' +т +' + +7 +: +' +с +' + +8 +: +' +т +' + +9 +: +' +в +' + +10 +: +' +у +' + +11 +: +' +ю +' + +12 +: +' +, +' + +13 +: +' + +' + +14 +: +' +м +' + +15 +: +' +и +' + +16 +: +' +р +' + +17 +: +' +! +' + +18 +: +' + + +' + + +via iteration and `debugPrintChar` (Unicode): #4 +1 +: +' +🙈 +' + +2 +: +' +🎸 +' + +3 +: +' +😋 +' + + +Приветствую, мир! + + +П + +🙈 + diff --git a/test/run/ok/text-iter.run.ok b/test/run/ok/text-iter.run.ok new file mode 100644 index 00000000000..a2ae9467155 --- /dev/null +++ b/test/run/ok/text-iter.run.ok @@ -0,0 +1,229 @@ +via `debugPrint`: +hello world! + +via iteration and `debugPrintChar`: #1 +h +e +l +l +o + +w +o +r +l +d +! + +via iteration and `debugPrintChar`: #2 +1 +: +' +h +' + +2 +: +' +e +' + +3 +: +' +l +' + +4 +: +' +l +' + +5 +: +' +o +' + +6 +: +' + +' + +7 +: +' +w +' + +8 +: +' +o +' + +9 +: +' +r +' + +10 +: +' +l +' + +11 +: +' +d +' + +12 +: +' +! +' + + +via iteration and `debugPrintChar` (Unicode): #3 +1 +: +' +П +' + +2 +: +' +р +' + +3 +: +' +и +' + +4 +: +' +в +' + +5 +: +' +е +' + +6 +: +' +т +' + +7 +: +' +с +' + +8 +: +' +т +' + +9 +: +' +в +' + +10 +: +' +у +' + +11 +: +' +ю +' + +12 +: +' +, +' + +13 +: +' + +' + +14 +: +' +м +' + +15 +: +' +и +' + +16 +: +' +р +' + +17 +: +' +! +' + +18 +: +' + + +' + + +via iteration and `debugPrintChar` (Unicode): #4 +1 +: +' +🙈 +' + +2 +: +' +🎸 +' + +3 +: +' +😋 +' + + +Приветствую, мир! + + +П + +🙈 + diff --git a/test/run/ok/text-iter.wasm-run.ok b/test/run/ok/text-iter.wasm-run.ok new file mode 100644 index 00000000000..a2ae9467155 --- /dev/null +++ b/test/run/ok/text-iter.wasm-run.ok @@ -0,0 +1,229 @@ +via `debugPrint`: +hello world! + +via iteration and `debugPrintChar`: #1 +h +e +l +l +o + +w +o +r +l +d +! + +via iteration and `debugPrintChar`: #2 +1 +: +' +h +' + +2 +: +' +e +' + +3 +: +' +l +' + +4 +: +' +l +' + +5 +: +' +o +' + +6 +: +' + +' + +7 +: +' +w +' + +8 +: +' +o +' + +9 +: +' +r +' + +10 +: +' +l +' + +11 +: +' +d +' + +12 +: +' +! +' + + +via iteration and `debugPrintChar` (Unicode): #3 +1 +: +' +П +' + +2 +: +' +р +' + +3 +: +' +и +' + +4 +: +' +в +' + +5 +: +' +е +' + +6 +: +' +т +' + +7 +: +' +с +' + +8 +: +' +т +' + +9 +: +' +в +' + +10 +: +' +у +' + +11 +: +' +ю +' + +12 +: +' +, +' + +13 +: +' + +' + +14 +: +' +м +' + +15 +: +' +и +' + +16 +: +' +р +' + +17 +: +' +! +' + +18 +: +' + + +' + + +via iteration and `debugPrintChar` (Unicode): #4 +1 +: +' +🙈 +' + +2 +: +' +🎸 +' + +3 +: +' +😋 +' + + +Приветствую, мир! + + +П + +🙈 + diff --git a/test/run/show.mo b/test/run/show.mo new file mode 100644 index 00000000000..88b0131995e --- /dev/null +++ b/test/run/show.mo @@ -0,0 +1,36 @@ +debugPrint(debug_show (true)); +debugPrint(debug_show (false)); +debugPrint(debug_show (-42000000000000)); +debugPrint(debug_show (-42000000)); +debugPrint(debug_show (-42000)); +debugPrint(debug_show (-42)); +debugPrint(debug_show (-0)); +debugPrint(debug_show (+0)); +debugPrint(debug_show (+42)); +debugPrint(debug_show (+42000)); +debugPrint(debug_show (+42000000)); +debugPrint(debug_show (+420000000000000)); +debugPrint(debug_show (0)); +debugPrint(debug_show (42)); +debugPrint(debug_show (42000)); +debugPrint(debug_show (42000000)); +debugPrint(debug_show (420000000000000)); +debugPrint(debug_show (42,-42,())); +debugPrint(debug_show ("Foobar", null, null, ?23)); +debugPrint(debug_show ([])); +debugPrint(debug_show ([1,2,3])); +debugPrint(debug_show ([var])); +debugPrint(debug_show ([var 1,2,3])); +class Foo() { public let foo : Int = 42; public var bar : Bool = true ; let hidden = [1,2] }; +debugPrint(debug_show (Foo())); +debugPrint(debug_show (#foo ())); +debugPrint(debug_show (#bar (1, 2))); +debugPrint(debug_show (#bar {})); +debugPrint(debug_show (#bar ([]))); +debugPrint(debug_show (#bar 42)); +debugPrint(debug_show (#bar (-42))); +debugPrint(debug_show (#foo 42 : {#foo : Int; #bar : Text})); +debugPrint(debug_show (42 : Word16)); +debugPrint(debug_show (42 : Nat8)); +debugPrint(debug_show (42 : Int32)); +debugPrint(debug_show (intToInt64 (-42))); diff --git a/test/run/text-iter.mo b/test/run/text-iter.mo new file mode 100644 index 00000000000..e2ce9e9ce45 --- /dev/null +++ b/test/run/text-iter.mo @@ -0,0 +1,69 @@ +let s = "hello world!"; + +debugPrint "via `debugPrint`:"; +debugPrint s; +debugPrint ""; + +debugPrint "via iteration and `debugPrintChar`: #1"; +for (a in s.chars()) { + debugPrintChar a; +}; +debugPrint ""; + +debugPrint "via iteration and `debugPrintChar`: #2"; +var x = 0; +for (a in s.chars()) { + x += 1; + debugPrintNat x; + debugPrint ":"; + debugPrintChar '\''; + debugPrintChar a; + debugPrintChar '\''; + debugPrint " "; +}; +debugPrint ""; + +let russian = "Приветствую, мир!\n"; +assert(russian.len() == 18); + +debugPrint "via iteration and `debugPrintChar` (Unicode): #3"; +x := 0; +for (a in russian.chars()) { + x += 1; + debugPrintNat x; + debugPrint ":"; + debugPrintChar '\''; + debugPrintChar a; + debugPrintChar '\''; + debugPrint " "; +}; +debugPrint ""; +assert(x == 18); + +let emojis = "🙈🎸😋"; +assert(emojis.len() == 3); + +debugPrint "via iteration and `debugPrintChar` (Unicode): #4"; +x := 0; +for (a in emojis.chars()) { + x += 1; + debugPrintNat x; + debugPrint ":"; + debugPrintChar '\''; + debugPrintChar a; + debugPrintChar '\''; + debugPrint " "; +}; +debugPrint ""; +assert(x == 3); + +debugPrint russian; debugPrint ""; +switch (russian.chars().next()) { + case (?c) { debugPrintChar c; debugPrint "" }; + case _ {}; +}; + +switch (emojis.chars().next()) { + case (?c) { assert (c == '\u{1f648}'); debugPrintChar c; debugPrint "" }; + case _ {}; +}; From e63033bddfdc99ede49507625aeb961d0e9a523c Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 29 Nov 2019 18:52:30 +0100 Subject: [PATCH 0742/1176] Test that a throw in a oneway does not trap (#957) --- src/codegen/compile.ml | 5 +---- test/run-drun/ok/oneway-throw.comp.ok | 4 ++++ test/run-drun/ok/oneway-throw.comp.ret.ok | 1 + test/run-drun/ok/oneway-throw.ic-stub-run.ok | 10 ++++++++++ test/run-drun/ok/oneway-throw.run-ir.ok | 4 ++++ test/run-drun/ok/oneway-throw.run-low.ok | 4 ++++ test/run-drun/ok/oneway-throw.run.ok | 4 ++++ test/run-drun/oneway-throw.mo | 20 ++++++++++++++++++++ 8 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 test/run-drun/ok/oneway-throw.comp.ok create mode 100644 test/run-drun/ok/oneway-throw.comp.ret.ok create mode 100644 test/run-drun/ok/oneway-throw.ic-stub-run.ok create mode 100644 test/run-drun/ok/oneway-throw.run-ir.ok create mode 100644 test/run-drun/ok/oneway-throw.run-low.ok create mode 100644 test/run-drun/ok/oneway-throw.run.ok create mode 100644 test/run-drun/oneway-throw.mo diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 5edb036c736..aaa5d8e2f4f 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -3069,11 +3069,8 @@ module Dfinity = struct let reject env arg_instrs = match E.mode env with | Flags.ICMode | Flags.StubMode -> - let (set_text, get_text) = new_local env "text" in arg_instrs ^^ - set_text ^^ - get_text ^^ Blob.payload_ptr_unskewed ^^ - get_text ^^ Heap.load_field (Blob.len_field) ^^ + Blob.as_ptr_len env ^^ begin match E.mode env with | Flags.ICMode -> system_call env "msg" "reject" | Flags.StubMode -> system_call env "ic0" "msg_reject" diff --git a/test/run-drun/ok/oneway-throw.comp.ok b/test/run-drun/ok/oneway-throw.comp.ok new file mode 100644 index 00000000000..9f4abefb861 --- /dev/null +++ b/test/run-drun/ok/oneway-throw.comp.ok @@ -0,0 +1,4 @@ +oneway-throw.mo:14.5-14.11: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +oneway-throw.mo:15.11-15.15: type error, calling a shared function not yet supported + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/oneway-throw.comp.ret.ok b/test/run-drun/ok/oneway-throw.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/oneway-throw.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-drun/ok/oneway-throw.ic-stub-run.ok b/test/run-drun/ok/oneway-throw.ic-stub-run.ok new file mode 100644 index 00000000000..012baa1ee18 --- /dev/null +++ b/test/run-drun/ok/oneway-throw.ic-stub-run.ok @@ -0,0 +1,10 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ update go(0x4449444c0000) +go1 +throws() +ping() +go2 +← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/oneway-throw.run-ir.ok b/test/run-drun/ok/oneway-throw.run-ir.ok new file mode 100644 index 00000000000..29baf3028ce --- /dev/null +++ b/test/run-drun/ok/oneway-throw.run-ir.ok @@ -0,0 +1,4 @@ +go1 +throws() +ping() +go2 diff --git a/test/run-drun/ok/oneway-throw.run-low.ok b/test/run-drun/ok/oneway-throw.run-low.ok new file mode 100644 index 00000000000..29baf3028ce --- /dev/null +++ b/test/run-drun/ok/oneway-throw.run-low.ok @@ -0,0 +1,4 @@ +go1 +throws() +ping() +go2 diff --git a/test/run-drun/ok/oneway-throw.run.ok b/test/run-drun/ok/oneway-throw.run.ok new file mode 100644 index 00000000000..29baf3028ce --- /dev/null +++ b/test/run-drun/ok/oneway-throw.run.ok @@ -0,0 +1,4 @@ +go1 +throws() +ping() +go2 diff --git a/test/run-drun/oneway-throw.mo b/test/run-drun/oneway-throw.mo new file mode 100644 index 00000000000..3a6eadd4329 --- /dev/null +++ b/test/run-drun/oneway-throw.mo @@ -0,0 +1,20 @@ +actor a { + var committed = false; + public func throws() : () = ignore async { + debugPrint "throws()"; + committed := true; + throw (error("ignored")); + debugPrint "unreachable"; + }; + public func ping() : async () { + debugPrint "ping()"; + }; + public func go() = ignore async { + debugPrint "go1"; + throws(); + await ping(); // in-order delivery guarantees that throw ran + debugPrint "go2"; + assert(committed); + }; +}; +a.go(); //OR-CALL ingress go "DIDL\x00\x00" From e5d8ccde3f13b2f3bddbfa42df9e34178cab31de Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 29 Nov 2019 19:01:10 +0100 Subject: [PATCH 0743/1176] gitSource.nix: Use cleanSourceWith (#952) following the example in https://github.com/dfinity-lab/dfinity/commit/4f2d90887218b1a243f3f21c74b0d2d967b748ad This changes changes the derivations used by `cabal2nix` to only contain the `.cabal` files. Which is a good thing. --- nix/gitSource.nix | 13 ++++++++----- test/.stderr | 0 2 files changed, 8 insertions(+), 5 deletions(-) delete mode 100644 test/.stderr diff --git a/nix/gitSource.nix b/nix/gitSource.nix index 2a652673a27..1983d838a06 100644 --- a/nix/gitSource.nix +++ b/nix/gitSource.nix @@ -54,10 +54,13 @@ let not_dot_git = p: t: !(has_suffix ".git" p); in +# unfortunately this is not completely self-contained, +# we needs pkgs this to get git and lib.cleanSourceWith +let nixpkgs = (import ./nixpkgs.nix).nixpkgs {}; in + if !isHydra && builtins.pathExists ../.git then let - nixpkgs = (import ./nixpkgs.nix).nixpkgs {}; git_dir = if builtins.pathExists ../.git/index @@ -85,9 +88,9 @@ then filter = filter_from_list ../. whitelist; in - subdir: path { + subdir: nixpkgs.lib.cleanSourceWith { name = baseNameOf (toString subdir); - path = if isString subdir then (../. + "/${subdir}") else subdir; + src = if isString subdir then (../. + "/${subdir}") else subdir; filter = filter; } @@ -100,8 +103,8 @@ else warn_unless (isHydra || has_prefix "/nix/store" (toString ../.)) "gitSource.nix: ${toString ../.} does not seem to be a git repository,\nassuming it is a clean checkout." - (subdir: path { + (subdir: nixpkgs.lib.cleanSourceWith { name = baseNameOf (toString subdir); - path = if isString subdir then (../. + "/${subdir}") else subdir; + src = if isString subdir then (../. + "/${subdir}") else subdir; filter = not_dot_git; }) diff --git a/test/.stderr b/test/.stderr deleted file mode 100644 index e69de29bb2d..00000000000 From 43eb2f44c0c51d909251411609c4de33eb0dbbd5 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 29 Nov 2019 19:13:38 +0100 Subject: [PATCH 0744/1176] Make test/repl self-contained (#953) by copying `type-lub.mo`, but probably fine. --- test/repl/lib/type-lub.mo | 136 +++++++++++++++++++++++++++++++++++++ test/repl/type-lub-repl.sh | 2 +- 2 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 test/repl/lib/type-lub.mo diff --git a/test/repl/lib/type-lub.mo b/test/repl/lib/type-lub.mo new file mode 100644 index 00000000000..ede56742f62 --- /dev/null +++ b/test/repl/lib/type-lub.mo @@ -0,0 +1,136 @@ +let opts = [null, ?42, ?-25]; +let nulls = [null, null]; + +let incompatible_objs = [{a = 42}, {b = 42}]; +let objs = [{a = 42}, {b = 42; a = 1}, {a = -25}]; + +let tups = [(12, -1), (-42, 25)]; +let tup1s = [(-1,), 25]; + +let arrs = [[-42], [25]]; + +let incompatible_funcs = [ func (a : [Int]) : Nat = a.len() + , func (a : ()) : Int = -42 + ]; + +let poly_funcs = [ func (a : [Int]) : Nat = a.len() + , func (a : [Nat]) : Int = -42 + ]; + +let poly_funcs2 = [ func (a : [Int]) : Nat = a.len() + , func (a : [Nat]) : Int = -42 + ]; + +let poly_funcs3 = [ func (as : [A], b : B) : A = as[0] + , func (bs : [B], a : A) : B = bs[0] + ]; + +let poly_funcs4 = [ func (as : [A], b : B) : A = as[0] + , func (bs : [B], a : A) : B = bs[0] + ]; + +let funcs = [ func (a : [Int]) : Nat = a.len() + , func (a : [Nat]) : Int = -42 + ]; + +let variant_funcs = [ func (a : {#foo; #bar}) { switch a { case (#foo) (); case (#bar) () } } + , func (a : {#baz; #bar}) { switch a { case (#baz) (); case (#bar) () } } + ]; + +// TODO(gabor), mutable arrays +let mut_arrs = [[var 42], [var 25], [77]]; // boring + +// TODO(gabor), mutable fields, see fail/type-inference.mo:13 + +let sh : Any = 42; +let shareds = [sh, 77, [1, 2, 3]]; +let shared2s = [77, [1, 2, 3], sh]; + +let shared_funcs = [ func (a : Int) : Int = a + , func (a : Nat) : Nat = 42 + ]; + +type C = async(?Int); +type D = async(?Nat); + +func c0(c : C, d : D) : [C] { ignore([c, d]); [c, d] }; +let c1s = [async ?4, async ?-42]; + + +// recursive objects + +// { need global types due to https://dfinity.atlassian.net/browse/AST-34 +type A = {x : A}; +type B = {x : B}; + +func f(v : {x : {x : B}; b : B}, x : A, y : B, z : {x : B; a : A}) : [A] { ignore([v, x, y, z]); [v, x, y, z] }; +// }; + +// { +type A1 = {x : B1}; +type B1 = {x : A1}; + +func f1(x : A1, y : B1) : [A1] { ignore([x, y]); [x, y] }; +// }; + +type O = ?O; +type P = ?P; + +type Q = ?R; +type R = ?S; +type S = ?Q; + +func g(o : O, p : P, q : Q, r : R) : [O] { ignore([o, p, q, r]); [o, p, q, r] }; + +// example from https://dfinity.atlassian.net/browse/AST-83 + +type Foo = ?(Foo); +ignore (if true (null : Foo) else (null : Foo)); + + +type U = { #a : U; #b : Int }; +type V = { #a : V; #b : Nat }; + +func v0(u : U, v : V, w : { #a : { #a : V; #b : Nat }; #b : Nat }) : [U] { ignore([u, v, w]); [u, v, w] }; + + +type G = (Nat, ?G); +type H = (Int, ?H); + +func g0(g : G, h : H) : [H] { ignore([g, h]); [g, h] }; + + +type K = [K]; +type L = [L]; + +func k0(k : K, l : L) : [L] { ignore([k, l]); [k, l] }; + + +type K1 = [?(Nat, K1)]; +type L1 = [?(Int, L1)]; + +func k1(k : K1, l : L1) : [L1] { ignore([k, l]); [k, l] }; + + +/* +type M = [var ?M]; +type N = [?N]; + +func m0(m : M, n : N) : [M] { ignore([m, n]); [m, n] }; +*/ + +type E = Int -> E; +type F = Nat -> F; + +func f0(e : E, f : F) : [F] { ignore([e, f]); [e, f] }; + +type E1 = E1 -> E1; +type F1 = F1 -> F1; + +func f12(e : E1, f : F1) : [F1] { ignore([e, f]); [e, f] }; + +type E2 = F2 -> E2; +type F2 = E2 -> F2; + +func f2(e : E2, f : F2) : [F2] { ignore([e, f]); [e, f] }; + diff --git a/test/repl/type-lub-repl.sh b/test/repl/type-lub-repl.sh index 2d5167ef991..e16082189f2 100755 --- a/test/repl/type-lub-repl.sh +++ b/test/repl/type-lub-repl.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # Tests that correct lub types are inferred when values appear in arrays -${MOC:-$(dirname "$BASH_SOURCE")/../../src/moc} -i ../run-drun/type-lub.mo <<__END__ +${MOC:-$(dirname "$BASH_SOURCE")/../../src/moc} -i lib/type-lub.mo <<__END__ opts; nulls; incompatible_objs; From 8de99afeae26b7fcd75fd348437fa8ce437bc965 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 29 Nov 2019 19:22:37 +0100 Subject: [PATCH 0745/1176] Implement updated data format for IDL references (#949) as specified in https://github.com/dfinity-lab/motoko/pull/920 --- src/codegen/compile.ml | 116 ++++++++++++++++---------- test/run-drun/ok/idl-func.drun-run.ok | 2 +- 2 files changed, 75 insertions(+), 43 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index aaa5d8e2f4f..7b509f8e842 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -3331,19 +3331,6 @@ module Serialization = struct (fun (h1,_) (h2,_) -> Lib.Uint32.compare h1 h2) (List.map (fun f -> (Idllib.Escape.unescape_hash f.Type.lab, f)) fs) - (* The code below does not work on all Motoko types, but only certain “raw - types”. In particular, type definitions have to be removed (using Type.normalize). - But also, at least for now, actor and function references are represented - as data, https://github.com/dfinity-lab/motoko/pull/883 - *) - let raw_type env : Type.typ -> Type.typ = fun t -> - let open Type in - match normalize t with - | Obj (Actor, _) -> Prim Blob - | Func _ -> Tup [Prim Blob; Prim Text] - | t -> t - - (* The IDL serialization prefaces the data with a type description. We can statically create the type description in Ocaml code, store it in the program, and just copy it to the beginning of the message. @@ -3383,7 +3370,7 @@ module Serialization = struct let typs = ref [] in let idx = ref TM.empty in let rec go t = - let t = raw_type env t in + let t = Type.normalize t in if to_idl_prim t <> None then () else if TM.mem t !idx then () else begin idx := TM.add t (List.length !typs) !idx; @@ -3439,7 +3426,7 @@ module Serialization = struct (* Actual binary data *) let add_idx t = - let t = raw_type env t in + let t = Type.normalize t in match to_idl_prim t with | Some i -> add_sleb128 (-i) | None -> add_sleb128 (TM.find (normalize t) idx) in @@ -3464,8 +3451,6 @@ module Serialization = struct add_leb128_32 h; add_idx f.typ ) (sort_by_hash fs) - | Obj (Actor, fs) -> - assert false; | Array t -> add_sleb128 (-19); add_idx t | Opt t -> @@ -3477,8 +3462,22 @@ module Serialization = struct add_leb128_32 h; add_idx f.typ ) (sort_by_hash vs) - | Func _ -> - assert false + | Func (s, c, tbs, ts1, ts2) -> + assert (Type.is_shared_sort s); + add_sleb128 (-22); + add_leb128 (List.length ts1); + List.iter add_idx ts1; + add_leb128 (List.length ts2); + List.iter add_idx ts2; + add_leb128 0 (* no annotations *) + | Obj (Actor, fs) -> + add_sleb128 (-23); + add_leb128 (List.length fs); + List.iter (fun f -> + add_leb128 (String.length f.lab); + Buffer.add_string buf f.lab; + add_idx f.typ + ) fs | _ -> assert false in Buffer.add_string buf "DIDL"; @@ -3491,7 +3490,7 @@ module Serialization = struct (* Returns data (in bytes) and reference buffer size (in entries) needed *) let rec buffer_size env t = let open Type in - let t = raw_type env t in + let t = Type.normalize t in let name = "@buffer_size<" ^ typ_id t ^ ">" in Func.share_code1 env name ("x", I32Type) [I32Type; I32Type] (fun env get_x -> @@ -3569,8 +3568,13 @@ module Serialization = struct ) ( List.mapi (fun i (_h, f) -> (i,f)) (sort_by_hash vs) ) ( E.trap_with env "buffer_size: unexpected variant" ) - | (Func _ | Obj (Actor, _)) -> - assert false + | Func _ -> + inc_data_size (compile_unboxed_const 1l) ^^ (* one byte tag *) + get_x ^^ Arr.load_field 0l ^^ size env (Obj (Actor, [])) ^^ + get_x ^^ Arr.load_field 1l ^^ size env (Prim Text) + | Obj (Actor, _) -> + inc_data_size (compile_unboxed_const 1l) ^^ (* one byte tag *) + get_x ^^ size env (Prim Blob) | Non -> E.trap_with env "buffer_size called on value of type None" | _ -> todo "buffer_size" (Arrange_ir.typ t) G.nop @@ -3582,7 +3586,7 @@ module Serialization = struct (* Copies x to the data_buffer, storing references after ref_count entries in ref_base *) let rec serialize_go env t = let open Type in - let t = raw_type env t in + let t = Type.normalize t in let name = "@serialize_go<" ^ typ_id t ^ ">" in Func.share_code3 env name (("x", I32Type), ("data_buffer", I32Type), ("ref_buffer", I32Type)) [I32Type; I32Type] (fun env get_x get_data_buf get_ref_buf -> @@ -3615,7 +3619,6 @@ module Serialization = struct set_data_buf in - (* Now the actual serialization *) begin match t with @@ -3707,8 +3710,13 @@ module Serialization = struct get_len ^^ Heap.memcpy env ^^ get_len ^^ advance_data_buf - | (Func _ | Obj (Actor, _)) -> - assert false + | Func _ -> + write_byte (compile_unboxed_const 1l) ^^ + get_x ^^ Arr.load_field 0l ^^ write env (Obj (Actor, [])) ^^ + get_x ^^ Arr.load_field 1l ^^ write env (Prim Text) + | Obj (Actor, _) -> + write_byte (compile_unboxed_const 1l) ^^ + get_x ^^ write env (Prim Blob) | Non -> E.trap_with env "serializing value of type None" | _ -> todo "serialize" (Arrange_ir.typ t) G.nop @@ -3719,7 +3727,7 @@ module Serialization = struct let rec deserialize_go env t = let open Type in - let t = raw_type env t in + let t = Type.normalize t in let name = "@deserialize_go<" ^ typ_id t ^ ">" in Func.share_code4 env name (("data_buffer", I32Type), @@ -3749,6 +3757,23 @@ module Serialization = struct E.else_trap_with env ("IDL error: unexpected IDL type when parsing " ^ string_of_typ t) in + let read_byte_tagged = function + | [code0; code1] -> + ReadBuf.read_byte env get_data_buf ^^ + let (set_b, get_b) = new_local env "b" in + set_b ^^ + get_b ^^ + compile_eq_const 0l ^^ + G.if_ (ValBlockType (Some I32Type)) + begin code0 + end begin + get_b ^^ compile_eq_const 1l ^^ + E.else_trap_with env "IDL error: byte tag not 0 or 1" ^^ + code1 + end + | _ -> assert false; (* can be generalized later as needed *) + in + let read_blob validate = let (set_len, get_len) = new_local env "len" in let (set_x, get_x) = new_local env "x" in @@ -3764,6 +3789,13 @@ module Serialization = struct get_x in + let read_actor_data () = + read_byte_tagged + [ E.trap_with env "IDL error: unexpected actor reference" + ; read_blob false + ] + in + (* checks that idltyp is positive, looks it up in the table, updates the typ_buf, reads the type constructor index and traps if it is the wrong one. typ_buf left in place to read the type constructor arguments *) @@ -3924,19 +3956,10 @@ module Serialization = struct let (set_idltyp, get_idltyp) = new_local env "idltyp" in with_composite_typ (-18l) (fun get_typ_buf -> ReadBuf.read_sleb128 env get_typ_buf ^^ set_idltyp ^^ - ReadBuf.read_byte env get_data_buf ^^ - let (set_b, get_b) = new_local env "b" in - set_b ^^ - get_b ^^ - compile_eq_const 0l ^^ - G.if_ (ValBlockType (Some I32Type)) - begin - Opt.null - end begin - get_b ^^ compile_eq_const 1l ^^ - E.else_trap_with env "IDL error: opt tag not 0 or 1" ^^ - Opt.inject env (get_idltyp ^^ go env t) - end + read_byte_tagged + [ Opt.null + ; Opt.inject env (get_idltyp ^^ go env t) + ] ) end | Variant vs -> @@ -3973,8 +3996,17 @@ module Serialization = struct ( sort_by_hash vs ) ( E.trap_with env "IDL error: unexpected variant tag" ) ) - | (Func _ | Obj (Actor, _)) -> - assert false; + | Func _ -> + with_composite_typ (-22l) (fun _get_typ_buf -> + read_byte_tagged + [ E.trap_with env "IDL error: unexpected function reference" + ; read_actor_data () ^^ + read_blob true ^^ + Tuple.from_stack env 2 + ] + ); + | Obj (Actor, _) -> + with_composite_typ (-23l) (fun _get_typ_buf -> read_actor_data ()) | Non -> E.trap_with env "IDL error: deserializing value of type None" | _ -> todo_trap env "deserialize" (Arrange_ir.typ t) diff --git a/test/run-drun/ok/idl-func.drun-run.ok b/test/run-drun/ok/idl-func.drun-run.ok index a775313ab56..408aa441387 100644 --- a/test/run-drun/ok/idl-func.drun-run.ok +++ b/test/run-drun/ok/idl-func.drun-run.ok @@ -1,3 +1,3 @@ ingress(0) System -Ok: Payload: 0x4449444c036e016c02000201716d7b010000 +Ok: Payload: 0x4449444c026e016a017c010100010000 Ok: Payload: 0x4449444c0000 From fd4a379077670a8699313cff56d8dc509ab2545d Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 29 Nov 2019 19:58:31 +0100 Subject: [PATCH 0746/1176] Merge test/run-release into test/run (#955) with a new ``` +//MOC-FLAG --release ``` feature (may be handy for other things too). --- test/Makefile | 5 ---- test/run-release/Makefile | 12 --------- test/run.sh | 26 ++++++++----------- .../debug.mo => run/debug-release.mo} | 2 ++ .../ok/debug-release.run-ir.ok} | 0 .../ok/debug-release.run-low.ok} | 0 .../ok/debug-release.run.ok} | 0 .../ok/debug-release.wasm-run.ok} | 0 8 files changed, 13 insertions(+), 32 deletions(-) delete mode 100644 test/run-release/Makefile rename test/{run-release/debug.mo => run/debug-release.mo} (84%) rename test/{run-release/ok/debug.run-ir.ok => run/ok/debug-release.run-ir.ok} (100%) rename test/{run-release/ok/debug.run-low.ok => run/ok/debug-release.run-low.ok} (100%) rename test/{run-release/ok/debug.run.ok => run/ok/debug-release.run.ok} (100%) rename test/{run-release/ok/debug.wasm-run.ok => run/ok/debug-release.wasm-run.ok} (100%) diff --git a/test/Makefile b/test/Makefile index 558a137a001..d58ab8caf74 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,7 +1,6 @@ all: $(MAKE) -C fail $(MAKE) -C run - $(MAKE) -C run-release $(MAKE) -C run-drun $(MAKE) -C repl $(MAKE) -C ld @@ -14,7 +13,6 @@ MAKE_PAR := $(MAKE) --no-print-directory --load-average -j $(shell getconf _NPRO quick: $(MAKE_PAR) -C fail quick $(MAKE_PAR) -C run quick - $(MAKE_PAR) -C run-release quick $(MAKE_PAR) -C repl quick $(MAKE_PAR) -C ld quick $(MAKE_PAR) -C idl quick @@ -32,7 +30,6 @@ coverage: export SKIP_RUNNING=yes; \ $(MAKE) -C fail; \ $(MAKE) -C run; \ - $(MAKE) -C run-release; \ $(MAKE) -C run-drun; \ $(MAKE) -C repl; $(MAKE) -C ld || true @@ -42,7 +39,6 @@ coverage: accept: $(MAKE) -C fail accept $(MAKE) -C run accept - $(MAKE) -C run-release accept $(MAKE) -C run-drun accept $(MAKE) -C repl accept $(MAKE) -C ld accept @@ -54,7 +50,6 @@ accept: clean: $(MAKE) -C fail clean $(MAKE) -C run clean - $(MAKE) -C run-release clean $(MAKE) -C run-drun clean $(MAKE) -C repl clean $(MAKE) -C ld clean diff --git a/test/run-release/Makefile b/test/run-release/Makefile deleted file mode 100644 index b81927e20ed..00000000000 --- a/test/run-release/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -RUNFLAGS = -r - -all: - ../run.sh $(RUNFLAGS) *.mo - -accept: - ../run.sh $(RUNFLAGS) -a *.mo - -clean: - rm -rf _out - -include ../*.mk diff --git a/test/run.sh b/test/run.sh index 1dc04b44057..027f46bde7f 100755 --- a/test/run.sh +++ b/test/run.sh @@ -11,7 +11,6 @@ # -t: Only typecheck # -s: Be silent in sunny-day execution # -i: Only check mo to idl generation -# -r: Activate release mode (eliminate `debug` blocks) # function realpath() { @@ -22,7 +21,6 @@ function realpath() { ACCEPT=no DRUN=no IDL=no -RELEASE=no MOC=${MOC:-$(realpath $(dirname $0)/../src/moc)} MO_LD=${MO_LD:-$(realpath $(dirname $0)/../src/mo-ld)} DIDC=${DIDC:-$(realpath $(dirname $0)/../src/didc)} @@ -51,14 +49,9 @@ while getopts "adstir" o; do i) IDL=yes ;; - r) - RELEASE=yes - ;; esac done -if [ $RELEASE = "yes" ]; then MOC_FLAGS=--release; fi - shift $((OPTIND-1)) failures=no @@ -156,15 +149,18 @@ do if [ ${file: -3} == ".mo" ] then + # extra flags + moc_extra_flags="$(grep '//MOC-FLAG' $base.mo | cut -c11- | paste -sd' ')" + # Typecheck - run tc $MOC $MOC_FLAGS --check $base.mo + run tc $MOC $moc_extra_flags --check $base.mo tc_succeeded=$? if [ "$tc_succeeded" -eq 0 -a "$ONLY_TYPECHECK" = "no" ] then if [ $IDL = 'yes' ] then - run idl $MOC $MOC_FLAGS --idl $base.mo -o $out/$base.did + run idl $MOC $moc_extra_flags --idl $base.mo -o $out/$base.did idl_succeeded=$? normalize $out/$base.did @@ -178,10 +174,10 @@ do if [ "$SKIP_RUNNING" != yes ] then # Interpret - run run $MOC $MOC_FLAGS --hide-warnings -r $base.mo + run run $MOC $moc_extra_flags --hide-warnings -r $base.mo # Interpret IR without lowering - run run-ir $MOC $MOC_FLAGS --hide-warnings -r -iR -no-async -no-await $base.mo + run run-ir $MOC $moc_extra_flags --hide-warnings -r -iR -no-async -no-await $base.mo # Diff interpretations without/with lowering if [ -e $out/$base.run -a -e $out/$base.run-ir ] @@ -191,7 +187,7 @@ do fi # Interpret IR with lowering - run run-low $MOC $MOC_FLAGS --hide-warnings -r -iR $base.mo + run run-low $MOC $moc_extra_flags --hide-warnings -r -iR $base.mo # Diff interpretations without/with lowering if [ -e $out/$base.run -a -e $out/$base.run-low ] @@ -224,14 +220,14 @@ do # Compile if [ $DRUN = no ] then - run comp $MOC $MOC_FLAGS -wasi-system-api --hide-warnings --map -c $mangled -o $out/$base.wasm + run comp $MOC $moc_extra_flags -wasi-system-api --hide-warnings --map -c $mangled -o $out/$base.wasm else - run comp $MOC $MOC_FLAGS --hide-warnings --map -c $mangled -o $out/$base.wasm + run comp $MOC $moc_extra_flags --hide-warnings --map -c $mangled -o $out/$base.wasm can_use_drun=$? if [ "$can_use_drun" -ne 0 ]; then - run comp-stub $MOC $MOC_FLAGS -stub-system-api --hide-warnings --map -c $mangled -o $out/$base.wasm + run comp-stub $MOC $moc_extra_flags -stub-system-api --hide-warnings --map -c $mangled -o $out/$base.wasm fi fi diff --git a/test/run-release/debug.mo b/test/run/debug-release.mo similarity index 84% rename from test/run-release/debug.mo rename to test/run/debug-release.mo index 7a4417f2e9c..45b73ac9655 100644 --- a/test/run-release/debug.mo +++ b/test/run/debug-release.mo @@ -1,3 +1,5 @@ +//MOC-FLAG --release + debugPrint "This should appear"; debug { debugPrint "This shouldn't appear" }; debugPrint "This should appear too"; diff --git a/test/run-release/ok/debug.run-ir.ok b/test/run/ok/debug-release.run-ir.ok similarity index 100% rename from test/run-release/ok/debug.run-ir.ok rename to test/run/ok/debug-release.run-ir.ok diff --git a/test/run-release/ok/debug.run-low.ok b/test/run/ok/debug-release.run-low.ok similarity index 100% rename from test/run-release/ok/debug.run-low.ok rename to test/run/ok/debug-release.run-low.ok diff --git a/test/run-release/ok/debug.run.ok b/test/run/ok/debug-release.run.ok similarity index 100% rename from test/run-release/ok/debug.run.ok rename to test/run/ok/debug-release.run.ok diff --git a/test/run-release/ok/debug.wasm-run.ok b/test/run/ok/debug-release.wasm-run.ok similarity index 100% rename from test/run-release/ok/debug.wasm-run.ok rename to test/run/ok/debug-release.wasm-run.ok From 8b949dc33250b6e067c07b563e388c19e450c3c7 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Fri, 29 Nov 2019 18:58:55 +0000 Subject: [PATCH 0747/1176] adapt mo-idl and tests to scopes --- src/mo_idl/mo_to_idl.ml | 7 ++++++- test/mo-idl/counter.mo | 6 +++--- test/mo-idl/pa_cars.mo | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/mo_idl/mo_to_idl.ml b/src/mo_idl/mo_to_idl.ml index 339080821a8..b4787fb6c61 100644 --- a/src/mo_idl/mo_to_idl.ml +++ b/src/mo_idl/mo_to_idl.ml @@ -104,7 +104,12 @@ let rec typ vs t = | Obj (Module, _) -> assert false | Variant fs -> I.VariantT (List.map (field vs) fs) - | Func (Shared s, c, [], ts1, ts2) -> + | Func (Shared s, c, tbs, ts1, ts2) -> + let nons = List.map (fun _ -> Non) tbs in + let c, ts1, ts2 = + (map_control (open_ nons) c, + List.map (open_ nons) ts1, + List.map (open_ nons) ts2) in let t1 = args vs ts1 in (match ts2, c with | [], Returns -> I.FuncT ([I.Oneway @@ no_region], t1, []) diff --git a/test/mo-idl/counter.mo b/test/mo-idl/counter.mo index 636588fa7ed..5373aaf6aeb 100644 --- a/test/mo-idl/counter.mo +++ b/test/mo-idl/counter.mo @@ -15,7 +15,7 @@ actor class Counter(i : Int) { // Dummy functions to show intermediate value in trace. func show(note : Text, c : Int) {}; -func showAsync(note : Text, a : async Int) {}; +func showAsync<@>(note : Text, a : async<@> Int) {}; // Create an actor. let c = Counter(10); @@ -38,9 +38,9 @@ func testRead() { while (i > 0) { c.dec(); let t = c.read(); - showAsync("before", t); + showAsync<@>("before", t); show("await", await t); - showAsync("after", t); + showAsync<@>("after", t); i -= 1; } } diff --git a/test/mo-idl/pa_cars.mo b/test/mo-idl/pa_cars.mo index 80a51e39899..9a6dde6b4c8 100644 --- a/test/mo-idl/pa_cars.mo +++ b/test/mo-idl/pa_cars.mo @@ -21,7 +21,7 @@ actor class PACars(dmv : DMV) { public func verifyCarInformation(user : User, car : Car) : async ?(shared (Location, TimeSpan) -> async Result) { let carInfo = await dmv.check(car); if (carInfo.isValid and not carInfo.wasStolen) { - return ?(shared func (location, time) : async Result { + return ?(shared func (location:Location, time:TimeSpan) : async Result { return reserveSpot(user, carInfo, location, time); }) } else { From 3d22ee529c2866f788fc7ee5b9104f34423393c8 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 29 Nov 2019 20:06:25 +0100 Subject: [PATCH 0748/1176] Fix unescaped quotes in test/idl (#956) --- test/run.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/run.sh b/test/run.sh index 027f46bde7f..73e6bb2e3d4 100755 --- a/test/run.sh +++ b/test/run.sh @@ -305,7 +305,7 @@ do sed -i 's/import "/import "..\//g' $out/$base.pp.did $DIDC --check $out/$base.pp.did > $out/$base.pp.tc 2>&1 diff_files="$diff_files $base.pp.tc" - + $ECHO -n " [js]" $DIDC --js $base.did -o $out/$base.js >& $out/$base.js.out normalize $out/$base.js @@ -324,7 +324,7 @@ do node -r esm -e \ "import actorInterface from './$out/$base.js'; import { makeActor, makeHttpAgent } from '$JS_USER_LIBRARY'; - const httpAgent = makeHttpAgent({ canisterId: "ffffffffffffffff" }); + const httpAgent = makeHttpAgent({ canisterId: \"ffffffffffffffff\" }); const actor = makeActor(actorInterface)(httpAgent); assert(Object.entries(actor).length > 0);" fi From 89be5d4f8feb765da6b9396d757ff85122b39b11 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Sat, 30 Nov 2019 00:37:02 +0100 Subject: [PATCH 0749/1176] Split various test directories into subderivations (#954) * gitSource.nix: Use cleanSourceWith following the example in https://github.com/dfinity-lab/dfinity/commit/4f2d90887218b1a243f3f21c74b0d2d967b748ad This changes changes the derivations used by `cabal2nix` to only contain the `.cabal` files. Which is a good thing. * Merge test/run-release into test/run with a new ``` +//MOC-FLAG --release ``` feature (may be handy for other things too). * Make test/repl self-contained by copying `type-lub.mo`, but probably fine. * Split various test directories into subderivations having spent so much time on nix this week I felt motivated to refine our `test` derivation, by splitting it up into several subtests. The benefits are * more parallelism * less rereuns (e.g. bumping `drun` will only re-run the tests using it) * quicker feedback on GitHub, e.g. the fact _which_ subderivation has failed will already be useful feedback. * Fix shell and all-systems-go --- default.nix | 161 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 99 insertions(+), 62 deletions(-) diff --git a/default.nix b/default.nix index 6343844a83e..c7fd7b60b4b 100644 --- a/default.nix +++ b/default.nix @@ -191,70 +191,109 @@ rec { # “our” Haskell packages inherit (haskellPackages) lsp-int qc-motoko ic-stub; - tests = stdenv.mkDerivation { - name = "tests"; - src = subpath ./test; - buildInputs = - [ moc - mo-ld - didc - deser - nixpkgs.wabt - nixpkgs.bash - nixpkgs.perl - nixpkgs.getconf - nixpkgs.moreutils - nixpkgs.nodejs-10_x - filecheck - js-user-library - drun - wasmtime - haskellPackages.qc-motoko - haskellPackages.lsp-int - ic-stub - esm - ] ++ - llvmBuildInputs; + tests = + let testDerivationArgs = { + # by default, an empty source directory. how to best get an empty directory? + src = builtins.path { name = "empty"; path = ./nix; filter = p: t: false; }; + phases = "unpackPhase checkPhase installPhase"; + doCheck = true; + installPhase = "touch $out"; + }; in + let testDerivation = args: + stdenv.mkDerivation (testDerivationArgs // args); in + let ocamlTestDerivation = args: + ocamlpkgs.stdenv.mkDerivation (testDerivationArgs // args); in + + # we test each subdirectory of test/ in its own derivation with + # cleaner dependencies, for more paralleism, more caching + # and better feedback about what aspect broke + let test_subdir = dir: deps: + testDerivation { + name = "test-${dir}"; + # include from test/ only the common files, plus everything in test/${dir}/ + src = + with nixpkgs.lib; + cleanSourceWith { + filter = path: type: + let relPath = removePrefix (toString ./test + "/") (toString path); in + type != "directory" || hasPrefix "${dir}/" "${relPath}/"; + src = subpath ./test; + name = "test-${dir}-src"; + }; + buildInputs = + deps ++ + [ nixpkgs.wabt + nixpkgs.bash + nixpkgs.perl + nixpkgs.getconf + nixpkgs.moreutils + nixpkgs.nodejs-10_x + filecheck + wasmtime + esm + ] ++ + llvmBuildInputs; + + checkPhase = '' + patchShebangs . + ${llvmEnv} + export MOC=moc + export MO_LD=mo-ld + export DIDC=didc + export DESER=deser + export ESM=${esm} + export JS_USER_LIBRARY=${js-user-library} + type -p moc && moc --version + # run this once to work around self-unpacking-race-condition + type -p drun && drun --version + make -C ${dir} + ''; + }; in - buildPhase = '' - patchShebangs . - ${llvmEnv} - export MOC=moc - export MO_LD=mo-ld - export DIDC=didc - export DESER=deser - export ESM=${esm} - export JS_USER_LIBRARY=${js-user-library} - moc --version - drun --version # run this once to work around self-unpacking-race-condition - make parallel + let qc = testDerivation { + name = "test-qc"; + # maybe use wasm instead? + buildInputs = [ moc nixpkgs.wabt haskellPackages.qc-motoko ]; + checkPhase = '' qc-motoko${nixpkgs.lib.optionalString (replay != 0) - " --quickcheck-replay=${toString replay}"} - cp -R ${subpath ./test/lsp-int/test-project} test-project - find ./test-project -type d -exec chmod +w {} + - lsp-int ${mo-ide}/bin/mo-ide ./test-project + " --quickcheck-replay=${toString replay}"} ''; + }; in - installPhase = '' - touch $out - ''; - }; - - unit-tests = ocamlpkgs.stdenv.mkDerivation { - name = "unit-tests"; - - src = subpath ./src; + let lsp = testDerivation { + name = "test-lsp"; + src = subpath ./test/lsp-int/test-project; + buildInputs = [ moc haskellPackages.lsp-int ]; + checkPhase = '' + echo running lsp-int + lsp-int ${mo-ide}/bin/mo-ide . + ''; + }; in - buildInputs = commonBuildInputs ocamlpkgs; + let unit-tests = ocamlTestDerivation { + name = "unit-tests"; + src = subpath ./src; + buildInputs = commonBuildInputs ocamlpkgs; + checkPhase = '' + make DUNE_OPTS="--display=short" unit-tests + ''; + installPhase = '' + touch $out + ''; + }; in - buildPhase = '' - make DUNE_OPTS="--display=short" unit-tests - ''; + { run = test_subdir "run" [ moc ] ; + run-drun = test_subdir "run-drun" [ moc drun ic-stub ]; + fail = test_subdir "fail" [ moc ]; + repl = test_subdir "repl" [ moc ]; + ld = test_subdir "ld" [ mo-ld ]; + idl = test_subdir "idl" [ didc ]; + mo-idl = test_subdir "mo-idl" [ moc didc ]; + trap = test_subdir "trap" [ moc ]; + run-deser = test_subdir "run-deser" [ deser ]; + inherit qc lsp unit-tests; + }; - installPhase = '' - touch $out - ''; - }; samples = stdenv.mkDerivation { name = "samples"; @@ -413,8 +452,6 @@ rec { js didc deser - tests - unit-tests samples rts stdlib @@ -423,7 +460,7 @@ rec { users-guide ic-stub shell - ]; + ] ++ builtins.attrValues tests; }; shell = nixpkgs.mkShell { @@ -439,10 +476,10 @@ rec { nixpkgs.lib.lists.unique (builtins.filter (i: !(builtins.elem i dont_build)) ( commonBuildInputs nixpkgs ++ rts.buildInputs ++ - tests.buildInputs ++ js.buildInputs ++ users-guide.buildInputs ++ - [ nixpkgs.ncurses nixpkgs.ocamlPackages.merlin nixpkgs.ocamlPackages.utop ] + [ nixpkgs.ncurses nixpkgs.ocamlPackages.merlin nixpkgs.ocamlPackages.utop ] ++ + builtins.concatMap (d: d.buildInputs) (builtins.attrValues tests) )); shellHook = llvmEnv; From 370444ee733d4754f01211e8300de38bc00d5282 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Sat, 30 Nov 2019 01:02:14 +0100 Subject: [PATCH 0750/1176] Bump drun (#941) to get the benefit of, among other things: * https://github.com/dfinity-lab/dfinity/pull/1965 * https://github.com/dfinity-lab/dfinity/pull/1976 * https://github.com/dfinity-lab/dfinity/pull/1995 (not yet used by Motoko) This does _not_ yet enable inter-canister calls on `drun`; that turned out to be not yet a smooth thing (see https://dfinity.atlassian.net/browse/DFN-1185). So this bumps `drun` and updates the System API we use (so that releases are possible), without enabling new features. That we can do separately. Other changes: ``` af802ab2d Public Spec: Fix formatting of textual id example (#2007) 4f84250bf Add a fake for the StateManager. (#1968) 076ce4eca Merge pull request #2005 from dfinity-lab/dimitris/restructure-scheduling fc61b5987 Merge pull request #1995 from dfinity-lab/DFN-1172/msg_caller 6b7d26fcf Merge pull request #2006 from dfinity-lab/nm-re-add-git-only 1a4ebe97b Merge pull request #2003 from dfinity-lab/dimitris/derive-deser ba7669852 Merge pull request #2001 from dfinity-lab/dsd/remove_cyclic_dependency 0355a37c7 Make Notification more useful. (#1998) c0ac603a0 Merge pull request #1999 from dfinity-lab/akhi3030/use-hypervisor-config 4da566c0b Merge pull request #1996 from dfinity-lab/akhi3030/update-initialization 67a69c568 Add `Notification` test utility. (#1985) 25be08c8b Merge pull request #1990 from dfinity-lab/johnw/try_fold 517d0036d DFN-1028: Add key generation for committee member keys (#1982) 11e333d71 Merge pull request #1994 from dfinity-lab/dimitris/remove-as-ingress d1847afc2 Merge pull request #1964 from dfinity-lab/dimitris/set-log-level 3d0c99a87 Merge pull request #1980 from dfinity-lab/dsd/registry/test_port_binding b0f24ee10 Merge pull request #1984 from dfinity-lab/johnw/procman-tests 72c11097f Merge pull request #1991 from dfinity-lab/mw/nix-shell-experimental d0277e5c3 Merge pull request #1976 from dfinity-lab/DFN-1172/msg_arg_data 53096c8c7 Add concurrency design for client 22af52fd5 Remove Robert from CODEOWNERS 921a49530 Merge pull request #1986 from dfinity-lab/johnw/procman-update 15bd8724f Bump common (#1983) 096b6bbef Merge pull request #1979 from dfinity-lab/nm-cargo-build-locked 9e420a543 Merge pull request #1977 from dfinity-lab/nm-d0-cargo-test 082c47c25 Merge pull request #1971 from dfinity-lab/DFN-1172/fix_call_simple 7ac088fcc Merge pull request #1972 from dfinity-lab/nm-git-dir 18fc596ce Merge pull request #1973 from dfinity-lab/nm-disable-proc-tests 5ab77b283 drops redundant words (#1975) 3d8b099b6 Rename gen_key_pair_pop (#1974) 0a8c9f54f DFN-1004: Csp multisig keygen (#1955) baf8173d8 Correct a type error on Linux 79e3613dd Bump two of the test delays, since they don't represent actual run time 6909259d2 Drop futures and tokio dependencies from Cargo.lock dac801f92 Drop dependency on tokio and futures ab99330c8 Remove manual setting of CARGO_HOME and CARGO_TARGET_DIR d562d1737 Make log passed to Director mandatory c2a9e79ca Rename UnknownEvent to RawEvent 3c3b41654 Make Director::log private a391ae8e8 Add a type alias ChildRef = Arc> 87cde3c52 Refactor process_monitor 69db3cc94 Remove an unused struct member 312b66eb9 Remove StdInput b66336d2a Reduce delays on two tests to five seconds, and add comments 3abc443e3 Instead of heap_used, use resident_used cf6458755 Fix two Clippy warnings 1a278a3e7 Prefer Debug to Display 499c753a4 Remove two unnecessary print statements a588d750b Add a TODO comment 59181750b Allow setting of process limits when using the 'guarded' utility 2c159feb3 Add a 'guarded' utility, based on the process_manager crate 28ff25f88 Add "time spent running" to the Heartbeat information a65cc8032 Use .clone() instead of .to_string() f43f52e0f Extend comment in process.rs ee5dcada4 Run cargo fmt 60510b984 If no memstats can be gathered (the process has exited), return 0 9b69508d0 Add process memory usage information to each Heartbeat b364c7095 A few minor cleanups 21488ebd6 Enable RUST_BACKTRACE when running a process 85925c2d7 Record process status changes as an event 8c7d37275 Run cargo fmt a78e11dba Fix warnings reported by clippy 4afb7a34a Add a heartbeat monitor that ensures the monitor is alive 938a9cb6a Use slog instead of printing to stdout cce56141c Add another test in process.rs 241c2fa55 Add a basic functionality test for process.rs 89ef6f11a test_exit is now functioning 7affcb302 More code reorganization in process.rs 2dd0df078 Add two calls to panic! 67034955f Code reorganization, and beginning work on stopping all other processes 13aae4d6e Include the time with observed event data d4907a481 Run cargo fmt 04a491b83 Split lib.rs into process.rs and director.rs 51df3fcc8 Begin a process_manager crate for managing, yes, processes 7b390c3b9 DFN-1130: Consensus team has stubs for the revised signing API (#1921) 2239d56d0 Merge pull request #1967 from dfinity-lab/nm-fix-typos fe2a72399 Make temporary switch to `Hash` trait for `crypto_hash` permanent (#1947) b1c3a1e19 Merge pull request #1963 from dfinity-lab/nm-document-graph-filter d5f76dea3 Merge pull request #1965 from dfinity-lab/dimitris/add-default-configs c7ee193ff cargo fmt d82e26604 review comments 307ab49a5 temporaly fixes the integration test 9dd68cbd1 implements canister_self_* calls f2e427b20 Merge pull request #1959 from dfinity-lab/akhi3030/rename-wasmpages 5a49e48a3 Merge pull request #1960 from dfinity-lab/DFN-1172/removes-anyref 7362df46b Public Spec: One-character typo (#1961) ``` --- default.nix | 39 ++++++++++--------------- src/codegen/compile.ml | 22 +++++--------- test/run-drun/empty-call.mo | 5 ++++ test/run-drun/ok/empty-call.drun-run.ok | 2 ++ 4 files changed, 31 insertions(+), 37 deletions(-) create mode 100644 test/run-drun/empty-call.mo create mode 100644 test/run-drun/ok/empty-call.drun-run.ok diff --git a/default.nix b/default.nix index c7fd7b60b4b..aa282709087 100644 --- a/default.nix +++ b/default.nix @@ -16,12 +16,16 @@ let stdenv = nixpkgs.stdenv; in let subpath = p: import ./nix/gitSource.nix p; in -let dfinity-repo = import (builtins.fetchGit { - name = "dfinity-sources"; - url = "ssh://git@github.com/dfinity-lab/dfinity"; - # ref = "master"; - rev = "a77f9b30fa5b1f35bef2913c2329e2c8e81c1af8"; -}) { inherit (nixpkgs) system; }; in +let dfinity-src = + let env = builtins.getEnv "DFINITY_SRC"; in + if env != "" then env else builtins.fetchGit { + name = "dfinity-sources"; + url = "ssh://git@github.com/dfinity-lab/dfinity"; + # ref = "master"; + rev = "af802ab2d5758522525dcdc4c24a0fd95a950449"; + }; in + +let dfinity-pkgs = import dfinity-src { inherit (nixpkgs) system; }; in let sdk = import (builtins.fetchGit { name = "sdk-sources"; @@ -35,7 +39,7 @@ let esm = builtins.fetchTarball { url = "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz"; }; in -let drun = dfinity-repo.drun or dfinity-repo.dfinity.drun; in +let drun = dfinity-pkgs.drun or dfinity-pkgs.dfinity.drun; in let js-user-library = sdk.js-user-library; in let haskellPackages = nixpkgs.haskellPackages.override { @@ -294,26 +298,15 @@ rec { inherit qc lsp unit-tests; }; - samples = stdenv.mkDerivation { name = "samples"; src = subpath ./samples; - buildInputs = - [ moc - didc - nixpkgs.wabt - nixpkgs.bash - nixpkgs.perl - filecheck - drun - ] ++ - llvmBuildInputs; - + buildInputs = [ moc ]; buildPhase = '' - patchShebangs . - export MOC=moc - make all - ''; + patchShebangs . + export MOC=moc + make all + ''; installPhase = '' touch $out ''; diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 7b509f8e842..dfab2b1ab13 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -2904,8 +2904,11 @@ module Dfinity = struct match E.mode env with | Flags.ICMode -> E.add_func_import env "debug" "print" [I32Type; I32Type] []; - E.add_func_import env "msg" "arg_data_size" [] [I32Type]; - E.add_func_import env "msg" "arg_data_copy" [I32Type; I32Type; I32Type] []; + E.add_func_import env "ic0" "call_simple" (i32s 10) [I32Type]; + E.add_func_import env "ic0" "canister_self_copy" (i32s 3) []; + E.add_func_import env "ic0" "canister_self_size" [] [I32Type]; + E.add_func_import env "ic0" "msg_arg_data_copy" (i32s 3) []; + E.add_func_import env "ic0" "msg_arg_data_size" [] [I32Type]; E.add_func_import env "msg" "reply" [I32Type; I32Type] []; E.add_func_import env "msg" "reject" [I32Type; I32Type] []; E.add_func_import env "msg" "reject_code" [] [I32Type]; @@ -3048,7 +3051,7 @@ module Dfinity = struct let get_self_reference env = match E.mode env with - | Flags.StubMode -> + | Flags.ICMode | Flags.StubMode -> Func.share_code0 env "canister_self" [I32Type] (fun env -> let (set_len, get_len) = new_local env "len" in let (set_blob, get_blob) = new_local env "blob" in @@ -4015,20 +4018,13 @@ module Serialization = struct let argument_data_size env = match E.mode env with - | Flags.ICMode -> - Dfinity.system_call env "msg" "arg_data_size" - | Flags.StubMode -> + | Flags.ICMode | Flags.StubMode -> Dfinity.system_call env "ic0" "msg_arg_data_size" | _ -> assert false let argument_data_copy env get_dest get_length = match E.mode env with - | Flags.ICMode -> - get_dest ^^ - get_length ^^ - (compile_unboxed_const 0l) ^^ - Dfinity.system_call env "msg" "arg_data_copy" - | Flags.StubMode -> + | Flags.ICMode | Flags.StubMode -> get_dest ^^ (compile_unboxed_const 0l) ^^ get_length ^^ @@ -4828,7 +4824,6 @@ module FuncDec = struct *) let closures_to_reply_reject_callbacks env ts = - assert (E.mode env = Flags.StubMode); let reply_name = "@callback<" ^ Serialization.typ_id (Type.Tup ts) ^ ">" in Func.define_built_in env reply_name ["env", I32Type] [] (fun env -> (* Look up closure *) @@ -4883,7 +4878,6 @@ module FuncDec = struct get_cb_index let ignoring_callback env = - assert (E.mode env = Flags.StubMode); let name = "@ignore_callback" in Func.define_built_in env name ["env", I32Type] [] (fun env -> G.nop); compile_unboxed_const (E.built_in env name) diff --git a/test/run-drun/empty-call.mo b/test/run-drun/empty-call.mo new file mode 100644 index 00000000000..fee9c79d954 --- /dev/null +++ b/test/run-drun/empty-call.mo @@ -0,0 +1,5 @@ +actor { + public func go() { + } +} +//CALL ingress go 0x4449444C0000 diff --git a/test/run-drun/ok/empty-call.drun-run.ok b/test/run-drun/ok/empty-call.drun-run.ok new file mode 100644 index 00000000000..91c74b55809 --- /dev/null +++ b/test/run-drun/ok/empty-call.drun-run.ok @@ -0,0 +1,2 @@ +ingress(0) System +ingress(1) Completed: Canister: Payload: 0x4449444c0000 From c0f585aede16d0ec11c10fcada3d73308ba8045f Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Sat, 30 Nov 2019 13:35:44 +0100 Subject: [PATCH 0751/1176] actory-ify type-lub.mo (#959) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit so that we don’t do inter-canister calls (due to `async`) from the canister initialization --- test/run-drun/ok/type-lub.comp.ok | 2 +- test/run-drun/ok/type-lub.ic-stub-run.ok | 2 + test/run-drun/type-lub.mo | 180 ++++++++++++----------- 3 files changed, 95 insertions(+), 89 deletions(-) diff --git a/test/run-drun/ok/type-lub.comp.ok b/test/run-drun/ok/type-lub.comp.ok index 9f592a9df67..38646553187 100644 --- a/test/run-drun/ok/type-lub.comp.ok +++ b/test/run-drun/ok/type-lub.comp.ok @@ -1,2 +1,2 @@ -type-lub.mo:57.12-57.20: type error, unsupported async block +type-lub.mo:59.16-59.24: type error, unsupported async block (This is a limitation of the current version.) diff --git a/test/run-drun/ok/type-lub.ic-stub-run.ok b/test/run-drun/ok/type-lub.ic-stub-run.ok index 54225bc8555..be9fb5d62c0 100644 --- a/test/run-drun/ok/type-lub.ic-stub-run.ok +++ b/test/run-drun/ok/type-lub.ic-stub-run.ok @@ -2,3 +2,5 @@ ← completed: canister-id = 0x0000000000000400 → install ← completed +→ update go(0x4449444c0000) +← completed: 0x4449444c0000 diff --git a/test/run-drun/type-lub.mo b/test/run-drun/type-lub.mo index ede56742f62..41e7fd815f5 100644 --- a/test/run-drun/type-lub.mo +++ b/test/run-drun/type-lub.mo @@ -1,136 +1,140 @@ -let opts = [null, ?42, ?-25]; -let nulls = [null, null]; +actor a { + public func go() { + let opts = [null, ?42, ?-25]; + let nulls = [null, null]; -let incompatible_objs = [{a = 42}, {b = 42}]; -let objs = [{a = 42}, {b = 42; a = 1}, {a = -25}]; + let incompatible_objs = [{a = 42}, {b = 42}]; + let objs = [{a = 42}, {b = 42; a = 1}, {a = -25}]; -let tups = [(12, -1), (-42, 25)]; -let tup1s = [(-1,), 25]; + let tups = [(12, -1), (-42, 25)]; + let tup1s = [(-1,), 25]; -let arrs = [[-42], [25]]; + let arrs = [[-42], [25]]; -let incompatible_funcs = [ func (a : [Int]) : Nat = a.len() - , func (a : ()) : Int = -42 - ]; + let incompatible_funcs = [ func (a : [Int]) : Nat = a.len() + , func (a : ()) : Int = -42 + ]; -let poly_funcs = [ func (a : [Int]) : Nat = a.len() - , func (a : [Nat]) : Int = -42 - ]; + let poly_funcs = [ func (a : [Int]) : Nat = a.len() + , func (a : [Nat]) : Int = -42 + ]; -let poly_funcs2 = [ func (a : [Int]) : Nat = a.len() - , func (a : [Nat]) : Int = -42 - ]; + let poly_funcs2 = [ func (a : [Int]) : Nat = a.len() + , func (a : [Nat]) : Int = -42 + ]; -let poly_funcs3 = [ func (as : [A], b : B) : A = as[0] - , func (bs : [B], a : A) : B = bs[0] - ]; + let poly_funcs3 = [ func (as : [A], b : B) : A = as[0] + , func (bs : [B], a : A) : B = bs[0] + ]; -let poly_funcs4 = [ func (as : [A], b : B) : A = as[0] - , func (bs : [B], a : A) : B = bs[0] - ]; + let poly_funcs4 = [ func (as : [A], b : B) : A = as[0] + , func (bs : [B], a : A) : B = bs[0] + ]; -let funcs = [ func (a : [Int]) : Nat = a.len() - , func (a : [Nat]) : Int = -42 - ]; + let funcs = [ func (a : [Int]) : Nat = a.len() + , func (a : [Nat]) : Int = -42 + ]; -let variant_funcs = [ func (a : {#foo; #bar}) { switch a { case (#foo) (); case (#bar) () } } - , func (a : {#baz; #bar}) { switch a { case (#baz) (); case (#bar) () } } - ]; + let variant_funcs = [ func (a : {#foo; #bar}) { switch a { case (#foo) (); case (#bar) () } } + , func (a : {#baz; #bar}) { switch a { case (#baz) (); case (#bar) () } } + ]; -// TODO(gabor), mutable arrays -let mut_arrs = [[var 42], [var 25], [77]]; // boring + // TODO(gabor), mutable arrays + let mut_arrs = [[var 42], [var 25], [77]]; // boring -// TODO(gabor), mutable fields, see fail/type-inference.mo:13 + // TODO(gabor), mutable fields, see fail/type-inference.mo:13 -let sh : Any = 42; -let shareds = [sh, 77, [1, 2, 3]]; -let shared2s = [77, [1, 2, 3], sh]; + let sh : Any = 42; + let shareds = [sh, 77, [1, 2, 3]]; + let shared2s = [77, [1, 2, 3], sh]; -let shared_funcs = [ func (a : Int) : Int = a - , func (a : Nat) : Nat = 42 - ]; + let shared_funcs = [ func (a : Int) : Int = a + , func (a : Nat) : Nat = 42 + ]; -type C = async(?Int); -type D = async(?Nat); + type C = async(?Int); + type D = async(?Nat); -func c0(c : C, d : D) : [C] { ignore([c, d]); [c, d] }; -let c1s = [async ?4, async ?-42]; + func c0(c : C, d : D) : [C] { ignore([c, d]); [c, d] }; + let c1s = [async ?4, async ?-42]; -// recursive objects + // recursive objects -// { need global types due to https://dfinity.atlassian.net/browse/AST-34 -type A = {x : A}; -type B = {x : B}; + // { need global types due to https://dfinity.atlassian.net/browse/AST-34 + type A = {x : A}; + type B = {x : B}; -func f(v : {x : {x : B}; b : B}, x : A, y : B, z : {x : B; a : A}) : [A] { ignore([v, x, y, z]); [v, x, y, z] }; -// }; + func f(v : {x : {x : B}; b : B}, x : A, y : B, z : {x : B; a : A}) : [A] { ignore([v, x, y, z]); [v, x, y, z] }; + // }; -// { -type A1 = {x : B1}; -type B1 = {x : A1}; + // { + type A1 = {x : B1}; + type B1 = {x : A1}; -func f1(x : A1, y : B1) : [A1] { ignore([x, y]); [x, y] }; -// }; + func f1(x : A1, y : B1) : [A1] { ignore([x, y]); [x, y] }; + // }; -type O = ?O; -type P = ?P; + type O = ?O; + type P = ?P; -type Q = ?R; -type R = ?S; -type S = ?Q; + type Q = ?R; + type R = ?S; + type S = ?Q; -func g(o : O, p : P, q : Q, r : R) : [O] { ignore([o, p, q, r]); [o, p, q, r] }; + func g(o : O, p : P, q : Q, r : R) : [O] { ignore([o, p, q, r]); [o, p, q, r] }; -// example from https://dfinity.atlassian.net/browse/AST-83 + // example from https://dfinity.atlassian.net/browse/AST-83 -type Foo = ?(Foo); -ignore (if true (null : Foo) else (null : Foo)); + type Foo = ?(Foo); + ignore (if true (null : Foo) else (null : Foo)); -type U = { #a : U; #b : Int }; -type V = { #a : V; #b : Nat }; + type U = { #a : U; #b : Int }; + type V = { #a : V; #b : Nat }; -func v0(u : U, v : V, w : { #a : { #a : V; #b : Nat }; #b : Nat }) : [U] { ignore([u, v, w]); [u, v, w] }; + func v0(u : U, v : V, w : { #a : { #a : V; #b : Nat }; #b : Nat }) : [U] { ignore([u, v, w]); [u, v, w] }; -type G = (Nat, ?G); -type H = (Int, ?H); + type G = (Nat, ?G); + type H = (Int, ?H); -func g0(g : G, h : H) : [H] { ignore([g, h]); [g, h] }; + func g0(g : G, h : H) : [H] { ignore([g, h]); [g, h] }; -type K = [K]; -type L = [L]; + type K = [K]; + type L = [L]; -func k0(k : K, l : L) : [L] { ignore([k, l]); [k, l] }; + func k0(k : K, l : L) : [L] { ignore([k, l]); [k, l] }; -type K1 = [?(Nat, K1)]; -type L1 = [?(Int, L1)]; + type K1 = [?(Nat, K1)]; + type L1 = [?(Int, L1)]; -func k1(k : K1, l : L1) : [L1] { ignore([k, l]); [k, l] }; + func k1(k : K1, l : L1) : [L1] { ignore([k, l]); [k, l] }; -/* -type M = [var ?M]; -type N = [?N]; + /* + type M = [var ?M]; + type N = [?N]; -func m0(m : M, n : N) : [M] { ignore([m, n]); [m, n] }; -*/ + func m0(m : M, n : N) : [M] { ignore([m, n]); [m, n] }; + */ -type E = Int -> E; -type F = Nat -> F; + type E = Int -> E; + type F = Nat -> F; -func f0(e : E, f : F) : [F] { ignore([e, f]); [e, f] }; + func f0(e : E, f : F) : [F] { ignore([e, f]); [e, f] }; -type E1 = E1 -> E1; -type F1 = F1 -> F1; + type E1 = E1 -> E1; + type F1 = F1 -> F1; -func f12(e : E1, f : F1) : [F1] { ignore([e, f]); [e, f] }; + func f12(e : E1, f : F1) : [F1] { ignore([e, f]); [e, f] }; -type E2 = F2 -> E2; -type F2 = E2 -> F2; - -func f2(e : E2, f : F2) : [F2] { ignore([e, f]); [e, f] }; + type E2 = F2 -> E2; + type F2 = E2 -> F2; + func f2(e : E2, f : F2) : [F2] { ignore([e, f]); [e, f] }; + } +}; +a.go(); //OR-CALL ingress go "DIDL\x00\x00" From df29bf1df2260aca2d5fbfe2784dc640300737d2 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Sun, 1 Dec 2019 23:42:02 +0100 Subject: [PATCH 0752/1176] Async helper method: Really only allow selfcalls (#960) The `__motoko_async_helper` should only be callable from the canister itself. This compares `i0.canister_self` with `ic0.msg_caller`, which is supported by `drun` and `ic-stub`. --- rts/rts.c | 8 +++++ src/codegen/compile.ml | 34 ++++++++++++++++++- test/run-drun/call-async-method.mo | 8 +++++ .../run-drun/ok/call-async-method.drun-run.ok | 2 ++ 4 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 test/run-drun/call-async-method.mo create mode 100644 test/run-drun/ok/call-async-method.drun-run.ok diff --git a/rts/rts.c b/rts/rts.c index 15ea2ffe724..52e7729d28a 100644 --- a/rts/rts.c +++ b/rts/rts.c @@ -14,6 +14,14 @@ export void as_memcpy(char *str1, const char *str2, size_t n) { } } +export int as_memcmp(const unsigned char *str1, const unsigned char *str2, size_t n) { + for (size_t i = 0; i < n; i++) { + if (str1[i] != str2[i]) + return str1[i]-str2[i]; + } + return 0; +} + size_t as_strlen(const char* p) { size_t i = 0; while (p[i]) i++; diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index dfab2b1ab13..4edda740dd6 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -602,6 +602,7 @@ module RTS = struct (* The connection to the C parts of the RTS *) let system_imports env = E.add_func_import env "rts" "as_memcpy" [I32Type; I32Type; I32Type] []; + E.add_func_import env "rts" "as_memcmp" [I32Type; I32Type; I32Type] [I32Type]; E.add_func_import env "rts" "version" [] [I32Type]; E.add_func_import env "rts" "parse_idl_header" [I32Type; I32Type; I32Type] []; E.add_func_import env "rts" "read_u32_of_leb128" [I32Type] [I32Type]; @@ -793,6 +794,8 @@ module Heap = struct (* Convenience functions related to memory *) (* Copying bytes (works on unskewed memory addresses) *) let memcpy env = E.call_import env "rts" "as_memcpy" + (* Comparing bytes (works on unskewed memory addresses) *) + let memcmp env = E.call_import env "rts" "as_memcmp" (* Copying words (works on skewed memory addresses) *) let memcpy_words_skewed env = @@ -2909,6 +2912,8 @@ module Dfinity = struct E.add_func_import env "ic0" "canister_self_size" [] [I32Type]; E.add_func_import env "ic0" "msg_arg_data_copy" (i32s 3) []; E.add_func_import env "ic0" "msg_arg_data_size" [] [I32Type]; + E.add_func_import env "ic0" "msg_caller_copy" (i32s 3) []; + E.add_func_import env "ic0" "msg_caller_size" [] [I32Type]; E.add_func_import env "msg" "reply" [I32Type; I32Type] []; E.add_func_import env "msg" "reject" [I32Type; I32Type] []; E.add_func_import env "msg" "reject_code" [] [I32Type]; @@ -2921,6 +2926,8 @@ module Dfinity = struct E.add_func_import env "ic0" "debug_print" (i32s 2) []; E.add_func_import env "ic0" "msg_arg_data_copy" (i32s 3) []; E.add_func_import env "ic0" "msg_arg_data_size" [] [I32Type]; + E.add_func_import env "ic0" "msg_caller_copy" (i32s 3) []; + E.add_func_import env "ic0" "msg_caller_size" [] [I32Type]; E.add_func_import env "ic0" "msg_reject_code" [] [I32Type]; E.add_func_import env "ic0" "msg_reject" (i32s 2) []; E.add_func_import env "ic0" "msg_reply_data_append" (i32s 2) []; @@ -3118,6 +3125,30 @@ module Dfinity = struct let async_method_name = "__motoko_async_helper" + let assert_caller_self env = + let (set_len1, get_len1) = new_local env "len1" in + let (set_len2, get_len2) = new_local env "len2" in + let (set_str1, get_str1) = new_local env "str1" in + let (set_str2, get_str2) = new_local env "str2" in + system_call env "ic0" "canister_self_size" ^^ set_len1 ^^ + system_call env "ic0" "msg_caller_size" ^^ set_len2 ^^ + get_len1 ^^ get_len2 ^^ G.i (Compare (Wasm.Values.I32 I32Op.Eq)) ^^ + E.else_trap_with env "not a self-call" ^^ + + get_len1 ^^ Blob.dyn_alloc_scratch env ^^ set_str1 ^^ + get_str1 ^^ compile_unboxed_const 0l ^^ get_len1 ^^ + system_call env "ic0" "canister_self_copy" ^^ + + get_len2 ^^ Blob.dyn_alloc_scratch env ^^ set_str2 ^^ + get_str2 ^^ compile_unboxed_const 0l ^^ get_len2 ^^ + system_call env "ic0" "msg_caller_copy" ^^ + + + get_str1 ^^ get_str2 ^^ get_len1 ^^ Heap.memcmp env ^^ + compile_unboxed_const 0l ^^ G.i (Compare (Wasm.Values.I32 I32Op.Eq)) ^^ + E.else_trap_with env "not a self-call" + + end (* Dfinity *) module RTS_Exports = struct @@ -4929,7 +4960,8 @@ module FuncDec = struct Func.define_built_in env name [] [] (fun env -> let (set_closure, get_closure) = new_local env "closure" in - (* TODO: Check that it is us that is calling this *) + (* Check that we are calling this *) + Dfinity.assert_caller_self env ^^ (* Deserialize and look up closure argument *) Serialization.deserialize env [Type.Prim Type.Word32] ^^ diff --git a/test/run-drun/call-async-method.mo b/test/run-drun/call-async-method.mo new file mode 100644 index 00000000000..2857d303d6e --- /dev/null +++ b/test/run-drun/call-async-method.mo @@ -0,0 +1,8 @@ +actor a { +}; +//CALL ingress __motoko_async_helper "DIDL\x00\x00" + +//SKIP run +//SKIP run-ir +//SKIP run-low + diff --git a/test/run-drun/ok/call-async-method.drun-run.ok b/test/run-drun/ok/call-async-method.drun-run.ok new file mode 100644 index 00000000000..ffe3f56379c --- /dev/null +++ b/test/run-drun/ok/call-async-method.drun-run.ok @@ -0,0 +1,2 @@ +ingress(0) System +ingress(1) Err: IC0503: Canister 42 trapped explicitly: not a self-call From a17d57dd519e2aef0a8cd32a5a849478bfa4fced Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 2 Dec 2019 16:36:41 +0100 Subject: [PATCH 0753/1176] Expose Blob type, with equality and comparisons (#963) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit this does not yet add intro forms. The goal of this is that we can merge and play around with #789 (caller information in the context) while we flesh out questions like * what type is the caller? `Entity`? Do we want users and canisters separate? etc. * do we want to have `type Blob = [Word8]`? What does that mean for comparisons? Can we make that efficient? Without intro forms we can’t test much yet. Maybe we can add intro forms, but that’s suitable for a separate PR. --- src/codegen/compile.ml | 6 +++--- src/mo_types/type.ml | 1 + src/mo_values/operator.ml | 21 +++++++++++---------- src/prelude/prelude.ml | 1 + test/run/blobs.mo | 7 +++++++ 5 files changed, 23 insertions(+), 13 deletions(-) create mode 100644 test/run/blobs.mo diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 4edda740dd6..e455e622b36 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -4428,7 +4428,7 @@ module StackRep = struct | Prim (Nat64 | Int64 | Word64) -> UnboxedWord64 | Prim (Nat32 | Int32 | Word32) -> UnboxedWord32 | Prim (Nat8 | Nat16 | Int8 | Int16 | Word8 | Word16 | Char) -> Vanilla - | Prim Text -> Vanilla + | Prim (Text|Blob) -> Vanilla | p -> todo "of_type" (Arrange_ir.typ p) Vanilla let to_block_type env = function @@ -5845,7 +5845,7 @@ let compile_binop env t op = ) let compile_eq env = function - | Type.(Prim Text) -> Blob.compare env Operator.EqOp + | Type.(Prim (Text|Blob)) -> Blob.compare env Operator.EqOp | Type.(Prim Bool) -> G.i (Compare (Wasm.Values.I32 I32Op.Eq)) | Type.(Prim (Nat | Int)) -> BigNum.compile_eq env | Type.(Prim (Int64 | Nat64 | Word64)) -> G.i (Compare (Wasm.Values.I64 I64Op.Eq)) @@ -5877,7 +5877,7 @@ let compile_relop env t op = StackRep.of_type t, let open Operator in match t, op with - | Type.Prim Type.Text, _ -> Blob.compare env op + | Type.(Prim (Text|Blob)), _ -> Blob.compare env op | _, EqOp -> compile_eq env t | _, NeqOp -> compile_eq env t ^^ G.i (Test (Wasm.Values.I32 I32Op.Eqz)) diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index 8707b236e28..73067aba089 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -127,6 +127,7 @@ let prim = function | "Float" -> Float | "Char" -> Char | "Text" -> Text + | "Blob" -> Blob | "Error" -> Error | s -> raise (Invalid_argument ("Type.prim: " ^ s)) diff --git a/src/mo_values/operator.ml b/src/mo_values/operator.ml index 378fbf18652..fc0643bc335 100644 --- a/src/mo_values/operator.ml +++ b/src/mo_values/operator.ml @@ -147,26 +147,27 @@ let num_relop fnat (fnat8, fnat16, fnat32, fnat64) fint (fint8, fint16, fint32, | T.Float -> fun v1 v2 -> Bool (ffloat (as_float v1) (as_float v2)) | t -> word_relop fwords t -let ord_relop fnat fnats fint fints fwords ffloat fchar ftext = function +let ord_relop fnat fnats fint fints fwords ffloat fchar ftext fblob = function | T.Char -> fun v1 v2 -> Bool (fchar (as_char v1) (as_char v2)) | T.Text -> fun v1 v2 -> Bool (ftext (as_text v1) (as_text v2)) + | T.Blob -> fun v1 v2 -> Bool (ftext (as_text v1) (as_text v2)) | t -> num_relop fnat fnats fint fints fwords ffloat t -let eq_relop fnat fnats fint fints fwords ffloat fchar ftext fnull fbool = function +let eq_relop fnat fnats fint fints fwords ffloat fchar ftext fblob fnull fbool = function | T.Null -> fun v1 v2 -> Bool (fnull (as_null v1) (as_null v2)) | T.Bool -> fun v1 v2 -> Bool (fbool (as_bool v1) (as_bool v2)) - | t -> ord_relop fnat fnats fint fints fwords ffloat fchar ftext t + | t -> ord_relop fnat fnats fint fints fwords ffloat fchar ftext fblob t let relop op t = match t with - | T.Prim p -> + | T.Prim p -> (match op with - | EqOp -> eq_relop Nat.eq (Nat8.eq, Nat16.eq, Nat32.eq, Nat64.eq) Int.eq (Int_8.eq, Int_16.eq, Int_32.eq, Int_64.eq) (Word8.eq, Word16.eq, Word32.eq, Word64.eq) Float.eq (=) (=) (=) (=) p - | NeqOp -> eq_relop Nat.ne (Nat8.ne, Nat16.ne, Nat32.ne, Nat64.ne) Int.ne (Int_8.ne, Int_16.ne, Int_32.ne, Int_64.ne) (Word8.ne, Word16.ne, Word32.ne, Word64.ne) Float.ne (<>) (<>) (<>) (<>) p - | LtOp -> ord_relop Nat.lt (Nat8.lt, Nat16.lt, Nat32.lt, Nat64.lt) Int.lt (Int_8.lt, Int_16.lt, Int_32.lt, Int_64.lt) (Word8.lt_u, Word16.lt_u, Word32.lt_u, Word64.lt_u) Float.lt (<) (<) p - | GtOp -> ord_relop Nat.gt (Nat8.gt, Nat16.gt, Nat32.gt, Nat64.gt) Int.gt (Int_8.gt, Int_16.gt, Int_32.gt, Int_64.gt) (Word8.gt_u, Word16.gt_u, Word32.gt_u, Word64.gt_u) Float.gt (>) (>) p - | LeOp -> ord_relop Nat.le (Nat8.le, Nat16.le, Nat32.le, Nat64.le) Int.le (Int_8.le, Int_16.le, Int_32.le, Int_64.le) (Word8.le_u, Word16.le_u, Word32.le_u, Word64.le_u) Float.le (<=) (<=) p - | GeOp -> ord_relop Nat.ge (Nat8.ge, Nat16.ge, Nat32.ge, Nat64.ge) Int.ge (Int_8.ge, Int_16.ge, Int_32.ge, Int_64.ge) (Word8.ge_u, Word16.ge_u, Word32.ge_u, Word64.ge_u) Float.ge (>=) (>=) p + | EqOp -> eq_relop Nat.eq (Nat8.eq, Nat16.eq, Nat32.eq, Nat64.eq) Int.eq (Int_8.eq, Int_16.eq, Int_32.eq, Int_64.eq) (Word8.eq, Word16.eq, Word32.eq, Word64.eq) Float.eq (=) (=) (=) (=) (=) p + | NeqOp -> eq_relop Nat.ne (Nat8.ne, Nat16.ne, Nat32.ne, Nat64.ne) Int.ne (Int_8.ne, Int_16.ne, Int_32.ne, Int_64.ne) (Word8.ne, Word16.ne, Word32.ne, Word64.ne) Float.ne (<>) (<>) (<>) (<>) (<>) p + | LtOp -> ord_relop Nat.lt (Nat8.lt, Nat16.lt, Nat32.lt, Nat64.lt) Int.lt (Int_8.lt, Int_16.lt, Int_32.lt, Int_64.lt) (Word8.lt_u, Word16.lt_u, Word32.lt_u, Word64.lt_u) Float.lt (<) (<) (<) p + | GtOp -> ord_relop Nat.gt (Nat8.gt, Nat16.gt, Nat32.gt, Nat64.gt) Int.gt (Int_8.gt, Int_16.gt, Int_32.gt, Int_64.gt) (Word8.gt_u, Word16.gt_u, Word32.gt_u, Word64.gt_u) Float.gt (>) (>) (>) p + | LeOp -> ord_relop Nat.le (Nat8.le, Nat16.le, Nat32.le, Nat64.le) Int.le (Int_8.le, Int_16.le, Int_32.le, Int_64.le) (Word8.le_u, Word16.le_u, Word32.le_u, Word64.le_u) Float.le (<=) (<=) (<=) p + | GeOp -> ord_relop Nat.ge (Nat8.ge, Nat16.ge, Nat32.ge, Nat64.ge) Int.ge (Int_8.ge, Int_16.ge, Int_32.ge, Int_64.ge) (Word8.ge_u, Word16.ge_u, Word32.ge_u, Word64.ge_u) Float.ge (>=) (>=) (>=) p ) | T.Non -> impossible | _ -> raise (Invalid_argument "relop") diff --git a/src/prelude/prelude.ml b/src/prelude/prelude.ml index d8f8e8170be..ea84d7aa81e 100644 --- a/src/prelude/prelude.ml +++ b/src/prelude/prelude.ml @@ -21,6 +21,7 @@ type Word64 = prim "Word64"; type Float = prim "Float"; type Char = prim "Char"; type Text = prim "Text"; +type Blob = prim "Blob"; type Error = prim "Error"; type Iter = {next : () -> ?T_}; diff --git a/test/run/blobs.mo b/test/run/blobs.mo new file mode 100644 index 00000000000..4e55a41d243 --- /dev/null +++ b/test/run/blobs.mo @@ -0,0 +1,7 @@ +func foo(b1 : Blob, b2 : Blob) { + ignore (b1 == b2); + ignore (b1 < b2); + ignore (b1 <= b2); + ignore (b1 > b2); + ignore (b1 >= b2); +} From 5b457a0552436f07830f43bfc1a618969745592a Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Mon, 2 Dec 2019 17:41:38 +0100 Subject: [PATCH 0754/1176] Implement type-annotated object field matching (#964) * accept shorthand annotated field pattern syntax * add tests --- src/mo_frontend/parser.mly | 2 ++ test/run/objects1.mo | 11 ++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/mo_frontend/parser.mly b/src/mo_frontend/parser.mly index e0e726e1650..c6e6410e418 100644 --- a/src/mo_frontend/parser.mly +++ b/src/mo_frontend/parser.mly @@ -592,6 +592,8 @@ pat_field : { {id = x; pat = VarP x @! x.at} @@ at $sloc } | x=id EQ p=pat { {id = x; pat = p} @@ at $sloc } + | x=id COLON t=typ + { {id = x; pat = AnnotP(VarP x @! x.at, t) @! t.at} @@ at $sloc } (* Declarations *) diff --git a/test/run/objects1.mo b/test/run/objects1.mo index ef91c97ead3..265f11f301f 100644 --- a/test/run/objects1.mo +++ b/test/run/objects1.mo @@ -44,4 +44,13 @@ func foo () : Int = switch row { case (a : Int, -42, {c} : {c : Char}) (word32ToNat(charToWord32 c)) // OK }; -assert (foo () == 67) +assert (foo () == 67); + +// matching on type-annotated fields + +func baz () : Int = switch {a = 42} { + case {a : Int} a // OK +}; + +func full_name({first_name : Text; last_name : Text}) : Text = + first_name # " " # last_name; From 213ddb04c7c38db03db17dcbd97bb1d80422b5e8 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 2 Dec 2019 17:55:12 +0100 Subject: [PATCH 0755/1176] Switch to `winter` branch with performance tweaks (#961) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Switch to `winter` branch with performance tweaks in particular, a branch that merges https://github.com/dfinity/winter/pull/2 https://github.com/dfinity/winter/pull/3 https://github.com/dfinity/winter/pull/6 * Track winter “master” --- ic-stub/src/IC/Wasm/Winter.hs | 7 ++----- ic-stub/src/IC/Wasm/Winter/Persist.hs | 9 ++++----- nix/haskell-packages.nix | 6 +++--- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/ic-stub/src/IC/Wasm/Winter.hs b/ic-stub/src/IC/Wasm/Winter.hs index 2fe17e1aa79..af44f9e6996 100644 --- a/ic-stub/src/IC/Wasm/Winter.hs +++ b/ic-stub/src/IC/Wasm/Winter.hs @@ -37,7 +37,6 @@ import Control.Monad.ST import Data.Binary.Get (runGetOrFail) import Data.Default.Class (Default (..)) import Data.Int -import qualified Data.Vector as V import qualified Wasm.Binary.Decode as W import qualified Wasm.Exec.Eval as W @@ -115,13 +114,11 @@ getBytes :: Instance s -> W.Address -> W.Size -> HostM s BS.ByteString getBytes (mods', ref) ptr len = do let inst = mods' IM.! ref let mem = head (W._miMemories inst) - vec <- withExceptT show $ W.loadBytes mem ptr len - return $ BS.pack $ V.toList vec + withExceptT show $ W.loadBytes mem ptr len setBytes :: Instance s -> W.Address -> BS.ByteString -> HostM s () setBytes (mods', ref) ptr blob = do let inst = mods' IM.! ref let mem = head (W._miMemories inst) - withExceptT show $ - W.storeBytes mem (fromIntegral ptr) (V.fromList (BS.unpack blob)) + withExceptT show $ W.storeBytes mem (fromIntegral ptr) blob diff --git a/ic-stub/src/IC/Wasm/Winter/Persist.hs b/ic-stub/src/IC/Wasm/Winter/Persist.hs index 66c637538d6..b7ff5753085 100644 --- a/ic-stub/src/IC/Wasm/Winter/Persist.hs +++ b/ic-stub/src/IC/Wasm/Winter/Persist.hs @@ -23,8 +23,7 @@ import Data.Primitive.MutVar import qualified Data.IntMap as IM import qualified Data.Map.Lazy as M import qualified Data.Text.Lazy as T -import Data.Word -import qualified Data.Vector.Unboxed as V +import Data.ByteString.Lazy (ByteString) import qualified Wasm.Runtime.Global as W import qualified Wasm.Runtime.Instance as W @@ -54,10 +53,10 @@ class Monad (M a) => Persistable a where resume :: a -> Persisted a -> M a () instance Persistable (W.MemoryInst (ST s)) where - type Persisted (W.MemoryInst (ST s)) = V.Vector Word8 + type Persisted (W.MemoryInst (ST s)) = ByteString type M (W.MemoryInst (ST s)) = ST s - persist m = readMutVar (W._miContent m) >>= V.freeze - resume m v = V.thaw v >>= writeMutVar (W._miContent m) + persist = W.exportMemory + resume = W.importMemory instance Persistable (W.GlobalInst (ST s)) where type Persisted (W.GlobalInst (ST s)) = W.Value diff --git a/nix/haskell-packages.nix b/nix/haskell-packages.nix index 0061c9e5876..c9c1c699885 100644 --- a/nix/haskell-packages.nix +++ b/nix/haskell-packages.nix @@ -98,10 +98,10 @@ nix: subpath: winter = self.callCabal2nixWithOptions "winter" (nix.fetchFromGitHub { - owner = "nomeata"; + owner = "dfinity"; repo = "winter"; - rev = "eb8add32c7de95ccdaf1c896f894814833633bbc"; - sha256 = "05pa6fwvs7galf0gnjngampfdfrki8zjd92f4hzr9yv75jxzv10v"; + rev = "4295ff98da8ca890e824130152a78892ad6420ba"; + sha256 = "05wr3066mlz7hh2s49wgf9pgdsh1bsivnhp6j7hklmw2cnj9g0sl"; }) "--no-check" {}; ic-stub = self.callCabal2nixWithOptions "ic-stub" (subpath "ic-stub") "-frelease" { }; From 2067926801e2b8d720c7a7961d45322e5ab5cf4c Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 2 Dec 2019 22:42:04 +0100 Subject: [PATCH 0756/1176] IDL encoder: Write function annotations (#967) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Test case: Returning functions with annotations * IDL encoder: Write function annotations now that our type system has an idea of what’s a query and what’s a one-way-function, the IDL encoder should properly set the annotation flags. This fixes an omission thatn @chenyan-dfinity menitioned at https://github.com/dfinity-lab/motoko/pull/949#discussion_r352815889 --- src/codegen/compile.ml | 10 +++++++++- test/run-drun/idl-func.mo | 14 +++++++++----- test/run-drun/ok/idl-func.drun-run.ok | 2 ++ 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index e455e622b36..cb75d84fef1 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -3503,7 +3503,15 @@ module Serialization = struct List.iter add_idx ts1; add_leb128 (List.length ts2); List.iter add_idx ts2; - add_leb128 0 (* no annotations *) + begin match s, c with + | _, Returns -> + add_leb128 1; add_u8 2; (* oneway *) + | Shared Write, _ -> + add_leb128 0; (* no annotation *) + | Shared Query, _ -> + add_leb128 1; add_u8 1; (* query *) + | _ -> assert false + end | Obj (Actor, fs) -> add_sleb128 (-23); add_leb128 (List.length fs); diff --git a/test/run-drun/idl-func.mo b/test/run-drun/idl-func.mo index 1d90a7c72cf..3ef2b3e4138 100644 --- a/test/run-drun/idl-func.mo +++ b/test/run-drun/idl-func.mo @@ -1,16 +1,20 @@ type Func = shared Int -> async Func; +type Query = shared query () -> async ?Func; +type Oneway = shared () -> (); actor { - public query func fun() : async ?Func { - null - }; - public query func fun2(arg : ?Func) : async () { - }; + public func oneway() {}; + public query func fun() : async ?Func { null }; + public query func fun2(arg : ?Func) : async () { }; + public query func fun3() : async Query { fun }; + public query func fun4() : async Oneway { oneway }; } //CALL query fun 0x4449444C0000 //CALL query fun2 0x4449444c026e016a017c0000010000 +//CALL query fun3 0x4449444C0000 +//CALL query fun4 0x4449444C0000 //SKIP run //SKIP run-ir diff --git a/test/run-drun/ok/idl-func.drun-run.ok b/test/run-drun/ok/idl-func.drun-run.ok index 408aa441387..f2b11cd7e85 100644 --- a/test/run-drun/ok/idl-func.drun-run.ok +++ b/test/run-drun/ok/idl-func.drun-run.ok @@ -1,3 +1,5 @@ ingress(0) System Ok: Payload: 0x4449444c026e016a017c010100010000 Ok: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c036a00010101016e026a017c01020001000101082a000000000000000366756e +Ok: Payload: 0x4449444c016a0000010201000101082a00000000000000066f6e65776179 From a971f4ede6172941894d872b699abeb1ba07a468 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 3 Dec 2019 16:25:53 +0100 Subject: [PATCH 0757/1176] Bump drun (#969) mainly to get https://github.com/dfinity-lab/dfinity/pull/2018 other changes: ``` c1cce4a71 (HEAD -> master, origin/master, origin/HEAD) Merge pull request #1989 from dfinity-lab/johnw/rust_slog 646af6723 Merge pull request #2015 from dfinity-lab/nm-no-repo-root 02a62db97 Squashed crypto/DFN-1005-csp-multisig-sign from cefac7789523599b6d69459375dceb1f9bf414f0 (#1978) 21b473c33 Merge pull request #2016 from dfinity-lab/johnw/procman 5a6a3155c fixes msg_reject ac09f8fb8 fixes msg_reject_msg_copy 9e0571453 fixes msg_reject_msg_size 73109b4fc fixes msg_reject_code 997fdc096 Merge pull request #2004 from dfinity-lab/nm-release-drun f6c480191 Add a StateManager method to access the latest state. (#2008) 896713019 Initial outline for DKG component structure (#1936) 1b8057a92 Merge pull request #2010 from dfinity-lab/mw/update-wasmtime-example ``` --- default.nix | 2 +- src/codegen/compile.ml | 17 ++++------------- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/default.nix b/default.nix index aa282709087..05ecde629a9 100644 --- a/default.nix +++ b/default.nix @@ -22,7 +22,7 @@ let dfinity-src = name = "dfinity-sources"; url = "ssh://git@github.com/dfinity-lab/dfinity"; # ref = "master"; - rev = "af802ab2d5758522525dcdc4c24a0fd95a950449"; + rev = "c1cce4a71ddbeaf044ee15c4da3619a24d447edf"; }; in let dfinity-pkgs = import dfinity-src { inherit (nixpkgs) system; }; in diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index cb75d84fef1..a70fc4b6a59 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -2914,9 +2914,9 @@ module Dfinity = struct E.add_func_import env "ic0" "msg_arg_data_size" [] [I32Type]; E.add_func_import env "ic0" "msg_caller_copy" (i32s 3) []; E.add_func_import env "ic0" "msg_caller_size" [] [I32Type]; + E.add_func_import env "ic0" "msg_reject_code" [] [I32Type]; + E.add_func_import env "ic0" "msg_reject" (i32s 2) []; E.add_func_import env "msg" "reply" [I32Type; I32Type] []; - E.add_func_import env "msg" "reject" [I32Type; I32Type] []; - E.add_func_import env "msg" "reject_code" [] [I32Type]; E.add_func_import env "ic" "trap" [I32Type; I32Type] []; () | Flags.StubMode -> @@ -3081,22 +3081,13 @@ module Dfinity = struct | Flags.ICMode | Flags.StubMode -> arg_instrs ^^ Blob.as_ptr_len env ^^ - begin match E.mode env with - | Flags.ICMode -> system_call env "msg" "reject" - | Flags.StubMode -> system_call env "ic0" "msg_reject" - | _ -> assert false - end + system_call env "ic0" "msg_reject" | _ -> assert false let error_code env = SR.UnboxedWord32, - match E.mode env with - | Flags.ICMode -> - system_call env "msg" "reject_code" - | Flags.StubMode -> - system_call env "ic" "msg_reject_code" - | _ -> assert false + system_call env "ic0" "msg_reject_code" let reply_with_data env = Func.share_code2 env "reply_with_data" (("start", I32Type), ("size", I32Type)) [] ( From 3d929c793789c12584b871ee48f698aef63aec17 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 3 Dec 2019 16:35:02 +0100 Subject: [PATCH 0758/1176] IC Stub: Do not provide `caller` in callbacks (#962) to conform with the Public Spec, which states that `ic.msg_caller` is not available in callbacks. --- ic-stub/src/IC/Canister.hs | 6 +++--- ic-stub/src/IC/Canister/Imp.hs | 13 ++++++------- ic-stub/src/IC/Canister/Interface.hs | 2 +- ic-stub/src/IC/Stub.hs | 6 +++--- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/ic-stub/src/IC/Canister.hs b/ic-stub/src/IC/Canister.hs index ca218e95541..3bc96edfdae 100644 --- a/ic-stub/src/IC/Canister.hs +++ b/ic-stub/src/IC/Canister.hs @@ -33,7 +33,7 @@ data CanisterModule = CanisterModule { init_method :: InitFunc , update_methods :: MethodName ↦ (ExistingCanisters -> EntityId -> Blob -> UpdateFunc) , query_methods :: MethodName ↦ (EntityId -> Blob -> QueryFunc) - , callbacks :: Callback -> ExistingCanisters -> EntityId -> Response -> UpdateFunc + , callbacks :: Callback -> ExistingCanisters -> Response -> UpdateFunc } parseCanister :: Blob -> Either String CanisterModule @@ -56,6 +56,6 @@ concreteToAbstractModule wasm_mod = CanisterModule | n <- exportedFunctions wasm_mod , Just m <- return $ stripPrefix "canister_query " n ] - , callbacks = \cb ex cid res wasm_state -> - invoke wasm_state (CI.Callback cb ex cid res) + , callbacks = \cb ex res wasm_state -> + invoke wasm_state (CI.Callback cb ex res) } diff --git a/ic-stub/src/IC/Canister/Imp.hs b/ic-stub/src/IC/Canister/Imp.hs index bd7f65987b4..b04e62abe1f 100644 --- a/ic-stub/src/IC/Canister/Imp.hs +++ b/ic-stub/src/IC/Canister/Imp.hs @@ -357,8 +357,8 @@ rawInvoke esref (CI.Query name caller dat) = rawQueryMethod esref name caller dat rawInvoke esref (CI.Update name ex caller dat) = rawUpdateMethod esref name ex caller dat -rawInvoke esref (CI.Callback cb ex caller res) = - rawCallbackMethod esref cb ex caller res +rawInvoke esref (CI.Callback cb ex res) = + rawCallbackMethod esref cb ex res rawInitializeMethod :: ImpState s -> ExistingCanisters -> Module -> EntityId -> Blob -> ST s (TrapOr InitResult) rawInitializeMethod (esref, cid, inst) ex wasm_mod caller dat = do @@ -421,14 +421,13 @@ rawUpdateMethod (esref, cid, inst) method ex caller dat = do Left err -> return $ Trap err Right (_, es') -> return $ Return (new_canisters es', calls es', response es') -rawCallbackMethod :: ImpState s -> Callback -> ExistingCanisters -> EntityId -> Response -> ST s (TrapOr UpdateResult) -rawCallbackMethod (esref, cid, inst) callback ex caller res = do - let param_caller = Just caller +rawCallbackMethod :: ImpState s -> Callback -> ExistingCanisters -> Response -> ST s (TrapOr UpdateResult) +rawCallbackMethod (esref, cid, inst) callback ex res = do let params = case res of Reply dat -> - Params { param_dat = Just dat, param_caller, reject_code = 0, reject_message = "" } + Params { param_dat = Just dat, param_caller = Nothing, reject_code = 0, reject_message = "" } Reject (rc, reject_message) -> - Params { param_dat = Nothing, param_caller, reject_code = rejectCode rc, reject_message } + Params { param_dat = Nothing, param_caller = Nothing, reject_code = rejectCode rc, reject_message } let es = (initalExecutionState cid inst ex) { params } let WasmClosure fun_idx env = case res of diff --git a/ic-stub/src/IC/Canister/Interface.hs b/ic-stub/src/IC/Canister/Interface.hs index 93a8755023e..0e2551df33f 100644 --- a/ic-stub/src/IC/Canister/Interface.hs +++ b/ic-stub/src/IC/Canister/Interface.hs @@ -21,4 +21,4 @@ data CanisterMethod r where Initialize :: ExistingCanisters -> Module -> EntityId -> Blob -> CanisterMethod InitResult Query :: MethodName -> EntityId -> Blob -> CanisterMethod Response Update :: MethodName -> ExistingCanisters -> EntityId -> Blob -> CanisterMethod UpdateResult - Callback :: Callback -> ExistingCanisters -> EntityId -> Response -> CanisterMethod UpdateResult + Callback :: Callback -> ExistingCanisters -> Response -> CanisterMethod UpdateResult diff --git a/ic-stub/src/IC/Stub.hs b/ic-stub/src/IC/Stub.hs index dea3114ec99..896ebac94dd 100644 --- a/ic-stub/src/IC/Stub.hs +++ b/ic-stub/src/IC/Stub.hs @@ -298,9 +298,9 @@ invokeEntry :: ICT m => m (TrapOr (WasmState, UpdateResult)) invokeEntry ctxt_id (CanState wasm_state can_mod) entry = do existing_canisters <- gets (M.keys . canisters) - caller <- callerOfCallID ctxt_id case entry of - Public method dat -> + Public method dat -> do + caller <- callerOfCallID ctxt_id case M.lookup method (update_methods can_mod) of Just f -> return $ f existing_canisters caller dat wasm_state @@ -308,7 +308,7 @@ invokeEntry ctxt_id (CanState wasm_state can_mod) entry = do let reject = Reject (RC_DESTINATION_INVALID, "update method does not exist: " ++ method) return $ Return (wasm_state, ([], [], Just reject)) Closure cb r -> - return $ callbacks can_mod cb existing_canisters caller r wasm_state + return $ callbacks can_mod cb existing_canisters r wasm_state newCall :: ICT m => CallId -> MethodCall -> m () newCall from_ctxt_id call = do From 31fc78f733fd8db3dc9bf7b60237e9b358663fc2 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Tue, 3 Dec 2019 16:48:11 +0100 Subject: [PATCH 0759/1176] Prune haskell packages (#971) * clean up haskell customisations * bump customised packages to latest --- nix/haskell-packages.nix | 28 ++++++---------------------- test/lsp-int/lsp-int.cabal | 2 +- 2 files changed, 7 insertions(+), 23 deletions(-) diff --git a/nix/haskell-packages.nix b/nix/haskell-packages.nix index c9c1c699885..1421efe9417 100644 --- a/nix/haskell-packages.nix +++ b/nix/haskell-packages.nix @@ -8,8 +8,8 @@ nix: subpath: }: mkDerivation { pname = "haskell-lsp-types"; - version = "0.16.0.0"; - sha256 = "14wlv54ydbddpw6cwgykcas3rb55w7m78q0s1wdbi594wg1bscqg"; + version = "0.18.0.0"; + sha256 = "1ypa3gxxcg7dl905d4nprcqzw2fcl7z7xy1hpg5har1dw3w9fyiq"; libraryHaskellDepends = [ aeson base bytestring data-default deepseq filepath hashable lens network-uri scientific text unordered-containers @@ -19,22 +19,6 @@ nix: subpath: hydraPlatforms = stdenv.lib.platforms.none; }) {}; - rope-utf16-splay = self.callPackage - ({ mkDerivation, base, QuickCheck, tasty, tasty-hunit - , tasty-quickcheck, text - }: - mkDerivation { - pname = "rope-utf16-splay"; - version = "0.3.1.0"; - sha256 = "1ilcgwmdwqnp95vb7652fc03ji9dnzy6cm24pvbiwi2mhc4piy6b"; - libraryHaskellDepends = [ base text ]; - testHaskellDepends = [ - base QuickCheck tasty tasty-hunit tasty-quickcheck text - ]; - description = "Ropes optimised for updating using UTF-16 code units and row/column pairs"; - license = stdenv.lib.licenses.bsd3; - }) {}; - haskell-lsp = self.callPackage ({ mkDerivation, aeson, async, attoparsec, base, bytestring , containers, data-default, directory, filepath, hashable @@ -44,8 +28,8 @@ nix: subpath: }: mkDerivation { pname = "haskell-lsp"; - version = "0.16.0.0"; - sha256 = "1s04lfnb3c0g9bkwp4j7j59yw8ypps63dq27ayybynrfci4bpj95"; + version = "0.18.0.0"; + sha256 = "0q9xpjgr3n7svhd9f7mmkw113avswvfm08fnbijdr1sblipd12sl"; isLibrary = true; isExecutable = true; libraryHaskellDepends = [ @@ -74,8 +58,8 @@ nix: subpath: }: mkDerivation { pname = "lsp-test"; - version = "0.7.0.0"; - sha256 = "1lm299gbahrnwfrprhhpzxrmjljj33pps1gzz2wzmp3m9gzl1dx5"; + version = "0.8.2.0"; + sha256 = "1762avrs4fkkd9v8i76giaf6km5f3lds5laickn7la7zq7ysh8a3"; libraryHaskellDepends = [ aeson aeson-pretty ansi-terminal async base bytestring conduit conduit-parse containers data-default Diff directory filepath diff --git a/test/lsp-int/lsp-int.cabal b/test/lsp-int/lsp-int.cabal index 436e19d917f..45cfb8dac78 100644 --- a/test/lsp-int/lsp-int.cabal +++ b/test/lsp-int/lsp-int.cabal @@ -22,6 +22,6 @@ executable lsp-int , lens , data-default , haskell-lsp-types - , lsp-test ^>=0.7.0.0 + , lsp-test ^>=0.8 -- hs-source-dirs: default-language: Haskell2010 From 62f6e414583d0c7efa1bce04690f4bbc4d789fba Mon Sep 17 00:00:00 2001 From: chenyan-dfinity <48968912+chenyan-dfinity@users.noreply.github.com> Date: Tue, 3 Dec 2019 10:33:08 -0800 Subject: [PATCH 0760/1176] update compile_js to be compatible with the new JS lib (#968) * update compile_js to be compatible with the new JS lib * bump sdk * fix test --- default.nix | 2 +- src/idllib/compile_js.ml | 18 ++++++++++++++++-- test/idl/ok/actor.js.ok | 8 ++++---- test/idl/ok/cyclic.js.ok | 2 +- test/idl/ok/diamond.js.ok | 3 ++- test/idl/ok/escape.js.ok | 2 +- test/idl/ok/fieldnat.js.ok | 8 ++++---- test/idl/ok/fields.js.ok | 2 +- test/idl/ok/import.js.ok | 4 ++-- test/idl/ok/import1.js.ok | 3 ++- test/idl/ok/import3.js.ok | 10 ++++++---- test/idl/ok/integer.js.ok | 6 +++--- test/idl/ok/keywords.js.ok | 5 +++-- test/idl/ok/px.js.ok | 3 ++- test/idl/ok/recursion.js.ok | 10 ++++++---- test/idl/ok/test.js.ok | 18 +++++++++--------- test/idl/ok/unicode.js.ok | 7 ++++--- 17 files changed, 67 insertions(+), 44 deletions(-) diff --git a/default.nix b/default.nix index 05ecde629a9..817695eab7b 100644 --- a/default.nix +++ b/default.nix @@ -31,7 +31,7 @@ let sdk = import (builtins.fetchGit { name = "sdk-sources"; url = "ssh://git@github.com/dfinity-lab/sdk"; ref = "master"; - rev = "7ee8cc40abab5b33c68bc8a32412e5be33a9f410"; + rev = "d7559c97edfcdfdb1ded48b551cb51de60e87d04"; }) { inherit (nixpkgs) system; }; in let esm = builtins.fetchTarball { diff --git a/src/idllib/compile_js.ml b/src/idllib/compile_js.ml index 983cb104083..9276a33f4d1 100644 --- a/src/idllib/compile_js.ml +++ b/src/idllib/compile_js.ml @@ -91,7 +91,12 @@ let pp_prim p = | Null -> "Unit" | Reserved -> "None" | Empty -> "Empty" - + +let pp_mode ppf m = + match m.it with + | Oneway -> str ppf "'oneway'" + | Query -> str ppf "'query'" + let rec concat ppf f sep list = match list with | [] -> () @@ -112,6 +117,8 @@ let rec pp_typ ppf t = pp_args ppf t1; kwd ppf ","; pp_args ppf t2; + kwd ppf ","; + pp_modes ppf ms; str ppf ")"; | ServT ts -> pp_open_hovbox ppf 1; @@ -131,6 +138,13 @@ and pp_args ppf args = str ppf "]"; pp_close_box ppf () +and pp_modes ppf modes = + pp_open_box ppf 1; + str ppf "["; + concat ppf pp_mode "," modes; + str ppf "]"; + pp_close_box ppf () + and pp_fields ppf fs = pp_open_box ppf 1; str ppf "IDL.Obj({"; @@ -196,7 +210,7 @@ let pp_actor ppf actor recs = | VarT var -> id ppf x; space ppf (); kwd ppf "="; if TS.mem var.it recs then - str ppf (var.it ^ ".__typ;") + str ppf (var.it ^ ".getType();") else str ppf var.it; | _ -> assert false diff --git a/test/idl/ok/actor.js.ok b/test/idl/ok/actor.js.ok index 2370c62aa8c..c1e32cab6ac 100644 --- a/test/idl/ok/actor.js.ok +++ b/test/idl/ok/actor.js.ok @@ -1,10 +1,10 @@ export default ({ IDL }) => { const o = IDL.Rec() - const f = IDL.Func([IDL.Int8], [IDL.Int8]) - const h = IDL.Func([f], [f]) + const f = IDL.Func([IDL.Int8], [IDL.Int8], []) + const h = IDL.Func([f], [f], []) const g = f o.fill(IDL.Opt(o)) - const actor_g = new IDL.ActorInterface({'f': IDL.Func([IDL.Nat], [h]), - 'g': f, 'h': g, 'o': IDL.Func([o], [o])}); + const actor_g = new IDL.ActorInterface({'f': IDL.Func([IDL.Nat], [h], []), + 'g': f, 'h': g, 'o': IDL.Func([o], [o], [])}); return actor_g; }; diff --git a/test/idl/ok/cyclic.js.ok b/test/idl/ok/cyclic.js.ok index 4aba8bf66cd..3e62e4842d0 100644 --- a/test/idl/ok/cyclic.js.ok +++ b/test/idl/ok/cyclic.js.ok @@ -7,6 +7,6 @@ export default ({ IDL }) => { const Y = Z const X = Y const actor_S = new IDL.ActorInterface({ - 'f': IDL.Func([A, B, C, X, Y, Z], [])}); + 'f': IDL.Func([A, B, C, X, Y, Z], [], [])}); return actor_S; }; diff --git a/test/idl/ok/diamond.js.ok b/test/idl/ok/diamond.js.ok index 2e957b9362b..ab6f5a0ed9d 100644 --- a/test/idl/ok/diamond.js.ok +++ b/test/idl/ok/diamond.js.ok @@ -3,6 +3,7 @@ export default ({ IDL }) => { const t2 = IDL.Arr(t) const t3 = IDL.Opt(t) const t1 = IDL.Obj({'0': t2, '1': t3, '2': t}) - const actor_S = new IDL.ActorInterface({'f': IDL.Func([t, t2, t3], [t1])}); + const actor_S = new IDL.ActorInterface({'f': IDL.Func([t, t2, t3], [t1], []) + }); return actor_S; }; diff --git a/test/idl/ok/escape.js.ok b/test/idl/ok/escape.js.ok index c39ee2a7772..4d79a82e592 100644 --- a/test/idl/ok/escape.js.ok +++ b/test/idl/ok/escape.js.ok @@ -3,6 +3,6 @@ export default ({ IDL }) => { IDL.Obj({'\"': IDL.Nat, '\'': IDL.Nat, '\"\'': IDL.Nat, '\\\n\'\"': IDL.Nat }) const actor_E = new IDL.ActorInterface({ - '\n\'\"\'\'\"\"\r\t': IDL.Func([t], [])}); + '\n\'\"\'\'\"\"\r\t': IDL.Func([t], [], [])}); return actor_E; }; diff --git a/test/idl/ok/fieldnat.js.ok b/test/idl/ok/fieldnat.js.ok index 60b621faf12..a7773235ac7 100644 --- a/test/idl/ok/fieldnat.js.ok +++ b/test/idl/ok/fieldnat.js.ok @@ -1,8 +1,8 @@ export default ({ IDL }) => { const actor_Foo = new IDL.ActorInterface({ - 'foo': IDL.Func([IDL.Obj({'2': IDL.Int})], []), - 'bar': IDL.Func([IDL.Obj({'2': IDL.Int})], []), - 'baz': IDL.Func([IDL.Obj({'2': IDL.Int, '2': IDL.Nat})], []), - 'bab': IDL.Func([IDL.Int, IDL.Nat], [])}); + 'foo': IDL.Func([IDL.Obj({'2': IDL.Int})], [], []), + 'bar': IDL.Func([IDL.Obj({'2': IDL.Int})], [], []), + 'baz': IDL.Func([IDL.Obj({'2': IDL.Int, '2': IDL.Nat})], [], []), + 'bab': IDL.Func([IDL.Int, IDL.Nat], [], [])}); return actor_Foo; }; diff --git a/test/idl/ok/fields.js.ok b/test/idl/ok/fields.js.ok index 71e1f4e4ad7..95d64834951 100644 --- a/test/idl/ok/fields.js.ok +++ b/test/idl/ok/fields.js.ok @@ -14,6 +14,6 @@ export default ({ IDL }) => { '3': IDL.Obj({'0': IDL.Nat, '1': IDL.Nat, '2': IDL.Nat}), '4': IDL.Nat, '5': IDL.Nat, '6': IDL.Nat, '7': A, '8': B, '9': C, '10': IDL.Nat}) const actor_S = new IDL.ActorInterface({ - 'f': IDL.Func([A, B, C, nest_record], [])}); + 'f': IDL.Func([A, B, C, nest_record], [], [])}); return actor_S; }; diff --git a/test/idl/ok/import.js.ok b/test/idl/ok/import.js.ok index 1a56ff8bf8f..a422910dad1 100644 --- a/test/idl/ok/import.js.ok +++ b/test/idl/ok/import.js.ok @@ -12,7 +12,7 @@ export default ({ IDL }) => { const IdErr = IDL.Obj({'idErr': OpEntId}) const Inventory = IDL.Obj({'produce_id': IDL.Nat, 'quantity': IDL.Nat}) const actor_S = new IDL.ActorInterface({ - 'f': IDL.Func([t, t1, t2], [list, IdErr]), - 'getInventory': IDL.Func([IDL.Nat], [Inventory])}); + 'f': IDL.Func([t, t1, t2], [list, IdErr], []), + 'getInventory': IDL.Func([IDL.Nat], [Inventory], ['query'])}); return actor_S; }; diff --git a/test/idl/ok/import1.js.ok b/test/idl/ok/import1.js.ok index f9f378b390b..b820edecdfe 100644 --- a/test/idl/ok/import1.js.ok +++ b/test/idl/ok/import1.js.ok @@ -3,6 +3,7 @@ export default ({ IDL }) => { const t1 = t const UserId = IDL.Nat const t2 = UserId - const actor_S = new IDL.ActorInterface({'f': IDL.Func([t, t1, t2], [])}); + const actor_S = new IDL.ActorInterface({'f': IDL.Func([t, t1, t2], [], []) + }); return actor_S; }; diff --git a/test/idl/ok/import3.js.ok b/test/idl/ok/import3.js.ok index d6beb90cb66..af87b4f2b00 100644 --- a/test/idl/ok/import3.js.ok +++ b/test/idl/ok/import3.js.ok @@ -4,7 +4,7 @@ export default ({ IDL }) => { const s = IDL.Rec() const stream = IDL.Rec() const tree = IDL.Rec() - const t = IDL.Func([s], []) + const t = IDL.Func([s], [], []) const node = IDL.Obj({'head': IDL.Nat, 'tail': list}) list.fill(IDL.Opt(node)) const A = B @@ -14,9 +14,11 @@ export default ({ IDL }) => { 'branch': IDL.Obj({'val': IDL.Int, 'left': tree, 'right': tree}), 'leaf': IDL.Int})) stream.fill( - IDL.Opt(IDL.Obj({'head': IDL.Nat, 'next': IDL.Func([], [stream])}))) + IDL.Opt( + IDL.Obj({'head': IDL.Nat, 'next': IDL.Func([], [stream], ['query'])}))) s.fill( - new IDL.ActorInterface({'f': t, 'g': IDL.Func([list], [B, tree, stream])})) - const actor_S = s.__typ; + new IDL.ActorInterface({'f': t, + 'g': IDL.Func([list], [B, tree, stream], [])})) + const actor_S = s.getType(); return actor_S; }; diff --git a/test/idl/ok/integer.js.ok b/test/idl/ok/integer.js.ok index c0dc38ae2e4..dc3d0e6eda9 100644 --- a/test/idl/ok/integer.js.ok +++ b/test/idl/ok/integer.js.ok @@ -1,7 +1,7 @@ export default ({ IDL }) => { const actor_num = new IDL.ActorInterface({ - 'f': IDL.Func([IDL.Nat8], [IDL.Int16]), - 'g': IDL.Func([IDL.Nat64], [IDL.Int64]), - 'h': IDL.Func([IDL.Int8], [IDL.Nat])}); + 'f': IDL.Func([IDL.Nat8], [IDL.Int16], []), + 'g': IDL.Func([IDL.Nat64], [IDL.Int64], []), + 'h': IDL.Func([IDL.Int8], [IDL.Nat], [])}); return actor_num; }; diff --git a/test/idl/ok/keywords.js.ok b/test/idl/ok/keywords.js.ok index 338022c9e51..cd57bc9004d 100644 --- a/test/idl/ok/keywords.js.ok +++ b/test/idl/ok/keywords.js.ok @@ -2,8 +2,9 @@ export default ({ IDL }) => { const const_ = IDL.Obj({'type_': IDL.Nat, 'vec_': IDL.Nat, 'service_': IDL.Nat}) const actor_s = new IDL.ActorInterface({ - 'blob': IDL.Func([const_], [IDL.Arr(IDL.Nat8)]), + 'blob': IDL.Func([const_], [IDL.Arr(IDL.Nat8)], []), 'record': - IDL.Func([IDL.Nat, IDL.Nat, IDL.Variant({})], [IDL.Nat, IDL.Obj({})])}); + IDL.Func([IDL.Nat, IDL.Nat, IDL.Variant({})], [IDL.Nat, IDL.Obj({})], []) + }); return actor_s; }; diff --git a/test/idl/ok/px.js.ok b/test/idl/ok/px.js.ok index 1ae4b25bbf0..7139338968f 100644 --- a/test/idl/ok/px.js.ok +++ b/test/idl/ok/px.js.ok @@ -13,6 +13,7 @@ export default ({ IDL }) => { const OpEntId = IDL.Opt(EntId) const IdErr = IDL.Obj({'idErr': OpEntId}) const actor_ProduceExchange = new IDL.ActorInterface({ - 'getInventory': IDL.Func([IDL.Nat, UserInfo], [Inventory, IdErr])}); + 'getInventory': + IDL.Func([IDL.Nat, UserInfo], [Inventory, IdErr], ['query'])}); return actor_ProduceExchange; }; diff --git a/test/idl/ok/recursion.js.ok b/test/idl/ok/recursion.js.ok index 747b82cfdec..ad7e4d49be7 100644 --- a/test/idl/ok/recursion.js.ok +++ b/test/idl/ok/recursion.js.ok @@ -4,7 +4,7 @@ export default ({ IDL }) => { const s = IDL.Rec() const stream = IDL.Rec() const tree = IDL.Rec() - const t = IDL.Func([s], []) + const t = IDL.Func([s], [], []) const node = IDL.Obj({'head': IDL.Nat, 'tail': list}) list.fill(IDL.Opt(node)) const A = B @@ -14,9 +14,11 @@ export default ({ IDL }) => { 'branch': IDL.Obj({'val': IDL.Int, 'left': tree, 'right': tree}), 'leaf': IDL.Int})) stream.fill( - IDL.Opt(IDL.Obj({'head': IDL.Nat, 'next': IDL.Func([], [stream])}))) + IDL.Opt( + IDL.Obj({'head': IDL.Nat, 'next': IDL.Func([], [stream], ['query'])}))) s.fill( - new IDL.ActorInterface({'f': t, 'g': IDL.Func([list], [B, tree, stream])})) - const actor_A = s.__typ; + new IDL.ActorInterface({'f': t, + 'g': IDL.Func([list], [B, tree, stream], [])})) + const actor_A = s.getType(); return actor_A; }; diff --git a/test/idl/ok/test.js.ok b/test/idl/ok/test.js.ok index 1ea953ff2a5..f51cf54ee8e 100644 --- a/test/idl/ok/test.js.ok +++ b/test/idl/ok/test.js.ok @@ -7,15 +7,15 @@ export default ({ IDL }) => { 'find': IDL.Func([IDL.Text], [ - new IDL.ActorInterface({'up': IDL.Func([], []), - 'current': IDL.Func([], [IDL.Nat])}) - ]) - }) + new IDL.ActorInterface({'up': IDL.Func([], [], []), + 'current': IDL.Func([], [IDL.Nat], [])}) + ], + [])}) const actor_server = new IDL.ActorInterface({ - 'addUser': IDL.Func([IDL.Text, IDL.Nat8], [IDL.Nat64]), - 'userName': IDL.Func([IDL.Nat64], [IDL.Text]), - 'userAge': IDL.Func([IDL.Nat64], [IDL.Nat8]), - 'deleteUser': IDL.Func([IDL.Nat64], []), 'f': IDL.Func([message], [broker]) - }); + 'addUser': IDL.Func([IDL.Text, IDL.Nat8], [IDL.Nat64], []), + 'userName': IDL.Func([IDL.Nat64], [IDL.Text], ['query']), + 'userAge': IDL.Func([IDL.Nat64], [IDL.Nat8], ['query']), + 'deleteUser': IDL.Func([IDL.Nat64], [], ['oneway']), + 'f': IDL.Func([message], [broker], [])}); return actor_server; }; diff --git a/test/idl/ok/unicode.js.ok b/test/idl/ok/unicode.js.ok index 9fa4d61d285..26c5cabc17d 100644 --- a/test/idl/ok/unicode.js.ok +++ b/test/idl/ok/unicode.js.ok @@ -5,8 +5,9 @@ export default ({ IDL }) => { const B = IDL.Variant({'': IDL.Unit, '空的': IDL.Unit, ' 空的 ': IDL.Unit, '1⃣️2⃣️3⃣️': IDL.Unit}) - const actor_C = new IDL.ActorInterface({'函数名': IDL.Func([A], [B]), - '': IDL.Func([IDL.Nat], [IDL.Nat]), '👀': IDL.Func([IDL.Nat], [IDL.Nat]), - '✈️ 🚗 ⛱️ ': IDL.Func([], [])}); + const actor_C = new IDL.ActorInterface({'函数名': IDL.Func([A], [B], []), + '': IDL.Func([IDL.Nat], [IDL.Nat], []), + '👀': IDL.Func([IDL.Nat], [IDL.Nat], ['query']), + '✈️ 🚗 ⛱️ ': IDL.Func([], [], ['oneway'])}); return actor_C; }; From b777034ab70a0d4c9700c91437e623e0be9a6a54 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 4 Dec 2019 19:28:57 +0100 Subject: [PATCH 0761/1176] Remove dependency on the SDK repo (#965) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Remove dependency on the SDK repo according to Hans on Slack, they are testing the JS user library there, so we don’t have to, and these cross-repo dependencies are bothering some people who have to deal with the CI implications. So lets get rid of this. We still check that the output of `didc` is valid JS using node, and we any unintentional changes to the output will be flagged by the test suite. * Update test output * Normalize test output better * Do not use `$out/$base.js` twice --- default.nix | 10 ------- ...diamond2.js.out.ok => diamond2.didc-js.ok} | 0 test/idl/ok/diamond2.didc-js.ret.ok | 1 + ...diamond3.js.out.ok => diamond3.didc-js.ok} | 0 test/idl/ok/diamond3.didc-js.ret.ok | 1 + ...diamond4.js.out.ok => diamond4.didc-js.ok} | 0 test/idl/ok/diamond4.didc-js.ret.ok | 1 + test/run.sh | 26 +++++++------------ 8 files changed, 13 insertions(+), 26 deletions(-) rename test/idl/ok/{diamond2.js.out.ok => diamond2.didc-js.ok} (100%) create mode 100644 test/idl/ok/diamond2.didc-js.ret.ok rename test/idl/ok/{diamond3.js.out.ok => diamond3.didc-js.ok} (100%) create mode 100644 test/idl/ok/diamond3.didc-js.ret.ok rename test/idl/ok/{diamond4.js.out.ok => diamond4.didc-js.ok} (100%) create mode 100644 test/idl/ok/diamond4.didc-js.ret.ok diff --git a/default.nix b/default.nix index 817695eab7b..c19f563f57f 100644 --- a/default.nix +++ b/default.nix @@ -27,20 +27,12 @@ let dfinity-src = let dfinity-pkgs = import dfinity-src { inherit (nixpkgs) system; }; in -let sdk = import (builtins.fetchGit { - name = "sdk-sources"; - url = "ssh://git@github.com/dfinity-lab/sdk"; - ref = "master"; - rev = "d7559c97edfcdfdb1ded48b551cb51de60e87d04"; -}) { inherit (nixpkgs) system; }; in - let esm = builtins.fetchTarball { sha256 = "116k10q9v0yzpng9bgdx3xrjm2kppma2db62mnbilbi66dvrvz9q"; url = "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz"; }; in let drun = dfinity-pkgs.drun or dfinity-pkgs.dfinity.drun; in -let js-user-library = sdk.js-user-library; in let haskellPackages = nixpkgs.haskellPackages.override { overrides = import nix/haskell-packages.nix nixpkgs subpath; @@ -246,7 +238,6 @@ rec { export DIDC=didc export DESER=deser export ESM=${esm} - export JS_USER_LIBRARY=${js-user-library} type -p moc && moc --version # run this once to work around self-unpacking-race-condition type -p drun && drun --version @@ -477,7 +468,6 @@ rec { shellHook = llvmEnv; ESM=esm; - JS_USER_LIBRARY=js-user-library; TOMMATHSRC = libtommath; NIX_FONTCONFIG_FILE = users-guide.NIX_FONTCONFIG_FILE; LOCALE_ARCHIVE = stdenv.lib.optionalString stdenv.isLinux "${nixpkgs.glibcLocales}/lib/locale/locale-archive"; diff --git a/test/idl/ok/diamond2.js.out.ok b/test/idl/ok/diamond2.didc-js.ok similarity index 100% rename from test/idl/ok/diamond2.js.out.ok rename to test/idl/ok/diamond2.didc-js.ok diff --git a/test/idl/ok/diamond2.didc-js.ret.ok b/test/idl/ok/diamond2.didc-js.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/idl/ok/diamond2.didc-js.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/idl/ok/diamond3.js.out.ok b/test/idl/ok/diamond3.didc-js.ok similarity index 100% rename from test/idl/ok/diamond3.js.out.ok rename to test/idl/ok/diamond3.didc-js.ok diff --git a/test/idl/ok/diamond3.didc-js.ret.ok b/test/idl/ok/diamond3.didc-js.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/idl/ok/diamond3.didc-js.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/idl/ok/diamond4.js.out.ok b/test/idl/ok/diamond4.didc-js.ok similarity index 100% rename from test/idl/ok/diamond4.js.out.ok rename to test/idl/ok/diamond4.didc-js.ok diff --git a/test/idl/ok/diamond4.didc-js.ret.ok b/test/idl/ok/diamond4.didc-js.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/idl/ok/diamond4.didc-js.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run.sh b/test/run.sh index 73e6bb2e3d4..36b2a40c0bf 100755 --- a/test/run.sh +++ b/test/run.sh @@ -73,6 +73,7 @@ function normalize () { sed 's,/tmp/.*ic.[^/]*,/tmp/ic.XXX,g' | sed 's,/build/.*ic.[^/]*,/tmp/ic.XXX,g' | sed 's/^.*run-dfinity\/\.\.\/drun.sh: line/drun.sh: line/g' | + sed 's,^.*/idl/_out/,..../idl/_out/,g' | # node puts full paths in error messages sed 's,\([a-zA-Z0-9.-]*\).mo.mangled,\1.mo,g' | sed 's/trap at 0x[a-f0-9]*/trap at 0x___:/g' | sed 's/source location: @[a-f0-9]*/source location: @___:/g' | @@ -92,6 +93,12 @@ function run () { if grep -q "^//SKIP $ext" $file; then return 1; fi + if test -e $out/$base.$ext + then + echo "Output $ext already exists." + exit 1 + fi + $ECHO -n " [$ext]" "$@" >& $out/$base.$ext local ret=$? @@ -306,27 +313,14 @@ do $DIDC --check $out/$base.pp.did > $out/$base.pp.tc 2>&1 diff_files="$diff_files $base.pp.tc" - $ECHO -n " [js]" - $DIDC --js $base.did -o $out/$base.js >& $out/$base.js.out + run didc-js $DIDC --js $base.did -o $out/$base.js normalize $out/$base.js - normalize $out/$base.js.out - diff_files="$diff_files $base.js.out $base.js" + diff_files="$diff_files $base.js" if [ -e $out/$base.js ] then - $ECHO -n " [node]" export NODE_PATH=$NODE_PATH:$ESM - - node -r esm $out/$base.js > $out/$base.node 2>&1 - normalize $out/$base.node - diff_files="$diff_files $base.node" - - node -r esm -e \ - "import actorInterface from './$out/$base.js'; - import { makeActor, makeHttpAgent } from '$JS_USER_LIBRARY'; - const httpAgent = makeHttpAgent({ canisterId: \"ffffffffffffffff\" }); - const actor = makeActor(actorInterface)(httpAgent); - assert(Object.entries(actor).length > 0);" + run node node -r esm $out/$base.js fi fi fi From 2808ad5328a1aa81da9c39a77a6a1cda62d20bd5 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Thu, 5 Dec 2019 10:52:57 +0100 Subject: [PATCH 0762/1176] Tweaks Move reference rep to Serialisation section, plus some minor fixes. --- design/IDL.md | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/design/IDL.md b/design/IDL.md index 14644f1aa23..5ef10dd2a7b 100644 --- a/design/IDL.md +++ b/design/IDL.md @@ -434,11 +434,6 @@ An *actor reference* points to a service and is described by an actor type. Thro ::= ... | service ``` -There are two forms of values for actor references: - -* `Ref(r)` indicates an opaque reference, understood only by the underlying system. -* `Id(b)`, where `b : blob`, indicates a transparent reference to a service addressed by the blob `b`. - ##### Example ``` @@ -456,11 +451,6 @@ A *function reference* is described by its function type. For example, they allo ::= func | ... ``` -There are two forms of values for actor references: - -* `Ref(r)` indicates an opaque reference, understood only by the underlying system. -* `Public(s,n)`, where `s : service ` and `n : text`, indicates the public method `n` of the service referenced by `s`. - ##### Example ``` @@ -900,6 +890,21 @@ Note: ### Serialisation +This section describes how abstract *IDL values* of the types described by the IDL are serialised into a binary representation for transfer between actors. + +Serialisation is defined by three functions `T`, `M`, and `R` defined below. + +Most IDL values are self-explanatory, except for references. There are two forms of IDL values for actor references: + +* `ref(r)` indicates an opaque reference, understood only by the underlying system. +* `id(b)`, indicates a transparent reference to a service addressed by the blob `b`. + +Likewise, there are two forms of IDL values for function references: + +* `ref(r)` indicates an opaque reference, understood only by the underlying system. +* `pub(s,n)`, indicates the public method name `n` of the service referenced by `s`. + + #### Notation `T` and `M` create a byte sequence described below in terms of natural storage types (`i` for `N = 8, 16, 32, 64`, `f` for `N = 32, 64`). The bytes are sequenced according to increasing significance (least significant byte first, a.k.a. little-endian). @@ -1017,11 +1022,11 @@ M : (, ) -> -> i8* M((k,v) : k:) = M(v : ) M : -> -> i8* -M(Ref(r) : service ) = i8(0) -M(Id(blob) : service ) = i8(1) M(blob) +M(ref(r) : service ) = i8(0) +M(id(v*) : service ) = i8(1) M(v* : vec i8) -M(Ref(r) : func ) = i8(0) -M(Public(service, name) : func ) = i8(1) M(service) M(name) +M(ref(r) : func ) = i8(0) +M(pub(s,n) : func ) = i8(1) M(s : service {}) M(n : text) ``` @@ -1045,10 +1050,10 @@ R : (, ) -> -> * R((k,v) : k:) = R(v : ) R : -> -> * -R(Ref(r) : service ) = r -R(Id(blob) : service ) = . -R(Ref(r) : func ) = r -R(Public(service, name) : func ) = . +R(ref(r) : service ) = r +R(id(b*) : service ) = . +R(ref(r) : func ) = r +R(pub(s,n) : func ) = . ``` Note: From adc4566533ae23c866bba9a03301926d38a4f65c Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Thu, 5 Dec 2019 10:55:15 +0100 Subject: [PATCH 0763/1176] Eps --- design/IDL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/design/IDL.md b/design/IDL.md index 5ef10dd2a7b..e0692e5699f 100644 --- a/design/IDL.md +++ b/design/IDL.md @@ -892,7 +892,7 @@ Note: This section describes how abstract *IDL values* of the types described by the IDL are serialised into a binary representation for transfer between actors. -Serialisation is defined by three functions `T`, `M`, and `R` defined below. +Serialisation is defined by three functions `T`, `M`, and `R` given below. Most IDL values are self-explanatory, except for references. There are two forms of IDL values for actor references: From e6f09d282500326e6fe2c9c7358768785859a1de Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 5 Dec 2019 19:45:29 +0100 Subject: [PATCH 0764/1176] Bump drun (#977) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mostly to get https://github.com/dfinity-lab/dfinity/pull/2019 which was crucial in yesterday’s R&D demo. This will help towards (but not completely unblock) https://github.com/dfinity-lab/motoko/pull/958 Also included: ``` 0cb40446d Let drun run longer (#2048) 10f45b313 INF-666 Conditional --clippy and --format runs for dcheck (#2030) 60191d91c Create a memory_check crate, for bounding memory usage in functions (#2027) 281732d25 Merge pull request #2047 from dfinity-lab/INF-637-switch-to-ubuntu 692f379a8 Remove msg from the csp.combine_sigs() API (#2041) 96d431a5c Fix failed integration tests. (#2042) 3722ccaf1 DFN-1191: Refactor call context manager API (#2019) 8cf85750d Merge pull request #2040 from dfinity-lab/nm-limit-retries 9e9935401 Merge pull request #2026 from dfinity-lab/manu/index-typo e3f63aaa5 Merge pull request #2031 from dfinity-lab/pshahi/DFN-1181 6c6e1dbe1 Merge pull request #2021 from dfinity-lab/kb/remove_hashOf 13e0ddcb4 Merge pull request #2032 from dfinity-lab/david-dfn-1206 b9a889f52 Merge pull request #2020 from dfinity-lab/david-dfn-1121 c57b2e933 Merge pull request #2034 from dfinity-lab/fix-mk-release d4df86395 Merge pull request #2012 from dfinity-lab/dfn-1154 06281005b Execute batches in a separate thread. (#1966) b02ba1734 Merge pull request #2033 from dfinity-lab/nm-fix-typo 24f0f6ee6 Merge pull request #2029 from dfinity-lab/david-dfn-1155 21f7cb12a Merge pull request #2024 from dfinity-lab/dsd/registry/remove_view_factory ``` --- default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/default.nix b/default.nix index c19f563f57f..10fb2b42a19 100644 --- a/default.nix +++ b/default.nix @@ -22,7 +22,7 @@ let dfinity-src = name = "dfinity-sources"; url = "ssh://git@github.com/dfinity-lab/dfinity"; # ref = "master"; - rev = "c1cce4a71ddbeaf044ee15c4da3619a24d447edf"; + rev = "0cb40446dbac6623a41180f168aaf528f69de159"; }; in let dfinity-pkgs = import dfinity-src { inherit (nixpkgs) system; }; in From ea0e03d59dc2e2ed8c0f86b60dca1cc2860a581d Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 6 Dec 2019 10:04:44 +0100 Subject: [PATCH 0765/1176] Document our interface towards SDK/dfx (#928) An important way of using the Motoko compiler is via the the `dfx` tool, provided by the DFINITY SDK, which provides project and package management support. This document describes the interface that `moc` and related tools provide to `dfx`. The goal is that * the Motoko developers know which command line flags have to be kept stable in order to not break `dfx`, and that * the SDK developers have a single place to read about the moc interface, and a place to express additional requirements (by collaborating on a PR against this document.) This interface includes: * nix derivations imported by SDK * binaries executed * command line arguments and environment varialbes passed to these binaries * where these binaries read files and * where these binaries write files, output or temporary * where they do _not_ write to, so that upgrading `moc` doesn't suddenly leave artifacts where `dfx` does not expect them --- design/DFX-Interface.md | 96 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 design/DFX-Interface.md diff --git a/design/DFX-Interface.md b/design/DFX-Interface.md new file mode 100644 index 00000000000..a03a62edab8 --- /dev/null +++ b/design/DFX-Interface.md @@ -0,0 +1,96 @@ +Stable CLI for dfx +================== + +An important way of using the Motoko compiler is via the the `dfx` tool, +provided by the DFINITY SDK, which provides project and package management +support. + +This document describes the interface that `moc` and related tools provide to +`dfx`. The goal is that + * the Motoko developers know which command line flags have to + be kept stable in order to not break `dfx`, and that + * the SDK developers have a single place to read about the moc interface, and + a place to express additional requirements (by collaborating on a PR against + this document.) + +This interface includes: + * nix derivations imported by SDK + * binaries executed + * command line arguments and environment varialbes passed to these binaries + * where these binaries read files and + * where these binaries write files, output or temporary + * where they do _not_ write to, so that upgrading `moc` doesn’t suddenly leave + artifacts where `dfx` does not expect them + +It does not replace proper documentation, but should be kept rather concise. + +Nix derivations +--------------- + +The `motoko` repository defines the following nix derivations, as attributes of +the top-level `default.nix`: + +* `moc-bin`: contains `bin/moc` +* `mo-ide`: contains `bin/mo-ide` +* `didc`: contains `bin/didc` +* `rts`: contains `rts/mo-rts.wasm`, the Motoko runtime system +* `stdlib`: contains the standard library, directly in the top level directory, + as `*.mo` files. It does not contain extra files (test files, for example) + +The `default.nix` file itself takes an optional `system` parameter which is +either `"x86_64-linux"` or `"x86_64-darwin"`, and defaults to +`builtins.currentSystem`. + +All binaries are either built statically (Linux) or only use system libraries (OSX). + +Compiling Motoko Files to Wasm +------------------------------ + +In order to compile a motoko file, `dfx` invokes `moc` with + + moc some/path/input.mo -o another/path/output.wasm { --package pkgname pkgpath } + +in an environment where `MOC_RTS` points to the location of the Motoko runtime system. + +This _reads_ `some/path/input.mo` and any `.mo` file referenced by +`some/path/input.mo`, either relatively, absolutely or via the provided package aliases. It also reads the given `mo-rts.wasm` file. + +No constraints are imposed where these imported files reside (this may be refined to prevent relative imports from looking outside the project and the declared packages) + +This _writes_ to `another/path/output.wasm`, but has no other effect. It does +not create `another/path/`. + +Compiling Motoko Files to IDL +----------------------------- + +As the previous point, but passing `--idl` to `moc`. + +Compiling IDL Files to JS +------------------------- + +In order to compile a IDL file, `dfx` invokes `didc` with + + didc --js some/path/input.did -o another/path/output.js + +This _reads_ `some/path/input.did` and any `.did` file referenced by +`some/path/input.did`. + +No constraints are imposed where these imported files reside (this may be refined to prevent relative imports from looking outside the project and the declared packages) + +This _writes_ to `another/path/output.js`, but has no other effect. It does +not create `another/path/`. + +Invoking the IDE +---------------- + +In order to start the language server, `dfx` invokes + + mo-ide --canister-main some/path/main.mo { --package pkgname pkgpath } + +with `stdin` and `stdout` connected to the LSP client. + + +This _reads_ `some/path/input.mo` and any `.mo` file referenced by +`some/path/input.mo`, either relatively, absolutely or via the provided package aliases. + +No constraints are imposed where these imported files reside (this may be refined to prevent relative imports from looking outside the project and the declared packages) From ddb4e15933f0ebb0efc87fee16a34625ca80f850 Mon Sep 17 00:00:00 2001 From: Nicolas Mattia Date: Fri, 6 Dec 2019 19:48:44 +0100 Subject: [PATCH 0766/1176] Use fetchzip instead of builtins.fetchTarball (#983) The behavior is the same except that `fetchzip` creates an actual derivation at build time as opposed to eval time. --- default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/default.nix b/default.nix index 10fb2b42a19..25e6839a326 100644 --- a/default.nix +++ b/default.nix @@ -27,7 +27,7 @@ let dfinity-src = let dfinity-pkgs = import dfinity-src { inherit (nixpkgs) system; }; in -let esm = builtins.fetchTarball { +let esm = nixpkgs.fetchzip { sha256 = "116k10q9v0yzpng9bgdx3xrjm2kppma2db62mnbilbi66dvrvz9q"; url = "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz"; }; in From 75909a3a21a8b521e7218201ee07e4a71a22b06f Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 9 Dec 2019 10:47:17 +0100 Subject: [PATCH 0767/1176] Bump drun (#987) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mainly to get https://github.com/dfinity-lab/dfinity/pull/2052 https://github.com/dfinity-lab/dfinity/pull/2054 in order to unblock https://github.com/dfinity-lab/motoko/pull/958 other changes in `rs/`: ``` ~/dfinity/dfinity $ git log --oneline --first-parent 0cb40446dbac6623a41180f168aaf528f69de159..ea4f38b262d80e3c31c414cd0e6bd676da99f191 rs/ ea4f38b26 (HEAD -> master, origin/master, origin/HEAD) Increase default canister queue capacity 10 → 100. (#2052) b97e44587 Merge pull request #2043 from dfinity-lab/johnw/procsimp 277477ddd Merge pull request #2035 from dfinity-lab/dfn-1210 0c21fdbc4 Merge pull request #2039 from dfinity-lab/DFN-1066 647aa911e Store original callback id in canister call origin. (#2054) 5f63955d0 Remove msg from combine sigs (#2049) 0118d26c8 Merge pull request #1987 from dfinity-lab/rsub/conn-manager 69c5774de Merge pull request #2022 from dfinity-lab/useActualCryptoSigningInterface 20203d6b5 Merge pull request #2037 from dfinity-lab/btree 53bfccf0c Merge pull request #2050 from dfinity-lab/franzstefan/ingress-hash-domain 0952469c8 Merge pull request #2045 from dfinity-lab/DFN-1048 ``` --- default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/default.nix b/default.nix index 25e6839a326..7f0e9bcf7b3 100644 --- a/default.nix +++ b/default.nix @@ -22,7 +22,7 @@ let dfinity-src = name = "dfinity-sources"; url = "ssh://git@github.com/dfinity-lab/dfinity"; # ref = "master"; - rev = "0cb40446dbac6623a41180f168aaf528f69de159"; + rev = "ea4f38b262d80e3c31c414cd0e6bd676da99f191"; }; in let dfinity-pkgs = import dfinity-src { inherit (nixpkgs) system; }; in From 9c4f2192fb5a4f162446d3e64a7f1146bbcecced Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 9 Dec 2019 10:57:24 +0100 Subject: [PATCH 0768/1176] IC Stub: Preprend `debug.print: ` to debug logs (#989) this means the output is closer to what `drun` does, which will make the diff of #958 more meaningful. --- ic-stub/src/IC/Canister/Imp.hs | 2 +- .../run-drun/ok/actor-creation.ic-stub-run.ok | 18 ++-- .../run-drun/ok/async-free-var.ic-stub-run.ok | 14 ++-- .../ok/async-loop-while.ic-stub-run.ok | 24 +++--- test/run-drun/ok/async-new-obj.ic-stub-run.ok | 10 +-- test/run-drun/ok/async-obj-mut.ic-stub-run.ok | 14 ++-- test/run-drun/ok/async-while.ic-stub-run.ok | 24 +++--- test/run-drun/ok/await.ic-stub-run.ok | 54 ++++++------ test/run-drun/ok/block.ic-stub-run.ok | 20 ++--- test/run-drun/ok/chat.ic-stub-run.ok | 36 ++++---- .../run-drun/ok/closure-params.ic-stub-run.ok | 20 ++--- .../ok/count-callbacks.ic-stub-run.ok | 26 +++--- test/run-drun/ok/counter2.ic-stub-run.ok | 28 +++---- test/run-drun/ok/data-params.ic-stub-run.ok | 82 +++++++++---------- .../ok/flatten-awaitables.ic-stub-run.ok | 68 +++++++-------- test/run-drun/ok/for-await.ic-stub-run.ok | 22 ++--- .../run-drun/ok/free-callbacks.ic-stub-run.ok | 2 +- .../ok/hello-world-async.ic-stub-run.ok | 4 +- .../ok/hello-world-await.ic-stub-run.ok | 2 +- .../ok/indirect-counter.ic-stub-run.ok | 8 +- test/run-drun/ok/interleave.ic-stub-run.ok | 30 +++---- test/run-drun/ok/issue-894.ic-stub-run.ok | 18 ++-- test/run-drun/ok/local-throw.ic-stub-run.ok | 4 +- test/run-drun/ok/nary-async.ic-stub-run.ok | 16 ++-- test/run-drun/ok/oneway-throw.ic-stub-run.ok | 8 +- test/run-drun/ok/oneway.ic-stub-run.ok | 22 ++--- test/run-drun/ok/overflow.ic-stub-run.ok | 10 +-- .../ok/pass-references.ic-stub-run.ok | 6 +- test/run-drun/ok/query2.ic-stub-run.ok | 8 +- .../ok/reference-params.ic-stub-run.ok | 10 +-- test/run-drun/ok/transpose.ic-stub-run.ok | 2 +- 31 files changed, 306 insertions(+), 306 deletions(-) diff --git a/ic-stub/src/IC/Canister/Imp.hs b/ic-stub/src/IC/Canister/Imp.hs index b04e62abe1f..9df690c0063 100644 --- a/ic-stub/src/IC/Canister/Imp.hs +++ b/ic-stub/src/IC/Canister/Imp.hs @@ -212,7 +212,7 @@ systemAPI esref = putBytes :: BS.ByteString -> HostM s () putBytes bytes = stToPrim (readSTRef (fst esref)) >>= \case - True -> unsafeIOToPrim (BSC.putStrLn bytes) + True -> unsafeIOToPrim $ BSC.putStrLn $ BSC.pack "debug.print: " <> bytes False -> return () -- The system calls (in the order of the public spec) diff --git a/test/run-drun/ok/actor-creation.ic-stub-run.ok b/test/run-drun/ok/actor-creation.ic-stub-run.ok index 983be8d9fef..aaa611cea86 100644 --- a/test/run-drun/ok/actor-creation.ic-stub-run.ok +++ b/test/run-drun/ok/actor-creation.ic-stub-run.ok @@ -1,13 +1,13 @@ → create ← completed: canister-id = 0x0000000000000400 → install -main actor creating a -main actor calling a.foo() -a created -a.foo() called -a creating b -a calling b.foo() -a.foo() done -b created -b.foo() called +debug.print: main actor creating a +debug.print: main actor calling a.foo() +debug.print: a created +debug.print: a.foo() called +debug.print: a creating b +debug.print: a calling b.foo() +debug.print: a.foo() done +debug.print: b created +debug.print: b.foo() called ← completed diff --git a/test/run-drun/ok/async-free-var.ic-stub-run.ok b/test/run-drun/ok/async-free-var.ic-stub-run.ok index dd58dcb8c5e..c035c8a3e87 100644 --- a/test/run-drun/ok/async-free-var.ic-stub-run.ok +++ b/test/run-drun/ok/async-free-var.ic-stub-run.ok @@ -3,11 +3,11 @@ → install ← completed → update go(0x4449444c0000) -A -A -C -Now in async -C -B -B +debug.print: A +debug.print: A +debug.print: C +debug.print: Now in async +debug.print: C +debug.print: B +debug.print: B ← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/async-loop-while.ic-stub-run.ok b/test/run-drun/ok/async-loop-while.ic-stub-run.ok index 975b7da4a42..132140ba1df 100644 --- a/test/run-drun/ok/async-loop-while.ic-stub-run.ok +++ b/test/run-drun/ok/async-loop-while.ic-stub-run.ok @@ -3,16 +3,16 @@ → install ← completed → update go(0x4449444c0000) -0 -1 -2 -0 -1 -2 -0 -1 -2 -0 -1 -2 +debug.print: 0 +debug.print: 1 +debug.print: 2 +debug.print: 0 +debug.print: 1 +debug.print: 2 +debug.print: 0 +debug.print: 1 +debug.print: 2 +debug.print: 0 +debug.print: 1 +debug.print: 2 ← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/async-new-obj.ic-stub-run.ok b/test/run-drun/ok/async-new-obj.ic-stub-run.ok index bc679bfb508..a1f0dd20497 100644 --- a/test/run-drun/ok/async-new-obj.ic-stub-run.ok +++ b/test/run-drun/ok/async-new-obj.ic-stub-run.ok @@ -3,9 +3,9 @@ → install ← completed → update go(0x4449444c0000) -aaab -babb -dadb -eaeb -cacb +debug.print: aaab +debug.print: babb +debug.print: dadb +debug.print: eaeb +debug.print: cacb ← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/async-obj-mut.ic-stub-run.ok b/test/run-drun/ok/async-obj-mut.ic-stub-run.ok index 67a77baa02f..410b0e9f1f3 100644 --- a/test/run-drun/ok/async-obj-mut.ic-stub-run.ok +++ b/test/run-drun/ok/async-obj-mut.ic-stub-run.ok @@ -3,12 +3,12 @@ → install ← completed → update go(0x4449444c0000) -1 -2 -3 -done creating +debug.print: 1 +debug.print: 2 +debug.print: 3 +debug.print: done creating -3 -4 -5 +debug.print: 3 +debug.print: 4 +debug.print: 5 ← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/async-while.ic-stub-run.ok b/test/run-drun/ok/async-while.ic-stub-run.ok index 975b7da4a42..132140ba1df 100644 --- a/test/run-drun/ok/async-while.ic-stub-run.ok +++ b/test/run-drun/ok/async-while.ic-stub-run.ok @@ -3,16 +3,16 @@ → install ← completed → update go(0x4449444c0000) -0 -1 -2 -0 -1 -2 -0 -1 -2 -0 -1 -2 +debug.print: 0 +debug.print: 1 +debug.print: 2 +debug.print: 0 +debug.print: 1 +debug.print: 2 +debug.print: 0 +debug.print: 1 +debug.print: 2 +debug.print: 0 +debug.print: 1 +debug.print: 2 ← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/await.ic-stub-run.ok b/test/run-drun/ok/await.ic-stub-run.ok index 3ea1de6ccaf..e622e712cbc 100644 --- a/test/run-drun/ok/await.ic-stub-run.ok +++ b/test/run-drun/ok/await.ic-stub-run.ok @@ -3,31 +3,31 @@ → install ← completed → update go(0x4449444c0000) -a -b -c -d -e -g -holy -e-while -g-label -. -a -b -cnt: 0 i: 0 -cnt: 1 i: 1 -cnt: 2 i: 2 -cnt: 3 i: 4 -cnt: 4 i: 5 -cnt: 5 i: 10 -. -cnt: 6 i: 3 -cnt: 7 i: 6 -cnt: 8 i: 11 -. -cnt: 9 i: 7 -cnt: 10 i: 12 -e-exit -g-exit +debug.print: a +debug.print: b +debug.print: c +debug.print: d +debug.print: e +debug.print: g +debug.print: holy +debug.print: e-while +debug.print: g-label +debug.print: . +debug.print: a +debug.print: b +debug.print: cnt: 0 i: 0 +debug.print: cnt: 1 i: 1 +debug.print: cnt: 2 i: 2 +debug.print: cnt: 3 i: 4 +debug.print: cnt: 4 i: 5 +debug.print: cnt: 5 i: 10 +debug.print: . +debug.print: cnt: 6 i: 3 +debug.print: cnt: 7 i: 6 +debug.print: cnt: 8 i: 11 +debug.print: . +debug.print: cnt: 9 i: 7 +debug.print: cnt: 10 i: 12 +debug.print: e-exit +debug.print: g-exit ← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/block.ic-stub-run.ok b/test/run-drun/ok/block.ic-stub-run.ok index 5b07d035c27..e2f6f35e10e 100644 --- a/test/run-drun/ok/block.ic-stub-run.ok +++ b/test/run-drun/ok/block.ic-stub-run.ok @@ -3,14 +3,14 @@ → install ← completed → update go(0x4449444c0000) -a1 -b1 -1 -a2 -b2 -a3 -b3 -3 -5 -6 +debug.print: a1 +debug.print: b1 +debug.print: 1 +debug.print: a2 +debug.print: b2 +debug.print: a3 +debug.print: b3 +debug.print: 3 +debug.print: 5 +debug.print: 6 ← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/chat.ic-stub-run.ok b/test/run-drun/ok/chat.ic-stub-run.ok index ea692752113..abb785b3c60 100644 --- a/test/run-drun/ok/chat.ic-stub-run.ok +++ b/test/run-drun/ok/chat.ic-stub-run.ok @@ -1,22 +1,22 @@ → create ← completed: canister-id = 0x0000000000000400 → install -charlie received hello from bob -alice received hello from bob -bob received hello from bob -charlie received goodbye from bob -alice received goodbye from bob -bob received goodbye from bob -charlie received hello from alice -alice received hello from alice -bob received hello from alice -charlie received goodbye from alice -alice received goodbye from alice -bob received goodbye from alice -charlie received hello from charlie -alice received hello from charlie -bob received hello from charlie -charlie received goodbye from charlie -alice received goodbye from charlie -bob received goodbye from charlie +debug.print: charlie received hello from bob +debug.print: alice received hello from bob +debug.print: bob received hello from bob +debug.print: charlie received goodbye from bob +debug.print: alice received goodbye from bob +debug.print: bob received goodbye from bob +debug.print: charlie received hello from alice +debug.print: alice received hello from alice +debug.print: bob received hello from alice +debug.print: charlie received goodbye from alice +debug.print: alice received goodbye from alice +debug.print: bob received goodbye from alice +debug.print: charlie received hello from charlie +debug.print: alice received hello from charlie +debug.print: bob received hello from charlie +debug.print: charlie received goodbye from charlie +debug.print: alice received goodbye from charlie +debug.print: bob received goodbye from charlie ← completed diff --git a/test/run-drun/ok/closure-params.ic-stub-run.ok b/test/run-drun/ok/closure-params.ic-stub-run.ok index 83872c169e0..ee68b9ca825 100644 --- a/test/run-drun/ok/closure-params.ic-stub-run.ok +++ b/test/run-drun/ok/closure-params.ic-stub-run.ok @@ -3,14 +3,14 @@ → install ← completed → update go(0x4449444c0000) -1 -3 -6 -10 -15 -1 -3 -6 -10 -15 +debug.print: 1 +debug.print: 3 +debug.print: 6 +debug.print: 10 +debug.print: 15 +debug.print: 1 +debug.print: 3 +debug.print: 6 +debug.print: 10 +debug.print: 15 ← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/count-callbacks.ic-stub-run.ok b/test/run-drun/ok/count-callbacks.ic-stub-run.ok index b8bcc69c966..992fe1c0c94 100644 --- a/test/run-drun/ok/count-callbacks.ic-stub-run.ok +++ b/test/run-drun/ok/count-callbacks.ic-stub-run.ok @@ -3,17 +3,17 @@ → install ← completed → update go(0x4449444c0000) -go 1: 0 -go 1: 1 -go 1: 2 -go 1: 3 -go 1: 4 -ping! 4 -ping! 4 -ping! 4 -ping! 4 -go 2: 3 -go 3: 2 -go 4: 1 -go 5: 0 +debug.print: go 1: 0 +debug.print: go 1: 1 +debug.print: go 1: 2 +debug.print: go 1: 3 +debug.print: go 1: 4 +debug.print: ping! 4 +debug.print: ping! 4 +debug.print: ping! 4 +debug.print: ping! 4 +debug.print: go 2: 3 +debug.print: go 3: 2 +debug.print: go 4: 1 +debug.print: go 5: 0 ← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/counter2.ic-stub-run.ok b/test/run-drun/ok/counter2.ic-stub-run.ok index 084e444ee29..b8085d2fb55 100644 --- a/test/run-drun/ok/counter2.ic-stub-run.ok +++ b/test/run-drun/ok/counter2.ic-stub-run.ok @@ -3,18 +3,18 @@ → install ← completed → update go(0x4449444c0000) -2 -3 -4 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 +debug.print: 2 +debug.print: 3 +debug.print: 4 +debug.print: 4 +debug.print: 5 +debug.print: 6 +debug.print: 7 +debug.print: 8 +debug.print: 9 +debug.print: 10 +debug.print: 11 +debug.print: 12 +debug.print: 13 +debug.print: 14 ← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/data-params.ic-stub-run.ok b/test/run-drun/ok/data-params.ic-stub-run.ok index f91829e5655..9d8d53af4c6 100644 --- a/test/run-drun/ok/data-params.ic-stub-run.ok +++ b/test/run-drun/ok/data-params.ic-stub-run.ok @@ -3,45 +3,45 @@ → install ← completed → update go(0x4449444c0000) -0 -+1 -+3 -+6 -+10 -+1_010 -+1_021 -+6_021 -+6_045 -+6_091 -+1_006_091 -+1_006_105 -+1_006_136 -+1_006_171 -+1_006_191 -+1_006_211 -+1_006_211 -Foo1: -+1_006_211 -μεταγράψτε: -+1_006_211 -Foo2: -+1_006_211 -+10_000_001_006_211 -+20_000_001_006_211 -+1_006_211 -+1_006_221 -+1_006_211 -+1_006_221 -+1_006_231 -+1_006_221 -+1_267_650_600_228_229_401_496_704_211_597 -+2_535_301_200_456_458_802_993_407_416_973 -+1_006_221 -+1_074_748_045 -+2_148_489_868 -+2_148_489_868 -+2_148_489_869 -+2_148_489_911 -+2_148_489_869 -+4_295_973_516 +debug.print: 0 +debug.print: +1 +debug.print: +3 +debug.print: +6 +debug.print: +10 +debug.print: +1_010 +debug.print: +1_021 +debug.print: +6_021 +debug.print: +6_045 +debug.print: +6_091 +debug.print: +1_006_091 +debug.print: +1_006_105 +debug.print: +1_006_136 +debug.print: +1_006_171 +debug.print: +1_006_191 +debug.print: +1_006_211 +debug.print: +1_006_211 +debug.print: Foo1: +debug.print: +1_006_211 +debug.print: μεταγράψτε: +debug.print: +1_006_211 +debug.print: Foo2: +debug.print: +1_006_211 +debug.print: +10_000_001_006_211 +debug.print: +20_000_001_006_211 +debug.print: +1_006_211 +debug.print: +1_006_221 +debug.print: +1_006_211 +debug.print: +1_006_221 +debug.print: +1_006_231 +debug.print: +1_006_221 +debug.print: +1_267_650_600_228_229_401_496_704_211_597 +debug.print: +2_535_301_200_456_458_802_993_407_416_973 +debug.print: +1_006_221 +debug.print: +1_074_748_045 +debug.print: +2_148_489_868 +debug.print: +2_148_489_868 +debug.print: +2_148_489_869 +debug.print: +2_148_489_911 +debug.print: +2_148_489_869 +debug.print: +4_295_973_516 ← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/flatten-awaitables.ic-stub-run.ok b/test/run-drun/ok/flatten-awaitables.ic-stub-run.ok index 68cd8a896b3..e82a85d7443 100644 --- a/test/run-drun/ok/flatten-awaitables.ic-stub-run.ok +++ b/test/run-drun/ok/flatten-awaitables.ic-stub-run.ok @@ -3,38 +3,38 @@ → install ← completed → update go(0x4449444c0000) -first-order -0 -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -higher-order -0 -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 +debug.print: first-order +debug.print: 0 +debug.print: 1 +debug.print: 2 +debug.print: 3 +debug.print: 4 +debug.print: 5 +debug.print: 6 +debug.print: 7 +debug.print: 8 +debug.print: 9 +debug.print: 10 +debug.print: 11 +debug.print: 12 +debug.print: 13 +debug.print: 14 +debug.print: 15 +debug.print: higher-order +debug.print: 0 +debug.print: 1 +debug.print: 2 +debug.print: 3 +debug.print: 4 +debug.print: 5 +debug.print: 6 +debug.print: 7 +debug.print: 8 +debug.print: 9 +debug.print: 10 +debug.print: 11 +debug.print: 12 +debug.print: 13 +debug.print: 14 +debug.print: 15 ← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/for-await.ic-stub-run.ok b/test/run-drun/ok/for-await.ic-stub-run.ok index f87d851ae57..c10d4285eb7 100644 --- a/test/run-drun/ok/for-await.ic-stub-run.ok +++ b/test/run-drun/ok/for-await.ic-stub-run.ok @@ -3,15 +3,15 @@ → install ← completed → update go(0x4449444c0000) -0 -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 +debug.print: 0 +debug.print: 1 +debug.print: 2 +debug.print: 3 +debug.print: 4 +debug.print: 5 +debug.print: 6 +debug.print: 7 +debug.print: 8 +debug.print: 9 +debug.print: 10 ← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/free-callbacks.ic-stub-run.ok b/test/run-drun/ok/free-callbacks.ic-stub-run.ok index c0dd9fe3c55..01b067f68f9 100644 --- a/test/run-drun/ok/free-callbacks.ic-stub-run.ok +++ b/test/run-drun/ok/free-callbacks.ic-stub-run.ok @@ -3,5 +3,5 @@ → install ← completed → update go(0x4449444c0000) -Ignore Diff: (ignored) +debug.print: Ignore Diff: (ignored) ← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/hello-world-async.ic-stub-run.ok b/test/run-drun/ok/hello-world-async.ic-stub-run.ok index 6e0af8d4f09..1531f51761b 100644 --- a/test/run-drun/ok/hello-world-async.ic-stub-run.ok +++ b/test/run-drun/ok/hello-world-async.ic-stub-run.ok @@ -3,6 +3,6 @@ → install ← completed → update go(0x4449444c0000) -Hello -World! +debug.print: Hello +debug.print: World! ← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/hello-world-await.ic-stub-run.ok b/test/run-drun/ok/hello-world-await.ic-stub-run.ok index 4b03e43e0df..3e98e12dcd0 100644 --- a/test/run-drun/ok/hello-world-await.ic-stub-run.ok +++ b/test/run-drun/ok/hello-world-await.ic-stub-run.ok @@ -3,5 +3,5 @@ → install ← completed → update go(0x4449444c0000) -Hello World! +debug.print: Hello World! ← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/indirect-counter.ic-stub-run.ok b/test/run-drun/ok/indirect-counter.ic-stub-run.ok index d5913df8b46..b8bc9426a98 100644 --- a/test/run-drun/ok/indirect-counter.ic-stub-run.ok +++ b/test/run-drun/ok/indirect-counter.ic-stub-run.ok @@ -1,8 +1,8 @@ → create ← completed: canister-id = 0x0000000000000400 → install -2 -3 -4 -4 +debug.print: 2 +debug.print: 3 +debug.print: 4 +debug.print: 4 ← completed diff --git a/test/run-drun/ok/interleave.ic-stub-run.ok b/test/run-drun/ok/interleave.ic-stub-run.ok index ef7d5a7b558..88b295fbdeb 100644 --- a/test/run-drun/ok/interleave.ic-stub-run.ok +++ b/test/run-drun/ok/interleave.ic-stub-run.ok @@ -3,23 +3,23 @@ → install ← completed → update go(0x4449444c0000) -g - e-while +debug.print: g +debug.print: e-while -g-label +debug.print: g-label - e cnt: 0 i: 5 -g cnt: 1 i: 10 - e cnt: 2 i: 6 -g cnt: 3 i: 11 - e cnt: 4 i: 7 -g cnt: 5 i: 12 - e cnt: 6 i: 8 -g cnt: 7 i: 13 - e cnt: 8 i: 9 -g cnt: 9 i: 14 - e-exit +debug.print: e cnt: 0 i: 5 +debug.print: g cnt: 1 i: 10 +debug.print: e cnt: 2 i: 6 +debug.print: g cnt: 3 i: 11 +debug.print: e cnt: 4 i: 7 +debug.print: g cnt: 5 i: 12 +debug.print: e cnt: 6 i: 8 +debug.print: g cnt: 7 i: 13 +debug.print: e cnt: 8 i: 9 +debug.print: g cnt: 9 i: 14 +debug.print: e-exit -g-exit +debug.print: g-exit ← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/issue-894.ic-stub-run.ok b/test/run-drun/ok/issue-894.ic-stub-run.ok index 00808d3be96..f84aadc892b 100644 --- a/test/run-drun/ok/issue-894.ic-stub-run.ok +++ b/test/run-drun/ok/issue-894.ic-stub-run.ok @@ -3,13 +3,13 @@ → install ← completed → update go(0x4449444c0000) -1 -1 -1 -1 -0 -1 -2 -3 -4 +debug.print: 1 +debug.print: 1 +debug.print: 1 +debug.print: 1 +debug.print: 0 +debug.print: 1 +debug.print: 2 +debug.print: 3 +debug.print: 4 ← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/local-throw.ic-stub-run.ok b/test/run-drun/ok/local-throw.ic-stub-run.ok index 4421ebdca21..77677f155a9 100644 --- a/test/run-drun/ok/local-throw.ic-stub-run.ok +++ b/test/run-drun/ok/local-throw.ic-stub-run.ok @@ -3,6 +3,6 @@ → install ← completed → update go(0x4449444c0000) -t2 ok -t3 ok +debug.print: t2 ok +debug.print: t3 ok ← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/nary-async.ic-stub-run.ok b/test/run-drun/ok/nary-async.ic-stub-run.ok index 2a1bd71f3fc..67cdd79a076 100644 --- a/test/run-drun/ok/nary-async.ic-stub-run.ok +++ b/test/run-drun/ok/nary-async.ic-stub-run.ok @@ -3,14 +3,14 @@ → install ← completed → update go1(0x4449444c0000) -0_0 -1_0 -2_0 -3_0 +debug.print: 0_0 +debug.print: 1_0 +debug.print: 2_0 +debug.print: 3_0 ← completed: 0x4449444c0000 → update go2(0x4449444c0000) -0_0 -0_1 -0_2 -0_3 +debug.print: 0_0 +debug.print: 0_1 +debug.print: 0_2 +debug.print: 0_3 ← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/oneway-throw.ic-stub-run.ok b/test/run-drun/ok/oneway-throw.ic-stub-run.ok index 012baa1ee18..3f95346d97b 100644 --- a/test/run-drun/ok/oneway-throw.ic-stub-run.ok +++ b/test/run-drun/ok/oneway-throw.ic-stub-run.ok @@ -3,8 +3,8 @@ → install ← completed → update go(0x4449444c0000) -go1 -throws() -ping() -go2 +debug.print: go1 +debug.print: throws() +debug.print: ping() +debug.print: go2 ← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/oneway.ic-stub-run.ok b/test/run-drun/ok/oneway.ic-stub-run.ok index 77ae2960ad1..13f27e947a6 100644 --- a/test/run-drun/ok/oneway.ic-stub-run.ok +++ b/test/run-drun/ok/oneway.ic-stub-run.ok @@ -3,15 +3,15 @@ → install ← completed → update go(0x4449444c0000) -A -B -C -D -E -1 -2 -3 -4 -5 -6 +debug.print: A +debug.print: B +debug.print: C +debug.print: D +debug.print: E +debug.print: 1 +debug.print: 2 +debug.print: 3 +debug.print: 4 +debug.print: 5 +debug.print: 6 ← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/overflow.ic-stub-run.ok b/test/run-drun/ok/overflow.ic-stub-run.ok index 75dbec3a4ea..1145efecc4d 100644 --- a/test/run-drun/ok/overflow.ic-stub-run.ok +++ b/test/run-drun/ok/overflow.ic-stub-run.ok @@ -3,11 +3,11 @@ → install ← completed → update go(0x4449444c0000) -This is reachable. -This is reachable. +debug.print: This is reachable. +debug.print: This is reachable. Trap: EvalTrapError :0.1 "canister trapped explicitly: Natural subtraction underflow" -This is reachable. -This is reachable. -This is reachable. +debug.print: This is reachable. +debug.print: This is reachable. +debug.print: This is reachable. Trap: EvalTrapError :0.1 "canister trapped explicitly: reject_callback" ← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/pass-references.ic-stub-run.ok b/test/run-drun/ok/pass-references.ic-stub-run.ok index da7d6668992..9772ec1f610 100644 --- a/test/run-drun/ok/pass-references.ic-stub-run.ok +++ b/test/run-drun/ok/pass-references.ic-stub-run.ok @@ -3,7 +3,7 @@ → install ← completed → update go(0x4449444c0000) -a -b -b +debug.print: a +debug.print: b +debug.print: b ← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/query2.ic-stub-run.ok b/test/run-drun/ok/query2.ic-stub-run.ok index 85d7fc58931..d67f63cdfd2 100644 --- a/test/run-drun/ok/query2.ic-stub-run.ok +++ b/test/run-drun/ok/query2.ic-stub-run.ok @@ -3,9 +3,9 @@ → install ← completed → update go(0x4449444c0000) -2 -3 -4 -4 +debug.print: 2 +debug.print: 3 +debug.print: 4 +debug.print: 4 Trap: EvalTrapError :0.1 "canister trapped explicitly: reject_callback" ← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/reference-params.ic-stub-run.ok b/test/run-drun/ok/reference-params.ic-stub-run.ok index bb1a279f272..d7f9b18f9b0 100644 --- a/test/run-drun/ok/reference-params.ic-stub-run.ok +++ b/test/run-drun/ok/reference-params.ic-stub-run.ok @@ -1,9 +1,9 @@ → create ← completed: canister-id = 0x0000000000000400 → install -Hello World! -Hello World! -Hello World! -Hello Universe! -Hello Galaxy! +debug.print: Hello World! +debug.print: Hello World! +debug.print: Hello World! +debug.print: Hello Universe! +debug.print: Hello Galaxy! ← completed diff --git a/test/run-drun/ok/transpose.ic-stub-run.ok b/test/run-drun/ok/transpose.ic-stub-run.ok index 42f71fbb799..20914d363ef 100644 --- a/test/run-drun/ok/transpose.ic-stub-run.ok +++ b/test/run-drun/ok/transpose.ic-stub-run.ok @@ -3,5 +3,5 @@ → install ← completed → update go(0x4449444c0000) -All good +debug.print: All good ← completed: 0x4449444c0000 From 34bde8de65cd8c717b1045dd67eb0fd1c3cdaedb Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 9 Dec 2019 11:29:59 +0100 Subject: [PATCH 0769/1176] Bump drun again (#990) to get https://github.com/dfinity-lab/dfinity/pull/2028 and https://github.com/dfinity-lab/dfinity/pull/2044 ``` 4d09038b0 Merge pull request #2044 from dfinity-lab/DFN-1172/reply 638d6eb5c adds Response type 80d290b71 adds comments 76e30cb56 introduces response tracking f873f1b3d makes fields non-public ``` --- default.nix | 2 +- src/codegen/compile.ml | 11 ++++------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/default.nix b/default.nix index 7f0e9bcf7b3..756fca6a2c8 100644 --- a/default.nix +++ b/default.nix @@ -22,7 +22,7 @@ let dfinity-src = name = "dfinity-sources"; url = "ssh://git@github.com/dfinity-lab/dfinity"; # ref = "master"; - rev = "ea4f38b262d80e3c31c414cd0e6bd676da99f191"; + rev = "4d09038b09b4ba230205216a0a590b80c33a59cb"; }; in let dfinity-pkgs = import dfinity-src { inherit (nixpkgs) system; }; in diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index a70fc4b6a59..cf75181ecef 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -2916,7 +2916,8 @@ module Dfinity = struct E.add_func_import env "ic0" "msg_caller_size" [] [I32Type]; E.add_func_import env "ic0" "msg_reject_code" [] [I32Type]; E.add_func_import env "ic0" "msg_reject" (i32s 2) []; - E.add_func_import env "msg" "reply" [I32Type; I32Type] []; + E.add_func_import env "ic0" "msg_reply_data_append" (i32s 2) []; + E.add_func_import env "ic0" "msg_reply" [] []; E.add_func_import env "ic" "trap" [I32Type; I32Type] []; () | Flags.StubMode -> @@ -3094,12 +3095,8 @@ module Dfinity = struct fun env get_data_start get_data_size -> get_data_start ^^ get_data_size ^^ - match E.mode env with - | Flags.ICMode -> system_call env "msg" "reply" - | Flags.StubMode -> - system_call env "ic0" "msg_reply_data_append" ^^ - system_call env "ic0" "msg_reply" - | _ -> assert false + system_call env "ic0" "msg_reply_data_append" ^^ + system_call env "ic0" "msg_reply" ) (* Actor reference on the stack *) From 7882ada39952bcbd7084da5b0fc48311406f968b Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Mon, 9 Dec 2019 11:22:35 +0000 Subject: [PATCH 0770/1176] WIP --- src/mo_def/syntax.ml | 24 +++++++---- src/mo_frontend/parser.mly | 2 +- src/mo_frontend/typing.ml | 45 ++++++++++++++------- src/mo_types/type.ml | 53 +++++++++++++++---------- test/run-drun/general_await.mo | 6 +-- test/run-drun/general_await_implicit.mo | 5 +-- 6 files changed, 86 insertions(+), 49 deletions(-) diff --git a/src/mo_def/syntax.ml b/src/mo_def/syntax.ml index 2da689160a7..2ab73af711c 100644 --- a/src/mo_def/syntax.ml +++ b/src/mo_def/syntax.ml @@ -248,8 +248,8 @@ let scope_id = "@" let scope_bind() = { var = scope_id @@ no_region; - bound = PrimT "Any" @! no_region} - @= no_region + bound = PrimT "Any" @! no_region + } @= no_region let pun_bind typ_bind = { var = typ_bind.it.var.it @@ no_region; @@ -277,11 +277,19 @@ let funcT(sort, tbs_opt, t1, t2) = | Some tbs -> FuncT(sort, tbs, t1, t2) let funcE (f, s, tbs_opt, p, t_opt, e) = - match tbs_opt, t_opt with - | None, None -> FuncE(f, s, [], p, t_opt, e) - | None, Some t -> + let tbs = match tbs_opt with + | None -> [] + | Some tbs -> tbs + in + match t_opt with + | None -> FuncE(f, s, tbs, p, t_opt, e) + | Some t -> (match t.it with | AsyncT (t1, _) when is_scope_typ t1 -> - FuncE(f, s, [scope_bind()], p, t_opt, e) - | _ -> FuncE(f, s, [], p, t_opt, e)) - | Some tbs, _ -> FuncE(f, s, tbs, p, t_opt, e) + let tbs' = + if List.exists (fun tb -> tb.it.var.it = scope_id) tbs + then tbs + else scope_bind()::tbs + in + FuncE(f, s, tbs', p, t_opt, e) + | _ -> FuncE(f, s, tbs, p, t_opt, e)) diff --git a/src/mo_frontend/parser.mly b/src/mo_frontend/parser.mly index 95c186f32ed..85a4d94a914 100644 --- a/src/mo_frontend/parser.mly +++ b/src/mo_frontend/parser.mly @@ -640,7 +640,7 @@ dec_nonvar : match t with | Some {it = AsyncT _; _} -> (match tps with - | Some [tb] -> AsyncE(pun_bind tb, e, scope_typ()) @? e.at + | Some (tb::_) -> AsyncE(pun_bind tb, e, scope_typ()) @? e.at | _ -> AsyncE(scope_bind(), e, scope_typ()) @? e.at) | _ -> e in diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 85690c3efa8..323c7fbbefa 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -255,13 +255,17 @@ let check_shared_return env at sort c ts = | T.Shared T.Query, _, _ -> error env at "shared query function must have syntactic return type `async `" | _ -> () -let infer_scope env cs cod = - match cs, cod.it with - | [c], AsyncT(typ0,_) when is_scope_typ typ0 -> - { env with typs = T.Env.add scope_id c env.typs } - | _ -> env - -let rec check_typ env typ : T.typ = +let rec infer_scope env cs cod = + match cod.it with + | AsyncT (typ,_) -> + let t = check_typ env typ in + (match T.close cs t with + | T.Var (_, n) -> + { env with typs = T.Env.add scope_id (List.nth cs n) env.typs } + | _ -> env) + | _ -> env + +and check_typ env typ : T.typ = let t = check_typ' env typ in typ.note <- t; t @@ -791,13 +795,26 @@ and infer_exp'' env exp : T.typ = "expected function type, but expression produces type\n %s" (T.string_of_typ_expand t1) in - (* only attempt scope inference when no inst, not empty inst (`<>`), provided *) - let typs = match !insts, t1 with - | None, T.Func(_,T.Promises (T.Var (_,0)),[_],_,_) - | None, T.Func(_,T.Returns,[_],_,[T.Async (T.Var (_,0),_)]) -> - [Syntax.scope_typ {left=exp1.at.right; right = exp2.at.left}] - | None, _ -> [] - | Some typs, _ -> typs + (* scope inference *) + let pre_typs = + match !insts with + | None -> [] + | Some tys -> tys + in + let expected = List.length tbs in + let rec insert n typ typs = match n, typs with + | 0, typs -> typ::typs + | n, typ'::typs -> typ'::insert (n-1) typ typs + | n, [] -> [typ] + in + let typs = match t1 with + | T.Func(_,T.Promises (T.Var (_, n)), _, _, _) + | T.Func(_,T.Returns, _, _, [T.Async (T.Var (_, n),_)]) + when n < expected && List.length pre_typs = expected - 1 -> + insert n + (Syntax.scope_typ {left=exp1.at.right; right = exp2.at.left}) + pre_typs + | _ -> pre_typs in insts := Some typs; let ts = check_inst_bounds env tbs typs exp.at in diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index 934f89a04f6..7c3be331c42 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -1216,26 +1216,24 @@ and string_of_control_cod sugar c vs ts = | Replies, _ -> sprintf "replies %s" (string_of_cod vs ts) and can_sugar t = match t with - | Func(s,Promises (Var(_,0)),[tb],ts1,ts2) -> - can_omit 0 tb.bound && - List.for_all (can_omit 0) ts1 && - List.for_all (can_omit 0) ts2 - | Func(s,Returns,[tb],ts1,([Async (Var(_,0),_)] as ts2)) -> - can_omit 0 tb.bound && - List.for_all (can_omit 0) ts1 && - List.for_all (can_omit 0) ts2 + | Func(s, Promises (Var(_, n)), tbs, ts1, ts2) + | Func(s, Returns, tbs, ts1, ([Async (Var(_, n),_)] as ts2)) -> + n = 0 && + List.for_all (fun tb -> can_omit n tb.bound) tbs && + List.for_all (can_omit n) ts1 && + List.for_all (can_omit n) ts2 | _ -> false -and can_omit i t = +and can_omit n t = let rec go i t = begin match t with - | Var (_,j) -> i <> j + | Var (_, j) -> i <> j | Pre -> assert false | Prim _ | Any | Non -> true | Con (c, ts) -> List.for_all (go i ) ts | Array t | Opt t | Mut t -> go i t - | Async (Var (_,0), t2) when i = 0 -> go i t2 (* t1 is a phantom type *) + | Async (Var (_, j), t2) when j = i && i <= n -> go i t2 (* t1 is a phantom type *) | Async (t1, t2) -> go i t1 && go i t2 | Tup ts -> List.for_all (go i ) ts | Obj (_, fs) | Variant fs -> List.for_all (fun f -> go i f.typ) fs @@ -1244,17 +1242,32 @@ and can_omit i t = List.for_all (fun {var;bound} -> (go i' bound)) tbs && List.for_all (go i') ts1 && List.for_all (go i') ts2 - | Typ c -> assert false (* TBR *) + | Typ c -> true (* assuming type defs are closed *) end - in go i t + in go n t and string_of_typ' vs t = match t with - | Func (s, c, [tb], ts1, ts2) when can_sugar t -> - let vs' = ("",0)::vs in - sprintf "%s%s -> %s" (string_of_func_sort s) - (string_of_dom vs' ts1) - (string_of_control_cod true c vs' ts2) + | Func (s, c, tbs, ts1, ts2) when can_sugar t -> + let n = match c, ts2 with + | Promises (Var (s,n)), _ -> n + | Returns, [Async (Var (s,n),_)] -> n + | _ -> assert false + in + assert (n = 0); + let vs' = vars_of_binds vs tbs in + let vs'', tbs' = List.tl vs', List.tl tbs in + begin + match tbs with + | [tb] -> + sprintf "%s%s -> %s" (string_of_func_sort s) + (string_of_dom vs ts1) + (string_of_control_cod true c vs ts2) + | _ -> + sprintf "%s%s%s -> %s" + (string_of_func_sort s) (string_of_binds (vs' @ vs) vs'' tbs') + (string_of_dom (vs' @ vs) ts1) (string_of_control_cod true c (vs' @ vs) ts2) + end | Func (s, c, [], ts1, ts2) -> sprintf "%s%s -> %s" (string_of_func_sort s) (string_of_dom vs ts1) @@ -1267,8 +1280,8 @@ and string_of_typ' vs t = | Opt t -> sprintf "?%s" (string_of_typ_nullary vs t) | Async (t1, t2) -> - (match t1, vs with - | Var(_,0), ("",_)::vs -> sprintf "async %s" (string_of_typ_nullary vs t2) + (match t1 with + | Var(_, n) when fst (List.nth vs n) = "" -> sprintf "async %s" (string_of_typ_nullary vs t2) | _ -> sprintf "async<%s> %s" (string_of_typ' vs t1) (string_of_typ_nullary vs t2)) | Obj (s, fs) -> sprintf "%s%s" (string_of_obj_sort s) (string_of_typ_nullary vs (Obj (Object, fs))) diff --git a/test/run-drun/general_await.mo b/test/run-drun/general_await.mo index 461d1c78df6..76685564443 100644 --- a/test/run-drun/general_await.mo +++ b/test/run-drun/general_await.mo @@ -28,7 +28,7 @@ actor Await { public shared func DPA<@>() : async<@>() { let as: [async()] = Array_tabulate(10, func (_) { Ack<@>(); }); - for (a in as.vals()) { + for (a in as.vals()) { await a; }; }; @@ -36,8 +36,8 @@ actor Await { // Dynamic parallel waiting (with results) public shared func DPR<@>() : async<@>[Int] { - func f<>(i:Nat) : async Int = Request<@>(i); - let as = Array_tabulate(10, f); + func f(i:Nat) : async Int = Request<@>(i); + let as = Array_tabulate(10, func i {f i}); let res = Array_init(as.len(),-1); for (i in as.keys()) { // res[i] := (await as[i]); <-- compiler bug (generates incorrect code) diff --git a/test/run-drun/general_await_implicit.mo b/test/run-drun/general_await_implicit.mo index 6b5e045f2e4..b59fd8ac541 100644 --- a/test/run-drun/general_await_implicit.mo +++ b/test/run-drun/general_await_implicit.mo @@ -36,9 +36,8 @@ actor Await { // Dynamic parallel waiting (with results) public shared func DPR() : async [Int] { - func f<>(i:Nat) : async Int = Request(i); - //NB: <> necesary to suppress implicit @-quantification - let as = Array_tabulate(10, f); + func f(i:Nat) : async Int = Request(i); + let as = Array_tabulate(10, func i { f i }); let res = Array_init(as.len(),-1); for (i in as.keys()) { // res[i] := (await as[i]); <-- compiler bug (generates incorrect code) From e071a19bf781d4d5404e4e454c21051a10ce5ac8 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 9 Dec 2019 15:22:26 +0100 Subject: [PATCH 0771/1176] Move text-handling functions into the C RTS (#984) Create a RTS `text.c` module and move basically all text operations into text.c which removes a lot of hairy Wasm code from the backend, and also opens the path towards smarter implementations in `text.c`. Also move `alloc_blob` into `rts.c`. --- rts/Makefile | 2 +- rts/bigint.c | 5 +- rts/rts.c | 22 +-- rts/rts.h | 15 +- rts/text.c | 164 ++++++++++++++++ src/codegen/compile.ml | 404 ++++++++++++---------------------------- src/mo_values/prim.ml | 35 ++-- src/mo_values/value.ml | 2 + src/mo_values/value.mli | 2 + src/prelude/prelude.ml | 11 +- test/run/text-iter.mo | 1 + 11 files changed, 330 insertions(+), 333 deletions(-) create mode 100644 rts/text.c diff --git a/rts/Makefile b/rts/Makefile index 3a8ebaec451..157edfef025 100644 --- a/rts/Makefile +++ b/rts/Makefile @@ -81,7 +81,7 @@ TOMMATH_NATIVE_O=$(TOMMATHFILES:%=_build/native/tommath_%.o) # Our part of the RTS, Wasm and native # -RTSFILES=rts idl bigint buf utf8_valid closure-table +RTSFILES=rts idl bigint buf utf8_valid closure-table text _build/wasm/%.o: %.c rts.h buf.h | _build/wasm $(WASM_CLANG) -c $(CLANG_FLAGS) $(WASM_FLAGS) $(TOMMATH_FLAGS) -I$(TOMMATHSRC) --std=c11 $< --output $@ diff --git a/rts/bigint.c b/rts/bigint.c index 8c8e7ae611a..c05eb223387 100644 --- a/rts/bigint.c +++ b/rts/bigint.c @@ -29,10 +29,7 @@ pointer to a data array. */ void* mp_alloc(size_t l) { - as_ptr r = alloc_bytes (2*sizeof(void*) + l); - FIELD(r, 0) = TAG_BLOB; - FIELD(r, 1) = l; - return &FIELD(r,2); + return alloc(l); } export void* mp_calloc(size_t n, size_t size) { diff --git a/rts/rts.c b/rts/rts.c index 52e7729d28a..91876b7427a 100644 --- a/rts/rts.c +++ b/rts/rts.c @@ -1,23 +1,27 @@ #include "rts.h" +as_ptr alloc_blob(size_t n) { + as_ptr r = alloc_bytes (BLOB_HEADER_SIZE*sizeof(void*) + n); + TAG(r) = TAG_BLOB; + BLOB_LEN(r) = n; + return r; +} + char *alloc(size_t n) { - as_ptr r = alloc_bytes (2*sizeof(void*) + n); - FIELD(r, 0) = TAG_BLOB; - FIELD(r, 1) = n; + as_ptr r = alloc_blob(n); return (char *)&FIELD(r,2); } - export void as_memcpy(char *str1, const char *str2, size_t n) { for (size_t i = 0; i < n; i++) { str1[i] = str2[i]; } } -export int as_memcmp(const unsigned char *str1, const unsigned char *str2, size_t n) { +export int as_memcmp(const char *str1, const char *str2, size_t n) { for (size_t i = 0; i < n; i++) { if (str1[i] != str2[i]) - return str1[i]-str2[i]; + return ((uint8_t*)str1)[i]-((uint8_t*)str2)[i]; } return 0; } @@ -30,11 +34,7 @@ size_t as_strlen(const char* p) { as_ptr as_str_of_cstr(const char * const s) { size_t l = as_strlen(s); - as_ptr r = alloc_bytes (2*sizeof(void*) + l); - FIELD(r, 0) = TAG_BLOB; - FIELD(r, 1) = l; - as_memcpy((char *)(&FIELD(r,2)), s, l); - return r; + return text_of_ptr_size(s, l); } void __attribute__ ((noreturn)) trap_with_prefix(const char* prefix, const char *str) { diff --git a/rts/rts.h b/rts/rts.h index 632b05092c5..1f26e4fcaa3 100644 --- a/rts/rts.h +++ b/rts/rts.h @@ -22,11 +22,13 @@ typedef intptr_t as_ptr; #define UNSKEW(p) ((size_t *)((as_ptr)p+1)) #define FIELD(p,n) (UNSKEW(p)[n]) #define TAG(p) FIELD(p,0) -#define TEXT_LEN(p) (FIELD(p,1)) -#define TEXT_PAYLOAD(p) ((uint8_t *)(&FIELD(p,2))) -#define ARRAY_LEN(p) (FIELD(p,1)) +#define BLOB_HEADER_SIZE 2 +#define BLOB_LEN(p) (FIELD(p,1)) +#define BLOB_PAYLOAD(p) ((char *)(&FIELD(p,2))) + #define ARRAY_HEADER_SIZE 2 +#define ARRAY_LEN(p) (FIELD(p,1)) #define ARRAY_FIELD(p,n) (FIELD(p,ARRAY_HEADER_SIZE+n)) /* Heap tags. Needs to stay in sync with compile.ml */ @@ -67,7 +69,6 @@ alloc_bytes from the Motoko RTS: */ from_rts as_ptr alloc_bytes(size_t n); from_rts as_ptr alloc_words(size_t n); -char *alloc(size_t n); /* IDL code */ @@ -77,6 +78,12 @@ from_rts __attribute__ ((noreturn)) void bigint_trap(); /** Functions used in multiple modules of the RTS */ export void as_memcpy(char *str1, const char *str2, size_t n); +export int as_memcmp(const char *str1, const char *str2, size_t n); + +char *alloc(size_t n); +as_ptr alloc_blob(size_t n); +as_ptr text_of_ptr_size(const char *buf, size_t n); + export __attribute__ ((noreturn)) void idl_trap_with(const char *str1); export __attribute__ ((noreturn)) void rts_trap_with(const char *str1); diff --git a/rts/text.c b/rts/text.c new file mode 100644 index 00000000000..96c3fc2ec2d --- /dev/null +++ b/rts/text.c @@ -0,0 +1,164 @@ +/* +The implementation of the Text type in Motoko. + +One main goal of this datastructure (inspired by ropes and similar) is to +support constant time concatenation, by having a dedicated heap object for +the concatentation of two strings. + +The current implementation does not do any of this; the first goal is to wire up +this C code with the RTS that encapsulates the internals of strings. + +This encapsulation is not complete (and likely never will) + * the compiler needs to emit static text literals, + * the garbage collector needs to know some of the internals. + +In a subsequent step, the actual concatentation node will be introduced. + +From then on, there are stretch goals like: + - when concatenating short (<= 8 bytes maybe) strings, just copy them + - restructure recursive code to not use unbounded C stack + - maybe rebalancing +*/ + +#include "rts.h" + +typedef as_ptr blob_t; // a skewed pointer to a Blob heap object +typedef as_ptr text_t; // a skewed pointer to a Blob (or, later, Concat) heap object + +// Create +export text_t text_of_ptr_size(const char *buf, size_t n) { + as_ptr r = alloc_blob(n); + as_memcpy(BLOB_PAYLOAD(r), buf, n); + return r; +} + +// Concat +export text_t text_concat(text_t s1, text_t s2) { + uint32_t n1 = BLOB_LEN(s1); + uint32_t n2 = BLOB_LEN(s2); + as_ptr r = alloc_blob(n1 + n2); + as_memcpy(BLOB_PAYLOAD(r), BLOB_PAYLOAD(s1), n1); + as_memcpy(BLOB_PAYLOAD(r) + n1, BLOB_PAYLOAD(s2), n2); + return r; +} + +// straighten into contiguous memory, if needed (e.g. for system calls) +export blob_t blob_of_text(text_t s) { + return s; +} + +// similarly, but writing into a buffer (must have the right size) +export void text_to_buf(text_t s, char *buf) { + as_memcpy(buf, BLOB_PAYLOAD(s), BLOB_LEN(s)); +} + +export uint32_t text_size(text_t s) { + return BLOB_LEN(s); +} + +// Compare +export int text_compare(text_t s1, text_t s2) { + uint32_t n1 = BLOB_LEN(s1); + uint32_t n2 = BLOB_LEN(s2); + uint32_t n = n1 < n2 ? n1 : n2; + uint32_t r = as_memcmp(BLOB_PAYLOAD(s1), BLOB_PAYLOAD(s2), n); + if (r == 0) { + if (n1 < n2) { return -1; } + else if (n1 > n2) { return 1; } + else return 0; + } else { + return r; + } +} + +// Stuff that deals with characters + +// decodes the character at position n in the array +// returns the character, and updates n +// based on https://gist.github.com/tylerneylon/9773800 +uint32_t decode_code_point(char *s, size_t *n) { + int k = s[*n] ? __builtin_clz(~(s[*n] << 24)) : 0; // Count # of leading 1 bits. + int mask = (1 << (8 - k)) - 1; // All 1's with k leading 0's. + uint32_t value = s[*n] & mask; + for (++*n, --k; k > 0; --k, ++*n) { // Note that k = 0 or #total bytes + value <<= 6; + value += (s[*n] & 0x3F); + } + return value; +} + +// Length in characters +export uint32_t text_len(text_t s) { + char *p = BLOB_PAYLOAD(s); + size_t n = 0; + uint32_t c = 0; + while (n < BLOB_LEN(s)) { + int k = p[n] ? __builtin_clz(~(p[n] << 24)) : 0; // Count # of leading 1 bits. + n += k ? k : 1; + c += 1; + } + return c; +} + +// Text from Char +export text_t text_singleton(uint32_t code) { + // adapted from https://gist.github.com/tylerneylon/9773800 + char val[4]; + int lead_byte_max = 0x7F; + int val_index = 0; + while (code > lead_byte_max) { + val[val_index++] = (code & 0x3F) | 0x80; + code >>= 6; + lead_byte_max >>= (val_index == 1 ? 2 : 1); + } + val[val_index++] = (code & lead_byte_max) | (~lead_byte_max << 1); + + as_ptr r = alloc_blob(val_index); + char *p = BLOB_PAYLOAD(r); + while (val_index--) { + *p = val[val_index]; + p++; + } + return r; +} + + + +// Iterators + +// Currently a vanilla tuple: +// First component the array to the text +// Second the index into the array (shifted by two for GC's sake) +// +// TODO: do we have to worry about texts longer than 2^30 bytes +// (and thus shifting is // bad) +// +// Eventually, this will be a pointer into a tree or something. + +typedef as_ptr text_iter_t; // the data structure used to iterate a text value +#define TEXT_ITER_TEXT(p) (ARRAY_FIELD(p,0)) +#define TEXT_ITER_POS(p) (ARRAY_FIELD(p,1)) + + +export text_iter_t text_iter(text_t s) { + // Maybe use a dedicated heap type instead of a vanilla tuple? + as_ptr i = alloc_words(ARRAY_HEADER_SIZE + 2); + TAG(i) = TAG_ARRAY; + TEXT_ITER_TEXT(i) = s; + TEXT_ITER_POS(i) = 0; + return i; +} + +export uint32_t text_iter_done(text_iter_t i) { + return (TEXT_ITER_POS(i) >> 2) >= BLOB_LEN(TEXT_ITER_TEXT(i)); +} + +export uint32_t text_iter_next(text_iter_t i) { + if (text_iter_done(i)) { + rts_trap_with("text_iter_next: Iter already done"); + } + size_t n = TEXT_ITER_POS(i) >> 2; + uint32_t c = decode_code_point(BLOB_PAYLOAD(TEXT_ITER_TEXT(i)), &n); + TEXT_ITER_POS(i) = n << 2; + return c; +} diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index cf75181ecef..b9086c492f0 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -652,6 +652,17 @@ module RTS = struct E.add_func_import env "rts" "closure_count" [] [I32Type]; E.add_func_import env "rts" "closure_table_loc" [] [I32Type]; E.add_func_import env "rts" "closure_table_size" [] [I32Type]; + E.add_func_import env "rts" "blob_of_text" [I32Type] [I32Type]; + E.add_func_import env "rts" "text_compare" [I32Type; I32Type] [I32Type]; + E.add_func_import env "rts" "text_concat" [I32Type; I32Type] [I32Type]; + E.add_func_import env "rts" "text_iter_done" [I32Type] [I32Type]; + E.add_func_import env "rts" "text_iter" [I32Type] [I32Type]; + E.add_func_import env "rts" "text_iter_next" [I32Type] [I32Type]; + E.add_func_import env "rts" "text_len" [I32Type] [I32Type]; + E.add_func_import env "rts" "text_of_ptr_size" [I32Type; I32Type] [I32Type]; + E.add_func_import env "rts" "text_singleton" [I32Type] [I32Type]; + E.add_func_import env "rts" "text_size" [I32Type] [I32Type]; + E.add_func_import env "rts" "text_to_buf" [I32Type; I32Type] []; () end (* RTS *) @@ -716,11 +727,14 @@ module Heap = struct ) G.nop ) - (* Dynamic allocation *) - let dyn_alloc_words env = - Func.share_code1 env "alloc_words" ("n", I32Type) [I32Type] (fun env get_n -> - (* expects the size (in words), returns the skewed pointer *) + let dyn_alloc_words env = G.i (Call (nr (E.built_in env "alloc_words"))) + let dyn_alloc_bytes env = G.i (Call (nr (E.built_in env "alloc_bytes"))) + let declare_alloc_functions env = + (* Dynamic allocation *) + Func.define_built_in env "alloc_words" [("n", I32Type)] [I32Type] (fun env -> + (* expects the size (in words), returns the skewed pointer *) + let get_n = G.i (LocalGet (nr 0l)) in (* return the current pointer (skewed) *) get_skewed_heap_ptr env ^^ @@ -736,12 +750,11 @@ module Heap = struct (* grow memory if needed *) get_heap_ptr env ^^ grow_memory env - ) - - let dyn_alloc_bytes env = - Func.share_code1 env "alloc_bytes" ("n", I32Type) [I32Type] (fun env get_n -> - get_n ^^ + ); + Func.define_built_in env "alloc_bytes" [("n", I32Type)] [I32Type] (fun env -> + let get_n = G.i (LocalGet (nr 0l)) in (* Round up to next multiple of the word size and convert to words *) + get_n ^^ compile_add_const 3l ^^ compile_divU_const word_size ^^ dyn_alloc_words env @@ -1079,8 +1092,6 @@ module MutBox = struct (* Mutable heap objects *) let field = Tagged.header_size - let load = Heap.load_field field - let store = Heap.store_field field end @@ -1157,7 +1168,6 @@ module Closure = struct let funptr_field = Tagged.header_size let len_field = Int32.add 1l Tagged.header_size - let get = G.i (LocalGet (nr 0l)) let load_data i = Heap.load_field (Int32.add header_size i) let store_data i = Heap.store_field (Int32.add header_size i) @@ -1178,12 +1188,6 @@ module Closure = struct G.i (CallIndirect (nr ty)) ^^ FakeMultiVal.load env (Lib.List.make n_res I32Type) - let fixed_closure env fi fields = - Tagged.obj env Tagged.Closure - ([ compile_unboxed_const fi - ; compile_unboxed_const (Int32.of_int (List.length fields)) ] @ - fields) - end (* Closure *) @@ -1410,53 +1414,6 @@ module UnboxedSmallWord = struct E.then_trap_with env "codepoint out of range" ^^ get_n ^^ box_codepoint - (* Two utilities for dealing with utf-8 encoded bytes. *) - let compile_load_byte get_ptr offset = - get_ptr ^^ G.i (Load {ty = I32Type; align = 0; offset; sz = Some (Wasm.Memory.Pack8, Wasm.Memory.ZX)}) - - let compile_6bit_mask = compile_bitand_const 0b00111111l - - (* Examines the byte pointed to the address on the stack - * and following bytes, - * building an unboxed Unicode code point, and passing it to set_res. - * and finally returning the number of bytes consumed on the stack. - * Inspired by https://rosettacode.org/wiki/UTF-8_encode_and_decode#C - *) - let len_UTF8_head env set_res = - let (set_ptr, get_ptr) = new_local env "ptr" in - let (set_byte, get_byte) = new_local env "byte" in - let if_under thres mk_then mk_else = - get_byte ^^ compile_unboxed_const thres ^^ G.i (Compare (Wasm.Values.I32 I32Op.LtU)) ^^ - G.if_ (ValBlockType (Some I32Type)) mk_then mk_else in - let or_follower offset = - compile_shl_const 6l ^^ - compile_load_byte get_ptr offset ^^ - compile_6bit_mask ^^ - G.i (Binary (Wasm.Values.I32 I32Op.Or)) in - set_ptr ^^ - compile_load_byte get_ptr 0l ^^ set_byte ^^ - if_under 0x80l - ( get_byte ^^ - set_res ^^ - compile_unboxed_const 1l) - (if_under 0xe0l - (get_byte ^^ compile_bitand_const 0b00011111l ^^ - or_follower 1l ^^ - set_res ^^ - compile_unboxed_const 2l) - (if_under 0xf0l - (get_byte ^^ compile_bitand_const 0b00001111l ^^ - or_follower 1l ^^ - or_follower 2l ^^ - set_res ^^ - compile_unboxed_const 3l) - (get_byte ^^ compile_bitand_const 0b00000111l ^^ - or_follower 1l ^^ - or_follower 2l^^ - or_follower 3l ^^ - set_res ^^ - compile_unboxed_const 4l))) - let lit env ty v = compile_unboxed_const Int32.(shift_left (of_int v) (to_int (shift_of_type ty))) @@ -2402,77 +2359,6 @@ module Object = struct end (* Object *) - -module Iterators = struct - (* - We have to synthesize iterators for various functions in Text and Array. - This is the common code for that. - *) - - (* - Parameters: - name: base name for this built-in function (needs to be unique) - mk_stop get_x: counter value at which to stop (unboxed) - mk_next env get_i get_x: pushes onto the stack: - * how much to increase the counter (unboxed) - * the thing to return, Vanilla stackrep. - get_x: The thing to put in the closure, and pass to mk_next - - Return code that takes the object (array or text) on the stack and puts a - the iterator onto the stack. - *) - let create outer_env name mk_stop mk_next = - Func.share_code1 outer_env name ("x", I32Type) [I32Type] (fun env get_x -> - (* Register functions as needed *) - let next_funid = E.add_fun env (name ^ "_next") ( - Func.of_body env ["clos", I32Type] [I32Type] (fun env -> - let (set_n, get_n) = new_local env "n" in - let (set_x, get_x) = new_local env "x" in - let (set_ret, get_ret) = new_local env "ret" in - - (* Get pointer to counter from closure *) - Closure.get ^^ Closure.load_data 0l ^^ - MutBox.load ^^ BoxedSmallWord.unbox env ^^ set_n ^^ - - (* Get pointer to object in closure *) - Closure.get ^^ Closure.load_data 1l ^^ set_x ^^ - - get_n ^^ - (* Get counter end *) - mk_stop env get_x ^^ - G.i (Compare (Wasm.Values.I32 I32Op.GeU)) ^^ - G.if_ (ValBlockType (Some I32Type)) - (* Then *) - Opt.null - (* Else *) - begin (* Return stuff *) - Opt.inject env ( - (* Put address of conter on the stack, for the store *) - Closure.get ^^ Closure.load_data 0l ^^ - (* Get value and increase *) - mk_next env get_n get_x ^^ - set_ret ^^ (* put return value aside *) - (* Advance counter *) - get_n ^^ G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ - BoxedSmallWord.box env ^^ MutBox.store ^^ - (* Return new value *) - get_ret) - end - ) - ) in - - let (set_ni, get_ni) = new_local env "next" in - Closure.fixed_closure env next_funid - [ Tagged.obj env Tagged.MutBox [ compile_unboxed_zero ] - ; get_x - ] ^^ - set_ni ^^ - - Object.lit_raw env [ "next", fun _ -> get_ni ] - ) - -end (* Iterators *) - module Blob = struct (* The layout of a blob object is @@ -2519,38 +2405,6 @@ module Blob = struct get_x ^^ Heap.load_field len_field ) - (* Blob concatenation. Expects two strings on stack *) - let concat env = Func.share_code2 env "concat" (("x", I32Type), ("y", I32Type)) [I32Type] (fun env get_x get_y -> - let (set_z, get_z) = new_local env "z" in - let (set_len1, get_len1) = new_local env "len1" in - let (set_len2, get_len2) = new_local env "len2" in - - get_x ^^ Heap.load_field len_field ^^ set_len1 ^^ - get_y ^^ Heap.load_field len_field ^^ set_len2 ^^ - - (* allocate memory *) - get_len1 ^^ - get_len2 ^^ - G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ - alloc env ^^ - set_z ^^ - - (* Copy first string *) - get_z ^^ payload_ptr_unskewed ^^ - get_x ^^ payload_ptr_unskewed ^^ - get_len1 ^^ - Heap.memcpy env ^^ - - (* Copy second string *) - get_z ^^ payload_ptr_unskewed ^^ get_len1 ^^ G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ - get_y ^^ payload_ptr_unskewed ^^ - get_len2 ^^ - Heap.memcpy env ^^ - - (* Done *) - get_z - ) - (* Lexicographic blob comparison. Expects two blobs on the stack *) let rec compare env op = @@ -2638,99 +2492,53 @@ module Blob = struct end (* Blob *) module Text = struct + (* + Most of the heavy lifting around text values is in rts/text.c + *) - let prim_decodeUTF8 env = - Func.share_code1 env "decodeUTF8" ("string", I32Type) - [I32Type; I32Type] (fun env get_string -> - let (set_res, get_res) = new_local env "res" in - get_string ^^ Blob.payload_ptr_unskewed ^^ - UnboxedSmallWord.len_UTF8_head env set_res ^^ - BoxedSmallWord.box env ^^ - get_res ^^ UnboxedSmallWord.box_codepoint - ) - - let text_chars_direct env = - Iterators.create env "text_chars_direct" - (fun env get_x -> get_x ^^ Heap.load_field Blob.len_field) - (fun env get_i get_x -> - let (set_char, get_char) = new_local env "char" in - get_x ^^ Blob.payload_ptr_unskewed ^^ - get_i ^^ G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ - UnboxedSmallWord.len_UTF8_head env set_char ^^ - get_char ^^ UnboxedSmallWord.box_codepoint - ) - + let of_ptr_size env = + E.call_import env "rts" "text_of_ptr_size" + let concat env = + E.call_import env "rts" "text_concat" + let size env = + E.call_import env "rts" "text_size" + let to_buf env = + E.call_import env "rts" "text_to_buf" let len env = - Func.share_code1 env "text_len" ("x", I32Type) [I32Type] (fun env get_x -> - let (set_max, get_max) = new_local env "max" in - let (set_n, get_n) = new_local env "n" in - let (set_len, get_len) = new_local env "len" in - compile_unboxed_zero ^^ set_n ^^ - compile_unboxed_zero ^^ set_len ^^ - get_x ^^ Heap.load_field Blob.len_field ^^ set_max ^^ - compile_while - (get_n ^^ get_max ^^ G.i (Compare (Wasm.Values.I32 I32Op.LtU))) - begin - get_x ^^ Blob.payload_ptr_unskewed ^^ get_n ^^ - G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ - UnboxedSmallWord.len_UTF8_head env (G.i Drop) ^^ - get_n ^^ G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ set_n ^^ - get_len ^^ compile_add_const 1l ^^ set_len - end ^^ - get_len ^^ - BigNum.from_word32 env - ) - + E.call_import env "rts" "text_len" ^^ BigNum.from_word32 env let prim_showChar env = - let (set_c, get_c) = new_local env "c" in - let (set_utf8, get_utf8) = new_local env "utf8" in - let storeLeader bitpat shift = - get_c ^^ compile_shrU_const shift ^^ compile_bitor_const bitpat ^^ - G.i (Store {ty = I32Type; align = 0; - offset = Blob.unskewed_payload_offset; - sz = Some Wasm.Memory.Pack8}) in - let storeFollower offset shift = - get_c ^^ compile_shrU_const shift ^^ UnboxedSmallWord.compile_6bit_mask ^^ - compile_bitor_const 0b10000000l ^^ - G.i (Store {ty = I32Type; align = 0; - offset = Int32.add offset Blob.unskewed_payload_offset; - sz = Some Wasm.Memory.Pack8}) in - let allocPayload n = compile_unboxed_const n ^^ Blob.alloc env ^^ set_utf8 ^^ get_utf8 in UnboxedSmallWord.unbox_codepoint ^^ - set_c ^^ - get_c ^^ - compile_unboxed_const 0x80l ^^ - G.i (Compare (Wasm.Values.I32 I32Op.LtU)) ^^ - G.if_ (ValBlockType None) - (allocPayload 1l ^^ storeLeader 0b00000000l 0l) - begin - get_c ^^ - compile_unboxed_const 0x800l ^^ - G.i (Compare (Wasm.Values.I32 I32Op.LtU)) ^^ - G.if_ (ValBlockType None) - begin - allocPayload 2l ^^ storeFollower 1l 0l ^^ - get_utf8 ^^ storeLeader 0b11000000l 6l - end - begin - get_c ^^ - compile_unboxed_const 0x10000l ^^ - G.i (Compare (Wasm.Values.I32 I32Op.LtU)) ^^ - G.if_ (ValBlockType None) - begin - allocPayload 3l ^^ storeFollower 2l 0l ^^ - get_utf8 ^^ storeFollower 1l 6l ^^ - get_utf8 ^^ storeLeader 0b11100000l 12l - end - begin - allocPayload 4l ^^ storeFollower 3l 0l ^^ - get_utf8 ^^ storeFollower 2l 6l ^^ - get_utf8 ^^ storeFollower 1l 12l ^^ - get_utf8 ^^ storeLeader 0b11110000l 18l - end - end - end ^^ - get_utf8 + E.call_import env "rts" "text_singleton" + let to_blob env = E.call_import env "rts" "blob_of_text" + let iter env = + E.call_import env "rts" "text_iter" + let iter_done env = + E.call_import env "rts" "text_iter_done" + let iter_next env = + E.call_import env "rts" "text_iter_next" ^^ + UnboxedSmallWord.box_codepoint + + let compare env op = + let open Operator in + let name = match op with + | LtOp -> "Text.compare_lt" + | LeOp -> "Text.compare_le" + | GeOp -> "Text.compare_ge" + | GtOp -> "Text.compare_gt" + | EqOp -> "Text.compare_eq" + | NeqOp -> "Text.compare_ne" in + Func.share_code2 env name (("x", I32Type), ("y", I32Type)) [I32Type] (fun env get_x get_y -> + get_x ^^ get_y ^^ E.call_import env "rts" "text_compare" ^^ + compile_unboxed_const 0l ^^ + match op with + | LtOp -> G.i (Compare (Wasm.Values.I32 I32Op.LtS)) + | LeOp -> G.i (Compare (Wasm.Values.I32 I32Op.LeS)) + | GtOp -> G.i (Compare (Wasm.Values.I32 I32Op.GtS)) + | GeOp -> G.i (Compare (Wasm.Values.I32 I32Op.GeS)) + | EqOp -> G.i (Compare (Wasm.Values.I32 I32Op.Eq)) + | NeqOp -> G.i (Compare (Wasm.Values.I32 I32Op.Eq)) ^^ Bool.neg + ) + end (* Text *) @@ -2995,8 +2803,10 @@ module Dfinity = struct let print_text env = Func.share_code1 env "print_text" ("str", I32Type) [] (fun env get_str -> - get_str ^^ Blob.payload_ptr_unskewed ^^ - get_str ^^ Heap.load_field (Blob.len_field) ^^ + let (set_blob, get_blob) = new_local env "blob" in + get_str ^^ Text.to_blob env ^^ set_blob ^^ + get_blob ^^ Blob.payload_ptr_unskewed ^^ + get_blob ^^ Heap.load_field (Blob.len_field) ^^ print_ptr_len env ) @@ -3141,6 +2951,7 @@ end (* Dfinity *) module RTS_Exports = struct let system_exports env = + Heap.declare_alloc_functions env; E.add_export env (nr { name = Wasm.Utf8.decode "alloc_bytes"; edesc = nr (FuncExport (nr (E.built_in env "alloc_bytes"))) @@ -3578,11 +3389,16 @@ module Serialization = struct get_x ^^ get_i ^^ Arr.idx env ^^ load_ptr ^^ size env t ) - | Prim (Text | Blob) -> + | Prim Blob -> let (set_len, get_len) = new_local env "len" in get_x ^^ Heap.load_field Blob.len_field ^^ set_len ^^ size_word env get_len ^^ inc_data_size get_len + | Prim Text -> + let (set_len, get_len) = new_local env "len" in + get_x ^^ Text.size env ^^ set_len ^^ + size_word env get_len ^^ + inc_data_size get_len | Opt t -> inc_data_size (compile_unboxed_const 1l) ^^ (* one byte tag *) get_x ^^ Opt.is_some env ^^ @@ -3730,8 +3546,7 @@ module Serialization = struct ) ( List.mapi (fun i (_h, f) -> (i,f)) (sort_by_hash vs) ) ( E.trap_with env "serialize_go: unexpected variant" ) - | Prim (Text | Blob )-> - (* Serializes to text or vec word8 respectively, but same data format *) + | Prim Blob -> let (set_len, get_len) = new_local env "len" in get_x ^^ Heap.load_field Blob.len_field ^^ set_len ^^ write_word get_len ^^ @@ -3740,6 +3555,12 @@ module Serialization = struct get_len ^^ Heap.memcpy env ^^ get_len ^^ advance_data_buf + | Prim Text -> + let (set_len, get_len) = new_local env "len" in + get_x ^^ Text.size env ^^ set_len ^^ + write_word get_len ^^ + get_x ^^ get_data_buf ^^ Text.to_buf env ^^ + get_len ^^ advance_data_buf | Func _ -> write_byte (compile_unboxed_const 1l) ^^ get_x ^^ Arr.load_field 0l ^^ write env (Obj (Actor, [])) ^^ @@ -3804,7 +3625,7 @@ module Serialization = struct | _ -> assert false; (* can be generalized later as needed *) in - let read_blob validate = + let read_blob () = let (set_len, get_len) = new_local env "len" in let (set_x, get_x) = new_local env "x" in ReadBuf.read_leb128 env get_data_buf ^^ set_len ^^ @@ -3812,17 +3633,25 @@ module Serialization = struct get_len ^^ Blob.alloc env ^^ set_x ^^ get_x ^^ Blob.payload_ptr_unskewed ^^ ReadBuf.read_blob env get_data_buf get_len ^^ - begin if validate then - get_x ^^ Blob.payload_ptr_unskewed ^^ get_len ^^ - E.call_import env "rts" "utf8_validate" - else G.nop end ^^ get_x in + let read_text () = + let (set_len, get_len) = new_local env "len" in + ReadBuf.read_leb128 env get_data_buf ^^ set_len ^^ + let (set_ptr, get_ptr) = new_local env "x" in + ReadBuf.get_ptr get_data_buf ^^ set_ptr ^^ + ReadBuf.advance get_data_buf get_len ^^ + (* validate *) + get_ptr ^^ get_len ^^ E.call_import env "rts" "utf8_validate" ^^ + (* copy *) + get_ptr ^^ get_len ^^ Text.of_ptr_size env + in + let read_actor_data () = read_byte_tagged [ E.trap_with env "IDL error: unexpected actor reference" - ; read_blob false + ; read_blob () ] in @@ -3914,12 +3743,12 @@ module Serialization = struct (* Any vanilla value works here *) Opt.null - | Prim Text -> - assert_prim_typ t ^^ - read_blob true | Prim Blob -> assert_blob_typ env ^^ - read_blob false + read_blob () + | Prim Text -> + assert_prim_typ t ^^ + read_text () | Tup [] -> (* e(()) = null *) assert_prim_typ t ^^ Tuple.from_stack env 0 @@ -4031,7 +3860,7 @@ module Serialization = struct read_byte_tagged [ E.trap_with env "IDL error: unexpected function reference" ; read_actor_data () ^^ - read_blob true ^^ + read_text () ^^ Tuple.from_stack env 2 ] ); @@ -5835,13 +5664,14 @@ let compile_binop env t op = get_by ^^ lsb_adjust ty ^^ clamp_shift_amount ty ^^ G.i (Binary (I32 I32Op.Rotr)) ^^ sanitize_word_result ty)) - | Type.Prim Type.Text, CatOp -> Blob.concat env + | Type.Prim Type.Text, CatOp -> Text.concat env | Type.Non, _ -> G.i Unreachable | _ -> todo_trap env "compile_binop" (Arrange_ops.binop op) ) let compile_eq env = function - | Type.(Prim (Text|Blob)) -> Blob.compare env Operator.EqOp + | Type.(Prim Text) -> Text.compare env Operator.EqOp + | Type.(Prim Blob) -> Blob.compare env Operator.EqOp | Type.(Prim Bool) -> G.i (Compare (Wasm.Values.I32 I32Op.Eq)) | Type.(Prim (Nat | Int)) -> BigNum.compile_eq env | Type.(Prim (Int64 | Nat64 | Word64)) -> G.i (Compare (Wasm.Values.I64 I64Op.Eq)) @@ -5873,7 +5703,8 @@ let compile_relop env t op = StackRep.of_type t, let open Operator in match t, op with - | Type.(Prim (Text|Blob)), _ -> Blob.compare env op + | Type.(Prim Text), _ -> Text.compare env op + | Type.(Prim Blob), _ -> Blob.compare env op | _, EqOp -> compile_eq env t | _, NeqOp -> compile_eq env t ^^ G.i (Test (Wasm.Values.I32 I32Op.Eqz)) @@ -6089,14 +5920,13 @@ and compile_exp (env : E.t) ae exp = BigNum.from_word32 env | OtherPrim "text_len", [e] -> - SR.Vanilla, - compile_exp_vanilla env ae e ^^ - Text.len env - - | OtherPrim "text_chars", [e] -> - SR.Vanilla, - compile_exp_vanilla env ae e ^^ - Text.text_chars_direct env + SR.Vanilla, compile_exp_vanilla env ae e ^^ Text.len env + | OtherPrim "text_iter", [e] -> + SR.Vanilla, compile_exp_vanilla env ae e ^^ Text.iter env + | OtherPrim "text_iter_done", [e] -> + SR.Vanilla, compile_exp_vanilla env ae e ^^ Text.iter_done env + | OtherPrim "text_iter_next", [e] -> + SR.Vanilla, compile_exp_vanilla env ae e ^^ Text.iter_next env | OtherPrim "abs", [e] -> SR.Vanilla, @@ -6165,10 +5995,6 @@ and compile_exp (env : E.t) ae exp = SR.unit, compile_exp_vanilla env ae e ^^ Dfinity.print_text env - | OtherPrim "decodeUTF8", [e] -> - SR.UnboxedTuple 2, - compile_exp_vanilla env ae e ^^ - Text.prim_decodeUTF8 env (* Other prims, binary*) | OtherPrim "Array.init", [_;_] -> @@ -6535,7 +6361,7 @@ and compile_lit_pat env l = compile_eq env Type.(Prim Word64) | TextLit t -> Blob.lit env t ^^ - Blob.compare env Operator.EqOp + Text.compare env Operator.EqOp | _ -> todo_trap env "compile_lit_pat" (Arrange_ir.lit l) and fill_pat env ae pat : patternCode = diff --git a/src/mo_values/prim.ml b/src/mo_values/prim.ml index 4472a76aa7c..4c8f6ead562 100644 --- a/src/mo_values/prim.ml +++ b/src/mo_values/prim.ml @@ -246,34 +246,23 @@ let prim = function | "rts_total_allocation" -> fun v k -> as_unit v; k (Int (Int.of_int 0)) | "rts_outstanding_callbacks" -> fun v k -> as_unit v; k (Int (Int.of_int 0)) | "idlHash" -> fun v k -> let s = as_text v in k (Word32 (Lib.Uint32.to_int32 (Idllib.IdlHash.idl_hash s))) - | "decodeUTF8" -> fun v k -> - let s = as_text v in - let open Int32 in - let take_and_mask bits offset = - logand (sub (shift_left 1l bits) 1l) (of_int (Char.code s.[offset])) in - let open List in - let classify_utf8_leader = - function - | ch when compare ch 0x80l < 0 -> map take_and_mask [7] - | ch when compare ch 0xe0l < 0 -> map take_and_mask [5; 6] - | ch when compare ch 0xf0l < 0 -> map take_and_mask [4; 6; 6] - | ch -> map take_and_mask [3; 6; 6; 6] in - let nobbles = mapi (fun i f -> f i) (classify_utf8_leader (of_int (Char.code s.[0]))) in - let code = fold_left (fun acc nobble -> logor (shift_left acc 6) nobble) 0l nobbles in - k (Tup [Word32 (of_int (length nobbles)); Char (to_int code)]) - | "array_len" -> fun v k -> k (Int (Int.of_int (Array.length (Value.as_array v)))) | "text_len" -> fun v k -> k (Int (Nat.of_int (List.length (Wasm.Utf8.decode (Value.as_text v))))) - | "text_chars" -> fun v k -> - let i = ref 0 in + | "text_iter" -> fun v k -> let s = Wasm.Utf8.decode (Value.as_text v) in - let next = local_func 0 1 @@ fun v k' -> - if !i = List.length s then k' Null else - let v = Opt (Char (List.nth s !i)) in incr i; k' v - in k (Obj (Env.singleton "next" next)) - + let i = ref s in + k (TextIter i) + | "text_iter_done" -> fun v k -> + let i = Value.as_text_iter v in + k (Bool (!i = [])) + | "text_iter_next" -> fun v k -> + let i = Value.as_text_iter v in + begin match !i with + | [] -> assert false + | (c::cs) -> i := cs; k (Char c) + end | "Array.init" -> fun v k -> (match Value.as_tup v with | [len; x] -> diff --git a/src/mo_values/value.ml b/src/mo_values/value.ml index 582fed3ec31..d3bdcdbe82a 100644 --- a/src/mo_values/value.ml +++ b/src/mo_values/value.ml @@ -288,6 +288,7 @@ and value = | Func of Call_conv.t * func | Async of async | Mut of value ref + | TextIter of int list ref (* internal to t.char() iterator *) and res = Ok of value | Error of value and async = {result : res Lib.Promise.t ; mutable waiters : (value cont * value cont) list} @@ -328,6 +329,7 @@ let as_word64 = function Word64 w -> w | _ -> invalid "as_word64" let as_float = function Float f -> f | _ -> invalid "as_float" let as_char = function Char c -> c | _ -> invalid "as_char" let as_text = function Text s -> s | _ -> invalid "as_text" +let as_text_iter = function TextIter i -> i | _ -> invalid "as_text_iter" let as_array = function Array a -> a | _ -> invalid "as_array" let as_opt = function Opt v -> v | _ -> invalid "as_opt" let as_variant = function Variant (i, v) -> i, v | _ -> invalid "as_variant" diff --git a/src/mo_values/value.mli b/src/mo_values/value.mli index 8c1b2581427..515a0a8214d 100644 --- a/src/mo_values/value.mli +++ b/src/mo_values/value.mli @@ -102,6 +102,7 @@ and value = | Func of Call_conv.t * func | Async of async | Mut of value ref + | TextIter of int list ref (* internal to t.char() iterator *) and res = Ok of value | Error of value and async = {result : res Lib.Promise.t ; mutable waiters : (value cont * value cont) list} @@ -140,6 +141,7 @@ val as_word64 : value -> Word64.t val as_float : value -> Float.t val as_char : value -> unicode val as_text : value -> string +val as_text_iter : value -> int list ref val as_array : value -> value array val as_tup : value -> value list val as_unit : value -> unit diff --git a/src/prelude/prelude.ml b/src/prelude/prelude.ml index ea84d7aa81e..2818b2b306d 100644 --- a/src/prelude/prelude.ml +++ b/src/prelude/prelude.ml @@ -79,7 +79,16 @@ func @mut_array_vals(xs : [var A]) : (() -> Iter) = func @text_len(xs : Text) : (() -> Nat) = (func () : Nat = (prim "text_len" : Text -> Nat) xs); func @text_chars(xs : Text) : (() -> Iter) = - (func () : Iter = (prim "text_chars" : Text -> Iter) xs); + (func () : Iter = object { + type TextIter = Any; // not exposed + let i = (prim "text_iter" : Text -> TextIter) xs; + public func next() : ?Char { + if ((prim "text_iter_done" : TextIter -> Bool) i) + null + else + ?((prim "text_iter_next" : TextIter -> Char) i) + }; + }); // for testing func idlHash(x : Text) : Word32 { (prim "idlHash" : Text -> Word32) x }; diff --git a/test/run/text-iter.mo b/test/run/text-iter.mo index e2ce9e9ce45..38fc8a9f253 100644 --- a/test/run/text-iter.mo +++ b/test/run/text-iter.mo @@ -1,4 +1,5 @@ let s = "hello world!"; +assert(s.len() == 12); debugPrint "via `debugPrint`:"; debugPrint s; From 7f40617e11b14973271aa03b9e38ea5bad03107c Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 9 Dec 2019 18:23:11 +0100 Subject: [PATCH 0772/1176] Implement fetching reject message on the system (#970) Fetch reject message from system using `ic0.msg_reject_msg_*`. Als introduces the `CastPrim (t1,t2)` form for primitive operations to the IR. --- src/codegen/compile.ml | 82 ++++++++++------------- src/ir_def/arrange_ir.ml | 2 +- src/ir_def/check_ir.ml | 21 ++---- src/ir_def/construct.ml | 8 +-- src/ir_def/construct.mli | 1 - src/ir_def/ir.ml | 2 +- src/ir_interpreter/interpret_ir.ml | 6 +- src/ir_passes/async.ml | 38 ++--------- src/lowering/desugar.ml | 4 ++ src/mo_types/type.ml | 1 + src/mo_types/type.mli | 1 + src/mo_values/prim.ml | 15 +---- src/prelude/prelude.ml | 22 +++--- test/run-drun/ok/overflow.ic-stub-run.ok | 1 - test/run-drun/ok/query2.ic-stub-run.ok | 1 - test/run-drun/ok/simple-throw.drun-run.ok | 7 -- test/run-drun/ok/simple-throw.run-ir.ok | 5 -- test/run-drun/ok/simple-throw.run-low.ok | 5 -- test/run-drun/ok/simple-throw.run.ok | 5 -- test/run-drun/ok/throw.comp.ok | 8 +++ test/run-drun/ok/throw.comp.ret.ok | 1 + test/run-drun/ok/throw.ic-stub-run.ok | 8 +++ test/run-drun/ok/throw.run-ir.ok | 2 + test/run-drun/ok/throw.run-low.ok | 2 + test/run-drun/ok/throw.run.ok | 2 + test/run-drun/simple-throw.mo | 20 ------ test/run-drun/throw.mo | 73 ++++++++++++++++++++ 27 files changed, 167 insertions(+), 176 deletions(-) delete mode 100644 test/run-drun/ok/simple-throw.drun-run.ok delete mode 100644 test/run-drun/ok/simple-throw.run-ir.ok delete mode 100644 test/run-drun/ok/simple-throw.run-low.ok delete mode 100644 test/run-drun/ok/simple-throw.run.ok create mode 100644 test/run-drun/ok/throw.comp.ok create mode 100644 test/run-drun/ok/throw.comp.ret.ok create mode 100644 test/run-drun/ok/throw.ic-stub-run.ok create mode 100644 test/run-drun/ok/throw.run-ir.ok create mode 100644 test/run-drun/ok/throw.run-low.ok create mode 100644 test/run-drun/ok/throw.run.ok delete mode 100644 test/run-drun/simple-throw.mo create mode 100644 test/run-drun/throw.mo diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index b9086c492f0..5a7f7f11f36 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -2738,6 +2738,8 @@ module Dfinity = struct E.add_func_import env "ic0" "msg_caller_copy" (i32s 3) []; E.add_func_import env "ic0" "msg_caller_size" [] [I32Type]; E.add_func_import env "ic0" "msg_reject_code" [] [I32Type]; + E.add_func_import env "ic0" "msg_reject_msg_size" [] [I32Type]; + E.add_func_import env "ic0" "msg_reject_msg_copy" (i32s 3) []; E.add_func_import env "ic0" "msg_reject" (i32s 2) []; E.add_func_import env "ic0" "msg_reply_data_append" (i32s 2) []; E.add_func_import env "ic0" "msg_reply" [] []; @@ -2897,8 +2899,34 @@ module Dfinity = struct assert false let error_code env = - SR.UnboxedWord32, - system_call env "ic0" "msg_reject_code" + let (set_code, get_code) = new_local env "code" in + system_call env "ic0" "msg_reject_code" ^^ set_code ^^ + get_code ^^ compile_unboxed_const 4l ^^ + G.i (Compare (Wasm.Values.I32 I32Op.Eq)) ^^ + G.if_ (ValBlockType (Some I32Type)) + (Variant.inject env "error" Tuple.compile_unit) + (Variant.inject env "system" Tuple.compile_unit) + + let error_message env = + let (set_len, get_len) = new_local env "len" in + let (set_blob, get_blob) = new_local env "blob" in + system_call env "ic0" "msg_reject_msg_size" ^^ + set_len ^^ + + get_len ^^ Blob.alloc env ^^ set_blob ^^ + get_blob ^^ Blob.payload_ptr_unskewed ^^ + compile_unboxed_const 0l ^^ + get_len ^^ + system_call env "ic0" "msg_reject_msg_copy" ^^ + + get_blob + + let error_value env = + Func.share_code0 env "error_value" [I32Type] (fun env -> + error_code env ^^ + error_message env ^^ + Tuple.from_stack env 2 + ) let reply_with_data env = Func.share_code2 env "reply_with_data" (("start", I32Type), ("size", I32Type)) [] ( @@ -4709,8 +4737,10 @@ module FuncDec = struct set_closure ^^ get_closure ^^ - (* Synthesize value of type `Error` *) - E.trap_with env "reject_callback" ^^ + (* Synthesize value of type `Text`, the error message + (The error code is fetched via a prim) + *) + Dfinity.error_value env ^^ get_closure ^^ Closure.call_closure env 1 0 ^^ @@ -4866,37 +4896,9 @@ module PatCode = struct end (* PatCode *) open PatCode - (* All the code above is independent of the IR *) open Ir -(* Compiling Error primitives *) -module Error = struct - - (* Opaque type `Error` is represented as concrete type `(ErrorCode,Text)` *) - - let compile_error env arg_instrs = - SR.UnboxedTuple 2, - Variant.inject env "error" Tuple.compile_unit ^^ - arg_instrs - - let compile_errorCode arg_instrs = - SR.Vanilla, - arg_instrs ^^ - Tuple.load_n (Int32.of_int 0) - - let compile_errorMessage arg_instrs = - SR.Vanilla, - arg_instrs ^^ - Tuple.load_n (Int32.of_int 1) - - let compile_make_error arg_instrs1 arg_instrs2 = - SR.UnboxedTuple 2, - arg_instrs1 ^^ - arg_instrs2 - -end - module AllocHow = struct (* When compiling a (recursive) block, we need to do a dependency analysis, to @@ -6014,15 +6016,9 @@ and compile_exp (env : E.t) ae exp = G.i (Binary (Wasm.Values.I64 I64Op.And)) ) - (* Error related prims *) - | OtherPrim "error", [e] -> - Error.compile_error env (compile_exp_vanilla env ae e) - | OtherPrim "errorCode", [e] -> - Error.compile_errorCode (compile_exp_vanilla env ae e) - | OtherPrim "errorMessage", [e] -> - Error.compile_errorMessage (compile_exp_vanilla env ae e) - | OtherPrim "make_error", [e1; e2] -> - Error.compile_make_error (compile_exp_vanilla env ae e1) (compile_exp_vanilla env ae e2) + (* Coercions for abstract types *) + | CastPrim (_,_), [e] -> + compile_exp env ae e | ICReplyPrim ts, [e] -> SR.unit, begin match E.mode env with @@ -6038,10 +6034,6 @@ and compile_exp (env : E.t) ae exp = | ICRejectPrim, [e] -> SR.unit, Dfinity.reject env (compile_exp_vanilla env ae e) - | ICErrorCodePrim, [] -> - assert (E.mode env = Flags.ICMode || E.mode env = Flags.StubMode); - Dfinity.error_code env - | ICCallPrim, [f;e;k;r] -> SR.unit, begin (* TBR: Can we do better than using the notes? *) diff --git a/src/ir_def/arrange_ir.ml b/src/ir_def/arrange_ir.ml index ca0ed7d53b3..745b1682310 100644 --- a/src/ir_def/arrange_ir.ml +++ b/src/ir_def/arrange_ir.ml @@ -61,12 +61,12 @@ and prim = function | RelPrim (t, ro) -> "RelPrim" $$ [typ t; Arrange_ops.relop ro] | ShowPrim t -> "ShowPrim" $$ [typ t] | NumConvPrim (t1, t2) -> "NumConvPrim" $$ [prim_ty t1; prim_ty t2] + | CastPrim (t1, t2) -> "CastPrim" $$ [typ t1; typ t2] | OtherPrim s -> Atom s | CPSAwait -> Atom "CPSAwait" | CPSAsync -> Atom "CPSAsync" | ICReplyPrim ts -> "ICReplyPrim" $$ List.map typ ts | ICRejectPrim -> Atom "ICRejectPrim" - | ICErrorCodePrim -> Atom "ICErrorCodePrim" | ICCallPrim -> Atom "ICCallPrim" and mut = function diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 41d7c7a30fc..33e1554aae5 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -330,30 +330,25 @@ let rec check_exp env (exp:Ir.exp) : unit = | LitE lit -> T.Prim (type_lit env lit exp.at) <: t | PrimE (p, es) -> + List.iter (check_exp env) es; begin match p, es with | UnPrim (ot, op), [exp1] -> check (Operator.has_unop op ot) "unary operator is not defined for operand type"; - check_exp env exp1; typ exp1 <: ot; ot <: t | BinPrim (ot, op), [exp1; exp2] -> check (Operator.has_binop op ot) "binary operator is not defined for operand type"; - check_exp env exp1; - check_exp env exp2; typ exp1 <: ot; typ exp2 <: ot; ot <: t | RelPrim (ot, op), [exp1; exp2] -> check (Operator.has_relop op ot) "relational operator is not defined for operand type"; - check_exp env exp1; - check_exp env exp2; typ exp1 <: ot; typ exp2 <: ot; T.bool <: t | ShowPrim ot, [exp1] -> check env.flavor.has_show "show expression in non-show flavor"; check (Show.can_show ot) "show is not defined for operand type"; - check_exp env exp1; typ exp1 <: ot; T.Prim T.Text <: t | CPSAwait, [a; kr] -> @@ -368,35 +363,31 @@ let rec check_exp env (exp:Ir.exp) : unit = check (not (env.flavor.has_async_typ)) "ICReplyPrim in async flavor"; check (T.shared t) "ICReplyPrim is not defined for non-shared operand type"; (* TODO: check against expected reply typ; note this may not be env.ret_tys. *) - check_exp env exp1; typ exp1 <: (T.seq ts); T.Non <: t | ICRejectPrim, [exp1] -> check (not (env.flavor.has_async_typ)) "ICRejectPrim in async flavor"; - check_exp env exp1; typ exp1 <: T.text; T.Non <: t - | ICErrorCodePrim, [] -> - T.Prim (T.Int32) <: t | ICCallPrim, [exp1; exp2; k; r] -> - check_exp env exp1; - check_exp env exp2; check_exp env k; check_exp env r; let t1 = T.promote (typ exp1) in begin match t1 with | T.Func (sort, T.Replies, [], arg_tys, ret_tys) -> - check_exp env exp2; let t_arg = T.seq arg_tys in typ exp2 <: t_arg; check_concrete env exp.at t_arg; typ k <: T.Func (T.Local, T.Returns, [], ret_tys, []); - typ r <: T.Func (T.Local, T.Returns, [], [T.text], []); + typ r <: T.Func (T.Local, T.Returns, [], [T.error], []); | T.Non -> () (* dead code, not much to check here *) | _ -> error env exp1.at "expected function type, but expression produces type\n %s" (T.string_of_typ_expand t1) end + | CastPrim (t1, t2), [e] -> + typ e <: t1; + t2 <: t | OtherPrim _, _ -> () | _ -> error env exp.at "PrimE with wrong number of arguments" @@ -629,7 +620,7 @@ let rec check_exp env (exp:Ir.exp) : unit = check_exp env exp_r; typ exp_f <: T.unit; typ exp_k <: T.Func (T.Local, T.Returns, [], ts, []); - typ exp_r <: T.Func (T.Local, T.Returns, [], [T.text], []); + typ exp_r <: T.Func (T.Local, T.Returns, [], [T.error], []); | ActorE (id, ds, fs, t0) -> let env' = { env with async = false } in let ve0 = T.Env.singleton id t0 in diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index 1b58e0c46f9..98f985c13b6 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -80,7 +80,7 @@ let primE prim es = | ShowPrim _ -> T.text | ICReplyPrim _ -> T.Non | ICRejectPrim -> T.Non - | ICErrorCodePrim -> T.Prim T.Int32 + | CastPrim (t1, t2) -> t2 | _ -> assert false (* implement more as needed *) in let effs = List.map eff es in @@ -123,12 +123,6 @@ let ic_rejectE e = note = { note_typ = T.unit; note_eff = eff e } } -let ic_error_codeE () = - { it = PrimE (ICErrorCodePrim, []); - at = no_region; - note = { note_typ = T.Prim T.Int32; note_eff = T.Triv } - } - let ic_callE f e k r = let es = [f; e; k; r] in let effs = List.map eff es in diff --git a/src/ir_def/construct.mli b/src/ir_def/construct.mli index cffd0af420f..3efe3c68acc 100644 --- a/src/ir_def/construct.mli +++ b/src/ir_def/construct.mli @@ -44,7 +44,6 @@ val assertE : exp -> exp val awaitE : typ -> exp -> exp -> exp val ic_replyE : typ list -> exp -> exp val ic_rejectE : exp -> exp -val ic_error_codeE : unit -> exp val ic_callE : exp -> exp -> exp -> exp -> exp val projE : exp -> int -> exp val blockE : dec list -> exp -> exp diff --git a/src/ir_def/ir.ml b/src/ir_def/ir.ml index e610ba1d0ef..3e415fa75e7 100644 --- a/src/ir_def/ir.ml +++ b/src/ir_def/ir.ml @@ -106,12 +106,12 @@ and prim = | RelPrim of Type.typ * relop (* relational operator *) | ShowPrim of Type.typ (* debug show *) | NumConvPrim of Type.prim * Type.prim + | CastPrim of Type.typ * Type.typ (* representationally a noop *) | OtherPrim of string (* Other primitive operation, no custom typing rule *) | CPSAwait | CPSAsync | ICReplyPrim of Type.typ list | ICRejectPrim - | ICErrorCodePrim | ICCallPrim diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index 0211d5940f6..ebf6dd1c7f5 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -362,6 +362,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = let arg = match vs with [v] -> v | _ -> V.Tup vs in Prim.prim s arg k ) + | CastPrim _, [e] -> interpret_exp env e k | NumConvPrim (t1, t2), exps -> interpret_exps env exps [] (fun vs -> let arg = match vs with [v] -> v | _ -> V.Tup vs in @@ -376,7 +377,9 @@ and interpret_exp_mut env exp (k : V.value V.cont) = assert (not env.flavor.has_async_typ); let reject = Lib.Option.value env.rejects in interpret_exp env exp1 - (fun v -> Scheduler.queue (fun () -> reject v)) + (fun v -> + let e = V.Tup [V.Variant ("error", V.unit); v] in + Scheduler.queue (fun () -> reject e)) | ICCallPrim, [exp1; exp2; expk ; expr] -> assert (not env.flavor.has_async_typ); interpret_exp env exp1 (fun v1 -> @@ -818,4 +821,3 @@ let interpret_prog flags scope ((ds, exp), flavor) : scope = Scheduler.run (); !ve with exn -> print_exn flags exn; !ve - diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index 7d0f4c72ba8..c86e1997075 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -1,4 +1,3 @@ -open Mo_config open Mo_types open Ir_def @@ -25,20 +24,6 @@ module ConRenaming = E.Make(struct type t = T.con let compare = Con.compare end) (* Helpers *) -let error_codeE mode = - match mode with - | Flags.ICMode -> callE - (idE "@int32ToErrorCode" - (T.Func (T.Local, T.Returns, [], [T.Prim T.Int32], [T.Variant T.catchErrorCodes]))) - [] - (ic_error_codeE()) - | _ -> { it = TagE ("error", tupE []); - at = no_region; - note = { - note_typ = T.Variant (T.catchErrorCodes); - note_eff = T.Triv } - } - let selfcallE ts e1 e2 e3 = { it = SelfCallE (ts, e1, e2, e3); at = no_region; @@ -46,17 +31,11 @@ let selfcallE ts e1 e2 e3 = note_eff = T.Triv } } -let errorMessageE e = -{ it = PrimE (OtherPrim "errorMessage", [e]); - at = no_region; - note = { note_typ = T.text; note_eff = eff e } -} +let error_ty = + T.(Tup [ Variant [{lab = "error"; typ = unit};{lab = "system"; typ = unit}]; text]) -let make_errorE e_code e_msg = -{ it = PrimE (OtherPrim "make_error", [e_code; e_msg]); - at = no_region; - note = { note_typ = T.Prim T.Error; note_eff = max (eff e_code) (eff e_msg) } -} +let errorMessageE e = + projE (primE (CastPrim (T.error, error_ty)) [e]) 1 let unary typ = [typ] @@ -119,19 +98,14 @@ let new_nary_async_reply mode ts1 = in vs -->* (unary_fulfill -*- seq_of_vs) in - (* construct the n-ary reject callback *) - let nary_reject = - let v = fresh_var "msg" T.text in - [v] -->* (fail -*- (make_errorE (error_codeE mode) v)) - in let async,reply,reject = fresh_var "async" (typ nary_async), fresh_var "reply" (typ nary_reply), - fresh_var "reject" (typ nary_reject) + fresh_var "reject" (typ fail) in (async, reply, reject), blockE [letP (tupP [varP unary_async; varP unary_fulfill; varP fail]) call_new_async] - (tupE [nary_async; nary_reply; nary_reject]) + (tupE [nary_async; nary_reply; fail]) let letEta e scope = match e.it with diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 9ac36149747..4895fa016a6 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -102,6 +102,10 @@ and exp' at note = function I.PrimE (I.NumConvPrim (p1, p2), [exp e]) | _ -> assert false end + | S.CallE ({it=S.AnnotE ({it=S.PrimE "cast";_}, _);note;_}, _, e) -> + let p1 = e.note.S.note_typ in + let p2 = note.S.note_typ in + I.PrimE (I.CastPrim (p1, p2), [exp e]) | S.CallE ({it=S.AnnotE ({it=S.PrimE p;_},_);_}, _, {it=S.TupE es;_}) -> I.PrimE (I.OtherPrim p, exps es) | S.CallE ({it=S.AnnotE ({it=S.PrimE p;_},_);_}, _, e) -> diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index 73067aba089..f2209e682f0 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -92,6 +92,7 @@ let bool = Prim Bool let nat = Prim Nat let int = Prim Int let text = Prim Text +let error = Prim Error let char = Prim Char let throwErrorCodes = List.sort compare_field [ diff --git a/src/mo_types/type.mli b/src/mo_types/type.mli index f6dcb71302f..d48d837b388 100644 --- a/src/mo_types/type.mli +++ b/src/mo_types/type.mli @@ -69,6 +69,7 @@ val bool : typ val nat : typ val int : typ val text : typ +val error : typ val char : typ val throwErrorCodes : field list diff --git a/src/mo_values/prim.ml b/src/mo_values/prim.ml index 4c8f6ead562..de3ebf618e0 100644 --- a/src/mo_values/prim.ml +++ b/src/mo_values/prim.ml @@ -281,20 +281,7 @@ let prim = function in go (fun xs -> xs) k 0 | _ -> assert false ) - | "error" -> fun v k -> - k (Value.Tup [Variant ("error", Tup []); v]) - | "errorCode" -> fun v k -> - (match Value.as_tup v with - | [code; _message] -> - k code - | _ -> assert false - ) - | "errorMessage" -> fun v k -> - (match Value.as_tup v with - | [_code; message] -> - k message - | _ -> assert false - ) + | "cast" -> fun v k -> k v | p when Lib.String.chop_prefix "num_conv" p <> None -> begin match String.split_on_char '_' p with | [_;_;s1;s2] -> diff --git a/src/prelude/prelude.ml b/src/prelude/prelude.ml index 2818b2b306d..318982086f0 100644 --- a/src/prelude/prelude.ml +++ b/src/prelude/prelude.ml @@ -346,21 +346,15 @@ func Array_tabulate(len : Nat, gen : Nat -> T) : [T] { // these will change type ErrorCode = {#error; #system}; /* TBC */ -func error(message : Text) : Error = - (prim "error" : Text -> Error)(message); - -func errorCode(e : Error) : ErrorCode = - (prim "errorCode" : Error -> ErrorCode)(e); - -func errorMessage(e : Error) : Text = - (prim "errorMessage" : Error -> Text)(e); - -func @int32ToErrorCode(i : Int32) : ErrorCode { - switch (int32ToInt(i)) { /*TODO: conversion only to avoid bug in moc-js, TBR */ - case 4 /* CANISTER_REJECT */ #error; - case _ #system; /* TBC */ - } +// creation and inspection of abstract error +func openError(e : Error) : (ErrorCode, Text) = + (prim "cast" : Error -> (ErrorCode, Text)) e; +func error(message : Text) : Error = { + let e = (#error, message); + ((prim "cast" : (ErrorCode, Text)-> Error) e) }; +func errorCode(e : Error) : ErrorCode = (openError e).0; +func errorMessage(e : Error) : Text = (openError e).1; type Cont = T -> () ; type Async = (Cont,Cont) -> (); diff --git a/test/run-drun/ok/overflow.ic-stub-run.ok b/test/run-drun/ok/overflow.ic-stub-run.ok index 1145efecc4d..f26b454c94e 100644 --- a/test/run-drun/ok/overflow.ic-stub-run.ok +++ b/test/run-drun/ok/overflow.ic-stub-run.ok @@ -9,5 +9,4 @@ Trap: EvalTrapError :0.1 "canister trapped explicitly: Natural subtraction under debug.print: This is reachable. debug.print: This is reachable. debug.print: This is reachable. -Trap: EvalTrapError :0.1 "canister trapped explicitly: reject_callback" ← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/query2.ic-stub-run.ok b/test/run-drun/ok/query2.ic-stub-run.ok index d67f63cdfd2..e4ee45cba03 100644 --- a/test/run-drun/ok/query2.ic-stub-run.ok +++ b/test/run-drun/ok/query2.ic-stub-run.ok @@ -7,5 +7,4 @@ debug.print: 2 debug.print: 3 debug.print: 4 debug.print: 4 -Trap: EvalTrapError :0.1 "canister trapped explicitly: reject_callback" ← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/simple-throw.drun-run.ok b/test/run-drun/ok/simple-throw.drun-run.ok deleted file mode 100644 index fc761d02e54..00000000000 --- a/test/run-drun/ok/simple-throw.drun-run.ok +++ /dev/null @@ -1,7 +0,0 @@ -ingress(0) System -debug.print: 1 -debug.print: 2 -debug.print: 3 -debug.print: 4 -debug.print: done -ingress(1) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/simple-throw.run-ir.ok b/test/run-drun/ok/simple-throw.run-ir.ok deleted file mode 100644 index f3e51c00a71..00000000000 --- a/test/run-drun/ok/simple-throw.run-ir.ok +++ /dev/null @@ -1,5 +0,0 @@ -1 -2 -3 -4 -done diff --git a/test/run-drun/ok/simple-throw.run-low.ok b/test/run-drun/ok/simple-throw.run-low.ok deleted file mode 100644 index f3e51c00a71..00000000000 --- a/test/run-drun/ok/simple-throw.run-low.ok +++ /dev/null @@ -1,5 +0,0 @@ -1 -2 -3 -4 -done diff --git a/test/run-drun/ok/simple-throw.run.ok b/test/run-drun/ok/simple-throw.run.ok deleted file mode 100644 index f3e51c00a71..00000000000 --- a/test/run-drun/ok/simple-throw.run.ok +++ /dev/null @@ -1,5 +0,0 @@ -1 -2 -3 -4 -done diff --git a/test/run-drun/ok/throw.comp.ok b/test/run-drun/ok/throw.comp.ok new file mode 100644 index 00000000000..bece8b63cfd --- /dev/null +++ b/test/run-drun/ok/throw.comp.ok @@ -0,0 +1,8 @@ +throw.mo:7.14-10.8: type error, unsupported async block + (This is a limitation of the current version.) +throw.mo:22.13-41.8: type error, unsupported async block + (This is a limitation of the current version.) +throw.mo:59.13-59.15: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +throw.mo:66.13-66.15: type error, calling a shared function not yet supported + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/throw.comp.ret.ok b/test/run-drun/ok/throw.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/throw.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-drun/ok/throw.ic-stub-run.ok b/test/run-drun/ok/throw.ic-stub-run.ok new file mode 100644 index 00000000000..77677f155a9 --- /dev/null +++ b/test/run-drun/ok/throw.ic-stub-run.ok @@ -0,0 +1,8 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ update go(0x4449444c0000) +debug.print: t2 ok +debug.print: t3 ok +← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/throw.run-ir.ok b/test/run-drun/ok/throw.run-ir.ok new file mode 100644 index 00000000000..33bffc9666e --- /dev/null +++ b/test/run-drun/ok/throw.run-ir.ok @@ -0,0 +1,2 @@ +t2 ok +t3 ok diff --git a/test/run-drun/ok/throw.run-low.ok b/test/run-drun/ok/throw.run-low.ok new file mode 100644 index 00000000000..33bffc9666e --- /dev/null +++ b/test/run-drun/ok/throw.run-low.ok @@ -0,0 +1,2 @@ +t2 ok +t3 ok diff --git a/test/run-drun/ok/throw.run.ok b/test/run-drun/ok/throw.run.ok new file mode 100644 index 00000000000..33bffc9666e --- /dev/null +++ b/test/run-drun/ok/throw.run.ok @@ -0,0 +1,2 @@ +t2 ok +t3 ok diff --git a/test/run-drun/simple-throw.mo b/test/run-drun/simple-throw.mo deleted file mode 100644 index 740bcc16beb..00000000000 --- a/test/run-drun/simple-throw.mo +++ /dev/null @@ -1,20 +0,0 @@ -// This file only exercises local throws that don't cross function boundaries. -actor a { - public func go() = ignore async { - debugPrint "1"; - try { - debugPrint "2"; - throw error("t2"); - assert(false); - } catch e { - switch (errorCode(e), errorMessage(e)) { - case (#error, "t1") { assert false; }; - case (#system, _ ) { assert false; }; - case (#error, _) { debugPrint "3"; }; - } - }; - debugPrint "4"; - debugPrint "done"; - }; -}; -a.go(); //OR-CALL ingress go "DIDL\x00\x00" diff --git a/test/run-drun/throw.mo b/test/run-drun/throw.mo new file mode 100644 index 00000000000..99b7dbb956e --- /dev/null +++ b/test/run-drun/throw.mo @@ -0,0 +1,73 @@ +// This is like local-throw.as, just not local +// (Using `await async { … }` around relevant parts + +actor a { + public func t2() : async () { + try { + await async { + throw error("t2"); + assert(false); + } + } catch e { + switch (errorCode(e),errorMessage(e)) { + case (#error, "t2") { }; + case (#system, _ ) { assert false;}; + case (#error, _) { assert false;}; + } + } + }; + + public func t3() : async () { + try { + await async { + try { + await async { + throw error("t3"); + assert(false); + } + } catch e1 { + switch (errorCode(e1), errorMessage(e1)) { + case (#error, "t3") { + throw error("t31"); + }; + case (#system, _) { + assert false; + }; + case (#error, _) { + assert false; + }; + } + } + } + } + catch e2 { + switch (errorCode(e2),errorMessage(e2)) { + case (#error, "t31") { }; + case (#system, _) { + assert false; + }; + case (#error, _) { + assert true; + }; + } + } + }; + + + public func go() = ignore async { + try { + await t2(); + debugPrint ("t2 ok"); + } catch _ { + assert false; + }; + + try { + await t3(); + debugPrint ("t3 ok"); + } catch _ { + assert false; + }; + }; +}; +a.go(); //OR-CALL ingress go "DIDL\x00\x00" From 0c1bb03ff9ca343a7028bd480f02478453915673 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Mon, 9 Dec 2019 18:29:21 +0000 Subject: [PATCH 0773/1176] rework sugaring --- design/scoped-await.md | 288 +++++++++++++++--------- src/mo_def/arrange.ml | 6 +- src/mo_def/syntax.ml | 54 +++-- src/mo_frontend/parser.mly | 31 +-- src/mo_frontend/typing.ml | 19 +- test/fail/ok/illegal-await.tc.ok | 10 +- test/run-drun/await-sugar.mo | 97 ++++++++ test/run-drun/general_await.mo | 4 +- test/run-drun/general_await_implicit.mo | 4 +- test/run-stub/general_await.mo | 2 +- 10 files changed, 356 insertions(+), 159 deletions(-) create mode 100644 test/run-drun/await-sugar.mo diff --git a/design/scoped-await.md b/design/scoped-await.md index 62f7d481275..0723c1e839b 100644 --- a/design/scoped-await.md +++ b/design/scoped-await.md @@ -4,9 +4,8 @@ Inspired by Launchbury's RunST trick and Rust's lifetimes. *Basic idea:* -Use type indexing and parametricity to ensure -that a function can only await async -values it has created, hopefully ruling out: +Use type indexing and parametricity to ensure that a function can only +await async values it has created, hopefully ruling out: * deadlock, and * reply to wrong sender @@ -97,13 +96,18 @@ E; _ |- e': [T/X] U E; _ |- f e' : async([T/X]V) ``` -Application must provide an instantiation, typically the nearest enclosing index parameter if want to await the result, but it -could be any type. +Application must provide an instantiation, typically the nearest +enclosing index parameter if want to await the result, but it could be +any type. -In the implicit system, we change the rule for application to (if necessary) insert a single missing scope parameter (`@`) -amongst the remaining explicit type parameters, driven by the expected async returning function type -and the 1-deficit of type arguments. This is a simple check to see if the index of the return type is a type parameter and the number of arguments is 1 less than the number of parameters, -and then inserting '@' at the correct index in the type arguments (otherwise the arguments are as given). +In the implicit system, we change the rule for application to (if +necessary) insert a single missing scope parameter (`@`) amongst the +remaining explicit type parameters, driven by the expected async +returning function type and the 1-deficit of type arguments. This is a +simple check to see if the index of the return type is a type +parameter and the number of arguments is 1 less than the number of +parameters, and then inserting '@' at the correct index in the type +arguments (otherwise the arguments are as given). ### Abstraction (Derived Rule) @@ -113,11 +117,14 @@ Derivation for (desugared) shared functions (ignoring recursion). Consider the desugared async function: -```shared f(x:T) : asyncU = async e ;``` +``` +shared f(x:T) : asyncU = async e ; +``` -For reusability in different async contexts, -every shared function should introduce a new index parameter, immediately supplied to the inner async expression. -Using non-generic shared functions is ok, but less useful (typically only locally useful): the result type needs to +For reusability in different async contexts, every shared function +should introduce a new index parameter, immediately supplied to the +inner async expression. Using non-generic shared functions is ok, but +less useful (typically only locally useful): the result type needs to be generic if we want to await it from other async contexts. Using the above rules and ordinary lambda abstraction we get: @@ -151,7 +158,7 @@ E; _ |- shared f(x:T) : async U { e; } : shared T -> async U ## Examples: -(These need fixing for typos below but are all coded in +(These examples and more are all coded in * [general_await.mo](../test/run-stub/general_await.mo) (no-sugar) * [general_await_implicit.mo](../test/run-stub/general_await_implicit.mo) (with sugar) @@ -160,123 +167,149 @@ E; _ |- shared f(x:T) : async U { e; } : shared T -> async U Assuming the following requests: ``` -shared Ack() : async(){ }; + public shared func Ack<@>() : async<@> (){ + debugPrint "Ack" + }; -shared Request(i : Int) : async Int { return i; } + public shared func Request<@>(i : Int) : async<@> Int { + debugPrint("Request(" # debug_show i # ")"); + return i; + }; ``` ### Static parralel waiting: ``` -async { - let a1 = Ack(); - let a2 = Ack(); - await(a1); - await(a2); -}; + public shared func PA<@>() : async<@> () { + let a1 = Ack<@>(); + let a2 = Ack<@>(); + await a1; + await a2; + }; ``` ### Dynamic parallel waiting for acknowledgements ``` -async { - let as = Array_tabulate()>(func _ { Ack(); }); - for (a in as.key) { - await(a2); + // Dynamic parallel waiting for acknowledgements + + public shared func DPA<@>() : async<@>() { + let as: [async()] = Array_tabulate(N, func (_) { Ack<@>(); }); + for (a in as.vals()) { + await a; + }; }; -}; ``` ### Dynamic parallel waiting (with results) ``` -async { - let as = Array_tabulate()>(func _ { Ack(); }); - let res = Array_init<>(as.len,-1); - rs = for (i in as.keys()) { - res[i] := await(a2); + // Dynamic parallel waiting (with results) + + public shared func DPR<@>() : async<@>[Int] { + func f<>(i:Nat) : async Int = Request<@>(i); + let as = Array_tabulate(N, f); + let res = Array_init(as.len(),-1); + for (i in as.keys()) { + res[i] := (await as[i]); + }; + Array_tabulate(as.len(),func i = res[i]) }; - res; -}; ``` ### Recursive parallel waiting ``` -shared func waitN(n:Nat) : async() { - if (n = 0) - () - else { - let a = Ack(); - await waitN(n-1); // recurse - await(a); + public shared func RPA<@>(n:Nat) : async<@>() { + if (n == 0) () + else { + let a = Ack<@>(); + await RPA<@>(n-1); // recurse + await a; + }; }; -}; ``` ### Recursive parallel waiting (with results) ``` -shared func waitN(n:Nat) : async(List) { - if (n = 0) - List.null(); - else { - let a = Request(n); - let tl = await waitN(n-1); - List.cons(await(a),tl); + public type List = ?(Int,List); + + public shared func RPR<@>(n:Nat) : async<@> List { + if (n == 0) null + else { + let a = Request<@>(n); + let tl = await RPR<@>(n-1); // recurse + ?(await a,tl) + } }; -}; ``` ### Deadlock Prevention: -(These need fixing but are all correctly coded in [illegal-await.mo](../test/fail/illegal-await.mo) +(These examples are all coded in [illegal-await.mo](../test/fail/illegal-await.mo) #### Immediate deadlock ``` -let t:asyncU = async{ await t;}; // bad await since t : AsyncU U + let t : async () = async { await t}; ``` +is rejected because, once annotated: -Ruled out by index scoping (`X != T`, any `T`) +``` + let t:async<@>U = async{ await t;} <@>; // bad await since t : Async<@>U U +``` + +Ruled out by index scoping (`X != @`, any `@`) #### Indirect deadlock ``` -async { - let a1 = async{ await a2; }; // bad await since a1 : Async() () - let a2 = async{ await a1; }; // bad await since a2 : Async() () - await(a1); -}; + async { + let a1 : async () = async { await a2; }; // illegal await since a1 : Async() () + let a2 : async () = async { await a1; }; // illegal await since a2 : Async() () + }; ``` -Ruled out by index scoping (`X != Y,Z`, any `Y,Z`) +is rejected because, once annotated: + +``` + async { + let a1 : async = async { await a2; }; // bad await since a1 : Async() () + let a2 : async = async { await a1; }; // bad await since a2 : Async() () + }<@> +``` + +since `X != Y,Z`, any `Y,Z`. ### Imperative deadlock The informal example: + ``` -shared func f() : async () { - var x : async Nat = async 0; - x := async { - await x - }; -} + async { + var x = async { 0 }; + x := (async { + await x // illegal: await _ : asyncT -> T (not async T -> T) (any T)) + }); + } ``` -is rejected by this system: +that attempts to tie an imperative knot, is rejected by this system. -Explicitly, the shared function and nested async would have distinct indices,so the await for type `asyncNat` on `x` (of type asyncNat (with the outer parameter) would actually be illegal: +Explicitly, the outer and nested async would have distinct parameters `` and ``, so the await for type `asyncNat` on `x` (of type asyncNat (with the outer parameter) would actually be illegal: ``` -shared func f() : async () { +async { var x : async Nat = async<_> 0 ; x := async{ await x // illegal: await _ : asyncT -> T (not async T -> T) (any T) } ; -} +}<@> ``` +Note that simply renaming `S` to `R` would not circumvent the error.) + ## Sugar Principle: Desugaring should be: @@ -286,15 +319,11 @@ Principle: Desugaring should be: * avoidable (by supplying explicit binders and instantations). -*UPDATE*: The scheme below selectively adds a `@`-parameter to a (sugared) function with 0 or 1 type parameters and an omitted return index. -I now think it might be better to just always add to `@` to non-`@` declaring type parameters when the return type is `async<@> U`, regardless of the arity, n, of the original type parameters. We can then just insert @ at the correct position in a call with n-1 type arguments by inspecting the index of the async return type. Pretty printing can detect and elide the parameter in a slight generalization of what I do now. - - ### Basic idea: Prelude: -Defines default scope @ = Any (non-awaitable in any async context) and instantiation: +Defines default scope `@ = Any` (non-awaitable in any async context) and instantiation: ``` type @ = Any @@ -304,61 +333,114 @@ type @ = Any Parsing: -* inserts `<@>` type instantiations and binders for missing `async` binders and instantiations (in types and terms) and `async` binders (in terms) -* adds missing `<@>` bindings to async returning functions with absent quantifiers (note we distinguish missing type parameters from empty parameters `<>`) +* inserts `<@>` type binders for missing `async` binders and instantiations (in types and terms) and `async` binders (in terms); +* adds missing `<@>` bindings to async returning functions with missing async indices. Elaboration: -* Elaboration ensures `@` is bound to appropriate constructor, shadowing any previous `@`-binding to ensure structured scoping. -* Elaboration adds missing unary instantiations to function applications that require them, guided by the synthesized function type. - -syntactic sugar (during parse, applied bottom up as we construct types and terms) +* Elaboration ensures `@` is bound to an appropriate constructor, shadowing any previous `@`-binding to ensure lexical scoping. +* Elaboration adds missing scope instantiations to function applications that require them, guided by the synthesized function type. +Syntactic sugar (during parse, applied bottom up as we construct types and terms) ``` -async T := async<@> T -T1 -> async<@> T2 := <@>T1 -> async<@> T1 +<...>T1 -> async T2 := (@ not in ...) + <@,...>T1 -> async T1 -func f() : async<@> T = e := -func<@>f() : async<@> T = e +func f<...>() : async T = e := (@ not in ...) + func f<@,...> f() : async T = e -func f() : async<@> T { e } := -func<@>f() : async<@> T = async<@> e <@> +func f<...>() : async T { e } := + func f<@,...>() : async T = async<@> e <@> -func f() : async<@> T { e } := -funcf() : async<@> T = async e <@> +func f<...>() : async T { e } := + func f<...>() : async T = async e -f() : async<@> T {e} := f<@>(): async<@> T = async <@> e <@> -f() : async<@> T := e = f<@>(): async<@> T = e + (binds inner scope as X, not @, to pun X in e) -async e := async<@> e <@> +func f<...>() : async T { e } := (U <> X) + func f<...>() : async T = async <@> e + +async e := + async<@> e <@> ``` -static sugar (during elaboration) +Syntax elaboration (applied during type checking) ``` -T1 -> async<@> T2 ~~> T1[X/@] -> async T[X/@] -T1 -> async T2 ~~> LHS (|tbs| <> 1) +Types: + +@* ~~> + @* + + (* interprets @ at its current binding (which may be some X) *) + +(async t)* ~~> + async<@*> t* + +(async t1)* + ~~> async t2* + +<...>T1 -> async T2 ~~> (* syntax sugaring ensures @ bound in ... *) + <...>T1* -> async<@*> T2* + +<...,X,...>T1 -> async T2 ~~> + <...*,X,...*>T1*[X/@] -> async T2*[X/@], (* rebind @ to X *) +<...>T1 -> async T2 ~~> (* U <> X in ... *) + <...*>T1* -> async T2* + +Terms: async e ~~> async e[X/@] -f e = f<@>e when f: sort (typ,...) ~~> async t -funcf() : async<@> T = async e <@> ~~> -funcf() : async<@> T[X/@] = (async e <@>) [X/@] -```` +f e ~~> + f e when f : <...,Xi,...> T1 ~~> async T1 -(basically, we rebind `@` to the current scope during elaboration, so references inserted during parsing elaborate to the nearest appropiate binding, and default missing scope instantiations to the current meaning of `@`). + (note inference can infer a missing scope parameter at any position, not just position 0) -Note that in a function type or definition with n>1 type parameters, `@` either shadows one of those eponymous type parameters or it retains its outer meaning. In the latter case (outer binding), we might either warn appropriately or reject as ambiguous, requiring the user to -give the missing instantiation of the `async T` return type. +func<...>f() : async T = e ~~> (* syntax sugaring ensures @ bound in ... *) + func<...*>f() : (async T)* = e* -(The implementation is currently silent and defaults `@` to the enclosing interpretation.) +func<...,X,...>f() : async T = e (* rebind @ to X *) + func<...*,X,...*>f() : (async T)*[X/@] = e*[X/@] +func<...>f() : async T = e ~~> (* U <> X in ... *) + func<...*>f() : async T* = e* +``` +Basically, during elaboration, we rebind `@` to the current scope +identifier (aliasing `@` with some type parameter `X` if necessary) so +that: + * references inserted during parsing elaborate to the nearest appropiate binding + * missing scope instantiations default to the current binding of `@`. + +Note that in a function type or definition with n>1 type parameters, +`@` either shadows one of those eponymous type parameters or it +retains its outer meaning. In the latter case (outer binding), we +might either warn appropriately or reject as ambiguous, requiring the +user to give the missing instantiation of the `async T` return type. + +(The implementation is currently silent and defaults `@` to the enclosing interpretation.) ### Sugaring types (for pretty printing) -During pretty printing of types, we suppress a unary type binding in a function type if it only occurs as an `async` type instantiation at DeBruijn level 0, in which case we elide all those `async` type instantiations too. Binders with async instantiations at DeBruijn levels higher than 0 must be shown to avoid ambiguity. +During pretty printing of types, we suppress a unary type binding in a +function type if it only occurs as an `async` type instantiation at +DeBruijn level 0, in which case we elide all those `async` type +instantiations too. + +Binders with async instantiations at DeBruijn levels other than 0 must +be shown to avoid ambiguity, in particular so that the user knows +which parameter is the scope parameter if explicit (not implicit) +instantiation is desired. + +### Refinements + +Since users may find it odd that we can instantiate the index at any +type, it might be better to define "type @ = Non" and always bound +index-parameters by `Non`. Then the top-level choice really is unique +since `Non` (and any `Non`-bounded type parameter) ares the only type +bounded by `Non` and thus suitable for uses as index instantiations. diff --git a/src/mo_def/arrange.ml b/src/mo_def/arrange.ml index 037f1c0a043..bdc2c073892 100644 --- a/src/mo_def/arrange.ml +++ b/src/mo_def/arrange.ml @@ -151,9 +151,13 @@ and typ t = match t.it with | VariantT cts -> "VariantT" $$ List.map typ_tag cts | TupT ts -> "TupT" $$ List.map typ ts | FuncT (s, tbs, at, rt) -> "FuncT" $$ [func_sort s] @ List.map typ_bind tbs @ [ typ at; typ rt] - | AsyncT (t1, t2) -> "AsyncT" $$ [typ t1; typ t2] + | AsyncT (t1_opt, t2) -> "AsyncT" $$ [typ_opt t1_opt; typ t2] | ParT t -> "ParT" $$ [typ t] +and typ_opt t_opt = match t_opt with + Some t -> typ t + | None -> Atom "?" + and dec d = match d.it with | ExpD e -> "ExpD" $$ [exp e ] | LetD (p, e) -> "LetD" $$ [pat p; exp e] diff --git a/src/mo_def/syntax.ml b/src/mo_def/syntax.ml index 2ab73af711c..567786e9b1d 100644 --- a/src/mo_def/syntax.ml +++ b/src/mo_def/syntax.ml @@ -40,7 +40,7 @@ and typ' = | VariantT of typ_tag list (* variant *) | TupT of typ list (* tuple *) | FuncT of func_sort * typ_bind list * typ * typ (* function *) - | AsyncT of typ * typ (* future *) + | AsyncT of typ option * typ (* future *) | ParT of typ (* parentheses, used to control function arity only *) and typ_field = typ_field' Source.phrase @@ -251,8 +251,8 @@ let scope_bind() = bound = PrimT "Any" @! no_region } @= no_region -let pun_bind typ_bind = - { var = typ_bind.it.var.it @@ no_region; +let pun_id id = + { var = id.it @@ no_region; bound = PrimT "Any" @! no_region } @= no_region @@ -266,30 +266,34 @@ let rec is_scope_typ t = | ParT t -> is_scope_typ t | _ -> false -let funcT(sort, tbs_opt, t1, t2) = - match tbs_opt with - | None -> - (match t2.it with - | AsyncT (t21, _) when is_scope_typ t21 -> - FuncT(sort, [scope_bind ()], t1, t2) - | _ -> - FuncT(sort, [], t1, t2)) - | Some tbs -> FuncT(sort, tbs, t1, t2) - -let funcE (f, s, tbs_opt, p, t_opt, e) = - let tbs = match tbs_opt with - | None -> [] - | Some tbs -> tbs - in +let rec as_idT t = + match t.it with + | PathT (p, []) -> + (match p.it with + | IdH id -> + Some id + | _ -> None) + | ParT t -> as_idT t + | _ -> None + + +let ensure_scope_bind tbs = + if List.exists (fun tb -> tb.it.var.it = scope_id) tbs + then tbs + else scope_bind()::tbs + +let funcT(sort, tbs, t1, t2) = + match t2.it with + | AsyncT (None, _) -> + FuncT(sort, ensure_scope_bind tbs, t1, t2) + | _ -> + FuncT(sort, tbs, t1, t2) + +let funcE (f, s, tbs, p, t_opt, e) = match t_opt with | None -> FuncE(f, s, tbs, p, t_opt, e) | Some t -> (match t.it with - | AsyncT (t1, _) when is_scope_typ t1 -> - let tbs' = - if List.exists (fun tb -> tb.it.var.it = scope_id) tbs - then tbs - else scope_bind()::tbs - in - FuncE(f, s, tbs', p, t_opt, e) + | AsyncT (None, t22) -> + FuncE(f, s, ensure_scope_bind tbs, p, t_opt, e) | _ -> FuncE(f, s, tbs, p, t_opt, e)) diff --git a/src/mo_frontend/parser.mly b/src/mo_frontend/parser.mly index 85a4d94a914..1bdc8a3312a 100644 --- a/src/mo_frontend/parser.mly +++ b/src/mo_frontend/parser.mly @@ -253,7 +253,7 @@ typ_pre : typ : | t=typ_pre { t } - | s=func_sort_opt tps=typ_params_opt t1=typ_un ARROW t2=typ + | s=func_sort_opt tps=typ_params t1=typ_un ARROW t2=typ { funcT(s, tps, t1, t2) @! at $sloc } typ_item : @@ -267,14 +267,10 @@ typ_args : | (* empty *) { [] } | LT ts=seplist(typ_bind, COMMA) GT { ts } -%inline typ_params_opt : - | (* empty *) { None } - | LT ts=seplist(typ_bind, COMMA) GT { Some ts } - typ_field : | mut=var_opt x=id COLON t=typ { {id = x; typ = t; mut} @@ at $sloc } - | x=id tps=typ_params_opt t1=typ_nullary t2=return_typ + | x=id tps=typ_params t1=typ_nullary t2=return_typ { let t = funcT(Type.Local @@ no_region, tps, t1, t2) @! span x.at t2.at in {id = x; typ = t; mut = Const @@ no_region} @@ at $sloc } @@ -293,11 +289,15 @@ typ_bind : | LT tb=typ_bind GT { tb } -%inline scope_inst_opt : +%inline scope_inst : | LT t=typ GT { t } + +%inline scope_inst_opt : + | t=scope_inst + { Some t } | (* empty *) - { scope_typ () } + { None } (* Expressions *) @@ -451,7 +451,7 @@ exp_nondec(B) : { RetE(e) @? at $sloc } | ASYNC e=exp(bl) { AsyncE(scope_bind(), e, scope_typ()) @? at $sloc } - | ASYNC tb = scope_bind e=exp_nullary(bl) t=scope_inst_opt + | ASYNC tb = scope_bind e=exp_nullary(bl) t=scope_inst { AsyncE(tb, e, t) @? at $sloc } | AWAIT e=exp(bl) { AwaitE(e) @? at $sloc } @@ -630,7 +630,7 @@ dec_nonvar : if s.it = Type.Actor then List.map share_expfield efs else efs in let_or_exp named x (ObjE(s, efs')) (at $sloc) } | s=func_sort_opt FUNC xf=id_opt - tps=typ_params_opt p=pat_param t=return_typ? fb=func_body + tps=typ_params p=pat_param t=return_typ? fb=func_body { (* This is a hack to support local func declarations that return a computed async. These should be defined using RHS syntax EQ e to avoid the implicit AsyncE introduction around bodies declared as blocks *) @@ -638,10 +638,13 @@ dec_nonvar : | (false, e) -> e (* body declared as EQ e *) | (true, e) -> (* body declared as immediate block *) match t with - | Some {it = AsyncT _; _} -> - (match tps with - | Some (tb::_) -> AsyncE(pun_bind tb, e, scope_typ()) @? e.at - | _ -> AsyncE(scope_bind(), e, scope_typ()) @? e.at) + | Some {it = AsyncT (None,_); _} -> + AsyncE(scope_bind(), e, scope_typ()) @? e.at + | Some {it = AsyncT (Some typ,_); _} -> + (match as_idT typ with + | Some id -> + AsyncE(pun_id id, e, typ) @? e.at + | _ -> AsyncE(scope_bind(), e, typ) @? e.at) | _ -> e in let named, x = xf "func" $sloc in diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 323c7fbbefa..119c12a9fbd 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -244,7 +244,8 @@ let as_domT t = let as_codomT sort t = match sort, t.Source.it with - | T.Shared _, AsyncT (t1, t2) -> T.Promises t1 , as_domT t2 + | T.Shared _, AsyncT (None, t2) -> T.Promises (scope_typ no_region) , as_domT t2 + | T.Shared _, AsyncT (Some t1, t2) -> T.Promises t1 , as_domT t2 | _ -> T.Returns, as_domT t let check_shared_return env at sort c ts = @@ -257,7 +258,8 @@ let check_shared_return env at sort c ts = let rec infer_scope env cs cod = match cod.it with - | AsyncT (typ,_) -> + | AsyncT (typ_opt,_) -> + let typ = match typ_opt with Some typ -> typ | None -> scope_typ no_region in let t = check_typ env typ in (match T.close cs t with | T.Var (_, n) -> @@ -265,7 +267,7 @@ let rec infer_scope env cs cod = | _ -> env) | _ -> env -and check_typ env typ : T.typ = +and check_typ env (typ:typ) : T.typ = let t = check_typ' env typ in typ.note <- t; t @@ -330,7 +332,10 @@ and check_typ' env typ : T.typ = (List.map (fun (tag : typ_tag) -> tag.it.tag) tags); let fs = List.map (check_typ_tag env) tags in T.Variant (List.sort T.compare_field fs) - | AsyncT (typ0, typ) -> + | AsyncT (typ0_opt, typ) -> + let typ0 = match typ0_opt with + | None -> scope_typ no_region + | Some typ0 -> typ0 in let t0 = check_typ env typ0 in let t = check_typ env typ in if not env.pre && not (T.shared t) then @@ -997,7 +1002,8 @@ and infer_exp'' env exp : T.typ = (try let (t2, t3) = T.as_async_sub t0 t1 in if not (T.eq t0 t2) then - error env exp.at "ill-scoped await"; + error env exp.at "ill-scoped await: expecting index %s, found index %s" + (T.string_of_typ t0) (T.string_of_typ t2); t3 with Invalid_argument _ -> error env exp1.at "expected async type, but expression has type\n %s" @@ -1067,8 +1073,9 @@ and check_exp' env0 t exp : T.typ = (T.string_of_typ_expand t1) (T.string_of_typ_expand t1'); let c, tb, ce, cs = check_typ_bind env tb in + let ce_scope = T.Env.add "@" c ce in (* pun scope identifier @ with c *) let env' = - {(adjoin_typs env ce cs) with labs = T.Env.empty; rets = Some t'; async = Some c} in + {(adjoin_typs env ce_scope cs) with labs = T.Env.empty; rets = Some t'; async = Some c} in check_exp env' t' exp1; t | BlockE decs, _ -> diff --git a/test/fail/ok/illegal-await.tc.ok b/test/fail/ok/illegal-await.tc.ok index 3d5e328ee7b..165028adeda 100644 --- a/test/fail/ok/illegal-await.tc.ok +++ b/test/fail/ok/illegal-await.tc.ok @@ -1,5 +1,5 @@ -illegal-await.mo:3.30-3.37: type error, ill-scoped await -illegal-await.mo:12.32-12.40: type error, ill-scoped await -illegal-await.mo:13.32-13.40: type error, ill-scoped await -illegal-await.mo:24.7-24.14: type error, ill-scoped await -illegal-await.mo:33.5-33.12: type error, ill-scoped await +illegal-await.mo:3.30-3.37: type error, ill-scoped await: expecting index @/2, found index @ +illegal-await.mo:12.32-12.40: type error, ill-scoped await: expecting index @/4, found index @/3 +illegal-await.mo:13.32-13.40: type error, ill-scoped await: expecting index @/5, found index @/3 +illegal-await.mo:24.7-24.14: type error, ill-scoped await: expecting index @/8, found index @/6 +illegal-await.mo:33.5-33.12: type error, ill-scoped await: expecting index @/9, found index @/1 diff --git a/test/run-drun/await-sugar.mo b/test/run-drun/await-sugar.mo new file mode 100644 index 00000000000..e7e29a94aed --- /dev/null +++ b/test/run-drun/await-sugar.mo @@ -0,0 +1,97 @@ +actor A { + +public func f0 () : async () {}; + +public func test0 () : async () { await f0 ();}; + +public func f1 () : async<@> () {}; + +public func test1 () : async () { + // f1 not parametric, can call f1(), but can't await f1(); + ignore f1(); +}; + +public func f2<@>() : async<@> () {}; + +public func test2(): async () { + await f2(); + await f2<@>(); +}; + +public func f2b<@>() : async () {}; + +public func test2b() : async () { + await f2b(); + await f2b<@>(); +}; + + +public func f3() : async () {}; + +public func test3 () : async () { + await f3(); // scope passed as implicit first argument + await f3<@,Int>(); // scope passed as explicit first argument +}; + +public func f4<@,B<:Int>() : async<@> () {}; // explict scope parameter 1 + +public func test4() : async () { + await f4(); // scope passed as implicit first argument + await f4<@,Int>(); // scope passed as exlicit first argument +}; + + +public func f5() : async<@> () {}; // explict scope parameter 2 + +public func test5() : async () { + await f5(); // scope passed as implicit second argument + await f5(); +} +; + + +public func f6() : async () {}; // explict scope parameter 2, implicit index + +public func test6() : async () { + await f6(); // scope passed as implicit second argument + await f6(); +} +; + + +public func f7(n:Int) : async() { + if (n == 0) () + else + switch (n % 3) { + case 0 (await f7(n-1)); + case 1 (await f7(n-1)); + case 2 (await f7<@,A>(n-1)); + case _ (); + }; +}; + +public func test7 () : async () { + await f7(1); // scope passed as implicit second argument + await f7<@,Int>(1); +}; + +public func test() : async () { + await test1(); + await test2(); + await test2b(); + await test3(); + await test4(); + await test5(); + await test6(); + await test7(); +}; + +}; + +A.test() //OR-CALL ingress c1 0x4449444C0000 +//SKIP run-drun +//SKIP comp + + + + diff --git a/test/run-drun/general_await.mo b/test/run-drun/general_await.mo index 76685564443..8db6ba4f91b 100644 --- a/test/run-drun/general_await.mo +++ b/test/run-drun/general_await.mo @@ -36,8 +36,8 @@ actor Await { // Dynamic parallel waiting (with results) public shared func DPR<@>() : async<@>[Int] { - func f(i:Nat) : async Int = Request<@>(i); - let as = Array_tabulate(10, func i {f i}); + func f(i:Nat) : async<@> Int = Request<@>(i); + let as = Array_tabulate(10, f); let res = Array_init(as.len(),-1); for (i in as.keys()) { // res[i] := (await as[i]); <-- compiler bug (generates incorrect code) diff --git a/test/run-drun/general_await_implicit.mo b/test/run-drun/general_await_implicit.mo index b59fd8ac541..054a4a97c85 100644 --- a/test/run-drun/general_await_implicit.mo +++ b/test/run-drun/general_await_implicit.mo @@ -36,8 +36,8 @@ actor Await { // Dynamic parallel waiting (with results) public shared func DPR() : async [Int] { - func f(i:Nat) : async Int = Request(i); - let as = Array_tabulate(10, func i { f i }); + func f(i:Nat) : async<@> Int = Request(i); + let as = Array_tabulate(10, f); let res = Array_init(as.len(),-1); for (i in as.keys()) { // res[i] := (await as[i]); <-- compiler bug (generates incorrect code) diff --git a/test/run-stub/general_await.mo b/test/run-stub/general_await.mo index 74f77a7b926..05901741cb0 100644 --- a/test/run-stub/general_await.mo +++ b/test/run-stub/general_await.mo @@ -1,7 +1,7 @@ actor Await { let N = 4; - + public shared func Ack<@>() : async<@> (){ debugPrint "Ack" }; From d5b9d89220e0cec4b5980cee080538d2df3794ac Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Mon, 9 Dec 2019 18:43:06 +0000 Subject: [PATCH 0774/1176] merge --- src/codegen/compile.ml | 1 - src/ir_def/check_ir.ml | 6 ------ test/fail/ok/asyncret2.tc.ok | 2 +- test/fail/ok/objpat-infer.tc.ok | 2 +- 4 files changed, 2 insertions(+), 9 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 96361bb6352..e7a93a86459 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -4593,7 +4593,6 @@ module FuncDec = struct mk_body env ae1 ^^ message_cleanup env sort )) ->>>>>>> master (* Compile a closed function declaration (captures no local variables) *) let closed pre_env sort control name args mk_body ret_tys at = diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index a6a6b723a1a..7ff86b93570 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -353,14 +353,11 @@ let rec check_exp env (exp:Ir.exp) : unit = | CPSAwait, [a; kr] -> check (not (env.flavor.has_await)) "CPSAwait await flavor"; check (env.flavor.has_async_typ) "CPSAwait in post-async flavor"; - check_exp env a; - check_exp env kr (* TODO: We can check more here, can we *) | CPSAsync t, [exp] -> check (not (env.flavor.has_await)) "CPSAsync await flavor"; check (env.flavor.has_async_typ) "CPSAsync in post-async flavor"; check_typ env t; - check_exp env exp; (* TODO: We can check more here, can we *) | ICReplyPrim ts, [exp1] -> check (not (env.flavor.has_async_typ)) "ICReplyPrim in async flavor"; @@ -373,12 +370,9 @@ let rec check_exp env (exp:Ir.exp) : unit = typ exp1 <: T.text; T.Non <: t | ICCallPrim, [exp1; exp2; k; r] -> - check_exp env k; - check_exp env r; let t1 = T.promote (typ exp1) in begin match t1 with | T.Func (sort, T.Replies, _ (*TBR*), arg_tys, ret_tys) -> - check_exp env exp2; let t_arg = T.seq arg_tys in typ exp2 <: t_arg; check_concrete env exp.at t_arg; diff --git a/test/fail/ok/asyncret2.tc.ok b/test/fail/ok/asyncret2.tc.ok index e8b9e5ae132..9b0fbaddcdc 100644 --- a/test/fail/ok/asyncret2.tc.ok +++ b/test/fail/ok/asyncret2.tc.ok @@ -1,4 +1,4 @@ asyncret2.mo:1.54-1.57: type error, expression of type - async Int + async<@> Int cannot produce expected type Int diff --git a/test/fail/ok/objpat-infer.tc.ok b/test/fail/ok/objpat-infer.tc.ok index bea0e0d5256..85859ee47d4 100644 --- a/test/fail/ok/objpat-infer.tc.ok +++ b/test/fail/ok/objpat-infer.tc.ok @@ -5,7 +5,7 @@ objpat-infer.mo:21.13-21.21: type error, expression of type cannot produce expected type {} objpat-infer.mo:24.13-24.14: type error, expression of type - actor {bar : shared {} -> async Nat} + actor {bar : shared {} -> async<@> Nat} cannot produce expected type {} objpat-infer.mo:27.13-27.15: type error, expression of type From c3145633d54054243787c00b52b8b27b69bc1dc1 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Mon, 9 Dec 2019 22:19:50 +0000 Subject: [PATCH 0775/1176] merge with parent; fixups --- test/fail/ok/objpat-infer.tc.ok | 2 +- test/run-drun/await-sugar.mo | 3 +- test/run-drun/general_await.mo | 11 +++-- test/run-drun/general_await_implicit.mo | 10 ++--- test/run-drun/ok/await-sugar.ic-stub-run.ok | 6 +++ test/run-drun/ok/general_await.run-ir.ok | 44 +++++++++---------- test/run-drun/ok/general_await.run-low.ok | 44 +++++++++---------- .../ok/general_await_implicit.run-ir.ok | 44 +++++++++---------- .../ok/general_await_implicit.run-low.ok | 44 +++++++++---------- 9 files changed, 105 insertions(+), 103 deletions(-) create mode 100644 test/run-drun/ok/await-sugar.ic-stub-run.ok diff --git a/test/fail/ok/objpat-infer.tc.ok b/test/fail/ok/objpat-infer.tc.ok index 85859ee47d4..bea0e0d5256 100644 --- a/test/fail/ok/objpat-infer.tc.ok +++ b/test/fail/ok/objpat-infer.tc.ok @@ -5,7 +5,7 @@ objpat-infer.mo:21.13-21.21: type error, expression of type cannot produce expected type {} objpat-infer.mo:24.13-24.14: type error, expression of type - actor {bar : shared {} -> async<@> Nat} + actor {bar : shared {} -> async Nat} cannot produce expected type {} objpat-infer.mo:27.13-27.15: type error, expression of type diff --git a/test/run-drun/await-sugar.mo b/test/run-drun/await-sugar.mo index e7e29a94aed..68668f9d13b 100644 --- a/test/run-drun/await-sugar.mo +++ b/test/run-drun/await-sugar.mo @@ -88,8 +88,7 @@ public func test() : async () { }; -A.test() //OR-CALL ingress c1 0x4449444C0000 -//SKIP run-drun +A.test() //OR-CALL ingress test 0x4449444C0000 //SKIP comp diff --git a/test/run-drun/general_await.mo b/test/run-drun/general_await.mo index 8db6ba4f91b..3dfddee9877 100644 --- a/test/run-drun/general_await.mo +++ b/test/run-drun/general_await.mo @@ -5,7 +5,8 @@ actor Await { }; public shared func Request<@>(i : Int) : async<@> Int { - debugPrint("Request(" # debug_show i # ")"); +// debugPrint("Request(" # debug_show i # ")"); <-- compiler bug + debugPrintInt(i); return i; }; @@ -40,9 +41,7 @@ actor Await { let as = Array_tabulate(10, f); let res = Array_init(as.len(),-1); for (i in as.keys()) { -// res[i] := (await as[i]); <-- compiler bug (generates incorrect code) - let a = await as[i]; - res[i] := a; + res[i] := (await as[i]); }; Array_tabulate(as.len(),func i = res[i]) }; @@ -103,7 +102,7 @@ actor Await { } }; -Await.Test<@>(); +Await.Test<@>(); //OR-CALL ingress Test 0x4449444C0000 + -//SKIP run-drun //SKIP comp diff --git a/test/run-drun/general_await_implicit.mo b/test/run-drun/general_await_implicit.mo index 054a4a97c85..41c36537521 100644 --- a/test/run-drun/general_await_implicit.mo +++ b/test/run-drun/general_await_implicit.mo @@ -5,7 +5,8 @@ actor Await { }; public shared func Request(i : Int) : async Int { - debugPrint("Request(" # debug_show i # ")"); +// debugPrint("Request(" # debug_show i # ")"); <-- compiler bug + debugPrintInt(i); return i }; @@ -40,9 +41,7 @@ actor Await { let as = Array_tabulate(10, f); let res = Array_init(as.len(),-1); for (i in as.keys()) { -// res[i] := (await as[i]); <-- compiler bug (generates incorrect code) - let a = await as[i]; - res[i] := a; + res[i] := await as[i]; }; Array_tabulate(as.len(),func i = res[i]) }; @@ -103,7 +102,6 @@ actor Await { } }; -Await.Test(); +Await.Test(); //OR-CALL ingress Test 0x4449444C0000 -//SKIP run-drun //SKIP comp diff --git a/test/run-drun/ok/await-sugar.ic-stub-run.ok b/test/run-drun/ok/await-sugar.ic-stub-run.ok new file mode 100644 index 00000000000..3317e0c3469 --- /dev/null +++ b/test/run-drun/ok/await-sugar.ic-stub-run.ok @@ -0,0 +1,6 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ update test(0x4449444c0000) +← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/general_await.run-ir.ok b/test/run-drun/ok/general_await.run-ir.ok index 3e8ef58ba9f..d095037cfec 100644 --- a/test/run-drun/ok/general_await.run-ir.ok +++ b/test/run-drun/ok/general_await.run-ir.ok @@ -1,7 +1,7 @@ Ack Ack -Request(+1) -Request(+2) ++1 ++2 Ack Ack Ack @@ -12,16 +12,16 @@ Ack Ack Ack Ack -Request(0) -Request(+1) -Request(+2) -Request(+3) -Request(+4) -Request(+5) -Request(+6) -Request(+7) -Request(+8) -Request(+9) +0 ++1 ++2 ++3 ++4 ++5 ++6 ++7 ++8 ++9 Ack Ack Ack @@ -32,13 +32,13 @@ Ack Ack Ack Ack -Request(+10) -Request(+9) -Request(+8) -Request(+7) -Request(+6) -Request(+5) -Request(+4) -Request(+3) -Request(+2) -Request(+1) ++10 ++9 ++8 ++7 ++6 ++5 ++4 ++3 ++2 ++1 diff --git a/test/run-drun/ok/general_await.run-low.ok b/test/run-drun/ok/general_await.run-low.ok index 3e8ef58ba9f..d095037cfec 100644 --- a/test/run-drun/ok/general_await.run-low.ok +++ b/test/run-drun/ok/general_await.run-low.ok @@ -1,7 +1,7 @@ Ack Ack -Request(+1) -Request(+2) ++1 ++2 Ack Ack Ack @@ -12,16 +12,16 @@ Ack Ack Ack Ack -Request(0) -Request(+1) -Request(+2) -Request(+3) -Request(+4) -Request(+5) -Request(+6) -Request(+7) -Request(+8) -Request(+9) +0 ++1 ++2 ++3 ++4 ++5 ++6 ++7 ++8 ++9 Ack Ack Ack @@ -32,13 +32,13 @@ Ack Ack Ack Ack -Request(+10) -Request(+9) -Request(+8) -Request(+7) -Request(+6) -Request(+5) -Request(+4) -Request(+3) -Request(+2) -Request(+1) ++10 ++9 ++8 ++7 ++6 ++5 ++4 ++3 ++2 ++1 diff --git a/test/run-drun/ok/general_await_implicit.run-ir.ok b/test/run-drun/ok/general_await_implicit.run-ir.ok index 3e8ef58ba9f..d095037cfec 100644 --- a/test/run-drun/ok/general_await_implicit.run-ir.ok +++ b/test/run-drun/ok/general_await_implicit.run-ir.ok @@ -1,7 +1,7 @@ Ack Ack -Request(+1) -Request(+2) ++1 ++2 Ack Ack Ack @@ -12,16 +12,16 @@ Ack Ack Ack Ack -Request(0) -Request(+1) -Request(+2) -Request(+3) -Request(+4) -Request(+5) -Request(+6) -Request(+7) -Request(+8) -Request(+9) +0 ++1 ++2 ++3 ++4 ++5 ++6 ++7 ++8 ++9 Ack Ack Ack @@ -32,13 +32,13 @@ Ack Ack Ack Ack -Request(+10) -Request(+9) -Request(+8) -Request(+7) -Request(+6) -Request(+5) -Request(+4) -Request(+3) -Request(+2) -Request(+1) ++10 ++9 ++8 ++7 ++6 ++5 ++4 ++3 ++2 ++1 diff --git a/test/run-drun/ok/general_await_implicit.run-low.ok b/test/run-drun/ok/general_await_implicit.run-low.ok index 3e8ef58ba9f..d095037cfec 100644 --- a/test/run-drun/ok/general_await_implicit.run-low.ok +++ b/test/run-drun/ok/general_await_implicit.run-low.ok @@ -1,7 +1,7 @@ Ack Ack -Request(+1) -Request(+2) ++1 ++2 Ack Ack Ack @@ -12,16 +12,16 @@ Ack Ack Ack Ack -Request(0) -Request(+1) -Request(+2) -Request(+3) -Request(+4) -Request(+5) -Request(+6) -Request(+7) -Request(+8) -Request(+9) +0 ++1 ++2 ++3 ++4 ++5 ++6 ++7 ++8 ++9 Ack Ack Ack @@ -32,13 +32,13 @@ Ack Ack Ack Ack -Request(+10) -Request(+9) -Request(+8) -Request(+7) -Request(+6) -Request(+5) -Request(+4) -Request(+3) -Request(+2) -Request(+1) ++10 ++9 ++8 ++7 ++6 ++5 ++4 ++3 ++2 ++1 From 1569e16b53a435f7cfe71e32333199748a477a87 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Mon, 9 Dec 2019 22:31:24 +0000 Subject: [PATCH 0776/1176] add tests results --- test/run-drun/ok/general_await.ic-stub-run.ok | 50 +++++++++++++++++++ test/run-drun/ok/general_await.run.ok | 44 ++++++++++++++++ .../ok/general_await_implicit.ic-stub-run.ok | 50 +++++++++++++++++++ .../run-drun/ok/general_await_implicit.run.ok | 44 ++++++++++++++++ 4 files changed, 188 insertions(+) create mode 100644 test/run-drun/ok/general_await.ic-stub-run.ok create mode 100644 test/run-drun/ok/general_await.run.ok create mode 100644 test/run-drun/ok/general_await_implicit.ic-stub-run.ok create mode 100644 test/run-drun/ok/general_await_implicit.run.ok diff --git a/test/run-drun/ok/general_await.ic-stub-run.ok b/test/run-drun/ok/general_await.ic-stub-run.ok new file mode 100644 index 00000000000..270da561546 --- /dev/null +++ b/test/run-drun/ok/general_await.ic-stub-run.ok @@ -0,0 +1,50 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ update Test(0x4449444c0000) +debug.print: Ack +debug.print: Ack +debug.print: +1 +debug.print: +2 +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: 0 +debug.print: +1 +debug.print: +2 +debug.print: +3 +debug.print: +4 +debug.print: +5 +debug.print: +6 +debug.print: +7 +debug.print: +8 +debug.print: +9 +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: +10 +debug.print: +9 +debug.print: +8 +debug.print: +7 +debug.print: +6 +debug.print: +5 +debug.print: +4 +debug.print: +3 +debug.print: +2 +debug.print: +1 +← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/general_await.run.ok b/test/run-drun/ok/general_await.run.ok new file mode 100644 index 00000000000..d095037cfec --- /dev/null +++ b/test/run-drun/ok/general_await.run.ok @@ -0,0 +1,44 @@ +Ack +Ack ++1 ++2 +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Ack +0 ++1 ++2 ++3 ++4 ++5 ++6 ++7 ++8 ++9 +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Ack ++10 ++9 ++8 ++7 ++6 ++5 ++4 ++3 ++2 ++1 diff --git a/test/run-drun/ok/general_await_implicit.ic-stub-run.ok b/test/run-drun/ok/general_await_implicit.ic-stub-run.ok new file mode 100644 index 00000000000..270da561546 --- /dev/null +++ b/test/run-drun/ok/general_await_implicit.ic-stub-run.ok @@ -0,0 +1,50 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ update Test(0x4449444c0000) +debug.print: Ack +debug.print: Ack +debug.print: +1 +debug.print: +2 +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: 0 +debug.print: +1 +debug.print: +2 +debug.print: +3 +debug.print: +4 +debug.print: +5 +debug.print: +6 +debug.print: +7 +debug.print: +8 +debug.print: +9 +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: +10 +debug.print: +9 +debug.print: +8 +debug.print: +7 +debug.print: +6 +debug.print: +5 +debug.print: +4 +debug.print: +3 +debug.print: +2 +debug.print: +1 +← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/general_await_implicit.run.ok b/test/run-drun/ok/general_await_implicit.run.ok new file mode 100644 index 00000000000..d095037cfec --- /dev/null +++ b/test/run-drun/ok/general_await_implicit.run.ok @@ -0,0 +1,44 @@ +Ack +Ack ++1 ++2 +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Ack +0 ++1 ++2 ++3 ++4 ++5 ++6 ++7 ++8 ++9 +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Ack +Ack ++10 ++9 ++8 ++7 ++6 ++5 ++4 ++3 ++2 ++1 From 982c2a31ee971a022e38c6e4116145508d6576e9 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Mon, 9 Dec 2019 22:54:34 +0000 Subject: [PATCH 0777/1176] delete redundant tests --- test/run-stub/general_await.mo | 108 ----------------- test/run-stub/general_await_implicit.mo | 111 ------------------ test/run-stub/ok/general_await.ic-stub-run.ok | 26 ---- .../ok/general_await_implicit.ic-stub-run.ok | 26 ---- .../ok/scope-inference.ic-stub-run.ok | 4 - 5 files changed, 275 deletions(-) delete mode 100644 test/run-stub/general_await.mo delete mode 100644 test/run-stub/general_await_implicit.mo delete mode 100644 test/run-stub/ok/general_await.ic-stub-run.ok delete mode 100644 test/run-stub/ok/general_await_implicit.ic-stub-run.ok delete mode 100644 test/run-stub/ok/scope-inference.ic-stub-run.ok diff --git a/test/run-stub/general_await.mo b/test/run-stub/general_await.mo deleted file mode 100644 index 05901741cb0..00000000000 --- a/test/run-stub/general_await.mo +++ /dev/null @@ -1,108 +0,0 @@ -actor Await { - - let N = 4; - - public shared func Ack<@>() : async<@> (){ - debugPrint "Ack" - }; - - public shared func Request<@>(i : Int) : async<@> Int { - debugPrint("Request(" # debug_show i # ")"); - return i; - }; - - // Static parallel waiting: - - public shared func PA<@>() : async<@> () { - let a1 = Ack<@>(); - let a2 = Ack<@>(); - await a1; - await a2; - }; - - public shared func PR<@>() : async<@>(Int,Int) { - let a1 = Request<@>(1); - let a2 = Request<@>(2); - (await a1, await a2) - }; - - // Dynamic parallel waiting for acknowledgements - - public shared func DPA<@>() : async<@>() { - let as: [async()] = Array_tabulate(N, func (_) { Ack<@>(); }); - for (a in as.vals()) { - await a; - }; - }; - - // Dynamic parallel waiting (with results) - - public shared func DPR<@>() : async<@>[Int] { - func f<>(i:Nat) : async Int = Request<@>(i); - let as = Array_tabulate(N, f); - let res = Array_init(as.len(),-1); - for (i in as.keys()) { -// res[i] := (await as[i]); <-- compiler bug (generates incorrect code) - let a = await as[i]; - res[i] := a; - }; - Array_tabulate(as.len(),func i = res[i]) - }; - - // Recursive parallel waiting - - public shared func RPA<@>(n:Nat) : async<@>() { - if (n == 0) () - else { - let a = Ack<@>(); - await RPA<@>(n-1); // recurse - await a; - }; - }; - - // Recursive parallel waiting (with results) - - public type List = ?(Int,List); - - public shared func RPR<@>(n:Nat) : async<@> List { - if (n == 0) null - else { - let a = Request<@>(n); - let tl = await RPR<@>(n-1); // recurse - ?(await a,tl) - } - }; - - - public shared func Test<@>() : async<@>() { - - await PA<@>(); - - switch (await PR<@>()) { - case (1,2) (); - case _ (assert false); - }; - - await DPA<@>(); - - let rs = await DPR<@>(); - for (i in rs.keys()) { - assert rs[i] == i; - }; - - await RPA<@>(N); - - var l = await RPR<@>(N); - for (i in revrange(N, 1)) { - switch (l) { - case (?(h, t)) { - assert (h == i); - l := t; - }; - case null (assert false); - } - }; - } -}; - -//CALL ingress Test 0x4449444C0000 diff --git a/test/run-stub/general_await_implicit.mo b/test/run-stub/general_await_implicit.mo deleted file mode 100644 index b1a25606d56..00000000000 --- a/test/run-stub/general_await_implicit.mo +++ /dev/null @@ -1,111 +0,0 @@ -actor Await { - - let N = 4; - - public shared func Ack() : async(){ - debugPrint "Ack" - }; - - public shared func Request(i : Int) : async Int { - debugPrint("Request(" # debug_show i # ")"); - return i - }; - - // Static parallel waiting: - - public shared func PA() : async () { - let a1 = Ack(); - let a2 = Ack(); - await a1; - await a2; - }; - - public shared func PR() : async (Int,Int) { - let a1 = Request(1); - let a2 = Request(2); - (await a1, await a2) - }; - - // Dynamic parallel waiting for acknowledgements - - public shared func DPA() : async () { - let as: [async()] = Array_tabulate(N, func (_) { Ack(); }); - for (a in as.vals()) { - await a; - }; - }; - - // Dynamic parallel waiting (with results) - - public shared func DPR() : async [Int] { - func f<>(i:Nat) : async Int = Request(i); - //NB: <> necesary to suppress implicit @-quantification - let as = Array_tabulate(N, f); - let res = Array_init(as.len(),-1); - for (i in as.keys()) { -// res[i] := (await as[i]); <-- compiler bug (generates incorrect code) - let a = await as[i]; - res[i] := a; - }; - Array_tabulate(as.len(),func i = res[i]) - }; - - // Recursive parallel waiting - - public shared func RPA(n:Nat) : async () { - if (n == 0) () - else { - let a = Ack(); - await RPA(n-1); // recurse - await a; - }; - }; - - // Recursive parallel waiting (with results) - - public type List = ?(Int,List); - - public shared func RPR(n:Nat) : async List { - if (n == 0) null - else { - let a = Request(n); - let tl = await RPR(n-1); // recurse - ?(await a,tl) - } - }; - - - public shared func Test() : async () { - - await PA(); - - switch (await PR()) { - case (1,2) (); - case _ (assert false); - }; - - await DPA(); - - let rs = await DPR(); - for (i in rs.keys()) { - assert rs[i] == i; - }; - - await RPA(N); - - var l = await RPR(N); - for (i in revrange(N, 1)) { - switch (l) { - case (?(h, t)) { - assert (h == i); - l := t; - }; - case null (assert false); - } - }; - } -}; - - -//CALL ingress Test 0x4449444C0000 - diff --git a/test/run-stub/ok/general_await.ic-stub-run.ok b/test/run-stub/ok/general_await.ic-stub-run.ok deleted file mode 100644 index e679f36413e..00000000000 --- a/test/run-stub/ok/general_await.ic-stub-run.ok +++ /dev/null @@ -1,26 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -← completed -→ update Test(0x4449444c0000) -Ack -Ack -Request(+1) -Request(+2) -Ack -Ack -Ack -Ack -Request(0) -Request(+1) -Request(+2) -Request(+3) -Ack -Ack -Ack -Ack -Request(+4) -Request(+3) -Request(+2) -Request(+1) -← completed: 0x4449444c0000 diff --git a/test/run-stub/ok/general_await_implicit.ic-stub-run.ok b/test/run-stub/ok/general_await_implicit.ic-stub-run.ok deleted file mode 100644 index e679f36413e..00000000000 --- a/test/run-stub/ok/general_await_implicit.ic-stub-run.ok +++ /dev/null @@ -1,26 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -← completed -→ update Test(0x4449444c0000) -Ack -Ack -Request(+1) -Request(+2) -Ack -Ack -Ack -Ack -Request(0) -Request(+1) -Request(+2) -Request(+3) -Ack -Ack -Ack -Ack -Request(+4) -Request(+3) -Request(+2) -Request(+1) -← completed: 0x4449444c0000 diff --git a/test/run-stub/ok/scope-inference.ic-stub-run.ok b/test/run-stub/ok/scope-inference.ic-stub-run.ok deleted file mode 100644 index 54225bc8555..00000000000 --- a/test/run-stub/ok/scope-inference.ic-stub-run.ok +++ /dev/null @@ -1,4 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -← completed From 1a3d93dca93f45cd52e18da377c99ae169583e5b Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Mon, 9 Dec 2019 23:01:44 +0000 Subject: [PATCH 0778/1176] Update scoped-await.md --- design/scoped-await.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/design/scoped-await.md b/design/scoped-await.md index 0723c1e839b..70e3c57ea05 100644 --- a/design/scoped-await.md +++ b/design/scoped-await.md @@ -441,6 +441,6 @@ instantiation is desired. Since users may find it odd that we can instantiate the index at any type, it might be better to define "type @ = Non" and always bound -index-parameters by `Non`. Then the top-level choice really is unique -since `Non` (and any `Non`-bounded type parameter) ares the only type +index-parameters by `Non`. Then the top-level choice of index really is unique +since `Non`, and any `Non`-bounded type parameter, are the only types bounded by `Non` and thus suitable for uses as index instantiations. From ba0bd9336e5da4979f29a42ac6f55b003a64d2f3 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 10 Dec 2019 10:21:07 +0000 Subject: [PATCH 0779/1176] Update src/mo_frontend/typing.ml --- src/mo_frontend/typing.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index a9d1a25459a..bc8363908a9 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -812,7 +812,7 @@ and infer_exp'' env exp : T.typ = | n, [] -> [typ] in let typs = match t1 with - | T.Func(_,T.Promises (T.Var (_, n)), _, _, _) + | T.Func (_, T.Promises (T.Var (_, n)), _, _, _) | T.Func(_,T.Returns, _, _, [T.Async (T.Var (_, n),_)]) when n < expected && List.length pre_typs = expected - 1 -> insert n From d7dee8e9d7ced627162f82f2e6938e952b27a417 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 10 Dec 2019 10:21:43 +0000 Subject: [PATCH 0780/1176] Update src/mo_frontend/typing.ml --- src/mo_frontend/typing.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index bc8363908a9..b0d89a9b5ff 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -816,7 +816,7 @@ and infer_exp'' env exp : T.typ = | T.Func(_,T.Returns, _, _, [T.Async (T.Var (_, n),_)]) when n < expected && List.length pre_typs = expected - 1 -> insert n - (Syntax.scope_typ {left=exp1.at.right; right = exp2.at.left}) + (Syntax.scope_typ {left = exp1.at.right; right = exp2.at.left}) pre_typs | _ -> pre_typs in From 93473606f1aac0c1f0b9fdf7ad7d82d0caf49be8 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 10 Dec 2019 10:21:56 +0000 Subject: [PATCH 0781/1176] Update src/mo_frontend/typing.ml --- src/mo_frontend/typing.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index b0d89a9b5ff..2fa1cddc28b 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -813,7 +813,7 @@ and infer_exp'' env exp : T.typ = in let typs = match t1 with | T.Func (_, T.Promises (T.Var (_, n)), _, _, _) - | T.Func(_,T.Returns, _, _, [T.Async (T.Var (_, n),_)]) + | T.Func (_, T.Returns, _, _, [T.Async (T.Var (_, n),_)]) when n < expected && List.length pre_typs = expected - 1 -> insert n (Syntax.scope_typ {left = exp1.at.right; right = exp2.at.left}) From acaf51ac8334ffe1d3523afc54f873c41dd84b09 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 10 Dec 2019 10:22:13 +0000 Subject: [PATCH 0782/1176] Update src/ir_passes/async.ml --- src/ir_passes/async.ml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index 966ec1f5c58..5f0c2d3b268 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -275,7 +275,6 @@ let transform mode env prog = nary_async ).it | CallE (exp1, typs, exp2) when isAwaitableFunc exp1 -> - (* assert (typs = []); *) let ts1,ts2 = match typ exp1 with | T.Func (T.Shared _, T.Promises _,tbs,ts1,ts2) -> From 20dfe157c2cf071b3f2c1b8ea7da1484dfe5ae03 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 10 Dec 2019 10:22:27 +0000 Subject: [PATCH 0783/1176] Update test/fail/illegal-await.mo --- test/fail/illegal-await.mo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/fail/illegal-await.mo b/test/fail/illegal-await.mo index f387af761c3..75da42e2c9c 100644 --- a/test/fail/illegal-await.mo +++ b/test/fail/illegal-await.mo @@ -43,4 +43,4 @@ shared func Rec(n : Int, a : async ()) : async () { let t : async () = Rec(10,t); await t; } -}; \ No newline at end of file +}; From 2dc6a4c4d43553a874b095bf1a22e67d971e7190 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 10 Dec 2019 10:22:38 +0000 Subject: [PATCH 0784/1176] Update src/ir_passes/await.ml --- src/ir_passes/await.ml | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/ir_passes/await.ml b/src/ir_passes/await.ml index 0ae89b73ee0..a7124a5215c 100644 --- a/src/ir_passes/await.ml +++ b/src/ir_passes/await.ml @@ -117,7 +117,6 @@ and t_exp' context exp' = | None -> assert false end | AsyncE (tb, exp1, typ1) -> - (* TODO: this needs more work to account for _tb and _ty *) let exp1 = R.exp R.Renaming.empty exp1 in (* rename all bound vars apart *) (* add the implicit return/throw label *) let k_ret = fresh_cont (typ exp1) in @@ -554,4 +553,3 @@ and t_prog (prog, flavor) = let transform prog = t_prog prog - From d7452f15bf1931fe4b59f1e9dc0c11156263ad63 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 10 Dec 2019 10:22:57 +0000 Subject: [PATCH 0785/1176] Update src/ir_passes/await.ml --- src/ir_passes/await.ml | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/ir_passes/await.ml b/src/ir_passes/await.ml index a7124a5215c..0c16a50ff8d 100644 --- a/src/ir_passes/await.ml +++ b/src/ir_passes/await.ml @@ -369,7 +369,6 @@ and c_exp' context exp k = | None -> assert false end | AsyncE (tb, exp1, typ1) -> - (* TODO: this needs more thought *) (* add the implicit return label *) let k_ret = fresh_cont (typ exp1) in let k_fail = fresh_err_cont () in @@ -552,4 +551,3 @@ and t_prog (prog, flavor) = (t_block LabelEnv.empty prog, { flavor with has_await = false }) let transform prog = t_prog prog - From 0153d7126a091193c351b0ca784c321617a80943 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 10 Dec 2019 10:23:54 +0000 Subject: [PATCH 0786/1176] Update src/ir_passes/show.ml --- src/ir_passes/show.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ir_passes/show.ml b/src/ir_passes/show.ml index 344307a67ab..8f7ff7e78fe 100644 --- a/src/ir_passes/show.ml +++ b/src/ir_passes/show.ml @@ -124,7 +124,7 @@ and t_exp' env = function RetE (t_exp env exp1) | ThrowE exp1 -> ThrowE (t_exp env exp1) - | AsyncE (tb, e, typ) -> AsyncE (tb, t_exp env e, typ) (* TBR *) + | AsyncE (tb, e, typ) -> AsyncE (tb, t_exp env e, typ) | AwaitE e -> AwaitE (t_exp env e) | AssertE exp1 -> AssertE (t_exp env exp1) From c514e8503c97e44bec98785fa1f3f3e325d2ebcf Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Tue, 10 Dec 2019 11:26:14 +0100 Subject: [PATCH 0787/1176] check whether clever encodings (of options of records) work (#725) --- test/run-drun/idl-tuple.mo | 7 +++++++ test/run-drun/ok/idl-tuple.drun-run.ok | 2 ++ 2 files changed, 9 insertions(+) diff --git a/test/run-drun/idl-tuple.mo b/test/run-drun/idl-tuple.mo index 20456305b3f..42a553f5418 100644 --- a/test/run-drun/idl-tuple.mo +++ b/test/run-drun/idl-tuple.mo @@ -6,15 +6,22 @@ actor { // a pair embedded in top-level tuple public query func len3((x:Text, i:Int32), y:Text) : async (Int,Int,Int) { (x.len(), y.len(), int32ToInt i) + }; + // a triple embedded in top-level tuple + public query func len3a((x:Text, i:Int32, z:?(Text,Int32)), y:Text) : async (Int,Int,Int) { + (x.len(), y.len(), int32ToInt i) } } //CALL query len2 "DIDL\x00\x02\x71\x71\x02Hi\x05World" //CALL query len3 0x4449444c016c02007101750200710548656c6c6f0102030405576f726c64 +//CALL query len3a 0x4449444c036c02007101756c030071017502026e000201710548656c6c6f010203040005576f726c64 // testing redundant first tuple member (repeated hash with different type), currently ignored, it is although invalid IDL data //CALL query len3 0x4449444c016c030071007601750200710548656c6c6fdead0102030405576f726c64 // testing redundant third tuple member, gets ignored //CALL query len3 0x4449444c016c030071017502760200710548656c6c6f01020304dead05576f726c64 +// testing third tuple member (recursive option, containing null), gets ignored +//CALL query len3a 0x4449444c026c030071017502016e000200710548656c6c6f010203040005576f726c64 //SKIP run //SKIP run-ir diff --git a/test/run-drun/ok/idl-tuple.drun-run.ok b/test/run-drun/ok/idl-tuple.drun-run.ok index 6789a1dbd26..cf3e86f68cf 100644 --- a/test/run-drun/ok/idl-tuple.drun-run.ok +++ b/test/run-drun/ok/idl-tuple.drun-run.ok @@ -3,3 +3,5 @@ Ok: Payload: 0x4449444c00027c7c0205 Ok: Payload: 0x4449444c00037c7c7c050581848c20 Ok: Payload: 0x4449444c00037c7c7c050581848c20 Ok: Payload: 0x4449444c00037c7c7c050581848c20 +Ok: Payload: 0x4449444c00037c7c7c050581848c20 +Ok: Payload: 0x4449444c00037c7c7c050581848c20 From cb4f99b6ef3f5f0850da08012ba97236a77e5dd4 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 10 Dec 2019 11:47:31 +0100 Subject: [PATCH 0788/1176] DFX Interface: Canister data (#981) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit this is a concrete specification for how to let dfx know Motoko about the ids and types of canisters. The highlevel idea is: * dfx gets a list of all imported canisters (via #979). canisters can be referred to by their concrete id or an alias. * dfx provides the mapping from alias to id via command line flags. * dfx puts IDL files for these canisters (name based on concrete id) in a directory specified by command line flag This proposed to use `import A "ic:…"` to import actors, in contrast to `import A "mo:pkgs/file"` which imports modules from packages. --- design/DFX-Interface.md | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/design/DFX-Interface.md b/design/DFX-Interface.md index a03a62edab8..ddffbf9e8a2 100644 --- a/design/DFX-Interface.md +++ b/design/DFX-Interface.md @@ -48,14 +48,21 @@ Compiling Motoko Files to Wasm In order to compile a motoko file, `dfx` invokes `moc` with - moc some/path/input.mo -o another/path/output.wasm { --package pkgname pkgpath } + moc some/path/input.mo \ + -o another/path/output.wasm \ + { --package pkgname pkgpath } \ + { --actor-alias alias id } + [ --actor-idl actorpath ] in an environment where `MOC_RTS` points to the location of the Motoko runtime system. -This _reads_ `some/path/input.mo` and any `.mo` file referenced by -`some/path/input.mo`, either relatively, absolutely or via the provided package aliases. It also reads the given `mo-rts.wasm` file. +This _reads_ the follwing files + * `some/path/input.mo` + * any `.mo` file referenced by `some/path/input.mo`, either relatively, absolutely or via the provided package aliases + * for every actor import `ic:canisteridoralias` imported by any of the Motoko files, it reads `actorpath/canisteridoralias.mo`, see section Resolving Canister Ids below. + * the given `mo-rts.wasm` file. -No constraints are imposed where these imported files reside (this may be refined to prevent relative imports from looking outside the project and the declared packages) +No constraints are imposed where imported files reside (this may be refined to prevent relative imports from looking outside the project and the declared packages) This _writes_ to `another/path/output.wasm`, but has no other effect. It does not create `another/path/`. @@ -65,6 +72,25 @@ Compiling Motoko Files to IDL As the previous point, but passing `--idl` to `moc`. + +Resolving Canister aliases +-------------------------- + +For every actor imported using `import "ic:alias"`, the Motoko compiler treats that as `import "ic:caniserid"`, if the command line flag `--actor-alias alias id` is given. + +The relation defined by the set of `--actor-alias` arguments must be left-unique and have disjoint range and domain (i.e. no `--actor-alias a b --actor-alias a c` or `--actor-alias a b --actor-alias b c` or even `--actor-alias a a`). + +It is up to `dfx` to determine which urls are aliases that need resolving and which are concrete ids, and to set up `--actor-alias` flags accordingly. + +After applying any aliases, the Motoko compiler assume these imports to refer to the [textual representation] of principal ids (e.g. `ic:ABCDE01A7`), and compilation will fail if they are not. + +[textual representation]: https://docs.dfinity.systems/spec/public/#textual-ids + +Resolving Canister types +------------------------ + +For every actor imports using `import "ic:canisterid"` (or `import "ic:canisteralias"` if `canisteralias` resolves to `canisterid` as described above), the motoko compiler assumes the presence of a file `canisterid.did` in the actor idl path specified by `--actor-idl`. This files informs motoko about the interface of that canister, e.g. the output of `moc --idl` for a locally known canister, or the IDL file as fetched from the Internet Computer. + Compiling IDL Files to JS ------------------------- @@ -85,7 +111,10 @@ Invoking the IDE In order to start the language server, `dfx` invokes - mo-ide --canister-main some/path/main.mo { --package pkgname pkgpath } + mo-ide --canister-main some/path/main.mo \ + { --package pkgname pkgpath } \ + { --actor-alias alias id } + [ --actor-idl actorpath ] with `stdin` and `stdout` connected to the LSP client. From d296f8ceedb0c49061f20fb62f56ec9fddf804f0 Mon Sep 17 00:00:00 2001 From: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> Date: Tue, 10 Dec 2019 11:59:55 +0100 Subject: [PATCH 0789/1176] Implements --print-deps (#982) * implements --print-deps This additional mode for `moc` accepts a path to a source file and then prints all the imported paths in that module to stdout one line at a time. * adds a test for --print-deps * address review feedback * refactors import resolving to use a more flexible traversal * implements collect_imports in resolve_imports.ml * moves print_deps into pipeline now also shares the traversal with our "proper" import resolving * small refactor * reverse list of collected imports We're recursively building the List with cons, so we'll get an order roughly corresponding to the source file ordering this way * don't forget to traverse cases * moved traversal into mo_frontend also added an `over_prog` one --- design/DFX-Interface.md | 21 +++++++++ src/exes/moc.ml | 9 +++- src/mo_frontend/traversals.ml | 78 +++++++++++++++++++++++++++++++ src/mo_frontend/traversals.mli | 7 +++ src/pipeline/pipeline.ml | 6 +++ src/pipeline/pipeline.mli | 2 + src/pipeline/resolve_import.ml | 78 ++++++------------------------- src/pipeline/resolve_import.mli | 2 +- test/repl/ok/print-deps.stdout.ok | 2 + test/repl/print-deps.sh | 2 + 10 files changed, 141 insertions(+), 66 deletions(-) create mode 100644 src/mo_frontend/traversals.ml create mode 100644 src/mo_frontend/traversals.mli create mode 100644 test/repl/ok/print-deps.stdout.ok create mode 100755 test/repl/print-deps.sh diff --git a/design/DFX-Interface.md b/design/DFX-Interface.md index ddffbf9e8a2..a7fb88fb98f 100644 --- a/design/DFX-Interface.md +++ b/design/DFX-Interface.md @@ -123,3 +123,24 @@ This _reads_ `some/path/input.mo` and any `.mo` file referenced by `some/path/input.mo`, either relatively, absolutely or via the provided package aliases. No constraints are imposed where these imported files reside (this may be refined to prevent relative imports from looking outside the project and the declared packages) + +Listing dependencies +-------------------- + +The command + + moc --print-deps some/path/input.mo + +prints to the standard output all URLs _directly_ imported by +`some/path/input.mo`, one per line, e.g. + + mo:stdlib/List + mo:other_package/Some/Module + + +This _reads_ only `some/path/input.mo`, and writes no files. + +By transitively exploring the dependency graph using this command (and +resolving URLs appropriately before passing them as files to `moc`), one can +determine the full set of set of `.mo` files read by the two compilation modes +described above (to wasm and to IDL). diff --git a/src/exes/moc.ml b/src/exes/moc.ml index d4bc64915c6..b81c806f51a 100644 --- a/src/exes/moc.ml +++ b/src/exes/moc.ml @@ -11,7 +11,7 @@ let usage = "Usage: " ^ name ^ " [option] [file ...]" (* Argument handling *) -type mode = Default | Check | Compile | Run | Interact | Idl +type mode = Default | Check | Compile | Run | Interact | Idl | PrintDeps let mode = ref Default let args = ref [] @@ -35,6 +35,7 @@ let argspec = Arg.align "-i", Arg.Unit (set_mode Interact), " run interactive REPL (implies -r)"; "--check", Arg.Unit (set_mode Check), " type-check only"; "--idl", Arg.Unit (set_mode Idl), " generate IDL spec"; + "--print-deps", Arg.Unit (set_mode PrintDeps), " prints the dependencies for a given source file"; "-o", Arg.Set_string out_file, " output file"; "-v", Arg.Set Flags.verbose, " verbose output"; @@ -140,6 +141,12 @@ let process_files files : unit = let oc_ = open_out source_map_file in output_string oc_ source_map; close_out oc_ end + | PrintDeps -> + match files with + | [file] -> Pipeline.print_deps file + | _ -> + (eprintf "--print-deps expects exactly one source file as an argument"; + exit 1) (* Copy relevant flags into the profiler library's (global) settings. This indirection affords the profiler library an independence from the (hacky) Flags library. diff --git a/src/mo_frontend/traversals.ml b/src/mo_frontend/traversals.ml new file mode 100644 index 00000000000..4193a08e7be --- /dev/null +++ b/src/mo_frontend/traversals.ml @@ -0,0 +1,78 @@ +open Mo_def +open Syntax +open Source + +let rec over_exp (f : exp -> exp) (exp : exp) : exp = match exp.it with + | ImportE _ | PrimE _ | VarE _ | LitE _ -> f exp + | UnE (x, y, exp1) -> f { exp with it=UnE (x, y, over_exp f exp1) } + | ShowE (x, exp1) -> f { exp with it=ShowE (x, over_exp f exp1) } + | ProjE (exp1, x) -> f { exp with it=ProjE (over_exp f exp1, x) } + | OptE exp1 -> f { exp with it=OptE (over_exp f exp1) } + | TagE (x, exp1) -> f { exp with it=TagE (x, over_exp f exp1) } + | DotE (exp1, x) -> f { exp with it=DotE (over_exp f exp1, x) } + | NotE exp1 -> f { exp with it=NotE (over_exp f exp1) } + | AssertE exp1 -> f { exp with it=AssertE (over_exp f exp1) } + | LabelE (x, y, exp1) -> f { exp with it=LabelE (x, y, over_exp f exp1) } + | BreakE (x, exp1) -> f { exp with it=BreakE (x, over_exp f exp1) } + | RetE exp1 -> f { exp with it=RetE (over_exp f exp1) } + | AnnotE (exp1, x) -> f { exp with it=AnnotE (over_exp f exp1, x) } + | AsyncE exp1 -> f { exp with it=AsyncE (over_exp f exp1) } + | AwaitE exp1 -> f { exp with it=AwaitE (over_exp f exp1) } + | ThrowE exp1 -> f { exp with it=ThrowE (over_exp f exp1) } + | BinE (x, exp1, y, exp2) -> + f { exp with it=BinE (x, over_exp f exp1, y, over_exp f exp2) } + | IdxE (exp1, exp2) -> + f { exp with it=IdxE (over_exp f exp1, over_exp f exp2) } + | RelE (x, exp1, y, exp2) -> + f { exp with it=RelE (x, over_exp f exp1, y, over_exp f exp2) } + | AssignE (exp1, exp2) -> + f { exp with it=AssignE (over_exp f exp1, over_exp f exp2) } + | CallE (exp1, x, exp2) -> + f { exp with it=CallE (over_exp f exp1, x, over_exp f exp2) } + | AndE (exp1, exp2) -> + f { exp with it=AndE (over_exp f exp1, over_exp f exp2) } + | OrE (exp1, exp2) -> + f { exp with it=OrE (over_exp f exp1, over_exp f exp2) } + | WhileE (exp1, exp2) -> + f { exp with it=WhileE (over_exp f exp1, over_exp f exp2) } + | LoopE (exp1, exp2_opt) -> + f { exp with it=LoopE (over_exp f exp1, Lib.Option.map (over_exp f) exp2_opt) } + | ForE (x, exp1, exp2) -> + f { exp with it=ForE (x, over_exp f exp1, over_exp f exp2) } + | DebugE exp1 -> + f { exp with it=DebugE (over_exp f exp1) } + | TupE exps -> + f { exp with it=TupE (List.map (over_exp f) exps) } + | ArrayE (x, exps) -> + f { exp with it=ArrayE (x, List.map (over_exp f) exps) } + | BlockE ds -> + f { exp with it=BlockE (List.map (over_dec f) ds) } + | ObjE (x, efs) -> + f { exp with it=ObjE (x, List.map (over_exp_field f) efs) } + | IfE (exp1, exp2, exp3) -> + f { exp with it=IfE(over_exp f exp1, over_exp f exp2, over_exp f exp3) } + | TryE (exp1, cases) -> + f { exp with it=TryE (over_exp f exp1, List.map (over_case f) cases) } + | SwitchE (exp1, cases) -> + f { exp with it=SwitchE (over_exp f exp1, List.map (over_case f) cases) } + | FuncE (a, b, c, d, g, e) -> + f { exp with it=FuncE (a, b, c, d, g, over_exp f e) } + +and over_dec (f : exp -> exp) (d : dec) : dec = match d.it with + | TypD _ -> d + | ExpD e -> { d with it=ExpD (over_exp f e)} + | VarD (x, e) -> + { d with it=VarD (x, over_exp f e)} + | LetD (x, e) -> + { d with it=LetD (x, over_exp f e)} + | ClassD (a, b, c, d1, e, g, efs) -> + { d with it=ClassD (a, b, c, d1, e, g, List.map (over_exp_field f) efs)} + +and over_exp_field (f : exp -> exp) (ef : exp_field) : exp_field = + { ef with it={ ef.it with dec=over_dec f ef.it.dec } } + +and over_case (f : exp -> exp) (case : case) : case = + { case with it={ case.it with exp=over_exp f case.it.exp } } + +and over_prog (f : exp -> exp) (prog : prog) : prog = + { prog with it=List.map (over_dec f) prog.it } diff --git a/src/mo_frontend/traversals.mli b/src/mo_frontend/traversals.mli new file mode 100644 index 00000000000..83656ae1ac9 --- /dev/null +++ b/src/mo_frontend/traversals.mli @@ -0,0 +1,7 @@ +open Mo_def.Syntax + +val over_exp: (exp -> exp) -> exp -> exp +val over_dec: (exp -> exp) -> dec -> dec +val over_exp_field: (exp -> exp) -> exp_field -> exp_field +val over_case: (exp -> exp) -> case -> case +val over_prog: (exp -> exp) -> prog -> prog diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index 9a3f16e90c7..d8582fd5bbd 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -114,6 +114,12 @@ let resolve_prog (prog, base) : resolve_result = let resolve_progs = Diag.traverse resolve_prog +(* Printing dependency information *) + +let print_deps (file : string) : unit = + let (prog, _) = Diag.run (parse_file file) in + let imports = Resolve_import.collect_imports prog in + List.iter print_endline imports (* Checking *) diff --git a/src/pipeline/pipeline.mli b/src/pipeline/pipeline.mli index b2a1b0c47e7..51f8054e248 100644 --- a/src/pipeline/pipeline.mli +++ b/src/pipeline/pipeline.mli @@ -6,6 +6,8 @@ type parse_fn = string -> (Syntax.prog * string) Diag.result val parse_file: parse_fn val parse_string: string -> parse_fn +val print_deps: string -> unit + val check_files : string list -> unit Diag.result val check_files' : parse_fn -> string list -> unit Diag.result val check_string : string -> string -> unit Diag.result diff --git a/src/pipeline/resolve_import.ml b/src/pipeline/resolve_import.ml index 5fd5dde93eb..534e0d8be21 100644 --- a/src/pipeline/resolve_import.ml +++ b/src/pipeline/resolve_import.ml @@ -1,4 +1,5 @@ open Mo_def +module Traversals = Mo_frontend.Traversals (* This module traverses the syntax tree. For each `import` statement, it looks @@ -138,70 +139,19 @@ let resolve_package_url (msgs:Diag.msg_store) (base:filepath) (pname:string) (f: }; None -let rec - exp env (e : exp) = match e.it with - | ImportE (f, fp) -> resolve_import_string env e.at f fp - (* The rest is just a boring syntax traversal *) - | (PrimE _ | VarE _ | LitE _) -> () - | UnE (_, _, exp1) - | ShowE (_, exp1) - | ProjE (exp1, _) - | OptE exp1 - | TagE (_, exp1) - | DotE (exp1, _) - | NotE exp1 - | AssertE exp1 - | LabelE (_, _, exp1) - | BreakE (_, exp1) - | RetE exp1 - | AnnotE (exp1, _) - | AsyncE exp1 - | AwaitE exp1 - | ThrowE exp1 - | LoopE (exp1, None) -> - exp env exp1 - | BinE (_, exp1, _, exp2) - | IdxE (exp1, exp2) - | RelE (_, exp1, _, exp2) - | AssignE (exp1, exp2) - | CallE (exp1, _, exp2) - | AndE (exp1, exp2) - | OrE (exp1, exp2) - | WhileE (exp1, exp2) - | LoopE (exp1, Some exp2) - | ForE (_, exp1, exp2) -> - exp env exp1; exp env exp2 - | DebugE exp1 -> - exp env exp1 - | TupE exps - | ArrayE (_, exps) -> - List.iter (exp env) exps - | BlockE ds -> - decs env ds - | ObjE (_, efs) -> - List.iter (fun ef -> dec env ef.it.dec) efs - | IfE (exp1, exp2, exp3) -> - exp env exp1; - exp env exp2; - exp env exp3 - | TryE (exp1, cases) - | SwitchE (exp1, cases) -> - exp env exp1; - List.iter (fun c -> exp env c.it.exp) cases - | FuncE (_, _, _ , _ , _, e) -> - exp env e - -and decs env = List.iter (dec env) -and dec env d = match d.it with - | TypD _ -> () - | ExpD e - | VarD (_, e) - | LetD (_, e) -> - exp env e - | ClassD (_, _, _, _, _ , _, efs) -> - List.iter (fun ef -> dec env ef.it.dec) efs - -let prog env p = decs env p.it +let collect_imports (p : prog): string list = + let res = ref [] in + let f e = match e.it with + | ImportE (f, _) -> res := f::!res; e + | _ -> e in + let _ = ignore (Traversals.over_prog f p) in + List.rev !res + +let prog env p = + let f e = match e.it with + | ImportE (f, fp) -> resolve_import_string env e.at f fp; e + | _ -> e in + ignore (Traversals.over_prog f p) type package_urls = (string * string) list diff --git a/src/pipeline/resolve_import.mli b/src/pipeline/resolve_import.mli index 114eea7b96e..8f69e1fed55 100644 --- a/src/pipeline/resolve_import.mli +++ b/src/pipeline/resolve_import.mli @@ -4,5 +4,5 @@ module S : Set.S with type elt = String.t type package_urls = (string * string) list +val collect_imports : Syntax.prog -> string list val resolve : package_urls -> Syntax.prog -> string -> S.t Diag.result - diff --git a/test/repl/ok/print-deps.stdout.ok b/test/repl/ok/print-deps.stdout.ok new file mode 100644 index 00000000000..49ded34397f --- /dev/null +++ b/test/repl/ok/print-deps.stdout.ok @@ -0,0 +1,2 @@ +nested/a.mo +nested/b.mo diff --git a/test/repl/print-deps.sh b/test/repl/print-deps.sh new file mode 100755 index 00000000000..28067fd7e0a --- /dev/null +++ b/test/repl/print-deps.sh @@ -0,0 +1,2 @@ +#!/bin/bash +${MOC:-$(dirname "$BASH_SOURCE")/../../src/moc} --print-deps lib/nested.mo From 1abb77d241b293a36cac111fc9706be118be00fc Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 10 Dec 2019 11:12:45 +0000 Subject: [PATCH 0790/1176] Update DFX-Interface.md (#995) Typos --- design/DFX-Interface.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/design/DFX-Interface.md b/design/DFX-Interface.md index a7fb88fb98f..b43a1a4e1b3 100644 --- a/design/DFX-Interface.md +++ b/design/DFX-Interface.md @@ -56,7 +56,7 @@ In order to compile a motoko file, `dfx` invokes `moc` with in an environment where `MOC_RTS` points to the location of the Motoko runtime system. -This _reads_ the follwing files +This _reads_ the following files * `some/path/input.mo` * any `.mo` file referenced by `some/path/input.mo`, either relatively, absolutely or via the provided package aliases * for every actor import `ic:canisteridoralias` imported by any of the Motoko files, it reads `actorpath/canisteridoralias.mo`, see section Resolving Canister Ids below. @@ -82,7 +82,7 @@ The relation defined by the set of `--actor-alias` arguments must be left-unique It is up to `dfx` to determine which urls are aliases that need resolving and which are concrete ids, and to set up `--actor-alias` flags accordingly. -After applying any aliases, the Motoko compiler assume these imports to refer to the [textual representation] of principal ids (e.g. `ic:ABCDE01A7`), and compilation will fail if they are not. +After applying any aliases, the Motoko compiler assume these imports to refer to [textual representations] of principal ids (e.g. `ic:ABCDE01A7`), and compilation will fail if they do not. [textual representation]: https://docs.dfinity.systems/spec/public/#textual-ids From 0c5ae635e1337f1ce7797fa3c56d3302c6df6cd2 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 10 Dec 2019 12:21:39 +0100 Subject: [PATCH 0791/1176] Do the show-translation per actor (#994) * Do the show-translation per actor there was a long-standing bug that using `debug_show` in a close actor would make it non-closed, and @crusso just hit it. So I guess I should have fixed that. One solution is to run the show translation independently in the main program and each actor. @crusso, it seems that the detection of `actor` literatls in ICMode in `typing` is incomplete. * Ugh, stupid bug. Should have just shadowed :-) --- src/ir_passes/show.ml | 208 ++++++++++-------- test/run-drun/ok/show-in-actor.comp.ok | 1 + test/run-drun/ok/show-in-actor.comp.ret.ok | 1 + test/run-drun/ok/show-in-actor.ic-stub-run.ok | 7 + test/run-drun/ok/show-in-actor.run-ir.ok | 3 + test/run-drun/ok/show-in-actor.run-low.ok | 3 + test/run-drun/ok/show-in-actor.run.ok | 3 + test/run-drun/show-in-actor.mo | 6 + 8 files changed, 135 insertions(+), 97 deletions(-) create mode 100644 test/run-drun/ok/show-in-actor.comp.ok create mode 100644 test/run-drun/ok/show-in-actor.comp.ret.ok create mode 100644 test/run-drun/ok/show-in-actor.ic-stub-run.ok create mode 100644 test/run-drun/ok/show-in-actor.run-ir.ok create mode 100644 test/run-drun/ok/show-in-actor.run-low.ok create mode 100644 test/run-drun/ok/show-in-actor.run.ok create mode 100644 test/run-drun/show-in-actor.mo diff --git a/src/ir_passes/show.ml b/src/ir_passes/show.ml index b0c0bef564d..89138885e5d 100644 --- a/src/ir_passes/show.ml +++ b/src/ir_passes/show.ml @@ -17,6 +17,9 @@ open Construct - It may fail upon type parameters (i.e. no polymorphism) We can use string_of_typ here for now, it seems. + +Same things is needed Compile.Serialization, so a better solution should be +used there as well! *) let typ_id : T.typ -> string = @@ -33,7 +36,7 @@ type env = { params : T.typ M.t ref } -let empty_env : env = { +let empty_env () : env = { params = ref M.empty; } @@ -56,101 +59,6 @@ let show_fun_typ_for t = let show_var_for t : Construct.var = idE (show_name_for t) (show_fun_typ_for t) -(* The AST traversal *) - -let rec t_exps env decs = List.map (t_exp env) decs - -and t_exp env (e : Ir.exp) = - { e with it = t_exp' env e.it } - -and t_exp' env = function - | LitE l -> LitE l - | VarE id -> VarE id - | PrimE (ShowPrim ot, [exp1]) -> - let t' = T.normalize ot in - add_type env t'; - let f = idE (show_name_for t') (show_fun_typ_for t') in - CallE (f, [], t_exp env exp1) - | PrimE (p, es) -> PrimE (p, t_exps env es) - | TupE exps -> TupE (t_exps env exps) - | OptE exp1 -> - OptE (t_exp env exp1) - | TagE (l, exp1) -> - TagE (l, t_exp env exp1) - | ProjE (exp1, n) -> - ProjE (t_exp env exp1, n) - | ActorE (id, ds, fields, typ) -> - ActorE (id, t_decs env ds, fields, typ) - | DotE (exp1, id) -> - DotE (t_exp env exp1, id) - | ActorDotE (exp1, id) -> - ActorDotE (t_exp env exp1, id) - | AssignE (exp1, exp2) -> - AssignE (t_exp env exp1, t_exp env exp2) - | ArrayE (mut, t, exps) -> - ArrayE (mut, t, t_exps env exps) - | IdxE (exp1, exp2) -> - IdxE (t_exp env exp1, t_exp env exp2) - | FuncE (s, c, id, typbinds, pat, typT, exp) -> - FuncE (s, c, id, typbinds, pat, typT, t_exp env exp) - | CallE (exp1, typs, exp2) -> - CallE(t_exp env exp1, typs, t_exp env exp2) - | BlockE block -> BlockE (t_block env block) - | IfE (exp1, exp2, exp3) -> - IfE (t_exp env exp1, t_exp env exp2, t_exp env exp3) - | SwitchE (exp1, cases) -> - let cases' = - List.map - (fun {it = {pat;exp}; at; note} -> - {it = {pat = pat; exp = t_exp env exp}; at; note}) - cases - in - SwitchE (t_exp env exp1, cases') - | TryE (exp1, cases) -> - let cases' = - List.map - (fun {it = {pat;exp}; at; note} -> - {it = {pat = pat; exp = t_exp env exp}; at; note}) - cases - in - TryE (t_exp env exp1, cases') - | LoopE exp1 -> - LoopE (t_exp env exp1) - | LabelE (id, typ, exp1) -> - LabelE (id, typ, t_exp env exp1) - | BreakE (id, exp1) -> - BreakE (id, t_exp env exp1) - | RetE exp1 -> - RetE (t_exp env exp1) - | ThrowE exp1 -> - ThrowE (t_exp env exp1) - | AsyncE e -> AsyncE (t_exp env e) - | AwaitE e -> AwaitE (t_exp env e) - | AssertE exp1 -> - AssertE (t_exp env exp1) - | DeclareE (id, typ, exp1) -> - DeclareE (id, typ, t_exp env exp1) - | DefineE (id, mut ,exp1) -> - DefineE (id, mut, t_exp env exp1) - | NewObjE (sort, ids, t) -> - NewObjE (sort, ids, t) - | SelfCallE (ts, e1, e2, e3) -> - SelfCallE (ts, t_exp env e1, t_exp env e2, t_exp env e3) - -and t_dec env dec = { dec with it = t_dec' env dec.it } - -and t_dec' env dec' = - match dec' with - | TypD con_id -> TypD con_id - | LetD (pat,exp) -> LetD (pat,t_exp env exp) - | VarD (id,exp) -> VarD (id,t_exp env exp) - -and t_decs env decs = List.map (t_dec env) decs - -and t_block env (ds, exp) = (t_decs env ds, t_exp env exp) - -and t_prog env (prog, flavor) = (t_block env prog, flavor) - (* Construction helpers *) @@ -413,10 +321,116 @@ let show_decls : T.typ M.t -> Ir.dec list = fun roots -> decl :: go (deps @ todo) in go (List.map snd (M.bindings roots)) +(* The AST traversal *) + +(* Does two things: + - collects all uses of `debug_show` in the `env` + - for each actor, resets the environment, recurses, + and adds the show functions (this keeps closed actors closed) +*) + +let rec t_exps env decs = List.map (t_exp env) decs + +and t_exp env (e : Ir.exp) = + { e with it = t_exp' env e.it } + +and t_exp' env = function + | LitE l -> LitE l + | VarE id -> VarE id + | PrimE (ShowPrim ot, [exp1]) -> + let t' = T.normalize ot in + add_type env t'; + let f = idE (show_name_for t') (show_fun_typ_for t') in + CallE (f, [], t_exp env exp1) + | PrimE (p, es) -> PrimE (p, t_exps env es) + | TupE exps -> TupE (t_exps env exps) + | OptE exp1 -> + OptE (t_exp env exp1) + | TagE (l, exp1) -> + TagE (l, t_exp env exp1) + | ProjE (exp1, n) -> + ProjE (t_exp env exp1, n) + | DotE (exp1, id) -> + DotE (t_exp env exp1, id) + | ActorDotE (exp1, id) -> + ActorDotE (t_exp env exp1, id) + | AssignE (exp1, exp2) -> + AssignE (t_exp env exp1, t_exp env exp2) + | ArrayE (mut, t, exps) -> + ArrayE (mut, t, t_exps env exps) + | IdxE (exp1, exp2) -> + IdxE (t_exp env exp1, t_exp env exp2) + | FuncE (s, c, id, typbinds, pat, typT, exp) -> + FuncE (s, c, id, typbinds, pat, typT, t_exp env exp) + | CallE (exp1, typs, exp2) -> + CallE(t_exp env exp1, typs, t_exp env exp2) + | BlockE block -> BlockE (t_block env block) + | IfE (exp1, exp2, exp3) -> + IfE (t_exp env exp1, t_exp env exp2, t_exp env exp3) + | SwitchE (exp1, cases) -> + let cases' = + List.map + (fun {it = {pat;exp}; at; note} -> + {it = {pat = pat; exp = t_exp env exp}; at; note}) + cases + in + SwitchE (t_exp env exp1, cases') + | TryE (exp1, cases) -> + let cases' = + List.map + (fun {it = {pat;exp}; at; note} -> + {it = {pat = pat; exp = t_exp env exp}; at; note}) + cases + in + TryE (t_exp env exp1, cases') + | LoopE exp1 -> + LoopE (t_exp env exp1) + | LabelE (id, typ, exp1) -> + LabelE (id, typ, t_exp env exp1) + | BreakE (id, exp1) -> + BreakE (id, t_exp env exp1) + | RetE exp1 -> + RetE (t_exp env exp1) + | ThrowE exp1 -> + ThrowE (t_exp env exp1) + | AsyncE e -> AsyncE (t_exp env e) + | AwaitE e -> AwaitE (t_exp env e) + | AssertE exp1 -> + AssertE (t_exp env exp1) + | DeclareE (id, typ, exp1) -> + DeclareE (id, typ, t_exp env exp1) + | DefineE (id, mut ,exp1) -> + DefineE (id, mut, t_exp env exp1) + | NewObjE (sort, ids, t) -> + NewObjE (sort, ids, t) + | SelfCallE (ts, e1, e2, e3) -> + SelfCallE (ts, t_exp env e1, t_exp env e2, t_exp env e3) + | ActorE (id, ds, fields, typ) -> + (* compare with transform below *) + let env1 = empty_env () in + let ds' = t_decs env1 ds in + let decls = show_decls !(env1.params) in + ActorE (id, decls @ ds', fields, typ) + +and t_dec env dec = { dec with it = t_dec' env dec.it } + +and t_dec' env dec' = + match dec' with + | TypD con_id -> TypD con_id + | LetD (pat,exp) -> LetD (pat,t_exp env exp) + | VarD (id,exp) -> VarD (id,t_exp env exp) + +and t_decs env decs = List.map (t_dec env) decs + +and t_block env (ds, exp) = (t_decs env ds, t_exp env exp) + +and t_prog env (prog, flavor) = (t_block env prog, flavor) + + (* Entry point for the program transformation *) let transform scope prog = - let env = empty_env in + let env = empty_env () in (* Find all parameters to show in the program *) let prog = t_prog env prog in (* Create declarations for them *) diff --git a/test/run-drun/ok/show-in-actor.comp.ok b/test/run-drun/ok/show-in-actor.comp.ok new file mode 100644 index 00000000000..b87b02ce518 --- /dev/null +++ b/test/run-drun/ok/show-in-actor.comp.ok @@ -0,0 +1 @@ +Fatal error: exception "Assert_failure codegen/compile.ml:6733:11" diff --git a/test/run-drun/ok/show-in-actor.comp.ret.ok b/test/run-drun/ok/show-in-actor.comp.ret.ok new file mode 100644 index 00000000000..63e15a4d3fa --- /dev/null +++ b/test/run-drun/ok/show-in-actor.comp.ret.ok @@ -0,0 +1 @@ +Return code 2 diff --git a/test/run-drun/ok/show-in-actor.ic-stub-run.ok b/test/run-drun/ok/show-in-actor.ic-stub-run.ok new file mode 100644 index 00000000000..68f8eba0f7f --- /dev/null +++ b/test/run-drun/ok/show-in-actor.ic-stub-run.ok @@ -0,0 +1,7 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +debug.print: true +debug.print: false +debug.print: 1 +← completed diff --git a/test/run-drun/ok/show-in-actor.run-ir.ok b/test/run-drun/ok/show-in-actor.run-ir.ok new file mode 100644 index 00000000000..38f979e6b02 --- /dev/null +++ b/test/run-drun/ok/show-in-actor.run-ir.ok @@ -0,0 +1,3 @@ +true +false +1 diff --git a/test/run-drun/ok/show-in-actor.run-low.ok b/test/run-drun/ok/show-in-actor.run-low.ok new file mode 100644 index 00000000000..38f979e6b02 --- /dev/null +++ b/test/run-drun/ok/show-in-actor.run-low.ok @@ -0,0 +1,3 @@ +true +false +1 diff --git a/test/run-drun/ok/show-in-actor.run.ok b/test/run-drun/ok/show-in-actor.run.ok new file mode 100644 index 00000000000..38f979e6b02 --- /dev/null +++ b/test/run-drun/ok/show-in-actor.run.ok @@ -0,0 +1,3 @@ +true +false +1 diff --git a/test/run-drun/show-in-actor.mo b/test/run-drun/show-in-actor.mo new file mode 100644 index 00000000000..9af5a51fbd6 --- /dev/null +++ b/test/run-drun/show-in-actor.mo @@ -0,0 +1,6 @@ +debugPrint (debug_show true); +let _ = actor { + debugPrint (debug_show false); + debugPrint (debug_show 1); +}; +() From 1999696613a55989b5d09f2da2fcd58ab254ed8b Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 10 Dec 2019 12:26:48 +0100 Subject: [PATCH 0792/1176] IDL spec: Remove unsound rules (#710) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * IDL spec: Remove unsound rules now that other teams are starting to look at the IDL spec we should not confuse them by having broken rules in this document, so let’s remove them. Issue #364 is where we are discussing possible ways to fix them. * More unsound sections * Add note about missing record field adding rules --- design/IDL.md | 75 +-------------------------------------------------- 1 file changed, 1 insertion(+), 74 deletions(-) diff --git a/design/IDL.md b/design/IDL.md index e0692e5699f..c45434b69f0 100644 --- a/design/IDL.md +++ b/design/IDL.md @@ -535,18 +535,6 @@ That is, outbound message results can only be replaced with a subtype (more fiel Subtyping applies recursively to the types of the fields themselves. Moreover, the directions get *inverted* for inbound function and actor references, in compliance with standard rules. -**TODO: unsound, fix** - -To make these constraints as flexible as possible, two special rules apply: - - * An absent record field is considered equivalent to a present field with value `null`. Moreover, a record field of type `null` is a subtype of a field with type `opt `. That way, That way, a field of option (or null) type can always be added to a record type, no matter whether in co- or contra-variant position. If an optional field is added to an inbound record, and he client did not provide it, the service will read it as if its value was null. - - - in an outbound record, a field of option (or null) type can also be removed in an upgrade, in which case the client will read it as if its value was null; - - in an inbound record, a field of option (or null) type can also be added, in which case the service will read it as if its value was null. - -Future extensions: defaults, including for variants? - - ### Rules #### Primitive Types @@ -618,54 +606,7 @@ record { ;* } <: record { ;* } record { : ; ;* } <: record { : ; ;* } ``` -**TODO: Rules below are unsound as is, need fixing!** - -In addition, record fields of `null` or option type can be removed, treating the absent field as having value `null`. -``` -record { ;* } <: record { ;* } -------------------------------------------------------------------- -record { ;* } <: record { : null; ;* } - -record { ;* } <: record { ;* } ------------------------------------------------------------------------------ -record { ;* } <: record { : opt ; ;* } -``` -TODO: What we want to achieve: Taken together, these rules ensure that adding an optional field creates both a co- and a contra-variant subtype. Consequently, it is always possible to add an optional field. In particular, that allows extending round-tripping record types as well. For example, -``` -type T = {}; -actor { f : T -> T }; -``` -can safely be upgraded to -``` -type T' = {x : opt text}; -actor { f : T' -> T' }; -``` -for all first-order uses of `T`, because both of the following hold: -``` -upgrade T' <: T -upgrade T <: T' -``` -And hence: -``` -upgrade (T' -> T') <: (T -> T) -``` -for some version of a type `upgrade T`. -Moreover, this extends to the higher-order case, where e.g. a function of the above type is expected as a parameter: -``` -actor { g : (h : T -> T) -> ()} -``` -Upgrading `T` as above contra-variantly requires -``` -upgrade (T -> T) <: (T' -> T') -``` -which also holds. - -Note: Subtyping still needs to be transitive . We must not allow: -``` -record {x : opt text} <: record {} <: record {x : opt nat} -``` -**TODO: Sanity continues from here.** - +**NOTE**: There is a need for a mechanism to also remove fields (which means adding a field when a record appears as an argument). The precise mechanism is still work in progress. #### Variants @@ -770,20 +711,6 @@ record { : ; ;* } <: record { : ; \x.{f2 x with = f1 x.} ``` -TODO: Fix -``` -record { ;* } <: record { ;* } ~> f -------------------------------------------------------------------- -record { ;* } <: record { : null; ;* } - ~> \x.{f x; = null} - -record { ;* } <: record { ;* } ~> f ------------------------------------------------------------------------------ -record { ;* } <: record { : opt ; ;* } - ~> \x.{f x; = null} -``` - - #### Variants ``` From 9f745e902613c9b499aebaf5300ac99f3bc56db1 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 10 Dec 2019 12:33:51 +0100 Subject: [PATCH 0793/1176] Remove openError (#993) which I never thought of as public, as requested by @rossber. I guess inlining the prim is fine for now, but it goes against the kind of structure I am anticipating for prelude/prim/stdlib, as outlined in https://github.com/dfinity-lab/motoko/pull/867#issuecomment-558708888 --- src/prelude/prelude.ml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/prelude/prelude.ml b/src/prelude/prelude.ml index 318982086f0..fa83d21defc 100644 --- a/src/prelude/prelude.ml +++ b/src/prelude/prelude.ml @@ -347,14 +347,16 @@ func Array_tabulate(len : Nat, gen : Nat -> T) : [T] { type ErrorCode = {#error; #system}; /* TBC */ // creation and inspection of abstract error -func openError(e : Error) : (ErrorCode, Text) = - (prim "cast" : Error -> (ErrorCode, Text)) e; func error(message : Text) : Error = { let e = (#error, message); ((prim "cast" : (ErrorCode, Text)-> Error) e) }; -func errorCode(e : Error) : ErrorCode = (openError e).0; -func errorMessage(e : Error) : Text = (openError e).1; +func errorCode(e : Error) : ErrorCode = { + ((prim "cast" : Error -> (ErrorCode, Text)) e).0; +}; +func errorMessage(e : Error) : Text = { + ((prim "cast" : Error -> (ErrorCode, Text)) e).1; +}; type Cont = T -> () ; type Async = (Cont,Cont) -> (); From 03c29b6650b0d4a83df20ef1dba50647a18b1f3e Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 10 Dec 2019 19:40:25 +0100 Subject: [PATCH 0794/1176] IDL grammar summary: service id is optional (#997) this just syncs it with the corresponding line below --- design/IDL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/design/IDL.md b/design/IDL.md index c45434b69f0..71f622dc34f 100644 --- a/design/IDL.md +++ b/design/IDL.md @@ -60,7 +60,7 @@ This is a summary of the grammar proposed: ``` ::= ;* ;? ::= type = | import - ::= service : ( | ) + ::= service ? : ( | ) ::= { ;* } ::= : ( | ) From b04c7e16324093e67e3bcdd730812417a207b2d4 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Tue, 10 Dec 2019 15:43:55 -0700 Subject: [PATCH 0795/1176] basic imperative hash table --- stdlib/hashtbl.mo | 99 +++++++++++++++++++++++++++++++++++++++++++ stdlib/hashtblTest.mo | 23 ++++++++++ 2 files changed, 122 insertions(+) create mode 100644 stdlib/hashtbl.mo create mode 100644 stdlib/hashtblTest.mo diff --git a/stdlib/hashtbl.mo b/stdlib/hashtbl.mo new file mode 100644 index 00000000000..89b8d3c23af --- /dev/null +++ b/stdlib/hashtbl.mo @@ -0,0 +1,99 @@ +import P "prelude.mo"; +import Hash "hash.mo"; +import AssocList "assocList.mo"; + +module { + +/** + +Hash tables +=============== + +This module defines imperative hash tables, with general key and value types. + +It has a minimal object-oriented interface: get, set and iter. + +The class is parameterized by the key's equality and hash functions, +and an initial capacity. However, as with `Buf`, no array allocation +happens until the first `set`. + +Internally, table growth policy is very simple, for now: + Double an initial capacity when the expected + bucket list beyond a certain constant. + +*/ + +// key-val list type +public type KVs = AssocList.AssocList; + +public class Hashtbl ( + initCapacity: Nat, + keyEq: (K,K) -> Bool, + keyHash: K -> Hash.Hash) { + + var table : [var KVs] = [var]; + var count : Nat = 0; + + public func get(k:K) : ?V { + let h = word32ToNat(keyHash(k)); + let m = table.len(); + let v = if (m > 0) { + AssocList.find(table[h % m], k, keyEq) + } else { + null + }; + }; + + public func set(k:K, v:V) : ?V { + if (count >= table.len() * 4) { + let size = + if (count == 0) + initCapacity + else table.len() * 2; + let table2 = Array_init>(size, null); + for (i in table.keys()) { + table2[i] := table[i]; + }; + table := table2; + }; + let h = word32ToNat(keyHash(k)); + let pos = h % table.len(); + let (kvs2, ov) = AssocList.replace(table[pos], k, keyEq, ?v); + table[pos] := kvs2; + switch(ov){ + case null { count += 1 }; + case _ {} + }; + ov + }; + + public func iter() : Iter<(K,V)> { + if (table.len() == 0) { + object { public func next() : ?(K,V) { null } } + } + else { + object { + var kvs = table[0]; + var nextTablePos = 1; + public func next () : ?(K,V) { + switch kvs { + case (?(kv, kvs2)) { + kvs := kvs2; + ?kv + }; + case null { + if (nextTablePos < table.len()) { + kvs := table[nextTablePos]; + nextTablePos += 1; + next() + } else { + null + } + } + } + }; + } + } + }; +}; +} diff --git a/stdlib/hashtblTest.mo b/stdlib/hashtblTest.mo new file mode 100644 index 00000000000..7af84c008cf --- /dev/null +++ b/stdlib/hashtblTest.mo @@ -0,0 +1,23 @@ +import H "Hashtbl.mo"; +import Hash "Hash.mo"; + +func textIsEq(x:Text,y:Text):Bool { x == y }; + +let a = H.Hashtbl(3, textIsEq, Hash.Hash.hashOfText); + +ignore a.set("apple", 1); +ignore a.set("banana", 2); +ignore a.set("pear", 3); +ignore a.set("avocado", 4); + +for ((k,v) in a.iter()) { + debugPrint(debug_show (k,v)); +}; + +/* +prints these pairs, in some order or another: +("banana", 2) +("pear", 3) +("apple", 1) +("avocado", 4) +*/ From 9264b8a0b70cd9b6b50f3f736688e254aca31705 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Tue, 10 Dec 2019 15:53:55 -0700 Subject: [PATCH 0796/1176] implement hash table operations: remove and count --- stdlib/hashtbl.mo | 29 ++++++++++++++++++++++++----- stdlib/hashtblTest.mo | 15 +++++++++++++++ 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/stdlib/hashtbl.mo b/stdlib/hashtbl.mo index 89b8d3c23af..a7f9ee9c218 100644 --- a/stdlib/hashtbl.mo +++ b/stdlib/hashtbl.mo @@ -11,7 +11,7 @@ Hash tables This module defines imperative hash tables, with general key and value types. -It has a minimal object-oriented interface: get, set and iter. +It has a minimal object-oriented interface: get, set, remove, count and iter. The class is parameterized by the key's equality and hash functions, and an initial capacity. However, as with `Buf`, no array allocation @@ -32,7 +32,26 @@ public class Hashtbl ( keyHash: K -> Hash.Hash) { var table : [var KVs] = [var]; - var count : Nat = 0; + var _count : Nat = 0; + + public func count() : Nat = _count; + + public func remove(k:K) : ?V { + let h = word32ToNat(keyHash(k)); + let m = table.len(); + let pos = h % m; + if (m > 0) { + let (kvs2, ov) = AssocList.replace(table[pos], k, keyEq, null); + table[pos] := kvs2; + switch(ov){ + case null { }; + case _ { _count -= 1; } + }; + ov + } else { + null + }; + }; public func get(k:K) : ?V { let h = word32ToNat(keyHash(k)); @@ -45,9 +64,9 @@ public class Hashtbl ( }; public func set(k:K, v:V) : ?V { - if (count >= table.len() * 4) { + if (_count >= table.len() * 4) { let size = - if (count == 0) + if (_count == 0) initCapacity else table.len() * 2; let table2 = Array_init>(size, null); @@ -61,7 +80,7 @@ public class Hashtbl ( let (kvs2, ov) = AssocList.replace(table[pos], k, keyEq, ?v); table[pos] := kvs2; switch(ov){ - case null { count += 1 }; + case null { _count += 1 }; case _ {} }; ov diff --git a/stdlib/hashtblTest.mo b/stdlib/hashtblTest.mo index 7af84c008cf..959a2932fed 100644 --- a/stdlib/hashtblTest.mo +++ b/stdlib/hashtblTest.mo @@ -21,3 +21,18 @@ prints these pairs, in some order or another: ("apple", 1) ("avocado", 4) */ + +ignore a.set("apple", 1111); +ignore a.set("banana", 2222); +ignore a.remove("pear"); +ignore a.remove("avocado"); + +for ((k,v) in a.iter()) { + debugPrint(debug_show (k,v)); +}; + +/* +prints these pairs, in some order or another: +("banana", 2222) +("apple", 1111) +*/ From de030ae0e29f5bc2d27d52990453a73e3c425f18 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Tue, 10 Dec 2019 15:56:31 -0700 Subject: [PATCH 0797/1176] add Makefiles lines, for CI --- stdlib/Makefile | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/stdlib/Makefile b/stdlib/Makefile index 49762f71ad4..70acafbdaa8 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -24,6 +24,8 @@ TESTS=\ Function \ FunctionTest \ Hash \ + Hashtbl \ + HashtblTest \ Int \ IntTest \ Iter \ @@ -81,6 +83,12 @@ $(OUTDIR)/Buf.out: buf.mo | $(OUTDIR) $(OUTDIR)/BufTest.out: bufTest.mo | $(OUTDIR) $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ +$(OUTDIR)/HashtblTest.out: HashtblTest.mo | $(OUTDIR) + $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ + +$(OUTDIR)/Hashtbl.out: Hashtbl.mo | $(OUTDIR) + $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ + $(OUTDIR)/Function.out: function.mo | $(OUTDIR) $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ From 8814b96fe9509fc3c9f14a6e3ee458a0613b5c1a Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 11 Dec 2019 00:29:34 +0100 Subject: [PATCH 0798/1176] Bump Ocaml (#551) Bump Ocaml to 4.07, including minor reorganization of `default.nix`. Upgrade to 4.08 and/or of `wasm` can come separately. --- default.nix | 45 ++++++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/default.nix b/default.nix index 756fca6a2c8..59aa2cb78da 100644 --- a/default.nix +++ b/default.nix @@ -6,7 +6,23 @@ let nixpkgs = (import ./nix/nixpkgs.nix).nixpkgs { inherit system; overlays = [ + # Adding wasmtime (self: super: { wasmtime = self.callPackage ./nix/wasmtime {}; }) + # Selecting the ocaml version + (self: super: { ocamlPackages = self.ocaml-ng.ocamlPackages_4_07; }) + # Additional ocaml package + (self: super: { + ocamlPackages = super.ocamlPackages // { + wasm = import ./nix/ocaml-wasm.nix { + inherit (self) stdenv fetchFromGitHub ocaml; + inherit (self.ocamlPackages) findlib ocamlbuild; + }; + vlq = import ./nix/ocaml-vlq.nix { + inherit (self) stdenv fetchFromGitHub ocaml dune; + inherit (self.ocamlPackages) findlib; + }; + }; + }) ]; }; in @@ -63,8 +79,7 @@ let in # When building for linux (but not in nix-shell) we build statically -# (We should probably just figure out how to use nix overlays to add this to nixpkgs) -let ocamlpkgs = +let staticpkgs = if nixpkgs.stdenv.isDarwin then nixpkgs else nixpkgs.pkgsMusl; in @@ -74,32 +89,21 @@ let ocamlpkgs = # normal nixpkgs (nix-shell, darwin) # nixpkgs.pkgsMusl for static building (release builds) let commonBuildInputs = pkgs: - let ocaml_wasm = import ./nix/ocaml-wasm.nix { - inherit (pkgs) stdenv fetchFromGitHub ocaml; - inherit (pkgs.ocamlPackages) findlib ocamlbuild; - }; in - - let ocaml_vlq = import ./nix/ocaml-vlq.nix { - inherit (pkgs) stdenv fetchFromGitHub ocaml dune; - inherit (pkgs.ocamlPackages) findlib; - }; in - [ - pkgs.ocaml pkgs.dune + pkgs.ocamlPackages.ocaml pkgs.ocamlPackages.atdgen pkgs.ocamlPackages.findlib pkgs.ocamlPackages.menhir pkgs.ocamlPackages.num pkgs.ocamlPackages.stdint - ocaml_wasm - ocaml_vlq + pkgs.ocamlPackages.wasm + pkgs.ocamlPackages.vlq pkgs.ocamlPackages.zarith pkgs.ocamlPackages.yojson pkgs.ocamlPackages.ppxlib pkgs.ocamlPackages.ppx_inline_test pkgs.ocamlPackages.bisect_ppx - pkgs.ocamlPackages.bisect_ppx-ocamlbuild pkgs.ocamlPackages.ocaml-migrate-parsetree pkgs.ocamlPackages.ppx_tools_versioned ]; in @@ -117,14 +121,14 @@ let ocaml_exe = name: bin: then "release" else "release-static"; - drv = ocamlpkgs.stdenv.mkDerivation { + drv = staticpkgs.stdenv.mkDerivation { inherit name; ${if nixpkgs.stdenv.isDarwin then null else "allowedRequisites"} = []; src = subpath ./src; - buildInputs = commonBuildInputs ocamlpkgs; + buildInputs = commonBuildInputs staticpkgs; buildPhase = '' make DUNE_OPTS="--display=short --profile ${profile}" ${bin} @@ -198,7 +202,7 @@ rec { let testDerivation = args: stdenv.mkDerivation (testDerivationArgs // args); in let ocamlTestDerivation = args: - ocamlpkgs.stdenv.mkDerivation (testDerivationArgs // args); in + staticpkgs.stdenv.mkDerivation (testDerivationArgs // args); in # we test each subdirectory of test/ in its own derivation with # cleaner dependencies, for more paralleism, more caching @@ -268,7 +272,7 @@ rec { let unit-tests = ocamlTestDerivation { name = "unit-tests"; src = subpath ./src; - buildInputs = commonBuildInputs ocamlpkgs; + buildInputs = commonBuildInputs staticpkgs; checkPhase = '' make DUNE_OPTS="--display=short" unit-tests ''; @@ -310,7 +314,6 @@ rec { buildInputs = commonBuildInputs nixpkgs ++ [ nixpkgs.ocamlPackages.js_of_ocaml - nixpkgs.ocamlPackages.js_of_ocaml-ocamlbuild nixpkgs.ocamlPackages.js_of_ocaml-ppx nixpkgs.nodejs-10_x ]; From f6c376612f73eaaaec2f2ed95a0341f24a74dc61 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 11 Dec 2019 09:55:00 +0100 Subject: [PATCH 0799/1176] Fix the ic-stub nix-shell (#1003) --- ic-stub/shell.nix | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ic-stub/shell.nix b/ic-stub/shell.nix index 9e1ba03df1f..c25d45ba5df 100644 --- a/ic-stub/shell.nix +++ b/ic-stub/shell.nix @@ -1,7 +1,9 @@ -{ nixpkgs ? (import ../nix/nixpkgs.nix).nixpkgs {} }: - +{ system ? builtins.currentSystem, +}: let - ic-stub = (import ../default.nix {inherit nixpkgs;}).ic-stub; + ic-stub = (import ../default.nix {inherit system;}).ic-stub; + + nixpkgs = (import ../nix/nixpkgs.nix).nixpkgs { inherit system; }; extra-pkgs = [ nixpkgs.haskellPackages.cabal-install From 599e494fa61efe5ad213dc12d8e19cd3a7808a5d Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 11 Dec 2019 12:30:16 +0100 Subject: [PATCH 0800/1176] Tighten actor check on ICMode (#996) * Do the show-translation per actor there was a long-standing bug that using `debug_show` in a close actor would make it non-closed, and @crusso just hit it. So I guess I should have fixed that. One solution is to run the show translation independently in the main program and each actor. @crusso, it seems that the detection of `actor` literatls in ICMode in `typing` is incomplete. * Ugh, stupid bug. Should have just shadowed :-) * Tighten actor check on ICMode should be merged after #994. * Newlines * Update test --- src/mo_frontend/typing.ml | 21 ++++++++++----------- test/run-drun/ok/show-in-actor.comp.ok | 3 ++- test/run-drun/ok/show-in-actor.comp.ret.ok | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index eb4170984c5..5c1cc639f9c 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -1871,14 +1871,13 @@ let check_actors scope progs : unit Diag.result = recover_opt (fun progs -> let prog = List.concat (List.map (fun prog -> prog.Source.it) progs) in let env = env_of_scope msgs scope in - match List.filter is_actor_dec prog with - | [] -> () - | [d] -> () - | ds -> - List.iter (fun d -> - recover - (error_in [Flags.ICMode; Flags.StubMode] env d.at) - "multiple actors in program; there must be at most one actor declaration in a program") - ds - ) - progs) + let rec go = function + | [] -> () + | [d] -> () + | (d::ds) when is_actor_dec d -> + recover (error_in [Flags.ICMode] env d.at) + "an actor must be the last declaration in a program" + | (d::ds) -> go ds in + go prog + ) progs + ) diff --git a/test/run-drun/ok/show-in-actor.comp.ok b/test/run-drun/ok/show-in-actor.comp.ok index b87b02ce518..2657536c521 100644 --- a/test/run-drun/ok/show-in-actor.comp.ok +++ b/test/run-drun/ok/show-in-actor.comp.ok @@ -1 +1,2 @@ -Fatal error: exception "Assert_failure codegen/compile.ml:6733:11" +show-in-actor.mo:2.1-5.2: type error, an actor must be the last declaration in a program + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/show-in-actor.comp.ret.ok b/test/run-drun/ok/show-in-actor.comp.ret.ok index 63e15a4d3fa..69becfa16f9 100644 --- a/test/run-drun/ok/show-in-actor.comp.ret.ok +++ b/test/run-drun/ok/show-in-actor.comp.ret.ok @@ -1 +1 @@ -Return code 2 +Return code 1 From 808cd57b259066cf8a83dd690be7e4939c224685 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 11 Dec 2019 12:45:34 +0100 Subject: [PATCH 0801/1176] Link to `Building.md` from `README.md` (#1006) would have helped @dsarlis. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 6db21f37507..5f58436c802 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ A simple language for writing Dfinity actors. ## User Documentation & Samples +* [Building, installing, developing on Motoko](Building.md). * [Overview slides](https://hydra.dfinity.systems/job/dfinity-ci-build/motoko/users-guide/latest/download/1/as-slides.html) ([sources](guide/as-slides.md)). * [Draft (incomplete) manual](guide/guide.md). * [Prelude](src/prelude/prelude.ml). From 959698e9e164bfafeda75ba89b81a24371c03113 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 11 Dec 2019 12:54:04 +0100 Subject: [PATCH 0802/1176] Bump drun, finishes migration to ic0 (#998) mainly to get https://github.com/dfinity-lab/dfinity/pull/2068 also includes ``` 9bc86873d Merge pull request #2068 from dfinity-lab/DFN-1172/remaining 40a58c936 Merge pull request #2078 from dfinity-lab/akhi3030/unique-queues 1bff1bba6 SDK-603: improve error message on checkpoint recovery failure (#2079) 2efaa5e8d First round of applying StateManager deep dive feedback. (#2064) 6a6838b50 simplifies gas accounting (#2071) a7176704c Make HypervisorError::MethodNotFound more expressive (#2076) 776fca57d Merge pull request #2017 from dfinity-lab/dimitris/add-allocation-message 1d00f53d9 Squashed crypto/ed25519-clib-types from 89c8abe508f7075477b458d01b3538b02ff188d0 (#2059) 989fd0530 DFN-1223: Add BasicSigByPubkeyVerifier trait (#2067) 809599eba DFN-1227: Add algorithm_id field to UserPublicKey (#2066) 5ef3f6272 Merge pull request #2063 from dfinity-lab/johnw/log_analyzer 4060d63e7 Use process_manager in nodemanager to control client processes (#2061) 74989d44f Merge pull request #1754 from dfinity-lab/dimitris/improve-allocation-type 2185562ed Restructure some of canister queue related code 20c3a05bd drun: Return immediatelly when message is available (#2065) ``` --- default.nix | 2 +- src/codegen/compile.ml | 44 +++++++++++++----------------------------- 2 files changed, 14 insertions(+), 32 deletions(-) diff --git a/default.nix b/default.nix index 59aa2cb78da..1439f52347c 100644 --- a/default.nix +++ b/default.nix @@ -38,7 +38,7 @@ let dfinity-src = name = "dfinity-sources"; url = "ssh://git@github.com/dfinity-lab/dfinity"; # ref = "master"; - rev = "4d09038b09b4ba230205216a0a590b80c33a59cb"; + rev = "9bc86873da48fcc54677d8905669e726b5a32406"; }; in let dfinity-pkgs = import dfinity-src { inherit (nixpkgs) system; }; in diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 5a7f7f11f36..a3ff0277c15 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -2710,25 +2710,9 @@ end (* Tuple *) module Dfinity = struct (* Dfinity-specific stuff: System imports, databufs etc. *) - let system_imports env = - let i32s n = Lib.List.make n I32Type in - match E.mode env with - | Flags.ICMode -> - E.add_func_import env "debug" "print" [I32Type; I32Type] []; - E.add_func_import env "ic0" "call_simple" (i32s 10) [I32Type]; - E.add_func_import env "ic0" "canister_self_copy" (i32s 3) []; - E.add_func_import env "ic0" "canister_self_size" [] [I32Type]; - E.add_func_import env "ic0" "msg_arg_data_copy" (i32s 3) []; - E.add_func_import env "ic0" "msg_arg_data_size" [] [I32Type]; - E.add_func_import env "ic0" "msg_caller_copy" (i32s 3) []; - E.add_func_import env "ic0" "msg_caller_size" [] [I32Type]; - E.add_func_import env "ic0" "msg_reject_code" [] [I32Type]; - E.add_func_import env "ic0" "msg_reject" (i32s 2) []; - E.add_func_import env "ic0" "msg_reply_data_append" (i32s 2) []; - E.add_func_import env "ic0" "msg_reply" [] []; - E.add_func_import env "ic" "trap" [I32Type; I32Type] []; - () - | Flags.StubMode -> + let i32s n = Lib.List.make n I32Type + + let import_ic0 env = E.add_func_import env "ic0" "call_simple" (i32s 10) [I32Type]; E.add_func_import env "ic0" "canister_self_copy" (i32s 3) []; E.add_func_import env "ic0" "canister_self_size" [] [I32Type]; @@ -2744,6 +2728,14 @@ module Dfinity = struct E.add_func_import env "ic0" "msg_reply_data_append" (i32s 2) []; E.add_func_import env "ic0" "msg_reply" [] []; E.add_func_import env "ic0" "trap" (i32s 2) []; + () + + let system_imports env = + match E.mode env with + | Flags.ICMode -> + import_ic0 env + | Flags.StubMode -> + import_ic0 env; E.add_func_import env "stub" "create_canister" (i32s 4) [I32Type]; E.add_func_import env "stub" "created_canister_id_size" (i32s 1) [I32Type]; E.add_func_import env "stub" "created_canister_id_copy" (i32s 4) []; @@ -2757,8 +2749,7 @@ module Dfinity = struct let print_ptr_len env = match E.mode env with | Flags.WasmMode -> G.i Drop ^^ G.i Drop - | Flags.ICMode -> system_call env "debug" "print" - | Flags.StubMode -> system_call env "ic0" "debug_print" + | Flags.ICMode | Flags.StubMode -> system_call env "ic0" "debug_print" | Flags.WASIMode -> Func.share_code2 env "print_ptr" (("ptr", I32Type), ("len", I32Type)) [] (fun env get_ptr get_len -> Stack.with_words env "io_vec" 6l (fun get_iovec_ptr -> @@ -2816,16 +2807,7 @@ module Dfinity = struct let compile_static_print env s = Blob.lit env s ^^ print_text env - let _compile_println_int env = - system_call env "test" "show_i32" ^^ - system_call env "test" "print" ^^ - compile_static_print env "\n" - - let ic_trap env = - match E.mode env with - | Flags.ICMode -> system_call env "ic" "trap" - | Flags.StubMode -> system_call env "ic0" "trap" - | _ -> assert false + let ic_trap env = system_call env "ic0" "trap" let ic_trap_str env = Func.share_code1 env "ic_trap" ("str", I32Type) [] (fun env get_str -> From ebd710ae22fcb4a5c9b42fb6ad2fe781d9f25ecf Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 11 Dec 2019 16:13:27 +0100 Subject: [PATCH 0803/1176] Bump drun (#1008) mainly to get https://github.com/dfinity-lab/dfinity/pull/2060 which is @Dfinity-skaestle's debut. Also included ``` dedfec2e2 Merge pull request #2060 from dfinity-lab/DFN-1156-drun-no-client d5d265157 Improve error message for invalid imported function (#2088) cc627c81e Merge pull request #2084 from dfinity-lab/dsd/nodemanager/integrate_metrics_runtime 2ccd9fe43 DFN-1006: Implement MultiSigner trait for crypto component (#2002) 56eb04e67 Use FullFormat for logs instead of CompactFormat (#2073) 7b0b8feee Merge pull request #2053 from dfinity-lab/kb/demo_changes 818a7de02 Merge pull request #2081 from dfinity-lab/dsd/metrics_in_node_manager ``` --- default.nix | 2 +- test/run-drun/ok/divide-by-zero.drun-run.ok | 1 + test/run-drun/ok/divide-by-zero.drun-run.ret.ok | 1 + test/run-drun/ok/selftail.drun-run.ok | 1 + test/run-drun/ok/selftail.drun-run.ret.ok | 1 + 5 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 test/run-drun/ok/divide-by-zero.drun-run.ret.ok create mode 100644 test/run-drun/ok/selftail.drun-run.ret.ok diff --git a/default.nix b/default.nix index 1439f52347c..2f6c99e22a2 100644 --- a/default.nix +++ b/default.nix @@ -38,7 +38,7 @@ let dfinity-src = name = "dfinity-sources"; url = "ssh://git@github.com/dfinity-lab/dfinity"; # ref = "master"; - rev = "9bc86873da48fcc54677d8905669e726b5a32406"; + rev = "dedfec2e294a29f8a1f5f39f1700ebcdad3c6db4"; }; in let dfinity-pkgs = import dfinity-src { inherit (nixpkgs) system; }; in diff --git a/test/run-drun/ok/divide-by-zero.drun-run.ok b/test/run-drun/ok/divide-by-zero.drun-run.ok index 5da68903a6c..1830f40cd69 100644 --- a/test/run-drun/ok/divide-by-zero.drun-run.ok +++ b/test/run-drun/ok/divide-by-zero.drun-run.ok @@ -1 +1,2 @@ ingress(0) Err: IC0502: Canister 42 trapped: integer division by 0 +Error: "Failed to install canister - ignoring message stream" diff --git a/test/run-drun/ok/divide-by-zero.drun-run.ret.ok b/test/run-drun/ok/divide-by-zero.drun-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/divide-by-zero.drun-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-drun/ok/selftail.drun-run.ok b/test/run-drun/ok/selftail.drun-run.ok index 2bed2f23c23..e693dfb619f 100644 --- a/test/run-drun/ok/selftail.drun-run.ok +++ b/test/run-drun/ok/selftail.drun-run.ok @@ -1,3 +1,4 @@ debug.print: ok1 debug.print: ok2 ingress(0) Err: IC0502: Canister 42 trapped: stack overflow +Error: "Failed to install canister - ignoring message stream" diff --git a/test/run-drun/ok/selftail.drun-run.ret.ok b/test/run-drun/ok/selftail.drun-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/selftail.drun-run.ret.ok @@ -0,0 +1 @@ +Return code 1 From 61d2798d4430f331444731f8c740f173f9399094 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 11 Dec 2019 16:49:20 +0100 Subject: [PATCH 0804/1176] IR: Introduce BlobLit and ActorOfIdBlob (#1005) This is to support #1001. The ir interpreter implementation of `ActorOfIdBlob` likely needs help from @crusso, and may relate to #986. No tests, because we have no surface syntax for blob literals yet; one source of such literals will come with #1001. --- src/codegen/compile.ml | 15 ++++++++++----- src/ir_def/arrange_ir.ml | 2 ++ src/ir_def/check_ir.ml | 1 + src/ir_def/ir.ml | 3 +++ src/ir_interpreter/interpret_ir.ml | 3 +++ 5 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index a3ff0277c15..f868c073c91 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -5060,7 +5060,7 @@ let compile_lit env lit = try match lit with (* Booleans are directly in Vanilla representation *) | BoolLit false -> SR.bool, Bool.lit false - | BoolLit true -> SR.bool, Bool.lit true + | BoolLit true -> SR.bool, Bool.lit true | IntLit n | NatLit n -> SR.Vanilla, BigNum.compile_lit env n | Word8Lit n -> SR.Vanilla, compile_unboxed_const (Value.Word8.to_bits n) @@ -5077,8 +5077,9 @@ let compile_lit env lit = | Nat64Lit n -> SR.UnboxedWord64, compile_const_64 (Big_int.int64_of_big_int (nat64_to_int64 n)) | CharLit c -> SR.Vanilla, compile_unboxed_const Int32.(shift_left (of_int c) 8) | NullLit -> SR.Vanilla, Opt.null - | TextLit t -> SR.Vanilla, Blob.lit env t - | _ -> todo_trap_SR env "compile_lit" (Arrange_ir.lit lit) + | TextLit t + | BlobLit t -> SR.Vanilla, Blob.lit env t + | FloatLit _ -> todo_trap_SR env "compile_lit" (Arrange_ir.lit lit) with Failure _ -> Printf.eprintf "compile_lit: Overflow in literal %s\n" (string_of_lit lit); SR.Unreachable, E.trap_with env "static literal overflow" @@ -6001,6 +6002,9 @@ and compile_exp (env : E.t) ae exp = (* Coercions for abstract types *) | CastPrim (_,_), [e] -> compile_exp env ae e + (* Actor ids are blobs in the RTS *) + | ActorOfIdBlob _, [e] -> + compile_exp env ae e | ICReplyPrim ts, [e] -> SR.unit, begin match E.mode env with @@ -6333,10 +6337,11 @@ and compile_lit_pat env l = BoxedWord64.unbox env ^^ snd (compile_lit env l) ^^ compile_eq env Type.(Prim Word64) - | TextLit t -> + | TextLit t + | BlobLit t -> Blob.lit env t ^^ Text.compare env Operator.EqOp - | _ -> todo_trap env "compile_lit_pat" (Arrange_ir.lit l) + | FloatLit _ -> todo_trap env "compile_lit_pat" (Arrange_ir.lit l) and fill_pat env ae pat : patternCode = PatCode.with_region pat.at @@ diff --git a/src/ir_def/arrange_ir.ml b/src/ir_def/arrange_ir.ml index 745b1682310..81e7ee16681 100644 --- a/src/ir_def/arrange_ir.ml +++ b/src/ir_def/arrange_ir.ml @@ -62,6 +62,7 @@ and prim = function | ShowPrim t -> "ShowPrim" $$ [typ t] | NumConvPrim (t1, t2) -> "NumConvPrim" $$ [prim_ty t1; prim_ty t2] | CastPrim (t1, t2) -> "CastPrim" $$ [typ t1; typ t2] + | ActorOfIdBlob t -> "ActorOfIdBlob" $$ [typ t] | OtherPrim s -> Atom s | CPSAwait -> Atom "CPSAwait" | CPSAsync -> Atom "CPSAsync" @@ -104,6 +105,7 @@ and lit (l:lit) = match l with | FloatLit f -> "FloatLit" $$ [ Atom (Value.Float.to_pretty_string f) ] | CharLit c -> "CharLit" $$ [ Atom (string_of_int c) ] | TextLit t -> "TextLit" $$ [ Atom t ] + | BlobLit b -> "BlobLit" $$ [ Atom (Printf.sprintf "%S" b) ] (* hex might be nicer *) and pat_field pf = pf.it.name $$ [pat pf.it.pat] diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 33e1554aae5..e61e3bdcdad 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -298,6 +298,7 @@ let type_lit env lit at : T.prim = | FloatLit _ -> T.Float | CharLit _ -> T.Char | TextLit _ -> T.Text + | BlobLit _ -> T.Blob (* Expressions *) diff --git a/src/ir_def/ir.ml b/src/ir_def/ir.ml index 3e415fa75e7..054cd45d4f1 100644 --- a/src/ir_def/ir.ml +++ b/src/ir_def/ir.ml @@ -25,6 +25,7 @@ type lit = | FloatLit of Value.Float.t | CharLit of Value.unicode | TextLit of string + | BlobLit of string (* Patterns *) type typ_note = {note_typ : Type.typ; note_eff : Type.eff} @@ -107,6 +108,7 @@ and prim = | ShowPrim of Type.typ (* debug show *) | NumConvPrim of Type.prim * Type.prim | CastPrim of Type.typ * Type.typ (* representationally a noop *) + | ActorOfIdBlob of Type.typ | OtherPrim of string (* Other primitive operation, no custom typing rule *) | CPSAwait | CPSAsync @@ -145,6 +147,7 @@ let string_of_lit = function | CharLit c -> string_of_int c | NullLit -> "null" | TextLit t -> t + | BlobLit b -> Printf.sprintf "%s" b | FloatLit f -> Value.Float.to_pretty_string f (* Flavor *) diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index ebf6dd1c7f5..b8a1fa9e242 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -258,6 +258,7 @@ let interpret_lit env lit : V.value = | FloatLit f -> V.Float f | CharLit c -> V.Char c | TextLit s -> V.Text s + | BlobLit b -> V.Text b (* Expressions *) @@ -363,6 +364,8 @@ and interpret_exp_mut env exp (k : V.value V.cont) = Prim.prim s arg k ) | CastPrim _, [e] -> interpret_exp env e k + | ActorOfIdBlob t, [e] -> + assert false; (* probably related to #986 *) | NumConvPrim (t1, t2), exps -> interpret_exps env exps [] (fun vs -> let arg = match vs with [v] -> v | _ -> V.Tup vs in From 0b31789ea03ae7c4d223a5b8ae744d3b7fc4cb6d Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 11 Dec 2019 17:50:28 +0000 Subject: [PATCH 0805/1176] scope counterexample --- test/run-drun/ok/scope-example.comp.ok | 2 ++ test/run-drun/ok/scope-example.comp.ret.ok | 1 + test/run-drun/ok/scope-example.ic-stub-run.ok | 7 ++++++ test/run-drun/scope-example.mo | 22 +++++++++++++++++++ 4 files changed, 32 insertions(+) create mode 100644 test/run-drun/ok/scope-example.comp.ok create mode 100644 test/run-drun/ok/scope-example.comp.ret.ok create mode 100644 test/run-drun/ok/scope-example.ic-stub-run.ok create mode 100644 test/run-drun/scope-example.mo diff --git a/test/run-drun/ok/scope-example.comp.ok b/test/run-drun/ok/scope-example.comp.ok new file mode 100644 index 00000000000..6ee5d1d6fb6 --- /dev/null +++ b/test/run-drun/ok/scope-example.comp.ok @@ -0,0 +1,2 @@ +scope-example.mo:8.20-11.10: type error, unsupported async block + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/scope-example.comp.ret.ok b/test/run-drun/ok/scope-example.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/scope-example.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-drun/ok/scope-example.ic-stub-run.ok b/test/run-drun/ok/scope-example.ic-stub-run.ok new file mode 100644 index 00000000000..e9decbe8ec6 --- /dev/null +++ b/test/run-drun/ok/scope-example.ic-stub-run.ok @@ -0,0 +1,7 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ update f(0x4449444c0000) +Trap: EvalTrapError :0.1 "uninitialized element 0" +← rejected (RC_CANISTER_ERROR): canister trapped: EvalTrapError :0.1 "uninitialized element 0" diff --git a/test/run-drun/scope-example.mo b/test/run-drun/scope-example.mo new file mode 100644 index 00000000000..78741e989cf --- /dev/null +++ b/test/run-drun/scope-example.mo @@ -0,0 +1,22 @@ +actor A { + public shared func ping() : async Int = async {666;} ; // normal remote function + + public shared func f() : async () = async { + // current scope: Y + var m : ? (async Int) = null; + + let i = await (async { + // current scope: Z + m := ? (ping ()); // this seems well-typed according to “Application (Derived Rule)”; + } ); + + switch (m) { + case null assert false; + case (? a) assert (await a) == 666; // Boom! + } + } ; + +}; + +A.f() //OR-CALL ingress f 0x4449444C0000 + From 25a7ae9c78eebe5241e4d9b66b84dce3d6efe2ed Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Wed, 11 Dec 2019 13:43:32 -0800 Subject: [PATCH 0806/1176] test growth; clone helper --- stdlib/hashtbl.mo | 30 +++++++++++- stdlib/hashtblTest.mo | 111 +++++++++++++++++++++++++++++++----------- 2 files changed, 110 insertions(+), 31 deletions(-) diff --git a/stdlib/hashtbl.mo b/stdlib/hashtbl.mo index a7f9ee9c218..f9a85ecaa09 100644 --- a/stdlib/hashtbl.mo +++ b/stdlib/hashtbl.mo @@ -64,14 +64,26 @@ public class Hashtbl ( }; public func set(k:K, v:V) : ?V { - if (_count >= table.len() * 4) { + if (_count >= table.len()) { let size = if (_count == 0) initCapacity else table.len() * 2; let table2 = Array_init>(size, null); for (i in table.keys()) { - table2[i] := table[i]; + var kvs = table[i]; + label moveKeyVals : () + loop { + switch kvs { + case null { break moveKeyVals }; + case (?((k, v), kvsTail)) { + let h = word32ToNat(keyHash(k)); + let pos2 = h % table.len(); + table2[pos2] := ?((k,v), table2[pos2]); + kvs := kvsTail; + }; + } + }; }; table := table2; }; @@ -115,4 +127,18 @@ public class Hashtbl ( } }; }; + +// clone cannot be an efficient object method, +// ...but is still useful in tests, and beyond. +public func clone + (h:Hashtbl, + initCapacity: Nat, + keyEq: (K,K) -> Bool, + keyHash: K -> Hash.Hash) : Hashtbl { + let h2 = Hashtbl(h.count(), keyEq, keyHash); + for ((k,v) in h.iter()) { + ignore h2.set(k,v); + }; + h2 +}; } diff --git a/stdlib/hashtblTest.mo b/stdlib/hashtblTest.mo index 959a2932fed..ecda25fa96d 100644 --- a/stdlib/hashtblTest.mo +++ b/stdlib/hashtblTest.mo @@ -3,36 +3,89 @@ import Hash "Hash.mo"; func textIsEq(x:Text,y:Text):Bool { x == y }; -let a = H.Hashtbl(3, textIsEq, Hash.Hash.hashOfText); +debug { + let a = H.Hashtbl(3, textIsEq, Hash.Hash.hashOfText); -ignore a.set("apple", 1); -ignore a.set("banana", 2); -ignore a.set("pear", 3); -ignore a.set("avocado", 4); + ignore a.set("apple", 1); + ignore a.set("banana", 2); + ignore a.set("pear", 3); + ignore a.set("avocado", 4); + ignore a.set("Apple", 11); + ignore a.set("Banana", 22); + ignore a.set("Pear", 33); + ignore a.set("Avocado", 44); + ignore a.set("ApplE", 111); + ignore a.set("BananA", 222); + ignore a.set("PeaR", 333); + ignore a.set("AvocadO", 444); -for ((k,v) in a.iter()) { - debugPrint(debug_show (k,v)); -}; + // need to resupply the constructor args; they are private to the object; but, should they be? + let b = H.clone(a, 3, textIsEq, Hash.Hash.hashOfText); -/* -prints these pairs, in some order or another: -("banana", 2) -("pear", 3) -("apple", 1) -("avocado", 4) -*/ - -ignore a.set("apple", 1111); -ignore a.set("banana", 2222); -ignore a.remove("pear"); -ignore a.remove("avocado"); - -for ((k,v) in a.iter()) { - debugPrint(debug_show (k,v)); -}; + // ensure clone has each key-value pair present in original + for ((k,v) in a.iter()) { + debugPrint(debug_show (k,v)); + switch (b.get(k)) { + case null { assert false }; + case (?w) { assert v == w }; + }; + }; + + // ensure original has each key-value pair present in clone + for ((k,v) in b.iter()) { + debugPrint(debug_show (k,v)); + switch (a.get(k)) { + case null { assert false }; + case (?w) { assert v == w }; + }; + }; + + // do some more operations: + ignore a.set("apple", 1111); + ignore a.set("banana", 2222); + ignore a.remove("pear"); + ignore a.remove("avocado"); + + // check them: + switch (a.get("apple")) { + case (?1111) { }; + case _ { assert false }; + }; + switch (a.get("apple")) { + case (?2222) { }; + case _ { assert false }; + }; + switch (a.get("pear")) { + case null { }; + case (?_) { assert false }; + }; + switch (a.get("avocado")) { + case null { }; + case (?_) { assert false }; + }; -/* -prints these pairs, in some order or another: -("banana", 2222) -("apple", 1111) -*/ + // undo operations above: + ignore a.set("apple", 1); + ignore a.set("banana", 2); + ignore a.set("pear", 3); + ignore a.set("avocado", 4); + + // ensure clone has each key-value pair present in original + for ((k,v) in a.iter()) { + debugPrint(debug_show (k,v)); + switch (b.get(k)) { + case null { assert false }; + case (?w) { assert v == w }; + }; + }; + + // ensure original has each key-value pair present in clone + for ((k,v) in b.iter()) { + debugPrint(debug_show (k,v)); + switch (a.get(k)) { + case null { assert false }; + case (?w) { assert v == w }; + }; + }; + +}; From 2c18f9e7afdf68a6b682e1b412c0c6e114fd40f7 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Wed, 11 Dec 2019 15:13:08 -0800 Subject: [PATCH 0807/1176] mapFilter generalizes 'clone' --- stdlib/hashtbl.mo | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/stdlib/hashtbl.mo b/stdlib/hashtbl.mo index f9a85ecaa09..4b9b6a48c43 100644 --- a/stdlib/hashtbl.mo +++ b/stdlib/hashtbl.mo @@ -141,4 +141,26 @@ public func clone }; h2 }; + +// clone cannot be an efficient object method, +// ...but is still useful in tests, and beyond. +public func mapFilter + (h:Hashtbl, + initCapacity: Nat, + keyEq: (K,K) -> Bool, + keyHash: K -> Hash.Hash, + mapFn: (K, V1) -> ?V2, + ) : Hashtbl { + let h2 = Hashtbl(h.count(), keyEq, keyHash); + for ((k, v1) in h.iter()) { + switch (mapFn(k, v1)) { + case null { }; + case (?v2) { + ignore h2.set(k,v2); + }; + } + }; + h2 +}; + } From 9f91249b16efc3f2223376ba791dbe899b1cfe20 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Wed, 11 Dec 2019 15:27:32 -0800 Subject: [PATCH 0808/1176] nit --- stdlib/hashtbl.mo | 2 -- 1 file changed, 2 deletions(-) diff --git a/stdlib/hashtbl.mo b/stdlib/hashtbl.mo index 4b9b6a48c43..357d226d2fa 100644 --- a/stdlib/hashtbl.mo +++ b/stdlib/hashtbl.mo @@ -142,8 +142,6 @@ public func clone h2 }; -// clone cannot be an efficient object method, -// ...but is still useful in tests, and beyond. public func mapFilter (h:Hashtbl, initCapacity: Nat, From 083d7c37b55bd060abdf973cbb6f30f9fd82cd6a Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 12 Dec 2019 09:35:30 +0100 Subject: [PATCH 0809/1176] Remove obsolete code in backend (#1010) there is a TODO telling me to do X when Y. I believe Y holds. Doing X now. --- src/codegen/compile.ml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index f868c073c91..4531f2d53b3 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -2343,11 +2343,8 @@ module Object = struct (* Determines whether the field is mutable (and thus needs an indirection) *) let is_mut_field env obj_type s = - (* TODO: remove try once array and text accessors are separated *) - try - let _, fields = Type.as_obj_sub [s] obj_type in - Type.is_mut (Type.lookup_val_field s fields) - with Invalid_argument _ -> false + let _, fields = Type.as_obj_sub [s] obj_type in + Type.is_mut (Type.lookup_val_field s fields) let idx env obj_type name = compile_unboxed_const (Mo_types.Hash.hash name) ^^ From e6a01d6c96c43e55003d85bbc57e96a0f730de2a Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 12 Dec 2019 12:48:33 +0100 Subject: [PATCH 0810/1176] Async pass: Descend into all `prim`s with types (#1013) --- src/ir_passes/async.ml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index c86e1997075..8206fd2d358 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -207,6 +207,8 @@ let transform mode env prog = | RelPrim (ot, op) -> RelPrim (t_typ ot, op) | ShowPrim ot -> ShowPrim (t_typ ot) | NumConvPrim (t1,t2) -> NumConvPrim (t1,t2) + | CastPrim (t1,t2) -> CastPrim (t_typ t1,t_typ t2) + | ActorOfIdBlob t -> ActorOfIdBlob (t_typ t) | ICReplyPrim ts -> ICReplyPrim (List.map t_typ ts) | p -> p From a1245626051bba08b63e6d1fe29bc2966c57572b Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 12 Dec 2019 13:10:51 +0100 Subject: [PATCH 0811/1176] Backend: Trap if ic0.call_simple fails (#1011) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Backend: Trap if ic0.call_simple fails there is a discussion in #933 about what to do if the system doesn’t want the call we are trying to send. Or rather, there should be a discussion. But in any case, I guess trapping is better than ignoring the error, at least for non-one-way-functions. * Fix wasm type --- src/codegen/compile.ml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 4531f2d53b3..deb3cd9dbf4 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -4761,8 +4761,9 @@ module FuncDec = struct get_arg ^^ Serialization.serialize env ts1 ^^ (* done! *) Dfinity.system_call env "ic0" "call_simple" ^^ - (* TODO: Check error code *) - G.i Drop + (* Check error code *) + G.i (Test (Wasm.Values.I32 I32Op.Eqz)) ^^ + E.else_trap_with env "could not perform call" | _ -> assert false let ic_call_one_shot env ts get_meth_pair get_arg = @@ -4783,7 +4784,7 @@ module FuncDec = struct get_arg ^^ Serialization.serialize env ts ^^ (* done! *) Dfinity.system_call env "ic0" "call_simple" ^^ - (* TODO: Check error code *) + (* This is a one-shot function: Ignore error code *) G.i Drop | _ -> assert false From bdaf2a851625508841c877166294421b50923ff7 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Thu, 12 Dec 2019 13:25:03 +0000 Subject: [PATCH 0812/1176] another bad scope example using functions --- test/run-drun/ok/scope-example-func.comp.ok | 4 +++ .../ok/scope-example-func.comp.ret.ok | 1 + .../ok/scope-example-func.ic-stub-run.ok | 7 +++++ test/run-drun/scope-example-func.mo | 29 +++++++++++++++++++ 4 files changed, 41 insertions(+) create mode 100644 test/run-drun/ok/scope-example-func.comp.ok create mode 100644 test/run-drun/ok/scope-example-func.comp.ret.ok create mode 100644 test/run-drun/ok/scope-example-func.ic-stub-run.ok create mode 100644 test/run-drun/scope-example-func.mo diff --git a/test/run-drun/ok/scope-example-func.comp.ok b/test/run-drun/ok/scope-example-func.comp.ok new file mode 100644 index 00000000000..af81a3fd713 --- /dev/null +++ b/test/run-drun/ok/scope-example-func.comp.ok @@ -0,0 +1,4 @@ +scope-example-func.mo:16.19-16.20: type error, argument to await must be a call expression + (This is a limitation of the current version.) +scope-example-func.mo:22.23-22.24: type error, calling a shared function not yet supported + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/scope-example-func.comp.ret.ok b/test/run-drun/ok/scope-example-func.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/scope-example-func.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-drun/ok/scope-example-func.ic-stub-run.ok b/test/run-drun/ok/scope-example-func.ic-stub-run.ok new file mode 100644 index 00000000000..711ce0f41ed --- /dev/null +++ b/test/run-drun/ok/scope-example-func.ic-stub-run.ok @@ -0,0 +1,7 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ update Test(0x4449444c0000) +Trap: EvalTrapError :0.1 "uninitialized element 0" +← rejected (RC_CANISTER_REJECT): canister trapped: EvalTrapError :0.1 "uninitialized element 0" diff --git a/test/run-drun/scope-example-func.mo b/test/run-drun/scope-example-func.mo new file mode 100644 index 00000000000..26e400d65ac --- /dev/null +++ b/test/run-drun/scope-example-func.mo @@ -0,0 +1,29 @@ +actor A { + + public shared func f() : async (Int,Int) = async { + // current scope: Y + var a : (async Int) = async 0; + + func set () { + a := async {return 666} ; + }; + + await (async { + // current scope: Z + set(); // this seems well-typed according to “Application (Derived Rule)”; + } ); + + let i = await a; + assert i == 666; // Boom! + return (0,0) + } ; + + public shared func Test() : async () { + let (x,y) = await f(); + assert x == 0 and y == 0; + }; + +}; + +A.Test() //OR-CALL ingress Test 0x4449444C0000 + From 11fe5f16c1bddd8b54c82e8fb2c190d7e6163cd0 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Thu, 12 Dec 2019 15:05:37 +0100 Subject: [PATCH 0813/1176] Update DFX-Interface.md (#1016) --- design/DFX-Interface.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/design/DFX-Interface.md b/design/DFX-Interface.md index b43a1a4e1b3..1007fc21390 100644 --- a/design/DFX-Interface.md +++ b/design/DFX-Interface.md @@ -76,7 +76,7 @@ As the previous point, but passing `--idl` to `moc`. Resolving Canister aliases -------------------------- -For every actor imported using `import "ic:alias"`, the Motoko compiler treats that as `import "ic:caniserid"`, if the command line flag `--actor-alias alias id` is given. +For every actor imported using `import "ic:alias"`, the Motoko compiler treats that as `import "ic:canisterid"`, if the command line flag `--actor-alias alias id` is given. The relation defined by the set of `--actor-alias` arguments must be left-unique and have disjoint range and domain (i.e. no `--actor-alias a b --actor-alias a c` or `--actor-alias a b --actor-alias b c` or even `--actor-alias a a`). From 1d7e93731ec1068e13d488e061f0df7212cfc8e9 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Thu, 12 Dec 2019 14:23:35 +0000 Subject: [PATCH 0814/1176] simplify test --- test/run-drun/ok/scope-example.comp.ok | 4 +++- test/run-drun/ok/scope-example.ic-stub-run.ok | 4 ++-- test/run-drun/scope-example.mo | 21 +++++++++++-------- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/test/run-drun/ok/scope-example.comp.ok b/test/run-drun/ok/scope-example.comp.ok index 6ee5d1d6fb6..663defa5b9c 100644 --- a/test/run-drun/ok/scope-example.comp.ok +++ b/test/run-drun/ok/scope-example.comp.ok @@ -1,2 +1,4 @@ -scope-example.mo:8.20-11.10: type error, unsupported async block +scope-example.mo:13.19-13.20: type error, argument to await must be a call expression + (This is a limitation of the current version.) +scope-example.mo:19.23-19.24: type error, calling a shared function not yet supported (This is a limitation of the current version.) diff --git a/test/run-drun/ok/scope-example.ic-stub-run.ok b/test/run-drun/ok/scope-example.ic-stub-run.ok index e9decbe8ec6..711ce0f41ed 100644 --- a/test/run-drun/ok/scope-example.ic-stub-run.ok +++ b/test/run-drun/ok/scope-example.ic-stub-run.ok @@ -2,6 +2,6 @@ ← completed: canister-id = 0x0000000000000400 → install ← completed -→ update f(0x4449444c0000) +→ update Test(0x4449444c0000) Trap: EvalTrapError :0.1 "uninitialized element 0" -← rejected (RC_CANISTER_ERROR): canister trapped: EvalTrapError :0.1 "uninitialized element 0" +← rejected (RC_CANISTER_REJECT): canister trapped: EvalTrapError :0.1 "uninitialized element 0" diff --git a/test/run-drun/scope-example.mo b/test/run-drun/scope-example.mo index 78741e989cf..4e595935bfe 100644 --- a/test/run-drun/scope-example.mo +++ b/test/run-drun/scope-example.mo @@ -1,22 +1,25 @@ actor A { public shared func ping() : async Int = async {666;} ; // normal remote function - public shared func f() : async () = async { + public shared func f() : async (Int,Int) = async { // current scope: Y - var m : ? (async Int) = null; + var a : (async Int) = async 0; - let i = await (async { + await (async { // current scope: Z - m := ? (ping ()); // this seems well-typed according to “Application (Derived Rule)”; + a := ping (); // this seems well-typed according to “Application (Derived Rule)”; } ); - switch (m) { - case null assert false; - case (? a) assert (await a) == 666; // Boom! - } + let i = await a; + assert i == 666; // Boom! + return (0,0) } ; + public shared func Test() : async () { + let (0,0) = await f() + }; + }; -A.f() //OR-CALL ingress f 0x4449444C0000 +A.Test() //OR-CALL ingress Test 0x4449444C0000 From d847b5c565aa62e2cb0caf698ee0e4462494c230 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 12 Dec 2019 15:34:29 +0100 Subject: [PATCH 0815/1176] IC Stub: Simplify `Imports` type (#1002) * IC Stub: Simplify `Imports` type to a flat list, which also allows `toImport` to include the module name in the error message. * Helpful type aliases --- ic-stub/src/IC/Canister/Imp.hs | 48 ++++++++++++++++------------------ ic-stub/src/IC/Wasm/Imports.hs | 6 ++--- ic-stub/src/IC/Wasm/Winter.hs | 27 ++++++++++++------- 3 files changed, 43 insertions(+), 38 deletions(-) diff --git a/ic-stub/src/IC/Canister/Imp.hs b/ic-stub/src/IC/Canister/Imp.hs index 9df690c0063..efe5e363a77 100644 --- a/ic-stub/src/IC/Canister/Imp.hs +++ b/ic-stub/src/IC/Canister/Imp.hs @@ -144,29 +144,25 @@ appendNewCanister esref c = modES esref $ \es -> systemAPI :: forall s. ESRef s -> Imports s systemAPI esref = - [ (,) "ic0" - [ toImport "msg_arg_data_size" msg_arg_data_size - , toImport "msg_arg_data_copy" msg_arg_data_copy - , toImport "msg_caller_size" msg_caller_size - , toImport "msg_caller_copy" msg_caller_copy - , toImport "msg_reject_code" msg_reject_code - , toImport "msg_reject_msg_size" msg_reject_msg_size - , toImport "msg_reject_msg_copy" msg_reject_msg_copy - , toImport "msg_reply_data_append" msg_reply_data_append - , toImport "msg_reply" msg_reply - , toImport "msg_reject" msg_reject - , toImport "canister_self_copy" canister_self_copy - , toImport "canister_self_size" canister_self_size - , toImport "call_simple" call_simple - , toImport "debug_print" debug_print - , toImport "trap" explicit_trap - ] - , (,) "stub" - [ toImport "create_canister" create_canister - , toImport "created_canister_id_size" created_canister_id_size - , toImport "created_canister_id_copy" created_canister_id_copy - ] - ] + [ toImport "ic0" "msg_arg_data_size" msg_arg_data_size + , toImport "ic0" "msg_arg_data_copy" msg_arg_data_copy + , toImport "ic0" "msg_caller_size" msg_caller_size + , toImport "ic0" "msg_caller_copy" msg_caller_copy + , toImport "ic0" "msg_reject_code" msg_reject_code + , toImport "ic0" "msg_reject_msg_size" msg_reject_msg_size + , toImport "ic0" "msg_reject_msg_copy" msg_reject_msg_copy + , toImport "ic0" "msg_reply_data_append" msg_reply_data_append + , toImport "ic0" "msg_reply" msg_reply + , toImport "ic0" "msg_reject" msg_reject + , toImport "ic0" "canister_self_copy" canister_self_copy + , toImport "ic0" "canister_self_size" canister_self_size + , toImport "ic0" "call_simple" call_simple + , toImport "ic0" "debug_print" debug_print + , toImport "ic0" "trap" explicit_trap + , toImport "stub" "create_canister" create_canister + , toImport "stub" "created_canister_id_size" created_canister_id_size + , toImport "stub" "created_canister_id_copy" created_canister_id_copy + ] where -- Utilities gets :: (ExecutionState s -> b) -> HostM s b @@ -221,12 +217,12 @@ systemAPI esref = msg_arg_data_size :: () -> HostM s Int32 msg_arg_data_copy :: (Int32, Int32, Int32) -> HostM s () (msg_arg_data_size, msg_arg_data_copy) = size_and_copy $ - gets (param_dat . params) >>= maybe (throwError "arg_data_size: No argument") return + gets (param_dat . params) >>= maybe (throwError "No argument") return msg_caller_size :: () -> HostM s Int32 msg_caller_copy :: (Int32, Int32, Int32) -> HostM s () (msg_caller_size, msg_caller_copy) = size_and_copy $ - fmap rawEntityId $ gets (param_caller . params) >>= maybe (throwError "arg_data_size: No argument") return + fmap rawEntityId $ gets (param_caller . params) >>= maybe (throwError "No argument") return msg_reject_code :: () -> HostM s Int32 msg_reject_code () = @@ -236,7 +232,7 @@ systemAPI esref = msg_reject_msg_copy :: (Int32, Int32, Int32) -> HostM s () (msg_reject_msg_size, msg_reject_msg_copy) = size_and_copy $ do c <- gets (reject_code . params) - when (c == 0) $ throwError "msg_reject_msg: No reject message" + when (c == 0) $ throwError "No reject message" msg <- gets (reject_message . params) return $ BSU.fromString msg diff --git a/ic-stub/src/IC/Wasm/Imports.hs b/ic-stub/src/IC/Wasm/Imports.hs index dacd814d173..b947d353a4a 100644 --- a/ic-stub/src/IC/Wasm/Imports.hs +++ b/ic-stub/src/IC/Wasm/Imports.hs @@ -232,12 +232,12 @@ instance toImport :: forall a b s. (WasmArgs a, WasmArgs b) => - String -> (a -> HostM s b) -> Import s -toImport name f = (name, stackType @a, stackType @b, f') + String -> String -> (a -> HostM s b) -> Import s +toImport mod_name fun_name f = (mod_name, fun_name, stackType @a, stackType @b, f') where f' :: [Value] -> HostFunc s f' xs = do - a <- withExceptT ((name ++ ": ") ++) $ + a <- withExceptT ((mod_name ++ "." ++ fun_name ++ ": ") ++) $ ExceptT $ return (fromValues xs) b <- f a return $ toValues b diff --git a/ic-stub/src/IC/Wasm/Winter.hs b/ic-stub/src/IC/Wasm/Winter.hs index af44f9e6996..0eee955b525 100644 --- a/ic-stub/src/IC/Wasm/Winter.hs +++ b/ic-stub/src/IC/Wasm/Winter.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE ScopedTypeVariables #-} {-| This module provides a thin wrapper around the winter Wasm engine, exposing just @@ -54,9 +55,10 @@ type HostM s = ExceptT String (ST s) type HostFunc s = HostM s [W.Value] -type Import s = (String, W.StackType, W.StackType, [W.Value] -> HostFunc s) - -type Imports s = [(String, [Import s])] +type ModName = String +type FuncName = String +type Import s = (ModName, FuncName, W.StackType, W.StackType, [W.Value] -> HostFunc s) +type Imports s = [Import s] type Module = W.Module Identity @@ -66,9 +68,16 @@ parseModule bytes = case runGetOrFail W.getModule bytes of Right (_,_,wasm_mod) -> Right wasm_mod -initialize :: Module -> Imports s -> HostM s (Instance s) +initialize :: forall s. Module -> Imports s -> HostM s (Instance s) initialize mod imps = withExceptT show $ do - let names = M.fromList (zip (map (T.pack . fst) imps) [1..]) + let by_mod :: [(T.Text, [(T.Text, W.StackType, W.StackType, [W.Value] -> HostFunc s)])] + by_mod = M.toList $ M.fromListWith (<>) + [ (T.pack m, [(T.pack n,t1,t2,f)]) | (m,n,t1,t2,f) <- imps ] + + names :: M.Map T.Text Int + names = M.fromList (zip (map fst by_mod) [1..]) + + mods :: IM.IntMap (W.ModuleInst Identity (ST s)) mods = IM.fromList $ zip [1..] [ (W.emptyModuleInst def) { W._miGlobals = [ ] @@ -76,20 +85,20 @@ initialize mod imps = withExceptT show $ do , W._miMemories = [ ] , W._miFuncs = [ ] , W._miExports = M.fromList - [ (,) (T.pack fname) $ W.ExternFunc $ + [ (,) fname $ W.ExternFunc $ W.allocHostEff (W.FuncType arg_ty ret_ty) (\ args -> runExceptT $ f args) | (fname, arg_ty, ret_ty, f) <- funcs ] } - | (_name, funcs) <- imps + | (_name, funcs) <- by_mod ] (ref, inst) <- W.initialize (Identity mod) names mods let mods' = IM.insert ref inst mods return (mods', ref) -exportedFunctions :: Module -> [String] +exportedFunctions :: Module -> [FuncName] exportedFunctions wasm_mod = [ T.unpack (W._exportName e) | Identity e <- W._moduleExports wasm_mod @@ -97,7 +106,7 @@ exportedFunctions wasm_mod = ] -invokeExport :: Instance s -> String -> [W.Value] -> HostM s [W.Value] +invokeExport :: Instance s -> FuncName -> [W.Value] -> HostM s [W.Value] invokeExport (mods', ref) method args = do let inst = mods' IM.! ref withExceptT show $ From a1405c19acef18af8c34fb18bd48570750aa6d71 Mon Sep 17 00:00:00 2001 From: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> Date: Thu, 12 Dec 2019 15:59:03 +0100 Subject: [PATCH 0816/1176] Resolve package paths in IDE (#951) * define an interface for Declaration_index * moves module imports around * Stop outputting every message to the log_file This information is easily obtained from all the editor plugins * properly resolves package paths when reading module headers * returns the correct URIs for definitions from libraries * adds a test to check the LSP is picking up package paths * tests that auto completion works on dependency modules * adds some log statements to make error diagnosis easier * make sure the project path is absolute * small refactor * Update src/languageServer/declaration_index.ml Co-Authored-By: Claudio Russo * exports FilePath and ResolveImport from the pipeline module --- src/languageServer/completion.ml | 46 ++--- src/languageServer/declaration_index.ml | 25 ++- src/languageServer/declaration_index.mli | 30 ++++ src/languageServer/definition.ml | 40 +++-- src/languageServer/dune | 2 +- src/languageServer/hover.ml | 2 +- src/languageServer/languageServer.ml | 11 +- src/languageServer/source_file.ml | 36 +++- src/languageServer/source_file_tests.ml | 7 + src/pipeline/pipeline.ml | 15 +- src/pipeline/pipeline.mli | 3 + src/pipeline/resolve_import.mli | 1 + test/lsp-int/Main.hs | 164 ++++++++++++------ .../test-project/mydependency/broken.mo | 5 + test/lsp-int/test-project/mydependency/lib.mo | 5 + 15 files changed, 265 insertions(+), 127 deletions(-) create mode 100644 src/languageServer/declaration_index.mli create mode 100644 test/lsp-int/test-project/mydependency/broken.mo create mode 100644 test/lsp-int/test-project/mydependency/lib.mo diff --git a/src/languageServer/completion.ml b/src/languageServer/completion.ml index 3be02afb733..a538b32d56d 100644 --- a/src/languageServer/completion.ml +++ b/src/languageServer/completion.ml @@ -1,7 +1,7 @@ open Mo_types open Mo_frontend -open Declaration_index module Lsp_t = Lsp.Lsp_t +module DI = Declaration_index let string_of_list f xs = List.map f xs @@ -12,8 +12,8 @@ let template_of_ide_decl decl = let supply = ref 0 in let fresh () = supply := !supply + 1; string_of_int !supply in match decl with - | ValueDecl value -> - (match value.typ with + | DI.ValueDecl value -> + (match value.DI.typ with | Type.Func(_, _, binds, ty_list1, ty_list2) -> let ty_args = binds @@ -25,27 +25,27 @@ let template_of_ide_decl decl = |> List.map (fun _ -> Printf.sprintf "$%s" (fresh ())) |> String.concat ", " in let ty_args = if ty_args = "" then "" else "<" ^ ty_args ^ ">" in - Printf.sprintf "%s%s(%s)" value.name ty_args args - | _ -> value.name) - | TypeDecl ty -> - ty.name + Printf.sprintf "%s%s(%s)" value.DI.name ty_args args + | _ -> value.DI.name) + | DI.TypeDecl ty -> + ty.DI.name -let item_of_ide_decl (d : ide_decl) : Lsp_t.completion_item = +let item_of_ide_decl (d : DI.ide_decl) : Lsp_t.completion_item = let tmpl = template_of_ide_decl d in match d with - | ValueDecl value -> + | DI.ValueDecl value -> Lsp_t.{ - completion_item_label = value.name; + completion_item_label = value.DI.name; completion_item_kind = 3; completion_item_insertText = tmpl; completion_item_insertTextFormat = 2; - completion_item_detail = Some(Type.string_of_typ value.typ); + completion_item_detail = Some(Type.string_of_typ value.DI.typ); } - | TypeDecl ty -> - let con = ty.typ in + | DI.TypeDecl ty -> + let con = ty.DI.typ in let eq, params, typ = Type.strings_of_kind (Con.kind con) in Lsp_t.{ - completion_item_label = ty.name; + completion_item_label = ty.DI.name; completion_item_kind = 7; completion_item_insertText = tmpl; completion_item_insertTextFormat = 2; @@ -53,19 +53,19 @@ let item_of_ide_decl (d : ide_decl) : Lsp_t.completion_item = Some (Printf.sprintf "type %s%s" - ty.name + ty.DI.name params); } let import_relative_to_project_root root module_path dependency = - match Pipeline__.File_path.relative_to root module_path with + match Pipeline.FilePath.relative_to root module_path with | None -> None | Some root_to_module -> root_to_module |> Filename.dirname |> Lib.Fun.flip Filename.concat dependency - |> Pipeline__.File_path.normalise + |> Pipeline.FilePath.normalise |> Lib.Option.some (* Given a source file and a cursor position in that file, figure out @@ -109,9 +109,9 @@ let find_completion_prefix logger file line column: (string * string) option = | _ -> loop (next ()) in try loop (next ()) with _ -> None -let has_prefix (prefix : string) (ide_decl : ide_decl): bool = +let has_prefix (prefix : string) (ide_decl : DI.ide_decl): bool = ide_decl - |> name_of_ide_decl + |> DI.name_of_ide_decl |> Lib.String.chop_prefix prefix |> Lib.Option.is_some @@ -121,7 +121,7 @@ let opt_bind f = function let completions index logger project_root file_path file_contents line column = let imported = Source_file.parse_module_header project_root file_path file_contents in - let current_uri_opt = Pipeline__.File_path.relative_to project_root file_path in + let current_uri_opt = Pipeline.FilePath.relative_to project_root file_path in let module_alias_completion_item alias = Lsp_t.{ completion_item_label = alias; @@ -137,7 +137,7 @@ let completions index logger project_root file_path file_contents line column = the current file *) let toplevel = current_uri_opt - |> opt_bind (fun uri -> Index.find_opt uri index) + |> opt_bind (fun uri -> DI.lookup_module uri index) |> Lib.Option.map (List.map item_of_ide_decl) |> Lib.Fun.flip Lib.Option.get [] in imported @@ -147,7 +147,7 @@ let completions index logger project_root file_path file_contents line column = (* Without an alias but with a prefix we filter the toplevel idenfiers of the current module *) current_uri_opt - |> opt_bind (fun uri -> Index.find_opt uri index) + |> opt_bind (fun uri -> DI.lookup_module uri index) |> Lib.Option.map (fun decls -> decls |> List.filter (has_prefix prefix) @@ -159,7 +159,7 @@ let completions index logger project_root file_path file_contents line column = |> List.find_opt (fun (mn, _) -> String.equal mn alias) in match module_path with | Some mp -> - (match Index.find_opt (snd mp) index with + (match DI.lookup_module (snd mp) index with | Some decls -> decls |> List.filter (has_prefix prefix) diff --git a/src/languageServer/declaration_index.ml b/src/languageServer/declaration_index.ml index f1342bded64..231cf5bc562 100644 --- a/src/languageServer/declaration_index.ml +++ b/src/languageServer/declaration_index.ml @@ -3,8 +3,6 @@ open Mo_def open Source open Syntax -let flat_map f xs = List.flatten (List.map f xs) - type value_decl = { name : string; typ: Type.typ; @@ -52,7 +50,24 @@ let name_of_ide_decl (d : ide_decl) : string = | TypeDecl ty -> ty.name module Index = Map.Make(String) -type declaration_index = (ide_decl list) Index.t +type t = ide_decl list Index.t + +type path = string +let lookup_module + (path : path) + (index : t) + : ide_decl list option = + match Pipeline.ResolveImport.match_package_name path with + | None -> Index.find_opt path index + | Some (pkg, path) -> + Lib.Option.bind + (List.find_opt + (fun (name, _) -> pkg = name) + !Mo_config.Flags.package_urls) + (fun (_, pkg_path) -> + Index.find_opt (Filename.concat pkg_path path) index) + +let empty : t = Index.empty module PatternMap = Map.Make(String) type pattern_map = Source.region PatternMap.t @@ -153,7 +168,7 @@ let populate_definitions | Some lib -> List.map (find_def lib) decls -let make_index_inner vfs entry_points : declaration_index Diag.result = +let make_index_inner vfs entry_points : t Diag.result = Pipeline.load_progs (Vfs.parse_file vfs) entry_points @@ -171,6 +186,6 @@ let make_index_inner vfs entry_points : declaration_index Diag.result = scope.Scope.lib_env Index.empty) -let make_index vfs entry_points : declaration_index Diag.result = +let make_index vfs entry_points : t Diag.result = (* TODO(Christoph): Actually handle errors here *) try make_index_inner vfs entry_points with _ -> Diag.return Index.empty diff --git a/src/languageServer/declaration_index.mli b/src/languageServer/declaration_index.mli new file mode 100644 index 00000000000..edf8149b679 --- /dev/null +++ b/src/languageServer/declaration_index.mli @@ -0,0 +1,30 @@ +open Source +open Mo_types + +type t +val empty : t +val string_of_index : t -> string + +type value_decl = { + name : string; + typ: Type.typ; + definition: region option; + } + +type type_decl = { + name : string; + typ: Type.con; + definition: region option; + } + +type ide_decl = + | ValueDecl of value_decl + | TypeDecl of type_decl + +val string_of_ide_decl : ide_decl -> string +val name_of_ide_decl : ide_decl -> string + +type path = string +val lookup_module : path -> t -> ide_decl list option + +val make_index : Vfs.t -> string list -> t Diag.result diff --git a/src/languageServer/definition.ml b/src/languageServer/definition.ml index 718579df563..315b5e3a375 100644 --- a/src/languageServer/definition.ml +++ b/src/languageServer/definition.ml @@ -1,5 +1,5 @@ module Lsp = Lsp.Lsp_t -open Declaration_index +module DI = Declaration_index let position_of_pos (pos : Source.pos) : Lsp.position = Lsp. (* The LSP spec requires zero-based positions *) @@ -12,15 +12,15 @@ let range_of_region (at : Source.region) : Lsp.range = Lsp. range_end_ = position_of_pos at.Source.right; } -let find_named (name : string) : ide_decl list -> Source.region option = +let find_named (name : string) : DI.ide_decl list -> Source.region option = Lib.List.first_opt (function - | ValueDecl value -> - if String.equal value.name name - then value.definition + | DI.ValueDecl value -> + if String.equal value.DI.name name + then value.DI.definition else None - | TypeDecl typ -> - if String.equal typ.name name - then typ.definition + | DI.TypeDecl typ -> + if String.equal typ.DI.name name + then typ.DI.definition else None) let opt_bind f = function @@ -34,6 +34,7 @@ let definition_handler project_root file_path = let result = + let open Source_file in Lib.Option.bind (Source_file.identifier_at_pos project_root @@ -41,23 +42,26 @@ let definition_handler file_contents position) (function - | Source_file.Alias _ -> None - | Source_file.Unresolved _ -> None - | Source_file.Resolved resolved -> - Index.find_opt resolved.Source_file.path index - |> opt_bind (find_named resolved.Source_file.ident) - |> Lib.Option.map (fun loc -> (resolved.Source_file.path, loc)) - | Source_file.Ident ident -> - Pipeline__.File_path.relative_to project_root file_path + | Alias _ -> None + | Unresolved _ -> None + | Resolved resolved -> + DI.lookup_module resolved.path index + |> opt_bind (find_named resolved.ident) + |> Lib.Option.map (fun loc -> (resolved.path, loc)) + | Ident ident -> + Pipeline.FilePath.relative_to project_root file_path |> opt_bind (fun uri -> - Index.find_opt uri index + DI.lookup_module uri index |> opt_bind (find_named ident) |> Lib.Option.map (fun loc -> (uri, loc)) )) in let location = Lib.Option.map (fun (path, region) -> Lsp. - { location_uri = Vfs.uri_from_file path; + { location_uri = + if Source_file.is_package_path path + then Lib.Option.value (Source_file.uri_for_package path) + else Vfs.uri_from_file path; location_range = range_of_region region }) result in `TextDocumentDefinitionResponse location diff --git a/src/languageServer/dune b/src/languageServer/dune index b9a31912258..58f89fec479 100644 --- a/src/languageServer/dune +++ b/src/languageServer/dune @@ -1,6 +1,6 @@ (library (name languageServer) - (libraries lib lang_utils lsp pipeline) + (libraries lib lang_utils lsp pipeline mo_config) (inline_tests) (preprocess (pps ppx_inline_test)) (flags (:standard -w -48)) diff --git a/src/languageServer/hover.ml b/src/languageServer/hover.ml index c78520119f0..835fc1a9747 100644 --- a/src/languageServer/hover.ml +++ b/src/languageServer/hover.ml @@ -25,7 +25,7 @@ let hover_handler index position file_contents project_root file_path = | Source_file.Alias (_, path) -> Some Lsp.{ hover_result_contents = markup_content path } | Source_file.Resolved resolved -> - Index.find_opt resolved.Source_file.path index + lookup_module resolved.Source_file.path index |> Lib.Fun.flip Lib.Option.bind (fun decls -> List.find_opt (fun d -> name_of_ide_decl d = resolved.Source_file.ident) diff --git a/src/languageServer/languageServer.ml b/src/languageServer/languageServer.ml index 851193ac969..f50185bec91 100644 --- a/src/languageServer/languageServer.ml +++ b/src/languageServer/languageServer.ml @@ -36,9 +36,7 @@ module Channel = struct print_string cl; print_string "\r\n\r\n"; print_string out; - flush stdout; - log_to_file oc (label ^ "_length") cl; - log_to_file oc label out + flush stdout let send_response (oc : out_channel) : string -> unit = send oc "response" let send_notification (oc : out_channel) : string -> unit = send oc "notification" @@ -111,12 +109,11 @@ let start entry_point debug = let ix = match Declaration_index.make_index !vfs [entry_point] with | Error(err) -> List.iter (fun e -> log_to_file "Error" (Diag.string_of_message e)) err; - Declaration_index.Index.empty + Declaration_index.empty | Ok((ix, _)) -> ix in ref ix in let rec loop () = let clength = read_line () in - log_to_file "content-length" clength; let cl = "Content-Length: " in let cll = String.length cl in let num = @@ -129,8 +126,6 @@ let start entry_point debug = let buffer = Buffer.create num in Buffer.add_channel buffer stdin num; let raw = String.trim (Buffer.contents buffer) in - log_to_file "raw" raw; - let message = Lsp_j.incoming_message_of_string raw in let message_id = message.Lsp_t.incoming_message_id in @@ -243,7 +238,7 @@ let start entry_point debug = (* Notification messages *) | (None, `Initialized _) -> - show_message Lsp.MessageType.Info "Language server initialized" + show_message Lsp.MessageType.Info "Motoko LS initialized"; | (Some id, `Shutdown _) -> shutdown := true; diff --git a/src/languageServer/source_file.ml b/src/languageServer/source_file.ml index 597736b6f7b..3ae4cf324dc 100644 --- a/src/languageServer/source_file.ml +++ b/src/languageServer/source_file.ml @@ -39,15 +39,35 @@ let cursor_target_at_pos | _ -> loop (next ()) in try loop (next ()) with _ -> None -let import_relative_to_project_root root module_path dependency = - match Pipeline__.File_path.relative_to root module_path with +let is_package_path (path : string) = + Lib.Option.is_some (Pipeline.ResolveImport.match_package_name path) + +let uri_for_package (path : string) = + match Pipeline.ResolveImport.match_package_name path with | None -> None - | Some root_to_module -> - root_to_module - |> Filename.dirname - |> Lib.Fun.flip Filename.concat dependency - |> Pipeline__.File_path.normalise - |> Lib.Option.some + | Some (pkg, path) -> + begin match + List.find_opt + (fun (name, _) -> pkg = name) + !Mo_config.Flags.package_urls with + | None -> None + | Some (_, pkg_path) -> + (* Resolved package paths are always absolute *) + Some ("file://" ^ Filename.concat pkg_path path) + end + +let import_relative_to_project_root root module_path dependency = + if is_package_path dependency + then Some dependency + else + match Pipeline.FilePath.relative_to root module_path with + | None -> None + | Some root_to_module -> + root_to_module + |> Filename.dirname + |> Lib.Fun.flip Filename.concat dependency + |> Pipeline.FilePath.normalise + |> Lib.Option.some (* Given the source of a module, figure out under what names what modules have been imported. Normalizes the imported modules diff --git a/src/languageServer/source_file_tests.ml b/src/languageServer/source_file_tests.ml index a5eeae5f79f..eab90417053 100644 --- a/src/languageServer/source_file_tests.ml +++ b/src/languageServer/source_file_tests.ml @@ -70,6 +70,13 @@ let%test "it parses a simple module header" = "import P \"lib/prelude.mo\"" ["P", "src/lib/prelude.mo"] +let%test "it parses a simple module header with package paths" = + parse_module_header_test_case + "/project" + "/project/src/Main.mo" + "import P \"mo:stdlib/prelude.mo\"" + ["P", "mo:stdlib/prelude.mo"] + let%test "it parses a simple module header" = parse_module_header_test_case "/project" diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index d8582fd5bbd..c254d4658a3 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -10,6 +10,9 @@ open Mo_config open Printf +module ResolveImport = Resolve_import +module FilePath = File_path + type stat_env = Scope.t type dyn_env = Interpret.scope type env = stat_env * dyn_env @@ -104,12 +107,12 @@ let parse_file filename : parse_result = (* Import file name resolution *) -type resolve_result = (Syntax.prog * Resolve_import.S.t) Diag.result +type resolve_result = (Syntax.prog * ResolveImport.S.t) Diag.result let resolve_prog (prog, base) : resolve_result = Diag.map (fun libs -> (prog, libs)) - (Resolve_import.resolve !Flags.package_urls prog base) + (ResolveImport.resolve !Flags.package_urls prog base) let resolve_progs = Diag.traverse resolve_prog @@ -118,7 +121,7 @@ let resolve_progs = let print_deps (file : string) : unit = let (prog, _) = Diag.run (parse_file file) in - let imports = Resolve_import.collect_imports prog in + let imports = ResolveImport.collect_imports prog in List.iter print_endline imports (* Checking *) @@ -217,7 +220,7 @@ let chase_imports parsefn senv0 imports : (Syntax.lib list * Scope.scope) Diag.r * We accumulate the resulting libraries in reverse order, for O(1) appending. *) - let open Resolve_import.S in + let open ResolveImport.S in let pending = ref empty in let senv = ref senv0 in let libs = ref [] in @@ -234,7 +237,7 @@ let chase_imports parsefn senv0 imports : (Syntax.lib list * Scope.scope) Diag.r pending := add f !pending; Diag.bind (parsefn f) (fun (prog, base) -> Diag.bind (Static.prog prog) (fun () -> - Diag.bind (Resolve_import.resolve !Flags.package_urls prog base) (fun more_imports -> + Diag.bind (ResolveImport.resolve !Flags.package_urls prog base) (fun more_imports -> Diag.bind (go_set more_imports) (fun () -> let lib = lib_of_prog f prog in Diag.bind (check_lib !senv lib) (fun sscope -> @@ -253,7 +256,7 @@ let load_progs parsefn files senv : load_result = Diag.bind (resolve_progs parsed) (fun rs -> let progs' = List.map fst rs in let libs = - List.fold_left Resolve_import.S.union Resolve_import.S.empty + List.fold_left ResolveImport.S.union ResolveImport.S.empty (List.map snd rs) in Diag.bind (chase_imports parsefn senv libs) (fun (libs, senv') -> Diag.bind (check_progs senv' progs') (fun senv'' -> diff --git a/src/pipeline/pipeline.mli b/src/pipeline/pipeline.mli index 51f8054e248..a78e0762444 100644 --- a/src/pipeline/pipeline.mli +++ b/src/pipeline/pipeline.mli @@ -2,6 +2,9 @@ open Mo_def open Mo_config open Mo_types +module ResolveImport = Resolve_import +module FilePath = File_path + type parse_fn = string -> (Syntax.prog * string) Diag.result val parse_file: parse_fn val parse_string: string -> parse_fn diff --git a/src/pipeline/resolve_import.mli b/src/pipeline/resolve_import.mli index 8f69e1fed55..5bcf24c969d 100644 --- a/src/pipeline/resolve_import.mli +++ b/src/pipeline/resolve_import.mli @@ -6,3 +6,4 @@ type package_urls = (string * string) list val collect_imports : Syntax.prog -> string list val resolve : package_urls -> Syntax.prog -> string -> S.t Diag.result +val match_package_name : string -> (string * string) option diff --git a/test/lsp-int/Main.hs b/test/lsp-int/Main.hs index 895d479a6f5..c5795584378 100644 --- a/test/lsp-int/Main.hs +++ b/test/lsp-int/Main.hs @@ -5,6 +5,8 @@ module Main where +import Prelude hiding (log) + import qualified Control.Exception as Exception import Control.Lens ((^.)) import Control.Monad (unless) @@ -12,9 +14,9 @@ import Control.Monad.IO.Class (liftIO) import Data.Default import Data.Text (Text) import Language.Haskell.LSP.Test hiding (message) -import Language.Haskell.LSP.Types (TextDocumentIdentifier(..), Position(..), HoverContents(..), MarkupContent(..), MarkupKind(..), TextEdit(..), Range(..), DidSaveTextDocumentParams(..), ClientMethod(..)) +import Language.Haskell.LSP.Types (TextDocumentIdentifier(..), Position(..), HoverContents(..), MarkupContent(..), MarkupKind(..), TextEdit(..), Range(..), DidSaveTextDocumentParams(..), ClientMethod(..), Diagnostic(..)) import Language.Haskell.LSP.Types.Lens (contents, label, detail, message) -import System.Directory (setCurrentDirectory) +import System.Directory (setCurrentDirectory, makeAbsolute) import System.Environment (getArgs) import System.Exit (exitFailure) import System.IO (hPutStr, stderr) @@ -42,6 +44,13 @@ hoverTestCase doc pos expected = do actual <- getHover doc pos liftIO (shouldBe (fmap (^.contents) actual) expected) +-- | Discards all empty diagnostic reports (as those are merely used +-- to clear out old reports) +waitForActualDiagnostics :: Session [Diagnostic] +waitForActualDiagnostics = do + diags <- waitForDiagnostics + if null diags then waitForActualDiagnostics else pure diags + plainMarkup :: Text -> Maybe HoverContents plainMarkup t = Just @@ -50,18 +59,22 @@ plainMarkup t = , _value = t }) -handleHUnitFailure :: forall a. IO a -> IO a -handleHUnitFailure act = do +handleHUnitFailure :: forall a. String -> IO a -> IO a +handleHUnitFailure project act = do result :: Either HUnitFailure a <- Exception.try act case result of Right res -> pure res Left (HUnitFailure _ reason) -> do + hPutStr stderr =<< readFile (project <> "/ls.log") hPutStr stderr (formatFailureReason reason) exitFailure +log :: String -> Session () +log = liftIO . putStrLn + main :: IO () -main = handleHUnitFailure $ do +main = do args <- getArgs unless (length args == 2) (putStrLn @@ -69,58 +82,95 @@ main = handleHUnitFailure $ do \the path to the mo-ide binary and the path to\ \the test project it's supposed to run in") let [mo_ide, project] = args + project <- makeAbsolute project setCurrentDirectory project - runSession (mo_ide <> " --canister-main app.mo --debug") fullCaps "." $ do - initRes <- initializeResponse - doc <- openDoc "ListClient.mo" "motoko" - hoverTestCase - doc - (Position 13 11) - (plainMarkup "push : (T, List) -> List") - hoverTestCase - doc - (Position 16 11) - (plainMarkup "pop : List -> (?T, List)") - hoverTestCase - doc - (Position 50 50) - Nothing - -- 14 | List.push(x, s); - -- ==> 14 | List.pus - let edit = TextEdit (Range (Position 13 11) (Position 13 27)) "pus" - _ <- applyEdit doc edit - completionTestCase - doc - -- 14 | List.pus| - (Position 13 14) - [("push",Just "(T, List) -> List")] - closeDoc doc - doc <- openDoc "ListClient.mo" "motoko" - -- 1 | import List - -- ==> 1 | ort List - let edit = TextEdit (Range (Position 0 1) (Position 0 3)) "" - _ <- applyEdit doc edit - sendNotification TextDocumentDidSave (DidSaveTextDocumentParams doc) - (diagnostic:_) <- waitForDiagnostics - liftIO (diagnostic^.message `shouldBe` "unexpected token") - closeDoc doc + handleHUnitFailure project $ do + putStrLn "Starting the session" + runSession + (mo_ide + <> " --canister-main app.mo --debug" + <> " --package mydep " <> project <> "/mydependency/") + fullCaps + "." $ do + log "Initializing" + initRes <- initializeResponse + log "Hover tests" + doc <- openDoc "ListClient.mo" "motoko" + hoverTestCase + doc + (Position 13 11) + (plainMarkup "push : (T, List) -> List") + hoverTestCase + doc + (Position 16 11) + (plainMarkup "pop : List -> (?T, List)") + hoverTestCase + doc + (Position 50 50) + Nothing + log "Completion tests" + -- 14 | List.push(x, s); + -- ==> 14 | List.pus + let edit = TextEdit (Range (Position 13 11) (Position 13 27)) "pus" + _ <- applyEdit doc edit + completionTestCase + doc + -- 14 | List.pus| + (Position 13 14) + [("push",Just "(T, List) -> List")] + closeDoc doc + doc <- openDoc "ListClient.mo" "motoko" + -- 1 | import List + -- ==> 1 | ort List + let edit = TextEdit (Range (Position 0 1) (Position 0 3)) "" + _ <- applyEdit doc edit + sendNotification TextDocumentDidSave (DidSaveTextDocumentParams doc) + (diagnostic:_) <- waitForDiagnostics + liftIO (diagnostic^.message `shouldBe` "unexpected token") + closeDoc doc + + log "Lexer failures don't crash the server" + doc <- openDoc "ListClient.mo" "motoko" + -- Creates an unclosed text literal, which triggers a lexer error + let edit = TextEdit (Range (Position 0 1) (Position 0 3)) "\"hello" + _ <- applyEdit doc edit + -- We're just testing that the server doesn't crash here + getCompletions doc (Position 0 0) + getHover doc (Position 0 0) + closeDoc doc + + log "Finds errors in non-saved files" + -- It finds errors in transitive modules that have been changed in + -- the vfs but not yet stored to disc + doc <- openDoc "ListClient.mo" "motoko" + let edit = TextEdit (Range (Position 0 1) (Position 0 3)) "" + _ <- applyEdit doc edit + appDoc <- openDoc "app.mo" "motoko" + sendNotification TextDocumentDidSave (DidSaveTextDocumentParams appDoc) + diagnostic:_ <- waitForActualDiagnostics + liftIO (diagnostic^.message `shouldBe` "unexpected token") + closeDoc doc + closeDoc appDoc - doc <- openDoc "ListClient.mo" "motoko" - -- Creates an unclosed text literal, which triggers a lexer error - let edit = TextEdit (Range (Position 0 1) (Position 0 3)) "\"hello" - _ <- applyEdit doc edit - -- We're just testing that the server doesn't crash here - getCompletions doc (Position 0 0) - getHover doc (Position 0 0) - closeDoc doc + log "Rebuilding with package paths" + -- It knows how to handle package paths for rebuilding, and also + -- for completions + doc <- openDoc "app.mo" "motoko" + let edit = TextEdit (Range (Position 1 0) (Position 1 0)) "\nimport MyDep \"mo:mydep/broken.mo\"" + _ <- applyEdit doc edit + sendNotification TextDocumentDidSave (DidSaveTextDocumentParams doc) + [diag] <- waitForActualDiagnostics + liftIO (diag^.message `shouldBe` "operator not defined for operand types\n Text\nand\n Nat") - -- It finds errors in transitive modules that have been changed in - -- the vfs but not yet stored to disc - doc <- openDoc "ListClient.mo" "motoko" - let edit = TextEdit (Range (Position 0 1) (Position 0 3)) "" - _ <- applyEdit doc edit - appDoc <- openDoc "app.mo" "motoko" - sendNotification TextDocumentDidSave (DidSaveTextDocumentParams appDoc) - diags <- waitForDiagnostics - (diagnostic:_) <- waitForDiagnostics - liftIO (diagnostic^.message `shouldBe` "unexpected token") + log "Completions from package paths" + -- Imports the non-broken dependency module + let edit2 = TextEdit (Range (Position 2 0) (Position 3 0)) "\nimport MyDep \"mo:mydep/lib.mo\"" + _ <- applyEdit doc edit2 + sendNotification TextDocumentDidSave (DidSaveTextDocumentParams doc) + let edit3 = TextEdit (Range (Position 3 0) (Position 3 0)) "\nMyDep." + _ <- applyEdit doc edit3 + completionTestCase + doc + -- MyDep.| + (Position 4 6) + [("print_hello", Just "() -> Text")] diff --git a/test/lsp-int/test-project/mydependency/broken.mo b/test/lsp-int/test-project/mydependency/broken.mo new file mode 100644 index 00000000000..b6bfc5278d1 --- /dev/null +++ b/test/lsp-int/test-project/mydependency/broken.mo @@ -0,0 +1,5 @@ +module { + public func print_hello(): Text { + debug_show("hello" + 1) + } +} diff --git a/test/lsp-int/test-project/mydependency/lib.mo b/test/lsp-int/test-project/mydependency/lib.mo new file mode 100644 index 00000000000..0c23d2c7b95 --- /dev/null +++ b/test/lsp-int/test-project/mydependency/lib.mo @@ -0,0 +1,5 @@ +module { + public func print_hello(): Text { + debug_show("hello") + } +} From a3afff12ae81a118439f4711db1e9caa6275fd49 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 12 Dec 2019 16:16:52 +0100 Subject: [PATCH 0817/1176] Add IR.Construct.blobE (#1014) just like there is `textE`, to simplify #1001. --- src/ir_def/construct.ml | 8 +++++++- src/ir_def/construct.mli | 1 + src/mo_types/type.ml | 1 + src/mo_types/type.mli | 1 + 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index 98f985c13b6..b2ad7cfbf2c 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -169,7 +169,13 @@ let blockE decs exp = let textE s = { it = LitE (TextLit s); at = no_region; - note = { note_typ = T.Prim T.Text; note_eff = T.Triv } + note = { note_typ = T.text; note_eff = T.Triv } + } + +let blobE s = + { it = LitE (BlobLit s); + at = no_region; + note = { note_typ = T.blob; note_eff = T.Triv } } let unitE = diff --git a/src/ir_def/construct.mli b/src/ir_def/construct.mli index 3efe3c68acc..cab2e0a80dd 100644 --- a/src/ir_def/construct.mli +++ b/src/ir_def/construct.mli @@ -48,6 +48,7 @@ val ic_callE : exp -> exp -> exp -> exp -> exp val projE : exp -> int -> exp val blockE : dec list -> exp -> exp val textE : string -> exp +val blobE : string -> exp val letE : var -> exp -> exp -> exp val ignoreE : exp -> exp diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index f2209e682f0..cb20b31c83a 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -92,6 +92,7 @@ let bool = Prim Bool let nat = Prim Nat let int = Prim Int let text = Prim Text +let blob = Prim Blob let error = Prim Error let char = Prim Char diff --git a/src/mo_types/type.mli b/src/mo_types/type.mli index d48d837b388..1e615bd05d8 100644 --- a/src/mo_types/type.mli +++ b/src/mo_types/type.mli @@ -69,6 +69,7 @@ val bool : typ val nat : typ val int : typ val text : typ +val blob : typ val error : typ val char : typ From 11e50959ce0401c5a5337819f5fd64391c51c812 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 12 Dec 2019 17:47:58 +0100 Subject: [PATCH 0818/1176] =?UTF-8?q?Closure=20table:=20Print=20error=20me?= =?UTF-8?q?ssage=20if=20entry=20isn=E2=80=99t=20there=20(#1015)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Closure table: Print error message if entry isn’t there this might be helpful to debug cases where the system violates the “at most one callback” guarantee. * Fix tests * Update rts/closure-table.c Co-Authored-By: Gabor Greif * Update rts/rts.h * Update rts/test_rts.c Co-Authored-By: Gabor Greif * Update rts/test_rts.c Co-Authored-By: Gabor Greif --- rts/closure-table.c | 8 ++++++++ rts/rts.h | 2 ++ rts/test_rts.c | 8 ++++---- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/rts/closure-table.c b/rts/closure-table.c index cadd3fe7f93..44587567dbc 100644 --- a/rts/closure-table.c +++ b/rts/closure-table.c @@ -73,6 +73,10 @@ export uint32_t remember_closure(as_ptr cls) { else if (free_slot == FULL) double_closure_table(); + if (!IS_SKEWED(cls)) + // we could support this, but then we couldn't detect a double recall_closure + rts_trap_with("remember_closure: Storing unboxed literals not supports"); + uint32_t idx = free_slot >> 2; free_slot = ARRAY_FIELD(table, idx); ARRAY_FIELD(table, idx) = cls; @@ -90,6 +94,10 @@ export as_ptr recall_closure(uint32_t idx) { ARRAY_FIELD(table, idx) = free_slot; free_slot = idx << 2; n_closures--; + + if (!IS_SKEWED(cls)) + rts_trap_with("recall_closure: Closure index not in table"); + return cls; } diff --git a/rts/rts.h b/rts/rts.h index 1f26e4fcaa3..849eeebcf3f 100644 --- a/rts/rts.h +++ b/rts/rts.h @@ -20,6 +20,8 @@ _not_ encode that a word is 4 bytes! typedef intptr_t as_ptr; #define SKEW(p) ((as_ptr)p-1) #define UNSKEW(p) ((size_t *)((as_ptr)p+1)) +#define IS_SKEWED(p) ((p & 0x02)==0x02) + #define FIELD(p,n) (UNSKEW(p)[n]) #define TAG(p) FIELD(p,0) diff --git a/rts/test_rts.c b/rts/test_rts.c index 2ee59b9b5de..96b9276f2bc 100644 --- a/rts/test_rts.c +++ b/rts/test_rts.c @@ -141,19 +141,19 @@ int main () { ret = EXIT_FAILURE; } for (int i = 0; i=0; i--) { - assert(reference[i] == recall_closure(i),"Recall went wrong\n"); + assert((i<<2)-1 == recall_closure(reference[i]), "Recall went wrong\n"); assert(closure_count() == i, "Closure count wrong\n"); } From f056cbc01fe23d9880cba2b4db63b90105c11076 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 12 Dec 2019 18:44:32 +0100 Subject: [PATCH 0819/1176] IR: Introduce lexp (#1009) * IR: Introduce lexp I was never quite happy about the partial functions `compile_lexp` and `c_assign`, and when working on #1004, this got in the way too. So let's be more honest and create a data type `lexp` for the kind of things that may appear on the left of `:=`, as I think we dicussed on some slack discussion once. * Traverse all annotations in async.ml * Apply suggestions from code review Co-Authored-By: Claudio Russo * Simplify Check_ir.check_lexp --- src/codegen/compile.ml | 13 ++++---- src/ir_def/arrange_ir.ml | 7 +++- src/ir_def/check_ir.ml | 53 +++++++++++++++++++++++++----- src/ir_def/construct.ml | 14 ++++++-- src/ir_def/freevars.ml | 7 +++- src/ir_def/ir.ml | 9 ++++- src/ir_def/ir_effect.ml | 4 +-- src/ir_interpreter/interpret_ir.ml | 29 ++++++++++++++-- src/ir_passes/async.ml | 15 ++++++++- src/ir_passes/await.ml | 27 +++++++++------ src/ir_passes/rename.ml | 8 ++++- src/ir_passes/show.ml | 12 +++++-- src/ir_passes/tailcall.ml | 9 ++++- src/lowering/desugar.ml | 14 +++++++- 14 files changed, 179 insertions(+), 42 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index deb3cd9dbf4..8eb6ab41f28 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -5700,24 +5700,23 @@ let compile_load_field env typ name = (* compile_lexp is used for expressions on the left of an assignment operator, produces some code (with side effect), and some pure code *) -let rec compile_lexp (env : E.t) ae exp = - (fun (code,fill_code) -> (G.with_region exp.at code, G.with_region exp.at fill_code)) @@ - match exp.it with - | VarE var -> +let rec compile_lexp (env : E.t) ae lexp = + (fun (code, fill_code) -> (G.with_region lexp.at code, G.with_region lexp.at fill_code)) @@ + match lexp.it with + | VarLE var -> G.nop, Var.set_val env ae var - | IdxE (e1,e2) -> + | IdxLE (e1, e2) -> compile_exp_vanilla env ae e1 ^^ (* offset to array *) compile_exp_vanilla env ae e2 ^^ (* idx *) BigNum.to_word32 env ^^ Arr.idx env, store_ptr - | DotE (e, n) -> + | DotLE (e, n) -> compile_exp_vanilla env ae e ^^ (* Only real objects have mutable fields, no need to branch on the tag *) Object.idx env e.note.note_typ n, store_ptr - | _ -> todo "compile_lexp" (Arrange_ir.exp exp) (E.trap_with env "TODO: compile_lexp", G.nop) and compile_exp (env : E.t) ae exp = (fun (sr,code) -> (sr, G.with_region exp.at code)) @@ diff --git a/src/ir_def/arrange_ir.ml b/src/ir_def/arrange_ir.ml index 81e7ee16681..58213b2a7f9 100644 --- a/src/ir_def/arrange_ir.ml +++ b/src/ir_def/arrange_ir.ml @@ -20,7 +20,7 @@ let rec exp e = match e.it with | ProjE (e, i) -> "ProjE" $$ [exp e; Atom (string_of_int i)] | DotE (e, n) -> "DotE" $$ [exp e; Atom n] | ActorDotE (e, n) -> "ActorDotE" $$ [exp e; Atom n] - | AssignE (e1, e2) -> "AssignE" $$ [exp e1; exp e2] + | AssignE (le1, e2) -> "AssignE" $$ [lexp le1; exp e2] | ArrayE (m, t, es) -> "ArrayE" $$ [mut m; typ t] @ List.map exp es | IdxE (e1, e2) -> "IdxE" $$ [exp e1; exp e2] | CallE (e1, ts, e2) -> "CallE" $$ [exp e1] @ List.map typ ts @ [exp e2] @@ -47,6 +47,11 @@ let rec exp e = match e.it with | ThrowE e -> "ThrowE" $$ [exp e] | TryE (e, cs) -> "TryE" $$ [exp e] @ List.map case cs +and lexp le = match le.it with + | VarLE i -> "VarLE" $$ [id i] + | IdxLE (e1, e2) -> "IdxLE" $$ [exp e1; exp e2] + | DotLE (e1, n) -> "DotLE" $$ [exp e1; Atom n] + and fields fs = List.fold_left (fun flds (f : field) -> (f.it.name $$ [ id f.it.var ]):: flds) [] fs and args = function diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index e61e3bdcdad..60feeba2d98 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -432,16 +432,11 @@ let rec check_exp env (exp:Ir.exp) : unit = error env exp1.at "field name %s does not exist in type\n %s" n (T.string_of_typ_expand t1) end - | AssignE (exp1, exp2) -> - begin - match exp1.it with - | (VarE _ | DotE _ | IdxE _) -> () - | _ -> error env exp.at "unexpected assignment target" - end; - check_exp env exp1; + | AssignE (lexp1, exp2) -> + check_lexp env lexp1; check_exp env exp2; - let t2 = try T.as_mut (typ exp1) with - Invalid_argument _ -> error env exp.at "expected mutable assignment target" + let t2 = try T.as_mut lexp1.note with + Invalid_argument _ -> error env exp.at "expected mutable assignment target" in typ exp2 <: t2; T.unit <: t @@ -646,6 +641,46 @@ let rec check_exp env (exp:Ir.exp) : unit = t0 <: t + +and check_lexp env (lexp:Ir.lexp) : unit = + (* helpers *) + let check p = check env lexp.at p in + let (<:) t1 t2 = check_sub env lexp.at t1 t2 in + (* check type annotation *) + let t = lexp.note in + check_typ env t; + (* check typing *) + match lexp.it with + | VarLE id -> + let t0 = try T.Env.find id env.vals with + | Not_found -> error env lexp.at "unbound variable %s" id + in + t0 <: t + | DotLE (exp1, n) -> + begin + let t1 = typ exp1 in + let sort, tfs = + try T.as_obj_sub [n] t1 with Invalid_argument _ -> + error env exp1.at "expected object type, but expression produces type\n %s" + (T.string_of_typ_expand t1) + in + check (sort <> T.Actor) "sort mismatch"; + try T.lookup_val_field n tfs <: t with Invalid_argument _ -> + error env exp1.at "field name %s does not exist in type\n %s" + n (T.string_of_typ_expand t1) + end + | IdxLE (exp1, exp2) -> + check_exp env exp1; + check_exp env exp2; + let t1 = T.promote (typ exp1) in + let t2 = try T.as_array_sub t1 with + | Invalid_argument _ -> + error env exp1.at "expected array type, but expression produces type\n %s" + (T.string_of_typ_expand t1) + in + typ exp2 <: T.nat; + t2 <: t + (* Cases *) and check_cases env t_pat t cases = diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index b2ad7cfbf2c..6c26b42b6e1 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -299,11 +299,21 @@ let immuteE e = } +(* just like we use exp also for vars, we use exp also for lvalues +in the constructor DSL *) +let lexp_of_exp' = function + | VarE i -> VarLE i + | DotE (e1,n) -> DotLE (e1, n) + | IdxE (e1,e2) -> IdxLE (e1, e2) + | _ -> failwith "Impossible: lexp_of_exp" + +let lexp_of_exp (e:exp) = { e with it = lexp_of_exp' e.it; note = typ e } + let assignE exp1 exp2 = assert (T.is_mut (typ exp1)); - { it = AssignE (exp1, exp2); + { it = AssignE (lexp_of_exp exp1, exp2); at = no_region; - note = { note_eff = Ir_effect.max_eff (eff exp1) (eff exp2); + note = { note_eff = eff exp2; note_typ = T.unit } } diff --git a/src/ir_def/freevars.ml b/src/ir_def/freevars.ml index 1ae023fc615..60853fd54a9 100644 --- a/src/ir_def/freevars.ml +++ b/src/ir_def/freevars.ml @@ -64,7 +64,7 @@ let rec exp e : f = match e.it with | ProjE (e, i) -> exp e | DotE (e, i) -> exp e | ActorDotE (e, i) -> exp e - | AssignE (e1, e2) -> exps [e1; e2] + | AssignE (e1, e2) -> lexp e1 ++ exp e2 | ArrayE (m, t, es) -> exps es | IdxE (e1, e2) -> exps [e1; e2] | CallE (e1, ts, e2) -> exps [e1; e2] @@ -97,6 +97,11 @@ and arg a : fd = (M.empty, S.singleton a.it) and args as_ : fd = union_binders arg as_ +and lexp le : f = match le.it with + | VarLE i -> M.singleton i {captured = false} + | DotLE (e1, _) -> exp e1 + | IdxLE (e1, e2) -> exps [e1; e2] + and pat p : fd = match p.it with | WildP -> (M.empty, S.empty) | VarP i -> (M.empty, S.singleton i) diff --git a/src/ir_def/ir.ml b/src/ir_def/ir.ml index 054cd45d4f1..ea7fe461ef8 100644 --- a/src/ir_def/ir.ml +++ b/src/ir_def/ir.ml @@ -71,7 +71,7 @@ and exp' = | TagE of id * exp (* variant injection *) | DotE of exp * Type.lab (* object projection *) | ActorDotE of exp * Type.lab (* actor field access *) - | AssignE of exp * exp (* assignment *) + | AssignE of lexp * exp (* assignment *) | ArrayE of mut * Type.typ * exp list (* array *) | IdxE of exp * exp (* array indexing *) | CallE of exp * Type.typ list * exp (* function call *) @@ -101,6 +101,13 @@ and field' = {name : Type.lab; var : id} (* the var is by reference, not by valu and case = case' Source.phrase and case' = {pat : pat; exp : exp} +and lexp = (lexp', Type.typ) Source.annotated_phrase +and lexp' = + | VarLE of id (* variable *) + | IdxLE of exp * exp (* array indexing *) + | DotLE of exp * Type.lab (* object projection *) + + and prim = | UnPrim of Type.typ * unop (* unary operator *) | BinPrim of Type.typ * binop (* binary operator *) diff --git a/src/ir_def/ir_effect.ml b/src/ir_def/ir_effect.ml index 731d98cc0ca..e8a2255f39a 100644 --- a/src/ir_def/ir_effect.ml +++ b/src/ir_def/ir_effect.ml @@ -37,10 +37,10 @@ let rec infer_effect_exp (exp: exp) : T.eff = | LabelE (_, _, exp1) | BreakE (_, exp1) | RetE exp1 - | LoopE exp1 -> + | LoopE exp1 + | AssignE (_, exp1) -> effect_exp exp1 | IdxE (exp1, exp2) - | AssignE (exp1, exp2) | CallE (exp1, _, exp2) -> let t1 = effect_exp exp1 in let t2 = effect_exp exp2 in diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index b8a1fa9e242..4adb536793f 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -412,10 +412,10 @@ and interpret_exp_mut env exp (k : V.value V.cont) = let fs = V.as_obj v1 in k (try find n fs with _ -> assert false) ) - | AssignE (exp1, exp2) -> - interpret_exp_mut env exp1 (fun v1 -> + | AssignE (lexp1, exp2) -> + interpret_lexp env lexp1 (fun v1 -> interpret_exp env exp2 (fun v2 -> - V.as_mut v1 := v2; k V.unit + v1 := v2; k V.unit ) ) | ArrayE (mut, _, exps) -> @@ -543,6 +543,29 @@ and interpret_exp_mut env exp (k : V.value V.cont) = | NewObjE (sort, fs, _) -> k (interpret_fields env fs) +and interpret_lexp env lexp (k : (V.value ref) V.cont) = + last_region := lexp.at; + last_env := env; + match lexp.it with + | VarLE id -> + (match Lib.Promise.value_opt (find id env.vals) with + | Some v -> k (V.as_mut v) + | None -> trap lexp.at "accessing identifier before its definition" + ) + | DotLE (exp1, n) -> + interpret_exp env exp1 (fun v1 -> + let fs = V.as_obj v1 in + k (V.as_mut (try find n fs with _ -> assert false)) + ) + | IdxLE (exp1, exp2) -> + interpret_exp env exp1 (fun v1 -> + interpret_exp env exp2 (fun v2 -> + k (V.as_mut + (try (V.as_array v1).(V.Int.to_int (V.as_int v2)) + with Invalid_argument s -> trap lexp.at "%s" s)) + ) + ) + and interpret_fields env fs = let ve = List.fold_left diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index 8206fd2d358..ceaac21f942 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -240,7 +240,7 @@ let transform mode env prog = | ActorDotE (exp1, id) -> ActorDotE (t_exp exp1, id) | AssignE (exp1, exp2) -> - AssignE (t_exp exp1, t_exp exp2) + AssignE (t_lexp exp1, t_exp exp2) | ArrayE (mut, t, exps) -> ArrayE (mut, t_typ t, List.map t_exp exps) | IdxE (exp1, exp2) -> @@ -387,6 +387,19 @@ let transform mode env prog = NewObjE (sort, t_fields ids, t_typ t) | SelfCallE _ -> assert false + and t_lexp lexp = + { it = t_lexp' lexp.it; + note = t_typ lexp.note; + at = lexp.at; + } + and t_lexp' (lexp':lexp') = + match lexp' with + | VarLE _ -> lexp' + | DotLE (exp1, id) -> + DotLE (t_exp exp1, id) + | IdxLE (exp1, exp2) -> + IdxLE (t_exp exp1, t_exp exp2) + and t_dec dec = { dec with it = t_dec' dec.it } and t_dec' dec' = diff --git a/src/ir_passes/await.ml b/src/ir_passes/await.ml index 92ba33c389d..a65529d2da7 100644 --- a/src/ir_passes/await.ml +++ b/src/ir_passes/await.ml @@ -79,7 +79,7 @@ and t_exp' context exp' = | ActorDotE (exp1, id) -> ActorDotE (t_exp context exp1, id) | AssignE (exp1, exp2) -> - AssignE (t_exp context exp1, t_exp context exp2) + AssignE (t_lexp context exp1, t_exp context exp2) | ArrayE (mut, typ, exps) -> ArrayE (mut, typ, List.map (t_exp context) exps) | IdxE (exp1, exp2) -> @@ -144,6 +144,14 @@ and t_exp' context exp' = | NewObjE (sort, ids, typ) -> exp' | SelfCallE _ -> assert false +and t_lexp context lexp = + { lexp with it = t_lexp' context lexp.it } +and t_lexp' context lexp' = + match lexp' with + | VarLE i -> VarLE i + | DotLE (exp1, id) -> DotLE (t_exp context exp1, id) + | IdxLE (exp1, exp2) -> IdxLE (t_exp context exp1, t_exp context exp2) + and t_dec context dec = {dec with it = t_dec' context dec.it} and t_dec' context dec' = @@ -228,20 +236,19 @@ and c_loop context k e1 = (c_exp context e1 (ContVar loop))] (loop -*- unitE) -and c_assign context k e exp1 exp2 = - match exp1.it with - | VarE _ -> - unary context k (fun v2 -> e (AssignE(exp1, v2))) exp2 - | DotE (exp11, id) -> +and c_assign context k e lexp1 exp2 = + match lexp1.it with + | VarLE _ -> + unary context k (fun v2 -> e (AssignE(lexp1, v2))) exp2 + | DotLE (exp11, id) -> binary context k (fun v11 v2 -> - e (AssignE ({exp1 with it = DotE (v11, id)}, v2))) exp11 exp2 - | IdxE (exp11, exp12) -> + e (AssignE ({lexp1 with it = DotLE (v11, id)}, v2))) exp11 exp2 + | IdxLE (exp11, exp12) -> nary context k (fun vs -> match vs with | [v11; v12; v2] -> - e (AssignE ({exp1 with it = IdxE (v11, v12)}, v2)) + e (AssignE ({lexp1 with it = IdxLE (v11, v12)}, v2)) | _ -> assert false) [exp11; exp12; exp2] - | _ -> assert false and c_exp context exp = c_exp' context exp diff --git a/src/ir_passes/rename.ml b/src/ir_passes/rename.ml index 319d3d5c1b9..83405c950c1 100644 --- a/src/ir_passes/rename.ml +++ b/src/ir_passes/rename.ml @@ -41,7 +41,7 @@ and exp' rho e = match e with in ActorE (i', ds', fields rho'' fs, t) | DotE (e, i) -> DotE (exp rho e, i) | ActorDotE (e, i) -> ActorDotE (exp rho e, i) - | AssignE (e1, e2) -> AssignE (exp rho e1, exp rho e2) + | AssignE (e1, e2) -> AssignE (lexp rho e1, exp rho e2) | ArrayE (m, t, es) -> ArrayE (m, t, exps rho es) | IdxE (e1, e2) -> IdxE (exp rho e1, exp rho e2) | CallE (e1, ts, e2) -> CallE (exp rho e1, ts, exp rho e2) @@ -72,6 +72,12 @@ and exp' rho e = match e with | SelfCallE (ts, e1, e2, e3) -> SelfCallE (ts, exp rho e1, exp rho e2, exp rho e3) +and lexp rho le = {le with it = lexp' rho le.it} +and lexp' rho = function + | VarLE i -> VarLE (id rho i) + | DotLE (e, i) -> DotLE (exp rho e, i) + | IdxLE (e1, e2) -> IdxLE (exp rho e1, exp rho e2) + and exps rho es = List.map (exp rho) es and fields rho fs = diff --git a/src/ir_passes/show.ml b/src/ir_passes/show.ml index 89138885e5d..fa5f11a1334 100644 --- a/src/ir_passes/show.ml +++ b/src/ir_passes/show.ml @@ -354,8 +354,8 @@ and t_exp' env = function DotE (t_exp env exp1, id) | ActorDotE (exp1, id) -> ActorDotE (t_exp env exp1, id) - | AssignE (exp1, exp2) -> - AssignE (t_exp env exp1, t_exp env exp2) + | AssignE (lexp1, exp2) -> + AssignE (t_lexp env lexp1, t_exp env exp2) | ArrayE (mut, t, exps) -> ArrayE (mut, t, t_exps env exps) | IdxE (exp1, exp2) -> @@ -412,6 +412,14 @@ and t_exp' env = function let decls = show_decls !(env1.params) in ActorE (id, decls @ ds', fields, typ) +and t_lexp env (e : Ir.lexp) = { e with it = t_lexp' env e.it } +and t_lexp' env = function + | VarLE id -> VarLE id + | IdxLE (exp1, exp2) -> + IdxLE (t_exp env exp1, t_exp env exp2) + | DotLE (exp1, n) -> + DotLE (t_exp env exp1, n) + and t_dec env dec = { dec with it = t_dec' env dec.it } and t_dec' env dec' = diff --git a/src/ir_passes/tailcall.ml b/src/ir_passes/tailcall.ml index 612e11206db..c4ea922a2a3 100644 --- a/src/ir_passes/tailcall.ml +++ b/src/ir_passes/tailcall.ml @@ -98,7 +98,7 @@ and exp' env e : exp' = match e.it with | ProjE (e, i) -> ProjE (exp env e, i) | DotE (e, sn) -> DotE (exp env e, sn) | ActorDotE (e, sn) -> ActorDotE (exp env e, sn) - | AssignE (e1, e2) -> AssignE (exp env e1, exp env e2) + | AssignE (e1, e2) -> AssignE (lexp env e1, exp env e2) | ArrayE (m,t,es) -> ArrayE (m,t,(exps env es)) | IdxE (e1, e2) -> IdxE (exp env e1, exp env e2) | CallE (e1, insts, e2) -> @@ -147,6 +147,13 @@ and exp' env e : exp' = match e.it with and exps env es = List.map (exp env) es +and lexp env le : lexp = {le with it = lexp' env le} + +and lexp' env le : lexp' = match le.it with + | VarLE i -> VarLE i + | DotLE (e, sn) -> DotLE (exp env e, sn) + | IdxLE (e1, e2) -> IdxLE (exp env e1, exp env e2) + and args env as_ = List.fold_left (fun env a -> bind_arg env a None) env as_ diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 4895fa016a6..ee9b58c58b3 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -81,7 +81,7 @@ and exp' at note = function | T.Actor, _ -> I.ActorDotE (exp e, x.it) | _ -> I.DotE (exp e, x.it) end - | S.AssignE (e1, e2) -> I.AssignE (exp e1, exp e2) + | S.AssignE (e1, e2) -> I.AssignE (lexp e1, exp e2) | S.ArrayE (m, es) -> let t = T.as_array note.I.note_typ in I.ArrayE (mut m, T.as_immut t, exps es) @@ -144,6 +144,18 @@ and exp' at note = function I.VarE (id_of_full_path !fp).it | S.PrimE s -> raise (Invalid_argument ("Unapplied prim " ^ s)) +and lexp e = + (* We short-cut AnnotE here, so that we get the position of the inner expression *) + match e.it with + | S.AnnotE (e,_) -> lexp e + | _ -> { e with it = lexp' e.it; note = e.note.S.note_typ } + +and lexp' = function + | S.VarE i -> I.VarLE i.it + | S.DotE (e, x) -> I.DotLE (exp e, x.it) + | S.IdxE (e1, e2) -> I.IdxLE (exp e1, exp e2) + | _ -> raise (Invalid_argument ("Unexpected expression as lvalue")) + and mut m = match m.it with | S.Const -> Ir.Const | S.Var -> Ir.Var From 6173c04cb61b7f7b726ce92b2c926819fa9a728c Mon Sep 17 00:00:00 2001 From: chenyan-dfinity <48968912+chenyan-dfinity@users.noreply.github.com> Date: Thu, 12 Dec 2019 10:40:28 -0800 Subject: [PATCH 0820/1176] update IDL parser to match spec (#1012) * update IDL parser to match spec * fixup --- src/idllib/arrange_idl.ml | 13 +++---- src/idllib/compile_js.ml | 58 ++++++++++++----------------- src/idllib/parser.mly | 12 ++++-- src/idllib/syntax.ml | 6 +-- src/idllib/typing.ml | 8 ++-- src/mo_idl/mo_to_idl.ml | 9 ++--- test/idl/actor.did | 3 +- test/idl/cyclic.did | 2 +- test/idl/diamond.did | 2 +- test/idl/escape.did | 2 +- test/idl/fieldnat.did | 3 +- test/idl/fields.did | 3 +- test/idl/func.did | 2 +- test/idl/import.did | 3 +- test/idl/import1.did | 2 +- test/idl/integer.did | 2 +- test/idl/keywords.did | 2 +- test/idl/meths.did | 3 +- test/idl/missing_semicolon.did | 3 +- test/idl/ok/actor.js.ok | 5 +-- test/idl/ok/cyclic.js.ok | 4 +- test/idl/ok/diamond.js.ok | 8 ++-- test/idl/ok/escape.js.ok | 9 ++--- test/idl/ok/fieldnat.js.ok | 9 ++--- test/idl/ok/fields.js.ok | 13 +++---- test/idl/ok/import.js.ok | 13 +++---- test/idl/ok/import1.js.ok | 6 +-- test/idl/ok/import3.js.ok | 9 ++--- test/idl/ok/integer.js.ok | 4 +- test/idl/ok/keywords.js.ok | 11 +++--- test/idl/ok/meths.tc.ok | 2 +- test/idl/ok/missing_semicolon.tc.ok | 2 +- test/idl/ok/px.js.ok | 11 +++--- test/idl/ok/recursion.js.ok | 9 ++--- test/idl/ok/test.js.ok | 5 +-- test/idl/ok/unicode.js.ok | 5 +-- test/idl/px.did | 2 +- test/idl/test.did | 3 +- test/idl/unicode.did | 3 +- test/mo-idl/ok/counter.did.ok | 2 +- test/mo-idl/ok/fields.did.ok | 2 +- test/mo-idl/ok/func_mode.did.ok | 2 +- test/mo-idl/ok/inline_result.did.ok | 2 +- test/mo-idl/ok/keyword.did.ok | 2 +- test/mo-idl/ok/prelude.did.ok | 2 +- test/mo-idl/ok/recursion.did.ok | 2 +- test/mo-idl/ok/result.did.ok | 2 +- 47 files changed, 131 insertions(+), 156 deletions(-) diff --git a/src/idllib/arrange_idl.ml b/src/idllib/arrange_idl.ml index 378d193f270..64079be0000 100644 --- a/src/idllib/arrange_idl.ml +++ b/src/idllib/arrange_idl.ml @@ -65,8 +65,8 @@ and dec d = match d.it with and actor a = match a with | None -> Atom "NoActor" - | Some {it=ActorD (x, t); _} -> - "ActorD" $$ id x :: [typ t] + | Some t -> + "Actor" $$ [typ t] and prog prog = "Decs" $$ List.map dec prog.it.decs @ [actor prog.it.actor] @@ -177,21 +177,18 @@ let pp_dec ppf d = let pp_actor ppf actor = (match actor with | None -> () - | Some {it = ActorD (id, {it=ServT ms; _}); _} -> + | Some {it=ServT ms; _} -> pp_open_vbox ppf 2; pp_open_hbox ppf (); - kwd ppf "service"; - kwd ppf id.it; - str ppf "{"; + str ppf "service : {"; pp_close_box ppf (); List.iter (fun m -> pp_print_cut ppf (); pp_meth ppf m; str ppf ";") ms; pp_print_break ppf 0 (-2); str ppf "}"; pp_close_box ppf () - | Some {it = ActorD (id, {it=VarT x; _}); _} -> + | Some {it=VarT x; _} -> pp_open_hbox ppf (); kwd ppf "service"; - kwd ppf id.it; kwd ppf ":"; str ppf x.it; pp_close_box ppf () diff --git a/src/idllib/compile_js.ml b/src/idllib/compile_js.ml index 9276a33f4d1..c7ed7f74b77 100644 --- a/src/idllib/compile_js.ml +++ b/src/idllib/compile_js.ml @@ -36,10 +36,8 @@ let chase_env env actor = and chase_fields fs = List.iter (fun (f : typ_field) -> chase f.it.typ) fs in - match actor.it with - | ActorD (_, t) -> - chase t; - List.rev (!new_env) + chase actor; + List.rev (!new_env) (* Given a topologically sorted type definition list, infer which types are recursive *) let infer_rec env_list = @@ -84,13 +82,13 @@ let pp_prim p = | Int16 -> "Int16" | Int32 -> "Int32" | Int64 -> "Int64" - | Float32 -> "Float" - | Float64 -> "Float" + | Float32 -> "Float32" + | Float64 -> "Float64" | Bool -> "Bool" | Text -> "Text" | Null -> "Unit" | Reserved -> "None" - | Empty -> "Empty" + | Empty -> "None" let pp_mode ppf m = match m.it with @@ -109,7 +107,7 @@ let rec pp_typ ppf t = | VarT s -> id ppf s | PrimT p -> str ppf ("IDL."^(pp_prim p)) | RecordT ts -> pp_fields ppf ts - | VecT t -> str ppf "IDL.Arr("; pp_typ ppf t; str ppf ")"; + | VecT t -> str ppf "IDL.Vec("; pp_typ ppf t; str ppf ")"; | OptT t -> str ppf "IDL.Opt("; pp_typ ppf t; str ppf ")"; | VariantT ts -> str ppf "IDL.Variant({"; concat ppf pp_field "," ts; str ppf "})"; | FuncT (ms, t1, t2) -> @@ -147,7 +145,7 @@ and pp_modes ppf modes = and pp_fields ppf fs = pp_open_box ppf 1; - str ppf "IDL.Obj({"; + str ppf "IDL.Record({"; concat ppf pp_field "," fs; str ppf "})"; pp_close_box ppf () @@ -195,31 +193,23 @@ let pp_rec ppf x = pp_close_box ppf (); pp_print_cut ppf () -let pp_actor ppf actor recs = - match actor.it with - | ActorD (x, t) -> - let x = ("actor_" ^ x.it) @@ x.at in - pp_open_hovbox ppf 1; - kwd ppf "const"; - (match t.it with - | ServT tp -> - id ppf x; space ppf (); kwd ppf "="; kwd ppf "new"; - str ppf "IDL.ActorInterface({"; - concat ppf pp_meth "," tp; - str ppf "});" - | VarT var -> - id ppf x; space ppf (); kwd ppf "="; - if TS.mem var.it recs then - str ppf (var.it ^ ".getType();") - else - str ppf var.it; - | _ -> assert false - ); - pp_close_box ppf (); - pp_force_newline ppf (); - pp_open_hovbox ppf 0; - kwd ppf "return"; id ppf x; str ppf ";"; - pp_close_box ppf () +let pp_actor ppf t recs = + pp_open_hovbox ppf 1; + kwd ppf "return"; + (match t.it with + | ServT tp -> + kwd ppf "new"; + str ppf "IDL.ActorInterface({"; + concat ppf pp_meth "," tp; + str ppf "});" + | VarT var -> + if TS.mem var.it recs then + str ppf (var.it ^ ".getType();") + else + str ppf var.it; + | _ -> assert false + ); + pp_close_box ppf () let pp_header ppf () = pp_open_vbox ppf 1; diff --git a/src/idllib/parser.mly b/src/idllib/parser.mly index def2c37de69..09562ac19fe 100644 --- a/src/idllib/parser.mly +++ b/src/idllib/parser.mly @@ -172,12 +172,16 @@ def : | IMPORT file=TEXT { ImportD (file, ref "") @@ at $sloc } +id_opt : + | (* empty *) { } + | id { } + actor : | (* empty *) { None } - | SERVICE id=id tys=actor_typ - { Some (ActorD(id, ServT tys @@ at $loc(tys)) @@ at $sloc) } - | SERVICE id=id COLON x=id - { Some (ActorD(id, VarT x @@ x.at) @@ at $sloc) } + | SERVICE id_opt COLON tys=actor_typ + { Some (ServT tys @@ at $loc(tys)) } + | SERVICE id_opt COLON x=id + { Some (VarT x @@ x.at) } (* Programs *) diff --git a/src/idllib/syntax.ml b/src/idllib/syntax.ml index 94dee6f5162..41f3912c421 100644 --- a/src/idllib/syntax.ml +++ b/src/idllib/syntax.ml @@ -55,12 +55,8 @@ and dec' = | TypD of id * typ (* type *) | ImportD of string * string ref (* import *) -and actor = actor' Source.phrase -and actor' = - | ActorD of id * typ (* service *) - (* Program *) type prog = (prog', string) Source.annotated_phrase -and prog' = { decs : dec list; actor : actor option } +and prog' = { decs : dec list; actor : typ option } diff --git a/src/idllib/typing.ml b/src/idllib/typing.ml index 883a4209fe6..4650b2fe3bd 100644 --- a/src/idllib/typing.ml +++ b/src/idllib/typing.ml @@ -204,16 +204,16 @@ and gather_decs env decs = let check_actor env actor_opt = match actor_opt with | None -> Env.empty - | Some {it=ActorD (id, t); at; _} -> + | Some t -> (match as_serv env t with | None -> - error env at "%s is a non-service type\n %s" (string_of_typ t) (string_of_typ t) + error env t.at "%s is a non-service type\n %s" (string_of_typ t) (string_of_typ t) | Some {it=ServT meths; _} -> let meths' = check_meths env meths in - Env.singleton id.it (ServT (List.sort compare_meth meths') @@ at) + Env.singleton "service" (ServT (List.sort compare_meth meths') @@ t.at) | Some _ -> assert false ) - + (* Programs *) let check_prog scope prog : scope Diag.result = diff --git a/src/mo_idl/mo_to_idl.ml b/src/mo_idl/mo_to_idl.ml index cf0340c1190..586d1c1ab95 100644 --- a/src/mo_idl/mo_to_idl.ml +++ b/src/mo_idl/mo_to_idl.ml @@ -181,17 +181,16 @@ let gather_decs () = let actor progs = let open E in let find_last_actor (prog : prog) = - let anon = "anon" in let check_dec d t def = let rec check_pat p = match p.it with - | WildP -> Some (anon, t) - | VarP id -> Some (id.it, t) + | WildP -> Some t + | VarP id -> Some t | ParP p -> check_pat p | _ -> def in match d.it with - | ExpD _ -> Some (anon, t) + | ExpD _ -> Some t | LetD (pat, _) -> check_pat pat | _ -> def in @@ -209,7 +208,7 @@ let actor progs = let prog = Lib.List.last progs in match find_last_actor prog with | None -> None - | Some (id, t) -> Some (I.ActorD (id @@ no_region, typ [] t) @@ no_region) + | Some t -> Some (typ [] t) let prog (progs, senv) : I.prog = env := Env.empty; diff --git a/test/idl/actor.did b/test/idl/actor.did index 19fde259828..12a7e20d453 100644 --- a/test/idl/actor.did +++ b/test/idl/actor.did @@ -2,7 +2,8 @@ type f = func (int8) -> (int8); type g = f; type h = func (f) -> (f); type o = opt o; -service g { +service : +{ f : (nat) -> (h); g : f; h : g; diff --git a/test/idl/cyclic.did b/test/idl/cyclic.did index 729a9f4234c..cd086f15747 100644 --- a/test/idl/cyclic.did +++ b/test/idl/cyclic.did @@ -6,6 +6,6 @@ type X = Y; type Y = Z; type Z = A; -service S { +service S : { f : (A,B,C,X,Y,Z) -> (); } diff --git a/test/idl/diamond.did b/test/idl/diamond.did index 85dd9572d3b..ccf9526a45c 100644 --- a/test/idl/diamond.did +++ b/test/idl/diamond.did @@ -1,6 +1,6 @@ type t1 = record { t2; t3; t }; import "diamond2.did"; import "diamond3.did"; -service S { +service S: { f : (t, t2, t3) -> (t1); } diff --git a/test/idl/escape.did b/test/idl/escape.did index a811617704e..b96d8c4d161 100644 --- a/test/idl/escape.did +++ b/test/idl/escape.did @@ -1,5 +1,5 @@ type t = record {"'":nat; "\"":nat; "\"'":nat; "\\\n'\"":nat; }; -service E { +service E : { "\n'\"''\"\"\r\t": (t) -> (); } diff --git a/test/idl/fieldnat.did b/test/idl/fieldnat.did index 7f1ebd2d3d6..e3dee70d29f 100644 --- a/test/idl/fieldnat.did +++ b/test/idl/fieldnat.did @@ -1,4 +1,5 @@ -service Foo { +service Foo: +{ foo : (record {2 : int}) -> (); bar : (record {"2" : int}) -> (); // TODO: JS binding treats all field names as string diff --git a/test/idl/fields.did b/test/idl/fields.did index 7c4aa3c0f6e..653c6f3038b 100644 --- a/test/idl/fields.did +++ b/test/idl/fields.did @@ -11,6 +11,7 @@ type nest_record = record { A; B; C; nat; }; -service S { +service S: +{ f : (A,B,C,nest_record) -> (); } diff --git a/test/idl/func.did b/test/idl/func.did index eddea8f17b6..db413daf4fb 100644 --- a/test/idl/func.did +++ b/test/idl/func.did @@ -2,7 +2,7 @@ type f = func (int8) -> (int8); type g = f; type h = func (f) -> (f); type o = opt f; -service g { +service g : { f : f; g : g; h : h; diff --git a/test/idl/import.did b/test/idl/import.did index 1b9d4bca99c..997d2f4f796 100644 --- a/test/idl/import.did +++ b/test/idl/import.did @@ -3,7 +3,8 @@ type list = vec nat; import "px.did"; import "import1.did"; -service S { +service S : +{ f: (t, t1, t2) -> (list, IdErr); getInventory: (producer_id: nat) -> (Inventory) query; } diff --git a/test/idl/import1.did b/test/idl/import1.did index 525ad927aa8..75caa958975 100644 --- a/test/idl/import1.did +++ b/test/idl/import1.did @@ -4,6 +4,6 @@ import "px.did"; type t1 = t; type t2 = UserId; -service S { +service : { f : (t,t1,t2) -> (); } diff --git a/test/idl/integer.did b/test/idl/integer.did index 1fcbdfbe502..fc1839bc9a4 100644 --- a/test/idl/integer.did +++ b/test/idl/integer.did @@ -1,4 +1,4 @@ -service num { +service : { f : (nat8) -> (int16); g : (nat64) -> (int64); h : (int8) -> (nat); diff --git a/test/idl/keywords.did b/test/idl/keywords.did index 16cfb66696a..181e77f1713 100644 --- a/test/idl/keywords.did +++ b/test/idl/keywords.did @@ -1,5 +1,5 @@ type const_ = record { type_:nat; service_:nat; vec_:nat }; -service s { +service : { "blob": (const_) -> (blob); "record": (opt_:nat, import_:nat, variant_:variant {}) -> (record_:nat, record {}); } diff --git a/test/idl/meths.did b/test/idl/meths.did index 56436c210b9..98e25fe9516 100644 --- a/test/idl/meths.did +++ b/test/idl/meths.did @@ -1,4 +1,5 @@ -service A { +service A: +{ f : (nat) -> (); g : f; } diff --git a/test/idl/missing_semicolon.did b/test/idl/missing_semicolon.did index 903fa08a587..3c788655a27 100644 --- a/test/idl/missing_semicolon.did +++ b/test/idl/missing_semicolon.did @@ -1,4 +1,5 @@ -service Foo { +service Foo: +{ foo : (record {2 : int}) -> () bar : (record {"2" : int}) -> () } diff --git a/test/idl/ok/actor.js.ok b/test/idl/ok/actor.js.ok index c1e32cab6ac..adb582b68c2 100644 --- a/test/idl/ok/actor.js.ok +++ b/test/idl/ok/actor.js.ok @@ -4,7 +4,6 @@ export default ({ IDL }) => { const h = IDL.Func([f], [f], []) const g = f o.fill(IDL.Opt(o)) - const actor_g = new IDL.ActorInterface({'f': IDL.Func([IDL.Nat], [h], []), - 'g': f, 'h': g, 'o': IDL.Func([o], [o], [])}); - return actor_g; + return new IDL.ActorInterface({'f': IDL.Func([IDL.Nat], [h], []), 'g': f, + 'h': g, 'o': IDL.Func([o], [o], [])}); }; diff --git a/test/idl/ok/cyclic.js.ok b/test/idl/ok/cyclic.js.ok index 3e62e4842d0..8e346b1a28d 100644 --- a/test/idl/ok/cyclic.js.ok +++ b/test/idl/ok/cyclic.js.ok @@ -6,7 +6,5 @@ export default ({ IDL }) => { const Z = A const Y = Z const X = Y - const actor_S = new IDL.ActorInterface({ - 'f': IDL.Func([A, B, C, X, Y, Z], [], [])}); - return actor_S; + return new IDL.ActorInterface({'f': IDL.Func([A, B, C, X, Y, Z], [], [])}); }; diff --git a/test/idl/ok/diamond.js.ok b/test/idl/ok/diamond.js.ok index ab6f5a0ed9d..ebc0e990f6a 100644 --- a/test/idl/ok/diamond.js.ok +++ b/test/idl/ok/diamond.js.ok @@ -1,9 +1,7 @@ export default ({ IDL }) => { const t = IDL.Nat - const t2 = IDL.Arr(t) + const t2 = IDL.Vec(t) const t3 = IDL.Opt(t) - const t1 = IDL.Obj({'0': t2, '1': t3, '2': t}) - const actor_S = new IDL.ActorInterface({'f': IDL.Func([t, t2, t3], [t1], []) - }); - return actor_S; + const t1 = IDL.Record({'0': t2, '1': t3, '2': t}) + return new IDL.ActorInterface({'f': IDL.Func([t, t2, t3], [t1], [])}); }; diff --git a/test/idl/ok/escape.js.ok b/test/idl/ok/escape.js.ok index 4d79a82e592..cbfb408e594 100644 --- a/test/idl/ok/escape.js.ok +++ b/test/idl/ok/escape.js.ok @@ -1,8 +1,7 @@ export default ({ IDL }) => { const t = - IDL.Obj({'\"': IDL.Nat, '\'': IDL.Nat, '\"\'': IDL.Nat, '\\\n\'\"': IDL.Nat - }) - const actor_E = new IDL.ActorInterface({ - '\n\'\"\'\'\"\"\r\t': IDL.Func([t], [], [])}); - return actor_E; + IDL.Record({'\"': IDL.Nat, '\'': IDL.Nat, '\"\'': IDL.Nat, + '\\\n\'\"': IDL.Nat}) + return new IDL.ActorInterface({'\n\'\"\'\'\"\"\r\t': IDL.Func([t], [], []) + }); }; diff --git a/test/idl/ok/fieldnat.js.ok b/test/idl/ok/fieldnat.js.ok index a7773235ac7..f964918b2a2 100644 --- a/test/idl/ok/fieldnat.js.ok +++ b/test/idl/ok/fieldnat.js.ok @@ -1,8 +1,7 @@ export default ({ IDL }) => { - const actor_Foo = new IDL.ActorInterface({ - 'foo': IDL.Func([IDL.Obj({'2': IDL.Int})], [], []), - 'bar': IDL.Func([IDL.Obj({'2': IDL.Int})], [], []), - 'baz': IDL.Func([IDL.Obj({'2': IDL.Int, '2': IDL.Nat})], [], []), + return new IDL.ActorInterface({ + 'foo': IDL.Func([IDL.Record({'2': IDL.Int})], [], []), + 'bar': IDL.Func([IDL.Record({'2': IDL.Int})], [], []), + 'baz': IDL.Func([IDL.Record({'2': IDL.Int, '2': IDL.Nat})], [], []), 'bab': IDL.Func([IDL.Int, IDL.Nat], [], [])}); - return actor_Foo; }; diff --git a/test/idl/ok/fields.js.ok b/test/idl/ok/fields.js.ok index 95d64834951..d6dd372b3f1 100644 --- a/test/idl/ok/fields.js.ok +++ b/test/idl/ok/fields.js.ok @@ -1,7 +1,7 @@ export default ({ IDL }) => { - const A = IDL.Obj({'0': IDL.Nat, '1': IDL.Nat, '2': IDL.Nat}) + const A = IDL.Record({'0': IDL.Nat, '1': IDL.Nat, '2': IDL.Nat}) const B = - IDL.Obj({'0': IDL.Arr(IDL.Nat8), '35': IDL.Arr(IDL.Nat8), '36': IDL.Nat, + IDL.Record({'0': IDL.Vec(IDL.Nat8), '35': IDL.Vec(IDL.Nat8), '36': IDL.Nat, '37': IDL.Nat, 'named_files': IDL.None, '3629958706': IDL.Nat, '3629958707': IDL.Nat}) const C = @@ -10,10 +10,9 @@ export default ({ IDL }) => { 'red': IDL.Unit, 'blue': IDL.Unit, 'reserved': IDL.Unit, 'green': IDL.Unit }) const nest_record = - IDL.Obj({'0': IDL.Nat, '1': IDL.Nat, '2': IDL.Nat, - '3': IDL.Obj({'0': IDL.Nat, '1': IDL.Nat, '2': IDL.Nat}), '4': IDL.Nat, + IDL.Record({'0': IDL.Nat, '1': IDL.Nat, '2': IDL.Nat, + '3': IDL.Record({'0': IDL.Nat, '1': IDL.Nat, '2': IDL.Nat}), '4': IDL.Nat, '5': IDL.Nat, '6': IDL.Nat, '7': A, '8': B, '9': C, '10': IDL.Nat}) - const actor_S = new IDL.ActorInterface({ - 'f': IDL.Func([A, B, C, nest_record], [], [])}); - return actor_S; + return new IDL.ActorInterface({'f': IDL.Func([A, B, C, nest_record], [], []) + }); }; diff --git a/test/idl/ok/import.js.ok b/test/idl/ok/import.js.ok index a422910dad1..0200ab84be4 100644 --- a/test/idl/ok/import.js.ok +++ b/test/idl/ok/import.js.ok @@ -1,18 +1,17 @@ export default ({ IDL }) => { - const t = IDL.Arr(IDL.Nat8) + const t = IDL.Vec(IDL.Nat8) const t1 = t const UserId = IDL.Nat const t2 = UserId - const list = IDL.Arr(IDL.Nat) + const list = IDL.Vec(IDL.Nat) const RegionId = IDL.Nat const TruckTypeId = IDL.Nat const EntId = - IDL.Obj({'region': RegionId, 'user': UserId, 'truckType': TruckTypeId}) + IDL.Record({'region': RegionId, 'user': UserId, 'truckType': TruckTypeId}) const OpEntId = IDL.Opt(EntId) - const IdErr = IDL.Obj({'idErr': OpEntId}) - const Inventory = IDL.Obj({'produce_id': IDL.Nat, 'quantity': IDL.Nat}) - const actor_S = new IDL.ActorInterface({ + const IdErr = IDL.Record({'idErr': OpEntId}) + const Inventory = IDL.Record({'produce_id': IDL.Nat, 'quantity': IDL.Nat}) + return new IDL.ActorInterface({ 'f': IDL.Func([t, t1, t2], [list, IdErr], []), 'getInventory': IDL.Func([IDL.Nat], [Inventory], ['query'])}); - return actor_S; }; diff --git a/test/idl/ok/import1.js.ok b/test/idl/ok/import1.js.ok index b820edecdfe..f25f6306af4 100644 --- a/test/idl/ok/import1.js.ok +++ b/test/idl/ok/import1.js.ok @@ -1,9 +1,7 @@ export default ({ IDL }) => { - const t = IDL.Arr(IDL.Nat8) + const t = IDL.Vec(IDL.Nat8) const t1 = t const UserId = IDL.Nat const t2 = UserId - const actor_S = new IDL.ActorInterface({'f': IDL.Func([t, t1, t2], [], []) - }); - return actor_S; + return new IDL.ActorInterface({'f': IDL.Func([t, t1, t2], [], [])}); }; diff --git a/test/idl/ok/import3.js.ok b/test/idl/ok/import3.js.ok index af87b4f2b00..a79d5adb6c0 100644 --- a/test/idl/ok/import3.js.ok +++ b/test/idl/ok/import3.js.ok @@ -5,20 +5,19 @@ export default ({ IDL }) => { const stream = IDL.Rec() const tree = IDL.Rec() const t = IDL.Func([s], [], []) - const node = IDL.Obj({'head': IDL.Nat, 'tail': list}) + const node = IDL.Record({'head': IDL.Nat, 'tail': list}) list.fill(IDL.Opt(node)) const A = B B.fill(IDL.Opt(A)) tree.fill( IDL.Variant({ - 'branch': IDL.Obj({'val': IDL.Int, 'left': tree, 'right': tree}), + 'branch': IDL.Record({'val': IDL.Int, 'left': tree, 'right': tree}), 'leaf': IDL.Int})) stream.fill( IDL.Opt( - IDL.Obj({'head': IDL.Nat, 'next': IDL.Func([], [stream], ['query'])}))) + IDL.Record({'head': IDL.Nat, 'next': IDL.Func([], [stream], ['query'])}))) s.fill( new IDL.ActorInterface({'f': t, 'g': IDL.Func([list], [B, tree, stream], [])})) - const actor_S = s.getType(); - return actor_S; + return s.getType(); }; diff --git a/test/idl/ok/integer.js.ok b/test/idl/ok/integer.js.ok index dc3d0e6eda9..ac73a9c7d56 100644 --- a/test/idl/ok/integer.js.ok +++ b/test/idl/ok/integer.js.ok @@ -1,7 +1,5 @@ export default ({ IDL }) => { - const actor_num = new IDL.ActorInterface({ - 'f': IDL.Func([IDL.Nat8], [IDL.Int16], []), + return new IDL.ActorInterface({'f': IDL.Func([IDL.Nat8], [IDL.Int16], []), 'g': IDL.Func([IDL.Nat64], [IDL.Int64], []), 'h': IDL.Func([IDL.Int8], [IDL.Nat], [])}); - return actor_num; }; diff --git a/test/idl/ok/keywords.js.ok b/test/idl/ok/keywords.js.ok index cd57bc9004d..c3047104cb7 100644 --- a/test/idl/ok/keywords.js.ok +++ b/test/idl/ok/keywords.js.ok @@ -1,10 +1,9 @@ export default ({ IDL }) => { const const_ = - IDL.Obj({'type_': IDL.Nat, 'vec_': IDL.Nat, 'service_': IDL.Nat}) - const actor_s = new IDL.ActorInterface({ - 'blob': IDL.Func([const_], [IDL.Arr(IDL.Nat8)], []), + IDL.Record({'type_': IDL.Nat, 'vec_': IDL.Nat, 'service_': IDL.Nat}) + return new IDL.ActorInterface({ + 'blob': IDL.Func([const_], [IDL.Vec(IDL.Nat8)], []), 'record': - IDL.Func([IDL.Nat, IDL.Nat, IDL.Variant({})], [IDL.Nat, IDL.Obj({})], []) - }); - return actor_s; + IDL.Func([IDL.Nat, IDL.Nat, IDL.Variant({})], [IDL.Nat, IDL.Record({})], + [])}); }; diff --git a/test/idl/ok/meths.tc.ok b/test/idl/ok/meths.tc.ok index 564a9f619f7..1965bcdce4e 100644 --- a/test/idl/ok/meths.tc.ok +++ b/test/idl/ok/meths.tc.ok @@ -1 +1 @@ -meths.did:3.7-3.8: type error, unbound type identifier f +meths.did:4.7-4.8: type error, unbound type identifier f diff --git a/test/idl/ok/missing_semicolon.tc.ok b/test/idl/ok/missing_semicolon.tc.ok index 81d455243a3..ec0105b869e 100644 --- a/test/idl/ok/missing_semicolon.tc.ok +++ b/test/idl/ok/missing_semicolon.tc.ok @@ -1 +1 @@ -missing_semicolon.did:3.7-3.8: syntax error, unexpected token +missing_semicolon.did:4.7-4.8: syntax error, unexpected token diff --git a/test/idl/ok/px.js.ok b/test/idl/ok/px.js.ok index 7139338968f..05f72377b6b 100644 --- a/test/idl/ok/px.js.ok +++ b/test/idl/ok/px.js.ok @@ -3,17 +3,16 @@ export default ({ IDL }) => { const RegionId = IDL.Nat const ProducerId = IDL.Nat const UserInfo = - IDL.Obj({'id': UserId, 'region': RegionId, 'user_name': IDL.Text, + IDL.Record({'id': UserId, 'region': RegionId, 'user_name': IDL.Text, 'public_key': IDL.Text, 'description': IDL.Text, 'produceId': IDL.Opt(ProducerId)}) - const Inventory = IDL.Obj({'produce_id': IDL.Nat, 'quantity': IDL.Nat}) + const Inventory = IDL.Record({'produce_id': IDL.Nat, 'quantity': IDL.Nat}) const TruckTypeId = IDL.Nat const EntId = - IDL.Obj({'region': RegionId, 'user': UserId, 'truckType': TruckTypeId}) + IDL.Record({'region': RegionId, 'user': UserId, 'truckType': TruckTypeId}) const OpEntId = IDL.Opt(EntId) - const IdErr = IDL.Obj({'idErr': OpEntId}) - const actor_ProduceExchange = new IDL.ActorInterface({ + const IdErr = IDL.Record({'idErr': OpEntId}) + return new IDL.ActorInterface({ 'getInventory': IDL.Func([IDL.Nat, UserInfo], [Inventory, IdErr], ['query'])}); - return actor_ProduceExchange; }; diff --git a/test/idl/ok/recursion.js.ok b/test/idl/ok/recursion.js.ok index ad7e4d49be7..a79d5adb6c0 100644 --- a/test/idl/ok/recursion.js.ok +++ b/test/idl/ok/recursion.js.ok @@ -5,20 +5,19 @@ export default ({ IDL }) => { const stream = IDL.Rec() const tree = IDL.Rec() const t = IDL.Func([s], [], []) - const node = IDL.Obj({'head': IDL.Nat, 'tail': list}) + const node = IDL.Record({'head': IDL.Nat, 'tail': list}) list.fill(IDL.Opt(node)) const A = B B.fill(IDL.Opt(A)) tree.fill( IDL.Variant({ - 'branch': IDL.Obj({'val': IDL.Int, 'left': tree, 'right': tree}), + 'branch': IDL.Record({'val': IDL.Int, 'left': tree, 'right': tree}), 'leaf': IDL.Int})) stream.fill( IDL.Opt( - IDL.Obj({'head': IDL.Nat, 'next': IDL.Func([], [stream], ['query'])}))) + IDL.Record({'head': IDL.Nat, 'next': IDL.Func([], [stream], ['query'])}))) s.fill( new IDL.ActorInterface({'f': t, 'g': IDL.Func([list], [B, tree, stream], [])})) - const actor_A = s.getType(); - return actor_A; + return s.getType(); }; diff --git a/test/idl/ok/test.js.ok b/test/idl/ok/test.js.ok index f51cf54ee8e..581065ce509 100644 --- a/test/idl/ok/test.js.ok +++ b/test/idl/ok/test.js.ok @@ -1,7 +1,7 @@ export default ({ IDL }) => { const my_type = IDL.Nat const B = my_type - const message = IDL.Obj({'25': B, '26': IDL.None, 'name': IDL.Text}) + const message = IDL.Record({'25': B, '26': IDL.None, 'name': IDL.Text}) const broker = new IDL.ActorInterface({ 'find': @@ -11,11 +11,10 @@ export default ({ IDL }) => { 'current': IDL.Func([], [IDL.Nat], [])}) ], [])}) - const actor_server = new IDL.ActorInterface({ + return new IDL.ActorInterface({ 'addUser': IDL.Func([IDL.Text, IDL.Nat8], [IDL.Nat64], []), 'userName': IDL.Func([IDL.Nat64], [IDL.Text], ['query']), 'userAge': IDL.Func([IDL.Nat64], [IDL.Nat8], ['query']), 'deleteUser': IDL.Func([IDL.Nat64], [], ['oneway']), 'f': IDL.Func([message], [broker], [])}); - return actor_server; }; diff --git a/test/idl/ok/unicode.js.ok b/test/idl/ok/unicode.js.ok index 26c5cabc17d..8ca39e34301 100644 --- a/test/idl/ok/unicode.js.ok +++ b/test/idl/ok/unicode.js.ok @@ -1,13 +1,12 @@ export default ({ IDL }) => { const A = - IDL.Obj({'': IDL.Nat, '📦🍦': IDL.Nat, '字段名': IDL.Nat, + IDL.Record({'': IDL.Nat, '📦🍦': IDL.Nat, '字段名': IDL.Nat, '字 段 名2': IDL.Nat}) const B = IDL.Variant({'': IDL.Unit, '空的': IDL.Unit, ' 空的 ': IDL.Unit, '1⃣️2⃣️3⃣️': IDL.Unit}) - const actor_C = new IDL.ActorInterface({'函数名': IDL.Func([A], [B], []), + return new IDL.ActorInterface({'函数名': IDL.Func([A], [B], []), '': IDL.Func([IDL.Nat], [IDL.Nat], []), '👀': IDL.Func([IDL.Nat], [IDL.Nat], ['query']), '✈️ 🚗 ⛱️ ': IDL.Func([], [], ['oneway'])}); - return actor_C; }; diff --git a/test/idl/px.did b/test/idl/px.did index 4a21e8afc26..3026ce01101 100644 --- a/test/idl/px.did +++ b/test/idl/px.did @@ -25,7 +25,7 @@ type Inventory = record { quantity: nat; } -service ProduceExchange { +service ProduceExchange : { getInventory: (producer_id: nat, UserInfo) -> (Inventory, IdErr) query; } diff --git a/test/idl/test.did b/test/idl/test.did index 999f151f3d0..7a790ca650a 100644 --- a/test/idl/test.did +++ b/test/idl/test.did @@ -11,7 +11,8 @@ type broker = service { (service {up:() -> (); current:() -> (nat)}); }; -service server { +service server: +{ addUser : (name : text, age : nat8) -> (id : nat64); userName : (id : nat64) -> (text) query; userAge : (id : nat64) -> (nat8) query; diff --git a/test/idl/unicode.did b/test/idl/unicode.did index aad635a43ad..ef80093dceb 100644 --- a/test/idl/unicode.did +++ b/test/idl/unicode.did @@ -6,7 +6,8 @@ type A = record { }; type B = variant { ""; "空的"; " 空的 "; "1⃣️2⃣️3⃣️"; }; -service C { +service C: +{ "函数名": (A) -> (B); "": (nat) -> (nat); "👀": (nat) -> (nat) query; diff --git a/test/mo-idl/ok/counter.did.ok b/test/mo-idl/ok/counter.did.ok index 6d278fcfcce..230d6ae9f77 100644 --- a/test/mo-idl/ok/counter.did.ok +++ b/test/mo-idl/ok/counter.did.ok @@ -3,4 +3,4 @@ type Counter = "dec": () -> () oneway; "read": () -> (int); }; -service c : Counter +service : Counter diff --git a/test/mo-idl/ok/fields.did.ok b/test/mo-idl/ok/fields.did.ok index cf85958da08..31f0ba156c3 100644 --- a/test/mo-idl/ok/fields.did.ok +++ b/test/mo-idl/ok/fields.did.ok @@ -14,7 +14,7 @@ type Info = "name": text; "name_": nat; }; -service Server { +service : { "f": (Tup) -> (); "f_": (opt Tup) -> () oneway; } diff --git a/test/mo-idl/ok/func_mode.did.ok b/test/mo-idl/ok/func_mode.did.ok index c3867b8d58f..2bc79df07b1 100644 --- a/test/mo-idl/ok/func_mode.did.ok +++ b/test/mo-idl/ok/func_mode.did.ok @@ -1,4 +1,4 @@ -service s { +service : { "f": () -> () query; "g": () -> () oneway; } diff --git a/test/mo-idl/ok/inline_result.did.ok b/test/mo-idl/ok/inline_result.did.ok index 35a34389ce7..b27fecfc9fe 100644 --- a/test/mo-idl/ok/inline_result.did.ok +++ b/test/mo-idl/ok/inline_result.did.ok @@ -1,4 +1,4 @@ -service anon { +service : { "f": (opt nat) -> (variant { "err": text; "ok": nat; diff --git a/test/mo-idl/ok/keyword.did.ok b/test/mo-idl/ok/keyword.did.ok index 378323b0b63..6e6a55c19d2 100644 --- a/test/mo-idl/ok/keyword.did.ok +++ b/test/mo-idl/ok/keyword.did.ok @@ -1,4 +1,4 @@ type record_ = nat; -service record_ { +service : { "record": (record_) -> (); } diff --git a/test/mo-idl/ok/prelude.did.ok b/test/mo-idl/ok/prelude.did.ok index 3f065033fc4..112b7598cdd 100644 --- a/test/mo-idl/ok/prelude.did.ok +++ b/test/mo-idl/ok/prelude.did.ok @@ -1,6 +1,6 @@ type Text_1 = Nat_1; type Nat_1 = null; type Id = int; -service A { +service : { "f": (Nat_1, Text_1) -> (Id); } diff --git a/test/mo-idl/ok/recursion.did.ok b/test/mo-idl/ok/recursion.did.ok index e4bc02bb91a..861930f3954 100644 --- a/test/mo-idl/ok/recursion.did.ok +++ b/test/mo-idl/ok/recursion.did.ok @@ -8,7 +8,7 @@ type List_1 = "head": int; "tail": opt List_1; }; -service anon { +service : { "f": (nat) -> (List_2); "g": (int) -> (List_1); } diff --git a/test/mo-idl/ok/result.did.ok b/test/mo-idl/ok/result.did.ok index 463a16fd59a..a3dd61c201b 100644 --- a/test/mo-idl/ok/result.did.ok +++ b/test/mo-idl/ok/result.did.ok @@ -23,7 +23,7 @@ type Result2_1 = "err": Result_1_1; "ok": null; }; -service anon { +service : { "f": (opt nat) -> (Result_1_2); "g": (Result3_1) -> (Result2_2); } From ff3d6913b35e2a580ca8f9f30b8583511726f10c Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Fri, 13 Dec 2019 11:28:20 +0000 Subject: [PATCH 0821/1176] add scope checks; WIP; need to enforce parametericity of async functions --- src/mo_frontend/typing.ml | 26 ++++++++++++++++--- test/run-drun/general_await.mo | 4 ++- test/run-drun/ok/scope-example-func.comp.ok | 4 --- .../ok/scope-example-func.comp.ret.ok | 1 - .../ok/scope-example-func.ic-stub-run.ok | 7 ----- test/run-drun/ok/scope-example.comp.ok | 4 --- test/run-drun/ok/scope-example.comp.ret.ok | 1 - test/run-drun/ok/scope-example.ic-stub-run.ok | 7 ----- 8 files changed, 26 insertions(+), 28 deletions(-) delete mode 100644 test/run-drun/ok/scope-example-func.comp.ok delete mode 100644 test/run-drun/ok/scope-example-func.comp.ret.ok delete mode 100644 test/run-drun/ok/scope-example-func.ic-stub-run.ok delete mode 100644 test/run-drun/ok/scope-example.comp.ok delete mode 100644 test/run-drun/ok/scope-example.comp.ret.ok delete mode 100644 test/run-drun/ok/scope-example.ic-stub-run.ok diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 2fa1cddc28b..f31813a7131 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -262,9 +262,22 @@ let rec infer_scope env cs cod = let t = check_typ env typ in (match T.close cs t with | T.Var (_, n) -> - { env with typs = T.Env.add scope_id (List.nth cs n) env.typs } + let c = (List.nth cs n) in + { env with typs = T.Env.add scope_id (List.nth cs n) env.typs; + async = Some c } | _ -> env) - | _ -> env + | _ -> + { env with async = None } + +and check_scope env t at = + (match env.async with + | Some c -> + if not (T.eq t (T.Con(c,[]))) then + local_error env at "bad scope" + | None -> + if not (T.eq t T.Any) then + local_error env at "bad scope") + and check_typ env (typ:typ) : T.typ = let t = check_typ' env typ in @@ -758,7 +771,7 @@ and infer_exp'' env exp : T.typ = { env' with labs = T.Env.empty; rets = Some codom; - async = None; } + (* async = None; *) } in check_exp (adjoin_vals env'' ve) codom exp; if Type.is_shared_sort sort.it then begin @@ -822,6 +835,11 @@ and infer_exp'' env exp : T.typ = in insts := Some typs; let ts = check_inst_bounds env tbs typs exp.at in + (match t1 with + | T.Func (_, T.Promises (T.Var (_, n)), _, _, _) + | T.Func (_, T.Returns, _, _, [T.Async (T.Var (_, n),_)]) -> + check_scope env (List.nth ts n) (List.nth typs n).at + | _ -> ()); let t_arg = T.open_ ts t_arg in let t_ret = T.open_ ts t_ret in if not env.pre then begin @@ -978,6 +996,7 @@ and infer_exp'' env exp : T.typ = if not (in_shared_async env || in_oneway_ignore env) then error_in [Flags.ICMode] env exp.at "unsupported async block"; let t1 = check_typ env typ1 in + check_scope env t1 typ1.at; let c, tb, ce, cs = check_typ_bind env typ_bind in let ce_scope = T.Env.add "@" c ce in (* pun scope identifier @ with c *) let env' = @@ -1067,6 +1086,7 @@ and check_exp' env0 t exp : T.typ = if not (in_shared_async env || in_oneway_ignore env) then error_in [Flags.ICMode] env exp.at "freestanding async expression not yet supported"; let t1 = check_typ env typ1 in + check_scope env t1 typ1.at; if not (T.eq t1 t1') then error env exp.at "async at scope\n %s\ncannot produce expected scope\n %s" (T.string_of_typ_expand t1) diff --git a/test/run-drun/general_await.mo b/test/run-drun/general_await.mo index 3dfddee9877..22170af5cd4 100644 --- a/test/run-drun/general_await.mo +++ b/test/run-drun/general_await.mo @@ -28,10 +28,12 @@ actor Await { // Dynamic parallel waiting for acknowledgements public shared func DPA<@>() : async<@>() { - let as: [async()] = Array_tabulate(10, func (_) { Ack<@>(); }); +/* +let as: [async()] = Array_tabulate(10, func (_) { Ack<@>(); }); for (a in as.vals()) { await a; }; +*/ }; // Dynamic parallel waiting (with results) diff --git a/test/run-drun/ok/scope-example-func.comp.ok b/test/run-drun/ok/scope-example-func.comp.ok deleted file mode 100644 index af81a3fd713..00000000000 --- a/test/run-drun/ok/scope-example-func.comp.ok +++ /dev/null @@ -1,4 +0,0 @@ -scope-example-func.mo:16.19-16.20: type error, argument to await must be a call expression - (This is a limitation of the current version.) -scope-example-func.mo:22.23-22.24: type error, calling a shared function not yet supported - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/scope-example-func.comp.ret.ok b/test/run-drun/ok/scope-example-func.comp.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/scope-example-func.comp.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/scope-example-func.ic-stub-run.ok b/test/run-drun/ok/scope-example-func.ic-stub-run.ok deleted file mode 100644 index 711ce0f41ed..00000000000 --- a/test/run-drun/ok/scope-example-func.ic-stub-run.ok +++ /dev/null @@ -1,7 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -← completed -→ update Test(0x4449444c0000) -Trap: EvalTrapError :0.1 "uninitialized element 0" -← rejected (RC_CANISTER_REJECT): canister trapped: EvalTrapError :0.1 "uninitialized element 0" diff --git a/test/run-drun/ok/scope-example.comp.ok b/test/run-drun/ok/scope-example.comp.ok deleted file mode 100644 index 663defa5b9c..00000000000 --- a/test/run-drun/ok/scope-example.comp.ok +++ /dev/null @@ -1,4 +0,0 @@ -scope-example.mo:13.19-13.20: type error, argument to await must be a call expression - (This is a limitation of the current version.) -scope-example.mo:19.23-19.24: type error, calling a shared function not yet supported - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/scope-example.comp.ret.ok b/test/run-drun/ok/scope-example.comp.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/scope-example.comp.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/scope-example.ic-stub-run.ok b/test/run-drun/ok/scope-example.ic-stub-run.ok deleted file mode 100644 index 711ce0f41ed..00000000000 --- a/test/run-drun/ok/scope-example.ic-stub-run.ok +++ /dev/null @@ -1,7 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -← completed -→ update Test(0x4449444c0000) -Trap: EvalTrapError :0.1 "uninitialized element 0" -← rejected (RC_CANISTER_REJECT): canister trapped: EvalTrapError :0.1 "uninitialized element 0" From dc257a2d6a2bf8261102a5db00f032ca6f9a386f Mon Sep 17 00:00:00 2001 From: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> Date: Fri, 13 Dec 2019 13:03:01 +0100 Subject: [PATCH 0822/1176] Don't make multiple `..` parent directory refs cancel each other (#1023) --- src/pipeline/file_path.ml | 2 +- src/pipeline/file_path_test.ml | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/pipeline/file_path.ml b/src/pipeline/file_path.ml index b77585c12fe..8df0815d9f4 100644 --- a/src/pipeline/file_path.ml +++ b/src/pipeline/file_path.ml @@ -9,7 +9,7 @@ let normalise file_path = | "" -> () | "." -> () | ".." -> - if Stack.is_empty acc + if Stack.is_empty acc || Stack.top acc = ".." then Stack.push ".." acc else ignore (Stack.pop acc) | segment -> Stack.push segment acc); diff --git a/src/pipeline/file_path_test.ml b/src/pipeline/file_path_test.ml index a86db8f1da7..348b27b7154 100644 --- a/src/pipeline/file_path_test.ml +++ b/src/pipeline/file_path_test.ml @@ -40,6 +40,9 @@ let%test "it applies parent directory traversals" = let%test "it keeps parent directory references at the start of a path" = normalise_test_case "../foo/lib" "../foo/lib" +let%test "it keeps multiple parent directory references at the start of a path" = + normalise_test_case "../../foo/lib" "../../foo/lib" + let%test "it does everything at once" = normalise_test_case "../foo//.././lib" "../lib" From 04c3db4118fa79008384a445b50927c8f4b32821 Mon Sep 17 00:00:00 2001 From: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> Date: Mon, 16 Dec 2019 11:01:44 +0100 Subject: [PATCH 0823/1176] dfx renamed the ide command to _language-service (#1028) --- emacs/init.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/emacs/init.el b/emacs/init.el index 0553b57c063..6b6325db2bf 100644 --- a/emacs/init.el +++ b/emacs/init.el @@ -31,7 +31,7 @@ ;; ide`. If you have a more complicated setup you have to pass the ;; proper entry point and library paths to the `mo-ide` binary ;; yourself. -(setq mo/lsp-command '("dfx" "ide")) +(setq mo/lsp-command '("dfx" "_language-service")) ;; Change this to point to the directory where you cloned the ;; motoko repo From 30fcf512cbb625e6552b822ec03d6cf161b7cae9 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 16 Dec 2019 11:38:43 +0100 Subject: [PATCH 0824/1176] Check_ir: Oneway function must return unit (#1025) while working on #1020 I made some mistakes that this would have caught. --- src/ir_def/check_ir.ml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 60feeba2d98..f476f6f9abb 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -169,7 +169,10 @@ let rec check_typ env typ : unit = match control with | T.Returns -> check env' no_region (sort = T.Shared T.Write) - "one-shot query function pointless" + "one-shot query function pointless"; + check env' no_region (ts2 = []) + "one-shot function cannot have non-unit return types:\n %s" + (T.string_of_typ_expand (T.seq ts2)); | T.Promises -> check env no_region env.flavor.Ir.has_async_typ "promising function in post-async flavor"; From 2bfbdc7c5f184b297f12c3226d100c92a5235464 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 16 Dec 2019 11:49:59 +0100 Subject: [PATCH 0825/1176] Check_ir: Check types of ActorOfIdBlob (#1021) --- src/ir_def/check_ir.ml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index f476f6f9abb..c91da6d2a23 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -392,6 +392,15 @@ let rec check_exp env (exp:Ir.exp) : unit = | CastPrim (t1, t2), [e] -> typ e <: t1; t2 <: t + | ActorOfIdBlob actor_typ, [e] -> + typ e <: T.blob; + check_typ env actor_typ; + begin match T.normalize actor_typ with + | T.Obj (T.Actor, _) -> () + | _ -> error env exp.at "ActorOfIdBlob cast to actor object type, not\n %s" + (T.string_of_typ_expand actor_typ) + end; + actor_typ <: t; | OtherPrim _, _ -> () | _ -> error env exp.at "PrimE with wrong number of arguments" From 0795267dc19c9b7bf0c91c140e4236cf620f22f6 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 16 Dec 2019 11:56:19 +0100 Subject: [PATCH 0826/1176] ic-stub: Correctly trap upon double response (#1017) Helps debugging #942 --- ic-stub/src/IC/Canister.hs | 12 +++++---- ic-stub/src/IC/Canister/Imp.hs | 40 +++++++++++++++++----------- ic-stub/src/IC/Canister/Interface.hs | 4 +-- ic-stub/src/IC/Stub.hs | 26 +++++++++--------- ic-stub/src/IC/Types.hs | 2 ++ 5 files changed, 49 insertions(+), 35 deletions(-) diff --git a/ic-stub/src/IC/Canister.hs b/ic-stub/src/IC/Canister.hs index 3bc96edfdae..c4bb63f4664 100644 --- a/ic-stub/src/IC/Canister.hs +++ b/ic-stub/src/IC/Canister.hs @@ -31,9 +31,9 @@ type QueryFunc = WasmState -> TrapOr Response data CanisterModule = CanisterModule { init_method :: InitFunc - , update_methods :: MethodName ↦ (ExistingCanisters -> EntityId -> Blob -> UpdateFunc) + , update_methods :: MethodName ↦ (ExistingCanisters -> EntityId -> Responded -> Blob -> UpdateFunc) , query_methods :: MethodName ↦ (EntityId -> Blob -> QueryFunc) - , callbacks :: Callback -> ExistingCanisters -> Response -> UpdateFunc + , callbacks :: Callback -> ExistingCanisters -> Responded -> Response -> UpdateFunc } parseCanister :: Blob -> Either String CanisterModule @@ -46,7 +46,9 @@ concreteToAbstractModule :: Module -> CanisterModule concreteToAbstractModule wasm_mod = CanisterModule { init_method = \ex cid caller dat -> initialize ex wasm_mod cid caller dat , update_methods = M.fromList - [ (m, \ex caller dat wasm_state -> invoke wasm_state (CI.Update m ex caller dat)) + [ (m, + \ex caller responded dat wasm_state -> + invoke wasm_state (CI.Update m ex caller responded dat)) | n <- exportedFunctions wasm_mod , Just m <- return $ stripPrefix "canister_update " n ] @@ -56,6 +58,6 @@ concreteToAbstractModule wasm_mod = CanisterModule | n <- exportedFunctions wasm_mod , Just m <- return $ stripPrefix "canister_query " n ] - , callbacks = \cb ex res wasm_state -> - invoke wasm_state (CI.Callback cb ex res) + , callbacks = \cb ex responded res wasm_state -> + invoke wasm_state (CI.Callback cb ex responded res) } diff --git a/ic-stub/src/IC/Canister/Imp.hs b/ic-stub/src/IC/Canister/Imp.hs index efe5e363a77..a9cf5705192 100644 --- a/ic-stub/src/IC/Canister/Imp.hs +++ b/ic-stub/src/IC/Canister/Imp.hs @@ -53,6 +53,7 @@ data ExecutionState s = ExecutionState , params :: Params , existing_canisters :: ExistingCanisters -- now the mutable parts + , responded :: Responded , response :: Maybe Response , reply_data :: Blob , calls :: [MethodCall] @@ -60,12 +61,13 @@ data ExecutionState s = ExecutionState } -initalExecutionState :: CanisterId -> Instance s -> ExistingCanisters -> ExecutionState s -initalExecutionState self_id inst ex = ExecutionState +initalExecutionState :: CanisterId -> Instance s -> ExistingCanisters -> Responded -> ExecutionState s +initalExecutionState self_id inst ex responded = ExecutionState { inst , self_id , existing_canisters = ex , params = Params Nothing Nothing 0 "" + , responded , response = Nothing , reply_data = mempty , calls = mempty @@ -237,10 +239,13 @@ systemAPI esref = return $ BSU.fromString msg assert_not_responded :: HostM s () - assert_not_responded = + assert_not_responded = do + gets responded >>= \case + Responded False -> return () + Responded True -> throwError "This call has already been responded to earlier" gets response >>= \case Nothing -> return () - Just _ -> throwError "This call has already been responded to" + Just _ -> throwError "This call has already been responded to in this function" msg_reply_data_append :: (Int32, Int32) -> HostM s () msg_reply_data_append (src, size) = do @@ -351,15 +356,18 @@ rawInvoke esref (CI.Initialize ex wasm_mod caller dat) = rawInitializeMethod esref ex wasm_mod caller dat rawInvoke esref (CI.Query name caller dat) = rawQueryMethod esref name caller dat -rawInvoke esref (CI.Update name ex caller dat) = - rawUpdateMethod esref name ex caller dat -rawInvoke esref (CI.Callback cb ex res) = - rawCallbackMethod esref cb ex res +rawInvoke esref (CI.Update name ex caller responded dat) = + rawUpdateMethod esref name ex caller responded dat +rawInvoke esref (CI.Callback cb ex responded res) = + rawCallbackMethod esref cb ex responded res + +cantRespond :: Responded +cantRespond = Responded True rawInitializeMethod :: ImpState s -> ExistingCanisters -> Module -> EntityId -> Blob -> ST s (TrapOr InitResult) rawInitializeMethod (esref, cid, inst) ex wasm_mod caller dat = do result <- runExceptT $ do - let es = (initalExecutionState cid inst ex) + let es = (initalExecutionState cid inst ex cantRespond) { params = Params { param_dat = Just dat , param_caller = Just caller @@ -382,7 +390,7 @@ rawInitializeMethod (esref, cid, inst) ex wasm_mod caller dat = do rawQueryMethod :: ImpState s -> MethodName -> EntityId -> Blob -> ST s (TrapOr Response) rawQueryMethod (esref, cid, inst) method caller dat = do - let es = (initalExecutionState cid inst []) + let es = (initalExecutionState cid inst [] cantRespond) { params = Params { param_dat = Just dat , param_caller = Just caller @@ -400,9 +408,9 @@ rawQueryMethod (esref, cid, inst) method caller dat = do | Just r <- response es' -> return $ Return r | otherwise -> return $ Trap "No response" -rawUpdateMethod :: ImpState s -> MethodName -> ExistingCanisters -> EntityId -> Blob -> ST s (TrapOr UpdateResult) -rawUpdateMethod (esref, cid, inst) method ex caller dat = do - let es = (initalExecutionState cid inst ex) +rawUpdateMethod :: ImpState s -> MethodName -> ExistingCanisters -> EntityId -> Responded -> Blob -> ST s (TrapOr UpdateResult) +rawUpdateMethod (esref, cid, inst) method ex caller responded dat = do + let es = (initalExecutionState cid inst ex responded) { params = Params { param_dat = Just dat , param_caller = Just caller @@ -417,14 +425,14 @@ rawUpdateMethod (esref, cid, inst) method ex caller dat = do Left err -> return $ Trap err Right (_, es') -> return $ Return (new_canisters es', calls es', response es') -rawCallbackMethod :: ImpState s -> Callback -> ExistingCanisters -> Response -> ST s (TrapOr UpdateResult) -rawCallbackMethod (esref, cid, inst) callback ex res = do +rawCallbackMethod :: ImpState s -> Callback -> ExistingCanisters -> Responded -> Response -> ST s (TrapOr UpdateResult) +rawCallbackMethod (esref, cid, inst) callback ex responded res = do let params = case res of Reply dat -> Params { param_dat = Just dat, param_caller = Nothing, reject_code = 0, reject_message = "" } Reject (rc, reject_message) -> Params { param_dat = Nothing, param_caller = Nothing, reject_code = rejectCode rc, reject_message } - let es = (initalExecutionState cid inst ex) { params } + let es = (initalExecutionState cid inst ex responded) { params } let WasmClosure fun_idx env = case res of Reply {} -> reply_callback callback diff --git a/ic-stub/src/IC/Canister/Interface.hs b/ic-stub/src/IC/Canister/Interface.hs index 0e2551df33f..779a61caa91 100644 --- a/ic-stub/src/IC/Canister/Interface.hs +++ b/ic-stub/src/IC/Canister/Interface.hs @@ -20,5 +20,5 @@ import IC.Wasm.Winter (Module) data CanisterMethod r where Initialize :: ExistingCanisters -> Module -> EntityId -> Blob -> CanisterMethod InitResult Query :: MethodName -> EntityId -> Blob -> CanisterMethod Response - Update :: MethodName -> ExistingCanisters -> EntityId -> Blob -> CanisterMethod UpdateResult - Callback :: Callback -> ExistingCanisters -> Response -> CanisterMethod UpdateResult + Update :: MethodName -> ExistingCanisters -> EntityId -> Responded -> Blob -> CanisterMethod UpdateResult + Callback :: Callback -> ExistingCanisters -> Responded -> Response -> CanisterMethod UpdateResult diff --git a/ic-stub/src/IC/Stub.hs b/ic-stub/src/IC/Stub.hs index 896ebac94dd..87040c83ec9 100644 --- a/ic-stub/src/IC/Stub.hs +++ b/ic-stub/src/IC/Stub.hs @@ -87,7 +87,7 @@ type CallId = Int data CallContext = CallContext { canister :: CanisterId , origin :: CallOrigin - , responded :: Bool + , responded :: Responded , last_trap :: Maybe String } deriving Show @@ -158,11 +158,11 @@ nextStarved :: ICT m => m (Maybe CallId) nextStarved = gets $ \ic -> listToMaybe [ c | (c, ctxt) <- M.toList (call_contexts ic) - , not $ responded ctxt + , Responded False <- return $ responded ctxt , null [ () | ResponseMessage { call_context = c' } <- toList (messages ic), c' == c ] , null [ () - | CallContext { responded = False, origin = FromCanister c' _} + | CallContext { responded = Responded False, origin = FromCanister c' _} <- M.elems (call_contexts ic) , c' == c ] @@ -217,7 +217,7 @@ processRequest r@(InstallRequest canister_id user_id can_mod dat) = ctxt_id <- newCallContext $ CallContext { canister = canister_id , origin = FromInit user_id - , responded = True + , responded = Responded True , last_trap = Nothing } @@ -237,7 +237,7 @@ processRequest r@(UpdateRequest canister_id _user_id method arg) = do ctxt_id <- newCallContext $ CallContext { canister = canister_id , origin = FromUser r - , responded = False + , responded = Responded False , last_trap = Nothing } enqueueMessage $ CallMessage @@ -268,7 +268,7 @@ modifyCallContext ctxt_id f = respondCallContext :: ICT m => CallId -> Response -> m () respondCallContext ctxt_id response = do -- TODO: check no prior response - modifyCallContext ctxt_id $ \ctxt -> ctxt { responded = True } + modifyCallContext ctxt_id $ \ctxt -> ctxt { responded = Responded True } enqueueMessage $ ResponseMessage { call_context = ctxt_id, response } rememberTrap :: ICT m => CallId -> String -> m () @@ -289,33 +289,35 @@ callerOfCallID ctxt_id = do FromInit entity_id -> return entity_id calleeOfCallID :: ICT m => CallId -> m EntityId -calleeOfCallID ctxt_id = do - ctxt <- getCallContext ctxt_id - return $ canister ctxt +calleeOfCallID ctxt_id = canister <$> getCallContext ctxt_id + +respondedCallID :: ICT m => CallId -> m Responded +respondedCallID ctxt_id = responded <$> getCallContext ctxt_id invokeEntry :: ICT m => CallId -> CanState -> EntryPoint -> m (TrapOr (WasmState, UpdateResult)) invokeEntry ctxt_id (CanState wasm_state can_mod) entry = do + responded <- respondedCallID ctxt_id existing_canisters <- gets (M.keys . canisters) case entry of Public method dat -> do caller <- callerOfCallID ctxt_id case M.lookup method (update_methods can_mod) of Just f -> - return $ f existing_canisters caller dat wasm_state + return $ f existing_canisters caller responded dat wasm_state Nothing -> do let reject = Reject (RC_DESTINATION_INVALID, "update method does not exist: " ++ method) return $ Return (wasm_state, ([], [], Just reject)) Closure cb r -> - return $ callbacks can_mod cb existing_canisters r wasm_state + return $ callbacks can_mod cb existing_canisters responded r wasm_state newCall :: ICT m => CallId -> MethodCall -> m () newCall from_ctxt_id call = do new_ctxt_id <- newCallContext $ CallContext { canister = call_callee call , origin = FromCanister from_ctxt_id (call_callback call) - , responded = False + , responded = Responded False , last_trap = Nothing } enqueueMessage $ CallMessage diff --git a/ic-stub/src/IC/Types.hs b/ic-stub/src/IC/Types.hs index a76fb8238d9..39415fb0824 100644 --- a/ic-stub/src/IC/Types.hs +++ b/ic-stub/src/IC/Types.hs @@ -25,6 +25,8 @@ prettyBlob b = "0x" ++ T.unpack (T.encodeHex (BS.toStrict b)) prettyID :: EntityId -> String prettyID = prettyBlob . rawEntityId -- implement the "ic:…" stuff +newtype Responded = Responded Bool + deriving Show data RejectCode = RC_SYS_FATAL From e10eec5cd7ac2201145c91b8c7b020cf8db997c5 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 16 Dec 2019 13:40:34 +0100 Subject: [PATCH 0827/1176] Pull in hex decoding and CRC calculation (#1030) * Import URL decoding code from #2001 * Add some tests to hex decoding and crc calculation --- src/lib/dune | 3 ++- src/lib/lib.ml | 56 +++++++++++++++++++++++++++++++++++++++++++++++++ src/lib/lib.mli | 12 +++++++++++ 3 files changed, 70 insertions(+), 1 deletion(-) diff --git a/src/lib/dune b/src/lib/dune index 87151ffe9b6..c69f23f29d4 100644 --- a/src/lib/dune +++ b/src/lib/dune @@ -1,5 +1,6 @@ (library (name lib) (libraries bigarray) - (preprocess (pps bisect_ppx -conditional)) + (inline_tests) + (preprocess (pps ppx_inline_test bisect_ppx -conditional)) ) diff --git a/src/lib/lib.ml b/src/lib/lib.ml index 94404402787..853dc5900db 100644 --- a/src/lib/lib.ml +++ b/src/lib/lib.ml @@ -46,6 +46,36 @@ struct else Int32.compare i1 i2 end +module CRC = +struct + let crc8 (bs : bytes) : int = + let inner _ = function + | crc when crc land 0x80 <> 0 -> (crc lsl 1) lxor 0x7 + | crc -> crc lsl 1 in + let outer crc b = + List.fold_right inner [0;1;2;3;4;5;6;7] (Char.code b lxor crc) land 0xFF in + Seq.fold_left outer 0 (Bytes.to_seq bs) +end + +module Hex = +struct + let hexdigit = let open Char in function + | c when c >= '0' && c <= '9' -> code c - code '0' + | c when c >= 'A' && c <= 'F' -> code c - code 'A' + 10 + | c when c >= 'a' && c <= 'f' -> code c - code 'a' + 10 + | _ -> assert false + + let bytes_of_hex hex : bytes = + let open String in + let extract i _ = + Char.chr (hexdigit (get hex (i * 2)) lsl 4 lor hexdigit (get hex (i * 2 + 1))) in + Bytes.mapi extract (Bytes.create (length hex / 2)) + + let int_of_hex_byte hex : int = + assert (String.length hex = 2); + String.(hexdigit (get hex 0) lsl 4 lor hexdigit (get hex 1)) +end + module String = struct let implode cs = @@ -376,3 +406,29 @@ struct let value_opt p = !p let value p = match !p with Some x -> x | None -> raise Promise end + +[@@@warning "-60"] +module Test = +struct +(* need to put tests in this file because + dune does not like it if other files in lib depend on Lib + Maybe we should break up lib into its components, now that + it is a dune library. +*) + let%test "bytes_of_hex DEADBEEF" = + Hex.bytes_of_hex "DEADBEEF" = Bytes.of_string "\xDE\xAD\xBE\xEF" + let%test "bytes_of_hex 0000" = + Hex.bytes_of_hex "0000" = Bytes.of_string "\x00\x00" + let%test "bytes_of_hex empty" = + Hex.bytes_of_hex "" = Bytes.of_string "" + + let%test "int_of_hex_byte 00" = Hex.int_of_hex_byte "00" = 0 + let%test "int_of_hex_byte AB" = Hex.int_of_hex_byte "AB" = 0xAB + let%test "int_of_hex_byte FF" = Hex.int_of_hex_byte "FF" = 0xFF + + (* see https://crccalc.com/ *) + let %test "crc8 DEADBEEF" = CRC.crc8 (Bytes.of_string "\xDE\xAD\xBE\xEF") = 0xCA + let %test "crc8 empty" = CRC.crc8 (Bytes.of_string "") = 0x00 + let %test "crc8 0000" = CRC.crc8 (Bytes.of_string "\x00\x00") = 0x00 +end + diff --git a/src/lib/lib.mli b/src/lib/lib.mli index 9cd858f1893..ea065518f36 100644 --- a/src/lib/lib.mli +++ b/src/lib/lib.mli @@ -137,3 +137,15 @@ sig val chop_suffix : string -> string -> string option val lightweight_escaped : string -> string end + +module CRC : +sig + val crc8 : bytes -> int +end + +module Hex : +sig + val hexdigit : char -> int + val bytes_of_hex : string -> bytes + val int_of_hex_byte : string -> int +end From 1a2c596efea205db3ba4fb07a0e602a4221e48e3 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 16 Dec 2019 14:03:28 +0100 Subject: [PATCH 0828/1176] Update building instructions (#1029) --- Building.md | 5 +++-- default.nix | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Building.md b/Building.md index 62d7aad8b57..bf09698b502 100644 --- a/Building.md +++ b/Building.md @@ -32,11 +32,11 @@ This invokes `dune` under the hood, which will, as a side effect, also create You can get a development environment that is independent of nix (although installing all required tools without nix is out of scope). - * Use your system’s package manager to install `ocaml` and + * Use your system’s package manager to install `ocaml` (4.07) and [`opam`](https://opam.ocaml.org/doc/Install.html) * Install the packages: ``` - opam install num vlq yojson menhir + opam install num vlq yojson menhir stdio js_of_ocaml js_of_ocaml-ppx ppx_inline_test bisect_ppx atdgen ``` * Install the `wasm` Ocaml package. We use a newer version than is on opam, and a fork that supports the multi-value extension. See `nix/ocaml-wasm.nix` for @@ -45,6 +45,7 @@ installing all required tools without nix is out of scope). ``` cp -R $(nix-build --no-out-link -Q -A wasm.src)/interpreter /tmp/interpreter cd /tmp/interpreter + chmod u+w -R . make install ``` * Install various command line tools used by, in particuar, the test suite: diff --git a/default.nix b/default.nix index 2f6c99e22a2..a1fcbd91d89 100644 --- a/default.nix +++ b/default.nix @@ -340,6 +340,7 @@ rec { [ { name = "bin/FileCheck"; path = "${nixpkgs.llvm}/bin/FileCheck";} ]; wabt = nixpkgs.wabt; wasmtime = nixpkgs.wasmtime; + wasm = nixpkgs.wasm; users-guide = stdenv.mkDerivation { name = "users-guide"; From b626349e1c516355f5f00a1bbd3f70ad4294110a Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 16 Dec 2019 14:42:15 +0100 Subject: [PATCH 0829/1176] Towards actor imports (#1020) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit an `ImportE` can now either import a Motoko library (`import "mo:…"`), or an actor (`import "ic:…"`). This refactors `Pipeline.resolve_imports` to cater for that. Currently all `import "ic:…"` imports ignore the filename, assume type `actor {}`, and assert false if any other id than `ic:00…4000..` is imported. It warns that actor imports are still unchecked Next steps: * Get the URL parser from #1001 and compile to the proper blob. * Add support for the `--actor-idl` command line flag * Actually read the IDL files and implement type import as specified in https://github.com/dfinity-lab/motoko/blob/master/design/IDL-Motoko.md --- src/ir_interpreter/interpret_ir.ml | 2 +- src/lang_utils/diag.ml | 2 + src/lang_utils/diag.mli | 1 + src/languageServer/declaration_index.ml | 8 +- src/languageServer/source_file.ml | 12 +- src/lowering/desugar.ml | 13 +- src/mo_def/arrange.ml | 2 +- src/mo_def/syntax.ml | 9 +- src/mo_frontend/parser.mly | 2 +- src/mo_frontend/typing.ml | 30 ++- src/mo_interpreter/interpret.ml | 8 +- src/pipeline/pipeline.ml | 57 +++-- src/pipeline/pipeline.mli | 2 +- src/pipeline/resolve_import.ml | 291 ++++++++++++---------- src/pipeline/resolve_import.mli | 17 +- test/fail/ok/self-import.tc.ok | 2 +- test/run-drun/actor-import.mo | 11 + test/run-drun/ok/actor-import.drun-run.ok | 2 + test/run-drun/ok/actor-import.tc.ok | 1 + 19 files changed, 286 insertions(+), 186 deletions(-) create mode 100644 test/run-drun/actor-import.mo create mode 100644 test/run-drun/ok/actor-import.drun-run.ok create mode 100644 test/run-drun/ok/actor-import.tc.ok diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index 4adb536793f..7e3f0f70641 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -365,7 +365,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = ) | CastPrim _, [e] -> interpret_exp env e k | ActorOfIdBlob t, [e] -> - assert false; (* probably related to #986 *) + trap exp.at "ActorOfIdBlob not implemented" | NumConvPrim (t1, t2), exps -> interpret_exps env exps [] (fun vs -> let arg = match vs with [v] -> v | _ -> V.Tup vs in diff --git a/src/lang_utils/diag.ml b/src/lang_utils/diag.ml index 7ba7e8bb5e3..b21c5570b8c 100644 --- a/src/lang_utils/diag.ml +++ b/src/lang_utils/diag.ml @@ -13,6 +13,8 @@ type 'a result = ('a * messages, messages) Pervasives.result let return x = Ok (x, []) +let warn at cat text = Ok ((), [{ sev = Warning; at; cat; text}]) + let map f = function | Pervasives.Error msgs -> Pervasives.Error msgs | Ok (x, msgs) -> Ok (f x, msgs) diff --git a/src/lang_utils/diag.mli b/src/lang_utils/diag.mli index b76c34f1495..8a0adfd2b00 100644 --- a/src/lang_utils/diag.mli +++ b/src/lang_utils/diag.mli @@ -33,6 +33,7 @@ val fold: ('a -> 'b -> 'a result) -> 'a -> 'b list -> 'a result val flush_messages : 'a result -> 'a option val run : 'a result -> 'a (* Prints messages, and exits upon failure *) +val warn : Source.region -> string -> string -> unit result (* An impure, but more more convenient interface. diff --git a/src/languageServer/declaration_index.ml b/src/languageServer/declaration_index.ml index 231cf5bc562..893e42e03b8 100644 --- a/src/languageServer/declaration_index.ml +++ b/src/languageServer/declaration_index.ml @@ -57,15 +57,17 @@ let lookup_module (path : path) (index : t) : ide_decl list option = - match Pipeline.ResolveImport.match_package_name path with - | None -> Index.find_opt path index - | Some (pkg, path) -> + let open Pipeline.ResolveImport in + match parse_import path with + | RelativeImport path -> Index.find_opt path index + | PackageImport (pkg, path) -> Lib.Option.bind (List.find_opt (fun (name, _) -> pkg = name) !Mo_config.Flags.package_urls) (fun (_, pkg_path) -> Index.find_opt (Filename.concat pkg_path path) index) + | ActorImport _ -> assert false let empty : t = Index.empty diff --git a/src/languageServer/source_file.ml b/src/languageServer/source_file.ml index 3ae4cf324dc..a25fe2c81e0 100644 --- a/src/languageServer/source_file.ml +++ b/src/languageServer/source_file.ml @@ -40,12 +40,15 @@ let cursor_target_at_pos try loop (next ()) with _ -> None let is_package_path (path : string) = - Lib.Option.is_some (Pipeline.ResolveImport.match_package_name path) + let open Pipeline.ResolveImport in + match parse_import path with + | PackageImport _ -> true + | _ -> false let uri_for_package (path : string) = - match Pipeline.ResolveImport.match_package_name path with - | None -> None - | Some (pkg, path) -> + let open Pipeline.ResolveImport in + match parse_import path with + | PackageImport (pkg, path) -> begin match List.find_opt (fun (name, _) -> pkg = name) @@ -55,6 +58,7 @@ let uri_for_package (path : string) = (* Resolved package paths are always absolute *) Some ("file://" ^ Filename.concat pkg_path path) end + | _ -> None let import_relative_to_project_root root module_path dependency = if is_package_path dependency diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index ee9b58c58b3..fef4b7b5e89 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -139,9 +139,16 @@ and exp' at note = function | S.AwaitE e -> I.AwaitE (exp e) | S.AssertE e -> I.AssertE (exp e) | S.AnnotE (e, _) -> assert false - | S.ImportE (f, fp) -> - if !fp = "" then assert false; (* unresolved import *) - I.VarE (id_of_full_path !fp).it + | S.ImportE (f, ir) -> + begin match !ir with + | S.Unresolved -> raise (Invalid_argument ("Unresolved import " ^ f)) + | S.LibPath fp -> I.VarE (id_of_full_path fp).it + | S.IDLPath fp -> + assert (f = "ic:000000000000040054"); + let blob_id = "\x00\x00\x00\x00\x00\x00\x04\x00" in + (* TODO: Properly decode the URL *) + I.(PrimE (ActorOfIdBlob note.note_typ, [blobE blob_id])) + end | S.PrimE s -> raise (Invalid_argument ("Unapplied prim " ^ s)) and lexp e = diff --git a/src/mo_def/arrange.ml b/src/mo_def/arrange.ml index 7a3377c9f2e..8198140f0f4 100644 --- a/src/mo_def/arrange.ml +++ b/src/mo_def/arrange.ml @@ -56,7 +56,7 @@ let rec exp e = match e.it with | OptE e -> "OptE" $$ [exp e] | TagE (i, e) -> "TagE" $$ [id i; exp e] | PrimE p -> "PrimE" $$ [Atom p] - | ImportE (f, fp) -> "ImportE" $$ [Atom (if !fp = "" then f else !fp)] + | ImportE (f, _fp) -> "ImportE" $$ [Atom f] | ThrowE e -> "ThrowE" $$ [exp e] | TryE (e, cs) -> "TryE" $$ [exp e] @ List.map catch cs diff --git a/src/mo_def/syntax.ml b/src/mo_def/syntax.ml index dff44ea575a..a0c9fc187bc 100644 --- a/src/mo_def/syntax.ml +++ b/src/mo_def/syntax.ml @@ -10,6 +10,12 @@ type typ_note = {note_typ : Type.typ; note_eff : Type.eff} let empty_typ_note = {note_typ = Type.Pre; note_eff = Type.Triv} +(* Resolved imports (filled in separately after parsing) *) + +type resolved_import = + | Unresolved + | LibPath of string + | IDLPath of string (* Identifiers *) @@ -145,7 +151,7 @@ and exp' = | AwaitE of exp (* await *) | AssertE of exp (* assertion *) | AnnotE of exp * typ (* type annotation *) - | ImportE of (string * string ref) (* import statement *) + | ImportE of (string * resolved_import ref) (* import statement *) | ThrowE of exp (* throw exception *) | TryE of exp * case list (* catch exception *) (* @@ -222,3 +228,4 @@ let string_of_lit = function | TextLit t -> t | FloatLit f -> Value.Float.to_pretty_string f | PreLit _ -> assert false + diff --git a/src/mo_frontend/parser.mly b/src/mo_frontend/parser.mly index c6e6410e418..0d040c28506 100644 --- a/src/mo_frontend/parser.mly +++ b/src/mo_frontend/parser.mly @@ -680,7 +680,7 @@ class_body : imp : | IMPORT xf=id_opt EQ? f=TEXT { let _, x = xf "import" $sloc in - let_or_exp true x (ImportE (f, ref "")) (at $sloc) } + let_or_exp true x (ImportE (f, ref Unresolved)) (at $sloc) } parse_prog : | is=seplist(imp, semicolon) ds=seplist(dec, semicolon) EOF diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 5c1cc639f9c..10abc404252 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -169,6 +169,20 @@ let infer_mut mut : T.typ -> T.typ = | Const -> fun t -> t | Var -> fun t -> T.Mut t +(* Imports *) + +let check_import env at f ri = + let full_path = + match !ri with + | Unresolved -> error env at "unresolved import %s" f + | LibPath fp -> fp + | IDLPath fp -> fp + in + match T.Env.find_opt full_path env.libs with + | Some T.Pre -> + error env at "cannot infer type of forward import %s" f + | Some t -> t + | None -> error env at "imported file %s not loaded" full_path (* Paths *) @@ -955,14 +969,8 @@ and infer_exp'' env exp : T.typ = let t = check_typ env typ in if not env.pre then check_exp env t exp1; t - | ImportE (_, fp) -> - assert (!fp <> ""); - (match T.Env.find_opt !fp env.libs with - | Some T.Pre -> - error env exp.at "cannot infer type of forward import %s" !fp - | Some t -> t - | None -> error env exp.at "unresolved import %s" !fp - ) + | ImportE (f, ri) -> + check_import env exp.at f ri and check_exp env t exp = assert (not env.pre); @@ -1595,9 +1603,8 @@ and check_dec env t dec = and infer_val_path env exp : T.typ option = match exp.it with - | ImportE (_, fp) -> - assert (!fp <> ""); - T.Env.find_opt !fp env.libs + | ImportE (f, ri) -> + Some (check_import env exp.at f ri) | VarE id -> T.Env.find_opt id.it env.vals | DotE (path, id) -> @@ -1836,6 +1843,7 @@ and infer_dec_valdecs env dec : Scope.t = con_env = T.ConSet.singleton c; } + (* Programs *) let infer_prog scope prog : (T.typ * Scope.t) Diag.result = diff --git a/src/mo_interpreter/interpret.ml b/src/mo_interpreter/interpret.ml index 5da3190e8f0..a61b2b3e38d 100644 --- a/src/mo_interpreter/interpret.ml +++ b/src/mo_interpreter/interpret.ml @@ -379,8 +379,12 @@ and interpret_exp_mut env exp (k : V.value V.cont) = | Some v -> k v | None -> trap exp.at "accessing identifier before its definition" end - | ImportE (f, fp) -> - k (find !fp env.libs) + | ImportE (f, ri) -> + (match !ri with + | Unresolved -> assert false + | LibPath fp -> k (find fp env.libs) + | IDLPath _ -> trap exp.at "actor import" + ) | LitE lit -> k (interpret_lit env lit) | UnE (ot, op, exp1) -> diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index c254d4658a3..9caa4bf64e4 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -107,7 +107,7 @@ let parse_file filename : parse_result = (* Import file name resolution *) -type resolve_result = (Syntax.prog * ResolveImport.S.t) Diag.result +type resolve_result = (Syntax.prog * ResolveImport.resolved_imports) Diag.result let resolve_prog (prog, base) : resolve_result = Diag.map @@ -159,7 +159,6 @@ let check_lib senv lib : Scope.scope Diag.result = Diag.bind (Definedness.check_lib lib) (fun () -> Diag.return sscope) ) - (* Imported file loading *) (* @@ -225,29 +224,35 @@ let chase_imports parsefn senv0 imports : (Syntax.lib list * Scope.scope) Diag.r let senv = ref senv0 in let libs = ref [] in - let rec go f = - if Type.Env.mem f !senv.Scope.lib_env then - Diag.return () - else if mem f !pending then - Error [{ - Diag.sev = Diag.Error; at = Source.no_region; cat = "import"; - text = Printf.sprintf "file %s must not depend on itself" f - }] - else begin - pending := add f !pending; - Diag.bind (parsefn f) (fun (prog, base) -> - Diag.bind (Static.prog prog) (fun () -> - Diag.bind (ResolveImport.resolve !Flags.package_urls prog base) (fun more_imports -> - Diag.bind (go_set more_imports) (fun () -> - let lib = lib_of_prog f prog in - Diag.bind (check_lib !senv lib) (fun sscope -> - libs := lib :: !libs; (* NB: Conceptually an append *) + let rec go ri = match ri.Source.it with + | Syntax.Unresolved -> assert false + | Syntax.LibPath f -> + if Type.Env.mem f !senv.Scope.lib_env then + Diag.return () + else if mem ri.Source.it !pending then + Error [{ + Diag.sev = Diag.Error; at = ri.Source.at; cat = "import"; + text = Printf.sprintf "file %s must not depend on itself" f + }] + else begin + pending := add ri.Source.it !pending; + Diag.bind (parsefn f) (fun (prog, base) -> + Diag.bind (Static.prog prog) (fun () -> + Diag.bind (ResolveImport.resolve !Flags.package_urls prog base) (fun more_imports -> + Diag.bind (go_set more_imports) (fun () -> + let lib = lib_of_prog f prog in + Diag.bind (check_lib !senv lib) (fun sscope -> + libs := lib :: !libs; (* NB: Conceptually an append *) + senv := Scope.adjoin !senv sscope; + pending := remove ri.Source.it !pending; + Diag.return () + ))))) + end + | Syntax.IDLPath f -> + let sscope = Scope.lib f Type.(Obj (Actor, [])) in senv := Scope.adjoin !senv sscope; - pending := remove f !pending; - Diag.return () - ))))) - end - and go_set todo = Diag.traverse_ go (elements todo) + Diag.warn ri.Source.at "import" "imported actors assumed to have type actor {}" + and go_set todo = Diag.traverse_ go todo in Diag.map (fun () -> (List.rev !libs, !senv)) (go_set imports) @@ -255,9 +260,7 @@ let load_progs parsefn files senv : load_result = Diag.bind (Diag.traverse parsefn files) (fun parsed -> Diag.bind (resolve_progs parsed) (fun rs -> let progs' = List.map fst rs in - let libs = - List.fold_left ResolveImport.S.union ResolveImport.S.empty - (List.map snd rs) in + let libs = List.concat (List.map snd rs) in Diag.bind (chase_imports parsefn senv libs) (fun (libs, senv') -> Diag.bind (check_progs senv' progs') (fun senv'' -> Diag.return (libs, progs', senv'') diff --git a/src/pipeline/pipeline.mli b/src/pipeline/pipeline.mli index a78e0762444..0abd85100a7 100644 --- a/src/pipeline/pipeline.mli +++ b/src/pipeline/pipeline.mli @@ -18,7 +18,7 @@ val check_string : string -> string -> unit Diag.result val generate_idl : string list -> Idllib.Syntax.prog Diag.result val initial_stat_env : Scope.scope -val chase_imports : parse_fn -> Scope.scope -> Resolve_import.S.t -> +val chase_imports : parse_fn -> Scope.scope -> Resolve_import.resolved_imports -> (Syntax.lib list * Scope.scope) Diag.result val run_files : string list -> unit option diff --git a/src/pipeline/resolve_import.ml b/src/pipeline/resolve_import.ml index 534e0d8be21..e78c5e3818b 100644 --- a/src/pipeline/resolve_import.ml +++ b/src/pipeline/resolve_import.ml @@ -13,12 +13,26 @@ It returns a list of all imported file names. *) -(* written as a functor so we can allocate some temporary shared state without making it global *) - type filepath = string -module S = Set.Make(String) -module M = Map.Make(String) +type resolved_imports = Syntax.resolved_import Source.phrase list + +(* This returns a map from Syntax.resolved_import + to the location of the first import of that library +*) +module RIM = Map.Make + (struct + type t = Syntax.resolved_import + let compare = compare + end) + +(* The Set variant is used in the pipeline module *) +module S = Set.Make + (struct + type t = Syntax.resolved_import + let compare = compare + end) + (* a map of type package_map will map each package name to a(n optional) package URL, which for now is just a filesystem path: @@ -28,161 +42,184 @@ module M = Map.Make(String) packages("foo") = "/Users/home/username/fooPackage/1.2.3/src" *) +module M = Map.Make(String) type package_map = string M.t -type env = { - msgs : Diag.msg_store; - base : filepath; - packages : package_map; - imported : S.t ref; -} - open Syntax open Source -(* match `f` against the URL pattern 'mo://package-name/path', - optionally returning the package-name and path components as a pair of strings. +type parsed_import = + | PackageImport of (string * string) + | RelativeImport of string + | ActorImport of string - e.g., - match_package_name "mo:std/list" = Some("std", "list") - match_package_name "mo:std/foo/bar" = Some("std", "foo/bar") - match_package_name "mo:foo/bar" = Some("foo", "bar") +(* decodes `f` according to the following URL patterns: - match_package_name "mo:" = None - match_package_name "mo:std" = None - match_package_name "std/foo" = None - match_package_name "std/foo/bar" = None + parse_import "mo:std/list" = PackageImport ("std", "list") + parse_import "mo:std/foo/bar" = PackageImport ("std", "foo/bar") + parse_import "mo:foo/bar" = PackageImport ("foo", "bar") + parse_import "mo:foo" = PackageImport ("foo", "") + parse_import "ic:alias" = ActorImport "alias" + parse_import "ic:DEADBEEF" = ActorImport "DEADBEEF" + + parse_import "std/foo" = RelativeImport "std/foo" + parse_import "foo" = RelativeImport "foo" + parse_import "./foo" = RelativeImport "foo" + + TODO: This could be the place to reject things like + ic: mo: http:std/foo + and also to do proper URL decoding. *) -let match_package_name (f: string) : (string * string) option = - let rec loop (f: string) (path_accum:string) : (string * string) option = - let (dir, base) = (Filename.dirname f, Filename.basename f) in - match dir with - | "." -> if path_accum = "" then None else Some (f, path_accum) - | _ -> - let path_accum = - match path_accum with - | "" -> base - | _ -> Filename.concat base path_accum - in - loop dir path_accum - in - if String.length f < 3 then None else - let (prefix, suffix) = ( - String.sub f 0 3, - String.sub f 3 ((String.length f) - 3) - ) - in - match prefix with - | "mo:" -> loop suffix "" - | _ -> None - -(* using env, resolve import strings of the form "mo:package-name/mod1/mod2/item" - into the triple ("package-name", "package-url", "mod1/mod2/item") when the package name is defined. - Does not validate the package url or path. - *) -let resolve_package env (f: string) : (string * string * string) option = - match match_package_name f with - | None -> None - | Some (name, path) -> - if M.mem name env.packages then - Some (name, M.find name env.packages, path) - else - None - -let resolve_import_string env region (f: string) (fp: string ref) = - let f = - match resolve_package env f with - | None -> f - | Some (_pname, url, path) -> Filename.concat url path - in - let f = - if Filename.is_relative f - then Filename.concat env.base f - else f in - let f = - if Sys.file_exists f && Sys.is_directory f - then Filename.concat f "lib.mo" - else f in - let f = File_path.normalise f in - if Sys.file_exists f +let parse_import (f: string) : parsed_import = + match Lib.String.chop_prefix "mo:" f with + | Some suffix -> + begin match String.index_opt suffix '/' with + | None -> PackageImport (suffix, "") + | Some i -> + let pkg = String.sub suffix 0 i in + let path = String.sub suffix (i+1) (String.length suffix - (i+1)) in + PackageImport (pkg, path) + end + | None -> + match Lib.String.chop_prefix "ic:" f with + | Some suffix -> ActorImport suffix + | None -> + (* TODO: Check and reject other URL schemas? *) + RelativeImport (File_path.normalise f) + +let append_lib_if_needed f = + if Sys.file_exists f && Sys.is_directory f + then Filename.concat f "lib.mo" + else f + +let err_file_does_not_exist msgs at full_path = + let open Diag in + add_msg msgs { + sev = Error; + at; + cat = "import"; + text = Printf.sprintf "File \"%s\" does not exist" full_path + } + +let err_package_not_defined msgs at pkg = + let open Diag in + add_msg msgs { + sev = Error; + at; + cat = "import"; + text = Printf.sprintf "Package \"%s\" not defined" pkg + } + +let err_package_file_does_not_exist msgs f pname = + let open Diag in + add_msg msgs { + sev = Error; + at = no_region; + cat = "package"; + text = Printf.sprintf "File \"%s\" (for package `%s`) does not exist" f pname + } + +let err_package_already_defined msgs package_name = + let open Diag in + Diag.add_msg msgs { + sev = Error; + at = no_region; + cat = "--package"; + text = Printf.sprintf "Package name \"%s\" already defined" package_name; + } + +let add_lib_import msgs imported ri_ref at full_path = + let full_path = append_lib_if_needed full_path in + if Sys.file_exists full_path then begin - fp := f; - env.imported := S.add f !(env.imported) - end else - let open Diag in - add_msg env.msgs { - sev = Error; - at = region; - cat = "import"; - text = Printf.sprintf "File \"%s\" does not exist" f - } - -(* compare to the filesystem semantics of function `resolve_import_string`: - the import-string to filesystem-path resolution semantics are related, but distinct. - *) + ri_ref := LibPath full_path; + imported := RIM.add (LibPath full_path) at !imported + end else + err_file_does_not_exist msgs at full_path + +let add_idl_import msgs imported ri_ref at full_path = + ri_ref := IDLPath full_path; + imported := RIM.add (IDLPath full_path) at !imported + (* + if Sys.file_exists full_path + then begin + ri_ref := IDLPath full_path; + imported := S.add full_path !imported + end else + does_not_exist_error msgs at full_path + *) + + + +let in_base base f = + if base = "." + then f + else Filename.concat base f + +let resolve_import_string msgs base packages imported (f, ri_ref, at) = + match parse_import f with + | RelativeImport path -> + add_lib_import msgs imported ri_ref at (in_base base path) + | PackageImport (pkg,path) -> + begin match M.find_opt pkg packages with + | Some pkg_path -> + add_lib_import msgs imported ri_ref at (in_base pkg_path path) + | None -> + err_package_not_defined msgs at pkg + end + | ActorImport path -> + let full_path = (* in_base actor_base *) path in + add_idl_import msgs imported ri_ref at full_path + +(* Resolve the argument to --package. These can also be relative to base *) let resolve_package_url (msgs:Diag.msg_store) (base:filepath) (pname:string) (f: string) : string option = let f = if Filename.is_relative f - then Filename.concat base f + then in_base base f else f in let f = File_path.normalise f in if Sys.file_exists f then Some f else - let open Diag in - add_msg msgs { - sev = Error; - at = no_region; - cat = "package"; - text = Printf.sprintf "File \"%s\" (for package `%s`) does not exist" f pname - }; + begin + err_package_file_does_not_exist msgs f pname; None + end -let collect_imports (p : prog): string list = +let prog_imports (p : prog): (string * resolved_import ref * Source.region) list = let res = ref [] in let f e = match e.it with - | ImportE (f, _) -> res := f::!res; e + | ImportE (f, fp) -> res := (f, fp, e.at) ::!res; e | _ -> e in let _ = ignore (Traversals.over_prog f p) in List.rev !res -let prog env p = - let f e = match e.it with - | ImportE (f, fp) -> resolve_import_string env e.at f fp; e - | _ -> e in - ignore (Traversals.over_prog f p) +let collect_imports (p : prog): string list = + List.map (fun (f, _, _) -> f) (prog_imports p) type package_urls = (string * string) list let resolve_packages : package_urls -> filepath -> package_map Diag.result = fun purls base -> Diag.fold (fun package_map (package_name, package_url) -> - if M.mem package_name package_map then - Diag.with_message_store (fun msgs -> - let open Diag in - Diag.add_msg msgs { - sev = Error; - at = no_region; - cat = "--package"; - text = Printf.sprintf "Package name \"%s\" already defined" package_name; - }; - None - ) - else - Diag.with_message_store (fun msgs -> - match resolve_package_url msgs base package_name package_url with - | None -> None - | Some resolved_url -> Some (M.add package_name resolved_url package_map) - ) + Diag.with_message_store (fun msgs -> + if M.mem package_name package_map + then begin err_package_already_defined msgs package_name; None end + else match resolve_package_url msgs base package_name package_url with + | None -> None + | Some resolved_url -> Some (M.add package_name resolved_url package_map) ) - M.empty purls + ) + M.empty purls -let resolve : package_urls -> Syntax.prog -> filepath -> S.t Diag.result = fun purls p base -> +let resolve + : package_urls -> Syntax.prog -> filepath -> resolved_imports Diag.result + = fun purls p base -> Diag.bind (resolve_packages purls base) (fun (packages:package_map) -> - Diag.with_message_store (fun msgs -> - let base = if Sys.is_directory base then base else Filename.dirname base in - let env = { msgs; base; imported = ref S.empty; packages } in - prog env p; - Some !(env.imported) - ) + Diag.with_message_store (fun msgs -> + let base = if Sys.is_directory base then base else Filename.dirname base in + let imported = ref RIM.empty in + List.iter (resolve_import_string msgs base packages imported) (prog_imports p); + Some (List.map (fun (rim,at) -> Source.(rim @@ at)) (RIM.bindings !imported)) ) + ) diff --git a/src/pipeline/resolve_import.mli b/src/pipeline/resolve_import.mli index 5bcf24c969d..df85e7cded5 100644 --- a/src/pipeline/resolve_import.mli +++ b/src/pipeline/resolve_import.mli @@ -1,9 +1,20 @@ open Mo_def -module S : Set.S with type elt = String.t +type filepath = string + +module S : Set.S with type elt = Syntax.resolved_import +module RIM : Map.S with type key = Syntax.resolved_import type package_urls = (string * string) list +type parsed_import = + | PackageImport of (string * string) + | RelativeImport of string + | ActorImport of string + + +type resolved_imports = Syntax.resolved_import Source.phrase list + val collect_imports : Syntax.prog -> string list -val resolve : package_urls -> Syntax.prog -> string -> S.t Diag.result -val match_package_name : string -> (string * string) option +val resolve : package_urls -> Syntax.prog -> filepath -> resolved_imports Diag.result +val parse_import : string -> parsed_import diff --git a/test/fail/ok/self-import.tc.ok b/test/fail/ok/self-import.tc.ok index 7d8d8da903a..d51b2ac1b9b 100644 --- a/test/fail/ok/self-import.tc.ok +++ b/test/fail/ok/self-import.tc.ok @@ -1 +1 @@ -(unknown location): import error, file self-import.mo must not depend on itself +self-import.mo:1.1-1.24: import error, file self-import.mo must not depend on itself diff --git a/test/run-drun/actor-import.mo b/test/run-drun/actor-import.mo new file mode 100644 index 00000000000..c1edf9a4c48 --- /dev/null +++ b/test/run-drun/actor-import.mo @@ -0,0 +1,11 @@ +import imported "ic:000000000000040054"; +actor a { + public func go() : async (actor {}) = async imported; +}; +//CALL ingress go "DIDL\x00\x00" + + +//SKIP run +//SKIP run-ir +//SKIP run-low + diff --git a/test/run-drun/ok/actor-import.drun-run.ok b/test/run-drun/ok/actor-import.drun-run.ok new file mode 100644 index 00000000000..68a7bd4541f --- /dev/null +++ b/test/run-drun/ok/actor-import.drun-run.ok @@ -0,0 +1,2 @@ +ingress(0) System +ingress(1) Completed: Canister: Payload: 0x4449444c016900010001080000000000000400 diff --git a/test/run-drun/ok/actor-import.tc.ok b/test/run-drun/ok/actor-import.tc.ok new file mode 100644 index 00000000000..98f95fb5d3c --- /dev/null +++ b/test/run-drun/ok/actor-import.tc.ok @@ -0,0 +1 @@ +actor-import.mo:1.1-1.40: warning, imported actors assumed to have type actor {} From f86375ba3a4fc8fac22498ca1e5abee63097ce8d Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 16 Dec 2019 14:52:01 +0100 Subject: [PATCH 0830/1176] Use Stdlib., not Pervasives. (#1031) --- src/codegen/compile.ml | 4 ++-- src/lang_utils/diag.ml | 12 ++++++------ src/lang_utils/diag.mli | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 8eb6ab41f28..d1a51204722 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -18,8 +18,8 @@ open Mo_config open Wasm.Ast open Wasm.Types open Source -(* Re-shadow Source.(@@), to get Pervasives.(@@) *) -let (@@) = Pervasives.(@@) +(* Re-shadow Source.(@@), to get Stdlib.(@@) *) +let (@@) = Stdlib.(@@) module G = InstrList let (^^) = G.(^^) (* is this how we import a single operator from a module that we otherwise use qualified? *) diff --git a/src/lang_utils/diag.ml b/src/lang_utils/diag.ml index b21c5570b8c..a8f23a5e433 100644 --- a/src/lang_utils/diag.ml +++ b/src/lang_utils/diag.ml @@ -9,21 +9,21 @@ type message = { } type messages = message list -type 'a result = ('a * messages, messages) Pervasives.result +type 'a result = ('a * messages, messages) Stdlib.result let return x = Ok (x, []) let warn at cat text = Ok ((), [{ sev = Warning; at; cat; text}]) let map f = function - | Pervasives.Error msgs -> Pervasives.Error msgs + | Stdlib.Error msgs -> Stdlib.Error msgs | Ok (x, msgs) -> Ok (f x, msgs) let bind x f = match x with - | Pervasives.Error msgs -> Pervasives.Error msgs + | Stdlib.Error msgs -> Stdlib.Error msgs | Ok (y, msgs1) -> match f y with | Ok (z, msgs2) -> Ok (z, msgs1 @ msgs2) - | Pervasives.Error msgs2 -> Error (msgs1 @ msgs2) + | Stdlib.Error msgs2 -> Error (msgs1 @ msgs2) let rec traverse : ('a -> 'b result) -> 'a list -> 'b list result = fun f -> function | [] -> return [] @@ -36,7 +36,7 @@ let rec traverse_ : ('a -> unit result) -> 'a list -> unit result = fun f -> fun let rec fold : ('a -> 'b -> 'a result) -> 'a -> 'b list -> 'a result = fun f acc -> function | [] -> return acc | x :: xs -> bind (f acc x) (fun y -> fold f y xs) - + type msg_store = messages ref let add_msg s m = s := m :: !s let add_msgs s ms = s := List.rev ms @ !s @@ -69,7 +69,7 @@ let with_message_store f = | _ -> Error msgs let flush_messages : 'a result -> 'a option = function - | Pervasives.Error msgs -> print_messages msgs; None + | Stdlib.Error msgs -> print_messages msgs; None | Ok (x, msgs) -> print_messages msgs; Some x let run r = match flush_messages r with diff --git a/src/lang_utils/diag.mli b/src/lang_utils/diag.mli index 8a0adfd2b00..4018670a02f 100644 --- a/src/lang_utils/diag.mli +++ b/src/lang_utils/diag.mli @@ -22,7 +22,7 @@ An extension of the built-in result type that also reports diagnostic messages. Both success and failure can come with messages) *) -type 'a result = ('a * messages, messages) Pervasives.result +type 'a result = ('a * messages, messages) Stdlib.result val return : 'a -> 'a result val bind : 'a result -> ('a -> 'b result) -> 'b result From 4b8fb63d4e7d423117ce6c15cb1fd42a3130eb8c Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 16 Dec 2019 15:22:08 +0100 Subject: [PATCH 0831/1176] Desguar: Do not get a lib_env (#1024) we have all relevant information in the notes --- src/lowering/desugar.ml | 12 ++++++------ src/lowering/desugar.mli | 3 +-- src/pipeline/pipeline.ml | 22 +++++++++++----------- 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index fef4b7b5e89..0530c4fd09c 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -446,18 +446,18 @@ and prog (p : Syntax.prog) : Ir.prog = } -let declare_import imp_env lib = +let declare_import lib = let open Source in let f = lib.note in - let t = T.Env.find f imp_env in + let t = lib.it.note.Syntax.note_typ in let typ_note = { Syntax.empty_typ_note with Syntax.note_typ = t } in let p = { it = Syntax.VarP (id_of_full_path f); at = lib.at; note = t } in { it = Syntax.LetD (p, lib.it); at = lib.at; note = typ_note } -let combine_files imp_env libs progs : Syntax.prog = +let combine_files libs progs : Syntax.prog = (* This is a hack until the backend has explicit support for libraries *) let open Source in - { it = List.map (declare_import imp_env) libs + { it = List.map declare_import libs @ List.concat (List.map (fun p -> p.it) progs) ; at = no_region ; note = match progs with @@ -467,6 +467,6 @@ let combine_files imp_env libs progs : Syntax.prog = let transform p = prog p -let transform_graph imp_env libraries progs = - prog (combine_files imp_env libraries progs) +let transform_graph libraries progs = + prog (combine_files libraries progs) diff --git a/src/lowering/desugar.mli b/src/lowering/desugar.mli index cfe10d33ef9..58391773630 100644 --- a/src/lowering/desugar.mli +++ b/src/lowering/desugar.mli @@ -1,6 +1,5 @@ open Mo_def -open Mo_types open Ir_def val transform : Syntax.prog -> Ir.prog -val transform_graph : Scope.lib_env -> Syntax.lib list -> Syntax.prog list -> Ir.prog +val transform_graph : Syntax.lib list -> Syntax.prog list -> Ir.prog diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index 9caa4bf64e4..1b87702205e 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -461,9 +461,9 @@ let transform_if transform_name trans flag env prog name = if flag then transform transform_name trans env prog name else prog -let desugar env lib_env libs progs name = +let desugar env libs progs name = phase "Desugaring" name; - let prog_ir' : Ir.prog = Lowering.Desugar.transform_graph lib_env libs progs in + let prog_ir' : Ir.prog = Lowering.Desugar.transform_graph libs progs in dump_ir Flags.dump_lowering prog_ir'; if !Flags.check_ir then Check_ir.check_prog !Flags.verbose env "Desugaring" prog_ir'; @@ -512,18 +512,18 @@ let name_progs progs = then "empty" else (Lib.List.last progs).Source.note -let lower_prog mode senv lib_env libs progs name = - let prog_ir = desugar senv lib_env libs progs name in +let lower_prog mode senv libs progs name = + let prog_ir = desugar senv libs progs name in let prog_ir = await_lowering !Flags.await_lowering initial_stat_env prog_ir name in let prog_ir = async_lowering mode !Flags.async_lowering initial_stat_env prog_ir name in let prog_ir = tailcall_optimization true initial_stat_env prog_ir name in let prog_ir = show_translation true initial_stat_env prog_ir name in prog_ir -let compile_prog mode do_link lib_env libs progs : Wasm_exts.CustomModule.extended_module = +let compile_prog mode do_link libs progs : Wasm_exts.CustomModule.extended_module = let prelude_ir = Lowering.Desugar.transform prelude in let name = name_progs progs in - let prog_ir = lower_prog mode initial_stat_env lib_env libs progs name in + let prog_ir = lower_prog mode initial_stat_env libs progs name in phase "Compiling" name; let rts = if do_link then Some (load_as_rts ()) else None in Codegen.Compile.compile mode name rts prelude_ir [prog_ir] @@ -532,19 +532,19 @@ let compile_files mode do_link files : compile_result = Diag.bind (load_progs parse_file files initial_stat_env) (fun (libs, progs, senv) -> Diag.bind (Typing.check_actors senv progs) (fun () -> - Diag.return (compile_prog mode do_link senv.Scope.lib_env libs progs))) + Diag.return (compile_prog mode do_link libs progs))) let compile_string mode s name : compile_result = Diag.bind (load_decl (parse_string name s) initial_stat_env) (fun (libs, prog, senv, _t, _sscope) -> - Diag.return (compile_prog mode false senv.Scope.lib_env libs [prog])) + Diag.return (compile_prog mode false libs [prog])) (* Interpretation (IR) *) -let interpret_ir_prog inp_env libs progs = +let interpret_ir_prog libs progs = let prelude_ir = Lowering.Desugar.transform prelude in let name = name_progs progs in - let prog_ir = lower_prog (!Flags.compile_mode) initial_stat_env inp_env libs progs name in + let prog_ir = lower_prog (!Flags.compile_mode) initial_stat_env libs progs name in phase "Interpreting" name; let open Interpret_ir in let flags = { trace = !Flags.trace; print_depth = !Flags.print_depth } in @@ -556,5 +556,5 @@ let interpret_ir_prog inp_env libs progs = let interpret_ir_files files = Lib.Option.map - (fun (libs, progs, senv) -> interpret_ir_prog senv.Scope.lib_env libs progs) + (fun (libs, progs, senv) -> interpret_ir_prog libs progs) (Diag.flush_messages (load_progs parse_file files initial_stat_env)) From 75e091917063f6607600343c4eb79cacb38aa53e Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Mon, 16 Dec 2019 18:49:50 +0000 Subject: [PATCH 0832/1176] Add support for caller ID * add support for context arguments as optional patterns on shared functions = shared query? ? * implement context arguments in interpreters and backend In a separate PR, I'd like to go further and add context arguments not just to the function space but all term interpreters so we can separated things which are closed over in environments and the ambient context, which is not. That should let us more accurately model the system API by keeping not just the caller but the reply and reject continuations in the context, with IC prims examining the context, not environment, to retrieve them. We might even be able to detect reply to wrong caller by comparing the reply in the context against a ghost reply stored in the environment, using either physical equality (cheap and cheerful) or a stamped value. --- src/codegen/compile.ml | 25 ++++- src/ir_def/arrange_ir.ml | 1 + src/ir_def/check_ir.ml | 2 + src/ir_def/construct.ml | 1 + src/ir_def/ir.ml | 1 + src/ir_interpreter/interpret_ir.ml | 99 +++++++++++-------- src/lowering/desugar.ml | 40 ++++++-- src/mo_def/arrange.ml | 10 +- src/mo_def/syntax.ml | 4 +- src/mo_frontend/definedness.ml | 10 +- src/mo_frontend/parser.mly | 15 ++- src/mo_frontend/typing.ml | 51 ++++++---- src/mo_interpreter/interpret.ml | 82 ++++++++++------ src/mo_types/type.ml | 9 +- src/mo_types/type.mli | 7 +- src/mo_values/prim.ml | 142 ++++++++++++++-------------- src/mo_values/value.ml | 20 +++- src/mo_values/value.mli | 14 ++- src/pipeline/resolve_import.ml | 1 + test/run-drun/caller.mo | 44 +++++++++ test/run-drun/ok/caller.drun-run.ok | 7 ++ test/run/caller.mo | 17 ++++ test/run/multi-caller.mo | 98 +++++++++++++++++++ test/run/ok/caller.comp.ok | 2 + test/run/ok/caller.comp.ret.ok | 1 + 25 files changed, 514 insertions(+), 189 deletions(-) create mode 100644 test/run-drun/caller.mo create mode 100644 test/run-drun/ok/caller.drun-run.ok create mode 100644 test/run/caller.mo create mode 100644 test/run/multi-caller.mo create mode 100644 test/run/ok/caller.comp.ok create mode 100644 test/run/ok/caller.comp.ret.ok diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index d1a51204722..204eea7d377 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -2868,6 +2868,24 @@ module Dfinity = struct | _ -> assert false + let caller env = + SR.Vanilla, + match E.mode env with + | Flags.ICMode | Flags.StubMode -> + let (set_len, get_len) = new_local env "len" in + let (set_blob, get_blob) = new_local env "blob" in + system_call env "ic0" "msg_caller_size" ^^ + set_len ^^ + + get_len ^^ Blob.alloc env ^^ set_blob ^^ + get_blob ^^ Blob.payload_ptr_unskewed ^^ + compile_unboxed_const 0l ^^ + get_len ^^ + system_call env "ic0" "msg_caller_copy" ^^ + + get_blob + | _ -> assert false + let reject env arg_instrs = match E.mode env with | Flags.ICMode | Flags.StubMode -> @@ -4260,7 +4278,7 @@ module StackRep = struct | Prim (Nat64 | Int64 | Word64) -> UnboxedWord64 | Prim (Nat32 | Int32 | Word32) -> UnboxedWord32 | Prim (Nat8 | Nat16 | Int8 | Int16 | Word8 | Word16 | Char) -> Vanilla - | Prim (Text|Blob) -> Vanilla + | Prim (Text | Blob) -> Vanilla | p -> todo "of_type" (Arrange_ir.typ p) Vanilla let to_block_type env = function @@ -6017,6 +6035,10 @@ and compile_exp (env : E.t) ae exp = | ICRejectPrim, [e] -> SR.unit, Dfinity.reject env (compile_exp_vanilla env ae e) + | ICCallerPrim, [] -> + assert (E.mode env = Flags.ICMode || E.mode env = Flags.StubMode); + Dfinity.caller env + | ICCallPrim, [f;e;k;r] -> SR.unit, begin (* TBR: Can we do better than using the notes? *) @@ -6032,6 +6054,7 @@ and compile_exp (env : E.t) ae exp = compile_exp_as env ae SR.Vanilla r ^^ set_r ^^ FuncDec.ic_call env ts1 ts2 get_meth_pair get_arg get_k get_r end + (* Unknown prim *) | _ -> SR.Unreachable, todo_trap env "compile_exp" (Arrange_ir.exp exp) end diff --git a/src/ir_def/arrange_ir.ml b/src/ir_def/arrange_ir.ml index 58213b2a7f9..8024140acab 100644 --- a/src/ir_def/arrange_ir.ml +++ b/src/ir_def/arrange_ir.ml @@ -73,6 +73,7 @@ and prim = function | CPSAsync -> Atom "CPSAsync" | ICReplyPrim ts -> "ICReplyPrim" $$ List.map typ ts | ICRejectPrim -> Atom "ICRejectPrim" + | ICCallerPrim -> Atom "ICCallerPrim" | ICCallPrim -> Atom "ICCallPrim" and mut = function diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index c91da6d2a23..9aba7596b50 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -373,6 +373,8 @@ let rec check_exp env (exp:Ir.exp) : unit = check (not (env.flavor.has_async_typ)) "ICRejectPrim in async flavor"; typ exp1 <: T.text; T.Non <: t + | ICCallerPrim, [] -> + T.caller <: t | ICCallPrim, [exp1; exp2; k; r] -> check_exp env k; check_exp env r; diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index 6c26b42b6e1..7da0a8af0d3 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -80,6 +80,7 @@ let primE prim es = | ShowPrim _ -> T.text | ICReplyPrim _ -> T.Non | ICRejectPrim -> T.Non + | ICCallerPrim -> T.caller | CastPrim (t1, t2) -> t2 | _ -> assert false (* implement more as needed *) in diff --git a/src/ir_def/ir.ml b/src/ir_def/ir.ml index ea7fe461ef8..1cce7271e12 100644 --- a/src/ir_def/ir.ml +++ b/src/ir_def/ir.ml @@ -121,6 +121,7 @@ and prim = | CPSAsync | ICReplyPrim of Type.typ list | ICRejectPrim + | ICCallerPrim | ICCallPrim diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index 7e3f0f70641..f6b6f5ec685 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -34,7 +34,9 @@ type env = throws : throw_env; replies : reply_env; rejects : reject_env; - async : bool + async : bool; + caller : V.value; + self : V.actor_id; } let adjoin_scope s ve = V.Env.adjoin s ve @@ -51,9 +53,12 @@ let env_of_scope flags flavor ve = throws = None; replies = None; rejects = None; + caller = V.Text V.top_id; + self = V.top_id; async = false; } +let context env = V.Text env.self (* Error handling *) @@ -115,6 +120,7 @@ struct if not (Queue.is_empty q) then (yield (); run ()) end + (* Async auxiliary functions *) (* Are these just duplicates of the corresponding functions in interpret.ml? If so, refactor *) @@ -151,7 +157,6 @@ let reject async v = let async env at (f: (V.value V.cont) -> (V.value V.cont) -> unit) (k : V.value V.cont) = let async = make_async () in - (* let k' = fun v1 -> set_async async v1 in *) let k' = reply async in let r = reject async in if env.flags.trace then trace "-> async %s" (string_of_region at); @@ -177,57 +182,53 @@ let await env at async k = k v ) ) -(*; Scheduler.yield () *) -let actor_msg env id f v (k : V.value V.cont) = + +let actor_msg env id f c v (k : V.value V.cont) = if env.flags.trace then trace "-> message %s%s" id (string_of_arg env v); Scheduler.queue (fun () -> if env.flags.trace then trace "<- message %s%s" id (string_of_arg env v); incr trace_depth; - f v k + f c v k ) let make_unit_message env id call_conv f = let open CC in match call_conv with | {sort = T.Shared s; n_res = 0; _} -> - Value.message_func s call_conv.n_args (fun v k -> - actor_msg env id f v (fun _ -> ()); + Value.message_func s call_conv.n_args (fun c v k -> + actor_msg env id f c v (fun _ -> ()); k V.unit ) | _ -> failwith ("unexpected call_conv " ^ string_of_call_conv call_conv) -(* assert (false) *) let make_async_message env id call_conv f = assert env.flavor.has_async_typ; let open CC in match call_conv with | {sort = T.Shared s; control = T.Promises; _} -> - Value.async_func s call_conv.n_args call_conv.n_res (fun v k -> + Value.async_func s call_conv.n_args call_conv.n_res (fun c v k -> let async = make_async () in - actor_msg env id f v (fun v_async -> + actor_msg env id f c v (fun v_async -> get_async (V.as_async v_async) (set_async async) (reject_async async) ); k (V.Async async) ) | _ -> failwith ("unexpected call_conv " ^ string_of_call_conv call_conv) - (* assert (false) *) let make_replying_message env id call_conv f = assert (not env.flavor.has_async_typ); let open CC in match call_conv with | {sort = T.Shared s; control = T.Replies; _} -> - Value.replies_func s call_conv.n_args call_conv.n_res (fun v k -> - actor_msg env id f v (fun v -> ()); + Value.replies_func s call_conv.n_args call_conv.n_res (fun c v k -> + actor_msg env id f c v (fun v -> ()); k (V.unit) ) | _ -> failwith ("unexpected call_conv " ^ string_of_call_conv call_conv) - (* assert (false) *) - let make_message env x cc f : V.value = match cc.CC.control with @@ -337,9 +338,10 @@ and interpret_exp_mut env exp (k : V.value V.cont) = let call_conv_r = CC.call_conv_of_typ r_dom in async env exp.at (fun k' r -> - let vk' = Value.Func (call_conv_f, fun v _ -> k' v) in - let vr = Value.Func (call_conv_r, fun v _ -> r v) in - f (V.Tup [vk';vr]) V.as_unit + let vk' = Value.Func (call_conv_f, fun c v _ -> k' v) in + let vr = Value.Func (call_conv_r, fun c v _ -> r v) in + let vc = context env in + f vc (V.Tup [vk'; vr]) V.as_unit ) k | _ -> assert false @@ -353,15 +355,15 @@ and interpret_exp_mut env exp (k : V.value V.cont) = let (_, f) = V.as_func vf in let (_, r) = V.as_func vr in await env exp.at (V.as_async v1) - (fun v -> f v k) - (fun e -> r e k) (* TBR *) + (fun v -> f (context env) v k) + (fun e -> r (context env) e k) (* TBR *) | _ -> assert false ) ) | OtherPrim s, exps -> interpret_exps env exps [] (fun vs -> let arg = match vs with [v] -> v | _ -> V.Tup vs in - Prim.prim s arg k + Prim.prim s (context env) arg k ) | CastPrim _, [e] -> interpret_exp env e k | ActorOfIdBlob t, [e] -> @@ -369,7 +371,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = | NumConvPrim (t1, t2), exps -> interpret_exps env exps [] (fun vs -> let arg = match vs with [v] -> v | _ -> V.Tup vs in - Prim.num_conv_prim t1 t2 arg k + Prim.num_conv_prim t1 t2 (context env) arg k ) | ICReplyPrim ts, [exp1] -> assert (not env.flavor.has_async_typ); @@ -389,11 +391,14 @@ and interpret_exp_mut env exp (k : V.value V.cont) = interpret_exp env exp2 (fun v2 -> interpret_exp env expk (fun kv -> interpret_exp env expr (fun rv -> - let call_conv, f = V.as_func v1 in - check_call_conv exp1 call_conv; - check_call_conv_arg env exp v2 call_conv; - last_region := exp.at; (* in case the following throws *) - f (V.Tup[kv;rv;v2]) k)))) + let call_conv, f = V.as_func v1 in + check_call_conv exp1 call_conv; + check_call_conv_arg env exp v2 call_conv; + last_region := exp.at; (* in case the following throws *) + let vc = context env in + f (V.Tup[vc; kv; rv]) v2 k)))) + | ICCallerPrim, [] -> + k env.caller | _ -> trap exp.at "Unknown prim or wrong number of arguments (%d given):\n %s" (List.length es) (Wasm.Sexpr.to_string 80 (Arrange_ir.prim p)) @@ -406,7 +411,11 @@ and interpret_exp_mut env exp (k : V.value V.cont) = interpret_exp env exp1 (fun v1 -> k (V.Variant (i, v1))) | ProjE (exp1, n) -> interpret_exp env exp1 (fun v1 -> k (List.nth (V.as_tup v1) n)) - | DotE (exp1, n) + | DotE (exp1, n) -> + interpret_exp env exp1 (fun v1 -> + let fs = V.as_obj v1 in + k (try find n fs with _ -> assert false) + ) | ActorDotE (exp1, n) -> interpret_exp env exp1 (fun v1 -> let fs = V.as_obj v1 in @@ -440,7 +449,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = check_call_conv exp1 call_conv; check_call_conv_arg env exp v2 call_conv; last_region := exp.at; (* in case the following throws *) - f v2 k + f (context env) v2 k ) ) | BlockE (decs, exp1) -> @@ -514,7 +523,8 @@ and interpret_exp_mut env exp (k : V.value V.cont) = interpret_exp env exp_r (fun rv -> let _call_conv, f = V.as_func v in last_region := exp.at; (* in case the following throws *) - f (V.Tup[kv;rv;V.Tup []]) k)) + let vc = context env in + f (V.Tup[vc; kv; rv]) (V.Tup []) k)) | FuncE (x, (T.Shared _ as sort), (T.Replies as control), _typbinds, args, ret_typs, e) -> assert (not env.flavor.has_async_typ); let cc = { sort; control; n_args = List.length args; n_res = List.length ret_typs } in @@ -524,7 +534,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = k v | FuncE (x, sort, control, _typbinds, args, ret_typs, e) -> let cc = { sort; control; n_args = List.length args; n_res = List.length ret_typs } in - let f = interpret_func env exp.at x args + let f = interpret_func env exp.at sort x args (fun env' -> interpret_exp env' e) in let v = match cc.sort with | T.Shared _ -> make_message env x cc f @@ -532,8 +542,9 @@ and interpret_exp_mut env exp (k : V.value V.cont) = in k v | ActorE (id, ds, fs, _) -> + let self = V.fresh_id () in let ve0 = declare_id id in - let env0 = adjoin_vals env ve0 in + let env0 = adjoin_vals {env with self = self} ve0 in let ve = declare_decs ds V.Env.empty in let env' = adjoin_vals env0 ve in interpret_decs env' ds (fun _ -> @@ -612,7 +623,8 @@ and match_args at args v : val_env = | [a] -> match_arg a v | _ -> let vs = V.as_tup v in - assert (List.length vs = List.length args); + if (List.length vs <> List.length args) then + failwith (Printf.sprintf "%s %s" (Source.string_of_region at) (V.string_of_val 0 v)); List.fold_left V.Env.adjoin V.Env.empty (List.map2 match_arg args vs) (* Patterns *) @@ -789,8 +801,13 @@ and interpret_decs env decs (k : unit V.cont) = | [] -> k () | d::ds -> interpret_dec env d (fun () -> interpret_decs env ds k) -and interpret_func env at x args f v (k : V.value V.cont) = +and interpret_func env at sort x args f c v (k : V.value V.cont) = if env.flags.trace then trace "%s%s" x (string_of_arg env v); + let caller = + if T.is_shared_sort sort + then c + else env.caller + in let ve = match_args at args v in incr trace_depth; let k' = fun v' -> @@ -803,13 +820,14 @@ and interpret_func env at x args f v (k : V.value V.cont) = vals = V.Env.adjoin env.vals ve; labs = V.Env.empty; rets = Some k'; - async = false + async = false; + caller = caller; } in f env' k' -and interpret_message env at x args f v (k : V.value V.cont) = - let v_reply, v_reject, v = match V.as_tup v with - | [v_reply ; v_reject; v] -> v_reply, v_reject, v +and interpret_message env at x args f c v (k : V.value V.cont) = + let v_caller, v_reply, v_reject = match V.as_tup c with + | [v_caller; v_reply; v_reject] -> v_caller, v_reply, v_reject | _ -> assert false in if env.flags.trace then trace "%s%s" x (string_of_arg env v); @@ -827,8 +845,9 @@ and interpret_message env at x args f v (k : V.value V.cont) = vals = V.Env.adjoin env.vals ve; labs = V.Env.empty; rets = Some k'; - replies = Some (fun v -> reply v V.as_unit); - rejects = Some (fun v -> reject v V.as_unit); + replies = Some (fun v -> reply (context env) v V.as_unit); + rejects = Some (fun v -> reject (context env) v V.as_unit); + caller = v_caller; async = false } in f env' k' diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 0530c4fd09c..37b23300db2 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -86,12 +86,17 @@ and exp' at note = function let t = T.as_array note.I.note_typ in I.ArrayE (mut m, T.as_immut t, exps es) | S.IdxE (e1, e2) -> I.IdxE (exp e1, exp e2) - | S.FuncE (name, s, tbs, p, _t_opt, e) -> - let args, wrap, control, res_tys = to_args note.I.note_typ p in + | S.FuncE (name, sp, tbs, p, _t_opt, e) -> + let s, po = match sp.it with + | T.Local -> (T.Local, None) + | T.Shared (ss, {it = S.WildP; _} ) -> (* don't bother with ctxt pat *) + (T.Shared ss, None) + | T.Shared (ss, sp) -> (T.Shared ss, Some sp) in + let args, wrap, control, res_tys = to_args note.I.note_typ po p in let tbs' = typ_binds tbs in let vars = List.map (fun (tb : I.typ_bind) -> T.Con (tb.it.I.con, [])) tbs' in let tys = List.map (T.open_ vars) res_tys in - I.FuncE (name, s.it, control, tbs', args, tys, wrap (exp e)) + I.FuncE (name, s, control, tbs', args, tys, wrap (exp e)) (* Primitive functions in the prelude have particular shapes *) | S.CallE ({it=S.AnnotE ({it=S.PrimE p;_}, _);note;_}, _, e) when Lib.String.chop_prefix "num_conv" p <> None -> @@ -313,7 +318,7 @@ and dec' at n d = match d with | _ -> assert false in let varPat = {it = I.VarP id'.it; at = at; note = fun_typ } in - let args, wrap, control, _n_res = to_args n.S.note_typ p in + let args, wrap, control, _n_res = to_args n.S.note_typ None p in let fn = { it = I.FuncE (id.it, sort, control, typ_binds tbs, args, [obj_typ], wrap { it = obj at s (Some self_id) es obj_typ; @@ -389,8 +394,7 @@ and to_arg p : (Ir.arg * (Ir.exp -> Ir.exp)) = arg_of_exp v, (fun e -> blockE [letP (pat p) v] e) - -and to_args typ p : Ir.arg list * (Ir.exp -> Ir.exp) * T.control * T.typ list = +and to_args typ po p : Ir.arg list * (Ir.exp -> Ir.exp) * T.control * T.typ list = let sort, control, n_args, res_tys = match typ with | Type.Func (sort, control, tbds, dom, res) -> @@ -418,19 +422,37 @@ and to_args typ p : Ir.arg list * (Ir.exp -> Ir.exp) * T.control * T.typ list = List.fold_right (fun p (args, wrap) -> let (a, wrap1) = to_arg p in (a::args, fun e -> wrap1 (wrap e)) - ) ps ([], (fun e -> e)) + ) ps ([], fun e -> e) | _, _ -> let vs = fresh_vars "param" tys in List.map arg_of_exp vs, (fun e -> blockE [letP (pat p) (tupE vs)] e) in + let wrap_po e = + match po with + | None -> wrap e + | Some p -> + let v = fresh_var "caller" T.caller in + let c = fresh_var "ctxt" T.ctxt in + blockE + [letD v (primE I.ICCallerPrim []); + letD c + (newObjE T.Object + [{ it = {Ir.name = "caller"; var = id_of_exp v}; + at = no_region; + note = T.caller }] + T.ctxt); + letP (pat p) c] + (wrap e) + in + let wrap_under_async e = if T.is_shared_sort sort && control <> T.Returns then match e.it with - | Ir.AsyncE e' -> { e with it = Ir.AsyncE (wrap e') } + | Ir.AsyncE e' -> { e with it = Ir.AsyncE (wrap_po e') } | _ -> assert false - else wrap e in + else wrap_po e in args, wrap_under_async, control, res_tys diff --git a/src/mo_def/arrange.ml b/src/mo_def/arrange.ml index 8198140f0f4..3e2fcf2ad12 100644 --- a/src/mo_def/arrange.ml +++ b/src/mo_def/arrange.ml @@ -24,10 +24,10 @@ let rec exp e = match e.it with | AssignE (e1, e2) -> "AssignE" $$ [exp e1; exp e2] | ArrayE (m, es) -> "ArrayE" $$ [mut m] @ List.map exp es | IdxE (e1, e2) -> "IdxE" $$ [exp e1; exp e2] - | FuncE (x, s, tp, p, t, e') -> + | FuncE (x, sp, tp, p, t, e') -> "FuncE" $$ [ Atom (Type.string_of_typ e.note.note_typ); - func_sort s; + sort_pat sp; Atom x] @ List.map typ_bind tp @ [ pat p; @@ -107,6 +107,12 @@ and obj_sort s = match s.it with | Type.Actor -> Atom "Actor" | Type.Module -> Atom "Module" + +and sort_pat sp = match sp.it with + | Type.Local -> Atom "Local" + | Type.Shared (Type.Write, p) -> "Shared" $$ [pat p] + | Type.Shared (Type.Query, p) -> "Query" $$ [pat p] + and func_sort s = match s.it with | Type.Local -> Atom "Local" | Type.Shared Type.Write -> Atom "Shared" diff --git a/src/mo_def/syntax.ml b/src/mo_def/syntax.ml index a0c9fc187bc..a387272131b 100644 --- a/src/mo_def/syntax.ml +++ b/src/mo_def/syntax.ml @@ -114,6 +114,8 @@ and vis' = Public | Private type op_typ = Type.typ ref (* For overloaded resolution; initially Type.Pre. *) +type sort_pat = (Type.shared_sort * pat) Type.shared Source.phrase + type exp = (exp', typ_note) Source.annotated_phrase and exp' = | PrimE of string (* primitive *) @@ -132,7 +134,7 @@ and exp' = | AssignE of exp * exp (* assignment *) | ArrayE of mut * exp list (* array *) | IdxE of exp * exp (* array indexing *) - | FuncE of string * func_sort * typ_bind list * pat * typ option * exp (* function *) + | FuncE of string * sort_pat * typ_bind list * pat * typ option * exp (* function *) | CallE of exp * typ list * exp (* function call *) | BlockE of dec list (* block (with type after avoidance)*) | NotE of exp (* negation *) diff --git a/src/mo_frontend/definedness.ml b/src/mo_frontend/definedness.ml index 3eb1b082db9..25078e40e02 100644 --- a/src/mo_frontend/definedness.ml +++ b/src/mo_frontend/definedness.ml @@ -11,7 +11,7 @@ here in for blocks (function decs). *) open Mo_def - +open Mo_types open Source open Syntax @@ -86,8 +86,12 @@ let rec exp msgs e : f = match e.it with | RetE e -> eagerify (exp msgs e) | ThrowE e -> eagerify (exp msgs e) (* Uses are delayed by function expressions *) - | FuncE (_, s, tp, p, t, e) -> delayify (exp msgs e /// pat msgs p) - + | FuncE (_, sort_pat, tp, p, t, e) -> + (match sort_pat.it with + | Type.Local -> + delayify (exp msgs e /// pat msgs p) + | Type.Shared (_, p1) -> + delayify ((exp msgs e /// pat msgs p) /// pat msgs p1)) (* The rest remaining cases just collect the uses of subexpressions: *) | LitE l -> M.empty | PrimE _ -> M.empty diff --git a/src/mo_frontend/parser.mly b/src/mo_frontend/parser.mly index 0d040c28506..b371682ad06 100644 --- a/src/mo_frontend/parser.mly +++ b/src/mo_frontend/parser.mly @@ -76,7 +76,7 @@ let share_typfield (tf : typ_field) = let share_exp e = match e.it with | FuncE (x, ({it = Type.Local; _} as s), tbs, p, t, e) -> - FuncE (x, {s with it = Type.Shared Type.Write}, tbs, p, t, e) @? e.at + FuncE (x, {s with it = Type.Shared (Type.Write, WildP @! s.at)}, tbs, p, t, e) @? e.at | _ -> e let share_dec d = @@ -200,6 +200,10 @@ seplist1(X, SEP) : | SHARED m=mode_opt { Type.Shared m @@ at $sloc } | QUERY { Type.Shared Type.Query @@ at $sloc } +%inline sort_pat : + | (* empty *) { Type.Local @@ no_region } + | SHARED m=mode_opt op=sort_pat_opt { Type.Shared (m,op (at $sloc)) @@ at $sloc } + | QUERY op=sort_pat_opt { Type.Shared (Type.Query, op (at $sloc)) @@ at $sloc } (* Paths *) @@ -595,6 +599,11 @@ pat_field : | x=id COLON t=typ { {id = x; pat = AnnotP(VarP x @! x.at, t) @! t.at} @@ at $sloc } +sort_pat_opt : + | p=pat_nullary + { fun sloc -> p } + | (* Empty *) + { fun sloc -> WildP @! sloc } (* Declarations *) @@ -620,7 +629,7 @@ dec_nonvar : let efs' = if s.it = Type.Actor then List.map share_expfield efs else efs in let_or_exp named x (ObjE(s, efs')) (at $sloc) } - | s=func_sort_opt FUNC xf=id_opt + | sp=sort_pat FUNC xf=id_opt tps=typ_params_opt p=pat_param t=return_typ? fb=func_body { (* This is a hack to support local func declarations that return a computed async. These should be defined using RHS syntax EQ e to avoid the implicit AsyncE introduction @@ -633,7 +642,7 @@ dec_nonvar : | _ -> e in let named, x = xf "func" $sloc in - let_or_exp named x (FuncE(x.it, s, tps, p, t, e)) (at $sloc) } + let_or_exp named x (FuncE(x.it, sp, tps, p, t, e)) (at $sloc) } | s=obj_sort_opt CLASS xf=typ_id_opt tps=typ_params_opt p=pat_param t=return_typ? cb=class_body { let x, efs = cb in diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 10abc404252..8e85667c51b 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -301,7 +301,6 @@ and check_typ' env typ : T.typ = let ts1 = List.map (check_typ env') typs1 in let ts2 = List.map (check_typ env') typs2 in check_shared_return env typ2.at sort.it c ts2; - if Type.is_shared_sort sort.it then if not env.pre then begin let t1 = T.seq ts1 in @@ -726,20 +725,21 @@ and infer_exp'' env exp : T.typ = "expected array type, but expression produces type\n %s" (T.string_of_typ_expand t1) ) - | FuncE (_, sort, typ_binds, pat, typ_opt, exp) -> - if not env.pre && not in_actor && T.is_shared_sort sort.it then + | FuncE (_, sort_pat, typ_binds, pat, typ_opt, exp) -> + if not env.pre && not in_actor && T.is_shared_sort sort_pat.it then error_in [Flags.ICMode; Flags.StubMode] env exp.at "a shared function is only allowed as a public field of an actor"; let typ = match typ_opt with | Some typ -> typ | None -> {it = TupT []; at = no_region; note = T.Pre} in - let c, ts2 = as_codomT sort.it typ in - check_shared_return env typ.at sort.it c ts2; - + let sort, ve = check_sort_pat env sort_pat in + let c, ts2 = as_codomT sort typ in + check_shared_return env typ.at sort c ts2; let cs, ts, te, ce = check_typ_binds env typ_binds in let env' = adjoin_typs env te ce in - let t1, ve = infer_pat_exhaustive env' pat in + let t1, ve1 = infer_pat_exhaustive env' pat in + let ve2 = T.Env.adjoin ve ve1 in let ts2 = List.map (check_typ env') ts2 in let codom = T.codom c ts2 in if not env.pre then begin @@ -747,10 +747,9 @@ and infer_exp'' env exp : T.typ = { env' with labs = T.Env.empty; rets = Some codom; - async = false } - in - check_exp (adjoin_vals env'' ve) codom exp; - if Type.is_shared_sort sort.it then begin + async = false } in + check_exp (adjoin_vals env'' ve2) codom exp; + if Type.is_shared_sort sort then begin if not (T.shared t1) then error_shared env t1 pat.at "shared function has non-shared parameter type\n %s" @@ -762,7 +761,7 @@ and infer_exp'' env exp : T.typ = (T.string_of_typ_expand t); ) ts2; match c, ts2 with - | T.Returns, [] when sort.it = T.Shared T.Write -> () + | T.Returns, [] when sort = T.Shared T.Write -> () | T.Promises, _ -> if not (isAsyncE exp) then error env exp.at @@ -774,7 +773,7 @@ and infer_exp'' env exp : T.typ = end; let ts1 = match pat.it with TupP _ -> T.seq_of_tup t1 | _ -> [t1] in let tbs = List.map2 (fun c t -> {T.var = Con.name c; bound = T.close cs t}) cs ts in - T.Func (sort.it, c, tbs, List.map (T.close cs) ts1, List.map (T.close cs) ts2) + T.Func (sort, c, tbs, List.map (T.close cs) ts1, List.map (T.close cs) ts2) | CallE (exp1, insts, exp2) -> let t1 = infer_exp_promote env exp1 in let sort, tbs, t_arg, t_ret = @@ -1050,20 +1049,22 @@ and check_exp' env0 t exp : T.typ = (String.concat " or\n " ss) ); t - | FuncE (_, s', [], pat, typ_opt, exp), T.Func (s, c, [], ts1, ts2) -> - if not env.pre && not env0.in_actor && T.is_shared_sort s'.it then + | FuncE (_, sort_pat, [], pat, typ_opt, exp), T.Func (s, c, [], ts1, ts2) -> + let sort, ve = check_sort_pat env sort_pat in + if not env.pre && not env0.in_actor && T.is_shared_sort sort then error_in [Flags.ICMode; Flags.StubMode] env exp.at "a shared function is only allowed as a public field of an actor"; - let ve = check_pat_exhaustive env (T.seq ts1) pat in + let ve1 = check_pat_exhaustive env (T.seq ts1) pat in + let ve2 = T.Env.adjoin ve ve1 in let codom = T.codom c ts2 in let t2 = match typ_opt with | None -> codom | Some typ -> check_typ env typ in - if s'.it <> s then + if sort <> s then error env exp.at "%sshared function does not match expected %sshared function type" - (if s'.it = T.Local then "non-" else "") + (if sort = T.Local then "non-" else "") (if s = T.Local then "non-" else ""); if not (T.sub t2 codom) then error env exp.at @@ -1075,7 +1076,7 @@ and check_exp' env0 t exp : T.typ = rets = Some t2; async = false } in - check_exp (adjoin_vals env' ve) t2 exp; + check_exp (adjoin_vals env' ve2) t2 exp; t | _ -> let t' = infer_exp env0 exp in @@ -1200,6 +1201,14 @@ and infer_pat_fields at env pfs ts ve : (T.obj_sort * T.field list) * Scope.val_ let ve' = disjoint_union env at "duplicate binding for %s in pattern" ve ve1 in infer_pat_fields at env pfs' (T.{ lab = pf.it.id.it; typ }::ts) ve' +and check_sort_pat env sort_pat : T.func_sort * Scope.val_env = + match sort_pat.it with + | T.Local -> T.Local, T.Env.empty + | T.Shared (ss, pat) -> + if pat.it <> WildP then + error_in [Flags.WASIMode; Flags.WasmMode] env pat.at "shared function cannot take a context pattern"; + T.Shared ss, check_pat_exhaustive env T.ctxt pat + and check_pat_exhaustive env t pat : Scope.val_env = let ve = check_pat env t pat in if not env.pre then begin @@ -1462,8 +1471,8 @@ and object_of_scope env sort fields scope at = (T.string_of_typ_expand t) and is_actor_method dec : bool = match dec.it with - | LetD ({it = VarP _; _}, {it = FuncE (_, sort, _, _, _, _); _}) -> - T.is_shared_sort sort.it + | LetD ({it = VarP _; _}, {it = FuncE (_, sort_pat, _, _, _, _); _}) -> + T.is_shared_sort sort_pat.it | _ -> false and is_typ_dec dec : bool = match dec.it with diff --git a/src/mo_interpreter/interpret.ml b/src/mo_interpreter/interpret.ml index a61b2b3e38d..c6fad813ef7 100644 --- a/src/mo_interpreter/interpret.ml +++ b/src/mo_interpreter/interpret.ml @@ -34,6 +34,7 @@ type env = libs : lib_env; rets : ret_env; throws : throw_env; + self : V.actor_id; async : bool } @@ -56,9 +57,11 @@ let env_of_scope flags scope = labs = V.Env.empty; rets = None; throws = None; + self = V.top_id; async = false; } +let context env = V.Text env.self (* Error handling *) @@ -69,7 +72,8 @@ let trap at fmt = Printf.ksprintf (fun s -> raise (Trap (at, s))) fmt let find id env = try V.Env.find id env with Not_found -> - trap no_region "unbound identifier %s" id + let dom = V.Env.keys env in + trap no_region "unbound identifier %s in domain %s" id (String.concat " " dom) (* Tracing *) @@ -189,12 +193,12 @@ let await env at async k = r v )) -let actor_msg env id f v (k : V.value V.cont) = +let actor_msg env id f c v (k : V.value V.cont) = if env.flags.trace then trace "-> message %s%s" id (string_of_arg env v); Scheduler.queue (fun () -> if env.flags.trace then trace "<- message %s%s" id (string_of_arg env v); incr trace_depth; - f v k + f c v k ) let make_unit_message env id v = @@ -202,8 +206,8 @@ let make_unit_message env id v = let call_conv, f = V.as_func v in match call_conv with | {sort = T.Shared s; n_res = 0; _} -> - Value.message_func s call_conv.n_args (fun v k -> - actor_msg env id f v (fun _ -> ()); + Value.message_func s call_conv.n_args (fun c v k -> + actor_msg env id f c v (fun _ -> ()); k V.unit ) | _ -> (* assert false *) @@ -214,9 +218,9 @@ let make_async_message env id v = let call_conv, f = V.as_func v in match call_conv with | {sort = T.Shared s; control = T.Promises; _} -> - Value.async_func s call_conv.n_args call_conv.n_res (fun v k -> + Value.async_func s call_conv.n_args call_conv.n_res (fun c v k -> let async = make_async () in - actor_msg env id f v (fun v_async -> + actor_msg env id f c v (fun v_async -> get_async (V.as_async v_async) (set_async async) (reject_async async) ); k (V.Async async) @@ -262,7 +266,7 @@ let interpret_lit env lit : V.value = (* Overloaded dot implementations *) let array_get a at = - V.local_func 1 1 (fun v k -> + V.local_func 1 1 (fun c v k -> let n = V.as_int v in if V.Nat.lt n (V.Nat.of_int (Array.length a)) then k (a.(V.Nat.to_int n)) @@ -270,7 +274,7 @@ let array_get a at = ) let array_set a at = - V.local_func 2 0 (fun v k -> + V.local_func 2 0 (fun c v k -> let v1, v2 = V.as_pair v in let n = V.as_int v1 in if V.Nat.lt n (V.Nat.of_int (Array.length a)) @@ -279,17 +283,17 @@ let array_set a at = ) let array_len a at = - V.local_func 0 1 (fun v k -> + V.local_func 0 1 (fun c v k -> V.as_unit v; k (V.Int (V.Nat.of_int (Array.length a))) ) let array_keys a at = - V.local_func 0 1 (fun v k -> + V.local_func 0 1 (fun c v k -> V.as_unit v; let i = ref 0 in let next = - V.local_func 0 1 (fun v k' -> + V.local_func 0 1 (fun c v k' -> if !i = Array.length a then k' V.Null else let v = V.Opt (V.Int (V.Nat.of_int !i)) in incr i; k' v @@ -298,11 +302,11 @@ let array_keys a at = ) let array_vals a at = - V.local_func 0 1 (fun v k -> + V.local_func 0 1 (fun c v k -> V.as_unit v; let i = ref 0 in let next = - V.local_func 0 1 (fun v k' -> + V.local_func 0 1 (fun c v k' -> if !i = Array.length a then k' V.Null else let v = V.Opt a.(!i) in incr i; k' v @@ -311,12 +315,12 @@ let array_vals a at = ) let text_chars t at = - V.local_func 0 1 (fun v k -> + V.local_func 0 1 (fun c v k -> V.as_unit v; let i = ref 0 in let s = Wasm.Utf8.decode t in let next = - V.local_func 0 1 (fun v k' -> + V.local_func 0 1 (fun c v k' -> if !i = List.length s then k' V.Null else let v = V.Opt (V.Char (List.nth s !i)) in incr i; k' v @@ -325,11 +329,14 @@ let text_chars t at = ) let text_len t at = - V.local_func 0 1 (fun v k -> + V.local_func 0 1 (fun c v k -> V.as_unit v; k (V.Int (V.Nat.of_int (List.length (Wasm.Utf8.decode t)))) ) +(* Helpers *) + +let local_sort_pat = { it = T.Local; at = Source.no_region; note = () } (* Expressions *) @@ -462,11 +469,11 @@ and interpret_exp_mut env exp (k : V.value V.cont) = with Invalid_argument s -> trap exp.at "%s" s) ) ) - | FuncE (name, _sort, _typbinds, pat, _typ, exp2) -> - let f = interpret_func env name pat (fun env' -> interpret_exp env' exp2) in + | FuncE (name, sort_pat, _typbinds, pat, _typ, exp2) -> + let f = interpret_func env name sort_pat pat (fun env' -> interpret_exp env' exp2) in let v = V.Func (CC.call_conv_of_typ exp.note.note_typ, f) in let v' = - match _sort.it with + match sort_pat.it with | T.Shared _ -> make_message env name exp.note.note_typ v | T.Local -> v in k v' @@ -477,7 +484,8 @@ and interpret_exp_mut env exp (k : V.value V.cont) = check_call_conv exp1 call_conv; check_call_conv_arg env exp v2 call_conv; last_region := exp.at; (* in case the following throws *) - f v2 k + let c = context env in + f c v2 k ) ) | BlockE decs -> @@ -534,7 +542,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = let _, next = V.as_func (find "next" fs) in let rec k_continue = fun v -> V.as_unit v; - next V.unit (fun v' -> + next (context env) V.unit (fun v' -> match v' with | V.Opt v1 -> (match match_pat pat v1 with @@ -756,11 +764,23 @@ and match_pat_fields pfs vs ve : val_env option = | None -> None end +and match_sort_pat env sort_pat c = + match sort_pat.it, c with + | T.Local, _ -> V.Env.empty + | T.Shared (_, pat), v -> + (match match_pat pat v with + | None -> + (* shouldn't occur with our irrefutable patterns, but may in future *) + trap pat.at "context value %s does not match context pattern" (string_of_val env v) + | Some ve1 -> + ve1) + (* Objects *) and interpret_obj env sort fields (k : V.value V.cont) = + let self = if sort.it = T.Actor then V.fresh_id () else env.self in let ve_ex, ve_in = declare_exp_fields fields V.Env.empty V.Env.empty in - let env' = adjoin_vals env ve_in in + let env' = adjoin_vals {env with self = self} ve_in in interpret_exp_fields env' sort.it fields ve_ex k and declare_exp_fields fields ve_ex ve_in : val_env * val_env = @@ -774,7 +794,9 @@ and declare_exp_fields fields ve_ex ve_in : val_env * val_env = and interpret_exp_fields env s fields ve (k : V.value V.cont) = match fields with - | [] -> k (V.Obj (V.Env.map Lib.Promise.value ve)) + | [] -> + let obj = V.Obj (V.Env.map Lib.Promise.value ve) in + k obj | {it = {dec; _}; _}::fields' -> interpret_dec env dec (fun _v -> interpret_exp_fields env s fields' ve k) @@ -820,7 +842,7 @@ and interpret_dec env dec (k : V.value V.cont) = | TypD _ -> k V.unit | ClassD (id, _typbinds, pat, _typ_opt, sort, id', fields) -> - let f = interpret_func env id.it pat (fun env' k' -> + let f = interpret_func env id.it local_sort_pat pat (fun env' k' -> let env'' = adjoin_vals env' (declare_id id') in interpret_obj env'' sort fields (fun v' -> define_id env'' id' v'; @@ -838,13 +860,14 @@ and interpret_decs env decs (k : V.value V.cont) = | dec::decs' -> interpret_dec env dec (fun _v -> interpret_decs env decs' k) - -and interpret_func env name pat f v (k : V.value V.cont) = +and interpret_func env name sort_pat pat f c v (k : V.value V.cont) = if env.flags.trace then trace "%s%s" name (string_of_arg env v); + let v1 = V.Obj (V.Env.singleton "caller" c) in + let ve1 = match_sort_pat env sort_pat v1 in match match_pat pat v with | None -> trap pat.at "argument value %s does not match parameter list" (string_of_val env v) - | Some ve -> + | Some ve2 -> incr trace_depth; let k' = fun v' -> if env.flags.trace then trace "<= %s" (string_of_val env v'); @@ -853,7 +876,7 @@ and interpret_func env name pat f v (k : V.value V.cont) = in let env' = { env with - vals = V.Env.adjoin env.vals ve; + vals = V.Env.adjoin env.vals (V.Env.adjoin ve1 ve2); libs = env.libs; labs = V.Env.empty; rets = Some k'; @@ -861,7 +884,6 @@ and interpret_func env name pat f v (k : V.value V.cont) = } in f env' k' - (* Programs *) let interpret_prog flags scope p : (V.value * scope) option = diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index cb20b31c83a..bd71b6729ed 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -8,7 +8,8 @@ type control = | Replies (* (IR only): responds asynchronously using `reply` *) type obj_sort = Object | Actor | Module type shared_sort = Query | Write -type func_sort = Local | Shared of shared_sort +type 'a shared = Local | Shared of 'a +type func_sort = shared_sort shared type eff = Triv | Await type prim = @@ -109,6 +110,11 @@ let catchErrorCodes = List.sort compare_field ( let throw = Prim Error let catch = Prim Error +(* Shared call context *) + +let caller = Prim Blob +let ctxt = Obj (Object,[{ lab = "caller"; typ = caller }]) + let prim = function | "Null" -> Null | "Bool" -> Bool @@ -1265,4 +1271,3 @@ let rec string_of_typ_expand t = ) | _ -> s -let is_shared_sort sort = sort <> Local diff --git a/src/mo_types/type.mli b/src/mo_types/type.mli index 1e615bd05d8..ac7a3387d5b 100644 --- a/src/mo_types/type.mli +++ b/src/mo_types/type.mli @@ -6,7 +6,8 @@ type var = string type control = Returns | Promises | Replies type obj_sort = Object | Actor | Module type shared_sort = Query | Write -type func_sort = Local | Shared of shared_sort +type 'a shared = Local | Shared of 'a +type func_sort = shared_sort shared type eff = Triv | Await type prim = @@ -60,7 +61,7 @@ and kind = (* Function sorts *) -val is_shared_sort : func_sort -> bool +val is_shared_sort : 'a shared -> bool (* Short-hands *) @@ -78,6 +79,8 @@ val catchErrorCodes : field list val throw : typ val catch : typ +val caller : typ +val ctxt: typ val iter_obj : typ -> typ diff --git a/src/mo_values/prim.ml b/src/mo_values/prim.ml index de3ebf618e0..8993cfdeeb3 100644 --- a/src/mo_values/prim.ml +++ b/src/mo_values/prim.ml @@ -45,162 +45,162 @@ let range_violation () = raise (Invalid_argument "numeric overflow") let num_conv_prim t1 t2 = let module T = Type in match (t1, t2) with - | T.Nat8, T.Word8 -> fun v k -> + | T.Nat8, T.Word8 -> fun _ v k -> let i = Nat8.to_int (as_nat8 v) in k (Word8 (Word8.of_int_u i)) - | T.Nat, T.Word8 -> fun v k -> + | T.Nat, T.Word8 -> fun _ v k -> let i = Conv.wrapped_int_of_big_int (as_int v) in k (Word8 (Word8.of_int_u i)) - | T.Nat, T.Nat8 -> fun v k -> + | T.Nat, T.Nat8 -> fun _ v k -> let q, r = Big_int.quomod_big_int (as_int v) (Big_int.power_int_positive_int 2 8) in let i = Big_int.int_of_big_int r in Big_int.(if eq_big_int q zero_big_int then k (Nat8 (Nat8.of_int i)) else range_violation ()) - | T.Int8, T.Word8 -> fun v k -> + | T.Int8, T.Word8 -> fun _ v k -> let i = Int_8.to_int (as_int8 v) in k (Word8 (Word8.of_int_s i)) - | T.Int, T.Word8 -> fun v k -> + | T.Int, T.Word8 -> fun _ v k -> let i = Conv.wrapped_int_of_big_int (as_int v) in k (Word8 (Word8.of_int_s i)) - | T.Int, T.Int8 -> fun v k -> + | T.Int, T.Int8 -> fun _ v k -> let q, r = Big_int.quomod_big_int (as_int v) (Big_int.power_int_positive_int 2 7) in let i = Big_int.int_of_big_int r in Big_int. (if eq_big_int q zero_big_int || eq_big_int q (pred_big_int zero_big_int) then k (Int8(Int_8.of_int (Conv.to_signed i q 0x80))) else range_violation ()) - | T.Nat16, T.Word16 -> fun v k -> + | T.Nat16, T.Word16 -> fun _ v k -> let i = Nat16.to_int (as_nat16 v) in k (Word16 (Word16.of_int_u i)) - | T.Nat, T.Word16 -> fun v k -> + | T.Nat, T.Word16 -> fun _ v k -> let i = Conv.wrapped_int_of_big_int (as_int v) in k (Word16 (Word16.of_int_u i)) - | T.Nat, T.Nat16 -> fun v k -> + | T.Nat, T.Nat16 -> fun _ v k -> let q, r = Big_int.quomod_big_int (as_int v) (Big_int.power_int_positive_int 2 16) in let i = Big_int.int_of_big_int r in Big_int.(if eq_big_int q zero_big_int then k (Nat16 (Nat16.of_int i)) else range_violation ()) - | T.Int16, T.Word16 -> fun v k -> + | T.Int16, T.Word16 -> fun _ v k -> let i = Int_16.to_int (as_int16 v) in k (Word16 (Word16.of_int_s i)) - | T.Int, T.Word16 -> fun v k -> + | T.Int, T.Word16 -> fun _ v k -> let i = Conv.wrapped_int_of_big_int (as_int v) in k (Word16 (Word16.of_int_s i)) - | T.Int, T.Int16 -> fun v k -> + | T.Int, T.Int16 -> fun _ v k -> let q, r = Big_int.quomod_big_int (as_int v) (Big_int.power_int_positive_int 2 15) in let i = Big_int.int_of_big_int r in Big_int. (if eq_big_int q zero_big_int || eq_big_int q (pred_big_int zero_big_int) then k (Int16(Int_16.of_int (Conv.to_signed i q 0x8000))) else range_violation ()) - | T.Nat32, T.Word32 -> fun v k -> + | T.Nat32, T.Word32 -> fun _ v k -> let i = Nat32.to_int (as_nat32 v) in k (Word32 (Word32.of_int_u i)) - | T.Nat, T.Word32 -> fun v k -> + | T.Nat, T.Word32 -> fun _ v k -> let i = Conv.wrapped_int_of_big_int (as_int v) in k (Word32 (Word32.of_int_u i)) - | T.Nat, T.Nat32 -> fun v k -> + | T.Nat, T.Nat32 -> fun _ v k -> let q, r = Big_int.quomod_big_int (as_int v) (Big_int.power_int_positive_int 2 32) in let i = Big_int.int_of_big_int r in Big_int.(if eq_big_int q zero_big_int then k (Nat32 (Nat32.of_int i)) else range_violation ()) - | T.Int32, T.Word32 -> fun v k -> + | T.Int32, T.Word32 -> fun _ v k -> let i = Int_32.to_int (as_int32 v) in k (Word32 (Word32.of_int_s i)) - | T.Int, T.Word32 -> fun v k -> + | T.Int, T.Word32 -> fun _ v k -> let i = Conv.wrapped_int_of_big_int (as_int v) in k (Word32 (Word32.of_int_s i)) - | T.Int, T.Int32 -> fun v k -> + | T.Int, T.Int32 -> fun _ v k -> let q, r = Big_int.quomod_big_int (as_int v) (Big_int.power_int_positive_int 2 31) in let i = Big_int.int_of_big_int r in Big_int. (if eq_big_int q zero_big_int || eq_big_int q (pred_big_int zero_big_int) then k (Int32 (Int_32.of_int (Conv.to_signed i q 0x80000000))) else range_violation ()) - | T.Nat64, T.Word64 -> fun v k -> + | T.Nat64, T.Word64 -> fun _ v k -> let q, r = Big_int.quomod_big_int (Nat64.to_big_int (as_nat64 v)) Conv.twoRaised63 in let i = Conv.(to_signed_big_int r q twoRaised63) in k (Word64 (Big_int.int64_of_big_int i)) - | T.Nat, T.Word64 -> fun v k -> k (Word64 (Conv.word64_of_big_int_u (as_int v))) - | T.Nat, T.Nat64 -> fun v k -> + | T.Nat, T.Word64 -> fun _ v k -> k (Word64 (Conv.word64_of_big_int_u (as_int v))) + | T.Nat, T.Nat64 -> fun _ v k -> let q, r = Big_int.quomod_big_int (as_int v) Conv.twoRaised64 in Big_int. (if eq_big_int q zero_big_int then k (Nat64 (Nat64.of_big_int r)) else range_violation ()) - | T.Int64, T.Word64 -> fun v k -> k (Word64 (Big_int.int64_of_big_int (Int_64.to_big_int (as_int64 v)))) - | T.Int, T.Word64 -> fun v k -> k (Word64 (Conv.word64_of_big_int_s (as_int v))) - | T.Int, T.Int64 -> fun v k -> + | T.Int64, T.Word64 -> fun _ v k -> k (Word64 (Big_int.int64_of_big_int (Int_64.to_big_int (as_int64 v)))) + | T.Int, T.Word64 -> fun _ v k -> k (Word64 (Conv.word64_of_big_int_s (as_int v))) + | T.Int, T.Int64 -> fun _ v k -> let q, r = Big_int.quomod_big_int (as_int v) Conv.twoRaised63 in Big_int. (if eq_big_int q zero_big_int || eq_big_int q (pred_big_int zero_big_int) then k (Int64 (Int_64.of_big_int Conv.(to_signed_big_int r q twoRaised63))) else range_violation ()) - | T.Word8, T.Nat -> fun v k -> + | T.Word8, T.Nat -> fun _ v k -> let i = Int32.to_int (Int32.shift_right_logical (Word8.to_bits (as_word8 v)) 24) in k (Int (Big_int.big_int_of_int i)) - | T.Word8, T.Nat8 -> fun v k -> + | T.Word8, T.Nat8 -> fun _ v k -> let i = Int32.to_int (Int32.shift_right_logical (Word8.to_bits (as_word8 v)) 24) in k (Nat8 (Nat8.of_int i)) - | T.Int8, T.Int -> fun v k -> k (Int (Int.of_int (Int_8.to_int (as_int8 v)))) - | T.Nat8, T.Nat -> fun v k -> k (Int (Nat.of_int (Nat8.to_int (as_nat8 v)))) - | T.Word8, T.Int -> fun v k -> + | T.Int8, T.Int -> fun _ v k -> k (Int (Int.of_int (Int_8.to_int (as_int8 v)))) + | T.Nat8, T.Nat -> fun _ v k -> k (Int (Nat.of_int (Nat8.to_int (as_nat8 v)))) + | T.Word8, T.Int -> fun _ v k -> let i = Int32.to_int (Int32.shift_right (Word8.to_bits (as_word8 v)) 24) in k (Int (Big_int.big_int_of_int i)) - | T.Word8, T.Int8 -> fun v k -> + | T.Word8, T.Int8 -> fun _ v k -> let i = Int32.to_int (Int32.shift_right (Word8.to_bits (as_word8 v)) 24) in k (Int8 (Int_8.of_int i)) - | T.Word16, T.Nat -> fun v k -> + | T.Word16, T.Nat -> fun _ v k -> let i = Int32.to_int (Int32.shift_right_logical (Word16.to_bits (as_word16 v)) 16) in k (Int (Big_int.big_int_of_int i)) - | T.Word16, T.Nat16 -> fun v k -> + | T.Word16, T.Nat16 -> fun _ v k -> let i = Int32.to_int (Int32.shift_right_logical (Word16.to_bits (as_word16 v)) 16) in k (Nat16 (Nat16.of_int i)) - | T.Int16, T.Int -> fun v k -> k (Int (Int.of_int (Int_16.to_int (as_int16 v)))) - | T.Nat16, T.Nat -> fun v k -> k (Int (Nat.of_int (Nat16.to_int (as_nat16 v)))) - | T.Word16, T.Int -> fun v k -> + | T.Int16, T.Int -> fun _ v k -> k (Int (Int.of_int (Int_16.to_int (as_int16 v)))) + | T.Nat16, T.Nat -> fun _ v k -> k (Int (Nat.of_int (Nat16.to_int (as_nat16 v)))) + | T.Word16, T.Int -> fun _ v k -> let i = Int32.to_int (Int32.shift_right (Word16.to_bits (as_word16 v)) 16) in k (Int (Big_int.big_int_of_int i)) - | T.Word16, T.Int16 -> fun v k -> + | T.Word16, T.Int16 -> fun _ v k -> let i = Int32.to_int (Int32.shift_right (Word16.to_bits (as_word16 v)) 16) in k (Int16 (Int_16.of_int i)) - | T.Int32, T.Int -> fun v k -> k (Int (Int.of_int (Int_32.to_int (as_int32 v)))) - | T.Nat32, T.Nat -> fun v k -> k (Int (Nat.of_int (Nat32.to_int (as_nat32 v)))) - | T.Word32, T.Nat -> fun v k -> + | T.Int32, T.Int -> fun _ v k -> k (Int (Int.of_int (Int_32.to_int (as_int32 v)))) + | T.Nat32, T.Nat -> fun _ v k -> k (Int (Nat.of_int (Nat32.to_int (as_nat32 v)))) + | T.Word32, T.Nat -> fun _ v k -> let i = Conv.int_of_word32_u (as_word32 v) in k (Int (Big_int.big_int_of_int i)) - | T.Word32, T.Int -> fun v k -> k (Int (Big_int.big_int_of_int32 (as_word32 v))) - | T.Word32, T.Int32 -> fun v k -> + | T.Word32, T.Int -> fun _ v k -> k (Int (Big_int.big_int_of_int32 (as_word32 v))) + | T.Word32, T.Int32 -> fun _ v k -> let i = Big_int.(int_of_big_int (big_int_of_int32 (as_word32 v))) in k (Int32 (Int_32.of_int i)) - | T.Word32, T.Nat32 -> fun v k -> + | T.Word32, T.Nat32 -> fun _ v k -> let i = Big_int.(int_of_big_int (big_int_of_int32 (as_word32 v))) in let i' = if i < 0 then i + 0x100000000 else i in k (Nat32 (Nat32.of_int i')) - | T.Int64, T.Int -> fun v k -> k (Int (Int_64.to_big_int (as_int64 v))) - | T.Nat64, T.Nat -> fun v k -> k (Int (Nat64.to_big_int (as_nat64 v))) - | T.Word64, T.Nat -> fun v k -> + | T.Int64, T.Int -> fun _ v k -> k (Int (Int_64.to_big_int (as_int64 v))) + | T.Nat64, T.Nat -> fun _ v k -> k (Int (Nat64.to_big_int (as_nat64 v))) + | T.Word64, T.Nat -> fun _ v k -> let i = Conv.big_int_of_word64_u (as_word64 v) in k (Int i) - | T.Word64, T.Nat64 -> fun v k -> + | T.Word64, T.Nat64 -> fun _ v k -> let i = Conv.big_int_of_word64_u (as_word64 v) in k (Nat64 (Nat64.of_big_int i)) - | T.Word64, T.Int -> fun v k -> k (Int (Big_int.big_int_of_int64 (as_word64 v))) - | T.Word64, T.Int64 -> fun v k -> + | T.Word64, T.Int -> fun _ v k -> k (Int (Big_int.big_int_of_int64 (as_word64 v))) + | T.Word64, T.Int64 -> fun _ v k -> let i = Big_int.big_int_of_int64 (as_word64 v) in k (Int64 (Int_64.of_big_int i)) - | T.Char, T.Word32 -> fun v k -> + | T.Char, T.Word32 -> fun _ v k -> let i = as_char v in k (Word32 (Word32.of_int_u i)) - | T.Word32, T.Char -> fun v k -> + | T.Word32, T.Char -> fun _ v k -> let i = Conv.int_of_word32_u (as_word32 v) in if i < 0xD800 || i >= 0xE000 && i < 0x110000 then k (Char i) else raise (Invalid_argument "character value out of bounds") | t1, t2 -> raise (Invalid_argument ("Value.num_conv_prim: " ^ T.string_of_typ (T.Prim t1) ^ T.string_of_typ (T.Prim t2) )) let prim = function - | "abs" -> fun v k -> k (Int (Nat.abs (as_int v))) + | "abs" -> fun _ v k -> k (Int (Nat.abs (as_int v))) | "popcnt8" | "popcnt16" | "popcnt32" | "popcnt64" -> - fun v k -> + fun _ v k -> k (match v with | Word8 w -> Word8 (Word8. popcnt w) | Word16 w -> Word16 (Word16.popcnt w) @@ -209,7 +209,7 @@ let prim = function | _ -> failwith "popcnt") | "clz8" | "clz16" | "clz32" | "clz64" -> - fun v k -> + fun _ v k -> k (match v with | Word8 w -> Word8 (Word8. clz w) | Word16 w -> Word16 (Word16.clz w) @@ -218,7 +218,7 @@ let prim = function | _ -> failwith "clz") | "ctz8" | "ctz16" | "ctz32" | "ctz64" -> - fun v k -> + fun _ v k -> k (match v with | Word8 w -> Word8 (Word8. ctz w) | Word16 w -> Word16 (Word16.ctz w) @@ -227,7 +227,7 @@ let prim = function | _ -> failwith "ctz") | "btst8" | "btst16" | "btst32" | "btst64" -> - fun v k -> + fun _ v k -> let w, a = as_pair v in k (match w with | Word8 y -> Word8 Word8. (and_ y (shl (of_int_u 1) (as_word8 a))) @@ -236,40 +236,40 @@ let prim = function | Word64 y -> Word64 Word64.(and_ y (shl 1L (as_word64 a))) | _ -> failwith "btst") - | "conv_Char_Text" -> fun v k -> let str = match as_char v with + | "conv_Char_Text" -> fun _ v k -> let str = match as_char v with | c when c <= 0o177 -> String.make 1 (Char.chr c) | code -> Wasm.Utf8.encode [code] in k (Text str) - | "print" -> fun v k -> Printf.printf "%s\n%!" (as_text v); k unit - | "rts_version" -> fun v k -> as_unit v; k (Text "0.1") - | "rts_heap_size" -> fun v k -> as_unit v; k (Int (Int.of_int 0)) - | "rts_total_allocation" -> fun v k -> as_unit v; k (Int (Int.of_int 0)) - | "rts_outstanding_callbacks" -> fun v k -> as_unit v; k (Int (Int.of_int 0)) - | "idlHash" -> fun v k -> let s = as_text v in k (Word32 (Lib.Uint32.to_int32 (Idllib.IdlHash.idl_hash s))) - | "array_len" -> fun v k -> + | "print" -> fun _ v k -> Printf.printf "%s\n%!" (as_text v); k unit + | "rts_version" -> fun _ v k -> as_unit v; k (Text "0.1") + | "rts_heap_size" -> fun _ v k -> as_unit v; k (Int (Int.of_int 0)) + | "rts_total_allocation" -> fun _ v k -> as_unit v; k (Int (Int.of_int 0)) + | "rts_outstanding_callbacks" -> fun _ v k -> as_unit v; k (Int (Int.of_int 0)) + | "idlHash" -> fun _ v k -> let s = as_text v in k (Word32 (Lib.Uint32.to_int32 (Idllib.IdlHash.idl_hash s))) + | "array_len" -> fun _ v k -> k (Int (Int.of_int (Array.length (Value.as_array v)))) - | "text_len" -> fun v k -> + | "text_len" -> fun _ v k -> k (Int (Nat.of_int (List.length (Wasm.Utf8.decode (Value.as_text v))))) - | "text_iter" -> fun v k -> + | "text_iter" -> fun _ v k -> let s = Wasm.Utf8.decode (Value.as_text v) in let i = ref s in k (TextIter i) - | "text_iter_done" -> fun v k -> + | "text_iter_done" -> fun _ v k -> let i = Value.as_text_iter v in k (Bool (!i = [])) - | "text_iter_next" -> fun v k -> + | "text_iter_next" -> fun _ v k -> let i = Value.as_text_iter v in begin match !i with | [] -> assert false | (c::cs) -> i := cs; k (Char c) end - | "Array.init" -> fun v k -> + | "Array.init" -> fun _ v k -> (match Value.as_tup v with | [len; x] -> k (Array (Array.init (Int.to_int (as_int len)) (fun _ -> Mut (ref x)))) | _ -> assert false ) - | "Array.tabulate" -> fun v k -> + | "Array.tabulate" -> fun c v k -> (match Value.as_tup v with | [len; g] -> let len_nat = Int.to_int (as_int len) in @@ -277,11 +277,11 @@ let prim = function let rec go prefix k i = if i == len_nat then k (Array (Array.of_list (prefix []))) - else g' (Int (Int.of_int i)) (fun x -> go (fun tl -> prefix (x::tl)) k (i + 1)) + else g' c (Int (Int.of_int i)) (fun x -> go (fun tl -> prefix (x::tl)) k (i + 1)) in go (fun xs -> xs) k 0 | _ -> assert false ) - | "cast" -> fun v k -> k v + | "cast" -> fun _ v k -> k v | p when Lib.String.chop_prefix "num_conv" p <> None -> begin match String.split_on_char '_' p with | [_;_;s1;s2] -> diff --git a/src/mo_values/value.ml b/src/mo_values/value.ml index d3bdcdbe82a..810c7dd6570 100644 --- a/src/mo_values/value.ml +++ b/src/mo_values/value.ml @@ -259,8 +259,13 @@ module Int_64 = Ranged (Int) (IntRange (struct let upper = Big_int.power_int_pos type unicode = int -type func = - (value -> value cont -> unit) +type actor_id = string + +type context = value + +and func = + context -> value -> value cont -> unit + and value = | Null | Bool of bool @@ -374,6 +379,17 @@ let rec compare x1 x2 = let equal x1 x2 = compare x1 x2 = 0 +(* (Pseudo)-Identities (for caller and self) *) + +let next_id = ref 0 + +let fresh_id() = + let id = Printf.sprintf "ID:%i" (!next_id) in + next_id := !next_id + 1; + id + +let top_id = fresh_id () + (* Pretty Printing *) let add_unicode buf = function diff --git a/src/mo_values/value.mli b/src/mo_values/value.mli index 515a0a8214d..e1abd1fc873 100644 --- a/src/mo_values/value.mli +++ b/src/mo_values/value.mli @@ -73,8 +73,13 @@ module Env : Env.S with type key = string (* Types *) type unicode = int +type actor_id = string + +type context = value + +and func = + context -> value -> value cont -> unit -type func = value -> value cont -> unit and value = | Null | Bool of bool @@ -121,6 +126,12 @@ val async_func : Type.shared_sort -> int -> int -> func -> value val replies_func : Type.shared_sort -> int -> int -> func -> value +(* Pseudo actor ids *) + +val fresh_id : unit -> actor_id +val top_id : actor_id + + (* Projections *) val as_null : value -> unit @@ -164,4 +175,3 @@ val compare : value -> value -> int val string_of_val : int -> value -> string val string_of_def : int -> def -> string - diff --git a/src/pipeline/resolve_import.ml b/src/pipeline/resolve_import.ml index e78c5e3818b..7f38d3cd4cd 100644 --- a/src/pipeline/resolve_import.ml +++ b/src/pipeline/resolve_import.ml @@ -198,6 +198,7 @@ let prog_imports (p : prog): (string * resolved_import ref * Source.region) list let collect_imports (p : prog): string list = List.map (fun (f, _, _) -> f) (prog_imports p) + type package_urls = (string * string) list let resolve_packages : package_urls -> filepath -> package_map Diag.result = fun purls base -> diff --git a/test/run-drun/caller.mo b/test/run-drun/caller.mo new file mode 100644 index 00000000000..b0991f1f3e1 --- /dev/null +++ b/test/run-drun/caller.mo @@ -0,0 +1,44 @@ +actor a { + + public shared ctxt func c1 () : async () { + let c : Blob = ctxt.caller; + return; + }; + + public shared {caller} func c2 () : async () { + let c1 : Blob = caller; + return; + }; + + public shared _ func c3 () : async () { + return; + }; + + public shared {} func c4 () : async () { + }; + + public shared {caller = c} func c5 (c:Bool) : async () { // allow shadowing + let c1 : Bool = c; + return; + }; + + public shared query {caller} func c6 () : async () { + let c1 : Blob = caller; + return; + }; + + public shared {caller} func c7() : async Blob { + return caller; + }; + +}; + +ignore a.c1(); //OR-CALL ingress c1 0x4449444C0000 +ignore a.c2(); //OR-CALL ingress c2 0x4449444C0000 +ignore a.c3(); //OR-CALL ingress c3 0x4449444C0000 +ignore a.c4(); //OR-CALL ingress c4 0x4449444C0000 +ignore a.c6(); //OR-CALL query c6 0x4449444C0000 +ignore a.c7(); //OR-CALL ingress c7 0x4449444C0000 + + + diff --git a/test/run-drun/ok/caller.drun-run.ok b/test/run-drun/ok/caller.drun-run.ok new file mode 100644 index 00000000000..0171dc3ed16 --- /dev/null +++ b/test/run-drun/ok/caller.drun-run.ok @@ -0,0 +1,7 @@ +ingress(0) System +ingress(1) Completed: Canister: Payload: 0x4449444c0000 +ingress(2) Completed: Canister: Payload: 0x4449444c0000 +ingress(3) Completed: Canister: Payload: 0x4449444c0000 +ingress(4) Completed: Canister: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0000 +ingress(5) Completed: Canister: Payload: 0x4449444c016d7b0100080000000000000000 diff --git a/test/run/caller.mo b/test/run/caller.mo new file mode 100644 index 00000000000..54504e6a2e1 --- /dev/null +++ b/test/run/caller.mo @@ -0,0 +1,17 @@ +actor a { + + public shared { caller = c } func getCaller() : async Blob { + return c; + }; + + public shared {caller} func c () : async () { + let self1 = await getCaller(); + let self2 = await getCaller(); + assert caller != self1; // assuming this is an ingress message + assert self1 == self2; + }; + +}; + +ignore a.c(); //OR-CALL ingress c 0x4449444C0000 + diff --git a/test/run/multi-caller.mo b/test/run/multi-caller.mo new file mode 100644 index 00000000000..dfae6def25b --- /dev/null +++ b/test/run/multi-caller.mo @@ -0,0 +1,98 @@ + + +actor a { + + // returns caller id + public shared { caller = c } func getCaller() : async Blob { + c + }; + + // returns self id when called (internally or externally) + public shared func getSelf() : async Blob { + await getCaller(); + }; + +}; + + +actor class C () { + + // returns caller id + public shared { caller = c } func getCaller() : async Blob { + c + }; + + // returns self id when called (internally or externally) + public shared func getSelf() : async Blob { + await getCaller(); + }; + +}; + +let alias = a; +let b = C(); +let c = C(); + +ignore async { + let id_a = await a.getSelf(); + let id_b = await b.getSelf(); + let id_c = await c.getSelf(); + let id_alias = await alias.getSelf(); + // check ids are distinct + assert (id_a != id_b); + assert (id_b != id_c); + assert (id_c != id_a); + assert (id_alias == id_a); +}; + + +// test caller alternation is correct + +actor Ping { + + // returns caller id + public shared { caller = c } func getCaller() : async Blob { + c + }; + + // returns self id when called (internally or externally) + public func getSelf() : async Blob { + await getCaller(); + }; + + public shared {caller} func call (n:Nat) : async () { + if (n > 0) { + assert (caller == (await Pong.getSelf())); + await Pong.call(n - 1); + }; + }; +}; + +actor Pong { + + // returns caller id + public shared { caller = c } func getCaller() : async Blob { + c + }; + + // returns self id when called (internally or externally) + public func getSelf() : async Blob { + await getCaller(); + }; + + public shared {caller} func call (n:Nat) : async () { + if (n > 0) { + assert caller == (await Ping.getSelf()); + await Ping.call(n - 1); + }; + }; + + public func test(n:Nat) { + ignore async await Ping.call(n); + }; + +}; + +Pong.test(5); + +//SKIP comp diff --git a/test/run/ok/caller.comp.ok b/test/run/ok/caller.comp.ok new file mode 100644 index 00000000000..3e3db5ebe39 --- /dev/null +++ b/test/run/ok/caller.comp.ok @@ -0,0 +1,2 @@ +caller.mo:3.17-3.31: type error, shared function cannot take a context pattern + (This is a limitation of the current version and flag -wasi-system-api.) diff --git a/test/run/ok/caller.comp.ret.ok b/test/run/ok/caller.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run/ok/caller.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 From acae13f1b1b660c6d1920951e607e7110a57908b Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 17 Dec 2019 00:27:14 +0100 Subject: [PATCH 0833/1176] Bump wasm dependency to v1.1 (#1032) * Bump wasm dependency to v1.1 this prepares for #1000 This rips out multi-value support in our serializer/parser. * Special stack_type encoding/decoding * Bumping wasm changed the FloatLit printing I hope that is ok. * Update nix/ocaml-wasm.nix Co-Authored-By: Gabor Greif --- Building.md | 12 +- nix/ocaml-wasm.nix | 8 +- src/codegen/compile.ml | 206 ++++++++++++++-------------- src/codegen/instrList.ml | 9 +- src/linking/linkModule.ml | 10 +- src/wasm-exts/customModuleDecode.ml | 23 ++-- src/wasm-exts/customModuleEncode.ml | 20 +-- test/run/ok/issue36.comp.ok | 6 +- test/run/ok/type-inference.comp.ok | 2 +- 9 files changed, 140 insertions(+), 156 deletions(-) diff --git a/Building.md b/Building.md index bf09698b502..ed7c21c60d9 100644 --- a/Building.md +++ b/Building.md @@ -36,17 +36,7 @@ installing all required tools without nix is out of scope). [`opam`](https://opam.ocaml.org/doc/Install.html) * Install the packages: ``` - opam install num vlq yojson menhir stdio js_of_ocaml js_of_ocaml-ppx ppx_inline_test bisect_ppx atdgen - ``` - * Install the `wasm` Ocaml package. We use a newer version than is on opam, and a - fork that supports the multi-value extension. See `nix/ocaml-wasm.nix` for - the precise repository and version. You can use `nix` to fetch the correct - source for you, and run the manual installation inside: - ``` - cp -R $(nix-build --no-out-link -Q -A wasm.src)/interpreter /tmp/interpreter - cd /tmp/interpreter - chmod u+w -R . - make install + opam install num vlq yojson menhir stdio js_of_ocaml js_of_ocaml-ppx ppx_inline_test bisect_ppx atdgen wasm ``` * Install various command line tools used by, in particuar, the test suite: ``` diff --git a/nix/ocaml-wasm.nix b/nix/ocaml-wasm.nix index 8b241090891..6d665442545 100644 --- a/nix/ocaml-wasm.nix +++ b/nix/ocaml-wasm.nix @@ -8,13 +8,13 @@ else stdenv.mkDerivation rec { name = "ocaml${ocaml.version}-wasm-${version}"; - version = "1.0"; + version = "1.1"; src = fetchFromGitHub { owner = "WebAssembly"; - repo = "multi-value"; - rev = "fa755dfe0c8ab3ec93636a092fc3dfbe8c8a232c"; - sha256 = "0867nd4k2lypal7g2a7816wi5zs4kp4w2dv9dxan9vvn3wi19b5i"; + repo = "spec"; + rev = "v${version}"; + sha256 = "1jsgrjqzsdmm6f5pgd947nikj7pnxx1mqdnz16j7s62rg8x06h7d"; }; buildInputs = [ ocaml findlib ocamlbuild ]; diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 204eea7d377..7fdcb8f4722 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -341,8 +341,8 @@ module E = struct let get_trap_with (env : t) = env.trap_with let trap_with env msg = env.trap_with env msg - let then_trap_with env msg = G.if_ (ValBlockType None) (trap_with env msg) G.nop - let else_trap_with env msg = G.if_ (ValBlockType None) G.nop (trap_with env msg) + let then_trap_with env msg = G.if_ [] (trap_with env msg) G.nop + let else_trap_with env msg = G.if_ [] G.nop (trap_with env msg) let reserve_static_memory (env : t) size : int32 = if !(env.static_memory_frozen) then assert false (* "Static memory frozen" *); @@ -469,8 +469,8 @@ let new_local64 env name = (* Iterates while cond is true. *) let compile_while cond body = - G.loop_ (ValBlockType None) ( - cond ^^ G.if_ (ValBlockType None) (body ^^ G.i (Br (nr 1l))) G.nop + G.loop_ [] ( + cond ^^ G.if_ [] (body ^^ G.i (Br (nr 1l))) G.nop ) (* Expects a number on the stack. Iterates from zero to below that number. *) @@ -717,7 +717,7 @@ module Heap = struct get_pages_needed ^^ compile_unboxed_zero ^^ G.i (Compare (Wasm.Values.I32 I32Op.GtS)) ^^ - G.if_ (ValBlockType None) + G.if_ [] ( get_pages_needed ^^ G.i MemoryGrow ^^ (* Check result *) @@ -1218,14 +1218,14 @@ module BoxedWord64 = struct let box env = Func.share_code1 env "box_i64" ("n", I64Type) [I32Type] (fun env get_n -> get_n ^^ compile_const_64 (Int64.of_int (1 lsl 5)) ^^ G.i (Compare (Wasm.Values.I64 I64Op.LtU)) ^^ - G.if_ (ValBlockType (Some I32Type)) + G.if_ [I32Type] (get_n ^^ BitTagged.tag) (compile_box env get_n) ) let unbox env = Func.share_code1 env "unbox_i64" ("n", I32Type) [I64Type] (fun env get_n -> get_n ^^ - BitTagged.if_unboxed env (ValBlockType (Some I64Type)) + BitTagged.if_unboxed env [I64Type] ( get_n ^^ BitTagged.untag_scalar env) ( get_n ^^ Heap.load_field64 payload_field) ) @@ -1260,10 +1260,10 @@ module BoxedWord64 = struct G.i (Binary (I64 I64Op.ShrU)) ^^ pow () ^^ set_res ^^ get_res ^^ get_res ^^ G.i (Binary (Wasm.Values.I64 I64Op.Mul)) in get_exp ^^ G.i (Test (I64 I64Op.Eqz)) ^^ - G.if_ (ValBlockType (Some I64Type)) + G.if_ [I64Type] one (get_exp ^^ one ^^ G.i (Binary (I64 I64Op.And)) ^^ G.i (Test (I64 I64Op.Eqz)) ^^ - G.if_ (ValBlockType (Some I64Type)) + G.if_ [I64Type] square_recurse_with_shifted (get_n ^^ square_recurse_with_shifted ^^ @@ -1303,14 +1303,14 @@ module BoxedSmallWord = struct let box env = Func.share_code1 env "box_i32" ("n", I32Type) [I32Type] (fun env get_n -> get_n ^^ compile_unboxed_const (Int32.of_int (1 lsl 10)) ^^ G.i (Compare (Wasm.Values.I32 I32Op.LtU)) ^^ - G.if_ (ValBlockType (Some I32Type)) + G.if_ [I32Type] (get_n ^^ BitTagged.tag_i32) (compile_box env get_n) ) let unbox env = Func.share_code1 env "unbox_i32" ("n", I32Type) [I32Type] (fun env get_n -> get_n ^^ - BitTagged.if_unboxed env (ValBlockType (Some I32Type)) + BitTagged.if_unboxed env [I32Type] ( get_n ^^ BitTagged.untag_i32 env) ( get_n ^^ Heap.load_field payload_field) ) @@ -1434,10 +1434,10 @@ module UnboxedSmallWord = struct get_n ^^ get_exp ^^ compile_shrU_const 1l ^^ sanitize ^^ pow () ^^ set_res ^^ get_res ^^ get_res ^^ mul in get_exp ^^ G.i (Test (I32 I32Op.Eqz)) ^^ - G.if_ (ValBlockType (Some I32Type)) + G.if_ [I32Type] one (get_exp ^^ one ^^ G.i (Binary (I32 I32Op.And)) ^^ G.i (Test (I32 I32Op.Eqz)) ^^ - G.if_ (ValBlockType (Some I32Type)) + G.if_ [I32Type] (square_recurse_with_shifted G.nop) (get_n ^^ square_recurse_with_shifted (sanitize_word_result ty) ^^ @@ -1637,7 +1637,7 @@ let signed_dynamics get_x = module I32Leb = struct let compile_size dynamics get_x = - get_x ^^ G.if_ (ValBlockType (Some I32Type)) + get_x ^^ G.if_ [I32Type] begin compile_unboxed_const 38l ^^ dynamics get_x ^^ @@ -1761,26 +1761,26 @@ module MakeCompact (Num : BigNumType) : BigNumType = struct let set_res, get_res = new_local env "res" in let set_res64, get_res64 = new_local64 env "res64" in get_a ^^ get_b ^^ - BitTagged.if_both_unboxed env (ValBlockType (Some I32Type)) + BitTagged.if_both_unboxed env [I32Type] begin get_a ^^ extend64 ^^ get_b ^^ extend64 ^^ fast env ^^ set_res64 ^^ get_res64 ^^ get_res64 ^^ speculate_compact64 32 ^^ - G.if_ (ValBlockType (Some I32Type)) + G.if_ [I32Type] (get_res64 ^^ compress64) (get_res64 ^^ box64 env) end begin - get_a ^^ BitTagged.if_unboxed env (ValBlockType (Some I32Type)) + get_a ^^ BitTagged.if_unboxed env [I32Type] (get_a ^^ extend_and_box64 env) get_a ^^ - get_b ^^ BitTagged.if_unboxed env (ValBlockType (Some I32Type)) + get_b ^^ BitTagged.if_unboxed env [I32Type] (get_b ^^ extend_and_box64 env) get_b ^^ slow env ^^ set_res ^^ get_res ^^ fits_in_vanilla env ^^ - G.if_ (ValBlockType (Some I32Type)) + G.if_ [I32Type] (get_res ^^ Num.truncate_to_word32 env ^^ compress) get_res end) @@ -1806,7 +1806,7 @@ module MakeCompact (Num : BigNumType) : BigNumType = struct let set_b64, get_b64 = new_local64 env "b64" in let set_res64, get_res64 = new_local64 env "res64" in get_a ^^ get_b ^^ - BitTagged.if_both_unboxed env (ValBlockType (Some I32Type)) + BitTagged.if_both_unboxed env [I32Type] begin (* estimate bitcount of result: `bits(a) * b <= 65` guarantees the absence of overflow in 64-bit arithmetic *) @@ -1817,14 +1817,14 @@ module MakeCompact (Num : BigNumType) : BigNumType = struct get_b ^^ extend64 ^^ set_b64 ^^ get_b64 ^^ G.i (Binary (Wasm.Values.I64 I64Op.Mul)) ^^ compile_const_64 130L ^^ G.i (Compare (Wasm.Values.I64 I64Op.LeU)) ^^ - G.if_ (ValBlockType (Some I32Type)) + G.if_ [I32Type] begin get_a64 ^^ compile_shrS64_const 1L ^^ get_b64 ^^ compile_shrS64_const 1L ^^ BoxedWord64.compile_unsigned_pow env ^^ compile_shl64_const 1L ^^ set_res64 ^^ get_res64 ^^ get_res64 ^^ speculate_compact64 32 ^^ - G.if_ (ValBlockType (Some I32Type)) + G.if_ [I32Type] (get_res64 ^^ compress64) (get_res64 ^^ box64 env) end @@ -1833,21 +1833,21 @@ module MakeCompact (Num : BigNumType) : BigNumType = struct get_b64 ^^ box64 env ^^ Num.compile_unsigned_pow env ^^ set_res ^^ get_res ^^ fits_in_vanilla env ^^ - G.if_ (ValBlockType (Some I32Type)) + G.if_ [I32Type] (get_res ^^ Num.truncate_to_word32 env ^^ compress) get_res end end begin - get_a ^^ BitTagged.if_unboxed env (ValBlockType (Some I32Type)) + get_a ^^ BitTagged.if_unboxed env [I32Type] (get_a ^^ extend_and_box64 env) get_a ^^ - get_b ^^ BitTagged.if_unboxed env (ValBlockType (Some I32Type)) + get_b ^^ BitTagged.if_unboxed env [I32Type] (get_b ^^ extend_and_box64 env) get_b ^^ Num.compile_unsigned_pow env ^^ set_res ^^ get_res ^^ fits_in_vanilla env ^^ - G.if_ (ValBlockType (Some I32Type)) + G.if_ [I32Type] (get_res ^^ Num.truncate_to_word32 env ^^ compress) get_res end) @@ -1855,7 +1855,7 @@ module MakeCompact (Num : BigNumType) : BigNumType = struct let compile_is_negative env = let set_n, get_n = new_local env "n" in set_n ^^ get_n ^^ - BitTagged.if_unboxed env (ValBlockType (Some I32Type)) + BitTagged.if_unboxed env [I32Type] (get_n ^^ compile_bitand_const 1l) (get_n ^^ Num.compile_is_negative env) @@ -1869,11 +1869,11 @@ module MakeCompact (Num : BigNumType) : BigNumType = struct let compile_neg env = Func.share_code1 env "B_neg" ("n", I32Type) [I32Type] (fun env get_n -> - get_n ^^ BitTagged.if_unboxed env (ValBlockType (Some I32Type)) + get_n ^^ BitTagged.if_unboxed env [I32Type] begin get_n ^^ compile_unboxed_one ^^ G.i (Compare (Wasm.Values.I32 I32Op.Eq)) ^^ - G.if_ (ValBlockType (Some I32Type)) + G.if_ [I32Type] (compile_lit env (Big_int.big_int_of_int 0x40000000)) begin compile_unboxed_zero ^^ @@ -1889,17 +1889,17 @@ module MakeCompact (Num : BigNumType) : BigNumType = struct Func.share_code2 env name (("a", I32Type), ("b", I32Type)) [I32Type] (fun env get_a get_b -> get_a ^^ get_b ^^ - BitTagged.if_both_unboxed env (ValBlockType (Some I32Type)) + BitTagged.if_both_unboxed env [I32Type] begin get_a ^^ extend64 ^^ get_b ^^ extend64 ^^ fast env end begin - get_a ^^ BitTagged.if_unboxed env (ValBlockType (Some I32Type)) + get_a ^^ BitTagged.if_unboxed env [I32Type] (get_a ^^ extend_and_box64 env) get_a ^^ - get_b ^^ BitTagged.if_unboxed env (ValBlockType (Some I32Type)) + get_b ^^ BitTagged.if_unboxed env [I32Type] (get_b ^^ extend_and_box64 env) get_b ^^ slow env @@ -1915,7 +1915,7 @@ module MakeCompact (Num : BigNumType) : BigNumType = struct let try_unbox iN fast slow env = let set_a, get_a = new_local env "a" in set_a ^^ get_a ^^ - BitTagged.if_unboxed env (ValBlockType (Some iN)) + BitTagged.if_unboxed env [iN] (get_a ^^ fast env) (get_a ^^ slow env) @@ -1957,12 +1957,12 @@ module MakeCompact (Num : BigNumType) : BigNumType = struct let set_a, get_a = new_local env "a" in set_a ^^ get_a ^^ compile_bitand_const 1l ^^ - G.if_ (ValBlockType (Some I32Type)) + G.if_ [I32Type] begin get_a ^^ compile_unboxed_one ^^ (* i.e. -(2**30) == -1073741824 *) G.i (Compare (Wasm.Values.I32 I32Op.Eq)) ^^ - G.if_ (ValBlockType (Some I32Type)) + G.if_ [I32Type] (compile_unboxed_const 0x40000000l ^^ Num.from_word32 env) (* is non-representable *) begin get_a ^^ @@ -1980,7 +1980,7 @@ module MakeCompact (Num : BigNumType) : BigNumType = struct Num.compile_load_from_data_buf env signed ^^ set_res ^^ get_res ^^ fits_in_vanilla env ^^ - G.if_ (ValBlockType (Some I32Type)) + G.if_ [I32Type] (get_res ^^ Num.truncate_to_word32 env ^^ compress) get_res @@ -2034,7 +2034,7 @@ module MakeCompact (Num : BigNumType) : BigNumType = struct let set_a, get_a = new_local env "a" in set_a ^^ get_a ^^ get_a ^^ speculate_compact ^^ - G.if_ (ValBlockType (Some I32Type)) + G.if_ [I32Type] (get_a ^^ compress) (get_a ^^ Num.from_signed_word32 env) @@ -2042,7 +2042,7 @@ module MakeCompact (Num : BigNumType) : BigNumType = struct let set_a, get_a = new_local64 env "a" in set_a ^^ get_a ^^ get_a ^^ speculate_compact64 31 ^^ - G.if_ (ValBlockType (Some I32Type)) + G.if_ [I32Type] (get_a ^^ compile_shl64_const 1L ^^ compress64) (get_a ^^ Num.from_signed_word64 env) @@ -2052,7 +2052,7 @@ module MakeCompact (Num : BigNumType) : BigNumType = struct compile_unboxed_const Int32.(shift_left minus_one 30) ^^ G.i (Binary (Wasm.Values.I32 I32Op.And)) ^^ G.i (Test (Wasm.Values.I32 I32Op.Eqz)) ^^ - G.if_ (ValBlockType (Some I32Type)) + G.if_ [I32Type] (get_a ^^ compile_rotl_const 2l) (get_a ^^ G.i (Convert (Wasm.Values.I64 I64Op.ExtendUI32)) ^^ Num.from_word64 env) @@ -2062,14 +2062,14 @@ module MakeCompact (Num : BigNumType) : BigNumType = struct compile_const_64 Int64.(shift_left minus_one 30) ^^ G.i (Binary (Wasm.Values.I64 I64Op.And)) ^^ G.i (Test (Wasm.Values.I64 I64Op.Eqz)) ^^ - G.if_ (ValBlockType (Some I32Type)) + G.if_ [I32Type] (get_a ^^ G.i (Convert (Wasm.Values.I32 I32Op.WrapI64)) ^^ compile_rotl_const 2l) (get_a ^^ Num.from_word64 env) let truncate_to_word64 env = let set_a, get_a = new_local env "a" in set_a ^^ get_a ^^ - BitTagged.if_unboxed env (ValBlockType (Some I64Type)) + BitTagged.if_unboxed env [I64Type] begin get_a ^^ extend ^^ compile_unboxed_one ^^ G.i (Binary (Wasm.Values.I32 I32Op.ShrS)) ^^ @@ -2079,20 +2079,20 @@ module MakeCompact (Num : BigNumType) : BigNumType = struct let truncate_to_word32 env = let set_a, get_a = new_local env "a" in set_a ^^ get_a ^^ - BitTagged.if_unboxed env (ValBlockType (Some I32Type)) + BitTagged.if_unboxed env [I32Type] (get_a ^^ extend ^^ compile_unboxed_one ^^ G.i (Binary (Wasm.Values.I32 I32Op.ShrS))) (get_a ^^ Num.truncate_to_word32 env) let to_word64 env = let set_a, get_a = new_local env "a" in set_a ^^ get_a ^^ - BitTagged.if_unboxed env (ValBlockType (Some I64Type)) + BitTagged.if_unboxed env [I64Type] (get_a ^^ extend64 ^^ compile_shrS64_const 1L) (get_a ^^ Num.to_word64 env) let to_word32 env = let set_a, get_a = new_local env "a" in set_a ^^ get_a ^^ - BitTagged.if_unboxed env (ValBlockType (Some I32Type)) + BitTagged.if_unboxed env [I32Type] (get_a ^^ extend ^^ compile_unboxed_one ^^ G.i (Binary (Wasm.Values.I32 I32Op.ShrS))) (get_a ^^ Num.to_word32 env) end @@ -2322,7 +2322,7 @@ module Object = struct Heap.load_field 0l ^^ (* the hash field *) get_hash ^^ G.i (Compare (Wasm.Values.I32 I32Op.Eq)) ^^ - G.if_ (ValBlockType None) + G.if_ [] ( get_f ^^ compile_add_const Heap.word_size ^^ set_r @@ -2434,12 +2434,12 @@ module Blob = struct begin if op = EqOp then (* Early exit for equality *) get_len1 ^^ get_len2 ^^ G.i (Compare (Wasm.Values.I32 I32Op.Eq)) ^^ - G.if_ (ValBlockType None) G.nop (Bool.lit false ^^ G.i Return) ^^ + G.if_ [] G.nop (Bool.lit false ^^ G.i Return) ^^ get_len1 ^^ set_len else get_len1 ^^ get_len2 ^^ G.i (Compare (Wasm.Values.I32 I32Op.LeU)) ^^ - G.if_ (ValBlockType None) + G.if_ [] (get_len1 ^^ set_len) (get_len2 ^^ set_len) end ^^ @@ -2464,7 +2464,7 @@ module Blob = struct set_b ^^ get_a ^^ get_b ^^ G.i (Compare (Wasm.Values.I32 I32Op.Eq)) ^^ - G.if_ (ValBlockType None) G.nop ( + G.if_ [] G.nop ( (* first non-equal elements *) begin match op with | LeOp -> get_a ^^ get_b ^^ G.i (Compare (Wasm.Values.I32 I32Op.LeU)) @@ -2900,7 +2900,7 @@ module Dfinity = struct system_call env "ic0" "msg_reject_code" ^^ set_code ^^ get_code ^^ compile_unboxed_const 4l ^^ G.i (Compare (Wasm.Values.I32 I32Op.Eq)) ^^ - G.if_ (ValBlockType (Some I32Type)) + G.if_ [I32Type] (Variant.inject env "error" Tuple.compile_unit) (Variant.inject env "system" Tuple.compile_unit) @@ -3015,7 +3015,7 @@ module HeapTraversal = struct let object_size env = Func.share_code1 env "object_size" ("x", I32Type) [I32Type] (fun env get_x -> get_x ^^ - Tagged.branch env (ValBlockType (Some I32Type)) + Tagged.branch env [I32Type] [ Tagged.Int, compile_unboxed_const 3l ; Tagged.SmallWord, @@ -3077,7 +3077,7 @@ module HeapTraversal = struct let code = mk_code get_ptr_loc in let code_offset = mk_code_offset get_ptr_loc in get_x ^^ - Tagged.branch_default env (ValBlockType None) G.nop + Tagged.branch_default env [] G.nop [ Tagged.MutBox, get_x ^^ compile_add_const (Int32.mul Heap.word_size MutBox.field) ^^ @@ -3427,12 +3427,12 @@ module Serialization = struct | Opt t -> inc_data_size (compile_unboxed_const 1l) ^^ (* one byte tag *) get_x ^^ Opt.is_some env ^^ - G.if_ (ValBlockType None) (get_x ^^ Opt.project ^^ size env t) G.nop + G.if_ [] (get_x ^^ Opt.project ^^ size env t) G.nop | Variant vs -> List.fold_right (fun (i, {lab = l; typ = t}) continue -> get_x ^^ Variant.test_is env l ^^ - G.if_ (ValBlockType None) + G.if_ [] ( size_word env (compile_unboxed_const (Int32.of_int i)) ^^ get_x ^^ Variant.project ^^ size env t ) continue @@ -3557,14 +3557,14 @@ module Serialization = struct | Opt t -> get_x ^^ Opt.is_some env ^^ - G.if_ (ValBlockType None) + G.if_ [] ( write_byte (compile_unboxed_const 1l) ^^ get_x ^^ Opt.project ^^ write env t ) ( write_byte (compile_unboxed_const 0l) ) | Variant vs -> List.fold_right (fun (i, {lab = l; typ = t}) continue -> get_x ^^ Variant.test_is env l ^^ - G.if_ (ValBlockType None) + G.if_ [] ( write_word (compile_unboxed_const (Int32.of_int i)) ^^ get_x ^^ Variant.project ^^ write env t) continue @@ -3640,7 +3640,7 @@ module Serialization = struct set_b ^^ get_b ^^ compile_eq_const 0l ^^ - G.if_ (ValBlockType (Some I32Type)) + G.if_ [I32Type] begin code0 end begin get_b ^^ compile_eq_const 1l ^^ @@ -3724,7 +3724,7 @@ module Serialization = struct | Prim Int -> (* Subtyping with nat *) check_prim_typ (Prim Nat) ^^ - G.if_ (ValBlockType (Some I32Type)) + G.if_ [I32Type] begin get_data_buf ^^ BigNum.compile_load_from_data_buf env false @@ -3832,7 +3832,7 @@ module Serialization = struct ) | Opt t -> check_prim_typ (Prim Null) ^^ - G.if_ (ValBlockType (Some I32Type)) + G.if_ [I32Type] begin Opt.null end @@ -3873,7 +3873,7 @@ module Serialization = struct List.fold_right (fun (h, {lab = l; typ = t}) continue -> get_tag ^^ compile_eq_const (Lib.Uint32.to_int32 h) ^^ - G.if_ (ValBlockType (Some I32Type)) + G.if_ [I32Type] ( Variant.inject env l (get_idltyp ^^ go env t) ) continue ) @@ -4023,7 +4023,7 @@ module Serialization = struct ) ts ^^ get_arg_count ^^ compile_eq_const (Int32.of_int (List.length ts)) ^^ - G.if_ (ValBlockType None) + G.if_ [] begin ReadBuf.is_empty env get_data_buf ^^ E.else_trap_with env ("IDL error: left-over bytes " ^ ts_name) ^^ @@ -4066,11 +4066,11 @@ module GC = struct get_obj ^^ get_begin_from_space ^^ G.i (Compare (Wasm.Values.I32 I32Op.LtU)) ^^ - G.if_ (ValBlockType None) (get_end_to_space ^^ G.i Return) G.nop ^^ + G.if_ [] (get_end_to_space ^^ G.i Return) G.nop ^^ (* If this is an indirection, just use that value *) get_obj ^^ - Tagged.branch_default env (ValBlockType None) G.nop [ + Tagged.branch_default env [] G.nop [ Tagged.Indirection, update_ptr (get_obj ^^ Heap.load_field 1l) ^^ get_end_to_space ^^ G.i Return @@ -4122,7 +4122,7 @@ module GC = struct (* If this is an unboxed scalar, ignore it *) get_obj ^^ - BitTagged.if_unboxed env (ValBlockType None) (get_end_to_space ^^ G.i Return) G.nop ^^ + BitTagged.if_unboxed env [] (get_end_to_space ^^ G.i Return) G.nop ^^ let update_ptr new_val_code = get_ptr_loc ^^ new_val_code ^^ store_ptr in @@ -4282,15 +4282,15 @@ module StackRep = struct | p -> todo "of_type" (Arrange_ir.typ p) Vanilla let to_block_type env = function - | Vanilla -> ValBlockType (Some I32Type) - | UnboxedWord64 -> ValBlockType (Some I64Type) - | UnboxedWord32 -> ValBlockType (Some I32Type) - | UnboxedTuple 0 -> ValBlockType None - | UnboxedTuple 1 -> ValBlockType (Some I32Type) - | UnboxedTuple n when not !Flags.multi_value -> assert false - | UnboxedTuple n -> VarBlockType (nr (E.func_type env (FuncType ([], Lib.List.make n I32Type)))) - | StaticThing _ -> ValBlockType None - | Unreachable -> ValBlockType None + | Vanilla -> [I32Type] + | UnboxedWord64 -> [I64Type] + | UnboxedWord32 -> [I32Type] + | UnboxedTuple 0 -> [] + | UnboxedTuple 1 -> [I32Type] + | UnboxedTuple n -> + assert false; (* not supported without muti_value *) + | StaticThing _ -> [] + | Unreachable -> [] let to_string = function | Vanilla -> "Vanilla" @@ -4873,14 +4873,14 @@ module PatCode = struct | CanFail is2 -> CanFail (fun fail_code -> let inner_fail = G.new_depth_label () in let inner_fail_code = Bool.lit false ^^ G.branch_to_ inner_fail in - G.labeled_block_ (ValBlockType (Some I32Type)) inner_fail (is1 inner_fail_code ^^ Bool.lit true) ^^ - G.if_ (ValBlockType None) G.nop (is2 fail_code) + G.labeled_block_ [I32Type] inner_fail (is1 inner_fail_code ^^ Bool.lit true) ^^ + G.if_ [] G.nop (is2 fail_code) ) | CannotFail is2 -> CannotFail ( let inner_fail = G.new_depth_label () in let inner_fail_code = Bool.lit false ^^ G.branch_to_ inner_fail in - G.labeled_block_ (ValBlockType (Some I32Type)) inner_fail (is1 inner_fail_code ^^ Bool.lit true) ^^ - G.if_ (ValBlockType None) G.nop is2 + G.labeled_block_ [I32Type] inner_fail (is1 inner_fail_code ^^ Bool.lit true) ^^ + G.if_ [] G.nop is2 ) let orTrap env : patternCode -> G.t = function @@ -5183,7 +5183,7 @@ let additiveInt64_shortcut fast env get_a get_b slow = get_b ^^ get_b ^^ compile_shl64_const 1L ^^ G.i (Binary (Wasm.Values.I64 I64Op.Xor)) ^^ compile_shrU64_const 63L ^^ G.i (Binary (Wasm.Values.I64 I64Op.Or)) ^^ G.i (Test (Wasm.Values.I64 I64Op.Eqz)) ^^ - G.if_ (ValBlockType (Some I64Type)) + G.if_ [I64Type] (get_a ^^ get_b ^^ fast) slow @@ -5192,28 +5192,28 @@ let mulInt64_shortcut fast env get_a get_b slow = get_b ^^ get_b ^^ compile_shl64_const 1L ^^ G.i (Binary (Wasm.Values.I64 I64Op.Xor)) ^^ G.i (Unary (Wasm.Values.I64 I64Op.Clz)) ^^ G.i (Binary (Wasm.Values.I64 I64Op.Add)) ^^ compile_const_64 65L ^^ G.i (Compare (Wasm.Values.I64 I64Op.GeU)) ^^ - G.if_ (ValBlockType (Some I64Type)) + G.if_ [I64Type] (get_a ^^ get_b ^^ fast) slow let powInt64_shortcut fast env get_a get_b slow = get_b ^^ G.i (Test (Wasm.Values.I64 I64Op.Eqz)) ^^ - G.if_ (ValBlockType (Some I64Type)) + G.if_ [I64Type] (compile_const_64 1L) (* ^0 *) begin (* ^(1+n) *) get_a ^^ compile_const_64 (-1L) ^^ G.i (Compare (Wasm.Values.I64 I64Op.Eq)) ^^ - G.if_ (ValBlockType (Some I64Type)) + G.if_ [I64Type] begin (* -1 ** (1+exp) == if even (1+exp) then 1 else -1 *) get_b ^^ compile_const_64 1L ^^ G.i (Binary (Wasm.Values.I64 I64Op.And)) ^^ G.i (Test (Wasm.Values.I64 I64Op.Eqz)) ^^ - G.if_ (ValBlockType (Some I64Type)) + G.if_ [I64Type] (compile_const_64 1L) get_a end begin get_a ^^ compile_shrS64_const 1L ^^ G.i (Test (Wasm.Values.I64 I64Op.Eqz)) ^^ - G.if_ (ValBlockType (Some I64Type)) + G.if_ [I64Type] get_a (* {0,1}^(1+n) *) begin get_b ^^ compile_const_64 64L ^^ @@ -5222,7 +5222,7 @@ let powInt64_shortcut fast env get_a get_b slow = G.i (Unary (Wasm.Values.I64 I64Op.Clz)) ^^ compile_sub64_const 63L ^^ get_b ^^ G.i (Binary (Wasm.Values.I64 I64Op.Mul)) ^^ compile_const_64 (-63L) ^^ G.i (Compare (Wasm.Values.I64 I64Op.GeS)) ^^ - G.if_ (ValBlockType (Some I64Type)) + G.if_ [I64Type] (get_a ^^ get_b ^^ fast) slow end @@ -5257,7 +5257,7 @@ let additiveNat64_shortcut fast env get_a get_b slow = get_b ^^ compile_shrU64_const 62L ^^ G.i (Binary (Wasm.Values.I64 I64Op.Or)) ^^ G.i (Test (Wasm.Values.I64 I64Op.Eqz)) ^^ - G.if_ (ValBlockType (Some I64Type)) + G.if_ [I64Type] (get_a ^^ get_b ^^ fast) slow @@ -5266,24 +5266,24 @@ let mulNat64_shortcut fast env get_a get_b slow = get_b ^^ G.i (Unary (Wasm.Values.I64 I64Op.Clz)) ^^ G.i (Binary (Wasm.Values.I64 I64Op.Add)) ^^ compile_const_64 64L ^^ G.i (Compare (Wasm.Values.I64 I64Op.GeU)) ^^ - G.if_ (ValBlockType (Some I64Type)) + G.if_ [I64Type] (get_a ^^ get_b ^^ fast) slow let powNat64_shortcut fast env get_a get_b slow = get_b ^^ G.i (Test (Wasm.Values.I64 I64Op.Eqz)) ^^ - G.if_ (ValBlockType (Some I64Type)) + G.if_ [I64Type] (compile_const_64 1L) (* ^0 *) begin (* ^(1+n) *) get_a ^^ compile_shrU64_const 1L ^^ G.i (Test (Wasm.Values.I64 I64Op.Eqz)) ^^ - G.if_ (ValBlockType (Some I64Type)) + G.if_ [I64Type] get_a (* {0,1}^(1+n) *) begin get_b ^^ compile_const_64 64L ^^ G.i (Compare (Wasm.Values.I64 I64Op.GeU)) ^^ then_arithmetic_overflow env ^^ get_a ^^ G.i (Unary (Wasm.Values.I64 I64Op.Clz)) ^^ compile_sub64_const 64L ^^ get_b ^^ G.i (Binary (Wasm.Values.I64 I64Op.Mul)) ^^ compile_const_64 (-64L) ^^ G.i (Compare (Wasm.Values.I64 I64Op.GeS)) ^^ - G.if_ (ValBlockType (Some I64Type)) + G.if_ [I64Type] (get_a ^^ get_b ^^ fast) slow end @@ -5489,10 +5489,10 @@ let compile_binop env t op = let (set_res, get_res) = new_local env "res" in let bits = UnboxedSmallWord.bits_of_type ty in get_exp ^^ - G.if_ (ValBlockType (Some I32Type)) + G.if_ [I32Type] begin get_n ^^ compile_shrU_const Int32.(sub 33l (of_int bits)) ^^ - G.if_ (ValBlockType (Some I32Type)) + G.if_ [I32Type] begin unsigned_dynamics get_n ^^ compile_sub_const (Int32.of_int bits) ^^ get_exp ^^ UnboxedSmallWord.lsb_adjust ty ^^ G.i (Binary (Wasm.Values.I32 I32Op.Mul)) ^^ @@ -5514,10 +5514,10 @@ let compile_binop env t op = (fun env get_n get_exp -> let (set_res, get_res) = new_local64 env "res" in get_exp ^^ - G.if_ (ValBlockType (Some I32Type)) + G.if_ [I32Type] begin get_n ^^ compile_shrU_const 1l ^^ - G.if_ (ValBlockType (Some I32Type)) + G.if_ [I32Type] begin get_exp ^^ compile_unboxed_const 32l ^^ G.i (Compare (Wasm.Values.I32 I32Op.GeU)) ^^ then_arithmetic_overflow env ^^ @@ -5543,10 +5543,10 @@ let compile_binop env t op = get_exp ^^ compile_unboxed_zero ^^ G.i (Compare (Wasm.Values.I32 I32Op.LtS)) ^^ E.then_trap_with env "negative power" ^^ get_exp ^^ - G.if_ (ValBlockType (Some I32Type)) + G.if_ [I32Type] begin get_n ^^ compile_shrS_const Int32.(sub 33l (of_int bits)) ^^ - G.if_ (ValBlockType (Some I32Type)) + G.if_ [I32Type] begin signed_dynamics get_n ^^ compile_sub_const (Int32.of_int (bits - 1)) ^^ get_exp ^^ UnboxedSmallWord.lsb_adjust ty ^^ G.i (Binary (Wasm.Values.I32 I32Op.Mul)) ^^ @@ -5570,19 +5570,19 @@ let compile_binop env t op = get_exp ^^ compile_unboxed_zero ^^ G.i (Compare (Wasm.Values.I32 I32Op.LtS)) ^^ E.then_trap_with env "negative power" ^^ get_exp ^^ - G.if_ (ValBlockType (Some I32Type)) + G.if_ [I32Type] begin get_n ^^ compile_unboxed_one ^^ G.i (Compare (Wasm.Values.I32 I32Op.LeS)) ^^ get_n ^^ compile_unboxed_const (-1l) ^^ G.i (Compare (Wasm.Values.I32 I32Op.GeS)) ^^ G.i (Binary (Wasm.Values.I32 I32Op.And)) ^^ - G.if_ (ValBlockType (Some I32Type)) + G.if_ [I32Type] begin get_n ^^ compile_unboxed_zero ^^ G.i (Compare (Wasm.Values.I32 I32Op.LtS)) ^^ - G.if_ (ValBlockType (Some I32Type)) + G.if_ [I32Type] begin (* -1 ** (1+exp) == if even (1+exp) then 1 else -1 *) get_exp ^^ compile_unboxed_one ^^ G.i (Binary (Wasm.Values.I32 I32Op.And)) ^^ - G.if_ (ValBlockType (Some I32Type)) + G.if_ [I32Type] get_n compile_unboxed_one end @@ -6071,7 +6071,7 @@ and compile_exp (env : E.t) ae exp = | AssertE e1 -> SR.unit, compile_exp_as env ae SR.bool e1 ^^ - G.if_ (ValBlockType None) G.nop (Dfinity.fail_assert env exp.at) + G.if_ [] G.nop (Dfinity.fail_assert env exp.at) | IfE (scrut, e1, e2) -> let code_scrut = compile_exp_as env ae SR.bool scrut in let sr1, code1 = compile_exp env ae e1 in @@ -6106,7 +6106,7 @@ and compile_exp (env : E.t) ae exp = G.branch_to_ d | LoopE e -> SR.Unreachable, - G.loop_ (ValBlockType None) (compile_exp_unit env ae e ^^ G.i (Br (nr 0l)) + G.loop_ [] (compile_exp_unit env ae e ^^ G.i (Br (nr 0l)) ) ^^ G.i Unreachable @@ -6373,7 +6373,7 @@ and fill_pat env ae pat : patternCode = set_x ^^ get_x ^^ Opt.is_some env ^^ - G.if_ (ValBlockType None) + G.if_ [] ( get_x ^^ Opt.project ^^ with_fail fail_code (fill_pat env ae p) @@ -6386,7 +6386,7 @@ and fill_pat env ae pat : patternCode = set_x ^^ get_x ^^ Variant.test_is env l ^^ - G.if_ (ValBlockType None) + G.if_ [] ( get_x ^^ Variant.project ^^ with_fail fail_code (fill_pat env ae p) @@ -6396,7 +6396,7 @@ and fill_pat env ae pat : patternCode = | LitP l -> CanFail (fun fail_code -> compile_lit_pat env l ^^ - G.if_ (ValBlockType None) G.nop fail_code) + G.if_ [] G.nop fail_code) | VarP name -> CannotFail (Var.set_val env ae name) | TupP ps -> diff --git a/src/codegen/instrList.ml b/src/codegen/instrList.ml index 3644936b837..5155e1f7ac4 100644 --- a/src/codegen/instrList.ml +++ b/src/codegen/instrList.ml @@ -10,6 +10,7 @@ features are open Wasm.Ast open Wasm.Source open Wasm.Values +open Wasm.Types let combine_shifts const op = function | I32 opl, ({it = I32 l'; _} as cl), I32 opr, I32 r' when opl = opr -> @@ -99,15 +100,15 @@ let with_region (pos : Source.region) (body : t) : t = (* Depths-managing combinators *) -let if_ (ty : block_type) (thn : t) (els : t) : t = +let if_ (ty : stack_type) (thn : t) (els : t) : t = fun d pos rest -> (If (ty, to_nested_list d pos thn, to_nested_list d pos els) @@ pos) :: rest -let block_ (ty : block_type) (body : t) : t = +let block_ (ty : stack_type) (body : t) : t = fun d pos rest -> (Block (ty, to_nested_list d pos body) @@ pos) :: rest -let loop_ (ty : block_type) (body : t) : t = +let loop_ (ty : stack_type) (body : t) : t = fun d pos rest -> (Loop (ty, to_nested_list d pos body) @@ pos) :: rest @@ -134,7 +135,7 @@ let branch_to_ (p : depth) : t = (* Convenience combinations *) -let labeled_block_ (ty : block_type) depth (body : t) : t = +let labeled_block_ (ty : stack_type) depth (body : t) : t = block_ ty (remember_depth depth body) (* Intended to be used within assert *) diff --git a/src/linking/linkModule.ml b/src/linking/linkModule.ml index cc9ece17047..d730ecaf076 100644 --- a/src/linking/linkModule.ml +++ b/src/linking/linkModule.ml @@ -393,15 +393,11 @@ let rename_types rn m = let ty_var' = rn in let ty_var = phrase ty_var' in - let block_type = function - | VarBlockType tv -> VarBlockType (ty_var tv) - | ValBlockType vto -> ValBlockType vto in - let rec instr' = function | CallIndirect tv -> CallIndirect (ty_var tv) - | Block (bty, is) -> Block (block_type bty, instrs is) - | Loop (bty, is) -> Loop (block_type bty, instrs is) - | If (bty, is1, is2) -> If (block_type bty, instrs is1, instrs is2) + | Block (bty, is) -> Block (bty, instrs is) + | Loop (bty, is) -> Loop (bty, instrs is) + | If (bty, is1, is2) -> If (bty, instrs is1, instrs is2) | i -> i and instr i = phrase instr' i and instrs is = List.map instr is in diff --git a/src/wasm-exts/customModuleDecode.ml b/src/wasm-exts/customModuleDecode.ml index d404edd64c1..499d74473a8 100644 --- a/src/wasm-exts/customModuleDecode.ml +++ b/src/wasm-exts/customModuleDecode.ml @@ -112,7 +112,6 @@ let vu1 s = Int64.to_int (vuN 1 s) let vu32 s = Int64.to_int32 (vuN 32 s) let vs7 s = Int64.to_int (vsN 7 s) let vs32 s = Int64.to_int32 (vsN 32 s) -let vs33 s = I32_convert.wrap_i64 (vsN 33 s) let vs64 s = vsN 64 s let f32 s = F32.of_bits (u32 s) let f64 s = F64.of_bits (u64 s) @@ -159,12 +158,16 @@ let elem_type s = | -0x10 -> FuncRefType | _ -> error s (pos s - 1) "invalid element type" -let stack_type s = vec value_type s +let stack_type s = + match peek s with + | Some 0x40 -> skip 1 s; [] + | _ -> [value_type s] + let func_type s = match vs7 s with | -0x20 -> - let ins = stack_type s in - let out = stack_type s in + let ins = vec value_type s in + let out = vec value_type s in FuncType (ins, out) | _ -> error s (pos s - 1) "invalid function type" @@ -211,12 +214,6 @@ let memop s = let offset = vu32 s in Int32.to_int align, offset -let block_type s = - match peek s with - | Some 0x40 -> skip 1 s; ValBlockType None - | Some b when b land 0xc0 = 0x40 -> ValBlockType (Some (value_type s)) - | _ -> VarBlockType (at vs33 s) - let rec instr s = let pos = pos s in match op s with @@ -224,17 +221,17 @@ let rec instr s = | 0x01 -> nop | 0x02 -> - let bt = block_type s in + let bt = stack_type s in let es' = instr_block s in end_ s; block bt es' | 0x03 -> - let bt = block_type s in + let bt = stack_type s in let es' = instr_block s in end_ s; loop bt es' | 0x04 -> - let bt = block_type s in + let bt = stack_type s in let es1 = instr_block s in if peek s = Some 0x05 then begin expect 0x05 s "ELSE or END opcode expected"; diff --git a/src/wasm-exts/customModuleEncode.ml b/src/wasm-exts/customModuleEncode.ml index 7850e44bba8..85886e2561b 100644 --- a/src/wasm-exts/customModuleEncode.ml +++ b/src/wasm-exts/customModuleEncode.ml @@ -108,7 +108,6 @@ let encode (em : extended_module) = let vu32 i = vu64 Int64.(logand (of_int32 i) 0xffffffffL) let vs7 i = vs64 (Int64.of_int i) let vs32 i = vs64 (Int64.of_int32 i) - let vs33 i = vs64 (Wasm.I64_convert.extend_i32_s i) let f32 x = u32 (Wasm.F32.to_bits x) let f64 x = u64 (Wasm.F64.to_bits x) @@ -148,9 +147,8 @@ let encode (em : extended_module) = let elem_type = function | FuncRefType -> vs7 (-0x10) - let stack_type = vec value_type let func_type = function - | FuncType (ins, out) -> vs7 (-0x20); stack_type ins; stack_type out + | FuncType (ins, out) -> vs7 (-0x20); vec value_type ins; vec value_type out let limits vu {min; max} = bool (max <> None); vu min; opt vu max @@ -182,10 +180,12 @@ let encode (em : extended_module) = let var x = vu32 x.it - let block_type = function - | VarBlockType x -> vs33 x.it - | ValBlockType None -> vs7 (-0x40) - | ValBlockType (Some t) -> value_type t + let stack_type = function + | [] -> vs7 (-0x40) + | [t] -> value_type t + | _ -> + Code.error Wasm.Source.no_region + "cannot encode stack type with arity > 1 (yet)" let rec instr e = if e.at <> no_region then add_to_map e.at.left.file e.at.left.line e.at.left.column 0 (pos s); @@ -194,10 +194,10 @@ let encode (em : extended_module) = | Unreachable -> op 0x00 | Nop -> op 0x01 - | Block (ts, es) -> op 0x02; block_type ts; list instr es; end_ () - | Loop (ts, es) -> op 0x03; block_type ts; list instr es; end_ () + | Block (ts, es) -> op 0x02; stack_type ts; list instr es; end_ () + | Loop (ts, es) -> op 0x03; stack_type ts; list instr es; end_ () | If (ts, es1, es2) -> - op 0x04; block_type ts; list instr es1; + op 0x04; stack_type ts; list instr es1; if es2 <> [] then op 0x05; list instr es2; end_ () diff --git a/test/run/ok/issue36.comp.ok b/test/run/ok/issue36.comp.ok index 06889a31a60..de1fadfdc43 100644 --- a/test/run/ok/issue36.comp.ok +++ b/test/run/ok/issue36.comp.ok @@ -1,5 +1,5 @@ -compile_lit: (FloatLit 1.) +compile_lit: (FloatLit 1) compile_lit: (FloatLit 1.7) -compile_lit: (FloatLit 0.000_18) -compile_lit: (FloatLit 1_604.) +compile_lit: (FloatLit 0.000_180_000_000_000_000_01) +compile_lit: (FloatLit 1_604) compile_lit: (FloatLit 802.156_25) diff --git a/test/run/ok/type-inference.comp.ok b/test/run/ok/type-inference.comp.ok index b3d258e7112..a955962091b 100644 --- a/test/run/ok/type-inference.comp.ok +++ b/test/run/ok/type-inference.comp.ok @@ -1 +1 @@ -compile_lit: (FloatLit 5.1) +compile_lit: (FloatLit 5.099_999_999_999_999_6) From 380da56a2503b287cf1d7c73437344e1167016f8 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 17 Dec 2019 09:51:03 +0100 Subject: [PATCH 0834/1176] IC Stub: Query methods can be responded to (#1036) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I made a mistake in #1017, breaking query methods on `ic-stub`. We didn’t notice because all tests using query methods are only run on `drun`. More evidence that #1018 is the right way to go. --- ic-stub/src/IC/Canister/Imp.hs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ic-stub/src/IC/Canister/Imp.hs b/ic-stub/src/IC/Canister/Imp.hs index a9cf5705192..fd9a89660b6 100644 --- a/ic-stub/src/IC/Canister/Imp.hs +++ b/ic-stub/src/IC/Canister/Imp.hs @@ -364,6 +364,9 @@ rawInvoke esref (CI.Callback cb ex responded res) = cantRespond :: Responded cantRespond = Responded True +canRespond :: Responded +canRespond = Responded False + rawInitializeMethod :: ImpState s -> ExistingCanisters -> Module -> EntityId -> Blob -> ST s (TrapOr InitResult) rawInitializeMethod (esref, cid, inst) ex wasm_mod caller dat = do result <- runExceptT $ do @@ -390,7 +393,7 @@ rawInitializeMethod (esref, cid, inst) ex wasm_mod caller dat = do rawQueryMethod :: ImpState s -> MethodName -> EntityId -> Blob -> ST s (TrapOr Response) rawQueryMethod (esref, cid, inst) method caller dat = do - let es = (initalExecutionState cid inst [] cantRespond) + let es = (initalExecutionState cid inst [] canRespond) { params = Params { param_dat = Just dat , param_caller = Just caller From 8ca6e6b461fd526b24ccbf00bfda82d1e3fb1509 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 17 Dec 2019 10:12:42 +0100 Subject: [PATCH 0835/1176] Remove issue template (#1037) we are not using JIRA for project management (and @crusso keeps forgetting to delete this text from the issues he creates :-)) --- .github/issue_template.md | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 .github/issue_template.md diff --git a/.github/issue_template.md b/.github/issue_template.md deleted file mode 100644 index a6692b142b1..00000000000 --- a/.github/issue_template.md +++ /dev/null @@ -1,3 +0,0 @@ -Reminder: - * Is this related to a story on JIRA? Include AST-nnn in the title. - * Use JIRA to plan who is working when on what. From 3eeeeacd2ce27b47cdba57558d5dcc14419570b1 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Tue, 17 Dec 2019 11:26:37 +0100 Subject: [PATCH 0836/1176] Temporarily disable -(no-)multi-value options (#1038) leaving back a TODO. These don't make sense right now, --- src/exes/moc.ml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/exes/moc.ml b/src/exes/moc.ml index b81c806f51a..274ec8f0e66 100644 --- a/src/exes/moc.ml +++ b/src/exes/moc.ml @@ -78,8 +78,11 @@ let argspec = Arg.align "-stub-system-api", Arg.Unit (fun () -> Flags.(compile_mode := StubMode)), " use the future DFINITY system API (ic-stub-run)"; + (* TODO: bring this back (possibly with flipped default) + as soon as the multi-value `wasm` library is out. "-multi-value", Arg.Set Flags.multi_value, " use multi-value extension"; "-no-multi-value", Arg.Clear Flags.multi_value, " avoid multi-value extension"; + *) "-dp", Arg.Set Flags.dump_parse, " dump parse"; "-dt", Arg.Set Flags.dump_tc, " dump type-checked AST"; From ff13b8445247f7ce2680b6a9aaf9cc1e36414b98 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 17 Dec 2019 12:01:35 +0100 Subject: [PATCH 0837/1176] Test suite: Run in both `drun` and `ic-stub` (#1018) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This runs all tests, unless otherwise configured, in both `drun` and `ic-stub`, so that when the output changes it is clearer whether the problem is likely with us or `drun` or the stub. This would have caught #1036. Also , enabling `async { … }` on `drun` makes some of our tests less useful, as `drun` does not wait for all queus to drain; it only runs until a response appears, which can be early. By running tests in both we can enable `async` on the ic, while still getting the more thorough testing from `ic-stub`. So this unblocks #958. And once we open source, we can make the testsuite ignore the `drun` tests if no `drun` is available. People won’t be able to run `make accept`, but at least they can run some of the tests. --- test/run-drun/large-array.mo | 2 +- test/run-drun/log-slow.mo | 2 + test/run-drun/ok/GIT-843.ic-stub-run.ok | 7 + test/run-drun/ok/actor-import.ic-stub-run.ok | 6 + .../ok/array-out-of-bounds.ic-stub-run.ok | 10 + .../ok/call-async-method.ic-stub-run.ok | 7 + test/run-drun/ok/caller.ic-stub-run.ok | 16 ++ test/run-drun/ok/counter.ic-stub-run.ok | 18 ++ .../run-drun/ok/divide-by-zero.ic-stub-run.ok | 4 + test/run-drun/ok/empty-actor.ic-stub-run.ok | 4 + test/run-drun/ok/empty-call.ic-stub-run.ok | 6 + .../ok/generic-tail-rec.ic-stub-run.ok | 8 + .../ok/hello-world-message.ic-stub-run.ok | 7 + .../ok/hello-world-message.ic-stub-run.ret.ok | 1 + .../ok/hello-world-return.ic-stub-run.ok | 8 + test/run-drun/ok/hello-world.ic-stub-run.ok | 5 + test/run-drun/ok/idl-any.ic-stub-run.ok | 88 +++++++ test/run-drun/ok/idl-bad.ic-stub-run.ok | 7 + .../ok/idl-field-escape.ic-stub-run.ok | 12 + test/run-drun/ok/idl-func.ic-stub-run.ok | 12 + test/run-drun/ok/idl-nary.ic-stub-run.ok | 28 +++ test/run-drun/ok/idl-nat-int.ic-stub-run.ok | 12 + test/run-drun/ok/idl-option.ic-stub-run.ok | 13 + test/run-drun/ok/idl-pair.ic-stub-run.ok | 6 + test/run-drun/ok/idl-record.ic-stub-run.ok | 16 ++ test/run-drun/ok/idl-shorthand.ic-stub-run.ok | 6 + test/run-drun/ok/idl-tuple.ic-stub-run.ok | 16 ++ test/run-drun/ok/idl-unit.ic-stub-run.ok | 6 + test/run-drun/ok/idl-variant.ic-stub-run.ok | 6 + test/run-drun/ok/idl-vector.ic-stub-run.ok | 6 + test/run-drun/ok/oom.ic-stub-run.ok | 8 + .../ok/print-from-init.ic-stub-run.ok | 5 + test/run-drun/ok/query.ic-stub-run.ok | 30 +++ test/run-drun/ok/reject.ic-stub-run.ok | 15 ++ test/run-drun/ok/reversi.ic-stub-run.ok | 20 ++ test/run-drun/ok/rts-stats.ic-stub-run.ok | 5 + test/run-drun/ok/selftail.ic-stub-run.ok | 6 + test/run-drun/ok/show.ic-stub-run.ok | 39 +++ test/run-drun/ok/text-iter.ic-stub-run.ok | 233 ++++++++++++++++++ test/run-drun/tailpositions.mo | 2 + test/run.sh | 52 ++-- 41 files changed, 737 insertions(+), 23 deletions(-) create mode 100644 test/run-drun/ok/GIT-843.ic-stub-run.ok create mode 100644 test/run-drun/ok/actor-import.ic-stub-run.ok create mode 100644 test/run-drun/ok/array-out-of-bounds.ic-stub-run.ok create mode 100644 test/run-drun/ok/call-async-method.ic-stub-run.ok create mode 100644 test/run-drun/ok/caller.ic-stub-run.ok create mode 100644 test/run-drun/ok/counter.ic-stub-run.ok create mode 100644 test/run-drun/ok/divide-by-zero.ic-stub-run.ok create mode 100644 test/run-drun/ok/empty-actor.ic-stub-run.ok create mode 100644 test/run-drun/ok/empty-call.ic-stub-run.ok create mode 100644 test/run-drun/ok/generic-tail-rec.ic-stub-run.ok create mode 100644 test/run-drun/ok/hello-world-message.ic-stub-run.ok create mode 100644 test/run-drun/ok/hello-world-message.ic-stub-run.ret.ok create mode 100644 test/run-drun/ok/hello-world-return.ic-stub-run.ok create mode 100644 test/run-drun/ok/hello-world.ic-stub-run.ok create mode 100644 test/run-drun/ok/idl-any.ic-stub-run.ok create mode 100644 test/run-drun/ok/idl-bad.ic-stub-run.ok create mode 100644 test/run-drun/ok/idl-field-escape.ic-stub-run.ok create mode 100644 test/run-drun/ok/idl-func.ic-stub-run.ok create mode 100644 test/run-drun/ok/idl-nary.ic-stub-run.ok create mode 100644 test/run-drun/ok/idl-nat-int.ic-stub-run.ok create mode 100644 test/run-drun/ok/idl-option.ic-stub-run.ok create mode 100644 test/run-drun/ok/idl-pair.ic-stub-run.ok create mode 100644 test/run-drun/ok/idl-record.ic-stub-run.ok create mode 100644 test/run-drun/ok/idl-shorthand.ic-stub-run.ok create mode 100644 test/run-drun/ok/idl-tuple.ic-stub-run.ok create mode 100644 test/run-drun/ok/idl-unit.ic-stub-run.ok create mode 100644 test/run-drun/ok/idl-variant.ic-stub-run.ok create mode 100644 test/run-drun/ok/idl-vector.ic-stub-run.ok create mode 100644 test/run-drun/ok/oom.ic-stub-run.ok create mode 100644 test/run-drun/ok/print-from-init.ic-stub-run.ok create mode 100644 test/run-drun/ok/query.ic-stub-run.ok create mode 100644 test/run-drun/ok/reject.ic-stub-run.ok create mode 100644 test/run-drun/ok/reversi.ic-stub-run.ok create mode 100644 test/run-drun/ok/rts-stats.ic-stub-run.ok create mode 100644 test/run-drun/ok/selftail.ic-stub-run.ok create mode 100644 test/run-drun/ok/show.ic-stub-run.ok create mode 100644 test/run-drun/ok/text-iter.ic-stub-run.ok diff --git a/test/run-drun/large-array.mo b/test/run-drun/large-array.mo index 5a8b76c762b..3b09dd76757 100644 --- a/test/run-drun/large-array.mo +++ b/test/run-drun/large-array.mo @@ -4,4 +4,4 @@ ignore(Array_init<()>(1024*1024*1024/4, ())); //SKIP run //SKIP run-ir //SKIP run-low -//SKIP ic-stub-run +//SKIP comp-stub diff --git a/test/run-drun/log-slow.mo b/test/run-drun/log-slow.mo index d73e746e510..f1260d2d64d 100644 --- a/test/run-drun/log-slow.mo +++ b/test/run-drun/log-slow.mo @@ -1,5 +1,7 @@ // These are rather long-running tests, not advisable for wasm-run! +//SKIP comp-stub + // Nat* for (n in range(0, 255)) { diff --git a/test/run-drun/ok/GIT-843.ic-stub-run.ok b/test/run-drun/ok/GIT-843.ic-stub-run.ok new file mode 100644 index 00000000000..4e7ad8dbdc3 --- /dev/null +++ b/test/run-drun/ok/GIT-843.ic-stub-run.ok @@ -0,0 +1,7 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ update Bad(0x4449444c0000) +debug.print: ok +← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/actor-import.ic-stub-run.ok b/test/run-drun/ok/actor-import.ic-stub-run.ok new file mode 100644 index 00000000000..a1a43a23aef --- /dev/null +++ b/test/run-drun/ok/actor-import.ic-stub-run.ok @@ -0,0 +1,6 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ update go(0x4449444c0000) +← completed: 0x4449444c016900010001080000000000000400 diff --git a/test/run-drun/ok/array-out-of-bounds.ic-stub-run.ok b/test/run-drun/ok/array-out-of-bounds.ic-stub-run.ok new file mode 100644 index 00000000000..511d283f933 --- /dev/null +++ b/test/run-drun/ok/array-out-of-bounds.ic-stub-run.ok @@ -0,0 +1,10 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ update foo1(0x4449444c0000) +Trap: EvalTrapError :0.1 "canister trapped explicitly: Array index out of bounds" +← rejected (RC_CANISTER_ERROR): canister trapped: EvalTrapError :0.1 "canister trapped explicitly: Array index out of bounds" +→ update foo2(0x4449444c0000) +Trap: EvalTrapError :0.1 "canister trapped explicitly: Array index out of bounds" +← rejected (RC_CANISTER_ERROR): canister trapped: EvalTrapError :0.1 "canister trapped explicitly: Array index out of bounds" diff --git a/test/run-drun/ok/call-async-method.ic-stub-run.ok b/test/run-drun/ok/call-async-method.ic-stub-run.ok new file mode 100644 index 00000000000..4d183fa65f6 --- /dev/null +++ b/test/run-drun/ok/call-async-method.ic-stub-run.ok @@ -0,0 +1,7 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ update __motoko_async_helper(0x4449444c0000) +Trap: EvalTrapError :0.1 "canister trapped explicitly: not a self-call" +← rejected (RC_CANISTER_ERROR): canister trapped: EvalTrapError :0.1 "canister trapped explicitly: not a self-call" diff --git a/test/run-drun/ok/caller.ic-stub-run.ok b/test/run-drun/ok/caller.ic-stub-run.ok new file mode 100644 index 00000000000..b49bf45f6ac --- /dev/null +++ b/test/run-drun/ok/caller.ic-stub-run.ok @@ -0,0 +1,16 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ update c1(0x4449444c0000) +← completed: 0x4449444c0000 +→ update c2(0x4449444c0000) +← completed: 0x4449444c0000 +→ update c3(0x4449444c0000) +← completed: 0x4449444c0000 +→ update c4(0x4449444c0000) +← completed: 0x4449444c0000 +→ query c6(0x4449444c0000) +← completed: 0x4449444c0000 +→ update c7(0x4449444c0000) +← completed: 0x4449444c016d7b010003caffee diff --git a/test/run-drun/ok/counter.ic-stub-run.ok b/test/run-drun/ok/counter.ic-stub-run.ok new file mode 100644 index 00000000000..dca569ca0e7 --- /dev/null +++ b/test/run-drun/ok/counter.ic-stub-run.ok @@ -0,0 +1,18 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ update inc(0x4449444c0000) +debug.print: 2 +← completed: 0x4449444c0000 +→ update inc(0x4449444c0000) +debug.print: 3 +← completed: 0x4449444c0000 +→ update inc(0x4449444c0000) +debug.print: 4 +← completed: 0x4449444c0000 +→ update printCounter(0x4449444c0000) +debug.print: 4 +← completed: 0x4449444c0000 +→ update get(0x4449444c0000) +← completed: 0x4449444c00017d04 diff --git a/test/run-drun/ok/divide-by-zero.ic-stub-run.ok b/test/run-drun/ok/divide-by-zero.ic-stub-run.ok new file mode 100644 index 00000000000..761eb6df0e1 --- /dev/null +++ b/test/run-drun/ok/divide-by-zero.ic-stub-run.ok @@ -0,0 +1,4 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← rejected (RC_CANISTER_ERROR): Initialization trapped: EvalTrapError :0.1 "NumericIntegerDivideByZero" diff --git a/test/run-drun/ok/empty-actor.ic-stub-run.ok b/test/run-drun/ok/empty-actor.ic-stub-run.ok new file mode 100644 index 00000000000..54225bc8555 --- /dev/null +++ b/test/run-drun/ok/empty-actor.ic-stub-run.ok @@ -0,0 +1,4 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed diff --git a/test/run-drun/ok/empty-call.ic-stub-run.ok b/test/run-drun/ok/empty-call.ic-stub-run.ok new file mode 100644 index 00000000000..be9fb5d62c0 --- /dev/null +++ b/test/run-drun/ok/empty-call.ic-stub-run.ok @@ -0,0 +1,6 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ update go(0x4449444c0000) +← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/generic-tail-rec.ic-stub-run.ok b/test/run-drun/ok/generic-tail-rec.ic-stub-run.ok new file mode 100644 index 00000000000..cab5d9173c3 --- /dev/null +++ b/test/run-drun/ok/generic-tail-rec.ic-stub-run.ok @@ -0,0 +1,8 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +debug.print: done 1 +debug.print: done 2 +debug.print: done 3 +debug.print: done 4 +← completed diff --git a/test/run-drun/ok/hello-world-message.ic-stub-run.ok b/test/run-drun/ok/hello-world-message.ic-stub-run.ok new file mode 100644 index 00000000000..f7b62ca515e --- /dev/null +++ b/test/run-drun/ok/hello-world-message.ic-stub-run.ok @@ -0,0 +1,7 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +ic-stub-run: Invalid ingress type hello +CallStack (from HasCallStack): + error, called at src/IC/DRun/Parse.hs:32:15 in main:IC.DRun.Parse diff --git a/test/run-drun/ok/hello-world-message.ic-stub-run.ret.ok b/test/run-drun/ok/hello-world-message.ic-stub-run.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/hello-world-message.ic-stub-run.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-drun/ok/hello-world-return.ic-stub-run.ok b/test/run-drun/ok/hello-world-return.ic-stub-run.ok new file mode 100644 index 00000000000..ced690a2811 --- /dev/null +++ b/test/run-drun/ok/hello-world-return.ic-stub-run.ok @@ -0,0 +1,8 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ query hello(0x4449444c00017105576f726c64) +← completed: 0x4449444c0001710c48656c6c6f20576f726c6421 +→ query hello2(0x4449444c00017105576f726c64) +← completed: 0x4449444c0001710c48656c6c6f20576f726c6421 diff --git a/test/run-drun/ok/hello-world.ic-stub-run.ok b/test/run-drun/ok/hello-world.ic-stub-run.ok new file mode 100644 index 00000000000..1eeeb078e34 --- /dev/null +++ b/test/run-drun/ok/hello-world.ic-stub-run.ok @@ -0,0 +1,5 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +debug.print: Hello World! +← completed diff --git a/test/run-drun/ok/idl-any.ic-stub-run.ok b/test/run-drun/ok/idl-any.ic-stub-run.ok new file mode 100644 index 00000000000..894b48fff3d --- /dev/null +++ b/test/run-drun/ok/idl-any.ic-stub-run.ok @@ -0,0 +1,88 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ update any(0x4449444c00027f7103466f6f) +debug.print: ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c00027e710103466f6f) +debug.print: ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c00027d718080800803466f6f) +debug.print: ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c00027c718080800803466f6f) +debug.print: ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c00027b71ab03466f6f) +debug.print: ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c00027a71abcd03466f6f) +debug.print: ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c00027971deadbeef03466f6f) +debug.print: ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c00027871deadbeefcaffee6603466f6f) +debug.print: ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c00027771ab03466f6f) +debug.print: ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c00027671abcd03466f6f) +debug.print: ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c00027571deadbeef03466f6f) +debug.print: ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c00027471deadbeefcaffee6603466f6f) +debug.print: ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c00027371deadbeef03466f6f) +debug.print: ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c00027271deadbeefcaffee6603466f6f) +debug.print: ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c0002717103466f6f03466f6f) +debug.print: ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c0002707103466f6f) +debug.print: ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c016e710200710003466f6f) +debug.print: ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c016e710200710103466f6f03466f6f) +debug.print: ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c016d710200710003466f6f) +debug.print: ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c016d710200710103466f6f03466f6f) +debug.print: ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c016d71020071020003466f6f03466f6f) +debug.print: ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c016c0002007103466f6f) +debug.print: ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c016c01800175020071deadbeef03466f6f) +debug.print: ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c016c02007180017502007101a0deadbeef03466f6f) +debug.print: ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c016b0180017502007100deadbeef03466f6f) +debug.print: ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c016b0200718001750200710001a003466f6f) +debug.print: ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c016b02007180017502007101deadbeef03466f6f) +debug.print: ok: Foo +← completed: 0x4449444c0000 +→ update any(0x4449444c016602abcd0200710400deadbeef03466f6f) +debug.print: ok: Foo +← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-bad.ic-stub-run.ok b/test/run-drun/ok/idl-bad.ic-stub-run.ok new file mode 100644 index 00000000000..8106b29424e --- /dev/null +++ b/test/run-drun/ok/idl-bad.ic-stub-run.ok @@ -0,0 +1,7 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ query foo(0x4e4f544449444c) +debug.print: IDL error: missing magic bytes +← rejected (RC_CANISTER_ERROR): canister trapped: EvalTrapError :0.1 "unreachable executed" diff --git a/test/run-drun/ok/idl-field-escape.ic-stub-run.ok b/test/run-drun/ok/idl-field-escape.ic-stub-run.ok new file mode 100644 index 00000000000..fa73a9cfd53 --- /dev/null +++ b/test/run-drun/ok/idl-field-escape.ic-stub-run.ok @@ -0,0 +1,12 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ update foo1(0x4449444c0000) +← completed: 0x4449444c016c01868eb7027f0100 +→ update foo2(0x4449444c0000) +← completed: 0x4449444c016c01868eb7027f0100 +→ update out(0x4449444c0000) +← completed: 0x4449444c016c03007c017dbcfef7b102710100ffff03802003585858 +→ update input(0x4449444c016c03007c017dbcfef7b102710100ffff03802003585858) +← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-func.ic-stub-run.ok b/test/run-drun/ok/idl-func.ic-stub-run.ok new file mode 100644 index 00000000000..3bf918ef016 --- /dev/null +++ b/test/run-drun/ok/idl-func.ic-stub-run.ok @@ -0,0 +1,12 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ query fun(0x4449444c0000) +← completed: 0x4449444c026e016a017c010100010000 +→ query fun2(0x4449444c026e016a017c0000010000) +← completed: 0x4449444c0000 +→ query fun3(0x4449444c0000) +← completed: 0x4449444c036a00010101016e026a017c010200010001010800000000000004000366756e +→ query fun4(0x4449444c0000) +← completed: 0x4449444c016a0000010201000101080000000000000400066f6e65776179 diff --git a/test/run-drun/ok/idl-nary.ic-stub-run.ok b/test/run-drun/ok/idl-nary.ic-stub-run.ok new file mode 100644 index 00000000000..53330a2c4ac --- /dev/null +++ b/test/run-drun/ok/idl-nary.ic-stub-run.ok @@ -0,0 +1,28 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ update two(0x4449444c00027171034f6e650354776f) +← completed: 0x4449444c00027171034f6e650354776f +→ update three(0x4449444c0003717171034f6e650354776f055468726565) +← completed: 0x4449444c0003717171034f6e650354776f055468726565 +→ update four(0x4449444c000471717171034f6e650354776f05546872656504466f7572) +← completed: 0x4449444c000471717171034f6e650354776f05546872656504466f7572 +→ update mkRecord(0x4449444c0000) +← completed: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 +→ update unary1(0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572) +← completed: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 +→ update unary2(0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572) +← completed: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 +→ update unary3(0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572) +← completed: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 +→ update unary4(0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572) +← completed: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 +→ update three(0x4449444c00027171034f6e650354776f) +Trap: EvalTrapError :0.1 "canister trapped explicitly: IDL error: too few arguments Text,Text,Text" +← rejected (RC_CANISTER_ERROR): canister trapped: EvalTrapError :0.1 "canister trapped explicitly: IDL error: too few arguments Text,Text,Text" +→ update three(0x4449444c0003717171034f6e650354776f05546872656545585452414259544553) +Trap: EvalTrapError :0.1 "canister trapped explicitly: IDL error: left-over bytes Text,Text,Text" +← rejected (RC_CANISTER_ERROR): canister trapped: EvalTrapError :0.1 "canister trapped explicitly: IDL error: left-over bytes Text,Text,Text" +→ update four(0x4449444c00057171717171034f6e650354776f05546872656504466f75720446697665) +← completed: 0x4449444c000471717171034f6e650354776f05546872656504466f7572 diff --git a/test/run-drun/ok/idl-nat-int.ic-stub-run.ok b/test/run-drun/ok/idl-nat-int.ic-stub-run.ok new file mode 100644 index 00000000000..e2cfca32cb4 --- /dev/null +++ b/test/run-drun/ok/idl-nat-int.ic-stub-run.ok @@ -0,0 +1,12 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ query absolute(0x4449444c00017d2a) +← completed: 0x4449444c00017d2a +→ query absolute(0x4449444c00017c56) +← completed: 0x4449444c00017d2a +→ query absolutes(0x4449444c016d7d0100022a19) +← completed: 0x4449444c016d7d0100022a19 +→ query absolutes(0x4449444c016d7c0100025619) +← completed: 0x4449444c016d7d0100022a19 diff --git a/test/run-drun/ok/idl-option.ic-stub-run.ok b/test/run-drun/ok/idl-option.ic-stub-run.ok new file mode 100644 index 00000000000..5a164f4cb11 --- /dev/null +++ b/test/run-drun/ok/idl-option.ic-stub-run.ok @@ -0,0 +1,13 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ update any(0x4449444c00017f) +debug.print: ok: null +← completed: 0x4449444c0000 +→ update any(0x4449444c016e71010000) +debug.print: ok: null +← completed: 0x4449444c0000 +→ update any(0x4449444c016e7101000103466f6f) +debug.print: ok: Foo +← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-pair.ic-stub-run.ok b/test/run-drun/ok/idl-pair.ic-stub-run.ok new file mode 100644 index 00000000000..5fc5fed734d --- /dev/null +++ b/test/run-drun/ok/idl-pair.ic-stub-run.ok @@ -0,0 +1,6 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ update len2(0x4449444c0002717102486905576f726c64) +← completed: 0x4449444c016c02007c017c01000205 diff --git a/test/run-drun/ok/idl-record.ic-stub-run.ok b/test/run-drun/ok/idl-record.ic-stub-run.ok new file mode 100644 index 00000000000..caf6de36b5b --- /dev/null +++ b/test/run-drun/ok/idl-record.ic-stub-run.ok @@ -0,0 +1,16 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ update pair(0x4449444c016c020071017c010004486579212a) +debug.print: ok: +42 +← completed: 0x4449444c0000 +→ update record(0x4449444c016c02b99adecb0171f1fee18d037c010004486579212a) +debug.print: ok: Hey! +← completed: 0x4449444c0000 +→ update record1(0x4449444c016c03b99adecb0171f1fee18d037c88be8c890477010004486579212a19) +debug.print: ok: +25 +← completed: 0x4449444c0000 +→ update record2(0x4449444c016c03b99adecb0171f1fee18d037c88be8c89047702007704486579212a1819) +debug.print: ok: Hey! +25 +← completed: 0x4449444c00017719 diff --git a/test/run-drun/ok/idl-shorthand.ic-stub-run.ok b/test/run-drun/ok/idl-shorthand.ic-stub-run.ok new file mode 100644 index 00000000000..8268976065e --- /dev/null +++ b/test/run-drun/ok/idl-shorthand.ic-stub-run.ok @@ -0,0 +1,6 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ query foo(0x4449444c016b01d1a7cf027f010000) +← completed: 0x4449444c016b01d1a7cf027f010000 diff --git a/test/run-drun/ok/idl-tuple.ic-stub-run.ok b/test/run-drun/ok/idl-tuple.ic-stub-run.ok new file mode 100644 index 00000000000..5962adf545e --- /dev/null +++ b/test/run-drun/ok/idl-tuple.ic-stub-run.ok @@ -0,0 +1,16 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ query len2(0x4449444c0002717102486905576f726c64) +← completed: 0x4449444c00027c7c0205 +→ query len3(0x4449444c016c02007101750200710548656c6c6f0102030405576f726c64) +← completed: 0x4449444c00037c7c7c050581848c20 +→ query len3a(0x4449444c036c02007101756c030071017502026e000201710548656c6c6f010203040005576f726c64) +← completed: 0x4449444c00037c7c7c050581848c20 +→ query len3(0x4449444c016c030071007601750200710548656c6c6fdead0102030405576f726c64) +← completed: 0x4449444c00037c7c7c050581848c20 +→ query len3(0x4449444c016c030071017502760200710548656c6c6f01020304dead05576f726c64) +← completed: 0x4449444c00037c7c7c050581848c20 +→ query len3a(0x4449444c026c030071017502016e000200710548656c6c6f010203040005576f726c64) +← completed: 0x4449444c00037c7c7c050581848c20 diff --git a/test/run-drun/ok/idl-unit.ic-stub-run.ok b/test/run-drun/ok/idl-unit.ic-stub-run.ok new file mode 100644 index 00000000000..e7d4b9a40ab --- /dev/null +++ b/test/run-drun/ok/idl-unit.ic-stub-run.ok @@ -0,0 +1,6 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ query unit_id(0x4449444c0000) +← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-variant.ic-stub-run.ok b/test/run-drun/ok/idl-variant.ic-stub-run.ok new file mode 100644 index 00000000000..75074f6bd69 --- /dev/null +++ b/test/run-drun/ok/idl-variant.ic-stub-run.ok @@ -0,0 +1,6 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ query numify(0x4449444c016b03d583b702008790c0bd0479dc9790cb0e790100000220000000) +← completed: 0x4449444c016b03d583b702008790c0bd0479dc9790cb0e790100000120000000 diff --git a/test/run-drun/ok/idl-vector.ic-stub-run.ok b/test/run-drun/ok/idl-vector.ic-stub-run.ok new file mode 100644 index 00000000000..352cb7766e8 --- /dev/null +++ b/test/run-drun/ok/idl-vector.ic-stub-run.ok @@ -0,0 +1,6 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ query rose(0x4449444c016d00010003000400020000000000) +← completed: 0x4449444c026e016d0001000103010001040100010201000100010001000100 diff --git a/test/run-drun/ok/oom.ic-stub-run.ok b/test/run-drun/ok/oom.ic-stub-run.ok new file mode 100644 index 00000000000..563d63af289 --- /dev/null +++ b/test/run-drun/ok/oom.ic-stub-run.ok @@ -0,0 +1,8 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ update go(0x4449444c0000) +← completed: 0x4449444c0000 +→ update go(0x4449444c0000) +← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/print-from-init.ic-stub-run.ok b/test/run-drun/ok/print-from-init.ic-stub-run.ok new file mode 100644 index 00000000000..fc6374816a2 --- /dev/null +++ b/test/run-drun/ok/print-from-init.ic-stub-run.ok @@ -0,0 +1,5 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +debug.print: Debug out +← completed diff --git a/test/run-drun/ok/query.ic-stub-run.ok b/test/run-drun/ok/query.ic-stub-run.ok new file mode 100644 index 00000000000..5608f187c54 --- /dev/null +++ b/test/run-drun/ok/query.ic-stub-run.ok @@ -0,0 +1,30 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ update inc(0x4449444c0000) +debug.print: 2 +← completed: 0x4449444c0000 +→ update inc(0x4449444c0000) +debug.print: 3 +← completed: 0x4449444c0000 +→ update inc(0x4449444c0000) +debug.print: 4 +← completed: 0x4449444c0000 +→ update printCounter(0x4449444c0000) +debug.print: 4 +← completed: 0x4449444c0000 +→ update get(0x4449444c0000) +← completed: 0x4449444c00017d04 +→ query read(0x4449444c0000) +debug.print: 5 +← completed: 0x4449444c00017d04 +→ update printCounter(0x4449444c0000) +debug.print: 4 +← completed: 0x4449444c0000 +→ query read(0x4449444c0000) +debug.print: 5 +← completed: 0x4449444c00017d04 +→ update printCounter(0x4449444c0000) +debug.print: 4 +← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/reject.ic-stub-run.ok b/test/run-drun/ok/reject.ic-stub-run.ok new file mode 100644 index 00000000000..6345e111974 --- /dev/null +++ b/test/run-drun/ok/reject.ic-stub-run.ok @@ -0,0 +1,15 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ update reject1(0x4449444c0000) +debug.print: 1 +← rejected (RC_CANISTER_REJECT): Error +→ update reject2(0x4449444c0000) +debug.print: 1 +debug.print: ok +← completed: 0x4449444c0000 +→ update reject3(0x4449444c0000) +debug.print: 1 +debug.print: ok +← rejected (RC_CANISTER_REJECT): Error diff --git a/test/run-drun/ok/reversi.ic-stub-run.ok b/test/run-drun/ok/reversi.ic-stub-run.ok new file mode 100644 index 00000000000..2bddbf68bb6 --- /dev/null +++ b/test/run-drun/ok/reversi.ic-stub-run.ok @@ -0,0 +1,20 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ update reset(0x4449444c0000) +← completed: 0x4449444c0000 +→ update board(0x4449444c0000) +← completed: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e4f2a2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a +→ update place(0x4449444c00037c7c7c010204) +← completed: 0x4449444c000171024f4b +→ update board(0x4449444c0000) +← completed: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e4f2e2e2e0a2e2e2e4f4f2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a +→ update place(0x4449444c00037c7c7c020203) +← completed: 0x4449444c000171024f4b +→ update board(0x4449444c0000) +← completed: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a +→ update place(0x4449444c00037c7c7c010402) +← completed: 0x4449444c000171024f4b +→ update board(0x4449444c0000) +← completed: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e4f4f2e2e2e0a2e2e4f4f4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a diff --git a/test/run-drun/ok/rts-stats.ic-stub-run.ok b/test/run-drun/ok/rts-stats.ic-stub-run.ok new file mode 100644 index 00000000000..fd75777735a --- /dev/null +++ b/test/run-drun/ok/rts-stats.ic-stub-run.ok @@ -0,0 +1,5 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +debug.print: Size and allocation delta: (10_008, 10_008) +← completed diff --git a/test/run-drun/ok/selftail.ic-stub-run.ok b/test/run-drun/ok/selftail.ic-stub-run.ok new file mode 100644 index 00000000000..cd60c0c2f8f --- /dev/null +++ b/test/run-drun/ok/selftail.ic-stub-run.ok @@ -0,0 +1,6 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +debug.print: ok1 +debug.print: ok2 +← rejected (RC_CANISTER_ERROR): Initialization trapped: EvalExhaustionError :0.1 "call stack exhausted" diff --git a/test/run-drun/ok/show.ic-stub-run.ok b/test/run-drun/ok/show.ic-stub-run.ok new file mode 100644 index 00000000000..3e9eb501dcb --- /dev/null +++ b/test/run-drun/ok/show.ic-stub-run.ok @@ -0,0 +1,39 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +debug.print: true +debug.print: false +debug.print: -42_000_000_000_000 +debug.print: -42_000_000 +debug.print: -42_000 +debug.print: -42 +debug.print: 0 +debug.print: 0 +debug.print: +42 +debug.print: +42_000 +debug.print: +42_000_000 +debug.print: +420_000_000_000_000 +debug.print: 0 +debug.print: 42 +debug.print: 42_000 +debug.print: 42_000_000 +debug.print: 420_000_000_000_000 +debug.print: (42, -42, ()) +debug.print: ("Foobar", null, null, ?23) +debug.print: [] +debug.print: [1, 2, 3] +debug.print: [var] +debug.print: [var 1, 2, 3] +debug.print: {bar = true; foo = +42} +debug.print: #foo +debug.print: #bar(1, 2) +debug.print: #bar({}) +debug.print: #bar([]) +debug.print: #bar(42) +debug.print: #bar(-42) +debug.print: #foo(+42) +debug.print: 0x2A +debug.print: 42 +debug.print: +42 +debug.print: -42 +← completed diff --git a/test/run-drun/ok/text-iter.ic-stub-run.ok b/test/run-drun/ok/text-iter.ic-stub-run.ok new file mode 100644 index 00000000000..42a8ffb6c61 --- /dev/null +++ b/test/run-drun/ok/text-iter.ic-stub-run.ok @@ -0,0 +1,233 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +debug.print: via `debugPrint`: +debug.print: hello world! +debug.print: +debug.print: via iteration and `debugPrintChar`: #1 +debug.print: h +debug.print: e +debug.print: l +debug.print: l +debug.print: o +debug.print: +debug.print: w +debug.print: o +debug.print: r +debug.print: l +debug.print: d +debug.print: ! +debug.print: +debug.print: via iteration and `debugPrintChar`: #2 +debug.print: 1 +debug.print: : +debug.print: ' +debug.print: h +debug.print: ' +debug.print: +debug.print: 2 +debug.print: : +debug.print: ' +debug.print: e +debug.print: ' +debug.print: +debug.print: 3 +debug.print: : +debug.print: ' +debug.print: l +debug.print: ' +debug.print: +debug.print: 4 +debug.print: : +debug.print: ' +debug.print: l +debug.print: ' +debug.print: +debug.print: 5 +debug.print: : +debug.print: ' +debug.print: o +debug.print: ' +debug.print: +debug.print: 6 +debug.print: : +debug.print: ' +debug.print: +debug.print: ' +debug.print: +debug.print: 7 +debug.print: : +debug.print: ' +debug.print: w +debug.print: ' +debug.print: +debug.print: 8 +debug.print: : +debug.print: ' +debug.print: o +debug.print: ' +debug.print: +debug.print: 9 +debug.print: : +debug.print: ' +debug.print: r +debug.print: ' +debug.print: +debug.print: 10 +debug.print: : +debug.print: ' +debug.print: l +debug.print: ' +debug.print: +debug.print: 11 +debug.print: : +debug.print: ' +debug.print: d +debug.print: ' +debug.print: +debug.print: 12 +debug.print: : +debug.print: ' +debug.print: ! +debug.print: ' +debug.print: +debug.print: +debug.print: via iteration and `debugPrintChar` (Unicode): #3 +debug.print: 1 +debug.print: : +debug.print: ' +debug.print: П +debug.print: ' +debug.print: +debug.print: 2 +debug.print: : +debug.print: ' +debug.print: р +debug.print: ' +debug.print: +debug.print: 3 +debug.print: : +debug.print: ' +debug.print: и +debug.print: ' +debug.print: +debug.print: 4 +debug.print: : +debug.print: ' +debug.print: в +debug.print: ' +debug.print: +debug.print: 5 +debug.print: : +debug.print: ' +debug.print: е +debug.print: ' +debug.print: +debug.print: 6 +debug.print: : +debug.print: ' +debug.print: т +debug.print: ' +debug.print: +debug.print: 7 +debug.print: : +debug.print: ' +debug.print: с +debug.print: ' +debug.print: +debug.print: 8 +debug.print: : +debug.print: ' +debug.print: т +debug.print: ' +debug.print: +debug.print: 9 +debug.print: : +debug.print: ' +debug.print: в +debug.print: ' +debug.print: +debug.print: 10 +debug.print: : +debug.print: ' +debug.print: у +debug.print: ' +debug.print: +debug.print: 11 +debug.print: : +debug.print: ' +debug.print: ю +debug.print: ' +debug.print: +debug.print: 12 +debug.print: : +debug.print: ' +debug.print: , +debug.print: ' +debug.print: +debug.print: 13 +debug.print: : +debug.print: ' +debug.print: +debug.print: ' +debug.print: +debug.print: 14 +debug.print: : +debug.print: ' +debug.print: м +debug.print: ' +debug.print: +debug.print: 15 +debug.print: : +debug.print: ' +debug.print: и +debug.print: ' +debug.print: +debug.print: 16 +debug.print: : +debug.print: ' +debug.print: р +debug.print: ' +debug.print: +debug.print: 17 +debug.print: : +debug.print: ' +debug.print: ! +debug.print: ' +debug.print: +debug.print: 18 +debug.print: : +debug.print: ' +debug.print: + +debug.print: ' +debug.print: +debug.print: +debug.print: via iteration and `debugPrintChar` (Unicode): #4 +debug.print: 1 +debug.print: : +debug.print: ' +debug.print: 🙈 +debug.print: ' +debug.print: +debug.print: 2 +debug.print: : +debug.print: ' +debug.print: 🎸 +debug.print: ' +debug.print: +debug.print: 3 +debug.print: : +debug.print: ' +debug.print: 😋 +debug.print: ' +debug.print: +debug.print: +debug.print: Приветствую, мир! + +debug.print: +debug.print: П +debug.print: +debug.print: 🙈 +debug.print: +← completed diff --git a/test/run-drun/tailpositions.mo b/test/run-drun/tailpositions.mo index ed9e5f9f44f..a1040719cfb 100644 --- a/test/run-drun/tailpositions.mo +++ b/test/run-drun/tailpositions.mo @@ -1,5 +1,7 @@ /* test tail-position calculation; error would stack overflow in drun*/ +//SKIP comp-stub + let bound:Int = 100000; { diff --git a/test/run.sh b/test/run.sh index 36b2a40c0bf..eba626288b5 100755 --- a/test/run.sh +++ b/test/run.sh @@ -91,7 +91,7 @@ function run () { local ext="$1" shift - if grep -q "^//SKIP $ext" $file; then return 1; fi + if grep -q "^//SKIP $ext$" $file; then return 1; fi if test -e $out/$base.$ext then @@ -115,6 +115,21 @@ function run () { return $ret } +function run_if () { + # first argument: a file extension + # remaining argument: passed to run + + local ext="$1" + shift + + if test -e $out/$base.$ext + then + run "$@" + else + return 1 + fi +} + for file in "$@"; do if ! [ -r $file ] @@ -230,19 +245,14 @@ do run comp $MOC $moc_extra_flags -wasi-system-api --hide-warnings --map -c $mangled -o $out/$base.wasm else run comp $MOC $moc_extra_flags --hide-warnings --map -c $mangled -o $out/$base.wasm - can_use_drun=$? - - if [ "$can_use_drun" -ne 0 ]; - then - run comp-stub $MOC $moc_extra_flags -stub-system-api --hide-warnings --map -c $mangled -o $out/$base.wasm - fi + run comp-stub $MOC $moc_extra_flags -stub-system-api --hide-warnings --map -c $mangled -o $out/$base.stub.wasm fi + run_if wasm valid wasm-validate $out/$base.wasm + run_if stub.wasm valid-stub wasm-validate $out/$base.stub.wasm + if [ -e $out/$base.wasm ] then - # Validate wasm - run valid wasm-validate $out/$base.wasm - # Check filecheck if [ "$SKIP_RUNNING" != yes ] then @@ -254,20 +264,18 @@ do diff_files="$diff_files $base.filecheck" fi fi + fi - # Run compiled program - if [ "$SKIP_RUNNING" != yes ] + # Run compiled program + if [ "$SKIP_RUNNING" != yes ] + then + if [ $DRUN = no ] then - if [ $DRUN = no ] - then - run wasm-run $WASMTIME --disable-cache $out/$base.wasm - elif [ "$can_use_drun" -eq 0 ] - then - run drun-run $DRUN_WRAPPER $out/$base.wasm $mangled - else - DRUN=$IC_STUB_RUN \ - run ic-stub-run $DRUN_WRAPPER $out/$base.wasm $mangled - fi + run_if wasm wasm-run $WASMTIME --disable-cache $out/$base.wasm + else + run_if wasm drun-run $DRUN_WRAPPER $out/$base.wasm $mangled + DRUN=$IC_STUB_RUN \ + run_if stub.wasm ic-stub-run $DRUN_WRAPPER $out/$base.stub.wasm $mangled fi fi rm -f $mangled From 24b9155f2f0916e970ec9b11879ee7fa3158b6a1 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 17 Dec 2019 12:24:22 +0100 Subject: [PATCH 0838/1176] Correctly decode imported actor URLs (#1034) no longer hardcoding `"ic:000000000000040054"` This pulls the URL decoding code from #1001 into `Lib.URL`. Not the best place, but we want to use it from `pipeline` and `lowering` and maybe more places eventually. --- src/languageServer/completion.ml | 6 +- src/languageServer/declaration_index.ml | 10 +- src/languageServer/definition.ml | 2 +- src/languageServer/source_file.ml | 16 +- src/lib/lib.ml | 225 ++++++++++++++++++++++-- src/lib/lib.mli | 34 +++- src/lowering/desugar.ml | 8 +- src/pipeline/file_path.ml | 25 --- src/pipeline/file_path.mli | 16 -- src/pipeline/file_path_test.ml | 95 ---------- src/pipeline/pipeline.ml | 1 - src/pipeline/pipeline.mli | 1 - src/pipeline/resolve_import.ml | 71 +++----- src/pipeline/resolve_import.mli | 7 - 14 files changed, 289 insertions(+), 228 deletions(-) delete mode 100644 src/pipeline/file_path.ml delete mode 100644 src/pipeline/file_path.mli delete mode 100644 src/pipeline/file_path_test.ml diff --git a/src/languageServer/completion.ml b/src/languageServer/completion.ml index a538b32d56d..240b1d106f0 100644 --- a/src/languageServer/completion.ml +++ b/src/languageServer/completion.ml @@ -59,13 +59,13 @@ let item_of_ide_decl (d : DI.ide_decl) : Lsp_t.completion_item = let import_relative_to_project_root root module_path dependency = - match Pipeline.FilePath.relative_to root module_path with + match Lib.FilePath.relative_to root module_path with | None -> None | Some root_to_module -> root_to_module |> Filename.dirname |> Lib.Fun.flip Filename.concat dependency - |> Pipeline.FilePath.normalise + |> Lib.FilePath.normalise |> Lib.Option.some (* Given a source file and a cursor position in that file, figure out @@ -121,7 +121,7 @@ let opt_bind f = function let completions index logger project_root file_path file_contents line column = let imported = Source_file.parse_module_header project_root file_path file_contents in - let current_uri_opt = Pipeline.FilePath.relative_to project_root file_path in + let current_uri_opt = Lib.FilePath.relative_to project_root file_path in let module_alias_completion_item alias = Lsp_t.{ completion_item_label = alias; diff --git a/src/languageServer/declaration_index.ml b/src/languageServer/declaration_index.ml index 893e42e03b8..879b1d11e76 100644 --- a/src/languageServer/declaration_index.ml +++ b/src/languageServer/declaration_index.ml @@ -57,17 +57,17 @@ let lookup_module (path : path) (index : t) : ide_decl list option = - let open Pipeline.ResolveImport in - match parse_import path with - | RelativeImport path -> Index.find_opt path index - | PackageImport (pkg, path) -> + let open Lib.URL in + match parse path with + | Ok (Relative path) -> Index.find_opt path index + | Ok (Package (pkg, path)) -> Lib.Option.bind (List.find_opt (fun (name, _) -> pkg = name) !Mo_config.Flags.package_urls) (fun (_, pkg_path) -> Index.find_opt (Filename.concat pkg_path path) index) - | ActorImport _ -> assert false + | _ -> assert false let empty : t = Index.empty diff --git a/src/languageServer/definition.ml b/src/languageServer/definition.ml index 315b5e3a375..e98ea629528 100644 --- a/src/languageServer/definition.ml +++ b/src/languageServer/definition.ml @@ -49,7 +49,7 @@ let definition_handler |> opt_bind (find_named resolved.ident) |> Lib.Option.map (fun loc -> (resolved.path, loc)) | Ident ident -> - Pipeline.FilePath.relative_to project_root file_path + Lib.FilePath.relative_to project_root file_path |> opt_bind (fun uri -> DI.lookup_module uri index |> opt_bind (find_named ident) diff --git a/src/languageServer/source_file.ml b/src/languageServer/source_file.ml index a25fe2c81e0..bbb7e7e223d 100644 --- a/src/languageServer/source_file.ml +++ b/src/languageServer/source_file.ml @@ -40,15 +40,15 @@ let cursor_target_at_pos try loop (next ()) with _ -> None let is_package_path (path : string) = - let open Pipeline.ResolveImport in - match parse_import path with - | PackageImport _ -> true + let open Lib.URL in + match parse path with + | Ok (Package _) -> true | _ -> false let uri_for_package (path : string) = - let open Pipeline.ResolveImport in - match parse_import path with - | PackageImport (pkg, path) -> + let open Lib.URL in + match parse path with + | Ok (Package (pkg, path)) -> begin match List.find_opt (fun (name, _) -> pkg = name) @@ -64,13 +64,13 @@ let import_relative_to_project_root root module_path dependency = if is_package_path dependency then Some dependency else - match Pipeline.FilePath.relative_to root module_path with + match Lib.FilePath.relative_to root module_path with | None -> None | Some root_to_module -> root_to_module |> Filename.dirname |> Lib.Fun.flip Filename.concat dependency - |> Pipeline.FilePath.normalise + |> Lib.FilePath.normalise |> Lib.Option.some (* Given the source of a module, figure out under what names what diff --git a/src/lib/lib.ml b/src/lib/lib.ml index 853dc5900db..980d91c9b4e 100644 --- a/src/lib/lib.ml +++ b/src/lib/lib.ml @@ -48,13 +48,13 @@ end module CRC = struct - let crc8 (bs : bytes) : int = + let crc8 (bs : string) : int = let inner _ = function | crc when crc land 0x80 <> 0 -> (crc lsl 1) lxor 0x7 | crc -> crc lsl 1 in let outer crc b = List.fold_right inner [0;1;2;3;4;5;6;7] (Char.code b lxor crc) land 0xFF in - Seq.fold_left outer 0 (Bytes.to_seq bs) + Seq.fold_left outer 0 (String.to_seq bs) end module Hex = @@ -65,11 +65,11 @@ struct | c when c >= 'a' && c <= 'f' -> code c - code 'a' + 10 | _ -> assert false - let bytes_of_hex hex : bytes = + let bytes_of_hex hex : string = let open String in let extract i _ = Char.chr (hexdigit (get hex (i * 2)) lsl 4 lor hexdigit (get hex (i * 2 + 1))) in - Bytes.mapi extract (Bytes.create (length hex / 2)) + Bytes.to_string (Bytes.mapi extract (Bytes.create (length hex / 2))) let int_of_hex_byte hex : int = assert (String.length hex = 2); @@ -267,6 +267,13 @@ struct | x::ys -> List.iter (fun y -> f x y) ys; iter_pairs f ys end +module Seq = +struct + let rec for_all p s = match s () with + | Seq.Nil -> true + | Seq.Cons (x, s') -> p x && for_all p s' +end + module List32 = struct let rec make n x = make' n x [] @@ -407,6 +414,106 @@ struct let value p = match !p with Some x -> x | None -> raise Promise end +module FilePath = +struct + let normalise file_path = + let has_trailing_slash = + Option.is_some (String.chop_suffix "/" file_path) in + let has_leading_slash = not (Filename.is_relative file_path) in + let acc = Stack.create () in + String.split file_path '/' + |> Stdlib.List.iter + (function + | "" -> () + | "." -> () + | ".." -> + if Stack.is_empty acc || Stack.top acc = ".." + then Stack.push ".." acc + else ignore (Stack.pop acc) + | segment -> Stack.push segment acc); + let result = Stack.fold (fun x y -> y ^ "/" ^ x) "" acc in + let prefix = if has_leading_slash then "/" else "" in + prefix ^ (if has_trailing_slash + then result + else Option.value (String.chop_suffix "/" result)) + + let relative_to base path = + String.chop_prefix + (normalise (base ^ "/")) + (normalise path) +end + + +module URL = +struct +(* Parsing known URLs from mo: and ic: URLs *) +(* Not really best in lib, but where else (used from pipeline and lowering) *) + +(* + parse "mo:std/list" = Ok (Package ("std", "list")) + parse "mo:std/foo/bar" = Ok (Package ("std", "foo/bar")) + parse "mo:foo/bar" = Ok (Package ("foo", "bar")) + parse "mo:foo" = Ok (Package ("foo", "")) + + parse "ic:DEADBEEF" = Ok (Ic "\DE\AD\BE\EF") + parse "ic:alias" = (not yet supported) + + parse "std/foo" = Ok (Relative "std/foo") + parse "foo" = Ok (Relative "foo") + parse "./foo" = Ok (Relative "foo") + + parse "something:else" = Error … + + TODO: This could be the place to reject things like + ic: mo: http:std/foo + *) + + + (* helper (only to be used on "ic:…" urls) *) + let decode_actor_url url : (string, string) result = + let open Stdlib.String in + let hex = Option.value (String.chop_prefix "ic:" url) in + + if equal hex "" then Error "principal ID must not be empty" else + if uppercase_ascii hex <> hex then Error "principal ID must be uppercase" else + let isHex c = (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') in + if not (Seq.for_all isHex (to_seq hex)) then Error "principal ID must contain uppercase hexadecimal digits" else + if length hex mod 2 = 1 then Error "principal ID must contain an even number of hexadecimal digits" else + let blob, crc = sub hex 0 (length hex - 2), sub hex (length hex - 2) 2 in + let bs = Hex.bytes_of_hex blob in + let checksum = CRC.crc8 bs in + if checksum <> Hex.int_of_hex_byte crc then Error "invald checksum in principal ID, please check for typos" else + Ok bs + + type parsed = + | Package of (string * string) + | Relative of string + | Ic of string + + + let parse (f: string) : (parsed, string) result = + match String.chop_prefix "mo:" f with + | Some suffix -> + begin match Stdlib.String.index_opt suffix '/' with + | None -> Ok (Package (suffix, "")) + | Some i -> + let pkg = Stdlib.String.sub suffix 0 i in + let path = Stdlib.String.sub suffix (i+1) (Stdlib.String.length suffix - (i+1)) in + Ok (Package (pkg, path)) + end + | None -> + match String.chop_prefix "ic:" f with + | Some _suffix -> begin match decode_actor_url f with + | Ok bytes -> Ok (Ic bytes) + | Error err -> Error err + end + | None -> + begin match Stdlib.String.index_opt f ':' with + | Some _ -> Error "Unrecognized URL" + | None -> Ok (Relative (FilePath.normalise f)) + end +end + [@@@warning "-60"] module Test = struct @@ -416,19 +523,117 @@ struct it is a dune library. *) let%test "bytes_of_hex DEADBEEF" = - Hex.bytes_of_hex "DEADBEEF" = Bytes.of_string "\xDE\xAD\xBE\xEF" + Hex.bytes_of_hex "DEADBEEF" = "\xDE\xAD\xBE\xEF" let%test "bytes_of_hex 0000" = - Hex.bytes_of_hex "0000" = Bytes.of_string "\x00\x00" + Hex.bytes_of_hex "0000" = "\x00\x00" let%test "bytes_of_hex empty" = - Hex.bytes_of_hex "" = Bytes.of_string "" + Hex.bytes_of_hex "" = "" let%test "int_of_hex_byte 00" = Hex.int_of_hex_byte "00" = 0 let%test "int_of_hex_byte AB" = Hex.int_of_hex_byte "AB" = 0xAB let%test "int_of_hex_byte FF" = Hex.int_of_hex_byte "FF" = 0xFF (* see https://crccalc.com/ *) - let %test "crc8 DEADBEEF" = CRC.crc8 (Bytes.of_string "\xDE\xAD\xBE\xEF") = 0xCA - let %test "crc8 empty" = CRC.crc8 (Bytes.of_string "") = 0x00 - let %test "crc8 0000" = CRC.crc8 (Bytes.of_string "\x00\x00") = 0x00 + let %test "crc8 DEADBEEF" = CRC.crc8 "\xDE\xAD\xBE\xEF" = 0xCA + let %test "crc8 empty" = CRC.crc8 "" = 0x00 + let %test "crc8 0000" = CRC.crc8 "\x00\x00" = 0x00 + + + (* FilePath tests *) + let normalise_test_case input expected = + let actual = FilePath.normalise input in + Stdlib.String.equal actual expected || + (Printf.printf + "\nExpected: %s\nActual: %s\n" + expected + actual; + false) + + let relative_to_test_case root contained expected = + let actual = FilePath.relative_to root contained in + let show = function + | None -> "None" + | Some s -> "Some " ^ s in + Option.equal Stdlib.String.equal actual expected || + (Printf.printf + "\nExpected: %s\nActual: %s\n" + (show expected) + (show actual); + false) + + let%test "it removes leading current directory" = + normalise_test_case "./ListClient.mo" "ListClient.mo" + + let%test "it removes leading `./` for relative paths" = + normalise_test_case "./lib/foo" "lib/foo" + + let%test "it removes duplicate `//`s" = + normalise_test_case ".//lib/foo" "lib/foo" + + let%test "it preserves trailing slashes" = + normalise_test_case "lib/foo/" "lib/foo/" + + let%test "it drops intermediate references to the `.` directory" = + normalise_test_case "lib/./foo/" "lib/foo/" + + let%test "it applies parent directory traversals" = + normalise_test_case "lib/../foo/" "foo/" + + let%test "it keeps parent directory references at the start of a path" = + normalise_test_case "../foo/lib" "../foo/lib" + + let%test "it keeps multiple parent directory references at the start of a path" = + normalise_test_case "../../foo/lib" "../../foo/lib" + + let%test "it does everything at once" = + normalise_test_case "../foo//.././lib" "../lib" + + let%test "it handles absolute paths" = + normalise_test_case "/foo" "/foo" + + let%test "it handles absolute directory paths" = + normalise_test_case "/foo/./lib/" "/foo/lib/" + + let%test "it makes one absolute path relative to another one" = + relative_to_test_case + "/home/project" + "/home/project/src/main.mo" + (Some "src/main.mo") + + let%test "it's robust in the face of trailing slashes" = + relative_to_test_case + "/home/project/" + "/home/project/src/main.mo" + (Some "src/main.mo") + + let%test "it makes a file path relative to a path" = + relative_to_test_case + "/home/project" + "/home/project/main.mo" + (Some "main.mo") + + let%test "it preserves trailing slashes" = + relative_to_test_case + "/home/project/" + "/home/project/src/" + (Some "src/") + + let%test "it handles directory traversals" = + relative_to_test_case + "/home/project" + "/home/project/src/../lib/" + (Some "lib/") + + let%test "it fails to make disjoint paths relative to one another" = + relative_to_test_case + "/home/project" + "/home/main.mo" + None + + let%test "it handles relative paths" = + relative_to_test_case + "project/src" + "project/src/Main.mo" + (Some "Main.mo") end diff --git a/src/lib/lib.mli b/src/lib/lib.mli index ea065518f36..7398e531a09 100644 --- a/src/lib/lib.mli +++ b/src/lib/lib.mli @@ -140,12 +140,42 @@ end module CRC : sig - val crc8 : bytes -> int + val crc8 : string -> int end module Hex : sig val hexdigit : char -> int - val bytes_of_hex : string -> bytes + val bytes_of_hex : string -> string val int_of_hex_byte : string -> int end + +module FilePath : +sig + (** + * Normalises a file path + *) + val normalise : string -> string + + (** + * Makes one path relative to another path. + * + * Examples: + * + * relative_to "/home/foo" "/home/foo/project" = Some "project" + * relative_to "/home/foo" "/home/foo/project/lib" = Some "project/lib" + * relative_to "/home/foo" "/home/bar/project" = None + * relative_to "foo/bar" "foo/bar/project" = Some "project" + *) + val relative_to : string -> string -> string option +end + +module URL : +sig + type parsed = + | Package of (string * string) + | Relative of string + | Ic of string + + val parse : string -> (parsed, string) result +end diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 37b23300db2..7fa99492710 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -149,10 +149,10 @@ and exp' at note = function | S.Unresolved -> raise (Invalid_argument ("Unresolved import " ^ f)) | S.LibPath fp -> I.VarE (id_of_full_path fp).it | S.IDLPath fp -> - assert (f = "ic:000000000000040054"); - let blob_id = "\x00\x00\x00\x00\x00\x00\x04\x00" in - (* TODO: Properly decode the URL *) - I.(PrimE (ActorOfIdBlob note.note_typ, [blobE blob_id])) + match Lib.URL.parse f with + | Ok (Lib.URL.Ic blob_id) -> + I.(PrimE (ActorOfIdBlob note.note_typ, [blobE blob_id])) + | _ -> raise (Invalid_argument ("Invalid import URL during desugaring")) end | S.PrimE s -> raise (Invalid_argument ("Unapplied prim " ^ s)) diff --git a/src/pipeline/file_path.ml b/src/pipeline/file_path.ml deleted file mode 100644 index 8df0815d9f4..00000000000 --- a/src/pipeline/file_path.ml +++ /dev/null @@ -1,25 +0,0 @@ -let normalise file_path = - let has_trailing_slash = - Lib.Option.is_some (Lib.String.chop_suffix "/" file_path) in - let has_leading_slash = not (Filename.is_relative file_path) in - let acc = Stack.create () in - Lib.String.split file_path '/' - |> List.iter - (function - | "" -> () - | "." -> () - | ".." -> - if Stack.is_empty acc || Stack.top acc = ".." - then Stack.push ".." acc - else ignore (Stack.pop acc) - | segment -> Stack.push segment acc); - let result = Stack.fold (fun x y -> y ^ "/" ^ x) "" acc in - let prefix = if has_leading_slash then "/" else "" in - prefix ^ (if has_trailing_slash - then result - else Lib.Option.value (Lib.String.chop_suffix "/" result)) - -let relative_to base path = - Lib.String.chop_prefix - (normalise (base ^ "/")) - (normalise path) diff --git a/src/pipeline/file_path.mli b/src/pipeline/file_path.mli deleted file mode 100644 index 2cf21b0011f..00000000000 --- a/src/pipeline/file_path.mli +++ /dev/null @@ -1,16 +0,0 @@ -(** - * Normalises a file path - *) -val normalise : string -> string - -(** - * Makes one path relative to another path. - * - * Examples: - * - * relative_to "/home/foo" "/home/foo/project" = Some "project" - * relative_to "/home/foo" "/home/foo/project/lib" = Some "project/lib" - * relative_to "/home/foo" "/home/bar/project" = None - * relative_to "foo/bar" "foo/bar/project" = Some "project" - *) -val relative_to : string -> string -> string option diff --git a/src/pipeline/file_path_test.ml b/src/pipeline/file_path_test.ml deleted file mode 100644 index 348b27b7154..00000000000 --- a/src/pipeline/file_path_test.ml +++ /dev/null @@ -1,95 +0,0 @@ -let normalise_test_case input expected = - let actual = File_path.normalise input in - String.equal actual expected || - (Printf.printf - "\nExpected: %s\nActual: %s\n" - expected - actual; - false) - -let relative_to_test_case root contained expected = - let actual = File_path.relative_to root contained in - let show = function - | None -> "None" - | Some s -> "Some " ^ s in - Lib.Option.equal String.equal actual expected || - (Printf.printf - "\nExpected: %s\nActual: %s\n" - (show expected) - (show actual); - false) - -let%test "it removes leading current directory" = - normalise_test_case "./ListClient.mo" "ListClient.mo" - -let%test "it removes leading `./` for relative paths" = - normalise_test_case "./lib/foo" "lib/foo" - -let%test "it removes duplicate `//`s" = - normalise_test_case ".//lib/foo" "lib/foo" - -let%test "it preserves trailing slashes" = - normalise_test_case "lib/foo/" "lib/foo/" - -let%test "it drops intermediate references to the `.` directory" = - normalise_test_case "lib/./foo/" "lib/foo/" - -let%test "it applies parent directory traversals" = - normalise_test_case "lib/../foo/" "foo/" - -let%test "it keeps parent directory references at the start of a path" = - normalise_test_case "../foo/lib" "../foo/lib" - -let%test "it keeps multiple parent directory references at the start of a path" = - normalise_test_case "../../foo/lib" "../../foo/lib" - -let%test "it does everything at once" = - normalise_test_case "../foo//.././lib" "../lib" - -let%test "it handles absolute paths" = - normalise_test_case "/foo" "/foo" - -let%test "it handles absolute directory paths" = - normalise_test_case "/foo/./lib/" "/foo/lib/" - -let%test "it makes one absolute path relative to another one" = - relative_to_test_case - "/home/project" - "/home/project/src/main.mo" - (Some "src/main.mo") - -let%test "it's robust in the face of trailing slashes" = - relative_to_test_case - "/home/project/" - "/home/project/src/main.mo" - (Some "src/main.mo") - -let%test "it makes a file path relative to a path" = - relative_to_test_case - "/home/project" - "/home/project/main.mo" - (Some "main.mo") - -let%test "it preserves trailing slashes" = - relative_to_test_case - "/home/project/" - "/home/project/src/" - (Some "src/") - -let%test "it handles directory traversals" = - relative_to_test_case - "/home/project" - "/home/project/src/../lib/" - (Some "lib/") - -let%test "it fails to make disjoint paths relative to one another" = - relative_to_test_case - "/home/project" - "/home/main.mo" - None - -let%test "it handles relative paths" = - relative_to_test_case - "project/src" - "project/src/Main.mo" - (Some "Main.mo") diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index 1b87702205e..abb52b82326 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -11,7 +11,6 @@ open Mo_config open Printf module ResolveImport = Resolve_import -module FilePath = File_path type stat_env = Scope.t type dyn_env = Interpret.scope diff --git a/src/pipeline/pipeline.mli b/src/pipeline/pipeline.mli index 0abd85100a7..09134265c45 100644 --- a/src/pipeline/pipeline.mli +++ b/src/pipeline/pipeline.mli @@ -3,7 +3,6 @@ open Mo_config open Mo_types module ResolveImport = Resolve_import -module FilePath = File_path type parse_fn = string -> (Syntax.prog * string) Diag.result val parse_file: parse_fn diff --git a/src/pipeline/resolve_import.ml b/src/pipeline/resolve_import.ml index 7f38d3cd4cd..c95c11e1556 100644 --- a/src/pipeline/resolve_import.ml +++ b/src/pipeline/resolve_import.ml @@ -48,58 +48,27 @@ type package_map = string M.t open Syntax open Source -type parsed_import = - | PackageImport of (string * string) - | RelativeImport of string - | ActorImport of string - -(* decodes `f` according to the following URL patterns: - - parse_import "mo:std/list" = PackageImport ("std", "list") - parse_import "mo:std/foo/bar" = PackageImport ("std", "foo/bar") - parse_import "mo:foo/bar" = PackageImport ("foo", "bar") - parse_import "mo:foo" = PackageImport ("foo", "") - - parse_import "ic:alias" = ActorImport "alias" - parse_import "ic:DEADBEEF" = ActorImport "DEADBEEF" - - parse_import "std/foo" = RelativeImport "std/foo" - parse_import "foo" = RelativeImport "foo" - parse_import "./foo" = RelativeImport "foo" - - TODO: This could be the place to reject things like - ic: mo: http:std/foo - and also to do proper URL decoding. -*) -let parse_import (f: string) : parsed_import = - match Lib.String.chop_prefix "mo:" f with - | Some suffix -> - begin match String.index_opt suffix '/' with - | None -> PackageImport (suffix, "") - | Some i -> - let pkg = String.sub suffix 0 i in - let path = String.sub suffix (i+1) (String.length suffix - (i+1)) in - PackageImport (pkg, path) - end - | None -> - match Lib.String.chop_prefix "ic:" f with - | Some suffix -> ActorImport suffix - | None -> - (* TODO: Check and reject other URL schemas? *) - RelativeImport (File_path.normalise f) - let append_lib_if_needed f = if Sys.file_exists f && Sys.is_directory f then Filename.concat f "lib.mo" else f +let err_unrecognized_url msgs at url msg = + let open Diag in + add_msg msgs { + sev = Error; + at; + cat = "import"; + text = Printf.sprintf "cannot parse import URL %s: %s" url msg + } + let err_file_does_not_exist msgs at full_path = let open Diag in add_msg msgs { sev = Error; at; cat = "import"; - text = Printf.sprintf "File \"%s\" does not exist" full_path + text = Printf.sprintf "file \"%s\" does not exist" full_path } let err_package_not_defined msgs at pkg = @@ -108,7 +77,7 @@ let err_package_not_defined msgs at pkg = sev = Error; at; cat = "import"; - text = Printf.sprintf "Package \"%s\" not defined" pkg + text = Printf.sprintf "package \"%s\" not defined" pkg } let err_package_file_does_not_exist msgs f pname = @@ -117,7 +86,7 @@ let err_package_file_does_not_exist msgs f pname = sev = Error; at = no_region; cat = "package"; - text = Printf.sprintf "File \"%s\" (for package `%s`) does not exist" f pname + text = Printf.sprintf "file \"%s\" (for package `%s`) does not exist" f pname } let err_package_already_defined msgs package_name = @@ -126,7 +95,7 @@ let err_package_already_defined msgs package_name = sev = Error; at = no_region; cat = "--package"; - text = Printf.sprintf "Package name \"%s\" already defined" package_name; + text = Printf.sprintf "package name \"%s\" already defined" package_name; } let add_lib_import msgs imported ri_ref at full_path = @@ -158,19 +127,21 @@ let in_base base f = else Filename.concat base f let resolve_import_string msgs base packages imported (f, ri_ref, at) = - match parse_import f with - | RelativeImport path -> + match Lib.URL.parse f with + | Ok (Lib.URL.Relative path) -> add_lib_import msgs imported ri_ref at (in_base base path) - | PackageImport (pkg,path) -> + | Ok (Lib.URL.Package (pkg,path)) -> begin match M.find_opt pkg packages with | Some pkg_path -> add_lib_import msgs imported ri_ref at (in_base pkg_path path) | None -> err_package_not_defined msgs at pkg end - | ActorImport path -> - let full_path = (* in_base actor_base *) path in + | Ok (Lib.URL.Ic bytes) -> + let full_path = (* in_base actor_base *) bytes in add_idl_import msgs imported ri_ref at full_path + | Error msg -> + err_unrecognized_url msgs at f msg (* Resolve the argument to --package. These can also be relative to base *) let resolve_package_url (msgs:Diag.msg_store) (base:filepath) (pname:string) (f: string) : string option = @@ -178,7 +149,7 @@ let resolve_package_url (msgs:Diag.msg_store) (base:filepath) (pname:string) (f: if Filename.is_relative f then in_base base f else f in - let f = File_path.normalise f in + let f = Lib.FilePath.normalise f in if Sys.file_exists f then Some f else diff --git a/src/pipeline/resolve_import.mli b/src/pipeline/resolve_import.mli index df85e7cded5..9e9adb6c668 100644 --- a/src/pipeline/resolve_import.mli +++ b/src/pipeline/resolve_import.mli @@ -7,14 +7,7 @@ module RIM : Map.S with type key = Syntax.resolved_import type package_urls = (string * string) list -type parsed_import = - | PackageImport of (string * string) - | RelativeImport of string - | ActorImport of string - - type resolved_imports = Syntax.resolved_import Source.phrase list val collect_imports : Syntax.prog -> string list val resolve : package_urls -> Syntax.prog -> filepath -> resolved_imports Diag.result -val parse_import : string -> parsed_import From bc1b0c13f34c1b174c535013a90e12ac7f18c722 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 17 Dec 2019 13:12:05 +0100 Subject: [PATCH 0839/1176] Move URL parsing from lib to pipeline (#1042) and do not parse any URLs in the desugarer, but instead extend `resolved_import` to carry both the full path to the IDL _and_ the blob id of the actor. Maybe import resolution should move out of pipeline into its own library, for cleaner access from `languageServer`. --- src/languageServer/declaration_index.ml | 2 +- src/languageServer/source_file.ml | 4 +- src/lib/lib.ml | 84 +++---------------------- src/lib/lib.mli | 15 ++--- src/lowering/desugar.ml | 6 +- src/mo_def/syntax.ml | 2 +- src/mo_frontend/typing.ml | 2 +- src/pipeline/pipeline.ml | 3 +- src/pipeline/pipeline.mli | 1 + src/pipeline/resolve_import.ml | 16 ++--- src/pipeline/url.ml | 65 +++++++++++++++++++ src/pipeline/url.mli | 6 ++ 12 files changed, 100 insertions(+), 106 deletions(-) create mode 100644 src/pipeline/url.ml create mode 100644 src/pipeline/url.mli diff --git a/src/languageServer/declaration_index.ml b/src/languageServer/declaration_index.ml index 879b1d11e76..a2fda20f216 100644 --- a/src/languageServer/declaration_index.ml +++ b/src/languageServer/declaration_index.ml @@ -57,7 +57,7 @@ let lookup_module (path : path) (index : t) : ide_decl list option = - let open Lib.URL in + let open Pipeline.URL in match parse path with | Ok (Relative path) -> Index.find_opt path index | Ok (Package (pkg, path)) -> diff --git a/src/languageServer/source_file.ml b/src/languageServer/source_file.ml index bbb7e7e223d..3a73e6c7d7e 100644 --- a/src/languageServer/source_file.ml +++ b/src/languageServer/source_file.ml @@ -40,13 +40,13 @@ let cursor_target_at_pos try loop (next ()) with _ -> None let is_package_path (path : string) = - let open Lib.URL in + let open Pipeline.URL in match parse path with | Ok (Package _) -> true | _ -> false let uri_for_package (path : string) = - let open Lib.URL in + let open Pipeline.URL in match parse path with | Ok (Package (pkg, path)) -> begin match diff --git a/src/lib/lib.ml b/src/lib/lib.ml index 980d91c9b4e..7fb7d219aaa 100644 --- a/src/lib/lib.ml +++ b/src/lib/lib.ml @@ -267,13 +267,6 @@ struct | x::ys -> List.iter (fun y -> f x y) ys; iter_pairs f ys end -module Seq = -struct - let rec for_all p s = match s () with - | Seq.Nil -> true - | Seq.Cons (x, s') -> p x && for_all p s' -end - module List32 = struct let rec make n x = make' n x [] @@ -364,6 +357,13 @@ struct end end +module Seq = +struct + let rec for_all p s = match s () with + | Seq.Nil -> true + | Seq.Cons (x, s') -> p x && for_all p s' +end + module Option = struct let equal p x y = @@ -444,76 +444,6 @@ struct end -module URL = -struct -(* Parsing known URLs from mo: and ic: URLs *) -(* Not really best in lib, but where else (used from pipeline and lowering) *) - -(* - parse "mo:std/list" = Ok (Package ("std", "list")) - parse "mo:std/foo/bar" = Ok (Package ("std", "foo/bar")) - parse "mo:foo/bar" = Ok (Package ("foo", "bar")) - parse "mo:foo" = Ok (Package ("foo", "")) - - parse "ic:DEADBEEF" = Ok (Ic "\DE\AD\BE\EF") - parse "ic:alias" = (not yet supported) - - parse "std/foo" = Ok (Relative "std/foo") - parse "foo" = Ok (Relative "foo") - parse "./foo" = Ok (Relative "foo") - - parse "something:else" = Error … - - TODO: This could be the place to reject things like - ic: mo: http:std/foo - *) - - - (* helper (only to be used on "ic:…" urls) *) - let decode_actor_url url : (string, string) result = - let open Stdlib.String in - let hex = Option.value (String.chop_prefix "ic:" url) in - - if equal hex "" then Error "principal ID must not be empty" else - if uppercase_ascii hex <> hex then Error "principal ID must be uppercase" else - let isHex c = (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') in - if not (Seq.for_all isHex (to_seq hex)) then Error "principal ID must contain uppercase hexadecimal digits" else - if length hex mod 2 = 1 then Error "principal ID must contain an even number of hexadecimal digits" else - let blob, crc = sub hex 0 (length hex - 2), sub hex (length hex - 2) 2 in - let bs = Hex.bytes_of_hex blob in - let checksum = CRC.crc8 bs in - if checksum <> Hex.int_of_hex_byte crc then Error "invald checksum in principal ID, please check for typos" else - Ok bs - - type parsed = - | Package of (string * string) - | Relative of string - | Ic of string - - - let parse (f: string) : (parsed, string) result = - match String.chop_prefix "mo:" f with - | Some suffix -> - begin match Stdlib.String.index_opt suffix '/' with - | None -> Ok (Package (suffix, "")) - | Some i -> - let pkg = Stdlib.String.sub suffix 0 i in - let path = Stdlib.String.sub suffix (i+1) (Stdlib.String.length suffix - (i+1)) in - Ok (Package (pkg, path)) - end - | None -> - match String.chop_prefix "ic:" f with - | Some _suffix -> begin match decode_actor_url f with - | Ok bytes -> Ok (Ic bytes) - | Error err -> Error err - end - | None -> - begin match Stdlib.String.index_opt f ':' with - | Some _ -> Error "Unrecognized URL" - | None -> Ok (Relative (FilePath.normalise f)) - end -end - [@@@warning "-60"] module Test = struct diff --git a/src/lib/lib.mli b/src/lib/lib.mli index 7398e531a09..8685e1a072d 100644 --- a/src/lib/lib.mli +++ b/src/lib/lib.mli @@ -74,6 +74,11 @@ sig end end +module Seq : +sig + val for_all : ('a -> bool) -> 'a Seq.t -> bool +end + module Option : sig val equal : ('a -> 'a -> bool) -> 'a option -> 'a option -> bool @@ -169,13 +174,3 @@ sig *) val relative_to : string -> string -> string option end - -module URL : -sig - type parsed = - | Package of (string * string) - | Relative of string - | Ic of string - - val parse : string -> (parsed, string) result -end diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 7fa99492710..444ce4dcfbc 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -148,11 +148,7 @@ and exp' at note = function begin match !ir with | S.Unresolved -> raise (Invalid_argument ("Unresolved import " ^ f)) | S.LibPath fp -> I.VarE (id_of_full_path fp).it - | S.IDLPath fp -> - match Lib.URL.parse f with - | Ok (Lib.URL.Ic blob_id) -> - I.(PrimE (ActorOfIdBlob note.note_typ, [blobE blob_id])) - | _ -> raise (Invalid_argument ("Invalid import URL during desugaring")) + | S.IDLPath (fp, blob_id) -> I.(PrimE (ActorOfIdBlob note.note_typ, [blobE blob_id])) end | S.PrimE s -> raise (Invalid_argument ("Unapplied prim " ^ s)) diff --git a/src/mo_def/syntax.ml b/src/mo_def/syntax.ml index a387272131b..7bc9ca4b276 100644 --- a/src/mo_def/syntax.ml +++ b/src/mo_def/syntax.ml @@ -15,7 +15,7 @@ let empty_typ_note = {note_typ = Type.Pre; note_eff = Type.Triv} type resolved_import = | Unresolved | LibPath of string - | IDLPath of string + | IDLPath of (string * string) (* filepath * bytes *) (* Identifiers *) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 8e85667c51b..39cc955a3bf 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -176,7 +176,7 @@ let check_import env at f ri = match !ri with | Unresolved -> error env at "unresolved import %s" f | LibPath fp -> fp - | IDLPath fp -> fp + | IDLPath (fp, _) -> fp in match T.Env.find_opt full_path env.libs with | Some T.Pre -> diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index abb52b82326..80bfccddee5 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -11,6 +11,7 @@ open Mo_config open Printf module ResolveImport = Resolve_import +module URL = Url type stat_env = Scope.t type dyn_env = Interpret.scope @@ -247,7 +248,7 @@ let chase_imports parsefn senv0 imports : (Syntax.lib list * Scope.scope) Diag.r Diag.return () ))))) end - | Syntax.IDLPath f -> + | Syntax.IDLPath (f, _) -> let sscope = Scope.lib f Type.(Obj (Actor, [])) in senv := Scope.adjoin !senv sscope; Diag.warn ri.Source.at "import" "imported actors assumed to have type actor {}" diff --git a/src/pipeline/pipeline.mli b/src/pipeline/pipeline.mli index 09134265c45..1a5be804581 100644 --- a/src/pipeline/pipeline.mli +++ b/src/pipeline/pipeline.mli @@ -3,6 +3,7 @@ open Mo_config open Mo_types module ResolveImport = Resolve_import +module URL = Url type parse_fn = string -> (Syntax.prog * string) Diag.result val parse_file: parse_fn diff --git a/src/pipeline/resolve_import.ml b/src/pipeline/resolve_import.ml index c95c11e1556..599abce5a0b 100644 --- a/src/pipeline/resolve_import.ml +++ b/src/pipeline/resolve_import.ml @@ -107,9 +107,9 @@ let add_lib_import msgs imported ri_ref at full_path = end else err_file_does_not_exist msgs at full_path -let add_idl_import msgs imported ri_ref at full_path = - ri_ref := IDLPath full_path; - imported := RIM.add (IDLPath full_path) at !imported +let add_idl_import msgs imported ri_ref at full_path bytes = + ri_ref := IDLPath (full_path, bytes); + imported := RIM.add (IDLPath (full_path, bytes)) at !imported (* if Sys.file_exists full_path then begin @@ -127,19 +127,19 @@ let in_base base f = else Filename.concat base f let resolve_import_string msgs base packages imported (f, ri_ref, at) = - match Lib.URL.parse f with - | Ok (Lib.URL.Relative path) -> + match Url.parse f with + | Ok (Url.Relative path) -> add_lib_import msgs imported ri_ref at (in_base base path) - | Ok (Lib.URL.Package (pkg,path)) -> + | Ok (Url.Package (pkg,path)) -> begin match M.find_opt pkg packages with | Some pkg_path -> add_lib_import msgs imported ri_ref at (in_base pkg_path path) | None -> err_package_not_defined msgs at pkg end - | Ok (Lib.URL.Ic bytes) -> + | Ok (Url.Ic bytes) -> let full_path = (* in_base actor_base *) bytes in - add_idl_import msgs imported ri_ref at full_path + add_idl_import msgs imported ri_ref at full_path bytes | Error msg -> err_unrecognized_url msgs at f msg diff --git a/src/pipeline/url.ml b/src/pipeline/url.ml new file mode 100644 index 00000000000..5ff6815e640 --- /dev/null +++ b/src/pipeline/url.ml @@ -0,0 +1,65 @@ +(* Parsing known URLs from mo: and ic: URLs *) + +(* + parse "mo:std/list" = Ok (Package ("std", "list")) + parse "mo:std/foo/bar" = Ok (Package ("std", "foo/bar")) + parse "mo:foo/bar" = Ok (Package ("foo", "bar")) + parse "mo:foo" = Ok (Package ("foo", "")) + + parse "ic:DEADBEEF" = Ok (Ic "\DE\AD\BE\EF") + parse "ic:alias" = (not yet supported) + + parse "std/foo" = Ok (Relative "std/foo") + parse "foo" = Ok (Relative "foo") + parse "./foo" = Ok (Relative "foo") + + parse "something:else" = Error … + + TODO: This could be the place to reject things like + ic: mo: http:std/foo + *) + + +(* helper (only to be used on "ic:…" urls) *) +let decode_actor_url url : (string, string) result = + let open Stdlib.String in + let hex = Lib.Option.value (Lib.String.chop_prefix "ic:" url) in + + if equal hex "" then Error "principal ID must not be empty" else + if uppercase_ascii hex <> hex then Error "principal ID must be uppercase" else + let isHex c = (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') in + if not (Lib.Seq.for_all isHex (to_seq hex)) then Error "principal ID must contain uppercase hexadecimal digits" else + if length hex mod 2 = 1 then Error "principal ID must contain an even number of hexadecimal digits" else + let blob, crc = sub hex 0 (length hex - 2), sub hex (length hex - 2) 2 in + let bs = Lib.Hex.bytes_of_hex blob in + let checksum = Lib.CRC.crc8 bs in + if checksum <> Lib.Hex.int_of_hex_byte crc then Error "invald checksum in principal ID, please check for typos" else + Ok bs + +type parsed = + | Package of (string * string) + | Relative of string + | Ic of string + + +let parse (f: string) : (parsed, string) result = + match Lib.String.chop_prefix "mo:" f with + | Some suffix -> + begin match Stdlib.String.index_opt suffix '/' with + | None -> Ok (Package (suffix, "")) + | Some i -> + let pkg = Stdlib.String.sub suffix 0 i in + let path = Stdlib.String.sub suffix (i+1) (Stdlib.String.length suffix - (i+1)) in + Ok (Package (pkg, path)) + end + | None -> + match Lib.String.chop_prefix "ic:" f with + | Some _suffix -> begin match decode_actor_url f with + | Ok bytes -> Ok (Ic bytes) + | Error err -> Error err + end + | None -> + begin match Stdlib.String.index_opt f ':' with + | Some _ -> Error "Unrecognized URL" + | None -> Ok (Relative (Lib.FilePath.normalise f)) + end diff --git a/src/pipeline/url.mli b/src/pipeline/url.mli new file mode 100644 index 00000000000..d97161a02e1 --- /dev/null +++ b/src/pipeline/url.mli @@ -0,0 +1,6 @@ +type parsed = + | Package of (string * string) + | Relative of string + | Ic of string + +val parse : string -> (parsed, string) result From 61ae539bede6dc15f1dd84cc5ec5a28930f90428 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Tue, 17 Dec 2019 13:50:18 +0100 Subject: [PATCH 0840/1176] Introduce actor references (#1001) * intro actor references * add tests * add rts tests Caveats: - revisit parser - revisit `ignore (actor "foo")` error message - implement interpreters (FIXMEs in place) --- rts/Makefile | 2 +- rts/rts.h | 2 + rts/test_rts.c | 21 +++++ rts/url.c | 78 +++++++++++++++++++ src/codegen/compile.ml | 6 ++ src/ir_def/arrange_ir.ml | 1 + src/ir_def/check_ir.ml | 2 + src/ir_def/ir.ml | 1 + src/ir_interpreter/interpret_ir.ml | 2 + src/lib/lib.ml | 5 +- src/lowering/desugar.ml | 12 +++ src/mo_def/arrange.ml | 27 +++---- src/mo_def/syntax.ml | 1 + src/mo_frontend/definedness.ml | 5 +- src/mo_frontend/effect.ml | 1 + src/mo_frontend/parser.mly | 6 ++ src/mo_frontend/static.ml | 2 +- src/mo_frontend/traversals.ml | 2 +- src/mo_frontend/typing.ml | 9 +++ src/mo_interpreter/interpret.ml | 1 + test/fail/actor-reference-infer.mo | 3 + test/fail/actor-reference.mo | 21 +++++ test/fail/ok/actor-reference-infer.tc.ok | 1 + test/fail/ok/actor-reference-infer.tc.ret.ok | 1 + test/fail/ok/actor-reference.tc.ok | 13 ++++ test/fail/ok/actor-reference.tc.ret.ok | 1 + test/run-drun/actor-reference-return.mo | 14 ++++ test/run-drun/actor-reference.mo | 10 +++ .../ok/actor-reference-return.drun-run.ok | 3 + .../ok/actor-reference-return.ic-stub-run.ok | 8 ++ test/run-drun/ok/actor-reference.comp.ok | 4 + test/run-drun/ok/actor-reference.comp.ret.ok | 1 + .../ok/actor-reference.ic-stub-run.ok | 4 + 33 files changed, 248 insertions(+), 22 deletions(-) create mode 100644 rts/url.c create mode 100644 test/fail/actor-reference-infer.mo create mode 100644 test/fail/actor-reference.mo create mode 100644 test/fail/ok/actor-reference-infer.tc.ok create mode 100644 test/fail/ok/actor-reference-infer.tc.ret.ok create mode 100644 test/fail/ok/actor-reference.tc.ok create mode 100644 test/fail/ok/actor-reference.tc.ret.ok create mode 100644 test/run-drun/actor-reference-return.mo create mode 100644 test/run-drun/actor-reference.mo create mode 100644 test/run-drun/ok/actor-reference-return.drun-run.ok create mode 100644 test/run-drun/ok/actor-reference-return.ic-stub-run.ok create mode 100644 test/run-drun/ok/actor-reference.comp.ok create mode 100644 test/run-drun/ok/actor-reference.comp.ret.ok create mode 100644 test/run-drun/ok/actor-reference.ic-stub-run.ok diff --git a/rts/Makefile b/rts/Makefile index 157edfef025..f07db20ad95 100644 --- a/rts/Makefile +++ b/rts/Makefile @@ -81,7 +81,7 @@ TOMMATH_NATIVE_O=$(TOMMATHFILES:%=_build/native/tommath_%.o) # Our part of the RTS, Wasm and native # -RTSFILES=rts idl bigint buf utf8_valid closure-table text +RTSFILES=rts idl bigint buf utf8_valid closure-table text url _build/wasm/%.o: %.c rts.h buf.h | _build/wasm $(WASM_CLANG) -c $(CLANG_FLAGS) $(WASM_FLAGS) $(TOMMATH_FLAGS) -I$(TOMMATHSRC) --std=c11 $< --output $@ diff --git a/rts/rts.h b/rts/rts.h index 849eeebcf3f..5eef2b8e8d4 100644 --- a/rts/rts.h +++ b/rts/rts.h @@ -89,4 +89,6 @@ as_ptr text_of_ptr_size(const char *buf, size_t n); export __attribute__ ((noreturn)) void idl_trap_with(const char *str1); export __attribute__ ((noreturn)) void rts_trap_with(const char *str1); +export as_ptr blob_of_text(as_ptr); + #endif /* RTS_H */ diff --git a/rts/test_rts.c b/rts/test_rts.c index 96b9276f2bc..2746006c383 100644 --- a/rts/test_rts.c +++ b/rts/test_rts.c @@ -4,6 +4,7 @@ #include #include #include +#include "rts.h" typedef intptr_t as_ptr; @@ -157,5 +158,25 @@ int main () { assert(closure_count() == i, "Closure count wrong\n"); } + /* + * Testing 'IC:' scheme URL decoding + */ + printf("Testing IC: URL...\n"); + + extern as_ptr crc8_decode(as_ptr); + as_ptr blob0 = alloc_blob(7); + char* blob0p = (char*)BLOB_PAYLOAD(blob0); + blob0p[0] = 'I'; + blob0p[1] = 'c'; + blob0p[2] = ':'; + blob0p[3] = blob0p[4] = blob0p[5] = blob0p[6] = '0'; + (void)crc8_decode(blob0); + + const int blob1len = 15; + as_ptr blob1 = alloc_blob(blob1len); + char* blob1p = (char*)BLOB_PAYLOAD(blob1); + memcpy(blob1p, "ic:C0FEFED00D41", blob1len); + (void)crc8_decode(blob1); + return ret; } diff --git a/rts/url.c b/rts/url.c new file mode 100644 index 00000000000..657c4786f60 --- /dev/null +++ b/rts/url.c @@ -0,0 +1,78 @@ +/* +The URLs with conversions and integrity checking. +*/ + +#include "rts.h" + +typedef as_ptr blob_t; // a skewed pointer to a Blob heap object +typedef as_ptr text_t; // a skewed pointer to a Blob (or, later, Concat) heap object +typedef unsigned char uint8_t; + +static void check_all_uppercase_hex(const char* s, const char* const e) { + while (s != e) { + const char c = *s++; + if ((c >= '0' && c <= '9') + || (c >= 'A' && c <= 'F')) continue; + else rts_trap_with("ic_url_decode: Not all uppercase hex digit"); + } +} + +static void check_ci_scheme(const char* s) { + const char c0 = *s++; + const char c1 = *s++; + const char c2 = *s; + if ((c0 == 'i' || c0 == 'I') + && (c1 == 'c' || c1 == 'C') + && c2 == ':') return; + else rts_trap_with("ic_url_decode: Wrong URL scheme (not 'ic:')"); +} + +// assumption: uppercase hex +static uint8_t hex_digit(uint8_t c) { + if (c >= '0' && c <= '9') return c - '0'; + else return c - 'A' + 0xA; +} + +// assumption: uppercase hex +static uint8_t hex_byte(const char* h) { + return hex_digit(h[0]) << 4 | hex_digit(h[1]); +} + +// assumption: uppercase hex, len is even +static uint8_t compute_crc8(const char data[], size_t len) { + uint8_t crc = 0; + for (size_t i = 0; i < len; i += 2) { + crc ^= hex_byte(data + i); + for (size_t j = 0; j < 8; ++j) { + if (crc & 0x80) + crc = (uint8_t)((crc << 1) ^ 0x7); + else + crc <<= 1; + } + } + return crc; +} + +// CRC-8 from IC-URL +export blob_t crc8_decode(text_t t) { + blob_t b0 = blob_of_text(t); + size_t n = BLOB_LEN(b0); + if (n < 3) rts_trap_with("ic_url_decode: Not an URL"); + const char* const s = BLOB_PAYLOAD(b0); + const char* const e = s + n; + check_ci_scheme(s); + const char* hex = s + 3; // skip over "ic:" + size_t hex_len = n - 5; // strip "ic:" and 2 last digits + check_all_uppercase_hex(hex, e); + if (hex_len & 1) rts_trap_with("ic_url_decode: Not an even number of hex digits"); + uint8_t crc = compute_crc8(hex, hex_len); + uint8_t exp = hex_byte(e - 2); + if (crc != exp) { + rts_trap_with("ic_url_decode: CRC-8 mismatch"); + } + as_ptr r = alloc_blob(hex_len / 2); + for (char *bytes = BLOB_PAYLOAD(r); hex_len; hex += 2, hex_len -= 2) { + *bytes++ = (char)hex_byte(hex); + } + return r; +} diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 7fdcb8f4722..107516827e1 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -663,6 +663,7 @@ module RTS = struct E.add_func_import env "rts" "text_singleton" [I32Type] [I32Type]; E.add_func_import env "rts" "text_size" [I32Type] [I32Type]; E.add_func_import env "rts" "text_to_buf" [I32Type; I32Type] []; + E.add_func_import env "rts" "crc8_decode" [I32Type] [I32Type]; () end (* RTS *) @@ -6017,6 +6018,11 @@ and compile_exp (env : E.t) ae exp = (* Coercions for abstract types *) | CastPrim (_,_), [e] -> compile_exp env ae e + + (* CRC-check and strip "ic:" and checksum *) + | BlobOfIcUrl, [_] -> + const_sr SR.Vanilla (E.call_import env "rts" "crc8_decode") + (* Actor ids are blobs in the RTS *) | ActorOfIdBlob _, [e] -> compile_exp env ae e diff --git a/src/ir_def/arrange_ir.ml b/src/ir_def/arrange_ir.ml index 8024140acab..33490b65f39 100644 --- a/src/ir_def/arrange_ir.ml +++ b/src/ir_def/arrange_ir.ml @@ -68,6 +68,7 @@ and prim = function | NumConvPrim (t1, t2) -> "NumConvPrim" $$ [prim_ty t1; prim_ty t2] | CastPrim (t1, t2) -> "CastPrim" $$ [typ t1; typ t2] | ActorOfIdBlob t -> "ActorOfIdBlob" $$ [typ t] + | BlobOfIcUrl -> Atom "BlobOfIcUrl" | OtherPrim s -> Atom s | CPSAwait -> Atom "CPSAwait" | CPSAsync -> Atom "CPSAsync" diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 9aba7596b50..9468a210196 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -394,6 +394,8 @@ let rec check_exp env (exp:Ir.exp) : unit = | CastPrim (t1, t2), [e] -> typ e <: t1; t2 <: t + | BlobOfIcUrl, [e] -> + typ e <: T.text; | ActorOfIdBlob actor_typ, [e] -> typ e <: T.blob; check_typ env actor_typ; diff --git a/src/ir_def/ir.ml b/src/ir_def/ir.ml index 1cce7271e12..fa657c429fa 100644 --- a/src/ir_def/ir.ml +++ b/src/ir_def/ir.ml @@ -116,6 +116,7 @@ and prim = | NumConvPrim of Type.prim * Type.prim | CastPrim of Type.typ * Type.typ (* representationally a noop *) | ActorOfIdBlob of Type.typ + | BlobOfIcUrl (* traps on syntax or checksum failure *) | OtherPrim of string (* Other primitive operation, no custom typing rule *) | CPSAwait | CPSAsync diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index f6b6f5ec685..3a67ecd122c 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -368,6 +368,8 @@ and interpret_exp_mut env exp (k : V.value V.cont) = | CastPrim _, [e] -> interpret_exp env e k | ActorOfIdBlob t, [e] -> trap exp.at "ActorOfIdBlob not implemented" + | BlobOfIcUrl, [e] -> + trap exp.at "BlobOfIcUrl not implemented" (* FIXME: #1001, call Lib.URL.decode_actor_url *) | NumConvPrim (t1, t2), exps -> interpret_exps env exps [] (fun vs -> let arg = match vs with [v] -> v | _ -> V.Tup vs in diff --git a/src/lib/lib.ml b/src/lib/lib.ml index 7fb7d219aaa..4a4c787407a 100644 --- a/src/lib/lib.ml +++ b/src/lib/lib.ml @@ -152,13 +152,13 @@ struct | '\b' -> Bytes.set s' !n '\\'; n := !n + 1; Bytes.set s' !n 'b' | '\t' -> - Bytes.set s' !n '\\'; n := !n + 1; Bytes.set s' !n 't' + Bytes.set s' !n '\\'; n := !n + 1; Bytes.set s' !n 't' | c -> Bytes.set s' !n c end; n := !n + 1 done; Bytes.unsafe_to_string s' - end + end end module List = @@ -566,4 +566,3 @@ struct "project/src/Main.mo" (Some "Main.mo") end - diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 444ce4dcfbc..026803de764 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -57,6 +57,8 @@ and exp e = and exp' at note = function | S.VarE i -> I.VarE i.it + | S.ActorUrlE e -> + I.(PrimE (ActorOfIdBlob note.note_typ, [url e])) | S.LitE l -> I.LitE (lit !l) | S.UnE (ot, o, e) -> I.PrimE (I.UnPrim (!ot, o), [exp e]) @@ -152,6 +154,16 @@ and exp' at note = function end | S.PrimE s -> raise (Invalid_argument ("Unapplied prim " ^ s)) +and url e = + (* We short-cut AnnotE here, so that we get the position of the inner expression *) + match e.it with + | S.AnnotE (e,_) -> url e + | _ -> + let transformed = typed_phrase' (url' e) e in + I.{ transformed with note = { transformed.note with note_typ = T.blob } } + +and url' e at _ _ = I.(PrimE (BlobOfIcUrl, [exp e])) + and lexp e = (* We short-cut AnnotE here, so that we get the position of the inner expression *) match e.it with diff --git a/src/mo_def/arrange.ml b/src/mo_def/arrange.ml index 3e2fcf2ad12..82bc35a460b 100644 --- a/src/mo_def/arrange.ml +++ b/src/mo_def/arrange.ml @@ -11,19 +11,20 @@ and id i = Atom i.it and tag i = Atom ("#" ^ i.it) let rec exp e = match e.it with - | VarE x -> "VarE" $$ [id x] - | LitE l -> "LitE" $$ [lit !l] - | UnE (ot, uo, e) -> "UnE" $$ [operator_type !ot; Arrange_ops.unop uo; exp e] - | BinE (ot, e1, bo, e2) -> "BinE" $$ [operator_type !ot; exp e1; Arrange_ops.binop bo; exp e2] - | RelE (ot, e1, ro, e2) -> "RelE" $$ [operator_type !ot; exp e1; Arrange_ops.relop ro; exp e2] - | ShowE (ot, e) -> "ShowE" $$ [operator_type !ot; exp e] - | TupE es -> "TupE" $$ List.map exp es - | ProjE (e, i) -> "ProjE" $$ [exp e; Atom (string_of_int i)] - | ObjE (s, efs) -> "ObjE" $$ [obj_sort s] @ List.map exp_field efs - | DotE (e, x) -> "DotE" $$ [exp e; id x] - | AssignE (e1, e2) -> "AssignE" $$ [exp e1; exp e2] - | ArrayE (m, es) -> "ArrayE" $$ [mut m] @ List.map exp es - | IdxE (e1, e2) -> "IdxE" $$ [exp e1; exp e2] + | VarE x -> "VarE" $$ [id x] + | LitE l -> "LitE" $$ [lit !l] + | ActorUrlE e -> "ActorUrlE" $$ [exp e] + | UnE (ot, uo, e) -> "UnE" $$ [operator_type !ot; Arrange_ops.unop uo; exp e] + | BinE (ot, e1, bo, e2) -> "BinE" $$ [operator_type !ot; exp e1; Arrange_ops.binop bo; exp e2] + | RelE (ot, e1, ro, e2) -> "RelE" $$ [operator_type !ot; exp e1; Arrange_ops.relop ro; exp e2] + | ShowE (ot, e) -> "ShowE" $$ [operator_type !ot; exp e] + | TupE es -> "TupE" $$ List.map exp es + | ProjE (e, i) -> "ProjE" $$ [exp e; Atom (string_of_int i)] + | ObjE (s, efs) -> "ObjE" $$ [obj_sort s] @ List.map exp_field efs + | DotE (e, x) -> "DotE" $$ [exp e; id x] + | AssignE (e1, e2) -> "AssignE" $$ [exp e1; exp e2] + | ArrayE (m, es) -> "ArrayE" $$ [mut m] @ List.map exp es + | IdxE (e1, e2) -> "IdxE" $$ [exp e1; exp e2] | FuncE (x, sp, tp, p, t, e') -> "FuncE" $$ [ Atom (Type.string_of_typ e.note.note_typ); diff --git a/src/mo_def/syntax.ml b/src/mo_def/syntax.ml index 7bc9ca4b276..1e4478cffb8 100644 --- a/src/mo_def/syntax.ml +++ b/src/mo_def/syntax.ml @@ -121,6 +121,7 @@ and exp' = | PrimE of string (* primitive *) | VarE of id (* variable *) | LitE of lit ref (* literal *) + | ActorUrlE of exp (* actor reference *) | UnE of op_typ * unop * exp (* unary operator *) | BinE of op_typ * exp * binop * exp (* binary operator *) | RelE of op_typ * exp * relop * exp (* relational operator *) diff --git a/src/mo_frontend/definedness.ml b/src/mo_frontend/definedness.ml index 25078e40e02..6a087762b2b 100644 --- a/src/mo_frontend/definedness.ml +++ b/src/mo_frontend/definedness.ml @@ -93,9 +93,8 @@ let rec exp msgs e : f = match e.it with | Type.Shared (_, p1) -> delayify ((exp msgs e /// pat msgs p) /// pat msgs p1)) (* The rest remaining cases just collect the uses of subexpressions: *) - | LitE l -> M.empty - | PrimE _ -> M.empty - | ImportE _ -> M.empty + | LitE _ | ActorUrlE _ + | PrimE _ | ImportE _ -> M.empty | UnE (_, uo, e) -> exp msgs e | BinE (_, e1, bo, e2)-> exps msgs [e1; e2] | RelE (_, e1, ro, e2)-> exps msgs [e1; e2] diff --git a/src/mo_frontend/effect.ml b/src/mo_frontend/effect.ml index 5f89c72e0fd..710605a8a7f 100644 --- a/src/mo_frontend/effect.ml +++ b/src/mo_frontend/effect.ml @@ -32,6 +32,7 @@ let rec infer_effect_exp (exp:Syntax.exp) : T.eff = | PrimE _ | VarE _ | LitE _ + | ActorUrlE _ | ImportE _ | FuncE _ -> T.Triv diff --git a/src/mo_frontend/parser.mly b/src/mo_frontend/parser.mly index b371682ad06..621999e29e7 100644 --- a/src/mo_frontend/parser.mly +++ b/src/mo_frontend/parser.mly @@ -361,6 +361,10 @@ bl : { fun ds -> BlockE(ds) } ob : { fun ds -> ObjE(Type.Object @@ no_region, List.map (fun d -> {dec = d; vis = Public @@ d.at} @@ d.at) ds) } +text_like : + | t=TEXT { LitE (ref (TextLit t)) @? at $sloc } + | LPAR e=exp(bl) RPAR { e } + exp_block : | LCURLY ds=seplist(dec, semicolon) RCURLY { BlockE(ds) @? at $sloc } @@ -414,6 +418,8 @@ exp_un(B) : } | op=unassign e=exp_un(ob) { assign_op e (fun e' -> UnE(ref Type.Pre, op, e') @? at $sloc) (at $sloc) } + | ACTOR e=text_like + { ActorUrlE e @? at $sloc } | NOT e=exp_un(ob) { NotE e @? at $sloc } | DEBUG_SHOW e=exp_un(ob) diff --git a/src/mo_frontend/static.ml b/src/mo_frontend/static.ml index bd026dca468..c5553cfe8a4 100644 --- a/src/mo_frontend/static.ml +++ b/src/mo_frontend/static.ml @@ -35,7 +35,7 @@ let pat_err m at = let rec exp m e = match e.it with (* Plain values *) - | (PrimE _ | LitE _ | FuncE _) -> () + | (PrimE _ | LitE _ | ActorUrlE _ | FuncE _) -> () | (TagE (_, exp1) | OptE exp1) -> exp m exp1 | (TupE es | ArrayE (_, es)) -> List.iter (exp m) es | ObjE (_, efs) -> fields m efs diff --git a/src/mo_frontend/traversals.ml b/src/mo_frontend/traversals.ml index 4193a08e7be..825b213e6d4 100644 --- a/src/mo_frontend/traversals.ml +++ b/src/mo_frontend/traversals.ml @@ -3,7 +3,7 @@ open Syntax open Source let rec over_exp (f : exp -> exp) (exp : exp) : exp = match exp.it with - | ImportE _ | PrimE _ | VarE _ | LitE _ -> f exp + | ImportE _ | PrimE _ | VarE _ | LitE _ | ActorUrlE _ -> f exp | UnE (x, y, exp1) -> f { exp with it=UnE (x, y, over_exp f exp1) } | ShowE (x, exp1) -> f { exp with it=ShowE (x, over_exp f exp1) } | ProjE (exp1, x) -> f { exp with it=ProjE (over_exp f exp1, x) } diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 39cc955a3bf..17b2b659a13 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -602,6 +602,9 @@ and infer_exp'' env exp : T.typ = ) | LitE lit -> T.Prim (infer_lit env lit exp.at) + | ActorUrlE exp' -> + if not env.pre then check_exp env T.text exp'; + error env exp.at "no type can be inferred for actor reference" | UnE (ot, op, exp1) -> let t1 = infer_exp_promote env exp1 in let t = Operator.type_unop op t1 in @@ -987,6 +990,12 @@ and check_exp' env0 t exp : T.typ = | LitE lit, _ -> check_lit env t lit exp.at; t + | ActorUrlE exp', t' -> + check_exp env T.text exp'; + begin match T.normalize t' with + | T.(Obj (Actor, _)) -> t' + | _ -> error env exp.at "actor reference must have an actor type" + end | UnE (ot, op, exp1), _ when Operator.has_unop op t -> ot := t; check_exp env t exp1; diff --git a/src/mo_interpreter/interpret.ml b/src/mo_interpreter/interpret.ml index c6fad813ef7..6b1c6dbd7ce 100644 --- a/src/mo_interpreter/interpret.ml +++ b/src/mo_interpreter/interpret.ml @@ -394,6 +394,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = ) | LitE lit -> k (interpret_lit env lit) + | ActorUrlE url -> interpret_exp env url (fun v1 -> assert false (* FIXME: #1001, call Lib.URL.decode_actor_url *)) | UnE (ot, op, exp1) -> interpret_exp env exp1 (fun v1 -> diff --git a/test/fail/actor-reference-infer.mo b/test/fail/actor-reference-infer.mo new file mode 100644 index 00000000000..f0862c77450 --- /dev/null +++ b/test/fail/actor-reference-infer.mo @@ -0,0 +1,3 @@ +// actor references + +let _ = actor "ic:C0FEFED00D41"; // cannot infer diff --git a/test/fail/actor-reference.mo b/test/fail/actor-reference.mo new file mode 100644 index 00000000000..e3fdf160f81 --- /dev/null +++ b/test/fail/actor-reference.mo @@ -0,0 +1,21 @@ +// actor references + +ignore (actor ""); // missing scheme + +ignore (actor "CI"); // missing colon + +ignore (actor "https://cern.ch"); // wrong scheme + +ignore (actor "ic:"); // empty principal + +ignore (actor "ic:c0fefed00d41"); // lowercase not allowed + +ignore (actor "ic:ABCDEFGH"); // not hex + +ignore (actor "ic:C0FEFED00DE"); // not even number of digits + +ignore (actor "ic:C0FEFED00D42"); // does not validate + +ignore (actor "IC:C0FEFED00D41" : ()); // must be actor type + +ignore (actor (45)); // argument must be text type diff --git a/test/fail/ok/actor-reference-infer.tc.ok b/test/fail/ok/actor-reference-infer.tc.ok new file mode 100644 index 00000000000..9123b8722dd --- /dev/null +++ b/test/fail/ok/actor-reference-infer.tc.ok @@ -0,0 +1 @@ +actor-reference-infer.mo:3.9-3.32: type error, no type can be inferred for actor reference diff --git a/test/fail/ok/actor-reference-infer.tc.ret.ok b/test/fail/ok/actor-reference-infer.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/actor-reference-infer.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/actor-reference.tc.ok b/test/fail/ok/actor-reference.tc.ok new file mode 100644 index 00000000000..dd5c835aaf4 --- /dev/null +++ b/test/fail/ok/actor-reference.tc.ok @@ -0,0 +1,13 @@ +actor-reference.mo:3.9-3.17: type error, actor reference must have an actor type +actor-reference.mo:5.9-5.19: type error, actor reference must have an actor type +actor-reference.mo:7.9-7.32: type error, actor reference must have an actor type +actor-reference.mo:9.9-9.20: type error, actor reference must have an actor type +actor-reference.mo:11.9-11.32: type error, actor reference must have an actor type +actor-reference.mo:13.9-13.28: type error, actor reference must have an actor type +actor-reference.mo:15.9-15.31: type error, actor reference must have an actor type +actor-reference.mo:17.9-17.32: type error, actor reference must have an actor type +actor-reference.mo:19.9-19.32: type error, actor reference must have an actor type +actor-reference.mo:21.16-21.18: type error, literal of type + Nat +does not have expected type + Text diff --git a/test/fail/ok/actor-reference.tc.ret.ok b/test/fail/ok/actor-reference.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/actor-reference.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-drun/actor-reference-return.mo b/test/run-drun/actor-reference-return.mo new file mode 100644 index 00000000000..9a334ebc297 --- /dev/null +++ b/test/run-drun/actor-reference-return.mo @@ -0,0 +1,14 @@ +// returning an actor reference + +actor { + public query func foo() : async actor {} { + actor "ic:C0FEFED00D41"; + }; + + public query func bar() : async actor {} { + actor ("ic:C0FEFED00D" # "CAFEBABEDEADBEEF84"); + } +} + +//CALL query foo 0x4449444c0000 +//CALL query bar 0x4449444c0000 diff --git a/test/run-drun/actor-reference.mo b/test/run-drun/actor-reference.mo new file mode 100644 index 00000000000..51a83ffac5a --- /dev/null +++ b/test/run-drun/actor-reference.mo @@ -0,0 +1,10 @@ +// actor references + +actor { + public func quux() : async Nat { + let orange = actor "IC:C0FEFED00D41" : actor { fubar(n : Nat) : async Nat }; + let n = await orange.fubar(45); + let tangerine = actor ("ic:C0FEFE" # "D00D41") : actor { fubar(n : Nat) : async Nat }; + let m = await tangerine.fubar(45) + } +} diff --git a/test/run-drun/ok/actor-reference-return.drun-run.ok b/test/run-drun/ok/actor-reference-return.drun-run.ok new file mode 100644 index 00000000000..c18e4d259db --- /dev/null +++ b/test/run-drun/ok/actor-reference-return.drun-run.ok @@ -0,0 +1,3 @@ +ingress(0) System +Ok: Payload: 0x4449444c01690001000105c0fefed00d +Ok: Payload: 0x4449444c0169000100010dc0fefed00dcafebabedeadbeef diff --git a/test/run-drun/ok/actor-reference-return.ic-stub-run.ok b/test/run-drun/ok/actor-reference-return.ic-stub-run.ok new file mode 100644 index 00000000000..4193215d040 --- /dev/null +++ b/test/run-drun/ok/actor-reference-return.ic-stub-run.ok @@ -0,0 +1,8 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ query foo(0x4449444c0000) +← completed: 0x4449444c01690001000105c0fefed00d +→ query bar(0x4449444c0000) +← completed: 0x4449444c0169000100010dc0fefed00dcafebabedeadbeef diff --git a/test/run-drun/ok/actor-reference.comp.ok b/test/run-drun/ok/actor-reference.comp.ok new file mode 100644 index 00000000000..b7925fb3193 --- /dev/null +++ b/test/run-drun/ok/actor-reference.comp.ok @@ -0,0 +1,4 @@ +actor-reference.mo:6.19-6.31: type error, calling a shared function not yet supported + (This is a limitation of the current version.) +actor-reference.mo:8.19-8.34: type error, calling a shared function not yet supported + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/actor-reference.comp.ret.ok b/test/run-drun/ok/actor-reference.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/actor-reference.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-drun/ok/actor-reference.ic-stub-run.ok b/test/run-drun/ok/actor-reference.ic-stub-run.ok new file mode 100644 index 00000000000..54225bc8555 --- /dev/null +++ b/test/run-drun/ok/actor-reference.ic-stub-run.ok @@ -0,0 +1,4 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed From b285da9c0c2095c2a5db938d574b92f19f955475 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 17 Dec 2019 15:03:15 +0100 Subject: [PATCH 0841/1176] Enable inter-canister calls on ICMode (#1041) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Enable inter-canister calls on ICMode _without_ also enabling first-class `async` (which would be #958, but requires a decision if we want feature first or safe first). We could in theory allow `ignore async …` and `await async …` already (as these are safe). But surely #942 lands soon :-) See `test/run-drun/ok/hello-world-async.drun-run.ok` for the effect of `drun` aborting earlier than we want. * Update test suite --- src/mo_frontend/typing.ml | 1 - test/run-drun/ok/actor-reference.comp.ok | 4 - test/run-drun/ok/actor-reference.comp.ret.ok | 1 - test/run-drun/ok/actor-reference.drun-run.ok | 1 + test/run-drun/ok/async-calls1.comp.ok | 2 - test/run-drun/ok/async-calls1.comp.ret.ok | 1 - test/run-drun/ok/async-calls1.drun-run.ok | 2 + test/run-drun/ok/async-calls2.comp.ok | 4 - test/run-drun/ok/async-calls2.comp.ret.ok | 1 - test/run-drun/ok/async-calls2.drun-run.ok | 2 + test/run-drun/ok/async-calls3.comp.ok | 6 -- test/run-drun/ok/async-calls3.comp.ret.ok | 1 - test/run-drun/ok/async-calls3.drun-run.ok | 2 + test/run-drun/ok/closure-params.comp.ok | 22 ----- test/run-drun/ok/closure-params.comp.ret.ok | 1 - test/run-drun/ok/closure-params.drun-run.ok | 2 + test/run-drun/ok/counter2.comp.ok | 10 --- test/run-drun/ok/counter2.comp.ret.ok | 1 - test/run-drun/ok/counter2.drun-run.ok | 2 + test/run-drun/ok/create-then-trap.comp.ok | 2 - test/run-drun/ok/data-params.comp.ok | 76 ------------------ test/run-drun/ok/data-params.comp.ret.ok | 1 - test/run-drun/ok/data-params.drun-run.ok | 2 + test/run-drun/ok/flatten-awaitables.comp.ok | 80 ------------------- .../ok/flatten-awaitables.comp.ret.ok | 1 - .../ok/flatten-awaitables.drun-run.ok | 3 + test/run-drun/ok/free-callbacks.comp.ok | 6 -- test/run-drun/ok/free-callbacks.comp.ret.ok | 1 - test/run-drun/ok/free-callbacks.drun-run.ok | 2 + test/run-drun/ok/hello-world-async.comp.ok | 2 - .../run-drun/ok/hello-world-async.comp.ret.ok | 1 - .../run-drun/ok/hello-world-async.drun-run.ok | 3 + test/run-drun/ok/hello-world-await.comp.ok | 2 - .../run-drun/ok/hello-world-await.comp.ret.ok | 1 - .../run-drun/ok/hello-world-await.drun-run.ok | 2 + test/run-drun/ok/ic-calls.comp.ok | 6 -- test/run-drun/ok/ic-calls.comp.ret.ok | 1 - test/run-drun/ok/ic-calls.drun-run.ok | 2 + test/run-drun/ok/issue-894.comp.ok | 2 - test/run-drun/ok/local-throw.comp.ok | 4 - test/run-drun/ok/local-throw.comp.ret.ok | 1 - test/run-drun/ok/local-throw.drun-run.ok | 2 + test/run-drun/ok/oneway-throw.comp.ok | 4 - test/run-drun/ok/oneway-throw.comp.ret.ok | 1 - test/run-drun/ok/oneway-throw.drun-run.ok | 3 + test/run-drun/ok/oneway.comp.ok | 8 -- test/run-drun/ok/oneway.comp.ret.ok | 1 - test/run-drun/ok/oneway.drun-run.ok | 7 ++ test/run-drun/ok/pass-references.comp.ok | 10 --- test/run-drun/ok/query2.comp.ok | 18 ----- test/run-drun/ok/query2.comp.ret.ok | 1 - test/run-drun/ok/query2.drun-run.ok | 2 + test/run-drun/ok/shared-object.comp.ok | 2 - test/run-drun/ok/shared-object.comp.ret.ok | 1 - test/run-drun/ok/shared-object.drun-run.ok | 2 + test/run-drun/ok/throw.comp.ok | 4 - test/run-drun/ok/transpose.comp.ok | 2 - test/run-drun/ok/transpose.comp.ret.ok | 1 - test/run-drun/ok/transpose.drun-run.ok | 2 + test/run-drun/ok/unsupported.comp.ok | 2 - 60 files changed, 43 insertions(+), 297 deletions(-) delete mode 100644 test/run-drun/ok/actor-reference.comp.ok delete mode 100644 test/run-drun/ok/actor-reference.comp.ret.ok create mode 100644 test/run-drun/ok/actor-reference.drun-run.ok delete mode 100644 test/run-drun/ok/async-calls1.comp.ok delete mode 100644 test/run-drun/ok/async-calls1.comp.ret.ok create mode 100644 test/run-drun/ok/async-calls1.drun-run.ok delete mode 100644 test/run-drun/ok/async-calls2.comp.ok delete mode 100644 test/run-drun/ok/async-calls2.comp.ret.ok create mode 100644 test/run-drun/ok/async-calls2.drun-run.ok delete mode 100644 test/run-drun/ok/async-calls3.comp.ok delete mode 100644 test/run-drun/ok/async-calls3.comp.ret.ok create mode 100644 test/run-drun/ok/async-calls3.drun-run.ok delete mode 100644 test/run-drun/ok/closure-params.comp.ok delete mode 100644 test/run-drun/ok/closure-params.comp.ret.ok create mode 100644 test/run-drun/ok/closure-params.drun-run.ok delete mode 100644 test/run-drun/ok/counter2.comp.ok delete mode 100644 test/run-drun/ok/counter2.comp.ret.ok create mode 100644 test/run-drun/ok/counter2.drun-run.ok delete mode 100644 test/run-drun/ok/data-params.comp.ok delete mode 100644 test/run-drun/ok/data-params.comp.ret.ok create mode 100644 test/run-drun/ok/data-params.drun-run.ok delete mode 100644 test/run-drun/ok/flatten-awaitables.comp.ok delete mode 100644 test/run-drun/ok/flatten-awaitables.comp.ret.ok create mode 100644 test/run-drun/ok/flatten-awaitables.drun-run.ok delete mode 100644 test/run-drun/ok/free-callbacks.comp.ok delete mode 100644 test/run-drun/ok/free-callbacks.comp.ret.ok create mode 100644 test/run-drun/ok/free-callbacks.drun-run.ok delete mode 100644 test/run-drun/ok/hello-world-async.comp.ok delete mode 100644 test/run-drun/ok/hello-world-async.comp.ret.ok create mode 100644 test/run-drun/ok/hello-world-async.drun-run.ok delete mode 100644 test/run-drun/ok/hello-world-await.comp.ok delete mode 100644 test/run-drun/ok/hello-world-await.comp.ret.ok create mode 100644 test/run-drun/ok/hello-world-await.drun-run.ok delete mode 100644 test/run-drun/ok/ic-calls.comp.ok delete mode 100644 test/run-drun/ok/ic-calls.comp.ret.ok create mode 100644 test/run-drun/ok/ic-calls.drun-run.ok delete mode 100644 test/run-drun/ok/local-throw.comp.ok delete mode 100644 test/run-drun/ok/local-throw.comp.ret.ok create mode 100644 test/run-drun/ok/local-throw.drun-run.ok delete mode 100644 test/run-drun/ok/oneway-throw.comp.ok delete mode 100644 test/run-drun/ok/oneway-throw.comp.ret.ok create mode 100644 test/run-drun/ok/oneway-throw.drun-run.ok delete mode 100644 test/run-drun/ok/oneway.comp.ok delete mode 100644 test/run-drun/ok/oneway.comp.ret.ok create mode 100644 test/run-drun/ok/oneway.drun-run.ok delete mode 100644 test/run-drun/ok/query2.comp.ok delete mode 100644 test/run-drun/ok/query2.comp.ret.ok create mode 100644 test/run-drun/ok/query2.drun-run.ok delete mode 100644 test/run-drun/ok/shared-object.comp.ok delete mode 100644 test/run-drun/ok/shared-object.comp.ret.ok create mode 100644 test/run-drun/ok/shared-object.drun-run.ok delete mode 100644 test/run-drun/ok/transpose.comp.ok delete mode 100644 test/run-drun/ok/transpose.comp.ret.ok create mode 100644 test/run-drun/ok/transpose.drun-run.ok diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 17b2b659a13..55eace31193 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -795,7 +795,6 @@ and infer_exp'' env exp : T.typ = if T.is_async t_ret && not (in_await env) then error_in [Flags.ICMode] env exp2.at "shared, async function must be called within an await expression"; - error_in [Flags.ICMode] env exp1.at "calling a shared function not yet supported"; if not (T.concrete t_arg) then error env exp1.at "shared function argument contains abstract type\n %s" diff --git a/test/run-drun/ok/actor-reference.comp.ok b/test/run-drun/ok/actor-reference.comp.ok deleted file mode 100644 index b7925fb3193..00000000000 --- a/test/run-drun/ok/actor-reference.comp.ok +++ /dev/null @@ -1,4 +0,0 @@ -actor-reference.mo:6.19-6.31: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -actor-reference.mo:8.19-8.34: type error, calling a shared function not yet supported - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/actor-reference.comp.ret.ok b/test/run-drun/ok/actor-reference.comp.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/actor-reference.comp.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/actor-reference.drun-run.ok b/test/run-drun/ok/actor-reference.drun-run.ok new file mode 100644 index 00000000000..43d7af40394 --- /dev/null +++ b/test/run-drun/ok/actor-reference.drun-run.ok @@ -0,0 +1 @@ +ingress(0) System diff --git a/test/run-drun/ok/async-calls1.comp.ok b/test/run-drun/ok/async-calls1.comp.ok deleted file mode 100644 index f1562045834..00000000000 --- a/test/run-drun/ok/async-calls1.comp.ok +++ /dev/null @@ -1,2 +0,0 @@ -async-calls1.mo:10.43-10.47: type error, calling a shared function not yet supported - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/async-calls1.comp.ret.ok b/test/run-drun/ok/async-calls1.comp.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/async-calls1.comp.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/async-calls1.drun-run.ok b/test/run-drun/ok/async-calls1.drun-run.ok new file mode 100644 index 00000000000..91c74b55809 --- /dev/null +++ b/test/run-drun/ok/async-calls1.drun-run.ok @@ -0,0 +1,2 @@ +ingress(0) System +ingress(1) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/async-calls2.comp.ok b/test/run-drun/ok/async-calls2.comp.ok deleted file mode 100644 index 6d2e7554b87..00000000000 --- a/test/run-drun/ok/async-calls2.comp.ok +++ /dev/null @@ -1,4 +0,0 @@ -async-calls2.mo:12.43-12.47: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -async-calls2.mo:12.72-12.79: type error, calling a shared function not yet supported - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/async-calls2.comp.ret.ok b/test/run-drun/ok/async-calls2.comp.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/async-calls2.comp.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/async-calls2.drun-run.ok b/test/run-drun/ok/async-calls2.drun-run.ok new file mode 100644 index 00000000000..91c74b55809 --- /dev/null +++ b/test/run-drun/ok/async-calls2.drun-run.ok @@ -0,0 +1,2 @@ +ingress(0) System +ingress(1) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/async-calls3.comp.ok b/test/run-drun/ok/async-calls3.comp.ok deleted file mode 100644 index cf63d7526aa..00000000000 --- a/test/run-drun/ok/async-calls3.comp.ok +++ /dev/null @@ -1,6 +0,0 @@ -async-calls3.mo:10.35-10.39: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -async-calls3.mo:10.69-10.76: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -async-calls3.mo:16.5-16.9: type error, calling a shared function not yet supported - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/async-calls3.comp.ret.ok b/test/run-drun/ok/async-calls3.comp.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/async-calls3.comp.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/async-calls3.drun-run.ok b/test/run-drun/ok/async-calls3.drun-run.ok new file mode 100644 index 00000000000..91c74b55809 --- /dev/null +++ b/test/run-drun/ok/async-calls3.drun-run.ok @@ -0,0 +1,2 @@ +ingress(0) System +ingress(1) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/closure-params.comp.ok b/test/run-drun/ok/closure-params.comp.ok deleted file mode 100644 index 791ed4ed180..00000000000 --- a/test/run-drun/ok/closure-params.comp.ok +++ /dev/null @@ -1,22 +0,0 @@ -closure-params.mo:8.5-8.6: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -closure-params.mo:14.5-14.9: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -closure-params.mo:15.5-15.16: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -closure-params.mo:16.5-16.9: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -closure-params.mo:17.5-17.16: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -closure-params.mo:18.5-18.9: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -closure-params.mo:19.5-19.16: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -closure-params.mo:20.5-20.9: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -closure-params.mo:21.5-21.16: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -closure-params.mo:22.5-22.9: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -closure-params.mo:23.5-23.16: type error, calling a shared function not yet supported - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/closure-params.comp.ret.ok b/test/run-drun/ok/closure-params.comp.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/closure-params.comp.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/closure-params.drun-run.ok b/test/run-drun/ok/closure-params.drun-run.ok new file mode 100644 index 00000000000..91c74b55809 --- /dev/null +++ b/test/run-drun/ok/closure-params.drun-run.ok @@ -0,0 +1,2 @@ +ingress(0) System +ingress(1) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/counter2.comp.ok b/test/run-drun/ok/counter2.comp.ok deleted file mode 100644 index 5e48f60d71f..00000000000 --- a/test/run-drun/ok/counter2.comp.ok +++ /dev/null @@ -1,10 +0,0 @@ -counter2.mo:12.5-12.10: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -counter2.mo:13.5-13.10: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -counter2.mo:14.5-14.10: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -counter2.mo:15.5-15.19: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -counter2.mo:19.7-19.12: type error, calling a shared function not yet supported - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/counter2.comp.ret.ok b/test/run-drun/ok/counter2.comp.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/counter2.comp.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/counter2.drun-run.ok b/test/run-drun/ok/counter2.drun-run.ok new file mode 100644 index 00000000000..91c74b55809 --- /dev/null +++ b/test/run-drun/ok/counter2.drun-run.ok @@ -0,0 +1,2 @@ +ingress(0) System +ingress(1) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/create-then-trap.comp.ok b/test/run-drun/ok/create-then-trap.comp.ok index 06f08486cd5..50b82c8fb73 100644 --- a/test/run-drun/ok/create-then-trap.comp.ok +++ b/test/run-drun/ok/create-then-trap.comp.ok @@ -1,4 +1,2 @@ create-then-trap.mo:3.5-7.6: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program (This is a limitation of the current version.) -create-then-trap.mo:8.5-8.10: type error, calling a shared function not yet supported - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/data-params.comp.ok b/test/run-drun/ok/data-params.comp.ok deleted file mode 100644 index fcde506cb9a..00000000000 --- a/test/run-drun/ok/data-params.comp.ok +++ /dev/null @@ -1,76 +0,0 @@ -data-params.mo:76.5-76.11: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -data-params.mo:77.5-77.11: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -data-params.mo:78.5-78.11: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -data-params.mo:79.5-79.11: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -data-params.mo:80.5-80.11: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -data-params.mo:81.5-81.11: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -data-params.mo:82.5-82.12: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -data-params.mo:83.5-83.12: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -data-params.mo:84.5-84.16: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -data-params.mo:85.5-85.15: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -data-params.mo:86.5-86.13: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -data-params.mo:87.5-87.13: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -data-params.mo:88.5-88.16: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -data-params.mo:89.5-89.16: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -data-params.mo:90.5-90.17: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -data-params.mo:91.5-91.17: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -data-params.mo:92.5-92.19: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -data-params.mo:93.5-93.19: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -data-params.mo:94.5-94.19: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -data-params.mo:95.5-95.22: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -data-params.mo:96.5-96.11: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -data-params.mo:97.5-97.11: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -data-params.mo:98.5-98.11: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -data-params.mo:99.5-99.15: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -data-params.mo:100.5-100.15: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -data-params.mo:101.5-101.14: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -data-params.mo:102.5-102.14: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -data-params.mo:103.5-103.14: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -data-params.mo:104.5-104.11: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -data-params.mo:105.5-105.11: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -data-params.mo:106.5-106.11: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -data-params.mo:107.5-107.11: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -data-params.mo:108.5-108.11: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -data-params.mo:109.5-109.11: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -data-params.mo:110.5-110.11: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -data-params.mo:111.5-111.11: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -data-params.mo:112.5-112.11: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -data-params.mo:113.5-113.11: type error, calling a shared function not yet supported - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/data-params.comp.ret.ok b/test/run-drun/ok/data-params.comp.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/data-params.comp.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/data-params.drun-run.ok b/test/run-drun/ok/data-params.drun-run.ok new file mode 100644 index 00000000000..91c74b55809 --- /dev/null +++ b/test/run-drun/ok/data-params.drun-run.ok @@ -0,0 +1,2 @@ +ingress(0) System +ingress(1) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/flatten-awaitables.comp.ok b/test/run-drun/ok/flatten-awaitables.comp.ok deleted file mode 100644 index 454b23a70f0..00000000000 --- a/test/run-drun/ok/flatten-awaitables.comp.ok +++ /dev/null @@ -1,80 +0,0 @@ -flatten-awaitables.mo:16.16-16.18: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -flatten-awaitables.mo:18.16-18.18: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -flatten-awaitables.mo:20.16-20.18: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -flatten-awaitables.mo:22.16-22.18: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -flatten-awaitables.mo:25.16-25.18: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -flatten-awaitables.mo:27.16-27.18: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -flatten-awaitables.mo:29.16-29.18: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -flatten-awaitables.mo:31.16-31.18: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -flatten-awaitables.mo:37.20-37.24: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -flatten-awaitables.mo:39.19-39.23: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -flatten-awaitables.mo:41.26-41.30: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -flatten-awaitables.mo:43.34-43.38: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -flatten-awaitables.mo:46.20-46.24: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -flatten-awaitables.mo:48.19-48.23: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -flatten-awaitables.mo:50.26-50.30: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -flatten-awaitables.mo:52.34-52.38: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -flatten-awaitables.mo:60.20-60.24: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -flatten-awaitables.mo:62.19-62.23: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -flatten-awaitables.mo:64.26-64.30: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -flatten-awaitables.mo:66.34-66.38: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -flatten-awaitables.mo:69.20-69.24: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -flatten-awaitables.mo:71.19-71.23: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -flatten-awaitables.mo:73.26-73.30: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -flatten-awaitables.mo:75.34-75.38: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -flatten-awaitables.mo:79.20-79.24: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -flatten-awaitables.mo:81.19-81.23: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -flatten-awaitables.mo:83.26-83.30: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -flatten-awaitables.mo:85.34-85.38: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -flatten-awaitables.mo:88.20-88.24: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -flatten-awaitables.mo:90.19-90.23: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -flatten-awaitables.mo:92.26-92.30: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -flatten-awaitables.mo:94.34-94.38: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -flatten-awaitables.mo:97.20-97.24: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -flatten-awaitables.mo:99.19-99.23: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -flatten-awaitables.mo:101.26-101.30: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -flatten-awaitables.mo:103.34-103.38: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -flatten-awaitables.mo:106.20-106.24: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -flatten-awaitables.mo:108.19-108.23: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -flatten-awaitables.mo:110.26-110.30: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -flatten-awaitables.mo:112.34-112.38: type error, calling a shared function not yet supported - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/flatten-awaitables.comp.ret.ok b/test/run-drun/ok/flatten-awaitables.comp.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/flatten-awaitables.comp.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/flatten-awaitables.drun-run.ok b/test/run-drun/ok/flatten-awaitables.drun-run.ok new file mode 100644 index 00000000000..56cdd90b3a1 --- /dev/null +++ b/test/run-drun/ok/flatten-awaitables.drun-run.ok @@ -0,0 +1,3 @@ +ingress(0) System +debug.print: first-order +ingress(1) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/free-callbacks.comp.ok b/test/run-drun/ok/free-callbacks.comp.ok deleted file mode 100644 index ba466e2a62a..00000000000 --- a/test/run-drun/ok/free-callbacks.comp.ok +++ /dev/null @@ -1,6 +0,0 @@ -free-callbacks.mo:8.11-8.15: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -free-callbacks.mo:10.11-10.15: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -free-callbacks.mo:14.11-14.15: type error, calling a shared function not yet supported - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/free-callbacks.comp.ret.ok b/test/run-drun/ok/free-callbacks.comp.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/free-callbacks.comp.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/free-callbacks.drun-run.ok b/test/run-drun/ok/free-callbacks.drun-run.ok new file mode 100644 index 00000000000..91c74b55809 --- /dev/null +++ b/test/run-drun/ok/free-callbacks.drun-run.ok @@ -0,0 +1,2 @@ +ingress(0) System +ingress(1) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/hello-world-async.comp.ok b/test/run-drun/ok/hello-world-async.comp.ok deleted file mode 100644 index daff32bfed8..00000000000 --- a/test/run-drun/ok/hello-world-async.comp.ok +++ /dev/null @@ -1,2 +0,0 @@ -hello-world-async.mo:6.5-6.12: type error, calling a shared function not yet supported - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/hello-world-async.comp.ret.ok b/test/run-drun/ok/hello-world-async.comp.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/hello-world-async.comp.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/hello-world-async.drun-run.ok b/test/run-drun/ok/hello-world-async.drun-run.ok new file mode 100644 index 00000000000..81574f8917d --- /dev/null +++ b/test/run-drun/ok/hello-world-async.drun-run.ok @@ -0,0 +1,3 @@ +ingress(0) System +debug.print: Hello +ingress(1) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/hello-world-await.comp.ok b/test/run-drun/ok/hello-world-await.comp.ok deleted file mode 100644 index 3a0f615f7b1..00000000000 --- a/test/run-drun/ok/hello-world-await.comp.ok +++ /dev/null @@ -1,2 +0,0 @@ -hello-world-await.mo:9.23-9.28: type error, calling a shared function not yet supported - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/hello-world-await.comp.ret.ok b/test/run-drun/ok/hello-world-await.comp.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/hello-world-await.comp.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/hello-world-await.drun-run.ok b/test/run-drun/ok/hello-world-await.drun-run.ok new file mode 100644 index 00000000000..91c74b55809 --- /dev/null +++ b/test/run-drun/ok/hello-world-await.drun-run.ok @@ -0,0 +1,2 @@ +ingress(0) System +ingress(1) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/ic-calls.comp.ok b/test/run-drun/ok/ic-calls.comp.ok deleted file mode 100644 index 14732db46bd..00000000000 --- a/test/run-drun/ok/ic-calls.comp.ok +++ /dev/null @@ -1,6 +0,0 @@ -ic-calls.mo:14.20-14.21: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -ic-calls.mo:15.19-15.20: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -ic-calls.mo:16.26-16.27: type error, calling a shared function not yet supported - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/ic-calls.comp.ret.ok b/test/run-drun/ok/ic-calls.comp.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/ic-calls.comp.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/ic-calls.drun-run.ok b/test/run-drun/ok/ic-calls.drun-run.ok new file mode 100644 index 00000000000..91c74b55809 --- /dev/null +++ b/test/run-drun/ok/ic-calls.drun-run.ok @@ -0,0 +1,2 @@ +ingress(0) System +ingress(1) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/issue-894.comp.ok b/test/run-drun/ok/issue-894.comp.ok index 5499821b6d7..10ef901c51d 100644 --- a/test/run-drun/ok/issue-894.comp.ok +++ b/test/run-drun/ok/issue-894.comp.ok @@ -4,5 +4,3 @@ issue-894.mo:22.15-22.22: type error, unsupported async block (This is a limitation of the current version.) issue-894.mo:29.15-29.22: type error, unsupported async block (This is a limitation of the current version.) -issue-894.mo:37.17-37.19: type error, calling a shared function not yet supported - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/local-throw.comp.ok b/test/run-drun/ok/local-throw.comp.ok deleted file mode 100644 index 2d6bffe44eb..00000000000 --- a/test/run-drun/ok/local-throw.comp.ok +++ /dev/null @@ -1,4 +0,0 @@ -local-throw.mo:53.13-53.15: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -local-throw.mo:60.13-60.15: type error, calling a shared function not yet supported - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/local-throw.comp.ret.ok b/test/run-drun/ok/local-throw.comp.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/local-throw.comp.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/local-throw.drun-run.ok b/test/run-drun/ok/local-throw.drun-run.ok new file mode 100644 index 00000000000..91c74b55809 --- /dev/null +++ b/test/run-drun/ok/local-throw.drun-run.ok @@ -0,0 +1,2 @@ +ingress(0) System +ingress(1) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/oneway-throw.comp.ok b/test/run-drun/ok/oneway-throw.comp.ok deleted file mode 100644 index 9f4abefb861..00000000000 --- a/test/run-drun/ok/oneway-throw.comp.ok +++ /dev/null @@ -1,4 +0,0 @@ -oneway-throw.mo:14.5-14.11: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -oneway-throw.mo:15.11-15.15: type error, calling a shared function not yet supported - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/oneway-throw.comp.ret.ok b/test/run-drun/ok/oneway-throw.comp.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/oneway-throw.comp.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/oneway-throw.drun-run.ok b/test/run-drun/ok/oneway-throw.drun-run.ok new file mode 100644 index 00000000000..1cd45a1b62a --- /dev/null +++ b/test/run-drun/ok/oneway-throw.drun-run.ok @@ -0,0 +1,3 @@ +ingress(0) System +debug.print: go1 +ingress(1) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/oneway.comp.ok b/test/run-drun/ok/oneway.comp.ok deleted file mode 100644 index 8142047c85a..00000000000 --- a/test/run-drun/ok/oneway.comp.ok +++ /dev/null @@ -1,8 +0,0 @@ -oneway.mo:57.5-57.11: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -oneway.mo:59.5-59.14: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -oneway.mo:61.5-61.12: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -oneway.mo:63.5-63.15: type error, calling a shared function not yet supported - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/oneway.comp.ret.ok b/test/run-drun/ok/oneway.comp.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/oneway.comp.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/oneway.drun-run.ok b/test/run-drun/ok/oneway.drun-run.ok new file mode 100644 index 00000000000..4a239d3bf08 --- /dev/null +++ b/test/run-drun/ok/oneway.drun-run.ok @@ -0,0 +1,7 @@ +ingress(0) System +debug.print: A +debug.print: B +debug.print: C +debug.print: D +debug.print: E +ingress(1) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/pass-references.comp.ok b/test/run-drun/ok/pass-references.comp.ok index 77c0fedbdf0..be0c963c22b 100644 --- a/test/run-drun/ok/pass-references.comp.ok +++ b/test/run-drun/ok/pass-references.comp.ok @@ -1,12 +1,2 @@ -pass-references.mo:5.5-5.6: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -pass-references.mo:9.5-9.10: type error, calling a shared function not yet supported - (This is a limitation of the current version.) pass-references.mo:13.5-15.6: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program (This is a limitation of the current version.) -pass-references.mo:16.5-16.14: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -pass-references.mo:17.5-17.14: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -pass-references.mo:18.5-18.15: type error, calling a shared function not yet supported - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/query2.comp.ok b/test/run-drun/ok/query2.comp.ok deleted file mode 100644 index b97f086058d..00000000000 --- a/test/run-drun/ok/query2.comp.ok +++ /dev/null @@ -1,18 +0,0 @@ -query2.mo:22.4-22.15: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -query2.mo:23.4-23.15: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -query2.mo:24.4-24.15: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -query2.mo:25.4-25.24: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -query2.mo:26.19-26.30: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -query2.mo:28.19-28.31: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -query2.mo:29.4-29.24: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -query2.mo:31.19-31.31: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -query2.mo:32.4-32.24: type error, calling a shared function not yet supported - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/query2.comp.ret.ok b/test/run-drun/ok/query2.comp.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/query2.comp.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/query2.drun-run.ok b/test/run-drun/ok/query2.drun-run.ok new file mode 100644 index 00000000000..91c74b55809 --- /dev/null +++ b/test/run-drun/ok/query2.drun-run.ok @@ -0,0 +1,2 @@ +ingress(0) System +ingress(1) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/shared-object.comp.ok b/test/run-drun/ok/shared-object.comp.ok deleted file mode 100644 index ee047cbf1b6..00000000000 --- a/test/run-drun/ok/shared-object.comp.ok +++ /dev/null @@ -1,2 +0,0 @@ -shared-object.mo:15.20-15.23: type error, calling a shared function not yet supported - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/shared-object.comp.ret.ok b/test/run-drun/ok/shared-object.comp.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/shared-object.comp.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/shared-object.drun-run.ok b/test/run-drun/ok/shared-object.drun-run.ok new file mode 100644 index 00000000000..91c74b55809 --- /dev/null +++ b/test/run-drun/ok/shared-object.drun-run.ok @@ -0,0 +1,2 @@ +ingress(0) System +ingress(1) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/throw.comp.ok b/test/run-drun/ok/throw.comp.ok index bece8b63cfd..22422ae6054 100644 --- a/test/run-drun/ok/throw.comp.ok +++ b/test/run-drun/ok/throw.comp.ok @@ -2,7 +2,3 @@ throw.mo:7.14-10.8: type error, unsupported async block (This is a limitation of the current version.) throw.mo:22.13-41.8: type error, unsupported async block (This is a limitation of the current version.) -throw.mo:59.13-59.15: type error, calling a shared function not yet supported - (This is a limitation of the current version.) -throw.mo:66.13-66.15: type error, calling a shared function not yet supported - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/transpose.comp.ok b/test/run-drun/ok/transpose.comp.ok deleted file mode 100644 index 2c654224f3c..00000000000 --- a/test/run-drun/ok/transpose.comp.ok +++ /dev/null @@ -1,2 +0,0 @@ -transpose.mo:10.19-10.30: type error, calling a shared function not yet supported - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/transpose.comp.ret.ok b/test/run-drun/ok/transpose.comp.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/transpose.comp.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/transpose.drun-run.ok b/test/run-drun/ok/transpose.drun-run.ok new file mode 100644 index 00000000000..91c74b55809 --- /dev/null +++ b/test/run-drun/ok/transpose.drun-run.ok @@ -0,0 +1,2 @@ +ingress(0) System +ingress(1) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/unsupported.comp.ok b/test/run-drun/ok/unsupported.comp.ok index a2844d732ce..aff34c930f4 100644 --- a/test/run-drun/ok/unsupported.comp.ok +++ b/test/run-drun/ok/unsupported.comp.ok @@ -1,7 +1,5 @@ unsupported.mo:19.19-19.21: type error, shared, async function must be called within an await expression (This is a limitation of the current version.) -unsupported.mo:23.16-23.18: type error, calling a shared function not yet supported - (This is a limitation of the current version.) unsupported.mo:28.8-28.9: type error, argument to await must be a call expression (This is a limitation of the current version.) unsupported.mo:32.17-32.29: type error, unsupported async block From 1922d3adf61060e8c812395d310f5d91a940221f Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 17 Dec 2019 16:25:21 +0100 Subject: [PATCH 0842/1176] Add the `--actor-idl` flag (#1045) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add the `--actor-idl` flag as per https://github.com/dfinity-lab/motoko/blob/master/design/DFX-Interface.md Doesn’t read the IDL file yet. * Safer hex_of_byte * mo-ide: Also accept --actor-idl --- src/exes/mo_ide.ml | 9 ++++++--- src/exes/moc.ml | 1 + src/lib/lib.ml | 19 +++++++++++++++++++ src/lib/lib.mli | 4 ++++ src/mo_config/flags.ml | 1 + src/pipeline/pipeline.ml | 4 ++-- src/pipeline/resolve_import.ml | 27 ++++++++++++++++++++------- src/pipeline/resolve_import.mli | 3 ++- src/pipeline/url.ml | 5 +++++ src/pipeline/url.mli | 1 + test/run-drun/actor-import.mo | 2 ++ test/run-drun/ok/actor-import.tc.ok | 2 +- 12 files changed, 64 insertions(+), 14 deletions(-) diff --git a/src/exes/mo_ide.ml b/src/exes/mo_ide.ml index ab498bf33bb..e11df1f0697 100644 --- a/src/exes/mo_ide.ml +++ b/src/exes/mo_ide.ml @@ -1,3 +1,5 @@ +open Mo_config + let entry_point : string option ref = ref None let debug = ref false @@ -19,12 +21,13 @@ let argspec = Arg.Set_string package_name_ref ; Arg.String begin fun package_url -> (* push (package_name, package_url) onto the list. *) - Mo_config.Flags.package_urls := ( + Flags.package_urls := ( !package_name_ref, package_url - ) :: ! Mo_config.Flags.package_urls + ) :: ! Flags.package_urls end - ]), " Specify a package-name-package-URL pair, separated by a space" ; + ]), " Specify a package-name-package-URL pair, separated by a space" + ; "--actor-idl", Arg.String (fun fp -> Flags.actor_idl_path := Some fp), " path to actor IDL files" ] let () = diff --git a/src/exes/moc.ml b/src/exes/moc.ml index 274ec8f0e66..c1c7c42ef69 100644 --- a/src/exes/moc.ml +++ b/src/exes/moc.ml @@ -58,6 +58,7 @@ let argspec = Arg.align ) :: ! Flags.package_urls end ]), " Specify a package-name-package-URL pair, separated by a space" ; + "--actor-idl", Arg.String (fun fp -> Flags.actor_idl_path := Some fp), " path to actor IDL files"; "--profile", Arg.Set Flags.profile, " activate profiling counters in interpreters "; "--profile-file", Arg.Set_string Flags.profile_file, " set profiling output file "; "--profile-line-prefix", Arg.Set_string Flags.profile_line_prefix, " prefix each profile line with the given string "; diff --git a/src/lib/lib.ml b/src/lib/lib.ml index 4a4c787407a..2a2210893f9 100644 --- a/src/lib/lib.ml +++ b/src/lib/lib.ml @@ -74,6 +74,25 @@ struct let int_of_hex_byte hex : int = assert (String.length hex = 2); String.(hexdigit (get hex 0) lsl 4 lor hexdigit (get hex 1)) + + let hex_of_nibble = + let open Char in + function + | c when 0 <= c && c <= 9 -> chr (code '0' + c) + | c when 10 < c && c <= 15 -> chr (code 'A' + (c - 10)) + | _ -> assert false + + let hex_of_byte i : string = + String.init 2 (function + | 0 -> hex_of_nibble (i / 16) + | 1 -> hex_of_nibble (i mod 16) + | _ -> assert false) + + let hex_of_char c = hex_of_byte (Char.code c) + + let hex_of_bytes bytes : string = + let open Stdlib.String in + of_seq (Stdlib.Seq.flat_map (fun c -> to_seq (hex_of_char c)) (to_seq bytes)) end module String = diff --git a/src/lib/lib.mli b/src/lib/lib.mli index 8685e1a072d..f66d5313f1d 100644 --- a/src/lib/lib.mli +++ b/src/lib/lib.mli @@ -153,6 +153,10 @@ sig val hexdigit : char -> int val bytes_of_hex : string -> string val int_of_hex_byte : string -> int + + val hex_of_byte : int -> string + val hex_of_char : char -> string + val hex_of_bytes : string -> string end module FilePath : diff --git a/src/mo_config/flags.ml b/src/mo_config/flags.ml index ea22cc2ed37..16af3208126 100644 --- a/src/mo_config/flags.ml +++ b/src/mo_config/flags.ml @@ -16,6 +16,7 @@ let dump_tc = ref false let dump_lowering = ref false let check_ir = ref true let package_urls : (string * string) list ref = ref [] +let actor_idl_path : string option ref = ref None let profile = ref false let profile_verbose = ref false let profile_file = ref "profiling-counters.csv" diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index 80bfccddee5..280fa74c092 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -112,7 +112,7 @@ type resolve_result = (Syntax.prog * ResolveImport.resolved_imports) Diag.result let resolve_prog (prog, base) : resolve_result = Diag.map (fun libs -> (prog, libs)) - (ResolveImport.resolve !Flags.package_urls prog base) + (ResolveImport.resolve !Flags.actor_idl_path !Flags.package_urls prog base) let resolve_progs = Diag.traverse resolve_prog @@ -238,7 +238,7 @@ let chase_imports parsefn senv0 imports : (Syntax.lib list * Scope.scope) Diag.r pending := add ri.Source.it !pending; Diag.bind (parsefn f) (fun (prog, base) -> Diag.bind (Static.prog prog) (fun () -> - Diag.bind (ResolveImport.resolve !Flags.package_urls prog base) (fun more_imports -> + Diag.bind (ResolveImport.resolve !Flags.actor_idl_path !Flags.package_urls prog base) (fun more_imports -> Diag.bind (go_set more_imports) (fun () -> let lib = lib_of_prog f prog in Diag.bind (check_lib !senv lib) (fun sscope -> diff --git a/src/pipeline/resolve_import.ml b/src/pipeline/resolve_import.ml index 599abce5a0b..a843939f9a5 100644 --- a/src/pipeline/resolve_import.ml +++ b/src/pipeline/resolve_import.ml @@ -62,6 +62,15 @@ let err_unrecognized_url msgs at url msg = text = Printf.sprintf "cannot parse import URL %s: %s" url msg } +let err_actor_import_without_idl_path msgs at = + let open Diag in + add_msg msgs { + sev = Error; + at; + cat = "import"; + text = Printf.sprintf "cannot import canister urls without --actor-idl param" + } + let err_file_does_not_exist msgs at full_path = let open Diag in add_msg msgs { @@ -126,7 +135,7 @@ let in_base base f = then f else Filename.concat base f -let resolve_import_string msgs base packages imported (f, ri_ref, at) = +let resolve_import_string msgs base actor_idl_path packages imported (f, ri_ref, at) = match Url.parse f with | Ok (Url.Relative path) -> add_lib_import msgs imported ri_ref at (in_base base path) @@ -137,9 +146,12 @@ let resolve_import_string msgs base packages imported (f, ri_ref, at) = | None -> err_package_not_defined msgs at pkg end - | Ok (Url.Ic bytes) -> - let full_path = (* in_base actor_base *) bytes in - add_idl_import msgs imported ri_ref at full_path bytes + | Ok (Url.Ic bytes) -> begin match actor_idl_path with + | None -> err_actor_import_without_idl_path msgs at + | Some actor_base -> + let full_path = in_base actor_base (Url.idl_basename_of_blob bytes) in + add_idl_import msgs imported ri_ref at full_path bytes + end | Error msg -> err_unrecognized_url msgs at f msg @@ -170,6 +182,7 @@ let collect_imports (p : prog): string list = List.map (fun (f, _, _) -> f) (prog_imports p) +type actor_idl_path = string option type package_urls = (string * string) list let resolve_packages : package_urls -> filepath -> package_map Diag.result = fun purls base -> @@ -185,13 +198,13 @@ let resolve_packages : package_urls -> filepath -> package_map Diag.result = fun M.empty purls let resolve - : package_urls -> Syntax.prog -> filepath -> resolved_imports Diag.result - = fun purls p base -> + : actor_idl_path -> package_urls -> Syntax.prog -> filepath -> resolved_imports Diag.result + = fun actor_idl_path purls p base -> Diag.bind (resolve_packages purls base) (fun (packages:package_map) -> Diag.with_message_store (fun msgs -> let base = if Sys.is_directory base then base else Filename.dirname base in let imported = ref RIM.empty in - List.iter (resolve_import_string msgs base packages imported) (prog_imports p); + List.iter (resolve_import_string msgs base actor_idl_path packages imported) (prog_imports p); Some (List.map (fun (rim,at) -> Source.(rim @@ at)) (RIM.bindings !imported)) ) ) diff --git a/src/pipeline/resolve_import.mli b/src/pipeline/resolve_import.mli index 9e9adb6c668..b840c0b9334 100644 --- a/src/pipeline/resolve_import.mli +++ b/src/pipeline/resolve_import.mli @@ -5,9 +5,10 @@ type filepath = string module S : Set.S with type elt = Syntax.resolved_import module RIM : Map.S with type key = Syntax.resolved_import +type actor_idl_path = string option type package_urls = (string * string) list type resolved_imports = Syntax.resolved_import Source.phrase list val collect_imports : Syntax.prog -> string list -val resolve : package_urls -> Syntax.prog -> filepath -> resolved_imports Diag.result +val resolve : actor_idl_path -> package_urls -> Syntax.prog -> filepath -> resolved_imports Diag.result diff --git a/src/pipeline/url.ml b/src/pipeline/url.ml index 5ff6815e640..640bfb0adf9 100644 --- a/src/pipeline/url.ml +++ b/src/pipeline/url.ml @@ -63,3 +63,8 @@ let parse (f: string) : (parsed, string) result = | Some _ -> Error "Unrecognized URL" | None -> Ok (Relative (Lib.FilePath.normalise f)) end + + +(* Basename of the IDL file searched (see DFX-Interface.md) *) +let idl_basename_of_blob bytes = + Lib.Hex.hex_of_bytes bytes ^ Lib.Hex.hex_of_byte (Lib.CRC.crc8 bytes) ^ ".did" diff --git a/src/pipeline/url.mli b/src/pipeline/url.mli index d97161a02e1..0306344cab5 100644 --- a/src/pipeline/url.mli +++ b/src/pipeline/url.mli @@ -4,3 +4,4 @@ type parsed = | Ic of string val parse : string -> (parsed, string) result +val idl_basename_of_blob : string -> string diff --git a/test/run-drun/actor-import.mo b/test/run-drun/actor-import.mo index c1edf9a4c48..fb00113a7de 100644 --- a/test/run-drun/actor-import.mo +++ b/test/run-drun/actor-import.mo @@ -1,3 +1,5 @@ +//MOC-FLAG --actor-idl . + import imported "ic:000000000000040054"; actor a { public func go() : async (actor {}) = async imported; diff --git a/test/run-drun/ok/actor-import.tc.ok b/test/run-drun/ok/actor-import.tc.ok index 98f95fb5d3c..5561b580d80 100644 --- a/test/run-drun/ok/actor-import.tc.ok +++ b/test/run-drun/ok/actor-import.tc.ok @@ -1 +1 @@ -actor-import.mo:1.1-1.40: warning, imported actors assumed to have type actor {} +actor-import.mo:3.1-3.40: warning, imported actors assumed to have type actor {} From f4479a8e04ffece40713974aab80b64d8d78d925 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 17 Dec 2019 20:17:19 +0100 Subject: [PATCH 0843/1176] --print-deps test: Also include ic-imports (#1048) --- test/repl/lib/actor-import.mo | 2 ++ test/repl/ok/print-deps.stdout.ok | 2 ++ test/repl/print-deps.sh | 1 + 3 files changed, 5 insertions(+) create mode 100644 test/repl/lib/actor-import.mo diff --git a/test/repl/lib/actor-import.mo b/test/repl/lib/actor-import.mo new file mode 100644 index 00000000000..2e099250838 --- /dev/null +++ b/test/repl/lib/actor-import.mo @@ -0,0 +1,2 @@ +import "ic:ABCDE01A7"; +import "ic:alias"; diff --git a/test/repl/ok/print-deps.stdout.ok b/test/repl/ok/print-deps.stdout.ok index 49ded34397f..a98fe175b79 100644 --- a/test/repl/ok/print-deps.stdout.ok +++ b/test/repl/ok/print-deps.stdout.ok @@ -1,2 +1,4 @@ nested/a.mo nested/b.mo +ic:ABCDE01A7 +ic:alias diff --git a/test/repl/print-deps.sh b/test/repl/print-deps.sh index 28067fd7e0a..3669eaabf10 100755 --- a/test/repl/print-deps.sh +++ b/test/repl/print-deps.sh @@ -1,2 +1,3 @@ #!/bin/bash ${MOC:-$(dirname "$BASH_SOURCE")/../../src/moc} --print-deps lib/nested.mo +${MOC:-$(dirname "$BASH_SOURCE")/../../src/moc} --print-deps lib/actor-import.mo From df30711bee01d15072f459cad5187197151113e2 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Tue, 17 Dec 2019 23:08:43 +0100 Subject: [PATCH 0844/1176] Use abbreviations (#1049) * use abbreviations * a few more tweaks --- src/codegen/compile.ml | 10 +++++----- src/ir_def/check_ir.ml | 2 +- src/ir_passes/show.ml | 30 +++++++++++++++--------------- src/mo_frontend/typing.ml | 2 +- src/mo_values/operator.ml | 2 +- src/mo_values/show.ml | 6 +++--- 6 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 107516827e1..2bd6cbbe3e7 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -1381,7 +1381,7 @@ module UnboxedSmallWord = struct compile_word_padding ty ^^ G.i (Unary (Wasm.Values.I32 I32Op.Clz)) ^^ msb_adjust ty - + (* Kernel for counting trailing zeros, according to the word invariant. *) let ctz_kernel ty = compile_word_padding ty ^^ @@ -4818,7 +4818,7 @@ module FuncDec = struct Dfinity.assert_caller_self env ^^ (* Deserialize and look up closure argument *) - Serialization.deserialize env [Type.Prim Type.Word32] ^^ + Serialization.deserialize env Type.[Prim Word32] ^^ BoxedSmallWord.unbox env ^^ ClosureTable.recall env ^^ set_closure ^^ get_closure ^^ get_closure ^^ @@ -5666,7 +5666,7 @@ let compile_binop env t op = get_by ^^ lsb_adjust ty ^^ clamp_shift_amount ty ^^ G.i (Binary (I32 I32Op.Rotr)) ^^ sanitize_word_result ty)) - | Type.Prim Type.Text, CatOp -> Text.concat env + | Type.(Prim Text), CatOp -> Text.concat env | Type.Non, _ -> G.i Unreachable | _ -> todo_trap env "compile_binop" (Arrange_ops.binop op) ) @@ -6224,7 +6224,7 @@ and compile_exp (env : E.t) ae exp = compile_exp_as env ae SR.Vanilla exp_k ^^ set_k ^^ compile_exp_as env ae SR.Vanilla exp_r ^^ set_r ^^ - FuncDec.ic_call env [Type.Prim Type.Word32] ts + FuncDec.ic_call env Type.[Prim Word32] ts ( Dfinity.get_self_reference env ^^ Dfinity.actor_public_field env (Dfinity.async_method_name)) (get_closure_idx ^^ BoxedSmallWord.box env) @@ -6650,7 +6650,7 @@ and compile_start_func mod_env (progs : Ir.prog list) : E.func_with_names = and export_actor_field env ae (f : Ir.field) = let sr, code = Var.get_val env ae f.it.var in - (* A public actor field is guaranteed to be compiled as a PublicMethod *) + (* A public actor field is guaranteed to be compiled as a PublicMethod *) let fi = match sr with | SR.StaticThing (SR.PublicMethod (fi, _)) -> fi | _ -> assert false in diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 9468a210196..ef1f08fdac9 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -354,7 +354,7 @@ let rec check_exp env (exp:Ir.exp) : unit = check env.flavor.has_show "show expression in non-show flavor"; check (Show.can_show ot) "show is not defined for operand type"; typ exp1 <: ot; - T.Prim T.Text <: t + T.text <: t | CPSAwait, [a; kr] -> check (not (env.flavor.has_await)) "CPSAwait await flavor"; check (env.flavor.has_async_typ) "CPSAwait in post-async flavor"; diff --git a/src/ir_passes/show.ml b/src/ir_passes/show.ml index fa5f11a1334..74941f79364 100644 --- a/src/ir_passes/show.ml +++ b/src/ir_passes/show.ml @@ -54,7 +54,7 @@ let show_name_for t = "@show<" ^ typ_id t ^ ">" let show_fun_typ_for t = - T.Func (T.Local, T.Returns, [], [t], [T.Prim T.Text]) + T.Func (T.Local, T.Returns, [], [t], [T.text]) let show_var_for t : Construct.var = idE (show_name_for t) (show_fun_typ_for t) @@ -73,14 +73,14 @@ let define_show : T.typ -> Ir.exp -> Ir.dec = fun t e -> let text_exp : Ir.exp' -> Ir.exp = fun e -> { it = e; at = no_region; - note = { note_typ = T.Prim T.Text; note_eff = T.Triv } + note = { note_typ = T.text; note_eff = T.Triv } } let invoke_generated_show : T.typ -> Ir.exp -> Ir.exp = fun t e -> text_exp (CallE (show_var_for t, [], e)) let invoke_prelude_show : string -> T.typ -> Ir.exp -> Ir.exp = fun n t e -> - let fun_typ = T.Func (T.Local, T.Returns, [], [t], [T.Prim T.Text]) in + let fun_typ = T.Func (T.Local, T.Returns, [], [t], [T.text]) in text_exp (CallE ( { it = VarE n ; at = no_region @@ -93,7 +93,7 @@ let invoke_prelude_show : string -> T.typ -> Ir.exp -> Ir.exp = fun n t e -> let invoke_text_of_option : T.typ -> Ir.exp -> Ir.exp -> Ir.exp = fun t f e -> let fun_typ = - T.Func (T.Local, T.Returns, [{T.var="T";T.bound=T.Any}], [show_fun_typ_for (T.Var ("T",0)); T.Opt (T.Var ("T",0))], [T.Prim T.Text]) in + T.Func (T.Local, T.Returns, [{T.var="T";T.bound=T.Any}], [show_fun_typ_for (T.Var ("T",0)); T.Opt (T.Var ("T",0))], [T.text]) in text_exp (CallE ( { it = VarE "@text_of_option" ; at = no_region @@ -109,7 +109,7 @@ let invoke_text_of_option : T.typ -> Ir.exp -> Ir.exp -> Ir.exp = fun t f e -> let invoke_text_of_variant : T.typ -> Ir.exp -> T.lab -> Ir.exp -> Ir.exp = fun t f l e -> let fun_typ = - T.Func (T.Local, T.Returns, [{T.var="T";T.bound=T.Any}], [T.Prim T.Text; show_fun_typ_for (T.Var ("T",0)); T.Var ("T",0)], [T.Prim T.Text]) in + T.Func (T.Local, T.Returns, [{T.var="T";T.bound=T.Any}], [T.text; show_fun_typ_for (T.Var ("T",0)); T.Var ("T",0)], [T.text]) in text_exp (CallE ( { it = VarE "@text_of_variant" ; at = no_region @@ -118,14 +118,14 @@ let invoke_text_of_variant : T.typ -> Ir.exp -> T.lab -> Ir.exp -> Ir.exp = fun , [t] , { it = TupE [textE l; f; e] ; at = no_region - ; note = { note_typ = T.Tup [T.Prim T.Text; show_fun_typ_for t; t]; note_eff = T.Triv } + ; note = { note_typ = T.Tup [T.text; show_fun_typ_for t; t]; note_eff = T.Triv } } ) ) let invoke_text_of_array : T.typ -> Ir.exp -> Ir.exp -> Ir.exp = fun t f e -> let fun_typ = - T.Func (T.Local, T.Returns, [{T.var="T";T.bound=T.Any}], [show_fun_typ_for (T.Var ("T",0)); T.Array (T.Var ("T",0))], [T.Prim T.Text]) in + T.Func (T.Local, T.Returns, [{T.var="T";T.bound=T.Any}], [show_fun_typ_for (T.Var ("T",0)); T.Array (T.Var ("T",0))], [T.text]) in text_exp (CallE ( { it = VarE "@text_of_array" ; at = no_region @@ -141,7 +141,7 @@ let invoke_text_of_array : T.typ -> Ir.exp -> Ir.exp -> Ir.exp = fun t f e -> let invoke_text_of_array_mut : T.typ -> Ir.exp -> Ir.exp -> Ir.exp = fun t f e -> let fun_typ = - T.Func (T.Local, T.Returns, [{T.var="T";T.bound=T.Any}], [show_fun_typ_for (T.Var ("T",0)); T.Array (T.Mut (T.Var ("T",0)))], [T.Prim T.Text]) in + T.Func (T.Local, T.Returns, [{T.var="T";T.bound=T.Any}], [show_fun_typ_for (T.Var ("T",0)); T.Array (T.Mut (T.Var ("T",0)))], [T.text]) in text_exp (CallE ( { it = VarE "@text_of_array_mut" ; at = no_region @@ -165,7 +165,7 @@ let list_build : 'a -> 'a -> 'a -> 'a list -> 'a list = fun pre sep post xs -> let catE : Ir.exp -> Ir.exp -> Ir.exp = fun e1 e2 -> { it = PrimE (BinPrim (T.text, Operator.CatOp), [e1; e2]) ; at = no_region - ; note = { note_typ = T.Prim T.Text; note_eff = T.Triv } + ; note = { note_typ = T.text; note_eff = T.Triv } } let cat_list : Ir.exp list -> Ir.exp = fun es -> @@ -178,13 +178,13 @@ let cat_list : Ir.exp list -> Ir.exp = fun es -> let show_for : T.typ -> Ir.dec * T.typ list = fun t -> match t with - | T.Prim T.Bool -> + | T.(Prim Bool) -> define_show t (invoke_prelude_show "@text_of_Bool" t (argE t)), [] - | T.Prim T.Nat -> + | T.(Prim Nat) -> define_show t (invoke_prelude_show "@text_of_Nat" t (argE t)), [] - | T.Prim T.Int -> + | T.(Prim Int) -> define_show t (invoke_prelude_show "@text_of_Int" t (argE t)), [] | T.(Prim Nat8) -> @@ -223,10 +223,10 @@ let show_for : T.typ -> Ir.dec * T.typ list = fun t -> | T.(Prim Word64) -> define_show t (invoke_prelude_show "@text_of_Word64" t (argE t)), [] - | T.Prim T.Text -> + | T.(Prim Text) -> define_show t (invoke_prelude_show "@text_of_Text" t (argE t)), [] - | T.Prim T.Null -> + | T.(Prim Null) -> define_show t (textE ("null")), [] | T.Func _ -> @@ -298,7 +298,7 @@ let show_for : T.typ -> Ir.dec * T.typ list = fun t -> (varP (argE t')), (* Shadowing, but that's fine *) (invoke_text_of_variant t' (show_var_for t') l (argE t')) ) fs) - (T.Prim T.Text) + (T.text) ), List.map (fun (f : T.field) -> T.normalize f.T.typ) fs | T.Non -> diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 55eace31193..0841183d548 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -652,7 +652,7 @@ and infer_exp'' env exp : T.typ = (T.string_of_typ_expand t); ot := t end; - T.Prim T.Text + T.text | TupE exps -> let ts = List.map (infer_exp env) exps in T.Tup ts diff --git a/src/mo_values/operator.ml b/src/mo_values/operator.ml index fc0643bc335..9d2983f39c0 100644 --- a/src/mo_values/operator.ml +++ b/src/mo_values/operator.ml @@ -178,6 +178,6 @@ let has_unop op t = has unop op t let has_binop op t = has binop op t let has_relop op t = has relop op t -let type_unop op t = if t = T.Prim T.Nat then T.Prim T.Int else t +let type_unop op t = if t = T.nat then T.int else t let type_binop op t = t let type_relop op t = t diff --git a/src/mo_values/show.ml b/src/mo_values/show.ml index eedd7a07a86..2879408086b 100644 --- a/src/mo_values/show.ml +++ b/src/mo_values/show.ml @@ -29,7 +29,7 @@ let sign b s = (if b then "+" else "") ^ s let rec show_val t v = let t = T.normalize t in match t, v with - | T.Prim T.Bool, Value.Bool b -> if b then "true" else "false" + | T.(Prim Bool), Value.Bool b -> if b then "true" else "false" | T.(Prim Nat), Value.Int i -> Value.Int.to_string i | T.(Prim Nat8), Value.Nat8 i -> Value.Nat8.to_string i | T.(Prim Nat16), Value.Nat16 i -> Value.Nat16.to_string i @@ -44,8 +44,8 @@ let rec show_val t v = | T.(Prim Word16), Value.Word16 i -> "0x" ^ Value.Word16.to_string i | T.(Prim Word32), Value.Word32 i -> "0x" ^ Value.Word32.to_string i | T.(Prim Word64), Value.Word64 i -> "0x" ^ Value.Word64.to_string i - | T.Prim T.Text, Value.Text s -> "\"" ^ s ^ "\"" - | T.Prim T.Null, Value.Null -> "null" + | T.(Prim Text), Value.Text s -> "\"" ^ s ^ "\"" + | T.(Prim Null), Value.Null -> "null" | T.Opt _, Value.Null -> "null" | T.Opt t', Value.Opt v -> "?" ^ parens (show_val t' v) | T.Tup ts', Value.Tup vs -> From fa57d3297560a5768a38ad9bc04c8f62c1ec9b0f Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 18 Dec 2019 00:12:18 +0100 Subject: [PATCH 0845/1176] Hook up actor imports to Idllib.check_file (#1046) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit this prepares and outlines the connection to @chenyan-dfinity’s #1026. --- src/pipeline/pipeline.ml | 16 +++++++++++++--- test/run-drun/actor-import.mo | 10 +++++++++- .../run-drun/actor-import/000000000000040054.did | 3 +++ test/run-drun/ok/actor-import.drun-run.ok | 2 -- test/run-drun/ok/actor-import.ic-stub-run.ok | 2 ++ test/run-drun/ok/actor-import.tc.ok | 2 +- 6 files changed, 28 insertions(+), 7 deletions(-) create mode 100644 test/run-drun/actor-import/000000000000040054.did delete mode 100644 test/run-drun/ok/actor-import.drun-run.ok diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index 280fa74c092..aa57057dca1 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -249,9 +249,19 @@ let chase_imports parsefn senv0 imports : (Syntax.lib list * Scope.scope) Diag.r ))))) end | Syntax.IDLPath (f, _) -> - let sscope = Scope.lib f Type.(Obj (Actor, [])) in - senv := Scope.adjoin !senv sscope; - Diag.warn ri.Source.at "import" "imported actors assumed to have type actor {}" + Diag.bind (Idllib.Pipeline.check_file f) (fun _ -> + let scaffold_type = + (* hard-coded for test/run-drun/actor-import.mo *) + (* to be replaced with the imported type in #1026 *) + let open Type in + Obj (Actor, [{lab = "go"; typ = Func (Shared Write, Promises, [], [], [Obj (Actor, [])])}]) + in + let sscope = Scope.lib f scaffold_type in + senv := Scope.adjoin !senv sscope; + Diag.warn ri.Source.at "import" + (Printf.sprintf "imported actors assumed to have type %s" + (Type.string_of_typ scaffold_type)) + ) and go_set todo = Diag.traverse_ go todo in Diag.map (fun () -> (List.rev !libs, !senv)) (go_set imports) diff --git a/test/run-drun/actor-import.mo b/test/run-drun/actor-import.mo index fb00113a7de..e713abef820 100644 --- a/test/run-drun/actor-import.mo +++ b/test/run-drun/actor-import.mo @@ -1,13 +1,21 @@ -//MOC-FLAG --actor-idl . +//MOC-FLAG --actor-idl actor-import + +// this imports our own IDL, stored in actor-import + +// currently hard-codes the ic-stub self id +// once we have actor aliases we can let run.sh set an alias. import imported "ic:000000000000040054"; actor a { public func go() : async (actor {}) = async imported; + public func go2() : async (actor {}) = async await (imported.go()); }; //CALL ingress go "DIDL\x00\x00" +//CALL ingress go2 "DIDL\x00\x00" //SKIP run //SKIP run-ir //SKIP run-low +//SKIP drun-run diff --git a/test/run-drun/actor-import/000000000000040054.did b/test/run-drun/actor-import/000000000000040054.did new file mode 100644 index 00000000000..73b43c85006 --- /dev/null +++ b/test/run-drun/actor-import/000000000000040054.did @@ -0,0 +1,3 @@ +service : { + "go": () -> (service {}); +} diff --git a/test/run-drun/ok/actor-import.drun-run.ok b/test/run-drun/ok/actor-import.drun-run.ok deleted file mode 100644 index 68a7bd4541f..00000000000 --- a/test/run-drun/ok/actor-import.drun-run.ok +++ /dev/null @@ -1,2 +0,0 @@ -ingress(0) System -ingress(1) Completed: Canister: Payload: 0x4449444c016900010001080000000000000400 diff --git a/test/run-drun/ok/actor-import.ic-stub-run.ok b/test/run-drun/ok/actor-import.ic-stub-run.ok index a1a43a23aef..53c6f5d873b 100644 --- a/test/run-drun/ok/actor-import.ic-stub-run.ok +++ b/test/run-drun/ok/actor-import.ic-stub-run.ok @@ -4,3 +4,5 @@ ← completed → update go(0x4449444c0000) ← completed: 0x4449444c016900010001080000000000000400 +→ update go2(0x4449444c0000) +← completed: 0x4449444c016900010001080000000000000400 diff --git a/test/run-drun/ok/actor-import.tc.ok b/test/run-drun/ok/actor-import.tc.ok index 5561b580d80..6faf5ac4c7a 100644 --- a/test/run-drun/ok/actor-import.tc.ok +++ b/test/run-drun/ok/actor-import.tc.ok @@ -1 +1 @@ -actor-import.mo:3.1-3.40: warning, imported actors assumed to have type actor {} +actor-import.mo:8.1-8.40: warning, imported actors assumed to have type actor {go : shared () -> async actor {}} From cd95850336ac1470c50c132fd4035a1e2557bcee Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 18 Dec 2019 11:47:41 +0100 Subject: [PATCH 0846/1176] Refine rts_tests for URL decoding (#1043) --- rts/rts.c | 7 +------ rts/rts.h | 3 +++ rts/test_rts.c | 28 ++++++++++++++-------------- rts/text.c | 6 ++++++ rts/url.c | 4 ++-- src/codegen/compile.ml | 4 ++-- 6 files changed, 28 insertions(+), 24 deletions(-) diff --git a/rts/rts.c b/rts/rts.c index 91876b7427a..a65c9c4b27a 100644 --- a/rts/rts.c +++ b/rts/rts.c @@ -32,11 +32,6 @@ size_t as_strlen(const char* p) { return i; } -as_ptr as_str_of_cstr(const char * const s) { - size_t l = as_strlen(s); - return text_of_ptr_size(s, l); -} - void __attribute__ ((noreturn)) trap_with_prefix(const char* prefix, const char *str) { int len1 = as_strlen(prefix); int len2 = as_strlen(str); @@ -58,7 +53,7 @@ void __attribute__ ((noreturn)) rts_trap_with(const char *str) { const char* RTS_VERSION = "0.1"; // This is mostly to test function pointers -as_ptr get_version() { return as_str_of_cstr(RTS_VERSION); } +as_ptr get_version() { return text_of_cstr(RTS_VERSION); } as_ptr (*version_getter)() = &get_version; export as_ptr version() { return (*version_getter)(); } diff --git a/rts/rts.h b/rts/rts.h index 5eef2b8e8d4..2b36cbc4d0e 100644 --- a/rts/rts.h +++ b/rts/rts.h @@ -81,10 +81,13 @@ from_rts __attribute__ ((noreturn)) void bigint_trap(); /** Functions used in multiple modules of the RTS */ export void as_memcpy(char *str1, const char *str2, size_t n); export int as_memcmp(const char *str1, const char *str2, size_t n); +export size_t as_strlen(const char *str1); char *alloc(size_t n); as_ptr alloc_blob(size_t n); as_ptr text_of_ptr_size(const char *buf, size_t n); +as_ptr text_of_cstr(const char *buf); +int text_compare(as_ptr s1, as_ptr s2); export __attribute__ ((noreturn)) void idl_trap_with(const char *str1); export __attribute__ ((noreturn)) void rts_trap_with(const char *str1); diff --git a/rts/test_rts.c b/rts/test_rts.c index 2746006c383..e60830443f1 100644 --- a/rts/test_rts.c +++ b/rts/test_rts.c @@ -163,20 +163,20 @@ int main () { */ printf("Testing IC: URL...\n"); - extern as_ptr crc8_decode(as_ptr); - as_ptr blob0 = alloc_blob(7); - char* blob0p = (char*)BLOB_PAYLOAD(blob0); - blob0p[0] = 'I'; - blob0p[1] = 'c'; - blob0p[2] = ':'; - blob0p[3] = blob0p[4] = blob0p[5] = blob0p[6] = '0'; - (void)crc8_decode(blob0); - - const int blob1len = 15; - as_ptr blob1 = alloc_blob(blob1len); - char* blob1p = (char*)BLOB_PAYLOAD(blob1); - memcpy(blob1p, "ic:C0FEFED00D41", blob1len); - (void)crc8_decode(blob1); + extern as_ptr blob_of_ic_url(as_ptr); + assert( + text_compare( + blob_of_ic_url(text_of_cstr("Ic:0000")), + text_of_ptr_size("\0",1) + ) == 0, + "Ic:0000 not decoded correctly\n"); + + assert( + text_compare( + blob_of_ic_url(text_of_cstr("ic:C0FEFED00D41")), + text_of_ptr_size("\xC0\xFE\xFE\xD0\x0D",5) + ) == 0, + "ic:C0FEFED00D41 not decoded correctly\n"); return ret; } diff --git a/rts/text.c b/rts/text.c index 96c3fc2ec2d..0452a1d0fa3 100644 --- a/rts/text.c +++ b/rts/text.c @@ -32,6 +32,12 @@ export text_t text_of_ptr_size(const char *buf, size_t n) { return r; } +text_t text_of_cstr(const char * const s) { + size_t l = as_strlen(s); + return text_of_ptr_size(s, l); +} + + // Concat export text_t text_concat(text_t s1, text_t s2) { uint32_t n1 = BLOB_LEN(s1); diff --git a/rts/url.c b/rts/url.c index 657c4786f60..dd8efe91155 100644 --- a/rts/url.c +++ b/rts/url.c @@ -53,8 +53,8 @@ static uint8_t compute_crc8(const char data[], size_t len) { return crc; } -// CRC-8 from IC-URL -export blob_t crc8_decode(text_t t) { +// Decode an IC-URL into a Blob +export blob_t blob_of_ic_url(text_t t) { blob_t b0 = blob_of_text(t); size_t n = BLOB_LEN(b0); if (n < 3) rts_trap_with("ic_url_decode: Not an URL"); diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 2bd6cbbe3e7..63a3cadd40b 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -663,7 +663,7 @@ module RTS = struct E.add_func_import env "rts" "text_singleton" [I32Type] [I32Type]; E.add_func_import env "rts" "text_size" [I32Type] [I32Type]; E.add_func_import env "rts" "text_to_buf" [I32Type; I32Type] []; - E.add_func_import env "rts" "crc8_decode" [I32Type] [I32Type]; + E.add_func_import env "rts" "blob_of_ic_url" [I32Type] [I32Type]; () end (* RTS *) @@ -6021,7 +6021,7 @@ and compile_exp (env : E.t) ae exp = (* CRC-check and strip "ic:" and checksum *) | BlobOfIcUrl, [_] -> - const_sr SR.Vanilla (E.call_import env "rts" "crc8_decode") + const_sr SR.Vanilla (E.call_import env "rts" "blob_of_ic_url") (* Actor ids are blobs in the RTS *) | ActorOfIdBlob _, [e] -> From e92d026c10e7bf79aab88f6237d7e3145fe59ec0 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 18 Dec 2019 12:00:17 +0100 Subject: [PATCH 0847/1176] Remove dead code from `Typing.error_shared` (#1040) cherry-picked from #958, but really should have been part of #913 which made objects and functions sharable. --- src/mo_frontend/typing.ml | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 0841183d548..b682bb57f4a 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -239,16 +239,7 @@ let error_shared env t at fmt = | Some t1 -> let s = Printf.sprintf "\ntype\n %s\nis or contains non-shared type\n %s" (T.string_of_typ_expand t) (T.string_of_typ_expand t1) in - Printf.ksprintf - (fun s1 -> - Diag.add_msg env.msgs (type_error at (s1^s)); - match t1 with - | T.Obj (T.Actor, _) -> - error_in [Flags.ICMode] env at "actor types are non-shared." - | T.Func (T.Shared _, _, _, _, _) -> - error_in [Flags.ICMode] env at "shared function types are non-shared." - | _ -> raise Recover) - fmt + Printf.ksprintf (fun s1 -> Diag.add_msg env.msgs (type_error at (s1^s)); raise Recover) fmt let as_domT t = match t.Source.it with From ca16901abb5ec06325aaa5f838af6b5feed506fb Mon Sep 17 00:00:00 2001 From: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> Date: Wed, 18 Dec 2019 12:07:34 +0100 Subject: [PATCH 0848/1176] [IDE] Handles more edge-cases for completion prefixes (#1044) --- src/languageServer/completion.ml | 42 +++++++++++++++------------ src/languageServer/completion_test.ml | 4 +++ 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/src/languageServer/completion.ml b/src/languageServer/completion.ml index 240b1d106f0..ca34d2c65b8 100644 --- a/src/languageServer/completion.ml +++ b/src/languageServer/completion.ml @@ -73,37 +73,43 @@ let import_relative_to_project_root root module_path dependency = List.fi| (where | is the cursor) return `Some ("List", "fi")` *) let find_completion_prefix logger file line column: (string * string) option = + let open Source in (* The LSP sends 0 based line numbers *) let line = line + 1 in let lexbuf = Lexing.from_string file in let next () = Lexer.token Lexer.Normal lexbuf in let pos_eq_cursor pos = - pos.Source.line = line && pos.Source.column = column in + pos.line = line && pos.column = column in let pos_past_cursor pos = - pos.Source.line > line - || (pos.Source.line = line && pos.Source.column > column) in + pos.line > line + || (pos.line = line && pos.column > column) in let rec loop = function - | _ when (pos_past_cursor (Lexer.region lexbuf).Source.right) -> None + | _ when (pos_past_cursor (Lexer.region lexbuf).right) -> None | Parser.ID ident -> - let next_token_end = (Lexer.region lexbuf).Source.right in + let next_token_end = (Lexer.region lexbuf).right in if pos_eq_cursor next_token_end then Some("", ident) else (match next () with | Parser.DOT -> - (match next () with - | Parser.EOF -> Some (ident, "") - | Parser.ID prefix -> - let next_token_end = (Lexer.region lexbuf).Source.right in - if pos_eq_cursor next_token_end - then Some (ident, prefix) - else loop (Parser.ID prefix) - | tkn -> - let next_token_start = (Lexer.region lexbuf).Source.left in - if pos_eq_cursor next_token_start - || pos_past_cursor next_token_start - then Some (ident, "") - else loop tkn) + let next_token = next () in + let next_token_start = (Lexer.region lexbuf).left in + if pos_eq_cursor next_token_start + || pos_past_cursor next_token_start + then Some (ident, "") + else + (match next_token with + | Parser.EOF -> Some (ident, "") + | Parser.ID prefix -> + let next_token_start = (Lexer.region lexbuf).left in + let next_token_end = (Lexer.region lexbuf).right in + if pos_eq_cursor next_token_start + || pos_past_cursor next_token_start + then Some (ident, "") + else if pos_eq_cursor next_token_end + then Some (ident, prefix) + else loop (Parser.ID prefix) + | tkn -> loop tkn) | tkn -> loop tkn) | Parser.EOF -> None | _ -> loop (next ()) in diff --git a/src/languageServer/completion_test.ml b/src/languageServer/completion_test.ml index 078dbc4ac27..381c74e3e3e 100644 --- a/src/languageServer/completion_test.ml +++ b/src/languageServer/completion_test.ml @@ -64,6 +64,10 @@ let%test "it handles immediately following single character tokens" = let%test "it handles qualifier + partial identifier" = prefix_test_case "Stack.so|" (Some ("Stack", "so")) +let%test "it handles qualifiers following the cursor" = + prefix_test_case "List.| Option" (Some ("List", "")) + && prefix_test_case "List.fil| Option" (Some ("List", "fil")) + let%test "it handles multiline files" = prefix_test_case {|Stak. From 7cea51ba9d151d862525f4ed808dfb02a1f99c65 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 18 Dec 2019 12:12:59 +0100 Subject: [PATCH 0849/1176] Ropy texts: Introduce concat heap operator (#985) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Create a RTS text.c module (imported, but unused) * stash * Use basically all text operations into text.c which removes a lot of hairy Wasm code from the backend, and also opens the path towards smarter implementations in `text.c` * The null byte is valid utf8 hat tip to @ggreif’s randomized tests that caught this. * Constant, not linear * Ropy texts: Introduce concat heap operator and update operations in `text.c` to use it. A test case checks that we can now build huge strings based on sharing. The implementation enforces a hard limit of 2^30 bytes, though. The code uses stack space liberally. I am not sure how much of a problem that is. If it is, we might have to revisit some of the algorithms. * Update rts/text.c Co-Authored-By: Claudio Russo * Update rts/text.c Co-Authored-By: Claudio Russo * Update rts/text.c Co-Authored-By: Claudio Russo * Typos * Update rts/text.c Co-Authored-By: Gabor Greif * Update rts/text.c Co-Authored-By: Gabor Greif * Update rts/text.c Co-Authored-By: Gabor Greif * Update rts/text.c Co-Authored-By: Gabor Greif * Move alloc_blob into rts.c * Update rts/text.c Co-Authored-By: Gabor Greif * Apply suggestions from code review Co-Authored-By: Gabor Greif --- rts/rts.h | 2 +- rts/text.c | 186 ++++++++++++++++++++++++++++++++-------- src/codegen/compile.ml | 25 ++++++ test/run/huge-string.mo | 17 ++++ test/run/text-concat.mo | 25 +++++- test/run/text-iter.mo | 4 +- 6 files changed, 221 insertions(+), 38 deletions(-) create mode 100644 test/run/huge-string.mo diff --git a/rts/rts.h b/rts/rts.h index 2b36cbc4d0e..4e04d54045e 100644 --- a/rts/rts.h +++ b/rts/rts.h @@ -39,7 +39,6 @@ enum as_heap_tag { TAG_OBJECT = 1, TAG_OBJIND = 2, TAG_ARRAY = 3, - TAG_REFERENCE = 4, TAG_INT = 5, TAG_MUTBOX = 6, TAG_CLOSURE = 7, @@ -49,6 +48,7 @@ enum as_heap_tag { TAG_INDIRECTION = 11, TAG_SMALLWORD = 12, TAG_BIGINT = 13, + TAG_CONCAT = 14, }; /** Functions imported from the Motoko RTS */ diff --git a/rts/text.c b/rts/text.c index 0452a1d0fa3..b31dcf67d59 100644 --- a/rts/text.c +++ b/rts/text.c @@ -23,11 +23,41 @@ From then on, there are stretch goals like: #include "rts.h" typedef as_ptr blob_t; // a skewed pointer to a Blob heap object -typedef as_ptr text_t; // a skewed pointer to a Blob (or, later, Concat) heap object +typedef as_ptr text_t; // a skewed pointer to a Blob or Concat heap object + +/* +Layout of a concat node: + + ┌─────┬─────────┬───────┬───────┐ + │ tag │ n_bytes │ text1 │ text2 │ + └─────┴─────────┴───────┴───────┘ + +Note that CONCAT_LEN and BLOB_LEN are identical, so no need to check the +tag to know the size of the text. +*/ + +#define CONCAT_WORDS 4 +#define CONCAT_LEN(p) (FIELD(p,1)) +#define CONCAT_ARG1(p) (FIELD(p,2)) +#define CONCAT_ARG2(p) (FIELD(p,3)) + + +#define MAX_STR_SIZE ((1<<30)-1) +// strings smaller than this _must_ be blobs +// You can set this to MAX_STR_SIZE to disable the use of ropes completely, +// e.g. for debugging +#define MIN_CONCAT_SIZE (9) + +blob_t alloc_text_blob(size_t n) { + if (n > MAX_STR_SIZE) { + rts_trap_with("alloc_blob: Text too large"); + } + return alloc_blob(n); +} // Create export text_t text_of_ptr_size(const char *buf, size_t n) { - as_ptr r = alloc_blob(n); + as_ptr r = alloc_text_blob(n); as_memcpy(BLOB_PAYLOAD(r), buf, n); return r; } @@ -40,22 +70,51 @@ text_t text_of_cstr(const char * const s) { // Concat export text_t text_concat(text_t s1, text_t s2) { + // empty strings are ignored + if (BLOB_LEN(s1) == 0) return s2; + if (BLOB_LEN(s2) == 0) return s1; uint32_t n1 = BLOB_LEN(s1); uint32_t n2 = BLOB_LEN(s2); - as_ptr r = alloc_blob(n1 + n2); - as_memcpy(BLOB_PAYLOAD(r), BLOB_PAYLOAD(s1), n1); - as_memcpy(BLOB_PAYLOAD(r) + n1, BLOB_PAYLOAD(s2), n2); + uint32_t n = n1 + n2; + // short texts are copied into a single blob + if (n < MIN_CONCAT_SIZE) { + as_ptr r = alloc_text_blob(n1 + n2); + as_memcpy(BLOB_PAYLOAD(r), BLOB_PAYLOAD(s1), n1); + as_memcpy(BLOB_PAYLOAD(r) + n1, BLOB_PAYLOAD(s2), n2); + return r; + } + // Check max size + if (n > MAX_STR_SIZE) { + rts_trap_with("text_concat: Text too large"); + } + // Create concat node + as_ptr r = alloc_words(CONCAT_WORDS); + TAG(r) = TAG_CONCAT; + CONCAT_LEN(r) = n; + CONCAT_ARG1(r) = s1; + CONCAT_ARG2(r) = s2; return r; } -// straighten into contiguous memory, if needed (e.g. for system calls) -export blob_t blob_of_text(text_t s) { - return s; +// write all data into a buffer (must have the right size) +export void text_to_buf(text_t s, char *buf) { + if (TAG(s) == TAG_BLOB) { + as_memcpy(buf, BLOB_PAYLOAD(s), BLOB_LEN(s)); + } else { + text_to_buf(CONCAT_ARG1(s), buf); + text_to_buf(CONCAT_ARG2(s), buf + BLOB_LEN(CONCAT_ARG1(s))); + } } -// similarly, but writing into a buffer (must have the right size) -export void text_to_buf(text_t s, char *buf) { - as_memcpy(buf, BLOB_PAYLOAD(s), BLOB_LEN(s)); +// straighten into contiguous memory, if needed (e.g. for system calls) +export blob_t blob_of_text(text_t s) { + if (TAG(s) == TAG_BLOB) { + return s; + } else { + as_ptr r = alloc_text_blob(CONCAT_LEN(s)); + text_to_buf(s, BLOB_PAYLOAD(r)); + return r; + } } export uint32_t text_size(text_t s) { @@ -63,7 +122,7 @@ export uint32_t text_size(text_t s) { } // Compare -export int text_compare(text_t s1, text_t s2) { +export int blob_compare(text_t s1, text_t s2) { uint32_t n1 = BLOB_LEN(s1); uint32_t n2 = BLOB_LEN(s2); uint32_t n = n1 < n2 ? n1 : n2; @@ -77,12 +136,57 @@ export int text_compare(text_t s1, text_t s2) { } } +// compares the texts from the given offset on for the given number of bytes +// all assumed to be in range +static int text_compare_range(text_t s1, size_t offset1, text_t s2, size_t offset2, size_t n) { + // strip off left legs if range is in the right leg + if (TAG(s1) == TAG_CONCAT && BLOB_LEN(CONCAT_ARG1(s1)) <= offset1) { + return text_compare_range(CONCAT_ARG2(s1), offset1 - BLOB_LEN(CONCAT_ARG1(s1)), s2, offset2, n); + } + if (TAG(s2) == TAG_CONCAT && BLOB_LEN(CONCAT_ARG1(s2)) <= offset2) { + return text_compare_range(s1, offset1, CONCAT_ARG2(s2), offset2 - BLOB_LEN(CONCAT_ARG1(s2)), n); + } + // strip off rights legs if range is in the left leg + if (TAG(s1) == TAG_CONCAT && BLOB_LEN(CONCAT_ARG1(s1)) >= offset1 + n ) { + return text_compare_range(CONCAT_ARG1(s1), offset1, s2, offset2, n); + } + if (TAG(s2) == TAG_CONCAT && BLOB_LEN(CONCAT_ARG1(s2)) >= offset2 + n) { + return text_compare_range(s1, offset1, CONCAT_ARG1(s2), offset2, n); + } + // Decompose concats + if (TAG(s1) == TAG_CONCAT) { + uint32_t n1 = BLOB_LEN(CONCAT_ARG1(s1)) - offset1; + int r1 = text_compare_range(CONCAT_ARG1(s1), offset1, s2, offset2, n1); + if (r1 != 0) return r1; + else return text_compare_range(CONCAT_ARG2(s1), 0, s2, offset2 + n1, n - n1); + } + if (TAG(s2) == TAG_CONCAT) { + uint32_t n1 = BLOB_LEN(CONCAT_ARG1(s2)) - offset2; + int r1 = text_compare_range(s1, offset1, CONCAT_ARG1(s2), offset2, n1); + if (r1 != 0) return r1; + else return text_compare_range(s1, offset1 + n1, CONCAT_ARG2(s2), 0, n - n1); + } + // now both are blobs + return as_memcmp(BLOB_PAYLOAD(s1) + offset1, BLOB_PAYLOAD(s2) + offset2, n); +} + +export int text_compare(text_t s1, text_t s2) { + uint32_t n1 = BLOB_LEN(s1); + uint32_t n2 = BLOB_LEN(s2); + uint32_t n = n1 < n2 ? n1 : n2; + int r = text_compare_range(s1, 0, s2, 0, n); + if (r != 0) return r; + if (n1 > n) return 1; + if (n2 > n) return -1; + return 0; +} + // Stuff that deals with characters -// decodes the character at position n in the array -// returns the character, and updates n -// based on https://gist.github.com/tylerneylon/9773800 -uint32_t decode_code_point(char *s, size_t *n) { +// decodes the character at pointer +// returns the character, the size via the out parameter +static uint32_t decode_code_point(char *s, size_t *n) { + *n = 0; int k = s[*n] ? __builtin_clz(~(s[*n] << 24)) : 0; // Count # of leading 1 bits. int mask = (1 << (8 - k)) - 1; // All 1's with k leading 0's. uint32_t value = s[*n] & mask; @@ -95,15 +199,19 @@ uint32_t decode_code_point(char *s, size_t *n) { // Length in characters export uint32_t text_len(text_t s) { - char *p = BLOB_PAYLOAD(s); - size_t n = 0; - uint32_t c = 0; - while (n < BLOB_LEN(s)) { - int k = p[n] ? __builtin_clz(~(p[n] << 24)) : 0; // Count # of leading 1 bits. - n += k ? k : 1; - c += 1; + if (TAG(s) == TAG_BLOB) { + char *p = BLOB_PAYLOAD(s); + size_t n = 0; + uint32_t c = 0; + while (n < BLOB_LEN(s)) { + int k = p[n] ? __builtin_clz(~(p[n] << 24)) : 0; // Count # of leading 1 bits. + n += k ? k : 1; + c += 1; + } + return c; + } else { + return text_len(CONCAT_ARG1(s)) + text_len(CONCAT_ARG2(s)); } - return c; } // Text from Char @@ -119,7 +227,7 @@ export text_t text_singleton(uint32_t code) { } val[val_index++] = (code & lead_byte_max) | (~lead_byte_max << 1); - as_ptr r = alloc_blob(val_index); + as_ptr r = alloc_text_blob(val_index); char *p = BLOB_PAYLOAD(r); while (val_index--) { *p = val[val_index]; @@ -132,14 +240,16 @@ export text_t text_singleton(uint32_t code) { // Iterators -// Currently a vanilla tuple: -// First component the array to the text -// Second the index into the array (shifted by two for GC's sake) +// The iterator needs to point to a specific position in the tree // -// TODO: do we have to worry about texts longer than 2^30 bytes -// (and thus shifting is // bad) +// This is currently a simple tuple: +// - First component the array to the whole text +// - Second the index into the array (shifted by two for GC's sake) // -// Eventually, this will be a pointer into a tree or something. +// This requires indexing into the tree upon each call to step, which +// is not great, especially if the trees are not balanced. +// Ideally, the iterator would contain the whole path from the root to the +// node… but one step at a time. typedef as_ptr text_iter_t; // the data structure used to iterate a text value #define TEXT_ITER_TEXT(p) (ARRAY_FIELD(p,0)) @@ -147,7 +257,6 @@ typedef as_ptr text_iter_t; // the data structure used to iterate a text value export text_iter_t text_iter(text_t s) { - // Maybe use a dedicated heap type instead of a vanilla tuple? as_ptr i = alloc_words(ARRAY_HEADER_SIZE + 2); TAG(i) = TAG_ARRAY; TEXT_ITER_TEXT(i) = s; @@ -159,12 +268,21 @@ export uint32_t text_iter_done(text_iter_t i) { return (TEXT_ITER_POS(i) >> 2) >= BLOB_LEN(TEXT_ITER_TEXT(i)); } +// pointer into the leaf at the given byte position +char *text_pos(text_t s, size_t offset) { + if (TAG(s) == TAG_BLOB) return (BLOB_PAYLOAD(s) + offset); + uint32_t n1 = BLOB_LEN(CONCAT_ARG1(s)); + if (offset < n1) return text_pos(CONCAT_ARG1(s), offset); + else return text_pos(CONCAT_ARG2(s), offset - n1); +} + export uint32_t text_iter_next(text_iter_t i) { if (text_iter_done(i)) { rts_trap_with("text_iter_next: Iter already done"); } size_t n = TEXT_ITER_POS(i) >> 2; - uint32_t c = decode_code_point(BLOB_PAYLOAD(TEXT_ITER_TEXT(i)), &n); - TEXT_ITER_POS(i) = n << 2; + size_t step = 0; + uint32_t c = decode_code_point(text_pos(TEXT_ITER_TEXT(i), n), &step); + TEXT_ITER_POS(i) = (n+step) << 2; return c; } diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 63a3cadd40b..752e27616ab 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -983,6 +983,7 @@ module Tagged = struct | Indirection | SmallWord (* Contains a 32 bit unsigned number *) | BigInt + | Concat (* String concatenation, used by rts/text.c *) (* Let's leave out tag 0 to trap earlier on invalid memory *) let int_of_tag = function @@ -998,6 +999,7 @@ module Tagged = struct | Indirection -> 11l | SmallWord -> 12l | BigInt -> 13l + | Concat -> 14l (* The tag *) let header_size = 1l @@ -2494,6 +2496,18 @@ module Text = struct Most of the heavy lifting around text values is in rts/text.c *) + (* The layout of a concatenation node is + + ┌─────┬─────────┬───────┬───────┐ + │ tag │ n_bytes │ text1 │ text2 │ + └─────┴─────────┴───────┴───────┘ + + This is internal to rts/text.c, with the exception of GC-related code. + *) + + let concat_field1 = Int32.add Tagged.header_size 1l + let concat_field2 = Int32.add Tagged.header_size 2l + let of_ptr_size env = E.call_import env "rts" "text_of_ptr_size" let concat env = @@ -3050,6 +3064,8 @@ module HeapTraversal = struct get_x ^^ Heap.load_field Closure.len_field ^^ compile_add_const Closure.header_size + ; Tagged.Concat, + compile_unboxed_const 4l ] (* Indirections have unknown size. *) ) @@ -3143,6 +3159,15 @@ module HeapTraversal = struct set_ptr_loc ^^ code ) + ; Tagged.Concat, + get_x ^^ + compile_add_const (Int32.mul Heap.word_size Text.concat_field1) ^^ + set_ptr_loc ^^ + code ^^ + get_x ^^ + compile_add_const (Int32.mul Heap.word_size Text.concat_field2) ^^ + set_ptr_loc ^^ + code ] end (* HeapTraversal *) diff --git a/test/run/huge-string.mo b/test/run/huge-string.mo new file mode 100644 index 00000000000..18b1cf6997b --- /dev/null +++ b/test/run/huge-string.mo @@ -0,0 +1,17 @@ +/* +This uses repeated self-concatenation to build a huge string +that would fill up most of the memory if implemented naively. +It then checks that heap usage is actually not too bad, +showing that string concatenation works as a tree with sharing. +*/ + +var s = "Badger"; +let n = 27; +for (i in range(1,n)) { + s := s # s; +}; +assert(rts_heap_size() < 2_000); + +//SKIP run +//SKIP run-low +//SKIP run-ir diff --git a/test/run/text-concat.mo b/test/run/text-concat.mo index b38af7d5a3f..e375ff0ec2c 100644 --- a/test/run/text-concat.mo +++ b/test/run/text-concat.mo @@ -1 +1,24 @@ -assert ("Hello " # "World!" == "Hello World!") +assert ("Hello " # "World!" == "Hello World!"); + +assert ( + "This is a test of string " # "concatentation" + == + "This is a " # "test of string concatentation" +); +assert ( + "This is a " # "test of string concatentation" + == + "This is a test of string " # "concatentation" +); + +assert ( + "This is a test of string " # "concatentation" + < + "This is a " # "test of string concatentation with " # "more text" +); + +assert ( + "This is a " # "test of string concatentation with " # "more text" + > + "This is a test of string " # "concatentation" +); diff --git a/test/run/text-iter.mo b/test/run/text-iter.mo index 38fc8a9f253..a26a4e74a18 100644 --- a/test/run/text-iter.mo +++ b/test/run/text-iter.mo @@ -1,4 +1,4 @@ -let s = "hello world!"; +let s = "hello " # "world!"; assert(s.len() == 12); debugPrint "via `debugPrint`:"; @@ -24,7 +24,7 @@ for (a in s.chars()) { }; debugPrint ""; -let russian = "Приветствую, мир!\n"; +let russian = "Приветствую," # " мир!\n"; assert(russian.len() == 18); debugPrint "via iteration and `debugPrintChar` (Unicode): #3"; From 948a262fa8ce9d0663a275c5182f2e85a2007cfa Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Wed, 18 Dec 2019 15:16:49 +0100 Subject: [PATCH 0850/1176] make alloc_text_blob internal (#1053) --- rts/text.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rts/text.c b/rts/text.c index b31dcf67d59..f72b4a4c94b 100644 --- a/rts/text.c +++ b/rts/text.c @@ -48,7 +48,7 @@ tag to know the size of the text. // e.g. for debugging #define MIN_CONCAT_SIZE (9) -blob_t alloc_text_blob(size_t n) { +static blob_t alloc_text_blob(size_t n) { if (n > MAX_STR_SIZE) { rts_trap_with("alloc_blob: Text too large"); } From 88c9f4944013239bdc928e36190369cdbaea6cf0 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 18 Dec 2019 19:16:23 +0000 Subject: [PATCH 0851/1176] Fix for Issue #1051 (Implement IgnoreD) (#1054) * implement IgnoreD; WIP * check don't infer exp in IgnoreD --- src/lowering/desugar.ml | 2 + src/mo_def/arrange.ml | 1 + src/mo_def/syntax.ml | 3 +- src/mo_frontend/definedness.ml | 2 +- src/mo_frontend/effect.ml | 1 + src/mo_frontend/parser.mly | 4 +- src/mo_frontend/static.ml | 2 +- src/mo_frontend/traversals.ml | 83 +++++++++++++++++---------------- src/mo_frontend/typing.ml | 14 +++--- src/mo_interpreter/interpret.ml | 3 ++ 10 files changed, 63 insertions(+), 52 deletions(-) diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 026803de764..5a4c07e2924 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -275,6 +275,7 @@ and block force_unit ds = | false, S.LetD (p', e') -> let x = fresh_var "x" (e'.note.S.note_typ) in (extra @ List.map dec prefix @ [letD x (exp e'); letP (pat p') x], x) + | _ , S.IgnoreD _ (* redundant, but explicit *) | _, _ -> (extra @ List.map dec ds, tupE []) @@ -295,6 +296,7 @@ and dec d = { (phrase' dec' d) with note = () } and dec' at n d = match d with | S.ExpD e -> (expD (exp e)).it + | S.IgnoreD e -> I.LetD ({ it = I.WildP; at = e.at; note = T.Any}, exp e) | S.LetD (p, e) -> let p' = pat p in let e' = exp e in diff --git a/src/mo_def/arrange.ml b/src/mo_def/arrange.ml index 82bc35a460b..a1d44e3f869 100644 --- a/src/mo_def/arrange.ml +++ b/src/mo_def/arrange.ml @@ -159,6 +159,7 @@ and typ t = match t.it with and dec d = match d.it with | ExpD e -> "ExpD" $$ [exp e ] + | IgnoreD e -> "IgnoreD" $$ [exp e ] | LetD (p, e) -> "LetD" $$ [pat p; exp e] | VarD (x, e) -> "VarD" $$ [id x; exp e] | TypD (x, tp, t) -> diff --git a/src/mo_def/syntax.ml b/src/mo_def/syntax.ml index 1e4478cffb8..2b56259be44 100644 --- a/src/mo_def/syntax.ml +++ b/src/mo_def/syntax.ml @@ -173,7 +173,8 @@ and case' = {pat : pat; exp : exp} and dec = (dec', typ_note) Source.annotated_phrase and dec' = - | ExpD of exp (* plain expression *) + | ExpD of exp (* plain unit expression *) + | IgnoreD of exp (* plain any expression *) | LetD of pat * exp (* immutable *) | VarD of id * exp (* mutable *) | TypD of typ_id * typ_bind list * typ (* type *) diff --git a/src/mo_frontend/definedness.ml b/src/mo_frontend/definedness.ml index 6a087762b2b..62943a5b55e 100644 --- a/src/mo_frontend/definedness.ml +++ b/src/mo_frontend/definedness.ml @@ -156,7 +156,7 @@ and exp_fields msgs efs : f = decs msgs (List.map (fun ef -> ef.it.dec) efs) and dec msgs d = match d.it with - | ExpD e -> (exp msgs e, S.empty) + | ExpD e | IgnoreD e -> (exp msgs e, S.empty) | LetD (p, e) -> pat msgs p +++ exp msgs e | VarD (i, e) -> (M.empty, S.singleton i.it) +++ exp msgs e | TypD (i, tp, t) -> (M.empty, S.empty) diff --git a/src/mo_frontend/effect.ml b/src/mo_frontend/effect.ml index 710605a8a7f..d3f925841d4 100644 --- a/src/mo_frontend/effect.ml +++ b/src/mo_frontend/effect.ml @@ -107,6 +107,7 @@ and effect_dec dec = and infer_effect_dec dec = match dec.it with | ExpD e + | IgnoreD e | LetD (_,e) | VarD (_, e) -> effect_exp e diff --git a/src/mo_frontend/parser.mly b/src/mo_frontend/parser.mly index 621999e29e7..f9e8ddafaec 100644 --- a/src/mo_frontend/parser.mly +++ b/src/mo_frontend/parser.mly @@ -202,7 +202,7 @@ seplist1(X, SEP) : %inline sort_pat : | (* empty *) { Type.Local @@ no_region } - | SHARED m=mode_opt op=sort_pat_opt { Type.Shared (m,op (at $sloc)) @@ at $sloc } + | SHARED m=mode_opt op=sort_pat_opt { Type.Shared (m, op (at $sloc)) @@ at $sloc } | QUERY op=sort_pat_opt { Type.Shared (Type.Query, op (at $sloc)) @@ at $sloc } (* Paths *) @@ -656,7 +656,7 @@ dec_nonvar : if s.it = Type.Actor then List.map share_expfield efs else efs in ClassD(xf "class" $sloc, tps, p, t, s, x, efs') @? at $sloc } | IGNORE e=exp(ob) - { LetD(WildP @! no_region, AnnotE (e, PrimT "Any" @! no_region) @? no_region) @? at $sloc } + { IgnoreD e @? at $sloc } dec : | d=dec_var diff --git a/src/mo_frontend/static.ml b/src/mo_frontend/static.ml index c5553cfe8a4..bd4195127c1 100644 --- a/src/mo_frontend/static.ml +++ b/src/mo_frontend/static.ml @@ -82,7 +82,7 @@ and fields m efs = List.iter (fun ef -> dec m ef.it.dec) efs and dec m d = match d.it with | TypD _ | ClassD _ -> () - | ExpD e -> exp m e + | ExpD e | IgnoreD e -> exp m e | LetD (p, e) -> triv m p; exp m e | VarD _ -> err m d.at diff --git a/src/mo_frontend/traversals.ml b/src/mo_frontend/traversals.ml index 825b213e6d4..c1a43335c73 100644 --- a/src/mo_frontend/traversals.ml +++ b/src/mo_frontend/traversals.ml @@ -4,75 +4,76 @@ open Source let rec over_exp (f : exp -> exp) (exp : exp) : exp = match exp.it with | ImportE _ | PrimE _ | VarE _ | LitE _ | ActorUrlE _ -> f exp - | UnE (x, y, exp1) -> f { exp with it=UnE (x, y, over_exp f exp1) } - | ShowE (x, exp1) -> f { exp with it=ShowE (x, over_exp f exp1) } - | ProjE (exp1, x) -> f { exp with it=ProjE (over_exp f exp1, x) } - | OptE exp1 -> f { exp with it=OptE (over_exp f exp1) } - | TagE (x, exp1) -> f { exp with it=TagE (x, over_exp f exp1) } - | DotE (exp1, x) -> f { exp with it=DotE (over_exp f exp1, x) } - | NotE exp1 -> f { exp with it=NotE (over_exp f exp1) } - | AssertE exp1 -> f { exp with it=AssertE (over_exp f exp1) } - | LabelE (x, y, exp1) -> f { exp with it=LabelE (x, y, over_exp f exp1) } - | BreakE (x, exp1) -> f { exp with it=BreakE (x, over_exp f exp1) } - | RetE exp1 -> f { exp with it=RetE (over_exp f exp1) } - | AnnotE (exp1, x) -> f { exp with it=AnnotE (over_exp f exp1, x) } - | AsyncE exp1 -> f { exp with it=AsyncE (over_exp f exp1) } - | AwaitE exp1 -> f { exp with it=AwaitE (over_exp f exp1) } - | ThrowE exp1 -> f { exp with it=ThrowE (over_exp f exp1) } + | UnE (x, y, exp1) -> f { exp with it = UnE (x, y, over_exp f exp1) } + | ShowE (x, exp1) -> f { exp with it = ShowE (x, over_exp f exp1) } + | ProjE (exp1, x) -> f { exp with it = ProjE (over_exp f exp1, x) } + | OptE exp1 -> f { exp with it = OptE (over_exp f exp1) } + | TagE (x, exp1) -> f { exp with it = TagE (x, over_exp f exp1) } + | DotE (exp1, x) -> f { exp with it = DotE (over_exp f exp1, x) } + | NotE exp1 -> f { exp with it = NotE (over_exp f exp1) } + | AssertE exp1 -> f { exp with it = AssertE (over_exp f exp1) } + | LabelE (x, y, exp1) -> f { exp with it = LabelE (x, y, over_exp f exp1) } + | BreakE (x, exp1) -> f { exp with it = BreakE (x, over_exp f exp1) } + | RetE exp1 -> f { exp with it = RetE (over_exp f exp1) } + | AnnotE (exp1, x) -> f { exp with it = AnnotE (over_exp f exp1, x) } + | AsyncE exp1 -> f { exp with it = AsyncE (over_exp f exp1) } + | AwaitE exp1 -> f { exp with it = AwaitE (over_exp f exp1) } + | ThrowE exp1 -> f { exp with it = ThrowE (over_exp f exp1) } | BinE (x, exp1, y, exp2) -> - f { exp with it=BinE (x, over_exp f exp1, y, over_exp f exp2) } + f { exp with it = BinE (x, over_exp f exp1, y, over_exp f exp2) } | IdxE (exp1, exp2) -> - f { exp with it=IdxE (over_exp f exp1, over_exp f exp2) } + f { exp with it = IdxE (over_exp f exp1, over_exp f exp2) } | RelE (x, exp1, y, exp2) -> - f { exp with it=RelE (x, over_exp f exp1, y, over_exp f exp2) } + f { exp with it = RelE (x, over_exp f exp1, y, over_exp f exp2) } | AssignE (exp1, exp2) -> - f { exp with it=AssignE (over_exp f exp1, over_exp f exp2) } + f { exp with it = AssignE (over_exp f exp1, over_exp f exp2) } | CallE (exp1, x, exp2) -> - f { exp with it=CallE (over_exp f exp1, x, over_exp f exp2) } + f { exp with it = CallE (over_exp f exp1, x, over_exp f exp2) } | AndE (exp1, exp2) -> - f { exp with it=AndE (over_exp f exp1, over_exp f exp2) } + f { exp with it = AndE (over_exp f exp1, over_exp f exp2) } | OrE (exp1, exp2) -> - f { exp with it=OrE (over_exp f exp1, over_exp f exp2) } + f { exp with it = OrE (over_exp f exp1, over_exp f exp2) } | WhileE (exp1, exp2) -> - f { exp with it=WhileE (over_exp f exp1, over_exp f exp2) } + f { exp with it = WhileE (over_exp f exp1, over_exp f exp2) } | LoopE (exp1, exp2_opt) -> - f { exp with it=LoopE (over_exp f exp1, Lib.Option.map (over_exp f) exp2_opt) } + f { exp with it = LoopE (over_exp f exp1, Lib.Option.map (over_exp f) exp2_opt) } | ForE (x, exp1, exp2) -> - f { exp with it=ForE (x, over_exp f exp1, over_exp f exp2) } + f { exp with it = ForE (x, over_exp f exp1, over_exp f exp2) } | DebugE exp1 -> - f { exp with it=DebugE (over_exp f exp1) } + f { exp with it = DebugE (over_exp f exp1) } | TupE exps -> - f { exp with it=TupE (List.map (over_exp f) exps) } + f { exp with it = TupE (List.map (over_exp f) exps) } | ArrayE (x, exps) -> - f { exp with it=ArrayE (x, List.map (over_exp f) exps) } + f { exp with it = ArrayE (x, List.map (over_exp f) exps) } | BlockE ds -> - f { exp with it=BlockE (List.map (over_dec f) ds) } + f { exp with it = BlockE (List.map (over_dec f) ds) } | ObjE (x, efs) -> - f { exp with it=ObjE (x, List.map (over_exp_field f) efs) } + f { exp with it = ObjE (x, List.map (over_exp_field f) efs) } | IfE (exp1, exp2, exp3) -> - f { exp with it=IfE(over_exp f exp1, over_exp f exp2, over_exp f exp3) } + f { exp with it = IfE(over_exp f exp1, over_exp f exp2, over_exp f exp3) } | TryE (exp1, cases) -> - f { exp with it=TryE (over_exp f exp1, List.map (over_case f) cases) } + f { exp with it = TryE (over_exp f exp1, List.map (over_case f) cases) } | SwitchE (exp1, cases) -> - f { exp with it=SwitchE (over_exp f exp1, List.map (over_case f) cases) } + f { exp with it = SwitchE (over_exp f exp1, List.map (over_case f) cases) } | FuncE (a, b, c, d, g, e) -> - f { exp with it=FuncE (a, b, c, d, g, over_exp f e) } + f { exp with it = FuncE (a, b, c, d, g, over_exp f e) } and over_dec (f : exp -> exp) (d : dec) : dec = match d.it with | TypD _ -> d - | ExpD e -> { d with it=ExpD (over_exp f e)} + | ExpD e -> { d with it = ExpD (over_exp f e)} + | IgnoreD e -> { d with it = IgnoreD (over_exp f e)} | VarD (x, e) -> - { d with it=VarD (x, over_exp f e)} + { d with it = VarD (x, over_exp f e)} | LetD (x, e) -> - { d with it=LetD (x, over_exp f e)} + { d with it = LetD (x, over_exp f e)} | ClassD (a, b, c, d1, e, g, efs) -> - { d with it=ClassD (a, b, c, d1, e, g, List.map (over_exp_field f) efs)} + { d with it = ClassD (a, b, c, d1, e, g, List.map (over_exp_field f) efs)} and over_exp_field (f : exp -> exp) (ef : exp_field) : exp_field = - { ef with it={ ef.it with dec=over_dec f ef.it.dec } } + { ef with it = { ef.it with dec = over_dec f ef.it.dec } } and over_case (f : exp -> exp) (case : case) : case = - { case with it={ case.it with exp=over_exp f case.it.exp } } + { case with it = { case.it with exp = over_exp f case.it.exp } } and over_prog (f : exp -> exp) (prog : prog) : prog = - { prog with it=List.map (over_dec f) prog.it } + { prog with it = List.map (over_dec f) prog.it } diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index b682bb57f4a..bd380d1a80c 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -143,8 +143,7 @@ let in_shared_async env = let in_oneway_ignore env = match env.context with | _ :: - AnnotE _ :: - BlockE [ {it = LetD ({ it = WildP;_}, _); _} ] :: + BlockE [ {it = IgnoreD _; _} ] :: FuncE (_, {it = T.Shared _; _} , _, _, typ_opt, _) :: _ -> (match typ_opt with @@ -1389,7 +1388,7 @@ and pub_field field xs : region T.Env.t * region T.Env.t = and pub_dec dec xs : region T.Env.t * region T.Env.t = match dec.it with - | ExpD _ -> xs + | ExpD _ | IgnoreD _ -> xs | LetD (pat, _) -> pub_pat pat xs | VarD (id, _) -> pub_val_id id xs | ClassD (id, _, _, _, _, _, _) -> @@ -1540,6 +1539,9 @@ and infer_dec env dec : T.typ = | ExpD exp | LetD (_, exp) -> infer_exp env exp + | IgnoreD exp -> + if not env.pre then check_exp env T.Any exp; + T.unit | VarD (_, exp) -> if not env.pre then ignore (infer_exp env exp); T.unit @@ -1638,7 +1640,7 @@ and gather_block_decs env decs : Scope.t = and gather_dec env scope dec : Scope.t = match dec.it with - | ExpD _ -> scope + | ExpD _ | IgnoreD _ -> scope (* TODO: generalize beyond let = *) | LetD ( {it = VarP id; _}, @@ -1733,7 +1735,7 @@ and infer_dec_typdecs env dec : Scope.t = | T.Obj (_, _) as t' -> { Scope.empty with val_env = T.Env.singleton id.it t' } | _ -> { Scope.empty with val_env = T.Env.singleton id.it T.Pre } ) - | LetD _ | ExpD _ | VarD _ -> + | LetD _ | ExpD _ | IgnoreD _ | VarD _ -> Scope.empty | TypD (id, binds, typ) -> let c = T.Env.find id.it env.typs in @@ -1796,7 +1798,7 @@ and infer_block_valdecs env decs scope : Scope.t = and infer_dec_valdecs env dec : Scope.t = match dec.it with - | ExpD _ -> + | ExpD _ | IgnoreD _ -> Scope.empty (* TODO: generalize beyond let = *) | LetD ( diff --git a/src/mo_interpreter/interpret.ml b/src/mo_interpreter/interpret.ml index 6b1c6dbd7ce..6fd80af947e 100644 --- a/src/mo_interpreter/interpret.ml +++ b/src/mo_interpreter/interpret.ml @@ -813,6 +813,7 @@ and interpret_block env decs ro (k : V.value V.cont) = and declare_dec dec : val_env = match dec.it with | ExpD _ + | IgnoreD _ | TypD _ -> V.Env.empty | LetD (pat, _) -> declare_pat pat | VarD (id, _) -> declare_id id @@ -830,6 +831,8 @@ and interpret_dec env dec (k : V.value V.cont) = match dec.it with | ExpD exp -> interpret_exp env exp k + | IgnoreD exp -> + interpret_exp env exp (fun _v -> k V.unit) | LetD (pat, exp) -> interpret_exp env exp (fun v -> define_pat env pat v; From 6e4447b86ca3009f14c58456993b3fcb202f2dd3 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 18 Dec 2019 19:26:05 +0000 Subject: [PATCH 0852/1176] dec-bug repro & fix (#1050) * dec-bug repro * forgotten file with fix * Update src/mo_interpreter/interpret.ml --- src/mo_interpreter/interpret.ml | 7 ++++++- test/run/dec-bug.mo | 6 ++++++ 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 test/run/dec-bug.mo diff --git a/src/mo_interpreter/interpret.ml b/src/mo_interpreter/interpret.ml index 6fd80af947e..efac6697755 100644 --- a/src/mo_interpreter/interpret.ml +++ b/src/mo_interpreter/interpret.ml @@ -490,7 +490,12 @@ and interpret_exp_mut env exp (k : V.value V.cont) = ) ) | BlockE decs -> - interpret_block env decs None k + let k' = + if T.is_unit exp.note.note_typ (* TODO: peeking at types violates erasure semantics, revisit! *) + then (fun _v -> k V.unit) + else k + in + interpret_block env decs None k' | NotE exp1 -> interpret_exp env exp1 (fun v1 -> k (V.Bool (not (V.as_bool v1)))) | AndE (exp1, exp2) -> diff --git a/test/run/dec-bug.mo b/test/run/dec-bug.mo new file mode 100644 index 00000000000..9173e2d15b7 --- /dev/null +++ b/test/run/dec-bug.mo @@ -0,0 +1,6 @@ +func wrong() { for (i in range(0,1)) ignore 666 }; +wrong(); + +let () = (let _ = 1) : () ; + + From d6190dcccfabaa2b99e18232c7751b954569a9a5 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 18 Dec 2019 20:30:31 +0100 Subject: [PATCH 0853/1176] Clarify some wording in DFX-Interface (#1047) * Clarify some wording in DFX-Interface * Update design/DFX-Interface.md --- design/DFX-Interface.md | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/design/DFX-Interface.md b/design/DFX-Interface.md index 1007fc21390..ef2bb02c429 100644 --- a/design/DFX-Interface.md +++ b/design/DFX-Interface.md @@ -51,7 +51,7 @@ In order to compile a motoko file, `dfx` invokes `moc` with moc some/path/input.mo \ -o another/path/output.wasm \ { --package pkgname pkgpath } \ - { --actor-alias alias id } + { --actor-alias alias canisterhexid } [ --actor-idl actorpath ] in an environment where `MOC_RTS` points to the location of the Motoko runtime system. @@ -59,7 +59,7 @@ in an environment where `MOC_RTS` points to the location of the Motoko runtime s This _reads_ the following files * `some/path/input.mo` * any `.mo` file referenced by `some/path/input.mo`, either relatively, absolutely or via the provided package aliases - * for every actor import `ic:canisteridoralias` imported by any of the Motoko files, it reads `actorpath/canisteridoralias.mo`, see section Resolving Canister Ids below. + * for every actor import `ic:canisteridoralias` imported by any of the Motoko files, it reads `actorpath/canisterhexid.did`, see section Resolving Canister Ids below. * the given `mo-rts.wasm` file. No constraints are imposed where imported files reside (this may be refined to prevent relative imports from looking outside the project and the declared packages) @@ -76,7 +76,7 @@ As the previous point, but passing `--idl` to `moc`. Resolving Canister aliases -------------------------- -For every actor imported using `import "ic:alias"`, the Motoko compiler treats that as `import "ic:canisterid"`, if the command line flag `--actor-alias alias id` is given. +For every actor imported using `import "ic:alias"`, the Motoko compiler treats that as `import "ic:canisterhexid"`, if the command line flag `--actor-alias alias id` is given. The relation defined by the set of `--actor-alias` arguments must be left-unique and have disjoint range and domain (i.e. no `--actor-alias a b --actor-alias a c` or `--actor-alias a b --actor-alias b c` or even `--actor-alias a a`). @@ -89,7 +89,13 @@ After applying any aliases, the Motoko compiler assume these imports to refer to Resolving Canister types ------------------------ -For every actor imports using `import "ic:canisterid"` (or `import "ic:canisteralias"` if `canisteralias` resolves to `canisterid` as described above), the motoko compiler assumes the presence of a file `canisterid.did` in the actor idl path specified by `--actor-idl`. This files informs motoko about the interface of that canister, e.g. the output of `moc --idl` for a locally known canister, or the IDL file as fetched from the Internet Computer. +For every actor import using `import "ic:canisterhexid"` (or `import "ic:canisteralias"` if `canisteralias` resolves to `canisterhexid` as described above), the motoko compiler assumes the presence of a file `canisterhexid.did` in the actor idl path specified by `--actor-idl`. + +The `canisterid` here refers the “textual representation“ without the `ic:` prefix, but including the checksum. Note that this representation is unique. + +This files informs motoko about the interface of that canister. It could be the output of `moc --idl` for a locally known canister, or the IDL file as fetched from the Internet Computer, or created any other way. + + Compiling IDL Files to JS ------------------------- @@ -113,16 +119,12 @@ In order to start the language server, `dfx` invokes mo-ide --canister-main some/path/main.mo \ { --package pkgname pkgpath } \ - { --actor-alias alias id } + { --actor-alias alias canisterhexid } [ --actor-idl actorpath ] with `stdin` and `stdout` connected to the LSP client. - -This _reads_ `some/path/input.mo` and any `.mo` file referenced by -`some/path/input.mo`, either relatively, absolutely or via the provided package aliases. - -No constraints are imposed where these imported files reside (this may be refined to prevent relative imports from looking outside the project and the declared packages) +This may _read_ the same files as `moc` would. Listing dependencies -------------------- @@ -136,7 +138,8 @@ prints to the standard output all URLs _directly_ imported by mo:stdlib/List mo:other_package/Some/Module - + ic:ABCDE01A7 + ic:alias This _reads_ only `some/path/input.mo`, and writes no files. From 8efc57bbf5feba2cb476f97ec1769a418e7aa678 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 18 Dec 2019 22:00:36 +0000 Subject: [PATCH 0854/1176] merge with parent, rewrite test to avoid h.o. functions and pass --- test/run-drun/general_await.mo | 16 ++++++++++------ test/run-drun/general_await_implicit.mo | 16 +++++++++++----- test/run-drun/ok/scope-example-func.comp.ok | 2 -- .../ok/scope-example-func.ic-stub-run.ok | 7 ------- test/run-drun/ok/scope-example.comp.ok | 2 -- test/run-drun/ok/scope-example.ic-stub-run.ok | 7 ------- 6 files changed, 21 insertions(+), 29 deletions(-) delete mode 100644 test/run-drun/ok/scope-example-func.comp.ok delete mode 100644 test/run-drun/ok/scope-example-func.ic-stub-run.ok delete mode 100644 test/run-drun/ok/scope-example.comp.ok delete mode 100644 test/run-drun/ok/scope-example.ic-stub-run.ok diff --git a/test/run-drun/general_await.mo b/test/run-drun/general_await.mo index 22170af5cd4..9a77ffdcca9 100644 --- a/test/run-drun/general_await.mo +++ b/test/run-drun/general_await.mo @@ -28,12 +28,16 @@ actor Await { // Dynamic parallel waiting for acknowledgements public shared func DPA<@>() : async<@>() { -/* -let as: [async()] = Array_tabulate(10, func (_) { Ack<@>(); }); - for (a in as.vals()) { - await a; - }; -*/ + let os = Array_init(10, null); + for (i in os.keys()) { + os[i] := ? (Ack<@>()); + }; + for (o in os.vals()) { + switch o { + case (? a) await a; + case null (assert false); + }; + }; }; // Dynamic parallel waiting (with results) diff --git a/test/run-drun/general_await_implicit.mo b/test/run-drun/general_await_implicit.mo index 41c36537521..1ce3d3671aa 100644 --- a/test/run-drun/general_await_implicit.mo +++ b/test/run-drun/general_await_implicit.mo @@ -27,11 +27,17 @@ actor Await { // Dynamic parallel waiting for acknowledgements - public shared func DPA() : async () { - let as: [async()] = Array_tabulate(10, func (_) { Ack(); }); - for (a in as.vals()) { - await a; - }; + public shared func DPA() : async() { + let os = Array_init(10, null); + for (i in os.keys()) { + os[i] := ? (Ack()); + }; + for (o in os.vals()) { + switch o { + case (? a) await a; + case null (assert false); + }; + }; }; // Dynamic parallel waiting (with results) diff --git a/test/run-drun/ok/scope-example-func.comp.ok b/test/run-drun/ok/scope-example-func.comp.ok deleted file mode 100644 index 0d3974ebff8..00000000000 --- a/test/run-drun/ok/scope-example-func.comp.ok +++ /dev/null @@ -1,2 +0,0 @@ -scope-example-func.mo:16.19-16.20: type error, argument to await must be a call expression - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/scope-example-func.ic-stub-run.ok b/test/run-drun/ok/scope-example-func.ic-stub-run.ok deleted file mode 100644 index 93413930a05..00000000000 --- a/test/run-drun/ok/scope-example-func.ic-stub-run.ok +++ /dev/null @@ -1,7 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -← completed -→ update Test(0x4449444c0000) -Trap: EvalTrapError :0.1 "This call has already been responded to earlier" -← rejected (RC_CANISTER_REJECT): canister did not respond diff --git a/test/run-drun/ok/scope-example.comp.ok b/test/run-drun/ok/scope-example.comp.ok deleted file mode 100644 index f2e89350bfc..00000000000 --- a/test/run-drun/ok/scope-example.comp.ok +++ /dev/null @@ -1,2 +0,0 @@ -scope-example.mo:13.19-13.20: type error, argument to await must be a call expression - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/scope-example.ic-stub-run.ok b/test/run-drun/ok/scope-example.ic-stub-run.ok deleted file mode 100644 index 93413930a05..00000000000 --- a/test/run-drun/ok/scope-example.ic-stub-run.ok +++ /dev/null @@ -1,7 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -← completed -→ update Test(0x4449444c0000) -Trap: EvalTrapError :0.1 "This call has already been responded to earlier" -← rejected (RC_CANISTER_REJECT): canister did not respond From 73dd345df27ae0e049ce5c1c9320d3ab9f3dba26 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Thu, 19 Dec 2019 11:13:44 +0100 Subject: [PATCH 0855/1176] Typo in test (#1057) --- test/run-drun/overflow.mo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/run-drun/overflow.mo b/test/run-drun/overflow.mo index 1f37251088f..c5c40a9adfd 100644 --- a/test/run-drun/overflow.mo +++ b/test/run-drun/overflow.mo @@ -1,4 +1,4 @@ -// We have theses tests in run-drun because we want to check that certain +// We have these tests in run-drun because we want to check that certain // traps are happening, and a good way to test this is if a message gets // aborted. From 743fc61681fda0274d0077561e982706a4d3322e Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 19 Dec 2019 11:40:08 +0100 Subject: [PATCH 0856/1176] Ropes: Use an iterator with a linked list (#991) so that we don't have to traverse the whole tree upon every step. --- rts/rts.h | 4 +++ rts/text.c | 94 ++++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 70 insertions(+), 28 deletions(-) diff --git a/rts/rts.h b/rts/rts.h index 4e04d54045e..4189ced826c 100644 --- a/rts/rts.h +++ b/rts/rts.h @@ -33,6 +33,10 @@ typedef intptr_t as_ptr; #define ARRAY_LEN(p) (FIELD(p,1)) #define ARRAY_FIELD(p,n) (FIELD(p,ARRAY_HEADER_SIZE+n)) +#define TUPLE_HEADER_SIZE 2 +#define TUPLE_LEN(p) (FIELD(p,1)) +#define TUPLE_FIELD(p,n,t) (*(t *)(&(FIELD(p,TUPLE_HEADER_SIZE+n)))) + /* Heap tags. Needs to stay in sync with compile.ml */ enum as_heap_tag { TAG_INVALID = 0, diff --git a/rts/text.c b/rts/text.c index f72b4a4c94b..db8d938e618 100644 --- a/rts/text.c +++ b/rts/text.c @@ -242,47 +242,85 @@ export text_t text_singleton(uint32_t code) { // The iterator needs to point to a specific position in the tree // -// This is currently a simple tuple: -// - First component the array to the whole text -// - Second the index into the array (shifted by two for GC's sake) +// This is currently a simple triple: +// 1. a pointer to a current leaf (must be a BLOB) +// 2. index into that blob (shifted by two for GC's sake) +// 3. 0, or a pointer to a linked list of non-empty text values to do next +// +// The linked list (text_cont_t) is a tuple with +// 1. a pointer to the text_t +// 2. 0, or a pointer to the next list entry // -// This requires indexing into the tree upon each call to step, which -// is not great, especially if the trees are not balanced. -// Ideally, the iterator would contain the whole path from the root to the -// node… but one step at a time. -typedef as_ptr text_iter_t; // the data structure used to iterate a text value -#define TEXT_ITER_TEXT(p) (ARRAY_FIELD(p,0)) -#define TEXT_ITER_POS(p) (ARRAY_FIELD(p,1)) +typedef as_ptr text_iter_cont_t; +#define TEXT_CONT_TEXT(p) (TUPLE_FIELD(p,0,text_t)) +#define TEXT_CONT_NEXT(p) (TUPLE_FIELD(p,1,text_iter_cont_t)) +typedef as_ptr text_iter_t; // the data structure used to iterate a text value +#define TEXT_ITER_BLOB(p) (TUPLE_FIELD(p,0,blob_t)) +#define TEXT_ITER_POS(p) (TUPLE_FIELD(p,1,uint32_t)) +#define TEXT_ITER_TODO(p) (TUPLE_FIELD(p,2,text_iter_cont_t)) + + +// Find the leftmost leaf of a text, putting all the others onto a list, +// used to enforce the invariant about TEXT_ITER_BLOB to be a blob. +static blob_t find_leaf(text_t s, text_iter_cont_t *todo) { + while (TAG(s) == TAG_CONCAT) { + as_ptr c = alloc_words(TUPLE_HEADER_SIZE + 2); + TAG(c) = TAG_ARRAY; + TEXT_CONT_TEXT(c) = CONCAT_ARG2(s); + TEXT_CONT_NEXT(c) = *todo; + *todo = c; + s = CONCAT_ARG1(s); + } + return s; +} export text_iter_t text_iter(text_t s) { - as_ptr i = alloc_words(ARRAY_HEADER_SIZE + 2); + as_ptr i = alloc_words(TUPLE_HEADER_SIZE + 3); TAG(i) = TAG_ARRAY; - TEXT_ITER_TEXT(i) = s; TEXT_ITER_POS(i) = 0; + TEXT_ITER_TODO(i) = 0; + TEXT_ITER_BLOB(i) = find_leaf(s, &TEXT_ITER_TODO(i)); return i; } export uint32_t text_iter_done(text_iter_t i) { - return (TEXT_ITER_POS(i) >> 2) >= BLOB_LEN(TEXT_ITER_TEXT(i)); -} - -// pointer into the leaf at the given byte position -char *text_pos(text_t s, size_t offset) { - if (TAG(s) == TAG_BLOB) return (BLOB_PAYLOAD(s) + offset); - uint32_t n1 = BLOB_LEN(CONCAT_ARG1(s)); - if (offset < n1) return text_pos(CONCAT_ARG1(s), offset); - else return text_pos(CONCAT_ARG2(s), offset - n1); + size_t n = TEXT_ITER_POS(i) >> 2; + text_t s = TEXT_ITER_BLOB(i); + return n >= BLOB_LEN(s) && TEXT_ITER_TODO(i) == 0; } export uint32_t text_iter_next(text_iter_t i) { - if (text_iter_done(i)) { - rts_trap_with("text_iter_next: Iter already done"); - } size_t n = TEXT_ITER_POS(i) >> 2; - size_t step = 0; - uint32_t c = decode_code_point(text_pos(TEXT_ITER_TEXT(i), n), &step); - TEXT_ITER_POS(i) = (n+step) << 2; - return c; + text_t s = TEXT_ITER_BLOB(i); + + // If we are at the end, find the next iterator to use + if (n >= BLOB_LEN(s)) { + // this one is done, try next + text_iter_cont_t c = TEXT_ITER_TODO(i); + // are we done? + if (c == 0) rts_trap_with("text_iter_next: Iter already done"); + text_t s2 = TEXT_CONT_TEXT(c); + // if next one is a concat node, re-use both text iterator structures + // (avoids an allocation) + if (TAG(s2) == TAG_CONCAT) { + TEXT_ITER_POS(i) = 0; + TEXT_CONT_TEXT(i) = CONCAT_ARG2(s2); + TEXT_ITER_BLOB(i) = find_leaf(CONCAT_ARG1(s2), &TEXT_ITER_TODO(i)); + return text_iter_next(i); + // else remove that entry from the chain + } else { + TEXT_ITER_BLOB(i) = s2; + TEXT_ITER_POS(i) = 0; + TEXT_ITER_TODO(i) = TEXT_CONT_NEXT(c); + return text_iter_next(i); + } + } else { + // We are not at the end, so read the next character + size_t step = 0; + uint32_t c = decode_code_point(BLOB_PAYLOAD(s) + n, &step); + TEXT_ITER_POS(i) = (n+step) << 2; + return c; + } } From 43fec1e6ac322e407a074c79121d05b12e39ee78 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 19 Dec 2019 12:01:16 +0100 Subject: [PATCH 0857/1176] Implement --actor-alias (#1052) * Move package/idl/etc. argument parsers into Mo_config.Args * Implement --actor-alias including some refactoring around import resolution: * The argument parsers for the flags common to `moc` and `mo_ide` are moved to `Mo_config.Args`. * These flags are directly parsed into maps instead of association lists, with duplicate entries warned about early. (guess nothing was wrong with the old design either, though) * Aliases are now `canister:alias`, not `ic:alias`, to make it clear what is an alias and what not, as discussed on Slack. * The `DFX-Interface` file is updated accordingly * Update languageServer * Apply suggestions from code review Co-Authored-By: Claudio Russo --- design/DFX-Interface.md | 26 ++-- src/exes/mo_ide.ml | 14 +- src/exes/moc.ml | 15 +- src/languageServer/declaration_index.ml | 7 +- src/languageServer/source_file.ml | 9 +- src/mo_config/args.ml | 23 +++ src/mo_config/args.mli | 1 + src/mo_config/flags.ml | 5 +- src/pipeline/pipeline.ml | 11 +- src/pipeline/resolve_import.ml | 145 +++++++++++-------- src/pipeline/resolve_import.mli | 13 +- src/pipeline/url.ml | 15 +- src/pipeline/url.mli | 1 + test/fail/actor-alias1.mo | 3 + test/fail/ok/actor-alias1.tc.ok | 3 + test/fail/ok/actor-alias1.tc.ret.ok | 1 + test/run-drun/actor-import.mo | 12 +- test/run-drun/ok/actor-import.ic-stub-run.ok | 2 + test/run-drun/ok/actor-import.tc.ok | 2 +- 19 files changed, 183 insertions(+), 125 deletions(-) create mode 100644 src/mo_config/args.ml create mode 100644 src/mo_config/args.mli create mode 100644 test/fail/actor-alias1.mo create mode 100644 test/fail/ok/actor-alias1.tc.ok create mode 100644 test/fail/ok/actor-alias1.tc.ret.ok diff --git a/design/DFX-Interface.md b/design/DFX-Interface.md index ef2bb02c429..3ab8f40d127 100644 --- a/design/DFX-Interface.md +++ b/design/DFX-Interface.md @@ -50,16 +50,16 @@ In order to compile a motoko file, `dfx` invokes `moc` with moc some/path/input.mo \ -o another/path/output.wasm \ - { --package pkgname pkgpath } \ - { --actor-alias alias canisterhexid } - [ --actor-idl actorpath ] + { --package pkgname pkgpath } \ + { --actor-alias alias url } + [ --actor-idl actorpath ] in an environment where `MOC_RTS` points to the location of the Motoko runtime system. This _reads_ the following files * `some/path/input.mo` * any `.mo` file referenced by `some/path/input.mo`, either relatively, absolutely or via the provided package aliases - * for every actor import `ic:canisteridoralias` imported by any of the Motoko files, it reads `actorpath/canisterhexid.did`, see section Resolving Canister Ids below. + * for every actor import `ic:canisterid` imported by any of the Motoko files, it reads `actorpath/canisterid.did`, see section Resolving Canister Ids below. * the given `mo-rts.wasm` file. No constraints are imposed where imported files reside (this may be refined to prevent relative imports from looking outside the project and the declared packages) @@ -76,27 +76,23 @@ As the previous point, but passing `--idl` to `moc`. Resolving Canister aliases -------------------------- -For every actor imported using `import "ic:alias"`, the Motoko compiler treats that as `import "ic:canisterhexid"`, if the command line flag `--actor-alias alias id` is given. +For every actor imported using `import "canister:alias"`, the Motoko compiler treats that as `import "ic:canisterid"`, if the command line flag `--actor-alias alias ic:canisterid` is given. -The relation defined by the set of `--actor-alias` arguments must be left-unique and have disjoint range and domain (i.e. no `--actor-alias a b --actor-alias a c` or `--actor-alias a b --actor-alias b c` or even `--actor-alias a a`). +The first argument to `--actor-alias` is the alias without the URL scheme. The second argument must be a valid `"ic:"` url according to the [textual representation] of principal ids. -It is up to `dfx` to determine which urls are aliases that need resolving and which are concrete ids, and to set up `--actor-alias` flags accordingly. - -After applying any aliases, the Motoko compiler assume these imports to refer to [textual representations] of principal ids (e.g. `ic:ABCDE01A7`), and compilation will fail if they do not. +The given aliases must be unique (i.e. no `--actor-alias a ic:00 --actor-alias a ic:ABCDE01A7`). [textual representation]: https://docs.dfinity.systems/spec/public/#textual-ids Resolving Canister types ------------------------ -For every actor import using `import "ic:canisterhexid"` (or `import "ic:canisteralias"` if `canisteralias` resolves to `canisterhexid` as described above), the motoko compiler assumes the presence of a file `canisterhexid.did` in the actor idl path specified by `--actor-idl`. +For every actor imported using `import "ic:canisterid"` (or `import "canister:alias"` if `alias` resolves to `ic:canisterid` as described above), the motoko compiler assumes the presence of a file `canisterid.did` in the actor idl path specified by `--actor-idl`. This file informs motoko about the interface of that canister, e.g. the output of `moc --idl` for a locally known canister, or the IDL file as fetched from the Internet Computer. The `canisterid` here refers the “textual representation“ without the `ic:` prefix, but including the checksum. Note that this representation is unique. This files informs motoko about the interface of that canister. It could be the output of `moc --idl` for a locally known canister, or the IDL file as fetched from the Internet Computer, or created any other way. - - Compiling IDL Files to JS ------------------------- @@ -118,9 +114,9 @@ Invoking the IDE In order to start the language server, `dfx` invokes mo-ide --canister-main some/path/main.mo \ - { --package pkgname pkgpath } \ - { --actor-alias alias canisterhexid } - [ --actor-idl actorpath ] + { --package pkgname pkgpath } \ + { --actor-alias alias url } + [ --actor-idl actorpath ] with `stdin` and `stdout` connected to the LSP client. diff --git a/src/exes/mo_ide.ml b/src/exes/mo_ide.ml index e11df1f0697..40c10a22562 100644 --- a/src/exes/mo_ide.ml +++ b/src/exes/mo_ide.ml @@ -15,20 +15,8 @@ let argspec = ; "--canister-main", Arg.String set_entry_point, " specifies the entry point for the current project" - ; "--package", - (let package_name_ref = ref "DEADBEEF" in - Arg.Tuple [ - Arg.Set_string package_name_ref ; - Arg.String begin fun package_url -> - (* push (package_name, package_url) onto the list. *) - Flags.package_urls := ( - !package_name_ref, - package_url - ) :: ! Flags.package_urls - end - ]), " Specify a package-name-package-URL pair, separated by a space" - ; "--actor-idl", Arg.String (fun fp -> Flags.actor_idl_path := Some fp), " path to actor IDL files" ] + @ Args.package_args let () = Arg.parse argspec ignore usage; diff --git a/src/exes/moc.ml b/src/exes/moc.ml index c1c7c42ef69..f29c0dca59f 100644 --- a/src/exes/moc.ml +++ b/src/exes/moc.ml @@ -46,19 +46,8 @@ let argspec = Arg.align Arg.Unit (fun () -> printf "%s\n%!" banner; exit 0), " show version"; "--map", Arg.Set gen_source_map, " output source map"; - "-t", Arg.Set Flags.trace, " activate tracing"; - "--package", (let package_name_ref = ref "DEADBEEF" in - Arg.Tuple [ - Arg.Set_string package_name_ref ; - Arg.String begin fun package_url -> - (* push (package_name, package_url) onto the list. *) - Flags.package_urls := ( - !package_name_ref, - package_url - ) :: ! Flags.package_urls - end - ]), " Specify a package-name-package-URL pair, separated by a space" ; - "--actor-idl", Arg.String (fun fp -> Flags.actor_idl_path := Some fp), " path to actor IDL files"; + "-t", Arg.Set Flags.trace, " activate tracing in interpreters"] + @ Args.package_args @ [ "--profile", Arg.Set Flags.profile, " activate profiling counters in interpreters "; "--profile-file", Arg.Set_string Flags.profile_file, " set profiling output file "; "--profile-line-prefix", Arg.Set_string Flags.profile_line_prefix, " prefix each profile line with the given string "; diff --git a/src/languageServer/declaration_index.ml b/src/languageServer/declaration_index.ml index a2fda20f216..28482710a7a 100644 --- a/src/languageServer/declaration_index.ml +++ b/src/languageServer/declaration_index.ml @@ -1,4 +1,5 @@ open Mo_types +open Mo_config open Mo_def open Source open Syntax @@ -62,10 +63,8 @@ let lookup_module | Ok (Relative path) -> Index.find_opt path index | Ok (Package (pkg, path)) -> Lib.Option.bind - (List.find_opt - (fun (name, _) -> pkg = name) - !Mo_config.Flags.package_urls) - (fun (_, pkg_path) -> + (Flags.M.find_opt pkg !Flags.package_urls) + (fun pkg_path -> Index.find_opt (Filename.concat pkg_path path) index) | _ -> assert false diff --git a/src/languageServer/source_file.ml b/src/languageServer/source_file.ml index 3a73e6c7d7e..91cc08a4668 100644 --- a/src/languageServer/source_file.ml +++ b/src/languageServer/source_file.ml @@ -1,4 +1,5 @@ open Mo_frontend +open Mo_config module Lsp = Lsp.Lsp_t type cursor_target = @@ -49,13 +50,11 @@ let uri_for_package (path : string) = let open Pipeline.URL in match parse path with | Ok (Package (pkg, path)) -> - begin match - List.find_opt - (fun (name, _) -> pkg = name) - !Mo_config.Flags.package_urls with + begin match Flags.M.find_opt pkg !Flags.package_urls with | None -> None - | Some (_, pkg_path) -> + | Some pkg_path -> (* Resolved package paths are always absolute *) + (* TBR: But Flags.package_urls does not contain the resolved paths! *) Some ("file://" ^ Filename.concat pkg_path path) end | _ -> None diff --git a/src/mo_config/args.ml b/src/mo_config/args.ml new file mode 100644 index 00000000000..c6d65296069 --- /dev/null +++ b/src/mo_config/args.ml @@ -0,0 +1,23 @@ +(* This module contains some argument parsing that is common between +multiple executables *) + +let string_map flag r desc = + let key_ref = ref "DEADBEEF" in + flag, + Arg.Tuple [ + Arg.Set_string key_ref ; + Arg.String (fun value -> + let key = !key_ref in + if Flags.M.mem key !r + then (Printf.eprintf "duplicate %s %s" flag key ; exit 1) + else r := Flags.M.add key value !r + ) + ], + desc + +(* Everything related to imports, packages, aliases *) +let package_args = [ + string_map "--package" Flags.package_urls " Specify a package-name-package-URL pair, separated by a space"; + "--actor-idl", Arg.String (fun fp -> Flags.actor_idl_path := Some fp), " path to actor IDL files"; + string_map "--actor-alias" Flags.actor_aliases " actor import alias" + ] diff --git a/src/mo_config/args.mli b/src/mo_config/args.mli new file mode 100644 index 00000000000..b70076ade3d --- /dev/null +++ b/src/mo_config/args.mli @@ -0,0 +1 @@ +val package_args : (Arg.key * Arg.spec * Arg.doc) list diff --git a/src/mo_config/flags.ml b/src/mo_config/flags.ml index 16af3208126..4d16f401570 100644 --- a/src/mo_config/flags.ml +++ b/src/mo_config/flags.ml @@ -1,5 +1,7 @@ (* common flags for the moc compiler *) +module M = Map.Make(String) + type compile_mode = WasmMode | ICMode | StubMode | WASIMode let trace = ref false @@ -15,7 +17,8 @@ let dump_parse = ref false let dump_tc = ref false let dump_lowering = ref false let check_ir = ref true -let package_urls : (string * string) list ref = ref [] +let package_urls : string M.t ref = ref M.empty +let actor_aliases : string M.t ref = ref M.empty let actor_idl_path : string option ref = ref None let profile = ref false let profile_verbose = ref false diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index aa57057dca1..8b3e714ae02 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -109,10 +109,17 @@ let parse_file filename : parse_result = type resolve_result = (Syntax.prog * ResolveImport.resolved_imports) Diag.result +let resolve_flags () = + ResolveImport.{ + package_urls = !Flags.package_urls; + actor_aliases = !Flags.actor_aliases; + actor_idl_path = !Flags.actor_idl_path + } + let resolve_prog (prog, base) : resolve_result = Diag.map (fun libs -> (prog, libs)) - (ResolveImport.resolve !Flags.actor_idl_path !Flags.package_urls prog base) + (ResolveImport.resolve (resolve_flags ()) prog base) let resolve_progs = Diag.traverse resolve_prog @@ -238,7 +245,7 @@ let chase_imports parsefn senv0 imports : (Syntax.lib list * Scope.scope) Diag.r pending := add ri.Source.it !pending; Diag.bind (parsefn f) (fun (prog, base) -> Diag.bind (Static.prog prog) (fun () -> - Diag.bind (ResolveImport.resolve !Flags.actor_idl_path !Flags.package_urls prog base) (fun more_imports -> + Diag.bind (ResolveImport.resolve (resolve_flags ()) prog base) (fun more_imports -> Diag.bind (go_set more_imports) (fun () -> let lib = lib_of_prog f prog in Diag.bind (check_lib !senv lib) (fun sscope -> diff --git a/src/pipeline/resolve_import.ml b/src/pipeline/resolve_import.ml index a843939f9a5..641f2dceb45 100644 --- a/src/pipeline/resolve_import.ml +++ b/src/pipeline/resolve_import.ml @@ -14,6 +14,8 @@ It returns a list of all imported file names. *) type filepath = string +type url = string +type blob = string type resolved_imports = Syntax.resolved_import Source.phrase list @@ -34,16 +36,13 @@ module S = Set.Make end) -(* a map of type package_map will map each package name to a(n optional) package URL, - which for now is just a filesystem path: - - e.g., +(* a map of type package_map will map each package name to local, non-relative + filepath e.g., packages("std") = "/Users/home/username/.dfinity-sdk/src/mo-stdlib/0.1.0/" packages("foo") = "/Users/home/username/fooPackage/1.2.3/src" *) - module M = Map.Make(String) -type package_map = string M.t +type package_map = filepath M.t open Syntax open Source @@ -59,7 +58,16 @@ let err_unrecognized_url msgs at url msg = sev = Error; at; cat = "import"; - text = Printf.sprintf "cannot parse import URL %s: %s" url msg + text = Printf.sprintf "cannot parse import URL \"%s\": %s" url msg + } + +let err_unrecognized_alias_url msgs alias url msg = + let open Diag in + add_msg msgs { + sev = Error; + at = no_region; + cat = "actor-alias"; + text = Printf.sprintf "cannot parse URL \"%s\" for actor alias \"%s\": %s" url alias msg } let err_actor_import_without_idl_path msgs at = @@ -89,22 +97,32 @@ let err_package_not_defined msgs at pkg = text = Printf.sprintf "package \"%s\" not defined" pkg } -let err_package_file_does_not_exist msgs f pname = +let err_alias_not_defined msgs at alias = let open Diag in add_msg msgs { sev = Error; - at = no_region; - cat = "package"; - text = Printf.sprintf "file \"%s\" (for package `%s`) does not exist" f pname + at; + cat = "import"; + text = Printf.sprintf "canister alias \"%s\" not defined" alias } -let err_package_already_defined msgs package_name = +let err_alias_wrong_scheme msgs at alias url = let open Diag in - Diag.add_msg msgs { + add_msg msgs { + sev = Error; + at; + cat = "import"; + text = Printf.sprintf "canister alias \"%s\" target \"%s\" is not \"ic:\" url" alias url + } + + +let err_package_file_does_not_exist msgs f pname = + let open Diag in + add_msg msgs { sev = Error; at = no_region; - cat = "--package"; - text = Printf.sprintf "package name \"%s\" already defined" package_name; + cat = "package"; + text = Printf.sprintf "file \"%s\" (for package `%s`) does not exist" f pname } let add_lib_import msgs imported ri_ref at full_path = @@ -117,16 +135,12 @@ let add_lib_import msgs imported ri_ref at full_path = err_file_does_not_exist msgs at full_path let add_idl_import msgs imported ri_ref at full_path bytes = - ri_ref := IDLPath (full_path, bytes); - imported := RIM.add (IDLPath (full_path, bytes)) at !imported - (* if Sys.file_exists full_path then begin - ri_ref := IDLPath full_path; - imported := S.add full_path !imported + ri_ref := IDLPath (full_path, bytes); + imported := RIM.add (IDLPath (full_path, bytes)) at !imported end else - does_not_exist_error msgs at full_path - *) + err_file_does_not_exist msgs at full_path @@ -135,42 +149,50 @@ let in_base base f = then f else Filename.concat base f -let resolve_import_string msgs base actor_idl_path packages imported (f, ri_ref, at) = +let resolve_import_string msgs base actor_idl_path aliases packages imported (f, ri_ref, at) = + let resolve_ic bytes = match actor_idl_path with + | None -> err_actor_import_without_idl_path msgs at + | Some actor_base -> + let full_path = in_base actor_base (Url.idl_basename_of_blob bytes) in + add_idl_import msgs imported ri_ref at full_path bytes + in match Url.parse f with | Ok (Url.Relative path) -> add_lib_import msgs imported ri_ref at (in_base base path) | Ok (Url.Package (pkg,path)) -> begin match M.find_opt pkg packages with - | Some pkg_path -> - add_lib_import msgs imported ri_ref at (in_base pkg_path path) - | None -> - err_package_not_defined msgs at pkg + | Some pkg_path -> add_lib_import msgs imported ri_ref at (in_base pkg_path path) + | None -> err_package_not_defined msgs at pkg end - | Ok (Url.Ic bytes) -> begin match actor_idl_path with - | None -> err_actor_import_without_idl_path msgs at - | Some actor_base -> - let full_path = in_base actor_base (Url.idl_basename_of_blob bytes) in - add_idl_import msgs imported ri_ref at full_path bytes + | Ok (Url.Ic bytes) -> resolve_ic bytes + | Ok (Url.IcAlias alias) -> + begin match M.find_opt alias aliases with + | Some bytes -> resolve_ic bytes + | None -> err_alias_not_defined msgs at alias end | Error msg -> err_unrecognized_url msgs at f msg (* Resolve the argument to --package. These can also be relative to base *) -let resolve_package_url (msgs:Diag.msg_store) (base:filepath) (pname:string) (f: string) : string option = +let resolve_package_url (msgs:Diag.msg_store) (base:filepath) (pname:string) (f:url) : filepath = let f = if Filename.is_relative f then in_base base f else f in let f = Lib.FilePath.normalise f in - if Sys.file_exists f then - Some f - else - begin - err_package_file_does_not_exist msgs f pname; - None - end - -let prog_imports (p : prog): (string * resolved_import ref * Source.region) list = + if Sys.file_exists f + then f + else (err_package_file_does_not_exist msgs f pname;"") + +(* Resolve the argument to --actor-alias. Check eagerly for well-formedness *) +let resolve_alias_url (msgs:Diag.msg_store) (alias:string) (f:url) : blob = + match Url.parse f with + | Ok (Url.Ic bytes) -> bytes + | Ok _ -> err_alias_wrong_scheme msgs no_region alias f; "" + | Error msg -> err_unrecognized_alias_url msgs alias f msg; "" + + +let prog_imports (p : prog): (url * resolved_import ref * Source.region) list = let res = ref [] in let f e = match e.it with | ImportE (f, fp) -> res := (f, fp, e.at) ::!res; e @@ -178,33 +200,36 @@ let prog_imports (p : prog): (string * resolved_import ref * Source.region) list let _ = ignore (Traversals.over_prog f p) in List.rev !res -let collect_imports (p : prog): string list = +let collect_imports (p : prog): url list = List.map (fun (f, _, _) -> f) (prog_imports p) -type actor_idl_path = string option -type package_urls = (string * string) list +type actor_idl_path = filepath option +type package_urls = url M.t +type actor_aliases = url M.t +type aliases = blob M.t let resolve_packages : package_urls -> filepath -> package_map Diag.result = fun purls base -> - Diag.fold (fun package_map (package_name, package_url) -> - Diag.with_message_store (fun msgs -> - if M.mem package_name package_map - then begin err_package_already_defined msgs package_name; None end - else match resolve_package_url msgs base package_name package_url with - | None -> None - | Some resolved_url -> Some (M.add package_name resolved_url package_map) - ) - ) - M.empty purls + Diag.with_message_store (fun msgs -> Some (M.mapi (resolve_package_url msgs base) purls)) + +let resolve_aliases : actor_aliases -> aliases Diag.result = fun alias_urls -> + Diag.with_message_store (fun msgs -> Some (M.mapi (resolve_alias_url msgs) alias_urls)) + +type flags = { + package_urls : package_urls; + actor_aliases : actor_aliases; + actor_idl_path : actor_idl_path; +} let resolve - : actor_idl_path -> package_urls -> Syntax.prog -> filepath -> resolved_imports Diag.result - = fun actor_idl_path purls p base -> - Diag.bind (resolve_packages purls base) (fun (packages:package_map) -> + : flags -> Syntax.prog -> filepath -> resolved_imports Diag.result + = fun {actor_idl_path; package_urls; actor_aliases} p base -> + Diag.bind (resolve_packages package_urls base) (fun (packages:package_map) -> + Diag.bind (resolve_aliases actor_aliases) (fun aliases -> Diag.with_message_store (fun msgs -> let base = if Sys.is_directory base then base else Filename.dirname base in let imported = ref RIM.empty in - List.iter (resolve_import_string msgs base actor_idl_path packages imported) (prog_imports p); + List.iter (resolve_import_string msgs base actor_idl_path aliases packages imported) (prog_imports p); Some (List.map (fun (rim,at) -> Source.(rim @@ at)) (RIM.bindings !imported)) ) - ) + )) diff --git a/src/pipeline/resolve_import.mli b/src/pipeline/resolve_import.mli index b840c0b9334..63368ddfc66 100644 --- a/src/pipeline/resolve_import.mli +++ b/src/pipeline/resolve_import.mli @@ -1,4 +1,5 @@ open Mo_def +open Mo_config type filepath = string @@ -6,9 +7,17 @@ module S : Set.S with type elt = Syntax.resolved_import module RIM : Map.S with type key = Syntax.resolved_import type actor_idl_path = string option -type package_urls = (string * string) list +type package_urls = string Flags.M.t +type actor_aliases = string Flags.M.t type resolved_imports = Syntax.resolved_import Source.phrase list val collect_imports : Syntax.prog -> string list -val resolve : actor_idl_path -> package_urls -> Syntax.prog -> filepath -> resolved_imports Diag.result + +type flags = { + package_urls : package_urls; + actor_aliases : actor_aliases; + actor_idl_path : actor_idl_path; +} + +val resolve : flags -> Syntax.prog -> filepath -> resolved_imports Diag.result diff --git a/src/pipeline/url.ml b/src/pipeline/url.ml index 640bfb0adf9..620f8454cfa 100644 --- a/src/pipeline/url.ml +++ b/src/pipeline/url.ml @@ -7,7 +7,8 @@ parse "mo:foo" = Ok (Package ("foo", "")) parse "ic:DEADBEEF" = Ok (Ic "\DE\AD\BE\EF") - parse "ic:alias" = (not yet supported) + + parse "ic-alias:foo" = Ok (IcAlias "foo") parse "std/foo" = Ok (Relative "std/foo") parse "foo" = Ok (Relative "foo") @@ -40,6 +41,7 @@ type parsed = | Package of (string * string) | Relative of string | Ic of string + | IcAlias of string let parse (f: string) : (parsed, string) result = @@ -59,10 +61,13 @@ let parse (f: string) : (parsed, string) result = | Error err -> Error err end | None -> - begin match Stdlib.String.index_opt f ':' with - | Some _ -> Error "Unrecognized URL" - | None -> Ok (Relative (Lib.FilePath.normalise f)) - end + match Lib.String.chop_prefix "canister:" f with + | Some suffix -> Ok (IcAlias suffix) + | None -> + begin match Stdlib.String.index_opt f ':' with + | Some _ -> Error "Unrecognized URL" + | None -> Ok (Relative (Lib.FilePath.normalise f)) + end (* Basename of the IDL file searched (see DFX-Interface.md) *) diff --git a/src/pipeline/url.mli b/src/pipeline/url.mli index 0306344cab5..b9299577ac4 100644 --- a/src/pipeline/url.mli +++ b/src/pipeline/url.mli @@ -2,6 +2,7 @@ type parsed = | Package of (string * string) | Relative of string | Ic of string + | IcAlias of string val parse : string -> (parsed, string) result val idl_basename_of_blob : string -> string diff --git a/test/fail/actor-alias1.mo b/test/fail/actor-alias1.mo new file mode 100644 index 00000000000..aceed61fb9e --- /dev/null +++ b/test/fail/actor-alias1.mo @@ -0,0 +1,3 @@ +//MOC-FLAG --actor-alias foo https://dfinity.org +//MOC-FLAG --actor-alias bar not_an_ic_url +//MOC-FLAG --actor-alias baz canister:baz diff --git a/test/fail/ok/actor-alias1.tc.ok b/test/fail/ok/actor-alias1.tc.ok new file mode 100644 index 00000000000..207349220e2 --- /dev/null +++ b/test/fail/ok/actor-alias1.tc.ok @@ -0,0 +1,3 @@ +(unknown location): import error, canister alias "bar" target "not_an_ic_url" is not "ic:" url +(unknown location): import error, canister alias "baz" target "canister:baz" is not "ic:" url +(unknown location): actor-alias error, cannot parse URL "https://dfinity.org" for actor alias "foo": Unrecognized URL diff --git a/test/fail/ok/actor-alias1.tc.ret.ok b/test/fail/ok/actor-alias1.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/actor-alias1.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-drun/actor-import.mo b/test/run-drun/actor-import.mo index e713abef820..763de3bd4c5 100644 --- a/test/run-drun/actor-import.mo +++ b/test/run-drun/actor-import.mo @@ -1,17 +1,21 @@ -//MOC-FLAG --actor-idl actor-import +//MOC-FLAG --actor-idl actor-import +//MOC-FLAG --actor-alias self ic:000000000000040054 // this imports our own IDL, stored in actor-import // currently hard-codes the ic-stub self id // once we have actor aliases we can let run.sh set an alias. -import imported "ic:000000000000040054"; +import imported1 "ic:000000000000040054"; +import imported2 "canister:self"; actor a { - public func go() : async (actor {}) = async imported; - public func go2() : async (actor {}) = async await (imported.go()); + public func go() : async (actor {}) = async imported1; + public func go2() : async (actor {}) = async await (imported1.go()); + public func go3() : async (actor {}) = async await (imported2.go()); }; //CALL ingress go "DIDL\x00\x00" //CALL ingress go2 "DIDL\x00\x00" +//CALL ingress go3 "DIDL\x00\x00" //SKIP run diff --git a/test/run-drun/ok/actor-import.ic-stub-run.ok b/test/run-drun/ok/actor-import.ic-stub-run.ok index 53c6f5d873b..04506fe8c95 100644 --- a/test/run-drun/ok/actor-import.ic-stub-run.ok +++ b/test/run-drun/ok/actor-import.ic-stub-run.ok @@ -6,3 +6,5 @@ ← completed: 0x4449444c016900010001080000000000000400 → update go2(0x4449444c0000) ← completed: 0x4449444c016900010001080000000000000400 +→ update go3(0x4449444c0000) +← completed: 0x4449444c016900010001080000000000000400 diff --git a/test/run-drun/ok/actor-import.tc.ok b/test/run-drun/ok/actor-import.tc.ok index 6faf5ac4c7a..f33bef8ed9a 100644 --- a/test/run-drun/ok/actor-import.tc.ok +++ b/test/run-drun/ok/actor-import.tc.ok @@ -1 +1 @@ -actor-import.mo:8.1-8.40: warning, imported actors assumed to have type actor {go : shared () -> async actor {}} +actor-import.mo:10.1-10.33: warning, imported actors assumed to have type actor {go : shared () -> async actor {}} From 9fa9f588bb82921b6cff0fa934741b453adac004 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 19 Dec 2019 18:14:18 +0100 Subject: [PATCH 0858/1176] Rope iterators: confused the iterator with the continuation (#1059) one-character difference... --- rts/text.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rts/text.c b/rts/text.c index db8d938e618..3bc2a64316c 100644 --- a/rts/text.c +++ b/rts/text.c @@ -305,8 +305,8 @@ export uint32_t text_iter_next(text_iter_t i) { // if next one is a concat node, re-use both text iterator structures // (avoids an allocation) if (TAG(s2) == TAG_CONCAT) { + TEXT_CONT_TEXT(c) = CONCAT_ARG2(s2); TEXT_ITER_POS(i) = 0; - TEXT_CONT_TEXT(i) = CONCAT_ARG2(s2); TEXT_ITER_BLOB(i) = find_leaf(CONCAT_ARG1(s2), &TEXT_ITER_TODO(i)); return text_iter_next(i); // else remove that entry from the chain From 23dd24a6043a04e0b615738efe7109d2f6b87d15 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Thu, 19 Dec 2019 18:18:45 +0100 Subject: [PATCH 0859/1176] Randomised rope tests (#1058) * ignore stuff * testing ropes * test ropeConcat * Motokise * simplify * simplify more * test rope iterators --- test/random/.gitignore | 2 + test/random/Main.hs | 361 ++++++++++++++++++++++++----------------- 2 files changed, 217 insertions(+), 146 deletions(-) create mode 100644 test/random/.gitignore diff --git a/test/random/.gitignore b/test/random/.gitignore new file mode 100644 index 00000000000..a69dcce068e --- /dev/null +++ b/test/random/.gitignore @@ -0,0 +1,2 @@ +TAGS +dist* diff --git a/test/random/Main.hs b/test/random/Main.hs index ce42b1d46cb..a2b97404fb0 100644 --- a/test/random/Main.hs +++ b/test/random/Main.hs @@ -1,4 +1,4 @@ -{-# language ConstraintKinds, DataKinds, FlexibleContexts, FlexibleInstances, GADTs +{-# language ConstraintKinds, DataKinds, DeriveFoldable, FlexibleContexts, FlexibleInstances, GADTs , KindSignatures, MultiParamTypeClasses, OverloadedStrings, ScopedTypeVariables, StandaloneDeriving , TypeApplications, TypeOperators, TypeFamilies, TupleSections , UndecidableInstances, ViewPatterns #-} @@ -19,7 +19,7 @@ import Data.Bool (bool) import Data.Proxy import Data.Type.Equality import GHC.Natural -import GHC.TypeLits +import GHC.TypeLits hiding (Text) import qualified Data.Word import Data.Bits (Bits(..), FiniteBits(..)) import Numeric @@ -52,6 +52,9 @@ utf8Props = testGroup "UTF-8 coding" [ QC.testProperty "explode >>> concat roundtrips" $ prop_explodeConcat , QC.testProperty "charToText >>> head roundtrips" $ prop_charToText , QC.testProperty "length computation" $ prop_textLength + , QC.testProperty "chunky concat (ropes)" $ prop_ropeConcat + , QC.testProperty "chunky length (ropes)" $ prop_ropeLength + , QC.testProperty "chunky iterator (ropes)" $ prop_ropeIterator ] matchingProps = testGroup "Pattern matching" @@ -108,6 +111,57 @@ prop_textLength (UTF8 text) = monadicIO $ do let testCase = "assert(\"" <> (text >>= escape) <> "\".len() == " <> show (length text) <> ")" runScriptNoFuzz "textLength" testCase +data Rope a = EmptyChunk | Chunk a | UTF8Chunk a | LongChunk a | Rope a `Rope` Rope a deriving (Eq, Show, Foldable) + +instance Semigroup (Rope a) where + (<>) = Rope + +instance Monoid (Rope a) where + mempty = EmptyChunk + +instance Arbitrary (Rope String) where + arbitrary = frequency [ (2, pure mempty) + , (4, Chunk <$> arbitrary) + , (5, elements [ UTF8Chunk "Медве́ди хо́дят по у́лицам. Коне́чно, э́то непра́вда!" + , UTF8Chunk "Boci, boci tarka, se füle, se farka, oda megyünk lakni, ahol tejet kapni." + , UTF8Chunk "十年树木,百年树人" ]) + , (7, pure $ LongChunk "The quick brown fox jumps over the lazy dog") + , (3, Rope <$> arbitrary <*> arbitrary) ] + +instance Semigroup (MOTerm String) where + (<>) = Concat + +instance Monoid (MOTerm String) where + mempty = Text mempty + +asString = foldMap id + +asMot :: Rope String -> MOTerm String +asMot = foldMap Text + +prop_ropeConcat rope = monadicIO $ do + let testCase = "assert (" <> ropeMot <> " == " <> string <> ")" + string = unparseMO (Text (asString rope)) + ropeMot = unparseMO (asMot rope) + runScriptNoFuzz "ropeConcat" testCase + +prop_ropeLength rope = monadicIO $ do + let testCase = "assert (" <> ropeMot <> ".len() == " <> show len <> ")" + len = length (asString rope) + ropeMot = unparseMO (asMot rope) + runScriptNoFuzz "ropeLength" testCase + +prop_ropeIterator rope = monadicIO $ do + let testCase = "func same(c : ?Char, d : Char) : Bool = switch c { case (?cc) { cc == d }; case null false };" + <> "let i = (" <> ropeMot <> ").chars();" + <> concatMap testStep string + <> "assert (switch (i.next()) { case null true; case _ false })" + testStep c = "assert (same(i.next(), '" <> escape c <> "'));" + string = asString rope + ropeMot = unparseMO (asMot rope) + runScriptNoFuzz "ropeLength" testCase + + assertSuccessNoFuzz relevant (compiled, (exitCode, out, err)) = do let fuzzErr = not $ Data.Text.null err when fuzzErr $ do @@ -123,7 +177,7 @@ assertSuccessNoFuzz relevant (compiled, (exitCode, out, err)) = do newtype Failing a = Failing a deriving Show instance Arbitrary (Failing String) where - arbitrary = do let failed as = "let _ = " ++ unparseAS as ++ ";" + arbitrary = do let failed as = "let _ = " ++ unparseMO as ++ ";" Failing . failed <$> suchThat (resize 5 arbitrary) (\(evaluate @Integer -> res) -> null res) prop_rejects (Failing testCase) = monadicIO $ runScriptWantFuzz "fails" testCase @@ -137,7 +191,7 @@ newtype TestCase = TestCase [String] deriving Show instance Arbitrary TestCase where arbitrary = do tests <- infiniteListOf arbitrary let expected = evaluate @Integer <$> tests - let paired as = fmap (\res -> "assert (" ++ unparseAS as ++ " == " ++ show res ++ ");") + let paired as = fmap (\res -> "assert (" ++ unparseMO as ++ " == " ++ show res ++ ");") pure . TestCase . take 100 . catMaybes $ zipWith paired tests expected @@ -166,7 +220,7 @@ prop_verifies (TestCase (map fromString -> testCase)) = monadicIO $ do assertSuccessNoFuzz id res -newtype ConversionTest n = ConversionTest (ASTerm (BitLimited n Word)) deriving Show +newtype ConversionTest n = ConversionTest (MOTerm (BitLimited n Word)) deriving Show instance WordLike n => Arbitrary (ConversionTest n) where arbitrary = ConversionTest . ConvertNatToWord . ConvertWordToNat . Neuralgic <$> (arbitrary :: Gen (Neuralgic (BitLimited n Word))) @@ -176,13 +230,13 @@ prop_roundtripWNW (ConversionTest term) = case term of ConvertNatToWord (ConvertWordToNat n) -> case sameNat (bitsIn term) (bitsIn n) of - Just Refl -> let testCase = "assert(" <> unparseAS (term `Equals` n) <> ")" in + Just Refl -> let testCase = "assert(" <> unparseMO (term `Equals` n) <> ")" in monadicIO $ runScriptNoFuzz "roundtripWNW" testCase - where bitsIn :: KnownNat n => ASTerm (BitLimited n Word) -> Proxy n + where bitsIn :: KnownNat n => MOTerm (BitLimited n Word) -> Proxy n bitsIn _ = Proxy -newtype ModuloTest (n :: Nat) = ModuloTest (ASTerm (BitLimited n Word)) deriving Show +newtype ModuloTest (n :: Nat) = ModuloTest (MOTerm (BitLimited n Word)) deriving Show instance WordLike n => Arbitrary (ModuloTest n) where arbitrary = ModuloTest . ConvertNatToWord @n . Neuralgic <$> (arbitrary :: Gen (Neuralgic Natural)) @@ -190,11 +244,11 @@ instance WordLike n => Arbitrary (ModuloTest n) where prop_moduloNWN :: forall n . KnownNat n => ModuloTest n -> Property prop_moduloNWN (ModuloTest term@(ConvertNatToWord (Neuralgic m))) = monadicIO $ runScriptNoFuzz "moduloNWN" testCase where m' = evalN m .&. maskFor term - testCase = "assert(" <> unparseAS (ConvertWordToNat term) + testCase = "assert(" <> unparseMO (ConvertWordToNat term) <> " == " <> show m' <> ")" data Matching where - Matching :: (AnnotLit t, ASValue t, Show t) => (ASTerm t, t) -> Matching + Matching :: (AnnotLit t, MOValue t, Show t) => (MOTerm t, t) -> Matching deriving instance Show Matching @@ -207,7 +261,7 @@ instance Arbitrary Matching where , realise Matching <$> gen @(BitLimited 8 Natural, BitLimited 8 Integer, BitLimited 8 Word) , realise Matching <$> gen @(Maybe Integer) ] - where gen :: (Arbitrary (ASTerm a), Evaluatable a) => Gen (ASTerm a, Maybe a) + where gen :: (Arbitrary (MOTerm a), Evaluatable a) => Gen (MOTerm a, Maybe a) gen = (do term <- arbitrary let val = evaluate term pure (term, val)) `suchThat` (isJust . snd) @@ -216,67 +270,67 @@ instance Arbitrary Matching where prop_matchStructured :: Matching -> Property prop_matchStructured (Matching a) = locally a -locally :: (AnnotLit t, ASValue t) => (ASTerm t, t) -> Property +locally :: (AnnotLit t, MOValue t) => (MOTerm t, t) -> Property locally (tm, v) = monadicIO $ do let testCase = "assert (switch (" <> expr <> ") { case (" <> eval'd <> ") true; case _ false })" eval'd = unparse v - expr = unparseAS tm + expr = unparseMO tm runScriptNoFuzz "matchLocally" testCase prop_matchInActor :: Matching -> Property prop_matchInActor (Matching a) = mobile a -mobile :: (AnnotLit t, ASValue t) => (ASTerm t, t) -> Property +mobile :: (AnnotLit t, MOValue t) => (MOTerm t, t) -> Property mobile (tm, v) = monadicIO $ do let testCase = "/*let a = actor { public func match (b : " <> typed <> ") : async Bool = async { true } };*/ assert (switch (" <> expr <> " : " <> typed <> ") { case (" <> eval'd <> ") true; case _ false })" eval'd = unparse v typed = unparseType v - expr = unparseAS tm + expr = unparseMO tm runScriptNoFuzz "matchMobile" testCase --- instances of ASValue describe "ground values" in +-- instances of MOValue describe "ground values" in -- Motoko. These can appear in patterns and have --- well-defined AS type. +-- well-defined Motoko type. -- -class ASValue a where +class MOValue a where unparseType :: a -> String unparse :: a -> String -instance ASValue Bool where +instance MOValue Bool where unparseType _ = "Bool" - unparse = unparseAS . Bool + unparse = unparseMO . Bool -instance ASValue Integer where +instance MOValue Integer where unparseType _ = "Int" unparse = show -instance ASValue Natural where +instance MOValue Natural where unparseType _ = "Nat" unparse = show -instance KnownNat n => ASValue (BitLimited n Natural) where +instance KnownNat n => MOValue (BitLimited n Natural) where unparseType _ = "Nat" <> bitWidth (Proxy @n) unparse (NatN a) = annot (Five @(BitLimited n Natural)) (show a) -instance KnownNat n => ASValue (BitLimited n Integer) where +instance KnownNat n => MOValue (BitLimited n Integer) where unparseType _ = "Int" <> bitWidth (Proxy @n) unparse (IntN a) = annot (Five @(BitLimited n Integer)) (show a) -instance KnownNat n => ASValue (BitLimited n Word) where +instance KnownNat n => MOValue (BitLimited n Word) where unparseType _ = "Word" <> bitWidth (Proxy @n) unparse (WordN a) = annot (Five @(BitLimited n Word)) (show a) -instance (ASValue a, ASValue b) => ASValue (a, b) where +instance (MOValue a, MOValue b) => MOValue (a, b) where unparseType (a, b) = "(" <> unparseType a <> ", " <> unparseType b <> ")" unparse (a, b) = "(" <> unparse a <> ", " <> unparse b <> ")" -instance (ASValue a, ASValue b, ASValue c) => ASValue (a, b, c) where +instance (MOValue a, MOValue b, MOValue c) => MOValue (a, b, c) where unparseType (a, b, c) = "(" <> unparseType a <> ", " <> unparseType b <> ", " <> unparseType c <> ")" unparse (a, b, c) = "(" <> unparse a <> ", " <> unparse b <> ", " <> unparse c <> ")" -instance ASValue a => ASValue (Maybe a) where +instance MOValue a => MOValue (Maybe a) where unparseType Nothing = "Null" unparseType (Just a) = "?" <> unparseType a unparse Nothing = "null" @@ -349,48 +403,51 @@ instance KnownNat n => Arbitrary (Neuralgic (BitLimited n Word)) where menu 64 = [Around0, AroundNeg 3, AroundNeg 11, AroundNeg 21, AroundNeg 31, AroundNeg 42, AroundNeg 64, AroundPos 6, AroundPos 14, AroundPos 27, AroundPos 43, AroundPos 57, AroundPos 64] -data ASTerm :: * -> * where +data MOTerm :: * -> * where -- Comparisons NotEqual, Equals, GreaterEqual, Greater, LessEqual, Less - :: (AnnotLit a, Evaluatable a) => ASTerm a -> ASTerm a -> ASTerm Bool + :: (AnnotLit a, Evaluatable a) => MOTerm a -> MOTerm a -> MOTerm Bool -- Short-circuit ShortAnd, ShortOr - :: ASTerm Bool -> ASTerm Bool -> ASTerm Bool + :: MOTerm Bool -> MOTerm Bool -> MOTerm Bool -- Boolean - Not :: ASTerm Bool -> ASTerm Bool - Bool :: Bool -> ASTerm Bool + Not :: MOTerm Bool -> MOTerm Bool + Bool :: Bool -> MOTerm Bool -- Bitwise - Complement :: ASTerm (BitLimited n Word) -> ASTerm (BitLimited n Word) + Complement :: MOTerm (BitLimited n Word) -> MOTerm (BitLimited n Word) Or, And, Xor, RotL, RotR, ShiftL, ShiftR, ShiftRSigned - :: ASTerm (BitLimited n Word) -> ASTerm (BitLimited n Word) -> ASTerm (BitLimited n Word) - PopCnt, Clz, Ctz :: ASTerm (BitLimited n Word) -> ASTerm (BitLimited n Word) + :: MOTerm (BitLimited n Word) -> MOTerm (BitLimited n Word) -> MOTerm (BitLimited n Word) + PopCnt, Clz, Ctz :: MOTerm (BitLimited n Word) -> MOTerm (BitLimited n Word) -- Arithmetic - Pos, Neg, Abs :: ASTerm a -> ASTerm a - Add, Sub, Mul, Div, Mod, Pow :: ASTerm a -> ASTerm a -> ASTerm a + Pos, Neg, Abs :: MOTerm a -> MOTerm a + Add, Sub, Mul, Div, Mod, Pow :: MOTerm a -> MOTerm a -> MOTerm a -- Numeric - Neuralgic :: Neuralgic a -> ASTerm a - Five :: ASTerm a + Neuralgic :: Neuralgic a -> MOTerm a + Five :: MOTerm a + -- Text + Text :: String -> MOTerm String + Concat :: MOTerm String -> MOTerm String -> MOTerm String -- Conditional - IfThenElse :: ASTerm a -> ASTerm a -> ASTerm Bool -> ASTerm a + IfThenElse :: MOTerm a -> MOTerm a -> MOTerm Bool -> MOTerm a -- Conversion - ConvertNatural :: ASTerm Natural -> ASTerm Integer - ConvertNat :: KnownNat n => ASTerm (BitLimited n Natural) -> ASTerm Integer - ConvertInt :: KnownNat n => ASTerm (BitLimited n Integer) -> ASTerm Integer - ConvertWord :: WordLike n => ASTerm (BitLimited n Word) -> ASTerm Integer - ConvertNatToWord :: WordLike n => ASTerm Natural -> ASTerm (BitLimited n Word) - ConvertWordToNat :: WordLike n => ASTerm (BitLimited n Word) -> ASTerm Natural + ConvertNatural :: MOTerm Natural -> MOTerm Integer + ConvertNat :: KnownNat n => MOTerm (BitLimited n Natural) -> MOTerm Integer + ConvertInt :: KnownNat n => MOTerm (BitLimited n Integer) -> MOTerm Integer + ConvertWord :: WordLike n => MOTerm (BitLimited n Word) -> MOTerm Integer + ConvertNatToWord :: WordLike n => MOTerm Natural -> MOTerm (BitLimited n Word) + ConvertWordToNat :: WordLike n => MOTerm (BitLimited n Word) -> MOTerm Natural -- Constructors (intro forms) - Pair :: (AnnotLit a, AnnotLit b, Evaluatable a, Evaluatable b) => ASTerm a -> ASTerm b -> ASTerm (a, b) + Pair :: (AnnotLit a, AnnotLit b, Evaluatable a, Evaluatable b) => MOTerm a -> MOTerm b -> MOTerm (a, b) Triple :: (AnnotLit a, AnnotLit b, AnnotLit c, Evaluatable a, Evaluatable b, Evaluatable c) - => ASTerm a -> ASTerm b -> ASTerm c -> ASTerm (a, b, c) - Array :: ASTerm a -> ASTerm [a] -- not matchable! - Null :: ASTerm (Maybe a) - Some :: (AnnotLit a, Evaluatable a) => ASTerm a -> ASTerm (Maybe a) + => MOTerm a -> MOTerm b -> MOTerm c -> MOTerm (a, b, c) + Array :: MOTerm a -> MOTerm [a] -- not matchable! + Null :: MOTerm (Maybe a) + Some :: (AnnotLit a, Evaluatable a) => MOTerm a -> MOTerm (Maybe a) -- Variants, Objects (TODO) -deriving instance Show (ASTerm t) +deriving instance Show (MOTerm t) -subTerm :: Arbitrary (ASTerm t) => Bool -> Int -> [(Int, Gen (ASTerm t))] +subTerm :: Arbitrary (MOTerm t) => Bool -> Int -> [(Int, Gen (MOTerm t))] subTerm fullPow n = [ (1, resize (n `div` 5) $ Pow <$> arbitrary <*> arbitrary) | fullPow] ++ [ (n, resize (n `div` 3) $ Add <$> arbitrary <*> arbitrary) @@ -401,12 +458,12 @@ subTerm fullPow n = , (n, resize (n `div` 4) $ IfThenElse <$> arbitrary <*> arbitrary <*> arbitrary) ] -subTermPow :: Arbitrary (ASTerm t) => (ASTerm t -> ASTerm t) -> Int -> [(Int, Gen (ASTerm t))] +subTermPow :: Arbitrary (MOTerm t) => (MOTerm t -> MOTerm t) -> Int -> [(Int, Gen (MOTerm t))] subTermPow mod n = (n, resize (n `div` 5) $ Pow <$> arbitrary <*> (mod <$> arbitrary)) : subTerm False n -subTermPow5 :: Arbitrary (ASTerm t) - => Int -> [(Int, Gen (ASTerm t))] +subTermPow5 :: Arbitrary (MOTerm t) + => Int -> [(Int, Gen (MOTerm t))] subTermPow5 n = (n, resize (n `div` 5) $ Pow <$> arbitrary <*> (Neuralgic <$> elements [ Around0 @@ -417,7 +474,7 @@ subTermPow5 n = (n, resize (n `div` 5) ])) : subTerm False n -bitwiseTerm :: WordLike n => Arbitrary (ASTerm (BitLimited n Word)) => Int -> [(Int, Gen (ASTerm (BitLimited n Word)))] +bitwiseTerm :: WordLike n => Arbitrary (MOTerm (BitLimited n Word)) => Int -> [(Int, Gen (MOTerm (BitLimited n Word)))] bitwiseTerm n = [ (n `div` 5, resize (n `div` 3) $ Or <$> arbitrary <*> arbitrary) , (n `div` 5, resize (n `div` 3) $ And <$> arbitrary <*> arbitrary) @@ -436,43 +493,43 @@ bitwiseTerm n = -- generate reasonably formed trees from smaller subterms -- reasonablyShaped :: (Arbitrary (Neuralgic a), AnnotLit a, Evaluatable a) - => (Int -> [(Int, Gen (ASTerm a))]) - -> Gen (ASTerm a) + => (Int -> [(Int, Gen (MOTerm a))]) + -> Gen (MOTerm a) reasonablyShaped sub = sized $ \(succ -> n) -> frequency $ (30 `div` n, Neuralgic <$> arbitrary) : if n > 1 then sub n else [] -instance {-# OVERLAPPABLE #-} KnownNat n => Arbitrary (ASTerm (BitLimited n Natural)) where +instance {-# OVERLAPPABLE #-} KnownNat n => Arbitrary (MOTerm (BitLimited n Natural)) where arbitrary = reasonablyShaped $ subTermPow (`Mod` Five) -instance {-# OVERLAPS #-} Arbitrary (ASTerm Nat8) where +instance {-# OVERLAPS #-} Arbitrary (MOTerm Nat8) where arbitrary = reasonablyShaped $ subTerm True -instance {-# OVERLAPPABLE #-} KnownNat n => Arbitrary (ASTerm (BitLimited n Integer)) where +instance {-# OVERLAPPABLE #-} KnownNat n => Arbitrary (MOTerm (BitLimited n Integer)) where arbitrary = reasonablyShaped subTermPow5 -instance {-# OVERLAPS #-} Arbitrary (ASTerm Int8) where +instance {-# OVERLAPS #-} Arbitrary (MOTerm Int8) where arbitrary = reasonablyShaped $ subTerm True -instance {-# OVERLAPPABLE #-} WordLike n => Arbitrary (ASTerm (BitLimited n Word)) where +instance {-# OVERLAPPABLE #-} WordLike n => Arbitrary (MOTerm (BitLimited n Word)) where arbitrary = reasonablyShaped $ (<>) <$> subTermPow (`Mod` Five) <*> bitwiseTerm -instance {-# OVERLAPS #-} Arbitrary (ASTerm Word8) where +instance {-# OVERLAPS #-} Arbitrary (MOTerm Word8) where arbitrary = reasonablyShaped $ (<>) <$> subTerm True <*> bitwiseTerm -instance (AnnotLit a, AnnotLit b, Evaluatable a, Evaluatable b, Arbitrary (ASTerm a), Arbitrary (ASTerm b)) => Arbitrary (ASTerm (a, b)) where +instance (AnnotLit a, AnnotLit b, Evaluatable a, Evaluatable b, Arbitrary (MOTerm a), Arbitrary (MOTerm b)) => Arbitrary (MOTerm (a, b)) where arbitrary = scale (`quot` 2) $ Pair <$> arbitrary <*> arbitrary -instance (AnnotLit a, AnnotLit b, AnnotLit c, Evaluatable a, Evaluatable b, Evaluatable c, Arbitrary (ASTerm a), Arbitrary (ASTerm b), Arbitrary (ASTerm c)) - => Arbitrary (ASTerm (a, b, c)) where +instance (AnnotLit a, AnnotLit b, AnnotLit c, Evaluatable a, Evaluatable b, Evaluatable c, Arbitrary (MOTerm a), Arbitrary (MOTerm b), Arbitrary (MOTerm c)) + => Arbitrary (MOTerm (a, b, c)) where arbitrary = scale (`quot` 3) $ Triple <$> arbitrary <*> arbitrary <*> arbitrary -instance (AnnotLit a, Evaluatable a, Arbitrary (ASTerm a)) => Arbitrary (ASTerm (Maybe a)) where +instance (AnnotLit a, Evaluatable a, Arbitrary (MOTerm a)) => Arbitrary (MOTerm (Maybe a)) where arbitrary = frequency [(1, pure Null), (10, Some <$> arbitrary)] -instance Arbitrary (ASTerm Bool) where +instance Arbitrary (MOTerm Bool) where arbitrary = sized $ \(succ -> n) -> -- TODO: use frequency? oneof $ (Bool <$> arbitrary) : if n <= 1 then [] else [ resize (n `div` 3) $ elements [NotEqual @Integer, Equals, GreaterEqual, Greater, LessEqual, Less] <*> arbitrary <*> arbitrary @@ -480,27 +537,27 @@ instance Arbitrary (ASTerm Bool) where , resize (n `div` 2) $ Not <$> arbitrary ] -instance Arbitrary (ASTerm Natural) where +instance Arbitrary (MOTerm Natural) where arbitrary = reasonablyShaped $ subTermPow (`Mod` Five) -instance Arbitrary (ASTerm Integer) where +instance Arbitrary (MOTerm Integer) where arbitrary = reasonablyShaped $ \n -> [ (n, resize (n `div` 2) $ Pos <$> arbitrary) , (n, resize (n `div` 2) $ Neg <$> arbitrary) , (n, resize (n `div` 2) $ Abs <$> arbitrary) , (n, ConvertNatural <$> arbitrary) - , (n `div` 2, ConvertNat <$> (arbitrary @(ASTerm Nat8))) - , (n `div` 2, ConvertNat <$> (arbitrary @(ASTerm Nat16))) - , (n `div` 2, ConvertNat <$> (arbitrary @(ASTerm Nat32))) - , (n `div` 2, ConvertNat <$> (arbitrary @(ASTerm Nat64))) - , (n `div` 3, ConvertWord <$> (arbitrary @(ASTerm Word8))) - , (n `div` 3, ConvertWord <$> (arbitrary @(ASTerm Word16))) - , (n `div` 3, ConvertWord <$> (arbitrary @(ASTerm Word32))) - , (n `div` 3, ConvertWord <$> (arbitrary @(ASTerm Word64))) - , (n `div` 3, ConvertInt <$> (arbitrary @(ASTerm Int8))) - , (n `div` 3, ConvertInt <$> (arbitrary @(ASTerm Int16))) - , (n `div` 3, ConvertInt <$> (arbitrary @(ASTerm Int32))) - , (n `div` 3, ConvertInt <$> (arbitrary @(ASTerm Int64))) + , (n `div` 2, ConvertNat <$> (arbitrary @(MOTerm Nat8))) + , (n `div` 2, ConvertNat <$> (arbitrary @(MOTerm Nat16))) + , (n `div` 2, ConvertNat <$> (arbitrary @(MOTerm Nat32))) + , (n `div` 2, ConvertNat <$> (arbitrary @(MOTerm Nat64))) + , (n `div` 3, ConvertWord <$> (arbitrary @(MOTerm Word8))) + , (n `div` 3, ConvertWord <$> (arbitrary @(MOTerm Word16))) + , (n `div` 3, ConvertWord <$> (arbitrary @(MOTerm Word32))) + , (n `div` 3, ConvertWord <$> (arbitrary @(MOTerm Word64))) + , (n `div` 3, ConvertInt <$> (arbitrary @(MOTerm Int8))) + , (n `div` 3, ConvertInt <$> (arbitrary @(MOTerm Int16))) + , (n `div` 3, ConvertInt <$> (arbitrary @(MOTerm Int32))) + , (n `div` 3, ConvertInt <$> (arbitrary @(MOTerm Int64))) ] <> subTermPow ((`Mod` Five) . Abs) n instance Num a => Num (Maybe a) where @@ -568,7 +625,7 @@ instance KnownNat n => Restricted (BitLimited n Word) where else defaultExponentRestriction class Ord a => Evaluatable a where - evaluate :: ASTerm a -> Maybe a + evaluate :: MOTerm a -> Maybe a data BitLimited (n :: Nat) (a :: *) where @@ -779,11 +836,11 @@ instance Evaluatable a => Evaluatable (Maybe a) where evaluate Null = pure Nothing evaluate (Some a) = Just <$> evaluate a -maskFor :: forall n . KnownNat n => ASTerm (BitLimited n Word) -> Natural +maskFor :: forall n . KnownNat n => MOTerm (BitLimited n Word) -> Natural maskFor _ = fromIntegral $ 2 ^ natVal (Proxy @n) - 1 -eval :: (Restricted a, Integral a) => ASTerm a -> Maybe a +eval :: (Restricted a, Integral a) => MOTerm a -> Maybe a eval Five = pure 5 eval (Neuralgic n) = evalN n eval (Pos n) = eval n @@ -818,11 +875,15 @@ instance Evaluatable Bool where evaluate (Not a) = not <$> evaluate a evaluate (Bool b) = pure b +instance Evaluatable String where + evaluate (Text a) = pure a + evaluate (a `Concat` b) = (<>) <$> evaluate a <*> evaluate b + type AnnotLit t = (Annot t, Literal t) class Annot t where - annot :: ASTerm t -> String -> String - sizeSuffix :: ASTerm t -> String -> String + annot :: MOTerm t -> String -> String + sizeSuffix :: MOTerm t -> String -> String sizeSuffix _ = id instance Annot (a, b) where @@ -840,6 +901,8 @@ instance Annot Integer where instance Annot Natural where annot _ s = "((" <> s <> ") : Nat)" +instance Annot String where + annot _ = id bitWidth :: KnownNat n => Proxy n -> String bitWidth p = show (natVal p) @@ -870,6 +933,9 @@ instance Literal (a, b, c) where instance Literal (Maybe a) where literal _ = error "Literal (Maybe a) makes no sense" +instance Literal String where + literal _ = error "Literal String makes no sense" + instance Literal Integer instance Literal Natural instance Literal (BitLimited n Natural) @@ -886,61 +952,63 @@ instance Literal Bool where inParens :: (a -> String) -> String -> a -> a -> String inParens to op lhs rhs = "(" <> to lhs <> " " <> op <> " " <> to rhs <> ")" -unparseAS :: AnnotLit a => ASTerm a -> String -unparseAS f@Five = annot f "5" -unparseAS a@(Neuralgic n) = annot a $ literal n -unparseAS (Pos n) = "(+" <> unparseAS n <> ")" -unparseAS (Neg n) = "(-" <> unparseAS n <> ")" -unparseAS (Abs n) = "(abs " <> unparseAS n <> ")" -unparseAS (a `Add` b) = inParens unparseAS "+" a b -unparseAS (a `Sub` b) = annot a $ inParens unparseAS "-" a b -unparseAS (a `Mul` b) = inParens unparseAS "*" a b -unparseAS (a `Div` b) = inParens unparseAS "/" a b -unparseAS (a `Mod` b) = inParens unparseAS "%" a b -unparseAS (a `Pow` b) = inParens unparseAS "**" a b -unparseAS (a `Or` b) = inParens unparseAS "|" a b -unparseAS (a `And` b) = inParens unparseAS "&" a b -unparseAS (a `Xor` b) = inParens unparseAS "^" a b -unparseAS (a `RotL` b) = inParens unparseAS "<<>" a b -unparseAS (a `RotR` b) = inParens unparseAS "<>>" a b -unparseAS (a `ShiftL` b) = inParens unparseAS "<<" a b -unparseAS (a `ShiftR` b) = inParens unparseAS ">>" a b -unparseAS (a `ShiftRSigned` b) = inParens unparseAS "+>>" a b -unparseAS (PopCnt n) = sizeSuffix n "(popcntWord" <> " " <> unparseAS n <> ")" -unparseAS (Clz n) = sizeSuffix n "(clzWord" <> " " <> unparseAS n <> ")" -unparseAS (Ctz n) = sizeSuffix n "(ctzWord" <> " " <> unparseAS n <> ")" -unparseAS (Complement a) = "(^ " <> unparseAS a <> ")" -unparseAS (ConvertNatural a) = "(++++(" <> unparseAS a <> "))" -unparseAS (ConvertNat a) = unparseNat Proxy a -unparseAS (ConvertInt a) = unparseInt Proxy a -unparseAS (ConvertWord a) = unparseWord Proxy a -unparseAS (ConvertWordToNat a) = sizeSuffix a "(word" <> "ToNat " <> unparseAS a <> ")" -unparseAS t@(ConvertNatToWord a) = sizeSuffix t "(natToWord" <> " " <> unparseAS a <> ")" -unparseAS (IfThenElse a b c) = "(if (" <> unparseAS c <> ") " <> unparseAS a <> " else " <> unparseAS b <> ")" -unparseAS (a `NotEqual` b) = inParens unparseAS "!=" a b -unparseAS (a `Equals` b) = inParens unparseAS "==" a b -unparseAS (a `GreaterEqual` b) = inParens unparseAS ">=" a b -unparseAS (a `Greater` b) = inParens unparseAS ">" a b -unparseAS (a `LessEqual` b) = inParens unparseAS "<=" a b -unparseAS (a `Less` b) = inParens unparseAS "<" a b -unparseAS (a `ShortAnd` b) = inParens unparseAS "and" a b -unparseAS (a `ShortOr` b) = inParens unparseAS "or" a b -unparseAS (Not a) = "(not " <> unparseAS a <> ")" -unparseAS (Bool False) = "false" -unparseAS (Bool True) = "true" -unparseAS (a `Pair` b) = "(" <> unparseAS a <> ", " <> unparseAS b <> ")" -unparseAS (Triple a b c) = "(" <> unparseAS a <> ", " <> unparseAS b <> ", " <> unparseAS c <> ")" -unparseAS Null = "null" -unparseAS (Some a) = '?' : unparseAS a - -unparseNat :: KnownNat n => Proxy n -> ASTerm (BitLimited n Natural) -> String -unparseNat p a = "(nat" <> bitWidth p <> "ToNat(" <> unparseAS a <> "))" - -unparseInt :: KnownNat n => Proxy n -> ASTerm (BitLimited n Integer) -> String -unparseInt p a = "(int" <> bitWidth p <> "ToInt(" <> unparseAS a <> "))" - -unparseWord :: KnownNat n => Proxy n -> ASTerm (BitLimited n Word) -> String -unparseWord p a = "(word" <> bitWidth p <> "ToNat(" <> unparseAS a <> "))" -- TODO we want signed too: wordToInt +unparseMO :: AnnotLit a => MOTerm a -> String +unparseMO f@Five = annot f "5" +unparseMO a@(Neuralgic n) = annot a $ literal n +unparseMO (Pos n) = "(+" <> unparseMO n <> ")" +unparseMO (Neg n) = "(-" <> unparseMO n <> ")" +unparseMO (Abs n) = "(abs " <> unparseMO n <> ")" +unparseMO (a `Add` b) = inParens unparseMO "+" a b +unparseMO (a `Sub` b) = annot a $ inParens unparseMO "-" a b +unparseMO (a `Mul` b) = inParens unparseMO "*" a b +unparseMO (a `Div` b) = inParens unparseMO "/" a b +unparseMO (a `Mod` b) = inParens unparseMO "%" a b +unparseMO (a `Pow` b) = inParens unparseMO "**" a b +unparseMO (a `Or` b) = inParens unparseMO "|" a b +unparseMO (a `And` b) = inParens unparseMO "&" a b +unparseMO (a `Xor` b) = inParens unparseMO "^" a b +unparseMO (a `RotL` b) = inParens unparseMO "<<>" a b +unparseMO (a `RotR` b) = inParens unparseMO "<>>" a b +unparseMO (a `ShiftL` b) = inParens unparseMO "<<" a b +unparseMO (a `ShiftR` b) = inParens unparseMO ">>" a b +unparseMO (a `ShiftRSigned` b) = inParens unparseMO "+>>" a b +unparseMO (PopCnt n) = sizeSuffix n "(popcntWord" <> " " <> unparseMO n <> ")" +unparseMO (Clz n) = sizeSuffix n "(clzWord" <> " " <> unparseMO n <> ")" +unparseMO (Ctz n) = sizeSuffix n "(ctzWord" <> " " <> unparseMO n <> ")" +unparseMO (Complement a) = "(^ " <> unparseMO a <> ")" +unparseMO (ConvertNatural a) = "(++++(" <> unparseMO a <> "))" +unparseMO (ConvertNat a) = unparseNat Proxy a +unparseMO (ConvertInt a) = unparseInt Proxy a +unparseMO (ConvertWord a) = unparseWord Proxy a +unparseMO (ConvertWordToNat a) = sizeSuffix a "(word" <> "ToNat " <> unparseMO a <> ")" +unparseMO t@(ConvertNatToWord a) = sizeSuffix t "(natToWord" <> " " <> unparseMO a <> ")" +unparseMO (IfThenElse a b c) = "(if (" <> unparseMO c <> ") " <> unparseMO a <> " else " <> unparseMO b <> ")" +unparseMO (a `NotEqual` b) = inParens unparseMO "!=" a b +unparseMO (a `Equals` b) = inParens unparseMO "==" a b +unparseMO (a `GreaterEqual` b) = inParens unparseMO ">=" a b +unparseMO (a `Greater` b) = inParens unparseMO ">" a b +unparseMO (a `LessEqual` b) = inParens unparseMO "<=" a b +unparseMO (a `Less` b) = inParens unparseMO "<" a b +unparseMO (a `ShortAnd` b) = inParens unparseMO "and" a b +unparseMO (a `ShortOr` b) = inParens unparseMO "or" a b +unparseMO (Not a) = "(not " <> unparseMO a <> ")" +unparseMO (Bool False) = "false" +unparseMO (Bool True) = "true" +unparseMO (a `Pair` b) = "(" <> unparseMO a <> ", " <> unparseMO b <> ")" +unparseMO (Triple a b c) = "(" <> unparseMO a <> ", " <> unparseMO b <> ", " <> unparseMO c <> ")" +unparseMO Null = "null" +unparseMO (Some a) = '?' : unparseMO a +unparseMO (Text a) = '"' : (concatMap escape a) <> "\"" +unparseMO (a `Concat` b) = "(" <> unparseMO a <> " # " <> unparseMO b <> ")" + +unparseNat :: KnownNat n => Proxy n -> MOTerm (BitLimited n Natural) -> String +unparseNat p a = "(nat" <> bitWidth p <> "ToNat(" <> unparseMO a <> "))" + +unparseInt :: KnownNat n => Proxy n -> MOTerm (BitLimited n Integer) -> String +unparseInt p a = "(int" <> bitWidth p <> "ToInt(" <> unparseMO a <> "))" + +unparseWord :: KnownNat n => Proxy n -> MOTerm (BitLimited n Word) -> String +unparseWord p a = "(word" <> bitWidth p <> "ToNat(" <> unparseMO a <> "))" -- TODO we want signed too: wordToInt -- TODOs: -- - wordToInt @@ -950,4 +1018,5 @@ unparseWord p a = "(word" <> bitWidth p <> "ToNat(" <> unparseAS a <> "))" -- TO -- - pattern matches (over numeric, bool, structured) -- - trapping flavour-preserving conversions Nat -> NatN -- - bitsize-preserving conversions --- - data ASTerm (p :: {Term, Pattern}) where ... Pattern :: ASValue a => a -> ASTerm (Pattern/both) a +-- - data MOTerm (p :: {Term, Pattern}) where ... Pattern :: MOValue a => a -> MOTerm (Pattern/both) a +-- - Text and Concat tests (partly covered by rope tests) From e3f0efd182d8a4a898590b4dc92a49b7d24185af Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 19 Dec 2019 18:22:48 +0100 Subject: [PATCH 0860/1176] debug_show: Also handle Char (#1060) --- src/ir_passes/show.ml | 3 +++ src/mo_values/show.ml | 3 ++- src/prelude/prelude.ml | 6 ++++++ test/run/ok/show.run-ir.ok | 1 + test/run/ok/show.run-low.ok | 1 + test/run/ok/show.run.ok | 1 + test/run/ok/show.wasm-run.ok | 1 + test/run/show.mo | 1 + 8 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/ir_passes/show.ml b/src/ir_passes/show.ml index 74941f79364..3d111009c2f 100644 --- a/src/ir_passes/show.ml +++ b/src/ir_passes/show.ml @@ -226,6 +226,9 @@ let show_for : T.typ -> Ir.dec * T.typ list = fun t -> | T.(Prim Text) -> define_show t (invoke_prelude_show "@text_of_Text" t (argE t)), [] + | T.(Prim Char) -> + define_show t (invoke_prelude_show "@text_of_Char" t (argE t)), + [] | T.(Prim Null) -> define_show t (textE ("null")), [] diff --git a/src/mo_values/show.ml b/src/mo_values/show.ml index 2879408086b..6f5cd147c92 100644 --- a/src/mo_values/show.ml +++ b/src/mo_values/show.ml @@ -5,7 +5,7 @@ module T = Mo_types.Type let rec can_show t = let open T in match normalize t with - | Prim (Bool|Nat|Int|Text|Null) -> true + | Prim (Bool|Nat|Int|Text|Char|Null) -> true | Prim (Nat8|Int8|Word8) | Prim (Nat16|Int16|Word16) | Prim (Nat32|Int32|Word32) @@ -45,6 +45,7 @@ let rec show_val t v = | T.(Prim Word32), Value.Word32 i -> "0x" ^ Value.Word32.to_string i | T.(Prim Word64), Value.Word64 i -> "0x" ^ Value.Word64.to_string i | T.(Prim Text), Value.Text s -> "\"" ^ s ^ "\"" + | T.(Prim Char), Value.Char c -> "\'" ^ Wasm.Utf8.encode [c] ^ "\'" | T.(Prim Null), Value.Null -> "null" | T.Opt _, Value.Null -> "null" | T.Opt t', Value.Opt v -> "?" ^ parens (show_val t' v) diff --git a/src/prelude/prelude.ml b/src/prelude/prelude.ml index fa83d21defc..2c1a01ababa 100644 --- a/src/prelude/prelude.ml +++ b/src/prelude/prelude.ml @@ -267,6 +267,12 @@ func @text_of_Text(t : Text) : Text { "\"" # t # "\""; }; +func @text_of_Char(c : Char) : Text { + // TODO: Escape properly + "\'" # charToText c # "\'"; +}; + + func @text_has_parens(t : Text) : Bool { switch (t.chars().next()) { case (?'(') true; diff --git a/test/run/ok/show.run-ir.ok b/test/run/ok/show.run-ir.ok index 7f4f28dc1ee..64312e3ecf3 100644 --- a/test/run/ok/show.run-ir.ok +++ b/test/run/ok/show.run-ir.ok @@ -33,3 +33,4 @@ false 42 +42 -42 +'☃' diff --git a/test/run/ok/show.run-low.ok b/test/run/ok/show.run-low.ok index 7f4f28dc1ee..64312e3ecf3 100644 --- a/test/run/ok/show.run-low.ok +++ b/test/run/ok/show.run-low.ok @@ -33,3 +33,4 @@ false 42 +42 -42 +'☃' diff --git a/test/run/ok/show.run.ok b/test/run/ok/show.run.ok index 7f4f28dc1ee..64312e3ecf3 100644 --- a/test/run/ok/show.run.ok +++ b/test/run/ok/show.run.ok @@ -33,3 +33,4 @@ false 42 +42 -42 +'☃' diff --git a/test/run/ok/show.wasm-run.ok b/test/run/ok/show.wasm-run.ok index 7f4f28dc1ee..64312e3ecf3 100644 --- a/test/run/ok/show.wasm-run.ok +++ b/test/run/ok/show.wasm-run.ok @@ -33,3 +33,4 @@ false 42 +42 -42 +'☃' diff --git a/test/run/show.mo b/test/run/show.mo index 88b0131995e..13cc2532662 100644 --- a/test/run/show.mo +++ b/test/run/show.mo @@ -34,3 +34,4 @@ debugPrint(debug_show (42 : Word16)); debugPrint(debug_show (42 : Nat8)); debugPrint(debug_show (42 : Int32)); debugPrint(debug_show (intToInt64 (-42))); +debugPrint(debug_show '☃'); From a14250ca2970b04606bd3203141dadd79c86ffb7 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Fri, 20 Dec 2019 12:11:45 +0000 Subject: [PATCH 0861/1176] factor out async_cap.ml for use by both typecheckers, add Typing.initial_scope for prelude --- src/mo_frontend/typing.ml | 61 ++++++++++++++++++++++---------------- src/mo_frontend/typing.mli | 1 + src/mo_types/async_cap.ml | 13 ++++++++ src/mo_types/scope.ml | 1 - src/pipeline/pipeline.ml | 2 +- src/prelude/prelude.ml | 3 -- 6 files changed, 50 insertions(+), 31 deletions(-) create mode 100644 src/mo_types/async_cap.ml diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 1e7a2c4802f..8e0c4412e00 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -1,5 +1,5 @@ open Mo_def -open Mo_types +open Mo_types open Mo_values module Flags = Mo_config.Flags @@ -8,6 +8,7 @@ open Source module T = Type module A = Effect +module C = Async_cap (* Contexts *) @@ -15,6 +16,12 @@ module A = Effect type lab_env = T.typ T.Env.t type ret_env = T.typ option +let initial_scope = + { Scope.empty with + Scope.typ_env = T.Env.singleton scope_id C.top_cap; + Scope.con_env = T.ConSet.singleton C.top_cap; + } + type env = { vals : Scope.val_env; libs : Scope.lib_env; @@ -23,7 +30,7 @@ type env = objs : Scope.obj_env; labs : lab_env; rets : ret_env; - async : T.con option; + async : C.async_cap; in_actor : bool; in_prog : bool; context : exp' list; @@ -39,7 +46,7 @@ let env_of_scope msgs scope = objs = T.Env.empty; labs = T.Env.empty; rets = None; - async = None; + async = C.initial_cap(); in_actor = false; in_prog = true; context = []; @@ -269,20 +276,27 @@ let rec infer_scope env cs cod = | T.Var (_, n) -> let c = (List.nth cs n) in { env with typs = T.Env.add scope_id (List.nth cs n) env.typs; - async = Some c } + async = C.AsyncCap c } | _ -> env) | _ -> - { env with async = None } + { env with async = C.NullCap } and check_scope env t at = - (match env.async with - | Some c -> + match env.async with + | C.AsyncCap c + | C.AwaitCap c -> if not (T.eq t (T.Con(c,[]))) then - local_error env at "bad scope" - | None -> - if not (T.eq t T.Any) then - local_error env at "bad scope") - + local_error env at "bad scope" + | C.NullCap -> + if not (T.eq t T.Any) then (* TBR *) + local_error env at "bad scope" + +and check_AwaitCap env s at = + match env.async with + | C.AwaitCap c -> T.Con(c, []) + | C.AsyncCap c -> + error env at "misplaced %s; try enclosing in an async expression" s + | C.NullCap -> error env at "misplaced %s" s and check_typ env (typ:typ) : T.typ = let t = check_typ' env typ in @@ -706,7 +720,7 @@ and infer_exp'' env exp : T.typ = | ObjE (sort, fields) -> if not in_prog && sort.it = T.Actor then error_in [Flags.ICMode] env exp.at "non-toplevel actor; an actor can only be declared at the toplevel of a program"; - let env' = if sort.it = T.Actor then {env with async = None; in_actor = true} else env in + let env' = if sort.it = T.Actor then {env with async = C.NullCap; in_actor = true} else env in infer_obj env' sort.it fields exp.at | DotE (exp1, id) -> let t1 = infer_exp_promote env exp1 in @@ -917,8 +931,7 @@ and infer_exp'' env exp : T.typ = end; t | TryE (exp1, cases) -> - if env.async = None then - error env exp.at "misplaced try"; + ignore (check_AwaitCap env "try" exp.at); let t1 = infer_exp env exp1 in let t2 = infer_cases env T.catch T.Non cases in if not env.pre then begin @@ -996,8 +1009,7 @@ and infer_exp'' env exp : T.typ = end; T.Non | ThrowE exp1 -> - if env.async = None then - error env exp.at "misplaced throw"; + ignore (check_AwaitCap env "throw" exp.at); if not env.pre then check_exp env T.throw exp1; T.Non | AsyncE (typ_bind, exp1, typ1) -> @@ -1008,7 +1020,7 @@ and infer_exp'' env exp : T.typ = let c, tb, ce, cs = check_typ_bind env typ_bind in let ce_scope = T.Env.add "@" c ce in (* pun scope identifier @ with c *) let env' = - {(adjoin_typs env ce_scope cs) with labs = T.Env.empty; rets = Some T.Pre; async = Some c} in + {(adjoin_typs env ce_scope cs) with labs = T.Env.empty; rets = Some T.Pre; async = C.AwaitCap c} in let t = infer_exp env' exp1 in let t' = T.open_ [t1] (T.close [c] t) in if not (T.shared t') then @@ -1016,9 +1028,7 @@ and infer_exp'' env exp : T.typ = (T.string_of_typ_expand t'); T.Async (t1, t') | AwaitE exp1 -> - let t0 = match env.async with - | Some c -> T.Con(c, []) - | None -> error env exp.at "misplaced await" in + let t0 = check_AwaitCap env "await" exp.at in let t1 = infer_exp_promote env exp1 in (match exp1.it with | CallE (f, _, _) -> @@ -1102,7 +1112,7 @@ and check_exp' env0 t exp : T.typ = let c, tb, ce, cs = check_typ_bind env tb in let ce_scope = T.Env.add "@" c ce in (* pun scope identifier @ with c *) let env' = - {(adjoin_typs env ce_scope cs) with labs = T.Env.empty; rets = Some t'; async = Some c} in + {(adjoin_typs env ce_scope cs) with labs = T.Env.empty; rets = Some t'; async = C.AwaitCap c} in check_exp env' t' exp1; t | BlockE decs, _ -> @@ -1126,8 +1136,7 @@ and check_exp' env0 t exp : T.typ = ); t | TryE (exp1, cases), _ -> - if env.async = None then - error env exp.at "misplaced try"; + ignore (check_AwaitCap env "try" exp.at); check_exp env t exp1; check_cases env T.catch t cases; (match Coverage.check_cases cases T.catch with @@ -1163,7 +1172,7 @@ and check_exp' env0 t exp : T.typ = { env with labs = T.Env.empty; rets = Some t2; - async = None; } + async = C.NullCap; } in check_exp (adjoin_vals env' ve2) t2 exp; t @@ -1646,7 +1655,7 @@ and infer_dec env dec : T.typ = { (add_val env'' self_id.it self_typ) with labs = T.Env.empty; rets = None; - async = None; + async = C.NullCap; in_actor = sort.it = T.Actor; } in diff --git a/src/mo_frontend/typing.mli b/src/mo_frontend/typing.mli index 43e93f2dcfe..ccbb377f53e 100644 --- a/src/mo_frontend/typing.mli +++ b/src/mo_frontend/typing.mli @@ -4,6 +4,7 @@ open Mo_types open Type open Scope +val initial_scope : scope val infer_prog : scope -> Syntax.prog -> (typ * scope) Diag.result val check_lib : scope -> Syntax.lib -> scope Diag.result val check_actors : scope -> Syntax.prog list -> unit Diag.result diff --git a/src/mo_types/async_cap.ml b/src/mo_types/async_cap.ml new file mode 100644 index 00000000000..6d1f4f404e2 --- /dev/null +++ b/src/mo_types/async_cap.ml @@ -0,0 +1,13 @@ +(* Async capabilities *) +open Mo_config + +module T = Type + +type async_cap = + | NullCap + | AsyncCap of T.con + | AwaitCap of T.con + +let top_cap = Con.fresh "@" (T.Def([],T.Any)) + +let initial_cap () = if !Flags.compiled then NullCap else AsyncCap top_cap diff --git a/src/mo_types/scope.ml b/src/mo_types/scope.ml index b6ab6467ae0..1a7df717e73 100644 --- a/src/mo_types/scope.ml +++ b/src/mo_types/scope.ml @@ -34,7 +34,6 @@ let adjoin scope1 scope2 = obj_env = T.Env.adjoin scope1.obj_env scope2.obj_env; } - let adjoin_val_env scope ve = {scope with val_env = T.Env.adjoin scope.val_env ve} let lib f t = diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index b56ff52bccb..06df8b9d259 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -346,7 +346,7 @@ let check_prelude () : Syntax.prog * stat_env = match parse_with Lexer.Privileged lexer parse prelude_name with | Error e -> prelude_error "parsing" [e] | Ok prog -> - let senv0 = Scope.empty in + let senv0 = Typing.initial_scope in match infer_prog senv0 prog with | Error es -> prelude_error "checking" es | Ok ((_t, sscope), msgs) -> diff --git a/src/prelude/prelude.ml b/src/prelude/prelude.ml index 8ca788a5c8f..fa83d21defc 100644 --- a/src/prelude/prelude.ml +++ b/src/prelude/prelude.ml @@ -24,9 +24,6 @@ type Text = prim "Text"; type Blob = prim "Blob"; type Error = prim "Error"; -// top level scope -type @ = Any; - type Iter = {next : () -> ?T_}; func abs(x : Int) : Nat { (prim "abs" : Int -> Nat) x }; From c7e0cc7cb83ba4ce38b10c1f5a6624070dc90b0f Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Fri, 20 Dec 2019 17:07:52 +0000 Subject: [PATCH 0862/1176] remove scope_inst from async expressions; add impliclity scope_bind to oneways to allow async expressions (sigh) --- src/lowering/desugar.ml | 6 +++- src/mo_def/arrange.ml | 2 +- src/mo_def/syntax.ml | 26 +++++++++------ src/mo_frontend/definedness.ml | 2 +- src/mo_frontend/parser.mly | 32 +++++++++--------- src/mo_frontend/traversals.ml | 2 +- src/mo_frontend/typing.ml | 44 +++++++++++++++++-------- src/mo_interpreter/interpret.ml | 2 +- src/mo_types/type.ml | 13 ++++---- test/run-drun/await-sugar.mo | 6 ++-- test/run-drun/general_await.mo | 39 +++++++++++++--------- test/run-drun/general_await_implicit.mo | 35 +++++++++++--------- test/run-drun/type-lub.mo | 6 ++-- 13 files changed, 128 insertions(+), 87 deletions(-) diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 5117eb43251..1ac0fea28e2 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -147,7 +147,11 @@ and exp' at note = function | S.BreakE (l, e) -> I.BreakE (l.it, exp e) | S.RetE e -> I.RetE (exp e) | S.ThrowE e -> I.ThrowE (exp e) - | S.AsyncE (tb, e, t) -> I.AsyncE (typ_bind tb, exp e, t.Source.note) + | S.AsyncE (tb, e) -> + I.AsyncE (typ_bind tb, exp e, + match note.I.note_typ with + | T.Async (t, _) -> t + | _ -> assert false) | S.AwaitE e -> I.AwaitE (exp e) | S.AssertE e -> I.AssertE (exp e) | S.AnnotE (e, _) -> assert false diff --git a/src/mo_def/arrange.ml b/src/mo_def/arrange.ml index f1bcf6165fe..1a3da173ee6 100644 --- a/src/mo_def/arrange.ml +++ b/src/mo_def/arrange.ml @@ -50,7 +50,7 @@ let rec exp e = match e.it with | DebugE e -> "DebugE" $$ [exp e] | BreakE (i, e) -> "BreakE" $$ [id i; exp e] | RetE e -> "RetE" $$ [exp e] - | AsyncE (tb, e, t) -> "AsyncE" $$ [typ_bind tb; exp e; typ t] + | AsyncE (tb, e) -> "AsyncE" $$ [typ_bind tb; exp e] | AwaitE e -> "AwaitE" $$ [exp e] | AssertE e -> "AssertE" $$ [exp e] | AnnotE (e, t) -> "AnnotE" $$ [exp e; typ t] diff --git a/src/mo_def/syntax.ml b/src/mo_def/syntax.ml index 82814a6fea5..eae38a74f6a 100644 --- a/src/mo_def/syntax.ml +++ b/src/mo_def/syntax.ml @@ -153,7 +153,7 @@ and exp' = | BreakE of id * exp (* break *) | RetE of exp (* return *) | DebugE of exp (* debugging *) - | AsyncE of typ_bind * exp * typ (* async *) + | AsyncE of typ_bind * exp (* async *) | AwaitE of exp (* await *) | AssertE of exp (* assertion *) | AnnotE of exp * typ (* type annotation *) @@ -293,18 +293,24 @@ let ensure_scope_bind tbs = else scope_bind()::tbs let funcT(sort, tbs, t1, t2) = - match t2.it with - | AsyncT (None, _) -> + match sort.it, t2.it with + | _, AsyncT (None, _) -> + FuncT(sort, ensure_scope_bind tbs, t1, t2) + | Type.Shared _, TupT [] -> FuncT(sort, ensure_scope_bind tbs, t1, t2) | _ -> FuncT(sort, tbs, t1, t2) let funcE (f, s, tbs, p, t_opt, e) = - match t_opt with - | None -> FuncE(f, s, tbs, p, t_opt, e) - | Some t -> - (match t.it with - | AsyncT (None, t22) -> - FuncE(f, s, ensure_scope_bind tbs, p, t_opt, e) - | _ -> FuncE(f, s, tbs, p, t_opt, e)) + let t = match t_opt with + | None -> TupT [] + | Some t -> t.it + in + match s.it, t with + | _, AsyncT (None, _) -> + FuncE(f, s, ensure_scope_bind tbs, p, t_opt, e) + | Type.Shared _, TupT [] -> + FuncE(f, s, ensure_scope_bind tbs, p, t_opt, e) + | _ -> + FuncE(f, s, tbs, p, t_opt, e) diff --git a/src/mo_frontend/definedness.ml b/src/mo_frontend/definedness.ml index ee270ae7425..4346f8643f2 100644 --- a/src/mo_frontend/definedness.ml +++ b/src/mo_frontend/definedness.ml @@ -122,7 +122,7 @@ let rec exp msgs e : f = match e.it with | ForE (p, e1, e2) -> exp msgs e1 ++ (exp msgs e2 /// pat msgs p) | LabelE (i, t, e) -> exp msgs e | DebugE e -> exp msgs e - | AsyncE (_, e, _) -> exp msgs e + | AsyncE (_, e) -> exp msgs e | AwaitE e -> exp msgs e | AssertE e -> exp msgs e | AnnotE (e, t) -> exp msgs e diff --git a/src/mo_frontend/parser.mly b/src/mo_frontend/parser.mly index 1bf6fb307f5..32b5db7eb0b 100644 --- a/src/mo_frontend/parser.mly +++ b/src/mo_frontend/parser.mly @@ -63,7 +63,7 @@ let let_or_exp named x e' at = let share_typ t = match t.it with | FuncT ({it = Type.Local; _} as s, tbs, t1, t2) -> - { t with it = FuncT ({s with it = Type.Shared Type.Write}, tbs, t1, t2)} + { t with it = funcT ({s with it = Type.Shared Type.Write}, tbs, t1, t2)} | _ -> t let share_typfield (tf : typ_field) = @@ -72,7 +72,7 @@ let share_typfield (tf : typ_field) = let share_exp e = match e.it with | FuncE (x, ({it = Type.Local; _} as s), tbs, p, t, e) -> - FuncE (x, {s with it = Type.Shared (Type.Write, WildP @! s.at)}, tbs, p, t, e) @? e.at + funcE (x, {s with it = Type.Shared (Type.Write, WildP @! s.at)}, tbs, p, t, e) @? e.at | _ -> e let share_dec d = @@ -85,9 +85,7 @@ let share_expfield (ef : exp_field) = then ef else {ef with it = {ef.it with dec = share_dec ef.it.dec}} -let scope_typ() = scope_typ no_region - - %} +%} %token EOF @@ -257,7 +255,7 @@ typ_pre : typ : | t=typ_pre { t } - | s=func_sort_opt tps=typ_params t1=typ_un ARROW t2=typ + | s=func_sort_opt tps=typ_params_opt t1=typ_un ARROW t2=typ { funcT(s, tps, t1, t2) @! at $sloc } typ_item : @@ -267,14 +265,14 @@ typ_item : typ_args : | LT ts=seplist(typ, COMMA) GT { ts } -%inline typ_params : +%inline typ_params_opt : | (* empty *) { [] } | LT ts=seplist(typ_bind, COMMA) GT { ts } typ_field : | mut=var_opt x=id COLON t=typ { {id = x; typ = t; mut} @@ at $sloc } - | x=id tps=typ_params t1=typ_nullary t2=return_typ + | x=id tps=typ_params_opt t1=typ_nullary t2=return_typ { let t = funcT(Type.Local @@ no_region, tps, t1, t2) @! span x.at t2.at in {id = x; typ = t; mut = Const @@ no_region} @@ at $sloc } @@ -460,9 +458,9 @@ exp_nondec(B) : | RETURN e=exp(ob) { RetE(e) @? at $sloc } | ASYNC e=exp(bl) - { AsyncE(scope_bind(), e, scope_typ()) @? at $sloc } - | ASYNC tb = scope_bind e=exp_nullary(bl) t=scope_inst - { AsyncE(tb, e, t) @? at $sloc } + { AsyncE(scope_bind(), e) @? at $sloc } + | ASYNC tb = scope_bind e=exp_nullary(bl) + { AsyncE(tb, e) @? at $sloc } | AWAIT e=exp(bl) { AwaitE(e) @? at $sloc } | ASSERT e=exp(bl) @@ -639,7 +637,7 @@ dec_nonvar : | AnnotP (p', t) -> p', AnnotE (e, t) @? p.at | _ -> p, e in LetD (p', e') @? at $sloc } - | TYPE x=typ_id tps=typ_params EQ t=typ + | TYPE x=typ_id tps=typ_params_opt EQ t=typ { TypD(x, tps, t) @? at $sloc } | s=obj_sort xf=id_opt EQ? efs=obj_body { let named, x = xf "object" $sloc in @@ -647,7 +645,7 @@ dec_nonvar : if s.it = Type.Actor then List.map share_expfield efs else efs in let_or_exp named x (ObjE(s, efs')) (at $sloc) } | sp=sort_pat FUNC xf=id_opt - tps=typ_params p=pat_param t=return_typ? fb=func_body + tps=typ_params_opt p=pat_param t=return_typ? fb=func_body { (* This is a hack to support local func declarations that return a computed async. These should be defined using RHS syntax EQ e to avoid the implicit AsyncE introduction around bodies declared as blocks *) @@ -656,18 +654,18 @@ dec_nonvar : | (true, e) -> (* body declared as immediate block *) match t with | Some {it = AsyncT (None,_); _} -> - AsyncE(scope_bind(), e, scope_typ()) @? e.at + AsyncE(scope_bind(), e) @? e.at | Some {it = AsyncT (Some typ,_); _} -> (match as_idT typ with | Some id -> - AsyncE(pun_id id, e, typ) @? e.at - | _ -> AsyncE(scope_bind(), e, typ) @? e.at) + AsyncE(pun_id id, e) @? e.at + | _ -> AsyncE(scope_bind(), e) @? e.at) | _ -> e in let named, x = xf "func" $sloc in let_or_exp named x (funcE(x.it, sp, tps, p, t, e)) (at $sloc) } | s=obj_sort_opt CLASS xf=typ_id_opt - tps=typ_params p=pat_param t=return_typ? cb=class_body + tps=typ_params_opt p=pat_param t=return_typ? cb=class_body { let x, efs = cb in let efs' = if s.it = Type.Actor then List.map share_expfield efs else efs diff --git a/src/mo_frontend/traversals.ml b/src/mo_frontend/traversals.ml index 6c96c283042..58301e6edd7 100644 --- a/src/mo_frontend/traversals.ml +++ b/src/mo_frontend/traversals.ml @@ -16,7 +16,7 @@ let rec over_exp (f : exp -> exp) (exp : exp) : exp = match exp.it with | BreakE (x, exp1) -> f { exp with it=BreakE (x, over_exp f exp1) } | RetE exp1 -> f { exp with it=RetE (over_exp f exp1) } | AnnotE (exp1, x) -> f { exp with it=AnnotE (over_exp f exp1, x) } - | AsyncE (tb, exp1, ty) -> f { exp with it = AsyncE (tb, over_exp f exp1, ty) } + | AsyncE (tb, exp1) -> f { exp with it = AsyncE (tb, over_exp f exp1) } | AwaitE exp1 -> f { exp with it=AwaitE (over_exp f exp1) } | ThrowE exp1 -> f { exp with it=ThrowE (over_exp f exp1) } | BinE (x, exp1, y, exp2) -> diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 8e0c4412e00..deaa3fab09f 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -267,9 +267,12 @@ let check_shared_return env at sort c ts = | T.Shared T.Query, _, _ -> error env at "shared query function must have syntactic return type `async `" | _ -> () -let rec infer_scope env cs cod = - match cod.it with - | AsyncT (typ_opt,_) -> +let rec infer_scope env sort cs cod = + let env = { env with async = C.NullCap } in + match sort, cod.it with + | T.Shared T.Query, AsyncT (typ_opt, _) (* remove this case to prevent sends from query methods *) + | T.Shared T.Write, AsyncT (typ_opt, _) + | T.Local, AsyncT (typ_opt, _) -> let typ = match typ_opt with Some typ -> typ | None -> scope_typ no_region in let t = check_typ env typ in (match T.close cs t with @@ -277,9 +280,15 @@ let rec infer_scope env cs cod = let c = (List.nth cs n) in { env with typs = T.Env.add scope_id (List.nth cs n) env.typs; async = C.AsyncCap c } + | _ -> + env) + | T.Shared T.Write, TupT [] -> + (match cs with (* we assume the first parameter is the scope parameter *) + | c::cs -> + { env with typs = T.Env.add scope_id c env.typs; + async = C.AsyncCap c } | _ -> env) - | _ -> - { env with async = C.NullCap } + | _ -> env and check_scope env t at = match env.async with @@ -291,6 +300,12 @@ and check_scope env t at = if not (T.eq t T.Any) then (* TBR *) local_error env at "bad scope" +and check_AsyncCap env s at = + match env.async with + | C.AwaitCap c -> T.Con(c, []) + | C.AsyncCap c -> T.Con(c, []) + | C.NullCap -> error env at "misplaced %s" s + and check_AwaitCap env s at = match env.async with | C.AwaitCap c -> T.Con(c, []) @@ -326,7 +341,7 @@ and check_typ' env typ : T.typ = | FuncT (sort, binds, typ1, typ2) -> let cs, ts, te, ce = check_typ_binds env binds in let env' = adjoin_typs env te ce in - let env' = infer_scope env' cs typ2 in + let env' = infer_scope env' sort.it cs typ2 in let typs1 = as_domT typ1 in let c, typs2 = as_codomT sort.it typ2 in let ts1 = List.map (check_typ env') typs1 in @@ -783,7 +798,7 @@ and infer_exp'' env exp : T.typ = check_shared_return env typ.at sort cT ts2; let cs, ts, te, ce = check_typ_binds env typ_binds in let env' = adjoin_typs env te ce in - let env' = infer_scope env' cs typ in + let env' = infer_scope env' sort cs typ in let t1, ve1 = infer_pat_exhaustive env' pat in let ve2 = T.Env.adjoin ve ve1 in let ts2 = List.map (check_typ env') ts2 in @@ -854,6 +869,11 @@ and infer_exp'' env exp : T.typ = insert n (Syntax.scope_typ {left = exp1.at.right; right = exp2.at.left}) pre_typs + | T.Func (T.Shared _, T.Returns, _, _, []) + when List.length pre_typs = expected - 1 -> + insert 0 + (Syntax.scope_typ {left = exp1.at.right; right = exp2.at.left}) + pre_typs | _ -> pre_typs in insts := Some typs; @@ -1012,11 +1032,10 @@ and infer_exp'' env exp : T.typ = ignore (check_AwaitCap env "throw" exp.at); if not env.pre then check_exp env T.throw exp1; T.Non - | AsyncE (typ_bind, exp1, typ1) -> + | AsyncE (typ_bind, exp1) -> if not (in_shared_async env || in_oneway_ignore env) then error_in [Flags.ICMode] env exp.at "unsupported async block"; - let t1 = check_typ env typ1 in - check_scope env t1 typ1.at; + let t1 = check_AsyncCap env "async expression" exp.at in let c, tb, ce, cs = check_typ_bind env typ_bind in let ce_scope = T.Env.add "@" c ce in (* pun scope identifier @ with c *) let env' = @@ -1100,11 +1119,10 @@ and check_exp' env0 t exp : T.typ = (T.string_of_typ_expand (T.Array t')); List.iter (check_exp env (T.as_immut t')) exps; t - | AsyncE (tb, exp1, typ1), T.Async (t1', t') -> + | AsyncE (tb, exp1), T.Async (t1', t') -> if not (in_shared_async env || in_oneway_ignore env) then error_in [Flags.ICMode] env exp.at "freestanding async expression not yet supported"; - let t1 = check_typ env typ1 in - check_scope env t1 typ1.at; + let t1 = check_AsyncCap env "async expression" exp.at in if not (T.eq t1 t1') then error env exp.at "async at scope\n %s\ncannot produce expected scope\n %s" (T.string_of_typ_expand t1) diff --git a/src/mo_interpreter/interpret.ml b/src/mo_interpreter/interpret.ml index f12684ae6fc..66d0638dd9f 100644 --- a/src/mo_interpreter/interpret.ml +++ b/src/mo_interpreter/interpret.ml @@ -569,7 +569,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = interpret_exp env exp1 (Lib.Option.value env.rets) | ThrowE exp1 -> interpret_exp env exp1 (Lib.Option.value env.throws) - | AsyncE (_, exp1, _) -> + | AsyncE (_, exp1) -> async env exp.at (fun k' r -> diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index e2b3a832209..c4e252b218c 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -1225,12 +1225,12 @@ and string_of_control_cod sugar c vs ts = | Replies, _ -> sprintf "replies %s" (string_of_cod vs ts) and can_sugar t = match t with - | Func(s, Promises (Var(_, n)), tbs, ts1, ts2) - | Func(s, Returns, tbs, ts1, ([Async (Var(_, n),_)] as ts2)) -> - n = 0 && - List.for_all (fun tb -> can_omit n tb.bound) tbs && - List.for_all (can_omit n) ts1 && - List.for_all (can_omit n) ts2 + | Func(s, Promises (Var(_, 0)), tbs, ts1, ts2) + | Func((Shared _ as s), Returns, tbs, ts1, ([] as ts2)) + | Func(s, Returns, tbs, ts1, ([Async (Var(_, 0),_)] as ts2)) -> + List.for_all (fun tb -> can_omit 0 tb.bound) tbs && + List.for_all (can_omit 0) ts1 && + List.for_all (can_omit 0) ts2 | _ -> false and can_omit n t = @@ -1260,6 +1260,7 @@ and string_of_typ' vs t = | Func (s, c, tbs, ts1, ts2) when can_sugar t -> let n = match c, ts2 with | Promises (Var (s,n)), _ -> n + | Returns, [] -> 0 | Returns, [Async (Var (s,n),_)] -> n | _ -> assert false in diff --git a/test/run-drun/await-sugar.mo b/test/run-drun/await-sugar.mo index 68668f9d13b..4a50b148963 100644 --- a/test/run-drun/await-sugar.mo +++ b/test/run-drun/await-sugar.mo @@ -4,12 +4,14 @@ public func f0 () : async () {}; public func test0 () : async () { await f0 ();}; -public func f1 () : async<@> () {}; +/* +public func f1 () : async<@> () {}; // this is now illegal since f1 not (implicitly) parametric public func test1 () : async () { // f1 not parametric, can call f1(), but can't await f1(); ignore f1(); }; +*/ public func f2<@>() : async<@> () {}; @@ -76,7 +78,7 @@ public func test7 () : async () { }; public func test() : async () { - await test1(); +// await test1(); await test2(); await test2b(); await test3(); diff --git a/test/run-drun/general_await.mo b/test/run-drun/general_await.mo index 9a77ffdcca9..ce59f785045 100644 --- a/test/run-drun/general_await.mo +++ b/test/run-drun/general_await.mo @@ -29,27 +29,34 @@ actor Await { public shared func DPA<@>() : async<@>() { let os = Array_init(10, null); - for (i in os.keys()) { - os[i] := ? (Ack<@>()); - }; - for (o in os.vals()) { - switch o { - case (? a) await a; - case null (assert false); - }; - }; + for (i in os.keys()) { + os[i] := ? (Ack<@>()); + }; + for (o in os.vals()) { + switch o { + case (? a) await a; + case null (assert false); + }; + }; }; // Dynamic parallel waiting (with results) - public shared func DPR<@>() : async<@>[Int] { - func f(i:Nat) : async<@> Int = Request<@>(i); - let as = Array_tabulate(10, f); - let res = Array_init(as.len(),-1); - for (i in as.keys()) { - res[i] := (await as[i]); + // Dynamic parallel waiting (with results) + + public shared func DPR<@>() : async<@> [Int] { + let os = Array_init(10, null); + for (i in os.keys()) { + os[i] := ? (Request<@>(i)); + }; + let res = Array_init(os.len(),-1); + for (i in os.keys()) { + switch (os[i]) { + case (? a) res[i] := await a; + case null (assert false); + }; }; - Array_tabulate(as.len(),func i = res[i]) + Array_tabulate(res.len(),func i { res[i] }) }; // Recursive parallel waiting diff --git a/test/run-drun/general_await_implicit.mo b/test/run-drun/general_await_implicit.mo index 1ce3d3671aa..d419e6841f0 100644 --- a/test/run-drun/general_await_implicit.mo +++ b/test/run-drun/general_await_implicit.mo @@ -29,27 +29,32 @@ actor Await { public shared func DPA() : async() { let os = Array_init(10, null); - for (i in os.keys()) { - os[i] := ? (Ack()); - }; - for (o in os.vals()) { - switch o { - case (? a) await a; - case null (assert false); - }; - }; + for (i in os.keys()) { + os[i] := ? (Ack()); + }; + for (o in os.vals()) { + switch o { + case (? a) await a; + case null (assert false); + }; + }; }; // Dynamic parallel waiting (with results) public shared func DPR() : async [Int] { - func f(i:Nat) : async<@> Int = Request(i); - let as = Array_tabulate(10, f); - let res = Array_init(as.len(),-1); - for (i in as.keys()) { - res[i] := await as[i]; + let os = Array_init(10, null); + for (i in os.keys()) { + os[i] := ? (Request(i)); + }; + let res = Array_init(os.len(),-1); + for (i in os.keys()) { + switch (os[i]) { + case (? a) res[i] := await a; + case null (assert false); + }; }; - Array_tabulate(as.len(),func i = res[i]) + Array_tabulate(res.len(),func i { res[i] }) }; // Recursive parallel waiting diff --git a/test/run-drun/type-lub.mo b/test/run-drun/type-lub.mo index 41e7fd815f5..532aaff6d9d 100644 --- a/test/run-drun/type-lub.mo +++ b/test/run-drun/type-lub.mo @@ -52,10 +52,10 @@ actor a { , func (a : Nat) : Nat = 42 ]; - type C = async(?Int); - type D = async(?Nat); + type C<@> = async<@> (?Int); + type D<@> = async<@> (?Nat); - func c0(c : C, d : D) : [C] { ignore([c, d]); [c, d] }; + func c0(c : C<@>, d : D<@>) : [C<@>] { ignore([c, d]); [c, d] }; let c1s = [async ?4, async ?-42]; From 2722600ca59f829ee839329df2285c2515b0562b Mon Sep 17 00:00:00 2001 From: chenyan-dfinity <48968912+chenyan-dfinity@users.noreply.github.com> Date: Sun, 29 Dec 2019 09:32:00 -0800 Subject: [PATCH 0863/1176] IDL-to-Motoko import (#1026) --- design/IDL-Motoko.md | 14 +++- src/exes/didc.ml | 2 +- src/idllib/escape.ml | 12 +-- src/idllib/escape.mli | 1 + src/idllib/pipeline.ml | 19 ++--- src/idllib/pipeline.mli | 2 +- src/idllib/typing.ml | 14 ++-- src/idllib/typing.mli | 3 +- src/lib/lib.ml | 3 +- src/lib/lib.mli | 1 + src/mo_idl/idl_to_mo.ml | 102 +++++++++++++++++++++++++ src/pipeline/dune | 1 + src/pipeline/pipeline.ml | 25 +++--- src/pipeline/resolve_import.ml | 31 ++++---- test/idl/ok/oneway.tc.ok | 2 +- test/idl/oneway.did | 4 +- test/run-drun/idl-mo.mo | 35 +++++++++ test/run-drun/idl-mo/00.did | 23 ++++++ test/run-drun/ok/actor-import.tc.ok | 1 - test/run-drun/ok/idl-mo.ic-stub-run.ok | 4 + 20 files changed, 237 insertions(+), 62 deletions(-) create mode 100644 src/mo_idl/idl_to_mo.ml create mode 100644 test/run-drun/idl-mo.mo create mode 100644 test/run-drun/idl-mo/00.did delete mode 100644 test/run-drun/ok/actor-import.tc.ok create mode 100644 test/run-drun/ok/idl-mo.ic-stub-run.ok diff --git a/design/IDL-Motoko.md b/design/IDL-Motoko.md index 140d53e63dd..3f576c3d822 100644 --- a/design/IDL-Motoko.md +++ b/design/IDL-Motoko.md @@ -130,12 +130,13 @@ i(int) = Int for n = 8, 16, 32, 64 i(float64) = Float i(text) = Text i(reserved) = Any +i(empty) = None i(opt ) = ? i() i(vec ) = [ i() ] i(blob) = [ word8 ] // if Motoko had a bytes type, it would show up here i(record { ;^N }) = ( i(),^N ) if n > 1 // matches tuple short-hand i(record { ;* }) = { if();* } -i(variant { ;* }) = variant { if();* } +i(variant { ;* }) = variant { ivf();* } i(func ) = ifn() i(service { ;* }) = actor { im();* } @@ -143,8 +144,13 @@ if : -> if( : ) = escape() : i() if( : ) = "_" "_": i() // also for implicit labels +ivf : -> +ivf( : null) = escape() : () +ivf( : null) = "_" "_": () +ivf( = if() otherwise + ifn : -> -ifn((,*) -> () oneway) = shared ia() -> () +ifn((,*) -> () oneway) = shared ia() -> () ifn((,*) -> (,*) query?) = shared query? ia(,*) -> async ia(,*) ia : ,* -> @@ -226,8 +232,8 @@ escape = "_" hash() "_" otherwise ``` In other words: Motoko subtyping must be contained in IDL subtyping. - * There is no way to produce `float32` or functions with a `query` annotation. - Importing interfaces that contain these types fails. + * There is no way to produce `float32`. + Importing interfaces that contain `float32` types fails. ## The value mappings diff --git a/src/exes/didc.ml b/src/exes/didc.ml index 8cba5593981..b6550fa209c 100644 --- a/src/exes/didc.ml +++ b/src/exes/didc.ml @@ -45,7 +45,7 @@ let process_file file : unit = | Check -> ignore (Diag.run (Pipeline.check_file file)) | PrettyPrint -> - let (ast, _) = Diag.run (Pipeline.check_file file) in + let (ast, _, _) = Diag.run (Pipeline.check_file file) in printf "%s" (Idllib.Arrange_idl.string_of_prog ast); | Js -> if !out_file = "" then diff --git a/src/idllib/escape.ml b/src/idllib/escape.ml index 29b757c8067..452bec49e4f 100644 --- a/src/idllib/escape.ml +++ b/src/idllib/escape.ml @@ -1,9 +1,9 @@ (* -This module implements the field name mapping from AS to IDL +This module implements the field name mapping from Motoko to IDL and back. -(It could live in as_idl/, but as_idl depends on as_def/, codegen/ needs this -encoding, but codegen/ should not depend on as_def/.) +(It could live in mo_idl/, but mo_idl depends on mo_def/, codegen/ needs this +encoding, but codegen/ should not depend on mo_def/.) *) (* Utilities (cf. lexer.mll) *) @@ -64,7 +64,7 @@ let is_keyword = function | _ -> false -(* Escaping (used for IDL → AS) *) +(* Escaping (used for IDL → Motoko) *) let escape_num h = Printf.sprintf "_%s_" (Lib.Uint32.to_string h) @@ -74,7 +74,7 @@ let escape str = then if ends_with_underscore str then str ^ "_" else str else escape_num (IdlHash.idl_hash str) -(* Unescaping (used for AS → IDL) *) +(* Unescaping (used for Motoko → IDL) *) let is_escaped_num str = match Lib.String.chop_prefix "_" str with @@ -83,7 +83,7 @@ let is_escaped_num str = | Some str when String.length str > 0 && List.for_all is_digit (Lib.String.explode str) - -> Some (Lib.Uint32.of_string str) + -> Lib.Uint32.of_string_opt str | _ -> None end | _ -> None diff --git a/src/idllib/escape.mli b/src/idllib/escape.mli index 61001b6bf46..0bddc015ab9 100644 --- a/src/idllib/escape.mli +++ b/src/idllib/escape.mli @@ -1,5 +1,6 @@ (* This (or a type like this) could move into the IDL AST *) type label = Nat of Lib.Uint32.t | Id of string val escape : string -> string +val escape_num : Lib.Uint32.t -> string val unescape : string -> label val unescape_hash : string -> Lib.Uint32.t diff --git a/src/idllib/pipeline.ml b/src/idllib/pipeline.ml index ffe1e3e2684..ae4453c0833 100644 --- a/src/idllib/pipeline.ml +++ b/src/idllib/pipeline.ml @@ -58,18 +58,18 @@ let parse_file filename : parse_result = (* Type checking *) let check_prog senv prog - : Typing.scope Diag.result = + : (Typing.scope * Syntax.typ option) Diag.result = phase "Checking" prog.Source.note; let r = Typing.check_prog senv prog in (match r with - | Ok (scope, _) -> + | Ok ((scope, _), _) -> if !Flags.verbose then print_stat_te scope; | Error _ -> ()); r (* Imported file loading *) -type load_result = (Syntax.prog * Typing.scope) Diag.result +type load_result = (Syntax.prog * Typing.scope * Syntax.typ option) Diag.result module LibEnv = Env.Make(String) @@ -99,7 +99,7 @@ let chase_imports senv imports = Diag.bind (Resolve_import.resolve prog base) (fun imports -> Diag.bind (go_set imports) (fun () -> Diag.bind (merge_env imports senv !lib_env) (fun base_env -> - Diag.bind (check_prog base_env prog) (fun scope -> + Diag.bind (check_prog base_env prog) (fun (scope, _) -> lib_env := LibEnv.add file scope !lib_env; pending := S.remove file !pending; Diag.return () @@ -113,15 +113,16 @@ let load_prog parse senv = Diag.bind (Resolve_import.resolve prog base) (fun imports -> Diag.bind (chase_imports senv imports) (fun lib_env -> Diag.bind (merge_env imports senv lib_env) (fun base_env -> - Diag.bind (check_prog base_env prog) (fun scope -> - Diag.return (prog, scope)))))) - + Diag.bind (check_prog base_env prog) (fun (scope, actor) -> + Diag.return (prog, scope, actor)))))) + (* Only type checking *) let initial_stat_env = Typing.empty_scope let check_file file : load_result = load_prog (parse_file file) initial_stat_env -let check_prog prog : Typing.scope Diag.result = check_prog initial_stat_env prog +let check_prog prog : Typing.scope Diag.result = + Diag.bind (check_prog initial_stat_env prog) (fun (scope, _) -> Diag.return scope) (* JS Compilation *) @@ -129,6 +130,6 @@ type compile_result = Buffer.t Diag.result let compile_js_file file : compile_result = Diag.bind (check_file file) - (fun (prog, senv) -> + (fun (prog, senv, _) -> phase "JS Compiling" file; Diag.return (Compile_js.compile senv prog)) diff --git a/src/idllib/pipeline.mli b/src/idllib/pipeline.mli index 4e234a159c8..cc18de26f27 100644 --- a/src/idllib/pipeline.mli +++ b/src/idllib/pipeline.mli @@ -1,3 +1,3 @@ -val check_file : string -> (Syntax.prog * Typing.scope) Diag.result +val check_file : string -> (Syntax.prog * Typing.scope * Syntax.typ option) Diag.result val check_prog : Syntax.prog -> Typing.scope Diag.result val compile_js_file : string -> Buffer.t Diag.result diff --git a/src/idllib/typing.ml b/src/idllib/typing.ml index 4650b2fe3bd..0803dda4c9d 100644 --- a/src/idllib/typing.ml +++ b/src/idllib/typing.ml @@ -115,7 +115,9 @@ let rec check_typ env t = | FuncT (ms, t1, t2) -> let t1' = List.map (fun t -> check_typ env t) t1 in let t2' = List.map (fun t -> check_typ env t) t2 in - if List.exists (fun m -> m.it == Oneway) ms && List.length t2 > 0 then + if List.length ms > 1 then + error env t.at "cannot have more than one mode" + else if List.length ms = 1 && (List.hd ms).it = Oneway && List.length t2 > 0 then error env t.at "oneway function has non-unit return type"; FuncT (ms, t1', t2') @@ t.at | OptT t -> OptT (check_typ env t) @@ t.at @@ -203,28 +205,28 @@ and gather_decs env decs = let check_actor env actor_opt = match actor_opt with - | None -> Env.empty + | None -> None | Some t -> (match as_serv env t with | None -> error env t.at "%s is a non-service type\n %s" (string_of_typ t) (string_of_typ t) | Some {it=ServT meths; _} -> let meths' = check_meths env meths in - Env.singleton "service" (ServT (List.sort compare_meth meths') @@ t.at) + Some (ServT (List.sort compare_meth meths') @@ t.at) | Some _ -> assert false ) (* Programs *) -let check_prog scope prog : scope Diag.result = +let check_prog scope prog : (scope * typ option) Diag.result = Diag.with_message_store (fun msgs -> recover_opt (fun prog -> let env = env_of_scope msgs scope in let te = check_decs env prog.it.decs in - ignore (check_actor (env_of_scope msgs te) prog.it.actor); - te + let actor = check_actor (env_of_scope msgs te) prog.it.actor in + (te, actor) ) prog ) diff --git a/src/idllib/typing.mli b/src/idllib/typing.mli index d72f09f07a7..ac41a096560 100644 --- a/src/idllib/typing.mli +++ b/src/idllib/typing.mli @@ -6,5 +6,4 @@ type scope = typ_env val empty_scope : scope -val check_prog : scope -> Syntax.prog -> scope Diag.result - +val check_prog : scope -> Syntax.prog -> (scope * Syntax.typ option) Diag.result diff --git a/src/lib/lib.ml b/src/lib/lib.ml index 2a2210893f9..6ceb3cbdb81 100644 --- a/src/lib/lib.ml +++ b/src/lib/lib.ml @@ -25,7 +25,8 @@ end module Uint32 = struct type t = int32 - let of_string = Int32.of_string + let of_string str = Int32.of_string ("0u" ^ str) + let of_string_opt str = Int32.of_string_opt ("0u" ^ str) let to_string n = Printf.sprintf "%lu" n let add = Int32.add let sub = Int32.sub diff --git a/src/lib/lib.mli b/src/lib/lib.mli index f66d5313f1d..09892d695c5 100644 --- a/src/lib/lib.mli +++ b/src/lib/lib.mli @@ -115,6 +115,7 @@ sig type t val to_string : t -> string val of_string : string -> t + val of_string_opt : string -> t option val of_int : int -> t val to_int : t -> int val of_int32 : int32 -> t diff --git a/src/mo_idl/idl_to_mo.ml b/src/mo_idl/idl_to_mo.ml new file mode 100644 index 00000000000..ac4e8c3e92a --- /dev/null +++ b/src/mo_idl/idl_to_mo.ml @@ -0,0 +1,102 @@ +open Idllib.Syntax +open Source +module M = Mo_types.Type +module I = Idllib.Typing + +let m_env = ref M.Env.empty + +let check_prim p = + match p with + | Null -> M.Prim M.Null + | Bool -> M.Prim M.Bool + | Int -> M.Prim M.Int + | Int8 -> M.Prim M.Int8 + | Int16 -> M.Prim M.Int16 + | Int32 -> M.Prim M.Int32 + | Int64 -> M.Prim M.Int64 + | Nat -> M.Prim M.Nat + | Nat8 -> M.Prim M.Nat8 + | Nat16 -> M.Prim M.Nat16 + | Nat32 -> M.Prim M.Nat32 + | Nat64 -> M.Prim M.Nat64 + | Float32 -> raise (Invalid_argument "float32 not supported") + | Float64 -> M.Prim M.Float + | Text -> M.Prim M.Text + | Reserved -> M.Any + | Empty -> M.Non + +let check_modes ms = + match ms with + | [] -> (M.Write, M.Promises) + | [{it=Oneway; _}] -> (M.Write, M.Returns) + | [{it=Query; _}] -> (M.Query, M.Promises) + | _ -> assert false + +let check_label lab = + match lab.it with + | Named name -> Idllib.Escape.escape name + | Id id -> Idllib.Escape.escape_num id + | Unnamed id -> Idllib.Escape.escape_num id + +let is_tuple fs = + List.length fs > 1 && + let fs = List.mapi (fun i f -> (i, f)) fs in + List.for_all (fun (i, f) -> + match f.it.label.it with + | Unnamed id -> Lib.Uint32.to_int id = i + | _ -> false) fs + +let rec check_typ env t = + match t.it with + | PrimT p -> check_prim p + | VarT {it=id; _} -> + (match M.Env.find_opt id !m_env with + | None -> + let con = Mo_types.Con.fresh id (M.Abs ([], M.Pre)) in + let res_t = M.Con (con, []) in + m_env := M.Env.add id res_t !m_env; + let t' = I.Env.find id env in + let t' = check_typ env t' in + M.set_kind con (M.Def ([], t')); + res_t + | Some t -> t + ) + | OptT t -> M.Opt (check_typ env t) + | VecT t -> M.Array (check_typ env t) + | RecordT fs -> + if is_tuple fs then + M.Tup (List.map (fun f -> check_typ env f.it.typ) fs) + else + let fs = List.map (check_field env) fs in + M.Obj (M.Object, List.sort M.compare_field fs) + | VariantT fs -> + let fs = List.map (check_variant_field env) fs in + M.Variant (List.sort M.compare_field fs) + | FuncT (ms, ts1, ts2) -> + let (s, c) = check_modes ms in + M.Func (M.Shared s, c, [], List.map (check_typ env) ts1, List.map (check_typ env) ts2) + | ServT ms -> + let fs = List.map (check_meth env) ms in + M.Obj (M.Actor, List.sort M.compare_field fs) + | PreT -> assert false +and check_field env f = + M.{lab = check_label f.it.label; typ = check_typ env f.it.typ} +and check_variant_field env f = + match f.it.typ.it with + | PrimT Null -> M.{lab = check_label f.it.label; typ = M.Tup []} + | _ -> check_field env f +and check_meth env (m: typ_meth) = + M.{lab = Idllib.Escape.escape m.it.var.it; typ = check_typ env m.it.meth} + +let check_prog (env: typ I.Env.t) actor : M.typ = + match actor with + | Some {it=ServT ms; _} -> + let fs = List.map (check_meth env) ms in + let fs = M.Env.fold (fun id t fs -> + match t with + | M.Con (c, _) -> M.{lab = id; typ = M.Typ c}::fs + | _ -> assert false) !m_env fs in + M.Obj (M.Actor, List.sort M.compare_field fs) + | None -> assert false + | _ -> assert false + diff --git a/src/pipeline/dune b/src/pipeline/dune index 3828550a006..9cdd009ba05 100644 --- a/src/pipeline/dune +++ b/src/pipeline/dune @@ -2,6 +2,7 @@ (name pipeline) (libraries lib + idllib lang_utils mo_def mo_config diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index 8b3e714ae02..92c6b981ff6 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -256,19 +256,18 @@ let chase_imports parsefn senv0 imports : (Syntax.lib list * Scope.scope) Diag.r ))))) end | Syntax.IDLPath (f, _) -> - Diag.bind (Idllib.Pipeline.check_file f) (fun _ -> - let scaffold_type = - (* hard-coded for test/run-drun/actor-import.mo *) - (* to be replaced with the imported type in #1026 *) - let open Type in - Obj (Actor, [{lab = "go"; typ = Func (Shared Write, Promises, [], [], [Obj (Actor, [])])}]) - in - let sscope = Scope.lib f scaffold_type in - senv := Scope.adjoin !senv sscope; - Diag.warn ri.Source.at "import" - (Printf.sprintf "imported actors assumed to have type %s" - (Type.string_of_typ scaffold_type)) - ) + Diag.bind (Idllib.Pipeline.check_file f) (fun (prog, idl_scope, actor_opt) -> + if actor_opt = None then + Error [{ + Diag.sev = Diag.Error; at = ri.Source.at; cat = "import"; + text = Printf.sprintf "file %s does not define a service" f + }] + else + let actor = Mo_idl.Idl_to_mo.check_prog idl_scope actor_opt in + let sscope = Scope.lib f actor in + senv := Scope.adjoin !senv sscope; + Diag.return () + ) and go_set todo = Diag.traverse_ go todo in Diag.map (fun () -> (List.rev !libs, !senv)) (go_set imports) diff --git a/src/pipeline/resolve_import.ml b/src/pipeline/resolve_import.ml index 641f2dceb45..251607880da 100644 --- a/src/pipeline/resolve_import.ml +++ b/src/pipeline/resolve_import.ml @@ -157,21 +157,22 @@ let resolve_import_string msgs base actor_idl_path aliases packages imported (f, add_idl_import msgs imported ri_ref at full_path bytes in match Url.parse f with - | Ok (Url.Relative path) -> - add_lib_import msgs imported ri_ref at (in_base base path) - | Ok (Url.Package (pkg,path)) -> - begin match M.find_opt pkg packages with - | Some pkg_path -> add_lib_import msgs imported ri_ref at (in_base pkg_path path) - | None -> err_package_not_defined msgs at pkg - end - | Ok (Url.Ic bytes) -> resolve_ic bytes - | Ok (Url.IcAlias alias) -> - begin match M.find_opt alias aliases with - | Some bytes -> resolve_ic bytes - | None -> err_alias_not_defined msgs at alias - end - | Error msg -> - err_unrecognized_url msgs at f msg + | Ok (Url.Relative path) -> + (* TODO support importing local .did file *) + add_lib_import msgs imported ri_ref at (in_base base path) + | Ok (Url.Package (pkg,path)) -> + begin match M.find_opt pkg packages with + | Some pkg_path -> add_lib_import msgs imported ri_ref at (in_base pkg_path path) + | None -> err_package_not_defined msgs at pkg + end + | Ok (Url.Ic bytes) -> resolve_ic bytes + | Ok (Url.IcAlias alias) -> + begin match M.find_opt alias aliases with + | Some bytes -> resolve_ic bytes + | None -> err_alias_not_defined msgs at alias + end + | Error msg -> + err_unrecognized_url msgs at f msg (* Resolve the argument to --package. These can also be relative to base *) let resolve_package_url (msgs:Diag.msg_store) (base:filepath) (pname:string) (f:url) : filepath = diff --git a/test/idl/ok/oneway.tc.ok b/test/idl/ok/oneway.tc.ok index c06d4d1af22..8e8c5677f5a 100644 --- a/test/idl/ok/oneway.tc.ok +++ b/test/idl/ok/oneway.tc.ok @@ -1 +1 @@ -oneway.did:2.15-2.42: type error, oneway function has non-unit return type +oneway.did:2.15-2.36: type error, oneway function has non-unit return type diff --git a/test/idl/oneway.did b/test/idl/oneway.did index 7ac77bb19cf..8f94446320d 100644 --- a/test/idl/oneway.did +++ b/test/idl/oneway.did @@ -1,3 +1,3 @@ -type g = func (nat) -> () oneway query; -type f = func (nat) -> (nat) query oneway; +type g = func (nat) -> () oneway; +type f = func (nat) -> (nat) oneway; diff --git a/test/run-drun/idl-mo.mo b/test/run-drun/idl-mo.mo new file mode 100644 index 00000000000..96fe7a99d16 --- /dev/null +++ b/test/run-drun/idl-mo.mo @@ -0,0 +1,35 @@ +//MOC-FLAG --actor-idl idl-mo + +import imported "ic:00"; +/* +type node = {head : Nat; tail : list}; +type list = ?node; +type o = ?o; +type stream = ?{head : Nat; next : shared query () -> async stream}; +type tree = {#branch : {left : tree; right : tree; val : Int}; #leaf : Int}; +type s = actor {f : t; g : shared list -> async (tree, stream)}; +type t = shared s -> async (); + +type field = shared {_1291438163_ : Nat8; test : tree} -> async {}; +*/ + +type expected = actor { + _2669435454_ : shared () -> async (); + field : shared {_1291438163_ : Nat8; test : Nat16} -> async {}; + fieldnat : shared {_2_ : Int; _50_ : Nat} -> async {_0_ : Int}; + //o : shared o -> async o; + oneway : shared Nat8 -> (); + query_ : shared query [Nat8] -> async [Nat8]; + //service : t; + tuple : shared ((Int, [Nat8], Text)) -> async {_0_ : Int; _1_ : Nat8}; + variant : shared {#A; #B; #C; #D : Float} -> async () +}; + +ignore ([var imported] : [var expected]); // variable arrays are invariant, so this checks type equality. + +//SKIP run +//SKIP run-ir +//SKIP run-low +//SKIP drun-run +//SKIP wasm-run + diff --git a/test/run-drun/idl-mo/00.did b/test/run-drun/idl-mo/00.did new file mode 100644 index 00000000000..8b830dd46d1 --- /dev/null +++ b/test/run-drun/idl-mo/00.did @@ -0,0 +1,23 @@ +/* +type o = opt o; +type node = record {head:nat; tail:list}; +type list = opt node; +type tree = variant { + leaf : int; + branch : record { left : tree; val : int; right : tree }; +}; +type s = service { f : t; g : (list) -> (tree,stream); }; +type t = func (server : s) -> (); +type stream = opt record {head:nat; next:func ()-> (stream) query}; +*/ +service : { + //o: (o) -> (o); + fieldnat: (record {2 : int; "2": nat}) -> (record { int }); + field: (record {test: nat16; nat8;}) -> (record {}); + "variant": (variant { A; B; C: null; D: float64}) -> (); + oneway: (nat8) -> () oneway; + query: (blob) -> (blob) query; + //"service": t; + "👀": () -> (); + tuple: (record { int; blob; text }) -> (record { int; 1: nat8 }); +} diff --git a/test/run-drun/ok/actor-import.tc.ok b/test/run-drun/ok/actor-import.tc.ok deleted file mode 100644 index f33bef8ed9a..00000000000 --- a/test/run-drun/ok/actor-import.tc.ok +++ /dev/null @@ -1 +0,0 @@ -actor-import.mo:10.1-10.33: warning, imported actors assumed to have type actor {go : shared () -> async actor {}} diff --git a/test/run-drun/ok/idl-mo.ic-stub-run.ok b/test/run-drun/ok/idl-mo.ic-stub-run.ok new file mode 100644 index 00000000000..54225bc8555 --- /dev/null +++ b/test/run-drun/ok/idl-mo.ic-stub-run.ok @@ -0,0 +1,4 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed From 91e8fb355506130001e59b7a979ef10d2c42d459 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 2 Jan 2020 08:21:22 -0700 Subject: [PATCH 0864/1176] fix bug in hashtable clone; fix bug in test --- stdlib/hashtbl.mo | 2 +- stdlib/hashtblTest.mo | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/hashtbl.mo b/stdlib/hashtbl.mo index 357d226d2fa..22cc27ab544 100644 --- a/stdlib/hashtbl.mo +++ b/stdlib/hashtbl.mo @@ -78,7 +78,7 @@ public class Hashtbl ( case null { break moveKeyVals }; case (?((k, v), kvsTail)) { let h = word32ToNat(keyHash(k)); - let pos2 = h % table.len(); + let pos2 = h % table2.len(); table2[pos2] := ?((k,v), table2[pos2]); kvs := kvsTail; }; diff --git a/stdlib/hashtblTest.mo b/stdlib/hashtblTest.mo index ecda25fa96d..2cee2faf1bd 100644 --- a/stdlib/hashtblTest.mo +++ b/stdlib/hashtblTest.mo @@ -51,7 +51,7 @@ debug { case (?1111) { }; case _ { assert false }; }; - switch (a.get("apple")) { + switch (a.get("banana")) { case (?2222) { }; case _ { assert false }; }; From f6c17f5b1e5257e6de3fe62e5df365c73ab470b6 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 2 Jan 2020 08:30:34 -0700 Subject: [PATCH 0865/1176] fix typo --- stdlib/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/Makefile b/stdlib/Makefile index 70acafbdaa8..c1c972e8f6c 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -86,7 +86,7 @@ $(OUTDIR)/BufTest.out: bufTest.mo | $(OUTDIR) $(OUTDIR)/HashtblTest.out: HashtblTest.mo | $(OUTDIR) $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ -$(OUTDIR)/Hashtbl.out: Hashtbl.mo | $(OUTDIR) +$(OUTDIR)/Hashtbl.out: hashtbl.mo | $(OUTDIR) $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ $(OUTDIR)/Function.out: function.mo | $(OUTDIR) From 75fcbce06764d2cbe9ba6d9a76c4a0ee0b2922f2 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 2 Jan 2020 08:35:14 -0700 Subject: [PATCH 0866/1176] fix upper/lowercase typo --- stdlib/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/Makefile b/stdlib/Makefile index c1c972e8f6c..8c443dfe129 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -83,7 +83,7 @@ $(OUTDIR)/Buf.out: buf.mo | $(OUTDIR) $(OUTDIR)/BufTest.out: bufTest.mo | $(OUTDIR) $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ -$(OUTDIR)/HashtblTest.out: HashtblTest.mo | $(OUTDIR) +$(OUTDIR)/HashtblTest.out: hashtblTest.mo | $(OUTDIR) $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ $(OUTDIR)/Hashtbl.out: hashtbl.mo | $(OUTDIR) From 31769d1fccb385e95d7ed5395c8386d260e88d35 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 2 Jan 2020 08:36:48 -0700 Subject: [PATCH 0867/1176] fix upper/lowercase typos in motoko imports --- stdlib/hashtblTest.mo | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/hashtblTest.mo b/stdlib/hashtblTest.mo index 2cee2faf1bd..3e48a586267 100644 --- a/stdlib/hashtblTest.mo +++ b/stdlib/hashtblTest.mo @@ -1,5 +1,5 @@ -import H "Hashtbl.mo"; -import Hash "Hash.mo"; +import H "hashtbl.mo"; +import Hash "hash.mo"; func textIsEq(x:Text,y:Text):Bool { x == y }; From 30caea684f2bee5e9cd034cd97889c2256afe8a4 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 2 Jan 2020 08:44:40 -0700 Subject: [PATCH 0868/1176] address Andreas's review comments --- stdlib/hashtbl.mo | 19 +++++++++++++++++-- stdlib/hashtblTest.mo | 4 ++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/stdlib/hashtbl.mo b/stdlib/hashtbl.mo index 22cc27ab544..9f909d0155f 100644 --- a/stdlib/hashtbl.mo +++ b/stdlib/hashtbl.mo @@ -24,7 +24,7 @@ Internally, table growth policy is very simple, for now: */ // key-val list type -public type KVs = AssocList.AssocList; +type KVs = AssocList.AssocList; public class Hashtbl ( initCapacity: Nat, @@ -36,7 +36,7 @@ public class Hashtbl ( public func count() : Nat = _count; - public func remove(k:K) : ?V { + public func del(k:K) : ?V { let h = word32ToNat(keyHash(k)); let m = table.len(); let pos = h % m; @@ -142,6 +142,21 @@ public func clone h2 }; +public func map + (h:Hashtbl, + initCapacity: Nat, + keyEq: (K,K) -> Bool, + keyHash: K -> Hash.Hash, + mapFn: (K, V1) -> V2, + ) : Hashtbl { + let h2 = Hashtbl(h.count(), keyEq, keyHash); + for ((k, v1) in h.iter()) { + let v2 = mapFn(k, v1); + ignore h2.set(k,v2); + }; + h2 +}; + public func mapFilter (h:Hashtbl, initCapacity: Nat, diff --git a/stdlib/hashtblTest.mo b/stdlib/hashtblTest.mo index 3e48a586267..c01e358e8c6 100644 --- a/stdlib/hashtblTest.mo +++ b/stdlib/hashtblTest.mo @@ -43,8 +43,8 @@ debug { // do some more operations: ignore a.set("apple", 1111); ignore a.set("banana", 2222); - ignore a.remove("pear"); - ignore a.remove("avocado"); + ignore a.del("pear"); + ignore a.del("avocado"); // check them: switch (a.get("apple")) { From 16f4dfd061a78565f4df372535c32033cacf6c1e Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Thu, 2 Jan 2020 11:27:08 -0700 Subject: [PATCH 0869/1176] feedback from Roman --- stdlib/hashtbl.mo | 15 ++++++++++++--- stdlib/hashtblTest.mo | 2 +- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/stdlib/hashtbl.mo b/stdlib/hashtbl.mo index 9f909d0155f..93852bd2d5c 100644 --- a/stdlib/hashtbl.mo +++ b/stdlib/hashtbl.mo @@ -132,7 +132,6 @@ public class Hashtbl ( // ...but is still useful in tests, and beyond. public func clone (h:Hashtbl, - initCapacity: Nat, keyEq: (K,K) -> Bool, keyHash: K -> Hash.Hash) : Hashtbl { let h2 = Hashtbl(h.count(), keyEq, keyHash); @@ -142,9 +141,20 @@ public func clone h2 }; +// Clone from any iterator of key-value pairs +public func fromIter(iter:Iter<(K, V)>, + initCapacity: Nat, + keyEq: (K,K) -> Bool, + keyHash: K -> Hash.Hash) : Hashtbl { + let h = Hashtbl(initCapacity, keyEq, keyHash); + for ((k,v) in h.iter()) { + ignore h.set(k,v); + }; + h +}; + public func map (h:Hashtbl, - initCapacity: Nat, keyEq: (K,K) -> Bool, keyHash: K -> Hash.Hash, mapFn: (K, V1) -> V2, @@ -159,7 +169,6 @@ public func map public func mapFilter (h:Hashtbl, - initCapacity: Nat, keyEq: (K,K) -> Bool, keyHash: K -> Hash.Hash, mapFn: (K, V1) -> ?V2, diff --git a/stdlib/hashtblTest.mo b/stdlib/hashtblTest.mo index c01e358e8c6..a433c19bcda 100644 --- a/stdlib/hashtblTest.mo +++ b/stdlib/hashtblTest.mo @@ -20,7 +20,7 @@ debug { ignore a.set("AvocadO", 444); // need to resupply the constructor args; they are private to the object; but, should they be? - let b = H.clone(a, 3, textIsEq, Hash.Hash.hashOfText); + let b = H.clone(a, textIsEq, Hash.Hash.hashOfText); // ensure clone has each key-value pair present in original for ((k,v) in a.iter()) { From 87d700f3acfba6284bc7ef1ec4b904b65a3bf521 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Thu, 2 Jan 2020 23:55:53 +0100 Subject: [PATCH 0870/1176] Clean up comments w.r.t. concatenation (#1069) * clean up comments w.r.t. concatenation fix a few typos too * Apply suggestions from code review Co-authored-by: Joachim Breitner --- rts/text.c | 9 ++++----- test/run/text-concat.mo | 16 ++++++++-------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/rts/text.c b/rts/text.c index 3bc2a64316c..afab1543cfc 100644 --- a/rts/text.c +++ b/rts/text.c @@ -3,19 +3,18 @@ The implementation of the Text type in Motoko. One main goal of this datastructure (inspired by ropes and similar) is to support constant time concatenation, by having a dedicated heap object for -the concatentation of two strings. +the concatenation of two strings. -The current implementation does not do any of this; the first goal is to wire up +The first goal was to wire up this C code with the RTS that encapsulates the internals of strings. This encapsulation is not complete (and likely never will) * the compiler needs to emit static text literals, * the garbage collector needs to know some of the internals. -In a subsequent step, the actual concatentation node will be introduced. +In a subsequent step, the actual concatenation node has been introduced. -From then on, there are stretch goals like: - - when concatenating short (<= 8 bytes maybe) strings, just copy them +From here on, there are stretch goals like: - restructure recursive code to not use unbounded C stack - maybe rebalancing */ diff --git a/test/run/text-concat.mo b/test/run/text-concat.mo index e375ff0ec2c..b5366b9bba0 100644 --- a/test/run/text-concat.mo +++ b/test/run/text-concat.mo @@ -1,24 +1,24 @@ assert ("Hello " # "World!" == "Hello World!"); assert ( - "This is a test of string " # "concatentation" + "This is a test of string " # "concatenation" == - "This is a " # "test of string concatentation" + "This is a " # "test of string concatenation" ); assert ( - "This is a " # "test of string concatentation" + "This is a " # "test of string concatenation" == - "This is a test of string " # "concatentation" + "This is a test of string " # "concatenation" ); assert ( - "This is a test of string " # "concatentation" + "This is a test of string " # "concatenation" < - "This is a " # "test of string concatentation with " # "more text" + "This is a " # "test of string concatenation with " # "more text" ); assert ( - "This is a " # "test of string concatentation with " # "more text" + "This is a " # "test of string concatenation with " # "more text" > - "This is a test of string " # "concatentation" + "This is a test of string " # "concatenation" ); From 394a0eda8e963dde7096ff2f68dc89eed54f8583 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 3 Jan 2020 19:57:41 +0100 Subject: [PATCH 0871/1176] Create test/perf, record file sizes (#1064) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Create test/perf, record file sizes this is the first step towards performance tracking: * Creates a dedicated directory `test/perf` for a set of “realistic” programs with “realistic” workload that we want to track performance. (Our other regression tests are not suitable for that.) * For each program therein, records the size of the wasm binary. (Maybe we should report the size after stripping optional sections, i.e. `names`?) Next steps: * Get `drun` to tell us about the amount of gas we used, and maybe other stats (memory size, page churn) (https://github.com/dfinity-lab/dfinity/pull/2193) * Report changes in these numbers in PRs (#1065). * Set up gipeda (or something like this) to show nice graphs. --- default.nix | 8 ++++ test/Makefile | 5 ++ test/README.md | 28 ++++++++++- test/perf/Makefile | 12 +++++ .../{run-drun => perf}/ok/reversi.drun-run.ok | 0 test/{run-drun => perf}/reversi.mo | 0 test/run-drun/ok/reversi.ic-stub-run.ok | 20 -------- test/run.sh | 46 +++++++++++++++---- 8 files changed, 90 insertions(+), 29 deletions(-) create mode 100644 test/perf/Makefile rename test/{run-drun => perf}/ok/reversi.drun-run.ok (100%) rename test/{run-drun => perf}/reversi.mo (100%) delete mode 100644 test/run-drun/ok/reversi.ic-stub-run.ok diff --git a/default.nix b/default.nix index a1fcbd91d89..0d49c85bbd1 100644 --- a/default.nix +++ b/default.nix @@ -249,6 +249,13 @@ rec { ''; }; in + let perf_subdir = dir: deps: + (test_subdir dir deps).overrideAttrs (args: { + checkPhase = '' + export PERF_OUT=$out + '' + args.checkPhase; + }); in + let qc = testDerivation { name = "test-qc"; # maybe use wasm instead? @@ -283,6 +290,7 @@ rec { { run = test_subdir "run" [ moc ] ; run-drun = test_subdir "run-drun" [ moc drun ic-stub ]; + perf = perf_subdir "perf" [ moc drun ]; fail = test_subdir "fail" [ moc ]; repl = test_subdir "repl" [ moc ]; ld = test_subdir "ld" [ mo-ld ]; diff --git a/test/Makefile b/test/Makefile index d58ab8caf74..c68229fcc9b 100644 --- a/test/Makefile +++ b/test/Makefile @@ -2,6 +2,7 @@ all: $(MAKE) -C fail $(MAKE) -C run $(MAKE) -C run-drun + $(MAKE) -C perf $(MAKE) -C repl $(MAKE) -C ld $(MAKE) -C idl @@ -20,6 +21,7 @@ quick: parallel: quick $(MAKE_PAR) -C run-drun quick + $(MAKE_PAR) -C perf quick $(MAKE_PAR) -C trap quick $(MAKE_PAR) -C run-deser quick @@ -31,6 +33,7 @@ coverage: $(MAKE) -C fail; \ $(MAKE) -C run; \ $(MAKE) -C run-drun; \ + $(MAKE) -C perf; \ $(MAKE) -C repl; $(MAKE) -C ld || true bisect-ppx-report -I ../src/_build/ -html coverage/ _coverage/bisect*.out @@ -40,6 +43,7 @@ accept: $(MAKE) -C fail accept $(MAKE) -C run accept $(MAKE) -C run-drun accept + $(MAKE) -C perf accept $(MAKE) -C repl accept $(MAKE) -C ld accept $(MAKE) -C idl accept @@ -51,6 +55,7 @@ clean: $(MAKE) -C fail clean $(MAKE) -C run clean $(MAKE) -C run-drun clean + $(MAKE) -C perf clean $(MAKE) -C repl clean $(MAKE) -C ld clean $(MAKE) -C mo-idl clean diff --git a/test/README.md b/test/README.md index 6ca993c1438..b0a6518e0e6 100644 --- a/test/README.md +++ b/test/README.md @@ -30,7 +30,8 @@ to run and ./run.sh -a run/fac.mo -to accept. +to accept. Check `run.sh` for other flags (e.g. drun-mode), and see `Makefile` +in each subdirectory for the right flags for that directory. Adding a new test ----------------- @@ -49,7 +50,32 @@ You can run the test suite from the `motoko` (top-level) directory as: $ nix-build -A tests ``` +You can also run individual directories via, say, + +``` shell +$ nix-build -A tests.run-drun +``` + Randomised testing ------------------ See `README.md` in the `random/` subdirectory. + +Performance regression testing +------------------------------ + +The purpose of the `perf/` directory is to have a small (<20) set of test +programs representative of real use of Motoko. + +For these tests the test suite records the following numbers: + +* Size of the produced Wasm binary. +* Gas consumed by a single run in drun [not yet implemented] + +The numbers are written to `_out/stats.csv`, and are also the output of the nix +derivation `tests.perf`. + +The format is a simple CSV format, as consumed by +[gipeda](https://github.com/nomeata/gipeda). + +Every PR reports a summary of changes to these numbers to the PR. [not yet implemented] diff --git a/test/perf/Makefile b/test/perf/Makefile new file mode 100644 index 00000000000..37290697cf4 --- /dev/null +++ b/test/perf/Makefile @@ -0,0 +1,12 @@ +RUNFLAGS = -p + +all: + ../run.sh $(RUNFLAGS) *.mo + +accept: + ../run.sh $(RUNFLAGS) -a *.mo + +clean: + rm -rf _out + +include ../*.mk diff --git a/test/run-drun/ok/reversi.drun-run.ok b/test/perf/ok/reversi.drun-run.ok similarity index 100% rename from test/run-drun/ok/reversi.drun-run.ok rename to test/perf/ok/reversi.drun-run.ok diff --git a/test/run-drun/reversi.mo b/test/perf/reversi.mo similarity index 100% rename from test/run-drun/reversi.mo rename to test/perf/reversi.mo diff --git a/test/run-drun/ok/reversi.ic-stub-run.ok b/test/run-drun/ok/reversi.ic-stub-run.ok deleted file mode 100644 index 2bddbf68bb6..00000000000 --- a/test/run-drun/ok/reversi.ic-stub-run.ok +++ /dev/null @@ -1,20 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -← completed -→ update reset(0x4449444c0000) -← completed: 0x4449444c0000 -→ update board(0x4449444c0000) -← completed: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e4f2a2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a -→ update place(0x4449444c00037c7c7c010204) -← completed: 0x4449444c000171024f4b -→ update board(0x4449444c0000) -← completed: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e4f2e2e2e0a2e2e2e4f4f2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a -→ update place(0x4449444c00037c7c7c020203) -← completed: 0x4449444c000171024f4b -→ update board(0x4449444c0000) -← completed: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a -→ update place(0x4449444c00037c7c7c010402) -← completed: 0x4449444c000171024f4b -→ update board(0x4449444c0000) -← completed: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e4f4f2e2e2e0a2e2e4f4f4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a diff --git a/test/run.sh b/test/run.sh index eba626288b5..59e71d7606b 100755 --- a/test/run.sh +++ b/test/run.sh @@ -11,6 +11,8 @@ # -t: Only typecheck # -s: Be silent in sunny-day execution # -i: Only check mo to idl generation +# -p: Produce perf statistics +# only compiles and runs drun, writes stats to $PERF_OUT # function realpath() { @@ -21,6 +23,7 @@ function realpath() { ACCEPT=no DRUN=no IDL=no +PERF=no MOC=${MOC:-$(realpath $(dirname $0)/../src/moc)} MO_LD=${MO_LD:-$(realpath $(dirname $0)/../src/mo-ld)} DIDC=${DIDC:-$(realpath $(dirname $0)/../src/didc)} @@ -32,7 +35,7 @@ SKIP_RUNNING=${SKIP_RUNNING:-no} ONLY_TYPECHECK=no ECHO=echo -while getopts "adstir" o; do +while getopts "adpstir" o; do case "${o}" in a) ACCEPT=yes @@ -40,6 +43,9 @@ while getopts "adstir" o; do d) DRUN=yes ;; + p) + PERF=yes + ;; s) ECHO=true ;; @@ -130,6 +136,14 @@ function run_if () { fi } +if [ "$PERF" = "yes" ] +then + if [ -z "$PERF_OUT" ] + then + echo "Warning: \$PERF_OUT not set" >&2 + fi +fi + for file in "$@"; do if ! [ -r $file ] @@ -193,7 +207,7 @@ do run didc $DIDC --check $out/$base.did fi else - if [ "$SKIP_RUNNING" != yes ] + if [ "$SKIP_RUNNING" != yes -a "$PERF" != yes ] then # Interpret run run $MOC $moc_extra_flags --hide-warnings -r $base.mo @@ -240,12 +254,15 @@ do # Compile - if [ $DRUN = no ] + if [ $DRUN = yes ] then - run comp $MOC $moc_extra_flags -wasi-system-api --hide-warnings --map -c $mangled -o $out/$base.wasm - else run comp $MOC $moc_extra_flags --hide-warnings --map -c $mangled -o $out/$base.wasm run comp-stub $MOC $moc_extra_flags -stub-system-api --hide-warnings --map -c $mangled -o $out/$base.stub.wasm + elif [ $PERF = yes ] + then + run comp $MOC $moc_extra_flags --hide-warnings --map -c $mangled -o $out/$base.wasm + else + run comp $MOC $moc_extra_flags -wasi-system-api --hide-warnings --map -c $mangled -o $out/$base.wasm fi run_if wasm valid wasm-validate $out/$base.wasm @@ -269,15 +286,28 @@ do # Run compiled program if [ "$SKIP_RUNNING" != yes ] then - if [ $DRUN = no ] + if [ $DRUN = yes ] then - run_if wasm wasm-run $WASMTIME --disable-cache $out/$base.wasm - else run_if wasm drun-run $DRUN_WRAPPER $out/$base.wasm $mangled DRUN=$IC_STUB_RUN \ run_if stub.wasm ic-stub-run $DRUN_WRAPPER $out/$base.stub.wasm $mangled + elif [ $PERF = yes ] + then + run_if wasm drun-run $DRUN_WRAPPER $out/$base.wasm $mangled + else + run_if wasm wasm-run $WASMTIME --disable-cache $out/$base.wasm fi fi + + # collect size stats + if [ "$PERF" = yes -a -e "$out/$base.wasm" ] + then + if [ -n "$PERF_OUT" ] + then + echo "size/$base;$(stat --format=%s $out/$base.wasm)" >> $PERF_OUT + fi + fi + rm -f $mangled fi fi From e15d6016197d9d2ca9ae72e00a6d7c3afca0f5bb Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Sat, 4 Jan 2020 20:06:44 +0100 Subject: [PATCH 0872/1176] Bump drun (#1062) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mainly to get multi-canister drun https://github.com/dfinity-lab/dfinity/pull/2118 and also https://github.com/dfinity-lab/dfinity/pull/2193 Requires to insert canister id in drun. This means we know the id of the test canister, which makes tests like `actor-import.mo` easier to write and to run across both `drun` and `ic-stub`. Updates IC Stub to read updated `drun` format and implement the “desired id” field of `InstallRequest` Updates test output becaues `drun` now runs commands to completion, and we get more output. That’s good. Also included ``` 48ab58e7b MR: handle invalid destinations (#2187) 83a6377ac DFN-1260: Add an option to dump metrics into a file (#2193) 62161fdd7 Merge pull request #2135 from dfinity-lab/addLogger 421a2e53e Merge pull request #2201 from dfinity-lab/rsub/xport-init 61766a245 Merge pull request #2199 from dfinity-lab/rsub/xport-retry 7b020dd2b Have cargo test -p ic-metrics not fail, by explicitly adding the serde derive dependency. (#2191) 011a67717 Implement a proper display function for canister ids (#2188) 11889b8b3 StateManager: safer checkpoints removal (#2145) 27ecb20d3 Phantom Newtype: add get_ref() method (#2142) 1faa8ff4a Merge pull request #2173 from dfinity-lab/basvandijk/ignore-RUSTSEC-2019-0011 b9c6cd13a Merge pull request #2152 from dfinity-lab/kb/submit 4eadc395b Merge pull request #2051 from dfinity-lab/paulliu/implement-priority-function 2672056e3 Merge pull request #2149 from dfinity-lab/rsub/cleanups 4fbf5e00e Merge pull request #2163 from dfinity-lab/paulliu/message-attribute d669cdae1 DFN-1250: IHR: add a method to read IngressStatus @ Hight (#2175) 0553a6832 Merge pull request #2172 from dfinity-lab/basvandijk/upgrade-string-interner 13048950d Merge pull request #2170 from dfinity-lab/chmllr/print_batch_errors 07ad601f1 Merge pull request #2171 from dfinity-lab/basvandijk/upgrade-serde_cbor c7614927d Merge pull request #2174 from dfinity-lab/skaestle/drun-doc ec92aaa4f Merge pull request #2161 from dfinity-lab/basvandijk/add-cargo-audit-job 15e05aa36 Merge pull request #2160 from dfinity-lab/chmllr/fix-drun-for-inter-canister-messages bf2b4e976 Merge pull request #2151 from dfinity-lab/david-con-156 4628c3e5b Merge pull request #2136 from dfinity-lab/NewMembership2 1827079f0 Merge pull request #2150 from dfinity-lab/rsub/registry a492a8770 Merge pull request #2148 from dfinity-lab/akhi3030/sys-api-queues 899075a96 Merge pull request #2155 from dfinity-lab/dimitris/scheduler-feedback 70a976de2 Merge pull request #2139 from dfinity-lab/manu/consensus/remove-cert-checkpoint-height 3a565a1d0 DFN-746 Stop using canonical errors in registry. (#2147) f44c79c6d Merge pull request #2126 from dfinity-lab/kb/remove_submit 454b90b40 DFN-746 Get rid of canonical errors use in client (#2143) 44644c21a Merge pull request #2140 from dfinity-lab/dimitris/fix-checkpoint 059781307 Merge pull request #2114 from dfinity-lab/hassen-dfn-712 81a6cbd3b Merge pull request #2103 from dfinity-lab/consensusCrypto c36f75ad9 Merge pull request #2118 from dfinity-lab/drun-multiple-canister 0149a8df1 Merge pull request #2116 from dfinity-lab/InjectClientConfig 330287112 Merge pull request #2102 from dfinity-lab/float_operations f1a5dc2ab Merge pull request #2121 from dfinity-lab/dsd/http_metrics/code_level_changes c06f8067d Merge pull request #2108 from dfinity-lab/dsd/client_http_metrics 3679c9fe7 MsgRouting: return an error if the queue is full (#2112) ec0af6f9b Merge pull request #2110 from dfinity-lab/manu/deliver-batch 81fb47ac9 Rename ic-state_manager crate to ic-state-manager. (#2098) b6af6368e Merge pull request #2109 from dfinity-lab/DFN-1172/fix_call_simple d61275123 Use a simpler structure to represent input queues (#2091) 20e8c4143 DFN-1010: Implement MultiSigVerifier trait for crypto component (#2094) 78c514d23 Merge pull request #2101 from dfinity-lab/systemapi-improvements c63019964 Merge pull request #2100 from dfinity-lab/dimitris/fix-log-output 8927ca10b Merge pull request #2093 from dfinity-lab/cargo-fix-nodemanager 72b2f8260 Merge pull request #2089 from dfinity-lab/chmllr/payload-type 31b1ade26 Merge pull request #2080 from dfinity-lab/dimitris/use-compute-allocation ``` --- default.nix | 2 +- ic-stub/src/IC/DRun/Parse.hs | 24 +++++++---- ic-stub/src/IC/Stub.hs | 15 +++++-- ic-stub/src/ic-stub-run.hs | 25 +++++------ test/drun-wrapper.sh | 9 +++- test/run-drun/actor-import.mo | 1 - test/run-drun/ok/actor-import.drun-run.ok | 4 ++ .../ok/array-out-of-bounds.drun-run.ok | 4 +- .../run-drun/ok/call-async-method.drun-run.ok | 2 +- test/run-drun/ok/caller.drun-run.ok | 2 +- test/run-drun/ok/closure-params.drun-run.ok | 5 +++ test/run-drun/ok/counter2.drun-run.ok | 14 +++++++ test/run-drun/ok/data-params.drun-run.ok | 41 +++++++++++++++++++ test/run-drun/ok/divide-by-zero.drun-run.ok | 3 +- .../ok/divide-by-zero.drun-run.ret.ok | 1 - .../run-drun/ok/hello-world-async.drun-run.ok | 1 + .../ok/hello-world-message.drun-run.ok | 1 - .../ok/hello-world-message.drun-run.ret.ok | 1 - .../ok/hello-world-message.ic-stub-run.ok | 3 -- .../ok/hello-world-message.ic-stub-run.ret.ok | 1 - test/run-drun/ok/idl-bad.drun-run.ok | 2 +- test/run-drun/ok/idl-func.drun-run.ok | 4 +- test/run-drun/ok/idl-nary.drun-run.ok | 4 +- test/run-drun/ok/oneway-throw.drun-run.ok | 2 + test/run-drun/ok/oneway.drun-run.ok | 6 +++ test/run-drun/ok/query.drun-run.ok | 4 +- test/run-drun/ok/query2.drun-run.ok | 4 ++ test/run-drun/ok/selftail.drun-run.ok | 3 +- test/run-drun/ok/selftail.drun-run.ret.ok | 1 - 29 files changed, 138 insertions(+), 51 deletions(-) create mode 100644 test/run-drun/ok/actor-import.drun-run.ok delete mode 100644 test/run-drun/ok/divide-by-zero.drun-run.ret.ok delete mode 100644 test/run-drun/ok/hello-world-message.drun-run.ret.ok delete mode 100644 test/run-drun/ok/hello-world-message.ic-stub-run.ret.ok delete mode 100644 test/run-drun/ok/selftail.drun-run.ret.ok diff --git a/default.nix b/default.nix index 0d49c85bbd1..7b94f5be5c3 100644 --- a/default.nix +++ b/default.nix @@ -38,7 +38,7 @@ let dfinity-src = name = "dfinity-sources"; url = "ssh://git@github.com/dfinity-lab/dfinity"; # ref = "master"; - rev = "dedfec2e294a29f8a1f5f39f1700ebcdad3c6db4"; + rev = "48ab58e7bf4de892a5c5c926050a350947ed2514"; }; in let dfinity-pkgs = import dfinity-src { inherit (nixpkgs) system; }; in diff --git a/ic-stub/src/IC/DRun/Parse.hs b/ic-stub/src/IC/DRun/Parse.hs index ddf6f2c9efb..4525ae4c70b 100644 --- a/ic-stub/src/IC/DRun/Parse.hs +++ b/ic-stub/src/IC/DRun/Parse.hs @@ -1,16 +1,24 @@ +{-# LANGUAGE ScopedTypeVariables #-} module IC.DRun.Parse where import qualified Data.ByteString.Lazy as B +import qualified Data.ByteString.Builder as B import qualified Text.Hex as H import qualified Data.Text as T import Data.Char import Control.Exception +import Data.Word +import Text.Read -data Type = Query | Update deriving Show type MethodName = String type Payload = B.ByteString +type Id = B.ByteString -type Ingress = (Type, String, Payload) +data Ingress + = Install Id FilePath Payload + | Update Id MethodName Payload + | Query Id MethodName Payload + deriving Show parseFile :: FilePath -> IO [Ingress] parseFile input = do @@ -23,13 +31,15 @@ parse = map parseLine . lines parseLine :: String -> Ingress parseLine l = case words l of - [t,m,a] -> (parseType t, m, parseArg a) + ["install", i, f, a] -> Install (parseId i) f (parseArg a) + ["ingress", i, m, a] -> Update (parseId i) m (parseArg a) + ["query", i, m, a] -> Query (parseId i) m (parseArg a) _ -> error $ "Cannot parse: " ++ show l -parseType :: String -> Type -parseType "ingress" = Update -parseType "query" = Query -parseType x = error $ "Invalid ingress type " ++ x +parseId :: String -> Id +parseId x = case readMaybe x of + Just (n::Word64) -> B.toLazyByteString $ B.word64LE n + Nothing -> error "Invalid canister id (decimal number)" parseArg :: String -> Payload parseArg ('0':'x':xs) diff --git a/ic-stub/src/IC/Stub.hs b/ic-stub/src/IC/Stub.hs index 87040c83ec9..f9e661cd644 100644 --- a/ic-stub/src/IC/Stub.hs +++ b/ic-stub/src/IC/Stub.hs @@ -40,7 +40,7 @@ import IC.Logger -- Abstract HTTP Interface data AsyncRequest - = CreateRequest UserId + = CreateRequest UserId (Maybe CanisterId) | InstallRequest CanisterId UserId Blob Blob | UpdateRequest CanisterId UserId MethodName Blob deriving (Eq, Ord, Show) @@ -200,7 +200,16 @@ setCanisterState cid wasm_state = processRequest :: ICT m => AsyncRequest -> m () -processRequest r@(CreateRequest _user_id) = do +processRequest r@(CreateRequest _user_id (Just desired)) = do + exists <- gets (M.member desired . canisters) + if exists + then + setReqStatus r $ Rejected (RC_DESTINATION_INVALID, "Desired canister id already exists") + else do + createEmptyCanister desired + setReqStatus r $ Completed $ CompleteCanisterId desired + +processRequest r@(CreateRequest _user_id Nothing) = do existing_canisters <- gets (M.keys . canisters) let new_id = freshId existing_canisters createEmptyCanister new_id @@ -276,7 +285,7 @@ rememberTrap ctxt_id msg = modifyCallContext ctxt_id $ \ctxt -> ctxt { last_trap = Just msg } callerOfRequest :: AsyncRequest -> EntityId -callerOfRequest (CreateRequest user_id) = user_id +callerOfRequest (CreateRequest user_id _) = user_id callerOfRequest (InstallRequest _ user_id _ _) = user_id callerOfRequest (UpdateRequest _ user_id _ _) = user_id diff --git a/ic-stub/src/ic-stub-run.hs b/ic-stub/src/ic-stub-run.hs index f450ba95346..e137058d05a 100644 --- a/ic-stub/src/ic-stub-run.hs +++ b/ic-stub/src/ic-stub-run.hs @@ -13,7 +13,7 @@ import Text.Printf import IC.Types import IC.Stub -import IC.DRun.Parse (Type(..), parseFile) +import IC.DRun.Parse (Ingress(..), parseFile) type DRun = StateT IC IO @@ -68,19 +68,20 @@ submitRead r = do lift $ printReqStatus r return r -work :: FilePath -> FilePath -> IO () -work wasm_file msg_file = do - wasm <- B.readFile wasm_file +work :: FilePath -> IO () +work msg_file = do msgs <- parseFile msg_file let user_id = dummyUserId - flip evalStateT initialIC $ do - Completed (CompleteCanisterId cid) <- submitAndRun (CreateRequest user_id) - _ <- submitAndRun (InstallRequest cid user_id wasm B.empty) + flip evalStateT initialIC $ forM_ msgs $ \case - (Query, method, arg) -> submitRead (QueryRequest cid user_id method arg) - (Update, method, arg) -> submitAndRun (UpdateRequest cid user_id method arg) + Install cid filename arg -> do + wasm <- liftIO $ B.readFile filename + _ <- submitAndRun (CreateRequest user_id (Just (EntityId cid))) + submitAndRun (InstallRequest (EntityId cid) user_id wasm arg) + Query cid method arg -> submitRead (QueryRequest (EntityId cid) user_id method arg) + Update cid method arg -> submitAndRun (UpdateRequest (EntityId cid) user_id method arg) main :: IO () main = join . customExecParser (prefs showHelpOnError) $ @@ -99,11 +100,7 @@ main = join . customExecParser (prefs showHelpOnError) $ <> metavar "CONFIG" <> value "" ) - <*> strArgument - ( metavar "*.wasm" - <> help "Wasm module" - ) <*> strArgument ( metavar "script" - <> help "messags to execute" + <> help "messages to execute" ) diff --git a/test/drun-wrapper.sh b/test/drun-wrapper.sh index d5b0bbcd61f..322054d62e2 100755 --- a/test/drun-wrapper.sh +++ b/test/drun-wrapper.sh @@ -13,5 +13,10 @@ fi export LANG=C.UTF-8 -( if [ -n "$2" ]; then grep '^//CALL ' $2 | cut -c8-; fi;) | - $DRUN -c "$CONFIG" $1 /dev/stdin +# canister id "ic:000000000000040054", in little-endian decimal, is: +# 1125899906842624 +# (drun currently expects a decimal number for the canister id) + +(echo "install 1125899906842624 $1 0x"; + if [ -n "$2" ]; then LANG=C perl -ne 'print "$1 1125899906842624 $2\n" if m,^//CALL (ingress|query) (.*),' $2; fi; +) | $DRUN -c "$CONFIG" /dev/stdin diff --git a/test/run-drun/actor-import.mo b/test/run-drun/actor-import.mo index 763de3bd4c5..ea0fe04aa4d 100644 --- a/test/run-drun/actor-import.mo +++ b/test/run-drun/actor-import.mo @@ -21,5 +21,4 @@ actor a { //SKIP run //SKIP run-ir //SKIP run-low -//SKIP drun-run diff --git a/test/run-drun/ok/actor-import.drun-run.ok b/test/run-drun/ok/actor-import.drun-run.ok new file mode 100644 index 00000000000..b490e3d8ecc --- /dev/null +++ b/test/run-drun/ok/actor-import.drun-run.ok @@ -0,0 +1,4 @@ +ingress(0) System +ingress(1) Completed: Canister: Payload: 0x4449444c016900010001080000000000000400 +ingress(2) Completed: Canister: Payload: 0x4449444c016900010001080000000000000400 +ingress(3) Completed: Canister: Payload: 0x4449444c016900010001080000000000000400 diff --git a/test/run-drun/ok/array-out-of-bounds.drun-run.ok b/test/run-drun/ok/array-out-of-bounds.drun-run.ok index b006eea0561..979281404cd 100644 --- a/test/run-drun/ok/array-out-of-bounds.drun-run.ok +++ b/test/run-drun/ok/array-out-of-bounds.drun-run.ok @@ -1,3 +1,3 @@ ingress(0) System -ingress(1) Err: IC0503: Canister 42 trapped explicitly: Array index out of bounds -ingress(2) Err: IC0503: Canister 42 trapped explicitly: Array index out of bounds +ingress(1) Err: IC0503: Canister 1125899906842624 trapped explicitly: Array index out of bounds +ingress(2) Err: IC0503: Canister 1125899906842624 trapped explicitly: Array index out of bounds diff --git a/test/run-drun/ok/call-async-method.drun-run.ok b/test/run-drun/ok/call-async-method.drun-run.ok index ffe3f56379c..f5a4ad71f0d 100644 --- a/test/run-drun/ok/call-async-method.drun-run.ok +++ b/test/run-drun/ok/call-async-method.drun-run.ok @@ -1,2 +1,2 @@ ingress(0) System -ingress(1) Err: IC0503: Canister 42 trapped explicitly: not a self-call +ingress(1) Err: IC0503: Canister 1125899906842624 trapped explicitly: not a self-call diff --git a/test/run-drun/ok/caller.drun-run.ok b/test/run-drun/ok/caller.drun-run.ok index 0171dc3ed16..3509aab2a35 100644 --- a/test/run-drun/ok/caller.drun-run.ok +++ b/test/run-drun/ok/caller.drun-run.ok @@ -4,4 +4,4 @@ ingress(2) Completed: Canister: Payload: 0x4449444c0000 ingress(3) Completed: Canister: Payload: 0x4449444c0000 ingress(4) Completed: Canister: Payload: 0x4449444c0000 Ok: Payload: 0x4449444c0000 -ingress(5) Completed: Canister: Payload: 0x4449444c016d7b0100080000000000000000 +ingress(6) Completed: Canister: Payload: 0x4449444c016d7b0100080000000000000000 diff --git a/test/run-drun/ok/closure-params.drun-run.ok b/test/run-drun/ok/closure-params.drun-run.ok index 91c74b55809..65b69a19788 100644 --- a/test/run-drun/ok/closure-params.drun-run.ok +++ b/test/run-drun/ok/closure-params.drun-run.ok @@ -1,2 +1,7 @@ ingress(0) System ingress(1) Completed: Canister: Payload: 0x4449444c0000 +debug.print: 1 +debug.print: 3 +debug.print: 6 +debug.print: 10 +debug.print: 15 diff --git a/test/run-drun/ok/counter2.drun-run.ok b/test/run-drun/ok/counter2.drun-run.ok index 91c74b55809..6ae2944f48c 100644 --- a/test/run-drun/ok/counter2.drun-run.ok +++ b/test/run-drun/ok/counter2.drun-run.ok @@ -1,2 +1,16 @@ ingress(0) System ingress(1) Completed: Canister: Payload: 0x4449444c0000 +debug.print: 2 +debug.print: 3 +debug.print: 4 +debug.print: 4 +debug.print: 5 +debug.print: 6 +debug.print: 7 +debug.print: 8 +debug.print: 9 +debug.print: 10 +debug.print: 11 +debug.print: 12 +debug.print: 13 +debug.print: 14 diff --git a/test/run-drun/ok/data-params.drun-run.ok b/test/run-drun/ok/data-params.drun-run.ok index 91c74b55809..6c02e39ff56 100644 --- a/test/run-drun/ok/data-params.drun-run.ok +++ b/test/run-drun/ok/data-params.drun-run.ok @@ -1,2 +1,43 @@ ingress(0) System ingress(1) Completed: Canister: Payload: 0x4449444c0000 +debug.print: 0 +debug.print: +1 +debug.print: +3 +debug.print: +6 +debug.print: +10 +debug.print: +1_010 +debug.print: +1_021 +debug.print: +6_021 +debug.print: +6_045 +debug.print: +6_091 +debug.print: +1_006_091 +debug.print: +1_006_105 +debug.print: +1_006_136 +debug.print: +1_006_171 +debug.print: +1_006_191 +debug.print: +1_006_211 +debug.print: +1_006_211 +debug.print: Foo1: +debug.print: +1_006_211 +debug.print: μεταγράψτε: +debug.print: +1_006_211 +debug.print: Foo2: +debug.print: +1_006_211 +debug.print: +10_000_001_006_211 +debug.print: +20_000_001_006_211 +debug.print: +1_006_211 +debug.print: +1_006_221 +debug.print: +1_006_211 +debug.print: +1_006_221 +debug.print: +1_006_231 +debug.print: +1_006_221 +debug.print: +1_267_650_600_228_229_401_496_704_211_597 +debug.print: +2_535_301_200_456_458_802_993_407_416_973 +debug.print: +1_006_221 +debug.print: +1_074_748_045 +debug.print: +2_148_489_868 +debug.print: +2_148_489_868 +debug.print: +2_148_489_869 +debug.print: +2_148_489_911 +debug.print: +2_148_489_869 +debug.print: +4_295_973_516 diff --git a/test/run-drun/ok/divide-by-zero.drun-run.ok b/test/run-drun/ok/divide-by-zero.drun-run.ok index 1830f40cd69..b2f6837768e 100644 --- a/test/run-drun/ok/divide-by-zero.drun-run.ok +++ b/test/run-drun/ok/divide-by-zero.drun-run.ok @@ -1,2 +1 @@ -ingress(0) Err: IC0502: Canister 42 trapped: integer division by 0 -Error: "Failed to install canister - ignoring message stream" +ingress(0) Err: IC0502: Canister 1125899906842624 trapped: integer division by 0 diff --git a/test/run-drun/ok/divide-by-zero.drun-run.ret.ok b/test/run-drun/ok/divide-by-zero.drun-run.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/divide-by-zero.drun-run.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/hello-world-async.drun-run.ok b/test/run-drun/ok/hello-world-async.drun-run.ok index 81574f8917d..fc1914a38ce 100644 --- a/test/run-drun/ok/hello-world-async.drun-run.ok +++ b/test/run-drun/ok/hello-world-async.drun-run.ok @@ -1,3 +1,4 @@ ingress(0) System debug.print: Hello ingress(1) Completed: Canister: Payload: 0x4449444c0000 +debug.print: World! diff --git a/test/run-drun/ok/hello-world-message.drun-run.ok b/test/run-drun/ok/hello-world-message.drun-run.ok index ae5f39f9b7f..43d7af40394 100644 --- a/test/run-drun/ok/hello-world-message.drun-run.ok +++ b/test/run-drun/ok/hello-world-message.drun-run.ok @@ -1,2 +1 @@ ingress(0) System -Error: "Line 1: Illegal method name: 0x4449444C0000." diff --git a/test/run-drun/ok/hello-world-message.drun-run.ret.ok b/test/run-drun/ok/hello-world-message.drun-run.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/hello-world-message.drun-run.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/hello-world-message.ic-stub-run.ok b/test/run-drun/ok/hello-world-message.ic-stub-run.ok index f7b62ca515e..54225bc8555 100644 --- a/test/run-drun/ok/hello-world-message.ic-stub-run.ok +++ b/test/run-drun/ok/hello-world-message.ic-stub-run.ok @@ -2,6 +2,3 @@ ← completed: canister-id = 0x0000000000000400 → install ← completed -ic-stub-run: Invalid ingress type hello -CallStack (from HasCallStack): - error, called at src/IC/DRun/Parse.hs:32:15 in main:IC.DRun.Parse diff --git a/test/run-drun/ok/hello-world-message.ic-stub-run.ret.ok b/test/run-drun/ok/hello-world-message.ic-stub-run.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/hello-world-message.ic-stub-run.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/idl-bad.drun-run.ok b/test/run-drun/ok/idl-bad.drun-run.ok index 2bc34fb40a7..dddcbedf783 100644 --- a/test/run-drun/ok/idl-bad.drun-run.ok +++ b/test/run-drun/ok/idl-bad.drun-run.ok @@ -1,3 +1,3 @@ ingress(0) System debug.print: IDL error: missing magic bytes -Err: IC0502: Canister 42 trapped: unreachable +Err: IC0502: Canister 1125899906842624 trapped: unreachable diff --git a/test/run-drun/ok/idl-func.drun-run.ok b/test/run-drun/ok/idl-func.drun-run.ok index f2b11cd7e85..ad76efaffa6 100644 --- a/test/run-drun/ok/idl-func.drun-run.ok +++ b/test/run-drun/ok/idl-func.drun-run.ok @@ -1,5 +1,5 @@ ingress(0) System Ok: Payload: 0x4449444c026e016a017c010100010000 Ok: Payload: 0x4449444c0000 -Ok: Payload: 0x4449444c036a00010101016e026a017c01020001000101082a000000000000000366756e -Ok: Payload: 0x4449444c016a0000010201000101082a00000000000000066f6e65776179 +Ok: Payload: 0x4449444c036a00010101016e026a017c010200010001010800000000000004000366756e +Ok: Payload: 0x4449444c016a0000010201000101080000000000000400066f6e65776179 diff --git a/test/run-drun/ok/idl-nary.drun-run.ok b/test/run-drun/ok/idl-nary.drun-run.ok index e6f3a393455..4402c0df173 100644 --- a/test/run-drun/ok/idl-nary.drun-run.ok +++ b/test/run-drun/ok/idl-nary.drun-run.ok @@ -7,6 +7,6 @@ ingress(5) Completed: Canister: Payload: 0x4449444c016c0400710171027103710100034 ingress(6) Completed: Canister: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 ingress(7) Completed: Canister: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 ingress(8) Completed: Canister: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 -ingress(9) Err: IC0503: Canister 42 trapped explicitly: IDL error: too few arguments Text,Text,Text -ingress(10) Err: IC0503: Canister 42 trapped explicitly: IDL error: left-over bytes Text,Text,Text +ingress(9) Err: IC0503: Canister 1125899906842624 trapped explicitly: IDL error: too few arguments Text,Text,Text +ingress(10) Err: IC0503: Canister 1125899906842624 trapped explicitly: IDL error: left-over bytes Text,Text,Text ingress(11) Completed: Canister: Payload: 0x4449444c000471717171034f6e650354776f05546872656504466f7572 diff --git a/test/run-drun/ok/oneway-throw.drun-run.ok b/test/run-drun/ok/oneway-throw.drun-run.ok index 1cd45a1b62a..c1cc4f9e0fd 100644 --- a/test/run-drun/ok/oneway-throw.drun-run.ok +++ b/test/run-drun/ok/oneway-throw.drun-run.ok @@ -1,3 +1,5 @@ ingress(0) System debug.print: go1 ingress(1) Completed: Canister: Payload: 0x4449444c0000 +debug.print: throws() +debug.print: ping() diff --git a/test/run-drun/ok/oneway.drun-run.ok b/test/run-drun/ok/oneway.drun-run.ok index 4a239d3bf08..9f33620c3b2 100644 --- a/test/run-drun/ok/oneway.drun-run.ok +++ b/test/run-drun/ok/oneway.drun-run.ok @@ -5,3 +5,9 @@ debug.print: C debug.print: D debug.print: E ingress(1) Completed: Canister: Payload: 0x4449444c0000 +debug.print: 1 +debug.print: 2 +debug.print: 3 +debug.print: 4 +debug.print: 5 +debug.print: 6 diff --git a/test/run-drun/ok/query.drun-run.ok b/test/run-drun/ok/query.drun-run.ok index aab5adff8d1..e8c656b0d07 100644 --- a/test/run-drun/ok/query.drun-run.ok +++ b/test/run-drun/ok/query.drun-run.ok @@ -11,8 +11,8 @@ ingress(5) Completed: Canister: Payload: 0x4449444c00017d04 debug.print: 5 Ok: Payload: 0x4449444c00017d04 debug.print: 4 -ingress(6) Completed: Canister: Payload: 0x4449444c0000 +ingress(7) Completed: Canister: Payload: 0x4449444c0000 debug.print: 5 Ok: Payload: 0x4449444c00017d04 debug.print: 4 -ingress(7) Completed: Canister: Payload: 0x4449444c0000 +ingress(9) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/query2.drun-run.ok b/test/run-drun/ok/query2.drun-run.ok index 91c74b55809..8bf828fb58a 100644 --- a/test/run-drun/ok/query2.drun-run.ok +++ b/test/run-drun/ok/query2.drun-run.ok @@ -1,2 +1,6 @@ ingress(0) System ingress(1) Completed: Canister: Payload: 0x4449444c0000 +debug.print: 2 +debug.print: 3 +debug.print: 4 +debug.print: 4 diff --git a/test/run-drun/ok/selftail.drun-run.ok b/test/run-drun/ok/selftail.drun-run.ok index e693dfb619f..b5601dba467 100644 --- a/test/run-drun/ok/selftail.drun-run.ok +++ b/test/run-drun/ok/selftail.drun-run.ok @@ -1,4 +1,3 @@ debug.print: ok1 debug.print: ok2 -ingress(0) Err: IC0502: Canister 42 trapped: stack overflow -Error: "Failed to install canister - ignoring message stream" +ingress(0) Err: IC0502: Canister 1125899906842624 trapped: stack overflow diff --git a/test/run-drun/ok/selftail.drun-run.ret.ok b/test/run-drun/ok/selftail.drun-run.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/selftail.drun-run.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 From 3f37bcafaa03191242f72e8022de341978da75ac Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 7 Jan 2020 10:55:31 +0100 Subject: [PATCH 0873/1176] CI job to report performance changes (#1065) see the `perf-delta` Hydra job. Does not yet report the results as a github comment, though. --- ci-pr.nix | 35 +++++++++++++++++- default.nix | 5 +++ test/diff-stats.pl | 88 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 127 insertions(+), 1 deletion(-) create mode 100755 test/diff-stats.pl diff --git a/ci-pr.nix b/ci-pr.nix index 7dcd26dad09..205b6b13c97 100644 --- a/ci-pr.nix +++ b/ci-pr.nix @@ -1 +1,34 @@ -import ./ci.nix +{ src ? { rev = null; }, base ? null }: +let + nixpkgs = (import ./nix/nixpkgs.nix).nixpkgs { }; + + # Wrap in a derivation to fix path to perl in shebang + diff-stats = nixpkgs.stdenvNoCC.mkDerivation { + name = "diff-stats"; + src = ./test/diff-stats.pl; + phases = [ "installPhase fixupPhase" ]; + buildInputs = [ nixpkgs.perl ]; + installPhase = '' + mkdir -p $out/bin + cp $src $out/bin/diff-stats + ''; + }; + +in +import ./ci.nix { inherit src; } // nixpkgs.lib.optionalAttrs (base != null) { + perf-delta = + let + baseJobs = import "${base}/default.nix" { system = "x86_64-linux"; }; + prJobs = import ./default.nix { system = "x86_64-linux"; }; + in + nixpkgs.runCommandNoCC "perf-delta" { + baseStats = baseJobs.tests.perf; + prStats = prJobs.tests.perf; + nativeBuildInputs = [ nixpkgs.coreutils diff-stats ]; + } '' + mkdir -p $out + diff-stats $baseStats $prStats > $out/report; + mkdir -p $out/nix-support + echo "report perf-delta $out report" >> $out/nix-support/hydra-build-products + ''; + } diff --git a/default.nix b/default.nix index 7b94f5be5c3..7b48ca5bc02 100644 --- a/default.nix +++ b/default.nix @@ -246,6 +246,11 @@ rec { # run this once to work around self-unpacking-race-condition type -p drun && drun --version make -C ${dir} + + if test -e ${dir}/_out/stats.csv + then + cp ${dir}/_out/stats.csv $out + fi ''; }; in diff --git a/test/diff-stats.pl b/test/diff-stats.pl new file mode 100755 index 00000000000..74f91de5726 --- /dev/null +++ b/test/diff-stats.pl @@ -0,0 +1,88 @@ +#!/usr/bin/env perl + +# +# This script compares two CSV files with performance stats, and produces a +# short textual summary +# + +use strict; +use warnings; + +die "Usage: $0 file1.csv file2.csv" unless scalar @ARGV == 2; + +my %stats; + +sub read_file ($$) { + my $pos = shift; + my $file = shift; + open FILE, '<', $file; + while() { + m,(.*)/(.*);([0-9]+), or die "Cannot parse line $. of $file"; + $stats{$1} = {} unless exists $stats{$1}; + $stats{$1}{$2} = [0,0] unless exists $stats{$1}{$2}; + $stats{$1}{$2}[$pos] = $3; + } +} + +read_file(0, $ARGV[0]); +read_file(1, $ARGV[1]); + +sub comma_and { + if (scalar @_ == 0) { + return "" + } elsif (scalar @_ == 1) { + return $_[0] + } elsif (scalar @_ == 2) { + return (sprintf "%s and %s", @_) + } else { + my $head = shift; + return (sprintf "%s, %s", $head, comma_and(@_)); + } +} + +for my $group (keys %stats) { + my $gstats = $stats{$group}; + my $total = 0; + my $any_change = 0; + my $regressed = 0; + my $improved = 0; + my $missing = 0; + my $new = 0; + my $geometric_mean = 1; + my $geometric_mean_denom = 0; + + for my $test (keys %$gstats) { + $total++; + my $stat1 = $gstats->{$test}[0]; + my $stat2 = $gstats->{$test}[1]; + if ($stat1 and $stat2) { + $geometric_mean *= $stat2/$stat1; + $geometric_mean_denom++; + if ($stat1 < $stat2) { + $regressed++; + } elsif ($stat1 > $stat2) { + $improved++; + } + } elsif ($stat1 and not $stat2) { + $missing++; + } elsif ($stat2 and not $stat1) { + $new++; + } else { + # unlikely + } + } + + $geometric_mean = $geometric_mean ** (1/$geometric_mean_denom) if $geometric_mean_denom; + + if ($regressed or $improved or $new or $missing ) { + my @clauses; + push @clauses, sprintf "%d tests regressed", $regressed if $regressed; + push @clauses, sprintf "%d tests improved", $improved if $improved; + push @clauses, sprintf "%d tests are new", $new if $new; + push @clauses, sprintf "%d tests are removed", $missing if $missing; + push @clauses, sprintf "the mean change is %+.0f%%.\n", (($geometric_mean - 1) * 100); + printf "In terms of %s, %s", $group, comma_and(@clauses); + } else { + printf "In terms of %s, no changes are observed in %d tests.\n", $group, $total; + } +} From e9e1daf5cfc9df00e6f260cef3ae564382935ee7 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity <48968912+chenyan-dfinity@users.noreply.github.com> Date: Tue, 7 Jan 2020 01:58:44 -0800 Subject: [PATCH 0874/1176] update IDL-Motoko unescape function (#1067) * update IDL field label to nat32 * update Co-authored-by: Joachim Breitner --- design/IDL-Motoko.md | 2 +- design/IDL.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/design/IDL-Motoko.md b/design/IDL-Motoko.md index 3f576c3d822..cbadb4cf662 100644 --- a/design/IDL-Motoko.md +++ b/design/IDL-Motoko.md @@ -111,7 +111,7 @@ em : -> em( : ) = unescape() : efn() unescape : -> | -unescape("_" "_") = +unescape("_" "_") = if is 32-bit unescape( "_") = unescape() = ``` diff --git a/design/IDL.md b/design/IDL.md index 71f622dc34f..07b7e4e43f0 100644 --- a/design/IDL.md +++ b/design/IDL.md @@ -327,7 +327,7 @@ A *record* is a *heterogeneous* sequence of values of different data types. Each ``` We identify `` lists in a record type up to reordering. -The id is described as a simple unsigned integer that has to fit the 64 bit value range. It can be given in either decimal or hexadecimal notation: +The id is described as a simple unsigned integer that has to fit the 32 bit value range. It can be given in either decimal or hexadecimal notation: ``` ::= (0..9)(_? 0..9)* | 0x(0..9|a..f|A..F)(_? 0..9|a..f|A..F)* From 1185bf9c6bb124fd1c46cabb217de163ef7656ad Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Tue, 7 Jan 2020 11:54:59 +0100 Subject: [PATCH 0875/1176] Use wasm reference interpreter in qc-motoko (#1070) * use wasm reference interpreter in qc-motoko plus some typo fixes * factor out embedder logic * switch to WasmTime to check viability in CI. Performace is bad, where are the tuning knobs for speeding it up? --- Building.md | 2 +- default.nix | 5 ++--- test/random/Main.hs | 42 ++++++++++++++++++++++++++++-------------- 3 files changed, 31 insertions(+), 18 deletions(-) diff --git a/Building.md b/Building.md index ed7c21c60d9..64557955397 100644 --- a/Building.md +++ b/Building.md @@ -38,7 +38,7 @@ installing all required tools without nix is out of scope). ``` opam install num vlq yojson menhir stdio js_of_ocaml js_of_ocaml-ppx ppx_inline_test bisect_ppx atdgen wasm ``` - * Install various command line tools used by, in particuar, the test suite: + * Install various command line tools used by, in particular, the test suite: ``` nix-env -i -f . -A wasmtime nix-env -i -f . -A filecheck diff --git a/default.nix b/default.nix index 7b48ca5bc02..453572afa4c 100644 --- a/default.nix +++ b/default.nix @@ -205,7 +205,7 @@ rec { staticpkgs.stdenv.mkDerivation (testDerivationArgs // args); in # we test each subdirectory of test/ in its own derivation with - # cleaner dependencies, for more paralleism, more caching + # cleaner dependencies, for more parallelism, more caching # and better feedback about what aspect broke let test_subdir = dir: deps: testDerivation { @@ -263,8 +263,7 @@ rec { let qc = testDerivation { name = "test-qc"; - # maybe use wasm instead? - buildInputs = [ moc nixpkgs.wabt haskellPackages.qc-motoko ]; + buildInputs = [ moc /* nixpkgs.wasm */ wasmtime haskellPackages.qc-motoko ]; checkPhase = '' qc-motoko${nixpkgs.lib.optionalString (replay != 0) " --quickcheck-replay=${toString replay}"} diff --git a/test/random/Main.hs b/test/random/Main.hs index a2b97404fb0..bac0578b575 100644 --- a/test/random/Main.hs +++ b/test/random/Main.hs @@ -62,8 +62,22 @@ matchingProps = testGroup "Pattern matching" , QC.testProperty "inter-actor" $ prop_matchInActor ] -(runScriptNoFuzz, runScriptWantFuzz) = (runner id, runner not) - where runner relevant name testCase = + +data Embedder = Reference | WasmTime + +instance Arbitrary Embedder where arbitrary = elements [Reference, WasmTime] + +embedderCommand Reference = "wasm" +embedderCommand WasmTime = "wasmtime" + +addEmbedderArgs Reference = id +addEmbedderArgs WasmTime = ("--disable-cache" :) . ("--cranelift" :) + +embedder :: Embedder +embedder = WasmTime + +(runScriptNoFuzz, runScriptWantFuzz) = (runner ExitSuccess id, runner (ExitFailure 1) not) + where runner reqOutcome relevant name testCase = let as = name <.> "as" wasm = name <.> "wasm" fileArg = fromString . encodeString @@ -71,9 +85,9 @@ matchingProps = testGroup "Pattern matching" res@(exitCode, _, _) <- procStrictWithErr "moc" ["-no-system-api", "-no-check-ir", fileArg as] empty if ExitSuccess == exitCode - then (True,) <$> procStrictWithErr "wasm-interp" ["--enable-multi", fileArg wasm] empty + then (True,) <$> procStrictWithErr (embedderCommand embedder) (addEmbedderArgs embedder [fileArg wasm]) empty else pure (False, res) - in run script >>= assertSuccessNoFuzz relevant + in run script >>= assertOutcomeCheckingFuzz reqOutcome relevant prop_explodeConcat :: UTF8 String -> Property prop_explodeConcat (UTF8 str) = monadicIO $ do @@ -162,17 +176,19 @@ prop_ropeIterator rope = monadicIO $ do runScriptNoFuzz "ropeLength" testCase -assertSuccessNoFuzz relevant (compiled, (exitCode, out, err)) = do +assertOutcomeCheckingFuzz outcome relevant (compiled, (exitCode, out, err)) = do let fuzzErr = not $ Data.Text.null err - when fuzzErr $ do + fuzzErrRelevant = relevant fuzzErr + when (fuzzErr && fuzzErrRelevant) $ do monitor (counterexample "STDERR:") monitor (counterexample . Data.Text.unpack $ err) let fuzzOut = not $ Data.Text.null out - let fuzzOutRelevant = relevant fuzzOut - when (fuzzOut && fuzzOutRelevant) $ do + when fuzzOut $ do monitor (counterexample "STDOUT:") monitor (counterexample . Data.Text.unpack $ out) - assert (not $ ExitSuccess /= exitCode || (if compiled then fuzzOutRelevant else fuzzOut) || fuzzErr) + assert (not $ outcome /= exitCode || (if compiled then fuzzErrRelevant else fuzzErr) || fuzzOut) + +assertSuccessNoFuzz = assertOutcomeCheckingFuzz ExitSuccess id newtype Failing a = Failing a deriving Show @@ -192,9 +208,7 @@ instance Arbitrary TestCase where arbitrary = do tests <- infiniteListOf arbitrary let expected = evaluate @Integer <$> tests let paired as = fmap (\res -> "assert (" ++ unparseMO as ++ " == " ++ show res ++ ");") - pure . TestCase . take 100 . catMaybes $ zipWith paired tests expected - - + pure . TestCase . take 10 . catMaybes $ zipWith paired tests expected prop_verifies (TestCase (map fromString -> testCase)) = monadicIO $ do @@ -202,7 +216,7 @@ prop_verifies (TestCase (map fromString -> testCase)) = monadicIO $ do res@(exitCode, _, _) <- procStrictWithErr "moc" ["-no-system-api", "-no-check-ir", "tests.mo"] empty if ExitSuccess == exitCode - then (True,) <$> procStrictWithErr "wasm-interp" ["--enable-multi", "tests.wasm"] empty + then (True,) <$> procStrictWithErr (embedderCommand embedder) (addEmbedderArgs embedder ["tests.wasm"]) empty else pure (False, res) res@(compiled, (exitCode, out, err)) <- run $ script testCase when compiled $ do @@ -217,7 +231,7 @@ prop_verifies (TestCase (map fromString -> testCase)) = monadicIO $ do (_, False) -> bisect $ halve jokers let good = Data.Text.null out unless good $ (run . bisect $ halve testCase) >>= monitor . (counterexample . Data.Text.unpack $) - assertSuccessNoFuzz id res + assertSuccessNoFuzz res newtype ConversionTest n = ConversionTest (MOTerm (BitLimited n Word)) deriving Show From 9984351bdf84b294dc682d38eea70078aa4abd47 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 7 Jan 2020 13:27:50 +0100 Subject: [PATCH 0876/1176] Performance tracking: strip wasm before reportig size (#1073) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit it would set up the wrong incentives if we would be “penalized” for having a better `names` section. So report the size of the stripped wasm (using `wasm-strip` from `wabt`). (This is also the the first PR where the `perf-delta` report should report something, I hope). --- test/run.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/test/run.sh b/test/run.sh index 59e71d7606b..99bd0e132a0 100755 --- a/test/run.sh +++ b/test/run.sh @@ -304,6 +304,7 @@ do then if [ -n "$PERF_OUT" ] then + wasm-strip $out/$base.wasm echo "size/$base;$(stat --format=%s $out/$base.wasm)" >> $PERF_OUT fi fi From c5bb5800aceeef437d06267205e273073fbe47e7 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 7 Jan 2020 16:54:17 +0100 Subject: [PATCH 0877/1176] Fix comment in await.ml (#1068) Co-authored-by: Claudio Russo --- src/ir_passes/await.ml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ir_passes/await.ml b/src/ir_passes/await.ml index a65529d2da7..2e45565fb06 100644 --- a/src/ir_passes/await.ml +++ b/src/ir_passes/await.ml @@ -31,8 +31,7 @@ let letcont k scope = blockE [funcD k' v (cont v)] (* at this point, I'm really worried about variable capture *) (scope k') -(* The empty identifier names the implicit return label *) - +(* Named labels for break, special labels for return and throw *) type label = Return | Throw | Named of string let ( -@- ) k exp2 = From 65e33117de0b42f65b59e60575a2479ae5619e70 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 7 Jan 2020 17:40:23 +0100 Subject: [PATCH 0878/1176] IR.Construct: Optimize `let (p1,p2) = (e1, e2)` (#1075) makes output of async pass easier to read, and avoids useless allocations. --- src/ir_def/construct.ml | 14 +++++++++----- test/compare-wat.sh | 4 ++-- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index 7da0a8af0d3..8f3d24fea79 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -149,13 +149,17 @@ let dec_eff dec = match dec.it with | TypD _ -> T.Triv | LetD (_,e) | VarD (_,e) -> eff e -let is_useful_dec dec = match dec.it with - | LetD ({it = WildP;_}, {it = TupE [];_}) -> false - | LetD ({it = TupP [];_}, {it = TupE [];_}) -> false - | _ -> true +let rec simpl_decs decs = List.concat (List.map simpl_dec decs) +and simpl_dec dec = match dec.it with + | LetD ({it = WildP;_}, {it = TupE [];_}) -> + [] + | LetD ({it = TupP ps;_}, {it = TupE es;_}) when List.length ps = List.length es -> + simpl_decs (List.map2 (fun p e -> LetD (p, e) @@ p.at) ps es) + | _ -> + [ dec ] let blockE decs exp = - let decs' = List.filter is_useful_dec decs in + let decs' = simpl_decs decs in match decs' with | [] -> exp | _ -> diff --git a/test/compare-wat.sh b/test/compare-wat.sh index 129c2c9792c..d4791551085 100755 --- a/test/compare-wat.sh +++ b/test/compare-wat.sh @@ -71,14 +71,14 @@ do rm -rf compare-out/$base.old mkdir compare-out/$base.old - old-moc/bin/moc $file -o compare-out/$base.old/$base.wasm 2> compare-out/$base.old/$base.stderr + old-moc/bin/moc $file -stub-system-api -o compare-out/$base.old/$base.wasm 2> compare-out/$base.old/$base.stderr test ! -e compare-out/$base.old/$base.wasm || $WASM2WAT compare-out/$base.old/$base.wasm >& compare-out/$base.old/$base.wat #wasm-objdump -s -h -d compare-out/$base.old/$base.wasm > compare-out/$base.old/$base.dump rm -rf compare-out/$base.new mkdir compare-out/$base.new - new-moc/bin/moc $file -o compare-out/$base.new/$base.wasm 2> compare-out/$base.new/$base.stderr + new-moc/bin/moc $file -stub-system-api -o compare-out/$base.new/$base.wasm 2> compare-out/$base.new/$base.stderr test ! -e compare-out/$base.new/$base.wasm || $WASM2WAT compare-out/$base.new/$base.wasm >& compare-out/$base.new/$base.wat #wasm-objdump -s -h -d compare-out/$base.new/$base.wasm > compare-out/$base.new/$base.dump From f21e95d063f377b3171ad07e2c3a8ed9d8372d7b Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Tue, 7 Jan 2020 18:03:30 +0100 Subject: [PATCH 0879/1176] Bump wasmtime to v0.8.0 (#1074) * bump wasmtime to v0.8.0 * accept test output changes (mostly whitespace) --- nix/wasmtime/cargo-lock.patch | 1020 +++++++++-------- nix/wasmtime/default.nix | 16 +- test/run/ok/array-bounds.wasm-run.ok | 1 - test/run/ok/assertFalse.wasm-run.ok | 1 - .../ok/char-high-surrogate-trap.wasm-run.ok | 1 - .../ok/char-low-surrogate-trap.wasm-run.ok | 1 - test/run/ok/char-trap.wasm-run.ok | 1 - test/run/ok/issue36.wasm-run.ok | 1 - test/run/ok/overflow.wasm-run.ok | 1 - test/trap/ok/addInt16-lower.wasm-run.ok | 1 - test/trap/ok/addInt16-upper.wasm-run.ok | 1 - test/trap/ok/addInt32-lower.wasm-run.ok | 1 - test/trap/ok/addInt32-upper.wasm-run.ok | 1 - test/trap/ok/addInt64-lower.wasm-run.ok | 1 - test/trap/ok/addInt64-upper.wasm-run.ok | 1 - test/trap/ok/addInt8-lower.wasm-run.ok | 1 - test/trap/ok/addInt8-upper.wasm-run.ok | 1 - test/trap/ok/addNat16.wasm-run.ok | 1 - test/trap/ok/addNat32.wasm-run.ok | 1 - test/trap/ok/addNat64.wasm-run.ok | 1 - test/trap/ok/addNat8.wasm-run.ok | 1 - test/trap/ok/divInt16.wasm-run.ok | 1 - test/trap/ok/divInt32.wasm-run.ok | 1 - test/trap/ok/divInt64.wasm-run.ok | 1 - test/trap/ok/divInt8.wasm-run.ok | 1 - test/trap/ok/mulInt16-lower.wasm-run.ok | 1 - test/trap/ok/mulInt16-upper.wasm-run.ok | 1 - test/trap/ok/mulInt32-lower.wasm-run.ok | 1 - test/trap/ok/mulInt32-upper.wasm-run.ok | 1 - test/trap/ok/mulInt64-lower.wasm-run.ok | 1 - test/trap/ok/mulInt64-upper.wasm-run.ok | 1 - test/trap/ok/mulInt8-lower.wasm-run.ok | 1 - test/trap/ok/mulInt8-upper.wasm-run.ok | 1 - test/trap/ok/mulNat16.wasm-run.ok | 1 - test/trap/ok/mulNat32.wasm-run.ok | 1 - test/trap/ok/mulNat64.wasm-run.ok | 1 - test/trap/ok/mulNat8.wasm-run.ok | 1 - test/trap/ok/outrange-int16-lower.wasm-run.ok | 1 - .../ok/outrange-int16-negation.wasm-run.ok | 1 - test/trap/ok/outrange-int16-upper.wasm-run.ok | 1 - test/trap/ok/outrange-int32-lower.wasm-run.ok | 1 - .../ok/outrange-int32-negation.wasm-run.ok | 1 - test/trap/ok/outrange-int32-upper.wasm-run.ok | 1 - test/trap/ok/outrange-int64-lower.wasm-run.ok | 1 - .../ok/outrange-int64-negation.wasm-run.ok | 1 - test/trap/ok/outrange-int64-upper.wasm-run.ok | 1 - test/trap/ok/outrange-int8-lower.wasm-run.ok | 1 - .../ok/outrange-int8-negation.wasm-run.ok | 1 - test/trap/ok/outrange-int8-upper.wasm-run.ok | 1 - test/trap/ok/outrange-nat16.wasm-run.ok | 1 - test/trap/ok/outrange-nat32.wasm-run.ok | 1 - test/trap/ok/outrange-nat64.wasm-run.ok | 1 - test/trap/ok/outrange-nat8.wasm-run.ok | 1 - test/trap/ok/powInt32-lower.wasm-run.ok | 1 - test/trap/ok/powInt32-raise-neg.wasm-run.ok | 1 - test/trap/ok/powInt32-upper.wasm-run.ok | 1 - test/trap/ok/powInt64-lower-fast.wasm-run.ok | 1 - test/trap/ok/powInt64-lower-slow.wasm-run.ok | 1 - test/trap/ok/powInt64-raise-neg.wasm-run.ok | 1 - test/trap/ok/powInt64-upper-fast.wasm-run.ok | 1 - test/trap/ok/powInt64-upper-slow.wasm-run.ok | 1 - test/trap/ok/powInt8-lower.wasm-run.ok | 1 - test/trap/ok/powInt8-raise-neg.wasm-run.ok | 1 - test/trap/ok/powInt8-upper.wasm-run.ok | 1 - test/trap/ok/powNat16.wasm-run.ok | 1 - test/trap/ok/powNat32.wasm-run.ok | 1 - test/trap/ok/powNat64.wasm-run.ok | 1 - test/trap/ok/powNat8.wasm-run.ok | 1 - test/trap/ok/subInt16-lower.wasm-run.ok | 1 - test/trap/ok/subInt16-upper.wasm-run.ok | 1 - test/trap/ok/subInt32-lower.wasm-run.ok | 1 - test/trap/ok/subInt32-upper.wasm-run.ok | 1 - test/trap/ok/subInt64-lower.wasm-run.ok | 1 - test/trap/ok/subInt64-upper.wasm-run.ok | 1 - test/trap/ok/subInt8-lower.wasm-run.ok | 1 - test/trap/ok/subInt8-upper.wasm-run.ok | 1 - test/trap/ok/subNat16.wasm-run.ok | 1 - test/trap/ok/subNat32.wasm-run.ok | 1 - test/trap/ok/subNat64-slow.wasm-run.ok | 1 - test/trap/ok/subNat64.wasm-run.ok | 1 - test/trap/ok/subNat8.wasm-run.ok | 1 - 81 files changed, 520 insertions(+), 595 deletions(-) diff --git a/nix/wasmtime/cargo-lock.patch b/nix/wasmtime/cargo-lock.patch index 56c9879dd6e..3ce3f765988 100644 --- a/nix/wasmtime/cargo-lock.patch +++ b/nix/wasmtime/cargo-lock.patch @@ -1,20 +1,12 @@ diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 -index 00000000..3b45d5eb +index 00000000..818de492 --- /dev/null +++ b/Cargo.lock -@@ -0,0 +1,2272 @@ +@@ -0,0 +1,2276 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] -+name = "ahash" -+version = "0.2.16" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "const-random 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] +name = "aho-corasick" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" @@ -32,7 +24,7 @@ index 00000000..3b45d5eb + +[[package]] +name = "anyhow" -+version = "1.0.19" ++version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] @@ -49,17 +41,23 @@ index 00000000..3b45d5eb +] + +[[package]] ++name = "arrayvec" ++version = "0.5.1" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++ ++[[package]] +name = "atty" -+version = "0.2.13" ++version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "hermit-abi 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "autocfg" -+version = "0.1.6" ++version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] @@ -69,7 +67,7 @@ index 00000000..3b45d5eb +dependencies = [ + "backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", +] + @@ -78,8 +76,8 @@ index 00000000..3b45d5eb +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cc 1.0.49 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] @@ -97,12 +95,11 @@ index 00000000..3b45d5eb + +[[package]] +name = "bincode" -+version = "1.2.0" ++version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ++ "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] @@ -111,7 +108,7 @@ index 00000000..3b45d5eb +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cexpr 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cexpr 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "clang-sys 0.28.1 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -119,12 +116,12 @@ index 00000000..3b45d5eb + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "which 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "which 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] @@ -134,11 +131,11 @@ index 00000000..3b45d5eb + +[[package]] +name = "blake2b_simd" -+version = "0.5.8" ++version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", -+ "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", ++ "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + @@ -147,7 +144,7 @@ index 00000000..3b45d5eb +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ++ "block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -155,7 +152,7 @@ index 00000000..3b45d5eb + +[[package]] +name = "block-padding" -+version = "0.1.4" ++version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -173,11 +170,10 @@ index 00000000..3b45d5eb + +[[package]] +name = "c2-chacha" -+version = "0.2.2" ++version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ++ "ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] @@ -193,21 +189,21 @@ index 00000000..3b45d5eb +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cc 1.0.49 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cc" -+version = "1.0.46" ++version = "1.0.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "jobserver 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", -+ "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cexpr" -+version = "0.3.5" ++version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -220,12 +216,11 @@ index 00000000..3b45d5eb + +[[package]] +name = "chrono" -+version = "0.4.9" ++version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", -+ "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ++ "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", +] + @@ -235,7 +230,7 @@ index 00000000..3b45d5eb +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "libloading 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + @@ -245,11 +240,11 @@ index 00000000..3b45d5eb +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", ++ "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + @@ -266,25 +261,7 @@ index 00000000..3b45d5eb +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "const-random" -+version = "0.1.6" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "const-random-macro 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -+ "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "const-random-macro" -+version = "0.1.6" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", -+ "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cc 1.0.49 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] @@ -297,112 +274,109 @@ index 00000000..3b45d5eb +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-bforest" -+version = "0.49.0" ++version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "cranelift-entity 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-codegen" -+version = "0.49.0" ++version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-bforest 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-codegen-meta 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-codegen-shared 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-entity 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "hashbrown 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-bforest 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-codegen-meta 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-codegen-shared 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", -+ "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", -+ "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ++ "smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "thiserror 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++ "thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-codegen-meta" -+version = "0.49.0" ++version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "cranelift-codegen-shared 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-entity 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-codegen-shared 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-codegen-shared" -+version = "0.49.0" ++version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cranelift-entity" -+version = "0.49.0" ++version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ++ "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-frontend" -+version = "0.49.0" ++version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "cranelift-codegen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "hashbrown 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", -+ "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-native" -+version = "0.49.0" ++version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "cranelift-codegen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "raw-cpuid 7.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cranelift-wasm" -+version = "0.49.0" ++version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "cranelift-codegen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-entity 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-frontend 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "hashbrown 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-frontend 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", -+ "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", -+ "thiserror 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasmparser 0.39.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ++ "thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasmparser 0.39.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-deque" -+version = "0.7.1" ++version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-epoch" -+version = "0.7.2" ++version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", ++ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", -+ "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -410,10 +384,11 @@ index 00000000..3b45d5eb + +[[package]] +name = "crossbeam-queue" -+version = "0.1.2" ++version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ++ "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] @@ -426,12 +401,22 @@ index 00000000..3b45d5eb +] + +[[package]] ++name = "crossbeam-utils" ++version = "0.7.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ++ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] +name = "ctor" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] @@ -465,7 +450,7 @@ index 00000000..3b45d5eb +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] @@ -477,27 +462,27 @@ index 00000000..3b45d5eb +dependencies = [ + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", -+ "strsim 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ++ "strsim 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "dynasm" -+version = "0.5.1" ++version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "dynasmrt" -+version = "0.5.1" ++version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -514,7 +499,7 @@ index 00000000..3b45d5eb +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", ++ "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -527,7 +512,7 @@ index 00000000..3b45d5eb +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + @@ -537,21 +522,22 @@ index 00000000..3b45d5eb +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "faerie" -+version = "0.12.0" ++version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -+ "goblin 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "indexmap 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", ++ "goblin 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ++ "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "scroll 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "string-interner 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] @@ -568,10 +554,10 @@ index 00000000..3b45d5eb +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", -+ "synstructure 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", ++ "synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] @@ -595,11 +581,11 @@ index 00000000..3b45d5eb + +[[package]] +name = "filetime" -+version = "0.2.7" ++version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] @@ -624,11 +610,11 @@ index 00000000..3b45d5eb + +[[package]] +name = "getrandom" -+version = "0.1.12" ++version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + @@ -637,9 +623,9 @@ index 00000000..3b45d5eb +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] @@ -650,7 +636,7 @@ index 00000000..3b45d5eb + "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fallible-iterator 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "indexmap 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + @@ -661,7 +647,7 @@ index 00000000..3b45d5eb + +[[package]] +name = "goblin" -+version = "0.1.1" ++version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -670,25 +656,19 @@ index 00000000..3b45d5eb +] + +[[package]] -+name = "hashbrown" -+version = "0.5.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "hashbrown" -+version = "0.6.1" ++name = "heck" ++version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "ahash 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", -+ "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] -+name = "heck" -+version = "0.3.1" ++name = "hermit-abi" ++version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] @@ -696,7 +676,7 @@ index 00000000..3b45d5eb +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "quick-error 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] @@ -706,8 +686,11 @@ index 00000000..3b45d5eb + +[[package]] +name = "indexmap" -+version = "1.2.0" ++version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ++] + +[[package]] +name = "indoc" @@ -724,35 +707,35 @@ index 00000000..3b45d5eb +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", -+ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "unindent 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "inventory" -+version = "0.1.4" ++version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ctor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "ghost 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "inventory-impl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ++ "inventory-impl 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "inventory-impl" -+version = "0.1.4" ++version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "itertools" -+version = "0.8.0" ++version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -768,8 +751,8 @@ index 00000000..3b45d5eb +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + @@ -785,7 +768,7 @@ index 00000000..3b45d5eb + +[[package]] +name = "libc" -+version = "0.2.64" ++version = "0.2.66" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] @@ -793,30 +776,31 @@ index 00000000..3b45d5eb +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cc 1.0.49 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lightbeam" -+version = "0.0.0" ++version = "0.8.0" +dependencies = [ ++ "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", + "capstone 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-codegen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "dynasm 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "dynasmrt 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "dynasm 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "dynasmrt 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", -+ "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "more-asserts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "multi_mut 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "quickcheck 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "thiserror 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++ "smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "typemap 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasmparser 0.39.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wat 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasmparser 0.39.3 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wat 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] @@ -832,7 +816,7 @@ index 00000000..3b45d5eb +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] @@ -845,7 +829,7 @@ index 00000000..3b45d5eb +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + @@ -873,9 +857,9 @@ index 00000000..3b45d5eb +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cc 1.0.49 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + @@ -902,7 +886,7 @@ index 00000000..3b45d5eb + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ++ "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] @@ -910,8 +894,8 @@ index 00000000..3b45d5eb +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -+ "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ++ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ++ "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] @@ -919,8 +903,8 @@ index 00000000..3b45d5eb +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -+ "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ++ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ++ "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] @@ -928,9 +912,9 @@ index 00000000..3b45d5eb +version = "0.1.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", -+ "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ++ "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] @@ -938,25 +922,26 @@ index 00000000..3b45d5eb +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", -+ "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ++ "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-traits" -+version = "0.2.8" ++version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num_cpus" -+version = "1.10.1" ++version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "hermit-abi 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] @@ -969,7 +954,7 @@ index 00000000..3b45d5eb +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + @@ -996,9 +981,9 @@ index 00000000..3b45d5eb +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", -+ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] @@ -1013,7 +998,7 @@ index 00000000..3b45d5eb + +[[package]] +name = "ppv-lite86" -+version = "0.2.5" ++version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] @@ -1021,7 +1006,7 @@ index 00000000..3b45d5eb +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", ++ "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", +] @@ -1031,14 +1016,14 @@ index 00000000..3b45d5eb +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro2" -+version = "1.0.6" ++version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1046,19 +1031,19 @@ index 00000000..3b45d5eb + +[[package]] +name = "pyo3" -+version = "0.8.1" ++version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "indoc 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", -+ "inventory 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ++ "inventory 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", -+ "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ++ "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -+ "pyo3cls 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "pyo3cls 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", -+ "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", ++ "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ++ "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unindent 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1066,28 +1051,28 @@ index 00000000..3b45d5eb + +[[package]] +name = "pyo3-derive-backend" -+version = "0.8.1" ++version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pyo3cls" -+version = "0.8.1" ++version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", -+ "pyo3-derive-backend 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", ++ "pyo3-derive-backend 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quick-error" -+version = "1.2.2" ++version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] @@ -1106,7 +1091,7 @@ index 00000000..3b45d5eb +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] @@ -1114,12 +1099,12 @@ index 00000000..3b45d5eb +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "rand_pcg 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "rand_pcg 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] @@ -1127,7 +1112,7 @@ index 00000000..3b45d5eb +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + @@ -1149,7 +1134,7 @@ index 00000000..3b45d5eb +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ++ "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] @@ -1167,7 +1152,7 @@ index 00000000..3b45d5eb +dependencies = [ + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1175,10 +1160,9 @@ index 00000000..3b45d5eb + +[[package]] +name = "rand_pcg" -+version = "0.2.0" ++version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + @@ -1188,30 +1172,30 @@ index 00000000..3b45d5eb +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cc 1.0.49 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rayon" -+version = "1.2.0" ++version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", -+ "rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rayon-core" -+version = "1.6.0" ++version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] @@ -1260,7 +1244,7 @@ index 00000000..3b45d5eb +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "mach 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] @@ -1279,7 +1263,7 @@ index 00000000..3b45d5eb +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "blake2b_simd 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", ++ "blake2b_simd 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + @@ -1327,9 +1311,9 @@ index 00000000..3b45d5eb +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] @@ -1347,35 +1331,35 @@ index 00000000..3b45d5eb + +[[package]] +name = "serde" -+version = "1.0.101" ++version = "1.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ++ "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_derive" -+version = "1.0.101" ++version = "1.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_json" -+version = "1.0.41" ++version = "1.0.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ++ "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sha2" -+version = "0.8.0" ++version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1391,7 +1375,7 @@ index 00000000..3b45d5eb + +[[package]] +name = "smallvec" -+version = "1.0.0" ++version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] @@ -1409,7 +1393,7 @@ index 00000000..3b45d5eb +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ++ "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] @@ -1419,27 +1403,27 @@ index 00000000..3b45d5eb + +[[package]] +name = "strsim" -+version = "0.9.2" ++version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "syn" -+version = "1.0.5" ++version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "synstructure" -+version = "0.12.1" ++version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + @@ -1454,7 +1438,7 @@ index 00000000..3b45d5eb +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1470,29 +1454,49 @@ index 00000000..3b45d5eb +] + +[[package]] ++name = "test-programs" ++version = "0.8.0" ++dependencies = [ ++ "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "os_pipe 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "pretty_env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasi-common 0.8.0", ++ "wasmtime 0.8.0", ++ "wasmtime-environ 0.8.0", ++ "wasmtime-jit 0.8.0", ++ "wasmtime-runtime 0.8.0", ++ "wasmtime-wasi 0.8.0", ++ "wat 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "thiserror" -+version = "1.0.5" ++version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "thiserror-impl 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++ "thiserror-impl 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "thiserror-impl" -+version = "1.0.5" ++version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] @@ -1508,7 +1512,7 @@ index 00000000..3b45d5eb +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] @@ -1518,7 +1522,7 @@ index 00000000..3b45d5eb +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ++ "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] @@ -1528,13 +1532,13 @@ index 00000000..3b45d5eb + +[[package]] +name = "trybuild" -+version = "1.0.17" ++version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", -+ "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", ++ "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ++ "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", +] @@ -1554,12 +1558,12 @@ index 00000000..3b45d5eb + +[[package]] +name = "unicode-segmentation" -+version = "1.3.0" ++version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-width" -+version = "0.1.6" ++version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] @@ -1605,12 +1609,12 @@ index 00000000..3b45d5eb +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "anyhow 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", ++ "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", + "id-arena 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "leb128 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "walrus-macro 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasmparser 0.39.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasmparser 0.39.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] @@ -1619,9 +1623,9 @@ index 00000000..3b45d5eb +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] @@ -1631,42 +1635,33 @@ index 00000000..3b45d5eb + +[[package]] +name = "wasi-common" -+version = "0.5.0" ++version = "0.8.0" +dependencies = [ -+ "anyhow 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", ++ "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cpu-time 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-codegen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "filetime 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ++ "filetime 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "nix 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "os_pipe 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "pretty_env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "thiserror 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasi-common-cbindgen 0.5.0", -+ "wasmtime 0.1.0", -+ "wasmtime-environ 0.2.0", -+ "wasmtime-jit 0.2.0", -+ "wasmtime-runtime 0.2.0", -+ "wasmtime-wasi 0.2.0", -+ "wig 0.1.0", ++ "thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasi-common-cbindgen 0.8.0", ++ "wig 0.8.0", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -+ "winx 0.5.0", ++ "winx 0.8.0", +] + +[[package]] +name = "wasi-common-cbindgen" -+version = "0.5.0" ++version = "0.8.0" +dependencies = [ ++ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", -+ "trybuild 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", ++ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", ++ "trybuild 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] @@ -1674,7 +1669,7 @@ index 00000000..3b45d5eb +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "anyhow 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", ++ "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", + "id-arena 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "leb128 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "walrus 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1682,284 +1677,291 @@ index 00000000..3b45d5eb + +[[package]] +name = "wasmparser" -+version = "0.39.2" ++version = "0.39.3" +source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "hashbrown 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", -+] + +[[package]] +name = "wasmtime" -+version = "0.1.0" ++version = "0.8.0" +dependencies = [ -+ "anyhow 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-codegen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-entity 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-frontend 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-native 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-wasm 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-frontend 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-native 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-wasm 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "docopt 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "file-per-thread-logger 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "hashbrown 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pretty_env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "region 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ++ "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "thiserror 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasi-common 0.5.0", -+ "wasmparser 0.39.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasmtime-environ 0.2.0", -+ "wasmtime-jit 0.2.0", -+ "wasmtime-runtime 0.2.0", -+ "wasmtime-wasi 0.2.0", -+ "wasmtime-wast 0.2.0", ++ "thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasi-common 0.8.0", ++ "wasmparser 0.39.3 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasmtime-environ 0.8.0", ++ "wasmtime-jit 0.8.0", ++ "wasmtime-runtime 0.8.0", ++ "wasmtime-wasi 0.8.0", ++ "wasmtime-wast 0.8.0", ++ "wat 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasmtime-cli" -+version = "0.2.0" ++version = "0.8.0" +dependencies = [ -+ "anyhow 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-codegen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-entity 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-native 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-wasm 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-native 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-wasm 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "docopt 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "faerie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "faerie 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "file-per-thread-logger 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "more-asserts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pretty_env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ++ "rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasi-common 0.5.0", ++ "test-programs 0.8.0", ++ "wasi-common 0.8.0", + "wasm-webidl-bindings 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasmtime 0.1.0", -+ "wasmtime-debug 0.2.0", -+ "wasmtime-environ 0.2.0", -+ "wasmtime-interface-types 0.2.0", -+ "wasmtime-jit 0.2.0", -+ "wasmtime-obj 0.2.0", -+ "wasmtime-runtime 0.2.0", -+ "wasmtime-wasi 0.2.0", -+ "wasmtime-wasi-c 0.2.0", -+ "wasmtime-wast 0.2.0", -+ "wat 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasmtime 0.8.0", ++ "wasmtime-debug 0.8.0", ++ "wasmtime-environ 0.8.0", ++ "wasmtime-interface-types 0.8.0", ++ "wasmtime-jit 0.8.0", ++ "wasmtime-obj 0.8.0", ++ "wasmtime-runtime 0.8.0", ++ "wasmtime-wasi 0.8.0", ++ "wasmtime-wasi-c 0.8.0", ++ "wasmtime-wast 0.8.0", ++ "wat 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasmtime-debug" -+version = "0.2.0" ++version = "0.8.0" +dependencies = [ -+ "cranelift-codegen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-entity 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-wasm 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "faerie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-wasm 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "faerie 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gimli 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "hashbrown 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "more-asserts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "thiserror 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasmparser 0.39.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasmtime-environ 0.2.0", ++ "thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasmparser 0.39.3 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasmtime-environ 0.8.0", +] + +[[package]] +name = "wasmtime-environ" -+version = "0.2.0" ++version = "0.8.0" +dependencies = [ + "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-codegen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-entity 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-wasm 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "bincode 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-wasm 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "directories 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "file-per-thread-logger 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "filetime 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", -+ "indexmap 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "filetime 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ++ "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", -+ "lightbeam 0.0.0", ++ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ++ "lightbeam 0.8.0", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "more-asserts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pretty_env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", -+ "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ++ "sha2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "thiserror 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++ "thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasmparser 0.39.3 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "zstd 0.5.1+zstd.1.4.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasmtime-interface-types" -+version = "0.2.0" ++version = "0.8.0" +dependencies = [ -+ "anyhow 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-codegen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "walrus 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-webidl-bindings 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasmparser 0.39.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasmtime-jit 0.2.0", -+ "wasmtime-runtime 0.2.0", ++ "wasmparser 0.39.3 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasmtime 0.8.0", ++ "wasmtime-jit 0.8.0", ++ "wasmtime-runtime 0.8.0", ++ "wasmtime-wasi 0.8.0", +] + +[[package]] +name = "wasmtime-jit" -+version = "0.2.0" ++version = "0.8.0" +dependencies = [ -+ "cranelift-codegen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-entity 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-frontend 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-wasm 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -+ "hashbrown 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-frontend 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-wasm 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "more-asserts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "region 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "thiserror 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasmparser 0.39.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasmtime-debug 0.2.0", -+ "wasmtime-environ 0.2.0", -+ "wasmtime-runtime 0.2.0", ++ "thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasmparser 0.39.3 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasmtime-debug 0.8.0", ++ "wasmtime-environ 0.8.0", ++ "wasmtime-runtime 0.8.0", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasmtime-obj" -+version = "0.2.0" ++version = "0.8.0" +dependencies = [ -+ "cranelift-codegen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-entity 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-wasm 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "faerie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-wasm 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "faerie 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "more-asserts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasmtime-environ 0.2.0", ++ "wasmtime-environ 0.8.0", +] + +[[package]] +name = "wasmtime-py" -+version = "0.2.0" ++version = "0.8.0" +dependencies = [ -+ "anyhow 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-codegen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-entity 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-frontend 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-native 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-wasm 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "pyo3 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-frontend 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-native 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-wasm 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "pyo3 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", + "region 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasmparser 0.39.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasmtime-environ 0.2.0", -+ "wasmtime-interface-types 0.2.0", -+ "wasmtime-jit 0.2.0", -+ "wasmtime-runtime 0.2.0", ++ "wasmparser 0.39.3 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasmtime 0.8.0", ++ "wasmtime-environ 0.8.0", ++ "wasmtime-interface-types 0.8.0", ++ "wasmtime-jit 0.8.0", ++ "wasmtime-runtime 0.8.0", ++ "wasmtime-wasi 0.8.0", +] + +[[package]] +name = "wasmtime-runtime" -+version = "0.2.0" ++version = "0.8.0" +dependencies = [ -+ "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-codegen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-entity 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-wasm 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "hashbrown 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "indexmap 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cc 1.0.49 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-wasm 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "more-asserts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "region 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "thiserror 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasmtime-environ 0.2.0", ++ "thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasmtime-environ 0.8.0", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasmtime-rust" -+version = "0.2.0" ++version = "0.8.0" +dependencies = [ -+ "anyhow 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-codegen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-native 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasmtime-interface-types 0.2.0", -+ "wasmtime-jit 0.2.0", -+ "wasmtime-rust-macro 0.2.0", -+ "wasmtime-wasi 0.2.0", ++ "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasmtime 0.8.0", ++ "wasmtime-interface-types 0.8.0", ++ "wasmtime-jit 0.8.0", ++ "wasmtime-rust-macro 0.8.0", ++ "wasmtime-wasi 0.8.0", +] + +[[package]] +name = "wasmtime-rust-macro" -+version = "0.2.0" ++version = "0.8.0" +dependencies = [ -+ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ++ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasmtime-wasi" -+version = "0.2.0" ++version = "0.8.0" +dependencies = [ -+ "cranelift-codegen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-entity 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-wasm 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-wasm 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasi-common 0.5.0", -+ "wasmtime-environ 0.2.0", -+ "wasmtime-jit 0.2.0", -+ "wasmtime-runtime 0.2.0", ++ "wasi-common 0.8.0", ++ "wasmtime 0.8.0", ++ "wasmtime-environ 0.8.0", ++ "wasmtime-jit 0.8.0", ++ "wasmtime-runtime 0.8.0", +] + +[[package]] +name = "wasmtime-wasi-c" -+version = "0.2.0" ++version = "0.8.0" +dependencies = [ + "bindgen 0.51.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-codegen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-entity 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-wasm 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-wasm 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "more-asserts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasmtime-environ 0.2.0", -+ "wasmtime-jit 0.2.0", -+ "wasmtime-runtime 0.2.0", ++ "wasmtime-environ 0.8.0", ++ "wasmtime-jit 0.8.0", ++ "wasmtime-runtime 0.8.0", +] + +[[package]] +name = "wasmtime-wast" -+version = "0.2.0" ++version = "0.8.0" +dependencies = [ -+ "anyhow 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-codegen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-entity 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-wasm 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cranelift-wasm 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasmtime-environ 0.2.0", -+ "wasmtime-jit 0.2.0", -+ "wasmtime-runtime 0.2.0", -+ "wast 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wasmtime-environ 0.8.0", ++ "wasmtime-jit 0.8.0", ++ "wasmtime-runtime 0.8.0", ++ "wast 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ++] ++ ++[[package]] ++name = "wast" ++version = "3.0.4" ++source = "registry+https://github.com/rust-lang/crates.io-index" ++dependencies = [ ++ "leb128 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wast" -+version = "3.0.2" ++version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "leb128 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1967,27 +1969,28 @@ index 00000000..3b45d5eb + +[[package]] +name = "wat" -+version = "1.0.3" ++version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "wast 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wast 5.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "which" -+version = "3.0.0" ++version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wig" -+version = "0.1.0" ++version = "0.8.0" +dependencies = [ -+ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ++ "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ++ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "witx 0.4.0", ++ "witx 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] @@ -2028,7 +2031,7 @@ index 00000000..3b45d5eb + +[[package]] +name = "winx" -+version = "0.5.0" ++version = "0.8.0" +dependencies = [ + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cvt 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2037,11 +2040,12 @@ index 00000000..3b45d5eb + +[[package]] +name = "witx" -+version = "0.4.0" ++version = "0.5.0" ++source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wast 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ++ "wast 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] @@ -2057,7 +2061,7 @@ index 00000000..3b45d5eb +version = "2.0.3+zstd.1.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "zstd-sys 1.4.15+zstd.1.4.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + @@ -2066,102 +2070,100 @@ index 00000000..3b45d5eb +version = "1.4.15+zstd.1.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ -+ "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cc 1.0.49 (registry+https://github.com/rust-lang/crates.io-index)", + "glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)", ++ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[metadata] -+"checksum ahash 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)" = "b35dfc96a657c1842b4eb73180b65e37152d4b94d0eb5cb51708aee7826950b4" +"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" +"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -+"checksum anyhow 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "57114fc2a6cc374bce195d3482057c846e706d252ff3604363449695684d7a0d" ++"checksum anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "7825f6833612eb2414095684fcf6c635becf3ce97fe48cf6421321e93bfbd53c" +"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" +"checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" -+"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" -+"checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" ++"checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" ++"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" ++"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" +"checksum backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea" +"checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491" +"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" +"checksum base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" -+"checksum bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8ab639324e3ee8774d296864fbc0dbbb256cf1a41c490b94cba90c082915f92" ++"checksum bincode 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5753e2a71534719bf3f4e57006c3a4f0d2c672a4b676eec84161f763eca87dbf" +"checksum bindgen 0.51.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ebd71393f1ec0509b553aa012b9b58e81dadbdff7130bd3b8cba576e69b32f75" +"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" -+"checksum blake2b_simd 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "5850aeee1552f495dd0250014cf64b82b7c8879a89d83b33bbdace2cc4f63182" ++"checksum blake2b_simd 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a" +"checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" -+"checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09" ++"checksum block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" +"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" -+"checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" ++"checksum c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" +"checksum capstone 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "031ba51c39151a1d6336ec859646153187204b0147c7b3f6fe2de636f1b8dbb3" +"checksum capstone-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fae25eddcb80e24f98c35952c37a91ff7f8d0f60dbbdafb9763e8d5cc566b8d7" -+"checksum cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)" = "0213d356d3c4ea2c18c40b037c3be23cd639825c18f25ee670ac7813beeef99c" -+"checksum cexpr 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7fa24eb00d5ffab90eaeaf1092ac85c04c64aaf358ea6f84505b8116d24c6af" ++"checksum cc 1.0.49 (registry+https://github.com/rust-lang/crates.io-index)" = "e450b8da92aa6f274e7c6437692f9f2ce6d701fb73bacfcf87897b3f89a4c20e" ++"checksum cexpr 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fce5b5fb86b0c57c20c834c1b412fd09c77c8a59b9473f86272709e78874cd1d" +"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" -+"checksum chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e8493056968583b0193c1bb04d6f7684586f3726992d6c573261941a895dbd68" ++"checksum chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "31850b4a4d6bae316f7a09e691c944c28299298837edc0a03f755618c23cbc01" +"checksum clang-sys 0.28.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81de550971c976f176130da4b2978d3b524eaa0fd9ac31f3ceb5ae1231fb4853" +"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" +"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +"checksum cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "81fb25b677f8bf1eb325017cb6bb8452f87969db0fedb4f757b297bee78a7c62" -+"checksum const-random 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7b641a8c9867e341f3295564203b1c250eb8ce6cb6126e007941f78c4d2ed7fe" -+"checksum const-random-macro 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c750ec12b83377637110d5a57f5ae08e895b06c4b16e2bdbf1a94ef717428c59" +"checksum constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "995a44c877f9212528ccc74b21a232f66ad69001e40ede5bcee2ac9ef2657120" +"checksum cpu-time 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e9e393a7668fe1fad3075085b86c781883000b4ede868f43627b34a87c8b7ded" -+"checksum cranelift-bforest 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba29e425110674c89fdc2f79479d767f31003dd9187c29ba2dad57fe4d321670" -+"checksum cranelift-codegen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8cb71c7ce1438c41f3d35383fa41eee26f5adf9815c7f5c2e7029a6c9356df2c" -+"checksum cranelift-codegen-meta 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4aa634fd60290d5047d40172028a0aa86458e32a72c76fcce0a317bbbbcca4e5" -+"checksum cranelift-codegen-shared 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6fa6cf5c2adc031be07cd5bc88145ebb93d9d2a05a28a93136782b2167eacb62" -+"checksum cranelift-entity 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)" = "932d5f9622b336e10e8cf843ded09a688ec49f32c32b3101d7c5a7b71cad3dc9" -+"checksum cranelift-frontend 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d1a3c105c657cd65c20d9183bbd4f2b16bf3548db4b865c065bf7028f3021de" -+"checksum cranelift-native 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba5e34645453b73a9e2def05561f957a9df17253996379dd59c4afe3cf7db0f1" -+"checksum cranelift-wasm 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23410ae1f5edf7d83e95bf8537e771345ecc2b11e5c7208cbee8151ea3b88e97" -+"checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" -+"checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" -+"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" ++"checksum cranelift-bforest 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd05aac8cefcde54ce26178df8f36cb1f518ac691db650e7d2440c2b6b41c4dc" ++"checksum cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c63d9b6ff8a94f98deabab21880d7fd54996e0e16be687b6f80a3b6bdd9c188d" ++"checksum cranelift-codegen-meta 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7cb3df51c2c07d719d02869bfac6cabd8d82ee308d5b29ca62e6528723cc33a4" ++"checksum cranelift-codegen-shared 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "758f9426b2e22bf83fc1a6b231a9d53cd4830751883c7f0e196ebb3c210467b3" ++"checksum cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff064733df8b98f453060264a8790393d1e807aca6942706b42f79a4f7aae9ed" ++"checksum cranelift-frontend 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1eaafb5fa623dcbe19a28084a8226d7a1b17184a949c1a1f29a46b479867998d" ++"checksum cranelift-native 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "90033dbd7293f6fad4cf9dcd769cd621d60df22b1c5a11799e86359b7447a51d" ++"checksum cranelift-wasm 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "54cb82a1071f88822763a583ec1a8688ffe5e2cda02c111d4483dd4376ed14d8" ++"checksum crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3aa945d63861bfe624b55d153a39684da1e8c0bc8fba932f7ee3a3c16cea3ca" ++"checksum crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac" ++"checksum crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db" +"checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" ++"checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" +"checksum ctor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd8ce37ad4184ab2ce004c33bf6379185d3b1c95801cab51026bd271bf68eedc" +"checksum cvt 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "34ac344c7efccb80cd25bc61b2170aec26f2f693fd40e765a539a1243db48c71" +"checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +"checksum directories 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "551a778172a450d7fc12e629ca3b0428d00f6afa9a43da1b630d54604e97371c" +"checksum dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b" +"checksum docopt 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f525a586d310c87df72ebcd98009e57f1cc030c8c268305287a476beb653969" -+"checksum dynasm 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8654f63488a94cd11feac2a609fdcdecd09e02fb582731f635783689fbb429f3" -+"checksum dynasmrt 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b0046b083139885c38990f2fb9822d06f6c5902068d93a6ed9e56b63011b9932" ++"checksum dynasm 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "42a814e1edeb85dd2a3c6fc0d6bf76d02ca5695d438c70ecee3d90774f3259c5" ++"checksum dynasmrt 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8a393aaeb4441a48bcf47b5b6155971f82cc1eb77e22855403ccc0415ac8328d" +"checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" +"checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" +"checksum errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2a071601ed01b988f896ab14b95e67335d1eeb50190932a1320f7fe3cadc84e" +"checksum errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "14ca354e36190500e1e1fb267c647932382b54053c50b14970856c0b00a35067" -+"checksum faerie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "01fed63609767c70e34203201032c249d60a24578a67ef0ce7cc13ff010e9cf2" ++"checksum faerie 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f902f2af041f6c7177a2a04f805687cdc71e69c7cbef059a2755d8923f4cd7a8" +"checksum failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9" +"checksum failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0bc225b78e0391e4b8683440bf2e63c2deeeb2ce5189eab46e2b68c6d3725d08" +"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" +"checksum fallible-iterator 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" +"checksum file-per-thread-logger 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8505b75b31ef7285168dd237c4a7db3c1f3e0927e7d314e670bc98e854272fe9" -+"checksum filetime 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6bd7380b54ced79dda72ecc35cc4fbbd1da6bba54afaa37e96fd1c2a308cd469" ++"checksum filetime 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1ff6d4dab0aa0c8e6346d46052e93b13a16cf847b54ed357087c35011048cc7d" +"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" +"checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" +"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" -+"checksum getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571" ++"checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407" +"checksum ghost 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2a36606a68532b5640dc86bb1f33c64b45c4682aad4c50f3937b317ea387f3d6" +"checksum gimli 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "162d18ae5f2e3b90a993d202f1ba17a5633c2484426f8bcae201f86194bacd00" +"checksum glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" -+"checksum goblin 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6040506480da04a63de51a478e8021892d65d8411f29b2a422c2648bdd8bcb" -+"checksum hashbrown 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e1de41fb8dba9714efd92241565cdff73f78508c95697dd56787d3cba27e2353" -+"checksum hashbrown 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6587d09be37fb98a11cb08b9000a3f592451c1b1b613ca69d949160e313a430a" ++"checksum goblin 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3081214398d39e4bd7f2c1975f0488ed04614ffdd976c6fc7a0708278552c0da" +"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" ++"checksum hermit-abi 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eff2656d88f158ce120947499e971d743c05dbcbed62e5bd2f38f1698bbc3772" +"checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" +"checksum id-arena 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" -+"checksum indexmap 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a61202fbe46c4a951e9404a720a0180bcf3212c750d735cb5c4ba4dc551299f3" ++"checksum indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712d7b3ea5827fcb9d4fda14bf4da5f136f0db2ae9c8f4bd4e2d1c6fde4e6db2" +"checksum indoc 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3f9553c1e16c114b8b77ebeb329e5f2876eed62a8d51178c8bc6bff0d65f98f8" +"checksum indoc-impl 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b714fc08d0961716390977cdff1536234415ac37b509e34e5a983def8340fb75" -+"checksum inventory 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f4cece20baea71d9f3435e7bbe9adf4765f091c5fe404975f844006964a71299" -+"checksum inventory-impl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2869bf972e998977b1cb87e60df70341d48e48dca0823f534feb91ea44adaf9" -+"checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" ++"checksum inventory 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2bf98296081bd2cb540acc09ef9c97f22b7e487841520350293605db1b2c7a27" ++"checksum inventory-impl 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0a8e30575afe28eea36a9a39136b70b2fb6b0dd0a212a5bd1f30a498395c0274" ++"checksum itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484" +"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" +"checksum jobserver 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "f2b1d42ef453b30b7387e113da1c83ab1605d90c5b4e0eb8e96d016ed3b8c160" +"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +"checksum leb128 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3576a87f2ba00f6f106fdfcd16db1d698d648a26ad8e0573cad8537c3c362d2a" -+"checksum libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)" = "74dfca3d9957906e8d1e6a0b641dc9a59848e793f1da2165889fd4f62d10d79c" ++"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" +"checksum libloading 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753" +"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" +"checksum mach 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "86dd2487cdfea56def77b88438a2c915fb45113c5319bfe7e14306ca4cd0b0e1" @@ -2178,8 +2180,8 @@ index 00000000..3b45d5eb +"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" +"checksum num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "76bd5272412d173d6bf9afdf98db8612bbabc9a7a830b7bfc9c188911716132e" +"checksum num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2885278d5fe2adc2f75ced642d52d879bffaceb5a2e0b1d4309ffdfb239b454" -+"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" -+"checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" ++"checksum num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c81ffc11c212fa327657cb19dd85eb7419e163b5b076bede2bdb5c974c07e4" ++"checksum num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76dac5ed2a876980778b8b85f75a71b6cbf0db0b1232ee12f826bccb00d09d72" +"checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" +"checksum os_pipe 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "db4d06355a7090ce852965b2d08e11426c315438462638c6d721448d0b47aa22" +"checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" @@ -2187,14 +2189,14 @@ index 00000000..3b45d5eb +"checksum paste-impl 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4214c9e912ef61bf42b81ba9a47e8aad1b2ffaf739ab162bf96d1e011f54e6c5" +"checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" +"checksum plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" -+"checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" ++"checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" +"checksum pretty_env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "717ee476b1690853d222af4634056d830b5197ffd747726a9a1eee6da9f49074" +"checksum proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5" -+"checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" -+"checksum pyo3 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a00f96312ebe4082db7d93ad062df1818f597660002541c1bbae6752ec583244" -+"checksum pyo3-derive-backend 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1a7caa60cb986fca5b488e29d078fb25ae228e01dab080b855168ce061bbef0a" -+"checksum pyo3cls 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a5ccfa624ed9b5d805079f1ad64b3f1de5d551a946d4cf494f1f032b5572d39f" -+"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" ++"checksum proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0319972dcae462681daf4da1adeeaa066e3ebd29c69be96c6abb1259d2ee2bcc" ++"checksum pyo3 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e1bfe257586436fbe1296d917f14a167d4253d0873bf43e2c9b9bdd58a3f9f35" ++"checksum pyo3-derive-backend 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4882d8237fd8c7373cc25cb802fe0dab9ff70830fd56f47ef6c7f3f287fcc057" ++"checksum pyo3cls 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fdf321cfab555f7411298733c86d21e5136f5ded13f5872fabf9de3337beecda" ++"checksum quick-error 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" +"checksum quickcheck 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d5ca504a2fdaa08d3517f442fbbba91ac24d1ec4c51ea68688a038765e3b2662" +"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" +"checksum rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412" @@ -2204,10 +2206,10 @@ index 00000000..3b45d5eb +"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" -+"checksum rand_pcg 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e196346cbbc5c70c77e7b4926147ee8e383a38ee4d15d58a08098b169e492b6" ++"checksum rand_pcg 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" +"checksum raw-cpuid 7.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4a349ca83373cfa5d6dbb66fd76e58b2cca08da71a5f6400de0a0a6a9bceeaf" -+"checksum rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83a27732a533a1be0a0035a111fe76db89ad312f6f0347004c220c57f209a123" -+"checksum rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98dcf634205083b17d0861252431eb2acbfb698ab7478a2d20de07954f47ec7b" ++"checksum rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db6ce3297f9c85e16621bb8cca38a06779ffc31bb8184e1be4bed2be4678a098" ++"checksum rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9" +"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" +"checksum redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecedbca3bf205f8d8f5c2b44d83cd0690e39ee84b951ed649e9f1841132b66d" @@ -2225,34 +2227,34 @@ index 00000000..3b45d5eb +"checksum scroll_derive 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8584eea9b9ff42825b46faf46a8c24d2cff13ec152fa2a50df788b87c07ee28" +"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -+"checksum serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd" -+"checksum serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "4b133a43a1ecd55d4086bd5b4dc6c1751c68b1bfbeba7a5040442022c7e7c02e" -+"checksum serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "2f72eb2a68a7dc3f9a691bfda9305a1c017a6215e5a4545c258500d2099a37c2" -+"checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" ++"checksum serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449" ++"checksum serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64" ++"checksum serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)" = "48c575e0cc52bdd09b47f330f646cf59afc586e9c4e3ccd6fc1f625b8ea1dad7" ++"checksum sha2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "27044adfd2e1f077f649f59deb9490d3941d674002f7d062870a60ebe9bd47a0" +"checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" -+"checksum smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecf3b85f68e8abaa7555aa5abdb1153079387e60b718283d732f03897fcfc86" ++"checksum smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44e59e0c9fa00817912ae6e4e6e3c4fe04455e75699d06eedc7d85917ed8e8f4" +"checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" +"checksum string-interner 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd710eadff449a1531351b0e43eb81ea404336fa2f56c777427ab0e32a4cf183" +"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -+"checksum strsim 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "032c03039aae92b350aad2e3779c352e104d919cb192ba2fabbd7b831ce4f0f6" -+"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" -+"checksum synstructure 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f085a5855930c0441ca1288cf044ea4aecf4f43a91668abdb870b4ba546a203" ++"checksum strsim 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" ++"checksum syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1e4ff033220a41d1a57d8125eab57bf5263783dfdcc18688b1dacc6ce9651ef8" ++"checksum synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" +"checksum target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6f4c118a7a38378f305a9e111fcb2f7f838c0be324bfb31a77ea04f7f6e684b4" +"checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" +"checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" +"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -+"checksum thiserror 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f9fb62ff737e573b1e677459bea6fd023cd5d6e868c3242d3cdf3ef2f0554824" -+"checksum thiserror-impl 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "24069c0ba08aab54289d6a25f5036d94afc61e1538bbc42ae5501df141c9027d" ++"checksum thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6f357d1814b33bc2dc221243f8424104bfe72dbe911d5b71b3816a2dff1c977e" ++"checksum thiserror-impl 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2e25d25307eb8436894f727aba8f65d07adf02e5b35a13cebed48bd282bfef" +"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" +"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" +"checksum toml 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "01d1404644c8b12b16bfcffa4322403a91a451584daaaa7c28d3152e6cbc98cf" +"checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" -+"checksum trybuild 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "e6851bf8351876984fbab8a2391de6378947b898410d8714edd12164d2137127" ++"checksum trybuild 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "987d6fdc45ddd7f3be5aa7386c8c8a844d1655c95b9ed948a9cd9cded8f2b79f" +"checksum typemap 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "653be63c80a3296da5551e1bfd2cca35227e13cdd08c6668903ae2f4f77aa1f6" +"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" -+"checksum unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1967f4cdfc355b37fd76d2a954fb2ed3871034eb4f26d60537d88795cfc332a9" -+"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" ++"checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" ++"checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" +"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +"checksum unindent 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "63f18aa3b0e35fed5a0048f029558b1518095ffe2a0a31fb87c93dece93a4993" +"checksum unsafe-any 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f30360d7979f5e9c6e6cea48af192ea8fab4afb3cf72597154b8f08935bc9c7f" @@ -2264,15 +2266,17 @@ index 00000000..3b45d5eb +"checksum walrus-macro 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8757b0da38353d55a9687f4dee68a8f441f980dd36e16ab07d6e6c673f505f76" +"checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" +"checksum wasm-webidl-bindings 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b5cae185868c6038a48f487b9af3766ee0c68d4a85fa3610c3a0522092b3cec1" -+"checksum wasmparser 0.39.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e5083b449454f7de0b15f131eee17de54b5a71dcb9adcf11df2b2f78fad0cd82" -+"checksum wast 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "86b52202bd73a756b216bbfea019991ff317b1e5f22677da5cef2964696a3245" -+"checksum wat 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "80db13d155bab63db0f19c24a0e12bf60c3fe346edba8da508ba6962e08c137b" -+"checksum which 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "240a31163872f7e8e49f35b42b58485e35355b07eb009d9f3686733541339a69" ++"checksum wasmparser 0.39.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c702914acda5feeeffbc29e4d953e5b9ce79d8b98da4dbf18a77086e116c5470" ++"checksum wast 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "233648f540f07fce9b972436f2fbcae8a750c1121b6d32d949e1a44b4d9fc7b1" ++"checksum wast 5.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8d1de68310854a9840d39487701a8c1acccb5c9f9f2650d5fce3cdfe6650c372" ++"checksum wat 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d916cc60b1b79ac1ca7683af8d6ec56b789167f7f696b3f1ab3d98961129f192" ++"checksum which 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5475d47078209a02e60614f7ba5e645ef3ed60f771920ac1906d7c1cc65024c8" +"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +"checksum wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "96f5016b18804d24db43cebf3c77269e7569b8954a8464501c216cc5e070eaa9" ++"checksum witx 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6d075344afebe51633c0302fc11698c2d6414f9d366c749db1af57710f112561" +"checksum zstd 0.5.1+zstd.1.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5c5d978b793ae64375b80baf652919b148f6a496ac8802922d9999f5a553194f" +"checksum zstd-safe 2.0.3+zstd.1.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bee25eac9753cfedd48133fa1736cbd23b774e253d89badbeac7d12b23848d3f" +"checksum zstd-sys 1.4.15+zstd.1.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "89719b034dc22d240d5b407fb0a3fe6d29952c181cff9a9f95c0bd40b4f8f7d8" diff --git a/nix/wasmtime/default.nix b/nix/wasmtime/default.nix index 7b263b5c9aa..c978f023936 100644 --- a/nix/wasmtime/default.nix +++ b/nix/wasmtime/default.nix @@ -1,18 +1,18 @@ { rustPlatform, fetchFromGitHub, lib, python, cmake, llvmPackages, clang, stdenv, darwin }: -rustPlatform.buildRustPackage { +rustPlatform.buildRustPackage rec { pname = "wasmtime"; - version = "20191111"; + version = "v0.8.0"; src = fetchFromGitHub { - owner = "CraneStation"; - repo = "wasmtime"; - rev = "0006a2af954eba74c79885cb1fe8cdeb68f531c1"; - sha256 = "0lf3pdkjxcrjmjic7xxyjl5dka3arxi809sp9hm4hih5p2fhf2gw"; + owner = "bytecodealliance"; + repo = "${pname}"; + rev = "${version}"; + sha256 = "0az893srw49szvs5461bd165ffla4cc98gh42p3dwskwfkhpqjm4"; fetchSubmodules = true; }; - cargoSha256 = "0mnwaipa2az3vpgbz4m9siz6bfyhmzwz174k678cv158m7mxx12f"; + cargoSha256 = "08b3rbnl7qwyfbwaqcb7z84sh0h94v18v6557hrf0dlil414v54i"; cargoPatches = [ ./cargo-lock.patch ]; @@ -22,7 +22,7 @@ rustPlatform.buildRustPackage { LIBCLANG_PATH = "${llvmPackages.libclang}/lib"; meta = with lib; { - description = "Standalone JIT-style runtime for WebAsssembly, using Cranelift"; + description = "Standalone JIT-style runtime for WebAssembly, using Cranelift"; homepage = https://github.com/CraneStation/wasmtime; license = licenses.asl20; maintainers = [ maintainers.matthewbauer ]; diff --git a/test/run/ok/array-bounds.wasm-run.ok b/test/run/ok/array-bounds.wasm-run.ok index 943ff8632a4..d2c3f9c6bb0 100644 --- a/test/run/ok/array-bounds.wasm-run.ok +++ b/test/run/ok/array-bounds.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/array-bounds.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/run/ok/assertFalse.wasm-run.ok b/test/run/ok/assertFalse.wasm-run.ok index 6e98ff9615e..b5ec0369a16 100644 --- a/test/run/ok/assertFalse.wasm-run.ok +++ b/test/run/ok/assertFalse.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/assertFalse.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/run/ok/char-high-surrogate-trap.wasm-run.ok b/test/run/ok/char-high-surrogate-trap.wasm-run.ok index 972c78476b8..1b908ca9606 100644 --- a/test/run/ok/char-high-surrogate-trap.wasm-run.ok +++ b/test/run/ok/char-high-surrogate-trap.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/char-high-surrogate-trap.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/run/ok/char-low-surrogate-trap.wasm-run.ok b/test/run/ok/char-low-surrogate-trap.wasm-run.ok index 0d0f8a91520..f4b509fcd4f 100644 --- a/test/run/ok/char-low-surrogate-trap.wasm-run.ok +++ b/test/run/ok/char-low-surrogate-trap.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/char-low-surrogate-trap.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/run/ok/char-trap.wasm-run.ok b/test/run/ok/char-trap.wasm-run.ok index 29f16842009..5ba0b5269d2 100644 --- a/test/run/ok/char-trap.wasm-run.ok +++ b/test/run/ok/char-trap.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/char-trap.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/run/ok/issue36.wasm-run.ok b/test/run/ok/issue36.wasm-run.ok index 445adce17bc..eb44a3c30de 100644 --- a/test/run/ok/issue36.wasm-run.ok +++ b/test/run/ok/issue36.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/issue36.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/run/ok/overflow.wasm-run.ok b/test/run/ok/overflow.wasm-run.ok index 8ef1d926e00..d7211f6845c 100644 --- a/test/run/ok/overflow.wasm-run.ok +++ b/test/run/ok/overflow.wasm-run.ok @@ -3,4 +3,3 @@ Error: failed to process main module `_out/overflow.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: integer divide by zero, source location: @___: - diff --git a/test/trap/ok/addInt16-lower.wasm-run.ok b/test/trap/ok/addInt16-lower.wasm-run.ok index 66f5dd7070f..0861ba0549d 100644 --- a/test/trap/ok/addInt16-lower.wasm-run.ok +++ b/test/trap/ok/addInt16-lower.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/addInt16-lower.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/addInt16-upper.wasm-run.ok b/test/trap/ok/addInt16-upper.wasm-run.ok index 81472dc98e6..cd784351a49 100644 --- a/test/trap/ok/addInt16-upper.wasm-run.ok +++ b/test/trap/ok/addInt16-upper.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/addInt16-upper.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/addInt32-lower.wasm-run.ok b/test/trap/ok/addInt32-lower.wasm-run.ok index cd7e4fbd4f8..afbed682f3d 100644 --- a/test/trap/ok/addInt32-lower.wasm-run.ok +++ b/test/trap/ok/addInt32-lower.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/addInt32-lower.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/addInt32-upper.wasm-run.ok b/test/trap/ok/addInt32-upper.wasm-run.ok index a9762336fc4..5e5959f29f1 100644 --- a/test/trap/ok/addInt32-upper.wasm-run.ok +++ b/test/trap/ok/addInt32-upper.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/addInt32-upper.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/addInt64-lower.wasm-run.ok b/test/trap/ok/addInt64-lower.wasm-run.ok index 4f7d61c40c1..017b0b16a2b 100644 --- a/test/trap/ok/addInt64-lower.wasm-run.ok +++ b/test/trap/ok/addInt64-lower.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/addInt64-lower.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/addInt64-upper.wasm-run.ok b/test/trap/ok/addInt64-upper.wasm-run.ok index c7b874379e6..e04749d8a0a 100644 --- a/test/trap/ok/addInt64-upper.wasm-run.ok +++ b/test/trap/ok/addInt64-upper.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/addInt64-upper.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/addInt8-lower.wasm-run.ok b/test/trap/ok/addInt8-lower.wasm-run.ok index 5c7f24a3211..2421b36d2e5 100644 --- a/test/trap/ok/addInt8-lower.wasm-run.ok +++ b/test/trap/ok/addInt8-lower.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/addInt8-lower.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/addInt8-upper.wasm-run.ok b/test/trap/ok/addInt8-upper.wasm-run.ok index 227c8e7e58e..2261e57658d 100644 --- a/test/trap/ok/addInt8-upper.wasm-run.ok +++ b/test/trap/ok/addInt8-upper.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/addInt8-upper.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/addNat16.wasm-run.ok b/test/trap/ok/addNat16.wasm-run.ok index 3bf65cf51be..4b6b91e1352 100644 --- a/test/trap/ok/addNat16.wasm-run.ok +++ b/test/trap/ok/addNat16.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/addNat16.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/addNat32.wasm-run.ok b/test/trap/ok/addNat32.wasm-run.ok index 5b0915d0018..dfb0c06c275 100644 --- a/test/trap/ok/addNat32.wasm-run.ok +++ b/test/trap/ok/addNat32.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/addNat32.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/addNat64.wasm-run.ok b/test/trap/ok/addNat64.wasm-run.ok index 314b6a5d3b7..89ec7b62c09 100644 --- a/test/trap/ok/addNat64.wasm-run.ok +++ b/test/trap/ok/addNat64.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/addNat64.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/addNat8.wasm-run.ok b/test/trap/ok/addNat8.wasm-run.ok index ba41678f4e8..13e29034703 100644 --- a/test/trap/ok/addNat8.wasm-run.ok +++ b/test/trap/ok/addNat8.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/addNat8.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/divInt16.wasm-run.ok b/test/trap/ok/divInt16.wasm-run.ok index 5876e2b0c3d..6fec54566f9 100644 --- a/test/trap/ok/divInt16.wasm-run.ok +++ b/test/trap/ok/divInt16.wasm-run.ok @@ -3,4 +3,3 @@ Error: failed to process main module `_out/divInt16.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/divInt32.wasm-run.ok b/test/trap/ok/divInt32.wasm-run.ok index 00be4caef22..beff237fe9b 100644 --- a/test/trap/ok/divInt32.wasm-run.ok +++ b/test/trap/ok/divInt32.wasm-run.ok @@ -3,4 +3,3 @@ Error: failed to process main module `_out/divInt32.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: integer overflow, source location: @___: - diff --git a/test/trap/ok/divInt64.wasm-run.ok b/test/trap/ok/divInt64.wasm-run.ok index 340edc6b0f4..ae6b293988a 100644 --- a/test/trap/ok/divInt64.wasm-run.ok +++ b/test/trap/ok/divInt64.wasm-run.ok @@ -3,4 +3,3 @@ Error: failed to process main module `_out/divInt64.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: integer overflow, source location: @___: - diff --git a/test/trap/ok/divInt8.wasm-run.ok b/test/trap/ok/divInt8.wasm-run.ok index 6ea2a31d06a..0adadab621f 100644 --- a/test/trap/ok/divInt8.wasm-run.ok +++ b/test/trap/ok/divInt8.wasm-run.ok @@ -3,4 +3,3 @@ Error: failed to process main module `_out/divInt8.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/mulInt16-lower.wasm-run.ok b/test/trap/ok/mulInt16-lower.wasm-run.ok index 6e55364e9ab..4d870eb01e3 100644 --- a/test/trap/ok/mulInt16-lower.wasm-run.ok +++ b/test/trap/ok/mulInt16-lower.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/mulInt16-lower.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/mulInt16-upper.wasm-run.ok b/test/trap/ok/mulInt16-upper.wasm-run.ok index c02d0722720..7929c4c5353 100644 --- a/test/trap/ok/mulInt16-upper.wasm-run.ok +++ b/test/trap/ok/mulInt16-upper.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/mulInt16-upper.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/mulInt32-lower.wasm-run.ok b/test/trap/ok/mulInt32-lower.wasm-run.ok index dbff0ee6f35..5bf40b5a9bb 100644 --- a/test/trap/ok/mulInt32-lower.wasm-run.ok +++ b/test/trap/ok/mulInt32-lower.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/mulInt32-lower.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/mulInt32-upper.wasm-run.ok b/test/trap/ok/mulInt32-upper.wasm-run.ok index 8b8ba7b5a2f..e627505a1d3 100644 --- a/test/trap/ok/mulInt32-upper.wasm-run.ok +++ b/test/trap/ok/mulInt32-upper.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/mulInt32-upper.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/mulInt64-lower.wasm-run.ok b/test/trap/ok/mulInt64-lower.wasm-run.ok index ab1ef3a5bb0..45ad51624fb 100644 --- a/test/trap/ok/mulInt64-lower.wasm-run.ok +++ b/test/trap/ok/mulInt64-lower.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/mulInt64-lower.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/mulInt64-upper.wasm-run.ok b/test/trap/ok/mulInt64-upper.wasm-run.ok index 872febf92eb..2d366e7cb8c 100644 --- a/test/trap/ok/mulInt64-upper.wasm-run.ok +++ b/test/trap/ok/mulInt64-upper.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/mulInt64-upper.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/mulInt8-lower.wasm-run.ok b/test/trap/ok/mulInt8-lower.wasm-run.ok index 3ec6c499100..394fa8efa7e 100644 --- a/test/trap/ok/mulInt8-lower.wasm-run.ok +++ b/test/trap/ok/mulInt8-lower.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/mulInt8-lower.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/mulInt8-upper.wasm-run.ok b/test/trap/ok/mulInt8-upper.wasm-run.ok index 2b9d0f59008..e777a5ce464 100644 --- a/test/trap/ok/mulInt8-upper.wasm-run.ok +++ b/test/trap/ok/mulInt8-upper.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/mulInt8-upper.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/mulNat16.wasm-run.ok b/test/trap/ok/mulNat16.wasm-run.ok index c747f9ed52b..95a5e3afb3d 100644 --- a/test/trap/ok/mulNat16.wasm-run.ok +++ b/test/trap/ok/mulNat16.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/mulNat16.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/mulNat32.wasm-run.ok b/test/trap/ok/mulNat32.wasm-run.ok index f1597b57be5..4e34afa3076 100644 --- a/test/trap/ok/mulNat32.wasm-run.ok +++ b/test/trap/ok/mulNat32.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/mulNat32.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/mulNat64.wasm-run.ok b/test/trap/ok/mulNat64.wasm-run.ok index 321ddaac2a9..e9357ac3bb0 100644 --- a/test/trap/ok/mulNat64.wasm-run.ok +++ b/test/trap/ok/mulNat64.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/mulNat64.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/mulNat8.wasm-run.ok b/test/trap/ok/mulNat8.wasm-run.ok index ec4a78110b2..02865757ab2 100644 --- a/test/trap/ok/mulNat8.wasm-run.ok +++ b/test/trap/ok/mulNat8.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/mulNat8.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/outrange-int16-lower.wasm-run.ok b/test/trap/ok/outrange-int16-lower.wasm-run.ok index 7d213d546ff..01e790b7f92 100644 --- a/test/trap/ok/outrange-int16-lower.wasm-run.ok +++ b/test/trap/ok/outrange-int16-lower.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/outrange-int16-lower.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/outrange-int16-negation.wasm-run.ok b/test/trap/ok/outrange-int16-negation.wasm-run.ok index 9b283bc29b3..d1ab931d0cb 100644 --- a/test/trap/ok/outrange-int16-negation.wasm-run.ok +++ b/test/trap/ok/outrange-int16-negation.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/outrange-int16-negation.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/outrange-int16-upper.wasm-run.ok b/test/trap/ok/outrange-int16-upper.wasm-run.ok index faa0f23873e..4ed09dfc005 100644 --- a/test/trap/ok/outrange-int16-upper.wasm-run.ok +++ b/test/trap/ok/outrange-int16-upper.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/outrange-int16-upper.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/outrange-int32-lower.wasm-run.ok b/test/trap/ok/outrange-int32-lower.wasm-run.ok index 660d4c55346..fa6faaae4e3 100644 --- a/test/trap/ok/outrange-int32-lower.wasm-run.ok +++ b/test/trap/ok/outrange-int32-lower.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/outrange-int32-lower.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/outrange-int32-negation.wasm-run.ok b/test/trap/ok/outrange-int32-negation.wasm-run.ok index 172647b70c6..47f5a81a7c1 100644 --- a/test/trap/ok/outrange-int32-negation.wasm-run.ok +++ b/test/trap/ok/outrange-int32-negation.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/outrange-int32-negation.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/outrange-int32-upper.wasm-run.ok b/test/trap/ok/outrange-int32-upper.wasm-run.ok index db07dd973c3..f464866e48f 100644 --- a/test/trap/ok/outrange-int32-upper.wasm-run.ok +++ b/test/trap/ok/outrange-int32-upper.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/outrange-int32-upper.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/outrange-int64-lower.wasm-run.ok b/test/trap/ok/outrange-int64-lower.wasm-run.ok index d98ac51337c..9494106f158 100644 --- a/test/trap/ok/outrange-int64-lower.wasm-run.ok +++ b/test/trap/ok/outrange-int64-lower.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/outrange-int64-lower.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/outrange-int64-negation.wasm-run.ok b/test/trap/ok/outrange-int64-negation.wasm-run.ok index efe18ad0a40..1822a52cfed 100644 --- a/test/trap/ok/outrange-int64-negation.wasm-run.ok +++ b/test/trap/ok/outrange-int64-negation.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/outrange-int64-negation.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/outrange-int64-upper.wasm-run.ok b/test/trap/ok/outrange-int64-upper.wasm-run.ok index 5829cc9b2ee..8e4893c80c4 100644 --- a/test/trap/ok/outrange-int64-upper.wasm-run.ok +++ b/test/trap/ok/outrange-int64-upper.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/outrange-int64-upper.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/outrange-int8-lower.wasm-run.ok b/test/trap/ok/outrange-int8-lower.wasm-run.ok index 797ec799d07..ab1a1063eac 100644 --- a/test/trap/ok/outrange-int8-lower.wasm-run.ok +++ b/test/trap/ok/outrange-int8-lower.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/outrange-int8-lower.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/outrange-int8-negation.wasm-run.ok b/test/trap/ok/outrange-int8-negation.wasm-run.ok index 05b412f4453..acb832aeb41 100644 --- a/test/trap/ok/outrange-int8-negation.wasm-run.ok +++ b/test/trap/ok/outrange-int8-negation.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/outrange-int8-negation.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/outrange-int8-upper.wasm-run.ok b/test/trap/ok/outrange-int8-upper.wasm-run.ok index 5c141ce09a6..5f00b95e138 100644 --- a/test/trap/ok/outrange-int8-upper.wasm-run.ok +++ b/test/trap/ok/outrange-int8-upper.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/outrange-int8-upper.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/outrange-nat16.wasm-run.ok b/test/trap/ok/outrange-nat16.wasm-run.ok index 18dd920aed5..8274175224a 100644 --- a/test/trap/ok/outrange-nat16.wasm-run.ok +++ b/test/trap/ok/outrange-nat16.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/outrange-nat16.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/outrange-nat32.wasm-run.ok b/test/trap/ok/outrange-nat32.wasm-run.ok index 4fd28c74b8c..f809fd8f8ea 100644 --- a/test/trap/ok/outrange-nat32.wasm-run.ok +++ b/test/trap/ok/outrange-nat32.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/outrange-nat32.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/outrange-nat64.wasm-run.ok b/test/trap/ok/outrange-nat64.wasm-run.ok index 3722f18faf1..c361b62f32c 100644 --- a/test/trap/ok/outrange-nat64.wasm-run.ok +++ b/test/trap/ok/outrange-nat64.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/outrange-nat64.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/outrange-nat8.wasm-run.ok b/test/trap/ok/outrange-nat8.wasm-run.ok index cadbc4eef86..7f1bc546bd4 100644 --- a/test/trap/ok/outrange-nat8.wasm-run.ok +++ b/test/trap/ok/outrange-nat8.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/outrange-nat8.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/powInt32-lower.wasm-run.ok b/test/trap/ok/powInt32-lower.wasm-run.ok index 226791f6cca..950ee3f2c54 100644 --- a/test/trap/ok/powInt32-lower.wasm-run.ok +++ b/test/trap/ok/powInt32-lower.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/powInt32-lower.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/powInt32-raise-neg.wasm-run.ok b/test/trap/ok/powInt32-raise-neg.wasm-run.ok index afc323030d3..229a242da15 100644 --- a/test/trap/ok/powInt32-raise-neg.wasm-run.ok +++ b/test/trap/ok/powInt32-raise-neg.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/powInt32-raise-neg.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/powInt32-upper.wasm-run.ok b/test/trap/ok/powInt32-upper.wasm-run.ok index b9417bd905f..4b0604d4283 100644 --- a/test/trap/ok/powInt32-upper.wasm-run.ok +++ b/test/trap/ok/powInt32-upper.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/powInt32-upper.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/powInt64-lower-fast.wasm-run.ok b/test/trap/ok/powInt64-lower-fast.wasm-run.ok index fb1c13ee042..5ee86da17ae 100644 --- a/test/trap/ok/powInt64-lower-fast.wasm-run.ok +++ b/test/trap/ok/powInt64-lower-fast.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/powInt64-lower-fast.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/powInt64-lower-slow.wasm-run.ok b/test/trap/ok/powInt64-lower-slow.wasm-run.ok index 85490c02c8b..c213797d99e 100644 --- a/test/trap/ok/powInt64-lower-slow.wasm-run.ok +++ b/test/trap/ok/powInt64-lower-slow.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/powInt64-lower-slow.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/powInt64-raise-neg.wasm-run.ok b/test/trap/ok/powInt64-raise-neg.wasm-run.ok index e232f0211e7..fc4e0b2be82 100644 --- a/test/trap/ok/powInt64-raise-neg.wasm-run.ok +++ b/test/trap/ok/powInt64-raise-neg.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/powInt64-raise-neg.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/powInt64-upper-fast.wasm-run.ok b/test/trap/ok/powInt64-upper-fast.wasm-run.ok index b8c1d2707f9..0c019930f43 100644 --- a/test/trap/ok/powInt64-upper-fast.wasm-run.ok +++ b/test/trap/ok/powInt64-upper-fast.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/powInt64-upper-fast.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/powInt64-upper-slow.wasm-run.ok b/test/trap/ok/powInt64-upper-slow.wasm-run.ok index edfd23fafb7..d42e5839bca 100644 --- a/test/trap/ok/powInt64-upper-slow.wasm-run.ok +++ b/test/trap/ok/powInt64-upper-slow.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/powInt64-upper-slow.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/powInt8-lower.wasm-run.ok b/test/trap/ok/powInt8-lower.wasm-run.ok index 0d2d17b9853..dcad5ad7ade 100644 --- a/test/trap/ok/powInt8-lower.wasm-run.ok +++ b/test/trap/ok/powInt8-lower.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/powInt8-lower.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/powInt8-raise-neg.wasm-run.ok b/test/trap/ok/powInt8-raise-neg.wasm-run.ok index 00ac4b9efc9..5d4001af7b6 100644 --- a/test/trap/ok/powInt8-raise-neg.wasm-run.ok +++ b/test/trap/ok/powInt8-raise-neg.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/powInt8-raise-neg.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/powInt8-upper.wasm-run.ok b/test/trap/ok/powInt8-upper.wasm-run.ok index 90937a6e45b..8045842272d 100644 --- a/test/trap/ok/powInt8-upper.wasm-run.ok +++ b/test/trap/ok/powInt8-upper.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/powInt8-upper.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/powNat16.wasm-run.ok b/test/trap/ok/powNat16.wasm-run.ok index 1125671217f..9a958fba0a5 100644 --- a/test/trap/ok/powNat16.wasm-run.ok +++ b/test/trap/ok/powNat16.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/powNat16.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/powNat32.wasm-run.ok b/test/trap/ok/powNat32.wasm-run.ok index a0f41f7fa06..c662b7a9a02 100644 --- a/test/trap/ok/powNat32.wasm-run.ok +++ b/test/trap/ok/powNat32.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/powNat32.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/powNat64.wasm-run.ok b/test/trap/ok/powNat64.wasm-run.ok index 2312bf471c7..17ad0b59e55 100644 --- a/test/trap/ok/powNat64.wasm-run.ok +++ b/test/trap/ok/powNat64.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/powNat64.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/powNat8.wasm-run.ok b/test/trap/ok/powNat8.wasm-run.ok index 478841e9cd6..326f59cbe66 100644 --- a/test/trap/ok/powNat8.wasm-run.ok +++ b/test/trap/ok/powNat8.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/powNat8.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/subInt16-lower.wasm-run.ok b/test/trap/ok/subInt16-lower.wasm-run.ok index 10f94d0bb9f..aaf1c494570 100644 --- a/test/trap/ok/subInt16-lower.wasm-run.ok +++ b/test/trap/ok/subInt16-lower.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/subInt16-lower.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/subInt16-upper.wasm-run.ok b/test/trap/ok/subInt16-upper.wasm-run.ok index d6dee45676d..1adfa940c86 100644 --- a/test/trap/ok/subInt16-upper.wasm-run.ok +++ b/test/trap/ok/subInt16-upper.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/subInt16-upper.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/subInt32-lower.wasm-run.ok b/test/trap/ok/subInt32-lower.wasm-run.ok index 9745a378cda..43c99d8af14 100644 --- a/test/trap/ok/subInt32-lower.wasm-run.ok +++ b/test/trap/ok/subInt32-lower.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/subInt32-lower.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/subInt32-upper.wasm-run.ok b/test/trap/ok/subInt32-upper.wasm-run.ok index 367bb8caa3c..426e3225ddf 100644 --- a/test/trap/ok/subInt32-upper.wasm-run.ok +++ b/test/trap/ok/subInt32-upper.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/subInt32-upper.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/subInt64-lower.wasm-run.ok b/test/trap/ok/subInt64-lower.wasm-run.ok index e18a4ca4d22..dea5839b540 100644 --- a/test/trap/ok/subInt64-lower.wasm-run.ok +++ b/test/trap/ok/subInt64-lower.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/subInt64-lower.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/subInt64-upper.wasm-run.ok b/test/trap/ok/subInt64-upper.wasm-run.ok index 49cf86c7fe0..129ba24de8f 100644 --- a/test/trap/ok/subInt64-upper.wasm-run.ok +++ b/test/trap/ok/subInt64-upper.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/subInt64-upper.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/subInt8-lower.wasm-run.ok b/test/trap/ok/subInt8-lower.wasm-run.ok index d739b3a12b3..828c1d14eaf 100644 --- a/test/trap/ok/subInt8-lower.wasm-run.ok +++ b/test/trap/ok/subInt8-lower.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/subInt8-lower.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/subInt8-upper.wasm-run.ok b/test/trap/ok/subInt8-upper.wasm-run.ok index 001d37b54b2..3df85352e54 100644 --- a/test/trap/ok/subInt8-upper.wasm-run.ok +++ b/test/trap/ok/subInt8-upper.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/subInt8-upper.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/subNat16.wasm-run.ok b/test/trap/ok/subNat16.wasm-run.ok index 519021fd938..b6b403f9d99 100644 --- a/test/trap/ok/subNat16.wasm-run.ok +++ b/test/trap/ok/subNat16.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/subNat16.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/subNat32.wasm-run.ok b/test/trap/ok/subNat32.wasm-run.ok index 1a07c6b8b01..68b69f2bd01 100644 --- a/test/trap/ok/subNat32.wasm-run.ok +++ b/test/trap/ok/subNat32.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/subNat32.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/subNat64-slow.wasm-run.ok b/test/trap/ok/subNat64-slow.wasm-run.ok index 89836cdf57c..b6e13796f7d 100644 --- a/test/trap/ok/subNat64-slow.wasm-run.ok +++ b/test/trap/ok/subNat64-slow.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/subNat64-slow.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/subNat64.wasm-run.ok b/test/trap/ok/subNat64.wasm-run.ok index 5c30141a3cc..f4ebe380a90 100644 --- a/test/trap/ok/subNat64.wasm-run.ok +++ b/test/trap/ok/subNat64.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/subNat64.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - diff --git a/test/trap/ok/subNat8.wasm-run.ok b/test/trap/ok/subNat8.wasm-run.ok index 7f0bcec3b56..9baba70538c 100644 --- a/test/trap/ok/subNat8.wasm-run.ok +++ b/test/trap/ok/subNat8.wasm-run.ok @@ -5,4 +5,3 @@ Error: failed to process main module `_out/subNat8.wasm` Caused by: 0: Instantiation failed during setup 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: - From 177203b3388a1720cdd492ebe009f0e3b87a788c Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Tue, 7 Jan 2020 18:40:05 +0100 Subject: [PATCH 0880/1176] request the cranelift engine for wasmtime (#1076) --- test/run.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/run.sh b/test/run.sh index 99bd0e132a0..150a91a8fa0 100755 --- a/test/run.sh +++ b/test/run.sh @@ -29,6 +29,7 @@ MO_LD=${MO_LD:-$(realpath $(dirname $0)/../src/mo-ld)} DIDC=${DIDC:-$(realpath $(dirname $0)/../src/didc)} export MO_LD WASMTIME=${WASMTIME:-wasmtime} +WASMTIME_OPTIONS="--disable-cache --cranelift" DRUN_WRAPPER=$(realpath $(dirname $0)/drun-wrapper.sh) IC_STUB_RUN=${IC_STUB_RUN:-ic-stub-run} SKIP_RUNNING=${SKIP_RUNNING:-no} @@ -295,7 +296,7 @@ do then run_if wasm drun-run $DRUN_WRAPPER $out/$base.wasm $mangled else - run_if wasm wasm-run $WASMTIME --disable-cache $out/$base.wasm + run_if wasm wasm-run $WASMTIME $WASMTIME_OPTIONS $out/$base.wasm fi fi From df395c438746370324c7bb2815e1b6a4f88fd179 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Tue, 7 Jan 2020 14:02:33 -0700 Subject: [PATCH 0881/1176] fix test bug; fix another bug; rename class and module --- stdlib/{hashtbl.mo => hashMap.mo} | 34 +++++++++++++---------- stdlib/{hashtblTest.mo => hashMapTest.mo} | 26 +++++++++++++++-- 2 files changed, 43 insertions(+), 17 deletions(-) rename stdlib/{hashtbl.mo => hashMap.mo} (86%) rename stdlib/{hashtblTest.mo => hashMapTest.mo} (78%) diff --git a/stdlib/hashtbl.mo b/stdlib/hashMap.mo similarity index 86% rename from stdlib/hashtbl.mo rename to stdlib/hashMap.mo index 93852bd2d5c..d554c9564a3 100644 --- a/stdlib/hashtbl.mo +++ b/stdlib/hashMap.mo @@ -26,7 +26,7 @@ Internally, table growth policy is very simple, for now: // key-val list type type KVs = AssocList.AssocList; -public class Hashtbl ( +public class HashMap ( initCapacity: Nat, keyEq: (K,K) -> Bool, keyHash: K -> Hash.Hash) { @@ -67,8 +67,12 @@ public class Hashtbl ( if (_count >= table.len()) { let size = if (_count == 0) - initCapacity - else table.len() * 2; + if (initCapacity > 0) + initCapacity + else + 1 + else + table.len() * 2; let table2 = Array_init>(size, null); for (i in table.keys()) { var kvs = table[i]; @@ -131,10 +135,10 @@ public class Hashtbl ( // clone cannot be an efficient object method, // ...but is still useful in tests, and beyond. public func clone - (h:Hashtbl, + (h:HashMap, keyEq: (K,K) -> Bool, - keyHash: K -> Hash.Hash) : Hashtbl { - let h2 = Hashtbl(h.count(), keyEq, keyHash); + keyHash: K -> Hash.Hash) : HashMap { + let h2 = HashMap(h.count(), keyEq, keyHash); for ((k,v) in h.iter()) { ignore h2.set(k,v); }; @@ -145,21 +149,21 @@ public func clone public func fromIter(iter:Iter<(K, V)>, initCapacity: Nat, keyEq: (K,K) -> Bool, - keyHash: K -> Hash.Hash) : Hashtbl { - let h = Hashtbl(initCapacity, keyEq, keyHash); - for ((k,v) in h.iter()) { + keyHash: K -> Hash.Hash) : HashMap { + let h = HashMap(initCapacity, keyEq, keyHash); + for ((k,v) in iter) { ignore h.set(k,v); }; h }; public func map - (h:Hashtbl, + (h:HashMap, keyEq: (K,K) -> Bool, keyHash: K -> Hash.Hash, mapFn: (K, V1) -> V2, - ) : Hashtbl { - let h2 = Hashtbl(h.count(), keyEq, keyHash); + ) : HashMap { + let h2 = HashMap(h.count(), keyEq, keyHash); for ((k, v1) in h.iter()) { let v2 = mapFn(k, v1); ignore h2.set(k,v2); @@ -168,12 +172,12 @@ public func map }; public func mapFilter - (h:Hashtbl, + (h:HashMap, keyEq: (K,K) -> Bool, keyHash: K -> Hash.Hash, mapFn: (K, V1) -> ?V2, - ) : Hashtbl { - let h2 = Hashtbl(h.count(), keyEq, keyHash); + ) : HashMap { + let h2 = HashMap(h.count(), keyEq, keyHash); for ((k, v1) in h.iter()) { switch (mapFn(k, v1)) { case null { }; diff --git a/stdlib/hashtblTest.mo b/stdlib/hashMapTest.mo similarity index 78% rename from stdlib/hashtblTest.mo rename to stdlib/hashMapTest.mo index a433c19bcda..11541e5aaa4 100644 --- a/stdlib/hashtblTest.mo +++ b/stdlib/hashMapTest.mo @@ -1,10 +1,10 @@ -import H "hashtbl.mo"; +import H "hashMap.mo"; import Hash "hash.mo"; func textIsEq(x:Text,y:Text):Bool { x == y }; debug { - let a = H.Hashtbl(3, textIsEq, Hash.Hash.hashOfText); + let a = H.HashMap(3, textIsEq, Hash.Hash.hashOfText); ignore a.set("apple", 1); ignore a.set("banana", 2); @@ -88,4 +88,26 @@ debug { }; }; + + // test fromIter method + let c = H.fromIter(b.iter(), 0, textIsEq, Hash.Hash.hashOfText); + + // c agrees with each entry of b + for ((k,v) in b.iter()) { + debugPrint(debug_show (k,v)); + switch (c.get(k)) { + case null { assert false }; + case (?w) { assert v == w }; + }; + }; + + // b agrees with each entry of c + for ((k,v) in c.iter()) { + debugPrint(debug_show (k,v)); + switch (b.get(k)) { + case null { assert false }; + case (?w) { assert v == w }; + }; + }; + }; From 9f94a5f657fc14cda2ef592884bc7406025d93f8 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Tue, 7 Jan 2020 14:23:09 -0700 Subject: [PATCH 0882/1176] fix makefile --- stdlib/Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stdlib/Makefile b/stdlib/Makefile index 8c443dfe129..934e1dcc506 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -24,8 +24,8 @@ TESTS=\ Function \ FunctionTest \ Hash \ - Hashtbl \ - HashtblTest \ + HashMap \ + HashMapTest \ Int \ IntTest \ Iter \ @@ -83,10 +83,10 @@ $(OUTDIR)/Buf.out: buf.mo | $(OUTDIR) $(OUTDIR)/BufTest.out: bufTest.mo | $(OUTDIR) $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ -$(OUTDIR)/HashtblTest.out: hashtblTest.mo | $(OUTDIR) +$(OUTDIR)/HashMapTest.out: hashMapTest.mo | $(OUTDIR) $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ -$(OUTDIR)/Hashtbl.out: hashtbl.mo | $(OUTDIR) +$(OUTDIR)/HashMap.out: HashMap.mo | $(OUTDIR) $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ $(OUTDIR)/Function.out: function.mo | $(OUTDIR) From 43fe4b068e59615d5b60255a3e9b37023d1d3c6e Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Tue, 7 Jan 2020 14:27:00 -0700 Subject: [PATCH 0883/1176] typo --- stdlib/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/Makefile b/stdlib/Makefile index 934e1dcc506..74b48a43a8f 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -86,7 +86,7 @@ $(OUTDIR)/BufTest.out: bufTest.mo | $(OUTDIR) $(OUTDIR)/HashMapTest.out: hashMapTest.mo | $(OUTDIR) $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ -$(OUTDIR)/HashMap.out: HashMap.mo | $(OUTDIR) +$(OUTDIR)/HashMap.out: hashMap.mo | $(OUTDIR) $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ $(OUTDIR)/Function.out: function.mo | $(OUTDIR) From e6ef5b59a836b523f794c39d8ed994eec76e9262 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Tue, 7 Jan 2020 14:34:05 -0700 Subject: [PATCH 0884/1176] nits to comments' doc --- stdlib/hashMap.mo | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stdlib/hashMap.mo b/stdlib/hashMap.mo index d554c9564a3..81523994a64 100644 --- a/stdlib/hashMap.mo +++ b/stdlib/hashMap.mo @@ -6,12 +6,12 @@ module { /** -Hash tables -=============== +Hash Map (aka Hash table) +========================= -This module defines imperative hash tables, with general key and value types. +This module defines an imperative hash map (hash table), with a general key and value type. -It has a minimal object-oriented interface: get, set, remove, count and iter. +It has a minimal object-oriented interface: get, set, del, count and iter. The class is parameterized by the key's equality and hash functions, and an initial capacity. However, as with `Buf`, no array allocation From 748a6c937ca2f8d1756f56606f495322a7f443c6 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Wed, 8 Jan 2020 11:09:53 +0100 Subject: [PATCH 0885/1176] Get stock wasmtime - nixpkgs master (#1077) * bump nixpkgs to get stock wasmtime * clean up --- default.nix | 2 - nix/nixpkgs.nix | 4 +- nix/wasmtime/cargo-lock.patch | 2282 --------------------------------- nix/wasmtime/default.nix | 31 - 4 files changed, 2 insertions(+), 2317 deletions(-) delete mode 100644 nix/wasmtime/cargo-lock.patch delete mode 100644 nix/wasmtime/default.nix diff --git a/default.nix b/default.nix index 453572afa4c..2dfacd6c91a 100644 --- a/default.nix +++ b/default.nix @@ -6,8 +6,6 @@ let nixpkgs = (import ./nix/nixpkgs.nix).nixpkgs { inherit system; overlays = [ - # Adding wasmtime - (self: super: { wasmtime = self.callPackage ./nix/wasmtime {}; }) # Selecting the ocaml version (self: super: { ocamlPackages = self.ocaml-ng.ocamlPackages_4_07; }) # Additional ocaml package diff --git a/nix/nixpkgs.nix b/nix/nixpkgs.nix index 18edb15f256..9b3e2158e19 100644 --- a/nix/nixpkgs.nix +++ b/nix/nixpkgs.nix @@ -1,8 +1,8 @@ rec { - rev = "96c9578020133fe64feab90c00f3cb880d53ad0d"; + rev = "82875a20ba444110396f95537b18247898e40e22"; src = builtins.fetchTarball { - sha256 = "03rn7gn8r129a8cj527nhs7k28ibzwqw083iirwvas2x4k9mir9z"; + sha256 = "1xy2zn3hkcv66ddvscr3l32jcx1qg9h14zvhmy5zf0pcfb8gn42i"; url = "https://github.com/NixOS/nixpkgs/archive/${rev}.tar.gz"; }; diff --git a/nix/wasmtime/cargo-lock.patch b/nix/wasmtime/cargo-lock.patch deleted file mode 100644 index 3ce3f765988..00000000000 --- a/nix/wasmtime/cargo-lock.patch +++ /dev/null @@ -1,2282 +0,0 @@ -diff --git a/Cargo.lock b/Cargo.lock -new file mode 100644 -index 00000000..818de492 ---- /dev/null -+++ b/Cargo.lock -@@ -0,0 +1,2276 @@ -+# This file is automatically @generated by Cargo. -+# It is not intended for manual editing. -+[[package]] -+name = "aho-corasick" -+version = "0.7.6" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "ansi_term" -+version = "0.11.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "anyhow" -+version = "1.0.26" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "arrayref" -+version = "0.3.5" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "arrayvec" -+version = "0.4.12" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "arrayvec" -+version = "0.5.1" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "atty" -+version = "0.2.14" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "hermit-abi 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "autocfg" -+version = "0.1.7" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "backtrace" -+version = "0.3.40" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -+ "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "backtrace-sys" -+version = "0.1.32" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "cc 1.0.49 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "base64" -+version = "0.10.1" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "base64" -+version = "0.11.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "bincode" -+version = "1.2.1" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "bindgen" -+version = "0.51.1" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cexpr 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", -+ "clang-sys 0.28.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", -+ "peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", -+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "which 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "bitflags" -+version = "1.2.1" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "blake2b_simd" -+version = "0.5.10" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", -+ "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "block-buffer" -+version = "0.7.3" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -+ "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "block-padding" -+version = "0.1.5" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "byte-tools" -+version = "0.3.1" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "byteorder" -+version = "1.3.2" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "c2-chacha" -+version = "0.2.3" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "capstone" -+version = "0.6.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "capstone-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "capstone-sys" -+version = "0.10.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "cc 1.0.49 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "cc" -+version = "1.0.49" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "jobserver 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", -+ "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "cexpr" -+version = "0.3.6" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "cfg-if" -+version = "0.1.10" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "chrono" -+version = "0.4.10" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", -+ "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", -+ "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "clang-sys" -+version = "0.28.1" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libloading 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "clap" -+version = "2.33.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", -+ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -+ "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "cloudabi" -+version = "0.0.3" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "cmake" -+version = "0.1.42" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "cc 1.0.49 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "constant_time_eq" -+version = "0.1.4" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "cpu-time" -+version = "1.0.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "cranelift-bforest" -+version = "0.50.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "cranelift-codegen" -+version = "0.50.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-bforest 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-codegen-meta 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-codegen-shared 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", -+ "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", -+ "smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "cranelift-codegen-meta" -+version = "0.50.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "cranelift-codegen-shared 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "cranelift-codegen-shared" -+version = "0.50.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "cranelift-entity" -+version = "0.50.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "cranelift-frontend" -+version = "0.50.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", -+ "smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "cranelift-native" -+version = "0.50.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "raw-cpuid 7.0.3 (registry+https://github.com/rust-lang/crates.io-index)", -+ "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "cranelift-wasm" -+version = "0.50.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-frontend 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", -+ "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", -+ "thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasmparser 0.39.3 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "crossbeam-deque" -+version = "0.7.2" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "crossbeam-epoch" -+version = "0.8.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", -+ "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", -+ "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "crossbeam-queue" -+version = "0.2.1" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", -+ "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "crossbeam-utils" -+version = "0.6.6" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", -+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "crossbeam-utils" -+version = "0.7.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", -+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "ctor" -+version = "0.1.12" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "cvt" -+version = "0.1.1" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "digest" -+version = "0.8.1" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "directories" -+version = "2.0.2" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", -+ "dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "dirs-sys" -+version = "0.3.4" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -+ "redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "docopt" -+version = "1.1.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", -+ "strsim 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "dynasm" -+version = "0.5.2" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", -+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "dynasmrt" -+version = "0.5.2" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "either" -+version = "1.5.3" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "env_logger" -+version = "0.6.2" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", -+ "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", -+ "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "errno" -+version = "0.2.4" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "errno-dragonfly" -+version = "0.1.1" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "faerie" -+version = "0.13.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", -+ "goblin 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -+ "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", -+ "scroll 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "string-interner 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "failure" -+version = "0.1.6" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", -+ "failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "failure_derive" -+version = "0.1.6" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", -+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", -+ "synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "fake-simd" -+version = "0.1.2" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "fallible-iterator" -+version = "0.2.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "file-per-thread-logger" -+version = "0.1.2" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "filetime" -+version = "0.2.8" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -+ "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", -+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "fuchsia-cprng" -+version = "0.1.1" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "gcc" -+version = "0.3.55" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "generic-array" -+version = "0.12.3" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "getrandom" -+version = "0.1.13" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "ghost" -+version = "0.1.1" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", -+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "gimli" -+version = "0.19.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", -+ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "fallible-iterator 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "glob" -+version = "0.3.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "goblin" -+version = "0.1.3" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", -+ "plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -+ "scroll 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "heck" -+version = "0.3.1" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "hermit-abi" -+version = "0.1.6" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "humantime" -+version = "1.3.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "quick-error 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "id-arena" -+version = "2.2.1" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "indexmap" -+version = "1.3.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "indoc" -+version = "0.3.4" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "indoc-impl 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", -+ "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "indoc-impl" -+version = "0.3.4" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", -+ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", -+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", -+ "unindent 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "inventory" -+version = "0.1.5" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "ctor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", -+ "ghost 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "inventory-impl 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "inventory-impl" -+version = "0.1.5" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", -+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "itertools" -+version = "0.8.2" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "itoa" -+version = "0.4.4" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "jobserver" -+version = "0.1.17" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -+ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "lazy_static" -+version = "1.4.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "leb128" -+version = "0.2.4" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "libc" -+version = "0.2.66" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "libloading" -+version = "0.5.2" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "cc 1.0.49 (registry+https://github.com/rust-lang/crates.io-index)", -+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "lightbeam" -+version = "0.8.0" -+dependencies = [ -+ "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", -+ "capstone 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "dynasm 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "dynasmrt 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", -+ "itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", -+ "more-asserts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "multi_mut 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -+ "quickcheck 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", -+ "typemap 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasmparser 0.39.3 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wat 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "log" -+version = "0.4.8" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "mach" -+version = "0.2.3" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "memchr" -+version = "2.2.1" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "memmap" -+version = "0.7.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "memoffset" -+version = "0.5.3" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "more-asserts" -+version = "0.2.1" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "multi_mut" -+version = "0.1.3" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "nix" -+version = "0.15.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cc 1.0.49 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -+ "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "nodrop" -+version = "0.1.14" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "nom" -+version = "4.2.3" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "num" -+version = "0.2.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "num-complex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -+ "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", -+ "num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", -+ "num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "num-complex" -+version = "0.2.3" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -+ "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "num-integer" -+version = "0.1.41" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -+ "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "num-iter" -+version = "0.1.39" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -+ "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", -+ "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "num-rational" -+version = "0.2.2" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -+ "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", -+ "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "num-traits" -+version = "0.2.10" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "num_cpus" -+version = "1.11.1" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "hermit-abi 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "opaque-debug" -+version = "0.2.3" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "os_pipe" -+version = "0.9.1" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "owning_ref" -+version = "0.4.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "paste" -+version = "0.1.6" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "paste-impl 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -+ "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "paste-impl" -+version = "0.1.6" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", -+ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", -+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "peeking_take_while" -+version = "0.1.2" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "plain" -+version = "0.2.3" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "ppv-lite86" -+version = "0.2.6" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "pretty_env_logger" -+version = "0.3.1" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", -+ "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "proc-macro-hack" -+version = "0.5.11" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", -+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "proc-macro2" -+version = "1.0.7" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "pyo3" -+version = "0.8.5" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "indoc 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", -+ "inventory 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -+ "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", -+ "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -+ "pyo3cls 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", -+ "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", -+ "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", -+ "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "unindent 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -+ "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "pyo3-derive-backend" -+version = "0.8.5" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", -+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "pyo3cls" -+version = "0.8.5" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", -+ "pyo3-derive-backend 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", -+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "quick-error" -+version = "1.2.3" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "quickcheck" -+version = "0.9.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", -+ "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "quote" -+version = "1.0.2" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "rand" -+version = "0.7.2" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -+ "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "rand_pcg 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "rand_chacha" -+version = "0.2.1" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -+ "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "rand_core" -+version = "0.3.1" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "rand_core" -+version = "0.4.2" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "rand_core" -+version = "0.5.1" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "rand_hc" -+version = "0.2.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "rand_os" -+version = "0.1.3" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", -+ "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -+ "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "rand_pcg" -+version = "0.2.1" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "raw-cpuid" -+version = "7.0.3" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cc 1.0.49 (registry+https://github.com/rust-lang/crates.io-index)", -+ "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "rayon" -+version = "1.3.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", -+ "rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "rayon-core" -+version = "1.7.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "rdrand" -+version = "0.4.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "redox_syscall" -+version = "0.1.56" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "redox_users" -+version = "0.3.1" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -+ "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -+ "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", -+ "rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "regex" -+version = "1.3.1" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", -+ "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", -+ "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "regex-syntax" -+version = "0.6.12" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "region" -+version = "2.1.2" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -+ "mach 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "remove_dir_all" -+version = "0.5.2" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "rust-argon2" -+version = "0.5.1" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "blake2b_simd 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", -+ "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "rustc-demangle" -+version = "0.1.16" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "rustc-hash" -+version = "1.0.1" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "rustc_version" -+version = "0.2.3" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "ryu" -+version = "1.0.2" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "scopeguard" -+version = "1.0.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "scroll" -+version = "0.10.1" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "scroll_derive 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "scroll_derive" -+version = "0.10.1" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", -+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "semver" -+version = "0.9.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "semver-parser" -+version = "0.7.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "serde" -+version = "1.0.104" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "serde_derive" -+version = "1.0.104" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", -+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "serde_json" -+version = "1.0.44" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", -+ "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "sha2" -+version = "0.8.1" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", -+ "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "shlex" -+version = "0.1.1" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "smallvec" -+version = "1.1.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "spin" -+version = "0.5.2" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "stable_deref_trait" -+version = "1.1.1" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "string-interner" -+version = "0.7.1" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "strsim" -+version = "0.8.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "strsim" -+version = "0.9.3" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "syn" -+version = "1.0.13" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", -+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "synstructure" -+version = "0.12.3" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", -+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", -+ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "target-lexicon" -+version = "0.9.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "tempfile" -+version = "3.1.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -+ "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", -+ "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "termcolor" -+version = "1.0.5" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "test-programs" -+version = "0.8.0" -+dependencies = [ -+ "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "os_pipe 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "pretty_env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasi-common 0.8.0", -+ "wasmtime 0.8.0", -+ "wasmtime-environ 0.8.0", -+ "wasmtime-jit 0.8.0", -+ "wasmtime-runtime 0.8.0", -+ "wasmtime-wasi 0.8.0", -+ "wat 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "textwrap" -+version = "0.11.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "thiserror" -+version = "1.0.9" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "thiserror-impl 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "thiserror-impl" -+version = "1.0.9" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", -+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "thread_local" -+version = "0.3.6" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "time" -+version = "0.1.42" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -+ "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", -+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "toml" -+version = "0.5.5" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "traitobject" -+version = "0.1.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "trybuild" -+version = "1.0.19" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", -+ "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", -+ "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", -+ "toml 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "typemap" -+version = "0.3.3" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "unsafe-any 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "typenum" -+version = "1.11.2" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "unicode-segmentation" -+version = "1.6.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "unicode-width" -+version = "0.1.7" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "unicode-xid" -+version = "0.2.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "unindent" -+version = "0.1.5" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "unsafe-any" -+version = "0.4.2" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "vec_map" -+version = "0.8.1" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "version_check" -+version = "0.1.5" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "version_check" -+version = "0.9.1" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "void" -+version = "1.0.2" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "walrus" -+version = "0.13.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", -+ "id-arena 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "leb128 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", -+ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", -+ "walrus-macro 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasmparser 0.39.3 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "walrus-macro" -+version = "0.13.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", -+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "wasi" -+version = "0.7.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "wasi-common" -+version = "0.8.0" -+dependencies = [ -+ "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cpu-time 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "filetime 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -+ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", -+ "nix 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasi-common-cbindgen 0.8.0", -+ "wig 0.8.0", -+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -+ "winx 0.8.0", -+] -+ -+[[package]] -+name = "wasi-common-cbindgen" -+version = "0.8.0" -+dependencies = [ -+ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", -+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", -+ "trybuild 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "wasm-webidl-bindings" -+version = "0.6.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", -+ "id-arena 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "leb128 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", -+ "walrus 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "wasmparser" -+version = "0.39.3" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "wasmtime" -+version = "0.8.0" -+dependencies = [ -+ "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-frontend 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-native 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-wasm 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "docopt 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "file-per-thread-logger 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "pretty_env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "region 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", -+ "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasi-common 0.8.0", -+ "wasmparser 0.39.3 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasmtime-environ 0.8.0", -+ "wasmtime-jit 0.8.0", -+ "wasmtime-runtime 0.8.0", -+ "wasmtime-wasi 0.8.0", -+ "wasmtime-wast 0.8.0", -+ "wat 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "wasmtime-cli" -+version = "0.8.0" -+dependencies = [ -+ "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-native 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-wasm 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "docopt 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "faerie 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "file-per-thread-logger 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -+ "more-asserts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "pretty_env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", -+ "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "test-programs 0.8.0", -+ "wasi-common 0.8.0", -+ "wasm-webidl-bindings 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasmtime 0.8.0", -+ "wasmtime-debug 0.8.0", -+ "wasmtime-environ 0.8.0", -+ "wasmtime-interface-types 0.8.0", -+ "wasmtime-jit 0.8.0", -+ "wasmtime-obj 0.8.0", -+ "wasmtime-runtime 0.8.0", -+ "wasmtime-wasi 0.8.0", -+ "wasmtime-wasi-c 0.8.0", -+ "wasmtime-wast 0.8.0", -+ "wat 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "wasmtime-debug" -+version = "0.8.0" -+dependencies = [ -+ "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-wasm 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "faerie 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "gimli 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "more-asserts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasmparser 0.39.3 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasmtime-environ 0.8.0", -+] -+ -+[[package]] -+name = "wasmtime-environ" -+version = "0.8.0" -+dependencies = [ -+ "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "bincode 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-wasm 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "directories 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", -+ "file-per-thread-logger 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "filetime 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -+ "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -+ "lightbeam 0.8.0", -+ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", -+ "more-asserts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "pretty_env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", -+ "sha2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", -+ "toml 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasmparser 0.39.3 (registry+https://github.com/rust-lang/crates.io-index)", -+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -+ "zstd 0.5.1+zstd.1.4.4 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "wasmtime-interface-types" -+version = "0.8.0" -+dependencies = [ -+ "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "walrus 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasm-webidl-bindings 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasmparser 0.39.3 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasmtime 0.8.0", -+ "wasmtime-jit 0.8.0", -+ "wasmtime-runtime 0.8.0", -+ "wasmtime-wasi 0.8.0", -+] -+ -+[[package]] -+name = "wasmtime-jit" -+version = "0.8.0" -+dependencies = [ -+ "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-frontend 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-wasm 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "more-asserts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "region 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasmparser 0.39.3 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasmtime-debug 0.8.0", -+ "wasmtime-environ 0.8.0", -+ "wasmtime-runtime 0.8.0", -+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "wasmtime-obj" -+version = "0.8.0" -+dependencies = [ -+ "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-wasm 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "faerie 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "more-asserts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasmtime-environ 0.8.0", -+] -+ -+[[package]] -+name = "wasmtime-py" -+version = "0.8.0" -+dependencies = [ -+ "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-frontend 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-native 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-wasm 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "pyo3 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", -+ "region 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasmparser 0.39.3 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasmtime 0.8.0", -+ "wasmtime-environ 0.8.0", -+ "wasmtime-interface-types 0.8.0", -+ "wasmtime-jit 0.8.0", -+ "wasmtime-runtime 0.8.0", -+ "wasmtime-wasi 0.8.0", -+] -+ -+[[package]] -+name = "wasmtime-runtime" -+version = "0.8.0" -+dependencies = [ -+ "cc 1.0.49 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-wasm 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -+ "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", -+ "more-asserts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "region 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasmtime-environ 0.8.0", -+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "wasmtime-rust" -+version = "0.8.0" -+dependencies = [ -+ "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasmtime 0.8.0", -+ "wasmtime-interface-types 0.8.0", -+ "wasmtime-jit 0.8.0", -+ "wasmtime-rust-macro 0.8.0", -+ "wasmtime-wasi 0.8.0", -+] -+ -+[[package]] -+name = "wasmtime-rust-macro" -+version = "0.8.0" -+dependencies = [ -+ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", -+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "wasmtime-wasi" -+version = "0.8.0" -+dependencies = [ -+ "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-wasm 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", -+ "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasi-common 0.8.0", -+ "wasmtime 0.8.0", -+ "wasmtime-environ 0.8.0", -+ "wasmtime-jit 0.8.0", -+ "wasmtime-runtime 0.8.0", -+] -+ -+[[package]] -+name = "wasmtime-wasi-c" -+version = "0.8.0" -+dependencies = [ -+ "bindgen 0.51.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-wasm 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -+ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", -+ "more-asserts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasmtime-environ 0.8.0", -+ "wasmtime-jit 0.8.0", -+ "wasmtime-runtime 0.8.0", -+] -+ -+[[package]] -+name = "wasmtime-wast" -+version = "0.8.0" -+dependencies = [ -+ "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cranelift-wasm 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wasmtime-environ 0.8.0", -+ "wasmtime-jit 0.8.0", -+ "wasmtime-runtime 0.8.0", -+ "wast 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "wast" -+version = "3.0.4" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "leb128 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "wast" -+version = "5.0.1" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "leb128 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "wat" -+version = "1.0.6" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "wast 5.0.1 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "which" -+version = "3.1.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "wig" -+version = "0.8.0" -+dependencies = [ -+ "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", -+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -+ "witx 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "winapi" -+version = "0.3.8" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "winapi-i686-pc-windows-gnu" -+version = "0.4.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "winapi-util" -+version = "0.1.2" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "winapi-x86_64-pc-windows-gnu" -+version = "0.4.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+ -+[[package]] -+name = "wincolor" -+version = "1.0.2" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -+ "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "winx" -+version = "0.8.0" -+dependencies = [ -+ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "cvt 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "witx" -+version = "0.5.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -+ "wast 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "zstd" -+version = "0.5.1+zstd.1.4.4" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "zstd-safe 2.0.3+zstd.1.4.4 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "zstd-safe" -+version = "2.0.3+zstd.1.4.4" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -+ "zstd-sys 1.4.15+zstd.1.4.4 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[[package]] -+name = "zstd-sys" -+version = "1.4.15+zstd.1.4.4" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+dependencies = [ -+ "cc 1.0.49 (registry+https://github.com/rust-lang/crates.io-index)", -+ "glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -+] -+ -+[metadata] -+"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" -+"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -+"checksum anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "7825f6833612eb2414095684fcf6c635becf3ce97fe48cf6421321e93bfbd53c" -+"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" -+"checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" -+"checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" -+"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -+"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" -+"checksum backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea" -+"checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491" -+"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" -+"checksum base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" -+"checksum bincode 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5753e2a71534719bf3f4e57006c3a4f0d2c672a4b676eec84161f763eca87dbf" -+"checksum bindgen 0.51.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ebd71393f1ec0509b553aa012b9b58e81dadbdff7130bd3b8cba576e69b32f75" -+"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" -+"checksum blake2b_simd 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a" -+"checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" -+"checksum block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" -+"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" -+"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" -+"checksum c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" -+"checksum capstone 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "031ba51c39151a1d6336ec859646153187204b0147c7b3f6fe2de636f1b8dbb3" -+"checksum capstone-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fae25eddcb80e24f98c35952c37a91ff7f8d0f60dbbdafb9763e8d5cc566b8d7" -+"checksum cc 1.0.49 (registry+https://github.com/rust-lang/crates.io-index)" = "e450b8da92aa6f274e7c6437692f9f2ce6d701fb73bacfcf87897b3f89a4c20e" -+"checksum cexpr 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fce5b5fb86b0c57c20c834c1b412fd09c77c8a59b9473f86272709e78874cd1d" -+"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" -+"checksum chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "31850b4a4d6bae316f7a09e691c944c28299298837edc0a03f755618c23cbc01" -+"checksum clang-sys 0.28.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81de550971c976f176130da4b2978d3b524eaa0fd9ac31f3ceb5ae1231fb4853" -+"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" -+"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -+"checksum cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "81fb25b677f8bf1eb325017cb6bb8452f87969db0fedb4f757b297bee78a7c62" -+"checksum constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "995a44c877f9212528ccc74b21a232f66ad69001e40ede5bcee2ac9ef2657120" -+"checksum cpu-time 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e9e393a7668fe1fad3075085b86c781883000b4ede868f43627b34a87c8b7ded" -+"checksum cranelift-bforest 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd05aac8cefcde54ce26178df8f36cb1f518ac691db650e7d2440c2b6b41c4dc" -+"checksum cranelift-codegen 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c63d9b6ff8a94f98deabab21880d7fd54996e0e16be687b6f80a3b6bdd9c188d" -+"checksum cranelift-codegen-meta 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7cb3df51c2c07d719d02869bfac6cabd8d82ee308d5b29ca62e6528723cc33a4" -+"checksum cranelift-codegen-shared 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "758f9426b2e22bf83fc1a6b231a9d53cd4830751883c7f0e196ebb3c210467b3" -+"checksum cranelift-entity 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff064733df8b98f453060264a8790393d1e807aca6942706b42f79a4f7aae9ed" -+"checksum cranelift-frontend 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1eaafb5fa623dcbe19a28084a8226d7a1b17184a949c1a1f29a46b479867998d" -+"checksum cranelift-native 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "90033dbd7293f6fad4cf9dcd769cd621d60df22b1c5a11799e86359b7447a51d" -+"checksum cranelift-wasm 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "54cb82a1071f88822763a583ec1a8688ffe5e2cda02c111d4483dd4376ed14d8" -+"checksum crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3aa945d63861bfe624b55d153a39684da1e8c0bc8fba932f7ee3a3c16cea3ca" -+"checksum crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac" -+"checksum crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db" -+"checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" -+"checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" -+"checksum ctor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd8ce37ad4184ab2ce004c33bf6379185d3b1c95801cab51026bd271bf68eedc" -+"checksum cvt 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "34ac344c7efccb80cd25bc61b2170aec26f2f693fd40e765a539a1243db48c71" -+"checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" -+"checksum directories 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "551a778172a450d7fc12e629ca3b0428d00f6afa9a43da1b630d54604e97371c" -+"checksum dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b" -+"checksum docopt 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f525a586d310c87df72ebcd98009e57f1cc030c8c268305287a476beb653969" -+"checksum dynasm 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "42a814e1edeb85dd2a3c6fc0d6bf76d02ca5695d438c70ecee3d90774f3259c5" -+"checksum dynasmrt 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8a393aaeb4441a48bcf47b5b6155971f82cc1eb77e22855403ccc0415ac8328d" -+"checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" -+"checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" -+"checksum errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2a071601ed01b988f896ab14b95e67335d1eeb50190932a1320f7fe3cadc84e" -+"checksum errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "14ca354e36190500e1e1fb267c647932382b54053c50b14970856c0b00a35067" -+"checksum faerie 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f902f2af041f6c7177a2a04f805687cdc71e69c7cbef059a2755d8923f4cd7a8" -+"checksum failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9" -+"checksum failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0bc225b78e0391e4b8683440bf2e63c2deeeb2ce5189eab46e2b68c6d3725d08" -+"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" -+"checksum fallible-iterator 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" -+"checksum file-per-thread-logger 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8505b75b31ef7285168dd237c4a7db3c1f3e0927e7d314e670bc98e854272fe9" -+"checksum filetime 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1ff6d4dab0aa0c8e6346d46052e93b13a16cf847b54ed357087c35011048cc7d" -+"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" -+"checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" -+"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" -+"checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407" -+"checksum ghost 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2a36606a68532b5640dc86bb1f33c64b45c4682aad4c50f3937b317ea387f3d6" -+"checksum gimli 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "162d18ae5f2e3b90a993d202f1ba17a5633c2484426f8bcae201f86194bacd00" -+"checksum glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" -+"checksum goblin 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3081214398d39e4bd7f2c1975f0488ed04614ffdd976c6fc7a0708278552c0da" -+"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" -+"checksum hermit-abi 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eff2656d88f158ce120947499e971d743c05dbcbed62e5bd2f38f1698bbc3772" -+"checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" -+"checksum id-arena 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" -+"checksum indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712d7b3ea5827fcb9d4fda14bf4da5f136f0db2ae9c8f4bd4e2d1c6fde4e6db2" -+"checksum indoc 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3f9553c1e16c114b8b77ebeb329e5f2876eed62a8d51178c8bc6bff0d65f98f8" -+"checksum indoc-impl 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b714fc08d0961716390977cdff1536234415ac37b509e34e5a983def8340fb75" -+"checksum inventory 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2bf98296081bd2cb540acc09ef9c97f22b7e487841520350293605db1b2c7a27" -+"checksum inventory-impl 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0a8e30575afe28eea36a9a39136b70b2fb6b0dd0a212a5bd1f30a498395c0274" -+"checksum itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484" -+"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" -+"checksum jobserver 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "f2b1d42ef453b30b7387e113da1c83ab1605d90c5b4e0eb8e96d016ed3b8c160" -+"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -+"checksum leb128 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3576a87f2ba00f6f106fdfcd16db1d698d648a26ad8e0573cad8537c3c362d2a" -+"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" -+"checksum libloading 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753" -+"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" -+"checksum mach 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "86dd2487cdfea56def77b88438a2c915fb45113c5319bfe7e14306ca4cd0b0e1" -+"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" -+"checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" -+"checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" -+"checksum more-asserts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0debeb9fcf88823ea64d64e4a815ab1643f33127d995978e099942ce38f25238" -+"checksum multi_mut 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "816df386e5557ac1843a96f1ba8a7cbf4ab175d05ccc15c87a3cda27b4fbdece" -+"checksum nix 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3b2e0b4f3320ed72aaedb9a5ac838690a8047c7b275da22711fddff4f8a14229" -+"checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" -+"checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" -+"checksum num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf4825417e1e1406b3782a8ce92f4d53f26ec055e3622e1881ca8e9f5f9e08db" -+"checksum num-complex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fcb0cf31fb3ff77e6d2a6ebd6800df7fdcd106f2ad89113c9130bcd07f93dffc" -+"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" -+"checksum num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "76bd5272412d173d6bf9afdf98db8612bbabc9a7a830b7bfc9c188911716132e" -+"checksum num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2885278d5fe2adc2f75ced642d52d879bffaceb5a2e0b1d4309ffdfb239b454" -+"checksum num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c81ffc11c212fa327657cb19dd85eb7419e163b5b076bede2bdb5c974c07e4" -+"checksum num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76dac5ed2a876980778b8b85f75a71b6cbf0db0b1232ee12f826bccb00d09d72" -+"checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" -+"checksum os_pipe 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "db4d06355a7090ce852965b2d08e11426c315438462638c6d721448d0b47aa22" -+"checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" -+"checksum paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "423a519e1c6e828f1e73b720f9d9ed2fa643dce8a7737fb43235ce0b41eeaa49" -+"checksum paste-impl 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4214c9e912ef61bf42b81ba9a47e8aad1b2ffaf739ab162bf96d1e011f54e6c5" -+"checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" -+"checksum plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" -+"checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" -+"checksum pretty_env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "717ee476b1690853d222af4634056d830b5197ffd747726a9a1eee6da9f49074" -+"checksum proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5" -+"checksum proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0319972dcae462681daf4da1adeeaa066e3ebd29c69be96c6abb1259d2ee2bcc" -+"checksum pyo3 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e1bfe257586436fbe1296d917f14a167d4253d0873bf43e2c9b9bdd58a3f9f35" -+"checksum pyo3-derive-backend 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4882d8237fd8c7373cc25cb802fe0dab9ff70830fd56f47ef6c7f3f287fcc057" -+"checksum pyo3cls 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fdf321cfab555f7411298733c86d21e5136f5ded13f5872fabf9de3337beecda" -+"checksum quick-error 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" -+"checksum quickcheck 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d5ca504a2fdaa08d3517f442fbbba91ac24d1ec4c51ea68688a038765e3b2662" -+"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" -+"checksum rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412" -+"checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" -+"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -+"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" -+"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -+"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -+"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" -+"checksum rand_pcg 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" -+"checksum raw-cpuid 7.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4a349ca83373cfa5d6dbb66fd76e58b2cca08da71a5f6400de0a0a6a9bceeaf" -+"checksum rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db6ce3297f9c85e16621bb8cca38a06779ffc31bb8184e1be4bed2be4678a098" -+"checksum rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9" -+"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -+"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" -+"checksum redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecedbca3bf205f8d8f5c2b44d83cd0690e39ee84b951ed649e9f1841132b66d" -+"checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" -+"checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" -+"checksum region 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "448e868c6e4cfddfa49b6a72c95906c04e8547465e9536575b95c70a4044f856" -+"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" -+"checksum rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf" -+"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" -+"checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" -+"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -+"checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" -+"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" -+"checksum scroll 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "abb2332cb595d33f7edd5700f4cbf94892e680c7f0ae56adab58a35190b66cb1" -+"checksum scroll_derive 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8584eea9b9ff42825b46faf46a8c24d2cff13ec152fa2a50df788b87c07ee28" -+"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -+"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -+"checksum serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449" -+"checksum serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64" -+"checksum serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)" = "48c575e0cc52bdd09b47f330f646cf59afc586e9c4e3ccd6fc1f625b8ea1dad7" -+"checksum sha2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "27044adfd2e1f077f649f59deb9490d3941d674002f7d062870a60ebe9bd47a0" -+"checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" -+"checksum smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44e59e0c9fa00817912ae6e4e6e3c4fe04455e75699d06eedc7d85917ed8e8f4" -+"checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" -+"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" -+"checksum string-interner 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd710eadff449a1531351b0e43eb81ea404336fa2f56c777427ab0e32a4cf183" -+"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -+"checksum strsim 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" -+"checksum syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1e4ff033220a41d1a57d8125eab57bf5263783dfdcc18688b1dacc6ce9651ef8" -+"checksum synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" -+"checksum target-lexicon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6f4c118a7a38378f305a9e111fcb2f7f838c0be324bfb31a77ea04f7f6e684b4" -+"checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" -+"checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" -+"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -+"checksum thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6f357d1814b33bc2dc221243f8424104bfe72dbe911d5b71b3816a2dff1c977e" -+"checksum thiserror-impl 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2e25d25307eb8436894f727aba8f65d07adf02e5b35a13cebed48bd282bfef" -+"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" -+"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" -+"checksum toml 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "01d1404644c8b12b16bfcffa4322403a91a451584daaaa7c28d3152e6cbc98cf" -+"checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" -+"checksum trybuild 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "987d6fdc45ddd7f3be5aa7386c8c8a844d1655c95b9ed948a9cd9cded8f2b79f" -+"checksum typemap 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "653be63c80a3296da5551e1bfd2cca35227e13cdd08c6668903ae2f4f77aa1f6" -+"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" -+"checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" -+"checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" -+"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" -+"checksum unindent 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "63f18aa3b0e35fed5a0048f029558b1518095ffe2a0a31fb87c93dece93a4993" -+"checksum unsafe-any 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f30360d7979f5e9c6e6cea48af192ea8fab4afb3cf72597154b8f08935bc9c7f" -+"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" -+"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" -+"checksum version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" -+"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -+"checksum walrus 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85ce93ab0c27412ba41d509f2410fa575ecbfdb4a6aba0e02e79e12c09745485" -+"checksum walrus-macro 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8757b0da38353d55a9687f4dee68a8f441f980dd36e16ab07d6e6c673f505f76" -+"checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" -+"checksum wasm-webidl-bindings 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b5cae185868c6038a48f487b9af3766ee0c68d4a85fa3610c3a0522092b3cec1" -+"checksum wasmparser 0.39.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c702914acda5feeeffbc29e4d953e5b9ce79d8b98da4dbf18a77086e116c5470" -+"checksum wast 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "233648f540f07fce9b972436f2fbcae8a750c1121b6d32d949e1a44b4d9fc7b1" -+"checksum wast 5.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8d1de68310854a9840d39487701a8c1acccb5c9f9f2650d5fce3cdfe6650c372" -+"checksum wat 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d916cc60b1b79ac1ca7683af8d6ec56b789167f7f696b3f1ab3d98961129f192" -+"checksum which 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5475d47078209a02e60614f7ba5e645ef3ed60f771920ac1906d7c1cc65024c8" -+"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" -+"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -+"checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" -+"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -+"checksum wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "96f5016b18804d24db43cebf3c77269e7569b8954a8464501c216cc5e070eaa9" -+"checksum witx 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6d075344afebe51633c0302fc11698c2d6414f9d366c749db1af57710f112561" -+"checksum zstd 0.5.1+zstd.1.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5c5d978b793ae64375b80baf652919b148f6a496ac8802922d9999f5a553194f" -+"checksum zstd-safe 2.0.3+zstd.1.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bee25eac9753cfedd48133fa1736cbd23b774e253d89badbeac7d12b23848d3f" -+"checksum zstd-sys 1.4.15+zstd.1.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "89719b034dc22d240d5b407fb0a3fe6d29952c181cff9a9f95c0bd40b4f8f7d8" diff --git a/nix/wasmtime/default.nix b/nix/wasmtime/default.nix deleted file mode 100644 index c978f023936..00000000000 --- a/nix/wasmtime/default.nix +++ /dev/null @@ -1,31 +0,0 @@ -{ rustPlatform, fetchFromGitHub, lib, python, cmake, llvmPackages, clang, stdenv, darwin }: - -rustPlatform.buildRustPackage rec { - pname = "wasmtime"; - version = "v0.8.0"; - - src = fetchFromGitHub { - owner = "bytecodealliance"; - repo = "${pname}"; - rev = "${version}"; - sha256 = "0az893srw49szvs5461bd165ffla4cc98gh42p3dwskwfkhpqjm4"; - fetchSubmodules = true; - }; - - cargoSha256 = "08b3rbnl7qwyfbwaqcb7z84sh0h94v18v6557hrf0dlil414v54i"; - - cargoPatches = [ ./cargo-lock.patch ]; - - nativeBuildInputs = [ python cmake clang ]; - buildInputs = [ llvmPackages.libclang ] ++ - lib.optionals stdenv.isDarwin [ darwin.apple_sdk.frameworks.Security ]; - LIBCLANG_PATH = "${llvmPackages.libclang}/lib"; - - meta = with lib; { - description = "Standalone JIT-style runtime for WebAssembly, using Cranelift"; - homepage = https://github.com/CraneStation/wasmtime; - license = licenses.asl20; - maintainers = [ maintainers.matthewbauer ]; - platforms = platforms.unix; - }; -} From cb635b43ead82bf657f2ea7b6c815913249a0c6b Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Wed, 8 Jan 2020 11:58:21 +0100 Subject: [PATCH 0886/1176] Fix URL schema (#1078) * Fix URL schema * qualify with List. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5f58436c802..867517b1105 100644 --- a/README.md +++ b/README.md @@ -212,12 +212,12 @@ A simple language for writing Dfinity actors. ## Example ``` -import List "as:std/list"; +import List "mo:std/list"; type Post = shared Text -> (); actor class Server() = { - private var clients : List = List.empty(); + private var clients : List.List = List.empty(); private func broadcast(msg : Text) { for (client in List.iter(clients)) { From dcd7916ee7ece0706a6b1846a8ab3ca857fa4654 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 8 Jan 2020 13:34:06 +0000 Subject: [PATCH 0887/1176] improve error messages and update tests --- src/mo_def/syntax.ml | 12 +++------ src/mo_frontend/parser.mly | 8 +++--- src/mo_frontend/typing.ml | 10 ++++--- .../ok/scope-example-func-implicit.tc.ok | 1 + ... => scope-example-func-implicit.tc.ret.ok} | 0 test/run-drun/ok/scope-example-implicit.tc.ok | 4 +++ ...et.ok => scope-example-implicit.tc.ret.ok} | 0 test/run-drun/ok/unsupported.comp-stub.ok | 10 ------- test/run-drun/ok/unsupported.comp.ok | 26 ------------------ test/run-drun/scope-example-func-implicit.mo | 27 +++++++++++++++++++ test/run-drun/scope-example-func.mo | 6 ++--- test/run-drun/scope-example-implicit.mo | 26 ++++++++++++++++++ test/run-drun/scope-example.mo | 9 ++++--- test/run-drun/unsupported.mo | 2 +- 14 files changed, 81 insertions(+), 60 deletions(-) create mode 100644 test/run-drun/ok/scope-example-func-implicit.tc.ok rename test/run-drun/ok/{unsupported.comp-stub.ret.ok => scope-example-func-implicit.tc.ret.ok} (100%) create mode 100644 test/run-drun/ok/scope-example-implicit.tc.ok rename test/run-drun/ok/{unsupported.comp.ret.ok => scope-example-implicit.tc.ret.ok} (100%) delete mode 100644 test/run-drun/ok/unsupported.comp-stub.ok delete mode 100644 test/run-drun/ok/unsupported.comp.ok create mode 100644 test/run-drun/scope-example-func-implicit.mo create mode 100644 test/run-drun/scope-example-implicit.mo diff --git a/src/mo_def/syntax.ml b/src/mo_def/syntax.ml index eae38a74f6a..30d02e7d243 100644 --- a/src/mo_def/syntax.ml +++ b/src/mo_def/syntax.ml @@ -302,14 +302,10 @@ let funcT(sort, tbs, t1, t2) = FuncT(sort, tbs, t1, t2) let funcE (f, s, tbs, p, t_opt, e) = - let t = match t_opt with - | None -> TupT [] - | Some t -> t.it - in - match s.it, t with - | _, AsyncT (None, _) -> - FuncE(f, s, ensure_scope_bind tbs, p, t_opt, e) - | Type.Shared _, TupT [] -> + match s.it, t_opt with + | _, Some { it = AsyncT (None, _); _} + | Type.Shared _, Some { it = TupT []; _} + | Type.Shared _, None -> FuncE(f, s, ensure_scope_bind tbs, p, t_opt, e) | _ -> FuncE(f, s, tbs, p, t_opt, e) diff --git a/src/mo_frontend/parser.mly b/src/mo_frontend/parser.mly index 32b5db7eb0b..990c870634f 100644 --- a/src/mo_frontend/parser.mly +++ b/src/mo_frontend/parser.mly @@ -287,9 +287,11 @@ typ_bind : | x=id { {var = x; bound = PrimT "Any" @! at $sloc} @= at $sloc } -%inline scope_bind : +%inline scope_bind_opt : | LT tb=typ_bind GT { tb } + | (* empty *) + { scope_bind() } %inline scope_inst : | LT t=typ GT @@ -457,9 +459,7 @@ exp_nondec(B) : { RetE(TupE([]) @? at $sloc) @? at $sloc } | RETURN e=exp(ob) { RetE(e) @? at $sloc } - | ASYNC e=exp(bl) - { AsyncE(scope_bind(), e) @? at $sloc } - | ASYNC tb = scope_bind e=exp_nullary(bl) + | ASYNC tb=scope_bind_opt e=exp(bl) { AsyncE(tb, e) @? at $sloc } | AWAIT e=exp(bl) { AwaitE(e) @? at $sloc } diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index deaa3fab09f..a203c6377e7 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -1,5 +1,5 @@ open Mo_def -open Mo_types +open Mo_types open Mo_values module Flags = Mo_config.Flags @@ -295,10 +295,12 @@ and check_scope env t at = | C.AsyncCap c | C.AwaitCap c -> if not (T.eq t (T.Con(c,[]))) then - local_error env at "bad scope" + local_error env at "bad scope: expecting scope instantiation %s, found %s" + (T.string_of_con c) + (T.string_of_typ_expand t) | C.NullCap -> - if not (T.eq t T.Any) then (* TBR *) - local_error env at "bad scope" + local_error env at "bad scope: expecting no scope instantiation, found %s" + (T.string_of_typ_expand t) and check_AsyncCap env s at = match env.async with diff --git a/test/run-drun/ok/scope-example-func-implicit.tc.ok b/test/run-drun/ok/scope-example-func-implicit.tc.ok new file mode 100644 index 00000000000..b58d2027d39 --- /dev/null +++ b/test/run-drun/ok/scope-example-func-implicit.tc.ok @@ -0,0 +1 @@ +scope-example-func-implicit.mo:7.13-7.22: type error, misplaced async expression diff --git a/test/run-drun/ok/unsupported.comp-stub.ret.ok b/test/run-drun/ok/scope-example-func-implicit.tc.ret.ok similarity index 100% rename from test/run-drun/ok/unsupported.comp-stub.ret.ok rename to test/run-drun/ok/scope-example-func-implicit.tc.ret.ok diff --git a/test/run-drun/ok/scope-example-implicit.tc.ok b/test/run-drun/ok/scope-example-implicit.tc.ok new file mode 100644 index 00000000000..bfc16f39e94 --- /dev/null +++ b/test/run-drun/ok/scope-example-implicit.tc.ok @@ -0,0 +1,4 @@ +scope-example-implicit.mo:10.12-10.19: type error, expression of type + async<@/7> Int +cannot produce expected type + async<@/5> Int diff --git a/test/run-drun/ok/unsupported.comp.ret.ok b/test/run-drun/ok/scope-example-implicit.tc.ret.ok similarity index 100% rename from test/run-drun/ok/unsupported.comp.ret.ok rename to test/run-drun/ok/scope-example-implicit.tc.ret.ok diff --git a/test/run-drun/ok/unsupported.comp-stub.ok b/test/run-drun/ok/unsupported.comp-stub.ok deleted file mode 100644 index 9b69d1cae08..00000000000 --- a/test/run-drun/ok/unsupported.comp-stub.ok +++ /dev/null @@ -1,10 +0,0 @@ -unsupported.mo:4.5-4.41: type error, a shared function cannot be private - (This is a limitation of the current version and flag -stub-system-api.) -unsupported.mo:38.26-38.29: type error, a shared function is only allowed as a public field of an actor - (This is a limitation of the current version and flag -stub-system-api.) -unsupported.mo:66.3-66.42: type error, actor classes with parameters are not supported; use an actor declaration instead - (This is a limitation of the current version and flag -stub-system-api.) -unsupported.mo:84.34-84.37: type error, a shared function is only allowed as a public field of an actor - (This is a limitation of the current version and flag -stub-system-api.) -unsupported.mo:85.27-85.30: type error, a shared function is only allowed as a public field of an actor - (This is a limitation of the current version and flag -stub-system-api.) diff --git a/test/run-drun/ok/unsupported.comp.ok b/test/run-drun/ok/unsupported.comp.ok deleted file mode 100644 index aff34c930f4..00000000000 --- a/test/run-drun/ok/unsupported.comp.ok +++ /dev/null @@ -1,26 +0,0 @@ -unsupported.mo:19.19-19.21: type error, shared, async function must be called within an await expression - (This is a limitation of the current version.) -unsupported.mo:28.8-28.9: type error, argument to await must be a call expression - (This is a limitation of the current version.) -unsupported.mo:32.17-32.29: type error, unsupported async block - (This is a limitation of the current version.) -unsupported.mo:4.5-4.41: type error, a shared function cannot be private - (This is a limitation of the current version.) -unsupported.mo:38.26-38.29: type error, a shared function is only allowed as a public field of an actor - (This is a limitation of the current version.) -unsupported.mo:41.10-41.18: type error, unsupported async block - (This is a limitation of the current version.) -unsupported.mo:62.3-62.35: type error, actor classes are not supported; use an actor declaration instead - (This is a limitation of the current version.) -unsupported.mo:66.3-66.42: type error, actor classes are not supported; use an actor declaration instead - (This is a limitation of the current version.) -unsupported.mo:70.45-70.53: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program - (This is a limitation of the current version.) -unsupported.mo:74.37-74.45: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program - (This is a limitation of the current version.) -unsupported.mo:81.34-81.37: type error, freestanding async expression not yet supported - (This is a limitation of the current version.) -unsupported.mo:84.34-84.37: type error, a shared function is only allowed as a public field of an actor - (This is a limitation of the current version.) -unsupported.mo:85.27-85.30: type error, a shared function is only allowed as a public field of an actor - (This is a limitation of the current version.) diff --git a/test/run-drun/scope-example-func-implicit.mo b/test/run-drun/scope-example-func-implicit.mo new file mode 100644 index 00000000000..267babbcfe4 --- /dev/null +++ b/test/run-drun/scope-example-func-implicit.mo @@ -0,0 +1,27 @@ +actor A { + + public shared func f() : async(Int,Int) { + var a : async Int = async 0; + + func set () { + a := async 666; // error: misplaced async + }; + + await (async { + set(); + }); + + let i = await a; + assert i == 666; // Boom! + return (0,0) + }; + + public shared func Test() : async () { + let (x,y) = await f(); + assert x == 0 and y == 0; + }; + +}; + +A.Test() //OR-CALL ingress Test 0x4449444C0000 + diff --git a/test/run-drun/scope-example-func.mo b/test/run-drun/scope-example-func.mo index 26e400d65ac..670c7fd2bff 100644 --- a/test/run-drun/scope-example-func.mo +++ b/test/run-drun/scope-example-func.mo @@ -5,18 +5,18 @@ actor A { var a : (async Int) = async 0; func set () { - a := async {return 666} ; + a := async {return 666} /**/; }; await (async { // current scope: Z set(); // this seems well-typed according to “Application (Derived Rule)”; - } ); + } /**/); let i = await a; assert i == 666; // Boom! return (0,0) - } ; + } /**/; public shared func Test() : async () { let (x,y) = await f(); diff --git a/test/run-drun/scope-example-implicit.mo b/test/run-drun/scope-example-implicit.mo new file mode 100644 index 00000000000..16abb74e38f --- /dev/null +++ b/test/run-drun/scope-example-implicit.mo @@ -0,0 +1,26 @@ +actor A { + public shared func ping() : async Int { 666 }; // normal remote function + + public shared func f() : async(Int,Int) { + // current scope: Y + var a : async Int = async 0; + + await (async { + // current scope: Z + a := ping (); // this seems well-typed according to “Application (Derived Rule)”; + }) ; + + let i = await a; + assert i == 666; // Boom! + return (0,0) + }; + + public shared func Test() : async () { + let (x,y) = await f(); + assert x == 0 and y == 0; + }; + +}; + +A.Test() //OR-CALL ingress Test 0x4449444C0000 + diff --git a/test/run-drun/scope-example.mo b/test/run-drun/scope-example.mo index 4e595935bfe..09838525c59 100644 --- a/test/run-drun/scope-example.mo +++ b/test/run-drun/scope-example.mo @@ -1,5 +1,5 @@ actor A { - public shared func ping() : async Int = async {666;} ; // normal remote function + public shared func ping() : async Int = async {666;} /**/; // normal remote function public shared func f() : async (Int,Int) = async { // current scope: Y @@ -8,15 +8,16 @@ actor A { await (async { // current scope: Z a := ping (); // this seems well-typed according to “Application (Derived Rule)”; - } ); + } /**/); let i = await a; assert i == 666; // Boom! return (0,0) - } ; + } /**/; public shared func Test() : async () { - let (0,0) = await f() + let (x,y) = await f(); + assert x == 0 and y == 0; }; }; diff --git a/test/run-drun/unsupported.mo b/test/run-drun/unsupported.mo index 3a402421999..ecef513fa31 100644 --- a/test/run-drun/unsupported.mo +++ b/test/run-drun/unsupported.mo @@ -38,7 +38,7 @@ actor Counter { shared func bad_shared() { }; // not actor enclosed func local_spawn() { - ignore(async ()); // not yet supported + ignore(async ()); // no async capability }; { From 4b277e8ef460568a9cbd9d12cb46c10abd152372 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 8 Jan 2020 14:38:13 +0100 Subject: [PATCH 0888/1176] Bump drun (#1080) mainly to run https://github.com/dfinity-lab/dfinity/pull/2211 through our test suite. Also included: ``` dfc8aa148 Merge pull request #2211 from dfinity-lab/chmllr/fixes-rejection 864b42d1b Merge pull request #2216 from dfinity-lab/xport/reconnect e377817b3 Merge pull request #2212 from dfinity-lab/consensusMetrics db2ba379b Merge pull request #2184 from dfinity-lab/dsd/prometheus/hypervisor aede634ae Merge pull request #2213 from dfinity-lab/dimitris/collapse-imports 7797cac4a Introduce a type for principal ids (#2192) 631eab223 Merge pull request #2180 from dfinity-lab/paulliu/unvalidated-purge 919539c4a Merge pull request #2177 from dfinity-lab/NewMembershipImpl 027d9eb49 Merge pull request #2185 from dfinity-lab/dsd/prometheus/consensus 48310e490 Merge pull request #2179 from dfinity-lab/paulliu/timer-extra 77f24555a Merge pull request #2186 from dfinity-lab/dsd/prometheus/messaging d1a6bd8ab OP: Add host page iterator for PageMap. (#2208) 18f6163d2 Merge pull request #2203 from dfinity-lab/johnw/assert_cmd 9910cbf30 Merge pull request #2117 from dfinity-lab/dimitris/gossip-signed-ingress 447a66e7e Merge pull request #2159 from dfinity-lab/dimitris/feeback-2 b69eb6256 StateManager: introduce LabeledState type. (#2194) ``` --- default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/default.nix b/default.nix index 2dfacd6c91a..9db54f98f9d 100644 --- a/default.nix +++ b/default.nix @@ -36,7 +36,7 @@ let dfinity-src = name = "dfinity-sources"; url = "ssh://git@github.com/dfinity-lab/dfinity"; # ref = "master"; - rev = "48ab58e7bf4de892a5c5c926050a350947ed2514"; + rev = "dfc8aa148021534ad01d321d1f2a843ab2933fa3"; }; in let dfinity-pkgs = import dfinity-src { inherit (nixpkgs) system; }; in From 43560d9a20d372db858718b8b6b40505ed0e5ffb Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Wed, 8 Jan 2020 15:23:26 +0100 Subject: [PATCH 0889/1176] prune haskell-packages.nix (#1079) * prune haskell-packages.nix now that we track nixpkgs:master also adapt package dependencies * remove redundant bound * use dontCheck * bump winter --- nix/haskell-packages.nix | 81 +++----------------------------------- test/lsp-int/lsp-int.cabal | 6 +-- 2 files changed, 9 insertions(+), 78 deletions(-) diff --git a/nix/haskell-packages.nix b/nix/haskell-packages.nix index 1421efe9417..63238da0834 100644 --- a/nix/haskell-packages.nix +++ b/nix/haskell-packages.nix @@ -1,80 +1,11 @@ nix: subpath: let stdenv = nix.stdenv; in self: super: { - haskell-lsp-types = self.callPackage - ({ mkDerivation, aeson, base, bytestring, data-default, deepseq - , filepath, hashable, lens, network-uri, scientific, text - , unordered-containers - }: - mkDerivation { - pname = "haskell-lsp-types"; - version = "0.18.0.0"; - sha256 = "1ypa3gxxcg7dl905d4nprcqzw2fcl7z7xy1hpg5har1dw3w9fyiq"; - libraryHaskellDepends = [ - aeson base bytestring data-default deepseq filepath hashable lens - network-uri scientific text unordered-containers - ]; - description = "Haskell library for the Microsoft Language Server Protocol, data types"; - license = stdenv.lib.licenses.mit; - hydraPlatforms = stdenv.lib.platforms.none; - }) {}; + haskell-lsp-types = self.haskell-lsp-types_0_19_0_0; - haskell-lsp = self.callPackage - ({ mkDerivation, aeson, async, attoparsec, base, bytestring - , containers, data-default, directory, filepath, hashable - , haskell-lsp-types, hslogger, hspec, hspec-discover, lens, mtl - , network-uri, QuickCheck, quickcheck-instances, rope-utf16-splay - , sorted-list, stm, temporary, text, time, unordered-containers - }: - mkDerivation { - pname = "haskell-lsp"; - version = "0.18.0.0"; - sha256 = "0q9xpjgr3n7svhd9f7mmkw113avswvfm08fnbijdr1sblipd12sl"; - isLibrary = true; - isExecutable = true; - libraryHaskellDepends = [ - aeson async attoparsec base bytestring containers data-default - directory filepath hashable haskell-lsp-types hslogger lens mtl - network-uri rope-utf16-splay sorted-list stm temporary text time - unordered-containers - ]; - testHaskellDepends = [ - aeson base bytestring containers data-default directory filepath - hashable hspec lens network-uri QuickCheck quickcheck-instances - rope-utf16-splay sorted-list stm text - ]; - testToolDepends = [ hspec-discover ]; - description = "Haskell library for the Microsoft Language Server Protocol"; - license = stdenv.lib.licenses.mit; - hydraPlatforms = stdenv.lib.platforms.none; - }) {}; + haskell-lsp = self.haskell-lsp_0_19_0_0; - lsp-test = self.callPackage - ({ mkDerivation, aeson, aeson-pretty, ansi-terminal, async, base - , bytestring, conduit, conduit-parse, containers, data-default - , Diff, directory, filepath, hspec, haskell-lsp, lens, mtl - , parser-combinators, process, rope-utf16-splay, text, transformers - , unix, unordered-containers - }: - mkDerivation { - pname = "lsp-test"; - version = "0.8.2.0"; - sha256 = "1762avrs4fkkd9v8i76giaf6km5f3lds5laickn7la7zq7ysh8a3"; - libraryHaskellDepends = [ - aeson aeson-pretty ansi-terminal async base bytestring conduit - conduit-parse containers data-default Diff directory filepath - haskell-lsp lens mtl parser-combinators process rope-utf16-splay - text transformers unix unordered-containers - ]; - doCheck = false; - testHaskellDepends = [ - aeson base data-default haskell-lsp hspec lens text - unordered-containers - ]; - description = "Functional test framework for LSP servers"; - license = stdenv.lib.licenses.bsd3; - hydraPlatforms = stdenv.lib.platforms.none; - }) {}; + lsp-test = nix.haskell.lib.dontCheck self.lsp-test_0_9_0_0; lsp-int = self.callCabal2nix "lsp-int" (subpath "test/lsp-int") { }; @@ -82,10 +13,10 @@ nix: subpath: winter = self.callCabal2nixWithOptions "winter" (nix.fetchFromGitHub { - owner = "dfinity"; + owner = "dfinity-side-projects"; repo = "winter"; - rev = "4295ff98da8ca890e824130152a78892ad6420ba"; - sha256 = "05wr3066mlz7hh2s49wgf9pgdsh1bsivnhp6j7hklmw2cnj9g0sl"; + rev = "1e16b471644be26160cc20c4e2144c643c547ed8"; + sha256 = "191fk1dv8vp28rwpl75nz9y3pbypc8jv9w669mvl9d2k5f74jirm"; }) "--no-check" {}; ic-stub = self.callCabal2nixWithOptions "ic-stub" (subpath "ic-stub") "-frelease" { }; diff --git a/test/lsp-int/lsp-int.cabal b/test/lsp-int/lsp-int.cabal index 45cfb8dac78..af1750c7de6 100644 --- a/test/lsp-int/lsp-int.cabal +++ b/test/lsp-int/lsp-int.cabal @@ -14,14 +14,14 @@ executable lsp-int main-is: Main.hs -- other-modules: other-extensions: OverloadedStrings, DuplicateRecordFields - build-depends: base ^>=4.12.0.0 - , text ^>=1.2.3.1 + build-depends: base ^>=4.12 + , text ^>=1.2 , hspec , HUnit , directory , lens , data-default , haskell-lsp-types - , lsp-test ^>=0.8 + , lsp-test ^>=0.9 -- hs-source-dirs: default-language: Haskell2010 From bc515bf4aafbc5e8be40d33b215b7221539f9f11 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 8 Jan 2020 15:20:29 +0000 Subject: [PATCH 0890/1176] rewrite test to pass checker --- test/mo-idl/counter.mo | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/mo-idl/counter.mo b/test/mo-idl/counter.mo index 5373aaf6aeb..d229d7ae191 100644 --- a/test/mo-idl/counter.mo +++ b/test/mo-idl/counter.mo @@ -32,7 +32,7 @@ func testDec() { testDec(); // Issue ten `dec` & `read` messages. -func testRead() { +func testRead() : async () { var i : Int = 10; let _ = async { while (i > 0) { @@ -46,4 +46,4 @@ func testRead() { } }; -testRead(); +ignore testRead(); From 49116a852acf5794121ae8f8bb46ec4b81cb281a Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 8 Jan 2020 16:53:29 +0100 Subject: [PATCH 0891/1176] Simple tests for package imports (#1081) exhibiting that I broke relative imports (will be fixed in separate PR). --- test/run.sh | 4 ++-- test/run/lib/pkg/lib.mo | 3 +++ test/run/lib/pkg/other-module.mo | 3 +++ test/run/ok/pkg-import-relative.tc.ok | 1 + test/run/ok/pkg-import-relative.tc.ret.ok | 1 + test/run/ok/pkg-missing.tc.ok | 1 + test/run/ok/pkg-missing.tc.ret.ok | 1 + test/run/pkg-import-absolute.mo | 6 ++++++ test/run/pkg-import-relative.mo | 5 +++++ test/run/pkg-missing.mo | 1 + 10 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 test/run/lib/pkg/lib.mo create mode 100644 test/run/lib/pkg/other-module.mo create mode 100644 test/run/ok/pkg-import-relative.tc.ok create mode 100644 test/run/ok/pkg-import-relative.tc.ret.ok create mode 100644 test/run/ok/pkg-missing.tc.ok create mode 100644 test/run/ok/pkg-missing.tc.ret.ok create mode 100755 test/run/pkg-import-absolute.mo create mode 100755 test/run/pkg-import-relative.mo create mode 100755 test/run/pkg-missing.mo diff --git a/test/run.sh b/test/run.sh index 150a91a8fa0..d4e1fdadf94 100755 --- a/test/run.sh +++ b/test/run.sh @@ -186,8 +186,8 @@ do if [ ${file: -3} == ".mo" ] then - # extra flags - moc_extra_flags="$(grep '//MOC-FLAG' $base.mo | cut -c11- | paste -sd' ')" + # extra flags (allow shell variables there) + moc_extra_flags="$(eval echo $(grep '//MOC-FLAG' $base.mo | cut -c11- | paste -sd' '))" # Typecheck run tc $MOC $moc_extra_flags --check $base.mo diff --git a/test/run/lib/pkg/lib.mo b/test/run/lib/pkg/lib.mo new file mode 100644 index 00000000000..13920308928 --- /dev/null +++ b/test/run/lib/pkg/lib.mo @@ -0,0 +1,3 @@ +module { + public func foo() = (); +} diff --git a/test/run/lib/pkg/other-module.mo b/test/run/lib/pkg/other-module.mo new file mode 100644 index 00000000000..6a748eba9c5 --- /dev/null +++ b/test/run/lib/pkg/other-module.mo @@ -0,0 +1,3 @@ +module { + public func bar() = (); +} diff --git a/test/run/ok/pkg-import-relative.tc.ok b/test/run/ok/pkg-import-relative.tc.ok new file mode 100644 index 00000000000..ea4b88fb5e1 --- /dev/null +++ b/test/run/ok/pkg-import-relative.tc.ok @@ -0,0 +1 @@ +(unknown location): package error, file "pkg-import-relative.mo/lib/pkg" (for package `pkg`) does not exist diff --git a/test/run/ok/pkg-import-relative.tc.ret.ok b/test/run/ok/pkg-import-relative.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run/ok/pkg-import-relative.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run/ok/pkg-missing.tc.ok b/test/run/ok/pkg-missing.tc.ok new file mode 100644 index 00000000000..4635d03e96a --- /dev/null +++ b/test/run/ok/pkg-missing.tc.ok @@ -0,0 +1 @@ +(unknown location): package error, file "pkg-missing.mo/does-not-exist" (for package `pkg`) does not exist diff --git a/test/run/ok/pkg-missing.tc.ret.ok b/test/run/ok/pkg-missing.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run/ok/pkg-missing.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run/pkg-import-absolute.mo b/test/run/pkg-import-absolute.mo new file mode 100755 index 00000000000..1f5ba383e1f --- /dev/null +++ b/test/run/pkg-import-absolute.mo @@ -0,0 +1,6 @@ +//MOC-FLAG --package pkg "$(realpath lib/pkg)" +import P1 "mo:pkg"; +import P2 "mo:pkg/other-module.mo"; +P1.foo(); +P2.bar(); + diff --git a/test/run/pkg-import-relative.mo b/test/run/pkg-import-relative.mo new file mode 100755 index 00000000000..3e47f3825c5 --- /dev/null +++ b/test/run/pkg-import-relative.mo @@ -0,0 +1,5 @@ +//MOC-FLAG --package pkg lib/pkg +import P "mo:pkg"; +import P "mo:pkg/other-module.mo"; +P1.foo(); +P2.bar(); diff --git a/test/run/pkg-missing.mo b/test/run/pkg-missing.mo new file mode 100755 index 00000000000..3a5b3220219 --- /dev/null +++ b/test/run/pkg-missing.mo @@ -0,0 +1 @@ +//MOC-FLAG --package pkg does-not-exist From 74936af19887b4541cf4bc2822858c7b7b7c8b12 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 8 Jan 2020 16:48:43 +0000 Subject: [PATCH 0892/1176] update test output --- test/run-drun/ok/scope-example-func.tc.ok | 1 + test/run-drun/ok/scope-example-func.tc.ret.ok | 1 + test/run-drun/ok/scope-example.tc.ok | 1 + test/run-drun/ok/scope-example.tc.ret.ok | 1 + test/run-drun/ok/unsupported.tc.ok | 1 + test/run-drun/ok/unsupported.tc.ret.ok | 1 + 6 files changed, 6 insertions(+) create mode 100644 test/run-drun/ok/scope-example-func.tc.ok create mode 100644 test/run-drun/ok/scope-example-func.tc.ret.ok create mode 100644 test/run-drun/ok/scope-example.tc.ok create mode 100644 test/run-drun/ok/scope-example.tc.ret.ok create mode 100644 test/run-drun/ok/unsupported.tc.ok create mode 100644 test/run-drun/ok/unsupported.tc.ret.ok diff --git a/test/run-drun/ok/scope-example-func.tc.ok b/test/run-drun/ok/scope-example-func.tc.ok new file mode 100644 index 00000000000..d933fb4d510 --- /dev/null +++ b/test/run-drun/ok/scope-example-func.tc.ok @@ -0,0 +1 @@ +scope-example-func.mo:8.13-8.34: type error, misplaced async expression diff --git a/test/run-drun/ok/scope-example-func.tc.ret.ok b/test/run-drun/ok/scope-example-func.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/scope-example-func.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-drun/ok/scope-example.tc.ok b/test/run-drun/ok/scope-example.tc.ok new file mode 100644 index 00000000000..90b864bacb6 --- /dev/null +++ b/test/run-drun/ok/scope-example.tc.ok @@ -0,0 +1 @@ +scope-example.mo:10.18-10.19: type error, bad scope: expecting scope instantiation Z, found Y/1 diff --git a/test/run-drun/ok/scope-example.tc.ret.ok b/test/run-drun/ok/scope-example.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/scope-example.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-drun/ok/unsupported.tc.ok b/test/run-drun/ok/unsupported.tc.ok new file mode 100644 index 00000000000..1d8b975d138 --- /dev/null +++ b/test/run-drun/ok/unsupported.tc.ok @@ -0,0 +1 @@ +unsupported.mo:41.10-41.18: type error, misplaced async expression diff --git a/test/run-drun/ok/unsupported.tc.ret.ok b/test/run-drun/ok/unsupported.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/unsupported.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 From 5ecee771ecfca02fa1f6a137165c857c5e9de449 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 8 Jan 2020 17:48:55 +0100 Subject: [PATCH 0893/1176] Do not treat package paths relative to file (#1082) The code was buggy (it would not take the dirname of the file, as it does for relative imports), and I also think it is wrong: If you write `moc --package pkg pkg-dir foo/bar.mo`, and `bar` imports `mo:pkg/a`, then you want that to resolve to `./pkg-dir/a.mo`, not `./foo/pkg-dir/a.mo`. --- src/pipeline/resolve_import.ml | 14 +++++--------- test/run/ok/pkg-import-relative.tc.ok | 1 - test/run/ok/pkg-import-relative.tc.ret.ok | 1 - test/run/ok/pkg-missing.tc.ok | 2 +- test/run/pkg-import-relative.mo | 4 ++-- 5 files changed, 8 insertions(+), 14 deletions(-) delete mode 100644 test/run/ok/pkg-import-relative.tc.ok delete mode 100644 test/run/ok/pkg-import-relative.tc.ret.ok diff --git a/src/pipeline/resolve_import.ml b/src/pipeline/resolve_import.ml index 251607880da..4864db1ee4c 100644 --- a/src/pipeline/resolve_import.ml +++ b/src/pipeline/resolve_import.ml @@ -174,12 +174,8 @@ let resolve_import_string msgs base actor_idl_path aliases packages imported (f, | Error msg -> err_unrecognized_url msgs at f msg -(* Resolve the argument to --package. These can also be relative to base *) -let resolve_package_url (msgs:Diag.msg_store) (base:filepath) (pname:string) (f:url) : filepath = - let f = - if Filename.is_relative f - then in_base base f - else f in +(* Resolve the argument to --package. *) +let resolve_package_url (msgs:Diag.msg_store) (pname:string) (f:url) : filepath = let f = Lib.FilePath.normalise f in if Sys.file_exists f then f @@ -210,8 +206,8 @@ type package_urls = url M.t type actor_aliases = url M.t type aliases = blob M.t -let resolve_packages : package_urls -> filepath -> package_map Diag.result = fun purls base -> - Diag.with_message_store (fun msgs -> Some (M.mapi (resolve_package_url msgs base) purls)) +let resolve_packages : package_urls -> package_map Diag.result = fun purls -> + Diag.with_message_store (fun msgs -> Some (M.mapi (resolve_package_url msgs) purls)) let resolve_aliases : actor_aliases -> aliases Diag.result = fun alias_urls -> Diag.with_message_store (fun msgs -> Some (M.mapi (resolve_alias_url msgs) alias_urls)) @@ -225,7 +221,7 @@ type flags = { let resolve : flags -> Syntax.prog -> filepath -> resolved_imports Diag.result = fun {actor_idl_path; package_urls; actor_aliases} p base -> - Diag.bind (resolve_packages package_urls base) (fun (packages:package_map) -> + Diag.bind (resolve_packages package_urls) (fun (packages:package_map) -> Diag.bind (resolve_aliases actor_aliases) (fun aliases -> Diag.with_message_store (fun msgs -> let base = if Sys.is_directory base then base else Filename.dirname base in diff --git a/test/run/ok/pkg-import-relative.tc.ok b/test/run/ok/pkg-import-relative.tc.ok deleted file mode 100644 index ea4b88fb5e1..00000000000 --- a/test/run/ok/pkg-import-relative.tc.ok +++ /dev/null @@ -1 +0,0 @@ -(unknown location): package error, file "pkg-import-relative.mo/lib/pkg" (for package `pkg`) does not exist diff --git a/test/run/ok/pkg-import-relative.tc.ret.ok b/test/run/ok/pkg-import-relative.tc.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run/ok/pkg-import-relative.tc.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run/ok/pkg-missing.tc.ok b/test/run/ok/pkg-missing.tc.ok index 4635d03e96a..54ea8f2bd68 100644 --- a/test/run/ok/pkg-missing.tc.ok +++ b/test/run/ok/pkg-missing.tc.ok @@ -1 +1 @@ -(unknown location): package error, file "pkg-missing.mo/does-not-exist" (for package `pkg`) does not exist +(unknown location): package error, file "does-not-exist" (for package `pkg`) does not exist diff --git a/test/run/pkg-import-relative.mo b/test/run/pkg-import-relative.mo index 3e47f3825c5..f2a52b4a99c 100755 --- a/test/run/pkg-import-relative.mo +++ b/test/run/pkg-import-relative.mo @@ -1,5 +1,5 @@ //MOC-FLAG --package pkg lib/pkg -import P "mo:pkg"; -import P "mo:pkg/other-module.mo"; +import P1 "mo:pkg"; +import P2 "mo:pkg/other-module.mo"; P1.foo(); P2.bar(); From 8a6b6c7d8ea9b97f8507f72599ecfa80fd822e52 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 8 Jan 2020 18:47:39 +0000 Subject: [PATCH 0894/1176] rule out oneway calls from nullscoped context; fix tests to pass --- src/mo_frontend/typing.ml | 2 + test/fail/actor-match.mo | 2 +- test/mo-idl/counter.mo | 4 +- test/run-drun/actor-creation.mo | 5 +- test/run-drun/chat.mo | 19 +++-- test/run-drun/general-type-components.mo | 2 +- test/run-drun/indirect-counter.mo | 8 +- .../run-drun/ok/actor-creation.ic-stub-run.ok | 5 +- test/run-drun/ok/actor-creation.run-ir.ok | 1 - test/run-drun/ok/actor-creation.run-low.ok | 1 - test/run-drun/ok/actor-creation.run.ok | 1 - test/run-drun/ok/chat.ic-stub-run.ok | 4 +- .../ok/indirect-counter.ic-stub-run.ok | 10 ++- .../ok/reference-params.ic-stub-run.ok | 4 +- test/run-drun/reference-params.mo | 84 ++++++++++--------- test/run/chatpp.mo | 20 ++++- test/run/counter-class.mo | 14 ++-- 17 files changed, 113 insertions(+), 73 deletions(-) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index a203c6377e7..8d9789fd4b5 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -884,6 +884,8 @@ and infer_exp'' env exp : T.typ = | T.Func (_, T.Promises (T.Var (_, n)), _, _, _) | T.Func (_, T.Returns, _, _, [T.Async (T.Var (_, n),_)]) -> check_scope env (List.nth ts n) (List.nth typs n).at + | T.Func (T.Shared _, T.Returns, _, _, []) -> + check_scope env (List.nth ts 0) (List.nth typs 0).at | _ -> ()); let t_arg = T.open_ ts t_arg in let t_ret = T.open_ ts t_ret in diff --git a/test/fail/actor-match.mo b/test/fail/actor-match.mo index 3a00e3f59e7..5f901cb11d9 100644 --- a/test/fail/actor-match.mo +++ b/test/fail/actor-match.mo @@ -4,7 +4,7 @@ let a : actor {f : () -> (); g : () -> ()} = actor { }; func foo() = switch a { - case {f; g} { f() } + case {f; g} { () } }; assert ((switch (foo()) { case () 0 }) == 0) diff --git a/test/mo-idl/counter.mo b/test/mo-idl/counter.mo index d229d7ae191..b4e80c382be 100644 --- a/test/mo-idl/counter.mo +++ b/test/mo-idl/counter.mo @@ -21,7 +21,7 @@ func showAsync<@>(note : Text, a : async<@> Int) {}; let c = Counter(10); // Issue ten `dec` messages. -func testDec() { +func testDec() : async () { var i : Int = 10; while (i > 0) { c.dec(); @@ -29,7 +29,7 @@ func testDec() { } }; -testDec(); +ignore testDec(); // Issue ten `dec` & `read` messages. func testRead() : async () { diff --git a/test/run-drun/actor-creation.mo b/test/run-drun/actor-creation.mo index 96c82eaeb02..776b2943432 100644 --- a/test/run-drun/actor-creation.mo +++ b/test/run-drun/actor-creation.mo @@ -15,10 +15,11 @@ actor a { b.foo(); debugPrint ("a.foo() done"); }; + debugPrint ("a created"); }; -debugPrint ("main actor calling a.foo()"); -a.foo(); + +a.foo(); //OR-CALL ingress foo "DIDL\x00\x00" // certainly won’t work on drun //SKIP comp diff --git a/test/run-drun/chat.mo b/test/run-drun/chat.mo index 1b21856a93c..21b92fd2537 100644 --- a/test/run-drun/chat.mo +++ b/test/run-drun/chat.mo @@ -47,13 +47,17 @@ actor class Client() = this { }; -let server = Server(); -let bob = Client(); -let alice = Client(); -let charlie = Client(); -bob.go("bob", server); -alice.go("alice", server); -charlie.go("charlie", server); +actor Test { + public func go() { + let server = Server(); + let bob = Client(); + let alice = Client(); + let charlie = Client(); + bob.go("bob", server); + alice.go("alice", server); + charlie.go("charlie", server); + } +}; /* design flaws: @@ -63,4 +67,5 @@ charlie.go("charlie", server); - parameterising Client on s:IServer argument complains about non-closed actor (expected acc. to Joachim, pending system changes) */ +Test.go(); //OR-CALL ingress go "DIDL\x00\x00" //SKIP comp diff --git a/test/run-drun/general-type-components.mo b/test/run-drun/general-type-components.mo index 788fb16c49b..cad2c15b898 100644 --- a/test/run-drun/general-type-components.mo +++ b/test/run-drun/general-type-components.mo @@ -16,7 +16,7 @@ type XYU = X.Y.U; actor A = { public func f() { g();}; - func g() { f();}; + shared func g() { f();}; object Y = { public type U = Int; }; diff --git a/test/run-drun/indirect-counter.mo b/test/run-drun/indirect-counter.mo index 8d9bc3f5a89..8bf1228698f 100644 --- a/test/run-drun/indirect-counter.mo +++ b/test/run-drun/indirect-counter.mo @@ -13,9 +13,9 @@ let a = actor { public func debugPrint() { aa.debugPrint() }; }; -a.inc(); -a.inc(); -a.inc(); -a.debugPrint() +a.inc(); //OR-CALL ingress inc "DIDL\x00\x00" +a.inc(); //OR-CALL ingress inc "DIDL\x00\x00" +a.inc(); //OR-CALL ingress inc "DIDL\x00\x00" +a.debugPrint() //OR-CALL ingress debugPrint "DIDL\x00\x00" //SKIP comp diff --git a/test/run-drun/ok/actor-creation.ic-stub-run.ok b/test/run-drun/ok/actor-creation.ic-stub-run.ok index aaa611cea86..dd52e6cd83c 100644 --- a/test/run-drun/ok/actor-creation.ic-stub-run.ok +++ b/test/run-drun/ok/actor-creation.ic-stub-run.ok @@ -2,12 +2,13 @@ ← completed: canister-id = 0x0000000000000400 → install debug.print: main actor creating a -debug.print: main actor calling a.foo() debug.print: a created +← completed +→ update foo(0x4449444c0000) debug.print: a.foo() called debug.print: a creating b debug.print: a calling b.foo() debug.print: a.foo() done debug.print: b created debug.print: b.foo() called -← completed +← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/actor-creation.run-ir.ok b/test/run-drun/ok/actor-creation.run-ir.ok index 8605c4121d3..ec60a00515c 100644 --- a/test/run-drun/ok/actor-creation.run-ir.ok +++ b/test/run-drun/ok/actor-creation.run-ir.ok @@ -1,6 +1,5 @@ main actor creating a a created -main actor calling a.foo() a.foo() called a creating b b created diff --git a/test/run-drun/ok/actor-creation.run-low.ok b/test/run-drun/ok/actor-creation.run-low.ok index 8605c4121d3..ec60a00515c 100644 --- a/test/run-drun/ok/actor-creation.run-low.ok +++ b/test/run-drun/ok/actor-creation.run-low.ok @@ -1,6 +1,5 @@ main actor creating a a created -main actor calling a.foo() a.foo() called a creating b b created diff --git a/test/run-drun/ok/actor-creation.run.ok b/test/run-drun/ok/actor-creation.run.ok index 8605c4121d3..ec60a00515c 100644 --- a/test/run-drun/ok/actor-creation.run.ok +++ b/test/run-drun/ok/actor-creation.run.ok @@ -1,6 +1,5 @@ main actor creating a a created -main actor calling a.foo() a.foo() called a creating b b created diff --git a/test/run-drun/ok/chat.ic-stub-run.ok b/test/run-drun/ok/chat.ic-stub-run.ok index abb785b3c60..2434b62be24 100644 --- a/test/run-drun/ok/chat.ic-stub-run.ok +++ b/test/run-drun/ok/chat.ic-stub-run.ok @@ -1,6 +1,8 @@ → create ← completed: canister-id = 0x0000000000000400 → install +← completed +→ update go(0x4449444c0000) debug.print: charlie received hello from bob debug.print: alice received hello from bob debug.print: bob received hello from bob @@ -19,4 +21,4 @@ debug.print: bob received hello from charlie debug.print: charlie received goodbye from charlie debug.print: alice received goodbye from charlie debug.print: bob received goodbye from charlie -← completed +← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/indirect-counter.ic-stub-run.ok b/test/run-drun/ok/indirect-counter.ic-stub-run.ok index b8bc9426a98..b138275f349 100644 --- a/test/run-drun/ok/indirect-counter.ic-stub-run.ok +++ b/test/run-drun/ok/indirect-counter.ic-stub-run.ok @@ -1,8 +1,16 @@ → create ← completed: canister-id = 0x0000000000000400 → install +← completed +→ update inc(0x4449444c0000) debug.print: 2 +← completed: 0x4449444c0000 +→ update inc(0x4449444c0000) debug.print: 3 +← completed: 0x4449444c0000 +→ update inc(0x4449444c0000) debug.print: 4 +← completed: 0x4449444c0000 +→ update debugPrint(0x4449444c0000) debug.print: 4 -← completed +← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/reference-params.ic-stub-run.ok b/test/run-drun/ok/reference-params.ic-stub-run.ok index d7f9b18f9b0..c08400f59d6 100644 --- a/test/run-drun/ok/reference-params.ic-stub-run.ok +++ b/test/run-drun/ok/reference-params.ic-stub-run.ok @@ -1,9 +1,11 @@ → create ← completed: canister-id = 0x0000000000000400 → install +← completed +→ update go(0x4449444c0000) debug.print: Hello World! debug.print: Hello World! debug.print: Hello World! debug.print: Hello Universe! debug.print: Hello Galaxy! -← completed +← completed: 0x4449444c0000 diff --git a/test/run-drun/reference-params.mo b/test/run-drun/reference-params.mo index df186f35eb6..5e74668b233 100644 --- a/test/run-drun/reference-params.mo +++ b/test/run-drun/reference-params.mo @@ -1,50 +1,54 @@ -actor { - let a = actor { - public func hello() { - debugPrint("Hello World!"); +actor Test { + public func go () { + let a = actor { + public func hello() { + debugPrint("Hello World!"); + }; }; - }; - a.hello(); + a.hello(); - // test passing an actor to an actor - let b = actor this { - public func say_hi(a : actor { hello : () -> () } ) { - a.hello(); + // test passing an actor to an actor + let b = actor this { + public func say_hi(a : actor { hello : () -> () } ) { + a.hello(); + }; }; - }; - b.say_hi(a); + b.say_hi(a); - // test passing a funcref to an actor - let c = actor { - public func say_hi(f : shared () -> ()) { - f(); + // test passing a funcref to an actor + let c = actor { + public func say_hi(f : shared () -> ()) { + f(); + }; }; - }; - c.say_hi(a.hello); + c.say_hi(a.hello); - // test passing a own funcref to an actor - let d = actor { - public func say_hi(f : shared () -> ()) { - f(); + // test passing a own funcref to an actor + let d = actor { + public func say_hi(f : shared () -> ()) { + f(); + }; + public func hello() { + debugPrint("Hello Universe!"); + }; + public func go() { + say_hi(hello); + } }; - public func hello() { - debugPrint("Hello Universe!"); - }; - public func go() { - say_hi(hello); - } - }; - d.go(); + d.go(); - // test passing a self to an actor - let e = actor this { - public func hello() { - debugPrint("Hello Galaxy!"); + // test passing a self to an actor + let e = actor this { + public func hello() { + debugPrint("Hello Galaxy!"); + }; + public func send_to(f : shared (actor { hello : () -> () }) -> ()) { + f(this); + } }; - public func send_to(f : shared (actor { hello : () -> () }) -> ()) { - f(this); - } - }; - e.send_to(b.say_hi); -} + e.send_to(b.say_hi); + } +}; + +Test.go() //OR-CALL ingress go "DIDL\x00\x00" //SKIP comp diff --git a/test/run/chatpp.mo b/test/run/chatpp.mo index d96e11d9bba..63d5e7dd19f 100644 --- a/test/run/chatpp.mo +++ b/test/run/chatpp.mo @@ -15,18 +15,22 @@ actor class Server() = { var nextId : Nat = 0; var clients : List = null; +/* + // casualty of scope-awaits - can't abstract out a sequential broadcast function + // instead, inline it below ... func broadcast(id : Nat, message : Text) { var next = clients; label sends loop { switch next { case null { break sends }; case (?n) { - if (n.head.id != id) n.head.client.send(message); + if (n.head.id != id) n.head.client.send(message); // rejected due to async send next := n.tail; }; }; }; }; +*/ public func subscribe(aclient : Client) : async Subscription { let c = {id = nextId; client = aclient; var revoked = false}; @@ -35,7 +39,19 @@ actor class Server() = { clients := ?cs; return object { public shared func post(message : Text) { - if (not c.revoked) broadcast(c.id, message); + if (not c.revoked) { // inlined call to broadcast(c.id,message) + let id = c.id; + var next = clients; + label sends loop { + switch next { + case null { break sends }; + case (?n) { + if (n.head.id != id) n.head.client.send(message); + next := n.tail; + }; + }; + }; + } }; public shared func cancel() { unsubscribe(c.id) }; }; diff --git a/test/run/counter-class.mo b/test/run/counter-class.mo index bfc4d6d2820..7da517ed5ed 100644 --- a/test/run/counter-class.mo +++ b/test/run/counter-class.mo @@ -13,15 +13,17 @@ func showCounter(c : Int) {}; let c = Counter(10); -func test() { - var i : Int = 10; - while (i > 0) { - c.dec(); - i -= 1; +actor Test { + public func go() { + var i : Int = 10; + while (i > 0) { + c.dec(); + i -= 1; + } } }; -let _ = test(); +Test.go(); // no support for first-class shared functions anywhere yet //SKIP comp From dfa1a66e8284620eed3049e4e3fa57cbab380ab9 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Wed, 8 Jan 2020 12:38:10 -0700 Subject: [PATCH 0895/1176] implement HashMap OO interface using tries --- stdlib/trieMap.mo | 145 ++++++++++++++++++++++++++++++++++++++++++ stdlib/trieMapTest.mo | 113 ++++++++++++++++++++++++++++++++ 2 files changed, 258 insertions(+) create mode 100644 stdlib/trieMap.mo create mode 100644 stdlib/trieMapTest.mo diff --git a/stdlib/trieMap.mo b/stdlib/trieMap.mo new file mode 100644 index 00000000000..589404f630c --- /dev/null +++ b/stdlib/trieMap.mo @@ -0,0 +1,145 @@ +import T "trie.mo"; +import P "prelude.mo"; +import Hash "hash.mo"; +import List "list.mo"; + +/** + +Hash Map (aka Hash table) +========================= + +This module defines an imperative hash map, with a general key and value type. It matches the interface and semantics of HashMap. Unlike HashMap, its internal representation uses a functional hash trie (see `trie.mo`). + +This class permits us to compare the performance of two representations of hash-based maps, where tries (as binary trees) permit more efficient, constant-time, cloning compared with ordinary tables. This property is nice for supporting transactional workflows where map mutations may be provisional, and where we may expect some mutations to be uncommitted, or to "roll back". + +For now, this class does not permit a direct `clone` operation (neither does `HashMap`), but it does permit creating iterators via `iter()`. The effect is similar: Each iterator costs `O(1)` to create, but represents a fixed view of the mapping that does not interfere with mutations (it will _not_ view subsequent insertions or mutations, if any). + +*/ + +module { +public class TrieMap (isEq:(K, K) -> Bool, hashOf: K -> T.Hash) { + + var map = T.empty(); + var _count : Nat = 0; + + public func count() : Nat = _count; + + public func set(k:K, v:V) : ?V { + let keyObj = {key=k; hash=hashOf(k);}; + let (map2, ov) = + T.insert(map, keyObj, isEq, v); + map := map2; + switch(ov){ + case null { _count += 1 }; + case _ {} + }; + ov + }; + + public func get(k:K) : ?V = { + let keyObj = {key=k; hash=hashOf(k);}; + T.find(map, keyObj, isEq) + }; + + public func del(k:K) : ?V = { + let keyObj = {key=k; hash=hashOf(k);}; + let (t, ov) = T.remove(map, keyObj, isEq); + map := t; + switch(ov){ + case null { _count -= 1 }; + case _ {} + }; + ov + }; + + // notably, each iterator gets a _persistent view_ of the mapping, + // by virtue of the trie being a persistent data structure. + public func iter() : Iter<(K,V)> = object { + var stack = ?(map, null) : List.List>; + public func next() : ?(K,V) { + switch stack { + case null { null }; + case (?(trie, stack2)) { + switch trie { + case (#empty) { + stack := stack2; + next() + }; + case (#leaf({keyvals=null})) { + stack := stack2; + next() + }; + case (#leaf({count=c; keyvals=?((k,v),kvs)})) { + stack := ?(#leaf({count=c-1; keyvals=kvs}), stack2); + ?(k.key, v) + }; + case (#branch(br)) { + stack := ?(br.left, ?(br.right, stack2)); + next() + }; + } + } + } + } + }; + + }; + + +// clone cannot be an efficient object method, +// ...but is still useful in tests, and beyond. +public func clone + (h:TrieMap, + keyEq: (K,K) -> Bool, + keyHash: K -> Hash.Hash) : TrieMap { + let h2 = TrieMap(keyEq, keyHash); + for ((k,v) in h.iter()) { + ignore h2.set(k,v); + }; + h2 +}; + +// Clone from any iterator of key-value pairs +public func fromIter(iter:Iter<(K, V)>, + keyEq: (K,K) -> Bool, + keyHash: K -> Hash.Hash) : TrieMap { + let h = TrieMap(keyEq, keyHash); + for ((k,v) in iter) { + ignore h.set(k,v); + }; + h +}; + +public func map + (h:TrieMap, + keyEq: (K,K) -> Bool, + keyHash: K -> Hash.Hash, + mapFn: (K, V1) -> V2, + ) : TrieMap { + let h2 = TrieMap(keyEq, keyHash); + for ((k, v1) in h.iter()) { + let v2 = mapFn(k, v1); + ignore h2.set(k,v2); + }; + h2 +}; + +public func mapFilter + (h:TrieMap, + keyEq: (K,K) -> Bool, + keyHash: K -> Hash.Hash, + mapFn: (K, V1) -> ?V2, + ) : TrieMap { + let h2 = TrieMap(keyEq, keyHash); + for ((k, v1) in h.iter()) { + switch (mapFn(k, v1)) { + case null { }; + case (?v2) { + ignore h2.set(k,v2); + }; + } + }; + h2 +}; + +} diff --git a/stdlib/trieMapTest.mo b/stdlib/trieMapTest.mo new file mode 100644 index 00000000000..1f75f6104e5 --- /dev/null +++ b/stdlib/trieMapTest.mo @@ -0,0 +1,113 @@ +import H "trieMap.mo"; +import Hash "hash.mo"; + +func textIsEq(x:Text,y:Text):Bool { x == y }; + +debug { + let a = H.TrieMap(textIsEq, Hash.Hash.hashOfText); + + ignore a.set("apple", 1); + ignore a.set("banana", 2); + ignore a.set("pear", 3); + ignore a.set("avocado", 4); + ignore a.set("Apple", 11); + ignore a.set("Banana", 22); + ignore a.set("Pear", 33); + ignore a.set("Avocado", 44); + ignore a.set("ApplE", 111); + ignore a.set("BananA", 222); + ignore a.set("PeaR", 333); + ignore a.set("AvocadO", 444); + + // need to resupply the constructor args; they are private to the object; but, should they be? + let b = H.clone(a, textIsEq, Hash.Hash.hashOfText); + + // ensure clone has each key-value pair present in original + for ((k,v) in a.iter()) { + debugPrint(debug_show (k,v)); + switch (b.get(k)) { + case null { assert false }; + case (?w) { assert v == w }; + }; + }; + + // ensure original has each key-value pair present in clone + for ((k,v) in b.iter()) { + debugPrint(debug_show (k,v)); + switch (a.get(k)) { + case null { assert false }; + case (?w) { assert v == w }; + }; + }; + + // do some more operations: + ignore a.set("apple", 1111); + ignore a.set("banana", 2222); + ignore a.del("pear"); + ignore a.del("avocado"); + + // check them: + switch (a.get("apple")) { + case (?1111) { }; + case _ { assert false }; + }; + switch (a.get("banana")) { + case (?2222) { }; + case _ { assert false }; + }; + switch (a.get("pear")) { + case null { }; + case (?_) { assert false }; + }; + switch (a.get("avocado")) { + case null { }; + case (?_) { assert false }; + }; + + // undo operations above: + ignore a.set("apple", 1); + ignore a.set("banana", 2); + ignore a.set("pear", 3); + ignore a.set("avocado", 4); + + // ensure clone has each key-value pair present in original + for ((k,v) in a.iter()) { + debugPrint(debug_show (k,v)); + switch (b.get(k)) { + case null { assert false }; + case (?w) { assert v == w }; + }; + }; + + // ensure original has each key-value pair present in clone + for ((k,v) in b.iter()) { + debugPrint(debug_show (k,v)); + switch (a.get(k)) { + case null { assert false }; + case (?w) { assert v == w }; + }; + }; + + + // test fromIter method + let c = H.fromIter(b.iter(), textIsEq, Hash.Hash.hashOfText); + + // c agrees with each entry of b + for ((k,v) in b.iter()) { + debugPrint(debug_show (k,v)); + switch (c.get(k)) { + case null { assert false }; + case (?w) { assert v == w }; + }; + }; + + // b agrees with each entry of c + for ((k,v) in c.iter()) { + debugPrint(debug_show (k,v)); + switch (b.get(k)) { + case null { assert false }; + case (?w) { assert v == w }; + }; + }; + +}; From 46807d8aa1de42e103089cc31df520a44702202d Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Wed, 8 Jan 2020 12:42:12 -0700 Subject: [PATCH 0896/1176] typo --- stdlib/trieMap.mo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/trieMap.mo b/stdlib/trieMap.mo index 589404f630c..8e523599400 100644 --- a/stdlib/trieMap.mo +++ b/stdlib/trieMap.mo @@ -5,7 +5,7 @@ import List "list.mo"; /** -Hash Map (aka Hash table) +Trie Map ========================= This module defines an imperative hash map, with a general key and value type. It matches the interface and semantics of HashMap. Unlike HashMap, its internal representation uses a functional hash trie (see `trie.mo`). From 3918bef6b4e62e3514560e7ac47720e0f194e1ef Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Wed, 8 Jan 2020 12:44:10 -0700 Subject: [PATCH 0897/1176] Makefile additions --- stdlib/Makefile | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/stdlib/Makefile b/stdlib/Makefile index 74b48a43a8f..980f8f69a2e 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -26,6 +26,8 @@ TESTS=\ Hash \ HashMap \ HashMapTest \ + TrieMap \ + TrieMapTest \ Int \ IntTest \ Iter \ @@ -89,6 +91,12 @@ $(OUTDIR)/HashMapTest.out: hashMapTest.mo | $(OUTDIR) $(OUTDIR)/HashMap.out: hashMap.mo | $(OUTDIR) $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ +$(OUTDIR)/TrieMapTest.out: trieMapTest.mo | $(OUTDIR) + $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ + +$(OUTDIR)/TrieMap.out: trieMap.mo | $(OUTDIR) + $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ + $(OUTDIR)/Function.out: function.mo | $(OUTDIR) $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ From 0665f8b31295c41a1186969645eaef83b809696a Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 9 Jan 2020 10:33:58 +0100 Subject: [PATCH 0898/1176] Bump to Ocaml 4.08 (#1000) --- default.nix | 2 +- test/repl/ok/stateful.stderr.ok | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/default.nix b/default.nix index 9db54f98f9d..c92f8da61dd 100644 --- a/default.nix +++ b/default.nix @@ -7,7 +7,7 @@ let nixpkgs = (import ./nix/nixpkgs.nix).nixpkgs { inherit system; overlays = [ # Selecting the ocaml version - (self: super: { ocamlPackages = self.ocaml-ng.ocamlPackages_4_07; }) + (self: super: { ocamlPackages = self.ocaml-ng.ocamlPackages_4_08; }) # Additional ocaml package (self: super: { ocamlPackages = super.ocamlPackages // { diff --git a/test/repl/ok/stateful.stderr.ok b/test/repl/ok/stateful.stderr.ok index 72a3f26c62e..769234f3997 100644 --- a/test/repl/ok/stateful.stderr.ok +++ b/test/repl/ok/stateful.stderr.ok @@ -1,5 +1,5 @@ stdin:2.9-2.17: syntax error, unclosed text literal -stdin:2.9-2.17: type error, operator not defined for operand types +stdin:1.9-1.17: type error, operator not defined for operand types Nat and Bool From 493810f18396b52ee3983baf65dac3dfb8a965fb Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Thu, 9 Jan 2020 10:49:33 +0000 Subject: [PATCH 0899/1176] fix samples --- samples/ListClient.mo | 4 ++-- samples/ListClient.txt | 1 + samples/app/server.mo | 27 +++++++++++++-------------- samples/counter.mo | 26 ++++++++++++-------------- samples/pa_cars.mo | 2 +- 5 files changed, 29 insertions(+), 31 deletions(-) diff --git a/samples/ListClient.mo b/samples/ListClient.mo index f8c8647fcdf..6df35c58472 100644 --- a/samples/ListClient.mo +++ b/samples/ListClient.mo @@ -1,7 +1,7 @@ -module { - import List = "ListLib.mo"; // private, so we don't re-export List +module { + public type Stack = List.List; public func push(x : Int, s : Stack) : Stack = List.cons(x, s); diff --git a/samples/ListClient.txt b/samples/ListClient.txt index 03f7ebe32f4..1f93f337921 100644 --- a/samples/ListClient.txt +++ b/samples/ListClient.txt @@ -3,6 +3,7 @@ -- Checking ListLib.mo: -- Definedness ListLib.mo: -- Checking ListClient.mo: +let List : module {type List = ?(T, List); cons : (T, List) -> List; nil : () -> List} -- Definedness ListClient.mo: -- Interpreting ListLib.mo: -- Interpreting ListClient.mo: diff --git a/samples/app/server.mo b/samples/app/server.mo index afcccab76c6..3416e4a0083 100644 --- a/samples/app/server.mo +++ b/samples/app/server.mo @@ -11,19 +11,6 @@ actor class Server() = { var nextId : Nat = 0; var clients : L.List = null; - func broadcast(id : Nat, message : Text) { - var next = clients; - label sends loop { - switch next { - case null { break sends }; - case (?n) { - if (n.head.id != id) n.head.client(message); - next := n.tail; - }; - }; - }; - }; - public func subscribe(aclient : shared Text -> ()) : async T.Subscription { let c = {id = nextId; client = aclient; var revoked = false}; nextId += 1; @@ -31,7 +18,19 @@ actor class Server() = { clients := ?cs; return object { public shared func post(message : Text) { - if (not c.revoked) broadcast(c.id, message); + if (not c.revoked) { // inlined call to broadcast(c.id,message) + let id = c.id; + var next = clients; + label sends loop { + switch next { + case null { break sends }; + case (?n) { + if (n.head.id != id) n.head.client(message); + next := n.tail; + }; + }; + }; + } }; public shared func cancel() { unsubscribe(c.id) }; }; diff --git a/samples/counter.mo b/samples/counter.mo index 636588fa7ed..2b1cb43e03d 100644 --- a/samples/counter.mo +++ b/samples/counter.mo @@ -15,13 +15,13 @@ actor class Counter(i : Int) { // Dummy functions to show intermediate value in trace. func show(note : Text, c : Int) {}; -func showAsync(note : Text, a : async Int) {}; +func showAsync<@>(note : Text, a : async<@> Int) {}; // Create an actor. let c = Counter(10); // Issue ten `dec` messages. -func testDec() { +func testDec() : async () { var i : Int = 10; while (i > 0) { c.dec(); @@ -29,21 +29,19 @@ func testDec() { } }; -testDec(); +ignore testDec(); // Issue ten `dec` & `read` messages. -func testRead() { +func testRead() : async () { var i : Int = 10; - let _ = async { - while (i > 0) { - c.dec(); - let t = c.read(); - showAsync("before", t); - show("await", await t); - showAsync("after", t); - i -= 1; - } + while (i > 0) { + c.dec(); + let t = c.read(); + showAsync<@>("before", t); + show("await", await t); + showAsync<@>("after", t); + i -= 1; } }; -testRead(); +ignore testRead(); diff --git a/samples/pa_cars.mo b/samples/pa_cars.mo index 80a51e39899..86822f1bc49 100644 --- a/samples/pa_cars.mo +++ b/samples/pa_cars.mo @@ -21,7 +21,7 @@ actor class PACars(dmv : DMV) { public func verifyCarInformation(user : User, car : Car) : async ?(shared (Location, TimeSpan) -> async Result) { let carInfo = await dmv.check(car); if (carInfo.isValid and not carInfo.wasStolen) { - return ?(shared func (location, time) : async Result { + return ?(shared func (location : Location, time : TimeSpan) : async Result { return reserveSpot(user, carInfo, location, time); }) } else { From cf3d7e1358afda1ecf9e775fc09236429c1f1694 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Thu, 9 Jan 2020 10:50:36 +0000 Subject: [PATCH 0900/1176] remove comment --- samples/app/server.mo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/app/server.mo b/samples/app/server.mo index 3416e4a0083..d3fc52cf6fa 100644 --- a/samples/app/server.mo +++ b/samples/app/server.mo @@ -18,7 +18,7 @@ actor class Server() = { clients := ?cs; return object { public shared func post(message : Text) { - if (not c.revoked) { // inlined call to broadcast(c.id,message) + if (not c.revoked) { let id = c.id; var next = clients; label sends loop { From 67be9dba7bdf4b1c1c9e1ec5b6a5bfdf7953f2c7 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 9 Jan 2020 13:41:18 +0100 Subject: [PATCH 0901/1176] IC Stub: Remove files added by accident (#1085) --- ic-stub/loop.c | 5 ----- ic-stub/loop.wasm | Bin 295 -> 0 bytes ic-stub/print.mo | 1 - ic-stub/print.wasm | Bin 51147 -> 0 bytes 4 files changed, 6 deletions(-) delete mode 100644 ic-stub/loop.c delete mode 100755 ic-stub/loop.wasm delete mode 100644 ic-stub/print.mo delete mode 100644 ic-stub/print.wasm diff --git a/ic-stub/loop.c b/ic-stub/loop.c deleted file mode 100644 index 2a0c8f36876..00000000000 --- a/ic-stub/loop.c +++ /dev/null @@ -1,5 +0,0 @@ -unsigned int i; -void canister_init () { -i = 1024*1024; -while (i--) {}; -} diff --git a/ic-stub/loop.wasm b/ic-stub/loop.wasm deleted file mode 100755 index 9fb34a22b3abbd13c7086c9c21ea6546ae180542..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 295 zcmZ9Fy-ve09K`>Bf25^u1q)(B_Ev^eEmiqgP(APfhzBrkVnKkoQJf;W5DyF;c_bc< zAYkE^JN@pY0~<;N0AzRvKnVilSRo>(2qZbAE$WXQ6D|DNdtdYxEGb>NuD1k)F%QmG zW@Uq;I4~x+jWy2al#DX#i_o~*6uxKx2Df;Fy;jHg2?{hQlqlhh#9fR)mUP)6BFXp% zD5_h> diff --git a/ic-stub/print.mo b/ic-stub/print.mo deleted file mode 100644 index 66a86a75b0b..00000000000 --- a/ic-stub/print.mo +++ /dev/null @@ -1 +0,0 @@ -debugPrint "Hi\n"; diff --git a/ic-stub/print.wasm b/ic-stub/print.wasm deleted file mode 100644 index 23e892104e49577ea9fe6d11149c0d908e63a1b6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 51147 zcmdUY37jNVeSf{GzN>quW|v)HcY*2#lQjY|v%|0$#H}&Qse%z>5>1BQnciitp4sl6 z-C45i3^&LjmlukFpdg2U$|>q{dnK9}^Utj@cQoqXBWf=G-|z3es;)j}*wH1Q{1;}r z>ecW4-tT_D_j|8;ta5!yS(c?fb>YH-<)3TM&s*oJy=wm4#NK&cJNUqFxwg=(=Jl_= z1eHtc+ytHiD9I1DS-JzR?7e%{Uj3Y~d#!UL95RxD#E|IUjz$l_p=BH(62k0xpb=OZ z%Kr8OC{HIxD_du`CueG7)rMs`Q}ykIa&7zYXt_}yu8*Bxu~ci@$n?x^%Vt}$R+*XH zZ8^M7)hgqak%qp>Rcf{A+VIHqD0JOkX1UxWc4wNu%=m9YwiOza;dX{BQK z%ef??=*R8Sv(Qt(KR(E&QrS!f1Ep4Qv{WjApO$}kydslHrxjY$^28t{g_f1b=e>NY zC((1zK`U3UTGQLRYSqe>tJfTS$iauM#TEXoTeoig`a_%l&~)g^m3StP0ls$a+BJu= z+hK>TTX#4C*RDErE&fC6nnPEvUA6XbfJpn{hab8MkI{ea+9MK|Q(tOE{X70kUMx43 zoqC8DnRyj_@4p`T@dYj}EdE+pNVt2|kX*O?vVwhIOt|UW*v%=7l&fR)Mx{19Rvl|t z&qLRhDcedm%3CKZ%E~}t3)W}s>}}MXZ3P4Fb1I$5=G=T?MUU6Ja@9fP{m`}R)*p8G z5q`0Bf`$QHx3*>c*3R=U-PRcz4qkSZ4QQB|7%-LIrX&D z&p7i9Z+z2PXTSN^-*V1df8%Yx`CGsJ_ILcw?+%|^-a0Z`*|z<>vGIw?sp|C1j#|Aj zyK~pv?(=_d&jowu7u1F7B6YF4L|v*bQMC`$x<*~A-leWn*Q*=Ujp`=# zZuK7ZUiCipes#0@fcl`iMSV!!s%}%as}HL?)Sc=h>Z9r|b+`JMx<}os?o;=xkE;jN zgX$sm3H3?!DfO^=L_Mk=Q;(}B)Th;x>ND!I>T_zJdP+U5o>9-L=hXA+1@(FL1@%Ss zC1nLaQ?B|WmHX_+E~0&3L!nu|6*%KTqUv3u+-t*@?6_}ju#;ZOy;7Qj7eANqGM2gX zEnj&l%l!H&j&WB0D{z@tpINg+5j#(zAC1D$4}!nND?9w;9B{a;9*6OOkfY%SwG`D zgLVNQxa;*Z#bl5ma5eyt^5r9mkAJ@Br#}E-*3bG$!e>h<_d*6owFCh`b@`%HJaK@i zxKG4jL!L!j)9z?So#06s!XYbJhyolIe8*j)!)KP;;j_!_@VVu7*tgsc&n&mYbIa}U z!g4!&VYwZ?wA>C~?b_j8Vj4=D#(SR8B^OkG5YyCuz`v3>Gk&Eo*@ZLSD>ZN&M2-TXgyH{YHJra#2696zY$53SGp#M~nNe zz!q8mQ@b=Cd ze^GvNDU`Rzc#r1DK+OeemUjCs(!(p^H50vO@*YOI<~y&kvfwOO@YraZ#^7~309JdAmGe1m zq;>}Tc&8y35(IVHLER9vwQqiB@J-zpX^|c>!k%yMqH&;0D~^>rgYOFt*9C-owP;Dt z3}bY`=ImLrgBM?XF7baQaX+sBQ5PA*!4PP@sl7GuFajR5jNowuPmjl4xAs+jWACZTW1JCZ%_`y-(+hk{}^1o`0BeF-jxM%{;_ zr_i5}JWrC7fRn6fKDg?cL^62qGYK%k?w*Sj>@m!j+J#O2_U&h|wn3kLR^SD98RP)# zi5X#(!oAk3bZb7bd-L(#oBO&qALDK7hWnM>n_tnrx!ApV$lKlx_bJ_*&*6^R7aFLT!_c{6 z7QeH_41Obx{*!QM4$1-9_~&7x?S`${VBxVNF2*Jm#&nCi0 z!B@};6$QrPzZ6{o*e+oj@soNa)B*kxFrP+MA^0IMD+~pSu<+O!Yr!p>LxA8#p+#B^ zU5NKjijHz{&*xB1fDXm~yfvkiPfpuR!Yp233StE`4Xu+HCtR&)1~VmB%gm+BazDevd}yk<~ZK@0+x7*r?`vkG#8JEUjH>2Y5O8F-+DfrDRm z20;I(4gCj-mwy*+XW%ffx)l!k^v37x_e z55I!7VwAJ!ua>mG-&(HyeHZq(w42-%)7x^~XB|G$$=tFg37=JN+qGJh7Nd*C0SI+ ztPxz9Sz7^ihwbrF@)*lPy2wi4e1PmAg&G|$@p;6KAl2~kT%iV6TN}V4Qb>FB!=9Fh z2GG`k4gu4P0vKRN17n78K?m&FVSevOe$VaaW>ii{R8F*QE-)mOly{4Azb*d3M1YxK zLT6}+;430ebY>=q51oRy#4hf?CVa%PUTjb+_zU{mdZSrBkYY49njtvC+wR>mo=(v+ z6bF*JhVd^I+tGs%n5FWF94}17?41bj(1q*%ov6sTHCkA@lUY*o8{bCLS(4po z(j(6$i7?8$Mmn8R+Y$1q5rD&tFTe}=l zu$G(>-?H2(@!OF6Hz{9avd-T2^cZE#ecZ-GHS_XIcVD2hJ3XYGo?nt%PzRmz5ZEwKUg9yTP`n4;c_3-wul<-*`Oc(3yP7G z3(G_53UE-eeS0s)q!3~)d*OF4mFr)4;B);SEg=~9TB9*+7lYW&1RAX)Se zmm(=lmFd2qDzJCn4_UsF{`*-GJ#$vGBgpXSa3QnLdZUzrUU*6uJS@a1>CXihwhZrs zn!LYND zYgo;FBeXdLWA_6xteOupSY&x=lo3#U5u4Jp(^A!gH!n9%{R>R&r6S5j2i|>`j409B zHcq)FS?2KPG1vyd{ubp>)bDE2*G8_nnalMv?A(|8msR6}})C?ZLTq(=ERHs*{ zIl{!lLxmSf3DOg03wqVltJB%lP$YH^Wjm;tf|p{~LywL@bqSe=yA3-x>n!%_KB7b#=qM_ZR41u7~f>LR75iP- z8cN_yC7aeDN7_p80KMyk0BK`SC84*4U`sz|w=aq9tumuI9JCikhmX~;I}uO2-DzuF zp_d|2vG}`^5BKV&h*XISey_iR>yF+c3eLVq8{v*wu}61ZrB^Ylg6~P!Rl4gcePnbM zZK~H_Ra^<1T8XYri=i8ovU)2k3w)*3_@xaVzTx8zTaz@ka4Qt0DlWha0PD2O*q&JF zAVEZvAtKym^)^|A$Zqb6#ZA0v!|o#@PfX=`z0fjIK>HlG;3W;o>iNQN+bR^5PY^_#rP|iHjF`ag1*lE$;oxiY!>ESAjAz4q{O3 z*pDF~4&;U-JK@MqII*fLy!Uxj8Yah!c|Pz_=>{syxkQDN z4GJ64B6^3Sht-Pc6Grr|7CkIC{!EJ=$975LBK<`4P5{w&;uO&@(oaOs6Bn2XtYQwd zV#8Eu^>Y+`D>fe+z~jZ7mKi28A&8yZQV0})W1@H3iNY2!&`9!-^xZ&24;rvV3>s3P z0jUOQNEy+0B0x=ZyqIbcJr<6k=yjC|^DuKg{6g+A!E{erc!TXYvt#EytGwrw3-?>V zj$InPGKI1&OE)Ix$b7fq9lyu919*=W{#;%OT z+Q}Pku^8xNFFVoXkTBp5lL-=RGm7E!Qn4KG_mz8xTm?UU4s4CfhXr~pxyp>=wVpuk z&Cyq>FJ|&-t5eB3HZ9-P)Kq31Wc2o0?sFm#*sJo{2birOy|ZLQ4~kx6DLz9f z9p_^yOHhnvh}9+_Hp+ZQL@Rr&008WZ){YR@K5Lv+cu`~=4TqU68BmO%(c-;2fj>(y zeqU&FSnY=q6>WR7y_x#*F64=@&7y4I*;24w-URExC*859F!tmeQ8GjMar1hx-$l#;MKc**yzQ#pJB z!=K_OkoMq(vvt&!H14x@AR?u3T2>%h2`phJ1I?O5q)0gM*9a^>wGL>HICGtE*9_H$ z(l`fSz^PVC<>pB#1ay%dJbT0S-%3Ctq#r*ZyU9ZmK#&{g-2%FJqlK5G@NBN8DLkiv zdIAC@jS&Rn#Gwce;IQ#G6fBMeD*_Nd6VMqR*bVOwc!rfvgiCc=fzw+WisQ*vy8(-4 zc)%(fKNR6 z99vmQo+pmvu-|-~T7W-y5-*MWPrSWZjI0~^r$Jya(bEdA(7tgMc0a^Xem-jR-Kdqu z1552u9n?CIFP8xlGva2SZ#Vlw%rd^t#?Iopo1f==%c;`#U#6u~rmrF9m zWl83ccFBOY{ge!Cm(|{;=b8y{T|3V8F`N?i+arOc=e>-ixj&E0Pc0nY%>qQCP(WKG=tYE*@h-OWhwGpbPprO+O`7&BE1tW=r{s?IIHE3jPeatJ2Jb)g0lUxg%KRRe)+^I{6@l5j#Z#Tu;;Siry2(fpuTw_poBNaN zxX#L;eh_#QrNmLPCT(W+%`0&K_ZAW=-Ga69{28(^v4dV5ZwkEjB|&mUZ!(WH0agVr zf3UriPr98XAq z8L3YCP-bJWKuOr&pv7JDh8^ z!zkH^o#nBD)j%gJE7(YH*gsYzbJJ0Sh5@Hsp2WM@cM1Fbrxb7q0U|>EmLhT~A{QcB z9f_#jE8}94!caU`pf(bTDJqA=VujW`UXO-DQ8{$;lx>0!G!{pgGL@!O7<>?Q=(Q4j zcy5RsBr-=2Pb8ALX1uN@~2# zDGNnr;~=n{gki30m|c>&ZjwU5)}6PKBff7+<|<$%AJZqkV@$ECM~-J zvP#HEdSg_A=>>G*UiUrZ+5@GrdXRg#~71cnM&8O3y<1WSHJ$QGJ&5 zCRx*yqHN48p5}f{_E)eYr+jM?dofFH%W?a~x0s#TMFm+P2Z`+mK}X{y?wVn5#r>|? zQ(}i;j=5lv!%l?U?i$CQRtX!BRta0L+%vHCxU$!UlXKie2)6?X=41Pc+ag))_4&Ay zy)|s$qBr+@ki~o1=vbX>9pdfe;2=2`3Osn1mILG1G5UL#a$k$^SUOqWRoEcYyN&zZ zr;T5y8@XdRUFRp?zDpemDG@W0Fiv}>N2?MS-*m>>-de_=T z;v=y@Wxb&QVf)quxQ3ju^Ad6$C**qb2FGHAJjK-rD7oHHB8Oyceu)`I5_*Le17?V! zyl=2$svol6R=^ix`t}7N#vYn~8*mzg%ai@PmM{D3*ahpaQ1+r!@16D*{Z$@d4pI*r zgCll!ZMM$n+N@5CUTKLV!Iwe;kA54$Sd~rdG*)F(%?_+e^kfD{vUM37j98Z4`SM?+ z^A)kqUvJtP4sjUE6h~-Uoq}Z+?N)cu&Jt$}bq4Q!#Efr&q4$Jmvv6P zpd#_WI@NqJ&wiN?!6$(3W)~;$&dlO=gDQPq}IsISc6J! z0b$`$4$Ts>Oj3*`JdIS~b_jR81B1jK^2jE`W-4HQhcDjP$+a^W4wt(=EDGY#(Gp*~ zLNnktJOy+)asfx2Y;ieYMCuU<*h3}=(AnV4B_#zq9Kw;#e-Y-&@IRO?Q!a%QLv9%H zqFy-9#heSZy*HY!KWuiDR1IG>V3}_$P*|4;tRB*y@D;K<8SpB+mck7n9}a@kNf^+* zOLUfOhABMb8K~d_nt-T+)+QE*j1Z&)z&S;{#TvBoP-Y%Z1L;_D#F4i}oTgAkm>HPC zDI3%f5XJ;U3U3X`E59`yY~1&hgYW*k5X%IVQ30L`4&PB=@z~xBd1M-p7BJW~pxAfe zGkD>5;lhj3Of~U+;QLO(`JF9D#~kUnux|j14TdX@P(t#l{-x>nyg@wckJYD1d87?j4wSa>LGk8M@%F2{@BuMWYpaV?H_C5dyBM>a_ zgD6w$=cwjp@D!llEqLDAhFN*ljp{Wbp+boHXT?=J+0zpS8Z@z5hA} zac=|>V%0q#jM~w29L|GM{)-MO`x-O8$?qWz5#4_R_Y@zFQJpGNYhazRgWM+F=R`wT zenDMyLis>Nj!Y(Cs6sog^F@n+DFniqED*!>7FGoq8pj`>Fqm}T44jsdV}T3r7s9^O zDeFYXxDrD~nEoKOs&%ek1~Xq%f&~a7p#w}jO36##Hm6t>zhV;0QPRq@o^VtLA^-%= z-tE)}EDaOD%$+G`S-kO99Z8jXBi z`hqjpl^`NgL$L>YeS1Qvr5tSP0A>equ5Z+$Lz{?llmoj2d#D-KBoKmc5F6HC{SuSu z+3hmDYjL3tt-qp#wbrl8sv0EFYC7Z!A<(cxxypHCZ7D`YdS%`w*S%Vgr?>)s(WVHH?XkWo{v@+B4cUOxU+4CsWSff#8E4rMzOlkFZf?pai} zL$EQ())`uVnQt9$TbGDI!L^_#%9b%YE?dXF8DA-8*&c>I(uUJV`*0E#Am9r^_lEI= zF-_(H)I*?2`aT8e-JyLG@f>09N}J6IOwO2Bzzoizd$-{`{~!?A-(tg{U}2dLlQbWJ zaV~Pg%iuWlMfMln`&f^fdklmpuxWX^M zw3+2V_C%~vy%RG4XIb=ogO7|9&PQ43EFl7u4#-L5&@0}#GD8=hM1ywro!Z$;19Eb`0Yr9s6|duivXNy~mXcGQJE0?)mER2btRa6qkm>V&0@x{7La62g)N*MEQg(4-M;ro-ZEa01& z8K!!2^jkR5F-6w?CaQov2hg&Is@>ZAu5lRA%|G+TyULFdsnKWN7i7-?Q|Y5}nbl`1g{y+D+>5E_7>O;D-`eY66kO6Y*WkbI#j zvVx>mG>F&aYb$`=$yar0^>fn`;YCgj3p}P$%9P1i+`aJKochR=SV816N9;uJ3_T}9 z+BuFdq|xW(eHeqZJGxdp%p*!^g9ogTjuM0iu|TO|CZP#w$@oL1ViB4&e@RMSsFJA1 zbtaq&%!4|kJ-Y#!+YRrp@y(vlh}0KoRL~>9Vc2j}W)YZ3DF(4FFvj>;1TBym!jU$z zh=o}6fcBdE5_(jw8w8C|z`@5w_h5{C>O(9Nfkb_wT^OUqT&TyxN>G0<3Rl$N0gMF> zssQ+kkR@s+{OSSlBm|>s@;t++ZDUP?rG+=K*2kA32}i!d1u825&7e@rRs?zsfxCox zq@`haiJDuQiN3XE;j;ekmls<*(0yf}zC=W0x@ox;_ zeM6ztqiNv>`2LzqLtNu>0GU5=0p~N0X450s6&~SGo^%L!l0-R7s{ppcNGRnjYC_&i z;(8L167ZD0yiCnE!NlN6Xz0qUorsMCB_uF`pitxi4m7N%61dnnrDovp6pSL0I7|q`M#u#@K}ky9L?WyQ>mdfn z5Pxj0ff9opf`lxJPy^^KrRgl7f~r9H#tuK{MEukB72`T66Ycanrle3`oi#SPhD0Sn>fB^6e=kvmcB+2T2I1$aH=nUz@EDBV@PqFgzQ+xfi ztowQ{-cw44D?ZYnMg@lJ%y2@7)ibEbghWEL8mL_S{lB}SES&O%<8oq^u%`QSKrNOC zAH)Jl(G?6smeHlr9!@eP+^-nzL1MI6QwPONMdcxrhiS-)5;{cEO7Y6Rer;8(O4|m^HaP)fm6uP!88-RoUd#X`#Dj;TCBnm^hbaLJ6f$ho zD6j-$GsNnrcNFPLEpcBb7sAsg;ufhr4LpczYXt*k$Sl;kep1&9z#m2zT_ZZ#Vk+XX zRnB4ph%yNhTqLXE>_{^c!WD>?yplbjNrgxb`hZa@02(7)Niizo5qN@TrPxVzP!<1q zDGXH~{{ALYD<<9)f~1Q`XPCvDv5vp_gOYS=O16<46sfpBq$^4p>W!9wBc-_TQC0H5 ziz6#F=JVbsk-f^Yfc>~Mpb7y3qzvQ^R-Tx4WG3Rw|~7;;TM;JSkh#$BG%mC zZ%c%?SYU@7qGE-GFQJgJ%XSaUz65upKLI_5Ujii*vu~3YS(QVo& ztDK)UlxDd=yE->R&<4BEmI@L#*n1$&v`NYtgCfn(h~{TP&6_MG z%D~x)%wTZ%v(N^lP;l0bS>fCor1KgTIJ zS133)Opu}lA#4xD*t3dU0VaGL!FGLoUzL$;NDOU~LczdslGsFoVw8v&-XSE4O>y5^ zs)$Wlw0S`!3s3^P1xorFja6GuCj zk)k;og-j|S?U>LxZd~XmEh+TlgoNXoV}lZ|!X>6a=sBNrMlL3Fl(LKgz)vI#26-_n z-~>Q&VswZUj$TsazR=-!h(bh8lueQA@I&i!=qe0{FnE1~-*gWrfIBrGfKUmtJPjhS zVYCtl3mZdkLsx*q^B9ifnDxM2hGf&jt+1Mk7_140F%t0C^jfKjo(W&flZB0lia6t7 zpY>Bso|c6kk`E$@gp8B>CU`jAh)|lq8jCz6lD1(Ds%EnmlkP-mN7U#C_#If@qale9 zCx+9|#2!I6n;r>aH6!~(kGO6QsgdZ%xNaiRL+Z!fY4IZLaY|Z{=m)}oOS`lz#8s?^ zLzB@^8#DTG3zxvbZ|~sDs8vRobl}Kbsas?i-4)7;R7k3_&3++yU37;(*cDUZ4nxd6^Sw@Q|*yNZlAspxn*tEXbC%K>F zK5z+bKh4~aiyt2P-78x%+=7oxUd@WhW2q26M1RpYmX$F2*aMJ3JAhrbwu9WR?cgyH z?8W)37Vr>vh=%uY8rVFlY;YKOk1S!aUO<+#n8R>87yFjUaEeX}+ET_?_#4FI(l3pG zgqJdc1*(R}pN$VBi70fy#VIHldn6jlO=N#Fd_cECXvQ}L2r@CA z5q}N|3eYW49~uig;ALKYAr?bR5I~++5B3J6flXo_>-OJ1jHQq}Z8P6AHuJNKVKa%W zoDq@38Vh)7Iy{q%lqjt8Fg8hP97W}@YOli{#D)OKQU^0As8WT-!6?lHO?I1%y0D-} zuo4T%4OvC5BJt%vxGDfoo@+2akBYD?22;F&W=b$-{4GVU-0_LnG=VRTM~uR?94eC% zP7Z55ElgN5`#Q-o2uz4^6!BKaJXzhkegR*s?Yn>? zMc51kXZV|o5J0eJ2M;2YT;J7bSQFyWhjG6UFG>|ylycbxr#fTSBj1Faj zR-Axgxlkrei2Zi>KfErKy%GJ3%|zwALplMvy;H?;;(7-O^wk59r(W3gMqhJig6 zyY&M`D&{Z}&UF(42k~`)A{eC@wz=qwfg^IYwwPO#4-hub)gLehITn2^#OQ9nO1z4?P z1pIYOnhMaq1K5*os9RB(eOVfN=uTSV2E$3PGM&Z2_6$kJf=n`J0tcn4XB1g|Q1K3@ z3O$oFl`4&Rgt=Va0*cp*T3cuWPJm=ZCJk9vhMn;!Y=z=vKn-e8LT#+?5KLZjBAPgu zOgYkMrX19Q^^`-x1eL}YO*tBaq%Z3vp_e&C*x+O$bm|L}l4$02Q#j>ligereW%5b5 zcX9HuIr$*`aN;rF*1_x)d4Npq$ndeb!%bp1P)e$w+Qcvw=((I#LsWh+Ib;J}sfIeB zI-7rA6(5pq@Zf;Fxt-IIS8OI<%yWJKV$0bK<6)o&Rx|&=5a}x=meFYJXokL_XT%s? z=ET{7aISG+dI(RlU(q_pM0quWjou-ILo70B;0v#5)+jKESu;s*XM|E*p93 zq#5Hh(J2}cr~oULDcr@U3P(>B2DWvoFq<2gD)3#GCSLuQOcic4RfMX-DGPnN8Z5x^m$bJx&pIHTZF&nTivqH}<49A%b?9ZYy zjVS`0$)E)Y0>=z3A3{W0up(X}=l3x~w<%8F_@aBA7kH@fS&(1S_gbeAP9T2I-aRER zJ~?@uobXp!8Ge%C6l(&&3Q-qoYIPYO6r8aRiu3N$YcU+Lgk#a1QQro`oHMZVnE@M6 z5e!q$7zqXrEc-ZPB%&FEr`xc!O}hHahxx_0W~zo%v6YC|45(bpMc@m;nA0K}c<2>v z8io}^ZaRTm9_T_NObc%sfETGRlMEE4&*G%0ZH|8jGs$_3sW1*c=`MNGB~K;E3Y1!x zDU^dVwGd(*b9^g2c7=p8B34LkAtYa7R5j-pEbQ6J^eLF!8)$Y|(}a4K$ppulB;Ukv zsF)x;*w|yE37H*p$^kY)mr4uPfT1oht_jnd~q_3;tX7dGReY z5<;kRF8)OInP8oM?;AqXF-WwZ;yD&tVo{DMgESdmnkZkA!x;)2wqeFbWit}U$#qcC zGFD6OM(((m3QD;Mbblb*bDd(Lje&E@#A%la4}>&j0?(oN=y3QR5>SDRm>wn5d0xJ& z$A|?78;n?XB80Bf`-lz`XguKu@^qxhMZRnZqQM806N-WygG+Au#l}Kc$lGZNLAoNM zJEM2VF%l@rTjjLD9khmoBdZn1!AzwpsbI63+Q~o-aQQBY*u@U{3;zkdooBh=c>{aDwaD&7F3k>!Tqc2c^a|B->b}6em%q4L@;$|&23wQ=V z4rEbIMRs$H`*7)Q&Hx3lINacn48%n@cf#`s=6sk=vwhA5(5nf{J??%TM7mHI315*y zWZ(pe1Do844qY0?hxmyH@E=Us-V=BaqM$U7=%M$l<%J2|OSH~E!OK&T;^+9LFBlxW zfrZ5o9+*CD>(eQhEJ6i|5vN?7n8%kxj2tW_A@gm7JZT7df(etZ@E}_f%Lkv5EkQ+y z#0-m=JitkqHBn0ZPrQI$2w54~1bTXgZqZlX1q4HUNl)iYQh-Ec#M=YVdj^(*$I%Y8 zIVl0}YHnF0@PJZ=6N-hiMmKysClyiz0m2;vrB8M;{NiAPlC(zthz`i&vDW6Pn<(){ zC{DqeaDo$Cy<`rrFW}F|gY!}bB(M~Uj6u%YKq7pu)yti045w*qN`e*yL;%D86U~Dn z%sR=C*cJ}(M1f2b0+Tm_hzMhv7f1-yYd{Lm%-}zj$t-1N@RwAdIT!+pjEV2J7GSuX zTBrr+K?(*tPE z8BXO-F~flbM0=yi9g_?jDJ(&aV@2JRYEHc3T{0>aq%eJ@J~+QJ?jd_ZB}hV0hv4<` z%ede%r0hP3@Dt%*)%ddVUcmPzf9Ps>QlEwQMHB8}Im@zE<7eyG_OWWi-!@wvX^c%* z{YtGiU9*DQ0Fz1Kx%><6ZoPdFx9f;u6@Fe{u2!cT{`T7RE`O>rHC@|%tQCA25U(J_ zVfcAdxiMQSPx|%Qt&Lh)k26~xt<<(nPVcgU9|5*V*hBFX)N1A3{urLl`O~uve|nq0 zbsE5RD|p{i3HLa{ZNSgi=;UeT`g#6zbrRrHGn196O0`iLMOXaasMKa^75s)bejeQp zVK)yylhgIF>UJLwN5<;l*9yLg$A|Or8vKk*k5*=;DG)Putz6w+fykbQI0z*Ff-7*F z<*mZcaaM3s{C*hHi{C@y_r>q~t>Cfv{YEQzHhw=~1z(NdA8!SJ8NVO2f`5wNp8yHQ z?>B+mXJYi7Xa!ft?~j2bA2L*;<`Mbzp`TR{5^ zqe!i?4K!6pAd|}6Ol71=yuWR%GCArK=?v_u`%@!#tGkNITkEs6QAkDTGfJ?i9gJHZ z4FlBH*=-=g+69SqYcG%PEQ7!{=(nD8$}yY#o#n}~QEgPT|Jho_vcC9-m?IL^@>IpT zlE<7gkZZMZ?9{Y+`gYttYNuVX#bGg%OnPi&7$JQo>*{$#ZgLp}XSs46aFI`qZLdz( zDutw|enqBM*(p~&-sZ8XsoBPGnK6HOd!^y6*xYj8+X^vRsjiGe;C@y7zFuh@)Z2n{ zqO!Zbx+jK|4QpCqAcp$EaTqonlHJ^>%r%BF#G$Uf967ICtFKL)iDzAIw6b+}``HxF z`a<&>bKPOF+taI!!&fw)z8*M^aBGeFF#L=2kDopdvlyU?IUpJwIAmx0^Z|4Ksk4N9+HiF)-7 zzKXrr&R%_kM@ugQ*Ee`f7Ed=xr(=03SDRk#>Q;8ybev1-G|Z;HT(vA5K_vaWK4%(N zg9952rkz~|2L>XJZHhPo+{XSB2}w$E_nN3z-{7yZSCgZY zB8~vpH~88to`PE3oXktP+VnbCw+cs_LyiEmDbSeZ!BEbyiU+UPGL-gT3)@exHntE` zD9uv@lcDicN-cbHTJ!{cPH*mvljqCTZ)8Rq`s!`j zt&O^V{G0hEY~SE-WesrO;BRLQbl>3Hb0K)&;5%aQ8~cAJgx}czyCM9>{^1CIWB<7^ z_`!j42tPQmHH04=7>VEq2S)SSbEmfrV-Bk{?;x3N%{xeAdm(}(d*?N80lH~yMf4Q6 zeS_mI_Z#~sTJ8r2CY#-Xd(%|&F>dAt8G@29)O;1nGHgBoZot{RB&@((!#tc^9wNkfKE0xi(ZLW!QdWNaTZqp6oG;`?r zO-dz(|DHhu2p!WA&G+Oag&7{Jjx{b=p|6n}%ubdYmAy$>Zp>%pF z%iAj#D#U6X$+mD|LXeA8ZgaJ=Yq(tBT^+et<;Lp6v(>HBbCuCcl$o4%K}_{amCH5B zuwIi~rV>NL+Z&gwzMEx!`10(wX*$cm9CZ> zd~%J3zgA_1gJZ`==ia4OlmT`O^Mzvu29F)MuBBnqu>;q~8;(Ej*nt~b8v2hNxUr>S z;Mjqigv`pj^>FWLd5j_6tJ~ifZyyAn_v`kXTiQXv2Xy-fe^{;QfE=b+?`XjZ`tDRYNhF2|{}B;- zmGA5ehm&hr1Ele5`LrOCt|ng_(|nPPdA{2oW-GImXH~M^DAyX#sr1P7 zW+DxrS1w2g#BhD={K^+prn0jY^sOjfq`^=}%Ml}_dBYDK-J;ZM{`CeOpO zm{<^`^t1n?R!Ji)nvJH%pDGWks#l=C$>Ho@>$QhQb z|1S-c+|>U{Wv6CD0@EXZt#Y`=SX|A0L#1)EtyZagQ+XzP#^{vl#{R!i2e&st5!1OMAD?aa*oPOa~N*O(+j|NHiCg9C!@AG)*?-9NUY1AGkKKee+m zIPlNytVBKjMP&_Xl^x%Xt|uGciLSRd{x!Outb8}R-d_10{7@=a4CddDZV;*eZ*(&? zJNbj?1|jB$(G7g_N6`&D_s7u1et`hVH|vWXwGY@C#3W(*gEBf8BcZpLcF5pE!a9?UTLtgPWO-`lwk8c!-t7WY znHxFp!v>~OuH7MxB=JtW0JKdz`iRZ20kIDEkA763YW4F*?~<-;9lcusz$*Ygrh%tN zaea^N3AtO#lU(={#l3bxnowz(;{AQ``}&UB{q{JRC9D|A<@)gO5g+ z8y^!{!1+cWm#eYrNbL!^f^pYAEr2l3;n64M65I@re#XvCj#Vf0#Ag4~1E^zQ22_@+ zW|ZaB8?~&Jv*kiLSns<@D=~sPvC15U37|an>f>xR=csZ*mGgGnqdrtDHL#kq)ow?P zC0xuEGsAlFOiGfO>Xpe|HyyLF@7Rrf=`=G~_*W*&d})~DWgS4QSU$eNV>b>gimxZp zMsdGw&()n(&2)pAtBmipgAR0nBBK=0-geNzc2H)!0=lvt^n?yjN9#tk9@Wu0fYw)Zpa$1O{YxF-V7&Uv z9j#!zx}l>Lj8|XTff|ex^{=#pZv@ZPS9P?K$)h`3$>A~Ws5g>Bpgy((oJ_vDqm@h^ z*U?H2`#MmQL!j>O04I|hJ6g%)Kzr)|IXu1{^?*_1U-Kwga_MH8F{lOp^Mvv1w9vH=*(eZ$6qsN&Y z4-DsT=y+f_e`Ci3!}*&!9vIHg>Udx{KfB|B;rz|*S{elBBfs9>dIH$q^_FmE53TbA z@I2zEkwk*|?l~Qu!1=DXcC>=+UBA)M3Z8epEu>QIvQyu+|zLJYfptD_Y% z*!9~Ttq{Pjw|B++jt*GJWY_O>v_c@eez(1K69qEd74Nwnun^O(az`trv$dm@(i!QB zcQlsU$QMAeSd?W|xzd3hQl8t^(F%FaZSQD>Jm=2q zXoWoI#yVOdxw-L0OaM{2W;U2X>w2xFN@GTHK^!Iy1b=9-stSu={-1}>c@Rf!l?NwquGBrI)j z+no_6c87_KnzYq6N6jVdZF5O^bbg_UmkF~NXCk?6tX6L%Q%6J4^-kJ+_!O<3pw5 zHy5du22rY3sbhg@$Dca(M7?!&X4mR1{nKH6H6!KKY*;tVg{w6;yvWB97sA#R@z$Qa zDb`9>?`2uAmCN3|DaXp)#R?12xl8!Fda1%Pbf!^L`5Eke)KN;Wj8;Z3L#rw)we@n9 z&=)qsW8F#O*WkbvDl+0RS%HoxLUNLEa;^-qyt5mYt7QDE0b^JDlwIw=Mul^w60{-C z76D!h_@r#~C`UF#!am{3S+8;wOt5@igfM(~yexs_;q{Saz}IY5zM<{@#;CIrvj!AU z-W0O*?iLwLI%*LayhnvIkPI`{Vzdc0X_o6Duc2qRuF&7RpM$;cKn(VN6^3G}VbT%C z$CDw2DOFC#m3;Go81nwI4p>X4I4bMF(+RWIOe^4R8^`B-#{jQ zUn^7G32S-&@z&c1T5liJ#0av7V%MLDU4Jrm{V5^gVT?(&C^h#;$n~Q{%*YfENRMgd zsNJ?Y-$|fHUxL5;AMXbI1my-zvTh(#a4n&#Nj3Iqm1R4S2nNB^pWygORZgj`Y1Zz> zo&=Q%9ECeh@poTKwEql<)CSX>u1@%Dm&Q$>i)M``B+5w>b;ryi3Ct5o)krm`_;hTF z&ot-vtTRy`ZcY|)JKUcMBlK!7-mzDh*w;xT%UJC+R`!QRZ0f!&G(OcijrSqrn{X(V zglg!-N@q4tcY#HUS#umvmr#{B>@#YO(WIIn2&ZwQnIvcMMbx4i*`{W4s?w2%6-2Tt zNL>$y^+Nggu5MOGH_EQ6%+xEx=c`(tbBk4;AC$$3LY@1rZeBhMvkyDsG=Z-AwpeOQ z@On-iYM9a)9M zZOnB*RbI^%LXZ`z+M~uiRqa({D^+!s8as#}t5tQ48hakTo-NOe@%+O` Date: Thu, 9 Jan 2020 22:47:45 +0100 Subject: [PATCH 0902/1176] implement crc32 hashing on blobs (#1089) * implement crc32 hashing on blobs (codegen) * add interpreter support * augment existing tests --- default.nix | 1 + rts/text.c | 41 ++++++++++++++++++++++++++ src/codegen/compile.ml | 5 ++++ src/mo_values/dune | 2 +- src/mo_values/prim.ml | 2 ++ src/prelude/prelude.ml | 1 + test/run-drun/caller.mo | 9 ++++-- test/run-drun/ok/caller.drun-run.ok | 1 + test/run-drun/ok/caller.ic-stub-run.ok | 2 ++ test/run/caller.mo | 8 +++-- 10 files changed, 67 insertions(+), 5 deletions(-) diff --git a/default.nix b/default.nix index c92f8da61dd..dea80936176 100644 --- a/default.nix +++ b/default.nix @@ -91,6 +91,7 @@ let commonBuildInputs = pkgs: pkgs.dune pkgs.ocamlPackages.ocaml pkgs.ocamlPackages.atdgen + pkgs.ocamlPackages.checkseum pkgs.ocamlPackages.findlib pkgs.ocamlPackages.menhir pkgs.ocamlPackages.num diff --git a/rts/text.c b/rts/text.c index afab1543cfc..819351a55c7 100644 --- a/rts/text.c +++ b/rts/text.c @@ -323,3 +323,44 @@ export uint32_t text_iter_next(text_iter_t i) { return c; } } + +// CRC32 for blobs + +// loosely based on https://rosettacode.org/wiki/CRC-32#Implementation_2 +// +export uint32_t compute_crc32(blob_t b) +{ + if (TAG(b) != TAG_BLOB) rts_trap_with("compute_crc32: Blob expected"); + + uint32_t crc = 0; + const char *buf = BLOB_PAYLOAD(b); + size_t len = BLOB_LEN(b); + + static uint32_t const table[256] = { + 0x0, 0x77073096, 0xee0e612c, 0x990951ba, 0x76dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0xedb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x9b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x1db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x6b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0xf00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x86d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x3b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x4db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0xd6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0xa00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x26d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x5005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0xcb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0xbdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d + }; + + crc = ~crc; + const char *q = buf + len; + for (const char *p = buf; p < q; p++) { + uint8_t octet = *p; /* Cast to unsigned octet. */ + crc = (crc >> 8) ^ table[(crc & 0xff) ^ octet]; + } + + return ~crc; +} diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 752e27616ab..4339d265848 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -664,6 +664,7 @@ module RTS = struct E.add_func_import env "rts" "text_size" [I32Type] [I32Type]; E.add_func_import env "rts" "text_to_buf" [I32Type; I32Type] []; E.add_func_import env "rts" "blob_of_ic_url" [I32Type] [I32Type]; + E.add_func_import env "rts" "compute_crc32" [I32Type] [I32Type]; () end (* RTS *) @@ -5979,6 +5980,10 @@ and compile_exp (env : E.t) ae exp = SR.Vanilla, ClosureTable.size env ^^ Prim.prim_word32toNat env + | OtherPrim "crc32Hash", [e] -> + SR.UnboxedWord32, + compile_exp_vanilla env ae e ^^ + E.call_import env "rts" "compute_crc32" | OtherPrim "idlHash", [e] -> SR.Vanilla, diff --git a/src/mo_values/dune b/src/mo_values/dune index 85cf9c0d448..6b5b7c20325 100644 --- a/src/mo_values/dune +++ b/src/mo_values/dune @@ -1,4 +1,4 @@ (library (name mo_values) - (libraries num wasm lib lang_utils mo_types idllib) + (libraries num wasm lib lang_utils mo_types idllib checkseum) ) diff --git a/src/mo_values/prim.ml b/src/mo_values/prim.ml index 8993cfdeeb3..1c7329be7d9 100644 --- a/src/mo_values/prim.ml +++ b/src/mo_values/prim.ml @@ -246,6 +246,8 @@ let prim = function | "rts_total_allocation" -> fun _ v k -> as_unit v; k (Int (Int.of_int 0)) | "rts_outstanding_callbacks" -> fun _ v k -> as_unit v; k (Int (Int.of_int 0)) | "idlHash" -> fun _ v k -> let s = as_text v in k (Word32 (Lib.Uint32.to_int32 (Idllib.IdlHash.idl_hash s))) + | "crc32Hash" -> fun _ v k -> let s = as_text v in + k (Word32 Optint.(to_int32 (Checkseum.Crc32.digest_string s 0 (String.length s) zero))) | "array_len" -> fun _ v k -> k (Int (Int.of_int (Array.length (Value.as_array v)))) | "text_len" -> fun _ v k -> diff --git a/src/prelude/prelude.ml b/src/prelude/prelude.ml index 2c1a01ababa..7511ffbfd3c 100644 --- a/src/prelude/prelude.ml +++ b/src/prelude/prelude.ml @@ -119,6 +119,7 @@ func hashInt(x : Int) : Word32 { return hash; }; +func hashBlob(b : Blob) : Word32 { (prim "crc32Hash" : Blob -> Word32) b }; // Conversions diff --git a/test/run-drun/caller.mo b/test/run-drun/caller.mo index b0991f1f3e1..2dbe31b5472 100644 --- a/test/run-drun/caller.mo +++ b/test/run-drun/caller.mo @@ -1,6 +1,6 @@ actor a { - public shared ctxt func c1 () : async () { + public shared ctxt func c1 () : async () { let c : Blob = ctxt.caller; return; }; @@ -27,10 +27,14 @@ actor a { return; }; - public shared {caller} func c7() : async Blob { + public shared {caller} func c7() : async Blob { return caller; }; + public shared query {caller} func c8() : async Word32 { + hashBlob caller; + }; + }; ignore a.c1(); //OR-CALL ingress c1 0x4449444C0000 @@ -39,6 +43,7 @@ ignore a.c3(); //OR-CALL ingress c3 0x4449444C0000 ignore a.c4(); //OR-CALL ingress c4 0x4449444C0000 ignore a.c6(); //OR-CALL query c6 0x4449444C0000 ignore a.c7(); //OR-CALL ingress c7 0x4449444C0000 +ignore a.c8(); //OR-CALL query c8 0x4449444C0000 diff --git a/test/run-drun/ok/caller.drun-run.ok b/test/run-drun/ok/caller.drun-run.ok index 3509aab2a35..257ddcc26b4 100644 --- a/test/run-drun/ok/caller.drun-run.ok +++ b/test/run-drun/ok/caller.drun-run.ok @@ -5,3 +5,4 @@ ingress(3) Completed: Canister: Payload: 0x4449444c0000 ingress(4) Completed: Canister: Payload: 0x4449444c0000 Ok: Payload: 0x4449444c0000 ingress(6) Completed: Canister: Payload: 0x4449444c016d7b0100080000000000000000 +Ok: Payload: 0x4449444c00017969df2265 diff --git a/test/run-drun/ok/caller.ic-stub-run.ok b/test/run-drun/ok/caller.ic-stub-run.ok index b49bf45f6ac..9fda4c73e75 100644 --- a/test/run-drun/ok/caller.ic-stub-run.ok +++ b/test/run-drun/ok/caller.ic-stub-run.ok @@ -14,3 +14,5 @@ ← completed: 0x4449444c0000 → update c7(0x4449444c0000) ← completed: 0x4449444c016d7b010003caffee +→ query c8(0x4449444c0000) +← completed: 0x4449444c00017989f8efb7 diff --git a/test/run/caller.mo b/test/run/caller.mo index 54504e6a2e1..896c74bf183 100644 --- a/test/run/caller.mo +++ b/test/run/caller.mo @@ -1,9 +1,13 @@ actor a { - public shared { caller = c } func getCaller() : async Blob { + public shared { caller = c } func getCaller() : async Blob { return c; }; + public shared query { caller = c } func getCallerHash() : async Word32 { + hashBlob c; + }; + public shared {caller} func c () : async () { let self1 = await getCaller(); let self2 = await getCaller(); @@ -14,4 +18,4 @@ actor a { }; ignore a.c(); //OR-CALL ingress c 0x4449444C0000 - +ignore a.getCallerHash(); //OR-CALL ingress getCallerHash 0x4449444C0000 From ea1626a9346c916863edab2aa7fa32145ef72a49 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 10 Jan 2020 10:42:29 +0100 Subject: [PATCH 0903/1176] Bump drun (`--extra-batches`) (#1086) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is an attempt to make `drun` more reproducible: Wait for a specified number of extra rounds (“batches”), building on https://github.com/dfinity-lab/dfinity/pull/2234 Not sure why one extra rounds seems to suffice, though. Other commits picked up: ``` 64cdcb2a0 Merge pull request #2228 from dfinity-lab/rust-wasm-1 cfc6afd25 Merge pull request #2230 from dfinity-lab/CON-218 0698263fe Merge pull request #2240 from dfinity-lab/basvandijk/fix-RUSTSEC-2019-0033 fd64793ba Merge pull request #2242 from dfinity-lab/FixThreshold 81aee49b0 Merge pull request #2204 from dfinity-lab/manu/consensus/realistic-timeouts 57decda2f DFN-588/1262: Upgrade to dalek 1.0.0-pre.3 and rand 0.7 (#2205) 9e5998fcc Merge pull request #2217 from dfinity-lab/eftychis-fix-source 123ad4850 drun: support --extra-batches (#2234) ce06888f5 Merge pull request #2232 from dfinity-lab/nm-cargo-audit-local d02b60d6d Squashed crypto/cli from f9f31966c52ae867ee9ee464a4ae9d99659ac99d (#2183) 11a91f7bc Merge pull request #2181 from dfinity-lab/paulliu/consensus-test-timestamp ``` --- default.nix | 2 +- test/drun-wrapper.sh | 2 +- test/ic-stub-run-wrapper.sh | 22 ++++++++++++++++++++++ test/run.sh | 4 ++-- 4 files changed, 26 insertions(+), 4 deletions(-) create mode 100755 test/ic-stub-run-wrapper.sh diff --git a/default.nix b/default.nix index dea80936176..4cb34d7ed5b 100644 --- a/default.nix +++ b/default.nix @@ -36,7 +36,7 @@ let dfinity-src = name = "dfinity-sources"; url = "ssh://git@github.com/dfinity-lab/dfinity"; # ref = "master"; - rev = "dfc8aa148021534ad01d321d1f2a843ab2933fa3"; + rev = "502ff80e26ac5a6cf10ae3f92fdea70de7d1f58e"; }; in let dfinity-pkgs = import dfinity-src { inherit (nixpkgs) system; }; in diff --git a/test/drun-wrapper.sh b/test/drun-wrapper.sh index 322054d62e2..e4888df2186 100755 --- a/test/drun-wrapper.sh +++ b/test/drun-wrapper.sh @@ -19,4 +19,4 @@ export LANG=C.UTF-8 (echo "install 1125899906842624 $1 0x"; if [ -n "$2" ]; then LANG=C perl -ne 'print "$1 1125899906842624 $2\n" if m,^//CALL (ingress|query) (.*),' $2; fi; -) | $DRUN -c "$CONFIG" /dev/stdin +) | $DRUN -c "$CONFIG" --extra-batches 1 /dev/stdin diff --git a/test/ic-stub-run-wrapper.sh b/test/ic-stub-run-wrapper.sh new file mode 100755 index 00000000000..170cbc24c1e --- /dev/null +++ b/test/ic-stub-run-wrapper.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +IC_STUB_RUN=${IC_STUB_RUN:-ic-stub-run} +CONFIG=$(realpath $(dirname $0)/drun.toml) + + + +if [ -z "$1" ] +then + echo "Usage: $0 .wasm [call-script]" + exit 1 +fi + +export LANG=C.UTF-8 + +# canister id "ic:000000000000040054", in little-endian decimal, is: +# 1125899906842624 +# (drun currently expects a decimal number for the canister id) + +(echo "install 1125899906842624 $1 0x"; + if [ -n "$2" ]; then LANG=C perl -ne 'print "$1 1125899906842624 $2\n" if m,^//CALL (ingress|query) (.*),' $2; fi; +) | $IC_STUB_RUN -c "$CONFIG" /dev/stdin diff --git a/test/run.sh b/test/run.sh index d4e1fdadf94..3b120a5af4c 100755 --- a/test/run.sh +++ b/test/run.sh @@ -31,6 +31,7 @@ export MO_LD WASMTIME=${WASMTIME:-wasmtime} WASMTIME_OPTIONS="--disable-cache --cranelift" DRUN_WRAPPER=$(realpath $(dirname $0)/drun-wrapper.sh) +IC_STUB_RUN_WRAPPER=$(realpath $(dirname $0)/ic-stub-run-wrapper.sh) IC_STUB_RUN=${IC_STUB_RUN:-ic-stub-run} SKIP_RUNNING=${SKIP_RUNNING:-no} ONLY_TYPECHECK=no @@ -290,8 +291,7 @@ do if [ $DRUN = yes ] then run_if wasm drun-run $DRUN_WRAPPER $out/$base.wasm $mangled - DRUN=$IC_STUB_RUN \ - run_if stub.wasm ic-stub-run $DRUN_WRAPPER $out/$base.stub.wasm $mangled + run_if stub.wasm ic-stub-run $IC_STUB_RUN_WRAPPER $out/$base.stub.wasm $mangled elif [ $PERF = yes ] then run_if wasm drun-run $DRUN_WRAPPER $out/$base.wasm $mangled From d1741b14ad364462006f59cc0db20aff3f1747e8 Mon Sep 17 00:00:00 2001 From: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> Date: Fri, 10 Jan 2020 13:26:01 +0100 Subject: [PATCH 0904/1176] Use OCaml 4.08 Stdlib additions (#1087) * Use 4.08 stdlib's Option module over our own * Use 4.08's new Stdlib.Fun module * Use 4.08's filter_map Co-authored-by: Gabor Greif --- src/codegen/compile.ml | 2 +- src/codegen/instrList.ml | 4 +-- src/ir_interpreter/interpret_ir.ml | 14 ++++---- src/languageServer/completion.ml | 14 ++++---- src/languageServer/completion_test.ml | 4 +-- src/languageServer/declaration_index.ml | 14 ++++---- src/languageServer/definition.ml | 10 +++--- src/languageServer/hover.ml | 6 ++-- src/languageServer/hover_tests.ml | 2 +- src/languageServer/source_file.ml | 6 ++-- src/languageServer/source_file_tests.ml | 2 +- src/languageServer/vfs.ml | 2 +- src/lib/lib.ml | 46 +++---------------------- src/lib/lib.mli | 12 ------- src/linking/linkModule.ml | 2 +- src/lowering/desugar.ml | 4 +-- src/mo_frontend/traversals.ml | 2 +- src/mo_frontend/typing.ml | 4 +-- src/mo_interpreter/interpret.ml | 12 +++---- src/mo_types/con.ml | 1 - src/pipeline/pipeline.ml | 8 ++--- src/pipeline/url.ml | 2 +- src/wasm-exts/customModuleDecode.ml | 2 +- src/wasm-exts/customModuleEncode.ml | 2 +- 24 files changed, 63 insertions(+), 114 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 4339d265848..51ac560b554 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -3652,7 +3652,7 @@ module Serialization = struct let check_prim_typ t = get_idltyp ^^ - compile_eq_const (Int32.of_int (- (Lib.Option.value (to_idl_prim t)))) + compile_eq_const (Int32.of_int (- (Option.get (to_idl_prim t)))) in let assert_prim_typ t = diff --git a/src/codegen/instrList.ml b/src/codegen/instrList.ml index 5155e1f7ac4..f9157172cb8 100644 --- a/src/codegen/instrList.ml +++ b/src/codegen/instrList.ml @@ -48,8 +48,8 @@ let optimize : instr list -> instr list = fun is -> (* Constant shifts can be combined *) | {it = Binary (I32 I32Op.(Shl|ShrS|ShrU) as opl); _} :: {it = Const cl; _} :: l', ({it = Const cr; _} as const) :: ({it = Binary opr; _} as op) :: r' - when Lib.Option.is_some (combine_shifts const op (opl, cl, opr, cr.it)) -> - go l' (Lib.Option.value (combine_shifts const op (opl, cl, opr, cr.it)) @ r') + when Option.is_some (combine_shifts const op (opl, cl, opr, cr.it)) -> + go l' (Option.get (combine_shifts const op (opl, cl, opr, cr.it)) @ r') (* Null shifts can be eliminated *) | l', {it = Const {it = I32 0l; _}; _} :: {it = Binary (I32 I32Op.(Shl|ShrS|ShrU)); _} :: r' -> go l' r' diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index 3a67ecd122c..d8a5229ae37 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -377,12 +377,12 @@ and interpret_exp_mut env exp (k : V.value V.cont) = ) | ICReplyPrim ts, [exp1] -> assert (not env.flavor.has_async_typ); - let reply = Lib.Option.value env.replies in + let reply = Option.get env.replies in interpret_exp env exp1 (fun v -> Scheduler.queue (fun () -> reply v)) | ICRejectPrim, [exp1] -> assert (not env.flavor.has_async_typ); - let reject = Lib.Option.value env.rejects in + let reject = Option.get env.rejects in interpret_exp env exp1 (fun v -> let e = V.Tup [V.Variant ("error", V.unit); v] in @@ -478,9 +478,9 @@ and interpret_exp_mut env exp (k : V.value V.cont) = | BreakE (id, exp1) -> interpret_exp env exp1 (find id env.labs) | RetE exp1 -> - interpret_exp env exp1 (Lib.Option.value env.rets) + interpret_exp env exp1 (Option.get env.rets) | ThrowE exp1 -> - interpret_exp env exp1 (Lib.Option.value env.throws) + interpret_exp env exp1 (Option.get env.throws) | AsyncE exp1 -> assert env.flavor.has_await; async env @@ -493,7 +493,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = | AwaitE exp1 -> assert env.flavor.has_await; interpret_exp env exp1 - (fun v1 -> await env exp.at (V.as_async v1) k (Lib.Option.value env.throws)) + (fun v1 -> await env exp.at (V.as_async v1) k (Option.get env.throws)) | AssertE exp1 -> interpret_exp env exp1 (fun v -> if V.as_bool v @@ -610,7 +610,7 @@ and interpret_cases env cases at v (k : V.value V.cont) = and interpret_catches env cases at v (k : V.value V.cont) = match cases with | [] -> - Lib.Option.value env.throws v (* re-throw v *) + Option.get env.throws v (* re-throw v *) | {it = {pat; exp}; at; _}::cases' -> match match_pat pat v with | Some ve -> interpret_exp (adjoin_vals env ve) exp k @@ -766,7 +766,7 @@ and match_pat_fields pfs vs ve : val_env option = and interpret_block env ro decs exp k = let ve = declare_decs decs V.Env.empty in - Lib.Option.iter (fun r -> r := ve) ro; + Option.iter (fun r -> r := ve) ro; let env' = adjoin_vals env ve in interpret_decs env' decs (fun _ -> interpret_exp env' exp k) diff --git a/src/languageServer/completion.ml b/src/languageServer/completion.ml index ca34d2c65b8..750c11dcd45 100644 --- a/src/languageServer/completion.ml +++ b/src/languageServer/completion.ml @@ -64,9 +64,9 @@ let import_relative_to_project_root root module_path dependency = | Some root_to_module -> root_to_module |> Filename.dirname - |> Lib.Fun.flip Filename.concat dependency + |> Fun.flip Filename.concat dependency |> Lib.FilePath.normalise - |> Lib.Option.some + |> Option.some (* Given a source file and a cursor position in that file, figure out the prefix relevant to searching completions. For example, given: @@ -119,7 +119,7 @@ let has_prefix (prefix : string) (ide_decl : DI.ide_decl): bool = ide_decl |> DI.name_of_ide_decl |> Lib.String.chop_prefix prefix - |> Lib.Option.is_some + |> Option.is_some let opt_bind f = function | None -> None @@ -144,8 +144,8 @@ let completions index logger project_root file_path file_contents line column = let toplevel = current_uri_opt |> opt_bind (fun uri -> DI.lookup_module uri index) - |> Lib.Option.map (List.map item_of_ide_decl) - |> Lib.Fun.flip Lib.Option.get [] in + |> Option.map (List.map item_of_ide_decl) + |> Fun.flip Lib.Option.get [] in imported |> List.map (fun (alias, _) -> module_alias_completion_item alias) |> List.append toplevel @@ -154,11 +154,11 @@ let completions index logger project_root file_path file_contents line column = idenfiers of the current module *) current_uri_opt |> opt_bind (fun uri -> DI.lookup_module uri index) - |> Lib.Option.map (fun decls -> + |> Option.map (fun decls -> decls |> List.filter (has_prefix prefix) |> List.map item_of_ide_decl) - |> Lib.Fun.flip Lib.Option.get [] + |> Fun.flip Lib.Option.get [] | Some (alias, prefix) -> let module_path = imported diff --git a/src/languageServer/completion_test.ml b/src/languageServer/completion_test.ml index 381c74e3e3e..bdf654b84ae 100644 --- a/src/languageServer/completion_test.ml +++ b/src/languageServer/completion_test.ml @@ -23,7 +23,7 @@ let prefix_test_case file expected = | Some (m, p) -> "Some (" ^ m ^ ", " ^ p ^ ")" in let actual = Completion.find_completion_prefix dummy_logger file line column in - Lib.Option.equal (=) actual expected || + Option.equal (=) actual expected || (Printf.printf "\nExpected: %s\nActual: %s\n" (show expected) @@ -36,7 +36,7 @@ let import_relative_test_case root module_path import expected = let show = function | None -> "None" | Some s -> "Some " ^ s in - Lib.Option.equal String.equal actual expected || + Option.equal String.equal actual expected || (Printf.printf "\nExpected: %s\nActual: %s\n" (show expected) diff --git a/src/languageServer/declaration_index.ml b/src/languageServer/declaration_index.ml index 28482710a7a..1de1bfa8a31 100644 --- a/src/languageServer/declaration_index.ml +++ b/src/languageServer/declaration_index.ml @@ -28,7 +28,7 @@ let string_of_ide_decl = function ^ ", typ = " ^ Type.string_of_typ value.typ ^ Lib.Option.get - (Lib.Option.map + (Option.map (fun pos -> ", definition = " ^ string_of_region pos) value.definition) "" @@ -39,7 +39,7 @@ let string_of_ide_decl = function ^ ", typ = " ^ Type.string_of_con ty.typ ^ Lib.Option.get - (Lib.Option.map + (Option.map (fun pos -> ", definition = " ^ string_of_region pos) ty.definition) "" @@ -62,7 +62,7 @@ let lookup_module match parse path with | Ok (Relative path) -> Index.find_opt path index | Ok (Package (pkg, path)) -> - Lib.Option.bind + Option.bind (Flags.M.find_opt pkg !Flags.package_urls) (fun pkg_path -> Index.find_opt (Filename.concat pkg_path path) index) @@ -110,7 +110,7 @@ let read_single_module_lib (ty: Type.typ): ide_decl list option = | typ -> ValueDecl { name; typ; definition = None } ) ) - |> Lib.Option.some + |> Option.some | _ -> None let unwrap_module_ast (lib : Syntax.lib): Syntax.exp_field list option = @@ -144,7 +144,7 @@ let populate_definitions let fields = Lib.Option.get (unwrap_module_ast lib) [] in let positioned_binder = fields - |> Lib.List.map_filter is_let_bound + |> List.filter_map is_let_bound |> List.fold_left extract_binders PatternMap.empty |> PatternMap.find_opt value.name in @@ -153,7 +153,7 @@ let populate_definitions let fields = Lib.Option.get (unwrap_module_ast lib) [] in let type_definition = fields - |> Lib.List.map_filter is_type_def + |> List.filter_map is_type_def |> Lib.List.first_opt (fun ty_id -> if ty_id.it = typ.name then Some ty_id.at @@ -181,7 +181,7 @@ let make_index_inner vfs entry_points : t Diag.result = path (ty |> read_single_module_lib - |> Lib.Fun.flip Lib.Option.get [] + |> Fun.flip Lib.Option.get [] |> populate_definitions libs path) acc) scope.Scope.lib_env diff --git a/src/languageServer/definition.ml b/src/languageServer/definition.ml index e98ea629528..815c4818cdf 100644 --- a/src/languageServer/definition.ml +++ b/src/languageServer/definition.ml @@ -35,7 +35,7 @@ let definition_handler file_path = let result = let open Source_file in - Lib.Option.bind + Option.bind (Source_file.identifier_at_pos project_root file_path @@ -47,20 +47,20 @@ let definition_handler | Resolved resolved -> DI.lookup_module resolved.path index |> opt_bind (find_named resolved.ident) - |> Lib.Option.map (fun loc -> (resolved.path, loc)) + |> Option.map (fun loc -> (resolved.path, loc)) | Ident ident -> Lib.FilePath.relative_to project_root file_path |> opt_bind (fun uri -> DI.lookup_module uri index |> opt_bind (find_named ident) - |> Lib.Option.map (fun loc -> (uri, loc)) + |> Option.map (fun loc -> (uri, loc)) )) in let location = - Lib.Option.map (fun (path, region) -> + Option.map (fun (path, region) -> Lsp. { location_uri = if Source_file.is_package_path path - then Lib.Option.value (Source_file.uri_for_package path) + then Option.get (Source_file.uri_for_package path) else Vfs.uri_from_file path; location_range = range_of_region region }) result in diff --git a/src/languageServer/hover.ml b/src/languageServer/hover.ml index 835fc1a9747..c990e111c27 100644 --- a/src/languageServer/hover.ml +++ b/src/languageServer/hover.ml @@ -15,7 +15,7 @@ let markup_content (msg : string) : Lsp.markup_content = let hover_handler index position file_contents project_root file_path = let hover_result = - Lib.Option.bind + Option.bind (Source_file.identifier_at_pos project_root file_path @@ -26,11 +26,11 @@ let hover_handler index position file_contents project_root file_path = Some Lsp.{ hover_result_contents = markup_content path } | Source_file.Resolved resolved -> lookup_module resolved.Source_file.path index - |> Lib.Fun.flip Lib.Option.bind (fun decls -> + |> Fun.flip Option.bind (fun decls -> List.find_opt (fun d -> name_of_ide_decl d = resolved.Source_file.ident) decls) - |> Lib.Option.map (fun ide_decl -> + |> Option.map (fun ide_decl -> Lsp.{ hover_result_contents = markup_content (hover_detail ide_decl) }) | Source_file.Ident _ -> diff --git a/src/languageServer/hover_tests.ml b/src/languageServer/hover_tests.ml index 189f9f37108..6ab38d1bcfa 100644 --- a/src/languageServer/hover_tests.ml +++ b/src/languageServer/hover_tests.ml @@ -24,7 +24,7 @@ let hovered_identifier_test_case file expected = let actual = Source_file.cursor_target_at_pos Lsp.{ position_line = line; position_character = column } file in - Lib.Option.equal (=) actual expected || + Option.equal (=) actual expected || (Printf.printf "\nExpected: %s\nActual: %s\n" (show expected) diff --git a/src/languageServer/source_file.ml b/src/languageServer/source_file.ml index 91cc08a4668..76fa8145570 100644 --- a/src/languageServer/source_file.ml +++ b/src/languageServer/source_file.ml @@ -68,9 +68,9 @@ let import_relative_to_project_root root module_path dependency = | Some root_to_module -> root_to_module |> Filename.dirname - |> Lib.Fun.flip Filename.concat dependency + |> Fun.flip Filename.concat dependency |> Lib.FilePath.normalise - |> Lib.Option.some + |> Option.some (* Given the source of a module, figure out under what names what modules have been imported. Normalizes the imported modules @@ -117,7 +117,7 @@ let identifier_at_pos project_root file_path file_contents position = file_path file_contents in cursor_target_at_pos position file_contents - |> Lib.Option.map (function + |> Option.map (function | CIdent s -> (match List.find_opt (fun (alias, _) -> alias = s) imported with | None -> Ident s diff --git a/src/languageServer/source_file_tests.ml b/src/languageServer/source_file_tests.ml index eab90417053..a1946b40d5f 100644 --- a/src/languageServer/source_file_tests.ml +++ b/src/languageServer/source_file_tests.ml @@ -24,7 +24,7 @@ let hovered_identifier_test_case file expected = let actual = Source_file.cursor_target_at_pos Lsp.{ position_line = line; position_character = column } file in - Lib.Option.equal (=) actual expected || + Option.equal (=) actual expected || (Printf.printf "\nExpected: %s\nActual: %s\n" (show expected) diff --git a/src/languageServer/vfs.ml b/src/languageServer/vfs.ml index 534ec4d9a25..f121724de5b 100644 --- a/src/languageServer/vfs.ml +++ b/src/languageServer/vfs.ml @@ -45,7 +45,7 @@ let open_file did_open_params vfs = let read_file uri vfs = VfsStore.find_opt uri vfs - |> Lib.Option.map (String.concat "\n") + |> Option.map (String.concat "\n") let close_file did_close_params = let uri = diff --git a/src/lib/lib.ml b/src/lib/lib.ml index 6ceb3cbdb81..f7b1d0d6ecd 100644 --- a/src/lib/lib.ml +++ b/src/lib/lib.ml @@ -1,8 +1,5 @@ module Fun = struct - let id x = x - let flip f x y = f y x - let curry f x y = f (x, y) let uncurry f (x, y) = f x y @@ -26,7 +23,7 @@ module Uint32 = struct type t = int32 let of_string str = Int32.of_string ("0u" ^ str) - let of_string_opt str = Int32.of_string_opt ("0u" ^ str) + let of_string_opt str = Int32.of_string_opt ("0u" ^ str) let to_string n = Printf.sprintf "%lu" n let add = Int32.add let sub = Int32.sub @@ -249,13 +246,6 @@ struct let index_of x = index_where ((=) x) - let rec map_filter f = function - | [] -> [] - | x::xs -> - match f x with - | None -> map_filter f xs - | Some y -> y :: map_filter f xs - let rec compare f xs ys = match xs, ys with | [], [] -> 0 @@ -386,38 +376,10 @@ end module Option = struct - let equal p x y = - match x, y with - | Some x', Some y' -> p x' y' - | None, None -> true - | _, _ -> false - let get o x = match o with | Some y -> y | None -> x - - let value = function - | Some x -> x - | None -> raise Not_found - - let map f = function - | Some x -> Some (f x) - | None -> None - - let iter f = function - | Some x -> f x - | None -> () - - let some x = Some x - - let bind x f = match x with - | Some x -> f x - | None -> None - - let is_some x = x <> None - - let is_none x = x = None end module Promise = @@ -438,7 +400,7 @@ module FilePath = struct let normalise file_path = let has_trailing_slash = - Option.is_some (String.chop_suffix "/" file_path) in + Stdlib.Option.is_some (String.chop_suffix "/" file_path) in let has_leading_slash = not (Filename.is_relative file_path) in let acc = Stack.create () in String.split file_path '/' @@ -455,7 +417,7 @@ struct let prefix = if has_leading_slash then "/" else "" in prefix ^ (if has_trailing_slash then result - else Option.value (String.chop_suffix "/" result)) + else Stdlib.Option.get (String.chop_suffix "/" result)) let relative_to base path = String.chop_prefix @@ -504,7 +466,7 @@ struct let show = function | None -> "None" | Some s -> "Some " ^ s in - Option.equal Stdlib.String.equal actual expected || + Stdlib.Option.equal Stdlib.String.equal actual expected || (Printf.printf "\nExpected: %s\nActual: %s\n" (show expected) diff --git a/src/lib/lib.mli b/src/lib/lib.mli index 09892d695c5..03a896128ba 100644 --- a/src/lib/lib.mli +++ b/src/lib/lib.mli @@ -2,9 +2,6 @@ module Fun : sig - val id : 'a -> 'a - val flip : ('a -> 'b -> 'c) -> 'b -> 'a -> 'c - val curry : ('a * 'b -> 'c) -> ('a -> 'b -> 'c) val uncurry : ('a -> 'b -> 'c) -> ('a * 'b -> 'c) @@ -27,7 +24,6 @@ sig val index_of : 'a -> 'a list -> int option val index_where : ('a -> bool) -> 'a list -> int option - val map_filter : ('a -> 'b option) -> 'a list -> 'b list val first_opt : ('a -> 'b option) -> 'a list -> 'b option val compare : ('a -> 'a -> int) -> 'a list -> 'a list -> int @@ -81,15 +77,7 @@ end module Option : sig - val equal : ('a -> 'a -> bool) -> 'a option -> 'a option -> bool val get : 'a option -> 'a -> 'a - val value : 'a option -> 'a - val map : ('a -> 'b) -> 'a option -> 'b option - val some : 'a -> 'a option - val iter : ('a -> unit) -> 'a option -> unit - val bind : 'a option -> ('a -> 'b option) -> 'b option - val is_some : 'a option -> bool - val is_none : 'a option -> bool end module Promise : diff --git a/src/linking/linkModule.ml b/src/linking/linkModule.ml index d730ecaf076..1ca64ccde16 100644 --- a/src/linking/linkModule.ml +++ b/src/linking/linkModule.ml @@ -277,7 +277,7 @@ let rename_funcs rn : module_' -> module_' = fun m -> { m with funcs = funcs m.funcs; exports = exports m.exports; - start = Lib.Option.map var m.start; + start = Option.map var m.start; elems = List.map (segment (List.map var)) m.elems; } diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 5a4c07e2924..4c112c6bb34 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -285,7 +285,7 @@ and extra_typDs ds = | d::ds -> match d.it with | S.ClassD (id, _, _, _, _, _, _) -> - let c = Lib.Option.value id.note in + let c = Option.get id.note in let typD = I.TypD c @@ d.at in typD :: extra_typDs ds | _ -> extra_typDs ds @@ -308,7 +308,7 @@ and dec' at n d = match d with end | S.VarD (i, e) -> I.VarD (i.it, exp e) | S.TypD (id, typ_bind, t) -> - let c = Lib.Option.value id.note in + let c = Option.get id.note in I.TypD c | S.ClassD (id, tbs, p, _t_opt, s, self_id, es) -> let id' = {id with note = ()} in diff --git a/src/mo_frontend/traversals.ml b/src/mo_frontend/traversals.ml index c1a43335c73..ca47b82e0bd 100644 --- a/src/mo_frontend/traversals.ml +++ b/src/mo_frontend/traversals.ml @@ -36,7 +36,7 @@ let rec over_exp (f : exp -> exp) (exp : exp) : exp = match exp.it with | WhileE (exp1, exp2) -> f { exp with it = WhileE (over_exp f exp1, over_exp f exp2) } | LoopE (exp1, exp2_opt) -> - f { exp with it = LoopE (over_exp f exp1, Lib.Option.map (over_exp f) exp2_opt) } + f { exp with it = LoopE (over_exp f exp1, Option.map (over_exp f) exp2_opt) } | ForE (x, exp1, exp2) -> f { exp with it = ForE (x, over_exp f exp1, over_exp f exp2) } | DebugE exp1 -> diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index bd380d1a80c..e027ae14415 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -552,7 +552,7 @@ let rec infer_exp env exp : T.typ = infer_exp' T.as_immut env exp and infer_exp_mut env exp : T.typ = - infer_exp' Lib.Fun.id env exp + infer_exp' Fun.id env exp and infer_exp_promote env exp : T.typ = let t = infer_exp env exp in @@ -1823,7 +1823,7 @@ and infer_dec_valdecs env dec : Scope.t = let t = infer_exp {env with pre = true} exp in Scope.{empty with val_env = T.Env.singleton id.it (T.Mut t)} | TypD (id, _, _) -> - let c = Lib.Option.value id.note in + let c = Option.get id.note in Scope.{ empty with typ_env = T.Env.singleton id.it c; con_env = T.ConSet.singleton c ; diff --git a/src/mo_interpreter/interpret.ml b/src/mo_interpreter/interpret.ml index efac6697755..0e3f56316f6 100644 --- a/src/mo_interpreter/interpret.ml +++ b/src/mo_interpreter/interpret.ml @@ -184,7 +184,7 @@ let await env at async k = k v ) ) - (let r = Lib.Option.value (env.throws) in + (let r = Option.get (env.throws) in fun v -> Scheduler.queue (fun () -> if env.flags.trace then @@ -571,9 +571,9 @@ and interpret_exp_mut env exp (k : V.value V.cont) = | DebugE exp1 -> if !Mo_config.Flags.release_mode then k V.unit else interpret_exp env exp1 k | RetE exp1 -> - interpret_exp env exp1 (Lib.Option.value env.rets) + interpret_exp env exp1 (Option.get env.rets) | ThrowE exp1 -> - interpret_exp env exp1 (Lib.Option.value env.throws) + interpret_exp env exp1 (Option.get env.throws) | AsyncE exp1 -> async env exp.at @@ -616,7 +616,7 @@ and interpret_cases env cases at v (k : V.value V.cont) = and interpret_catches env cases at v (k : V.value V.cont) = match cases with | [] -> - Lib.Option.value env.throws v (* re-throw v *) + Option.get env.throws v (* re-throw v *) | {it = {pat; exp}; at; _}::cases' -> match match_pat pat v with | Some ve -> interpret_exp (adjoin_vals env ve) exp k @@ -811,7 +811,7 @@ and interpret_exp_fields env s fields ve (k : V.value V.cont) = and interpret_block env decs ro (k : V.value V.cont) = let ve = declare_decs decs V.Env.empty in - Lib.Option.iter (fun r -> r := ve) ro; + Option.iter (fun r -> r := ve) ro; interpret_decs (adjoin_vals env ve) decs k @@ -926,4 +926,4 @@ let interpret_lib flags scope lib : scope = interpret_exp env lib.it (fun v -> vo := Some v) ); Scheduler.run (); - lib_scope lib.note (Lib.Option.value !vo) scope + lib_scope lib.note (Option.get !vo) scope diff --git a/src/mo_types/con.ml b/src/mo_types/con.ml index d8d442cc75e..376cb46a92a 100644 --- a/src/mo_types/con.ml +++ b/src/mo_types/con.ml @@ -34,4 +34,3 @@ let to_string c = let eq c1 c2 = (c1.name, c1.stamp) = (c2.name, c2.stamp) let compare c1 c2 = compare (c1.name, c1.stamp) (c2.name, c2.stamp) - diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index 92c6b981ff6..9118ac7943a 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -324,7 +324,7 @@ let rec interpret_progs denv progs : Interpret.scope option = | None -> None let interpret_files (senv0, denv0) files : (Scope.scope * Interpret.scope) option = - Lib.Option.bind + Option.bind (Diag.flush_messages (load_progs parse_file files senv0)) (fun (libs, progs, senv1) -> let denv1 = interpret_libs denv0 libs in @@ -392,7 +392,7 @@ let generate_idl files : Idllib.Syntax.prog Diag.result = (* Running *) let run_files files : unit option = - Lib.Option.map ignore (interpret_files initial_env files) + Option.map ignore (interpret_files initial_env files) (* Interactively *) @@ -455,7 +455,7 @@ let run_stdin lexer (senv, denv) : env option = let run_files_and_stdin files = let lexer = Lexing.from_function lexer_stdin in - Lib.Option.bind (interpret_files initial_env files) (fun env -> + Option.bind (interpret_files initial_env files) (fun env -> let rec loop env = loop (Lib.Option.get (run_stdin lexer env) env) in try loop env with End_of_file -> printf "\n%!"; @@ -571,6 +571,6 @@ let interpret_ir_prog libs progs = () let interpret_ir_files files = - Lib.Option.map + Option.map (fun (libs, progs, senv) -> interpret_ir_prog libs progs) (Diag.flush_messages (load_progs parse_file files initial_stat_env)) diff --git a/src/pipeline/url.ml b/src/pipeline/url.ml index 620f8454cfa..830b1039340 100644 --- a/src/pipeline/url.ml +++ b/src/pipeline/url.ml @@ -24,7 +24,7 @@ (* helper (only to be used on "ic:…" urls) *) let decode_actor_url url : (string, string) result = let open Stdlib.String in - let hex = Lib.Option.value (Lib.String.chop_prefix "ic:" url) in + let hex = Option.get (Lib.String.chop_prefix "ic:" url) in if equal hex "" then Error "principal ID must not be empty" else if uppercase_ascii hex <> hex then Error "principal ID must be uppercase" else diff --git a/src/wasm-exts/customModuleDecode.ml b/src/wasm-exts/customModuleDecode.ml index 499d74473a8..3e994396138 100644 --- a/src/wasm-exts/customModuleDecode.ml +++ b/src/wasm-exts/customModuleDecode.ml @@ -467,7 +467,7 @@ let const s = let id s = let bo = peek s in - Lib.Option.map + Option.map (function | 0 -> `CustomSection | 1 -> `TypeSection diff --git a/src/wasm-exts/customModuleEncode.ml b/src/wasm-exts/customModuleEncode.ml index 85886e2561b..f15cec46f0a 100644 --- a/src/wasm-exts/customModuleEncode.ml +++ b/src/wasm-exts/customModuleEncode.ml @@ -121,7 +121,7 @@ let encode (em : extended_module) = let string bs = len (String.length bs); put_string s bs let name n = string (Wasm.Utf8.encode n) let list f xs = List.iter f xs - let opt f xo = Lib.Option.iter f xo + let opt f xo = Option.iter f xo let vec f xs = len (List.length xs); list f xs let gap32 () = let p = pos s in u32 0l; u8 0; p From cb714f5df9cf9b33cb40e96f420332b0e2b4fb63 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Fri, 10 Jan 2020 12:28:13 +0000 Subject: [PATCH 0905/1176] revise design for feedback and final implementation --- design/scoped-await.md | 253 ++++++++++++++++++++------------- test/run-drun/general_await.mo | 37 +++-- 2 files changed, 174 insertions(+), 116 deletions(-) diff --git a/design/scoped-await.md b/design/scoped-await.md index 70e3c57ea05..f48663c7220 100644 --- a/design/scoped-await.md +++ b/design/scoped-await.md @@ -34,80 +34,148 @@ _Please break it_ ```bnf := ... - | asyncU // T is an index, typically a type parameter + | asyncU // T is an index, typically a scope parameter X + | shared? T -> U // function types (with optional scope parameter X) + + +Xs := X,Ys + | Ys + +Ys := Y, Ys + +(type parameters are an optional scope parameter X followed by ordinary type parameters Y(s)) := - | async e // index abstraction plus application in one (parameter X free in e, but not in instantiation U) - | shared f(x:T) : asyncU = async e ; // requests - | shared f(x:T) : asyncU { e; } // sugar (for the above) - | f e // (indexed) application + | async e // async (scope X bound in e) + | shared? f(x:T) : U = e // functions + | f e // application + | ... + +Ctxt := E; Cap // Environment and capability C + +// capabilites -Ctxt := E; async // async context with index U - | E; - // non-async context +Cap := + | NullCap // no async capability (top-level, in constructors, some local functions) + | AsyncCap // capability to async/send at T + | AwaitCap // capability to async/send at T and await an async Env := // the usual suspects - | E, x : T - | E, X <: T + | E, x : T // term va + | E, X // scope var + | E, Y // type var | -``` -# Concrete Syntax +scope(AsyncCap) = Some T +scope(AwaitCap) = Some T +scope(NullCap) = None -TBD, but hopefully the explicit parameterization/instantiation can be supressed, much as Rust *lifetimes* are largely implicit. -Here, the simplist might be to use the function name itself for the implicit index parameter -(although not all motoko functions are named) and always instantiate with the ambient index (or `Any` if none). +cap(@ X,Ys) = AsyncCap +cap(Ys) = NullCap +``` ### Parameterized async expressions ``` -E, X; async |- e : T E |- U :: * (X fresh) -------------------------------------------------- -E; - |- async e : async T[U/X] +E, X; AwaitCap |- e : U (X not in E,cap) +scope(cap) = Some T +---------------------------------------------------------- +E; cap |- async e: async U[T/X] ``` -An `async` expression at index `X` provides the scoped ability to await asyncs with index `X`. +An `async` expression at index `X` provides the scoped capability, `AwaitCap`, to await asyncs with index `X`, provided +the current capability is `AwaitCap` or `AsyncCap`. That is, async expressions are only allowed in async or await contexts, +and the body of async expressions can await, spawn an async or send a message (at scope `X`). + +The body `e` of an async must be parametric in the index but the index parameter is immediately eliminated at the current scope `T`. -The body `e` of an async must be parametric in the index but the index -parameter is immediately eliminated at some index `U` (not mentioning `X`). +Async expressions are illegal if the current capability is `NullCap` (e.g. at top-level, or in a constructor or vanilla function). -### (restricted) await expressions +### (restricted) Await expressions ``` -E; async |- e : async T +E; AwaitCap |- e : async U ------------------------------ -E; async |- await e : T +E; AwaitCap |- await e : U ``` -We can only await things of the current index `U`, recorded in the context as `_ ; async`. +We can only await things of the current index `T`, recorded in the context as `_ ; AwaitCap`. + +In particular, you cannot await anything unless you've entered an async expression. (For *closure under type substitution* of contexts, note that we need the annotation in the context to be a type, not just a type parameter). +### Formation + +Function types are only well-formed if async and oneway functions have an initial scope type parameter (our sugar will ensure this). + +``` +E,Xs; cap |- T E,Xs; cap(Xs) |- U +shared? = shared implies Xs = X,Ys and (U = () or U = asyncW) ... +Xs = X,Ys and U = asyncW implies V = X and +----------------------------------------------------[func ok] +E; cap |- shared? T -> U +``` +The first side condition ensures that a shared function has a scope parameter `X` (invokation requires a capability and scope instantiation). +The second side condition ensures that an async return is parametric in `X` (local or shared). + +Note that a local function may or may not take a scope parameter. + + +### Abstraction + +The rules for async/oneway function abstraction are as follows: + +``` +E,Xs,x:T; cap(Xs) |- e : U +E, cap |- shared? T -> U +shared? = shared implies U = () or e == asynce' (some e') +-----------------------------------------------------------------------------------------[func] +E; cap |- shared? f (x:T) : U = e : shared? T -> U +``` + +The second premise ensure the initial parameter of a oneway or async function must be a scope parameter `X` (see formation [func ok]). +In this way, regardless, of the current capability, the body of an (shared/local) async function or shared oneway +is granted the capability to enter an async expression and send messages. -### Application (Derived Rule) +Without a scope parameter in `Xs` (`Xs` = `Ys`), the abstraction rule simple introduces the null capability, `NullCap`, to prevent sends and async expressions in the body. -In the explicit system, the rules for function abstraction and application are *unchanged*. But -to illustrate how this works, we consider the derived rules: +Not that a local function is may or may not introduce a scope parameter, affecting the capabilities of its body (and the ability to invoke that function). +This means that a local function *can* be used to abstract out async and sends, provided it has a scope parameter that is supplied when called. + +### Application + +Async and oneway functions: + +Application of an async (or, in the full system, shared +oneway) uses the current scope `T` as the instantiation of the scope +parameter and is rejected when no such parameter exists (`scope(cap) = None`). + +One cannot specify the instantiation of the initial scope parameter, it +is determined by the context if at all. ``` -E; _ |- f : shared U -> async V -E; _ |- e': [T/X] U -------------------------------------- -E; _ |- f e' : async([T/X]V) +E; cap |- f : shared? U -> V +Xs = X,Ys +scope(cap) = Some T +E; cap |- e': U[T/X,Ts/Ys] +------------------------------------------------------- +E; cap |- f e' : V[T/X,Ts/Ys] ``` -Application must provide an instantiation, typically the nearest -enclosing index parameter if want to await the result, but it could be -any type. +(Local) Functions with no scope parameters are instantiated as usual and can be invoked with any capability. -In the implicit system, we change the rule for application to (if -necessary) insert a single missing scope parameter (`@`) amongst the -remaining explicit type parameters, driven by the expected async -returning function type and the 1-deficit of type arguments. This is a -simple check to see if the index of the return type is a type -parameter and the number of arguments is 1 less than the number of -parameters, and then inserting '@' at the correct index in the type -arguments (otherwise the arguments are as given). +``` +E; cap |- f : U -> V +E; cap |- e': U[Ts/Ys] +---------------------------------------------- +E; cap |- f e' : V[Ts/Ys] +``` + +By construction, shared functions must have a scope parameter and can never be invoked in a `NullCap` context. + +For local functions, it depends on the type of the function (i.e. whether it has a scope parameter). ### Abstraction (Derived Rule) @@ -118,50 +186,46 @@ Derivation for (desugared) shared functions (ignoring recursion). Consider the desugared async function: ``` -shared f(x:T) : asyncU = async e ; +shared? f(X:T) : async U { e } := +shared? f(x:T) : asyncU = async e; ``` For reusability in different async contexts, every shared function -should introduce a new index parameter, immediately supplied to the -inner async expression. Using non-generic shared functions is ok, but -less useful (typically only locally useful): the result type needs to -be generic if we want to await it from other async contexts. +should introduce a new index parameter, implicitly supplied to the +inner async expression. The result type needs to +be generic if we want to invoke and await it from other async contexts. -Using the above rules and ordinary lambda abstraction we get: +Using the above rules we get: ``` -E, X, x : T, Y; async |- e : U[Y] Y fresh +E, X, Ys, x : T, Y; AwaitCap |- e : U ------------------------------------------------------------- -E, X, x : T |- async e : U[Y] : (U[Y])[X/Y] X fresh +E, X, Ys, x : T; AsyncCap |- async e ------------------------------------------------------------- -E; _ |- shared f(x:T) : asyncU[X] = async e ; - shared (x:T) : asyncU[X] +E; _ |- shared? f(x:T) : asyncU = async e : + shared? (x:T) : asyncU ``` +Notice that the context transitions from `AsyncCap` to `AwaitCap` to allow awaits from within `e`. - -If we explicitly pun `X` and `Y` in our *implicit* syntax desugaring we get: +Applying the sugar below, which implicitly introduces scope parameters in types and terms we get the more manageable: ``` -shared f(x:T) : async U := - shared f(x:T) : asyncU = async e ; - +E; _ |- shared? f(x:T) : async U { e } : + shared? (x:T) : async U ``` -Then we get the derived rule: +(in which the scope parameters `X` are completely elided). -``` -E, X, x : T; async |- e : U (X fresh) ----------------------------------------------------------------------- ----------------------------------------------------------------------- -E; _ |- shared f(x:T) : async U { e; } : shared T -> async U -``` + + +### DON'T READ TOO CLOSELY BELOW HERE, needs revising ## Examples: (These examples and more are all coded in -* [general_await.mo](../test/run-stub/general_await.mo) (no-sugar) -* [general_await_implicit.mo](../test/run-stub/general_await_implicit.mo) (with sugar) +* [general_await.mo](../test/run-drun/general_await.mo) (no-sugar) +* [general_await_implicit.mo](../test/run-drun/general_await_implicit.mo) (with sugar) ) Assuming the following requests: @@ -177,12 +241,12 @@ Assuming the following requests: }; ``` -### Static parralel waiting: +### Static parallel waiting: ``` public shared func PA<@>() : async<@> () { - let a1 = Ack<@>(); - let a2 = Ack<@>(); + let a1 = Ack(); + let a2 = Ack(); await a1; await a2; }; @@ -315,54 +379,51 @@ Note that simply renaming `S` to `R` would not circumvent the error.) Principle: Desugaring should be: * simple and unambiguous -* expressible in the syntax (as explicit binders and instantiations). -* avoidable (by supplying explicit binders and instantations). +* expressible in the syntax (as explicit binders). +* avoidable (by supplying explicit binders). ### Basic idea: -Prelude: - -Defines default scope `@ = Any` (non-awaitable in any async context) and instantiation: - -``` -type @ = Any -``` - -(`@` is a newly legal scope identifier) +(`@` is a new type identifier, used for scopes) Parsing: -* inserts `<@>` type binders for missing `async` binders and instantiations (in types and terms) and `async` binders (in terms); +* inserts `<@,...>` type binders for missing scope binders (in types and terms); * adds missing `<@>` bindings to async returning functions with missing async indices. Elaboration: * Elaboration ensures `@` is bound to an appropriate constructor, shadowing any previous `@`-binding to ensure lexical scoping. -* Elaboration adds missing scope instantiations to function applications that require them, guided by the synthesized function type. Syntactic sugar (during parse, applied bottom up as we construct types and terms) ``` -<...>T1 -> async T2 := (@ not in ...) - <@,...>T1 -> async T1 +(async T)^ := async<@> (T^) + +(<...>T1 -> async T2)^ := (@ not in ...) + <@,...^>T1^ -> (async T2)^ -func f<...>() : async T = e := (@ not in ...) - func f<@,...> f() : async T = e +(shared? f<...>() : async T = e)^ := (@ not in ...) + shared? f<@,...^>(^) : (async T)^ = e^ -func f<...>() : async T { e } := - func f<@,...>() : async T = async<@> e <@> +(shared? f<...>() : async T { e })^ := (@ not in ...) + shared? f<@,...^>(^) : (async T)^ = async<@> e^ -func f<...>() : async T { e } := - func f<...>() : async T = async e +(shared? f<...>() : async T { e }) := + shared? f<...^>(^) : async T^ = async e ^ (binds inner scope as X, not @, to pun X in e) -func f<...>() : async T { e } := (U <> X) - func f<...>() : async T = async <@> e +(shared f<...>() : () = e)^ := (@ not in ...) + shared f<@,...^>(^) : () = e^ + +(shared f<...>() { e })^ := (@ not in ...) + shared f<@,...^>(^) : () = e^ + -async e := - async<@> e <@> +(async e)^ := + async<@> e^ ``` @@ -379,7 +440,7 @@ Types: (async t)* ~~> async<@*> t* -(async t1)* +(async t2)* ~~> async t2* <...>T1 -> async T2 ~~> (* syntax sugaring ensures @ bound in ... *) @@ -398,7 +459,7 @@ async e ~~> async e[X/@] f e ~~> f e when f : <...,Xi,...> T1 ~~> async T1 - (note inference can infer a missing scope parameter at any position, not just position 0) +(note inference can infer a missing scope parameter at any position, not just position 0) func<...>f() : async T = e ~~> (* syntax sugaring ensures @ bound in ... *) func<...*>f() : (async T)* = e* diff --git a/test/run-drun/general_await.mo b/test/run-drun/general_await.mo index ce59f785045..9e33432da49 100644 --- a/test/run-drun/general_await.mo +++ b/test/run-drun/general_await.mo @@ -5,7 +5,6 @@ actor Await { }; public shared func Request<@>(i : Int) : async<@> Int { -// debugPrint("Request(" # debug_show i # ")"); <-- compiler bug debugPrintInt(i); return i; }; @@ -13,15 +12,15 @@ actor Await { // Static parallel waiting: public shared func PA<@>() : async<@> () { - let a1 = Ack<@>(); - let a2 = Ack<@>(); + let a1 = Ack(); + let a2 = Ack(); await a1; await a2; }; public shared func PR<@>() : async<@>(Int,Int) { - let a1 = Request<@>(1); - let a2 = Request<@>(2); + let a1 = Request(1); + let a2 = Request(2); (await a1, await a2) }; @@ -30,7 +29,7 @@ actor Await { public shared func DPA<@>() : async<@>() { let os = Array_init(10, null); for (i in os.keys()) { - os[i] := ? (Ack<@>()); + os[i] := ? (Ack()); }; for (o in os.vals()) { switch o { @@ -42,12 +41,10 @@ actor Await { // Dynamic parallel waiting (with results) - // Dynamic parallel waiting (with results) - public shared func DPR<@>() : async<@> [Int] { let os = Array_init(10, null); for (i in os.keys()) { - os[i] := ? (Request<@>(i)); + os[i] := ? (Request(i)); }; let res = Array_init(os.len(),-1); for (i in os.keys()) { @@ -64,8 +61,8 @@ actor Await { public shared func RPA<@>(n:Nat) : async<@>() { if (n == 0) () else { - let a = Ack<@>(); - await RPA<@>(n-1); // recurse + let a = Ack(); + await RPA(n-1); // recurse await a; }; }; @@ -77,8 +74,8 @@ actor Await { public shared func RPR<@>(n:Nat) : async<@> List { if (n == 0) null else { - let a = Request<@>(n); - let tl = await RPR<@>(n-1); // recurse + let a = Request(n); + let tl = await RPR(n-1); // recurse ?(await a,tl) } }; @@ -86,23 +83,23 @@ actor Await { public shared func Test<@>() : async<@>() { - await PA<@>(); + await PA(); - switch (await PR<@>()) { + switch (await PR()) { case (1,2) (); case _ (assert false); }; - await DPA<@>(); + await DPA(); - let rs = await DPR<@>(); + let rs = await DPR(); for (i in rs.keys()) { assert rs[i] == i; }; - await RPA<@>(10); + await RPA(10); - var l = await RPR<@>(10); + var l = await RPR(10); for (i in revrange(10, 1)) { switch (l) { case (?(h, t)) { @@ -115,7 +112,7 @@ actor Await { } }; -Await.Test<@>(); //OR-CALL ingress Test 0x4449444C0000 +Await.Test(); //OR-CALL ingress Test 0x4449444C0000 //SKIP comp From a67f7066a28dc693ea0ba70bb18320779d060bea Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Fri, 10 Jan 2020 12:36:09 +0000 Subject: [PATCH 0906/1176] typos --- design/scoped-await.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/design/scoped-await.md b/design/scoped-await.md index f48663c7220..9a1e24f0630 100644 --- a/design/scoped-await.md +++ b/design/scoped-await.md @@ -47,7 +47,7 @@ Ys := Y, Ys := | async e // async (scope X bound in e) - | shared? f(x:T) : U = e // functions + |shared? f(x:T) : U = e // functions | f e // application | ... @@ -58,12 +58,12 @@ Ctxt := E; Cap // Environment and capability C Cap := | NullCap // no async capability (top-level, in constructors, some local functions) | AsyncCap // capability to async/send at T - | AwaitCap // capability to async/send at T and await an async + | AwaitCap // capability to async/send at T and await an async Env := // the usual suspects | E, x : T // term va | E, X // scope var - | E, Y // type var + | E, Y // type var | scope(AsyncCap) = Some T @@ -151,8 +151,6 @@ Application of an async (or, in the full system, shared oneway) uses the current scope `T` as the instantiation of the scope parameter and is rejected when no such parameter exists (`scope(cap) = None`). -One cannot specify the instantiation of the initial scope parameter, it -is determined by the context if at all. ``` @@ -163,6 +161,9 @@ E; cap |- e': U[T/X,Ts/Ys] ------------------------------------------------------- E; cap |- f e' : V[T/X,Ts/Ys] ``` +One cannot specify the instantiation of an initial scope parameter, it +is determined by the context, if at all (as per async expressions). + (Local) Functions with no scope parameters are instantiated as usual and can be invoked with any capability. @@ -207,7 +208,7 @@ E; _ |- shared? f(x:T) : asyncU = async e : ``` Notice that the context transitions from `AsyncCap` to `AwaitCap` to allow awaits from within `e`. -Applying the sugar below, which implicitly introduces scope parameters in types and terms we get the more manageable: +Applying the sugar above, which implicitly introduces scope parameters in types and terms we get the more manageable: ``` E; _ |- shared? f(x:T) : async U { e } : @@ -235,7 +236,7 @@ Assuming the following requests: debugPrint "Ack" }; - public shared func Request<@>(i : Int) : async<@> Int { +x public shared func Request<@>(i : Int) : async<@> Int { debugPrint("Request(" # debug_show i # ")"); return i; }; From 6846d06c0bac2fc018c3d2798c0e981e13fb023f Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Fri, 10 Jan 2020 14:19:18 +0000 Subject: [PATCH 0907/1176] Apply suggestions from code review nits --- design/scoped-await.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/design/scoped-await.md b/design/scoped-await.md index 9a1e24f0630..44d13b4a520 100644 --- a/design/scoped-await.md +++ b/design/scoped-await.md @@ -70,7 +70,7 @@ scope(AsyncCap) = Some T scope(AwaitCap) = Some T scope(NullCap) = None -cap(@ X,Ys) = AsyncCap +cap(X,Ys) = AsyncCap cap(Ys) = NullCap ``` @@ -140,7 +140,7 @@ is granted the capability to enter an async expression and send messages. Without a scope parameter in `Xs` (`Xs` = `Ys`), the abstraction rule simple introduces the null capability, `NullCap`, to prevent sends and async expressions in the body. -Not that a local function is may or may not introduce a scope parameter, affecting the capabilities of its body (and the ability to invoke that function). +Note that a local function may or may not introduce a scope parameter, affecting the capabilities of its body (and the ability to invoke that function). This means that a local function *can* be used to abstract out async and sends, provided it has a scope parameter that is supplied when called. ### Application From b6ac99585eaa5500ad60d2363f119650f49a58f2 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 10 Jan 2020 15:58:45 +0100 Subject: [PATCH 0908/1176] Infrastructure for the hard-coded prim module (#1093) * Infrastructure for the hard-coded prim module this make `import "mo:prim"` import the module in the `prim_module` string in `prelude.ml`. This is currently empty; the code is added in PR #1088. * Print an error upon `--package prim ...` * Update src/prelude/prelude.ml Co-Authored-By: Gabor Greif Co-authored-by: Gabor Greif --- src/lowering/desugar.ml | 1 + src/mo_def/syntax.ml | 1 + src/mo_frontend/typing.ml | 1 + src/mo_interpreter/interpret.ml | 1 + src/pipeline/pipeline.ml | 104 +++++++++++++++-------- src/pipeline/resolve_import.ml | 15 ++++ src/pipeline/url.ml | 19 ++++- src/pipeline/url.mli | 1 + src/prelude/prelude.ml | 21 +++++ src/prelude/prelude.mli | 1 + test/fail/ok/prim-package-flag.tc.ok | 1 + test/fail/ok/prim-package-flag.tc.ret.ok | 1 + test/fail/prim-package-flag.mo | 1 + 13 files changed, 129 insertions(+), 39 deletions(-) create mode 100644 test/fail/ok/prim-package-flag.tc.ok create mode 100644 test/fail/ok/prim-package-flag.tc.ret.ok create mode 100644 test/fail/prim-package-flag.mo diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 4c112c6bb34..76a29b083fe 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -150,6 +150,7 @@ and exp' at note = function begin match !ir with | S.Unresolved -> raise (Invalid_argument ("Unresolved import " ^ f)) | S.LibPath fp -> I.VarE (id_of_full_path fp).it + | S.PrimPath -> I.VarE (id_of_full_path "@prim").it | S.IDLPath (fp, blob_id) -> I.(PrimE (ActorOfIdBlob note.note_typ, [blobE blob_id])) end | S.PrimE s -> raise (Invalid_argument ("Unapplied prim " ^ s)) diff --git a/src/mo_def/syntax.ml b/src/mo_def/syntax.ml index 2b56259be44..1114bbc6338 100644 --- a/src/mo_def/syntax.ml +++ b/src/mo_def/syntax.ml @@ -16,6 +16,7 @@ type resolved_import = | Unresolved | LibPath of string | IDLPath of (string * string) (* filepath * bytes *) + | PrimPath (* the built-in prim module *) (* Identifiers *) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index e027ae14415..799e38f1272 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -176,6 +176,7 @@ let check_import env at f ri = | Unresolved -> error env at "unresolved import %s" f | LibPath fp -> fp | IDLPath (fp, _) -> fp + | PrimPath -> "@prim" in match T.Env.find_opt full_path env.libs with | Some T.Pre -> diff --git a/src/mo_interpreter/interpret.ml b/src/mo_interpreter/interpret.ml index 0e3f56316f6..c435d9490c4 100644 --- a/src/mo_interpreter/interpret.ml +++ b/src/mo_interpreter/interpret.ml @@ -391,6 +391,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = | Unresolved -> assert false | LibPath fp -> k (find fp env.libs) | IDLPath _ -> trap exp.at "actor import" + | PrimPath -> k (find "@prim" env.libs) ) | LitE lit -> k (interpret_lit env lit) diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index 9118ac7943a..bdda4a6f483 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -166,16 +166,7 @@ let check_lib senv lib : Scope.scope Diag.result = Diag.bind (Definedness.check_lib lib) (fun () -> Diag.return sscope) ) -(* Imported file loading *) - -(* -Loading a file (or string) implies lexing, parsing, resolving imports to -libraries, and typechecking. -The resulting prog is typechecked. -The Typing.scope field in load_result is the accumulated scope. -When we load a declaration (i.e from the REPL), we also care about the type -and the newly added scopes, so these are returned separately. -*) +(* Parsing libraries *) let is_import dec = let open Source in let open Syntax in @@ -206,6 +197,65 @@ let lib_of_prog f prog = {it = exp; at = prog.at; note = f} +(* Prelude *) + +let prelude_name = "prelude" + +let prelude_error phase (msgs : Diag.messages) = + Printf.eprintf "%s prelude failed\n" phase; + Diag.print_messages msgs; + exit 1 + +let check_prelude () : Syntax.prog * stat_env = + let lexer = Lexing.from_string Prelude.prelude in + let parse = Parser.parse_prog in + match parse_with Lexer.Privileged lexer parse prelude_name with + | Error e -> prelude_error "parsing" [e] + | Ok prog -> + let senv0 = Scope.empty in + match infer_prog senv0 prog with + | Error es -> prelude_error "checking" es + | Ok ((_t, sscope), msgs) -> + let senv1 = Scope.adjoin senv0 sscope in + prog, senv1 + +let prelude, initial_stat_env = check_prelude () + +(* The prim module *) + +let prim_name = "prim" + +let prim_error phase (msgs : Diag.messages) = + Printf.eprintf "%s prim failed\n" phase; + Diag.print_messages msgs; + exit 1 + +let check_prim () : Syntax.lib * stat_env = + let lexer = Lexing.from_string Prelude.prim_module in + let parse = Parser.parse_prog in + match parse_with Lexer.Privileged lexer parse prim_name with + | Error e -> prim_error "parsing" [e] + | Ok prog -> + let senv0 = initial_stat_env in + let lib = lib_of_prog "@prim" prog in + match check_lib senv0 lib with + | Error es -> prim_error "checking" es + | Ok (sscope, msgs) -> + let senv1 = Scope.adjoin senv0 sscope in + lib, senv1 + +(* Imported file loading *) + +(* +Loading a file (or string) implies lexing, parsing, resolving imports to +libraries, and typechecking. +The resulting prog is typechecked. +The Typing.scope field in load_result is the accumulated scope. +When we load a declaration (i.e from the REPL), we also care about the type +and the newly added scopes, so these are returned separately. +*) + + type load_result = (Syntax.lib list * Syntax.prog list * Scope.scope) Diag.result @@ -232,6 +282,15 @@ let chase_imports parsefn senv0 imports : (Syntax.lib list * Scope.scope) Diag.r let libs = ref [] in let rec go ri = match ri.Source.it with + | Syntax.PrimPath -> + (* a bit of an hack, lib_env should key on resolved_import *) + if Type.Env.mem "@prim" !senv.Scope.lib_env then + Diag.return () + else + let lib, sscope = check_prim () in + libs := lib :: !libs; (* NB: Conceptually an append *) + senv := Scope.adjoin !senv sscope; + Diag.return () | Syntax.Unresolved -> assert false | Syntax.LibPath f -> if Type.Env.mem f !senv.Scope.lib_env then @@ -333,31 +392,6 @@ let interpret_files (senv0, denv0) files : (Scope.scope * Interpret.scope) optio | Some denv2 -> Some (senv1, denv2) ) - -(* Prelude *) - -let prelude_name = "prelude" - -let prelude_error phase (msgs : Diag.messages) = - Printf.eprintf "%s prelude failed\n" phase; - Diag.print_messages msgs; - exit 1 - -let check_prelude () : Syntax.prog * stat_env = - let lexer = Lexing.from_string Prelude.prelude in - let parse = Parser.parse_prog in - match parse_with Lexer.Privileged lexer parse prelude_name with - | Error e -> prelude_error "parsing" [e] - | Ok prog -> - let senv0 = Scope.empty in - match infer_prog senv0 prog with - | Error es -> prelude_error "checking" es - | Ok ((_t, sscope), msgs) -> - let senv1 = Scope.adjoin senv0 sscope in - prog, senv1 - -let prelude, initial_stat_env = check_prelude () - let run_prelude () : dyn_env = match interpret_prog Interpret.empty_scope prelude with | None -> prelude_error "initializing" [] diff --git a/src/pipeline/resolve_import.ml b/src/pipeline/resolve_import.ml index 4864db1ee4c..a3037419054 100644 --- a/src/pipeline/resolve_import.ml +++ b/src/pipeline/resolve_import.ml @@ -125,6 +125,15 @@ let err_package_file_does_not_exist msgs f pname = text = Printf.sprintf "file \"%s\" (for package `%s`) does not exist" f pname } +let err_prim_pkg msgs = + let open Diag in + add_msg msgs { + sev = Error; + at = no_region; + cat = "package"; + text = "the \"prim\" package is built-in, and cannot be mapped to a directory" + } + let add_lib_import msgs imported ri_ref at full_path = let full_path = append_lib_if_needed full_path in if Sys.file_exists full_path @@ -143,6 +152,9 @@ let add_idl_import msgs imported ri_ref at full_path bytes = err_file_does_not_exist msgs at full_path +let add_prim_import imported ri_ref at = + ri_ref := PrimPath; + imported := RIM.add PrimPath at !imported let in_base base f = if base = "." @@ -171,11 +183,14 @@ let resolve_import_string msgs base actor_idl_path aliases packages imported (f, | Some bytes -> resolve_ic bytes | None -> err_alias_not_defined msgs at alias end + | Ok Url.Prim -> + add_prim_import imported ri_ref at | Error msg -> err_unrecognized_url msgs at f msg (* Resolve the argument to --package. *) let resolve_package_url (msgs:Diag.msg_store) (pname:string) (f:url) : filepath = + if pname = "prim" then (err_prim_pkg msgs ;"") else let f = Lib.FilePath.normalise f in if Sys.file_exists f then f diff --git a/src/pipeline/url.ml b/src/pipeline/url.ml index 830b1039340..bbbec42244c 100644 --- a/src/pipeline/url.ml +++ b/src/pipeline/url.ml @@ -6,6 +6,9 @@ parse "mo:foo/bar" = Ok (Package ("foo", "bar")) parse "mo:foo" = Ok (Package ("foo", "")) + parse "mo:prim" = Ok (Prim) + parse "mo:prim/bar" = Error… + parse "ic:DEADBEEF" = Ok (Ic "\DE\AD\BE\EF") parse "ic-alias:foo" = Ok (IcAlias "foo") @@ -14,6 +17,7 @@ parse "foo" = Ok (Relative "foo") parse "./foo" = Ok (Relative "foo") + parse "something:else" = Error … TODO: This could be the place to reject things like @@ -42,17 +46,24 @@ type parsed = | Relative of string | Ic of string | IcAlias of string + | Prim let parse (f: string) : (parsed, string) result = match Lib.String.chop_prefix "mo:" f with | Some suffix -> begin match Stdlib.String.index_opt suffix '/' with - | None -> Ok (Package (suffix, "")) + | None -> + if suffix = "prim" + then Ok Prim + else Ok (Package (suffix, "")) | Some i -> - let pkg = Stdlib.String.sub suffix 0 i in - let path = Stdlib.String.sub suffix (i+1) (Stdlib.String.length suffix - (i+1)) in - Ok (Package (pkg, path)) + if suffix = "prim" + then Error "The prim package has no modules" + else + let pkg = Stdlib.String.sub suffix 0 i in + let path = Stdlib.String.sub suffix (i+1) (Stdlib.String.length suffix - (i+1)) in + Ok (Package (pkg, path)) end | None -> match Lib.String.chop_prefix "ic:" f with diff --git a/src/pipeline/url.mli b/src/pipeline/url.mli index b9299577ac4..94e9be4f2cf 100644 --- a/src/pipeline/url.mli +++ b/src/pipeline/url.mli @@ -3,6 +3,7 @@ type parsed = | Relative of string | Ic of string | IcAlias of string + | Prim val parse : string -> (parsed, string) result val idl_basename_of_blob : string -> string diff --git a/src/prelude/prelude.ml b/src/prelude/prelude.ml index 7511ffbfd3c..139ba3b1ae7 100644 --- a/src/prelude/prelude.ml +++ b/src/prelude/prelude.ml @@ -1,3 +1,9 @@ +(* +The prelude. This stuff is always initially in scope. This should be only + * type definitions for primitive types + * code with privileged names (@…) that are used by the desugarer or ir-passes + (the moving of the definitions is done in #1088) +*) let prelude = {| type Any = prim "Any"; @@ -419,3 +425,18 @@ func @new_async() : (Async, Cont, Cont) { (enqueue, fulfill, fail) }; |} + +(* +The primitive definitions. + +This module should contain everything that cannot be implemented in plain +Motoko. It is available via `import Prim "mo:prim"`. Normal user code would +usually not import that module directly, but through the stdlib, which takes +care of providing a proper module structure, e.g. exposing Array_tabulate +through Array.tabulate. +*) +let prim_module = +{| + + +|} diff --git a/src/prelude/prelude.mli b/src/prelude/prelude.mli index e9b8a0b9f64..cbd4880cd8f 100644 --- a/src/prelude/prelude.mli +++ b/src/prelude/prelude.mli @@ -1 +1,2 @@ val prelude : string +val prim_module : string diff --git a/test/fail/ok/prim-package-flag.tc.ok b/test/fail/ok/prim-package-flag.tc.ok new file mode 100644 index 00000000000..389c11ae20d --- /dev/null +++ b/test/fail/ok/prim-package-flag.tc.ok @@ -0,0 +1 @@ +(unknown location): package error, the "prim" package is built-in, and cannot be mapped to a directory diff --git a/test/fail/ok/prim-package-flag.tc.ret.ok b/test/fail/ok/prim-package-flag.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/prim-package-flag.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/prim-package-flag.mo b/test/fail/prim-package-flag.mo new file mode 100644 index 00000000000..9c96cbfbef8 --- /dev/null +++ b/test/fail/prim-package-flag.mo @@ -0,0 +1 @@ +//MOC-FLAG --package prim . From a5c5392238ca3f7b49dc6d21b046bc06e98bfb76 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 10 Jan 2020 18:06:16 +0100 Subject: [PATCH 0909/1176] Stdlib: Export more prelude stuff via the stdlib (#1096) * Stdlib: Export some conversion functions also in Nat and Int this anticipates #1088: With this change, the LinkedUp code can be changed to use only the stdlib, but _no_ definitions from the prelude. This means that #1088 would not break LinkedUp. * Likewise, export Array.{init/tabulate} * Expose Debug.print --- stdlib/Makefile | 4 ++++ stdlib/array.mo | 9 +++++++++ stdlib/debug.mo | 3 +++ stdlib/int.mo | 9 +++++++++ stdlib/nat.mo | 19 +++++++++++++++++++ 5 files changed, 44 insertions(+) create mode 100644 stdlib/debug.mo diff --git a/stdlib/Makefile b/stdlib/Makefile index 980f8f69a2e..fd7d3289a38 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -16,6 +16,7 @@ WASM=\ TESTS=\ Array \ + Debug \ ArrayTest \ BufTest \ Buf \ @@ -73,6 +74,9 @@ clean: $(OUTDIR): @mkdir $@ +$(OUTDIR)/Debug.out: debug.mo | $(OUTDIR) + $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ + $(OUTDIR)/Array.out: array.mo | $(OUTDIR) $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ diff --git a/stdlib/array.mo b/stdlib/array.mo index af45a1c472c..76880de9457 100644 --- a/stdlib/array.mo +++ b/stdlib/array.mo @@ -133,6 +133,15 @@ module { ys; }; + public func init(len : Nat, x : A) : [var A] { + Array_init(len, x); + }; + + public func tabulate(len : Nat, gen : Nat -> A) : [A] { + Array_tabulate(len, gen); + }; + + public func tabulateVar(len : Nat, gen : Nat -> A) : [var A] { if (len == 0) { return [var] }; let xs = Array_init(len, gen 0); diff --git a/stdlib/debug.mo b/stdlib/debug.mo new file mode 100644 index 00000000000..9adc14b7aff --- /dev/null +++ b/stdlib/debug.mo @@ -0,0 +1,3 @@ +module { + public func print(x : Text) = debugPrint x; +} diff --git a/stdlib/int.mo b/stdlib/int.mo index d7a6432c505..c0c34b335c1 100644 --- a/stdlib/int.mo +++ b/stdlib/int.mo @@ -36,4 +36,13 @@ module { return if isNegative ("-" # text) else text; }; + + public func fromInt8 (x : Int8): Int = int8ToInt x; + public func fromInt16(x : Int16): Int = int16ToInt x; + public func fromInt32(x : Int32): Int = int32ToInt x; + public func fromInt64(x : Int64): Int = int64ToInt x; + public func toInt8 (x : Int) : Int8 = intToInt8 x; + public func toInt16(x : Int) : Int16 = intToInt16 x; + public func toInt32(x : Int) : Int32 = intToInt32 x; + public func toInt64(x : Int) : Int64 = intToInt64 x; } diff --git a/stdlib/nat.mo b/stdlib/nat.mo index 8e6068bd388..99ddc12ceb4 100644 --- a/stdlib/nat.mo +++ b/stdlib/nat.mo @@ -9,4 +9,23 @@ module { public func toText(x : Nat) : Text { Int.toText(x); }; + + public func fromWord8 (x : Word8): Nat = word8ToNat x; + public func fromWord16(x : Word16): Nat = word16ToNat x; + public func fromWord32(x : Word32): Nat = word32ToNat x; + public func fromWord64(x : Word64): Nat = word64ToNat x; + public func toWord8 (x : Nat) : Word8 = natToWord8 x; + public func toWord16(x : Nat) : Word16 = natToWord16 x; + public func toWord32(x : Nat) : Word32 = natToWord32 x; + public func toWord64(x : Nat) : Word64 = natToWord64 x; + + public func fromNat8 (x : Nat8): Nat = nat8ToNat x; + public func fromNat16(x : Nat16): Nat = nat16ToNat x; + public func fromNat32(x : Nat32): Nat = nat32ToNat x; + public func fromNat64(x : Nat64): Nat = nat64ToNat x; + public func toNat8 (x : Nat) : Nat8 = natToNat8 x; + public func toNat16(x : Nat) : Nat16 = natToNat16 x; + public func toNat32(x : Nat) : Nat32 = natToNat32 x; + public func toNat64(x : Nat) : Nat64 = natToNat64 x; + } From 8e485d30ef2aabc841b1b9047f384ef3e57709f7 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 10 Jan 2020 18:34:10 +0100 Subject: [PATCH 0910/1176] Empty out the prelude (#1088) this implements the plan in https://github.com/dfinity-lab/motoko/pull/867#issuecomment-558708888 No values are in scope by default; the prelude only define type names. In bare uses of Motoko: Use `import Prim "mo:prim"` to get `Prim.debugPrint` etc. In real uses, the `stdlib` should provide everything you need. Also moves the lsp test project into its own directory, to avoid spurious recompilation of the `lsp-int` binary. --- default.nix | 2 +- design/DFX-Interface.md | 2 + samples/ListClient.mo | 4 +- samples/ListClient.txt | 1 + samples/app/client.mo | 3 +- samples/app/server.mo | 3 +- src/ir_def/check_ir.ml | 10 +- src/lowering/desugar.ml | 10 +- src/pipeline/pipeline.ml | 19 +- src/prelude/prelude.ml | 371 +++++++++--------- stdlib/Makefile | 4 + stdlib/array.mo | 24 +- stdlib/blob.mo | 4 + stdlib/buf.mo | 10 +- stdlib/bufTest.mo | 12 +- stdlib/debug.mo | 3 +- stdlib/examples/actorspec/src/ActorSpec.mo | 11 +- .../examples/produce-exchange/serverActor.mo | 3 +- .../examples/produce-exchange/serverModel.mo | 55 +-- .../produce-exchange/test/evalBulk.mo | 107 ++--- .../test/producerRemInventory.mo | 109 ++--- .../test/profileFastCounts.mo | 27 +- .../test/retailerReserveMany.mo | 171 ++++---- .../test/simpleSetupAndQuery.mo | 123 +++--- stdlib/hash.mo | 37 +- stdlib/hashMap.mo | 17 +- stdlib/hashMapTest.mo | 13 +- stdlib/int.mo | 19 +- stdlib/iter.mo | 7 + stdlib/list.mo | 2 +- stdlib/nat.mo | 33 +- stdlib/prelude.mo | 4 +- stdlib/result.mo | 3 +- stdlib/text.mo | 4 +- stdlib/trie.mo | 40 +- stdlib/trieMap.mo | 5 +- stdlib/trieMapTest.mo | 13 +- test/fail/actor-reexport.mo | 4 +- test/fail/branch-before-define.mo | 6 +- test/fail/issue-894-fail.mo | 5 +- test/fail/objpat-infer.mo | 4 +- test/fail/objpat-mutable.mo | 10 +- test/fail/ok/actor-reexport.tc.ok | 6 +- test/fail/ok/branch-before-define.tc.ok | 2 +- test/fail/ok/issue-894-fail.tc.ok | 4 +- test/fail/ok/modexp5.tc.ok | 2 +- test/fail/ok/objpat-infer.tc.ok | 12 +- test/fail/ok/objpat-mutable.tc.ok | 2 +- test/fail/ok/return-before-define.tc.ok | 2 +- test/fail/ok/use-before-define.tc.ok | 2 +- test/fail/return-before-define.mo | 6 +- test/fail/use-before-define.mo | 4 +- .../.gitignore | 0 .../ListClient.mo | 0 .../app.mo | 0 .../lib/ListFuncs.mo | 0 .../lib/ListLib.mo | 0 .../lib/list.mo | 0 .../lib/option.mo | 5 +- .../lib/prelude.mo | 3 +- .../mydependency/broken.mo | 0 .../mydependency/lib.mo | 0 test/mo-idl/ok/pa_cars.did.ok | 4 +- test/mo-idl/ok/result.did.ok | 10 +- test/perf/reversi.mo | 25 +- test/random/Main.hs | 31 +- test/repl/ok/double-import.stdout.ok | 4 +- test/repl/ok/outrange-int-nat.stdout.ok | 25 +- test/repl/ok/triangle-import.stdout.ok | 8 +- test/repl/outrange-int-nat.sh | 49 +-- test/run-drun/GIT-843.mo | 3 +- test/run-drun/actor-creation.mo | 20 +- test/run-drun/array-out-of-bounds.mo | 5 +- test/run-drun/async-free-var.mo | 15 +- test/run-drun/async-loop-while.mo | 9 +- test/run-drun/async-loop.mo | 18 +- test/run-drun/async-new-obj.mo | 11 +- test/run-drun/async-obj-mut.mo | 15 +- test/run-drun/async-while.mo | 9 +- test/run-drun/await.mo | 31 +- test/run-drun/block.mo | 19 +- test/run-drun/caller.mo | 3 +- test/run-drun/chat.mo | 5 +- test/run-drun/closure-params.mo | 5 +- test/run-drun/count-callbacks.mo | 21 +- test/run-drun/counter.mo | 5 +- test/run-drun/counter2.mo | 5 +- test/run-drun/create-then-trap.mo | 9 +- test/run-drun/data-params.mo | 57 +-- test/run-drun/flatten-awaitables.mo | 69 ++-- test/run-drun/for-await.mo | 10 +- test/run-drun/free-callbacks.mo | 13 +- test/run-drun/generic-tail-rec.mo | 9 +- test/run-drun/hello-world-async.mo | 5 +- test/run-drun/hello-world-await.mo | 3 +- test/run-drun/hello-world-message.mo | 3 +- test/run-drun/hello-world.mo | 3 +- test/run-drun/idl-any.mo | 3 +- test/run-drun/idl-nat-int.mo | 6 +- test/run-drun/idl-option.mo | 5 +- test/run-drun/idl-record.mo | 9 +- test/run-drun/idl-tuple.mo | 5 +- test/run-drun/idl-variant.mo | 4 +- test/run-drun/idl-vector.mo | 5 +- test/run-drun/indirect-counter.mo | 21 - test/run-drun/interleave.mo | 13 +- test/run-drun/issue-894.mo | 13 +- test/run-drun/large-array.mo | 4 +- test/run-drun/local-throw.mo | 17 +- test/run-drun/log-slow.mo | 109 ++--- test/run-drun/nary-async.mo | 17 +- .../run-drun/ok/array-out-of-bounds.run-ir.ok | 4 +- .../ok/array-out-of-bounds.run-low.ok | 4 +- test/run-drun/ok/array-out-of-bounds.run.ok | 4 +- test/run-drun/ok/async-free-var.comp.ok | 2 +- test/run-drun/ok/async-loop-while.comp.ok | 6 +- test/run-drun/ok/async-loop.comp.ok | 6 + ...-loop.tc.ret.ok => async-loop.comp.ret.ok} | 0 ...-stub-run.ok => async-loop.ic-stub-run.ok} | 3 - test/run-drun/ok/async-loop.tc.ok | 1 - test/run-drun/ok/async-new-obj.comp.ok | 2 +- test/run-drun/ok/async-obj-mut.comp.ok | 2 +- test/run-drun/ok/async-while.comp.ok | 6 +- test/run-drun/ok/await.comp.ok | 2 +- test/run-drun/ok/block.comp.ok | 2 +- test/run-drun/ok/count-callbacks.comp.ok | 16 +- test/run-drun/ok/create-then-trap.comp.ok | 2 +- .../ok/create-then-trap.ic-stub-run.ok | 7 - test/run-drun/ok/create-then-trap.run-ir.ok | 2 +- test/run-drun/ok/create-then-trap.run-low.ok | 2 +- test/run-drun/ok/create-then-trap.run.ok | 2 +- test/run-drun/ok/data-params.tc.ok | 2 +- test/run-drun/ok/flatten-awaitables.tc.ok | 48 +-- test/run-drun/ok/for-await.comp.ok | 2 +- .../ok/indirect-counter.ic-stub-run.ok | 8 - test/run-drun/ok/indirect-counter.run-ir.ok | 4 - test/run-drun/ok/indirect-counter.run-low.ok | 4 - test/run-drun/ok/indirect-counter.run.ok | 4 - test/run-drun/ok/interleave.comp.ok | 2 +- test/run-drun/ok/issue-894.comp.ok | 6 +- test/run-drun/ok/nary-async.comp.ok | 16 +- test/run-drun/ok/overflow.comp.ok | 12 +- test/run-drun/ok/overflow.run-ir.ok | 2 +- test/run-drun/ok/overflow.run-low.ok | 2 +- test/run-drun/ok/overflow.run.ok | 2 +- test/run-drun/ok/pass-references.comp.ok | 2 +- .../ok/pass-references.ic-stub-run.ok | 1 + test/run-drun/ok/pass-references.run-ir.ok | 1 + test/run-drun/ok/pass-references.run-low.ok | 1 + test/run-drun/ok/pass-references.run.ok | 1 + test/run-drun/ok/query2.run-ir.ok | 2 +- test/run-drun/ok/query2.run-low.ok | 2 +- test/run-drun/ok/query2.run.ok | 2 +- test/run-drun/ok/show-in-actor.comp.ok | 2 - test/run-drun/ok/show-in-actor.comp.ret.ok | 1 - test/run-drun/ok/test_oneway.tc.ok | 2 +- test/run-drun/ok/throw.comp.ok | 4 +- test/run-drun/oneway-throw.mo | 13 +- test/run-drun/oneway.mo | 39 +- test/run-drun/oom.mo | 3 +- test/run-drun/overflow.mo | 13 +- test/run-drun/pass-references.mo | 14 +- test/run-drun/print-from-init.mo | 3 +- test/run-drun/query.mo | 7 +- test/run-drun/query2.mo | 11 +- test/run-drun/reference-params.mo | 8 +- test/run-drun/reject.mo | 22 +- test/run-drun/rts-stats.mo | 17 +- test/run-drun/selftail.mo | 7 +- test/run-drun/show-in-actor.mo | 11 +- test/run-drun/show.mo | 71 ++-- test/run-drun/tailpositions.mo | 15 +- test/run-drun/text-iter.mo | 67 ++-- test/run-drun/throw.mo | 17 +- test/run-drun/transpose.mo | 7 +- test/run.sh | 1 + test/run/array-gen.mo | 6 +- test/run/caller.mo | 3 +- test/run/char-high-surrogate-trap.mo | 3 +- test/run/char-low-surrogate-trap.mo | 3 +- test/run/char-trap.mo | 3 +- test/run/chatpp.mo | 8 +- test/run/conversions.mo | 342 ++++++++-------- test/run/debug-release.mo | 8 +- test/run/debug.mo | 4 +- test/run/dec-bug.mo | 7 + test/run/for.mo | 9 +- test/run/hashes.mo | 17 + test/run/huge-string.mo | 11 +- test/run/idlHash.mo | 8 +- test/run/issue83.mo | 6 +- test/run/numeric-ops.mo | 10 +- test/run/objects1.mo | 3 +- test/run/ok/caller.comp.ok | 2 +- .../run/ok/char-high-surrogate-trap.run-ir.ok | 2 +- .../ok/char-high-surrogate-trap.run-low.ok | 2 +- test/run/ok/char-high-surrogate-trap.run.ok | 2 +- test/run/ok/char-low-surrogate-trap.run-ir.ok | 2 +- .../run/ok/char-low-surrogate-trap.run-low.ok | 2 +- test/run/ok/char-low-surrogate-trap.run.ok | 2 +- test/run/ok/char-trap.run-ir.ok | 2 +- test/run/ok/char-trap.run-low.ok | 2 +- test/run/ok/char-trap.run.ok | 2 +- test/run/ok/idlHash.run-ir.ok | 20 +- test/run/ok/idlHash.run-low.ok | 20 +- test/run/ok/idlHash.run.ok | 20 +- test/run/ok/objects1.comp.ok | 4 +- test/run/ok/objects1.run-ir.ok | 4 +- test/run/ok/objects1.run-low.ok | 4 +- test/run/ok/objects1.run.ok | 4 +- test/run/ok/objects1.tc.ok | 8 +- test/run/ok/type-inference.tc.ok | 18 +- test/run/print.mo | 5 +- test/run/rts.mo | 4 +- test/run/show.mo | 74 ++-- test/run/text-iter.mo | 68 ++-- test/run/type-inference.mo | 30 +- test/run/variants.mo | 6 +- test/run/words.mo | 76 ++-- test/trap/divInt16.mo | 3 +- test/trap/divInt32.mo | 3 +- test/trap/divInt64.mo | 3 +- test/trap/divInt8.mo | 3 +- test/trap/ok/divInt16.run-ir.ok | 2 +- test/trap/ok/divInt16.run-low.ok | 2 +- test/trap/ok/divInt16.run.ok | 2 +- test/trap/ok/divInt32.run-ir.ok | 2 +- test/trap/ok/divInt32.run-low.ok | 2 +- test/trap/ok/divInt32.run.ok | 2 +- test/trap/ok/divInt64.run-ir.ok | 2 +- test/trap/ok/divInt64.run-low.ok | 2 +- test/trap/ok/divInt64.run.ok | 2 +- test/trap/ok/divInt8.run-ir.ok | 2 +- test/trap/ok/divInt8.run-low.ok | 2 +- test/trap/ok/divInt8.run.ok | 2 +- test/trap/ok/outrange-int16-lower.run-ir.ok | 2 +- test/trap/ok/outrange-int16-lower.run-low.ok | 2 +- test/trap/ok/outrange-int16-lower.run.ok | 2 +- .../trap/ok/outrange-int16-negation.run-ir.ok | 2 +- .../ok/outrange-int16-negation.run-low.ok | 2 +- test/trap/ok/outrange-int16-negation.run.ok | 2 +- test/trap/ok/outrange-int16-upper.run-ir.ok | 2 +- test/trap/ok/outrange-int16-upper.run-low.ok | 2 +- test/trap/ok/outrange-int16-upper.run.ok | 2 +- test/trap/ok/outrange-int32-lower.run-ir.ok | 2 +- test/trap/ok/outrange-int32-lower.run-low.ok | 2 +- test/trap/ok/outrange-int32-lower.run.ok | 2 +- .../trap/ok/outrange-int32-negation.run-ir.ok | 2 +- .../ok/outrange-int32-negation.run-low.ok | 2 +- test/trap/ok/outrange-int32-negation.run.ok | 2 +- test/trap/ok/outrange-int32-upper.run-ir.ok | 2 +- test/trap/ok/outrange-int32-upper.run-low.ok | 2 +- test/trap/ok/outrange-int32-upper.run.ok | 2 +- test/trap/ok/outrange-int64-lower.run-ir.ok | 2 +- test/trap/ok/outrange-int64-lower.run-low.ok | 2 +- test/trap/ok/outrange-int64-lower.run.ok | 2 +- .../trap/ok/outrange-int64-negation.run-ir.ok | 2 +- .../ok/outrange-int64-negation.run-low.ok | 2 +- test/trap/ok/outrange-int64-negation.run.ok | 2 +- test/trap/ok/outrange-int64-upper.run-ir.ok | 2 +- test/trap/ok/outrange-int64-upper.run-low.ok | 2 +- test/trap/ok/outrange-int64-upper.run.ok | 2 +- test/trap/ok/outrange-int8-lower.run-ir.ok | 2 +- test/trap/ok/outrange-int8-lower.run-low.ok | 2 +- test/trap/ok/outrange-int8-lower.run.ok | 2 +- test/trap/ok/outrange-int8-negation.run-ir.ok | 2 +- .../trap/ok/outrange-int8-negation.run-low.ok | 2 +- test/trap/ok/outrange-int8-negation.run.ok | 2 +- test/trap/ok/outrange-int8-upper.run-ir.ok | 2 +- test/trap/ok/outrange-int8-upper.run-low.ok | 2 +- test/trap/ok/outrange-int8-upper.run.ok | 2 +- test/trap/ok/outrange-nat16.run-ir.ok | 2 +- test/trap/ok/outrange-nat16.run-low.ok | 2 +- test/trap/ok/outrange-nat16.run.ok | 2 +- test/trap/ok/outrange-nat32.run-ir.ok | 2 +- test/trap/ok/outrange-nat32.run-low.ok | 2 +- test/trap/ok/outrange-nat32.run.ok | 2 +- test/trap/ok/outrange-nat64.run-ir.ok | 2 +- test/trap/ok/outrange-nat64.run-low.ok | 2 +- test/trap/ok/outrange-nat64.run.ok | 2 +- test/trap/ok/outrange-nat8.run-ir.ok | 2 +- test/trap/ok/outrange-nat8.run-low.ok | 2 +- test/trap/ok/outrange-nat8.run.ok | 2 +- test/trap/outrange-int16-lower.mo | 3 +- test/trap/outrange-int16-negation.mo | 3 +- test/trap/outrange-int16-upper.mo | 3 +- test/trap/outrange-int32-lower.mo | 3 +- test/trap/outrange-int32-negation.mo | 3 +- test/trap/outrange-int32-upper.mo | 3 +- test/trap/outrange-int64-lower.mo | 3 +- test/trap/outrange-int64-negation.mo | 3 +- test/trap/outrange-int64-upper.mo | 3 +- test/trap/outrange-int8-lower.mo | 3 +- test/trap/outrange-int8-negation.mo | 3 +- test/trap/outrange-int8-upper.mo | 3 +- test/trap/outrange-nat16.mo | 3 +- test/trap/outrange-nat32.mo | 3 +- test/trap/outrange-nat64.mo | 3 +- test/trap/outrange-nat8.mo | 3 +- 299 files changed, 1976 insertions(+), 1727 deletions(-) create mode 100644 stdlib/blob.mo rename test/{lsp-int/test-project => lsp-int-test-project}/.gitignore (100%) rename test/{lsp-int/test-project => lsp-int-test-project}/ListClient.mo (100%) rename test/{lsp-int/test-project => lsp-int-test-project}/app.mo (100%) rename test/{lsp-int/test-project => lsp-int-test-project}/lib/ListFuncs.mo (100%) rename test/{lsp-int/test-project => lsp-int-test-project}/lib/ListLib.mo (100%) rename test/{lsp-int/test-project => lsp-int-test-project}/lib/list.mo (100%) rename test/{lsp-int/test-project => lsp-int-test-project}/lib/option.mo (95%) rename test/{lsp-int/test-project => lsp-int-test-project}/lib/prelude.mo (94%) rename test/{lsp-int/test-project => lsp-int-test-project}/mydependency/broken.mo (100%) rename test/{lsp-int/test-project => lsp-int-test-project}/mydependency/lib.mo (100%) delete mode 100644 test/run-drun/indirect-counter.mo create mode 100644 test/run-drun/ok/async-loop.comp.ok rename test/run-drun/ok/{async-loop.tc.ret.ok => async-loop.comp.ret.ok} (100%) rename test/run-drun/ok/{show-in-actor.ic-stub-run.ok => async-loop.ic-stub-run.ok} (62%) delete mode 100644 test/run-drun/ok/async-loop.tc.ok delete mode 100644 test/run-drun/ok/create-then-trap.ic-stub-run.ok delete mode 100644 test/run-drun/ok/indirect-counter.ic-stub-run.ok delete mode 100644 test/run-drun/ok/indirect-counter.run-ir.ok delete mode 100644 test/run-drun/ok/indirect-counter.run-low.ok delete mode 100644 test/run-drun/ok/indirect-counter.run.ok delete mode 100644 test/run-drun/ok/show-in-actor.comp.ok delete mode 100644 test/run-drun/ok/show-in-actor.comp.ret.ok diff --git a/default.nix b/default.nix index 4cb34d7ed5b..27edd1e04e1 100644 --- a/default.nix +++ b/default.nix @@ -271,7 +271,7 @@ rec { let lsp = testDerivation { name = "test-lsp"; - src = subpath ./test/lsp-int/test-project; + src = subpath ./test/lsp-int-test-project; buildInputs = [ moc haskellPackages.lsp-int ]; checkPhase = '' echo running lsp-int diff --git a/design/DFX-Interface.md b/design/DFX-Interface.md index 3ab8f40d127..cb899a61a40 100644 --- a/design/DFX-Interface.md +++ b/design/DFX-Interface.md @@ -62,6 +62,8 @@ This _reads_ the following files * for every actor import `ic:canisterid` imported by any of the Motoko files, it reads `actorpath/canisterid.did`, see section Resolving Canister Ids below. * the given `mo-rts.wasm` file. +The package name `prim` is special and should not be set using `--package`. + No constraints are imposed where imported files reside (this may be refined to prevent relative imports from looking outside the project and the declared packages) This _writes_ to `another/path/output.wasm`, but has no other effect. It does diff --git a/samples/ListClient.mo b/samples/ListClient.mo index f8c8647fcdf..6df35c58472 100644 --- a/samples/ListClient.mo +++ b/samples/ListClient.mo @@ -1,7 +1,7 @@ -module { - import List = "ListLib.mo"; // private, so we don't re-export List +module { + public type Stack = List.List; public func push(x : Int, s : Stack) : Stack = List.cons(x, s); diff --git a/samples/ListClient.txt b/samples/ListClient.txt index 03f7ebe32f4..1f93f337921 100644 --- a/samples/ListClient.txt +++ b/samples/ListClient.txt @@ -3,6 +3,7 @@ -- Checking ListLib.mo: -- Definedness ListLib.mo: -- Checking ListClient.mo: +let List : module {type List = ?(T, List); cons : (T, List) -> List; nil : () -> List} -- Definedness ListClient.mo: -- Interpreting ListLib.mo: -- Interpreting ListClient.mo: diff --git a/samples/app/client.mo b/samples/app/client.mo index 07ae7b5d0b1..4de8d62e10a 100644 --- a/samples/app/client.mo +++ b/samples/app/client.mo @@ -1,3 +1,4 @@ +import Prim "mo:prim"; import S "server.mo"; actor class Client() = this { @@ -17,7 +18,7 @@ actor class Client() = this { }; public func send(msg : Text) { - debugPrint(name # " received " # msg # "\n"); + Prim.debugPrint(name # " received " # msg # "\n"); }; }; diff --git a/samples/app/server.mo b/samples/app/server.mo index afcccab76c6..787b5e4f121 100644 --- a/samples/app/server.mo +++ b/samples/app/server.mo @@ -1,3 +1,4 @@ +import Prim "mo:prim"; import L "list.mo"; import T "types.mo"; @@ -49,7 +50,7 @@ actor class Server() = { case null { clients := n.tail }; case (?p) { p.tail := n.tail }; }; - debugPrint "(unsubscribe "; debugPrintInt id; debugPrint ")\n"; + Prim.debugPrint "(unsubscribe "; Prim.debugPrintInt id; Prim.debugPrint ")\n"; return; }; prev := next; diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index ef1f08fdac9..94f4bddf5a5 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -391,6 +391,10 @@ let rec check_exp env (exp:Ir.exp) : unit = error env exp1.at "expected function type, but expression produces type\n %s" (T.string_of_typ_expand t1) end + | NumConvPrim (p1, p2), [e] -> + (* we could check if this conversion is supported *) + typ e <: T.Prim p1; + T.Prim p2 <: t | CastPrim (t1, t2), [e] -> typ e <: t1; t2 <: t @@ -406,8 +410,9 @@ let rec check_exp env (exp:Ir.exp) : unit = end; actor_typ <: t; | OtherPrim _, _ -> () - | _ -> - error env exp.at "PrimE with wrong number of arguments" + | p, args -> + error env exp.at "PrimE %s does not work with %d arguments" + (Wasm.Sexpr.to_string 80 (Arrange_ir.prim p)) (List.length args); end | TupE exps -> List.iter (check_exp env) exps; @@ -924,4 +929,3 @@ let check_prog verbose scope phase (((ds, exp), flavor) as prog) : unit = Printf.eprintf "%s" bt; end; exit 1 - diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 76a29b083fe..7b3b33a00d0 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -103,16 +103,18 @@ and exp' at note = function | S.CallE ({it=S.AnnotE ({it=S.PrimE p;_}, _);note;_}, _, e) when Lib.String.chop_prefix "num_conv" p <> None -> begin match String.split_on_char '_' p with - | [_;_;s1;s2] -> + | ["num";"conv";s1;s2] -> let p1 = Type.prim s1 in let p2 = Type.prim s2 in I.PrimE (I.NumConvPrim (p1, p2), [exp e]) | _ -> assert false end | S.CallE ({it=S.AnnotE ({it=S.PrimE "cast";_}, _);note;_}, _, e) -> - let p1 = e.note.S.note_typ in - let p2 = note.S.note_typ in - I.PrimE (I.CastPrim (p1, p2), [exp e]) + begin match note.S.note_typ with + | T.Func (T.Local, T.Returns, [], ts1, ts2) -> + I.PrimE (I.CastPrim (T.seq ts1, T.seq ts2), [exp e]) + | _ -> assert false + end | S.CallE ({it=S.AnnotE ({it=S.PrimE p;_},_);_}, _, {it=S.TupE es;_}) -> I.PrimE (I.OtherPrim p, exps es) | S.CallE ({it=S.AnnotE ({it=S.PrimE p;_},_);_}, _, e) -> diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index bdda4a6f483..6ad39b07036 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -40,11 +40,18 @@ let print_stat_ve = let print_dyn_ve scope = Value.Env.iter (fun x d -> - let t = Type.Env.find x scope.Scope.val_env in - let t' = Type.as_immut t in - printf "%s %s : %s = %s\n" - (if t == t' then "let" else "var") x - (Type.string_of_typ t') (Value.string_of_def !Flags.print_depth d) + let open Type in + let t = Env.find x scope.Scope.val_env in + let t' = as_immut t in + match normalize t' with + | Obj (Module, fs) -> + printf "%s %s : module {...}\n" + (if t == t' then "let" else "var") x + | _ -> + printf "%s %s : %s = %s\n" + (if t == t' then "let" else "var") x + (Type.string_of_typ t') + (Value.string_of_def !Flags.print_depth d) ) let print_scope senv scope dve = @@ -283,7 +290,7 @@ let chase_imports parsefn senv0 imports : (Syntax.lib list * Scope.scope) Diag.r let rec go ri = match ri.Source.it with | Syntax.PrimPath -> - (* a bit of an hack, lib_env should key on resolved_import *) + (* a bit of a hack, lib_env should key on resolved_import *) if Type.Env.mem "@prim" !senv.Scope.lib_env then Diag.return () else diff --git a/src/prelude/prelude.ml b/src/prelude/prelude.ml index 139ba3b1ae7..e23278e6320 100644 --- a/src/prelude/prelude.ml +++ b/src/prelude/prelude.ml @@ -2,7 +2,6 @@ The prelude. This stuff is always initially in scope. This should be only * type definitions for primitive types * code with privileged names (@…) that are used by the desugarer or ir-passes - (the moving of the definitions is done in #1088) *) let prelude = {| @@ -30,19 +29,10 @@ type Text = prim "Text"; type Blob = prim "Blob"; type Error = prim "Error"; -type Iter = {next : () -> ?T_}; +type @Iter = {next : () -> ?T_}; -func abs(x : Int) : Nat { (prim "abs" : Int -> Nat) x }; - -class range(x : Nat, y : Nat) { - var i = x; - public func next() : ?Nat { if (i > y) null else {let j = i; i += 1; ?j} }; -}; - -class revrange(x : Nat, y : Nat) { - var i = x + 1; - public func next() : ?Nat { if (i <= y) null else {i -= 1; ?i} }; -}; +// The @ in the name ensures that this cannot be shadowed by user code, so +// compiler passes can rely on them being in scope // Implementations for overloaded dot operations // Note that these return functions! @@ -58,34 +48,34 @@ func @mut_array_len(xs : [var A]) : (() -> Nat) = (func () : Nat = (prim "array_len" : ([var A]) -> Nat) xs); func @mut_array_set(xs : [var A]) : ((Nat, A) -> ()) = (func (n : Nat, x : A) = (xs[n] := x)); -func @immut_array_keys(xs : [A]) : (() -> Iter) = - (func () : Iter = object { +func @immut_array_keys(xs : [A]) : (() -> @Iter) = + (func () : @Iter = object { var i = 0; let l = xs.len(); public func next() : ?Nat { if (i >= l) null else {let j = i; i += 1; ?j} }; }); -func @mut_array_keys(xs : [var A]) : (() -> Iter) = - (func () : Iter = object { +func @mut_array_keys(xs : [var A]) : (() -> @Iter) = + (func () : @Iter = object { var i = 0; let l = xs.len(); public func next() : ?Nat { if (i >= l) null else {let j = i; i += 1; ?j} }; }); -func @immut_array_vals(xs : [A]) : (() -> Iter) = - (func () : Iter = object { +func @immut_array_vals(xs : [A]) : (() -> @Iter) = + (func () : @Iter = object { var i = 0; let l = xs.len(); public func next() : ?A { if (i >= l) null else {let j = i; i += 1; ?xs[j]} }; }); -func @mut_array_vals(xs : [var A]) : (() -> Iter) = - (func () : Iter = object { +func @mut_array_vals(xs : [var A]) : (() -> @Iter) = + (func () : @Iter = object { var i = 0; let l = xs.len(); public func next() : ?A { if (i >= l) null else {let j = i; i += 1; ?xs[j]} }; }); func @text_len(xs : Text) : (() -> Nat) = (func () : Nat = (prim "text_len" : Text -> Nat) xs); -func @text_chars(xs : Text) : (() -> Iter) = - (func () : Iter = object { +func @text_chars(xs : Text) : (() -> @Iter) = + (func () : @Iter = object { type TextIter = Any; // not exposed let i = (prim "text_iter" : Text -> TextIter) xs; public func next() : ?Char { @@ -96,125 +86,9 @@ func @text_chars(xs : Text) : (() -> Iter) = }; }); -// for testing -func idlHash(x : Text) : Word32 { (prim "idlHash" : Text -> Word32) x }; - -func debugPrint(x : Text) { (prim "print" : Text -> ()) x }; -func debugPrintNat(x : Nat) { debugPrint (@text_of_Nat x) }; -func debugPrintInt(x : Int) { debugPrint (@text_of_Int x) }; -func debugPrintChar(x : Char) { debugPrint (charToText x) }; -func rts_version() : Text { (prim "rts_version" : () -> Text) () }; -func rts_heap_size() : Nat { (prim "rts_heap_size" : () -> Nat) () }; -func rts_total_allocation() : Nat { (prim "rts_total_allocation" : () -> Nat) () }; -func rts_callback_table_count() : Nat { (prim "rts_callback_table_count" : () -> Nat) () }; -func rts_callback_table_size() : Nat { (prim "rts_callback_table_size" : () -> Nat) () }; - -// Hashing -func hashInt(x : Int) : Word32 { - var n = x; - var hash : Word32 = 0; - if (n < 0) { - hash := ^hash; - n := abs n; - }; - let base = 2**32; - while (n > 0) { - hash ^= intToWord32(n % base); - n /= base; - }; - return hash; -}; - -func hashBlob(b : Blob) : Word32 { (prim "crc32Hash" : Blob -> Word32) b }; - -// Conversions - -func int64ToInt(n : Int64) : Int = (prim "num_conv_Int64_Int" : Int64 -> Int) n; -func intToInt64(n : Int) : Int64 = (prim "num_conv_Int_Int64" : Int -> Int64) n; -func int64ToWord64(n : Int64) : Word64 = (prim "num_conv_Int64_Word64" : Int64 -> Word64) n; -func word64ToInt64(n : Word64) : Int64 = (prim "num_conv_Word64_Int64" : Word64 -> Int64) n; -func int32ToInt(n : Int32) : Int = (prim "num_conv_Int32_Int" : Int32 -> Int) n; -func intToInt32(n : Int) : Int32 = (prim "num_conv_Int_Int32" : Int -> Int32) n; -func int32ToWord32(n : Int32) : Word32 = (prim "num_conv_Int32_Word32" : Int32 -> Word32) n; -func word32ToInt32(n : Word32) : Int32 = (prim "num_conv_Word32_Int32" : Word32 -> Int32) n; -func int16ToInt(n : Int16) : Int = (prim "num_conv_Int16_Int" : Int16 -> Int) n; -func intToInt16(n : Int) : Int16 = (prim "num_conv_Int_Int16" : Int -> Int16) n; -func int16ToWord16(n : Int16) : Word16 = (prim "num_conv_Int16_Word16" : Int16 -> Word16) n; -func word16ToInt16(n : Word16) : Int16 = (prim "num_conv_Word16_Int16" : Word16 -> Int16) n; -func int8ToInt(n : Int8) : Int = (prim "num_conv_Int8_Int" : Int8 -> Int) n; -func intToInt8(n : Int) : Int8 = (prim "num_conv_Int_Int8" : Int -> Int8) n; -func int8ToWord8(n : Int8) : Word8 = (prim "num_conv_Int8_Word8" : Int8 -> Word8) n; -func word8ToInt8(n : Word8) : Int8 = (prim "num_conv_Word8_Int8" : Word8 -> Int8) n; - -func nat64ToNat(n : Nat64) : Nat = (prim "num_conv_Nat64_Nat" : Nat64 -> Nat) n; -func natToNat64(n : Nat) : Nat64 = (prim "num_conv_Nat_Nat64" : Nat -> Nat64) n; -func nat64ToWord64(n : Nat64) : Word64 = (prim "num_conv_Nat64_Word64" : Nat64 -> Word64) n; -func word64ToNat64(n : Word64) : Nat64 = (prim "num_conv_Word64_Nat64" : Word64 -> Nat64) n; -func nat32ToNat(n : Nat32) : Nat = (prim "num_conv_Nat32_Nat" : Nat32 -> Nat) n; -func natToNat32(n : Nat) : Nat32 = (prim "num_conv_Nat_Nat32" : Nat -> Nat32) n; -func nat32ToWord32(n : Nat32) : Word32 = (prim "num_conv_Nat32_Word32" : Nat32 -> Word32) n; -func word32ToNat32(n : Word32) : Nat32 = (prim "num_conv_Word32_Nat32" : Word32 -> Nat32) n; -func nat16ToNat(n : Nat16) : Nat = (prim "num_conv_Nat16_Nat" : Nat16 -> Nat) n; -func natToNat16(n : Nat) : Nat16 = (prim "num_conv_Nat_Nat16" : Nat -> Nat16) n; -func nat16ToWord16(n : Nat16) : Word16 = (prim "num_conv_Nat16_Word16" : Nat16 -> Word16) n; -func word16ToNat16(n : Word16) : Nat16 = (prim "num_conv_Word16_Nat16" : Word16 -> Nat16) n; -func nat8ToNat(n : Nat8) : Nat = (prim "num_conv_Nat8_Nat" : Nat8 -> Nat) n; -func natToNat8(n : Nat) : Nat8 = (prim "num_conv_Nat_Nat8" : Nat -> Nat8) n; -func nat8ToWord8(n : Nat8) : Word8 = (prim "num_conv_Nat8_Word8" : Nat8 -> Word8) n; -func word8ToNat8(n : Word8) : Nat8 = (prim "num_conv_Word8_Nat8" : Word8 -> Nat8) n; - - -func natToWord8(n : Nat) : Word8 = (prim "num_conv_Nat_Word8" : Nat -> Word8) n; -func word8ToNat(n : Word8) : Nat = (prim "num_conv_Word8_Nat" : Word8 -> Nat) n; -func intToWord8(n : Int) : Word8 = (prim "num_conv_Int_Word8" : Int -> Word8) n; -func word8ToInt(n : Word8) : Int = (prim "num_conv_Word8_Int" : Word8 -> Int) n; - -func natToWord16(n : Nat) : Word16 = (prim "num_conv_Nat_Word16" : Nat -> Word16) n; -func word16ToNat(n : Word16) : Nat = (prim "num_conv_Word16_Nat" : Word16 -> Nat) n; -func intToWord16(n : Int) : Word16 = (prim "num_conv_Int_Word16" : Int -> Word16) n; -func word16ToInt(n : Word16) : Int = (prim "num_conv_Word16_Int" : Word16 -> Int) n; - -func natToWord32(n : Nat) : Word32 = (prim "num_conv_Nat_Word32" : Nat -> Word32) n; -func word32ToNat(n : Word32) : Nat = (prim "num_conv_Word32_Nat" : Word32 -> Nat) n; -func intToWord32(n : Int) : Word32 = (prim "num_conv_Int_Word32" : Int -> Word32) n; -func word32ToInt(n : Word32) : Int = (prim "num_conv_Word32_Int" : Word32 -> Int) n; - -func natToWord64(n : Nat) : Word64 = (prim "num_conv_Nat_Word64" : Nat -> Word64) n; -func word64ToNat(n : Word64) : Nat = (prim "num_conv_Word64_Nat" : Word64 -> Nat) n; -func intToWord64(n : Int) : Word64 = (prim "num_conv_Int_Word64" : Int -> Word64) n; -func word64ToInt(n : Word64) : Int = (prim "num_conv_Word64_Int" : Word64 -> Int) n; - -func charToWord32(c : Char) : Word32 = (prim "num_conv_Char_Word32" : Char -> Word32) c; -func word32ToChar(w : Word32) : Char = (prim "num_conv_Word32_Char" : Word32 -> Char) w; - -func charToText(c : Char) : Text = (prim "conv_Char_Text" : Char -> Text) c; - -// Exotic bitwise operations -func popcntWord8(w : Word8) : Word8 = (prim "popcnt8" : Word8 -> Word8) w; -func clzWord8(w : Word8) : Word8 = (prim "clz8" : Word8 -> Word8) w; -func ctzWord8(w : Word8) : Word8 = (prim "ctz8" : Word8 -> Word8) w; -func btstWord8(w : Word8, amount : Word8) : Bool = (prim "btst8" : (Word8, Word8) -> Word8) (w, amount) != (0 : Word8); - -func popcntWord16(w : Word16) : Word16 = (prim "popcnt16" : Word16 -> Word16) w; -func clzWord16(w : Word16) : Word16 = (prim "clz16" : Word16 -> Word16) w; -func ctzWord16(w : Word16) : Word16 = (prim "ctz16" : Word16 -> Word16) w; -func btstWord16(w : Word16, amount : Word16) : Bool = (prim "btst16" : (Word16, Word16) -> Word16) (w, amount) != (0 : Word16); - -func popcntWord32(w : Word32) : Word32 = (prim "popcnt32" : Word32 -> Word32) w; -func clzWord32(w : Word32) : Word32 = (prim "clz32" : Word32 -> Word32) w; -func ctzWord32(w : Word32) : Word32 = (prim "ctz32" : Word32 -> Word32) w; -func btstWord32(w : Word32, amount : Word32) : Bool = (prim "btst32" : (Word32, Word32) -> Word32) (w, amount) != (0 : Word32); - -func popcntWord64(w : Word64) : Word64 = (prim "popcnt64" : Word64 -> Word64) w; -func clzWord64(w : Word64) : Word64 = (prim "clz64" : Word64 -> Word64) w; -func ctzWord64(w : Word64) : Word64 = (prim "ctz64" : Word64 -> Word64) w; -func btstWord64(w : Word64, amount : Word64) : Bool = (prim "btst64" : (Word64, Word64) -> Word64) (w, amount) != (0 : Word64); - // Internal helper functions for the show translation -// The @ in the name ensures that this cannot be shadowed by user code, so -// compiler passes can rely on them being in scope // The text_of functions do not need to be exposed; the user can just use // the show above. @@ -241,7 +115,8 @@ func @text_of_Nat(x : Nat) : Text { }; func @text_of_Int(x : Int) : Text { - if (x == 0) "0" else (if (x < 0) "-" else "+") # @text_of_Nat(abs x) + if (x == 0) "0" else (if (x < 0) "-" else "+") # + @text_of_Nat((prim "abs" : Int -> Nat) x) }; let @hexdigits = @@ -251,18 +126,33 @@ func @text_of_Word(x : Nat) : Text { return "0x" # @text_of_num(x, 16, 4, @hexdigits); }; -func @text_of_Nat8(x : Nat8) : Text = @text_of_Nat (nat8ToNat x); -func @text_of_Nat16(x : Nat16) : Text = @text_of_Nat (nat16ToNat x); -func @text_of_Nat32(x : Nat32) : Text = @text_of_Nat (nat32ToNat x); -func @text_of_Nat64(x : Nat64) : Text = @text_of_Nat (nat64ToNat x); -func @text_of_Int8(x : Int8) : Text = @text_of_Int (int8ToInt x); -func @text_of_Int16(x : Int16) : Text = @text_of_Int (int16ToInt x); -func @text_of_Int32(x : Int32) : Text = @text_of_Int (int32ToInt x); -func @text_of_Int64(x : Int64) : Text = @text_of_Int (int64ToInt x); -func @text_of_Word8(x : Word8) : Text = @text_of_Word (word8ToNat x); -func @text_of_Word16(x : Word16) : Text = @text_of_Word (word16ToNat x); -func @text_of_Word32(x : Word32) : Text = @text_of_Word (word32ToNat x); -func @text_of_Word64(x : Word64) : Text = @text_of_Word (word64ToNat x); +// Thre is some duplication with the prim_module, but we need these here +// before we can load the prim module +func @int64ToInt(n : Int64) : Int = (prim "num_conv_Int64_Int" : Int64 -> Int) n; +func @int32ToInt(n : Int32) : Int = (prim "num_conv_Int32_Int" : Int32 -> Int) n; +func @int16ToInt(n : Int16) : Int = (prim "num_conv_Int16_Int" : Int16 -> Int) n; +func @int8ToInt(n : Int8) : Int = (prim "num_conv_Int8_Int" : Int8 -> Int) n; +func @nat64ToNat(n : Nat64) : Nat = (prim "num_conv_Nat64_Nat" : Nat64 -> Nat) n; +func @nat32ToNat(n : Nat32) : Nat = (prim "num_conv_Nat32_Nat" : Nat32 -> Nat) n; +func @nat16ToNat(n : Nat16) : Nat = (prim "num_conv_Nat16_Nat" : Nat16 -> Nat) n; +func @nat8ToNat(n : Nat8) : Nat = (prim "num_conv_Nat8_Nat" : Nat8 -> Nat) n; +func @word64ToNat(n : Word64) : Nat = (prim "num_conv_Word64_Nat" : Word64 -> Nat) n; +func @word32ToNat(n : Word32) : Nat = (prim "num_conv_Word32_Nat" : Word32 -> Nat) n; +func @word16ToNat(n : Word16) : Nat = (prim "num_conv_Word16_Nat" : Word16 -> Nat) n; +func @word8ToNat(n : Word8) : Nat = (prim "num_conv_Word8_Nat" : Word8 -> Nat) n; + +func @text_of_Nat8(x : Nat8) : Text = @text_of_Nat (@nat8ToNat x); +func @text_of_Nat16(x : Nat16) : Text = @text_of_Nat (@nat16ToNat x); +func @text_of_Nat32(x : Nat32) : Text = @text_of_Nat (@nat32ToNat x); +func @text_of_Nat64(x : Nat64) : Text = @text_of_Nat (@nat64ToNat x); +func @text_of_Int8(x : Int8) : Text = @text_of_Int (@int8ToInt x); +func @text_of_Int16(x : Int16) : Text = @text_of_Int (@int16ToInt x); +func @text_of_Int32(x : Int32) : Text = @text_of_Int (@int32ToInt x); +func @text_of_Int64(x : Int64) : Text = @text_of_Int (@int64ToInt x); +func @text_of_Word8(x : Word8) : Text = @text_of_Word (@word8ToNat x); +func @text_of_Word16(x : Word16) : Text = @text_of_Word (@word16ToNat x); +func @text_of_Word32(x : Word32) : Text = @text_of_Word (@word32ToNat x); +func @text_of_Word64(x : Word64) : Text = @text_of_Word (@word64ToNat x); func @text_of_Bool(b : Bool) : Text { @@ -276,7 +166,7 @@ func @text_of_Text(t : Text) : Text { func @text_of_Char(c : Char) : Text { // TODO: Escape properly - "\'" # charToText c # "\'"; + "\'" # (prim "conv_Char_Text" : Char -> Text) c # "\'"; }; @@ -344,44 +234,17 @@ func @text_of_array_mut(f : T -> Text, xs : [var T]) : Text { }; -// Array utilities +type @Cont = T -> () ; +type @Async = (@Cont,@Cont) -> (); -// TODO: These would be nicer as a objects, but lets do them as functions -// until the compiler has a concept of “static objects” -func Array_init(len : Nat, x : T) : [var T] { - (prim "Array.init" : (Nat, T) -> [var T])(len, x) -}; - -func Array_tabulate(len : Nat, gen : Nat -> T) : [T] { - (prim "Array.tabulate" : (Nat, Nat -> T) -> [T])(len, gen) -}; - -// these will change -type ErrorCode = {#error; #system}; /* TBC */ +type @Result = {#ok : T; #error : Error}; -// creation and inspection of abstract error -func error(message : Text) : Error = { - let e = (#error, message); - ((prim "cast" : (ErrorCode, Text)-> Error) e) -}; -func errorCode(e : Error) : ErrorCode = { - ((prim "cast" : Error -> (ErrorCode, Text)) e).0; -}; -func errorMessage(e : Error) : Text = { - ((prim "cast" : Error -> (ErrorCode, Text)) e).1; -}; - -type Cont = T -> () ; -type Async = (Cont,Cont) -> (); - -type Result = {#ok : T; #error : Error}; - -func @new_async() : (Async, Cont, Cont) { +func @new_async() : (@Async, @Cont, @Cont) { let k_null = func(_ : T) {}; let r_null = func(_ : Error) {}; - var result : ?(Result) = null; - var ks : Cont = k_null; - var rs : Cont = r_null; + var result : ?(@Result) = null; + var ks : @Cont = k_null; + var rs : @Cont = r_null; func fulfill(t : T) { switch result { @@ -409,7 +272,7 @@ func @new_async() : (Async, Cont, Cont) { }; }; - func enqueue(k : Cont, r : Cont) { + func enqueue(k : @Cont, r : @Cont) { switch result { case null { let ks_ = ks; @@ -437,6 +300,138 @@ through Array.tabulate. *) let prim_module = {| +func abs(x : Int) : Nat { (prim "abs" : Int -> Nat) x }; + +// for testing +func idlHash(x : Text) : Word32 { (prim "idlHash" : Text -> Word32) x }; + +// Priting + +func debugPrint(x : Text) { (prim "print" : Text -> ()) x }; +func debugPrintNat(x : Nat) { debugPrint (@text_of_Nat x) }; +func debugPrintInt(x : Int) { debugPrint (@text_of_Int x) }; +func debugPrintChar(x : Char) { debugPrint (charToText x) }; + +// RTS stats + +func rts_version() : Text { (prim "rts_version" : () -> Text) () }; +func rts_heap_size() : Nat { (prim "rts_heap_size" : () -> Nat) () }; +func rts_total_allocation() : Nat { (prim "rts_total_allocation" : () -> Nat) () }; +func rts_callback_table_count() : Nat { (prim "rts_callback_table_count" : () -> Nat) () }; +func rts_callback_table_size() : Nat { (prim "rts_callback_table_size" : () -> Nat) () }; + +// Hashing + +func hashBlob(b : Blob) : Word32 { (prim "crc32Hash" : Blob -> Word32) b }; + +// Conversions + +func int64ToInt(n : Int64) : Int = (prim "num_conv_Int64_Int" : Int64 -> Int) n; +func intToInt64(n : Int) : Int64 = (prim "num_conv_Int_Int64" : Int -> Int64) n; +func int64ToWord64(n : Int64) : Word64 = (prim "num_conv_Int64_Word64" : Int64 -> Word64) n; +func word64ToInt64(n : Word64) : Int64 = (prim "num_conv_Word64_Int64" : Word64 -> Int64) n; +func int32ToInt(n : Int32) : Int = (prim "num_conv_Int32_Int" : Int32 -> Int) n; +func intToInt32(n : Int) : Int32 = (prim "num_conv_Int_Int32" : Int -> Int32) n; +func int32ToWord32(n : Int32) : Word32 = (prim "num_conv_Int32_Word32" : Int32 -> Word32) n; +func word32ToInt32(n : Word32) : Int32 = (prim "num_conv_Word32_Int32" : Word32 -> Int32) n; +func int16ToInt(n : Int16) : Int = (prim "num_conv_Int16_Int" : Int16 -> Int) n; +func intToInt16(n : Int) : Int16 = (prim "num_conv_Int_Int16" : Int -> Int16) n; +func int16ToWord16(n : Int16) : Word16 = (prim "num_conv_Int16_Word16" : Int16 -> Word16) n; +func word16ToInt16(n : Word16) : Int16 = (prim "num_conv_Word16_Int16" : Word16 -> Int16) n; +func int8ToInt(n : Int8) : Int = (prim "num_conv_Int8_Int" : Int8 -> Int) n; +func intToInt8(n : Int) : Int8 = (prim "num_conv_Int_Int8" : Int -> Int8) n; +func int8ToWord8(n : Int8) : Word8 = (prim "num_conv_Int8_Word8" : Int8 -> Word8) n; +func word8ToInt8(n : Word8) : Int8 = (prim "num_conv_Word8_Int8" : Word8 -> Int8) n; + +func nat64ToNat(n : Nat64) : Nat = (prim "num_conv_Nat64_Nat" : Nat64 -> Nat) n; +func natToNat64(n : Nat) : Nat64 = (prim "num_conv_Nat_Nat64" : Nat -> Nat64) n; +func nat64ToWord64(n : Nat64) : Word64 = (prim "num_conv_Nat64_Word64" : Nat64 -> Word64) n; +func word64ToNat64(n : Word64) : Nat64 = (prim "num_conv_Word64_Nat64" : Word64 -> Nat64) n; +func nat32ToNat(n : Nat32) : Nat = (prim "num_conv_Nat32_Nat" : Nat32 -> Nat) n; +func natToNat32(n : Nat) : Nat32 = (prim "num_conv_Nat_Nat32" : Nat -> Nat32) n; +func nat32ToWord32(n : Nat32) : Word32 = (prim "num_conv_Nat32_Word32" : Nat32 -> Word32) n; +func word32ToNat32(n : Word32) : Nat32 = (prim "num_conv_Word32_Nat32" : Word32 -> Nat32) n; +func nat16ToNat(n : Nat16) : Nat = (prim "num_conv_Nat16_Nat" : Nat16 -> Nat) n; +func natToNat16(n : Nat) : Nat16 = (prim "num_conv_Nat_Nat16" : Nat -> Nat16) n; +func nat16ToWord16(n : Nat16) : Word16 = (prim "num_conv_Nat16_Word16" : Nat16 -> Word16) n; +func word16ToNat16(n : Word16) : Nat16 = (prim "num_conv_Word16_Nat16" : Word16 -> Nat16) n; +func nat8ToNat(n : Nat8) : Nat = (prim "num_conv_Nat8_Nat" : Nat8 -> Nat) n; +func natToNat8(n : Nat) : Nat8 = (prim "num_conv_Nat_Nat8" : Nat -> Nat8) n; +func nat8ToWord8(n : Nat8) : Word8 = (prim "num_conv_Nat8_Word8" : Nat8 -> Word8) n; +func word8ToNat8(n : Word8) : Nat8 = (prim "num_conv_Word8_Nat8" : Word8 -> Nat8) n; + + +func natToWord8(n : Nat) : Word8 = (prim "num_conv_Nat_Word8" : Nat -> Word8) n; +func word8ToNat(n : Word8) : Nat = (prim "num_conv_Word8_Nat" : Word8 -> Nat) n; +func intToWord8(n : Int) : Word8 = (prim "num_conv_Int_Word8" : Int -> Word8) n; +func word8ToInt(n : Word8) : Int = (prim "num_conv_Word8_Int" : Word8 -> Int) n; + +func natToWord16(n : Nat) : Word16 = (prim "num_conv_Nat_Word16" : Nat -> Word16) n; +func word16ToNat(n : Word16) : Nat = (prim "num_conv_Word16_Nat" : Word16 -> Nat) n; +func intToWord16(n : Int) : Word16 = (prim "num_conv_Int_Word16" : Int -> Word16) n; +func word16ToInt(n : Word16) : Int = (prim "num_conv_Word16_Int" : Word16 -> Int) n; + +func natToWord32(n : Nat) : Word32 = (prim "num_conv_Nat_Word32" : Nat -> Word32) n; +func word32ToNat(n : Word32) : Nat = (prim "num_conv_Word32_Nat" : Word32 -> Nat) n; +func intToWord32(n : Int) : Word32 = (prim "num_conv_Int_Word32" : Int -> Word32) n; +func word32ToInt(n : Word32) : Int = (prim "num_conv_Word32_Int" : Word32 -> Int) n; + +func natToWord64(n : Nat) : Word64 = (prim "num_conv_Nat_Word64" : Nat -> Word64) n; +func word64ToNat(n : Word64) : Nat = (prim "num_conv_Word64_Nat" : Word64 -> Nat) n; +func intToWord64(n : Int) : Word64 = (prim "num_conv_Int_Word64" : Int -> Word64) n; +func word64ToInt(n : Word64) : Int = (prim "num_conv_Word64_Int" : Word64 -> Int) n; + +func charToWord32(c : Char) : Word32 = (prim "num_conv_Char_Word32" : Char -> Word32) c; +func word32ToChar(w : Word32) : Char = (prim "num_conv_Word32_Char" : Word32 -> Char) w; + +func charToText(c : Char) : Text = (prim "conv_Char_Text" : Char -> Text) c; + +// Exotic bitwise operations +func popcntWord8(w : Word8) : Word8 = (prim "popcnt8" : Word8 -> Word8) w; +func clzWord8(w : Word8) : Word8 = (prim "clz8" : Word8 -> Word8) w; +func ctzWord8(w : Word8) : Word8 = (prim "ctz8" : Word8 -> Word8) w; +func btstWord8(w : Word8, amount : Word8) : Bool = (prim "btst8" : (Word8, Word8) -> Word8) (w, amount) != (0 : Word8); + +func popcntWord16(w : Word16) : Word16 = (prim "popcnt16" : Word16 -> Word16) w; +func clzWord16(w : Word16) : Word16 = (prim "clz16" : Word16 -> Word16) w; +func ctzWord16(w : Word16) : Word16 = (prim "ctz16" : Word16 -> Word16) w; +func btstWord16(w : Word16, amount : Word16) : Bool = (prim "btst16" : (Word16, Word16) -> Word16) (w, amount) != (0 : Word16); + +func popcntWord32(w : Word32) : Word32 = (prim "popcnt32" : Word32 -> Word32) w; +func clzWord32(w : Word32) : Word32 = (prim "clz32" : Word32 -> Word32) w; +func ctzWord32(w : Word32) : Word32 = (prim "ctz32" : Word32 -> Word32) w; +func btstWord32(w : Word32, amount : Word32) : Bool = (prim "btst32" : (Word32, Word32) -> Word32) (w, amount) != (0 : Word32); + +func popcntWord64(w : Word64) : Word64 = (prim "popcnt64" : Word64 -> Word64) w; +func clzWord64(w : Word64) : Word64 = (prim "clz64" : Word64 -> Word64) w; +func ctzWord64(w : Word64) : Word64 = (prim "ctz64" : Word64 -> Word64) w; +func btstWord64(w : Word64, amount : Word64) : Bool = (prim "btst64" : (Word64, Word64) -> Word64) (w, amount) != (0 : Word64); + +// Array utilities + +func Array_init(len : Nat, x : T) : [var T] { + (prim "Array.init" : (Nat, T) -> [var T])(len, x) +}; + +func Array_tabulate(len : Nat, gen : Nat -> T) : [T] { + (prim "Array.tabulate" : (Nat, Nat -> T) -> [T])(len, gen) +}; + +// Error + +type ErrorCode = {#error; #system}; /* TBC */ + +// creation and inspection of abstract error +func error(message : Text) : Error = { + let e = (#error, message); + ((prim "cast" : (ErrorCode, Text) -> Error) e) +}; +func errorCode(e : Error) : ErrorCode = { + ((prim "cast" : Error -> (ErrorCode, Text)) e).0; +}; +func errorMessage(e : Error) : Text = { + ((prim "cast" : Error -> (ErrorCode, Text)) e).1; +}; |} diff --git a/stdlib/Makefile b/stdlib/Makefile index fd7d3289a38..a70fab7e344 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -16,6 +16,7 @@ WASM=\ TESTS=\ Array \ + Blob \ Debug \ ArrayTest \ BufTest \ @@ -77,6 +78,9 @@ $(OUTDIR): $(OUTDIR)/Debug.out: debug.mo | $(OUTDIR) $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ +$(OUTDIR)/Blob.out: blob.mo | $(OUTDIR) + $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ + $(OUTDIR)/Array.out: array.mo | $(OUTDIR) $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ diff --git a/stdlib/array.mo b/stdlib/array.mo index 76880de9457..b3cf155133d 100644 --- a/stdlib/array.mo +++ b/stdlib/array.mo @@ -1,3 +1,4 @@ +import Prim "mo:prim"; module { public func equals(a : [A], b : [A], eq : (A,A) -> Bool) : Bool { if (a.len() != b.len()) { @@ -19,7 +20,7 @@ module { case (0, _) { ys; }; case (_, 0) { xs; }; case (xsLen, ysLen) { - Array_tabulate(xsLen + ysLen, func (i : Nat) : A { + Prim.Array_tabulate(xsLen + ysLen, func (i : Nat) : A { if (i < xsLen) { xs[i]; } else { @@ -47,7 +48,7 @@ module { }; public func enumerate(xs : [A]) : [(A, Nat)] { - Array_tabulate<(A, Nat)>(xs.len(), func (i : Nat) : (A, Nat) { + Prim.Array_tabulate<(A, Nat)>(xs.len(), func (i : Nat) : (A, Nat) { (xs[i], i); }); }; @@ -94,7 +95,7 @@ module { }; public func freeze(xs : [var A]) : [A] { - Array_tabulate(xs.len(), func (i : Nat) : A { + Prim.Array_tabulate(xs.len(), func (i : Nat) : A { xs[i]; }); }; @@ -106,13 +107,13 @@ module { }; public func map(f : A -> B, xs : [A]) : [B] { - Array_tabulate(xs.len(), func (i : Nat) : B { + Prim.Array_tabulate(xs.len(), func (i : Nat) : B { f(xs[i]); }); }; public func mapWithIndex(f : (A, Nat) -> B, xs : [A]) : [B] { - Array_tabulate(xs.len(), func (i : Nat) : B { + Prim.Array_tabulate(xs.len(), func (i : Nat) : B { f(xs[i], i); }); }; @@ -126,7 +127,7 @@ module { if (xsLen == 0) { return [var]; }; - let ys = Array_init(xsLen, xs[0]); + let ys = Prim.Array_init(xsLen, xs[0]); for (i in ys.keys()) { ys[i] := xs[i]; }; @@ -134,17 +135,22 @@ module { }; public func init(len : Nat, x : A) : [var A] { - Array_init(len, x); + Prim.Array_init(len, x); }; public func tabulate(len : Nat, gen : Nat -> A) : [A] { - Array_tabulate(len, gen); + Prim.Array_tabulate(len, gen); }; + // copy from iter.mo, but iter depends on array + class range(x : Nat, y : Nat) { + var i = x; + public func next() : ?Nat { if (i > y) null else {let j = i; i += 1; ?j} }; + }; public func tabulateVar(len : Nat, gen : Nat -> A) : [var A] { if (len == 0) { return [var] }; - let xs = Array_init(len, gen 0); + let xs = Prim.Array_init(len, gen 0); for (i in range(1,len)) { xs[i] := gen i; }; diff --git a/stdlib/blob.mo b/stdlib/blob.mo new file mode 100644 index 00000000000..541206f6392 --- /dev/null +++ b/stdlib/blob.mo @@ -0,0 +1,4 @@ +import Prim "mo:prim"; +module { + public func hash(x : Blob) : Word32 = Prim.hashBlob x; +} diff --git a/stdlib/buf.mo b/stdlib/buf.mo index 910a56a99a3..610bb3af413 100644 --- a/stdlib/buf.mo +++ b/stdlib/buf.mo @@ -1,4 +1,6 @@ import P "prelude.mo"; +import I "iter.mo"; +import A "array.mo"; module { @@ -48,7 +50,7 @@ public class Buf (initCapacity : Nat) { initCapacity else 2 * elems.len(); - let elems2 = Array_init(size, elem); + let elems2 = A.init(size, elem); for (i in elems.keys()) { elems2[i] := elems[i]; }; @@ -82,7 +84,7 @@ public class Buf (initCapacity : Nat) { c }; - public func iter() : Iter = object { + public func iter() : I.Iter = object { var pos = 0; public func next() : ?X { if (pos == count) { null } else { @@ -95,14 +97,14 @@ public class Buf (initCapacity : Nat) { public func toArray() : [X] = // immutable clone of array - Array_tabulate( + A.tabulate( elems.len(), func(x: Nat): X { elems[x] } ); public func toVarArray() : [var X] = { if (count == 0) { [var] } else { - let a = Array_init(count, elems[0]); + let a = A.init(count, elems[0]); for (i in elems.keys()) { a[i] := elems[i] }; diff --git a/stdlib/bufTest.mo b/stdlib/bufTest.mo index d87bc3031bd..119b36a3ce3 100644 --- a/stdlib/bufTest.mo +++ b/stdlib/bufTest.mo @@ -1,20 +1,22 @@ +import Prim "mo:prim"; import B "buf.mo"; +import I "iter.mo"; // test repeated growing let a = B.Buf(3); -for (i in range(0, 123)) { +for (i in I.range(0, 123)) { a.add(i); }; -for (i in range(0, 123)) { +for (i in I.range(0, 123)) { assert (a.get(i) == i); }; // test repeated appending let b = B.Buf(3); -for (i in range(0, 123)) { +for (i in I.range(0, 123)) { b.append(a); }; -debugPrint(debug_show(a.toArray())); -debugPrint(debug_show(b.toArray())); +Prim.debugPrint(debug_show(a.toArray())); +Prim.debugPrint(debug_show(b.toArray())); diff --git a/stdlib/debug.mo b/stdlib/debug.mo index 9adc14b7aff..e2c51f5d93e 100644 --- a/stdlib/debug.mo +++ b/stdlib/debug.mo @@ -1,3 +1,4 @@ +import Prim "mo:prim"; module { - public func print(x : Text) = debugPrint x; + public func print(x : Text) = Prim.debugPrint x; } diff --git a/stdlib/examples/actorspec/src/ActorSpec.mo b/stdlib/examples/actorspec/src/ActorSpec.mo index a64cac3c92f..f24da8ecf67 100644 --- a/stdlib/examples/actorspec/src/ActorSpec.mo +++ b/stdlib/examples/actorspec/src/ActorSpec.mo @@ -1,3 +1,4 @@ +import Prim "mo:prim"; import Array "../../../array.mo"; import Int "../../../int.mo"; import Text "../../../text.mo"; @@ -42,10 +43,10 @@ module { public func run(groups_ : [Group]) : Bool { let (groups, status) = getGroups(groups_); printGroups(groups, ""); - debugPrint("\n"); - debugPrint(printStatus(status)); - debugPrint("\n"); - debugPrint("\n"); + Prim.debugPrint("\n"); + Prim.debugPrint(printStatus(status)); + Prim.debugPrint("\n"); + Prim.debugPrint("\n"); status.failed == 0; }; @@ -86,7 +87,7 @@ module { case (_, _, _) { ":" # printStatus(status); }; }; }; - debugPrint(newline # indent # group.name # statusText # "\n"); + Prim.debugPrint(newline # indent # group.name # statusText # "\n"); printGroups(group.groups, indent # " "); }; }; diff --git a/stdlib/examples/produce-exchange/serverActor.mo b/stdlib/examples/produce-exchange/serverActor.mo index abff3bddd30..3b3f68717af 100644 --- a/stdlib/examples/produce-exchange/serverActor.mo +++ b/stdlib/examples/produce-exchange/serverActor.mo @@ -4,6 +4,7 @@ -------------------- */ +import Prim "mo:prim"; import P = "../../prelude.mo"; import Option = "../../option.mo"; import T = "serverTypes.mo"; @@ -1048,7 +1049,7 @@ been processed public func loadWorkload(params:T.WorkloadParams) : () { - func db(s:Text) = if false {debugPrint "Model::loadWorkload: "; debugPrint s; debugPrint "\n"}; + func db(s:Text) = if false {Prim.debugPrint "Model::loadWorkload: "; Prim.debugPrint s; Prim.debugPrint "\n"}; getModel().loadWorkload(params) }; diff --git a/stdlib/examples/produce-exchange/serverModel.mo b/stdlib/examples/produce-exchange/serverModel.mo index 9ed579e0459..f2be7afbadd 100644 --- a/stdlib/examples/produce-exchange/serverModel.mo +++ b/stdlib/examples/produce-exchange/serverModel.mo @@ -1,3 +1,4 @@ +import Prim = "mo:prim"; import P = "../../prelude.mo"; import T = "serverTypes.mo"; @@ -8,6 +9,8 @@ import List = "../../list.mo"; import Hash_ = "../../hash.mo"; import Option = "../../option.mo"; import Trie = "../../trie.mo"; +import Iter = "../../iter.mo"; +import Array = "../../array.mo"; import DT = "../../docTable.mo"; import Result = "../../result.mo"; @@ -82,7 +85,7 @@ public class Model() { */ public func loadWorkload(params:T.WorkloadParams) : () { - func db(s:Text) = if false {debugPrint "Model::loadWorkload: "; debugPrint s; debugPrint "\n"}; + func db(s:Text) = if false {Prim.debugPrint "Model::loadWorkload: "; Prim.debugPrint s; Prim.debugPrint "\n"}; /**- generate add requests for these params: */ db "generate requests for workload..."; @@ -130,7 +133,7 @@ public class Model() { */ public func evalReq(req:L.Req) : Result { - if false {debugPrint "Model::evalReq: "; debugPrint (debug_show req); debugPrint "\n"; }; + if false {Prim.debugPrint "Model::evalReq: "; Prim.debugPrint (debug_show req); Prim.debugPrint "\n"; }; switch req { case (#reset) { /**- 1. reset each entity table: */ @@ -334,7 +337,7 @@ public class Model() { switch req { case (#add reqs) #add ( - Array_tabulate>( + Array.tabulate>( reqs.len(), func(i:Nat):Result = Result.mapOk( @@ -361,7 +364,7 @@ public class Model() { - Each bulk request in this array consists of an array of similar requests (adds, updates, or removes). */ public func evalBulkArray(reqs:[L.BulkReq]) : [L.BulkResp] { - Array_tabulate( + Array.tabulate( reqs.len(), func(i:Nat):L.BulkResp = evalBulk(reqs[i]) ) @@ -387,23 +390,23 @@ public class Model() { func min(x:Nat, y:Nat) : Nat = if (x < y) { x } else { y }; /**- add routes and inventory, across time and space: */ - for (start_day in range(0, day_count-1)) { + for (start_day in Iter.range(0, day_count-1)) { let max_end_day = min( start_day + max_route_duration, day_count - 1 ); - for (end_day in range(start_day, max_end_day)) { + for (end_day in Iter.range(start_day, max_end_day)) { /**- consider all pairs of start and end region: */ - for (start_reg in range(0, region_count - 1)) { - for (end_reg in range(0, region_count - 1)) { + for (start_reg in Iter.range(0, region_count - 1)) { + for (end_reg in Iter.range(0, region_count - 1)) { /**- for each producer we choose, add inventory that will be ready on "start_day", but not beforehand. It will remain ready until the end of the day count. */ - for (p in range(0, producer_count - 1)) { + for (p in Iter.range(0, producer_count - 1)) { /**- choose this producer iff they are located in the start region: */ if ((p % region_count) == start_reg) { inventoryCount := inventoryCount + 1; @@ -414,7 +417,7 @@ public class Model() { add a route that will start and end on the current values of `start_day`, `end_day`, `start_reg`, `end_reg`, respectively: */ - for (t in range(0, transporter_count - 1)) { + for (t in Iter.range(0, transporter_count - 1)) { /**- choose this transporter iff their id matches the id of the region, modulo the number of regions: */ if ((t % region_count) == start_reg) { routeCount := routeCount + 1; @@ -451,7 +454,7 @@ public class Model() { /**- `reqs` accumulates the add requests that we form below: */ var reqs : List = null; /**- add truck types; for now, just 2. */ - for (i in range(0, 1)) { + for (i in Iter.range(0, 1)) { reqs := ?( #truckType ( { @@ -462,19 +465,19 @@ public class Model() { ), reqs); }; /**- add regions */ - for (i in range(0, region_count - 1)) { + for (i in Iter.range(0, region_count - 1)) { reqs := ?(#region { id=i; short_name=""; description="" }, reqs); }; /**- add produce types, one per region. */ - for (i in range(0, region_count - 1)) { + for (i in Iter.range(0, region_count - 1)) { reqs := ?(#produce { id=i; short_name=""; description=""; grade=1; }, reqs); }; /**- add producers */ - for (i in range(0, producer_count - 1)) { + for (i in Iter.range(0, producer_count - 1)) { reqs := ?(#producer { id=i; public_key=""; short_name=""; description=""; region=(i % region_count); @@ -482,37 +485,37 @@ public class Model() { }, reqs); }; /**- add transporters */ - for (i in range(0, producer_count - 1)) { + for (i in Iter.range(0, producer_count - 1)) { reqs := ?(#transporter { id=i; public_key=""; short_name=""; description=""; routes=[]; reserved=[]; }, reqs); }; /**- add retailers */ - for (i in range(0, retailer_count - 1)) { + for (i in Iter.range(0, retailer_count - 1)) { reqs := ?(#retailer { id=i; public_key=""; short_name=""; description=""; region=(i % region_count); }, reqs); }; /**- add routes and inventory, across time and space: */ - for (start_day in range(0, day_count-1)) { + for (start_day in Iter.range(0, day_count-1)) { let max_end_day = min( start_day + max_route_duration, day_count - 1 ); - for (end_day in range(start_day, max_end_day)) { + for (end_day in Iter.range(start_day, max_end_day)) { /**- consider all pairs of start and end region: */ - for (start_reg in range(0, region_count - 1)) { - for (end_reg in range(0, region_count - 1)) { + for (start_reg in Iter.range(0, region_count - 1)) { + for (end_reg in Iter.range(0, region_count - 1)) { /**- for each producer we choose, add inventory that will be ready on "start_day", but not beforehand. It will remain ready until the end of the day count. */ - for (p in range(0, producer_count)) { + for (p in Iter.range(0, producer_count)) { /**- choose this producer iff they are located in the start region: */ if ((p % region_count) == start_reg) { reqs := ?(#inventory @@ -534,7 +537,7 @@ public class Model() { add a route that will start and end on the current values of `start_day`, `end_day`, `start_reg`, `end_reg`, respectively: */ - for (t in range(0, transporter_count - 1)) { + for (t in Iter.range(0, transporter_count - 1)) { /**- choose this transporter iff their id matches the id of the region, modulo the number of regions: */ if ((t % region_count) == start_reg) { reqs := ?(#route @@ -604,8 +607,8 @@ public class Model() { ================== */ - func debugOut (t:Text) { debug { debugPrint t } }; - func debugInt (i:Int) { debug { debugPrintInt i } }; + func debugOut (t:Text) { debug { Prim.debugPrint t } }; + func debugInt (i:Int) { debug { Prim.debugPrintInt i } }; func debugOff (t:Text) { debug { } }; func debugIntOff (i:Int) { debug { } }; @@ -2287,7 +2290,7 @@ than the MVP goals, however. array:[(T.InventoryId,T.RouteId)]) : [Result<(T.ReservedRouteId, T.ReservedInventoryId), T.IdErr>] { - let a = Array_init)>( + let a = Array.init)>( array.len(), null ); @@ -2297,7 +2300,7 @@ than the MVP goals, however. a[i] := ?x; }; let results = - Array_tabulate>( + Array.tabulate>( array.len(), func(i:Nat):Result<(T.ReservedRouteId, T.ReservedInventoryId), T.IdErr>{ Option.unwrap>(a[i]) diff --git a/stdlib/examples/produce-exchange/test/evalBulk.mo b/stdlib/examples/produce-exchange/test/evalBulk.mo index 580e14b632f..955a71a9512 100644 --- a/stdlib/examples/produce-exchange/test/evalBulk.mo +++ b/stdlib/examples/produce-exchange/test/evalBulk.mo @@ -1,18 +1,19 @@ +import Prim "mo:prim"; import T = "../serverTypes.mo"; import A = "../serverActor.mo"; import Result = "../../../result.mo"; import Option = "../../../option.mo"; func printEntityCount(entname:Text, count:Nat) { - debugPrint ("- " # entname # " count: "); - debugPrintInt count; - debugPrint "\n"; + Prim.debugPrint ("- " # entname # " count: "); + Prim.debugPrintInt count; + Prim.debugPrint "\n"; }; func printLabeledCost(lab:Text, cost:Nat) { - debugPrint ("- " # lab # " cost: "); - debugPrintInt cost; - debugPrint "\n"; + Prim.debugPrint ("- " # lab # " cost: "); + Prim.debugPrintInt cost; + Prim.debugPrint "\n"; }; actor class Test() = this { @@ -21,7 +22,7 @@ actor class Test() = this { { let s = A.Server(); - debugPrint "\nExchange setup: Begin...\n====================================\n"; + Prim.debugPrint "\nExchange setup: Begin...\n====================================\n"; let pka = "beef"; let pkb = "dead"; @@ -123,7 +124,7 @@ actor class Test() = this { ////////////////////////////////////////////////////////////////// - debugPrint "\nRetailer queries\n====================================\n"; + Prim.debugPrint "\nRetailer queries\n====================================\n"; // do some queries await retailerQueryAll(s, pka, ? Result.assertUnwrapAny(uida)); @@ -132,7 +133,7 @@ actor class Test() = this { await retailerQueryAll(s, pkd, ? Result.assertUnwrapAny(uidd)); await retailerQueryAll(s, pke, ? Result.assertUnwrapAny(uide)); - debugPrint "\nQuery counts\n----------------\n"; + Prim.debugPrint "\nQuery counts\n----------------\n"; let counts = await s.getCounts(); printEntityCount("Retailer join", counts.retailer_join_count); @@ -146,84 +147,84 @@ actor class Test() = this { func retailerQueryAll(server:A.Server, pk:Text, r:?T.UserId) : async () { - debugPrint "\nRetailer "; + Prim.debugPrint "\nRetailer "; let retailerId: T.UserId = Option.unwrap(r); - debugPrintInt retailerId; - debugPrint " sends `retailerQueryAll`\n"; - debugPrint "------------------------------------\n"; + Prim.debugPrintInt retailerId; + Prim.debugPrint " sends `retailerQueryAll`\n"; + Prim.debugPrint "------------------------------------\n"; - debugPrint "\n## Query begin:\n"; + Prim.debugPrint "\n## Query begin:\n"; let res = Result.assertUnwrapAny( await server.retailerQueryAll(pk, retailerId, null, null) ); - debugPrint "\n## Query end."; + Prim.debugPrint "\n## Query end."; - debugPrint "\n## Query results ("; - debugPrintInt (res.len()); - debugPrint ")\n"; + Prim.debugPrint "\n## Query results ("; + Prim.debugPrintInt (res.len()); + Prim.debugPrint ")\n"; for (info in res.vals()) { - debugPrint "- "; - debugPrint (debug_show info); - debugPrint "\n"; + Prim.debugPrint "- "; + Prim.debugPrint (debug_show info); + Prim.debugPrint "\n"; } }; func debugDumpAll(server:A.Server) : async () { - debugPrint "\nTruck type info\n----------------\n"; + Prim.debugPrint "\nTruck type info\n----------------\n"; for ( info in ((await server.allTruckTypeInfo()).vals()) ) { - debugPrint "- "; - debugPrint (debug_show info); - debugPrint "\n"; + Prim.debugPrint "- "; + Prim.debugPrint (debug_show info); + Prim.debugPrint "\n"; }; - debugPrint "\nRegion info\n----------------\n"; + Prim.debugPrint "\nRegion info\n----------------\n"; for ( info in ((await server.allRegionInfo()).vals()) ) { - debugPrint "- "; - debugPrint (debug_show info); - debugPrint "\n"; + Prim.debugPrint "- "; + Prim.debugPrint (debug_show info); + Prim.debugPrint "\n"; }; - debugPrint "\nProduce info\n----------------\n"; + Prim.debugPrint "\nProduce info\n----------------\n"; for ( info in ((await server.allProduceInfo()).vals()) ) { - debugPrint "- "; - debugPrint (debug_show info); - debugPrint "\n"; + Prim.debugPrint "- "; + Prim.debugPrint (debug_show info); + Prim.debugPrint "\n"; }; - debugPrint "\nProducer info\n----------------\n"; + Prim.debugPrint "\nProducer info\n----------------\n"; for ( info in ((await server.allProducerInfo()).vals()) ) { - debugPrint "- "; - debugPrint (debug_show info); - debugPrint "\n"; + Prim.debugPrint "- "; + Prim.debugPrint (debug_show info); + Prim.debugPrint "\n"; }; - debugPrint "\nTransporter info\n----------------\n"; + Prim.debugPrint "\nTransporter info\n----------------\n"; for ( info in ((await server.allTransporterInfo()).vals()) ) { - debugPrint "- "; - debugPrint (debug_show info); - debugPrint "\n"; + Prim.debugPrint "- "; + Prim.debugPrint (debug_show info); + Prim.debugPrint "\n"; }; - debugPrint "\nRetailer info\n----------------\n"; + Prim.debugPrint "\nRetailer info\n----------------\n"; for ( info in ((await server.allRetailerInfo()).vals()) ) { - debugPrint "- "; - debugPrint (debug_show info); - debugPrint "\n"; + Prim.debugPrint "- "; + Prim.debugPrint (debug_show info); + Prim.debugPrint "\n"; }; - debugPrint "\nInventory info\n----------------\n"; + Prim.debugPrint "\nInventory info\n----------------\n"; for ( info in ((await server.allInventoryInfo()).vals()) ) { - debugPrint "- "; - debugPrint (debug_show info); - debugPrint "\n"; + Prim.debugPrint "- "; + Prim.debugPrint (debug_show info); + Prim.debugPrint "\n"; }; - debugPrint "\nRoute info\n----------------\n"; + Prim.debugPrint "\nRoute info\n----------------\n"; for ( info in ((await server.allRouteInfo()).vals()) ) { - debugPrint "- "; - debugPrint (debug_show info); - debugPrint "\n"; + Prim.debugPrint "- "; + Prim.debugPrint (debug_show info); + Prim.debugPrint "\n"; }; }; diff --git a/stdlib/examples/produce-exchange/test/producerRemInventory.mo b/stdlib/examples/produce-exchange/test/producerRemInventory.mo index 47626266f72..bc119f4fca3 100644 --- a/stdlib/examples/produce-exchange/test/producerRemInventory.mo +++ b/stdlib/examples/produce-exchange/test/producerRemInventory.mo @@ -1,18 +1,19 @@ +import Prim "mo:prim"; import T = "../serverTypes.mo"; import A = "../serverActor.mo"; import Result = "../../../result.mo"; import Option = "../../../option.mo"; func printEntityCount(entname:Text, count:Nat) { - debugPrint ("- " # entname # " count: "); - debugPrintInt count; - debugPrint "\n"; + Prim.debugPrint ("- " # entname # " count: "); + Prim.debugPrintInt count; + Prim.debugPrint "\n"; }; func printLabeledCost(lab:Text, cost:Nat) { - debugPrint ("- " # lab # " cost: "); - debugPrintInt cost; - debugPrint "\n"; + Prim.debugPrint ("- " # lab # " cost: "); + Prim.debugPrintInt cost; + Prim.debugPrint "\n"; }; actor class Test() = this { @@ -21,7 +22,7 @@ actor class Test() = this { { let s = A.Server(); - debugPrint "\nExchange setup: Begin...\n====================================\n"; + Prim.debugPrint "\nExchange setup: Begin...\n====================================\n"; let pka = "beef"; let pkb = "dead"; @@ -124,22 +125,22 @@ actor class Test() = this { await debugDumpInventory(s, pka, 0); await debugDumpAll(s); - debugPrint "\n First time: Producer remove query\n====================================\n"; + Prim.debugPrint "\n First time: Producer remove query\n====================================\n"; let rem0 = await s.producerRemInventory(pka, 0); - debugPrint "- first producerRemInventory(pka, 0) result:"; - debugPrint (debug_show rem0); - debugPrint "\n"; + Prim.debugPrint "- first producerRemInventory(pka, 0) result:"; + Prim.debugPrint (debug_show rem0); + Prim.debugPrint "\n"; await debugDumpInventory(s, pka, 0); await debugDumpAll(s); - debugPrint "\n Second time: Producer remove query\n====================================\n"; + Prim.debugPrint "\n Second time: Producer remove query\n====================================\n"; let rem0b = await s.producerRemInventory(pka, 0); - debugPrint "- second producerRemInventory(pka, 0) result:"; - debugPrint (debug_show rem0b); - debugPrint "\n"; + Prim.debugPrint "- second producerRemInventory(pka, 0) result:"; + Prim.debugPrint (debug_show rem0b); + Prim.debugPrint "\n"; await debugDumpInventory(s, pka, 0); await debugDumpAll(s); @@ -148,75 +149,75 @@ actor class Test() = this { }; func debugDumpInventory(server:A.Server, pk:T.PublicKey, p:T.ProducerId) : async () { - debugPrint "\nProducer "; - debugPrintInt p; - debugPrint "'s inventory:\n--------------------------------\n"; + Prim.debugPrint "\nProducer "; + Prim.debugPrintInt p; + Prim.debugPrint "'s inventory:\n--------------------------------\n"; let res = await server.producerAllInventoryInfo(pk, p); let items = Result.assertUnwrapAny<[T.InventoryInfo]>(res); for (i in items.keys()) { - debugPrintInt i; - debugPrint ". "; - debugPrint (debug_show (items[i])); - debugPrint "\n"; + Prim.debugPrintInt i; + Prim.debugPrint ". "; + Prim.debugPrint (debug_show (items[i])); + Prim.debugPrint "\n"; } }; func debugDumpAll(server:A.Server) : async () { - debugPrint "\nTruck type info\n----------------\n"; + Prim.debugPrint "\nTruck type info\n----------------\n"; for ( info in ((await server.allTruckTypeInfo()).vals()) ) { - debugPrint "- "; - debugPrint (debug_show info); - debugPrint "\n"; + Prim.debugPrint "- "; + Prim.debugPrint (debug_show info); + Prim.debugPrint "\n"; }; - debugPrint "\nRegion info\n----------------\n"; + Prim.debugPrint "\nRegion info\n----------------\n"; for ( info in ((await server.allRegionInfo()).vals()) ) { - debugPrint "- "; - debugPrint (debug_show info); - debugPrint "\n"; + Prim.debugPrint "- "; + Prim.debugPrint (debug_show info); + Prim.debugPrint "\n"; }; - debugPrint "\nProduce info\n----------------\n"; + Prim.debugPrint "\nProduce info\n----------------\n"; for ( info in ((await server.allProduceInfo()).vals()) ) { - debugPrint "- "; - debugPrint (debug_show info); - debugPrint "\n"; + Prim.debugPrint "- "; + Prim.debugPrint (debug_show info); + Prim.debugPrint "\n"; }; - debugPrint "\nProducer info\n----------------\n"; + Prim.debugPrint "\nProducer info\n----------------\n"; for ( info in ((await server.allProducerInfo()).vals()) ) { - debugPrint "- "; - debugPrint (debug_show info); - debugPrint "\n"; + Prim.debugPrint "- "; + Prim.debugPrint (debug_show info); + Prim.debugPrint "\n"; }; - debugPrint "\nTransporter info\n----------------\n"; + Prim.debugPrint "\nTransporter info\n----------------\n"; for ( info in ((await server.allTransporterInfo()).vals()) ) { - debugPrint "- "; - debugPrint (debug_show info); - debugPrint "\n"; + Prim.debugPrint "- "; + Prim.debugPrint (debug_show info); + Prim.debugPrint "\n"; }; - debugPrint "\nRetailer info\n----------------\n"; + Prim.debugPrint "\nRetailer info\n----------------\n"; for ( info in ((await server.allRetailerInfo()).vals()) ) { - debugPrint "- "; - debugPrint (debug_show info); - debugPrint "\n"; + Prim.debugPrint "- "; + Prim.debugPrint (debug_show info); + Prim.debugPrint "\n"; }; - debugPrint "\nInventory info\n----------------\n"; + Prim.debugPrint "\nInventory info\n----------------\n"; for ( info in ((await server.allInventoryInfo()).vals()) ) { - debugPrint "- "; - debugPrint (debug_show info); - debugPrint "\n"; + Prim.debugPrint "- "; + Prim.debugPrint (debug_show info); + Prim.debugPrint "\n"; }; - debugPrint "\nRoute info\n----------------\n"; + Prim.debugPrint "\nRoute info\n----------------\n"; for ( info in ((await server.allRouteInfo()).vals()) ) { - debugPrint "- "; - debugPrint (debug_show info); - debugPrint "\n"; + Prim.debugPrint "- "; + Prim.debugPrint (debug_show info); + Prim.debugPrint "\n"; }; }; diff --git a/stdlib/examples/produce-exchange/test/profileFastCounts.mo b/stdlib/examples/produce-exchange/test/profileFastCounts.mo index b9cc55987a2..3989d96c7c6 100644 --- a/stdlib/examples/produce-exchange/test/profileFastCounts.mo +++ b/stdlib/examples/produce-exchange/test/profileFastCounts.mo @@ -1,7 +1,8 @@ -// debugPrint a table of numbers (somewhat) quickly. +// print a table of numbers (somewhat) quickly. // we correlate these numbers with times that we // measure elsewhere, where these numbers are not available. +import Prim "mo:prim"; import T = "../serverTypes.mo"; import Model = "../serverModel.mo"; @@ -10,10 +11,10 @@ let m = Model.Model(); let scales = [1,2,3,4,5,6,7,8,9,10, 20,50,100]; -debugPrint "# column: region count\n"; -debugPrint "# column: workload scale\n"; -debugPrint "# column: inventory count\n"; -debugPrint "# column: route count\n"; +Prim.debugPrint "# column: region count\n"; +Prim.debugPrint "# column: workload scale\n"; +Prim.debugPrint "# column: inventory count\n"; +Prim.debugPrint "# column: route count\n"; for (scale in scales.vals()) { let (ic, rc) = m.countAddReqs(3, 1, @@ -22,12 +23,12 @@ for (scale in scales.vals()) { 5 * scale, 5); - debugPrintInt 5; - debugPrint ", "; - debugPrintInt scale; - debugPrint ", "; - debugPrintInt ic; - debugPrint ", "; - debugPrintInt rc; - debugPrint "\n"; + Prim.debugPrintInt 5; + Prim.debugPrint ", "; + Prim.debugPrintInt scale; + Prim.debugPrint ", "; + Prim.debugPrintInt ic; + Prim.debugPrint ", "; + Prim.debugPrintInt rc; + Prim.debugPrint "\n"; }; diff --git a/stdlib/examples/produce-exchange/test/retailerReserveMany.mo b/stdlib/examples/produce-exchange/test/retailerReserveMany.mo index 949e50d94e0..a46931d7c2e 100644 --- a/stdlib/examples/produce-exchange/test/retailerReserveMany.mo +++ b/stdlib/examples/produce-exchange/test/retailerReserveMany.mo @@ -1,18 +1,19 @@ +import Prim "mo:prim"; import T = "../serverTypes.mo"; import A = "../serverActor.mo"; import Result = "../../../result.mo"; import Option = "../../../option.mo"; func printEntityCount(entname:Text, count:Nat) { - debugPrint ("- " # entname # " count: "); - debugPrintInt count; - debugPrint "\n"; + Prim.debugPrint ("- " # entname # " count: "); + Prim.debugPrintInt count; + Prim.debugPrint "\n"; }; func printLabeledCost(lab:Text, cost:Nat) { - debugPrint ("- " # lab # " cost: "); - debugPrintInt cost; - debugPrint "\n"; + Prim.debugPrint ("- " # lab # " cost: "); + Prim.debugPrintInt cost; + Prim.debugPrint "\n"; }; actor class Test() = this { @@ -21,7 +22,7 @@ actor class Test() = this { { let s = A.Server(); - debugPrint "\nExchange setup: Begin...\n====================================\n"; + Prim.debugPrint "\nExchange setup: Begin...\n====================================\n"; let pka = "beef"; let pkb = "dead"; @@ -97,7 +98,7 @@ actor class Test() = this { ////////////////////////////////////////////////////////////////// - debugPrint "\nExchange setup: Done.\n====================================\n"; + Prim.debugPrint "\nExchange setup: Done.\n====================================\n"; let inventoryCount1 = await debugDumpInventory(s, pka, 0); let routeCount1 = await debugDumpRoutes(s, pka, 0); @@ -105,7 +106,7 @@ actor class Test() = this { ////////////////////////////////////////////////////////////////// - debugPrint "\nRetailer queries\n====================================\n"; + Prim.debugPrint "\nRetailer queries\n====================================\n"; // do some queries await retailerQueryAll(s, pka, ? Result.assertUnwrapAny(uida)); @@ -114,17 +115,17 @@ actor class Test() = this { await retailerQueryAll(s, pkd, ? Result.assertUnwrapAny(uidd)); await retailerQueryAll(s, pke, ? Result.assertUnwrapAny(uide)); - debugPrint "\nQuery counts\n----------------\n"; + Prim.debugPrint "\nQuery counts\n----------------\n"; let counts = await s.getCounts(); printEntityCount("Retailer join", counts.retailer_join_count); printEntityCount("Retailer query", counts.retailer_query_count); printLabeledCost("Retailer query", counts.retailer_query_cost); - debugPrint "\nRetailer reservations\n====================================\n"; + Prim.debugPrint "\nRetailer reservations\n====================================\n"; - debugPrint "\nRetailer reservations: begin...\n------------------------\n"; + Prim.debugPrint "\nRetailer reservations: begin...\n------------------------\n"; let rrm = await s.retailerReserveMany(pka, @@ -135,24 +136,24 @@ actor class Test() = this { let urrm = Result.assertUnwrapAny<[Result.Result<(T.ReservedInventoryId, T.ReservedRouteId), T.ServerErr>]>(rrm); - debugPrint "\nRetailer reservations: results:\n---------------------------------\n"; + Prim.debugPrint "\nRetailer reservations: results:\n---------------------------------\n"; for (i in urrm.keys()) { - debugPrintInt i; - debugPrint ". "; - debugPrint (debug_show urrm[i]); - debugPrint "\n"; + Prim.debugPrintInt i; + Prim.debugPrint ". "; + Prim.debugPrint (debug_show urrm[i]); + Prim.debugPrint "\n"; }; - debugPrint "\nRetailer reservations: results[0]: expect success.\n---------------------------------\n"; + Prim.debugPrint "\nRetailer reservations: results[0]: expect success.\n---------------------------------\n"; let (ri0, rr0) = Result.assertUnwrapAny<(T.ReservedInventoryId, T.ReservedRouteId)>(urrm[0]); - debugPrint "- "; - debugPrint (debug_show (ri0, rr0)); - debugPrint "\n"; + Prim.debugPrint "- "; + Prim.debugPrint (debug_show (ri0, rr0)); + Prim.debugPrint "\n"; - debugPrint "\nRetailer reservations: results[1]: expect error: already reserved by us!\n---------------------------------\n"; + Prim.debugPrint "\nRetailer reservations: results[1]: expect error: already reserved by us!\n---------------------------------\n"; Result.assertErrAs (urrm[1], @@ -160,7 +161,7 @@ actor class Test() = this { switch err { case (#idErr entid) { switch entid { - case (?(#inventory 0)) debugPrint "- error is `#idErr(?(#inventory 0))`\n"; + case (?(#inventory 0)) Prim.debugPrint "- error is `#idErr(?(#inventory 0))`\n"; case _ assert false; } }; @@ -168,9 +169,9 @@ actor class Test() = this { } }); - debugPrint "\nRetailer reservations: done.\n---------------------------------\n"; + Prim.debugPrint "\nRetailer reservations: done.\n---------------------------------\n"; - debugPrint "\nExchange interactions: Done.\n====================================\n"; + Prim.debugPrint "\nExchange interactions: Done.\n====================================\n"; let inventoryCount2 = await debugDumpInventory(s, pka, 0); let routeCount2 = await debugDumpRoutes(s, pka, 0); @@ -183,117 +184,117 @@ actor class Test() = this { }; func debugDumpInventory(server:A.Server, pk:T.PublicKey, p:T.ProducerId) : async Nat { - debugPrint "\nProducer "; - debugPrintInt p; - debugPrint "'s inventory:\n--------------------------------\n"; + Prim.debugPrint "\nProducer "; + Prim.debugPrintInt p; + Prim.debugPrint "'s inventory:\n--------------------------------\n"; let res = await server.producerAllInventoryInfo(pk, p); let items = Result.assertUnwrapAny<[T.InventoryInfo]>(res); for (i in items.keys()) { - debugPrintInt i; - debugPrint ". "; - debugPrint (debug_show (items[i])); - debugPrint "\n"; + Prim.debugPrintInt i; + Prim.debugPrint ". "; + Prim.debugPrint (debug_show (items[i])); + Prim.debugPrint "\n"; }; - debugPrint "(list end)\n"; + Prim.debugPrint "(list end)\n"; items.len() }; func debugDumpRoutes(server:A.Server, pk:T.PublicKey, t:T.TransporterId) : async Nat { - debugPrint "\nTransporter "; - debugPrintInt t; - debugPrint "'s routes:\n--------------------------------\n"; + Prim.debugPrint "\nTransporter "; + Prim.debugPrintInt t; + Prim.debugPrint "'s routes:\n--------------------------------\n"; let res = await server.transporterAllRouteInfo(pk, t); let items = Result.assertUnwrapAny<[T.RouteInfo]>(res); for (i in items.keys()) { - debugPrintInt i; - debugPrint ". "; - debugPrint (debug_show (items[i])); - debugPrint "\n"; + Prim.debugPrintInt i; + Prim.debugPrint ". "; + Prim.debugPrint (debug_show (items[i])); + Prim.debugPrint "\n"; }; - debugPrint "(list end)\n"; + Prim.debugPrint "(list end)\n"; items.len() }; func retailerQueryAll(server:A.Server, pk:Text, r:?T.UserId) : async () { - debugPrint "\nRetailer "; + Prim.debugPrint "\nRetailer "; let retailerId: T.UserId = Option.unwrap(r); - debugPrintInt retailerId; - debugPrint " sends `retailerQueryAll`\n"; - debugPrint "------------------------------------\n"; + Prim.debugPrintInt retailerId; + Prim.debugPrint " sends `retailerQueryAll`\n"; + Prim.debugPrint "------------------------------------\n"; - debugPrint "\n## Query begin:\n"; + Prim.debugPrint "\n## Query begin:\n"; let res = Result.assertUnwrapAny( await server.retailerQueryAll(pk, retailerId, null, null) ); - debugPrint "\n## Query end."; + Prim.debugPrint "\n## Query end."; - debugPrint "\n## Query results ("; - debugPrintInt (res.len()); - debugPrint ")\n"; + Prim.debugPrint "\n## Query results ("; + Prim.debugPrintInt (res.len()); + Prim.debugPrint ")\n"; for (info in res.vals()) { - debugPrint "- "; - debugPrint (debug_show info); - debugPrint "\n"; + Prim.debugPrint "- "; + Prim.debugPrint (debug_show info); + Prim.debugPrint "\n"; } }; func debugDumpAll(server:A.Server) : async () { - debugPrint "\nTruck type info\n----------------\n"; + Prim.debugPrint "\nTruck type info\n----------------\n"; for ( info in ((await server.allTruckTypeInfo()).vals()) ) { - debugPrint "- "; - debugPrint (debug_show info); - debugPrint "\n"; + Prim.debugPrint "- "; + Prim.debugPrint (debug_show info); + Prim.debugPrint "\n"; }; - debugPrint "\nRegion info\n----------------\n"; + Prim.debugPrint "\nRegion info\n----------------\n"; for ( info in ((await server.allRegionInfo()).vals()) ) { - debugPrint "- "; - debugPrint (debug_show info); - debugPrint "\n"; + Prim.debugPrint "- "; + Prim.debugPrint (debug_show info); + Prim.debugPrint "\n"; }; - debugPrint "\nProduce info\n----------------\n"; + Prim.debugPrint "\nProduce info\n----------------\n"; for ( info in ((await server.allProduceInfo()).vals()) ) { - debugPrint "- "; - debugPrint (debug_show info); - debugPrint "\n"; + Prim.debugPrint "- "; + Prim.debugPrint (debug_show info); + Prim.debugPrint "\n"; }; - debugPrint "\nProducer info\n----------------\n"; + Prim.debugPrint "\nProducer info\n----------------\n"; for ( info in ((await server.allProducerInfo()).vals()) ) { - debugPrint "- "; - debugPrint (debug_show info); - debugPrint "\n"; + Prim.debugPrint "- "; + Prim.debugPrint (debug_show info); + Prim.debugPrint "\n"; }; - debugPrint "\nTransporter info\n----------------\n"; + Prim.debugPrint "\nTransporter info\n----------------\n"; for ( info in ((await server.allTransporterInfo()).vals()) ) { - debugPrint "- "; - debugPrint (debug_show info); - debugPrint "\n"; + Prim.debugPrint "- "; + Prim.debugPrint (debug_show info); + Prim.debugPrint "\n"; }; - debugPrint "\nRetailer info\n----------------\n"; + Prim.debugPrint "\nRetailer info\n----------------\n"; for ( info in ((await server.allRetailerInfo()).vals()) ) { - debugPrint "- "; - debugPrint (debug_show info); - debugPrint "\n"; + Prim.debugPrint "- "; + Prim.debugPrint (debug_show info); + Prim.debugPrint "\n"; }; - debugPrint "\nInventory info\n----------------\n"; + Prim.debugPrint "\nInventory info\n----------------\n"; for ( info in ((await server.allInventoryInfo()).vals()) ) { - debugPrint "- "; - debugPrint (debug_show info); - debugPrint "\n"; + Prim.debugPrint "- "; + Prim.debugPrint (debug_show info); + Prim.debugPrint "\n"; }; - debugPrint "\nRoute info\n----------------\n"; + Prim.debugPrint "\nRoute info\n----------------\n"; for ( info in ((await server.allRouteInfo()).vals()) ) { - debugPrint "- "; - debugPrint (debug_show info); - debugPrint "\n"; + Prim.debugPrint "- "; + Prim.debugPrint (debug_show info); + Prim.debugPrint "\n"; }; }; diff --git a/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.mo b/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.mo index 089237e312a..54f00cb28f3 100644 --- a/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.mo +++ b/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.mo @@ -1,18 +1,19 @@ +import Prim "mo:prim"; import T = "../serverTypes.mo"; import A = "../serverActor.mo"; import Result = "../../../result.mo"; import Option = "../../../option.mo"; func printEntityCount(entname:Text, count:Nat) { - debugPrint ("- " # entname # " count: "); - debugPrintInt count; - debugPrint "\n"; + Prim.debugPrint ("- " # entname # " count: "); + Prim.debugPrintInt count; + Prim.debugPrint "\n"; }; func printLabeledCost(lab:Text, cost:Nat) { - debugPrint ("- " # lab # " cost: "); - debugPrintInt cost; - debugPrint "\n"; + Prim.debugPrint ("- " # lab # " cost: "); + Prim.debugPrintInt cost; + Prim.debugPrint "\n"; }; actor class Test() = this { @@ -21,7 +22,7 @@ actor class Test() = this { { let s = A.Server(); - debugPrint "\nExchange setup: Begin...\n====================================\n"; + Prim.debugPrint "\nExchange setup: Begin...\n====================================\n"; let pka = "beef"; let pkb = "dead"; @@ -289,13 +290,13 @@ actor class Test() = this { ////////////////////////////////////////////////////////////////// - debugPrint "\nExchange setup: Done.\n====================================\n"; + Prim.debugPrint "\nExchange setup: Done.\n====================================\n"; await debugDumpAll(s); ////////////////////////////////////////////////////////////////// - debugPrint "\nRetailer queries\n====================================\n"; + Prim.debugPrint "\nRetailer queries\n====================================\n"; // do some queries await retailerQueryAll(s, pka, ? Result.assertUnwrapAny(uida)); @@ -304,32 +305,32 @@ actor class Test() = this { await retailerQueryAll(s, pkd, ? Result.assertUnwrapAny(uidd)); await retailerQueryAll(s, pke, ? Result.assertUnwrapAny(uide)); - debugPrint "\nQuery counts\n----------------\n"; + Prim.debugPrint "\nQuery counts\n----------------\n"; let counts = await s.getCounts(); printEntityCount("Retailer join", counts.retailer_join_count); printEntityCount("Retailer query", counts.retailer_query_count); printLabeledCost("Retailer query", counts.retailer_query_cost); - debugPrint "\nAuthentication test:\n====================================\n"; + Prim.debugPrint "\nAuthentication test:\n====================================\n"; - debugPrint "\npk a == uid a"; + Prim.debugPrint "\npk a == uid a"; assert(await s.validateUser(pka, Result.assertUnwrapAny(uida))); - debugPrint "\npk b == uid b"; + Prim.debugPrint "\npk b == uid b"; assert(await s.validateUser(pkb, Result.assertUnwrapAny(uidb))); - debugPrint "\npk a != uid b"; + Prim.debugPrint "\npk a != uid b"; assert(not(await s.validateUser(pka, Result.assertUnwrapAny(uidb)))); - debugPrint "\npk b != uid a"; + Prim.debugPrint "\npk b != uid a"; assert(not(await s.validateUser(pkb, Result.assertUnwrapAny(uida)))); ////////////////////////////////////////////////////////////////// // xxx --- todo: separate test(s) for expected failures // User c should not be able to remove user a's route if false { - debugPrint "\nAuthentication test, expect Result.assertion failure:\n"; + Prim.debugPrint "\nAuthentication test, expect Result.assertion failure:\n"; ignore(await s.transporterRemRoute(pkc, Result.assertUnwrapAny(rta_a_c_tta))) }; - debugPrint "\n"; + Prim.debugPrint "\n"; }) }; }; @@ -337,84 +338,84 @@ actor class Test() = this { func retailerQueryAll(server:A.Server, pk:Text, r:?T.UserId) : async () { - debugPrint "\nRetailer "; + Prim.debugPrint "\nRetailer "; let retailerId: T.UserId = Option.unwrap(r); - debugPrintInt retailerId; - debugPrint " sends `retailerQueryAll`\n"; - debugPrint "------------------------------------\n"; + Prim.debugPrintInt retailerId; + Prim.debugPrint " sends `retailerQueryAll`\n"; + Prim.debugPrint "------------------------------------\n"; - debugPrint "\n## Query begin:\n"; + Prim.debugPrint "\n## Query begin:\n"; let res = Result.assertUnwrapAny( await server.retailerQueryAll(pk, retailerId, null, null) ); - debugPrint "\n## Query end."; + Prim.debugPrint "\n## Query end."; - debugPrint "\n## Query results ("; - debugPrintInt (res.len()); - debugPrint ")\n"; + Prim.debugPrint "\n## Query results ("; + Prim.debugPrintInt (res.len()); + Prim.debugPrint ")\n"; for (info in res.vals()) { - debugPrint "- "; - debugPrint (debug_show info); - debugPrint "\n"; + Prim.debugPrint "- "; + Prim.debugPrint (debug_show info); + Prim.debugPrint "\n"; } }; func debugDumpAll(server:A.Server) : async () { - debugPrint "\nTruck type info\n----------------\n"; + Prim.debugPrint "\nTruck type info\n----------------\n"; for ( info in ((await server.allTruckTypeInfo()).vals()) ) { - debugPrint "- "; - debugPrint (debug_show info); - debugPrint "\n"; + Prim.debugPrint "- "; + Prim.debugPrint (debug_show info); + Prim.debugPrint "\n"; }; - debugPrint "\nRegion info\n----------------\n"; + Prim.debugPrint "\nRegion info\n----------------\n"; for ( info in ((await server.allRegionInfo()).vals()) ) { - debugPrint "- "; - debugPrint (debug_show info); - debugPrint "\n"; + Prim.debugPrint "- "; + Prim.debugPrint (debug_show info); + Prim.debugPrint "\n"; }; - debugPrint "\nProduce info\n----------------\n"; + Prim.debugPrint "\nProduce info\n----------------\n"; for ( info in ((await server.allProduceInfo()).vals()) ) { - debugPrint "- "; - debugPrint (debug_show info); - debugPrint "\n"; + Prim.debugPrint "- "; + Prim.debugPrint (debug_show info); + Prim.debugPrint "\n"; }; - debugPrint "\nProducer info\n----------------\n"; + Prim.debugPrint "\nProducer info\n----------------\n"; for ( info in ((await server.allProducerInfo()).vals()) ) { - debugPrint "- "; - debugPrint (debug_show info); - debugPrint "\n"; + Prim.debugPrint "- "; + Prim.debugPrint (debug_show info); + Prim.debugPrint "\n"; }; - debugPrint "\nTransporter info\n----------------\n"; + Prim.debugPrint "\nTransporter info\n----------------\n"; for ( info in ((await server.allTransporterInfo()).vals()) ) { - debugPrint "- "; - debugPrint (debug_show info); - debugPrint "\n"; + Prim.debugPrint "- "; + Prim.debugPrint (debug_show info); + Prim.debugPrint "\n"; }; - debugPrint "\nRetailer info\n----------------\n"; + Prim.debugPrint "\nRetailer info\n----------------\n"; for ( info in ((await server.allRetailerInfo()).vals()) ) { - debugPrint "- "; - debugPrint (debug_show info); - debugPrint "\n"; + Prim.debugPrint "- "; + Prim.debugPrint (debug_show info); + Prim.debugPrint "\n"; }; - debugPrint "\nInventory info\n----------------\n"; + Prim.debugPrint "\nInventory info\n----------------\n"; for ( info in ((await server.allInventoryInfo()).vals()) ) { - debugPrint "- "; - debugPrint (debug_show info); - debugPrint "\n"; + Prim.debugPrint "- "; + Prim.debugPrint (debug_show info); + Prim.debugPrint "\n"; }; - debugPrint "\nRoute info\n----------------\n"; + Prim.debugPrint "\nRoute info\n----------------\n"; for ( info in ((await server.allRouteInfo()).vals()) ) { - debugPrint "- "; - debugPrint (debug_show info); - debugPrint "\n"; + Prim.debugPrint "- "; + Prim.debugPrint (debug_show info); + Prim.debugPrint "\n"; }; }; diff --git a/stdlib/hash.mo b/stdlib/hash.mo index 0bf6bd19fa7..deb6951fd7c 100644 --- a/stdlib/hash.mo +++ b/stdlib/hash.mo @@ -1,3 +1,6 @@ +import Prim "mo:prim"; +import Iter "iter.mo"; + module { /** @@ -55,7 +58,7 @@ public module BitVec { // The input type should actually be [Word8]. // Note: Be sure to explode each Word8 of a Word32 into its own Word32, and to shift into lower 8 bits. public func hashWord8s(key:[BitVec]) : BitVec = label profile_hash_hashWord8s : BitVec { - var hash = natToWord32(0); + var hash = Prim.natToWord32(0); for (wordOfKey in key.vals()) { label profile_hash_hashWord8s_forLoop : () hash := hash + wordOfKey; hash := hash + hash << 10; @@ -73,7 +76,7 @@ public module BitVec { public func hashOfInt(i:Int) : BitVec = label profile_hash_hashOfInt : BitVec { //hashInt(i) - let j = intToWord32(i); + let j = Prim.intToWord32(i); hashWord8s( [j & (255 << 0), j & (255 << 8), @@ -83,7 +86,7 @@ public module BitVec { }; public func hashOfIntAcc(h1:BitVec, i:Int) : BitVec = label profile_hash_hashOfIntAcc : BitVec { - let j = intToWord32(i); + let j = Prim.intToWord32(i); hashWord8s( [h1, j & (255 << 0), @@ -96,7 +99,7 @@ public module BitVec { public func hashOfText(t:Text) : BitVec = label profile_hash_hashOfText : BitVec { var x = 0 : Word32; for (c in t.chars()) { - x := x ^ charToWord32(c); + x := x ^ Prim.charToWord32(c); }; return x }; @@ -104,7 +107,7 @@ public module BitVec { /** Project a given bit from the bit vector. */ public func getHashBit(h:BitVec, pos:Nat) : Bool = label profile_getHashBit : Bool { assert (pos <= length()); - if ((h & (natToWord32(1) << natToWord32(pos))) != natToWord32(0)) + if ((h & (Prim.natToWord32(1) << Prim.natToWord32(pos))) != Prim.natToWord32(0)) { label profile_getHashBit_true : Bool true } @@ -121,21 +124,21 @@ public module BitVec { }; public func bitsPrintRev(bits:BitVec) { - for (j in range(0, length() - 1)) { + for (j in Iter.range(0, length() - 1)) { if (getHashBit(bits, j)) { - debugPrint "1" + Prim.debugPrint "1" } else { - debugPrint "0" + Prim.debugPrint "0" } } }; public func hashPrintRev(bits:BitVec) { - for (j in range(length() - 1, 0)) { + for (j in Iter.range(length() - 1, 0)) { if (getHashBit(bits, j)) { - debugPrint "1" + Prim.debugPrint "1" } else { - debugPrint "0" + Prim.debugPrint "0" } } }; @@ -200,22 +203,22 @@ public module BitList { public func bitsPrintRev(bits:BitList) { switch bits { - case null { debugPrint "" }; + case null { Prim.debugPrint "" }; case (?(bit,bits_)) { bitsPrintRev(bits_); - if bit { debugPrint "1R." } - else { debugPrint "0L." } + if bit { Prim.debugPrint "1R." } + else { Prim.debugPrint "0L." } } } }; public func hashPrintRev(bits:BitList) { switch bits { - case null { debugPrint "" }; + case null { Prim.debugPrint "" }; case (?(bit,bits_)) { hashPrintRev(bits_); - if bit { debugPrint "1" } - else { debugPrint "0" } + if bit { Prim.debugPrint "1" } + else { Prim.debugPrint "0" } } } }; diff --git a/stdlib/hashMap.mo b/stdlib/hashMap.mo index 81523994a64..87f509bcac2 100644 --- a/stdlib/hashMap.mo +++ b/stdlib/hashMap.mo @@ -1,5 +1,8 @@ +import Prim "mo:prim"; import P "prelude.mo"; +import A "array.mo"; import Hash "hash.mo"; +import Iter "iter.mo"; import AssocList "assocList.mo"; module { @@ -37,7 +40,7 @@ public class HashMap ( public func count() : Nat = _count; public func del(k:K) : ?V { - let h = word32ToNat(keyHash(k)); + let h = Prim.word32ToNat(keyHash(k)); let m = table.len(); let pos = h % m; if (m > 0) { @@ -54,7 +57,7 @@ public class HashMap ( }; public func get(k:K) : ?V { - let h = word32ToNat(keyHash(k)); + let h = Prim.word32ToNat(keyHash(k)); let m = table.len(); let v = if (m > 0) { AssocList.find(table[h % m], k, keyEq) @@ -73,7 +76,7 @@ public class HashMap ( 1 else table.len() * 2; - let table2 = Array_init>(size, null); + let table2 = A.init>(size, null); for (i in table.keys()) { var kvs = table[i]; label moveKeyVals : () @@ -81,7 +84,7 @@ public class HashMap ( switch kvs { case null { break moveKeyVals }; case (?((k, v), kvsTail)) { - let h = word32ToNat(keyHash(k)); + let h = Prim.word32ToNat(keyHash(k)); let pos2 = h % table2.len(); table2[pos2] := ?((k,v), table2[pos2]); kvs := kvsTail; @@ -91,7 +94,7 @@ public class HashMap ( }; table := table2; }; - let h = word32ToNat(keyHash(k)); + let h = Prim.word32ToNat(keyHash(k)); let pos = h % table.len(); let (kvs2, ov) = AssocList.replace(table[pos], k, keyEq, ?v); table[pos] := kvs2; @@ -102,7 +105,7 @@ public class HashMap ( ov }; - public func iter() : Iter<(K,V)> { + public func iter() : Iter.Iter<(K,V)> { if (table.len() == 0) { object { public func next() : ?(K,V) { null } } } @@ -146,7 +149,7 @@ public func clone }; // Clone from any iterator of key-value pairs -public func fromIter(iter:Iter<(K, V)>, +public func fromIter(iter:Iter.Iter<(K, V)>, initCapacity: Nat, keyEq: (K,K) -> Bool, keyHash: K -> Hash.Hash) : HashMap { diff --git a/stdlib/hashMapTest.mo b/stdlib/hashMapTest.mo index 11541e5aaa4..56c0dc571aa 100644 --- a/stdlib/hashMapTest.mo +++ b/stdlib/hashMapTest.mo @@ -1,3 +1,4 @@ +import Prim "mo:prim"; import H "hashMap.mo"; import Hash "hash.mo"; @@ -24,7 +25,7 @@ debug { // ensure clone has each key-value pair present in original for ((k,v) in a.iter()) { - debugPrint(debug_show (k,v)); + Prim.debugPrint(debug_show (k,v)); switch (b.get(k)) { case null { assert false }; case (?w) { assert v == w }; @@ -33,7 +34,7 @@ debug { // ensure original has each key-value pair present in clone for ((k,v) in b.iter()) { - debugPrint(debug_show (k,v)); + Prim.debugPrint(debug_show (k,v)); switch (a.get(k)) { case null { assert false }; case (?w) { assert v == w }; @@ -72,7 +73,7 @@ debug { // ensure clone has each key-value pair present in original for ((k,v) in a.iter()) { - debugPrint(debug_show (k,v)); + Prim.debugPrint(debug_show (k,v)); switch (b.get(k)) { case null { assert false }; case (?w) { assert v == w }; @@ -81,7 +82,7 @@ debug { // ensure original has each key-value pair present in clone for ((k,v) in b.iter()) { - debugPrint(debug_show (k,v)); + Prim.debugPrint(debug_show (k,v)); switch (a.get(k)) { case null { assert false }; case (?w) { assert v == w }; @@ -94,7 +95,7 @@ debug { // c agrees with each entry of b for ((k,v) in b.iter()) { - debugPrint(debug_show (k,v)); + Prim.debugPrint(debug_show (k,v)); switch (c.get(k)) { case null { assert false }; case (?w) { assert v == w }; @@ -103,7 +104,7 @@ debug { // b agrees with each entry of c for ((k,v) in c.iter()) { - debugPrint(debug_show (k,v)); + Prim.debugPrint(debug_show (k,v)); switch (b.get(k)) { case null { assert false }; case (?w) { assert v == w }; diff --git a/stdlib/int.mo b/stdlib/int.mo index c0c34b335c1..456950d91ca 100644 --- a/stdlib/int.mo +++ b/stdlib/int.mo @@ -1,6 +1,9 @@ +import Prim "mo:prim"; import Prelude "prelude.mo"; module { + public func abs(x : Int) : Nat = Prim.abs x; + public func add(x : Int, y : Int) : Int { x + y; }; @@ -37,12 +40,12 @@ module { return if isNegative ("-" # text) else text; }; - public func fromInt8 (x : Int8): Int = int8ToInt x; - public func fromInt16(x : Int16): Int = int16ToInt x; - public func fromInt32(x : Int32): Int = int32ToInt x; - public func fromInt64(x : Int64): Int = int64ToInt x; - public func toInt8 (x : Int) : Int8 = intToInt8 x; - public func toInt16(x : Int) : Int16 = intToInt16 x; - public func toInt32(x : Int) : Int32 = intToInt32 x; - public func toInt64(x : Int) : Int64 = intToInt64 x; + public func fromInt8 (x : Int8): Int = Prim.int8ToInt x; + public func fromInt16(x : Int16): Int = Prim.int16ToInt x; + public func fromInt32(x : Int32): Int = Prim.int32ToInt x; + public func fromInt64(x : Int64): Int = Prim.int64ToInt x; + public func toInt8 (x : Int) : Int8 = Prim.intToInt8 x; + public func toInt16(x : Int) : Int16 = Prim.intToInt16 x; + public func toInt32(x : Int) : Int32 = Prim.intToInt32 x; + public func toInt64(x : Int) : Int64 = Prim.intToInt64 x; } diff --git a/stdlib/iter.mo b/stdlib/iter.mo index c5caa6da6b0..67b2a335f24 100644 --- a/stdlib/iter.mo +++ b/stdlib/iter.mo @@ -2,6 +2,13 @@ import Array "array.mo"; import List "list.mo"; module { + public type Iter = {next : () -> ?T}; + + public class range(x : Nat, y : Nat) { + var i = x; + public func next() : ?Nat { if (i > y) null else {let j = i; i += 1; ?j} }; + }; + public func forIn( f : (A, Nat) -> (), xs : Iter diff --git a/stdlib/list.mo b/stdlib/list.mo index 15580fcefab..90b156e8182 100644 --- a/stdlib/list.mo +++ b/stdlib/list.mo @@ -609,7 +609,7 @@ public type List = ?(T, List); public func toArray(xs : List) : [A] { let length = len(xs); var list = xs; - Array_tabulate(length, func (i) { + Array.tabulate(length, func (i) { let popped = pop(list); list := popped.1; Option.unwrap(popped.0); diff --git a/stdlib/nat.mo b/stdlib/nat.mo index 99ddc12ceb4..9db8be1e94a 100644 --- a/stdlib/nat.mo +++ b/stdlib/nat.mo @@ -1,3 +1,4 @@ +import Prim "mo:prim"; import Int "int.mo"; import Prelude "prelude.mo"; @@ -10,22 +11,22 @@ module { Int.toText(x); }; - public func fromWord8 (x : Word8): Nat = word8ToNat x; - public func fromWord16(x : Word16): Nat = word16ToNat x; - public func fromWord32(x : Word32): Nat = word32ToNat x; - public func fromWord64(x : Word64): Nat = word64ToNat x; - public func toWord8 (x : Nat) : Word8 = natToWord8 x; - public func toWord16(x : Nat) : Word16 = natToWord16 x; - public func toWord32(x : Nat) : Word32 = natToWord32 x; - public func toWord64(x : Nat) : Word64 = natToWord64 x; + public func fromWord8 (x : Word8): Nat = Prim.word8ToNat x; + public func fromWord16(x : Word16): Nat = Prim.word16ToNat x; + public func fromWord32(x : Word32): Nat = Prim.word32ToNat x; + public func fromWord64(x : Word64): Nat = Prim.word64ToNat x; + public func toWord8 (x : Nat) : Word8 = Prim.natToWord8 x; + public func toWord16(x : Nat) : Word16 = Prim.natToWord16 x; + public func toWord32(x : Nat) : Word32 = Prim.natToWord32 x; + public func toWord64(x : Nat) : Word64 = Prim.natToWord64 x; - public func fromNat8 (x : Nat8): Nat = nat8ToNat x; - public func fromNat16(x : Nat16): Nat = nat16ToNat x; - public func fromNat32(x : Nat32): Nat = nat32ToNat x; - public func fromNat64(x : Nat64): Nat = nat64ToNat x; - public func toNat8 (x : Nat) : Nat8 = natToNat8 x; - public func toNat16(x : Nat) : Nat16 = natToNat16 x; - public func toNat32(x : Nat) : Nat32 = natToNat32 x; - public func toNat64(x : Nat) : Nat64 = natToNat64 x; + public func fromNat8 (x : Nat8): Nat = Prim.nat8ToNat x; + public func fromNat16(x : Nat16): Nat = Prim.nat16ToNat x; + public func fromNat32(x : Nat32): Nat = Prim.nat32ToNat x; + public func fromNat64(x : Nat64): Nat = Prim.nat64ToNat x; + public func toNat8 (x : Nat) : Nat8 = Prim.natToNat8 x; + public func toNat16(x : Nat) : Nat16 = Prim.natToNat16 x; + public func toNat32(x : Nat) : Nat32 = Prim.natToNat32 x; + public func toNat64(x : Nat) : Nat64 = Prim.natToNat64 x; } diff --git a/stdlib/prelude.mo b/stdlib/prelude.mo index 0405bef8f6f..8dc42ff5c0b 100644 --- a/stdlib/prelude.mo +++ b/stdlib/prelude.mo @@ -1,3 +1,5 @@ +import Prim "mo:prim"; + module { /** @@ -19,7 +21,7 @@ some further experience and discussion. Until then, they live here. */ public func printLn(x : Text) { - debugPrint(x # "\n"); + Prim.debugPrint(x # "\n"); }; /*** diff --git a/stdlib/result.mo b/stdlib/result.mo index 1d8b669ef25..56e76f71b52 100644 --- a/stdlib/result.mo +++ b/stdlib/result.mo @@ -1,4 +1,5 @@ import P "prelude.mo"; +import Array "array.mo"; module { /** @@ -163,6 +164,6 @@ public func joinArrayIfOk(x:[Result]) : Result<[R],E> { } }; /**- all of the results are Ok; tabulate them. */ - #ok(Array_tabulate(x.len(), func (i:Nat):R { assertUnwrap(x[i]) })) + #ok(Array.tabulate(x.len(), func (i:Nat):R { assertUnwrap(x[i]) })) }; } diff --git a/stdlib/text.mo b/stdlib/text.mo index bc46bb3d4cd..b1e9d82d4ac 100644 --- a/stdlib/text.mo +++ b/stdlib/text.mo @@ -1,10 +1,12 @@ +import Iter "iter.mo"; + module { public func append(x : Text, y : Text) : Text { x # y; }; - public func toIter(text : Text) : Iter { + public func toIter(text : Text) : Iter.Iter { { next = text.chars().next } } diff --git a/stdlib/trie.mo b/stdlib/trie.mo index 44181962b7b..d0267f7b379 100644 --- a/stdlib/trie.mo +++ b/stdlib/trie.mo @@ -1,6 +1,8 @@ +import Prim "mo:prim"; import P "prelude.mo"; import Option "option.mo"; import H "hash.mo"; +import A "array.mo"; import List "list.mo"; import AssocList "assocList.mo"; @@ -142,31 +144,31 @@ public func isValid (t:Trie, enforceNormal:Bool) : Bool { ( List.all<(Key,V)>( l.keyvals, func ((k:Key,v:V)):Bool{ - //{ debugPrint "testing hash..."; true } + //{ Prim.debugPrint "testing hash..."; true } //and ((k.hash & mask) == bits) or - { debugPrint "\nmalformed hash!:\n"; - debugPrintInt (word32ToNat(k.hash)); - debugPrint "\n (key hash) != (path bits): \n"; - debugPrintInt (word32ToNat(bits)); - debugPrint "\nmask : "; debugPrintInt (word32ToNat(mask)); - debugPrint "\n"; + { Prim.debugPrint "\nmalformed hash!:\n"; + Prim.debugPrintInt (Prim.word32ToNat(k.hash)); + Prim.debugPrint "\n (key hash) != (path bits): \n"; + Prim.debugPrintInt (Prim.word32ToNat(bits)); + Prim.debugPrint "\nmask : "; Prim.debugPrintInt (Prim.word32ToNat(mask)); + Prim.debugPrint "\n"; false } } ) or - { debugPrint "one or more hashes are malformed"; false } + { Prim.debugPrint "one or more hashes are malformed"; false } ) }; case (#branch b) { let bitpos1 = switch bitpos { - case null (natToWord32(0)); - case (?bp) (natToWord32(word32ToNat(bp) + 1)) + case null (Prim.natToWord32(0)); + case (?bp) (Prim.natToWord32(Prim.word32ToNat(bp) + 1)) }; - let mask1 = mask | (natToWord32(1) << bitpos1); - let bits1 = bits | (natToWord32(1) << bitpos1); + let mask1 = mask | (Prim.natToWord32(1) << bitpos1); + let bits1 = bits | (Prim.natToWord32(1) << bitpos1); let sum = count(b.left) + count(b.right); - (b.count == sum or { debugPrint "malformed count"; false }) + (b.count == sum or { Prim.debugPrint "malformed count"; false }) and rec(b.left, ?bitpos1, bits, mask1) and @@ -976,7 +978,7 @@ public func disj( */ public func buildToArray(tb:TrieBuild,f:(K,V)->W):[W] = label profile_triebuild_toArray_begin : [W] { - let a = Array_tabulate ( + let a = A.tabulate ( buildCount(tb), func (i:Nat) : W = label profile_triebuild_toArray_nth : W { let (k,_,v) = Option.unwrap<(K,?Hash,V)>(buildNth(tb, i)); @@ -996,7 +998,7 @@ public func disj( */ public func buildToArray2(tb:TrieBuild,f:(K,V)->W):[W] { let c = buildCount(tb); - let a = Array_init(c, null); + let a = A.init(c, null); var i = 0; func rec(tb:TrieBuild) = label profile_triebuild_toArray2_rec { switch tb { @@ -1006,7 +1008,7 @@ public func disj( } }; rec(tb); - Array_tabulate(c, func(i:Nat) : W = Option.unwrap(a[i])) + A.tabulate(c, func(i:Nat) : W = Option.unwrap(a[i])) }; }; @@ -1080,7 +1082,7 @@ public func disj( Project the nth key-value pair from the trie. Note: This position is not meaningful; it's only here so that we - can inject tries into arrays given the Array_tabulate interface for + can inject tries into arrays given the A.tabulate interface for doing so. */ public func nth(t:Trie, i:Nat) : ?(Key, V) = label profile_trie_nth : (?(Key, V)) { @@ -1120,7 +1122,7 @@ public func disj( project each element with an independent trie traversal. This approach is somewhat forced on us by the type signature of - Array_tabulate, and the desire to only allocate one array; that requirement rules + A.tabulate, and the desire to only allocate one array; that requirement rules out iterative mutation of an optionally-null array, since an imperative approach which would give us the wrong return type. @@ -1131,7 +1133,7 @@ public func disj( */ public func toArray(t:Trie,f:(K,V)->W):[W] = label profile_trie_toArray_begin : [W] { - let a = Array_tabulate ( + let a = A.tabulate ( count(t), func (i:Nat) : W = label profile_trie_toArray_nth : W { let (k,v) = Option.unwrap<(Key,V)>(nth(t, i)); diff --git a/stdlib/trieMap.mo b/stdlib/trieMap.mo index 8e523599400..f67c6563ed1 100644 --- a/stdlib/trieMap.mo +++ b/stdlib/trieMap.mo @@ -1,5 +1,6 @@ import T "trie.mo"; import P "prelude.mo"; +import I "iter.mo"; import Hash "hash.mo"; import List "list.mo"; @@ -54,7 +55,7 @@ public class TrieMap (isEq:(K, K) -> Bool, hashOf: K -> T.Hash) { // notably, each iterator gets a _persistent view_ of the mapping, // by virtue of the trie being a persistent data structure. - public func iter() : Iter<(K,V)> = object { + public func iter() : I.Iter<(K,V)> = object { var stack = ?(map, null) : List.List>; public func next() : ?(K,V) { switch stack { @@ -100,7 +101,7 @@ public func clone }; // Clone from any iterator of key-value pairs -public func fromIter(iter:Iter<(K, V)>, +public func fromIter(iter:I.Iter<(K, V)>, keyEq: (K,K) -> Bool, keyHash: K -> Hash.Hash) : TrieMap { let h = TrieMap(keyEq, keyHash); diff --git a/stdlib/trieMapTest.mo b/stdlib/trieMapTest.mo index 1f75f6104e5..fd4a1fbb52d 100644 --- a/stdlib/trieMapTest.mo +++ b/stdlib/trieMapTest.mo @@ -1,3 +1,4 @@ +import Prim "mo:prim"; import H "trieMap.mo"; import Hash "hash.mo"; @@ -24,7 +25,7 @@ debug { // ensure clone has each key-value pair present in original for ((k,v) in a.iter()) { - debugPrint(debug_show (k,v)); + Prim.debugPrint(debug_show (k,v)); switch (b.get(k)) { case null { assert false }; case (?w) { assert v == w }; @@ -33,7 +34,7 @@ debug { // ensure original has each key-value pair present in clone for ((k,v) in b.iter()) { - debugPrint(debug_show (k,v)); + Prim.debugPrint(debug_show (k,v)); switch (a.get(k)) { case null { assert false }; case (?w) { assert v == w }; @@ -72,7 +73,7 @@ debug { // ensure clone has each key-value pair present in original for ((k,v) in a.iter()) { - debugPrint(debug_show (k,v)); + Prim.debugPrint(debug_show (k,v)); switch (b.get(k)) { case null { assert false }; case (?w) { assert v == w }; @@ -81,7 +82,7 @@ debug { // ensure original has each key-value pair present in clone for ((k,v) in b.iter()) { - debugPrint(debug_show (k,v)); + Prim.debugPrint(debug_show (k,v)); switch (a.get(k)) { case null { assert false }; case (?w) { assert v == w }; @@ -94,7 +95,7 @@ debug { // c agrees with each entry of b for ((k,v) in b.iter()) { - debugPrint(debug_show (k,v)); + Prim.debugPrint(debug_show (k,v)); switch (c.get(k)) { case null { assert false }; case (?w) { assert v == w }; @@ -103,7 +104,7 @@ debug { // b agrees with each entry of c for ((k,v) in c.iter()) { - debugPrint(debug_show (k,v)); + Prim.debugPrint(debug_show (k,v)); switch (b.get(k)) { case null { assert false }; case (?w) { assert v == w }; diff --git a/test/fail/actor-reexport.mo b/test/fail/actor-reexport.mo index 51b75c6162d..b1c8fd76f84 100644 --- a/test/fail/actor-reexport.mo +++ b/test/fail/actor-reexport.mo @@ -1,6 +1,8 @@ +import Prim "mo:prim"; + actor test { public func exported() { - debugPrint("exported()"); + Prim.debugPrint("exported()"); }; public let exported_too = exported; }; diff --git a/test/fail/branch-before-define.mo b/test/fail/branch-before-define.mo index 88877861117..26c1be608d8 100644 --- a/test/fail/branch-before-define.mo +++ b/test/fail/branch-before-define.mo @@ -1,3 +1,5 @@ +import Prim "mo:prim"; + func f():() -> Int { { label exit : (() -> Int) { func g() : Int = x; // reference x @@ -8,8 +10,8 @@ func f():() -> Int { }; }; -debugPrint "1"; +Prim.debugPrint "1"; let h = f(); -debugPrint "2"; +Prim.debugPrint "2"; let wrong = h(); diff --git a/test/fail/issue-894-fail.mo b/test/fail/issue-894-fail.mo index 32c14cc99c6..d83509e9007 100644 --- a/test/fail/issue-894-fail.mo +++ b/test/fail/issue-894-fail.mo @@ -1,16 +1,17 @@ +import Prim "mo:prim"; actor a { public shared func test() : async () { { let o = {var l = 0}; (await async o).l := await async 1; // type error (o mutable, not shared) - debugPrintNat(o.l); + Prim.debugPrintNat(o.l); assert o.l == 1; }; { let a = [var 0]; (await async a)[0] := await async 1; // type error (a mutable, not shared) - debugPrintNat(a[0]); + Prim.debugPrintNat(a[0]); assert a[0] == 1; }; } diff --git a/test/fail/objpat-infer.mo b/test/fail/objpat-infer.mo index 53815989d5d..6b5d932725a 100644 --- a/test/fail/objpat-infer.mo +++ b/test/fail/objpat-infer.mo @@ -1,10 +1,12 @@ +import Prim "mo:prim"; + // checks ignore (switch (object {}) { case {a} 42 }); // checks -for ({} in [object {}].vals()) { debugPrint "hey" }; +for ({} in [object {}].vals()) { Prim.debugPrint "hey" }; // infers diff --git a/test/fail/objpat-mutable.mo b/test/fail/objpat-mutable.mo index 4547e41a22b..3d8bd84c2c3 100644 --- a/test/fail/objpat-mutable.mo +++ b/test/fail/objpat-mutable.mo @@ -1,9 +1,11 @@ +import Prim "mo:prim"; + type WithMut = { var x : Int; y : Text }; func reject (o : WithMut) = switch o { - case { y = "good" } { debugPrint "good" }; - //case { x = -42 } { debugPrint "bad" }; // backend: Invalid_argument("unop") - //case { x = (42 : Int) } { debugPrint "bad" }; // tc: cannot consume expected - case { x } { debugPrintInt x } + case { y = "good" } { Prim.debugPrint "good" }; + //case { x = -42 } { Prim.debugPrint "bad" }; // backend: Invalid_argument("unop") + //case { x = (42 : Int) } { Prim.debugPrint "bad" }; // tc: cannot consume expected + case { x } { Prim.debugPrintInt x } }; diff --git a/test/fail/ok/actor-reexport.tc.ok b/test/fail/ok/actor-reexport.tc.ok index b62fb6463f0..d82f501a084 100644 --- a/test/fail/ok/actor-reexport.tc.ok +++ b/test/fail/ok/actor-reexport.tc.ok @@ -1,3 +1,3 @@ -actor-reexport.mo:5.10-5.37: type error, public actor field needs to be a manifest function -actor-reexport.mo:9.10-9.48: type error, public actor field needs to be a manifest function -actor-reexport.mo:10.10-14.39: type error, public actor field needs to be a manifest function +actor-reexport.mo:7.10-7.37: type error, public actor field needs to be a manifest function +actor-reexport.mo:11.10-11.48: type error, public actor field needs to be a manifest function +actor-reexport.mo:12.10-16.39: type error, public actor field needs to be a manifest function diff --git a/test/fail/ok/branch-before-define.tc.ok b/test/fail/ok/branch-before-define.tc.ok index 2d6a970dae5..de290e895f3 100644 --- a/test/fail/ok/branch-before-define.tc.ok +++ b/test/fail/ok/branch-before-define.tc.ok @@ -1 +1 @@ -branch-before-define.mo:4.7-4.40: definedness error, cannot use g before x has been defined +branch-before-define.mo:6.7-6.40: definedness error, cannot use g before x has been defined diff --git a/test/fail/ok/issue-894-fail.tc.ok b/test/fail/ok/issue-894-fail.tc.ok index c9ebafcca33..85e1c297bb9 100644 --- a/test/fail/ok/issue-894-fail.tc.ok +++ b/test/fail/ok/issue-894-fail.tc.ok @@ -1,10 +1,10 @@ -issue-894-fail.mo:5.20-5.21: type error, async type has non-shared content type +issue-894-fail.mo:6.20-6.21: type error, async type has non-shared content type {var l : Nat} type {var l : Nat} is or contains non-shared type var Nat -issue-894-fail.mo:12.20-12.21: type error, async type has non-shared content type +issue-894-fail.mo:13.20-13.21: type error, async type has non-shared content type [var Nat] type [var Nat] diff --git a/test/fail/ok/modexp5.tc.ok b/test/fail/ok/modexp5.tc.ok index ec638653931..441de01b8df 100644 --- a/test/fail/ok/modexp5.tc.ok +++ b/test/fail/ok/modexp5.tc.ok @@ -1 +1 @@ -modexp5.mo:6.20-6.30: type error, type definition U = T/17 references type parameter(s) T/17 from an outer scope +modexp5.mo:6.20-6.30: type error, type definition U = T/13 references type parameter(s) T/13 from an outer scope diff --git a/test/fail/ok/objpat-infer.tc.ok b/test/fail/ok/objpat-infer.tc.ok index bea0e0d5256..32ca82794d1 100644 --- a/test/fail/ok/objpat-infer.tc.ok +++ b/test/fail/ok/objpat-infer.tc.ok @@ -1,22 +1,22 @@ -objpat-infer.mo:3.36-3.37: type error, object field a is not contained in expected type +objpat-infer.mo:5.36-5.37: type error, object field a is not contained in expected type {} -objpat-infer.mo:21.13-21.21: type error, expression of type +objpat-infer.mo:23.13-23.21: type error, expression of type actor {} cannot produce expected type {} -objpat-infer.mo:24.13-24.14: type error, expression of type +objpat-infer.mo:26.13-26.14: type error, expression of type actor {bar : shared {} -> async Nat} cannot produce expected type {} -objpat-infer.mo:27.13-27.15: type error, expression of type +objpat-infer.mo:29.13-29.15: type error, expression of type {} cannot produce expected type actor {} -objpat-infer.mo:28.13-28.22: type error, expression of type +objpat-infer.mo:30.13-30.22: type error, expression of type {} cannot produce expected type actor {} -objpat-infer.mo:33.15-33.23: type error, expression of type +objpat-infer.mo:35.15-35.23: type error, expression of type actor {} cannot produce expected type {} diff --git a/test/fail/ok/objpat-mutable.tc.ok b/test/fail/ok/objpat-mutable.tc.ok index 93b9f497d6d..628c837dbcb 100644 --- a/test/fail/ok/objpat-mutable.tc.ok +++ b/test/fail/ok/objpat-mutable.tc.ok @@ -1 +1 @@ -objpat-mutable.mo:8.12-8.13: type error, cannot pattern match mutable field x +objpat-mutable.mo:10.12-10.13: type error, cannot pattern match mutable field x diff --git a/test/fail/ok/return-before-define.tc.ok b/test/fail/ok/return-before-define.tc.ok index fd459cd7fd6..cb51ab13378 100644 --- a/test/fail/ok/return-before-define.tc.ok +++ b/test/fail/ok/return-before-define.tc.ok @@ -1 +1 @@ -return-before-define.mo:3.5-3.34: definedness error, cannot use g before x has been defined +return-before-define.mo:5.5-5.34: definedness error, cannot use g before x has been defined diff --git a/test/fail/ok/use-before-define.tc.ok b/test/fail/ok/use-before-define.tc.ok index d8cb5f5f0ca..629ef1c9363 100644 --- a/test/fail/ok/use-before-define.tc.ok +++ b/test/fail/ok/use-before-define.tc.ok @@ -1 +1 @@ -use-before-define.mo:2.1-2.12: definedness error, cannot use f before x has been defined +use-before-define.mo:4.1-4.12: definedness error, cannot use f before x has been defined diff --git a/test/fail/return-before-define.mo b/test/fail/return-before-define.mo index d6aaf72b8e8..dc13bd47127 100644 --- a/test/fail/return-before-define.mo +++ b/test/fail/return-before-define.mo @@ -1,3 +1,5 @@ +import Prim "mo:prim"; + func f():() -> Int { { func g() : Int = x; // reference x return (func() : Int{ g(); }); // early exit omits definition of x @@ -6,8 +8,8 @@ func f():() -> Int { }; }; -debugPrint "1"; +Prim.debugPrint "1"; let h = f(); -debugPrint "2"; +Prim.debugPrint "2"; let wrong = h(); diff --git a/test/fail/use-before-define.mo b/test/fail/use-before-define.mo index 442a59688e3..90a834add40 100644 --- a/test/fail/use-before-define.mo +++ b/test/fail/use-before-define.mo @@ -1,4 +1,6 @@ +import Prim "mo:prim"; + func f():Int = x; let y = f(); let x = 1; -debugPrintInt(x); +Prim.debugPrintInt(x); diff --git a/test/lsp-int/test-project/.gitignore b/test/lsp-int-test-project/.gitignore similarity index 100% rename from test/lsp-int/test-project/.gitignore rename to test/lsp-int-test-project/.gitignore diff --git a/test/lsp-int/test-project/ListClient.mo b/test/lsp-int-test-project/ListClient.mo similarity index 100% rename from test/lsp-int/test-project/ListClient.mo rename to test/lsp-int-test-project/ListClient.mo diff --git a/test/lsp-int/test-project/app.mo b/test/lsp-int-test-project/app.mo similarity index 100% rename from test/lsp-int/test-project/app.mo rename to test/lsp-int-test-project/app.mo diff --git a/test/lsp-int/test-project/lib/ListFuncs.mo b/test/lsp-int-test-project/lib/ListFuncs.mo similarity index 100% rename from test/lsp-int/test-project/lib/ListFuncs.mo rename to test/lsp-int-test-project/lib/ListFuncs.mo diff --git a/test/lsp-int/test-project/lib/ListLib.mo b/test/lsp-int-test-project/lib/ListLib.mo similarity index 100% rename from test/lsp-int/test-project/lib/ListLib.mo rename to test/lsp-int-test-project/lib/ListLib.mo diff --git a/test/lsp-int/test-project/lib/list.mo b/test/lsp-int-test-project/lib/list.mo similarity index 100% rename from test/lsp-int/test-project/lib/list.mo rename to test/lsp-int-test-project/lib/list.mo diff --git a/test/lsp-int/test-project/lib/option.mo b/test/lsp-int-test-project/lib/option.mo similarity index 95% rename from test/lsp-int/test-project/lib/option.mo rename to test/lsp-int-test-project/lib/option.mo index 7fd53890a47..a4ad45219e6 100644 --- a/test/lsp-int/test-project/lib/option.mo +++ b/test/lsp-int-test-project/lib/option.mo @@ -1,3 +1,4 @@ +import Prim "mo:prim"; import P "prelude.mo"; module { @@ -135,8 +136,8 @@ public func assertNull(x: ?A) = assertNullAny(x); */ public func printOpInt(x : ?Int) = switch x { - case null { debugPrint "null" }; - case (?x_) { debugPrint "?"; debugPrintInt x_ }; + case null { Prim.debugPrint "null" }; + case (?x_) { Prim.debugPrint "?"; Prim.debugPrintInt x_ }; }; public func apply(f : ?(A -> B), x : ?A) : ?B { diff --git a/test/lsp-int/test-project/lib/prelude.mo b/test/lsp-int-test-project/lib/prelude.mo similarity index 94% rename from test/lsp-int/test-project/lib/prelude.mo rename to test/lsp-int-test-project/lib/prelude.mo index 0405bef8f6f..ecce079ab4e 100644 --- a/test/lsp-int/test-project/lib/prelude.mo +++ b/test/lsp-int-test-project/lib/prelude.mo @@ -1,3 +1,4 @@ +import Prim "mo:prim"; module { /** @@ -19,7 +20,7 @@ some further experience and discussion. Until then, they live here. */ public func printLn(x : Text) { - debugPrint(x # "\n"); + Prim.debugPrint(x # "\n"); }; /*** diff --git a/test/lsp-int/test-project/mydependency/broken.mo b/test/lsp-int-test-project/mydependency/broken.mo similarity index 100% rename from test/lsp-int/test-project/mydependency/broken.mo rename to test/lsp-int-test-project/mydependency/broken.mo diff --git a/test/lsp-int/test-project/mydependency/lib.mo b/test/lsp-int-test-project/mydependency/lib.mo similarity index 100% rename from test/lsp-int/test-project/mydependency/lib.mo rename to test/lsp-int-test-project/mydependency/lib.mo diff --git a/test/mo-idl/ok/pa_cars.did.ok b/test/mo-idl/ok/pa_cars.did.ok index 7d82ad5c81c..439828c3c6c 100644 --- a/test/mo-idl/ok/pa_cars.did.ok +++ b/test/mo-idl/ok/pa_cars.did.ok @@ -4,11 +4,11 @@ type TimeSpan = "end": int; "start": int; }; -type Result_1 = opt record {"reservationId": text;}; +type Result = opt record {"reservationId": text;}; type PACars = service { "verifyCarInformation": (User, Car) -> - (opt func (Location, TimeSpan) -> (Result_1)); + (opt func (Location, TimeSpan) -> (Result)); }; type Location = record { diff --git a/test/mo-idl/ok/result.did.ok b/test/mo-idl/ok/result.did.ok index a3dd61c201b..505e85c3ce7 100644 --- a/test/mo-idl/ok/result.did.ok +++ b/test/mo-idl/ok/result.did.ok @@ -1,9 +1,9 @@ -type Result_1_2 = +type Result_2 = variant { "err": text; "ok": nat; }; -type Result_1_1 = +type Result_1 = variant { "err": text; "ok": null; @@ -15,15 +15,15 @@ type Result3_1 = }; type Result2_2 = variant { - "err": Result_1_2; + "err": Result_2; "ok": nat; }; type Result2_1 = variant { - "err": Result_1_1; + "err": Result_1; "ok": null; }; service : { - "f": (opt nat) -> (Result_1_2); + "f": (opt nat) -> (Result_2); "g": (Result3_1) -> (Result2_2); } diff --git a/test/perf/reversi.mo b/test/perf/reversi.mo index 95704d2ef1d..a793c4b3cde 100644 --- a/test/perf/reversi.mo +++ b/test/perf/reversi.mo @@ -1,9 +1,16 @@ +import Prim "mo:prim"; actor { // based on https://github.com/dfinity-lab/dapps/blob/75ead35363574f3697e37cd3a0592e51d3253a36/examples/reversi/src/reversi/main.mo // with stdlib inlined and board size changed to 8 // inline parts of stdlib + + class range(x : Nat, y : Nat) { + var i = x; + public func next() : ?Nat { if (i > y) null else {let j = i; i += 1; ?j} }; + }; + func unreachable() : None = { assert false ; loop { } }; func toText(x : Int) : Text { @@ -51,7 +58,7 @@ actor { // Board is NxN array type Board = [var Color]; - let Board : Board = Array_init(N * N, empty); + let Board : Board = Prim.Array_init(N * N, empty); // Which color should move next var next_color : Color = white; @@ -121,7 +128,7 @@ actor { if (s < 0 or s >= N or t < 0 or t >= N) { return false; }; - return (board[abs (s * N + t)] == color); + return (board[Prim.abs (s * N + t)] == color); }; // Check if a piece of the given color eventually exits on the board @@ -131,7 +138,7 @@ actor { func eventually(board: Board, color: Color, i: Nat, j: Nat, p:Int, q:Int) : Bool { if (exists(board, opponent(color), i, j, p, q)) { // the abs below is save because its precondition is already checked - return eventually(board, color, abs(i + p), abs(j + q), p, q); + return eventually(board, color, Prim.abs(i + p), Prim.abs(j + q), p, q); } else { return exists(board, color, i, j, p, q); } @@ -142,8 +149,8 @@ actor { func flip(board: Board, color: Color, i: Nat, j: Nat, p:Int, q:Int) { if (exists(board, opponent(color), i, j, p, q)) { // the abs below is save because its precondition is already checked - let s = abs(i + p); - let t = abs(j + q); + let s = Prim.abs(i + p); + let t = Prim.abs(j + q); board[s * N + t] := color; flip(board, color, s, t, p, q); } @@ -152,7 +159,7 @@ actor { // Calculate all validate positions for a given color by returning // a board that has the cells colored. func valid_moves(board: Board, color: Color) : Board { - let next : Board = Array_init(N * N, empty); + let next : Board = Prim.Array_init(N * N, empty); for (i in range(0, N-1)) { for (j in range(0, N-1)) { if (board[i * N + j] == empty) { @@ -219,9 +226,9 @@ actor { // It returns "OK" when the move is valid. public func place(color_: Int, row_: Int, col_: Int) : async Text { // The casting is necessary because dfx has yet to support Nat on commandline - let color : Color = abs(color_); - let row : Nat = abs(row_); - let col : Nat = abs(col_); + let color : Color = Prim.abs(color_); + let row : Nat = Prim.abs(row_); + let col : Nat = Prim.abs(col_); // Check input validity if (row >= N or col >= N) { diff --git a/test/random/Main.hs b/test/random/Main.hs index bac0578b575..eaf1fc6ada6 100644 --- a/test/random/Main.hs +++ b/test/random/Main.hs @@ -76,12 +76,15 @@ addEmbedderArgs WasmTime = ("--disable-cache" :) . ("--cranelift" :) embedder :: Embedder embedder = WasmTime +withPrim :: Line -> Line +withPrim = (fromString "import Prim \"mo:prim\";" <>) + (runScriptNoFuzz, runScriptWantFuzz) = (runner ExitSuccess id, runner (ExitFailure 1) not) where runner reqOutcome relevant name testCase = - let as = name <.> "as" + let as = name <.> "mo" wasm = name <.> "wasm" fileArg = fromString . encodeString - script = do Turtle.output as $ fromString testCase + script = do Turtle.output as $ withPrim <$> fromString testCase res@(exitCode, _, _) <- procStrictWithErr "moc" ["-no-system-api", "-no-check-ir", fileArg as] empty if ExitSuccess == exitCode @@ -93,7 +96,7 @@ prop_explodeConcat :: UTF8 String -> Property prop_explodeConcat (UTF8 str) = monadicIO $ do let testCase :: String testCase = "{ var str = \"\"; for (c in \"" - <> s <> "\".chars()) { str #= charToText c }; assert (str == \"" <> s <> "\") }" + <> s <> "\".chars()) { str #= Prim.charToText c }; assert (str == \"" <> s <> "\") }" s = concatMap escape str runScriptNoFuzz "explodeConcat" testCase @@ -115,7 +118,7 @@ escape '"' = "\\\"" escape ch = pure ch prop_charToText (UTF8 char) = monadicIO $ do - let testCase = "assert (switch ((charToText '" + let testCase = "assert (switch ((Prim.charToText '" <> c <> "').chars().next()) { case (?'" <> c <> "') true; case _ false })" c = escape char @@ -212,7 +215,7 @@ instance Arbitrary TestCase where prop_verifies (TestCase (map fromString -> testCase)) = monadicIO $ do - let script cases = do Turtle.output "tests.mo" $ msum cases + let script cases = do Turtle.output "tests.mo" $ msum (pure (withPrim mempty) : cases) res@(exitCode, _, _) <- procStrictWithErr "moc" ["-no-system-api", "-no-check-ir", "tests.mo"] empty if ExitSuccess == exitCode @@ -971,7 +974,7 @@ unparseMO f@Five = annot f "5" unparseMO a@(Neuralgic n) = annot a $ literal n unparseMO (Pos n) = "(+" <> unparseMO n <> ")" unparseMO (Neg n) = "(-" <> unparseMO n <> ")" -unparseMO (Abs n) = "(abs " <> unparseMO n <> ")" +unparseMO (Abs n) = "(Prim.abs " <> unparseMO n <> ")" unparseMO (a `Add` b) = inParens unparseMO "+" a b unparseMO (a `Sub` b) = annot a $ inParens unparseMO "-" a b unparseMO (a `Mul` b) = inParens unparseMO "*" a b @@ -986,16 +989,16 @@ unparseMO (a `RotR` b) = inParens unparseMO "<>>" a b unparseMO (a `ShiftL` b) = inParens unparseMO "<<" a b unparseMO (a `ShiftR` b) = inParens unparseMO ">>" a b unparseMO (a `ShiftRSigned` b) = inParens unparseMO "+>>" a b -unparseMO (PopCnt n) = sizeSuffix n "(popcntWord" <> " " <> unparseMO n <> ")" -unparseMO (Clz n) = sizeSuffix n "(clzWord" <> " " <> unparseMO n <> ")" -unparseMO (Ctz n) = sizeSuffix n "(ctzWord" <> " " <> unparseMO n <> ")" +unparseMO (PopCnt n) = sizeSuffix n "(Prim.popcntWord" <> " " <> unparseMO n <> ")" +unparseMO (Clz n) = sizeSuffix n "(Prim.clzWord" <> " " <> unparseMO n <> ")" +unparseMO (Ctz n) = sizeSuffix n "(Prim.ctzWord" <> " " <> unparseMO n <> ")" unparseMO (Complement a) = "(^ " <> unparseMO a <> ")" unparseMO (ConvertNatural a) = "(++++(" <> unparseMO a <> "))" unparseMO (ConvertNat a) = unparseNat Proxy a unparseMO (ConvertInt a) = unparseInt Proxy a unparseMO (ConvertWord a) = unparseWord Proxy a -unparseMO (ConvertWordToNat a) = sizeSuffix a "(word" <> "ToNat " <> unparseMO a <> ")" -unparseMO t@(ConvertNatToWord a) = sizeSuffix t "(natToWord" <> " " <> unparseMO a <> ")" +unparseMO (ConvertWordToNat a) = sizeSuffix a "(Prim.word" <> "ToNat " <> unparseMO a <> ")" +unparseMO t@(ConvertNatToWord a) = sizeSuffix t "(Prim.natToWord" <> " " <> unparseMO a <> ")" unparseMO (IfThenElse a b c) = "(if (" <> unparseMO c <> ") " <> unparseMO a <> " else " <> unparseMO b <> ")" unparseMO (a `NotEqual` b) = inParens unparseMO "!=" a b unparseMO (a `Equals` b) = inParens unparseMO "==" a b @@ -1016,13 +1019,13 @@ unparseMO (Text a) = '"' : (concatMap escape a) <> "\"" unparseMO (a `Concat` b) = "(" <> unparseMO a <> " # " <> unparseMO b <> ")" unparseNat :: KnownNat n => Proxy n -> MOTerm (BitLimited n Natural) -> String -unparseNat p a = "(nat" <> bitWidth p <> "ToNat(" <> unparseMO a <> "))" +unparseNat p a = "(Prim.nat" <> bitWidth p <> "ToNat(" <> unparseMO a <> "))" unparseInt :: KnownNat n => Proxy n -> MOTerm (BitLimited n Integer) -> String -unparseInt p a = "(int" <> bitWidth p <> "ToInt(" <> unparseMO a <> "))" +unparseInt p a = "(Prim.int" <> bitWidth p <> "ToInt(" <> unparseMO a <> "))" unparseWord :: KnownNat n => Proxy n -> MOTerm (BitLimited n Word) -> String -unparseWord p a = "(word" <> bitWidth p <> "ToNat(" <> unparseMO a <> "))" -- TODO we want signed too: wordToInt +unparseWord p a = "(Prim.word" <> bitWidth p <> "ToNat(" <> unparseMO a <> "))" -- TODO we want signed too: wordToInt -- TODOs: -- - wordToInt diff --git a/test/repl/ok/double-import.stdout.ok b/test/repl/ok/double-import.stdout.ok index ae051459fc0..1c8fbb037f3 100644 --- a/test/repl/ok/double-import.stdout.ok +++ b/test/repl/ok/double-import.stdout.ok @@ -8,14 +8,14 @@ Motoko 0.1 interpreter -- Interpreting empty.mo: -- Interpreting stdin: -- Finished stdin: -let anon-import-1.1 : module {} = {} +let anon-import-1.1 : module {...} -- Parsing stdin: > -- Checking stdin: -- Definedness stdin: -- Interpreting stdin: -- Finished stdin: -let anon-import-2.1 : module {} = {} +let anon-import-2.1 : module {...} -- Parsing stdin: > diff --git a/test/repl/ok/outrange-int-nat.stdout.ok b/test/repl/ok/outrange-int-nat.stdout.ok index 75ef205c01f..4991e7fc60c 100644 --- a/test/repl/ok/outrange-int-nat.stdout.ok +++ b/test/repl/ok/outrange-int-nat.stdout.ok @@ -1,28 +1,29 @@ Motoko 0.1 interpreter +> let Prim : module {...} > +127 : Int8 -> prelude:___: execution error, numeric overflow +> prim:___: execution error, numeric overflow > -128 : Int8 -> prelude:___: execution error, numeric overflow +> prim:___: execution error, numeric overflow > +32_767 : Int16 -> prelude:___: execution error, numeric overflow +> prim:___: execution error, numeric overflow > -32_768 : Int16 -> prelude:___: execution error, numeric overflow +> prim:___: execution error, numeric overflow > +2_147_483_647 : Int32 -> prelude:___: execution error, numeric overflow +> prim:___: execution error, numeric overflow > -2_147_483_648 : Int32 -> prelude:___: execution error, numeric overflow +> prim:___: execution error, numeric overflow > +9_223_372_036_854_775_807 : Int64 -> prelude:___: execution error, numeric overflow +> prim:___: execution error, numeric overflow > -9_223_372_036_854_775_808 : Int64 -> prelude:___: execution error, numeric overflow +> prim:___: execution error, numeric overflow > 255 : Nat8 -> prelude:___: execution error, numeric overflow +> prim:___: execution error, numeric overflow > 65_535 : Nat16 -> prelude:___: execution error, numeric overflow +> prim:___: execution error, numeric overflow > 4_294_967_295 : Nat32 -> prelude:___: execution error, numeric overflow +> prim:___: execution error, numeric overflow > 18_446_744_073_709_551_615 : Nat64 -> prelude:___: execution error, numeric overflow +> prim:___: execution error, numeric overflow > -127 : Int8 > -127 : Int8 > -32_767 : Int16 diff --git a/test/repl/ok/triangle-import.stdout.ok b/test/repl/ok/triangle-import.stdout.ok index e12a3548380..c3c1e0e1472 100644 --- a/test/repl/ok/triangle-import.stdout.ok +++ b/test/repl/ok/triangle-import.stdout.ok @@ -12,7 +12,7 @@ Motoko 0.1 interpreter -- Interpreting b.mo: -- Interpreting stdin: -- Finished stdin: -let anon-import-1.1 : module {i : Nat} = {i = 42} +let anon-import-1.1 : module {...} -- Parsing stdin: > -- Parsing lib/a.mo: @@ -23,14 +23,14 @@ let anon-import-1.1 : module {i : Nat} = {i = 42} -- Interpreting a.mo: -- Interpreting stdin: -- Finished stdin: -let anon-import-2.1 : module {i : Nat} = {i = 42} +let anon-import-2.1 : module {...} -- Parsing stdin: > -- Checking stdin: -- Definedness stdin: -- Interpreting stdin: -- Finished stdin: -let anon-import-3.1 : module {i : Nat} = {i = 42} +let anon-import-3.1 : module {...} -- Parsing stdin: > -- Parsing lib/triangle.mo: @@ -41,7 +41,7 @@ let anon-import-3.1 : module {i : Nat} = {i = 42} -- Interpreting triangle.mo: -- Interpreting stdin: -- Finished stdin: -let anon-import-4.1 : module {} = {} +let anon-import-4.1 : module {...} -- Parsing stdin: > diff --git a/test/repl/outrange-int-nat.sh b/test/repl/outrange-int-nat.sh index 762427192e7..03507485ac5 100755 --- a/test/repl/outrange-int-nat.sh +++ b/test/repl/outrange-int-nat.sh @@ -1,38 +1,39 @@ #!/usr/bin/env bash # Tests that the repl Int* and Nat* types properly trap ${MOC:-$(dirname "$BASH_SOURCE")/../../src/moc} -i <<__END__ -intToInt8 0x7F; -intToInt8 0x80; -intToInt8 (-0x80); -intToInt8 (-0x81); +import Prim "mo:prim"; +Prim.intToInt8 0x7F; +Prim.intToInt8 0x80; +Prim.intToInt8 (-0x80); +Prim.intToInt8 (-0x81); -intToInt16 0x7FFF; -intToInt16 0x8000; -intToInt16 (-0x8000); -intToInt16 (-0x8001); +Prim.intToInt16 0x7FFF; +Prim.intToInt16 0x8000; +Prim.intToInt16 (-0x8000); +Prim.intToInt16 (-0x8001); -intToInt32 0x7FFFFFFF; -intToInt32 0x80000000; -intToInt32 (-0x80000000); -intToInt32 (-0x80000001); +Prim.intToInt32 0x7FFFFFFF; +Prim.intToInt32 0x80000000; +Prim.intToInt32 (-0x80000000); +Prim.intToInt32 (-0x80000001); -intToInt64 0x7FFFFFFFFFFFFFFF; -intToInt64 0x8000000000000000; -intToInt64 (-0x8000000000000000); -intToInt64 (-0x8000000000000001); +Prim.intToInt64 0x7FFFFFFFFFFFFFFF; +Prim.intToInt64 0x8000000000000000; +Prim.intToInt64 (-0x8000000000000000); +Prim.intToInt64 (-0x8000000000000001); -natToNat8 0xFF; -natToNat8 0x100; +Prim.natToNat8 0xFF; +Prim.natToNat8 0x100; -natToNat16 0xFFFF; -natToNat16 0x10000; +Prim.natToNat16 0xFFFF; +Prim.natToNat16 0x10000; -natToNat32 0xFFFFFFFF; -natToNat32 0x100000000; +Prim.natToNat32 0xFFFFFFFF; +Prim.natToNat32 0x100000000; -natToNat64 0xFFFFFFFFFFFFFFFF; -natToNat64 0x10000000000000000; +Prim.natToNat64 0xFFFFFFFFFFFFFFFF; +Prim.natToNat64 0x10000000000000000; -127 : Int8; diff --git a/test/run-drun/GIT-843.mo b/test/run-drun/GIT-843.mo index b9bdf431d1a..eefc560327e 100644 --- a/test/run-drun/GIT-843.mo +++ b/test/run-drun/GIT-843.mo @@ -1,7 +1,8 @@ +import Prim "mo:prim"; // Both check_ir and ir_interpreter would failed // if an actor field name (legally) shadowed the actor name actor Bad { - public func Bad (){ debugPrint "ok"}; + public func Bad (){ Prim.debugPrint "ok"}; }; Bad.Bad(); //OR-CALL ingress Bad "DIDL\x00\x00" diff --git a/test/run-drun/actor-creation.mo b/test/run-drun/actor-creation.mo index 96c82eaeb02..ce5317928eb 100644 --- a/test/run-drun/actor-creation.mo +++ b/test/run-drun/actor-creation.mo @@ -1,24 +1,26 @@ -debugPrint ("main actor creating a"); +import Prim "mo:prim"; +Prim.debugPrint ("main actor creating a"); actor a { public func foo() { - debugPrint ("a.foo() called"); + Prim.debugPrint ("a.foo() called"); - debugPrint ("a creating b"); + Prim.debugPrint ("a creating b"); actor b { public func foo() { - debugPrint ("b.foo() called"); + Prim.debugPrint ("b.foo() called"); }; - debugPrint ("b created"); + Prim.debugPrint ("b created"); }; - debugPrint ("a calling b.foo()"); + Prim.debugPrint ("a calling b.foo()"); b.foo(); - debugPrint ("a.foo() done"); + Prim.debugPrint ("a.foo() done"); }; - debugPrint ("a created"); + Prim.debugPrint ("a created"); }; -debugPrint ("main actor calling a.foo()"); +Prim.debugPrint ("main actor calling a.foo()"); a.foo(); // certainly won’t work on drun //SKIP comp +//SKIP comp-stub diff --git a/test/run-drun/array-out-of-bounds.mo b/test/run-drun/array-out-of-bounds.mo index 6cb386c27c4..5c2cac415bf 100644 --- a/test/run-drun/array-out-of-bounds.mo +++ b/test/run-drun/array-out-of-bounds.mo @@ -1,14 +1,15 @@ +import Prim "mo:prim"; actor a { let xs = [0, 1, 2, 3, 4]; let ys = []; public func foo1() { ignore(xs[5]); - debugPrint("Unreachable code reached"); + Prim.debugPrint("Unreachable code reached"); }; public func foo2() { ignore(ys[0]); - debugPrint("Unreachable code reached"); + Prim.debugPrint("Unreachable code reached"); }; }; diff --git a/test/run-drun/async-free-var.mo b/test/run-drun/async-free-var.mo index f8fecce961d..88f77165736 100644 --- a/test/run-drun/async-free-var.mo +++ b/test/run-drun/async-free-var.mo @@ -1,18 +1,19 @@ +import Prim "mo:prim"; actor a { public func go() = ignore async { var x = "A"; - debugPrint x; + Prim.debugPrint x; let a = async { - debugPrint "Now in async"; - debugPrint x; + Prim.debugPrint "Now in async"; + Prim.debugPrint x; x := "B"; - debugPrint x; + Prim.debugPrint x; }; - debugPrint x; + Prim.debugPrint x; x := "C"; - debugPrint x; + Prim.debugPrint x; await a; - debugPrint x; + Prim.debugPrint x; }; }; a.go(); //OR-CALL ingress go "DIDL\x00\x00" diff --git a/test/run-drun/async-loop-while.mo b/test/run-drun/async-loop-while.mo index b99c622a8ac..d3542dab4bb 100644 --- a/test/run-drun/async-loop-while.mo +++ b/test/run-drun/async-loop-while.mo @@ -1,9 +1,10 @@ +import Prim "mo:prim"; actor a { public func go() = ignore async { { var i = 0; var j = 0; loop { - debugPrintNat(j); + Prim.debugPrintNat(j); assert(j == i); i += 1; j += 1; @@ -16,7 +17,7 @@ actor a { var i = 0; var j = 0; loop { - debugPrintNat(j); + Prim.debugPrintNat(j); assert(j == i); i += 1; j += 1; @@ -28,7 +29,7 @@ actor a { var i = 0; var j = 0; loop { - debugPrintNat(j); + Prim.debugPrintNat(j); assert(j == i); await (async (i += 1)); j += 1; @@ -45,7 +46,7 @@ actor a { break l; assert(false); }; - debugPrintNat(j); + Prim.debugPrintNat(j); assert(j == i); await (async (i += 1)); j += 1; diff --git a/test/run-drun/async-loop.mo b/test/run-drun/async-loop.mo index 4a8375753f8..aec697dacaf 100644 --- a/test/run-drun/async-loop.mo +++ b/test/run-drun/async-loop.mo @@ -1,10 +1,11 @@ +import Prim "mo:prim"; actor a { public func go() = ignore async { { var i = 0; var j = 0; label l loop { - debugPrintNat(j); + Prim.debugPrintNat(j); assert(j == i); i += 1; j += 1; @@ -19,7 +20,7 @@ actor a { var j = 0; label l loop { - debugPrintNat(j); + Prim.debugPrintNat(j); assert(j == i); i += 1; j += 1; @@ -34,7 +35,7 @@ actor a { var j = 0; label l loop { - debugPrintNat(j); + Prim.debugPrintNat(j); assert(j == i); await (async (i += 1)); j += 1; @@ -53,7 +54,7 @@ actor a { break l; assert(false); }; - debugPrintNat(j); + Prim.debugPrintNat(j); assert(j == i); await (async (i += 1)); j += 1; @@ -62,10 +63,5 @@ actor a { }; assert(i == 3); }; - - }; - - - - - + }; +}; diff --git a/test/run-drun/async-new-obj.mo b/test/run-drun/async-new-obj.mo index 1865b45a247..15f30b1870d 100644 --- a/test/run-drun/async-new-obj.mo +++ b/test/run-drun/async-new-obj.mo @@ -1,3 +1,4 @@ +import Prim "mo:prim"; actor a { public func go() = ignore async { /* Test asynchronous construction of an object */ @@ -10,7 +11,7 @@ actor a { public func get_b() : Text { b }; }; let (a, b) = (o.get_a(), o.get_b()); - debugPrint (a#b); + Prim.debugPrint (a#b); }; let b = async { @@ -21,7 +22,7 @@ actor a { public func get_b() : Text { b }; }; let (a, b) = (o.get_a(), o.get_b()); - debugPrint (a#b); + Prim.debugPrint (a#b); }; let c = async { @@ -32,7 +33,7 @@ actor a { public func get_b() : Text { b }; }; let (a, b) = (o.get_a(), o.get_b()); - debugPrint (a#b); + Prim.debugPrint (a#b); }; let d = async { @@ -43,7 +44,7 @@ actor a { public func get_b() : Text { b }; }; let (a, b) = (o.get_a(), o.get_b()); - debugPrint (a#b); + Prim.debugPrint (a#b); }; let e = async { @@ -57,7 +58,7 @@ actor a { }; }; let (a, b) = o.get_ab(); - debugPrint (a#b); + Prim.debugPrint (a#b); }; () diff --git a/test/run-drun/async-obj-mut.mo b/test/run-drun/async-obj-mut.mo index d94e2a13e29..a2624f73331 100644 --- a/test/run-drun/async-obj-mut.mo +++ b/test/run-drun/async-obj-mut.mo @@ -1,21 +1,22 @@ +import Prim "mo:prim"; actor a { public func go() = ignore async { let o = object { public var x = await { async { 1 } }; - let a = debugPrintNat(x); + let a = Prim.debugPrintNat(x); // private b = (x := await { async (x + 1) }); let b = (x := x + 1); - let c = debugPrintNat(x); + let c = Prim.debugPrintNat(x); public func foo() = { x := x + 1 }; let e = foo(); - let f = debugPrintNat(x); + let f = Prim.debugPrintNat(x); }; - debugPrint("done creating\n"); - debugPrintNat(o.x); + Prim.debugPrint("done creating\n"); + Prim.debugPrintNat(o.x); o.x := o.x + 1; - debugPrintNat(o.x); + Prim.debugPrintNat(o.x); o.foo(); - debugPrintNat(o.x); + Prim.debugPrintNat(o.x); } }; a.go(); //OR-CALL ingress go "DIDL\x00\x00" diff --git a/test/run-drun/async-while.mo b/test/run-drun/async-while.mo index 91b43fd5fde..56ec373b2de 100644 --- a/test/run-drun/async-while.mo +++ b/test/run-drun/async-while.mo @@ -1,9 +1,10 @@ +import Prim "mo:prim"; actor a { public func go() = ignore async { { var i = 0; var j = 0; while (j <= 2) { - debugPrintNat(j); + Prim.debugPrintNat(j); assert(j == i); i += 1; j += 1; @@ -16,7 +17,7 @@ actor a { var i = 0; var j = 0; while (await async (j <= 2)) { - debugPrintNat(j); + Prim.debugPrintNat(j); assert(j == i); i += 1; j += 1; @@ -28,7 +29,7 @@ actor a { var i = 0; var j = 0; while (j <= 2) { - debugPrintNat(j); + Prim.debugPrintNat(j); assert(j == i); await (async (i += 1)); j += 1; @@ -45,7 +46,7 @@ actor a { break l; assert(false); }; - debugPrintNat(j); + Prim.debugPrintNat(j); assert(j == i); await (async (i += 1)); j += 1; diff --git a/test/run-drun/await.mo b/test/run-drun/await.mo index 1f0cd0d5eb1..1089e5eeda6 100644 --- a/test/run-drun/await.mo +++ b/test/run-drun/await.mo @@ -1,69 +1,70 @@ +import Prim "mo:prim"; actor a { public func go() { var cnt : Nat = 0; func f(i:Nat) : async Nat { - debugPrint ("cnt: " # debug_show cnt # " i: " # debug_show i); + Prim.debugPrint ("cnt: " # debug_show cnt # " i: " # debug_show i); cnt += 1; cnt; }; - debugPrint "a"; + Prim.debugPrint "a"; let a = async await f(0); - debugPrint "b"; + Prim.debugPrint "b"; let b = async { await f(1); }; - debugPrint "c"; + Prim.debugPrint "c"; let c = async { let _ = await f(2); await f(3); }; - debugPrint "d"; + Prim.debugPrint "d"; let d = (async { return await f(4); }) : async Int; - debugPrint "e"; + Prim.debugPrint "e"; let e = async { var i = 5; - debugPrint "e-while"; + Prim.debugPrint "e-while"; while (i < 8) { let _ = await f(i); i += 1; }; - debugPrint "e-exit"; + Prim.debugPrint "e-exit"; }; - debugPrint "g"; + Prim.debugPrint "g"; let g = async { var i = 10; - debugPrint "g-label"; + Prim.debugPrint "g-label"; label lp while (true) { if (i < 13) { - debugPrint "."; + Prim.debugPrint "."; let _ = await f(i); i += 1; continue lp; } else {}; break lp; }; - debugPrint "g-exit"; + Prim.debugPrint "g-exit"; }; - debugPrint "holy"; + Prim.debugPrint "holy"; func p():async (Text,Text) { ("fst","snd"); }; let h = async { let (a,b) = ("a","b"); /* await p(a,b);*/ - debugPrint a; - debugPrint b; + Prim.debugPrint a; + Prim.debugPrint b; }; } }; diff --git a/test/run-drun/block.mo b/test/run-drun/block.mo index 665170fbf8d..e50efce4f50 100644 --- a/test/run-drun/block.mo +++ b/test/run-drun/block.mo @@ -1,38 +1,39 @@ +import Prim "mo:prim"; actor a { public func go() = ignore { let a = async { let (a,b) = ("a1","b1"); - debugPrint a; - debugPrint b; + Prim.debugPrint a; + Prim.debugPrint b; }; let b = async { let (a,b) = await (async ("a2","b2")); - debugPrint a; - debugPrint b; + Prim.debugPrint a; + Prim.debugPrint b; }; let c = async { - func f(a:Text,b:Text):(){ debugPrint a; debugPrint b;}; + func f(a:Text,b:Text):(){ Prim.debugPrint a; Prim.debugPrint b;}; let (a,b) = await (async ("a3","b3")); let _ = f(a,b); }; let d = async { var f = 1; - debugPrintNat (f); + Prim.debugPrintNat (f); let (a,b) = await (async ("a4","b4")); f += 2; - debugPrintNat (f); + Prim.debugPrintNat (f); }; let e = async { var f = await (async 5); - debugPrintNat (f); + Prim.debugPrintNat (f); let (a,b) = await (async ("a5","b5")); f += 1; - debugPrintNat (f); + Prim.debugPrintNat (f); }; } }; diff --git a/test/run-drun/caller.mo b/test/run-drun/caller.mo index 2dbe31b5472..d3081f0e54e 100644 --- a/test/run-drun/caller.mo +++ b/test/run-drun/caller.mo @@ -1,3 +1,4 @@ +import Prim "mo:prim"; actor a { public shared ctxt func c1 () : async () { @@ -32,7 +33,7 @@ actor a { }; public shared query {caller} func c8() : async Word32 { - hashBlob caller; + Prim.hashBlob caller; }; }; diff --git a/test/run-drun/chat.mo b/test/run-drun/chat.mo index 1b21856a93c..3fce8bfb8ad 100644 --- a/test/run-drun/chat.mo +++ b/test/run-drun/chat.mo @@ -1,3 +1,4 @@ +import Prim "mo:prim"; type List = ?{head : T; var tail : List}; type Post = shared Text -> (); @@ -42,7 +43,7 @@ actor class Client() = this { }; public func send(msg : Text) { - debugPrint(name # " received " # msg); + Prim.debugPrint(name # " received " # msg); }; }; @@ -63,4 +64,6 @@ charlie.go("charlie", server); - parameterising Client on s:IServer argument complains about non-closed actor (expected acc. to Joachim, pending system changes) */ +// non-closed actors not allowed //SKIP comp +//SKIP comp-stub diff --git a/test/run-drun/closure-params.mo b/test/run-drun/closure-params.mo index 0e529f6e6ae..d66788fc4bc 100644 --- a/test/run-drun/closure-params.mo +++ b/test/run-drun/closure-params.mo @@ -1,14 +1,15 @@ +import Prim "mo:prim"; let a = actor { var c = 0; public func incn(n : Nat) : () { c += n; - debugPrintNat(c); + Prim.debugPrintNat(c); }; public func readCounter(f : shared Nat -> ()) : () { f(c); }; - public func printNat(n: Nat) { debugPrintNat n }; + public func printNat(n: Nat) { Prim.debugPrintNat n }; public func go() { incn(1); diff --git a/test/run-drun/count-callbacks.mo b/test/run-drun/count-callbacks.mo index 639ce158e79..97dec174607 100644 --- a/test/run-drun/count-callbacks.mo +++ b/test/run-drun/count-callbacks.mo @@ -1,28 +1,29 @@ +import Prim "mo:prim"; actor a { public func ping() : async () { - debugPrint("ping! " # debug_show rts_callback_table_count()); + Prim.debugPrint("ping! " # debug_show Prim.rts_callback_table_count()); }; public func go() = ignore async { - debugPrint("go 1: " # debug_show rts_callback_table_count()); + Prim.debugPrint("go 1: " # debug_show Prim.rts_callback_table_count()); let a1 = ping(); - debugPrint("go 1: " # debug_show rts_callback_table_count()); + Prim.debugPrint("go 1: " # debug_show Prim.rts_callback_table_count()); let a2 = ping(); - debugPrint("go 1: " # debug_show rts_callback_table_count()); + Prim.debugPrint("go 1: " # debug_show Prim.rts_callback_table_count()); let a3 = ping(); - debugPrint("go 1: " # debug_show rts_callback_table_count()); + Prim.debugPrint("go 1: " # debug_show Prim.rts_callback_table_count()); let a4 = ping(); - debugPrint("go 1: " # debug_show rts_callback_table_count()); + Prim.debugPrint("go 1: " # debug_show Prim.rts_callback_table_count()); await a1; - debugPrint("go 2: " # debug_show rts_callback_table_count()); + Prim.debugPrint("go 2: " # debug_show Prim.rts_callback_table_count()); await a2; - debugPrint("go 3: " # debug_show rts_callback_table_count()); + Prim.debugPrint("go 3: " # debug_show Prim.rts_callback_table_count()); await a3; - debugPrint("go 4: " # debug_show rts_callback_table_count()); + Prim.debugPrint("go 4: " # debug_show Prim.rts_callback_table_count()); await a4; - debugPrint("go 5: " # debug_show rts_callback_table_count()); + Prim.debugPrint("go 5: " # debug_show Prim.rts_callback_table_count()); }; }; a.go(); //OR-CALL ingress go "DIDL\x00\x00" diff --git a/test/run-drun/counter.mo b/test/run-drun/counter.mo index 0f4e4ba26ce..4c98915fa51 100644 --- a/test/run-drun/counter.mo +++ b/test/run-drun/counter.mo @@ -1,11 +1,12 @@ +import Prim "mo:prim"; actor { var c = 1; public func inc() { c += 1; - debugPrintNat c + Prim.debugPrintNat c }; public func printCounter () { - debugPrintNat c + Prim.debugPrintNat c }; public func get() : async Nat { return c diff --git a/test/run-drun/counter2.mo b/test/run-drun/counter2.mo index 7ff9a17359b..e6c14bb83e8 100644 --- a/test/run-drun/counter2.mo +++ b/test/run-drun/counter2.mo @@ -1,11 +1,12 @@ +import Prim "mo:prim"; let a = actor { var c = 1; public func inc() { c += 1; - debugPrintNat c; + Prim.debugPrintNat c; }; public func printCounter () { - debugPrintNat c; + Prim.debugPrintNat c; }; public func go() { diff --git a/test/run-drun/create-then-trap.mo b/test/run-drun/create-then-trap.mo index 4150b084c84..50ff8f6c635 100644 --- a/test/run-drun/create-then-trap.mo +++ b/test/run-drun/create-then-trap.mo @@ -1,8 +1,9 @@ +import Prim "mo:prim"; actor a { public func go() { actor b { public func bad() { - debugPrint ("b.bad() called (should not happen)"); + Prim.debugPrint ("b.bad() called (should not happen)"); } }; b.bad(); @@ -10,3 +11,9 @@ actor a { } }; a.go(); //OR-CALL ingress go "DIDL\x00\x00" + + +// disabled, because hard to use Prim from inner actor +// a bit sad, because this test is mostly interesting on ic-stub + +//SKIP comp-stub diff --git a/test/run-drun/data-params.mo b/test/run-drun/data-params.mo index aa83f24286b..8a014db2dad 100644 --- a/test/run-drun/data-params.mo +++ b/test/run-drun/data-params.mo @@ -1,75 +1,76 @@ +import Prim "mo:prim"; actor a { var c : Int = 0; public func inci(n : Int) : () { c += n; - debugPrintInt(c); + Prim.debugPrintInt(c); }; public func incn(n : Nat) : () { c += n; - debugPrintInt(c); + Prim.debugPrintInt(c); }; public func incnn(n1 : Nat, n2 : Nat) : () { c += n1 + n2; - debugPrintInt(c); + Prim.debugPrintInt(c); }; public func incnested(n1 : Nat, (n2 : Nat, n3 : Nat)) : () { c += n1 + n2 + n3; - debugPrintInt(c); + Prim.debugPrintInt(c); }; public func incarray(a : [Nat]) : () { for (i in a.vals()) { c += i }; - debugPrintInt(c); + Prim.debugPrintInt(c); }; public func incopt(a : ?Nat) : () { switch a { case null { c += 1000000 }; case (?a) { c += a }; }; - debugPrintInt(c); + Prim.debugPrintInt(c); }; public func increcord(a : { x : Nat; y : Nat }) : () { c += a.x; c += a.y; - debugPrintInt(c); + Prim.debugPrintInt(c); }; public func incVariant(v : { #foo : Nat; #bar : Nat }) { c += (switch v { case (#foo n) n; case (#bar n) n; }); - debugPrintInt(c); + Prim.debugPrintInt(c); }; public func printCounter() { - debugPrintInt(c); + Prim.debugPrintInt(c); }; public func printLabeled(l:Text) { - debugPrint l; - debugPrintInt(c); + Prim.debugPrint l; + Prim.debugPrintInt(c); }; public func printLabeledOpt(?l:?Text) { - debugPrint l; - debugPrintInt(c); + Prim.debugPrint l; + Prim.debugPrintInt(c); }; public func incwords(w8 : Word8, w16 : Word16, w32 : Word32, w64 : Word64) : () { - c += word8ToInt(w8); - c += word16ToInt(w16); - c += word32ToInt(w32); - c += word64ToInt(w64); - debugPrintInt(c); + c += Prim.word8ToInt(w8); + c += Prim.word16ToInt(w16); + c += Prim.word32ToInt(w32); + c += Prim.word64ToInt(w64); + Prim.debugPrintInt(c); }; public func incnats(n8 : Nat8, n16 : Nat16, n32 : Nat32, n64 : Nat64) : () { - c += nat8ToNat(n8); - c += nat16ToNat(n16); - c += nat32ToNat(n32); - c += nat64ToNat(n64); - debugPrintInt(c); + c += Prim.nat8ToNat(n8); + c += Prim.nat16ToNat(n16); + c += Prim.nat32ToNat(n32); + c += Prim.nat64ToNat(n64); + Prim.debugPrintInt(c); }; public func incints(i8 : Int8, i16 : Int16, i32 : Int32, i64 : Int64) : () { - c += int8ToInt(i8); - c += int16ToInt(i16); - c += int32ToInt(i32); - c += int64ToInt(i64); - debugPrintInt(c); + c += Prim.int8ToInt(i8); + c += Prim.int16ToInt(i16); + c += Prim.int32ToInt(i32); + c += Prim.int64ToInt(i64); + Prim.debugPrintInt(c); }; public func go() : () { diff --git a/test/run-drun/flatten-awaitables.mo b/test/run-drun/flatten-awaitables.mo index 1111f312180..34f33152c1e 100644 --- a/test/run-drun/flatten-awaitables.mo +++ b/test/run-drun/flatten-awaitables.mo @@ -1,3 +1,4 @@ +import Prim "mo:prim"; // test flattening of awaitable, shared function arguments let a = actor { @@ -32,25 +33,25 @@ let a = actor { public func go() = ignore async { - debugPrint "first-order"; + Prim.debugPrint "first-order"; let () = await a.m0(); - debugPrint "0"; + Prim.debugPrint "0"; let 1 = await a.m1(1); - debugPrint "1"; + Prim.debugPrint "1"; let (2,true) = await a.m2(2,true); - debugPrint "2"; + Prim.debugPrint "2"; let (3,false,"text") = await a.m3(3,false,"text"); - debugPrint "3"; + Prim.debugPrint "3"; let () = await a.n0(); - debugPrint "4"; + Prim.debugPrint "4"; let 1 = await a.n1(1); - debugPrint "5"; + Prim.debugPrint "5"; let (2,true) = await a.n2(2,true); - debugPrint "6"; + Prim.debugPrint "6"; let (3,false,"text") = await a.n3(3,false,"text"); - debugPrint "7"; + Prim.debugPrint "7"; let u = (); let x:Int = 1; @@ -58,59 +59,59 @@ let a = actor { let xyz:(Int,Bool,Text) = (3,false,"text"); let () = await a.m0 u; - debugPrint "8"; + Prim.debugPrint "8"; let 1 = await a.m1 x; - debugPrint "9"; + Prim.debugPrint "9"; let (2,true) = await a.m2 xy; - debugPrint "10"; + Prim.debugPrint "10"; let (3,false,"text") = await a.m3 xyz; - debugPrint "11"; + Prim.debugPrint "11"; let () = await a.n0 u; - debugPrint "12"; + Prim.debugPrint "12"; let 1 = await a.n1 x; - debugPrint "13"; + Prim.debugPrint "13"; let (2,true) = await a.n2 xy; - debugPrint "14"; + Prim.debugPrint "14"; let (3,false,"text") = await a.n3 xyz; - debugPrint "15"; + Prim.debugPrint "15"; - debugPrint "higher-order"; + Prim.debugPrint "higher-order"; let () = await a.h0(a.m0,()); - debugPrint "0"; + Prim.debugPrint "0"; let 1 = await a.h1(a.m1,1); - debugPrint "1"; + Prim.debugPrint "1"; let (2,true) = await a.h2(a.m2,(2,true)); - debugPrint "2"; + Prim.debugPrint "2"; let (3,false,"text") = await a.h3(a.m3,(3,false,"text")); - debugPrint "3"; + Prim.debugPrint "3"; let () = await a.g0(a.n0,()); - debugPrint "4"; + Prim.debugPrint "4"; let 1 = await a.g1(a.n1,1); - debugPrint "5"; + Prim.debugPrint "5"; let (2,true) = await a.g2(a.n2,(2,true)); - debugPrint "6"; + Prim.debugPrint "6"; let (3,false,"text") = await a.g3(a.n3,(3,false,"text")); - debugPrint "7"; + Prim.debugPrint "7"; let () = await a.h0(a.m0,u); - debugPrint "8"; + Prim.debugPrint "8"; let 1 = await a.h1(a.m1,x); - debugPrint "9"; + Prim.debugPrint "9"; let (2,true) = await a.h2(a.m2,xy); - debugPrint "10"; + Prim.debugPrint "10"; let (3,false,"text") = await a.h3(a.m3,xyz); - debugPrint "11"; + Prim.debugPrint "11"; let () = await a.g0(a.n0,u); - debugPrint "12"; + Prim.debugPrint "12"; let 1 = await a.g1(a.n1,x); - debugPrint "13"; + Prim.debugPrint "13"; let (2,true) = await a.g2(a.n2,xy); - debugPrint "14"; + Prim.debugPrint "14"; let (3,false,"text") = await a.g3(a.n3,xyz); - debugPrint "15"; + Prim.debugPrint "15"; }; }; a.go(); //OR-CALL ingress go "DIDL\x00\x00" diff --git a/test/run-drun/for-await.mo b/test/run-drun/for-await.mo index d6139b230f1..724fe878972 100644 --- a/test/run-drun/for-await.mo +++ b/test/run-drun/for-await.mo @@ -1,10 +1,18 @@ +import Prim "mo:prim"; + +class range(x : Nat, y : Nat) { + var i = x; + public func next() : ?Nat { if (i > y) null else {let j = i; i += 1; ?j} }; +}; + + actor a { public func go() = ignore async { { var i = 0; i := 0; for (j in range(0, 10)) { - debugPrintNat(j); + Prim.debugPrintNat(j); assert(j == i); await (async (i += 1)); }; diff --git a/test/run-drun/free-callbacks.mo b/test/run-drun/free-callbacks.mo index 7fbe09ba40a..7c31aa1bdd3 100644 --- a/test/run-drun/free-callbacks.mo +++ b/test/run-drun/free-callbacks.mo @@ -1,21 +1,22 @@ +import Prim "mo:prim"; actor a { public func ping() : async () { }; public func go() = ignore async { - let s0 = rts_heap_size(); - let a = Array_init<()>(2500, ()); + let s0 = Prim.rts_heap_size(); + let a = Prim.Array_init<()>(2500, ()); await ping(); - let s1 = rts_heap_size(); + let s1 = Prim.rts_heap_size(); await ping(); - let s2 = rts_heap_size(); + let s2 = Prim.rts_heap_size(); // last use of a ignore(a); await ping(); // now a should be freed - let s3 = rts_heap_size(); + let s3 = Prim.rts_heap_size(); - debugPrint( + Prim.debugPrint( "Ignore Diff: " # debug_show s0 # " " # debug_show s1 # " " # diff --git a/test/run-drun/generic-tail-rec.mo b/test/run-drun/generic-tail-rec.mo index 87cde02b7b4..1481f6f2b68 100644 --- a/test/run-drun/generic-tail-rec.mo +++ b/test/run-drun/generic-tail-rec.mo @@ -1,3 +1,4 @@ +import Prim "mo:prim"; /* test generic self-tail-recursion */ let bound:Int = 100000; @@ -5,7 +6,7 @@ let bound:Int = 100000; { func Loop(n:Int){ if (n >= bound) { - debugPrint "done 1"; + Prim.debugPrint "done 1"; return; }; Loop(n+1); @@ -17,7 +18,7 @@ Loop(0); { func Loop(n:Int){ if (n >= bound) { - debugPrint "done 2"; + Prim.debugPrint "done 2"; return; }; return Loop(n+1); @@ -30,7 +31,7 @@ Loop(0); { func Loop(n:Int){ if (n >= bound) { - debugPrint "done 3"; + Prim.debugPrint "done 3"; return; }; Loop(n+1); @@ -42,7 +43,7 @@ Loop(0); { func Loop(n:Int){ if (n >= bound) { - debugPrint "done 4"; + Prim.debugPrint "done 4"; return; }; Loop(n+1); diff --git a/test/run-drun/hello-world-async.mo b/test/run-drun/hello-world-async.mo index ff441afb7e2..63e00d32a47 100644 --- a/test/run-drun/hello-world-async.mo +++ b/test/run-drun/hello-world-async.mo @@ -1,10 +1,11 @@ +import Prim "mo:prim"; actor a { public func world() { - debugPrint("World!"); + Prim.debugPrint("World!"); }; public func go() { a.world(); - debugPrint("Hello "); + Prim.debugPrint("Hello "); }; }; a.go(); //OR-CALL ingress go "DIDL\x00\x00" diff --git a/test/run-drun/hello-world-await.mo b/test/run-drun/hello-world-await.mo index b1f47ee503f..841f6a86052 100644 --- a/test/run-drun/hello-world-await.mo +++ b/test/run-drun/hello-world-await.mo @@ -1,3 +1,4 @@ +import Prim "mo:prim"; let a = actor { public func hello() : async Text { "Hello "; @@ -6,7 +7,7 @@ let a = actor { "World!" }; public func go() = ignore async { - debugPrint((await hello()) # (await world())); + Prim.debugPrint((await hello()) # (await world())); }; }; a.go(); //OR-CALL ingress go "DIDL\x00\x00" diff --git a/test/run-drun/hello-world-message.mo b/test/run-drun/hello-world-message.mo index cd14b3d32b4..1964ee8e6d3 100644 --- a/test/run-drun/hello-world-message.mo +++ b/test/run-drun/hello-world-message.mo @@ -1,6 +1,7 @@ +import Prim "mo:prim"; actor { public func hello() { - debugPrint("Hello World!"); + Prim.debugPrint("Hello World!"); } } diff --git a/test/run-drun/hello-world.mo b/test/run-drun/hello-world.mo index 84266d49e9c..4723bc1871f 100644 --- a/test/run-drun/hello-world.mo +++ b/test/run-drun/hello-world.mo @@ -1 +1,2 @@ -debugPrint("Hello World!"); +import Prim "mo:prim"; +Prim.debugPrint("Hello World!"); diff --git a/test/run-drun/idl-any.mo b/test/run-drun/idl-any.mo index f05a21c217c..a8e2efc8de5 100644 --- a/test/run-drun/idl-any.mo +++ b/test/run-drun/idl-any.mo @@ -1,8 +1,9 @@ +import Prim "mo:prim"; // This tests checks that the IDL decoder properly // zooms past the any argument and finds the beginning of the string actor { public func any(_ : Any, x : Text) : async () { - debugPrint ("ok: " # x); + Prim.debugPrint ("ok: " # x); }; } diff --git a/test/run-drun/idl-nat-int.mo b/test/run-drun/idl-nat-int.mo index 2e5b3c1bd47..99ee900eb80 100644 --- a/test/run-drun/idl-nat-int.mo +++ b/test/run-drun/idl-nat-int.mo @@ -1,9 +1,11 @@ +import Prim "mo:prim"; + actor { public query func absolute(x:Int) : async Nat { - abs x + Prim.abs x }; public query func absolutes(xs:[Int]) : async [Nat] { - Array_tabulate(xs.len(), func (i:Int) : Nat = abs(xs[i])) + Prim.Array_tabulate(xs.len(), func (i:Int) : Nat = Prim.abs(xs[i])) }; } diff --git a/test/run-drun/idl-option.mo b/test/run-drun/idl-option.mo index e620332618f..543001cfc15 100644 --- a/test/run-drun/idl-option.mo +++ b/test/run-drun/idl-option.mo @@ -1,10 +1,11 @@ +import Prim "mo:prim"; // This test checks that the IDL decoder can // do the subtyping from null to option actor { public func any(o : ?Text) : async () { switch o { - case null debugPrint ("ok: null"); - case (?x) debugPrint ("ok: " # x); + case null Prim.debugPrint ("ok: null"); + case (?x) Prim.debugPrint ("ok: " # x); } }; } diff --git a/test/run-drun/idl-record.mo b/test/run-drun/idl-record.mo index 4194e64299e..95dc5231ad9 100644 --- a/test/run-drun/idl-record.mo +++ b/test/run-drun/idl-record.mo @@ -1,25 +1,26 @@ +import Prim "mo:prim"; // This test checks that the IDL decoder can // do the subtyping from received many-field record // to a double-field one (field names are in hash order) actor { public func pair(o : (Text, Int)) : async () { switch o { - case (content, num) debugPrint ("ok: " # debug_show num); + case (content, num) Prim.debugPrint ("ok: " # debug_show num); } }; public func record(o : {content: Text; value : Int}) : async () { switch o { - case {content} debugPrint ("ok: " # content); + case {content} Prim.debugPrint ("ok: " # content); } }; public func record1(o : {value : Int; byte : Int8}) : async () { switch o { - case {byte} debugPrint ("ok: " # debug_show byte); + case {byte} Prim.debugPrint ("ok: " # debug_show byte); } }; public func record2(o : {content: Text; value : Int}, follower : Int8) : async Int8 { switch o { - case {content} { debugPrint ("ok: " # " " # content # " " # debug_show follower); follower }; + case {content} { Prim.debugPrint ("ok: " # " " # content # " " # debug_show follower); follower }; } }; } diff --git a/test/run-drun/idl-tuple.mo b/test/run-drun/idl-tuple.mo index 42a553f5418..6336158f46e 100644 --- a/test/run-drun/idl-tuple.mo +++ b/test/run-drun/idl-tuple.mo @@ -1,3 +1,4 @@ +import Prim "mo:prim"; actor { // top-level tuple public query func len2(x:Text, y:Text) : async (Int,Int) { @@ -5,11 +6,11 @@ actor { }; // a pair embedded in top-level tuple public query func len3((x:Text, i:Int32), y:Text) : async (Int,Int,Int) { - (x.len(), y.len(), int32ToInt i) + (x.len(), y.len(), Prim.int32ToInt i) }; // a triple embedded in top-level tuple public query func len3a((x:Text, i:Int32, z:?(Text,Int32)), y:Text) : async (Int,Int,Int) { - (x.len(), y.len(), int32ToInt i) + (x.len(), y.len(), Prim.int32ToInt i) } } diff --git a/test/run-drun/idl-variant.mo b/test/run-drun/idl-variant.mo index e9c4207bd38..6a81e47dfa5 100644 --- a/test/run-drun/idl-variant.mo +++ b/test/run-drun/idl-variant.mo @@ -1,8 +1,10 @@ +import Prim "mo:prim"; + type Either = { #left: Word32; #right: Char; #fix: Either }; func to_left(e : Either) : Either = switch e { - case (#right n) #left (charToWord32 n); + case (#right n) #left (Prim.charToWord32 n); case (#fix t) #fix (to_left t); case other other }; diff --git a/test/run-drun/idl-vector.mo b/test/run-drun/idl-vector.mo index dbecbcd2c11..824126edc7d 100644 --- a/test/run-drun/idl-vector.mo +++ b/test/run-drun/idl-vector.mo @@ -1,7 +1,10 @@ +import Prim "mo:prim"; + type Rose = [Rose]; type MayRose = ?[MayRose]; -func may(r : Rose) : MayRose = ?Array_tabulate(r.len(), func (i : Nat) = may(r[i])); +func may(r : Rose) : MayRose = + ?Prim.Array_tabulate(r.len(), func (i : Nat) = may(r[i])); actor { public query func rose(r : Rose) : async MayRose { diff --git a/test/run-drun/indirect-counter.mo b/test/run-drun/indirect-counter.mo deleted file mode 100644 index 8d9bc3f5a89..00000000000 --- a/test/run-drun/indirect-counter.mo +++ /dev/null @@ -1,21 +0,0 @@ -let a = actor { - let aa = actor { - var c = 1; - public func inc() { - c += 1; - debugPrintNat(c) - }; - public func debugPrint() { - debugPrintNat(c) - }; - }; - public func inc() { aa.inc() }; - public func debugPrint() { aa.debugPrint() }; -}; - -a.inc(); -a.inc(); -a.inc(); -a.debugPrint() - -//SKIP comp diff --git a/test/run-drun/interleave.mo b/test/run-drun/interleave.mo index d5c78eb8d56..d567d28fbb2 100644 --- a/test/run-drun/interleave.mo +++ b/test/run-drun/interleave.mo @@ -1,9 +1,10 @@ +import Prim "mo:prim"; actor a { public func go() { var cnt : Nat = 0; func f(m: Text, i:Nat) : async Nat { - debugPrint (m # " cnt: " # debug_show cnt # " i: " # debug_show i); + Prim.debugPrint (m # " cnt: " # debug_show cnt # " i: " # debug_show i); cnt += 1; cnt; }; @@ -12,19 +13,19 @@ actor a { let e = async { var i = 5; - debugPrint " e-while\n"; + Prim.debugPrint " e-while\n"; while (i < 10) { let _ = await f(" e",i); i += 1; }; - debugPrint " e-exit\n"; + Prim.debugPrint " e-exit\n"; }; - debugPrint "g"; + Prim.debugPrint "g"; let g = async { var i = 10; - debugPrint "g-label\n"; + Prim.debugPrint "g-label\n"; label lp while (true) { if (i < 15) { @@ -34,7 +35,7 @@ actor a { } else {}; break lp; }; - debugPrint "g-exit\n"; + Prim.debugPrint "g-exit\n"; }; } diff --git a/test/run-drun/issue-894.mo b/test/run-drun/issue-894.mo index 591e969ec2e..73cb3612714 100644 --- a/test/run-drun/issue-894.mo +++ b/test/run-drun/issue-894.mo @@ -1,3 +1,4 @@ +import Prim "mo:prim"; actor a { public shared func id(i : Nat) : async Nat { i }; @@ -6,36 +7,36 @@ actor a { { let o = {var l = 0}; o.l := 1; - debugPrintNat(o.l); + Prim.debugPrintNat(o.l); assert o.l == 1; }; { let o = {var l = 0}; o.l := await async 1; - debugPrintNat(o.l); + Prim.debugPrintNat(o.l); assert o.l == 1; }; { let a = [var 0]; a[await async 0] := 1; - debugPrintNat(a[0]); + Prim.debugPrintNat(a[0]); assert a[0] == 1; }; { let a = [var 0]; a[await async 0] := await async 1; - debugPrintNat(a[0]); + Prim.debugPrintNat(a[0]); assert a[0] == 1; }; { - let a = Array_init(5, 0); + let a = Prim.Array_init(5, 0); for (i in a.keys()) { a[await id(i)] := await id(i); - debugPrintNat(a[i]); + Prim.debugPrintNat(a[i]); assert a[i] == i; }; }; diff --git a/test/run-drun/large-array.mo b/test/run-drun/large-array.mo index 3b09dd76757..9998b870507 100644 --- a/test/run-drun/large-array.mo +++ b/test/run-drun/large-array.mo @@ -1,5 +1,7 @@ +import Prim "mo:prim"; + // Should allocate 1G -ignore(Array_init<()>(1024*1024*1024/4, ())); +ignore(Prim.Array_init<()>(1024*1024*1024/4, ())); //SKIP run //SKIP run-ir diff --git a/test/run-drun/local-throw.mo b/test/run-drun/local-throw.mo index edb93b96f1e..48ec018fb55 100644 --- a/test/run-drun/local-throw.mo +++ b/test/run-drun/local-throw.mo @@ -1,13 +1,14 @@ +import Prim "mo:prim"; // This file only exercises local throws that don't cross function boundaries. // In principle, it should run on all targets. actor a { public func t2() : async () { try { - throw error("t2"); + throw Prim.error("t2"); assert(false); } catch e { - switch (errorCode(e),errorMessage(e)) { + switch (Prim.errorCode(e),Prim.errorMessage(e)) { case (#error, "t2") { }; case (#system, _ ) { assert false;}; case (#error, _) { assert false;}; @@ -18,12 +19,12 @@ actor a { public func t3() : async () { try { try { - throw error("t3"); + throw Prim.error("t3"); assert(false); } catch e1 { - switch (errorCode(e1), errorMessage(e1)) { + switch (Prim.errorCode(e1), Prim.errorMessage(e1)) { case (#error, "t3") { - throw error("t31"); + throw Prim.error("t31"); }; case (#system, _) { assert false; @@ -35,7 +36,7 @@ actor a { } } catch e2 { - switch (errorCode(e2),errorMessage(e2)) { + switch (Prim.errorCode(e2),Prim.errorMessage(e2)) { case (#error, "t31") { }; case (#system, _) { assert false; @@ -51,14 +52,14 @@ actor a { public func go() = ignore async { try { await t2(); - debugPrint ("t2 ok"); + Prim.debugPrint ("t2 ok"); } catch _ { assert false; }; try { await t3(); - debugPrint ("t3 ok"); + Prim.debugPrint ("t3 ok"); } catch _ { assert false; }; diff --git a/test/run-drun/log-slow.mo b/test/run-drun/log-slow.mo index f1260d2d64d..49111076ed5 100644 --- a/test/run-drun/log-slow.mo +++ b/test/run-drun/log-slow.mo @@ -1,56 +1,63 @@ // These are rather long-running tests, not advisable for wasm-run! - //SKIP comp-stub +import Prim "mo:prim"; + +class range(x : Nat, y : Nat) { + var i = x; + public func next() : ?Nat { if (i > y) null else {let j = i; i += 1; ?j} }; +}; + // Nat* + for (n in range(0, 255)) { for (exp in range(0, 255)) { if (n <= 1 or exp <= 1 or (n <= 16 and exp <= 9)) { let res = n ** exp; - if (res <= 255) { assert (natToNat8 n ** natToNat8 exp == natToNat8 res) } + if (res <= 255) { assert (Prim.natToNat8 n ** Prim.natToNat8 exp == Prim.natToNat8 res) } } } }; -assert (natToNat8 2 ** natToNat8 7 == natToNat8 128); // highest exponent +assert (Prim.natToNat8 2 ** Prim.natToNat8 7 == Prim.natToNat8 128); // highest exponent for (n in range(0, 255)) { for (exp in range(0, 255)) { if (n <= 1 or exp <= 1 or (n <= 16 and exp <= 9)) { // see #537 let res = n ** exp; - if (res <= 255) { assert (natToNat8 n ** natToNat8 exp == natToNat8 res) } + if (res <= 255) { assert (Prim.natToNat8 n ** Prim.natToNat8 exp == Prim.natToNat8 res) } } } }; -assert (natToNat16 2 ** natToNat16 15 == natToNat16 32768); // highest exponent +assert (Prim.natToNat16 2 ** Prim.natToNat16 15 == Prim.natToNat16 32768); // highest exponent for (n in range(0, 255)) { for (exp in range(0, 255)) { if (n <= 1 or exp <= 106) { // see #537 let res = n ** exp; - if (res <= 65535) { assert (natToNat16 n ** natToNat16 exp == natToNat16 res) } + if (res <= 65535) { assert (Prim.natToNat16 n ** Prim.natToNat16 exp == Prim.natToNat16 res) } } } }; -assert (natToNat32 2 ** natToNat32 31 == natToNat32 2_147_483_648); // highest exponent +assert (Prim.natToNat32 2 ** Prim.natToNat32 31 == Prim.natToNat32 2_147_483_648); // highest exponent for (n in range(0, 255)) { for (exp in range(0, 255)) { if (n <= 1 or exp <= 106) { // see #537 let res = n ** exp; - if (res <= 65535) { assert (natToNat32 n ** natToNat32 exp == natToNat32 res) } + if (res <= 65535) { assert (Prim.natToNat32 n ** Prim.natToNat32 exp == Prim.natToNat32 res) } } } }; -assert (natToNat64 2 ** natToNat64 63 == natToNat64 9223372036854775808); // highest exponent -assert (natToNat64 2642245 ** natToNat64 3 == natToNat64 18_446_724_184_312_856_125); +assert (Prim.natToNat64 2 ** Prim.natToNat64 63 == Prim.natToNat64 9223372036854775808); // highest exponent +assert (Prim.natToNat64 2642245 ** Prim.natToNat64 3 == Prim.natToNat64 18_446_724_184_312_856_125); for (n in range(0, 255)) { for (exp in range(0, 255)) { @@ -58,7 +65,7 @@ for (n in range(0, 255)) { let res = n ** exp; if (res <= 18446744073709551615) { - assert (natToNat64 n ** natToNat64 exp == natToNat64 res) + assert (Prim.natToNat64 n ** Prim.natToNat64 exp == Prim.natToNat64 res) } } } @@ -67,19 +74,19 @@ for (n in range(0, 255)) { // Int* -assert (intToInt8 2 ** intToInt8 6 == intToInt8 64); // highest exponent +assert (Prim.intToInt8 2 ** Prim.intToInt8 6 == Prim.intToInt8 64); // highest exponent for (n in range(0, 127)) { for (exp in range(0, 127)) { if (n <= 1 or exp <= 1 or (n <= 16 and exp <= 9)) { let res = n ** exp; - if (res <= 127) { assert (intToInt8 n ** intToInt8 exp == intToInt8 res) } + if (res <= 127) { assert (Prim.intToInt8 n ** Prim.intToInt8 exp == Prim.intToInt8 res) } } } }; -assert (intToInt8 (-2) ** intToInt8 7 == intToInt8 (-128)); // highest exponent +assert (Prim.intToInt8 (-2) ** Prim.intToInt8 7 == Prim.intToInt8 (-128)); // highest exponent { var n = -128; @@ -88,7 +95,7 @@ while (n < -1) { if (n == -1 or exp <= 1 or (n >= -17 and exp <= 9)) { let res = n ** exp; if (res >= -128 and res <= 127) { - assert (intToInt8 n ** intToInt8 exp == intToInt8 res) + assert (Prim.intToInt8 n ** Prim.intToInt8 exp == Prim.intToInt8 res) } } }; @@ -98,19 +105,19 @@ while (n < -1) { -assert (intToInt16 2 ** intToInt16 14 == intToInt16 16384); // highest exponent +assert (Prim.intToInt16 2 ** Prim.intToInt16 14 == Prim.intToInt16 16384); // highest exponent for (n in range(0, 127)) { for (exp in range(0, 127)) { if (n <= 1 or exp <= 1 or exp <= 14) { let res = n ** exp; - if (res <= 32767) { assert (intToInt16 n ** intToInt16 exp == intToInt16 res) } + if (res <= 32767) { assert (Prim.intToInt16 n ** Prim.intToInt16 exp == Prim.intToInt16 res) } } } }; -assert (intToInt16 (-2) ** intToInt16 15 == intToInt16 (-32768)); // highest exponent +assert (Prim.intToInt16 (-2) ** Prim.intToInt16 15 == Prim.intToInt16 (-32768)); // highest exponent { var n = -128; @@ -119,7 +126,7 @@ while (n < -1) { if (n == -1 or exp <= 1 or exp <= 15) { let res = n ** exp; if (res >= -32768 and res <= 32767) { - assert (intToInt16 n ** intToInt16 exp == intToInt16 res) + assert (Prim.intToInt16 n ** Prim.intToInt16 exp == Prim.intToInt16 res) } } }; @@ -127,28 +134,28 @@ while (n < -1) { } }; -assert (intToInt32 3 ** intToInt32 19 == intToInt32 1_162_261_467); -assert (intToInt32 2 ** intToInt32 30 == intToInt32 1_073_741_824); // highest exponent -assert (intToInt32 (-2) ** intToInt32 31 == intToInt32 (-2_147_483_648)); // highest exponent -assert (intToInt32 (-3) ** intToInt32 19 == intToInt32 (-1_162_261_467)); +assert (Prim.intToInt32 3 ** Prim.intToInt32 19 == Prim.intToInt32 1_162_261_467); +assert (Prim.intToInt32 2 ** Prim.intToInt32 30 == Prim.intToInt32 1_073_741_824); // highest exponent +assert (Prim.intToInt32 (-2) ** Prim.intToInt32 31 == Prim.intToInt32 (-2_147_483_648)); // highest exponent +assert (Prim.intToInt32 (-3) ** Prim.intToInt32 19 == Prim.intToInt32 (-1_162_261_467)); -assert (intToInt32 1 ** intToInt32 19 == intToInt32 1); -assert (intToInt32 1 ** intToInt32 100 == intToInt32 1); -assert (intToInt32 1 ** intToInt32 101 == intToInt32 1); +assert (Prim.intToInt32 1 ** Prim.intToInt32 19 == Prim.intToInt32 1); +assert (Prim.intToInt32 1 ** Prim.intToInt32 100 == Prim.intToInt32 1); +assert (Prim.intToInt32 1 ** Prim.intToInt32 101 == Prim.intToInt32 1); -assert (intToInt32 0 ** intToInt32 19 == intToInt32 0); -assert (intToInt32 0 ** intToInt32 100 == intToInt32 0); -assert (intToInt32 0 ** intToInt32 101 == intToInt32 0); +assert (Prim.intToInt32 0 ** Prim.intToInt32 19 == Prim.intToInt32 0); +assert (Prim.intToInt32 0 ** Prim.intToInt32 100 == Prim.intToInt32 0); +assert (Prim.intToInt32 0 ** Prim.intToInt32 101 == Prim.intToInt32 0); -assert (intToInt32 (-1) ** intToInt32 19 == intToInt32 (-1)); -assert (intToInt32 (-1) ** intToInt32 100 == intToInt32 1); -assert (intToInt32 (-1) ** intToInt32 101 == intToInt32 (-1)); +assert (Prim.intToInt32 (-1) ** Prim.intToInt32 19 == Prim.intToInt32 (-1)); +assert (Prim.intToInt32 (-1) ** Prim.intToInt32 100 == Prim.intToInt32 1); +assert (Prim.intToInt32 (-1) ** Prim.intToInt32 101 == Prim.intToInt32 (-1)); for (n in range(0, 127)) { for (exp in range(0, 127)) { if (n <= 1 or exp <= 1 or exp <= 30) { let res = n ** exp; - if (res <= 2_147_483_647) { assert (intToInt32 n ** intToInt32 exp == intToInt32 res) } + if (res <= 2_147_483_647) { assert (Prim.intToInt32 n ** Prim.intToInt32 exp == Prim.intToInt32 res) } } } }; @@ -160,7 +167,7 @@ while (n < -1) { if (n == -1 or exp <= 1 or exp <= 31) { let res = n ** exp; if (res >= -2_147_483_648 and res <= 2_147_483_647) { - assert (intToInt32 n ** intToInt32 exp == intToInt32 res) + assert (Prim.intToInt32 n ** Prim.intToInt32 exp == Prim.intToInt32 res) } } }; @@ -169,32 +176,32 @@ while (n < -1) { }; -assert (intToInt64 3 ** intToInt64 31 == intToInt64 617_673_396_283_947); // still on fast path +assert (Prim.intToInt64 3 ** Prim.intToInt64 31 == Prim.intToInt64 617_673_396_283_947); // still on fast path -assert (intToInt64 3 ** intToInt64 39 == intToInt64 4_052_555_153_018_976_267); -assert (intToInt64 2 ** intToInt64 62 == intToInt64 4_611_686_018_427_387_904); // highest exponent -assert (intToInt64 (-2) ** intToInt64 63 == intToInt64 (-9_223_372_036_854_775_808)); // highest exponent -assert (intToInt64 (-3) ** intToInt64 39 == intToInt64 (-4_052_555_153_018_976_267)); +assert (Prim.intToInt64 3 ** Prim.intToInt64 39 == Prim.intToInt64 4_052_555_153_018_976_267); +assert (Prim.intToInt64 2 ** Prim.intToInt64 62 == Prim.intToInt64 4_611_686_018_427_387_904); // highest exponent +assert (Prim.intToInt64 (-2) ** Prim.intToInt64 63 == Prim.intToInt64 (-9_223_372_036_854_775_808)); // highest exponent +assert (Prim.intToInt64 (-3) ** Prim.intToInt64 39 == Prim.intToInt64 (-4_052_555_153_018_976_267)); -assert (intToInt64 (-3) ** intToInt64 31 == intToInt64 (-617_673_396_283_947)); // still on fast path +assert (Prim.intToInt64 (-3) ** Prim.intToInt64 31 == Prim.intToInt64 (-617_673_396_283_947)); // still on fast path -assert (intToInt64 1 ** intToInt64 39 == intToInt64 1); -assert (intToInt64 1 ** intToInt64 100 == intToInt64 1); -assert (intToInt64 1 ** intToInt64 101 == intToInt64 1); +assert (Prim.intToInt64 1 ** Prim.intToInt64 39 == Prim.intToInt64 1); +assert (Prim.intToInt64 1 ** Prim.intToInt64 100 == Prim.intToInt64 1); +assert (Prim.intToInt64 1 ** Prim.intToInt64 101 == Prim.intToInt64 1); -assert (intToInt64 0 ** intToInt64 39 == intToInt64 0); -assert (intToInt64 0 ** intToInt64 100 == intToInt64 0); -assert (intToInt64 0 ** intToInt64 101 == intToInt64 0); +assert (Prim.intToInt64 0 ** Prim.intToInt64 39 == Prim.intToInt64 0); +assert (Prim.intToInt64 0 ** Prim.intToInt64 100 == Prim.intToInt64 0); +assert (Prim.intToInt64 0 ** Prim.intToInt64 101 == Prim.intToInt64 0); -assert (intToInt64 (-1) ** intToInt64 39 == intToInt64 (-1)); -assert (intToInt64 (-1) ** intToInt64 100 == intToInt64 1); -assert (intToInt64 (-1) ** intToInt64 101 == intToInt64 (-1)); +assert (Prim.intToInt64 (-1) ** Prim.intToInt64 39 == Prim.intToInt64 (-1)); +assert (Prim.intToInt64 (-1) ** Prim.intToInt64 100 == Prim.intToInt64 1); +assert (Prim.intToInt64 (-1) ** Prim.intToInt64 101 == Prim.intToInt64 (-1)); for (n in range(0, 127)) { for (exp in range(0, 127)) { if (n <= 1 or exp <= 1 or exp <= 63) { let res = n ** exp; - if (res <= 9_223_372_036_854_775_807) { assert (intToInt64 n ** intToInt64 exp == intToInt64 res) } + if (res <= 9_223_372_036_854_775_807) { assert (Prim.intToInt64 n ** Prim.intToInt64 exp == Prim.intToInt64 res) } } } }; @@ -206,7 +213,7 @@ while (n < -1) { if (n == -1 or exp <= 1 or exp <= 63) { let res = n ** exp; if (res >= -9_223_372_036_854_775_808 and res <= 9_223_372_036_854_775_807) { - assert (intToInt64 n ** intToInt64 exp == intToInt64 res) + assert (Prim.intToInt64 n ** Prim.intToInt64 exp == Prim.intToInt64 res) } } }; diff --git a/test/run-drun/nary-async.mo b/test/run-drun/nary-async.mo index 0243a91e766..46ec2736fbd 100644 --- a/test/run-drun/nary-async.mo +++ b/test/run-drun/nary-async.mo @@ -1,3 +1,4 @@ +import Prim "mo:prim"; /* test n-ary async/await */ actor a { @@ -21,7 +22,7 @@ actor a { let t = "0_0"; ignore async { await f0_0(); - debugPrint t; + Prim.debugPrint t; }; }; @@ -29,7 +30,7 @@ actor a { let t = "1_0"; ignore async { await f1_0(1); - debugPrint t; + Prim.debugPrint t; }; }; @@ -37,7 +38,7 @@ actor a { let t = "2_0"; ignore async { await f2_0(1,true); - debugPrint t; + Prim.debugPrint t; }; }; @@ -45,7 +46,7 @@ actor a { let t = "3_0"; ignore async { await f3_0(1,true,"a"); - debugPrint t; + Prim.debugPrint t; }; }; }; @@ -67,7 +68,7 @@ actor a { let t = "0_0"; ignore async { await g0_0(); - debugPrint t; + Prim.debugPrint t; }; }; @@ -76,7 +77,7 @@ actor a { ignore async { let x = await g0_1(); assert(x == 1); - debugPrint t; + Prim.debugPrint t; x; }; }; @@ -87,7 +88,7 @@ actor a { let (x,y) = await g0_2(); assert(x==1); assert(y==true); - debugPrint t; + Prim.debugPrint t; (x,y); }; }; @@ -100,7 +101,7 @@ actor a { assert(x==1); assert(y==true); assert(z=="a"); - debugPrint t; + Prim.debugPrint t; (x,y,z); }; }; diff --git a/test/run-drun/ok/array-out-of-bounds.run-ir.ok b/test/run-drun/ok/array-out-of-bounds.run-ir.ok index 2c3843087e9..afeaf87cf5a 100644 --- a/test/run-drun/ok/array-out-of-bounds.run-ir.ok +++ b/test/run-drun/ok/array-out-of-bounds.run-ir.ok @@ -1,2 +1,2 @@ -array-out-of-bounds.mo:6.12-6.17: execution error, index out of bounds -array-out-of-bounds.mo:10.12-10.17: execution error, index out of bounds +array-out-of-bounds.mo:7.12-7.17: execution error, index out of bounds +array-out-of-bounds.mo:11.12-11.17: execution error, index out of bounds diff --git a/test/run-drun/ok/array-out-of-bounds.run-low.ok b/test/run-drun/ok/array-out-of-bounds.run-low.ok index 2c3843087e9..afeaf87cf5a 100644 --- a/test/run-drun/ok/array-out-of-bounds.run-low.ok +++ b/test/run-drun/ok/array-out-of-bounds.run-low.ok @@ -1,2 +1,2 @@ -array-out-of-bounds.mo:6.12-6.17: execution error, index out of bounds -array-out-of-bounds.mo:10.12-10.17: execution error, index out of bounds +array-out-of-bounds.mo:7.12-7.17: execution error, index out of bounds +array-out-of-bounds.mo:11.12-11.17: execution error, index out of bounds diff --git a/test/run-drun/ok/array-out-of-bounds.run.ok b/test/run-drun/ok/array-out-of-bounds.run.ok index 2c3843087e9..afeaf87cf5a 100644 --- a/test/run-drun/ok/array-out-of-bounds.run.ok +++ b/test/run-drun/ok/array-out-of-bounds.run.ok @@ -1,2 +1,2 @@ -array-out-of-bounds.mo:6.12-6.17: execution error, index out of bounds -array-out-of-bounds.mo:10.12-10.17: execution error, index out of bounds +array-out-of-bounds.mo:7.12-7.17: execution error, index out of bounds +array-out-of-bounds.mo:11.12-11.17: execution error, index out of bounds diff --git a/test/run-drun/ok/async-free-var.comp.ok b/test/run-drun/ok/async-free-var.comp.ok index 6908efc9d22..de73457b5e0 100644 --- a/test/run-drun/ok/async-free-var.comp.ok +++ b/test/run-drun/ok/async-free-var.comp.ok @@ -1,2 +1,2 @@ -async-free-var.mo:5.13-10.6: type error, unsupported async block +async-free-var.mo:6.13-11.6: type error, unsupported async block (This is a limitation of the current version.) diff --git a/test/run-drun/ok/async-loop-while.comp.ok b/test/run-drun/ok/async-loop-while.comp.ok index d977d56c237..404d3221c6a 100644 --- a/test/run-drun/ok/async-loop-while.comp.ok +++ b/test/run-drun/ok/async-loop-while.comp.ok @@ -1,6 +1,6 @@ -async-loop-while.mo:23.22-23.35: type error, unsupported async block +async-loop-while.mo:24.22-24.35: type error, unsupported async block (This is a limitation of the current version.) -async-loop-while.mo:33.15-33.29: type error, unsupported async block +async-loop-while.mo:34.15-34.29: type error, unsupported async block (This is a limitation of the current version.) -async-loop-while.mo:50.15-50.29: type error, unsupported async block +async-loop-while.mo:51.15-51.29: type error, unsupported async block (This is a limitation of the current version.) diff --git a/test/run-drun/ok/async-loop.comp.ok b/test/run-drun/ok/async-loop.comp.ok new file mode 100644 index 00000000000..97383f3d658 --- /dev/null +++ b/test/run-drun/ok/async-loop.comp.ok @@ -0,0 +1,6 @@ +async-loop.mo:27.19-27.33: type error, unsupported async block + (This is a limitation of the current version.) +async-loop.mo:40.15-40.29: type error, unsupported async block + (This is a limitation of the current version.) +async-loop.mo:59.15-59.29: type error, unsupported async block + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/async-loop.tc.ret.ok b/test/run-drun/ok/async-loop.comp.ret.ok similarity index 100% rename from test/run-drun/ok/async-loop.tc.ret.ok rename to test/run-drun/ok/async-loop.comp.ret.ok diff --git a/test/run-drun/ok/show-in-actor.ic-stub-run.ok b/test/run-drun/ok/async-loop.ic-stub-run.ok similarity index 62% rename from test/run-drun/ok/show-in-actor.ic-stub-run.ok rename to test/run-drun/ok/async-loop.ic-stub-run.ok index 68f8eba0f7f..54225bc8555 100644 --- a/test/run-drun/ok/show-in-actor.ic-stub-run.ok +++ b/test/run-drun/ok/async-loop.ic-stub-run.ok @@ -1,7 +1,4 @@ → create ← completed: canister-id = 0x0000000000000400 → install -debug.print: true -debug.print: false -debug.print: 1 ← completed diff --git a/test/run-drun/ok/async-loop.tc.ok b/test/run-drun/ok/async-loop.tc.ok deleted file mode 100644 index c7c2f07b4ce..00000000000 --- a/test/run-drun/ok/async-loop.tc.ok +++ /dev/null @@ -1 +0,0 @@ -async-loop.mo:72.1: syntax error, unexpected token diff --git a/test/run-drun/ok/async-new-obj.comp.ok b/test/run-drun/ok/async-new-obj.comp.ok index 2e4d9158230..674f52c5f1f 100644 --- a/test/run-drun/ok/async-new-obj.comp.ok +++ b/test/run-drun/ok/async-new-obj.comp.ok @@ -1,2 +1,2 @@ -async-new-obj.mo:5.13-14.6: type error, unsupported async block +async-new-obj.mo:6.13-15.6: type error, unsupported async block (This is a limitation of the current version.) diff --git a/test/run-drun/ok/async-obj-mut.comp.ok b/test/run-drun/ok/async-obj-mut.comp.ok index 8f859721af3..d17008eef84 100644 --- a/test/run-drun/ok/async-obj-mut.comp.ok +++ b/test/run-drun/ok/async-obj-mut.comp.ok @@ -1,2 +1,2 @@ -async-obj-mut.mo:4.30-4.41: type error, unsupported async block +async-obj-mut.mo:5.30-5.41: type error, unsupported async block (This is a limitation of the current version.) diff --git a/test/run-drun/ok/async-while.comp.ok b/test/run-drun/ok/async-while.comp.ok index 6f612fb7993..85ae14f649e 100644 --- a/test/run-drun/ok/async-while.comp.ok +++ b/test/run-drun/ok/async-while.comp.ok @@ -1,6 +1,6 @@ -async-while.mo:18.20-18.34: type error, unsupported async block +async-while.mo:19.20-19.34: type error, unsupported async block (This is a limitation of the current version.) -async-while.mo:33.15-33.29: type error, unsupported async block +async-while.mo:34.15-34.29: type error, unsupported async block (This is a limitation of the current version.) -async-while.mo:50.15-50.29: type error, unsupported async block +async-while.mo:51.15-51.29: type error, unsupported async block (This is a limitation of the current version.) diff --git a/test/run-drun/ok/await.comp.ok b/test/run-drun/ok/await.comp.ok index 463f2a585c1..0a1c1d879b9 100644 --- a/test/run-drun/ok/await.comp.ok +++ b/test/run-drun/ok/await.comp.ok @@ -1,2 +1,2 @@ -await.mo:13.13-13.29: type error, unsupported async block +await.mo:14.13-14.29: type error, unsupported async block (This is a limitation of the current version.) diff --git a/test/run-drun/ok/block.comp.ok b/test/run-drun/ok/block.comp.ok index b2d8a0da451..1d1315a298d 100644 --- a/test/run-drun/ok/block.comp.ok +++ b/test/run-drun/ok/block.comp.ok @@ -1,2 +1,2 @@ -block.mo:3.13-7.6: type error, unsupported async block +block.mo:4.13-8.6: type error, unsupported async block (This is a limitation of the current version.) diff --git a/test/run-drun/ok/count-callbacks.comp.ok b/test/run-drun/ok/count-callbacks.comp.ok index 4645af5d7de..e35d7ef6b6d 100644 --- a/test/run-drun/ok/count-callbacks.comp.ok +++ b/test/run-drun/ok/count-callbacks.comp.ok @@ -1,16 +1,16 @@ -count-callbacks.mo:9.18-9.20: type error, shared, async function must be called within an await expression +count-callbacks.mo:10.18-10.20: type error, shared, async function must be called within an await expression (This is a limitation of the current version.) -count-callbacks.mo:11.18-11.20: type error, shared, async function must be called within an await expression +count-callbacks.mo:12.18-12.20: type error, shared, async function must be called within an await expression (This is a limitation of the current version.) -count-callbacks.mo:13.18-13.20: type error, shared, async function must be called within an await expression +count-callbacks.mo:14.18-14.20: type error, shared, async function must be called within an await expression (This is a limitation of the current version.) -count-callbacks.mo:15.18-15.20: type error, shared, async function must be called within an await expression +count-callbacks.mo:16.18-16.20: type error, shared, async function must be called within an await expression (This is a limitation of the current version.) -count-callbacks.mo:18.11-18.13: type error, argument to await must be a call expression +count-callbacks.mo:19.11-19.13: type error, argument to await must be a call expression (This is a limitation of the current version.) -count-callbacks.mo:20.11-20.13: type error, argument to await must be a call expression +count-callbacks.mo:21.11-21.13: type error, argument to await must be a call expression (This is a limitation of the current version.) -count-callbacks.mo:22.11-22.13: type error, argument to await must be a call expression +count-callbacks.mo:23.11-23.13: type error, argument to await must be a call expression (This is a limitation of the current version.) -count-callbacks.mo:24.11-24.13: type error, argument to await must be a call expression +count-callbacks.mo:25.11-25.13: type error, argument to await must be a call expression (This is a limitation of the current version.) diff --git a/test/run-drun/ok/create-then-trap.comp.ok b/test/run-drun/ok/create-then-trap.comp.ok index 50b82c8fb73..b36fc61e2bd 100644 --- a/test/run-drun/ok/create-then-trap.comp.ok +++ b/test/run-drun/ok/create-then-trap.comp.ok @@ -1,2 +1,2 @@ -create-then-trap.mo:3.5-7.6: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program +create-then-trap.mo:4.5-8.6: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program (This is a limitation of the current version.) diff --git a/test/run-drun/ok/create-then-trap.ic-stub-run.ok b/test/run-drun/ok/create-then-trap.ic-stub-run.ok deleted file mode 100644 index 92afdf91f16..00000000000 --- a/test/run-drun/ok/create-then-trap.ic-stub-run.ok +++ /dev/null @@ -1,7 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -← completed -→ update go(0x4449444c0000) -Trap: EvalTrapError :0.1 "canister trapped explicitly: assertion failed at create-then-trap.mo:9.5-9.17" -← rejected (RC_CANISTER_ERROR): canister trapped: EvalTrapError :0.1 "canister trapped explicitly: assertion failed at create-then-trap.mo:9.5-9.17" diff --git a/test/run-drun/ok/create-then-trap.run-ir.ok b/test/run-drun/ok/create-then-trap.run-ir.ok index bbda0311c17..bbcfa935cb5 100644 --- a/test/run-drun/ok/create-then-trap.run-ir.ok +++ b/test/run-drun/ok/create-then-trap.run-ir.ok @@ -1,2 +1,2 @@ -create-then-trap.mo:9.5-9.17: execution error, assertion failure +create-then-trap.mo:10.5-10.17: execution error, assertion failure b.bad() called (should not happen) diff --git a/test/run-drun/ok/create-then-trap.run-low.ok b/test/run-drun/ok/create-then-trap.run-low.ok index bbda0311c17..bbcfa935cb5 100644 --- a/test/run-drun/ok/create-then-trap.run-low.ok +++ b/test/run-drun/ok/create-then-trap.run-low.ok @@ -1,2 +1,2 @@ -create-then-trap.mo:9.5-9.17: execution error, assertion failure +create-then-trap.mo:10.5-10.17: execution error, assertion failure b.bad() called (should not happen) diff --git a/test/run-drun/ok/create-then-trap.run.ok b/test/run-drun/ok/create-then-trap.run.ok index bbda0311c17..bbcfa935cb5 100644 --- a/test/run-drun/ok/create-then-trap.run.ok +++ b/test/run-drun/ok/create-then-trap.run.ok @@ -1,2 +1,2 @@ -create-then-trap.mo:9.5-9.17: execution error, assertion failure +create-then-trap.mo:10.5-10.17: execution error, assertion failure b.bad() called (should not happen) diff --git a/test/run-drun/ok/data-params.tc.ok b/test/run-drun/ok/data-params.tc.ok index 8121106181c..8669117887e 100644 --- a/test/run-drun/ok/data-params.tc.ok +++ b/test/run-drun/ok/data-params.tc.ok @@ -1,4 +1,4 @@ -data-params.mo:49.30-49.40: warning, this pattern consuming type +data-params.mo:50.30-50.40: warning, this pattern consuming type ?Text does not cover value null diff --git a/test/run-drun/ok/flatten-awaitables.tc.ok b/test/run-drun/ok/flatten-awaitables.tc.ok index 96cd1962c42..36432a4d370 100644 --- a/test/run-drun/ok/flatten-awaitables.tc.ok +++ b/test/run-drun/ok/flatten-awaitables.tc.ok @@ -1,118 +1,118 @@ -flatten-awaitables.mo:39.9-39.10: warning, this pattern consuming type +flatten-awaitables.mo:40.9-40.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.mo:41.9-41.17: warning, this pattern consuming type +flatten-awaitables.mo:42.9-42.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.mo:43.9-43.25: warning, this pattern consuming type +flatten-awaitables.mo:44.9-44.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.mo:48.9-48.10: warning, this pattern consuming type +flatten-awaitables.mo:49.9-49.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.mo:50.9-50.17: warning, this pattern consuming type +flatten-awaitables.mo:51.9-51.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.mo:52.9-52.25: warning, this pattern consuming type +flatten-awaitables.mo:53.9-53.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.mo:62.9-62.10: warning, this pattern consuming type +flatten-awaitables.mo:63.9-63.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.mo:64.9-64.17: warning, this pattern consuming type +flatten-awaitables.mo:65.9-65.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.mo:66.9-66.25: warning, this pattern consuming type +flatten-awaitables.mo:67.9-67.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.mo:71.9-71.10: warning, this pattern consuming type +flatten-awaitables.mo:72.9-72.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.mo:73.9-73.17: warning, this pattern consuming type +flatten-awaitables.mo:74.9-74.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.mo:75.9-75.25: warning, this pattern consuming type +flatten-awaitables.mo:76.9-76.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.mo:81.9-81.10: warning, this pattern consuming type +flatten-awaitables.mo:82.9-82.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.mo:83.9-83.17: warning, this pattern consuming type +flatten-awaitables.mo:84.9-84.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.mo:85.9-85.25: warning, this pattern consuming type +flatten-awaitables.mo:86.9-86.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.mo:90.9-90.10: warning, this pattern consuming type +flatten-awaitables.mo:91.9-91.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.mo:92.9-92.17: warning, this pattern consuming type +flatten-awaitables.mo:93.9-93.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.mo:94.9-94.25: warning, this pattern consuming type +flatten-awaitables.mo:95.9-95.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.mo:99.9-99.10: warning, this pattern consuming type +flatten-awaitables.mo:100.9-100.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.mo:101.9-101.17: warning, this pattern consuming type +flatten-awaitables.mo:102.9-102.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.mo:103.9-103.25: warning, this pattern consuming type +flatten-awaitables.mo:104.9-104.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or (3, true, _) or (0 or 1 or _, _, _) -flatten-awaitables.mo:108.9-108.10: warning, this pattern consuming type +flatten-awaitables.mo:109.9-109.10: warning, this pattern consuming type Int does not cover value 0 or -1 or _ -flatten-awaitables.mo:110.9-110.17: warning, this pattern consuming type +flatten-awaitables.mo:111.9-111.17: warning, this pattern consuming type (Int, Bool) does not cover value (2, false) or (0 or 1 or _, _) -flatten-awaitables.mo:112.9-112.25: warning, this pattern consuming type +flatten-awaitables.mo:113.9-113.25: warning, this pattern consuming type (Int, Bool, Text) does not cover value (3, false, _) or diff --git a/test/run-drun/ok/for-await.comp.ok b/test/run-drun/ok/for-await.comp.ok index 96103de3721..469481f5f15 100644 --- a/test/run-drun/ok/for-await.comp.ok +++ b/test/run-drun/ok/for-await.comp.ok @@ -1,2 +1,2 @@ -for-await.mo:9.15-9.29: type error, unsupported async block +for-await.mo:17.15-17.29: type error, unsupported async block (This is a limitation of the current version.) diff --git a/test/run-drun/ok/indirect-counter.ic-stub-run.ok b/test/run-drun/ok/indirect-counter.ic-stub-run.ok deleted file mode 100644 index b8bc9426a98..00000000000 --- a/test/run-drun/ok/indirect-counter.ic-stub-run.ok +++ /dev/null @@ -1,8 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -debug.print: 2 -debug.print: 3 -debug.print: 4 -debug.print: 4 -← completed diff --git a/test/run-drun/ok/indirect-counter.run-ir.ok b/test/run-drun/ok/indirect-counter.run-ir.ok deleted file mode 100644 index 95c45d6da51..00000000000 --- a/test/run-drun/ok/indirect-counter.run-ir.ok +++ /dev/null @@ -1,4 +0,0 @@ -2 -3 -4 -4 diff --git a/test/run-drun/ok/indirect-counter.run-low.ok b/test/run-drun/ok/indirect-counter.run-low.ok deleted file mode 100644 index 95c45d6da51..00000000000 --- a/test/run-drun/ok/indirect-counter.run-low.ok +++ /dev/null @@ -1,4 +0,0 @@ -2 -3 -4 -4 diff --git a/test/run-drun/ok/indirect-counter.run.ok b/test/run-drun/ok/indirect-counter.run.ok deleted file mode 100644 index 95c45d6da51..00000000000 --- a/test/run-drun/ok/indirect-counter.run.ok +++ /dev/null @@ -1,4 +0,0 @@ -2 -3 -4 -4 diff --git a/test/run-drun/ok/interleave.comp.ok b/test/run-drun/ok/interleave.comp.ok index de4aa60175f..1a3e66d735f 100644 --- a/test/run-drun/ok/interleave.comp.ok +++ b/test/run-drun/ok/interleave.comp.ok @@ -1,2 +1,2 @@ -interleave.mo:13.13-21.6: type error, unsupported async block +interleave.mo:14.13-22.6: type error, unsupported async block (This is a limitation of the current version.) diff --git a/test/run-drun/ok/issue-894.comp.ok b/test/run-drun/ok/issue-894.comp.ok index 10ef901c51d..bfb4f571c53 100644 --- a/test/run-drun/ok/issue-894.comp.ok +++ b/test/run-drun/ok/issue-894.comp.ok @@ -1,6 +1,6 @@ -issue-894.mo:15.20-15.27: type error, unsupported async block +issue-894.mo:16.20-16.27: type error, unsupported async block (This is a limitation of the current version.) -issue-894.mo:22.15-22.22: type error, unsupported async block +issue-894.mo:23.15-23.22: type error, unsupported async block (This is a limitation of the current version.) -issue-894.mo:29.15-29.22: type error, unsupported async block +issue-894.mo:30.15-30.22: type error, unsupported async block (This is a limitation of the current version.) diff --git a/test/run-drun/ok/nary-async.comp.ok b/test/run-drun/ok/nary-async.comp.ok index df59247982e..03af1589cf7 100644 --- a/test/run-drun/ok/nary-async.comp.ok +++ b/test/run-drun/ok/nary-async.comp.ok @@ -1,16 +1,16 @@ -nary-async.mo:22.14-25.8: type error, unsupported async block +nary-async.mo:23.14-26.8: type error, unsupported async block (This is a limitation of the current version.) -nary-async.mo:30.14-33.8: type error, unsupported async block +nary-async.mo:31.14-34.8: type error, unsupported async block (This is a limitation of the current version.) -nary-async.mo:38.14-41.8: type error, unsupported async block +nary-async.mo:39.14-42.8: type error, unsupported async block (This is a limitation of the current version.) -nary-async.mo:46.14-49.8: type error, unsupported async block +nary-async.mo:47.14-50.8: type error, unsupported async block (This is a limitation of the current version.) -nary-async.mo:68.14-71.8: type error, unsupported async block +nary-async.mo:69.14-72.8: type error, unsupported async block (This is a limitation of the current version.) -nary-async.mo:76.14-81.8: type error, unsupported async block +nary-async.mo:77.14-82.8: type error, unsupported async block (This is a limitation of the current version.) -nary-async.mo:86.14-92.8: type error, unsupported async block +nary-async.mo:87.14-93.8: type error, unsupported async block (This is a limitation of the current version.) -nary-async.mo:98.14-105.8: type error, unsupported async block +nary-async.mo:99.14-106.8: type error, unsupported async block (This is a limitation of the current version.) diff --git a/test/run-drun/ok/overflow.comp.ok b/test/run-drun/ok/overflow.comp.ok index 03d8fa71e12..ae19590ce91 100644 --- a/test/run-drun/ok/overflow.comp.ok +++ b/test/run-drun/ok/overflow.comp.ok @@ -1,12 +1,12 @@ -overflow.mo:7.12-10.6: type error, unsupported async block +overflow.mo:8.12-11.6: type error, unsupported async block (This is a limitation of the current version.) -overflow.mo:11.12-14.6: type error, unsupported async block +overflow.mo:12.12-15.6: type error, unsupported async block (This is a limitation of the current version.) -overflow.mo:15.12-18.6: type error, unsupported async block +overflow.mo:16.12-19.6: type error, unsupported async block (This is a limitation of the current version.) -overflow.mo:19.12-22.6: type error, unsupported async block +overflow.mo:20.12-23.6: type error, unsupported async block (This is a limitation of the current version.) -overflow.mo:23.12-26.6: type error, unsupported async block +overflow.mo:24.12-27.6: type error, unsupported async block (This is a limitation of the current version.) -overflow.mo:27.12-30.6: type error, unsupported async block +overflow.mo:28.12-31.6: type error, unsupported async block (This is a limitation of the current version.) diff --git a/test/run-drun/ok/overflow.run-ir.ok b/test/run-drun/ok/overflow.run-ir.ok index 87b51c66e67..1632edd500f 100644 --- a/test/run-drun/ok/overflow.run-ir.ok +++ b/test/run-drun/ok/overflow.run-ir.ok @@ -1,6 +1,6 @@ This is reachable. This is reachable. -overflow.mo:16.18-16.21: execution error, arithmetic overflow +overflow.mo:17.18-17.21: execution error, arithmetic overflow This is reachable. This is reachable. This is reachable. diff --git a/test/run-drun/ok/overflow.run-low.ok b/test/run-drun/ok/overflow.run-low.ok index 87b51c66e67..1632edd500f 100644 --- a/test/run-drun/ok/overflow.run-low.ok +++ b/test/run-drun/ok/overflow.run-low.ok @@ -1,6 +1,6 @@ This is reachable. This is reachable. -overflow.mo:16.18-16.21: execution error, arithmetic overflow +overflow.mo:17.18-17.21: execution error, arithmetic overflow This is reachable. This is reachable. This is reachable. diff --git a/test/run-drun/ok/overflow.run.ok b/test/run-drun/ok/overflow.run.ok index 87b51c66e67..1632edd500f 100644 --- a/test/run-drun/ok/overflow.run.ok +++ b/test/run-drun/ok/overflow.run.ok @@ -1,6 +1,6 @@ This is reachable. This is reachable. -overflow.mo:16.18-16.21: execution error, arithmetic overflow +overflow.mo:17.18-17.21: execution error, arithmetic overflow This is reachable. This is reachable. This is reachable. diff --git a/test/run-drun/ok/pass-references.comp.ok b/test/run-drun/ok/pass-references.comp.ok index be0c963c22b..796990f25f6 100644 --- a/test/run-drun/ok/pass-references.comp.ok +++ b/test/run-drun/ok/pass-references.comp.ok @@ -1,2 +1,2 @@ -pass-references.mo:13.5-15.6: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program +pass-references.mo:14.5-16.6: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program (This is a limitation of the current version.) diff --git a/test/run-drun/ok/pass-references.ic-stub-run.ok b/test/run-drun/ok/pass-references.ic-stub-run.ok index 9772ec1f610..446392dd5b5 100644 --- a/test/run-drun/ok/pass-references.ic-stub-run.ok +++ b/test/run-drun/ok/pass-references.ic-stub-run.ok @@ -5,5 +5,6 @@ → update go(0x4449444c0000) debug.print: a debug.print: b +debug.print: a debug.print: b ← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/pass-references.run-ir.ok b/test/run-drun/ok/pass-references.run-ir.ok index ee12596769e..da40f8bcedb 100644 --- a/test/run-drun/ok/pass-references.run-ir.ok +++ b/test/run-drun/ok/pass-references.run-ir.ok @@ -1,3 +1,4 @@ a b +a b diff --git a/test/run-drun/ok/pass-references.run-low.ok b/test/run-drun/ok/pass-references.run-low.ok index ee12596769e..da40f8bcedb 100644 --- a/test/run-drun/ok/pass-references.run-low.ok +++ b/test/run-drun/ok/pass-references.run-low.ok @@ -1,3 +1,4 @@ a b +a b diff --git a/test/run-drun/ok/pass-references.run.ok b/test/run-drun/ok/pass-references.run.ok index ee12596769e..da40f8bcedb 100644 --- a/test/run-drun/ok/pass-references.run.ok +++ b/test/run-drun/ok/pass-references.run.ok @@ -1,3 +1,4 @@ a b +a b diff --git a/test/run-drun/ok/query2.run-ir.ok b/test/run-drun/ok/query2.run-ir.ok index 2fe69e6672e..8bf44627e97 100644 --- a/test/run-drun/ok/query2.run-ir.ok +++ b/test/run-drun/ok/query2.run-ir.ok @@ -8,5 +8,5 @@ In read: In read: 6 The following fails in the intepreter, for lack of query semantics -query2.mo:34.4-34.18: execution error, assertion failure +query2.mo:35.4-35.18: execution error, assertion failure 6 diff --git a/test/run-drun/ok/query2.run-low.ok b/test/run-drun/ok/query2.run-low.ok index 2fe69e6672e..8bf44627e97 100644 --- a/test/run-drun/ok/query2.run-low.ok +++ b/test/run-drun/ok/query2.run-low.ok @@ -8,5 +8,5 @@ In read: In read: 6 The following fails in the intepreter, for lack of query semantics -query2.mo:34.4-34.18: execution error, assertion failure +query2.mo:35.4-35.18: execution error, assertion failure 6 diff --git a/test/run-drun/ok/query2.run.ok b/test/run-drun/ok/query2.run.ok index 2fe69e6672e..8bf44627e97 100644 --- a/test/run-drun/ok/query2.run.ok +++ b/test/run-drun/ok/query2.run.ok @@ -8,5 +8,5 @@ In read: In read: 6 The following fails in the intepreter, for lack of query semantics -query2.mo:34.4-34.18: execution error, assertion failure +query2.mo:35.4-35.18: execution error, assertion failure 6 diff --git a/test/run-drun/ok/show-in-actor.comp.ok b/test/run-drun/ok/show-in-actor.comp.ok deleted file mode 100644 index 2657536c521..00000000000 --- a/test/run-drun/ok/show-in-actor.comp.ok +++ /dev/null @@ -1,2 +0,0 @@ -show-in-actor.mo:2.1-5.2: type error, an actor must be the last declaration in a program - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/show-in-actor.comp.ret.ok b/test/run-drun/ok/show-in-actor.comp.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/show-in-actor.comp.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/test_oneway.tc.ok b/test/run-drun/ok/test_oneway.tc.ok index 447e9090f16..60dfe4908cf 100644 --- a/test/run-drun/ok/test_oneway.tc.ok +++ b/test/run-drun/ok/test_oneway.tc.ok @@ -1 +1 @@ -oneway.mo:67.1-67.7: type error, non-static expression in library or module +oneway.mo:68.1-68.7: type error, non-static expression in library or module diff --git a/test/run-drun/ok/throw.comp.ok b/test/run-drun/ok/throw.comp.ok index 22422ae6054..601f679ac60 100644 --- a/test/run-drun/ok/throw.comp.ok +++ b/test/run-drun/ok/throw.comp.ok @@ -1,4 +1,4 @@ -throw.mo:7.14-10.8: type error, unsupported async block +throw.mo:8.14-11.8: type error, unsupported async block (This is a limitation of the current version.) -throw.mo:22.13-41.8: type error, unsupported async block +throw.mo:23.13-42.8: type error, unsupported async block (This is a limitation of the current version.) diff --git a/test/run-drun/oneway-throw.mo b/test/run-drun/oneway-throw.mo index 3a6eadd4329..12362206a63 100644 --- a/test/run-drun/oneway-throw.mo +++ b/test/run-drun/oneway-throw.mo @@ -1,19 +1,20 @@ +import Prim "mo:prim"; actor a { var committed = false; public func throws() : () = ignore async { - debugPrint "throws()"; + Prim.debugPrint "throws()"; committed := true; - throw (error("ignored")); - debugPrint "unreachable"; + throw (Prim.error("ignored")); + Prim.debugPrint "unreachable"; }; public func ping() : async () { - debugPrint "ping()"; + Prim.debugPrint "ping()"; }; public func go() = ignore async { - debugPrint "go1"; + Prim.debugPrint "go1"; throws(); await ping(); // in-order delivery guarantees that throw ran - debugPrint "go2"; + Prim.debugPrint "go2"; assert(committed); }; }; diff --git a/test/run-drun/oneway.mo b/test/run-drun/oneway.mo index 3aa615b9962..899975e285f 100644 --- a/test/run-drun/oneway.mo +++ b/test/run-drun/oneway.mo @@ -1,14 +1,15 @@ +import Prim "mo:prim"; actor a { // test that oneways can locally try/throw public func oneway() : () { ignore ( async { - debugPrint "1"; + Prim.debugPrint "1"; try { - throw (error("Error")); - debugPrint "unreachable"; + throw (Prim.error("Error")); + Prim.debugPrint "unreachable"; } - catch e { debugPrint "2"}; + catch e { Prim.debugPrint "2"}; } ) }; @@ -18,12 +19,12 @@ actor a { public func onewayAlt() : () = ignore ( async { - debugPrint "3"; + Prim.debugPrint "3"; try { - throw (error("Error")); - debugPrint "unreachable"; + throw (Prim.error("Error")); + Prim.debugPrint "unreachable"; } - catch e { debugPrint "4"}; + catch e { Prim.debugPrint "4"}; } ); @@ -32,9 +33,9 @@ actor a { public func discard() : () { ignore ( async { - debugPrint "5"; - throw (error("ignored")); - debugPrint "unreachable"; + Prim.debugPrint "5"; + throw (Prim.error("ignored")); + Prim.debugPrint "unreachable"; } ) }; @@ -44,24 +45,24 @@ actor a { public func discardAlt() : () = ignore ( async { - debugPrint "6"; - throw (error("ignored")); - debugPrint "unreachable"; + Prim.debugPrint "6"; + throw (Prim.error("ignored")); + Prim.debugPrint "unreachable"; } ); // TODO test await and calls to shared functions public func go() = ignore async { - debugPrint("A"); + Prim.debugPrint("A"); oneway(); - debugPrint("B"); + Prim.debugPrint("B"); onewayAlt(); - debugPrint("C"); + Prim.debugPrint("C"); discard(); - debugPrint("D"); + Prim.debugPrint("D"); discardAlt(); - debugPrint("E"); + Prim.debugPrint("E"); }; }; a.go(); //OR-CALL ingress go 0x4449444C0000 diff --git a/test/run-drun/oom.mo b/test/run-drun/oom.mo index 88e8197fc7d..e2b829c6276 100644 --- a/test/run-drun/oom.mo +++ b/test/run-drun/oom.mo @@ -1,6 +1,7 @@ +import Prim "mo:prim"; actor a { public func go() { - ignore(Array_init<()>(1200*1024/4, ())); + ignore(Prim.Array_init<()>(1200*1024/4, ())); }; }; diff --git a/test/run-drun/overflow.mo b/test/run-drun/overflow.mo index c5c40a9adfd..b9b995e0508 100644 --- a/test/run-drun/overflow.mo +++ b/test/run-drun/overflow.mo @@ -1,3 +1,4 @@ +import Prim "mo:prim"; // We have these tests in run-drun because we want to check that certain // traps are happening, and a good way to test this is if a message gets // aborted. @@ -6,27 +7,27 @@ actor a { public func go() { ignore(async { ignore ((0-1):Int); - debugPrint("This is reachable."); + Prim.debugPrint("This is reachable."); }); ignore(async { ignore ((1-1):Nat); - debugPrint("This is reachable."); + Prim.debugPrint("This is reachable."); }); ignore(async { ignore ((0-1):Nat); - debugPrint("This should be unreachable."); + Prim.debugPrint("This should be unreachable."); }); ignore(async { ignore ((18446744073709551615 + 0):Nat); - debugPrint("This is reachable."); + Prim.debugPrint("This is reachable."); }); ignore(async { ignore ((9223372036854775806 + 9223372036854775806 + 1):Nat); - debugPrint("This is reachable."); + Prim.debugPrint("This is reachable."); }); ignore(async { ignore ((9223372036854775806 + 9223372036854775806 + 2):Nat); - debugPrint("This is reachable."); + Prim.debugPrint("This is reachable."); }); } }; diff --git a/test/run-drun/pass-references.mo b/test/run-drun/pass-references.mo index 316e268fcac..318c55b22c9 100644 --- a/test/run-drun/pass-references.mo +++ b/test/run-drun/pass-references.mo @@ -1,20 +1,22 @@ +import Prim "mo:prim"; actor a { - public func foo() { debugPrint("a"); }; + public func foo() : async Text = async "a"; - public func pass_func(f : shared () -> ()) { - f(); + public func pass_func(f : shared () -> async Text) = ignore async { + Prim.debugPrint (await f()); }; - public func pass_actor(a : actor { foo : shared () -> () }) { - a.foo(); + public func pass_actor(a : actor { foo : shared () -> async Text }) = ignore async { + Prim.debugPrint (await a.foo()); }; public func go() { actor b { - public func foo() { debugPrint("b"); }; + public func foo() : async Text = async "b"; }; pass_func(foo); pass_func(b.foo); + pass_actor(a); pass_actor(b); }; }; diff --git a/test/run-drun/print-from-init.mo b/test/run-drun/print-from-init.mo index e65298d1a21..e7a50fae9c1 100644 --- a/test/run-drun/print-from-init.mo +++ b/test/run-drun/print-from-init.mo @@ -1,3 +1,4 @@ +import Prim "mo:prim"; actor { - debugPrint("Debug out"); + Prim.debugPrint("Debug out"); } diff --git a/test/run-drun/query.mo b/test/run-drun/query.mo index e6639a1ddce..4ab3fb1b912 100644 --- a/test/run-drun/query.mo +++ b/test/run-drun/query.mo @@ -1,11 +1,12 @@ +import Prim "mo:prim"; actor { var c = 1; public func inc() { c += 1; - debugPrintNat c + Prim.debugPrintNat c }; public func printCounter () { - debugPrintNat c + Prim.debugPrintNat c }; public func get() : async Nat { return c @@ -13,7 +14,7 @@ actor { public query func read() : async Nat { let tmp = c; c += 1; - debugPrintNat c; + Prim.debugPrintNat c; return tmp; }; diff --git a/test/run-drun/query2.mo b/test/run-drun/query2.mo index b0eead49084..02f6e4d8642 100644 --- a/test/run-drun/query2.mo +++ b/test/run-drun/query2.mo @@ -1,11 +1,12 @@ +import Prim "mo:prim"; actor counter = { var c = 1; public func inc() { c += 1; - debugPrintNat c; + Prim.debugPrintNat c; }; public func printCounter () { - debugPrintNat c; + Prim.debugPrintNat c; }; public func get() : async Nat { return c @@ -13,8 +14,8 @@ actor counter = { public query func read() : async Nat { let tmp = c; c += 1; - debugPrint "In read:"; - debugPrintNat c; + Prim.debugPrint "In read:"; + Prim.debugPrintNat c; return tmp; }; @@ -30,7 +31,7 @@ actor counter = { assert c2 == 4; let c3 = await counter.read(); counter.printCounter(); - debugPrint("The following fails in the intepreter, for lack of query semantics"); + Prim.debugPrint("The following fails in the intepreter, for lack of query semantics"); assert c3 == 4; }; }; diff --git a/test/run-drun/reference-params.mo b/test/run-drun/reference-params.mo index df186f35eb6..1da2e954a2b 100644 --- a/test/run-drun/reference-params.mo +++ b/test/run-drun/reference-params.mo @@ -1,7 +1,8 @@ +import Prim "mo:prim"; actor { let a = actor { public func hello() { - debugPrint("Hello World!"); + Prim.debugPrint("Hello World!"); }; }; a.hello(); @@ -28,7 +29,7 @@ actor { f(); }; public func hello() { - debugPrint("Hello Universe!"); + Prim.debugPrint("Hello Universe!"); }; public func go() { say_hi(hello); @@ -39,7 +40,7 @@ actor { // test passing a self to an actor let e = actor this { public func hello() { - debugPrint("Hello Galaxy!"); + Prim.debugPrint("Hello Galaxy!"); }; public func send_to(f : shared (actor { hello : () -> () }) -> ()) { f(this); @@ -48,3 +49,4 @@ actor { e.send_to(b.say_hi); } //SKIP comp +//SKIP comp-stub diff --git a/test/run-drun/reject.mo b/test/run-drun/reject.mo index 3b353eddae7..ef42fba6ce7 100644 --- a/test/run-drun/reject.mo +++ b/test/run-drun/reject.mo @@ -1,25 +1,26 @@ +import Prim "mo:prim"; actor { public func reject1() : async () { - debugPrint "1"; - throw (error("Error")); - debugPrint "wrong"; + Prim.debugPrint "1"; + throw (Prim.error("Error")); + Prim.debugPrint "wrong"; }; public func reject2() : async () { - debugPrint "1"; - try { throw (error("Error")) } + Prim.debugPrint "1"; + try { throw (Prim.error("Error")) } catch e {}; - debugPrint "ok"; + Prim.debugPrint "ok"; }; public func reject3() : async () { - debugPrint "1"; - try { throw (error("Error")) } + Prim.debugPrint "1"; + try { throw (Prim.error("Error")) } catch e { - debugPrint "ok"; + Prim.debugPrint "ok"; throw e; }; - debugPrint "wrong"; + Prim.debugPrint "wrong"; }; } @@ -31,3 +32,4 @@ actor { //SKIP run //SKIP run-ir //SKIP run-low + diff --git a/test/run-drun/rts-stats.mo b/test/run-drun/rts-stats.mo index a8a27f0c150..e2f7479d380 100644 --- a/test/run-drun/rts-stats.mo +++ b/test/run-drun/rts-stats.mo @@ -1,15 +1,16 @@ -let s0 = rts_heap_size(); -let a0 = rts_total_allocation(); -ignore(Array_init<()>(2500, ())); -let s1 = rts_heap_size(); -let a1 = rts_total_allocation(); +import Prim "mo:prim"; +let s0 = Prim.rts_heap_size(); +let a0 = Prim.rts_total_allocation(); +ignore(Prim.Array_init<()>(2500, ())); +let s1 = Prim.rts_heap_size(); +let a1 = Prim.rts_total_allocation(); // the following are too likey to change to be included in the test output -// debugPrint("Size and allocation before: " # debug_show (s0, a0)); -// debugPrint("Size and allocation after: " # debug_show (s1, a1)); +// Prim.debugPrint("Size and allocation before: " # debug_show (s0, a0)); +// Prim.debugPrint("Size and allocation after: " # debug_show (s1, a1)); // this should be rather stable unless the array representation changes -debugPrint("Size and allocation delta: " # debug_show (s1-s0, a1-a0)); +Prim.debugPrint("Size and allocation delta: " # debug_show (s1-s0, a1-a0)); assert (s1-s0 == 10008); assert (a1-a0 == 10008); diff --git a/test/run-drun/selftail.mo b/test/run-drun/selftail.mo index 040ed7fa744..ea7b08a33d0 100644 --- a/test/run-drun/selftail.mo +++ b/test/run-drun/selftail.mo @@ -1,3 +1,4 @@ +import Prim "mo:prim"; // a single function that can be evaluated recursively or tail-recursively func f (tailCall:Bool, n:Int, acc:Int) : Int { if (n<=0) @@ -11,12 +12,12 @@ func f (tailCall:Bool, n:Int, acc:Int) : Int { // check we get same results for small n assert (f(false, 100, 0) == f(true, 100, 0)); -debugPrint "ok1"; +Prim.debugPrint "ok1"; // check tail recursion works for large n assert(10000 == f (true, 10000, 0)); -debugPrint "ok2"; +Prim.debugPrint "ok2"; // check recursion overflows for large n (overflows on drun only) assert(10000 == f (false, 10000, 0)); -debugPrint "ok3 (unreachable on drun)"; +Prim.debugPrint "ok3 (unreachable on drun)"; diff --git a/test/run-drun/show-in-actor.mo b/test/run-drun/show-in-actor.mo index 9af5a51fbd6..feaca848341 100644 --- a/test/run-drun/show-in-actor.mo +++ b/test/run-drun/show-in-actor.mo @@ -1,6 +1,11 @@ -debugPrint (debug_show true); +import Prim "mo:prim"; +Prim.debugPrint (debug_show true); let _ = actor { - debugPrint (debug_show false); - debugPrint (debug_show 1); + Prim.debugPrint (debug_show false); + Prim.debugPrint (debug_show 1); }; () + +// non-closed actors not allowed +//SKIP comp +//SKIP comp-stub diff --git a/test/run-drun/show.mo b/test/run-drun/show.mo index 88b0131995e..878e789c25d 100644 --- a/test/run-drun/show.mo +++ b/test/run-drun/show.mo @@ -1,36 +1,37 @@ -debugPrint(debug_show (true)); -debugPrint(debug_show (false)); -debugPrint(debug_show (-42000000000000)); -debugPrint(debug_show (-42000000)); -debugPrint(debug_show (-42000)); -debugPrint(debug_show (-42)); -debugPrint(debug_show (-0)); -debugPrint(debug_show (+0)); -debugPrint(debug_show (+42)); -debugPrint(debug_show (+42000)); -debugPrint(debug_show (+42000000)); -debugPrint(debug_show (+420000000000000)); -debugPrint(debug_show (0)); -debugPrint(debug_show (42)); -debugPrint(debug_show (42000)); -debugPrint(debug_show (42000000)); -debugPrint(debug_show (420000000000000)); -debugPrint(debug_show (42,-42,())); -debugPrint(debug_show ("Foobar", null, null, ?23)); -debugPrint(debug_show ([])); -debugPrint(debug_show ([1,2,3])); -debugPrint(debug_show ([var])); -debugPrint(debug_show ([var 1,2,3])); +import Prim "mo:prim"; +Prim.debugPrint(debug_show (true)); +Prim.debugPrint(debug_show (false)); +Prim.debugPrint(debug_show (-42000000000000)); +Prim.debugPrint(debug_show (-42000000)); +Prim.debugPrint(debug_show (-42000)); +Prim.debugPrint(debug_show (-42)); +Prim.debugPrint(debug_show (-0)); +Prim.debugPrint(debug_show (+0)); +Prim.debugPrint(debug_show (+42)); +Prim.debugPrint(debug_show (+42000)); +Prim.debugPrint(debug_show (+42000000)); +Prim.debugPrint(debug_show (+420000000000000)); +Prim.debugPrint(debug_show (0)); +Prim.debugPrint(debug_show (42)); +Prim.debugPrint(debug_show (42000)); +Prim.debugPrint(debug_show (42000000)); +Prim.debugPrint(debug_show (420000000000000)); +Prim.debugPrint(debug_show (42,-42,())); +Prim.debugPrint(debug_show ("Foobar", null, null, ?23)); +Prim.debugPrint(debug_show ([])); +Prim.debugPrint(debug_show ([1,2,3])); +Prim.debugPrint(debug_show ([var])); +Prim.debugPrint(debug_show ([var 1,2,3])); class Foo() { public let foo : Int = 42; public var bar : Bool = true ; let hidden = [1,2] }; -debugPrint(debug_show (Foo())); -debugPrint(debug_show (#foo ())); -debugPrint(debug_show (#bar (1, 2))); -debugPrint(debug_show (#bar {})); -debugPrint(debug_show (#bar ([]))); -debugPrint(debug_show (#bar 42)); -debugPrint(debug_show (#bar (-42))); -debugPrint(debug_show (#foo 42 : {#foo : Int; #bar : Text})); -debugPrint(debug_show (42 : Word16)); -debugPrint(debug_show (42 : Nat8)); -debugPrint(debug_show (42 : Int32)); -debugPrint(debug_show (intToInt64 (-42))); +Prim.debugPrint(debug_show (Foo())); +Prim.debugPrint(debug_show (#foo ())); +Prim.debugPrint(debug_show (#bar (1, 2))); +Prim.debugPrint(debug_show (#bar {})); +Prim.debugPrint(debug_show (#bar ([]))); +Prim.debugPrint(debug_show (#bar 42)); +Prim.debugPrint(debug_show (#bar (-42))); +Prim.debugPrint(debug_show (#foo 42 : {#foo : Int; #bar : Text})); +Prim.debugPrint(debug_show (42 : Word16)); +Prim.debugPrint(debug_show (42 : Nat8)); +Prim.debugPrint(debug_show (42 : Int32)); +Prim.debugPrint(debug_show (Prim.intToInt64 (-42))); diff --git a/test/run-drun/tailpositions.mo b/test/run-drun/tailpositions.mo index a1040719cfb..bc1f6275e99 100644 --- a/test/run-drun/tailpositions.mo +++ b/test/run-drun/tailpositions.mo @@ -1,3 +1,4 @@ +import Prim "mo:prim"; /* test tail-position calculation; error would stack overflow in drun*/ //SKIP comp-stub @@ -7,7 +8,7 @@ let bound:Int = 100000; { func Loop(n:Int){ if (n >= bound) { - debugPrint "done 1"; + Prim.debugPrint "done 1"; return; }; Loop(n+1); @@ -18,7 +19,7 @@ let bound:Int = 100000; { func Loop(n:Int){ if (n >= bound) { - debugPrint "done 2"; + Prim.debugPrint "done 2"; return; }; if (true) @@ -33,7 +34,7 @@ let bound:Int = 100000; { func Loop(n:Int){ if (n >= bound) { - debugPrint "done 3"; + Prim.debugPrint "done 3"; return; }; switch (n % 2) { @@ -49,7 +50,7 @@ let bound:Int = 100000; { func Loop(n:Int){ if (n >= bound) { - debugPrint "done 4"; + Prim.debugPrint "done 4"; return; }; { let m = n; @@ -63,7 +64,7 @@ let bound:Int = 100000; { func Loop(n:Int){ if (n >= bound) { - debugPrint "done 5"; + Prim.debugPrint "done 5"; return; }; let _ = (return Loop(n+1)) + 1; @@ -75,7 +76,7 @@ let bound:Int = 100000; { func Loop(n:Int):Bool{ if (n >= bound) { - debugPrint "done 6"; + Prim.debugPrint "done 6"; return true; }; true and Loop(n+1); @@ -86,7 +87,7 @@ let bound:Int = 100000; { func Loop(n:Int):Bool { if (n >= bound) { - debugPrint "done 7"; + Prim.debugPrint "done 7"; return true; }; false or Loop(n+1); diff --git a/test/run-drun/text-iter.mo b/test/run-drun/text-iter.mo index e2ce9e9ce45..c728247c472 100644 --- a/test/run-drun/text-iter.mo +++ b/test/run-drun/text-iter.mo @@ -1,69 +1,70 @@ +import Prim "mo:prim"; let s = "hello world!"; -debugPrint "via `debugPrint`:"; -debugPrint s; -debugPrint ""; +Prim.debugPrint "via `debugPrint`:"; +Prim.debugPrint s; +Prim.debugPrint ""; -debugPrint "via iteration and `debugPrintChar`: #1"; +Prim.debugPrint "via iteration and `debugPrintChar`: #1"; for (a in s.chars()) { - debugPrintChar a; + Prim.debugPrintChar a; }; -debugPrint ""; +Prim.debugPrint ""; -debugPrint "via iteration and `debugPrintChar`: #2"; +Prim.debugPrint "via iteration and `debugPrintChar`: #2"; var x = 0; for (a in s.chars()) { x += 1; - debugPrintNat x; - debugPrint ":"; - debugPrintChar '\''; - debugPrintChar a; - debugPrintChar '\''; - debugPrint " "; + Prim.debugPrintNat x; + Prim.debugPrint ":"; + Prim.debugPrintChar '\''; + Prim.debugPrintChar a; + Prim.debugPrintChar '\''; + Prim.debugPrint " "; }; -debugPrint ""; +Prim.debugPrint ""; let russian = "Приветствую, мир!\n"; assert(russian.len() == 18); -debugPrint "via iteration and `debugPrintChar` (Unicode): #3"; +Prim.debugPrint "via iteration and `debugPrintChar` (Unicode): #3"; x := 0; for (a in russian.chars()) { x += 1; - debugPrintNat x; - debugPrint ":"; - debugPrintChar '\''; - debugPrintChar a; - debugPrintChar '\''; - debugPrint " "; + Prim.debugPrintNat x; + Prim.debugPrint ":"; + Prim.debugPrintChar '\''; + Prim.debugPrintChar a; + Prim.debugPrintChar '\''; + Prim.debugPrint " "; }; -debugPrint ""; +Prim.debugPrint ""; assert(x == 18); let emojis = "🙈🎸😋"; assert(emojis.len() == 3); -debugPrint "via iteration and `debugPrintChar` (Unicode): #4"; +Prim.debugPrint "via iteration and `debugPrintChar` (Unicode): #4"; x := 0; for (a in emojis.chars()) { x += 1; - debugPrintNat x; - debugPrint ":"; - debugPrintChar '\''; - debugPrintChar a; - debugPrintChar '\''; - debugPrint " "; + Prim.debugPrintNat x; + Prim.debugPrint ":"; + Prim.debugPrintChar '\''; + Prim.debugPrintChar a; + Prim.debugPrintChar '\''; + Prim.debugPrint " "; }; -debugPrint ""; +Prim.debugPrint ""; assert(x == 3); -debugPrint russian; debugPrint ""; +Prim.debugPrint russian; Prim.debugPrint ""; switch (russian.chars().next()) { - case (?c) { debugPrintChar c; debugPrint "" }; + case (?c) { Prim.debugPrintChar c; Prim.debugPrint "" }; case _ {}; }; switch (emojis.chars().next()) { - case (?c) { assert (c == '\u{1f648}'); debugPrintChar c; debugPrint "" }; + case (?c) { assert (c == '\u{1f648}'); Prim.debugPrintChar c; Prim.debugPrint "" }; case _ {}; }; diff --git a/test/run-drun/throw.mo b/test/run-drun/throw.mo index 99b7dbb956e..b8e8327f916 100644 --- a/test/run-drun/throw.mo +++ b/test/run-drun/throw.mo @@ -1,3 +1,4 @@ +import Prim "mo:prim"; // This is like local-throw.as, just not local // (Using `await async { … }` around relevant parts @@ -5,11 +6,11 @@ actor a { public func t2() : async () { try { await async { - throw error("t2"); + throw Prim.error("t2"); assert(false); } } catch e { - switch (errorCode(e),errorMessage(e)) { + switch (Prim.errorCode(e),Prim.errorMessage(e)) { case (#error, "t2") { }; case (#system, _ ) { assert false;}; case (#error, _) { assert false;}; @@ -22,13 +23,13 @@ actor a { await async { try { await async { - throw error("t3"); + throw Prim.error("t3"); assert(false); } } catch e1 { - switch (errorCode(e1), errorMessage(e1)) { + switch (Prim.errorCode(e1), Prim.errorMessage(e1)) { case (#error, "t3") { - throw error("t31"); + throw Prim.error("t31"); }; case (#system, _) { assert false; @@ -41,7 +42,7 @@ actor a { } } catch e2 { - switch (errorCode(e2),errorMessage(e2)) { + switch (Prim.errorCode(e2),Prim.errorMessage(e2)) { case (#error, "t31") { }; case (#system, _) { assert false; @@ -57,14 +58,14 @@ actor a { public func go() = ignore async { try { await t2(); - debugPrint ("t2 ok"); + Prim.debugPrint ("t2 ok"); } catch _ { assert false; }; try { await t3(); - debugPrint ("t3 ok"); + Prim.debugPrint ("t3 ok"); } catch _ { assert false; }; diff --git a/test/run-drun/transpose.mo b/test/run-drun/transpose.mo index 9fed4a2aa21..6cef2496bfb 100644 --- a/test/run-drun/transpose.mo +++ b/test/run-drun/transpose.mo @@ -1,8 +1,9 @@ +import Prim "mo:prim"; actor a { public func transpose (data : [(Int,Text)]) : async {ints: [Int]; txts: [Text]} { return { - ints = Array_tabulate(data.len(), func (i:Nat) : Int = (data[i].0)); - txts = Array_tabulate(data.len(), func (i:Nat) : Text = (data[i].1)) + ints = Prim.Array_tabulate(data.len(), func (i:Nat) : Int = (data[i].0)); + txts = Prim.Array_tabulate(data.len(), func (i:Nat) : Text = (data[i].1)) } }; @@ -12,7 +13,7 @@ actor a { assert (x.ints[1] == 2); assert (x.txts[0] == "Hi"); assert (x.txts[1] == "Ho"); - debugPrint("All good"); + Prim.debugPrint("All good"); } }; a.go(); //OR-CALL ingress go "DIDL\x00\x00" diff --git a/test/run.sh b/test/run.sh index 3b120a5af4c..ff351a252d2 100755 --- a/test/run.sh +++ b/test/run.sh @@ -73,6 +73,7 @@ function normalize () { sed 's/^.*[IW], hypervisor:/hypervisor:/g' | sed 's/wasm:0x[a-f0-9]*:/wasm:0x___:/g' | sed 's/prelude:[^:]*:/prelude:___:/g' | + sed 's/prim:[^:]*:/prim:___:/g' | sed 's/ calling func\$[0-9]*/ calling func$NNN/g' | sed 's/rip_addr: [0-9]*/rip_addr: XXX/g' | sed 's,/private/tmp/,/tmp/,g' | diff --git a/test/run/array-gen.mo b/test/run/array-gen.mo index 6dd071907db..8de98795b6f 100644 --- a/test/run/array-gen.mo +++ b/test/run/array-gen.mo @@ -1,11 +1,13 @@ -let a = Array_init(10,42); +import Prim "mo:prim"; + +let a = Prim.Array_init(10,42); assert (a.len() == 10); for (n in a.vals()) { assert(n == 42); }; -let b = Array_tabulate(10,func (x : Nat) : Nat = x); +let b = Prim.Array_tabulate(10,func (x : Nat) : Nat = x); assert(b.len() == 10); for (i in b.keys()) { diff --git a/test/run/caller.mo b/test/run/caller.mo index 896c74bf183..8557229bc2d 100644 --- a/test/run/caller.mo +++ b/test/run/caller.mo @@ -1,3 +1,4 @@ +import Prim "mo:prim"; actor a { public shared { caller = c } func getCaller() : async Blob { @@ -5,7 +6,7 @@ actor a { }; public shared query { caller = c } func getCallerHash() : async Word32 { - hashBlob c; + Prim.hashBlob c; }; public shared {caller} func c () : async () { diff --git a/test/run/char-high-surrogate-trap.mo b/test/run/char-high-surrogate-trap.mo index f643094a948..6057208e8b4 100644 --- a/test/run/char-high-surrogate-trap.mo +++ b/test/run/char-high-surrogate-trap.mo @@ -1 +1,2 @@ -let _ = word32ToChar 0xdfff +import Prim "mo:prim"; +let _ = Prim.word32ToChar 0xdfff diff --git a/test/run/char-low-surrogate-trap.mo b/test/run/char-low-surrogate-trap.mo index aada8d6bd59..d06ebff6800 100644 --- a/test/run/char-low-surrogate-trap.mo +++ b/test/run/char-low-surrogate-trap.mo @@ -1 +1,2 @@ -let _ = word32ToChar 0xd800 +import Prim "mo:prim"; +let _ = Prim.word32ToChar 0xd800 diff --git a/test/run/char-trap.mo b/test/run/char-trap.mo index 84430038a79..2c4ea6a576b 100644 --- a/test/run/char-trap.mo +++ b/test/run/char-trap.mo @@ -1 +1,2 @@ -let _ = word32ToChar 0x110000 +import Prim "mo:prim"; +let _ = Prim.word32ToChar 0x110000 diff --git a/test/run/chatpp.mo b/test/run/chatpp.mo index d96e11d9bba..5a8245052d8 100644 --- a/test/run/chatpp.mo +++ b/test/run/chatpp.mo @@ -1,3 +1,5 @@ +import Prim "mo:prim"; + type List = ?{head : T; var tail : List}; type Subscription = { @@ -53,8 +55,8 @@ actor class Server() = { case null { clients := n.tail }; case (?p) { p.tail := n.tail }; }; - debugPrint "unsubscribe "; - debugPrintInt id; + Prim.debugPrint "unsubscribe "; + Prim.debugPrintInt id; return; }; prev := next; @@ -82,7 +84,7 @@ actor class Client() = this { }; public func send(msg : Text) { - debugPrint(name # " received " # msg); + Prim.debugPrint(name # " received " # msg); }; }; diff --git a/test/run/conversions.mo b/test/run/conversions.mo index a5183b996a0..ecbdc2665fb 100644 --- a/test/run/conversions.mo +++ b/test/run/conversions.mo @@ -1,89 +1,91 @@ +import Prim "mo:prim"; + // Nat <--> Word32 func n2w(n : Nat) : ?Word32 { - let w = natToWord32 n; - if (n == word32ToNat w) + let w = Prim.natToWord32 n; + if (n == Prim.word32ToNat w) ?w else null }; -assert(natToWord32 0 == (0 : Word32)); -assert(natToWord32 42 == (42 : Word32)); -assert(natToWord32 65535 == (65535 : Word32)); // 2**16 - 1 +assert(Prim.natToWord32 0 == (0 : Word32)); +assert(Prim.natToWord32 42 == (42 : Word32)); +assert(Prim.natToWord32 65535 == (65535 : Word32)); // 2**16 - 1 -assert(natToWord32 2147483647 == (2147483647 : Word32)); // 2**31 - 1 -assert(natToWord32 2147483648 == (2147483648 : Word32)); // 2**31 -assert(natToWord32 2147483649 == (2147483649 : Word32)); // 2**31 + 1 -assert(natToWord32 4294967295 == (4294967295 : Word32)); // 2**32 - 1 +assert(Prim.natToWord32 2147483647 == (2147483647 : Word32)); // 2**31 - 1 +assert(Prim.natToWord32 2147483648 == (2147483648 : Word32)); // 2**31 +assert(Prim.natToWord32 2147483649 == (2147483649 : Word32)); // 2**31 + 1 +assert(Prim.natToWord32 4294967295 == (4294967295 : Word32)); // 2**32 - 1 -assert(word32ToNat 0 == 0); -assert(word32ToNat 42 == 42); -assert(word32ToNat 2147483647 == 2147483647); // 2**31 - 1 -assert(word32ToNat 4294967295 == 4294967295); // 2**32 - 1 +assert(Prim.word32ToNat 0 == 0); +assert(Prim.word32ToNat 42 == 42); +assert(Prim.word32ToNat 2147483647 == 2147483647); // 2**31 - 1 +assert(Prim.word32ToNat 4294967295 == 4294967295); // 2**32 - 1 func forall (f : T -> (), l : [T]) = for (e in l.vals()) { f e }; { - func roundtrip(n : Nat) = assert (word32ToNat (natToWord32 n) == n); + func roundtrip(n : Nat) = assert (Prim.word32ToNat (Prim.natToWord32 n) == n); forall(roundtrip, [0, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 0x7FFFFFFF, 0xFFFFFFFF]); }; { - func roundtrip(w : Word32) = assert (natToWord32 (word32ToNat w) == w); + func roundtrip(w : Word32) = assert (Prim.natToWord32 (Prim.word32ToNat w) == w); forall(roundtrip, [0, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 0x7FFFFFFF, 0xFFFFFFFF]); - func roundtripNat64(w : Word64) = assert (nat64ToWord64 (word64ToNat64 w) == w); + func roundtripNat64(w : Word64) = assert (Prim.nat64ToWord64 (Prim.word64ToNat64 w) == w); forall(roundtripNat64, [0, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 0x7FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFFFFFFFFFF]); - func roundtripInt64(w : Word64) = assert (int64ToWord64 (word64ToInt64 w) == w); + func roundtripInt64(w : Word64) = assert (Prim.int64ToWord64 (Prim.word64ToInt64 w) == w); forall(roundtripInt64, [0, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 0x7FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFFFFFFFFFF]); - func roundtrip64i(w : Int) = assert (int64ToInt (intToInt64 w) == w); + func roundtrip64i(w : Int) = assert (Prim.int64ToInt (Prim.intToInt64 w) == w); forall(roundtrip64i, [0, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 0x7FFFFFFF, 0x7FFFFFFFFFFFFFFF]); forall(roundtrip64i, [-10, -100, -1000, -10000, -100000, -1000000, -10000000, -100000000, -1000000000, -2147483648, -9223372036854775808]); - func roundtrip64n(w : Nat) = assert (nat64ToNat (natToNat64 w) == w); + func roundtrip64n(w : Nat) = assert (Prim.nat64ToNat (Prim.natToNat64 w) == w); forall(roundtrip64n, [0, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 0x7FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFFFFFFFFFF]); - func roundtripNat32(w : Word32) = assert (nat32ToWord32 (word32ToNat32 w) == w); + func roundtripNat32(w : Word32) = assert (Prim.nat32ToWord32 (Prim.word32ToNat32 w) == w); forall(roundtripNat32, [0, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 0x7FFFFFFF, 0xFFFFFFFF]); - func roundtripInt32(w : Word32) = assert (int32ToWord32 (word32ToInt32 w) == w); + func roundtripInt32(w : Word32) = assert (Prim.int32ToWord32 (Prim.word32ToInt32 w) == w); forall(roundtripInt32, [0, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 0x7FFFFFFF, 0xFFFFFFFF]); - func roundtrip32i(w : Int) = assert (int32ToInt (intToInt32 w) == w); + func roundtrip32i(w : Int) = assert (Prim.int32ToInt (Prim.intToInt32 w) == w); forall(roundtrip32i, [0, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 0x7FFFFFFF]); forall(roundtrip32i, [-10, -100, -1000, -10000, -100000, -1000000, -10000000, -100000000, -1000000000, -2147483648]); - func roundtrip32n(w : Nat) = assert (nat32ToNat (natToNat32 w) == w); + func roundtrip32n(w : Nat) = assert (Prim.nat32ToNat (Prim.natToNat32 w) == w); forall(roundtrip32n, [0, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 0x7FFFFFFF, 0xFFFFFFFF]); - func roundtripNat16(w : Word16) = assert (nat16ToWord16 (word16ToNat16 w) == w); + func roundtripNat16(w : Word16) = assert (Prim.nat16ToWord16 (Prim.word16ToNat16 w) == w); forall(roundtripNat16, [0, 10, 100, 1000, 10000, 0xFFFF]); - func roundtripInt16(w : Word16) = assert (int16ToWord16 (word16ToInt16 w) == w); + func roundtripInt16(w : Word16) = assert (Prim.int16ToWord16 (Prim.word16ToInt16 w) == w); forall(roundtripInt16, [0, 10, 100, 1000, 10000, 0xFFFF]); - func roundtrip16i(w : Int) = assert (int16ToInt (intToInt16 w) == w); + func roundtrip16i(w : Int) = assert (Prim.int16ToInt (Prim.intToInt16 w) == w); forall(roundtrip16i, [0, 10, 100, 1000, 10000, 0x7FFF]); forall(roundtrip16i, [-10, -100, -1000, -10000, -32768]); - func roundtrip16n(w : Nat) = assert (nat16ToNat (natToNat16 w) == w); + func roundtrip16n(w : Nat) = assert (Prim.nat16ToNat (Prim.natToNat16 w) == w); forall(roundtrip16n, [0, 10, 100, 1000, 10000, 0xFFFF]); - func roundtripNat8(w : Word8) = assert (nat8ToWord8 (word8ToNat8 w) == w); + func roundtripNat8(w : Word8) = assert (Prim.nat8ToWord8 (Prim.word8ToNat8 w) == w); forall(roundtripNat8, [0, 10, 100, 0xFF]); - func roundtripInt8(w : Word8) = assert (int8ToWord8 (word8ToInt8 w) == w); + func roundtripInt8(w : Word8) = assert (Prim.int8ToWord8 (Prim.word8ToInt8 w) == w); forall(roundtripInt8, [0, 10, 100, 0xFF]); - func roundtrip8i(w : Int) = assert (int8ToInt (intToInt8 w) == w); + func roundtrip8i(w : Int) = assert (Prim.int8ToInt (Prim.intToInt8 w) == w); forall(roundtrip8i, [0, 10, 100, 0x7F]); forall(roundtrip8i, [-10, -100, -128]); - func roundtrip8n(w : Nat) = assert (nat8ToNat (natToNat8 w) == w); + func roundtrip8n(w : Nat) = assert (Prim.nat8ToNat (Prim.natToNat8 w) == w); forall(roundtrip8n, [0, 10, 100, 0xFF]); }; @@ -91,49 +93,49 @@ func forall (f : T -> (), l : [T]) = for (e in l.vals()) { f e }; // Int <--> Word32 func i2w(n : Nat) : ?Word32 { - let w = intToWord32 n; - if (n == word32ToInt w) + let w = Prim.intToWord32 n; + if (n == Prim.word32ToInt w) ?w else null }; -assert(intToWord32 0 == (0 : Word32)); -assert(intToWord32 42 == (42 : Word32)); -assert(intToWord32 65535 == (65535 : Word32)); // 2**16 - 1 +assert(Prim.intToWord32 0 == (0 : Word32)); +assert(Prim.intToWord32 42 == (42 : Word32)); +assert(Prim.intToWord32 65535 == (65535 : Word32)); // 2**16 - 1 -assert(intToWord32 (-42) == (-42/*!*/ : Word32)); -assert(intToWord32 (-65535) == (-65535/*!*/ : Word32)); // - 2**16 + 1 -assert(intToWord32 (-65536) == (-65536/*!*/ : Word32)); // - 2**16 -assert(intToWord32 (-2147483648) == (-2147483648/*!*/ : Word32)); // - 2**31 +assert(Prim.intToWord32 (-42) == (-42/*!*/ : Word32)); +assert(Prim.intToWord32 (-65535) == (-65535/*!*/ : Word32)); // - 2**16 + 1 +assert(Prim.intToWord32 (-65536) == (-65536/*!*/ : Word32)); // - 2**16 +assert(Prim.intToWord32 (-2147483648) == (-2147483648/*!*/ : Word32)); // - 2**31 -assert(intToWord32 2147483647 == (2147483647 : Word32)); // 2**31 - 1 -assert(intToWord32 2147483648 == (2147483648 : Word32)); // 2**31 -assert(intToWord32 2147483649 == (2147483649 : Word32)); // 2**31 + 1 -assert(intToWord32 4294967295 == (4294967295 : Word32)); // 2**32 - 1 +assert(Prim.intToWord32 2147483647 == (2147483647 : Word32)); // 2**31 - 1 +assert(Prim.intToWord32 2147483648 == (2147483648 : Word32)); // 2**31 +assert(Prim.intToWord32 2147483649 == (2147483649 : Word32)); // 2**31 + 1 +assert(Prim.intToWord32 4294967295 == (4294967295 : Word32)); // 2**32 - 1 -func println(i : Int) { debugPrintInt(i) }; +func println(i : Int) { Prim.debugPrintInt(i) }; -println(word32ToInt (-2147483648)); // -2**31 -println(word32ToInt (-2147483647)); // -2**31 + 1 -println(word32ToInt (-42)); -println(word32ToInt (-1)); -println(word32ToInt 0); -println(word32ToInt 42); -println(word32ToInt 2147483647); // 2**31 - 1 -println(word32ToInt 2147483648); // == (-2147483648) // 2**31 -println(word32ToInt 4294967294); // == (-2) // 2**32 - 2 -println(word32ToInt 4294967295); // == (-1) // 2**32 - 1 +println(Prim.word32ToInt (-2147483648)); // -2**31 +println(Prim.word32ToInt (-2147483647)); // -2**31 + 1 +println(Prim.word32ToInt (-42)); +println(Prim.word32ToInt (-1)); +println(Prim.word32ToInt 0); +println(Prim.word32ToInt 42); +println(Prim.word32ToInt 2147483647); // 2**31 - 1 +println(Prim.word32ToInt 2147483648); // == (-2147483648) // 2**31 +println(Prim.word32ToInt 4294967294); // == (-2) // 2**32 - 2 +println(Prim.word32ToInt 4294967295); // == (-1) // 2**32 - 1 { - func roundtrip(i : Int) = assert (word32ToInt (intToWord32 i) == i); + func roundtrip(i : Int) = assert (Prim.word32ToInt (Prim.intToWord32 i) == i); forall(roundtrip, [0, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 0x7FFFFFFF]); forall(roundtrip, [-10, -100, -1000, -10000, -100000, -1000000, -10000000, -100000000, -1000000000, -2147483648]); }; { - func roundtrip(w : Word32) = assert (intToWord32 (word32ToInt w) == w); + func roundtrip(w : Word32) = assert (Prim.intToWord32 (Prim.word32ToInt w) == w); forall(roundtrip, [0, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 0x7FFFFFFF, 0xFFFFFFFF]); /* non-canonical range for Word32 */ @@ -145,161 +147,161 @@ println(word32ToInt 4294967295); // == (-1) // 2**32 - 1 // Char <--> Word32 -assert(charToWord32 '\u{00}' == (0 : Word32)); -assert(charToWord32 '*' == (42 : Word32)); -assert(charToWord32 'П' == (1055 : Word32)); -assert(charToWord32 '\u{ffff}' == (65535 : Word32)); // 2**16 - 1 -assert(charToWord32 '\u{10ffff}' == (0x10FFFF : Word32)); +assert(Prim.charToWord32 '\u{00}' == (0 : Word32)); +assert(Prim.charToWord32 '*' == (42 : Word32)); +assert(Prim.charToWord32 'П' == (1055 : Word32)); +assert(Prim.charToWord32 '\u{ffff}' == (65535 : Word32)); // 2**16 - 1 +assert(Prim.charToWord32 '\u{10ffff}' == (0x10FFFF : Word32)); { - func roundtrip(w : Word32) = assert (charToWord32 (word32ToChar w) == w); + func roundtrip(w : Word32) = assert (Prim.charToWord32 (Prim.word32ToChar w) == w); forall(roundtrip, [0, 10, 100, 1000, 10000, 100000, 1000000, 0x10FFFF]); // largest code point }; // Char <--> Text -assert(charToText 'П' == "П"); +assert(Prim.charToText 'П' == "П"); func snd((a : Word32, b : Char)) : Char = b; assert(switch ("П".chars().next()) { case (?'П') true; case _ false }); // Nat <--> Word64 -assert(natToWord64 0x0000000000000000 == (0x0000000000000000 : Word64)); -assert(natToWord64 0x0000000000000001 == (0x0000000000000001 : Word64)); -assert(natToWord64 0x7FFFFFFFFFFFFFFF == (0x7FFFFFFFFFFFFFFF : Word64)); -assert(natToWord64 0x8000000000000000 == (0x8000000000000000 : Word64)); -assert(natToWord64 0x8000000000000001 == (0x8000000000000001 : Word64)); -assert(natToWord64 0xFFFFFFFFFFFFFFFF == (0xFFFFFFFFFFFFFFFF : Word64)); +assert(Prim.natToWord64 0x0000000000000000 == (0x0000000000000000 : Word64)); +assert(Prim.natToWord64 0x0000000000000001 == (0x0000000000000001 : Word64)); +assert(Prim.natToWord64 0x7FFFFFFFFFFFFFFF == (0x7FFFFFFFFFFFFFFF : Word64)); +assert(Prim.natToWord64 0x8000000000000000 == (0x8000000000000000 : Word64)); +assert(Prim.natToWord64 0x8000000000000001 == (0x8000000000000001 : Word64)); +assert(Prim.natToWord64 0xFFFFFFFFFFFFFFFF == (0xFFFFFFFFFFFFFFFF : Word64)); -assert(word64ToNat 0x0000000000000000 == (0x0000000000000000 : Nat)); -assert(word64ToNat 0x0000000000000001 == (0x0000000000000001 : Nat)); -assert(word64ToNat 0x7FFFFFFFFFFFFFFF == (0x7FFFFFFFFFFFFFFF : Nat)); -assert(word64ToNat 0x8000000000000000 == (0x8000000000000000 : Nat)); -assert(word64ToNat 0x8000000000000001 == (0x8000000000000001 : Nat)); -assert(word64ToNat 0xFFFFFFFFFFFFFFFF == (0xFFFFFFFFFFFFFFFF : Nat)); +assert(Prim.word64ToNat 0x0000000000000000 == (0x0000000000000000 : Nat)); +assert(Prim.word64ToNat 0x0000000000000001 == (0x0000000000000001 : Nat)); +assert(Prim.word64ToNat 0x7FFFFFFFFFFFFFFF == (0x7FFFFFFFFFFFFFFF : Nat)); +assert(Prim.word64ToNat 0x8000000000000000 == (0x8000000000000000 : Nat)); +assert(Prim.word64ToNat 0x8000000000000001 == (0x8000000000000001 : Nat)); +assert(Prim.word64ToNat 0xFFFFFFFFFFFFFFFF == (0xFFFFFFFFFFFFFFFF : Nat)); // Int <--> Word64 -assert(intToWord64 0x0000000000000000 == (0x0000000000000000 : Word64)); -assert(intToWord64 0x0000000000000001 == (0x0000000000000001 : Word64)); -assert(intToWord64 0x7FFFFFFFFFFFFFFF == (0x7FFFFFFFFFFFFFFF : Word64)); -assert(intToWord64 (-0x8000000000000000) == (0x8000000000000000 : Word64)); -assert(intToWord64 (-0x7FFFFFFFFFFFFFFF) == (0x8000000000000001 : Word64)); -assert(intToWord64 (-0x7FFFFFFFFFFFFFFE) == (0x8000000000000002 : Word64)); -assert(intToWord64 (-0x0000000000000001) == (0xFFFFFFFFFFFFFFFF : Word64)); - -assert(word64ToInt (0x0000000000000000 : Word64) == 0x0000000000000000); -assert(word64ToInt (0x0000000000000001 : Word64) == 0x0000000000000001); -assert(word64ToInt (0x7FFFFFFFFFFFFFFF : Word64) == 0x7FFFFFFFFFFFFFFF); -assert(word64ToInt (0x8000000000000000 : Word64) == -0x8000000000000000); -assert(word64ToInt (0x8000000000000001 : Word64) == -0x7FFFFFFFFFFFFFFF); -assert(word64ToInt (0x8000000000000002 : Word64) == -0x7FFFFFFFFFFFFFFE); -assert(word64ToInt (0xFFFFFFFFFFFFFFFF : Word64) == -0x0000000000000001); +assert(Prim.intToWord64 0x0000000000000000 == (0x0000000000000000 : Word64)); +assert(Prim.intToWord64 0x0000000000000001 == (0x0000000000000001 : Word64)); +assert(Prim.intToWord64 0x7FFFFFFFFFFFFFFF == (0x7FFFFFFFFFFFFFFF : Word64)); +assert(Prim.intToWord64 (-0x8000000000000000) == (0x8000000000000000 : Word64)); +assert(Prim.intToWord64 (-0x7FFFFFFFFFFFFFFF) == (0x8000000000000001 : Word64)); +assert(Prim.intToWord64 (-0x7FFFFFFFFFFFFFFE) == (0x8000000000000002 : Word64)); +assert(Prim.intToWord64 (-0x0000000000000001) == (0xFFFFFFFFFFFFFFFF : Word64)); + +assert(Prim.word64ToInt (0x0000000000000000 : Word64) == 0x0000000000000000); +assert(Prim.word64ToInt (0x0000000000000001 : Word64) == 0x0000000000000001); +assert(Prim.word64ToInt (0x7FFFFFFFFFFFFFFF : Word64) == 0x7FFFFFFFFFFFFFFF); +assert(Prim.word64ToInt (0x8000000000000000 : Word64) == -0x8000000000000000); +assert(Prim.word64ToInt (0x8000000000000001 : Word64) == -0x7FFFFFFFFFFFFFFF); +assert(Prim.word64ToInt (0x8000000000000002 : Word64) == -0x7FFFFFFFFFFFFFFE); +assert(Prim.word64ToInt (0xFFFFFFFFFFFFFFFF : Word64) == -0x0000000000000001); // Below conversions mainly test the interpreter's bignum arithmetics // Int <--> Word8 -assert(intToWord8 (2 ** 62) == (0 : Word8)); -assert(intToWord8 (2 ** 62 + 1) == (1 : Word8)); -assert(intToWord8 (2 ** 62 - 1) == (255 : Word8)); -assert(intToWord8 (- 2 ** 62) == (0 : Word8)); -assert(intToWord8 (- 2 ** 62 + 1) == (1 : Word8)); -assert(intToWord8 (- 2 ** 62 - 1) == (255 : Word8)); +assert(Prim.intToWord8 (2 ** 62) == (0 : Word8)); +assert(Prim.intToWord8 (2 ** 62 + 1) == (1 : Word8)); +assert(Prim.intToWord8 (2 ** 62 - 1) == (255 : Word8)); +assert(Prim.intToWord8 (- 2 ** 62) == (0 : Word8)); +assert(Prim.intToWord8 (- 2 ** 62 + 1) == (1 : Word8)); +assert(Prim.intToWord8 (- 2 ** 62 - 1) == (255 : Word8)); -assert(intToWord8 (2 ** 63) == (0 : Word8)); -assert(intToWord8 (2 ** 63 + 1) == (1 : Word8)); -assert(intToWord8 (2 ** 63 - 1) == (255 : Word8)); -assert(intToWord8 (- 2 ** 63) == (0 : Word8)); -assert(intToWord8 (- 2 ** 63 + 1) == (1 : Word8)); -assert(intToWord8 (- 2 ** 63 - 1) == (255 : Word8)); +assert(Prim.intToWord8 (2 ** 63) == (0 : Word8)); +assert(Prim.intToWord8 (2 ** 63 + 1) == (1 : Word8)); +assert(Prim.intToWord8 (2 ** 63 - 1) == (255 : Word8)); +assert(Prim.intToWord8 (- 2 ** 63) == (0 : Word8)); +assert(Prim.intToWord8 (- 2 ** 63 + 1) == (1 : Word8)); +assert(Prim.intToWord8 (- 2 ** 63 - 1) == (255 : Word8)); -assert(intToWord8 (2 ** 64) == (0 : Word8)); -assert(intToWord8 (2 ** 64 + 1) == (1 : Word8)); -assert(intToWord8 (2 ** 64 - 1) == (255 : Word8)); -assert(intToWord8 (- 2 ** 64) == (0 : Word8)); -assert(intToWord8 (- 2 ** 64 + 1) == (1 : Word8)); -assert(intToWord8 (- 2 ** 64 - 1) == (255 : Word8)); +assert(Prim.intToWord8 (2 ** 64) == (0 : Word8)); +assert(Prim.intToWord8 (2 ** 64 + 1) == (1 : Word8)); +assert(Prim.intToWord8 (2 ** 64 - 1) == (255 : Word8)); +assert(Prim.intToWord8 (- 2 ** 64) == (0 : Word8)); +assert(Prim.intToWord8 (- 2 ** 64 + 1) == (1 : Word8)); +assert(Prim.intToWord8 (- 2 ** 64 - 1) == (255 : Word8)); // Nat <--> Word8 -assert(natToWord8 (2 ** 64) == (0 : Word8)); -assert(natToWord8 (2 ** 64 + 1) == (1 : Word8)); -assert(natToWord8 (2 ** 64 - 1) == (255 : Word8)); +assert(Prim.natToWord8 (2 ** 64) == (0 : Word8)); +assert(Prim.natToWord8 (2 ** 64 + 1) == (1 : Word8)); +assert(Prim.natToWord8 (2 ** 64 - 1) == (255 : Word8)); // Int <--> Word16 -assert(intToWord16 (2 ** 62) == (0 : Word16)); -assert(intToWord16 (2 ** 62 + 1) == (1 : Word16)); -assert(intToWord16 (2 ** 62 - 1) == (65535 : Word16)); -assert(intToWord16 (- 2 ** 62) == (0 : Word16)); -assert(intToWord16 (- 2 ** 62 + 1) == (1 : Word16)); -assert(intToWord16 (- 2 ** 62 - 1) == (65535 : Word16)); - -assert(intToWord16 (2 ** 63) == (0 : Word16)); -assert(intToWord16 (2 ** 63 + 1) == (1 : Word16)); -assert(intToWord16 (2 ** 63 - 1) == (65535 : Word16)); -assert(intToWord16 (- 2 ** 63) == (0 : Word16)); -assert(intToWord16 (- 2 ** 63 + 1) == (1 : Word16)); -assert(intToWord16 (- 2 ** 63 - 1) == (65535 : Word16)); - -assert(intToWord16 (2 ** 64) == (0 : Word16)); -assert(intToWord16 (2 ** 64 + 1) == (1 : Word16)); -assert(intToWord16 (2 ** 64 - 1) == (65535 : Word16)); -assert(intToWord16 (- 2 ** 64) == (0 : Word16)); -assert(intToWord16 (- 2 ** 64 + 1) == (1 : Word16)); -assert(intToWord16 (- 2 ** 64 - 1) == (65535 : Word16)); +assert(Prim.intToWord16 (2 ** 62) == (0 : Word16)); +assert(Prim.intToWord16 (2 ** 62 + 1) == (1 : Word16)); +assert(Prim.intToWord16 (2 ** 62 - 1) == (65535 : Word16)); +assert(Prim.intToWord16 (- 2 ** 62) == (0 : Word16)); +assert(Prim.intToWord16 (- 2 ** 62 + 1) == (1 : Word16)); +assert(Prim.intToWord16 (- 2 ** 62 - 1) == (65535 : Word16)); + +assert(Prim.intToWord16 (2 ** 63) == (0 : Word16)); +assert(Prim.intToWord16 (2 ** 63 + 1) == (1 : Word16)); +assert(Prim.intToWord16 (2 ** 63 - 1) == (65535 : Word16)); +assert(Prim.intToWord16 (- 2 ** 63) == (0 : Word16)); +assert(Prim.intToWord16 (- 2 ** 63 + 1) == (1 : Word16)); +assert(Prim.intToWord16 (- 2 ** 63 - 1) == (65535 : Word16)); + +assert(Prim.intToWord16 (2 ** 64) == (0 : Word16)); +assert(Prim.intToWord16 (2 ** 64 + 1) == (1 : Word16)); +assert(Prim.intToWord16 (2 ** 64 - 1) == (65535 : Word16)); +assert(Prim.intToWord16 (- 2 ** 64) == (0 : Word16)); +assert(Prim.intToWord16 (- 2 ** 64 + 1) == (1 : Word16)); +assert(Prim.intToWord16 (- 2 ** 64 - 1) == (65535 : Word16)); // Nat <--> Word16 -assert(natToWord16 (2 ** 62) == (0 : Word16)); -assert(natToWord16 (2 ** 62 + 1) == (1 : Word16)); -assert(natToWord16 (2 ** 62 - 1) == (65535 : Word16)); +assert(Prim.natToWord16 (2 ** 62) == (0 : Word16)); +assert(Prim.natToWord16 (2 ** 62 + 1) == (1 : Word16)); +assert(Prim.natToWord16 (2 ** 62 - 1) == (65535 : Word16)); -assert(natToWord16 (2 ** 63) == (0 : Word16)); -assert(natToWord16 (2 ** 63 + 1) == (1 : Word16)); -assert(natToWord16 (2 ** 63 - 1) == (65535 : Word16)); +assert(Prim.natToWord16 (2 ** 63) == (0 : Word16)); +assert(Prim.natToWord16 (2 ** 63 + 1) == (1 : Word16)); +assert(Prim.natToWord16 (2 ** 63 - 1) == (65535 : Word16)); -assert(natToWord16 (2 ** 64) == (0 : Word16)); -assert(natToWord16 (2 ** 64 + 1) == (1 : Word16)); -assert(natToWord16 (2 ** 64 - 1) == (65535 : Word16)); +assert(Prim.natToWord16 (2 ** 64) == (0 : Word16)); +assert(Prim.natToWord16 (2 ** 64 + 1) == (1 : Word16)); +assert(Prim.natToWord16 (2 ** 64 - 1) == (65535 : Word16)); // Int <--> Word32 -assert(intToWord32 (2 ** 62) == (0 : Word32)); -assert(intToWord32 (2 ** 62 + 1) == (1 : Word32)); -assert(intToWord32 (2 ** 62 - 1) == (4294967295 : Word32)); -assert(intToWord32 (- 2 ** 62) == (0 : Word32)); -assert(intToWord32 (- 2 ** 62 + 1) == (1 : Word32)); -assert(intToWord32 (- 2 ** 62 - 1) == (4294967295 : Word32)); - -assert(intToWord32 (2 ** 63) == (0 : Word32)); -assert(intToWord32 (2 ** 63 + 1) == (1 : Word32)); -assert(intToWord32 (2 ** 63 - 1) == (4294967295 : Word32)); -assert(intToWord32 (- 2 ** 63) == (0 : Word32)); -assert(intToWord32 (- 2 ** 63 + 1) == (1 : Word32)); -assert(intToWord32 (- 2 ** 63 - 1) == (4294967295 : Word32)); - -assert(intToWord32 (2 ** 64) == (0 : Word32)); -assert(intToWord32 (2 ** 64 + 1) == (1 : Word32)); -assert(intToWord32 (2 ** 64 - 1) == (4294967295 : Word32)); -assert(intToWord32 (- 2 ** 64) == (0 : Word32)); -assert(intToWord32 (- 2 ** 64 + 1) == (1 : Word32)); -assert(intToWord32 (- 2 ** 64 - 1) == (4294967295 : Word32)); +assert(Prim.intToWord32 (2 ** 62) == (0 : Word32)); +assert(Prim.intToWord32 (2 ** 62 + 1) == (1 : Word32)); +assert(Prim.intToWord32 (2 ** 62 - 1) == (4294967295 : Word32)); +assert(Prim.intToWord32 (- 2 ** 62) == (0 : Word32)); +assert(Prim.intToWord32 (- 2 ** 62 + 1) == (1 : Word32)); +assert(Prim.intToWord32 (- 2 ** 62 - 1) == (4294967295 : Word32)); + +assert(Prim.intToWord32 (2 ** 63) == (0 : Word32)); +assert(Prim.intToWord32 (2 ** 63 + 1) == (1 : Word32)); +assert(Prim.intToWord32 (2 ** 63 - 1) == (4294967295 : Word32)); +assert(Prim.intToWord32 (- 2 ** 63) == (0 : Word32)); +assert(Prim.intToWord32 (- 2 ** 63 + 1) == (1 : Word32)); +assert(Prim.intToWord32 (- 2 ** 63 - 1) == (4294967295 : Word32)); + +assert(Prim.intToWord32 (2 ** 64) == (0 : Word32)); +assert(Prim.intToWord32 (2 ** 64 + 1) == (1 : Word32)); +assert(Prim.intToWord32 (2 ** 64 - 1) == (4294967295 : Word32)); +assert(Prim.intToWord32 (- 2 ** 64) == (0 : Word32)); +assert(Prim.intToWord32 (- 2 ** 64 + 1) == (1 : Word32)); +assert(Prim.intToWord32 (- 2 ** 64 - 1) == (4294967295 : Word32)); // Nat <--> Word32 -assert(natToWord32 (2 ** 62) == (0 : Word32)); -assert(natToWord32 (2 ** 62 + 1) == (1 : Word32)); -assert(natToWord32 (2 ** 62 - 1) == (4294967295 : Word32)); +assert(Prim.natToWord32 (2 ** 62) == (0 : Word32)); +assert(Prim.natToWord32 (2 ** 62 + 1) == (1 : Word32)); +assert(Prim.natToWord32 (2 ** 62 - 1) == (4294967295 : Word32)); -assert(natToWord32 (2 ** 63) == (0 : Word32)); -assert(natToWord32 (2 ** 63 + 1) == (1 : Word32)); -assert(natToWord32 (2 ** 63 - 1) == (4294967295 : Word32)); +assert(Prim.natToWord32 (2 ** 63) == (0 : Word32)); +assert(Prim.natToWord32 (2 ** 63 + 1) == (1 : Word32)); +assert(Prim.natToWord32 (2 ** 63 - 1) == (4294967295 : Word32)); -assert(natToWord32 (2 ** 64) == (0 : Word32)); -assert(natToWord32 (2 ** 64 + 1) == (1 : Word32)); -assert(natToWord32 (2 ** 64 - 1) == (4294967295 : Word32)); +assert(Prim.natToWord32 (2 ** 64) == (0 : Word32)); +assert(Prim.natToWord32 (2 ** 64 + 1) == (1 : Word32)); +assert(Prim.natToWord32 (2 ** 64 - 1) == (4294967295 : Word32)); diff --git a/test/run/debug-release.mo b/test/run/debug-release.mo index 45b73ac9655..ff31c2d1eb2 100644 --- a/test/run/debug-release.mo +++ b/test/run/debug-release.mo @@ -1,6 +1,8 @@ +import Prim "mo:prim"; + //MOC-FLAG --release -debugPrint "This should appear"; -debug { debugPrint "This shouldn't appear" }; -debugPrint "This should appear too"; +Prim.debugPrint "This should appear"; +debug { Prim.debugPrint "This shouldn't appear" }; +Prim.debugPrint "This should appear too"; diff --git a/test/run/debug.mo b/test/run/debug.mo index 0c881ad1776..56978a35969 100644 --- a/test/run/debug.mo +++ b/test/run/debug.mo @@ -1 +1,3 @@ -debug { debugPrint "This is for debugging only" }; // okay: result () +import Prim "mo:prim" + +debug { Prim.debugPrint "This is for debugging only" }; // okay: result () diff --git a/test/run/dec-bug.mo b/test/run/dec-bug.mo index 9173e2d15b7..e08a859c64c 100644 --- a/test/run/dec-bug.mo +++ b/test/run/dec-bug.mo @@ -1,3 +1,10 @@ +import Prim "mo:prim"; + +class range(x : Nat, y : Nat) { + var i = x; + public func next() : ?Nat { if (i > y) null else {let j = i; i += 1; ?j} }; +}; + func wrong() { for (i in range(0,1)) ignore 666 }; wrong(); diff --git a/test/run/for.mo b/test/run/for.mo index 93468a301c4..84f667251e7 100644 --- a/test/run/for.mo +++ b/test/run/for.mo @@ -1,6 +1,13 @@ +import Prim "mo:prim"; + +class range(x : Nat, y : Nat) { + var i = x; + public func next() : ?Nat { if (i > y) null else {let j = i; i += 1; ?j} }; +}; + var i = 0; for (j in range(0, 10)) { - debugPrintNat(j); + Prim.debugPrintNat(j); assert(j == i); i += 1; }; diff --git a/test/run/hashes.mo b/test/run/hashes.mo index d232f6cf498..d5aef2a7a0b 100644 --- a/test/run/hashes.mo +++ b/test/run/hashes.mo @@ -1,3 +1,20 @@ +import Prim "mo:prim"; + +func hashInt(x : Int) : Word32 { + var n = x; + var hash : Word32 = 0; + if (n < 0) { + hash := ^hash; + n := Prim.abs n; + }; + let base = 2**32; + while (n > 0) { + hash ^= Prim.intToWord32(n % base); + n /= base; + }; + return hash; +}; + assert (hashInt (10**7) == (10000000 : Word32)); assert (hashInt 0 == (0 : Word32)); diff --git a/test/run/huge-string.mo b/test/run/huge-string.mo index 18b1cf6997b..b88672ddbab 100644 --- a/test/run/huge-string.mo +++ b/test/run/huge-string.mo @@ -1,3 +1,5 @@ +import Prim "mo:prim"; + /* This uses repeated self-concatenation to build a huge string that would fill up most of the memory if implemented naively. @@ -5,12 +7,19 @@ It then checks that heap usage is actually not too bad, showing that string concatenation works as a tree with sharing. */ +class range(x : Nat, y : Nat) { + var i = x; + public func next() : ?Nat { if (i > y) null else {let j = i; i += 1; ?j} }; +}; + +let before = Prim.rts_heap_size(); var s = "Badger"; let n = 27; for (i in range(1,n)) { s := s # s; }; -assert(rts_heap_size() < 2_000); +let after = Prim.rts_heap_size(); +assert(after-before < 2_000); //SKIP run //SKIP run-low diff --git a/test/run/idlHash.mo b/test/run/idlHash.mo index 756885df980..52ba053dd8b 100644 --- a/test/run/idlHash.mo +++ b/test/run/idlHash.mo @@ -1,7 +1,9 @@ +import Prim "mo:prim"; + func testHash(s : Text, h : Word32) { - debugPrint("Hash for " # s); - debugPrint("Expected: " # debug_show (word32ToNat(h))); - debugPrint("Actual: " # debug_show (word32ToNat(idlHash s))); + Prim.debugPrint("Hash for " # s); + Prim.debugPrint("Expected: " # debug_show h); + Prim.debugPrint("Actual: " # debug_show (Prim.idlHash s)); }; // The lines below can be copied verbatim out of the corresponding JS unit test diff --git a/test/run/issue83.mo b/test/run/issue83.mo index 7762dbb951b..ddb4f5b0854 100644 --- a/test/run/issue83.mo +++ b/test/run/issue83.mo @@ -1,9 +1,11 @@ +import Prim "mo:prim"; + func Array_thaw(xs : [A]) : [var A] { let xsLen = xs.len(); if (xsLen == 0) { return [var]; }; - let ys = Array_init(xsLen, xs[0]); + let ys = Prim.Array_init(xsLen, xs[0]); for (i in ys.keys()) { ys[i] := xs[i]; }; @@ -17,7 +19,7 @@ func Array_thaw(xs : [A]) : [var A] { let expected : [var Int] = [var 1, 2, 3]; assert(actual.len() == expected.len()); - + for (i in actual.keys()) { assert(actual[i] == expected[i]); }; diff --git a/test/run/numeric-ops.mo b/test/run/numeric-ops.mo index f18a6505473..f27728f856f 100644 --- a/test/run/numeric-ops.mo +++ b/test/run/numeric-ops.mo @@ -1,3 +1,5 @@ +import Prim "mo:prim"; + // Testing utility // expects 2 elements in results for each one in etalon @@ -62,10 +64,10 @@ verify([-31, 31, -20, -42, -341, -2, -9, -25408476896404831], testInt(-31, verify([-1500000000, 1500000000, -1499999998, -1500000002, -3000000000, -750000000, 0, 2250000000000000000], testInt(-1500000000, 2), intCompare); func testIntAbs(a : Int) : [Int] { - let abs1 = abs a; - let abs2 = (abs a) : Int; - let abs3 = abs (-a); - let abs4 = (abs (-a)) : Int; + let abs1 = Prim.abs a; + let abs2 = (Prim.abs a) : Int; + let abs3 = Prim.abs (-a); + let abs4 = (Prim.abs (-a)) : Int; [abs1, abs2, abs3, abs4] }; diff --git a/test/run/objects1.mo b/test/run/objects1.mo index 265f11f301f..9e94b724d00 100644 --- a/test/run/objects1.mo +++ b/test/run/objects1.mo @@ -1,3 +1,4 @@ +import Prim "mo:prim"; let p = object {public let x = 3; let y = 2; public func get_y() : Int = y}; assert(p.x == 3); assert(p.get_y() == 2); @@ -41,7 +42,7 @@ assert (get_a () == -42); let row : (Nat, Int, {c : Char; d : Text}) = (100, -42, {c = 'C'; d = "D"}); func foo () : Int = switch row { - case (a : Int, -42, {c} : {c : Char}) (word32ToNat(charToWord32 c)) // OK + case (a : Int, -42, {c} : {c : Char}) (Prim.word32ToNat(Prim.charToWord32 c)) // OK }; assert (foo () == 67); diff --git a/test/run/ok/caller.comp.ok b/test/run/ok/caller.comp.ok index 3e3db5ebe39..c7e9b463b9b 100644 --- a/test/run/ok/caller.comp.ok +++ b/test/run/ok/caller.comp.ok @@ -1,2 +1,2 @@ -caller.mo:3.17-3.31: type error, shared function cannot take a context pattern +caller.mo:4.17-4.31: type error, shared function cannot take a context pattern (This is a limitation of the current version and flag -wasi-system-api.) diff --git a/test/run/ok/char-high-surrogate-trap.run-ir.ok b/test/run/ok/char-high-surrogate-trap.run-ir.ok index fe3a4aa9bb4..667752b8d83 100644 --- a/test/run/ok/char-high-surrogate-trap.run-ir.ok +++ b/test/run/ok/char-high-surrogate-trap.run-ir.ok @@ -1 +1 @@ -prelude:___: execution error, character value out of bounds +prim:___: execution error, character value out of bounds diff --git a/test/run/ok/char-high-surrogate-trap.run-low.ok b/test/run/ok/char-high-surrogate-trap.run-low.ok index fe3a4aa9bb4..667752b8d83 100644 --- a/test/run/ok/char-high-surrogate-trap.run-low.ok +++ b/test/run/ok/char-high-surrogate-trap.run-low.ok @@ -1 +1 @@ -prelude:___: execution error, character value out of bounds +prim:___: execution error, character value out of bounds diff --git a/test/run/ok/char-high-surrogate-trap.run.ok b/test/run/ok/char-high-surrogate-trap.run.ok index fe3a4aa9bb4..667752b8d83 100644 --- a/test/run/ok/char-high-surrogate-trap.run.ok +++ b/test/run/ok/char-high-surrogate-trap.run.ok @@ -1 +1 @@ -prelude:___: execution error, character value out of bounds +prim:___: execution error, character value out of bounds diff --git a/test/run/ok/char-low-surrogate-trap.run-ir.ok b/test/run/ok/char-low-surrogate-trap.run-ir.ok index fe3a4aa9bb4..667752b8d83 100644 --- a/test/run/ok/char-low-surrogate-trap.run-ir.ok +++ b/test/run/ok/char-low-surrogate-trap.run-ir.ok @@ -1 +1 @@ -prelude:___: execution error, character value out of bounds +prim:___: execution error, character value out of bounds diff --git a/test/run/ok/char-low-surrogate-trap.run-low.ok b/test/run/ok/char-low-surrogate-trap.run-low.ok index fe3a4aa9bb4..667752b8d83 100644 --- a/test/run/ok/char-low-surrogate-trap.run-low.ok +++ b/test/run/ok/char-low-surrogate-trap.run-low.ok @@ -1 +1 @@ -prelude:___: execution error, character value out of bounds +prim:___: execution error, character value out of bounds diff --git a/test/run/ok/char-low-surrogate-trap.run.ok b/test/run/ok/char-low-surrogate-trap.run.ok index fe3a4aa9bb4..667752b8d83 100644 --- a/test/run/ok/char-low-surrogate-trap.run.ok +++ b/test/run/ok/char-low-surrogate-trap.run.ok @@ -1 +1 @@ -prelude:___: execution error, character value out of bounds +prim:___: execution error, character value out of bounds diff --git a/test/run/ok/char-trap.run-ir.ok b/test/run/ok/char-trap.run-ir.ok index fe3a4aa9bb4..667752b8d83 100644 --- a/test/run/ok/char-trap.run-ir.ok +++ b/test/run/ok/char-trap.run-ir.ok @@ -1 +1 @@ -prelude:___: execution error, character value out of bounds +prim:___: execution error, character value out of bounds diff --git a/test/run/ok/char-trap.run-low.ok b/test/run/ok/char-trap.run-low.ok index fe3a4aa9bb4..667752b8d83 100644 --- a/test/run/ok/char-trap.run-low.ok +++ b/test/run/ok/char-trap.run-low.ok @@ -1 +1 @@ -prelude:___: execution error, character value out of bounds +prim:___: execution error, character value out of bounds diff --git a/test/run/ok/char-trap.run.ok b/test/run/ok/char-trap.run.ok index fe3a4aa9bb4..667752b8d83 100644 --- a/test/run/ok/char-trap.run.ok +++ b/test/run/ok/char-trap.run.ok @@ -1 +1 @@ -prelude:___: execution error, character value out of bounds +prim:___: execution error, character value out of bounds diff --git a/test/run/ok/idlHash.run-ir.ok b/test/run/ok/idlHash.run-ir.ok index 4eb46c64984..eefe13e92ac 100644 --- a/test/run/ok/idlHash.run-ir.ok +++ b/test/run/ok/idlHash.run-ir.ok @@ -1,15 +1,15 @@ Hash for -Expected: 0 -Actual: 0 +Expected: 0x0 +Actual: 0x0 Hash for id -Expected: 23_515 -Actual: 23_515 +Expected: 0x5BDB +Actual: 0x5BDB Hash for description -Expected: 1_595_738_364 -Actual: 1_595_738_364 +Expected: 0x5F1D_08FC +Actual: 0x5F1D_08FC Hash for short_name -Expected: 3_261_810_734 -Actual: 3_261_810_734 +Expected: 0xC26B_482E +Actual: 0xC26B_482E Hash for Hi ☃ -Expected: 1_419_229_646 -Actual: 1_419_229_646 +Expected: 0x5497_B9CE +Actual: 0x5497_B9CE diff --git a/test/run/ok/idlHash.run-low.ok b/test/run/ok/idlHash.run-low.ok index 4eb46c64984..eefe13e92ac 100644 --- a/test/run/ok/idlHash.run-low.ok +++ b/test/run/ok/idlHash.run-low.ok @@ -1,15 +1,15 @@ Hash for -Expected: 0 -Actual: 0 +Expected: 0x0 +Actual: 0x0 Hash for id -Expected: 23_515 -Actual: 23_515 +Expected: 0x5BDB +Actual: 0x5BDB Hash for description -Expected: 1_595_738_364 -Actual: 1_595_738_364 +Expected: 0x5F1D_08FC +Actual: 0x5F1D_08FC Hash for short_name -Expected: 3_261_810_734 -Actual: 3_261_810_734 +Expected: 0xC26B_482E +Actual: 0xC26B_482E Hash for Hi ☃ -Expected: 1_419_229_646 -Actual: 1_419_229_646 +Expected: 0x5497_B9CE +Actual: 0x5497_B9CE diff --git a/test/run/ok/idlHash.run.ok b/test/run/ok/idlHash.run.ok index 4eb46c64984..eefe13e92ac 100644 --- a/test/run/ok/idlHash.run.ok +++ b/test/run/ok/idlHash.run.ok @@ -1,15 +1,15 @@ Hash for -Expected: 0 -Actual: 0 +Expected: 0x0 +Actual: 0x0 Hash for id -Expected: 23_515 -Actual: 23_515 +Expected: 0x5BDB +Actual: 0x5BDB Hash for description -Expected: 1_595_738_364 -Actual: 1_595_738_364 +Expected: 0x5F1D_08FC +Actual: 0x5F1D_08FC Hash for short_name -Expected: 3_261_810_734 -Actual: 3_261_810_734 +Expected: 0xC26B_482E +Actual: 0xC26B_482E Hash for Hi ☃ -Expected: 1_419_229_646 -Actual: 1_419_229_646 +Expected: 0x5497_B9CE +Actual: 0x5497_B9CE diff --git a/test/run/ok/objects1.comp.ok b/test/run/ok/objects1.comp.ok index 8a83a4aca71..8da0a1addee 100644 --- a/test/run/ok/objects1.comp.ok +++ b/test/run/ok/objects1.comp.ok @@ -1,2 +1,2 @@ -objects1.mo:22.3-22.26: warning, this case is never reached -objects1.mo:23.3-23.14: warning, this case is never reached +objects1.mo:23.3-23.26: warning, this case is never reached +objects1.mo:24.3-24.14: warning, this case is never reached diff --git a/test/run/ok/objects1.run-ir.ok b/test/run/ok/objects1.run-ir.ok index 8a83a4aca71..8da0a1addee 100644 --- a/test/run/ok/objects1.run-ir.ok +++ b/test/run/ok/objects1.run-ir.ok @@ -1,2 +1,2 @@ -objects1.mo:22.3-22.26: warning, this case is never reached -objects1.mo:23.3-23.14: warning, this case is never reached +objects1.mo:23.3-23.26: warning, this case is never reached +objects1.mo:24.3-24.14: warning, this case is never reached diff --git a/test/run/ok/objects1.run-low.ok b/test/run/ok/objects1.run-low.ok index 8a83a4aca71..8da0a1addee 100644 --- a/test/run/ok/objects1.run-low.ok +++ b/test/run/ok/objects1.run-low.ok @@ -1,2 +1,2 @@ -objects1.mo:22.3-22.26: warning, this case is never reached -objects1.mo:23.3-23.14: warning, this case is never reached +objects1.mo:23.3-23.26: warning, this case is never reached +objects1.mo:24.3-24.14: warning, this case is never reached diff --git a/test/run/ok/objects1.run.ok b/test/run/ok/objects1.run.ok index 8a83a4aca71..8da0a1addee 100644 --- a/test/run/ok/objects1.run.ok +++ b/test/run/ok/objects1.run.ok @@ -1,2 +1,2 @@ -objects1.mo:22.3-22.26: warning, this case is never reached -objects1.mo:23.3-23.14: warning, this case is never reached +objects1.mo:23.3-23.26: warning, this case is never reached +objects1.mo:24.3-24.14: warning, this case is never reached diff --git a/test/run/ok/objects1.tc.ok b/test/run/ok/objects1.tc.ok index 53be7fa8068..e046b261219 100644 --- a/test/run/ok/objects1.tc.ok +++ b/test/run/ok/objects1.tc.ok @@ -1,10 +1,10 @@ -objects1.mo:22.3-22.26: warning, this case is never reached -objects1.mo:23.3-23.14: warning, this case is never reached -objects1.mo:32.23-35.2: warning, the cases in this switch over type +objects1.mo:23.3-23.26: warning, this case is never reached +objects1.mo:24.3-24.14: warning, this case is never reached +objects1.mo:33.23-36.2: warning, the cases in this switch over type {a : Int; b : Nat} do not cover value {a = 0 or 1 or _; b = 0 or 1 or _) -objects1.mo:43.21-45.2: warning, the cases in this switch over type +objects1.mo:44.21-46.2: warning, the cases in this switch over type (Nat, Int, {c : Char; d : Text}) do not cover value (_, 0 or 1 or _, _) diff --git a/test/run/ok/type-inference.tc.ok b/test/run/ok/type-inference.tc.ok index a1077f043f0..84136688a73 100644 --- a/test/run/ok/type-inference.tc.ok +++ b/test/run/ok/type-inference.tc.ok @@ -1,37 +1,37 @@ -type-inference.mo:3.9-3.28: warning, this if has type Any because branches have inconsistent types, +type-inference.mo:5.9-5.28: warning, this if has type Any because branches have inconsistent types, true produces Bool false produces Nat -type-inference.mo:4.9-4.34: warning, this if has type Any because branches have inconsistent types, +type-inference.mo:6.9-6.34: warning, this if has type Any because branches have inconsistent types, true produces Bool false produces [var Nat] -type-inference.mo:5.9-5.27: warning, this if has type Any because branches have inconsistent types, +type-inference.mo:7.9-7.27: warning, this if has type Any because branches have inconsistent types, true produces Nat false produces Float -type-inference.mo:6.9-6.29: warning, this if has type Any because branches have inconsistent types, +type-inference.mo:8.9-8.29: warning, this if has type Any because branches have inconsistent types, true produces () false produces {} -type-inference.mo:11.33-11.41: warning, the switch has type Any because branches have inconsistent types, +type-inference.mo:13.33-13.41: warning, the switch has type Any because branches have inconsistent types, this case produces type Bool the previous produce type Nat -type-inference.mo:12.33-12.47: warning, the switch has type Any because branches have inconsistent types, +type-inference.mo:14.33-14.47: warning, the switch has type Any because branches have inconsistent types, this case produces type Bool the previous produce type [var Nat] -type-inference.mo:13.43-13.56: warning, the switch has type Any because branches have inconsistent types, +type-inference.mo:15.43-15.56: warning, the switch has type Any because branches have inconsistent types, this case produces type Int the previous produce type Text -type-inference.mo:19.9-19.18: warning, this array has type [Any] because elements have inconsistent types -type-inference.mo:20.9-20.24: warning, this array has type [Any] because elements have inconsistent types +type-inference.mo:21.9-21.18: warning, this array has type [Any] because elements have inconsistent types +type-inference.mo:22.9-22.24: warning, this array has type [Any] because elements have inconsistent types diff --git a/test/run/print.mo b/test/run/print.mo index f30cb8444ee..89827d89f3f 100644 --- a/test/run/print.mo +++ b/test/run/print.mo @@ -1,2 +1,3 @@ -debugPrint("Hello World!"); -debugPrint("How are you?"); +import Prim "mo:prim"; +Prim.debugPrint("Hello World!"); +Prim.debugPrint("How are you?"); diff --git a/test/run/rts.mo b/test/run/rts.mo index 2debbe4ad6f..b98a7a56af5 100644 --- a/test/run/rts.mo +++ b/test/run/rts.mo @@ -1 +1,3 @@ -assert(rts_version() == "0.1"); +import Prim "mo:prim"; + +assert(Prim.rts_version() == "0.1"); diff --git a/test/run/show.mo b/test/run/show.mo index 13cc2532662..8984ef1ca84 100644 --- a/test/run/show.mo +++ b/test/run/show.mo @@ -1,37 +1,39 @@ -debugPrint(debug_show (true)); -debugPrint(debug_show (false)); -debugPrint(debug_show (-42000000000000)); -debugPrint(debug_show (-42000000)); -debugPrint(debug_show (-42000)); -debugPrint(debug_show (-42)); -debugPrint(debug_show (-0)); -debugPrint(debug_show (+0)); -debugPrint(debug_show (+42)); -debugPrint(debug_show (+42000)); -debugPrint(debug_show (+42000000)); -debugPrint(debug_show (+420000000000000)); -debugPrint(debug_show (0)); -debugPrint(debug_show (42)); -debugPrint(debug_show (42000)); -debugPrint(debug_show (42000000)); -debugPrint(debug_show (420000000000000)); -debugPrint(debug_show (42,-42,())); -debugPrint(debug_show ("Foobar", null, null, ?23)); -debugPrint(debug_show ([])); -debugPrint(debug_show ([1,2,3])); -debugPrint(debug_show ([var])); -debugPrint(debug_show ([var 1,2,3])); +import Prim "mo:prim"; + +Prim.debugPrint(debug_show (true)); +Prim.debugPrint(debug_show (false)); +Prim.debugPrint(debug_show (-42000000000000)); +Prim.debugPrint(debug_show (-42000000)); +Prim.debugPrint(debug_show (-42000)); +Prim.debugPrint(debug_show (-42)); +Prim.debugPrint(debug_show (-0)); +Prim.debugPrint(debug_show (+0)); +Prim.debugPrint(debug_show (+42)); +Prim.debugPrint(debug_show (+42000)); +Prim.debugPrint(debug_show (+42000000)); +Prim.debugPrint(debug_show (+420000000000000)); +Prim.debugPrint(debug_show (0)); +Prim.debugPrint(debug_show (42)); +Prim.debugPrint(debug_show (42000)); +Prim.debugPrint(debug_show (42000000)); +Prim.debugPrint(debug_show (420000000000000)); +Prim.debugPrint(debug_show (42,-42,())); +Prim.debugPrint(debug_show ("Foobar", null, null, ?23)); +Prim.debugPrint(debug_show ([])); +Prim.debugPrint(debug_show ([1,2,3])); +Prim.debugPrint(debug_show ([var])); +Prim.debugPrint(debug_show ([var 1,2,3])); class Foo() { public let foo : Int = 42; public var bar : Bool = true ; let hidden = [1,2] }; -debugPrint(debug_show (Foo())); -debugPrint(debug_show (#foo ())); -debugPrint(debug_show (#bar (1, 2))); -debugPrint(debug_show (#bar {})); -debugPrint(debug_show (#bar ([]))); -debugPrint(debug_show (#bar 42)); -debugPrint(debug_show (#bar (-42))); -debugPrint(debug_show (#foo 42 : {#foo : Int; #bar : Text})); -debugPrint(debug_show (42 : Word16)); -debugPrint(debug_show (42 : Nat8)); -debugPrint(debug_show (42 : Int32)); -debugPrint(debug_show (intToInt64 (-42))); -debugPrint(debug_show '☃'); +Prim.debugPrint(debug_show (Foo())); +Prim.debugPrint(debug_show (#foo ())); +Prim.debugPrint(debug_show (#bar (1, 2))); +Prim.debugPrint(debug_show (#bar {})); +Prim.debugPrint(debug_show (#bar ([]))); +Prim.debugPrint(debug_show (#bar 42)); +Prim.debugPrint(debug_show (#bar (-42))); +Prim.debugPrint(debug_show (#foo 42 : {#foo : Int; #bar : Text})); +Prim.debugPrint(debug_show (42 : Word16)); +Prim.debugPrint(debug_show (42 : Nat8)); +Prim.debugPrint(debug_show (42 : Int32)); +Prim.debugPrint(debug_show (Prim.intToInt64 (-42))); +Prim.debugPrint(debug_show '☃'); diff --git a/test/run/text-iter.mo b/test/run/text-iter.mo index a26a4e74a18..eebdf8b5cd1 100644 --- a/test/run/text-iter.mo +++ b/test/run/text-iter.mo @@ -1,70 +1,72 @@ +import Prim "mo:prim" + let s = "hello " # "world!"; assert(s.len() == 12); -debugPrint "via `debugPrint`:"; -debugPrint s; -debugPrint ""; +Prim.debugPrint "via `debugPrint`:"; +Prim.debugPrint s; +Prim.debugPrint ""; -debugPrint "via iteration and `debugPrintChar`: #1"; +Prim.debugPrint "via iteration and `debugPrintChar`: #1"; for (a in s.chars()) { - debugPrintChar a; + Prim.debugPrintChar a; }; -debugPrint ""; +Prim.debugPrint ""; -debugPrint "via iteration and `debugPrintChar`: #2"; +Prim.debugPrint "via iteration and `debugPrintChar`: #2"; var x = 0; for (a in s.chars()) { x += 1; - debugPrintNat x; - debugPrint ":"; - debugPrintChar '\''; - debugPrintChar a; - debugPrintChar '\''; - debugPrint " "; + Prim.debugPrintNat x; + Prim.debugPrint ":"; + Prim.debugPrintChar '\''; + Prim.debugPrintChar a; + Prim.debugPrintChar '\''; + Prim.debugPrint " "; }; -debugPrint ""; +Prim.debugPrint ""; let russian = "Приветствую," # " мир!\n"; assert(russian.len() == 18); -debugPrint "via iteration and `debugPrintChar` (Unicode): #3"; +Prim.debugPrint "via iteration and `debugPrintChar` (Unicode): #3"; x := 0; for (a in russian.chars()) { x += 1; - debugPrintNat x; - debugPrint ":"; - debugPrintChar '\''; - debugPrintChar a; - debugPrintChar '\''; - debugPrint " "; + Prim.debugPrintNat x; + Prim.debugPrint ":"; + Prim.debugPrintChar '\''; + Prim.debugPrintChar a; + Prim.debugPrintChar '\''; + Prim.debugPrint " "; }; -debugPrint ""; +Prim.debugPrint ""; assert(x == 18); let emojis = "🙈🎸😋"; assert(emojis.len() == 3); -debugPrint "via iteration and `debugPrintChar` (Unicode): #4"; +Prim.debugPrint "via iteration and `debugPrintChar` (Unicode): #4"; x := 0; for (a in emojis.chars()) { x += 1; - debugPrintNat x; - debugPrint ":"; - debugPrintChar '\''; - debugPrintChar a; - debugPrintChar '\''; - debugPrint " "; + Prim.debugPrintNat x; + Prim.debugPrint ":"; + Prim.debugPrintChar '\''; + Prim.debugPrintChar a; + Prim.debugPrintChar '\''; + Prim.debugPrint " "; }; -debugPrint ""; +Prim.debugPrint ""; assert(x == 3); -debugPrint russian; debugPrint ""; +Prim.debugPrint russian; Prim.debugPrint ""; switch (russian.chars().next()) { - case (?c) { debugPrintChar c; debugPrint "" }; + case (?c) { Prim.debugPrintChar c; Prim.debugPrint "" }; case _ {}; }; switch (emojis.chars().next()) { - case (?c) { assert (c == '\u{1f648}'); debugPrintChar c; debugPrint "" }; + case (?c) { assert (c == '\u{1f648}'); Prim.debugPrintChar c; Prim.debugPrint "" }; case _ {}; }; diff --git a/test/run/type-inference.mo b/test/run/type-inference.mo index 26f434967a0..7ebed82d8f3 100644 --- a/test/run/type-inference.mo +++ b/test/run/type-inference.mo @@ -1,3 +1,5 @@ +import Prim "mo:prim"; + // Branch warnings. let _ = if true true else 5; @@ -103,40 +105,40 @@ func k(h : {#A; #B : Int} -> Int) : Int = h(#B 9); let _ = f(func x = x); let _ = f(func x = x + 1); -let _ = f(func x = abs(x + 1)); +let _ = f(func x = Prim.abs(x + 1)); let _ = f(func x = -1); -let _ = g(func p = abs(p.0)); +let _ = g(func p = Prim.abs(p.0)); let _ = g(func(x, y) = x + y); -let _ = g(func(x, y) = abs x); +let _ = g(func(x, y) = Prim.abs x); let _ = k(func(#A or #B _) = 0); let _ = f(func x : Int = x); let _ = f(func x : Int = x + 1); -let _ = f(func x : Nat = abs(x + 1)); +let _ = f(func x : Nat = Prim.abs(x + 1)); let _ = f(func x : Int = 0); -let _ = g(func p : Nat = abs(p.0)); +let _ = g(func p : Nat = Prim.abs(p.0)); let _ = g(func(x, y) : Int = x + y); -let _ = g(func(x, _) : Nat = abs x); +let _ = g(func(x, _) : Nat = Prim.abs x); let _ = k(func(#A or #B _) : Nat = 0); let _ = f(func(x : Int) : Int = x); let _ = f(func(x : Int) : Int = x + 1); -let _ = f(func(x : Int) : Nat = abs(x + 1)); +let _ = f(func(x : Int) : Nat = Prim.abs(x + 1)); let _ = f(func(x : Any) : Int = 0); -let _ = g(func(p : (Int, Any)) : Nat = abs(p.0)); +let _ = g(func(p : (Int, Any)) : Nat = Prim.abs(p.0)); let _ = g(func(x : Int, y : Int) : Int = x + y); -let _ = g(func(x : Int, _ : Any) : Nat = abs x); -let _ = g(func((x, _) : (Int, Any)) : Nat = abs x); +let _ = g(func(x : Int, _ : Any) : Nat = Prim.abs x); +let _ = g(func((x, _) : (Int, Any)) : Nat = Prim.abs x); let _ = k(func(#A or #B (_ : Any)) : Nat = 0); let _ = k(func((#A or #B _) : {#A; #B : Any}) : Nat = 0); let _ = f(func<>(x : Int) : Int = x); let _ = f(func<>(x : Int) : Int = x + 1); -let _ = f(func<>(x : Int) : Nat = abs(x + 1)); +let _ = f(func<>(x : Int) : Nat = Prim.abs(x + 1)); let _ = f(func<>(x : Any) : Int = 0); -let _ = g(func<>(p : (Int, Any)) : Nat = abs(p.0)); +let _ = g(func<>(p : (Int, Any)) : Nat = Prim.abs(p.0)); let _ = g(func<>(x : Int, y : Int) : Int = x + y); -let _ = g(func<>(x : Int, y : Any) : Nat = abs x); -let _ = g(func<>((x, _) : (Int, Any)) : Nat = abs x); +let _ = g(func<>(x : Int, y : Any) : Nat = Prim.abs x); +let _ = g(func<>((x, _) : (Int, Any)) : Nat = Prim.abs x); let _ = k(func<>(#A or #B (_ : Any)) : Nat = 0); let _ = k(func<>((#A or #B _) : {#A; #B : Any}) : Nat = 0); diff --git a/test/run/variants.mo b/test/run/variants.mo index f9181a06970..972bd79cacc 100644 --- a/test/run/variants.mo +++ b/test/run/variants.mo @@ -1,3 +1,5 @@ +import Prim "mo:prim"; + type Tree = {#leaf : A; #branch : (Tree, Tree)}; func size(t : Tree) : Nat { @@ -10,8 +12,8 @@ func size(t : Tree) : Nat { let tt1 : Tree = #branch(#leaf 1, #leaf (-1)); let tt2 = #leaf ""; // infers type {#leaf : Text} which is a subtype of Tree -debugPrintNat(size(tt1)); -debugPrintNat(size(tt2)); +Prim.debugPrintNat(size(tt1)); +Prim.debugPrintNat(size(tt2)); // subtyping diff --git a/test/run/words.mo b/test/run/words.mo index 899742ec0b5..e06575656c2 100644 --- a/test/run/words.mo +++ b/test/run/words.mo @@ -1,6 +1,8 @@ +import Prim "mo:prim"; + // CHECK: func $start -func printBit(a : Bool) { debugPrint(if a "set" else "clear") }; +func printBit(a : Bool) { Prim.debugPrint(if a "set" else "clear") }; func checkpointAlpha() {}; @@ -16,7 +18,11 @@ func checkpointJuliett() {}; // Word64 operations { - func printW64ln(w : Word64) { debugPrintNat(word64ToNat w); debugPrint " "; debugPrintInt(word64ToInt w) }; + func printW64ln(w : Word64) { + Prim.debugPrintNat(Prim.word64ToNat w); + Prim.debugPrint " "; + Prim.debugPrintInt(Prim.word64ToInt w) + }; let a : Word64 = 4567; let b : Word64 = 7; @@ -54,12 +60,12 @@ func checkpointJuliett() {}; printW64ln(-5225319197819536385 +>> 4); // 0b1011011101111011111011111101111111011111111011111111101111111111L == -5225319197819536385L --> -326582449863721025L printW64ln(c <<> b); printW64ln(c <>> b); - printW64ln(popcntWord64 d); // -15 = 0xfffffffffffffff1 = 0b1111_..._1111_1111_0001 (population = 61) - printW64ln(clzWord64 e); // 20000 = 0x0000000000004e20 (leading zeros = 49) - printW64ln(ctzWord64 e); // 20000 = 0x0000000000004e20 (trailing zeros = 5) - printBit(btstWord64(e, 5 : Word64)); // 20000 = 0x0000000000004e20 (result = true) - printBit(btstWord64(e, 63 : Word64)); // 20000 = 0x0000000000004e20 (result = false) - printBit(btstWord64(e, 69 : Word64)); // 20000 = 0x0000000000004e20 (mod 64, result = true) + printW64ln(Prim.popcntWord64 d); // -15 = 0xfffffffffffffff1 = 0b1111_..._1111_1111_0001 (population = 61) + printW64ln(Prim.clzWord64 e); // 20000 = 0x0000000000004e20 (leading zeros = 49) + printW64ln(Prim.ctzWord64 e); // 20000 = 0x0000000000004e20 (trailing zeros = 5) + printBit(Prim.btstWord64(e, 5 : Word64)); // 20000 = 0x0000000000004e20 (result = true) + printBit(Prim.btstWord64(e, 63 : Word64)); // 20000 = 0x0000000000004e20 (result = false) + printBit(Prim.btstWord64(e, 69 : Word64)); // 20000 = 0x0000000000004e20 (mod 64, result = true) assert (3 : Word64 ** (4 : Word64) == (81 : Word64)); assert (3 : Word64 ** (7 : Word64) == (2187 : Word64)); @@ -71,7 +77,11 @@ func checkpointJuliett() {}; // Word32 operations { - func printW32ln(w : Word32) { debugPrintNat(word32ToNat w); debugPrint " "; debugPrintInt(word32ToInt w) }; + func printW32ln(w : Word32) { + Prim.debugPrintNat(Prim.word32ToNat w); + Prim.debugPrint " "; + Prim.debugPrintInt(Prim.word32ToInt w) + }; let a : Word32 = 4567; let b : Word32 = 7; @@ -110,12 +120,12 @@ func checkpointJuliett() {}; printW32ln(-1216614433 +>> 4); // 0b10110111011110111110111111011111l == -1216614433l --> -76038403 printW32ln(c <<> b); printW32ln(c <>> b); - printW32ln(popcntWord32 d); // -15 = 0xfffffff1 = 0b1111_1111_1111_1111_1111_1111_1111_0001 (population = 29) - printW32ln(clzWord32 e); // 20000 = 0x00004e20 (leading zeros = 17) - printW32ln(ctzWord32 e); // 20000 = 0x00004e20 (trailing zeros = 5) - printBit(btstWord32(e, 5 : Word32)); // 20000 = 0x00004e20 (result = true) - printBit(btstWord32(e, 31 : Word32)); // 20000 = 0x00004e20 (result = false) - printBit(btstWord32(e, 37 : Word32)); // 20000 = 0x00004e20 (mod 32, result = true) + printW32ln(Prim.popcntWord32 d); // -15 = 0xfffffff1 = 0b1111_1111_1111_1111_1111_1111_1111_0001 (population = 29) + printW32ln(Prim.clzWord32 e); // 20000 = 0x00004e20 (leading zeros = 17) + printW32ln(Prim.ctzWord32 e); // 20000 = 0x00004e20 (trailing zeros = 5) + printBit(Prim.btstWord32(e, 5 : Word32)); // 20000 = 0x00004e20 (result = true) + printBit(Prim.btstWord32(e, 31 : Word32)); // 20000 = 0x00004e20 (result = false) + printBit(Prim.btstWord32(e, 37 : Word32)); // 20000 = 0x00004e20 (mod 32, result = true) assert (3 : Word32 ** (4 : Word32) == (81 : Word32)); assert (3 : Word32 ** (7 : Word32) == (2187 : Word32)); @@ -125,7 +135,11 @@ func checkpointJuliett() {}; // Word16 operations { - func printW16ln(w : Word16) { debugPrintNat(word16ToNat w); debugPrint " "; debugPrintInt(word16ToInt w) }; + func printW16ln(w : Word16) { + Prim.debugPrintNat(Prim.word16ToNat w); + Prim.debugPrint " "; + Prim.debugPrintInt(Prim.word16ToInt w) + }; let a : Word16 = 4567; let b : Word16 = 7; @@ -189,12 +203,12 @@ func checkpointJuliett() {}; // CHECK-NEXT: call $rotr // CHECK-NEXT: call $printW16ln printW16ln(c <>> b); - printW16ln(popcntWord16 d); // -15 = 0xfff1 = 0b1111_1111_1111_0001 (population = 13) - printW16ln(clzWord16 e); // 20000 = 0x4e20 (leading zeros = 1) - printW16ln(ctzWord16 e); // 20000 = 0x4e20 (trailing zeros = 5) - printBit(btstWord16(e, 5 : Word16)); // 20000 = 0x4e20 (result = true) - printBit(btstWord16(e, 15 : Word16)); // 20000 = 0x4e20 (result = false) - printBit(btstWord16(e, 21 : Word16)); // 20000 = 0x4e20 (mod 16, result = true) + printW16ln(Prim.popcntWord16 d); // -15 = 0xfff1 = 0b1111_1111_1111_0001 (population = 13) + printW16ln(Prim.clzWord16 e); // 20000 = 0x4e20 (leading zeros = 1) + printW16ln(Prim.ctzWord16 e); // 20000 = 0x4e20 (trailing zeros = 5) + printBit(Prim.btstWord16(e, 5 : Word16)); // 20000 = 0x4e20 (result = true) + printBit(Prim.btstWord16(e, 15 : Word16)); // 20000 = 0x4e20 (result = false) + printBit(Prim.btstWord16(e, 21 : Word16)); // 20000 = 0x4e20 (mod 16, result = true) assert (3 : Word16 ** (0 : Word16) == (1 : Word16)); @@ -205,7 +219,11 @@ func checkpointJuliett() {}; // Word8 operations { - func printW8ln(w : Word8) { debugPrintNat(word8ToNat w); debugPrint " "; debugPrintInt(word8ToInt w) }; + func printW8ln(w : Word8) { + Prim.debugPrintNat(Prim.word8ToNat w); + Prim.debugPrint " "; + Prim.debugPrintInt(Prim.word8ToInt w) + }; let a : Word8 = 67; let b : Word8 = 7; @@ -264,12 +282,12 @@ func checkpointJuliett() {}; // CHECK-NEXT: call $rotr // CHECK-NEXT: call $printW8ln printW8ln(c <>> b); - printW8ln(popcntWord8 d); // -15 = 0xf1 = 0b1111_0001 (population = 5) - printW8ln(clzWord8 e); // 200 = 0xC8 (leading zeros = 0) - printW8ln(ctzWord8 e); // 200 = 0xC8 (trailing zeros = 3) - printBit(btstWord8(e, 3 : Word8)); // 200 = 0xC8 (result = true) - printBit(btstWord8(e, 5 : Word8)); // 200 = 0xC8 (result = false) - printBit(btstWord8(e, 11 : Word8)); // 200 = 0xC8 (mod 8, result = true) + printW8ln(Prim.popcntWord8 d); // -15 = 0xf1 = 0b1111_0001 (population = 5) + printW8ln(Prim.clzWord8 e); // 200 = 0xC8 (leading zeros = 0) + printW8ln(Prim.ctzWord8 e); // 200 = 0xC8 (trailing zeros = 3) + printBit(Prim.btstWord8(e, 3 : Word8)); // 200 = 0xC8 (result = true) + printBit(Prim.btstWord8(e, 5 : Word8)); // 200 = 0xC8 (result = false) + printBit(Prim.btstWord8(e, 11 : Word8)); // 200 = 0xC8 (mod 8, result = true) assert (3 : Word8 ** (0 : Word8) == (1 : Word8)); assert (3 : Word8 ** (3 : Word8) == (27 : Word8)); diff --git a/test/trap/divInt16.mo b/test/trap/divInt16.mo index e94d269c0b6..b4c5b9dcb87 100644 --- a/test/trap/divInt16.mo +++ b/test/trap/divInt16.mo @@ -1 +1,2 @@ -let _ = intToInt16 (-32768) / (-1 : Int16) +import Prim "mo:prim"; +let _ = Prim.intToInt16 (-32768) / (-1 : Int16) diff --git a/test/trap/divInt32.mo b/test/trap/divInt32.mo index 5fbace59270..ace57d8c4c9 100644 --- a/test/trap/divInt32.mo +++ b/test/trap/divInt32.mo @@ -1 +1,2 @@ -let _ = intToInt32 (-0x80000000) / (-1 : Int32) +import Prim "mo:prim"; +let _ = Prim.intToInt32 (-0x80000000) / (-1 : Int32) diff --git a/test/trap/divInt64.mo b/test/trap/divInt64.mo index 603c31ff26b..ced0a720534 100644 --- a/test/trap/divInt64.mo +++ b/test/trap/divInt64.mo @@ -1 +1,2 @@ -let _ = intToInt64 (-0x8000000000000000) / (-1 : Int64) +import Prim "mo:prim"; +let _ = Prim.intToInt64 (-0x8000000000000000) / (-1 : Int64) diff --git a/test/trap/divInt8.mo b/test/trap/divInt8.mo index 4202c0c43df..0b741771b10 100644 --- a/test/trap/divInt8.mo +++ b/test/trap/divInt8.mo @@ -1 +1,2 @@ -let _ = intToInt8 (-128) / (-1 : Int8) +import Prim "mo:prim"; +let _ = Prim.intToInt8 (-128) / (-1 : Int8) diff --git a/test/trap/ok/divInt16.run-ir.ok b/test/trap/ok/divInt16.run-ir.ok index d7f65b77c81..8f37815b570 100644 --- a/test/trap/ok/divInt16.run-ir.ok +++ b/test/trap/ok/divInt16.run-ir.ok @@ -1 +1 @@ -divInt16.mo:1.9-1.43: execution error, arithmetic overflow +divInt16.mo:2.9-2.48: execution error, arithmetic overflow diff --git a/test/trap/ok/divInt16.run-low.ok b/test/trap/ok/divInt16.run-low.ok index d7f65b77c81..8f37815b570 100644 --- a/test/trap/ok/divInt16.run-low.ok +++ b/test/trap/ok/divInt16.run-low.ok @@ -1 +1 @@ -divInt16.mo:1.9-1.43: execution error, arithmetic overflow +divInt16.mo:2.9-2.48: execution error, arithmetic overflow diff --git a/test/trap/ok/divInt16.run.ok b/test/trap/ok/divInt16.run.ok index d7f65b77c81..8f37815b570 100644 --- a/test/trap/ok/divInt16.run.ok +++ b/test/trap/ok/divInt16.run.ok @@ -1 +1 @@ -divInt16.mo:1.9-1.43: execution error, arithmetic overflow +divInt16.mo:2.9-2.48: execution error, arithmetic overflow diff --git a/test/trap/ok/divInt32.run-ir.ok b/test/trap/ok/divInt32.run-ir.ok index 0f006e8e76c..a22bc719adc 100644 --- a/test/trap/ok/divInt32.run-ir.ok +++ b/test/trap/ok/divInt32.run-ir.ok @@ -1 +1 @@ -divInt32.mo:1.9-1.48: execution error, arithmetic overflow +divInt32.mo:2.9-2.53: execution error, arithmetic overflow diff --git a/test/trap/ok/divInt32.run-low.ok b/test/trap/ok/divInt32.run-low.ok index 0f006e8e76c..a22bc719adc 100644 --- a/test/trap/ok/divInt32.run-low.ok +++ b/test/trap/ok/divInt32.run-low.ok @@ -1 +1 @@ -divInt32.mo:1.9-1.48: execution error, arithmetic overflow +divInt32.mo:2.9-2.53: execution error, arithmetic overflow diff --git a/test/trap/ok/divInt32.run.ok b/test/trap/ok/divInt32.run.ok index 0f006e8e76c..a22bc719adc 100644 --- a/test/trap/ok/divInt32.run.ok +++ b/test/trap/ok/divInt32.run.ok @@ -1 +1 @@ -divInt32.mo:1.9-1.48: execution error, arithmetic overflow +divInt32.mo:2.9-2.53: execution error, arithmetic overflow diff --git a/test/trap/ok/divInt64.run-ir.ok b/test/trap/ok/divInt64.run-ir.ok index 25e8067c48b..b3a8b446873 100644 --- a/test/trap/ok/divInt64.run-ir.ok +++ b/test/trap/ok/divInt64.run-ir.ok @@ -1 +1 @@ -divInt64.mo:1.9-1.56: execution error, arithmetic overflow +divInt64.mo:2.9-2.61: execution error, arithmetic overflow diff --git a/test/trap/ok/divInt64.run-low.ok b/test/trap/ok/divInt64.run-low.ok index 25e8067c48b..b3a8b446873 100644 --- a/test/trap/ok/divInt64.run-low.ok +++ b/test/trap/ok/divInt64.run-low.ok @@ -1 +1 @@ -divInt64.mo:1.9-1.56: execution error, arithmetic overflow +divInt64.mo:2.9-2.61: execution error, arithmetic overflow diff --git a/test/trap/ok/divInt64.run.ok b/test/trap/ok/divInt64.run.ok index 25e8067c48b..b3a8b446873 100644 --- a/test/trap/ok/divInt64.run.ok +++ b/test/trap/ok/divInt64.run.ok @@ -1 +1 @@ -divInt64.mo:1.9-1.56: execution error, arithmetic overflow +divInt64.mo:2.9-2.61: execution error, arithmetic overflow diff --git a/test/trap/ok/divInt8.run-ir.ok b/test/trap/ok/divInt8.run-ir.ok index 5252362a667..78d2d8feea9 100644 --- a/test/trap/ok/divInt8.run-ir.ok +++ b/test/trap/ok/divInt8.run-ir.ok @@ -1 +1 @@ -divInt8.mo:1.9-1.39: execution error, arithmetic overflow +divInt8.mo:2.9-2.44: execution error, arithmetic overflow diff --git a/test/trap/ok/divInt8.run-low.ok b/test/trap/ok/divInt8.run-low.ok index 5252362a667..78d2d8feea9 100644 --- a/test/trap/ok/divInt8.run-low.ok +++ b/test/trap/ok/divInt8.run-low.ok @@ -1 +1 @@ -divInt8.mo:1.9-1.39: execution error, arithmetic overflow +divInt8.mo:2.9-2.44: execution error, arithmetic overflow diff --git a/test/trap/ok/divInt8.run.ok b/test/trap/ok/divInt8.run.ok index 5252362a667..78d2d8feea9 100644 --- a/test/trap/ok/divInt8.run.ok +++ b/test/trap/ok/divInt8.run.ok @@ -1 +1 @@ -divInt8.mo:1.9-1.39: execution error, arithmetic overflow +divInt8.mo:2.9-2.44: execution error, arithmetic overflow diff --git a/test/trap/ok/outrange-int16-lower.run-ir.ok b/test/trap/ok/outrange-int16-lower.run-ir.ok index 0356664e3e0..c528d8b4c4e 100644 --- a/test/trap/ok/outrange-int16-lower.run-ir.ok +++ b/test/trap/ok/outrange-int16-lower.run-ir.ok @@ -1 +1 @@ -prelude:___: execution error, numeric overflow +prim:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int16-lower.run-low.ok b/test/trap/ok/outrange-int16-lower.run-low.ok index 0356664e3e0..c528d8b4c4e 100644 --- a/test/trap/ok/outrange-int16-lower.run-low.ok +++ b/test/trap/ok/outrange-int16-lower.run-low.ok @@ -1 +1 @@ -prelude:___: execution error, numeric overflow +prim:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int16-lower.run.ok b/test/trap/ok/outrange-int16-lower.run.ok index 0356664e3e0..c528d8b4c4e 100644 --- a/test/trap/ok/outrange-int16-lower.run.ok +++ b/test/trap/ok/outrange-int16-lower.run.ok @@ -1 +1 @@ -prelude:___: execution error, numeric overflow +prim:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int16-negation.run-ir.ok b/test/trap/ok/outrange-int16-negation.run-ir.ok index 853ee28f05a..fcccaa926fb 100644 --- a/test/trap/ok/outrange-int16-negation.run-ir.ok +++ b/test/trap/ok/outrange-int16-negation.run-ir.ok @@ -1 +1 @@ -outrange-int16-negation.mo:1.9-1.33: execution error, value out of bounds +outrange-int16-negation.mo:2.9-2.38: execution error, value out of bounds diff --git a/test/trap/ok/outrange-int16-negation.run-low.ok b/test/trap/ok/outrange-int16-negation.run-low.ok index 853ee28f05a..fcccaa926fb 100644 --- a/test/trap/ok/outrange-int16-negation.run-low.ok +++ b/test/trap/ok/outrange-int16-negation.run-low.ok @@ -1 +1 @@ -outrange-int16-negation.mo:1.9-1.33: execution error, value out of bounds +outrange-int16-negation.mo:2.9-2.38: execution error, value out of bounds diff --git a/test/trap/ok/outrange-int16-negation.run.ok b/test/trap/ok/outrange-int16-negation.run.ok index 853ee28f05a..fcccaa926fb 100644 --- a/test/trap/ok/outrange-int16-negation.run.ok +++ b/test/trap/ok/outrange-int16-negation.run.ok @@ -1 +1 @@ -outrange-int16-negation.mo:1.9-1.33: execution error, value out of bounds +outrange-int16-negation.mo:2.9-2.38: execution error, value out of bounds diff --git a/test/trap/ok/outrange-int16-upper.run-ir.ok b/test/trap/ok/outrange-int16-upper.run-ir.ok index 0356664e3e0..c528d8b4c4e 100644 --- a/test/trap/ok/outrange-int16-upper.run-ir.ok +++ b/test/trap/ok/outrange-int16-upper.run-ir.ok @@ -1 +1 @@ -prelude:___: execution error, numeric overflow +prim:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int16-upper.run-low.ok b/test/trap/ok/outrange-int16-upper.run-low.ok index 0356664e3e0..c528d8b4c4e 100644 --- a/test/trap/ok/outrange-int16-upper.run-low.ok +++ b/test/trap/ok/outrange-int16-upper.run-low.ok @@ -1 +1 @@ -prelude:___: execution error, numeric overflow +prim:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int16-upper.run.ok b/test/trap/ok/outrange-int16-upper.run.ok index 0356664e3e0..c528d8b4c4e 100644 --- a/test/trap/ok/outrange-int16-upper.run.ok +++ b/test/trap/ok/outrange-int16-upper.run.ok @@ -1 +1 @@ -prelude:___: execution error, numeric overflow +prim:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int32-lower.run-ir.ok b/test/trap/ok/outrange-int32-lower.run-ir.ok index 0356664e3e0..c528d8b4c4e 100644 --- a/test/trap/ok/outrange-int32-lower.run-ir.ok +++ b/test/trap/ok/outrange-int32-lower.run-ir.ok @@ -1 +1 @@ -prelude:___: execution error, numeric overflow +prim:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int32-lower.run-low.ok b/test/trap/ok/outrange-int32-lower.run-low.ok index 0356664e3e0..c528d8b4c4e 100644 --- a/test/trap/ok/outrange-int32-lower.run-low.ok +++ b/test/trap/ok/outrange-int32-lower.run-low.ok @@ -1 +1 @@ -prelude:___: execution error, numeric overflow +prim:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int32-lower.run.ok b/test/trap/ok/outrange-int32-lower.run.ok index 0356664e3e0..c528d8b4c4e 100644 --- a/test/trap/ok/outrange-int32-lower.run.ok +++ b/test/trap/ok/outrange-int32-lower.run.ok @@ -1 +1 @@ -prelude:___: execution error, numeric overflow +prim:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int32-negation.run-ir.ok b/test/trap/ok/outrange-int32-negation.run-ir.ok index 792f81de9e7..08f0e48b1b8 100644 --- a/test/trap/ok/outrange-int32-negation.run-ir.ok +++ b/test/trap/ok/outrange-int32-negation.run-ir.ok @@ -1 +1 @@ -outrange-int32-negation.mo:1.9-1.33: execution error, value out of bounds +outrange-int32-negation.mo:2.9-2.38: execution error, value out of bounds diff --git a/test/trap/ok/outrange-int32-negation.run-low.ok b/test/trap/ok/outrange-int32-negation.run-low.ok index 792f81de9e7..08f0e48b1b8 100644 --- a/test/trap/ok/outrange-int32-negation.run-low.ok +++ b/test/trap/ok/outrange-int32-negation.run-low.ok @@ -1 +1 @@ -outrange-int32-negation.mo:1.9-1.33: execution error, value out of bounds +outrange-int32-negation.mo:2.9-2.38: execution error, value out of bounds diff --git a/test/trap/ok/outrange-int32-negation.run.ok b/test/trap/ok/outrange-int32-negation.run.ok index 792f81de9e7..08f0e48b1b8 100644 --- a/test/trap/ok/outrange-int32-negation.run.ok +++ b/test/trap/ok/outrange-int32-negation.run.ok @@ -1 +1 @@ -outrange-int32-negation.mo:1.9-1.33: execution error, value out of bounds +outrange-int32-negation.mo:2.9-2.38: execution error, value out of bounds diff --git a/test/trap/ok/outrange-int32-upper.run-ir.ok b/test/trap/ok/outrange-int32-upper.run-ir.ok index 0356664e3e0..c528d8b4c4e 100644 --- a/test/trap/ok/outrange-int32-upper.run-ir.ok +++ b/test/trap/ok/outrange-int32-upper.run-ir.ok @@ -1 +1 @@ -prelude:___: execution error, numeric overflow +prim:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int32-upper.run-low.ok b/test/trap/ok/outrange-int32-upper.run-low.ok index 0356664e3e0..c528d8b4c4e 100644 --- a/test/trap/ok/outrange-int32-upper.run-low.ok +++ b/test/trap/ok/outrange-int32-upper.run-low.ok @@ -1 +1 @@ -prelude:___: execution error, numeric overflow +prim:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int32-upper.run.ok b/test/trap/ok/outrange-int32-upper.run.ok index 0356664e3e0..c528d8b4c4e 100644 --- a/test/trap/ok/outrange-int32-upper.run.ok +++ b/test/trap/ok/outrange-int32-upper.run.ok @@ -1 +1 @@ -prelude:___: execution error, numeric overflow +prim:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int64-lower.run-ir.ok b/test/trap/ok/outrange-int64-lower.run-ir.ok index 0356664e3e0..c528d8b4c4e 100644 --- a/test/trap/ok/outrange-int64-lower.run-ir.ok +++ b/test/trap/ok/outrange-int64-lower.run-ir.ok @@ -1 +1 @@ -prelude:___: execution error, numeric overflow +prim:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int64-lower.run-low.ok b/test/trap/ok/outrange-int64-lower.run-low.ok index 0356664e3e0..c528d8b4c4e 100644 --- a/test/trap/ok/outrange-int64-lower.run-low.ok +++ b/test/trap/ok/outrange-int64-lower.run-low.ok @@ -1 +1 @@ -prelude:___: execution error, numeric overflow +prim:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int64-lower.run.ok b/test/trap/ok/outrange-int64-lower.run.ok index 0356664e3e0..c528d8b4c4e 100644 --- a/test/trap/ok/outrange-int64-lower.run.ok +++ b/test/trap/ok/outrange-int64-lower.run.ok @@ -1 +1 @@ -prelude:___: execution error, numeric overflow +prim:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int64-negation.run-ir.ok b/test/trap/ok/outrange-int64-negation.run-ir.ok index 45f6894b18d..b6883ff3e8f 100644 --- a/test/trap/ok/outrange-int64-negation.run-ir.ok +++ b/test/trap/ok/outrange-int64-negation.run-ir.ok @@ -1 +1 @@ -outrange-int64-negation.mo:1.9-1.33: execution error, value out of bounds +outrange-int64-negation.mo:2.9-2.38: execution error, value out of bounds diff --git a/test/trap/ok/outrange-int64-negation.run-low.ok b/test/trap/ok/outrange-int64-negation.run-low.ok index 45f6894b18d..b6883ff3e8f 100644 --- a/test/trap/ok/outrange-int64-negation.run-low.ok +++ b/test/trap/ok/outrange-int64-negation.run-low.ok @@ -1 +1 @@ -outrange-int64-negation.mo:1.9-1.33: execution error, value out of bounds +outrange-int64-negation.mo:2.9-2.38: execution error, value out of bounds diff --git a/test/trap/ok/outrange-int64-negation.run.ok b/test/trap/ok/outrange-int64-negation.run.ok index 45f6894b18d..b6883ff3e8f 100644 --- a/test/trap/ok/outrange-int64-negation.run.ok +++ b/test/trap/ok/outrange-int64-negation.run.ok @@ -1 +1 @@ -outrange-int64-negation.mo:1.9-1.33: execution error, value out of bounds +outrange-int64-negation.mo:2.9-2.38: execution error, value out of bounds diff --git a/test/trap/ok/outrange-int64-upper.run-ir.ok b/test/trap/ok/outrange-int64-upper.run-ir.ok index 0356664e3e0..c528d8b4c4e 100644 --- a/test/trap/ok/outrange-int64-upper.run-ir.ok +++ b/test/trap/ok/outrange-int64-upper.run-ir.ok @@ -1 +1 @@ -prelude:___: execution error, numeric overflow +prim:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int64-upper.run-low.ok b/test/trap/ok/outrange-int64-upper.run-low.ok index 0356664e3e0..c528d8b4c4e 100644 --- a/test/trap/ok/outrange-int64-upper.run-low.ok +++ b/test/trap/ok/outrange-int64-upper.run-low.ok @@ -1 +1 @@ -prelude:___: execution error, numeric overflow +prim:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int64-upper.run.ok b/test/trap/ok/outrange-int64-upper.run.ok index 0356664e3e0..c528d8b4c4e 100644 --- a/test/trap/ok/outrange-int64-upper.run.ok +++ b/test/trap/ok/outrange-int64-upper.run.ok @@ -1 +1 @@ -prelude:___: execution error, numeric overflow +prim:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int8-lower.run-ir.ok b/test/trap/ok/outrange-int8-lower.run-ir.ok index 0356664e3e0..c528d8b4c4e 100644 --- a/test/trap/ok/outrange-int8-lower.run-ir.ok +++ b/test/trap/ok/outrange-int8-lower.run-ir.ok @@ -1 +1 @@ -prelude:___: execution error, numeric overflow +prim:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int8-lower.run-low.ok b/test/trap/ok/outrange-int8-lower.run-low.ok index 0356664e3e0..c528d8b4c4e 100644 --- a/test/trap/ok/outrange-int8-lower.run-low.ok +++ b/test/trap/ok/outrange-int8-lower.run-low.ok @@ -1 +1 @@ -prelude:___: execution error, numeric overflow +prim:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int8-lower.run.ok b/test/trap/ok/outrange-int8-lower.run.ok index 0356664e3e0..c528d8b4c4e 100644 --- a/test/trap/ok/outrange-int8-lower.run.ok +++ b/test/trap/ok/outrange-int8-lower.run.ok @@ -1 +1 @@ -prelude:___: execution error, numeric overflow +prim:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int8-negation.run-ir.ok b/test/trap/ok/outrange-int8-negation.run-ir.ok index 17851ac1bc7..c81975d1bdc 100644 --- a/test/trap/ok/outrange-int8-negation.run-ir.ok +++ b/test/trap/ok/outrange-int8-negation.run-ir.ok @@ -1 +1 @@ -outrange-int8-negation.mo:1.9-1.31: execution error, value out of bounds +outrange-int8-negation.mo:2.9-2.36: execution error, value out of bounds diff --git a/test/trap/ok/outrange-int8-negation.run-low.ok b/test/trap/ok/outrange-int8-negation.run-low.ok index 17851ac1bc7..c81975d1bdc 100644 --- a/test/trap/ok/outrange-int8-negation.run-low.ok +++ b/test/trap/ok/outrange-int8-negation.run-low.ok @@ -1 +1 @@ -outrange-int8-negation.mo:1.9-1.31: execution error, value out of bounds +outrange-int8-negation.mo:2.9-2.36: execution error, value out of bounds diff --git a/test/trap/ok/outrange-int8-negation.run.ok b/test/trap/ok/outrange-int8-negation.run.ok index 17851ac1bc7..c81975d1bdc 100644 --- a/test/trap/ok/outrange-int8-negation.run.ok +++ b/test/trap/ok/outrange-int8-negation.run.ok @@ -1 +1 @@ -outrange-int8-negation.mo:1.9-1.31: execution error, value out of bounds +outrange-int8-negation.mo:2.9-2.36: execution error, value out of bounds diff --git a/test/trap/ok/outrange-int8-upper.run-ir.ok b/test/trap/ok/outrange-int8-upper.run-ir.ok index 0356664e3e0..c528d8b4c4e 100644 --- a/test/trap/ok/outrange-int8-upper.run-ir.ok +++ b/test/trap/ok/outrange-int8-upper.run-ir.ok @@ -1 +1 @@ -prelude:___: execution error, numeric overflow +prim:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int8-upper.run-low.ok b/test/trap/ok/outrange-int8-upper.run-low.ok index 0356664e3e0..c528d8b4c4e 100644 --- a/test/trap/ok/outrange-int8-upper.run-low.ok +++ b/test/trap/ok/outrange-int8-upper.run-low.ok @@ -1 +1 @@ -prelude:___: execution error, numeric overflow +prim:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-int8-upper.run.ok b/test/trap/ok/outrange-int8-upper.run.ok index 0356664e3e0..c528d8b4c4e 100644 --- a/test/trap/ok/outrange-int8-upper.run.ok +++ b/test/trap/ok/outrange-int8-upper.run.ok @@ -1 +1 @@ -prelude:___: execution error, numeric overflow +prim:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-nat16.run-ir.ok b/test/trap/ok/outrange-nat16.run-ir.ok index 0356664e3e0..c528d8b4c4e 100644 --- a/test/trap/ok/outrange-nat16.run-ir.ok +++ b/test/trap/ok/outrange-nat16.run-ir.ok @@ -1 +1 @@ -prelude:___: execution error, numeric overflow +prim:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-nat16.run-low.ok b/test/trap/ok/outrange-nat16.run-low.ok index 0356664e3e0..c528d8b4c4e 100644 --- a/test/trap/ok/outrange-nat16.run-low.ok +++ b/test/trap/ok/outrange-nat16.run-low.ok @@ -1 +1 @@ -prelude:___: execution error, numeric overflow +prim:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-nat16.run.ok b/test/trap/ok/outrange-nat16.run.ok index 0356664e3e0..c528d8b4c4e 100644 --- a/test/trap/ok/outrange-nat16.run.ok +++ b/test/trap/ok/outrange-nat16.run.ok @@ -1 +1 @@ -prelude:___: execution error, numeric overflow +prim:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-nat32.run-ir.ok b/test/trap/ok/outrange-nat32.run-ir.ok index 0356664e3e0..c528d8b4c4e 100644 --- a/test/trap/ok/outrange-nat32.run-ir.ok +++ b/test/trap/ok/outrange-nat32.run-ir.ok @@ -1 +1 @@ -prelude:___: execution error, numeric overflow +prim:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-nat32.run-low.ok b/test/trap/ok/outrange-nat32.run-low.ok index 0356664e3e0..c528d8b4c4e 100644 --- a/test/trap/ok/outrange-nat32.run-low.ok +++ b/test/trap/ok/outrange-nat32.run-low.ok @@ -1 +1 @@ -prelude:___: execution error, numeric overflow +prim:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-nat32.run.ok b/test/trap/ok/outrange-nat32.run.ok index 0356664e3e0..c528d8b4c4e 100644 --- a/test/trap/ok/outrange-nat32.run.ok +++ b/test/trap/ok/outrange-nat32.run.ok @@ -1 +1 @@ -prelude:___: execution error, numeric overflow +prim:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-nat64.run-ir.ok b/test/trap/ok/outrange-nat64.run-ir.ok index 0356664e3e0..c528d8b4c4e 100644 --- a/test/trap/ok/outrange-nat64.run-ir.ok +++ b/test/trap/ok/outrange-nat64.run-ir.ok @@ -1 +1 @@ -prelude:___: execution error, numeric overflow +prim:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-nat64.run-low.ok b/test/trap/ok/outrange-nat64.run-low.ok index 0356664e3e0..c528d8b4c4e 100644 --- a/test/trap/ok/outrange-nat64.run-low.ok +++ b/test/trap/ok/outrange-nat64.run-low.ok @@ -1 +1 @@ -prelude:___: execution error, numeric overflow +prim:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-nat64.run.ok b/test/trap/ok/outrange-nat64.run.ok index 0356664e3e0..c528d8b4c4e 100644 --- a/test/trap/ok/outrange-nat64.run.ok +++ b/test/trap/ok/outrange-nat64.run.ok @@ -1 +1 @@ -prelude:___: execution error, numeric overflow +prim:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-nat8.run-ir.ok b/test/trap/ok/outrange-nat8.run-ir.ok index 0356664e3e0..c528d8b4c4e 100644 --- a/test/trap/ok/outrange-nat8.run-ir.ok +++ b/test/trap/ok/outrange-nat8.run-ir.ok @@ -1 +1 @@ -prelude:___: execution error, numeric overflow +prim:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-nat8.run-low.ok b/test/trap/ok/outrange-nat8.run-low.ok index 0356664e3e0..c528d8b4c4e 100644 --- a/test/trap/ok/outrange-nat8.run-low.ok +++ b/test/trap/ok/outrange-nat8.run-low.ok @@ -1 +1 @@ -prelude:___: execution error, numeric overflow +prim:___: execution error, numeric overflow diff --git a/test/trap/ok/outrange-nat8.run.ok b/test/trap/ok/outrange-nat8.run.ok index 0356664e3e0..c528d8b4c4e 100644 --- a/test/trap/ok/outrange-nat8.run.ok +++ b/test/trap/ok/outrange-nat8.run.ok @@ -1 +1 @@ -prelude:___: execution error, numeric overflow +prim:___: execution error, numeric overflow diff --git a/test/trap/outrange-int16-lower.mo b/test/trap/outrange-int16-lower.mo index 51f97e6b3fc..8ddcfb6bae2 100644 --- a/test/trap/outrange-int16-lower.mo +++ b/test/trap/outrange-int16-lower.mo @@ -1 +1,2 @@ -let _ = intToInt16 (-32769) +import Prim "mo:prim"; +let _ = Prim.intToInt16 (-32769) diff --git a/test/trap/outrange-int16-negation.mo b/test/trap/outrange-int16-negation.mo index b144fc7c120..f911b9b7cc5 100644 --- a/test/trap/outrange-int16-negation.mo +++ b/test/trap/outrange-int16-negation.mo @@ -1 +1,2 @@ -let _ = - intToInt16 (- 2 ** 15); // this should trap +import Prim "mo:prim"; +let _ = - Prim.intToInt16 (- 2 ** 15); // this should trap diff --git a/test/trap/outrange-int16-upper.mo b/test/trap/outrange-int16-upper.mo index 568450cced3..a24146aa426 100644 --- a/test/trap/outrange-int16-upper.mo +++ b/test/trap/outrange-int16-upper.mo @@ -1 +1,2 @@ -let _ = intToInt16 (2 ** 15); +import Prim "mo:prim"; +let _ = Prim.intToInt16 (2 ** 15); diff --git a/test/trap/outrange-int32-lower.mo b/test/trap/outrange-int32-lower.mo index 2c319773417..07e9391c572 100644 --- a/test/trap/outrange-int32-lower.mo +++ b/test/trap/outrange-int32-lower.mo @@ -1 +1,2 @@ -let _ = intToInt32 (-2147483649) +import Prim "mo:prim"; +let _ = Prim.intToInt32 (-2147483649) diff --git a/test/trap/outrange-int32-negation.mo b/test/trap/outrange-int32-negation.mo index d7c164e2764..81a2bd0cf09 100644 --- a/test/trap/outrange-int32-negation.mo +++ b/test/trap/outrange-int32-negation.mo @@ -1 +1,2 @@ -let _ = - intToInt32 (- 2 ** 31); // this should trap +import Prim "mo:prim"; +let _ = - Prim.intToInt32 (- 2 ** 31); // this should trap diff --git a/test/trap/outrange-int32-upper.mo b/test/trap/outrange-int32-upper.mo index a7091425e94..5e473b898e4 100644 --- a/test/trap/outrange-int32-upper.mo +++ b/test/trap/outrange-int32-upper.mo @@ -1 +1,2 @@ -let _ = intToInt32 (2 ** 31); +import Prim "mo:prim"; +let _ = Prim.intToInt32 (2 ** 31); diff --git a/test/trap/outrange-int64-lower.mo b/test/trap/outrange-int64-lower.mo index a9a6a6625e8..a8697110b35 100644 --- a/test/trap/outrange-int64-lower.mo +++ b/test/trap/outrange-int64-lower.mo @@ -1 +1,2 @@ -let _ = intToInt64 (- 2 ** 63 - 1); +import Prim "mo:prim"; +let _ = Prim.intToInt64 (- 2 ** 63 - 1); diff --git a/test/trap/outrange-int64-negation.mo b/test/trap/outrange-int64-negation.mo index bfa832e02f9..e013037c847 100644 --- a/test/trap/outrange-int64-negation.mo +++ b/test/trap/outrange-int64-negation.mo @@ -1 +1,2 @@ -let _ = - intToInt64 (- 2 ** 63); // this should trap +import Prim "mo:prim"; +let _ = - Prim.intToInt64 (- 2 ** 63); // this should trap diff --git a/test/trap/outrange-int64-upper.mo b/test/trap/outrange-int64-upper.mo index 1c87d142031..62f41601083 100644 --- a/test/trap/outrange-int64-upper.mo +++ b/test/trap/outrange-int64-upper.mo @@ -1 +1,2 @@ -let _ = intToInt64 (2 ** 63); +import Prim "mo:prim"; +let _ = Prim.intToInt64 (2 ** 63); diff --git a/test/trap/outrange-int8-lower.mo b/test/trap/outrange-int8-lower.mo index 9cd498631cb..09dccecf2e6 100644 --- a/test/trap/outrange-int8-lower.mo +++ b/test/trap/outrange-int8-lower.mo @@ -1 +1,2 @@ -let _ = intToInt8 (-129); +import Prim "mo:prim"; +let _ = Prim.intToInt8 (-129); diff --git a/test/trap/outrange-int8-negation.mo b/test/trap/outrange-int8-negation.mo index bbfebafb79d..a0562ac696e 100644 --- a/test/trap/outrange-int8-negation.mo +++ b/test/trap/outrange-int8-negation.mo @@ -1 +1,2 @@ -let _ = - intToInt8 (- 2 ** 7); // this should trap +import Prim "mo:prim"; +let _ = - Prim.intToInt8 (- 2 ** 7); // this should trap diff --git a/test/trap/outrange-int8-upper.mo b/test/trap/outrange-int8-upper.mo index 95fc54f289a..f0ec90b2c04 100644 --- a/test/trap/outrange-int8-upper.mo +++ b/test/trap/outrange-int8-upper.mo @@ -1 +1,2 @@ -let _ = intToInt8 128; +import Prim "mo:prim"; +let _ = Prim.intToInt8 128; diff --git a/test/trap/outrange-nat16.mo b/test/trap/outrange-nat16.mo index 2c16854aa64..8a0aa40007d 100644 --- a/test/trap/outrange-nat16.mo +++ b/test/trap/outrange-nat16.mo @@ -1 +1,2 @@ -let _ = natToNat16 (2 ** 16); +import Prim "mo:prim"; +let _ = Prim.natToNat16 (2 ** 16); diff --git a/test/trap/outrange-nat32.mo b/test/trap/outrange-nat32.mo index bbd1c242388..8dbca3d6c49 100644 --- a/test/trap/outrange-nat32.mo +++ b/test/trap/outrange-nat32.mo @@ -1 +1,2 @@ -let _ = natToNat32 (2 ** 32); +import Prim "mo:prim"; +let _ = Prim.natToNat32 (2 ** 32); diff --git a/test/trap/outrange-nat64.mo b/test/trap/outrange-nat64.mo index 5fc78dd9b38..fb2365d6c22 100644 --- a/test/trap/outrange-nat64.mo +++ b/test/trap/outrange-nat64.mo @@ -1 +1,2 @@ -let _ = natToNat64 (2 ** 64); +import Prim "mo:prim"; +let _ = Prim.natToNat64 (2 ** 64); diff --git a/test/trap/outrange-nat8.mo b/test/trap/outrange-nat8.mo index cfce83df95f..a523ad878c8 100644 --- a/test/trap/outrange-nat8.mo +++ b/test/trap/outrange-nat8.mo @@ -1 +1,2 @@ -let _ = natToNat8 256 +import Prim "mo:prim"; +let _ = Prim.natToNat8 256 From 666b25d47789ea8dc35df5587d21230ed076780f Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Fri, 10 Jan 2020 19:11:56 +0000 Subject: [PATCH 0911/1176] typo --- design/scoped-await.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/design/scoped-await.md b/design/scoped-await.md index 44d13b4a520..dd1d54b7edc 100644 --- a/design/scoped-await.md +++ b/design/scoped-await.md @@ -47,7 +47,7 @@ Ys := Y, Ys := | async e // async (scope X bound in e) - |shared? f(x:T) : U = e // functions + | shared? f(x:T) : U = e // functions | f e // application | ... From d6cef7aca32b496ac342e0a3bd129568f91b116c Mon Sep 17 00:00:00 2001 From: chenyan-dfinity <48968912+chenyan-dfinity@users.noreply.github.com> Date: Fri, 10 Jan 2020 11:37:30 -0800 Subject: [PATCH 0912/1176] Update JS binding for numbered fields (#1090) * Update JS binding for numbered fields * fixup --- src/idllib/compile_js.ml | 5 ++--- test/idl/fieldnat.did | 1 - test/idl/ok/diamond.js.ok | 2 +- test/idl/ok/fieldnat.js.ok | 4 ++-- test/idl/ok/fields.js.ok | 23 ++++++++++++----------- test/idl/ok/test.js.ok | 2 +- 6 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/idllib/compile_js.ml b/src/idllib/compile_js.ml index c7ed7f74b77..d1558110dfc 100644 --- a/src/idllib/compile_js.ml +++ b/src/idllib/compile_js.ml @@ -154,9 +154,8 @@ and pp_field ppf tf = pp_open_box ppf 1; let f_name = match tf.it.label.it with - | Id n -> Lib.Uint32.to_string n | Named name -> name - | Unnamed n -> Lib.Uint32.to_string n + | Id n | Unnamed n -> "_" ^ (Lib.Uint32.to_string n) ^ "_" in quote_name ppf f_name; kwd ppf ":"; pp_typ ppf tf.it.typ; pp_close_box ppf () @@ -235,7 +234,7 @@ let pp_prog ppf env prog = List.iter (pp_dec ppf) env_list; pp_actor ppf actor recs; pp_footer ppf () - + let compile (scope : Typing.scope) (prog : Syntax.prog) = let buf = Buffer.create 100 in let ppf = formatter_of_buffer buf in diff --git a/test/idl/fieldnat.did b/test/idl/fieldnat.did index e3dee70d29f..4ba8762a2f0 100644 --- a/test/idl/fieldnat.did +++ b/test/idl/fieldnat.did @@ -2,7 +2,6 @@ service Foo: { foo : (record {2 : int}) -> (); bar : (record {"2" : int}) -> (); - // TODO: JS binding treats all field names as string baz : (record {2: int; "2": nat}) -> (); bab : (two: int, "2": nat) -> (); } diff --git a/test/idl/ok/diamond.js.ok b/test/idl/ok/diamond.js.ok index ebc0e990f6a..dc3bf76a756 100644 --- a/test/idl/ok/diamond.js.ok +++ b/test/idl/ok/diamond.js.ok @@ -2,6 +2,6 @@ export default ({ IDL }) => { const t = IDL.Nat const t2 = IDL.Vec(t) const t3 = IDL.Opt(t) - const t1 = IDL.Record({'0': t2, '1': t3, '2': t}) + const t1 = IDL.Record({'_0_': t2, '_1_': t3, '_2_': t}) return new IDL.ActorInterface({'f': IDL.Func([t, t2, t3], [t1], [])}); }; diff --git a/test/idl/ok/fieldnat.js.ok b/test/idl/ok/fieldnat.js.ok index f964918b2a2..01a9170e0a4 100644 --- a/test/idl/ok/fieldnat.js.ok +++ b/test/idl/ok/fieldnat.js.ok @@ -1,7 +1,7 @@ export default ({ IDL }) => { return new IDL.ActorInterface({ - 'foo': IDL.Func([IDL.Record({'2': IDL.Int})], [], []), + 'foo': IDL.Func([IDL.Record({'_2_': IDL.Int})], [], []), 'bar': IDL.Func([IDL.Record({'2': IDL.Int})], [], []), - 'baz': IDL.Func([IDL.Record({'2': IDL.Int, '2': IDL.Nat})], [], []), + 'baz': IDL.Func([IDL.Record({'_2_': IDL.Int, '2': IDL.Nat})], [], []), 'bab': IDL.Func([IDL.Int, IDL.Nat], [], [])}); }; diff --git a/test/idl/ok/fields.js.ok b/test/idl/ok/fields.js.ok index d6dd372b3f1..e51fdd02067 100644 --- a/test/idl/ok/fields.js.ok +++ b/test/idl/ok/fields.js.ok @@ -1,18 +1,19 @@ export default ({ IDL }) => { - const A = IDL.Record({'0': IDL.Nat, '1': IDL.Nat, '2': IDL.Nat}) + const A = IDL.Record({'_0_': IDL.Nat, '_1_': IDL.Nat, '_2_': IDL.Nat}) const B = - IDL.Record({'0': IDL.Vec(IDL.Nat8), '35': IDL.Vec(IDL.Nat8), '36': IDL.Nat, - '37': IDL.Nat, 'named_files': IDL.None, '3629958706': IDL.Nat, - '3629958707': IDL.Nat}) + IDL.Record({'_0_': IDL.Vec(IDL.Nat8), '_35_': IDL.Vec(IDL.Nat8), + '_36_': IDL.Nat, '_37_': IDL.Nat, 'named_files': IDL.None, + '_3629958706_': IDL.Nat, '_3629958707_': IDL.Nat}) const C = - IDL.Variant({'1': IDL.Unit, '2': IDL.Unit, '3': IDL.Unit, '4': IDL.Unit, - '10': IDL.Unit, 'A': IDL.Unit, 'B': IDL.Unit, 'C': IDL.Unit, - 'red': IDL.Unit, 'blue': IDL.Unit, 'reserved': IDL.Unit, 'green': IDL.Unit - }) + IDL.Variant({'_1_': IDL.Unit, '_2_': IDL.Unit, '_3_': IDL.Unit, + '_4_': IDL.Unit, '_10_': IDL.Unit, 'A': IDL.Unit, 'B': IDL.Unit, + 'C': IDL.Unit, 'red': IDL.Unit, 'blue': IDL.Unit, 'reserved': IDL.Unit, + 'green': IDL.Unit}) const nest_record = - IDL.Record({'0': IDL.Nat, '1': IDL.Nat, '2': IDL.Nat, - '3': IDL.Record({'0': IDL.Nat, '1': IDL.Nat, '2': IDL.Nat}), '4': IDL.Nat, - '5': IDL.Nat, '6': IDL.Nat, '7': A, '8': B, '9': C, '10': IDL.Nat}) + IDL.Record({'_0_': IDL.Nat, '_1_': IDL.Nat, '_2_': IDL.Nat, + '_3_': IDL.Record({'_0_': IDL.Nat, '_1_': IDL.Nat, '_2_': IDL.Nat}), + '_4_': IDL.Nat, '_5_': IDL.Nat, '_6_': IDL.Nat, '_7_': A, '_8_': B, + '_9_': C, '_10_': IDL.Nat}) return new IDL.ActorInterface({'f': IDL.Func([A, B, C, nest_record], [], []) }); }; diff --git a/test/idl/ok/test.js.ok b/test/idl/ok/test.js.ok index 581065ce509..098087e2e45 100644 --- a/test/idl/ok/test.js.ok +++ b/test/idl/ok/test.js.ok @@ -1,7 +1,7 @@ export default ({ IDL }) => { const my_type = IDL.Nat const B = my_type - const message = IDL.Record({'25': B, '26': IDL.None, 'name': IDL.Text}) + const message = IDL.Record({'_25_': B, '_26_': IDL.None, 'name': IDL.Text}) const broker = new IDL.ActorInterface({ 'find': From 24975e46fae5e392a0e17fc15db21bb64082dce0 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 10 Jan 2020 20:45:42 +0100 Subject: [PATCH 0913/1176] Bump drun (#1095) mainly to get https://github.com/dfinity-lab/dfinity/pull/2236 also included ``` fd316583e DFN-1043: Implement BasicSigByPubkeyVerifier for crypto component (#2178) 3f5b3e78d Parameterize components over prometheus registry (#2236) 1945a51fc Merge pull request #2250 from dfinity-lab/nm-dcheck-audit bea6a389d DFN-1253: Implement BasicSigner/BasicSigVerifier and migrate tests (#2157) f6b0244cb DFN-1119: Replace ThreadRng/StdRng with OsRng/ChaCha20Rng (#2206) ``` --- default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/default.nix b/default.nix index 27edd1e04e1..bd1ffc198d6 100644 --- a/default.nix +++ b/default.nix @@ -36,7 +36,7 @@ let dfinity-src = name = "dfinity-sources"; url = "ssh://git@github.com/dfinity-lab/dfinity"; # ref = "master"; - rev = "502ff80e26ac5a6cf10ae3f92fdea70de7d1f58e"; + rev = "91ff7b663820e6f9ba3aab3993b6f613482465ca"; }; in let dfinity-pkgs = import dfinity-src { inherit (nixpkgs) system; }; in From c4dbb935b94115d1b34ca74a62d0c883772dd2f1 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity <48968912+chenyan-dfinity@users.noreply.github.com> Date: Fri, 10 Jan 2020 16:38:57 -0800 Subject: [PATCH 0914/1176] Lib fix (#1098) * hex lib fix * fix --- src/lib/lib.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/lib.ml b/src/lib/lib.ml index f7b1d0d6ecd..2058b87b2b1 100644 --- a/src/lib/lib.ml +++ b/src/lib/lib.ml @@ -77,7 +77,7 @@ struct let open Char in function | c when 0 <= c && c <= 9 -> chr (code '0' + c) - | c when 10 < c && c <= 15 -> chr (code 'A' + (c - 10)) + | c when 10 <= c && c <= 15 -> chr (code 'A' + (c - 10)) | _ -> assert false let hex_of_byte i : string = From 4d6afaa511cd9ae62ad2bb6a3c9a0f79c818ab8d Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Sat, 11 Jan 2020 14:07:43 +0100 Subject: [PATCH 0915/1176] Update the Produce exchange to not use Prim (#1097) but only the standard library --- stdlib/examples/actorspec/src/ActorSpec.mo | 12 +- .../examples/produce-exchange/serverActor.mo | 4 +- .../examples/produce-exchange/serverModel.mo | 10 +- .../produce-exchange/test/evalBulk.mo | 100 ++++++------ .../test/producerRemInventory.mo | 101 ++++++------ .../test/profileFastCounts.mo | 19 +-- .../test/retailerReserveMany.mo | 152 ++++++++---------- .../test/simpleSetupAndQuery.mo | 116 +++++++------ 8 files changed, 230 insertions(+), 284 deletions(-) diff --git a/stdlib/examples/actorspec/src/ActorSpec.mo b/stdlib/examples/actorspec/src/ActorSpec.mo index f24da8ecf67..100d9a72ee1 100644 --- a/stdlib/examples/actorspec/src/ActorSpec.mo +++ b/stdlib/examples/actorspec/src/ActorSpec.mo @@ -1,4 +1,4 @@ -import Prim "mo:prim"; +import Debug "../../../debug.mo"; import Array "../../../array.mo"; import Int "../../../int.mo"; import Text "../../../text.mo"; @@ -43,10 +43,10 @@ module { public func run(groups_ : [Group]) : Bool { let (groups, status) = getGroups(groups_); printGroups(groups, ""); - Prim.debugPrint("\n"); - Prim.debugPrint(printStatus(status)); - Prim.debugPrint("\n"); - Prim.debugPrint("\n"); + Debug.print("\n"); + Debug.print(printStatus(status)); + Debug.print("\n"); + Debug.print("\n"); status.failed == 0; }; @@ -87,7 +87,7 @@ module { case (_, _, _) { ":" # printStatus(status); }; }; }; - Prim.debugPrint(newline # indent # group.name # statusText # "\n"); + Debug.print(newline # indent # group.name # statusText # "\n"); printGroups(group.groups, indent # " "); }; }; diff --git a/stdlib/examples/produce-exchange/serverActor.mo b/stdlib/examples/produce-exchange/serverActor.mo index 3b3f68717af..8bc814608a8 100644 --- a/stdlib/examples/produce-exchange/serverActor.mo +++ b/stdlib/examples/produce-exchange/serverActor.mo @@ -4,7 +4,7 @@ -------------------- */ -import Prim "mo:prim"; +import Debug "../../debug.mo"; import P = "../../prelude.mo"; import Option = "../../option.mo"; import T = "serverTypes.mo"; @@ -1049,7 +1049,7 @@ been processed public func loadWorkload(params:T.WorkloadParams) : () { - func db(s:Text) = if false {Prim.debugPrint "Model::loadWorkload: "; Prim.debugPrint s; Prim.debugPrint "\n"}; + func db(s:Text) = if false {Debug.print "Model::loadWorkload: "; Debug.print s; Debug.print "\n"}; getModel().loadWorkload(params) }; diff --git a/stdlib/examples/produce-exchange/serverModel.mo b/stdlib/examples/produce-exchange/serverModel.mo index f2be7afbadd..7da988945d6 100644 --- a/stdlib/examples/produce-exchange/serverModel.mo +++ b/stdlib/examples/produce-exchange/serverModel.mo @@ -1,4 +1,4 @@ -import Prim = "mo:prim"; +import Debug = "../../debug.mo"; import P = "../../prelude.mo"; import T = "serverTypes.mo"; @@ -85,7 +85,7 @@ public class Model() { */ public func loadWorkload(params:T.WorkloadParams) : () { - func db(s:Text) = if false {Prim.debugPrint "Model::loadWorkload: "; Prim.debugPrint s; Prim.debugPrint "\n"}; + func db(s:Text) = if false {Debug.print "Model::loadWorkload: "; Debug.print s; Debug.print "\n"}; /**- generate add requests for these params: */ db "generate requests for workload..."; @@ -133,7 +133,7 @@ public class Model() { */ public func evalReq(req:L.Req) : Result { - if false {Prim.debugPrint "Model::evalReq: "; Prim.debugPrint (debug_show req); Prim.debugPrint "\n"; }; + if false {Debug.print "Model::evalReq: "; Debug.print (debug_show req); Debug.print "\n"; }; switch req { case (#reset) { /**- 1. reset each entity table: */ @@ -607,8 +607,8 @@ public class Model() { ================== */ - func debugOut (t:Text) { debug { Prim.debugPrint t } }; - func debugInt (i:Int) { debug { Prim.debugPrintInt i } }; + func debugOut (t:Text) { debug { Debug.print t } }; + func debugInt (i:Int) { debug { Debug.print (debug_show i) } }; func debugOff (t:Text) { debug { } }; func debugIntOff (i:Int) { debug { } }; diff --git a/stdlib/examples/produce-exchange/test/evalBulk.mo b/stdlib/examples/produce-exchange/test/evalBulk.mo index 955a71a9512..8a8986dd4d0 100644 --- a/stdlib/examples/produce-exchange/test/evalBulk.mo +++ b/stdlib/examples/produce-exchange/test/evalBulk.mo @@ -1,19 +1,15 @@ -import Prim "mo:prim"; +import Debug = "../../../debug.mo"; import T = "../serverTypes.mo"; import A = "../serverActor.mo"; import Result = "../../../result.mo"; import Option = "../../../option.mo"; func printEntityCount(entname:Text, count:Nat) { - Prim.debugPrint ("- " # entname # " count: "); - Prim.debugPrintInt count; - Prim.debugPrint "\n"; + Debug.print ("- " # entname # " count: " # debug_show count # "\n"); }; func printLabeledCost(lab:Text, cost:Nat) { - Prim.debugPrint ("- " # lab # " cost: "); - Prim.debugPrintInt cost; - Prim.debugPrint "\n"; + Debug.print ("- " # lab # " cost: " # debug_show cost # "\n"); }; actor class Test() = this { @@ -22,7 +18,7 @@ actor class Test() = this { { let s = A.Server(); - Prim.debugPrint "\nExchange setup: Begin...\n====================================\n"; + Debug.print "\nExchange setup: Begin...\n====================================\n"; let pka = "beef"; let pkb = "dead"; @@ -124,7 +120,7 @@ actor class Test() = this { ////////////////////////////////////////////////////////////////// - Prim.debugPrint "\nRetailer queries\n====================================\n"; + Debug.print "\nRetailer queries\n====================================\n"; // do some queries await retailerQueryAll(s, pka, ? Result.assertUnwrapAny(uida)); @@ -133,7 +129,7 @@ actor class Test() = this { await retailerQueryAll(s, pkd, ? Result.assertUnwrapAny(uidd)); await retailerQueryAll(s, pke, ? Result.assertUnwrapAny(uide)); - Prim.debugPrint "\nQuery counts\n----------------\n"; + Debug.print "\nQuery counts\n----------------\n"; let counts = await s.getCounts(); printEntityCount("Retailer join", counts.retailer_join_count); @@ -147,84 +143,80 @@ actor class Test() = this { func retailerQueryAll(server:A.Server, pk:Text, r:?T.UserId) : async () { - Prim.debugPrint "\nRetailer "; let retailerId: T.UserId = Option.unwrap(r); - Prim.debugPrintInt retailerId; - Prim.debugPrint " sends `retailerQueryAll`\n"; - Prim.debugPrint "------------------------------------\n"; + Debug.print ("\nRetailer " # debug_show retailerId # " sends `retailerQueryAll`\n"); + Debug.print "------------------------------------\n"; - Prim.debugPrint "\n## Query begin:\n"; + Debug.print "\n## Query begin:\n"; let res = Result.assertUnwrapAny( await server.retailerQueryAll(pk, retailerId, null, null) ); - Prim.debugPrint "\n## Query end."; + Debug.print "\n## Query end."; - Prim.debugPrint "\n## Query results ("; - Prim.debugPrintInt (res.len()); - Prim.debugPrint ")\n"; + Debug.print ("\n## Query results (" # debug_show res.len() # ")\n"); for (info in res.vals()) { - Prim.debugPrint "- "; - Prim.debugPrint (debug_show info); - Prim.debugPrint "\n"; + Debug.print "- "; + Debug.print (debug_show info); + Debug.print "\n"; } }; func debugDumpAll(server:A.Server) : async () { - Prim.debugPrint "\nTruck type info\n----------------\n"; + Debug.print "\nTruck type info\n----------------\n"; for ( info in ((await server.allTruckTypeInfo()).vals()) ) { - Prim.debugPrint "- "; - Prim.debugPrint (debug_show info); - Prim.debugPrint "\n"; + Debug.print "- "; + Debug.print (debug_show info); + Debug.print "\n"; }; - Prim.debugPrint "\nRegion info\n----------------\n"; + Debug.print "\nRegion info\n----------------\n"; for ( info in ((await server.allRegionInfo()).vals()) ) { - Prim.debugPrint "- "; - Prim.debugPrint (debug_show info); - Prim.debugPrint "\n"; + Debug.print "- "; + Debug.print (debug_show info); + Debug.print "\n"; }; - Prim.debugPrint "\nProduce info\n----------------\n"; + Debug.print "\nProduce info\n----------------\n"; for ( info in ((await server.allProduceInfo()).vals()) ) { - Prim.debugPrint "- "; - Prim.debugPrint (debug_show info); - Prim.debugPrint "\n"; + Debug.print "- "; + Debug.print (debug_show info); + Debug.print "\n"; }; - Prim.debugPrint "\nProducer info\n----------------\n"; + Debug.print "\nProducer info\n----------------\n"; for ( info in ((await server.allProducerInfo()).vals()) ) { - Prim.debugPrint "- "; - Prim.debugPrint (debug_show info); - Prim.debugPrint "\n"; + Debug.print "- "; + Debug.print (debug_show info); + Debug.print "\n"; }; - Prim.debugPrint "\nTransporter info\n----------------\n"; + Debug.print "\nTransporter info\n----------------\n"; for ( info in ((await server.allTransporterInfo()).vals()) ) { - Prim.debugPrint "- "; - Prim.debugPrint (debug_show info); - Prim.debugPrint "\n"; + Debug.print "- "; + Debug.print (debug_show info); + Debug.print "\n"; }; - Prim.debugPrint "\nRetailer info\n----------------\n"; + Debug.print "\nRetailer info\n----------------\n"; for ( info in ((await server.allRetailerInfo()).vals()) ) { - Prim.debugPrint "- "; - Prim.debugPrint (debug_show info); - Prim.debugPrint "\n"; + Debug.print "- "; + Debug.print (debug_show info); + Debug.print "\n"; }; - Prim.debugPrint "\nInventory info\n----------------\n"; + Debug.print "\nInventory info\n----------------\n"; for ( info in ((await server.allInventoryInfo()).vals()) ) { - Prim.debugPrint "- "; - Prim.debugPrint (debug_show info); - Prim.debugPrint "\n"; + Debug.print "- "; + Debug.print (debug_show info); + Debug.print "\n"; }; - Prim.debugPrint "\nRoute info\n----------------\n"; + Debug.print "\nRoute info\n----------------\n"; for ( info in ((await server.allRouteInfo()).vals()) ) { - Prim.debugPrint "- "; - Prim.debugPrint (debug_show info); - Prim.debugPrint "\n"; + Debug.print "- "; + Debug.print (debug_show info); + Debug.print "\n"; }; }; diff --git a/stdlib/examples/produce-exchange/test/producerRemInventory.mo b/stdlib/examples/produce-exchange/test/producerRemInventory.mo index bc119f4fca3..d637b0b3951 100644 --- a/stdlib/examples/produce-exchange/test/producerRemInventory.mo +++ b/stdlib/examples/produce-exchange/test/producerRemInventory.mo @@ -1,19 +1,15 @@ -import Prim "mo:prim"; +import Debug "../../../debug.mo"; import T = "../serverTypes.mo"; import A = "../serverActor.mo"; import Result = "../../../result.mo"; import Option = "../../../option.mo"; func printEntityCount(entname:Text, count:Nat) { - Prim.debugPrint ("- " # entname # " count: "); - Prim.debugPrintInt count; - Prim.debugPrint "\n"; + Debug.print ("- " # entname # " count: " # debug_show count # "\n"); }; func printLabeledCost(lab:Text, cost:Nat) { - Prim.debugPrint ("- " # lab # " cost: "); - Prim.debugPrintInt cost; - Prim.debugPrint "\n"; + Debug.print ("- " # lab # " cost: " # debug_show cost # "\n"); }; actor class Test() = this { @@ -22,7 +18,7 @@ actor class Test() = this { { let s = A.Server(); - Prim.debugPrint "\nExchange setup: Begin...\n====================================\n"; + Debug.print "\nExchange setup: Begin...\n====================================\n"; let pka = "beef"; let pkb = "dead"; @@ -125,22 +121,22 @@ actor class Test() = this { await debugDumpInventory(s, pka, 0); await debugDumpAll(s); - Prim.debugPrint "\n First time: Producer remove query\n====================================\n"; + Debug.print "\n First time: Producer remove query\n====================================\n"; let rem0 = await s.producerRemInventory(pka, 0); - Prim.debugPrint "- first producerRemInventory(pka, 0) result:"; - Prim.debugPrint (debug_show rem0); - Prim.debugPrint "\n"; + Debug.print "- first producerRemInventory(pka, 0) result:"; + Debug.print (debug_show rem0); + Debug.print "\n"; await debugDumpInventory(s, pka, 0); await debugDumpAll(s); - Prim.debugPrint "\n Second time: Producer remove query\n====================================\n"; + Debug.print "\n Second time: Producer remove query\n====================================\n"; let rem0b = await s.producerRemInventory(pka, 0); - Prim.debugPrint "- second producerRemInventory(pka, 0) result:"; - Prim.debugPrint (debug_show rem0b); - Prim.debugPrint "\n"; + Debug.print "- second producerRemInventory(pka, 0) result:"; + Debug.print (debug_show rem0b); + Debug.print "\n"; await debugDumpInventory(s, pka, 0); await debugDumpAll(s); @@ -149,75 +145,70 @@ actor class Test() = this { }; func debugDumpInventory(server:A.Server, pk:T.PublicKey, p:T.ProducerId) : async () { - Prim.debugPrint "\nProducer "; - Prim.debugPrintInt p; - Prim.debugPrint "'s inventory:\n--------------------------------\n"; + Debug.print ("\nProducer " # debug_show p # "'s inventory:\n--------------------------------\n"); let res = await server.producerAllInventoryInfo(pk, p); let items = Result.assertUnwrapAny<[T.InventoryInfo]>(res); for (i in items.keys()) { - Prim.debugPrintInt i; - Prim.debugPrint ". "; - Prim.debugPrint (debug_show (items[i])); - Prim.debugPrint "\n"; + Debug.print (debug_show i # ". " # debug_show (items[i]) # "\n"); } }; func debugDumpAll(server:A.Server) : async () { - Prim.debugPrint "\nTruck type info\n----------------\n"; + Debug.print "\nTruck type info\n----------------\n"; for ( info in ((await server.allTruckTypeInfo()).vals()) ) { - Prim.debugPrint "- "; - Prim.debugPrint (debug_show info); - Prim.debugPrint "\n"; + Debug.print "- "; + Debug.print (debug_show info); + Debug.print "\n"; }; - Prim.debugPrint "\nRegion info\n----------------\n"; + Debug.print "\nRegion info\n----------------\n"; for ( info in ((await server.allRegionInfo()).vals()) ) { - Prim.debugPrint "- "; - Prim.debugPrint (debug_show info); - Prim.debugPrint "\n"; + Debug.print "- "; + Debug.print (debug_show info); + Debug.print "\n"; }; - Prim.debugPrint "\nProduce info\n----------------\n"; + Debug.print "\nProduce info\n----------------\n"; for ( info in ((await server.allProduceInfo()).vals()) ) { - Prim.debugPrint "- "; - Prim.debugPrint (debug_show info); - Prim.debugPrint "\n"; + Debug.print "- "; + Debug.print (debug_show info); + Debug.print "\n"; }; - Prim.debugPrint "\nProducer info\n----------------\n"; + Debug.print "\nProducer info\n----------------\n"; for ( info in ((await server.allProducerInfo()).vals()) ) { - Prim.debugPrint "- "; - Prim.debugPrint (debug_show info); - Prim.debugPrint "\n"; + Debug.print "- "; + Debug.print (debug_show info); + Debug.print "\n"; }; - Prim.debugPrint "\nTransporter info\n----------------\n"; + Debug.print "\nTransporter info\n----------------\n"; for ( info in ((await server.allTransporterInfo()).vals()) ) { - Prim.debugPrint "- "; - Prim.debugPrint (debug_show info); - Prim.debugPrint "\n"; + Debug.print "- "; + Debug.print (debug_show info); + Debug.print "\n"; }; - Prim.debugPrint "\nRetailer info\n----------------\n"; + Debug.print "\nRetailer info\n----------------\n"; for ( info in ((await server.allRetailerInfo()).vals()) ) { - Prim.debugPrint "- "; - Prim.debugPrint (debug_show info); - Prim.debugPrint "\n"; + Debug.print "- "; + Debug.print (debug_show info); + Debug.print "\n"; }; - Prim.debugPrint "\nInventory info\n----------------\n"; + Debug.print "\nInventory info\n----------------\n"; for ( info in ((await server.allInventoryInfo()).vals()) ) { - Prim.debugPrint "- "; - Prim.debugPrint (debug_show info); - Prim.debugPrint "\n"; + Debug.print "- "; + Debug.print (debug_show info); + Debug.print "\n"; }; - Prim.debugPrint "\nRoute info\n----------------\n"; + Debug.print "\nRoute info\n----------------\n"; for ( info in ((await server.allRouteInfo()).vals()) ) { - Prim.debugPrint "- "; - Prim.debugPrint (debug_show info); - Prim.debugPrint "\n"; + Debug.print "- "; + Debug.print (debug_show info); + Debug.print "\n"; }; }; diff --git a/stdlib/examples/produce-exchange/test/profileFastCounts.mo b/stdlib/examples/produce-exchange/test/profileFastCounts.mo index 3989d96c7c6..78498b0ac48 100644 --- a/stdlib/examples/produce-exchange/test/profileFastCounts.mo +++ b/stdlib/examples/produce-exchange/test/profileFastCounts.mo @@ -2,7 +2,7 @@ // we correlate these numbers with times that we // measure elsewhere, where these numbers are not available. -import Prim "mo:prim"; +import Debug "../../../debug.mo"; import T = "../serverTypes.mo"; import Model = "../serverModel.mo"; @@ -11,10 +11,10 @@ let m = Model.Model(); let scales = [1,2,3,4,5,6,7,8,9,10, 20,50,100]; -Prim.debugPrint "# column: region count\n"; -Prim.debugPrint "# column: workload scale\n"; -Prim.debugPrint "# column: inventory count\n"; -Prim.debugPrint "# column: route count\n"; +Debug.print "# column: region count\n"; +Debug.print "# column: workload scale\n"; +Debug.print "# column: inventory count\n"; +Debug.print "# column: route count\n"; for (scale in scales.vals()) { let (ic, rc) = m.countAddReqs(3, 1, @@ -23,12 +23,5 @@ for (scale in scales.vals()) { 5 * scale, 5); - Prim.debugPrintInt 5; - Prim.debugPrint ", "; - Prim.debugPrintInt scale; - Prim.debugPrint ", "; - Prim.debugPrintInt ic; - Prim.debugPrint ", "; - Prim.debugPrintInt rc; - Prim.debugPrint "\n"; + Debug.print (debug_show 5 # ", " # debug_show scale # ", " # debug_show ic # ", " # debug_show rc # "\n"); }; diff --git a/stdlib/examples/produce-exchange/test/retailerReserveMany.mo b/stdlib/examples/produce-exchange/test/retailerReserveMany.mo index a46931d7c2e..eff0bdf02d6 100644 --- a/stdlib/examples/produce-exchange/test/retailerReserveMany.mo +++ b/stdlib/examples/produce-exchange/test/retailerReserveMany.mo @@ -1,28 +1,25 @@ -import Prim "mo:prim"; +import Debug "../../../debug.mo"; import T = "../serverTypes.mo"; import A = "../serverActor.mo"; import Result = "../../../result.mo"; import Option = "../../../option.mo"; func printEntityCount(entname:Text, count:Nat) { - Prim.debugPrint ("- " # entname # " count: "); - Prim.debugPrintInt count; - Prim.debugPrint "\n"; + Debug.print ("- " # entname # " count: " # debug_show count # "\n"); }; func printLabeledCost(lab:Text, cost:Nat) { - Prim.debugPrint ("- " # lab # " cost: "); - Prim.debugPrintInt cost; - Prim.debugPrint "\n"; + Debug.print ("- " # lab # " cost: " # debug_show cost # "\n"); }; + actor class Test() = this { public func go() { ignore(async { let s = A.Server(); - Prim.debugPrint "\nExchange setup: Begin...\n====================================\n"; + Debug.print "\nExchange setup: Begin...\n====================================\n"; let pka = "beef"; let pkb = "dead"; @@ -98,7 +95,7 @@ actor class Test() = this { ////////////////////////////////////////////////////////////////// - Prim.debugPrint "\nExchange setup: Done.\n====================================\n"; + Debug.print "\nExchange setup: Done.\n====================================\n"; let inventoryCount1 = await debugDumpInventory(s, pka, 0); let routeCount1 = await debugDumpRoutes(s, pka, 0); @@ -106,7 +103,7 @@ actor class Test() = this { ////////////////////////////////////////////////////////////////// - Prim.debugPrint "\nRetailer queries\n====================================\n"; + Debug.print "\nRetailer queries\n====================================\n"; // do some queries await retailerQueryAll(s, pka, ? Result.assertUnwrapAny(uida)); @@ -115,17 +112,17 @@ actor class Test() = this { await retailerQueryAll(s, pkd, ? Result.assertUnwrapAny(uidd)); await retailerQueryAll(s, pke, ? Result.assertUnwrapAny(uide)); - Prim.debugPrint "\nQuery counts\n----------------\n"; + Debug.print "\nQuery counts\n----------------\n"; let counts = await s.getCounts(); printEntityCount("Retailer join", counts.retailer_join_count); printEntityCount("Retailer query", counts.retailer_query_count); printLabeledCost("Retailer query", counts.retailer_query_cost); - Prim.debugPrint "\nRetailer reservations\n====================================\n"; + Debug.print "\nRetailer reservations\n====================================\n"; - Prim.debugPrint "\nRetailer reservations: begin...\n------------------------\n"; + Debug.print "\nRetailer reservations: begin...\n------------------------\n"; let rrm = await s.retailerReserveMany(pka, @@ -136,24 +133,21 @@ actor class Test() = this { let urrm = Result.assertUnwrapAny<[Result.Result<(T.ReservedInventoryId, T.ReservedRouteId), T.ServerErr>]>(rrm); - Prim.debugPrint "\nRetailer reservations: results:\n---------------------------------\n"; + Debug.print "\nRetailer reservations: results:\n---------------------------------\n"; for (i in urrm.keys()) { - Prim.debugPrintInt i; - Prim.debugPrint ". "; - Prim.debugPrint (debug_show urrm[i]); - Prim.debugPrint "\n"; + Debug.print (debug_show i # ". " # debug_show urrm[i] # "\n"); }; - Prim.debugPrint "\nRetailer reservations: results[0]: expect success.\n---------------------------------\n"; + Debug.print "\nRetailer reservations: results[0]: expect success.\n---------------------------------\n"; let (ri0, rr0) = Result.assertUnwrapAny<(T.ReservedInventoryId, T.ReservedRouteId)>(urrm[0]); - Prim.debugPrint "- "; - Prim.debugPrint (debug_show (ri0, rr0)); - Prim.debugPrint "\n"; + Debug.print "- "; + Debug.print (debug_show (ri0, rr0)); + Debug.print "\n"; - Prim.debugPrint "\nRetailer reservations: results[1]: expect error: already reserved by us!\n---------------------------------\n"; + Debug.print "\nRetailer reservations: results[1]: expect error: already reserved by us!\n---------------------------------\n"; Result.assertErrAs (urrm[1], @@ -161,7 +155,7 @@ actor class Test() = this { switch err { case (#idErr entid) { switch entid { - case (?(#inventory 0)) Prim.debugPrint "- error is `#idErr(?(#inventory 0))`\n"; + case (?(#inventory 0)) Debug.print "- error is `#idErr(?(#inventory 0))`\n"; case _ assert false; } }; @@ -169,9 +163,9 @@ actor class Test() = this { } }); - Prim.debugPrint "\nRetailer reservations: done.\n---------------------------------\n"; + Debug.print "\nRetailer reservations: done.\n---------------------------------\n"; - Prim.debugPrint "\nExchange interactions: Done.\n====================================\n"; + Debug.print "\nExchange interactions: Done.\n====================================\n"; let inventoryCount2 = await debugDumpInventory(s, pka, 0); let routeCount2 = await debugDumpRoutes(s, pka, 0); @@ -184,117 +178,101 @@ actor class Test() = this { }; func debugDumpInventory(server:A.Server, pk:T.PublicKey, p:T.ProducerId) : async Nat { - Prim.debugPrint "\nProducer "; - Prim.debugPrintInt p; - Prim.debugPrint "'s inventory:\n--------------------------------\n"; + Debug.print ("\nProducer " # debug_show p # "'s inventory:\n--------------------------------\n"); let res = await server.producerAllInventoryInfo(pk, p); let items = Result.assertUnwrapAny<[T.InventoryInfo]>(res); for (i in items.keys()) { - Prim.debugPrintInt i; - Prim.debugPrint ". "; - Prim.debugPrint (debug_show (items[i])); - Prim.debugPrint "\n"; + Debug.print (debug_show i # ". " # debug_show items[i] # "\n"); }; - Prim.debugPrint "(list end)\n"; + Debug.print "(list end)\n"; items.len() }; func debugDumpRoutes(server:A.Server, pk:T.PublicKey, t:T.TransporterId) : async Nat { - Prim.debugPrint "\nTransporter "; - Prim.debugPrintInt t; - Prim.debugPrint "'s routes:\n--------------------------------\n"; + Debug.print ("\nTransporter " # debug_show t # "'s routes:\n--------------------------------\n"); let res = await server.transporterAllRouteInfo(pk, t); let items = Result.assertUnwrapAny<[T.RouteInfo]>(res); for (i in items.keys()) { - Prim.debugPrintInt i; - Prim.debugPrint ". "; - Prim.debugPrint (debug_show (items[i])); - Prim.debugPrint "\n"; + Debug.print (debug_show i # ". " # debug_show items[i] # "\n"); }; - Prim.debugPrint "(list end)\n"; + Debug.print "(list end)\n"; items.len() }; func retailerQueryAll(server:A.Server, pk:Text, r:?T.UserId) : async () { - - Prim.debugPrint "\nRetailer "; let retailerId: T.UserId = Option.unwrap(r); - Prim.debugPrintInt retailerId; - Prim.debugPrint " sends `retailerQueryAll`\n"; - Prim.debugPrint "------------------------------------\n"; + Debug.print ("\nRetailer " # debug_show retailerId # " sends `retailerQueryAll`\n"); - Prim.debugPrint "\n## Query begin:\n"; + Debug.print "\n## Query begin:\n"; let res = Result.assertUnwrapAny( await server.retailerQueryAll(pk, retailerId, null, null) ); - Prim.debugPrint "\n## Query end."; + Debug.print "\n## Query end."; - Prim.debugPrint "\n## Query results ("; - Prim.debugPrintInt (res.len()); - Prim.debugPrint ")\n"; + Debug.print ("\n## Query results (" # debug_show res.len() # ")\n"); for (info in res.vals()) { - Prim.debugPrint "- "; - Prim.debugPrint (debug_show info); - Prim.debugPrint "\n"; + Debug.print "- "; + Debug.print (debug_show info); + Debug.print "\n"; } }; func debugDumpAll(server:A.Server) : async () { - Prim.debugPrint "\nTruck type info\n----------------\n"; + Debug.print "\nTruck type info\n----------------\n"; for ( info in ((await server.allTruckTypeInfo()).vals()) ) { - Prim.debugPrint "- "; - Prim.debugPrint (debug_show info); - Prim.debugPrint "\n"; + Debug.print "- "; + Debug.print (debug_show info); + Debug.print "\n"; }; - Prim.debugPrint "\nRegion info\n----------------\n"; + Debug.print "\nRegion info\n----------------\n"; for ( info in ((await server.allRegionInfo()).vals()) ) { - Prim.debugPrint "- "; - Prim.debugPrint (debug_show info); - Prim.debugPrint "\n"; + Debug.print "- "; + Debug.print (debug_show info); + Debug.print "\n"; }; - Prim.debugPrint "\nProduce info\n----------------\n"; + Debug.print "\nProduce info\n----------------\n"; for ( info in ((await server.allProduceInfo()).vals()) ) { - Prim.debugPrint "- "; - Prim.debugPrint (debug_show info); - Prim.debugPrint "\n"; + Debug.print "- "; + Debug.print (debug_show info); + Debug.print "\n"; }; - Prim.debugPrint "\nProducer info\n----------------\n"; + Debug.print "\nProducer info\n----------------\n"; for ( info in ((await server.allProducerInfo()).vals()) ) { - Prim.debugPrint "- "; - Prim.debugPrint (debug_show info); - Prim.debugPrint "\n"; + Debug.print "- "; + Debug.print (debug_show info); + Debug.print "\n"; }; - Prim.debugPrint "\nTransporter info\n----------------\n"; + Debug.print "\nTransporter info\n----------------\n"; for ( info in ((await server.allTransporterInfo()).vals()) ) { - Prim.debugPrint "- "; - Prim.debugPrint (debug_show info); - Prim.debugPrint "\n"; + Debug.print "- "; + Debug.print (debug_show info); + Debug.print "\n"; }; - Prim.debugPrint "\nRetailer info\n----------------\n"; + Debug.print "\nRetailer info\n----------------\n"; for ( info in ((await server.allRetailerInfo()).vals()) ) { - Prim.debugPrint "- "; - Prim.debugPrint (debug_show info); - Prim.debugPrint "\n"; + Debug.print "- "; + Debug.print (debug_show info); + Debug.print "\n"; }; - Prim.debugPrint "\nInventory info\n----------------\n"; + Debug.print "\nInventory info\n----------------\n"; for ( info in ((await server.allInventoryInfo()).vals()) ) { - Prim.debugPrint "- "; - Prim.debugPrint (debug_show info); - Prim.debugPrint "\n"; + Debug.print "- "; + Debug.print (debug_show info); + Debug.print "\n"; }; - Prim.debugPrint "\nRoute info\n----------------\n"; + Debug.print "\nRoute info\n----------------\n"; for ( info in ((await server.allRouteInfo()).vals()) ) { - Prim.debugPrint "- "; - Prim.debugPrint (debug_show info); - Prim.debugPrint "\n"; + Debug.print "- "; + Debug.print (debug_show info); + Debug.print "\n"; }; }; diff --git a/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.mo b/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.mo index 54f00cb28f3..c434db2fef2 100644 --- a/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.mo +++ b/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.mo @@ -1,19 +1,15 @@ -import Prim "mo:prim"; +import Debug "../../../debug.mo"; import T = "../serverTypes.mo"; import A = "../serverActor.mo"; import Result = "../../../result.mo"; import Option = "../../../option.mo"; func printEntityCount(entname:Text, count:Nat) { - Prim.debugPrint ("- " # entname # " count: "); - Prim.debugPrintInt count; - Prim.debugPrint "\n"; + Debug.print ("- " # entname # " count: " # debug_show count # "\n"); }; func printLabeledCost(lab:Text, cost:Nat) { - Prim.debugPrint ("- " # lab # " cost: "); - Prim.debugPrintInt cost; - Prim.debugPrint "\n"; + Debug.print ("- " # lab # " cost: " # debug_show cost # "\n"); }; actor class Test() = this { @@ -22,7 +18,7 @@ actor class Test() = this { { let s = A.Server(); - Prim.debugPrint "\nExchange setup: Begin...\n====================================\n"; + Debug.print "\nExchange setup: Begin...\n====================================\n"; let pka = "beef"; let pkb = "dead"; @@ -290,13 +286,13 @@ actor class Test() = this { ////////////////////////////////////////////////////////////////// - Prim.debugPrint "\nExchange setup: Done.\n====================================\n"; + Debug.print "\nExchange setup: Done.\n====================================\n"; await debugDumpAll(s); ////////////////////////////////////////////////////////////////// - Prim.debugPrint "\nRetailer queries\n====================================\n"; + Debug.print "\nRetailer queries\n====================================\n"; // do some queries await retailerQueryAll(s, pka, ? Result.assertUnwrapAny(uida)); @@ -305,32 +301,32 @@ actor class Test() = this { await retailerQueryAll(s, pkd, ? Result.assertUnwrapAny(uidd)); await retailerQueryAll(s, pke, ? Result.assertUnwrapAny(uide)); - Prim.debugPrint "\nQuery counts\n----------------\n"; + Debug.print "\nQuery counts\n----------------\n"; let counts = await s.getCounts(); printEntityCount("Retailer join", counts.retailer_join_count); printEntityCount("Retailer query", counts.retailer_query_count); printLabeledCost("Retailer query", counts.retailer_query_cost); - Prim.debugPrint "\nAuthentication test:\n====================================\n"; + Debug.print "\nAuthentication test:\n====================================\n"; - Prim.debugPrint "\npk a == uid a"; + Debug.print "\npk a == uid a"; assert(await s.validateUser(pka, Result.assertUnwrapAny(uida))); - Prim.debugPrint "\npk b == uid b"; + Debug.print "\npk b == uid b"; assert(await s.validateUser(pkb, Result.assertUnwrapAny(uidb))); - Prim.debugPrint "\npk a != uid b"; + Debug.print "\npk a != uid b"; assert(not(await s.validateUser(pka, Result.assertUnwrapAny(uidb)))); - Prim.debugPrint "\npk b != uid a"; + Debug.print "\npk b != uid a"; assert(not(await s.validateUser(pkb, Result.assertUnwrapAny(uida)))); ////////////////////////////////////////////////////////////////// // xxx --- todo: separate test(s) for expected failures // User c should not be able to remove user a's route if false { - Prim.debugPrint "\nAuthentication test, expect Result.assertion failure:\n"; + Debug.print "\nAuthentication test, expect Result.assertion failure:\n"; ignore(await s.transporterRemRoute(pkc, Result.assertUnwrapAny(rta_a_c_tta))) }; - Prim.debugPrint "\n"; + Debug.print "\n"; }) }; }; @@ -338,84 +334,80 @@ actor class Test() = this { func retailerQueryAll(server:A.Server, pk:Text, r:?T.UserId) : async () { - Prim.debugPrint "\nRetailer "; let retailerId: T.UserId = Option.unwrap(r); - Prim.debugPrintInt retailerId; - Prim.debugPrint " sends `retailerQueryAll`\n"; - Prim.debugPrint "------------------------------------\n"; + Debug.print ("\nRetailer " # debug_show retailerId # " sends `retailerQueryAll`\n"); + Debug.print "------------------------------------\n"; - Prim.debugPrint "\n## Query begin:\n"; + Debug.print "\n## Query begin:\n"; let res = Result.assertUnwrapAny( await server.retailerQueryAll(pk, retailerId, null, null) ); - Prim.debugPrint "\n## Query end."; + Debug.print "\n## Query end."; - Prim.debugPrint "\n## Query results ("; - Prim.debugPrintInt (res.len()); - Prim.debugPrint ")\n"; + Debug.print ("\n## Query results (" # debug_show res.len() # ")\n"); for (info in res.vals()) { - Prim.debugPrint "- "; - Prim.debugPrint (debug_show info); - Prim.debugPrint "\n"; + Debug.print "- "; + Debug.print (debug_show info); + Debug.print "\n"; } }; func debugDumpAll(server:A.Server) : async () { - Prim.debugPrint "\nTruck type info\n----------------\n"; + Debug.print "\nTruck type info\n----------------\n"; for ( info in ((await server.allTruckTypeInfo()).vals()) ) { - Prim.debugPrint "- "; - Prim.debugPrint (debug_show info); - Prim.debugPrint "\n"; + Debug.print "- "; + Debug.print (debug_show info); + Debug.print "\n"; }; - Prim.debugPrint "\nRegion info\n----------------\n"; + Debug.print "\nRegion info\n----------------\n"; for ( info in ((await server.allRegionInfo()).vals()) ) { - Prim.debugPrint "- "; - Prim.debugPrint (debug_show info); - Prim.debugPrint "\n"; + Debug.print "- "; + Debug.print (debug_show info); + Debug.print "\n"; }; - Prim.debugPrint "\nProduce info\n----------------\n"; + Debug.print "\nProduce info\n----------------\n"; for ( info in ((await server.allProduceInfo()).vals()) ) { - Prim.debugPrint "- "; - Prim.debugPrint (debug_show info); - Prim.debugPrint "\n"; + Debug.print "- "; + Debug.print (debug_show info); + Debug.print "\n"; }; - Prim.debugPrint "\nProducer info\n----------------\n"; + Debug.print "\nProducer info\n----------------\n"; for ( info in ((await server.allProducerInfo()).vals()) ) { - Prim.debugPrint "- "; - Prim.debugPrint (debug_show info); - Prim.debugPrint "\n"; + Debug.print "- "; + Debug.print (debug_show info); + Debug.print "\n"; }; - Prim.debugPrint "\nTransporter info\n----------------\n"; + Debug.print "\nTransporter info\n----------------\n"; for ( info in ((await server.allTransporterInfo()).vals()) ) { - Prim.debugPrint "- "; - Prim.debugPrint (debug_show info); - Prim.debugPrint "\n"; + Debug.print "- "; + Debug.print (debug_show info); + Debug.print "\n"; }; - Prim.debugPrint "\nRetailer info\n----------------\n"; + Debug.print "\nRetailer info\n----------------\n"; for ( info in ((await server.allRetailerInfo()).vals()) ) { - Prim.debugPrint "- "; - Prim.debugPrint (debug_show info); - Prim.debugPrint "\n"; + Debug.print "- "; + Debug.print (debug_show info); + Debug.print "\n"; }; - Prim.debugPrint "\nInventory info\n----------------\n"; + Debug.print "\nInventory info\n----------------\n"; for ( info in ((await server.allInventoryInfo()).vals()) ) { - Prim.debugPrint "- "; - Prim.debugPrint (debug_show info); - Prim.debugPrint "\n"; + Debug.print "- "; + Debug.print (debug_show info); + Debug.print "\n"; }; - Prim.debugPrint "\nRoute info\n----------------\n"; + Debug.print "\nRoute info\n----------------\n"; for ( info in ((await server.allRouteInfo()).vals()) ) { - Prim.debugPrint "- "; - Prim.debugPrint (debug_show info); - Prim.debugPrint "\n"; + Debug.print "- "; + Debug.print (debug_show info); + Debug.print "\n"; }; }; From 81c1ad4a8999c24630543d91d71c60a96b3a812a Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 13 Jan 2020 12:59:51 +0100 Subject: [PATCH 0916/1176] compile_local_function: Do not use `VarLoc.deferred` (#1102) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `Varloc.deferred` stuff in the backend is quite an ugly hack, and I want to get rid of it. This gets rid of one of the two uses of it. (I know that the method names in the `VarEnv` are kinda unhelpful, because there `local` may refer to “local Mokoto variable” and “Wasm local”.) --- src/codegen/compile.ml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 51ac560b554..298901700ed 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -4447,10 +4447,13 @@ module VarEnv = struct let d = {stack_rep; materialize; is_local} in { ae with vars = NameEnv.add name (VarLoc.Deferred d) ae.vars } + let add_local_local env (ae : t) name i = + { ae with vars = NameEnv.add name (VarLoc.Local i) ae.vars } + let add_direct_local env (ae : t) name = let i = E.add_anon_local env I32Type in E.add_local_name env i name; - ({ ae with vars = NameEnv.add name (VarLoc.Local i) ae.vars }, i) + (add_local_local env ae name i, i) (* Adds the names to the environment and returns a list of setters *) let rec add_argument_locals env (ae : t) = function @@ -4562,14 +4565,13 @@ end (* Var *) (* This comes late because it also deals with messages *) module FuncDec = struct - let bind_args ae0 first_arg as_ bind_arg = + let bind_args env ae0 first_arg args = let rec go i ae = function | [] -> ae - | a::as_ -> - let get = G.i (LocalGet (nr (Int32.of_int i))) in - let ae' = bind_arg ae a get in - go (i+1) ae' as_ in - go first_arg ae0 as_ + | a::args -> + let ae' = VarEnv.add_local_local env ae a.it (Int32.of_int i) in + go (i+1) ae' args in + go first_arg ae0 args (* Create a WebAssembly func from a pattern (for the argument) and the body. Parameter `captured` should contain the, well, captured local variables that @@ -4584,10 +4586,8 @@ module FuncDec = struct let (ae1, closure_code) = restore_env env ae0 get_closure in - (* Add arguments to the environment *) - let ae2 = bind_args ae1 1 args (fun env a get -> - VarEnv.add_local_deferred env a.it SR.Vanilla (fun _ -> get) true - ) in + (* Add arguments to the environment (shifted by 1) *) + let ae2 = bind_args env ae1 1 args in closure_code ^^ mk_body env ae2 From b85c417bce7dee1b28b20583d31245cc72ce220b Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 13 Jan 2020 14:17:54 +0100 Subject: [PATCH 0917/1176] AllocHow.decs: Also do fixed-point iteration for top-level blocks (#1099) * AllocHow.decs: Also do fixed-point iteration for top-level blocks Previously, the code was taking some short-cuts for top-level blocks, and that was fine. But I want more than just functions to be static, and the two different implementations here were a problem. So this unifies them again, making just surgical adjustments where needed. No change to any wasm output. Adds a test case that I broke along the way. * Update src/codegen/compile.ml Co-Authored-By: Gabor Greif * Update src/codegen/compile.ml Co-Authored-By: Gabor Greif * fix compilation Co-authored-by: Gabor Greif --- src/codegen/compile.ml | 125 +++++++++++++++++++++-------------------- test/run/issue1099.mo | 4 ++ 2 files changed, 67 insertions(+), 62 deletions(-) create mode 100644 test/run/issue1099.mo diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 298901700ed..a2cbd849377 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -4420,7 +4420,13 @@ module VarEnv = struct *) let mk_fun_ae ae = { ae with - vars = NameEnv.filter (fun _ -> VarLoc.is_non_local) ae.vars; + vars = NameEnv.filter (fun v l -> + let non_local = VarLoc.is_non_local l in + (* For debugging, enable this: + (if not non_local then Printf.eprintf "VarEnv.mk_fun_ae: Removing %s\n" v); + *) + non_local + ) ae.vars; } let lookup_var ae var = match NameEnv.find_opt var ae.vars with @@ -4941,11 +4947,6 @@ module AllocHow = struct These rules require a fixed-point analysis. - For the top-level blocks the rules are simpler - - all functions are static - - everything that is captured in a function is statically heap allocated - - everything else is a local - We represent this as a lattice as follows: *) @@ -4973,6 +4974,13 @@ module AllocHow = struct let map_of_set x s = S.fold (fun v m -> M.add v x m) s M.empty let set_of_map m = M.fold (fun v _ m -> S.add v m) m S.empty + let is_local_mut _ b = LocalMut = b + + let is_not_static _ = function + | StoreStatic -> false + | _ -> true + + let is_static ae how f = (* Does this capture nothing from outside? *) (S.is_empty (S.inter @@ -4981,23 +4989,37 @@ module AllocHow = struct (* Does this capture nothing non-static from here? *) (S.is_empty (S.inter (Freevars.captured_vars f) - (set_of_map (M.filter (fun _ h -> h != StoreStatic) how)))) + (set_of_map (M.filter is_not_static how)))) let is_func_exp exp = match exp.it with | FuncE _ -> true | _ -> false - let is_static_exp env how0 exp = - (* Functions are static when they do not capture anything *) + let is_static_exp env lvl how0 exp = + (* Functions are static when they are on the top-level or do not capture anything *) if is_func_exp exp - then is_static env how0 (Freevars.exp exp) + then lvl = TopLvl || is_static env how0 (Freevars.exp exp) else false - let is_local_mut _ = function - | LocalMut -> true - | _ -> false + let store_heap lvl = match lvl with + (* In the top level, never store in the dynamic heap; either use + locals or static heap *) + | TopLvl -> StoreStatic + | NotTopLvl -> StoreHeap + + let how_captured how lvl captured = + (* Some captured variables must be on the heap + * For local blocks, mutable things suffice (the others can be copied to the closure + by value) + * For top-level blocks, everything non-static should be statically allocated + *) + let force_to_heap = match lvl with + | TopLvl -> is_not_static + | NotTopLvl -> is_local_mut in + map_of_set (store_heap lvl) + (S.inter (set_of_map (M.filter force_to_heap how)) captured) - let dec_local env (seen, how0) dec = + let dec env lvl (seen, how0) dec = let (f,d) = Freevars.dec dec in let captured = Freevars.captured_vars f in @@ -5007,7 +5029,7 @@ module AllocHow = struct | VarD _ -> map_of_set LocalMut d (* Static functions in an let-expression *) - | LetD ({it = VarP _; _}, e) when is_static_exp env how0 e -> + | LetD ({it = VarP _; _}, e) when is_static_exp env lvl how0 e -> M.empty (* Everything else needs at least a local *) | _ -> @@ -5017,55 +5039,26 @@ module AllocHow = struct These need to be heap-allocated. *) let how2 = - map_of_set StoreHeap + map_of_set (store_heap lvl) (S.inter (set_of_map how0) (S.diff (Freevars.captured_vars f) seen)) in - (* Do we capture anything else? - For local blocks, mutable things must be heap allocated. - *) - let how3 = - map_of_set StoreHeap - (S.inter (set_of_map (M.filter is_local_mut how0)) captured) in + (* More captures? *) + let how3 = how_captured how0 lvl captured in let how = List.fold_left join M.empty [how0; how1; how2; how3] in let seen' = S.union seen d in (seen', how) - let decs_local env decs captured_in_body : allocHow = + let decs env lvl decs captured_in_body : allocHow = let rec go how = - let _seen, how1 = List.fold_left (dec_local env) (S.empty, how) decs in - let how2 = map_of_set StoreHeap - (S.inter (set_of_map (M.filter is_local_mut how1)) captured_in_body) in + let _seen, how1 = List.fold_left (dec env lvl) (S.empty, how) decs in + let how2 = how_captured how1 lvl captured_in_body in let how' = join how1 how2 in - if M.equal (=) how how' then how else go how' in + if M.equal (=) how how' then how' else go how' in go M.empty - let decs_top_lvl env decs captured_in_body : allocHow = - let how0 = M.empty in - (* All non-function are at least locals *) - let how1 = - let go how dec = - let (f,d) = Freevars.dec dec in - match dec.it with - | LetD ({it = VarP _; _}, e) when is_func_exp e -> how - | _ -> join how (map_of_set LocalMut d) in - List.fold_left go how0 decs in - (* All captured non-functions are heap allocated *) - let how2 = join how1 (map_of_set StoreStatic (S.inter (set_of_map how1) captured_in_body)) in - let how3 = - let go how dec = - let (f,d) = Freevars.dec dec in - let captured = Freevars.captured_vars f in - join how (map_of_set StoreStatic (S.inter (set_of_map how1) captured)) in - List.fold_left go how2 decs in - how3 - - let decs env lvl decs captured_in_body : allocHow = match lvl with - | TopLvl -> decs_top_lvl env decs captured_in_body - | NotTopLvl -> decs_local env decs captured_in_body - (* Functions to extend the environment (and possibly allocate memory) based on how we want to store them. *) let add_how env ae name : nonStatic option -> VarEnv.t * G.t = function @@ -6546,6 +6539,7 @@ and compile_dec env pre_ae how v2en dec : VarEnv.t * G.t * (VarEnv.t -> G.t) = let pre_ae1 = VarEnv.add_local_deferred pre_ae v (SR.StaticThing static_thing) (fun _ -> G.nop) false in ( pre_ae1, G.nop, fun ae -> fill env ae; G.nop) + | LetD (p, e) -> let (pre_ae1, alloc_code, pat_arity, fill_code) = compile_n_ary_pat env pre_ae how p in ( pre_ae1, alloc_code, fun ae -> @@ -6563,11 +6557,8 @@ and compile_dec env pre_ae how v2en dec : VarEnv.t * G.t * (VarEnv.t -> G.t) = Var.set_val env ae name ) -and compile_decs env ae lvl decs captured_in_body : VarEnv.t * G.t = - compile_decs_public env ae lvl decs E.NameEnv.empty captured_in_body - -and compile_decs_public env ae lvl decs v2en captured_in_body : VarEnv.t * G.t = - let how = AllocHow.decs ae lvl decs captured_in_body in +and compile_decs_open env pre_ae lvl decs v2en captured_in_body : VarEnv.t * G.t * (VarEnv.t -> G.t)= + let how = AllocHow.decs pre_ae lvl decs captured_in_body in let rec go pre_ae decs = match decs with | [] -> (pre_ae, G.nop, fun _ -> G.nop) | [dec] -> compile_dec env pre_ae how v2en dec @@ -6576,14 +6567,20 @@ and compile_decs_public env ae lvl decs v2en captured_in_body : VarEnv.t * G.t = let (pre_ae2, alloc_code2, mk_code2) = go pre_ae1 decs in ( pre_ae2, alloc_code1 ^^ alloc_code2, - fun env -> let code1 = mk_code1 env in - let code2 = mk_code2 env in - code1 ^^ code2 + fun ae -> let code1 = mk_code1 ae in + let code2 = mk_code2 ae in + code1 ^^ code2 ) in - let (ae1, alloc_code, mk_code) = go ae decs in + go pre_ae decs + +and compile_decs_public env ae lvl decs v2en captured_in_body : VarEnv.t * G.t = + let (ae1, alloc_code, mk_code) = compile_decs_open env ae lvl decs v2en captured_in_body in let code = mk_code ae1 in (ae1, alloc_code ^^ code) +and compile_decs env ae lvl decs captured_in_body : VarEnv.t * G.t = + compile_decs_public env ae lvl decs E.NameEnv.empty captured_in_body + and compile_top_lvl_expr env ae e = match e.it with | BlockE (decs, exp) -> let captured = Freevars.captured_vars (Freevars.exp e) in @@ -6608,8 +6605,12 @@ and compile_static_exp env pre_ae how exp = match exp.it with | Type.Promises -> assert false in let mk_body env ae = assert begin (* Is this really closed? *) - List.for_all (fun v -> VarEnv.NameEnv.mem v ae.VarEnv.vars) - (Freevars.M.keys (Freevars.exp e)) + List.for_all (fun v -> + let found = VarEnv.NameEnv.mem v ae.VarEnv.vars in + (if not found then Printf.eprintf "internal error: static %s captures %s, not found in static environment\n" + name v); + found + ) (Freevars.M.keys (Freevars.exp e)) end; compile_exp_as env ae (StackRep.of_arity (List.length return_tys)) e in FuncDec.closed env sort control name args mk_body return_tys exp.at diff --git a/test/run/issue1099.mo b/test/run/issue1099.mo new file mode 100644 index 00000000000..8bf32b65bb3 --- /dev/null +++ b/test/run/issue1099.mo @@ -0,0 +1,4 @@ +let M = module { public func foo() = () }; +module { + public func bar() = M.foo(); +} From 17dcbb1145f6b0e874601d1c8f8d654014b270c6 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 13 Jan 2020 14:46:43 +0100 Subject: [PATCH 0918/1176] Performance tracking: Also track gas usage (#1101) * Performance tracking: Also track gas usage this is going to be exciting * Update test/drun-wrapper.sh Co-authored-by: Gabor Greif --- test/drun-wrapper.sh | 9 +++++++++ test/drun.toml | 4 ++++ test/run.sh | 6 +++++- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/test/drun-wrapper.sh b/test/drun-wrapper.sh index e4888df2186..12836c6e77c 100755 --- a/test/drun-wrapper.sh +++ b/test/drun-wrapper.sh @@ -3,6 +3,15 @@ DRUN=${DRUN:-drun} CONFIG=$(realpath $(dirname $0)/drun.toml) +# +# This script wraps drun to +# +# * extract the methods calls from comments in the second argument +# (typically the test source files) +# * adds "ic:000000000000040054" as the destination to these calls +# * writes prometheus metrics to file descriptor 222 +# (for run.sh -p; post-processing happening in run.sh) +# if [ -z "$1" ] diff --git a/test/drun.toml b/test/drun.toml index 37e4b23227c..2f020c9f7b5 100644 --- a/test/drun.toml +++ b/test/drun.toml @@ -2,3 +2,7 @@ scheduler_cores = 1 round_gas_max = 10_000_000_000_000 exec_gas = 1_000_000_000_000 + +[metrics] +exporter = { file = "/dev/fd/222" } + diff --git a/test/run.sh b/test/run.sh index ff351a252d2..61444d05c12 100755 --- a/test/run.sh +++ b/test/run.sh @@ -295,7 +295,11 @@ do run_if stub.wasm ic-stub-run $IC_STUB_RUN_WRAPPER $out/$base.stub.wasm $mangled elif [ $PERF = yes ] then - run_if wasm drun-run $DRUN_WRAPPER $out/$base.wasm $mangled + run_if wasm drun-run $DRUN_WRAPPER $out/$base.wasm $mangled 222> $out/$base.metrics + if [ -e $out/$base.metrics -a -n "$PERF_OUT" ] + then + LANG=C perl -ne "print \"gas/$base;\$1\n\" if /^gas_consumed_per_round_sum (\\d+)\$/" $out/$base.metrics >> $PERF_OUT; + fi else run_if wasm wasm-run $WASMTIME $WASMTIME_OPTIONS $out/$base.wasm fi From a7fe7b43f23c38d509f4a89dea00da75311a121f Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Mon, 13 Jan 2020 15:14:23 +0100 Subject: [PATCH 0919/1176] Iterate over Blobs (#1100) * move compute_crc32 to blob.c, add iterator stuff * implement Blob blob_iter protocol * implement accessors for Blob in the interpreter, add test * make Blobs have a size, resolving an interpreter ambiguity * use generic value iteration * port text iteration to generic value iterators, removing a bunch of cruft in the process --- rts/Makefile | 2 +- rts/blob.c | 80 ++++++++++++++++++++++++++ rts/text.c | 41 ------------- src/codegen/compile.ml | 26 ++++++++- src/lowering/desugar.ml | 12 ++++ src/mo_frontend/typing.ml | 8 +++ src/mo_interpreter/interpret.ml | 21 +++++++ src/mo_values/prim.ml | 28 +++++---- src/mo_values/value.ml | 4 +- src/mo_values/value.mli | 4 +- src/prelude/prelude.ml | 13 +++++ test/run-drun/caller.mo | 10 ++++ test/run-drun/ok/caller.drun-run.ok | 2 + test/run-drun/ok/caller.ic-stub-run.ok | 4 ++ test/run/caller.mo | 5 ++ 15 files changed, 201 insertions(+), 59 deletions(-) create mode 100644 rts/blob.c diff --git a/rts/Makefile b/rts/Makefile index f07db20ad95..c577959c088 100644 --- a/rts/Makefile +++ b/rts/Makefile @@ -81,7 +81,7 @@ TOMMATH_NATIVE_O=$(TOMMATHFILES:%=_build/native/tommath_%.o) # Our part of the RTS, Wasm and native # -RTSFILES=rts idl bigint buf utf8_valid closure-table text url +RTSFILES=rts idl bigint buf utf8_valid closure-table text blob url _build/wasm/%.o: %.c rts.h buf.h | _build/wasm $(WASM_CLANG) -c $(CLANG_FLAGS) $(WASM_FLAGS) $(TOMMATH_FLAGS) -I$(TOMMATHSRC) --std=c11 $< --output $@ diff --git a/rts/blob.c b/rts/blob.c new file mode 100644 index 00000000000..517a1f90eb6 --- /dev/null +++ b/rts/blob.c @@ -0,0 +1,80 @@ +#include "rts.h" + +typedef as_ptr blob_t; // a skewed pointer to a Blob heap object + +// CRC32 for blobs + +// loosely based on https://rosettacode.org/wiki/CRC-32#Implementation_2 +// +export uint32_t compute_crc32(blob_t b) +{ + if (TAG(b) != TAG_BLOB) rts_trap_with("compute_crc32: Blob expected"); + + uint32_t crc = 0; + const char *buf = BLOB_PAYLOAD(b); + size_t len = BLOB_LEN(b); + + static uint32_t const table[256] = { + 0x0, 0x77073096, 0xee0e612c, 0x990951ba, 0x76dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0xedb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x9b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x1db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x6b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0xf00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x86d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x3b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x4db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0xd6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0xa00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x26d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x5005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0xcb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0xbdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d + }; + + crc = ~crc; + const char *q = buf + len; + for (const char *p = buf; p < q; p++) { + uint8_t octet = *p; /* Cast to unsigned octet. */ + crc = (crc >> 8) ^ table[(crc & 0xff) ^ octet]; + } + + return ~crc; +} + + +// Iterators + +// The iterator needs to point to a specific position into the blob +// +// This is currently a simple pair: +// 1. a pointer to the blob +// 2. index into that blob (shifted by two for GC's sake) +// + +typedef as_ptr blob_iter_t; // the data structure used to iterate a text value +#define BLOB_ITER_BLOB(p) (TUPLE_FIELD(p,0,blob_t)) +#define BLOB_ITER_POS(p) (TUPLE_FIELD(p,1,uint32_t)) + + +export blob_iter_t blob_iter(blob_t s) { + as_ptr i = alloc_words(TUPLE_HEADER_SIZE + 2); + TAG(i) = TAG_ARRAY; + BLOB_ITER_BLOB(i) = s; + BLOB_ITER_POS(i) = 0; + return i; +} + +export uint32_t blob_iter_done(blob_iter_t i) { + size_t n = BLOB_ITER_POS(i) >> 2; + blob_t s = BLOB_ITER_BLOB(i); + return n >= BLOB_LEN(s); +} + +export uint32_t blob_iter_next(blob_iter_t i) { + size_t n = BLOB_ITER_POS(i) >> 2; + blob_t s = BLOB_ITER_BLOB(i); + BLOB_ITER_POS(i) = (n + 1) << 2; + return *(uint8_t*)(BLOB_PAYLOAD(s) + n); +} diff --git a/rts/text.c b/rts/text.c index 819351a55c7..afab1543cfc 100644 --- a/rts/text.c +++ b/rts/text.c @@ -323,44 +323,3 @@ export uint32_t text_iter_next(text_iter_t i) { return c; } } - -// CRC32 for blobs - -// loosely based on https://rosettacode.org/wiki/CRC-32#Implementation_2 -// -export uint32_t compute_crc32(blob_t b) -{ - if (TAG(b) != TAG_BLOB) rts_trap_with("compute_crc32: Blob expected"); - - uint32_t crc = 0; - const char *buf = BLOB_PAYLOAD(b); - size_t len = BLOB_LEN(b); - - static uint32_t const table[256] = { - 0x0, 0x77073096, 0xee0e612c, 0x990951ba, 0x76dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0xedb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x9b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, - 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, - 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, - 0x76dc4190, 0x1db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x6b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0xf00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x86d3d2d, 0x91646c97, 0xe6635c01, - 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, - 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, - 0xedb88320, 0x9abfb3b6, 0x3b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x4db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0xd6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0xa00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, - 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, - 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x26d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x5005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0xcb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0xbdbdf21, - 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, - 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d - }; - - crc = ~crc; - const char *q = buf + len; - for (const char *p = buf; p < q; p++) { - uint8_t octet = *p; /* Cast to unsigned octet. */ - crc = (crc >> 8) ^ table[(crc & 0xff) ^ octet]; - } - - return ~crc; -} diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index a2cbd849377..06849fa2497 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -665,6 +665,9 @@ module RTS = struct E.add_func_import env "rts" "text_to_buf" [I32Type; I32Type] []; E.add_func_import env "rts" "blob_of_ic_url" [I32Type] [I32Type]; E.add_func_import env "rts" "compute_crc32" [I32Type] [I32Type]; + E.add_func_import env "rts" "blob_iter_done" [I32Type] [I32Type]; + E.add_func_import env "rts" "blob_iter" [I32Type] [I32Type]; + E.add_func_import env "rts" "blob_iter_next" [I32Type] [I32Type]; () end (* RTS *) @@ -2488,6 +2491,16 @@ module Blob = struct end ) + let len env = + Heap.load_field len_field ^^ BigNum.from_word32 env + let iter env = + E.call_import env "rts" "blob_iter" + let iter_done env = + E.call_import env "rts" "blob_iter_done" + let iter_next env = + E.call_import env "rts" "blob_iter_next" ^^ + UnboxedSmallWord.msb_adjust Type.Word8 + let dyn_alloc_scratch env = alloc env ^^ payload_ptr_unskewed end (* Blob *) @@ -2812,7 +2825,7 @@ module Dfinity = struct let (set_blob, get_blob) = new_local env "blob" in get_str ^^ Text.to_blob env ^^ set_blob ^^ get_blob ^^ Blob.payload_ptr_unskewed ^^ - get_blob ^^ Heap.load_field (Blob.len_field) ^^ + get_blob ^^ Heap.load_field Blob.len_field ^^ print_ptr_len env ) @@ -2825,7 +2838,7 @@ module Dfinity = struct let ic_trap_str env = Func.share_code1 env "ic_trap" ("str", I32Type) [] (fun env get_str -> get_str ^^ Blob.payload_ptr_unskewed ^^ - get_str ^^ Heap.load_field (Blob.len_field) ^^ + get_str ^^ Heap.load_field Blob.len_field ^^ ic_trap env ) @@ -5948,6 +5961,15 @@ and compile_exp (env : E.t) ae exp = | OtherPrim "text_iter_next", [e] -> SR.Vanilla, compile_exp_vanilla env ae e ^^ Text.iter_next env + | OtherPrim "blob_size", [e] -> + SR.Vanilla, compile_exp_vanilla env ae e ^^ Blob.len env + | OtherPrim "blob_iter", [e] -> + SR.Vanilla, compile_exp_vanilla env ae e ^^ Blob.iter env + | OtherPrim "blob_iter_done", [e] -> + SR.Vanilla, compile_exp_vanilla env ae e ^^ Blob.iter_done env + | OtherPrim "blob_iter_next", [e] -> + SR.Vanilla, compile_exp_vanilla env ae e ^^ Blob.iter_next env + | OtherPrim "abs", [e] -> SR.Vanilla, compile_exp_vanilla env ae e ^^ diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 7b3b33a00d0..c5d21ec6360 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -76,6 +76,8 @@ and exp' at note = function | S.TagE (c, e) -> I.TagE (c.it, exp e) | S.DotE (e, x) when T.is_array e.note.S.note_typ -> (array_dotE e.note.S.note_typ x.it (exp e)).it + | S.DotE (e, x) when T.is_prim T.Blob e.note.S.note_typ -> + (blob_dotE x.it (exp e)).it | S.DotE (e, x) when T.is_prim T.Text e.note.S.note_typ -> (text_dotE x.it (exp e)).it | S.DotE (e, x) -> @@ -257,6 +259,16 @@ and array_dotE array_ty proj e = | false, "vals" -> call "@immut_array_vals" [] [T.iter_obj varA] | _, _ -> assert false +and blob_dotE proj e = + let fun_ty t1 t2 = T.Func (T.Local, T.Returns, [], t1, t2) in + let call name t1 t2 = + let f = idE name (fun_ty [T.blob] [fun_ty t1 t2]) in + callE f [] e in + match proj with + | "size" -> call "@blob_size" [] [T.nat] + | "bytes" -> call "@blob_bytes" [] [T.iter_obj T.(Prim Word8)] + | _ -> assert false + and text_dotE proj e = let fun_ty t1 t2 = T.Func (T.Local, T.Returns, [], t1, t2) in let call name t1 t2 = diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 799e38f1272..e3ddba4563e 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -534,6 +534,13 @@ let array_obj t = Object, List.sort compare_field (match t with Mut t' -> mut t' | t -> immut t) +let blob_obj () = + let open T in + Object, + [ {lab = "bytes"; typ = Func (Local, Returns, [], [], [iter_obj (Prim Word8)])}; + {lab = "size"; typ = Func (Local, Returns, [], [], [Prim Nat])}; + ] + let text_obj () = let open T in Object, @@ -676,6 +683,7 @@ and infer_exp'' env exp : T.typ = let _s, tfs = try T.as_obj_sub [id.it] t1 with Invalid_argument _ -> try array_obj (T.as_array_sub t1) with Invalid_argument _ -> + try blob_obj (T.as_prim_sub T.Blob t1) with Invalid_argument _ -> try text_obj (T.as_prim_sub T.Text t1) with Invalid_argument _ -> error env exp1.at "expected object type, but expression produces type\n %s" diff --git a/src/mo_interpreter/interpret.ml b/src/mo_interpreter/interpret.ml index c435d9490c4..ce68db3e73b 100644 --- a/src/mo_interpreter/interpret.ml +++ b/src/mo_interpreter/interpret.ml @@ -314,6 +314,25 @@ let array_vals a at = in k (V.Obj (V.Env.singleton "next" next)) ) +let blob_bytes t at = + V.local_func 0 1 (fun c v k -> + V.as_unit v; + let i = ref 0 in + let next = + V.local_func 0 1 (fun c v k' -> + if !i = String.length t + then k' V.Null + else let v = V.Opt V.(Word8 (Word8.of_int_u (Char.code (String.get t !i)))) in incr i; k' v + ) + in k (V.Obj (V.Env.singleton "next" next)) + ) + +let blob_size t at = + V.local_func 0 1 (fun c v k -> + V.as_unit v; + k (V.Int (V.Nat.of_int (String.length t))) + ) + let text_chars t at = V.local_func 0 1 (fun c v k -> V.as_unit v; @@ -446,6 +465,8 @@ and interpret_exp_mut env exp (k : V.value V.cont) = let f = match id.it with | "len" -> text_len | "chars" -> text_chars + | "size" -> blob_size + | "bytes" -> blob_bytes | _ -> assert false in k (f s exp.at) | _ -> assert false diff --git a/src/mo_values/prim.ml b/src/mo_values/prim.ml index 1c7329be7d9..6c8bb3a2304 100644 --- a/src/mo_values/prim.ml +++ b/src/mo_values/prim.ml @@ -250,21 +250,27 @@ let prim = function k (Word32 Optint.(to_int32 (Checkseum.Crc32.digest_string s 0 (String.length s) zero))) | "array_len" -> fun _ v k -> k (Int (Int.of_int (Array.length (Value.as_array v)))) + | "blob_size" -> fun _ v k -> + k (Int (Nat.of_int (String.length (Value.as_text v)))) + | "blob_iter" -> fun _ v k -> + let s = String.to_seq (Value.as_text v) in + let valuation b = Word8 (Word8.of_int_u (Char.code b)) in + k (Iter (ref (Seq.map valuation s))) + | "blob_iter_done" | "text_iter_done" -> fun _ v k -> + let i = Value.as_iter v in + k (Bool (!i () = Seq.Nil)) + | "blob_iter_next" | "text_iter_next" -> fun _ v k -> + let i = Value.as_iter v in + begin match !i () with + | Seq.Nil -> assert false + | Seq.Cons (v, vs) -> i := vs; k v + end | "text_len" -> fun _ v k -> k (Int (Nat.of_int (List.length (Wasm.Utf8.decode (Value.as_text v))))) | "text_iter" -> fun _ v k -> let s = Wasm.Utf8.decode (Value.as_text v) in - let i = ref s in - k (TextIter i) - | "text_iter_done" -> fun _ v k -> - let i = Value.as_text_iter v in - k (Bool (!i = [])) - | "text_iter_next" -> fun _ v k -> - let i = Value.as_text_iter v in - begin match !i with - | [] -> assert false - | (c::cs) -> i := cs; k (Char c) - end + let i = Seq.map (fun c -> Char c) (List.to_seq s) in + k (Iter (ref i)) | "Array.init" -> fun _ v k -> (match Value.as_tup v with | [len; x] -> diff --git a/src/mo_values/value.ml b/src/mo_values/value.ml index 810c7dd6570..82079a98879 100644 --- a/src/mo_values/value.ml +++ b/src/mo_values/value.ml @@ -293,7 +293,7 @@ and value = | Func of Call_conv.t * func | Async of async | Mut of value ref - | TextIter of int list ref (* internal to t.char() iterator *) + | Iter of value Seq.t ref (* internal to {b.bytes(), t.chars()} iterator *) and res = Ok of value | Error of value and async = {result : res Lib.Promise.t ; mutable waiters : (value cont * value cont) list} @@ -334,7 +334,7 @@ let as_word64 = function Word64 w -> w | _ -> invalid "as_word64" let as_float = function Float f -> f | _ -> invalid "as_float" let as_char = function Char c -> c | _ -> invalid "as_char" let as_text = function Text s -> s | _ -> invalid "as_text" -let as_text_iter = function TextIter i -> i | _ -> invalid "as_text_iter" +let as_iter = function Iter i -> i | _ -> invalid "as_iter" let as_array = function Array a -> a | _ -> invalid "as_array" let as_opt = function Opt v -> v | _ -> invalid "as_opt" let as_variant = function Variant (i, v) -> i, v | _ -> invalid "as_variant" diff --git a/src/mo_values/value.mli b/src/mo_values/value.mli index e1abd1fc873..201ba7fa7ab 100644 --- a/src/mo_values/value.mli +++ b/src/mo_values/value.mli @@ -107,7 +107,7 @@ and value = | Func of Call_conv.t * func | Async of async | Mut of value ref - | TextIter of int list ref (* internal to t.char() iterator *) + | Iter of value Seq.t ref (* internal to {b.bytes(), t.chars()} iterator *) and res = Ok of value | Error of value and async = {result : res Lib.Promise.t ; mutable waiters : (value cont * value cont) list} @@ -152,7 +152,7 @@ val as_word64 : value -> Word64.t val as_float : value -> Float.t val as_char : value -> unicode val as_text : value -> string -val as_text_iter : value -> int list ref +val as_iter : value -> value Seq.t ref val as_array : value -> value array val as_tup : value -> value list val as_unit : value -> unit diff --git a/src/prelude/prelude.ml b/src/prelude/prelude.ml index e23278e6320..7a019a09f0c 100644 --- a/src/prelude/prelude.ml +++ b/src/prelude/prelude.ml @@ -72,6 +72,19 @@ func @mut_array_vals(xs : [var A]) : (() -> @Iter) = let l = xs.len(); public func next() : ?A { if (i >= l) null else {let j = i; i += 1; ?xs[j]} }; }); +func @blob_size(xs : Blob) : (() -> Nat) = + (func () : Nat = (prim "blob_size" : Blob -> Nat) xs); +func @blob_bytes(xs : Blob) : (() -> @Iter) = + (func () : @Iter = object { + type BlobIter = Any; // not exposed + let i = (prim "blob_iter" : Blob -> BlobIter) xs; + public func next() : ?Word8 { + if ((prim "blob_iter_done" : BlobIter -> Bool) i) + null + else + ?((prim "blob_iter_next" : BlobIter -> Word8) i) + }; + }); func @text_len(xs : Text) : (() -> Nat) = (func () : Nat = (prim "text_len" : Text -> Nat) xs); func @text_chars(xs : Text) : (() -> @Iter) = diff --git a/test/run-drun/caller.mo b/test/run-drun/caller.mo index d3081f0e54e..c7245f88dbe 100644 --- a/test/run-drun/caller.mo +++ b/test/run-drun/caller.mo @@ -36,6 +36,14 @@ actor a { Prim.hashBlob caller; }; + public shared query {caller} func c9() : async Nat { + caller.size(); + }; + + public shared query {caller} func c10() : async ?Word8 { + caller.bytes().next(); + }; + }; ignore a.c1(); //OR-CALL ingress c1 0x4449444C0000 @@ -45,6 +53,8 @@ ignore a.c4(); //OR-CALL ingress c4 0x4449444C0000 ignore a.c6(); //OR-CALL query c6 0x4449444C0000 ignore a.c7(); //OR-CALL ingress c7 0x4449444C0000 ignore a.c8(); //OR-CALL query c8 0x4449444C0000 +ignore a.c9(); //OR-CALL query c9 0x4449444C0000 +ignore a.c10(); //OR-CALL query c10 0x4449444C0000 diff --git a/test/run-drun/ok/caller.drun-run.ok b/test/run-drun/ok/caller.drun-run.ok index 257ddcc26b4..a74b246d435 100644 --- a/test/run-drun/ok/caller.drun-run.ok +++ b/test/run-drun/ok/caller.drun-run.ok @@ -6,3 +6,5 @@ ingress(4) Completed: Canister: Payload: 0x4449444c0000 Ok: Payload: 0x4449444c0000 ingress(6) Completed: Canister: Payload: 0x4449444c016d7b0100080000000000000000 Ok: Payload: 0x4449444c00017969df2265 +Ok: Payload: 0x4449444c00017d08 +Ok: Payload: 0x4449444c016e7b01000100 diff --git a/test/run-drun/ok/caller.ic-stub-run.ok b/test/run-drun/ok/caller.ic-stub-run.ok index 9fda4c73e75..d1a9dd2d121 100644 --- a/test/run-drun/ok/caller.ic-stub-run.ok +++ b/test/run-drun/ok/caller.ic-stub-run.ok @@ -16,3 +16,7 @@ ← completed: 0x4449444c016d7b010003caffee → query c8(0x4449444c0000) ← completed: 0x4449444c00017989f8efb7 +→ query c9(0x4449444c0000) +← completed: 0x4449444c00017d03 +→ query c10(0x4449444c0000) +← completed: 0x4449444c016e7b010001ca diff --git a/test/run/caller.mo b/test/run/caller.mo index 8557229bc2d..6ff1a92c3d1 100644 --- a/test/run/caller.mo +++ b/test/run/caller.mo @@ -9,6 +9,10 @@ actor a { Prim.hashBlob c; }; + public shared query { caller = c } func getCallerSize() : async Nat { + c.size(); + }; + public shared {caller} func c () : async () { let self1 = await getCaller(); let self2 = await getCaller(); @@ -20,3 +24,4 @@ actor a { ignore a.c(); //OR-CALL ingress c 0x4449444C0000 ignore a.getCallerHash(); //OR-CALL ingress getCallerHash 0x4449444C0000 +ignore a.getCallerSize(); //OR-CALL ingress getCallerSize 0x4449444C0000 From d99b9769248b174556a072571c2a6a54874491cf Mon Sep 17 00:00:00 2001 From: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> Date: Mon, 13 Jan 2020 16:13:50 +0100 Subject: [PATCH 0920/1176] Completions for Prim (#1092) * Completes primitive identifiers * shows prim types on hover * fixes merge leftovers * adds a test for hovering over Prim identifiers * Accesses Prim definitions through the new @prim mechanism * Fixes tests for new way of accessing Prim * Update src/languageServer/completion.ml Co-Authored-By: Gabor Greif Co-authored-by: Gabor Greif --- src/languageServer/completion.ml | 33 ++--- src/languageServer/declaration_index.ml | 34 +++-- src/languageServer/declaration_index.mli | 2 +- src/languageServer/hover.ml | 30 +++- src/languageServer/languageServer.ml | 5 +- src/languageServer/source_file.ml | 1 + src/languageServer/source_file_tests.ml | 7 + src/languageServer/vfs.ml | 3 +- test/lsp-int-test-project/ListClient.mo | 1 + test/lsp-int-test-project/app.mo | 2 + test/lsp-int/Main.hs | 178 ++++++++++++++--------- test/lsp-int/lsp-int.cabal | 1 + 12 files changed, 181 insertions(+), 116 deletions(-) diff --git a/src/languageServer/completion.ml b/src/languageServer/completion.ml index 750c11dcd45..f30cf6175d3 100644 --- a/src/languageServer/completion.ml +++ b/src/languageServer/completion.ml @@ -30,6 +30,9 @@ let template_of_ide_decl decl = | DI.TypeDecl ty -> ty.DI.name +let string_of_item (item : Lsp_t.completion_item) : string = + item.Lsp_t.completion_item_label + let item_of_ide_decl (d : DI.ide_decl) : Lsp_t.completion_item = let tmpl = template_of_ide_decl d in match d with @@ -57,7 +60,6 @@ let item_of_ide_decl (d : DI.ide_decl) : Lsp_t.completion_item = params); } - let import_relative_to_project_root root module_path dependency = match Lib.FilePath.relative_to root module_path with | None -> None @@ -128,6 +130,13 @@ let opt_bind f = function let completions index logger project_root file_path file_contents line column = let imported = Source_file.parse_module_header project_root file_path file_contents in let current_uri_opt = Lib.FilePath.relative_to project_root file_path in + let toplevel_decls = + let current_module_decls = + current_uri_opt + |> opt_bind (fun uri -> DI.lookup_module uri index) + |> Fun.flip Lib.Option.get [] in + current_module_decls + in let module_alias_completion_item alias = Lsp_t.{ completion_item_label = alias; @@ -141,24 +150,14 @@ let completions index logger project_root file_path file_contents line column = (* If we don't have any prefix to work with, just suggest the imported module aliases, as well as top-level definitions in the current file *) - let toplevel = - current_uri_opt - |> opt_bind (fun uri -> DI.lookup_module uri index) - |> Option.map (List.map item_of_ide_decl) - |> Fun.flip Lib.Option.get [] in - imported - |> List.map (fun (alias, _) -> module_alias_completion_item alias) - |> List.append toplevel + let decls = List.map item_of_ide_decl toplevel_decls in + decls @ List.map (fun (alias, _) -> module_alias_completion_item alias) imported | Some ("", prefix) -> (* Without an alias but with a prefix we filter the toplevel - idenfiers of the current module *) - current_uri_opt - |> opt_bind (fun uri -> DI.lookup_module uri index) - |> Option.map (fun decls -> - decls - |> List.filter (has_prefix prefix) - |> List.map item_of_ide_decl) - |> Fun.flip Lib.Option.get [] + identifiers of the current module *) + toplevel_decls + |> List.filter (has_prefix prefix) + |> List.map item_of_ide_decl | Some (alias, prefix) -> let module_path = imported diff --git a/src/languageServer/declaration_index.ml b/src/languageServer/declaration_index.ml index 1de1bfa8a31..5760a9d2681 100644 --- a/src/languageServer/declaration_index.ml +++ b/src/languageServer/declaration_index.ml @@ -66,6 +66,9 @@ let lookup_module (Flags.M.find_opt pkg !Flags.package_urls) (fun pkg_path -> Index.find_opt (Filename.concat pkg_path path) index) + | Ok Prim -> + Index.find_opt "@prim" index + | Error _ -> None | _ -> assert false let empty : t = Index.empty @@ -169,24 +172,25 @@ let populate_definitions | Some lib -> List.map (find_def lib) decls -let make_index_inner vfs entry_points : t Diag.result = +let make_index_inner logger vfs entry_points : t Diag.result = Pipeline.load_progs (Vfs.parse_file vfs) entry_points Pipeline.initial_stat_env |> Diag.map (fun (libs, _, scope) -> - Type.Env.fold - (fun path ty acc -> - Index.add - path - (ty - |> read_single_module_lib - |> Fun.flip Lib.Option.get [] - |> populate_definitions libs path) - acc) - scope.Scope.lib_env - Index.empty) - -let make_index vfs entry_points : t Diag.result = + Type.Env.fold + (fun path ty acc -> + Index.add + path + (ty + |> read_single_module_lib + |> Fun.flip Lib.Option.get [] + |> populate_definitions libs path) + acc) + scope.Scope.lib_env + Index.empty) + +let make_index logger vfs entry_points : t Diag.result = (* TODO(Christoph): Actually handle errors here *) - try make_index_inner vfs entry_points with _ -> Diag.return Index.empty + try make_index_inner logger vfs entry_points + with _ -> Diag.return Index.empty diff --git a/src/languageServer/declaration_index.mli b/src/languageServer/declaration_index.mli index edf8149b679..fb9fe1fd66d 100644 --- a/src/languageServer/declaration_index.mli +++ b/src/languageServer/declaration_index.mli @@ -27,4 +27,4 @@ val name_of_ide_decl : ide_decl -> string type path = string val lookup_module : path -> t -> ide_decl list option -val make_index : Vfs.t -> string list -> t Diag.result +val make_index : (string -> string -> unit) -> Vfs.t -> string list -> t Diag.result diff --git a/src/languageServer/hover.ml b/src/languageServer/hover.ml index c990e111c27..2cbc9f2be2d 100644 --- a/src/languageServer/hover.ml +++ b/src/languageServer/hover.ml @@ -1,6 +1,7 @@ open Mo_types open Declaration_index module Lsp = Lsp.Lsp_t +module DI = Declaration_index let hover_detail = function | ValueDecl value -> @@ -13,7 +14,22 @@ let markup_content (msg : string) : Lsp.markup_content = Lsp.{ markup_content_kind = "plaintext"; markup_content_value = msg } -let hover_handler index position file_contents project_root file_path = +let hover_handler + (logger : string -> string -> unit) + (index : DI.t) + (position : Lsp.position) + (file_contents : string) + (project_root : string) + (file_path : string) = + let current_uri_opt = Lib.FilePath.relative_to project_root file_path in + let toplevel_decls = + let current_module_decls = + current_uri_opt + |> Fun.flip Option.bind (fun uri -> lookup_module uri index) + |> Fun.flip Lib.Option.get [] in + current_module_decls in + let mk_hover_result ide_decl = + Lsp.{ hover_result_contents = markup_content (hover_detail ide_decl) } in let hover_result = Option.bind (Source_file.identifier_at_pos @@ -30,13 +46,11 @@ let hover_handler index position file_contents project_root file_path = List.find_opt (fun d -> name_of_ide_decl d = resolved.Source_file.ident) decls) - |> Option.map (fun ide_decl -> - Lsp.{ hover_result_contents = - markup_content (hover_detail ide_decl) }) - | Source_file.Ident _ -> - (* At some point we'll want to look this Ident up in the - local context*) - None + |> Option.map mk_hover_result + | Source_file.Ident ident -> + toplevel_decls + |> List.find_opt (fun d -> name_of_ide_decl d = ident) + |> Option.map mk_hover_result | Source_file.Unresolved _ -> None) in diff --git a/src/languageServer/languageServer.ml b/src/languageServer/languageServer.ml index f50185bec91..eaa8a099911 100644 --- a/src/languageServer/languageServer.ml +++ b/src/languageServer/languageServer.ml @@ -106,7 +106,7 @@ let start entry_point debug = let vfs = ref Vfs.empty in let decl_index = - let ix = match Declaration_index.make_index !vfs [entry_point] with + let ix = match Declaration_index.make_index log_to_file !vfs [entry_point] with | Error(err) -> List.iter (fun e -> log_to_file "Error" (Diag.string_of_message e)) err; Declaration_index.empty @@ -179,6 +179,7 @@ let start entry_point debug = | Some file_content -> let result = Hover.hover_handler + log_to_file !decl_index position file_content @@ -216,7 +217,7 @@ let start entry_point debug = | (_, `TextDocumentDidClose params) -> vfs := Vfs.close_file params !vfs | (_, `TextDocumentDidSave _) -> - let msgs = match Declaration_index.make_index !vfs [entry_point] with + let msgs = match Declaration_index.make_index log_to_file !vfs [entry_point] with | Error msgs' -> msgs' | Ok((ix, msgs')) -> decl_index := ix; diff --git a/src/languageServer/source_file.ml b/src/languageServer/source_file.ml index 76fa8145570..299bb5658a3 100644 --- a/src/languageServer/source_file.ml +++ b/src/languageServer/source_file.ml @@ -44,6 +44,7 @@ let is_package_path (path : string) = let open Pipeline.URL in match parse path with | Ok (Package _) -> true + | Ok Prim -> true | _ -> false let uri_for_package (path : string) = diff --git a/src/languageServer/source_file_tests.ml b/src/languageServer/source_file_tests.ml index a1946b40d5f..1cede45b808 100644 --- a/src/languageServer/source_file_tests.ml +++ b/src/languageServer/source_file_tests.ml @@ -70,6 +70,13 @@ let%test "it parses a simple module header" = "import P \"lib/prelude.mo\"" ["P", "src/lib/prelude.mo"] +let%test "it parses a simple module header that contains a prim import" = + parse_module_header_test_case + "/project" + "/project/src/Main.mo" + "import Prim \"mo:prim\"" + ["Prim", "mo:prim"] + let%test "it parses a simple module header with package paths" = parse_module_header_test_case "/project" diff --git a/src/languageServer/vfs.ml b/src/languageServer/vfs.ml index f121724de5b..4905e764fd9 100644 --- a/src/languageServer/vfs.ml +++ b/src/languageServer/vfs.ml @@ -11,7 +11,8 @@ type t = virtual_file VfsStore.t type uri = string let file_uri_prefix = "file://" ^ Sys.getcwd () ^ "/" -let uri_from_file path = file_uri_prefix ^ path +let uri_from_file path = + if Filename.is_relative path then file_uri_prefix ^ path else "file://" ^ path let file_from_uri logger uri = match Lib.String.chop_prefix file_uri_prefix uri with | Some file -> file diff --git a/test/lsp-int-test-project/ListClient.mo b/test/lsp-int-test-project/ListClient.mo index baa04f1246d..cfc3026321d 100644 --- a/test/lsp-int-test-project/ListClient.mo +++ b/test/lsp-int-test-project/ListClient.mo @@ -1,3 +1,4 @@ +import Prim "mo:prim"; import List "lib/list.mo"; import Option "lib/option.mo"; import P "lib/prelude.mo"; diff --git a/test/lsp-int-test-project/app.mo b/test/lsp-int-test-project/app.mo index b4d2104cd37..1de717cfaf8 100644 --- a/test/lsp-int-test-project/app.mo +++ b/test/lsp-int-test-project/app.mo @@ -1,8 +1,10 @@ import Stack "ListClient.mo"; +import Prim "mo:prim"; actor { func main(): () { let st = Stack.empty(); let newst = Stack.push(0, st); + let primTest: Word8 = Prim.natToWord8(5); } } diff --git a/test/lsp-int/Main.hs b/test/lsp-int/Main.hs index c5795584378..bcdd5b267cc 100644 --- a/test/lsp-int/Main.hs +++ b/test/lsp-int/Main.hs @@ -2,6 +2,7 @@ {-# language DuplicateRecordFields #-} {-# language ExplicitForAll #-} {-# language ScopedTypeVariables #-} +{-# language BlockArguments #-} module Main where @@ -9,16 +10,18 @@ import Prelude hiding (log) import qualified Control.Exception as Exception import Control.Lens ((^.)) -import Control.Monad (unless) +import Control.Monad (unless, guard) import Control.Monad.IO.Class (liftIO) import Data.Default +import Data.Maybe (mapMaybe) import Data.Text (Text) import Language.Haskell.LSP.Test hiding (message) import Language.Haskell.LSP.Types (TextDocumentIdentifier(..), Position(..), HoverContents(..), MarkupContent(..), MarkupKind(..), TextEdit(..), Range(..), DidSaveTextDocumentParams(..), ClientMethod(..), Diagnostic(..)) import Language.Haskell.LSP.Types.Lens (contents, label, detail, message) -import System.Directory (setCurrentDirectory, makeAbsolute) +import System.Directory (setCurrentDirectory, makeAbsolute, removeFile) import System.Environment (getArgs) import System.Exit (exitFailure) +import System.FilePath (()) import System.IO (hPutStr, stderr) import Test.HUnit.Lang (HUnitFailure(..), formatFailureReason) import Test.Hspec (shouldBe, shouldMatchList) @@ -51,6 +54,14 @@ waitForActualDiagnostics = do diags <- waitForDiagnostics if null diags then waitForActualDiagnostics else pure diags +-- | Brackets an action with the closing and opening of a TextDocument +withDoc :: String -> (TextDocumentIdentifier -> Session a) -> Session a +withDoc path action = do + doc <- openDoc path "motoko" + res <- action doc + closeDoc doc + pure res + plainMarkup :: Text -> Maybe HoverContents plainMarkup t = Just @@ -83,6 +94,7 @@ main = do \the test project it's supposed to run in") let [mo_ide, project] = args project <- makeAbsolute project + removeFile (project "ls.log") `Exception.catch` \(_ :: Exception.SomeException) -> pure () setCurrentDirectory project handleHUnitFailure project $ do putStrLn "Starting the session" @@ -95,82 +107,104 @@ main = do log "Initializing" initRes <- initializeResponse log "Hover tests" - doc <- openDoc "ListClient.mo" "motoko" - hoverTestCase - doc - (Position 13 11) - (plainMarkup "push : (T, List) -> List") - hoverTestCase - doc - (Position 16 11) - (plainMarkup "pop : List -> (?T, List)") - hoverTestCase - doc - (Position 50 50) - Nothing + withDoc "ListClient.mo" \doc -> do + hoverTestCase + doc + (Position 14 11) + (plainMarkup "push : (T, List) -> List") + hoverTestCase + doc + (Position 17 11) + (plainMarkup "pop : List -> (?T, List)") + hoverTestCase + doc + (Position 50 50) + Nothing + withDoc "app.mo" \doc -> do + hoverTestCase + doc + (Position 7 39) + (plainMarkup "natToWord8 : Nat -> Word8") log "Completion tests" - -- 14 | List.push(x, s); - -- ==> 14 | List.pus - let edit = TextEdit (Range (Position 13 11) (Position 13 27)) "pus" - _ <- applyEdit doc edit - completionTestCase - doc - -- 14 | List.pus| - (Position 13 14) - [("push",Just "(T, List) -> List")] - closeDoc doc - doc <- openDoc "ListClient.mo" "motoko" - -- 1 | import List - -- ==> 1 | ort List - let edit = TextEdit (Range (Position 0 1) (Position 0 3)) "" - _ <- applyEdit doc edit - sendNotification TextDocumentDidSave (DidSaveTextDocumentParams doc) - (diagnostic:_) <- waitForDiagnostics - liftIO (diagnostic^.message `shouldBe` "unexpected token") - closeDoc doc + -- Completing top level definitions: + withDoc "ListClient.mo" \doc -> do + actual <- getCompletions doc (Position 7 0) + liftIO + (shouldBe + ([("empty", Just "() -> Stack")]) + (mapMaybe (\c -> guard (c^.label == "empty") + *> pure (c^.label, c^.detail)) actual)) + -- 15 | List.push(x, s); + -- ==> 15 | List.pus + let edit = TextEdit (Range (Position 14 11) (Position 14 27)) "pus" + _ <- applyEdit doc edit + completionTestCase + doc + -- 15 | List.pus| + (Position 14 14) + [("push",Just "(T, List) -> List")] + + -- Completing primitives: + withDoc "ListClient.mo" \doc -> do + let edit = TextEdit (Range (Position 15 0) (Position 15 0)) "Prim." + _ <- applyEdit doc edit + actual <- getCompletions doc (Position 15 6) + liftIO + (shouldBe + (mapMaybe (\c -> guard (c^.label == "word32ToNat") + *> pure (c^.label, c^.detail)) actual) + ([("word32ToNat", Just "Word32 -> Nat")])) + + withDoc "ListClient.mo" \doc -> do + -- 1 | import List + -- ==> 1 | ort List + let edit = TextEdit (Range (Position 0 1) (Position 0 3)) "" + _ <- applyEdit doc edit + sendNotification TextDocumentDidSave (DidSaveTextDocumentParams doc) + (diagnostic:_) <- waitForDiagnostics + liftIO (diagnostic^.message `shouldBe` "unexpected token") log "Lexer failures don't crash the server" - doc <- openDoc "ListClient.mo" "motoko" - -- Creates an unclosed text literal, which triggers a lexer error - let edit = TextEdit (Range (Position 0 1) (Position 0 3)) "\"hello" - _ <- applyEdit doc edit - -- We're just testing that the server doesn't crash here - getCompletions doc (Position 0 0) - getHover doc (Position 0 0) - closeDoc doc + withDoc "ListClient.mo" \doc -> do + -- Creates an unclosed text literal, which triggers a lexer error + let edit = TextEdit (Range (Position 0 1) (Position 0 3)) "\"hello" + _ <- applyEdit doc edit + -- We're just testing that the server doesn't crash here + getCompletions doc (Position 0 0) + getHover doc (Position 0 0) log "Finds errors in non-saved files" - -- It finds errors in transitive modules that have been changed in - -- the vfs but not yet stored to disc - doc <- openDoc "ListClient.mo" "motoko" - let edit = TextEdit (Range (Position 0 1) (Position 0 3)) "" - _ <- applyEdit doc edit - appDoc <- openDoc "app.mo" "motoko" - sendNotification TextDocumentDidSave (DidSaveTextDocumentParams appDoc) - diagnostic:_ <- waitForActualDiagnostics - liftIO (diagnostic^.message `shouldBe` "unexpected token") - closeDoc doc - closeDoc appDoc + withDoc "ListClient.mo" \doc -> do + -- It finds errors in transitive modules that have been changed in + -- the vfs but not yet stored to disc + + let edit = TextEdit (Range (Position 0 1) (Position 0 3)) "" + _ <- applyEdit doc edit + withDoc "app.mo" \appDoc -> do + sendNotification TextDocumentDidSave (DidSaveTextDocumentParams appDoc) + diagnostic:_ <- waitForActualDiagnostics + liftIO (diagnostic^.message `shouldBe` "unexpected token") log "Rebuilding with package paths" - -- It knows how to handle package paths for rebuilding, and also - -- for completions - doc <- openDoc "app.mo" "motoko" - let edit = TextEdit (Range (Position 1 0) (Position 1 0)) "\nimport MyDep \"mo:mydep/broken.mo\"" - _ <- applyEdit doc edit - sendNotification TextDocumentDidSave (DidSaveTextDocumentParams doc) - [diag] <- waitForActualDiagnostics - liftIO (diag^.message `shouldBe` "operator not defined for operand types\n Text\nand\n Nat") + withDoc "app.mo" \doc -> do + -- It knows how to handle package paths for rebuilding, and also + -- for completions + let edit = TextEdit (Range (Position 3 0) (Position 3 0)) "\nimport MyDep \"mo:mydep/broken.mo\"" + _ <- applyEdit doc edit + sendNotification TextDocumentDidSave (DidSaveTextDocumentParams doc) + [diag] <- waitForActualDiagnostics + liftIO (diag^.message `shouldBe` "operator not defined for operand types\n Text\nand\n Nat") log "Completions from package paths" - -- Imports the non-broken dependency module - let edit2 = TextEdit (Range (Position 2 0) (Position 3 0)) "\nimport MyDep \"mo:mydep/lib.mo\"" - _ <- applyEdit doc edit2 - sendNotification TextDocumentDidSave (DidSaveTextDocumentParams doc) - let edit3 = TextEdit (Range (Position 3 0) (Position 3 0)) "\nMyDep." - _ <- applyEdit doc edit3 - completionTestCase - doc - -- MyDep.| - (Position 4 6) - [("print_hello", Just "() -> Text")] + withDoc "app.mo" \doc -> do + -- Imports the non-broken dependency module + let edit2 = TextEdit (Range (Position 3 0) (Position 3 0)) "\nimport MyDep \"mo:mydep/lib.mo\"" + _ <- applyEdit doc edit2 + sendNotification TextDocumentDidSave (DidSaveTextDocumentParams doc) + let edit3 = TextEdit (Range (Position 4 0) (Position 4 0)) "\nMyDep." + _ <- applyEdit doc edit3 + completionTestCase + doc + -- MyDep.| + (Position 5 6) + [("print_hello", Just "() -> Text")] diff --git a/test/lsp-int/lsp-int.cabal b/test/lsp-int/lsp-int.cabal index af1750c7de6..25291457571 100644 --- a/test/lsp-int/lsp-int.cabal +++ b/test/lsp-int/lsp-int.cabal @@ -18,6 +18,7 @@ executable lsp-int , text ^>=1.2 , hspec , HUnit + , filepath , directory , lens , data-default From 6f3eb9d4e0baa112fabf11eee2bbb330168f51e8 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 13 Jan 2020 16:49:16 +0100 Subject: [PATCH 0921/1176] More extra-rounds (#1105) we have to tell `drun` to wait for a certain amount of time (rounds) after each message to allow for subsequent computation in the call tree. This bumps this number to something that might cover all our test cases (even `flatten-awaitables` and `large-array.) This hack should go away with DFN-1269. Also bumps drun mostly to get https://github.com/dfinity-lab/dfinity/pull/2270 Also included ``` 947195fb1 Drun: wait extra batches, then print result (#2270) a544b6dec DFN-1267: Create Rust trait and types for DKG API based on crypto spec (#2225) 698fb5cfb ExecEnv: use vanilla slog everywhere (#2253) 0dfe895c6 Merge pull request #2258 from dfinity-lab/johnw/debug-syms 52dc9e6db Merge pull request #2252 from dfinity-lab/rsub/xport-metrics afc6db283 Merge pull request #2062 from dfinity-lab/faraz 87d5594e4 Merge pull request #2243 from dfinity-lab/david-con-209 7ead6c55f Merge pull request #2229 from dfinity-lab/fs/mastersquash e55afef23 Merge pull request #2137 from dfinity-lab/INF-532 91917d470 Merge pull request #2169 from dfinity-lab/akhi3030/call-simple-update ``` --- default.nix | 2 +- test/drun-wrapper.sh | 7 +++- test/run-drun/large-array.mo | 2 ++ test/run-drun/mod-rebind.mo | 4 +++ .../run-drun/ok/actor-creation.ic-stub-run.ok | 13 -------- test/run-drun/ok/chat.ic-stub-run.ok | 22 ------------- test/run-drun/ok/closure-params.drun-run.ok | 7 +++- test/run-drun/ok/counter2.drun-run.ok | 2 +- test/run-drun/ok/data-params.drun-run.ok | 2 +- .../ok/flatten-awaitables.drun-run.ok | 33 +++++++++++++++++++ test/run-drun/ok/free-callbacks.drun-run.ok | 1 + .../run-drun/ok/hello-world-async.drun-run.ok | 2 +- .../run-drun/ok/hello-world-await.drun-run.ok | 1 + test/run-drun/ok/large-array.drun-run.ok | 1 + test/run-drun/ok/local-throw.drun-run.ok | 2 ++ test/run-drun/ok/mod-rebind.drun-run.ok | 1 + test/run-drun/ok/mod-rebind.ic-stub-run.ok | 4 +++ test/run-drun/ok/oneway-throw.drun-run.ok | 3 +- test/run-drun/ok/oneway.drun-run.ok | 2 +- test/run-drun/ok/query2.drun-run.ok | 9 ++++- .../ok/reference-params.ic-stub-run.ok | 9 ----- test/run-drun/ok/transpose.drun-run.ok | 1 + 22 files changed, 77 insertions(+), 53 deletions(-) create mode 100644 test/run-drun/mod-rebind.mo delete mode 100644 test/run-drun/ok/actor-creation.ic-stub-run.ok delete mode 100644 test/run-drun/ok/chat.ic-stub-run.ok create mode 100644 test/run-drun/ok/mod-rebind.drun-run.ok create mode 100644 test/run-drun/ok/mod-rebind.ic-stub-run.ok delete mode 100644 test/run-drun/ok/reference-params.ic-stub-run.ok diff --git a/default.nix b/default.nix index bd1ffc198d6..ab184b3ed4a 100644 --- a/default.nix +++ b/default.nix @@ -36,7 +36,7 @@ let dfinity-src = name = "dfinity-sources"; url = "ssh://git@github.com/dfinity-lab/dfinity"; # ref = "master"; - rev = "91ff7b663820e6f9ba3aab3993b6f613482465ca"; + rev = "947195fb1395eac397b8490fc8000e3afe5ef820"; }; in let dfinity-pkgs = import dfinity-src { inherit (nixpkgs) system; }; in diff --git a/test/drun-wrapper.sh b/test/drun-wrapper.sh index 12836c6e77c..7b35f74b047 100755 --- a/test/drun-wrapper.sh +++ b/test/drun-wrapper.sh @@ -26,6 +26,11 @@ export LANG=C.UTF-8 # 1125899906842624 # (drun currently expects a decimal number for the canister id) +# this number is determined empirically: how many extra batches are needed +# until all call-trees have finished (even those that return early). +# Usually darwin needs more! (Should go away with DFN-1269) +EXTRA_BATCHES=100 + (echo "install 1125899906842624 $1 0x"; if [ -n "$2" ]; then LANG=C perl -ne 'print "$1 1125899906842624 $2\n" if m,^//CALL (ingress|query) (.*),' $2; fi; -) | $DRUN -c "$CONFIG" --extra-batches 1 /dev/stdin +) | $DRUN -c "$CONFIG" --extra-batches $EXTRA_BATCHES /dev/stdin diff --git a/test/run-drun/large-array.mo b/test/run-drun/large-array.mo index 9998b870507..778ea148c75 100644 --- a/test/run-drun/large-array.mo +++ b/test/run-drun/large-array.mo @@ -3,6 +3,8 @@ import Prim "mo:prim"; // Should allocate 1G ignore(Prim.Array_init<()>(1024*1024*1024/4, ())); +Prim.debugPrint "done"; + //SKIP run //SKIP run-ir //SKIP run-low diff --git a/test/run-drun/mod-rebind.mo b/test/run-drun/mod-rebind.mo new file mode 100644 index 00000000000..ad0f33acbb9 --- /dev/null +++ b/test/run-drun/mod-rebind.mo @@ -0,0 +1,4 @@ +module { + public module x = {public type T = Int}; + public let y = x; +} diff --git a/test/run-drun/ok/actor-creation.ic-stub-run.ok b/test/run-drun/ok/actor-creation.ic-stub-run.ok deleted file mode 100644 index aaa611cea86..00000000000 --- a/test/run-drun/ok/actor-creation.ic-stub-run.ok +++ /dev/null @@ -1,13 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -debug.print: main actor creating a -debug.print: main actor calling a.foo() -debug.print: a created -debug.print: a.foo() called -debug.print: a creating b -debug.print: a calling b.foo() -debug.print: a.foo() done -debug.print: b created -debug.print: b.foo() called -← completed diff --git a/test/run-drun/ok/chat.ic-stub-run.ok b/test/run-drun/ok/chat.ic-stub-run.ok deleted file mode 100644 index abb785b3c60..00000000000 --- a/test/run-drun/ok/chat.ic-stub-run.ok +++ /dev/null @@ -1,22 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -debug.print: charlie received hello from bob -debug.print: alice received hello from bob -debug.print: bob received hello from bob -debug.print: charlie received goodbye from bob -debug.print: alice received goodbye from bob -debug.print: bob received goodbye from bob -debug.print: charlie received hello from alice -debug.print: alice received hello from alice -debug.print: bob received hello from alice -debug.print: charlie received goodbye from alice -debug.print: alice received goodbye from alice -debug.print: bob received goodbye from alice -debug.print: charlie received hello from charlie -debug.print: alice received hello from charlie -debug.print: bob received hello from charlie -debug.print: charlie received goodbye from charlie -debug.print: alice received goodbye from charlie -debug.print: bob received goodbye from charlie -← completed diff --git a/test/run-drun/ok/closure-params.drun-run.ok b/test/run-drun/ok/closure-params.drun-run.ok index 65b69a19788..aaf93d82b59 100644 --- a/test/run-drun/ok/closure-params.drun-run.ok +++ b/test/run-drun/ok/closure-params.drun-run.ok @@ -1,7 +1,12 @@ ingress(0) System -ingress(1) Completed: Canister: Payload: 0x4449444c0000 debug.print: 1 debug.print: 3 debug.print: 6 debug.print: 10 debug.print: 15 +debug.print: 1 +debug.print: 3 +debug.print: 6 +debug.print: 10 +debug.print: 15 +ingress(1) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/counter2.drun-run.ok b/test/run-drun/ok/counter2.drun-run.ok index 6ae2944f48c..03da5a03e23 100644 --- a/test/run-drun/ok/counter2.drun-run.ok +++ b/test/run-drun/ok/counter2.drun-run.ok @@ -1,5 +1,4 @@ ingress(0) System -ingress(1) Completed: Canister: Payload: 0x4449444c0000 debug.print: 2 debug.print: 3 debug.print: 4 @@ -14,3 +13,4 @@ debug.print: 11 debug.print: 12 debug.print: 13 debug.print: 14 +ingress(1) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/data-params.drun-run.ok b/test/run-drun/ok/data-params.drun-run.ok index 6c02e39ff56..bd36923f3b9 100644 --- a/test/run-drun/ok/data-params.drun-run.ok +++ b/test/run-drun/ok/data-params.drun-run.ok @@ -1,5 +1,4 @@ ingress(0) System -ingress(1) Completed: Canister: Payload: 0x4449444c0000 debug.print: 0 debug.print: +1 debug.print: +3 @@ -41,3 +40,4 @@ debug.print: +2_148_489_869 debug.print: +2_148_489_911 debug.print: +2_148_489_869 debug.print: +4_295_973_516 +ingress(1) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/flatten-awaitables.drun-run.ok b/test/run-drun/ok/flatten-awaitables.drun-run.ok index 56cdd90b3a1..a5dc4ab027c 100644 --- a/test/run-drun/ok/flatten-awaitables.drun-run.ok +++ b/test/run-drun/ok/flatten-awaitables.drun-run.ok @@ -1,3 +1,36 @@ ingress(0) System debug.print: first-order +debug.print: 0 +debug.print: 1 +debug.print: 2 +debug.print: 3 +debug.print: 4 +debug.print: 5 +debug.print: 6 +debug.print: 7 +debug.print: 8 +debug.print: 9 +debug.print: 10 +debug.print: 11 +debug.print: 12 +debug.print: 13 +debug.print: 14 +debug.print: 15 +debug.print: higher-order +debug.print: 0 +debug.print: 1 +debug.print: 2 +debug.print: 3 +debug.print: 4 +debug.print: 5 +debug.print: 6 +debug.print: 7 +debug.print: 8 +debug.print: 9 +debug.print: 10 +debug.print: 11 +debug.print: 12 +debug.print: 13 +debug.print: 14 +debug.print: 15 ingress(1) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/free-callbacks.drun-run.ok b/test/run-drun/ok/free-callbacks.drun-run.ok index 91c74b55809..51a7daa2389 100644 --- a/test/run-drun/ok/free-callbacks.drun-run.ok +++ b/test/run-drun/ok/free-callbacks.drun-run.ok @@ -1,2 +1,3 @@ ingress(0) System +debug.print: Ignore Diff: (ignored) ingress(1) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/hello-world-async.drun-run.ok b/test/run-drun/ok/hello-world-async.drun-run.ok index fc1914a38ce..b41f48223f2 100644 --- a/test/run-drun/ok/hello-world-async.drun-run.ok +++ b/test/run-drun/ok/hello-world-async.drun-run.ok @@ -1,4 +1,4 @@ ingress(0) System debug.print: Hello -ingress(1) Completed: Canister: Payload: 0x4449444c0000 debug.print: World! +ingress(1) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/hello-world-await.drun-run.ok b/test/run-drun/ok/hello-world-await.drun-run.ok index 91c74b55809..d124edaa379 100644 --- a/test/run-drun/ok/hello-world-await.drun-run.ok +++ b/test/run-drun/ok/hello-world-await.drun-run.ok @@ -1,2 +1,3 @@ ingress(0) System +debug.print: Hello World! ingress(1) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/large-array.drun-run.ok b/test/run-drun/ok/large-array.drun-run.ok index 43d7af40394..b95c84fe751 100644 --- a/test/run-drun/ok/large-array.drun-run.ok +++ b/test/run-drun/ok/large-array.drun-run.ok @@ -1 +1,2 @@ +debug.print: done ingress(0) System diff --git a/test/run-drun/ok/local-throw.drun-run.ok b/test/run-drun/ok/local-throw.drun-run.ok index 91c74b55809..26a900a3a48 100644 --- a/test/run-drun/ok/local-throw.drun-run.ok +++ b/test/run-drun/ok/local-throw.drun-run.ok @@ -1,2 +1,4 @@ ingress(0) System +debug.print: t2 ok +debug.print: t3 ok ingress(1) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/mod-rebind.drun-run.ok b/test/run-drun/ok/mod-rebind.drun-run.ok new file mode 100644 index 00000000000..43d7af40394 --- /dev/null +++ b/test/run-drun/ok/mod-rebind.drun-run.ok @@ -0,0 +1 @@ +ingress(0) System diff --git a/test/run-drun/ok/mod-rebind.ic-stub-run.ok b/test/run-drun/ok/mod-rebind.ic-stub-run.ok new file mode 100644 index 00000000000..54225bc8555 --- /dev/null +++ b/test/run-drun/ok/mod-rebind.ic-stub-run.ok @@ -0,0 +1,4 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed diff --git a/test/run-drun/ok/oneway-throw.drun-run.ok b/test/run-drun/ok/oneway-throw.drun-run.ok index c1cc4f9e0fd..ed40bddbf25 100644 --- a/test/run-drun/ok/oneway-throw.drun-run.ok +++ b/test/run-drun/ok/oneway-throw.drun-run.ok @@ -1,5 +1,6 @@ ingress(0) System debug.print: go1 -ingress(1) Completed: Canister: Payload: 0x4449444c0000 debug.print: throws() debug.print: ping() +debug.print: go2 +ingress(1) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/oneway.drun-run.ok b/test/run-drun/ok/oneway.drun-run.ok index 9f33620c3b2..8331dc9ecc9 100644 --- a/test/run-drun/ok/oneway.drun-run.ok +++ b/test/run-drun/ok/oneway.drun-run.ok @@ -4,10 +4,10 @@ debug.print: B debug.print: C debug.print: D debug.print: E -ingress(1) Completed: Canister: Payload: 0x4449444c0000 debug.print: 1 debug.print: 2 debug.print: 3 debug.print: 4 debug.print: 5 debug.print: 6 +ingress(1) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/query2.drun-run.ok b/test/run-drun/ok/query2.drun-run.ok index 8bf828fb58a..c24669e8a03 100644 --- a/test/run-drun/ok/query2.drun-run.ok +++ b/test/run-drun/ok/query2.drun-run.ok @@ -1,6 +1,13 @@ ingress(0) System -ingress(1) Completed: Canister: Payload: 0x4449444c0000 debug.print: 2 debug.print: 3 debug.print: 4 debug.print: 4 +debug.print: In read: +debug.print: 5 +debug.print: 4 +debug.print: In read: +debug.print: 5 +debug.print: The following fails in the intepreter, for lack of query semantics +debug.print: 4 +ingress(1) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/reference-params.ic-stub-run.ok b/test/run-drun/ok/reference-params.ic-stub-run.ok deleted file mode 100644 index d7f9b18f9b0..00000000000 --- a/test/run-drun/ok/reference-params.ic-stub-run.ok +++ /dev/null @@ -1,9 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -debug.print: Hello World! -debug.print: Hello World! -debug.print: Hello World! -debug.print: Hello Universe! -debug.print: Hello Galaxy! -← completed diff --git a/test/run-drun/ok/transpose.drun-run.ok b/test/run-drun/ok/transpose.drun-run.ok index 91c74b55809..5fbed08ce5a 100644 --- a/test/run-drun/ok/transpose.drun-run.ok +++ b/test/run-drun/ok/transpose.drun-run.ok @@ -1,2 +1,3 @@ ingress(0) System +debug.print: All good ingress(1) Completed: Canister: Payload: 0x4449444c0000 From 3914ac142a85da566abd9747d7f023db36f92521 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Mon, 13 Jan 2020 17:23:50 +0100 Subject: [PATCH 0922/1176] Kill a few typos in the error message (#1109) --- stdlib/examples/produce-exchange/test/loadWorkloadAndQuery.mo | 2 +- .../examples/produce-exchange/test/loadWorkloadAndQueryBig.mo | 2 +- test/run-drun/ok/query2.drun-run.ok | 2 +- test/run-drun/ok/query2.run-ir.ok | 2 +- test/run-drun/ok/query2.run-low.ok | 2 +- test/run-drun/ok/query2.run.ok | 2 +- test/run-drun/query2.mo | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/stdlib/examples/produce-exchange/test/loadWorkloadAndQuery.mo b/stdlib/examples/produce-exchange/test/loadWorkloadAndQuery.mo index af8658b8f41..75b3f20471e 100644 --- a/stdlib/examples/produce-exchange/test/loadWorkloadAndQuery.mo +++ b/stdlib/examples/produce-exchange/test/loadWorkloadAndQuery.mo @@ -19,7 +19,7 @@ actor class Test() = this { // Vary the choice of region count and scaling factor here; // Each choice leads to a different count of (InventoryCount, RouteCount), and load time: let params = { - //scaledParams(2, 2); // (40, 40 ), loads in 0.7s in my AS intepreter + //scaledParams(2, 2); // (40, 40 ), loads in 0.7s in my AS interpreter //scaledParams(5, 5); // (625 , 625 ), loads in 8.8s in my AS interpreter //scaledParams(8, 10); // (3_200, 3_200), loads in 1:07min in my AS interpreter //scaledParams(10, 10); // (5_000, 5_000), loads in 2:13min in my AS interpreter diff --git a/stdlib/examples/produce-exchange/test/loadWorkloadAndQueryBig.mo b/stdlib/examples/produce-exchange/test/loadWorkloadAndQueryBig.mo index 6a5cd73fc3c..ac60d00a63c 100644 --- a/stdlib/examples/produce-exchange/test/loadWorkloadAndQueryBig.mo +++ b/stdlib/examples/produce-exchange/test/loadWorkloadAndQueryBig.mo @@ -21,7 +21,7 @@ actor class Test() = this { // Vary the choice of region count and scaling factor here; // Each choice leads to a different count of (InventoryCount, RouteCount), and load time: let params = { - //scaledParams(2, 2); // (40, 40 ), loads in 0.7s in my AS intepreter + //scaledParams(2, 2); // (40, 40 ), loads in 0.7s in my AS interpreter //scaledParams(5, 5); // (625 , 625 ), loads in 8.8s in my AS interpreter scaledParams(8, 10); // (3_200, 3_200), loads in 1:07min in my AS interpreter //scaledParams(10, 10); // (5_000, 5_000), loads in 2:13min in my AS interpreter diff --git a/test/run-drun/ok/query2.drun-run.ok b/test/run-drun/ok/query2.drun-run.ok index c24669e8a03..d4a603fb3cc 100644 --- a/test/run-drun/ok/query2.drun-run.ok +++ b/test/run-drun/ok/query2.drun-run.ok @@ -8,6 +8,6 @@ debug.print: 5 debug.print: 4 debug.print: In read: debug.print: 5 -debug.print: The following fails in the intepreter, for lack of query semantics +debug.print: The following fails in the interpreter, for lack of query semantics debug.print: 4 ingress(1) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/query2.run-ir.ok b/test/run-drun/ok/query2.run-ir.ok index 8bf44627e97..f8d54b980f3 100644 --- a/test/run-drun/ok/query2.run-ir.ok +++ b/test/run-drun/ok/query2.run-ir.ok @@ -7,6 +7,6 @@ In read: 5 In read: 6 -The following fails in the intepreter, for lack of query semantics +The following fails in the interpreter, for lack of query semantics query2.mo:35.4-35.18: execution error, assertion failure 6 diff --git a/test/run-drun/ok/query2.run-low.ok b/test/run-drun/ok/query2.run-low.ok index 8bf44627e97..f8d54b980f3 100644 --- a/test/run-drun/ok/query2.run-low.ok +++ b/test/run-drun/ok/query2.run-low.ok @@ -7,6 +7,6 @@ In read: 5 In read: 6 -The following fails in the intepreter, for lack of query semantics +The following fails in the interpreter, for lack of query semantics query2.mo:35.4-35.18: execution error, assertion failure 6 diff --git a/test/run-drun/ok/query2.run.ok b/test/run-drun/ok/query2.run.ok index 8bf44627e97..f8d54b980f3 100644 --- a/test/run-drun/ok/query2.run.ok +++ b/test/run-drun/ok/query2.run.ok @@ -7,6 +7,6 @@ In read: 5 In read: 6 -The following fails in the intepreter, for lack of query semantics +The following fails in the interpreter, for lack of query semantics query2.mo:35.4-35.18: execution error, assertion failure 6 diff --git a/test/run-drun/query2.mo b/test/run-drun/query2.mo index 02f6e4d8642..7f12f2e64ca 100644 --- a/test/run-drun/query2.mo +++ b/test/run-drun/query2.mo @@ -31,7 +31,7 @@ actor counter = { assert c2 == 4; let c3 = await counter.read(); counter.printCounter(); - Prim.debugPrint("The following fails in the intepreter, for lack of query semantics"); + Prim.debugPrint("The following fails in the interpreter, for lack of query semantics"); assert c3 == 4; }; }; From b6f0d791dc454b3d16d03861388f1ab498f38292 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Mon, 13 Jan 2020 20:40:45 +0000 Subject: [PATCH 0923/1176] removing freedom to instantiate scope function type parameter --- src/ir_def/check_ir.ml | 1 + src/ir_passes/async.ml | 1 + src/lowering/desugar.ml | 15 ++---- src/mo_def/arrange.ml | 6 +-- src/mo_def/syntax.ml | 6 +-- src/mo_frontend/parser.mly | 2 +- src/mo_frontend/typing.ml | 102 ++++++++++++++++--------------------- src/mo_types/async_cap.ml | 2 +- src/mo_types/type.ml | 33 ++++++++---- src/mo_types/type.mli | 1 + 10 files changed, 82 insertions(+), 87 deletions(-) diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 958c01e2824..6e879606cb7 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -210,6 +210,7 @@ let rec check_typ env typ : unit = check_typ env typ | T.Typ c -> check_con env c + | T.Scope -> () and check_con env c = let env = {env with cons = T.ConSet.add c env.cons} in diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index 7867f390329..1fdd70076e8 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -178,6 +178,7 @@ let transform mode env prog = | Non -> Non | Pre -> Pre | Typ c -> Typ (t_con c) + | Scope -> Scope and t_bind {var; bound} = {var; bound = t_typ bound} diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 1ac0fea28e2..cf8ada31740 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -119,16 +119,11 @@ and exp' at note = function | S.CallE ({it=S.AnnotE ({it=S.PrimE p;_},_);_}, _, e) -> I.PrimE (I.OtherPrim p, [exp e]) | S.CallE (e1, inst, e2) -> - begin - match !inst with - | None -> assert false - | Some typs -> - let t = e1.Source.note.S.note_typ in - let ts = List.map (fun t -> t.Source.note) typs in - if T.is_non t - then unreachableE.it (* BUG?, why should we discard the code for e1 just because e1 has type non (Issue #945) *) - else I.CallE (exp e1, ts, exp e2) - end + let t = e1.Source.note.S.note_typ in + let ts = inst.note (*List.map (fun t -> t.Source.note) inst.it*) in + if T.is_non t + then unreachableE.it (* BUG?, why should we discard the code for e1 just because e1 has type non (Issue #945) *) + else I.CallE (exp e1, ts, exp e2) | S.BlockE [] -> I.TupE [] | S.BlockE [{it = S.ExpD e; _}] -> (exp e).it | S.BlockE ds -> I.BlockE (block (T.is_unit note.I.note_typ) ds) diff --git a/src/mo_def/arrange.ml b/src/mo_def/arrange.ml index 1a3da173ee6..01759763067 100644 --- a/src/mo_def/arrange.ml +++ b/src/mo_def/arrange.ml @@ -35,7 +35,7 @@ let rec exp e = match e.it with (match t with None -> Atom "_" | Some t -> typ t); exp e' ] - | CallE (e1, ts_opt_ref, e2) -> "CallE" $$ [exp e1] @ inst ts_opt_ref @ [exp e2] + | CallE (e1, ts, e2) -> "CallE" $$ [exp e1] @ inst ts @ [exp e2] | BlockE ds -> "BlockE" $$ List.map dec ds | NotE e -> "NotE" $$ [exp e] | AndE (e1, e2) -> "AndE" $$ [exp e1; exp e2] @@ -61,9 +61,7 @@ let rec exp e = match e.it with | ThrowE e -> "ThrowE" $$ [exp e] | TryE (e, cs) -> "TryE" $$ [exp e] @ List.map catch cs -and inst ts_opt_ref = match !ts_opt_ref with - | None -> [Atom ("?")] - | Some ts -> List.map typ ts +and inst ts = List.map typ ts.it and pat p = match p.it with | WildP -> Atom "WildP" diff --git a/src/mo_def/syntax.ml b/src/mo_def/syntax.ml index 30d02e7d243..dfa5b3c7bf2 100644 --- a/src/mo_def/syntax.ml +++ b/src/mo_def/syntax.ml @@ -115,7 +115,7 @@ and vis' = Public | Private type op_typ = Type.typ ref (* For overloaded resolution; initially Type.Pre. *) -type inst = typ list option ref (* For implicit scope instantiation *) +type inst = (typ list, Type.typ list) Source.annotated_phrase (* For implicit scope instantiation *) type sort_pat = (Type.shared_sort * pat) Type.shared Source.phrase @@ -258,12 +258,12 @@ let scope_id = "@" let scope_bind() = { var = scope_id @@ no_region; - bound = PrimT "Any" @! no_region + bound = PrimT "Scope" @! no_region } @= no_region let pun_id id = { var = id.it @@ no_region; - bound = PrimT "Any" @! no_region + bound = PrimT "Scope" @! no_region } @= no_region let rec is_scope_typ t = diff --git a/src/mo_frontend/parser.mly b/src/mo_frontend/parser.mly index 990c870634f..843b73bca86 100644 --- a/src/mo_frontend/parser.mly +++ b/src/mo_frontend/parser.mly @@ -407,7 +407,7 @@ exp_post(B) : | e=exp_post(ob) DOT x=id { DotE(e, x) @? at $sloc } | e1=exp_post(ob) tso=typ_args? e2=exp_nullary(ob) - { CallE(e1, ref tso, e2) @? at $sloc } + { CallE(e1, {it = Lib.Option.get tso []; at = no_region; note = []}, e2) @? at $sloc } exp_un(B) : | e=exp_post(B) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 8d9789fd4b5..c79844c0f79 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -290,18 +290,6 @@ let rec infer_scope env sort cs cod = | _ -> env) | _ -> env -and check_scope env t at = - match env.async with - | C.AsyncCap c - | C.AwaitCap c -> - if not (T.eq t (T.Con(c,[]))) then - local_error env at "bad scope: expecting scope instantiation %s, found %s" - (T.string_of_con c) - (T.string_of_typ_expand t) - | C.NullCap -> - local_error env at "bad scope: expecting no scope instantiation, found %s" - (T.string_of_typ_expand t) - and check_AsyncCap env s at = match env.async with | C.AwaitCap c -> T.Con(c, []) @@ -329,6 +317,7 @@ and check_typ' env typ : T.typ = let tbs' = List.map (fun {T.var; T.bound} -> {T.var; bound = T.open_ ts bound}) tbs in check_typ_bounds env tbs' ts typs typ.at; T.Con (c, ts) + | PrimT "Scope" -> T.Scope | PrimT "Any" -> T.Any | PrimT "None" -> T.Non | PrimT s -> @@ -486,10 +475,45 @@ and check_typ_bounds env (tbs : T.bind list) (ts : T.typ list) typs at = | _ -> assert false in go tbs ts typs -and check_inst_bounds env tbs typs at = - let ts = List.map (check_typ env) typs in - check_typ_bounds env tbs ts typs at; - ts +and infer_inst env tbs typs at = + match tbs,typs with + | {T.bound = T.Scope; _}::tbs', typs' -> + (match env.async with + | C.NullCap -> error env at "scope required, but non available" + | C.AwaitCap c + | C.AsyncCap c -> + let (ts,typs'') = infer_inst env tbs' typs' at in + (T.Con(c,[])::ts, + { (scope_typ no_region) with note = T.Con(c, []) } + ::typs'') + ) + | _::tbs', typ::typs' -> + let (ts,typs'') = infer_inst env tbs' typs' at in + (check_typ env typ::ts, + typ::typs'') + | _::tbs', [] -> + ([], []) + | [], typs' -> + (List.map (check_typ env) typs', + typs') + +(*and infer_inst env tbs typs at = + let ts = List.map (check_typ env typ::ts) in + match List.find_opt (fun {T.Bound = Scope; _} -> true | _ -> false) tbs with + | Some i -> + *) + +and check_inst_bounds env tbs inst at = + let ts, inst' = infer_inst env tbs inst at in +(* if List.length tbs <> List.length inst' then + ( List.iter (fun t -> Printf.printf "%s" (T.string_of_typ t)) ts; + Printf.printf "\n"; + List.iter (fun t -> Printf.printf "%s " (T.string_of_typ t.note)) inst'; + Printf.printf "\n\n" + ); + *) + check_typ_bounds env tbs ts inst' at; + ts, inst' (* Literals *) @@ -839,54 +863,18 @@ and infer_exp'' env exp : T.typ = let ts1 = match pat.it with TupP _ -> T.seq_of_tup t1 | _ -> [t1] in let tbs = List.map2 (fun c t -> {T.var = Con.name c; bound = T.close cs t}) cs ts in T.Func (sort, T.map_control (T.close cs) c, tbs, List.map (T.close cs) ts1, List.map (T.close cs) ts2) - | CallE (exp1, insts, exp2) -> - let n_insts = match !insts with - | Some ts -> List.length ts - | None -> 0 - in + | CallE (exp1, inst, exp2) -> + let typs = inst.it in let t1 = infer_exp_promote env exp1 in let sort, tbs, t_arg, t_ret = - try T.as_func_sub T.Local n_insts t1 + try T.as_func_sub T.Local (List.length typs) t1 with Invalid_argument _ -> error env exp1.at "expected function type, but expression produces type\n %s" (T.string_of_typ_expand t1) in - (* scope inference *) - let pre_typs = - match !insts with - | None -> [] - | Some tys -> tys - in - let expected = List.length tbs in - let rec insert n typ typs = match n, typs with - | 0, typs -> typ::typs - | n, typ'::typs -> typ'::insert (n-1) typ typs - | n, [] -> [typ] - in - let typs = match t1 with - | T.Func (_, T.Promises (T.Var (_, n)), _, _, _) - | T.Func (_, T.Returns, _, _, [T.Async (T.Var (_, n),_)]) - when n < expected && List.length pre_typs = expected - 1 -> - insert n - (Syntax.scope_typ {left = exp1.at.right; right = exp2.at.left}) - pre_typs - | T.Func (T.Shared _, T.Returns, _, _, []) - when List.length pre_typs = expected - 1 -> - insert 0 - (Syntax.scope_typ {left = exp1.at.right; right = exp2.at.left}) - pre_typs - | _ -> pre_typs - in - insts := Some typs; - let ts = check_inst_bounds env tbs typs exp.at in - (match t1 with - | T.Func (_, T.Promises (T.Var (_, n)), _, _, _) - | T.Func (_, T.Returns, _, _, [T.Async (T.Var (_, n),_)]) -> - check_scope env (List.nth ts n) (List.nth typs n).at - | T.Func (T.Shared _, T.Returns, _, _, []) -> - check_scope env (List.nth ts 0) (List.nth typs 0).at - | _ -> ()); + let ts, inst' = check_inst_bounds env tbs typs exp.at in + inst.note <- ts; let t_arg = T.open_ ts t_arg in let t_ret = T.open_ ts t_ret in if not env.pre then begin diff --git a/src/mo_types/async_cap.ml b/src/mo_types/async_cap.ml index 6d1f4f404e2..26eb851bd4c 100644 --- a/src/mo_types/async_cap.ml +++ b/src/mo_types/async_cap.ml @@ -8,6 +8,6 @@ type async_cap = | AsyncCap of T.con | AwaitCap of T.con -let top_cap = Con.fresh "@" (T.Def([],T.Any)) +let top_cap = Con.fresh "@" (T.Abs([],T.Scope)) let initial_cap () = if !Flags.compiled then NullCap else AsyncCap top_cap diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index c4e252b218c..e29631f9ce6 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -52,6 +52,7 @@ and typ = | Any (* top *) | Non (* bottom *) | Typ of con (* type (field of module) *) + | Scope (* Scope pseudo type *) | Pre (* pre-type *) and bind = {var : var; bound : typ} @@ -187,6 +188,7 @@ let rec shift i n t = | Non -> Non | Pre -> Pre | Typ c -> Typ c + | Scope -> Scope and shift_bind i n {var; bound} = {var; bound = shift i n bound} @@ -237,7 +239,8 @@ let rec subst sigma t = in particular, type components defined within the scope of an enclosing type parameter cannot mention that parameter (but can mention other (closed) type constructors). - *) + *) + | Scope -> Scope and subst_bind sigma {var; bound} = {var; bound = subst sigma bound} @@ -288,6 +291,7 @@ let rec open' i ts t = | Non -> Non | Pre -> Pre | Typ c -> Typ c + | Scope -> Scope and open_bind i ts {var; bound} = {var; bound = open' i ts bound} @@ -465,6 +469,7 @@ let rec span = function | Mut t -> span t | Non -> Some 0 | Typ _ -> Some 1 + | Scope -> Some 0 (* Avoiding local constructors *) @@ -472,7 +477,7 @@ let rec span = function exception Unavoidable of con let rec avoid' cons seen = function - | (Prim _ | Var _ | Any | Non | Pre) as t -> t + | (Prim _ | Var _ | Any | Non | Pre | Scope) as t -> t | Con (c, ts) -> if ConSet.mem c seen then raise (Unavoidable c) else if ConSet.mem c cons then @@ -501,6 +506,7 @@ let rec avoid' cons seen = function | Mut t -> Mut (avoid' cons seen t) | Typ c -> if ConSet.mem c cons then raise (Unavoidable c) else Typ c (* TBR *) + and avoid_bind cons seen {var; bound} = {var; bound = avoid' cons seen bound} @@ -530,7 +536,7 @@ let avoid cons t = let rec cons t cs = match t with | Var _ -> cs - | (Prim _ | Any | Non | Pre) -> cs + | (Prim _ | Any | Non | Pre | Scope) -> cs | Con (c, ts) -> List.fold_right cons ts (ConSet.add c cs) | (Opt t | Mut t | Array t) -> @@ -576,7 +582,7 @@ let concrete t = seen := S.add t !seen; match t with | Var _ | Pre -> assert false - | Prim _ | Any | Non -> true + | Prim _ | Any | Non | Scope -> true | Con (c, ts) -> (match Con.kind c with | Abs _ -> false @@ -602,7 +608,7 @@ let shared t = seen := S.add t !seen; match t with | Var _ | Pre -> assert false - | Prim Error -> false + | Prim Error | Scope -> false | Any | Non | Prim _ | Typ _ -> true | Async _ | Mut _ -> false | Con (c, ts) -> @@ -629,7 +635,7 @@ let find_unshared t = seen := S.add t !seen; match t with | Var _ | Pre -> assert false - | Prim Error -> Some t + | Prim Error | Scope -> Some t | Any | Non | Prim _ | Typ _ -> None | Async _ | Mut _ -> Some t | Con (c, ts) -> @@ -656,6 +662,9 @@ let is_shared_func t = | Func (Shared _, _, _, _, _) -> true | _ -> false +(* Forward declare + TODO: haul string_of_typ before the lub/glb business, if possible *) +let str = ref (fun _ -> failwith "") (* Equivalence & Subtyping *) @@ -667,6 +676,7 @@ let rel_list p rel eq xs1 xs2 = let rec rel_typ rel eq t1 t2 = t1 == t2 || SS.mem (t1, t2) !rel || begin rel := SS.add (t1, t2) !rel; + (* Printf.printf "%s %s\n" (!str t1) (!str t2); *) match t1, t2 with | Pre, _ | _, Pre -> assert false @@ -738,6 +748,7 @@ let rec rel_typ rel eq t1 t2 = eq_typ rel eq t1' t2' | Typ c1, Typ c2 -> eq_con eq c1 c2 + | Scope, Scope -> true | _, _ -> false end @@ -909,7 +920,7 @@ let rec inhabited_typ co t = co := S.add t !co; match promote t with | Pre -> assert false - | Non -> false + | Non | Scope -> false | Any | Prim _ | Array _ | Opt _ | Async _ | Func _ | Typ _ -> true | Mut t' -> inhabited_typ co t' | Tup ts -> List.for_all (inhabited_typ co) ts @@ -933,10 +944,6 @@ and inhabited t : bool = inhabited_typ (ref S.empty) t module M = Map.Make (struct type t = typ * typ let compare = compare end) -(* Forward declare - TODO: haul string_of_typ before the lub/glb business, if possible *) -let str = ref (fun _ -> failwith "") - let rec lub' lubs glbs t1 t2 = if t1 == t2 then t1 else match M.find_opt (t1, t2) !lubs with @@ -965,6 +972,7 @@ let rec lub' lubs glbs t1 t2 = Obj (s1, lub_fields lubs glbs tf1 tf2) | Func (s1, c1, bs1, args1, res1), Func (s2, c2, bs2, args2, res2) when s1 = s2 && eq_control c1 c2 && List.(length bs1 = length bs2) && + List.for_all2 (fun b1 b2 -> (b1.bound = Scope) = (b2.bound = Scope)) bs1 bs2 && List.(length args1 = length args2 && length res1 = length res2) -> combine_func_parts s1 c1 bs1 args1 res1 bs2 args2 res2 lubs glbs glb' lub' | Async (t11, t12), Async (t21, t22) when eq t11 t21 -> @@ -1038,6 +1046,7 @@ and glb' lubs glbs t1 t2 = ) | Func (s1, c1, bs1, args1, res1), Func (s2, c2, bs2, args2, res2) when s1 = s2 && eq_control c1 c2 && List.(length bs1 = length bs2) && + List.for_all2 (fun b1 b2 -> (b1.bound = Scope) = (b2.bound = Scope)) bs1 bs2 && List.(length args1 = length args2 && length res1 = length res2) -> combine_func_parts s1 c1 bs1 args1 res1 bs2 args2 res2 lubs glbs lub' glb' | Async (t11, t12), Async (t21, t22) when eq t11 t21 -> @@ -1174,6 +1183,7 @@ let rec string_of_typ_nullary vs = function | Pre -> "???" | Any -> "Any" | Non -> "None" + | Scope -> "Scope" | Prim p -> string_of_prim p | Var (s, i) -> (try string_of_var (List.nth vs i) with _ -> assert false) | Con (c, []) -> string_of_con' vs c @@ -1252,6 +1262,7 @@ and can_omit n t = List.for_all (go i') ts1 && List.for_all (go i') ts2 | Typ c -> true (* assuming type defs are closed *) + | Scope -> true end in go n t diff --git a/src/mo_types/type.mli b/src/mo_types/type.mli index 9d4c4201999..7e1db57310a 100644 --- a/src/mo_types/type.mli +++ b/src/mo_types/type.mli @@ -49,6 +49,7 @@ and typ = | Any (* top *) | Non (* bottom *) | Typ of con (* type (field of module) *) + | Scope (* scope pseudo type *) | Pre (* pre-type *) and bind = {var : var; bound : typ} From add834e1b566c07e626f18efaf4dd43dfbf29c96 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Tue, 14 Jan 2020 01:38:11 +0100 Subject: [PATCH 0924/1176] move bugs around, prepare for #1019 (#1110) * move bugs around * fixup --- test/bugs/freeclass1.mo | 2 +- test/bugs/unboundclass.mo | 2 +- test/bugs/usedefbug.mo | 6 ++---- test/{bugs => run-drun}/aritybug.mo | 3 ++- test/run-drun/ok/aritybug.comp-stub.ok | 2 ++ test/run-drun/ok/aritybug.comp-stub.ret.ok | 1 + test/run-drun/ok/aritybug.comp.ok | 4 ++++ test/run-drun/ok/aritybug.comp.ret.ok | 1 + test/run-drun/ok/aritybug.run-ir.ok | 1 + test/run-drun/ok/aritybug.run-low.ok | 1 + test/run-drun/ok/aritybug.run.ok | 1 + test/run-drun/ok/sharingbug.drun-run.ok | 1 + test/run-drun/ok/sharingbug.ic-stub-run.ok | 4 ++++ test/{bugs => run-drun}/sharingbug.mo | 0 14 files changed, 22 insertions(+), 7 deletions(-) rename test/{bugs => run-drun}/aritybug.mo (92%) create mode 100644 test/run-drun/ok/aritybug.comp-stub.ok create mode 100644 test/run-drun/ok/aritybug.comp-stub.ret.ok create mode 100644 test/run-drun/ok/aritybug.comp.ok create mode 100644 test/run-drun/ok/aritybug.comp.ret.ok create mode 100644 test/run-drun/ok/aritybug.run-ir.ok create mode 100644 test/run-drun/ok/aritybug.run-low.ok create mode 100644 test/run-drun/ok/aritybug.run.ok create mode 100644 test/run-drun/ok/sharingbug.drun-run.ok create mode 100644 test/run-drun/ok/sharingbug.ic-stub-run.ok rename test/{bugs => run-drun}/sharingbug.mo (100%) diff --git a/test/bugs/freeclass1.mo b/test/bugs/freeclass1.mo index c69527dac15..b29fbb3aa2e 100644 --- a/test/bugs/freeclass1.mo +++ b/test/bugs/freeclass1.mo @@ -3,7 +3,7 @@ class Foo(f1:Int -> Int, f2:Int -> Int) { }; class Bar () { - private g(n:Int) : Int = n + 1; + private func g(n:Int) : Int = n + 1; let Bar = Foo(g, g) ; diff --git a/test/bugs/unboundclass.mo b/test/bugs/unboundclass.mo index 52737cb8982..d9cb3f03071 100644 --- a/test/bugs/unboundclass.mo +++ b/test/bugs/unboundclass.mo @@ -5,6 +5,6 @@ class Bar () { let Bar = Foo(g, g); - private g(n:Int) : Int = n + 1; + private func g(n:Int) : Int = n + 1; } diff --git a/test/bugs/usedefbug.mo b/test/bugs/usedefbug.mo index 54d9b0cddc3..82fc85c5ea0 100644 --- a/test/bugs/usedefbug.mo +++ b/test/bugs/usedefbug.mo @@ -1,13 +1,11 @@ - - class Bar () { private class Foo(f1:Int -> Int, f2:Int -> Int) { - private bomb = f1(666) + f2(666); + let bomb = f1(666) + f2(666); }; let Bar = Foo(g, g); - private g(n:Int) : Int = n + 1; + private func g(n:Int) : Int = n + 1; } diff --git a/test/bugs/aritybug.mo b/test/run-drun/aritybug.mo similarity index 92% rename from test/bugs/aritybug.mo rename to test/run-drun/aritybug.mo index aafd6353565..bb90e1b219c 100644 --- a/test/bugs/aritybug.mo +++ b/test/run-drun/aritybug.mo @@ -1,3 +1,4 @@ +import Prim "mo:prim"; // fails in the interpreter at line * with ../../src/moc -r u.mo // fails in the interpreter at line * with ../../src/moc -r -a u.mo @@ -16,7 +17,7 @@ shared func fu_u(a:Int,) : async (Int,) { let _ : async (Int,) = async { let (x,) = await fu_u(1); // * assert(x==2); - debugPrint t; + Prim.debugPrint t; return (x,); }; }; diff --git a/test/run-drun/ok/aritybug.comp-stub.ok b/test/run-drun/ok/aritybug.comp-stub.ok new file mode 100644 index 00000000000..f1e4ad96014 --- /dev/null +++ b/test/run-drun/ok/aritybug.comp-stub.ok @@ -0,0 +1,2 @@ +aritybug.mo:13.41-15.2: type error, a shared function is only allowed as a public field of an actor + (This is a limitation of the current version and flag -stub-system-api.) diff --git a/test/run-drun/ok/aritybug.comp-stub.ret.ok b/test/run-drun/ok/aritybug.comp-stub.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/aritybug.comp-stub.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-drun/ok/aritybug.comp.ok b/test/run-drun/ok/aritybug.comp.ok new file mode 100644 index 00000000000..abdda835a03 --- /dev/null +++ b/test/run-drun/ok/aritybug.comp.ok @@ -0,0 +1,4 @@ +aritybug.mo:13.41-15.2: type error, a shared function is only allowed as a public field of an actor + (This is a limitation of the current version.) +aritybug.mo:17.25-22.2: type error, freestanding async expression not yet supported + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/aritybug.comp.ret.ok b/test/run-drun/ok/aritybug.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/aritybug.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-drun/ok/aritybug.run-ir.ok b/test/run-drun/ok/aritybug.run-ir.ok new file mode 100644 index 00000000000..e34a79b1f91 --- /dev/null +++ b/test/run-drun/ok/aritybug.run-ir.ok @@ -0,0 +1 @@ +u_u diff --git a/test/run-drun/ok/aritybug.run-low.ok b/test/run-drun/ok/aritybug.run-low.ok new file mode 100644 index 00000000000..e34a79b1f91 --- /dev/null +++ b/test/run-drun/ok/aritybug.run-low.ok @@ -0,0 +1 @@ +u_u diff --git a/test/run-drun/ok/aritybug.run.ok b/test/run-drun/ok/aritybug.run.ok new file mode 100644 index 00000000000..e34a79b1f91 --- /dev/null +++ b/test/run-drun/ok/aritybug.run.ok @@ -0,0 +1 @@ +u_u diff --git a/test/run-drun/ok/sharingbug.drun-run.ok b/test/run-drun/ok/sharingbug.drun-run.ok new file mode 100644 index 00000000000..43d7af40394 --- /dev/null +++ b/test/run-drun/ok/sharingbug.drun-run.ok @@ -0,0 +1 @@ +ingress(0) System diff --git a/test/run-drun/ok/sharingbug.ic-stub-run.ok b/test/run-drun/ok/sharingbug.ic-stub-run.ok new file mode 100644 index 00000000000..54225bc8555 --- /dev/null +++ b/test/run-drun/ok/sharingbug.ic-stub-run.ok @@ -0,0 +1,4 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed diff --git a/test/bugs/sharingbug.mo b/test/run-drun/sharingbug.mo similarity index 100% rename from test/bugs/sharingbug.mo rename to test/run-drun/sharingbug.mo From 3855b96065cc071f445ad02755f55553fc009d5d Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 14 Jan 2020 11:24:14 +0000 Subject: [PATCH 0925/1176] WIP --- src/mo_frontend/typing.ml | 8 ++++---- src/prelude/prelude.ml | 1 + test/run-drun/scope-example.mo | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index c79844c0f79..070ea0dbb1d 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -477,7 +477,7 @@ and check_typ_bounds env (tbs : T.bind list) (ts : T.typ list) typs at = and infer_inst env tbs typs at = match tbs,typs with - | {T.bound = T.Scope; _}::tbs', typs' -> + | {T.bound; _}::tbs', typs' when T.eq bound = T.Scope -> (match env.async with | C.NullCap -> error env at "scope required, but non available" | C.AwaitCap c @@ -513,8 +513,8 @@ and check_inst_bounds env tbs inst at = ); *) check_typ_bounds env tbs ts inst' at; - ts, inst' - + ts + (* Literals *) let check_lit_val env t of_string at s = @@ -873,7 +873,7 @@ and infer_exp'' env exp : T.typ = "expected function type, but expression produces type\n %s" (T.string_of_typ_expand t1) in - let ts, inst' = check_inst_bounds env tbs typs exp.at in + let ts = check_inst_bounds env tbs typs exp.at in inst.note <- ts; let t_arg = T.open_ ts t_arg in let t_ret = T.open_ ts t_ret in diff --git a/src/prelude/prelude.ml b/src/prelude/prelude.ml index fa83d21defc..767785d7af9 100644 --- a/src/prelude/prelude.ml +++ b/src/prelude/prelude.ml @@ -1,5 +1,6 @@ let prelude = {| +type Scope = prim "Scope"; type Any = prim "Any"; type None = prim "None"; type Null = prim "Null"; diff --git a/test/run-drun/scope-example.mo b/test/run-drun/scope-example.mo index 09838525c59..1813672a4ee 100644 --- a/test/run-drun/scope-example.mo +++ b/test/run-drun/scope-example.mo @@ -1,7 +1,7 @@ actor A { - public shared func ping() : async Int = async {666;} /**/; // normal remote function + public shared func ping() : async Int = async {666;} /**/; // normal remote function - public shared func f() : async (Int,Int) = async { + public shared func f() : async (Int,Int) = async { // current scope: Y var a : (async Int) = async 0; From a132164b95f837924da09f35da87c0e895225f3e Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 14 Jan 2020 18:39:04 +0100 Subject: [PATCH 0926/1176] Refactor the AllocHow analysis (#1111) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit while trying to add new features (more expressions compiled statically) I kept bumping into dark corner of this code. Clear indication that it it could be cleared up. No wasm code changes here, verified with `./compare-wat.sh` (yay!) Main selling points: * The `VarEnv` data structure doesn't leak into the `AllocHow` internals anymore, thanks to `how_of_ae`. This will allow `AllocHow` to look at nested blocks in a later PR. * Previously, absence of a variable in a map had meaning. Cute, but less robust. Now the `how` maps are supposed to be defined for all variables of the appropriate scope, and the code blows up if we miss variables. * This should now be correct in the presence of shadowing (I believe it wasn’t fully previously). * it is less focused on functions, and look more at the set of free variables, which will be easier to extend to other syntactic forms. This required the Freevars analysis to separate the eager variables (occur outside a lambda) from the closed vars (occur under a lambda). --- src/codegen/compile.ml | 234 +++++++++++++++++++++++------------------ src/ir_def/freevars.ml | 26 +++-- 2 files changed, 152 insertions(+), 108 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 06849fa2497..9401a320ade 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -39,6 +39,9 @@ let nr x = { Wasm.Source.it = x; Wasm.Source.at = Wasm.Source.no_region } let todo fn se x = Printf.eprintf "%s: %s" fn (Wasm.Sexpr.to_string 80 se); x +exception CodegenError of string +let fatal fmt = Printf.ksprintf (fun s -> raise (CodegenError s)) fmt + module SR = struct (* This goes with the StackRep module, but we need the types earlier *) @@ -4519,8 +4522,8 @@ module Var = struct compile_unboxed_const ptr ^^ get_new_val ^^ Heap.store_field 1l - | Some (Deferred d) -> assert false - | None -> assert false + | Some (Deferred d) -> fatal "set_val: %s is deferred" var + | None -> fatal "set_val: %s missing" var (* Returns the payload (optimized representation) *) let get_val (env : E.t) (ae : VarEnv.t) var = match VarEnv.lookup_var ae var with @@ -4946,154 +4949,186 @@ open Ir module AllocHow = struct (* When compiling a (recursive) block, we need to do a dependency analysis, to - find out which names need to be heap-allocated, which local-allocated and which - are simply static functions. The goal is to avoid dynamic allocation where - possible (and use locals), and to avoid turning function references into closures. - - The rules for non-top-level-blocks are: + find out how the things are allocated. The options are: + - static: completely known, constant, not stored anywhere (think static function) + (no need to mention in a closure) + - local: only needed locally, stored in a Wasm local, immutable + (can be copied into a closure by value) + - local mutable: only needed locally, stored in a Wasm local, mutable + (cannot be copied into a closure) + - heap allocated: stored on the dynamic heap, address in Wasm local + (can be copied into a closure by reference) + - static heap: stored on the static heap, address known statically + (no need to mention in a closure) + + The goal is to avoid dynamic allocation where possible (and use locals), and + to avoid turning function references into closures. + + The rules are: - functions are static, unless they capture something that is not a static function or a static heap allocation. - - everything that is captured before it is defined needs to be dynamically - heap-allocated, unless it is a static function - - everything that is mutable and captured needs to be dynamically heap-allocated - - the rest can be local (immutable things can be put into closures by values) - - These rules require a fixed-point analysis. - - We represent this as a lattice as follows: + in particular, top-level functions are always static + - everything that is captured on the top-level needs to be statically + heap-allocated + - everything that is captured before it is defined, or is captured and mutable + needs to be dynamically heap-allocated + - the rest can be local *) module M = Freevars.M module S = Freevars.S - type nonStatic = LocalImmut | LocalMut | StoreHeap | StoreStatic - type allocHow = nonStatic M.t (* absent means static *) + (* + We represent this as a lattice as follows: + *) + type how = Static | LocalImmut | LocalMut | StoreHeap | StoreStatic + type allocHow = how M.t (* absent means static *) + + let disjoint_union : allocHow -> allocHow -> allocHow = + M.union (fun v _ _ -> fatal "AllocHow.disjoint_union: %s" v) let join : allocHow -> allocHow -> allocHow = M.union (fun _ x y -> Some (match x, y with - | StoreStatic, StoreHeap -> assert false - | StoreHeap, StoreStatic -> assert false - | _, StoreHeap -> StoreHeap - | StoreHeap, _ -> StoreHeap - | _, StoreStatic -> StoreStatic - | StoreStatic, _ -> StoreStatic - | LocalMut, _ -> LocalMut - | _, LocalMut -> LocalMut - | LocalImmut, LocalImmut -> LocalImmut + | StoreStatic, StoreHeap | StoreHeap, StoreStatic + -> fatal "AllocHow.join: cannot join StoreStatic and StoreHeap" + + | _, StoreHeap | StoreHeap, _ -> StoreHeap + | _, StoreStatic | StoreStatic, _ -> StoreStatic + | _, LocalMut | LocalMut, _ -> LocalMut + | _, LocalImmut | LocalImmut, _ -> LocalImmut + + | Static, Static -> Static )) + let joins = List.fold_left join M.empty type lvl = TopLvl | NotTopLvl - let map_of_set x s = S.fold (fun v m -> M.add v x m) s M.empty - let set_of_map m = M.fold (fun v _ m -> S.add v m) m S.empty + let map_of_set = Freevars.map_of_set + let set_of_map = Freevars.set_of_map + let disjoint s1 s2 = S.is_empty (S.inter s1 s2) - let is_local_mut _ b = LocalMut = b + (* Various filters used in the set operations below *) + let is_local_mut _ = function + | LocalMut -> true + | _ -> false + + let is_local _ = function + | LocalImmut -> true + | LocalMut -> true + | _ -> false let is_not_static _ = function - | StoreStatic -> false + | Static -> false | _ -> true + let require_closure _ = function + | Static -> false + | StoreStatic -> false + | _ -> true - let is_static ae how f = - (* Does this capture nothing from outside? *) - (S.is_empty (S.inter - (Freevars.captured_vars f) - (set_of_map (M.filter (fun _ x -> not (VarLoc.is_non_local x)) (ae.VarEnv.vars))))) && - (* Does this capture nothing non-static from here? *) - (S.is_empty (S.inter - (Freevars.captured_vars f) - (set_of_map (M.filter is_not_static how)))) + let how_captured lvl how seen captured = + (* What to do so that we can capture something? + * For local blocks, put on the dynamic heap: + - mutable things + - not yet defined things + * For top-level blocks, put on the static heap: + - everything that is non-static (i.e. still in locals) + *) + match lvl with + | NotTopLvl -> + map_of_set StoreHeap (S.union + (S.inter (set_of_map (M.filter is_local_mut how)) captured) + (S.inter (set_of_map (M.filter is_local how)) (S.diff captured seen)) + ) + | TopLvl -> + map_of_set StoreStatic + (S.inter (set_of_map (M.filter is_local how)) captured) - let is_func_exp exp = match exp.it with + let is_static_exp exp = match exp.it with | FuncE _ -> true | _ -> false - let is_static_exp env lvl how0 exp = - (* Functions are static when they are on the top-level or do not capture anything *) - if is_func_exp exp - then lvl = TopLvl || is_static env how0 (Freevars.exp exp) - else false - - let store_heap lvl = match lvl with - (* In the top level, never store in the dynamic heap; either use - locals or static heap *) - | TopLvl -> StoreStatic - | NotTopLvl -> StoreHeap - - let how_captured how lvl captured = - (* Some captured variables must be on the heap - * For local blocks, mutable things suffice (the others can be copied to the closure - by value) - * For top-level blocks, everything non-static should be statically allocated - *) - let force_to_heap = match lvl with - | TopLvl -> is_not_static - | NotTopLvl -> is_local_mut in - map_of_set (store_heap lvl) - (S.inter (set_of_map (M.filter force_to_heap how)) captured) + let dec lvl how_outer (seen, how0) dec = + let how_all = disjoint_union how_outer how0 in - let dec env lvl (seen, how0) dec = let (f,d) = Freevars.dec dec in - let captured = Freevars.captured_vars f in + let captured = S.inter (set_of_map how0) (Freevars.captured_vars f) in (* Which allocation is required for the things defined here? *) let how1 = match dec.it with (* Mutable variables are, well, mutable *) | VarD _ -> map_of_set LocalMut d - (* Static functions in an let-expression *) - | LetD ({it = VarP _; _}, e) when is_static_exp env lvl how0 e -> - M.empty + + (* Static expressions on the top-level: + - need to be static forms + - all non-captured free variables must be static + - all captured variables must be static or static-heap, if not on top level + (top level captures variables will be forced to be static-heap below, via how2) + *) + | LetD ({it = VarP _; _}, e) when + is_static_exp e && + disjoint (Freevars.eager_vars f) (set_of_map (M.filter is_not_static how_all)) && + (lvl = TopLvl || disjoint (Freevars.captured_vars f) (set_of_map (M.filter require_closure how_all))) + -> map_of_set Static d + + (* Everything else needs at least a local *) | _ -> map_of_set LocalImmut d in - (* Do we capture anything unseen, but non-static? - These need to be heap-allocated. - *) - let how2 = - map_of_set (store_heap lvl) - (S.inter - (set_of_map how0) - (S.diff (Freevars.captured_vars f) seen)) in + (* Which allocation does this require for its captured things? *) + let how2 = how_captured lvl how_all seen captured in - (* More captures? *) - let how3 = how_captured how0 lvl captured in - - let how = List.fold_left join M.empty [how0; how1; how2; how3] in + let how = joins [how0; how1; how2] in let seen' = S.union seen d in (seen', how) - let decs env lvl decs captured_in_body : allocHow = + (* find the allocHow for the variables currently in scope *) + (* we assume things are mutable, as we do not know better here *) + let how_of_ae ae : allocHow = M.map (fun l -> + match l with + | VarLoc.Deferred d when d.VarLoc.is_local -> LocalMut (* conservatively assumes immutable *) + | VarLoc.Deferred d -> Static + | VarLoc.Static _ -> StoreStatic + | VarLoc.Local _ -> LocalMut (* conservatively assume immutable *) + | VarLoc.HeapInd _ -> StoreHeap + ) ae.VarEnv.vars + + let decs (ae : VarEnv.t) lvl decs captured_in_body : allocHow = + let how_outer = how_of_ae ae in + let defined_here = snd (Freevars.decs decs) in (* TODO: implement gather_decs more directly *) + let how_outer = Freevars.diff how_outer defined_here in (* shadowing *) + let how0 = map_of_set Static defined_here in + let captured = S.inter defined_here captured_in_body in let rec go how = - let _seen, how1 = List.fold_left (dec env lvl) (S.empty, how) decs in - let how2 = how_captured how1 lvl captured_in_body in + let seen, how1 = List.fold_left (dec lvl how_outer) (S.empty, how) decs in + assert (S.equal seen defined_here); + let how2 = how_captured lvl how1 seen captured in let how' = join how1 how2 in if M.equal (=) how how' then how' else go how' in - go M.empty + go how0 (* Functions to extend the environment (and possibly allocate memory) based on how we want to store them. *) - let add_how env ae name : nonStatic option -> VarEnv.t * G.t = function - | Some LocalImmut | Some LocalMut -> + let add_local env ae how name : VarEnv.t * G.t = + match M.find name how with + | Static -> (ae, G.nop) + | LocalImmut | LocalMut -> let (ae1, i) = VarEnv.add_direct_local env ae name in (ae1, G.nop) - | Some StoreHeap -> + | StoreHeap -> let (ae1, i) = VarEnv.add_local_with_offset env ae name 1l in let alloc_code = Tagged.obj env Tagged.MutBox [ compile_unboxed_zero ] ^^ G.i (LocalSet (nr i)) in (ae1, alloc_code) - | Some StoreStatic -> + | StoreStatic -> let tag = bytes_of_int32 (Tagged.int_of_tag Tagged.MutBox) in let zero = bytes_of_int32 0l in let ptr = E.add_mutable_static_bytes env (tag ^ zero) in let ae1 = VarEnv.add_local_static ae name ptr in (ae1, G.nop) - | None -> (ae, G.nop) - - let add_local env ae how name = - add_how env ae name (M.find_opt name how) end (* AllocHow *) @@ -6543,6 +6578,7 @@ and compile_dec env pre_ae how v2en dec : VarEnv.t * G.t * (VarEnv.t -> G.t) = match dec.it with | TypD _ -> (pre_ae, G.nop, fun _ -> G.nop) + (* A special case for public methods *) (* This relies on the fact that in the top-level mutually recursive group, no shadowing happens. *) | LetD ({it = VarP v; _}, e) when E.NameEnv.mem v v2en -> @@ -6556,7 +6592,7 @@ and compile_dec env pre_ae how v2en dec : VarEnv.t * G.t * (VarEnv.t -> G.t) = ( pre_ae1, G.nop, fun ae -> fill env ae; G.nop) (* A special case for static expressions *) - | LetD ({it = VarP v; _}, e) when not (AllocHow.M.mem v how) -> + | LetD ({it = VarP v; _}, e) when AllocHow.M.find v how = AllocHow.Static -> let (static_thing, fill) = compile_static_exp env pre_ae how e in let pre_ae1 = VarEnv.add_local_deferred pre_ae v (SR.StaticThing static_thing) (fun _ -> G.nop) false in @@ -6626,14 +6662,10 @@ and compile_static_exp env pre_ae how exp = match exp.it with | Type.Replies -> [] | Type.Promises -> assert false in let mk_body env ae = - assert begin (* Is this really closed? *) - List.for_all (fun v -> - let found = VarEnv.NameEnv.mem v ae.VarEnv.vars in - (if not found then Printf.eprintf "internal error: static %s captures %s, not found in static environment\n" - name v); - found - ) (Freevars.M.keys (Freevars.exp e)) - end; + List.iter (fun v -> + if not (VarEnv.NameEnv.mem v ae.VarEnv.vars) + then fatal "internal error: static \"%s\": captures \"%s\", not found in static environment\n" name v + ) (Freevars.M.keys (Freevars.exp e)); compile_exp_as env ae (StackRep.of_arity (List.length return_tys)) e in FuncDec.closed env sort control name args mk_body return_tys exp.at | _ -> assert false diff --git a/src/ir_def/freevars.ml b/src/ir_def/freevars.ml index 60853fd54a9..a9a17878181 100644 --- a/src/ir_def/freevars.ml +++ b/src/ir_def/freevars.ml @@ -5,10 +5,16 @@ open Ir (* We want to know: Is this variable used (potentially) captured? + Is this variable used eagerly. + + capture = true; eager = false means it is _only_ used under lambdas *) -type usage_info = { captured : bool } +type usage_info = { captured : bool; eager : bool } -let join u1 u2 = { captured = u1.captured || u2.captured } +let join u1 u2 = { + captured = u1.captured || u2.captured; + eager = u1.captured || u2.captured +} module M = Env.Make(String) module S = Set.Make(String) @@ -37,6 +43,9 @@ let union_binders f xs = List.fold_left (++++) (M.empty, S.empty) (List.map f xs let diff f d = M.filter (fun k _ -> not (S.mem k d)) f +let map_of_set x s = S.fold (fun v m -> M.add v x m) s M.empty +let set_of_map m = M.fold (fun v _ m -> S.add v m) m S.empty + (* The bound variables from the second argument scope over the first *) let (///) (x : f) ((f,d) : fd) = f ++ diff x d @@ -46,10 +55,13 @@ let (///) (x : f) ((f,d) : fd) = f ++ diff x d Initially, variables are not captured. All variables under a lambda become captured. *) -let under_lambda : f -> f = M.map (fun _ -> { captured = true }) +let under_lambda : f -> f = M.map (fun _ -> { captured = true; eager = false }) +(* Projections *) let captured_vars : f -> S.t = - fun f -> S.of_list (List.map fst (List.filter (fun (k,u) -> u.captured) (M.bindings f))) + fun f -> set_of_map (M.filter (fun _ u -> u.captured) f) +let eager_vars : f -> S.t = + fun f -> set_of_map (M.filter (fun _ u -> u.eager) f) (* This closes a combined set over itself (recursion or mutual recursion) *) let close (f,d) = diff f d @@ -57,7 +69,7 @@ let close (f,d) = diff f d (* One traversal for each syntactic category, named by that category *) let rec exp e : f = match e.it with - | VarE i -> M.singleton i {captured = false} + | VarE i -> id i | LitE l -> M.empty | PrimE (_, es) -> exps es | TupE es -> exps es @@ -98,7 +110,7 @@ and arg a : fd = (M.empty, S.singleton a.it) and args as_ : fd = union_binders arg as_ and lexp le : f = match le.it with - | VarLE i -> M.singleton i {captured = false} + | VarLE i -> id i | DotLE (e1, _) -> exp e1 | IdxLE (e1, e2) -> exps [e1; e2] @@ -118,7 +130,7 @@ and case (c : case) = exp c.it.exp /// pat c.it.pat and cases cs : f = unions case cs -and id i = M.singleton i {captured = false} +and id i = M.singleton i {captured = false; eager = true} and dec d = match d.it with | LetD (p, e) -> pat p +++ exp e From 609e55efa1cf8963e9e34ee868b3f4c75296b2c5 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 14 Jan 2020 22:31:05 +0000 Subject: [PATCH 0927/1176] update tests; make top_cap = Scope, not a parameter to avoid non-closed type def warning --- src/mo_frontend/typing.ml | 55 +++++++---------------- src/mo_types/async_cap.ml | 2 +- src/pipeline/pipeline.ml | 2 +- test/repl/lib/type-lub.mo | 1 + test/run-drun/await-sugar.mo | 41 ++++++++++------- test/run-drun/general_await.mo | 19 ++++---- test/run-drun/ok/scope-example-func.tc.ok | 2 +- test/run-drun/ok/scope-example.tc.ok | 5 ++- test/run-drun/scope-example-func.mo | 8 ++-- test/run-drun/scope-example.mo | 12 ++--- 10 files changed, 71 insertions(+), 76 deletions(-) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 070ea0dbb1d..b0385ec5b88 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -315,7 +315,7 @@ and check_typ' env typ : T.typ = let ts = List.map (check_typ env) typs in let T.Def (tbs, _) | T.Abs (tbs, _) = Con.kind c in let tbs' = List.map (fun {T.var; T.bound} -> {T.var; bound = T.open_ ts bound}) tbs in - check_typ_bounds env tbs' ts typs typ.at; + check_typ_bounds env tbs' ts (List.map (fun typ -> typ.at) typs) typ.at; T.Con (c, ts) | PrimT "Scope" -> T.Scope | PrimT "Any" -> T.Any @@ -453,68 +453,47 @@ and check_typ_bind env typ_bind : T.con * T.typ * Scope.typ_env * Scope.con_env | [c], [t], te, cs -> c, t, te, cs | _ -> assert false -and check_typ_bounds env (tbs : T.bind list) (ts : T.typ list) typs at = +and check_typ_bounds env (tbs : T.bind list) (ts : T.typ list) ats at = let pars = List.length tbs in let args = List.length ts in if pars > args then error env at "too few type arguments"; if pars < args then error env at "too many type arguments"; - let rec go tbs' ts' typs' = - match tbs', ts', typs' with - | tb::tbs', t::ts', typ::typs' -> + let rec go tbs' ts' ats' = + match tbs', ts', ats' with + | tb::tbs', t::ts', at'::ats' -> if not env.pre then let u = T.open_ ts tb.T.bound in if not (T.sub t u) then - local_error env typ.at + local_error env at' "type argument\n %s\ndoes not match parameter bound\n %s" (T.string_of_typ_expand t) (T.string_of_typ_expand u); - go tbs' ts' typs' + go tbs' ts' ats' | [], [], [] -> () | _ -> assert false - in go tbs ts typs + in go tbs ts ats and infer_inst env tbs typs at = + let ts = List.map (check_typ env) typs in + let ats = List.map (fun typ -> typ.at) typs in match tbs,typs with - | {T.bound; _}::tbs', typs' when T.eq bound = T.Scope -> + | {T.bound; _}::tbs', typs' when T.eq bound T.Scope -> (match env.async with | C.NullCap -> error env at "scope required, but non available" | C.AwaitCap c | C.AsyncCap c -> - let (ts,typs'') = infer_inst env tbs' typs' at in - (T.Con(c,[])::ts, - { (scope_typ no_region) with note = T.Con(c, []) } - ::typs'') + (T.Con(c,[])::ts, at::ats) ) - | _::tbs', typ::typs' -> - let (ts,typs'') = infer_inst env tbs' typs' at in - (check_typ env typ::ts, - typ::typs'') - | _::tbs', [] -> - ([], []) - | [], typs' -> - (List.map (check_typ env) typs', - typs') - -(*and infer_inst env tbs typs at = - let ts = List.map (check_typ env typ::ts) in - match List.find_opt (fun {T.Bound = Scope; _} -> true | _ -> false) tbs with - | Some i -> - *) + | tbs', typs' -> + ts, ats and check_inst_bounds env tbs inst at = - let ts, inst' = infer_inst env tbs inst at in -(* if List.length tbs <> List.length inst' then - ( List.iter (fun t -> Printf.printf "%s" (T.string_of_typ t)) ts; - Printf.printf "\n"; - List.iter (fun t -> Printf.printf "%s " (T.string_of_typ t.note)) inst'; - Printf.printf "\n\n" - ); - *) - check_typ_bounds env tbs ts inst' at; + let ts, ats = infer_inst env tbs inst at in + check_typ_bounds env tbs ts ats at; ts - + (* Literals *) let check_lit_val env t of_string at s = diff --git a/src/mo_types/async_cap.ml b/src/mo_types/async_cap.ml index 26eb851bd4c..25dccf6490a 100644 --- a/src/mo_types/async_cap.ml +++ b/src/mo_types/async_cap.ml @@ -8,6 +8,6 @@ type async_cap = | AsyncCap of T.con | AwaitCap of T.con -let top_cap = Con.fresh "@" (T.Abs([],T.Scope)) +let top_cap = Con.fresh "@" (T.Def([],T.Scope)) let initial_cap () = if !Flags.compiled then NullCap else AsyncCap top_cap diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index 06df8b9d259..0feef8964e4 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -256,7 +256,7 @@ let chase_imports parsefn senv0 imports : (Syntax.lib list * Scope.scope) Diag.r let open Type in Obj (Actor, [{lab = "go"; - typ = Func (Shared Write, Promises (Var ("@", 0)), [{var = "@"; bound = Any}], + typ = Func (Shared Write, Promises (Var ("@", 0)), [{var = "@"; bound = Scope}], [], [Obj (Actor, [])])}]) in let sscope = Scope.lib f scaffold_type in diff --git a/test/repl/lib/type-lub.mo b/test/repl/lib/type-lub.mo index ede56742f62..b1f7c1004c1 100644 --- a/test/repl/lib/type-lub.mo +++ b/test/repl/lib/type-lub.mo @@ -54,6 +54,7 @@ type C = async(?Int); type D = async(?Nat); func c0(c : C, d : D) : [C] { ignore([c, d]); [c, d] }; + let c1s = [async ?4, async ?-42]; diff --git a/test/run-drun/await-sugar.mo b/test/run-drun/await-sugar.mo index 4a50b148963..4a725b93983 100644 --- a/test/run-drun/await-sugar.mo +++ b/test/run-drun/await-sugar.mo @@ -1,3 +1,6 @@ +// test scoping sugar - most tests disabled until we support explicit +// scope parameterisation/instantiation + actor A { public func f0 () : async () {}; @@ -13,6 +16,7 @@ public func test1 () : async () { }; */ +/* public func f2<@>() : async<@> () {}; public func test2(): async () { @@ -26,15 +30,16 @@ public func test2b() : async () { await f2b(); await f2b<@>(); }; - +*/ public func f3() : async () {}; public func test3 () : async () { await f3(); // scope passed as implicit first argument - await f3<@,Int>(); // scope passed as explicit first argument +/* await f3<@,Int>(); // scope passed as explicit first argument */ }; +/* public func f4<@,B<:Int>() : async<@> () {}; // explict scope parameter 1 public func test4() : async () { @@ -47,11 +52,12 @@ public func f5() : async<@> () {}; // explict scope parameter 2 public func test5() : async () { await f5(); // scope passed as implicit second argument - await f5(); +// await f5(); } ; +*/ - +/* public func f6() : async () {}; // explict scope parameter 2, implicit index public func test6() : async () { @@ -59,8 +65,9 @@ public func test6() : async () { await f6(); } ; +*/ - +/* public func f7(n:Int) : async() { if (n == 0) () else @@ -73,26 +80,26 @@ public func f7(n:Int) : async() { }; public func test7 () : async () { - await f7(1); // scope passed as implicit second argument - await f7<@,Int>(1); + await f7(1); // scope passed as implicit argument +/* await f7<@,Int>(1); */ }; +*/ + public func test() : async () { -// await test1(); - await test2(); - await test2b(); + await test0(); +// await test2(); +// await test2b(); await test3(); - await test4(); - await test5(); - await test6(); - await test7(); +// await test4(); +// await test5(); +// await test6(); +// await test7(); }; }; -A.test() //OR-CALL ingress test 0x4449444C0000 +A.test(); //OR-CALL ingress test 0x4449444C0000 //SKIP comp - - diff --git a/test/run-drun/general_await.mo b/test/run-drun/general_await.mo index 9e33432da49..e1d2be5a58e 100644 --- a/test/run-drun/general_await.mo +++ b/test/run-drun/general_await.mo @@ -1,24 +1,25 @@ +// test for explicit scope parameterization (disabled for now, uncomment /*<@>*/ once supported) actor Await { - public shared func Ack<@>() : async<@> (){ + public shared func Ack/*<@>*/() : async/*<@>*/ (){ debugPrint "Ack" }; - public shared func Request<@>(i : Int) : async<@> Int { + public shared func Request/*<@>*/(i : Int) : async/*<@>*/ Int { debugPrintInt(i); return i; }; // Static parallel waiting: - public shared func PA<@>() : async<@> () { + public shared func PA/*<@>*/() : async/*<@>*/ () { let a1 = Ack(); let a2 = Ack(); await a1; await a2; }; - public shared func PR<@>() : async<@>(Int,Int) { + public shared func PR/*<@>*/() : async/*<@>*/(Int,Int) { let a1 = Request(1); let a2 = Request(2); (await a1, await a2) @@ -26,7 +27,7 @@ actor Await { // Dynamic parallel waiting for acknowledgements - public shared func DPA<@>() : async<@>() { + public shared func DPA/*<@>*/() : async/*<@>*/() { let os = Array_init(10, null); for (i in os.keys()) { os[i] := ? (Ack()); @@ -41,7 +42,7 @@ actor Await { // Dynamic parallel waiting (with results) - public shared func DPR<@>() : async<@> [Int] { + public shared func DPR/*<@>*/() : async/*<@>*/ [Int] { let os = Array_init(10, null); for (i in os.keys()) { os[i] := ? (Request(i)); @@ -58,7 +59,7 @@ actor Await { // Recursive parallel waiting - public shared func RPA<@>(n:Nat) : async<@>() { + public shared func RPA/*<@>*/(n:Nat) : async/*<@>*/() { if (n == 0) () else { let a = Ack(); @@ -71,7 +72,7 @@ actor Await { public type List = ?(Int,List); - public shared func RPR<@>(n:Nat) : async<@> List { + public shared func RPR/*<@>*/(n:Nat) : async/*<@>*/ List { if (n == 0) null else { let a = Request(n); @@ -81,7 +82,7 @@ actor Await { }; - public shared func Test<@>() : async<@>() { + public shared func Test/*<@>*/() : async/*<@>*/() { await PA(); diff --git a/test/run-drun/ok/scope-example-func.tc.ok b/test/run-drun/ok/scope-example-func.tc.ok index d933fb4d510..1716f7b59a8 100644 --- a/test/run-drun/ok/scope-example-func.tc.ok +++ b/test/run-drun/ok/scope-example-func.tc.ok @@ -1 +1 @@ -scope-example-func.mo:8.13-8.34: type error, misplaced async expression +scope-example-func.mo:10.13-10.34: type error, misplaced async expression diff --git a/test/run-drun/ok/scope-example.tc.ok b/test/run-drun/ok/scope-example.tc.ok index 90b864bacb6..00366a48ebd 100644 --- a/test/run-drun/ok/scope-example.tc.ok +++ b/test/run-drun/ok/scope-example.tc.ok @@ -1 +1,4 @@ -scope-example.mo:10.18-10.19: type error, bad scope: expecting scope instantiation Z, found Y/1 +scope-example.mo:12.13-12.27: type error, expression of type + async<@/7> Int +cannot produce expected type + async<@/5> Int diff --git a/test/run-drun/scope-example-func.mo b/test/run-drun/scope-example-func.mo index 670c7fd2bff..f514c1c3f37 100644 --- a/test/run-drun/scope-example-func.mo +++ b/test/run-drun/scope-example-func.mo @@ -1,14 +1,16 @@ +// version of scope-example-func-implicit.mo that +// uses explicit scope parameters/instantiation (commented out for now until supported) actor A { - public shared func f() : async (Int,Int) = async { + public shared func f/**/() : async/**/ (Int,Int) = async /**/ { // current scope: Y - var a : (async Int) = async 0; + var a : (async/**/ Int) = async 0; func set () { a := async {return 666} /**/; }; - await (async { + await (async/**/ { // current scope: Z set(); // this seems well-typed according to “Application (Derived Rule)”; } /**/); diff --git a/test/run-drun/scope-example.mo b/test/run-drun/scope-example.mo index 1813672a4ee..295ffdd6e67 100644 --- a/test/run-drun/scope-example.mo +++ b/test/run-drun/scope-example.mo @@ -1,13 +1,15 @@ +// version of scope-example-implicit.mo that +// uses explicit scope parameters/instantiation (commented out for now until supported) actor A { - public shared func ping() : async Int = async {666;} /**/; // normal remote function + public shared func ping/**/() : async/**/ Int = async /**/ {666;} /**/; // normal remote function - public shared func f() : async (Int,Int) = async { + public shared func f/**/() : async/**/ (Int,Int) = async /**/ { // current scope: Y - var a : (async Int) = async 0; + var a : (async/**/ Int) = async 0; - await (async { + await (async/**/ { // current scope: Z - a := ping (); // this seems well-typed according to “Application (Derived Rule)”; + a := ping/**/ (); // this seems well-typed according to “Application (Derived Rule)”; } /**/); let i = await a; From 4b77bc535241d42bc2b0a0f7796ef836a6d21f23 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 11 Dec 2019 09:57:53 +0100 Subject: [PATCH 0928/1176] IR: Introduce TupPrim in the IR, the tupling operator is just another operator, so really it should be part of `prim` (like any other AST node that is call-by-name and does not bind any variables). This removes a case from every AST traversal. --- src/codegen/compile.ml | 10 ++++++---- src/ir_def/arrange_ir.ml | 2 +- src/ir_def/check_ir.ml | 5 ++--- src/ir_def/construct.ml | 14 +++++--------- src/ir_def/freevars.ml | 1 - src/ir_def/ir.ml | 2 +- src/ir_def/ir_effect.ml | 1 - src/ir_interpreter/interpret_ir.ml | 4 ++-- src/ir_passes/async.ml | 4 +--- src/ir_passes/await.ml | 4 ---- src/ir_passes/rename.ml | 1 - src/ir_passes/show.ml | 21 ++++----------------- src/ir_passes/tailcall.ml | 3 +-- src/lowering/desugar.ml | 6 +++--- 14 files changed, 26 insertions(+), 52 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 9401a320ade..cc4930829c1 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -5848,7 +5848,12 @@ and compile_exp (env : E.t) ae exp = SR.bool, compile_exp_as env ae sr e1 ^^ compile_exp_as env ae sr e2 ^^ + code + (* Tuples *) + | TupPrim, es -> + SR.UnboxedTuple (List.length es), + G.concat_map (compile_exp_vanilla env ae) es (* Numeric conversions *) | NumConvPrim (t1, t2), [e] -> begin @@ -6207,9 +6212,6 @@ and compile_exp (env : E.t) ae exp = | TagE (l, e) -> SR.Vanilla, Variant.inject env l (compile_exp_vanilla env ae e) - | TupE es -> - SR.UnboxedTuple (List.length es), - G.concat_map (compile_exp_vanilla env ae) es | ProjE (e1,n) -> SR.Vanilla, compile_exp_vanilla env ae e1 ^^ (* offset to tuple (an array) *) @@ -6700,7 +6702,7 @@ and compile_start_func mod_env (progs : Ir.prog list) : E.func_with_names = let find_last_expr ds e = if ds = [] then [], e.it else match Lib.List.split_last ds, e.it with - | (ds1', {it = LetD ({it = VarP i1; _}, e'); _}), TupE [] -> + | (ds1', {it = LetD ({it = VarP i1; _}, e'); _}), PrimE (TupPrim, []) -> ds1', e'.it | (ds1', {it = LetD ({it = VarP i1; _}, e'); _}), VarE i2 when i1 = i2 -> ds1', e'.it diff --git a/src/ir_def/arrange_ir.ml b/src/ir_def/arrange_ir.ml index 33490b65f39..2be216888eb 100644 --- a/src/ir_def/arrange_ir.ml +++ b/src/ir_def/arrange_ir.ml @@ -16,7 +16,6 @@ let rec exp e = match e.it with | VarE i -> "VarE" $$ [id i] | LitE l -> "LitE" $$ [lit l] | PrimE (p, es) -> "PrimE" $$ [prim p] @ List.map exp es - | TupE es -> "TupE" $$ List.map exp es | ProjE (e, i) -> "ProjE" $$ [exp e; Atom (string_of_int i)] | DotE (e, n) -> "DotE" $$ [exp e; Atom n] | ActorDotE (e, n) -> "ActorDotE" $$ [exp e; Atom n] @@ -64,6 +63,7 @@ and prim = function | UnPrim (t, uo) -> "UnPrim" $$ [typ t; Arrange_ops.unop uo] | BinPrim (t, bo) -> "BinPrim" $$ [typ t; Arrange_ops.binop bo] | RelPrim (t, ro) -> "RelPrim" $$ [typ t; Arrange_ops.relop ro] + | TupPrim -> Atom "TupPrim" | ShowPrim t -> "ShowPrim" $$ [typ t] | NumConvPrim (t1, t2) -> "NumConvPrim" $$ [prim_ty t1; prim_ty t2] | CastPrim (t1, t2) -> "CastPrim" $$ [typ t1; typ t2] diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 94f4bddf5a5..5648dd7a814 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -350,6 +350,8 @@ let rec check_exp env (exp:Ir.exp) : unit = typ exp1 <: ot; typ exp2 <: ot; T.bool <: t + | TupPrim, exps -> + T.Tup (List.map typ exps) <: t | ShowPrim ot, [exp1] -> check env.flavor.has_show "show expression in non-show flavor"; check (Show.can_show ot) "show is not defined for operand type"; @@ -414,9 +416,6 @@ let rec check_exp env (exp:Ir.exp) : unit = error env exp.at "PrimE %s does not work with %d arguments" (Wasm.Sexpr.to_string 80 (Arrange_ir.prim p)) (List.length args); end - | TupE exps -> - List.iter (check_exp env) exps; - T.Tup (List.map typ exps) <: t | OptE exp1 -> check_exp env exp1; T.Opt (typ exp1) <: t diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index 8f3d24fea79..6968e21c0dd 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -151,9 +151,9 @@ let dec_eff dec = match dec.it with let rec simpl_decs decs = List.concat (List.map simpl_dec decs) and simpl_dec dec = match dec.it with - | LetD ({it = WildP;_}, {it = TupE [];_}) -> + | LetD ({it = WildP;_}, {it = PrimE (TupPrim, []);_}) -> [] - | LetD ({it = TupP ps;_}, {it = TupE es;_}) when List.length ps = List.length es -> + | LetD ({it = TupP ps;_}, {it = PrimE (TupPrim, es);_}) when List.length ps = List.length es -> simpl_decs (List.map2 (fun p e -> LetD (p, e) @@ p.at) ps es) | _ -> [ dec ] @@ -183,12 +183,6 @@ let blobE s = note = { note_typ = T.blob; note_eff = T.Triv } } -let unitE = - { it = TupE []; - at = no_region; - note = { note_typ = T.Tup []; note_eff = T.Triv } - } - let boolE b = { it = LitE (BoolLit b); at = no_region; @@ -273,7 +267,7 @@ let switch_variantE exp1 cases typ1 = let tupE exps = let effs = List.map eff exps in let eff = List.fold_left max_eff T.Triv effs in - { it = TupE exps; + { it = PrimE (TupPrim, exps); at = no_region; note = { note_typ = T.Tup (List.map typ exps); @@ -281,6 +275,8 @@ let tupE exps = } } +let unitE = tupE [] + let breakE l exp = { it = BreakE (l, exp); at = no_region; diff --git a/src/ir_def/freevars.ml b/src/ir_def/freevars.ml index a9a17878181..c48f4c85b9f 100644 --- a/src/ir_def/freevars.ml +++ b/src/ir_def/freevars.ml @@ -72,7 +72,6 @@ let rec exp e : f = match e.it with | VarE i -> id i | LitE l -> M.empty | PrimE (_, es) -> exps es - | TupE es -> exps es | ProjE (e, i) -> exp e | DotE (e, i) -> exp e | ActorDotE (e, i) -> exp e diff --git a/src/ir_def/ir.ml b/src/ir_def/ir.ml index fa657c429fa..b572e3f1f0e 100644 --- a/src/ir_def/ir.ml +++ b/src/ir_def/ir.ml @@ -65,7 +65,6 @@ and exp' = | PrimE of (prim * exp list) (* primitive *) | VarE of id (* variable *) | LitE of lit (* literal *) - | TupE of exp list (* tuple *) | ProjE of exp * int (* tuple projection *) | OptE of exp (* option injection *) | TagE of id * exp (* variant injection *) @@ -112,6 +111,7 @@ and prim = | UnPrim of Type.typ * unop (* unary operator *) | BinPrim of Type.typ * binop (* binary operator *) | RelPrim of Type.typ * relop (* relational operator *) + | TupPrim (* the tuple constructor *) | ShowPrim of Type.typ (* debug show *) | NumConvPrim of Type.prim * Type.prim | CastPrim of Type.typ * Type.typ (* representationally a noop *) diff --git a/src/ir_def/ir_effect.ml b/src/ir_def/ir_effect.ml index e8a2255f39a..587efad3d08 100644 --- a/src/ir_def/ir_effect.ml +++ b/src/ir_def/ir_effect.ml @@ -46,7 +46,6 @@ let rec infer_effect_exp (exp: exp) : T.eff = let t2 = effect_exp exp2 in max_eff t1 t2 | PrimE (_, exps) - | TupE exps | ArrayE (_, _, exps) -> let es = List.map effect_exp exps in List.fold_left max_eff T.Triv es diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index d8a5229ae37..7299520a98b 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -322,6 +322,8 @@ and interpret_exp_mut env exp (k : V.value V.cont) = k (Operator.relop op ot v1 v2) ) ) + | TupPrim, exps -> + interpret_exps env exps [] (fun vs -> k (V.Tup vs)) | ShowPrim ot, [exp1] -> interpret_exp env exp1 (fun v -> if Show.can_show ot @@ -405,8 +407,6 @@ and interpret_exp_mut env exp (k : V.value V.cont) = trap exp.at "Unknown prim or wrong number of arguments (%d given):\n %s" (List.length es) (Wasm.Sexpr.to_string 80 (Arrange_ir.prim p)) end - | TupE exps -> - interpret_exps env exps [] (fun vs -> k (V.Tup vs)) | OptE exp1 -> interpret_exp env exp1 (fun v1 -> k (V.Opt v1)) | TagE (i, exp1) -> diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index ceaac21f942..676000985d7 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -227,8 +227,6 @@ let transform mode env prog = match exp' with | LitE _ -> exp' | VarE id -> exp' - | TupE exps -> - TupE (List.map t_exp exps) | OptE exp1 -> OptE (t_exp exp1) | TagE (i, exp1) -> @@ -354,7 +352,7 @@ let transform mode env prog = [{ it = LetD ( { it = WildP; _}, ({ it = PrimE (CPSAsync, _); _} as exp)); _ }], - { it = TupE []; _}); + { it = PrimE (TupPrim, []); _}); _ } -> let ret_tys = List.map t_typ ret_tys in let args' = t_args args in diff --git a/src/ir_passes/await.ml b/src/ir_passes/await.ml index 2e45565fb06..3621480258f 100644 --- a/src/ir_passes/await.ml +++ b/src/ir_passes/await.ml @@ -65,8 +65,6 @@ and t_exp' context exp' = | LitE _ -> exp' | PrimE (p, exps) -> PrimE (p, List.map (t_exp context) exps) - | TupE exps -> - TupE (List.map (t_exp context) exps) | OptE exp1 -> OptE (t_exp context exp1) | TagE (id, exp1) -> @@ -263,8 +261,6 @@ and c_exp' context exp k = assert false | PrimE (p, exps) -> nary context k (fun vs -> e (PrimE (p, vs))) exps - | TupE exps -> - nary context k (fun vs -> e (TupE vs)) exps | OptE exp1 -> unary context k (fun v1 -> e (OptE v1)) exp1 | TagE (i, exp1) -> diff --git a/src/ir_passes/rename.ml b/src/ir_passes/rename.ml index 83405c950c1..ccc934ace56 100644 --- a/src/ir_passes/rename.ml +++ b/src/ir_passes/rename.ml @@ -34,7 +34,6 @@ and exp' rho e = match e with | VarE i -> VarE (id rho i) | LitE l -> e | PrimE (p, es) -> PrimE (p, List.map (exp rho) es) - | TupE es -> TupE (List.map (exp rho) es) | ProjE (e, i) -> ProjE (exp rho e, i) | ActorE (i, ds, fs, t)-> let i',rho' = id_bind rho i in let ds', rho'' = decs rho' ds diff --git a/src/ir_passes/show.ml b/src/ir_passes/show.ml index 3d111009c2f..67b602175d9 100644 --- a/src/ir_passes/show.ml +++ b/src/ir_passes/show.ml @@ -100,10 +100,7 @@ let invoke_text_of_option : T.typ -> Ir.exp -> Ir.exp -> Ir.exp = fun t f e -> ; note = { note_typ = fun_typ; note_eff = T.Triv } } , [t] - , { it = TupE [f; e] - ; at = no_region - ; note = { note_typ = T.Tup [show_fun_typ_for t; T.Opt t]; note_eff = T.Triv } - } + , tupE [f; e] ) ) @@ -116,10 +113,7 @@ let invoke_text_of_variant : T.typ -> Ir.exp -> T.lab -> Ir.exp -> Ir.exp = fun ; note = { note_typ = fun_typ; note_eff = T.Triv } } , [t] - , { it = TupE [textE l; f; e] - ; at = no_region - ; note = { note_typ = T.Tup [T.text; show_fun_typ_for t; t]; note_eff = T.Triv } - } + , tupE [textE l; f; e] ) ) @@ -132,10 +126,7 @@ let invoke_text_of_array : T.typ -> Ir.exp -> Ir.exp -> Ir.exp = fun t f e -> ; note = { note_typ = fun_typ; note_eff = T.Triv } } , [t] - , { it = TupE [f; e] - ; at = no_region - ; note = { note_typ = T.Tup [show_fun_typ_for t; T.Array t]; note_eff = T.Triv } - } + , tupE [f; e] ) ) @@ -148,10 +139,7 @@ let invoke_text_of_array_mut : T.typ -> Ir.exp -> Ir.exp -> Ir.exp = fun t f e - ; note = { note_typ = fun_typ; note_eff = T.Triv } } , [t] - , { it = TupE [f; e] - ; at = no_region - ; note = { note_typ = T.Tup [show_fun_typ_for t; T.Array (T.Mut t)]; note_eff = T.Triv } - } + , tupE [f; e] ) ) @@ -346,7 +334,6 @@ and t_exp' env = function let f = idE (show_name_for t') (show_fun_typ_for t') in CallE (f, [], t_exp env exp1) | PrimE (p, es) -> PrimE (p, t_exps env es) - | TupE exps -> TupE (t_exps env exps) | OptE exp1 -> OptE (t_exp env exp1) | TagE (l, exp1) -> diff --git a/src/ir_passes/tailcall.ml b/src/ir_passes/tailcall.ml index c4ea922a2a3..8558926efb5 100644 --- a/src/ir_passes/tailcall.ml +++ b/src/ir_passes/tailcall.ml @@ -84,7 +84,7 @@ and exp env e : exp = and assignEs vars exp : dec list = match vars, exp.it with | [v], _ -> [ expD (assignE v exp) ] - | _, TupE es when List.length es = List.length vars -> + | _, PrimE (TupPrim, es) when List.length es = List.length vars -> List.map expD (List.map2 assignE vars es) | _, _ -> let tup = fresh_var "tup" (typ exp) in @@ -94,7 +94,6 @@ and assignEs vars exp : dec list = and exp' env e : exp' = match e.it with | VarE _ | LitE _ -> e.it | PrimE (p, es) -> PrimE (p, List.map (exp env) es) - | TupE es -> TupE (List.map (exp env) es) | ProjE (e, i) -> ProjE (exp env e, i) | DotE (e, sn) -> DotE (exp env e, sn) | ActorDotE (e, sn) -> ActorDotE (exp env e, sn) diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index c5d21ec6360..b68ac0c35fa 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -68,7 +68,7 @@ and exp' at note = function I.PrimE (I.RelPrim (!ot, o), [exp e1; exp e2]) | S.ShowE (ot, e) -> I.PrimE (I.ShowPrim !ot, [exp e]) - | S.TupE es -> I.TupE (exps es) + | S.TupE es -> (tupE (exps es)).it | S.ProjE (e, i) -> I.ProjE (exp e, i) | S.OptE e -> I.OptE (exp e) | S.ObjE (s, es) -> @@ -128,7 +128,7 @@ and exp' at note = function else let inst = List.map (fun t -> t.Source.note) inst in I.CallE (exp e1, inst, exp e2) - | S.BlockE [] -> I.TupE [] + | S.BlockE [] -> unitE.it | S.BlockE [{it = S.ExpD e; _}] -> (exp e).it | S.BlockE ds -> I.BlockE (block (T.is_unit note.I.note_typ) ds) | S.NotE e -> I.IfE (exp e, falseE, trueE) @@ -141,7 +141,7 @@ and exp' at note = function | S.LoopE (e1, None) -> I.LoopE (exp e1) | S.LoopE (e1, Some e2) -> (loopWhileE (exp e1) (exp e2)).it | S.ForE (p, e1, e2) -> (forE (pat p) (exp e1) (exp e2)).it - | S.DebugE e -> if !Mo_config.Flags.release_mode then I.TupE [] else (exp e).it + | S.DebugE e -> if !Mo_config.Flags.release_mode then unitE.it else (exp e).it | S.LabelE (l, t, e) -> I.LabelE (l.it, t.Source.note, exp e) | S.BreakE (l, e) -> I.BreakE (l.it, exp e) | S.RetE e -> I.RetE (exp e) From d4dde1203edaa8edee8afbfec3095a638f0e7a2e Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 11 Dec 2019 10:10:13 +0100 Subject: [PATCH 0929/1176] Dito with ProjPrim --- src/codegen/compile.ml | 8 ++++---- src/ir_def/arrange_ir.ml | 2 +- src/ir_def/check_ir.ml | 23 +++++++++++------------ src/ir_def/construct.ml | 2 +- src/ir_def/freevars.ml | 1 - src/ir_def/ir.ml | 3 ++- src/ir_def/ir_effect.ml | 1 - src/ir_interpreter/interpret_ir.ml | 4 ++-- src/ir_passes/async.ml | 2 -- src/ir_passes/await.ml | 4 ---- src/ir_passes/rename.ml | 1 - src/ir_passes/show.ml | 11 +---------- src/ir_passes/tailcall.ml | 1 - src/lowering/desugar.ml | 2 +- 14 files changed, 23 insertions(+), 42 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index cc4930829c1..3154c4debdb 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -5854,6 +5854,10 @@ and compile_exp (env : E.t) ae exp = | TupPrim, es -> SR.UnboxedTuple (List.length es), G.concat_map (compile_exp_vanilla env ae) es + | ProjPrim n, [e1] -> + SR.Vanilla, + compile_exp_vanilla env ae e1 ^^ (* offset to tuple (an array) *) + Tuple.load_n (Int32.of_int n) (* Numeric conversions *) | NumConvPrim (t1, t2), [e] -> begin @@ -6212,10 +6216,6 @@ and compile_exp (env : E.t) ae exp = | TagE (l, e) -> SR.Vanilla, Variant.inject env l (compile_exp_vanilla env ae e) - | ProjE (e1,n) -> - SR.Vanilla, - compile_exp_vanilla env ae e1 ^^ (* offset to tuple (an array) *) - Tuple.load_n (Int32.of_int n) | ArrayE (m, t, es) -> SR.Vanilla, Arr.lit env (List.map (compile_exp_vanilla env ae) es) | CallE (e1, _, e2) -> diff --git a/src/ir_def/arrange_ir.ml b/src/ir_def/arrange_ir.ml index 2be216888eb..eec3c7eb9b6 100644 --- a/src/ir_def/arrange_ir.ml +++ b/src/ir_def/arrange_ir.ml @@ -16,7 +16,6 @@ let rec exp e = match e.it with | VarE i -> "VarE" $$ [id i] | LitE l -> "LitE" $$ [lit l] | PrimE (p, es) -> "PrimE" $$ [prim p] @ List.map exp es - | ProjE (e, i) -> "ProjE" $$ [exp e; Atom (string_of_int i)] | DotE (e, n) -> "DotE" $$ [exp e; Atom n] | ActorDotE (e, n) -> "ActorDotE" $$ [exp e; Atom n] | AssignE (le1, e2) -> "AssignE" $$ [lexp le1; exp e2] @@ -64,6 +63,7 @@ and prim = function | BinPrim (t, bo) -> "BinPrim" $$ [typ t; Arrange_ops.binop bo] | RelPrim (t, ro) -> "RelPrim" $$ [typ t; Arrange_ops.relop ro] | TupPrim -> Atom "TupPrim" + | ProjPrim i -> "ProjPrim" $$ [Atom (string_of_int i)] | ShowPrim t -> "ShowPrim" $$ [typ t] | NumConvPrim (t1, t2) -> "NumConvPrim" $$ [prim_ty t1; prim_ty t2] | CastPrim (t1, t2) -> "CastPrim" $$ [typ t1; typ t2] diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 5648dd7a814..e5de7f7f489 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -352,6 +352,17 @@ let rec check_exp env (exp:Ir.exp) : unit = T.bool <: t | TupPrim, exps -> T.Tup (List.map typ exps) <: t + | ProjPrim n, [exp1] -> + let t1 = T.promote (immute_typ exp1) in + let ts = try T.as_tup_sub n t1 + with Invalid_argument _ -> + error env exp1.at "expected tuple type, but expression produces type\n %s" + (T.string_of_typ_expand t1) in + let tn = try List.nth ts n with + | Invalid_argument _ -> + error env exp.at "tuple projection %n is out of bounds for type\n %s" + n (T.string_of_typ_expand t1) in + tn <: t | ShowPrim ot, [exp1] -> check env.flavor.has_show "show expression in non-show flavor"; check (Show.can_show ot) "show is not defined for operand type"; @@ -422,18 +433,6 @@ let rec check_exp env (exp:Ir.exp) : unit = | TagE (i, exp1) -> check_exp env exp1; T.Variant [{T.lab = i; typ = typ exp1}] <: t - | ProjE (exp1, n) -> - check_exp env exp1; - let t1 = T.promote (immute_typ exp1) in - let ts = try T.as_tup_sub n t1 - with Invalid_argument _ -> - error env exp1.at "expected tuple type, but expression produces type\n %s" - (T.string_of_typ_expand t1) in - let tn = try List.nth ts n with - | Invalid_argument _ -> - error env exp.at "tuple projection %n is out of bounds for type\n %s" - n (T.string_of_typ_expand t1) in - tn <: t | ActorDotE(exp1, n) | DotE (exp1, n) -> begin diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index 6968e21c0dd..4b2d49450b4 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -139,7 +139,7 @@ let ic_callE f e k r = let projE e n = match typ e with | T.Tup ts -> - { it = ProjE (e, n); + { it = PrimE (ProjPrim n, [e]); note = { note_typ = List.nth ts n; note_eff = eff e }; at = no_region; } diff --git a/src/ir_def/freevars.ml b/src/ir_def/freevars.ml index c48f4c85b9f..b90c4dc0409 100644 --- a/src/ir_def/freevars.ml +++ b/src/ir_def/freevars.ml @@ -72,7 +72,6 @@ let rec exp e : f = match e.it with | VarE i -> id i | LitE l -> M.empty | PrimE (_, es) -> exps es - | ProjE (e, i) -> exp e | DotE (e, i) -> exp e | ActorDotE (e, i) -> exp e | AssignE (e1, e2) -> lexp e1 ++ exp e2 diff --git a/src/ir_def/ir.ml b/src/ir_def/ir.ml index b572e3f1f0e..40f15c8221b 100644 --- a/src/ir_def/ir.ml +++ b/src/ir_def/ir.ml @@ -65,7 +65,6 @@ and exp' = | PrimE of (prim * exp list) (* primitive *) | VarE of id (* variable *) | LitE of lit (* literal *) - | ProjE of exp * int (* tuple projection *) | OptE of exp (* option injection *) | TagE of id * exp (* variant injection *) | DotE of exp * Type.lab (* object projection *) @@ -112,12 +111,14 @@ and prim = | BinPrim of Type.typ * binop (* binary operator *) | RelPrim of Type.typ * relop (* relational operator *) | TupPrim (* the tuple constructor *) + | ProjPrim of int (* tuple projection *) | ShowPrim of Type.typ (* debug show *) | NumConvPrim of Type.prim * Type.prim | CastPrim of Type.typ * Type.typ (* representationally a noop *) | ActorOfIdBlob of Type.typ | BlobOfIcUrl (* traps on syntax or checksum failure *) | OtherPrim of string (* Other primitive operation, no custom typing rule *) + (* backend stuff *) | CPSAwait | CPSAsync | ICReplyPrim of Type.typ list diff --git a/src/ir_def/ir_effect.ml b/src/ir_def/ir_effect.ml index 587efad3d08..2c2a5eb0818 100644 --- a/src/ir_def/ir_effect.ml +++ b/src/ir_def/ir_effect.ml @@ -28,7 +28,6 @@ let rec infer_effect_exp (exp: exp) : T.eff = | VarE _ | LitE _ -> T.Triv - | ProjE (exp1, _) | OptE exp1 | TagE (_, exp1) | DotE (exp1, _) diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index 7299520a98b..2e2e7724587 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -324,6 +324,8 @@ and interpret_exp_mut env exp (k : V.value V.cont) = ) | TupPrim, exps -> interpret_exps env exps [] (fun vs -> k (V.Tup vs)) + | ProjPrim n, [exp1] -> + interpret_exp env exp1 (fun v1 -> k (List.nth (V.as_tup v1) n)) | ShowPrim ot, [exp1] -> interpret_exp env exp1 (fun v -> if Show.can_show ot @@ -411,8 +413,6 @@ and interpret_exp_mut env exp (k : V.value V.cont) = interpret_exp env exp1 (fun v1 -> k (V.Opt v1)) | TagE (i, exp1) -> interpret_exp env exp1 (fun v1 -> k (V.Variant (i, v1))) - | ProjE (exp1, n) -> - interpret_exp env exp1 (fun v1 -> k (List.nth (V.as_tup v1) n)) | DotE (exp1, n) -> interpret_exp env exp1 (fun v1 -> let fs = V.as_obj v1 in diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index 676000985d7..b90f3d49938 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -231,8 +231,6 @@ let transform mode env prog = OptE (t_exp exp1) | TagE (i, exp1) -> TagE (i, t_exp exp1) - | ProjE (exp1, n) -> - ProjE (t_exp exp1, n) | DotE (exp1, id) -> DotE (t_exp exp1, id) | ActorDotE (exp1, id) -> diff --git a/src/ir_passes/await.ml b/src/ir_passes/await.ml index 3621480258f..ec89cfbead8 100644 --- a/src/ir_passes/await.ml +++ b/src/ir_passes/await.ml @@ -69,8 +69,6 @@ and t_exp' context exp' = OptE (t_exp context exp1) | TagE (id, exp1) -> TagE (id, t_exp context exp1) - | ProjE (exp1, n) -> - ProjE (t_exp context exp1, n) | DotE (exp1, id) -> DotE (t_exp context exp1, id) | ActorDotE (exp1, id) -> @@ -265,8 +263,6 @@ and c_exp' context exp k = unary context k (fun v1 -> e (OptE v1)) exp1 | TagE (i, exp1) -> unary context k (fun v1 -> e (TagE (i, v1))) exp1 - | ProjE (exp1, n) -> - unary context k (fun v1 -> e (ProjE (v1, n))) exp1 | ActorE _ -> assert false; (* ActorE fields cannot await *) | DotE (exp1, id) -> diff --git a/src/ir_passes/rename.ml b/src/ir_passes/rename.ml index ccc934ace56..5e6ecbb7392 100644 --- a/src/ir_passes/rename.ml +++ b/src/ir_passes/rename.ml @@ -34,7 +34,6 @@ and exp' rho e = match e with | VarE i -> VarE (id rho i) | LitE l -> e | PrimE (p, es) -> PrimE (p, List.map (exp rho) es) - | ProjE (e, i) -> ProjE (exp rho e, i) | ActorE (i, ds, fs, t)-> let i',rho' = id_bind rho i in let ds', rho'' = decs rho' ds in ActorE (i', ds', fields rho'' fs, t) diff --git a/src/ir_passes/show.ml b/src/ir_passes/show.ml index 67b602175d9..dfe693867cf 100644 --- a/src/ir_passes/show.ml +++ b/src/ir_passes/show.ml @@ -235,14 +235,7 @@ let show_for : T.typ -> Ir.dec * T.typ list = fun t -> define_show t ( cat_list (list_build (textE "(") (textE ", ") (textE ")") - (List.mapi (fun i t' -> - invoke_generated_show t' ( - { it = ProjE (argE t, i) - ; at = no_region - ; note = { note_typ = t'; note_eff = T.Triv } - } - ) - ) ts') + (List.mapi (fun i t' -> invoke_generated_show t' (projE (argE t) i)) ts') ) ), ts' @@ -338,8 +331,6 @@ and t_exp' env = function OptE (t_exp env exp1) | TagE (l, exp1) -> TagE (l, t_exp env exp1) - | ProjE (exp1, n) -> - ProjE (t_exp env exp1, n) | DotE (exp1, id) -> DotE (t_exp env exp1, id) | ActorDotE (exp1, id) -> diff --git a/src/ir_passes/tailcall.ml b/src/ir_passes/tailcall.ml index 8558926efb5..55c46a5b714 100644 --- a/src/ir_passes/tailcall.ml +++ b/src/ir_passes/tailcall.ml @@ -94,7 +94,6 @@ and assignEs vars exp : dec list = and exp' env e : exp' = match e.it with | VarE _ | LitE _ -> e.it | PrimE (p, es) -> PrimE (p, List.map (exp env) es) - | ProjE (e, i) -> ProjE (exp env e, i) | DotE (e, sn) -> DotE (exp env e, sn) | ActorDotE (e, sn) -> ActorDotE (exp env e, sn) | AssignE (e1, e2) -> AssignE (lexp env e1, exp env e2) diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index b68ac0c35fa..b117176369a 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -69,7 +69,7 @@ and exp' at note = function | S.ShowE (ot, e) -> I.PrimE (I.ShowPrim !ot, [exp e]) | S.TupE es -> (tupE (exps es)).it - | S.ProjE (e, i) -> I.ProjE (exp e, i) + | S.ProjE (e, i) -> (projE (exp e) i).it | S.OptE e -> I.OptE (exp e) | S.ObjE (s, es) -> obj at s None es note.I.note_typ From 805e5fe8fd1f739419ec0f25fbd5d0519cd99d88 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 11 Dec 2019 10:18:27 +0100 Subject: [PATCH 0930/1176] Dito with OptPrim --- src/codegen/compile.ml | 7 ++++--- src/ir_def/arrange_ir.ml | 2 +- src/ir_def/check_ir.ml | 5 ++--- src/ir_def/construct.ml | 6 ++++++ src/ir_def/construct.mli | 3 ++- src/ir_def/freevars.ml | 1 - src/ir_def/ir.ml | 2 +- src/ir_def/ir_effect.ml | 1 - src/ir_interpreter/interpret_ir.ml | 4 ++-- src/ir_passes/async.ml | 2 -- src/ir_passes/await.ml | 4 ---- src/ir_passes/rename.ml | 1 - src/ir_passes/show.ml | 2 -- src/ir_passes/tailcall.ml | 1 - src/lowering/desugar.ml | 2 +- 15 files changed, 19 insertions(+), 24 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 3154c4debdb..95b7433faf6 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -5859,6 +5859,10 @@ and compile_exp (env : E.t) ae exp = compile_exp_vanilla env ae e1 ^^ (* offset to tuple (an array) *) Tuple.load_n (Int32.of_int n) + | OptPrim, [e] -> + SR.Vanilla, + Opt.inject env (compile_exp_vanilla env ae e) + (* Numeric conversions *) | NumConvPrim (t1, t2), [e] -> begin let open Type in @@ -6210,9 +6214,6 @@ and compile_exp (env : E.t) ae exp = compile_exp_as env ae (StackRep.of_arity (E.get_return_arity env)) e ^^ FakeMultiVal.store env (Lib.List.make (E.get_return_arity env) I32Type) ^^ G.i Return - | OptE e -> - SR.Vanilla, - Opt.inject env (compile_exp_vanilla env ae e) | TagE (l, e) -> SR.Vanilla, Variant.inject env l (compile_exp_vanilla env ae e) diff --git a/src/ir_def/arrange_ir.ml b/src/ir_def/arrange_ir.ml index eec3c7eb9b6..8ee999c21f2 100644 --- a/src/ir_def/arrange_ir.ml +++ b/src/ir_def/arrange_ir.ml @@ -32,7 +32,6 @@ let rec exp e = match e.it with | AsyncE e -> "AsyncE" $$ [exp e] | AwaitE e -> "AwaitE" $$ [exp e] | AssertE e -> "AssertE" $$ [exp e] - | OptE e -> "OptE" $$ [exp e] | TagE (i, e) -> "TagE" $$ [id i; exp e] | DeclareE (i, t, e1) -> "DeclareE" $$ [id i; exp e1] | DefineE (i, m, e1) -> "DefineE" $$ [id i; mut m; exp e1] @@ -64,6 +63,7 @@ and prim = function | RelPrim (t, ro) -> "RelPrim" $$ [typ t; Arrange_ops.relop ro] | TupPrim -> Atom "TupPrim" | ProjPrim i -> "ProjPrim" $$ [Atom (string_of_int i)] + | OptPrim -> Atom "OptPrim" | ShowPrim t -> "ShowPrim" $$ [typ t] | NumConvPrim (t1, t2) -> "NumConvPrim" $$ [prim_ty t1; prim_ty t2] | CastPrim (t1, t2) -> "CastPrim" $$ [typ t1; typ t2] diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index e5de7f7f489..1f42e14b898 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -363,6 +363,8 @@ let rec check_exp env (exp:Ir.exp) : unit = error env exp.at "tuple projection %n is out of bounds for type\n %s" n (T.string_of_typ_expand t1) in tn <: t + | OptPrim, [exp1] -> + T.Opt (typ exp1) <: t | ShowPrim ot, [exp1] -> check env.flavor.has_show "show expression in non-show flavor"; check (Show.can_show ot) "show is not defined for operand type"; @@ -427,9 +429,6 @@ let rec check_exp env (exp:Ir.exp) : unit = error env exp.at "PrimE %s does not work with %d arguments" (Wasm.Sexpr.to_string 80 (Arrange_ir.prim p)) (List.length args); end - | OptE exp1 -> - check_exp env exp1; - T.Opt (typ exp1) <: t | TagE (i, exp1) -> check_exp env exp1; T.Variant [{T.lab = i; typ = typ exp1}] <: t diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index 4b2d49450b4..1a9c6ccaec9 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -145,6 +145,12 @@ let projE e n = } | _ -> failwith "projE" +let optE e = + { it = PrimE (OptPrim, [e]); + note = { note_typ = T.Opt (typ e); note_eff = eff e }; + at = no_region; + } + let dec_eff dec = match dec.it with | TypD _ -> T.Triv | LetD (_,e) | VarD (_,e) -> eff e diff --git a/src/ir_def/construct.mli b/src/ir_def/construct.mli index cab2e0a80dd..48d77771315 100644 --- a/src/ir_def/construct.mli +++ b/src/ir_def/construct.mli @@ -45,7 +45,8 @@ val awaitE : typ -> exp -> exp -> exp val ic_replyE : typ list -> exp -> exp val ic_rejectE : exp -> exp val ic_callE : exp -> exp -> exp -> exp -> exp -val projE : exp -> int -> exp +val projE : exp -> int -> exp +val optE : exp -> exp val blockE : dec list -> exp -> exp val textE : string -> exp val blobE : string -> exp diff --git a/src/ir_def/freevars.ml b/src/ir_def/freevars.ml index b90c4dc0409..ffda1cbf3ff 100644 --- a/src/ir_def/freevars.ml +++ b/src/ir_def/freevars.ml @@ -88,7 +88,6 @@ let rec exp e : f = match e.it with | AsyncE e -> exp e | AwaitE e -> exp e | AssertE e -> exp e - | OptE e -> exp e | TagE (_, e) -> exp e | DeclareE (i, t, e) -> exp e // i | DefineE (i, m, e) -> id i ++ exp e diff --git a/src/ir_def/ir.ml b/src/ir_def/ir.ml index 40f15c8221b..7e0e4850088 100644 --- a/src/ir_def/ir.ml +++ b/src/ir_def/ir.ml @@ -65,7 +65,6 @@ and exp' = | PrimE of (prim * exp list) (* primitive *) | VarE of id (* variable *) | LitE of lit (* literal *) - | OptE of exp (* option injection *) | TagE of id * exp (* variant injection *) | DotE of exp * Type.lab (* object projection *) | ActorDotE of exp * Type.lab (* actor field access *) @@ -112,6 +111,7 @@ and prim = | RelPrim of Type.typ * relop (* relational operator *) | TupPrim (* the tuple constructor *) | ProjPrim of int (* tuple projection *) + | OptPrim (* option injection *) | ShowPrim of Type.typ (* debug show *) | NumConvPrim of Type.prim * Type.prim | CastPrim of Type.typ * Type.typ (* representationally a noop *) diff --git a/src/ir_def/ir_effect.ml b/src/ir_def/ir_effect.ml index 2c2a5eb0818..98526ffc61a 100644 --- a/src/ir_def/ir_effect.ml +++ b/src/ir_def/ir_effect.ml @@ -28,7 +28,6 @@ let rec infer_effect_exp (exp: exp) : T.eff = | VarE _ | LitE _ -> T.Triv - | OptE exp1 | TagE (_, exp1) | DotE (exp1, _) | ActorDotE (exp1, _) diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index 2e2e7724587..4dd115868f7 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -326,6 +326,8 @@ and interpret_exp_mut env exp (k : V.value V.cont) = interpret_exps env exps [] (fun vs -> k (V.Tup vs)) | ProjPrim n, [exp1] -> interpret_exp env exp1 (fun v1 -> k (List.nth (V.as_tup v1) n)) + | OptPrim, [exp1] -> + interpret_exp env exp1 (fun v1 -> k (V.Opt v1)) | ShowPrim ot, [exp1] -> interpret_exp env exp1 (fun v -> if Show.can_show ot @@ -409,8 +411,6 @@ and interpret_exp_mut env exp (k : V.value V.cont) = trap exp.at "Unknown prim or wrong number of arguments (%d given):\n %s" (List.length es) (Wasm.Sexpr.to_string 80 (Arrange_ir.prim p)) end - | OptE exp1 -> - interpret_exp env exp1 (fun v1 -> k (V.Opt v1)) | TagE (i, exp1) -> interpret_exp env exp1 (fun v1 -> k (V.Variant (i, v1))) | DotE (exp1, n) -> diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index b90f3d49938..35ec7dc94ec 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -227,8 +227,6 @@ let transform mode env prog = match exp' with | LitE _ -> exp' | VarE id -> exp' - | OptE exp1 -> - OptE (t_exp exp1) | TagE (i, exp1) -> TagE (i, t_exp exp1) | DotE (exp1, id) -> diff --git a/src/ir_passes/await.ml b/src/ir_passes/await.ml index ec89cfbead8..cfb13d81dc9 100644 --- a/src/ir_passes/await.ml +++ b/src/ir_passes/await.ml @@ -65,8 +65,6 @@ and t_exp' context exp' = | LitE _ -> exp' | PrimE (p, exps) -> PrimE (p, List.map (t_exp context) exps) - | OptE exp1 -> - OptE (t_exp context exp1) | TagE (id, exp1) -> TagE (id, t_exp context exp1) | DotE (exp1, id) -> @@ -259,8 +257,6 @@ and c_exp' context exp k = assert false | PrimE (p, exps) -> nary context k (fun vs -> e (PrimE (p, vs))) exps - | OptE exp1 -> - unary context k (fun v1 -> e (OptE v1)) exp1 | TagE (i, exp1) -> unary context k (fun v1 -> e (TagE (i, v1))) exp1 | ActorE _ -> diff --git a/src/ir_passes/rename.ml b/src/ir_passes/rename.ml index 5e6ecbb7392..4704d3dc086 100644 --- a/src/ir_passes/rename.ml +++ b/src/ir_passes/rename.ml @@ -55,7 +55,6 @@ and exp' rho e = match e with | AsyncE e -> AsyncE (exp rho e) | AwaitE e -> AwaitE (exp rho e) | AssertE e -> AssertE (exp rho e) - | OptE e -> OptE (exp rho e) | TagE (i, e) -> TagE (i, exp rho e) | DeclareE (i, t, e) -> let i',rho' = id_bind rho i in DeclareE (i', t, exp rho' e) diff --git a/src/ir_passes/show.ml b/src/ir_passes/show.ml index dfe693867cf..8490e9b5578 100644 --- a/src/ir_passes/show.ml +++ b/src/ir_passes/show.ml @@ -327,8 +327,6 @@ and t_exp' env = function let f = idE (show_name_for t') (show_fun_typ_for t') in CallE (f, [], t_exp env exp1) | PrimE (p, es) -> PrimE (p, t_exps env es) - | OptE exp1 -> - OptE (t_exp env exp1) | TagE (l, exp1) -> TagE (l, t_exp env exp1) | DotE (exp1, id) -> diff --git a/src/ir_passes/tailcall.ml b/src/ir_passes/tailcall.ml index 55c46a5b714..8393e33bb70 100644 --- a/src/ir_passes/tailcall.ml +++ b/src/ir_passes/tailcall.ml @@ -124,7 +124,6 @@ and exp' env e : exp' = match e.it with | AsyncE e -> AsyncE (exp { tail_pos = true; info = None } e) | AwaitE e -> AwaitE (exp env e) | AssertE e -> AssertE (exp env e) - | OptE e -> OptE (exp env e) | TagE (i, e) -> TagE (i, exp env e) | DeclareE (i, t, e) -> let env1 = bind env i None in DeclareE (i, t, tailexp env1 e) diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index b117176369a..090bc174df4 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -70,7 +70,7 @@ and exp' at note = function I.PrimE (I.ShowPrim !ot, [exp e]) | S.TupE es -> (tupE (exps es)).it | S.ProjE (e, i) -> (projE (exp e) i).it - | S.OptE e -> I.OptE (exp e) + | S.OptE e -> (optE (exp e)).it | S.ObjE (s, es) -> obj at s None es note.I.note_typ | S.TagE (c, e) -> I.TagE (c.it, exp e) From b0db19db629e1755b95c4da1f9c74ca7b653293d Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 11 Dec 2019 10:24:01 +0100 Subject: [PATCH 0931/1176] Dito with TagPrim --- src/codegen/compile.ml | 6 +++--- src/ir_def/arrange_ir.ml | 2 +- src/ir_def/check_ir.ml | 5 ++--- src/ir_def/construct.ml | 6 ++++++ src/ir_def/construct.mli | 1 + src/ir_def/freevars.ml | 1 - src/ir_def/ir.ml | 2 +- src/ir_def/ir_effect.ml | 1 - src/ir_interpreter/interpret_ir.ml | 10 +++------- src/ir_passes/async.ml | 2 -- src/ir_passes/await.ml | 4 ---- src/ir_passes/rename.ml | 1 - src/ir_passes/show.ml | 2 -- src/ir_passes/tailcall.ml | 1 - src/lowering/desugar.ml | 2 +- 15 files changed, 18 insertions(+), 28 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 95b7433faf6..18b12a1b66a 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -5862,6 +5862,9 @@ and compile_exp (env : E.t) ae exp = | OptPrim, [e] -> SR.Vanilla, Opt.inject env (compile_exp_vanilla env ae e) + | TagPrim l, [e] -> + SR.Vanilla, + Variant.inject env l (compile_exp_vanilla env ae e) (* Numeric conversions *) | NumConvPrim (t1, t2), [e] -> begin @@ -6214,9 +6217,6 @@ and compile_exp (env : E.t) ae exp = compile_exp_as env ae (StackRep.of_arity (E.get_return_arity env)) e ^^ FakeMultiVal.store env (Lib.List.make (E.get_return_arity env) I32Type) ^^ G.i Return - | TagE (l, e) -> - SR.Vanilla, - Variant.inject env l (compile_exp_vanilla env ae e) | ArrayE (m, t, es) -> SR.Vanilla, Arr.lit env (List.map (compile_exp_vanilla env ae) es) | CallE (e1, _, e2) -> diff --git a/src/ir_def/arrange_ir.ml b/src/ir_def/arrange_ir.ml index 8ee999c21f2..44624e57eba 100644 --- a/src/ir_def/arrange_ir.ml +++ b/src/ir_def/arrange_ir.ml @@ -32,7 +32,6 @@ let rec exp e = match e.it with | AsyncE e -> "AsyncE" $$ [exp e] | AwaitE e -> "AwaitE" $$ [exp e] | AssertE e -> "AssertE" $$ [exp e] - | TagE (i, e) -> "TagE" $$ [id i; exp e] | DeclareE (i, t, e1) -> "DeclareE" $$ [id i; exp e1] | DefineE (i, m, e1) -> "DefineE" $$ [id i; mut m; exp e1] | FuncE (x, s, c, tp, as_, ts, e) -> @@ -64,6 +63,7 @@ and prim = function | TupPrim -> Atom "TupPrim" | ProjPrim i -> "ProjPrim" $$ [Atom (string_of_int i)] | OptPrim -> Atom "OptPrim" + | TagPrim i -> "TagE" $$ [id i] | ShowPrim t -> "ShowPrim" $$ [typ t] | NumConvPrim (t1, t2) -> "NumConvPrim" $$ [prim_ty t1; prim_ty t2] | CastPrim (t1, t2) -> "CastPrim" $$ [typ t1; typ t2] diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 1f42e14b898..05acc599395 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -365,6 +365,8 @@ let rec check_exp env (exp:Ir.exp) : unit = tn <: t | OptPrim, [exp1] -> T.Opt (typ exp1) <: t + | TagPrim i, [exp1] -> + T.Variant [{T.lab = i; typ = typ exp1}] <: t | ShowPrim ot, [exp1] -> check env.flavor.has_show "show expression in non-show flavor"; check (Show.can_show ot) "show is not defined for operand type"; @@ -429,9 +431,6 @@ let rec check_exp env (exp:Ir.exp) : unit = error env exp.at "PrimE %s does not work with %d arguments" (Wasm.Sexpr.to_string 80 (Arrange_ir.prim p)) (List.length args); end - | TagE (i, exp1) -> - check_exp env exp1; - T.Variant [{T.lab = i; typ = typ exp1}] <: t | ActorDotE(exp1, n) | DotE (exp1, n) -> begin diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index 1a9c6ccaec9..f9176e9263c 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -151,6 +151,12 @@ let optE e = at = no_region; } +let tagE i e = + { it = PrimE (TagPrim i, [e]); + note = { note_typ = T.Variant [{T.lab = i; typ = typ e}]; note_eff = eff e }; + at = no_region; + } + let dec_eff dec = match dec.it with | TypD _ -> T.Triv | LetD (_,e) | VarD (_,e) -> eff e diff --git a/src/ir_def/construct.mli b/src/ir_def/construct.mli index 48d77771315..8309bc8da47 100644 --- a/src/ir_def/construct.mli +++ b/src/ir_def/construct.mli @@ -47,6 +47,7 @@ val ic_rejectE : exp -> exp val ic_callE : exp -> exp -> exp -> exp -> exp val projE : exp -> int -> exp val optE : exp -> exp +val tagE : id -> exp -> exp val blockE : dec list -> exp -> exp val textE : string -> exp val blobE : string -> exp diff --git a/src/ir_def/freevars.ml b/src/ir_def/freevars.ml index ffda1cbf3ff..456117c276a 100644 --- a/src/ir_def/freevars.ml +++ b/src/ir_def/freevars.ml @@ -88,7 +88,6 @@ let rec exp e : f = match e.it with | AsyncE e -> exp e | AwaitE e -> exp e | AssertE e -> exp e - | TagE (_, e) -> exp e | DeclareE (i, t, e) -> exp e // i | DefineE (i, m, e) -> id i ++ exp e | FuncE (x, s, c, tp, as_, t, e) -> under_lambda (exp e /// args as_) diff --git a/src/ir_def/ir.ml b/src/ir_def/ir.ml index 7e0e4850088..f6b732d5d9d 100644 --- a/src/ir_def/ir.ml +++ b/src/ir_def/ir.ml @@ -65,7 +65,6 @@ and exp' = | PrimE of (prim * exp list) (* primitive *) | VarE of id (* variable *) | LitE of lit (* literal *) - | TagE of id * exp (* variant injection *) | DotE of exp * Type.lab (* object projection *) | ActorDotE of exp * Type.lab (* actor field access *) | AssignE of lexp * exp (* assignment *) @@ -112,6 +111,7 @@ and prim = | TupPrim (* the tuple constructor *) | ProjPrim of int (* tuple projection *) | OptPrim (* option injection *) + | TagPrim of id (* variant injection *) | ShowPrim of Type.typ (* debug show *) | NumConvPrim of Type.prim * Type.prim | CastPrim of Type.typ * Type.typ (* representationally a noop *) diff --git a/src/ir_def/ir_effect.ml b/src/ir_def/ir_effect.ml index 98526ffc61a..2bc50191023 100644 --- a/src/ir_def/ir_effect.ml +++ b/src/ir_def/ir_effect.ml @@ -28,7 +28,6 @@ let rec infer_effect_exp (exp: exp) : T.eff = | VarE _ | LitE _ -> T.Triv - | TagE (_, exp1) | DotE (exp1, _) | ActorDotE (exp1, _) | AssertE exp1 diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index 4dd115868f7..d83346d947a 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -328,6 +328,8 @@ and interpret_exp_mut env exp (k : V.value V.cont) = interpret_exp env exp1 (fun v1 -> k (List.nth (V.as_tup v1) n)) | OptPrim, [exp1] -> interpret_exp env exp1 (fun v1 -> k (V.Opt v1)) + | TagPrim i, [exp1] -> + interpret_exp env exp1 (fun v1 -> k (V.Variant (i, v1))) | ShowPrim ot, [exp1] -> interpret_exp env exp1 (fun v -> if Show.can_show ot @@ -411,13 +413,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = trap exp.at "Unknown prim or wrong number of arguments (%d given):\n %s" (List.length es) (Wasm.Sexpr.to_string 80 (Arrange_ir.prim p)) end - | TagE (i, exp1) -> - interpret_exp env exp1 (fun v1 -> k (V.Variant (i, v1))) - | DotE (exp1, n) -> - interpret_exp env exp1 (fun v1 -> - let fs = V.as_obj v1 in - k (try find n fs with _ -> assert false) - ) + | DotE (exp1, n) | ActorDotE (exp1, n) -> interpret_exp env exp1 (fun v1 -> let fs = V.as_obj v1 in diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index 35ec7dc94ec..a591318f97e 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -227,8 +227,6 @@ let transform mode env prog = match exp' with | LitE _ -> exp' | VarE id -> exp' - | TagE (i, exp1) -> - TagE (i, t_exp exp1) | DotE (exp1, id) -> DotE (t_exp exp1, id) | ActorDotE (exp1, id) -> diff --git a/src/ir_passes/await.ml b/src/ir_passes/await.ml index cfb13d81dc9..774c0f006a6 100644 --- a/src/ir_passes/await.ml +++ b/src/ir_passes/await.ml @@ -65,8 +65,6 @@ and t_exp' context exp' = | LitE _ -> exp' | PrimE (p, exps) -> PrimE (p, List.map (t_exp context) exps) - | TagE (id, exp1) -> - TagE (id, t_exp context exp1) | DotE (exp1, id) -> DotE (t_exp context exp1, id) | ActorDotE (exp1, id) -> @@ -257,8 +255,6 @@ and c_exp' context exp k = assert false | PrimE (p, exps) -> nary context k (fun vs -> e (PrimE (p, vs))) exps - | TagE (i, exp1) -> - unary context k (fun v1 -> e (TagE (i, v1))) exp1 | ActorE _ -> assert false; (* ActorE fields cannot await *) | DotE (exp1, id) -> diff --git a/src/ir_passes/rename.ml b/src/ir_passes/rename.ml index 4704d3dc086..f92510204e8 100644 --- a/src/ir_passes/rename.ml +++ b/src/ir_passes/rename.ml @@ -55,7 +55,6 @@ and exp' rho e = match e with | AsyncE e -> AsyncE (exp rho e) | AwaitE e -> AwaitE (exp rho e) | AssertE e -> AssertE (exp rho e) - | TagE (i, e) -> TagE (i, exp rho e) | DeclareE (i, t, e) -> let i',rho' = id_bind rho i in DeclareE (i', t, exp rho' e) | DefineE (i, m, e) -> DefineE (id rho i, m, exp rho e) diff --git a/src/ir_passes/show.ml b/src/ir_passes/show.ml index 8490e9b5578..4d2052d8f5d 100644 --- a/src/ir_passes/show.ml +++ b/src/ir_passes/show.ml @@ -327,8 +327,6 @@ and t_exp' env = function let f = idE (show_name_for t') (show_fun_typ_for t') in CallE (f, [], t_exp env exp1) | PrimE (p, es) -> PrimE (p, t_exps env es) - | TagE (l, exp1) -> - TagE (l, t_exp env exp1) | DotE (exp1, id) -> DotE (t_exp env exp1, id) | ActorDotE (exp1, id) -> diff --git a/src/ir_passes/tailcall.ml b/src/ir_passes/tailcall.ml index 8393e33bb70..438723c9015 100644 --- a/src/ir_passes/tailcall.ml +++ b/src/ir_passes/tailcall.ml @@ -124,7 +124,6 @@ and exp' env e : exp' = match e.it with | AsyncE e -> AsyncE (exp { tail_pos = true; info = None } e) | AwaitE e -> AwaitE (exp env e) | AssertE e -> AssertE (exp env e) - | TagE (i, e) -> TagE (i, exp env e) | DeclareE (i, t, e) -> let env1 = bind env i None in DeclareE (i, t, tailexp env1 e) | DefineE (i, m, e) -> DefineE (i, m, exp env e) diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 090bc174df4..494ec1820e9 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -73,7 +73,7 @@ and exp' at note = function | S.OptE e -> (optE (exp e)).it | S.ObjE (s, es) -> obj at s None es note.I.note_typ - | S.TagE (c, e) -> I.TagE (c.it, exp e) + | S.TagE (c, e) -> (tagE c.it (exp e)).it | S.DotE (e, x) when T.is_array e.note.S.note_typ -> (array_dotE e.note.S.note_typ x.it (exp e)).it | S.DotE (e, x) when T.is_prim T.Blob e.note.S.note_typ -> From d701ed68ca5d0d9ddb880ce8e4da30c6505eb3c6 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 11 Dec 2019 15:05:22 +0100 Subject: [PATCH 0932/1176] Dito with (Actor)DotPrim --- src/codegen/compile.ml | 17 ++++++++------- src/ir_def/arrange_ir.ml | 6 ++--- src/ir_def/check_ir.ml | 35 +++++++++++++++--------------- src/ir_def/construct.ml | 4 ++-- src/ir_def/freevars.ml | 2 -- src/ir_def/ir.ml | 4 ++-- src/ir_def/ir_effect.ml | 2 -- src/ir_interpreter/interpret_ir.ml | 11 +++++----- src/ir_passes/async.ml | 4 ---- src/ir_passes/await.ml | 8 ------- src/ir_passes/rename.ml | 2 -- src/ir_passes/show.ml | 11 +--------- src/ir_passes/tailcall.ml | 2 -- src/lowering/desugar.ml | 4 ++-- 14 files changed, 41 insertions(+), 71 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 18b12a1b66a..7fb85998597 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -5814,14 +5814,6 @@ and compile_exp (env : E.t) ae exp = BigNum.to_word32 env ^^ Arr.idx env ^^ load_ptr - | DotE (e, name) -> - SR.Vanilla, - compile_exp_vanilla env ae e ^^ - Object.load_idx env e.note.note_typ name - | ActorDotE (e, name) -> - SR.Vanilla, - compile_exp_as env ae SR.Vanilla e ^^ - Dfinity.actor_public_field env name | PrimE (p, es) -> (* for more concise code when all arguments and result use the same sr *) @@ -5866,6 +5858,15 @@ and compile_exp (env : E.t) ae exp = SR.Vanilla, Variant.inject env l (compile_exp_vanilla env ae e) + | DotPrim name, [e] -> + SR.Vanilla, + compile_exp_vanilla env ae e ^^ + Object.load_idx env e.note.note_typ name + | ActorDotPrim name, [e] -> + SR.Vanilla, + compile_exp_vanilla env ae e ^^ + Dfinity.actor_public_field env name + (* Numeric conversions *) | NumConvPrim (t1, t2), [e] -> begin let open Type in diff --git a/src/ir_def/arrange_ir.ml b/src/ir_def/arrange_ir.ml index 44624e57eba..54ab3ff8ccf 100644 --- a/src/ir_def/arrange_ir.ml +++ b/src/ir_def/arrange_ir.ml @@ -16,8 +16,6 @@ let rec exp e = match e.it with | VarE i -> "VarE" $$ [id i] | LitE l -> "LitE" $$ [lit l] | PrimE (p, es) -> "PrimE" $$ [prim p] @ List.map exp es - | DotE (e, n) -> "DotE" $$ [exp e; Atom n] - | ActorDotE (e, n) -> "ActorDotE" $$ [exp e; Atom n] | AssignE (le1, e2) -> "AssignE" $$ [lexp le1; exp e2] | ArrayE (m, t, es) -> "ArrayE" $$ [mut m; typ t] @ List.map exp es | IdxE (e1, e2) -> "IdxE" $$ [exp e1; exp e2] @@ -40,7 +38,7 @@ let rec exp e = match e.it with "SelfCallE" $$ [typ (Type.seq ts); exp exp_f; exp exp_k; exp exp_r] | ActorE (i, ds, fs, t) -> "ActorE" $$ [id i] @ List.map dec ds @ fields fs @ [typ t] | NewObjE (s, fs, t) -> "NewObjE" $$ (Arrange_type.obj_sort s :: fields fs @ [typ t]) - | ThrowE e -> "ThrowE" $$ [exp e] + | ThrowE e -> "ThrowE" $$ [exp e] | TryE (e, cs) -> "TryE" $$ [exp e] @ List.map case cs and lexp le = match le.it with @@ -65,6 +63,8 @@ and prim = function | OptPrim -> Atom "OptPrim" | TagPrim i -> "TagE" $$ [id i] | ShowPrim t -> "ShowPrim" $$ [typ t] + | DotPrim n -> "DotPrim" $$ [Atom n] + | ActorDotPrim n -> "ActorDotPrim" $$ [Atom n] | NumConvPrim (t1, t2) -> "NumConvPrim" $$ [prim_ty t1; prim_ty t2] | CastPrim (t1, t2) -> "CastPrim" $$ [typ t1; typ t2] | ActorOfIdBlob t -> "ActorOfIdBlob" $$ [typ t] diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 05acc599395..55952f7a3a0 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -367,6 +367,23 @@ let rec check_exp env (exp:Ir.exp) : unit = T.Opt (typ exp1) <: t | TagPrim i, [exp1] -> T.Variant [{T.lab = i; typ = typ exp1}] <: t + | ActorDotPrim n, [exp1] + | DotPrim n, [exp1] -> + begin + let t1 = typ exp1 in + let sort, tfs = + try T.as_obj_sub [n] t1 with Invalid_argument _ -> + error env exp1.at "expected object type, but expression produces type\n %s" + (T.string_of_typ_expand t1) + in + check (match p with + | ActorDotPrim _ -> sort = T.Actor + | DotPrim _ -> sort <> T.Actor + | _ -> false) "sort mismatch"; + try T.lookup_val_field n tfs <~ t with Invalid_argument _ -> + error env exp1.at "field name %s does not exist in type\n %s" + n (T.string_of_typ_expand t1) + end | ShowPrim ot, [exp1] -> check env.flavor.has_show "show expression in non-show flavor"; check (Show.can_show ot) "show is not defined for operand type"; @@ -431,24 +448,6 @@ let rec check_exp env (exp:Ir.exp) : unit = error env exp.at "PrimE %s does not work with %d arguments" (Wasm.Sexpr.to_string 80 (Arrange_ir.prim p)) (List.length args); end - | ActorDotE(exp1, n) - | DotE (exp1, n) -> - begin - check_exp env exp1; - let t1 = typ exp1 in - let sort, tfs = - try T.as_obj_sub [n] t1 with Invalid_argument _ -> - error env exp1.at "expected object type, but expression produces type\n %s" - (T.string_of_typ_expand t1) - in - check (match exp.it with - | ActorDotE _ -> sort = T.Actor - | DotE _ -> sort <> T.Actor - | _ -> false) "sort mismatch"; - try T.lookup_val_field n tfs <~ t with Invalid_argument _ -> - error env exp1.at "field name %s does not exist in type\n %s" - n (T.string_of_typ_expand t1) - end | AssignE (lexp1, exp2) -> check_lexp env lexp1; check_exp env exp2; diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index f9176e9263c..7a74b34a79b 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -224,7 +224,7 @@ let ifE exp1 exp2 exp3 typ = } let dotE exp name typ = - { it = DotE (exp, name); + { it = PrimE (DotPrim name, [exp]); at = no_region; note = { note_typ = typ; @@ -316,7 +316,7 @@ let immuteE e = in the constructor DSL *) let lexp_of_exp' = function | VarE i -> VarLE i - | DotE (e1,n) -> DotLE (e1, n) + | PrimE (DotPrim n, [e1]) -> DotLE (e1, n) | IdxE (e1,e2) -> IdxLE (e1, e2) | _ -> failwith "Impossible: lexp_of_exp" diff --git a/src/ir_def/freevars.ml b/src/ir_def/freevars.ml index 456117c276a..eb3b5146ee5 100644 --- a/src/ir_def/freevars.ml +++ b/src/ir_def/freevars.ml @@ -72,8 +72,6 @@ let rec exp e : f = match e.it with | VarE i -> id i | LitE l -> M.empty | PrimE (_, es) -> exps es - | DotE (e, i) -> exp e - | ActorDotE (e, i) -> exp e | AssignE (e1, e2) -> lexp e1 ++ exp e2 | ArrayE (m, t, es) -> exps es | IdxE (e1, e2) -> exps [e1; e2] diff --git a/src/ir_def/ir.ml b/src/ir_def/ir.ml index f6b732d5d9d..8cbe22eab19 100644 --- a/src/ir_def/ir.ml +++ b/src/ir_def/ir.ml @@ -65,8 +65,6 @@ and exp' = | PrimE of (prim * exp list) (* primitive *) | VarE of id (* variable *) | LitE of lit (* literal *) - | DotE of exp * Type.lab (* object projection *) - | ActorDotE of exp * Type.lab (* actor field access *) | AssignE of lexp * exp (* assignment *) | ArrayE of mut * Type.typ * exp list (* array *) | IdxE of exp * exp (* array indexing *) @@ -112,6 +110,8 @@ and prim = | ProjPrim of int (* tuple projection *) | OptPrim (* option injection *) | TagPrim of id (* variant injection *) + | DotPrim of Type.lab (* object projection *) + | ActorDotPrim of Type.lab (* actor field access *) | ShowPrim of Type.typ (* debug show *) | NumConvPrim of Type.prim * Type.prim | CastPrim of Type.typ * Type.typ (* representationally a noop *) diff --git a/src/ir_def/ir_effect.ml b/src/ir_def/ir_effect.ml index 2bc50191023..58cd0f39aef 100644 --- a/src/ir_def/ir_effect.ml +++ b/src/ir_def/ir_effect.ml @@ -28,8 +28,6 @@ let rec infer_effect_exp (exp: exp) : T.eff = | VarE _ | LitE _ -> T.Triv - | DotE (exp1, _) - | ActorDotE (exp1, _) | AssertE exp1 | LabelE (_, _, exp1) | BreakE (_, exp1) diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index d83346d947a..adb3297a092 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -330,6 +330,11 @@ and interpret_exp_mut env exp (k : V.value V.cont) = interpret_exp env exp1 (fun v1 -> k (V.Opt v1)) | TagPrim i, [exp1] -> interpret_exp env exp1 (fun v1 -> k (V.Variant (i, v1))) + | (DotPrim n|ActorDotPrim n), [exp1] -> + interpret_exp env exp1 (fun v1 -> + let fs = V.as_obj v1 in + k (try find n fs with _ -> assert false) + ) | ShowPrim ot, [exp1] -> interpret_exp env exp1 (fun v -> if Show.can_show ot @@ -413,12 +418,6 @@ and interpret_exp_mut env exp (k : V.value V.cont) = trap exp.at "Unknown prim or wrong number of arguments (%d given):\n %s" (List.length es) (Wasm.Sexpr.to_string 80 (Arrange_ir.prim p)) end - | DotE (exp1, n) - | ActorDotE (exp1, n) -> - interpret_exp env exp1 (fun v1 -> - let fs = V.as_obj v1 in - k (try find n fs with _ -> assert false) - ) | AssignE (lexp1, exp2) -> interpret_lexp env lexp1 (fun v1 -> interpret_exp env exp2 (fun v2 -> diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index a591318f97e..60ae2836ffe 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -227,10 +227,6 @@ let transform mode env prog = match exp' with | LitE _ -> exp' | VarE id -> exp' - | DotE (exp1, id) -> - DotE (t_exp exp1, id) - | ActorDotE (exp1, id) -> - ActorDotE (t_exp exp1, id) | AssignE (exp1, exp2) -> AssignE (t_lexp exp1, t_exp exp2) | ArrayE (mut, t, exps) -> diff --git a/src/ir_passes/await.ml b/src/ir_passes/await.ml index 774c0f006a6..833c8fe78ef 100644 --- a/src/ir_passes/await.ml +++ b/src/ir_passes/await.ml @@ -65,10 +65,6 @@ and t_exp' context exp' = | LitE _ -> exp' | PrimE (p, exps) -> PrimE (p, List.map (t_exp context) exps) - | DotE (exp1, id) -> - DotE (t_exp context exp1, id) - | ActorDotE (exp1, id) -> - ActorDotE (t_exp context exp1, id) | AssignE (exp1, exp2) -> AssignE (t_lexp context exp1, t_exp context exp2) | ArrayE (mut, typ, exps) -> @@ -257,10 +253,6 @@ and c_exp' context exp k = nary context k (fun vs -> e (PrimE (p, vs))) exps | ActorE _ -> assert false; (* ActorE fields cannot await *) - | DotE (exp1, id) -> - unary context k (fun v1 -> e (DotE (v1, id))) exp1 - | ActorDotE (exp1, id) -> - unary context k (fun v1 -> e (DotE (v1, id))) exp1 | AssignE (exp1, exp2) -> c_assign context k e exp1 exp2 | ArrayE (mut, typ, exps) -> diff --git a/src/ir_passes/rename.ml b/src/ir_passes/rename.ml index f92510204e8..79f6965af4b 100644 --- a/src/ir_passes/rename.ml +++ b/src/ir_passes/rename.ml @@ -37,8 +37,6 @@ and exp' rho e = match e with | ActorE (i, ds, fs, t)-> let i',rho' = id_bind rho i in let ds', rho'' = decs rho' ds in ActorE (i', ds', fields rho'' fs, t) - | DotE (e, i) -> DotE (exp rho e, i) - | ActorDotE (e, i) -> ActorDotE (exp rho e, i) | AssignE (e1, e2) -> AssignE (lexp rho e1, exp rho e2) | ArrayE (m, t, es) -> ArrayE (m, t, exps rho es) | IdxE (e1, e2) -> IdxE (exp rho e1, exp rho e2) diff --git a/src/ir_passes/show.ml b/src/ir_passes/show.ml index 4d2052d8f5d..43d457886f6 100644 --- a/src/ir_passes/show.ml +++ b/src/ir_passes/show.ml @@ -261,12 +261,7 @@ let show_for : T.typ -> Ir.dec * T.typ list = fun t -> let t' = T.as_immut (T.normalize f.Type.typ) in catE (textE (f.Type.lab ^ " = ")) - (invoke_generated_show t' - { it = DotE (argE t, f.Type.lab) - ; at = no_region - ; note = { note_typ = t'; note_eff = T.Triv } - } - ) + (invoke_generated_show t' (dotE (argE t) f.Type.lab t')) ) fs ) ) @@ -327,10 +322,6 @@ and t_exp' env = function let f = idE (show_name_for t') (show_fun_typ_for t') in CallE (f, [], t_exp env exp1) | PrimE (p, es) -> PrimE (p, t_exps env es) - | DotE (exp1, id) -> - DotE (t_exp env exp1, id) - | ActorDotE (exp1, id) -> - ActorDotE (t_exp env exp1, id) | AssignE (lexp1, exp2) -> AssignE (t_lexp env lexp1, t_exp env exp2) | ArrayE (mut, t, exps) -> diff --git a/src/ir_passes/tailcall.ml b/src/ir_passes/tailcall.ml index 438723c9015..b25938824f1 100644 --- a/src/ir_passes/tailcall.ml +++ b/src/ir_passes/tailcall.ml @@ -94,8 +94,6 @@ and assignEs vars exp : dec list = and exp' env e : exp' = match e.it with | VarE _ | LitE _ -> e.it | PrimE (p, es) -> PrimE (p, List.map (exp env) es) - | DotE (e, sn) -> DotE (exp env e, sn) - | ActorDotE (e, sn) -> ActorDotE (exp env e, sn) | AssignE (e1, e2) -> AssignE (lexp env e1, exp env e2) | ArrayE (m,t,es) -> ArrayE (m,t,(exps env es)) | IdxE (e1, e2) -> IdxE (exp env e1, exp env e2) diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 494ec1820e9..abdd046799c 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -82,8 +82,8 @@ and exp' at note = function (text_dotE x.it (exp e)).it | S.DotE (e, x) -> begin match T.as_obj_sub [x.it] e.note.S.note_typ with - | T.Actor, _ -> I.ActorDotE (exp e, x.it) - | _ -> I.DotE (exp e, x.it) + | T.Actor, _ -> I.PrimE (I.ActorDotPrim x.it, [exp e]) + | _ -> I.PrimE (I.DotPrim x.it, [exp e]) end | S.AssignE (e1, e2) -> I.AssignE (lexp e1, exp e2) | S.ArrayE (m, es) -> From ef39e34d0cfb1c07ec108fa1405a980e92ca5bd8 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 19 Dec 2019 17:35:12 +0100 Subject: [PATCH 0933/1176] Dito with IdxPrim --- src/codegen/compile.ml | 15 ++++++++------- src/ir_def/arrange_ir.ml | 4 ++-- src/ir_def/check_ir.ml | 20 +++++++++----------- src/ir_def/construct.ml | 2 +- src/ir_def/freevars.ml | 1 - src/ir_def/ir.ml | 2 +- src/ir_def/ir_effect.ml | 1 - src/ir_interpreter/interpret_ir.ml | 14 +++++++------- src/ir_passes/async.ml | 2 -- src/ir_passes/await.ml | 4 ---- src/ir_passes/rename.ml | 1 - src/ir_passes/show.ml | 2 -- src/ir_passes/tailcall.ml | 1 - src/lowering/desugar.ml | 2 +- 14 files changed, 29 insertions(+), 42 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 7fb85998597..fac8cb66b09 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -5807,13 +5807,6 @@ let rec compile_lexp (env : E.t) ae lexp = and compile_exp (env : E.t) ae exp = (fun (sr,code) -> (sr, G.with_region exp.at code)) @@ match exp.it with - | IdxE (e1, e2) -> - SR.Vanilla, - compile_exp_vanilla env ae e1 ^^ (* offset to array *) - compile_exp_vanilla env ae e2 ^^ (* idx *) - BigNum.to_word32 env ^^ - Arr.idx env ^^ - load_ptr | PrimE (p, es) -> (* for more concise code when all arguments and result use the same sr *) @@ -5867,6 +5860,14 @@ and compile_exp (env : E.t) ae exp = compile_exp_vanilla env ae e ^^ Dfinity.actor_public_field env name + | IdxPrim, [e1; e2] -> + SR.Vanilla, + compile_exp_vanilla env ae e1 ^^ (* offset to array *) + compile_exp_vanilla env ae e2 ^^ (* idx *) + BigNum.to_word32 env ^^ + Arr.idx env ^^ + load_ptr + (* Numeric conversions *) | NumConvPrim (t1, t2), [e] -> begin let open Type in diff --git a/src/ir_def/arrange_ir.ml b/src/ir_def/arrange_ir.ml index 54ab3ff8ccf..57c8e942529 100644 --- a/src/ir_def/arrange_ir.ml +++ b/src/ir_def/arrange_ir.ml @@ -18,7 +18,6 @@ let rec exp e = match e.it with | PrimE (p, es) -> "PrimE" $$ [prim p] @ List.map exp es | AssignE (le1, e2) -> "AssignE" $$ [lexp le1; exp e2] | ArrayE (m, t, es) -> "ArrayE" $$ [mut m; typ t] @ List.map exp es - | IdxE (e1, e2) -> "IdxE" $$ [exp e1; exp e2] | CallE (e1, ts, e2) -> "CallE" $$ [exp e1] @ List.map typ ts @ [exp e2] | BlockE (ds, e1) -> "BlockE" $$ List.map dec ds @ [exp e1] | IfE (e1, e2, e3) -> "IfE" $$ [exp e1; exp e2; exp e3] @@ -62,9 +61,10 @@ and prim = function | ProjPrim i -> "ProjPrim" $$ [Atom (string_of_int i)] | OptPrim -> Atom "OptPrim" | TagPrim i -> "TagE" $$ [id i] - | ShowPrim t -> "ShowPrim" $$ [typ t] | DotPrim n -> "DotPrim" $$ [Atom n] | ActorDotPrim n -> "ActorDotPrim" $$ [Atom n] + | IdxPrim -> Atom "IdxPrim" + | ShowPrim t -> "ShowPrim" $$ [typ t] | NumConvPrim (t1, t2) -> "NumConvPrim" $$ [prim_ty t1; prim_ty t2] | CastPrim (t1, t2) -> "CastPrim" $$ [typ t1; typ t2] | ActorOfIdBlob t -> "ActorOfIdBlob" $$ [typ t] diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 55952f7a3a0..12691c5c16e 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -384,6 +384,15 @@ let rec check_exp env (exp:Ir.exp) : unit = error env exp1.at "field name %s does not exist in type\n %s" n (T.string_of_typ_expand t1) end + | IdxPrim, [exp1; exp2] -> + let t1 = T.promote (typ exp1) in + let t2 = try T.as_array_sub t1 with + | Invalid_argument _ -> + error env exp1.at "expected array type, but expression produces type\n %s" + (T.string_of_typ_expand t1) + in + typ exp2 <: T.nat; + t2 <~ t | ShowPrim ot, [exp1] -> check env.flavor.has_show "show expression in non-show flavor"; check (Show.can_show ot) "show is not defined for operand type"; @@ -461,17 +470,6 @@ let rec check_exp env (exp:Ir.exp) : unit = List.iter (fun e -> typ e <: t0) exps; let t1 = T.Array (match mut with Const -> t0 | Var -> T.Mut t0) in t1 <: t - | IdxE (exp1, exp2) -> - check_exp env exp1; - check_exp env exp2; - let t1 = T.promote (typ exp1) in - let t2 = try T.as_array_sub t1 with - | Invalid_argument _ -> - error env exp1.at "expected array type, but expression produces type\n %s" - (T.string_of_typ_expand t1) - in - typ exp2 <: T.nat; - t2 <~ t | CallE (exp1, insts, exp2) -> check_exp env exp1; check_exp env exp2; diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index 7a74b34a79b..51e1704156b 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -317,7 +317,7 @@ in the constructor DSL *) let lexp_of_exp' = function | VarE i -> VarLE i | PrimE (DotPrim n, [e1]) -> DotLE (e1, n) - | IdxE (e1,e2) -> IdxLE (e1, e2) + | PrimE (IdxPrim, [e1; e2]) -> IdxLE (e1, e2) | _ -> failwith "Impossible: lexp_of_exp" let lexp_of_exp (e:exp) = { e with it = lexp_of_exp' e.it; note = typ e } diff --git a/src/ir_def/freevars.ml b/src/ir_def/freevars.ml index eb3b5146ee5..2317911f2b9 100644 --- a/src/ir_def/freevars.ml +++ b/src/ir_def/freevars.ml @@ -74,7 +74,6 @@ let rec exp e : f = match e.it with | PrimE (_, es) -> exps es | AssignE (e1, e2) -> lexp e1 ++ exp e2 | ArrayE (m, t, es) -> exps es - | IdxE (e1, e2) -> exps [e1; e2] | CallE (e1, ts, e2) -> exps [e1; e2] | BlockE (ds, e1) -> close (decs ds +++ exp e1) | IfE (e1, e2, e3) -> exps [e1; e2; e3] diff --git a/src/ir_def/ir.ml b/src/ir_def/ir.ml index 8cbe22eab19..88b44caa77d 100644 --- a/src/ir_def/ir.ml +++ b/src/ir_def/ir.ml @@ -67,7 +67,6 @@ and exp' = | LitE of lit (* literal *) | AssignE of lexp * exp (* assignment *) | ArrayE of mut * Type.typ * exp list (* array *) - | IdxE of exp * exp (* array indexing *) | CallE of exp * Type.typ list * exp (* function call *) | BlockE of (dec list * exp) (* block *) | IfE of exp * exp * exp (* conditional *) @@ -112,6 +111,7 @@ and prim = | TagPrim of id (* variant injection *) | DotPrim of Type.lab (* object projection *) | ActorDotPrim of Type.lab (* actor field access *) + | IdxPrim (* array indexing *) | ShowPrim of Type.typ (* debug show *) | NumConvPrim of Type.prim * Type.prim | CastPrim of Type.typ * Type.typ (* representationally a noop *) diff --git a/src/ir_def/ir_effect.ml b/src/ir_def/ir_effect.ml index 58cd0f39aef..ade516f8122 100644 --- a/src/ir_def/ir_effect.ml +++ b/src/ir_def/ir_effect.ml @@ -35,7 +35,6 @@ let rec infer_effect_exp (exp: exp) : T.eff = | LoopE exp1 | AssignE (_, exp1) -> effect_exp exp1 - | IdxE (exp1, exp2) | CallE (exp1, _, exp2) -> let t1 = effect_exp exp1 in let t2 = effect_exp exp2 in diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index adb3297a092..861cdb8e133 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -335,6 +335,13 @@ and interpret_exp_mut env exp (k : V.value V.cont) = let fs = V.as_obj v1 in k (try find n fs with _ -> assert false) ) + | IdxPrim, [exp1; exp2] -> + interpret_exp env exp1 (fun v1 -> + interpret_exp env exp2 (fun v2 -> + k (try (V.as_array v1).(V.Int.to_int (V.as_int v2)) + with Invalid_argument s -> trap exp.at "%s" s) + ) + ) | ShowPrim ot, [exp1] -> interpret_exp env exp1 (fun v -> if Show.can_show ot @@ -432,13 +439,6 @@ and interpret_exp_mut env exp (k : V.value V.cont) = | Const -> vs in k (V.Array (Array.of_list vs')) ) - | IdxE (exp1, exp2) -> - interpret_exp env exp1 (fun v1 -> - interpret_exp env exp2 (fun v2 -> - k (try (V.as_array v1).(V.Int.to_int (V.as_int v2)) - with Invalid_argument s -> trap exp.at "%s" s) - ) - ) | CallE (exp1, typs, exp2) -> interpret_exp env exp1 (fun v1 -> interpret_exp env exp2 (fun v2 -> diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index 60ae2836ffe..5abffbabc33 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -231,8 +231,6 @@ let transform mode env prog = AssignE (t_lexp exp1, t_exp exp2) | ArrayE (mut, t, exps) -> ArrayE (mut, t_typ t, List.map t_exp exps) - | IdxE (exp1, exp2) -> - IdxE (t_exp exp1, t_exp exp2) | PrimE (CPSAwait, [a;kr]) -> ((t_exp a) -*- (t_exp kr)).it | PrimE (CPSAsync, [exp1]) -> diff --git a/src/ir_passes/await.ml b/src/ir_passes/await.ml index 833c8fe78ef..4c2335682a1 100644 --- a/src/ir_passes/await.ml +++ b/src/ir_passes/await.ml @@ -69,8 +69,6 @@ and t_exp' context exp' = AssignE (t_lexp context exp1, t_exp context exp2) | ArrayE (mut, typ, exps) -> ArrayE (mut, typ, List.map (t_exp context) exps) - | IdxE (exp1, exp2) -> - IdxE (t_exp context exp1, t_exp context exp2) | CallE (exp1, typs, exp2) -> CallE (t_exp context exp1, typs, t_exp context exp2) | BlockE b -> @@ -257,8 +255,6 @@ and c_exp' context exp k = c_assign context k e exp1 exp2 | ArrayE (mut, typ, exps) -> nary context k (fun vs -> e (ArrayE (mut, typ, vs))) exps - | IdxE (exp1, exp2) -> - binary context k (fun v1 v2 -> e (IdxE (v1, v2))) exp1 exp2 | CallE (exp1, typs, exp2) -> binary context k (fun v1 v2 -> e (CallE (v1, typs, v2))) exp1 exp2 | BlockE (decs, exp) -> diff --git a/src/ir_passes/rename.ml b/src/ir_passes/rename.ml index 79f6965af4b..a38db7dbe64 100644 --- a/src/ir_passes/rename.ml +++ b/src/ir_passes/rename.ml @@ -39,7 +39,6 @@ and exp' rho e = match e with in ActorE (i', ds', fields rho'' fs, t) | AssignE (e1, e2) -> AssignE (lexp rho e1, exp rho e2) | ArrayE (m, t, es) -> ArrayE (m, t, exps rho es) - | IdxE (e1, e2) -> IdxE (exp rho e1, exp rho e2) | CallE (e1, ts, e2) -> CallE (exp rho e1, ts, exp rho e2) | BlockE (ds, e1) -> let ds', rho' = decs rho ds in BlockE (ds', exp rho' e1) diff --git a/src/ir_passes/show.ml b/src/ir_passes/show.ml index 43d457886f6..1c0faa811a2 100644 --- a/src/ir_passes/show.ml +++ b/src/ir_passes/show.ml @@ -326,8 +326,6 @@ and t_exp' env = function AssignE (t_lexp env lexp1, t_exp env exp2) | ArrayE (mut, t, exps) -> ArrayE (mut, t, t_exps env exps) - | IdxE (exp1, exp2) -> - IdxE (t_exp env exp1, t_exp env exp2) | FuncE (s, c, id, typbinds, pat, typT, exp) -> FuncE (s, c, id, typbinds, pat, typT, t_exp env exp) | CallE (exp1, typs, exp2) -> diff --git a/src/ir_passes/tailcall.ml b/src/ir_passes/tailcall.ml index b25938824f1..0ef7f48b8a8 100644 --- a/src/ir_passes/tailcall.ml +++ b/src/ir_passes/tailcall.ml @@ -96,7 +96,6 @@ and exp' env e : exp' = match e.it with | PrimE (p, es) -> PrimE (p, List.map (exp env) es) | AssignE (e1, e2) -> AssignE (lexp env e1, exp env e2) | ArrayE (m,t,es) -> ArrayE (m,t,(exps env es)) - | IdxE (e1, e2) -> IdxE (exp env e1, exp env e2) | CallE (e1, insts, e2) -> begin match e1.it, env with diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index abdd046799c..c469e8a3c9a 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -89,7 +89,7 @@ and exp' at note = function | S.ArrayE (m, es) -> let t = T.as_array note.I.note_typ in I.ArrayE (mut m, T.as_immut t, exps es) - | S.IdxE (e1, e2) -> I.IdxE (exp e1, exp e2) + | S.IdxE (e1, e2) -> I.PrimE (I.IdxPrim, [exp e1; exp e2]) | S.FuncE (name, sp, tbs, p, _t_opt, e) -> let s, po = match sp.it with | T.Local -> (T.Local, None) From 396da01b02d4d4f6a801e59de99e6f8583536578 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 19 Dec 2019 17:40:38 +0100 Subject: [PATCH 0934/1176] Dito with ArrayPrim --- src/codegen/compile.ml | 5 +++-- src/ir_def/arrange_ir.ml | 2 +- src/ir_def/check_ir.ml | 9 ++++----- src/ir_def/freevars.ml | 1 - src/ir_def/ir.ml | 2 +- src/ir_def/ir_effect.ml | 3 +-- src/ir_interpreter/interpret_ir.ml | 16 ++++++++-------- src/ir_passes/async.ml | 3 +-- src/ir_passes/await.ml | 4 ---- src/ir_passes/rename.ml | 1 - src/ir_passes/show.ml | 2 -- src/ir_passes/tailcall.ml | 3 --- src/lowering/desugar.ml | 2 +- 13 files changed, 20 insertions(+), 33 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index fac8cb66b09..c4a170500f7 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -5860,6 +5860,9 @@ and compile_exp (env : E.t) ae exp = compile_exp_vanilla env ae e ^^ Dfinity.actor_public_field env name + | ArrayPrim (m, t), es -> + SR.Vanilla, + Arr.lit env (List.map (compile_exp_vanilla env ae) es) | IdxPrim, [e1; e2] -> SR.Vanilla, compile_exp_vanilla env ae e1 ^^ (* offset to array *) @@ -6219,8 +6222,6 @@ and compile_exp (env : E.t) ae exp = compile_exp_as env ae (StackRep.of_arity (E.get_return_arity env)) e ^^ FakeMultiVal.store env (Lib.List.make (E.get_return_arity env) I32Type) ^^ G.i Return - | ArrayE (m, t, es) -> - SR.Vanilla, Arr.lit env (List.map (compile_exp_vanilla env ae) es) | CallE (e1, _, e2) -> let sort, control, _, arg_tys, ret_tys = Type.as_func e1.note.note_typ in let n_args = List.length arg_tys in diff --git a/src/ir_def/arrange_ir.ml b/src/ir_def/arrange_ir.ml index 57c8e942529..f120280f353 100644 --- a/src/ir_def/arrange_ir.ml +++ b/src/ir_def/arrange_ir.ml @@ -17,7 +17,6 @@ let rec exp e = match e.it with | LitE l -> "LitE" $$ [lit l] | PrimE (p, es) -> "PrimE" $$ [prim p] @ List.map exp es | AssignE (le1, e2) -> "AssignE" $$ [lexp le1; exp e2] - | ArrayE (m, t, es) -> "ArrayE" $$ [mut m; typ t] @ List.map exp es | CallE (e1, ts, e2) -> "CallE" $$ [exp e1] @ List.map typ ts @ [exp e2] | BlockE (ds, e1) -> "BlockE" $$ List.map dec ds @ [exp e1] | IfE (e1, e2, e3) -> "IfE" $$ [exp e1; exp e2; exp e3] @@ -63,6 +62,7 @@ and prim = function | TagPrim i -> "TagE" $$ [id i] | DotPrim n -> "DotPrim" $$ [Atom n] | ActorDotPrim n -> "ActorDotPrim" $$ [Atom n] + | ArrayPrim (m, t) -> "ArrayPrim" $$ [mut m; typ t] | IdxPrim -> Atom "IdxPrim" | ShowPrim t -> "ShowPrim" $$ [typ t] | NumConvPrim (t1, t2) -> "NumConvPrim" $$ [prim_ty t1; prim_ty t2] diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 12691c5c16e..3a6b0363884 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -384,6 +384,10 @@ let rec check_exp env (exp:Ir.exp) : unit = error env exp1.at "field name %s does not exist in type\n %s" n (T.string_of_typ_expand t1) end + | ArrayPrim (mut, t0), exps -> + List.iter (fun e -> typ e <: t0) exps; + let t1 = T.Array (match mut with Const -> t0 | Var -> T.Mut t0) in + t1 <: t | IdxPrim, [exp1; exp2] -> let t1 = T.promote (typ exp1) in let t2 = try T.as_array_sub t1 with @@ -465,11 +469,6 @@ let rec check_exp env (exp:Ir.exp) : unit = in typ exp2 <: t2; T.unit <: t - | ArrayE (mut, t0, exps) -> - List.iter (check_exp env) exps; - List.iter (fun e -> typ e <: t0) exps; - let t1 = T.Array (match mut with Const -> t0 | Var -> T.Mut t0) in - t1 <: t | CallE (exp1, insts, exp2) -> check_exp env exp1; check_exp env exp2; diff --git a/src/ir_def/freevars.ml b/src/ir_def/freevars.ml index 2317911f2b9..2b63101b812 100644 --- a/src/ir_def/freevars.ml +++ b/src/ir_def/freevars.ml @@ -73,7 +73,6 @@ let rec exp e : f = match e.it with | LitE l -> M.empty | PrimE (_, es) -> exps es | AssignE (e1, e2) -> lexp e1 ++ exp e2 - | ArrayE (m, t, es) -> exps es | CallE (e1, ts, e2) -> exps [e1; e2] | BlockE (ds, e1) -> close (decs ds +++ exp e1) | IfE (e1, e2, e3) -> exps [e1; e2; e3] diff --git a/src/ir_def/ir.ml b/src/ir_def/ir.ml index 88b44caa77d..25ba10791b9 100644 --- a/src/ir_def/ir.ml +++ b/src/ir_def/ir.ml @@ -66,7 +66,6 @@ and exp' = | VarE of id (* variable *) | LitE of lit (* literal *) | AssignE of lexp * exp (* assignment *) - | ArrayE of mut * Type.typ * exp list (* array *) | CallE of exp * Type.typ list * exp (* function call *) | BlockE of (dec list * exp) (* block *) | IfE of exp * exp * exp (* conditional *) @@ -111,6 +110,7 @@ and prim = | TagPrim of id (* variant injection *) | DotPrim of Type.lab (* object projection *) | ActorDotPrim of Type.lab (* actor field access *) + | ArrayPrim of mut * Type.typ (* array constructor *) | IdxPrim (* array indexing *) | ShowPrim of Type.typ (* debug show *) | NumConvPrim of Type.prim * Type.prim diff --git a/src/ir_def/ir_effect.ml b/src/ir_def/ir_effect.ml index ade516f8122..3a37ab68f13 100644 --- a/src/ir_def/ir_effect.ml +++ b/src/ir_def/ir_effect.ml @@ -39,8 +39,7 @@ let rec infer_effect_exp (exp: exp) : T.eff = let t1 = effect_exp exp1 in let t2 = effect_exp exp2 in max_eff t1 t2 - | PrimE (_, exps) - | ArrayE (_, _, exps) -> + | PrimE (_, exps) -> let es = List.map effect_exp exps in List.fold_left max_eff T.Triv es | BlockE (ds, exp) -> diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index 861cdb8e133..499da4b2586 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -335,6 +335,14 @@ and interpret_exp_mut env exp (k : V.value V.cont) = let fs = V.as_obj v1 in k (try find n fs with _ -> assert false) ) + | ArrayPrim (mut, _), exps -> + interpret_exps env exps [] (fun vs -> + let vs' = + match mut with + | Var -> List.map (fun v -> V.Mut (ref v)) vs + | Const -> vs + in k (V.Array (Array.of_list vs')) + ) | IdxPrim, [exp1; exp2] -> interpret_exp env exp1 (fun v1 -> interpret_exp env exp2 (fun v2 -> @@ -431,14 +439,6 @@ and interpret_exp_mut env exp (k : V.value V.cont) = v1 := v2; k V.unit ) ) - | ArrayE (mut, _, exps) -> - interpret_exps env exps [] (fun vs -> - let vs' = - match mut with - | Var -> List.map (fun v -> V.Mut (ref v)) vs - | Const -> vs - in k (V.Array (Array.of_list vs')) - ) | CallE (exp1, typs, exp2) -> interpret_exp env exp1 (fun v1 -> interpret_exp env exp2 (fun v2 -> diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index 5abffbabc33..5283304f038 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -205,6 +205,7 @@ let transform mode env prog = | UnPrim (ot, op) -> UnPrim (t_typ ot, op) | BinPrim (ot, op) -> BinPrim (t_typ ot, op) | RelPrim (ot, op) -> RelPrim (t_typ ot, op) + | ArrayPrim (m, t) -> ArrayPrim (m, t_typ t) | ShowPrim ot -> ShowPrim (t_typ ot) | NumConvPrim (t1,t2) -> NumConvPrim (t1,t2) | CastPrim (t1,t2) -> CastPrim (t_typ t1,t_typ t2) @@ -229,8 +230,6 @@ let transform mode env prog = | VarE id -> exp' | AssignE (exp1, exp2) -> AssignE (t_lexp exp1, t_exp exp2) - | ArrayE (mut, t, exps) -> - ArrayE (mut, t_typ t, List.map t_exp exps) | PrimE (CPSAwait, [a;kr]) -> ((t_exp a) -*- (t_exp kr)).it | PrimE (CPSAsync, [exp1]) -> diff --git a/src/ir_passes/await.ml b/src/ir_passes/await.ml index 4c2335682a1..fd36fd7a3e3 100644 --- a/src/ir_passes/await.ml +++ b/src/ir_passes/await.ml @@ -67,8 +67,6 @@ and t_exp' context exp' = PrimE (p, List.map (t_exp context) exps) | AssignE (exp1, exp2) -> AssignE (t_lexp context exp1, t_exp context exp2) - | ArrayE (mut, typ, exps) -> - ArrayE (mut, typ, List.map (t_exp context) exps) | CallE (exp1, typs, exp2) -> CallE (t_exp context exp1, typs, t_exp context exp2) | BlockE b -> @@ -253,8 +251,6 @@ and c_exp' context exp k = assert false; (* ActorE fields cannot await *) | AssignE (exp1, exp2) -> c_assign context k e exp1 exp2 - | ArrayE (mut, typ, exps) -> - nary context k (fun vs -> e (ArrayE (mut, typ, vs))) exps | CallE (exp1, typs, exp2) -> binary context k (fun v1 v2 -> e (CallE (v1, typs, v2))) exp1 exp2 | BlockE (decs, exp) -> diff --git a/src/ir_passes/rename.ml b/src/ir_passes/rename.ml index a38db7dbe64..328848858c8 100644 --- a/src/ir_passes/rename.ml +++ b/src/ir_passes/rename.ml @@ -38,7 +38,6 @@ and exp' rho e = match e with let ds', rho'' = decs rho' ds in ActorE (i', ds', fields rho'' fs, t) | AssignE (e1, e2) -> AssignE (lexp rho e1, exp rho e2) - | ArrayE (m, t, es) -> ArrayE (m, t, exps rho es) | CallE (e1, ts, e2) -> CallE (exp rho e1, ts, exp rho e2) | BlockE (ds, e1) -> let ds', rho' = decs rho ds in BlockE (ds', exp rho' e1) diff --git a/src/ir_passes/show.ml b/src/ir_passes/show.ml index 1c0faa811a2..227b1c9310a 100644 --- a/src/ir_passes/show.ml +++ b/src/ir_passes/show.ml @@ -324,8 +324,6 @@ and t_exp' env = function | PrimE (p, es) -> PrimE (p, t_exps env es) | AssignE (lexp1, exp2) -> AssignE (t_lexp env lexp1, t_exp env exp2) - | ArrayE (mut, t, exps) -> - ArrayE (mut, t, t_exps env exps) | FuncE (s, c, id, typbinds, pat, typT, exp) -> FuncE (s, c, id, typbinds, pat, typT, t_exp env exp) | CallE (exp1, typs, exp2) -> diff --git a/src/ir_passes/tailcall.ml b/src/ir_passes/tailcall.ml index 0ef7f48b8a8..38d3fd36340 100644 --- a/src/ir_passes/tailcall.ml +++ b/src/ir_passes/tailcall.ml @@ -95,7 +95,6 @@ and exp' env e : exp' = match e.it with | VarE _ | LitE _ -> e.it | PrimE (p, es) -> PrimE (p, List.map (exp env) es) | AssignE (e1, e2) -> AssignE (lexp env e1, exp env e2) - | ArrayE (m,t,es) -> ArrayE (m,t,(exps env es)) | CallE (e1, insts, e2) -> begin match e1.it, env with @@ -138,8 +137,6 @@ and exp' env e : exp' = match e.it with | ActorE (i, ds, fs, t) -> ActorE (i, ds, fs, t) (* TODO: descent into ds *) | NewObjE (s,is,t) -> NewObjE (s, is, t) -and exps env es = List.map (exp env) es - and lexp env le : lexp = {le with it = lexp' env le} and lexp' env le : lexp' = match le.it with diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index c469e8a3c9a..a98af5cc989 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -88,7 +88,7 @@ and exp' at note = function | S.AssignE (e1, e2) -> I.AssignE (lexp e1, exp e2) | S.ArrayE (m, es) -> let t = T.as_array note.I.note_typ in - I.ArrayE (mut m, T.as_immut t, exps es) + I.PrimE (I.ArrayPrim (mut m, T.as_immut t), exps es) | S.IdxE (e1, e2) -> I.PrimE (I.IdxPrim, [exp e1; exp e2]) | S.FuncE (name, sp, tbs, p, _t_opt, e) -> let s, po = match sp.it with From 47203791a497ba625499850b4b86dd8848029b8f Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 19 Dec 2019 17:55:35 +0100 Subject: [PATCH 0935/1176] IR Interpreter: Unify handling of PrimE This is where we reap the benefits of #1004: by applying `interpret_exps` once for all prims, and then work with _values_ for each prim. Makes the interpreter much easier to read. --- src/ir_interpreter/interpret_ir.ml | 163 ++++++++++++----------------- 1 file changed, 66 insertions(+), 97 deletions(-) diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index 499da4b2586..67a6f932da8 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -306,61 +306,44 @@ and interpret_exp_mut env exp (k : V.value V.cont) = | LitE lit -> k (interpret_lit env lit) | PrimE (p, es) -> - begin match p, es with - | UnPrim (ot, op), [exp1] -> - interpret_exp env exp1 (fun v1 -> k (try Operator.unop op ot v1 with Invalid_argument s -> trap exp.at "%s" s)) - | BinPrim (ot, op), [exp1; exp2] -> - interpret_exp env exp1 (fun v1 -> - interpret_exp env exp2 (fun v2 -> - k (try Operator.binop op ot v1 v2 with _ -> - trap exp.at "arithmetic overflow") - ) - ) - | RelPrim (ot, op), [exp1; exp2] -> - interpret_exp env exp1 (fun v1 -> - interpret_exp env exp2 (fun v2 -> - k (Operator.relop op ot v1 v2) - ) - ) - | TupPrim, exps -> - interpret_exps env exps [] (fun vs -> k (V.Tup vs)) - | ProjPrim n, [exp1] -> - interpret_exp env exp1 (fun v1 -> k (List.nth (V.as_tup v1) n)) - | OptPrim, [exp1] -> - interpret_exp env exp1 (fun v1 -> k (V.Opt v1)) - | TagPrim i, [exp1] -> - interpret_exp env exp1 (fun v1 -> k (V.Variant (i, v1))) - | (DotPrim n|ActorDotPrim n), [exp1] -> - interpret_exp env exp1 (fun v1 -> + interpret_exps env es [] (fun vs -> + match p, vs with + | UnPrim (ot, op), [v1] -> + k (try Operator.unop op ot v1 with Invalid_argument s -> trap exp.at "%s" s) + | BinPrim (ot, op), [v1; v2] -> + k (try Operator.binop op ot v1 v2 with _ -> + trap exp.at "arithmetic overflow") + | RelPrim (ot, op), [v1; v2] -> + k (Operator.relop op ot v1 v2) + | TupPrim, exps -> + k (V.Tup vs) + | ProjPrim n, [v1] -> + k (List.nth (V.as_tup v1) n) + | OptPrim, [v1] -> + k (V.Opt v1) + | TagPrim i, [v1] -> + k (V.Variant (i, v1)) + | (DotPrim n|ActorDotPrim n), [v1] -> let fs = V.as_obj v1 in k (try find n fs with _ -> assert false) - ) - | ArrayPrim (mut, _), exps -> - interpret_exps env exps [] (fun vs -> + | ArrayPrim (mut, _), vs -> let vs' = match mut with | Var -> List.map (fun v -> V.Mut (ref v)) vs | Const -> vs in k (V.Array (Array.of_list vs')) - ) - | IdxPrim, [exp1; exp2] -> - interpret_exp env exp1 (fun v1 -> - interpret_exp env exp2 (fun v2 -> - k (try (V.as_array v1).(V.Int.to_int (V.as_int v2)) - with Invalid_argument s -> trap exp.at "%s" s) - ) - ) - | ShowPrim ot, [exp1] -> - interpret_exp env exp1 (fun v -> + | IdxPrim, [v1; v2] -> + k (try (V.as_array v1).(V.Int.to_int (V.as_int v2)) + with Invalid_argument s -> trap exp.at "%s" s) + | ShowPrim ot, [v1] -> if Show.can_show ot - then k (Value.Text (Show.show_val ot v)) - else raise (Invalid_argument "debug_show")) - | CPSAsync, [exp1] -> - interpret_exp env exp1 (fun v -> + then k (Value.Text (Show.show_val ot v1)) + else raise (Invalid_argument "debug_show") + | CPSAsync, [v1] -> assert (not env.flavor.has_await && env.flavor.has_async_typ); - let (_, f) = V.as_func v in + let (_, f) = V.as_func v1 in let typ = exp.note.note_typ in - match typ with + begin match typ with | T.Func(_, _, _, [T.Func(_, _, _, [f_dom], _);T.Func(_, _, _, [r_dom], _)], _) -> let call_conv_f = CC.call_conv_of_typ f_dom in let call_conv_r = CC.call_conv_of_typ r_dom in @@ -373,66 +356,52 @@ and interpret_exp_mut env exp (k : V.value V.cont) = ) k | _ -> assert false - ) - | CPSAwait, [exp1;exp2] -> - interpret_exp env exp1 (fun v1 -> - interpret_exp env exp2 (fun v2 -> - assert (not env.flavor.has_await && env.flavor.has_async_typ); - match V.as_tup v2 with - | [vf; vr] -> - let (_, f) = V.as_func vf in - let (_, r) = V.as_func vr in - await env exp.at (V.as_async v1) - (fun v -> f (context env) v k) - (fun e -> r (context env) e k) (* TBR *) - | _ -> assert false - ) - ) - | OtherPrim s, exps -> - interpret_exps env exps [] (fun vs -> + end + | CPSAwait, [v1; v2] -> + assert (not env.flavor.has_await && env.flavor.has_async_typ); + begin match V.as_tup v2 with + | [vf; vr] -> + let (_, f) = V.as_func vf in + let (_, r) = V.as_func vr in + await env exp.at (V.as_async v1) + (fun v -> f (context env) v k) + (fun e -> r (context env) e k) (* TBR *) + | _ -> assert false + end + | OtherPrim s, vs -> let arg = match vs with [v] -> v | _ -> V.Tup vs in Prim.prim s (context env) arg k - ) - | CastPrim _, [e] -> interpret_exp env e k - | ActorOfIdBlob t, [e] -> - trap exp.at "ActorOfIdBlob not implemented" - | BlobOfIcUrl, [e] -> - trap exp.at "BlobOfIcUrl not implemented" (* FIXME: #1001, call Lib.URL.decode_actor_url *) - | NumConvPrim (t1, t2), exps -> - interpret_exps env exps [] (fun vs -> + | CastPrim _, [v1] -> + k v1 + | ActorOfIdBlob t, [v1] -> + trap exp.at "ActorOfIdBlob not implemented" + | BlobOfIcUrl, [v1] -> + trap exp.at "BlobOfIcUrl not implemented" (* FIXME: #1001, call Lib.URL.decode_actor_url *) + | NumConvPrim (t1, t2), vs -> let arg = match vs with [v] -> v | _ -> V.Tup vs in Prim.num_conv_prim t1 t2 (context env) arg k - ) - | ICReplyPrim ts, [exp1] -> - assert (not env.flavor.has_async_typ); - let reply = Option.get env.replies in - interpret_exp env exp1 - (fun v -> Scheduler.queue (fun () -> reply v)) - | ICRejectPrim, [exp1] -> - assert (not env.flavor.has_async_typ); - let reject = Option.get env.rejects in - interpret_exp env exp1 - (fun v -> - let e = V.Tup [V.Variant ("error", V.unit); v] in - Scheduler.queue (fun () -> reject e)) - | ICCallPrim, [exp1; exp2; expk ; expr] -> - assert (not env.flavor.has_async_typ); - interpret_exp env exp1 (fun v1 -> - interpret_exp env exp2 (fun v2 -> - interpret_exp env expk (fun kv -> - interpret_exp env expr (fun rv -> + | ICReplyPrim ts, [v1] -> + assert (not env.flavor.has_async_typ); + let reply = Option.get env.replies in + Scheduler.queue (fun () -> reply v1) + | ICRejectPrim, [v1] -> + assert (not env.flavor.has_async_typ); + let reject = Option.get env.rejects in + let e = V.Tup [V.Variant ("error", V.unit); v1] in + Scheduler.queue (fun () -> reject e) + | ICCallPrim, [v1; v2; kv; rv] -> let call_conv, f = V.as_func v1 in - check_call_conv exp1 call_conv; + check_call_conv (List.hd es) call_conv; check_call_conv_arg env exp v2 call_conv; last_region := exp.at; (* in case the following throws *) let vc = context env in - f (V.Tup[vc; kv; rv]) v2 k)))) - | ICCallerPrim, [] -> - k env.caller - | _ -> - trap exp.at "Unknown prim or wrong number of arguments (%d given):\n %s" - (List.length es) (Wasm.Sexpr.to_string 80 (Arrange_ir.prim p)) - end + f (V.Tup[vc; kv; rv]) v2 k + | ICCallerPrim, [] -> + k env.caller + | _ -> + trap exp.at "Unknown prim or wrong number of arguments (%d given):\n %s" + (List.length es) (Wasm.Sexpr.to_string 80 (Arrange_ir.prim p)) + ) | AssignE (lexp1, exp2) -> interpret_lexp env lexp1 (fun v1 -> interpret_exp env exp2 (fun v2 -> From 9119049e605ea106a34a3f92cb5b2d091a18c54e Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Sat, 28 Dec 2019 18:57:19 +0100 Subject: [PATCH 0936/1176] Dito with Break, Ret, Await, Throw, Assert --- src/codegen/compile.ml | 29 ++++++------ src/ir_def/arrange_ir.ml | 10 ++-- src/ir_def/check_ir.ml | 74 +++++++++++++----------------- src/ir_def/construct.ml | 6 +-- src/ir_def/freevars.ml | 5 -- src/ir_def/ir.ml | 10 ++-- src/ir_def/ir_effect.ml | 17 ++++--- src/ir_interpreter/interpret_ir.ml | 26 ++++------- src/ir_passes/async.ml | 10 +--- src/ir_passes/await.ml | 65 +++++++++++--------------- src/ir_passes/rename.ml | 13 ++---- src/ir_passes/show.ml | 9 ---- src/ir_passes/tailcall.ml | 9 ++-- src/lowering/desugar.ml | 10 ++-- 14 files changed, 119 insertions(+), 174 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index c4a170500f7..07011dae04f 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -5871,6 +5871,21 @@ and compile_exp (env : E.t) ae exp = Arr.idx env ^^ load_ptr + | BreakPrim name, [e] -> + let d = VarEnv.get_label_depth ae name in + SR.Unreachable, + compile_exp_vanilla env ae e ^^ + G.branch_to_ d + | AssertPrim, [e1] -> + SR.unit, + compile_exp_as env ae SR.bool e1 ^^ + G.if_ [] G.nop (Dfinity.fail_assert env exp.at) + | RetPrim, [e] -> + SR.Unreachable, + compile_exp_as env ae (StackRep.of_arity (E.get_return_arity env)) e ^^ + FakeMultiVal.store env (Lib.List.make (E.get_return_arity env) I32Type) ^^ + G.i Return + (* Numeric conversions *) | NumConvPrim (t1, t2), [e] -> begin let open Type in @@ -6175,10 +6190,6 @@ and compile_exp (env : E.t) ae exp = store_code | LitE l -> compile_lit env l - | AssertE e1 -> - SR.unit, - compile_exp_as env ae SR.bool e1 ^^ - G.if_ [] G.nop (Dfinity.fail_assert env exp.at) | IfE (scrut, e1, e2) -> let code_scrut = compile_exp_as env ae SR.bool scrut in let sr1, code1 = compile_exp env ae e1 in @@ -6206,22 +6217,12 @@ and compile_exp (env : E.t) ae exp = compile_exp_vanilla env ae1 e ) ) - | BreakE (name, e) -> - let d = VarEnv.get_label_depth ae name in - SR.Unreachable, - compile_exp_vanilla env ae e ^^ - G.branch_to_ d | LoopE e -> SR.Unreachable, G.loop_ [] (compile_exp_unit env ae e ^^ G.i (Br (nr 0l)) ) ^^ G.i Unreachable - | RetE e -> - SR.Unreachable, - compile_exp_as env ae (StackRep.of_arity (E.get_return_arity env)) e ^^ - FakeMultiVal.store env (Lib.List.make (E.get_return_arity env) I32Type) ^^ - G.i Return | CallE (e1, _, e2) -> let sort, control, _, arg_tys, ret_tys = Type.as_func e1.note.note_typ in let n_args = List.length arg_tys in diff --git a/src/ir_def/arrange_ir.ml b/src/ir_def/arrange_ir.ml index f120280f353..92f48b95a06 100644 --- a/src/ir_def/arrange_ir.ml +++ b/src/ir_def/arrange_ir.ml @@ -23,11 +23,7 @@ let rec exp e = match e.it with | SwitchE (e, cs) -> "SwitchE" $$ [exp e] @ List.map case cs | LoopE e1 -> "LoopE" $$ [exp e1] | LabelE (i, t, e) -> "LabelE" $$ [id i; typ t; exp e] - | BreakE (i, e) -> "BreakE" $$ [id i; exp e] - | RetE e -> "RetE" $$ [exp e] | AsyncE e -> "AsyncE" $$ [exp e] - | AwaitE e -> "AwaitE" $$ [exp e] - | AssertE e -> "AssertE" $$ [exp e] | DeclareE (i, t, e1) -> "DeclareE" $$ [id i; exp e1] | DefineE (i, m, e1) -> "DefineE" $$ [id i; mut m; exp e1] | FuncE (x, s, c, tp, as_, ts, e) -> @@ -36,7 +32,6 @@ let rec exp e = match e.it with "SelfCallE" $$ [typ (Type.seq ts); exp exp_f; exp exp_k; exp exp_r] | ActorE (i, ds, fs, t) -> "ActorE" $$ [id i] @ List.map dec ds @ fields fs @ [typ t] | NewObjE (s, fs, t) -> "NewObjE" $$ (Arrange_type.obj_sort s :: fields fs @ [typ t]) - | ThrowE e -> "ThrowE" $$ [exp e] | TryE (e, cs) -> "TryE" $$ [exp e] @ List.map case cs and lexp le = match le.it with @@ -64,6 +59,11 @@ and prim = function | ActorDotPrim n -> "ActorDotPrim" $$ [Atom n] | ArrayPrim (m, t) -> "ArrayPrim" $$ [mut m; typ t] | IdxPrim -> Atom "IdxPrim" + | BreakPrim i -> "BreakPrim" $$ [id i] + | RetPrim -> Atom "RetPrim" + | AwaitPrim -> Atom "AwaitPrim" + | AssertPrim -> Atom "AssertPrim" + | ThrowPrim -> Atom "ThrowPrim" | ShowPrim t -> "ShowPrim" $$ [typ t] | NumConvPrim (t1, t2) -> "NumConvPrim" $$ [prim_ty t1; prim_ty t2] | CastPrim (t1, t2) -> "CastPrim" $$ [typ t1; typ t2] diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 3a6b0363884..80dee5a271b 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -397,6 +397,38 @@ let rec check_exp env (exp:Ir.exp) : unit = in typ exp2 <: T.nat; t2 <~ t + | BreakPrim id, [exp1] -> + begin + match T.Env.find_opt id env.labs with + | None -> error env exp.at "unbound label %s" id + | Some t1 -> typ exp1 <: t1; + end; + T.Non <: t (* vacuously true *) + | RetPrim, [exp1] -> + begin + match env.rets with + | None -> error env exp.at "misplaced return" + | Some t0 -> assert (t0 <> T.Pre); typ exp1 <: t0; + end; + T.Non <: t (* vacuously true *) + | ThrowPrim, [exp1] -> + check env.flavor.has_await "throw in non-await flavor"; + check env.async "misplaced throw"; + typ exp1 <: T.throw; + T.Non <: t (* vacuously true *) + | AwaitPrim, [exp1] -> + check env.flavor.has_await "await in non-await flavor"; + check env.async "misplaced await"; + let t1 = T.promote (typ exp1) in + let t2 = try T.as_async_sub t1 + with Invalid_argument _ -> + error env exp1.at "expected async type, but expression has type\n %s" + (T.string_of_typ_expand t1) + in + t2 <: t + | AssertPrim, [exp1] -> + typ exp1 <: T.bool; + T.unit <: t | ShowPrim ot, [exp1] -> check env.flavor.has_show "show expression in non-show flavor"; check (Show.can_show ot) "show is not defined for operand type"; @@ -527,33 +559,6 @@ let rec check_exp env (exp:Ir.exp) : unit = check_exp (add_lab env id t0) exp1; typ exp1 <: t0; t0 <: t - | BreakE (id, exp1) -> - begin - match T.Env.find_opt id env.labs with - | None -> - error env exp.at "unbound label %s" id - | Some t1 -> - check_exp env exp1; - typ exp1 <: t1; - end; - T.Non <: t (* vacuously true *) - | RetE exp1 -> - begin - match env.rets with - | None -> - error env exp.at "misplaced return" - | Some t0 -> - assert (t0 <> T.Pre); - check_exp env exp1; - typ exp1 <: t0; - end; - T.Non <: t (* vacuously true *) - | ThrowE exp1 -> - check env.flavor.has_await "throw in non-await flavor"; - check env.async "misplaced throw"; - check_exp env exp1; - typ exp1 <: T.throw; - T.Non <: t (* vacuously true *) | AsyncE exp1 -> check env.flavor.has_await "async expression in non-await flavor"; let t1 = typ exp1 in @@ -562,21 +567,6 @@ let rec check_exp env (exp:Ir.exp) : unit = check_exp env' exp1; t1 <: T.Any; T.Async t1 <: t - | AwaitE exp1 -> - check env.flavor.has_await "await in non-await flavor"; - check env.async "misplaced await"; - check_exp env exp1; - let t1 = T.promote (typ exp1) in - let t2 = try T.as_async_sub t1 - with Invalid_argument _ -> - error env exp1.at "expected async type, but expression has type\n %s" - (T.string_of_typ_expand t1) - in - t2 <: t - | AssertE exp1 -> - check_exp env exp1; - typ exp1 <: T.bool; - T.unit <: t | DeclareE (id, t0, exp1) -> check_typ env t0; let env' = adjoin_vals env (T.Env.singleton id t0) in diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index 51e1704156b..320b53fa021 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -98,7 +98,7 @@ let asyncE typ e = } let assertE e = - { it = AssertE e; + { it = PrimE (AssertPrim, [e]); at = no_region; note = { note_typ = T.unit; note_eff = eff e} } @@ -290,7 +290,7 @@ let tupE exps = let unitE = tupE [] let breakE l exp = - { it = BreakE (l, exp); + { it = PrimE (BreakPrim l, [exp]); at = no_region; note = { note_eff = eff exp; @@ -299,7 +299,7 @@ let breakE l exp = } let retE exp = - { it = RetE exp; + { it = PrimE (RetPrim, [exp]); at = no_region; note = { note_eff = eff exp; note_typ = T.Non } diff --git a/src/ir_def/freevars.ml b/src/ir_def/freevars.ml index 2b63101b812..9096541ec6f 100644 --- a/src/ir_def/freevars.ml +++ b/src/ir_def/freevars.ml @@ -79,17 +79,12 @@ let rec exp e : f = match e.it with | SwitchE (e, cs) -> exp e ++ cases cs | LoopE e1 -> exp e1 | LabelE (i, t, e) -> exp e - | BreakE (i, e) -> exp e - | RetE e -> exp e | AsyncE e -> exp e - | AwaitE e -> exp e - | AssertE e -> exp e | DeclareE (i, t, e) -> exp e // i | DefineE (i, m, e) -> id i ++ exp e | FuncE (x, s, c, tp, as_, t, e) -> under_lambda (exp e /// args as_) | ActorE (i, ds, fs, _) -> close (decs ds +++ fields fs) // i | NewObjE (_, fs, _) -> fields fs - | ThrowE e -> exp e | TryE (e, cs) -> exp e ++ cases cs | SelfCallE (_, e1, e2, e3) -> under_lambda (exp e1) ++ exp e2 ++ exp e3 diff --git a/src/ir_def/ir.ml b/src/ir_def/ir.ml index 25ba10791b9..e373faec735 100644 --- a/src/ir_def/ir.ml +++ b/src/ir_def/ir.ml @@ -72,11 +72,7 @@ and exp' = | SwitchE of exp * case list (* switch *) | LoopE of exp (* do-while loop *) | LabelE of id * Type.typ * exp (* label *) - | BreakE of id * exp (* break *) - | RetE of exp (* return *) | AsyncE of exp (* async *) - | AwaitE of exp (* await *) - | AssertE of exp (* assertion *) | DeclareE of id * Type.typ * exp (* local promise *) | DefineE of id * mut * exp (* promise fulfillment *) | FuncE of (* function *) @@ -84,7 +80,6 @@ and exp' = | SelfCallE of Type.typ list * exp * exp * exp (* essentially ICCallPrim (FuncE shared…) *) | ActorE of id * dec list * field list * Type.typ (* actor *) | NewObjE of Type.obj_sort * field list * Type.typ (* make an object *) - | ThrowE of exp (* throw *) | TryE of exp * case list (* try/catch *) and field = (field', Type.typ) Source.annotated_phrase @@ -112,6 +107,11 @@ and prim = | ActorDotPrim of Type.lab (* actor field access *) | ArrayPrim of mut * Type.typ (* array constructor *) | IdxPrim (* array indexing *) + | BreakPrim of id (* break *) + | RetPrim (* return *) + | AwaitPrim (* await *) + | AssertPrim (* assertion *) + | ThrowPrim (* throw *) | ShowPrim of Type.typ (* debug show *) | NumConvPrim of Type.prim * Type.prim | CastPrim of Type.typ * Type.typ (* representationally a noop *) diff --git a/src/ir_def/ir_effect.ml b/src/ir_def/ir_effect.ml index 3a37ab68f13..c9c659e9b41 100644 --- a/src/ir_def/ir_effect.ml +++ b/src/ir_def/ir_effect.ml @@ -23,15 +23,16 @@ let is_triv phrase = let effect_exp (exp: exp) : T.eff = eff exp (* infer the effect of an expression, assuming all sub-expressions are correctly effect-annotated es*) -let rec infer_effect_exp (exp: exp) : T.eff = +let rec infer_effect_prim = function + | ThrowPrim | AwaitPrim -> T.Await + | _ -> T.Triv + + and infer_effect_exp (exp: exp) : T.eff = match exp.it with | VarE _ | LitE _ -> T.Triv - | AssertE exp1 | LabelE (_, _, exp1) - | BreakE (_, exp1) - | RetE exp1 | LoopE exp1 | AssignE (_, exp1) -> effect_exp exp1 @@ -39,9 +40,9 @@ let rec infer_effect_exp (exp: exp) : T.eff = let t1 = effect_exp exp1 in let t2 = effect_exp exp2 in max_eff t1 t2 - | PrimE (_, exps) -> + | PrimE (p, exps) -> let es = List.map effect_exp exps in - List.fold_left max_eff T.Triv es + List.fold_left max_eff (infer_effect_prim p) es | BlockE (ds, exp) -> let es = List.map effect_dec ds in List.fold_left max_eff (effect_exp exp) es @@ -56,9 +57,7 @@ let rec infer_effect_exp (exp: exp) : T.eff = max_eff e1 e2 | AsyncE exp1 -> T.Triv - | ThrowE _ - | TryE _ - | AwaitE _ -> + | TryE _ -> T.Await | DeclareE (_, _, exp1) -> effect_exp exp1 diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index 67a6f932da8..671164b607f 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -335,6 +335,16 @@ and interpret_exp_mut env exp (k : V.value V.cont) = | IdxPrim, [v1; v2] -> k (try (V.as_array v1).(V.Int.to_int (V.as_int v2)) with Invalid_argument s -> trap exp.at "%s" s) + | BreakPrim id, [v1] -> find id env.labs v1 + | RetPrim, [v1] -> Option.get env.rets v1 + | ThrowPrim, [v1] -> Option.get env.throws v1 + | AwaitPrim, [v1] -> + assert env.flavor.has_await; + await env exp.at (V.as_async v1) k (Option.get env.throws) + | AssertPrim, [v1] -> + if V.as_bool v1 + then k V.unit + else trap exp.at "assertion failure" | ShowPrim ot, [v1] -> if Show.can_show ot then k (Value.Text (Show.show_val ot v1)) @@ -439,12 +449,6 @@ and interpret_exp_mut env exp (k : V.value V.cont) = | LabelE (id, _typ, exp1) -> let env' = {env with labs = V.Env.add id k env.labs} in interpret_exp env' exp1 k - | BreakE (id, exp1) -> - interpret_exp env exp1 (find id env.labs) - | RetE exp1 -> - interpret_exp env exp1 (Option.get env.rets) - | ThrowE exp1 -> - interpret_exp env exp1 (Option.get env.throws) | AsyncE exp1 -> assert env.flavor.has_await; async env @@ -454,16 +458,6 @@ and interpret_exp_mut env exp (k : V.value V.cont) = in interpret_exp env' exp1 k') k - | AwaitE exp1 -> - assert env.flavor.has_await; - interpret_exp env exp1 - (fun v1 -> await env exp.at (V.as_async v1) k (Option.get env.throws)) - | AssertE exp1 -> - interpret_exp env exp1 (fun v -> - if V.as_bool v - then k V.unit - else trap exp.at "assertion failure" - ) | DeclareE (id, typ, exp1) -> let env = adjoin_vals env (declare_id id) in interpret_exp env exp1 k diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index 5283304f038..d7bdffdb3e3 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -289,16 +289,8 @@ let transform mode env prog = LoopE (t_exp exp1) | LabelE (id, typ, exp1) -> LabelE (id, t_typ typ, t_exp exp1) - | BreakE (id, exp1) -> - BreakE (id, t_exp exp1) - | RetE exp1 -> - RetE (t_exp exp1) | AsyncE _ - | AwaitE _ - | TryE _ - | ThrowE _ -> assert false - | AssertE exp1 -> - AssertE (t_exp exp1) + | TryE _ -> assert false | DeclareE (id, typ, exp1) -> DeclareE (id, t_typ typ, t_exp exp1) | DefineE (id, mut ,exp1) -> diff --git a/src/ir_passes/await.ml b/src/ir_passes/await.ml index fd36fd7a3e3..cba31ffb2a2 100644 --- a/src/ir_passes/await.ml +++ b/src/ir_passes/await.ml @@ -63,8 +63,6 @@ and t_exp' context exp' = match exp' with | VarE _ | LitE _ -> exp' - | PrimE (p, exps) -> - PrimE (p, List.map (t_exp context) exps) | AssignE (exp1, exp2) -> AssignE (t_lexp context exp1, t_exp context exp2) | CallE (exp1, typs, exp2) -> @@ -85,18 +83,18 @@ and t_exp' context exp' = | LabelE (id, _typ, exp1) -> let context' = LabelEnv.add (Named id) Label context in LabelE (id, _typ, t_exp context' exp1) - | BreakE (id, exp1) -> + | PrimE (BreakPrim id, [exp1]) -> begin match LabelEnv.find_opt (Named id) context with - | Some (Cont k) -> RetE (k -@- (t_exp context exp1)) - | Some Label -> BreakE (id, t_exp context exp1) + | Some (Cont k) -> (retE (k -@- (t_exp context exp1))).it + | Some Label -> (breakE id (t_exp context exp1)).it | None -> assert false end - | RetE exp1 -> + | PrimE (RetPrim, [exp1]) -> begin match LabelEnv.find_opt Return context with - | Some (Cont k) -> RetE (k -@- (t_exp context exp1)) - | Some Label -> RetE (t_exp context exp1) + | Some (Cont k) -> (retE (k -@- (t_exp context exp1))).it + | Some Label -> (retE (t_exp context exp1)).it | None -> assert false end | AsyncE exp1 -> @@ -110,11 +108,7 @@ and t_exp' context exp' = in (asyncE (typ exp1) ([k_ret; k_fail] -->* c_exp context' exp1 (ContVar k_ret))).it - | TryE _ - | ThrowE _ - | AwaitE _ -> assert false (* these never have effect T.Triv *) - | AssertE exp1 -> - AssertE (t_exp context exp1) + | TryE _ -> assert false (* these never have effect T.Triv *) | DeclareE (id, typ, exp1) -> DeclareE (id, typ, t_exp context exp1) | DefineE (id, mut ,exp1) -> @@ -126,6 +120,8 @@ and t_exp' context exp' = ActorE (id, t_decs context ds, ids, t) | NewObjE (sort, ids, typ) -> exp' | SelfCallE _ -> assert false + | PrimE (p, exps) -> + PrimE (p, List.map (t_exp context) exps) and t_lexp context lexp = { lexp with it = t_lexp' context lexp.it } @@ -245,8 +241,6 @@ and c_exp' context exp k = | LitE _ | FuncE _ -> assert false - | PrimE (p, exps) -> - nary context k (fun vs -> e (PrimE (p, vs))) exps | ActorE _ -> assert false; (* ActorE fields cannot await *) | AssignE (exp1, exp2) -> @@ -318,23 +312,21 @@ and c_exp' context exp k = (fun k -> let context' = LabelEnv.add (Named id) (Cont (ContVar k)) context in c_exp context' exp1 (ContVar k)) (* TODO optimize me, if possible *) - | BreakE (id, exp1) -> + | PrimE (BreakPrim id, [exp1]) -> begin match LabelEnv.find_opt (Named id) context with - | Some (Cont k') -> - c_exp context exp1 k' + | Some (Cont k') -> c_exp context exp1 k' | Some Label -> assert false | None -> assert false end - | RetE exp1 -> + | PrimE (RetPrim, [exp1]) -> begin match LabelEnv.find_opt Return context with - | Some (Cont k') -> - c_exp context exp1 k' + | Some (Cont k') -> c_exp context exp1 k' | Some Label -> assert false | None -> assert false end - | ThrowE exp1 -> + | PrimE (ThrowPrim, [exp1]) -> begin match LabelEnv.find_opt Throw context with | Some (Cont k') -> c_exp context exp1 k' @@ -351,33 +343,30 @@ and c_exp' context exp k = in k -@- (asyncE (typ exp1) ([k_ret; k_fail] -->* (c_exp context' exp1 (ContVar k_ret)))) - | AwaitE exp1 -> + | PrimE (AwaitPrim, [exp1]) -> let r = match LabelEnv.find_opt Throw context with | Some (Cont r) -> r | Some Label | None -> assert false in - letcont r - (fun r -> - letcont k - (fun k -> - let kr = tupE [k;r] in - match eff exp1 with - | T.Triv -> - awaitE (typ exp) (t_exp context exp1) kr - | T.Await -> - c_exp context exp1 - (meta (typ exp1) (fun v1 -> (awaitE (typ exp) v1 kr))) - ) - ) - | AssertE exp1 -> - unary context k (fun v1 -> e (AssertE v1)) exp1 + letcont r (fun r -> + letcont k (fun k -> + let kr = tupE [k;r] in + match eff exp1 with + | T.Triv -> + awaitE (typ exp) (t_exp context exp1) kr + | T.Await -> + c_exp context exp1 + (meta (typ exp1) (fun v1 -> (awaitE (typ exp) v1 kr))) + )) | DeclareE (id, typ, exp1) -> unary context k (fun v1 -> e (DeclareE (id, typ, v1))) exp1 | DefineE (id, mut, exp1) -> unary context k (fun v1 -> e (DefineE (id, mut, v1))) exp1 | NewObjE _ -> exp | SelfCallE _ -> assert false + | PrimE (p, exps) -> + nary context k (fun vs -> e (PrimE (p, vs))) exps and c_block context decs exp k = let is_typ dec = diff --git a/src/ir_passes/rename.ml b/src/ir_passes/rename.ml index 328848858c8..4f40ab40bde 100644 --- a/src/ir_passes/rename.ml +++ b/src/ir_passes/rename.ml @@ -27,13 +27,15 @@ let arg_bind rho a = let i' = fresh_id a.it in ({a with it = i'}, Renaming.add a.it i' rho) -let rec exp rho e = - {e with it = exp' rho e.it} +let rec prim rho = function + | BreakPrim i -> BreakPrim (id rho i) + | p -> p +and exp rho e = {e with it = exp' rho e.it} and exp' rho e = match e with | VarE i -> VarE (id rho i) | LitE l -> e - | PrimE (p, es) -> PrimE (p, List.map (exp rho) es) + | PrimE (p, es) -> PrimE (prim rho p, List.map (exp rho) es) | ActorE (i, ds, fs, t)-> let i',rho' = id_bind rho i in let ds', rho'' = decs rho' ds in ActorE (i', ds', fields rho'' fs, t) @@ -46,11 +48,7 @@ and exp' rho e = match e with | LoopE e1 -> LoopE (exp rho e1) | LabelE (i, t, e) -> let i',rho' = id_bind rho i in LabelE(i', t, exp rho' e) - | BreakE (i, e) -> BreakE(id rho i,exp rho e) - | RetE e -> RetE (exp rho e) | AsyncE e -> AsyncE (exp rho e) - | AwaitE e -> AwaitE (exp rho e) - | AssertE e -> AssertE (exp rho e) | DeclareE (i, t, e) -> let i',rho' = id_bind rho i in DeclareE (i', t, exp rho' e) | DefineE (i, m, e) -> DefineE (id rho i, m, exp rho e) @@ -59,7 +57,6 @@ and exp' rho e = match e with let e' = exp rho' e in FuncE (x, s, c, tp, p', ts, e') | NewObjE (s, fs, t) -> NewObjE (s, fields rho fs, t) - | ThrowE e -> ThrowE (exp rho e) | TryE (e, cs) -> TryE (exp rho e, cases rho cs) | SelfCallE (ts, e1, e2, e3) -> SelfCallE (ts, exp rho e1, exp rho e2, exp rho e3) diff --git a/src/ir_passes/show.ml b/src/ir_passes/show.ml index 227b1c9310a..211a253c6e2 100644 --- a/src/ir_passes/show.ml +++ b/src/ir_passes/show.ml @@ -351,16 +351,7 @@ and t_exp' env = function LoopE (t_exp env exp1) | LabelE (id, typ, exp1) -> LabelE (id, typ, t_exp env exp1) - | BreakE (id, exp1) -> - BreakE (id, t_exp env exp1) - | RetE exp1 -> - RetE (t_exp env exp1) - | ThrowE exp1 -> - ThrowE (t_exp env exp1) | AsyncE e -> AsyncE (t_exp env e) - | AwaitE e -> AwaitE (t_exp env e) - | AssertE exp1 -> - AssertE (t_exp env exp1) | DeclareE (id, typ, exp1) -> DeclareE (id, typ, t_exp env exp1) | DefineE (id, mut ,exp1) -> diff --git a/src/ir_passes/tailcall.ml b/src/ir_passes/tailcall.ml index 38d3fd36340..4ee9d63553a 100644 --- a/src/ir_passes/tailcall.ml +++ b/src/ir_passes/tailcall.ml @@ -93,7 +93,6 @@ and assignEs vars exp : dec list = and exp' env e : exp' = match e.it with | VarE _ | LitE _ -> e.it - | PrimE (p, es) -> PrimE (p, List.map (exp env) es) | AssignE (e1, e2) -> AssignE (lexp env e1, exp env e2) | CallE (e1, insts, e2) -> begin @@ -113,13 +112,10 @@ and exp' env e : exp' = match e.it with | LoopE e1 -> LoopE (exp env e1) | LabelE (i, t, e) -> let env1 = bind env i None in LabelE(i, t, exp env1 e) - | BreakE (i, e) -> BreakE(i,exp env e) - | RetE e -> RetE (tailexp { env with tail_pos = true } e) + | PrimE (RetPrim, [e])-> PrimE (RetPrim, [tailexp { env with tail_pos = true } e]) (* NB:^ e is always in tailposition, regardless of fst env *) - | ThrowE e -> ThrowE (exp env e) (* TODO: make me a tail call *) + (* TODO: Make ThrowE a tail call *) | AsyncE e -> AsyncE (exp { tail_pos = true; info = None } e) - | AwaitE e -> AwaitE (exp env e) - | AssertE e -> AssertE (exp env e) | DeclareE (i, t, e) -> let env1 = bind env i None in DeclareE (i, t, tailexp env1 e) | DefineE (i, m, e) -> DefineE (i, m, exp env e) @@ -136,6 +132,7 @@ and exp' env e : exp' = match e.it with SelfCallE (ts, exp1', exp2', exp3') | ActorE (i, ds, fs, t) -> ActorE (i, ds, fs, t) (* TODO: descent into ds *) | NewObjE (s,is,t) -> NewObjE (s, is, t) + | PrimE (p, es) -> PrimE (p, List.map (exp env) es) and lexp env le : lexp = {le with it = lexp' env le} diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index a98af5cc989..0b5b7234287 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -143,12 +143,12 @@ and exp' at note = function | S.ForE (p, e1, e2) -> (forE (pat p) (exp e1) (exp e2)).it | S.DebugE e -> if !Mo_config.Flags.release_mode then unitE.it else (exp e).it | S.LabelE (l, t, e) -> I.LabelE (l.it, t.Source.note, exp e) - | S.BreakE (l, e) -> I.BreakE (l.it, exp e) - | S.RetE e -> I.RetE (exp e) - | S.ThrowE e -> I.ThrowE (exp e) + | S.BreakE (l, e) -> (breakE l.it (exp e)).it + | S.RetE e -> (retE (exp e)).it + | S.ThrowE e -> I.PrimE (I.ThrowPrim, [exp e]) | S.AsyncE e -> I.AsyncE (exp e) - | S.AwaitE e -> I.AwaitE (exp e) - | S.AssertE e -> I.AssertE (exp e) + | S.AwaitE e -> I.PrimE (I.AwaitPrim, [exp e]) + | S.AssertE e -> I.PrimE (I.AssertPrim, [exp e]) | S.AnnotE (e, _) -> assert false | S.ImportE (f, ir) -> begin match !ir with From 728ee2ca115be945a51269061d7582d46facb77e Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Sat, 28 Dec 2019 18:59:09 +0100 Subject: [PATCH 0937/1176] A comment explaining when something is an IR.prim --- src/ir_def/ir.ml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ir_def/ir.ml b/src/ir_def/ir.ml index e373faec735..509a721c365 100644 --- a/src/ir_def/ir.ml +++ b/src/ir_def/ir.ml @@ -95,6 +95,9 @@ and lexp' = | DotLE of exp * Type.lab (* object projection *) +(* In the IR, a prim is any AST node that has expr subexpressions, but they are +all call-by-value. Many passes can treat them uniformly, so they are unified using the +using the PrimE node. *) and prim = | UnPrim of Type.typ * unop (* unary operator *) | BinPrim of Type.typ * binop (* binary operator *) From 6242aaac7977dd5d3d8993a7c15bc9ca99fef109 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Sat, 28 Dec 2019 19:18:06 +0100 Subject: [PATCH 0938/1176] Dito CallE itself --- src/codegen/compile.ml | 77 +++++++++++++++--------------- src/ir_def/arrange_ir.ml | 2 +- src/ir_def/check_ir.ml | 37 +++++++------- src/ir_def/construct.ml | 4 +- src/ir_def/freevars.ml | 1 - src/ir_def/ir.ml | 2 +- src/ir_def/ir_effect.ml | 4 -- src/ir_interpreter/interpret_ir.ml | 16 +++---- src/ir_passes/async.ml | 6 +-- src/ir_passes/await.ml | 4 -- src/ir_passes/rename.ml | 1 - src/ir_passes/show.ml | 63 +++--------------------- src/ir_passes/tailcall.ml | 18 ++++--- src/lowering/desugar.ml | 8 ++-- 14 files changed, 85 insertions(+), 158 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 07011dae04f..f83d45a7633 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -5813,6 +5813,45 @@ and compile_exp (env : E.t) ae exp = let const_sr sr inst = sr, G.concat_map (compile_exp_as env ae sr) es ^^ inst in begin match p, es with + (* Calls *) + | CallPrim _, [e1; e2] -> + let sort, control, _, arg_tys, ret_tys = Type.as_func e1.note.note_typ in + let n_args = List.length arg_tys in + let return_arity = match control with + | Type.Returns -> List.length ret_tys + | Type.Replies -> 0 + | Type.Promises -> assert false in + + StackRep.of_arity return_arity, + let fun_sr, code1 = compile_exp env ae e1 in + begin match fun_sr, sort with + | SR.StaticThing (SR.StaticFun fi), _ -> + code1 ^^ + compile_unboxed_zero ^^ (* A dummy closure *) + compile_exp_as env ae (StackRep.of_arity n_args) e2 ^^ (* the args *) + G.i (Call (nr fi)) ^^ + FakeMultiVal.load env (Lib.List.make return_arity I32Type) + | _, Type.Local -> + let (set_clos, get_clos) = new_local env "clos" in + code1 ^^ StackRep.adjust env fun_sr SR.Vanilla ^^ + set_clos ^^ + get_clos ^^ + compile_exp_as env ae (StackRep.of_arity n_args) e2 ^^ + get_clos ^^ + Closure.call_closure env n_args return_arity + | _, Type.Shared _ -> + (* Non-one-shot functions have been rewritten in async.ml *) + assert (control = Type.Returns); + + let (set_meth_pair, get_meth_pair) = new_local env "meth_pair" in + let (set_arg, get_arg) = new_local env "arg" in + let _, _, _, ts, _ = Type.as_func e1.note.note_typ in + code1 ^^ StackRep.adjust env fun_sr SR.Vanilla ^^ + set_meth_pair ^^ + compile_exp_as env ae SR.Vanilla e2 ^^ set_arg ^^ + + FuncDec.ic_call_one_shot env ts get_meth_pair get_arg + end (* Operators *) @@ -6223,44 +6262,6 @@ and compile_exp (env : E.t) ae exp = ) ^^ G.i Unreachable - | CallE (e1, _, e2) -> - let sort, control, _, arg_tys, ret_tys = Type.as_func e1.note.note_typ in - let n_args = List.length arg_tys in - let return_arity = match control with - | Type.Returns -> List.length ret_tys - | Type.Replies -> 0 - | Type.Promises -> assert false in - - StackRep.of_arity return_arity, - let fun_sr, code1 = compile_exp env ae e1 in - begin match fun_sr, sort with - | SR.StaticThing (SR.StaticFun fi), _ -> - code1 ^^ - compile_unboxed_zero ^^ (* A dummy closure *) - compile_exp_as env ae (StackRep.of_arity n_args) e2 ^^ (* the args *) - G.i (Call (nr fi)) ^^ - FakeMultiVal.load env (Lib.List.make return_arity I32Type) - | _, Type.Local -> - let (set_clos, get_clos) = new_local env "clos" in - code1 ^^ StackRep.adjust env fun_sr SR.Vanilla ^^ - set_clos ^^ - get_clos ^^ - compile_exp_as env ae (StackRep.of_arity n_args) e2 ^^ - get_clos ^^ - Closure.call_closure env n_args return_arity - | _, Type.Shared _ -> - (* Non-one-shot functions have been rewritten in async.ml *) - assert (control = Type.Returns); - - let (set_meth_pair, get_meth_pair) = new_local env "meth_pair" in - let (set_arg, get_arg) = new_local env "arg" in - let _, _, _, ts, _ = Type.as_func e1.note.note_typ in - code1 ^^ StackRep.adjust env fun_sr SR.Vanilla ^^ - set_meth_pair ^^ - compile_exp_as env ae SR.Vanilla e2 ^^ set_arg ^^ - - FuncDec.ic_call_one_shot env ts get_meth_pair get_arg - end | SwitchE (e, cs) -> SR.Vanilla, let code1 = compile_exp_vanilla env ae e in diff --git a/src/ir_def/arrange_ir.ml b/src/ir_def/arrange_ir.ml index 92f48b95a06..946af5df23d 100644 --- a/src/ir_def/arrange_ir.ml +++ b/src/ir_def/arrange_ir.ml @@ -17,7 +17,6 @@ let rec exp e = match e.it with | LitE l -> "LitE" $$ [lit l] | PrimE (p, es) -> "PrimE" $$ [prim p] @ List.map exp es | AssignE (le1, e2) -> "AssignE" $$ [lexp le1; exp e2] - | CallE (e1, ts, e2) -> "CallE" $$ [exp e1] @ List.map typ ts @ [exp e2] | BlockE (ds, e1) -> "BlockE" $$ List.map dec ds @ [exp e1] | IfE (e1, e2, e3) -> "IfE" $$ [exp e1; exp e2; exp e3] | SwitchE (e, cs) -> "SwitchE" $$ [exp e] @ List.map case cs @@ -48,6 +47,7 @@ and args = function and arg a = Atom a.it and prim = function + | CallPrim ts -> "CallPrim" $$ List.map typ ts | UnPrim (t, uo) -> "UnPrim" $$ [typ t; Arrange_ops.unop uo] | BinPrim (t, bo) -> "BinPrim" $$ [typ t; Arrange_ops.binop bo] | RelPrim (t, ro) -> "RelPrim" $$ [typ t; Arrange_ops.relop ro] diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 80dee5a271b..c4cdef8ad7f 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -336,6 +336,22 @@ let rec check_exp env (exp:Ir.exp) : unit = | PrimE (p, es) -> List.iter (check_exp env) es; begin match p, es with + | CallPrim insts, [exp1; exp2] -> + begin match T.promote (typ exp1) with + | T.Func (sort, control, tbs, arg_tys, ret_tys) -> + check_inst_bounds env tbs insts exp.at; + let t_arg = T.open_ insts (T.seq arg_tys) in + let t_ret = T.open_ insts (T.codom control ret_tys) in + if T.is_shared_sort sort then begin + check_concrete env exp.at t_arg; + check_concrete env exp.at t_ret; + end; + typ exp2 <: t_arg; + t_ret <: t + | T.Non -> () (* dead code, not much to check here *) + | t1 -> error env exp1.at "expected function type, but expression produces type\n %s" + (T.string_of_typ_expand t1) + end | UnPrim (ot, op), [exp1] -> check (Operator.has_unop op ot) "unary operator is not defined for operand type"; typ exp1 <: ot; @@ -501,27 +517,6 @@ let rec check_exp env (exp:Ir.exp) : unit = in typ exp2 <: t2; T.unit <: t - | CallE (exp1, insts, exp2) -> - check_exp env exp1; - check_exp env exp2; - let t1 = T.promote (typ exp1) in - begin match t1 with - | T.Func (sort, control, tbs, arg_tys, ret_tys) -> - check_inst_bounds env tbs insts exp.at; - check_exp env exp2; - let t_arg = T.open_ insts (T.seq arg_tys) in - let t_ret = T.open_ insts (T.codom control ret_tys) in - if T.is_shared_sort sort then begin - check_concrete env exp.at t_arg; - check_concrete env exp.at t_ret; - end; - typ exp2 <: t_arg; - t_ret <: t - | T.Non -> () (* dead code, not much to check here *) - | _ -> - error env exp1.at "expected function type, but expression produces type\n %s" - (T.string_of_typ_expand t1) - end | BlockE (ds, exp1) -> let scope = gather_block_decs env ds in let env' = adjoin env scope in diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index 320b53fa021..866192e8ed3 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -204,7 +204,7 @@ let boolE b = let callE exp1 ts exp2 = match T.promote (typ exp1) with | T.Func (_sort, _control, _, _, ret_tys) -> - { it = CallE (exp1, ts, exp2); + { it = PrimE (CallPrim ts, [exp1; exp2]); at = no_region; note = { note_typ = T.open_ ts (T.seq ret_tys); @@ -492,7 +492,7 @@ let (-->*) xs exp = let ( -*- ) exp1 exp2 = match typ exp1 with | T.Func (_, _, [], _, ret_tys) -> - { it = CallE (exp1, [], exp2); + { it = PrimE (CallPrim [], [exp1; exp2]); at = no_region; note = {note_typ = T.seq ret_tys; note_eff = max_eff (eff exp1) (eff exp2)} diff --git a/src/ir_def/freevars.ml b/src/ir_def/freevars.ml index 9096541ec6f..6062d16a195 100644 --- a/src/ir_def/freevars.ml +++ b/src/ir_def/freevars.ml @@ -73,7 +73,6 @@ let rec exp e : f = match e.it with | LitE l -> M.empty | PrimE (_, es) -> exps es | AssignE (e1, e2) -> lexp e1 ++ exp e2 - | CallE (e1, ts, e2) -> exps [e1; e2] | BlockE (ds, e1) -> close (decs ds +++ exp e1) | IfE (e1, e2, e3) -> exps [e1; e2; e3] | SwitchE (e, cs) -> exp e ++ cases cs diff --git a/src/ir_def/ir.ml b/src/ir_def/ir.ml index 509a721c365..b69a0c3646f 100644 --- a/src/ir_def/ir.ml +++ b/src/ir_def/ir.ml @@ -66,7 +66,6 @@ and exp' = | VarE of id (* variable *) | LitE of lit (* literal *) | AssignE of lexp * exp (* assignment *) - | CallE of exp * Type.typ list * exp (* function call *) | BlockE of (dec list * exp) (* block *) | IfE of exp * exp * exp (* conditional *) | SwitchE of exp * case list (* switch *) @@ -99,6 +98,7 @@ and lexp' = all call-by-value. Many passes can treat them uniformly, so they are unified using the using the PrimE node. *) and prim = + | CallPrim of Type.typ list (* function call *) | UnPrim of Type.typ * unop (* unary operator *) | BinPrim of Type.typ * binop (* binary operator *) | RelPrim of Type.typ * relop (* relational operator *) diff --git a/src/ir_def/ir_effect.ml b/src/ir_def/ir_effect.ml index c9c659e9b41..cc3febc71de 100644 --- a/src/ir_def/ir_effect.ml +++ b/src/ir_def/ir_effect.ml @@ -36,10 +36,6 @@ let rec infer_effect_prim = function | LoopE exp1 | AssignE (_, exp1) -> effect_exp exp1 - | CallE (exp1, _, exp2) -> - let t1 = effect_exp exp1 in - let t2 = effect_exp exp2 in - max_eff t1 t2 | PrimE (p, exps) -> let es = List.map effect_exp exps in List.fold_left max_eff (infer_effect_prim p) es diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index 671164b607f..a5b8692d8ec 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -308,6 +308,12 @@ and interpret_exp_mut env exp (k : V.value V.cont) = | PrimE (p, es) -> interpret_exps env es [] (fun vs -> match p, vs with + | CallPrim typs, [v1; v2] -> + let call_conv, f = V.as_func v1 in + check_call_conv (List.hd es) call_conv; + check_call_conv_arg env exp v2 call_conv; + last_region := exp.at; (* in case the following throws *) + f (context env) v2 k | UnPrim (ot, op), [v1] -> k (try Operator.unop op ot v1 with Invalid_argument s -> trap exp.at "%s" s) | BinPrim (ot, op), [v1; v2] -> @@ -418,16 +424,6 @@ and interpret_exp_mut env exp (k : V.value V.cont) = v1 := v2; k V.unit ) ) - | CallE (exp1, typs, exp2) -> - interpret_exp env exp1 (fun v1 -> - interpret_exp env exp2 (fun v2 -> - let call_conv, f = V.as_func v1 in - check_call_conv exp1 call_conv; - check_call_conv_arg env exp v2 call_conv; - last_region := exp.at; (* in case the following throws *) - f (context env) v2 k - ) - ) | BlockE (decs, exp1) -> interpret_block env None decs exp1 k | IfE (exp1, exp2, exp3) -> diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index d7bdffdb3e3..1aefff5aadc 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -202,6 +202,7 @@ let transform mode env prog = clone and prim = function + | CallPrim typs -> CallPrim (List.map t_typ typs) | UnPrim (ot, op) -> UnPrim (t_typ ot, op) | BinPrim (ot, op) -> BinPrim (t_typ ot, op) | RelPrim (ot, op) -> RelPrim (t_typ ot, op) @@ -248,7 +249,7 @@ let transform mode env prog = ] nary_async ).it - | CallE (exp1, typs, exp2) when isAwaitableFunc exp1 -> + | PrimE (CallPrim typs, [exp1; exp2]) when isAwaitableFunc exp1 -> assert (typs = []); let ts1,ts2 = match typ exp1 with @@ -271,9 +272,6 @@ let transform mode env prog = .it | PrimE (p, exps) -> PrimE (prim p, List.map t_exp exps) - | CallE (exp1, typs, exp2) -> - assert (not (isAwaitableFunc exp1)); - CallE (t_exp exp1, List.map t_typ typs, t_exp exp2) | BlockE b -> BlockE (t_block b) | IfE (exp1, exp2, exp3) -> diff --git a/src/ir_passes/await.ml b/src/ir_passes/await.ml index cba31ffb2a2..67aa3fd0703 100644 --- a/src/ir_passes/await.ml +++ b/src/ir_passes/await.ml @@ -65,8 +65,6 @@ and t_exp' context exp' = | LitE _ -> exp' | AssignE (exp1, exp2) -> AssignE (t_lexp context exp1, t_exp context exp2) - | CallE (exp1, typs, exp2) -> - CallE (t_exp context exp1, typs, t_exp context exp2) | BlockE b -> BlockE (t_block context b) | IfE (exp1, exp2, exp3) -> @@ -245,8 +243,6 @@ and c_exp' context exp k = assert false; (* ActorE fields cannot await *) | AssignE (exp1, exp2) -> c_assign context k e exp1 exp2 - | CallE (exp1, typs, exp2) -> - binary context k (fun v1 v2 -> e (CallE (v1, typs, v2))) exp1 exp2 | BlockE (decs, exp) -> c_block context decs exp k | IfE (exp1, exp2, exp3) -> diff --git a/src/ir_passes/rename.ml b/src/ir_passes/rename.ml index 4f40ab40bde..3b998bbae6c 100644 --- a/src/ir_passes/rename.ml +++ b/src/ir_passes/rename.ml @@ -40,7 +40,6 @@ and exp' rho e = match e with let ds', rho'' = decs rho' ds in ActorE (i', ds', fields rho'' fs, t) | AssignE (e1, e2) -> AssignE (lexp rho e1, exp rho e2) - | CallE (e1, ts, e2) -> CallE (exp rho e1, ts, exp rho e2) | BlockE (ds, e1) -> let ds', rho' = decs rho ds in BlockE (ds', exp rho' e1) | IfE (e1, e2, e3) -> IfE (exp rho e1, exp rho e2, exp rho e3) diff --git a/src/ir_passes/show.ml b/src/ir_passes/show.ml index 211a253c6e2..2846828efb9 100644 --- a/src/ir_passes/show.ml +++ b/src/ir_passes/show.ml @@ -70,78 +70,32 @@ let argE t = idE "x" t let define_show : T.typ -> Ir.exp -> Ir.dec = fun t e -> Construct.funcD (show_var_for t) (argE t) e -let text_exp : Ir.exp' -> Ir.exp = fun e -> - { it = e; - at = no_region; - note = { note_typ = T.text; note_eff = T.Triv } - } - let invoke_generated_show : T.typ -> Ir.exp -> Ir.exp = fun t e -> - text_exp (CallE (show_var_for t, [], e)) + show_var_for t -*- e let invoke_prelude_show : string -> T.typ -> Ir.exp -> Ir.exp = fun n t e -> let fun_typ = T.Func (T.Local, T.Returns, [], [t], [T.text]) in - text_exp (CallE - ( { it = VarE n - ; at = no_region - ; note = { note_typ = fun_typ; note_eff = T.Triv } - } - , [] - , argE t - ) - ) + idE n fun_typ -*- argE t let invoke_text_of_option : T.typ -> Ir.exp -> Ir.exp -> Ir.exp = fun t f e -> let fun_typ = T.Func (T.Local, T.Returns, [{T.var="T";T.bound=T.Any}], [show_fun_typ_for (T.Var ("T",0)); T.Opt (T.Var ("T",0))], [T.text]) in - text_exp (CallE - ( { it = VarE "@text_of_option" - ; at = no_region - ; note = { note_typ = fun_typ; note_eff = T.Triv } - } - , [t] - , tupE [f; e] - ) - ) + callE (idE "@text_of_option" fun_typ) [t] (tupE [f; e]) let invoke_text_of_variant : T.typ -> Ir.exp -> T.lab -> Ir.exp -> Ir.exp = fun t f l e -> let fun_typ = T.Func (T.Local, T.Returns, [{T.var="T";T.bound=T.Any}], [T.text; show_fun_typ_for (T.Var ("T",0)); T.Var ("T",0)], [T.text]) in - text_exp (CallE - ( { it = VarE "@text_of_variant" - ; at = no_region - ; note = { note_typ = fun_typ; note_eff = T.Triv } - } - , [t] - , tupE [textE l; f; e] - ) - ) + callE (idE "@text_of_variant" fun_typ) [t] (tupE [textE l; f; e]) let invoke_text_of_array : T.typ -> Ir.exp -> Ir.exp -> Ir.exp = fun t f e -> let fun_typ = T.Func (T.Local, T.Returns, [{T.var="T";T.bound=T.Any}], [show_fun_typ_for (T.Var ("T",0)); T.Array (T.Var ("T",0))], [T.text]) in - text_exp (CallE - ( { it = VarE "@text_of_array" - ; at = no_region - ; note = { note_typ = fun_typ; note_eff = T.Triv } - } - , [t] - , tupE [f; e] - ) - ) + callE (idE "@text_of_array" fun_typ) [t] (tupE [f; e]) let invoke_text_of_array_mut : T.typ -> Ir.exp -> Ir.exp -> Ir.exp = fun t f e -> let fun_typ = T.Func (T.Local, T.Returns, [{T.var="T";T.bound=T.Any}], [show_fun_typ_for (T.Var ("T",0)); T.Array (T.Mut (T.Var ("T",0)))], [T.text]) in - text_exp (CallE - ( { it = VarE "@text_of_array_mut" - ; at = no_region - ; note = { note_typ = fun_typ; note_eff = T.Triv } - } - , [t] - , tupE [f; e] - ) - ) + callE (idE "@text_of_array_mut" fun_typ) [t] (tupE [f; e]) let list_build : 'a -> 'a -> 'a -> 'a list -> 'a list = fun pre sep post xs -> let rec go = function @@ -319,15 +273,12 @@ and t_exp' env = function | PrimE (ShowPrim ot, [exp1]) -> let t' = T.normalize ot in add_type env t'; - let f = idE (show_name_for t') (show_fun_typ_for t') in - CallE (f, [], t_exp env exp1) + (idE (show_name_for t') (show_fun_typ_for t') -*- t_exp env exp1).it | PrimE (p, es) -> PrimE (p, t_exps env es) | AssignE (lexp1, exp2) -> AssignE (t_lexp env lexp1, t_exp env exp2) | FuncE (s, c, id, typbinds, pat, typT, exp) -> FuncE (s, c, id, typbinds, pat, typT, t_exp env exp) - | CallE (exp1, typs, exp2) -> - CallE(t_exp env exp1, typs, t_exp env exp2) | BlockE block -> BlockE (t_block env block) | IfE (exp1, exp2, exp3) -> IfE (t_exp env exp1, t_exp env exp2, t_exp env exp3) diff --git a/src/ir_passes/tailcall.ml b/src/ir_passes/tailcall.ml index 4ee9d63553a..78777c9e7e9 100644 --- a/src/ir_passes/tailcall.ml +++ b/src/ir_passes/tailcall.ml @@ -94,16 +94,14 @@ and assignEs vars exp : dec list = and exp' env e : exp' = match e.it with | VarE _ | LitE _ -> e.it | AssignE (e1, e2) -> AssignE (lexp env e1, exp env e2) - | CallE (e1, insts, e2) -> - begin - match e1.it, env with - | VarE f1, { tail_pos = true; - info = Some { func; typ_binds; temps; label; tail_called } } - when f1 = func && are_generic_insts typ_binds insts -> - tail_called := true; - (blockE (assignEs temps (exp env e2)) - (breakE label (tupE []))).it - | _,_-> CallE (exp env e1, insts, exp env e2) + | PrimE (CallPrim insts, [e1; e2]) -> + begin match e1.it, env with + | VarE f1, { tail_pos = true; + info = Some { func; typ_binds; temps; label; tail_called } } + when f1 = func && are_generic_insts typ_binds insts -> + tail_called := true; + (blockE (assignEs temps (exp env e2)) (breakE label unitE)).it + | _,_-> PrimE (CallPrim insts, [exp env e1; exp env e2]) end | BlockE (ds, e) -> BlockE (block env ds e) | IfE (e1, e2, e3) -> IfE (exp env e1, tailexp env e2, tailexp env e3) diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 0b5b7234287..6e53269d135 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -123,11 +123,9 @@ and exp' at note = function I.PrimE (I.OtherPrim p, [exp e]) | S.CallE (e1, inst, e2) -> let t = e1.Source.note.S.note_typ in - if T.is_non t - then unreachableE.it - else - let inst = List.map (fun t -> t.Source.note) inst in - I.CallE (exp e1, inst, exp e2) + if T.is_non t then unreachableE.it else + let inst = List.map (fun t -> t.Source.note) inst in + I.PrimE (I.CallPrim inst, [exp e1; exp e2]) | S.BlockE [] -> unitE.it | S.BlockE [{it = S.ExpD e; _}] -> (exp e).it | S.BlockE ds -> I.BlockE (block (T.is_unit note.I.note_typ) ds) From 3c5ded9968c5fd5713c8f43da7ac0a8d28ee19a4 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 15 Jan 2020 12:13:26 +0100 Subject: [PATCH 0939/1176] Check_ir: No `gather_scope` (#1103) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit in another PR, I had to remove this to make it typecheck, and removing it does not break any tests. It also doesn’t make sense to me: I would expect ``` { type T = Int; let x = {} : {type T = Int;} foo () : T = 5; } ``` be legal. In the IR, type aliases don’t need to have a definition site any more, so this is removing it. --- src/ir_def/check_ir.ml | 56 +++++++++++++++--------------------------- 1 file changed, 20 insertions(+), 36 deletions(-) diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index c4cdef8ad7f..2d3baab559d 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -29,22 +29,24 @@ let immute_typ p = (* Scope *) type val_env = T.typ T.Env.t -type con_env = T.ConSet.t type scope = { val_env : val_env; - con_env : con_env; } let empty_scope : scope = { val_env = T.Env.empty; - con_env = T.ConSet.empty } (* Contexts (internal) *) type lab_env = T.typ T.Env.t type ret_env = T.typ option +(* the con_env tracks + - which abstract types (type parameters) are in scope + - which type aliases we are currently unfolding (to break recursion) +*) +type con_env = T.ConSet.t type env = { flavor : Ir.flavor; @@ -58,7 +60,7 @@ type env = let env_of_scope scope flavor : env = { flavor; vals = scope.Scope.val_env; - cons = scope.Scope.con_env; + cons = T.ConSet.empty; labs = T.Env.empty; rets = None; async = false; @@ -91,7 +93,6 @@ let add_typs c cs = let adjoin c scope = { c with vals = T.Env.adjoin c.vals scope.val_env; - cons = T.ConSet.(*disjoint_*)union c.cons scope.con_env; } let adjoin_vals c ve = {c with vals = T.Env.adjoin c.vals ve} @@ -158,37 +159,37 @@ let rec check_typ env typ : unit = List.iter (check_typ env) typs | T.Func (sort, control, binds, ts1, ts2) -> let cs, ce = check_typ_binds env binds in - let env' = adjoin_cons env ce in + let env = adjoin_cons env ce in let ts = List.map (fun c -> T.Con (c, [])) cs in let ts1 = List.map (T.open_ ts) ts1 in let ts2 = List.map (T.open_ ts) ts2 in - List.iter (check_typ env') ts1; - List.iter (check_typ env') ts2; + List.iter (check_typ env) ts1; + List.iter (check_typ env) ts2; if T.is_shared_sort sort then begin List.iter (fun t -> check_shared env no_region t) ts1; match control with | T.Returns -> - check env' no_region (sort = T.Shared T.Write) + check env no_region (sort = T.Shared T.Write) "one-shot query function pointless"; - check env' no_region (ts2 = []) + check env no_region (ts2 = []) "one-shot function cannot have non-unit return types:\n %s" (T.string_of_typ_expand (T.seq ts2)); | T.Promises -> check env no_region env.flavor.Ir.has_async_typ "promising function in post-async flavor"; - check env' no_region (sort <> T.Local) + check env no_region (sort <> T.Local) "promising function cannot be local:\n %s" (T.string_of_typ_expand (T.seq ts)); - check env' no_region (List.for_all T.shared ts) + check env no_region (List.for_all T.shared ts) "message result is not sharable:\n %s" (T.string_of_typ_expand (T.seq ts)) | T.Replies -> check env no_region (not env.flavor.Ir.has_async_typ) "replying function in pre-async flavor"; - check env' no_region (sort <> T.Local) + check env no_region (sort <> T.Local) "replying function cannot be local:\n %s" (T.string_of_typ_expand (T.seq ts)); - check env' no_region (List.for_all T.shared ts) + check env no_region (List.for_all T.shared ts) "message result is not sharable:\n %s" (T.string_of_typ_expand (T.seq ts)) end else - check env' no_region (control = T.Returns) + check env no_region (control = T.Returns) "promising function cannot be local:\n %s" (T.string_of_typ_expand typ); | T.Opt typ -> check_typ env typ @@ -845,8 +846,7 @@ and check_dec env dec = check_exp env exp; typ exp <: T.as_immut t0 | TypD c -> - check (T.ConSet.mem c env.cons) "free type constructor"; - check_con env c + check_con {env with cons = T.ConSet.add c env.cons} c; and check_decs env decs = List.iter (check_dec env) decs; @@ -858,30 +858,14 @@ and gather_dec env scope dec : scope = match dec.it with | LetD (pat, exp) -> let ve = gather_pat env scope.val_env pat in - let ce' = gather_typ env scope.con_env exp.note.note_typ in - { val_env = ve; con_env = ce'} + { val_env = ve } | VarD (id, exp) -> check env dec.at (not (T.Env.mem id scope.val_env)) "duplicate variable definition in block"; let ve = T.Env.add id (T.Mut (typ exp)) scope.val_env in - { scope with val_env = ve} - | TypD c -> - check env dec.at - (not (T.ConSet.mem c scope.con_env)) - "duplicate definition of type in block"; - let ce' = T.ConSet.disjoint_add c scope.con_env in - { scope with con_env = ce' } - -and gather_typ env ce typ = - match typ with - | T.Obj(_, fs) -> - List.fold_right (fun {T.lab;T.typ = typ1} ce -> - match typ1 with - | T.Typ c -> T.ConSet.add c ce - | _ -> gather_typ env ce typ1 - ) fs ce - | _ -> ce + { val_env = ve} + | TypD c -> scope (* Programs *) From 3707f377d479acf4979458d49840bfb69576351c Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 15 Jan 2020 12:49:21 +0100 Subject: [PATCH 0940/1176] Test suite: Use query more often (#1114) becaues of the hack in #1105, running ingress messages is pretty slow now. This speeds up the test suite by using queries more often. --- test/run-drun/idl-any.mo | 58 +++++++++---------- test/run-drun/idl-field-escape.mo | 16 ++--- test/run-drun/idl-nary.mo | 38 ++++++------ test/run-drun/idl-option.mo | 8 +-- test/run-drun/idl-pair.mo | 4 +- test/run-drun/idl-record.mo | 18 +++--- test/run-drun/ok/idl-any.drun-run.ok | 56 +++++++++--------- test/run-drun/ok/idl-any.ic-stub-run.ok | 56 +++++++++--------- test/run-drun/ok/idl-field-escape.drun-run.ok | 8 +-- .../ok/idl-field-escape.ic-stub-run.ok | 8 +-- test/run-drun/ok/idl-nary.drun-run.ok | 22 +++---- test/run-drun/ok/idl-nary.ic-stub-run.ok | 24 ++++---- test/run-drun/ok/idl-option.drun-run.ok | 6 +- test/run-drun/ok/idl-option.ic-stub-run.ok | 6 +- test/run-drun/ok/idl-pair.drun-run.ok | 2 +- test/run-drun/ok/idl-pair.ic-stub-run.ok | 2 +- test/run-drun/ok/idl-record.drun-run.ok | 8 +-- test/run-drun/ok/idl-record.ic-stub-run.ok | 8 +-- 18 files changed, 173 insertions(+), 175 deletions(-) diff --git a/test/run-drun/idl-any.mo b/test/run-drun/idl-any.mo index a8e2efc8de5..d20c79850da 100644 --- a/test/run-drun/idl-any.mo +++ b/test/run-drun/idl-any.mo @@ -2,42 +2,42 @@ import Prim "mo:prim"; // This tests checks that the IDL decoder properly // zooms past the any argument and finds the beginning of the string actor { - public func any(_ : Any, x : Text) : async () { + public query func any(_ : Any, x : Text) : async () { Prim.debugPrint ("ok: " # x); }; } // Primitive values: -//CALL ingress any 0x4449444C00027f7103466F6F -//CALL ingress any 0x4449444C00027e710103466F6F -//CALL ingress any 0x4449444C00027d718080800803466F6F -//CALL ingress any 0x4449444C00027c718080800803466F6F -//CALL ingress any 0x4449444C00027b71AB03466F6F -//CALL ingress any 0x4449444C00027a71ABCD03466F6F -//CALL ingress any 0x4449444C00027971DEADBEEF03466F6F -//CALL ingress any 0x4449444C00027871DEADBEEFCAFFEE6603466F6F -//CALL ingress any 0x4449444C00027771AB03466F6F -//CALL ingress any 0x4449444C00027671ABCD03466F6F -//CALL ingress any 0x4449444C00027571DEADBEEF03466F6F -//CALL ingress any 0x4449444C00027471DEADBEEFCAFFEE6603466F6F -//CALL ingress any 0x4449444C00027371DEADBEEF03466F6F -//CALL ingress any 0x4449444C00027271DEADBEEFCAFFEE6603466F6F -//CALL ingress any 0x4449444C0002717103466F6F03466F6F -//CALL ingress any 0x4449444C0002707103466F6F +//CALL query any 0x4449444C00027f7103466F6F +//CALL query any 0x4449444C00027e710103466F6F +//CALL query any 0x4449444C00027d718080800803466F6F +//CALL query any 0x4449444C00027c718080800803466F6F +//CALL query any 0x4449444C00027b71AB03466F6F +//CALL query any 0x4449444C00027a71ABCD03466F6F +//CALL query any 0x4449444C00027971DEADBEEF03466F6F +//CALL query any 0x4449444C00027871DEADBEEFCAFFEE6603466F6F +//CALL query any 0x4449444C00027771AB03466F6F +//CALL query any 0x4449444C00027671ABCD03466F6F +//CALL query any 0x4449444C00027571DEADBEEF03466F6F +//CALL query any 0x4449444C00027471DEADBEEFCAFFEE6603466F6F +//CALL query any 0x4449444C00027371DEADBEEF03466F6F +//CALL query any 0x4449444C00027271DEADBEEFCAFFEE6603466F6F +//CALL query any 0x4449444C0002717103466F6F03466F6F +//CALL query any 0x4449444C0002707103466F6F // Composite values: -//CALL ingress any 0x4449444C016e710200710003466F6F -//CALL ingress any 0x4449444C016e710200710103466F6F03466F6F -//CALL ingress any 0x4449444C016d710200710003466F6F -//CALL ingress any 0x4449444C016d710200710103466F6F03466F6F -//CALL ingress any 0x4449444C016d71020071020003466F6F03466F6F -//CALL ingress any 0x4449444C016c0002007103466F6F -//CALL ingress any 0x4449444C016c01800175020071DEADBEEF03466F6F -//CALL ingress any 0x4449444C016c02007180017502007101A0DEADBEEF03466F6F -//CALL ingress any 0x4449444C016b0180017502007100DEADBEEF03466F6F -//CALL ingress any 0x4449444C016b0200718001750200710001A003466F6F -//CALL ingress any 0x4449444C016b02007180017502007101DEADBEEF03466F6F -//CALL ingress any 0x4449444C016602ABCD0200710400DEADBEEF03466F6F +//CALL query any 0x4449444C016e710200710003466F6F +//CALL query any 0x4449444C016e710200710103466F6F03466F6F +//CALL query any 0x4449444C016d710200710003466F6F +//CALL query any 0x4449444C016d710200710103466F6F03466F6F +//CALL query any 0x4449444C016d71020071020003466F6F03466F6F +//CALL query any 0x4449444C016c0002007103466F6F +//CALL query any 0x4449444C016c01800175020071DEADBEEF03466F6F +//CALL query any 0x4449444C016c02007180017502007101A0DEADBEEF03466F6F +//CALL query any 0x4449444C016b0180017502007100DEADBEEF03466F6F +//CALL query any 0x4449444C016b0200718001750200710001A003466F6F +//CALL query any 0x4449444C016b02007180017502007101DEADBEEF03466F6F +//CALL query any 0x4449444C016602ABCD0200710400DEADBEEF03466F6F //SKIP run //SKIP run-ir diff --git a/test/run-drun/idl-field-escape.mo b/test/run-drun/idl-field-escape.mo index 0ad9549a16b..89124f0a339 100644 --- a/test/run-drun/idl-field-escape.mo +++ b/test/run-drun/idl-field-escape.mo @@ -7,24 +7,24 @@ actor { async_ : Text }; - public func out() : async R { + public query func out() : async R { { _0_ = 0xFFFF; _1_ = 0x1000; async_ = "XXX" } }; - public func foo1() : async {foo_ : ()} { { foo_ = () } }; - public func foo2() : async {foo : ()} { { foo = () } }; + public query func foo1() : async {foo_ : ()} { { foo_ = () } }; + public query func foo2() : async {foo : ()} { { foo = () } }; - public func input(r : R) : async () { + public query func input(r : R) : async () { }; } -//CALL ingress foo1 0x4449444C0000 -//CALL ingress foo2 0x4449444C0000 -//CALL ingress out 0x4449444C0000 -//CALL ingress input 0x4449444c016c03007c017dbcfef7b102710100ffff03802003585858 +//CALL query foo1 0x4449444C0000 +//CALL query foo2 0x4449444C0000 +//CALL query out 0x4449444C0000 +//CALL query input 0x4449444c016c03007c017dbcfef7b102710100ffff03802003585858 //SKIP run //SKIP run-ir diff --git a/test/run-drun/idl-nary.mo b/test/run-drun/idl-nary.mo index e441147eac4..9cc15e1708b 100644 --- a/test/run-drun/idl-nary.mo +++ b/test/run-drun/idl-nary.mo @@ -1,56 +1,56 @@ actor { - public func two(x:Text, y:Text) : async (Text, Text) { + public query func two(x:Text, y:Text) : async (Text, Text) { (x, y) }; - public func three(x:Text, y:Text, z: Text) : async (Text, Text, Text) { + public query func three(x:Text, y:Text, z: Text) : async (Text, Text, Text) { (x, y, z) }; - public func four(x:Text, y:Text, z: Text, w: Text) : async (Text, Text, Text, Text) { + public query func four(x:Text, y:Text, z: Text, w: Text) : async (Text, Text, Text, Text) { (x, y, z, w) }; - public func mkRecord() : async ((Text, Text, Text, Text)) { + public query func mkRecord() : async ((Text, Text, Text, Text)) { ("One", "Two", "Three", "Four") }; - public func unary1((x:Text, y:Text, z: Text, w: Text)) : async ((Text, Text, Text, Text)) { + public query func unary1((x:Text, y:Text, z: Text, w: Text)) : async ((Text, Text, Text, Text)) { (x, y, z, w) }; - public func unary2(xyzw : (Text, Text, Text, Text)) : async ((Text, Text, Text, Text)) { + public query func unary2(xyzw : (Text, Text, Text, Text)) : async ((Text, Text, Text, Text)) { xyzw }; - public func unary3(xyzw : (Text, Text, Text, Text)) : async ((Text, Text, Text, Text)) { + public query func unary3(xyzw : (Text, Text, Text, Text)) : async ((Text, Text, Text, Text)) { xyzw }; type T = (Text, Text, Text, Text); - public func unary4(xyzw : (Text, Text, Text, Text)) : async T { + public query func unary4(xyzw : (Text, Text, Text, Text)) : async T { xyzw } } -//CALL ingress two "DIDL\x00\x02\x71\x71\x03One\x03Two" -//CALL ingress three "DIDL\x00\x03\x71\x71\x71\x03One\x03Two\x05Three" -//CALL ingress four "DIDL\x00\x04\x71\x71\x71\x71\x03One\x03Two\x05Three\x04Four" -//CALL ingress mkRecord "DIDL\x00\x00" -//CALL ingress unary1 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 -//CALL ingress unary2 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 -//CALL ingress unary3 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 -//CALL ingress unary4 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 +//CALL query two "DIDL\x00\x02\x71\x71\x03One\x03Two" +//CALL query three "DIDL\x00\x03\x71\x71\x71\x03One\x03Two\x05Three" +//CALL query four "DIDL\x00\x04\x71\x71\x71\x71\x03One\x03Two\x05Three\x04Four" +//CALL query mkRecord "DIDL\x00\x00" +//CALL query unary1 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 +//CALL query unary2 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 +//CALL query unary3 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 +//CALL query unary4 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 // too few arguments -//CALL ingress three "DIDL\x00\x02\x71\x71\x03One\x03Two" +//CALL query three "DIDL\x00\x02\x71\x71\x03One\x03Two" // extra bytes (bad) -//CALL ingress three "DIDL\x00\x03\x71\x71\x71\x03One\x03Two\x05ThreeEXTRABYTES" +//CALL query three "DIDL\x00\x03\x71\x71\x71\x03One\x03Two\x05ThreeEXTRABYTES" // extra arguments (ok) -//CALL ingress four "DIDL\x00\x05\x71\x71\x71\x71\x71\x03One\x03Two\x05Three\x04Four\x04Five" +//CALL query four "DIDL\x00\x05\x71\x71\x71\x71\x71\x03One\x03Two\x05Three\x04Four\x04Five" //SKIP run //SKIP run-ir diff --git a/test/run-drun/idl-option.mo b/test/run-drun/idl-option.mo index 543001cfc15..0e4f7902c42 100644 --- a/test/run-drun/idl-option.mo +++ b/test/run-drun/idl-option.mo @@ -2,7 +2,7 @@ import Prim "mo:prim"; // This test checks that the IDL decoder can // do the subtyping from null to option actor { - public func any(o : ?Text) : async () { + public query func any(o : ?Text) : async () { switch o { case null Prim.debugPrint ("ok: null"); case (?x) Prim.debugPrint ("ok: " # x); @@ -10,9 +10,9 @@ actor { }; } -//CALL ingress any 0x4449444C00017f -//CALL ingress any 0x4449444C016e71010000 -//CALL ingress any 0x4449444C016e7101000103466F6F +//CALL query any 0x4449444C00017f +//CALL query any 0x4449444C016e71010000 +//CALL query any 0x4449444C016e7101000103466F6F //SKIP run //SKIP run-ir diff --git a/test/run-drun/idl-pair.mo b/test/run-drun/idl-pair.mo index 78ffddf8bb9..67a3587414d 100644 --- a/test/run-drun/idl-pair.mo +++ b/test/run-drun/idl-pair.mo @@ -1,11 +1,11 @@ type Pair = (Int,Int); actor { - public func len2(x:Text, y:Text) : async Pair { + public query func len2(x:Text, y:Text) : async Pair { (x.len(), y.len()) } } -//CALL ingress len2 "DIDL\x00\x02\x71\x71\x02Hi\x05World" +//CALL query len2 "DIDL\x00\x02\x71\x71\x02Hi\x05World" //SKIP run //SKIP run-ir diff --git a/test/run-drun/idl-record.mo b/test/run-drun/idl-record.mo index 95dc5231ad9..6006603b511 100644 --- a/test/run-drun/idl-record.mo +++ b/test/run-drun/idl-record.mo @@ -3,36 +3,36 @@ import Prim "mo:prim"; // do the subtyping from received many-field record // to a double-field one (field names are in hash order) actor { - public func pair(o : (Text, Int)) : async () { + public query func pair(o : (Text, Int)) : async () { switch o { case (content, num) Prim.debugPrint ("ok: " # debug_show num); } }; - public func record(o : {content: Text; value : Int}) : async () { + public query func record(o : {content: Text; value : Int}) : async () { switch o { case {content} Prim.debugPrint ("ok: " # content); } }; - public func record1(o : {value : Int; byte : Int8}) : async () { + public query func record1(o : {value : Int; byte : Int8}) : async () { switch o { case {byte} Prim.debugPrint ("ok: " # debug_show byte); } }; - public func record2(o : {content: Text; value : Int}, follower : Int8) : async Int8 { + public query func record2(o : {content: Text; value : Int}, follower : Int8) : async Int8 { switch o { case {content} { Prim.debugPrint ("ok: " # " " # content # " " # debug_show follower); follower }; } }; } -//CALL ingress pair 0x4449444C016C020071017C010004486579212A -//CALL ingress record 0x4449444C016C02b99adecb0171f1fee18d037C010004486579212A +//CALL query pair 0x4449444C016C020071017C010004486579212A +//CALL query record 0x4449444C016C02b99adecb0171f1fee18d037C010004486579212A // SKIPPED -// CALL ingress record1 0x4449444C016C0388be8c890477b99adecb0171f1fee18d037C010004486579212A19 +// CALL query record1 0x4449444C016C0388be8c890477b99adecb0171f1fee18d037C010004486579212A19 // needs to jump over redundant `content` field -//CALL ingress record1 0x4449444C016C03b99adecb0171f1fee18d037C88be8c890477010004486579212A19 +//CALL query record1 0x4449444C016C03b99adecb0171f1fee18d037C88be8c890477010004486579212A19 // needs to jump over redundant trailing `byte` field -//CALL ingress record2 0x4449444C016C03b99adecb0171f1fee18d037C88be8c89047702007704486579212A1819 +//CALL query record2 0x4449444C016C03b99adecb0171f1fee18d037C88be8c89047702007704486579212A1819 //SKIP run //SKIP run-ir diff --git a/test/run-drun/ok/idl-any.drun-run.ok b/test/run-drun/ok/idl-any.drun-run.ok index 4f76ce5ac28..c4d42e52ed1 100644 --- a/test/run-drun/ok/idl-any.drun-run.ok +++ b/test/run-drun/ok/idl-any.drun-run.ok @@ -1,57 +1,57 @@ ingress(0) System debug.print: ok: Foo -ingress(1) Completed: Canister: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(2) Completed: Canister: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(3) Completed: Canister: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(4) Completed: Canister: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(5) Completed: Canister: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(6) Completed: Canister: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(7) Completed: Canister: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(8) Completed: Canister: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(9) Completed: Canister: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(10) Completed: Canister: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(11) Completed: Canister: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(12) Completed: Canister: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(13) Completed: Canister: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(14) Completed: Canister: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(15) Completed: Canister: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(16) Completed: Canister: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(17) Completed: Canister: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(18) Completed: Canister: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(19) Completed: Canister: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(20) Completed: Canister: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(21) Completed: Canister: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(22) Completed: Canister: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(23) Completed: Canister: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(24) Completed: Canister: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(25) Completed: Canister: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(26) Completed: Canister: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(27) Completed: Canister: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(28) Completed: Canister: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-any.ic-stub-run.ok b/test/run-drun/ok/idl-any.ic-stub-run.ok index 894b48fff3d..28b2ef992b3 100644 --- a/test/run-drun/ok/idl-any.ic-stub-run.ok +++ b/test/run-drun/ok/idl-any.ic-stub-run.ok @@ -2,87 +2,87 @@ ← completed: canister-id = 0x0000000000000400 → install ← completed -→ update any(0x4449444c00027f7103466f6f) +→ query any(0x4449444c00027f7103466f6f) debug.print: ok: Foo ← completed: 0x4449444c0000 -→ update any(0x4449444c00027e710103466f6f) +→ query any(0x4449444c00027e710103466f6f) debug.print: ok: Foo ← completed: 0x4449444c0000 -→ update any(0x4449444c00027d718080800803466f6f) +→ query any(0x4449444c00027d718080800803466f6f) debug.print: ok: Foo ← completed: 0x4449444c0000 -→ update any(0x4449444c00027c718080800803466f6f) +→ query any(0x4449444c00027c718080800803466f6f) debug.print: ok: Foo ← completed: 0x4449444c0000 -→ update any(0x4449444c00027b71ab03466f6f) +→ query any(0x4449444c00027b71ab03466f6f) debug.print: ok: Foo ← completed: 0x4449444c0000 -→ update any(0x4449444c00027a71abcd03466f6f) +→ query any(0x4449444c00027a71abcd03466f6f) debug.print: ok: Foo ← completed: 0x4449444c0000 -→ update any(0x4449444c00027971deadbeef03466f6f) +→ query any(0x4449444c00027971deadbeef03466f6f) debug.print: ok: Foo ← completed: 0x4449444c0000 -→ update any(0x4449444c00027871deadbeefcaffee6603466f6f) +→ query any(0x4449444c00027871deadbeefcaffee6603466f6f) debug.print: ok: Foo ← completed: 0x4449444c0000 -→ update any(0x4449444c00027771ab03466f6f) +→ query any(0x4449444c00027771ab03466f6f) debug.print: ok: Foo ← completed: 0x4449444c0000 -→ update any(0x4449444c00027671abcd03466f6f) +→ query any(0x4449444c00027671abcd03466f6f) debug.print: ok: Foo ← completed: 0x4449444c0000 -→ update any(0x4449444c00027571deadbeef03466f6f) +→ query any(0x4449444c00027571deadbeef03466f6f) debug.print: ok: Foo ← completed: 0x4449444c0000 -→ update any(0x4449444c00027471deadbeefcaffee6603466f6f) +→ query any(0x4449444c00027471deadbeefcaffee6603466f6f) debug.print: ok: Foo ← completed: 0x4449444c0000 -→ update any(0x4449444c00027371deadbeef03466f6f) +→ query any(0x4449444c00027371deadbeef03466f6f) debug.print: ok: Foo ← completed: 0x4449444c0000 -→ update any(0x4449444c00027271deadbeefcaffee6603466f6f) +→ query any(0x4449444c00027271deadbeefcaffee6603466f6f) debug.print: ok: Foo ← completed: 0x4449444c0000 -→ update any(0x4449444c0002717103466f6f03466f6f) +→ query any(0x4449444c0002717103466f6f03466f6f) debug.print: ok: Foo ← completed: 0x4449444c0000 -→ update any(0x4449444c0002707103466f6f) +→ query any(0x4449444c0002707103466f6f) debug.print: ok: Foo ← completed: 0x4449444c0000 -→ update any(0x4449444c016e710200710003466f6f) +→ query any(0x4449444c016e710200710003466f6f) debug.print: ok: Foo ← completed: 0x4449444c0000 -→ update any(0x4449444c016e710200710103466f6f03466f6f) +→ query any(0x4449444c016e710200710103466f6f03466f6f) debug.print: ok: Foo ← completed: 0x4449444c0000 -→ update any(0x4449444c016d710200710003466f6f) +→ query any(0x4449444c016d710200710003466f6f) debug.print: ok: Foo ← completed: 0x4449444c0000 -→ update any(0x4449444c016d710200710103466f6f03466f6f) +→ query any(0x4449444c016d710200710103466f6f03466f6f) debug.print: ok: Foo ← completed: 0x4449444c0000 -→ update any(0x4449444c016d71020071020003466f6f03466f6f) +→ query any(0x4449444c016d71020071020003466f6f03466f6f) debug.print: ok: Foo ← completed: 0x4449444c0000 -→ update any(0x4449444c016c0002007103466f6f) +→ query any(0x4449444c016c0002007103466f6f) debug.print: ok: Foo ← completed: 0x4449444c0000 -→ update any(0x4449444c016c01800175020071deadbeef03466f6f) +→ query any(0x4449444c016c01800175020071deadbeef03466f6f) debug.print: ok: Foo ← completed: 0x4449444c0000 -→ update any(0x4449444c016c02007180017502007101a0deadbeef03466f6f) +→ query any(0x4449444c016c02007180017502007101a0deadbeef03466f6f) debug.print: ok: Foo ← completed: 0x4449444c0000 -→ update any(0x4449444c016b0180017502007100deadbeef03466f6f) +→ query any(0x4449444c016b0180017502007100deadbeef03466f6f) debug.print: ok: Foo ← completed: 0x4449444c0000 -→ update any(0x4449444c016b0200718001750200710001a003466f6f) +→ query any(0x4449444c016b0200718001750200710001a003466f6f) debug.print: ok: Foo ← completed: 0x4449444c0000 -→ update any(0x4449444c016b02007180017502007101deadbeef03466f6f) +→ query any(0x4449444c016b02007180017502007101deadbeef03466f6f) debug.print: ok: Foo ← completed: 0x4449444c0000 -→ update any(0x4449444c016602abcd0200710400deadbeef03466f6f) +→ query any(0x4449444c016602abcd0200710400deadbeef03466f6f) debug.print: ok: Foo ← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-field-escape.drun-run.ok b/test/run-drun/ok/idl-field-escape.drun-run.ok index 81c657b619a..3ac0b008387 100644 --- a/test/run-drun/ok/idl-field-escape.drun-run.ok +++ b/test/run-drun/ok/idl-field-escape.drun-run.ok @@ -1,5 +1,5 @@ ingress(0) System -ingress(1) Completed: Canister: Payload: 0x4449444c016c01868eb7027f0100 -ingress(2) Completed: Canister: Payload: 0x4449444c016c01868eb7027f0100 -ingress(3) Completed: Canister: Payload: 0x4449444c016c03007c017dbcfef7b102710100ffff03802003585858 -ingress(4) Completed: Canister: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c016c01868eb7027f0100 +Ok: Payload: 0x4449444c016c01868eb7027f0100 +Ok: Payload: 0x4449444c016c03007c017dbcfef7b102710100ffff03802003585858 +Ok: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-field-escape.ic-stub-run.ok b/test/run-drun/ok/idl-field-escape.ic-stub-run.ok index fa73a9cfd53..a38c7fe98bc 100644 --- a/test/run-drun/ok/idl-field-escape.ic-stub-run.ok +++ b/test/run-drun/ok/idl-field-escape.ic-stub-run.ok @@ -2,11 +2,11 @@ ← completed: canister-id = 0x0000000000000400 → install ← completed -→ update foo1(0x4449444c0000) +→ query foo1(0x4449444c0000) ← completed: 0x4449444c016c01868eb7027f0100 -→ update foo2(0x4449444c0000) +→ query foo2(0x4449444c0000) ← completed: 0x4449444c016c01868eb7027f0100 -→ update out(0x4449444c0000) +→ query out(0x4449444c0000) ← completed: 0x4449444c016c03007c017dbcfef7b102710100ffff03802003585858 -→ update input(0x4449444c016c03007c017dbcfef7b102710100ffff03802003585858) +→ query input(0x4449444c016c03007c017dbcfef7b102710100ffff03802003585858) ← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-nary.drun-run.ok b/test/run-drun/ok/idl-nary.drun-run.ok index 4402c0df173..c5d9ec994f4 100644 --- a/test/run-drun/ok/idl-nary.drun-run.ok +++ b/test/run-drun/ok/idl-nary.drun-run.ok @@ -1,12 +1,12 @@ ingress(0) System -ingress(1) Completed: Canister: Payload: 0x4449444c00027171034f6e650354776f -ingress(2) Completed: Canister: Payload: 0x4449444c0003717171034f6e650354776f055468726565 -ingress(3) Completed: Canister: Payload: 0x4449444c000471717171034f6e650354776f05546872656504466f7572 -ingress(4) Completed: Canister: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 -ingress(5) Completed: Canister: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 -ingress(6) Completed: Canister: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 -ingress(7) Completed: Canister: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 -ingress(8) Completed: Canister: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 -ingress(9) Err: IC0503: Canister 1125899906842624 trapped explicitly: IDL error: too few arguments Text,Text,Text -ingress(10) Err: IC0503: Canister 1125899906842624 trapped explicitly: IDL error: left-over bytes Text,Text,Text -ingress(11) Completed: Canister: Payload: 0x4449444c000471717171034f6e650354776f05546872656504466f7572 +Ok: Payload: 0x4449444c00027171034f6e650354776f +Ok: Payload: 0x4449444c0003717171034f6e650354776f055468726565 +Ok: Payload: 0x4449444c000471717171034f6e650354776f05546872656504466f7572 +Ok: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 +Ok: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 +Ok: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 +Ok: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 +Ok: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 +Err: IC0503: Canister 1125899906842624 trapped explicitly: IDL error: too few arguments Text,Text,Text +Err: IC0503: Canister 1125899906842624 trapped explicitly: IDL error: left-over bytes Text,Text,Text +Ok: Payload: 0x4449444c000471717171034f6e650354776f05546872656504466f7572 diff --git a/test/run-drun/ok/idl-nary.ic-stub-run.ok b/test/run-drun/ok/idl-nary.ic-stub-run.ok index 53330a2c4ac..cd94387094c 100644 --- a/test/run-drun/ok/idl-nary.ic-stub-run.ok +++ b/test/run-drun/ok/idl-nary.ic-stub-run.ok @@ -2,27 +2,25 @@ ← completed: canister-id = 0x0000000000000400 → install ← completed -→ update two(0x4449444c00027171034f6e650354776f) +→ query two(0x4449444c00027171034f6e650354776f) ← completed: 0x4449444c00027171034f6e650354776f -→ update three(0x4449444c0003717171034f6e650354776f055468726565) +→ query three(0x4449444c0003717171034f6e650354776f055468726565) ← completed: 0x4449444c0003717171034f6e650354776f055468726565 -→ update four(0x4449444c000471717171034f6e650354776f05546872656504466f7572) +→ query four(0x4449444c000471717171034f6e650354776f05546872656504466f7572) ← completed: 0x4449444c000471717171034f6e650354776f05546872656504466f7572 -→ update mkRecord(0x4449444c0000) +→ query mkRecord(0x4449444c0000) ← completed: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 -→ update unary1(0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572) +→ query unary1(0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572) ← completed: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 -→ update unary2(0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572) +→ query unary2(0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572) ← completed: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 -→ update unary3(0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572) +→ query unary3(0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572) ← completed: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 -→ update unary4(0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572) +→ query unary4(0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572) ← completed: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 -→ update three(0x4449444c00027171034f6e650354776f) -Trap: EvalTrapError :0.1 "canister trapped explicitly: IDL error: too few arguments Text,Text,Text" +→ query three(0x4449444c00027171034f6e650354776f) ← rejected (RC_CANISTER_ERROR): canister trapped: EvalTrapError :0.1 "canister trapped explicitly: IDL error: too few arguments Text,Text,Text" -→ update three(0x4449444c0003717171034f6e650354776f05546872656545585452414259544553) -Trap: EvalTrapError :0.1 "canister trapped explicitly: IDL error: left-over bytes Text,Text,Text" +→ query three(0x4449444c0003717171034f6e650354776f05546872656545585452414259544553) ← rejected (RC_CANISTER_ERROR): canister trapped: EvalTrapError :0.1 "canister trapped explicitly: IDL error: left-over bytes Text,Text,Text" -→ update four(0x4449444c00057171717171034f6e650354776f05546872656504466f75720446697665) +→ query four(0x4449444c00057171717171034f6e650354776f05546872656504466f75720446697665) ← completed: 0x4449444c000471717171034f6e650354776f05546872656504466f7572 diff --git a/test/run-drun/ok/idl-option.drun-run.ok b/test/run-drun/ok/idl-option.drun-run.ok index 028b1b4aa2e..6e6ad23462f 100644 --- a/test/run-drun/ok/idl-option.drun-run.ok +++ b/test/run-drun/ok/idl-option.drun-run.ok @@ -1,7 +1,7 @@ ingress(0) System debug.print: ok: null -ingress(1) Completed: Canister: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0000 debug.print: ok: null -ingress(2) Completed: Canister: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0000 debug.print: ok: Foo -ingress(3) Completed: Canister: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-option.ic-stub-run.ok b/test/run-drun/ok/idl-option.ic-stub-run.ok index 5a164f4cb11..850f2772096 100644 --- a/test/run-drun/ok/idl-option.ic-stub-run.ok +++ b/test/run-drun/ok/idl-option.ic-stub-run.ok @@ -2,12 +2,12 @@ ← completed: canister-id = 0x0000000000000400 → install ← completed -→ update any(0x4449444c00017f) +→ query any(0x4449444c00017f) debug.print: ok: null ← completed: 0x4449444c0000 -→ update any(0x4449444c016e71010000) +→ query any(0x4449444c016e71010000) debug.print: ok: null ← completed: 0x4449444c0000 -→ update any(0x4449444c016e7101000103466f6f) +→ query any(0x4449444c016e7101000103466f6f) debug.print: ok: Foo ← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-pair.drun-run.ok b/test/run-drun/ok/idl-pair.drun-run.ok index fd1ef07bac7..428fcb5b372 100644 --- a/test/run-drun/ok/idl-pair.drun-run.ok +++ b/test/run-drun/ok/idl-pair.drun-run.ok @@ -1,2 +1,2 @@ ingress(0) System -ingress(1) Completed: Canister: Payload: 0x4449444c016c02007c017c01000205 +Ok: Payload: 0x4449444c016c02007c017c01000205 diff --git a/test/run-drun/ok/idl-pair.ic-stub-run.ok b/test/run-drun/ok/idl-pair.ic-stub-run.ok index 5fc5fed734d..616b2dc8458 100644 --- a/test/run-drun/ok/idl-pair.ic-stub-run.ok +++ b/test/run-drun/ok/idl-pair.ic-stub-run.ok @@ -2,5 +2,5 @@ ← completed: canister-id = 0x0000000000000400 → install ← completed -→ update len2(0x4449444c0002717102486905576f726c64) +→ query len2(0x4449444c0002717102486905576f726c64) ← completed: 0x4449444c016c02007c017c01000205 diff --git a/test/run-drun/ok/idl-record.drun-run.ok b/test/run-drun/ok/idl-record.drun-run.ok index 933c43b7393..ca2c69d0c27 100644 --- a/test/run-drun/ok/idl-record.drun-run.ok +++ b/test/run-drun/ok/idl-record.drun-run.ok @@ -1,9 +1,9 @@ ingress(0) System debug.print: ok: +42 -ingress(1) Completed: Canister: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0000 debug.print: ok: Hey! -ingress(2) Completed: Canister: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0000 debug.print: ok: +25 -ingress(3) Completed: Canister: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0000 debug.print: ok: Hey! +25 -ingress(4) Completed: Canister: Payload: 0x4449444c00017719 +Ok: Payload: 0x4449444c00017719 diff --git a/test/run-drun/ok/idl-record.ic-stub-run.ok b/test/run-drun/ok/idl-record.ic-stub-run.ok index caf6de36b5b..211ebfdd389 100644 --- a/test/run-drun/ok/idl-record.ic-stub-run.ok +++ b/test/run-drun/ok/idl-record.ic-stub-run.ok @@ -2,15 +2,15 @@ ← completed: canister-id = 0x0000000000000400 → install ← completed -→ update pair(0x4449444c016c020071017c010004486579212a) +→ query pair(0x4449444c016c020071017c010004486579212a) debug.print: ok: +42 ← completed: 0x4449444c0000 -→ update record(0x4449444c016c02b99adecb0171f1fee18d037c010004486579212a) +→ query record(0x4449444c016c02b99adecb0171f1fee18d037c010004486579212a) debug.print: ok: Hey! ← completed: 0x4449444c0000 -→ update record1(0x4449444c016c03b99adecb0171f1fee18d037c88be8c890477010004486579212a19) +→ query record1(0x4449444c016c03b99adecb0171f1fee18d037c88be8c890477010004486579212a19) debug.print: ok: +25 ← completed: 0x4449444c0000 -→ update record2(0x4449444c016c03b99adecb0171f1fee18d037c88be8c89047702007704486579212a1819) +→ query record2(0x4449444c016c03b99adecb0171f1fee18d037c88be8c89047702007704486579212a1819) debug.print: ok: Hey! +25 ← completed: 0x4449444c00017719 From 1e38653da7794f0e28e8fd169204dd6722941e65 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 15 Jan 2020 14:36:18 +0100 Subject: [PATCH 0941/1176] IR Interpreter: Support actor ids (#1116) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit this changes the value representation of an `actor …` to use `Text`, i.e. a blob. This matches the RTS. When accessing an actor field, we look up the actor in a global actor map (representing, in a way, the state of the Internet Computer). We trap more eagerly upon missing actors or fields than the platform, but this is ok. This implemented `ActorOfIdBlob` (now trivial), and unblocks #1104. --- src/ir_interpreter/interpret_ir.ml | 39 ++++++++++++++++++++++------- src/ir_interpreter/interpret_ir.mli | 6 +++-- src/pipeline/pipeline.ml | 5 ++-- 3 files changed, 37 insertions(+), 13 deletions(-) diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index a5b8692d8ec..6d84436b4bd 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -17,6 +17,11 @@ type ret_env = V.value V.cont option type throw_env = V.value V.cont option type reply_env = V.value V.cont option type reject_env = V.value V.cont option +type actor_env = V.value V.Env.t ref (* indexed by actor ids *) + +type state = actor_env + +let initial_state () = ref V.Env.empty type scope = val_env @@ -37,14 +42,16 @@ type env = async : bool; caller : V.value; self : V.actor_id; + actor_env : actor_env; } let adjoin_scope s ve = V.Env.adjoin s ve -let adjoin_vals c ve = {c with vals = adjoin_scope c.vals ve} + +let adjoin_vals c ve = {c with vals = V.Env.adjoin c.vals ve} let empty_scope = V.Env.empty -let env_of_scope flags flavor ve = +let env_of_scope flags flavor ae ve = { flags; flavor; vals = ve; @@ -56,6 +63,7 @@ let env_of_scope flags flavor ve = caller = V.Text V.top_id; self = V.top_id; async = false; + actor_env = ae; } let context env = V.Text env.self @@ -89,7 +97,7 @@ let string_of_arg env = function (* Debugging aids *) -let last_env = ref (env_of_scope { trace = false; print_depth = 2} Ir.full_flavor empty_scope) +let last_env = ref (env_of_scope { trace = false; print_depth = 2} Ir.full_flavor (initial_state ()) empty_scope) let last_region = ref Source.no_region let print_exn flags exn = @@ -329,9 +337,20 @@ and interpret_exp_mut env exp (k : V.value V.cont) = k (V.Opt v1) | TagPrim i, [v1] -> k (V.Variant (i, v1)) - | (DotPrim n|ActorDotPrim n), [v1] -> + | DotPrim n, [v1] -> let fs = V.as_obj v1 in k (try find n fs with _ -> assert false) + | ActorDotPrim n, [v1] -> + let id = V.as_text v1 in + begin match V.Env.find_opt id !(env.actor_env) with + (* not quite correct: On the platform, you can invoke and get a reject *) + | None -> trap exp.at "Unkown actor \"%s\"" id + | Some actor_value -> + let fs = V.as_obj actor_value in + match V.Env.find_opt n fs with + | None -> trap exp.at "Actor \"%s\ has no method \"%s\"" id n + | Some field_value -> k field_value + end | ArrayPrim (mut, _), vs -> let vs' = match mut with @@ -390,7 +409,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = | CastPrim _, [v1] -> k v1 | ActorOfIdBlob t, [v1] -> - trap exp.at "ActorOfIdBlob not implemented" + k v1 | BlobOfIcUrl, [v1] -> trap exp.at "BlobOfIcUrl not implemented" (* FIXME: #1001, call Lib.URL.decode_actor_url *) | NumConvPrim (t1, t2), vs -> @@ -505,8 +524,10 @@ and interpret_exp_mut env exp (k : V.value V.cont) = let env' = adjoin_vals env0 ve in interpret_decs env' ds (fun _ -> let obj = interpret_fields env' fs in - define_id env0 id obj; - k obj) + env.actor_env := V.Env.add self obj !(env.actor_env); + let id_value = V.Text self in + define_id env0 id id_value; + k id_value) | NewObjE (sort, fs, _) -> k (interpret_fields env fs) @@ -810,8 +831,8 @@ and interpret_message env at x args f c v (k : V.value V.cont) = (* Programs *) -let interpret_prog flags scope ((ds, exp), flavor) : scope = - let env = env_of_scope flags flavor scope in +let interpret_prog flags state scope ((ds, exp), flavor) : scope = + let env = env_of_scope flags flavor state scope in trace_depth := 0; let ve = ref V.Env.empty in try diff --git a/src/ir_interpreter/interpret_ir.mli b/src/ir_interpreter/interpret_ir.mli index 420224d67e6..3c8f99e74ad 100644 --- a/src/ir_interpreter/interpret_ir.mli +++ b/src/ir_interpreter/interpret_ir.mli @@ -10,11 +10,13 @@ type flags = { print_depth : int } -type scope = V.def V.Env.t +type state +val initial_state : unit -> state +type scope val empty_scope : scope val adjoin_scope : scope -> scope -> scope exception Trap of Source.region * string -val interpret_prog : flags -> scope -> Ir.prog -> scope +val interpret_prog : flags -> state -> scope -> Ir.prog -> scope diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index 6ad39b07036..61e0aafbc9c 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -605,10 +605,11 @@ let interpret_ir_prog libs progs = phase "Interpreting" name; let open Interpret_ir in let flags = { trace = !Flags.trace; print_depth = !Flags.print_depth } in + let interpreter_state = initial_state () in let denv0 = empty_scope in - let dscope = interpret_prog flags denv0 prelude_ir in + let dscope = interpret_prog flags interpreter_state denv0 prelude_ir in let denv1 = adjoin_scope denv0 dscope in - let _ = interpret_prog flags denv1 prog_ir in + let _ = interpret_prog flags interpreter_state denv1 prog_ir in () let interpret_ir_files files = From f538e97d6fbb54b6416b757c3d749c0d7f6f1868 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 15 Jan 2020 14:48:51 +0100 Subject: [PATCH 0942/1176] Remove TypD from the IR (#1115) * Remove TypD from the IR after #1103, there is no point in keeping definition sites for type aliases around; they are not bound to their scope anyways anymore. So remove `TypD`. Code simplification ensues. * Boolean blindness --- src/codegen/compile.ml | 3 --- src/ir_def/arrange_ir.ml | 1 - src/ir_def/check_ir.ml | 3 --- src/ir_def/construct.ml | 1 - src/ir_def/freevars.ml | 1 - src/ir_def/ir.ml | 1 - src/ir_def/ir_effect.ml | 9 +-------- src/ir_interpreter/interpret_ir.ml | 2 -- src/ir_passes/async.ml | 1 - src/ir_passes/await.ml | 13 +------------ src/ir_passes/rename.ml | 3 --- src/ir_passes/show.ml | 1 - src/ir_passes/tailcall.ml | 3 --- src/lowering/desugar.ml | 28 ++++++++-------------------- 14 files changed, 10 insertions(+), 60 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index f83d45a7633..19be45f29e0 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -6584,9 +6584,6 @@ and compile_dec env pre_ae how v2en dec : VarEnv.t * G.t * (VarEnv.t -> G.t) = (pre_ae, G.with_region dec.at alloc_code, fun ae -> G.with_region dec.at (mk_code ae))) @@ match dec.it with - | TypD _ -> - (pre_ae, G.nop, fun _ -> G.nop) - (* A special case for public methods *) (* This relies on the fact that in the top-level mutually recursive group, no shadowing happens. *) | LetD ({it = VarP v; _}, e) when E.NameEnv.mem v v2en -> diff --git a/src/ir_def/arrange_ir.ml b/src/ir_def/arrange_ir.ml index 946af5df23d..dadecc6e17b 100644 --- a/src/ir_def/arrange_ir.ml +++ b/src/ir_def/arrange_ir.ml @@ -125,7 +125,6 @@ and control s = Atom (Arrange_type.control s) and dec d = match d.it with | LetD (p, e) -> "LetD" $$ [pat p; exp e] | VarD (i, e) -> "VarD" $$ [id i; exp e] - | TypD c -> "TypD" $$ [Arrange_type.con c; kind (Con.kind c)] and typ_bind (tb : typ_bind) = Con.to_string tb.it.con $$ [typ tb.it.bound] diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 2d3baab559d..46efefeb55a 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -845,8 +845,6 @@ and check_dec env dec = check (T.is_mut t0) "variable in VarD is not immutable"; check_exp env exp; typ exp <: T.as_immut t0 - | TypD c -> - check_con {env with cons = T.ConSet.add c env.cons} c; and check_decs env decs = List.iter (check_dec env) decs; @@ -865,7 +863,6 @@ and gather_dec env scope dec : scope = "duplicate variable definition in block"; let ve = T.Env.add id (T.Mut (typ exp)) scope.val_env in { val_env = ve} - | TypD c -> scope (* Programs *) diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index 866192e8ed3..3ae8f5ca41b 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -158,7 +158,6 @@ let tagE i e = } let dec_eff dec = match dec.it with - | TypD _ -> T.Triv | LetD (_,e) | VarD (_,e) -> eff e let rec simpl_decs decs = List.concat (List.map simpl_dec decs) diff --git a/src/ir_def/freevars.ml b/src/ir_def/freevars.ml index 6062d16a195..c373d93494f 100644 --- a/src/ir_def/freevars.ml +++ b/src/ir_def/freevars.ml @@ -121,7 +121,6 @@ and id i = M.singleton i {captured = false; eager = true} and dec d = match d.it with | LetD (p, e) -> pat p +++ exp e | VarD (i, e) -> (M.empty, S.singleton i) +++ exp e - | TypD c -> (M.empty, S.empty) (* The variables captured by a function. May include the function itself! *) and captured e = diff --git a/src/ir_def/ir.ml b/src/ir_def/ir.ml index b69a0c3646f..cfddec13680 100644 --- a/src/ir_def/ir.ml +++ b/src/ir_def/ir.ml @@ -136,7 +136,6 @@ and dec = dec' Source.phrase and dec' = | LetD of pat * exp (* immutable *) | VarD of id * exp (* mutable *) - | TypD of Type.con (* type *) (* Literals *) diff --git a/src/ir_def/ir_effect.ml b/src/ir_def/ir_effect.ml index cc3febc71de..b4274ab286b 100644 --- a/src/ir_def/ir_effect.ml +++ b/src/ir_def/ir_effect.ml @@ -79,13 +79,6 @@ and effect_cases cases = max_eff e (effect_cases cases') and effect_dec dec = match dec.it with - | TypD _ -> T.Triv | LetD (_,e) | VarD (_,e) -> effect_exp e -and infer_effect_dec (dec:Ir.dec) = - match dec.it with - | LetD (_,e) - | VarD (_, e) -> - effect_exp e - | TypD _ -> - T.Triv +let infer_effect_dec = effect_dec diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index 6d84436b4bd..69f84df3e06 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -747,7 +747,6 @@ and interpret_block env ro decs exp k = and declare_dec dec : val_env = match dec.it with - | TypD _ -> V.Env.empty | LetD (pat, _) -> declare_pat pat | VarD (id, _) -> declare_id id @@ -771,7 +770,6 @@ and interpret_dec env dec k = define_id env id (V.Mut (ref v)); k () ) - | TypD _ -> k () and interpret_decs env decs (k : unit V.cont) = match decs with diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index 1aefff5aadc..c4e6fd2187b 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -379,7 +379,6 @@ let transform mode env prog = and t_dec' dec' = match dec' with - | TypD con_id -> TypD (t_con con_id) | LetD (pat,exp) -> LetD (t_pat pat,t_exp exp) | VarD (id,exp) -> VarD (id,t_exp exp) diff --git a/src/ir_passes/await.ml b/src/ir_passes/await.ml index 67aa3fd0703..4bd74d1abe7 100644 --- a/src/ir_passes/await.ml +++ b/src/ir_passes/await.ml @@ -133,7 +133,6 @@ and t_dec context dec = {dec with it = t_dec' context dec.it} and t_dec' context dec' = match dec' with - | TypD _ -> dec' | LetD (pat, exp) -> LetD (pat, t_exp context exp) | VarD (id, exp) -> VarD (id, t_exp context exp) @@ -365,19 +364,10 @@ and c_exp' context exp k = nary context k (fun vs -> e (PrimE (p, vs))) exps and c_block context decs exp k = - let is_typ dec = - match dec.it with - | TypD _ -> true - | _ -> false - in - let (typ_decs,val_decs) = List.partition is_typ decs in - blockE typ_decs - (declare_decs val_decs (c_decs context val_decs (meta T.unit (fun _ -> c_exp context exp k)))) + declare_decs decs (c_decs context decs (meta T.unit (fun _ -> c_exp context exp k))) and c_dec context dec (k:kont) = match dec.it with - | TypD _ -> - assert false | LetD (pat,exp) -> let patenv,pat' = rename_pat pat in let block exp = @@ -416,7 +406,6 @@ and c_decs context decs k = and declare_dec dec exp : exp = match dec.it with - | TypD _ -> assert false | LetD (pat, _) -> declare_pat pat exp | VarD (id, exp1) -> declare_id id (T.Mut (typ exp1)) exp diff --git a/src/ir_passes/rename.ml b/src/ir_passes/rename.ml index 3b998bbae6c..d84d5bfafa8 100644 --- a/src/ir_passes/rename.ml +++ b/src/ir_passes/rename.ml @@ -134,9 +134,6 @@ and dec' rho d = match d with let i', rho = id_bind rho i in (fun rho' -> VarD (i',exp rho' e)), rho - | TypD c -> (* we don't rename type names *) - (fun rho -> d), - rho and decs rho ds = let rec decs_aux rho ds = diff --git a/src/ir_passes/show.ml b/src/ir_passes/show.ml index 2846828efb9..90102f9f90a 100644 --- a/src/ir_passes/show.ml +++ b/src/ir_passes/show.ml @@ -330,7 +330,6 @@ and t_dec env dec = { dec with it = t_dec' env dec.it } and t_dec' env dec' = match dec' with - | TypD con_id -> TypD con_id | LetD (pat,exp) -> LetD (pat,t_exp env exp) | VarD (id,exp) -> VarD (id,t_exp env exp) diff --git a/src/ir_passes/tailcall.ml b/src/ir_passes/tailcall.ml index 78777c9e7e9..e6dd2aa9e93 100644 --- a/src/ir_passes/tailcall.ml +++ b/src/ir_passes/tailcall.ml @@ -231,9 +231,6 @@ and dec' env d = let env = bind env i None in (fun env1 -> VarD(i,exp env1 e)), env - | TypD _ -> - (fun env -> d.it), - env and block env ds exp = let rec decs_aux env ds = diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 6e53269d135..c19b716f291 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -278,32 +278,22 @@ and text_dotE proj e = | _ -> assert false and block force_unit ds = - let extra = extra_typDs ds in let prefix, last = Lib.List.split_last ds in match force_unit, last.it with | _, S.ExpD e -> - (extra @ List.map dec prefix, exp e) + (decs prefix, exp e) | false, S.LetD ({it = S.VarP x; _}, e) -> - (extra @ List.map dec ds, idE x.it e.note.S.note_typ) + (decs ds, idE x.it e.note.S.note_typ) | false, S.LetD (p', e') -> let x = fresh_var "x" (e'.note.S.note_typ) in - (extra @ List.map dec prefix @ [letD x (exp e'); letP (pat p') x], x) + (decs prefix @ [letD x (exp e'); letP (pat p') x], x) | _ , S.IgnoreD _ (* redundant, but explicit *) | _, _ -> - (extra @ List.map dec ds, tupE []) + (decs ds, tupE []) -and extra_typDs ds = - match ds with - | [] -> [] - | d::ds -> - match d.it with - | S.ClassD (id, _, _, _, _, _, _) -> - let c = Option.get id.note in - let typD = I.TypD c @@ d.at in - typD :: extra_typDs ds - | _ -> extra_typDs ds - -and decs ds = extra_typDs ds @ List.map dec ds +and decs ds = + let is_not_typD d = match d.it with | S.TypD _ -> false | _ -> true in + List.map dec (List.filter is_not_typD ds) and dec d = { (phrase' dec' d) with note = () } @@ -320,9 +310,7 @@ and dec' at n d = match d with | _ -> I.LetD (p', e') end | S.VarD (i, e) -> I.VarD (i.it, exp e) - | S.TypD (id, typ_bind, t) -> - let c = Option.get id.note in - I.TypD c + | S.TypD _ -> assert false | S.ClassD (id, tbs, p, _t_opt, s, self_id, es) -> let id' = {id with note = ()} in let sort, _, _, _, _ = Type.as_func n.S.note_typ in From ded11e07857a365f9aae6473f7033bea60f82370 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 15 Jan 2020 15:08:35 +0100 Subject: [PATCH 0943/1176] Typo: Missing quote (#1117) thx @ggreif --- src/ir_interpreter/interpret_ir.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index 69f84df3e06..6ef89387805 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -348,7 +348,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = | Some actor_value -> let fs = V.as_obj actor_value in match V.Env.find_opt n fs with - | None -> trap exp.at "Actor \"%s\ has no method \"%s\"" id n + | None -> trap exp.at "Actor \"%s\" has no method \"%s\"" id n | Some field_value -> k field_value end | ArrayPrim (mut, _), vs -> From af654548b1e5bdc7f8758096aa863741f19038d9 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 15 Jan 2020 16:14:50 +0100 Subject: [PATCH 0944/1176] VarLoc: Introduce Static instead of using `Deferred` (which we can get rid of prettyy soon) --- src/codegen/compile.ml | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 19be45f29e0..83700b8b3a8 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -4284,7 +4284,9 @@ module VarLoc = struct Used for mutable captured data *) | HeapInd of (int32 * int32) (* A static mutable memory location (static address of a MutBox field) *) - | Static of int32 + | HeapStatic of int32 + (* Not materialized (yet), statically known constant *) + | Static of SR.static_thing (* Dynamic code to put the value on the heap. May be local to the current function or module (see is_local) *) | Deferred of deferred_loc @@ -4292,6 +4294,7 @@ module VarLoc = struct let is_non_local : varloc -> bool = function | Local _ -> false | HeapInd _ -> false + | HeapStatic _ -> true | Static _ -> true | Deferred d -> not d.is_local end @@ -4461,8 +4464,11 @@ module VarEnv = struct E.add_local_name env i name; (reuse_local_with_offset ae name i off, i) - let add_local_static (ae : t) name ptr = - { ae with vars = NameEnv.add name (VarLoc.Static ptr) ae.vars } + let add_local_heap_static (ae : t) name ptr = + { ae with vars = NameEnv.add name (VarLoc.HeapStatic ptr) ae.vars } + + let add_local_static (ae : t) name st = + { ae with vars = NameEnv.add name (VarLoc.Static st) ae.vars } let add_local_deferred (ae : t) name stack_rep materialize is_local = let open VarLoc in @@ -4516,12 +4522,13 @@ module Var = struct G.i (LocalGet (nr i)) ^^ get_new_val ^^ Heap.store_field off - | Some (Static ptr) -> + | Some (HeapStatic ptr) -> let (set_new_val, get_new_val) = new_local env "new_val" in set_new_val ^^ compile_unboxed_const ptr ^^ get_new_val ^^ Heap.store_field 1l + | Some (Static _) -> fatal "set_val: %s is static" var | Some (Deferred d) -> fatal "set_val: %s is deferred" var | None -> fatal "set_val: %s missing" var @@ -4531,8 +4538,10 @@ module Var = struct SR.Vanilla, G.i (LocalGet (nr i)) | Some (HeapInd (i, off)) -> SR.Vanilla, G.i (LocalGet (nr i)) ^^ Heap.load_field off - | Some (Static i) -> + | Some (HeapStatic i) -> SR.Vanilla, compile_unboxed_const i ^^ Heap.load_field 1l + | Some (Static st) -> + SR.StaticThing st, G.nop | Some (Deferred d) -> d.stack_rep, d.materialize env | None -> assert false @@ -4580,7 +4589,7 @@ module Var = struct let get_val_ptr env ae var = match VarEnv.lookup_var ae var with | Some (HeapInd (i, 1l)) -> G.i (LocalGet (nr i)) - | Some (Static _) -> assert false (* we never do this on the toplevel *) + | Some (HeapStatic _) -> assert false (* we never do this on the toplevel *) | _ -> field_box env (get_val_vanilla env ae var) end (* Var *) @@ -5090,7 +5099,8 @@ module AllocHow = struct match l with | VarLoc.Deferred d when d.VarLoc.is_local -> LocalMut (* conservatively assumes immutable *) | VarLoc.Deferred d -> Static - | VarLoc.Static _ -> StoreStatic + | VarLoc.Static _ -> Static + | VarLoc.HeapStatic _ -> StoreStatic | VarLoc.Local _ -> LocalMut (* conservatively assume immutable *) | VarLoc.HeapInd _ -> StoreHeap ) ae.VarEnv.vars @@ -5127,7 +5137,7 @@ module AllocHow = struct let tag = bytes_of_int32 (Tagged.int_of_tag Tagged.MutBox) in let zero = bytes_of_int32 0l in let ptr = E.add_mutable_static_bytes env (tag ^ zero) in - let ae1 = VarEnv.add_local_static ae name ptr in + let ae1 = VarEnv.add_local_heap_static ae name ptr in (ae1, G.nop) end (* AllocHow *) @@ -6591,16 +6601,14 @@ and compile_dec env pre_ae how v2en dec : VarEnv.t * G.t * (VarEnv.t -> G.t) = let fi = match static_thing with | SR.StaticMessage fi -> fi | _ -> assert false in - let pre_ae1 = VarEnv.add_local_deferred pre_ae v - (SR.StaticThing (SR.PublicMethod (fi, (E.NameEnv.find v v2en)))) - (fun _ -> G.nop) false in + let st = SR.PublicMethod (fi, (E.NameEnv.find v v2en)) in + let pre_ae1 = VarEnv.add_local_static pre_ae v st in ( pre_ae1, G.nop, fun ae -> fill env ae; G.nop) (* A special case for static expressions *) | LetD ({it = VarP v; _}, e) when AllocHow.M.find v how = AllocHow.Static -> let (static_thing, fill) = compile_static_exp env pre_ae how e in - let pre_ae1 = VarEnv.add_local_deferred pre_ae v - (SR.StaticThing static_thing) (fun _ -> G.nop) false in + let pre_ae1 = VarEnv.add_local_static pre_ae v static_thing in ( pre_ae1, G.nop, fun ae -> fill env ae; G.nop) | LetD (p, e) -> From 4054caa65fde77b97c823d124e590648790a370b Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 15 Jan 2020 16:18:38 +0100 Subject: [PATCH 0945/1176] IR: Remove self binder from ActorE (#1104) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * IR: Remove self binder from ActorE instead, * add a `SelfRef` prim * in the desugarer, add a binding to the body of the Actor if needed The “if needed” is a bit ugly, because of ubiqious recursion and that `ActorE` is like a block with a single recursive group. So we only add it if it is not shadowed. --- src/codegen/compile.ml | 42 ++++++++++----------- src/ir_def/arrange_ir.ml | 5 ++- src/ir_def/check_ir.ml | 11 ++++-- src/ir_def/construct.ml | 14 +++++++ src/ir_def/construct.mli | 3 ++ src/ir_def/freevars.ml | 2 +- src/ir_def/ir.ml | 3 +- src/ir_interpreter/interpret_ir.ml | 12 +++--- src/ir_passes/async.ml | 5 ++- src/ir_passes/await.ml | 4 +- src/ir_passes/rename.ml | 5 +-- src/ir_passes/show.ml | 4 +- src/ir_passes/tailcall.ml | 2 +- src/lowering/desugar.ml | 15 +++++--- test/run-drun/ok/self-shadow.comp.ok | 2 + test/run-drun/ok/self-shadow.comp.ret.ok | 1 + test/run-drun/ok/self-shadow.ic-stub-run.ok | 4 ++ test/run-drun/self-shadow.mo | 8 ++++ 18 files changed, 90 insertions(+), 52 deletions(-) create mode 100644 test/run-drun/ok/self-shadow.comp.ok create mode 100644 test/run-drun/ok/self-shadow.comp.ret.ok create mode 100644 test/run-drun/ok/self-shadow.ic-stub-run.ok create mode 100644 test/run-drun/self-shadow.mo diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 19be45f29e0..8880b306ae1 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -6182,6 +6182,10 @@ and compile_exp (env : E.t) ae exp = | ActorOfIdBlob _, [e] -> compile_exp env ae e + | SelfRef _, [] -> + SR.Vanilla, + Dfinity.get_self_reference env + | ICReplyPrim ts, [e] -> SR.unit, begin match E.mode env with | Flags.ICMode | Flags.StubMode -> @@ -6318,12 +6322,12 @@ and compile_exp (env : E.t) ae exp = (get_closure_idx ^^ BoxedSmallWord.box env) get_k get_r - | ActorE (i, ds, fs, _) -> + | ActorE (ds, fs, _) -> SR.Vanilla, let captured = Freevars.exp exp in let prelude_names = find_prelude_names env in if Freevars.M.is_empty (Freevars.diff captured prelude_names) - then actor_lit env i ds fs exp.at + then actor_lit env ds fs exp.at else todo_trap env "non-closed actor" (Arrange_ir.exp exp) | NewObjE ((Type.Object | Type.Module), fs, _) -> SR.Vanilla, @@ -6712,10 +6716,10 @@ and compile_start_func mod_env (progs : Ir.prog list) : E.func_with_names = | _ -> ds, e.it in let find_last_actor (ds,e) = match find_last_expr ds e with - | ds1, ActorE (i, ds2, fs, _) -> - Some (i, ds1 @ ds2, fs) - | ds1, FuncE (_name, _sort, _control, [], [], _, {it = ActorE (i, ds2, fs, _);_}) -> - Some (i, ds1 @ ds2, fs) + | ds1, ActorE (ds2, fs, _) -> + Some (ds1 @ ds2, fs) + | ds1, FuncE (_name, _sort, _control, [], [], _, {it = ActorE (ds2, fs, _);_}) -> + Some (ds1 @ ds2, fs) | _, _ -> None in @@ -6726,7 +6730,7 @@ and compile_start_func mod_env (progs : Ir.prog list) : E.func_with_names = (* If the last program ends with an actor, then consider this the current actor *) | [(prog, _flavor)] -> begin match find_last_actor prog with - | Some (i, ds, fs) -> main_actor env ae i ds fs + | Some (ds, fs) -> main_actor env ae ds fs | None -> let (_ae, code) = compile_prog env ae prog in code @@ -6762,7 +6766,7 @@ and export_actor_field env ae (f : Ir.field) = }) (* Local actor *) -and actor_lit outer_env this ds fs at = +and actor_lit outer_env ds fs at = let wasm_binary = let mod_env = E.mk_global (E.mode outer_env) @@ -6784,14 +6788,11 @@ and actor_lit outer_env this ds fs at = (* Compile the prelude *) let (ae1, prelude_code) = compile_prelude env ae0 in - (* Add this pointer *) - let ae2 = VarEnv.add_local_deferred ae1 this SR.Vanilla Dfinity.get_self_reference false in - (* Reverse the fs, to a map from variable to exported name *) let v2en = E.NameEnv.from_list (List.map (fun f -> (f.it.var, f.it.name)) fs) in (* Compile the declarations *) - let (ae3, decls_code) = compile_decs_public env ae2 AllocHow.TopLvl ds v2en Freevars.S.empty in + let (ae3, decls_code) = compile_decs_public env ae1 AllocHow.TopLvl ds v2en Freevars.S.empty in (* Export the public functions *) List.iter (export_actor_field env ae3) fs; @@ -6802,7 +6803,7 @@ and actor_lit outer_env this ds fs at = if E.mode mod_env = Flags.ICMode then Dfinity.export_start mod_env start_fi; if E.mode mod_env = Flags.StubMode then Dfinity.export_start mod_env start_fi; - let m = conclude_module mod_env this None in + let m = conclude_module mod_env None in let (_map, wasm_binary) = Wasm_exts.CustomModuleEncode.encode m in wasm_binary in @@ -6837,22 +6838,19 @@ and actor_lit outer_env this ds fs at = (* Main actor: Just return the initialization code, and export functions as needed *) -and main_actor env ae1 this ds fs = - (* Add this pointer *) - let ae2 = VarEnv.add_local_deferred ae1 this SR.Vanilla Dfinity.get_self_reference false in - +and main_actor env ae1 ds fs = (* Reverse the fs, to a map from variable to exported name *) let v2en = E.NameEnv.from_list (List.map (fun f -> (f.it.var, f.it.name)) fs) in (* Compile the declarations *) - let (ae3, decls_code) = compile_decs_public env ae2 AllocHow.TopLvl ds v2en Freevars.S.empty in + let (ae2, decls_code) = compile_decs_public env ae1 AllocHow.TopLvl ds v2en Freevars.S.empty in (* Export the public functions *) - List.iter (export_actor_field env ae3) fs; + List.iter (export_actor_field env ae2) fs; decls_code -and conclude_module env module_name start_fi_o = +and conclude_module env start_fi_o = FuncDec.export_async_method env; @@ -6914,7 +6912,7 @@ and conclude_module env module_name start_fi_o = { module_; dylink = None; name = { - module_ = Some module_name; + module_ = None; function_names = List.mapi (fun i (f,n,_) -> Int32.(add ni' (of_int i), n)) funcs; locals_names = @@ -6942,4 +6940,4 @@ let compile mode module_name rts (prelude : Ir.prog) (progs : Ir.prog list) : Wa | Flags.ICMode | Flags.StubMode -> Dfinity.export_start env start_fi; None | Flags.WasmMode | Flags.WASIMode-> Some (nr start_fi) in - conclude_module env module_name start_fi_o + conclude_module env start_fi_o diff --git a/src/ir_def/arrange_ir.ml b/src/ir_def/arrange_ir.ml index dadecc6e17b..ceb1ee7d09f 100644 --- a/src/ir_def/arrange_ir.ml +++ b/src/ir_def/arrange_ir.ml @@ -29,7 +29,7 @@ let rec exp e = match e.it with "FuncE" $$ [Atom x; func_sort s; control c] @ List.map typ_bind tp @ args as_@ [ typ (Type.seq ts); exp e] | SelfCallE (ts, exp_f, exp_k, exp_r) -> "SelfCallE" $$ [typ (Type.seq ts); exp exp_f; exp exp_k; exp exp_r] - | ActorE (i, ds, fs, t) -> "ActorE" $$ [id i] @ List.map dec ds @ fields fs @ [typ t] + | ActorE (ds, fs, t) -> "ActorE" $$ List.map dec ds @ fields fs @ [typ t] | NewObjE (s, fs, t) -> "NewObjE" $$ (Arrange_type.obj_sort s :: fields fs @ [typ t]) | TryE (e, cs) -> "TryE" $$ [exp e] @ List.map case cs @@ -66,9 +66,10 @@ and prim = function | ThrowPrim -> Atom "ThrowPrim" | ShowPrim t -> "ShowPrim" $$ [typ t] | NumConvPrim (t1, t2) -> "NumConvPrim" $$ [prim_ty t1; prim_ty t2] - | CastPrim (t1, t2) -> "CastPrim" $$ [typ t1; typ t2] + | CastPrim (t1, t2) -> "CastPrim" $$ [typ t1; typ t2] | ActorOfIdBlob t -> "ActorOfIdBlob" $$ [typ t] | BlobOfIcUrl -> Atom "BlobOfIcUrl" + | SelfRef t -> "SelfRef" $$ [typ t] | OtherPrim s -> Atom s | CPSAwait -> Atom "CPSAwait" | CPSAsync -> Atom "CPSAsync" diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 46efefeb55a..8c7d8f11a32 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -505,6 +505,10 @@ let rec check_exp env (exp:Ir.exp) : unit = (T.string_of_typ_expand actor_typ) end; actor_typ <: t; + | SelfRef t1, [] -> + (* We could additionally keep track of the type of the current actor in + the environment and see if this lines up. *) + t1 <: t; | OtherPrim _, _ -> () | p, args -> error env exp.at "PrimE %s does not work with %d arguments" @@ -616,11 +620,10 @@ let rec check_exp env (exp:Ir.exp) : unit = typ exp_f <: T.unit; typ exp_k <: T.Func (T.Local, T.Returns, [], ts, []); typ exp_r <: T.Func (T.Local, T.Returns, [], [T.error], []); - | ActorE (id, ds, fs, t0) -> + | ActorE (ds, fs, t0) -> let env' = { env with async = false } in - let ve0 = T.Env.singleton id t0 in - let scope1 = List.fold_left (gather_dec env') empty_scope ds in - let env'' = adjoin (adjoin_vals env' ve0) scope1 in + let scope1 = gather_block_decs env' ds in + let env'' = adjoin env' scope1 in check_decs env'' ds; check (T.is_obj t0) "bad annotation (object type expected)"; let (s0, tfs0) = T.as_obj t0 in diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index 3ae8f5ca41b..c6eb9733d8e 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -91,6 +91,12 @@ let primE prim es = note = { note_typ = ty; note_eff = e } } +let selfRefE typ = + { it = PrimE (SelfRef typ, []); + at = no_region; + note = { note_typ = typ; note_eff = T.Triv } + } + let asyncE typ e = { it = PrimE (CPSAsync, [e]); at = no_region; @@ -378,6 +384,14 @@ let expD exp = let pat = { it = WildP; at = exp.at; note = exp.note.note_typ } in LetD (pat, exp) @@ exp.at +let let_no_shadow x exp decs = + let id = id_of_exp x in + (* could be replaced by a more simple “defined by this decs” function *) + let (_,f) = Freevars.decs decs in + if Freevars.S.mem id f + then decs + else [ letD x exp ] @ decs + (* Derived expressions *) let letE x exp1 exp2 = blockE [letD x exp1] exp2 diff --git a/src/ir_def/construct.mli b/src/ir_def/construct.mli index 8309bc8da47..d1a75a7afe6 100644 --- a/src/ir_def/construct.mli +++ b/src/ir_def/construct.mli @@ -39,6 +39,7 @@ val seqP : pat list -> pat (* Expressions *) val primE : Ir.prim -> exp list -> exp +val selfRefE : typ -> exp val asyncE : typ -> exp -> exp val assertE : exp -> exp val awaitE : typ -> exp -> exp -> exp @@ -89,6 +90,8 @@ val expD : exp -> dec val funcD : var -> var -> exp -> dec val nary_funcD : var -> var list -> exp -> dec +val let_no_shadow : var -> exp -> dec list -> dec list + (* Continuations *) val answerT : typ diff --git a/src/ir_def/freevars.ml b/src/ir_def/freevars.ml index c373d93494f..0988f1fe321 100644 --- a/src/ir_def/freevars.ml +++ b/src/ir_def/freevars.ml @@ -82,7 +82,7 @@ let rec exp e : f = match e.it with | DeclareE (i, t, e) -> exp e // i | DefineE (i, m, e) -> id i ++ exp e | FuncE (x, s, c, tp, as_, t, e) -> under_lambda (exp e /// args as_) - | ActorE (i, ds, fs, _) -> close (decs ds +++ fields fs) // i + | ActorE (ds, fs, _) -> close (decs ds +++ fields fs) | NewObjE (_, fs, _) -> fields fs | TryE (e, cs) -> exp e ++ cases cs | SelfCallE (_, e1, e2, e3) -> under_lambda (exp e1) ++ exp e2 ++ exp e3 diff --git a/src/ir_def/ir.ml b/src/ir_def/ir.ml index cfddec13680..1916a52d78f 100644 --- a/src/ir_def/ir.ml +++ b/src/ir_def/ir.ml @@ -77,7 +77,7 @@ and exp' = | FuncE of (* function *) string * Type.func_sort * Type.control * typ_bind list * arg list * Type.typ list * exp | SelfCallE of Type.typ list * exp * exp * exp (* essentially ICCallPrim (FuncE shared…) *) - | ActorE of id * dec list * field list * Type.typ (* actor *) + | ActorE of dec list * field list * Type.typ (* actor *) | NewObjE of Type.obj_sort * field list * Type.typ (* make an object *) | TryE of exp * case list (* try/catch *) @@ -120,6 +120,7 @@ and prim = | CastPrim of Type.typ * Type.typ (* representationally a noop *) | ActorOfIdBlob of Type.typ | BlobOfIcUrl (* traps on syntax or checksum failure *) + | SelfRef of Type.typ (* returns the self actor ref *) | OtherPrim of string (* Other primitive operation, no custom typing rule *) (* backend stuff *) | CPSAwait diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index 6ef89387805..f7c9faefa49 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -433,6 +433,8 @@ and interpret_exp_mut env exp (k : V.value V.cont) = f (V.Tup[vc; kv; rv]) v2 k | ICCallerPrim, [] -> k env.caller + | SelfRef _, [] -> + k (V.Text env.self) | _ -> trap exp.at "Unknown prim or wrong number of arguments (%d given):\n %s" (List.length es) (Wasm.Sexpr.to_string 80 (Arrange_ir.prim p)) @@ -516,18 +518,16 @@ and interpret_exp_mut env exp (k : V.value V.cont) = | _ -> V.Func (cc, f) in k v - | ActorE (id, ds, fs, _) -> + | ActorE (ds, fs, _) -> let self = V.fresh_id () in - let ve0 = declare_id id in - let env0 = adjoin_vals {env with self = self} ve0 in + let env0 = {env with self = self} in let ve = declare_decs ds V.Env.empty in let env' = adjoin_vals env0 ve in interpret_decs env' ds (fun _ -> let obj = interpret_fields env' fs in env.actor_env := V.Env.add self obj !(env.actor_env); - let id_value = V.Text self in - define_id env0 id id_value; - k id_value) + k (V.Text self) + ) | NewObjE (sort, fs, _) -> k (interpret_fields env fs) diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index c4e6fd2187b..ae8a48b917f 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -212,6 +212,7 @@ let transform mode env prog = | CastPrim (t1,t2) -> CastPrim (t_typ t1,t_typ t2) | ActorOfIdBlob t -> ActorOfIdBlob (t_typ t) | ICReplyPrim ts -> ICReplyPrim (List.map t_typ ts) + | SelfRef t -> SelfRef (t_typ t) | p -> p and t_field {lab; typ} = @@ -356,8 +357,8 @@ let transform mode env prog = | Replies,_ -> assert false end end - | ActorE (id, ds, fs, typ) -> - ActorE (id, t_decs ds, t_fields fs, t_typ typ) + | ActorE (ds, fs, typ) -> + ActorE (t_decs ds, t_fields fs, t_typ typ) | NewObjE (sort, ids, t) -> NewObjE (sort, t_fields ids, t_typ t) | SelfCallE _ -> assert false diff --git a/src/ir_passes/await.ml b/src/ir_passes/await.ml index 4bd74d1abe7..cb2eaa02630 100644 --- a/src/ir_passes/await.ml +++ b/src/ir_passes/await.ml @@ -114,8 +114,8 @@ and t_exp' context exp' = | FuncE (x, s, c, typbinds, pat, typ, exp) -> let context' = LabelEnv.add Return Label LabelEnv.empty in FuncE (x, s, c, typbinds, pat, typ,t_exp context' exp) - | ActorE (id, ds, ids, t) -> - ActorE (id, t_decs context ds, ids, t) + | ActorE (ds, ids, t) -> + ActorE (t_decs context ds, ids, t) | NewObjE (sort, ids, typ) -> exp' | SelfCallE _ -> assert false | PrimE (p, exps) -> diff --git a/src/ir_passes/rename.ml b/src/ir_passes/rename.ml index d84d5bfafa8..aaefc3759c2 100644 --- a/src/ir_passes/rename.ml +++ b/src/ir_passes/rename.ml @@ -36,9 +36,8 @@ and exp' rho e = match e with | VarE i -> VarE (id rho i) | LitE l -> e | PrimE (p, es) -> PrimE (prim rho p, List.map (exp rho) es) - | ActorE (i, ds, fs, t)-> let i',rho' = id_bind rho i in - let ds', rho'' = decs rho' ds - in ActorE (i', ds', fields rho'' fs, t) + | ActorE (ds, fs, t) -> let ds', rho' = decs rho ds + in ActorE (ds', fields rho' fs, t) | AssignE (e1, e2) -> AssignE (lexp rho e1, exp rho e2) | BlockE (ds, e1) -> let ds', rho' = decs rho ds in BlockE (ds', exp rho' e1) diff --git a/src/ir_passes/show.ml b/src/ir_passes/show.ml index 90102f9f90a..a14f9e89f48 100644 --- a/src/ir_passes/show.ml +++ b/src/ir_passes/show.ml @@ -311,12 +311,12 @@ and t_exp' env = function NewObjE (sort, ids, t) | SelfCallE (ts, e1, e2, e3) -> SelfCallE (ts, t_exp env e1, t_exp env e2, t_exp env e3) - | ActorE (id, ds, fields, typ) -> + | ActorE (ds, fields, typ) -> (* compare with transform below *) let env1 = empty_env () in let ds' = t_decs env1 ds in let decls = show_decls !(env1.params) in - ActorE (id, decls @ ds', fields, typ) + ActorE (decls @ ds', fields, typ) and t_lexp env (e : Ir.lexp) = { e with it = t_lexp' env e.it } and t_lexp' env = function diff --git a/src/ir_passes/tailcall.ml b/src/ir_passes/tailcall.ml index e6dd2aa9e93..e5cdfe14023 100644 --- a/src/ir_passes/tailcall.ml +++ b/src/ir_passes/tailcall.ml @@ -128,7 +128,7 @@ and exp' env e : exp' = match e.it with let exp2' = exp env exp2 in let exp3' = exp env exp3 in SelfCallE (ts, exp1', exp2', exp3') - | ActorE (i, ds, fs, t) -> ActorE (i, ds, fs, t) (* TODO: descent into ds *) + | ActorE (ds, fs, t) -> ActorE (ds, fs, t) (* TODO: descent into ds *) | NewObjE (s,is,t) -> NewObjE (s, is, t) | PrimE (p, es) -> PrimE (p, List.map (exp env) es) diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index c19b716f291..92cb87a46df 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -204,13 +204,16 @@ and build_fields obj_typ = List.map build_field val_fields | _ -> assert false +and with_self i typ decs = + let_no_shadow (idE i typ) (selfRefE typ) decs + and build_actor at self_id es obj_typ = let fs = build_fields obj_typ in let ds = decs (List.map (fun ef -> ef.it.S.dec) es) in - let name = match self_id with - | Some n -> n.it - | None -> "anon-actor-" ^ string_of_pos at.left in - I.ActorE (name, ds, fs, obj_typ) + let ds' = match self_id with + | Some n -> with_self n.it obj_typ ds + | None -> ds in + I.ActorE (ds', fs, obj_typ) and build_obj at s self_id es obj_typ = let fs = build_fields obj_typ in @@ -305,8 +308,8 @@ and dec' at n d = match d with let e' = exp e in (* HACK: remove this once backend supports recursive actors *) begin match p'.it, e'.it with - | I.VarP i, I.ActorE (_, ds, fs, t) -> - I.LetD (p', {e' with it = I.ActorE (i, ds, fs, t)}) + | I.VarP i, I.ActorE (ds, fs, t) -> + I.LetD (p', {e' with it = I.ActorE (with_self i t ds, fs, t)}) | _ -> I.LetD (p', e') end | S.VarD (i, e) -> I.VarD (i.it, exp e) diff --git a/test/run-drun/ok/self-shadow.comp.ok b/test/run-drun/ok/self-shadow.comp.ok new file mode 100644 index 00000000000..5c6dae24bf6 --- /dev/null +++ b/test/run-drun/ok/self-shadow.comp.ok @@ -0,0 +1,2 @@ +self-shadow.mo:5.15-5.51: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/self-shadow.comp.ret.ok b/test/run-drun/ok/self-shadow.comp.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/self-shadow.comp.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-drun/ok/self-shadow.ic-stub-run.ok b/test/run-drun/ok/self-shadow.ic-stub-run.ok new file mode 100644 index 00000000000..54225bc8555 --- /dev/null +++ b/test/run-drun/ok/self-shadow.ic-stub-run.ok @@ -0,0 +1,4 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed diff --git a/test/run-drun/self-shadow.mo b/test/run-drun/self-shadow.mo new file mode 100644 index 00000000000..f449eac417a --- /dev/null +++ b/test/run-drun/self-shadow.mo @@ -0,0 +1,8 @@ +actor foo { + public func foo() = (); + + func go() { + let bar = actor bar { public func bar() = () } + }; + +} From 8b101127c38e690070f76deb0836296faf89c4de Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 15 Jan 2020 16:19:50 +0100 Subject: [PATCH 0946/1176] Get rid of VarLoc.deferred! Whoohoo! --- src/codegen/compile.ml | 35 ----------------------------------- 1 file changed, 35 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index cecde32bd2d..14f54b00041 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -4261,18 +4261,6 @@ module GC = struct end (* GC *) module VarLoc = struct - (* Most names are stored in heap locations or in locals. - But some are special (static functions, the current actor, static messages of - the current actor). These have no real location (yet), but we still need to - produce a value on demand: - *) - - type deferred_loc = - { stack_rep : SR.t - ; materialize : E.t -> G.t - ; is_local : bool (* Only valid within the current function *) - } - (* A type to record where Motoko names are stored. *) type varloc = (* A Wasm Local of the current function, directly containing the value @@ -4287,16 +4275,12 @@ module VarLoc = struct | HeapStatic of int32 (* Not materialized (yet), statically known constant *) | Static of SR.static_thing - (* Dynamic code to put the value on the heap. - May be local to the current function or module (see is_local) *) - | Deferred of deferred_loc let is_non_local : varloc -> bool = function | Local _ -> false | HeapInd _ -> false | HeapStatic _ -> true | Static _ -> true - | Deferred d -> not d.is_local end module StackRep = struct @@ -4470,11 +4454,6 @@ module VarEnv = struct let add_local_static (ae : t) name st = { ae with vars = NameEnv.add name (VarLoc.Static st) ae.vars } - let add_local_deferred (ae : t) name stack_rep materialize is_local = - let open VarLoc in - let d = {stack_rep; materialize; is_local} in - { ae with vars = NameEnv.add name (VarLoc.Deferred d) ae.vars } - let add_local_local env (ae : t) name i = { ae with vars = NameEnv.add name (VarLoc.Local i) ae.vars } @@ -4529,7 +4508,6 @@ module Var = struct get_new_val ^^ Heap.store_field 1l | Some (Static _) -> fatal "set_val: %s is static" var - | Some (Deferred d) -> fatal "set_val: %s is deferred" var | None -> fatal "set_val: %s missing" var (* Returns the payload (optimized representation) *) @@ -4542,8 +4520,6 @@ module Var = struct SR.Vanilla, compile_unboxed_const i ^^ Heap.load_field 1l | Some (Static st) -> SR.StaticThing st, G.nop - | Some (Deferred d) -> - d.stack_rep, d.materialize env | None -> assert false (* Returns the payload (vanilla representation) *) @@ -4570,15 +4546,6 @@ module Var = struct let restore_code = G.i (LocalSet (nr j)) in (ae2, restore_code) ) - | Some (Deferred d) -> - assert d.is_local; - ( d.materialize old_env ^^ - StackRep.adjust old_env d.stack_rep SR.Vanilla - , fun new_env ae1 -> - let (ae2, j) = VarEnv.add_direct_local new_env ae1 var in - let restore_code = G.i (LocalSet (nr j)) - in (ae2, restore_code) - ) | _ -> assert false (* Returns a pointer to a heap allocated box for this. @@ -5097,8 +5064,6 @@ module AllocHow = struct (* we assume things are mutable, as we do not know better here *) let how_of_ae ae : allocHow = M.map (fun l -> match l with - | VarLoc.Deferred d when d.VarLoc.is_local -> LocalMut (* conservatively assumes immutable *) - | VarLoc.Deferred d -> Static | VarLoc.Static _ -> Static | VarLoc.HeapStatic _ -> StoreStatic | VarLoc.Local _ -> LocalMut (* conservatively assume immutable *) From b4d4f681de5c2c0279ed5876c951dc01e0e5dd57 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 15 Jan 2020 16:21:04 +0100 Subject: [PATCH 0947/1176] Merge VarLoc into VarEnv --- src/codegen/compile.ml | 71 +++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 36 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 14f54b00041..26bf7ddf0d4 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -4260,29 +4260,6 @@ module GC = struct end (* GC *) -module VarLoc = struct - (* A type to record where Motoko names are stored. *) - type varloc = - (* A Wasm Local of the current function, directly containing the value - (note that most values are pointers, but not all) - Used for immutable and mutable, non-captured data *) - | Local of int32 - (* A Wasm Local of the current function, that points to memory location, - with an offset (in words) to value. - Used for mutable captured data *) - | HeapInd of (int32 * int32) - (* A static mutable memory location (static address of a MutBox field) *) - | HeapStatic of int32 - (* Not materialized (yet), statically known constant *) - | Static of SR.static_thing - - let is_non_local : varloc -> bool = function - | Local _ -> false - | HeapInd _ -> false - | HeapStatic _ -> true - | Static _ -> true -end - module StackRep = struct open SR @@ -4402,6 +4379,28 @@ module StackRep = struct end (* StackRep *) module VarEnv = struct + + (* A type to record where Motoko names are stored. *) + type varloc = + (* A Wasm Local of the current function, directly containing the value + (note that most values are pointers, but not all) + Used for immutable and mutable, non-captured data *) + | Local of int32 + (* A Wasm Local of the current function, that points to memory location, + with an offset (in words) to value. + Used for mutable captured data *) + | HeapInd of (int32 * int32) + (* A static mutable memory location (static address of a MutBox field) *) + | HeapStatic of int32 + (* Not materialized (yet), statically known constant *) + | Static of SR.static_thing + + let is_non_local : varloc -> bool = function + | Local _ -> false + | HeapInd _ -> false + | HeapStatic _ -> true + | Static _ -> true + (* The source variable environment: In scope variables and in-scope jump labels @@ -4409,7 +4408,7 @@ module VarEnv = struct module NameEnv = Env.Make(String) type t = { - vars : VarLoc.varloc NameEnv.t; (* variables ↦ their location *) + vars : varloc NameEnv.t; (* variables ↦ their location *) labels : G.depth NameEnv.t; (* jump label ↦ their depth *) } @@ -4424,7 +4423,7 @@ module VarEnv = struct let mk_fun_ae ae = { ae with vars = NameEnv.filter (fun v l -> - let non_local = VarLoc.is_non_local l in + let non_local = is_non_local l in (* For debugging, enable this: (if not non_local then Printf.eprintf "VarEnv.mk_fun_ae: Removing %s\n" v); *) @@ -4437,11 +4436,11 @@ module VarEnv = struct | None -> Printf.eprintf "Could not find %s\n" var; None let needs_capture ae var = match lookup_var ae var with - | Some l -> not (VarLoc.is_non_local l) + | Some l -> not (is_non_local l) | None -> assert false let reuse_local_with_offset (ae : t) name i off = - { ae with vars = NameEnv.add name (VarLoc.HeapInd (i, off)) ae.vars } + { ae with vars = NameEnv.add name (HeapInd (i, off)) ae.vars } let add_local_with_offset env (ae : t) name off = let i = E.add_anon_local env I32Type in @@ -4449,13 +4448,13 @@ module VarEnv = struct (reuse_local_with_offset ae name i off, i) let add_local_heap_static (ae : t) name ptr = - { ae with vars = NameEnv.add name (VarLoc.HeapStatic ptr) ae.vars } + { ae with vars = NameEnv.add name (HeapStatic ptr) ae.vars } let add_local_static (ae : t) name st = - { ae with vars = NameEnv.add name (VarLoc.Static st) ae.vars } + { ae with vars = NameEnv.add name (Static st) ae.vars } let add_local_local env (ae : t) name i = - { ae with vars = NameEnv.add name (VarLoc.Local i) ae.vars } + { ae with vars = NameEnv.add name (Local i) ae.vars } let add_direct_local env (ae : t) name = let i = E.add_anon_local env I32Type in @@ -4468,7 +4467,7 @@ module VarEnv = struct | (name :: names) -> let i = E.add_anon_local env I32Type in E.add_local_name env i name; - let ae' = { ae with vars = NameEnv.add name (VarLoc.Local i) ae.vars } in + let ae' = { ae with vars = NameEnv.add name (Local i) ae.vars } in let (ae_final, setters) = add_argument_locals env ae' names in (ae_final, G.i (LocalSet (nr i)) :: setters) @@ -4489,7 +4488,7 @@ module Var = struct (* This module is all about looking up Motoko variables in the environment, and dealing with mutable variables *) - open VarLoc + open VarEnv (* Stores the payload (which is found on the stack) *) let set_val env ae var = match VarEnv.lookup_var ae var with @@ -5064,10 +5063,10 @@ module AllocHow = struct (* we assume things are mutable, as we do not know better here *) let how_of_ae ae : allocHow = M.map (fun l -> match l with - | VarLoc.Static _ -> Static - | VarLoc.HeapStatic _ -> StoreStatic - | VarLoc.Local _ -> LocalMut (* conservatively assume immutable *) - | VarLoc.HeapInd _ -> StoreHeap + | VarEnv.Static _ -> Static + | VarEnv.HeapStatic _ -> StoreStatic + | VarEnv.Local _ -> LocalMut (* conservatively assume immutable *) + | VarEnv.HeapInd _ -> StoreHeap ) ae.VarEnv.vars let decs (ae : VarEnv.t) lvl decs captured_in_body : allocHow = From 99e5f8039e6e1b5377c42e047a55fd0d477ec012 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 15 Jan 2020 15:25:35 +0000 Subject: [PATCH 0948/1176] Hasta la vista T.Scope --- src/ir_def/check_ir.ml | 3 +- src/ir_def/construct.ml | 2 +- src/ir_def/ir.ml | 2 +- src/ir_passes/async.ml | 11 +++---- src/ir_passes/show.ml | 8 ++--- src/languageServer/completion.ml | 3 +- src/lowering/desugar.ml | 4 +-- src/mo_def/syntax.ml | 4 +-- src/mo_frontend/typing.ml | 52 +++++++++++++++-------------- src/mo_types/async_cap.ml | 2 +- src/mo_types/type.ml | 56 ++++++++++++++------------------ src/mo_types/type.mli | 6 ++-- src/pipeline/pipeline.ml | 2 +- src/prelude/prelude.ml | 1 - test/mo-idl/counter.mo | 9 ++--- 15 files changed, 81 insertions(+), 84 deletions(-) diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 6e879606cb7..3ea2017e1f7 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -210,7 +210,6 @@ let rec check_typ env typ : unit = check_typ env typ | T.Typ c -> check_con env c - | T.Scope -> () and check_con env c = let env = {env with cons = T.ConSet.add c env.cons} in @@ -854,7 +853,7 @@ and check_open_typ_bind env typ_bind = | _ -> assert false and close_typ_binds cs tbs = - List.map (fun {con; bound} -> {Type.var = Con.name con; bound = Type.close cs bound}) tbs + List.map (fun {con; sort; bound} -> {Type.var = Con.name con; sort = sort; bound = Type.close cs bound}) tbs and check_dec env dec = (* helpers *) diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index a02c3173289..6af201dc6cc 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -476,7 +476,7 @@ let (-->*) xs exp = nary_funcE "$lambda" fun_ty xs exp let close_typ_binds cs tbs = - List.map (fun {it = {con; bound}; _} -> {T.var = Con.name con; bound = T.close cs bound}) tbs + List.map (fun {it = {con; sort; bound}; _} -> {T.var = Con.name con; sort=sort; bound = T.close cs bound}) tbs (* polymorphic, n-ary local lambda *) let forall tbs e = diff --git a/src/ir_def/ir.ml b/src/ir_def/ir.ml index 7dc8b0a90c0..6440ad2eebb 100644 --- a/src/ir_def/ir.ml +++ b/src/ir_def/ir.ml @@ -32,7 +32,7 @@ type typ_note = {note_typ : Type.typ; note_eff : Type.eff} type 'a phrase = ('a, typ_note) Source.annotated_phrase -type typ_bind' = {con : Type.con; bound : Type.typ} +type typ_bind' = {con : Type.con; sort: Type.bind_sort; bound : Type.typ} type typ_bind = typ_bind' Source.phrase type unop = Operator.unop diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index 1fdd70076e8..9eda220aca0 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -54,7 +54,7 @@ let new_asyncT = T.Func ( T.Local, T.Returns, - [ { var = "T"; bound = T.Any } ], + [ { var = "T"; sort=T.Scope; bound = T.Any } ], [], new_async_ret unary (T.Var ("T", 0)) ) @@ -178,10 +178,9 @@ let transform mode env prog = | Non -> Non | Pre -> Pre | Typ c -> Typ (t_con c) - | Scope -> Scope - and t_bind {var; bound} = - {var; bound = t_typ bound} + and t_bind tb = + { tb with bound = t_typ tb.bound } and t_binds typbinds = List.map t_bind typbinds @@ -456,8 +455,8 @@ let transform mode env prog = | AltP (pat1, pat2) -> AltP (t_pat pat1, t_pat pat2) - and t_typ_bind' {con; bound} = - {con = t_con con; bound = t_typ bound} + and t_typ_bind' tb = + { tb with con = t_con tb.con; bound = t_typ tb.bound } and t_typ_bind typ_bind = { typ_bind with it = t_typ_bind' typ_bind.it } diff --git a/src/ir_passes/show.ml b/src/ir_passes/show.ml index 1a6681344da..8059952c428 100644 --- a/src/ir_passes/show.ml +++ b/src/ir_passes/show.ml @@ -93,7 +93,7 @@ let invoke_prelude_show : string -> T.typ -> Ir.exp -> Ir.exp = fun n t e -> let invoke_text_of_option : T.typ -> Ir.exp -> Ir.exp -> Ir.exp = fun t f e -> let fun_typ = - T.Func (T.Local, T.Returns, [{T.var="T";T.bound=T.Any}], [show_fun_typ_for (T.Var ("T",0)); T.Opt (T.Var ("T",0))], [T.text]) in + T.Func (T.Local, T.Returns, [{T.var="T";T.sort=T.Type;T.bound=T.Any}], [show_fun_typ_for (T.Var ("T",0)); T.Opt (T.Var ("T",0))], [T.text]) in text_exp (CallE ( { it = VarE "@text_of_option" ; at = no_region @@ -109,7 +109,7 @@ let invoke_text_of_option : T.typ -> Ir.exp -> Ir.exp -> Ir.exp = fun t f e -> let invoke_text_of_variant : T.typ -> Ir.exp -> T.lab -> Ir.exp -> Ir.exp = fun t f l e -> let fun_typ = - T.Func (T.Local, T.Returns, [{T.var="T";T.bound=T.Any}], [T.text; show_fun_typ_for (T.Var ("T",0)); T.Var ("T",0)], [T.text]) in + T.Func (T.Local, T.Returns, [{T.var="T";T.sort=T.Type;T.bound=T.Any}], [T.text; show_fun_typ_for (T.Var ("T",0)); T.Var ("T",0)], [T.text]) in text_exp (CallE ( { it = VarE "@text_of_variant" ; at = no_region @@ -125,7 +125,7 @@ let invoke_text_of_variant : T.typ -> Ir.exp -> T.lab -> Ir.exp -> Ir.exp = fun let invoke_text_of_array : T.typ -> Ir.exp -> Ir.exp -> Ir.exp = fun t f e -> let fun_typ = - T.Func (T.Local, T.Returns, [{T.var="T";T.bound=T.Any}], [show_fun_typ_for (T.Var ("T",0)); T.Array (T.Var ("T",0))], [T.text]) in + T.Func (T.Local, T.Returns, [{T.var="T";T.sort=T.Type;T.bound=T.Any}], [show_fun_typ_for (T.Var ("T",0)); T.Array (T.Var ("T",0))], [T.text]) in text_exp (CallE ( { it = VarE "@text_of_array" ; at = no_region @@ -141,7 +141,7 @@ let invoke_text_of_array : T.typ -> Ir.exp -> Ir.exp -> Ir.exp = fun t f e -> let invoke_text_of_array_mut : T.typ -> Ir.exp -> Ir.exp -> Ir.exp = fun t f e -> let fun_typ = - T.Func (T.Local, T.Returns, [{T.var="T";T.bound=T.Any}], [show_fun_typ_for (T.Var ("T",0)); T.Array (T.Mut (T.Var ("T",0)))], [T.text]) in + T.Func (T.Local, T.Returns, [{T.var="T";T.sort=T.Type;T.bound=T.Any}], [show_fun_typ_for (T.Var ("T",0)); T.Array (T.Mut (T.Var ("T",0)))], [T.text]) in text_exp (CallE ( { it = VarE "@text_of_array_mut" ; at = no_region diff --git a/src/languageServer/completion.ml b/src/languageServer/completion.ml index ca34d2c65b8..7578ad4fbe0 100644 --- a/src/languageServer/completion.ml +++ b/src/languageServer/completion.ml @@ -17,7 +17,8 @@ let template_of_ide_decl decl = | Type.Func(_, _, binds, ty_list1, ty_list2) -> let ty_args = binds - |> List.map (fun Type.{ var = var; bound = bound} -> + |> List.filter Type.(fun { sort; _ } -> sort = Type) + |> List.map (fun Type.{ var = var; bound = bound; _} -> Printf.sprintf "${%s:%s}" (fresh ()) var) |> String.concat ", " in let args = diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index cf8ada31740..0a604670666 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -229,7 +229,7 @@ and typ_bind tb = | Some c -> c | _ -> assert false in - { it = { Ir.con = c; Ir.bound = tb.it.S.bound.note} + { it = { Ir.con = c; Ir.sort = T.Type; Ir.bound = tb.it.S.bound.note} ; at = tb.at ; note = () } @@ -243,7 +243,7 @@ and array_dotE array_ty proj e = if T.is_mut (T.as_array array_ty) then T.Array (T.Mut varA) else T.Array varA in - let ty_param = {T.var = "A"; T.bound = T.Any} in + let ty_param = {T.var = "A"; sort = T.Type; T.bound = T.Any} in let f = idE name (fun_ty [ty_param] [poly_array_ty] [fun_ty [] t1 t2]) in callE f [element_ty] e in match T.is_mut (T.as_array array_ty), proj with diff --git a/src/mo_def/syntax.ml b/src/mo_def/syntax.ml index dfa5b3c7bf2..f1d8bd81bf8 100644 --- a/src/mo_def/syntax.ml +++ b/src/mo_def/syntax.ml @@ -258,12 +258,12 @@ let scope_id = "@" let scope_bind() = { var = scope_id @@ no_region; - bound = PrimT "Scope" @! no_region + bound = PrimT "Any" @! no_region } @= no_region let pun_id id = { var = id.it @@ no_region; - bound = PrimT "Scope" @! no_region + bound = PrimT "Any" @! no_region } @= no_region let rec is_scope_typ t = diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index b0385ec5b88..715178e278c 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -314,10 +314,9 @@ and check_typ' env typ : T.typ = let c = check_typ_path env path in let ts = List.map (check_typ env) typs in let T.Def (tbs, _) | T.Abs (tbs, _) = Con.kind c in - let tbs' = List.map (fun {T.var; T.bound} -> {T.var; bound = T.open_ ts bound}) tbs in + let tbs' = List.map (fun tb -> { tb with T.bound = T.open_ ts tb.T.bound }) tbs in check_typ_bounds env tbs' ts (List.map (fun typ -> typ.at) typs) typ.at; T.Con (c, ts) - | PrimT "Scope" -> T.Scope | PrimT "Any" -> T.Any | PrimT "None" -> T.Non | PrimT s -> @@ -330,7 +329,7 @@ and check_typ' env typ : T.typ = | TupT typs -> T.Tup (List.map (check_typ env) typs) | FuncT (sort, binds, typ1, typ2) -> - let cs, ts, te, ce = check_typ_binds env binds in + let cs, tbs, te, ce = check_typ_binds env binds in let env' = adjoin_typs env te ce in let env' = infer_scope env' sort.it cs typ2 in let typs1 = as_domT typ1 in @@ -358,8 +357,6 @@ and check_typ' env typ : T.typ = "shared function has non-async result type\n %s" (T.string_of_typ_expand (T.seq ts2)) end; - - let tbs = List.map2 (fun c t -> {T.var = Con.name c; bound = t}) cs ts in T.Func (sort.it, T.map_control (T.close cs) c', T.close_binds cs tbs, List.map (T.close cs) ts1, List.map (T.close cs) ts2) | OptT typ -> T.Opt (check_typ env typ) @@ -421,7 +418,7 @@ and check_typ_binds_acyclic env typ_binds cs ts = in chase 0 [] c in List.iter2 chase typ_binds cs -and check_typ_binds env typ_binds : T.con list * T.typ list * Scope.typ_env * Scope.con_env = +and check_typ_binds env typ_binds : T.con list * T.bind list * Scope.typ_env * Scope.con_env = let xs = List.map (fun typ_bind -> typ_bind.it.var.it) typ_binds in let cs = List.map2 (fun x tb -> @@ -435,7 +432,12 @@ and check_typ_binds env typ_binds : T.con list * T.typ list * Scope.typ_env * Sc T.Env.add id.it c te ) T.Env.empty typ_binds cs in let pre_env' = add_typs {env with pre = true} xs cs in - let ts = List.map (fun typ_bind -> check_typ pre_env' typ_bind.it.bound) typ_binds in + let tbs = List.map (fun typ_bind -> + { T.var = typ_bind.it.var.it; + T.sort = if typ_bind.it.var.it = Syntax.scope_id then T.Scope else T.Type; (* HACK *) + T.bound = check_typ pre_env' typ_bind.it.bound }) typ_binds + in + let ts = List.map (fun tb -> tb.T.bound) tbs in check_typ_binds_acyclic env typ_binds cs ts; let ks = List.map (fun t -> T.Abs ([], t)) ts in List.iter2 (fun c k -> @@ -446,11 +448,11 @@ and check_typ_binds env typ_binds : T.con list * T.typ list * Scope.typ_env * Sc let env' = add_typs env xs cs in let _ = List.map (fun typ_bind -> check_typ env' typ_bind.it.bound) typ_binds in List.iter2 (fun typ_bind c -> typ_bind.note <- Some c) typ_binds cs; - cs, ts, te, T.ConSet.of_list cs + cs, tbs, te, T.ConSet.of_list cs -and check_typ_bind env typ_bind : T.con * T.typ * Scope.typ_env * Scope.con_env = +and check_typ_bind env typ_bind : T.con * T.bind * Scope.typ_env * Scope.con_env = match check_typ_binds env [typ_bind] with - | [c], [t], te, cs -> c, t, te, cs + | [c], [tb], te, cs -> c, tb, te, cs | _ -> assert false and check_typ_bounds env (tbs : T.bind list) (ts : T.typ list) ats at = @@ -479,7 +481,8 @@ and infer_inst env tbs typs at = let ts = List.map (check_typ env) typs in let ats = List.map (fun typ -> typ.at) typs in match tbs,typs with - | {T.bound; _}::tbs', typs' when T.eq bound T.Scope -> + | {T.bound; sort = T.Scope; _}::tbs', typs' -> + assert (List.for_all (fun tb -> tb.T.sort = T.Type) tbs'); (match env.async with | C.NullCap -> error env at "scope required, but non available" | C.AwaitCap c @@ -487,6 +490,7 @@ and infer_inst env tbs typs at = (T.Con(c,[])::ts, at::ats) ) | tbs', typs' -> + assert (List.for_all (fun tb -> tb.T.sort = T.Type) tbs'); ts, ats and check_inst_bounds env tbs inst at = @@ -801,7 +805,7 @@ and infer_exp'' env exp : T.typ = let sort, ve = check_sort_pat env sort_pat in let cT, ts2 = as_codomT sort typ in check_shared_return env typ.at sort cT ts2; - let cs, ts, te, ce = check_typ_binds env typ_binds in + let cs, tbs, te, ce = check_typ_binds env typ_binds in let env' = adjoin_typs env te ce in let env' = infer_scope env' sort cs typ in let t1, ve1 = infer_pat_exhaustive env' pat in @@ -840,8 +844,7 @@ and infer_exp'' env exp : T.typ = end end; let ts1 = match pat.it with TupP _ -> T.seq_of_tup t1 | _ -> [t1] in - let tbs = List.map2 (fun c t -> {T.var = Con.name c; bound = T.close cs t}) cs ts in - T.Func (sort, T.map_control (T.close cs) c, tbs, List.map (T.close cs) ts1, List.map (T.close cs) ts2) + T.Func (sort, T.map_control (T.close cs) c, T.close_binds cs tbs, List.map (T.close cs) ts1, List.map (T.close cs) ts2) | CallE (exp1, inst, exp2) -> let typs = inst.it in let t1 = infer_exp_promote env exp1 in @@ -1751,7 +1754,11 @@ and gather_dec env scope dec : Scope.t = let open Scope in if T.Env.mem id.it scope.typ_env then error env dec.at "duplicate definition for type %s in block" id.it; - let pre_tbs = List.map (fun bind -> {T.var = bind.it.var.it; bound = T.Pre}) binds in + let pre_tbs = List.map (fun bind -> + {T.var = bind.it.var.it; + T.sort = if bind.it.var.it = scope_id then T.Scope else T.Type; + T.bound = T.Pre} + ) binds in let pre_k = T.Abs (pre_tbs, T.Pre) in let c = match id.note with | None -> let c = Con.fresh id.it pre_k in id.note <- Some c; c @@ -1825,11 +1832,10 @@ and infer_dec_typdecs env dec : Scope.t = Scope.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 cs, tbs, 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 - let k = T.Def (tbs, T.close cs t) in + let k = T.Def (T.close_binds cs tbs, T.close cs t) in begin let is_typ_param c = match Con.kind c with @@ -1852,14 +1858,13 @@ and infer_dec_typdecs env dec : Scope.t = } | ClassD (id, binds, pat, _typ_opt, sort, self_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 cs, tbs, 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 self_typ = T.Con (c, List.map (fun c -> T.Con (c, [])) cs) in let env'' = add_val (adjoin_vals env' ve) self_id.it self_typ in let t = infer_obj env'' sort.it fields dec.at in - let tbs = List.map2 (fun c' t -> {T.var = Con.name c'; bound = T.close cs t}) cs ts in - let k = T.Def (tbs, T.close cs t) in + let k = T.Def (T.close_binds cs tbs, T.close cs t) in Scope.{ empty with typ_env = T.Env.singleton id.it c; con_env = infer_id_typdecs id c k; @@ -1925,14 +1930,13 @@ and infer_dec_valdecs env dec : Scope.t = if sort.it = T.Actor && not (is_unit_pat pat) then error_in [Flags.StubMode] env dec.at "actor classes with parameters are not supported; use an actor declaration instead"; - let cs, ts, te, ce = check_typ_binds env typ_binds in + let cs, tbs, te, ce = check_typ_binds env typ_binds in let env' = adjoin_typs env te ce in let c = T.Env.find id.it env.typs in let t1, _ = infer_pat {env' with pre = true} pat in let ts1 = match pat.it with TupP _ -> T.seq_of_tup t1 | _ -> [t1] in let t2 = T.Con (c, List.map (fun c -> T.Con (c, [])) cs) in - let tbs = List.map2 (fun c t -> {T.var = Con.name c; bound = T.close cs t}) cs ts in - let t = T.Func (T.Local, T.Returns, tbs, List.map (T.close cs) ts1, [T.close cs t2]) in + let t = T.Func (T.Local, T.Returns, T.close_binds cs tbs, List.map (T.close cs) ts1, [T.close cs t2]) in Scope.{ empty with val_env = T.Env.singleton id.it t; typ_env = T.Env.singleton id.it c; diff --git a/src/mo_types/async_cap.ml b/src/mo_types/async_cap.ml index 25dccf6490a..6d1f4f404e2 100644 --- a/src/mo_types/async_cap.ml +++ b/src/mo_types/async_cap.ml @@ -8,6 +8,6 @@ type async_cap = | AsyncCap of T.con | AwaitCap of T.con -let top_cap = Con.fresh "@" (T.Def([],T.Scope)) +let top_cap = Con.fresh "@" (T.Def([],T.Any)) let initial_cap () = if !Flags.compiled then NullCap else AsyncCap top_cap diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index e29631f9ce6..6382a466ee5 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -52,10 +52,11 @@ and typ = | Any (* top *) | Non (* bottom *) | Typ of con (* type (field of module) *) - | Scope (* Scope pseudo type *) | Pre (* pre-type *) -and bind = {var : var; bound : typ} +and bind_sort = Scope | Type + +and bind = {var : var; sort: bind_sort; bound : typ} and field = {lab : lab; typ : typ} and con = kind Con.t @@ -188,10 +189,9 @@ let rec shift i n t = | Non -> Non | Pre -> Pre | Typ c -> Typ c - | Scope -> Scope -and shift_bind i n {var; bound} = - {var; bound = shift i n bound} +and shift_bind i n tb = + {tb with bound = shift i n tb.bound} and shift_field i n {lab; typ} = {lab; typ = shift i n typ} @@ -240,10 +240,9 @@ let rec subst sigma t = type parameter cannot mention that parameter (but can mention other (closed) type constructors). *) - | Scope -> Scope -and subst_bind sigma {var; bound} = - {var; bound = subst sigma bound} +and subst_bind sigma tb = + { tb with bound = subst sigma tb.bound} and subst_field sigma {lab; typ} = {lab; typ = subst sigma typ} @@ -269,7 +268,7 @@ let close cs t = let close_binds cs tbs = if cs = [] then tbs else - List.map (fun {var; bound} -> {var; bound = close cs bound}) tbs + List.map (fun tb -> { tb with bound = close cs tb.bound }) tbs let rec open' i ts t = @@ -291,10 +290,9 @@ let rec open' i ts t = | Non -> Non | Pre -> Pre | Typ c -> Typ c - | Scope -> Scope -and open_bind i ts {var; bound} = - {var; bound = open' i ts bound} +and open_bind i ts tb = + {tb with bound = open' i ts tb.bound} and open_field i ts {lab; typ} = {lab; typ = open' i ts typ} @@ -426,7 +424,7 @@ let as_pair_sub t = match promote t with | _ -> invalid "as_pair_sub" let as_func_sub default_s default_arity t = match promote t with | Func (s, c, tbs, ts1, ts2) -> s, tbs, seq ts1, codom c ts2 - | Non -> default_s, Lib.List.make default_arity {var = "X"; bound = Any}, Any, Non + | Non -> default_s, Lib.List.make default_arity {var = "X"; sort = Type; bound = Any}, Any, Non | _ -> invalid "as_func_sub" let as_mono_func_sub t = match promote t with | Func (_, _, [], ts1, ts2) -> seq ts1, seq ts2 @@ -469,15 +467,13 @@ let rec span = function | Mut t -> span t | Non -> Some 0 | Typ _ -> Some 1 - | Scope -> Some 0 - (* Avoiding local constructors *) exception Unavoidable of con let rec avoid' cons seen = function - | (Prim _ | Var _ | Any | Non | Pre | Scope) as t -> t + | (Prim _ | Var _ | Any | Non | Pre) as t -> t | Con (c, ts) -> if ConSet.mem c seen then raise (Unavoidable c) else if ConSet.mem c cons then @@ -506,10 +502,9 @@ let rec avoid' cons seen = function | Mut t -> Mut (avoid' cons seen t) | Typ c -> if ConSet.mem c cons then raise (Unavoidable c) else Typ c (* TBR *) - -and avoid_bind cons seen {var; bound} = - {var; bound = avoid' cons seen bound} +and avoid_bind cons seen tb= + { tb with bound = avoid' cons seen tb.bound} and avoid_field cons seen {lab; typ} = {lab; typ = avoid' cons seen typ} @@ -536,7 +531,7 @@ let avoid cons t = let rec cons t cs = match t with | Var _ -> cs - | (Prim _ | Any | Non | Pre | Scope) -> cs + | (Prim _ | Any | Non | Pre ) -> cs | Con (c, ts) -> List.fold_right cons ts (ConSet.add c cs) | (Opt t | Mut t | Array t) -> @@ -552,8 +547,8 @@ let rec cons t cs = List.fold_right cons_field fs cs | Typ c -> ConSet.add c cs -and cons_bind {var; bound} cs = - cons bound cs +and cons_bind tb cs = + cons tb.bound cs and cons_field {lab; typ} cs = cons typ cs @@ -582,7 +577,7 @@ let concrete t = seen := S.add t !seen; match t with | Var _ | Pre -> assert false - | Prim _ | Any | Non | Scope -> true + | Prim _ | Any | Non -> true | Con (c, ts) -> (match Con.kind c with | Abs _ -> false @@ -608,7 +603,7 @@ let shared t = seen := S.add t !seen; match t with | Var _ | Pre -> assert false - | Prim Error | Scope -> false + | Prim Error -> false | Any | Non | Prim _ | Typ _ -> true | Async _ | Mut _ -> false | Con (c, ts) -> @@ -635,7 +630,7 @@ let find_unshared t = seen := S.add t !seen; match t with | Var _ | Pre -> assert false - | Prim Error | Scope -> Some t + | Prim Error -> Some t | Any | Non | Prim _ | Typ _ -> None | Async _ | Mut _ -> Some t | Con (c, ts) -> @@ -748,7 +743,6 @@ let rec rel_typ rel eq t1 t2 = eq_typ rel eq t1' t2' | Typ c1, Typ c2 -> eq_con eq c1 c2 - | Scope, Scope -> true | _, _ -> false end @@ -920,7 +914,7 @@ let rec inhabited_typ co t = co := S.add t !co; match promote t with | Pre -> assert false - | Non | Scope -> false + | Non -> false | Any | Prim _ | Array _ | Opt _ | Async _ | Func _ | Typ _ -> true | Mut t' -> inhabited_typ co t' | Tup ts -> List.for_all (inhabited_typ co) ts @@ -972,7 +966,7 @@ let rec lub' lubs glbs t1 t2 = Obj (s1, lub_fields lubs glbs tf1 tf2) | Func (s1, c1, bs1, args1, res1), Func (s2, c2, bs2, args2, res2) when s1 = s2 && eq_control c1 c2 && List.(length bs1 = length bs2) && - List.for_all2 (fun b1 b2 -> (b1.bound = Scope) = (b2.bound = Scope)) bs1 bs2 && + List.for_all2 (fun b1 b2 -> b1.sort = b2.sort) bs1 bs2 && List.(length args1 = length args2 && length res1 = length res2) -> combine_func_parts s1 c1 bs1 args1 res1 bs2 args2 res2 lubs glbs glb' lub' | Async (t11, t12), Async (t21, t22) when eq t11 t21 -> @@ -1046,7 +1040,7 @@ and glb' lubs glbs t1 t2 = ) | Func (s1, c1, bs1, args1, res1), Func (s2, c2, bs2, args2, res2) when s1 = s2 && eq_control c1 c2 && List.(length bs1 = length bs2) && - List.for_all2 (fun b1 b2 -> (b1.bound = Scope) = (b2.bound = Scope)) bs1 bs2 && + List.for_all2 (fun b1 b2 -> b1.sort = b2.sort) bs1 bs2 && List.(length args1 = length args2 && length res1 = length res2) -> combine_func_parts s1 c1 bs1 args1 res1 bs2 args2 res2 lubs glbs lub' glb' | Async (t11, t12), Async (t21, t22) when eq t11 t21 -> @@ -1183,7 +1177,6 @@ let rec string_of_typ_nullary vs = function | Pre -> "???" | Any -> "Any" | Non -> "None" - | Scope -> "Scope" | Prim p -> string_of_prim p | Var (s, i) -> (try string_of_var (List.nth vs i) with _ -> assert false) | Con (c, []) -> string_of_con' vs c @@ -1258,11 +1251,10 @@ and can_omit n t = | Obj (_, fs) | Variant fs -> List.for_all (fun f -> go i f.typ) fs | Func (s, c, tbs, ts1, ts2) -> let i' = i+List.length tbs in - List.for_all (fun {var;bound} -> (go i' bound)) tbs && + List.for_all (fun tb -> (go i' tb.bound)) tbs && List.for_all (go i') ts1 && List.for_all (go i') ts2 | Typ c -> true (* assuming type defs are closed *) - | Scope -> true end in go n t diff --git a/src/mo_types/type.mli b/src/mo_types/type.mli index 7e1db57310a..5881f85f65c 100644 --- a/src/mo_types/type.mli +++ b/src/mo_types/type.mli @@ -49,10 +49,12 @@ and typ = | Any (* top *) | Non (* bottom *) | Typ of con (* type (field of module) *) - | Scope (* scope pseudo type *) | Pre (* pre-type *) -and bind = {var : var; bound : typ} + +and bind_sort = Scope | Type +and bind = {var : var; sort: bind_sort; bound : typ} + and field = {lab : lab; typ : typ} and con = kind Con.t diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index 0feef8964e4..fb2c533ba6d 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -256,7 +256,7 @@ let chase_imports parsefn senv0 imports : (Syntax.lib list * Scope.scope) Diag.r let open Type in Obj (Actor, [{lab = "go"; - typ = Func (Shared Write, Promises (Var ("@", 0)), [{var = "@"; bound = Scope}], + typ = Func (Shared Write, Promises (Var ("@", 0)), [{var = "@"; sort = Scope; bound = Any}], [], [Obj (Actor, [])])}]) in let sscope = Scope.lib f scaffold_type in diff --git a/src/prelude/prelude.ml b/src/prelude/prelude.ml index 767785d7af9..fa83d21defc 100644 --- a/src/prelude/prelude.ml +++ b/src/prelude/prelude.ml @@ -1,6 +1,5 @@ let prelude = {| -type Scope = prim "Scope"; type Any = prim "Any"; type None = prim "None"; type Null = prim "Null"; diff --git a/test/mo-idl/counter.mo b/test/mo-idl/counter.mo index b4e80c382be..7f8fff13a22 100644 --- a/test/mo-idl/counter.mo +++ b/test/mo-idl/counter.mo @@ -13,9 +13,8 @@ actor class Counter(i : Int) { public func read() : async Int { c }; }; -// Dummy functions to show intermediate value in trace. +// Dummy function to show intermediate value in trace. func show(note : Text, c : Int) {}; -func showAsync<@>(note : Text, a : async<@> Int) {}; // Create an actor. let c = Counter(10); @@ -35,12 +34,14 @@ ignore testDec(); func testRead() : async () { var i : Int = 10; let _ = async { + // Dummy function to show intermediate value in trace. + func showAsync(note : Text, a : async Int) {}; while (i > 0) { c.dec(); let t = c.read(); - showAsync<@>("before", t); + showAsync("before", t); show("await", await t); - showAsync<@>("after", t); + showAsync("after", t); i -= 1; } } From 0cef784b33931cddc6451db7009a9bc8744e734d Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 16 Jan 2020 09:46:05 +0100 Subject: [PATCH 0949/1176] =?UTF-8?q?Use=20=E2=80=9Cconst=E2=80=9D=20not?= =?UTF-8?q?=20=E2=80=9Cstatic=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit there was too much confusion around “static” in the sense “statically known value”, and “static” in the sense “located in the static heap”. So rename the former to `Const.t` (this type will become more expressive pretty soon.) --- src/codegen/compile.ml | 138 +++++++++++++++++++++++------------------ 1 file changed, 76 insertions(+), 62 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 26bf7ddf0d4..9474202196a 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -42,17 +42,30 @@ let todo fn se x = Printf.eprintf "%s: %s" fn (Wasm.Sexpr.to_string 80 se); x exception CodegenError of string let fatal fmt = Printf.ksprintf (fun s -> raise (CodegenError s)) fmt -module SR = struct - (* This goes with the StackRep module, but we need the types earlier *) +module Const = struct + + (* Constant known values. - (* Statically known values: They are not put on the stack, but the - “stack representation“ carries the static information. + These are values that + * are completely known constantly + * do not require Wasm code to be be executed (e.g. in `start`) + * can be used directly (e.g. Call, not CallIndirect) + * can be turned into Vanilla heap data on demand + * (future work) + vanilla heap representation may be placed in static heap and shared *) - type static_thing = - | StaticFun of int32 - | StaticMessage of int32 (* anonymous message, only temporary *) + + type t = + | Fun of int32 + | Message of int32 (* anonymous message, only temporary *) | PublicMethod of int32 * string +end (* Const *) + +module SR = struct + (* This goes with the StackRep module, but we need the types earlier *) + + (* Value representation on the stack: Compiling an expression means putting its value on the stack. But @@ -65,7 +78,7 @@ module SR = struct | UnboxedWord64 | UnboxedWord32 | Unreachable - | StaticThing of static_thing + | Const of Const.t let unit = UnboxedTuple 0 @@ -4296,7 +4309,7 @@ module StackRep = struct | UnboxedTuple 1 -> [I32Type] | UnboxedTuple n -> assert false; (* not supported without muti_value *) - | StaticThing _ -> [] + | Const _ -> [] | Unreachable -> [] let to_string = function @@ -4305,7 +4318,7 @@ module StackRep = struct | UnboxedWord32 -> "UnboxedWord32" | UnboxedTuple n -> Printf.sprintf "UnboxedTuple %d" n | Unreachable -> "Unreachable" - | StaticThing _ -> "StaticThing" + | Const _ -> "StaticThing" let join (sr1 : t) (sr2 : t) = match sr1, sr2 with | _, _ when sr1 = sr2 -> sr1 @@ -4315,7 +4328,7 @@ module StackRep = struct | UnboxedTuple n, UnboxedTuple m when n = m -> sr1 | _, Vanilla -> Vanilla | Vanilla, _ -> Vanilla - | StaticThing _, StaticThing _ -> Vanilla + | Const _, Const _ -> Vanilla | _, _ -> Printf.eprintf "Invalid stack rep join (%s, %s)\n" (to_string sr1) (to_string sr2); sr1 @@ -4335,20 +4348,20 @@ module StackRep = struct | UnboxedWord64 -> G.i Drop | UnboxedWord32 -> G.i Drop | UnboxedTuple n -> G.table n (fun _ -> G.i Drop) - | StaticThing _ -> G.nop + | Const _ -> G.nop | Unreachable -> G.nop let materialize env = function - | StaticFun fi -> - (* When accessing a variable that is a static function, then we need to + | Const.Fun fi -> + (* When accessing a variable that is a constant function, then we need to create a heap-allocated closure-like thing on the fly. *) Tagged.obj env Tagged.Closure [ compile_unboxed_const fi; compile_unboxed_zero (* number of parameters: none *) ] - | StaticMessage fi -> + | Const.Message fi -> assert false - | PublicMethod (_, name) -> + | Const.PublicMethod (_, name) -> Dfinity.get_self_reference env ^^ Dfinity.actor_public_field env name @@ -4368,8 +4381,8 @@ module StackRep = struct | UnboxedWord32, Vanilla -> BoxedSmallWord.box env | Vanilla, UnboxedWord32 -> BoxedSmallWord.unbox env - | StaticThing s, Vanilla -> materialize env s - | StaticThing s, UnboxedTuple 0 -> G.nop + | Const s, Vanilla -> materialize env s + | Const s, UnboxedTuple 0 -> G.nop | _, _ -> Printf.eprintf "Unknown stack_rep conversion %s -> %s\n" @@ -4391,15 +4404,16 @@ module VarEnv = struct Used for mutable captured data *) | HeapInd of (int32 * int32) (* A static mutable memory location (static address of a MutBox field) *) + (* TODO: Do we need static immutable? *) | HeapStatic of int32 (* Not materialized (yet), statically known constant *) - | Static of SR.static_thing + | Const of Const.t let is_non_local : varloc -> bool = function | Local _ -> false | HeapInd _ -> false | HeapStatic _ -> true - | Static _ -> true + | Const _ -> true (* The source variable environment: @@ -4450,8 +4464,8 @@ module VarEnv = struct let add_local_heap_static (ae : t) name ptr = { ae with vars = NameEnv.add name (HeapStatic ptr) ae.vars } - let add_local_static (ae : t) name st = - { ae with vars = NameEnv.add name (Static st) ae.vars } + let add_local_const (ae : t) name c = + { ae with vars = NameEnv.add name (Const c : varloc) ae.vars } let add_local_local env (ae : t) name i = { ae with vars = NameEnv.add name (Local i) ae.vars } @@ -4506,7 +4520,7 @@ module Var = struct compile_unboxed_const ptr ^^ get_new_val ^^ Heap.store_field 1l - | Some (Static _) -> fatal "set_val: %s is static" var + | Some (Const _) -> fatal "set_val: %s is const" var | None -> fatal "set_val: %s missing" var (* Returns the payload (optimized representation) *) @@ -4517,8 +4531,8 @@ module Var = struct SR.Vanilla, G.i (LocalGet (nr i)) ^^ Heap.load_field off | Some (HeapStatic i) -> SR.Vanilla, compile_unboxed_const i ^^ Heap.load_field 1l - | Some (Static st) -> - SR.StaticThing st, G.nop + | Some (Const c) -> + SR.Const c, G.nop | None -> assert false (* Returns the payload (vanilla representation) *) @@ -4595,7 +4609,7 @@ module FuncDec = struct | Type.Shared Type.Query -> G.i Nop | _ -> assert false - let compile_static_message outer_env outer_ae sort control args mk_body ret_tys at : E.func_with_names = + let compile_const_message outer_env outer_ae sort control args mk_body ret_tys at : E.func_with_names = let ae0 = VarEnv.mk_fun_ae outer_ae in Func.of_body outer_env [] [] (fun env -> G.with_region at ( (* reply early for a oneway *) @@ -4620,12 +4634,12 @@ module FuncDec = struct let (fi, fill) = E.reserve_fun pre_env name in if Type.is_shared_sort sort then begin - ( SR.StaticMessage fi, fun env ae -> - fill (compile_static_message env ae sort control args mk_body ret_tys at) + ( Const.Message fi, fun env ae -> + fill (compile_const_message env ae sort control args mk_body ret_tys at) ) end else begin assert (control = Type.Returns); - ( SR.StaticFun fi, fun env ae -> + ( Const.Fun fi, fun env ae -> let restore_no_env _env ae _ = (ae, G.nop) in fill (compile_local_function env ae restore_no_env args mk_body ret_tys at) ) @@ -4704,9 +4718,9 @@ module FuncDec = struct if captured = [] then - let (st, fill) = closed env sort control name args mk_body ret_tys at in + let (c, fill) = closed env sort control name args mk_body ret_tys at in fill env ae; - (SR.StaticThing st, G.nop) + (SR.Const c, G.nop) else closure env ae sort control name captured args mk_body ret_tys at (* Returns the index of a saved closure *) @@ -4925,7 +4939,7 @@ module AllocHow = struct (* When compiling a (recursive) block, we need to do a dependency analysis, to find out how the things are allocated. The options are: - - static: completely known, constant, not stored anywhere (think static function) + - const: completely known, constant, not stored anywhere (think static function) (no need to mention in a closure) - local: only needed locally, stored in a Wasm local, immutable (can be copied into a closure by value) @@ -4940,9 +4954,9 @@ module AllocHow = struct to avoid turning function references into closures. The rules are: - - functions are static, unless they capture something that is not a static + - functions are const, unless they capture something that is not a const function or a static heap allocation. - in particular, top-level functions are always static + in particular, top-level functions are always const - everything that is captured on the top-level needs to be statically heap-allocated - everything that is captured before it is defined, or is captured and mutable @@ -4956,8 +4970,8 @@ module AllocHow = struct (* We represent this as a lattice as follows: *) - type how = Static | LocalImmut | LocalMut | StoreHeap | StoreStatic - type allocHow = how M.t (* absent means static *) + type how = Const | LocalImmut | LocalMut | StoreHeap | StoreStatic + type allocHow = how M.t let disjoint_union : allocHow -> allocHow -> allocHow = M.union (fun v _ _ -> fatal "AllocHow.disjoint_union: %s" v) @@ -4972,7 +4986,7 @@ module AllocHow = struct | _, LocalMut | LocalMut, _ -> LocalMut | _, LocalImmut | LocalImmut, _ -> LocalImmut - | Static, Static -> Static + | Const, Const -> Const )) let joins = List.fold_left join M.empty @@ -4992,12 +5006,12 @@ module AllocHow = struct | LocalMut -> true | _ -> false - let is_not_static _ = function - | Static -> false + let is_not_const _ : how -> bool = function + | Const -> false | _ -> true - let require_closure _ = function - | Static -> false + let require_closure _ : how -> bool = function + | Const -> false | StoreStatic -> false | _ -> true @@ -5019,7 +5033,7 @@ module AllocHow = struct map_of_set StoreStatic (S.inter (set_of_map (M.filter is_local how)) captured) - let is_static_exp exp = match exp.it with + let is_const_exp exp = match exp.it with | FuncE _ -> true | _ -> false @@ -5036,16 +5050,16 @@ module AllocHow = struct map_of_set LocalMut d (* Static expressions on the top-level: - - need to be static forms + - need to be constant forms - all non-captured free variables must be static - all captured variables must be static or static-heap, if not on top level (top level captures variables will be forced to be static-heap below, via how2) *) | LetD ({it = VarP _; _}, e) when - is_static_exp e && - disjoint (Freevars.eager_vars f) (set_of_map (M.filter is_not_static how_all)) && + is_const_exp e && + disjoint (Freevars.eager_vars f) (set_of_map (M.filter is_not_const how_all)) && (lvl = TopLvl || disjoint (Freevars.captured_vars f) (set_of_map (M.filter require_closure how_all))) - -> map_of_set Static d + -> map_of_set (Const : how) d (* Everything else needs at least a local *) @@ -5063,7 +5077,7 @@ module AllocHow = struct (* we assume things are mutable, as we do not know better here *) let how_of_ae ae : allocHow = M.map (fun l -> match l with - | VarEnv.Static _ -> Static + | VarEnv.Const _ -> (Const : how) | VarEnv.HeapStatic _ -> StoreStatic | VarEnv.Local _ -> LocalMut (* conservatively assume immutable *) | VarEnv.HeapInd _ -> StoreHeap @@ -5073,7 +5087,7 @@ module AllocHow = struct let how_outer = how_of_ae ae in let defined_here = snd (Freevars.decs decs) in (* TODO: implement gather_decs more directly *) let how_outer = Freevars.diff how_outer defined_here in (* shadowing *) - let how0 = map_of_set Static defined_here in + let how0 = map_of_set (Const : how) defined_here in let captured = S.inter defined_here captured_in_body in let rec go how = let seen, how1 = List.fold_left (dec lvl how_outer) (S.empty, how) decs in @@ -5087,7 +5101,7 @@ module AllocHow = struct based on how we want to store them. *) let add_local env ae how name : VarEnv.t * G.t = match M.find name how with - | Static -> (ae, G.nop) + | (Const : how) -> (ae, G.nop) | LocalImmut | LocalMut -> let (ae1, i) = VarEnv.add_direct_local env ae name in (ae1, G.nop) @@ -5799,7 +5813,7 @@ and compile_exp (env : E.t) ae exp = StackRep.of_arity return_arity, let fun_sr, code1 = compile_exp env ae e1 in begin match fun_sr, sort with - | SR.StaticThing (SR.StaticFun fi), _ -> + | SR.Const (Const.Fun fi), _ -> code1 ^^ compile_unboxed_zero ^^ (* A dummy closure *) compile_exp_as env ae (StackRep.of_arity n_args) e2 ^^ (* the args *) @@ -6565,18 +6579,18 @@ and compile_dec env pre_ae how v2en dec : VarEnv.t * G.t * (VarEnv.t -> G.t) = (* A special case for public methods *) (* This relies on the fact that in the top-level mutually recursive group, no shadowing happens. *) | LetD ({it = VarP v; _}, e) when E.NameEnv.mem v v2en -> - let (static_thing, fill) = compile_static_exp env pre_ae how e in - let fi = match static_thing with - | SR.StaticMessage fi -> fi + let (const, fill) = compile_const_exp env pre_ae how e in + let fi = match const with + | Const.Message fi -> fi | _ -> assert false in - let st = SR.PublicMethod (fi, (E.NameEnv.find v v2en)) in - let pre_ae1 = VarEnv.add_local_static pre_ae v st in + let c = Const.PublicMethod (fi, (E.NameEnv.find v v2en)) in + let pre_ae1 = VarEnv.add_local_const pre_ae v c in ( pre_ae1, G.nop, fun ae -> fill env ae; G.nop) - (* A special case for static expressions *) - | LetD ({it = VarP v; _}, e) when AllocHow.M.find v how = AllocHow.Static -> - let (static_thing, fill) = compile_static_exp env pre_ae how e in - let pre_ae1 = VarEnv.add_local_static pre_ae v static_thing in + (* A special case for constant expressions *) + | LetD ({it = VarP v; _}, e) when AllocHow.M.find v how = AllocHow.Const -> + let (const, fill) = compile_const_exp env pre_ae how e in + let pre_ae1 = VarEnv.add_local_const pre_ae v const in ( pre_ae1, G.nop, fun ae -> fill env ae; G.nop) | LetD (p, e) -> @@ -6636,7 +6650,7 @@ and compile_prog env ae (ds, e) = let code2 = compile_top_lvl_expr env ae' e in (ae', code1 ^^ code2) -and compile_static_exp env pre_ae how exp = match exp.it with +and compile_const_exp env pre_ae how exp = match exp.it with | FuncE (name, sort, control, typ_binds, args, res_tys, e) -> let return_tys = match control with | Type.Returns -> res_tys @@ -6645,7 +6659,7 @@ and compile_static_exp env pre_ae how exp = match exp.it with let mk_body env ae = List.iter (fun v -> if not (VarEnv.NameEnv.mem v ae.VarEnv.vars) - then fatal "internal error: static \"%s\": captures \"%s\", not found in static environment\n" name v + then fatal "internal error: const \"%s\": captures \"%s\", not found in static environment\n" name v ) (Freevars.M.keys (Freevars.exp e)); compile_exp_as env ae (StackRep.of_arity (List.length return_tys)) e in FuncDec.closed env sort control name args mk_body return_tys exp.at @@ -6718,7 +6732,7 @@ and export_actor_field env ae (f : Ir.field) = let sr, code = Var.get_val env ae f.it.var in (* A public actor field is guaranteed to be compiled as a PublicMethod *) let fi = match sr with - | SR.StaticThing (SR.PublicMethod (fi, _)) -> fi + | SR.Const (Const.PublicMethod (fi, _)) -> fi | _ -> assert false in (* There should be no code associated with this *) assert (G.is_nop code); From 2d089adfa1773f6988d89b6694844ba3b3cf5cc6 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 16 Jan 2020 10:21:33 +0100 Subject: [PATCH 0950/1176] Test files: remove exectuable bits (#1120) I guess these were copied from `.sh` files, so they bogusly are executable. --- test/run/pkg-import-absolute.mo | 0 test/run/pkg-import-relative.mo | 0 test/run/pkg-missing.mo | 0 3 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 test/run/pkg-import-absolute.mo mode change 100755 => 100644 test/run/pkg-import-relative.mo mode change 100755 => 100644 test/run/pkg-missing.mo diff --git a/test/run/pkg-import-absolute.mo b/test/run/pkg-import-absolute.mo old mode 100755 new mode 100644 diff --git a/test/run/pkg-import-relative.mo b/test/run/pkg-import-relative.mo old mode 100755 new mode 100644 diff --git a/test/run/pkg-missing.mo b/test/run/pkg-missing.mo old mode 100755 new mode 100644 From 42f8ad78dfa15afcb0335d8cdae9feba04f843c1 Mon Sep 17 00:00:00 2001 From: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> Date: Thu, 16 Jan 2020 15:09:46 +0100 Subject: [PATCH 0951/1176] Find definitions for class definitions (#1122) * This makes it so we also extract position information for classes * adds tests for going to definitions * removes debugging output --- src/languageServer/declaration_index.ml | 2 + src/languageServer/definition.ml | 4 +- src/languageServer/languageServer.ml | 3 +- src/lsp/lsp.atd | 2 +- test/lsp-int-test-project/app.mo | 1 + test/lsp-int-test-project/definitions.mo | 9 +++ test/lsp-int-test-project/entrypoint.mo | 3 + test/lsp-int-test-project/mydependency/lib.mo | 8 ++- test/lsp-int/Main.hs | 65 ++++++++++++++----- 9 files changed, 74 insertions(+), 23 deletions(-) create mode 100644 test/lsp-int-test-project/definitions.mo create mode 100644 test/lsp-int-test-project/entrypoint.mo diff --git a/src/languageServer/declaration_index.ml b/src/languageServer/declaration_index.ml index 5760a9d2681..ddfeb62f4a7 100644 --- a/src/languageServer/declaration_index.ml +++ b/src/languageServer/declaration_index.ml @@ -139,6 +139,8 @@ let populate_definitions match exp_field.it.Syntax.dec.it with | Syntax.TypD (typ_id, _, _) -> Some typ_id + | Syntax.ClassD (typ_id, _, _, _, _, _, _) -> + Some typ_id | _ -> None in let extract_binders env (pat : Syntax.pat) = gather_pat env pat in let find_def (lib : Syntax.lib) def = diff --git a/src/languageServer/definition.ml b/src/languageServer/definition.ml index 815c4818cdf..c736d5c02b4 100644 --- a/src/languageServer/definition.ml +++ b/src/languageServer/definition.ml @@ -63,5 +63,5 @@ let definition_handler then Option.get (Source_file.uri_for_package path) else Vfs.uri_from_file path; location_range = range_of_region region - }) result in - `TextDocumentDefinitionResponse location + }) result in + `TextDocumentDefinitionResponse (Option.to_list location) diff --git a/src/languageServer/languageServer.ml b/src/languageServer/languageServer.ml index eaa8a099911..49cd2cfdc05 100644 --- a/src/languageServer/languageServer.ml +++ b/src/languageServer/languageServer.ml @@ -102,6 +102,7 @@ let start entry_point debug = let shutdown = ref false in let client_capabilities = ref None in let project_root = Sys.getcwd () in + let _ = log_to_file "project_root" project_root in let files_with_diags = ref [] in let vfs = ref Vfs.empty in @@ -218,7 +219,7 @@ let start entry_point debug = vfs := Vfs.close_file params !vfs | (_, `TextDocumentDidSave _) -> let msgs = match Declaration_index.make_index log_to_file !vfs [entry_point] with - | Error msgs' -> msgs' + | Error msgs' -> List.iter (fun msg -> log_to_file "rebuild_error" (Diag.string_of_message msg)) msgs'; msgs' | Ok((ix, msgs')) -> decl_index := ix; msgs' in diff --git a/src/lsp/lsp.atd b/src/lsp/lsp.atd index 0b0b2f94fb9..0db4a6202c8 100644 --- a/src/lsp/lsp.atd +++ b/src/lsp/lsp.atd @@ -74,7 +74,7 @@ type response_message = { type response_result = [ Initialize of initialize_result | TextDocumentHoverResponse of hover_result nullable - | TextDocumentDefinitionResponse of location nullable + | TextDocumentDefinitionResponse of location list | CompletionResponse of completion_item list | ShutdownResponse of unit nullable ] diff --git a/test/lsp-int-test-project/app.mo b/test/lsp-int-test-project/app.mo index 1de717cfaf8..cd3673b4255 100644 --- a/test/lsp-int-test-project/app.mo +++ b/test/lsp-int-test-project/app.mo @@ -1,5 +1,6 @@ import Stack "ListClient.mo"; import Prim "mo:prim"; +import Entry "entrypoint.mo"; actor { func main(): () { diff --git a/test/lsp-int-test-project/definitions.mo b/test/lsp-int-test-project/definitions.mo new file mode 100644 index 00000000000..ee38e119ac0 --- /dev/null +++ b/test/lsp-int-test-project/definitions.mo @@ -0,0 +1,9 @@ +import MyDependency "mo:mydep/lib.mo"; +import List "lib/list.mo"; + +module { + public func myFunc() { + let myClass = MyDependency.MyClass(); + let myNil = List.nil(); + } +} diff --git a/test/lsp-int-test-project/entrypoint.mo b/test/lsp-int-test-project/entrypoint.mo new file mode 100644 index 00000000000..fd395f7c5f0 --- /dev/null +++ b/test/lsp-int-test-project/entrypoint.mo @@ -0,0 +1,3 @@ +import Definitions "definitions.mo"; + +module {} diff --git a/test/lsp-int-test-project/mydependency/lib.mo b/test/lsp-int-test-project/mydependency/lib.mo index 0c23d2c7b95..2c4ac0007e9 100644 --- a/test/lsp-int-test-project/mydependency/lib.mo +++ b/test/lsp-int-test-project/mydependency/lib.mo @@ -1,5 +1,11 @@ module { public func print_hello(): Text { debug_show("hello") - } + }; + + public class MyClass() { + public func member(): Text { + return "Member" + }; + }; } diff --git a/test/lsp-int/Main.hs b/test/lsp-int/Main.hs index bcdd5b267cc..7a3fc05c838 100644 --- a/test/lsp-int/Main.hs +++ b/test/lsp-int/Main.hs @@ -12,11 +12,12 @@ import qualified Control.Exception as Exception import Control.Lens ((^.)) import Control.Monad (unless, guard) import Control.Monad.IO.Class (liftIO) -import Data.Default +import Data.Bifunctor (first) import Data.Maybe (mapMaybe) import Data.Text (Text) +import qualified Data.Text as Text import Language.Haskell.LSP.Test hiding (message) -import Language.Haskell.LSP.Types (TextDocumentIdentifier(..), Position(..), HoverContents(..), MarkupContent(..), MarkupKind(..), TextEdit(..), Range(..), DidSaveTextDocumentParams(..), ClientMethod(..), Diagnostic(..)) +import Language.Haskell.LSP.Types (TextDocumentIdentifier(..), Position(..), HoverContents(..), MarkupContent(..), MarkupKind(..), TextEdit(..), Range(..), DidSaveTextDocumentParams(..), ClientMethod(..), Diagnostic(..), Location(..), Uri(..), filePathToUri) import Language.Haskell.LSP.Types.Lens (contents, label, detail, message) import System.Directory (setCurrentDirectory, makeAbsolute, removeFile) import System.Environment (getArgs) @@ -24,19 +25,16 @@ import System.Exit (exitFailure) import System.FilePath (()) import System.IO (hPutStr, stderr) import Test.HUnit.Lang (HUnitFailure(..), formatFailureReason) -import Test.Hspec (shouldBe, shouldMatchList) +import Test.Hspec (shouldBe, shouldMatchList, shouldContain) completionTestCase :: TextDocumentIdentifier -> Position - -> [(Text, Maybe Text)] + -> ([(Text, Maybe Text)] -> IO ()) -> Session () -completionTestCase doc pos expected = do +completionTestCase doc pos pred = do actual <- getCompletions doc pos - liftIO - (shouldMatchList - (map (\c -> (c^.label, c^.detail)) actual) - expected) + liftIO (pred (map (\c -> (c^.label, c^.detail)) actual)) hoverTestCase :: TextDocumentIdentifier @@ -47,6 +45,19 @@ hoverTestCase doc pos expected = do actual <- getHover doc pos liftIO (shouldBe (fmap (^.contents) actual) expected) +definitionsTestCase + :: FilePath + -> TextDocumentIdentifier + -> Position + -> [(FilePath, Range)] + -> Session () +definitionsTestCase project doc pos expected = do + response <- getDefinitions doc pos + let expected' = map (first (filePathToUri . (project ))) expected + let actual = map (\(Location uri range) -> (uri, range)) response + liftIO (shouldMatchList actual expected') + + -- | Discards all empty diagnostic reports (as those are merely used -- to clear out old reports) waitForActualDiagnostics :: Session [Diagnostic] @@ -123,8 +134,26 @@ main = do withDoc "app.mo" \doc -> do hoverTestCase doc - (Position 7 39) + (Position 8 39) (plainMarkup "natToWord8 : Nat -> Word8") + + log "Definition tests" + withDoc "definitions.mo" \doc -> do + + log "Definition for a function" + definitionsTestCase + project + doc + (Position 6 25) + [("lib/list.mo", Range (Position 31 14) (Position 31 17))] + + log "Definition for a Class" + definitionsTestCase + project + doc + (Position 5 31) + [("mydependency/lib.mo", Range (Position 5 17) (Position 5 24))] + log "Completion tests" -- Completing top level definitions: withDoc "ListClient.mo" \doc -> do @@ -142,7 +171,7 @@ main = do doc -- 15 | List.pus| (Position 14 14) - [("push",Just "(T, List) -> List")] + (`shouldMatchList` [("push",Just "(T, List) -> List")]) -- Completing primitives: withDoc "ListClient.mo" \doc -> do @@ -189,7 +218,7 @@ main = do withDoc "app.mo" \doc -> do -- It knows how to handle package paths for rebuilding, and also -- for completions - let edit = TextEdit (Range (Position 3 0) (Position 3 0)) "\nimport MyDep \"mo:mydep/broken.mo\"" + let edit = TextEdit (Range (Position 4 0) (Position 4 0)) "\nimport MyDep \"mo:mydep/broken.mo\"" _ <- applyEdit doc edit sendNotification TextDocumentDidSave (DidSaveTextDocumentParams doc) [diag] <- waitForActualDiagnostics @@ -198,13 +227,13 @@ main = do log "Completions from package paths" withDoc "app.mo" \doc -> do -- Imports the non-broken dependency module - let edit2 = TextEdit (Range (Position 3 0) (Position 3 0)) "\nimport MyDep \"mo:mydep/lib.mo\"" - _ <- applyEdit doc edit2 + let edit = TextEdit (Range (Position 4 0) (Position 4 0)) "\nimport MyDep \"mo:mydep/lib.mo\"" + _ <- applyEdit doc edit sendNotification TextDocumentDidSave (DidSaveTextDocumentParams doc) - let edit3 = TextEdit (Range (Position 4 0) (Position 4 0)) "\nMyDep." - _ <- applyEdit doc edit3 + let edit2 = TextEdit (Range (Position 5 0) (Position 5 0)) "\nMyDep." + _ <- applyEdit doc edit2 completionTestCase doc -- MyDep.| - (Position 5 6) - [("print_hello", Just "() -> Text")] + (Position 6 6) + (`shouldContain` [("print_hello", Just "() -> Text")]) From bd7ca59266a24cf5b247cdff6a5c61e52dca1965 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 16 Jan 2020 15:05:36 +0100 Subject: [PATCH 0952/1176] Create static heap objects for constant values on demand MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, with code like ``` func foo() = …; foo(); higher_order(foo); higher_order(foo); ``` we would initially not create a heap representation for `foo`, and just do a direct call in `foo()`. But what if we _do_ need a heap object for `foo`? We would allocate it _dynamically_ upon each use, i.e. twice in the code above! With this change, if there is any first-class use of `foo`, we put the corresponding heap object into the static memory once, and use it in every use of `foo`. If there is no first-class use of `foo`, then no memory will be used. This will be more important with #1121, because we really don't want to synthesize whole module objects dynamically. The testcase confirms the improvement. --- src/codegen/compile.ml | 54 ++++++++++++++--------- test/run/const-func-static.mo | 13 ++++++ test/run/ok/const-func-static.wasm-run.ok | 1 + 3 files changed, 48 insertions(+), 20 deletions(-) create mode 100644 test/run/const-func-static.mo create mode 100644 test/run/ok/const-func-static.wasm-run.ok diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 9474202196a..e2045db5fdb 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -55,11 +55,18 @@ module Const = struct vanilla heap representation may be placed in static heap and shared *) - type t = + type v = | Fun of int32 | Message of int32 (* anonymous message, only temporary *) | PublicMethod of int32 * string + (* A constant known value together with a static memory location + (filled on demand) + *) + type t = (int32 Lib.Promise.t * v) + + let t_of_v v = (Lib.Promise.make (), v) + end (* Const *) module SR = struct @@ -1211,6 +1218,13 @@ module Closure = struct G.i (CallIndirect (nr ty)) ^^ FakeMultiVal.load env (Lib.List.make n_res I32Type) + let static_closure env fi : int32 = + let tag = bytes_of_int32 (Tagged.int_of_tag Tagged.Closure) in + let len = bytes_of_int32 fi in + let zero = bytes_of_int32 0l in + let data = tag ^ len ^ zero in + E.add_static_bytes env data + end (* Closure *) @@ -4351,14 +4365,14 @@ module StackRep = struct | Const _ -> G.nop | Unreachable -> G.nop - let materialize env = function + let materialize env (p, cv) = + if Lib.Promise.is_fulfilled p + then compile_unboxed_const (Lib.Promise.value p) + else match cv with | Const.Fun fi -> - (* When accessing a variable that is a constant function, then we need to - create a heap-allocated closure-like thing on the fly. *) - Tagged.obj env Tagged.Closure [ - compile_unboxed_const fi; - compile_unboxed_zero (* number of parameters: none *) - ] + let ptr = Closure.static_closure env fi in + Lib.Promise.fulfill p ptr; + compile_unboxed_const ptr | Const.Message fi -> assert false | Const.PublicMethod (_, name) -> @@ -4381,8 +4395,8 @@ module StackRep = struct | UnboxedWord32, Vanilla -> BoxedSmallWord.box env | Vanilla, UnboxedWord32 -> BoxedSmallWord.unbox env - | Const s, Vanilla -> materialize env s - | Const s, UnboxedTuple 0 -> G.nop + | Const c, Vanilla -> materialize env c + | Const c, UnboxedTuple 0 -> G.nop | _, _ -> Printf.eprintf "Unknown stack_rep conversion %s -> %s\n" @@ -4406,7 +4420,7 @@ module VarEnv = struct (* A static mutable memory location (static address of a MutBox field) *) (* TODO: Do we need static immutable? *) | HeapStatic of int32 - (* Not materialized (yet), statically known constant *) + (* Not materialized (yet), statically known constant, static location on demand *) | Const of Const.t let is_non_local : varloc -> bool = function @@ -4464,8 +4478,8 @@ module VarEnv = struct let add_local_heap_static (ae : t) name ptr = { ae with vars = NameEnv.add name (HeapStatic ptr) ae.vars } - let add_local_const (ae : t) name c = - { ae with vars = NameEnv.add name (Const c : varloc) ae.vars } + let add_local_const (ae : t) name cv = + { ae with vars = NameEnv.add name (Const (Const.t_of_v cv) : varloc) ae.vars } let add_local_local env (ae : t) name i = { ae with vars = NameEnv.add name (Local i) ae.vars } @@ -4720,7 +4734,7 @@ module FuncDec = struct then let (c, fill) = closed env sort control name args mk_body ret_tys at in fill env ae; - (SR.Const c, G.nop) + (SR.Const (Const.t_of_v c), G.nop) else closure env ae sort control name captured args mk_body ret_tys at (* Returns the index of a saved closure *) @@ -5813,7 +5827,7 @@ and compile_exp (env : E.t) ae exp = StackRep.of_arity return_arity, let fun_sr, code1 = compile_exp env ae e1 in begin match fun_sr, sort with - | SR.Const (Const.Fun fi), _ -> + | SR.Const (_, Const.Fun fi), _ -> code1 ^^ compile_unboxed_zero ^^ (* A dummy closure *) compile_exp_as env ae (StackRep.of_arity n_args) e2 ^^ (* the args *) @@ -6583,14 +6597,14 @@ and compile_dec env pre_ae how v2en dec : VarEnv.t * G.t * (VarEnv.t -> G.t) = let fi = match const with | Const.Message fi -> fi | _ -> assert false in - let c = Const.PublicMethod (fi, (E.NameEnv.find v v2en)) in - let pre_ae1 = VarEnv.add_local_const pre_ae v c in + let cv = Const.PublicMethod (fi, (E.NameEnv.find v v2en)) in + let pre_ae1 = VarEnv.add_local_const pre_ae v cv in ( pre_ae1, G.nop, fun ae -> fill env ae; G.nop) (* A special case for constant expressions *) | LetD ({it = VarP v; _}, e) when AllocHow.M.find v how = AllocHow.Const -> - let (const, fill) = compile_const_exp env pre_ae how e in - let pre_ae1 = VarEnv.add_local_const pre_ae v const in + let (cv, fill) = compile_const_exp env pre_ae how e in + let pre_ae1 = VarEnv.add_local_const pre_ae v cv in ( pre_ae1, G.nop, fun ae -> fill env ae; G.nop) | LetD (p, e) -> @@ -6732,7 +6746,7 @@ and export_actor_field env ae (f : Ir.field) = let sr, code = Var.get_val env ae f.it.var in (* A public actor field is guaranteed to be compiled as a PublicMethod *) let fi = match sr with - | SR.Const (Const.PublicMethod (fi, _)) -> fi + | SR.Const (_, Const.PublicMethod (fi, _)) -> fi | _ -> assert false in (* There should be no code associated with this *) assert (G.is_nop code); diff --git a/test/run/const-func-static.mo b/test/run/const-func-static.mo new file mode 100644 index 00000000000..144702e196d --- /dev/null +++ b/test/run/const-func-static.mo @@ -0,0 +1,13 @@ +import Prim "mo:prim"; + +let before = Prim.rts_heap_size(); +func higher_order(foo: () -> () ) = foo(); +func bar() = (); +higher_order(bar); +let after = Prim.rts_heap_size(); +assert(after-before == 0); +Prim.debugPrint("Ignore Diff: heap size increase " # debug_show (after-before)); + +//SKIP run +//SKIP run-low +//SKIP run-ir diff --git a/test/run/ok/const-func-static.wasm-run.ok b/test/run/ok/const-func-static.wasm-run.ok new file mode 100644 index 00000000000..160627aa445 --- /dev/null +++ b/test/run/ok/const-func-static.wasm-run.ok @@ -0,0 +1 @@ +Ignore Diff: (ignored) From 66996e1212568ec3a9749eeaf4e9ef44319f3792 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 16 Jan 2020 22:02:29 +0100 Subject: [PATCH 0953/1176] Get rid of VarLoc.deferred (#1119) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * VarLoc: Introduce Static instead of using `Deferred` (which we can get rid of prettyy soon) * Get rid of VarLoc.deferred! Whoohoo! * Merge VarLoc into VarEnv * Use “const” not “static” there was too much confusion around “static” in the sense “statically known value”, and “static” in the sense “located in the static heap”. So rename the former to `Const.t` (this type will become more expressive pretty soon.) --- src/codegen/compile.ml | 238 +++++++++++++++++++---------------------- 1 file changed, 112 insertions(+), 126 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 8880b306ae1..9474202196a 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -42,17 +42,30 @@ let todo fn se x = Printf.eprintf "%s: %s" fn (Wasm.Sexpr.to_string 80 se); x exception CodegenError of string let fatal fmt = Printf.ksprintf (fun s -> raise (CodegenError s)) fmt -module SR = struct - (* This goes with the StackRep module, but we need the types earlier *) +module Const = struct - (* Statically known values: They are not put on the stack, but the - “stack representation“ carries the static information. + (* Constant known values. + + These are values that + * are completely known constantly + * do not require Wasm code to be be executed (e.g. in `start`) + * can be used directly (e.g. Call, not CallIndirect) + * can be turned into Vanilla heap data on demand + * (future work) + vanilla heap representation may be placed in static heap and shared *) - type static_thing = - | StaticFun of int32 - | StaticMessage of int32 (* anonymous message, only temporary *) + + type t = + | Fun of int32 + | Message of int32 (* anonymous message, only temporary *) | PublicMethod of int32 * string +end (* Const *) + +module SR = struct + (* This goes with the StackRep module, but we need the types earlier *) + + (* Value representation on the stack: Compiling an expression means putting its value on the stack. But @@ -65,7 +78,7 @@ module SR = struct | UnboxedWord64 | UnboxedWord32 | Unreachable - | StaticThing of static_thing + | Const of Const.t let unit = UnboxedTuple 0 @@ -4260,42 +4273,6 @@ module GC = struct end (* GC *) -module VarLoc = struct - (* Most names are stored in heap locations or in locals. - But some are special (static functions, the current actor, static messages of - the current actor). These have no real location (yet), but we still need to - produce a value on demand: - *) - - type deferred_loc = - { stack_rep : SR.t - ; materialize : E.t -> G.t - ; is_local : bool (* Only valid within the current function *) - } - - (* A type to record where Motoko names are stored. *) - type varloc = - (* A Wasm Local of the current function, directly containing the value - (note that most values are pointers, but not all) - Used for immutable and mutable, non-captured data *) - | Local of int32 - (* A Wasm Local of the current function, that points to memory location, - with an offset (in words) to value. - Used for mutable captured data *) - | HeapInd of (int32 * int32) - (* A static mutable memory location (static address of a MutBox field) *) - | Static of int32 - (* Dynamic code to put the value on the heap. - May be local to the current function or module (see is_local) *) - | Deferred of deferred_loc - - let is_non_local : varloc -> bool = function - | Local _ -> false - | HeapInd _ -> false - | Static _ -> true - | Deferred d -> not d.is_local -end - module StackRep = struct open SR @@ -4332,7 +4309,7 @@ module StackRep = struct | UnboxedTuple 1 -> [I32Type] | UnboxedTuple n -> assert false; (* not supported without muti_value *) - | StaticThing _ -> [] + | Const _ -> [] | Unreachable -> [] let to_string = function @@ -4341,7 +4318,7 @@ module StackRep = struct | UnboxedWord32 -> "UnboxedWord32" | UnboxedTuple n -> Printf.sprintf "UnboxedTuple %d" n | Unreachable -> "Unreachable" - | StaticThing _ -> "StaticThing" + | Const _ -> "StaticThing" let join (sr1 : t) (sr2 : t) = match sr1, sr2 with | _, _ when sr1 = sr2 -> sr1 @@ -4351,7 +4328,7 @@ module StackRep = struct | UnboxedTuple n, UnboxedTuple m when n = m -> sr1 | _, Vanilla -> Vanilla | Vanilla, _ -> Vanilla - | StaticThing _, StaticThing _ -> Vanilla + | Const _, Const _ -> Vanilla | _, _ -> Printf.eprintf "Invalid stack rep join (%s, %s)\n" (to_string sr1) (to_string sr2); sr1 @@ -4371,20 +4348,20 @@ module StackRep = struct | UnboxedWord64 -> G.i Drop | UnboxedWord32 -> G.i Drop | UnboxedTuple n -> G.table n (fun _ -> G.i Drop) - | StaticThing _ -> G.nop + | Const _ -> G.nop | Unreachable -> G.nop let materialize env = function - | StaticFun fi -> - (* When accessing a variable that is a static function, then we need to + | Const.Fun fi -> + (* When accessing a variable that is a constant function, then we need to create a heap-allocated closure-like thing on the fly. *) Tagged.obj env Tagged.Closure [ compile_unboxed_const fi; compile_unboxed_zero (* number of parameters: none *) ] - | StaticMessage fi -> + | Const.Message fi -> assert false - | PublicMethod (_, name) -> + | Const.PublicMethod (_, name) -> Dfinity.get_self_reference env ^^ Dfinity.actor_public_field env name @@ -4404,8 +4381,8 @@ module StackRep = struct | UnboxedWord32, Vanilla -> BoxedSmallWord.box env | Vanilla, UnboxedWord32 -> BoxedSmallWord.unbox env - | StaticThing s, Vanilla -> materialize env s - | StaticThing s, UnboxedTuple 0 -> G.nop + | Const s, Vanilla -> materialize env s + | Const s, UnboxedTuple 0 -> G.nop | _, _ -> Printf.eprintf "Unknown stack_rep conversion %s -> %s\n" @@ -4415,6 +4392,29 @@ module StackRep = struct end (* StackRep *) module VarEnv = struct + + (* A type to record where Motoko names are stored. *) + type varloc = + (* A Wasm Local of the current function, directly containing the value + (note that most values are pointers, but not all) + Used for immutable and mutable, non-captured data *) + | Local of int32 + (* A Wasm Local of the current function, that points to memory location, + with an offset (in words) to value. + Used for mutable captured data *) + | HeapInd of (int32 * int32) + (* A static mutable memory location (static address of a MutBox field) *) + (* TODO: Do we need static immutable? *) + | HeapStatic of int32 + (* Not materialized (yet), statically known constant *) + | Const of Const.t + + let is_non_local : varloc -> bool = function + | Local _ -> false + | HeapInd _ -> false + | HeapStatic _ -> true + | Const _ -> true + (* The source variable environment: In scope variables and in-scope jump labels @@ -4422,7 +4422,7 @@ module VarEnv = struct module NameEnv = Env.Make(String) type t = { - vars : VarLoc.varloc NameEnv.t; (* variables ↦ their location *) + vars : varloc NameEnv.t; (* variables ↦ their location *) labels : G.depth NameEnv.t; (* jump label ↦ their depth *) } @@ -4437,7 +4437,7 @@ module VarEnv = struct let mk_fun_ae ae = { ae with vars = NameEnv.filter (fun v l -> - let non_local = VarLoc.is_non_local l in + let non_local = is_non_local l in (* For debugging, enable this: (if not non_local then Printf.eprintf "VarEnv.mk_fun_ae: Removing %s\n" v); *) @@ -4450,27 +4450,25 @@ module VarEnv = struct | None -> Printf.eprintf "Could not find %s\n" var; None let needs_capture ae var = match lookup_var ae var with - | Some l -> not (VarLoc.is_non_local l) + | Some l -> not (is_non_local l) | None -> assert false let reuse_local_with_offset (ae : t) name i off = - { ae with vars = NameEnv.add name (VarLoc.HeapInd (i, off)) ae.vars } + { ae with vars = NameEnv.add name (HeapInd (i, off)) ae.vars } let add_local_with_offset env (ae : t) name off = let i = E.add_anon_local env I32Type in E.add_local_name env i name; (reuse_local_with_offset ae name i off, i) - let add_local_static (ae : t) name ptr = - { ae with vars = NameEnv.add name (VarLoc.Static ptr) ae.vars } + let add_local_heap_static (ae : t) name ptr = + { ae with vars = NameEnv.add name (HeapStatic ptr) ae.vars } - let add_local_deferred (ae : t) name stack_rep materialize is_local = - let open VarLoc in - let d = {stack_rep; materialize; is_local} in - { ae with vars = NameEnv.add name (VarLoc.Deferred d) ae.vars } + let add_local_const (ae : t) name c = + { ae with vars = NameEnv.add name (Const c : varloc) ae.vars } let add_local_local env (ae : t) name i = - { ae with vars = NameEnv.add name (VarLoc.Local i) ae.vars } + { ae with vars = NameEnv.add name (Local i) ae.vars } let add_direct_local env (ae : t) name = let i = E.add_anon_local env I32Type in @@ -4483,7 +4481,7 @@ module VarEnv = struct | (name :: names) -> let i = E.add_anon_local env I32Type in E.add_local_name env i name; - let ae' = { ae with vars = NameEnv.add name (VarLoc.Local i) ae.vars } in + let ae' = { ae with vars = NameEnv.add name (Local i) ae.vars } in let (ae_final, setters) = add_argument_locals env ae' names in (ae_final, G.i (LocalSet (nr i)) :: setters) @@ -4504,7 +4502,7 @@ module Var = struct (* This module is all about looking up Motoko variables in the environment, and dealing with mutable variables *) - open VarLoc + open VarEnv (* Stores the payload (which is found on the stack) *) let set_val env ae var = match VarEnv.lookup_var ae var with @@ -4516,13 +4514,13 @@ module Var = struct G.i (LocalGet (nr i)) ^^ get_new_val ^^ Heap.store_field off - | Some (Static ptr) -> + | Some (HeapStatic ptr) -> let (set_new_val, get_new_val) = new_local env "new_val" in set_new_val ^^ compile_unboxed_const ptr ^^ get_new_val ^^ Heap.store_field 1l - | Some (Deferred d) -> fatal "set_val: %s is deferred" var + | Some (Const _) -> fatal "set_val: %s is const" var | None -> fatal "set_val: %s missing" var (* Returns the payload (optimized representation) *) @@ -4531,10 +4529,10 @@ module Var = struct SR.Vanilla, G.i (LocalGet (nr i)) | Some (HeapInd (i, off)) -> SR.Vanilla, G.i (LocalGet (nr i)) ^^ Heap.load_field off - | Some (Static i) -> + | Some (HeapStatic i) -> SR.Vanilla, compile_unboxed_const i ^^ Heap.load_field 1l - | Some (Deferred d) -> - d.stack_rep, d.materialize env + | Some (Const c) -> + SR.Const c, G.nop | None -> assert false (* Returns the payload (vanilla representation) *) @@ -4561,15 +4559,6 @@ module Var = struct let restore_code = G.i (LocalSet (nr j)) in (ae2, restore_code) ) - | Some (Deferred d) -> - assert d.is_local; - ( d.materialize old_env ^^ - StackRep.adjust old_env d.stack_rep SR.Vanilla - , fun new_env ae1 -> - let (ae2, j) = VarEnv.add_direct_local new_env ae1 var in - let restore_code = G.i (LocalSet (nr j)) - in (ae2, restore_code) - ) | _ -> assert false (* Returns a pointer to a heap allocated box for this. @@ -4580,7 +4569,7 @@ module Var = struct let get_val_ptr env ae var = match VarEnv.lookup_var ae var with | Some (HeapInd (i, 1l)) -> G.i (LocalGet (nr i)) - | Some (Static _) -> assert false (* we never do this on the toplevel *) + | Some (HeapStatic _) -> assert false (* we never do this on the toplevel *) | _ -> field_box env (get_val_vanilla env ae var) end (* Var *) @@ -4620,7 +4609,7 @@ module FuncDec = struct | Type.Shared Type.Query -> G.i Nop | _ -> assert false - let compile_static_message outer_env outer_ae sort control args mk_body ret_tys at : E.func_with_names = + let compile_const_message outer_env outer_ae sort control args mk_body ret_tys at : E.func_with_names = let ae0 = VarEnv.mk_fun_ae outer_ae in Func.of_body outer_env [] [] (fun env -> G.with_region at ( (* reply early for a oneway *) @@ -4645,12 +4634,12 @@ module FuncDec = struct let (fi, fill) = E.reserve_fun pre_env name in if Type.is_shared_sort sort then begin - ( SR.StaticMessage fi, fun env ae -> - fill (compile_static_message env ae sort control args mk_body ret_tys at) + ( Const.Message fi, fun env ae -> + fill (compile_const_message env ae sort control args mk_body ret_tys at) ) end else begin assert (control = Type.Returns); - ( SR.StaticFun fi, fun env ae -> + ( Const.Fun fi, fun env ae -> let restore_no_env _env ae _ = (ae, G.nop) in fill (compile_local_function env ae restore_no_env args mk_body ret_tys at) ) @@ -4729,9 +4718,9 @@ module FuncDec = struct if captured = [] then - let (st, fill) = closed env sort control name args mk_body ret_tys at in + let (c, fill) = closed env sort control name args mk_body ret_tys at in fill env ae; - (SR.StaticThing st, G.nop) + (SR.Const c, G.nop) else closure env ae sort control name captured args mk_body ret_tys at (* Returns the index of a saved closure *) @@ -4950,7 +4939,7 @@ module AllocHow = struct (* When compiling a (recursive) block, we need to do a dependency analysis, to find out how the things are allocated. The options are: - - static: completely known, constant, not stored anywhere (think static function) + - const: completely known, constant, not stored anywhere (think static function) (no need to mention in a closure) - local: only needed locally, stored in a Wasm local, immutable (can be copied into a closure by value) @@ -4965,9 +4954,9 @@ module AllocHow = struct to avoid turning function references into closures. The rules are: - - functions are static, unless they capture something that is not a static + - functions are const, unless they capture something that is not a const function or a static heap allocation. - in particular, top-level functions are always static + in particular, top-level functions are always const - everything that is captured on the top-level needs to be statically heap-allocated - everything that is captured before it is defined, or is captured and mutable @@ -4981,8 +4970,8 @@ module AllocHow = struct (* We represent this as a lattice as follows: *) - type how = Static | LocalImmut | LocalMut | StoreHeap | StoreStatic - type allocHow = how M.t (* absent means static *) + type how = Const | LocalImmut | LocalMut | StoreHeap | StoreStatic + type allocHow = how M.t let disjoint_union : allocHow -> allocHow -> allocHow = M.union (fun v _ _ -> fatal "AllocHow.disjoint_union: %s" v) @@ -4997,7 +4986,7 @@ module AllocHow = struct | _, LocalMut | LocalMut, _ -> LocalMut | _, LocalImmut | LocalImmut, _ -> LocalImmut - | Static, Static -> Static + | Const, Const -> Const )) let joins = List.fold_left join M.empty @@ -5017,12 +5006,12 @@ module AllocHow = struct | LocalMut -> true | _ -> false - let is_not_static _ = function - | Static -> false + let is_not_const _ : how -> bool = function + | Const -> false | _ -> true - let require_closure _ = function - | Static -> false + let require_closure _ : how -> bool = function + | Const -> false | StoreStatic -> false | _ -> true @@ -5044,7 +5033,7 @@ module AllocHow = struct map_of_set StoreStatic (S.inter (set_of_map (M.filter is_local how)) captured) - let is_static_exp exp = match exp.it with + let is_const_exp exp = match exp.it with | FuncE _ -> true | _ -> false @@ -5061,16 +5050,16 @@ module AllocHow = struct map_of_set LocalMut d (* Static expressions on the top-level: - - need to be static forms + - need to be constant forms - all non-captured free variables must be static - all captured variables must be static or static-heap, if not on top level (top level captures variables will be forced to be static-heap below, via how2) *) | LetD ({it = VarP _; _}, e) when - is_static_exp e && - disjoint (Freevars.eager_vars f) (set_of_map (M.filter is_not_static how_all)) && + is_const_exp e && + disjoint (Freevars.eager_vars f) (set_of_map (M.filter is_not_const how_all)) && (lvl = TopLvl || disjoint (Freevars.captured_vars f) (set_of_map (M.filter require_closure how_all))) - -> map_of_set Static d + -> map_of_set (Const : how) d (* Everything else needs at least a local *) @@ -5088,18 +5077,17 @@ module AllocHow = struct (* we assume things are mutable, as we do not know better here *) let how_of_ae ae : allocHow = M.map (fun l -> match l with - | VarLoc.Deferred d when d.VarLoc.is_local -> LocalMut (* conservatively assumes immutable *) - | VarLoc.Deferred d -> Static - | VarLoc.Static _ -> StoreStatic - | VarLoc.Local _ -> LocalMut (* conservatively assume immutable *) - | VarLoc.HeapInd _ -> StoreHeap + | VarEnv.Const _ -> (Const : how) + | VarEnv.HeapStatic _ -> StoreStatic + | VarEnv.Local _ -> LocalMut (* conservatively assume immutable *) + | VarEnv.HeapInd _ -> StoreHeap ) ae.VarEnv.vars let decs (ae : VarEnv.t) lvl decs captured_in_body : allocHow = let how_outer = how_of_ae ae in let defined_here = snd (Freevars.decs decs) in (* TODO: implement gather_decs more directly *) let how_outer = Freevars.diff how_outer defined_here in (* shadowing *) - let how0 = map_of_set Static defined_here in + let how0 = map_of_set (Const : how) defined_here in let captured = S.inter defined_here captured_in_body in let rec go how = let seen, how1 = List.fold_left (dec lvl how_outer) (S.empty, how) decs in @@ -5113,7 +5101,7 @@ module AllocHow = struct based on how we want to store them. *) let add_local env ae how name : VarEnv.t * G.t = match M.find name how with - | Static -> (ae, G.nop) + | (Const : how) -> (ae, G.nop) | LocalImmut | LocalMut -> let (ae1, i) = VarEnv.add_direct_local env ae name in (ae1, G.nop) @@ -5127,7 +5115,7 @@ module AllocHow = struct let tag = bytes_of_int32 (Tagged.int_of_tag Tagged.MutBox) in let zero = bytes_of_int32 0l in let ptr = E.add_mutable_static_bytes env (tag ^ zero) in - let ae1 = VarEnv.add_local_static ae name ptr in + let ae1 = VarEnv.add_local_heap_static ae name ptr in (ae1, G.nop) end (* AllocHow *) @@ -5825,7 +5813,7 @@ and compile_exp (env : E.t) ae exp = StackRep.of_arity return_arity, let fun_sr, code1 = compile_exp env ae e1 in begin match fun_sr, sort with - | SR.StaticThing (SR.StaticFun fi), _ -> + | SR.Const (Const.Fun fi), _ -> code1 ^^ compile_unboxed_zero ^^ (* A dummy closure *) compile_exp_as env ae (StackRep.of_arity n_args) e2 ^^ (* the args *) @@ -6591,20 +6579,18 @@ and compile_dec env pre_ae how v2en dec : VarEnv.t * G.t * (VarEnv.t -> G.t) = (* A special case for public methods *) (* This relies on the fact that in the top-level mutually recursive group, no shadowing happens. *) | LetD ({it = VarP v; _}, e) when E.NameEnv.mem v v2en -> - let (static_thing, fill) = compile_static_exp env pre_ae how e in - let fi = match static_thing with - | SR.StaticMessage fi -> fi + let (const, fill) = compile_const_exp env pre_ae how e in + let fi = match const with + | Const.Message fi -> fi | _ -> assert false in - let pre_ae1 = VarEnv.add_local_deferred pre_ae v - (SR.StaticThing (SR.PublicMethod (fi, (E.NameEnv.find v v2en)))) - (fun _ -> G.nop) false in + let c = Const.PublicMethod (fi, (E.NameEnv.find v v2en)) in + let pre_ae1 = VarEnv.add_local_const pre_ae v c in ( pre_ae1, G.nop, fun ae -> fill env ae; G.nop) - (* A special case for static expressions *) - | LetD ({it = VarP v; _}, e) when AllocHow.M.find v how = AllocHow.Static -> - let (static_thing, fill) = compile_static_exp env pre_ae how e in - let pre_ae1 = VarEnv.add_local_deferred pre_ae v - (SR.StaticThing static_thing) (fun _ -> G.nop) false in + (* A special case for constant expressions *) + | LetD ({it = VarP v; _}, e) when AllocHow.M.find v how = AllocHow.Const -> + let (const, fill) = compile_const_exp env pre_ae how e in + let pre_ae1 = VarEnv.add_local_const pre_ae v const in ( pre_ae1, G.nop, fun ae -> fill env ae; G.nop) | LetD (p, e) -> @@ -6664,7 +6650,7 @@ and compile_prog env ae (ds, e) = let code2 = compile_top_lvl_expr env ae' e in (ae', code1 ^^ code2) -and compile_static_exp env pre_ae how exp = match exp.it with +and compile_const_exp env pre_ae how exp = match exp.it with | FuncE (name, sort, control, typ_binds, args, res_tys, e) -> let return_tys = match control with | Type.Returns -> res_tys @@ -6673,7 +6659,7 @@ and compile_static_exp env pre_ae how exp = match exp.it with let mk_body env ae = List.iter (fun v -> if not (VarEnv.NameEnv.mem v ae.VarEnv.vars) - then fatal "internal error: static \"%s\": captures \"%s\", not found in static environment\n" name v + then fatal "internal error: const \"%s\": captures \"%s\", not found in static environment\n" name v ) (Freevars.M.keys (Freevars.exp e)); compile_exp_as env ae (StackRep.of_arity (List.length return_tys)) e in FuncDec.closed env sort control name args mk_body return_tys exp.at @@ -6746,7 +6732,7 @@ and export_actor_field env ae (f : Ir.field) = let sr, code = Var.get_val env ae f.it.var in (* A public actor field is guaranteed to be compiled as a PublicMethod *) let fi = match sr with - | SR.StaticThing (SR.PublicMethod (fi, _)) -> fi + | SR.Const (Const.PublicMethod (fi, _)) -> fi | _ -> assert false in (* There should be no code associated with this *) assert (G.is_nop code); From 9b4dba4aaf213eab92ded84bf8fd3ce5a58cf5c9 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Thu, 16 Jan 2020 23:38:06 +0000 Subject: [PATCH 0954/1176] simplify scope inference --- src/mo_frontend/typing.ml | 48 +++++++++++++++------------------------ 1 file changed, 18 insertions(+), 30 deletions(-) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 715178e278c..730fceb95d3 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -255,8 +255,10 @@ let as_domT t = let as_codomT sort t = match sort, t.Source.it with - | T.Shared _, AsyncT (None, t2) -> T.Promises (scope_typ no_region) , as_domT t2 - | T.Shared _, AsyncT (Some t1, t2) -> T.Promises t1 , as_domT t2 + | T.Shared _, AsyncT (Some t1, t2) -> + T.Promises t1, as_domT t2 + | T.Shared _, AsyncT (None, t2) -> + T.Promises (scope_typ no_region), as_domT t2 | _ -> T.Returns, as_domT t let check_shared_return env at sort c ts = @@ -267,27 +269,14 @@ let check_shared_return env at sort c ts = | T.Shared T.Query, _, _ -> error env at "shared query function must have syntactic return type `async `" | _ -> () -let rec infer_scope env sort cs cod = +let rec infer_async_cap env sort cs tbs = let env = { env with async = C.NullCap } in - match sort, cod.it with - | T.Shared T.Query, AsyncT (typ_opt, _) (* remove this case to prevent sends from query methods *) - | T.Shared T.Write, AsyncT (typ_opt, _) - | T.Local, AsyncT (typ_opt, _) -> - let typ = match typ_opt with Some typ -> typ | None -> scope_typ no_region in - let t = check_typ env typ in - (match T.close cs t with - | T.Var (_, n) -> - let c = (List.nth cs n) in - { env with typs = T.Env.add scope_id (List.nth cs n) env.typs; - async = C.AsyncCap c } - | _ -> - env) - | T.Shared T.Write, TupT [] -> - (match cs with (* we assume the first parameter is the scope parameter *) - | c::cs -> - { env with typs = T.Env.add scope_id c env.typs; - async = C.AsyncCap c } - | _ -> env) + match sort, cs, tbs with + (* TODO: refine T.Query *) + | (T.Shared _ | T.Local) , c::_, T.{sort = Scope; _}::_ -> + { env with typs = T.Env.add scope_id c env.typs; + async = C.AsyncCap c } + | T.Shared _, _, _ -> assert false (* impossible given sugaring *) | _ -> env and check_AsyncCap env s at = @@ -330,13 +319,12 @@ and check_typ' env typ : T.typ = T.Tup (List.map (check_typ env) typs) | FuncT (sort, binds, typ1, typ2) -> let cs, tbs, te, ce = check_typ_binds env binds in - let env' = adjoin_typs env te ce in - let env' = infer_scope env' sort.it cs typ2 in + let env' = infer_async_cap (adjoin_typs env te ce) sort.it cs tbs in let typs1 = as_domT typ1 in - let c, typs2 = as_codomT sort.it typ2 in + let cT, typs2 = as_codomT sort.it typ2 in let ts1 = List.map (check_typ env') typs1 in let ts2 = List.map (check_typ env') typs2 in - let c' = T.map_control (check_typ env') c in + let c = T.map_control (check_typ env') cT in check_shared_return env typ2.at sort.it c ts2; if Type.is_shared_sort sort.it then if not env.pre then begin @@ -357,7 +345,7 @@ and check_typ' env typ : T.typ = "shared function has non-async result type\n %s" (T.string_of_typ_expand (T.seq ts2)) end; - T.Func (sort.it, T.map_control (T.close cs) c', T.close_binds cs tbs, List.map (T.close cs) ts1, List.map (T.close cs) ts2) + T.Func (sort.it, T.map_control (T.close cs) c, T.close_binds cs tbs, List.map (T.close cs) ts1, List.map (T.close cs) ts2) | OptT typ -> T.Opt (check_typ env typ) | VariantT tags -> @@ -437,6 +425,7 @@ and check_typ_binds env typ_binds : T.con list * T.bind list * Scope.typ_env * S T.sort = if typ_bind.it.var.it = Syntax.scope_id then T.Scope else T.Type; (* HACK *) T.bound = check_typ pre_env' typ_bind.it.bound }) typ_binds in + List.iteri (fun i tb -> assert (i == 0 || T.(tb.sort = Type))) tbs; let ts = List.map (fun tb -> tb.T.bound) tbs in check_typ_binds_acyclic env typ_binds cs ts; let ks = List.map (fun t -> T.Abs ([], t)) ts in @@ -803,11 +792,10 @@ and infer_exp'' env exp : T.typ = | None -> {it = TupT []; at = no_region; note = T.Pre} in let sort, ve = check_sort_pat env sort_pat in + let cs, tbs, te, ce = check_typ_binds env typ_binds in let cT, ts2 = as_codomT sort typ in check_shared_return env typ.at sort cT ts2; - let cs, tbs, te, ce = check_typ_binds env typ_binds in - let env' = adjoin_typs env te ce in - let env' = infer_scope env' sort cs typ in + let env' = infer_async_cap (adjoin_typs env te ce) sort cs tbs in let t1, ve1 = infer_pat_exhaustive env' pat in let ve2 = T.Env.adjoin ve ve1 in let ts2 = List.map (check_typ env') ts2 in From ab77d3e46e94d7c46921accb546599c609b894e8 Mon Sep 17 00:00:00 2001 From: Enzo Haussecker Date: Thu, 16 Jan 2020 16:52:05 -0800 Subject: [PATCH 0955/1176] Add license and copyright notice. (#1125) * Add license and copyright notice * Add new line character to end of file * Move LLVM exception ahead of appendix --- LICENSE | 208 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ NOTICE | 12 ++++ 2 files changed, 220 insertions(+) create mode 100644 LICENSE create mode 100644 NOTICE diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000000..d5dadbd59b1 --- /dev/null +++ b/LICENSE @@ -0,0 +1,208 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, and + distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by the + copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all other + entities that control, are controlled by, or are under common control with + that entity. For the purposes of this definition, "control" means (i) the + power, direct or indirect, to cause the direction or management of such + entity, whether by contract or otherwise, or (ii) ownership of fifty percent + (50%) or more of the outstanding shares, or (iii) beneficial ownership of + such entity. + + "You" (or "Your") shall mean an individual or Legal Entity exercising + permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation source, and + configuration files. + + "Object" form shall mean any form resulting from mechanical transformation + or translation of a Source form, including but not limited to compiled + object code, generated documentation, and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or Object form, + made available under the License, as indicated by a copyright notice that is + included in or attached to the work (an example is provided in the Appendix + below). + + "Derivative Works" shall mean any work, whether in Source or Object form, + that is based on (or derived from) the Work and for which the editorial + revisions, annotations, elaborations, or other modifications represent, as a + whole, an original work of authorship. For the purposes of this License, + Derivative Works shall not include works that remain separable from, or + merely link (or bind by name) to the interfaces of, the Work and Derivative + Works thereof. + + "Contribution" shall mean any work of authorship, including the original + version of the Work and any modifications or additions to that Work or + Derivative Works thereof, that is intentionally submitted to Licensor for + inclusion in the Work by the copyright owner or by an individual or Legal + Entity authorized to submit on behalf of the copyright owner. For the + purposes of this definition, "submitted" means any form of electronic, + verbal, or written communication sent to the Licensor or its + representatives, including but not limited to communication on electronic + mailing lists, source code control systems, and issue tracking systems that + are managed by, or on behalf of, the Licensor for the purpose of discussing + and improving the Work, but excluding communication that is conspicuously + marked or otherwise designated in writing by the copyright owner as "Not a + Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity on + behalf of whom a Contribution has been received by Licensor and subsequently + incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this + License, each Contributor hereby grants to You a perpetual, worldwide, + non-exclusive, no-charge, royalty-free, irrevocable copyright license to + reproduce, prepare Derivative Works of, publicly display, publicly perform, + sublicense, and distribute the Work and such Derivative Works in Source or + Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this + License, each Contributor hereby grants to You a perpetual, worldwide, + non-exclusive, no-charge, royalty-free, irrevocable (except as stated in + this section) patent license to make, have made, use, offer to sell, sell, + import, and otherwise transfer the Work, where such license applies only to + those patent claims licensable by such Contributor that are necessarily + infringed by their Contribution(s) alone or by combination of their + Contribution(s) with the Work to which such Contribution(s) was submitted. + If You institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work or a + Contribution incorporated within the Work constitutes direct or contributory + patent infringement, then any patent licenses granted to You under this + License for that Work shall terminate as of the date such litigation is + filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or + Derivative Works thereof in any medium, with or without modifications, and + in Source or Object form, provided that You meet the following conditions: + + a. You must give any other recipients of the Work or Derivative Works a + copy of this License; and + + b. You must cause any modified files to carry prominent notices stating + that You changed the files; and + + c. You must retain, in the Source form of any Derivative Works that You + distribute, all copyright, patent, trademark, and attribution notices + from the Source form of the Work, excluding those notices that do not + pertain to any part of the Derivative Works; and + + d. If the Work includes a "NOTICE" text file as part of its distribution, + then any Derivative Works that You distribute must include a readable + copy of the attribution notices contained within such NOTICE file, + excluding those notices that do not pertain to any part of the Derivative + Works, in at least one of the following places: within a NOTICE text file + distributed as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, within a + display generated by the Derivative Works, if and wherever such + third-party notices normally appear. The contents of the NOTICE file are + for informational purposes only and do not modify the License. You may + add Your own attribution notices within Derivative Works that You + distribute, alongside or as an addendum to the NOTICE text from the Work, + provided that such additional attribution notices cannot be construed as + modifying the License. + + You may add Your own copyright statement to Your modifications and may + provide additional or different license terms and conditions for use, + reproduction, or distribution of Your modifications, or for any such + Derivative Works as a whole, provided Your use, reproduction, and + distribution of the Work otherwise complies with the conditions stated in + this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any + Contribution intentionally submitted for inclusion in the Work by You to the + Licensor shall be under the terms and conditions of this License, without + any additional terms or conditions. Notwithstanding the above, nothing + herein shall supersede or modify the terms of any separate license agreement + you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, + trademarks, service marks, or product names of the Licensor, except as + required for reasonable and customary use in describing the origin of the + Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in + writing, Licensor provides the Work (and each Contributor provides its + Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied, including, without limitation, any + warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or + FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining + the appropriateness of using or redistributing the Work and assume any risks + associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in + tort (including negligence), contract, or otherwise, unless required by + applicable law (such as deliberate and grossly negligent acts) or agreed to + in writing, shall any Contributor be liable to You for damages, including + any direct, indirect, special, incidental, or consequential damages of any + character arising as a result of this License or out of the use or inability + to use the Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all other + commercial damages or losses), even if such Contributor has been advised of + the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or + Derivative Works thereof, You may choose to offer, and charge a fee for, + acceptance of support, warranty, indemnity, or other liability obligations + and/or rights consistent with this License. However, in accepting such + obligations, You may act only on Your own behalf and on Your sole + responsibility, not on behalf of any other Contributor, and only if You + agree to indemnify, defend, and hold each Contributor harmless for any + liability incurred by, or claims asserted against, such Contributor by + reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +LLVM EXCEPTIONS TO THE APACHE 2.0 LICENSE + +As an exception, if, as a result of your compiling your source code, portions +of this Software are embedded into an Object form of such source code, you may +redistribute such embedded portions in such Object form without complying with +the conditions of Sections 4(a), 4(b) and 4(d) of the License. + +In addition, if you combine or link compiled forms of this Software with +software that is licensed under the GPLv2 ("Combined Software") and if a court +of competent jurisdiction determines that the patent provision (Section 3), the +indemnity provision (Section 9) or other Section of the License conflicts with +the conditions of the GPLv2, you may retroactively and prospectively choose to +deem waived or otherwise exclude such Section(s) of the License, but only in +their entirety and only with respect to the Combined Software. + +END OF LLVM EXCEPTIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate +notice, with the fields enclosed by brackets "[]" replaced with your own +identifying information. (Don't include the brackets!) The text should be +enclosed in the appropriate comment syntax for the file format. We also +recommend that a file or class name and description of purpose be included on +the same "printed page" as the copyright notice for easier identification +within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed +under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. + +END OF APPENDIX diff --git a/NOTICE b/NOTICE new file mode 100644 index 00000000000..477d5734305 --- /dev/null +++ b/NOTICE @@ -0,0 +1,12 @@ +Copyright 2020 DFINITY Stiftung + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed +under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. From c1c2ea4c2ac57b6d9c115a94343eee727b04da8a Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 17 Jan 2020 14:14:51 +0100 Subject: [PATCH 0956/1176] Remove tests/bugs (#1019) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Remove tests/bugs just found this directory, seems to be from a time before we added our regressions tests to the test suite. Most did not compile any more. Probably all long fixed. Proposing to just delete. If someone wants to go through them and turn them into proper tests, that’s fine for me. * move freeclass1 and unboundclass to `test/fail` and accept as-is Co-authored-by: Gabor Greif --- test/{bugs => fail}/freeclass1.mo | 0 test/fail/ok/freeclass1.tc.ok | 1 + test/fail/ok/freeclass1.tc.ret.ok | 1 + test/fail/ok/unboundclass.tc.ok | 1 + test/fail/ok/unboundclass.tc.ret.ok | 1 + test/fail/ok/usedefbug.tc.ok | 1 + test/fail/ok/usedefbug.tc.ret.ok | 1 + test/{bugs => fail}/unboundclass.mo | 0 test/{bugs => fail}/usedefbug.mo | 0 9 files changed, 6 insertions(+) rename test/{bugs => fail}/freeclass1.mo (100%) create mode 100644 test/fail/ok/freeclass1.tc.ok create mode 100644 test/fail/ok/freeclass1.tc.ret.ok create mode 100644 test/fail/ok/unboundclass.tc.ok create mode 100644 test/fail/ok/unboundclass.tc.ret.ok create mode 100644 test/fail/ok/usedefbug.tc.ok create mode 100644 test/fail/ok/usedefbug.tc.ret.ok rename test/{bugs => fail}/unboundclass.mo (100%) rename test/{bugs => fail}/usedefbug.mo (100%) diff --git a/test/bugs/freeclass1.mo b/test/fail/freeclass1.mo similarity index 100% rename from test/bugs/freeclass1.mo rename to test/fail/freeclass1.mo diff --git a/test/fail/ok/freeclass1.tc.ok b/test/fail/ok/freeclass1.tc.ok new file mode 100644 index 00000000000..b3b22b5d8a2 --- /dev/null +++ b/test/fail/ok/freeclass1.tc.ok @@ -0,0 +1 @@ +freeclass1.mo:8.13-8.16: type error, cannot infer type of forward variable Foo diff --git a/test/fail/ok/freeclass1.tc.ret.ok b/test/fail/ok/freeclass1.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/freeclass1.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/unboundclass.tc.ok b/test/fail/ok/unboundclass.tc.ok new file mode 100644 index 00000000000..717decb562f --- /dev/null +++ b/test/fail/ok/unboundclass.tc.ok @@ -0,0 +1 @@ +unboundclass.mo:6.13-6.16: type error, cannot infer type of forward variable Foo diff --git a/test/fail/ok/unboundclass.tc.ret.ok b/test/fail/ok/unboundclass.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/unboundclass.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/usedefbug.tc.ok b/test/fail/ok/usedefbug.tc.ok new file mode 100644 index 00000000000..9af1f9c49b5 --- /dev/null +++ b/test/fail/ok/usedefbug.tc.ok @@ -0,0 +1 @@ +usedefbug.mo:7.3-7.22: definedness error, cannot use g before g has been defined diff --git a/test/fail/ok/usedefbug.tc.ret.ok b/test/fail/ok/usedefbug.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/usedefbug.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/bugs/unboundclass.mo b/test/fail/unboundclass.mo similarity index 100% rename from test/bugs/unboundclass.mo rename to test/fail/unboundclass.mo diff --git a/test/bugs/usedefbug.mo b/test/fail/usedefbug.mo similarity index 100% rename from test/bugs/usedefbug.mo rename to test/fail/usedefbug.mo From 2c5ab971bf432b900d3219f5a89ba757c59872f8 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Fri, 17 Jan 2020 15:00:27 +0000 Subject: [PATCH 0957/1176] remove poly arg from Control.Promise --- src/codegen/compile.ml | 6 +-- src/ir_def/check_ir.ml | 11 +++-- src/ir_def/construct.ml | 2 +- src/ir_def/ir.ml | 2 +- src/ir_interpreter/interpret_ir.ml | 7 ++- src/ir_passes/async.ml | 9 ++-- src/lowering/desugar.ml | 8 ++-- src/mo_def/syntax.ml | 56 ++++++------------------ src/mo_frontend/parser.mly | 11 ++--- src/mo_frontend/typing.ml | 44 +++++++++---------- src/mo_idl/mo_to_idl.ml | 7 ++- src/mo_interpreter/interpret.ml | 4 +- src/mo_types/arrange_type.ml | 2 +- src/mo_types/type.ml | 69 +++++++++--------------------- src/mo_types/type.mli | 11 +++-- src/mo_values/call_conv.ml | 8 ++-- src/mo_values/call_conv.mli | 2 +- src/pipeline/pipeline.ml | 2 +- test/fail/ok/abstract-msgs.tc.ok | 16 +++---- 19 files changed, 104 insertions(+), 173 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 1fceb9a2d0a..752e27616ab 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -6167,7 +6167,7 @@ and compile_exp (env : E.t) ae exp = let return_arity = match control with | Type.Returns -> List.length ret_tys | Type.Replies -> 0 - | Type.Promises _ -> assert false in + | Type.Promises -> assert false in StackRep.of_arity return_arity, let fun_sr, code1 = compile_exp env ae e1 in @@ -6232,7 +6232,7 @@ and compile_exp (env : E.t) ae exp = let return_tys = match control with | Type.Returns -> res_tys | Type.Replies -> [] - | Type.Promises _ -> assert false in + | Type.Promises -> assert false in let return_arity = List.length return_tys in let mk_body env1 ae1 = compile_exp_as env1 ae1 (StackRep.of_arity return_arity) e in FuncDec.lit env ae x sort control captured args mk_body return_tys exp.at @@ -6600,7 +6600,7 @@ and compile_static_exp env pre_ae how exp = match exp.it with let return_tys = match control with | Type.Returns -> res_tys | Type.Replies -> [] - | Type.Promises _ -> assert false in + | Type.Promises -> assert false in let mk_body env ae = assert begin (* Is this really closed? *) List.for_all (fun v -> VarEnv.NameEnv.mem v ae.VarEnv.vars) diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 3ea2017e1f7..fb9b0f28b1f 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -161,7 +161,6 @@ let rec check_typ env typ : unit = let cs, ce = check_typ_binds env binds in let env' = adjoin_cons env ce in let ts = List.map (fun c -> T.Con (c, [])) cs in - let control = T.map_control (T.open_ ts) control in let ts1 = List.map (T.open_ ts) ts1 in let ts2 = List.map (T.open_ ts) ts2 in List.iter (check_typ env') ts1; @@ -175,8 +174,7 @@ let rec check_typ env typ : unit = check env' no_region (ts2 = []) "one-shot function cannot have non-unit return types:\n %s" (T.string_of_typ_expand (T.seq ts2)); - | T.Promises t' -> - check_typ env' t'; + | T.Promises -> check env no_region env.flavor.Ir.has_async_typ "promising function in post-async flavor"; check env' no_region (List.for_all T.shared ts2) @@ -479,7 +477,7 @@ let rec check_exp env (exp:Ir.exp) : unit = check_inst_bounds env tbs insts exp.at; check_exp env exp2; let t_arg = T.open_ insts (T.seq arg_tys) in - let t_ret = T.open_ insts (T.codom control ret_tys) in + let t_ret = T.codom control (fun () -> List.hd insts) (List.map (T.open_ insts) ret_tys) in if T.is_shared_sort sort then begin check_concrete env exp.at t_arg; check_concrete env exp.at t_ret; @@ -609,13 +607,14 @@ let rec check_exp env (exp:Ir.exp) : unit = T.unit <: t | FuncE (x, sort, control, typ_binds, args, ret_tys, exp) -> let cs, tbs, ce = check_open_typ_binds env typ_binds in + let ts = List.map (fun c -> T.Con(c, [])) cs in let env' = adjoin_cons env ce in let ve = check_args env' args in List.iter (check_typ env') ret_tys; check ((T.is_shared_sort sort && T.is_promising control) ==> isAsyncE exp) "shared function with async type has non-async body"; if T.is_shared_sort sort then List.iter (check_concrete env exp.at) ret_tys; - let codom = T.codom control ret_tys in + let codom = T.codom control (fun () -> List.hd ts) ret_tys in let env'' = {env' with labs = T.Env.empty; rets = Some codom; async = None} in check_exp (adjoin_vals env'' ve) exp; @@ -624,7 +623,7 @@ let rec check_exp env (exp:Ir.exp) : unit = let ts1 = List.map (fun a -> a.note) args in if T.is_shared_sort sort then List.iter (check_concrete env exp.at) ts1; let fun_ty = T.Func - ( sort, T.map_control (T.close cs) control + ( sort, control , tbs, List.map (T.close cs) ts1, List.map (T.close cs) ret_tys ) in fun_ty <: t diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index 6af201dc6cc..7fd34eb3210 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -487,7 +487,7 @@ let forall tbs e = { e with it = FuncE(n, s, c1, tbs, xs, ts, exp); note = { e.note with - note_typ = T.Func(s, T.map_control (T.close cs) c2, close_typ_binds cs tbs, + note_typ = T.Func(s, c2, close_typ_binds cs tbs, List.map (T.close cs) ts1, List.map (T.close cs) ts2) }} diff --git a/src/ir_def/ir.ml b/src/ir_def/ir.ml index 6440ad2eebb..26bb28132d9 100644 --- a/src/ir_def/ir.ml +++ b/src/ir_def/ir.ml @@ -88,7 +88,7 @@ and exp' = | DeclareE of id * Type.typ * exp (* local promise *) | DefineE of id * mut * exp (* promise fulfillment *) | FuncE of (* function *) - string * Type.func_sort * Type.typ Type.control * typ_bind list * arg list * Type.typ list * exp + string * Type.func_sort * Type.control * typ_bind list * arg list * Type.typ list * exp | SelfCallE of Type.typ list * exp * exp * exp (* essentially ICCallPrim (FuncE shared…) *) | ActorE of id * dec list * field list * Type.typ (* actor *) | NewObjE of Type.obj_sort * field list * Type.typ (* make an object *) diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index 9550e663706..768ec56b50e 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -207,7 +207,7 @@ let make_async_message env id call_conv f = assert env.flavor.has_async_typ; let open CC in match call_conv with - | {sort = T.Shared s; control = T.Promises _; _} -> + | {sort = T.Shared s; control = T.Promises; _} -> Value.async_func s call_conv.n_args call_conv.n_res (fun c v k -> let async = make_async () in actor_msg env id f c v (fun v_async -> @@ -233,7 +233,7 @@ let make_replying_message env id call_conv f = let make_message env x cc f : V.value = match cc.CC.control with | T.Returns -> make_unit_message env x cc f - | T.Promises _ -> make_async_message env x cc f + | T.Promises -> make_async_message env x cc f | T.Replies -> make_replying_message env x cc f @@ -535,8 +535,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = (fun env' -> interpret_exp env' e) in let v = make_message env x cc f in k v - | FuncE (x, sort, controlT, _typbinds, args, ret_typs, e) -> - let control = Type.map_control (fun _ -> ()) controlT in + | FuncE (x, sort, control, _typbinds, args, ret_typs, e) -> let cc = { sort; control; n_args = List.length args; n_res = List.length ret_typs } in let f = interpret_func env exp.at sort x args (fun env' -> interpret_exp env' e) in diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index 9eda220aca0..9ee39167e35 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -115,7 +115,7 @@ let letEta e scope = let isAwaitableFunc exp = match typ exp with - | T.Func (T.Shared _,T.Promises _,_,_,_) -> true + | T.Func (T.Shared _, T.Promises, _, _, _) -> true | _ -> false (* Given sequence type ts, bind e of type (seq ts) to a @@ -167,7 +167,7 @@ let transform mode env prog = | Array t -> Array (t_typ t) | Tup ts -> Tup (List.map t_typ ts) | Func (s, c, tbs, ts1, ts2) -> - let c' = match c with T.Promises _ -> T.Replies | _ -> c in + let c' = match c with T.Promises -> T.Replies | _ -> c in Func (s, c', List.map t_bind tbs, List.map t_typ ts1, List.map t_typ ts2) | Opt t -> Opt (t_typ t) | Variant fs -> Variant (List.map t_field fs) @@ -279,7 +279,7 @@ let transform mode env prog = | CallE (exp1, typs, exp2) when isAwaitableFunc exp1 -> let ts1,ts2 = match typ exp1 with - | T.Func (T.Shared _, T.Promises _,tbs,ts1,ts2) -> + | T.Func (T.Shared _, T.Promises, tbs, ts1, ts2) -> List.map (fun t -> t_typ (T.open_ typs t)) ts1, List.map (fun t -> t_typ (T.open_ typs t)) ts2 | _ -> assert(false) @@ -339,8 +339,7 @@ let transform mode env prog = | T.Shared s' -> begin match c, exp with - | Promises _t0, exp -> - (* TODO maybe check _t0 = t0 below *) + | Promises, exp -> let ret_tys = List.map t_typ ret_tys in let args' = t_args args in let typbinds' = t_typ_binds typbinds in diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 0a604670666..22a7b79e566 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -98,8 +98,7 @@ and exp' at note = function let tbs' = typ_binds tbs in let vars = List.map (fun (tb : I.typ_bind) -> T.Con (tb.it.I.con, [])) tbs' in let tys = List.map (T.open_ vars) res_tys in - let control' = T.map_control (T.open_ vars) control in - I.FuncE (name, s, control', tbs', args, tys, wrap (exp e)) + I.FuncE (name, s, control, tbs', args, tys, wrap (exp e)) (* Primitive functions in the prelude have particular shapes *) | S.CallE ({it=S.AnnotE ({it=S.PrimE p;_}, _);note;_}, _, e) when Lib.String.chop_prefix "num_conv" p <> None -> @@ -331,9 +330,8 @@ and dec' at n d = match d with in let varPat = {it = I.VarP id'.it; at = at; note = fun_typ } in let args, wrap, control, _n_res = to_args n.S.note_typ None p in - let control' = T.map_control (T.open_ inst) control in let fn = { - it = I.FuncE (id.it, sort, control', typ_binds tbs, args, [obj_typ], wrap + it = I.FuncE (id.it, sort, control, typ_binds tbs, args, [obj_typ], wrap { it = obj at s (Some self_id) es obj_typ; at = at; note = { I.note_typ = obj_typ; I.note_eff = T.Triv } }); @@ -407,7 +405,7 @@ and to_arg p : (Ir.arg * (Ir.exp -> Ir.exp)) = arg_of_exp v, (fun e -> blockE [letP (pat p) v] e) -and to_args typ po p : Ir.arg list * (Ir.exp -> Ir.exp) * T.typ T.control * T.typ list = +and to_args typ po p : Ir.arg list * (Ir.exp -> Ir.exp) * T.control * T.typ list = let sort, control, n_args, res_tys = match typ with | Type.Func (sort, control, tbds, dom, res) -> diff --git a/src/mo_def/syntax.ml b/src/mo_def/syntax.ml index f1d8bd81bf8..e78810aea23 100644 --- a/src/mo_def/syntax.ml +++ b/src/mo_def/syntax.ml @@ -55,8 +55,9 @@ and typ_field' = {id : id; typ : typ; mut : mut} and typ_tag = typ_tag' Source.phrase and typ_tag' = {tag : id; typ : typ} +and bind_sort = Type.bind_sort Source.phrase and typ_bind = (typ_bind', Type.con option) Source.annotated_phrase -and typ_bind' = {var : id; bound : typ} +and typ_bind' = {var : id; sort : bind_sort; bound : typ;} (* Literals *) @@ -254,59 +255,28 @@ let scope_typ region = at = region; note = Type.Pre }) -let scope_id = "@" - let scope_bind() = { var = scope_id @@ no_region; + sort = Type.Scope @@ no_region; bound = PrimT "Any" @! no_region } @= no_region -let pun_id id = - { var = id.it @@ no_region; - bound = PrimT "Any" @! no_region - } @= no_region - -let rec is_scope_typ t = - match t.it with - | PathT (p, []) -> - (match p.it with - | IdH id -> - id.it = scope_id - | _ -> false) - | ParT t -> is_scope_typ t - | _ -> false - -let rec as_idT t = - match t.it with - | PathT (p, []) -> - (match p.it with - | IdH id -> - Some id - | _ -> None) - | ParT t -> as_idT t - | _ -> None - - -let ensure_scope_bind tbs = - if List.exists (fun tb -> tb.it.var.it = scope_id) tbs - then tbs - else scope_bind()::tbs +let add_scope_bind tbs = scope_bind()::tbs let funcT(sort, tbs, t1, t2) = match sort.it, t2.it with - | _, AsyncT (None, _) -> - FuncT(sort, ensure_scope_bind tbs, t1, t2) - | Type.Shared _, TupT [] -> - FuncT(sort, ensure_scope_bind tbs, t1, t2) + | Type.Local, AsyncT _ -> + FuncT(sort, add_scope_bind tbs, t1, t2) + | Type.Shared _, _ -> + FuncT(sort, add_scope_bind tbs, t1, t2) | _ -> FuncT(sort, tbs, t1, t2) -let funcE (f, s, tbs, p, t_opt, e) = - match s.it, t_opt with - | _, Some { it = AsyncT (None, _); _} - | Type.Shared _, Some { it = TupT []; _} - | Type.Shared _, None -> - FuncE(f, s, ensure_scope_bind tbs, p, t_opt, e) +let funcE(f, s, tbs, p, t_opt, e) = + match s.it, t_opt, e with + | Type.Local, Some { it = AsyncT _; _}, {it = AsyncE _; _} + | Type.Shared _, _, _ -> + FuncE(f, s, add_scope_bind tbs, p, t_opt, e) | _ -> FuncE(f, s, tbs, p, t_opt, e) diff --git a/src/mo_frontend/parser.mly b/src/mo_frontend/parser.mly index 843b73bca86..e5820c3978c 100644 --- a/src/mo_frontend/parser.mly +++ b/src/mo_frontend/parser.mly @@ -283,9 +283,9 @@ typ_tag : typ_bind : | x=id SUB t=typ - { {var = x; bound = t} @= at $sloc } + { {var = x; sort = Type.Type @@ no_region; bound = t} @= at $sloc } | x=id - { {var = x; bound = PrimT "Any" @! at $sloc} @= at $sloc } + { {var = x; sort = Type.Type @@ no_region; bound = PrimT "Any" @! at $sloc} @= at $sloc } %inline scope_bind_opt : | LT tb=typ_bind GT @@ -653,13 +653,8 @@ dec_nonvar : | (false, e) -> e (* body declared as EQ e *) | (true, e) -> (* body declared as immediate block *) match t with - | Some {it = AsyncT (None,_); _} -> + | Some {it = AsyncT _; _} -> AsyncE(scope_bind(), e) @? e.at - | Some {it = AsyncT (Some typ,_); _} -> - (match as_idT typ with - | Some id -> - AsyncE(pun_id id, e) @? e.at - | _ -> AsyncE(scope_bind(), e) @? e.at) | _ -> e in let named, x = xf "func" $sloc in diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 730fceb95d3..2286573daa1 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -256,24 +256,24 @@ let as_domT t = let as_codomT sort t = match sort, t.Source.it with | T.Shared _, AsyncT (Some t1, t2) -> - T.Promises t1, as_domT t2 + T.Promises, as_domT t2 | T.Shared _, AsyncT (None, t2) -> - T.Promises (scope_typ no_region), as_domT t2 + T.Promises, as_domT t2 | _ -> T.Returns, as_domT t let check_shared_return env at sort c ts = match sort, c, ts with - | T.Shared _, T.Promises _, _ -> () - | T.Shared T.Write, T.Returns, [] -> () - | T.Shared T.Write, _, _ -> error env at "shared function must have syntactic return type `()` or `async `" - | T.Shared T.Query, _, _ -> error env at "shared query function must have syntactic return type `async `" - | _ -> () + | T.Shared _, T.Promises, _ -> () + | T.Shared T.Write, T.Returns, [] -> () + | T.Shared T.Write, _, _ -> error env at "shared function must have syntactic return type `()` or `async `" + | T.Shared T.Query, _, _ -> error env at "shared query function must have syntactic return type `async `" + | _ -> () let rec infer_async_cap env sort cs tbs = let env = { env with async = C.NullCap } in match sort, cs, tbs with (* TODO: refine T.Query *) - | (T.Shared _ | T.Local) , c::_, T.{sort = Scope; _}::_ -> + | (T.Shared _ | T.Local) , c::_, {T.sort = _ (*T.Scope*); _}::_ -> { env with typs = T.Env.add scope_id c env.typs; async = C.AsyncCap c } | T.Shared _, _, _ -> assert false (* impossible given sugaring *) @@ -321,10 +321,9 @@ and check_typ' env typ : T.typ = let cs, tbs, te, ce = check_typ_binds env binds in let env' = infer_async_cap (adjoin_typs env te ce) sort.it cs tbs in let typs1 = as_domT typ1 in - let cT, typs2 = as_codomT sort.it typ2 in + let c, typs2 = as_codomT sort.it typ2 in let ts1 = List.map (check_typ env') typs1 in let ts2 = List.map (check_typ env') typs2 in - let c = T.map_control (check_typ env') cT in check_shared_return env typ2.at sort.it c ts2; if Type.is_shared_sort sort.it then if not env.pre then begin @@ -339,13 +338,13 @@ and check_typ' env typ : T.typ = ) ts2; match c, ts2 with | T.Returns, [] when sort.it = T.Shared T.Write -> () - | T.Promises _, _ -> () + | T.Promises, _ -> () | _ -> error env typ2.at "shared function has non-async result type\n %s" (T.string_of_typ_expand (T.seq ts2)) end; - T.Func (sort.it, T.map_control (T.close cs) c, T.close_binds cs tbs, List.map (T.close cs) ts1, List.map (T.close cs) ts2) + T.Func (sort.it, c, T.close_binds cs tbs, List.map (T.close cs) ts1, List.map (T.close cs) ts2) | OptT typ -> T.Opt (check_typ env typ) | VariantT tags -> @@ -422,10 +421,10 @@ and check_typ_binds env typ_binds : T.con list * T.bind list * Scope.typ_env * S let pre_env' = add_typs {env with pre = true} xs cs in let tbs = List.map (fun typ_bind -> { T.var = typ_bind.it.var.it; - T.sort = if typ_bind.it.var.it = Syntax.scope_id then T.Scope else T.Type; (* HACK *) + T.sort = typ_bind.it.sort.it; T.bound = check_typ pre_env' typ_bind.it.bound }) typ_binds in - List.iteri (fun i tb -> assert (i == 0 || T.(tb.sort = Type))) tbs; + List.iteri (fun i tb -> assert (i == 0 || (tb.T.sort = T.Type))) tbs; let ts = List.map (fun tb -> tb.T.bound) tbs in check_typ_binds_acyclic env typ_binds cs ts; let ks = List.map (fun t -> T.Abs ([], t)) ts in @@ -793,14 +792,14 @@ and infer_exp'' env exp : T.typ = in let sort, ve = check_sort_pat env sort_pat in let cs, tbs, te, ce = check_typ_binds env typ_binds in - let cT, ts2 = as_codomT sort typ in - check_shared_return env typ.at sort cT ts2; + let ts = List.map (fun c -> T.Con(c,[])) cs in + let c, ts2 = as_codomT sort typ in + check_shared_return env typ.at sort c ts2; let env' = infer_async_cap (adjoin_typs env te ce) sort cs tbs in let t1, ve1 = infer_pat_exhaustive env' pat in let ve2 = T.Env.adjoin ve ve1 in let ts2 = List.map (check_typ env') ts2 in - let c = T.map_control (check_typ env') cT in - let codom = T.codom c ts2 in + let codom = T.codom c (fun () -> List.hd ts) ts2 in if not env.pre then begin let env'' = { env' with @@ -821,8 +820,8 @@ and infer_exp'' env exp : T.typ = (T.string_of_typ_expand t); ) ts2; match c, ts2 with - | T.Returns, [] when sort = T.Shared T.Write -> () - | T.Promises _, _ -> + | T.Returns, [] when sort = T.Shared T.Write -> () + | T.Promises, _ -> if not (isAsyncE exp) then error env exp.at "shared function with async result type has non-async body" @@ -832,7 +831,7 @@ and infer_exp'' env exp : T.typ = end end; let ts1 = match pat.it with TupP _ -> T.seq_of_tup t1 | _ -> [t1] in - T.Func (sort, T.map_control (T.close cs) c, T.close_binds cs tbs, List.map (T.close cs) ts1, List.map (T.close cs) ts2) + T.Func (sort, c, T.close_binds cs tbs, List.map (T.close cs) ts1, List.map (T.close cs) ts2) | CallE (exp1, inst, exp2) -> let typs = inst.it in let t1 = infer_exp_promote env exp1 in @@ -1127,13 +1126,14 @@ and check_exp' env0 t exp : T.typ = (String.concat " or\n " ss) ); t + (* TODO: allow mono shared with one scope par *) | FuncE (_, sort_pat, [], pat, typ_opt, exp), T.Func (s, c, [], ts1, ts2) -> let sort, ve = check_sort_pat env sort_pat in if not env.pre && not env0.in_actor && T.is_shared_sort sort then error_in [Flags.ICMode; Flags.StubMode] env exp.at "a shared function is only allowed as a public field of an actor"; let ve1 = check_pat_exhaustive env (T.seq ts1) pat in let ve2 = T.Env.adjoin ve ve1 in - let codom = T.codom c ts2 in + let codom = T.codom c (fun () -> assert false) ts2 in let t2 = match typ_opt with | None -> codom diff --git a/src/mo_idl/mo_to_idl.ml b/src/mo_idl/mo_to_idl.ml index 4185c77a48e..6099a742066 100644 --- a/src/mo_idl/mo_to_idl.ml +++ b/src/mo_idl/mo_to_idl.ml @@ -106,14 +106,13 @@ let rec typ vs t = I.VariantT (List.map (field vs) fs) | Func (Shared s, c, tbs, ts1, ts2) -> let nons = List.map (fun _ -> Non) tbs in - let c, ts1, ts2 = - (map_control (open_ nons) c, - List.map (open_ nons) ts1, + let ts1, ts2 = + (List.map (open_ nons) ts1, List.map (open_ nons) ts2) in let t1 = args vs ts1 in (match ts2, c with | [], Returns -> I.FuncT ([I.Oneway @@ no_region], t1, []) - | ts, Promises _ -> + | ts, Promises -> I.FuncT ( (match s with | Query -> [I.Query @@ no_region] diff --git a/src/mo_interpreter/interpret.ml b/src/mo_interpreter/interpret.ml index 66d0638dd9f..a88d1753865 100644 --- a/src/mo_interpreter/interpret.ml +++ b/src/mo_interpreter/interpret.ml @@ -217,7 +217,7 @@ let make_async_message env id v = let open CC in let call_conv, f = V.as_func v in match call_conv with - | {sort = T.Shared s; control = T.Promises _; _} -> + | {sort = T.Shared s; control = T.Promises; _} -> Value.async_func s call_conv.n_args call_conv.n_res (fun c v k -> let async = make_async () in actor_msg env id f c v (fun v_async -> @@ -232,7 +232,7 @@ let make_async_message env id v = let make_message env name t v : V.value = match t with | T.Func (_, T.Returns, _, _, _) -> make_unit_message env name v - | T.Func (_, T.Promises _, _, _, _) -> make_async_message env name v + | T.Func (_, T.Promises, _, _, _) -> make_async_message env name v | _ -> (* assert false *) failwith (Printf.sprintf "actorfield: %s %s" name (T.string_of_typ t)) diff --git a/src/mo_types/arrange_type.ml b/src/mo_types/arrange_type.ml index 53c0c7f54d1..ddc813d1052 100644 --- a/src/mo_types/arrange_type.ml +++ b/src/mo_types/arrange_type.ml @@ -5,7 +5,7 @@ let ($$) head inner = Node (head, inner) let control c = match c with | Returns -> "Returns" - | Promises t -> "Promises ?" + | Promises -> "Promises" | Replies -> "Replies" let obj_sort s = match s with diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index 6382a466ee5..75ecadb6d84 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -2,9 +2,9 @@ type lab = string type var = string -type 'a control = +type control = | Returns (* regular local function or one-shot shared function *) - | Promises of 'a (* shared function producing a future value upon call *) + | Promises (* shared function producing a future value upon call *) | Replies (* (IR only): responds asynchronously using `reply` *) type obj_sort = Object | Actor | Module @@ -46,7 +46,7 @@ and typ = | Array of typ (* array *) | Opt of typ (* option *) | Tup of typ list (* tuple *) - | Func of func_sort * typ control * bind list * typ list * typ list (* function *) + | Func of func_sort * control * bind list * typ list * typ list (* function *) | Async of typ * typ (* future *) | Mut of typ (* mutable type *) | Any (* top *) @@ -64,22 +64,14 @@ and kind = | Def of bind list * typ | Abs of bind list * typ - (* Function sorts *) let is_shared_sort sort = sort <> Local let is_promising c = match c with - | Promises _ -> true + | Promises -> true | _ -> false -let map_control f c = - match c with - | Promises x -> Promises (f x) - | Replies -> Replies - | Returns -> Returns - - (* Constructors *) let set_kind c k = @@ -156,9 +148,10 @@ let prim = function let seq = function [t] -> t | ts -> Tup ts -let codom c ts = match c with - | Promises t -> Async (t, seq ts) - | Returns -> seq ts + +let codom c to_scope ts2 = match c with + | Promises -> Async (to_scope(), seq ts2) + | Returns -> seq ts2 | Replies -> Tup [] (* Coercions *) @@ -179,7 +172,7 @@ let rec shift i n t = | Tup ts -> Tup (List.map (shift i n) ts) | Func (s, c, tbs, ts1, ts2) -> let i' = i + List.length tbs in - Func (s, map_control (shift i' n) c, List.map (shift_bind i' n) tbs, List.map (shift i' n) ts1, List.map (shift i' n) ts2) + Func (s, c, List.map (shift_bind i' n) tbs, List.map (shift i' n) ts1, List.map (shift i' n) ts2) | Opt t -> Opt (shift i n t) | Async (t1, t2) -> Async (shift i n t1, shift i n t2) | Obj (s, fs) -> Obj (s, List.map (shift_field n i) fs) @@ -224,7 +217,7 @@ let rec subst sigma t = | Tup ts -> Tup (List.map (subst sigma) ts) | Func (s, c, tbs, ts1, ts2) -> let sigma' = ConEnv.map (shift 0 (List.length tbs)) sigma in - Func (s, map_control (subst sigma') c, List.map (subst_bind sigma') tbs, + Func (s, c, List.map (subst_bind sigma') tbs, List.map (subst sigma') ts1, List.map (subst sigma') ts2) | Opt t -> Opt (subst sigma t) | Async (t1, t2) -> Async (subst sigma t1, subst sigma t2) @@ -280,7 +273,7 @@ let rec open' i ts t = | Tup ts' -> Tup (List.map (open' i ts) ts') | Func (s, c, tbs, ts1, ts2) -> let i' = i + List.length tbs in - Func (s, map_control (open' i' ts) c, List.map (open_bind i' ts) tbs, List.map (open' i' ts) ts1, List.map (open' i' ts) ts2) + Func (s, c, List.map (open_bind i' ts) tbs, List.map (open' i' ts) ts1, List.map (open' i' ts) ts2) | Opt t -> Opt (open' i ts t) | Async (t1, t2) -> Async (open' i ts t1, open' i ts t2) | Obj (s, fs) -> Obj (s, List.map (open_field i ts) fs) @@ -423,7 +416,8 @@ let as_pair_sub t = match promote t with | Non -> Non, Non | _ -> invalid "as_pair_sub" let as_func_sub default_s default_arity t = match promote t with - | Func (s, c, tbs, ts1, ts2) -> s, tbs, seq ts1, codom c ts2 + | Func (s, c, tbs, ts1, ts2) -> + s, tbs, seq ts1, codom c (fun () -> Var((List.hd tbs).var, 0)) ts2 | Non -> default_s, Lib.List.make default_arity {var = "X"; sort = Type; bound = Any}, Any, Non | _ -> invalid "as_func_sub" let as_mono_func_sub t = match promote t with @@ -728,10 +722,9 @@ let rec rel_typ rel eq t1 t2 = | Tup ts1, Tup ts2 -> rel_list rel_typ rel eq ts1 ts2 | Func (s1, c1, tbs1, t11, t12), Func (s2, c2, tbs2, t21, t22) -> - s1 = s2 && + s1 = s2 && c1 = c2 && (match rel_binds rel eq tbs1 tbs2 with | Some ts -> - eq_control' rel eq (map_control (open_ ts) c1) (map_control (open_ ts) c2) && rel_list rel_typ rel eq (List.map (open_ ts) t21) (List.map (open_ ts) t11) && rel_list rel_typ rel eq (List.map (open_ ts) t12) (List.map (open_ ts) t22) | None -> false @@ -746,13 +739,6 @@ let rec rel_typ rel eq t1 t2 = | _, _ -> false end -and eq_control' rel eq c1 c2 = - match c1, c2 with - | Promises t1, Promises t2 -> eq_typ rel eq t1 t2 - | Returns, Returns -> true - | Replies, Replies -> true - | _ -> false - and rel_fields rel eq tfs1 tfs2 = (* Assume that tfs1 and tfs2 are sorted. *) match tfs1, tfs2 with @@ -831,9 +817,6 @@ and eq_con eq c1 c2 = let eq_kind k1 k2 : bool = eq_kind' (ref SS.empty) k1 k2 -let eq_control c1 c2 : bool = - let eq = ref SS.empty in eq_control' eq eq c1 c2 - (* Compatibility *) let compatible_list p co xs1 xs2 = @@ -965,7 +948,7 @@ let rec lub' lubs glbs t1 t2 = | Obj (s1, tf1), Obj (s2, tf2) when s1 = s2 -> Obj (s1, lub_fields lubs glbs tf1 tf2) | Func (s1, c1, bs1, args1, res1), Func (s2, c2, bs2, args2, res2) when - s1 = s2 && eq_control c1 c2 && List.(length bs1 = length bs2) && + s1 = s2 && c1 = c2 && List.(length bs1 = length bs2) && List.for_all2 (fun b1 b2 -> b1.sort = b2.sort) bs1 bs2 && List.(length args1 = length args2 && length res1 = length res2) -> combine_func_parts s1 c1 bs1 args1 res1 bs2 args2 res2 lubs glbs glb' lub' @@ -1039,7 +1022,7 @@ and glb' lubs glbs t1 t2 = | Some fs -> Obj (s1, fs) ) | Func (s1, c1, bs1, args1, res1), Func (s2, c2, bs2, args2, res2) when - s1 = s2 && eq_control c1 c2 && List.(length bs1 = length bs2) && + s1 = s2 && c1 = c2 && List.(length bs1 = length bs2) && List.for_all2 (fun b1 b2 -> b1.sort = b2.sort) bs1 bs2 && List.(length args1 = length args2 && length res1 = length res2) -> combine_func_parts s1 c1 bs1 args1 res1 bs2 args2 res2 lubs glbs lub' glb' @@ -1178,7 +1161,7 @@ let rec string_of_typ_nullary vs = function | Any -> "Any" | Non -> "None" | Prim p -> string_of_prim p - | Var (s, i) -> (try string_of_var (List.nth vs i) with _ -> assert false) + | Var (s, i) -> (try string_of_var (List.nth vs i) with _ -> sprintf "??? %s %i" s i) | Con (c, []) -> string_of_con' vs c | Con (c, ts) -> sprintf "%s<%s>" (string_of_con' vs c) @@ -1214,21 +1197,18 @@ and string_of_cod vs ts = | _ -> cod and string_of_control_cod sugar c vs ts = - match c,ts with + match c, ts with (* sugar *) | Returns, [Async (_,t)] when sugar -> sprintf "async %s" (string_of_typ' vs t) - | Promises _, ts when sugar -> + | Promises, ts when sugar -> sprintf "async %s" (string_of_cod vs ts) (* explicit *) - | Returns, _ -> string_of_cod vs ts - | Promises t, _ -> - sprintf "async<%s> %s" (string_of_typ' vs t) - (string_of_cod vs ts) + | (Returns | Promises), _ -> string_of_cod vs ts | Replies, _ -> sprintf "replies %s" (string_of_cod vs ts) and can_sugar t = match t with - | Func(s, Promises (Var(_, 0)), tbs, ts1, ts2) + | Func(s, Promises, tbs, ts1, ts2) | Func((Shared _ as s), Returns, tbs, ts1, ([] as ts2)) | Func(s, Returns, tbs, ts1, ([Async (Var(_, 0),_)] as ts2)) -> List.for_all (fun tb -> can_omit 0 tb.bound) tbs && @@ -1261,13 +1241,6 @@ and can_omit n t = and string_of_typ' vs t = match t with | Func (s, c, tbs, ts1, ts2) when can_sugar t -> - let n = match c, ts2 with - | Promises (Var (s,n)), _ -> n - | Returns, [] -> 0 - | Returns, [Async (Var (s,n),_)] -> n - | _ -> assert false - in - assert (n = 0); let vs' = vars_of_binds vs tbs in let vs'', tbs' = List.tl vs', List.tl tbs in begin diff --git a/src/mo_types/type.mli b/src/mo_types/type.mli index 5881f85f65c..58782d7a627 100644 --- a/src/mo_types/type.mli +++ b/src/mo_types/type.mli @@ -3,7 +3,7 @@ type lab = string type var = string -type 'a control = Returns | Promises of 'a | Replies +type control = Returns | Promises | Replies type obj_sort = Object | Actor | Module type shared_sort = Query | Write type 'a shared = Local | Shared of 'a @@ -43,7 +43,7 @@ and typ = | Array of typ (* array *) | Opt of typ (* option *) | Tup of typ list (* tuple *) - | Func of func_sort * typ control * bind list * typ list * typ list (* function *) + | Func of func_sort * control * bind list * typ list * typ list (* function *) | Async of typ * typ (* future *) | Mut of typ (* mutable type *) | Any (* top *) @@ -65,8 +65,7 @@ and kind = (* Function sorts *) val is_shared_sort : 'a shared -> bool -val is_promising : 'a control -> bool -val map_control : ('a -> 'b) -> 'a control -> 'b control +val is_promising : control -> bool (* Short-hands *) @@ -116,7 +115,7 @@ val as_opt : typ -> typ val as_tup : typ -> typ list val as_unit : typ -> unit val as_pair : typ -> typ * typ -val as_func : typ -> func_sort * typ control * bind list * typ list * typ list +val as_func : typ -> func_sort * control * bind list * typ list * typ list val as_async : typ -> typ * typ val as_mut : typ -> typ val as_immut : typ -> typ @@ -138,7 +137,7 @@ val as_async_sub : typ -> typ -> typ * typ (* Argument/result sequences *) val seq : typ list -> typ -val codom : typ control -> typ list -> typ +val codom : control -> (unit -> typ) -> typ list -> typ val as_seq : typ -> typ list (* This needs to go away *) val seq_of_tup : typ -> typ list val arity : typ -> int diff --git a/src/mo_values/call_conv.ml b/src/mo_values/call_conv.ml index bd289db48ce..1e19c005878 100644 --- a/src/mo_values/call_conv.ml +++ b/src/mo_values/call_conv.ml @@ -10,7 +10,7 @@ with their “calling convention”, and check them in calls. type call_conv = { sort: func_sort; - control : unit control; + control : control; n_args : int; n_res : int; } @@ -18,14 +18,14 @@ type t = call_conv let local_cc n m = { sort = Local; control = Returns; n_args = n; n_res = m} let message_cc s n = { sort = Shared s; control = Returns; n_args = n; n_res = 0} -let async_cc s n m = { sort = Shared s; control = Promises (); n_args = n; n_res = m} +let async_cc s n m = { sort = Shared s; control = Promises; n_args = n; n_res = m} let replies_cc s n m = { sort = Shared s; control = Replies; n_args = n; n_res = m} let call_conv_of_typ typ = match typ with | Func (sort, control, tbds, dom, res) -> let control = match control with - | Promises t -> Promises () + | Promises -> Promises | Returns -> Returns | Replies -> Replies in @@ -38,6 +38,6 @@ let string_of_call_conv {sort;control;n_args;n_res} = Printf.sprintf "(%s%i %s %i)" (string_of_func_sort sort) n_args - (match control with Returns -> "->" | Promises _ -> "@>" | Replies -> "#>") + (match control with Returns -> "->" | Promises -> "@>" | Replies -> "#>") n_res diff --git a/src/mo_values/call_conv.mli b/src/mo_values/call_conv.mli index 0bfeb2e61a9..24fd4b318a1 100644 --- a/src/mo_values/call_conv.mli +++ b/src/mo_values/call_conv.mli @@ -3,7 +3,7 @@ open Mo_types type call_conv = { sort: Type.func_sort; - control : unit Type.control; + control : Type.control; n_args : int; n_res : int; } diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index fb2c533ba6d..1603c04e413 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -256,7 +256,7 @@ let chase_imports parsefn senv0 imports : (Syntax.lib list * Scope.scope) Diag.r let open Type in Obj (Actor, [{lab = "go"; - typ = Func (Shared Write, Promises (Var ("@", 0)), [{var = "@"; sort = Scope; bound = Any}], + typ = Func (Shared Write, Promises, [{var = "@"; sort = Scope; bound = Any}], [], [Obj (Actor, [])])}]) in let sscope = Scope.lib f scaffold_type in diff --git a/test/fail/ok/abstract-msgs.tc.ok b/test/fail/ok/abstract-msgs.tc.ok index 31c88c8727a..137706eb90a 100644 --- a/test/fail/ok/abstract-msgs.tc.ok +++ b/test/fail/ok/abstract-msgs.tc.ok @@ -2,18 +2,18 @@ abstract-msgs.mo:2.28-2.37: type error, shared function has non-shared parameter A/9 abstract-msgs.mo:3.33-3.35: type error, shared function must have syntactic return type `()` or `async ` abstract-msgs.mo:5.20-5.29: type error, shared function has non-shared parameter type - A/10 + A/11 abstract-msgs.mo:6.25-6.33: type error, shared function has non-shared return type - ?A/10 + ?A/11 abstract-msgs.mo:10.34-10.35: type error, shared function has non-shared parameter type - A/11 -abstract-msgs.mo:11.27-11.47: type error, shared function has non-shared return type A/12 -abstract-msgs.mo:14.30-14.31: type error, shared function has non-shared parameter type +abstract-msgs.mo:11.27-11.47: type error, shared function has non-shared return type A/13 -abstract-msgs.mo:15.13-15.43: type error, shared function has non-shared return type +abstract-msgs.mo:14.30-14.31: type error, shared function has non-shared parameter type A/14 -abstract-msgs.mo:16.31-16.32: type error, shared function has non-shared parameter type +abstract-msgs.mo:15.13-15.43: type error, shared function has non-shared return type A/15 -abstract-msgs.mo:17.24-17.44: type error, shared function has non-shared return type +abstract-msgs.mo:16.31-16.32: type error, shared function has non-shared parameter type A/16 +abstract-msgs.mo:17.24-17.44: type error, shared function has non-shared return type + A/17 From 0fda04909f43f320709aec96b957706247688e53 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Fri, 17 Jan 2020 15:59:56 +0000 Subject: [PATCH 0958/1176] remove option from AsyncT scope --- src/mo_def/arrange.ml | 6 +----- src/mo_def/syntax.ml | 17 ++++++++++------ src/mo_frontend/parser.mly | 24 ++++------------------- src/mo_frontend/typing.ml | 17 +++++----------- test/run-drun/ok/scope-example-func.tc.ok | 2 +- test/run-drun/ok/type-lub.comp.ok | 2 +- test/run-drun/scope-example-func.mo | 2 +- test/run-drun/type-lub.mo | 4 +--- 8 files changed, 25 insertions(+), 49 deletions(-) diff --git a/src/mo_def/arrange.ml b/src/mo_def/arrange.ml index 01759763067..2c6b0cc7061 100644 --- a/src/mo_def/arrange.ml +++ b/src/mo_def/arrange.ml @@ -156,13 +156,9 @@ and typ t = match t.it with | VariantT cts -> "VariantT" $$ List.map typ_tag cts | TupT ts -> "TupT" $$ List.map typ ts | FuncT (s, tbs, at, rt) -> "FuncT" $$ [func_sort s] @ List.map typ_bind tbs @ [ typ at; typ rt] - | AsyncT (t1_opt, t2) -> "AsyncT" $$ [typ_opt t1_opt; typ t2] + | AsyncT (t1, t2) -> "AsyncT" $$ [typ t1; typ t2] | ParT t -> "ParT" $$ [typ t] -and typ_opt t_opt = match t_opt with - Some t -> typ t - | None -> Atom "?" - and dec d = match d.it with | ExpD e -> "ExpD" $$ [exp e ] | LetD (p, e) -> "LetD" $$ [pat p; exp e] diff --git a/src/mo_def/syntax.ml b/src/mo_def/syntax.ml index e78810aea23..b685ba597dc 100644 --- a/src/mo_def/syntax.ml +++ b/src/mo_def/syntax.ml @@ -46,9 +46,9 @@ and typ' = | VariantT of typ_tag list (* variant *) | TupT of typ list (* tuple *) | FuncT of func_sort * typ_bind list * typ * typ (* function *) - | AsyncT of typ option * typ (* future *) + | AsyncT of scope * typ (* future *) | ParT of typ (* parentheses, used to control function arity only *) - +and scope = typ and typ_field = typ_field' Source.phrase and typ_field' = {id : id; typ : typ; mut : mut} @@ -261,14 +261,19 @@ let scope_bind() = bound = PrimT "Any" @! no_region } @= no_region -let add_scope_bind tbs = scope_bind()::tbs +let ensure_scope_bind tbs = + match tbs with + | tb::_ when tb.it.sort.it = Type.Scope -> + tbs + | _ -> + scope_bind()::tbs let funcT(sort, tbs, t1, t2) = match sort.it, t2.it with | Type.Local, AsyncT _ -> - FuncT(sort, add_scope_bind tbs, t1, t2) + FuncT(sort, ensure_scope_bind tbs, t1, t2) | Type.Shared _, _ -> - FuncT(sort, add_scope_bind tbs, t1, t2) + FuncT(sort, ensure_scope_bind tbs, t1, t2) | _ -> FuncT(sort, tbs, t1, t2) @@ -276,7 +281,7 @@ let funcE(f, s, tbs, p, t_opt, e) = match s.it, t_opt, e with | Type.Local, Some { it = AsyncT _; _}, {it = AsyncE _; _} | Type.Shared _, _, _ -> - FuncE(f, s, add_scope_bind tbs, p, t_opt, e) + FuncE(f, s, ensure_scope_bind tbs, p, t_opt, e) | _ -> FuncE(f, s, tbs, p, t_opt, e) diff --git a/src/mo_frontend/parser.mly b/src/mo_frontend/parser.mly index e5820c3978c..5857436381f 100644 --- a/src/mo_frontend/parser.mly +++ b/src/mo_frontend/parser.mly @@ -245,8 +245,8 @@ typ_pre : { t } | PRIM s=TEXT { PrimT(s) @! at $sloc } - | ASYNC t1 = scope_inst_opt t2=typ_pre - { AsyncT(t1, t2) @! at $sloc } + | ASYNC t=typ_pre + { AsyncT(scope_typ no_region, t) @! at $sloc } | s=obj_sort tfs=typ_obj { let tfs' = if s.it = Type.Actor then List.map share_typfield tfs else tfs @@ -287,22 +287,6 @@ typ_bind : | x=id { {var = x; sort = Type.Type @@ no_region; bound = PrimT "Any" @! at $sloc} @= at $sloc } -%inline scope_bind_opt : - | LT tb=typ_bind GT - { tb } - | (* empty *) - { scope_bind() } - -%inline scope_inst : - | LT t=typ GT - { t } - -%inline scope_inst_opt : - | t=scope_inst - { Some t } - | (* empty *) - { None } - (* Expressions *) lit : @@ -459,8 +443,8 @@ exp_nondec(B) : { RetE(TupE([]) @? at $sloc) @? at $sloc } | RETURN e=exp(ob) { RetE(e) @? at $sloc } - | ASYNC tb=scope_bind_opt e=exp(bl) - { AsyncE(tb, e) @? at $sloc } + | ASYNC e=exp(bl) + { AsyncE(scope_bind(), e) @? at $sloc } | AWAIT e=exp(bl) { AwaitE(e) @? at $sloc } | ASSERT e=exp(bl) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 2286573daa1..1f3a76022d6 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -255,10 +255,8 @@ let as_domT t = let as_codomT sort t = match sort, t.Source.it with - | T.Shared _, AsyncT (Some t1, t2) -> - T.Promises, as_domT t2 - | T.Shared _, AsyncT (None, t2) -> - T.Promises, as_domT t2 + | T.Shared _, AsyncT (_, t1) -> + T.Promises, as_domT t1 | _ -> T.Returns, as_domT t let check_shared_return env at sort c ts = @@ -352,10 +350,7 @@ and check_typ' env typ : T.typ = (List.map (fun (tag : typ_tag) -> tag.it.tag) tags); let fs = List.map (check_typ_tag env) tags in T.Variant (List.sort T.compare_field fs) - | AsyncT (typ0_opt, typ) -> - let typ0 = match typ0_opt with - | None -> scope_typ no_region - | Some typ0 -> typ0 in + | AsyncT (typ0, typ) -> let t0 = check_typ env typ0 in let t = check_typ env typ in if not env.pre && not (T.shared t) then @@ -785,8 +780,7 @@ and infer_exp'' env exp : T.typ = | FuncE (_, sort_pat, typ_binds, pat, typ_opt, exp) -> if not env.pre && not in_actor && T.is_shared_sort sort_pat.it then error_in [Flags.ICMode; Flags.StubMode] env exp.at "a shared function is only allowed as a public field of an actor"; - let typ = - match typ_opt with + let typ = match typ_opt with | Some typ -> typ | None -> {it = TupT []; at = no_region; note = T.Pre} in @@ -1134,8 +1128,7 @@ and check_exp' env0 t exp : T.typ = let ve1 = check_pat_exhaustive env (T.seq ts1) pat in let ve2 = T.Env.adjoin ve ve1 in let codom = T.codom c (fun () -> assert false) ts2 in - let t2 = - match typ_opt with + let t2 = match typ_opt with | None -> codom | Some typ -> check_typ env typ in diff --git a/test/run-drun/ok/scope-example-func.tc.ok b/test/run-drun/ok/scope-example-func.tc.ok index 1716f7b59a8..31dd2dd547e 100644 --- a/test/run-drun/ok/scope-example-func.tc.ok +++ b/test/run-drun/ok/scope-example-func.tc.ok @@ -1 +1 @@ -scope-example-func.mo:10.13-10.34: type error, misplaced async expression +scope-example-func.mo:10.13-10.38: type error, misplaced async expression diff --git a/test/run-drun/ok/type-lub.comp.ok b/test/run-drun/ok/type-lub.comp.ok index 38646553187..80ccbcab09c 100644 --- a/test/run-drun/ok/type-lub.comp.ok +++ b/test/run-drun/ok/type-lub.comp.ok @@ -1,2 +1,2 @@ -type-lub.mo:59.16-59.24: type error, unsupported async block +type-lub.mo:57.16-57.24: type error, unsupported async block (This is a limitation of the current version.) diff --git a/test/run-drun/scope-example-func.mo b/test/run-drun/scope-example-func.mo index f514c1c3f37..59dce5984ad 100644 --- a/test/run-drun/scope-example-func.mo +++ b/test/run-drun/scope-example-func.mo @@ -7,7 +7,7 @@ actor A { var a : (async/**/ Int) = async 0; func set () { - a := async {return 666} /**/; + a := async/**/ {return 666} /**/; }; await (async/**/ { diff --git a/test/run-drun/type-lub.mo b/test/run-drun/type-lub.mo index 532aaff6d9d..52eb642715b 100644 --- a/test/run-drun/type-lub.mo +++ b/test/run-drun/type-lub.mo @@ -52,10 +52,8 @@ actor a { , func (a : Nat) : Nat = 42 ]; - type C<@> = async<@> (?Int); - type D<@> = async<@> (?Nat); - func c0(c : C<@>, d : D<@>) : [C<@>] { ignore([c, d]); [c, d] }; + func c0(c : async (?Int), d : async (?Nat)) : [async (?Int)] { ignore([c, d]); [c, d] }; let c1s = [async ?4, async ?-42]; From fb769848bce418db0d1ddeb81f548d162e29f220 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Fri, 17 Jan 2020 16:04:52 +0000 Subject: [PATCH 0959/1176] remove @ from id --- src/mo_def/syntax.ml | 1 + src/mo_frontend/lexer.mll | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mo_def/syntax.ml b/src/mo_def/syntax.ml index b685ba597dc..9b61bce9ebe 100644 --- a/src/mo_def/syntax.ml +++ b/src/mo_def/syntax.ml @@ -48,6 +48,7 @@ and typ' = | FuncT of func_sort * typ_bind list * typ * typ (* function *) | AsyncT of scope * typ (* future *) | ParT of typ (* parentheses, used to control function arity only *) + and scope = typ and typ_field = typ_field' Source.phrase and typ_field' = {id : id; typ : typ; mut : mut} diff --git a/src/mo_frontend/lexer.mll b/src/mo_frontend/lexer.mll index 10c97ccc110..7b6986f26bc 100644 --- a/src/mo_frontend/lexer.mll +++ b/src/mo_frontend/lexer.mll @@ -107,7 +107,7 @@ let float = | "0x" hexnum ('.' hexfrac?)? ('p' | 'P') sign? num let char = '\'' character '\'' let text = '"' character* '"' -let id = '@' | ((letter | '_') ((letter | digit | '_')*)) +let id = ((letter | '_') ((letter | digit | '_')*)) let privileged_id = "@" id let reserved = ([^'\"''('')'';'] # space)+ (* hack for table size *) From aac015e9280aa0f338ff61db7d54e948d0429817 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 17 Jan 2020 17:23:16 +0100 Subject: [PATCH 0960/1176] Create table entries only on demand (#1124) * Create table entries only on demand Previously, the backend would simply put every functoin _n_ in the table at position _n_, and just conflate Wasm function identifiers and table entries. About time to remove the hack, and only add functions to the table when we actually need a table pointer. This will allow us to use off-the-shelve tools like `wasm-opt` to do dead-code elimination! * Fix the bug that I could not find yesterday * When calling ic.call_simple, pass function pointers, not function ids * Update src/codegen/compile.ml * Puns! Co-Authored-By: Gabor Greif Co-authored-by: Gabor Greif --- src/codegen/compile.ml | 54 +++++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 17 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 9474202196a..c50bbbd32a2 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -141,6 +141,7 @@ module E = struct (* The environment type *) module NameEnv = Env.Make(String) module StringEnv = Env.Make(String) + module FunEnv = Env.Make(Int32) type local_names = (int32 * string) list (* For the debug section: Names of locals *) type func_with_names = func * local_names type lazy_built_in = @@ -164,6 +165,8 @@ module E = struct other_imports : import list ref; exports : export list ref; funcs : (func * string * local_names) Lib.Promise.t list ref; + func_ptrs : int32 FunEnv.t ref; + end_of_table : int32 ref; globals : (global * string) list ref; global_names : int32 NameEnv.t ref; built_in_funcs : lazy_built_in NameEnv.t ref; @@ -197,6 +200,8 @@ module E = struct other_imports = ref []; exports = ref []; funcs = ref []; + func_ptrs = ref FunEnv.empty; + end_of_table = ref 0l; globals = ref []; global_names = ref NameEnv.empty; built_in_funcs = ref NameEnv.empty; @@ -372,6 +377,21 @@ module E = struct env.static_memory := !(env.static_memory) @ [ (ptr, data) ]; Int32.(add ptr ptr_skew) (* Return a skewed pointer *) + let add_fun_ptr (env : t) fi : int32 = + match FunEnv.find_opt fi !(env.func_ptrs) with + | Some fp -> fp + | None -> + let fp = !(env.end_of_table) in + env.func_ptrs := FunEnv.add fi fp !(env.func_ptrs); + env.end_of_table := Int32.add !(env.end_of_table) 1l; + fp + + let get_elems env = + FunEnv.bindings !(env.func_ptrs) + + let get_end_of_table env : int32 = + !(env.end_of_table) + let add_static_bytes (env : t) data : int32 = match StringEnv.find_opt data !(env.static_strings) with | Some ptr -> ptr @@ -4356,7 +4376,7 @@ module StackRep = struct (* When accessing a variable that is a constant function, then we need to create a heap-allocated closure-like thing on the fly. *) Tagged.obj env Tagged.Closure [ - compile_unboxed_const fi; + compile_unboxed_const (E.add_fun_ptr env fi); compile_unboxed_zero (* number of parameters: none *) ] | Const.Message fi -> @@ -4691,9 +4711,9 @@ module FuncDec = struct get_clos ^^ Tagged.store Tagged.Closure ^^ - (* Store the function number: *) + (* Store the function pointer number: *) get_clos ^^ - compile_unboxed_const fi ^^ + compile_unboxed_const (E.add_fun_ptr env fi) ^^ Heap.store_field Closure.funptr_field ^^ (* Store the length *) @@ -4793,15 +4813,15 @@ module FuncDec = struct set_cb_index ^^ (* return arguments for the ic.call *) - compile_unboxed_const (E.built_in env reply_name) ^^ + compile_unboxed_const (E.add_fun_ptr env (E.built_in env reply_name)) ^^ get_cb_index ^^ - compile_unboxed_const (E.built_in env reject_name) ^^ + compile_unboxed_const (E.add_fun_ptr env (E.built_in env reject_name)) ^^ get_cb_index let ignoring_callback env = let name = "@ignore_callback" in Func.define_built_in env name ["env", I32Type] [] (fun env -> G.nop); - compile_unboxed_const (E.built_in env name) + compile_unboxed_const (E.add_fun_ptr env (E.built_in env name)) let ic_call env ts1 ts2 get_meth_pair get_arg get_k get_r = match E.mode env with @@ -6862,14 +6882,9 @@ and conclude_module env start_fi_o = let other_imports = E.get_other_imports env in - let funcs = E.get_funcs env in - let nf = List.length funcs in - let nf' = Wasm.I32.of_int_u nf in - - let table_sz = Int32.add nf' ni' in - let memories = [nr {mtype = MemoryType {min = E.mem_size env; max = None}} ] in + let funcs = E.get_funcs env in let data = List.map (fun (offset, init) -> nr { index = nr 0l; @@ -6877,17 +6892,22 @@ and conclude_module env start_fi_o = init; }) (E.get_static_memory env) in + let elems = List.map (fun (fi, fp) -> nr { + index = nr 0l; + offset = nr (G.to_instr_list (compile_unboxed_const fp)); + init = [ nr fi ]; + }) (E.get_elems env) in + + let table_sz = E.get_end_of_table env in + let module_ = { types = List.map nr (E.get_types env); funcs = List.map (fun (f,_,_) -> f) funcs; tables = [ nr { ttype = TableType ({min = table_sz; max = Some table_sz}, FuncRefType) } ]; - elems = [ nr { - index = nr 0l; - offset = nr (G.to_instr_list (compile_unboxed_const ni')); - init = List.mapi (fun i _ -> nr (Wasm.I32.of_int_u (ni + i))) funcs } ]; + elems; start = Some (nr rts_start_fi); globals = E.get_globals env; - memories = memories; + memories; imports = func_imports @ other_imports; exports = E.get_exports env; data From 25521e646dbd4a0bc63efcde0ab2783c331397b8 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Fri, 17 Jan 2020 16:39:07 +0000 Subject: [PATCH 0961/1176] refactor --- src/mo_frontend/typing.ml | 5 ++--- src/mo_values/call_conv.ml | 5 ----- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 1f3a76022d6..388d5c75085 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -786,14 +786,13 @@ and infer_exp'' env exp : T.typ = in let sort, ve = check_sort_pat env sort_pat in let cs, tbs, te, ce = check_typ_binds env typ_binds in - let ts = List.map (fun c -> T.Con(c,[])) cs in let c, ts2 = as_codomT sort typ in check_shared_return env typ.at sort c ts2; let env' = infer_async_cap (adjoin_typs env te ce) sort cs tbs in let t1, ve1 = infer_pat_exhaustive env' pat in let ve2 = T.Env.adjoin ve ve1 in let ts2 = List.map (check_typ env') ts2 in - let codom = T.codom c (fun () -> List.hd ts) ts2 in + let codom = T.codom c (fun () -> T.Con(List.hd cs,[])) ts2 in if not env.pre then begin let env'' = { env' with @@ -1120,7 +1119,7 @@ and check_exp' env0 t exp : T.typ = (String.concat " or\n " ss) ); t - (* TODO: allow mono shared with one scope par *) + (* TODO: allow shared with one scope par *) | FuncE (_, sort_pat, [], pat, typ_opt, exp), T.Func (s, c, [], ts1, ts2) -> let sort, ve = check_sort_pat env sort_pat in if not env.pre && not env0.in_actor && T.is_shared_sort sort then diff --git a/src/mo_values/call_conv.ml b/src/mo_values/call_conv.ml index 1e19c005878..9e334c1d5c6 100644 --- a/src/mo_values/call_conv.ml +++ b/src/mo_values/call_conv.ml @@ -24,11 +24,6 @@ let replies_cc s n m = { sort = Shared s; control = Replies; n_args = n; n_res = let call_conv_of_typ typ = match typ with | Func (sort, control, tbds, dom, res) -> - let control = match control with - | Promises -> Promises - | Returns -> Returns - | Replies -> Replies - in { sort; control; n_args = List.length dom; n_res = List.length res } | Non -> { sort = Local; control = Returns; n_args = 1; n_res = 1 } From 5eee84afd1d5b247a4a7adf1abbb0284f1feb491 Mon Sep 17 00:00:00 2001 From: Bas van Dijk Date: Fri, 17 Jan 2020 17:47:04 +0100 Subject: [PATCH 0962/1176] nix: start using niv to manage external sources (#1118) * nix: start using niv to manage external sources This commit also adds support for restricted Nix evaluation which will be required on Hydra soon (for security reasons). Note that dfinity had to be upgraded to get restrict-eval support. * nix/sources.json: add libtommath * default.nix: specfify sources in an overlay so we can access it everywhere * nix/sources.json: add winter * nix/sources.json: add ocaml-vlq * nix/sources.json: add WebAssembly-spec * accept drun output (formatting change) * accept drun output (more formatting changes) * accept drun output (even more formatting changes) * Fetch remote sources.nix * Import packages in nix/default.nix * nix/ocaml-wasm.nix: use removePrefix instead of substring * Instantiate sources.nix only once * Inline definition of esm * Don't nivify files copied from nixpkgs Co-authored-by: Gabor Greif Co-authored-by: Nicolas Mattia --- ci-pr.nix | 2 +- ci.nix | 2 +- default.nix | 52 +++------------ ic-stub/shell.nix | 2 +- nix/default.nix | 31 +++++++++ nix/gitSource.nix | 2 +- nix/haskell-packages.nix | 8 +-- nix/llvm.nix | 4 +- nix/nixpkgs-llvm.nix | 6 -- nix/nixpkgs.nix | 10 --- nix/ocaml-vlq.nix | 1 - nix/sources.json | 66 +++++++++++++++++++ test/compare-wat.sh | 2 +- .../ok/array-out-of-bounds.drun-run.ok | 4 +- .../run-drun/ok/call-async-method.drun-run.ok | 2 +- test/run-drun/ok/divide-by-zero.drun-run.ok | 2 +- test/run-drun/ok/idl-bad.drun-run.ok | 2 +- test/run-drun/ok/idl-nary.drun-run.ok | 4 +- test/run-drun/ok/selftail.drun-run.ok | 2 +- 19 files changed, 121 insertions(+), 83 deletions(-) create mode 100644 nix/default.nix delete mode 100644 nix/nixpkgs-llvm.nix delete mode 100644 nix/nixpkgs.nix create mode 100644 nix/sources.json diff --git a/ci-pr.nix b/ci-pr.nix index 205b6b13c97..bb1617ca3c3 100644 --- a/ci-pr.nix +++ b/ci-pr.nix @@ -1,6 +1,6 @@ { src ? { rev = null; }, base ? null }: let - nixpkgs = (import ./nix/nixpkgs.nix).nixpkgs { }; + nixpkgs = import ./nix { }; # Wrap in a derivation to fix path to perl in shebang diff-stats = nixpkgs.stdenvNoCC.mkDerivation { diff --git a/ci.nix b/ci.nix index 62d5c13bbff..6035235af07 100644 --- a/ci.nix +++ b/ci.nix @@ -1,6 +1,6 @@ { src ? { rev = null; } }: let - nixpkgs = (import ./nix/nixpkgs.nix).nixpkgs { }; + nixpkgs = import ./nix { }; inject-rev = drv: drv.overrideAttrs (attrs: { rev = src.rev; }); linux = import ./default.nix { system = "x86_64-linux"; }; diff --git a/default.nix b/default.nix index ab184b3ed4a..90f11ee9693 100644 --- a/default.nix +++ b/default.nix @@ -3,28 +3,9 @@ system ? builtins.currentSystem, }: -let nixpkgs = (import ./nix/nixpkgs.nix).nixpkgs { - inherit system; - overlays = [ - # Selecting the ocaml version - (self: super: { ocamlPackages = self.ocaml-ng.ocamlPackages_4_08; }) - # Additional ocaml package - (self: super: { - ocamlPackages = super.ocamlPackages // { - wasm = import ./nix/ocaml-wasm.nix { - inherit (self) stdenv fetchFromGitHub ocaml; - inherit (self.ocamlPackages) findlib ocamlbuild; - }; - vlq = import ./nix/ocaml-vlq.nix { - inherit (self) stdenv fetchFromGitHub ocaml dune; - inherit (self.ocamlPackages) findlib; - }; - }; - }) - ]; -}; in +let nixpkgs = import ./nix { inherit system; }; in -let llvm = import ./nix/llvm.nix { inherit (nixpkgs) system; }; in +let llvm = import ./nix/llvm.nix { inherit (nixpkgs) system sources; }; in let stdenv = nixpkgs.stdenv; in @@ -32,33 +13,16 @@ let subpath = p: import ./nix/gitSource.nix p; in let dfinity-src = let env = builtins.getEnv "DFINITY_SRC"; in - if env != "" then env else builtins.fetchGit { - name = "dfinity-sources"; - url = "ssh://git@github.com/dfinity-lab/dfinity"; - # ref = "master"; - rev = "947195fb1395eac397b8490fc8000e3afe5ef820"; - }; in + if env != "" then env else nixpkgs.sources.dfinity; in let dfinity-pkgs = import dfinity-src { inherit (nixpkgs) system; }; in -let esm = nixpkgs.fetchzip { - sha256 = "116k10q9v0yzpng9bgdx3xrjm2kppma2db62mnbilbi66dvrvz9q"; - url = "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz"; -}; in - let drun = dfinity-pkgs.drun or dfinity-pkgs.dfinity.drun; in let haskellPackages = nixpkgs.haskellPackages.override { overrides = import nix/haskell-packages.nix nixpkgs subpath; }; in let - libtommath = nixpkgs.fetchFromGitHub { - owner = "libtom"; - repo = "libtommath"; - rev = "584405ff8e357290362671b5e7db6110a959cbaa"; - sha256 = "1vl606rm8ba7vjhr0rbdqvih5d4r5iqalqlj5mnz6j3bnsn83b2a"; - }; - llvmBuildInputs = [ nixpkgs.clang # for native building llvm.clang_9 # for wasm building @@ -156,7 +120,7 @@ rec { preBuild = '' ${llvmEnv} - export TOMMATHSRC=${libtommath} + export TOMMATHSRC=${nixpkgs.sources.libtommath} ''; doCheck = true; @@ -229,7 +193,7 @@ rec { nixpkgs.nodejs-10_x filecheck wasmtime - esm + nixpkgs.sources.esm ] ++ llvmBuildInputs; @@ -240,7 +204,7 @@ rec { export MO_LD=mo-ld export DIDC=didc export DESER=deser - export ESM=${esm} + export ESM=${nixpkgs.sources.esm} type -p moc && moc --version # run this once to work around self-unpacking-race-condition type -p drun && drun --version @@ -482,8 +446,8 @@ rec { )); shellHook = llvmEnv; - ESM=esm; - TOMMATHSRC = libtommath; + ESM=nixpkgs.sources.esm; + TOMMATHSRC = nixpkgs.sources.libtommath; NIX_FONTCONFIG_FILE = users-guide.NIX_FONTCONFIG_FILE; LOCALE_ARCHIVE = stdenv.lib.optionalString stdenv.isLinux "${nixpkgs.glibcLocales}/lib/locale/locale-archive"; diff --git a/ic-stub/shell.nix b/ic-stub/shell.nix index c25d45ba5df..18baf159054 100644 --- a/ic-stub/shell.nix +++ b/ic-stub/shell.nix @@ -3,7 +3,7 @@ let ic-stub = (import ../default.nix {inherit system;}).ic-stub; - nixpkgs = (import ../nix/nixpkgs.nix).nixpkgs { inherit system; }; + nixpkgs = import ../nix { inherit system; }; extra-pkgs = [ nixpkgs.haskellPackages.cabal-install diff --git a/nix/default.nix b/nix/default.nix new file mode 100644 index 00000000000..41ee345fa4d --- /dev/null +++ b/nix/default.nix @@ -0,0 +1,31 @@ +{ system ? builtins.currentSystem }: +let + sourcesnix = builtins.fetchurl https://raw.githubusercontent.com/nmattia/niv/506b896788d9705899592a303de95d8819504c55/nix/sources.nix; + nixpkgs_src = (import sourcesnix { sourcesFile = ./sources.json; inherit pkgs; }).nixpkgs; + + pkgs = + import nixpkgs_src { + inherit system; + overlays = [ + (self: super: { sources = import sourcesnix { sourcesFile = ./sources.json; pkgs = super; }; }) + # Selecting the ocaml version + (self: super: { ocamlPackages = self.ocaml-ng.ocamlPackages_4_08; }) + # Additional ocaml package + ( + self: super: { + ocamlPackages = super.ocamlPackages // { + wasm = import ./ocaml-wasm.nix { + inherit (self) stdenv fetchFromGitHub ocaml; + inherit (self.ocamlPackages) findlib ocamlbuild; + }; + vlq = import ./ocaml-vlq.nix { + inherit (self) stdenv fetchFromGitHub ocaml dune; + inherit (self.ocamlPackages) findlib; + }; + }; + } + ) + ]; + }; +in +pkgs diff --git a/nix/gitSource.nix b/nix/gitSource.nix index 1983d838a06..a3c217b0e21 100644 --- a/nix/gitSource.nix +++ b/nix/gitSource.nix @@ -56,7 +56,7 @@ in # unfortunately this is not completely self-contained, # we needs pkgs this to get git and lib.cleanSourceWith -let nixpkgs = (import ./nixpkgs.nix).nixpkgs {}; in +let nixpkgs = import ./. {}; in if !isHydra && builtins.pathExists ../.git then diff --git a/nix/haskell-packages.nix b/nix/haskell-packages.nix index 63238da0834..68ea54866d2 100644 --- a/nix/haskell-packages.nix +++ b/nix/haskell-packages.nix @@ -11,13 +11,7 @@ nix: subpath: qc-motoko = self.callCabal2nix "qc-motoko" (subpath "test/random") { }; - winter = self.callCabal2nixWithOptions "winter" - (nix.fetchFromGitHub { - owner = "dfinity-side-projects"; - repo = "winter"; - rev = "1e16b471644be26160cc20c4e2144c643c547ed8"; - sha256 = "191fk1dv8vp28rwpl75nz9y3pbypc8jv9w669mvl9d2k5f74jirm"; - }) "--no-check" {}; + winter = self.callCabal2nixWithOptions "winter" nix.sources.winter "--no-check" {}; ic-stub = self.callCabal2nixWithOptions "ic-stub" (subpath "ic-stub") "-frelease" { }; } diff --git a/nix/llvm.nix b/nix/llvm.nix index f7fdaa92a56..bb18c6f0a76 100644 --- a/nix/llvm.nix +++ b/nix/llvm.nix @@ -1,6 +1,6 @@ -{ system } : +{ system, sources } : -let pkgs = (import ./nixpkgs-llvm.nix) { +let pkgs = (import sources.nixpkgs-llvm) { system = system; }; in diff --git a/nix/nixpkgs-llvm.nix b/nix/nixpkgs-llvm.nix deleted file mode 100644 index 3c74a0151b5..00000000000 --- a/nix/nixpkgs-llvm.nix +++ /dev/null @@ -1,6 +0,0 @@ -with { rev = "42710203b04738b8f19ae51f0fd21d22fddf3f39"; }; - -import (builtins.fetchTarball { - sha256 = "1fqfi0rrlhmssp2cfz07f9sg3mvck28mxnmd39w2ir8670xfixvq"; - url = "https://github.com/NixOS/nixpkgs/archive/${rev}.tar.gz"; -}) diff --git a/nix/nixpkgs.nix b/nix/nixpkgs.nix deleted file mode 100644 index 9b3e2158e19..00000000000 --- a/nix/nixpkgs.nix +++ /dev/null @@ -1,10 +0,0 @@ -rec { - rev = "82875a20ba444110396f95537b18247898e40e22"; - - src = builtins.fetchTarball { - sha256 = "1xy2zn3hkcv66ddvscr3l32jcx1qg9h14zvhmy5zf0pcfb8gn42i"; - url = "https://github.com/NixOS/nixpkgs/archive/${rev}.tar.gz"; - }; - - nixpkgs = import src; -} diff --git a/nix/ocaml-vlq.nix b/nix/ocaml-vlq.nix index 20e681bf98d..ce69ae4fef7 100644 --- a/nix/ocaml-vlq.nix +++ b/nix/ocaml-vlq.nix @@ -1,7 +1,6 @@ { stdenv, fetchFromGitHub, ocaml, findlib, dune }: let version = "v0.2.0"; in - stdenv.mkDerivation { name = "ocaml${ocaml.version}-vlq-${version}"; diff --git a/nix/sources.json b/nix/sources.json new file mode 100644 index 00000000000..20d633da5aa --- /dev/null +++ b/nix/sources.json @@ -0,0 +1,66 @@ +{ + "dfinity": { + "ref": "master", + "repo": "ssh://git@github.com/dfinity-lab/dfinity", + "rev": "791d90bb7ca57d7afab4fd045025877acb892c00", + "type": "git" + }, + "esm": { + "builtin": false, + "sha256": "116k10q9v0yzpng9bgdx3xrjm2kppma2db62mnbilbi66dvrvz9q", + "type": "tarball", + "url": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", + "url_template": "https://registry.npmjs.org/esm/-/esm-.tgz", + "version": "3.2.25" + }, + "libtommath": { + "branch": "develop", + "builtin": false, + "description": "LibTomMath is a free open source portable number theoretic multiple-precision integer library written entirely in C.", + "homepage": "https://www.libtom.net", + "owner": "libtom", + "repo": "libtommath", + "rev": "584405ff8e357290362671b5e7db6110a959cbaa", + "sha256": "1vl606rm8ba7vjhr0rbdqvih5d4r5iqalqlj5mnz6j3bnsn83b2a", + "type": "tarball", + "url": "https://github.com/libtom/libtommath/archive/584405ff8e357290362671b5e7db6110a959cbaa.tar.gz", + "url_template": "https://github.com///archive/.tar.gz" + }, + "nixpkgs": { + "branch": "release-19.09", + "description": "A read-only mirror of NixOS/nixpkgs tracking the released channels. Send issues and PRs to", + "homepage": "https://github.com/NixOS/nixpkgs", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "82875a20ba444110396f95537b18247898e40e22", + "sha256": "1xy2zn3hkcv66ddvscr3l32jcx1qg9h14zvhmy5zf0pcfb8gn42i", + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/82875a20ba444110396f95537b18247898e40e22.tar.gz", + "url_template": "https://github.com///archive/.tar.gz" + }, + "nixpkgs-llvm": { + "branch": "master", + "description": "Nix Packages collection", + "homepage": null, + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "42710203b04738b8f19ae51f0fd21d22fddf3f39", + "sha256": "1fqfi0rrlhmssp2cfz07f9sg3mvck28mxnmd39w2ir8670xfixvq", + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/42710203b04738b8f19ae51f0fd21d22fddf3f39.tar.gz", + "url_template": "https://github.com///archive/.tar.gz" + }, + "winter": { + "branch": "master", + "builtin": false, + "description": "Haskell port of the WebAssembly OCaml reference interpreter", + "homepage": "https://github.com/WebAssembly/spec/tree/master/interpreter", + "owner": "dfinity-side-projects", + "repo": "winter", + "rev": "1e16b471644be26160cc20c4e2144c643c547ed8", + "sha256": "191fk1dv8vp28rwpl75nz9y3pbypc8jv9w669mvl9d2k5f74jirm", + "type": "tarball", + "url": "https://github.com/dfinity-side-projects/winter/archive/1e16b471644be26160cc20c4e2144c643c547ed8.tar.gz", + "url_template": "https://github.com///archive/.tar.gz" + } +} diff --git a/test/compare-wat.sh b/test/compare-wat.sh index d4791551085..6c7692f989b 100755 --- a/test/compare-wat.sh +++ b/test/compare-wat.sh @@ -39,7 +39,7 @@ function build_ref_to { --argstr path "$(realpath "$(dirname $0)/..")" \ -E ' {rev, ref, path}: - let nixpkg = import (../nix/nixpkgs.nix).nixpkgs {}; in + let nixpkg = import ../nix {}; in let checkout = (builtins.fetchGit {url = path; ref = ref; rev = rev; name = "old-moc";}).outPath; in builtins.trace checkout ( ((import checkout) {}).moc)' \ diff --git a/test/run-drun/ok/array-out-of-bounds.drun-run.ok b/test/run-drun/ok/array-out-of-bounds.drun-run.ok index 979281404cd..f7b89a6ce11 100644 --- a/test/run-drun/ok/array-out-of-bounds.drun-run.ok +++ b/test/run-drun/ok/array-out-of-bounds.drun-run.ok @@ -1,3 +1,3 @@ ingress(0) System -ingress(1) Err: IC0503: Canister 1125899906842624 trapped explicitly: Array index out of bounds -ingress(2) Err: IC0503: Canister 1125899906842624 trapped explicitly: Array index out of bounds +ingress(1) Err: IC0503: Canister ic:000000000000040054 trapped explicitly: Array index out of bounds +ingress(2) Err: IC0503: Canister ic:000000000000040054 trapped explicitly: Array index out of bounds diff --git a/test/run-drun/ok/call-async-method.drun-run.ok b/test/run-drun/ok/call-async-method.drun-run.ok index f5a4ad71f0d..7406b2a6114 100644 --- a/test/run-drun/ok/call-async-method.drun-run.ok +++ b/test/run-drun/ok/call-async-method.drun-run.ok @@ -1,2 +1,2 @@ ingress(0) System -ingress(1) Err: IC0503: Canister 1125899906842624 trapped explicitly: not a self-call +ingress(1) Err: IC0503: Canister ic:000000000000040054 trapped explicitly: not a self-call diff --git a/test/run-drun/ok/divide-by-zero.drun-run.ok b/test/run-drun/ok/divide-by-zero.drun-run.ok index b2f6837768e..f15b7e6ac5f 100644 --- a/test/run-drun/ok/divide-by-zero.drun-run.ok +++ b/test/run-drun/ok/divide-by-zero.drun-run.ok @@ -1 +1 @@ -ingress(0) Err: IC0502: Canister 1125899906842624 trapped: integer division by 0 +ingress(0) Err: IC0502: Canister ic:000000000000040054 trapped: integer division by 0 diff --git a/test/run-drun/ok/idl-bad.drun-run.ok b/test/run-drun/ok/idl-bad.drun-run.ok index dddcbedf783..51eababe4f0 100644 --- a/test/run-drun/ok/idl-bad.drun-run.ok +++ b/test/run-drun/ok/idl-bad.drun-run.ok @@ -1,3 +1,3 @@ ingress(0) System debug.print: IDL error: missing magic bytes -Err: IC0502: Canister 1125899906842624 trapped: unreachable +Err: IC0502: Canister ic:000000000000040054 trapped: unreachable diff --git a/test/run-drun/ok/idl-nary.drun-run.ok b/test/run-drun/ok/idl-nary.drun-run.ok index c5d9ec994f4..0bd09bf21f5 100644 --- a/test/run-drun/ok/idl-nary.drun-run.ok +++ b/test/run-drun/ok/idl-nary.drun-run.ok @@ -7,6 +7,6 @@ Ok: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f055468726565044 Ok: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 Ok: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 Ok: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 -Err: IC0503: Canister 1125899906842624 trapped explicitly: IDL error: too few arguments Text,Text,Text -Err: IC0503: Canister 1125899906842624 trapped explicitly: IDL error: left-over bytes Text,Text,Text +Err: IC0503: Canister ic:000000000000040054 trapped explicitly: IDL error: too few arguments Text,Text,Text +Err: IC0503: Canister ic:000000000000040054 trapped explicitly: IDL error: left-over bytes Text,Text,Text Ok: Payload: 0x4449444c000471717171034f6e650354776f05546872656504466f7572 diff --git a/test/run-drun/ok/selftail.drun-run.ok b/test/run-drun/ok/selftail.drun-run.ok index b5601dba467..f4caf71ca8f 100644 --- a/test/run-drun/ok/selftail.drun-run.ok +++ b/test/run-drun/ok/selftail.drun-run.ok @@ -1,3 +1,3 @@ debug.print: ok1 debug.print: ok2 -ingress(0) Err: IC0502: Canister 1125899906842624 trapped: stack overflow +ingress(0) Err: IC0502: Canister ic:000000000000040054 trapped: stack overflow From cb5016365637e77a9f6a2d010ecce52f938a52ca Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 17 Jan 2020 18:14:33 +0100 Subject: [PATCH 0963/1176] Nix: Do not pull separate nixpkgs for llvm (#1132) * Nix: Do not pull separate nixpkgs for llvm since 748a6c937ca2f8d1756f56606f495322a7f443c6 our nixpkgs is new enough * Delete nix/llvm.nix --- default.nix | 6 ++---- nix/llvm.nix | 11 ----------- nix/sources.json | 22 ++++++++++++---------- 3 files changed, 14 insertions(+), 25 deletions(-) delete mode 100644 nix/llvm.nix diff --git a/default.nix b/default.nix index 90f11ee9693..b548b9d6ada 100644 --- a/default.nix +++ b/default.nix @@ -5,8 +5,6 @@ let nixpkgs = import ./nix { inherit system; }; in -let llvm = import ./nix/llvm.nix { inherit (nixpkgs) system sources; }; in - let stdenv = nixpkgs.stdenv; in let subpath = p: import ./nix/gitSource.nix p; in @@ -25,8 +23,8 @@ let haskellPackages = nixpkgs.haskellPackages.override { let llvmBuildInputs = [ nixpkgs.clang # for native building - llvm.clang_9 # for wasm building - llvm.lld_9 # for wasm building + nixpkgs.clang_9 # for wasm building + nixpkgs.lld_9 # for wasm building ]; # When compiling natively, we want to use `clang` (which is a nixpkgs diff --git a/nix/llvm.nix b/nix/llvm.nix deleted file mode 100644 index bb18c6f0a76..00000000000 --- a/nix/llvm.nix +++ /dev/null @@ -1,11 +0,0 @@ -{ system, sources } : - -let pkgs = (import sources.nixpkgs-llvm) { - system = system; - }; in - -{ - pkgs = pkgs; - clang_9 = pkgs.llvmPackages_9.clang-unwrapped; - lld_9 = pkgs.llvmPackages_9.lld; -} diff --git a/nix/sources.json b/nix/sources.json index 20d633da5aa..f4a891c1259 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -27,7 +27,7 @@ "url_template": "https://github.com///archive/.tar.gz" }, "nixpkgs": { - "branch": "release-19.09", + "branch": "master", "description": "A read-only mirror of NixOS/nixpkgs tracking the released channels. Send issues and PRs to", "homepage": "https://github.com/NixOS/nixpkgs", "owner": "NixOS", @@ -38,17 +38,19 @@ "url": "https://github.com/NixOS/nixpkgs/archive/82875a20ba444110396f95537b18247898e40e22.tar.gz", "url_template": "https://github.com///archive/.tar.gz" }, - "nixpkgs-llvm": { - "branch": "master", - "description": "Nix Packages collection", + "ocaml-vlq": { + "branch": "v0.2.0", + "builtin": false, + "description": "A library to encode/decode numbers in OCaml.", "homepage": null, - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "42710203b04738b8f19ae51f0fd21d22fddf3f39", - "sha256": "1fqfi0rrlhmssp2cfz07f9sg3mvck28mxnmd39w2ir8670xfixvq", + "owner": "flowtype", + "repo": "ocaml-vlq", + "rev": "115bf0fef38018f31ac6386fef17a00bd8307218", + "sha256": "09jdgih2n2qwpxnlbcca4xa193rwbd1nw7prxaqlg134l4mbya83", "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/42710203b04738b8f19ae51f0fd21d22fddf3f39.tar.gz", - "url_template": "https://github.com///archive/.tar.gz" + "url": "https://github.com/flowtype/ocaml-vlq/archive/115bf0fef38018f31ac6386fef17a00bd8307218.tar.gz", + "url_template": "https://github.com///archive/.tar.gz", + "version": "v0.2.0" }, "winter": { "branch": "master", From fe78a2ee87f59035bc32c4ad42c76233a08a5998 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Sat, 18 Jan 2020 11:45:22 +0000 Subject: [PATCH 0964/1176] add test output file; delete commmented out code --- src/ir_passes/async.ml | 10 ---------- test/run-drun/ok/indirect-counter.ic-stub-run.ok | 12 ++++++++++++ 2 files changed, 12 insertions(+), 10 deletions(-) create mode 100644 test/run-drun/ok/indirect-counter.ic-stub-run.ok diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index f5bae02c5bd..ebbcf28df98 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -241,16 +241,6 @@ let transform mode env prog = tb, List.map t_typ (List.map (T.open_ [t0]) ts1) | t -> assert false in let ((nary_async, nary_reply, reject), def) = new_nary_async_reply mode ts1 in -(* TBD - (blockE [letP (tupP [varP nary_async; varP nary_reply; varP reject]) def; - funcD post u ( - let vs = fresh_vars "v" ts1 in - let k = vs -->* (ic_replyE ts1 (seqE vs)) in - let e = fresh_var "e" T.catch in - let r = [e] -->* (ic_rejectE (errorMessageE e)) in - callE (t_exp exp1) [t0] (tupE [k;r])); - expD (ic_callE post (seqE []) nary_reply reject); - *) (blockE [ letP (tupP [varP nary_async; varP nary_reply; varP reject]) def; let v = fresh_var "v" (T.seq ts1) in (* flatten v, here and below? *) diff --git a/test/run-drun/ok/indirect-counter.ic-stub-run.ok b/test/run-drun/ok/indirect-counter.ic-stub-run.ok new file mode 100644 index 00000000000..89e7adaf1a2 --- /dev/null +++ b/test/run-drun/ok/indirect-counter.ic-stub-run.ok @@ -0,0 +1,12 @@ +→ create +← completed: canister-id = 0x0000000000000400 +→ install +← completed +→ update inc(0x4449444c0000) +← completed: 0x4449444c0000 +→ update inc(0x4449444c0000) +← completed: 0x4449444c0000 +→ update inc(0x4449444c0000) +← completed: 0x4449444c0000 +→ update debugPrint(0x4449444c0000) +← completed: 0x4449444c0000 From 5111672d69b2d6fc74d89f787f2b46ea0e3560f1 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Sat, 18 Jan 2020 13:59:52 +0100 Subject: [PATCH 0965/1176] Make PrincipalId abstract (#1128) * Make PrincipalId abstract done in this commit: * Abstract `PrincipalId` * Equality, ordering * Primitive conversion to blob (meaning that hashing, pretty-printing can be done in stdlib) * IDL mapping as blob. * Stdlib: Add PrincipalId module * sed -i -e s,PrincipalId,Principal,g $(git grep -l PrincipalId) --- src/codegen/compile.ml | 7 ++++--- src/mo_frontend/coverage.ml | 1 + src/mo_idl/mo_to_idl.ml | 1 + src/mo_types/arrange_type.ml | 1 + src/mo_types/type.ml | 7 +++++-- src/mo_types/type.mli | 1 + src/mo_values/operator.ml | 2 +- src/prelude/prelude.ml | 6 ++++++ stdlib/Makefile | 4 ++++ stdlib/principalId.mo | 5 +++++ test/run-drun/caller.mo | 17 ++++++++++------- test/run/caller.mo | 6 +++--- test/run/multi-caller.mo | 16 ++++++++-------- 13 files changed, 50 insertions(+), 24 deletions(-) create mode 100644 stdlib/principalId.mo diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index c50bbbd32a2..eb75333a4d8 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -3319,6 +3319,7 @@ module Serialization = struct | Func (s, c, tbs, ts1, ts2) -> List.iter go ts1; List.iter go ts2 | Prim Blob -> () + | Prim Principal -> () | _ -> Printf.eprintf "type_desc: unexpected type %s\n" (string_of_typ t); assert false @@ -3368,7 +3369,7 @@ module Serialization = struct let rec add_typ t = match t with | Non -> assert false - | Prim Blob -> + | Prim Blob | Prim Principal -> add_typ Type.(Array (Prim Word8)) | Prim _ -> assert false | Tup ts -> @@ -3490,7 +3491,7 @@ module Serialization = struct get_x ^^ get_i ^^ Arr.idx env ^^ load_ptr ^^ size env t ) - | Prim Blob -> + | Prim Blob | Prim Principal -> let (set_len, get_len) = new_local env "len" in get_x ^^ Heap.load_field Blob.len_field ^^ set_len ^^ size_word env get_len ^^ @@ -3647,7 +3648,7 @@ module Serialization = struct ) ( List.mapi (fun i (_h, f) -> (i,f)) (sort_by_hash vs) ) ( E.trap_with env "serialize_go: unexpected variant" ) - | Prim Blob -> + | Prim (Blob | Principal) -> let (set_len, get_len) = new_local env "len" in get_x ^^ Heap.load_field Blob.len_field ^^ set_len ^^ write_word get_len ^^ diff --git a/src/mo_frontend/coverage.ml b/src/mo_frontend/coverage.ml index 211f70f65f7..1713878c7a5 100644 --- a/src/mo_frontend/coverage.ml +++ b/src/mo_frontend/coverage.ml @@ -104,6 +104,7 @@ let pick_val vs = function | T.Text | T.Blob | T.Error + | T.Principal | T.Float -> Any let rec expand_notval t n vs : desc list = diff --git a/src/mo_idl/mo_to_idl.ml b/src/mo_idl/mo_to_idl.ml index 586d1c1ab95..54cfbd83c59 100644 --- a/src/mo_idl/mo_to_idl.ml +++ b/src/mo_idl/mo_to_idl.ml @@ -58,6 +58,7 @@ let prim p = | Char -> I.PrimT I.Nat32 | Text -> I.PrimT I.Text | Blob -> I.VecT (I.PrimT I.Nat8 @@ no_region) + | Principal -> I.VecT (I.PrimT I.Nat8 @@ no_region) (* could also be an empty service? *) | Error -> assert false let rec typ vs t = diff --git a/src/mo_types/arrange_type.ml b/src/mo_types/arrange_type.ml index fe9cb123f55..b7283dfd95e 100644 --- a/src/mo_types/arrange_type.ml +++ b/src/mo_types/arrange_type.ml @@ -40,6 +40,7 @@ let prim p = match p with | Text -> Atom "Text" | Blob -> Atom "Blob" | Error -> Atom "Error" + | Principal -> Atom "Principal" let con c = Atom (Con.to_string c) diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index bd71b6729ed..3270fec8035 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -34,6 +34,7 @@ type prim = | Text | Blob (* IR use: Packed representation, vec u8 IDL type *) | Error + | Principal type t = typ and typ = @@ -112,7 +113,7 @@ let catch = Prim Error (* Shared call context *) -let caller = Prim Blob +let caller = Prim Principal let ctxt = Obj (Object,[{ lab = "caller"; typ = caller }]) let prim = function @@ -137,6 +138,7 @@ let prim = function | "Text" -> Text | "Blob" -> Blob | "Error" -> Error + | "Principal" -> Principal | s -> raise (Invalid_argument ("Type.prim: " ^ s)) let seq = function [t] -> t | ts -> Tup ts @@ -441,7 +443,7 @@ let rec span = function | Con _ as t -> span (promote t) | Prim Null -> Some 1 | Prim Bool -> Some 2 - | Prim (Nat | Int | Float | Text | Blob | Error) -> None + | Prim (Nat | Int | Float | Text | Blob | Error | Principal) -> None | Prim (Nat8 | Int8 | Word8) -> Some 0x100 | Prim (Nat16 | Int16 | Word16) -> Some 0x10000 | Prim (Nat32 | Int32 | Word32 | Nat64 | Int64 | Word64 | Char) -> None (* for all practical purposes *) @@ -1121,6 +1123,7 @@ let string_of_prim = function | Text -> "Text" | Blob -> "Blob" | Error -> "Error" + | Principal -> "Principal" let string_of_var (x, i) = if i = 0 then sprintf "%s" x else sprintf "%s.%d" x i diff --git a/src/mo_types/type.mli b/src/mo_types/type.mli index ac7a3387d5b..ac3b8e4a606 100644 --- a/src/mo_types/type.mli +++ b/src/mo_types/type.mli @@ -32,6 +32,7 @@ type prim = | Text | Blob (* IR use: Packed representation, vec u8 IDL type *) | Error + | Principal type t = typ and typ = diff --git a/src/mo_values/operator.ml b/src/mo_values/operator.ml index 9d2983f39c0..4ef4d443a6b 100644 --- a/src/mo_values/operator.ml +++ b/src/mo_values/operator.ml @@ -150,7 +150,7 @@ let num_relop fnat (fnat8, fnat16, fnat32, fnat64) fint (fint8, fint16, fint32, let ord_relop fnat fnats fint fints fwords ffloat fchar ftext fblob = function | T.Char -> fun v1 v2 -> Bool (fchar (as_char v1) (as_char v2)) | T.Text -> fun v1 v2 -> Bool (ftext (as_text v1) (as_text v2)) - | T.Blob -> fun v1 v2 -> Bool (ftext (as_text v1) (as_text v2)) + | T.Blob | T.Principal -> fun v1 v2 -> Bool (ftext (as_text v1) (as_text v2)) | t -> num_relop fnat fnats fint fints fwords ffloat t let eq_relop fnat fnats fint fints fwords ffloat fchar ftext fblob fnull fbool = function diff --git a/src/prelude/prelude.ml b/src/prelude/prelude.ml index 7a019a09f0c..00794aee7cb 100644 --- a/src/prelude/prelude.ml +++ b/src/prelude/prelude.ml @@ -28,6 +28,7 @@ type Char = prim "Char"; type Text = prim "Text"; type Blob = prim "Blob"; type Error = prim "Error"; +type Principal = prim "Principal"; type @Iter = {next : () -> ?T_}; @@ -446,5 +447,10 @@ func errorMessage(e : Error) : Text = { ((prim "cast" : Error -> (ErrorCode, Text)) e).1; }; +// Principal + +func blobOfPrincipal(id : Principal) : Blob = { + ((prim "cast" : Principal -> Blob) id) +}; |} diff --git a/stdlib/Makefile b/stdlib/Makefile index a70fab7e344..bdc8c83cddf 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -17,6 +17,7 @@ WASM=\ TESTS=\ Array \ Blob \ + Principal \ Debug \ ArrayTest \ BufTest \ @@ -81,6 +82,9 @@ $(OUTDIR)/Debug.out: debug.mo | $(OUTDIR) $(OUTDIR)/Blob.out: blob.mo | $(OUTDIR) $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ +$(OUTDIR)/Principal.out: principalId.mo | $(OUTDIR) + $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ + $(OUTDIR)/Array.out: array.mo | $(OUTDIR) $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ diff --git a/stdlib/principalId.mo b/stdlib/principalId.mo new file mode 100644 index 00000000000..3fd298abb29 --- /dev/null +++ b/stdlib/principalId.mo @@ -0,0 +1,5 @@ +import Prim "mo:prim"; +import Blob "blob.mo"; +module { + public func hash(x : Principal) : Word32 = Blob.hash (Prim.blobOfPrincipal x); +} diff --git a/test/run-drun/caller.mo b/test/run-drun/caller.mo index c7245f88dbe..cde3797b5a5 100644 --- a/test/run-drun/caller.mo +++ b/test/run-drun/caller.mo @@ -2,12 +2,12 @@ import Prim "mo:prim"; actor a { public shared ctxt func c1 () : async () { - let c : Blob = ctxt.caller; + let c : Principal = ctxt.caller; return; }; public shared {caller} func c2 () : async () { - let c1 : Blob = caller; + let c1 : Principal = caller; return; }; @@ -24,24 +24,27 @@ actor a { }; public shared query {caller} func c6 () : async () { - let c1 : Blob = caller; + let c1 : Principal = caller; return; }; - public shared {caller} func c7() : async Blob { + public shared {caller} func c7() : async Principal { return caller; }; + // NB: The following tests are more about Blob than Principal + // Maybe move to their own tests once we have intro forms for blobs + public shared query {caller} func c8() : async Word32 { - Prim.hashBlob caller; + Prim.hashBlob (Prim.blobOfPrincipal caller); }; public shared query {caller} func c9() : async Nat { - caller.size(); + (Prim.blobOfPrincipal caller).size(); }; public shared query {caller} func c10() : async ?Word8 { - caller.bytes().next(); + (Prim.blobOfPrincipal caller).bytes().next(); }; }; diff --git a/test/run/caller.mo b/test/run/caller.mo index 6ff1a92c3d1..63fd6f1775c 100644 --- a/test/run/caller.mo +++ b/test/run/caller.mo @@ -1,16 +1,16 @@ import Prim "mo:prim"; actor a { - public shared { caller = c } func getCaller() : async Blob { + public shared { caller = c } func getCaller() : async Principal { return c; }; public shared query { caller = c } func getCallerHash() : async Word32 { - Prim.hashBlob c; + Prim.hashBlob (Prim.blobOfPrincipal c); }; public shared query { caller = c } func getCallerSize() : async Nat { - c.size(); + (Prim.blobOfPrincipal c).size(); }; public shared {caller} func c () : async () { diff --git a/test/run/multi-caller.mo b/test/run/multi-caller.mo index dfae6def25b..79a7bece4b4 100644 --- a/test/run/multi-caller.mo +++ b/test/run/multi-caller.mo @@ -3,12 +3,12 @@ actor a { // returns caller id - public shared { caller = c } func getCaller() : async Blob { + public shared { caller = c } func getCaller() : async Principal { c }; // returns self id when called (internally or externally) - public shared func getSelf() : async Blob { + public shared func getSelf() : async Principal { await getCaller(); }; @@ -18,12 +18,12 @@ actor a { actor class C () { // returns caller id - public shared { caller = c } func getCaller() : async Blob { + public shared { caller = c } func getCaller() : async Principal { c }; // returns self id when called (internally or externally) - public shared func getSelf() : async Blob { + public shared func getSelf() : async Principal { await getCaller(); }; @@ -51,12 +51,12 @@ ignore async { actor Ping { // returns caller id - public shared { caller = c } func getCaller() : async Blob { + public shared { caller = c } func getCaller() : async Principal { c }; // returns self id when called (internally or externally) - public func getSelf() : async Blob { + public func getSelf() : async Principal { await getCaller(); }; @@ -71,12 +71,12 @@ actor Ping { actor Pong { // returns caller id - public shared { caller = c } func getCaller() : async Blob { + public shared { caller = c } func getCaller() : async Principal { c }; // returns self id when called (internally or externally) - public func getSelf() : async Blob { + public func getSelf() : async Principal { await getCaller(); }; From 6499a7addeebf50426bb7e552e27f6cd50f941b3 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Sun, 19 Jan 2020 23:26:36 +0100 Subject: [PATCH 0966/1176] Stdlib: Reorganize build, test and nix setup (#1135) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Stdlib: Reorganize build, test and nix setup Noteworthy changes: * Stdlib sources are in `stdlib/src` tests are in `stdlib/test` docs are in `stdlib/doc` (no more `rm $out/*Test.mo`) * Individual Makefiles in these directories, as well as the three examples in `stdlib/examples/*` * In `stdlib/tests`, auto-generate a test that simply imports all stdlib files. This makes sure the stdlib actually compiles (was not the case before) * Tests and examples use package imports `"mo:stdlib/…"` to import the stdlib, instead of relative paths. The `Makefile`s are set up to point to `./stdlib/src` by default. But when building via nix, we are building against the stdlib as installed by nix * More fine-grained nix setup, so when you just change the examples, or the tests, the `stdlib` derivation does not have to be rebuild. * Runs the tests for `Rx` and `ActorSpec` using `wasmtimes` * Fix all-systems-go * use patsubst * Update default.nix Co-Authored-By: Gabor Greif Co-authored-by: Gabor Greif --- .gitignore | 1 + default.nix | 84 +-- stdlib/.gitignore | 2 - stdlib/Makefile | 562 ------------------ stdlib/char.mo | 7 - stdlib/doc/Makefile | 51 ++ stdlib/{ => doc}/README.md | 0 .../{ => doc}/tools/markdown-of-markdown.py | 0 stdlib/{ => doc}/tools/markdown-of-motoko.py | 0 stdlib/dummy | 1 - stdlib/examples/actorspec/Makefile | 20 + stdlib/examples/actorspec/src/ActorSpec.mo | 8 +- stdlib/examples/produce-exchange/Makefile | 263 ++++++++ .../produce-exchange/{ => src}/serverActor.mo | 12 +- .../produce-exchange/{ => src}/serverLang.mo | 2 +- .../produce-exchange/{ => src}/serverModel.mo | 20 +- .../{ => src}/serverModelTypes.mo | 4 +- .../produce-exchange/{ => src}/serverTypes.mo | 0 .../produce-exchange/test/evalBulk.mo | 10 +- .../test/loadWorkloadAndQueryBig.mo | 8 +- .../test/producerRemInventory.mo | 10 +- .../{ => test}/profileActor.mo | 4 +- .../test/profileFastCounts.mo | 6 +- .../test/retailerReserveMany.mo | 10 +- .../test/simpleSetupAndQuery.mo | 10 +- .../produce-exchange}/tools/stopwatch.c | 0 stdlib/examples/rx/Makefile | 20 + stdlib/examples/rx/test/RxTest.mo | 2 +- stdlib/{ => src}/array.mo | 0 stdlib/{ => src}/assocList.mo | 0 stdlib/{ => src}/blob.mo | 0 stdlib/{ => src}/buf.mo | 0 stdlib/src/char.mo | 8 + stdlib/{ => src}/debug.mo | 0 stdlib/{ => src}/docTable.mo | 0 stdlib/{ => src}/function.mo | 0 stdlib/{ => src}/hash.mo | 0 stdlib/{ => src}/hashMap.mo | 0 stdlib/{ => src}/int.mo | 0 stdlib/{ => src}/iter.mo | 0 stdlib/{ => src}/list.mo | 0 stdlib/{ => src}/nat.mo | 0 stdlib/{ => src}/none.mo | 0 stdlib/{ => src}/option.mo | 0 stdlib/{ => src}/prelude.mo | 0 stdlib/{ => src}/principalId.mo | 0 stdlib/{ => src}/result.mo | 0 stdlib/{ => src}/text.mo | 0 stdlib/{ => src}/trie.mo | 0 stdlib/{ => src}/trieMap.mo | 0 stdlib/{ => src}/trieSet.mo | 0 stdlib/test/Makefile | 37 ++ stdlib/{ => test}/arrayTest.mo | 6 +- stdlib/{ => test}/bufTest.mo | 4 +- stdlib/{ => test}/functionTest.mo | 6 +- stdlib/{ => test}/hashMapTest.mo | 4 +- stdlib/{ => test}/intTest.mo | 4 +- stdlib/{ => test}/iterTest.mo | 6 +- stdlib/{ => test}/listTest.mo | 4 +- stdlib/{ => test}/natTest.mo | 4 +- stdlib/{ => test}/noneTest.mo | 6 +- stdlib/{ => test}/optionTest.mo | 4 +- stdlib/{ => test}/textTest.mo | 4 +- stdlib/{ => test}/trieMapTest.mo | 4 +- 64 files changed, 525 insertions(+), 693 deletions(-) delete mode 100644 stdlib/.gitignore delete mode 100644 stdlib/Makefile delete mode 100644 stdlib/char.mo create mode 100644 stdlib/doc/Makefile rename stdlib/{ => doc}/README.md (100%) rename stdlib/{ => doc}/tools/markdown-of-markdown.py (100%) rename stdlib/{ => doc}/tools/markdown-of-motoko.py (100%) delete mode 100644 stdlib/dummy create mode 100644 stdlib/examples/actorspec/Makefile create mode 100644 stdlib/examples/produce-exchange/Makefile rename stdlib/examples/produce-exchange/{ => src}/serverActor.mo (99%) rename stdlib/examples/produce-exchange/{ => src}/serverLang.mo (98%) rename stdlib/examples/produce-exchange/{ => src}/serverModel.mo (99%) rename stdlib/examples/produce-exchange/{ => src}/serverModelTypes.mo (98%) rename stdlib/examples/produce-exchange/{ => src}/serverTypes.mo (100%) rename stdlib/examples/produce-exchange/{ => test}/profileActor.mo (90%) rename stdlib/{ => examples/produce-exchange}/tools/stopwatch.c (100%) create mode 100644 stdlib/examples/rx/Makefile rename stdlib/{ => src}/array.mo (100%) rename stdlib/{ => src}/assocList.mo (100%) rename stdlib/{ => src}/blob.mo (100%) rename stdlib/{ => src}/buf.mo (100%) create mode 100644 stdlib/src/char.mo rename stdlib/{ => src}/debug.mo (100%) rename stdlib/{ => src}/docTable.mo (100%) rename stdlib/{ => src}/function.mo (100%) rename stdlib/{ => src}/hash.mo (100%) rename stdlib/{ => src}/hashMap.mo (100%) rename stdlib/{ => src}/int.mo (100%) rename stdlib/{ => src}/iter.mo (100%) rename stdlib/{ => src}/list.mo (100%) rename stdlib/{ => src}/nat.mo (100%) rename stdlib/{ => src}/none.mo (100%) rename stdlib/{ => src}/option.mo (100%) rename stdlib/{ => src}/prelude.mo (100%) rename stdlib/{ => src}/principalId.mo (100%) rename stdlib/{ => src}/result.mo (100%) rename stdlib/{ => src}/text.mo (100%) rename stdlib/{ => src}/trie.mo (100%) rename stdlib/{ => src}/trieMap.mo (100%) rename stdlib/{ => src}/trieSet.mo (100%) create mode 100644 stdlib/test/Makefile rename stdlib/{ => test}/arrayTest.mo (97%) rename stdlib/{ => test}/bufTest.mo (85%) rename stdlib/{ => test}/functionTest.mo (89%) rename stdlib/{ => test}/hashMapTest.mo (97%) rename stdlib/{ => test}/intTest.mo (86%) rename stdlib/{ => test}/iterTest.mo (96%) rename stdlib/{ => test}/listTest.mo (97%) rename stdlib/{ => test}/natTest.mo (84%) rename stdlib/{ => test}/noneTest.mo (54%) rename stdlib/{ => test}/optionTest.mo (98%) rename stdlib/{ => test}/textTest.mo (68%) rename stdlib/{ => test}/trieMapTest.mo (97%) diff --git a/.gitignore b/.gitignore index f52bf6e7a76..d75197c2921 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .database .dvm +_out /result* **/*~ diff --git a/default.nix b/default.nix index b548b9d6ada..a719cf42e67 100644 --- a/default.nix +++ b/default.nix @@ -345,63 +345,66 @@ rec { stdlib = stdenv.mkDerivation { name = "stdlib"; - src = subpath ./stdlib; - buildInputs = with nixpkgs; - [ bash ]; - buildPhase = '' - patchShebangs . + src = subpath ./stdlib/src; + phases = "unpackPhase installPhase"; + installPhase = '' + mkdir -p $out + cp ./*.mo $out ''; + }; + + stdlib-tests = stdenv.mkDerivation { + name = "stdlib-tests"; + src = subpath ./stdlib/test; + phases = "unpackPhase checkPhase installPhase"; doCheck = true; + installPhase = "touch $out"; checkInputs = [ + nixpkgs.wasmtime moc - nixpkgs.python ]; checkPhase = '' - make MOC=${moc}/bin/moc alltests + make MOC=moc STDLIB=${stdlib} ''; - installPhase = '' - mkdir -p $out - cp ./*.mo $out - rm $out/*Test.mo - ''; - forceShare = ["man"]; }; + examples = + let example_subdir = dir: stdenv.mkDerivation { + name = dir; + src = subpath "./stdlib/examples/${dir}"; + phases = "unpackPhase checkPhase installPhase"; + doCheck = true; + installPhase = "touch $out"; + buildInputs = [ + nixpkgs.bash + moc + nixpkgs.wasmtime + ]; + checkPhase = '' + make MOC=moc STDLIB=${stdlib} + ''; + }; in + { + actorspec = example_subdir "actorspec"; + rx = example_subdir "rx"; + produce-exchange = example_subdir "produce-exchange"; + }; + + stdlib-doc = stdenv.mkDerivation { name = "stdlib-doc"; - src = subpath ./stdlib; + src = subpath ./stdlib/doc; buildInputs = with nixpkgs; [ pandoc bash python ]; buildPhase = '' patchShebangs . - make alldoc + make STDLIB=${stdlib} ''; installPhase = '' mkdir -p $out - mv doc $out/ + mv _out/* $out/ mkdir -p $out/nix-support - echo "report docs $out/doc README.html" >> $out/nix-support/hydra-build-products - ''; - forceShare = ["man"]; - }; - - produce-exchange = stdenv.mkDerivation { - name = "produce-exchange"; - src = subpath ./stdlib; - buildInputs = [ - moc - ]; - - doCheck = true; - buildPhase = '' - make MOC=moc OUTDIR=_out _out/ProduceExchange.wasm - ''; - checkPhase = '' - make MOC=moc OUTDIR=_out _out/ProduceExchange.out - ''; - installPhase = '' - mkdir -p $out - cp _out/ProduceExchange.wasm $out + echo "report docs $out README.html" >> $out/nix-support/hydra-build-products ''; }; @@ -416,12 +419,13 @@ rec { samples rts stdlib + stdlib-tests stdlib-doc - produce-exchange users-guide ic-stub shell - ] ++ builtins.attrValues tests; + ] ++ builtins.attrValues tests + ++ builtins.attrValues examples; }; shell = nixpkgs.mkShell { diff --git a/stdlib/.gitignore b/stdlib/.gitignore deleted file mode 100644 index 9fbb0098fec..00000000000 --- a/stdlib/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -_out -doc diff --git a/stdlib/Makefile b/stdlib/Makefile deleted file mode 100644 index bdc8c83cddf..00000000000 --- a/stdlib/Makefile +++ /dev/null @@ -1,562 +0,0 @@ -MOC=../src/moc -DRUN=drun -OUTDIR=_out -DOCDIR=doc -STOPWATCH_C=./tools/stopwatch.c -MDofMO=./tools/markdown-of-motoko.py -MDofMD=./tools/markdown-of-markdown.py -PANDOC=pandoc -STOPWATCH=$(OUTDIR)/stopwatch - -WASM=\ - ActorSpec \ - ActorSpecDemo \ - ProduceExchange \ - Rx \ - -TESTS=\ - Array \ - Blob \ - Principal \ - Debug \ - ArrayTest \ - BufTest \ - Buf \ - AssocList \ - DocTable \ - Function \ - FunctionTest \ - Hash \ - HashMap \ - HashMapTest \ - TrieMap \ - TrieMapTest \ - Int \ - IntTest \ - Iter \ - IterTest \ - List \ - ListTest \ - Nat \ - NatTest \ - None \ - NoneTest \ - Option \ - OptionTest \ - Result \ - Text \ - TextTest \ - Trie \ - TrieSet \ - ProduceExchange \ - producerRemInventory \ - retailerReserveMany \ - evalBulk \ - RxTest \ - -OUTFILES=$(addsuffix .out, $(TESTS)) $(addsuffix .wasm, $(WASM)) - -OUTPATHS=$(addprefix $(OUTDIR)/, $(OUTFILES)) - -.PHONY: default all clean alltests alldoc docMd docHtml profile-wasm profile-interp - -default: all - -docmsg: - @echo Begin building documentation in \`$(DOCDIR)\`... - @echo $(HRULE) - -alltests: $(OUTDIR) $(OUTPATHS) - -all: alldoc alltests profile-wasm profile-interp - -clean: - rm -rf $(OUTDIR) $(DOCDIR) - -$(OUTDIR): - @mkdir $@ - -$(OUTDIR)/Debug.out: debug.mo | $(OUTDIR) - $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/Blob.out: blob.mo | $(OUTDIR) - $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/Principal.out: principalId.mo | $(OUTDIR) - $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/Array.out: array.mo | $(OUTDIR) - $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/ArrayTest.out: arrayTest.mo | $(OUTDIR) - $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/Buf.out: buf.mo | $(OUTDIR) - $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/BufTest.out: bufTest.mo | $(OUTDIR) - $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/HashMapTest.out: hashMapTest.mo | $(OUTDIR) - $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/HashMap.out: hashMap.mo | $(OUTDIR) - $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/TrieMapTest.out: trieMapTest.mo | $(OUTDIR) - $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/TrieMap.out: trieMap.mo | $(OUTDIR) - $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/Function.out: function.mo | $(OUTDIR) - $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/FunctionTest.out: functionTest.mo | $(OUTDIR) - $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/Int.out: int.mo | $(OUTDIR) - $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/IntTest.out: intTest.mo | $(OUTDIR) - $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/Iter.out: iter.mo | $(OUTDIR) - $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/IterTest.out: iterTest.mo | $(OUTDIR) - $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/Nat.out: nat.mo | $(OUTDIR) - $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/NatTest.out: natTest.mo | $(OUTDIR) - $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/Hash.out: hash.mo | $(OUTDIR) - $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/None.out: none.mo | $(OUTDIR) - $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/NoneTest.out: noneTest.mo | $(OUTDIR) - $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/Option.out: option.mo | $(OUTDIR) - $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/OptionTest.out: optionTest.mo | $(OUTDIR) - $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/Result.out: result.mo | $(OUTDIR) - $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/List.out: list.mo | $(OUTDIR) - $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/ListTest.out: listTest.mo | $(OUTDIR) - $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/AssocList.out: assocList.mo | $(OUTDIR) - $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/Text.out: text.mo | $(OUTDIR) - $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/TextTest.out: textTest.mo | $(OUTDIR) - $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ - - -$(OUTDIR)/Trie.out: trie.mo | $(OUTDIR) - $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/TrieSet.out: trieSet.mo | $(OUTDIR) - $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ - -$(OUTDIR)/DocTable.out: docTable.mo | $(OUTDIR) - $(MOC) -r $(filter-out $(OUTDIR), $^) > $@ - - -#########################################################################################################33 - -## -## Documentation -## - -alldoc: docMd docHtml - -# Markdown documentation, extracted from the source directory -docMd: \ - $(DOCDIR)/README.md \ - $(DOCDIR)/prelude.md \ - $(DOCDIR)/array.md \ - $(DOCDIR)/buf.md \ - $(DOCDIR)/option.md \ - $(DOCDIR)/result.md \ - $(DOCDIR)/hash.md \ - $(DOCDIR)/list.md \ - $(DOCDIR)/assocList.md \ - $(DOCDIR)/trie.md \ - $(DOCDIR)/trieSet.md \ - $(DOCDIR)/docTable.md \ - $(DOCDIR)/examples/produce-exchange/README.md \ - $(DOCDIR)/examples/produce-exchange/serverTypes.md \ - $(DOCDIR)/examples/produce-exchange/serverLang.md \ - $(DOCDIR)/examples/produce-exchange/serverActor.md \ - $(DOCDIR)/examples/produce-exchange/serverModelTypes.md \ - $(DOCDIR)/examples/produce-exchange/serverModel.md \ - | \ - $(DOCDIR)/ \ - $(DOCDIR)/examples/produce-exchange/ - -# HTML documentation, extracted from the source directory -docHtml: \ - $(DOCDIR)/README.html \ - $(DOCDIR)/prelude.html \ - $(DOCDIR)/array.html \ - $(DOCDIR)/buf.html \ - $(DOCDIR)/option.html \ - $(DOCDIR)/result.html \ - $(DOCDIR)/hash.html \ - $(DOCDIR)/list.html \ - $(DOCDIR)/assocList.html \ - $(DOCDIR)/trie.html \ - $(DOCDIR)/docTable.html \ - $(DOCDIR)/trieSet.html \ - $(DOCDIR)/examples/produce-exchange/README.html \ - $(DOCDIR)/examples/produce-exchange/serverTypes.html \ - $(DOCDIR)/examples/produce-exchange/serverLang.html \ - $(DOCDIR)/examples/produce-exchange/serverActor.html \ - $(DOCDIR)/examples/produce-exchange/serverModelTypes.html \ - $(DOCDIR)/examples/produce-exchange/serverModel.html \ - | \ - $(DOCDIR)/ \ - $(DOCDIR)/examples/produce-exchange/ - -$(DOCDIR): - mkdir $@ - -$(DOCDIR)/README.md: README.md | $(DOCDIR) - @echo "" > $@ - @echo "" >> $@ - $(MDofMD) $< >> $@ - -$(DOCDIR)/examples/produce-exchange/: README.md - @mkdir -p $@ - -$(DOCDIR)/examples/produce-exchange/README.md: examples/produce-exchange/README.md | $(DOCDIR)/examples/produce-exchange/ - @echo "" > $@ - @echo "" >> $@ - $(MDofMD) $< >> $@ - -#########################################################################################################33 - -## -## PX Unit tests -## - -PRODUCE_EXCHANGE_SRC=\ - prelude.mo option.mo hash.mo list.mo assocList.mo trie.mo docTable.mo result.mo \ - examples/produce-exchange/serverTypes.mo \ - examples/produce-exchange/serverLang.mo \ - examples/produce-exchange/serverModelTypes.mo \ - examples/produce-exchange/serverModel.mo \ - examples/produce-exchange/serverActor.mo \ - -$(OUTDIR)/ProduceExchange.out: $(PRODUCE_EXCHANGE_SRC) \ - examples/produce-exchange/test/simpleSetupAndQuery.mo | $(OUTDIR) - $(MOC) -stub-system-api -r examples/produce-exchange/test/simpleSetupAndQuery.mo > $@ - -$(OUTDIR)/retailerReserveMany.out: $(PRODUCE_EXCHANGE_SRC) \ - examples/produce-exchange/test/retailerReserveMany.mo | $(OUTDIR) - $(MOC) -stub-system-api -r examples/produce-exchange/test/retailerReserveMany.mo > $@ - -$(OUTDIR)/producerRemInventory.out: $(PRODUCE_EXCHANGE_SRC) \ - examples/produce-exchange/test/producerRemInventory.mo | $(OUTDIR) - $(MOC) -stub-system-api -r examples/produce-exchange/test/producerRemInventory.mo > $@ - -$(OUTDIR)/evalBulk.out: $(PRODUCE_EXCHANGE_SRC) \ - examples/produce-exchange/test/evalBulk.mo | $(OUTDIR) - $(MOC) -stub-system-api -r examples/produce-exchange/test/evalBulk.mo > $@ - -$(OUTDIR)/ProduceExchange.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(MOC) -stub-system-api -c -o $@ examples/produce-exchange/serverActor.mo - -$(DOCDIR)/%.md: %.mo $(MDofMO) | $(DOCDIR) - @echo "" > $@ - @echo "" >> $@ - @echo "" >> $@ - $(MDofMO) $< >> $@ - -$(DOCDIR)/%.html: $(DOCDIR)/%.md - $(PANDOC) -f gfm $^ > $@ - -#########################################################################################################33 - -## -## ActorSpec Example -## - -ACTORSPEC_SRC=\ - array.mo \ - int.mo \ - text.mo \ - examples/actorspec/src/ActorSpec.mo \ - examples/actorspec/demo/Demo.mo \ - -$(OUTDIR)/ActorSpec.wasm: $(ACTORSPEC_SRC) | $(OUTDIR) - $(MOC) -c -o $@ examples/actorspec/src/ActorSpec.mo - -$(OUTDIR)/ActorSpecDemo.wasm: $(ACTORSPEC_SRC) | $(OUTDIR) - $(MOC) -c -o $@ examples/actorspec/demo/Demo.mo - - -#########################################################################################################33 - -## -## Rx Example -## - -RX_SRC=\ - array.mo \ - examples/rx/src/Rx.mo \ - examples/rx/test/RxTest.mo \ - -$(OUTDIR)/RxTest.out: $(RX_SRC) \ - examples/rx/test/RxTest.mo | $(OUTDIR) - $(MOC) -r examples/rx/test/RxTest.mo > $@ - -$(OUTDIR)/Rx.wasm: $(RX_SRC) | $(OUTDIR) - $(MOC) -c -o $@ examples/rx/src/Rx.mo - -#########################################################################################################33 - -## -## Profiling -## - -# to do: Fix my Makefile targets below to make the file shorter; -# There is lot of redundancy, but I don't know how to hack the Makefile to overcome it without also making it too complex. - -PROFILE_LOAD_SRC=\ - examples/produce-exchange/serverActor.mo \ - examples/produce-exchange/test/profileLoad.mo - -PROFILE_LOAD_QUERY_SRC=\ - examples/produce-exchange/serverActor.mo \ - examples/produce-exchange/test/profileLoadQuery.mo - -PROFILE_FIELDS=\ - --profile-field "hash_bit_length" \ - --profile-field "producer_count" \ - --profile-field "inventory_count" \ - --profile-field "transporter_count" \ - --profile-field "route_count" \ - --profile-field "retailer_join_count" \ - --profile-field "retailer_query_cost" \ - --profile-field "retailer_query_size_max" \ - -## -## To see the sizes of the workloads below, run `make profile-fast-counts`: -## - -profile-fast-counts: \ - $(OUTDIR)/profileFastCounts.csv - -$(OUTDIR)/profileFastCounts.csv: examples/produce-exchange/test/profileFastCounts.mo - $(MOC) -r examples/produce-exchange/test/profileFastCounts.mo > $@ - -profile-interp: \ - $(OUTDIR)/profileLoadQuery.05-01.csv \ - $(OUTDIR)/profileLoadQuery.05-02.csv \ - $(OUTDIR)/profileLoadQuery.05-03.csv \ - $(OUTDIR)/profileLoadQuery.05-04.csv \ - $(OUTDIR)/profileLoadQuery.05-05.csv \ - $(OUTDIR)/profileLoadQuery.05-06.csv \ - $(OUTDIR)/profileLoadQuery.05-07.csv \ - $(OUTDIR)/profileLoadQuery.05-08.csv \ - $(OUTDIR)/profileLoadQuery.05-09.csv \ - $(OUTDIR)/profileLoadQuery.05-10.csv \ - $(OUTDIR)/profileLoadQuery.05-20.csv \ - $(OUTDIR)/profileLoadQuery.05-50.csv \ - $(OUTDIR)/profileLoadQuery.05-100.csv \ - -## MO wishlist: the following various targets each take a params file that defines two variables used in the common test file. -## it would be better if we could accept named MO values as CLI params; that feature would obviate the need for the `param-X-Y.mo` files used below: - -$(OUTDIR)/profileLoadQuery.05-01.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) - time $(MOC) -r --profile examples/produce-exchange/test/params-5-1.mo $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) - -$(OUTDIR)/profileLoadQuery.05-02.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) - time $(MOC) -r --profile examples/produce-exchange/test/params-5-2.mo $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) - -$(OUTDIR)/profileLoadQuery.05-03.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) - time $(MOC) -r --profile examples/produce-exchange/test/params-5-3.mo $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) - -$(OUTDIR)/profileLoadQuery.05-04.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) - time $(MOC) -r --profile examples/produce-exchange/test/params-5-4.mo $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) - -$(OUTDIR)/profileLoadQuery.05-05.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) - time $(MOC) -r --profile examples/produce-exchange/test/params-5-5.mo $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) - -$(OUTDIR)/profileLoadQuery.05-06.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) - time $(MOC) -r --profile examples/produce-exchange/test/params-5-6.mo $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) - -$(OUTDIR)/profileLoadQuery.05-07.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) - time $(MOC) -r --profile examples/produce-exchange/test/params-5-7.mo $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) - -$(OUTDIR)/profileLoadQuery.05-08.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) - time $(MOC) -r --profile examples/produce-exchange/test/params-5-8.mo $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) - -$(OUTDIR)/profileLoadQuery.05-09.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) - time $(MOC) -r --profile examples/produce-exchange/test/params-5-9.mo $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) - -$(OUTDIR)/profileLoadQuery.05-10.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) - time $(MOC) -r --profile examples/produce-exchange/test/params-5-10.mo $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) - -$(OUTDIR)/profileLoadQuery.05-20.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) - time $(MOC) -r --profile examples/produce-exchange/test/params-5-20.mo $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) - -$(OUTDIR)/profileLoadQuery.05-50.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) - time $(MOC) -r --profile examples/produce-exchange/test/params-5-50.mo $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) - -$(OUTDIR)/profileLoadQuery.05-100.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) - time $(MOC) -r --profile examples/produce-exchange/test/params-5-100.mo $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) - -# wasm binaries and time measurements for various-sized PX workloads -profile-wasm: $(OUTDIR) profile-fast-counts \ - \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm.csv \ - \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_2.wasm \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_2.wasm.csv \ - \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_3.wasm \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_3.wasm.csv \ - \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_4.wasm \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_4.wasm.csv \ - \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm.csv \ - \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_6.wasm \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_6.wasm.csv \ - \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_7.wasm \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_7.wasm.csv \ - \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_8.wasm \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_8.wasm.csv \ - \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_9.wasm \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_9.wasm.csv \ - \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_10.wasm \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_10.wasm.csv \ - \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_20.wasm \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_20.wasm.csv \ - \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_50.wasm \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_50.wasm.csv \ - \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_100.wasm \ - $(OUTDIR)/ProduceExchangeLoadQuery_5_100.wasm.csv \ - - -$(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(MOC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-1.mo examples/produce-exchange/profileActor.mo - -$(OUTDIR)/ProduceExchangeLoadQuery_5_2.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(MOC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-2.mo examples/produce-exchange/profileActor.mo - -$(OUTDIR)/ProduceExchangeLoadQuery_5_3.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(MOC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-3.mo examples/produce-exchange/profileActor.mo - -$(OUTDIR)/ProduceExchangeLoadQuery_5_4.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(MOC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-4.mo examples/produce-exchange/profileActor.mo - -$(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(MOC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-5.mo examples/produce-exchange/profileActor.mo - -$(OUTDIR)/ProduceExchangeLoadQuery_5_6.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(MOC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-6.mo examples/produce-exchange/profileActor.mo - -$(OUTDIR)/ProduceExchangeLoadQuery_5_7.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(MOC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-7.mo examples/produce-exchange/profileActor.mo - -$(OUTDIR)/ProduceExchangeLoadQuery_5_8.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(MOC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-8.mo examples/produce-exchange/profileActor.mo - -$(OUTDIR)/ProduceExchangeLoadQuery_5_9.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(MOC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-9.mo examples/produce-exchange/profileActor.mo - -$(OUTDIR)/ProduceExchangeLoadQuery_5_10.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(MOC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-10.mo examples/produce-exchange/profileActor.mo - -$(OUTDIR)/ProduceExchangeLoadQuery_5_20.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(MOC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-20.mo examples/produce-exchange/profileActor.mo - -$(OUTDIR)/ProduceExchangeLoadQuery_5_50.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(MOC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-50.mo examples/produce-exchange/profileActor.mo - -$(OUTDIR)/ProduceExchangeLoadQuery_5_100.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) - $(MOC) -c -no-check-ir -o $@ examples/produce-exchange/test/params-5-100.mo examples/produce-exchange/profileActor.mo - - -$(STOPWATCH): $(STOPWATCH_C) - $(CC) $< -o $@ - -$(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm $(STOPWATCH) - $(STOPWATCH) "$(DRUN) $< /dev/null" "5, 1, " > $@ - cat $@ - -$(OUTDIR)/ProduceExchangeLoadQuery_5_2.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_2.wasm $(STOPWATCH) - $(STOPWATCH) "$(DRUN) $< /dev/null" "5, 2, " > $@ - cat $@ - -$(OUTDIR)/ProduceExchangeLoadQuery_5_3.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_3.wasm $(STOPWATCH) - $(STOPWATCH) "$(DRUN) $< /dev/null" "5, 3, " > $@ - cat $@ - -$(OUTDIR)/ProduceExchangeLoadQuery_5_4.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_4.wasm $(STOPWATCH) - $(STOPWATCH) "$(DRUN) $< /dev/null" "5, 4, " > $@ - cat $@ - -$(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm $(STOPWATCH) - $(STOPWATCH) "$(DRUN) $< /dev/null" "5, 5, " > $@ - cat $@ - -$(OUTDIR)/ProduceExchangeLoadQuery_5_6.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_6.wasm $(STOPWATCH) - $(STOPWATCH) "$(DRUN) $< /dev/null" "5, 6, " > $@ - cat $@ - -$(OUTDIR)/ProduceExchangeLoadQuery_5_7.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_7.wasm $(STOPWATCH) - $(STOPWATCH) "$(DRUN) $< /dev/null" "5, 7, " > $@ - cat $@ - -$(OUTDIR)/ProduceExchangeLoadQuery_5_8.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_8.wasm $(STOPWATCH) - $(STOPWATCH) "$(DRUN) $< /dev/null" "5, 8, " > $@ - cat $@ - -$(OUTDIR)/ProduceExchangeLoadQuery_5_9.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_9.wasm $(STOPWATCH) - $(STOPWATCH) "$(DRUN) $< /dev/null" "5, 9, " > $@ - cat $@ - -$(OUTDIR)/ProduceExchangeLoadQuery_5_10.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_10.wasm $(STOPWATCH) - $(STOPWATCH) "$(DRUN) $< /dev/null" "5, 10, " > $@ - cat $@ - -$(OUTDIR)/ProduceExchangeLoadQuery_5_20.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_20.wasm $(STOPWATCH) - $(STOPWATCH) "$(DRUN) $< /dev/null" "5, 20, " > $@ - cat $@ - -$(OUTDIR)/ProduceExchangeLoadQuery_5_50.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_50.wasm $(STOPWATCH) - $(STOPWATCH) "$(DRUN) $< /dev/null" "5, 50, " > $@ - cat $@ - -$(OUTDIR)/ProduceExchangeLoadQuery_5_100.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_100.wasm $(STOPWATCH) - $(STOPWATCH) "$(DRUN) $< /dev/null" "5, 100, " > $@ - cat $@ diff --git a/stdlib/char.mo b/stdlib/char.mo deleted file mode 100644 index 62f5849546a..00000000000 --- a/stdlib/char.mo +++ /dev/null @@ -1,7 +0,0 @@ -module { - - public func isDigit(char : Char) : Bool { - charToWord32(char) - charToWord32('0') <= (9 : Word32) - }; - -} diff --git a/stdlib/doc/Makefile b/stdlib/doc/Makefile new file mode 100644 index 00000000000..4ccd4b566c8 --- /dev/null +++ b/stdlib/doc/Makefile @@ -0,0 +1,51 @@ +STDLIB ?= ../src + +OUTDIR=_out +MDofMO=./tools/markdown-of-motoko.py +MDofMD=./tools/markdown-of-markdown.py +PANDOC=pandoc + + +.PHONY: default all clean docMd docHtml + +default: all + +all: doc + +clean: + rm -rf $(OUTDIR) + +#########################################################################################################33 + +## +## Documentation +## + +doc: docMd docHtml + +$(OUTDIR): + @mkdir -p $@ + + +$(OUTDIR)/%.md: $(STDLIB)/%.mo $(MDofMO) | $(OUTDIR) + @echo "" > $@ + @echo "" >> $@ + @echo "" >> $@ + $(MDofMO) $< >> $@ + +$(OUTDIR)/%.html: $(OUTDIR)/%.md + $(PANDOC) -f gfm $^ > $@ + + +DOCS = README prelude array buf option result hash list assocList trie trieSet docTable + +# Markdown documentation, extracted from the source directory +docMd: $(patsubst %,$(OUTDIR)/%.md,$(DOCS)) | $(OUTDIR) + +# HTML documentation, extracted from the source directory +docHtml: $(patsubst %,$(OUTDIR)/%.html,$(DOCS)) | $(OUTDIR) + +$(OUTDIR)/README.md: README.md | $(OUTDIR) + @echo "" > $@ + @echo "" >> $@ + $(MDofMD) $< >> $@ diff --git a/stdlib/README.md b/stdlib/doc/README.md similarity index 100% rename from stdlib/README.md rename to stdlib/doc/README.md diff --git a/stdlib/tools/markdown-of-markdown.py b/stdlib/doc/tools/markdown-of-markdown.py similarity index 100% rename from stdlib/tools/markdown-of-markdown.py rename to stdlib/doc/tools/markdown-of-markdown.py diff --git a/stdlib/tools/markdown-of-motoko.py b/stdlib/doc/tools/markdown-of-motoko.py similarity index 100% rename from stdlib/tools/markdown-of-motoko.py rename to stdlib/doc/tools/markdown-of-motoko.py diff --git a/stdlib/dummy b/stdlib/dummy deleted file mode 100644 index 8f4bef751a6..00000000000 --- a/stdlib/dummy +++ /dev/null @@ -1 +0,0 @@ -Wed Jul 3 11:03:58 MDT 2019 diff --git a/stdlib/examples/actorspec/Makefile b/stdlib/examples/actorspec/Makefile new file mode 100644 index 00000000000..54d692f5e55 --- /dev/null +++ b/stdlib/examples/actorspec/Makefile @@ -0,0 +1,20 @@ +STDLIB ?= ../../src +MOC ?= ../../../src/moc +WASMTIME_OPTIONS = --disable-cache --cranelift + +OUTDIR=_out + +all: $(OUTDIR)/demo.out + +$(OUTDIR): + @mkdir $@ + +$(OUTDIR)/ActorSpecDemo.wasm: demo/Demo.mo src/*.mo | $(OUTDIR) + $(MOC) -c --package stdlib $(STDLIB) -wasi-system-api -o $@ $< + +$(OUTDIR)/demo.out: $(OUTDIR)/ActorSpecDemo.wasm + wasmtime $(WASMTIME_OPTIONS) $< + + +clean: + rm -rf $(OUTDIR) diff --git a/stdlib/examples/actorspec/src/ActorSpec.mo b/stdlib/examples/actorspec/src/ActorSpec.mo index 100d9a72ee1..1ef05904ee4 100644 --- a/stdlib/examples/actorspec/src/ActorSpec.mo +++ b/stdlib/examples/actorspec/src/ActorSpec.mo @@ -1,7 +1,7 @@ -import Debug "../../../debug.mo"; -import Array "../../../array.mo"; -import Int "../../../int.mo"; -import Text "../../../text.mo"; +import Debug "mo:stdlib/debug.mo"; +import Array "mo:stdlib/array.mo"; +import Int "mo:stdlib/int.mo"; +import Text "mo:stdlib/text.mo"; module { public type Group = { diff --git a/stdlib/examples/produce-exchange/Makefile b/stdlib/examples/produce-exchange/Makefile new file mode 100644 index 00000000000..710a9ea9be6 --- /dev/null +++ b/stdlib/examples/produce-exchange/Makefile @@ -0,0 +1,263 @@ +STDLIB ?= ../../src +MOC ?= ../../../src/moc +DRUN ?= drun + +WASMTIME_OPTIONS = --disable-cache --cranelift +OUTDIR=_out + +MOC_OPTIONS = --package stdlib $(STDLIB) + +TESTS = \ + simpleSetupAndQuery \ + producerRemInventory \ + retailerReserveMany \ + evalBulk \ + + +TESTS_OUT = $(patsubst %, $(OUTDIR)/%.out, $(TESTS)) + +all: $(TESTS_OUT) + +$(OUTDIR)/%.out: test/%.mo src/*.mo | $(OUTDIR) + $(MOC) $(MOC_OPTIONS) -r $< >$@ + +$(OUTDIR): + @mkdir $@ + +clean: + rm -rf $(OUTDIR) + + +######################################################################################################### + +## +## Profiling +## + +profile: profile-wasm profile-interp + +# to do: Fix my Makefile targets below to make the file shorter; +# There is lot of redundancy, but I don't know how to hack the Makefile to overcome it without also making it too complex. + +PROFILE_LOAD_SRC=\ + serverActor.mo \ + test/profileLoad.mo + +PROFILE_LOAD_QUERY_SRC=\ + serverActor.mo \ + test/profileLoadQuery.mo + +PROFILE_FIELDS=\ + --profile-field "hash_bit_length" \ + --profile-field "producer_count" \ + --profile-field "inventory_count" \ + --profile-field "transporter_count" \ + --profile-field "route_count" \ + --profile-field "retailer_join_count" \ + --profile-field "retailer_query_cost" \ + --profile-field "retailer_query_size_max" \ + +## +## To see the sizes of the workloads below, run `make profile-fast-counts`: +## + +profile-fast-counts: \ + $(OUTDIR)/profileFastCounts.csv + +$(OUTDIR)/profileFastCounts.csv: test/profileFastCounts.mo + $(MOC) $(MOC_OPTIONS) -r test/profileFastCounts.mo > $@ + +profile-interp: \ + $(OUTDIR)/profileLoadQuery.05-01.csv \ + $(OUTDIR)/profileLoadQuery.05-02.csv \ + $(OUTDIR)/profileLoadQuery.05-03.csv \ + $(OUTDIR)/profileLoadQuery.05-04.csv \ + $(OUTDIR)/profileLoadQuery.05-05.csv \ + $(OUTDIR)/profileLoadQuery.05-06.csv \ + $(OUTDIR)/profileLoadQuery.05-07.csv \ + $(OUTDIR)/profileLoadQuery.05-08.csv \ + $(OUTDIR)/profileLoadQuery.05-09.csv \ + $(OUTDIR)/profileLoadQuery.05-10.csv \ + $(OUTDIR)/profileLoadQuery.05-20.csv \ + $(OUTDIR)/profileLoadQuery.05-50.csv \ + $(OUTDIR)/profileLoadQuery.05-100.csv \ + +## MO wishlist: the following various targets each take a params file that defines two variables used in the common test file. +## it would be better if we could accept named MO values as CLI params; that feature would obviate the need for the `param-X-Y.mo` files used below: + +$(OUTDIR)/profileLoadQuery.05-01.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) + time $(MOC) $(MOC_OPTIONS) -r --profile test/params-5-1.mo $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + +$(OUTDIR)/profileLoadQuery.05-02.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) + time $(MOC) $(MOC_OPTIONS) -r --profile test/params-5-2.mo $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + +$(OUTDIR)/profileLoadQuery.05-03.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) + time $(MOC) $(MOC_OPTIONS) -r --profile test/params-5-3.mo $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + +$(OUTDIR)/profileLoadQuery.05-04.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) + time $(MOC) $(MOC_OPTIONS) -r --profile test/params-5-4.mo $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + +$(OUTDIR)/profileLoadQuery.05-05.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) + time $(MOC) $(MOC_OPTIONS) -r --profile test/params-5-5.mo $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + +$(OUTDIR)/profileLoadQuery.05-06.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) + time $(MOC) $(MOC_OPTIONS) -r --profile test/params-5-6.mo $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + +$(OUTDIR)/profileLoadQuery.05-07.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) + time $(MOC) $(MOC_OPTIONS) -r --profile test/params-5-7.mo $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + +$(OUTDIR)/profileLoadQuery.05-08.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) + time $(MOC) $(MOC_OPTIONS) -r --profile test/params-5-8.mo $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + +$(OUTDIR)/profileLoadQuery.05-09.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) + time $(MOC) $(MOC_OPTIONS) -r --profile test/params-5-9.mo $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + +$(OUTDIR)/profileLoadQuery.05-10.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) + time $(MOC) $(MOC_OPTIONS) -r --profile test/params-5-10.mo $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + +$(OUTDIR)/profileLoadQuery.05-20.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) + time $(MOC) $(MOC_OPTIONS) -r --profile test/params-5-20.mo $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + +$(OUTDIR)/profileLoadQuery.05-50.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) + time $(MOC) $(MOC_OPTIONS) -r --profile test/params-5-50.mo $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + +$(OUTDIR)/profileLoadQuery.05-100.csv: $(PRODUCE_EXCHANGE_SRC) $(PROFILE_LOAD_QUERY_SRC) | $(OUTDIR) + time $(MOC) $(MOC_OPTIONS) -r --profile test/params-5-100.mo $(PROFILE_LOAD_QUERY_SRC) --profile-file $@ $(PROFILE_FIELDS) + +# wasm binaries and time measurements for various-sized PX workloads +profile-wasm: $(OUTDIR) profile-fast-counts \ + \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm.csv \ + \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_2.wasm \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_2.wasm.csv \ + \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_3.wasm \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_3.wasm.csv \ + \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_4.wasm \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_4.wasm.csv \ + \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm.csv \ + \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_6.wasm \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_6.wasm.csv \ + \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_7.wasm \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_7.wasm.csv \ + \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_8.wasm \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_8.wasm.csv \ + \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_9.wasm \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_9.wasm.csv \ + \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_10.wasm \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_10.wasm.csv \ + \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_20.wasm \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_20.wasm.csv \ + \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_50.wasm \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_50.wasm.csv \ + \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_100.wasm \ + $(OUTDIR)/ProduceExchangeLoadQuery_5_100.wasm.csv \ + + +$(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) + $(MOC) $(MOC_OPTIONS) -c -no-check-ir -o $@ test/params-5-1.mo test/profileActor.mo + +$(OUTDIR)/ProduceExchangeLoadQuery_5_2.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) + $(MOC) $(MOC_OPTIONS) -c -no-check-ir -o $@ test/params-5-2.mo test/profileActor.mo + +$(OUTDIR)/ProduceExchangeLoadQuery_5_3.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) + $(MOC) $(MOC_OPTIONS) -c -no-check-ir -o $@ test/params-5-3.mo test/profileActor.mo + +$(OUTDIR)/ProduceExchangeLoadQuery_5_4.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) + $(MOC) $(MOC_OPTIONS) -c -no-check-ir -o $@ test/params-5-4.mo test/profileActor.mo + +$(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) + $(MOC) $(MOC_OPTIONS) -c -no-check-ir -o $@ test/params-5-5.mo test/profileActor.mo + +$(OUTDIR)/ProduceExchangeLoadQuery_5_6.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) + $(MOC) $(MOC_OPTIONS) -c -no-check-ir -o $@ test/params-5-6.mo test/profileActor.mo + +$(OUTDIR)/ProduceExchangeLoadQuery_5_7.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) + $(MOC) $(MOC_OPTIONS) -c -no-check-ir -o $@ test/params-5-7.mo test/profileActor.mo + +$(OUTDIR)/ProduceExchangeLoadQuery_5_8.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) + $(MOC) $(MOC_OPTIONS) -c -no-check-ir -o $@ test/params-5-8.mo test/profileActor.mo + +$(OUTDIR)/ProduceExchangeLoadQuery_5_9.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) + $(MOC) $(MOC_OPTIONS) -c -no-check-ir -o $@ test/params-5-9.mo test/profileActor.mo + +$(OUTDIR)/ProduceExchangeLoadQuery_5_10.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) + $(MOC) $(MOC_OPTIONS) -c -no-check-ir -o $@ test/params-5-10.mo test/profileActor.mo + +$(OUTDIR)/ProduceExchangeLoadQuery_5_20.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) + $(MOC) $(MOC_OPTIONS) -c -no-check-ir -o $@ test/params-5-20.mo test/profileActor.mo + +$(OUTDIR)/ProduceExchangeLoadQuery_5_50.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) + $(MOC) $(MOC_OPTIONS) -c -no-check-ir -o $@ test/params-5-50.mo test/profileActor.mo + +$(OUTDIR)/ProduceExchangeLoadQuery_5_100.wasm: $(PRODUCE_EXCHANGE_SRC) | $(OUTDIR) + $(MOC) $(MOC_OPTIONS) -c -no-check-ir -o $@ test/params-5-100.mo test/profileActor.mo + + +$(STOPWATCH): $(STOPWATCH_C) + $(CC) $< -o $@ + +$(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_1.wasm $(STOPWATCH) + $(STOPWATCH) "$(DRUN) $< /dev/null" "5, 1, " > $@ + cat $@ + +$(OUTDIR)/ProduceExchangeLoadQuery_5_2.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_2.wasm $(STOPWATCH) + $(STOPWATCH) "$(DRUN) $< /dev/null" "5, 2, " > $@ + cat $@ + +$(OUTDIR)/ProduceExchangeLoadQuery_5_3.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_3.wasm $(STOPWATCH) + $(STOPWATCH) "$(DRUN) $< /dev/null" "5, 3, " > $@ + cat $@ + +$(OUTDIR)/ProduceExchangeLoadQuery_5_4.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_4.wasm $(STOPWATCH) + $(STOPWATCH) "$(DRUN) $< /dev/null" "5, 4, " > $@ + cat $@ + +$(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_5.wasm $(STOPWATCH) + $(STOPWATCH) "$(DRUN) $< /dev/null" "5, 5, " > $@ + cat $@ + +$(OUTDIR)/ProduceExchangeLoadQuery_5_6.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_6.wasm $(STOPWATCH) + $(STOPWATCH) "$(DRUN) $< /dev/null" "5, 6, " > $@ + cat $@ + +$(OUTDIR)/ProduceExchangeLoadQuery_5_7.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_7.wasm $(STOPWATCH) + $(STOPWATCH) "$(DRUN) $< /dev/null" "5, 7, " > $@ + cat $@ + +$(OUTDIR)/ProduceExchangeLoadQuery_5_8.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_8.wasm $(STOPWATCH) + $(STOPWATCH) "$(DRUN) $< /dev/null" "5, 8, " > $@ + cat $@ + +$(OUTDIR)/ProduceExchangeLoadQuery_5_9.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_9.wasm $(STOPWATCH) + $(STOPWATCH) "$(DRUN) $< /dev/null" "5, 9, " > $@ + cat $@ + +$(OUTDIR)/ProduceExchangeLoadQuery_5_10.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_10.wasm $(STOPWATCH) + $(STOPWATCH) "$(DRUN) $< /dev/null" "5, 10, " > $@ + cat $@ + +$(OUTDIR)/ProduceExchangeLoadQuery_5_20.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_20.wasm $(STOPWATCH) + $(STOPWATCH) "$(DRUN) $< /dev/null" "5, 20, " > $@ + cat $@ + +$(OUTDIR)/ProduceExchangeLoadQuery_5_50.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_50.wasm $(STOPWATCH) + $(STOPWATCH) "$(DRUN) $< /dev/null" "5, 50, " > $@ + cat $@ + +$(OUTDIR)/ProduceExchangeLoadQuery_5_100.wasm.csv: $(OUTDIR)/ProduceExchangeLoadQuery_5_100.wasm $(STOPWATCH) + $(STOPWATCH) "$(DRUN) $< /dev/null" "5, 100, " > $@ + cat $@ diff --git a/stdlib/examples/produce-exchange/serverActor.mo b/stdlib/examples/produce-exchange/src/serverActor.mo similarity index 99% rename from stdlib/examples/produce-exchange/serverActor.mo rename to stdlib/examples/produce-exchange/src/serverActor.mo index 8bc814608a8..92631649c08 100644 --- a/stdlib/examples/produce-exchange/serverActor.mo +++ b/stdlib/examples/produce-exchange/src/serverActor.mo @@ -4,16 +4,16 @@ -------------------- */ -import Debug "../../debug.mo"; -import P = "../../prelude.mo"; -import Option = "../../option.mo"; +import Debug "mo:stdlib/debug.mo"; +import P = "mo:stdlib/prelude.mo"; +import Option = "mo:stdlib/option.mo"; import T = "serverTypes.mo"; import L = "serverLang.mo"; import Model = "serverModel.mo"; -import Result = "../../result.mo"; +import Result = "mo:stdlib/result.mo"; -import Trie = "../../trie.mo"; -import List = "../../list.mo"; +import Trie = "mo:stdlib/trie.mo"; +import List = "mo:stdlib/list.mo"; type List = List.List; diff --git a/stdlib/examples/produce-exchange/serverLang.mo b/stdlib/examples/produce-exchange/src/serverLang.mo similarity index 98% rename from stdlib/examples/produce-exchange/serverLang.mo rename to stdlib/examples/produce-exchange/src/serverLang.mo index 5ce8f33d1b3..ab29e2f7bc3 100644 --- a/stdlib/examples/produce-exchange/serverLang.mo +++ b/stdlib/examples/produce-exchange/src/serverLang.mo @@ -1,4 +1,4 @@ -import Result = "../../result.mo"; +import Result = "mo:stdlib/result.mo"; import T = "serverTypes.mo"; diff --git a/stdlib/examples/produce-exchange/serverModel.mo b/stdlib/examples/produce-exchange/src/serverModel.mo similarity index 99% rename from stdlib/examples/produce-exchange/serverModel.mo rename to stdlib/examples/produce-exchange/src/serverModel.mo index 7da988945d6..da341de6ef0 100644 --- a/stdlib/examples/produce-exchange/serverModel.mo +++ b/stdlib/examples/produce-exchange/src/serverModel.mo @@ -1,19 +1,19 @@ -import Debug = "../../debug.mo"; -import P = "../../prelude.mo"; +import Debug = "mo:stdlib/debug.mo"; +import P = "mo:stdlib/prelude.mo"; import T = "serverTypes.mo"; import L = "serverLang.mo"; import M = "serverModelTypes.mo"; -import List = "../../list.mo"; -import Hash_ = "../../hash.mo"; -import Option = "../../option.mo"; -import Trie = "../../trie.mo"; -import Iter = "../../iter.mo"; -import Array = "../../array.mo"; +import List = "mo:stdlib/list.mo"; +import Hash_ = "mo:stdlib/hash.mo"; +import Option = "mo:stdlib/option.mo"; +import Trie = "mo:stdlib/trie.mo"; +import Iter = "mo:stdlib/iter.mo"; +import Array = "mo:stdlib/array.mo"; -import DT = "../../docTable.mo"; -import Result = "../../result.mo"; +import DT = "mo:stdlib/docTable.mo"; +import Result = "mo:stdlib/result.mo"; module { diff --git a/stdlib/examples/produce-exchange/serverModelTypes.mo b/stdlib/examples/produce-exchange/src/serverModelTypes.mo similarity index 98% rename from stdlib/examples/produce-exchange/serverModelTypes.mo rename to stdlib/examples/produce-exchange/src/serverModelTypes.mo index 6352769d368..c60759ce8d1 100644 --- a/stdlib/examples/produce-exchange/serverModelTypes.mo +++ b/stdlib/examples/produce-exchange/src/serverModelTypes.mo @@ -1,6 +1,6 @@ import T = "serverTypes.mo"; -import Trie = "../../trie.mo"; -import DocTable = "../../docTable.mo"; +import Trie = "mo:stdlib/trie.mo"; +import DocTable = "mo:stdlib/docTable.mo"; module { diff --git a/stdlib/examples/produce-exchange/serverTypes.mo b/stdlib/examples/produce-exchange/src/serverTypes.mo similarity index 100% rename from stdlib/examples/produce-exchange/serverTypes.mo rename to stdlib/examples/produce-exchange/src/serverTypes.mo diff --git a/stdlib/examples/produce-exchange/test/evalBulk.mo b/stdlib/examples/produce-exchange/test/evalBulk.mo index 8a8986dd4d0..ca8fabb16f3 100644 --- a/stdlib/examples/produce-exchange/test/evalBulk.mo +++ b/stdlib/examples/produce-exchange/test/evalBulk.mo @@ -1,8 +1,8 @@ -import Debug = "../../../debug.mo"; -import T = "../serverTypes.mo"; -import A = "../serverActor.mo"; -import Result = "../../../result.mo"; -import Option = "../../../option.mo"; +import Debug = "mo:stdlib/debug.mo"; +import T = "../src/serverTypes.mo"; +import A = "../src/serverActor.mo"; +import Result = "mo:stdlib/result.mo"; +import Option = "mo:stdlib/option.mo"; func printEntityCount(entname:Text, count:Nat) { Debug.print ("- " # entname # " count: " # debug_show count # "\n"); diff --git a/stdlib/examples/produce-exchange/test/loadWorkloadAndQueryBig.mo b/stdlib/examples/produce-exchange/test/loadWorkloadAndQueryBig.mo index ac60d00a63c..11aa7f6f586 100644 --- a/stdlib/examples/produce-exchange/test/loadWorkloadAndQueryBig.mo +++ b/stdlib/examples/produce-exchange/test/loadWorkloadAndQueryBig.mo @@ -1,7 +1,7 @@ -//let T = (import "../serverTypes.mo"); -//let A = (import "../serverActor.mo"); -//let Result = (import "../../../result.mo"); -//let Option = (import "../../../option.mo"); +//let T = (import "../src/serverTypes.mo"); +//let A = (import "../src/serverActor.mo"); +//let Result = (import "mo:stdlib/result.mo"); +//let Option = (import "mo:stdlib/option.mo"); func scaledParams(region_count_:Nat, factor:Nat) : T.WorkloadParams = shared { region_count = region_count_:Nat; diff --git a/stdlib/examples/produce-exchange/test/producerRemInventory.mo b/stdlib/examples/produce-exchange/test/producerRemInventory.mo index d637b0b3951..51c65de62d9 100644 --- a/stdlib/examples/produce-exchange/test/producerRemInventory.mo +++ b/stdlib/examples/produce-exchange/test/producerRemInventory.mo @@ -1,8 +1,8 @@ -import Debug "../../../debug.mo"; -import T = "../serverTypes.mo"; -import A = "../serverActor.mo"; -import Result = "../../../result.mo"; -import Option = "../../../option.mo"; +import Debug "mo:stdlib/debug.mo"; +import T = "../src/serverTypes.mo"; +import A = "../src/serverActor.mo"; +import Result = "mo:stdlib/result.mo"; +import Option = "mo:stdlib/option.mo"; func printEntityCount(entname:Text, count:Nat) { Debug.print ("- " # entname # " count: " # debug_show count # "\n"); diff --git a/stdlib/examples/produce-exchange/profileActor.mo b/stdlib/examples/produce-exchange/test/profileActor.mo similarity index 90% rename from stdlib/examples/produce-exchange/profileActor.mo rename to stdlib/examples/produce-exchange/test/profileActor.mo index 79d5f62486b..8be8fd8b9d3 100644 --- a/stdlib/examples/produce-exchange/profileActor.mo +++ b/stdlib/examples/produce-exchange/test/profileActor.mo @@ -1,5 +1,5 @@ -import T = "serverTypes.mo"; -import Model = "serverModel.mo"; +import T = "../src/serverTypes.mo"; +import Model = "../src/serverModel.mo"; actor server { // morally: loadQuery (region_count:Nat, scale_factor:Nat) { diff --git a/stdlib/examples/produce-exchange/test/profileFastCounts.mo b/stdlib/examples/produce-exchange/test/profileFastCounts.mo index 78498b0ac48..64f45f39327 100644 --- a/stdlib/examples/produce-exchange/test/profileFastCounts.mo +++ b/stdlib/examples/produce-exchange/test/profileFastCounts.mo @@ -2,9 +2,9 @@ // we correlate these numbers with times that we // measure elsewhere, where these numbers are not available. -import Debug "../../../debug.mo"; -import T = "../serverTypes.mo"; -import Model = "../serverModel.mo"; +import Debug "mo:stdlib/debug.mo"; +import T = "../src/serverTypes.mo"; +import Model = "../src/serverModel.mo"; let m = Model.Model(); diff --git a/stdlib/examples/produce-exchange/test/retailerReserveMany.mo b/stdlib/examples/produce-exchange/test/retailerReserveMany.mo index eff0bdf02d6..4c7f6c7e8fb 100644 --- a/stdlib/examples/produce-exchange/test/retailerReserveMany.mo +++ b/stdlib/examples/produce-exchange/test/retailerReserveMany.mo @@ -1,8 +1,8 @@ -import Debug "../../../debug.mo"; -import T = "../serverTypes.mo"; -import A = "../serverActor.mo"; -import Result = "../../../result.mo"; -import Option = "../../../option.mo"; +import Debug "mo:stdlib/debug.mo"; +import T = "../src/serverTypes.mo"; +import A = "../src/serverActor.mo"; +import Result = "mo:stdlib/result.mo"; +import Option = "mo:stdlib/option.mo"; func printEntityCount(entname:Text, count:Nat) { Debug.print ("- " # entname # " count: " # debug_show count # "\n"); diff --git a/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.mo b/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.mo index c434db2fef2..bb027e47cb5 100644 --- a/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.mo +++ b/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.mo @@ -1,8 +1,8 @@ -import Debug "../../../debug.mo"; -import T = "../serverTypes.mo"; -import A = "../serverActor.mo"; -import Result = "../../../result.mo"; -import Option = "../../../option.mo"; +import Debug "mo:stdlib/debug.mo"; +import T = "../src/serverTypes.mo"; +import A = "../src/serverActor.mo"; +import Result = "mo:stdlib/result.mo"; +import Option = "mo:stdlib/option.mo"; func printEntityCount(entname:Text, count:Nat) { Debug.print ("- " # entname # " count: " # debug_show count # "\n"); diff --git a/stdlib/tools/stopwatch.c b/stdlib/examples/produce-exchange/tools/stopwatch.c similarity index 100% rename from stdlib/tools/stopwatch.c rename to stdlib/examples/produce-exchange/tools/stopwatch.c diff --git a/stdlib/examples/rx/Makefile b/stdlib/examples/rx/Makefile new file mode 100644 index 00000000000..d6cf1654779 --- /dev/null +++ b/stdlib/examples/rx/Makefile @@ -0,0 +1,20 @@ +STDLIB ?= ../../src +MOC ?= ../../../src/moc +WASMTIME_OPTIONS = --disable-cache --cranelift + +OUTDIR=_out + +all: $(OUTDIR)/test.out + +$(OUTDIR): + @mkdir $@ + +$(OUTDIR)/Test.wasm: test/RxTest.mo src/*.mo | $(OUTDIR) + $(MOC) -c --package stdlib $(STDLIB) -wasi-system-api -o $@ $< + +$(OUTDIR)/test.out: $(OUTDIR)/Test.wasm + wasmtime $(WASMTIME_OPTIONS) $< + + +clean: + rm -rf $(OUTDIR) diff --git a/stdlib/examples/rx/test/RxTest.mo b/stdlib/examples/rx/test/RxTest.mo index 69eaf73d630..80c72d0e075 100644 --- a/stdlib/examples/rx/test/RxTest.mo +++ b/stdlib/examples/rx/test/RxTest.mo @@ -1,4 +1,4 @@ -import Array "../../../array.mo"; +import Array "mo:stdlib/array.mo"; import Rx "../src/Rx.mo"; type Error = { diff --git a/stdlib/array.mo b/stdlib/src/array.mo similarity index 100% rename from stdlib/array.mo rename to stdlib/src/array.mo diff --git a/stdlib/assocList.mo b/stdlib/src/assocList.mo similarity index 100% rename from stdlib/assocList.mo rename to stdlib/src/assocList.mo diff --git a/stdlib/blob.mo b/stdlib/src/blob.mo similarity index 100% rename from stdlib/blob.mo rename to stdlib/src/blob.mo diff --git a/stdlib/buf.mo b/stdlib/src/buf.mo similarity index 100% rename from stdlib/buf.mo rename to stdlib/src/buf.mo diff --git a/stdlib/src/char.mo b/stdlib/src/char.mo new file mode 100644 index 00000000000..b7ddbcf75c4 --- /dev/null +++ b/stdlib/src/char.mo @@ -0,0 +1,8 @@ +import Prim "mo:prim"; +module { + + public func isDigit(char : Char) : Bool { + Prim.charToWord32(char) - Prim.charToWord32('0') <= (9 : Word32) + }; + +} diff --git a/stdlib/debug.mo b/stdlib/src/debug.mo similarity index 100% rename from stdlib/debug.mo rename to stdlib/src/debug.mo diff --git a/stdlib/docTable.mo b/stdlib/src/docTable.mo similarity index 100% rename from stdlib/docTable.mo rename to stdlib/src/docTable.mo diff --git a/stdlib/function.mo b/stdlib/src/function.mo similarity index 100% rename from stdlib/function.mo rename to stdlib/src/function.mo diff --git a/stdlib/hash.mo b/stdlib/src/hash.mo similarity index 100% rename from stdlib/hash.mo rename to stdlib/src/hash.mo diff --git a/stdlib/hashMap.mo b/stdlib/src/hashMap.mo similarity index 100% rename from stdlib/hashMap.mo rename to stdlib/src/hashMap.mo diff --git a/stdlib/int.mo b/stdlib/src/int.mo similarity index 100% rename from stdlib/int.mo rename to stdlib/src/int.mo diff --git a/stdlib/iter.mo b/stdlib/src/iter.mo similarity index 100% rename from stdlib/iter.mo rename to stdlib/src/iter.mo diff --git a/stdlib/list.mo b/stdlib/src/list.mo similarity index 100% rename from stdlib/list.mo rename to stdlib/src/list.mo diff --git a/stdlib/nat.mo b/stdlib/src/nat.mo similarity index 100% rename from stdlib/nat.mo rename to stdlib/src/nat.mo diff --git a/stdlib/none.mo b/stdlib/src/none.mo similarity index 100% rename from stdlib/none.mo rename to stdlib/src/none.mo diff --git a/stdlib/option.mo b/stdlib/src/option.mo similarity index 100% rename from stdlib/option.mo rename to stdlib/src/option.mo diff --git a/stdlib/prelude.mo b/stdlib/src/prelude.mo similarity index 100% rename from stdlib/prelude.mo rename to stdlib/src/prelude.mo diff --git a/stdlib/principalId.mo b/stdlib/src/principalId.mo similarity index 100% rename from stdlib/principalId.mo rename to stdlib/src/principalId.mo diff --git a/stdlib/result.mo b/stdlib/src/result.mo similarity index 100% rename from stdlib/result.mo rename to stdlib/src/result.mo diff --git a/stdlib/text.mo b/stdlib/src/text.mo similarity index 100% rename from stdlib/text.mo rename to stdlib/src/text.mo diff --git a/stdlib/trie.mo b/stdlib/src/trie.mo similarity index 100% rename from stdlib/trie.mo rename to stdlib/src/trie.mo diff --git a/stdlib/trieMap.mo b/stdlib/src/trieMap.mo similarity index 100% rename from stdlib/trieMap.mo rename to stdlib/src/trieMap.mo diff --git a/stdlib/trieSet.mo b/stdlib/src/trieSet.mo similarity index 100% rename from stdlib/trieSet.mo rename to stdlib/src/trieSet.mo diff --git a/stdlib/test/Makefile b/stdlib/test/Makefile new file mode 100644 index 00000000000..df698fc5de5 --- /dev/null +++ b/stdlib/test/Makefile @@ -0,0 +1,37 @@ +STDLIB ?= ../src +MOC ?= ../../src/moc +WASMTIME_OPTIONS = --disable-cache --cranelift + +OUTDIR=_out + +TESTS = $(wildcard *.mo) + +TEST_TARGETS = $(patsubst %.mo,_out/%.checked,$(TESTS)) + +all: $(TEST_TARGETS) $(OUTDIR)/import_all.checked + +STDLIB_FILES= $(wildcard $(STDLIB)/*.mo) + +$(OUTDIR): + @mkdir $@ + +$(OUTDIR)/import_all.mo: $(STDLIB_FILES) | $(OUTDIR) + > $@ + for f in $(patsubst $(STDLIB)/%.mo,%,$(STDLIB_FILES)); do \ + echo "import Import_$$f \"mo:stdlib/$$f.mo\";" >> $@; \ + done + +$(OUTDIR)/%.wasm: %.mo | $(OUTDIR) + $(MOC) -c --package stdlib $(STDLIB) -wasi-system-api -o $@ $< + +$(OUTDIR)/%.wasm: $(OUTDIR)/%.mo | $(OUTDIR) + $(MOC) -c --package stdlib $(STDLIB) -wasi-system-api -o $@ $< + +$(OUTDIR)/%.checked: $(OUTDIR)/%.wasm + wasmtime $(WASMTIME_OPTIONS) $< + touch $@ + +clean: + rm -rf $(OUTDIR) + +.PRECIOUS: $(OUTDIR)/%.wasm diff --git a/stdlib/arrayTest.mo b/stdlib/test/arrayTest.mo similarity index 97% rename from stdlib/arrayTest.mo rename to stdlib/test/arrayTest.mo index a8775d562fd..fdbe7c6e5ca 100644 --- a/stdlib/arrayTest.mo +++ b/stdlib/test/arrayTest.mo @@ -1,6 +1,6 @@ -import Array "array.mo"; -import Prelude "prelude.mo"; -import Text "text.mo"; +import Array "mo:stdlib/array.mo"; +import Prelude "mo:stdlib/prelude.mo"; +import Text "mo:stdlib/text.mo"; Prelude.printLn("Array"); diff --git a/stdlib/bufTest.mo b/stdlib/test/bufTest.mo similarity index 85% rename from stdlib/bufTest.mo rename to stdlib/test/bufTest.mo index 119b36a3ce3..d61f737c4fa 100644 --- a/stdlib/bufTest.mo +++ b/stdlib/test/bufTest.mo @@ -1,6 +1,6 @@ import Prim "mo:prim"; -import B "buf.mo"; -import I "iter.mo"; +import B "mo:stdlib/buf.mo"; +import I "mo:stdlib/iter.mo"; // test repeated growing let a = B.Buf(3); diff --git a/stdlib/functionTest.mo b/stdlib/test/functionTest.mo similarity index 89% rename from stdlib/functionTest.mo rename to stdlib/test/functionTest.mo index 37c82fa5918..bb06fedb534 100644 --- a/stdlib/functionTest.mo +++ b/stdlib/test/functionTest.mo @@ -1,6 +1,6 @@ -import Function "function.mo"; -import Prelude "prelude.mo"; -import Text "text.mo"; +import Function "mo:stdlib/function.mo"; +import Prelude "mo:stdlib/prelude.mo"; +import Text "mo:stdlib/text.mo"; Prelude.printLn("Function"); diff --git a/stdlib/hashMapTest.mo b/stdlib/test/hashMapTest.mo similarity index 97% rename from stdlib/hashMapTest.mo rename to stdlib/test/hashMapTest.mo index 56c0dc571aa..bbd69e3869f 100644 --- a/stdlib/hashMapTest.mo +++ b/stdlib/test/hashMapTest.mo @@ -1,6 +1,6 @@ import Prim "mo:prim"; -import H "hashMap.mo"; -import Hash "hash.mo"; +import H "mo:stdlib/hashMap.mo"; +import Hash "mo:stdlib/hash.mo"; func textIsEq(x:Text,y:Text):Bool { x == y }; diff --git a/stdlib/intTest.mo b/stdlib/test/intTest.mo similarity index 86% rename from stdlib/intTest.mo rename to stdlib/test/intTest.mo index 495116948b9..5b70c20b46e 100644 --- a/stdlib/intTest.mo +++ b/stdlib/test/intTest.mo @@ -1,5 +1,5 @@ -import Prelude "prelude.mo"; -import Int "int.mo"; +import Prelude "mo:stdlib/prelude.mo"; +import Int "mo:stdlib/int.mo"; Prelude.printLn("Int"); diff --git a/stdlib/iterTest.mo b/stdlib/test/iterTest.mo similarity index 96% rename from stdlib/iterTest.mo rename to stdlib/test/iterTest.mo index 14f6f20c731..b554a35c70b 100644 --- a/stdlib/iterTest.mo +++ b/stdlib/test/iterTest.mo @@ -1,6 +1,6 @@ -import Iter "iter.mo"; -import List "list.mo"; -import Prelude "prelude.mo"; +import Iter "mo:stdlib/iter.mo"; +import List "mo:stdlib/list.mo"; +import Prelude "mo:stdlib/prelude.mo"; Prelude.printLn("Iter"); diff --git a/stdlib/listTest.mo b/stdlib/test/listTest.mo similarity index 97% rename from stdlib/listTest.mo rename to stdlib/test/listTest.mo index e6e1e21aa11..74bfa8b3b01 100644 --- a/stdlib/listTest.mo +++ b/stdlib/test/listTest.mo @@ -1,5 +1,5 @@ -import List "list.mo"; -import Prelude "prelude.mo"; +import List "mo:stdlib/list.mo"; +import Prelude "mo:stdlib/prelude.mo"; type X = Nat; diff --git a/stdlib/natTest.mo b/stdlib/test/natTest.mo similarity index 84% rename from stdlib/natTest.mo rename to stdlib/test/natTest.mo index c6a2b7c3b49..c4f2ed0d37b 100644 --- a/stdlib/natTest.mo +++ b/stdlib/test/natTest.mo @@ -1,5 +1,5 @@ -import Prelude "prelude.mo"; -import Nat "nat.mo"; +import Prelude "mo:stdlib/prelude.mo"; +import Nat "mo:stdlib/nat.mo"; Prelude.printLn("Nat"); diff --git a/stdlib/noneTest.mo b/stdlib/test/noneTest.mo similarity index 54% rename from stdlib/noneTest.mo rename to stdlib/test/noneTest.mo index 389d878a5b4..fbbd085e0a8 100644 --- a/stdlib/noneTest.mo +++ b/stdlib/test/noneTest.mo @@ -1,6 +1,6 @@ -import Array "array.mo"; -import None "none.mo"; -import Prelude "prelude.mo"; +import Array "mo:stdlib/array.mo"; +import None "mo:stdlib/none.mo"; +import Prelude "mo:stdlib/prelude.mo"; Prelude.printLn("None"); diff --git a/stdlib/optionTest.mo b/stdlib/test/optionTest.mo similarity index 98% rename from stdlib/optionTest.mo rename to stdlib/test/optionTest.mo index 70f09ced846..342a9788bdb 100644 --- a/stdlib/optionTest.mo +++ b/stdlib/test/optionTest.mo @@ -1,5 +1,5 @@ -import Option "option.mo"; -import Prelude "prelude.mo"; +import Option "mo:stdlib/option.mo"; +import Prelude "mo:stdlib/prelude.mo"; Prelude.printLn("Option"); diff --git a/stdlib/textTest.mo b/stdlib/test/textTest.mo similarity index 68% rename from stdlib/textTest.mo rename to stdlib/test/textTest.mo index af3cdbd46de..f1c253f8ceb 100644 --- a/stdlib/textTest.mo +++ b/stdlib/test/textTest.mo @@ -1,5 +1,5 @@ -import Prelude "prelude.mo"; -import Text "text.mo"; +import Prelude "mo:stdlib/prelude.mo"; +import Text "mo:stdlib/text.mo"; Prelude.printLn("Text"); diff --git a/stdlib/trieMapTest.mo b/stdlib/test/trieMapTest.mo similarity index 97% rename from stdlib/trieMapTest.mo rename to stdlib/test/trieMapTest.mo index fd4a1fbb52d..3359afb38c8 100644 --- a/stdlib/trieMapTest.mo +++ b/stdlib/test/trieMapTest.mo @@ -1,6 +1,6 @@ import Prim "mo:prim"; -import H "trieMap.mo"; -import Hash "hash.mo"; +import H "mo:stdlib/trieMap.mo"; +import Hash "mo:stdlib/hash.mo"; func textIsEq(x:Text,y:Text):Bool { x == y }; From 315000f034a3e75e1a931c2195a152ad9abefbc1 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 20 Jan 2020 11:19:24 +0100 Subject: [PATCH 0967/1176] Update darwin packer (#1133) * Update darwin packer To version from https://github.com/dfinity-lab/common/commit/8c07b4a592e7c54ff43adf0420575d4069bfe8a9 This is copied from https://github.com/dfinity-lab/common/blob/master/nix/overlays/standalone/darwin.nix It is copied verbatin, so easy to update, but does not couple the repositories (important for eventual open sourcing) * Fix calling nix/standalone-darwin.nix * Try to import common --- default.nix | 6 +-- nix/sources.json | 6 +++ nix/standalone-darwin.nix | 102 -------------------------------------- 3 files changed, 8 insertions(+), 106 deletions(-) delete mode 100644 nix/standalone-darwin.nix diff --git a/default.nix b/default.nix index a719cf42e67..0f9d323ed14 100644 --- a/default.nix +++ b/default.nix @@ -70,10 +70,8 @@ let commonBuildInputs = pkgs: ]; in let darwin_standalone = - import nix/standalone-darwin.nix { - inherit (nixpkgs) runCommandNoCC stdenv removeReferencesTo lib; - grep = nixpkgs.gnugrep; - }; in + let common = import nixpkgs.sources.common { inherit (nixpkgs) system; }; in + common.lib.standaloneRust; in let ocaml_exe = name: bin: let diff --git a/nix/sources.json b/nix/sources.json index f4a891c1259..d3b9d607c37 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -5,6 +5,12 @@ "rev": "791d90bb7ca57d7afab4fd045025877acb892c00", "type": "git" }, + "common": { + "ref": "master", + "repo": "ssh://git@github.com/dfinity-lab/common", + "rev": "8c07b4a592e7c54ff43adf0420575d4069bfe8a9", + "type": "git" + }, "esm": { "builtin": false, "sha256": "116k10q9v0yzpng9bgdx3xrjm2kppma2db62mnbilbi66dvrvz9q", diff --git a/nix/standalone-darwin.nix b/nix/standalone-darwin.nix deleted file mode 100644 index bda5bcc0be2..00000000000 --- a/nix/standalone-darwin.nix +++ /dev/null @@ -1,102 +0,0 @@ -{ runCommandNoCC -, stdenv -, grep -, removeReferencesTo -, lib -}: - -{ drv -, exename -, extraBins ? [] -}: - -# on darwin we don't support shipping extra binaries -assert extraBins == []; - -# these are (1) the references we're okay with getting rid of and the dynamic -# libs that we're fine with pulling from /usr/lib. These should be passed as -# arguments, but they're very generic and for now it's simpler to have them -# here. -let - allowStrippedRefs = [ "*-crates-io" "*-swift-corefoundation" ]; - allowBundledDeps = [ "libSystem*.dylib" "libresolv*.dylib" "libc++*.dylib" ]; -in - -# For simplicity we assume those aren't empty. Empty lists would be the case -# analysis. -assert allowStrippedRefs != []; -assert allowBundledDeps != []; - - # Create a standalone executable from the given rust executable. - # * drv: the base derivation - # * name: the executable name, e.g. /bin/ - # The output is placed in $out/bin/. - # This works in two steps: - # 1. Strip out dynamic libraries - # 2. Strip out other nix store references -runCommandNoCC "${exename}-mkstandalone" - { buildInputs = [ grep stdenv.cc removeReferencesTo ]; - inherit exename; - allowedRequisites = []; - } - '' - dir=$(mktemp -d) - exe=$dir/$exename - - cp ${drv}/bin/$exename $exe - - # Make sure we can patch the exe - chmod +w $exe - - # For all dynamic dependencies... - otool -L $exe \ - | grep --only-match '${builtins.storeDir}/\S*' > libs - while read lib; do - libname=$(basename $lib) - - case $libname in - # ... strip out the widespread ones by making the RPATH entries - # point to /usr/lib. - # XXX: We should be able to statically link libc++ although we've - # wasted ~ 2 eng/days already, so this is good enough for now. - # See: https://github.com/rust-lang/rust/issues/64612 - ${lib.concatStringsSep "|" allowBundledDeps}) - newlibname=/usr/lib/''${libname%%\.*}.''${libname##*\.} - echo "Found $libname:" - echo " $lib -> $newlibname" - install_name_tool -change "$lib" "$newlibname" $exe - ;; - *) - echo "Found unknown library: $libname ($lib)" - echo "Please handle this case." - exit 1 - ;; - esac - done deps - - while read dep; do - depname=$(basename $dep) - - case "$depname" in - ${lib.concatStringsSep "|" allowStrippedRefs}) - remove-references-to -t /nix/store/$depname $exe - ;; - *) - echo "Unknown dependency: $dep" - exit 1 - ;; - esac - done Date: Mon, 20 Jan 2020 12:02:35 +0000 Subject: [PATCH 0968/1176] remove tests deleted from master --- test/run-drun/indirect-counter.mo | 23 ------------------ .../run-drun/ok/actor-creation.ic-stub-run.ok | 14 ----------- test/run-drun/ok/chat.ic-stub-run.ok | 24 ------------------- .../ok/indirect-counter.ic-stub-run.ok | 12 ---------- 4 files changed, 73 deletions(-) delete mode 100644 test/run-drun/indirect-counter.mo delete mode 100644 test/run-drun/ok/actor-creation.ic-stub-run.ok delete mode 100644 test/run-drun/ok/chat.ic-stub-run.ok delete mode 100644 test/run-drun/ok/indirect-counter.ic-stub-run.ok diff --git a/test/run-drun/indirect-counter.mo b/test/run-drun/indirect-counter.mo deleted file mode 100644 index 28fb5523212..00000000000 --- a/test/run-drun/indirect-counter.mo +++ /dev/null @@ -1,23 +0,0 @@ -import Prim "mo:prim"; - -let a = actor { - let aa = actor { - var c = 1; - public func inc() { - c += 1; -// Prim.debugPrintNat(c) - }; - public func debugPrint() { -// Prim.debugPrintNat(c) - }; - }; - public func inc() { aa.inc() }; - public func debugPrint() { aa.debugPrint() }; -}; - -a.inc(); //OR-CALL ingress inc "DIDL\x00\x00" -a.inc(); //OR-CALL ingress inc "DIDL\x00\x00" -a.inc(); //OR-CALL ingress inc "DIDL\x00\x00" -a.debugPrint() //OR-CALL ingress debugPrint "DIDL\x00\x00" - -//SKIP comp diff --git a/test/run-drun/ok/actor-creation.ic-stub-run.ok b/test/run-drun/ok/actor-creation.ic-stub-run.ok deleted file mode 100644 index dd52e6cd83c..00000000000 --- a/test/run-drun/ok/actor-creation.ic-stub-run.ok +++ /dev/null @@ -1,14 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -debug.print: main actor creating a -debug.print: a created -← completed -→ update foo(0x4449444c0000) -debug.print: a.foo() called -debug.print: a creating b -debug.print: a calling b.foo() -debug.print: a.foo() done -debug.print: b created -debug.print: b.foo() called -← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/chat.ic-stub-run.ok b/test/run-drun/ok/chat.ic-stub-run.ok deleted file mode 100644 index 2434b62be24..00000000000 --- a/test/run-drun/ok/chat.ic-stub-run.ok +++ /dev/null @@ -1,24 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -← completed -→ update go(0x4449444c0000) -debug.print: charlie received hello from bob -debug.print: alice received hello from bob -debug.print: bob received hello from bob -debug.print: charlie received goodbye from bob -debug.print: alice received goodbye from bob -debug.print: bob received goodbye from bob -debug.print: charlie received hello from alice -debug.print: alice received hello from alice -debug.print: bob received hello from alice -debug.print: charlie received goodbye from alice -debug.print: alice received goodbye from alice -debug.print: bob received goodbye from alice -debug.print: charlie received hello from charlie -debug.print: alice received hello from charlie -debug.print: bob received hello from charlie -debug.print: charlie received goodbye from charlie -debug.print: alice received goodbye from charlie -debug.print: bob received goodbye from charlie -← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/indirect-counter.ic-stub-run.ok b/test/run-drun/ok/indirect-counter.ic-stub-run.ok deleted file mode 100644 index 89e7adaf1a2..00000000000 --- a/test/run-drun/ok/indirect-counter.ic-stub-run.ok +++ /dev/null @@ -1,12 +0,0 @@ -→ create -← completed: canister-id = 0x0000000000000400 -→ install -← completed -→ update inc(0x4449444c0000) -← completed: 0x4449444c0000 -→ update inc(0x4449444c0000) -← completed: 0x4449444c0000 -→ update inc(0x4449444c0000) -← completed: 0x4449444c0000 -→ update debugPrint(0x4449444c0000) -← completed: 0x4449444c0000 From d1594d25e3e948387769ef3a58843858e8804cac Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Mon, 20 Jan 2020 12:16:58 +0000 Subject: [PATCH 0969/1176] remove debug residue (oops) --- src/mo_frontend/typing.ml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 9ecc890b27e..189ffbe34d4 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -270,12 +270,11 @@ let check_shared_return env at sort c ts = let rec infer_async_cap env sort cs tbs = let env = { env with async = C.NullCap } in match sort, cs, tbs with - (* TODO: refine T.Query *) - | (T.Shared _ | T.Local) , c::_, {T.sort = _ (*T.Scope*); _}::_ -> - { env with typs = T.Env.add scope_id c env.typs; - async = C.AsyncCap c } - | T.Shared _, _, _ -> assert false (* impossible given sugaring *) - | _ -> env + | (T.Shared _ | T.Local) , c::_, { T.sort = T.Scope; _ }::_ -> + { env with typs = T.Env.add scope_id c env.typs; + async = C.AsyncCap c } + | T.Shared _, _, _ -> assert false (* impossible given sugaring *) + | _ -> env and check_AsyncCap env s at = match env.async with From 0dc55192a720dd5e0938780e6415268a91a08601 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Mon, 20 Jan 2020 15:05:42 +0100 Subject: [PATCH 0970/1176] Bump libtommath to release v1.2.0 (#1138) * Bump libtommath to release v1.2.0 * by using niv like this: niv update libtommath -v v1.2.0 -t "https://github.com///archive/.tar.gz" niv drop libtommath rev niv drop libtommath branch --- nix/sources.json | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/nix/sources.json b/nix/sources.json index d3b9d607c37..e7b1459af10 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -20,17 +20,16 @@ "version": "3.2.25" }, "libtommath": { - "branch": "develop", "builtin": false, "description": "LibTomMath is a free open source portable number theoretic multiple-precision integer library written entirely in C.", "homepage": "https://www.libtom.net", "owner": "libtom", "repo": "libtommath", - "rev": "584405ff8e357290362671b5e7db6110a959cbaa", - "sha256": "1vl606rm8ba7vjhr0rbdqvih5d4r5iqalqlj5mnz6j3bnsn83b2a", + "sha256": "0cj4xdbh874hi8hx9ajygqk5411cnv260mfjrn68fsi9a6dw56ff", "type": "tarball", - "url": "https://github.com/libtom/libtommath/archive/584405ff8e357290362671b5e7db6110a959cbaa.tar.gz", - "url_template": "https://github.com///archive/.tar.gz" + "url": "https://github.com/libtom/libtommath/archive/v1.2.0.tar.gz", + "url_template": "https://github.com///archive/.tar.gz", + "version": "v1.2.0" }, "nixpkgs": { "branch": "master", From 2e604b42b160cac39b4ecbf3f6a6b8259419fe0f Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Mon, 20 Jan 2020 16:36:26 +0000 Subject: [PATCH 0971/1176] implement query restrictions --- src/mo_frontend/typing.ml | 22 ++++++++++++++-------- src/mo_types/async_cap.ml | 1 + test/fail/ok/queries.tc.ok | 7 +++++++ test/fail/queries.mo | 37 +++++++++++++++++++++++++++++++++++++ 4 files changed, 59 insertions(+), 8 deletions(-) create mode 100644 test/fail/ok/queries.tc.ok create mode 100644 test/fail/queries.mo diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 189ffbe34d4..18403c8612c 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -270,22 +270,27 @@ let check_shared_return env at sort c ts = let rec infer_async_cap env sort cs tbs = let env = { env with async = C.NullCap } in match sort, cs, tbs with - | (T.Shared _ | T.Local) , c::_, { T.sort = T.Scope; _ }::_ -> + | (T.Shared T.Write | T.Local) , c::_, { T.sort = T.Scope; _ }::_ -> { env with typs = T.Env.add scope_id c env.typs; async = C.AsyncCap c } + | (T.Shared T.Query) , c::_, { T.sort = T.Scope; _ }::_ -> + { env with typs = T.Env.add scope_id c env.typs; + async = C.QueryCap c } | T.Shared _, _, _ -> assert false (* impossible given sugaring *) | _ -> env and check_AsyncCap env s at = match env.async with - | C.AwaitCap c -> T.Con(c, []) - | C.AsyncCap c -> T.Con(c, []) + | C.AwaitCap c + | C.AsyncCap c -> T.Con(c, []), fun c' -> C.AwaitCap c' + | C.QueryCap c -> T.Con(c, []), fun _c' -> C.NullCap | C.NullCap -> error env at "misplaced %s" s and check_AwaitCap env s at = match env.async with | C.AwaitCap c -> T.Con(c, []) - | C.AsyncCap c -> + | C.AsyncCap _ + | C.QueryCap _ -> error env at "misplaced %s; try enclosing in an async expression" s | C.NullCap -> error env at "misplaced %s" s @@ -467,6 +472,7 @@ and infer_inst env tbs typs at = assert (List.for_all (fun tb -> tb.T.sort = T.Type) tbs'); (match env.async with | C.NullCap -> error env at "scope required, but non available" + | C.QueryCap c | C.AwaitCap c | C.AsyncCap c -> (T.Con(c,[])::ts, at::ats) @@ -996,11 +1002,11 @@ and infer_exp'' env exp : T.typ = | AsyncE (typ_bind, exp1) -> if not (in_shared_async env || in_oneway_ignore env) then error_in [Flags.ICMode] env exp.at "unsupported async block"; - let t1 = check_AsyncCap env "async expression" exp.at in + let t1, next_cap = check_AsyncCap env "async expression" exp.at in let c, tb, ce, cs = check_typ_bind env typ_bind in let ce_scope = T.Env.add "@" c ce in (* pun scope identifier @ with c *) let env' = - {(adjoin_typs env ce_scope cs) with labs = T.Env.empty; rets = Some T.Pre; async = C.AwaitCap c} in + {(adjoin_typs env ce_scope cs) with labs = T.Env.empty; rets = Some T.Pre; async = next_cap c} in let t = infer_exp env' exp1 in let t' = T.open_ [t1] (T.close [c] t) in if not (T.shared t') then @@ -1083,7 +1089,7 @@ and check_exp' env0 t exp : T.typ = | AsyncE (tb, exp1), T.Async (t1', t') -> if not (in_shared_async env || in_oneway_ignore env) then error_in [Flags.ICMode] env exp.at "freestanding async expression not yet supported"; - let t1 = check_AsyncCap env "async expression" exp.at in + let t1, next_cap = check_AsyncCap env "async expression" exp.at in if not (T.eq t1 t1') then error env exp.at "async at scope\n %s\ncannot produce expected scope\n %s" (T.string_of_typ_expand t1) @@ -1091,7 +1097,7 @@ and check_exp' env0 t exp : T.typ = let c, tb, ce, cs = check_typ_bind env tb in let ce_scope = T.Env.add "@" c ce in (* pun scope identifier @ with c *) let env' = - {(adjoin_typs env ce_scope cs) with labs = T.Env.empty; rets = Some t'; async = C.AwaitCap c} in + {(adjoin_typs env ce_scope cs) with labs = T.Env.empty; rets = Some t'; async = next_cap c} in check_exp env' t' exp1; t | BlockE decs, _ -> diff --git a/src/mo_types/async_cap.ml b/src/mo_types/async_cap.ml index 6d1f4f404e2..b87b110119d 100644 --- a/src/mo_types/async_cap.ml +++ b/src/mo_types/async_cap.ml @@ -5,6 +5,7 @@ module T = Type type async_cap = | NullCap + | QueryCap of T.con | AsyncCap of T.con | AwaitCap of T.con diff --git a/test/fail/ok/queries.tc.ok b/test/fail/ok/queries.tc.ok new file mode 100644 index 00000000000..ae4ae20fe08 --- /dev/null +++ b/test/fail/ok/queries.tc.ok @@ -0,0 +1,7 @@ +queries.mo:11.5-11.20: type error, misplaced await +queries.mo:15.5-15.13: type error, scope required, but non available +queries.mo:19.13-19.22: type error, scope required, but non available +queries.mo:20.5-20.20: type error, misplaced await +queries.mo:24.5-24.14: type error, misplaced async expression +queries.mo:29.5-29.21: type error, misplaced throw +queries.mo:33.5-33.22: type error, misplaced try diff --git a/test/fail/queries.mo b/test/fail/queries.mo new file mode 100644 index 00000000000..cda7aa705fe --- /dev/null +++ b/test/fail/queries.mo @@ -0,0 +1,37 @@ +actor a { + + public shared func oneway() { }; + + public shared func request() : async () { await okquery()}; + + public shared query func okquery() : async () { + }; + + public shared query func badquery() : async () { + await (loop {}); // can't await + }; + + public shared query func badquery1() : async () { + oneway(); // can't call a (oneway) shared method + }; + + public shared query func badquery2() : async () { + ignore (request()); // can't call a shared method + await request(); // can't wait its result + }; + + public shared query func badquery3() : async () { + async { }; // can't enter an async expression + }; + + // collateral damage (consider relaxing to allow throw and perhaps try/catch from queries) + public shared query func badquery4() : async () { + throw (error ""); // can't throw + }; + + public shared query func badquery5() : async () { + try {} catch _ {}; // can't catch + }; + +}; + From 735d1c7b87a0e2b67a51f52901a27cb6c977ece8 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 20 Jan 2020 18:15:08 +0100 Subject: [PATCH 0972/1176] Bump drun (#1141) mainly to get https://github.com/dfinity-lab/dfinity/pull/2341 i.e. `drun` dealing with `ic`-syntax, but also pulls in ``` 8224bf469 drun: Read canister ids in `ic:` syntax (#2341) bfdc61889 Crypto lib: Split out tests from the clib types file (#2294) 7ad10aeb2 Merge pull request #2321 from dfinity-lab/p2p-132 50bc9c932 Remove the ability to specify QueueIndex when creating Canister queues (#2327) 35b9b52ed Merge pull request #2329 from dfinity-lab/DFN-1266/system-api-deep-dive-3 df97c76dc DFN-746 Idiomatic error handling in ic_orthogonal_persistence. (#2287) 9070e738e DFN-746 Stop using canonical errors in ic-crypto (#2190) 3bb57a80b Merge pull request #2328 from dfinity-lab/nm-int-tests-darwin-sandbox 39f6b9453 Merge pull request #2326 from dfinity-lab/nm-sandbox 8dd94f635 Merge pull request #2311 from dfinity-lab/dimitris/slog-canister-installer 00fb34926 Merge pull request #2319 from dfinity-lab/eftychis-fix-comment ``` Also updates ic-stub (in a preliminary way) and the test suite. --- ic-stub/src/IC/DRun/Parse.hs | 15 +++++++++------ nix/sources.json | 12 ++++++------ test/drun-wrapper.sh | 10 +++------- test/ic-stub-run-wrapper.sh | 4 ++-- test/run-drun/actor-import.mo | 4 ++-- .../{000000000000040054.did => 2A012B.did} | 0 test/run-drun/ok/AST-64.ic-stub-run.ok | 2 +- test/run-drun/ok/AST-66.ic-stub-run.ok | 2 +- test/run-drun/ok/GIT-843.ic-stub-run.ok | 2 +- test/run-drun/ok/actor-import.drun-run.ok | 6 +++--- test/run-drun/ok/actor-import.ic-stub-run.ok | 8 ++++---- .../ok/actor-reference-return.ic-stub-run.ok | 2 +- test/run-drun/ok/actor-reference.ic-stub-run.ok | 2 +- test/run-drun/ok/array-out-of-bounds.drun-run.ok | 4 ++-- .../ok/array-out-of-bounds.ic-stub-run.ok | 2 +- test/run-drun/ok/async-any.ic-stub-run.ok | 2 +- test/run-drun/ok/async-calls1.ic-stub-run.ok | 2 +- test/run-drun/ok/async-calls2.ic-stub-run.ok | 2 +- test/run-drun/ok/async-calls3.ic-stub-run.ok | 2 +- test/run-drun/ok/async-free-var.ic-stub-run.ok | 2 +- test/run-drun/ok/async-loop-while.ic-stub-run.ok | 2 +- test/run-drun/ok/async-loop.ic-stub-run.ok | 2 +- test/run-drun/ok/async-new-obj.ic-stub-run.ok | 2 +- test/run-drun/ok/async-obj-mut.ic-stub-run.ok | 2 +- test/run-drun/ok/async-while.ic-stub-run.ok | 2 +- test/run-drun/ok/await.ic-stub-run.ok | 2 +- test/run-drun/ok/block.ic-stub-run.ok | 2 +- test/run-drun/ok/call-async-method.drun-run.ok | 2 +- test/run-drun/ok/call-async-method.ic-stub-run.ok | 2 +- test/run-drun/ok/caller.ic-stub-run.ok | 2 +- test/run-drun/ok/closure-params.ic-stub-run.ok | 2 +- test/run-drun/ok/count-callbacks.ic-stub-run.ok | 2 +- test/run-drun/ok/counter.ic-stub-run.ok | 2 +- test/run-drun/ok/counter2.ic-stub-run.ok | 2 +- test/run-drun/ok/data-params.ic-stub-run.ok | 2 +- test/run-drun/ok/divide-by-zero.drun-run.ok | 2 +- test/run-drun/ok/divide-by-zero.ic-stub-run.ok | 2 +- test/run-drun/ok/empty-actor.ic-stub-run.ok | 2 +- test/run-drun/ok/empty-call.ic-stub-run.ok | 2 +- .../run-drun/ok/flatten-awaitables.ic-stub-run.ok | 2 +- test/run-drun/ok/for-await.ic-stub-run.ok | 2 +- test/run-drun/ok/free-callbacks.ic-stub-run.ok | 2 +- test/run-drun/ok/generic-tail-rec.ic-stub-run.ok | 2 +- test/run-drun/ok/hello-world-async.ic-stub-run.ok | 2 +- test/run-drun/ok/hello-world-await.ic-stub-run.ok | 2 +- .../ok/hello-world-message.ic-stub-run.ok | 2 +- .../run-drun/ok/hello-world-return.ic-stub-run.ok | 2 +- test/run-drun/ok/hello-world.ic-stub-run.ok | 2 +- test/run-drun/ok/ic-calls.ic-stub-run.ok | 2 +- test/run-drun/ok/idl-any.ic-stub-run.ok | 2 +- test/run-drun/ok/idl-bad.drun-run.ok | 2 +- test/run-drun/ok/idl-bad.ic-stub-run.ok | 2 +- test/run-drun/ok/idl-field-escape.ic-stub-run.ok | 2 +- test/run-drun/ok/idl-func.drun-run.ok | 4 ++-- test/run-drun/ok/idl-func.ic-stub-run.ok | 6 +++--- test/run-drun/ok/idl-mo.ic-stub-run.ok | 2 +- test/run-drun/ok/idl-nary.drun-run.ok | 4 ++-- test/run-drun/ok/idl-nary.ic-stub-run.ok | 2 +- test/run-drun/ok/idl-nat-int.ic-stub-run.ok | 2 +- test/run-drun/ok/idl-option.ic-stub-run.ok | 2 +- test/run-drun/ok/idl-pair.ic-stub-run.ok | 2 +- test/run-drun/ok/idl-record.ic-stub-run.ok | 2 +- test/run-drun/ok/idl-shorthand.ic-stub-run.ok | 2 +- test/run-drun/ok/idl-tuple.ic-stub-run.ok | 2 +- test/run-drun/ok/idl-unit.ic-stub-run.ok | 2 +- test/run-drun/ok/idl-variant.ic-stub-run.ok | 2 +- test/run-drun/ok/idl-vector.ic-stub-run.ok | 2 +- test/run-drun/ok/interleave.ic-stub-run.ok | 2 +- test/run-drun/ok/issue-894.ic-stub-run.ok | 2 +- test/run-drun/ok/local-throw.ic-stub-run.ok | 2 +- test/run-drun/ok/mod-rebind.ic-stub-run.ok | 2 +- test/run-drun/ok/nary-async.ic-stub-run.ok | 2 +- test/run-drun/ok/oneway-throw.ic-stub-run.ok | 2 +- test/run-drun/ok/oneway.ic-stub-run.ok | 2 +- test/run-drun/ok/oom.ic-stub-run.ok | 2 +- test/run-drun/ok/overflow.ic-stub-run.ok | 2 +- test/run-drun/ok/pass-references.ic-stub-run.ok | 2 +- test/run-drun/ok/print-from-init.ic-stub-run.ok | 2 +- test/run-drun/ok/query.ic-stub-run.ok | 2 +- test/run-drun/ok/query2.ic-stub-run.ok | 2 +- test/run-drun/ok/reject.ic-stub-run.ok | 2 +- test/run-drun/ok/rts-stats.ic-stub-run.ok | 2 +- test/run-drun/ok/self-shadow.ic-stub-run.ok | 2 +- test/run-drun/ok/selftail.drun-run.ok | 2 +- test/run-drun/ok/selftail.ic-stub-run.ok | 2 +- test/run-drun/ok/shared-object.ic-stub-run.ok | 2 +- test/run-drun/ok/sharingbug.ic-stub-run.ok | 2 +- test/run-drun/ok/show.ic-stub-run.ok | 2 +- test/run-drun/ok/text-iter.ic-stub-run.ok | 2 +- test/run-drun/ok/throw.ic-stub-run.ok | 2 +- test/run-drun/ok/transpose.ic-stub-run.ok | 2 +- test/run-drun/ok/type-lub.ic-stub-run.ok | 2 +- 92 files changed, 118 insertions(+), 119 deletions(-) rename test/run-drun/actor-import/{000000000000040054.did => 2A012B.did} (100%) diff --git a/ic-stub/src/IC/DRun/Parse.hs b/ic-stub/src/IC/DRun/Parse.hs index 4525ae4c70b..d9d268b6b94 100644 --- a/ic-stub/src/IC/DRun/Parse.hs +++ b/ic-stub/src/IC/DRun/Parse.hs @@ -2,13 +2,11 @@ module IC.DRun.Parse where import qualified Data.ByteString.Lazy as B -import qualified Data.ByteString.Builder as B import qualified Text.Hex as H import qualified Data.Text as T import Data.Char +import Data.List import Control.Exception -import Data.Word -import Text.Read type MethodName = String type Payload = B.ByteString @@ -36,10 +34,15 @@ parseLine l = case words l of ["query", i, m, a] -> Query (parseId i) m (parseArg a) _ -> error $ "Cannot parse: " ++ show l +-- TODO: Implement proper and extract in own module parseId :: String -> Id -parseId x = case readMaybe x of - Just (n::Word64) -> B.toLazyByteString $ B.word64LE n - Nothing -> error "Invalid canister id (decimal number)" +parseId s + | "ic:" `isPrefixOf` s + , Just bs <- B.fromStrict <$> H.decodeHex (T.pack (drop 3 s)) + , B.length bs > 1 + = B.init bs + | otherwise + = error "Invalid canister id" parseArg :: String -> Payload parseArg ('0':'x':xs) diff --git a/nix/sources.json b/nix/sources.json index e7b1459af10..6353e9a435a 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -1,16 +1,16 @@ { - "dfinity": { - "ref": "master", - "repo": "ssh://git@github.com/dfinity-lab/dfinity", - "rev": "791d90bb7ca57d7afab4fd045025877acb892c00", - "type": "git" - }, "common": { "ref": "master", "repo": "ssh://git@github.com/dfinity-lab/common", "rev": "8c07b4a592e7c54ff43adf0420575d4069bfe8a9", "type": "git" }, + "dfinity": { + "ref": "master", + "repo": "ssh://git@github.com/dfinity-lab/dfinity", + "rev": "8224bf469c80ade492083461e7ee3c2cfdf3ec02", + "type": "git" + }, "esm": { "builtin": false, "sha256": "116k10q9v0yzpng9bgdx3xrjm2kppma2db62mnbilbi66dvrvz9q", diff --git a/test/drun-wrapper.sh b/test/drun-wrapper.sh index 7b35f74b047..b76ebf7b711 100755 --- a/test/drun-wrapper.sh +++ b/test/drun-wrapper.sh @@ -8,7 +8,7 @@ CONFIG=$(realpath $(dirname $0)/drun.toml) # # * extract the methods calls from comments in the second argument # (typically the test source files) -# * adds "ic:000000000000040054" as the destination to these calls +# * adds "ic:2A012B" as the destination to these calls # * writes prometheus metrics to file descriptor 222 # (for run.sh -p; post-processing happening in run.sh) # @@ -22,15 +22,11 @@ fi export LANG=C.UTF-8 -# canister id "ic:000000000000040054", in little-endian decimal, is: -# 1125899906842624 -# (drun currently expects a decimal number for the canister id) - # this number is determined empirically: how many extra batches are needed # until all call-trees have finished (even those that return early). # Usually darwin needs more! (Should go away with DFN-1269) EXTRA_BATCHES=100 -(echo "install 1125899906842624 $1 0x"; - if [ -n "$2" ]; then LANG=C perl -ne 'print "$1 1125899906842624 $2\n" if m,^//CALL (ingress|query) (.*),' $2; fi; +(echo "install ic:2A012B $1 0x"; + if [ -n "$2" ]; then LANG=C perl -ne 'print "$1 ic:2A012B $2\n" if m,^//CALL (ingress|query) (.*),' $2; fi; ) | $DRUN -c "$CONFIG" --extra-batches $EXTRA_BATCHES /dev/stdin diff --git a/test/ic-stub-run-wrapper.sh b/test/ic-stub-run-wrapper.sh index 170cbc24c1e..cc86f26c25b 100755 --- a/test/ic-stub-run-wrapper.sh +++ b/test/ic-stub-run-wrapper.sh @@ -17,6 +17,6 @@ export LANG=C.UTF-8 # 1125899906842624 # (drun currently expects a decimal number for the canister id) -(echo "install 1125899906842624 $1 0x"; - if [ -n "$2" ]; then LANG=C perl -ne 'print "$1 1125899906842624 $2\n" if m,^//CALL (ingress|query) (.*),' $2; fi; +(echo "install ic:2A012B $1 0x"; + if [ -n "$2" ]; then LANG=C perl -ne 'print "$1 ic:2A012B $2\n" if m,^//CALL (ingress|query) (.*),' $2; fi; ) | $IC_STUB_RUN -c "$CONFIG" /dev/stdin diff --git a/test/run-drun/actor-import.mo b/test/run-drun/actor-import.mo index ea0fe04aa4d..4085a78fbe2 100644 --- a/test/run-drun/actor-import.mo +++ b/test/run-drun/actor-import.mo @@ -1,12 +1,12 @@ //MOC-FLAG --actor-idl actor-import -//MOC-FLAG --actor-alias self ic:000000000000040054 +//MOC-FLAG --actor-alias self ic:2A012B // this imports our own IDL, stored in actor-import // currently hard-codes the ic-stub self id // once we have actor aliases we can let run.sh set an alias. -import imported1 "ic:000000000000040054"; +import imported1 "ic:2A012B"; import imported2 "canister:self"; actor a { public func go() : async (actor {}) = async imported1; diff --git a/test/run-drun/actor-import/000000000000040054.did b/test/run-drun/actor-import/2A012B.did similarity index 100% rename from test/run-drun/actor-import/000000000000040054.did rename to test/run-drun/actor-import/2A012B.did diff --git a/test/run-drun/ok/AST-64.ic-stub-run.ok b/test/run-drun/ok/AST-64.ic-stub-run.ok index 54225bc8555..c2b23162b29 100644 --- a/test/run-drun/ok/AST-64.ic-stub-run.ok +++ b/test/run-drun/ok/AST-64.ic-stub-run.ok @@ -1,4 +1,4 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed diff --git a/test/run-drun/ok/AST-66.ic-stub-run.ok b/test/run-drun/ok/AST-66.ic-stub-run.ok index be9fb5d62c0..afee61e2f46 100644 --- a/test/run-drun/ok/AST-66.ic-stub-run.ok +++ b/test/run-drun/ok/AST-66.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/GIT-843.ic-stub-run.ok b/test/run-drun/ok/GIT-843.ic-stub-run.ok index 4e7ad8dbdc3..fdc5fc797d6 100644 --- a/test/run-drun/ok/GIT-843.ic-stub-run.ok +++ b/test/run-drun/ok/GIT-843.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update Bad(0x4449444c0000) diff --git a/test/run-drun/ok/actor-import.drun-run.ok b/test/run-drun/ok/actor-import.drun-run.ok index b490e3d8ecc..f16e5e20feb 100644 --- a/test/run-drun/ok/actor-import.drun-run.ok +++ b/test/run-drun/ok/actor-import.drun-run.ok @@ -1,4 +1,4 @@ ingress(0) System -ingress(1) Completed: Canister: Payload: 0x4449444c016900010001080000000000000400 -ingress(2) Completed: Canister: Payload: 0x4449444c016900010001080000000000000400 -ingress(3) Completed: Canister: Payload: 0x4449444c016900010001080000000000000400 +ingress(1) Completed: Canister: Payload: 0x4449444c016900010001022a01 +ingress(2) Completed: Canister: Payload: 0x4449444c016900010001022a01 +ingress(3) Completed: Canister: Payload: 0x4449444c016900010001022a01 diff --git a/test/run-drun/ok/actor-import.ic-stub-run.ok b/test/run-drun/ok/actor-import.ic-stub-run.ok index 04506fe8c95..db1865fee01 100644 --- a/test/run-drun/ok/actor-import.ic-stub-run.ok +++ b/test/run-drun/ok/actor-import.ic-stub-run.ok @@ -1,10 +1,10 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update go(0x4449444c0000) -← completed: 0x4449444c016900010001080000000000000400 +← completed: 0x4449444c016900010001022a01 → update go2(0x4449444c0000) -← completed: 0x4449444c016900010001080000000000000400 +← completed: 0x4449444c016900010001022a01 → update go3(0x4449444c0000) -← completed: 0x4449444c016900010001080000000000000400 +← completed: 0x4449444c016900010001022a01 diff --git a/test/run-drun/ok/actor-reference-return.ic-stub-run.ok b/test/run-drun/ok/actor-reference-return.ic-stub-run.ok index 4193215d040..fa29433bf93 100644 --- a/test/run-drun/ok/actor-reference-return.ic-stub-run.ok +++ b/test/run-drun/ok/actor-reference-return.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → query foo(0x4449444c0000) diff --git a/test/run-drun/ok/actor-reference.ic-stub-run.ok b/test/run-drun/ok/actor-reference.ic-stub-run.ok index 54225bc8555..c2b23162b29 100644 --- a/test/run-drun/ok/actor-reference.ic-stub-run.ok +++ b/test/run-drun/ok/actor-reference.ic-stub-run.ok @@ -1,4 +1,4 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed diff --git a/test/run-drun/ok/array-out-of-bounds.drun-run.ok b/test/run-drun/ok/array-out-of-bounds.drun-run.ok index f7b89a6ce11..d907c8e8165 100644 --- a/test/run-drun/ok/array-out-of-bounds.drun-run.ok +++ b/test/run-drun/ok/array-out-of-bounds.drun-run.ok @@ -1,3 +1,3 @@ ingress(0) System -ingress(1) Err: IC0503: Canister ic:000000000000040054 trapped explicitly: Array index out of bounds -ingress(2) Err: IC0503: Canister ic:000000000000040054 trapped explicitly: Array index out of bounds +ingress(1) Err: IC0503: Canister ic:2A012B trapped explicitly: Array index out of bounds +ingress(2) Err: IC0503: Canister ic:2A012B trapped explicitly: Array index out of bounds diff --git a/test/run-drun/ok/array-out-of-bounds.ic-stub-run.ok b/test/run-drun/ok/array-out-of-bounds.ic-stub-run.ok index 511d283f933..e6fbfce33cd 100644 --- a/test/run-drun/ok/array-out-of-bounds.ic-stub-run.ok +++ b/test/run-drun/ok/array-out-of-bounds.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update foo1(0x4449444c0000) diff --git a/test/run-drun/ok/async-any.ic-stub-run.ok b/test/run-drun/ok/async-any.ic-stub-run.ok index be9fb5d62c0..afee61e2f46 100644 --- a/test/run-drun/ok/async-any.ic-stub-run.ok +++ b/test/run-drun/ok/async-any.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/async-calls1.ic-stub-run.ok b/test/run-drun/ok/async-calls1.ic-stub-run.ok index be9fb5d62c0..afee61e2f46 100644 --- a/test/run-drun/ok/async-calls1.ic-stub-run.ok +++ b/test/run-drun/ok/async-calls1.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/async-calls2.ic-stub-run.ok b/test/run-drun/ok/async-calls2.ic-stub-run.ok index be9fb5d62c0..afee61e2f46 100644 --- a/test/run-drun/ok/async-calls2.ic-stub-run.ok +++ b/test/run-drun/ok/async-calls2.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/async-calls3.ic-stub-run.ok b/test/run-drun/ok/async-calls3.ic-stub-run.ok index be9fb5d62c0..afee61e2f46 100644 --- a/test/run-drun/ok/async-calls3.ic-stub-run.ok +++ b/test/run-drun/ok/async-calls3.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/async-free-var.ic-stub-run.ok b/test/run-drun/ok/async-free-var.ic-stub-run.ok index c035c8a3e87..8f7bba2765d 100644 --- a/test/run-drun/ok/async-free-var.ic-stub-run.ok +++ b/test/run-drun/ok/async-free-var.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/async-loop-while.ic-stub-run.ok b/test/run-drun/ok/async-loop-while.ic-stub-run.ok index 132140ba1df..5590a21c0cc 100644 --- a/test/run-drun/ok/async-loop-while.ic-stub-run.ok +++ b/test/run-drun/ok/async-loop-while.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/async-loop.ic-stub-run.ok b/test/run-drun/ok/async-loop.ic-stub-run.ok index 54225bc8555..c2b23162b29 100644 --- a/test/run-drun/ok/async-loop.ic-stub-run.ok +++ b/test/run-drun/ok/async-loop.ic-stub-run.ok @@ -1,4 +1,4 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed diff --git a/test/run-drun/ok/async-new-obj.ic-stub-run.ok b/test/run-drun/ok/async-new-obj.ic-stub-run.ok index a1f0dd20497..9c1c1024157 100644 --- a/test/run-drun/ok/async-new-obj.ic-stub-run.ok +++ b/test/run-drun/ok/async-new-obj.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/async-obj-mut.ic-stub-run.ok b/test/run-drun/ok/async-obj-mut.ic-stub-run.ok index 410b0e9f1f3..6737780e9e8 100644 --- a/test/run-drun/ok/async-obj-mut.ic-stub-run.ok +++ b/test/run-drun/ok/async-obj-mut.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/async-while.ic-stub-run.ok b/test/run-drun/ok/async-while.ic-stub-run.ok index 132140ba1df..5590a21c0cc 100644 --- a/test/run-drun/ok/async-while.ic-stub-run.ok +++ b/test/run-drun/ok/async-while.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/await.ic-stub-run.ok b/test/run-drun/ok/await.ic-stub-run.ok index e622e712cbc..f9b45ab0b37 100644 --- a/test/run-drun/ok/await.ic-stub-run.ok +++ b/test/run-drun/ok/await.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/block.ic-stub-run.ok b/test/run-drun/ok/block.ic-stub-run.ok index e2f6f35e10e..bc7fdc731f7 100644 --- a/test/run-drun/ok/block.ic-stub-run.ok +++ b/test/run-drun/ok/block.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/call-async-method.drun-run.ok b/test/run-drun/ok/call-async-method.drun-run.ok index 7406b2a6114..68097b140dd 100644 --- a/test/run-drun/ok/call-async-method.drun-run.ok +++ b/test/run-drun/ok/call-async-method.drun-run.ok @@ -1,2 +1,2 @@ ingress(0) System -ingress(1) Err: IC0503: Canister ic:000000000000040054 trapped explicitly: not a self-call +ingress(1) Err: IC0503: Canister ic:2A012B trapped explicitly: not a self-call diff --git a/test/run-drun/ok/call-async-method.ic-stub-run.ok b/test/run-drun/ok/call-async-method.ic-stub-run.ok index 4d183fa65f6..5db2c220aa9 100644 --- a/test/run-drun/ok/call-async-method.ic-stub-run.ok +++ b/test/run-drun/ok/call-async-method.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update __motoko_async_helper(0x4449444c0000) diff --git a/test/run-drun/ok/caller.ic-stub-run.ok b/test/run-drun/ok/caller.ic-stub-run.ok index d1a9dd2d121..822fe5814e7 100644 --- a/test/run-drun/ok/caller.ic-stub-run.ok +++ b/test/run-drun/ok/caller.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update c1(0x4449444c0000) diff --git a/test/run-drun/ok/closure-params.ic-stub-run.ok b/test/run-drun/ok/closure-params.ic-stub-run.ok index ee68b9ca825..78e8d45a493 100644 --- a/test/run-drun/ok/closure-params.ic-stub-run.ok +++ b/test/run-drun/ok/closure-params.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/count-callbacks.ic-stub-run.ok b/test/run-drun/ok/count-callbacks.ic-stub-run.ok index 992fe1c0c94..cc9ae480184 100644 --- a/test/run-drun/ok/count-callbacks.ic-stub-run.ok +++ b/test/run-drun/ok/count-callbacks.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/counter.ic-stub-run.ok b/test/run-drun/ok/counter.ic-stub-run.ok index dca569ca0e7..e58b7435a4d 100644 --- a/test/run-drun/ok/counter.ic-stub-run.ok +++ b/test/run-drun/ok/counter.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update inc(0x4449444c0000) diff --git a/test/run-drun/ok/counter2.ic-stub-run.ok b/test/run-drun/ok/counter2.ic-stub-run.ok index b8085d2fb55..78ca22bb41e 100644 --- a/test/run-drun/ok/counter2.ic-stub-run.ok +++ b/test/run-drun/ok/counter2.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/data-params.ic-stub-run.ok b/test/run-drun/ok/data-params.ic-stub-run.ok index 9d8d53af4c6..bd4e6feb3b8 100644 --- a/test/run-drun/ok/data-params.ic-stub-run.ok +++ b/test/run-drun/ok/data-params.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/divide-by-zero.drun-run.ok b/test/run-drun/ok/divide-by-zero.drun-run.ok index f15b7e6ac5f..be93f590046 100644 --- a/test/run-drun/ok/divide-by-zero.drun-run.ok +++ b/test/run-drun/ok/divide-by-zero.drun-run.ok @@ -1 +1 @@ -ingress(0) Err: IC0502: Canister ic:000000000000040054 trapped: integer division by 0 +ingress(0) Err: IC0502: Canister ic:2A012B trapped: integer division by 0 diff --git a/test/run-drun/ok/divide-by-zero.ic-stub-run.ok b/test/run-drun/ok/divide-by-zero.ic-stub-run.ok index 761eb6df0e1..49f70070b4b 100644 --- a/test/run-drun/ok/divide-by-zero.ic-stub-run.ok +++ b/test/run-drun/ok/divide-by-zero.ic-stub-run.ok @@ -1,4 +1,4 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← rejected (RC_CANISTER_ERROR): Initialization trapped: EvalTrapError :0.1 "NumericIntegerDivideByZero" diff --git a/test/run-drun/ok/empty-actor.ic-stub-run.ok b/test/run-drun/ok/empty-actor.ic-stub-run.ok index 54225bc8555..c2b23162b29 100644 --- a/test/run-drun/ok/empty-actor.ic-stub-run.ok +++ b/test/run-drun/ok/empty-actor.ic-stub-run.ok @@ -1,4 +1,4 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed diff --git a/test/run-drun/ok/empty-call.ic-stub-run.ok b/test/run-drun/ok/empty-call.ic-stub-run.ok index be9fb5d62c0..afee61e2f46 100644 --- a/test/run-drun/ok/empty-call.ic-stub-run.ok +++ b/test/run-drun/ok/empty-call.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/flatten-awaitables.ic-stub-run.ok b/test/run-drun/ok/flatten-awaitables.ic-stub-run.ok index e82a85d7443..d921798208b 100644 --- a/test/run-drun/ok/flatten-awaitables.ic-stub-run.ok +++ b/test/run-drun/ok/flatten-awaitables.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/for-await.ic-stub-run.ok b/test/run-drun/ok/for-await.ic-stub-run.ok index c10d4285eb7..fcacff2dc33 100644 --- a/test/run-drun/ok/for-await.ic-stub-run.ok +++ b/test/run-drun/ok/for-await.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/free-callbacks.ic-stub-run.ok b/test/run-drun/ok/free-callbacks.ic-stub-run.ok index 01b067f68f9..43c43a8a35c 100644 --- a/test/run-drun/ok/free-callbacks.ic-stub-run.ok +++ b/test/run-drun/ok/free-callbacks.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/generic-tail-rec.ic-stub-run.ok b/test/run-drun/ok/generic-tail-rec.ic-stub-run.ok index cab5d9173c3..b93725a4983 100644 --- a/test/run-drun/ok/generic-tail-rec.ic-stub-run.ok +++ b/test/run-drun/ok/generic-tail-rec.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install debug.print: done 1 debug.print: done 2 diff --git a/test/run-drun/ok/hello-world-async.ic-stub-run.ok b/test/run-drun/ok/hello-world-async.ic-stub-run.ok index 1531f51761b..f8e57918ebf 100644 --- a/test/run-drun/ok/hello-world-async.ic-stub-run.ok +++ b/test/run-drun/ok/hello-world-async.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/hello-world-await.ic-stub-run.ok b/test/run-drun/ok/hello-world-await.ic-stub-run.ok index 3e98e12dcd0..5ebf1fd6f35 100644 --- a/test/run-drun/ok/hello-world-await.ic-stub-run.ok +++ b/test/run-drun/ok/hello-world-await.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/hello-world-message.ic-stub-run.ok b/test/run-drun/ok/hello-world-message.ic-stub-run.ok index 54225bc8555..c2b23162b29 100644 --- a/test/run-drun/ok/hello-world-message.ic-stub-run.ok +++ b/test/run-drun/ok/hello-world-message.ic-stub-run.ok @@ -1,4 +1,4 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed diff --git a/test/run-drun/ok/hello-world-return.ic-stub-run.ok b/test/run-drun/ok/hello-world-return.ic-stub-run.ok index ced690a2811..c8d43bb2112 100644 --- a/test/run-drun/ok/hello-world-return.ic-stub-run.ok +++ b/test/run-drun/ok/hello-world-return.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → query hello(0x4449444c00017105576f726c64) diff --git a/test/run-drun/ok/hello-world.ic-stub-run.ok b/test/run-drun/ok/hello-world.ic-stub-run.ok index 1eeeb078e34..787fda15c08 100644 --- a/test/run-drun/ok/hello-world.ic-stub-run.ok +++ b/test/run-drun/ok/hello-world.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install debug.print: Hello World! ← completed diff --git a/test/run-drun/ok/ic-calls.ic-stub-run.ok b/test/run-drun/ok/ic-calls.ic-stub-run.ok index be9fb5d62c0..afee61e2f46 100644 --- a/test/run-drun/ok/ic-calls.ic-stub-run.ok +++ b/test/run-drun/ok/ic-calls.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/idl-any.ic-stub-run.ok b/test/run-drun/ok/idl-any.ic-stub-run.ok index 28b2ef992b3..9c450eca4cf 100644 --- a/test/run-drun/ok/idl-any.ic-stub-run.ok +++ b/test/run-drun/ok/idl-any.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → query any(0x4449444c00027f7103466f6f) diff --git a/test/run-drun/ok/idl-bad.drun-run.ok b/test/run-drun/ok/idl-bad.drun-run.ok index 51eababe4f0..9a09fe7fddb 100644 --- a/test/run-drun/ok/idl-bad.drun-run.ok +++ b/test/run-drun/ok/idl-bad.drun-run.ok @@ -1,3 +1,3 @@ ingress(0) System debug.print: IDL error: missing magic bytes -Err: IC0502: Canister ic:000000000000040054 trapped: unreachable +Err: IC0502: Canister ic:2A012B trapped: unreachable diff --git a/test/run-drun/ok/idl-bad.ic-stub-run.ok b/test/run-drun/ok/idl-bad.ic-stub-run.ok index 8106b29424e..503aa6b80be 100644 --- a/test/run-drun/ok/idl-bad.ic-stub-run.ok +++ b/test/run-drun/ok/idl-bad.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → query foo(0x4e4f544449444c) diff --git a/test/run-drun/ok/idl-field-escape.ic-stub-run.ok b/test/run-drun/ok/idl-field-escape.ic-stub-run.ok index a38c7fe98bc..4acc93354d6 100644 --- a/test/run-drun/ok/idl-field-escape.ic-stub-run.ok +++ b/test/run-drun/ok/idl-field-escape.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → query foo1(0x4449444c0000) diff --git a/test/run-drun/ok/idl-func.drun-run.ok b/test/run-drun/ok/idl-func.drun-run.ok index ad76efaffa6..bfcc18007e7 100644 --- a/test/run-drun/ok/idl-func.drun-run.ok +++ b/test/run-drun/ok/idl-func.drun-run.ok @@ -1,5 +1,5 @@ ingress(0) System Ok: Payload: 0x4449444c026e016a017c010100010000 Ok: Payload: 0x4449444c0000 -Ok: Payload: 0x4449444c036a00010101016e026a017c010200010001010800000000000004000366756e -Ok: Payload: 0x4449444c016a0000010201000101080000000000000400066f6e65776179 +Ok: Payload: 0x4449444c036a00010101016e026a017c01020001000101022a010366756e +Ok: Payload: 0x4449444c016a0000010201000101022a01066f6e65776179 diff --git a/test/run-drun/ok/idl-func.ic-stub-run.ok b/test/run-drun/ok/idl-func.ic-stub-run.ok index 3bf918ef016..2187aa51f34 100644 --- a/test/run-drun/ok/idl-func.ic-stub-run.ok +++ b/test/run-drun/ok/idl-func.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → query fun(0x4449444c0000) @@ -7,6 +7,6 @@ → query fun2(0x4449444c026e016a017c0000010000) ← completed: 0x4449444c0000 → query fun3(0x4449444c0000) -← completed: 0x4449444c036a00010101016e026a017c010200010001010800000000000004000366756e +← completed: 0x4449444c036a00010101016e026a017c01020001000101022a010366756e → query fun4(0x4449444c0000) -← completed: 0x4449444c016a0000010201000101080000000000000400066f6e65776179 +← completed: 0x4449444c016a0000010201000101022a01066f6e65776179 diff --git a/test/run-drun/ok/idl-mo.ic-stub-run.ok b/test/run-drun/ok/idl-mo.ic-stub-run.ok index 54225bc8555..c2b23162b29 100644 --- a/test/run-drun/ok/idl-mo.ic-stub-run.ok +++ b/test/run-drun/ok/idl-mo.ic-stub-run.ok @@ -1,4 +1,4 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed diff --git a/test/run-drun/ok/idl-nary.drun-run.ok b/test/run-drun/ok/idl-nary.drun-run.ok index 0bd09bf21f5..5748bc6bff7 100644 --- a/test/run-drun/ok/idl-nary.drun-run.ok +++ b/test/run-drun/ok/idl-nary.drun-run.ok @@ -7,6 +7,6 @@ Ok: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f055468726565044 Ok: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 Ok: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 Ok: Payload: 0x4449444c016c0400710171027103710100034f6e650354776f05546872656504466f7572 -Err: IC0503: Canister ic:000000000000040054 trapped explicitly: IDL error: too few arguments Text,Text,Text -Err: IC0503: Canister ic:000000000000040054 trapped explicitly: IDL error: left-over bytes Text,Text,Text +Err: IC0503: Canister ic:2A012B trapped explicitly: IDL error: too few arguments Text,Text,Text +Err: IC0503: Canister ic:2A012B trapped explicitly: IDL error: left-over bytes Text,Text,Text Ok: Payload: 0x4449444c000471717171034f6e650354776f05546872656504466f7572 diff --git a/test/run-drun/ok/idl-nary.ic-stub-run.ok b/test/run-drun/ok/idl-nary.ic-stub-run.ok index cd94387094c..cbaf1fc6484 100644 --- a/test/run-drun/ok/idl-nary.ic-stub-run.ok +++ b/test/run-drun/ok/idl-nary.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → query two(0x4449444c00027171034f6e650354776f) diff --git a/test/run-drun/ok/idl-nat-int.ic-stub-run.ok b/test/run-drun/ok/idl-nat-int.ic-stub-run.ok index e2cfca32cb4..0534f71c702 100644 --- a/test/run-drun/ok/idl-nat-int.ic-stub-run.ok +++ b/test/run-drun/ok/idl-nat-int.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → query absolute(0x4449444c00017d2a) diff --git a/test/run-drun/ok/idl-option.ic-stub-run.ok b/test/run-drun/ok/idl-option.ic-stub-run.ok index 850f2772096..9dca8a15c39 100644 --- a/test/run-drun/ok/idl-option.ic-stub-run.ok +++ b/test/run-drun/ok/idl-option.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → query any(0x4449444c00017f) diff --git a/test/run-drun/ok/idl-pair.ic-stub-run.ok b/test/run-drun/ok/idl-pair.ic-stub-run.ok index 616b2dc8458..f8ab424d535 100644 --- a/test/run-drun/ok/idl-pair.ic-stub-run.ok +++ b/test/run-drun/ok/idl-pair.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → query len2(0x4449444c0002717102486905576f726c64) diff --git a/test/run-drun/ok/idl-record.ic-stub-run.ok b/test/run-drun/ok/idl-record.ic-stub-run.ok index 211ebfdd389..abdf225c1cb 100644 --- a/test/run-drun/ok/idl-record.ic-stub-run.ok +++ b/test/run-drun/ok/idl-record.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → query pair(0x4449444c016c020071017c010004486579212a) diff --git a/test/run-drun/ok/idl-shorthand.ic-stub-run.ok b/test/run-drun/ok/idl-shorthand.ic-stub-run.ok index 8268976065e..a03dae7bc92 100644 --- a/test/run-drun/ok/idl-shorthand.ic-stub-run.ok +++ b/test/run-drun/ok/idl-shorthand.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → query foo(0x4449444c016b01d1a7cf027f010000) diff --git a/test/run-drun/ok/idl-tuple.ic-stub-run.ok b/test/run-drun/ok/idl-tuple.ic-stub-run.ok index 5962adf545e..b2cf5de241c 100644 --- a/test/run-drun/ok/idl-tuple.ic-stub-run.ok +++ b/test/run-drun/ok/idl-tuple.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → query len2(0x4449444c0002717102486905576f726c64) diff --git a/test/run-drun/ok/idl-unit.ic-stub-run.ok b/test/run-drun/ok/idl-unit.ic-stub-run.ok index e7d4b9a40ab..68199a00422 100644 --- a/test/run-drun/ok/idl-unit.ic-stub-run.ok +++ b/test/run-drun/ok/idl-unit.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → query unit_id(0x4449444c0000) diff --git a/test/run-drun/ok/idl-variant.ic-stub-run.ok b/test/run-drun/ok/idl-variant.ic-stub-run.ok index 75074f6bd69..f7e488349e5 100644 --- a/test/run-drun/ok/idl-variant.ic-stub-run.ok +++ b/test/run-drun/ok/idl-variant.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → query numify(0x4449444c016b03d583b702008790c0bd0479dc9790cb0e790100000220000000) diff --git a/test/run-drun/ok/idl-vector.ic-stub-run.ok b/test/run-drun/ok/idl-vector.ic-stub-run.ok index 352cb7766e8..241d22977ff 100644 --- a/test/run-drun/ok/idl-vector.ic-stub-run.ok +++ b/test/run-drun/ok/idl-vector.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → query rose(0x4449444c016d00010003000400020000000000) diff --git a/test/run-drun/ok/interleave.ic-stub-run.ok b/test/run-drun/ok/interleave.ic-stub-run.ok index 88b295fbdeb..a723c66cd44 100644 --- a/test/run-drun/ok/interleave.ic-stub-run.ok +++ b/test/run-drun/ok/interleave.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/issue-894.ic-stub-run.ok b/test/run-drun/ok/issue-894.ic-stub-run.ok index f84aadc892b..e634922b493 100644 --- a/test/run-drun/ok/issue-894.ic-stub-run.ok +++ b/test/run-drun/ok/issue-894.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/local-throw.ic-stub-run.ok b/test/run-drun/ok/local-throw.ic-stub-run.ok index 77677f155a9..62e5e112d7b 100644 --- a/test/run-drun/ok/local-throw.ic-stub-run.ok +++ b/test/run-drun/ok/local-throw.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/mod-rebind.ic-stub-run.ok b/test/run-drun/ok/mod-rebind.ic-stub-run.ok index 54225bc8555..c2b23162b29 100644 --- a/test/run-drun/ok/mod-rebind.ic-stub-run.ok +++ b/test/run-drun/ok/mod-rebind.ic-stub-run.ok @@ -1,4 +1,4 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed diff --git a/test/run-drun/ok/nary-async.ic-stub-run.ok b/test/run-drun/ok/nary-async.ic-stub-run.ok index 67cdd79a076..5d6aaab1806 100644 --- a/test/run-drun/ok/nary-async.ic-stub-run.ok +++ b/test/run-drun/ok/nary-async.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update go1(0x4449444c0000) diff --git a/test/run-drun/ok/oneway-throw.ic-stub-run.ok b/test/run-drun/ok/oneway-throw.ic-stub-run.ok index 3f95346d97b..4f8ced56d84 100644 --- a/test/run-drun/ok/oneway-throw.ic-stub-run.ok +++ b/test/run-drun/ok/oneway-throw.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/oneway.ic-stub-run.ok b/test/run-drun/ok/oneway.ic-stub-run.ok index 13f27e947a6..85db204bcb2 100644 --- a/test/run-drun/ok/oneway.ic-stub-run.ok +++ b/test/run-drun/ok/oneway.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/oom.ic-stub-run.ok b/test/run-drun/ok/oom.ic-stub-run.ok index 563d63af289..301b73a2e17 100644 --- a/test/run-drun/ok/oom.ic-stub-run.ok +++ b/test/run-drun/ok/oom.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/overflow.ic-stub-run.ok b/test/run-drun/ok/overflow.ic-stub-run.ok index f26b454c94e..a57ceadf329 100644 --- a/test/run-drun/ok/overflow.ic-stub-run.ok +++ b/test/run-drun/ok/overflow.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/pass-references.ic-stub-run.ok b/test/run-drun/ok/pass-references.ic-stub-run.ok index 446392dd5b5..c9d7da8abcb 100644 --- a/test/run-drun/ok/pass-references.ic-stub-run.ok +++ b/test/run-drun/ok/pass-references.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/print-from-init.ic-stub-run.ok b/test/run-drun/ok/print-from-init.ic-stub-run.ok index fc6374816a2..2aa6c66be32 100644 --- a/test/run-drun/ok/print-from-init.ic-stub-run.ok +++ b/test/run-drun/ok/print-from-init.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install debug.print: Debug out ← completed diff --git a/test/run-drun/ok/query.ic-stub-run.ok b/test/run-drun/ok/query.ic-stub-run.ok index 5608f187c54..6cee50090f9 100644 --- a/test/run-drun/ok/query.ic-stub-run.ok +++ b/test/run-drun/ok/query.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update inc(0x4449444c0000) diff --git a/test/run-drun/ok/query2.ic-stub-run.ok b/test/run-drun/ok/query2.ic-stub-run.ok index e4ee45cba03..760b54d7faa 100644 --- a/test/run-drun/ok/query2.ic-stub-run.ok +++ b/test/run-drun/ok/query2.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/reject.ic-stub-run.ok b/test/run-drun/ok/reject.ic-stub-run.ok index 6345e111974..1cb96c6b834 100644 --- a/test/run-drun/ok/reject.ic-stub-run.ok +++ b/test/run-drun/ok/reject.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update reject1(0x4449444c0000) diff --git a/test/run-drun/ok/rts-stats.ic-stub-run.ok b/test/run-drun/ok/rts-stats.ic-stub-run.ok index fd75777735a..a5f2c60f539 100644 --- a/test/run-drun/ok/rts-stats.ic-stub-run.ok +++ b/test/run-drun/ok/rts-stats.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install debug.print: Size and allocation delta: (10_008, 10_008) ← completed diff --git a/test/run-drun/ok/self-shadow.ic-stub-run.ok b/test/run-drun/ok/self-shadow.ic-stub-run.ok index 54225bc8555..c2b23162b29 100644 --- a/test/run-drun/ok/self-shadow.ic-stub-run.ok +++ b/test/run-drun/ok/self-shadow.ic-stub-run.ok @@ -1,4 +1,4 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed diff --git a/test/run-drun/ok/selftail.drun-run.ok b/test/run-drun/ok/selftail.drun-run.ok index f4caf71ca8f..9bc92b6cea2 100644 --- a/test/run-drun/ok/selftail.drun-run.ok +++ b/test/run-drun/ok/selftail.drun-run.ok @@ -1,3 +1,3 @@ debug.print: ok1 debug.print: ok2 -ingress(0) Err: IC0502: Canister ic:000000000000040054 trapped: stack overflow +ingress(0) Err: IC0502: Canister ic:2A012B trapped: stack overflow diff --git a/test/run-drun/ok/selftail.ic-stub-run.ok b/test/run-drun/ok/selftail.ic-stub-run.ok index cd60c0c2f8f..7ce890fa05a 100644 --- a/test/run-drun/ok/selftail.ic-stub-run.ok +++ b/test/run-drun/ok/selftail.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install debug.print: ok1 debug.print: ok2 diff --git a/test/run-drun/ok/shared-object.ic-stub-run.ok b/test/run-drun/ok/shared-object.ic-stub-run.ok index be9fb5d62c0..afee61e2f46 100644 --- a/test/run-drun/ok/shared-object.ic-stub-run.ok +++ b/test/run-drun/ok/shared-object.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/sharingbug.ic-stub-run.ok b/test/run-drun/ok/sharingbug.ic-stub-run.ok index 54225bc8555..c2b23162b29 100644 --- a/test/run-drun/ok/sharingbug.ic-stub-run.ok +++ b/test/run-drun/ok/sharingbug.ic-stub-run.ok @@ -1,4 +1,4 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed diff --git a/test/run-drun/ok/show.ic-stub-run.ok b/test/run-drun/ok/show.ic-stub-run.ok index 3e9eb501dcb..cf0706b6256 100644 --- a/test/run-drun/ok/show.ic-stub-run.ok +++ b/test/run-drun/ok/show.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install debug.print: true debug.print: false diff --git a/test/run-drun/ok/text-iter.ic-stub-run.ok b/test/run-drun/ok/text-iter.ic-stub-run.ok index 42a8ffb6c61..3ef6493bd15 100644 --- a/test/run-drun/ok/text-iter.ic-stub-run.ok +++ b/test/run-drun/ok/text-iter.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install debug.print: via `debugPrint`: debug.print: hello world! diff --git a/test/run-drun/ok/throw.ic-stub-run.ok b/test/run-drun/ok/throw.ic-stub-run.ok index 77677f155a9..62e5e112d7b 100644 --- a/test/run-drun/ok/throw.ic-stub-run.ok +++ b/test/run-drun/ok/throw.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/transpose.ic-stub-run.ok b/test/run-drun/ok/transpose.ic-stub-run.ok index 20914d363ef..252f077943a 100644 --- a/test/run-drun/ok/transpose.ic-stub-run.ok +++ b/test/run-drun/ok/transpose.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/type-lub.ic-stub-run.ok b/test/run-drun/ok/type-lub.ic-stub-run.ok index be9fb5d62c0..afee61e2f46 100644 --- a/test/run-drun/ok/type-lub.ic-stub-run.ok +++ b/test/run-drun/ok/type-lub.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update go(0x4449444c0000) From 8f1ecbc8a6e468c91f1f9543fc717381dc7b8336 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Mon, 20 Jan 2020 18:01:48 +0000 Subject: [PATCH 0973/1176] refine async_cap to allow throw/try/catch from queries --- src/mo_frontend/typing.ml | 26 ++++++++++++++----- src/mo_types/async_cap.ml | 9 ++++--- test/fail/ok/queries.tc.ok | 12 ++++----- test/fail/queries.mo | 7 ++--- test/run-drun/ok/aritybug.comp-stub.ok | 2 +- .../ok/scope-example-func-implicit.tc.ok | 2 +- test/run-drun/ok/scope-example-func.tc.ok | 2 +- test/run-drun/ok/unsupported.tc.ok | 2 +- 8 files changed, 37 insertions(+), 25 deletions(-) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 18403c8612c..24552055e54 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -283,8 +283,9 @@ and check_AsyncCap env s at = match env.async with | C.AwaitCap c | C.AsyncCap c -> T.Con(c, []), fun c' -> C.AwaitCap c' - | C.QueryCap c -> T.Con(c, []), fun _c' -> C.NullCap - | C.NullCap -> error env at "misplaced %s" s + | C.QueryCap c -> T.Con(c, []), fun _c' -> C.ErrorCap + | C.ErrorCap + | C.NullCap -> error env at "misplaced %s; try enclosing in an async function" s and check_AwaitCap env s at = match env.async with @@ -292,6 +293,16 @@ and check_AwaitCap env s at = | C.AsyncCap _ | C.QueryCap _ -> error env at "misplaced %s; try enclosing in an async expression" s + | C.ErrorCap + | C.NullCap -> error env at "misplaced %s" s + +and check_ErrorCap env s at = + match env.async with + | C.AwaitCap c -> () + | C.ErrorCap -> () + | C.AsyncCap _ + | C.QueryCap _ -> + error env at "misplaced %s; try enclosing in an async expression or query function" s | C.NullCap -> error env at "misplaced %s" s and check_typ env (typ:typ) : T.typ = @@ -471,8 +482,9 @@ and infer_inst env tbs typs at = | {T.bound; sort = T.Scope; _}::tbs', typs' -> assert (List.for_all (fun tb -> tb.T.sort = T.Type) tbs'); (match env.async with - | C.NullCap -> error env at "scope required, but non available" - | C.QueryCap c + | C.ErrorCap + | C.QueryCap _ + | C.NullCap -> error env at "send capability required, but not available (need an enclosing async expression or function body" | C.AwaitCap c | C.AsyncCap c -> (T.Con(c,[])::ts, at::ats) @@ -918,7 +930,7 @@ and infer_exp'' env exp : T.typ = end; t | TryE (exp1, cases) -> - ignore (check_AwaitCap env "try" exp.at); + check_ErrorCap env "try" exp.at; let t1 = infer_exp env exp1 in let t2 = infer_cases env T.catch T.Non cases in if not env.pre then begin @@ -996,7 +1008,7 @@ and infer_exp'' env exp : T.typ = end; T.Non | ThrowE exp1 -> - ignore (check_AwaitCap env "throw" exp.at); + check_ErrorCap env "throw" exp.at; if not env.pre then check_exp env T.throw exp1; T.Non | AsyncE (typ_bind, exp1) -> @@ -1121,7 +1133,7 @@ and check_exp' env0 t exp : T.typ = ); t | TryE (exp1, cases), _ -> - ignore (check_AwaitCap env "try" exp.at); + check_ErrorCap env "try" exp.at; check_exp env t exp1; check_cases env T.catch t cases; (match Coverage.check_cases cases T.catch with diff --git a/src/mo_types/async_cap.ml b/src/mo_types/async_cap.ml index b87b110119d..47013161409 100644 --- a/src/mo_types/async_cap.ml +++ b/src/mo_types/async_cap.ml @@ -4,10 +4,11 @@ open Mo_config module T = Type type async_cap = - | NullCap - | QueryCap of T.con - | AsyncCap of T.con - | AwaitCap of T.con + | QueryCap of T.con (* can (query) async (i.e. in a shared query func) *) + | ErrorCap (* can try, catch (i.e. in the async body of shared query func) *) + | AsyncCap of T.con (* can async (i.e. in a func of async type or shared func) *) + | AwaitCap of T.con (* can async, send, try, catch, await (i.e. in an async expression *) + | NullCap (* none of the above *) let top_cap = Con.fresh "@" (T.Def([],T.Any)) diff --git a/test/fail/ok/queries.tc.ok b/test/fail/ok/queries.tc.ok index ae4ae20fe08..29de2c11311 100644 --- a/test/fail/ok/queries.tc.ok +++ b/test/fail/ok/queries.tc.ok @@ -1,7 +1,5 @@ -queries.mo:11.5-11.20: type error, misplaced await -queries.mo:15.5-15.13: type error, scope required, but non available -queries.mo:19.13-19.22: type error, scope required, but non available -queries.mo:20.5-20.20: type error, misplaced await -queries.mo:24.5-24.14: type error, misplaced async expression -queries.mo:29.5-29.21: type error, misplaced throw -queries.mo:33.5-33.22: type error, misplaced try +queries.mo:13.5-13.20: type error, misplaced await +queries.mo:17.5-17.13: type error, send capability required, but not available (need an enclosing async expression or function body +queries.mo:21.13-21.22: type error, send capability required, but not available (need an enclosing async expression or function body +queries.mo:22.5-22.20: type error, misplaced await +queries.mo:26.5-26.14: type error, misplaced async expression; try enclosing in an async function diff --git a/test/fail/queries.mo b/test/fail/queries.mo index cda7aa705fe..f7ee6e9a2cd 100644 --- a/test/fail/queries.mo +++ b/test/fail/queries.mo @@ -1,3 +1,5 @@ +import Prim "mo:prim"; + actor a { public shared func oneway() { }; @@ -24,13 +26,12 @@ actor a { async { }; // can't enter an async expression }; - // collateral damage (consider relaxing to allow throw and perhaps try/catch from queries) public shared query func badquery4() : async () { - throw (error ""); // can't throw + throw (Prim.error ""); // can throw }; public shared query func badquery5() : async () { - try {} catch _ {}; // can't catch + try () catch _ {}; // can catch }; }; diff --git a/test/run-drun/ok/aritybug.comp-stub.ok b/test/run-drun/ok/aritybug.comp-stub.ok index cdd45623b23..17030177185 100644 --- a/test/run-drun/ok/aritybug.comp-stub.ok +++ b/test/run-drun/ok/aritybug.comp-stub.ok @@ -1,3 +1,3 @@ aritybug.mo:13.41-15.2: type error, a shared function is only allowed as a public field of an actor (This is a limitation of the current version and flag -stub-system-api.) -aritybug.mo:17.25-22.2: type error, misplaced async expression +aritybug.mo:17.25-22.2: type error, misplaced async expression; try enclosing in an async function diff --git a/test/run-drun/ok/scope-example-func-implicit.tc.ok b/test/run-drun/ok/scope-example-func-implicit.tc.ok index b58d2027d39..8be480fa051 100644 --- a/test/run-drun/ok/scope-example-func-implicit.tc.ok +++ b/test/run-drun/ok/scope-example-func-implicit.tc.ok @@ -1 +1 @@ -scope-example-func-implicit.mo:7.13-7.22: type error, misplaced async expression +scope-example-func-implicit.mo:7.13-7.22: type error, misplaced async expression; try enclosing in an async function diff --git a/test/run-drun/ok/scope-example-func.tc.ok b/test/run-drun/ok/scope-example-func.tc.ok index 31dd2dd547e..fe627187b9c 100644 --- a/test/run-drun/ok/scope-example-func.tc.ok +++ b/test/run-drun/ok/scope-example-func.tc.ok @@ -1 +1 @@ -scope-example-func.mo:10.13-10.38: type error, misplaced async expression +scope-example-func.mo:10.13-10.38: type error, misplaced async expression; try enclosing in an async function diff --git a/test/run-drun/ok/unsupported.tc.ok b/test/run-drun/ok/unsupported.tc.ok index 1d8b975d138..4b6dfcb9936 100644 --- a/test/run-drun/ok/unsupported.tc.ok +++ b/test/run-drun/ok/unsupported.tc.ok @@ -1 +1 @@ -unsupported.mo:41.10-41.18: type error, misplaced async expression +unsupported.mo:41.10-41.18: type error, misplaced async expression; try enclosing in an async function From 5c6130d7c4e909a5ef440242fc9640acca6e3572 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Mon, 20 Jan 2020 18:17:24 +0000 Subject: [PATCH 0974/1176] missing file --- test/fail/ok/queries.tc.ret.ok | 1 + 1 file changed, 1 insertion(+) create mode 100644 test/fail/ok/queries.tc.ret.ok diff --git a/test/fail/ok/queries.tc.ret.ok b/test/fail/ok/queries.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/queries.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 From 69cd514850f0ab28ffe5296029909c69f5e45442 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 21 Jan 2020 13:32:41 +0100 Subject: [PATCH 0975/1176] More constant expressions: variables, blocks (#1113) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit this builds on top of #1111 and uses the infastructure there to let the compiler compile more stuff as “constant”, meaning no code generated, used directly in a direct call. Effect of this: No indirect call in ``` let fob = func fib (b:Bool) { if b { fob(false) } else () }; ``` or ``` func foobar2() = (); let foobaz2 = foobar2; foobaz2(); ``` or even ``` let foobar2 = func foobar2() = (); foobar2(); ``` (note the nested block there) --- src/codegen/compile.ml | 75 ++++++++++++++++++++++++------ test/run/static-call-func.mo | 15 ++++++ test/run/static-call-let-nested.mo | 41 ++++++++++++++++ test/run/static-call-let.mo | 15 ++++++ test/run/static-call-let2.mo | 17 +++++++ 5 files changed, 148 insertions(+), 15 deletions(-) create mode 100644 test/run/static-call-func.mo create mode 100644 test/run/static-call-let-nested.mo create mode 100644 test/run/static-call-let.mo create mode 100644 test/run/static-call-let2.mo diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index eb75333a4d8..734064af59d 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -5054,9 +5054,16 @@ module AllocHow = struct map_of_set StoreStatic (S.inter (set_of_map (M.filter is_local how)) captured) - let is_const_exp exp = match exp.it with + let rec is_const_exp exp = match exp.it with | FuncE _ -> true + | VarE _ -> true + | BlockE (ds, e) -> + List.for_all is_const_dec ds && is_const_exp e | _ -> false + and is_const_dec dec = match dec.it with + | VarD _ -> false + | LetD ({it = VarP v; _}, e) -> is_const_exp e + | LetD _ -> false let dec lvl how_outer (seen, how0) dec = let how_all = disjoint_union how_outer how0 in @@ -5070,11 +5077,11 @@ module AllocHow = struct | VarD _ -> map_of_set LocalMut d - (* Static expressions on the top-level: + (* Constant expressions on the top-level: - need to be constant forms - - all non-captured free variables must be static - - all captured variables must be static or static-heap, if not on top level - (top level captures variables will be forced to be static-heap below, via how2) + - all non-captured free variables must be constant + - all captured variables must be constant or static-heap, if not on top level + (stuff captured on the top level will always be static-heap, via how2 below) *) | LetD ({it = VarP _; _}, e) when is_const_exp e && @@ -6600,7 +6607,7 @@ and compile_dec env pre_ae how v2en dec : VarEnv.t * G.t * (VarEnv.t -> G.t) = (* A special case for public methods *) (* This relies on the fact that in the top-level mutually recursive group, no shadowing happens. *) | LetD ({it = VarP v; _}, e) when E.NameEnv.mem v v2en -> - let (const, fill) = compile_const_exp env pre_ae how e in + let (const, fill) = compile_const_exp env pre_ae e in let fi = match const with | Const.Message fi -> fi | _ -> assert false in @@ -6610,9 +6617,8 @@ and compile_dec env pre_ae how v2en dec : VarEnv.t * G.t * (VarEnv.t -> G.t) = (* A special case for constant expressions *) | LetD ({it = VarP v; _}, e) when AllocHow.M.find v how = AllocHow.Const -> - let (const, fill) = compile_const_exp env pre_ae how e in - let pre_ae1 = VarEnv.add_local_const pre_ae v const in - ( pre_ae1, G.nop, fun ae -> fill env ae; G.nop) + let (extend, fill) = compile_const_dec env pre_ae dec in + ( extend pre_ae, G.nop, fun ae -> fill env ae; G.nop) | LetD (p, e) -> let (pre_ae1, alloc_code, pat_arity, fill_code) = compile_n_ary_pat env pre_ae how p in @@ -6631,7 +6637,7 @@ and compile_dec env pre_ae how v2en dec : VarEnv.t * G.t * (VarEnv.t -> G.t) = Var.set_val env ae name ) -and compile_decs_open env pre_ae lvl decs v2en captured_in_body : VarEnv.t * G.t * (VarEnv.t -> G.t)= +and compile_decs_public env pre_ae lvl decs v2en captured_in_body : VarEnv.t * G.t = let how = AllocHow.decs pre_ae lvl decs captured_in_body in let rec go pre_ae decs = match decs with | [] -> (pre_ae, G.nop, fun _ -> G.nop) @@ -6645,10 +6651,7 @@ and compile_decs_open env pre_ae lvl decs v2en captured_in_body : VarEnv.t * G.t let code2 = mk_code2 ae in code1 ^^ code2 ) in - go pre_ae decs - -and compile_decs_public env ae lvl decs v2en captured_in_body : VarEnv.t * G.t = - let (ae1, alloc_code, mk_code) = compile_decs_open env ae lvl decs v2en captured_in_body in + let (ae1, alloc_code, mk_code) = go pre_ae decs in let code = mk_code ae1 in (ae1, alloc_code ^^ code) @@ -6671,7 +6674,8 @@ and compile_prog env ae (ds, e) = let code2 = compile_top_lvl_expr env ae' e in (ae', code1 ^^ code2) -and compile_const_exp env pre_ae how exp = match exp.it with +and compile_const_exp env pre_ae exp : Const.t * (E.t -> VarEnv.t -> unit) = + match exp.it with | FuncE (name, sort, control, typ_binds, args, res_tys, e) -> let return_tys = match control with | Type.Returns -> res_tys @@ -6684,8 +6688,49 @@ and compile_const_exp env pre_ae how exp = match exp.it with ) (Freevars.M.keys (Freevars.exp e)); compile_exp_as env ae (StackRep.of_arity (List.length return_tys)) e in FuncDec.closed env sort control name args mk_body return_tys exp.at + | BlockE (decs, e) -> + let (extend, fill1) = compile_const_decs env pre_ae decs in + let ae' = extend pre_ae in + let (c, fill2) = compile_const_exp env ae' e in + (c, fun env ae -> + let ae' = extend ae in + fill1 env ae'; + fill2 env ae') + | VarE v -> + let c = + match VarEnv.lookup_var pre_ae v with + | Some (VarEnv.Const c) -> c + | _ -> fatal "compile_const_exp/VarE: \"%s\" not found" v + in + (c, fun _ _ -> ()) | _ -> assert false +and compile_const_decs env pre_ae decs : (VarEnv.t -> VarEnv.t) * (E.t -> VarEnv.t -> unit) = + let rec go pre_ae decs = match decs with + | [] -> (fun ae -> ae), (fun _ _ -> ()) + | [dec] -> compile_const_dec env pre_ae dec + | (dec::decs) -> + let (extend1, fill1) = compile_const_dec env pre_ae dec in + let pre_ae1 = extend1 pre_ae in + let (extend2, fill2) = go pre_ae1 decs in + (fun ae -> extend2 (extend1 ae)), + (fun env ae -> fill1 env ae; fill2 env ae) in + go pre_ae decs + +and compile_const_dec env pre_ae dec : (VarEnv.t -> VarEnv.t) * (E.t -> VarEnv.t -> unit) = + (* This returns a _function_ to extend the VarEnv, instead of doing it, because + it needs to be extended twice: Once during the pass that gets the outer, static values + (no forward references), and then to implement the `fill`, which compiles the body + of functions (may contain forward references.) *) + match dec.it with + (* This should only contain constants (cf. is_const_exp) *) + | LetD ({it = VarP v; _}, e) -> + let (const, fill) = compile_const_exp env pre_ae e in + (fun ae -> VarEnv.add_local_const ae v const), + (fun env ae -> fill env ae) + + | _ -> fatal "compile_const_dec: Unexpected dec form" + and compile_prelude env ae = (* Allocate the primitive functions *) let (decs, _flavor) = E.get_prelude env in diff --git a/test/run/static-call-func.mo b/test/run/static-call-func.mo new file mode 100644 index 00000000000..faa9d94f44c --- /dev/null +++ b/test/run/static-call-func.mo @@ -0,0 +1,15 @@ +func go () { + func foobar1() = (); + foobar1(); +}; + +func foobar2() = (); +foobar2(); + +// CHECK: func $go +// CHECK-NOT: call_indirect +// CHECK: call $foobar1 + +// CHECK: func $start +// CHECK-NOT: call_indirect +// CHECK: call $foobar2 diff --git a/test/run/static-call-let-nested.mo b/test/run/static-call-let-nested.mo new file mode 100644 index 00000000000..2998c9890ca --- /dev/null +++ b/test/run/static-call-let-nested.mo @@ -0,0 +1,41 @@ +func go () { + let foobaz1 = { + func fuzz1() = (); + func foobar1() = fuzz1(); + let fooquux1 = foobar1; + fooquux1; + }; + foobaz1(); +}; + +let foobaz2 = { + func fuzz2() = (); + func foobar2() = fuzz2(); + let fooquux2 = foobar2; + fooquux2; +}; +foobaz2(); + +// It seems that we have to anticipate the order of these checks for FileCheck +// This means this needs to update if the compiler emits the functions in a different +// order. + +// There might be a way around using CHECK-DAG, but I am not sure. + + +// CHECK: func $go +// CHECK-NOT: call_indirect +// CHECK: call $foobar1 + +// CHECK: func $foobar2 +// CHECK-NOT: call_indirect +// CHECK: call $fuzz2 + +// CHECK: func $foobar1 +// CHECK-NOT: call_indirect +// CHECK: call $fuzz1 + +// CHECK: func $start +// CHECK-NOT: call_indirect +// CHECK: call $foobar2 + diff --git a/test/run/static-call-let.mo b/test/run/static-call-let.mo new file mode 100644 index 00000000000..73d3053ab3b --- /dev/null +++ b/test/run/static-call-let.mo @@ -0,0 +1,15 @@ +func go () { + let foobar1 = func foobar1() = (); + foobar1(); +}; + +let foobar2 = func foobar2() = (); +foobar2(); + +// CHECK: func $go +// CHECK-NOT: call_indirect +// CHECK: call $foobar1 + +// CHECK: func $start +// CHECK-NOT: call_indirect +// CHECK: call $foobar2 diff --git a/test/run/static-call-let2.mo b/test/run/static-call-let2.mo new file mode 100644 index 00000000000..e9a4d38111b --- /dev/null +++ b/test/run/static-call-let2.mo @@ -0,0 +1,17 @@ +func go () { + func foobar1() = (); + let foobaz1 = foobar1; + foobaz1(); +}; + +func foobar2() = (); +let foobaz2 = foobar2; +foobaz2(); + +// CHECK: func $go +// CHECK-NOT: call_indirect +// CHECK: call $foobar1 + +// CHECK: func $start +// CHECK-NOT: call_indirect +// CHECK: call $foobar2 From 9669c5074603c7d8737958db5338b6bae1922a0e Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 21 Jan 2020 13:58:35 +0100 Subject: [PATCH 0976/1176] Constant objects and modules (#1121) this means that importing a function from `Prim` or the standard library, and calling it, will be a direct call, not `CallIndirect`; an important prerequisite to allow the Wasm engine inline and optimize (I assume) --- src/codegen/compile.ml | 41 +++++++++++++++++++++++++++++----- test/run/static-call-module.mo | 15 +++++++++++++ 2 files changed, 51 insertions(+), 5 deletions(-) create mode 100644 test/run/static-call-module.mo diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 734064af59d..458926797db 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -59,6 +59,7 @@ module Const = struct | Fun of int32 | Message of int32 (* anonymous message, only temporary *) | PublicMethod of int32 * string + | Obj of (string * t) list end (* Const *) @@ -2389,6 +2390,10 @@ module Object = struct let _, fields = Type.as_obj_sub [s] obj_type in Type.is_mut (Type.lookup_val_field s fields) + let is_immutable obj_type = + let _, fields = Type.as_obj_sub [] obj_type in + List.for_all (fun f -> not (Type.is_mut f.Type.typ)) fields + let idx env obj_type name = compile_unboxed_const (Mo_types.Hash.hash name) ^^ idx_hash env (is_mut_field env obj_type name) @@ -4372,7 +4377,7 @@ module StackRep = struct | Const _ -> G.nop | Unreachable -> G.nop - let materialize env = function + let rec materialize env = function | Const.Fun fi -> (* When accessing a variable that is a constant function, then we need to create a heap-allocated closure-like thing on the fly. *) @@ -4385,6 +4390,8 @@ module StackRep = struct | Const.PublicMethod (_, name) -> Dfinity.get_self_reference env ^^ Dfinity.actor_public_field env name + | Const.Obj fs -> + Object.lit_raw env (List.map (fun (n, st) -> (n, fun () -> materialize env st)) fs) let adjust env (sr_in : t) sr_out = if sr_in = sr_out @@ -5059,7 +5066,10 @@ module AllocHow = struct | VarE _ -> true | BlockE (ds, e) -> List.for_all is_const_dec ds && is_const_exp e + | NewObjE (Type.(Object | Module), _, t) -> + Object.is_immutable t | _ -> false + and is_const_dec dec = match dec.it with | VarD _ -> false | LetD ({it = VarP v; _}, e) -> is_const_exp e @@ -5907,9 +5917,16 @@ and compile_exp (env : E.t) ae exp = Variant.inject env l (compile_exp_vanilla env ae e) | DotPrim name, [e] -> - SR.Vanilla, - compile_exp_vanilla env ae e ^^ - Object.load_idx env e.note.note_typ name + let sr, code1 = compile_exp env ae e in + begin match sr with + | SR.Const (Const.Obj fs) -> + let c = List.assoc name fs in + SR.Const c, code1 + | _ -> + SR.Vanilla, + code1 ^^ StackRep.adjust env sr SR.Vanilla ^^ + Object.load_idx env e.note.note_typ name + end | ActorDotPrim name, [e] -> SR.Vanilla, compile_exp_vanilla env ae e ^^ @@ -6345,7 +6362,12 @@ and compile_exp (env : E.t) ae exp = if Freevars.M.is_empty (Freevars.diff captured prelude_names) then actor_lit env ds fs exp.at else todo_trap env "non-closed actor" (Arrange_ir.exp exp) - | NewObjE ((Type.Object | Type.Module), fs, _) -> + | NewObjE (Type.(Object | Module) as _sort, fs, _) -> + (* + We can enable this warning once we treat everything as static that + mo_frontend/static.ml accepts, including _all_ literals. + if sort = Type.Module then Printf.eprintf "%s" "Warning: Non-static module\n"; + *) SR.Vanilla, let fs' = fs |> List.map (fun (f : Ir.field) -> (f.it.name, fun () -> @@ -6703,6 +6725,15 @@ and compile_const_exp env pre_ae exp : Const.t * (E.t -> VarEnv.t -> unit) = | _ -> fatal "compile_const_exp/VarE: \"%s\" not found" v in (c, fun _ _ -> ()) + | NewObjE (Type.(Object | Module), fs, _) -> + let static_fs = List.map (fun f -> + let st = + match VarEnv.lookup_var pre_ae f.it.var with + | Some (VarEnv.Const c) -> c + | _ -> fatal "compile_const_exp/ObjE: \"%s\" not found" f.it.var + in f.it.name, st) fs + in + (Const.Obj static_fs, fun _ _ -> ()) | _ -> assert false and compile_const_decs env pre_ae decs : (VarEnv.t -> VarEnv.t) * (E.t -> VarEnv.t -> unit) = diff --git a/test/run/static-call-module.mo b/test/run/static-call-module.mo new file mode 100644 index 00000000000..b775eeef556 --- /dev/null +++ b/test/run/static-call-module.mo @@ -0,0 +1,15 @@ +func go () { + let obj1 = module { public func foobar1() = () }; + obj1.foobar1(); +}; + +let obj2 = module { public func foobar2() = () }; +obj2.foobar2(); + +// CHECK: func $go +// CHECK-NOT: call_indirect +// CHECK: call $foobar1 + +// CHECK: func $start +// CHECK-NOT: call_indirect +// CHECK: call $foobar2 From a0f0d1fd96bfc059b4c535df508e988d419a12d2 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 21 Jan 2020 13:11:26 +0000 Subject: [PATCH 0977/1176] fix doc simplifying sugar and updating examples; address joachims suggestions --- design/scoped-await.md | 221 ++++++++++++++++++-------------------- src/ir_def/check_ir.ml | 4 +- src/mo_def/syntax.ml | 6 +- src/mo_frontend/typing.ml | 21 ++-- src/mo_idl/idl_to_mo.ml | 2 +- src/mo_types/async_cap.ml | 2 +- src/mo_types/type.ml | 14 +-- src/mo_types/type.mli | 9 +- 8 files changed, 141 insertions(+), 138 deletions(-) diff --git a/design/scoped-await.md b/design/scoped-await.md index dd1d54b7edc..d6a41488c50 100644 --- a/design/scoped-await.md +++ b/design/scoped-await.md @@ -12,10 +12,9 @@ await async values it has created, hopefully ruling out: while still allowing local uses of first-class async values. -Deadlock is (hopefully) prevented because an async can't await itself, since +Deadlock is prevented because an async can't await itself, since it can only await asyncs it has created. Similarly, a sequence of asyncs can only be awaited by the async that created them, not by each other. -That's the hope anyway. The idea behind ruling out *reply-to-wrong-sender* is that an async value cannot be stored in a non-local var or other mutable @@ -225,32 +224,39 @@ E; _ |- shared? f(x:T) : async U { e } : (These examples and more are all coded in -* [general_await.mo](../test/run-drun/general_await.mo) (no-sugar) -* [general_await_implicit.mo](../test/run-drun/general_await_implicit.mo) (with sugar) +* [general_await.mo](../test/run-drun/general_await.mo) (annotated with desugaring) +* [general_await_implicit.mo](../test/run-drun/general_await_implicit.mo) (sugar only) ) Assuming the following requests: ``` - public shared func Ack<@>() : async<@> (){ - debugPrint "Ack" + public shared func Ack() : async(){ + Prim.debugPrint "Ack" }; -x public shared func Request<@>(i : Int) : async<@> Int { - debugPrint("Request(" # debug_show i # ")"); - return i; + public shared func Request(i : Int) : async Int { + Prim.debugPrintInt(i); + return i }; + ``` ### Static parallel waiting: ``` - public shared func PA<@>() : async<@> () { + public shared func PA() : async () { let a1 = Ack(); let a2 = Ack(); await a1; await a2; }; + + public shared func PR() : async (Int,Int) { + let a1 = Request(1); + let a2 = Request(2); + (await a1, await a2) + }; ``` ### Dynamic parallel waiting for acknowledgements @@ -258,41 +264,51 @@ x public shared func Request<@>(i : Int) : async<@> Int { ``` // Dynamic parallel waiting for acknowledgements - public shared func DPA<@>() : async<@>() { - let as: [async()] = Array_tabulate(N, func (_) { Ack<@>(); }); - for (a in as.vals()) { - await a; - }; + public shared func DPA() : async() { + let os = Prim.Array_init(10, null); + for (i in os.keys()) { + os[i] := ? (Ack()); + }; + for (o in os.vals()) { + switch o { + case (? a) await a; + case null (assert false); + }; + }; }; ``` ### Dynamic parallel waiting (with results) ``` - // Dynamic parallel waiting (with results) - - public shared func DPR<@>() : async<@>[Int] { - func f<>(i:Nat) : async Int = Request<@>(i); - let as = Array_tabulate(N, f); - let res = Array_init(as.len(),-1); - for (i in as.keys()) { - res[i] := (await as[i]); + public shared func DPR() : async [Int] { + let os = Prim.Array_init(10, null); + for (i in os.keys()) { + os[i] := ? (Request(i)); + }; + let res = Prim.Array_init(os.len(),-1); + for (i in os.keys()) { + switch (os[i]) { + case (? a) res[i] := await a; + case null (assert false); + }; }; - Array_tabulate(as.len(),func i = res[i]) + Prim.Array_tabulate(res.len(),func i { res[i] }) }; ``` ### Recursive parallel waiting ``` - public shared func RPA<@>(n:Nat) : async<@>() { + public shared func RPA(n:Nat) : async () { if (n == 0) () else { - let a = Ack<@>(); - await RPA<@>(n-1); // recurse + let a = Ack(); + await RPA(n-1); // recurse await a; }; }; + ``` ### Recursive parallel waiting (with results) @@ -300,11 +316,11 @@ x public shared func Request<@>(i : Int) : async<@> Int { ``` public type List = ?(Int,List); - public shared func RPR<@>(n:Nat) : async<@> List { + public shared func RPR(n:Nat) : async List { if (n == 0) null else { - let a = Request<@>(n); - let tl = await RPR<@>(n-1); // recurse + let a = Request(n); + let tl = await RPR(n-1); // recurse ?(await a,tl) } }; @@ -322,30 +338,30 @@ x public shared func Request<@>(i : Int) : async<@> Int { is rejected because, once annotated: ``` - let t:async<@>U = async{ await t;} <@>; // bad await since t : Async<@>U U + let t:async<@>U = async<@1>{ await t;}; // bad await since t : Async<@>U U ``` -Ruled out by index scoping (`X != @`, any `@`) +Ruled out by index scoping (`@1 <> @ `) #### Indirect deadlock ``` async { - let a1 : async () = async { await a2; }; // illegal await since a1 : Async() () - let a2 : async () = async { await a1; }; // illegal await since a2 : Async() () + let a1 : async () = async { await a2; }; + let a2 : async () = async { await a1; }; }; ``` is rejected because, once annotated: ``` - async { - let a1 : async = async { await a2; }; // bad await since a1 : Async() () - let a2 : async = async { await a1; }; // bad await since a2 : Async() () - }<@> + async<@> { + let a1 : async<@> = async<@1> { await a2; }; // bad await since a2 : Async<@>() () + let a2 : async<@> = async<@2> { await a1; }; // bad await since a1 : Async<@>() () + } ``` -since `X != Y,Z`, any `Y,Z`. +since `@1 <> @` and `@2` <> `@`. ### Imperative deadlock @@ -354,27 +370,26 @@ The informal example: ``` async { var x = async { 0 }; - x := (async { - await x // illegal: await _ : asyncT -> T (not async T -> T) (any T)) - }); + x := async { + await x + }; } ``` that attempts to tie an imperative knot, is rejected by this system. -Explicitly, the outer and nested async would have distinct parameters `` and ``, so the await for type `asyncNat` on `x` (of type asyncNat (with the outer parameter) would actually be illegal: +Explicitly, the outer and nested async would have distinct parameters `<@>` and `<@2>`, so the await at type `async<@2>Nat` on `x` +(of type `async<@>Nat` (with the outer parameter) would actually be illegal: ``` -async { - var x : async Nat = async<_> 0 ; - x := async{ - await x // illegal: await _ : asyncT -> T (not async T -> T) (any T) - } ; -}<@> +async<@> { + var x : async<@> Nat = async<@1> 0; + x := async<@2>{ + await x // illegal: this await requires async<@2>Nat (not async<@>Nat) + }; +} ``` -Note that simply renaming `S` to `R` would not circumvent the error.) - ## Sugar Principle: Desugaring should be: @@ -386,7 +401,7 @@ Principle: Desugaring should be: ### Basic idea: -(`@` is a new type identifier, used for scopes) +(`@` is a new type identifier, reserved for scopes only, intially defined as 'Any') Parsing: @@ -411,11 +426,6 @@ Syntactic sugar (during parse, applied bottom up as we construct types and terms (shared? f<...>() : async T { e })^ := (@ not in ...) shared? f<@,...^>(^) : (async T)^ = async<@> e^ -(shared? f<...>() : async T { e }) := - shared? f<...^>(^) : async T^ = async e ^ - - (binds inner scope as X, not @, to pun X in e) - (shared f<...>() : () = e)^ := (@ not in ...) shared f<@,...^>(^) : () = e^ @@ -428,81 +438,62 @@ Syntactic sugar (during parse, applied bottom up as we construct types and terms ``` -Syntax elaboration (applied during type checking) - -``` -Types: - -@* ~~> - @* - - (* interprets @ at its current binding (which may be some X) *) - -(async t)* ~~> - async<@*> t* - -(async t2)* - ~~> async t2* +### Elaboration -<...>T1 -> async T2 ~~> (* syntax sugaring ensures @ bound in ... *) - <...>T1* -> async<@*> T2* +During elaboration, we rebind `@` to the current scope +identifier (aliasing `@` with some type parameter `X` if necessary) so +that: + * references inserted during parsing elaborate to the nearest appropiate binding -<...,X,...>T1 -> async T2 ~~> - <...*,X,...*>T1*[X/@] -> async T2*[X/@], (* rebind @ to X *) +Note that in a function type or definition with type parameters, `@` +either shadows one of those eponymous type parameters (if introduced by +de-sugaring) or it retains its outer meaning. -<...>T1 -> async T2 ~~> (* U <> X in ... *) - <...*>T1* -> async T2* +### Sugaring types (for pretty printing) -Terms: +During pretty printing of types, we suppress a unary type binding in a +function type if it only occurs as an `async` type instantiation at +DeBruijn level 0, in which case we elide all those `async` type +instantiations too. -async e ~~> async e[X/@] +Binders with async instantiations at DeBruijn levels other than 0 +cannot arise by construction (this is an invariant of desugaring and +the fact that we don't support explicit binding). -f e ~~> - f e when f : <...,Xi,...> T1 ~~> async T1 -(note inference can infer a missing scope parameter at any position, not just position 0) +### Initial Context -func<...>f() : async T = e ~~> (* syntax sugaring ensures @ bound in ... *) - func<...*>f() : (async T)* = e* +For compiled programs we restrict the inital capability to `NullCap`, +so that sends and async can only occur in shared functions. -func<...,X,...>f() : async T = e (* rebind @ to X *) - func<...*,X,...*>f() : (async T)*[X/@] = e*[X/@] +For interpreted programs we use the initial capability `Async @` so +that programs can `async` and `send` at top-level (but not `await`). -func<...>f() : async T = e ~~> (* U <> X in ... *) - func<...*>f() : async T* = e* +### Queries -``` +In Motoko, expressions that `await` can also `throw/try-catch`, but +`query` functions are not allowed to spawn async expressions or send +message (but can return errors). -Basically, during elaboration, we rebind `@` to the current scope -identifier (aliasing `@` with some type parameter `X` if necessary) so -that: - * references inserted during parsing elaborate to the nearest appropiate binding - * missing scope instantiations default to the current binding of `@`. - -Note that in a function type or definition with n>1 type parameters, -`@` either shadows one of those eponymous type parameters or it -retains its outer meaning. In the latter case (outer binding), we -might either warn appropriately or reject as ambiguous, requiring the -user to give the missing instantiation of the `async T` return type. +Query functions that may `throw/try/catch` but not send or `async` are +easily accomodated by: -(The implementation is currently silent and defaults `@` to the enclosing interpretation.) - -### Sugaring types (for pretty printing) +* refining the notion of capabilities, addinq `QueryCap` and + `ErrorCap`, where `AwaitCap` entails `ErrorCap`. +* making helper `cap` depend on the query modifer, returning + `QueryCap` for a query. +* conditionally transitioning the current capability accordingly when + entering an `async` expression (from `QueryCap` to `ErrorCap` + rather than `AsyncCap` to `AwaitCap`) -During pretty printing of types, we suppress a unary type binding in a -function type if it only occurs as an `async` type instantiation at -DeBruijn level 0, in which case we elide all those `async` type -instantiations too. +See the code for details. -Binders with async instantiations at DeBruijn levels other than 0 must -be shown to avoid ambiguity, in particular so that the user knows -which parameter is the scope parameter if explicit (not implicit) -instantiation is desired. ### Refinements Since users may find it odd that we can instantiate the index at any type, it might be better to define "type @ = Non" and always bound -index-parameters by `Non`. Then the top-level choice of index really is unique -since `Non`, and any `Non`-bounded type parameter, are the only types -bounded by `Non` and thus suitable for uses as index instantiations. +index-parameters by `Non`. Then the top-level choice of index really +is unique since `Non`, and any `Non`-bounded type parameter, are the +only types bounded by `Non` and thus suitable for uses as index +instantiations. diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 7a0df24b6f0..38af8805347 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -195,6 +195,8 @@ let rec check_typ env typ : unit = | T.Opt typ -> check_typ env typ | T.Async (typ1, typ2) -> + check_typ env typ1; + check_typ env typ2; check env no_region env.flavor.Ir.has_async_typ "async in non-async flavor"; let t' = T.promote typ2 in check_shared env no_region t' @@ -602,7 +604,7 @@ let rec check_exp env (exp:Ir.exp) : unit = let env' = adjoin_cons env ce in let ve = check_args env' args in List.iter (check_typ env') ret_tys; - check ((T.is_shared_sort sort && T.is_promising control) ==> isAsyncE exp) + check ((T.is_shared_sort sort && control = T.Promises) ==> isAsyncE exp) "shared function with async type has non-async body"; if T.is_shared_sort sort then List.iter (check_concrete env exp.at) ret_tys; let codom = T.codom control (fun () -> List.hd ts) ret_tys in diff --git a/src/mo_def/syntax.ml b/src/mo_def/syntax.ml index 5278e83e100..d413d432128 100644 --- a/src/mo_def/syntax.ml +++ b/src/mo_def/syntax.ml @@ -246,12 +246,10 @@ let (@?) it at = Source.({it; at; note = empty_typ_note}) let (@!) it at = Source.({it; at; note = Type.Pre}) let (@=) it at = Source.({it; at; note = None}) -let scope_id = "@" - let scope_typ region = Source.( { it = PathT ( - { it = IdH { it = scope_id; at = region; note = () }; + { it = IdH { it = Type.scope_var; at = region; note = () }; at = no_region; note = Type.Pre }, []); @@ -259,7 +257,7 @@ let scope_typ region = note = Type.Pre }) let scope_bind() = - { var = scope_id @@ no_region; + { var = Type.scope_var @@ no_region; sort = Type.Scope @@ no_region; bound = PrimT "Any" @! no_region } @= no_region diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 24552055e54..846ce21e8bf 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -18,7 +18,7 @@ type ret_env = T.typ option let initial_scope = { Scope.empty with - Scope.typ_env = T.Env.singleton scope_id C.top_cap; + Scope.typ_env = T.Env.singleton T.scope_var C.top_cap; Scope.con_env = T.ConSet.singleton C.top_cap; } @@ -268,16 +268,15 @@ let check_shared_return env at sort c ts = | _ -> () let rec infer_async_cap env sort cs tbs = - let env = { env with async = C.NullCap } in match sort, cs, tbs with | (T.Shared T.Write | T.Local) , c::_, { T.sort = T.Scope; _ }::_ -> - { env with typs = T.Env.add scope_id c env.typs; + { env with typs = T.Env.add T.scope_var c env.typs; async = C.AsyncCap c } | (T.Shared T.Query) , c::_, { T.sort = T.Scope; _ }::_ -> - { env with typs = T.Env.add scope_id c env.typs; + { env with typs = T.Env.add T.scope_var c env.typs; async = C.QueryCap c } | T.Shared _, _, _ -> assert false (* impossible given sugaring *) - | _ -> env + | _ -> { env with async = C.NullCap } and check_AsyncCap env s at = match env.async with @@ -415,6 +414,10 @@ and check_typ_binds_acyclic env typ_binds cs ts = in chase 0 [] c in List.iter2 chase typ_binds cs +and check_typ_bind_sorts env typs tbs = + (* assert, don't error, since this should be a syntactic invariant of parsing *) + List.iteri (fun i tb -> assert (i == 0 || (tb.T.sort = T.Type))) tbs; + and check_typ_binds env typ_binds : T.con list * T.bind list * Scope.typ_env * Scope.con_env = let xs = List.map (fun typ_bind -> typ_bind.it.var.it) typ_binds in let cs = @@ -434,7 +437,7 @@ and check_typ_binds env typ_binds : T.con list * T.bind list * Scope.typ_env * S T.sort = typ_bind.it.sort.it; T.bound = check_typ pre_env' typ_bind.it.bound }) typ_binds in - List.iteri (fun i tb -> assert (i == 0 || (tb.T.sort = T.Type))) tbs; + check_typ_bind_sorts env typ_binds; let ts = List.map (fun tb -> tb.T.bound) tbs in check_typ_binds_acyclic env typ_binds cs ts; let ks = List.map (fun t -> T.Abs ([], t)) ts in @@ -1016,7 +1019,7 @@ and infer_exp'' env exp : T.typ = error_in [Flags.ICMode] env exp.at "unsupported async block"; let t1, next_cap = check_AsyncCap env "async expression" exp.at in let c, tb, ce, cs = check_typ_bind env typ_bind in - let ce_scope = T.Env.add "@" c ce in (* pun scope identifier @ with c *) + let ce_scope = T.Env.add T.scope_var c ce in (* pun scope var with c *) let env' = {(adjoin_typs env ce_scope cs) with labs = T.Env.empty; rets = Some T.Pre; async = next_cap c} in let t = infer_exp env' exp1 in @@ -1107,7 +1110,7 @@ and check_exp' env0 t exp : T.typ = (T.string_of_typ_expand t1) (T.string_of_typ_expand t1'); let c, tb, ce, cs = check_typ_bind env tb in - let ce_scope = T.Env.add "@" c ce in (* pun scope identifier @ with c *) + let ce_scope = T.Env.add T.scope_var c ce in (* pun scope var with c *) let env' = {(adjoin_typs env ce_scope cs) with labs = T.Env.empty; rets = Some t'; async = next_cap c} in check_exp env' t' exp1; @@ -1764,7 +1767,7 @@ and gather_dec env scope dec : Scope.t = error env dec.at "duplicate definition for type %s in block" id.it; let pre_tbs = List.map (fun bind -> {T.var = bind.it.var.it; - T.sort = if bind.it.var.it = scope_id then T.Scope else T.Type; + T.sort = T.Type; T.bound = T.Pre} ) binds in let pre_k = T.Abs (pre_tbs, T.Pre) in diff --git a/src/mo_idl/idl_to_mo.ml b/src/mo_idl/idl_to_mo.ml index 9c9153c445c..b2b06b91800 100644 --- a/src/mo_idl/idl_to_mo.ml +++ b/src/mo_idl/idl_to_mo.ml @@ -74,7 +74,7 @@ let rec check_typ env t = M.Variant (List.sort M.compare_field fs) | FuncT (ms, ts1, ts2) -> let (s, c) = check_modes ms in - M.Func (M.Shared s, c, [{ M.var= "@"; M.sort = M.Scope; M.bound = M.Any }], List.map (check_typ env) ts1, List.map (check_typ env) ts2) + M.Func (M.Shared s, c, [M.scope_bind], List.map (check_typ env) ts1, List.map (check_typ env) ts2) | ServT ms -> let fs = List.map (check_meth env) ms in M.Obj (M.Actor, List.sort M.compare_field fs) diff --git a/src/mo_types/async_cap.ml b/src/mo_types/async_cap.ml index 47013161409..0c10b48193b 100644 --- a/src/mo_types/async_cap.ml +++ b/src/mo_types/async_cap.ml @@ -6,7 +6,7 @@ module T = Type type async_cap = | QueryCap of T.con (* can (query) async (i.e. in a shared query func) *) | ErrorCap (* can try, catch (i.e. in the async body of shared query func) *) - | AsyncCap of T.con (* can async (i.e. in a func of async type or shared func) *) + | AsyncCap of T.con (* can async, send (i.e. in a func of async type or shared func) *) | AwaitCap of T.con (* can async, send, try, catch, await (i.e. in an async expression *) | NullCap (* none of the above *) diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index c6fb6ac4cd6..0c17ef6e5b9 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -48,13 +48,14 @@ and typ = | Opt of typ (* option *) | Tup of typ list (* tuple *) | Func of func_sort * control * bind list * typ list * typ list (* function *) - | Async of typ * typ (* future *) + | Async of scope * typ (* future *) | Mut of typ (* mutable type *) | Any (* top *) | Non (* bottom *) | Typ of con (* type (field of module) *) | Pre (* pre-type *) +and scope = typ and bind_sort = Scope | Type and bind = {var : var; sort: bind_sort; bound : typ} @@ -68,10 +69,6 @@ and kind = (* Function sorts *) let is_shared_sort sort = sort <> Local -let is_promising c = - match c with - | Promises -> true - | _ -> false (* Constructors *) @@ -150,7 +147,6 @@ let prim = function let seq = function [t] -> t | ts -> Tup ts - let codom c to_scope ts2 = match c with | Promises -> Async (to_scope(), seq ts2) | Returns -> seq ts2 @@ -1114,6 +1110,12 @@ let glb t1 t2 = glb' (ref M.empty) (ref M.empty) t1 t2 module Env = Env.Make(String) +(* Scopes *) + +let scope_var = "@" +let scope_bound = Any +let scope_bind = { var = scope_var; sort = Scope; bound = scope_bound } + (* Pretty printing *) open Printf diff --git a/src/mo_types/type.mli b/src/mo_types/type.mli index ed1410e2a36..80a98af86cc 100644 --- a/src/mo_types/type.mli +++ b/src/mo_types/type.mli @@ -66,7 +66,6 @@ and kind = (* Function sorts *) val is_shared_sort : 'a shared -> bool -val is_promising : control -> bool (* Short-hands *) @@ -207,6 +206,14 @@ val open_binds : bind list -> typ list module Env : Env.S with type key = string + +(* Scope bindings *) + +val scope_var : var +val scope_bound : typ +val scope_bind : bind + + (* Pretty printing *) val string_of_obj_sort : obj_sort -> string From 5f3c1d85987ef9cea8adbb0a7dcb89d79295b695 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 21 Jan 2020 14:22:01 +0000 Subject: [PATCH 0978/1176] unbreak the build --- src/mo_frontend/typing.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 846ce21e8bf..104a8265ba7 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -414,7 +414,7 @@ and check_typ_binds_acyclic env typ_binds cs ts = in chase 0 [] c in List.iter2 chase typ_binds cs -and check_typ_bind_sorts env typs tbs = +and check_typ_bind_sorts env tbs = (* assert, don't error, since this should be a syntactic invariant of parsing *) List.iteri (fun i tb -> assert (i == 0 || (tb.T.sort = T.Type))) tbs; @@ -437,7 +437,7 @@ and check_typ_binds env typ_binds : T.con list * T.bind list * Scope.typ_env * S T.sort = typ_bind.it.sort.it; T.bound = check_typ pre_env' typ_bind.it.bound }) typ_binds in - check_typ_bind_sorts env typ_binds; + check_typ_bind_sorts env tbs; let ts = List.map (fun tb -> tb.T.bound) tbs in check_typ_binds_acyclic env typ_binds cs ts; let ks = List.map (fun t -> T.Abs ([], t)) ts in From 9b3a03b08c563ecba6e5822c363c5331b793261a Mon Sep 17 00:00:00 2001 From: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> Date: Tue, 21 Jan 2020 15:50:55 +0100 Subject: [PATCH 0979/1176] Stores all paths in the ide server as absolute paths (#1143) * Stores all paths in the ide server as absolute paths * accepts the base to use for make_absolute --- src/languageServer/debug.ml | 2 + src/languageServer/declaration_index.ml | 61 +++++++++++++++++------- src/languageServer/declaration_index.mli | 5 +- src/languageServer/languageServer.ml | 7 ++- src/lib/lib.ml | 4 ++ src/lib/lib.mli | 2 + src/pipeline/resolve_import.ml | 21 ++++++-- src/pipeline/resolve_import.mli | 12 ++++- 8 files changed, 88 insertions(+), 26 deletions(-) create mode 100644 src/languageServer/debug.ml diff --git a/src/languageServer/debug.ml b/src/languageServer/debug.ml new file mode 100644 index 00000000000..d3f9979252e --- /dev/null +++ b/src/languageServer/debug.ml @@ -0,0 +1,2 @@ +let logger : (string -> unit) ref = ref ignore +let log : string -> unit = fun msg -> !logger msg diff --git a/src/languageServer/declaration_index.ml b/src/languageServer/declaration_index.ml index ddfeb62f4a7..6a43e549e18 100644 --- a/src/languageServer/declaration_index.ml +++ b/src/languageServer/declaration_index.ml @@ -51,27 +51,50 @@ let name_of_ide_decl (d : ide_decl) : string = | TypeDecl ty -> ty.name module Index = Map.Make(String) -type t = ide_decl list Index.t -type path = string +type declaration_index = { + modules: ide_decl list Index.t; + actors: ide_decl list Index.t; + package_map: Pipeline.ResolveImport.package_map; + (* TODO: Add the mapping for IC urls here *) + } +type t = declaration_index +let add_module : string -> ide_decl list -> declaration_index -> declaration_index = + fun path decls ix -> { ix with modules = Index.add path decls ix.modules} + let lookup_module - (path : path) + (path : string) (index : t) : ide_decl list option = let open Pipeline.URL in + let make_absolute = Lib.FilePath.make_absolute (Sys.getcwd ()) in match parse path with - | Ok (Relative path) -> Index.find_opt path index + | Ok (Relative path) -> + Index.find_opt (make_absolute path) index.modules | Ok (Package (pkg, path)) -> Option.bind - (Flags.M.find_opt pkg !Flags.package_urls) + (Flags.M.find_opt pkg index.package_map) (fun pkg_path -> - Index.find_opt (Filename.concat pkg_path path) index) - | Ok Prim -> - Index.find_opt "@prim" index + Index.find_opt + (make_absolute (Filename.concat pkg_path path)) + index.modules) + | Ok Prim -> Index.find_opt "@prim" index.modules + | Ok (Ic _ | IcAlias _) -> (* TODO *) None | Error _ -> None - | _ -> assert false -let empty : t = Index.empty +let empty : unit -> t = fun _ -> + let open Pipeline.ResolveImport in + let resolved_flags = + Diag.run + (resolve_flags + { package_urls = !Flags.package_urls; + actor_aliases = !Flags.actor_aliases; + actor_idl_path = !Flags.actor_idl_path; + }) in + { modules = Index.empty; + actors = Index.empty; + package_map = resolved_flags.packages + } module PatternMap = Map.Make(String) type pattern_map = Source.region PatternMap.t @@ -93,8 +116,9 @@ let string_of_list f xs = |> String.concat "; " |> fun x -> "[ " ^ x ^ " ]" -let string_of_index index = - Index.bindings index +let string_of_index : declaration_index -> string = + fun index -> + Index.bindings index.modules |> string_of_list (fun (path, decls) -> path @@ -167,7 +191,7 @@ let populate_definitions TypeDecl { typ with definition = type_definition } in let opt_lib = List.find_opt - (fun lib -> String.equal path lib.note) + (fun lib -> String.equal path (Lib.FilePath.make_absolute (Sys.getcwd ()) lib.note)) libs in match opt_lib with | None -> decls @@ -182,7 +206,12 @@ let make_index_inner logger vfs entry_points : t Diag.result = |> Diag.map (fun (libs, _, scope) -> Type.Env.fold (fun path ty acc -> - Index.add + let path = + if path = "@prim" then + path + else + Lib.FilePath.make_absolute (Sys.getcwd ()) path in + add_module path (ty |> read_single_module_lib @@ -190,9 +219,9 @@ let make_index_inner logger vfs entry_points : t Diag.result = |> populate_definitions libs path) acc) scope.Scope.lib_env - Index.empty) + (empty ())) let make_index logger vfs entry_points : t Diag.result = (* TODO(Christoph): Actually handle errors here *) try make_index_inner logger vfs entry_points - with _ -> Diag.return Index.empty + with _ -> Diag.return (empty ()) diff --git a/src/languageServer/declaration_index.mli b/src/languageServer/declaration_index.mli index fb9fe1fd66d..46d0ffc3868 100644 --- a/src/languageServer/declaration_index.mli +++ b/src/languageServer/declaration_index.mli @@ -2,7 +2,7 @@ open Source open Mo_types type t -val empty : t +val empty : unit -> t val string_of_index : t -> string type value_decl = { @@ -24,7 +24,6 @@ type ide_decl = val string_of_ide_decl : ide_decl -> string val name_of_ide_decl : ide_decl -> string -type path = string -val lookup_module : path -> t -> ide_decl list option +val lookup_module : string -> t -> ide_decl list option val make_index : (string -> string -> unit) -> Vfs.t -> string list -> t Diag.result diff --git a/src/languageServer/languageServer.ml b/src/languageServer/languageServer.ml index 49cd2cfdc05..3d3ff4b4d2f 100644 --- a/src/languageServer/languageServer.ml +++ b/src/languageServer/languageServer.ml @@ -1,3 +1,4 @@ +open Mo_config module Lsp_j = Lsp.Lsp_j module Lsp_t = Lsp.Lsp_t @@ -95,6 +96,10 @@ let start entry_point debug = open_out "/dev/null" in let log_to_file = Channel.log_to_file oc in let _ = log_to_file "entry_point" entry_point in + let _ = Flags.M.iter + (fun k v -> log_to_file "package" (Printf.sprintf "%s => %s" k v)) + !Flags.package_urls in + let _ = Debug.logger := log_to_file "debug" in let publish_diagnostics = Channel.publish_diagnostics oc in let clear_diagnostics = Channel.clear_diagnostics oc in let send_response = Channel.send_response oc in @@ -110,7 +115,7 @@ let start entry_point debug = let ix = match Declaration_index.make_index log_to_file !vfs [entry_point] with | Error(err) -> List.iter (fun e -> log_to_file "Error" (Diag.string_of_message e)) err; - Declaration_index.empty + Declaration_index.empty () | Ok((ix, _)) -> ix in ref ix in let rec loop () = diff --git a/src/lib/lib.ml b/src/lib/lib.ml index 2058b87b2b1..31974f4fd76 100644 --- a/src/lib/lib.ml +++ b/src/lib/lib.ml @@ -423,6 +423,10 @@ struct String.chop_prefix (normalise (base ^ "/")) (normalise path) + let make_absolute base path = + if not (Filename.is_relative path) + then path + else normalise (Filename.concat base path) end diff --git a/src/lib/lib.mli b/src/lib/lib.mli index 03a896128ba..77343e6e81b 100644 --- a/src/lib/lib.mli +++ b/src/lib/lib.mli @@ -166,4 +166,6 @@ sig * relative_to "foo/bar" "foo/bar/project" = Some "project" *) val relative_to : string -> string -> string option + + val make_absolute : string -> string -> string end diff --git a/src/pipeline/resolve_import.ml b/src/pipeline/resolve_import.ml index a3037419054..fb575a2eb03 100644 --- a/src/pipeline/resolve_import.ml +++ b/src/pipeline/resolve_import.ml @@ -231,17 +231,28 @@ type flags = { package_urls : package_urls; actor_aliases : actor_aliases; actor_idl_path : actor_idl_path; -} + } + +type resolved_flags = { + packages : package_map; + aliases : aliases; + actor_idl_path : actor_idl_path; + } + +let resolve_flags : flags -> resolved_flags Diag.result + = fun { actor_idl_path; package_urls; actor_aliases } -> + Diag.bind (resolve_packages package_urls) (fun packages -> + Diag.bind (resolve_aliases actor_aliases) (fun aliases -> + Diag.return { packages; aliases; actor_idl_path })) let resolve : flags -> Syntax.prog -> filepath -> resolved_imports Diag.result - = fun {actor_idl_path; package_urls; actor_aliases} p base -> - Diag.bind (resolve_packages package_urls) (fun (packages:package_map) -> - Diag.bind (resolve_aliases actor_aliases) (fun aliases -> + = fun flags p base -> + Diag.bind (resolve_flags flags) (fun { packages; aliases; actor_idl_path } -> Diag.with_message_store (fun msgs -> let base = if Sys.is_directory base then base else Filename.dirname base in let imported = ref RIM.empty in List.iter (resolve_import_string msgs base actor_idl_path aliases packages imported) (prog_imports p); Some (List.map (fun (rim,at) -> Source.(rim @@ at)) (RIM.bindings !imported)) ) - )) + ) diff --git a/src/pipeline/resolve_import.mli b/src/pipeline/resolve_import.mli index 63368ddfc66..5f263479c63 100644 --- a/src/pipeline/resolve_import.mli +++ b/src/pipeline/resolve_import.mli @@ -18,6 +18,16 @@ type flags = { package_urls : package_urls; actor_aliases : actor_aliases; actor_idl_path : actor_idl_path; -} + } + +type package_map = filepath Flags.M.t +type blob = string +type aliases = blob Flags.M.t +type resolved_flags = { + packages : package_map; + aliases : aliases; + actor_idl_path : actor_idl_path; + } +val resolve_flags : flags -> resolved_flags Diag.result val resolve : flags -> Syntax.prog -> filepath -> resolved_imports Diag.result From 5ce300ae89ecd8741f1520f0affe2fdb62334683 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 21 Jan 2020 14:51:02 +0000 Subject: [PATCH 0980/1176] fix nit --- src/mo_frontend/typing.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 104a8265ba7..37027dc5c0c 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -278,7 +278,7 @@ let rec infer_async_cap env sort cs tbs = | T.Shared _, _, _ -> assert false (* impossible given sugaring *) | _ -> { env with async = C.NullCap } -and check_AsyncCap env s at = +and check_AsyncCap env s at : T.typ * (T.con -> C.async_cap) = match env.async with | C.AwaitCap c | C.AsyncCap c -> T.Con(c, []), fun c' -> C.AwaitCap c' From 73e82da6d9e3fb647459ba3e58f9feeda6612148 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 21 Jan 2020 17:35:55 +0100 Subject: [PATCH 0981/1176] Stdlib: Re-export from prim, not redefine (#1144) no need to add another function invocation around these functions --- stdlib/src/blob.mo | 2 +- stdlib/src/debug.mo | 2 +- stdlib/src/int.mo | 18 +++++++++--------- stdlib/src/nat.mo | 36 +++++++++++++++++------------------- 4 files changed, 28 insertions(+), 30 deletions(-) diff --git a/stdlib/src/blob.mo b/stdlib/src/blob.mo index 541206f6392..adde3dacaee 100644 --- a/stdlib/src/blob.mo +++ b/stdlib/src/blob.mo @@ -1,4 +1,4 @@ import Prim "mo:prim"; module { - public func hash(x : Blob) : Word32 = Prim.hashBlob x; + public let hash = Prim.hashBlob; } diff --git a/stdlib/src/debug.mo b/stdlib/src/debug.mo index e2c51f5d93e..9d499a54a7e 100644 --- a/stdlib/src/debug.mo +++ b/stdlib/src/debug.mo @@ -1,4 +1,4 @@ import Prim "mo:prim"; module { - public func print(x : Text) = Prim.debugPrint x; + public let print = Prim.debugPrint; } diff --git a/stdlib/src/int.mo b/stdlib/src/int.mo index 456950d91ca..bdde8b111e6 100644 --- a/stdlib/src/int.mo +++ b/stdlib/src/int.mo @@ -2,7 +2,7 @@ import Prim "mo:prim"; import Prelude "prelude.mo"; module { - public func abs(x : Int) : Nat = Prim.abs x; + public let abs = Prim.abs; public func add(x : Int, y : Int) : Int { x + y; @@ -40,12 +40,12 @@ module { return if isNegative ("-" # text) else text; }; - public func fromInt8 (x : Int8): Int = Prim.int8ToInt x; - public func fromInt16(x : Int16): Int = Prim.int16ToInt x; - public func fromInt32(x : Int32): Int = Prim.int32ToInt x; - public func fromInt64(x : Int64): Int = Prim.int64ToInt x; - public func toInt8 (x : Int) : Int8 = Prim.intToInt8 x; - public func toInt16(x : Int) : Int16 = Prim.intToInt16 x; - public func toInt32(x : Int) : Int32 = Prim.intToInt32 x; - public func toInt64(x : Int) : Int64 = Prim.intToInt64 x; + public let fromInt8 = Prim.int8ToInt; + public let fromInt16 = Prim.int16ToInt; + public let fromInt32 = Prim.int32ToInt; + public let fromInt64 = Prim.int64ToInt; + public let toInt8 = Prim.intToInt8; + public let toInt16 = Prim.intToInt16; + public let toInt32 = Prim.intToInt32; + public let toInt64 = Prim.intToInt64; } diff --git a/stdlib/src/nat.mo b/stdlib/src/nat.mo index 9db8be1e94a..a44c6afc551 100644 --- a/stdlib/src/nat.mo +++ b/stdlib/src/nat.mo @@ -7,26 +7,24 @@ module { x + y; }; - public func toText(x : Nat) : Text { - Int.toText(x); - }; + public let toText : Nat -> Text = Int.toText; - public func fromWord8 (x : Word8): Nat = Prim.word8ToNat x; - public func fromWord16(x : Word16): Nat = Prim.word16ToNat x; - public func fromWord32(x : Word32): Nat = Prim.word32ToNat x; - public func fromWord64(x : Word64): Nat = Prim.word64ToNat x; - public func toWord8 (x : Nat) : Word8 = Prim.natToWord8 x; - public func toWord16(x : Nat) : Word16 = Prim.natToWord16 x; - public func toWord32(x : Nat) : Word32 = Prim.natToWord32 x; - public func toWord64(x : Nat) : Word64 = Prim.natToWord64 x; + public let fromWord8 = Prim.word8ToNat; + public let fromWord16 = Prim.word16ToNat; + public let fromWord32 = Prim.word32ToNat; + public let fromWord64 = Prim.word64ToNat; + public let toWord8 = Prim.natToWord8; + public let toWord16 = Prim.natToWord16; + public let toWord32 = Prim.natToWord32; + public let toWord64 = Prim.natToWord64; - public func fromNat8 (x : Nat8): Nat = Prim.nat8ToNat x; - public func fromNat16(x : Nat16): Nat = Prim.nat16ToNat x; - public func fromNat32(x : Nat32): Nat = Prim.nat32ToNat x; - public func fromNat64(x : Nat64): Nat = Prim.nat64ToNat x; - public func toNat8 (x : Nat) : Nat8 = Prim.natToNat8 x; - public func toNat16(x : Nat) : Nat16 = Prim.natToNat16 x; - public func toNat32(x : Nat) : Nat32 = Prim.natToNat32 x; - public func toNat64(x : Nat) : Nat64 = Prim.natToNat64 x; + public let fromNat8 = Prim.nat8ToNat; + public let fromNat16 = Prim.nat16ToNat; + public let fromNat32 = Prim.nat32ToNat; + public let fromNat64 = Prim.nat64ToNat; + public let toNat8 = Prim.natToNat8; + public let toNat16 = Prim.natToNat16; + public let toNat32 = Prim.natToNat32; + public let toNat64 = Prim.natToNat64; } From 216ec9b60f3acaac7d619b6ab4c8346c77c16f74 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 21 Jan 2020 17:06:08 +0000 Subject: [PATCH 0982/1176] improve await error message by naming async scopes (withoug affecting other binders; update tests --- src/mo_def/syntax.ml | 14 +++++++------- src/mo_frontend/parser.mly | 6 +++--- src/mo_frontend/typing.ml | 4 ++-- test/fail/ok/asyncret2.tc.ok | 2 +- test/fail/ok/illegal-await.tc.ok | 10 +++++----- test/run-drun/ok/scope-example-implicit.tc.ok | 4 ++-- test/run-drun/ok/scope-example.tc.ok | 4 ++-- 7 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/mo_def/syntax.ml b/src/mo_def/syntax.ml index d413d432128..734fb9011e9 100644 --- a/src/mo_def/syntax.ml +++ b/src/mo_def/syntax.ml @@ -256,25 +256,25 @@ let scope_typ region = at = region; note = Type.Pre }) -let scope_bind() = - { var = Type.scope_var @@ no_region; +let scope_bind var = + { var = (Type.scope_var ^ var) @@ no_region; sort = Type.Scope @@ no_region; bound = PrimT "Any" @! no_region } @= no_region -let ensure_scope_bind tbs = +let ensure_scope_bind var tbs = match tbs with | tb::_ when tb.it.sort.it = Type.Scope -> tbs | _ -> - scope_bind()::tbs + scope_bind var::tbs let funcT(sort, tbs, t1, t2) = match sort.it, t2.it with | Type.Local, AsyncT _ -> - FuncT(sort, ensure_scope_bind tbs, t1, t2) + FuncT(sort, ensure_scope_bind "" tbs, t1, t2) | Type.Shared _, _ -> - FuncT(sort, ensure_scope_bind tbs, t1, t2) + FuncT(sort, ensure_scope_bind "" tbs, t1, t2) | _ -> FuncT(sort, tbs, t1, t2) @@ -282,7 +282,7 @@ let funcE(f, s, tbs, p, t_opt, e) = match s.it, t_opt, e with | Type.Local, Some { it = AsyncT _; _}, {it = AsyncE _; _} | Type.Shared _, _, _ -> - FuncE(f, s, ensure_scope_bind tbs, p, t_opt, e) + FuncE(f, s, ensure_scope_bind "" tbs, p, t_opt, e) | _ -> FuncE(f, s, tbs, p, t_opt, e) diff --git a/src/mo_frontend/parser.mly b/src/mo_frontend/parser.mly index 8e094898dba..d66e97ea268 100644 --- a/src/mo_frontend/parser.mly +++ b/src/mo_frontend/parser.mly @@ -444,7 +444,7 @@ exp_nondec(B) : | RETURN e=exp(ob) { RetE(e) @? at $sloc } | ASYNC e=exp(bl) - { AsyncE(scope_bind(), e) @? at $sloc } + { AsyncE(scope_bind (anon "async" (at $sloc)), e) @? at $sloc } | AWAIT e=exp(bl) { AwaitE(e) @? at $sloc } | ASSERT e=exp(bl) @@ -633,15 +633,15 @@ dec_nonvar : { (* This is a hack to support local func declarations that return a computed async. These should be defined using RHS syntax EQ e to avoid the implicit AsyncE introduction around bodies declared as blocks *) + let named, x = xf "func" $sloc in let e = match fb with | (false, e) -> e (* body declared as EQ e *) | (true, e) -> (* body declared as immediate block *) match t with | Some {it = AsyncT _; _} -> - AsyncE(scope_bind(), e) @? e.at + AsyncE(scope_bind x.it, e) @? e.at | _ -> e in - let named, x = xf "func" $sloc in let_or_exp named x (funcE(x.it, sp, tps, p, t, e)) (at $sloc) } | s=obj_sort_opt CLASS xf=typ_id_opt tps=typ_params_opt p=pat_param t=return_typ? cb=class_body diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 37027dc5c0c..04f1a5049eb 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -1039,8 +1039,8 @@ and infer_exp'' env exp : T.typ = (try let (t2, t3) = T.as_async_sub t0 t1 in if not (T.eq t0 t2) then - error env exp.at "ill-scoped await: expecting index %s, found index %s" - (T.string_of_typ t0) (T.string_of_typ t2); + error env exp.at "ill-scoped await: expected async type from current scope %s, found async type from other scope %s" + (T.string_of_typ_expand t0) (T.string_of_typ_expand t2); t3 with Invalid_argument _ -> error env exp1.at "expected async type, but expression has type\n %s" diff --git a/test/fail/ok/asyncret2.tc.ok b/test/fail/ok/asyncret2.tc.ok index 65fa3575b43..5eb51764c05 100644 --- a/test/fail/ok/asyncret2.tc.ok +++ b/test/fail/ok/asyncret2.tc.ok @@ -1,4 +1,4 @@ asyncret2.mo:1.54-1.57: type error, expression of type - async<@/3> Int + async<@call3> Int cannot produce expected type Int diff --git a/test/fail/ok/illegal-await.tc.ok b/test/fail/ok/illegal-await.tc.ok index 165028adeda..324e2c5ba1b 100644 --- a/test/fail/ok/illegal-await.tc.ok +++ b/test/fail/ok/illegal-await.tc.ok @@ -1,5 +1,5 @@ -illegal-await.mo:3.30-3.37: type error, ill-scoped await: expecting index @/2, found index @ -illegal-await.mo:12.32-12.40: type error, ill-scoped await: expecting index @/4, found index @/3 -illegal-await.mo:13.32-13.40: type error, ill-scoped await: expecting index @/5, found index @/3 -illegal-await.mo:24.7-24.14: type error, ill-scoped await: expecting index @/8, found index @/6 -illegal-await.mo:33.5-33.12: type error, ill-scoped await: expecting index @/9, found index @/1 +illegal-await.mo:3.30-3.37: type error, ill-scoped await: expected async type from current scope @anon-async-3.22, found async type from other scope @ +illegal-await.mo:12.32-12.40: type error, ill-scoped await: expected async type from current scope @anon-async-12.25, found async type from other scope @anon-async-11.10 +illegal-await.mo:13.32-13.40: type error, ill-scoped await: expected async type from current scope @anon-async-13.25, found async type from other scope @anon-async-11.10 +illegal-await.mo:24.7-24.14: type error, ill-scoped await: expected async type from current scope @anon-async-23.11, found async type from other scope @anon-async-21.10 +illegal-await.mo:33.5-33.12: type error, ill-scoped await: expected async type from current scope @Rec, found async type from other scope @/1 diff --git a/test/run-drun/ok/scope-example-implicit.tc.ok b/test/run-drun/ok/scope-example-implicit.tc.ok index bfc16f39e94..15f8e4dc915 100644 --- a/test/run-drun/ok/scope-example-implicit.tc.ok +++ b/test/run-drun/ok/scope-example-implicit.tc.ok @@ -1,4 +1,4 @@ scope-example-implicit.mo:10.12-10.19: type error, expression of type - async<@/7> Int + async<@anon-async-8.12> Int cannot produce expected type - async<@/5> Int + async<@f> Int diff --git a/test/run-drun/ok/scope-example.tc.ok b/test/run-drun/ok/scope-example.tc.ok index 00366a48ebd..921638355a6 100644 --- a/test/run-drun/ok/scope-example.tc.ok +++ b/test/run-drun/ok/scope-example.tc.ok @@ -1,4 +1,4 @@ scope-example.mo:12.13-12.27: type error, expression of type - async<@/7> Int + async<@anon-async-10.12> Int cannot produce expected type - async<@/5> Int + async<@anon-async-6.60> Int From 210943e4feaa55a808611e7f7a15cf74fcff132f Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 21 Jan 2020 23:02:18 +0100 Subject: [PATCH 0983/1176] Move docTable module from stdlib to PX (#1147) * Move docTable module from stdlib to PX as per https://dfinity.slack.com/archives/CPL67E7MX/p1579625927031000 * fix import --- stdlib/doc/Makefile | 2 +- stdlib/{ => examples/produce-exchange}/src/docTable.mo | 4 ++-- stdlib/examples/produce-exchange/src/serverModel.mo | 2 +- stdlib/examples/produce-exchange/src/serverModelTypes.mo | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename stdlib/{ => examples/produce-exchange}/src/docTable.mo (99%) diff --git a/stdlib/doc/Makefile b/stdlib/doc/Makefile index 4ccd4b566c8..7afd237d0d7 100644 --- a/stdlib/doc/Makefile +++ b/stdlib/doc/Makefile @@ -37,7 +37,7 @@ $(OUTDIR)/%.html: $(OUTDIR)/%.md $(PANDOC) -f gfm $^ > $@ -DOCS = README prelude array buf option result hash list assocList trie trieSet docTable +DOCS = README prelude array buf option result hash list assocList trie trieSet # Markdown documentation, extracted from the source directory docMd: $(patsubst %,$(OUTDIR)/%.md,$(DOCS)) | $(OUTDIR) diff --git a/stdlib/src/docTable.mo b/stdlib/examples/produce-exchange/src/docTable.mo similarity index 99% rename from stdlib/src/docTable.mo rename to stdlib/examples/produce-exchange/src/docTable.mo index 99d7e0844f1..0944ebec5d5 100644 --- a/stdlib/src/docTable.mo +++ b/stdlib/examples/produce-exchange/src/docTable.mo @@ -1,6 +1,6 @@ -import Hash "hash.mo"; +import Hash "mo:stdlib/hash.mo"; -import Trie "trie.mo"; +import Trie "mo:stdlib/trie.mo"; module { /** diff --git a/stdlib/examples/produce-exchange/src/serverModel.mo b/stdlib/examples/produce-exchange/src/serverModel.mo index da341de6ef0..fa6e902bba4 100644 --- a/stdlib/examples/produce-exchange/src/serverModel.mo +++ b/stdlib/examples/produce-exchange/src/serverModel.mo @@ -12,8 +12,8 @@ import Trie = "mo:stdlib/trie.mo"; import Iter = "mo:stdlib/iter.mo"; import Array = "mo:stdlib/array.mo"; -import DT = "mo:stdlib/docTable.mo"; import Result = "mo:stdlib/result.mo"; +import DT = "docTable.mo"; module { diff --git a/stdlib/examples/produce-exchange/src/serverModelTypes.mo b/stdlib/examples/produce-exchange/src/serverModelTypes.mo index c60759ce8d1..188390ff023 100644 --- a/stdlib/examples/produce-exchange/src/serverModelTypes.mo +++ b/stdlib/examples/produce-exchange/src/serverModelTypes.mo @@ -1,6 +1,6 @@ import T = "serverTypes.mo"; import Trie = "mo:stdlib/trie.mo"; -import DocTable = "mo:stdlib/docTable.mo"; +import DocTable = "docTable.mo"; module { From 1aeaf835ac1530dcf29b489f6acecb97e20af280 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 22 Jan 2020 12:48:47 +0100 Subject: [PATCH 0984/1176] Make hydra comment with the performance delta (#1151) --- ci-pr.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ci-pr.nix b/ci-pr.nix index bb1617ca3c3..e5686e133d0 100644 --- a/ci-pr.nix +++ b/ci-pr.nix @@ -30,5 +30,8 @@ import ./ci.nix { inherit src; } // nixpkgs.lib.optionalAttrs (base != null) { diff-stats $baseStats $prStats > $out/report; mkdir -p $out/nix-support echo "report perf-delta $out report" >> $out/nix-support/hydra-build-products + echo '{{{! comment:edit-one }}}' >> $out/comment + cat $out/report >> $out/comment + echo "comment manifest $out/comment" >> $out/nix-support/hydra-build-products ''; } From 3f13d924df804be1fb2c0d5a3e8fc5e32d12b69c Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 22 Jan 2020 14:14:53 +0100 Subject: [PATCH 0985/1176] Backend: Resolve constant DotE expressions (#1145) This makes sure hat module can re-rexport members from modules, as done in #1144, without breaking direct calls. --- src/codegen/compile.ml | 9 +++++++++ test/run/static-call-reexport.mo | 20 ++++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 test/run/static-call-reexport.mo diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 458926797db..9876366c7cd 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -5068,6 +5068,8 @@ module AllocHow = struct List.for_all is_const_dec ds && is_const_exp e | NewObjE (Type.(Object | Module), _, t) -> Object.is_immutable t + | PrimE (DotPrim n, [e]) -> + is_const_exp e | _ -> false and is_const_dec dec = match dec.it with @@ -6734,6 +6736,13 @@ and compile_const_exp env pre_ae exp : Const.t * (E.t -> VarEnv.t -> unit) = in f.it.name, st) fs in (Const.Obj static_fs, fun _ _ -> ()) + | PrimE (DotPrim name, [e]) -> + let (object_ct, fill) = compile_const_exp env pre_ae e in + let fs = match object_ct with + | Const.Obj fs -> fs + | _ -> fatal "compile_const_exp/DotE: not a static object" in + let member_ct = List.assoc name fs in + (member_ct, fill) | _ -> assert false and compile_const_decs env pre_ae decs : (VarEnv.t -> VarEnv.t) * (E.t -> VarEnv.t -> unit) = diff --git a/test/run/static-call-reexport.mo b/test/run/static-call-reexport.mo new file mode 100644 index 00000000000..cbd64adbad3 --- /dev/null +++ b/test/run/static-call-reexport.mo @@ -0,0 +1,20 @@ +// This tests that modules can re-rexport functions and still +// get direct calls + +func go () { + let objA1 = module { public func foobar1() = () }; + let objB1 = module { public let foobar1 = objA1.foobar1; }; + objB1.foobar1(); +}; + +let objA2 = module { public func foobar2() = () }; +let objB2 = module { public let foobar2 = objA2.foobar2; }; +objB2.foobar2(); + +// CHECK: func $go +// CHECK-NOT: call_indirect +// CHECK: call $foobar1 + +// CHECK: func $start +// CHECK-NOT: call_indirect +// CHECK: call $foobar2 From aef5f2153b3b354bc8e1a57f2a8aca2dd3265643 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 22 Jan 2020 14:33:35 +0100 Subject: [PATCH 0986/1176] Fix IDL encoding of positive ints (#1149) One typo (don't confuse signed and unsigned). One bug (need to add extra bit to positive ints). LEB rountrip tests added to test_rts.c. --- rts/bigint.c | 26 ++---- rts/test_leb128.c | 9 +- rts/test_rts.c | 83 +++++++++++++++++-- src/codegen/compile.ml | 10 ++- test/run-drun/idl-buf-size-bug.mo | 15 ++++ test/run-drun/ok/idl-buf-size-bug.drun-run.ok | 2 + .../ok/idl-buf-size-bug.ic-stub-run.ok | 6 ++ 7 files changed, 117 insertions(+), 34 deletions(-) create mode 100644 test/run-drun/idl-buf-size-bug.mo create mode 100644 test/run-drun/ok/idl-buf-size-bug.drun-run.ok create mode 100644 test/run-drun/ok/idl-buf-size-bug.ic-stub-run.ok diff --git a/rts/bigint.c b/rts/bigint.c index c05eb223387..7d1f6ff9b47 100644 --- a/rts/bigint.c +++ b/rts/bigint.c @@ -265,19 +265,19 @@ export int bigint_leb128_size(as_ptr n) { return ((x + 6) / 7); // divide by 7, round up } -void bigint_leb128_encode_go(mp_int *tmp, unsigned char *buf) { +void bigint_leb128_encode_go(mp_int *tmp, unsigned char *buf, bool add_bit) { // now the number should be positive if (mp_isneg(tmp)) bigint_trap(); while (true) { buf[0] = (unsigned char)(mp_get_u32(tmp)); // get low bits CHECK(mp_div_2d(tmp, 7, tmp, NULL)); - if (mp_iszero(tmp)) { - // we are done. high bit should be cleared anyways - return; - } else { + if (!mp_iszero(tmp) || add_bit && (buf[0] & 1<<6)) { // more bytes to come, set high bit and continue buf[0] |= 1<<7; buf++; + } else { + // we are done. high bit should be cleared anyways + return; } } } @@ -285,18 +285,9 @@ void bigint_leb128_encode_go(mp_int *tmp, unsigned char *buf) { export void bigint_leb128_encode(as_ptr n, unsigned char *buf) { mp_int tmp; CHECK(mp_init_copy(&tmp, BIGINT_PAYLOAD(n))); - bigint_leb128_encode_go(&tmp, buf); + bigint_leb128_encode_go(&tmp, buf, false); } - -int leb128_encoding_size(unsigned char *buf) { - // zoom to the end - int i = 0; - while (buf[i] & (1<<7)) i++; - return i+1; -} - - export int bigint_2complement_bits(as_ptr n) { if (mp_isneg(BIGINT_PAYLOAD(n))) { mp_int tmp; @@ -324,9 +315,10 @@ export void bigint_sleb128_encode(as_ptr n, unsigned char *buf) { CHECK(mp_init(&big)); CHECK(mp_2expt(&big, 7*bytes)); CHECK(mp_add(&tmp, &big, &tmp)); + bigint_leb128_encode_go(&tmp, buf, false); + } else { + bigint_leb128_encode_go(&tmp, buf, true); } - - bigint_leb128_encode_go(&tmp, buf); } /* (S)LEB128 Decoding */ diff --git a/rts/test_leb128.c b/rts/test_leb128.c index 770f3dbcfe7..bc6d3bd8c49 100644 --- a/rts/test_leb128.c +++ b/rts/test_leb128.c @@ -18,12 +18,12 @@ as_ptr alloc_words(size_t n) { return alloc_bytes(sizeof(uint32_t) * n); }; -void rts_trap() { - printf("RTS trap\n"); +void rts_trap(const char* str, size_t n) { + printf("RTS trap: %.*s\n", (int)n, str); abort(); } -void bigint_trap() { - printf("Bigint trap\n"); +void bigint_trap(const char* str, size_t n) { + printf("Bigint trap: %.*s\n", (int)n, str); abort(); } @@ -87,4 +87,3 @@ int main(int argc, char** argv) { return 0; } - diff --git a/rts/test_rts.c b/rts/test_rts.c index e60830443f1..1d446bc3245 100644 --- a/rts/test_rts.c +++ b/rts/test_rts.c @@ -4,7 +4,9 @@ #include #include #include + #include "rts.h" +#include "buf.h" typedef intptr_t as_ptr; @@ -18,12 +20,12 @@ as_ptr alloc_words(size_t n) { return alloc_bytes(sizeof(size_t) * n); }; -void rts_trap() { - printf("RTS trap\n"); +void rts_trap(const char* str, size_t n) { + printf("RTS trap: %.*s\n", (int)n, str); abort(); } -void bigint_trap() { - printf("Bigint trap\n"); +void bigint_trap(const char* str, size_t n) { + printf("Bigint trap: %.*s\n", (int)n, str); exit(1); } @@ -39,6 +41,43 @@ void assert(bool check, const char *fmt, ...) { } } +extern as_ptr bigint_of_word32(uint32_t b); +extern as_ptr bigint_sub(as_ptr a, as_ptr b); +extern as_ptr bigint_add(as_ptr a, as_ptr b); +extern as_ptr bigint_mul(as_ptr a, as_ptr b); +extern as_ptr bigint_pow(as_ptr a, as_ptr b); +extern as_ptr bigint_neg(as_ptr a); +extern bool bigint_eq(as_ptr a, as_ptr b); +extern int bigint_leb128_size(as_ptr n); +extern void bigint_leb128_encode(as_ptr n, unsigned char *buf); +extern as_ptr bigint_leb128_decode(buf *buf); +extern int bigint_sleb128_size(as_ptr n); +extern void bigint_sleb128_encode(as_ptr n, unsigned char *buf); +extern as_ptr bigint_sleb128_decode(buf *buf); + + +void test_bigint_leb128(as_ptr n) { + unsigned char b[100]; + int s = bigint_leb128_size(n); + bigint_leb128_encode(n, b); + buf buf = { b, b + 100 }; + as_ptr n2 = bigint_leb128_decode(&buf); + + printf("roundtrip: %s ", bigint_eq(n, n2) ? "ok" : (ret = EXIT_FAILURE, "not ok")); + printf("size: %s\n", (buf.p - b) == s ? "ok" : (ret = EXIT_FAILURE, "not ok")); +} + +void test_bigint_sleb128(as_ptr n) { + unsigned char b[100]; + int s = bigint_sleb128_size(n); + bigint_sleb128_encode(n, b); + buf buf = { b, b + 100 }; + as_ptr n2 = bigint_sleb128_decode(&buf); + + printf("roundtrip: %s ", bigint_eq(n, n2) ? "ok" : (ret = EXIT_FAILURE, "not ok")); + printf("size: %s\n", (buf.p - b) == s ? "ok" : (ret = EXIT_FAILURE, "not ok")); +} + int main () { printf("Motoko RTS test suite\n"); @@ -48,11 +87,6 @@ int main () { */ printf("Testing BigInt...\n"); - extern as_ptr bigint_of_word32(uint32_t b); - extern as_ptr bigint_mul(as_ptr a, as_ptr b); - extern as_ptr bigint_pow(as_ptr a, as_ptr b); - extern bool bigint_eq(as_ptr a, as_ptr b); - printf("70**32 = 70**31 * 70: %s\n", bigint_eq( bigint_pow(bigint_of_word32(70), bigint_of_word32(32)), @@ -61,6 +95,37 @@ int main () { bigint_of_word32(70) )) ? "ok" : (ret = EXIT_FAILURE, "not ok")); + /* + * Testing BigInt (s)leb128 encoding + */ + as_ptr one = bigint_of_word32(1); + as_ptr two = bigint_of_word32(2); + for (uint32_t i = 0; i < 100; i++){ + as_ptr two_pow_i = bigint_pow(two, bigint_of_word32(i)); + printf("leb128 2^%u-1: ", i); + test_bigint_leb128(bigint_sub(two_pow_i, one)); + printf("leb128 2^%u: ", i); + test_bigint_leb128(two_pow_i); + printf("leb128 2^%u+1: ", i); + test_bigint_leb128(bigint_add(two_pow_i, one)); + } + + for (uint32_t i = 0; i < 100; i++){ + as_ptr two_pow_i = bigint_pow(two, bigint_of_word32(i)); + printf("sleb128 2^%u-1: ", i); + test_bigint_sleb128(bigint_sub(two_pow_i, one)); + printf("sleb128 2^%u: ", i); + test_bigint_sleb128(two_pow_i); + printf("sleb128 2^%u+1: ", i); + test_bigint_sleb128(bigint_add(two_pow_i, one)); + printf("sleb128 -2^%u-1: ", i); + test_bigint_sleb128(bigint_neg(bigint_sub(two_pow_i, one))); + printf("sleb128 -2^%u: ", i); + test_bigint_sleb128(bigint_neg(two_pow_i)); + printf("sleb128 -2^%u+1: ", i); + test_bigint_sleb128(bigint_neg(bigint_add(two_pow_i, one))); + } + /* * Testing UTF8 */ diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 9876366c7cd..6924dadfbfa 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -2038,7 +2038,9 @@ module MakeCompact (Num : BigNumType) : BigNumType = struct extend ^^ compile_shrS_const 1l ^^ set_x ^^ I32Leb.compile_store_to_data_buf_unsigned env get_x get_buf ) - (fun env -> G.i Drop ^^ get_buf ^^ get_x ^^ Num.compile_store_to_data_buf_unsigned env) + (fun env -> + G.i Drop ^^ + get_buf ^^ get_x ^^ Num.compile_store_to_data_buf_unsigned env) env let compile_store_to_data_buf_signed env = @@ -2051,7 +2053,9 @@ module MakeCompact (Num : BigNumType) : BigNumType = struct extend ^^ compile_shrS_const 1l ^^ set_x ^^ I32Leb.compile_store_to_data_buf_signed env get_x get_buf ) - (fun env -> G.i Drop ^^ get_buf ^^ get_x ^^ Num.compile_store_to_data_buf_signed env) + (fun env -> + G.i Drop ^^ + get_buf ^^ get_x ^^ Num.compile_store_to_data_buf_signed env) env let compile_data_size_unsigned env = @@ -2071,7 +2075,7 @@ module MakeCompact (Num : BigNumType) : BigNumType = struct extend ^^ compile_shrS_const 1l ^^ set_x ^^ I32Leb.compile_sleb128_size get_x ) - (fun env -> Num.compile_data_size_unsigned env) + (fun env -> Num.compile_data_size_signed env) env let from_signed_word32 env = diff --git a/test/run-drun/idl-buf-size-bug.mo b/test/run-drun/idl-buf-size-bug.mo new file mode 100644 index 00000000000..842e26c6c9b --- /dev/null +++ b/test/run-drun/idl-buf-size-bug.mo @@ -0,0 +1,15 @@ +import Prim "mo:prim"; +actor { + public func match (b : Int) : async () { + assert (switch b { + case (4_619_372_036_854_775_805) true; + case _ false + }) + }; + + public func do () : async () { + await match (4_619_372_036_854_775_805); + } +}; + +//CALL ingress do 0x4449444C0000 diff --git a/test/run-drun/ok/idl-buf-size-bug.drun-run.ok b/test/run-drun/ok/idl-buf-size-bug.drun-run.ok new file mode 100644 index 00000000000..91c74b55809 --- /dev/null +++ b/test/run-drun/ok/idl-buf-size-bug.drun-run.ok @@ -0,0 +1,2 @@ +ingress(0) System +ingress(1) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-buf-size-bug.ic-stub-run.ok b/test/run-drun/ok/idl-buf-size-bug.ic-stub-run.ok new file mode 100644 index 00000000000..36f2cf59629 --- /dev/null +++ b/test/run-drun/ok/idl-buf-size-bug.ic-stub-run.ok @@ -0,0 +1,6 @@ +→ create +← completed: canister-id = 0x2a01 +→ install +← completed +→ update do(0x4449444c0000) +← completed: 0x4449444c0000 From f8609165e094ecc97588082cd137e7bd325bcdfe Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 22 Jan 2020 15:14:58 +0100 Subject: [PATCH 0987/1176] perf-delta: Include one decimal point (#1152) as suggested by @ggreif in https://github.com/dfinity-lab/motoko/pull/1149#issuecomment-577178020 --- test/diff-stats.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/diff-stats.pl b/test/diff-stats.pl index 74f91de5726..b4b8744ccad 100755 --- a/test/diff-stats.pl +++ b/test/diff-stats.pl @@ -80,7 +80,7 @@ sub comma_and { push @clauses, sprintf "%d tests improved", $improved if $improved; push @clauses, sprintf "%d tests are new", $new if $new; push @clauses, sprintf "%d tests are removed", $missing if $missing; - push @clauses, sprintf "the mean change is %+.0f%%.\n", (($geometric_mean - 1) * 100); + push @clauses, sprintf "the mean change is %+.1f%%.\n", (($geometric_mean - 1) * 100); printf "In terms of %s, %s", $group, comma_and(@clauses); } else { printf "In terms of %s, no changes are observed in %d tests.\n", $group, $total; From 0cf39d4f83acbc47b80dba48a5b6c7d57092d91c Mon Sep 17 00:00:00 2001 From: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> Date: Wed, 22 Jan 2020 15:54:49 +0100 Subject: [PATCH 0988/1176] Require imports to be specified without file extension (#1130) * requires imports to be specified without file extension * fixes print-deps tests * fixes tests that got caught up in the regex replace * don't require trailing slash for dir imports * reverts accidental modification * Makes the IDE use the same extension resolution as pipeline * fixes more `.mo` import leftovers --- design/DFX-Interface.md | 1 + samples/ListClient.mo | 2 +- samples/app/client.mo | 2 +- samples/app/main.mo | 4 +- samples/app/server.mo | 4 +- src/languageServer/completion.ml | 4 +- src/languageServer/completion_test.ml | 6 +-- src/languageServer/declaration_index.ml | 20 +++++++-- src/languageServer/declaration_index.mli | 2 +- src/languageServer/definition.ml | 11 +++-- src/languageServer/hover.ml | 4 +- src/languageServer/source_file.ml | 6 ++- src/languageServer/source_file_tests.ml | 16 ++++---- src/pipeline/resolve_import.ml | 41 ++++++++++++++----- src/pipeline/resolve_import.mli | 3 ++ src/pipeline/resolve_import_test.ml | 25 +++++++++++ stdlib/examples/actorspec/demo/Demo.mo | 2 +- stdlib/examples/actorspec/src/ActorSpec.mo | 8 ++-- .../examples/produce-exchange/src/docTable.mo | 4 +- .../produce-exchange/src/serverActor.mo | 20 ++++----- .../produce-exchange/src/serverLang.mo | 4 +- .../produce-exchange/src/serverModel.mo | 33 ++++++++------- .../produce-exchange/src/serverModelTypes.mo | 6 +-- .../produce-exchange/test/evalBulk.mo | 10 ++--- .../test/loadWorkloadAndQueryBig.mo | 8 ++-- .../test/producerRemInventory.mo | 10 ++--- .../produce-exchange/test/profileActor.mo | 4 +- .../test/profileFastCounts.mo | 6 +-- .../test/retailerReserveMany.mo | 10 ++--- .../test/simpleSetupAndQuery.mo | 10 ++--- stdlib/examples/rx/src/Observable.mo | 4 +- stdlib/examples/rx/src/Observer.mo | 2 +- stdlib/examples/rx/src/Rx.mo | 8 ++-- stdlib/examples/rx/test/RxTest.mo | 4 +- stdlib/src/assocList.mo | 2 +- stdlib/src/buf.mo | 6 +-- stdlib/src/hash.mo | 2 +- stdlib/src/hashMap.mo | 10 ++--- stdlib/src/int.mo | 2 +- stdlib/src/iter.mo | 4 +- stdlib/src/list.mo | 4 +- stdlib/src/nat.mo | 4 +- stdlib/src/option.mo | 2 +- stdlib/src/principalId.mo | 2 +- stdlib/src/result.mo | 4 +- stdlib/src/text.mo | 2 +- stdlib/src/trie.mo | 12 +++--- stdlib/src/trieMap.mo | 10 ++--- stdlib/src/trieSet.mo | 4 +- stdlib/test/Makefile | 2 +- stdlib/test/arrayTest.mo | 6 +-- stdlib/test/bufTest.mo | 4 +- stdlib/test/functionTest.mo | 6 +-- stdlib/test/hashMapTest.mo | 4 +- stdlib/test/intTest.mo | 4 +- stdlib/test/iterTest.mo | 6 +-- stdlib/test/listTest.mo | 4 +- stdlib/test/natTest.mo | 4 +- stdlib/test/noneTest.mo | 6 +-- stdlib/test/optionTest.mo | 4 +- stdlib/test/textTest.mo | 4 +- stdlib/test/trieMapTest.mo | 4 +- test/fail/not-static.mo | 2 +- test/fail/ok/self-import.tc.ok | 2 +- test/fail/self-import.mo | 2 +- test/lsp-int-test-project/ListClient.mo | 6 +-- test/lsp-int-test-project/app.mo | 4 +- test/lsp-int-test-project/definitions.mo | 4 +- test/lsp-int-test-project/entrypoint.mo | 2 +- test/lsp-int-test-project/lib/ListFuncs.mo | 2 +- test/lsp-int-test-project/lib/option.mo | 2 +- test/lsp-int/Main.hs | 4 +- test/repl/double-import.sh | 4 +- test/repl/lib/a.mo | 2 +- test/repl/lib/b.mo | 2 +- test/repl/lib/nested.mo | 4 +- test/repl/lib/nested/b.mo | 2 +- test/repl/lib/triangle.mo | 2 +- test/repl/nested-import.sh | 2 +- test/repl/ok/print-deps.stdout.ok | 4 +- test/repl/triangle-import.sh | 8 ++-- test/run-drun/test_oneway.mo | 2 +- test/run/import-module.mo | 2 +- test/run/import.mo | 4 +- test/run/pkg-import-absolute.mo | 2 +- test/run/pkg-import-relative.mo | 2 +- 86 files changed, 285 insertions(+), 219 deletions(-) create mode 100644 src/pipeline/resolve_import_test.ml diff --git a/design/DFX-Interface.md b/design/DFX-Interface.md index cb899a61a40..b139adf11b0 100644 --- a/design/DFX-Interface.md +++ b/design/DFX-Interface.md @@ -138,6 +138,7 @@ prints to the standard output all URLs _directly_ imported by mo:other_package/Some/Module ic:ABCDE01A7 ic:alias + relative/path This _reads_ only `some/path/input.mo`, and writes no files. diff --git a/samples/ListClient.mo b/samples/ListClient.mo index 6df35c58472..274eb702adb 100644 --- a/samples/ListClient.mo +++ b/samples/ListClient.mo @@ -1,4 +1,4 @@ -import List = "ListLib.mo"; // private, so we don't re-export List +import List = "ListLib"; // private, so we don't re-export List module { diff --git a/samples/app/client.mo b/samples/app/client.mo index 4de8d62e10a..2b021e8d333 100644 --- a/samples/app/client.mo +++ b/samples/app/client.mo @@ -1,5 +1,5 @@ import Prim "mo:prim"; -import S "server.mo"; +import S "server"; actor class Client() = this { // TODO: these should be constructor params once we can compile them diff --git a/samples/app/main.mo b/samples/app/main.mo index fb06fc323c6..4ca4b1805ca 100644 --- a/samples/app/main.mo +++ b/samples/app/main.mo @@ -1,5 +1,5 @@ -import Server "server.mo"; -import Client "client.mo"; +import Server "server"; +import Client "client"; let server = Server.Server(); let bob = Client.Client(); diff --git a/samples/app/server.mo b/samples/app/server.mo index 787b5e4f121..578ea40fe6c 100644 --- a/samples/app/server.mo +++ b/samples/app/server.mo @@ -1,6 +1,6 @@ import Prim "mo:prim"; -import L "list.mo"; -import T "types.mo"; +import L "list"; +import T "types"; type ClientData = { id : Nat; diff --git a/src/languageServer/completion.ml b/src/languageServer/completion.ml index f30cf6175d3..76dc967fab8 100644 --- a/src/languageServer/completion.ml +++ b/src/languageServer/completion.ml @@ -134,7 +134,7 @@ let completions index logger project_root file_path file_contents line column = let current_module_decls = current_uri_opt |> opt_bind (fun uri -> DI.lookup_module uri index) - |> Fun.flip Lib.Option.get [] in + |> Option.fold ~none:[] ~some:snd in current_module_decls in let module_alias_completion_item alias = @@ -165,7 +165,7 @@ let completions index logger project_root file_path file_contents line column = match module_path with | Some mp -> (match DI.lookup_module (snd mp) index with - | Some decls -> + | Some (_, decls) -> decls |> List.filter (has_prefix prefix) |> List.map item_of_ide_decl diff --git a/src/languageServer/completion_test.ml b/src/languageServer/completion_test.ml index bdf654b84ae..793063ca9ad 100644 --- a/src/languageServer/completion_test.ml +++ b/src/languageServer/completion_test.ml @@ -77,7 +77,7 @@ List.| let%test "it handles a full module" = prefix_test_case {|module { - private import List = "./ListLib.mo"; + private import List = "./ListLib"; func singleton(x: T): List.List = List.cons(x, Test.|()); @@ -89,8 +89,8 @@ let%test "it handles a full module" = let%test "it doesn't fall through to the next valid prefix" = prefix_test_case {|module { -private import List = "lib/ListLib.mo"; // private, so we don't re-export List -private import ListFns = "lib/ListFuncs.mo"; // private, so we don't re-export List +private import List = "lib/ListLib"; // private, so we don't re-export List +private import ListFns = "lib/ListFuncs"; // private, so we don't re-export List type Stack = List.List; func push(x : Int, s : Stack) : Stack = List.cons(x, s); func empty():Stack = List.nil(); diff --git a/src/languageServer/declaration_index.ml b/src/languageServer/declaration_index.ml index 6a43e549e18..f525f0242ed 100644 --- a/src/languageServer/declaration_index.ml +++ b/src/languageServer/declaration_index.ml @@ -65,20 +65,32 @@ let add_module : string -> ide_decl list -> declaration_index -> declaration_ind let lookup_module (path : string) (index : t) - : ide_decl list option = + : (string * ide_decl list) option = let open Pipeline.URL in let make_absolute = Lib.FilePath.make_absolute (Sys.getcwd ()) in match parse path with | Ok (Relative path) -> + let path = + Pipeline.ResolveImport.append_extension Sys.file_exists path + |> Option.value ~default:path in Index.find_opt (make_absolute path) index.modules + |> Option.map (fun decls -> (path, decls)) | Ok (Package (pkg, path)) -> Option.bind (Flags.M.find_opt pkg index.package_map) (fun pkg_path -> + let path = + Pipeline.ResolveImport.append_extension + Sys.file_exists (Filename.concat pkg_path path) + |> Option.value ~default:path in Index.find_opt - (make_absolute (Filename.concat pkg_path path)) - index.modules) - | Ok Prim -> Index.find_opt "@prim" index.modules + (make_absolute path) + index.modules + |> Option.map (fun decls -> (path, decls)) + ) + | Ok Prim -> + Index.find_opt "@prim" index.modules + |> Option.map (fun decls -> ("@prim", decls)) | Ok (Ic _ | IcAlias _) -> (* TODO *) None | Error _ -> None diff --git a/src/languageServer/declaration_index.mli b/src/languageServer/declaration_index.mli index 46d0ffc3868..3da4650704f 100644 --- a/src/languageServer/declaration_index.mli +++ b/src/languageServer/declaration_index.mli @@ -24,6 +24,6 @@ type ide_decl = val string_of_ide_decl : ide_decl -> string val name_of_ide_decl : ide_decl -> string -val lookup_module : string -> t -> ide_decl list option +val lookup_module : string -> t -> (string * ide_decl list) option val make_index : (string -> string -> unit) -> Vfs.t -> string list -> t Diag.result diff --git a/src/languageServer/definition.ml b/src/languageServer/definition.ml index c736d5c02b4..717d5f7b4c5 100644 --- a/src/languageServer/definition.ml +++ b/src/languageServer/definition.ml @@ -12,7 +12,11 @@ let range_of_region (at : Source.region) : Lsp.range = Lsp. range_end_ = position_of_pos at.Source.right; } -let find_named (name : string) : DI.ide_decl list -> Source.region option = +let find_named + : string -> + (string * DI.ide_decl list) -> + (string * Source.region) option = + fun name (path, decls) -> Lib.List.first_opt (function | DI.ValueDecl value -> if String.equal value.DI.name name @@ -21,7 +25,8 @@ let find_named (name : string) : DI.ide_decl list -> Source.region option = | DI.TypeDecl typ -> if String.equal typ.DI.name name then typ.DI.definition - else None) + else None) decls + |> Option.map (fun x -> (path, x)) let opt_bind f = function | Some x -> f x @@ -47,13 +52,11 @@ let definition_handler | Resolved resolved -> DI.lookup_module resolved.path index |> opt_bind (find_named resolved.ident) - |> Option.map (fun loc -> (resolved.path, loc)) | Ident ident -> Lib.FilePath.relative_to project_root file_path |> opt_bind (fun uri -> DI.lookup_module uri index |> opt_bind (find_named ident) - |> Option.map (fun loc -> (uri, loc)) )) in let location = Option.map (fun (path, region) -> diff --git a/src/languageServer/hover.ml b/src/languageServer/hover.ml index 2cbc9f2be2d..8723fa034c7 100644 --- a/src/languageServer/hover.ml +++ b/src/languageServer/hover.ml @@ -26,7 +26,7 @@ let hover_handler let current_module_decls = current_uri_opt |> Fun.flip Option.bind (fun uri -> lookup_module uri index) - |> Fun.flip Lib.Option.get [] in + |> Option.fold ~none:[] ~some:snd in current_module_decls in let mk_hover_result ide_decl = Lsp.{ hover_result_contents = markup_content (hover_detail ide_decl) } in @@ -42,7 +42,7 @@ let hover_handler Some Lsp.{ hover_result_contents = markup_content path } | Source_file.Resolved resolved -> lookup_module resolved.Source_file.path index - |> Fun.flip Option.bind (fun decls -> + |> Fun.flip Option.bind (fun (_, decls) -> List.find_opt (fun d -> name_of_ide_decl d = resolved.Source_file.ident) decls) diff --git a/src/languageServer/source_file.ml b/src/languageServer/source_file.ml index 299bb5658a3..4f11ea379d4 100644 --- a/src/languageServer/source_file.ml +++ b/src/languageServer/source_file.ml @@ -6,6 +6,10 @@ type cursor_target = | CIdent of string | CQualified of string * string +let string_of_cursor_target = function + | CIdent i -> "(CIdent " ^ i ^ ")" + | CQualified (q, i) -> "CQUalified (" ^ q ^ ", " ^ i ^ ")" + let cursor_target_at_pos (position : Lsp.position) (file_contents : string) @@ -118,7 +122,7 @@ let identifier_at_pos project_root file_path file_contents position = file_path file_contents in cursor_target_at_pos position file_contents - |> Option.map (function + |> Option.map (function | CIdent s -> (match List.find_opt (fun (alias, _) -> alias = s) imported with | None -> Ident s diff --git a/src/languageServer/source_file_tests.ml b/src/languageServer/source_file_tests.ml index 1cede45b808..f304440d8b6 100644 --- a/src/languageServer/source_file_tests.ml +++ b/src/languageServer/source_file_tests.ml @@ -67,8 +67,8 @@ let%test "it parses a simple module header" = parse_module_header_test_case "/project" "/project/src/Main.mo" - "import P \"lib/prelude.mo\"" - ["P", "src/lib/prelude.mo"] + "import P \"lib/prelude\"" + ["P", "src/lib/prelude"] let%test "it parses a simple module header that contains a prim import" = parse_module_header_test_case @@ -81,8 +81,8 @@ let%test "it parses a simple module header with package paths" = parse_module_header_test_case "/project" "/project/src/Main.mo" - "import P \"mo:stdlib/prelude.mo\"" - ["P", "mo:stdlib/prelude.mo"] + "import P \"mo:stdlib/prelude\"" + ["P", "mo:stdlib/prelude"] let%test "it parses a simple module header" = parse_module_header_test_case @@ -91,8 +91,8 @@ let%test "it parses a simple module header" = {| module { -private import List "lib/ListLib.mo"; -private import ListFuncs "lib/ListFuncs.mo"; +private import List "lib/ListLib"; +private import ListFuncs "lib/ListFuncs"; type Stack = List.List; @@ -106,6 +106,6 @@ func singleton(x: Int): Stack = ListFuncs.doubleton(x, x); } |} - [ ("List", "lib/ListLib.mo") - ; ("ListFuncs", "lib/ListFuncs.mo") + [ ("List", "lib/ListLib") + ; ("ListFuncs", "lib/ListFuncs") ] diff --git a/src/pipeline/resolve_import.ml b/src/pipeline/resolve_import.ml index fb575a2eb03..5edec3460c0 100644 --- a/src/pipeline/resolve_import.ml +++ b/src/pipeline/resolve_import.ml @@ -47,10 +47,16 @@ type package_map = filepath M.t open Syntax open Source -let append_lib_if_needed f = - if Sys.file_exists f && Sys.is_directory f - then Filename.concat f "lib.mo" - else f +let append_extension file_exists f = + if Option.is_some (Lib.String.chop_suffix "/" f) then + Some (Filename.concat f "lib.mo") + else if Filename.extension f = "" then + if file_exists (f ^ ".mo") then + Some (f ^ ".mo") + else + Some (Filename.concat f "lib.mo") + else + None let err_unrecognized_url msgs at url msg = let open Diag in @@ -88,6 +94,15 @@ let err_file_does_not_exist msgs at full_path = text = Printf.sprintf "file \"%s\" does not exist" full_path } +let err_import_musnt_have_extension msgs at full_path = + let open Diag in + add_msg msgs { + sev = Error; + at; + cat = "import"; + text = Printf.sprintf "an import must not have an extension, try importing %s as %s instead" full_path (Filename.chop_extension full_path) + } + let err_package_not_defined msgs at pkg = let open Diag in add_msg msgs { @@ -135,13 +150,17 @@ let err_prim_pkg msgs = } let add_lib_import msgs imported ri_ref at full_path = - let full_path = append_lib_if_needed full_path in - if Sys.file_exists full_path - then begin - ri_ref := LibPath full_path; - imported := RIM.add (LibPath full_path) at !imported - end else - err_file_does_not_exist msgs at full_path + match append_extension Sys.file_exists full_path with + | Some full_path -> + if Sys.file_exists full_path + then begin + ri_ref := LibPath full_path; + imported := RIM.add (LibPath full_path) at !imported + end else + err_file_does_not_exist msgs at full_path + | None -> + err_import_musnt_have_extension msgs at full_path + let add_idl_import msgs imported ri_ref at full_path bytes = if Sys.file_exists full_path diff --git a/src/pipeline/resolve_import.mli b/src/pipeline/resolve_import.mli index 5f263479c63..56bfbcd55ed 100644 --- a/src/pipeline/resolve_import.mli +++ b/src/pipeline/resolve_import.mli @@ -31,3 +31,6 @@ type resolved_flags = { val resolve_flags : flags -> resolved_flags Diag.result val resolve : flags -> Syntax.prog -> filepath -> resolved_imports Diag.result + +(* Exported for tests *) +val append_extension : (filepath -> bool) -> filepath -> filepath option diff --git a/src/pipeline/resolve_import_test.ml b/src/pipeline/resolve_import_test.ml new file mode 100644 index 00000000000..5b93e9f8ca4 --- /dev/null +++ b/src/pipeline/resolve_import_test.ml @@ -0,0 +1,25 @@ +(** Given a list of filenames that should be reported as existing + tests what a given import path resolves to *) +let import_relative_test_case files import expected = + let actual = Resolve_import.append_extension (fun x -> List.mem x files) import in + let show = function + | None -> "None" + | Some s -> "Some " ^ s in + Option.equal String.equal actual expected || + (Printf.printf + "\nExpected: %s\nActual: %s\n" + (show expected) + (show actual); + false) + +let%test "it resolves a relative file import" = + import_relative_test_case ["list.mo"] "list" (Some "list.mo") + +let%test "it resolves a relative directory import" = + import_relative_test_case [] "list/" (Some "list/lib.mo") + +let%test "it resolves to a relative directory import if no .mo file is found" = + import_relative_test_case [] "list" (Some "list/lib.mo") + +let%test "it fails on a relative import with an extension" = + import_relative_test_case [] "list.mo" None diff --git a/stdlib/examples/actorspec/demo/Demo.mo b/stdlib/examples/actorspec/demo/Demo.mo index 4da0be7bccf..154dff6f8e5 100644 --- a/stdlib/examples/actorspec/demo/Demo.mo +++ b/stdlib/examples/actorspec/demo/Demo.mo @@ -1,4 +1,4 @@ -import ActorSpec "../src/ActorSpec.mo"; +import ActorSpec "../src/ActorSpec"; type Group = ActorSpec.Group; diff --git a/stdlib/examples/actorspec/src/ActorSpec.mo b/stdlib/examples/actorspec/src/ActorSpec.mo index 1ef05904ee4..ec8d286ad2f 100644 --- a/stdlib/examples/actorspec/src/ActorSpec.mo +++ b/stdlib/examples/actorspec/src/ActorSpec.mo @@ -1,7 +1,7 @@ -import Debug "mo:stdlib/debug.mo"; -import Array "mo:stdlib/array.mo"; -import Int "mo:stdlib/int.mo"; -import Text "mo:stdlib/text.mo"; +import Debug "mo:stdlib/debug"; +import Array "mo:stdlib/array"; +import Int "mo:stdlib/int"; +import Text "mo:stdlib/text"; module { public type Group = { diff --git a/stdlib/examples/produce-exchange/src/docTable.mo b/stdlib/examples/produce-exchange/src/docTable.mo index 0944ebec5d5..c87e81be666 100644 --- a/stdlib/examples/produce-exchange/src/docTable.mo +++ b/stdlib/examples/produce-exchange/src/docTable.mo @@ -1,6 +1,6 @@ -import Hash "mo:stdlib/hash.mo"; +import Hash "mo:stdlib/hash"; -import Trie "mo:stdlib/trie.mo"; +import Trie "mo:stdlib/trie"; module { /** diff --git a/stdlib/examples/produce-exchange/src/serverActor.mo b/stdlib/examples/produce-exchange/src/serverActor.mo index 92631649c08..b44ded42f38 100644 --- a/stdlib/examples/produce-exchange/src/serverActor.mo +++ b/stdlib/examples/produce-exchange/src/serverActor.mo @@ -4,16 +4,16 @@ -------------------- */ -import Debug "mo:stdlib/debug.mo"; -import P = "mo:stdlib/prelude.mo"; -import Option = "mo:stdlib/option.mo"; -import T = "serverTypes.mo"; -import L = "serverLang.mo"; -import Model = "serverModel.mo"; -import Result = "mo:stdlib/result.mo"; - -import Trie = "mo:stdlib/trie.mo"; -import List = "mo:stdlib/list.mo"; +import Debug "mo:stdlib/debug"; +import P = "mo:stdlib/prelude"; +import Option = "mo:stdlib/option"; +import T = "serverTypes"; +import L = "serverLang"; +import Model = "serverModel"; +import Result = "mo:stdlib/result"; + +import Trie = "mo:stdlib/trie"; +import List = "mo:stdlib/list"; type List = List.List; diff --git a/stdlib/examples/produce-exchange/src/serverLang.mo b/stdlib/examples/produce-exchange/src/serverLang.mo index ab29e2f7bc3..0810d135ffe 100644 --- a/stdlib/examples/produce-exchange/src/serverLang.mo +++ b/stdlib/examples/produce-exchange/src/serverLang.mo @@ -1,5 +1,5 @@ -import Result = "mo:stdlib/result.mo"; -import T = "serverTypes.mo"; +import Result = "mo:stdlib/result"; +import T = "serverTypes"; module { diff --git a/stdlib/examples/produce-exchange/src/serverModel.mo b/stdlib/examples/produce-exchange/src/serverModel.mo index fa6e902bba4..e2fc908ac5c 100644 --- a/stdlib/examples/produce-exchange/src/serverModel.mo +++ b/stdlib/examples/produce-exchange/src/serverModel.mo @@ -1,20 +1,19 @@ -import Debug = "mo:stdlib/debug.mo"; -import P = "mo:stdlib/prelude.mo"; - -import T = "serverTypes.mo"; -import L = "serverLang.mo"; -import M = "serverModelTypes.mo"; - -import List = "mo:stdlib/list.mo"; -import Hash_ = "mo:stdlib/hash.mo"; -import Option = "mo:stdlib/option.mo"; -import Trie = "mo:stdlib/trie.mo"; -import Iter = "mo:stdlib/iter.mo"; -import Array = "mo:stdlib/array.mo"; - -import Result = "mo:stdlib/result.mo"; -import DT = "docTable.mo"; - +import Debug "mo:stdlib/debug"; +import P "mo:stdlib/prelude"; + +import T "serverTypes"; +import L "serverLang"; +import M "serverModelTypes"; + +import List "mo:stdlib/list"; +import Hash_ "mo:stdlib/hash"; +import Option "mo:stdlib/option"; +import Trie "mo:stdlib/trie"; +import Iter "mo:stdlib/iter"; +import Array "mo:stdlib/array"; + +import Result "mo:stdlib/result"; +import DT = "docTable"; module { /** diff --git a/stdlib/examples/produce-exchange/src/serverModelTypes.mo b/stdlib/examples/produce-exchange/src/serverModelTypes.mo index 188390ff023..803082bbdab 100644 --- a/stdlib/examples/produce-exchange/src/serverModelTypes.mo +++ b/stdlib/examples/produce-exchange/src/serverModelTypes.mo @@ -1,6 +1,6 @@ -import T = "serverTypes.mo"; -import Trie = "mo:stdlib/trie.mo"; -import DocTable = "docTable.mo"; +import T = "serverTypes"; +import Trie = "mo:stdlib/trie"; +import DocTable = "docTable"; module { diff --git a/stdlib/examples/produce-exchange/test/evalBulk.mo b/stdlib/examples/produce-exchange/test/evalBulk.mo index ca8fabb16f3..5d8a24ccbce 100644 --- a/stdlib/examples/produce-exchange/test/evalBulk.mo +++ b/stdlib/examples/produce-exchange/test/evalBulk.mo @@ -1,8 +1,8 @@ -import Debug = "mo:stdlib/debug.mo"; -import T = "../src/serverTypes.mo"; -import A = "../src/serverActor.mo"; -import Result = "mo:stdlib/result.mo"; -import Option = "mo:stdlib/option.mo"; +import Debug = "mo:stdlib/debug"; +import T = "../src/serverTypes"; +import A = "../src/serverActor"; +import Result = "mo:stdlib/result"; +import Option = "mo:stdlib/option"; func printEntityCount(entname:Text, count:Nat) { Debug.print ("- " # entname # " count: " # debug_show count # "\n"); diff --git a/stdlib/examples/produce-exchange/test/loadWorkloadAndQueryBig.mo b/stdlib/examples/produce-exchange/test/loadWorkloadAndQueryBig.mo index 11aa7f6f586..f20d86dc0e0 100644 --- a/stdlib/examples/produce-exchange/test/loadWorkloadAndQueryBig.mo +++ b/stdlib/examples/produce-exchange/test/loadWorkloadAndQueryBig.mo @@ -1,7 +1,7 @@ -//let T = (import "../src/serverTypes.mo"); -//let A = (import "../src/serverActor.mo"); -//let Result = (import "mo:stdlib/result.mo"); -//let Option = (import "mo:stdlib/option.mo"); +//let T = (import "../src/serverTypes"); +//let A = (import "../src/serverActor"); +//let Result = (import "mo:stdlib/result"); +//let Option = (import "mo:stdlib/option"); func scaledParams(region_count_:Nat, factor:Nat) : T.WorkloadParams = shared { region_count = region_count_:Nat; diff --git a/stdlib/examples/produce-exchange/test/producerRemInventory.mo b/stdlib/examples/produce-exchange/test/producerRemInventory.mo index 51c65de62d9..4c4937859ca 100644 --- a/stdlib/examples/produce-exchange/test/producerRemInventory.mo +++ b/stdlib/examples/produce-exchange/test/producerRemInventory.mo @@ -1,8 +1,8 @@ -import Debug "mo:stdlib/debug.mo"; -import T = "../src/serverTypes.mo"; -import A = "../src/serverActor.mo"; -import Result = "mo:stdlib/result.mo"; -import Option = "mo:stdlib/option.mo"; +import Debug "mo:stdlib/debug"; +import T = "../src/serverTypes"; +import A = "../src/serverActor"; +import Result = "mo:stdlib/result"; +import Option = "mo:stdlib/option"; func printEntityCount(entname:Text, count:Nat) { Debug.print ("- " # entname # " count: " # debug_show count # "\n"); diff --git a/stdlib/examples/produce-exchange/test/profileActor.mo b/stdlib/examples/produce-exchange/test/profileActor.mo index 8be8fd8b9d3..37446ba92c7 100644 --- a/stdlib/examples/produce-exchange/test/profileActor.mo +++ b/stdlib/examples/produce-exchange/test/profileActor.mo @@ -1,5 +1,5 @@ -import T = "../src/serverTypes.mo"; -import Model = "../src/serverModel.mo"; +import T = "../src/serverTypes"; +import Model = "../src/serverModel"; actor server { // morally: loadQuery (region_count:Nat, scale_factor:Nat) { diff --git a/stdlib/examples/produce-exchange/test/profileFastCounts.mo b/stdlib/examples/produce-exchange/test/profileFastCounts.mo index 64f45f39327..e10bfc39dd5 100644 --- a/stdlib/examples/produce-exchange/test/profileFastCounts.mo +++ b/stdlib/examples/produce-exchange/test/profileFastCounts.mo @@ -2,9 +2,9 @@ // we correlate these numbers with times that we // measure elsewhere, where these numbers are not available. -import Debug "mo:stdlib/debug.mo"; -import T = "../src/serverTypes.mo"; -import Model = "../src/serverModel.mo"; +import Debug "mo:stdlib/debug"; +import T "../src/serverTypes"; +import Model "../src/serverModel"; let m = Model.Model(); diff --git a/stdlib/examples/produce-exchange/test/retailerReserveMany.mo b/stdlib/examples/produce-exchange/test/retailerReserveMany.mo index 4c7f6c7e8fb..a68bdd85499 100644 --- a/stdlib/examples/produce-exchange/test/retailerReserveMany.mo +++ b/stdlib/examples/produce-exchange/test/retailerReserveMany.mo @@ -1,8 +1,8 @@ -import Debug "mo:stdlib/debug.mo"; -import T = "../src/serverTypes.mo"; -import A = "../src/serverActor.mo"; -import Result = "mo:stdlib/result.mo"; -import Option = "mo:stdlib/option.mo"; +import Debug "mo:stdlib/debug"; +import T = "../src/serverTypes"; +import A = "../src/serverActor"; +import Result = "mo:stdlib/result"; +import Option = "mo:stdlib/option"; func printEntityCount(entname:Text, count:Nat) { Debug.print ("- " # entname # " count: " # debug_show count # "\n"); diff --git a/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.mo b/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.mo index bb027e47cb5..524c0a4857a 100644 --- a/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.mo +++ b/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.mo @@ -1,8 +1,8 @@ -import Debug "mo:stdlib/debug.mo"; -import T = "../src/serverTypes.mo"; -import A = "../src/serverActor.mo"; -import Result = "mo:stdlib/result.mo"; -import Option = "mo:stdlib/option.mo"; +import Debug "mo:stdlib/debug"; +import T = "../src/serverTypes"; +import A = "../src/serverActor"; +import Result = "mo:stdlib/result"; +import Option = "mo:stdlib/option"; func printEntityCount(entname:Text, count:Nat) { Debug.print ("- " # entname # " count: " # debug_show count # "\n"); diff --git a/stdlib/examples/rx/src/Observable.mo b/stdlib/examples/rx/src/Observable.mo index 19be16008f9..181dc4e738d 100644 --- a/stdlib/examples/rx/src/Observable.mo +++ b/stdlib/examples/rx/src/Observable.mo @@ -1,5 +1,5 @@ -import Disposable "Disposable.mo"; -import Observer "Observer.mo"; +import Disposable "Disposable"; +import Observer "Observer"; module { type Subscriber = Observer.Type -> Disposable.Type; diff --git a/stdlib/examples/rx/src/Observer.mo b/stdlib/examples/rx/src/Observer.mo index c7e32d8a0d3..3e5fccf6ad6 100644 --- a/stdlib/examples/rx/src/Observer.mo +++ b/stdlib/examples/rx/src/Observer.mo @@ -1,4 +1,4 @@ -import Event "Event.mo"; +import Event "Event"; module { public type EventHandler = Event.Type -> (); diff --git a/stdlib/examples/rx/src/Rx.mo b/stdlib/examples/rx/src/Rx.mo index d5faf0ac9bd..d8971ae0c98 100644 --- a/stdlib/examples/rx/src/Rx.mo +++ b/stdlib/examples/rx/src/Rx.mo @@ -1,7 +1,7 @@ -import DisposableLib = "Disposable.mo"; -import EventLib = "Event.mo"; -import ObservableLib = "Observable.mo"; -import ObserverLib = "Observer.mo"; +import DisposableLib = "Disposable"; +import EventLib = "Event"; +import ObservableLib = "Observable"; +import ObserverLib = "Observer"; module { public let Disposable = DisposableLib; diff --git a/stdlib/examples/rx/test/RxTest.mo b/stdlib/examples/rx/test/RxTest.mo index 80c72d0e075..e0e96ed7cb3 100644 --- a/stdlib/examples/rx/test/RxTest.mo +++ b/stdlib/examples/rx/test/RxTest.mo @@ -1,5 +1,5 @@ -import Array "mo:stdlib/array.mo"; -import Rx "../src/Rx.mo"; +import Array "mo:stdlib/array"; +import Rx "../src/Rx"; type Error = { description : Text; diff --git a/stdlib/src/assocList.mo b/stdlib/src/assocList.mo index 693b595d124..9477308a4ef 100644 --- a/stdlib/src/assocList.mo +++ b/stdlib/src/assocList.mo @@ -1,4 +1,4 @@ -import List "list.mo"; +import List "list"; module { /** diff --git a/stdlib/src/buf.mo b/stdlib/src/buf.mo index 610bb3af413..31de3a963ec 100644 --- a/stdlib/src/buf.mo +++ b/stdlib/src/buf.mo @@ -1,6 +1,6 @@ -import P "prelude.mo"; -import I "iter.mo"; -import A "array.mo"; +import P "prelude"; +import I "iter"; +import A "array"; module { diff --git a/stdlib/src/hash.mo b/stdlib/src/hash.mo index deb6951fd7c..36a1823bee6 100644 --- a/stdlib/src/hash.mo +++ b/stdlib/src/hash.mo @@ -1,5 +1,5 @@ import Prim "mo:prim"; -import Iter "iter.mo"; +import Iter "iter"; module { /** diff --git a/stdlib/src/hashMap.mo b/stdlib/src/hashMap.mo index 87f509bcac2..613adec9698 100644 --- a/stdlib/src/hashMap.mo +++ b/stdlib/src/hashMap.mo @@ -1,9 +1,9 @@ import Prim "mo:prim"; -import P "prelude.mo"; -import A "array.mo"; -import Hash "hash.mo"; -import Iter "iter.mo"; -import AssocList "assocList.mo"; +import P "prelude"; +import A "array"; +import Hash "hash"; +import Iter "iter"; +import AssocList "assocList"; module { diff --git a/stdlib/src/int.mo b/stdlib/src/int.mo index bdde8b111e6..cbd51dfbca6 100644 --- a/stdlib/src/int.mo +++ b/stdlib/src/int.mo @@ -1,5 +1,5 @@ import Prim "mo:prim"; -import Prelude "prelude.mo"; +import Prelude "prelude"; module { public let abs = Prim.abs; diff --git a/stdlib/src/iter.mo b/stdlib/src/iter.mo index 67b2a335f24..df3fc70bf5b 100644 --- a/stdlib/src/iter.mo +++ b/stdlib/src/iter.mo @@ -1,5 +1,5 @@ -import Array "array.mo"; -import List "list.mo"; +import Array "array"; +import List "list"; module { public type Iter = {next : () -> ?T}; diff --git a/stdlib/src/list.mo b/stdlib/src/list.mo index 90b156e8182..775512d0158 100644 --- a/stdlib/src/list.mo +++ b/stdlib/src/list.mo @@ -1,5 +1,5 @@ -import Array "array.mo"; -import Option "option.mo"; +import Array "array"; +import Option "option"; module { /** diff --git a/stdlib/src/nat.mo b/stdlib/src/nat.mo index a44c6afc551..97f9441caaa 100644 --- a/stdlib/src/nat.mo +++ b/stdlib/src/nat.mo @@ -1,6 +1,6 @@ import Prim "mo:prim"; -import Int "int.mo"; -import Prelude "prelude.mo"; +import Int "int"; +import Prelude "prelude"; module { public func add(x : Nat, y : Nat) : Nat { diff --git a/stdlib/src/option.mo b/stdlib/src/option.mo index da0db4424c8..4d271a64514 100644 --- a/stdlib/src/option.mo +++ b/stdlib/src/option.mo @@ -1,4 +1,4 @@ -import P "prelude.mo"; +import P "prelude"; module { /** diff --git a/stdlib/src/principalId.mo b/stdlib/src/principalId.mo index 3fd298abb29..e54d2dfdc80 100644 --- a/stdlib/src/principalId.mo +++ b/stdlib/src/principalId.mo @@ -1,5 +1,5 @@ import Prim "mo:prim"; -import Blob "blob.mo"; +import Blob "blob"; module { public func hash(x : Principal) : Word32 = Blob.hash (Prim.blobOfPrincipal x); } diff --git a/stdlib/src/result.mo b/stdlib/src/result.mo index 56e76f71b52..2f7461de9ec 100644 --- a/stdlib/src/result.mo +++ b/stdlib/src/result.mo @@ -1,5 +1,5 @@ -import P "prelude.mo"; -import Array "array.mo"; +import P "prelude"; +import Array "array"; module { /** diff --git a/stdlib/src/text.mo b/stdlib/src/text.mo index b1e9d82d4ac..e78678500be 100644 --- a/stdlib/src/text.mo +++ b/stdlib/src/text.mo @@ -1,4 +1,4 @@ -import Iter "iter.mo"; +import Iter "iter"; module { diff --git a/stdlib/src/trie.mo b/stdlib/src/trie.mo index d0267f7b379..9783e2eb9e8 100644 --- a/stdlib/src/trie.mo +++ b/stdlib/src/trie.mo @@ -1,11 +1,11 @@ import Prim "mo:prim"; -import P "prelude.mo"; -import Option "option.mo"; -import H "hash.mo"; -import A "array.mo"; +import P "prelude"; +import Option "option"; +import H "hash"; +import A "array"; -import List "list.mo"; -import AssocList "assocList.mo"; +import List "list"; +import AssocList "assocList"; module { /** diff --git a/stdlib/src/trieMap.mo b/stdlib/src/trieMap.mo index f67c6563ed1..71beca9662b 100644 --- a/stdlib/src/trieMap.mo +++ b/stdlib/src/trieMap.mo @@ -1,8 +1,8 @@ -import T "trie.mo"; -import P "prelude.mo"; -import I "iter.mo"; -import Hash "hash.mo"; -import List "list.mo"; +import T "trie"; +import P "prelude"; +import I "iter"; +import Hash "hash"; +import List "list"; /** diff --git a/stdlib/src/trieSet.mo b/stdlib/src/trieSet.mo index 249c0e3800f..1315ea9cc0c 100644 --- a/stdlib/src/trieSet.mo +++ b/stdlib/src/trieSet.mo @@ -17,8 +17,8 @@ in the future, we might avoid this via https://dfinity.atlassian.net/browse/AST-32 */ -import Trie "trie.mo"; -import Hash "hash.mo"; +import Trie "trie"; +import Hash "hash"; module { public type Hash = Hash.Hash; diff --git a/stdlib/test/Makefile b/stdlib/test/Makefile index df698fc5de5..2dd01c71a0d 100644 --- a/stdlib/test/Makefile +++ b/stdlib/test/Makefile @@ -18,7 +18,7 @@ $(OUTDIR): $(OUTDIR)/import_all.mo: $(STDLIB_FILES) | $(OUTDIR) > $@ for f in $(patsubst $(STDLIB)/%.mo,%,$(STDLIB_FILES)); do \ - echo "import Import_$$f \"mo:stdlib/$$f.mo\";" >> $@; \ + echo "import Import_$$f \"mo:stdlib/$$f\";" >> $@; \ done $(OUTDIR)/%.wasm: %.mo | $(OUTDIR) diff --git a/stdlib/test/arrayTest.mo b/stdlib/test/arrayTest.mo index fdbe7c6e5ca..74527678001 100644 --- a/stdlib/test/arrayTest.mo +++ b/stdlib/test/arrayTest.mo @@ -1,6 +1,6 @@ -import Array "mo:stdlib/array.mo"; -import Prelude "mo:stdlib/prelude.mo"; -import Text "mo:stdlib/text.mo"; +import Array "mo:stdlib/array"; +import Prelude "mo:stdlib/prelude"; +import Text "mo:stdlib/text"; Prelude.printLn("Array"); diff --git a/stdlib/test/bufTest.mo b/stdlib/test/bufTest.mo index d61f737c4fa..08625f11512 100644 --- a/stdlib/test/bufTest.mo +++ b/stdlib/test/bufTest.mo @@ -1,6 +1,6 @@ import Prim "mo:prim"; -import B "mo:stdlib/buf.mo"; -import I "mo:stdlib/iter.mo"; +import B "mo:stdlib/buf"; +import I "mo:stdlib/iter"; // test repeated growing let a = B.Buf(3); diff --git a/stdlib/test/functionTest.mo b/stdlib/test/functionTest.mo index bb06fedb534..8020c5ceca8 100644 --- a/stdlib/test/functionTest.mo +++ b/stdlib/test/functionTest.mo @@ -1,6 +1,6 @@ -import Function "mo:stdlib/function.mo"; -import Prelude "mo:stdlib/prelude.mo"; -import Text "mo:stdlib/text.mo"; +import Function "mo:stdlib/function"; +import Prelude "mo:stdlib/prelude"; +import Text "mo:stdlib/text"; Prelude.printLn("Function"); diff --git a/stdlib/test/hashMapTest.mo b/stdlib/test/hashMapTest.mo index bbd69e3869f..bc2ef1c4788 100644 --- a/stdlib/test/hashMapTest.mo +++ b/stdlib/test/hashMapTest.mo @@ -1,6 +1,6 @@ import Prim "mo:prim"; -import H "mo:stdlib/hashMap.mo"; -import Hash "mo:stdlib/hash.mo"; +import H "mo:stdlib/hashMap"; +import Hash "mo:stdlib/hash"; func textIsEq(x:Text,y:Text):Bool { x == y }; diff --git a/stdlib/test/intTest.mo b/stdlib/test/intTest.mo index 5b70c20b46e..ba1991ad3a2 100644 --- a/stdlib/test/intTest.mo +++ b/stdlib/test/intTest.mo @@ -1,5 +1,5 @@ -import Prelude "mo:stdlib/prelude.mo"; -import Int "mo:stdlib/int.mo"; +import Prelude "mo:stdlib/prelude"; +import Int "mo:stdlib/int"; Prelude.printLn("Int"); diff --git a/stdlib/test/iterTest.mo b/stdlib/test/iterTest.mo index b554a35c70b..0c421b9def9 100644 --- a/stdlib/test/iterTest.mo +++ b/stdlib/test/iterTest.mo @@ -1,6 +1,6 @@ -import Iter "mo:stdlib/iter.mo"; -import List "mo:stdlib/list.mo"; -import Prelude "mo:stdlib/prelude.mo"; +import Iter "mo:stdlib/iter"; +import List "mo:stdlib/list"; +import Prelude "mo:stdlib/prelude"; Prelude.printLn("Iter"); diff --git a/stdlib/test/listTest.mo b/stdlib/test/listTest.mo index 74bfa8b3b01..2ead871523a 100644 --- a/stdlib/test/listTest.mo +++ b/stdlib/test/listTest.mo @@ -1,5 +1,5 @@ -import List "mo:stdlib/list.mo"; -import Prelude "mo:stdlib/prelude.mo"; +import List "mo:stdlib/list"; +import Prelude "mo:stdlib/prelude"; type X = Nat; diff --git a/stdlib/test/natTest.mo b/stdlib/test/natTest.mo index c4f2ed0d37b..7f344b4131c 100644 --- a/stdlib/test/natTest.mo +++ b/stdlib/test/natTest.mo @@ -1,5 +1,5 @@ -import Prelude "mo:stdlib/prelude.mo"; -import Nat "mo:stdlib/nat.mo"; +import Prelude "mo:stdlib/prelude"; +import Nat "mo:stdlib/nat"; Prelude.printLn("Nat"); diff --git a/stdlib/test/noneTest.mo b/stdlib/test/noneTest.mo index fbbd085e0a8..be57a716e9a 100644 --- a/stdlib/test/noneTest.mo +++ b/stdlib/test/noneTest.mo @@ -1,6 +1,6 @@ -import Array "mo:stdlib/array.mo"; -import None "mo:stdlib/none.mo"; -import Prelude "mo:stdlib/prelude.mo"; +import Array "mo:stdlib/array"; +import None "mo:stdlib/none"; +import Prelude "mo:stdlib/prelude"; Prelude.printLn("None"); diff --git a/stdlib/test/optionTest.mo b/stdlib/test/optionTest.mo index 342a9788bdb..f4978daacd8 100644 --- a/stdlib/test/optionTest.mo +++ b/stdlib/test/optionTest.mo @@ -1,5 +1,5 @@ -import Option "mo:stdlib/option.mo"; -import Prelude "mo:stdlib/prelude.mo"; +import Option "mo:stdlib/option"; +import Prelude "mo:stdlib/prelude"; Prelude.printLn("Option"); diff --git a/stdlib/test/textTest.mo b/stdlib/test/textTest.mo index f1c253f8ceb..8a7ab06fddc 100644 --- a/stdlib/test/textTest.mo +++ b/stdlib/test/textTest.mo @@ -1,5 +1,5 @@ -import Prelude "mo:stdlib/prelude.mo"; -import Text "mo:stdlib/text.mo"; +import Prelude "mo:stdlib/prelude"; +import Text "mo:stdlib/text"; Prelude.printLn("Text"); diff --git a/stdlib/test/trieMapTest.mo b/stdlib/test/trieMapTest.mo index 3359afb38c8..324bf70ed61 100644 --- a/stdlib/test/trieMapTest.mo +++ b/stdlib/test/trieMapTest.mo @@ -1,6 +1,6 @@ import Prim "mo:prim"; -import H "mo:stdlib/trieMap.mo"; -import Hash "mo:stdlib/hash.mo"; +import H "mo:stdlib/trieMap"; +import Hash "mo:stdlib/hash"; func textIsEq(x:Text,y:Text):Bool { x == y }; diff --git a/test/fail/not-static.mo b/test/fail/not-static.mo index d6e681668bb..3fd9b4de589 100644 --- a/test/fail/not-static.mo +++ b/test/fail/not-static.mo @@ -1 +1 @@ -import "lib/not-static.mo" +import "lib/not-static" diff --git a/test/fail/ok/self-import.tc.ok b/test/fail/ok/self-import.tc.ok index d51b2ac1b9b..6b826b74e91 100644 --- a/test/fail/ok/self-import.tc.ok +++ b/test/fail/ok/self-import.tc.ok @@ -1 +1 @@ -self-import.mo:1.1-1.24: import error, file self-import.mo must not depend on itself +self-import.mo:1.1-1.21: import error, file self-import.mo must not depend on itself diff --git a/test/fail/self-import.mo b/test/fail/self-import.mo index 2dbe7b954c5..b766dfeb263 100644 --- a/test/fail/self-import.mo +++ b/test/fail/self-import.mo @@ -1 +1 @@ -import "self-import.mo"; +import "self-import"; diff --git a/test/lsp-int-test-project/ListClient.mo b/test/lsp-int-test-project/ListClient.mo index cfc3026321d..5af4fd5991b 100644 --- a/test/lsp-int-test-project/ListClient.mo +++ b/test/lsp-int-test-project/ListClient.mo @@ -1,7 +1,7 @@ import Prim "mo:prim"; -import List "lib/list.mo"; -import Option "lib/option.mo"; -import P "lib/prelude.mo"; +import List "lib/list"; +import Option "lib/option"; +import P "lib/prelude"; module { public type Stack = List.List; diff --git a/test/lsp-int-test-project/app.mo b/test/lsp-int-test-project/app.mo index cd3673b4255..b14c821611f 100644 --- a/test/lsp-int-test-project/app.mo +++ b/test/lsp-int-test-project/app.mo @@ -1,6 +1,6 @@ -import Stack "ListClient.mo"; +import Stack "ListClient"; import Prim "mo:prim"; -import Entry "entrypoint.mo"; +import Entry "entrypoint"; actor { func main(): () { diff --git a/test/lsp-int-test-project/definitions.mo b/test/lsp-int-test-project/definitions.mo index ee38e119ac0..5a896306d38 100644 --- a/test/lsp-int-test-project/definitions.mo +++ b/test/lsp-int-test-project/definitions.mo @@ -1,5 +1,5 @@ -import MyDependency "mo:mydep/lib.mo"; -import List "lib/list.mo"; +import MyDependency "mo:mydep/lib"; +import List "lib/list"; module { public func myFunc() { diff --git a/test/lsp-int-test-project/entrypoint.mo b/test/lsp-int-test-project/entrypoint.mo index fd395f7c5f0..b57b68665e2 100644 --- a/test/lsp-int-test-project/entrypoint.mo +++ b/test/lsp-int-test-project/entrypoint.mo @@ -1,3 +1,3 @@ -import Definitions "definitions.mo"; +import Definitions "definitions"; module {} diff --git a/test/lsp-int-test-project/lib/ListFuncs.mo b/test/lsp-int-test-project/lib/ListFuncs.mo index e25064736d8..4d3907382a4 100644 --- a/test/lsp-int-test-project/lib/ListFuncs.mo +++ b/test/lsp-int-test-project/lib/ListFuncs.mo @@ -1,4 +1,4 @@ -import List = "./ListLib.mo"; +import List = "./ListLib"; module { public func singleton(x: T): List.List = diff --git a/test/lsp-int-test-project/lib/option.mo b/test/lsp-int-test-project/lib/option.mo index a4ad45219e6..df93548d50f 100644 --- a/test/lsp-int-test-project/lib/option.mo +++ b/test/lsp-int-test-project/lib/option.mo @@ -1,5 +1,5 @@ import Prim "mo:prim"; -import P "prelude.mo"; +import P "prelude"; module { /** diff --git a/test/lsp-int/Main.hs b/test/lsp-int/Main.hs index 7a3fc05c838..f6e7202c552 100644 --- a/test/lsp-int/Main.hs +++ b/test/lsp-int/Main.hs @@ -218,7 +218,7 @@ main = do withDoc "app.mo" \doc -> do -- It knows how to handle package paths for rebuilding, and also -- for completions - let edit = TextEdit (Range (Position 4 0) (Position 4 0)) "\nimport MyDep \"mo:mydep/broken.mo\"" + let edit = TextEdit (Range (Position 4 0) (Position 4 0)) "\nimport MyDep \"mo:mydep/broken\"" _ <- applyEdit doc edit sendNotification TextDocumentDidSave (DidSaveTextDocumentParams doc) [diag] <- waitForActualDiagnostics @@ -227,7 +227,7 @@ main = do log "Completions from package paths" withDoc "app.mo" \doc -> do -- Imports the non-broken dependency module - let edit = TextEdit (Range (Position 4 0) (Position 4 0)) "\nimport MyDep \"mo:mydep/lib.mo\"" + let edit = TextEdit (Range (Position 4 0) (Position 4 0)) "\nimport MyDep \"mo:mydep/lib\"" _ <- applyEdit doc edit sendNotification TextDocumentDidSave (DidSaveTextDocumentParams doc) let edit2 = TextEdit (Range (Position 5 0) (Position 5 0)) "\nMyDep." diff --git a/test/repl/double-import.sh b/test/repl/double-import.sh index 052db3fb5cf..befabcdb33e 100755 --- a/test/repl/double-import.sh +++ b/test/repl/double-import.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash ${MOC:-$(dirname "$BASH_SOURCE")/../../src/moc} -v -i <<__END__ -import "lib/empty.mo"; -import "lib/empty.mo"; +import "lib/empty"; +import "lib/empty"; __END__ diff --git a/test/repl/lib/a.mo b/test/repl/lib/a.mo index 7aa0183b2a5..50451bf6f3d 100644 --- a/test/repl/lib/a.mo +++ b/test/repl/lib/a.mo @@ -1,3 +1,3 @@ -import C "c.mo"; +import C "c"; let i = C.i; diff --git a/test/repl/lib/b.mo b/test/repl/lib/b.mo index b07786fc5c0..0fc4ef4834a 100644 --- a/test/repl/lib/b.mo +++ b/test/repl/lib/b.mo @@ -1,2 +1,2 @@ -import C "c.mo"; +import C "c"; let i = C.i; diff --git a/test/repl/lib/nested.mo b/test/repl/lib/nested.mo index 16a66c3d2f6..fa3d7e178aa 100644 --- a/test/repl/lib/nested.mo +++ b/test/repl/lib/nested.mo @@ -1,4 +1,4 @@ -import A "nested/a.mo"; -import "nested/b.mo"; +import A "nested/a"; +import "nested/b"; let i = A.i; diff --git a/test/repl/lib/nested/b.mo b/test/repl/lib/nested/b.mo index 81829339bc9..7816afc1816 100644 --- a/test/repl/lib/nested/b.mo +++ b/test/repl/lib/nested/b.mo @@ -1,4 +1,4 @@ -import A "./a.mo"; +import A "./a"; module { public let i = A.i } diff --git a/test/repl/lib/triangle.mo b/test/repl/lib/triangle.mo index b5f67a31883..4c80e9772cf 100644 --- a/test/repl/lib/triangle.mo +++ b/test/repl/lib/triangle.mo @@ -1 +1 @@ -import "a.mo" +import "a" diff --git a/test/repl/nested-import.sh b/test/repl/nested-import.sh index 4400a0a52b5..2aa139ee092 100755 --- a/test/repl/nested-import.sh +++ b/test/repl/nested-import.sh @@ -1,4 +1,4 @@ #!/bin/bash ${MOC:-$(dirname "$BASH_SOURCE")/../../src/moc} -v -i <<__END__ | grep Parsing -import "lib/nested.mo"; +import "lib/nested"; __END__ diff --git a/test/repl/ok/print-deps.stdout.ok b/test/repl/ok/print-deps.stdout.ok index a98fe175b79..b8c4099a282 100644 --- a/test/repl/ok/print-deps.stdout.ok +++ b/test/repl/ok/print-deps.stdout.ok @@ -1,4 +1,4 @@ -nested/a.mo -nested/b.mo +nested/a +nested/b ic:ABCDE01A7 ic:alias diff --git a/test/repl/triangle-import.sh b/test/repl/triangle-import.sh index 6890ac4f8b4..adbbe1fa91f 100755 --- a/test/repl/triangle-import.sh +++ b/test/repl/triangle-import.sh @@ -1,7 +1,7 @@ #!/bin/bash ${MOC:-$(dirname "$BASH_SOURCE")/../../src/moc} -v -i <<__END__ -import "lib/b.mo"; -import "lib/a.mo"; -import "lib/c.mo"; -import "lib/triangle.mo"; +import "lib/b"; +import "lib/a"; +import "lib/c"; +import "lib/triangle"; __END__ diff --git a/test/run-drun/test_oneway.mo b/test/run-drun/test_oneway.mo index 0ff6ddfc072..cc4b4f2e8fe 100644 --- a/test/run-drun/test_oneway.mo +++ b/test/run-drun/test_oneway.mo @@ -1,3 +1,3 @@ -import M "oneway.mo"; +import M "oneway"; //SKIP comp diff --git a/test/run/import-module.mo b/test/run/import-module.mo index d6faf86caab..9ab3d3e18bf 100644 --- a/test/run/import-module.mo +++ b/test/run/import-module.mo @@ -1,3 +1,3 @@ -import L = "lib/ListM.mo"; +import L = "lib/ListM"; type stack = L.List; let s = L.cons(1, L.nil()); diff --git a/test/run/import.mo b/test/run/import.mo index 6967a661ef8..ea75b7f4c99 100644 --- a/test/run/import.mo +++ b/test/run/import.mo @@ -1,5 +1,5 @@ -import A "lib/hello-string.mo"; -import B "lib/dir"; +import A "lib/hello-string"; +import B "lib/dir/"; assert (A.hello == "Hello!"); assert (B.hello == "Hello!"); diff --git a/test/run/pkg-import-absolute.mo b/test/run/pkg-import-absolute.mo index 1f5ba383e1f..37b0098a779 100644 --- a/test/run/pkg-import-absolute.mo +++ b/test/run/pkg-import-absolute.mo @@ -1,6 +1,6 @@ //MOC-FLAG --package pkg "$(realpath lib/pkg)" import P1 "mo:pkg"; -import P2 "mo:pkg/other-module.mo"; +import P2 "mo:pkg/other-module"; P1.foo(); P2.bar(); diff --git a/test/run/pkg-import-relative.mo b/test/run/pkg-import-relative.mo index f2a52b4a99c..00368c86654 100644 --- a/test/run/pkg-import-relative.mo +++ b/test/run/pkg-import-relative.mo @@ -1,5 +1,5 @@ //MOC-FLAG --package pkg lib/pkg import P1 "mo:pkg"; -import P2 "mo:pkg/other-module.mo"; +import P2 "mo:pkg/other-module"; P1.foo(); P2.bar(); From 97f96c80182b98b0139dfc0c441e0ccb3e1b0f65 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 22 Jan 2020 15:11:11 +0000 Subject: [PATCH 0989/1176] use $ not @ as scope parameter prefix to avoid clashes with priviledged type @Iter etc --- design/scoped-await.md | 66 +++++++++++++++++----------------- src/mo_def/syntax.ml | 4 +-- src/mo_frontend/typing.ml | 10 +++--- src/mo_types/type.ml | 5 +-- src/mo_types/type.mli | 3 +- test/run-drun/await-sugar.mo | 28 +++++++-------- test/run-drun/general_await.mo | 20 +++++------ 7 files changed, 69 insertions(+), 67 deletions(-) diff --git a/design/scoped-await.md b/design/scoped-await.md index d6a41488c50..6bc0ed30c88 100644 --- a/design/scoped-await.md +++ b/design/scoped-await.md @@ -338,10 +338,10 @@ Assuming the following requests: is rejected because, once annotated: ``` - let t:async<@>U = async<@1>{ await t;}; // bad await since t : Async<@>U U + let t:async<$>U = async<$1>{ await t;}; // bad await since t : Async<$>U U ``` -Ruled out by index scoping (`@1 <> @ `) +Ruled out by index scoping (`$1 <> $ `) #### Indirect deadlock @@ -355,13 +355,13 @@ Ruled out by index scoping (`@1 <> @ `) is rejected because, once annotated: ``` - async<@> { - let a1 : async<@> = async<@1> { await a2; }; // bad await since a2 : Async<@>() () - let a2 : async<@> = async<@2> { await a1; }; // bad await since a1 : Async<@>() () + async<$> { + let a1 : async<$> = async<$1> { await a2; }; // bad await since a2 : Async<$>() () + let a2 : async<$> = async<$2> { await a1; }; // bad await since a1 : Async<$>() () } ``` -since `@1 <> @` and `@2` <> `@`. +since `$1 <> $` and `$2` <> `$`. ### Imperative deadlock @@ -378,14 +378,14 @@ The informal example: that attempts to tie an imperative knot, is rejected by this system. -Explicitly, the outer and nested async would have distinct parameters `<@>` and `<@2>`, so the await at type `async<@2>Nat` on `x` -(of type `async<@>Nat` (with the outer parameter) would actually be illegal: +Explicitly, the outer and nested async would have distinct parameters `<$>` and `<$2>`, so the await at type `async<$2>Nat` on `x` +(of type `async<$>Nat` (with the outer parameter) would actually be illegal: ``` -async<@> { - var x : async<@> Nat = async<@1> 0; - x := async<@2>{ - await x // illegal: this await requires async<@2>Nat (not async<@>Nat) +async<$> { + var x : async<$> Nat = async<$1> 0; + x := async<$2>{ + await x // illegal: this await requires async<$2>Nat (not async<$>Nat) }; } ``` @@ -401,51 +401,51 @@ Principle: Desugaring should be: ### Basic idea: -(`@` is a new type identifier, reserved for scopes only, intially defined as 'Any') +(`$` is a new type identifier, reserved for scopes only, intially defined as 'Any') Parsing: -* inserts `<@,...>` type binders for missing scope binders (in types and terms); -* adds missing `<@>` bindings to async returning functions with missing async indices. +* inserts `<$,...>` type binders for missing scope binders (in types and terms); +* adds missing `<$>` bindings to async returning functions with missing async indices. Elaboration: -* Elaboration ensures `@` is bound to an appropriate constructor, shadowing any previous `@`-binding to ensure lexical scoping. +* Elaboration ensures `$` is bound to an appropriate constructor, shadowing any previous `$`-binding to ensure lexical scoping. Syntactic sugar (during parse, applied bottom up as we construct types and terms) ``` -(async T)^ := async<@> (T^) +(async T)^ := async<$> (T^) -(<...>T1 -> async T2)^ := (@ not in ...) - <@,...^>T1^ -> (async T2)^ +(<...>T1 -> async T2)^ := ($ not in ...) + <$,...^>T1^ -> (async T2)^ -(shared? f<...>() : async T = e)^ := (@ not in ...) - shared? f<@,...^>(^) : (async T)^ = e^ +(shared? f<...>() : async T = e)^ := ($ not in ...) + shared? f<$,...^>(^) : (async T)^ = e^ -(shared? f<...>() : async T { e })^ := (@ not in ...) - shared? f<@,...^>(^) : (async T)^ = async<@> e^ +(shared? f<...>() : async T { e })^ := ($ not in ...) + shared? f<$,...^>(^) : (async T)^ = async<$> e^ -(shared f<...>() : () = e)^ := (@ not in ...) - shared f<@,...^>(^) : () = e^ +(shared f<...>() : () = e)^ := ($ not in ...) + shared f<$,...^>(^) : () = e^ -(shared f<...>() { e })^ := (@ not in ...) - shared f<@,...^>(^) : () = e^ +(shared f<...>() { e })^ := ($ not in ...) + shared f<$,...^>(^) : () = e^ (async e)^ := - async<@> e^ + async<$> e^ ``` ### Elaboration -During elaboration, we rebind `@` to the current scope -identifier (aliasing `@` with some type parameter `X` if necessary) so +During elaboration, we rebind `$` to the current scope +identifier (aliasing `$` with some type parameter `X` if necessary) so that: * references inserted during parsing elaborate to the nearest appropiate binding -Note that in a function type or definition with type parameters, `@` +Note that in a function type or definition with type parameters, `$` either shadows one of those eponymous type parameters (if introduced by de-sugaring) or it retains its outer meaning. @@ -466,7 +466,7 @@ the fact that we don't support explicit binding). For compiled programs we restrict the inital capability to `NullCap`, so that sends and async can only occur in shared functions. -For interpreted programs we use the initial capability `Async @` so +For interpreted programs we use the initial capability `Async $` so that programs can `async` and `send` at top-level (but not `await`). ### Queries @@ -492,7 +492,7 @@ See the code for details. ### Refinements Since users may find it odd that we can instantiate the index at any -type, it might be better to define "type @ = Non" and always bound +type, it might be better to define "type $ = Non" and always bound index-parameters by `Non`. Then the top-level choice of index really is unique since `Non`, and any `Non`-bounded type parameter, are the only types bounded by `Non` and thus suitable for uses as index diff --git a/src/mo_def/syntax.ml b/src/mo_def/syntax.ml index 734fb9011e9..89d0f07bbbb 100644 --- a/src/mo_def/syntax.ml +++ b/src/mo_def/syntax.ml @@ -249,7 +249,7 @@ let (@=) it at = Source.({it; at; note = None}) let scope_typ region = Source.( { it = PathT ( - { it = IdH { it = Type.scope_var; at = region; note = () }; + { it = IdH { it = Type.default_scope_var; at = region; note = () }; at = no_region; note = Type.Pre }, []); @@ -257,7 +257,7 @@ let scope_typ region = note = Type.Pre }) let scope_bind var = - { var = (Type.scope_var ^ var) @@ no_region; + { var = Type.scope_var var @@ no_region; sort = Type.Scope @@ no_region; bound = PrimT "Any" @! no_region } @= no_region diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 04f1a5049eb..b4ab992b9a3 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -18,7 +18,7 @@ type ret_env = T.typ option let initial_scope = { Scope.empty with - Scope.typ_env = T.Env.singleton T.scope_var C.top_cap; + Scope.typ_env = T.Env.singleton T.default_scope_var C.top_cap; Scope.con_env = T.ConSet.singleton C.top_cap; } @@ -270,10 +270,10 @@ let check_shared_return env at sort c ts = let rec infer_async_cap env sort cs tbs = match sort, cs, tbs with | (T.Shared T.Write | T.Local) , c::_, { T.sort = T.Scope; _ }::_ -> - { env with typs = T.Env.add T.scope_var c env.typs; + { env with typs = T.Env.add T.default_scope_var c env.typs; async = C.AsyncCap c } | (T.Shared T.Query) , c::_, { T.sort = T.Scope; _ }::_ -> - { env with typs = T.Env.add T.scope_var c env.typs; + { env with typs = T.Env.add T.default_scope_var c env.typs; async = C.QueryCap c } | T.Shared _, _, _ -> assert false (* impossible given sugaring *) | _ -> { env with async = C.NullCap } @@ -1019,7 +1019,7 @@ and infer_exp'' env exp : T.typ = error_in [Flags.ICMode] env exp.at "unsupported async block"; let t1, next_cap = check_AsyncCap env "async expression" exp.at in let c, tb, ce, cs = check_typ_bind env typ_bind in - let ce_scope = T.Env.add T.scope_var c ce in (* pun scope var with c *) + let ce_scope = T.Env.add T.default_scope_var c ce in (* pun scope var with c *) let env' = {(adjoin_typs env ce_scope cs) with labs = T.Env.empty; rets = Some T.Pre; async = next_cap c} in let t = infer_exp env' exp1 in @@ -1110,7 +1110,7 @@ and check_exp' env0 t exp : T.typ = (T.string_of_typ_expand t1) (T.string_of_typ_expand t1'); let c, tb, ce, cs = check_typ_bind env tb in - let ce_scope = T.Env.add T.scope_var c ce in (* pun scope var with c *) + let ce_scope = T.Env.add T.default_scope_var c ce in (* pun scope var with c *) let env' = {(adjoin_typs env ce_scope cs) with labs = T.Env.empty; rets = Some t'; async = next_cap c} in check_exp env' t' exp1; diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index 0c17ef6e5b9..b713dcf479b 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -1112,9 +1112,10 @@ module Env = Env.Make(String) (* Scopes *) -let scope_var = "@" +let scope_var var = "$" ^ var +let default_scope_var = scope_var "" let scope_bound = Any -let scope_bind = { var = scope_var; sort = Scope; bound = scope_bound } +let scope_bind = { var = default_scope_var; sort = Scope; bound = scope_bound } (* Pretty printing *) diff --git a/src/mo_types/type.mli b/src/mo_types/type.mli index 80a98af86cc..acbcb3ccc99 100644 --- a/src/mo_types/type.mli +++ b/src/mo_types/type.mli @@ -209,7 +209,8 @@ module Env : Env.S with type key = string (* Scope bindings *) -val scope_var : var +val scope_var : var -> var +val default_scope_var : var val scope_bound : typ val scope_bind : bind diff --git a/test/run-drun/await-sugar.mo b/test/run-drun/await-sugar.mo index 4a725b93983..4af089e9620 100644 --- a/test/run-drun/await-sugar.mo +++ b/test/run-drun/await-sugar.mo @@ -8,7 +8,7 @@ public func f0 () : async () {}; public func test0 () : async () { await f0 ();}; /* -public func f1 () : async<@> () {}; // this is now illegal since f1 not (implicitly) parametric +public func f1 () : async<$> () {}; // this is now illegal since f1 not (implicitly) parametric public func test1 () : async () { // f1 not parametric, can call f1(), but can't await f1(); @@ -17,18 +17,18 @@ public func test1 () : async () { */ /* -public func f2<@>() : async<@> () {}; +public func f2<$>() : async<$> () {}; public func test2(): async () { await f2(); - await f2<@>(); + await f2<$>(); }; -public func f2b<@>() : async () {}; +public func f2b<$>() : async () {}; public func test2b() : async () { await f2b(); - await f2b<@>(); + await f2b<$>(); }; */ @@ -36,33 +36,33 @@ public func f3() : async () {}; public func test3 () : async () { await f3(); // scope passed as implicit first argument -/* await f3<@,Int>(); // scope passed as explicit first argument */ +/* await f3<$,Int>(); // scope passed as explicit first argument */ }; /* -public func f4<@,B<:Int>() : async<@> () {}; // explict scope parameter 1 +public func f4<$,B<:Int>() : async<$> () {}; // explict scope parameter 1 public func test4() : async () { await f4(); // scope passed as implicit first argument - await f4<@,Int>(); // scope passed as exlicit first argument + await f4<$,Int>(); // scope passed as exlicit first argument }; -public func f5() : async<@> () {}; // explict scope parameter 2 +public func f5() : async<$> () {}; // explict scope parameter 2 public func test5() : async () { await f5(); // scope passed as implicit second argument -// await f5(); +// await f5(); } ; */ /* -public func f6() : async () {}; // explict scope parameter 2, implicit index +public func f6() : async () {}; // explict scope parameter 2, implicit index public func test6() : async () { await f6(); // scope passed as implicit second argument - await f6(); + await f6(); } ; */ @@ -74,14 +74,14 @@ public func f7(n:Int) : async() { switch (n % 3) { case 0 (await f7(n-1)); case 1 (await f7(n-1)); - case 2 (await f7<@,A>(n-1)); + case 2 (await f7<$,A>(n-1)); case _ (); }; }; public func test7 () : async () { await f7(1); // scope passed as implicit argument -/* await f7<@,Int>(1); */ +/* await f7<$,Int>(1); */ }; */ diff --git a/test/run-drun/general_await.mo b/test/run-drun/general_await.mo index b629b5bb259..a6ff3e822fc 100644 --- a/test/run-drun/general_await.mo +++ b/test/run-drun/general_await.mo @@ -1,27 +1,27 @@ import Prim "mo:prim"; -// test for explicit scope parameterization (disabled for now, uncomment /*<@>*/ once supported) +// test for explicit scope parameterization (disabled for now, uncomment /*<$>*/ once supported) actor Await { - public shared func Ack/*<@>*/() : async/*<@>*/ (){ + public shared func Ack/*<$>*/() : async/*<$>*/ (){ Prim.debugPrint "Ack" }; - public shared func Request/*<@>*/(i : Int) : async/*<@>*/ Int { + public shared func Request/*<$>*/(i : Int) : async/*<$>*/ Int { Prim.debugPrintInt(i); return i; }; // Static parallel waiting: - public shared func PA/*<@>*/() : async/*<@>*/ () { + public shared func PA/*<$>*/() : async/*<$>*/ () { let a1 = Ack(); let a2 = Ack(); await a1; await a2; }; - public shared func PR/*<@>*/() : async/*<@>*/(Int,Int) { + public shared func PR/*<$>*/() : async/*<$>*/(Int,Int) { let a1 = Request(1); let a2 = Request(2); (await a1, await a2) @@ -29,7 +29,7 @@ actor Await { // Dynamic parallel waiting for acknowledgements - public shared func DPA/*<@>*/() : async/*<@>*/() { + public shared func DPA/*<$>*/() : async/*<$>*/() { let os = Prim.Array_init(10, null); for (i in os.keys()) { os[i] := ? (Ack()); @@ -44,7 +44,7 @@ actor Await { // Dynamic parallel waiting (with results) - public shared func DPR/*<@>*/() : async/*<@>*/ [Int] { + public shared func DPR/*<$>*/() : async/*<$>*/ [Int] { let os = Prim.Array_init(10, null); for (i in os.keys()) { os[i] := ? (Request(i)); @@ -61,7 +61,7 @@ actor Await { // Recursive parallel waiting - public shared func RPA/*<@>*/(n:Nat) : async/*<@>*/() { + public shared func RPA/*<$>*/(n:Nat) : async/*<$>*/() { if (n == 0) () else { let a = Ack(); @@ -74,7 +74,7 @@ actor Await { public type List = ?(Int,List); - public shared func RPR/*<@>*/(n:Nat) : async/*<@>*/ List { + public shared func RPR/*<$>*/(n:Nat) : async/*<$>*/ List { if (n == 0) null else { let a = Request(n); @@ -84,7 +84,7 @@ actor Await { }; - public shared func Test/*<@>*/() : async/*<@>*/() { + public shared func Test/*<$>*/() : async/*<$>*/() { await PA(); From 0ad74c9329ab934e7ad75cc383be009aa4e3a4ac Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 22 Jan 2020 15:32:11 +0000 Subject: [PATCH 0990/1176] missing test output --- test/run-drun/ok/await-sugar.ic-stub-run.ok | 2 +- test/run-drun/ok/general_await.ic-stub-run.ok | 2 +- test/run-drun/ok/general_await_implicit.ic-stub-run.ok | 2 +- test/run-drun/ok/scope-example-implicit.tc.ok | 4 ++-- test/run-drun/ok/scope-example.tc.ok | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/test/run-drun/ok/await-sugar.ic-stub-run.ok b/test/run-drun/ok/await-sugar.ic-stub-run.ok index 3317e0c3469..1a26642aeb8 100644 --- a/test/run-drun/ok/await-sugar.ic-stub-run.ok +++ b/test/run-drun/ok/await-sugar.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update test(0x4449444c0000) diff --git a/test/run-drun/ok/general_await.ic-stub-run.ok b/test/run-drun/ok/general_await.ic-stub-run.ok index 270da561546..1b4ca9da8d8 100644 --- a/test/run-drun/ok/general_await.ic-stub-run.ok +++ b/test/run-drun/ok/general_await.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update Test(0x4449444c0000) diff --git a/test/run-drun/ok/general_await_implicit.ic-stub-run.ok b/test/run-drun/ok/general_await_implicit.ic-stub-run.ok index 270da561546..1b4ca9da8d8 100644 --- a/test/run-drun/ok/general_await_implicit.ic-stub-run.ok +++ b/test/run-drun/ok/general_await_implicit.ic-stub-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x0000000000000400 +← completed: canister-id = 0x2a01 → install ← completed → update Test(0x4449444c0000) diff --git a/test/run-drun/ok/scope-example-implicit.tc.ok b/test/run-drun/ok/scope-example-implicit.tc.ok index 15f8e4dc915..a111cb497e6 100644 --- a/test/run-drun/ok/scope-example-implicit.tc.ok +++ b/test/run-drun/ok/scope-example-implicit.tc.ok @@ -1,4 +1,4 @@ scope-example-implicit.mo:10.12-10.19: type error, expression of type - async<@anon-async-8.12> Int + async<$anon-async-8.12> Int cannot produce expected type - async<@f> Int + async<$f> Int diff --git a/test/run-drun/ok/scope-example.tc.ok b/test/run-drun/ok/scope-example.tc.ok index 921638355a6..3df64817fa6 100644 --- a/test/run-drun/ok/scope-example.tc.ok +++ b/test/run-drun/ok/scope-example.tc.ok @@ -1,4 +1,4 @@ scope-example.mo:12.13-12.27: type error, expression of type - async<@anon-async-10.12> Int + async<$anon-async-10.12> Int cannot produce expected type - async<@anon-async-6.60> Int + async<$anon-async-6.60> Int From a7c50d1263cb502bbcc7ac5a7ce66481cad954cc Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 22 Jan 2020 16:34:16 +0100 Subject: [PATCH 0991/1176] Fix #945: Do not discard non-typed code (#1146) * Fix #945: Do not discard non-typed code * Remove test for Non completely * Backend: Handle calls to non-typed functions in general: handle the case of prims with non-typed arguments --- src/codegen/compile.ml | 12 +++++++++++- src/lowering/desugar.ml | 2 -- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 6924dadfbfa..4cb70a0d33a 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -5839,8 +5839,14 @@ let rec compile_lexp (env : E.t) ae lexp = and compile_exp (env : E.t) ae exp = (fun (sr,code) -> (sr, G.with_region exp.at code)) @@ match exp.it with - | PrimE (p, es) -> + | PrimE (p, es) when List.exists (fun e -> Type.is_non e.note.note_typ) es -> + (* Handle dead code separately, so that we can rely on useful type + annotations below *) + SR.Unreachable, + G.concat_map (compile_exp_ignore env ae) es ^^ + G.i Unreachable + | PrimE (p, es) -> (* for more concise code when all arguments and result use the same sr *) let const_sr sr inst = sr, G.concat_map (compile_exp_as env ae sr) es ^^ inst in @@ -6398,6 +6404,10 @@ and compile_exp_as env ae sr_out e = code ^^ StackRep.adjust env sr_in sr_out ) +and compile_exp_ignore env ae e = + let sr, code = compile_exp env ae e in + code ^^ StackRep.drop env sr + and compile_exp_as_opt env ae sr_out_o e = let sr_in, code = compile_exp env ae e in G.with_region e.at ( diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 92cb87a46df..5221e706fa5 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -122,8 +122,6 @@ and exp' at note = function | S.CallE ({it=S.AnnotE ({it=S.PrimE p;_},_);_}, _, e) -> I.PrimE (I.OtherPrim p, [exp e]) | S.CallE (e1, inst, e2) -> - let t = e1.Source.note.S.note_typ in - if T.is_non t then unreachableE.it else let inst = List.map (fun t -> t.Source.note) inst in I.PrimE (I.CallPrim inst, [exp e1; exp e2]) | S.BlockE [] -> unitE.it From 610549548fef24403a3b5184c16885d7f48266f3 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 22 Jan 2020 15:55:59 +0000 Subject: [PATCH 0992/1176] missing test output --- test/fail/ok/asyncret2.tc.ok | 2 +- test/fail/ok/illegal-await.tc.ok | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/test/fail/ok/asyncret2.tc.ok b/test/fail/ok/asyncret2.tc.ok index 5eb51764c05..be0c94c3ff3 100644 --- a/test/fail/ok/asyncret2.tc.ok +++ b/test/fail/ok/asyncret2.tc.ok @@ -1,4 +1,4 @@ asyncret2.mo:1.54-1.57: type error, expression of type - async<@call3> Int + async<$call3> Int cannot produce expected type Int diff --git a/test/fail/ok/illegal-await.tc.ok b/test/fail/ok/illegal-await.tc.ok index 324e2c5ba1b..1d990be4a8f 100644 --- a/test/fail/ok/illegal-await.tc.ok +++ b/test/fail/ok/illegal-await.tc.ok @@ -1,5 +1,5 @@ -illegal-await.mo:3.30-3.37: type error, ill-scoped await: expected async type from current scope @anon-async-3.22, found async type from other scope @ -illegal-await.mo:12.32-12.40: type error, ill-scoped await: expected async type from current scope @anon-async-12.25, found async type from other scope @anon-async-11.10 -illegal-await.mo:13.32-13.40: type error, ill-scoped await: expected async type from current scope @anon-async-13.25, found async type from other scope @anon-async-11.10 -illegal-await.mo:24.7-24.14: type error, ill-scoped await: expected async type from current scope @anon-async-23.11, found async type from other scope @anon-async-21.10 -illegal-await.mo:33.5-33.12: type error, ill-scoped await: expected async type from current scope @Rec, found async type from other scope @/1 +illegal-await.mo:3.30-3.37: type error, ill-scoped await: expected async type from current scope $anon-async-3.22, found async type from other scope @ +illegal-await.mo:12.32-12.40: type error, ill-scoped await: expected async type from current scope $anon-async-12.25, found async type from other scope $anon-async-11.10 +illegal-await.mo:13.32-13.40: type error, ill-scoped await: expected async type from current scope $anon-async-13.25, found async type from other scope $anon-async-11.10 +illegal-await.mo:24.7-24.14: type error, ill-scoped await: expected async type from current scope $anon-async-23.11, found async type from other scope $anon-async-21.10 +illegal-await.mo:33.5-33.12: type error, ill-scoped await: expected async type from current scope $Rec, found async type from other scope $ From 8228aa409f19933c0d2a01270cbb326d41bb2624 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Wed, 22 Jan 2020 17:11:18 +0100 Subject: [PATCH 0993/1176] QC: inter-actor message sends and encoding tests (#1094) * create an actor * intro Drun embedder use it like this: - `cd test` - `env PATH=$PATH:../src $(nix-build ../default.nix -A qc-motoko)/bin/qc-motoko -p inter --quickcheck-replay=628274` * reference Turtle issue * workarounds for stuff missing from Turtle/Filesystem these should be upstreamed See: https://github.com/Gabriel439/Haskell-Turtle-Library/issues/368 https://mail.haskell.org/pipermail/haskell-cafe/2012-October/104030.html * add prop_matchActorNat * add prop_matchActorInt * break out embedder-related stuff and clean up in general --- default.nix | 2 +- test/random/Embedder.hs | 68 +++++++++++++++++++++++++++++++++++++ test/random/Main.hs | 67 ++++++++++++++++++++---------------- test/random/Turtle/Pipe.hs | 53 +++++++++++++++++++++++++++++ test/random/qc-motoko.cabal | 6 ++-- 5 files changed, 163 insertions(+), 33 deletions(-) create mode 100644 test/random/Embedder.hs create mode 100644 test/random/Turtle/Pipe.hs diff --git a/default.nix b/default.nix index 0f9d323ed14..57e9b6526c4 100644 --- a/default.nix +++ b/default.nix @@ -222,7 +222,7 @@ rec { let qc = testDerivation { name = "test-qc"; - buildInputs = [ moc /* nixpkgs.wasm */ wasmtime haskellPackages.qc-motoko ]; + buildInputs = [ moc /* nixpkgs.wasm */ wasmtime drun haskellPackages.qc-motoko ]; checkPhase = '' qc-motoko${nixpkgs.lib.optionalString (replay != 0) " --quickcheck-replay=${toString replay}"} diff --git a/test/random/Embedder.hs b/test/random/Embedder.hs new file mode 100644 index 00000000000..9b615288711 --- /dev/null +++ b/test/random/Embedder.hs @@ -0,0 +1,68 @@ +{-# language OverloadedStrings, {-PartialTypeSignatures,-} ScopedTypeVariables, TupleSections #-} + +module Embedder (Embedder(..), WasmAPI(..), embedder, embedderCommand, addCompilerArgs, addEmbedderArgs, invokeEmbedder) where + +import Test.QuickCheck + +import Turtle +import Turtle.Pipe + +import Control.Monad.Catch +import GHC.IO.Exception (IOException) +import Data.IORef + +data WasmAPI = DontPrint | WASI + +data Embedder = Reference | WasmTime WasmAPI | Drun + +instance Arbitrary Embedder where arbitrary = elements [Reference, WasmTime DontPrint, WasmTime WASI, Drun] +instance Arbitrary WasmAPI where arbitrary = elements [DontPrint, WASI] + +embedderCommand Reference = "wasm" +embedderCommand (WasmTime _) = "wasmtime" +embedderCommand Drun = "drun" + +addCompilerArgs Reference = ("-no-system-api" :) +addCompilerArgs (WasmTime DontPrint) = ("-no-system-api" :) +addCompilerArgs (WasmTime WASI) = ("-wasi-system-api" :) +addCompilerArgs Drun = id + +addEmbedderArgs Reference = id +addEmbedderArgs (WasmTime _) = ("--disable-cache" :) . ("--cranelift" :) +addEmbedderArgs Drun = ("--extra-batches" :) . ("100" :) + +invokeEmbedder :: Embedder -> Turtle.FilePath -> IO (ExitCode, Text, Text) +invokeEmbedder embedder wasm = go embedder + where fileArg = fromString . encodeString + Right wasmFile = toText wasm + revconcating = Fold (flip (:)) [] id + go :: Embedder -> IO (ExitCode, Text, Text) + go Drun = do + fuzz <- newIORef "" + + sh $ do + let Right w = toText wasm + control = wasm <.> "fifo" + rm (fileArg control) `catch` \(_ :: GHC.IO.Exception.IOException) -> pure () -- rm -f + let Right c = toText control + procs "mkfifo" [c] empty + consumer <- forkShell $ inshell ("drun --extra-batches 100 " <> c) empty + let install = unsafeTextToLine $ format ("install ic:2A012B "%s%" 0x") w + + pipe (fileArg control) (pure install + <|> "ingress ic:2A012B do 0x4449444c0000") + lns <- wait consumer + view lns + let errors = grep (has "Err: " <|> has "Reject: ") lns + linesToText . reverse <$> fold errors revconcating >>= liftIO <$> writeIORef fuzz + + (ExitSuccess, "",) <$> readIORef fuzz + + go _ = procStrictWithErr (embedderCommand embedder) (addEmbedderArgs embedder [wasmFile]) empty + -- forkShell :: Show a => Shell a -> Shell (Async (Shell a)) + forkShell shell = do a <- fork (fold shell revconcating) + pure (select . reverse <$> a) + + +embedder :: Embedder +embedder = WasmTime DontPrint diff --git a/test/random/Main.hs b/test/random/Main.hs index eaf1fc6ada6..eeb4a5a6953 100644 --- a/test/random/Main.hs +++ b/test/random/Main.hs @@ -8,7 +8,6 @@ module Main where import Control.Applicative -import Control.Monad import Test.QuickCheck.Monadic import Test.Tasty import Test.Tasty.QuickCheck as QC hiding ((.&.)) @@ -24,9 +23,10 @@ import qualified Data.Word import Data.Bits (Bits(..), FiniteBits(..)) import Numeric -import System.Process hiding (proc) import Turtle --- import Debug.Trace (traceShowId) +import Embedder +-- import Debug.Trace (traceShowId, traceShow) + main = defaultMain tests where tests :: TestTree @@ -60,37 +60,31 @@ utf8Props = testGroup "UTF-8 coding" matchingProps = testGroup "Pattern matching" [ QC.testProperty "intra-actor" $ prop_matchStructured , QC.testProperty "inter-actor" $ prop_matchInActor + , QC.testProperty "encoded-Nat" $ prop_matchActorNat + , QC.testProperty "encoded-Int" $ prop_matchActorInt ] -data Embedder = Reference | WasmTime - -instance Arbitrary Embedder where arbitrary = elements [Reference, WasmTime] - -embedderCommand Reference = "wasm" -embedderCommand WasmTime = "wasmtime" - -addEmbedderArgs Reference = id -addEmbedderArgs WasmTime = ("--disable-cache" :) . ("--cranelift" :) - -embedder :: Embedder -embedder = WasmTime - withPrim :: Line -> Line withPrim = (fromString "import Prim \"mo:prim\";" <>) -(runScriptNoFuzz, runScriptWantFuzz) = (runner ExitSuccess id, runner (ExitFailure 1) not) - where runner reqOutcome relevant name testCase = - let as = name <.> "mo" - wasm = name <.> "wasm" - fileArg = fromString . encodeString - script = do Turtle.output as $ withPrim <$> fromString testCase - res@(exitCode, _, _) <- procStrictWithErr "moc" - ["-no-system-api", "-no-check-ir", fileArg as] empty - if ExitSuccess == exitCode - then (True,) <$> procStrictWithErr (embedderCommand embedder) (addEmbedderArgs embedder [fileArg wasm]) empty - else pure (False, res) - in run script >>= assertOutcomeCheckingFuzz reqOutcome relevant +runner :: Embedder -> ExitCode -> (Bool -> Bool) -> Turtle.FilePath -> String -> PropertyM IO () +runner embedder reqOutcome relevant name testCase = + let as = name <.> "mo" + wasm = name <.> "wasm" + fileArg = fromString . encodeString + script = do Turtle.output as $ withPrim <$> fromString testCase + res@(exitCode, _, _) <- procStrictWithErr "moc" + (addCompilerArgs embedder ["-no-check-ir", fileArg as]) empty + if ExitSuccess == exitCode + then (True,) <$> invokeEmbedder embedder wasm + else pure (False, res) + in run script >>= assertOutcomeCheckingFuzz reqOutcome relevant + +(runScriptNoFuzz, runScriptWantFuzz) = (runEmbedder ExitSuccess id, runEmbedder (ExitFailure 1) not) + where runEmbedder = runner embedder +(drunScriptNoFuzz, drunScriptWantFuzz) = (runEmbedder ExitSuccess id, runEmbedder (ExitFailure 1) not) + where runEmbedder = runner Drun prop_explodeConcat :: UTF8 String -> Property prop_explodeConcat (UTF8 str) = monadicIO $ do @@ -300,12 +294,25 @@ prop_matchInActor (Matching a) = mobile a mobile :: (AnnotLit t, MOValue t) => (MOTerm t, t) -> Property mobile (tm, v) = monadicIO $ do - let testCase = "/*let a = actor { public func match (b : " <> typed <> ") : async Bool = async { true } };*/ assert (switch (" <> expr <> " : " <> typed <> ") { case (" <> eval'd <> ") true; case _ false })" + let testCase = "actor { public func match (b : " <> typed <> ") : async () { assert (switch b { case (" <> eval'd <> ") true; case _ false }) }; public func do () : async () { let res = await match (" <> expr <> " : " <> typed <> "); return res } };" eval'd = unparse v typed = unparseType v expr = unparseMO tm - runScriptNoFuzz "matchMobile" testCase + drunScriptNoFuzz "matchMobile" testCase + + +prop_matchActorNat :: Neuralgic Natural -> Property +prop_matchActorNat nat = monadicIO $ do + let testCase = format ("actor { public func match (n : Nat) : async () { assert (switch n { case ("%d%") true; case _ false }) }; public func do () : async () { let res = await match ("%d%" : Nat); return res } };") eval'd eval'd + eval'd = evalN nat + drunScriptNoFuzz "matchActorNat" (Data.Text.unpack testCase) + +prop_matchActorInt :: Neuralgic Integer -> Property +prop_matchActorInt int = monadicIO $ do + let testCase = format ("actor { public func match (i : Int) : async () { assert (switch i { case ("%d%") true; case _ false }) }; public func do () : async () { let res = await match ("%d%" : Int); return res } };") eval'd eval'd + eval'd = evalN int + drunScriptNoFuzz "matchActorInt" (Data.Text.unpack testCase) -- instances of MOValue describe "ground values" in -- Motoko. These can appear in patterns and have diff --git a/test/random/Turtle/Pipe.hs b/test/random/Turtle/Pipe.hs new file mode 100644 index 00000000000..0039b03d797 --- /dev/null +++ b/test/random/Turtle/Pipe.hs @@ -0,0 +1,53 @@ +module Turtle.Pipe (pipe, writeonlyblocking) where + +import Turtle + +-- for missing stuff +import qualified System.IO +import qualified GHC.IO.Handle.FD +import qualified Control.Exception +import qualified Data.Text.IO (hPutStrLn) +import qualified Control.Monad.Managed + + +-- Stuff that is missing from Turtle + +-- | Stream lines of `Text` to a file, blocking + +pipe :: MonadIO io => Turtle.FilePath -> Shell Line -> io () +pipe file s = sh (do + handle <- using (writeonlyblocking file) + line <- s + liftIO (Data.Text.IO.hPutStrLn handle (lineToText line)) ) + + +-- | Acquire a `Managed` blocking write-only `Handle` from a `FilePath` +writeonlyblocking :: Control.Monad.Managed.MonadManaged managed => Turtle.FilePath -> managed System.IO.Handle +writeonlyblocking file = using (managed (withBlockingTextFile file System.IO.WriteMode)) + + +-- Stuff that is missing from Filesystem + +-- | Open a file in text mode, and pass its 'Handle' to a provided +-- computation. The 'Handle' will be automatically closed when the +-- computation returns. +-- +-- This computation throws 'IOError' on failure. See “Classifying +-- I/O errors” in the "System.IO.Error" documentation for information on +-- why the failure occured. +withBlockingTextFile :: Turtle.FilePath -> System.IO.IOMode -> (System.IO.Handle -> IO a) -> IO a +withBlockingTextFile path mode = Control.Exception.bracket (openBlockingTextFile path mode) System.IO.hClose + +-- | Open a file in text mode, and return an open 'Handle'. The 'Handle' +-- should be closed with 'IO.hClose' when it is no longer needed. +-- +-- 'withBlockingTextFile' is easier to use, because it will handle the +-- 'Handle'’s lifetime automatically. +-- +-- This computation throws 'IOError' on failure. See “Classifying +-- I/O errors” in the "System.IO.Error" documentation for information on +-- why the failure occured. +openBlockingTextFile path = GHC.IO.Handle.FD.openFileBlocking (encodeString path) + + +-- See discussion https://mail.haskell.org/pipermail/haskell-cafe/2012-October/104030.html diff --git a/test/random/qc-motoko.cabal b/test/random/qc-motoko.cabal index 50a61ad5e8a..dcf78743651 100644 --- a/test/random/qc-motoko.cabal +++ b/test/random/qc-motoko.cabal @@ -1,7 +1,7 @@ cabal-version: 2.4 name: qc-motoko -version: 0 +version: 1 synopsis: generate randomised tests for Motoko -- description: author: Gabor Greif @@ -12,11 +12,13 @@ extra-source-files: CHANGELOG.md executable qc-motoko main-is: Main.hs - -- other-modules: + other-modules: Embedder, Turtle.Pipe other-extensions: ConstraintKinds, StandaloneDeriving, DataKinds, KindSignatures, GADTs, MultiParamTypeClasses build-depends: base ^>=4.12.0.0 , text ^>=1.2.3.1 , process + , exceptions + , managed , QuickCheck , quickcheck-text , quickcheck-unicode From fc09987c26b2cfcecb1a7a1c0ce8f1adcb721128 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 22 Jan 2020 18:33:46 +0100 Subject: [PATCH 0994/1176] Backend: Remove code for local actors (#1140) * Backend: Remove code for local actors because * it is not supported by IC at the moment * there is a horrible and wrong hack about including the prelude * capturing imports not supported right now * the code is hardly exercised (only one test case needs to be restricted to the IR.) * in general, a bunch of complexity of dubious value * will allow me to remove that backdoor support from `ic-stub`, making it a better candidate at a reference implementation If and when we get dynamic actor creation on our platform, and if we indeed want to expose that via local actor expressions, we can resurrect (or re-implment more cleanly) this code. Or maybe we get in-canitster actors somehow and have to implement this differently anyways. * Reinstantiate local actor checks in typing --- src/codegen/compile.ml | 122 +----------------- src/codegen/compile.mli | 2 +- src/mo_frontend/typing.ml | 6 +- src/pipeline/pipeline.ml | 2 +- test/run-drun/AST-64.mo | 2 +- test/run-drun/ok/AST-64.ic-stub-run.ok | 4 - test/run-drun/ok/pass-references.comp-stub.ok | 2 + .../ok/pass-references.comp-stub.ret.ok | 1 + .../ok/pass-references.ic-stub-run.ok | 10 -- test/run-drun/ok/self-shadow.comp-stub.ok | 2 + test/run-drun/ok/self-shadow.comp-stub.ret.ok | 1 + test/run-drun/ok/self-shadow.ic-stub-run.ok | 4 - test/run-drun/ok/unsupported.comp-stub.ok | 8 +- 13 files changed, 25 insertions(+), 141 deletions(-) delete mode 100644 test/run-drun/ok/AST-64.ic-stub-run.ok create mode 100644 test/run-drun/ok/pass-references.comp-stub.ok create mode 100644 test/run-drun/ok/pass-references.comp-stub.ret.ok delete mode 100644 test/run-drun/ok/pass-references.ic-stub-run.ok create mode 100644 test/run-drun/ok/self-shadow.comp-stub.ok create mode 100644 test/run-drun/ok/self-shadow.comp-stub.ret.ok delete mode 100644 test/run-drun/ok/self-shadow.ic-stub-run.ok diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 4cb70a0d33a..7e684b72454 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -99,7 +99,7 @@ in one big record, for convenience). The fields fall into the following categories: 1. Static global fields. Never change. - Example: whether we are compiling with -no-system-api; the prelude code + Example: whether we are compiling with -no-system-api 2. Immutable global fields. Change in a well-scoped manner. Example: Mapping from Motoko names to their location. @@ -153,7 +153,6 @@ module E = struct (* Global fields *) (* Static *) mode : Flags.compile_mode; - prelude : Ir.prog; (* The prelude. Re-used when compiling actors *) rts : Wasm_exts.CustomModule.extended_module option; (* The rts. Re-used when compiling actors *) trap_with : t -> string -> G.t; (* Trap with message; in the env for dependency injection *) @@ -191,10 +190,9 @@ module E = struct (* The initial global environment *) - let mk_global mode rts prelude trap_with dyn_mem : t = { + let mk_global mode rts trap_with dyn_mem : t = { mode; rts; - prelude; trap_with; func_types = ref []; func_imports = ref []; @@ -358,10 +356,8 @@ module E = struct Printf.eprintf "Function import not declared: %s\n" name; G.i Unreachable - let get_prelude (env : t) = env.prelude let get_rts (env : t) = env.rts - let get_trap_with (env : t) = env.trap_with let trap_with env msg = env.trap_with env msg let then_trap_with env msg = G.if_ [] (trap_with env msg) G.nop let else_trap_with env msg = G.if_ [] G.nop (trap_with env msg) @@ -4517,9 +4513,6 @@ module VarEnv = struct let (ae_final, setters) = add_argument_locals env ae' names in (ae_final, G.i (LocalSet (nr i)) :: setters) - let in_scope_set (ae : t) = - NameEnv.fold (fun k _ -> Freevars.S.add k) ae.vars Freevars.S.empty - let add_label (ae : t) name (d : G.depth) = { ae with labels = NameEnv.add name d ae.labels } @@ -6368,12 +6361,7 @@ and compile_exp (env : E.t) ae exp = get_k get_r | ActorE (ds, fs, _) -> - SR.Vanilla, - let captured = Freevars.exp exp in - let prelude_names = find_prelude_names env in - if Freevars.M.is_empty (Freevars.diff captured prelude_names) - then actor_lit env ds fs exp.at - else todo_trap env "non-closed actor" (Arrange_ir.exp exp) + fatal "Local actors not supported by backend" | NewObjE (Type.(Object | Module) as _sort, fs, _) -> (* We can enable this warning once we treat everything as static that @@ -6785,32 +6773,6 @@ and compile_const_dec env pre_ae dec : (VarEnv.t -> VarEnv.t) * (E.t -> VarEnv.t | _ -> fatal "compile_const_dec: Unexpected dec form" -and compile_prelude env ae = - (* Allocate the primitive functions *) - let (decs, _flavor) = E.get_prelude env in - let (ae1, code) = compile_prog env ae decs in - (ae1, code) - -(* -This is a horrible hack -When determining whether an actor is closed, we disregard the prelude, because -every actor is compiled with the prelude. -This breaks with shadowing. -This function compiles the prelude, just to find out the bound names. -*) -and find_prelude_names env = - (* Create a throw-away environment *) - let env0 = E.mk_global (E.mode env) None (E.get_prelude env) (fun _ _ -> G.i Unreachable) 0l in - Heap.register_globals env0; - Stack.register_globals env0; - Dfinity.system_imports env0; - RTS.system_imports env0; - let env1 = E.mk_fun_env env0 0l 0 in - let ae = VarEnv.empty_ae in - let (env2, _) = compile_prelude env1 ae in - VarEnv.in_scope_set env2 - - and compile_start_func mod_env (progs : Ir.prog list) : E.func_with_names = let find_last_expr ds e = if ds = [] then [], e.it else @@ -6871,78 +6833,6 @@ and export_actor_field env ae (f : Ir.field) = edesc = nr (FuncExport (nr fi)) }) -(* Local actor *) -and actor_lit outer_env ds fs at = - let wasm_binary = - let mod_env = E.mk_global - (E.mode outer_env) - (E.get_rts outer_env) - (E.get_prelude outer_env) - (E.get_trap_with outer_env) - Stack.end_of_stack in - - Heap.register_globals mod_env; - Stack.register_globals mod_env; - - Dfinity.system_imports mod_env; - RTS.system_imports mod_env; - RTS_Exports.system_exports mod_env; - - let start_fun = Func.of_body mod_env [] [] (fun env -> G.with_region at @@ - let ae0 = VarEnv.empty_ae in - - (* Compile the prelude *) - let (ae1, prelude_code) = compile_prelude env ae0 in - - (* Reverse the fs, to a map from variable to exported name *) - let v2en = E.NameEnv.from_list (List.map (fun f -> (f.it.var, f.it.name)) fs) in - - (* Compile the declarations *) - let (ae3, decls_code) = compile_decs_public env ae1 AllocHow.TopLvl ds v2en Freevars.S.empty in - - (* Export the public functions *) - List.iter (export_actor_field env ae3) fs; - - prelude_code ^^ decls_code) in - let start_fi = E.add_fun mod_env "start" start_fun in - - if E.mode mod_env = Flags.ICMode then Dfinity.export_start mod_env start_fi; - if E.mode mod_env = Flags.StubMode then Dfinity.export_start mod_env start_fi; - - let m = conclude_module mod_env None in - let (_map, wasm_binary) = Wasm_exts.CustomModuleEncode.encode m in - wasm_binary in - - match E.mode outer_env with - | Flags.StubMode -> - let (set_idx, get_idx) = new_local outer_env "idx" in - let (set_len, get_len) = new_local outer_env "len" in - let (set_id, get_id) = new_local outer_env "id" in - (* the module *) - Blob.lit outer_env wasm_binary ^^ - Blob.as_ptr_len outer_env ^^ - (* the arg (not used in motoko yet) *) - compile_unboxed_const 0l ^^ - compile_unboxed_const 0l ^^ - Dfinity.system_call outer_env "stub" "create_canister" ^^ - set_idx ^^ - - get_idx ^^ - Dfinity.system_call outer_env "stub" "created_canister_id_size" ^^ - set_len ^^ - - get_len ^^ Blob.alloc outer_env ^^ set_id ^^ - - get_idx ^^ - get_id ^^ Blob.payload_ptr_unskewed ^^ - compile_unboxed_const 0l ^^ - get_len ^^ - Dfinity.system_call outer_env "stub" "created_canister_id_copy" ^^ - - get_id - | _ -> assert false - - (* Main actor: Just return the initialization code, and export functions as needed *) and main_actor env ae1 ds fs = (* Reverse the fs, to a map from variable to exported name *) @@ -7030,8 +6920,8 @@ and conclude_module env start_fi_o = | None -> emodule | Some rts -> Linking.LinkModule.link emodule "rts" rts -let compile mode module_name rts (prelude : Ir.prog) (progs : Ir.prog list) : Wasm_exts.CustomModule.extended_module = - let env = E.mk_global mode rts prelude Dfinity.trap_with Stack.end_of_stack in +let compile mode module_name rts (progs : Ir.prog list) : Wasm_exts.CustomModule.extended_module = + let env = E.mk_global mode rts Dfinity.trap_with Stack.end_of_stack in Heap.register_globals env; Stack.register_globals env; @@ -7040,7 +6930,7 @@ let compile mode module_name rts (prelude : Ir.prog) (progs : Ir.prog list) : Wa RTS.system_imports env; RTS_Exports.system_exports env; - let start_fun = compile_start_func env (prelude :: progs) in + let start_fun = compile_start_func env progs in let start_fi = E.add_fun env "start" start_fun in let start_fi_o = match E.mode env with | Flags.ICMode | Flags.StubMode -> Dfinity.export_start env start_fi; None diff --git a/src/codegen/compile.mli b/src/codegen/compile.mli index b5073d43fd8..86206519e59 100644 --- a/src/codegen/compile.mli +++ b/src/codegen/compile.mli @@ -1,3 +1,3 @@ open Ir_def -val compile : Mo_config.Flags.compile_mode -> string -> Wasm_exts.CustomModule.extended_module option -> Ir.prog -> Ir.prog list -> Wasm_exts.CustomModule.extended_module +val compile : Mo_config.Flags.compile_mode -> string -> Wasm_exts.CustomModule.extended_module option -> Ir.prog list -> Wasm_exts.CustomModule.extended_module diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index e3ddba4563e..ccc61759610 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -675,7 +675,7 @@ and infer_exp'' env exp : T.typ = ) | ObjE (sort, fields) -> if not in_prog && sort.it = T.Actor then - error_in [Flags.ICMode] env exp.at "non-toplevel actor; an actor can only be declared at the toplevel of a program"; + error_in [Flags.ICMode; Flags.StubMode] env exp.at "non-toplevel actor; an actor can only be declared at the toplevel of a program"; let env' = if sort.it = T.Actor then {env with async = false; in_actor = true} else env in infer_obj env' sort.it fields exp.at | DotE (exp1, id) -> @@ -1839,7 +1839,7 @@ and infer_dec_valdecs env dec : Scope.t = } | ClassD (id, typ_binds, pat, _, sort, _, _) -> if sort.it = T.Actor then - error_in [Flags.ICMode] env dec.at + error_in [Flags.ICMode; Flags.StubMode] env dec.at "actor classes are not supported; use an actor declaration instead"; let rec is_unit_pat p = match p.it with | ParP p -> is_unit_pat p @@ -1902,7 +1902,7 @@ let check_actors scope progs : unit Diag.result = | [] -> () | [d] -> () | (d::ds) when is_actor_dec d -> - recover (error_in [Flags.ICMode] env d.at) + recover (error_in [Flags.ICMode; Flags.StubMode] env d.at) "an actor must be the last declaration in a program" | (d::ds) -> go ds in go prog diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index 61e0aafbc9c..b0b747727e4 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -583,7 +583,7 @@ let compile_prog mode do_link libs progs : Wasm_exts.CustomModule.extended_modul let prog_ir = lower_prog mode initial_stat_env libs progs name in phase "Compiling" name; let rts = if do_link then Some (load_as_rts ()) else None in - Codegen.Compile.compile mode name rts prelude_ir [prog_ir] + Codegen.Compile.compile mode name rts [prelude_ir; prog_ir] let compile_files mode do_link files : compile_result = Diag.bind (load_progs parse_file files initial_stat_env) diff --git a/test/run-drun/AST-64.mo b/test/run-drun/AST-64.mo index 1d758f74748..9373aae8f42 100644 --- a/test/run-drun/AST-64.mo +++ b/test/run-drun/AST-64.mo @@ -13,5 +13,5 @@ let _ = (actor { public func x() { x() } }) : Any; let _ = (object this { public func x() { this.x() } }) : Any; let _ = (object { public func x() { x() } }) : Any; -// certainly won’t work on drun //SKIP comp +//SKIP comp-stub diff --git a/test/run-drun/ok/AST-64.ic-stub-run.ok b/test/run-drun/ok/AST-64.ic-stub-run.ok deleted file mode 100644 index c2b23162b29..00000000000 --- a/test/run-drun/ok/AST-64.ic-stub-run.ok +++ /dev/null @@ -1,4 +0,0 @@ -→ create -← completed: canister-id = 0x2a01 -→ install -← completed diff --git a/test/run-drun/ok/pass-references.comp-stub.ok b/test/run-drun/ok/pass-references.comp-stub.ok new file mode 100644 index 00000000000..46f914d3ac0 --- /dev/null +++ b/test/run-drun/ok/pass-references.comp-stub.ok @@ -0,0 +1,2 @@ +pass-references.mo:14.5-16.6: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program + (This is a limitation of the current version and flag -stub-system-api.) diff --git a/test/run-drun/ok/pass-references.comp-stub.ret.ok b/test/run-drun/ok/pass-references.comp-stub.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/pass-references.comp-stub.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-drun/ok/pass-references.ic-stub-run.ok b/test/run-drun/ok/pass-references.ic-stub-run.ok deleted file mode 100644 index c9d7da8abcb..00000000000 --- a/test/run-drun/ok/pass-references.ic-stub-run.ok +++ /dev/null @@ -1,10 +0,0 @@ -→ create -← completed: canister-id = 0x2a01 -→ install -← completed -→ update go(0x4449444c0000) -debug.print: a -debug.print: b -debug.print: a -debug.print: b -← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/self-shadow.comp-stub.ok b/test/run-drun/ok/self-shadow.comp-stub.ok new file mode 100644 index 00000000000..b608bf88ec7 --- /dev/null +++ b/test/run-drun/ok/self-shadow.comp-stub.ok @@ -0,0 +1,2 @@ +self-shadow.mo:5.15-5.51: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program + (This is a limitation of the current version and flag -stub-system-api.) diff --git a/test/run-drun/ok/self-shadow.comp-stub.ret.ok b/test/run-drun/ok/self-shadow.comp-stub.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/run-drun/ok/self-shadow.comp-stub.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/run-drun/ok/self-shadow.ic-stub-run.ok b/test/run-drun/ok/self-shadow.ic-stub-run.ok deleted file mode 100644 index c2b23162b29..00000000000 --- a/test/run-drun/ok/self-shadow.ic-stub-run.ok +++ /dev/null @@ -1,4 +0,0 @@ -→ create -← completed: canister-id = 0x2a01 -→ install -← completed diff --git a/test/run-drun/ok/unsupported.comp-stub.ok b/test/run-drun/ok/unsupported.comp-stub.ok index 9b69d1cae08..b1d376a35ac 100644 --- a/test/run-drun/ok/unsupported.comp-stub.ok +++ b/test/run-drun/ok/unsupported.comp-stub.ok @@ -2,7 +2,13 @@ unsupported.mo:4.5-4.41: type error, a shared function cannot be private (This is a limitation of the current version and flag -stub-system-api.) unsupported.mo:38.26-38.29: type error, a shared function is only allowed as a public field of an actor (This is a limitation of the current version and flag -stub-system-api.) -unsupported.mo:66.3-66.42: type error, actor classes with parameters are not supported; use an actor declaration instead +unsupported.mo:62.3-62.35: type error, actor classes are not supported; use an actor declaration instead + (This is a limitation of the current version and flag -stub-system-api.) +unsupported.mo:66.3-66.42: type error, actor classes are not supported; use an actor declaration instead + (This is a limitation of the current version and flag -stub-system-api.) +unsupported.mo:70.45-70.53: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program + (This is a limitation of the current version and flag -stub-system-api.) +unsupported.mo:74.37-74.45: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program (This is a limitation of the current version and flag -stub-system-api.) unsupported.mo:84.34-84.37: type error, a shared function is only allowed as a public field of an actor (This is a limitation of the current version and flag -stub-system-api.) From 9fbcc97b5497f8fcd2543cd3302fa82c7fe1540b Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Thu, 23 Jan 2020 00:28:26 +0100 Subject: [PATCH 0995/1176] QC: make sure we have 2 OS threads (#1153) * make sure we have 2 OS threads * restrain tasty to be single-threaded --- test/random/Main.hs | 3 ++- test/random/qc-motoko.cabal | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/test/random/Main.hs b/test/random/Main.hs index eeb4a5a6953..fb9a6020877 100644 --- a/test/random/Main.hs +++ b/test/random/Main.hs @@ -12,6 +12,7 @@ import Test.QuickCheck.Monadic import Test.Tasty import Test.Tasty.QuickCheck as QC hiding ((.&.)) import Test.QuickCheck.Unicode +import System.Environment import qualified Data.Text (null, unpack) import Data.Maybe import Data.Bool (bool) @@ -28,7 +29,7 @@ import Embedder -- import Debug.Trace (traceShowId, traceShow) -main = defaultMain tests +main = setEnv "TASTY_NUM_THREADS" "1" >> defaultMain tests where tests :: TestTree tests = testGroup "Motoko tests" [arithProps, conversionProps, utf8Props, matchingProps] diff --git a/test/random/qc-motoko.cabal b/test/random/qc-motoko.cabal index dcf78743651..f7e1a750dc8 100644 --- a/test/random/qc-motoko.cabal +++ b/test/random/qc-motoko.cabal @@ -14,6 +14,7 @@ executable qc-motoko main-is: Main.hs other-modules: Embedder, Turtle.Pipe other-extensions: ConstraintKinds, StandaloneDeriving, DataKinds, KindSignatures, GADTs, MultiParamTypeClasses + ghc-options: -O -threaded -with-rtsopts=-N2 build-depends: base ^>=4.12.0.0 , text ^>=1.2.3.1 , process From b7def7e6e17505969070ab139f4ba9213ceb2502 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Thu, 23 Jan 2020 10:31:07 +0100 Subject: [PATCH 0996/1176] bump dfinity using `niv update dfinity` primarily to obtain #2312 also getting the intervening commits $ git log --oneline --first-parent 8224bf469c80ade492083461e7ee3c2cfdf3ec02..0b3071a3f7d489d560a16417d07930687a6709d4 0b3071a3 (HEAD -> master, origin/master, origin/HEAD) Merge 'master' to 'roman/user-id-blob' (#2312) 3f530ee2 Merge pull request #2244 from dfinity-lab/ingress_fix e33fca0f Merge pull request #2334 from dfinity-lab/poolMetrics 9b601077 Merge pull request #2322 from dfinity-lab/paulliu/change-action-full-message fa87555b Merge pull request #2350 from dfinity-lab/rsub/prs-1 2228ab04 Merge pull request #2355 from dfinity-lab/dimitris/refactor-drun-message 7165f912 Merge pull request #2343 from dfinity-lab/wasm-cargo-integration 42925368 DFN-746 Error handling in ic-registry (#2346) 0795087c Merge pull request #2347 from dfinity-lab/DFN-1266/refactoring 5ae07555 Merge pull request #2353 from dfinity-lab/update-link-in-github-comment 2ecb78fd Merge pull request #2340 from dfinity-lab/dimitris/message-id-blob 970021b8 Introduce DkgSummary (#2332) db7dd8b2 Simplify metrics definition (#2342) cfda5fcd Message Routing Spec: Fix in Mapping Between Queues and Streams (#2315) 33a67fe3 Merge pull request #2345 from dfinity-lab/hassen/p2p-133 188bf4d8 DFN-1270: Add wrapper for seedable PRNG that is cryptographically secure (#2233) d8fa887f Merge pull request #2333 from dfinity-lab/dimitris/fix-string-bytes-serde add18092 Remove star imports (#2210) 4a990173 Merge pull request #2268 from dfinity-lab/DFN-1254/async 339a76a2 Restructure crypto DKG spec (#2310) 7c60c0ef Merge pull request #2316 from dfinity-lab/paulliu/artifact-id 06126ec8 Merge pull request #2344 from dfinity-lab/nm-fix-dtest --- nix/sources.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/sources.json b/nix/sources.json index 6353e9a435a..86b9847ff33 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -8,7 +8,7 @@ "dfinity": { "ref": "master", "repo": "ssh://git@github.com/dfinity-lab/dfinity", - "rev": "8224bf469c80ade492083461e7ee3c2cfdf3ec02", + "rev": "0b3071a3f7d489d560a16417d07930687a6709d4", "type": "git" }, "esm": { From bc0146ec804a1ba20fd981ec0cc594f8332f076e Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Thu, 23 Jan 2020 11:00:58 +0100 Subject: [PATCH 0997/1176] accept tests --- test/perf/ok/reversi.drun-run.ok | 18 +++++++++--------- test/run-drun/ok/GIT-843.drun-run.ok | 4 ++-- test/run-drun/ok/actor-import.drun-run.ok | 8 ++++---- .../ok/actor-reference-return.drun-run.ok | 2 +- test/run-drun/ok/actor-reference.drun-run.ok | 2 +- .../ok/array-out-of-bounds.drun-run.ok | 6 +++--- test/run-drun/ok/async-calls1.drun-run.ok | 4 ++-- test/run-drun/ok/async-calls2.drun-run.ok | 4 ++-- test/run-drun/ok/async-calls3.drun-run.ok | 4 ++-- test/run-drun/ok/call-async-method.drun-run.ok | 4 ++-- test/run-drun/ok/caller.drun-run.ok | 16 ++++++++-------- test/run-drun/ok/closure-params.drun-run.ok | 4 ++-- test/run-drun/ok/counter.drun-run.ok | 12 ++++++------ test/run-drun/ok/counter2.drun-run.ok | 4 ++-- test/run-drun/ok/data-params.drun-run.ok | 4 ++-- test/run-drun/ok/divide-by-zero.drun-run.ok | 2 +- test/run-drun/ok/empty-actor.drun-run.ok | 2 +- test/run-drun/ok/empty-call.drun-run.ok | 4 ++-- .../run-drun/ok/flatten-awaitables.drun-run.ok | 4 ++-- test/run-drun/ok/free-callbacks.drun-run.ok | 4 ++-- test/run-drun/ok/generic-tail-rec.drun-run.ok | 2 +- test/run-drun/ok/hello-world-async.drun-run.ok | 4 ++-- test/run-drun/ok/hello-world-await.drun-run.ok | 4 ++-- .../ok/hello-world-message.drun-run.ok | 2 +- .../run-drun/ok/hello-world-return.drun-run.ok | 2 +- test/run-drun/ok/hello-world.drun-run.ok | 2 +- test/run-drun/ok/ic-calls.drun-run.ok | 4 ++-- test/run-drun/ok/idl-any.drun-run.ok | 2 +- test/run-drun/ok/idl-bad.drun-run.ok | 2 +- test/run-drun/ok/idl-buf-size-bug.drun-run.ok | 4 ++-- test/run-drun/ok/idl-field-escape.drun-run.ok | 2 +- test/run-drun/ok/idl-func.drun-run.ok | 2 +- test/run-drun/ok/idl-nary.drun-run.ok | 2 +- test/run-drun/ok/idl-nat-int.drun-run.ok | 2 +- test/run-drun/ok/idl-option.drun-run.ok | 2 +- test/run-drun/ok/idl-pair.drun-run.ok | 2 +- test/run-drun/ok/idl-record.drun-run.ok | 2 +- test/run-drun/ok/idl-shorthand.drun-run.ok | 2 +- test/run-drun/ok/idl-tuple.drun-run.ok | 2 +- test/run-drun/ok/idl-unit.drun-run.ok | 2 +- test/run-drun/ok/idl-variant.drun-run.ok | 2 +- test/run-drun/ok/idl-vector.drun-run.ok | 2 +- test/run-drun/ok/large-array.drun-run.ok | 2 +- test/run-drun/ok/local-throw.drun-run.ok | 4 ++-- test/run-drun/ok/log-slow.drun-run.ok | 2 +- test/run-drun/ok/mod-rebind.drun-run.ok | 2 +- test/run-drun/ok/oneway-throw.drun-run.ok | 4 ++-- test/run-drun/ok/oneway.drun-run.ok | 4 ++-- test/run-drun/ok/oom.drun-run.ok | 6 +++--- test/run-drun/ok/print-from-init.drun-run.ok | 2 +- test/run-drun/ok/query.drun-run.ok | 16 ++++++++-------- test/run-drun/ok/query2.drun-run.ok | 4 ++-- test/run-drun/ok/reject.drun-run.ok | 8 ++++---- test/run-drun/ok/rts-stats.drun-run.ok | 2 +- test/run-drun/ok/selftail.drun-run.ok | 2 +- test/run-drun/ok/shared-object.drun-run.ok | 4 ++-- test/run-drun/ok/sharingbug.drun-run.ok | 2 +- test/run-drun/ok/show.drun-run.ok | 2 +- test/run-drun/ok/tailpositions.drun-run.ok | 2 +- test/run-drun/ok/text-iter.drun-run.ok | 2 +- test/run-drun/ok/transpose.drun-run.ok | 4 ++-- test/run-drun/ok/unsupported.comp-stub.ok | 16 ---------------- 62 files changed, 119 insertions(+), 135 deletions(-) delete mode 100644 test/run-drun/ok/unsupported.comp-stub.ok diff --git a/test/perf/ok/reversi.drun-run.ok b/test/perf/ok/reversi.drun-run.ok index fa534586835..7afeb992747 100644 --- a/test/perf/ok/reversi.drun-run.ok +++ b/test/perf/ok/reversi.drun-run.ok @@ -1,9 +1,9 @@ -ingress(0) System -ingress(1) Completed: Canister: Payload: 0x4449444c0000 -ingress(2) Completed: Canister: Payload: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e4f2a2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a -ingress(3) Completed: Canister: Payload: 0x4449444c000171024f4b -ingress(4) Completed: Canister: Payload: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e4f2e2e2e0a2e2e2e4f4f2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a -ingress(5) Completed: Canister: Payload: 0x4449444c000171024f4b -ingress(6) Completed: Canister: Payload: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a -ingress(7) Completed: Canister: Payload: 0x4449444c000171024f4b -ingress(8) Completed: Canister: Payload: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e4f4f2e2e2e0a2e2e4f4f4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 +ingress(0x0200000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e4f2a2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a +ingress(0x0300000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c000171024f4b +ingress(0x0400000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e4f2e2e2e0a2e2e2e4f4f2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a +ingress(0x0500000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c000171024f4b +ingress(0x0600000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a +ingress(0x0700000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c000171024f4b +ingress(0x0800000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e4f4f2e2e2e0a2e2e4f4f4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a diff --git a/test/run-drun/ok/GIT-843.drun-run.ok b/test/run-drun/ok/GIT-843.drun-run.ok index e51631cf793..ac0854c8f7e 100644 --- a/test/run-drun/ok/GIT-843.drun-run.ok +++ b/test/run-drun/ok/GIT-843.drun-run.ok @@ -1,3 +1,3 @@ -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System debug.print: ok -ingress(1) Completed: Canister: Payload: 0x4449444c0000 +ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/actor-import.drun-run.ok b/test/run-drun/ok/actor-import.drun-run.ok index f16e5e20feb..7ffff66814d 100644 --- a/test/run-drun/ok/actor-import.drun-run.ok +++ b/test/run-drun/ok/actor-import.drun-run.ok @@ -1,4 +1,4 @@ -ingress(0) System -ingress(1) Completed: Canister: Payload: 0x4449444c016900010001022a01 -ingress(2) Completed: Canister: Payload: 0x4449444c016900010001022a01 -ingress(3) Completed: Canister: Payload: 0x4449444c016900010001022a01 +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c016900010001022a01 +ingress(0x0200000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c016900010001022a01 +ingress(0x0300000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c016900010001022a01 diff --git a/test/run-drun/ok/actor-reference-return.drun-run.ok b/test/run-drun/ok/actor-reference-return.drun-run.ok index c18e4d259db..3cea69d6b5b 100644 --- a/test/run-drun/ok/actor-reference-return.drun-run.ok +++ b/test/run-drun/ok/actor-reference-return.drun-run.ok @@ -1,3 +1,3 @@ -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System Ok: Payload: 0x4449444c01690001000105c0fefed00d Ok: Payload: 0x4449444c0169000100010dc0fefed00dcafebabedeadbeef diff --git a/test/run-drun/ok/actor-reference.drun-run.ok b/test/run-drun/ok/actor-reference.drun-run.ok index 43d7af40394..28f361d9907 100644 --- a/test/run-drun/ok/actor-reference.drun-run.ok +++ b/test/run-drun/ok/actor-reference.drun-run.ok @@ -1 +1 @@ -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System diff --git a/test/run-drun/ok/array-out-of-bounds.drun-run.ok b/test/run-drun/ok/array-out-of-bounds.drun-run.ok index d907c8e8165..c7b5985b2d0 100644 --- a/test/run-drun/ok/array-out-of-bounds.drun-run.ok +++ b/test/run-drun/ok/array-out-of-bounds.drun-run.ok @@ -1,3 +1,3 @@ -ingress(0) System -ingress(1) Err: IC0503: Canister ic:2A012B trapped explicitly: Array index out of bounds -ingress(2) Err: IC0503: Canister ic:2A012B trapped explicitly: Array index out of bounds +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Err: IC0503: Canister ic:2A012B trapped explicitly: Array index out of bounds +ingress(0x0200000000000000000000000000000000000000000000000000000000000000) Err: IC0503: Canister ic:2A012B trapped explicitly: Array index out of bounds diff --git a/test/run-drun/ok/async-calls1.drun-run.ok b/test/run-drun/ok/async-calls1.drun-run.ok index 91c74b55809..c30c2566df1 100644 --- a/test/run-drun/ok/async-calls1.drun-run.ok +++ b/test/run-drun/ok/async-calls1.drun-run.ok @@ -1,2 +1,2 @@ -ingress(0) System -ingress(1) Completed: Canister: Payload: 0x4449444c0000 +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/async-calls2.drun-run.ok b/test/run-drun/ok/async-calls2.drun-run.ok index 91c74b55809..c30c2566df1 100644 --- a/test/run-drun/ok/async-calls2.drun-run.ok +++ b/test/run-drun/ok/async-calls2.drun-run.ok @@ -1,2 +1,2 @@ -ingress(0) System -ingress(1) Completed: Canister: Payload: 0x4449444c0000 +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/async-calls3.drun-run.ok b/test/run-drun/ok/async-calls3.drun-run.ok index 91c74b55809..c30c2566df1 100644 --- a/test/run-drun/ok/async-calls3.drun-run.ok +++ b/test/run-drun/ok/async-calls3.drun-run.ok @@ -1,2 +1,2 @@ -ingress(0) System -ingress(1) Completed: Canister: Payload: 0x4449444c0000 +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/call-async-method.drun-run.ok b/test/run-drun/ok/call-async-method.drun-run.ok index 68097b140dd..c244fbb189a 100644 --- a/test/run-drun/ok/call-async-method.drun-run.ok +++ b/test/run-drun/ok/call-async-method.drun-run.ok @@ -1,2 +1,2 @@ -ingress(0) System -ingress(1) Err: IC0503: Canister ic:2A012B trapped explicitly: not a self-call +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Err: IC0503: Canister ic:2A012B trapped explicitly: not a self-call diff --git a/test/run-drun/ok/caller.drun-run.ok b/test/run-drun/ok/caller.drun-run.ok index a74b246d435..2d8c9b2e202 100644 --- a/test/run-drun/ok/caller.drun-run.ok +++ b/test/run-drun/ok/caller.drun-run.ok @@ -1,10 +1,10 @@ -ingress(0) System -ingress(1) Completed: Canister: Payload: 0x4449444c0000 -ingress(2) Completed: Canister: Payload: 0x4449444c0000 -ingress(3) Completed: Canister: Payload: 0x4449444c0000 -ingress(4) Completed: Canister: Payload: 0x4449444c0000 +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 +ingress(0x0200000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 +ingress(0x0300000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 +ingress(0x0400000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 Ok: Payload: 0x4449444c0000 -ingress(6) Completed: Canister: Payload: 0x4449444c016d7b0100080000000000000000 -Ok: Payload: 0x4449444c00017969df2265 -Ok: Payload: 0x4449444c00017d08 +ingress(0x0600000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c016d7b010021000000000000000000000000000000000000000000000000000000000000000000 +Ok: Payload: 0x4449444c0001798d3a7c7a +Ok: Payload: 0x4449444c00017d21 Ok: Payload: 0x4449444c016e7b01000100 diff --git a/test/run-drun/ok/closure-params.drun-run.ok b/test/run-drun/ok/closure-params.drun-run.ok index aaf93d82b59..3d7c539c0f0 100644 --- a/test/run-drun/ok/closure-params.drun-run.ok +++ b/test/run-drun/ok/closure-params.drun-run.ok @@ -1,4 +1,4 @@ -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System debug.print: 1 debug.print: 3 debug.print: 6 @@ -9,4 +9,4 @@ debug.print: 3 debug.print: 6 debug.print: 10 debug.print: 15 -ingress(1) Completed: Canister: Payload: 0x4449444c0000 +ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/counter.drun-run.ok b/test/run-drun/ok/counter.drun-run.ok index 52942b3d790..c72b2fbb3b6 100644 --- a/test/run-drun/ok/counter.drun-run.ok +++ b/test/run-drun/ok/counter.drun-run.ok @@ -1,10 +1,10 @@ -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System debug.print: 2 -ingress(1) Completed: Canister: Payload: 0x4449444c0000 +ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 debug.print: 3 -ingress(2) Completed: Canister: Payload: 0x4449444c0000 +ingress(0x0200000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 debug.print: 4 -ingress(3) Completed: Canister: Payload: 0x4449444c0000 +ingress(0x0300000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 debug.print: 4 -ingress(4) Completed: Canister: Payload: 0x4449444c0000 -ingress(5) Completed: Canister: Payload: 0x4449444c00017d04 +ingress(0x0400000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 +ingress(0x0500000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c00017d04 diff --git a/test/run-drun/ok/counter2.drun-run.ok b/test/run-drun/ok/counter2.drun-run.ok index 03da5a03e23..2bb6d827c1d 100644 --- a/test/run-drun/ok/counter2.drun-run.ok +++ b/test/run-drun/ok/counter2.drun-run.ok @@ -1,4 +1,4 @@ -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System debug.print: 2 debug.print: 3 debug.print: 4 @@ -13,4 +13,4 @@ debug.print: 11 debug.print: 12 debug.print: 13 debug.print: 14 -ingress(1) Completed: Canister: Payload: 0x4449444c0000 +ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/data-params.drun-run.ok b/test/run-drun/ok/data-params.drun-run.ok index bd36923f3b9..47a14e2fcc4 100644 --- a/test/run-drun/ok/data-params.drun-run.ok +++ b/test/run-drun/ok/data-params.drun-run.ok @@ -1,4 +1,4 @@ -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System debug.print: 0 debug.print: +1 debug.print: +3 @@ -40,4 +40,4 @@ debug.print: +2_148_489_869 debug.print: +2_148_489_911 debug.print: +2_148_489_869 debug.print: +4_295_973_516 -ingress(1) Completed: Canister: Payload: 0x4449444c0000 +ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/divide-by-zero.drun-run.ok b/test/run-drun/ok/divide-by-zero.drun-run.ok index be93f590046..92786aae5bb 100644 --- a/test/run-drun/ok/divide-by-zero.drun-run.ok +++ b/test/run-drun/ok/divide-by-zero.drun-run.ok @@ -1 +1 @@ -ingress(0) Err: IC0502: Canister ic:2A012B trapped: integer division by 0 +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) Err: IC0502: Canister ic:2A012B trapped: integer division by 0 diff --git a/test/run-drun/ok/empty-actor.drun-run.ok b/test/run-drun/ok/empty-actor.drun-run.ok index 43d7af40394..28f361d9907 100644 --- a/test/run-drun/ok/empty-actor.drun-run.ok +++ b/test/run-drun/ok/empty-actor.drun-run.ok @@ -1 +1 @@ -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System diff --git a/test/run-drun/ok/empty-call.drun-run.ok b/test/run-drun/ok/empty-call.drun-run.ok index 91c74b55809..c30c2566df1 100644 --- a/test/run-drun/ok/empty-call.drun-run.ok +++ b/test/run-drun/ok/empty-call.drun-run.ok @@ -1,2 +1,2 @@ -ingress(0) System -ingress(1) Completed: Canister: Payload: 0x4449444c0000 +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/flatten-awaitables.drun-run.ok b/test/run-drun/ok/flatten-awaitables.drun-run.ok index a5dc4ab027c..bc4bd137795 100644 --- a/test/run-drun/ok/flatten-awaitables.drun-run.ok +++ b/test/run-drun/ok/flatten-awaitables.drun-run.ok @@ -1,4 +1,4 @@ -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System debug.print: first-order debug.print: 0 debug.print: 1 @@ -33,4 +33,4 @@ debug.print: 12 debug.print: 13 debug.print: 14 debug.print: 15 -ingress(1) Completed: Canister: Payload: 0x4449444c0000 +ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/free-callbacks.drun-run.ok b/test/run-drun/ok/free-callbacks.drun-run.ok index 51a7daa2389..d1fc8e14e09 100644 --- a/test/run-drun/ok/free-callbacks.drun-run.ok +++ b/test/run-drun/ok/free-callbacks.drun-run.ok @@ -1,3 +1,3 @@ -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System debug.print: Ignore Diff: (ignored) -ingress(1) Completed: Canister: Payload: 0x4449444c0000 +ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/generic-tail-rec.drun-run.ok b/test/run-drun/ok/generic-tail-rec.drun-run.ok index 86dfd61b593..fd26a31a9da 100644 --- a/test/run-drun/ok/generic-tail-rec.drun-run.ok +++ b/test/run-drun/ok/generic-tail-rec.drun-run.ok @@ -2,4 +2,4 @@ debug.print: done 1 debug.print: done 2 debug.print: done 3 debug.print: done 4 -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System diff --git a/test/run-drun/ok/hello-world-async.drun-run.ok b/test/run-drun/ok/hello-world-async.drun-run.ok index b41f48223f2..f995f560844 100644 --- a/test/run-drun/ok/hello-world-async.drun-run.ok +++ b/test/run-drun/ok/hello-world-async.drun-run.ok @@ -1,4 +1,4 @@ -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System debug.print: Hello debug.print: World! -ingress(1) Completed: Canister: Payload: 0x4449444c0000 +ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/hello-world-await.drun-run.ok b/test/run-drun/ok/hello-world-await.drun-run.ok index d124edaa379..0a99d430ad2 100644 --- a/test/run-drun/ok/hello-world-await.drun-run.ok +++ b/test/run-drun/ok/hello-world-await.drun-run.ok @@ -1,3 +1,3 @@ -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System debug.print: Hello World! -ingress(1) Completed: Canister: Payload: 0x4449444c0000 +ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/hello-world-message.drun-run.ok b/test/run-drun/ok/hello-world-message.drun-run.ok index 43d7af40394..28f361d9907 100644 --- a/test/run-drun/ok/hello-world-message.drun-run.ok +++ b/test/run-drun/ok/hello-world-message.drun-run.ok @@ -1 +1 @@ -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System diff --git a/test/run-drun/ok/hello-world-return.drun-run.ok b/test/run-drun/ok/hello-world-return.drun-run.ok index c1f0a27528b..786a08e7160 100644 --- a/test/run-drun/ok/hello-world-return.drun-run.ok +++ b/test/run-drun/ok/hello-world-return.drun-run.ok @@ -1,3 +1,3 @@ -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System Ok: Payload: 0x4449444c0001710c48656c6c6f20576f726c6421 Ok: Payload: 0x4449444c0001710c48656c6c6f20576f726c6421 diff --git a/test/run-drun/ok/hello-world.drun-run.ok b/test/run-drun/ok/hello-world.drun-run.ok index e019e1158f8..6c3938085f2 100644 --- a/test/run-drun/ok/hello-world.drun-run.ok +++ b/test/run-drun/ok/hello-world.drun-run.ok @@ -1,2 +1,2 @@ debug.print: Hello World! -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System diff --git a/test/run-drun/ok/ic-calls.drun-run.ok b/test/run-drun/ok/ic-calls.drun-run.ok index 91c74b55809..c30c2566df1 100644 --- a/test/run-drun/ok/ic-calls.drun-run.ok +++ b/test/run-drun/ok/ic-calls.drun-run.ok @@ -1,2 +1,2 @@ -ingress(0) System -ingress(1) Completed: Canister: Payload: 0x4449444c0000 +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-any.drun-run.ok b/test/run-drun/ok/idl-any.drun-run.ok index c4d42e52ed1..bc46256e3f6 100644 --- a/test/run-drun/ok/idl-any.drun-run.ok +++ b/test/run-drun/ok/idl-any.drun-run.ok @@ -1,4 +1,4 @@ -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System debug.print: ok: Foo Ok: Payload: 0x4449444c0000 debug.print: ok: Foo diff --git a/test/run-drun/ok/idl-bad.drun-run.ok b/test/run-drun/ok/idl-bad.drun-run.ok index 9a09fe7fddb..544da366c61 100644 --- a/test/run-drun/ok/idl-bad.drun-run.ok +++ b/test/run-drun/ok/idl-bad.drun-run.ok @@ -1,3 +1,3 @@ -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System debug.print: IDL error: missing magic bytes Err: IC0502: Canister ic:2A012B trapped: unreachable diff --git a/test/run-drun/ok/idl-buf-size-bug.drun-run.ok b/test/run-drun/ok/idl-buf-size-bug.drun-run.ok index 91c74b55809..c30c2566df1 100644 --- a/test/run-drun/ok/idl-buf-size-bug.drun-run.ok +++ b/test/run-drun/ok/idl-buf-size-bug.drun-run.ok @@ -1,2 +1,2 @@ -ingress(0) System -ingress(1) Completed: Canister: Payload: 0x4449444c0000 +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-field-escape.drun-run.ok b/test/run-drun/ok/idl-field-escape.drun-run.ok index 3ac0b008387..5a2c456067b 100644 --- a/test/run-drun/ok/idl-field-escape.drun-run.ok +++ b/test/run-drun/ok/idl-field-escape.drun-run.ok @@ -1,4 +1,4 @@ -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System Ok: Payload: 0x4449444c016c01868eb7027f0100 Ok: Payload: 0x4449444c016c01868eb7027f0100 Ok: Payload: 0x4449444c016c03007c017dbcfef7b102710100ffff03802003585858 diff --git a/test/run-drun/ok/idl-func.drun-run.ok b/test/run-drun/ok/idl-func.drun-run.ok index bfcc18007e7..a28d738f46e 100644 --- a/test/run-drun/ok/idl-func.drun-run.ok +++ b/test/run-drun/ok/idl-func.drun-run.ok @@ -1,4 +1,4 @@ -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System Ok: Payload: 0x4449444c026e016a017c010100010000 Ok: Payload: 0x4449444c0000 Ok: Payload: 0x4449444c036a00010101016e026a017c01020001000101022a010366756e diff --git a/test/run-drun/ok/idl-nary.drun-run.ok b/test/run-drun/ok/idl-nary.drun-run.ok index 5748bc6bff7..cb895549b50 100644 --- a/test/run-drun/ok/idl-nary.drun-run.ok +++ b/test/run-drun/ok/idl-nary.drun-run.ok @@ -1,4 +1,4 @@ -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System Ok: Payload: 0x4449444c00027171034f6e650354776f Ok: Payload: 0x4449444c0003717171034f6e650354776f055468726565 Ok: Payload: 0x4449444c000471717171034f6e650354776f05546872656504466f7572 diff --git a/test/run-drun/ok/idl-nat-int.drun-run.ok b/test/run-drun/ok/idl-nat-int.drun-run.ok index f450261cb17..a60e7eb074e 100644 --- a/test/run-drun/ok/idl-nat-int.drun-run.ok +++ b/test/run-drun/ok/idl-nat-int.drun-run.ok @@ -1,4 +1,4 @@ -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System Ok: Payload: 0x4449444c00017d2a Ok: Payload: 0x4449444c00017d2a Ok: Payload: 0x4449444c016d7d0100022a19 diff --git a/test/run-drun/ok/idl-option.drun-run.ok b/test/run-drun/ok/idl-option.drun-run.ok index 6e6ad23462f..a2f7e845525 100644 --- a/test/run-drun/ok/idl-option.drun-run.ok +++ b/test/run-drun/ok/idl-option.drun-run.ok @@ -1,4 +1,4 @@ -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System debug.print: ok: null Ok: Payload: 0x4449444c0000 debug.print: ok: null diff --git a/test/run-drun/ok/idl-pair.drun-run.ok b/test/run-drun/ok/idl-pair.drun-run.ok index 428fcb5b372..45b1fbf60f1 100644 --- a/test/run-drun/ok/idl-pair.drun-run.ok +++ b/test/run-drun/ok/idl-pair.drun-run.ok @@ -1,2 +1,2 @@ -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System Ok: Payload: 0x4449444c016c02007c017c01000205 diff --git a/test/run-drun/ok/idl-record.drun-run.ok b/test/run-drun/ok/idl-record.drun-run.ok index ca2c69d0c27..9f739e13fd6 100644 --- a/test/run-drun/ok/idl-record.drun-run.ok +++ b/test/run-drun/ok/idl-record.drun-run.ok @@ -1,4 +1,4 @@ -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System debug.print: ok: +42 Ok: Payload: 0x4449444c0000 debug.print: ok: Hey! diff --git a/test/run-drun/ok/idl-shorthand.drun-run.ok b/test/run-drun/ok/idl-shorthand.drun-run.ok index 42c68e92e5e..1d9bff524d5 100644 --- a/test/run-drun/ok/idl-shorthand.drun-run.ok +++ b/test/run-drun/ok/idl-shorthand.drun-run.ok @@ -1,2 +1,2 @@ -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System Ok: Payload: 0x4449444c016b01d1a7cf027f010000 diff --git a/test/run-drun/ok/idl-tuple.drun-run.ok b/test/run-drun/ok/idl-tuple.drun-run.ok index cf3e86f68cf..92c7ad8dd6d 100644 --- a/test/run-drun/ok/idl-tuple.drun-run.ok +++ b/test/run-drun/ok/idl-tuple.drun-run.ok @@ -1,4 +1,4 @@ -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System Ok: Payload: 0x4449444c00027c7c0205 Ok: Payload: 0x4449444c00037c7c7c050581848c20 Ok: Payload: 0x4449444c00037c7c7c050581848c20 diff --git a/test/run-drun/ok/idl-unit.drun-run.ok b/test/run-drun/ok/idl-unit.drun-run.ok index 139fbf3fc92..40815a20950 100644 --- a/test/run-drun/ok/idl-unit.drun-run.ok +++ b/test/run-drun/ok/idl-unit.drun-run.ok @@ -1,2 +1,2 @@ -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System Ok: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-variant.drun-run.ok b/test/run-drun/ok/idl-variant.drun-run.ok index 2e39e7bfc87..0f64928bc47 100644 --- a/test/run-drun/ok/idl-variant.drun-run.ok +++ b/test/run-drun/ok/idl-variant.drun-run.ok @@ -1,2 +1,2 @@ -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System Ok: Payload: 0x4449444c016b03d583b702008790c0bd0479dc9790cb0e790100000120000000 diff --git a/test/run-drun/ok/idl-vector.drun-run.ok b/test/run-drun/ok/idl-vector.drun-run.ok index a8c227d6d03..e663c8d4392 100644 --- a/test/run-drun/ok/idl-vector.drun-run.ok +++ b/test/run-drun/ok/idl-vector.drun-run.ok @@ -1,2 +1,2 @@ -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System Ok: Payload: 0x4449444c026e016d0001000103010001040100010201000100010001000100 diff --git a/test/run-drun/ok/large-array.drun-run.ok b/test/run-drun/ok/large-array.drun-run.ok index b95c84fe751..170cfc47522 100644 --- a/test/run-drun/ok/large-array.drun-run.ok +++ b/test/run-drun/ok/large-array.drun-run.ok @@ -1,2 +1,2 @@ debug.print: done -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System diff --git a/test/run-drun/ok/local-throw.drun-run.ok b/test/run-drun/ok/local-throw.drun-run.ok index 26a900a3a48..3b9d76c320a 100644 --- a/test/run-drun/ok/local-throw.drun-run.ok +++ b/test/run-drun/ok/local-throw.drun-run.ok @@ -1,4 +1,4 @@ -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System debug.print: t2 ok debug.print: t3 ok -ingress(1) Completed: Canister: Payload: 0x4449444c0000 +ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/log-slow.drun-run.ok b/test/run-drun/ok/log-slow.drun-run.ok index 43d7af40394..28f361d9907 100644 --- a/test/run-drun/ok/log-slow.drun-run.ok +++ b/test/run-drun/ok/log-slow.drun-run.ok @@ -1 +1 @@ -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System diff --git a/test/run-drun/ok/mod-rebind.drun-run.ok b/test/run-drun/ok/mod-rebind.drun-run.ok index 43d7af40394..28f361d9907 100644 --- a/test/run-drun/ok/mod-rebind.drun-run.ok +++ b/test/run-drun/ok/mod-rebind.drun-run.ok @@ -1 +1 @@ -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System diff --git a/test/run-drun/ok/oneway-throw.drun-run.ok b/test/run-drun/ok/oneway-throw.drun-run.ok index ed40bddbf25..c4fb20b0e26 100644 --- a/test/run-drun/ok/oneway-throw.drun-run.ok +++ b/test/run-drun/ok/oneway-throw.drun-run.ok @@ -1,6 +1,6 @@ -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System debug.print: go1 debug.print: throws() debug.print: ping() debug.print: go2 -ingress(1) Completed: Canister: Payload: 0x4449444c0000 +ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/oneway.drun-run.ok b/test/run-drun/ok/oneway.drun-run.ok index 8331dc9ecc9..408cea050e3 100644 --- a/test/run-drun/ok/oneway.drun-run.ok +++ b/test/run-drun/ok/oneway.drun-run.ok @@ -1,4 +1,4 @@ -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System debug.print: A debug.print: B debug.print: C @@ -10,4 +10,4 @@ debug.print: 3 debug.print: 4 debug.print: 5 debug.print: 6 -ingress(1) Completed: Canister: Payload: 0x4449444c0000 +ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/oom.drun-run.ok b/test/run-drun/ok/oom.drun-run.ok index 57687c597aa..c4dfadc376a 100644 --- a/test/run-drun/ok/oom.drun-run.ok +++ b/test/run-drun/ok/oom.drun-run.ok @@ -1,3 +1,3 @@ -ingress(0) System -ingress(1) Completed: Canister: Payload: 0x4449444c0000 -ingress(2) Completed: Canister: Payload: 0x4449444c0000 +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 +ingress(0x0200000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/print-from-init.drun-run.ok b/test/run-drun/ok/print-from-init.drun-run.ok index 4d57fad6ec2..f44c94649cc 100644 --- a/test/run-drun/ok/print-from-init.drun-run.ok +++ b/test/run-drun/ok/print-from-init.drun-run.ok @@ -1,2 +1,2 @@ debug.print: Debug out -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System diff --git a/test/run-drun/ok/query.drun-run.ok b/test/run-drun/ok/query.drun-run.ok index e8c656b0d07..488ed07d831 100644 --- a/test/run-drun/ok/query.drun-run.ok +++ b/test/run-drun/ok/query.drun-run.ok @@ -1,18 +1,18 @@ -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System debug.print: 2 -ingress(1) Completed: Canister: Payload: 0x4449444c0000 +ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 debug.print: 3 -ingress(2) Completed: Canister: Payload: 0x4449444c0000 +ingress(0x0200000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 debug.print: 4 -ingress(3) Completed: Canister: Payload: 0x4449444c0000 +ingress(0x0300000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 debug.print: 4 -ingress(4) Completed: Canister: Payload: 0x4449444c0000 -ingress(5) Completed: Canister: Payload: 0x4449444c00017d04 +ingress(0x0400000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 +ingress(0x0500000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c00017d04 debug.print: 5 Ok: Payload: 0x4449444c00017d04 debug.print: 4 -ingress(7) Completed: Canister: Payload: 0x4449444c0000 +ingress(0x0700000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 debug.print: 5 Ok: Payload: 0x4449444c00017d04 debug.print: 4 -ingress(9) Completed: Canister: Payload: 0x4449444c0000 +ingress(0x0900000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/query2.drun-run.ok b/test/run-drun/ok/query2.drun-run.ok index d4a603fb3cc..cd27ad478b5 100644 --- a/test/run-drun/ok/query2.drun-run.ok +++ b/test/run-drun/ok/query2.drun-run.ok @@ -1,4 +1,4 @@ -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System debug.print: 2 debug.print: 3 debug.print: 4 @@ -10,4 +10,4 @@ debug.print: In read: debug.print: 5 debug.print: The following fails in the interpreter, for lack of query semantics debug.print: 4 -ingress(1) Completed: Canister: Payload: 0x4449444c0000 +ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/reject.drun-run.ok b/test/run-drun/ok/reject.drun-run.ok index 8ea07ed3242..c1b99684fc1 100644 --- a/test/run-drun/ok/reject.drun-run.ok +++ b/test/run-drun/ok/reject.drun-run.ok @@ -1,9 +1,9 @@ -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System debug.print: 1 -ingress(1) Completed: Canister: Reject: Error +ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Reject: Error debug.print: 1 debug.print: ok -ingress(2) Completed: Canister: Payload: 0x4449444c0000 +ingress(0x0200000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 debug.print: 1 debug.print: ok -ingress(3) Completed: Canister: Reject: Error +ingress(0x0300000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Reject: Error diff --git a/test/run-drun/ok/rts-stats.drun-run.ok b/test/run-drun/ok/rts-stats.drun-run.ok index ebe75965c6a..c684eaf8299 100644 --- a/test/run-drun/ok/rts-stats.drun-run.ok +++ b/test/run-drun/ok/rts-stats.drun-run.ok @@ -1,2 +1,2 @@ debug.print: Size and allocation delta: (10_008, 10_008) -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System diff --git a/test/run-drun/ok/selftail.drun-run.ok b/test/run-drun/ok/selftail.drun-run.ok index 9bc92b6cea2..10f7e4714f4 100644 --- a/test/run-drun/ok/selftail.drun-run.ok +++ b/test/run-drun/ok/selftail.drun-run.ok @@ -1,3 +1,3 @@ debug.print: ok1 debug.print: ok2 -ingress(0) Err: IC0502: Canister ic:2A012B trapped: stack overflow +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) Err: IC0502: Canister ic:2A012B trapped: stack overflow diff --git a/test/run-drun/ok/shared-object.drun-run.ok b/test/run-drun/ok/shared-object.drun-run.ok index 91c74b55809..c30c2566df1 100644 --- a/test/run-drun/ok/shared-object.drun-run.ok +++ b/test/run-drun/ok/shared-object.drun-run.ok @@ -1,2 +1,2 @@ -ingress(0) System -ingress(1) Completed: Canister: Payload: 0x4449444c0000 +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/sharingbug.drun-run.ok b/test/run-drun/ok/sharingbug.drun-run.ok index 43d7af40394..28f361d9907 100644 --- a/test/run-drun/ok/sharingbug.drun-run.ok +++ b/test/run-drun/ok/sharingbug.drun-run.ok @@ -1 +1 @@ -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System diff --git a/test/run-drun/ok/show.drun-run.ok b/test/run-drun/ok/show.drun-run.ok index e422f408f34..f8b97731dfd 100644 --- a/test/run-drun/ok/show.drun-run.ok +++ b/test/run-drun/ok/show.drun-run.ok @@ -33,4 +33,4 @@ debug.print: 0x2A debug.print: 42 debug.print: +42 debug.print: -42 -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System diff --git a/test/run-drun/ok/tailpositions.drun-run.ok b/test/run-drun/ok/tailpositions.drun-run.ok index 2111364c1b2..6c2db2d2d4b 100644 --- a/test/run-drun/ok/tailpositions.drun-run.ok +++ b/test/run-drun/ok/tailpositions.drun-run.ok @@ -5,4 +5,4 @@ debug.print: done 4 debug.print: done 5 debug.print: done 6 debug.print: done 7 -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System diff --git a/test/run-drun/ok/text-iter.drun-run.ok b/test/run-drun/ok/text-iter.drun-run.ok index 2f4ecd9288b..68b1eb0d074 100644 --- a/test/run-drun/ok/text-iter.drun-run.ok +++ b/test/run-drun/ok/text-iter.drun-run.ok @@ -227,4 +227,4 @@ debug.print: П debug.print: debug.print: 🙈 debug.print: -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System diff --git a/test/run-drun/ok/transpose.drun-run.ok b/test/run-drun/ok/transpose.drun-run.ok index 5fbed08ce5a..3b545d87868 100644 --- a/test/run-drun/ok/transpose.drun-run.ok +++ b/test/run-drun/ok/transpose.drun-run.ok @@ -1,3 +1,3 @@ -ingress(0) System +ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System debug.print: All good -ingress(1) Completed: Canister: Payload: 0x4449444c0000 +ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/unsupported.comp-stub.ok b/test/run-drun/ok/unsupported.comp-stub.ok deleted file mode 100644 index b1d376a35ac..00000000000 --- a/test/run-drun/ok/unsupported.comp-stub.ok +++ /dev/null @@ -1,16 +0,0 @@ -unsupported.mo:4.5-4.41: type error, a shared function cannot be private - (This is a limitation of the current version and flag -stub-system-api.) -unsupported.mo:38.26-38.29: type error, a shared function is only allowed as a public field of an actor - (This is a limitation of the current version and flag -stub-system-api.) -unsupported.mo:62.3-62.35: type error, actor classes are not supported; use an actor declaration instead - (This is a limitation of the current version and flag -stub-system-api.) -unsupported.mo:66.3-66.42: type error, actor classes are not supported; use an actor declaration instead - (This is a limitation of the current version and flag -stub-system-api.) -unsupported.mo:70.45-70.53: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program - (This is a limitation of the current version and flag -stub-system-api.) -unsupported.mo:74.37-74.45: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program - (This is a limitation of the current version and flag -stub-system-api.) -unsupported.mo:84.34-84.37: type error, a shared function is only allowed as a public field of an actor - (This is a limitation of the current version and flag -stub-system-api.) -unsupported.mo:85.27-85.30: type error, a shared function is only allowed as a public field of an actor - (This is a limitation of the current version and flag -stub-system-api.) From b4c42890bace1854cd6c8c7e09e1a15e4688888b Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Thu, 23 Jan 2020 16:06:09 +0100 Subject: [PATCH 0998/1176] bump common (#1157) ...no specific reason, but it's fun! We get ``` $ git log --oneline --first-parent 8c07b4a592e7c54ff43adf0420575d4069bfe8a9..233f63f23f0a207f291693fc1983a92a53e28b59 ``` 233f63f (HEAD -> master, origin/master, origin/HEAD) Merge pull request https://github.com/dfinity-lab/common/pull/111 from dfinity-lab/nm-update-naersk acb95af Merge pull request https://github.com/dfinity-lab/common/pull/110 from dfinity-lab/nm-force-docheck 6b8ecf7 Merge pull request https://github.com/dfinity-lab/common/pull/108 from dfinity-lab/basvandijk/fetch-sources.nix 1b0691a Merge pull request https://github.com/dfinity-lab/common/pull/109 from dfinity-lab/basvandijk/filter-dot-git-from-nix-fmt f0db4f4 Merge pull request https://github.com/dfinity-lab/common/pull/107 from dfinity-lab/nm-cmake-bash --- nix/sources.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/sources.json b/nix/sources.json index 86b9847ff33..e3ebd2cead9 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -2,7 +2,7 @@ "common": { "ref": "master", "repo": "ssh://git@github.com/dfinity-lab/common", - "rev": "8c07b4a592e7c54ff43adf0420575d4069bfe8a9", + "rev": "233f63f23f0a207f291693fc1983a92a53e28b59", "type": "git" }, "dfinity": { From 69f248b11b4229f84fa5a5dcd92f7e83c2929f0e Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 24 Jan 2020 14:55:18 +0100 Subject: [PATCH 0999/1176] ic-stub: Remove ability to create canisters (#1154) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ic-stub: Remove ability to create canisters this was a “backdoor” to support code that was removed in #1140. In order to keep the delta betwen ic-stub and the Public Spec small, in both directions, this is removing the code. It was a hack anyway (e.g. it was synchronous), the real deal will likely look different. * Do not import stub.* system api --- ic-stub/src/IC/Canister.hs | 16 ++--- ic-stub/src/IC/Canister/Imp.hs | 90 +++++++--------------------- ic-stub/src/IC/Canister/Interface.hs | 7 +-- ic-stub/src/IC/Canister/Persisted.hs | 6 +- ic-stub/src/IC/Canister/Pure.hs | 6 +- ic-stub/src/IC/Stub.hs | 19 ++---- ic-stub/src/IC/Types.hs | 5 +- src/codegen/compile.ml | 8 +-- 8 files changed, 47 insertions(+), 110 deletions(-) diff --git a/ic-stub/src/IC/Canister.hs b/ic-stub/src/IC/Canister.hs index c4bb63f4664..c5a01ca516c 100644 --- a/ic-stub/src/IC/Canister.hs +++ b/ic-stub/src/IC/Canister.hs @@ -25,15 +25,15 @@ import qualified IC.Canister.Interface as CI -- Here we can swap out the persistence implementation import IC.Canister.Persisted -type InitFunc = ExistingCanisters -> CanisterId -> EntityId -> Blob -> TrapOr (InitResult, WasmState) +type InitFunc = CanisterId -> EntityId -> Blob -> TrapOr (InitResult, WasmState) type UpdateFunc = WasmState -> TrapOr (WasmState, UpdateResult) type QueryFunc = WasmState -> TrapOr Response data CanisterModule = CanisterModule { init_method :: InitFunc - , update_methods :: MethodName ↦ (ExistingCanisters -> EntityId -> Responded -> Blob -> UpdateFunc) + , update_methods :: MethodName ↦ (EntityId -> Responded -> Blob -> UpdateFunc) , query_methods :: MethodName ↦ (EntityId -> Blob -> QueryFunc) - , callbacks :: Callback -> ExistingCanisters -> Responded -> Response -> UpdateFunc + , callbacks :: Callback -> Responded -> Response -> UpdateFunc } parseCanister :: Blob -> Either String CanisterModule @@ -44,11 +44,11 @@ parseCanister bytes = concreteToAbstractModule :: Module -> CanisterModule concreteToAbstractModule wasm_mod = CanisterModule - { init_method = \ex cid caller dat -> initialize ex wasm_mod cid caller dat + { init_method = \cid caller dat -> initialize wasm_mod cid caller dat , update_methods = M.fromList [ (m, - \ex caller responded dat wasm_state -> - invoke wasm_state (CI.Update m ex caller responded dat)) + \caller responded dat wasm_state -> + invoke wasm_state (CI.Update m caller responded dat)) | n <- exportedFunctions wasm_mod , Just m <- return $ stripPrefix "canister_update " n ] @@ -58,6 +58,6 @@ concreteToAbstractModule wasm_mod = CanisterModule | n <- exportedFunctions wasm_mod , Just m <- return $ stripPrefix "canister_query " n ] - , callbacks = \cb ex responded res wasm_state -> - invoke wasm_state (CI.Callback cb ex responded res) + , callbacks = \cb responded res wasm_state -> + invoke wasm_state (CI.Callback cb responded res) } diff --git a/ic-stub/src/IC/Canister/Imp.hs b/ic-stub/src/IC/Canister/Imp.hs index fd9a89660b6..5c853bb0a7a 100644 --- a/ic-stub/src/IC/Canister/Imp.hs +++ b/ic-stub/src/IC/Canister/Imp.hs @@ -27,9 +27,7 @@ import Control.Monad.Except import Data.STRef import Data.Maybe import Data.Int -import Text.Printf -import IC.Id import IC.Types import IC.Wasm.Winter import IC.Wasm.Imports @@ -51,27 +49,23 @@ data ExecutionState s = ExecutionState { inst :: Instance s , self_id :: CanisterId , params :: Params - , existing_canisters :: ExistingCanisters -- now the mutable parts , responded :: Responded , response :: Maybe Response , reply_data :: Blob , calls :: [MethodCall] - , new_canisters :: NewCanisters } -initalExecutionState :: CanisterId -> Instance s -> ExistingCanisters -> Responded -> ExecutionState s -initalExecutionState self_id inst ex responded = ExecutionState +initalExecutionState :: CanisterId -> Instance s -> Responded -> ExecutionState s +initalExecutionState self_id inst responded = ExecutionState { inst , self_id - , existing_canisters = ex , params = Params Nothing Nothing 0 "" , responded , response = Nothing , reply_data = mempty , calls = mempty - , new_canisters = mempty } -- Some bookkeeping to access the ExecutionState @@ -136,10 +130,6 @@ appendCall :: ESRef s -> MethodCall -> HostM s () appendCall esref c = modES esref $ \es -> es { calls = calls es ++ [c] } -appendNewCanister :: ESRef s -> (CanisterId, Blob, Blob) -> HostM s () -appendNewCanister esref c = modES esref $ \es -> - es { new_canisters = new_canisters es ++ [c] } - -- The System API, with all imports -- The code is defined in the where clause to scope over the 'ESRef' @@ -161,9 +151,6 @@ systemAPI esref = , toImport "ic0" "call_simple" call_simple , toImport "ic0" "debug_print" debug_print , toImport "ic0" "trap" explicit_trap - , toImport "stub" "create_canister" create_canister - , toImport "stub" "created_canister_id_size" created_canister_id_size - , toImport "stub" "created_canister_id_copy" created_canister_id_copy ] where -- Utilities @@ -195,16 +182,6 @@ systemAPI esref = , \(dst, offset, size) -> get_blob >>= \blob -> copy_to_canister dst offset size blob ) - size_and_copy1 :: (a -> HostM s Blob) -> - ( a -> HostM s Int32 - , (a, Int32, Int32, Int32) -> HostM s () - ) - size_and_copy1 get_blob = - ( \x -> - get_blob x >>= \blob -> return $ fromIntegral (BS.length blob) - , \(x, dst, offset, size) -> - get_blob x >>= \blob -> copy_to_canister dst offset size blob - ) -- Unsafely print (if not in silent mode) putBytes :: BS.ByteString -> HostM s () @@ -314,30 +291,6 @@ systemAPI esref = let msg = BSU.toString bytes throwError $ "canister trapped explicitly: " ++ msg - -- These system calls are not specified, and are backdoors for use - -- by the Motoko test suite - - create_canister :: (Int32, Int32, Int32, Int32) -> HostM s Int32 - create_canister (mod_src, mod_size, arg_src, arg_size) = do - ex <- gets existing_canisters - new <- gets new_canisters - let can_id = freshId (map (\(i,_,_) -> i) new ++ ex) - let idx = fromIntegral $ length new - mod <- copy_from_canister "create_canister" mod_src mod_size - arg <- copy_from_canister "create_canister" arg_src arg_size - appendNewCanister esref (can_id, mod, arg) - return idx - - created_canister_id_size :: Int32 -> HostM s Int32 - created_canister_id_copy :: (Int32, Int32, Int32, Int32) -> HostM s () - (created_canister_id_size, created_canister_id_copy) = size_and_copy1 $ \idx' -> do - let idx = fromIntegral idx' - new <- gets new_canisters - unless (idx >= 0 && idx < length new) $ - throwError $ printf "created_canister_id index (%d) out of bounds (%d)" idx (length new) - let (i,_,_) = new !! idx - return (rawEntityId i) - -- The state of an instance, consistig of the underlying Wasm state, -- additional remembered information like the CanisterId -- and the 'ESRef' that the system api functions are accessing @@ -352,14 +305,14 @@ rawInitialize esref cid wasm_mod = do Right inst -> return $ Return (esref, cid, inst) rawInvoke :: ImpState s -> CI.CanisterMethod r -> ST s (TrapOr r) -rawInvoke esref (CI.Initialize ex wasm_mod caller dat) = - rawInitializeMethod esref ex wasm_mod caller dat +rawInvoke esref (CI.Initialize wasm_mod caller dat) = + rawInitializeMethod esref wasm_mod caller dat rawInvoke esref (CI.Query name caller dat) = rawQueryMethod esref name caller dat -rawInvoke esref (CI.Update name ex caller responded dat) = - rawUpdateMethod esref name ex caller responded dat -rawInvoke esref (CI.Callback cb ex responded res) = - rawCallbackMethod esref cb ex responded res +rawInvoke esref (CI.Update name caller responded dat) = + rawUpdateMethod esref name caller responded dat +rawInvoke esref (CI.Callback cb responded res) = + rawCallbackMethod esref cb responded res cantRespond :: Responded cantRespond = Responded True @@ -367,10 +320,10 @@ cantRespond = Responded True canRespond :: Responded canRespond = Responded False -rawInitializeMethod :: ImpState s -> ExistingCanisters -> Module -> EntityId -> Blob -> ST s (TrapOr InitResult) -rawInitializeMethod (esref, cid, inst) ex wasm_mod caller dat = do +rawInitializeMethod :: ImpState s -> Module -> EntityId -> Blob -> ST s (TrapOr InitResult) +rawInitializeMethod (esref, cid, inst) wasm_mod caller dat = do result <- runExceptT $ do - let es = (initalExecutionState cid inst ex cantRespond) + let es = (initalExecutionState cid inst cantRespond) { params = Params { param_dat = Just dat , param_caller = Just caller @@ -389,11 +342,11 @@ rawInitializeMethod (esref, cid, inst) ex wasm_mod caller dat = do Left err -> return $ Trap err Right (_, es') -> return $ -- TODO: extract canisters and calls here - Return (new_canisters es', calls es') + Return (calls es') rawQueryMethod :: ImpState s -> MethodName -> EntityId -> Blob -> ST s (TrapOr Response) rawQueryMethod (esref, cid, inst) method caller dat = do - let es = (initalExecutionState cid inst [] canRespond) + let es = (initalExecutionState cid inst canRespond) { params = Params { param_dat = Just dat , param_caller = Just caller @@ -411,9 +364,9 @@ rawQueryMethod (esref, cid, inst) method caller dat = do | Just r <- response es' -> return $ Return r | otherwise -> return $ Trap "No response" -rawUpdateMethod :: ImpState s -> MethodName -> ExistingCanisters -> EntityId -> Responded -> Blob -> ST s (TrapOr UpdateResult) -rawUpdateMethod (esref, cid, inst) method ex caller responded dat = do - let es = (initalExecutionState cid inst ex responded) +rawUpdateMethod :: ImpState s -> MethodName -> EntityId -> Responded -> Blob -> ST s (TrapOr UpdateResult) +rawUpdateMethod (esref, cid, inst) method caller responded dat = do + let es = (initalExecutionState cid inst responded) { params = Params { param_dat = Just dat , param_caller = Just caller @@ -426,16 +379,16 @@ rawUpdateMethod (esref, cid, inst) method ex caller responded dat = do invokeExport inst ("canister_update " ++ method) [] case result of Left err -> return $ Trap err - Right (_, es') -> return $ Return (new_canisters es', calls es', response es') + Right (_, es') -> return $ Return (calls es', response es') -rawCallbackMethod :: ImpState s -> Callback -> ExistingCanisters -> Responded -> Response -> ST s (TrapOr UpdateResult) -rawCallbackMethod (esref, cid, inst) callback ex responded res = do +rawCallbackMethod :: ImpState s -> Callback -> Responded -> Response -> ST s (TrapOr UpdateResult) +rawCallbackMethod (esref, cid, inst) callback responded res = do let params = case res of Reply dat -> Params { param_dat = Just dat, param_caller = Nothing, reject_code = 0, reject_message = "" } Reject (rc, reject_message) -> Params { param_dat = Nothing, param_caller = Nothing, reject_code = rejectCode rc, reject_message } - let es = (initalExecutionState cid inst ex responded) { params } + let es = (initalExecutionState cid inst responded) { params } let WasmClosure fun_idx env = case res of Reply {} -> reply_callback callback @@ -445,6 +398,5 @@ rawCallbackMethod (esref, cid, inst) callback ex responded res = do invokeTable inst fun_idx [I32 env] case result of Left err -> return $ Trap err - Right (_, es') -> return $ - Return (new_canisters es', calls es', response es') + Right (_, es') -> return $ Return (calls es', response es') diff --git a/ic-stub/src/IC/Canister/Interface.hs b/ic-stub/src/IC/Canister/Interface.hs index 779a61caa91..8b2a7d64446 100644 --- a/ic-stub/src/IC/Canister/Interface.hs +++ b/ic-stub/src/IC/Canister/Interface.hs @@ -16,9 +16,8 @@ module IC.Canister.Interface where import IC.Types import IC.Wasm.Winter (Module) - data CanisterMethod r where - Initialize :: ExistingCanisters -> Module -> EntityId -> Blob -> CanisterMethod InitResult + Initialize :: Module -> EntityId -> Blob -> CanisterMethod InitResult Query :: MethodName -> EntityId -> Blob -> CanisterMethod Response - Update :: MethodName -> ExistingCanisters -> EntityId -> Responded -> Blob -> CanisterMethod UpdateResult - Callback :: Callback -> ExistingCanisters -> Responded -> Response -> CanisterMethod UpdateResult + Update :: MethodName -> EntityId -> Responded -> Blob -> CanisterMethod UpdateResult + Callback :: Callback -> Responded -> Response -> CanisterMethod UpdateResult diff --git a/ic-stub/src/IC/Canister/Persisted.hs b/ic-stub/src/IC/Canister/Persisted.hs index ffb3ebbfbdd..2a0b4a7075e 100644 --- a/ic-stub/src/IC/Canister/Persisted.hs +++ b/ic-stub/src/IC/Canister/Persisted.hs @@ -23,12 +23,12 @@ import IC.Canister.Imp data WasmState = WasmState Module CanisterId PInstance -initialize :: ExistingCanisters -> Module -> CanisterId -> EntityId -> Blob -> TrapOr (InitResult, WasmState) -initialize ex wasm_mod cid caller dat = runESST $ \esref -> +initialize :: Module -> CanisterId -> EntityId -> Blob -> TrapOr (InitResult, WasmState) +initialize wasm_mod cid caller dat = runESST $ \esref -> rawInitialize esref cid wasm_mod >>= \case Trap err -> return $ Trap err Return rs -> - rawInvoke rs (CI.Initialize ex wasm_mod caller dat) >>= \case + rawInvoke rs (CI.Initialize wasm_mod caller dat) >>= \case Trap err -> return $ Trap err Return ir -> Return . (ir,) <$> newWasmState wasm_mod rs diff --git a/ic-stub/src/IC/Canister/Pure.hs b/ic-stub/src/IC/Canister/Pure.hs index dc03767347b..84573c722f8 100644 --- a/ic-stub/src/IC/Canister/Pure.hs +++ b/ic-stub/src/IC/Canister/Pure.hs @@ -34,12 +34,12 @@ data WasmState = WasmState , ws_calls :: [ACall] -- in reverse order } -initialize :: Module -> ExistingCanisters -> CanisterId -> EntityId -> Blob -> TrapOr WasmState -initialize wasm_mod ex cid caller dat = runESST $ \esref -> +initialize :: Module -> CanisterId -> EntityId -> Blob -> TrapOr WasmState +initialize wasm_mod cid caller dat = runESST $ \esref -> rawInitialize esref cid wasm_mod >>= \case Trap err -> return $ Trap err Return rs -> do - let m = CI.Initialize ex wasm_mod caller dat + let m = CI.Initialize wasm_mod caller dat result <- rawInvoke rs m let state' = WasmState wasm_mod cid [ACall m] case result of diff --git a/ic-stub/src/IC/Stub.hs b/ic-stub/src/IC/Stub.hs index f9e661cd644..dbcba177289 100644 --- a/ic-stub/src/IC/Stub.hs +++ b/ic-stub/src/IC/Stub.hs @@ -230,15 +230,11 @@ processRequest r@(InstallRequest canister_id user_id can_mod dat) = , last_trap = Nothing } - existing_canisters <- gets (M.keys . canisters) - - case init_method can_mod existing_canisters canister_id user_id dat of + case init_method can_mod canister_id user_id dat of Trap msg -> setReqStatus r $ Rejected (RC_CANISTER_ERROR, "Initialization trapped: " ++ msg) - Return ((new_canisters, new_calls), wasm_state) -> do + Return (new_calls, wasm_state) -> do installCanister canister_id can_mod wasm_state - mapM_ (\(i,_,_) -> createEmptyCanister i) new_canisters - mapM_ (\(i,mod,dat) -> submitRequest (InstallRequest i canister_id mod dat)) new_canisters mapM_ (newCall ctxt_id) new_calls setReqStatus r $ Completed CompleteUnit @@ -308,18 +304,17 @@ invokeEntry :: ICT m => m (TrapOr (WasmState, UpdateResult)) invokeEntry ctxt_id (CanState wasm_state can_mod) entry = do responded <- respondedCallID ctxt_id - existing_canisters <- gets (M.keys . canisters) case entry of Public method dat -> do caller <- callerOfCallID ctxt_id case M.lookup method (update_methods can_mod) of Just f -> - return $ f existing_canisters caller responded dat wasm_state + return $ f caller responded dat wasm_state Nothing -> do let reject = Reject (RC_DESTINATION_INVALID, "update method does not exist: " ++ method) - return $ Return (wasm_state, ([], [], Just reject)) + return $ Return (wasm_state, ([], Just reject)) Closure cb r -> - return $ callbacks can_mod cb existing_canisters responded r wasm_state + return $ callbacks can_mod cb responded r wasm_state newCall :: ICT m => CallId -> MethodCall -> m () newCall from_ctxt_id call = do @@ -346,10 +341,8 @@ processMessage (CallMessage ctxt_id entry) = do Trap msg -> do logTrap msg rememberTrap ctxt_id msg - Return (new_state, (new_canisters, new_calls, mb_response)) -> do + Return (new_state, (new_calls, mb_response)) -> do setCanisterState callee new_state - mapM_ (\(i,_,_) -> createEmptyCanister i) new_canisters - mapM_ (\(i,mod,dat) -> submitRequest (InstallRequest i callee mod dat)) new_canisters mapM_ (newCall ctxt_id) new_calls mapM_ res mb_response diff --git a/ic-stub/src/IC/Types.hs b/ic-stub/src/IC/Types.hs index 39415fb0824..b4d254d4b85 100644 --- a/ic-stub/src/IC/Types.hs +++ b/ic-stub/src/IC/Types.hs @@ -72,7 +72,6 @@ data MethodCall = MethodCall deriving Show type ExistingCanisters = [CanisterId] -type NewCanisters = [(CanisterId, Blob, Blob)] -type InitResult = (NewCanisters, [MethodCall]) -type UpdateResult = (NewCanisters, [MethodCall], Maybe Response) +type InitResult = [MethodCall] +type UpdateResult = ([MethodCall], Maybe Response) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 7e684b72454..b7a49a8cff1 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -2799,14 +2799,8 @@ module Dfinity = struct let system_imports env = match E.mode env with - | Flags.ICMode -> + | Flags.ICMode | Flags.StubMode -> import_ic0 env - | Flags.StubMode -> - import_ic0 env; - E.add_func_import env "stub" "create_canister" (i32s 4) [I32Type]; - E.add_func_import env "stub" "created_canister_id_size" (i32s 1) [I32Type]; - E.add_func_import env "stub" "created_canister_id_copy" (i32s 4) []; - () | Flags.WASIMode -> E.add_func_import env "wasi_unstable" "fd_write" [I32Type; I32Type; I32Type; I32Type] [I32Type]; | Flags.WasmMode -> () From ae9525c6c2e5fea7d8a937c2aad396855e7dba51 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Sat, 25 Jan 2020 14:59:55 +0100 Subject: [PATCH 1000/1176] Bump drun (#1158) * Bump drun ``` c9459e781 Drun: Do not print message id (#2368) f3196677c Merge pull request #2367 from dfinity-lab/refactor_induction_pool ``` * Update more test output --- nix/sources.json | 2 +- test/perf/ok/reversi.drun-run.ok | 18 +++++++++--------- test/run-drun/ok/GIT-843.drun-run.ok | 4 ++-- test/run-drun/ok/actor-import.drun-run.ok | 8 ++++---- .../ok/actor-reference-return.drun-run.ok | 2 +- test/run-drun/ok/actor-reference.drun-run.ok | 2 +- .../ok/array-out-of-bounds.drun-run.ok | 6 +++--- test/run-drun/ok/async-calls1.drun-run.ok | 4 ++-- test/run-drun/ok/async-calls2.drun-run.ok | 4 ++-- test/run-drun/ok/async-calls3.drun-run.ok | 4 ++-- test/run-drun/ok/call-async-method.drun-run.ok | 4 ++-- test/run-drun/ok/caller.drun-run.ok | 12 ++++++------ test/run-drun/ok/closure-params.drun-run.ok | 4 ++-- test/run-drun/ok/counter.drun-run.ok | 12 ++++++------ test/run-drun/ok/counter2.drun-run.ok | 4 ++-- test/run-drun/ok/data-params.drun-run.ok | 4 ++-- test/run-drun/ok/divide-by-zero.drun-run.ok | 2 +- test/run-drun/ok/empty-actor.drun-run.ok | 2 +- test/run-drun/ok/empty-call.drun-run.ok | 4 ++-- .../run-drun/ok/flatten-awaitables.drun-run.ok | 4 ++-- test/run-drun/ok/free-callbacks.drun-run.ok | 4 ++-- test/run-drun/ok/generic-tail-rec.drun-run.ok | 2 +- test/run-drun/ok/hello-world-async.drun-run.ok | 4 ++-- test/run-drun/ok/hello-world-await.drun-run.ok | 4 ++-- .../ok/hello-world-message.drun-run.ok | 2 +- .../run-drun/ok/hello-world-return.drun-run.ok | 2 +- test/run-drun/ok/hello-world.drun-run.ok | 2 +- test/run-drun/ok/ic-calls.drun-run.ok | 4 ++-- test/run-drun/ok/idl-any.drun-run.ok | 2 +- test/run-drun/ok/idl-bad.drun-run.ok | 2 +- test/run-drun/ok/idl-buf-size-bug.drun-run.ok | 4 ++-- test/run-drun/ok/idl-field-escape.drun-run.ok | 2 +- test/run-drun/ok/idl-func.drun-run.ok | 2 +- test/run-drun/ok/idl-nary.drun-run.ok | 2 +- test/run-drun/ok/idl-nat-int.drun-run.ok | 2 +- test/run-drun/ok/idl-option.drun-run.ok | 2 +- test/run-drun/ok/idl-pair.drun-run.ok | 2 +- test/run-drun/ok/idl-record.drun-run.ok | 2 +- test/run-drun/ok/idl-shorthand.drun-run.ok | 2 +- test/run-drun/ok/idl-tuple.drun-run.ok | 2 +- test/run-drun/ok/idl-unit.drun-run.ok | 2 +- test/run-drun/ok/idl-variant.drun-run.ok | 2 +- test/run-drun/ok/idl-vector.drun-run.ok | 2 +- test/run-drun/ok/large-array.drun-run.ok | 2 +- test/run-drun/ok/local-throw.drun-run.ok | 4 ++-- test/run-drun/ok/log-slow.drun-run.ok | 2 +- test/run-drun/ok/mod-rebind.drun-run.ok | 2 +- test/run-drun/ok/oneway-throw.drun-run.ok | 4 ++-- test/run-drun/ok/oneway.drun-run.ok | 4 ++-- test/run-drun/ok/oom.drun-run.ok | 6 +++--- test/run-drun/ok/print-from-init.drun-run.ok | 2 +- test/run-drun/ok/query.drun-run.ok | 16 ++++++++-------- test/run-drun/ok/query2.drun-run.ok | 4 ++-- test/run-drun/ok/reject.drun-run.ok | 8 ++++---- test/run-drun/ok/rts-stats.drun-run.ok | 2 +- test/run-drun/ok/selftail.drun-run.ok | 2 +- test/run-drun/ok/shared-object.drun-run.ok | 4 ++-- test/run-drun/ok/sharingbug.drun-run.ok | 2 +- test/run-drun/ok/show.drun-run.ok | 2 +- test/run-drun/ok/tailpositions.drun-run.ok | 2 +- test/run-drun/ok/text-iter.drun-run.ok | 2 +- test/run-drun/ok/transpose.drun-run.ok | 4 ++-- 62 files changed, 118 insertions(+), 118 deletions(-) diff --git a/nix/sources.json b/nix/sources.json index e3ebd2cead9..fa30810255e 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -8,7 +8,7 @@ "dfinity": { "ref": "master", "repo": "ssh://git@github.com/dfinity-lab/dfinity", - "rev": "0b3071a3f7d489d560a16417d07930687a6709d4", + "rev": "c9459e781f5b4b77452949f1e63725612b2201c3", "type": "git" }, "esm": { diff --git a/test/perf/ok/reversi.drun-run.ok b/test/perf/ok/reversi.drun-run.ok index 7afeb992747..d89058613fa 100644 --- a/test/perf/ok/reversi.drun-run.ok +++ b/test/perf/ok/reversi.drun-run.ok @@ -1,9 +1,9 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System -ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 -ingress(0x0200000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e4f2a2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a -ingress(0x0300000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c000171024f4b -ingress(0x0400000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e4f2e2e2e0a2e2e2e4f4f2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a -ingress(0x0500000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c000171024f4b -ingress(0x0600000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a -ingress(0x0700000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c000171024f4b -ingress(0x0800000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e4f4f2e2e2e0a2e2e4f4f4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a +ingress System +ingress Completed: Canister: Payload: 0x4449444c0000 +ingress Completed: Canister: Payload: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e4f2a2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a +ingress Completed: Canister: Payload: 0x4449444c000171024f4b +ingress Completed: Canister: Payload: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e4f2e2e2e0a2e2e2e4f4f2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a +ingress Completed: Canister: Payload: 0x4449444c000171024f4b +ingress Completed: Canister: Payload: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a +ingress Completed: Canister: Payload: 0x4449444c000171024f4b +ingress Completed: Canister: Payload: 0x4449444c000171482e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2a4f2e2e2e0a2e2e2e4f4f2e2e2e0a2e2e4f4f4f2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a2e2e2e2e2e2e2e2e0a diff --git a/test/run-drun/ok/GIT-843.drun-run.ok b/test/run-drun/ok/GIT-843.drun-run.ok index ac0854c8f7e..0b6b7d2be93 100644 --- a/test/run-drun/ok/GIT-843.drun-run.ok +++ b/test/run-drun/ok/GIT-843.drun-run.ok @@ -1,3 +1,3 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System debug.print: ok -ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/actor-import.drun-run.ok b/test/run-drun/ok/actor-import.drun-run.ok index 7ffff66814d..2c83c29a52f 100644 --- a/test/run-drun/ok/actor-import.drun-run.ok +++ b/test/run-drun/ok/actor-import.drun-run.ok @@ -1,4 +1,4 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System -ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c016900010001022a01 -ingress(0x0200000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c016900010001022a01 -ingress(0x0300000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c016900010001022a01 +ingress System +ingress Completed: Canister: Payload: 0x4449444c016900010001022a01 +ingress Completed: Canister: Payload: 0x4449444c016900010001022a01 +ingress Completed: Canister: Payload: 0x4449444c016900010001022a01 diff --git a/test/run-drun/ok/actor-reference-return.drun-run.ok b/test/run-drun/ok/actor-reference-return.drun-run.ok index 3cea69d6b5b..b2a472d30c7 100644 --- a/test/run-drun/ok/actor-reference-return.drun-run.ok +++ b/test/run-drun/ok/actor-reference-return.drun-run.ok @@ -1,3 +1,3 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System Ok: Payload: 0x4449444c01690001000105c0fefed00d Ok: Payload: 0x4449444c0169000100010dc0fefed00dcafebabedeadbeef diff --git a/test/run-drun/ok/actor-reference.drun-run.ok b/test/run-drun/ok/actor-reference.drun-run.ok index 28f361d9907..5d7495cc8a5 100644 --- a/test/run-drun/ok/actor-reference.drun-run.ok +++ b/test/run-drun/ok/actor-reference.drun-run.ok @@ -1 +1 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System diff --git a/test/run-drun/ok/array-out-of-bounds.drun-run.ok b/test/run-drun/ok/array-out-of-bounds.drun-run.ok index c7b5985b2d0..d8dd8c7a973 100644 --- a/test/run-drun/ok/array-out-of-bounds.drun-run.ok +++ b/test/run-drun/ok/array-out-of-bounds.drun-run.ok @@ -1,3 +1,3 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System -ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Err: IC0503: Canister ic:2A012B trapped explicitly: Array index out of bounds -ingress(0x0200000000000000000000000000000000000000000000000000000000000000) Err: IC0503: Canister ic:2A012B trapped explicitly: Array index out of bounds +ingress System +ingress Err: IC0503: Canister ic:2A012B trapped explicitly: Array index out of bounds +ingress Err: IC0503: Canister ic:2A012B trapped explicitly: Array index out of bounds diff --git a/test/run-drun/ok/async-calls1.drun-run.ok b/test/run-drun/ok/async-calls1.drun-run.ok index c30c2566df1..adce7c8af5f 100644 --- a/test/run-drun/ok/async-calls1.drun-run.ok +++ b/test/run-drun/ok/async-calls1.drun-run.ok @@ -1,2 +1,2 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System -ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 +ingress System +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/async-calls2.drun-run.ok b/test/run-drun/ok/async-calls2.drun-run.ok index c30c2566df1..adce7c8af5f 100644 --- a/test/run-drun/ok/async-calls2.drun-run.ok +++ b/test/run-drun/ok/async-calls2.drun-run.ok @@ -1,2 +1,2 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System -ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 +ingress System +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/async-calls3.drun-run.ok b/test/run-drun/ok/async-calls3.drun-run.ok index c30c2566df1..adce7c8af5f 100644 --- a/test/run-drun/ok/async-calls3.drun-run.ok +++ b/test/run-drun/ok/async-calls3.drun-run.ok @@ -1,2 +1,2 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System -ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 +ingress System +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/call-async-method.drun-run.ok b/test/run-drun/ok/call-async-method.drun-run.ok index c244fbb189a..10df3fc3ede 100644 --- a/test/run-drun/ok/call-async-method.drun-run.ok +++ b/test/run-drun/ok/call-async-method.drun-run.ok @@ -1,2 +1,2 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System -ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Err: IC0503: Canister ic:2A012B trapped explicitly: not a self-call +ingress System +ingress Err: IC0503: Canister ic:2A012B trapped explicitly: not a self-call diff --git a/test/run-drun/ok/caller.drun-run.ok b/test/run-drun/ok/caller.drun-run.ok index 2d8c9b2e202..ea45133a315 100644 --- a/test/run-drun/ok/caller.drun-run.ok +++ b/test/run-drun/ok/caller.drun-run.ok @@ -1,10 +1,10 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System -ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 -ingress(0x0200000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 -ingress(0x0300000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 -ingress(0x0400000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 +ingress System +ingress Completed: Canister: Payload: 0x4449444c0000 +ingress Completed: Canister: Payload: 0x4449444c0000 +ingress Completed: Canister: Payload: 0x4449444c0000 +ingress Completed: Canister: Payload: 0x4449444c0000 Ok: Payload: 0x4449444c0000 -ingress(0x0600000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c016d7b010021000000000000000000000000000000000000000000000000000000000000000000 +ingress Completed: Canister: Payload: 0x4449444c016d7b010021000000000000000000000000000000000000000000000000000000000000000000 Ok: Payload: 0x4449444c0001798d3a7c7a Ok: Payload: 0x4449444c00017d21 Ok: Payload: 0x4449444c016e7b01000100 diff --git a/test/run-drun/ok/closure-params.drun-run.ok b/test/run-drun/ok/closure-params.drun-run.ok index 3d7c539c0f0..ea0b75db99b 100644 --- a/test/run-drun/ok/closure-params.drun-run.ok +++ b/test/run-drun/ok/closure-params.drun-run.ok @@ -1,4 +1,4 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System debug.print: 1 debug.print: 3 debug.print: 6 @@ -9,4 +9,4 @@ debug.print: 3 debug.print: 6 debug.print: 10 debug.print: 15 -ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/counter.drun-run.ok b/test/run-drun/ok/counter.drun-run.ok index c72b2fbb3b6..7e9c582d028 100644 --- a/test/run-drun/ok/counter.drun-run.ok +++ b/test/run-drun/ok/counter.drun-run.ok @@ -1,10 +1,10 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System debug.print: 2 -ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 +ingress Completed: Canister: Payload: 0x4449444c0000 debug.print: 3 -ingress(0x0200000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 +ingress Completed: Canister: Payload: 0x4449444c0000 debug.print: 4 -ingress(0x0300000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 +ingress Completed: Canister: Payload: 0x4449444c0000 debug.print: 4 -ingress(0x0400000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 -ingress(0x0500000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c00017d04 +ingress Completed: Canister: Payload: 0x4449444c0000 +ingress Completed: Canister: Payload: 0x4449444c00017d04 diff --git a/test/run-drun/ok/counter2.drun-run.ok b/test/run-drun/ok/counter2.drun-run.ok index 2bb6d827c1d..d77cdc6fc88 100644 --- a/test/run-drun/ok/counter2.drun-run.ok +++ b/test/run-drun/ok/counter2.drun-run.ok @@ -1,4 +1,4 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System debug.print: 2 debug.print: 3 debug.print: 4 @@ -13,4 +13,4 @@ debug.print: 11 debug.print: 12 debug.print: 13 debug.print: 14 -ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/data-params.drun-run.ok b/test/run-drun/ok/data-params.drun-run.ok index 47a14e2fcc4..2c75785c8b9 100644 --- a/test/run-drun/ok/data-params.drun-run.ok +++ b/test/run-drun/ok/data-params.drun-run.ok @@ -1,4 +1,4 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System debug.print: 0 debug.print: +1 debug.print: +3 @@ -40,4 +40,4 @@ debug.print: +2_148_489_869 debug.print: +2_148_489_911 debug.print: +2_148_489_869 debug.print: +4_295_973_516 -ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/divide-by-zero.drun-run.ok b/test/run-drun/ok/divide-by-zero.drun-run.ok index 92786aae5bb..aa1e4ffefc8 100644 --- a/test/run-drun/ok/divide-by-zero.drun-run.ok +++ b/test/run-drun/ok/divide-by-zero.drun-run.ok @@ -1 +1 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) Err: IC0502: Canister ic:2A012B trapped: integer division by 0 +ingress Err: IC0502: Canister ic:2A012B trapped: integer division by 0 diff --git a/test/run-drun/ok/empty-actor.drun-run.ok b/test/run-drun/ok/empty-actor.drun-run.ok index 28f361d9907..5d7495cc8a5 100644 --- a/test/run-drun/ok/empty-actor.drun-run.ok +++ b/test/run-drun/ok/empty-actor.drun-run.ok @@ -1 +1 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System diff --git a/test/run-drun/ok/empty-call.drun-run.ok b/test/run-drun/ok/empty-call.drun-run.ok index c30c2566df1..adce7c8af5f 100644 --- a/test/run-drun/ok/empty-call.drun-run.ok +++ b/test/run-drun/ok/empty-call.drun-run.ok @@ -1,2 +1,2 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System -ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 +ingress System +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/flatten-awaitables.drun-run.ok b/test/run-drun/ok/flatten-awaitables.drun-run.ok index bc4bd137795..be2585eeb12 100644 --- a/test/run-drun/ok/flatten-awaitables.drun-run.ok +++ b/test/run-drun/ok/flatten-awaitables.drun-run.ok @@ -1,4 +1,4 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System debug.print: first-order debug.print: 0 debug.print: 1 @@ -33,4 +33,4 @@ debug.print: 12 debug.print: 13 debug.print: 14 debug.print: 15 -ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/free-callbacks.drun-run.ok b/test/run-drun/ok/free-callbacks.drun-run.ok index d1fc8e14e09..4d6a0e18dcb 100644 --- a/test/run-drun/ok/free-callbacks.drun-run.ok +++ b/test/run-drun/ok/free-callbacks.drun-run.ok @@ -1,3 +1,3 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System debug.print: Ignore Diff: (ignored) -ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/generic-tail-rec.drun-run.ok b/test/run-drun/ok/generic-tail-rec.drun-run.ok index fd26a31a9da..038476f0d49 100644 --- a/test/run-drun/ok/generic-tail-rec.drun-run.ok +++ b/test/run-drun/ok/generic-tail-rec.drun-run.ok @@ -2,4 +2,4 @@ debug.print: done 1 debug.print: done 2 debug.print: done 3 debug.print: done 4 -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System diff --git a/test/run-drun/ok/hello-world-async.drun-run.ok b/test/run-drun/ok/hello-world-async.drun-run.ok index f995f560844..631fce056df 100644 --- a/test/run-drun/ok/hello-world-async.drun-run.ok +++ b/test/run-drun/ok/hello-world-async.drun-run.ok @@ -1,4 +1,4 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System debug.print: Hello debug.print: World! -ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/hello-world-await.drun-run.ok b/test/run-drun/ok/hello-world-await.drun-run.ok index 0a99d430ad2..73210bba664 100644 --- a/test/run-drun/ok/hello-world-await.drun-run.ok +++ b/test/run-drun/ok/hello-world-await.drun-run.ok @@ -1,3 +1,3 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System debug.print: Hello World! -ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/hello-world-message.drun-run.ok b/test/run-drun/ok/hello-world-message.drun-run.ok index 28f361d9907..5d7495cc8a5 100644 --- a/test/run-drun/ok/hello-world-message.drun-run.ok +++ b/test/run-drun/ok/hello-world-message.drun-run.ok @@ -1 +1 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System diff --git a/test/run-drun/ok/hello-world-return.drun-run.ok b/test/run-drun/ok/hello-world-return.drun-run.ok index 786a08e7160..d4f4cd6989c 100644 --- a/test/run-drun/ok/hello-world-return.drun-run.ok +++ b/test/run-drun/ok/hello-world-return.drun-run.ok @@ -1,3 +1,3 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System Ok: Payload: 0x4449444c0001710c48656c6c6f20576f726c6421 Ok: Payload: 0x4449444c0001710c48656c6c6f20576f726c6421 diff --git a/test/run-drun/ok/hello-world.drun-run.ok b/test/run-drun/ok/hello-world.drun-run.ok index 6c3938085f2..55e82f25c0b 100644 --- a/test/run-drun/ok/hello-world.drun-run.ok +++ b/test/run-drun/ok/hello-world.drun-run.ok @@ -1,2 +1,2 @@ debug.print: Hello World! -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System diff --git a/test/run-drun/ok/ic-calls.drun-run.ok b/test/run-drun/ok/ic-calls.drun-run.ok index c30c2566df1..adce7c8af5f 100644 --- a/test/run-drun/ok/ic-calls.drun-run.ok +++ b/test/run-drun/ok/ic-calls.drun-run.ok @@ -1,2 +1,2 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System -ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 +ingress System +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-any.drun-run.ok b/test/run-drun/ok/idl-any.drun-run.ok index bc46256e3f6..94fb99baad1 100644 --- a/test/run-drun/ok/idl-any.drun-run.ok +++ b/test/run-drun/ok/idl-any.drun-run.ok @@ -1,4 +1,4 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System debug.print: ok: Foo Ok: Payload: 0x4449444c0000 debug.print: ok: Foo diff --git a/test/run-drun/ok/idl-bad.drun-run.ok b/test/run-drun/ok/idl-bad.drun-run.ok index 544da366c61..f5db62135b4 100644 --- a/test/run-drun/ok/idl-bad.drun-run.ok +++ b/test/run-drun/ok/idl-bad.drun-run.ok @@ -1,3 +1,3 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System debug.print: IDL error: missing magic bytes Err: IC0502: Canister ic:2A012B trapped: unreachable diff --git a/test/run-drun/ok/idl-buf-size-bug.drun-run.ok b/test/run-drun/ok/idl-buf-size-bug.drun-run.ok index c30c2566df1..adce7c8af5f 100644 --- a/test/run-drun/ok/idl-buf-size-bug.drun-run.ok +++ b/test/run-drun/ok/idl-buf-size-bug.drun-run.ok @@ -1,2 +1,2 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System -ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 +ingress System +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-field-escape.drun-run.ok b/test/run-drun/ok/idl-field-escape.drun-run.ok index 5a2c456067b..4be00a322c4 100644 --- a/test/run-drun/ok/idl-field-escape.drun-run.ok +++ b/test/run-drun/ok/idl-field-escape.drun-run.ok @@ -1,4 +1,4 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System Ok: Payload: 0x4449444c016c01868eb7027f0100 Ok: Payload: 0x4449444c016c01868eb7027f0100 Ok: Payload: 0x4449444c016c03007c017dbcfef7b102710100ffff03802003585858 diff --git a/test/run-drun/ok/idl-func.drun-run.ok b/test/run-drun/ok/idl-func.drun-run.ok index a28d738f46e..7d1023f7a17 100644 --- a/test/run-drun/ok/idl-func.drun-run.ok +++ b/test/run-drun/ok/idl-func.drun-run.ok @@ -1,4 +1,4 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System Ok: Payload: 0x4449444c026e016a017c010100010000 Ok: Payload: 0x4449444c0000 Ok: Payload: 0x4449444c036a00010101016e026a017c01020001000101022a010366756e diff --git a/test/run-drun/ok/idl-nary.drun-run.ok b/test/run-drun/ok/idl-nary.drun-run.ok index cb895549b50..9fd72d9d6c3 100644 --- a/test/run-drun/ok/idl-nary.drun-run.ok +++ b/test/run-drun/ok/idl-nary.drun-run.ok @@ -1,4 +1,4 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System Ok: Payload: 0x4449444c00027171034f6e650354776f Ok: Payload: 0x4449444c0003717171034f6e650354776f055468726565 Ok: Payload: 0x4449444c000471717171034f6e650354776f05546872656504466f7572 diff --git a/test/run-drun/ok/idl-nat-int.drun-run.ok b/test/run-drun/ok/idl-nat-int.drun-run.ok index a60e7eb074e..a95454f107e 100644 --- a/test/run-drun/ok/idl-nat-int.drun-run.ok +++ b/test/run-drun/ok/idl-nat-int.drun-run.ok @@ -1,4 +1,4 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System Ok: Payload: 0x4449444c00017d2a Ok: Payload: 0x4449444c00017d2a Ok: Payload: 0x4449444c016d7d0100022a19 diff --git a/test/run-drun/ok/idl-option.drun-run.ok b/test/run-drun/ok/idl-option.drun-run.ok index a2f7e845525..e8159a31a1b 100644 --- a/test/run-drun/ok/idl-option.drun-run.ok +++ b/test/run-drun/ok/idl-option.drun-run.ok @@ -1,4 +1,4 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System debug.print: ok: null Ok: Payload: 0x4449444c0000 debug.print: ok: null diff --git a/test/run-drun/ok/idl-pair.drun-run.ok b/test/run-drun/ok/idl-pair.drun-run.ok index 45b1fbf60f1..8babfbcec74 100644 --- a/test/run-drun/ok/idl-pair.drun-run.ok +++ b/test/run-drun/ok/idl-pair.drun-run.ok @@ -1,2 +1,2 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System Ok: Payload: 0x4449444c016c02007c017c01000205 diff --git a/test/run-drun/ok/idl-record.drun-run.ok b/test/run-drun/ok/idl-record.drun-run.ok index 9f739e13fd6..13efbc5f8d5 100644 --- a/test/run-drun/ok/idl-record.drun-run.ok +++ b/test/run-drun/ok/idl-record.drun-run.ok @@ -1,4 +1,4 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System debug.print: ok: +42 Ok: Payload: 0x4449444c0000 debug.print: ok: Hey! diff --git a/test/run-drun/ok/idl-shorthand.drun-run.ok b/test/run-drun/ok/idl-shorthand.drun-run.ok index 1d9bff524d5..b7ccb1590b3 100644 --- a/test/run-drun/ok/idl-shorthand.drun-run.ok +++ b/test/run-drun/ok/idl-shorthand.drun-run.ok @@ -1,2 +1,2 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System Ok: Payload: 0x4449444c016b01d1a7cf027f010000 diff --git a/test/run-drun/ok/idl-tuple.drun-run.ok b/test/run-drun/ok/idl-tuple.drun-run.ok index 92c7ad8dd6d..96080634e45 100644 --- a/test/run-drun/ok/idl-tuple.drun-run.ok +++ b/test/run-drun/ok/idl-tuple.drun-run.ok @@ -1,4 +1,4 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System Ok: Payload: 0x4449444c00027c7c0205 Ok: Payload: 0x4449444c00037c7c7c050581848c20 Ok: Payload: 0x4449444c00037c7c7c050581848c20 diff --git a/test/run-drun/ok/idl-unit.drun-run.ok b/test/run-drun/ok/idl-unit.drun-run.ok index 40815a20950..a387d7d2ef7 100644 --- a/test/run-drun/ok/idl-unit.drun-run.ok +++ b/test/run-drun/ok/idl-unit.drun-run.ok @@ -1,2 +1,2 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System Ok: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-variant.drun-run.ok b/test/run-drun/ok/idl-variant.drun-run.ok index 0f64928bc47..66407ef58fe 100644 --- a/test/run-drun/ok/idl-variant.drun-run.ok +++ b/test/run-drun/ok/idl-variant.drun-run.ok @@ -1,2 +1,2 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System Ok: Payload: 0x4449444c016b03d583b702008790c0bd0479dc9790cb0e790100000120000000 diff --git a/test/run-drun/ok/idl-vector.drun-run.ok b/test/run-drun/ok/idl-vector.drun-run.ok index e663c8d4392..5c7deb99dda 100644 --- a/test/run-drun/ok/idl-vector.drun-run.ok +++ b/test/run-drun/ok/idl-vector.drun-run.ok @@ -1,2 +1,2 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System Ok: Payload: 0x4449444c026e016d0001000103010001040100010201000100010001000100 diff --git a/test/run-drun/ok/large-array.drun-run.ok b/test/run-drun/ok/large-array.drun-run.ok index 170cfc47522..4b5ab67c7f4 100644 --- a/test/run-drun/ok/large-array.drun-run.ok +++ b/test/run-drun/ok/large-array.drun-run.ok @@ -1,2 +1,2 @@ debug.print: done -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System diff --git a/test/run-drun/ok/local-throw.drun-run.ok b/test/run-drun/ok/local-throw.drun-run.ok index 3b9d76c320a..b498e8d296a 100644 --- a/test/run-drun/ok/local-throw.drun-run.ok +++ b/test/run-drun/ok/local-throw.drun-run.ok @@ -1,4 +1,4 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System debug.print: t2 ok debug.print: t3 ok -ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/log-slow.drun-run.ok b/test/run-drun/ok/log-slow.drun-run.ok index 28f361d9907..5d7495cc8a5 100644 --- a/test/run-drun/ok/log-slow.drun-run.ok +++ b/test/run-drun/ok/log-slow.drun-run.ok @@ -1 +1 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System diff --git a/test/run-drun/ok/mod-rebind.drun-run.ok b/test/run-drun/ok/mod-rebind.drun-run.ok index 28f361d9907..5d7495cc8a5 100644 --- a/test/run-drun/ok/mod-rebind.drun-run.ok +++ b/test/run-drun/ok/mod-rebind.drun-run.ok @@ -1 +1 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System diff --git a/test/run-drun/ok/oneway-throw.drun-run.ok b/test/run-drun/ok/oneway-throw.drun-run.ok index c4fb20b0e26..4c77e3ee6c6 100644 --- a/test/run-drun/ok/oneway-throw.drun-run.ok +++ b/test/run-drun/ok/oneway-throw.drun-run.ok @@ -1,6 +1,6 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System debug.print: go1 debug.print: throws() debug.print: ping() debug.print: go2 -ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/oneway.drun-run.ok b/test/run-drun/ok/oneway.drun-run.ok index 408cea050e3..f0c131491ab 100644 --- a/test/run-drun/ok/oneway.drun-run.ok +++ b/test/run-drun/ok/oneway.drun-run.ok @@ -1,4 +1,4 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System debug.print: A debug.print: B debug.print: C @@ -10,4 +10,4 @@ debug.print: 3 debug.print: 4 debug.print: 5 debug.print: 6 -ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/oom.drun-run.ok b/test/run-drun/ok/oom.drun-run.ok index c4dfadc376a..7bb2fd1d7eb 100644 --- a/test/run-drun/ok/oom.drun-run.ok +++ b/test/run-drun/ok/oom.drun-run.ok @@ -1,3 +1,3 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System -ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 -ingress(0x0200000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 +ingress System +ingress Completed: Canister: Payload: 0x4449444c0000 +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/print-from-init.drun-run.ok b/test/run-drun/ok/print-from-init.drun-run.ok index f44c94649cc..9dad15d9552 100644 --- a/test/run-drun/ok/print-from-init.drun-run.ok +++ b/test/run-drun/ok/print-from-init.drun-run.ok @@ -1,2 +1,2 @@ debug.print: Debug out -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System diff --git a/test/run-drun/ok/query.drun-run.ok b/test/run-drun/ok/query.drun-run.ok index 488ed07d831..c953352c309 100644 --- a/test/run-drun/ok/query.drun-run.ok +++ b/test/run-drun/ok/query.drun-run.ok @@ -1,18 +1,18 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System debug.print: 2 -ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 +ingress Completed: Canister: Payload: 0x4449444c0000 debug.print: 3 -ingress(0x0200000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 +ingress Completed: Canister: Payload: 0x4449444c0000 debug.print: 4 -ingress(0x0300000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 +ingress Completed: Canister: Payload: 0x4449444c0000 debug.print: 4 -ingress(0x0400000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 -ingress(0x0500000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c00017d04 +ingress Completed: Canister: Payload: 0x4449444c0000 +ingress Completed: Canister: Payload: 0x4449444c00017d04 debug.print: 5 Ok: Payload: 0x4449444c00017d04 debug.print: 4 -ingress(0x0700000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 +ingress Completed: Canister: Payload: 0x4449444c0000 debug.print: 5 Ok: Payload: 0x4449444c00017d04 debug.print: 4 -ingress(0x0900000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/query2.drun-run.ok b/test/run-drun/ok/query2.drun-run.ok index cd27ad478b5..4629047e37c 100644 --- a/test/run-drun/ok/query2.drun-run.ok +++ b/test/run-drun/ok/query2.drun-run.ok @@ -1,4 +1,4 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System debug.print: 2 debug.print: 3 debug.print: 4 @@ -10,4 +10,4 @@ debug.print: In read: debug.print: 5 debug.print: The following fails in the interpreter, for lack of query semantics debug.print: 4 -ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/reject.drun-run.ok b/test/run-drun/ok/reject.drun-run.ok index c1b99684fc1..d871bd8f1f6 100644 --- a/test/run-drun/ok/reject.drun-run.ok +++ b/test/run-drun/ok/reject.drun-run.ok @@ -1,9 +1,9 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System debug.print: 1 -ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Reject: Error +ingress Completed: Canister: Reject: Error debug.print: 1 debug.print: ok -ingress(0x0200000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 +ingress Completed: Canister: Payload: 0x4449444c0000 debug.print: 1 debug.print: ok -ingress(0x0300000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Reject: Error +ingress Completed: Canister: Reject: Error diff --git a/test/run-drun/ok/rts-stats.drun-run.ok b/test/run-drun/ok/rts-stats.drun-run.ok index c684eaf8299..278895ef95a 100644 --- a/test/run-drun/ok/rts-stats.drun-run.ok +++ b/test/run-drun/ok/rts-stats.drun-run.ok @@ -1,2 +1,2 @@ debug.print: Size and allocation delta: (10_008, 10_008) -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System diff --git a/test/run-drun/ok/selftail.drun-run.ok b/test/run-drun/ok/selftail.drun-run.ok index 10f7e4714f4..2679e7b9ca1 100644 --- a/test/run-drun/ok/selftail.drun-run.ok +++ b/test/run-drun/ok/selftail.drun-run.ok @@ -1,3 +1,3 @@ debug.print: ok1 debug.print: ok2 -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) Err: IC0502: Canister ic:2A012B trapped: stack overflow +ingress Err: IC0502: Canister ic:2A012B trapped: stack overflow diff --git a/test/run-drun/ok/shared-object.drun-run.ok b/test/run-drun/ok/shared-object.drun-run.ok index c30c2566df1..adce7c8af5f 100644 --- a/test/run-drun/ok/shared-object.drun-run.ok +++ b/test/run-drun/ok/shared-object.drun-run.ok @@ -1,2 +1,2 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System -ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 +ingress System +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/sharingbug.drun-run.ok b/test/run-drun/ok/sharingbug.drun-run.ok index 28f361d9907..5d7495cc8a5 100644 --- a/test/run-drun/ok/sharingbug.drun-run.ok +++ b/test/run-drun/ok/sharingbug.drun-run.ok @@ -1 +1 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System diff --git a/test/run-drun/ok/show.drun-run.ok b/test/run-drun/ok/show.drun-run.ok index f8b97731dfd..44a9f0d3226 100644 --- a/test/run-drun/ok/show.drun-run.ok +++ b/test/run-drun/ok/show.drun-run.ok @@ -33,4 +33,4 @@ debug.print: 0x2A debug.print: 42 debug.print: +42 debug.print: -42 -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System diff --git a/test/run-drun/ok/tailpositions.drun-run.ok b/test/run-drun/ok/tailpositions.drun-run.ok index 6c2db2d2d4b..24d869aba7e 100644 --- a/test/run-drun/ok/tailpositions.drun-run.ok +++ b/test/run-drun/ok/tailpositions.drun-run.ok @@ -5,4 +5,4 @@ debug.print: done 4 debug.print: done 5 debug.print: done 6 debug.print: done 7 -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System diff --git a/test/run-drun/ok/text-iter.drun-run.ok b/test/run-drun/ok/text-iter.drun-run.ok index 68b1eb0d074..de7f3032f81 100644 --- a/test/run-drun/ok/text-iter.drun-run.ok +++ b/test/run-drun/ok/text-iter.drun-run.ok @@ -227,4 +227,4 @@ debug.print: П debug.print: debug.print: 🙈 debug.print: -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System diff --git a/test/run-drun/ok/transpose.drun-run.ok b/test/run-drun/ok/transpose.drun-run.ok index 3b545d87868..131db0a3a92 100644 --- a/test/run-drun/ok/transpose.drun-run.ok +++ b/test/run-drun/ok/transpose.drun-run.ok @@ -1,3 +1,3 @@ -ingress(0x0000000000000000000000000000000000000000000000000000000000000000) System +ingress System debug.print: All good -ingress(0x0100000000000000000000000000000000000000000000000000000000000000) Completed: Canister: Payload: 0x4449444c0000 +ingress Completed: Canister: Payload: 0x4449444c0000 From b4fd84203bd0d2d3ea25e1f0d4a3107b28caaaba Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Sat, 25 Jan 2020 15:49:51 +0100 Subject: [PATCH 1001/1176] Apply suggestions from code review Co-Authored-By: Gabor Greif --- src/codegen/compile.ml | 2 +- test/run/const-func-static.mo | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 961ba951f7d..c4596ab4d35 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -1240,7 +1240,7 @@ module Closure = struct FakeMultiVal.load env (Lib.List.make n_res I32Type) let static_closure env fi : int32 = - let tag = bytes_of_int32 (Tagged.int_of_tag Tagged.Closure) in + let tag = bytes_of_int32 Tagged.(int_of_tag Closure) in let len = bytes_of_int32 (E.add_fun_ptr env fi) in let zero = bytes_of_int32 0l in let data = tag ^ len ^ zero in diff --git a/test/run/const-func-static.mo b/test/run/const-func-static.mo index 144702e196d..473afcdeebb 100644 --- a/test/run/const-func-static.mo +++ b/test/run/const-func-static.mo @@ -1,7 +1,7 @@ import Prim "mo:prim"; let before = Prim.rts_heap_size(); -func higher_order(foo: () -> () ) = foo(); +func higher_order(foo: () -> ()) = foo(); func bar() = (); higher_order(bar); let after = Prim.rts_heap_size(); From e9997d6c3ad8139042adc56c6ed2c427d91284da Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Sat, 25 Jan 2020 16:43:41 +0100 Subject: [PATCH 1002/1176] GC: Only traverse mutable static heap objects (#1139) * GC: Only traverse mutable static heap objects previously, the GC would scan the whole static heap for roots. This is wasteful, as it includes immutable static objects (e.g. strings) that cannot contain static roots. With this change, the RTS emits, to static memory, an array of roots with all mutable elements in the static memory, and traverses only these. The provided test case breaks if we forget to add the mutable variable there to the list (but of course there is a risk of hard-to-debug bugs if in the future we add something there). Can be sped up further by a version of `Array.idx` that does not do bounds checking, which can be used in other places as well. * Add test case * Update test/run-drun/static-gc.mo * Update test output --- src/codegen/compile.ml | 57 +++++++++++++++++------ test/run-drun/ok/static-gc.drun-run.ok | 3 ++ test/run-drun/ok/static-gc.ic-stub-run.ok | 8 ++++ test/run-drun/static-gc.mo | 26 +++++++++++ 4 files changed, 81 insertions(+), 13 deletions(-) create mode 100644 test/run-drun/ok/static-gc.drun-run.ok create mode 100644 test/run-drun/ok/static-gc.ic-stub-run.ok create mode 100644 test/run-drun/static-gc.mo diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index b7a49a8cff1..b3ccb734899 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -175,6 +175,8 @@ module E = struct static_memory : (int32 * string) list ref; (* Content of static memory *) static_memory_frozen : bool ref; (* Sanity check: Nothing should bump end_of_static_memory once it has been read *) + static_roots : int32 list ref; + (* GC roots in static memory. (Everything that may be mutable.) *) (* Local fields (only valid/used inside a function) *) (* Static *) @@ -208,6 +210,7 @@ module E = struct end_of_static_memory = ref dyn_mem; static_memory = ref []; static_memory_frozen = ref false; + static_roots = ref []; (* Actually unused outside mk_fun_env: *) n_param = 0l; return_arity = 0; @@ -401,6 +404,12 @@ module E = struct env.static_memory_frozen := true; !(env.end_of_static_memory) + let add_static_root (env : t) ptr = + env.static_roots := ptr :: !(env.static_roots) + + let get_static_roots (env : t) = + !(env.static_roots) + let get_static_memory env = !(env.static_memory) @@ -3135,6 +3144,17 @@ module HeapTraversal = struct set_x ) + let for_each_array_elem env get_array mk_code = + get_array ^^ + Heap.load_field Arr.len_field ^^ + from_0_to_n env (fun get_i -> + mk_code ( + get_array ^^ + get_i ^^ + Arr.idx env + ) + ) + (* Calls mk_code for each pointer in the object pointed to by get_x, passing code get the address of the pointer, and code to get the offset of the pointer (for the BigInt payload field). *) @@ -3170,13 +3190,8 @@ module HeapTraversal = struct set_ptr_loc ^^ code ; Tagged.Array, - get_x ^^ - Heap.load_field Arr.len_field ^^ - (* Adjust fields *) - from_0_to_n env (fun get_i -> - get_x ^^ - get_i ^^ - Arr.idx env ^^ + for_each_array_elem env get_x (fun get_elem_ptr -> + get_elem_ptr ^^ set_ptr_loc ^^ code ) @@ -4223,7 +4238,7 @@ module GC = struct get_begin_from_space get_begin_to_space get_end_to_space ) - let register env (end_of_static_space : int32) = + let register env static_roots (end_of_static_space : int32) = Func.define_built_in env "get_heap_size" [] [I32Type] (fun env -> Heap.get_heap_ptr env ^^ Heap.get_heap_base env ^^ @@ -4261,11 +4276,12 @@ module GC = struct set_end_to_space in (* Go through the roots, and evacuate them *) + HeapTraversal.for_each_array_elem env (compile_unboxed_const static_roots) (fun get_elem_ptr -> + let (set_static, get_static) = new_local env "static_obj" in + get_elem_ptr ^^ load_ptr ^^ set_static ^^ + HeapTraversal.for_each_pointer env get_static evac evac_offset + ) ^^ evac (ClosureTable.root env) ^^ - HeapTraversal.walk_heap_from_to env - (compile_unboxed_const Int32.(add Stack.end_of_stack ptr_skew)) - (compile_unboxed_const Int32.(add end_of_static_space ptr_skew)) - (fun get_x -> HeapTraversal.for_each_pointer env get_x evac evac_offset) ^^ (* Go through the to-space, and evacuate that. Note that get_end_to_space changes as we go, but walk_heap_from_to can handle that. @@ -4291,6 +4307,17 @@ module GC = struct let get_heap_size env = G.i (Call (nr (E.built_in env "get_heap_size"))) + let store_static_roots env = + let roots = E.get_static_roots env in + + let tag = bytes_of_int32 (Tagged.int_of_tag Tagged.Array) in + let len = bytes_of_int32 (Int32.of_int (List.length roots)) in + let payload = String.concat "" (List.map bytes_of_int32 roots) in + let data = tag ^ len ^ payload in + let ptr = E.add_static_bytes env data in + ptr + + end (* GC *) module StackRep = struct @@ -5146,6 +5173,7 @@ module AllocHow = struct let tag = bytes_of_int32 (Tagged.int_of_tag Tagged.MutBox) in let zero = bytes_of_int32 0l in let ptr = E.add_mutable_static_bytes env (tag ^ zero) in + E.add_static_root env ptr; let ae1 = VarEnv.add_local_heap_static ae name ptr in (ae1, G.nop) @@ -6844,6 +6872,8 @@ and conclude_module env start_fi_o = FuncDec.export_async_method env; + let static_roots = GC.store_static_roots env in + (* add beginning-of-heap pointer, may be changed by linker *) (* needs to happen here now that we know the size of static memory *) E.add_global32 env "__heap_base" Immutable (E.get_end_of_static_memory env); @@ -6858,7 +6888,8 @@ and conclude_module env start_fi_o = )) in Dfinity.default_exports env; - GC.register env (E.get_end_of_static_memory env); + + GC.register env static_roots (E.get_end_of_static_memory env); let func_imports = E.get_func_imports env in let ni = List.length func_imports in diff --git a/test/run-drun/ok/static-gc.drun-run.ok b/test/run-drun/ok/static-gc.drun-run.ok new file mode 100644 index 00000000000..7bb2fd1d7eb --- /dev/null +++ b/test/run-drun/ok/static-gc.drun-run.ok @@ -0,0 +1,3 @@ +ingress System +ingress Completed: Canister: Payload: 0x4449444c0000 +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/static-gc.ic-stub-run.ok b/test/run-drun/ok/static-gc.ic-stub-run.ok new file mode 100644 index 00000000000..53f26d861ca --- /dev/null +++ b/test/run-drun/ok/static-gc.ic-stub-run.ok @@ -0,0 +1,8 @@ +→ create +← completed: canister-id = 0x2a01 +→ install +← completed +→ update foo1(0x4449444c0000) +← completed: 0x4449444c0000 +→ update foo2(0x4449444c0000) +← completed: 0x4449444c0000 diff --git a/test/run-drun/static-gc.mo b/test/run-drun/static-gc.mo new file mode 100644 index 00000000000..02ba8a592ca --- /dev/null +++ b/test/run-drun/static-gc.mo @@ -0,0 +1,26 @@ +// Tests that GC properly looks through mutable things in global memory +// (This uses messages to trigger GC. If we don’t run GC after message, other ways need to be found.) + +actor a { + var x = ("Foo", "Bar"); + + public func foo1() { + ignore [1,2,3,4,5]; + x := ("abc", "def"); + ignore [1,2,3,4,5]; + + }; + public func foo2() { + ignore [1,2,3,4,5,6,7,8,9]; + assert (x.0 == "abc"); + assert (x.1 == "def"); + } + +} +//CALL ingress foo1 0x4449444C0000 +//CALL ingress foo2 0x4449444C0000 + + +// SKIP run +// SKIP run-ir +// SKIP run-low From 437e6ec311def11ed8b675918430d28f2ab4b19a Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Sat, 25 Jan 2020 17:02:37 +0100 Subject: [PATCH 1003/1176] Try reducing the drun extra batches (#1159) * Try reducing the drun extra batches in hope of reducing the test run time on macOS * reduce the required rounds for actor self-send tests These have run reliably for some time, so I am confident they are fine. Reduces the running time for Darwin CI significantly. --- test/random/Embedder.hs | 2 +- test/random/Main.hs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/random/Embedder.hs b/test/random/Embedder.hs index 9b615288711..0107f4fa41e 100644 --- a/test/random/Embedder.hs +++ b/test/random/Embedder.hs @@ -29,7 +29,7 @@ addCompilerArgs Drun = id addEmbedderArgs Reference = id addEmbedderArgs (WasmTime _) = ("--disable-cache" :) . ("--cranelift" :) -addEmbedderArgs Drun = ("--extra-batches" :) . ("100" :) +addEmbedderArgs Drun = ("--extra-batches" :) . ("10" :) invokeEmbedder :: Embedder -> Turtle.FilePath -> IO (ExitCode, Text, Text) invokeEmbedder embedder wasm = go embedder diff --git a/test/random/Main.hs b/test/random/Main.hs index fb9a6020877..b3937528b1f 100644 --- a/test/random/Main.hs +++ b/test/random/Main.hs @@ -60,9 +60,9 @@ utf8Props = testGroup "UTF-8 coding" matchingProps = testGroup "Pattern matching" [ QC.testProperty "intra-actor" $ prop_matchStructured - , QC.testProperty "inter-actor" $ prop_matchInActor - , QC.testProperty "encoded-Nat" $ prop_matchActorNat - , QC.testProperty "encoded-Int" $ prop_matchActorInt + , QC.testProperty "inter-actor" $ withMaxSuccess 20 prop_matchInActor + , QC.testProperty "encoded-Nat" $ withMaxSuccess 10 prop_matchActorNat + , QC.testProperty "encoded-Int" $ withMaxSuccess 10 prop_matchActorInt ] From 6c46355d7c45e19fe4a73c07d006b7e68ecb6511 Mon Sep 17 00:00:00 2001 From: chenyan-dfinity <48968912+chenyan-dfinity@users.noreply.github.com> Date: Sat, 25 Jan 2020 14:15:58 -0800 Subject: [PATCH 1004/1176] update DFX-Interface (#1148) * update DFX-Interface --- design/DFX-Interface.md | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/design/DFX-Interface.md b/design/DFX-Interface.md index b139adf11b0..5a974df4c03 100644 --- a/design/DFX-Interface.md +++ b/design/DFX-Interface.md @@ -69,11 +69,15 @@ No constraints are imposed where imported files reside (this may be refined to p This _writes_ to `another/path/output.wasm`, but has no other effect. It does not create `another/path/`. +Compiler warnings and errors are reported to `stderr`. Nothing writes to `stdout`. + Compiling Motoko Files to IDL ----------------------------- As the previous point, but passing `--idl` to `moc`. +The IDL generation does not issue any warnings. + Resolving Canister aliases -------------------------- @@ -95,6 +99,8 @@ The `canisterid` here refers the “textual representation“ without the `ic:` This files informs motoko about the interface of that canister. It could be the output of `moc --idl` for a locally known canister, or the IDL file as fetched from the Internet Computer, or created any other way. +Open problem: how to resolve mutual canister imports. + Compiling IDL Files to JS ------------------------- @@ -110,6 +116,8 @@ No constraints are imposed where these imported files reside (this may be refine This _writes_ to `another/path/output.js`, but has no other effect. It does not create `another/path/`. +Compiler warnings and errors are reported to `stderr`. Nothing writes to `stdout`. + Invoking the IDE ---------------- @@ -131,18 +139,17 @@ The command moc --print-deps some/path/input.mo -prints to the standard output all URLs _directly_ imported by -`some/path/input.mo`, one per line, e.g. +prints to the standard output all URLs _transitively_ imported by +`some/path/input.mo`, one per line. Each line outputs the original +URL, and optionally a full path if `moc` can resolve the URL, separated by a space. +For example, - mo:stdlib/List - mo:other_package/Some/Module - ic:ABCDE01A7 - ic:alias - relative/path + mo:stdlib/List + mo:other_package/Some/Module + ic:ABCDE01A7 + canister:alias + ./local_import some/path/local_import.mo + ./runtime some/path/runtime.wasm -This _reads_ only `some/path/input.mo`, and writes no files. +This may _read_ the same files as `moc -c` would, and writes no files. -By transitively exploring the dependency graph using this command (and -resolving URLs appropriately before passing them as files to `moc`), one can -determine the full set of set of `.mo` files read by the two compilation modes -described above (to wasm and to IDL). From 100a9c8a0d3703b17115385af68fab0aa6514322 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 27 Jan 2020 11:50:37 +0100 Subject: [PATCH 1005/1176] Add test/compare-perf.sh script (#1160) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit to quickly compare arbitrary revisions (in particular do double check in case hydra gets the base revision wrong.) Same “ui” as ./compare-wat.sh --- test/.gitignore | 2 ++ test/compare-perf.sh | 52 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100755 test/compare-perf.sh diff --git a/test/.gitignore b/test/.gitignore index 6b38fe97b53..271b908f477 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -3,6 +3,8 @@ _out new-moc old-moc compare-out +new-perf +old-perf coverage _coverage diff --git a/test/compare-perf.sh b/test/compare-perf.sh new file mode 100755 index 00000000000..256431c8b8f --- /dev/null +++ b/test/compare-perf.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash + +# This script compares the perf +# between the currently built version and the previous version +# +# With -f from -t to other branches can be selected (anything that git +# rev-parse understands) + +old="$(git rev-parse HEAD)" +new="" + +while getopts "f:t:" o; do + case "${o}" in + f) + old="$(git rev-parse ${OPTARG})" + ;; + t) + new="$(git rev-parse ${OPTARG})" + ;; + esac +done +shift $((OPTIND-1)) + +function build_ref_to { + rm -f $2-moc + if [ -z "$1" ] + then + echo "Building $2 moc from working copy.." + chronic nix-build -E '((import ./..) {}).tests.perf' \ + --option binary-caches '' \ + -o $2-perf + else + echo "Building $2 moc (rev $1).." + chronic nix-build \ + --argstr ref "$(git for-each-ref --count 1 --contains "$1" --format '%(refname)')" \ + --argstr rev "$1" \ + --argstr path "$(realpath "$(dirname $0)/..")" \ + -E ' + {rev, ref, path}: + let nixpkg = import ../nix {}; in + let checkout = (builtins.fetchGit {url = path; ref = ref; rev = rev; name = "old-moc";}).outPath; in + builtins.trace checkout ( + ((import checkout) {}).tests.perf)' \ + --option binary-caches '' \ + -o $2-perf + fi + test -e $2-perf || exit 1 +} +build_ref_to "$old" old +build_ref_to "$new" new + +$(dirname $0)/diff-stats.pl old-perf new-perf From 398079accc2e982e511c30c0869953594fb0fe96 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Mon, 27 Jan 2020 12:16:53 +0100 Subject: [PATCH 1006/1176] Avoid clang warning (#1161) fixes ``` bigint.c:274:36: warning: '&&' within '||' [-Wlogical-op-parentheses] if (!mp_iszero(tmp) || add_bit && (buf[0] & 1<<6)) { ~~ ~~~~~~~~^~~~~~~~~~~~~~~~~~ bigint.c:274:36: note: place parentheses around the '&&' expression to silence this warning if (!mp_iszero(tmp) || add_bit && (buf[0] & 1<<6)) { ^ ( ) 1 warning generated. ``` --- rts/bigint.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rts/bigint.c b/rts/bigint.c index 7d1f6ff9b47..55879b8f0b8 100644 --- a/rts/bigint.c +++ b/rts/bigint.c @@ -271,7 +271,7 @@ void bigint_leb128_encode_go(mp_int *tmp, unsigned char *buf, bool add_bit) { while (true) { buf[0] = (unsigned char)(mp_get_u32(tmp)); // get low bits CHECK(mp_div_2d(tmp, 7, tmp, NULL)); - if (!mp_iszero(tmp) || add_bit && (buf[0] & 1<<6)) { + if (!mp_iszero(tmp) || (add_bit && (buf[0] & 1<<6))) { // more bytes to come, set high bit and continue buf[0] |= 1<<7; buf++; From ad26233ab9fdc92b13ec3f3013b54cda256b7956 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Mon, 27 Jan 2020 15:47:44 +0000 Subject: [PATCH 1007/1176] Enable full async/await on IC target (Requires PR #1056) (#1142) * enable general await in ICMode * update drun-run test output; manually verified againd ic-stub-run output * update test output * updated unsupported.mo and andded unsupported-more.mo * update test output after merge * update test output after merge * remove oneway ingore async hack and update test output for scheduling changes * missing file * Revert "remove oneway ingore async hack and update test output for scheduling changes" This reverts commit 24804bacfb52163193ff19848e9a66ed497f9321. * Revert "missing file" This reverts commit a929d3e89b39d689a57bbe4dca99d4d43bc548aa. --- src/mo_frontend/typing.ml | 41 ----------------- test/run-drun/general_await.mo | 3 -- test/run-drun/general_await_implicit.mo | 2 - test/run-drun/ok/AST-66.comp.ok | 4 -- test/run-drun/ok/AST-66.drun-run.ok | 2 + test/run-drun/ok/aritybug.comp.ok | 3 +- test/run-drun/ok/async-any.comp.ok | 2 - test/run-drun/ok/async-any.drun-run.ok | 2 + test/run-drun/ok/async-free-var.comp.ok | 2 - test/run-drun/ok/async-free-var.drun-run.ok | 9 ++++ test/run-drun/ok/async-loop-while.comp.ok | 6 --- test/run-drun/ok/async-loop-while.drun-run.ok | 14 ++++++ test/run-drun/ok/async-loop.comp.ok | 6 --- test/run-drun/ok/async-loop.comp.ret.ok | 1 - test/run-drun/ok/async-loop.drun-run.ok | 1 + test/run-drun/ok/async-new-obj.comp.ok | 2 - test/run-drun/ok/async-new-obj.comp.ret.ok | 1 - test/run-drun/ok/async-new-obj.drun-run.ok | 7 +++ test/run-drun/ok/async-obj-mut.comp.ok | 2 - test/run-drun/ok/async-obj-mut.comp.ret.ok | 1 - test/run-drun/ok/async-obj-mut.drun-run.ok | 10 ++++ test/run-drun/ok/async-while.comp.ok | 6 --- test/run-drun/ok/async-while.comp.ret.ok | 1 - test/run-drun/ok/async-while.drun-run.ok | 14 ++++++ test/run-drun/ok/await.comp.ok | 2 - test/run-drun/ok/await.comp.ret.ok | 1 - test/run-drun/ok/await.drun-run.ok | 29 ++++++++++++ test/run-drun/ok/block.comp.ok | 2 - test/run-drun/ok/block.comp.ret.ok | 1 - test/run-drun/ok/block.drun-run.ok | 12 +++++ test/run-drun/ok/count-callbacks.comp.ok | 16 ------- test/run-drun/ok/count-callbacks.comp.ret.ok | 1 - test/run-drun/ok/count-callbacks.drun-run.ok | 15 ++++++ test/run-drun/ok/for-await.comp.ok | 2 - test/run-drun/ok/for-await.comp.ret.ok | 1 - test/run-drun/ok/for-await.drun-run.ok | 13 ++++++ test/run-drun/ok/general_await.drun-run.ok | 46 +++++++++++++++++++ .../ok/general_await_implicit.drun-run.ok | 46 +++++++++++++++++++ test/run-drun/ok/interleave.comp.ok | 2 - test/run-drun/ok/interleave.comp.ret.ok | 1 - test/run-drun/ok/interleave.drun-run.ok | 21 +++++++++ test/run-drun/ok/issue-894.comp.ok | 6 --- test/run-drun/ok/issue-894.comp.ret.ok | 1 - test/run-drun/ok/issue-894.drun-run.ok | 11 +++++ test/run-drun/ok/nary-async.comp.ok | 16 ------- test/run-drun/ok/nary-async.comp.ret.ok | 1 - test/run-drun/ok/nary-async.drun-run.ok | 11 +++++ test/run-drun/ok/overflow.comp.ok | 12 ----- test/run-drun/ok/overflow.comp.ret.ok | 1 - test/run-drun/ok/overflow.drun-run.ok | 7 +++ test/run-drun/ok/shared-match.diff-ir.ok | 7 +++ test/run-drun/ok/shared-match.diff-low.ok | 7 +++ test/run-drun/ok/shared-match.drun-run.ok | 5 ++ test/run-drun/ok/shared-match.ic-stub-run.ok | 10 ++++ test/run-drun/ok/shared-match.run-ir.ok | 3 ++ test/run-drun/ok/shared-match.run-low.ok | 3 ++ test/run-drun/ok/shared-match.run.ok | 3 ++ test/run-drun/ok/shared-match.tc.ok | 4 ++ test/run-drun/ok/throw.comp.ok | 4 -- test/run-drun/ok/throw.comp.ret.ok | 1 - test/run-drun/ok/throw.drun-run.ok | 4 ++ test/run-drun/ok/type-lub.comp.ok | 2 - test/run-drun/ok/type-lub.comp.ret.ok | 1 - test/run-drun/ok/type-lub.drun-run.ok | 2 + .../run-drun/ok/unsupported-more.comp-stub.ok | 2 + ...t.ok => unsupported-more.comp-stub.ret.ok} | 0 test/run-drun/ok/unsupported-more.comp.ok | 2 + ...mp.ret.ok => unsupported-more.comp.ret.ok} | 0 test/run-drun/ok/unsupported.comp-stub.ok | 16 +++++++ ...mp.ret.ok => unsupported.comp-stub.ret.ok} | 0 test/run-drun/ok/unsupported.comp.ok | 16 +++++++ ...le.comp.ret.ok => unsupported.comp.ret.ok} | 0 test/run-drun/ok/unsupported.tc.ok | 1 - test/run-drun/ok/unsupported.tc.ret.ok | 1 - test/run-drun/shared-match.mo | 20 ++++++++ test/run-drun/unsupported-more.mo | 9 ++++ test/run-drun/unsupported.mo | 46 +++++++------------ 77 files changed, 401 insertions(+), 187 deletions(-) delete mode 100644 test/run-drun/ok/AST-66.comp.ok create mode 100644 test/run-drun/ok/AST-66.drun-run.ok delete mode 100644 test/run-drun/ok/async-any.comp.ok create mode 100644 test/run-drun/ok/async-any.drun-run.ok delete mode 100644 test/run-drun/ok/async-free-var.comp.ok create mode 100644 test/run-drun/ok/async-free-var.drun-run.ok delete mode 100644 test/run-drun/ok/async-loop-while.comp.ok create mode 100644 test/run-drun/ok/async-loop-while.drun-run.ok delete mode 100644 test/run-drun/ok/async-loop.comp.ok delete mode 100644 test/run-drun/ok/async-loop.comp.ret.ok create mode 100644 test/run-drun/ok/async-loop.drun-run.ok delete mode 100644 test/run-drun/ok/async-new-obj.comp.ok delete mode 100644 test/run-drun/ok/async-new-obj.comp.ret.ok create mode 100644 test/run-drun/ok/async-new-obj.drun-run.ok delete mode 100644 test/run-drun/ok/async-obj-mut.comp.ok delete mode 100644 test/run-drun/ok/async-obj-mut.comp.ret.ok create mode 100644 test/run-drun/ok/async-obj-mut.drun-run.ok delete mode 100644 test/run-drun/ok/async-while.comp.ok delete mode 100644 test/run-drun/ok/async-while.comp.ret.ok create mode 100644 test/run-drun/ok/async-while.drun-run.ok delete mode 100644 test/run-drun/ok/await.comp.ok delete mode 100644 test/run-drun/ok/await.comp.ret.ok create mode 100644 test/run-drun/ok/await.drun-run.ok delete mode 100644 test/run-drun/ok/block.comp.ok delete mode 100644 test/run-drun/ok/block.comp.ret.ok create mode 100644 test/run-drun/ok/block.drun-run.ok delete mode 100644 test/run-drun/ok/count-callbacks.comp.ok delete mode 100644 test/run-drun/ok/count-callbacks.comp.ret.ok create mode 100644 test/run-drun/ok/count-callbacks.drun-run.ok delete mode 100644 test/run-drun/ok/for-await.comp.ok delete mode 100644 test/run-drun/ok/for-await.comp.ret.ok create mode 100644 test/run-drun/ok/for-await.drun-run.ok create mode 100644 test/run-drun/ok/general_await.drun-run.ok create mode 100644 test/run-drun/ok/general_await_implicit.drun-run.ok delete mode 100644 test/run-drun/ok/interleave.comp.ok delete mode 100644 test/run-drun/ok/interleave.comp.ret.ok create mode 100644 test/run-drun/ok/interleave.drun-run.ok delete mode 100644 test/run-drun/ok/issue-894.comp.ok delete mode 100644 test/run-drun/ok/issue-894.comp.ret.ok create mode 100644 test/run-drun/ok/issue-894.drun-run.ok delete mode 100644 test/run-drun/ok/nary-async.comp.ok delete mode 100644 test/run-drun/ok/nary-async.comp.ret.ok create mode 100644 test/run-drun/ok/nary-async.drun-run.ok delete mode 100644 test/run-drun/ok/overflow.comp.ok delete mode 100644 test/run-drun/ok/overflow.comp.ret.ok create mode 100644 test/run-drun/ok/overflow.drun-run.ok create mode 100644 test/run-drun/ok/shared-match.diff-ir.ok create mode 100644 test/run-drun/ok/shared-match.diff-low.ok create mode 100644 test/run-drun/ok/shared-match.drun-run.ok create mode 100644 test/run-drun/ok/shared-match.ic-stub-run.ok create mode 100644 test/run-drun/ok/shared-match.run-ir.ok create mode 100644 test/run-drun/ok/shared-match.run-low.ok create mode 100644 test/run-drun/ok/shared-match.run.ok create mode 100644 test/run-drun/ok/shared-match.tc.ok delete mode 100644 test/run-drun/ok/throw.comp.ok delete mode 100644 test/run-drun/ok/throw.comp.ret.ok create mode 100644 test/run-drun/ok/throw.drun-run.ok delete mode 100644 test/run-drun/ok/type-lub.comp.ok delete mode 100644 test/run-drun/ok/type-lub.comp.ret.ok create mode 100644 test/run-drun/ok/type-lub.drun-run.ok create mode 100644 test/run-drun/ok/unsupported-more.comp-stub.ok rename test/run-drun/ok/{AST-66.comp.ret.ok => unsupported-more.comp-stub.ret.ok} (100%) create mode 100644 test/run-drun/ok/unsupported-more.comp.ok rename test/run-drun/ok/{async-any.comp.ret.ok => unsupported-more.comp.ret.ok} (100%) create mode 100644 test/run-drun/ok/unsupported.comp-stub.ok rename test/run-drun/ok/{async-free-var.comp.ret.ok => unsupported.comp-stub.ret.ok} (100%) create mode 100644 test/run-drun/ok/unsupported.comp.ok rename test/run-drun/ok/{async-loop-while.comp.ret.ok => unsupported.comp.ret.ok} (100%) delete mode 100644 test/run-drun/ok/unsupported.tc.ok delete mode 100644 test/run-drun/ok/unsupported.tc.ret.ok create mode 100644 test/run-drun/shared-match.mo create mode 100644 test/run-drun/unsupported-more.mo diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index b4dd4a8edd3..2de84c4c310 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -131,35 +131,6 @@ let disjoint_union env at fmt env1 env2 = try T.Env.disjoint_union env1 env2 with T.Env.Clash k -> error env at fmt k - -(* Syntactic predicates for context dependent restrictions *) - -let in_await env = - match env.context with - | _ :: AwaitE _ :: _ -> true - | _ -> false - -let in_shared_async env = - match env.context with - | _ :: FuncE (_, {it = T.Shared _; _}, _, _, typ_opt, _) :: _ -> - (match typ_opt with - | Some {it = AsyncT _; _} -> true - | _ -> false) - | _ -> false - -let in_oneway_ignore env = - match env.context with - | _ :: - BlockE [ {it = IgnoreD _; _} ] :: - FuncE (_, {it = T.Shared _; _} , _, _, typ_opt, _) :: - _ -> - (match typ_opt with - | Some { it = TupT []; _} - | None -> true - | _ -> false) - | _ -> false - - (* Types *) let check_ids env kind member ids = Lib.List.iter_pairs @@ -870,9 +841,6 @@ and infer_exp'' env exp : T.typ = if not env.pre then begin check_exp env t_arg exp2; if Type.is_shared_sort sort then begin - if T.is_async t_ret && not (in_await env) then - error_in [Flags.ICMode] env exp2.at - "shared, async function must be called within an await expression"; if not (T.concrete t_arg) then error env exp1.at "shared function argument contains abstract type\n %s" @@ -1015,8 +983,6 @@ and infer_exp'' env exp : T.typ = if not env.pre then check_exp env T.throw exp1; T.Non | AsyncE (typ_bind, exp1) -> - if not (in_shared_async env || in_oneway_ignore env) then - error_in [Flags.ICMode] env exp.at "unsupported async block"; let t1, next_cap = check_AsyncCap env "async expression" exp.at in let c, tb, ce, cs = check_typ_bind env typ_bind in let ce_scope = T.Env.add T.default_scope_var c ce in (* pun scope var with c *) @@ -1031,11 +997,6 @@ and infer_exp'' env exp : T.typ = | AwaitE exp1 -> let t0 = check_AwaitCap env "await" exp.at in let t1 = infer_exp_promote env exp1 in - (match exp1.it with - | CallE (f, _, _) -> - if not env.pre && (Call_conv.call_conv_of_typ f.note.note_typ).Call_conv.control = T.Returns then - error_in [Flags.ICMode] env f.at "expecting call to shared async function in await"; - | _ -> error_in [Flags.ICMode] env exp1.at "argument to await must be a call expression"); (try let (t2, t3) = T.as_async_sub t0 t1 in if not (T.eq t0 t2) then @@ -1102,8 +1063,6 @@ and check_exp' env0 t exp : T.typ = List.iter (check_exp env (T.as_immut t')) exps; t | AsyncE (tb, exp1), T.Async (t1', t') -> - if not (in_shared_async env || in_oneway_ignore env) then - error_in [Flags.ICMode] env exp.at "freestanding async expression not yet supported"; let t1, next_cap = check_AsyncCap env "async expression" exp.at in if not (T.eq t1 t1') then error env exp.at "async at scope\n %s\ncannot produce expected scope\n %s" diff --git a/test/run-drun/general_await.mo b/test/run-drun/general_await.mo index a6ff3e822fc..e71b85ecee8 100644 --- a/test/run-drun/general_await.mo +++ b/test/run-drun/general_await.mo @@ -118,6 +118,3 @@ actor Await { }; Await.Test(); //OR-CALL ingress Test 0x4449444C0000 - - -//SKIP comp diff --git a/test/run-drun/general_await_implicit.mo b/test/run-drun/general_await_implicit.mo index 63fb871b22f..e5f39fc95dd 100644 --- a/test/run-drun/general_await_implicit.mo +++ b/test/run-drun/general_await_implicit.mo @@ -117,5 +117,3 @@ actor Await { }; Await.Test(); //OR-CALL ingress Test 0x4449444C0000 - -//SKIP comp diff --git a/test/run-drun/ok/AST-66.comp.ok b/test/run-drun/ok/AST-66.comp.ok deleted file mode 100644 index 648f0ea3cff..00000000000 --- a/test/run-drun/ok/AST-66.comp.ok +++ /dev/null @@ -1,4 +0,0 @@ -AST-66.mo:4.12-7.6: type error, unsupported async block - (This is a limitation of the current version.) -AST-66.mo:9.12-14.6: type error, unsupported async block - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/AST-66.drun-run.ok b/test/run-drun/ok/AST-66.drun-run.ok new file mode 100644 index 00000000000..adce7c8af5f --- /dev/null +++ b/test/run-drun/ok/AST-66.drun-run.ok @@ -0,0 +1,2 @@ +ingress System +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/aritybug.comp.ok b/test/run-drun/ok/aritybug.comp.ok index abdda835a03..6495bef2c3a 100644 --- a/test/run-drun/ok/aritybug.comp.ok +++ b/test/run-drun/ok/aritybug.comp.ok @@ -1,4 +1,3 @@ aritybug.mo:13.41-15.2: type error, a shared function is only allowed as a public field of an actor (This is a limitation of the current version.) -aritybug.mo:17.25-22.2: type error, freestanding async expression not yet supported - (This is a limitation of the current version.) +aritybug.mo:17.25-22.2: type error, misplaced async expression; try enclosing in an async function diff --git a/test/run-drun/ok/async-any.comp.ok b/test/run-drun/ok/async-any.comp.ok deleted file mode 100644 index 8cc6dffc4c0..00000000000 --- a/test/run-drun/ok/async-any.comp.ok +++ /dev/null @@ -1,2 +0,0 @@ -async-any.mo:3.13-3.29: type error, unsupported async block - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/async-any.drun-run.ok b/test/run-drun/ok/async-any.drun-run.ok new file mode 100644 index 00000000000..adce7c8af5f --- /dev/null +++ b/test/run-drun/ok/async-any.drun-run.ok @@ -0,0 +1,2 @@ +ingress System +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/async-free-var.comp.ok b/test/run-drun/ok/async-free-var.comp.ok deleted file mode 100644 index de73457b5e0..00000000000 --- a/test/run-drun/ok/async-free-var.comp.ok +++ /dev/null @@ -1,2 +0,0 @@ -async-free-var.mo:6.13-11.6: type error, unsupported async block - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/async-free-var.drun-run.ok b/test/run-drun/ok/async-free-var.drun-run.ok new file mode 100644 index 00000000000..3248979280b --- /dev/null +++ b/test/run-drun/ok/async-free-var.drun-run.ok @@ -0,0 +1,9 @@ +ingress System +debug.print: A +debug.print: A +debug.print: C +debug.print: Now in async +debug.print: C +debug.print: B +debug.print: B +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/async-loop-while.comp.ok b/test/run-drun/ok/async-loop-while.comp.ok deleted file mode 100644 index 404d3221c6a..00000000000 --- a/test/run-drun/ok/async-loop-while.comp.ok +++ /dev/null @@ -1,6 +0,0 @@ -async-loop-while.mo:24.22-24.35: type error, unsupported async block - (This is a limitation of the current version.) -async-loop-while.mo:34.15-34.29: type error, unsupported async block - (This is a limitation of the current version.) -async-loop-while.mo:51.15-51.29: type error, unsupported async block - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/async-loop-while.drun-run.ok b/test/run-drun/ok/async-loop-while.drun-run.ok new file mode 100644 index 00000000000..f297abcd777 --- /dev/null +++ b/test/run-drun/ok/async-loop-while.drun-run.ok @@ -0,0 +1,14 @@ +ingress System +debug.print: 0 +debug.print: 1 +debug.print: 2 +debug.print: 0 +debug.print: 1 +debug.print: 2 +debug.print: 0 +debug.print: 1 +debug.print: 2 +debug.print: 0 +debug.print: 1 +debug.print: 2 +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/async-loop.comp.ok b/test/run-drun/ok/async-loop.comp.ok deleted file mode 100644 index 97383f3d658..00000000000 --- a/test/run-drun/ok/async-loop.comp.ok +++ /dev/null @@ -1,6 +0,0 @@ -async-loop.mo:27.19-27.33: type error, unsupported async block - (This is a limitation of the current version.) -async-loop.mo:40.15-40.29: type error, unsupported async block - (This is a limitation of the current version.) -async-loop.mo:59.15-59.29: type error, unsupported async block - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/async-loop.comp.ret.ok b/test/run-drun/ok/async-loop.comp.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/async-loop.comp.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/async-loop.drun-run.ok b/test/run-drun/ok/async-loop.drun-run.ok new file mode 100644 index 00000000000..5d7495cc8a5 --- /dev/null +++ b/test/run-drun/ok/async-loop.drun-run.ok @@ -0,0 +1 @@ +ingress System diff --git a/test/run-drun/ok/async-new-obj.comp.ok b/test/run-drun/ok/async-new-obj.comp.ok deleted file mode 100644 index 674f52c5f1f..00000000000 --- a/test/run-drun/ok/async-new-obj.comp.ok +++ /dev/null @@ -1,2 +0,0 @@ -async-new-obj.mo:6.13-15.6: type error, unsupported async block - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/async-new-obj.comp.ret.ok b/test/run-drun/ok/async-new-obj.comp.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/async-new-obj.comp.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/async-new-obj.drun-run.ok b/test/run-drun/ok/async-new-obj.drun-run.ok new file mode 100644 index 00000000000..295f04c1c6d --- /dev/null +++ b/test/run-drun/ok/async-new-obj.drun-run.ok @@ -0,0 +1,7 @@ +ingress System +debug.print: aaab +debug.print: babb +debug.print: dadb +debug.print: eaeb +debug.print: cacb +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/async-obj-mut.comp.ok b/test/run-drun/ok/async-obj-mut.comp.ok deleted file mode 100644 index d17008eef84..00000000000 --- a/test/run-drun/ok/async-obj-mut.comp.ok +++ /dev/null @@ -1,2 +0,0 @@ -async-obj-mut.mo:5.30-5.41: type error, unsupported async block - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/async-obj-mut.comp.ret.ok b/test/run-drun/ok/async-obj-mut.comp.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/async-obj-mut.comp.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/async-obj-mut.drun-run.ok b/test/run-drun/ok/async-obj-mut.drun-run.ok new file mode 100644 index 00000000000..6cbc2f019f2 --- /dev/null +++ b/test/run-drun/ok/async-obj-mut.drun-run.ok @@ -0,0 +1,10 @@ +ingress System +debug.print: 1 +debug.print: 2 +debug.print: 3 +debug.print: done creating + +debug.print: 3 +debug.print: 4 +debug.print: 5 +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/async-while.comp.ok b/test/run-drun/ok/async-while.comp.ok deleted file mode 100644 index 85ae14f649e..00000000000 --- a/test/run-drun/ok/async-while.comp.ok +++ /dev/null @@ -1,6 +0,0 @@ -async-while.mo:19.20-19.34: type error, unsupported async block - (This is a limitation of the current version.) -async-while.mo:34.15-34.29: type error, unsupported async block - (This is a limitation of the current version.) -async-while.mo:51.15-51.29: type error, unsupported async block - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/async-while.comp.ret.ok b/test/run-drun/ok/async-while.comp.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/async-while.comp.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/async-while.drun-run.ok b/test/run-drun/ok/async-while.drun-run.ok new file mode 100644 index 00000000000..f297abcd777 --- /dev/null +++ b/test/run-drun/ok/async-while.drun-run.ok @@ -0,0 +1,14 @@ +ingress System +debug.print: 0 +debug.print: 1 +debug.print: 2 +debug.print: 0 +debug.print: 1 +debug.print: 2 +debug.print: 0 +debug.print: 1 +debug.print: 2 +debug.print: 0 +debug.print: 1 +debug.print: 2 +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/await.comp.ok b/test/run-drun/ok/await.comp.ok deleted file mode 100644 index 0a1c1d879b9..00000000000 --- a/test/run-drun/ok/await.comp.ok +++ /dev/null @@ -1,2 +0,0 @@ -await.mo:14.13-14.29: type error, unsupported async block - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/await.comp.ret.ok b/test/run-drun/ok/await.comp.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/await.comp.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/await.drun-run.ok b/test/run-drun/ok/await.drun-run.ok new file mode 100644 index 00000000000..b0b3d772cfa --- /dev/null +++ b/test/run-drun/ok/await.drun-run.ok @@ -0,0 +1,29 @@ +ingress System +debug.print: a +debug.print: b +debug.print: c +debug.print: d +debug.print: e +debug.print: g +debug.print: holy +debug.print: e-while +debug.print: g-label +debug.print: . +debug.print: a +debug.print: b +debug.print: cnt: 0 i: 0 +debug.print: cnt: 1 i: 1 +debug.print: cnt: 2 i: 2 +debug.print: cnt: 3 i: 4 +debug.print: cnt: 4 i: 5 +debug.print: cnt: 5 i: 10 +debug.print: . +debug.print: cnt: 6 i: 3 +debug.print: cnt: 7 i: 6 +debug.print: cnt: 8 i: 11 +debug.print: . +debug.print: cnt: 9 i: 7 +debug.print: cnt: 10 i: 12 +debug.print: e-exit +debug.print: g-exit +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/block.comp.ok b/test/run-drun/ok/block.comp.ok deleted file mode 100644 index 1d1315a298d..00000000000 --- a/test/run-drun/ok/block.comp.ok +++ /dev/null @@ -1,2 +0,0 @@ -block.mo:4.13-8.6: type error, unsupported async block - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/block.comp.ret.ok b/test/run-drun/ok/block.comp.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/block.comp.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/block.drun-run.ok b/test/run-drun/ok/block.drun-run.ok new file mode 100644 index 00000000000..841fcf375a0 --- /dev/null +++ b/test/run-drun/ok/block.drun-run.ok @@ -0,0 +1,12 @@ +ingress System +debug.print: a1 +debug.print: b1 +debug.print: 1 +debug.print: a2 +debug.print: b2 +debug.print: a3 +debug.print: b3 +debug.print: 3 +debug.print: 5 +debug.print: 6 +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/count-callbacks.comp.ok b/test/run-drun/ok/count-callbacks.comp.ok deleted file mode 100644 index e35d7ef6b6d..00000000000 --- a/test/run-drun/ok/count-callbacks.comp.ok +++ /dev/null @@ -1,16 +0,0 @@ -count-callbacks.mo:10.18-10.20: type error, shared, async function must be called within an await expression - (This is a limitation of the current version.) -count-callbacks.mo:12.18-12.20: type error, shared, async function must be called within an await expression - (This is a limitation of the current version.) -count-callbacks.mo:14.18-14.20: type error, shared, async function must be called within an await expression - (This is a limitation of the current version.) -count-callbacks.mo:16.18-16.20: type error, shared, async function must be called within an await expression - (This is a limitation of the current version.) -count-callbacks.mo:19.11-19.13: type error, argument to await must be a call expression - (This is a limitation of the current version.) -count-callbacks.mo:21.11-21.13: type error, argument to await must be a call expression - (This is a limitation of the current version.) -count-callbacks.mo:23.11-23.13: type error, argument to await must be a call expression - (This is a limitation of the current version.) -count-callbacks.mo:25.11-25.13: type error, argument to await must be a call expression - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/count-callbacks.comp.ret.ok b/test/run-drun/ok/count-callbacks.comp.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/count-callbacks.comp.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/count-callbacks.drun-run.ok b/test/run-drun/ok/count-callbacks.drun-run.ok new file mode 100644 index 00000000000..72772364151 --- /dev/null +++ b/test/run-drun/ok/count-callbacks.drun-run.ok @@ -0,0 +1,15 @@ +ingress System +debug.print: go 1: 0 +debug.print: go 1: 1 +debug.print: go 1: 2 +debug.print: go 1: 3 +debug.print: go 1: 4 +debug.print: ping! 4 +debug.print: ping! 4 +debug.print: ping! 4 +debug.print: ping! 4 +debug.print: go 2: 3 +debug.print: go 3: 2 +debug.print: go 4: 1 +debug.print: go 5: 0 +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/for-await.comp.ok b/test/run-drun/ok/for-await.comp.ok deleted file mode 100644 index 469481f5f15..00000000000 --- a/test/run-drun/ok/for-await.comp.ok +++ /dev/null @@ -1,2 +0,0 @@ -for-await.mo:17.15-17.29: type error, unsupported async block - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/for-await.comp.ret.ok b/test/run-drun/ok/for-await.comp.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/for-await.comp.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/for-await.drun-run.ok b/test/run-drun/ok/for-await.drun-run.ok new file mode 100644 index 00000000000..924e441db3d --- /dev/null +++ b/test/run-drun/ok/for-await.drun-run.ok @@ -0,0 +1,13 @@ +ingress System +debug.print: 0 +debug.print: 1 +debug.print: 2 +debug.print: 3 +debug.print: 4 +debug.print: 5 +debug.print: 6 +debug.print: 7 +debug.print: 8 +debug.print: 9 +debug.print: 10 +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/general_await.drun-run.ok b/test/run-drun/ok/general_await.drun-run.ok new file mode 100644 index 00000000000..220e2b312df --- /dev/null +++ b/test/run-drun/ok/general_await.drun-run.ok @@ -0,0 +1,46 @@ +ingress System +debug.print: Ack +debug.print: Ack +debug.print: +1 +debug.print: +2 +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: 0 +debug.print: +1 +debug.print: +2 +debug.print: +3 +debug.print: +4 +debug.print: +5 +debug.print: +6 +debug.print: +7 +debug.print: +8 +debug.print: +9 +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: +10 +debug.print: +9 +debug.print: +8 +debug.print: +7 +debug.print: +6 +debug.print: +5 +debug.print: +4 +debug.print: +3 +debug.print: +2 +debug.print: +1 +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/general_await_implicit.drun-run.ok b/test/run-drun/ok/general_await_implicit.drun-run.ok new file mode 100644 index 00000000000..220e2b312df --- /dev/null +++ b/test/run-drun/ok/general_await_implicit.drun-run.ok @@ -0,0 +1,46 @@ +ingress System +debug.print: Ack +debug.print: Ack +debug.print: +1 +debug.print: +2 +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: 0 +debug.print: +1 +debug.print: +2 +debug.print: +3 +debug.print: +4 +debug.print: +5 +debug.print: +6 +debug.print: +7 +debug.print: +8 +debug.print: +9 +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: Ack +debug.print: +10 +debug.print: +9 +debug.print: +8 +debug.print: +7 +debug.print: +6 +debug.print: +5 +debug.print: +4 +debug.print: +3 +debug.print: +2 +debug.print: +1 +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/interleave.comp.ok b/test/run-drun/ok/interleave.comp.ok deleted file mode 100644 index 1a3e66d735f..00000000000 --- a/test/run-drun/ok/interleave.comp.ok +++ /dev/null @@ -1,2 +0,0 @@ -interleave.mo:14.13-22.6: type error, unsupported async block - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/interleave.comp.ret.ok b/test/run-drun/ok/interleave.comp.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/interleave.comp.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/interleave.drun-run.ok b/test/run-drun/ok/interleave.drun-run.ok new file mode 100644 index 00000000000..1b07309b266 --- /dev/null +++ b/test/run-drun/ok/interleave.drun-run.ok @@ -0,0 +1,21 @@ +ingress System +debug.print: g +debug.print: e-while + +debug.print: g-label + +debug.print: e cnt: 0 i: 5 +debug.print: g cnt: 1 i: 10 +debug.print: e cnt: 2 i: 6 +debug.print: g cnt: 3 i: 11 +debug.print: e cnt: 4 i: 7 +debug.print: g cnt: 5 i: 12 +debug.print: e cnt: 6 i: 8 +debug.print: g cnt: 7 i: 13 +debug.print: e cnt: 8 i: 9 +debug.print: g cnt: 9 i: 14 +debug.print: e-exit + +debug.print: g-exit + +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/issue-894.comp.ok b/test/run-drun/ok/issue-894.comp.ok deleted file mode 100644 index bfb4f571c53..00000000000 --- a/test/run-drun/ok/issue-894.comp.ok +++ /dev/null @@ -1,6 +0,0 @@ -issue-894.mo:16.20-16.27: type error, unsupported async block - (This is a limitation of the current version.) -issue-894.mo:23.15-23.22: type error, unsupported async block - (This is a limitation of the current version.) -issue-894.mo:30.15-30.22: type error, unsupported async block - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/issue-894.comp.ret.ok b/test/run-drun/ok/issue-894.comp.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/issue-894.comp.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/issue-894.drun-run.ok b/test/run-drun/ok/issue-894.drun-run.ok new file mode 100644 index 00000000000..8025b729f6a --- /dev/null +++ b/test/run-drun/ok/issue-894.drun-run.ok @@ -0,0 +1,11 @@ +ingress System +debug.print: 1 +debug.print: 1 +debug.print: 1 +debug.print: 1 +debug.print: 0 +debug.print: 1 +debug.print: 2 +debug.print: 3 +debug.print: 4 +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/nary-async.comp.ok b/test/run-drun/ok/nary-async.comp.ok deleted file mode 100644 index 03af1589cf7..00000000000 --- a/test/run-drun/ok/nary-async.comp.ok +++ /dev/null @@ -1,16 +0,0 @@ -nary-async.mo:23.14-26.8: type error, unsupported async block - (This is a limitation of the current version.) -nary-async.mo:31.14-34.8: type error, unsupported async block - (This is a limitation of the current version.) -nary-async.mo:39.14-42.8: type error, unsupported async block - (This is a limitation of the current version.) -nary-async.mo:47.14-50.8: type error, unsupported async block - (This is a limitation of the current version.) -nary-async.mo:69.14-72.8: type error, unsupported async block - (This is a limitation of the current version.) -nary-async.mo:77.14-82.8: type error, unsupported async block - (This is a limitation of the current version.) -nary-async.mo:87.14-93.8: type error, unsupported async block - (This is a limitation of the current version.) -nary-async.mo:99.14-106.8: type error, unsupported async block - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/nary-async.comp.ret.ok b/test/run-drun/ok/nary-async.comp.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/nary-async.comp.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/nary-async.drun-run.ok b/test/run-drun/ok/nary-async.drun-run.ok new file mode 100644 index 00000000000..106feeb26ea --- /dev/null +++ b/test/run-drun/ok/nary-async.drun-run.ok @@ -0,0 +1,11 @@ +ingress System +debug.print: 0_0 +debug.print: 1_0 +debug.print: 2_0 +debug.print: 3_0 +ingress Completed: Canister: Payload: 0x4449444c0000 +debug.print: 0_0 +debug.print: 0_1 +debug.print: 0_2 +debug.print: 0_3 +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/overflow.comp.ok b/test/run-drun/ok/overflow.comp.ok deleted file mode 100644 index ae19590ce91..00000000000 --- a/test/run-drun/ok/overflow.comp.ok +++ /dev/null @@ -1,12 +0,0 @@ -overflow.mo:8.12-11.6: type error, unsupported async block - (This is a limitation of the current version.) -overflow.mo:12.12-15.6: type error, unsupported async block - (This is a limitation of the current version.) -overflow.mo:16.12-19.6: type error, unsupported async block - (This is a limitation of the current version.) -overflow.mo:20.12-23.6: type error, unsupported async block - (This is a limitation of the current version.) -overflow.mo:24.12-27.6: type error, unsupported async block - (This is a limitation of the current version.) -overflow.mo:28.12-31.6: type error, unsupported async block - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/overflow.comp.ret.ok b/test/run-drun/ok/overflow.comp.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/overflow.comp.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/overflow.drun-run.ok b/test/run-drun/ok/overflow.drun-run.ok new file mode 100644 index 00000000000..ee25d22dcf1 --- /dev/null +++ b/test/run-drun/ok/overflow.drun-run.ok @@ -0,0 +1,7 @@ +ingress System +debug.print: This is reachable. +debug.print: This is reachable. +debug.print: This is reachable. +debug.print: This is reachable. +debug.print: This is reachable. +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/shared-match.diff-ir.ok b/test/run-drun/ok/shared-match.diff-ir.ok new file mode 100644 index 00000000000..d1bad30548b --- /dev/null +++ b/test/run-drun/ok/shared-match.diff-ir.ok @@ -0,0 +1,7 @@ +--- shared-match.run ++++ shared-match.run-ir +@@ -1,3 +1,3 @@ + go1 + match_true +-shared-match.mo:8.25-8.31: execution error, argument value false does not match parameter list ++shared-match.mo:8.25-8.31: execution error, value false does not match pattern diff --git a/test/run-drun/ok/shared-match.diff-low.ok b/test/run-drun/ok/shared-match.diff-low.ok new file mode 100644 index 00000000000..de911e913e8 --- /dev/null +++ b/test/run-drun/ok/shared-match.diff-low.ok @@ -0,0 +1,7 @@ +--- shared-match.run ++++ shared-match.run-low +@@ -1,3 +1,3 @@ + go1 + match_true +-shared-match.mo:8.25-8.31: execution error, argument value false does not match parameter list ++shared-match.mo:8.25-8.31: execution error, value false does not match pattern diff --git a/test/run-drun/ok/shared-match.drun-run.ok b/test/run-drun/ok/shared-match.drun-run.ok new file mode 100644 index 00000000000..906299ef1d1 --- /dev/null +++ b/test/run-drun/ok/shared-match.drun-run.ok @@ -0,0 +1,5 @@ +ingress System +debug.print: go1 +debug.print: match_true +debug.print: go2 +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/shared-match.ic-stub-run.ok b/test/run-drun/ok/shared-match.ic-stub-run.ok new file mode 100644 index 00000000000..9a6b457bbc4 --- /dev/null +++ b/test/run-drun/ok/shared-match.ic-stub-run.ok @@ -0,0 +1,10 @@ +→ create +← completed: canister-id = 0x2a01 +→ install +← completed +→ update go(0x4449444c0000) +debug.print: go1 +debug.print: match_true +Trap: EvalTrapError :0.1 "canister trapped explicitly: pattern failed" +debug.print: go2 +← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/shared-match.run-ir.ok b/test/run-drun/ok/shared-match.run-ir.ok new file mode 100644 index 00000000000..a07bd253201 --- /dev/null +++ b/test/run-drun/ok/shared-match.run-ir.ok @@ -0,0 +1,3 @@ +go1 +match_true +shared-match.mo:8.25-8.31: execution error, value false does not match pattern diff --git a/test/run-drun/ok/shared-match.run-low.ok b/test/run-drun/ok/shared-match.run-low.ok new file mode 100644 index 00000000000..a07bd253201 --- /dev/null +++ b/test/run-drun/ok/shared-match.run-low.ok @@ -0,0 +1,3 @@ +go1 +match_true +shared-match.mo:8.25-8.31: execution error, value false does not match pattern diff --git a/test/run-drun/ok/shared-match.run.ok b/test/run-drun/ok/shared-match.run.ok new file mode 100644 index 00000000000..8318ff7a636 --- /dev/null +++ b/test/run-drun/ok/shared-match.run.ok @@ -0,0 +1,3 @@ +go1 +match_true +shared-match.mo:8.25-8.31: execution error, argument value false does not match parameter list diff --git a/test/run-drun/ok/shared-match.tc.ok b/test/run-drun/ok/shared-match.tc.ok new file mode 100644 index 00000000000..dc982dc11f8 --- /dev/null +++ b/test/run-drun/ok/shared-match.tc.ok @@ -0,0 +1,4 @@ +shared-match.mo:8.25-8.31: warning, this pattern consuming type + Bool +does not cover value + false diff --git a/test/run-drun/ok/throw.comp.ok b/test/run-drun/ok/throw.comp.ok deleted file mode 100644 index 601f679ac60..00000000000 --- a/test/run-drun/ok/throw.comp.ok +++ /dev/null @@ -1,4 +0,0 @@ -throw.mo:8.14-11.8: type error, unsupported async block - (This is a limitation of the current version.) -throw.mo:23.13-42.8: type error, unsupported async block - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/throw.comp.ret.ok b/test/run-drun/ok/throw.comp.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/throw.comp.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/throw.drun-run.ok b/test/run-drun/ok/throw.drun-run.ok new file mode 100644 index 00000000000..b498e8d296a --- /dev/null +++ b/test/run-drun/ok/throw.drun-run.ok @@ -0,0 +1,4 @@ +ingress System +debug.print: t2 ok +debug.print: t3 ok +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/type-lub.comp.ok b/test/run-drun/ok/type-lub.comp.ok deleted file mode 100644 index 80ccbcab09c..00000000000 --- a/test/run-drun/ok/type-lub.comp.ok +++ /dev/null @@ -1,2 +0,0 @@ -type-lub.mo:57.16-57.24: type error, unsupported async block - (This is a limitation of the current version.) diff --git a/test/run-drun/ok/type-lub.comp.ret.ok b/test/run-drun/ok/type-lub.comp.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/type-lub.comp.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/ok/type-lub.drun-run.ok b/test/run-drun/ok/type-lub.drun-run.ok new file mode 100644 index 00000000000..adce7c8af5f --- /dev/null +++ b/test/run-drun/ok/type-lub.drun-run.ok @@ -0,0 +1,2 @@ +ingress System +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/unsupported-more.comp-stub.ok b/test/run-drun/ok/unsupported-more.comp-stub.ok new file mode 100644 index 00000000000..da64326058f --- /dev/null +++ b/test/run-drun/ok/unsupported-more.comp-stub.ok @@ -0,0 +1,2 @@ +unsupported-more.mo:2.1-5.2: type error, an actor must be the last declaration in a program + (This is a limitation of the current version and flag -stub-system-api.) diff --git a/test/run-drun/ok/AST-66.comp.ret.ok b/test/run-drun/ok/unsupported-more.comp-stub.ret.ok similarity index 100% rename from test/run-drun/ok/AST-66.comp.ret.ok rename to test/run-drun/ok/unsupported-more.comp-stub.ret.ok diff --git a/test/run-drun/ok/unsupported-more.comp.ok b/test/run-drun/ok/unsupported-more.comp.ok new file mode 100644 index 00000000000..dc95d98012c --- /dev/null +++ b/test/run-drun/ok/unsupported-more.comp.ok @@ -0,0 +1,2 @@ +unsupported-more.mo:2.1-5.2: type error, an actor must be the last declaration in a program + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/async-any.comp.ret.ok b/test/run-drun/ok/unsupported-more.comp.ret.ok similarity index 100% rename from test/run-drun/ok/async-any.comp.ret.ok rename to test/run-drun/ok/unsupported-more.comp.ret.ok diff --git a/test/run-drun/ok/unsupported.comp-stub.ok b/test/run-drun/ok/unsupported.comp-stub.ok new file mode 100644 index 00000000000..03b4745f859 --- /dev/null +++ b/test/run-drun/ok/unsupported.comp-stub.ok @@ -0,0 +1,16 @@ +unsupported.mo:4.5-4.41: type error, a shared function cannot be private + (This is a limitation of the current version and flag -stub-system-api.) +unsupported.mo:36.26-36.29: type error, a shared function is only allowed as a public field of an actor + (This is a limitation of the current version and flag -stub-system-api.) +unsupported.mo:50.3-50.35: type error, actor classes are not supported; use an actor declaration instead + (This is a limitation of the current version and flag -stub-system-api.) +unsupported.mo:54.3-54.42: type error, actor classes are not supported; use an actor declaration instead + (This is a limitation of the current version and flag -stub-system-api.) +unsupported.mo:58.45-58.53: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program + (This is a limitation of the current version and flag -stub-system-api.) +unsupported.mo:62.37-62.45: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program + (This is a limitation of the current version and flag -stub-system-api.) +unsupported.mo:72.34-72.37: type error, a shared function is only allowed as a public field of an actor + (This is a limitation of the current version and flag -stub-system-api.) +unsupported.mo:73.27-73.30: type error, a shared function is only allowed as a public field of an actor + (This is a limitation of the current version and flag -stub-system-api.) diff --git a/test/run-drun/ok/async-free-var.comp.ret.ok b/test/run-drun/ok/unsupported.comp-stub.ret.ok similarity index 100% rename from test/run-drun/ok/async-free-var.comp.ret.ok rename to test/run-drun/ok/unsupported.comp-stub.ret.ok diff --git a/test/run-drun/ok/unsupported.comp.ok b/test/run-drun/ok/unsupported.comp.ok new file mode 100644 index 00000000000..e0847760a58 --- /dev/null +++ b/test/run-drun/ok/unsupported.comp.ok @@ -0,0 +1,16 @@ +unsupported.mo:4.5-4.41: type error, a shared function cannot be private + (This is a limitation of the current version.) +unsupported.mo:36.26-36.29: type error, a shared function is only allowed as a public field of an actor + (This is a limitation of the current version.) +unsupported.mo:50.3-50.35: type error, actor classes are not supported; use an actor declaration instead + (This is a limitation of the current version.) +unsupported.mo:54.3-54.42: type error, actor classes are not supported; use an actor declaration instead + (This is a limitation of the current version.) +unsupported.mo:58.45-58.53: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program + (This is a limitation of the current version.) +unsupported.mo:62.37-62.45: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program + (This is a limitation of the current version.) +unsupported.mo:72.34-72.37: type error, a shared function is only allowed as a public field of an actor + (This is a limitation of the current version.) +unsupported.mo:73.27-73.30: type error, a shared function is only allowed as a public field of an actor + (This is a limitation of the current version.) diff --git a/test/run-drun/ok/async-loop-while.comp.ret.ok b/test/run-drun/ok/unsupported.comp.ret.ok similarity index 100% rename from test/run-drun/ok/async-loop-while.comp.ret.ok rename to test/run-drun/ok/unsupported.comp.ret.ok diff --git a/test/run-drun/ok/unsupported.tc.ok b/test/run-drun/ok/unsupported.tc.ok deleted file mode 100644 index 4b6dfcb9936..00000000000 --- a/test/run-drun/ok/unsupported.tc.ok +++ /dev/null @@ -1 +0,0 @@ -unsupported.mo:41.10-41.18: type error, misplaced async expression; try enclosing in an async function diff --git a/test/run-drun/ok/unsupported.tc.ret.ok b/test/run-drun/ok/unsupported.tc.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run-drun/ok/unsupported.tc.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run-drun/shared-match.mo b/test/run-drun/shared-match.mo new file mode 100644 index 00000000000..5184542286f --- /dev/null +++ b/test/run-drun/shared-match.mo @@ -0,0 +1,20 @@ +/* this test show a discrepancy between argument pattern match failure in +shared methods in the interpreter (which traps, aborting the caller) +and compiled code (which continues with the caller) +This is expected since the interpreter does not yet turn message traps into rejects. +*/ +import Prim "mo:prim"; +actor a { + public func match_true(true) : async () { + Prim.debugPrint "match_true"; + }; + public func go() = ignore async { + Prim.debugPrint "go1"; + try { await match_true(true) } + catch e {}; + try { await match_true(false) } + catch e {}; + Prim.debugPrint "go2"; + }; +}; +a.go(); //OR-CALL ingress go "DIDL\x00\x00" \ No newline at end of file diff --git a/test/run-drun/unsupported-more.mo b/test/run-drun/unsupported-more.mo new file mode 100644 index 00000000000..bc1147975fa --- /dev/null +++ b/test/run-drun/unsupported-more.mo @@ -0,0 +1,9 @@ +// top-level actor objects are supported +actor Counter { + + +} +; + +actor BadSecondActor { }; + diff --git a/test/run-drun/unsupported.mo b/test/run-drun/unsupported.mo index ecef513fa31..7dac5618496 100644 --- a/test/run-drun/unsupported.mo +++ b/test/run-drun/unsupported.mo @@ -1,62 +1,50 @@ // top-level actor objects are supported actor Counter { - shared func bad_private_shared() { }; // not public + shared func bad_private_shared() { }; // unsupported private shared - public func badactorarg(a:actor{}) : async () {}; + public func ok_actorarg(a:actor{}) : async () {}; - public func badfunctionarg(f:shared()->async ()) : async () {}; + public func ok_functionarg(f:shared()->async ()) : async () {}; - /* TODO - public func badoneway(){}; // unsupported oneway - */ + public func ok_oneway(){}; // supported oneway public func ok() : async () {}; public func ok_explicit() : async () = async {}; - public func bad_call() : async () { - ignore (ok()); // unsupported intercanister messaging + public func ok_call() : async () { + ignore (ok()); // supported intercanister messaging }; - public func bad_await_call() : async () { - await (ok()); // unsupported intercanister messaging + public func ok_await_call() : async () { + await (ok()); // supported intercanister messaging }; - public func bad_await() : async () { + public func ok_await() : async () { let t : async () = loop {}; - await t; // unsupported general await + await t; // supported general await }; - public func badasync() : async () { - let a = async { 1; }; // unsupported async + public func ok_async() : async () { + let a = async { 1; }; // supported async }; } ; -shared func bad_shared() { }; // not actor enclosed - -func local_spawn() { - ignore(async ()); // no async capability -}; +shared func bad_shared() { }; // unsupported non actor-member { - // shared function types aren't sharable - type illformed_1 = shared (shared () -> ()) -> async (); + // shared function types are sharable + type wellformed_1 = shared (shared () -> ()) -> async (); }; { - // actors aren't shareable - type illformed_2 = shared (actor {}) -> async (); + // actors are shareable + type wellformed_2 = shared (actor {}) -> async (); }; -/* TODO -{ - // oneway functions aren't supported - type illformed_3 = shared () -> (); -}; -*/ { actor class BadActorClass () { }; // no actor classes From 7d223e247be606cb92aced20fa004bf836350fe9 Mon Sep 17 00:00:00 2001 From: Yan Chen <48968912+chenyan-dfinity@users.noreply.github.com> Date: Tue, 28 Jan 2020 09:02:49 -0800 Subject: [PATCH 1008/1176] resolve relative imports for --print-deps (#1165) * resolve relative imports for --print-deps * fix * fix test * refactoring to remove duplicated logic * add todo Co-authored-by: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> --- design/DFX-Interface.md | 10 ++- src/languageServer/declaration_index.ml | 4 +- src/pipeline/pipeline.ml | 10 ++- src/pipeline/resolve_import.ml | 89 ++++++++++++++++--------- src/pipeline/resolve_import.mli | 7 +- src/pipeline/resolve_import_test.ml | 4 +- test/repl/ok/print-deps.stdout.ok | 4 +- 7 files changed, 84 insertions(+), 44 deletions(-) diff --git a/design/DFX-Interface.md b/design/DFX-Interface.md index 5a974df4c03..91fdee37add 100644 --- a/design/DFX-Interface.md +++ b/design/DFX-Interface.md @@ -139,17 +139,21 @@ The command moc --print-deps some/path/input.mo -prints to the standard output all URLs _transitively_ imported by +prints to the standard output all URLs _directly_ imported by `some/path/input.mo`, one per line. Each line outputs the original URL, and optionally a full path if `moc` can resolve the URL, separated by a space. For example, - mo:stdlib/List + mo:stdlib/list mo:other_package/Some/Module ic:ABCDE01A7 canister:alias ./local_import some/path/local_import.mo ./runtime some/path/runtime.wasm -This may _read_ the same files as `moc -c` would, and writes no files. +This _reads_ only `some/path/input.mo`, and writes no files. +By transitively exploring the dependency graph using this command (and +resolving URLs appropriately before passing them as files to `moc`), one can +determine the full set of set of `.mo` files read by the two compilation modes +described above (to wasm and to IDL). diff --git a/src/languageServer/declaration_index.ml b/src/languageServer/declaration_index.ml index f525f0242ed..e907ed39d2d 100644 --- a/src/languageServer/declaration_index.ml +++ b/src/languageServer/declaration_index.ml @@ -72,7 +72,7 @@ let lookup_module | Ok (Relative path) -> let path = Pipeline.ResolveImport.append_extension Sys.file_exists path - |> Option.value ~default:path in + |> Result.value ~default:path in Index.find_opt (make_absolute path) index.modules |> Option.map (fun decls -> (path, decls)) | Ok (Package (pkg, path)) -> @@ -82,7 +82,7 @@ let lookup_module let path = Pipeline.ResolveImport.append_extension Sys.file_exists (Filename.concat pkg_path path) - |> Option.value ~default:path in + |> Result.value ~default:path in Index.find_opt (make_absolute path) index.modules diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index e3bb92491eb..f45df391ebd 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -135,8 +135,12 @@ let resolve_progs = let print_deps (file : string) : unit = let (prog, _) = Diag.run (parse_file file) in - let imports = ResolveImport.collect_imports prog in - List.iter print_endline imports + let imports = Diag.run (ResolveImport.collect_imports prog file) in + List.iter (fun (url, path) -> + match path with + | None -> Printf.printf "%s\n" url + | Some path -> Printf.printf "%s %s\n" url path + ) imports (* Checking *) @@ -423,7 +427,7 @@ let check_files files : check_result = let check_string s name : check_result = Diag.map ignore (load_decl (parse_string name s) initial_stat_env) - + (* Generate IDL *) let generate_idl files : Idllib.Syntax.prog Diag.result = diff --git a/src/pipeline/resolve_import.ml b/src/pipeline/resolve_import.ml index ed030c44824..753463fcd0a 100644 --- a/src/pipeline/resolve_import.ml +++ b/src/pipeline/resolve_import.ml @@ -47,17 +47,6 @@ type package_map = filepath M.t open Syntax open Source -let append_extension file_exists f = - if Option.is_some (Lib.String.chop_suffix "/" f) then - Some (Filename.concat f "lib.mo") - else if Filename.extension f = "" then - if file_exists (f ^ ".mo") then - Some (f ^ ".mo") - else - Some (Filename.concat f "lib.mo") - else - None - let err_unrecognized_url msgs at url msg = let open Diag in add_msg msgs { @@ -85,18 +74,19 @@ let err_actor_import_without_idl_path msgs at = text = Printf.sprintf "cannot import canister urls without --actor-idl param" } -let err_file_does_not_exist msgs at full_path = - let open Diag in - add_msg msgs { +let err_file_does_not_exist' at full_path = + Diag.{ sev = Error; at; cat = "import"; text = Printf.sprintf "file \"%s\" does not exist" full_path } -let err_import_musnt_have_extension msgs at full_path = - let open Diag in - add_msg msgs { +let err_file_does_not_exist msgs at full_path = + Diag.add_msg msgs (err_file_does_not_exist' at full_path) + +let err_import_musnt_have_extension at full_path = + Diag.{ sev = Error; at; cat = "import"; @@ -147,20 +137,40 @@ let err_prim_pkg msgs = at = no_region; cat = "package"; text = "the \"prim\" package is built-in, and cannot be mapped to a directory" - } + } -let add_lib_import msgs imported ri_ref at full_path = +let append_extension : + (string -> bool) -> + string -> + (string, Source.region -> Diag.message) result = + fun file_exists f -> + if Option.is_some (Lib.String.chop_suffix "/" f) then + Ok (Filename.concat f "lib.mo") + else if Filename.extension f = "" then + if file_exists (f ^ ".mo") then + Ok (f ^ ".mo") + else + Ok (Filename.concat f "lib.mo") + else + Error (fun at -> err_import_musnt_have_extension at f) + +let resolve_lib_import at full_path : (string, Diag.message) result = match append_extension Sys.file_exists full_path with - | Some full_path -> + | Ok full_path -> if Sys.file_exists full_path - then begin - ri_ref := LibPath full_path; - imported := RIM.add (LibPath full_path) at !imported - end else - err_file_does_not_exist msgs at full_path - | None -> - err_import_musnt_have_extension msgs at full_path + then Ok full_path + else Error (err_file_does_not_exist' at full_path) + | Error mk_err -> + Error (mk_err at) +let add_lib_import msgs imported ri_ref at full_path = + match resolve_lib_import at full_path with + | Ok full_path -> begin + ri_ref := LibPath full_path; + imported := RIM.add (LibPath full_path) at !imported + end + | Error err -> + Diag.add_msg msgs err let add_idl_import msgs imported ri_ref at full_path bytes = if Sys.file_exists full_path @@ -231,10 +241,6 @@ let prog_imports (p : prog): (url * resolved_import ref * Source.region) list = let _ = ignore (Traversals.over_prog f p) in List.rev !res -let collect_imports (p : prog): url list = - List.map (fun (f, _, _) -> f) (prog_imports p) - - type actor_idl_path = filepath option type package_urls = url M.t type actor_aliases = url M.t @@ -276,3 +282,24 @@ let resolve Some (List.map (fun (rim,at) -> Source.(rim @@ at)) (RIM.bindings !imported)) ) ) + + +let collect_imports (p:prog) base : ((url * url option) list) Diag.result = + (* TODO unify the code path for resolve and collect_imports *) + let base = if Sys.is_directory base then base else Filename.dirname base in + Diag.with_message_store (fun msgs -> + let imports = + List.map (fun (f, _, at) -> + match Url.parse f with + | Ok (Url.Relative path) -> begin + match resolve_lib_import at (in_base base path) with + | Ok full_path -> + (f, Some full_path) + | Error err -> + Diag.add_msg msgs err; + (f, None) + end + | _ -> (f, None) + ) (prog_imports p) in + Some imports + ) diff --git a/src/pipeline/resolve_import.mli b/src/pipeline/resolve_import.mli index 56bfbcd55ed..870f21eb585 100644 --- a/src/pipeline/resolve_import.mli +++ b/src/pipeline/resolve_import.mli @@ -12,7 +12,7 @@ type actor_aliases = string Flags.M.t type resolved_imports = Syntax.resolved_import Source.phrase list -val collect_imports : Syntax.prog -> string list +val collect_imports : Syntax.prog -> string -> ((string * string option) list) Diag.result type flags = { package_urls : package_urls; @@ -33,4 +33,7 @@ val resolve_flags : flags -> resolved_flags Diag.result val resolve : flags -> Syntax.prog -> filepath -> resolved_imports Diag.result (* Exported for tests *) -val append_extension : (filepath -> bool) -> filepath -> filepath option +val append_extension : + (filepath -> bool) -> + filepath -> + (filepath, Source.region -> Diag.message) result diff --git a/src/pipeline/resolve_import_test.ml b/src/pipeline/resolve_import_test.ml index 5b93e9f8ca4..ac08465d75b 100644 --- a/src/pipeline/resolve_import_test.ml +++ b/src/pipeline/resolve_import_test.ml @@ -1,7 +1,9 @@ (** Given a list of filenames that should be reported as existing tests what a given import path resolves to *) let import_relative_test_case files import expected = - let actual = Resolve_import.append_extension (fun x -> List.mem x files) import in + let actual = + Resolve_import.append_extension (fun x -> List.mem x files) import + |> Result.to_option in let show = function | None -> "None" | Some s -> "Some " ^ s in diff --git a/test/repl/ok/print-deps.stdout.ok b/test/repl/ok/print-deps.stdout.ok index b8c4099a282..02a9fbf6e69 100644 --- a/test/repl/ok/print-deps.stdout.ok +++ b/test/repl/ok/print-deps.stdout.ok @@ -1,4 +1,4 @@ -nested/a -nested/b +nested/a lib/nested/a.mo +nested/b lib/nested/b.mo ic:ABCDE01A7 ic:alias From a6dd07e6952b27ab0f7f0388133a5bdf8c03c681 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 29 Jan 2020 15:39:18 +0100 Subject: [PATCH 1009/1176] Refactor stdlib reference generation (#1166) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit See https://hydra.dfinity.systems/latest/dfinity-ci-build/motoko/stdlib-doc/index.html and README at https://github.com/dfinity-lab/motoko/tree/master/stdlib/doc I have updated the full `list.mo` file, and also `nat`, `int`, `char`, `text`, `none`. There is a dedicated stdlib-adocs nix output, documented in DFX-Interface.md, for inclusion in some other documents (anticipating a requirement from @lsgunnlsgunn). This can’t handle nested modules. I plan to remove the obsolete BitList from hash.mo (in a separate PR). The HTML style could be more efficient (the headers for the functions are pretty big), but that’s a separate concern. --- .gitignore | 5 +- default.nix | 10 +- design/DFX-Interface.md | 3 + stdlib/doc/Makefile | 61 +- stdlib/doc/README.md | 94 ++- stdlib/doc/adoc-of-mo.pl | 65 ++ stdlib/doc/index.adoc | 52 ++ stdlib/doc/tools/markdown-of-markdown.py | 20 - stdlib/doc/tools/markdown-of-motoko.py | 215 ------ stdlib/src/array.mo | 5 + stdlib/src/assocList.mo | 23 +- stdlib/src/blob.mo | 5 + stdlib/src/buf.mo | 7 +- stdlib/src/char.mo | 8 +- stdlib/src/debug.mo | 12 +- stdlib/src/function.mo | 5 + stdlib/src/hash.mo | 25 +- stdlib/src/hashMap.mo | 7 +- stdlib/src/int.mo | 35 +- stdlib/src/iter.mo | 5 + stdlib/src/list.mo | 933 +++++++++++------------ stdlib/src/nat.mo | 55 +- stdlib/src/none.mo | 15 +- stdlib/src/option.mo | 23 +- stdlib/src/prelude.mo | 13 +- stdlib/src/result.mo | 31 +- stdlib/src/text.mo | 17 +- stdlib/src/trie.mo | 123 +-- stdlib/src/trieMap.mo | 7 +- stdlib/src/trieSet.mo | 5 + 30 files changed, 958 insertions(+), 926 deletions(-) create mode 100755 stdlib/doc/adoc-of-mo.pl create mode 100644 stdlib/doc/index.adoc delete mode 100755 stdlib/doc/tools/markdown-of-markdown.py delete mode 100755 stdlib/doc/tools/markdown-of-motoko.py diff --git a/.gitignore b/.gitignore index d75197c2921..ffe32527beb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,10 @@ .database .dvm _out -/result* +_output +_build **/*~ -**/_build -**/_output /result* /samples/**/*.txt diff --git a/default.nix b/default.nix index 57e9b6526c4..844028052b4 100644 --- a/default.nix +++ b/default.nix @@ -392,8 +392,9 @@ rec { stdlib-doc = stdenv.mkDerivation { name = "stdlib-doc"; src = subpath ./stdlib/doc; + outputs = [ "out" "adocs" ]; buildInputs = with nixpkgs; - [ pandoc bash python ]; + [ bash perl asciidoctor ]; buildPhase = '' patchShebangs . make STDLIB=${stdlib} @@ -402,9 +403,13 @@ rec { mkdir -p $out mv _out/* $out/ mkdir -p $out/nix-support - echo "report docs $out README.html" >> $out/nix-support/hydra-build-products + echo "report docs $out index.html" >> $out/nix-support/hydra-build-products + + mkdir -p $adocs + mv _build/*.adoc $adocs/ ''; }; + stdlib-adocs = stdlib-doc.adocs; all-systems-go = nixpkgs.releaseTools.aggregate { name = "all-systems-go"; @@ -419,6 +424,7 @@ rec { stdlib stdlib-tests stdlib-doc + stdlib-adocs users-guide ic-stub shell diff --git a/design/DFX-Interface.md b/design/DFX-Interface.md index 91fdee37add..4611d5e93df 100644 --- a/design/DFX-Interface.md +++ b/design/DFX-Interface.md @@ -36,6 +36,9 @@ the top-level `default.nix`: * `rts`: contains `rts/mo-rts.wasm`, the Motoko runtime system * `stdlib`: contains the standard library, directly in the top level directory, as `*.mo` files. It does not contain extra files (test files, for example) +* `stdlib-adocs`: contains the documentation of the standard library, directly + in the top level directory, as `*.adoc` files. There is an `index.adoc` + file. The `default.nix` file itself takes an optional `system` parameter which is either `"x86_64-linux"` or `"x86_64-darwin"`, and defaults to diff --git a/stdlib/doc/Makefile b/stdlib/doc/Makefile index 7afd237d0d7..0c223144fda 100644 --- a/stdlib/doc/Makefile +++ b/stdlib/doc/Makefile @@ -1,51 +1,48 @@ STDLIB ?= ../src +ADocOfMo=./adoc-of-mo.pl -OUTDIR=_out -MDofMO=./tools/markdown-of-motoko.py -MDofMD=./tools/markdown-of-markdown.py -PANDOC=pandoc +SHELL=bash -.PHONY: default all clean docMd docHtml +STDLIB_FILES= $(patsubst $(STDLIB)/%.mo,%,$(wildcard $(STDLIB)/*.mo)) -default: all +DOCS = $(patsubst %,_build/%.adoc,$(STDLIB_FILES)) -all: doc +ADOCS = _build/index.adoc $(DOCS) -clean: - rm -rf $(OUTDIR) - -#########################################################################################################33 +all: _out/index.html -## -## Documentation -## +adocs: $(ADOCS) -doc: docMd docHtml +clean: + rm -rf _out _build -$(OUTDIR): +_out: @mkdir -p $@ +_build: + @mkdir -p $@ -$(OUTDIR)/%.md: $(STDLIB)/%.mo $(MDofMO) | $(OUTDIR) - @echo "" > $@ +_build/%.adoc: $(STDLIB)/%.mo $(ADocOfMo) | _build + $(ADocOfMo) $* < $< > $@.tmp + @echo "// Do not edit; This file was machine-generated" > $@ @echo "" >> $@ @echo "" >> $@ - $(MDofMO) $< >> $@ + cat $@.tmp >> $@ + rm -f $@.tmp -$(OUTDIR)/%.html: $(OUTDIR)/%.md - $(PANDOC) -f gfm $^ > $@ +_build/index.adoc: index.adoc | _build + cp $< $@ +_out/index.html: _build/index.adoc $(DOCS) | _out + # checking if all files are included + @diff -u \ + --label "Present" \ + <(echo $(STDLIB_FILES)| tr ' ' '\n' |sort) \ + --label "Included" \ + <(perl -n -e 'print "$$1\n" if m,include::(.*)\.adoc,' $< | sort) \ + # ok -DOCS = README prelude array buf option result hash list assocList trie trieSet + asciidoctor $< -o $@ -# Markdown documentation, extracted from the source directory -docMd: $(patsubst %,$(OUTDIR)/%.md,$(DOCS)) | $(OUTDIR) - -# HTML documentation, extracted from the source directory -docHtml: $(patsubst %,$(OUTDIR)/%.html,$(DOCS)) | $(OUTDIR) - -$(OUTDIR)/README.md: README.md | $(OUTDIR) - @echo "" > $@ - @echo "" >> $@ - $(MDofMD) $< >> $@ +.PHONY: all clean adocs diff --git a/stdlib/doc/README.md b/stdlib/doc/README.md index 80e9e33d79a..fb7950a0d9a 100644 --- a/stdlib/doc/README.md +++ b/stdlib/doc/README.md @@ -1,30 +1,84 @@ -Motoko Standard Library -============================== +Reference manual generation +=========================== -The standard library of Motoko. +This directory contains the tools to create the reference manual. -See [The Appendix Chapter](https://sdk.dfinity.org/language-guide/index.html#appendix-stdlib) -of [the Motoko Book](https://sdk.dfinity.org/language-guide/) for documentation with examples. +## Building -## Overview of modules +Run `make`. The output is in `_out`. -We group the modules conceptually, and indicate the status of each as planned -(`[ ]`) or implemented and tested, at least partially (`[x]`). +## Anchors -### Collections: +The tool creates HTML anchors of these forms: -- [x] `Array` module -- [x] `List` module -- [x] `AssocList` module -- [ ] `Map` interface (e.g., implemented by `Trie` below, via a class) -- [ ] `Set` interface (e.g., implemented by `TrieSet` below, via a class) + * `#mod-foo` for the module `foo` + (These are actually not generated, but are put in manually) + * `#foo_bar` for value `bar` in module `foo` + * `#foo_Bar` for type `Bar` in module `foo` -### Low-level collections (wrappers provide above interfaces): +To refer to them, use asciidoc syntax, as in -- [x] `TrieSet` module -- can implement `Set` above -- [x] `Trie` module -- can implement `Map` above + Also see <>. + +## Conventions and assumptions + +See `stdlib/src/list.mo` for inspiration. + +The doc generation tools requires the standard library code to be in a certain +shape: + + * No nested modules. + + * All public definitions are of the form + `public let val : typ =` (in one line), or + `public type name = …` (may span multiple lines, must be followed by a blank line). + + * Documentation comments have the form + + /** + comment + */ + + The common indentation is removed. The body should be indented no further + than the opening `/` (unless you want the indentation to carry over to the + ascii document, e.g. for inline code blocks). + + * A documentation comment must be followed by either + + - a blank line + then it is copied verbatim + - a public value or type definition, + then it is put between the header and the type listing for that definition + +## Turning function declarations into let declarations + +To appease this rigid regine, one has to rewrite + + public func foo(a : Bool) : Text = { + body + }; + +into + + public let foo : Bool -> Text = func(a) { + body + }; + +If the function is polymorphic, one also has to repeat the types, turning + + public func foo(a : T, f : T -> T) : T = { + body + }; + +into + + public let foo : (T, f : T -> T) -> T = { + func(a : T, f : T -> T) : T = { + body + }; + +Note that one can still _optionally_ name parameters. By convention, this is +only necessary when the name indicates semantic meaning (e.g. `eq : (T,T) -> +Bool`), or if it is referred to by the doc text (“the function `f`”). -### Misc utilities -- [x] `Prelude` module -- [x] `Hash` module diff --git a/stdlib/doc/adoc-of-mo.pl b/stdlib/doc/adoc-of-mo.pl new file mode 100755 index 00000000000..d142f4032a2 --- /dev/null +++ b/stdlib/doc/adoc-of-mo.pl @@ -0,0 +1,65 @@ +#!/usr/bin/env perl +# +# See README.md for the expected format +# + +use strict; +use warnings; + +my $block = ''; +my $mod = shift @ARGV; + +OUTER: while (<>) { + if (m,^(\s*)/\*\*$,) { + my $indent = $1; + my $start = $.; + die "Please put an empty line before new block in $.\n" if $block; + $block = ''; + while (<>) { + if (m,^$indent ?\*/$,) { $block .= "\n"; next OUTER; } + elsif (m,^$indent(.*)$,) { $block .= "$1\n" } + elsif (m,^\s*$,) { $block .= "\n" } + else { die "Wrong indentation in doc comment at line $..\n" }; + } + die "Doc comment in line $start not closed.\n"; + } elsif (m,^(?:\s*)public let\s*([a-zA-Z0-9]*)\s*:\s*([^=]*?)\s*=,) { + my $name = $1; + my $type = $2; + print <<__END__; +[#${mod}_$name] +== `$name` +$block + +[listing] +$name : $type + +__END__ + $block = '' + } elsif (m,^(\s*)public type\s*([a-zA-Z0-9]*)(.*)$,) { + my $indent = $1; + my $name = $2; + my $def = $3; + while (<>) { + if (m,^\s*$,) { last } + elsif (m,^$indent(.*)$,) { $def .= "$1\n" } + else { die "Wrong indentation in type def at line $..\n" }; + } + print <<__END__; +[#${mod}_$name] +== `$name` (type) +$block + +.... +type $name$def +.... + +__END__ + $block = ''; + } elsif ($block and m,^\s*$,) { + print "$block\n"; + $block = '' + } elsif ($block) { + die "Please put an empty line after the block at line $.\n" if $block; + } +} + diff --git a/stdlib/doc/index.adoc b/stdlib/doc/index.adoc new file mode 100644 index 00000000000..4bc9d248ecb --- /dev/null +++ b/stdlib/doc/index.adoc @@ -0,0 +1,52 @@ += The Motoko Standard Library +:toc: +:toc: right +:sectanchors: + +This is the reference manual for the Motoko standard library. The following chapters each describe one module provided by the standard library. You can import the module under a name of your choice, e.g. +.... +import List "stdlib:list" +.... + +or + +.... +import L "stdlib:list" +.... + +For most basic types (<>, <>) there is one module with common operations on them. Additionally, there are more advanced data structures (<>) and utility modules (<>, <>). + +// Primitive data types + +include::nat.adoc[leveloffset=+1] +include::int.adoc[leveloffset=+1] +include::char.adoc[leveloffset=+1] +include::text.adoc[leveloffset=+1] +include::none.adoc[leveloffset=+1] +include::option.adoc[leveloffset=+1] +include::function.adoc[leveloffset=+1] +include::array.adoc[leveloffset=+1] +include::blob.adoc[leveloffset=+1] +include::principalId.adoc[leveloffset=+1] + +// Complex data structures + +include::result.adoc[leveloffset=+1] +include::iter.adoc[leveloffset=+1] +include::buf.adoc[leveloffset=+1] +include::list.adoc[leveloffset=+1] +include::assocList.adoc[leveloffset=+1] +include::hash.adoc[leveloffset=+1] +include::hashMap.adoc[leveloffset=+1] +include::trie.adoc[leveloffset=+1] +include::trieMap.adoc[leveloffset=+1] +include::trieSet.adoc[leveloffset=+1] + +// Utilities +include::prelude.adoc[leveloffset=+1] +include::debug.adoc[leveloffset=+1] + + +// At this point I’d like to include a proper index, +// auto-generated with all functions. But that’s waiting for +// https://github.com/asciidoctor/asciidoctor/pull/3160 diff --git a/stdlib/doc/tools/markdown-of-markdown.py b/stdlib/doc/tools/markdown-of-markdown.py deleted file mode 100755 index e703fec09d5..00000000000 --- a/stdlib/doc/tools/markdown-of-markdown.py +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env python - -## Stable links -## ----------- -## https://hydra.oregon.dfinity.build//job/dfinity-ci-build/motoko.pr-234/stdlib-reference/latest/download/1/doc/ -## -## (PR 234 is the current PR for the standard library and produce exchange) -## - -DOCURL="https://hydra.oregon.dfinity.build//job/dfinity-ci-build/motoko.pr-234/stdlib-reference/latest/download/1/doc/" - -############################################################################################################# - -import sys -import re - -with open(sys.argv[1], "r") as ins: - for line in ins: - line = line.replace("$DOCURL", DOCURL); - print line.rstrip() diff --git a/stdlib/doc/tools/markdown-of-motoko.py b/stdlib/doc/tools/markdown-of-motoko.py deleted file mode 100755 index 31f9013d8ab..00000000000 --- a/stdlib/doc/tools/markdown-of-motoko.py +++ /dev/null @@ -1,215 +0,0 @@ -#!/usr/bin/env python - -## Objective -## ---------- -## -## The objective of this program is to "Invert" an Motoko source -## file into a corresponding Markdown file with snippets of -## Motoko. The markdown becomes the "outer format" with -## Motoko (as code blocks) as the "inner format". In this sense, -## the objective is to "invert" the inner/outer relationship, and -## preserve everything else that's sensible. -## -## Design question: If we have the freedom to order the Decls of an -## Motoko file any way we choose, then what's the best order to -## tell a **narrative** version of the file? - -## The immediate benefit of using this tool: -## -## - The stdlib directory is source code that documents itself to seed -## WIP guide for Motoko; this workflow is possible via a -## Makefile. -## -## - By exposing the Markdown on the outside, the outline/narrative -## structure is primary, and can be hyperlinked for sharing and -## remote discussions, e.g., as markdown files in a github repo. -## -## - By exposing the Markdown on the outside, the outline/narrative -## structure is primary and we can explain how implementations of -## the Produce Exchange and the standard library, and future -## examples, work, in a "literate programming" style. - -## Assumptions -## ------------ -## -## - KISS: This tool is a placeholder for a better tool that actually -## understands Motoko. -## -## - KISS: This tool does not try to be intelligent -## when it can force you (the programmer) to do something only -## somewhat annoying, e.g.: -## -## - KISS: Dont mix mode-switch patterns and other Motoko comments on a single line -## - KISS: Dont mix mode switches on a single line. -## - - -## Stable links -## ----------- -## https://hydra.oregon.dfinity.build//job/dfinity-ci-build/motoko.pr-234/stdlib-reference/latest/download/1/doc/ -## -## (PR 234 is the current PR for the standard library and produce exchange) -## - -DOCURL="https://hydra.oregon.dfinity.build//job/dfinity-ci-build/motoko.pr-234/stdlib-reference/latest/download/1/doc/" - -############################################################################################################# - -import sys -import re - -showMotoko=True -#showMotoko=False - -OmitMotoko="OmitMotoko" -Motoko="Motoko" -Markdown="Markdown" -Comment="Comment" -Done="Done" - -modeType=[Motoko, Markdown, Comment, OmitMotoko, Done] - -# eventually, detect this `outerMode` based on the input file name and -# handle the other way around; for now, we assume only this way -# around: -outerMode = Motoko -ignoreNonMarkdownComments= False - -mode = outerMode -modeOpen="```Motoko" -modeLines = [] -modeClose="```" - -def switchModeTo(toMode, toModeOpen, toModeClose): - global mode - global modeOpen - global modeClose - global modeLines - - if toMode == mode: - return (False, []) - - if len(modeLines) > 0: - # Normal case: - if mode != OmitMotoko and (showMotoko or mode != Motoko): - print modeOpen - if modeLines[-1] == "": - modeLines.pop() - print "" - for l in modeLines: - l = l.replace("$DOCURL", DOCURL); - print(l.rstrip()) - print modeClose - # The source file explicitly omitted this - elif mode == OmitMotoko: - print "```" - print ". . . (selectively omitted, explicitly) . . ." - print "```" - # the flag says no - elif mode == Motoko and not showMotoko: - print "```" - print ". . . (all Motoko is omitted) . . ." - print "```" - # impossible! - else: - assert False - - mode = toMode - modeOpen = toModeOpen - modeClose = toModeClose - modeLines = [] - -# empty line, or just whitespace; -def whiteSpaceLine(): - #debug "whitespace-only line, noted." - # record if its not the first, or last thing we saw - if len(modeLines) > 0 and modeLines[-1] != "": - modeLines.append("") - -with open(sys.argv[1], "r") as ins: - for line in ins: - #debug "read line (", mode, "): `", line.rstrip(), "`" - - # Now discriminate between lines that switch modes, and "ordinary lines" - # For now, assume 0 or 1 mode switches per line; later, handle breaking those on the same line up - - # Start Markdown comment - if re.match(r'/\*\*([^\*])+\*/', line.lstrip()): - p = re.compile(r'(/\*\*)([^\*/]*)(\*/)') - groups = p.match(line.lstrip()).groups() - if len(groups) == 3: - savedMode = mode - savedOpen = modeOpen - savedClose = modeClose - switchModeTo(Markdown, "", "") - modeLines.append(groups[1]) - switchModeTo(savedMode, savedOpen, savedClose) - else: - # ignore the comment; no content - assert True - - # Start Markdown comment - elif re.match(r'/\*\*', line.lstrip()): - switchModeTo(Markdown, "", "") - - # Start ordinary comment - elif re.match(r'/\*', line.lstrip()): - switchModeTo(Comment, "/* ", "*/") - - # Horizontal rule, in motoko code - elif re.match(r'//////////+', line.lstrip()): - # Horizontal rule in Motoko - if mode == Motoko: - if len(modeLines) > 0: - modeLines.append("```") - modeLines.append("-----------------------------------------------------------------------") - modeLines.append("```") - else: - assert True - - # Close markdown or comment block and omit the next otherwise-Motoko block: - elif re.match(r'//\s*@Omit:', line.lstrip()): - switchModeTo(OmitMotoko, "", "") - - # One-line comment - elif re.match(r'//+ \S*\s*', line.lstrip()): - matches = re.split(r'//+ ', line.lstrip()) - if mode == Markdown: - modeLines.append(matches[1].rstrip()) - elif mode == Motoko: - if ignoreNonMarkdownComments: - #debug "ignoring single-line comment." - assert True - else: - #debug "append single-line comment (", mode, "): `", line.rstrip(), "`" - modeLines.append(line.rstrip()) - elif mode == Comment: - modeLines.append(matches[1].rstrip()) - elif mode == OmitMotoko: - assert True - else: - assert False - - # One-line comment, with no content - elif re.match(r'//', line.lstrip()): - whiteSpaceLine() - - # Close markdown or comment block - elif re.match(r'\*/', line.lstrip()): - switchModeTo(Motoko, "```Motoko", "```") - - else: - #debug "non-empty line" - # non-empty line - if re.match(r'\S', line.lstrip()): - if mode == Comment: - # do nothing - #debug "ignore line (", mode, "): `", line.rstrip(), "`" - assert True - else: - #debug "append line (", mode, "): `", line.rstrip(), "`" - modeLines.append(line.rstrip()) - else: - whiteSpaceLine() - -switchModeTo(Done, "", "") diff --git a/stdlib/src/array.mo b/stdlib/src/array.mo index b3cf155133d..622b718b00b 100644 --- a/stdlib/src/array.mo +++ b/stdlib/src/array.mo @@ -1,3 +1,8 @@ +/** +[#mod-array] += `array` -- Arrays +*/ + import Prim "mo:prim"; module { public func equals(a : [A], b : [A], eq : (A,A) -> Bool) : Bool { diff --git a/stdlib/src/assocList.mo b/stdlib/src/assocList.mo index 9477308a4ef..8d637e684a8 100644 --- a/stdlib/src/assocList.mo +++ b/stdlib/src/assocList.mo @@ -1,7 +1,12 @@ +/** +[#mod-assocList] += `assocList` -- Association lists +*/ + import List "list"; module { -/** +/* Association Lists ================== @@ -15,7 +20,7 @@ Implements the same interface as `Trie`, but as a linked-list of key-value pairs // polymorphic association linked lists between keys and values public type AssocList = List.List<(K,V)>; - /** + /* `find` -------- find the value associated with a given key, or null if absent. @@ -42,7 +47,7 @@ public type AssocList = List.List<(K,V)>; rec(al) }; - /** + /* `replace` --------- replace the value associated with a given key, or add it, if missing. @@ -79,7 +84,7 @@ public type AssocList = List.List<(K,V)>; rec(al) }; - /** + /* `diff` --------- The key-value pairs of the final list consist of those pairs of @@ -105,7 +110,7 @@ public type AssocList = List.List<(K,V)>; rec(al1) }; - /** + /* `mapAppend` -------- */ @@ -133,7 +138,7 @@ public type AssocList = List.List<(K,V)>; mapAppend(al1, al2, vbin) }; - /** + /* `disj` -------- This operation generalizes the notion of "set union" to finite maps. @@ -179,7 +184,7 @@ public type AssocList = List.List<(K,V)>; rec1(al1) }; - /** + /* `join` --------- This operation generalizes the notion of "set intersection" to @@ -209,10 +214,10 @@ public type AssocList = List.List<(K,V)>; }; - /** + /* `fold` --------- - */ + */ public func fold(al:AssocList, nil:X, cons:(K,V,X)->X) diff --git a/stdlib/src/blob.mo b/stdlib/src/blob.mo index adde3dacaee..10ac3a232b0 100644 --- a/stdlib/src/blob.mo +++ b/stdlib/src/blob.mo @@ -1,3 +1,8 @@ +/* +[#mod-blob] += `blob` -- Binary blobs +*/ + import Prim "mo:prim"; module { public let hash = Prim.hashBlob; diff --git a/stdlib/src/buf.mo b/stdlib/src/buf.mo index 31de3a963ec..2a62bcada9f 100644 --- a/stdlib/src/buf.mo +++ b/stdlib/src/buf.mo @@ -1,10 +1,15 @@ +/** +[#mod-buf] += `buf` -- Growing buffers +*/ + import P "prelude"; import I "iter"; import A "array"; module { -/** +/* Buffers =================== diff --git a/stdlib/src/char.mo b/stdlib/src/char.mo index b7ddbcf75c4..888fe5a3516 100644 --- a/stdlib/src/char.mo +++ b/stdlib/src/char.mo @@ -1,7 +1,11 @@ +/** +[#mod-char] += `char` -- Characters +*/ + import Prim "mo:prim"; module { - - public func isDigit(char : Char) : Bool { + public let isDigit : Char -> Bool = func(char) { Prim.charToWord32(char) - Prim.charToWord32('0') <= (9 : Word32) }; diff --git a/stdlib/src/debug.mo b/stdlib/src/debug.mo index 9d499a54a7e..a9ea42e0088 100644 --- a/stdlib/src/debug.mo +++ b/stdlib/src/debug.mo @@ -1,4 +1,14 @@ +/** +[#mod-debug] += `debug` -- Debugging aids +*/ + import Prim "mo:prim"; module { - public let print = Prim.debugPrint; + /** + This prints a text (which typically does not include a final newline) to the + debug output. Where this debug output is stored and shown depends on the + environment the program runs in. + */ + public let print : Text -> () = Prim.debugPrint; } diff --git a/stdlib/src/function.mo b/stdlib/src/function.mo index 6ebc39088b3..c56018f66a8 100644 --- a/stdlib/src/function.mo +++ b/stdlib/src/function.mo @@ -1,3 +1,8 @@ +/** +[#mod-function] += `function` -- Functions on functions +*/ + module { public func compose(f : B -> C, g : A -> B) : A -> C { func (x : A) : C { diff --git a/stdlib/src/hash.mo b/stdlib/src/hash.mo index 36a1823bee6..5aae66d3c56 100644 --- a/stdlib/src/hash.mo +++ b/stdlib/src/hash.mo @@ -1,8 +1,13 @@ +/** +[#mod-hash] += `hash` -- Lists of bits +*/ + import Prim "mo:prim"; import Iter "iter"; module { -/** +/* Hash values =============================== @@ -34,13 +39,13 @@ going forward. */ -/** A "bit string" as a linked list of bits: */ +/* A "bit string" as a linked list of bits: */ public type BitList = ?(Bool, BitList); -/** A "bit vector" is a bounded-length bit string packed into a single word: */ +/* A "bit vector" is a bounded-length bit string packed into a single word: */ public type BitVec = Word32; -/** +/* `BitVec` ---------------------- @@ -104,7 +109,7 @@ public module BitVec { return x }; - /** Project a given bit from the bit vector. */ + /* Project a given bit from the bit vector. */ public func getHashBit(h:BitVec, pos:Nat) : Bool = label profile_getHashBit : Bool { assert (pos <= length()); if ((h & (Prim.natToWord32(1) << Prim.natToWord32(pos))) != Prim.natToWord32(0)) @@ -117,7 +122,7 @@ public module BitVec { } }; - /** Test if two lists of bits are equal. */ + /* Test if two lists of bits are equal. */ public func hashEq(ha:BitVec, hb:BitVec) : Bool { label profile_hashEq : Bool ha == hb @@ -157,7 +162,7 @@ public module BitVec { }; -/** +/* `BitList` ---------- @@ -174,7 +179,7 @@ public module BitList { BitVec.toList(BitVec.hashOfInt(i)) }; - /** Test if two lists of bits are equal. */ + /* Test if two lists of bits are equal. */ public func getHashBit(h:BitList, pos:Nat) : Bool { switch h { case null { @@ -188,7 +193,7 @@ public module BitList { } }; - /** Test if two lists of bits are equal. */ + /* Test if two lists of bits are equal. */ public func hashEq(ha:BitList, hb:BitList) : Bool { switch (ha, hb) { case (null, null) true; @@ -226,7 +231,7 @@ public module BitList { }; -/** +/* Canonical representations --------------------------- diff --git a/stdlib/src/hashMap.mo b/stdlib/src/hashMap.mo index 613adec9698..a19c6c5859f 100644 --- a/stdlib/src/hashMap.mo +++ b/stdlib/src/hashMap.mo @@ -1,3 +1,8 @@ +/** +[#mod-hashMap] += `hashMap` -- Mutable hash map +*/ + import Prim "mo:prim"; import P "prelude"; import A "array"; @@ -7,7 +12,7 @@ import AssocList "assocList"; module { -/** +/* Hash Map (aka Hash table) ========================= diff --git a/stdlib/src/int.mo b/stdlib/src/int.mo index cbd51dfbca6..a994dedf638 100644 --- a/stdlib/src/int.mo +++ b/stdlib/src/int.mo @@ -1,14 +1,28 @@ +/** +[#mod-int] += `int` -- Integer numbers + +Most operations on natural numbers (e.g. addition) are available as built-in operators (`1 + 1`). +This module provides conversion functions. + +The conversions `toInt*` will trap if the number is out of bounds. +*/ + import Prim "mo:prim"; import Prelude "prelude"; module { - public let abs = Prim.abs; + /** + Returns the absolute value of the number + */ + public let abs : Int -> Nat = Prim.abs; + // Remove? public func add(x : Int, y : Int) : Int { x + y; }; - public func toText(x : Int) : Text { + public let toText : Int -> Text = func(x) { if (x == 0) { return "0"; }; @@ -40,12 +54,13 @@ module { return if isNegative ("-" # text) else text; }; - public let fromInt8 = Prim.int8ToInt; - public let fromInt16 = Prim.int16ToInt; - public let fromInt32 = Prim.int32ToInt; - public let fromInt64 = Prim.int64ToInt; - public let toInt8 = Prim.intToInt8; - public let toInt16 = Prim.intToInt16; - public let toInt32 = Prim.intToInt32; - public let toInt64 = Prim.intToInt64; + public let fromInt8 : Int8 -> Int = Prim.int8ToInt; + public let fromInt16 : Int16 -> Int = Prim.int16ToInt; + public let fromInt32 : Int32 -> Int = Prim.int32ToInt; + public let fromInt64 : Int64 -> Int = Prim.int64ToInt; + + public let toInt8 : Int -> Int8 = Prim.intToInt8; + public let toInt16 : Int -> Int16 = Prim.intToInt16; + public let toInt32 : Int -> Int32 = Prim.intToInt32; + public let toInt64 : Int -> Int64 = Prim.intToInt64; } diff --git a/stdlib/src/iter.mo b/stdlib/src/iter.mo index df3fc70bf5b..127e51e7cc1 100644 --- a/stdlib/src/iter.mo +++ b/stdlib/src/iter.mo @@ -1,3 +1,8 @@ +/** +[#mod-iter] += `iter` -- Iterators +*/ + import Array "array"; import List "list"; diff --git a/stdlib/src/list.mo b/stdlib/src/list.mo index 775512d0158..b263339feb7 100644 --- a/stdlib/src/list.mo +++ b/stdlib/src/list.mo @@ -1,47 +1,34 @@ -import Array "array"; -import Option "option"; - -module { /** +[#mod-list] += `list` -- Lists -# List +This module provides purely-functional, singly-linked lists. -Purely-functional, singly-linked lists. */ -/** - Representation - ================= - - A singly-linked list consists of zero or more _cons cells_, wherein -each cell contains a single list element (the cell's _head_), and a pointer to the -remainder of the list (the cell's _tail_). - -*/ +import Array "array"; +import Option "option"; -public type List = ?(T, List); +module { -/** - Interface - ============== -*/ + /** + A singly-linked list consists of zero or more _cons cells_, wherein + each cell contains a single list element (the cell's _head_), and a pointer to the + remainder of the list (the cell's _tail_). + */ + public type List = ?(T, List); /** - `nil` - ------ - empty list - */ - public func nil() : List = - null; + The empty list + */ + public let nil : () -> List = func() : List = null; /** - `isNil` - -------- - test for empty list - */ - public func isNil(l : List) : Bool { + Returns true if the list is empty. + */ + public let isNil : List -> Bool = func(l : List) : Bool { switch l { case null { true }; case _ { false }; @@ -49,19 +36,15 @@ public type List = ?(T, List); }; /** - `push` - ------------- - aka "list cons" - */ - public func push(x : T, l : List) : List = - ?(x, l); + also known as "list cons" + */ + public let push : (T, List) -> List = + func(x : T, l : List) : List = ?(x, l); /** - `last` - ---------- - last element, optionally; tail recursive - */ - public func last(l : List) : ?T = { + The last element of the list, if present. + */ + public let last : List -> ?T = func(l : List) : ?T { switch l { case null { null }; case (?(x,null)) { ?x }; @@ -70,11 +53,9 @@ public type List = ?(T, List); }; /** - `pop` - -------- - treat the list as a stack; combines the usual operations `head` and (non-failing) `tail` into one operation - */ - public func pop(l : List) : (?T, List) = { + Treating the list as a stack; this combines the usual operations `head` and (non-failing) `tail` into one operation. + */ + public let pop : List -> (?T, List) = func(l : List) : (?T, List) { switch l { case null { (null, null) }; case (?(h, t)) { (?h, t) }; @@ -82,217 +63,213 @@ public type List = ?(T, List); }; /** - `len` - -------- - length; tail recursive - */ - public func len(l : List) : Nat = label profile_list_len : Nat { - func rec(l : List, n : Nat) : Nat = label profile_list_len_rec : Nat { - switch l { - case null { n }; - case (?(_,t)) { rec(t,n+1) }; - } + The length of the list + */ + public let len : List -> Nat = + func(l : List) : Nat = label profile_list_len : Nat { + func rec(l : List, n : Nat) : Nat = label profile_list_len_rec : Nat { + switch l { + case null { n }; + case (?(_,t)) { rec(t,n+1) }; + } + }; + rec(l,0) }; - rec(l,0) - }; /** - `lenIsLessThan` - -------- - test length against a maximum value; tail recursive - */ - public func lenIsEqLessThan(l : List, i : Nat) : Bool = - label profile_list_lenIsEqLessThan_begin : Bool { - func rec(l : List, i : Nat) : Bool = label profile_list_lenIsEqLessThan_rec : Bool { - switch l { - case null label profile_list_lenIsEqLessThan_end_true : Bool true; - case (?(_, t)) { - if ( i == 0 ) { - label profile_list_lenIsEqLessThan_end_false : Bool - false - } - else { - rec(t, i - 1) - } - }; - } - }; - rec(l, i) - }; + Tests the length against a maximum value + */ + public let lenIsEqLessThan : (List, Nat) -> Bool = + func(l : List , i : Nat) : Bool = + label profile_list_lenIsEqLessThan_begin : Bool { + func rec(l : List, i : Nat) : Bool = label profile_list_lenIsEqLessThan_rec : Bool { + switch l { + case null label profile_list_lenIsEqLessThan_end_true : Bool true; + case (?(_, t)) { + if ( i == 0 ) { + label profile_list_lenIsEqLessThan_end_false : Bool + false + } + else { + rec(t, i - 1) + } + }; + } + }; + rec(l, i) + }; /** - `lenClamp` - -------- - get the length, unless greater than a maximum value, in which return null; tail recursive - */ - public func lenClamp(l : List, i0 : Nat) : ?Nat = - label profile_list_lenClamp : (?Nat) { - func rec(l : List, i : Nat) : ?Nat = label profile_list_lenClamp_rec : (?Nat) { - switch l { - case null { label profile_list_lenClamp_end_some : (?Nat) ?(i0 - i) }; - case (?(_, t)) { - if ( i == 0 ) { - label profile_list_lenClamp_end_null : (?Nat) - null - } - else { - rec(t, i - 1) - } - }; - } - }; - rec(l, i0) - }; + Get the length, unless greater than a maximum value, in which return null. + */ + public let lenClamp : (List, Nat) -> ?Nat = + func(l : List, i0 : Nat) : ?Nat = + label profile_list_lenClamp : (?Nat) { + func rec(l : List, i : Nat) : ?Nat = label profile_list_lenClamp_rec : (?Nat) { + switch l { + case null { label profile_list_lenClamp_end_some : (?Nat) ?(i0 - i) }; + case (?(_, t)) { + if ( i == 0 ) { + label profile_list_lenClamp_end_null : (?Nat) + null + } + else { + rec(t, i - 1) + } + }; + } + }; + rec(l, i0) + }; /** - `nth` - --------- - array-like list access, but in linear time; tail recursive - */ - public func nth(l : List, n : Nat) : ?T = { - switch (n, l) { - case (_, null) { null }; - case (0, (?(h,t))) { ?h }; - case (_, (?(_,t))) { nth(t, n - 1) }; - } - }; + Random list access, zero-based. - /** - `rev` - -------- - reverse the list; tail recursive - */ - public func rev(l : List) : List = { - func rec(l : List, r : List) : List { - switch l { - case null { r }; - case (?(h,t)) { rec(t,?(h,r)) }; + NOTE: Indexing into a list is a linear operation, and usually an indication + that a list might not be the best data structure to use. + */ + public let nth : (List, Nat) -> ?T = + func(l : List, n : Nat) : ?T { + switch (n, l) { + case (_, null) { null }; + case (0, (?(h,t))) { ?h }; + case (_, (?(_,t))) { nth(t, n - 1) }; } }; - rec(l, null) - }; /** - `iter` - --------- - Called `app` in SML Basis, and `iter` in OCaml; tail recursive - */ - public func iter(l : List, f:T -> ()) : () = { - func rec(l : List) : () { - switch l { - case null { () }; - case (?(h,t)) { f(h) ; rec(t) }; - } + reverse the list; tail recursive + */ + public let rev : List -> List = + func(l : List) : List = { + func rec(l : List, r : List) : List { + switch l { + case null { r }; + case (?(h,t)) { rec(t,?(h,r)) }; + } + }; + rec(l, null) }; - rec(l) - }; /** - `map` - --------- - map the list elements; non-tail recursive + Calls the given function with each list element in turn. - Note: need mutable Cons tails for tail-recursive map. - */ - public func map(l : List, f:T -> S) : List = { - func rec(l : List) : List { - switch l { - case null { null }; - case (?(h,t)) { ?(f(h),rec(t)) }; - } + This is called `app` in SML Basis, and `iter` in OCaml. + */ + public let iter : (List, f : T -> ()) -> () = + func iter(l : List, f:T -> ()) : () = { + func rec(l : List) : () { + switch l { + case null { () }; + case (?(h,t)) { f(h) ; rec(t) }; + } + }; + rec(l) }; - rec(l) - }; /** - `filter` - ---------- - filter the list elements; non-tail recursive - */ - public func filter(l : List, f:T -> Bool) : List = { - func rec(l : List) : List { - switch l { - case null { null }; - case (?(h,t)) { if (f(h)){ ?(h,rec(t)) } else { rec(t) } }; - } + Calls the given function on each list element, collecing the results in a new + list. + */ + public let map : (List, f : T -> S) -> List = + func(l : List, f:T -> S) : List = { + func rec(l : List) : List { + switch l { + case null { null }; + case (?(h,t)) { ?(f(h),rec(t)) }; + } + }; + rec(l) }; - rec(l) - }; /** - `split` - ---------- - split the list elements; non-tail recursive - */ - public func split(l : List, f:T -> Bool) : (List, List) = { - func rec(l : List) : (List, List) = - label profile_list_split_rec : (List, List) { - switch l { - case null { (null, null) }; - case (?(h,t)) { let (l,r) = rec(t) ; - if (f(h)){ (?(h,l), r) } else { (l, ?(h,r)) } }; - } + Creates a new list with only those elements of the original list for which + the given function (often called the _predicate_) is returns true. + */ + public let filter : (List, p : T -> Bool) -> List = + func(l : List, f:T -> Bool) : List = { + func rec(l : List) : List { + switch l { + case null { null }; + case (?(h,t)) { if (f(h)){ ?(h,rec(t)) } else { rec(t) } }; + } + }; + rec(l) }; - label profile_list_split_begin : (List, List) - rec(l) - }; /** - `mapFilter` - -------------- - map and filter the list elements; non-tail recursive - */ - public func mapFilter(l : List, f:T -> ?S) : List = { - func rec(l : List) : List { - switch l { - case null { null }; - case (?(h,t)) { - switch (f(h)) { - case null { rec(t) }; - case (?h_){ ?(h_,rec(t)) }; - } - }; - } + Creates two new lists. The first has those elements for which the given + function `f` returns true, the second those for which it returns false. + + Also known as `partition`. + */ + public let split : (List, f : T -> Bool) -> (List, List) = + func(l : List, f:T -> Bool) : (List, List) = { + func rec(l : List) : (List, List) = + label profile_list_split_rec : (List, List) { + switch l { + case null { (null, null) }; + case (?(h,t)) { + let (l,r) = rec(t) ; + if (f(h)) { (?(h,l), r) } else { (l, ?(h,r)) } + }; + } + }; + label profile_list_split_begin : (List, List) + rec(l) }; - rec(l) - }; /** - `append` - --------- - append two lists; non-tail recursive - */ - public func append(l : List, m : List) : List = { - func rec(l : List) : List { - switch l { - case null { m }; - case (?(h,t)) {?(h,rec(t))}; - } + Calls the given function on each list element, collecing the non-null results + in a new list. + */ + public let mapFilter : (List, f : T -> ?S) -> List = + func(l : List, f:T -> ?S) : List = { + func rec(l : List) : List { + switch l { + case null { null }; + case (?(h,t)) { + switch (f(h)) { + case null { rec(t) }; + case (?h_){ ?(h_,rec(t)) }; + } + }; + } + }; + rec(l) }; - rec(l) - }; /** - `concat` - ----------- - concat (aka "list join"); tail recursive, but requires "two passes" - */ - public func concat(l : List>) : List = { - // 1/2: fold from left to right, reverse-appending the sublists... - let r = - { let f = func(a:List, b:List) : List { revAppend(a,b) }; - foldLeft, List>(l, null, f) + Appends two lists. + */ + public let append : (List, List) -> List = + func (l : List, m : List) : List = { + func rec(l : List) : List { + switch l { + case null { m }; + case (?(h,t)) {?(h,rec(t))}; + } }; - // 2/2: ...re-reverse the elements, to their original order: - rev(r) - }; + rec(l) + }; /** - `revAppend` - ------------- - See SML Basis library; tail recursive - */ - public func revAppend(l1 : List, l2 : List) : List = { + concatenations a list of lists (Also known as "list join") + */ + public let concat : (List>) -> List = + // tail recursive, but requires "two passes" + func(l : List>) : List = { + // 1/2: fold from left to right, reverse-appending the sublists... + let r = + { let f = func(a:List, b:List) : List { revAppend(a,b) }; + foldLeft, List>(l, null, f) + }; + // 2/2: ...re-reverse the elements, to their original order: + rev(r) + }; + + // Internal utility-function + func revAppend(l1 : List, l2 : List) : List = { switch l1 { case null { l2 }; case (?(h,t)) { revAppend(t, ?(h,l2)) }; @@ -300,327 +277,303 @@ public type List = ?(T, List); }; /** - `take` - --------- - "take" `n` elements from the prefix of the given list. - If the given list has fewer than `n` elements, we return the full input list. - */ - public func take(l : List, n:Nat) : List = { - switch (l, n) { - case (_, 0) { null }; - case (null,_) { null }; - case (?(h, t), m) {?(h, take(t, m - 1))}; - } - }; - - /** - `drop` - ---------- - */ - public func drop(l : List, n:Nat) : List = { - switch (l, n) { - case (l_, 0) { l_ }; - case (null, _) { null }; - case ((?(h,t)), m) { drop(t, m - 1) }; - } - }; + "takes" `n` elements from the prefix of the given list. + If the given list has fewer than `n` elements, this returns (a copy of) the + full input list. + */ + public let take : (List, n:Nat) -> List = + func(l : List, n:Nat) : List = { + switch (l, n) { + case (_, 0) { null }; + case (null,_) { null }; + case (?(h, t), m) {?(h, take(t, m - 1))}; + } + }; /** - `foldLeft` - --------------- - fold list left-to-right using function `f`; tail recursive - */ - public func foldLeft(l : List, a:S, f:(T,S) -> S) : S = { - func rec(l:List, a:S) : S = { - switch l { - case null { a }; - case (?(h,t)) { rec(t, f(h,a)) }; + "drops" an `n` element prefix from the given list. + */ + public let drop : (List, n:Nat) -> List = + func(l : List, n:Nat) : List = { + switch (l, n) { + case (l_, 0) { l_ }; + case (null, _) { null }; + case ((?(h,t)), m) { drop(t, m - 1) }; } }; - rec(l,a) - }; - /*** - `foldRight` - ------------ - fold the list right-to-left using function `f`; non-tail recursive - */ - public func foldRight(l : List, a:S, f:(T,S) -> S) : S = { - func rec(l:List) : S = { - switch l { - case null { a }; - case (?(h,t)) { f(h, rec(t)) }; - } + /** + fold list left-to-right using function `f`. + */ + public let foldLeft : (List, S, f : (T,S) -> S) -> S = + func(l : List, a:S, f:(T,S) -> S) : S = { + func rec(l:List, a:S) : S = { + switch l { + case null { a }; + case (?(h,t)) { rec(t, f(h,a)) }; + } + }; + rec(l,a) }; - rec(l) - }; /** - `find` - ----------- - test if there exists list element for which given predicate is true - */ - public func find(l: List, f:T -> Bool) : ?T = { - func rec(l:List) : ?T { - switch l { - case null { null }; - case (?(h,t)) { if (f(h)) { ?h } else { rec(t) } }; - } + fold the list right-to-left using function `f`. + */ + public let foldRight : (List, S, f : (T,S) -> S) -> S = + func(l : List, a:S, f:(T,S) -> S) : S = { + func rec(l:List) : S = { + switch l { + case null { a }; + case (?(h,t)) { f(h, rec(t)) }; + } + }; + rec(l) }; - rec(l) - }; /** - `exists` - --------- - test if there exists list element for which given predicate is true - */ - public func exists(l: List, f:T -> Bool) : Bool = { - func rec(l:List) : Bool { - switch l { - case null { false }; - // XXX/minor --- Missing parens on condition leads to unhelpful error: - //case (?(h,t)) { if f(h) { true } else { rec(t) } }; - case (?(h,t)) { if (f(h)) { true } else { rec(t) } }; - } + Returns the first element for which given predicate `f` is true, if such an element exists. + */ + public let find : (l: List, f : T -> Bool) -> ?T = + func(l: List, f:T -> Bool) : ?T = { + func rec(l:List) : ?T { + switch l { + case null { null }; + case (?(h,t)) { if (f(h)) { ?h } else { rec(t) } }; + } + }; + rec(l) }; - rec(l) - }; /** - `all` - ------- - test if given predicate is true for all list elements - */ - public func all(l: List, f:T -> Bool) : Bool = { - func rec(l:List) : Bool { - switch l { - case null { true }; - case (?(h,t)) { if (not f(h)) { false } else { rec(t) } }; - } + Returns true if there exists list element for which given predicate `f` is true + */ + public let exists : (List, f : T -> Bool) -> Bool = + func(l: List, f:T -> Bool) : Bool = { + func rec(l:List) : Bool { + switch l { + case null { false }; + // XXX/minor --- Missing parens on condition leads to unhelpful error: + //case (?(h,t)) { if f(h) { true } else { rec(t) } }; + case (?(h,t)) { if (f(h)) { true } else { rec(t) } }; + } + }; + rec(l) }; - rec(l) - }; /** - `merge` - --------- - Given two ordered lists, merge them into a single ordered list - */ - public func merge(l1: List, l2: List, lte:(T,T) -> Bool) : List { - func rec(l1: List, l2: List) : List { - switch (l1, l2) { - case (null, _) { l2 }; - case (_, null) { l1 }; - case (?(h1,t1), ?(h2,t2)) { - if (lte(h1,h2)) { - ?(h1, rec(t1, ?(h2,t2))) - } else { - ?(h2, rec(?(h1,t1), t2)) - } - }; - } + Returns true if for all list element the given predicate `f` is true + */ + public let all : (List, f : T -> Bool) -> Bool = + func(l: List, f:T -> Bool) : Bool = { + func rec(l:List) : Bool { + switch l { + case null { true }; + case (?(h,t)) { if (not f(h)) { false } else { rec(t) } }; + } + }; + rec(l) }; - rec(l1, l2) - }; /** - `lessThanEq` - -------------- + Given two lists that are orderd (with regard to the given relation `lte`), + merge them into a single ordered list + */ + public let merge : (List, List, lte : (T,T) -> Bool) -> List = + func(l1: List, l2: List, lte:(T,T) -> Bool) : List { + func rec(l1: List, l2: List) : List { + switch (l1, l2) { + case (null, _) { l2 }; + case (_, null) { l1 }; + case (?(h1,t1), ?(h2,t2)) { + if (lte(h1,h2)) { + ?(h1, rec(t1, ?(h2,t2))) + } else { + ?(h2, rec(?(h1,t1), t2)) + } + }; + } + }; + rec(l1, l2) + }; - Compare two lists lexicographic` ordering. tail recursive. + /** + Compares two lists using lexicographic ordering (with regard to the given relation `lte`). - To do: Eventually, follow `collate` design from SML Basis, with real sum types, use 3-valued `order` type here. + // To do: Eventually, follow `collate` design from SML Basis, with real sum + // types, use 3-valued `order` type here. */ - public func lessThanEq(l1: List, l2: List, lte:(T,T) -> Bool) : Bool { - func rec(l1: List, l2: List) : Bool { - switch (l1, l2) { - case (null, _) { true }; - case (_, null) { false }; - case (?(h1,t1), ?(h2,t2)) { lte(h1,h2) and rec(t1, t2) }; - } + public let lessThanEq : (List, List, lte: (T,T) -> Bool) -> Bool = + func(l1: List, l2: List, lte:(T,T) -> Bool) : Bool { + func rec(l1: List, l2: List) : Bool { + switch (l1, l2) { + case (null, _) { true }; + case (_, null) { false }; + case (?(h1,t1), ?(h2,t2)) { lte(h1,h2) and rec(t1, t2) }; + } + }; + rec(l1, l2) }; - rec(l1, l2) - }; /** - `isEq` - --------- - Compare two lists for equality. tail recursive. + Compares two lists for equality (with regard to the given relation `eq` on elements). - `isEq(l1, l2)` is equivalent to `lessThanEq(l1,l2) && lessThanEq(l2,l1)`, but the former is more efficient. - */ - public func isEq(l1: List, l2: List, eq:(T,T) -> Bool) : Bool { - func rec(l1: List, l2: List) : Bool { - switch (l1, l2) { - case (null, null) { true }; - case (null, _) { false }; - case (_, null) { false }; - case (?(h1,t1), ?(h2,t2)) { eq(h1,h2) and rec(t1, t2) }; - } + // `isEq(l1, l2)` is equivalent to `lessThanEq(l1,l2) && lessThanEq(l2,l1)`, but the former is more efficient. + */ + public let isEq : (List, List, eq : (T,T) -> Bool) -> Bool = + func(l1: List, l2: List, eq:(T,T) -> Bool) : Bool { + func rec(l1: List, l2: List) : Bool { + switch (l1, l2) { + case (null, null) { true }; + case (null, _) { false }; + case (_, null) { false }; + case (?(h1,t1), ?(h2,t2)) { eq(h1,h2) and rec(t1, t2) }; + } + }; + rec(l1, l2) }; - rec(l1, l2) - }; /** - `partition` - --------------- - using a predicate, create two lists from one: the "true" list, and the "false" list. - (See SML basis library); non-tail recursive. - */ - public func partition(l: List, f:T -> Bool) : (List, List) { - func rec(l: List) : (List, List) { - switch l { - case null { (null, null) }; - case (?(h,t)) { - let (pl,pr) = rec(t); - if (f(h)) { - (?(h, pl), pr) - } else { - (pl, ?(h, pr)) - } - }; - } + generates a list based on a length, and a function from list index to list element. + */ + public let tabulate : (Nat, f : Nat -> T) -> List = + func(n:Nat, f:Nat -> T) : List { + func rec(i:Nat) : List { + if (i == n) { null } else { ?(f(i), rec(i+1)) } + }; + rec(0) }; - rec(l) - }; /** - `tabulate` - -------------- - generate a list based on a length, and a function from list index to list element. - (See SML basis library); non-tail recursive. - */ - public func tabulate(n:Nat, f:Nat -> T) : List { - func rec(i:Nat) : List { - if (i == n) { null } else { ?(f(i), rec(i+1)) } + creates a list with exactly one element. + */ + public let singleton : X -> List = + func(x : X) : List { + ?(x, null) }; - rec(0) - }; /** - `singleton` - ---------------- - Creates a list with exactly one element. - */ - public func singleton(x : X) : List { - ?(x, null) - }; + creates a list of the given length with the same value in each position. + */ + public let replicate : (Nat, X) -> List = + func(n : Nat, x : X) : List { + tabulate(n, func _ { x }) + }; /** - `replicate` - ---------------- - Creates a list of the given length with the same value in each position. - */ - public func replicate(n : Nat, x : X) : List { - tabulate(n, func _ { x }) - }; + creates a list of pairs from a pair of lists. - /** - `zip` - ------------- - Creates a list of pairs from a pair of lists. If the given lists have - inconsistent lengths, then the list created will have a length equal to their - minimum. - */ - public func zip(xs : List, ys : List) : List<(X, Y)> { - zipWith(xs, ys, func (x, y) { (x, y) }) - }; + If the given lists have different lengths, then the created list will have a + length equal to the lenght of the smaller list. + */ + public let zip : (List, List) -> List<(X, Y)> = + func(xs : List, ys : List) : List<(X, Y)> { + zipWith(xs, ys, func (x, y) { (x, y) }) + }; /** - `zipWith` - ------------- - Creates a list whose elements are calculated from the given function and - elements occuring at the same position in the given lists. If the given lists - have inconsistent lengths, then the list created will have a length equal to - their minimum. - */ - public func zipWith( - xs : List, - ys : List, - f : (X, Y) -> Z - ) : List { - switch (pop(xs)) { - case (null, _) null; - case (?x, xt) { - switch (pop(ys)) { - case (null, _) null; - case (?y, yt) { - push(f(x, y), zipWith(xt, yt, f)) + Creates a list whose elements are calculated from the function `f` and + elements occuring at the same position in the given lists. + + If the given lists have different lengths, then the created list will have a + length equal to the length of the smaller list. + */ + public let zipWith : (List, List, f : (X, Y) -> Z) -> List = + func(xs : List, ys : List, f : (X, Y) -> Z) : List { + switch (pop(xs)) { + case (null, _) null; + case (?x, xt) { + switch (pop(ys)) { + case (null, _) null; + case (?y, yt) { + push(f(x, y), zipWith(xt, yt, f)) + } } } } - } - }; + }; /** - `splitAt` - ----------- - Split the given list at the given zero-based index. - */ - public func splitAt(n : Nat, xs : List) : (List, List) { - if (n == 0) { - (null, xs) - } else { - func rec(n : Nat, xs : List) : (List, List) { - switch (pop(xs)) { - case (null, _) { - (null, null) - }; - case (?h, t) { - if (n == 1) { - (singleton(h), t) - } else { - let (l, r) = rec(n - 1, t); - (push(h, l), r) + splits the given list at the given zero-based index. + */ + public let splitAt : (Nat, List) -> (List, List) = + func(n : Nat, xs : List) : (List, List) { + if (n == 0) { + (null, xs) + } else { + func rec(n : Nat, xs : List) : (List, List) { + switch (pop(xs)) { + case (null, _) { + (null, null) + }; + case (?h, t) { + if (n == 1) { + (singleton(h), t) + } else { + let (l, r) = rec(n - 1, t); + (push(h, l), r) + } } } - } - }; - rec(n, xs) - } - }; + }; + rec(n, xs) + } + }; /** - `chunksOf` - ----------- - Split the given list into length-n chunks. The last chunk will be shorter if - n does not evenly divide the length of the given list. - */ - public func chunksOf(n : Nat, xs : List) : List> { - let (l, r) = splitAt(n, xs); - if (isNil(l)) { - null - } else { - push>(l, chunksOf(n, r)) - } - }; + split the given list into length-n chunks. The last chunk will be shorter if + n does not evenly divide the length of the given list. + */ + public let chunksOf : (Nat, List) -> List> = + func(n : Nat, xs : List) : List> { + let (l, r) = splitAt(n, xs); + if (isNil(l)) { + null + } else { + push>(l, chunksOf(n, r)) + } + }; - public func fromArray(xs : [A]) : List { - Array.foldr>(func (x : A, ys : List) : List { - push(x, ys); - }, nil(), xs); - }; + /** + converts an array into a list. + */ + public let fromArray : [A] -> List = + func(xs : [A]) : List { + Array.foldr>(func (x : A, ys : List) : List { + push(x, ys); + }, nil(), xs); + }; - public func fromArrayMut(xs : [var A]) : List { - fromArray(Array.freeze(xs)); - }; + /** + converts a mutable array into a list. + */ + public let fromArrayMut : [var A] -> List = + func(xs : [var A]) : List { + fromArray(Array.freeze(xs)); + }; - public func toArray(xs : List) : [A] { - let length = len(xs); - var list = xs; - Array.tabulate(length, func (i) { - let popped = pop(list); - list := popped.1; - Option.unwrap(popped.0); - }); - }; + /** + creates an array from the list + */ + public let toArray : List -> [A] = + func(xs : List) : [A] { + let length = len(xs); + var list = xs; + Array.tabulate(length, func (i) { + let popped = pop(list); + list := popped.1; + Option.unwrap(popped.0); + }); + }; - public func toArrayMut(xs : List) : [var A] { - Array.thaw(toArray(xs)); - }; + /** + creates a mutable array from the list + */ + public let toArrayMut : List -> [var A] = + func(xs : List) : [var A] { + Array.thaw(toArray(xs)); + }; -/** +/* To do: -------- diff --git a/stdlib/src/nat.mo b/stdlib/src/nat.mo index 97f9441caaa..150ffb0197b 100644 --- a/stdlib/src/nat.mo +++ b/stdlib/src/nat.mo @@ -1,30 +1,45 @@ +/** +[#mod-nat] += `nat` -- Natural numbers + +Most operations on natural numbers (e.g. addition) are available as built-in operators (`1 + 1`). +This module provides conversion functions. + +The conversions `toNat*` will trap if the number is out of bounds; the conversions `toWord*` will wrap-around. + +*/ + import Prim "mo:prim"; import Int "int"; import Prelude "prelude"; module { - public func add(x : Nat, y : Nat) : Nat { - x + y; - }; public let toText : Nat -> Text = Int.toText; - public let fromWord8 = Prim.word8ToNat; - public let fromWord16 = Prim.word16ToNat; - public let fromWord32 = Prim.word32ToNat; - public let fromWord64 = Prim.word64ToNat; - public let toWord8 = Prim.natToWord8; - public let toWord16 = Prim.natToWord16; - public let toWord32 = Prim.natToWord32; - public let toWord64 = Prim.natToWord64; - - public let fromNat8 = Prim.nat8ToNat; - public let fromNat16 = Prim.nat16ToNat; - public let fromNat32 = Prim.nat32ToNat; - public let fromNat64 = Prim.nat64ToNat; - public let toNat8 = Prim.natToNat8; - public let toNat16 = Prim.natToNat16; - public let toNat32 = Prim.natToNat32; - public let toNat64 = Prim.natToNat64; + public let fromWord8 : Word8 -> Nat = Prim.word8ToNat; + public let fromWord16 : Word16 -> Nat = Prim.word16ToNat; + public let fromWord32 : Word32 -> Nat = Prim.word32ToNat; + public let fromWord64 : Word64 -> Nat = Prim.word64ToNat; + + public let toWord8 : Nat -> Word8 = Prim.natToWord8; + public let toWord16 : Nat -> Word16 = Prim.natToWord16; + public let toWord32 : Nat -> Word32 = Prim.natToWord32; + public let toWord64 : Nat -> Word64 = Prim.natToWord64; + + public let fromNat8 : Nat8 -> Nat = Prim.nat8ToNat; + public let fromNat16 : Nat16 -> Nat = Prim.nat16ToNat; + public let fromNat32 : Nat32 -> Nat = Prim.nat32ToNat; + public let fromNat64 : Nat64 -> Nat = Prim.nat64ToNat; + + public let toNat8 : Nat -> Nat8 = Prim.natToNat8; + public let toNat16 : Nat -> Nat16 = Prim.natToNat16; + public let toNat32 : Nat -> Nat32 = Prim.natToNat32; + public let toNat64 : Nat -> Nat64 = Prim.natToNat64; + + // Remove this? + public func add(x : Nat, y : Nat) : Nat { + x + y; + }; } diff --git a/stdlib/src/none.mo b/stdlib/src/none.mo index 1588c5ab8c7..e61aa95afb2 100644 --- a/stdlib/src/none.mo +++ b/stdlib/src/none.mo @@ -1,5 +1,18 @@ +/** +[#mod-none] += `none` -- The absent value + +The `None` type represents a type with _no_ value, often used to mark dead +code. + +For example, the type `[None]` has only empty lists. +*/ + module { - public func absurd(x : None) : A { + /** + Turns an absurd value into an arbitrary type. + */ + public let absurd : None -> A = func(x: None) : A { switch (x) {}; }; } diff --git a/stdlib/src/option.mo b/stdlib/src/option.mo index 4d271a64514..f8d7440be42 100644 --- a/stdlib/src/option.mo +++ b/stdlib/src/option.mo @@ -1,7 +1,12 @@ +/** +[#mod-option] += `option` -- Optional values +*/ + import P "prelude"; module { -/** +/* Functions for Option types. @@ -9,7 +14,7 @@ Functions for Option types. public type t = ?A; -/*** +/* `isSome` -------------------- @@ -25,7 +30,7 @@ public func isSomeAny(x: ?Any): Bool = public func isSome(x: t): Bool = isSomeAny(x); -/*** +/* `isNull` -------------------- @@ -37,7 +42,7 @@ public func isNullAny(x: ?Any): Bool = not isSome(x); public func isNull(x: t): Bool = not isSome(x); -/*** +/* `unwrap` -------------------- @@ -51,7 +56,7 @@ public func unwrap(x: ?T): T = case (?x_) x_; }; -/*** +/* `unwrapOr` -------------------- @@ -65,7 +70,7 @@ public func unwrapOr(x: ?T, d: T): T = case (?x_) x_; }; -/*** +/* `option` -------------------- @@ -79,7 +84,7 @@ public func option(x: ?A, f: A->B, d: B): B = case (?x_) f(x_); }; -/*** +/* `map` -------------------- @@ -93,7 +98,7 @@ public func map(f: A->B, x: ?A): ?B = case (?x_) ?f(x_); }; -/*** +/* `assertSome` -------------------- @@ -109,7 +114,7 @@ public func assertSomeAny(x: ?Any) = public func assertSome(x: ?A) = assertSomeAny(x); -/*** +/* `assertNull` -------------------- diff --git a/stdlib/src/prelude.mo b/stdlib/src/prelude.mo index 8dc42ff5c0b..998014e578e 100644 --- a/stdlib/src/prelude.mo +++ b/stdlib/src/prelude.mo @@ -1,7 +1,12 @@ +/** +[#mod-prelude] += `prelude` -- General utilities +*/ + import Prim "mo:prim"; module { -/** +/* Stdlib prelude =============== @@ -12,7 +17,7 @@ some further experience and discussion. Until then, they live here. */ -/*** +/* `printLn` --------- @@ -24,7 +29,7 @@ public func printLn(x : Text) { Prim.debugPrint(x # "\n"); }; -/*** +/* `nyi`: Not yet implemented ----------------------------- @@ -42,7 +47,7 @@ public func nyi() : None = public func xxx() : None = { assert false ; loop { } }; -/*** +/* `unreachable` -------------------- diff --git a/stdlib/src/result.mo b/stdlib/src/result.mo index 2f7461de9ec..43f8d318168 100644 --- a/stdlib/src/result.mo +++ b/stdlib/src/result.mo @@ -1,8 +1,13 @@ +/** +[#mod-result] += `result` -- Error-annotated values +*/ + import P "prelude"; import Array "array"; module { -/** +/* Result ========= @@ -22,7 +27,7 @@ public type Result = { -/** +/* `assertUnwrap` --------------- assert that we can unwrap the result; should only be used in tests, not in canister implementations. This will trap. @@ -34,7 +39,7 @@ public func assertUnwrap(r:Result):Ok { } }; -/** +/* `assertUnwrapAny` --------------- */ @@ -45,7 +50,7 @@ public func assertUnwrapAny(r:Result):Ok { } }; -/** +/* `assertOk` --------------- */ @@ -56,7 +61,7 @@ public func assertOk(r:Result) { } }; -/** +/* `assertErr` --------------- */ @@ -67,14 +72,14 @@ public func assertErr(r:Result) { } }; -/** +/* `assertErrIs` --------------- */ public func assertErrIs(r:Result, f:E->Bool) : Bool = assertErrAs(r, f); -/** +/* `assertErrAs` --------------- */ @@ -85,7 +90,7 @@ public func assertErrAs(r:Result, f:E->X) : X { } }; -/** +/* `bind` ------- bind operation in result monad. @@ -100,7 +105,7 @@ public func bind( }; -/** +/* `mapOk` ------- map the `Ok` type/value, leaving any `Error` type/value unchanged. @@ -114,7 +119,7 @@ public func mapOk( } }; -/** +/* `fromOption` -------------- create a result from an option, including an error value to handle the `null` case. @@ -126,7 +131,7 @@ public func fromOption(x:?R, err:E):Result { } }; -/** +/* `fromSomeMap` -------------- map the `Ok` type/value from the optional value, or else use the given error value. @@ -138,7 +143,7 @@ public func fromSomeMap(x:?R1, f:R1->R2, err:E):Result { } }; -/** +/* `fromSome` --------------- asserts that the option is Some(_) form. @@ -150,7 +155,7 @@ public func fromSome(o:?Ok):Result { } }; -/** +/* `joinArrayIfOk` --------------- a result that consists of an array of Ok results from an array of results, or the first error in the result array, if any. diff --git a/stdlib/src/text.mo b/stdlib/src/text.mo index e78678500be..494b0b9e65f 100644 --- a/stdlib/src/text.mo +++ b/stdlib/src/text.mo @@ -1,13 +1,24 @@ +/** +[#mod-text] += `text` -- Text values + +This type describes a valid, human-readable text. It does not contain arbitrary +binary data. +*/ + import Iter "iter"; module { + // remove? public func append(x : Text, y : Text) : Text { x # y; }; - public func toIter(text : Text) : Iter.Iter { - { next = text.chars().next } - } + /** + Creates an <> that traverses the characters of the text. + */ + public let toIter : Text -> Iter.Iter = + func(text) = text.chars() } diff --git a/stdlib/src/trie.mo b/stdlib/src/trie.mo index 9783e2eb9e8..ab9037e74cd 100644 --- a/stdlib/src/trie.mo +++ b/stdlib/src/trie.mo @@ -1,3 +1,8 @@ +/** +[#mod-trie] += `trie` -- Functional map +*/ + import Prim "mo:prim"; import P "prelude"; import Option "option"; @@ -8,7 +13,7 @@ import List "list"; import AssocList "assocList"; module { -/** +/* Hash tries ====================== @@ -31,7 +36,7 @@ these trees never do). */ -/** +/* Representation ===================== @@ -88,28 +93,28 @@ public type Hash = Hash.t; public type List = List.List; public type AssocList = AssocList.AssocList; -/** A `Key` for the trie has an associated hash value */ +/* A `Key` for the trie has an associated hash value */ public type Key = { - /** `hash` permits fast inequality checks, and permits collisions */ + /* `hash` permits fast inequality checks, and permits collisions */ hash: Hash; - /** `key` permits percise equality checks, but only used after equal hashes. */ + /* `key` permits percise equality checks, but only used after equal hashes. */ key: K; }; -/** Equality function for two `Key`s, in terms of equality of `K`'s. */ +/* Equality function for two `Key`s, in terms of equality of `K`'s. */ public func keyEq(keq:(K,K) -> Bool) : ((Key,Key) -> Bool) = { func (key1:Key, key2:Key) : Bool = label profile_trie_keyEq : Bool (Hash.hashEq(key1.hash, key2.hash) and keq(key1.key, key2.key)) }; -/** leaf nodes of trie consist of key-value pairs as a list. */ +/* leaf nodes of trie consist of key-value pairs as a list. */ public type Leaf = { count : Nat ; keyvals : AssocList,V> ; }; -/** branch nodes of the trie discriminate on a bit position of the keys' hashes. +/* branch nodes of the trie discriminate on a bit position of the keys' hashes. we never store this bitpos; rather, we enforce a style where this position is always known from context. */ @@ -119,7 +124,7 @@ public type Branch = { right : Trie ; }; -/** binary hash tries: either empty, a leaf node, or a branch node */ +/* binary hash tries: either empty, a leaf node, or a branch node */ public type Trie = { #empty ; #leaf : Leaf ; @@ -180,7 +185,7 @@ public func isValid (t:Trie, enforceNormal:Bool) : Bool { }; -/** +/* Two-dimensional trie --------------------- A 2D trie is just a trie that maps dimension-1 keys to another @@ -188,7 +193,7 @@ public func isValid (t:Trie, enforceNormal:Bool) : Bool { */ public type Trie2D = Trie >; -/** +/* Three-dimensional trie --------------------- A 3D trie is just a trie that maps dimension-1 keys to another @@ -196,12 +201,12 @@ public type Trie2D = Trie >; */ public type Trie3D = Trie >; -/** +/* Module interface =================== */ - /** + /* `empty` -------- An empty trie. @@ -209,7 +214,7 @@ public type Trie3D = Trie >; public func empty() : Trie = #empty; - /** + /* `count` -------- Get the number of key-value pairs in the trie, in constant time. @@ -228,7 +233,7 @@ public func count(t: Trie) : Nat = label profile_trie_count : Nat { } }; - /** + /* `branch` -------- Construct a branch node, computing the count stored there. @@ -244,7 +249,7 @@ public func branch(l:Trie, r:Trie) : Trie = label profile_tr ); }; - /** + /* `leaf` -------- Construct a leaf node, computing the count stored there. @@ -321,14 +326,14 @@ public func fromSizedList(kvc:?Nat, kvs:AssocList,V>, bitpos:Nat) : rec(kvc, kvs, bitpos) }; - /** + /* `copy` --------- Purely-functional representation permits _O(1)_-time copy, via persistent sharing. */ public func copy(t : Trie) : Trie = t; - /** + /* `replace` --------- replace the given key's value option with the given one, returning the previous one @@ -368,7 +373,7 @@ public func replace(t : Trie, k:Key, k_eq:(K,K)->Bool, v:?V) : (Tri (to, vo) }; - /** + /* `insert` ------------ insert the given key's value in the trie; return the new trie, and the previous value associated with the key, if any @@ -378,7 +383,7 @@ public func insert(t : Trie, k:Key, k_eq:(K,K)->Bool, v:V) : (Trie< replace(t, k, k_eq, ?v) }; -/** +/* `find` --------- find the given key's value in the trie, or return null if nonexistent @@ -447,7 +452,7 @@ public func splitSizedList(l:AssocList,V>, bitpos:Nat) rec(l) }; - /** + /* `merge` --------- merge tries, preferring the right trie where there are collisions @@ -501,7 +506,7 @@ public func merge(tl:Trie, tr:Trie, k_eq:(K,K)->Bool) : Trie rec(0, tl, tr) }; - /** + /* `mergeDisjoint` ---------------- like `merge`, it merges tries, but unlike `merge`, it signals a @@ -551,7 +556,7 @@ public func mergeDisjoint(tl:Trie, tr:Trie, k_eq:(K,K)->Bool): Tr rec(0, tl, tr) }; - /** + /* `diff` ------ The key-value pairs of the final trie consists of those pairs of @@ -596,7 +601,7 @@ public func diff(tl:Trie, tr:Trie, k_eq:(K,K)->Bool): Trie rec(0, tl, tr) }; - /** + /* `disj` -------- @@ -635,7 +640,7 @@ public func disj( func br3(l:Trie, r:Trie) : Trie = branch(l,r); func lf3(kvs:AssocList,X>, bitpos:Nat) : Trie = leaf(kvs, bitpos); - /** empty right case; build from left only: */ + /* empty right case; build from left only: */ func recL(t:Trie, bitpos:Nat) : Trie { switch t { case (#empty) #empty; @@ -645,7 +650,7 @@ public func disj( case (#branch(b)) { br3(recL(b.left,bitpos+1),recL(b.right,bitpos+1)) }; } }; - /** empty left case; build from right only: */ + /* empty left case; build from right only: */ func recR(t:Trie, bitpos:Nat) : Trie { switch t { case (#empty) #empty; @@ -656,7 +661,7 @@ public func disj( } }; - /** main recursion */ + /* main recursion */ func rec(bitpos:Nat, tl:Trie, tr:Trie) : Trie { func lf1(kvs:AssocList,V>) : Trie = leaf(kvs, bitpos); func lf2(kvs:AssocList,W>) : Trie = leaf(kvs, bitpos); @@ -686,7 +691,7 @@ public func disj( rec(0, tl, tr) }; - /** + /* `join` --------- This operation generalizes the notion of "set intersection" to @@ -742,7 +747,7 @@ public func disj( rec(0, tl, tr) }; - /** + /* `foldUp` ------------ This operation gives a recursor for the internal structure of @@ -768,7 +773,7 @@ public func disj( }; - /** + /* `prod` --------- @@ -796,11 +801,11 @@ public func disj( ) : Trie { - /**- binary case: merge disjoint results: */ + /*- binary case: merge disjoint results: */ func merge (a:Trie, b:Trie) : Trie = mergeDisjoint(a, b, k3_eq); - /**- "`foldUp` squared" (imagine two nested loops): */ + /*- "`foldUp` squared" (imagine two nested loops): */ foldUp>( tl, merge, func (k1:K1, v1:V1) : Trie { @@ -820,7 +825,7 @@ public func disj( }; - /** + /* Build: An ADT for "Trie Builds" ======================================== @@ -842,7 +847,7 @@ public func disj( */ public module Build { - /** Commands for building tries. + /* Commands for building tries. For PL academics: Imagine commands for the IMP imperative language, but where global memory consists of a single (anonymous) global trie */ @@ -871,7 +876,7 @@ public func disj( #seq { count = sum; left = l; right = r } }; - /** + /* `prodBuild` --------------- @@ -906,7 +911,7 @@ public func disj( buildSeq(a, b) }; - /**- "`foldUp` squared" (imagine two nested loops): */ + /*- "`foldUp` squared" (imagine two nested loops): */ foldUp>( tl, outer_bin, func (k1:K1, v1:V1) : TrieBuild { @@ -925,7 +930,7 @@ public func disj( ) }; - /** + /* `buildNth` -------- Project the nth key-value pair from the trie build. @@ -953,7 +958,7 @@ public func disj( rec(tb, i) }; - /** + /* `projectInnerBuild` -------------- @@ -971,7 +976,7 @@ public func disj( #skip ) }; - /** + /* `buildToArray` -------- Gather the collection of key-value pairs into an array of a (possibly-distinct) type. @@ -989,7 +994,7 @@ public func disj( a }; - /** + /* `buildToArray2` -------- Gather the collection of key-value pairs into an array of a (possibly-distinct) type. @@ -1013,7 +1018,7 @@ public func disj( }; - /** + /* `fold` --------- Fold over the key-value pairs of the trie, using an accumulator. @@ -1036,7 +1041,7 @@ public func disj( }; - /** + /* `exists` -------- Test whether a given key-value pair is present, or not. @@ -1056,7 +1061,7 @@ public func disj( rec(t) }; - /** + /* `forAll` --------- Test whether all key-value pairs have a given property. @@ -1076,7 +1081,7 @@ public func disj( rec(t) }; - /** + /* `nth` -------- Project the nth key-value pair from the trie. @@ -1104,7 +1109,7 @@ public func disj( }; - /** + /* `toArray` -------- Gather the collection of key-value pairs into an array of a (possibly-distinct) type. @@ -1144,7 +1149,7 @@ public func disj( a }; - /** + /* `isEmpty` ----------- specialized foldUp operation. @@ -1155,7 +1160,7 @@ public func disj( public func isEmpty(t:Trie) : Bool = count(t) == 0; - /** + /* `filter` ----------- filter the key-value pairs by a given predicate. @@ -1189,7 +1194,7 @@ public func disj( rec(t, 0) }; - /** + /* `mapFilter` ----------- map and filter the key-value pairs by a given predicate. @@ -1228,7 +1233,7 @@ public func disj( rec(t, 0) }; - /** + /* `equalStructure` ------------------ @@ -1265,7 +1270,7 @@ public func disj( rec(tl,tr) }; - /** + /* `replaceThen` ------------ replace the given key's value in the trie, @@ -1284,7 +1289,7 @@ public func disj( } }; - /** + /* `insertFresh` ---------------- insert the given key's value in the trie; return the new trie; assert that no prior value is associated with the key @@ -1298,7 +1303,7 @@ public func disj( t2 }; - /** + /* `insert2D` --------------- insert the given key's value in the 2D trie; return the new 2D trie. @@ -1318,7 +1323,7 @@ public func disj( updated_outer; }; - /** + /* `insert3D` --------------- insert the given key's value in the trie; return the new trie; @@ -1353,7 +1358,7 @@ public func disj( updated_outer; }; - /** + /* `remove` ------------- remove the given key's value in the trie; return the new trie @@ -1362,7 +1367,7 @@ public func disj( replace(t, k, k_eq, null) }; - /** + /* `removeThen` ------------ remove the given key's value in the trie, @@ -1382,7 +1387,7 @@ public func disj( }; - /** + /* `remove2D` -------------- remove the given key-key pair's value in the 2D trie; return the @@ -1407,7 +1412,7 @@ public func disj( } }; - /** + /* `remove3D` --------------- remove the given key-key pair's value in the 3D trie; return the @@ -1437,7 +1442,7 @@ public func disj( - /** + /* `mergeDisjoint2D` -------------- @@ -1457,7 +1462,7 @@ public func disj( }; -/** +/* Future work ============= diff --git a/stdlib/src/trieMap.mo b/stdlib/src/trieMap.mo index 71beca9662b..2f761202648 100644 --- a/stdlib/src/trieMap.mo +++ b/stdlib/src/trieMap.mo @@ -1,10 +1,15 @@ +/** +[#mod-trieMap] += `trieMap` -- Functional map +*/ + import T "trie"; import P "prelude"; import I "iter"; import Hash "hash"; import List "list"; -/** +/* Trie Map ========================= diff --git a/stdlib/src/trieSet.mo b/stdlib/src/trieSet.mo index 1315ea9cc0c..7c0bb85a95b 100644 --- a/stdlib/src/trieSet.mo +++ b/stdlib/src/trieSet.mo @@ -1,4 +1,9 @@ /** +[#mod-trieSet] += `trieSet` -- Functional set +*/ + +/* Trie-based Sets ================ From 3236ff9ccd6912a2cdbc82cae12eba3f05b59f4d Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Wed, 29 Jan 2020 18:07:55 -0700 Subject: [PATCH 1010/1176] fix correctness bug in Buf --- stdlib/src/buf.mo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/src/buf.mo b/stdlib/src/buf.mo index 2a62bcada9f..18d96c82749 100644 --- a/stdlib/src/buf.mo +++ b/stdlib/src/buf.mo @@ -103,7 +103,7 @@ public class Buf (initCapacity : Nat) { public func toArray() : [X] = // immutable clone of array A.tabulate( - elems.len(), + count, func(x: Nat): X { elems[x] } ); From 3f1b4e5d1ebbd28efa1f4c2fad34123ae7501cf2 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Wed, 29 Jan 2020 18:13:03 -0700 Subject: [PATCH 1011/1176] add regression test for bug fix --- stdlib/test/bufTest.mo | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/stdlib/test/bufTest.mo b/stdlib/test/bufTest.mo index 08625f11512..8f677f90d90 100644 --- a/stdlib/test/bufTest.mo +++ b/stdlib/test/bufTest.mo @@ -18,5 +18,16 @@ for (i in I.range(0, 123)) { b.append(a); }; +// regression test: buffers with extra space are converted to arrays of the correct length +let bigLen = 100; +let len = 3; +let c = B.Buf(bigLen); +assert (len < bigLen) +for (i in I.range(0, len)) { + b.append(c); +}; +assert (b.toArray().len() == len); +assert (b.toVarArray().len() == len); + Prim.debugPrint(debug_show(a.toArray())); Prim.debugPrint(debug_show(b.toArray())); From 9af8a98b97e12e2053c3b17f79bcb02b1bcd8bc3 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Wed, 29 Jan 2020 18:22:25 -0700 Subject: [PATCH 1012/1176] fix test, extend test; another bug fix --- stdlib/src/buf.mo | 2 +- stdlib/test/bufTest.mo | 29 ++++++++++++++++++----------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/stdlib/src/buf.mo b/stdlib/src/buf.mo index 18d96c82749..1a4b57bdb03 100644 --- a/stdlib/src/buf.mo +++ b/stdlib/src/buf.mo @@ -110,7 +110,7 @@ public class Buf (initCapacity : Nat) { public func toVarArray() : [var X] = { if (count == 0) { [var] } else { let a = A.init(count, elems[0]); - for (i in elems.keys()) { + for (i in I.range(0, count - 1)) { a[i] := elems[i] }; a diff --git a/stdlib/test/bufTest.mo b/stdlib/test/bufTest.mo index 8f677f90d90..0f9ca69666a 100644 --- a/stdlib/test/bufTest.mo +++ b/stdlib/test/bufTest.mo @@ -18,16 +18,23 @@ for (i in I.range(0, 123)) { b.append(a); }; -// regression test: buffers with extra space are converted to arrays of the correct length -let bigLen = 100; -let len = 3; -let c = B.Buf(bigLen); -assert (len < bigLen) -for (i in I.range(0, len)) { - b.append(c); -}; -assert (b.toArray().len() == len); -assert (b.toVarArray().len() == len); - Prim.debugPrint(debug_show(a.toArray())); Prim.debugPrint(debug_show(b.toArray())); + +// regression test: buffers with extra space are converted to arrays of the correct length +{ + let bigLen = 100; + let len = 3; + let c = B.Buf(bigLen); + assert (len < bigLen); + for (i in I.range(0, len - 1)) { + Prim.debugPrint(debug_show(i)); + c.add(i); + }; + Prim.debugPrint(debug_show(c.len())); + assert (c.len() == len); + Prim.debugPrint(debug_show(c.len())); + assert (c.toArray().len() == len); + Prim.debugPrint(debug_show(c.len())); + assert (c.toVarArray().len() == len); +} From 1fe00c9d9ab6b84ce75931c0bc60f4ba423b38ab Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Thu, 30 Jan 2020 16:42:24 +0000 Subject: [PATCH 1013/1176] Claudio/syntax errors (#1167) * prep work for generic syntax error reporting * error reporting files * working; needs cleanup * print_symbol bugs * add dummy start production to ensure parse stack non-empty (ErrorReporting bug workaround); echo unexpected token; add tests * echo unexpected token * re-abstract operators when printing to compress explanations * update error message and tests * only report expected tokens or phrases on error * forgot some binops * identify SEMICOLON & SEMICOLON_EOL; add new error mode reporting expected symbol*s*; rank by length then lex-order * updates test * refactoring * refactor stuff from pipeline into new parsing.ml; add error-detail flag and arg * default error-detail to 2 * remove dead definition * add --error-detail to mo-ide; update lsp tests using --error-detial 0 * add newlines to tests * update node-test.js --- src/exes/mo_ide.ml | 1 + src/exes/moc.ml | 14 +- src/mo_config/args.ml | 5 + src/mo_config/args.mli | 1 + src/mo_config/flags.ml | 1 + src/mo_frontend/dune | 4 +- src/mo_frontend/error_reporting.ml | 113 +++++++++++ src/mo_frontend/error_reporting.mli | 7 + src/mo_frontend/menhir_error_reporting.ml | 180 +++++++++++++++++ src/mo_frontend/menhir_error_reporting.mli | 79 ++++++++ src/mo_frontend/parser.mly | 48 ++++- src/mo_frontend/parsing.ml | 83 ++++++++ src/mo_frontend/parsing.mli | 15 ++ src/mo_frontend/printers.ml | 217 +++++++++++++++++++++ src/mo_frontend/printers.mli | 11 ++ src/pipeline/pipeline.ml | 19 +- test/fail/ok/syntax1.tc.ok | 3 + test/fail/ok/syntax1.tc.ret.ok | 1 + test/fail/ok/syntax2.tc.ok | 18 ++ test/fail/ok/syntax2.tc.ret.ok | 1 + test/fail/ok/syntax3.tc.ok | 18 ++ test/fail/ok/syntax3.tc.ret.ok | 1 + test/fail/ok/syntax4.tc.ok | 5 + test/fail/ok/syntax4.tc.ret.ok | 1 + test/fail/ok/syntax5.tc.ok | 18 ++ test/fail/ok/syntax5.tc.ret.ok | 1 + test/fail/ok/syntax6.tc.ok | 18 ++ test/fail/ok/syntax6.tc.ret.ok | 1 + test/fail/ok/syntax7.tc.ok | 4 + test/fail/ok/syntax7.tc.ret.ok | 1 + test/fail/syntax1.mo | 1 + test/fail/syntax2.mo | 2 + test/fail/syntax3.mo | 1 + test/fail/syntax4.mo | 1 + test/fail/syntax5.mo | 2 + test/fail/syntax6.mo | 1 + test/fail/syntax7.mo | 31 +++ test/lsp-int/Main.hs | 6 +- test/node-test.js | 4 +- 39 files changed, 915 insertions(+), 23 deletions(-) create mode 100644 src/mo_frontend/error_reporting.ml create mode 100644 src/mo_frontend/error_reporting.mli create mode 100644 src/mo_frontend/menhir_error_reporting.ml create mode 100644 src/mo_frontend/menhir_error_reporting.mli create mode 100644 src/mo_frontend/parsing.ml create mode 100644 src/mo_frontend/parsing.mli create mode 100644 src/mo_frontend/printers.ml create mode 100644 src/mo_frontend/printers.mli create mode 100644 test/fail/ok/syntax1.tc.ok create mode 100644 test/fail/ok/syntax1.tc.ret.ok create mode 100644 test/fail/ok/syntax2.tc.ok create mode 100644 test/fail/ok/syntax2.tc.ret.ok create mode 100644 test/fail/ok/syntax3.tc.ok create mode 100644 test/fail/ok/syntax3.tc.ret.ok create mode 100644 test/fail/ok/syntax4.tc.ok create mode 100644 test/fail/ok/syntax4.tc.ret.ok create mode 100644 test/fail/ok/syntax5.tc.ok create mode 100644 test/fail/ok/syntax5.tc.ret.ok create mode 100644 test/fail/ok/syntax6.tc.ok create mode 100644 test/fail/ok/syntax6.tc.ret.ok create mode 100644 test/fail/ok/syntax7.tc.ok create mode 100644 test/fail/ok/syntax7.tc.ret.ok create mode 100644 test/fail/syntax1.mo create mode 100644 test/fail/syntax2.mo create mode 100644 test/fail/syntax3.mo create mode 100644 test/fail/syntax4.mo create mode 100644 test/fail/syntax5.mo create mode 100644 test/fail/syntax6.mo create mode 100644 test/fail/syntax7.mo diff --git a/src/exes/mo_ide.ml b/src/exes/mo_ide.ml index 40c10a22562..074eacd46fe 100644 --- a/src/exes/mo_ide.ml +++ b/src/exes/mo_ide.ml @@ -16,6 +16,7 @@ let argspec = Arg.String set_entry_point, " specifies the entry point for the current project" ] + @ Args.error_args @ Args.package_args let () = diff --git a/src/exes/moc.ml b/src/exes/moc.ml index f29c0dca59f..91e18661e64 100644 --- a/src/exes/moc.ml +++ b/src/exes/moc.ml @@ -28,8 +28,7 @@ let link = ref true let interpret_ir = ref false let gen_source_map = ref false -let argspec = Arg.align -[ +let argspec = Arg.align [ "-c", Arg.Unit (set_mode Compile), " compile programs to WebAssembly"; "-r", Arg.Unit (set_mode Run), " interpret programs"; "-i", Arg.Unit (set_mode Interact), " run interactive REPL (implies -r)"; @@ -40,14 +39,21 @@ let argspec = Arg.align "-v", Arg.Set Flags.verbose, " verbose output"; "-p", Arg.Set_int Flags.print_depth, " set print depth"; - "--hide-warnings", Arg.Clear Flags.print_warnings, " hide warnings"; + "--hide-warnings", Arg.Clear Flags.print_warnings, " hide warnings"; ] + + @ Args.error_args + + @ [ "--version", Arg.Unit (fun () -> printf "%s\n%!" banner; exit 0), " show version"; "--map", Arg.Set gen_source_map, " output source map"; "-t", Arg.Set Flags.trace, " activate tracing in interpreters"] - @ Args.package_args @ [ + + @ Args.package_args + + @ [ "--profile", Arg.Set Flags.profile, " activate profiling counters in interpreters "; "--profile-file", Arg.Set_string Flags.profile_file, " set profiling output file "; "--profile-line-prefix", Arg.Set_string Flags.profile_line_prefix, " prefix each profile line with the given string "; diff --git a/src/mo_config/args.ml b/src/mo_config/args.ml index c6d65296069..df6fee6cc68 100644 --- a/src/mo_config/args.ml +++ b/src/mo_config/args.ml @@ -21,3 +21,8 @@ let package_args = [ "--actor-idl", Arg.String (fun fp -> Flags.actor_idl_path := Some fp), " path to actor IDL files"; string_map "--actor-alias" Flags.actor_aliases " actor import alias" ] + +let error_args = [ + "--error-detail", Arg.Set_int Flags.error_detail, " set error message detail for syntax errors" + (* TODO move --hide-warnings here? *) + ] diff --git a/src/mo_config/args.mli b/src/mo_config/args.mli index b70076ade3d..0978172d70a 100644 --- a/src/mo_config/args.mli +++ b/src/mo_config/args.mli @@ -1 +1,2 @@ +val error_args : (Arg.key * Arg.spec * Arg.doc) list val package_args : (Arg.key * Arg.spec * Arg.doc) list diff --git a/src/mo_config/flags.ml b/src/mo_config/flags.ml index 4d16f401570..23e05953f81 100644 --- a/src/mo_config/flags.ml +++ b/src/mo_config/flags.ml @@ -26,3 +26,4 @@ let profile_file = ref "profiling-counters.csv" let profile_line_prefix = ref "" let profile_field_names : string list ref = ref [] let compiled = ref false +let error_detail = ref 2; diff --git a/src/mo_frontend/dune b/src/mo_frontend/dune index 5d5caccba3f..9f767a6e2c0 100644 --- a/src/mo_frontend/dune +++ b/src/mo_frontend/dune @@ -1,10 +1,10 @@ (library (name mo_frontend) - (libraries lib lang_utils mo_config mo_def mo_types mo_values) + (libraries menhirLib lib lang_utils mo_config mo_def mo_types mo_values) ) (menhir (modules parser) - (flags -v --strict) + (flags --table --inspection -v --strict) (infer false) ) (ocamllex lexer) diff --git a/src/mo_frontend/error_reporting.ml b/src/mo_frontend/error_reporting.ml new file mode 100644 index 00000000000..1f6500c1e0d --- /dev/null +++ b/src/mo_frontend/error_reporting.ml @@ -0,0 +1,113 @@ +open Parser +open Parser.MenhirInterpreter + +(* In order to submit artificial tokens to the parser, we need a function that + converts a terminal symbol to a (dummy) token. Unfortunately, we cannot (in + general) auto-generate this code, because it requires making up semantic + values of arbitrary OCaml types. *) + +let terminal2token (type a) (symbol : a terminal) : token = + match symbol with + | T_error -> assert false + | T_XOROP -> XOROP + | T_XORASSIGN -> XORASSIGN + | T_WHILE -> WHILE + | T_VAR -> VAR + | T_USHROP -> USHROP + | T_USHRASSIGN -> USHRASSIGN + | T_UNDERSCORE -> UNDERSCORE + | T_TYPE -> TYPE + | T_TRY -> TRY + | T_THROW -> THROW + | T_TEXT -> TEXT "..." + | T_SWITCH -> SWITCH + | T_SUBOP -> SUBOP + | T_SUB -> SUB + | T_SSHROP -> SSHROP + | T_SSHRASSIGN -> SSHRASSIGN + | T_SHLOP -> SHLOP + | T_SHLASSIGN -> SHLASSIGN + | T_SHARED -> SHARED + | T_SEMICOLON_EOL -> SEMICOLON_EOL + | T_SEMICOLON -> SEMICOLON + | T_RPAR -> RPAR + | T_ROTROP -> ROTROP + | T_ROTRASSIGN -> ROTRASSIGN + | T_ROTLOP -> ROTLOP + | T_ROTLASSIGN -> ROTLASSIGN + | T_RETURN -> RETURN + | T_RCURLY -> RCURLY + | T_RBRACKET -> RBRACKET + | T_QUEST -> QUEST + | T_QUERY -> QUERY + | T_PUBLIC -> PUBLIC + | T_PRIVATE -> PRIVATE + | T_PRIM -> PRIM + | T_POWOP -> POWOP + | T_POWASSIGN -> POWASSIGN + | T_PLUSASSIGN -> PLUSASSIGN + | T_OROP -> OROP + | T_ORASSIGN -> ORASSIGN + | T_OR -> OR + | T_OBJECT -> OBJECT + | T_NULL -> NULL + | T_NOT -> NOT + | T_NEQOP -> NEQOP + | T_NAT -> NAT "" + | T_MULOP -> MULOP + | T_MULASSIGN -> MULASSIGN + | T_MODULE -> MODULE + | T_MODOP -> MODOP + | T_MODASSIGN -> MODASSIGN + | T_MINUSASSIGN -> MINUSASSIGN + | T_LTOP -> LTOP + | T_LT -> LT + | T_LPAR -> LPAR + | T_LOOP -> LOOP + | T_LET -> LET + | T_LEOP -> LEOP + | T_LCURLY -> LCURLY + | T_LBRACKET -> LBRACKET + | T_LABEL -> LABEL + | T_IN -> IN + | T_IMPORT -> IMPORT + | T_IGNORE -> IGNORE + | T_IF -> IF + | T_ID -> ID "" + | T_HASH -> HASH + | T_GTOP -> GTOP + | T_GT -> GT + | T_GEOP -> GEOP + | T_FUNC -> FUNC + | T_FOR -> FOR + | T_FLOAT -> FLOAT "" + | T_EQOP -> EQOP + | T_EQ -> EQ + | T_EOF -> EOF + | T_ELSE -> ELSE + | T_DOT_NUM -> DOT_NUM "" + | T_DOT -> DOT + | T_DIVOP -> DIVOP + | T_DIVASSIGN -> DIVASSIGN + | T_DEBUG_SHOW -> DEBUG_SHOW + | T_DEBUG -> DEBUG + | T_CONTINUE -> CONTINUE + | T_COMMA -> COMMA + | T_COLON -> COLON + | T_CLASS -> CLASS + | T_CHAR -> CHAR 0 + | T_CATCH -> CATCH + | T_CATASSIGN -> CATASSIGN + | T_CASE -> CASE + | T_BREAK -> BREAK + | T_BOOL -> BOOL false + | T_AWAIT -> AWAIT + | T_ASYNC -> ASYNC + | T_ASSIGN -> ASSIGN + | T_ASSERT -> ASSERT + | T_ARROW -> ARROW + | T_ANDOP -> ANDOP + | T_ANDASSIGN -> ANDASSIGN + | T_AND -> AND + | T_ADDOP -> ADDOP + | T_ACTOR -> ACTOR diff --git a/src/mo_frontend/error_reporting.mli b/src/mo_frontend/error_reporting.mli new file mode 100644 index 00000000000..5b9e4d471f4 --- /dev/null +++ b/src/mo_frontend/error_reporting.mli @@ -0,0 +1,7 @@ +open Parser.MenhirInterpreter + +(* This module offers the functionality required by the functor + [ErrorReporting.Printers.Make]. *) + +val terminal2token: _ terminal -> token + diff --git a/src/mo_frontend/menhir_error_reporting.ml b/src/mo_frontend/menhir_error_reporting.ml new file mode 100644 index 00000000000..6ae06903efe --- /dev/null +++ b/src/mo_frontend/menhir_error_reporting.ml @@ -0,0 +1,180 @@ +module Make + (I : MenhirLib.IncrementalEngine.EVERYTHING) + (User : sig + + (* In order to submit artificial tokens to the parser, we need a function + that converts a terminal symbol to a token. Unfortunately, we cannot + (in general) auto-generate this code, because it requires making up + semantic values of arbitrary OCaml types. *) + + val terminal2token: _ I.terminal -> I.token + + end) += struct + + open MenhirLib.General + open I + open User + + (* ------------------------------------------------------------------------ *) + + (* Explanations. *) + + type explanation = { + item: item; + past: (xsymbol * Lexing.position * Lexing.position) list + } + + let item explanation = + explanation.item + + let past explanation = + explanation.past + + let future explanation = + let prod, index = explanation.item in + let rhs = rhs prod in + drop index rhs + + let goal explanation = + let prod, _ = explanation.item in + lhs prod + + (* ------------------------------------------------------------------------ *) + + (* [items_current env] assumes that [env] is not an initial state (which + implies that the stack is non-empty). Under this assumption, it extracts + the automaton's current state, i.e., the LR(1) state found in the top + stack cell. It then goes through [items] so as to obtain the LR(0) items + associated with this state. *) + + let items_current env : item list = + (* Get the current state. *) + match Lazy.force (stack env) with + | Nil -> + (* If we get here, then the stack is empty, which means the parser + is in an initial state. This should not happen. *) + invalid_arg "items_current" (* TEMPORARY it DOES happen! *) + | Cons (Element (current, _, _, _), _) -> + (* Extract the current state out of the top stack element, and + convert it to a set of LR(0) items. Returning a set of items + instead of an ['a lr1state] is convenient; returning [current] + would require wrapping it in an existential type. *) + items current + + (* [is_shift_item t item] determines whether [item] justifies a shift + transition along the terminal symbol [t]. *) + + let is_shift_item (t : _ terminal) (prod, index) : bool = + let rhs = rhs prod in + let length = List.length rhs in + assert (0 < index && index <= length); + (* We test that there is one symbol after the bullet and this symbol + is [t] or can generate a word that begins with [t]. (Note that we + don't need to worry about the case where this symbol is nullable + and [t] is generated by the following symbol. In that situation, + we would have to reduce before we can shift [t].) *) + index < length && xfirst (List.nth rhs index) t + + let compare_explanations x1 x2 = + let c = compare_items x1.item x2.item in + (* TEMPORARY checking that if [c] is 0 then the positions are the same *) + assert ( + c <> 0 || List.for_all2 (fun (_, start1, end1) (_, start2, end2) -> + start1.Lexing.pos_cnum = start2.Lexing.pos_cnum && + end1.Lexing.pos_cnum = end2.Lexing.pos_cnum + ) x1.past x2.past + ); + c + + (* [marry past stack] TEMPORARY comment *) + + let rec marry past stack = + match past, stack with + | [], _ -> + [] + | symbol :: past, lazy (Cons (Element (s, _, startp, endp), stack)) -> + assert (compare_symbols symbol (X (incoming_symbol s)) = 0); + (symbol, startp, endp) :: marry past stack + | _ :: _, lazy Nil -> + assert false + + (* [accumulate t env explanations] is called if the parser decides to shift + the test token [t]. The parameter [env] describes the parser configuration + before it shifts this token. (Some reductions have taken place.) We use the + shift items found in [env] to produce new explanations. *) + + let accumulate (t : _ terminal) env explanations = + (* The parser is about to shift, which means it is willing to + consume the terminal symbol [t]. In the state before the + transition, look at the items that justify shifting [t]. + We view these items as explanations: they explain what + we have read and what we expect to read. *) + let stack = stack env in + List.fold_left (fun explanations item -> + if is_shift_item t item then + let prod, index = item in + let rhs = rhs prod in + { + item = item; + past = List.rev (marry (List.rev (take index rhs)) stack) + } :: explanations + else + explanations + ) explanations (items_current env) + (* TEMPORARY [env] may be an initial state! + violating [item_current]'s precondition *) + + (* [investigate pos checkpoint] assumes that [checkpoint] is of the form + [InputNeeded _]. For every terminal symbol [t], it investigates + how the parser reacts when fed the symbol [t], and returns a list + of explanations. The position [pos] is where a syntax error was + detected; it is used when manufacturing dummy tokens. This is + important because the position of the dummy token may end up in + the explanations that we produce. *) + + let investigate pos (checkpoint : _ checkpoint) : explanation list = + weed compare_explanations ( + foreach_terminal_but_error (fun symbol explanations -> + match symbol with + | X (N _) -> assert false + | X (T t) -> + (* Build a dummy token for the terminal symbol [t]. *) + let token = (terminal2token t, pos, pos) in + (* Submit it to the parser. Accumulate explanations. *) + match shifts (offer checkpoint token) with + | None -> + explanations + | Some env -> + accumulate t env explanations + ) [] + ) + + (* We drive the parser in the usual way, but records the last [InputNeeded] + checkpoint. If a syntax error is detected, we go back to this checkpoint + and analyze it in order to produce a meaningful diagnostic. *) + + exception Error of (Lexing.position * Lexing.position) * explanation list + + let entry (start : 'a I.checkpoint) lexer lexbuf = + let fail (inputneeded : 'a I.checkpoint) (checkpoint : 'a I.checkpoint) = + (* The parser signals a syntax error. Note the position of the + problematic token, which is useful. Then, go back to the + last [InputNeeded] checkpoint and investigate. *) + match checkpoint with + | HandlingError env -> + let (startp, _) as positions = positions env in + raise (Error (positions, investigate startp inputneeded)) + | _ -> + assert false + in + I.loop_handle_undo + (fun v -> v) + fail + (lexer_lexbuf_to_supplier lexer lexbuf) + start + + (* TEMPORARY could also publish a list of the terminal symbols that + do not cause an error *) + +end diff --git a/src/mo_frontend/menhir_error_reporting.mli b/src/mo_frontend/menhir_error_reporting.mli new file mode 100644 index 00000000000..8e397fca1e5 --- /dev/null +++ b/src/mo_frontend/menhir_error_reporting.mli @@ -0,0 +1,79 @@ +(* This module needs cleaning up. It is supposed to automatically + produce a syntax error message, based on the current state and + stack. *) + +module Make + (I : MenhirLib.IncrementalEngine.EVERYTHING) + (User : sig + + (* In order to submit artificial tokens to the parser, we need a function + that converts a terminal symbol to a token. Unfortunately, we cannot + (in general) auto-generate this code, because it requires making up + semantic values of arbitrary OCaml types. *) + + val terminal2token: _ I.terminal -> I.token + + end) +: sig + + open I + + (* An explanation is a description of what the parser has recognized in the + recent past and what it expects next. More precisely, an explanation is + an LR(0) item, enriched with positions. Indeed, the past (the first half + of the item's right-hand side, up to the bullet) corresponds to a part of + the input that has been read already, so it can be annotated with + positions. *) + + type explanation + + (* The LR(0) item. *) + + val item: explanation -> item + + (* The past. This is a non-empty sequence of (terminal and non-terminal) + symbols, each of which corresponds to a range of the input file. These + symbols correspond to the first half (up to the bullet) of the item's + right-hand side. In short, they represent what (we think) we have + recognized in the recent past. *) + + (* It is worth noting that, when an error occurs, we produce multiple + explanations, which may have different pasts. Indeed, not only may + these pasts have different lengths (one may be a suffix of another), + but two pasts can in fact be incomparable. Indeed, different choices + of the lookahead token may cause different reductions, hence different + interpretations of what has been read in the past. *) + + val past: explanation -> (xsymbol * Lexing.position * Lexing.position) list + + (* The future. This is a non-empty sequence of (terminal and non-terminal) + symbols. These symbols correspond to the second half (after the bullet) + of the item's right-hand side. In short, they represent what we expect + to recognize in the future, if this item is a good prediction. *) + + (* This information can be computed from [item]. This function is provided + only for convenience. *) + + val future: explanation -> xsymbol list + + (* A goal. This is a non-terminal symbol. It is the item's left-hand side. + In short, it represents the reduction that we will be able to perform if + we successfully recognize this future. *) + + (* This information can be computed from [item]. This function is provided + only for convenience. *) + + val goal: explanation -> xsymbol + + (* TEMPORARY *) + + (* We build lists of explanations. These explanations may originate in + distinct LR(1) states. They may have different pasts, because *) + + exception Error of (Lexing.position * Lexing.position) * explanation list + + (* TEMPORARY *) + + val entry: 'a I.checkpoint -> (Lexing.lexbuf -> token) -> Lexing.lexbuf -> 'a + +end diff --git a/src/mo_frontend/parser.mly b/src/mo_frontend/parser.mly index d66e97ea268..030953979c6 100644 --- a/src/mo_frontend/parser.mly +++ b/src/mo_frontend/parser.mly @@ -133,10 +133,49 @@ let share_expfield (ef : exp_field) = %nonassoc SHLOP USHROP SSHROP ROTLOP ROTROP %left POWOP -%type exp(ob) exp_nullary(ob) +%type exp(ob) exp_nullary(ob) text_like +%type typ_un typ_nullary typ typ_pre typ_item +%type vis +%type typ_tag +%type typ_variant +%type typ_field +%type typ_bind +%type typ_args +%type Mo_def.Syntax.pat> sort_pat_opt +%type seplist1(typ_tag,semicolon) seplist(typ_tag,semicolon) +%type seplist(typ_item,COMMA) +%type typ_obj seplist(typ_field,semicolon) +%type seplist(typ_bind,COMMA) +%type seplist(typ,COMMA) +%type seplist(pat_field,semicolon) +%type seplist(pat_bin,COMMA) +%type seplist(imp,semicolon) seplist(imp,SEMICOLON) seplist(dec_var,semicolon) seplist(dec,semicolon) seplist(dec,SEMICOLON) +%type seplist(exp_nonvar(ob),COMMA) seplist(exp(ob),COMMA) +%type seplist(exp_field,semicolon) seplist(dec_field,semicolon) obj_body exp_field_list_unamb +%type seplist(case,semicolon) +%type return_typ_nullary return_typ +%type option(return_typ_nullary) option(return_typ) +%type path +%type pat pat_un pat_param pat_nullary pat_bin +%type pat_field +%type option(typ_args) +%type option(exp_nullary(ob)) +%type option(EQ) +%type exp_un(ob) exp_un(bl) exp_post(ob) exp_post(bl) exp_nullary(bl) exp_nonvar(ob) exp_nonvar(bl) exp_nondec(ob) exp_nondec(bl) exp_block exp_bin(ob) exp_bin(bl) exp(bl) +%type func_body +%type lit +%type dec imp dec_var dec_nonvar +%type exp_field exp_field_nonvar dec_field +%type dec_list_unamb +%type class_body +%type catch case +%type Mo_def.Syntax.exp'> bl ob + +%type start %start Mo_def.Syntax.prog> parse_prog %start Mo_def.Syntax.prog> parse_prog_interactive +%on_error_reduce exp_bin(ob) exp_bin(bl) exp_nondec(bl) exp_nondec(ob) %% (* Helpers *) @@ -691,12 +730,15 @@ imp : { let _, x = xf "import" $sloc in let_or_exp true x (ImportE (f, ref Unresolved)) (at $sloc) } +start : (* dummy non-terminal to satisfy ErrorReporting.ml, that requires a non-empty parse stack *) + | /* Empty */ { () } + parse_prog : - | is=seplist(imp, semicolon) ds=seplist(dec, semicolon) EOF + | start is=seplist(imp, semicolon) ds=seplist(dec, semicolon) EOF { fun filename -> { it = is @ ds; at = at $sloc ; note = filename} } parse_prog_interactive : - | is=seplist(imp, SEMICOLON) ds=seplist(dec, SEMICOLON) SEMICOLON_EOL + | start is=seplist(imp, SEMICOLON) ds=seplist(dec, SEMICOLON) SEMICOLON_EOL { fun filename -> { it = is @ ds; at = at $sloc ; note = filename} } %% diff --git a/src/mo_frontend/parsing.ml b/src/mo_frontend/parsing.ml new file mode 100644 index 00000000000..0df6d5e8832 --- /dev/null +++ b/src/mo_frontend/parsing.ml @@ -0,0 +1,83 @@ + +module P = + MenhirLib.Printers.Make + (Parser.MenhirInterpreter) + (Printers) + +(* Instantiate [ErrorReporting] for our parser. This requires + providing a few functions -- see [CalcErrorReporting]. *) + +module E = + Menhir_error_reporting.Make + (Parser.MenhirInterpreter) + (Error_reporting) + +(* Define a printer for explanations. We treat an explanation as if it + were just an item: that is, we ignore the position information that + is provided in the explanation. Indeed, this information is hard to + show in text mode. *) + +let uniq xs = List.fold_right (fun x ys -> if List.mem x ys then ys else x::ys) xs [] + +let abstract_symbols explanations = + let symbols = List.sort Parser.MenhirInterpreter.compare_symbols + (List.map (fun e -> List.hd (E.future e)) explanations) in + let ss = List.map Printers.string_of_symbol symbols in + String.concat "\n " (uniq ss) + +let abstract_future future = + let ss = List.map Printers.string_of_symbol future in + String.concat " " ss + +let rec lex_compare_futures f1 f2 = + match f1,f2 with + | [], [] -> 0 + | s1::ss1,s2::ss2 -> + (match Parser.MenhirInterpreter.compare_symbols s1 s2 with + | 0 -> lex_compare_futures ss1 ss2 + | c -> c) + | _ -> assert false + +let compare_futures f1 f2 = match compare (List.length f1) (List.length f2) with + | 0 -> lex_compare_futures f1 f2 + | c -> c + +let abstract_futures explanations = + let futures = List.sort compare_futures (List.map E.future explanations) in + let ss = List.map abstract_future futures in + String.concat "\n " (uniq ss) + +let abstract_item item = + P.print_item item; + Printers.to_string() + +let abstract_items explanations = + let items = List.sort Parser.MenhirInterpreter.compare_items (List.map E.item explanations) in + let ss = List.map abstract_item items in + String.concat " " (uniq ss) + +let error_message error_detail lexeme explanations = + let token = String.escaped lexeme in + match error_detail with + | 1 -> + Printf.sprintf + "unexpected token '%s', \nexpected one of token or :\n %s" + token (abstract_symbols explanations) + | 2 -> + Printf.sprintf + "unexpected token '%s', \nexpected one of token or sequence:\n %s" + token (abstract_futures explanations) + | 3 -> + Printf.sprintf + "unexpected token '%s'\n in position marked . of partially parsed item(s):\n%s" + token (abstract_items explanations) + | _ -> + Printf.sprintf "unexpected token '%s'" token + +type error_detail = int + +exception Error of string + +let parse error_detail checkpoint lexer lexbuf = + try E.entry checkpoint lexer lexbuf with E.Error (_, explanations) -> + raise (Error (error_message error_detail (Lexing.lexeme lexbuf) explanations)) diff --git a/src/mo_frontend/parsing.mli b/src/mo_frontend/parsing.mli new file mode 100644 index 00000000000..843d5e580de --- /dev/null +++ b/src/mo_frontend/parsing.mli @@ -0,0 +1,15 @@ + +(* 0,_ : unexpected token *) +(* 1 : and expected symbol *) +(* 2 : and expected symbols *) +(* 3 : and parsed items *) + +type error_detail = int + +exception Error of string + +val parse : error_detail -> + 'a Parser.MenhirInterpreter.checkpoint -> + (Lexing.lexbuf -> Parser.token) -> + Lexing.lexbuf -> + 'a diff --git a/src/mo_frontend/printers.ml b/src/mo_frontend/printers.ml new file mode 100644 index 00000000000..88f05aac816 --- /dev/null +++ b/src/mo_frontend/printers.ml @@ -0,0 +1,217 @@ +open Parser.MenhirInterpreter + +(* In order to print syntax error messages and/or debugging information, we + need a symbol printer. *) + +let abstract abs con = abs + +let binop = abstract "" +let relop = abstract "" +let binassign = abstract "" + +(* all unary operators are also binary operators, so keep them unary *) +let unop = abstract "" +let unassign = abstract "" + + +let string_of_symbol symbol : string = + match symbol with + | X (T T_error) -> "error" + | X (T T_XOROP) -> unop "^" + | X (T T_XORASSIGN) -> unassign "^=" + | X (T T_WHILE) -> "while" + | X (T T_VAR) -> "var" + | X (T T_USHROP) -> binop " >>" + | X (T T_USHRASSIGN) -> binop ">>=" + | X (T T_UNDERSCORE) -> "_" + | X (T T_TYPE) -> "type" + | X (T T_TRY) -> "try" + | X (T T_THROW) -> "throw" + | X (T T_TEXT) -> "" + | X (T T_SWITCH) -> "switch" + | X (T T_SUBOP) -> unop "-" + | X (T T_SUB) -> "<:" + | X (T T_SSHROP) -> binop "+>>" + | X (T T_SSHRASSIGN) -> binassign "+>>=" + | X (T T_SHLOP) -> binop "<<" + | X (T T_SHLASSIGN) -> binassign "<<=" + | X (T T_SHARED) -> "shared" + | X (T T_SEMICOLON_EOL) -> ";" (* suppress the \n *) + | X (T T_SEMICOLON) -> ";" + | X (T T_RPAR) -> ")" + | X (T T_ROTROP) -> binop "<>>" + | X (T T_ROTRASSIGN) -> binassign "<>>=" + | X (T T_ROTLOP) -> binop "<<>" + | X (T T_ROTLASSIGN) -> binassign "<<>=" + | X (T T_RETURN) -> "return" + | X (T T_RCURLY) -> "}" + | X (T T_RBRACKET) -> "]" + | X (T T_QUEST) -> "?" + | X (T T_QUERY) -> "query" + | X (T T_PUBLIC) -> "public" + | X (T T_PRIVATE) -> "private" + | X (T T_PRIM) -> "prim" + | X (T T_POWOP) -> binop "**" + | X (T T_POWASSIGN) -> binassign "**-" + | X (T T_PLUSASSIGN) -> unassign "+=" + | X (T T_OROP) -> binop "|" + | X (T T_ORASSIGN) -> binassign "|=" + | X (T T_OR) -> "or" + | X (T T_OBJECT) -> "object" + | X (T T_NULL) -> "null" + | X (T T_NOT) -> "not" + | X (T T_NEQOP) -> binop "!=" + | X (T T_NAT) -> "" + | X (T T_MULOP) -> binop "*" + | X (T T_MULASSIGN) -> binassign "*=" + | X (T T_MODULE) -> "module" + | X (T T_MODOP) -> binop "%" + | X (T T_MODASSIGN) -> binassign "%=" + | X (T T_MINUSASSIGN) -> unassign "-=" + | X (T T_LTOP) -> relop " < " + | X (T T_LT) -> "<" + | X (T T_LPAR) -> "(" + | X (T T_LOOP) -> "loop" + | X (T T_LET) -> "let" + | X (T T_LEOP) -> relop "<=" + | X (T T_LCURLY) -> "{" + | X (T T_LBRACKET) -> "[" + | X (T T_LABEL) -> "label" + | X (T T_IN) -> "in" + | X (T T_IMPORT) -> "import" + | X (T T_IGNORE) -> "ignore" + | X (T T_IF) -> "if" + | X (T T_ID) -> "" + | X (T T_HASH) -> binop "#" + | X (T T_GTOP) -> relop " > " + | X (T T_GT) -> ">" + | X (T T_GEOP) -> relop ">=" + | X (T T_FUNC) -> "func" + | X (T T_FOR) -> "for" + | X (T T_FLOAT) -> "" + | X (T T_EQOP) -> relop "==" + | X (T T_EQ) -> "=" + | X (T T_EOF) -> "" + | X (T T_ELSE) -> "else" + | X (T T_DOT_NUM) -> "." + | X (T T_DOT) -> "." + | X (T T_DIVOP) -> binop "/" + | X (T T_DIVASSIGN) -> binassign "/=" + | X (T T_DEBUG_SHOW) -> "debug_show" + | X (T T_DEBUG) -> "debug" + | X (T T_CONTINUE) -> "continue" + | X (T T_COMMA) -> "," + | X (T T_COLON) -> ":" + | X (T T_CLASS) -> "class" + | X (T T_CHAR) -> "" + | X (T T_CATCH) -> "catch" + | X (T T_CATASSIGN) -> binassign "@=" + | X (T T_CASE) -> "case" + | X (T T_BREAK) -> "break" + | X (T T_BOOL) -> "" + | X (T T_AWAIT) -> "await" + | X (T T_ASYNC) -> "async" + | X (T T_ASSIGN) -> binassign "assign" + | X (T T_ASSERT) -> "assert" + | X (T T_ARROW) -> "->" + | X (T T_ANDOP) -> binop "&" + | X (T T_ANDASSIGN) -> binassign "&=" + | X (T T_AND) -> "and" + | X (T T_ADDOP) -> unop "+" + | X (T T_ACTOR) -> "actor" + (* non-terminals *) + | X (N N_bl) -> "" + | X (N N_case) -> "" + | X (N N_catch) -> "" + | X (N N_class_body) -> "" + | X (N N_dec) -> "" + | X (N N_dec_field) -> "" + | X (N N_dec_list_unamb) -> "" + | X (N N_dec_nonvar) -> "" + | X (N N_dec_var) -> "" + | X (N N_exp_bl_) -> "" + | X (N N_exp_ob_) -> "" + | X (N N_exp_bin_bl_) -> "" + | X (N N_exp_bin_ob_) -> "" + | X (N N_exp_block) -> "" + | X (N N_exp_field) -> "" + | X (N N_exp_field_list_unamb) -> "" + | X (N N_exp_field_nonvar) -> "" + | X (N N_exp_nondec_bl_) -> "" + | X (N N_exp_nondec_ob_) -> "" + | X (N N_exp_nonvar_bl_) -> "" + | X (N N_exp_nonvar_ob_) -> "" + | X (N N_exp_nullary_bl_) -> "" + | X (N N_exp_nullary_ob_) -> "" + | X (N N_exp_post_bl_) -> "" + | X (N N_exp_post_ob_) -> "" + | X (N N_exp_un_bl_) -> "" + | X (N N_exp_un_ob_) -> "" + | X (N N_func_body) -> "" + | X (N N_imp) -> "" + | X (N N_lit) -> "" + | X (N N_ob) -> "" + | X (N N_obj_body) -> "" + | X (N N_option_EQ_) -> "=?" + | X (N N_option_exp_nullary_ob__) -> "?" + | X (N N_option_return_typ_) -> "?" + | X (N N_option_return_typ_nullary_) -> "?" + | X (N N_option_typ_args_) -> "?" + | X (N N_parse_prog) -> "" + | X (N N_parse_prog_interactive) -> "" + | X (N N_pat) -> "" + | X (N N_pat_bin) -> "" + | X (N N_pat_field) -> "" + | X (N N_pat_nullary) -> "" + | X (N N_pat_param) -> "" + | X (N N_pat_un) -> "" + | X (N N_path) -> "" + | X (N N_return_typ) -> "" + | X (N N_return_typ_nullary) -> "" + | X (N N_seplist_case_semicolon_) -> "seplist(,)" + | X (N N_seplist_dec_SEMICOLON_) -> "seplist(,;)" + | X (N N_seplist_dec_semicolon_) -> "seplist(,)" + | X (N N_seplist_dec_field_semicolon_) -> "seplist(,)" + | X (N N_seplist_dec_var_semicolon_) -> "seplist(,)" + | X (N N_seplist_exp_ob__COMMA_) -> "seplist(,,)" + | X (N N_seplist_exp_field_semicolon_) -> "seplist(,)" + | X (N N_seplist_exp_nonvar_ob__COMMA_) -> "seplist( "seplist(,;)" + | X (N N_seplist_imp_semicolon_) -> "seplist(,)" + | X (N N_seplist_pat_bin_COMMA_) -> "seplist(,,)" + | X (N N_seplist_pat_field_semicolon_) -> "seplist(,)" + | X (N N_seplist_typ_COMMA_) -> "seplist(,,)" + | X (N N_seplist_typ_bind_COMMA_) -> "seplist(,,)" + | X (N N_seplist_typ_field_semicolon_) -> "seplist(,)" + | X (N N_seplist_typ_item_COMMA_) -> "seplist(,,)" + | X (N N_seplist_typ_tag_semicolon_) -> "seplist(,)" + | X (N N_seplist1_typ_tag_semicolon_) -> "seplist1(,)" + | X (N N_sort_pat_opt) -> "" + | X (N N_text_like) -> "" + | X (N N_typ) -> "" + | X (N N_typ_args) -> "" + | X (N N_typ_bind) -> "" + | X (N N_typ_field) -> "" + | X (N N_typ_item) -> "" + | X (N N_typ_nullary) -> "" + | X (N N_typ_obj) -> "" + | X (N N_typ_pre) -> "" + | X (N N_typ_tag) -> "" + | X (N N_typ_un) -> "" + | X (N N_typ_variant) -> "" + | X (N N_vis) -> "" + | X (N N_start) -> "" (* dummy non-terminal, don't display *) + +(* In order to print a view of the stack that includes semantic values, + we need an element printer. (If we don't need this feature, then + [print_symbol] above suffices.) *) + +(* The public functions. *) + +let buff :string list ref = ref [] +let print s = buff := s::!buff +let print_symbol s = print (string_of_symbol s) +let print_element = None +let to_string() = let s = String.concat "" (List.rev (!buff)) in + buff := []; + s diff --git a/src/mo_frontend/printers.mli b/src/mo_frontend/printers.mli new file mode 100644 index 00000000000..4ac72a04fce --- /dev/null +++ b/src/mo_frontend/printers.mli @@ -0,0 +1,11 @@ +open Parser.MenhirInterpreter + +(* This module offers the functionality required by the functor + [MenhirLib.Printers.Make]. *) + +val string_of_symbol : xsymbol -> string + +val print: string -> unit +val print_symbol: xsymbol -> unit +val print_element: (element -> unit) option +val to_string : unit -> string diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index f45df391ebd..0cc557cb49a 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -81,23 +81,23 @@ type parse_result = (Syntax.prog * rel_path) Diag.result type parse_fn = rel_path -> parse_result -let parse_with mode lexer parse name = +let parse_with mode lexer parser name = try phase "Parsing" name; lexer.Lexing.lex_curr_p <- {lexer.Lexing.lex_curr_p with Lexing.pos_fname = name}; - let prog = parse (Lexer.token mode) lexer name in + let prog = Parsing.parse (!Flags.error_detail) (parser lexer.Lexing.lex_curr_p) (Lexer.token mode) lexer name in dump_prog Flags.dump_parse prog; Ok prog with | Lexer.Error (at, msg) -> error at "syntax" msg - | Parser.Error -> - error (Lexer.region lexer) "syntax" "unexpected token" + | Parsing.Error msg -> + error (Lexer.region lexer) "syntax" msg let parse_string name s : parse_result = let lexer = Lexing.from_string s in - let parse = Parser.parse_prog in + let parse = Parser.Incremental.parse_prog in match parse_with Lexer.Normal lexer parse name with | Ok prog -> Diag.return (prog, name) | Error e -> Error [e] @@ -105,7 +105,7 @@ let parse_string name s : parse_result = let parse_file filename : parse_result = let ic = open_in filename in let lexer = Lexing.from_channel ic in - let parse = Parser.parse_prog in + let parse = Parser.Incremental.parse_prog in let result = parse_with Lexer.Normal lexer parse filename in close_in ic; match result with @@ -219,7 +219,7 @@ let prelude_error phase (msgs : Diag.messages) = let check_prelude () : Syntax.prog * stat_env = let lexer = Lexing.from_string Prelude.prelude in - let parse = Parser.parse_prog in + let parse = Parser.Incremental.parse_prog in match parse_with Lexer.Privileged lexer parse prelude_name with | Error e -> prelude_error "parsing" [e] | Ok prog -> @@ -243,7 +243,7 @@ let prim_error phase (msgs : Diag.messages) = let check_prim () : Syntax.lib * stat_env = let lexer = Lexing.from_string Prelude.prim_module in - let parse = Parser.parse_prog in + let parse = Parser.Incremental.parse_prog in match parse_with Lexer.Privileged lexer parse prim_name with | Error e -> prim_error "parsing" [e] | Ok prog -> @@ -403,6 +403,7 @@ let interpret_files (senv0, denv0) files : (Scope.scope * Interpret.scope) optio | None -> None | Some denv2 -> Some (senv1, denv2) ) + let run_prelude () : dyn_env = match interpret_prog Interpret.empty_scope prelude with @@ -458,7 +459,7 @@ let lexer_stdin buf len = let parse_lexer lexer : parse_result = let open Lexing in if lexer.lex_curr_pos >= lexer.lex_buffer_len - 1 then continuing := false; - match parse_with Lexer.Normal lexer Parser.parse_prog_interactive "stdin" with + match parse_with Lexer.Normal lexer Parser.Incremental.parse_prog_interactive "stdin" with | Error e -> Lexing.flush_input lexer; (* Reset beginning-of-line, too, to sync consecutive positions. *) diff --git a/test/fail/ok/syntax1.tc.ok b/test/fail/ok/syntax1.tc.ok new file mode 100644 index 00000000000..aecb159a0c7 --- /dev/null +++ b/test/fail/ok/syntax1.tc.ok @@ -0,0 +1,3 @@ +syntax1.mo:1.8-2.1: syntax error, unexpected token ';\n', +expected one of token or sequence: + diff --git a/test/fail/ok/syntax1.tc.ret.ok b/test/fail/ok/syntax1.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/syntax1.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/syntax2.tc.ok b/test/fail/ok/syntax2.tc.ok new file mode 100644 index 00000000000..ba89d9d6bb9 --- /dev/null +++ b/test/fail/ok/syntax2.tc.ok @@ -0,0 +1,18 @@ +syntax2.mo:2.1-2.4: syntax error, unexpected token 'let', +expected one of token or sequence: + + . + + + ; seplist(,) + or + + + . + : + + + and + + ? + [ ] diff --git a/test/fail/ok/syntax2.tc.ret.ok b/test/fail/ok/syntax2.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/syntax2.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/syntax3.tc.ok b/test/fail/ok/syntax3.tc.ok new file mode 100644 index 00000000000..b0ad3b7859a --- /dev/null +++ b/test/fail/ok/syntax3.tc.ok @@ -0,0 +1,18 @@ +syntax3.mo:1.3-1.4: syntax error, unexpected token ';', +expected one of token or sequence: + ] + . + + + or + + + . + , seplist( + + + and + + ? + [ ] diff --git a/test/fail/ok/syntax3.tc.ret.ok b/test/fail/ok/syntax3.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/syntax3.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/syntax4.tc.ok b/test/fail/ok/syntax4.tc.ok new file mode 100644 index 00000000000..0145c89e740 --- /dev/null +++ b/test/fail/ok/syntax4.tc.ok @@ -0,0 +1,5 @@ +syntax4.mo:1.1-1.2: syntax error, unexpected token '*', +expected one of token or sequence: + + seplist(,) + seplist(,) seplist(,) diff --git a/test/fail/ok/syntax4.tc.ret.ok b/test/fail/ok/syntax4.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/syntax4.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/syntax5.tc.ok b/test/fail/ok/syntax5.tc.ok new file mode 100644 index 00000000000..97d94d0ea1f --- /dev/null +++ b/test/fail/ok/syntax5.tc.ok @@ -0,0 +1,18 @@ +syntax5.mo:3.1: syntax error, unexpected token '', +expected one of token or sequence: + ) + . + + + or + + + . + , seplist(,,) + : + + + and + + ? + [ ] diff --git a/test/fail/ok/syntax5.tc.ret.ok b/test/fail/ok/syntax5.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/syntax5.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/syntax6.tc.ok b/test/fail/ok/syntax6.tc.ok new file mode 100644 index 00000000000..1a893de3e5a --- /dev/null +++ b/test/fail/ok/syntax6.tc.ok @@ -0,0 +1,18 @@ +syntax6.mo:1.5-1.6: syntax error, unexpected token '}', +expected one of token or sequence: + + . + + + ; seplist(,) + or + + + . + : + + + and + + ? + [ ] diff --git a/test/fail/ok/syntax6.tc.ret.ok b/test/fail/ok/syntax6.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/syntax6.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/syntax7.tc.ok b/test/fail/ok/syntax7.tc.ok new file mode 100644 index 00000000000..c134e9427f0 --- /dev/null +++ b/test/fail/ok/syntax7.tc.ok @@ -0,0 +1,4 @@ +syntax7.mo:30.1-30.4: syntax error, unexpected token 'let', +expected one of token or sequence: + + ; seplist(,) diff --git a/test/fail/ok/syntax7.tc.ret.ok b/test/fail/ok/syntax7.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/syntax7.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/syntax1.mo b/test/fail/syntax1.mo new file mode 100644 index 00000000000..636f34569d0 --- /dev/null +++ b/test/fail/syntax1.mo @@ -0,0 +1 @@ +1 + 2 *; diff --git a/test/fail/syntax2.mo b/test/fail/syntax2.mo new file mode 100644 index 00000000000..a31ff0eea0c --- /dev/null +++ b/test/fail/syntax2.mo @@ -0,0 +1,2 @@ +let x = 1 +let y = 2; diff --git a/test/fail/syntax3.mo b/test/fail/syntax3.mo new file mode 100644 index 00000000000..e2eb73d14d8 --- /dev/null +++ b/test/fail/syntax3.mo @@ -0,0 +1 @@ +[1;2;3]; diff --git a/test/fail/syntax4.mo b/test/fail/syntax4.mo new file mode 100644 index 00000000000..72e8ffc0db8 --- /dev/null +++ b/test/fail/syntax4.mo @@ -0,0 +1 @@ +* diff --git a/test/fail/syntax5.mo b/test/fail/syntax5.mo new file mode 100644 index 00000000000..0ba9248c60d --- /dev/null +++ b/test/fail/syntax5.mo @@ -0,0 +1,2 @@ +(((((((((((((((((())))))))))))))))) + diff --git a/test/fail/syntax6.mo b/test/fail/syntax6.mo new file mode 100644 index 00000000000..630999c6c9b --- /dev/null +++ b/test/fail/syntax6.mo @@ -0,0 +1 @@ +{{}}} diff --git a/test/fail/syntax7.mo b/test/fail/syntax7.mo new file mode 100644 index 00000000000..42f27d57095 --- /dev/null +++ b/test/fail/syntax7.mo @@ -0,0 +1,31 @@ +/* integer quicksort as top-level functions */ + +func swap(a : [var Int], i : Nat, j : Nat) { + let temp = a[i]; + a[i] := a[j]; + a[j] := temp; +}; + +func partition(a : [var Int], lo : Nat, hi : Nat) : Nat { + let pivot = a[lo]; + var i : Nat = lo; + var j : Nat = hi; + + loop { + while (a[i] < pivot) i += 1; + while (a[j] > pivot) j -= 1; + if (i >= j) return j; + swap(a, i, j); + }; +}; + +func quicksort(a : [var Int], lo : Nat, hi : Nat) { + if (lo < hi) { + let p = partition(a, lo, hi); + quicksort(a, lo, p); + quicksort(a, p + 1, hi); + }; +} /*;*/ + +let a : [var Int] = [var 8, 3, 9, 5, 2]; +quicksort(a, 0, 4); diff --git a/test/lsp-int/Main.hs b/test/lsp-int/Main.hs index f6e7202c552..c3eb8f50928 100644 --- a/test/lsp-int/Main.hs +++ b/test/lsp-int/Main.hs @@ -111,7 +111,7 @@ main = do putStrLn "Starting the session" runSession (mo_ide - <> " --canister-main app.mo --debug" + <> " --canister-main app.mo --debug --error-detail 0" <> " --package mydep " <> project <> "/mydependency/") fullCaps "." $ do @@ -191,7 +191,7 @@ main = do _ <- applyEdit doc edit sendNotification TextDocumentDidSave (DidSaveTextDocumentParams doc) (diagnostic:_) <- waitForDiagnostics - liftIO (diagnostic^.message `shouldBe` "unexpected token") + liftIO (diagnostic^.message `shouldBe` "unexpected token 'import'") log "Lexer failures don't crash the server" withDoc "ListClient.mo" \doc -> do @@ -212,7 +212,7 @@ main = do withDoc "app.mo" \appDoc -> do sendNotification TextDocumentDidSave (DidSaveTextDocumentParams appDoc) diagnostic:_ <- waitForActualDiagnostics - liftIO (diagnostic^.message `shouldBe` "unexpected token") + liftIO (diagnostic^.message `shouldBe` "unexpected token 'import'") log "Rebuilding with package paths" withDoc "app.mo" \doc -> do diff --git a/test/node-test.js b/test/node-test.js index 7b28e4c3e21..0deabe2e692 100644 --- a/test/node-test.js +++ b/test/node-test.js @@ -51,7 +51,7 @@ assert.deepStrictEqual(bad_result, { }, "severity": 1, "source": "motoko", - "message": "unexpected token" + "message": "unexpected token \'\', \nexpected one of token or sequence:\n " } ], "code": null, @@ -79,7 +79,7 @@ assert.deepStrictEqual(m.Motoko.check('1+'), { }, "severity": 1, "source": "motoko", - "message": "unexpected token" + "message": "unexpected token \'\', \nexpected one of token or sequence:\n " } ], "code": null From 5d6ac6c180a4e75971b6a1e2c8c1915817929fc4 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 30 Jan 2020 18:17:01 +0100 Subject: [PATCH 1014/1176] stlib/list: Avoid local closures (#1169) * stlib/list: Avoid local closures mostly by simplifying code, sometimes by passing arguments around to local functions explicitly. * Reformat * More reformat --- stdlib/src/list.mo | 300 +++++++++++++++++++-------------------------- 1 file changed, 127 insertions(+), 173 deletions(-) diff --git a/stdlib/src/list.mo b/stdlib/src/list.mo index b263339feb7..5177f19a5c4 100644 --- a/stdlib/src/list.mo +++ b/stdlib/src/list.mo @@ -22,18 +22,20 @@ module { /** The empty list */ - public let nil : () -> List = func() : List = null; + public let nil : () -> List = + func() : List = null; /** Returns true if the list is empty. */ - public let isNil : List -> Bool = func(l : List) : Bool { - switch l { - case null { true }; - case _ { false }; - } - }; + public let isNil : List -> Bool = + func(l : List) : Bool { + switch l { + case null { true }; + case _ { false }; + } + }; /** also known as "list cons" @@ -44,30 +46,32 @@ module { /** The last element of the list, if present. */ - public let last : List -> ?T = func(l : List) : ?T { - switch l { - case null { null }; - case (?(x,null)) { ?x }; - case (?(_,t)) { last(t) }; - } - }; + public let last : List -> ?T = + func(l : List) : ?T { + switch l { + case null { null }; + case (?(x,null)) { ?x }; + case (?(_,t)) { last(t) }; + } + }; /** Treating the list as a stack; this combines the usual operations `head` and (non-failing) `tail` into one operation. */ - public let pop : List -> (?T, List) = func(l : List) : (?T, List) { - switch l { - case null { (null, null) }; - case (?(h, t)) { (?h, t) }; - } - }; + public let pop : List -> (?T, List) = + func(l : List) : (?T, List) { + switch l { + case null { (null, null) }; + case (?(h, t)) { (?h, t) }; + } + }; /** The length of the list */ public let len : List -> Nat = - func(l : List) : Nat = label profile_list_len : Nat { - func rec(l : List, n : Nat) : Nat = label profile_list_len_rec : Nat { + func(l : List) : Nat { + func rec(l : List, n : Nat) : Nat { switch l { case null { n }; case (?(_,t)) { rec(t,n+1) }; @@ -80,47 +84,32 @@ module { Tests the length against a maximum value */ public let lenIsEqLessThan : (List, Nat) -> Bool = - func(l : List , i : Nat) : Bool = - label profile_list_lenIsEqLessThan_begin : Bool { - func rec(l : List, i : Nat) : Bool = label profile_list_lenIsEqLessThan_rec : Bool { - switch l { - case null label profile_list_lenIsEqLessThan_end_true : Bool true; - case (?(_, t)) { - if ( i == 0 ) { - label profile_list_lenIsEqLessThan_end_false : Bool - false - } - else { - rec(t, i - 1) - } - }; - } + func(l : List , i : Nat) : Bool { + switch l { + case null true; + case (?(_, t)) { + if (i == 0) { false } + else { lenIsEqLessThan(t, i - 1) } }; - rec(l, i) }; + }; /** - Get the length, unless greater than a maximum value, in which return null. - */ - public let lenClamp : (List, Nat) -> ?Nat = - func(l : List, i0 : Nat) : ?Nat = - label profile_list_lenClamp : (?Nat) { - func rec(l : List, i : Nat) : ?Nat = label profile_list_lenClamp_rec : (?Nat) { - switch l { - case null { label profile_list_lenClamp_end_some : (?Nat) ?(i0 - i) }; - case (?(_, t)) { - if ( i == 0 ) { - label profile_list_lenClamp_end_null : (?Nat) - null - } - else { - rec(t, i - 1) - } - }; - } - }; - rec(l, i0) + Get the length, unless greater than a maximum value, in which return `null`. + */ + public let lenClamp : (List, max : Nat) -> ?Nat = + func(l : List, max : Nat) : ?Nat { + func rec(l : List, max : Nat, i : Nat) : ?Nat { + switch l { + case null { ?i }; + case (?(_, t)) { + if ( i > max ) { null } + else { rec(t, max, i + 1) } + }; + } }; + rec(l, max, 0) + }; /** Random list access, zero-based. @@ -157,14 +146,11 @@ module { This is called `app` in SML Basis, and `iter` in OCaml. */ public let iter : (List, f : T -> ()) -> () = - func iter(l : List, f:T -> ()) : () = { - func rec(l : List) : () { - switch l { - case null { () }; - case (?(h,t)) { f(h) ; rec(t) }; - } - }; - rec(l) + func iter(l : List, f : T -> ()) { + switch l { + case null { () }; + case (?(h,t)) { f(h) ; iter(t, f) }; + } }; /** @@ -173,13 +159,10 @@ module { */ public let map : (List, f : T -> S) -> List = func(l : List, f:T -> S) : List = { - func rec(l : List) : List { - switch l { - case null { null }; - case (?(h,t)) { ?(f(h),rec(t)) }; - } - }; - rec(l) + switch l { + case null { null }; + case (?(h,t)) { ?(f(h),map(t,f)) }; + } }; /** @@ -188,13 +171,16 @@ module { */ public let filter : (List, p : T -> Bool) -> List = func(l : List, f:T -> Bool) : List = { - func rec(l : List) : List { - switch l { - case null { null }; - case (?(h,t)) { if (f(h)){ ?(h,rec(t)) } else { rec(t) } }; - } + switch l { + case null { null }; + case (?(h,t)) { + if (f(h)) { + ?(h,filter(t, f)) + } else { + filter(t, f) + } + }; }; - rec(l) }; /** @@ -205,18 +191,18 @@ module { */ public let split : (List, f : T -> Bool) -> (List, List) = func(l : List, f:T -> Bool) : (List, List) = { - func rec(l : List) : (List, List) = - label profile_list_split_rec : (List, List) { - switch l { - case null { (null, null) }; - case (?(h,t)) { - let (l,r) = rec(t) ; - if (f(h)) { (?(h,l), r) } else { (l, ?(h,r)) } - }; - } + switch l { + case null { (null, null) }; + case (?(h,t)) { + if (f(h)) { // call f in-order + let (l,r) = split(t, f); + (?(h,l), r) + } else { + let (l,r) = split(t, f); + (l, ?(h,r)) + } + }; }; - label profile_list_split_begin : (List, List) - rec(l) }; /** @@ -225,18 +211,15 @@ module { */ public let mapFilter : (List, f : T -> ?S) -> List = func(l : List, f:T -> ?S) : List = { - func rec(l : List) : List { - switch l { - case null { null }; - case (?(h,t)) { - switch (f(h)) { - case null { rec(t) }; - case (?h_){ ?(h_,rec(t)) }; - } - }; - } + switch l { + case null { null }; + case (?(h,t)) { + switch (f(h)) { + case null { mapFilter(t, f) }; + case (?h_){ ?(h_,mapFilter(t, f)) }; + } + }; }; - rec(l) }; /** @@ -260,16 +243,13 @@ module { // tail recursive, but requires "two passes" func(l : List>) : List = { // 1/2: fold from left to right, reverse-appending the sublists... - let r = - { let f = func(a:List, b:List) : List { revAppend(a,b) }; - foldLeft, List>(l, null, f) - }; + let r = foldLeft, List>(l, null, func(a,b) { revAppend(a,b) }); // 2/2: ...re-reverse the elements, to their original order: rev(r) }; // Internal utility-function - func revAppend(l1 : List, l2 : List) : List = { + func revAppend(l1 : List, l2 : List) : List { switch l1 { case null { l2 }; case (?(h,t)) { revAppend(t, ?(h,l2)) }; @@ -296,9 +276,9 @@ module { public let drop : (List, n:Nat) -> List = func(l : List, n:Nat) : List = { switch (l, n) { - case (l_, 0) { l_ }; - case (null, _) { null }; - case ((?(h,t)), m) { drop(t, m - 1) }; + case (l_, 0) { l_ }; + case (null, _) { null }; + case ((?(h,t)), m) { drop(t, m - 1) }; } }; @@ -307,13 +287,10 @@ module { */ public let foldLeft : (List, S, f : (T,S) -> S) -> S = func(l : List, a:S, f:(T,S) -> S) : S = { - func rec(l:List, a:S) : S = { - switch l { + switch l { case null { a }; - case (?(h,t)) { rec(t, f(h,a)) }; - } + case (?(h,t)) { foldLeft(t, f(h,a), f) }; }; - rec(l,a) }; /** @@ -321,13 +298,10 @@ module { */ public let foldRight : (List, S, f : (T,S) -> S) -> S = func(l : List, a:S, f:(T,S) -> S) : S = { - func rec(l:List) : S = { - switch l { + switch l { case null { a }; - case (?(h,t)) { f(h, rec(t)) }; - } + case (?(h,t)) { f(h, foldRight(t, a, f)) }; }; - rec(l) }; /** @@ -335,13 +309,10 @@ module { */ public let find : (l: List, f : T -> Bool) -> ?T = func(l: List, f:T -> Bool) : ?T = { - func rec(l:List) : ?T { - switch l { - case null { null }; - case (?(h,t)) { if (f(h)) { ?h } else { rec(t) } }; - } + switch l { + case null { null }; + case (?(h,t)) { if (f(h)) { ?h } else { find(t, f) } }; }; - rec(l) }; /** @@ -349,15 +320,10 @@ module { */ public let exists : (List, f : T -> Bool) -> Bool = func(l: List, f:T -> Bool) : Bool = { - func rec(l:List) : Bool { - switch l { - case null { false }; - // XXX/minor --- Missing parens on condition leads to unhelpful error: - //case (?(h,t)) { if f(h) { true } else { rec(t) } }; - case (?(h,t)) { if (f(h)) { true } else { rec(t) } }; - } + switch l { + case null { false }; + case (?(h,t)) { f(h) or exists(t, f)}; }; - rec(l) }; /** @@ -365,13 +331,10 @@ module { */ public let all : (List, f : T -> Bool) -> Bool = func(l: List, f:T -> Bool) : Bool = { - func rec(l:List) : Bool { - switch l { - case null { true }; - case (?(h,t)) { if (not f(h)) { false } else { rec(t) } }; - } - }; - rec(l) + switch l { + case null { true }; + case (?(h,t)) { f(h) and all(t, f) }; + } }; /** @@ -380,20 +343,17 @@ module { */ public let merge : (List, List, lte : (T,T) -> Bool) -> List = func(l1: List, l2: List, lte:(T,T) -> Bool) : List { - func rec(l1: List, l2: List) : List { - switch (l1, l2) { - case (null, _) { l2 }; - case (_, null) { l1 }; - case (?(h1,t1), ?(h2,t2)) { - if (lte(h1,h2)) { - ?(h1, rec(t1, ?(h2,t2))) - } else { - ?(h2, rec(?(h1,t1), t2)) - } - }; - } - }; - rec(l1, l2) + switch (l1, l2) { + case (null, _) { l2 }; + case (_, null) { l1 }; + case (?(h1,t1), ?(h2,t2)) { + if (lte(h1,h2)) { + ?(h1, merge(t1, l2, lte)) + } else { + ?(h2, merge(l1, t2, lte)) + } + }; + } }; /** @@ -404,14 +364,11 @@ module { */ public let lessThanEq : (List, List, lte: (T,T) -> Bool) -> Bool = func(l1: List, l2: List, lte:(T,T) -> Bool) : Bool { - func rec(l1: List, l2: List) : Bool { - switch (l1, l2) { - case (null, _) { true }; - case (_, null) { false }; - case (?(h1,t1), ?(h2,t2)) { lte(h1,h2) and rec(t1, t2) }; - } + switch (l1, l2) { + case (null, _) { true }; + case (_, null) { false }; + case (?(h1,t1), ?(h2,t2)) { lte(h1,h2) and lessThanEq(t1, t2, lte) }; }; - rec(l1, l2) }; /** @@ -421,15 +378,12 @@ module { */ public let isEq : (List, List, eq : (T,T) -> Bool) -> Bool = func(l1: List, l2: List, eq:(T,T) -> Bool) : Bool { - func rec(l1: List, l2: List) : Bool { - switch (l1, l2) { - case (null, null) { true }; - case (null, _) { false }; - case (_, null) { false }; - case (?(h1,t1), ?(h2,t2)) { eq(h1,h2) and rec(t1, t2) }; - } - }; - rec(l1, l2) + switch (l1, l2) { + case (null, null) { true }; + case (null, _) { false }; + case (_, null) { false }; + case (?(h1,t1), ?(h2,t2)) { eq(h1,h2) and isEq(t1, t2, eq) }; + } }; /** @@ -437,10 +391,10 @@ module { */ public let tabulate : (Nat, f : Nat -> T) -> List = func(n:Nat, f:Nat -> T) : List { - func rec(i:Nat) : List { - if (i == n) { null } else { ?(f(i), rec(i+1)) } + func rec(i:Nat, n: Nat, f : Nat -> T) : List { + if (i == n) { null } else { ?(f(i), rec(i+1, n, f)) } }; - rec(0) + rec(0, n, f) }; /** From 0b80a40cfaca770f9a55b5474330f296535799ad Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Fri, 31 Jan 2020 10:08:21 -0700 Subject: [PATCH 1015/1176] Stdlib: More bug fixes in `Buf` (#1177) * fix familar bugs in clone operations; add regression tests * cleanup * actually include Buf.clone() in regression test --- stdlib/src/buf.mo | 12 ++++++++---- stdlib/test/bufTest.mo | 40 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/stdlib/src/buf.mo b/stdlib/src/buf.mo index 1a4b57bdb03..729e3ec1170 100644 --- a/stdlib/src/buf.mo +++ b/stdlib/src/buf.mo @@ -56,8 +56,10 @@ public class Buf (initCapacity : Nat) { else 2 * elems.len(); let elems2 = A.init(size, elem); - for (i in elems.keys()) { - elems2[i] := elems[i]; + if (count > 0) { + for (i in I.range(0, count - 1)) { + elems2[i] := elems[i]; + }; }; elems := elems2; }; @@ -83,8 +85,10 @@ public class Buf (initCapacity : Nat) { public func clone() : Buf { let c = Buf(initCapacity); - for (i in elems.keys()) { - c.add(elems[i]) + if (count > 0) { + for (i in I.range(0, count - 1)) { + c.add(elems[i]) + }; }; c }; diff --git a/stdlib/test/bufTest.mo b/stdlib/test/bufTest.mo index 0f9ca69666a..b9c9f8f98be 100644 --- a/stdlib/test/bufTest.mo +++ b/stdlib/test/bufTest.mo @@ -21,6 +21,41 @@ for (i in I.range(0, 123)) { Prim.debugPrint(debug_show(a.toArray())); Prim.debugPrint(debug_show(b.toArray())); +func natArrayIter(elems:[Nat]) : I.Iter = object { + var pos = 0; + let count = elems.len(); + public func next() : ?Nat { + if (pos == count) { null } else { + let elem = ?elems[pos]; + pos += 1; + elem + } + } +}; + +func natVarArrayIter(elems:[var Nat]) : I.Iter = object { + var pos = 0; + let count = elems.len(); + public func next() : ?Nat { + if (pos == count) { null } else { + let elem = ?elems[pos]; + pos += 1; + elem + } + } +}; + +func natIterEq(a:I.Iter, b:I.Iter) : Bool { + switch (a.next(), b.next()) { + case (null, null) { true }; + case (?x, ?y) { + if (x == y) { natIterEq(a, b) } + else { false } + }; + case (_, _) { false }; + } +}; + // regression test: buffers with extra space are converted to arrays of the correct length { let bigLen = 100; @@ -31,10 +66,9 @@ Prim.debugPrint(debug_show(b.toArray())); Prim.debugPrint(debug_show(i)); c.add(i); }; - Prim.debugPrint(debug_show(c.len())); assert (c.len() == len); - Prim.debugPrint(debug_show(c.len())); assert (c.toArray().len() == len); - Prim.debugPrint(debug_show(c.len())); + assert (natIterEq(c.iter(), natArrayIter(c.clone().toArray()))); assert (c.toVarArray().len() == len); + assert (natIterEq(c.iter(), natVarArrayIter(c.clone().toVarArray()))); } From c178e042321ae45fe9c0bb3842f04abb423e043d Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Fri, 31 Jan 2020 19:33:22 +0000 Subject: [PATCH 1016/1176] Claudio/issue 827 (#1172) * fixed bug and added suggestions * more comments --- src/mo_idl/mo_to_idl.ml | 41 ++++++++++++++++++++------------- test/mo-idl/issue-827.mo | 4 ++++ test/mo-idl/ok/issue-827.did.ok | 8 +++++++ 3 files changed, 37 insertions(+), 16 deletions(-) create mode 100644 test/mo-idl/issue-827.mo create mode 100644 test/mo-idl/ok/issue-827.did.ok diff --git a/src/mo_idl/mo_to_idl.ml b/src/mo_idl/mo_to_idl.ml index 0bedd5b7d2c..1c2a4d2d4dd 100644 --- a/src/mo_idl/mo_to_idl.ml +++ b/src/mo_idl/mo_to_idl.ml @@ -8,14 +8,18 @@ module I = Idllib.Syntax let env = ref Env.empty (* For monomorphization *) let stamp = ref Env.empty -let type_map = ref Env.empty +(* can you replace this by a map with domain (Con.name) = string, ordered by Con.compare and implicit codomain int (or even int ref) *) +let type_map = ref Env.empty +(* can you replace this by a map with domain (con * typ list), ordered by +compare and implicit codomain int *) + let normalize str = let illegal_chars = ['-'; '/';] in String.map (fun c -> if List.mem c illegal_chars then '_' else c) str let string_of_con vs c = - let name = string_of_con c in + let name = string_of_con c in (* maybe use Con.name instead, excluding the stamp *) match Con.kind c with | Def ([], _) -> normalize name | Def (tbs, _) -> @@ -66,7 +70,11 @@ let rec typ vs t = | Any -> I.PrimT I.Reserved | Non -> I.PrimT I.Empty | Prim p -> prim p - | Var (s, i) -> (typ vs (List.nth vs i)).it + | Var (s, i) -> + (* matching on Var is dubious - + ideally we should use [Type.open_ ts typ] to go under binders + [Type.close cs typ] to introduce binders *) + (typ vs (List.nth vs i)).it | Con (c, []) -> (match Con.kind c with | Def ([], Prim p) -> prim p @@ -77,20 +85,22 @@ let rec typ vs t = I.VarT (string_of_con vs c @@ no_region) ) | Con (c, ts) -> - let ts = - List.map (fun t -> + let ts = + (* this looks like a broken attempt at subsitution, but only when the arguments are variables - why? *) + List.map (fun t -> match t with - | Var (s, i) -> List.nth vs i + | Var (s, i) -> List.nth vs i (* see above *) | _ -> t - ) ts in - (match Con.kind c with - | Def (tbs, t) -> - (* use this for inlining defs, doesn't work with recursion - (typ ts t).it - *) - chase_con ts c; - I.VarT (string_of_con ts c @@ no_region) - | _ -> assert false) + ) ts + in + (match Con.kind c with + | Def (tbs, t) -> + (* use this for inlining defs, doesn't work with recursion + (typ ts t).it + *) + chase_con ts c; + I.VarT (string_of_con ts c @@ no_region) + | _ -> assert false) | Typ c -> assert false | Tup ts -> if ts = [] then @@ -143,7 +153,6 @@ and meths vs fs = List.fold_right (fun f list -> match f.typ with | Typ c -> - chase_con vs c; list | _ -> let meth = diff --git a/test/mo-idl/issue-827.mo b/test/mo-idl/issue-827.mo new file mode 100644 index 00000000000..96b7e4aa903 --- /dev/null +++ b/test/mo-idl/issue-827.mo @@ -0,0 +1,4 @@ +actor { + public type List = ?(T, List); + public func f(i: List) : async List { i }; +} \ No newline at end of file diff --git a/test/mo-idl/ok/issue-827.did.ok b/test/mo-idl/ok/issue-827.did.ok new file mode 100644 index 00000000000..5aab225b14c --- /dev/null +++ b/test/mo-idl/ok/issue-827.did.ok @@ -0,0 +1,8 @@ +type List_1 = + opt record { + int; + List_1; + }; +service : { + "f": (List_1) -> (List_1); +} From 9a0fd639a0ad7f4f8f1af0211b198ef26a930ed6 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 3 Feb 2020 14:06:27 +0100 Subject: [PATCH 1017/1176] Simpler parameter desugaring (#1181) * Simpler parameter desugaring to fix https://dfinity.slack.com/archives/CPL67E7MX/p1580725876001800 we need the desugarer to more reliably look through `AnnotP` and `ParP` * Minor refactoring * Create parameter if there is a context pattern to keep patterns in the proper order. * More asserts --- src/lowering/desugar.ml | 54 +++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index a79dd8b42c2..45df586e494 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -394,21 +394,6 @@ and pat_fields pfs = List.map pat_field pfs and pat_field pf = phrase (fun S.{id; pat=p} -> I.{name=id.it; pat=pat p}) pf -and to_arg p : (Ir.arg * (Ir.exp -> Ir.exp)) = - match p.it with - | S.AnnotP (p, _) -> to_arg p - | S.VarP i -> - { i with note = p.note }, - (fun e -> e) - | S.WildP -> - let v = fresh_var "param" p.note in - arg_of_exp v, - (fun e -> e) - | _ -> - let v = fresh_var "param" p.note in - arg_of_exp v, - (fun e -> blockE [letP (pat p) v] e) - and to_args typ po p : Ir.arg list * (Ir.exp -> Ir.exp) * T.control * T.typ list = let sort, control, n_args, res_tys = match typ with @@ -421,10 +406,39 @@ and to_args typ po p : Ir.arg list * (Ir.exp -> Ir.exp) * T.control * T.typ list let tys = if n_args = 1 then [p.note] else T.seq_of_tup p.note in + let rec pat_unannot p = match p.it with + | S.AnnotP (p, _) -> pat_unannot p + | S.ParP p -> pat_unannot p + | _ -> p + in + + (* In source, the context pattern is outside the argument pattern, + but in the IR, paramteres are bound first. So if there is a context pattern, + we _must_ create fresh names for the parameters and bind the actual paramters + inside the wrapper. *) + let must_wrap = po != None in + + let to_arg p : (Ir.arg * (Ir.exp -> Ir.exp)) = + match (pat_unannot p).it with + | S.AnnotP _ | S.ParP _ -> assert false + | S.VarP i when not must_wrap -> + { i with note = p.note }, + (fun e -> e) + | S.WildP -> + let v = fresh_var "param" p.note in + arg_of_exp v, + (fun e -> e) + | _ -> + let v = fresh_var "param" p.note in + arg_of_exp v, + (fun e -> blockE [letP (pat p) v] e) + in + let args, wrap = - match n_args, p.it with + match n_args, (pat_unannot p).it with + | _, (S.AnnotP _ | S.ParP _) -> assert false | _, S.WildP -> - let vs = fresh_vars "param" tys in + let vs = fresh_vars "ignored" tys in List.map arg_of_exp vs, (fun e -> e) | 1, _ -> @@ -449,16 +463,14 @@ and to_args typ po p : Ir.arg list * (Ir.exp -> Ir.exp) * T.control * T.typ list | None -> wrap e | Some p -> let v = fresh_var "caller" T.caller in - let c = fresh_var "ctxt" T.ctxt in blockE [letD v (primE I.ICCallerPrim []); - letD c + letP (pat p) (newObjE T.Object [{ it = {Ir.name = "caller"; var = id_of_exp v}; at = no_region; note = T.caller }] - T.ctxt); - letP (pat p) c] + T.ctxt)] (wrap e) in From 5bea22ca7e6d574adcbe7cf0f14b27992618ec31 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 4 Feb 2020 16:07:07 +0000 Subject: [PATCH 1018/1176] desugar oneway bodies to `ignore (async _ : async ())` (#1179) * desugar oneway bodies to ignore (async _ : async ()) to support immediate await etc; require exhaustive patterns on shared functions * desugar oneway bodies to ignore (async _ : async ()) to support immediate await etc; require exhaustive patterns on shared functions * update test * fix desugaring of oneways to leave explicit declarations unchanged; make exhaustiveness errors local_errors; add tests * fix comment; add newline * modify tests * address review * write a short essay about sugar --- src/ir_passes/async.ml | 7 +-- src/lowering/desugar.ml | 12 +++-- src/mo_def/arrange.ml | 3 +- src/mo_def/syntax.ml | 52 ++++++++++++++++++-- src/mo_frontend/definedness.ml | 2 +- src/mo_frontend/parser.mly | 18 +++---- src/mo_frontend/traversals.ml | 4 +- src/mo_frontend/typing.ml | 38 +++++++------- src/mo_interpreter/interpret.ml | 2 +- test/fail/abstract-msgs.mo | 2 +- test/fail/duplicate-field.mo | 2 +- test/fail/ok/duplicate-field.tc.ok | 2 +- test/fail/ok/oneways.tc.ok | 12 +++++ test/fail/ok/oneways.tc.ret.ok | 1 + test/fail/ok/shared-nonexhaustive.tc.ok | 20 ++++++++ test/fail/ok/shared-nonexhaustive.tc.ret.ok | 1 + test/fail/oneways.mo | 17 +++++++ test/fail/shared-nonexhaustive.mo | 9 ++++ test/run-drun/async-calls3.mo | 2 +- test/run-drun/async-free-var.mo | 2 +- test/run-drun/async-loop-while.mo | 2 +- test/run-drun/async-loop.mo | 2 +- test/run-drun/async-new-obj.mo | 2 +- test/run-drun/async-obj-mut.mo | 2 +- test/run-drun/async-while.mo | 2 +- test/run-drun/block.mo | 2 +- test/run-drun/count-callbacks.mo | 2 +- test/run-drun/data-params.mo | 3 +- test/run-drun/flatten-awaitables.mo | 2 +- test/run-drun/for-await.mo | 2 +- test/run-drun/free-callbacks.mo | 2 +- test/run-drun/hello-world-await.mo | 2 +- test/run-drun/ic-calls.mo | 2 +- test/run-drun/local-throw.mo | 2 +- test/run-drun/ok/data-params.tc.ok | 2 +- test/run-drun/ok/self-shadow.comp-stub.ok | 2 +- test/run-drun/ok/self-shadow.comp.ok | 2 +- test/run-drun/ok/shared-match.diff-ir.ok | 7 --- test/run-drun/ok/shared-match.diff-low.ok | 7 --- test/run-drun/ok/shared-match.drun-run.ok | 5 -- test/run-drun/ok/shared-match.ic-stub-run.ok | 10 ---- test/run-drun/ok/shared-match.run-ir.ok | 3 -- test/run-drun/ok/shared-match.run-low.ok | 3 -- test/run-drun/ok/shared-match.run.ok | 3 -- test/run-drun/ok/shared-match.tc.ok | 4 -- test/run-drun/ok/test_oneway.tc.ok | 2 +- test/run-drun/oneway-throw.mo | 4 +- test/run-drun/oneway.mo | 36 ++++++-------- test/run-drun/pass-references.mo | 4 +- test/run-drun/query2.mo | 2 +- test/run-drun/self-shadow.mo | 4 +- test/run-drun/shared-match.mo | 20 -------- test/run-drun/shared-object.mo | 2 +- test/run-drun/throw.mo | 2 +- test/run-drun/transpose.mo | 2 +- 55 files changed, 196 insertions(+), 167 deletions(-) create mode 100644 test/fail/ok/oneways.tc.ok create mode 100644 test/fail/ok/oneways.tc.ret.ok create mode 100644 test/fail/ok/shared-nonexhaustive.tc.ok create mode 100644 test/fail/ok/shared-nonexhaustive.tc.ret.ok create mode 100644 test/fail/oneways.mo create mode 100644 test/fail/shared-nonexhaustive.mo delete mode 100644 test/run-drun/ok/shared-match.diff-ir.ok delete mode 100644 test/run-drun/ok/shared-match.diff-low.ok delete mode 100644 test/run-drun/ok/shared-match.drun-run.ok delete mode 100644 test/run-drun/ok/shared-match.ic-stub-run.ok delete mode 100644 test/run-drun/ok/shared-match.run-ir.ok delete mode 100644 test/run-drun/ok/shared-match.run-low.ok delete mode 100644 test/run-drun/ok/shared-match.run.ok delete mode 100644 test/run-drun/ok/shared-match.tc.ok delete mode 100644 test/run-drun/shared-match.mo diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index ebbcf28df98..7e867bbb973 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -324,9 +324,7 @@ let transform mode env prog = let r = [e] -->* (ic_rejectE (errorMessageE e)) in let exp' = callE (t_exp cps) [t0] (tupE [k;r]) in FuncE (x, T.Shared s', Replies, typbinds', args', ret_tys, exp') - (* oneway with an `ignore(async _)` body - TODO: remove this special casing once async fully supported - *) + (* oneway, always with `ignore(async _)` body *) | Returns, { it = BlockE ( [{ it = LetD ( @@ -353,9 +351,8 @@ let transform mode env prog = let r = [e] -->* tupE [] in (* discard error *) let exp' = callE (t_exp cps) [t0] (tupE [k;r]) in FuncE (x, T.Shared s', Returns, typbinds', args', ret_tys, exp') - (* sequential oneway *) | Returns, _ -> - FuncE (x, s, c, t_typ_binds typbinds, t_args args, List.map t_typ ret_tys, t_exp exp) + assert false | Replies,_ -> assert false end end diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 45df586e494..699e6b3de11 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -90,7 +90,7 @@ and exp' at note = function let t = T.as_array note.I.note_typ in I.PrimE (I.ArrayPrim (mut m, T.as_immut t), exps es) | S.IdxE (e1, e2) -> I.PrimE (I.IdxPrim, [exp e1; exp e2]) - | S.FuncE (name, sp, tbs, p, _t_opt, e) -> + | S.FuncE (name, sp, tbs, p, _t_opt, _, e) -> let s, po = match sp.it with | T.Local -> (T.Local, None) | T.Shared (ss, {it = S.WildP; _} ) -> (* don't bother with ctxt pat *) @@ -475,9 +475,13 @@ and to_args typ po p : Ir.arg list * (Ir.exp -> Ir.exp) * T.control * T.typ list in let wrap_under_async e = - if T.is_shared_sort sort && control <> T.Returns - then match e.it with - | Ir.AsyncE (tb, e', t) -> { e with it = Ir.AsyncE (tb, wrap_po e', t) } + if T.is_shared_sort sort + then match control, e.it with + | T.Promises, Ir.AsyncE (tb, e', t) -> { e with it = Ir.AsyncE (tb, wrap_po e', t) } + | T.Returns, Ir.BlockE ( + [{ it = Ir.LetD ({ it = Ir.WildP; _} as pat, ({ it = Ir.AsyncE (tb,e',t); _} as exp)); _ }], + ({ it = Ir.PrimE (Ir.TupPrim, []); _} as unit)) -> + blockE [letP pat {exp with it = Ir.AsyncE (tb,wrap_po e',t)} ] unit | _ -> assert false else wrap_po e in diff --git a/src/mo_def/arrange.ml b/src/mo_def/arrange.ml index d1878abcf91..bf1ee30e629 100644 --- a/src/mo_def/arrange.ml +++ b/src/mo_def/arrange.ml @@ -25,7 +25,7 @@ let rec exp e = match e.it with | AssignE (e1, e2) -> "AssignE" $$ [exp e1; exp e2] | ArrayE (m, es) -> "ArrayE" $$ [mut m] @ List.map exp es | IdxE (e1, e2) -> "IdxE" $$ [exp e1; exp e2] - | FuncE (x, sp, tp, p, t, e') -> + | FuncE (x, sp, tp, p, t, sugar, e') -> "FuncE" $$ [ Atom (Type.string_of_typ e.note.note_typ); sort_pat sp; @@ -33,6 +33,7 @@ let rec exp e = match e.it with List.map typ_bind tp @ [ pat p; (match t with None -> Atom "_" | Some t -> typ t); + Atom (if sugar then "" else "="); exp e' ] | CallE (e1, ts, e2) -> "CallE" $$ [exp e1] @ inst ts @ [exp e2] diff --git a/src/mo_def/syntax.ml b/src/mo_def/syntax.ml index 89d0f07bbbb..9eff044ceea 100644 --- a/src/mo_def/syntax.ml +++ b/src/mo_def/syntax.ml @@ -122,6 +122,15 @@ type inst = (typ list, Type.typ list) Source.annotated_phrase (* For implicit sc type sort_pat = (Type.shared_sort * pat) Type.shared Source.phrase +type sugar = bool (* Is the source of a function body a block ``, + subject to further desugaring during parse, + or the invariant form `= `. + In the final output of the parser, the exp in FuncE is + always in its fully desugared form and the + value of the sugar field is irrelevant. + This flag is used to correctly desugar an actor's + public functions as oneway, shared functions *) + type exp = (exp', typ_note) Source.annotated_phrase and exp' = | PrimE of string (* primitive *) @@ -141,7 +150,7 @@ and exp' = | AssignE of exp * exp (* assignment *) | ArrayE of mut * exp list (* array *) | IdxE of exp * exp (* array indexing *) - | FuncE of string * sort_pat * typ_bind list * pat * typ option * exp (* function *) + | FuncE of string * sort_pat * typ_bind list * pat * typ option * sugar * exp (* function *) | CallE of exp * inst * exp (* function call *) | BlockE of dec list (* block (with type after avoidance)*) | NotE of exp (* negation *) @@ -269,7 +278,8 @@ let ensure_scope_bind var tbs = | _ -> scope_bind var::tbs -let funcT(sort, tbs, t1, t2) = + +let funcT (sort, tbs, t1, t2) = match sort.it, t2.it with | Type.Local, AsyncT _ -> FuncT(sort, ensure_scope_bind "" tbs, t1, t2) @@ -278,11 +288,43 @@ let funcT(sort, tbs, t1, t2) = | _ -> FuncT(sort, tbs, t1, t2) -let funcE(f, s, tbs, p, t_opt, e) = +let is_Async e = + match e.it with + | AsyncE _ -> true + | _ -> false + +let is_IgnoreAsync e = + match e.it with + | BlockE [ { it = IgnoreD + { it = AnnotE ({ it = AsyncE _; _}, + { it = AsyncT (_, { it = TupT[]; _}); _}); _}; _}] -> + true + | _ -> false + +let async f e = + AsyncE (scope_bind f, e) @? e.at + +let ignoreAsync f e = + BlockE [ IgnoreD ( + AnnotE (AsyncE (scope_bind f, e) @? e.at, + AsyncT (scope_typ e.at,TupT[] @! e.at) @! e.at) @? e.at ) @? e.at] @? e.at + +let desugar sp f t_opt (sugar, e) = + match sugar, e with + | (false, e) -> false, e (* body declared as EQ e *) + | (true, e) -> (* body declared as immediate block *) + match sp.it, t_opt with + | _, Some {it = AsyncT _; _} -> + true, async f.it e + | Type.Shared _, (None | Some { it = TupT []; _}) -> + true, ignoreAsync f.it e + | _, _ -> (true, e) + +let funcE (f, s, tbs, p, t_opt, sugar, e) = match s.it, t_opt, e with | Type.Local, Some { it = AsyncT _; _}, {it = AsyncE _; _} | Type.Shared _, _, _ -> - FuncE(f, s, ensure_scope_bind "" tbs, p, t_opt, e) + FuncE(f, s, ensure_scope_bind "" tbs, p, t_opt, sugar, e) | _ -> - FuncE(f, s, tbs, p, t_opt, e) + FuncE(f, s, tbs, p, t_opt, sugar, e) diff --git a/src/mo_frontend/definedness.ml b/src/mo_frontend/definedness.ml index 4fd1ef3325a..c6a59d6c329 100644 --- a/src/mo_frontend/definedness.ml +++ b/src/mo_frontend/definedness.ml @@ -86,7 +86,7 @@ let rec exp msgs e : f = match e.it with | RetE e -> eagerify (exp msgs e) | ThrowE e -> eagerify (exp msgs e) (* Uses are delayed by function expressions *) - | FuncE (_, sort_pat, tp, p, t, e) -> + | FuncE (_, sort_pat, tp, p, t, _, e) -> (match sort_pat.it with | Type.Local -> delayify (exp msgs e /// pat msgs p) diff --git a/src/mo_frontend/parser.mly b/src/mo_frontend/parser.mly index 030953979c6..dffbf0834ea 100644 --- a/src/mo_frontend/parser.mly +++ b/src/mo_frontend/parser.mly @@ -71,8 +71,11 @@ let share_typfield (tf : typ_field) = let share_exp e = match e.it with - | FuncE (x, ({it = Type.Local; _} as s), tbs, p, t, e) -> - funcE (x, {s with it = Type.Shared (Type.Write, WildP @! s.at)}, tbs, p, t, e) @? e.at + | FuncE (x, ({it = Type.Local; _} as sp), tbs, p, + ((None | Some { it = TupT []; _ }) as t_opt), true, e) -> + funcE (x, {sp with it = Type.Shared (Type.Write, WildP @! sp.at)}, tbs, p, t_opt, true, ignoreAsync x e) @? e.at + | FuncE (x, ({it = Type.Local; _} as sp), tbs, p, t_opt, s, e) -> + funcE (x, {sp with it = Type.Shared (Type.Write, WildP @! sp.at)}, tbs, p, t_opt, s, e) @? e.at | _ -> e let share_dec d = @@ -673,15 +676,8 @@ dec_nonvar : These should be defined using RHS syntax EQ e to avoid the implicit AsyncE introduction around bodies declared as blocks *) let named, x = xf "func" $sloc in - let e = match fb with - | (false, e) -> e (* body declared as EQ e *) - | (true, e) -> (* body declared as immediate block *) - match t with - | Some {it = AsyncT _; _} -> - AsyncE(scope_bind x.it, e) @? e.at - | _ -> e - in - let_or_exp named x (funcE(x.it, sp, tps, p, t, e)) (at $sloc) } + let (sugar, e) = desugar sp x t fb in + let_or_exp named x (funcE(x.it, sp, tps, p, t, sugar, e)) (at $sloc) } | s=obj_sort_opt CLASS xf=typ_id_opt tps=typ_params_opt p=pat_param t=return_typ? cb=class_body { let x, efs = cb in diff --git a/src/mo_frontend/traversals.ml b/src/mo_frontend/traversals.ml index 352114da096..ad767f59aaf 100644 --- a/src/mo_frontend/traversals.ml +++ b/src/mo_frontend/traversals.ml @@ -55,8 +55,8 @@ let rec over_exp (f : exp -> exp) (exp : exp) : exp = match exp.it with f { exp with it = TryE (over_exp f exp1, List.map (over_case f) cases) } | SwitchE (exp1, cases) -> f { exp with it = SwitchE (over_exp f exp1, List.map (over_case f) cases) } - | FuncE (a, b, c, d, g, e) -> - f { exp with it = FuncE (a, b, c, d, g, over_exp f e) } + | FuncE (name, sort_pat, typ_binds, pat, typ_opt, sugar, exp1) -> + f { exp with it = FuncE (name, sort_pat, typ_binds, pat, typ_opt, sugar, over_exp f exp1) } and over_dec (f : exp -> exp) (d : dec) : dec = match d.it with | TypD _ -> d diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 2de84c4c310..698a36a869c 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -600,11 +600,6 @@ let text_obj () = (* Expressions *) -let isAsyncE exp = - match exp.it with - | AsyncE _ -> true - | _ -> false - let rec infer_exp env exp : T.typ = infer_exp' T.as_immut env exp @@ -776,7 +771,7 @@ and infer_exp'' env exp : T.typ = "expected array type, but expression produces type\n %s" (T.string_of_typ_expand t1) ) - | FuncE (_, sort_pat, typ_binds, pat, typ_opt, exp) -> + | FuncE (_, sort_pat, typ_binds, pat, typ_opt, _sugar, exp) -> if not env.pre && not in_actor && T.is_shared_sort sort_pat.it then error_in [Flags.ICMode; Flags.StubMode] env exp.at "a shared function is only allowed as a public field of an actor"; let typ = match typ_opt with @@ -788,7 +783,7 @@ and infer_exp'' env exp : T.typ = let c, ts2 = as_codomT sort typ in check_shared_return env typ.at sort c ts2; let env' = infer_async_cap (adjoin_typs env te ce) sort cs tbs in - let t1, ve1 = infer_pat_exhaustive env' pat in + let t1, ve1 = infer_pat_exhaustive (if T.is_shared_sort sort then local_error else warn) env' pat in let ve2 = T.Env.adjoin ve ve1 in let ts2 = List.map (check_typ env') ts2 in let codom = T.codom c (fun () -> T.Con(List.hd cs,[])) ts2 in @@ -812,9 +807,12 @@ and infer_exp'' env exp : T.typ = (T.string_of_typ_expand t); ) ts2; match c, ts2 with - | T.Returns, [] when sort = T.Shared T.Write -> () + | T.Returns, [] when sort = T.Shared T.Write -> + if not (is_IgnoreAsync exp) then + error env exp.at + "shared function with () result type has unexpected body:\n the body must either be of sugared form '{ ... }' \n or explicit form '= ignore ((async ...) : async ())'" | T.Promises, _ -> - if not (isAsyncE exp) then + if not (is_Async exp) then error env exp.at "shared function with async result type has non-async body" | _ -> @@ -939,7 +937,7 @@ and infer_exp'' env exp : T.typ = let t1, t2 = T.as_mono_func_sub t in if not (T.sub T.unit t1) then raise (Invalid_argument ""); let t2' = T.as_opt_sub t2 in - let ve = check_pat_exhaustive env t2' pat in + let ve = check_pat_exhaustive warn env t2' pat in check_exp (adjoin_vals env ve) T.unit exp2 with Invalid_argument _ | Not_found -> local_error env exp1.at @@ -1107,11 +1105,11 @@ and check_exp' env0 t exp : T.typ = ); t (* TODO: allow shared with one scope par *) - | FuncE (_, sort_pat, [], pat, typ_opt, exp), T.Func (s, c, [], ts1, ts2) -> + | FuncE (_, sort_pat, [], pat, typ_opt, _sugar, exp), T.Func (s, c, [], ts1, ts2) -> let sort, ve = check_sort_pat env sort_pat in if not env.pre && not env0.in_actor && T.is_shared_sort sort then error_in [Flags.ICMode; Flags.StubMode] env exp.at "a shared function is only allowed as a public field of an actor"; - let ve1 = check_pat_exhaustive env (T.seq ts1) pat in + let ve1 = check_pat_exhaustive (if T.is_shared_sort sort then local_error else warn) env (T.seq ts1) pat in let ve2 = T.Env.adjoin ve ve1 in let codom = T.codom c (fun () -> assert false) ts2 in let t2 = match typ_opt with @@ -1177,13 +1175,13 @@ and inconsistent t ts = (* Patterns *) -and infer_pat_exhaustive env pat : T.typ * Scope.val_env = +and infer_pat_exhaustive warnOrError env pat : T.typ * Scope.val_env = let t, ve = infer_pat env pat in if not env.pre then begin match Coverage.check_pat pat t with | [] -> () | ss -> - warn env pat.at + warnOrError env pat.at "this pattern consuming type\n %s\ndoes not cover value\n %s" (Type.string_of_typ_expand t) (String.concat " or\n " ss) @@ -1264,15 +1262,15 @@ and check_sort_pat env sort_pat : T.func_sort * Scope.val_env = | T.Shared (ss, pat) -> if pat.it <> WildP then error_in [Flags.WASIMode; Flags.WasmMode] env pat.at "shared function cannot take a context pattern"; - T.Shared ss, check_pat_exhaustive env T.ctxt pat + T.Shared ss, check_pat_exhaustive local_error env T.ctxt pat -and check_pat_exhaustive env t pat : Scope.val_env = +and check_pat_exhaustive warnOrError env t pat : Scope.val_env = let ve = check_pat env t pat in if not env.pre then begin match Coverage.check_pat pat t with | [] -> () | ss -> - warn env pat.at + warnOrError env pat.at "this pattern consuming type\n %s\ndoes not cover value\n %s" (Type.string_of_typ_expand t) (String.concat " or\n " ss) @@ -1528,7 +1526,7 @@ and object_of_scope env sort fields scope at = (T.string_of_typ_expand t) and is_actor_method dec : bool = match dec.it with - | LetD ({it = VarP _; _}, {it = FuncE (_, sort_pat, _, _, _, _); _}) -> + | LetD ({it = VarP _; _}, {it = FuncE (_, sort_pat, _, _, _, _, _); _}) -> T.is_shared_sort sort_pat.it | _ -> false @@ -1610,7 +1608,7 @@ and infer_dec env dec : T.typ = let c = T.Env.find id.it env.typs in let cs, _ts, te, ce = check_typ_binds env typ_binds in let env' = adjoin_typs env te ce in - let _, ve = infer_pat_exhaustive env' pat in + let _, ve = infer_pat_exhaustive (if sort.it = T.Actor then error else warn) env' pat in let env'' = adjoin_vals env' ve in let self_typ = T.Con (c, List.map (fun c -> T.Con (c, [])) cs) in let env''' = @@ -1878,7 +1876,7 @@ and infer_dec_valdecs env dec : Scope.t = Scope.{empty with val_env = T.Env.singleton id.it obj_typ} | LetD (pat, exp) -> let t = infer_exp {env with pre = true} exp in - let ve' = check_pat_exhaustive env t pat in + let ve' = check_pat_exhaustive warn env t pat in Scope.{empty with val_env = ve'} | VarD (id, exp) -> let t = infer_exp {env with pre = true} exp in diff --git a/src/mo_interpreter/interpret.ml b/src/mo_interpreter/interpret.ml index f7d82e0e889..bcc3abbb206 100644 --- a/src/mo_interpreter/interpret.ml +++ b/src/mo_interpreter/interpret.ml @@ -492,7 +492,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = with Invalid_argument s -> trap exp.at "%s" s) ) ) - | FuncE (name, sort_pat, _typbinds, pat, _typ, exp2) -> + | FuncE (name, sort_pat, _typbinds, pat, _typ, _sugar, exp2) -> let f = interpret_func env name sort_pat pat (fun env' -> interpret_exp env' exp2) in let v = V.Func (CC.call_conv_of_typ exp.note.note_typ, f) in let v' = diff --git a/test/fail/abstract-msgs.mo b/test/fail/abstract-msgs.mo index c3dbe6889f7..35472ca0fc8 100644 --- a/test/fail/abstract-msgs.mo +++ b/test/fail/abstract-msgs.mo @@ -19,5 +19,5 @@ // Phantom parameters are fine { type X = shared () -> (); - func foo() { shared func bar(f : X) = (); () } + func foo() { shared func bar(f : X) {}; () } }; diff --git a/test/fail/duplicate-field.mo b/test/fail/duplicate-field.mo index 0dbd8e705f1..5e3fda41fea 100644 --- a/test/fail/duplicate-field.mo +++ b/test/fail/duplicate-field.mo @@ -29,7 +29,7 @@ ignore(object {public func foo() = (); public func nxnnbkddcv() = ()}); }; { -ignore(actor {public func foo() = (); public func nxnnbkddcv() = ()}); +ignore(actor {public func foo() {}; public func nxnnbkddcv() {}}); }; { diff --git a/test/fail/ok/duplicate-field.tc.ok b/test/fail/ok/duplicate-field.tc.ok index cf88c6968a6..6a862a781cc 100644 --- a/test/fail/ok/duplicate-field.tc.ok +++ b/test/fail/ok/duplicate-field.tc.ok @@ -5,5 +5,5 @@ duplicate-field.mo:16.23-16.34: type error, tag names foo and nxnnbkddcv in vari duplicate-field.mo:20.18-20.21: type error, duplicate definition for foo in block duplicate-field.mo:24.8-24.36: type error, field names nxnnbkddcv and foo in object type have colliding hashes duplicate-field.mo:28.8-28.70: type error, field names nxnnbkddcv and foo in object type have colliding hashes -duplicate-field.mo:32.8-32.69: type error, field names nxnnbkddcv and foo in actor object type have colliding hashes +duplicate-field.mo:32.8-32.65: type error, field names nxnnbkddcv and foo in actor object type have colliding hashes duplicate-field.mo:36.8-36.70: type error, field names nxnnbkddcv and foo in module object type have colliding hashes diff --git a/test/fail/ok/oneways.tc.ok b/test/fail/ok/oneways.tc.ok new file mode 100644 index 00000000000..29437d351fe --- /dev/null +++ b/test/fail/ok/oneways.tc.ok @@ -0,0 +1,12 @@ +oneways.mo:8.25-8.27: type error, shared function with () result type has unexpected body: + the body must either be of sugared form '{ ... }' + or explicit form '= ignore ((async ...) : async ())' +oneways.mo:9.25-9.40: type error, shared function with () result type has unexpected body: + the body must either be of sugared form '{ ... }' + or explicit form '= ignore ((async ...) : async ())' +oneways.mo:15.24-15.26: type error, shared function with () result type has unexpected body: + the body must either be of sugared form '{ ... }' + or explicit form '= ignore ((async ...) : async ())' +oneways.mo:16.24-16.39: type error, shared function with () result type has unexpected body: + the body must either be of sugared form '{ ... }' + or explicit form '= ignore ((async ...) : async ())' diff --git a/test/fail/ok/oneways.tc.ret.ok b/test/fail/ok/oneways.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/oneways.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/shared-nonexhaustive.tc.ok b/test/fail/ok/shared-nonexhaustive.tc.ok new file mode 100644 index 00000000000..63575ba1335 --- /dev/null +++ b/test/fail/ok/shared-nonexhaustive.tc.ok @@ -0,0 +1,20 @@ +shared-nonexhaustive.mo:3.19-3.32: type error, this pattern consuming type + Bool +does not cover value + false +shared-nonexhaustive.mo:5.21-5.34: type error, this pattern consuming type + Bool +does not cover value + false +shared-nonexhaustive.mo:5.2-5.75: type error, expression of type + shared Bool -> async () +cannot produce expected type + () +shared-nonexhaustive.mo:7.19-7.32: type error, this pattern consuming type + Bool +does not cover value + false +shared-nonexhaustive.mo:9.21-9.34: type error, this pattern consuming type + Bool +does not cover value + false diff --git a/test/fail/ok/shared-nonexhaustive.tc.ret.ok b/test/fail/ok/shared-nonexhaustive.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/shared-nonexhaustive.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/oneways.mo b/test/fail/oneways.mo new file mode 100644 index 00000000000..b020648838c --- /dev/null +++ b/test/fail/oneways.mo @@ -0,0 +1,17 @@ +// check explicit oneway declarations + +actor a { + + public func ok1() {}; + public func ok2() = ignore ((async ()) : async ()); + + public func wrong1() = (); + public func wrong2() = ignore async (); +}; + +shared func ok1() {}; +shared func ok2() = ignore ((async ()) : async ()) ; +shared func ok3() = ignore ((async return) : async ()) ; +shared func wrong1() = (); +shared func wrong2() = ignore async (); + diff --git a/test/fail/shared-nonexhaustive.mo b/test/fail/shared-nonexhaustive.mo new file mode 100644 index 00000000000..9fe7ff83fc5 --- /dev/null +++ b/test/fail/shared-nonexhaustive.mo @@ -0,0 +1,9 @@ +// patterns on shared functions must be exhaustive + +shared func wrong1(true : Bool) : async () {}; + +((shared func wrong2(true : Bool) : async () {}) : shared Bool -> async ()); + +shared func wrong2(true : Bool) {}; + +((shared func wrong2(true : Bool) {}) : shared Bool -> ()); diff --git a/test/run-drun/async-calls3.mo b/test/run-drun/async-calls3.mo index 1adaa455d7a..ef71d974c47 100644 --- a/test/run-drun/async-calls3.mo +++ b/test/run-drun/async-calls3.mo @@ -16,4 +16,4 @@ actor a { test(true); } }; -a.go(); //OR-CALL ingress go "DIDL\x00\x00" +//a.go(); //OR-CALL ingress go "DIDL\x00\x00" diff --git a/test/run-drun/async-free-var.mo b/test/run-drun/async-free-var.mo index 88f77165736..490e6737cde 100644 --- a/test/run-drun/async-free-var.mo +++ b/test/run-drun/async-free-var.mo @@ -1,6 +1,6 @@ import Prim "mo:prim"; actor a { - public func go() = ignore async { + public func go() { var x = "A"; Prim.debugPrint x; let a = async { diff --git a/test/run-drun/async-loop-while.mo b/test/run-drun/async-loop-while.mo index d3542dab4bb..4207cd52daa 100644 --- a/test/run-drun/async-loop-while.mo +++ b/test/run-drun/async-loop-while.mo @@ -1,6 +1,6 @@ import Prim "mo:prim"; actor a { - public func go() = ignore async { + public func go() { { var i = 0; var j = 0; loop { diff --git a/test/run-drun/async-loop.mo b/test/run-drun/async-loop.mo index aec697dacaf..a91ab009dcf 100644 --- a/test/run-drun/async-loop.mo +++ b/test/run-drun/async-loop.mo @@ -1,6 +1,6 @@ import Prim "mo:prim"; actor a { - public func go() = ignore async { + public func go() { { var i = 0; var j = 0; label l diff --git a/test/run-drun/async-new-obj.mo b/test/run-drun/async-new-obj.mo index 15f30b1870d..50e15995503 100644 --- a/test/run-drun/async-new-obj.mo +++ b/test/run-drun/async-new-obj.mo @@ -1,6 +1,6 @@ import Prim "mo:prim"; actor a { - public func go() = ignore async { + public func go() { /* Test asynchronous construction of an object */ let a = async { diff --git a/test/run-drun/async-obj-mut.mo b/test/run-drun/async-obj-mut.mo index a2624f73331..421a7eee950 100644 --- a/test/run-drun/async-obj-mut.mo +++ b/test/run-drun/async-obj-mut.mo @@ -1,6 +1,6 @@ import Prim "mo:prim"; actor a { - public func go() = ignore async { + public func go() { let o = object { public var x = await { async { 1 } }; let a = Prim.debugPrintNat(x); diff --git a/test/run-drun/async-while.mo b/test/run-drun/async-while.mo index 56ec373b2de..b31684e1d1f 100644 --- a/test/run-drun/async-while.mo +++ b/test/run-drun/async-while.mo @@ -1,6 +1,6 @@ import Prim "mo:prim"; actor a { - public func go() = ignore async { + public func go() { { var i = 0; var j = 0; while (j <= 2) { diff --git a/test/run-drun/block.mo b/test/run-drun/block.mo index e50efce4f50..c40405adb8d 100644 --- a/test/run-drun/block.mo +++ b/test/run-drun/block.mo @@ -1,6 +1,6 @@ import Prim "mo:prim"; actor a { - public func go() = ignore { + public func go() { let a = async { let (a,b) = ("a1","b1"); Prim.debugPrint a; diff --git a/test/run-drun/count-callbacks.mo b/test/run-drun/count-callbacks.mo index 97dec174607..4e03fff646d 100644 --- a/test/run-drun/count-callbacks.mo +++ b/test/run-drun/count-callbacks.mo @@ -5,7 +5,7 @@ actor a { Prim.debugPrint("ping! " # debug_show Prim.rts_callback_table_count()); }; - public func go() = ignore async { + public func go() { Prim.debugPrint("go 1: " # debug_show Prim.rts_callback_table_count()); let a1 = ping(); Prim.debugPrint("go 1: " # debug_show Prim.rts_callback_table_count()); diff --git a/test/run-drun/data-params.mo b/test/run-drun/data-params.mo index 8a014db2dad..d8601f83627 100644 --- a/test/run-drun/data-params.mo +++ b/test/run-drun/data-params.mo @@ -47,7 +47,8 @@ actor a { Prim.debugPrint l; Prim.debugPrintInt(c); }; - public func printLabeledOpt(?l:?Text) { + public func printLabeledOpt(lo:?Text) { + let ?l = lo; Prim.debugPrint l; Prim.debugPrintInt(c); }; diff --git a/test/run-drun/flatten-awaitables.mo b/test/run-drun/flatten-awaitables.mo index 34f33152c1e..cb87a65c3ae 100644 --- a/test/run-drun/flatten-awaitables.mo +++ b/test/run-drun/flatten-awaitables.mo @@ -31,7 +31,7 @@ let a = actor { public func g3 (f3:shared ((Int,Bool,Text)) -> async (Int,Bool,Text), xyz:(Int,Bool,Text)) : async (Int,Bool,Text) { await f3 xyz; }; - public func go() = ignore async { + public func go() { Prim.debugPrint "first-order"; diff --git a/test/run-drun/for-await.mo b/test/run-drun/for-await.mo index 724fe878972..8dc4cfd84d4 100644 --- a/test/run-drun/for-await.mo +++ b/test/run-drun/for-await.mo @@ -7,7 +7,7 @@ class range(x : Nat, y : Nat) { actor a { - public func go() = ignore async { + public func go() { { var i = 0; i := 0; diff --git a/test/run-drun/free-callbacks.mo b/test/run-drun/free-callbacks.mo index 7c31aa1bdd3..1c0e92a201b 100644 --- a/test/run-drun/free-callbacks.mo +++ b/test/run-drun/free-callbacks.mo @@ -3,7 +3,7 @@ actor a { public func ping() : async () { }; - public func go() = ignore async { + public func go() { let s0 = Prim.rts_heap_size(); let a = Prim.Array_init<()>(2500, ()); await ping(); diff --git a/test/run-drun/hello-world-await.mo b/test/run-drun/hello-world-await.mo index 841f6a86052..7d9e66bbe83 100644 --- a/test/run-drun/hello-world-await.mo +++ b/test/run-drun/hello-world-await.mo @@ -6,7 +6,7 @@ let a = actor { public func world() : async Text { "World!" }; - public func go() = ignore async { + public func go() { Prim.debugPrint((await hello()) # (await world())); }; }; diff --git a/test/run-drun/ic-calls.mo b/test/run-drun/ic-calls.mo index 770d9422710..14922c2a763 100644 --- a/test/run-drun/ic-calls.mo +++ b/test/run-drun/ic-calls.mo @@ -10,7 +10,7 @@ actor a { (x,y); }; - public func go() = ignore async { + public func go() { let () = await A(); let 1 = await B(1); let (1,true) = await C(1,true); diff --git a/test/run-drun/local-throw.mo b/test/run-drun/local-throw.mo index 48ec018fb55..944f963a7d3 100644 --- a/test/run-drun/local-throw.mo +++ b/test/run-drun/local-throw.mo @@ -49,7 +49,7 @@ actor a { }; - public func go() = ignore async { + public func go() { try { await t2(); Prim.debugPrint ("t2 ok"); diff --git a/test/run-drun/ok/data-params.tc.ok b/test/run-drun/ok/data-params.tc.ok index 8669117887e..7a81a2cf18f 100644 --- a/test/run-drun/ok/data-params.tc.ok +++ b/test/run-drun/ok/data-params.tc.ok @@ -1,4 +1,4 @@ -data-params.mo:50.30-50.40: warning, this pattern consuming type +data-params.mo:51.9-51.11: warning, this pattern consuming type ?Text does not cover value null diff --git a/test/run-drun/ok/self-shadow.comp-stub.ok b/test/run-drun/ok/self-shadow.comp-stub.ok index b608bf88ec7..8765182a4d1 100644 --- a/test/run-drun/ok/self-shadow.comp-stub.ok +++ b/test/run-drun/ok/self-shadow.comp-stub.ok @@ -1,2 +1,2 @@ -self-shadow.mo:5.15-5.51: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program +self-shadow.mo:5.15-5.49: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program (This is a limitation of the current version and flag -stub-system-api.) diff --git a/test/run-drun/ok/self-shadow.comp.ok b/test/run-drun/ok/self-shadow.comp.ok index 5c6dae24bf6..a31f5a9e1e3 100644 --- a/test/run-drun/ok/self-shadow.comp.ok +++ b/test/run-drun/ok/self-shadow.comp.ok @@ -1,2 +1,2 @@ -self-shadow.mo:5.15-5.51: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program +self-shadow.mo:5.15-5.49: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program (This is a limitation of the current version.) diff --git a/test/run-drun/ok/shared-match.diff-ir.ok b/test/run-drun/ok/shared-match.diff-ir.ok deleted file mode 100644 index d1bad30548b..00000000000 --- a/test/run-drun/ok/shared-match.diff-ir.ok +++ /dev/null @@ -1,7 +0,0 @@ ---- shared-match.run -+++ shared-match.run-ir -@@ -1,3 +1,3 @@ - go1 - match_true --shared-match.mo:8.25-8.31: execution error, argument value false does not match parameter list -+shared-match.mo:8.25-8.31: execution error, value false does not match pattern diff --git a/test/run-drun/ok/shared-match.diff-low.ok b/test/run-drun/ok/shared-match.diff-low.ok deleted file mode 100644 index de911e913e8..00000000000 --- a/test/run-drun/ok/shared-match.diff-low.ok +++ /dev/null @@ -1,7 +0,0 @@ ---- shared-match.run -+++ shared-match.run-low -@@ -1,3 +1,3 @@ - go1 - match_true --shared-match.mo:8.25-8.31: execution error, argument value false does not match parameter list -+shared-match.mo:8.25-8.31: execution error, value false does not match pattern diff --git a/test/run-drun/ok/shared-match.drun-run.ok b/test/run-drun/ok/shared-match.drun-run.ok deleted file mode 100644 index 906299ef1d1..00000000000 --- a/test/run-drun/ok/shared-match.drun-run.ok +++ /dev/null @@ -1,5 +0,0 @@ -ingress System -debug.print: go1 -debug.print: match_true -debug.print: go2 -ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/shared-match.ic-stub-run.ok b/test/run-drun/ok/shared-match.ic-stub-run.ok deleted file mode 100644 index 9a6b457bbc4..00000000000 --- a/test/run-drun/ok/shared-match.ic-stub-run.ok +++ /dev/null @@ -1,10 +0,0 @@ -→ create -← completed: canister-id = 0x2a01 -→ install -← completed -→ update go(0x4449444c0000) -debug.print: go1 -debug.print: match_true -Trap: EvalTrapError :0.1 "canister trapped explicitly: pattern failed" -debug.print: go2 -← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/shared-match.run-ir.ok b/test/run-drun/ok/shared-match.run-ir.ok deleted file mode 100644 index a07bd253201..00000000000 --- a/test/run-drun/ok/shared-match.run-ir.ok +++ /dev/null @@ -1,3 +0,0 @@ -go1 -match_true -shared-match.mo:8.25-8.31: execution error, value false does not match pattern diff --git a/test/run-drun/ok/shared-match.run-low.ok b/test/run-drun/ok/shared-match.run-low.ok deleted file mode 100644 index a07bd253201..00000000000 --- a/test/run-drun/ok/shared-match.run-low.ok +++ /dev/null @@ -1,3 +0,0 @@ -go1 -match_true -shared-match.mo:8.25-8.31: execution error, value false does not match pattern diff --git a/test/run-drun/ok/shared-match.run.ok b/test/run-drun/ok/shared-match.run.ok deleted file mode 100644 index 8318ff7a636..00000000000 --- a/test/run-drun/ok/shared-match.run.ok +++ /dev/null @@ -1,3 +0,0 @@ -go1 -match_true -shared-match.mo:8.25-8.31: execution error, argument value false does not match parameter list diff --git a/test/run-drun/ok/shared-match.tc.ok b/test/run-drun/ok/shared-match.tc.ok deleted file mode 100644 index dc982dc11f8..00000000000 --- a/test/run-drun/ok/shared-match.tc.ok +++ /dev/null @@ -1,4 +0,0 @@ -shared-match.mo:8.25-8.31: warning, this pattern consuming type - Bool -does not cover value - false diff --git a/test/run-drun/ok/test_oneway.tc.ok b/test/run-drun/ok/test_oneway.tc.ok index 60dfe4908cf..3b4ae092109 100644 --- a/test/run-drun/ok/test_oneway.tc.ok +++ b/test/run-drun/ok/test_oneway.tc.ok @@ -1 +1 @@ -oneway.mo:68.1-68.7: type error, non-static expression in library or module +oneway.mo:60.1-60.7: type error, non-static expression in library or module diff --git a/test/run-drun/oneway-throw.mo b/test/run-drun/oneway-throw.mo index 12362206a63..ef858daa4fc 100644 --- a/test/run-drun/oneway-throw.mo +++ b/test/run-drun/oneway-throw.mo @@ -1,7 +1,7 @@ import Prim "mo:prim"; actor a { var committed = false; - public func throws() : () = ignore async { + public func throws() : () { Prim.debugPrint "throws()"; committed := true; throw (Prim.error("ignored")); @@ -10,7 +10,7 @@ actor a { public func ping() : async () { Prim.debugPrint "ping()"; }; - public func go() = ignore async { + public func go() { Prim.debugPrint "go1"; throws(); await ping(); // in-order delivery guarantees that throw ran diff --git a/test/run-drun/oneway.mo b/test/run-drun/oneway.mo index 899975e285f..0812aee17a4 100644 --- a/test/run-drun/oneway.mo +++ b/test/run-drun/oneway.mo @@ -2,58 +2,50 @@ import Prim "mo:prim"; actor a { // test that oneways can locally try/throw public func oneway() : () { - ignore ( - async { - Prim.debugPrint "1"; - try { - throw (Prim.error("Error")); - Prim.debugPrint "unreachable"; - } - catch e { Prim.debugPrint "2"}; - } - ) + Prim.debugPrint "1"; + try { + throw (Prim.error("Error")); + Prim.debugPrint "unreachable"; + } + catch e { Prim.debugPrint "2"}; }; // test that oneways can locally try/throw // using `=` syntax public func onewayAlt() : () = ignore ( - async { + (async { Prim.debugPrint "3"; try { throw (Prim.error("Error")); Prim.debugPrint "unreachable"; } catch e { Prim.debugPrint "4"}; - } + }) : async () ); // test that throws from oneways are silently discarded (because replies are eager) public func discard() : () { - ignore ( - async { - Prim.debugPrint "5"; - throw (Prim.error("ignored")); - Prim.debugPrint "unreachable"; - } - ) + Prim.debugPrint "5"; + throw (Prim.error("ignored")); + Prim.debugPrint "unreachable"; }; // test that throws from oneways are silently discarded (because replies are eager) // using `=` syntax public func discardAlt() : () = ignore ( - async { + (async { Prim.debugPrint "6"; throw (Prim.error("ignored")); Prim.debugPrint "unreachable"; - } + }) : async () ); // TODO test await and calls to shared functions - public func go() = ignore async { + public func go() { Prim.debugPrint("A"); oneway(); Prim.debugPrint("B"); diff --git a/test/run-drun/pass-references.mo b/test/run-drun/pass-references.mo index 318c55b22c9..7d6db7bd48a 100644 --- a/test/run-drun/pass-references.mo +++ b/test/run-drun/pass-references.mo @@ -2,11 +2,11 @@ import Prim "mo:prim"; actor a { public func foo() : async Text = async "a"; - public func pass_func(f : shared () -> async Text) = ignore async { + public func pass_func(f : shared () -> async Text) { Prim.debugPrint (await f()); }; - public func pass_actor(a : actor { foo : shared () -> async Text }) = ignore async { + public func pass_actor(a : actor { foo : shared () -> async Text }) { Prim.debugPrint (await a.foo()); }; diff --git a/test/run-drun/query2.mo b/test/run-drun/query2.mo index 7f12f2e64ca..32c19cf31b3 100644 --- a/test/run-drun/query2.mo +++ b/test/run-drun/query2.mo @@ -19,7 +19,7 @@ actor counter = { return tmp; }; - public func go() = ignore async { + public func go() { counter.inc(); counter.inc(); counter.inc(); diff --git a/test/run-drun/self-shadow.mo b/test/run-drun/self-shadow.mo index f449eac417a..0243b950df0 100644 --- a/test/run-drun/self-shadow.mo +++ b/test/run-drun/self-shadow.mo @@ -1,8 +1,8 @@ actor foo { - public func foo() = (); + public func foo() {}; func go() { - let bar = actor bar { public func bar() = () } + let bar = actor bar { public func bar() {} } }; } diff --git a/test/run-drun/shared-match.mo b/test/run-drun/shared-match.mo deleted file mode 100644 index 5184542286f..00000000000 --- a/test/run-drun/shared-match.mo +++ /dev/null @@ -1,20 +0,0 @@ -/* this test show a discrepancy between argument pattern match failure in -shared methods in the interpreter (which traps, aborting the caller) -and compiled code (which continues with the caller) -This is expected since the interpreter does not yet turn message traps into rejects. -*/ -import Prim "mo:prim"; -actor a { - public func match_true(true) : async () { - Prim.debugPrint "match_true"; - }; - public func go() = ignore async { - Prim.debugPrint "go1"; - try { await match_true(true) } - catch e {}; - try { await match_true(false) } - catch e {}; - Prim.debugPrint "go2"; - }; -}; -a.go(); //OR-CALL ingress go "DIDL\x00\x00" \ No newline at end of file diff --git a/test/run-drun/shared-object.mo b/test/run-drun/shared-object.mo index db4e1722e68..e4908687c73 100644 --- a/test/run-drun/shared-object.mo +++ b/test/run-drun/shared-object.mo @@ -11,7 +11,7 @@ actor a { case {a; b = {c = ?c}} (a + c) }); - public func go() = ignore async { + public func go() { let b = await (baz foo); assert (b == 42); }; diff --git a/test/run-drun/throw.mo b/test/run-drun/throw.mo index b8e8327f916..0ad119bccfd 100644 --- a/test/run-drun/throw.mo +++ b/test/run-drun/throw.mo @@ -55,7 +55,7 @@ actor a { }; - public func go() = ignore async { + public func go() { try { await t2(); Prim.debugPrint ("t2 ok"); diff --git a/test/run-drun/transpose.mo b/test/run-drun/transpose.mo index 6cef2496bfb..b20ce73e336 100644 --- a/test/run-drun/transpose.mo +++ b/test/run-drun/transpose.mo @@ -7,7 +7,7 @@ actor a { } }; - public func go() = ignore async { + public func go() { let x = await a.transpose([(1,"Hi"), (2, "Ho")]); assert (x.ints[0] == 1); assert (x.ints[1] == 2); From 20df62263fe1510ee59c8db19f5ec0cd949a368c Mon Sep 17 00:00:00 2001 From: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> Date: Wed, 5 Feb 2020 17:14:52 +0100 Subject: [PATCH 1019/1176] Makes the resolve logic more lenient around extensions (#1184) * Makes the resolve logic more lenient around extension This allows imports like `list.mo` to resolve to `list.mo.mo` or `list.mo/lib.mo`. * Removes the "musn't have extension" error for imports * fixes formatting and test --- src/languageServer/completion.ml | 2 +- src/languageServer/declaration_index.ml | 6 ++-- src/pipeline/resolve_import.ml | 37 ++++++++----------------- src/pipeline/resolve_import.mli | 5 +--- src/pipeline/resolve_import_test.ml | 26 ++++++++--------- test/lsp-int/Main.hs | 4 +-- 6 files changed, 28 insertions(+), 52 deletions(-) diff --git a/src/languageServer/completion.ml b/src/languageServer/completion.ml index 31453761a01..3602e9f43b6 100644 --- a/src/languageServer/completion.ml +++ b/src/languageServer/completion.ml @@ -134,7 +134,7 @@ let completions index logger project_root file_path file_contents line column = let toplevel_decls = let current_module_decls = current_uri_opt - |> opt_bind (fun uri -> DI.lookup_module uri index) + |> opt_bind (fun uri -> DI.lookup_module (Filename.remove_extension uri) index) |> Option.fold ~none:[] ~some:snd in current_module_decls in diff --git a/src/languageServer/declaration_index.ml b/src/languageServer/declaration_index.ml index e907ed39d2d..e9c508b5102 100644 --- a/src/languageServer/declaration_index.ml +++ b/src/languageServer/declaration_index.ml @@ -71,8 +71,7 @@ let lookup_module match parse path with | Ok (Relative path) -> let path = - Pipeline.ResolveImport.append_extension Sys.file_exists path - |> Result.value ~default:path in + Pipeline.ResolveImport.append_extension Sys.file_exists path in Index.find_opt (make_absolute path) index.modules |> Option.map (fun decls -> (path, decls)) | Ok (Package (pkg, path)) -> @@ -81,8 +80,7 @@ let lookup_module (fun pkg_path -> let path = Pipeline.ResolveImport.append_extension - Sys.file_exists (Filename.concat pkg_path path) - |> Result.value ~default:path in + Sys.file_exists (Filename.concat pkg_path path) in Index.find_opt (make_absolute path) index.modules diff --git a/src/pipeline/resolve_import.ml b/src/pipeline/resolve_import.ml index 753463fcd0a..d12bb919d5e 100644 --- a/src/pipeline/resolve_import.ml +++ b/src/pipeline/resolve_import.ml @@ -85,14 +85,6 @@ let err_file_does_not_exist' at full_path = let err_file_does_not_exist msgs at full_path = Diag.add_msg msgs (err_file_does_not_exist' at full_path) -let err_import_musnt_have_extension at full_path = - Diag.{ - sev = Error; - at; - cat = "import"; - text = Printf.sprintf "an import must not have an extension, try importing %s as %s instead" full_path (Filename.chop_extension full_path) - } - let err_package_not_defined msgs at pkg = let open Diag in add_msg msgs { @@ -139,29 +131,22 @@ let err_prim_pkg msgs = text = "the \"prim\" package is built-in, and cannot be mapped to a directory" } -let append_extension : - (string -> bool) -> - string -> - (string, Source.region -> Diag.message) result = +let append_extension : (string -> bool) -> string -> string = fun file_exists f -> + let file_path = f ^ ".mo" in + let lib_path = Filename.concat f "lib.mo" in if Option.is_some (Lib.String.chop_suffix "/" f) then - Ok (Filename.concat f "lib.mo") - else if Filename.extension f = "" then - if file_exists (f ^ ".mo") then - Ok (f ^ ".mo") - else - Ok (Filename.concat f "lib.mo") + lib_path + else if file_exists file_path then + file_path else - Error (fun at -> err_import_musnt_have_extension at f) + lib_path let resolve_lib_import at full_path : (string, Diag.message) result = - match append_extension Sys.file_exists full_path with - | Ok full_path -> - if Sys.file_exists full_path - then Ok full_path - else Error (err_file_does_not_exist' at full_path) - | Error mk_err -> - Error (mk_err at) + let full_path = append_extension Sys.file_exists full_path in + if Sys.file_exists full_path + then Ok full_path + else Error (err_file_does_not_exist' at full_path) let add_lib_import msgs imported ri_ref at full_path = match resolve_lib_import at full_path with diff --git a/src/pipeline/resolve_import.mli b/src/pipeline/resolve_import.mli index 870f21eb585..171001c7331 100644 --- a/src/pipeline/resolve_import.mli +++ b/src/pipeline/resolve_import.mli @@ -33,7 +33,4 @@ val resolve_flags : flags -> resolved_flags Diag.result val resolve : flags -> Syntax.prog -> filepath -> resolved_imports Diag.result (* Exported for tests *) -val append_extension : - (filepath -> bool) -> - filepath -> - (filepath, Source.region -> Diag.message) result +val append_extension : (filepath -> bool) -> filepath -> filepath diff --git a/src/pipeline/resolve_import_test.ml b/src/pipeline/resolve_import_test.ml index ac08465d75b..836bb1db5c9 100644 --- a/src/pipeline/resolve_import_test.ml +++ b/src/pipeline/resolve_import_test.ml @@ -2,26 +2,22 @@ tests what a given import path resolves to *) let import_relative_test_case files import expected = let actual = - Resolve_import.append_extension (fun x -> List.mem x files) import - |> Result.to_option in - let show = function - | None -> "None" - | Some s -> "Some " ^ s in - Option.equal String.equal actual expected || - (Printf.printf - "\nExpected: %s\nActual: %s\n" - (show expected) - (show actual); + Resolve_import.append_extension (fun x -> List.mem x files) import in + String.equal actual expected || + (Printf.printf "\nExpected: %s\nActual: %s\n" expected actual; false) let%test "it resolves a relative file import" = - import_relative_test_case ["list.mo"] "list" (Some "list.mo") + import_relative_test_case ["list.mo"] "list" "list.mo" + +let%test "it resolves a relative file import for a file with an extension" = + import_relative_test_case ["list.mo.mo"] "list.mo" "list.mo.mo" let%test "it resolves a relative directory import" = - import_relative_test_case [] "list/" (Some "list/lib.mo") + import_relative_test_case ["list.mo"] "list/" "list/lib.mo" let%test "it resolves to a relative directory import if no .mo file is found" = - import_relative_test_case [] "list" (Some "list/lib.mo") + import_relative_test_case [] "list" "list/lib.mo" -let%test "it fails on a relative import with an extension" = - import_relative_test_case [] "list.mo" None +let%test "it succeeds on a relative import with an extension" = + import_relative_test_case [] "list.mo" "list.mo/lib.mo" diff --git a/test/lsp-int/Main.hs b/test/lsp-int/Main.hs index c3eb8f50928..c62ebb12552 100644 --- a/test/lsp-int/Main.hs +++ b/test/lsp-int/Main.hs @@ -160,9 +160,9 @@ main = do actual <- getCompletions doc (Position 7 0) liftIO (shouldBe - ([("empty", Just "() -> Stack")]) (mapMaybe (\c -> guard (c^.label == "empty") - *> pure (c^.label, c^.detail)) actual)) + *> pure (c^.label, c^.detail)) actual) + ([("empty", Just "() -> Stack")])) -- 15 | List.push(x, s); -- ==> 15 | List.pus let edit = TextEdit (Range (Position 14 11) (Position 14 27)) "pus" From b937038c8964230528d8aa82aab480d8f00f4a4a Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 6 Feb 2020 00:20:40 +0100 Subject: [PATCH 1020/1176] Stdlib/hash: Cleanup (#1170) * stdlib/hash: Clean up and document * Stdlib/hash: Cleanup remove the list implementation, format for documentation. * Update some tests * More fixes * Simplify trie * No Hash.t * fix PX --- .../produce-exchange/src/serverModel.mo | 7 +- stdlib/src/hash.mo | 233 ++++-------------- stdlib/src/trie.mo | 21 +- stdlib/src/trieMap.mo | 2 +- stdlib/test/hashMapTest.mo | 6 +- stdlib/test/trieMapTest.mo | 6 +- 6 files changed, 68 insertions(+), 207 deletions(-) diff --git a/stdlib/examples/produce-exchange/src/serverModel.mo b/stdlib/examples/produce-exchange/src/serverModel.mo index e2fc908ac5c..dc634c918bb 100644 --- a/stdlib/examples/produce-exchange/src/serverModel.mo +++ b/stdlib/examples/produce-exchange/src/serverModel.mo @@ -6,7 +6,7 @@ import L "serverLang"; import M "serverModelTypes"; import List "mo:stdlib/list"; -import Hash_ "mo:stdlib/hash"; +import Hash "mo:stdlib/hash"; import Option "mo:stdlib/option"; import Trie "mo:stdlib/trie"; import Iter "mo:stdlib/iter"; @@ -40,10 +40,7 @@ uses are is not. public type List = List.List; - -public let Hash = Hash_.BitVec; -public type Hash = Hash.t; - +public type Hash = Hash.Hash; public type Trie = Trie.Trie; public type TrieBuild = Trie.Build.TrieBuild; public type Key = Trie.Key; diff --git a/stdlib/src/hash.mo b/stdlib/src/hash.mo index 5aae66d3c56..d4e13770bef 100644 --- a/stdlib/src/hash.mo +++ b/stdlib/src/hash.mo @@ -1,86 +1,23 @@ /** [#mod-hash] -= `hash` -- Lists of bits += `hash` -- Hash values */ import Prim "mo:prim"; import Iter "iter"; module { -/* + /** + Hash values represent a string of _hash bits_, packed into a `Word32`. + */ + public type Hash = Word32; -Hash values -=============================== + /** + The hash length, always 31. + */ + public let length : Nat = 31; // Why not 32? -Hash values represent a string of _hash bits_, and support associated _bit string_ operations. - -Representations for `Hash` type ---------------------------------- - -We consider two representations for a hash value: - - - as a linked list of booleans, as `BitList` below; or, - - as a "bit vector" packed into a `Word` type (viz., `Word32`). - - -### Why? - -Initially, during the first implementation of some of the standard -library (e.g., for hash tries), we didn't have access to `Word`-based -operations and hence we instead used bit lists. - -Bit lists are closest to the mathematical definition of finite, but -unbounded bit strings, but the `Word32` provides more efficient -practical operations. - -Now, the language supports `Word` operations, so we will use bit -vectors as the preferred representation for practical system tests -going forward. - -*/ - -/* A "bit string" as a linked list of bits: */ -public type BitList = ?(Bool, BitList); - -/* A "bit vector" is a bounded-length bit string packed into a single word: */ -public type BitVec = Word32; - -/* - - `BitVec` - ---------------------- - A "bit vector" is a bounded-length bit string packed into a single word. - - */ - -public module BitVec { - - public type t = BitVec; - - // Jenkin's one at a time: - // https://en.wikipedia.org/wiki/Jenkins_hash_function#one_at_a_time - // - // The input type should actually be [Word8]. - // Note: Be sure to explode each Word8 of a Word32 into its own Word32, and to shift into lower 8 bits. - public func hashWord8s(key:[BitVec]) : BitVec = label profile_hash_hashWord8s : BitVec { - var hash = Prim.natToWord32(0); - for (wordOfKey in key.vals()) { label profile_hash_hashWord8s_forLoop : () - hash := hash + wordOfKey; - hash := hash + hash << 10; - hash := hash ^ (hash >> 6); - }; - hash := hash + hash << 3; - hash := hash ^ (hash >> 11); - hash := hash + hash << 15; - return hash; - }; - - public func length() : Nat = - label profile_hash_length : Nat - 31; - - public func hashOfInt(i:Int) : BitVec = label profile_hash_hashOfInt : BitVec { - //hashInt(i) + public let hashOfInt : Int -> Hash = func(i) { let j = Prim.intToWord32(i); hashWord8s( [j & (255 << 0), @@ -90,7 +27,10 @@ public module BitVec { ]); }; - public func hashOfIntAcc(h1:BitVec, i:Int) : BitVec = label profile_hash_hashOfIntAcc : BitVec { + /** + WARNING: This only hashes the lowest 32 bits of the `Int` + */ + public let hashOfIntAcc : (Hash, Int) -> Hash = func(h1, i) { let j = Prim.intToWord32(i); hashWord8s( [h1, @@ -101,7 +41,10 @@ public module BitVec { ]); }; - public func hashOfText(t:Text) : BitVec = label profile_hash_hashOfText : BitVec { + /** + WARNING: This only hashes the lowest 32 bits of the `Int` + */ + public let hashOfText : Text -> Hash = func(t) { var x = 0 : Word32; for (c in t.chars()) { x := x ^ Prim.charToWord32(c); @@ -109,27 +52,23 @@ public module BitVec { return x }; - /* Project a given bit from the bit vector. */ - public func getHashBit(h:BitVec, pos:Nat) : Bool = label profile_getHashBit : Bool { - assert (pos <= length()); - if ((h & (Prim.natToWord32(1) << Prim.natToWord32(pos))) != Prim.natToWord32(0)) - { label profile_getHashBit_true : Bool - true - } - else - { label profile_getHashBit_false : Bool - false - } + /** + Project a given bit from the bit vector. + */ + public let getHashBit : (Hash, Nat) -> Bool = func(h, pos) { + assert (pos <= length); + (h & (Prim.natToWord32(1) << Prim.natToWord32(pos))) != Prim.natToWord32(0) }; - /* Test if two lists of bits are equal. */ - public func hashEq(ha:BitVec, hb:BitVec) : Bool { - label profile_hashEq : Bool + /** + Test if two hashes are equal + */ + public let hashEq : (Hash, Hash) -> Bool = func(ha, hb) { ha == hb }; - public func bitsPrintRev(bits:BitVec) { - for (j in Iter.range(0, length() - 1)) { + public let bitsPrintRev : Hash -> () = func(bits) { + for (j in Iter.range(0, length - 1)) { if (getHashBit(bits, j)) { Prim.debugPrint "1" } else { @@ -138,8 +77,8 @@ public module BitVec { } }; - public func hashPrintRev(bits:BitVec) { - for (j in Iter.range(length() - 1, 0)) { + public let hashPrintRev : Hash -> () = func(bits) { + for (j in Iter.range(length - 1, 0)) { if (getHashBit(bits, j)) { Prim.debugPrint "1" } else { @@ -148,97 +87,25 @@ public module BitVec { } }; - public func toList(v:BitVec) : BitList { - func rec(pos:Nat) : BitList { - if (pos >= length()) { null } - else { - let rest = rec(pos + 1); - if (getHashBit(v, pos)) { ?(true, rest) } - else { ?(false, rest) } - } - }; - rec(0) - } - -}; - -/* - - `BitList` - ---------- - - Encode hashes as lists of booleans. - - TODO: Replace with bitwise operations on Words, for greater efficiency. -*/ -public module BitList { - - public type t = BitList; - - public func hashOfInt(i:Int) : BitList { - BitVec.toList(BitVec.hashOfInt(i)) - }; - - /* Test if two lists of bits are equal. */ - public func getHashBit(h:BitList, pos:Nat) : Bool { - switch h { - case null { - // XXX: Should be an error case; it shouldn't happen in our tests if we set them up right. - false - }; - case (?(b, h_)) { - if (pos == 0) { b } - else { getHashBit(h_, pos-1) } - }; - } - }; - - /* Test if two lists of bits are equal. */ - public func hashEq(ha:BitList, hb:BitList) : Bool { - switch (ha, hb) { - case (null, null) true; - case (null, _) false; - case (_, null) false; - case (?(bita, ha2), ?(bitb, hb2)) { - if (bita == bitb) { hashEq(ha2, hb2) } - else { false } - }; - } - }; + /** + Jenkin's one at a time: + https://en.wikipedia.org/wiki/Jenkins_hash_function#one_at_a_time - public func bitsPrintRev(bits:BitList) { - switch bits { - case null { Prim.debugPrint "" }; - case (?(bit,bits_)) { - bitsPrintRev(bits_); - if bit { Prim.debugPrint "1R." } - else { Prim.debugPrint "0L." } - } - } - }; - - public func hashPrintRev(bits:BitList) { - switch bits { - case null { Prim.debugPrint "" }; - case (?(bit,bits_)) { - hashPrintRev(bits_); - if bit { Prim.debugPrint "1" } - else { Prim.debugPrint "0" } - } - } + The input type should actually be `[Word8]`. + Note: Be sure to explode each `Word8` of a `Word32` into its own `Word32`, and to shift into lower 8 bits. + // should this really be public? + */ + public let hashWord8s : [Hash] -> Hash = func(key) { + var hash = Prim.natToWord32(0); + for (wordOfKey in key.vals()) { + hash := hash + wordOfKey; + hash := hash + hash << 10; + hash := hash ^ (hash >> 6); + }; + hash := hash + hash << 3; + hash := hash ^ (hash >> 11); + hash := hash + hash << 15; + return hash; }; -}; - - -/* - Canonical representations - --------------------------- - - Choose a canonical representation of hash values for the rest of - the standard library to use: -*/ - -public type Hash = BitVec; -public let Hash = BitVec; } diff --git a/stdlib/src/trie.mo b/stdlib/src/trie.mo index ab9037e74cd..fec3341bd33 100644 --- a/stdlib/src/trie.mo +++ b/stdlib/src/trie.mo @@ -6,7 +6,7 @@ import Prim "mo:prim"; import P "prelude"; import Option "option"; -import H "hash"; +import Hash "hash"; import A "array"; import List "list"; @@ -87,16 +87,13 @@ public let MAX_LEAF_COUNT = 8; // <-- beats both 4 and 16 for me, now //let MAX_LEAF_COUNT = 16; //let MAX_LEAF_COUNT = 32; -public let Hash = H.BitVec; -public type Hash = Hash.t; - public type List = List.List; public type AssocList = AssocList.AssocList; /* A `Key` for the trie has an associated hash value */ public type Key = { /* `hash` permits fast inequality checks, and permits collisions */ - hash: Hash; + hash: Hash.Hash; /* `key` permits percise equality checks, but only used after equal hashes. */ key: K; }; @@ -132,7 +129,7 @@ public type Trie = { }; public func isValid (t:Trie, enforceNormal:Bool) : Bool { - func rec(t:Trie, bitpos:?Hash, bits:Hash, mask:Hash) : Bool { + func rec(t:Trie, bitpos:?Hash.Hash, bits:Hash.Hash, mask:Hash.Hash) : Bool { switch t { case (#empty) { switch bitpos { @@ -853,7 +850,7 @@ public func disj( but where global memory consists of a single (anonymous) global trie */ public type TrieBuild = { #skip ; - #insert : (K, ?Hash, V) ; + #insert : (K, ?Hash.Hash, V) ; #seq : { count : Nat ; left : TrieBuild ; @@ -937,15 +934,15 @@ public func disj( This position is meaningful only when the build contains multiple uses of one or more keys, otherwise it is not. */ - public func buildNth(tb:TrieBuild, i:Nat) : ?(K, ?Hash, V) = label profile_triebuild_nth : (?(K, ?Hash, V)) { - func rec(tb:TrieBuild, i:Nat) : ?(K, ?Hash, V) = label profile_triebuild_nth_rec : (?(K, ?Hash, V)) { + public func buildNth(tb:TrieBuild, i:Nat) : ?(K, ?Hash.Hash, V) = label profile_triebuild_nth : (?(K, ?Hash.Hash, V)) { + func rec(tb:TrieBuild, i:Nat) : ?(K, ?Hash.Hash, V) = label profile_triebuild_nth_rec : (?(K, ?Hash.Hash, V)) { switch tb { case (#skip) P.unreachable(); - case (#insert (k,h,v)) label profile_trie_buildNth_rec_end : (?(K, ?Hash, V)) { + case (#insert (k,h,v)) label profile_trie_buildNth_rec_end : (?(K, ?Hash.Hash, V)) { assert(i == 0); ?(k,h,v) }; - case (#seq s) label profile_trie_buildNth_rec_seq : (?(K, ?Hash, V)) { + case (#seq s) label profile_trie_buildNth_rec_seq : (?(K, ?Hash.Hash, V)) { let count_left = buildCount(s.left); if (i < count_left) { rec(s.left, i) } else { rec(s.right, i - count_left) } @@ -986,7 +983,7 @@ public func disj( let a = A.tabulate ( buildCount(tb), func (i:Nat) : W = label profile_triebuild_toArray_nth : W { - let (k,_,v) = Option.unwrap<(K,?Hash,V)>(buildNth(tb, i)); + let (k,_,v) = Option.unwrap<(K,?Hash.Hash,V)>(buildNth(tb, i)); f(k, v) } ); diff --git a/stdlib/src/trieMap.mo b/stdlib/src/trieMap.mo index 2f761202648..884281b314f 100644 --- a/stdlib/src/trieMap.mo +++ b/stdlib/src/trieMap.mo @@ -23,7 +23,7 @@ For now, this class does not permit a direct `clone` operation (neither does `Ha */ module { -public class TrieMap (isEq:(K, K) -> Bool, hashOf: K -> T.Hash) { +public class TrieMap (isEq:(K, K) -> Bool, hashOf: K -> Hash.Hash) { var map = T.empty(); var _count : Nat = 0; diff --git a/stdlib/test/hashMapTest.mo b/stdlib/test/hashMapTest.mo index bc2ef1c4788..cdb1199f0cf 100644 --- a/stdlib/test/hashMapTest.mo +++ b/stdlib/test/hashMapTest.mo @@ -5,7 +5,7 @@ import Hash "mo:stdlib/hash"; func textIsEq(x:Text,y:Text):Bool { x == y }; debug { - let a = H.HashMap(3, textIsEq, Hash.Hash.hashOfText); + let a = H.HashMap(3, textIsEq, Hash.hashOfText); ignore a.set("apple", 1); ignore a.set("banana", 2); @@ -21,7 +21,7 @@ debug { ignore a.set("AvocadO", 444); // need to resupply the constructor args; they are private to the object; but, should they be? - let b = H.clone(a, textIsEq, Hash.Hash.hashOfText); + let b = H.clone(a, textIsEq, Hash.hashOfText); // ensure clone has each key-value pair present in original for ((k,v) in a.iter()) { @@ -91,7 +91,7 @@ debug { // test fromIter method - let c = H.fromIter(b.iter(), 0, textIsEq, Hash.Hash.hashOfText); + let c = H.fromIter(b.iter(), 0, textIsEq, Hash.hashOfText); // c agrees with each entry of b for ((k,v) in b.iter()) { diff --git a/stdlib/test/trieMapTest.mo b/stdlib/test/trieMapTest.mo index 324bf70ed61..de41e6d900e 100644 --- a/stdlib/test/trieMapTest.mo +++ b/stdlib/test/trieMapTest.mo @@ -5,7 +5,7 @@ import Hash "mo:stdlib/hash"; func textIsEq(x:Text,y:Text):Bool { x == y }; debug { - let a = H.TrieMap(textIsEq, Hash.Hash.hashOfText); + let a = H.TrieMap(textIsEq, Hash.hashOfText); ignore a.set("apple", 1); ignore a.set("banana", 2); @@ -21,7 +21,7 @@ debug { ignore a.set("AvocadO", 444); // need to resupply the constructor args; they are private to the object; but, should they be? - let b = H.clone(a, textIsEq, Hash.Hash.hashOfText); + let b = H.clone(a, textIsEq, Hash.hashOfText); // ensure clone has each key-value pair present in original for ((k,v) in a.iter()) { @@ -91,7 +91,7 @@ debug { // test fromIter method - let c = H.fromIter(b.iter(), textIsEq, Hash.Hash.hashOfText); + let c = H.fromIter(b.iter(), textIsEq, Hash.hashOfText); // c agrees with each entry of b for ((k,v) in b.iter()) { From d26205bf2836d4fff863491c17fdd42d45cb51a1 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 6 Feb 2020 00:30:50 +0100 Subject: [PATCH 1021/1176] stdlib: Document and format option (#1186) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * stdlib: Document and format option including * don’t provide polymorphic functions where subtyping with `Any` does works just as well * move `unwrap` to the end (as it is not a nice function) * remove `Option.t`, as per discussion in https://github.com/dfinity-lab/motoko/issues/1176 * Update PX --- .../produce-exchange/src/serverModel.mo | 20 +- stdlib/src/option.mo | 220 ++++++++---------- 2 files changed, 106 insertions(+), 134 deletions(-) diff --git a/stdlib/examples/produce-exchange/src/serverModel.mo b/stdlib/examples/produce-exchange/src/serverModel.mo index dc634c918bb..3029697fe59 100644 --- a/stdlib/examples/produce-exchange/src/serverModel.mo +++ b/stdlib/examples/produce-exchange/src/serverModel.mo @@ -1502,9 +1502,7 @@ than the MVP goals, however. let producer = Option.unwrap(producerTable.getDoc(doc.producer)); /**- remove document from `inventoryTable` */ - Option.assertSome( - inventoryTable.rem( id ) - ); + Option.assertSome(inventoryTable.rem( id )); /// xxx an abstraction to hide these type arguments? let (updatedInventory, _) = @@ -1522,7 +1520,7 @@ than the MVP goals, however. reserved = producer.reserved ; }; - Option.assertSome( + Option.assertSome( producerTable.updateDoc( producer.id, updatedProducer ) ); @@ -1535,7 +1533,7 @@ than the MVP goals, however. keyOf(producer.id), idIsEq, keyOf(id), idIsEq ); - Option.assertSome(d); + Option.assertSome(d); t }; @@ -1724,7 +1722,7 @@ than the MVP goals, however. let transporter = Option.unwrap(transporterTable.getDoc(doc.transporter)); - Option.assertSome( + Option.assertSome( routeTable.rem( id ) ); @@ -1741,7 +1739,7 @@ than the MVP goals, however. reserved = transporter.reserved ; }; - Option.assertSome( + Option.assertSome( transporterTable.updateDoc( transporter.id, updatedTransporter ) ); @@ -1752,7 +1750,7 @@ than the MVP goals, however. keyOf(doc.start_region.id), idIsEq, keyOf(doc.id), idIsEq ); - Option.assertSome(d); + Option.assertSome(d); t }; @@ -2223,7 +2221,7 @@ than the MVP goals, however. reserved=updatedProducerReserved; // <-- the only field we are updating }; - Option.assertSome( + Option.assertSome( producerTable.updateDoc( producerDoc2.id, updatedProducer ) ) }; @@ -2246,7 +2244,7 @@ than the MVP goals, however. reserved=updatedTransporterReserved; // <-- the only field we are updating }; - Option.assertSome( + Option.assertSome( transporterTable.updateDoc( transporterDoc2.id, updatedTransporter ) ) }; @@ -2269,7 +2267,7 @@ than the MVP goals, however. reserved=updatedRetailerReserved; // <-- the only field we are updating }; - Option.assertSome( + Option.assertSome( retailerTable.updateDoc( retailerDoc.id, updatedRetailer ) ) }; diff --git a/stdlib/src/option.mo b/stdlib/src/option.mo index f8d7440be42..8470042e01e 100644 --- a/stdlib/src/option.mo +++ b/stdlib/src/option.mo @@ -6,160 +6,134 @@ import P "prelude"; module { -/* - -Functions for Option types. - -*/ - -public type t = ?A; - -/* - - `isSome` - -------------------- - - Returns true if the value is not `null`. +/** +Returns true if the argument is not `null`. */ -public func isSomeAny(x: ?Any): Bool = +public let isSome : ?Any -> Bool = func(x) = switch x { case null false; case _ true; }; -public func isSome(x: t): Bool = isSomeAny(x); - -/* - - `isNull` - -------------------- - - Returns true if the value is `null`. - -*/ -public func isNullAny(x: ?Any): Bool = not isSome(x); - -public func isNull(x: t): Bool = not isSome(x); - -/* - - `unwrap` - -------------------- - - Unwrap an optional value, and fail if it is `null`. - +/** +Returns true if the argument is `null`. */ -public func unwrap(x: ?T): T = +public let isNull : ?Any -> Bool = func(x) = switch x { - case null { P.unreachable() }; - case (?x_) x_; + case null true; + case _ false; }; -/* - - `unwrapOr` - -------------------- - - Unwrap an optional value or a default. - +/** +Unwraps an optional value, with a default value, i.e. `unwrap(?x, d) = x` and `unwrap(null, d) = d`. */ -public func unwrapOr(x: ?T, d: T): T = - switch x { - case null { d }; - case (?x_) x_; - }; - -/* - - `option` - -------------------- - - Unwrap an optional value. If null, return the default, else, apply the function to the unwrapped value. +public let unwrapOr : (?T, default : T) -> T = + func (x: ?T, d: T): T = + switch x { + case null { d }; + case (?x_) x_; + }; +/** +Unwraps an optional value using a function, or returns the default, i.e. `option(?x, f, d) = f x` and `option(null, f, d) = d`. */ -public func option(x: ?A, f: A->B, d: B): B = - switch x { - case null { d }; - case (?x_) f(x_); - }; - -/* - - `map` - -------------------- +public let option : (?A, f : A -> B, default : B) -> B = + func(x: ?A, f: A->B, d: B): B = + switch x { + case null { d }; + case (?x_) f(x_); + }; - Apply a function to the wrapped value. +/** +Applies a function to the wrapped value. +*/ +public let map : (f: A->B, x: ?A) -> ?B = + func map(f: A->B, x: ?A): ?B = + switch x { + case null null; + case (?x_) ?f(x_); + }; +/** +Applies an optional function to an optional value. Returns `null` if at least one of the arguments is `null`. */ -public func map(f: A->B, x: ?A): ?B = - switch x { - case null null; - case (?x_) ?f(x_); +public let apply : (?(A -> B), ?A) -> ?B = + func (f : ?(A -> B), x : ?A) : ?B { + switch (f, x) { + case (?f_, ?x_) { + ?f_(x_); + }; + case (_, _) { + null; + }; + }; }; -/* - - `assertSome` - -------------------- - - Assert that the given value is not `null`; ignore this value and return unit. +/** +Applies an function to an optional value. Returns `null` if the argument is `null`, or the function returns `null`. +NOTE: Together with <>, this forms a “monad”. */ -public func assertSomeAny(x: ?Any) = - switch x { - case null { P.unreachable() }; - case _ {}; +public let bind : (?A, A -> ?B) -> ?B = + func(x : ?A, f : A -> ?B) : ?B { + switch(x) { + case (?x_) { + f(x_); + }; + case (null) { + null; + }; + }; }; -public func assertSome(x: ?A) = assertSomeAny(x); - -/* - - `assertNull` - -------------------- - - Assert that the given value is `null`; ignore this value and return unit. - +/** +Given an optional optional value, removes one layer of optionality. */ -public func assertNullAny(x: ?Any) = - switch x { - case null { }; - case _ { P.unreachable() }; +public let join : ??A -> ?A = + func(x : ??A) : ?A { + bind(x, func (x_ : ?A) : ?A { + x_; + }); }; -public func assertNull(x: ?A) = assertNullAny(x); +/** +Creates an optional value from a definite value. +*/ +public let pure : A -> ?A = + func (x: A) : ?A = ?x; -public func apply(f : ?(A -> B), x : ?A) : ?B { - switch (f, x) { - case (?f_, ?x_) { - ?f_(x_); - }; - case (_, _) { - null; +/** +Asserts that the value is not `null`; fails otherwise. +*/ +public let assertSome : ?Any -> () = + func(x) = + switch x { + case null { P.unreachable() }; + case _ {}; }; - }; -}; -public func bind(x : ?A, f : A -> ?B) : ?B { - switch(x) { - case (?x_) { - f(x_); - }; - case (null) { - null; +/** +Asserts that the value _is_ `null`; fails otherwise. +*/ +public let assertNull : ?Any -> () = + func(x) = + switch x { + case null { }; + case _ { P.unreachable() }; }; - }; -}; -public func join(x : ??A) : ?A { - bind(x, func (x_ : ?A) : ?A { - x_; - }); -}; +/** +Unwraps an optional value, i.e. `unwrap(?x) = x`. + +WARNING: `unwrap(x)` will fail if the argument is `null`, and is generally considered bad style. Use `switch x` instead. +*/ +public let unwrap : ?T -> T = + func(x: ?T): T = + switch x { + case null { P.unreachable() }; + case (?x_) x_; + }; -public func pure(x: A) : ?A { - ?x; -}; } From 681e06c4217f54fae6b7ddbe26be19485a191349 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 6 Feb 2020 11:31:16 +0100 Subject: [PATCH 1022/1176] Prelude: Only define functions (#1187) as these can be compiled statically; other values would lead to dynamic allocation and construction in `$start`. Not horrible, but somewhat unsatisfying. --- src/prelude/prelude.ml | 31 ++++++++++++++++++++++--------- test/run-drun/empty-actor.mo | 11 +++++++++++ 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/src/prelude/prelude.ml b/src/prelude/prelude.ml index 33f72c17e80..4479d257c41 100644 --- a/src/prelude/prelude.ml +++ b/src/prelude/prelude.ml @@ -106,7 +106,7 @@ func @text_chars(xs : Text) : (() -> @Iter) = // The text_of functions do not need to be exposed; the user can just use // the show above. -func @text_of_num(x : Nat, base : Nat, sep : Nat, digits : [Text]) : Text { +func @text_of_num(x : Nat, base : Nat, sep : Nat, digits : Nat -> Text) : Text { var text = ""; var n = x; @@ -116,16 +116,24 @@ func @text_of_num(x : Nat, base : Nat, sep : Nat, digits : [Text]) : Text { while (n > 0) { let rem = n % base; if (i == sep) { text := "_" # text; i := 0 }; - text := digits[rem] # text; + text := digits rem # text; n := n / base; i += 1; }; return text; }; -let @decdigits = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]; +func @digits_dec(x : Nat) : Text = + (prim "conv_Char_Text" : Char -> Text) ( + (prim "num_conv_Word32_Char" : Word32 -> Char) ( + (prim "num_conv_Nat_Word32" : Nat -> Word32) ( + x + 0x30 + ) + ) + ); + func @text_of_Nat(x : Nat) : Text { - @text_of_num(x, 10, 3, @decdigits); + @text_of_num(x, 10, 3, @digits_dec); }; func @text_of_Int(x : Int) : Text { @@ -133,14 +141,19 @@ func @text_of_Int(x : Int) : Text { @text_of_Nat((prim "abs" : Int -> Nat) x) }; -let @hexdigits = - [ "0", "1", "2", "3", "4", "5", "6", "7", - "8", "9", "A", "B", "C", "D", "E", "F" ]; +func @digits_hex(x : Nat) : Text = + (prim "conv_Char_Text" : Char -> Text) ( + (prim "num_conv_Word32_Char" : Word32 -> Char) ( + (prim "num_conv_Nat_Word32" : Nat -> Word32) ( + x + (if (x < 10) 0x30 else 55) + ) + ) + ); func @text_of_Word(x : Nat) : Text { - return "0x" # @text_of_num(x, 16, 4, @hexdigits); + return "0x" # @text_of_num(x, 16, 4, @digits_hex); }; -// Thre is some duplication with the prim_module, but we need these here +// There is some duplication with the prim_module, but we need these here // before we can load the prim module func @int64ToInt(n : Int64) : Int = (prim "num_conv_Int64_Int" : Int64 -> Int) n; func @int32ToInt(n : Int32) : Int = (prim "num_conv_Int32_Int" : Int32 -> Int) n; diff --git a/test/run-drun/empty-actor.mo b/test/run-drun/empty-actor.mo index a0b4cbb51ad..b0a0b4da549 100644 --- a/test/run-drun/empty-actor.mo +++ b/test/run-drun/empty-actor.mo @@ -1 +1,12 @@ actor {}; + +// The prelude should not require any code (besides maybe a call to collect) at runtime +// CHECK: (func $start (type 4)) + +// CHECK: (func $start_stub (type 4) +// CHECK-NEXT: call $start +// CHECK-NEXT: call $collect) + +// CHECK: (export "canister_init" (func $start_stub)) + + From 4bf70d6579d33cc04a63d043c4ce47c941c7db54 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Mon, 10 Feb 2020 13:13:47 +0000 Subject: [PATCH 1023/1176] Fix for bad type annotation after cps conversion (#1190) * formatting * Update src/ir_passes/await.ml Co-Authored-By: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> Co-authored-by: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> --- src/ir_passes/await.ml | 132 ++++++++++--------- test/run-drun/ok/switch-await.drun-run.ok | 5 + test/run-drun/ok/switch-await.ic-stub-run.ok | 12 ++ test/run-drun/switch-await.mo | 38 ++++++ 4 files changed, 125 insertions(+), 62 deletions(-) create mode 100644 test/run-drun/ok/switch-await.drun-run.ok create mode 100644 test/run-drun/ok/switch-await.ic-stub-run.ok create mode 100644 test/run-drun/switch-await.mo diff --git a/src/ir_passes/await.ml b/src/ir_passes/await.ml index fa5df537ccf..07815708cc5 100644 --- a/src/ir_passes/await.ml +++ b/src/ir_passes/await.ml @@ -15,9 +15,10 @@ type kont = ContVar of exp let meta typ exp = let expanded = ref false in - let exp v = assert (not(!expanded)); - expanded := true; - exp v + let exp v = + assert (not(!expanded)); + expanded := true; + exp v in MetaCont (typ, exp) @@ -53,7 +54,6 @@ module PatEnv = Env.Make(String) type label_sort = Cont of kont | Label - (* Trivial translation of pure terms (eff = T.Triv) *) let rec t_exp context exp = @@ -172,17 +172,17 @@ and nary context k naryE es = match es with | [] -> k -@- naryE (List.rev vs) | [e1] when eff e1 = T.Triv -> - (* TBR: optimization - no need to name the last trivial argument *) - k -@- naryE (List.rev (e1 :: vs)) + (* TBR: optimization - no need to name the last trivial argument *) + k -@- naryE (List.rev (e1 :: vs)) | e1 :: es -> - match eff e1 with - | T.Triv -> - let v1 = fresh_var "v" (typ e1) in - letE v1 (t_exp context e1) - (nary_aux (v1 :: vs) es) - | T.Await -> - c_exp context e1 - (meta (typ e1) (fun v1 -> nary_aux (v1 :: vs) es)) + match eff e1 with + | T.Triv -> + let v1 = fresh_var "v" (typ e1) in + letE v1 (t_exp context e1) + (nary_aux (v1 :: vs) es) + | T.Await -> + c_exp context e1 + (meta (typ e1) (fun v1 -> nary_aux (v1 :: vs) es)) in nary_aux [] es @@ -209,9 +209,9 @@ and c_loop context k e1 = assert false | T.Await -> let v1 = fresh_var "v" T.unit in - blockE [funcD loop v1 - (c_exp context e1 (ContVar loop))] - (loop -*- unitE) + blockE + [funcD loop v1 (c_exp context e1 (ContVar loop))] + (loop -*- unitE) and c_assign context k e lexp1 exp2 = match lexp1.it with @@ -219,13 +219,14 @@ and c_assign context k e lexp1 exp2 = unary context k (fun v2 -> e (AssignE(lexp1, v2))) exp2 | DotLE (exp11, id) -> binary context k (fun v11 v2 -> - e (AssignE ({lexp1 with it = DotLE (v11, id)}, v2))) exp11 exp2 + e (AssignE ({lexp1 with it = DotLE (v11, id)}, v2))) exp11 exp2 | IdxLE (exp11, exp12) -> - nary context k (fun vs -> match vs with - | [v11; v12; v2] -> - e (AssignE ({lexp1 with it = IdxLE (v11, v12)}, v2)) - | _ -> assert false) - [exp11; exp12; exp2] + nary context k + (fun vs -> match vs with + | [v11; v12; v2] -> + e (AssignE ({lexp1 with it = IdxLE (v11, v12)}, v2)) + | _ -> assert false) + [exp11; exp12; exp2] and c_exp context exp = c_exp' context exp @@ -250,22 +251,27 @@ and c_exp' context exp k = | SwitchE (exp1, cases) -> letcont k (fun k -> let cases' = List.map - (fun {it = {pat;exp}; at; note} -> - let exp' = match eff exp with - | T.Triv -> k -*- (t_exp context exp) - | T.Await -> c_exp context exp (ContVar k) - in - {it = {pat;exp = exp' }; at; note}) - cases + (fun {it = {pat;exp}; at; note} -> + let exp' = match eff exp with + | T.Triv -> k -*- (t_exp context exp) + | T.Await -> c_exp context exp (ContVar k) + in + {it = { pat; exp = exp' }; at; note}) + cases in begin match eff exp1 with | T.Triv -> - {exp with it = SwitchE(t_exp context exp1, cases')} + { it = SwitchE(t_exp context exp1, cases'); + at = exp.at; + note = { exp.note with note_typ = answerT } } | T.Await -> c_exp context exp1 (meta (typ exp1) - (fun v1 -> {exp with it = SwitchE(v1,cases')})) + (fun v1 -> + { it = SwitchE(v1, cases'); + at = exp.at; + note = { exp.note with note_typ = answerT } })) end) | TryE (exp1, cases) -> (* TODO: do we need to reify f? *) @@ -273,18 +279,19 @@ and c_exp' context exp k = letcont f (fun f -> letcont k (fun k -> let cases' = List.map - (fun {it = {pat;exp}; at; note} -> - let exp' = match eff exp with - | T.Triv -> k -*- (t_exp context exp) - | T.Await -> c_exp context exp (ContVar k) - in - {it = {pat;exp = exp' }; at; note}) - cases + (fun {it = {pat;exp}; at; note} -> + let exp' = match eff exp with + | T.Triv -> k -*- (t_exp context exp) + | T.Await -> c_exp context exp (ContVar k) + in + { it = {pat;exp = exp' }; at; note }) + cases in let error = fresh_var "v" T.catch in - let cases' = cases' @ [{it = {pat = varP error; exp = f -*- error}; - at = no_region; - note = ()}] in + let cases' = cases' @ [ + { it = {pat = varP error; exp = f -*- error}; + at = no_region; + note = () }] in let throw = fresh_err_cont () in let e = fresh_var "e" T.catch in let context' = LabelEnv.add Throw (Cont (ContVar throw)) context in @@ -294,20 +301,20 @@ and c_exp' context exp k = k -*- (t_exp context exp1) | T.Await -> blockE - [funcD throw e { it = SwitchE (e, cases'); - at = exp.at; - note = {note_eff = T.Await; (* shouldn't matter *) - note_typ = T.unit} - }] + [funcD throw e + { it = SwitchE (e, cases'); + at = exp.at; + note = { note_eff = T.Await; (* shouldn't matter *) + note_typ = T.unit } }] (c_exp context' exp1 (ContVar k)) end)) | LoopE exp1 -> c_loop context k exp1 | LabelE (id, _typ, exp1) -> - letcont k - (fun k -> - let context' = LabelEnv.add (Named id) (Cont (ContVar k)) context in - c_exp context' exp1 (ContVar k)) (* TODO optimize me, if possible *) + letcont k + (fun k -> + let context' = LabelEnv.add (Named id) (Cont (ContVar k)) context in + c_exp context' exp1 (ContVar k)) (* TODO optimize me, if possible *) | PrimE (BreakPrim id, [exp1]) -> begin match LabelEnv.find_opt (Named id) context with @@ -337,16 +344,17 @@ and c_exp' context exp k = LabelEnv.add Return (Cont (ContVar k_ret)) (LabelEnv.add Throw (Cont (ContVar k_fail)) LabelEnv.empty) in - k -@- (asyncE typ1 (typ exp1) - (forall [tb] ([k_ret; k_fail] -->* - (c_exp context' exp1 (ContVar k_ret))))) + k -@- + (asyncE typ1 (typ exp1) + (forall [tb] ([k_ret; k_fail] -->* + (c_exp context' exp1 (ContVar k_ret))))) | PrimE (AwaitPrim, [exp1]) -> - let r = match LabelEnv.find_opt Throw context with - | Some (Cont r) -> r - | Some Label - | None -> assert false - in - letcont r (fun r -> + let r = match LabelEnv.find_opt Throw context with + | Some (Cont r) -> r + | Some Label + | None -> assert false + in + letcont r (fun r -> letcont k (fun k -> let kr = tupE [k;r] in match eff exp1 with @@ -375,7 +383,7 @@ and c_dec context dec (k:kont) = let block exp = let dec_pat' = {dec with it = LetD(pat',exp)} in blockE (dec_pat' :: define_pat patenv pat) - (k -@- tupE[]) + (k -@- tupE[]) in begin match eff exp with @@ -393,7 +401,7 @@ and c_dec context dec (k:kont) = | T.Await -> c_exp context exp (meta (typ exp) - (fun v -> k -@- define_idE id Var v)) + (fun v -> k -@- define_idE id Var v)) end diff --git a/test/run-drun/ok/switch-await.drun-run.ok b/test/run-drun/ok/switch-await.drun-run.ok new file mode 100644 index 00000000000..26dc3146226 --- /dev/null +++ b/test/run-drun/ok/switch-await.drun-run.ok @@ -0,0 +1,5 @@ +ingress System +ingress Completed: Canister: Payload: 0x4449444c000171034f6e65 +ingress Completed: Canister: Payload: 0x4449444c000171034f6e65 +ingress Completed: Canister: Payload: 0x4449444c000171034f6e65 +ingress Completed: Canister: Payload: 0x4449444c000171034f6e65 diff --git a/test/run-drun/ok/switch-await.ic-stub-run.ok b/test/run-drun/ok/switch-await.ic-stub-run.ok new file mode 100644 index 00000000000..e0d0b5c0113 --- /dev/null +++ b/test/run-drun/ok/switch-await.ic-stub-run.ok @@ -0,0 +1,12 @@ +→ create +← completed: canister-id = 0x2a01 +→ install +← completed +→ update go_tt(0x4449444c0000) +← completed: 0x4449444c000171034f6e65 +→ update go_ta(0x4449444c0000) +← completed: 0x4449444c000171034f6e65 +→ update go_at(0x4449444c0000) +← completed: 0x4449444c000171034f6e65 +→ update go_aa(0x4449444c0000) +← completed: 0x4449444c000171034f6e65 diff --git a/test/run-drun/switch-await.mo b/test/run-drun/switch-await.mo new file mode 100644 index 00000000000..149a04b4d11 --- /dev/null +++ b/test/run-drun/switch-await.mo @@ -0,0 +1,38 @@ +// test cps conversion of switch (bug fix) +actor a { + public shared func go_ta() : async Text { + switch 1 { + case 1 (await async "One"); + case 2 "Two"; + case _ "Other"; + } + }; + + public shared func go_tt() : async Text { + switch 1 { + case 1 "One"; + case 2 "Two"; + case _ "Other"; + } + }; + + public shared func go_at() : async Text { + switch (await async 1) { + case 1 "One"; + case 2 "Two"; + case _ "Other"; + } + }; + + public shared func go_aa() : async Text { + switch (await async 1) { + case 1 (await async "One"); + case 2 "Two"; + case _ "Other"; + } + }; +}; +ignore a.go_tt(); //OR-CALL ingress go_tt "DIDL\x00\x00" +ignore a.go_ta(); //OR-CALL ingress go_ta "DIDL\x00\x00" +ignore a.go_at(); //OR-CALL ingress go_at "DIDL\x00\x00" +ignore a.go_aa(); //OR-CALL ingress go_aa "DIDL\x00\x00" From 22e6f9f152122a7cdab07db279d9ee073e4cc39a Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Mon, 10 Feb 2020 17:20:50 +0000 Subject: [PATCH 1024/1176] fix interpreters to avoid second trip through scheduler in high-level messaging (#1180) * fix interpreters to avoid double trips through scheduler in high-level messaging * remove tracing of message sends and just rely on function tracing. --- src/ir_interpreter/interpret_ir.ml | 48 +++++++++++++++++------------- src/mo_interpreter/interpret.ml | 21 ++----------- 2 files changed, 29 insertions(+), 40 deletions(-) diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index 7be7427e5a2..9baacca7adb 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -128,7 +128,6 @@ struct if not (Queue.is_empty q) then (yield (); run ()) end - (* Async auxiliary functions *) (* Are these just duplicates of the corresponding functions in interpret.ml? If so, refactor *) @@ -192,22 +191,16 @@ let await env at async k = ) -let actor_msg env id f c v (k : V.value V.cont) = - if env.flags.trace then trace "-> message %s%s" id (string_of_arg env v); - Scheduler.queue (fun () -> - if env.flags.trace then trace "<- message %s%s" id (string_of_arg env v); - incr trace_depth; - f c v k - ) +(* queue a lowered oneway or replying function that no longer does AsyncE on entry *) +let queue f = fun c v k -> Scheduler.queue (fun () -> f c v k) let make_unit_message env id call_conv f = + assert env.flavor.has_async_typ; let open CC in match call_conv with | {sort = T.Shared s; n_res = 0; _} -> - Value.message_func s call_conv.n_args (fun c v k -> - actor_msg env id f c v (fun _ -> ()); - k V.unit - ) + (* message scheduled by AsyncE in f *) + Value.message_func s call_conv.n_args f | _ -> failwith ("unexpected call_conv " ^ string_of_call_conv call_conv) @@ -216,13 +209,21 @@ let make_async_message env id call_conv f = let open CC in match call_conv with | {sort = T.Shared s; control = T.Promises; _} -> - Value.async_func s call_conv.n_args call_conv.n_res (fun c v k -> - let async = make_async () in - actor_msg env id f c v (fun v_async -> - get_async (V.as_async v_async) (set_async async) (reject_async async) - ); - k (V.Async async) - ) + (* message scheduled by AsyncE in f *) + Value.async_func s call_conv.n_args call_conv.n_res f + | _ -> + failwith ("unexpected call_conv " ^ string_of_call_conv call_conv) + +let make_lowered_unit_message env id call_conv f = + assert (not env.flavor.has_async_typ); + let open CC in + match call_conv with + | {sort = T.Shared s; n_res = 0; _} -> + (* message scheduled here (not by f) *) + Value.message_func s call_conv.n_args (fun c v k -> + (queue f) c v (fun _ -> ()); + k (V.unit); + ); | _ -> failwith ("unexpected call_conv " ^ string_of_call_conv call_conv) @@ -232,7 +233,8 @@ let make_replying_message env id call_conv f = match call_conv with | {sort = T.Shared s; control = T.Replies; _} -> Value.replies_func s call_conv.n_args call_conv.n_res (fun c v k -> - actor_msg env id f c v (fun v -> ()); + (* message scheduled here (not by f) *) + (queue f) c v (fun _ -> ()); k (V.unit) ) | _ -> @@ -240,7 +242,11 @@ let make_replying_message env id call_conv f = let make_message env x cc f : V.value = match cc.CC.control with - | T.Returns -> make_unit_message env x cc f + | T.Returns -> + if env.flavor.has_async_typ then + make_unit_message env x cc f + else + make_lowered_unit_message env x cc f | T.Promises -> make_async_message env x cc f | T.Replies -> make_replying_message env x cc f diff --git a/src/mo_interpreter/interpret.ml b/src/mo_interpreter/interpret.ml index bcc3abbb206..1c4e04461e0 100644 --- a/src/mo_interpreter/interpret.ml +++ b/src/mo_interpreter/interpret.ml @@ -193,23 +193,12 @@ let await env at async k = r v )) -let actor_msg env id f c v (k : V.value V.cont) = - if env.flags.trace then trace "-> message %s%s" id (string_of_arg env v); - Scheduler.queue (fun () -> - if env.flags.trace then trace "<- message %s%s" id (string_of_arg env v); - incr trace_depth; - f c v k - ) - let make_unit_message env id v = let open CC in let call_conv, f = V.as_func v in match call_conv with | {sort = T.Shared s; n_res = 0; _} -> - Value.message_func s call_conv.n_args (fun c v k -> - actor_msg env id f c v (fun _ -> ()); - k V.unit - ) + Value.message_func s call_conv.n_args f | _ -> (* assert false *) failwith ("unexpected call_conv " ^ (string_of_call_conv call_conv)) @@ -218,13 +207,7 @@ let make_async_message env id v = let call_conv, f = V.as_func v in match call_conv with | {sort = T.Shared s; control = T.Promises; _} -> - Value.async_func s call_conv.n_args call_conv.n_res (fun c v k -> - let async = make_async () in - actor_msg env id f c v (fun v_async -> - get_async (V.as_async v_async) (set_async async) (reject_async async) - ); - k (V.Async async) - ) + Value.async_func s call_conv.n_args call_conv.n_res f | _ -> (* assert false *) failwith ("unexpected call_conv " ^ (string_of_call_conv call_conv)) From 31172248af5338eabb499b153c007f2bd0699074 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 11 Feb 2020 07:39:50 +0000 Subject: [PATCH 1025/1176] Claudio/check ir perf (#1192) * asympotically speedup check_ir using visited set when checking recursive types * enable check_typ * skool boy error: know your precedence --- src/ir_def/check_ir.ml | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 38af8805347..80f17bb6d53 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -55,6 +55,7 @@ type env = labs : lab_env; rets : ret_env; async : T.con option; + seen : con_env ref; } let env_of_scope scope flavor : env = @@ -64,6 +65,7 @@ let env_of_scope scope flavor : env = labs = T.Env.empty; rets = None; async = None; + seen = ref T.ConSet.empty; } @@ -141,10 +143,7 @@ let rec check_typ env typ : unit = begin match Con.kind c with | T.Def (tbs,_) -> - if not (T.ConSet.mem c env.cons) then - (* an anonymous recursive type, check its def but beware recursion - future: use a visited set *) - check_con {env with cons = T.ConSet.add c env.cons} c; + check_con env c; check_typ_bounds env tbs typs no_region | T.Abs (tbs, _) -> check env no_region (T.ConSet.mem c env.cons) "free type constructor %s " @@ -217,12 +216,16 @@ let rec check_typ env typ : unit = check_con env c and check_con env c = - let env = {env with cons = T.ConSet.add c env.cons} in - let T.Abs (binds,typ) | T.Def (binds, typ) = Con.kind c in - let cs, ce = check_typ_binds env binds in - let ts = List.map (fun c -> T.Con (c, [])) cs in - let env' = adjoin_cons env ce in - check_typ env' (T.open_ ts typ) + if T.ConSet.mem c !(env.seen) then () + else + begin + env.seen := T.ConSet.add c !(env.seen); + let T.Abs (binds,typ) | T.Def (binds, typ) = Con.kind c in + let cs, ce = check_typ_binds env binds in + let ts = List.map (fun c -> T.Con (c, [])) cs in + let env' = adjoin_cons env ce in + check_typ env' (T.open_ ts typ) + end and check_typ_field env s typ_field : unit = let T.{lab; typ} = typ_field in From 66b9e36b3f77b317313d2eeecd5c7ae708efe2b1 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 11 Feb 2020 17:59:56 +0000 Subject: [PATCH 1026/1176] Fix broken desugaring of var decls (#1191) * var-bug repro * fix var-bug.mo by preserving types of stripped annotations in desugaring * Simplify test case * add type annotation to Ir.VarD * remove dead code Co-authored-by: Joachim Breitner --- src/codegen/compile.ml | 2 +- src/ir_def/arrange_ir.ml | 2 +- src/ir_def/check_ir.ml | 14 +++++--------- src/ir_def/construct.ml | 6 +++--- src/ir_def/construct.mli | 2 +- src/ir_def/freevars.ml | 2 +- src/ir_def/ir.ml | 2 +- src/ir_def/ir_effect.ml | 2 +- src/ir_interpreter/interpret_ir.ml | 4 ++-- src/ir_passes/async.ml | 2 +- src/ir_passes/await.ml | 6 +++--- src/ir_passes/rename.ml | 4 ++-- src/ir_passes/show.ml | 2 +- src/ir_passes/tailcall.ml | 6 +++--- src/lowering/desugar.ml | 4 ++-- test/run/var-bug.mo | 7 +++++++ 16 files changed, 35 insertions(+), 32 deletions(-) create mode 100644 test/run/var-bug.mo diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index a0aa60fd273..cb6429e3bfb 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -6688,7 +6688,7 @@ and compile_dec env pre_ae how v2en dec : VarEnv.t * G.t * (VarEnv.t -> G.t) = compile_exp_as_opt env ae pat_arity e ^^ fill_code ) - | VarD (name, e) -> + | VarD (name, _, e) -> assert (AllocHow.M.find_opt name how = Some AllocHow.LocalMut || AllocHow.M.find_opt name how = Some AllocHow.StoreHeap || AllocHow.M.find_opt name how = Some AllocHow.StoreStatic); diff --git a/src/ir_def/arrange_ir.ml b/src/ir_def/arrange_ir.ml index 8dd055e7a20..d990cf4b19b 100644 --- a/src/ir_def/arrange_ir.ml +++ b/src/ir_def/arrange_ir.ml @@ -125,7 +125,7 @@ and control s = Atom (Arrange_type.control s) and dec d = match d.it with | LetD (p, e) -> "LetD" $$ [pat p; exp e] - | VarD (i, e) -> "VarD" $$ [id i; exp e] + | VarD (i, t, e) -> "VarD" $$ [id i; typ t; exp e] and typ_bind (tb : typ_bind) = Con.to_string tb.it.con $$ [typ tb.it.bound] diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 80f17bb6d53..30222c21cdc 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -851,20 +851,15 @@ and close_typ_binds cs tbs = and check_dec env dec = (* helpers *) - let check p = check env dec.at p in let (<:) t1 t2 = check_sub env dec.at t1 t2 in match dec.it with | LetD (pat, exp) -> ignore (check_pat_exhaustive env pat); check_exp env exp; typ exp <: pat.note - | VarD (id, exp) -> - let t0 = try T.Env.find id env.vals with - | Not_found -> error env dec.at "unbound variable %s" id - in - check (T.is_mut t0) "variable in VarD is not immutable"; + | VarD (id, t, exp) -> check_exp env exp; - typ exp <: T.as_immut t0 + typ exp <: t and check_decs env decs = List.iter (check_dec env) decs; @@ -877,11 +872,12 @@ and gather_dec env scope dec : scope = | LetD (pat, exp) -> let ve = gather_pat env scope.val_env pat in { val_env = ve } - | VarD (id, exp) -> + | VarD (id, t, exp) -> + check_typ env t; check env dec.at (not (T.Env.mem id scope.val_env)) "duplicate variable definition in block"; - let ve = T.Env.add id (T.Mut (typ exp)) scope.val_env in + let ve = T.Env.add id (T.Mut t) scope.val_env in { val_env = ve} (* Programs *) diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index a0634c065d0..98554165d64 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -164,7 +164,7 @@ let tagE i e = } let dec_eff dec = match dec.it with - | LetD (_,e) | VarD (_,e) -> eff e + | LetD (_,e) | VarD (_, _, e) -> eff e let rec simpl_decs decs = List.concat (List.map simpl_dec decs) and simpl_dec dec = match dec.it with @@ -377,8 +377,8 @@ let letP pat exp = LetD (pat, exp) @@ no_region let letD x exp = letP (varP x) exp -let varD x exp = - VarD (x, exp) @@ no_region +let varD x t exp = + VarD (x, t, exp) @@ no_region let expD exp = let pat = { it = WildP; at = exp.at; note = exp.note.note_typ } in diff --git a/src/ir_def/construct.mli b/src/ir_def/construct.mli index 3d9a8758737..4148897f291 100644 --- a/src/ir_def/construct.mli +++ b/src/ir_def/construct.mli @@ -85,7 +85,7 @@ val unreachableE : exp val letP : pat -> exp -> dec val letD : var -> exp -> dec -val varD : id -> exp -> dec +val varD : id -> typ -> exp -> dec val expD : exp -> dec val funcD : var -> var -> exp -> dec val nary_funcD : var -> var list -> exp -> dec diff --git a/src/ir_def/freevars.ml b/src/ir_def/freevars.ml index 823dece389f..dae0285ed63 100644 --- a/src/ir_def/freevars.ml +++ b/src/ir_def/freevars.ml @@ -120,7 +120,7 @@ and id i = M.singleton i {captured = false; eager = true} and dec d = match d.it with | LetD (p, e) -> pat p +++ exp e - | VarD (i, e) -> (M.empty, S.singleton i) +++ exp e + | VarD (i, _, e) -> (M.empty, S.singleton i) +++ exp e (* The variables captured by a function. May include the function itself! *) and captured e = diff --git a/src/ir_def/ir.ml b/src/ir_def/ir.ml index f920433be21..378a0ca7af4 100644 --- a/src/ir_def/ir.ml +++ b/src/ir_def/ir.ml @@ -136,7 +136,7 @@ and prim = and dec = dec' Source.phrase and dec' = | LetD of pat * exp (* immutable *) - | VarD of id * exp (* mutable *) + | VarD of id * Type.typ * exp (* mutable *) (* Literals *) diff --git a/src/ir_def/ir_effect.ml b/src/ir_def/ir_effect.ml index 53598521d25..6ad91076e80 100644 --- a/src/ir_def/ir_effect.ml +++ b/src/ir_def/ir_effect.ml @@ -79,6 +79,6 @@ and effect_cases cases = max_eff e (effect_cases cases') and effect_dec dec = match dec.it with - | LetD (_,e) | VarD (_,e) -> effect_exp e + | LetD (_, e) | VarD (_, _, e) -> effect_exp e let infer_effect_dec = effect_dec diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index 9baacca7adb..a46cfe43635 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -754,7 +754,7 @@ and interpret_block env ro decs exp k = and declare_dec dec : val_env = match dec.it with | LetD (pat, _) -> declare_pat pat - | VarD (id, _) -> declare_id id + | VarD (id, _, _) -> declare_id id and declare_decs decs ve : val_env = match decs with @@ -771,7 +771,7 @@ and interpret_dec env dec k = define_pat env pat v; k () ) - | VarD (id, exp) -> + | VarD (id, _, exp) -> interpret_exp env exp (fun v -> define_id env id (V.Mut (ref v)); k () diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index 7e867bbb973..512ff726661 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -380,7 +380,7 @@ let transform mode env prog = and t_dec' dec' = match dec' with | LetD (pat,exp) -> LetD (t_pat pat,t_exp exp) - | VarD (id,exp) -> VarD (id,t_exp exp) + | VarD (id, t, exp) -> VarD (id, t_typ t, t_exp exp) and t_decs decs = List.map t_dec decs diff --git a/src/ir_passes/await.ml b/src/ir_passes/await.ml index 07815708cc5..136feea822d 100644 --- a/src/ir_passes/await.ml +++ b/src/ir_passes/await.ml @@ -135,7 +135,7 @@ and t_dec context dec = and t_dec' context dec' = match dec' with | LetD (pat, exp) -> LetD (pat, t_exp context exp) - | VarD (id, exp) -> VarD (id, t_exp context exp) + | VarD (id, t, exp) -> VarD (id, t, t_exp context exp) and t_decs context decs = List.map (t_dec context) decs @@ -393,7 +393,7 @@ and c_dec context dec (k:kont) = c_exp context exp (meta (typ exp) (fun v -> block v)) end - | VarD (id,exp) -> + | VarD (id, _typ, exp) -> begin match eff exp with | T.Triv -> @@ -417,7 +417,7 @@ and c_decs context decs k = and declare_dec dec exp : exp = match dec.it with | LetD (pat, _) -> declare_pat pat exp - | VarD (id, exp1) -> declare_id id (T.Mut (typ exp1)) exp + | VarD (id, typ, exp1) -> declare_id id (T.Mut typ) exp and declare_decs decs exp : exp = match decs with diff --git a/src/ir_passes/rename.ml b/src/ir_passes/rename.ml index b8b93bed7a1..27e17243ed1 100644 --- a/src/ir_passes/rename.ml +++ b/src/ir_passes/rename.ml @@ -129,9 +129,9 @@ and dec' rho d = match d with let p', rho = pat rho p in (fun rho' -> LetD (p',exp rho' e)), rho - | VarD (i, e) -> + | VarD (i, t, e) -> let i', rho = id_bind rho i in - (fun rho' -> VarD (i',exp rho' e)), + (fun rho' -> VarD (i', t, exp rho' e)), rho and decs rho ds = diff --git a/src/ir_passes/show.ml b/src/ir_passes/show.ml index 84e61d76193..9d81146f389 100644 --- a/src/ir_passes/show.ml +++ b/src/ir_passes/show.ml @@ -331,7 +331,7 @@ and t_dec env dec = { dec with it = t_dec' env dec.it } and t_dec' env dec' = match dec' with | LetD (pat,exp) -> LetD (pat,t_exp env exp) - | VarD (id,exp) -> VarD (id,t_exp env exp) + | VarD (id, typ, exp) -> VarD (id, typ, t_exp env exp) and t_decs env decs = List.map (t_dec env) decs diff --git a/src/ir_passes/tailcall.ml b/src/ir_passes/tailcall.ml index b4857ee61f5..4f1f603d1bd 100644 --- a/src/ir_passes/tailcall.ml +++ b/src/ir_passes/tailcall.ml @@ -209,7 +209,7 @@ and dec' env d = in let l_typ = Type.unit in let body = - blockE (List.map2 (fun t i -> varD (id_of_exp t) i) temps ids) ( + blockE (List.map2 (fun t i -> varD (id_of_exp t) (typ i) i) temps ids) ( loopE ( labelE label l_typ (blockE (List.map2 (fun a t -> letD (exp_of_arg a) (immuteE t)) as_ temps) @@ -226,9 +226,9 @@ and dec' env d = let env = pat env p in (fun env1 -> LetD(p,exp env1 e)), env - | VarD (i, e) -> + | VarD (i, t, e) -> let env = bind env i None in - (fun env1 -> VarD(i,exp env1 e)), + (fun env1 -> VarD(i, t, exp env1 e)), env and block env ds exp = diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 699e6b3de11..91a9df7bef7 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -52,7 +52,7 @@ let rec exps es = List.map exp es and exp e = (* We short-cut AnnotE here, so that we get the position of the inner expression *) match e.it with - | S.AnnotE (e,_) -> exp e + | S.AnnotE (e', t) -> exp e' | _ -> typed_phrase' exp' e and exp' at note = function @@ -313,7 +313,7 @@ and dec' at n d = match d with I.LetD (p', {e' with it = I.ActorE (with_self i t ds, fs, t)}) | _ -> I.LetD (p', e') end - | S.VarD (i, e) -> I.VarD (i.it, exp e) + | S.VarD (i, e) -> I.VarD (i.it, e.note.S.note_typ, exp e) | S.TypD _ -> assert false | S.ClassD (id, tbs, p, _t_opt, s, self_id, es) -> let id' = {id with note = ()} in diff --git a/test/run/var-bug.mo b/test/run/var-bug.mo new file mode 100644 index 00000000000..2f9006ab3f6 --- /dev/null +++ b/test/run/var-bug.mo @@ -0,0 +1,7 @@ +module { + +public func init() : Any { + { var x : {#A;#B} = #A } +}; + +} From 68bdce76e7ef22e85664c9af781d254cc816d31c Mon Sep 17 00:00:00 2001 From: Jude Taylor Date: Tue, 11 Feb 2020 10:31:55 -0800 Subject: [PATCH 1027/1176] disable packager --- default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/default.nix b/default.nix index 844028052b4..9b1b5569ebf 100644 --- a/default.nix +++ b/default.nix @@ -101,7 +101,7 @@ let ocaml_exe = name: bin: in # Make standalone on darwin (nothing to do on linux, is static) if nixpkgs.stdenv.isDarwin - then darwin_standalone { inherit drv; exename = bin; } + then darwin_standalone { inherit drv; usePackager = false; exename = bin; } else drv; in From d3998beb4cb0125b7d6df67405e641c0016e0efe Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 11 Feb 2020 13:32:40 -0800 Subject: [PATCH 1028/1176] Remove mergify support for non-squash automerge (#1195) since we usually only squash. If you need to do something else, do it manually. --- .mergify.yml | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/.mergify.yml b/.mergify.yml index 14ea4a46616..ea04825f814 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -1,16 +1,4 @@ pull_request_rules: - - name: Automatic merge - conditions: - - "#approved-reviews-by>=1" - - "#changes-requested-reviews-by=0" - - status-success=hydra:dfinity-ci-build:motoko:all-systems-go - - base=master - - label=automerge - actions: - merge: - method: merge - strict: smart - delete_head_branch: {} - name: Automatic merge (squash) conditions: - "#approved-reviews-by>=1" @@ -23,19 +11,6 @@ pull_request_rules: method: squash strict: smart delete_head_branch: {} - - name: Automatic merge (rebase) - conditions: - - "#approved-reviews-by>=1" - - "#changes-requested-reviews-by=0" - - status-success=hydra:dfinity-ci-build:motoko:all-systems-go - - base=master - - label=automerge-rebase - actions: - merge: - method: rebase - strict: smart - strict_method: rebase - delete_head_branch: {} - name: Clean up automerge tags conditions: - closed From 788395608cdf75ecdff3c904bef52f2478467d5f Mon Sep 17 00:00:00 2001 From: Bas van Dijk Date: Thu, 13 Feb 2020 16:25:54 +0100 Subject: [PATCH 1029/1176] nix/sources.json: upgrade nixpkgs to the latest master (#1189) This upgrades `nixpkgs` to DFINITY's fork of nixpkgs which tracks the `master` branch. There're only two patches on top of `master`: ``` commit a4e23f32f8d7006e217125a9123b53597b9c0c24 (HEAD -> dfinity-motoko, dfinity-lab/dfinity-motoko) Author: Bas van Dijk Date: Wed Feb 12 16:08:05 2020 +0100 expect: remove autoreconfHook since that causes a wrong path to stty See: https://github.com/NixOS/nixpkgs/issues/79863 commit f359aea057db81c51e55d7250283a0b2201bd6b6 Author: Bas van Dijk Date: Thu Feb 6 19:14:09 2020 +0100 libuv: 1.34.1 -> 1.34.2 (cherry picked from commit 21ad5c123b8e76ab241b89acbc8db24925244d63) ``` We need this patch in order to build `motoko` without using the upstream `cache.nixos.org`. It would be good not to use an external cache to decrease the chance an attacker can infect the cache with a trojan and to ensure DFINITY can always build their own code without depending on an external cache. --- nix/haskell-packages.nix | 8 +++++--- nix/sources.json | 16 ++++++++-------- test/ld/ok/representative.linked.wat.ok | 2 +- test/lsp-int/lsp-int.cabal | 2 +- test/run-drun/ok/caller.drun-run.ok | 8 ++++---- 5 files changed, 19 insertions(+), 17 deletions(-) diff --git a/nix/haskell-packages.nix b/nix/haskell-packages.nix index 68ea54866d2..a578ba03910 100644 --- a/nix/haskell-packages.nix +++ b/nix/haskell-packages.nix @@ -1,11 +1,13 @@ nix: subpath: let stdenv = nix.stdenv; in self: super: { - haskell-lsp-types = self.haskell-lsp-types_0_19_0_0; + haskell-lsp-types = self.haskell-lsp-types_0_20_0_0; - haskell-lsp = self.haskell-lsp_0_19_0_0; + haskell-lsp = self.haskell-lsp_0_20_0_1; - lsp-test = nix.haskell.lib.dontCheck self.lsp-test_0_9_0_0; + parser-combinators = self.parser-combinators_1_2_1; + + lsp-test = nix.haskell.lib.dontCheck self.lsp-test_0_10_1_0; lsp-int = self.callCabal2nix "lsp-int" (subpath "test/lsp-int") { }; diff --git a/nix/sources.json b/nix/sources.json index fa30810255e..68a25931c28 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -2,13 +2,13 @@ "common": { "ref": "master", "repo": "ssh://git@github.com/dfinity-lab/common", - "rev": "233f63f23f0a207f291693fc1983a92a53e28b59", + "rev": "7cf0a0864bf0670a7cad441067af0178fe51d506", "type": "git" }, "dfinity": { - "ref": "master", + "ref": "v0.5.0", "repo": "ssh://git@github.com/dfinity-lab/dfinity", - "rev": "c9459e781f5b4b77452949f1e63725612b2201c3", + "rev": "fc1706faada19c3bcf0eee941b0468bf0c312d00", "type": "git" }, "esm": { @@ -32,15 +32,15 @@ "version": "v1.2.0" }, "nixpkgs": { - "branch": "master", + "branch": "dfinity-motoko", "description": "A read-only mirror of NixOS/nixpkgs tracking the released channels. Send issues and PRs to", "homepage": "https://github.com/NixOS/nixpkgs", - "owner": "NixOS", + "owner": "dfinity-lab", "repo": "nixpkgs", - "rev": "82875a20ba444110396f95537b18247898e40e22", - "sha256": "1xy2zn3hkcv66ddvscr3l32jcx1qg9h14zvhmy5zf0pcfb8gn42i", + "rev": "a4e23f32f8d7006e217125a9123b53597b9c0c24", + "sha256": "1afpk1w6akfpvyj3n0wmlydpmxzb6khcgl4vhi7qkgg9bp6rngg4", "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/82875a20ba444110396f95537b18247898e40e22.tar.gz", + "url": "https://github.com/dfinity-lab/nixpkgs/archive/a4e23f32f8d7006e217125a9123b53597b9c0c24.tar.gz", "url_template": "https://github.com///archive/.tar.gz" }, "ocaml-vlq": { diff --git a/test/ld/ok/representative.linked.wat.ok b/test/ld/ok/representative.linked.wat.ok index 88a9a7a604a..540fe39b6da 100644 --- a/test/ld/ok/representative.linked.wat.ok +++ b/test/ld/ok/representative.linked.wat.ok @@ -28,4 +28,4 @@ (table (;0;) 0 0 funcref) (memory (;0;) 2) (global (;0;) i32 (i32.const 65536)) - (start 8)) + (start $link_start)) diff --git a/test/lsp-int/lsp-int.cabal b/test/lsp-int/lsp-int.cabal index 25291457571..4f3d40e7d3b 100644 --- a/test/lsp-int/lsp-int.cabal +++ b/test/lsp-int/lsp-int.cabal @@ -23,6 +23,6 @@ executable lsp-int , lens , data-default , haskell-lsp-types - , lsp-test ^>=0.9 + , lsp-test ^>=0.10 -- hs-source-dirs: default-language: Haskell2010 diff --git a/test/run-drun/ok/caller.drun-run.ok b/test/run-drun/ok/caller.drun-run.ok index ea45133a315..b2226da639a 100644 --- a/test/run-drun/ok/caller.drun-run.ok +++ b/test/run-drun/ok/caller.drun-run.ok @@ -4,7 +4,7 @@ ingress Completed: Canister: Payload: 0x4449444c0000 ingress Completed: Canister: Payload: 0x4449444c0000 ingress Completed: Canister: Payload: 0x4449444c0000 Ok: Payload: 0x4449444c0000 -ingress Completed: Canister: Payload: 0x4449444c016d7b010021000000000000000000000000000000000000000000000000000000000000000000 -Ok: Payload: 0x4449444c0001798d3a7c7a -Ok: Payload: 0x4449444c00017d21 -Ok: Payload: 0x4449444c016e7b01000100 +ingress Completed: Canister: Payload: 0x4449444c016d7b0100020101 +Ok: Payload: 0x4449444c0001792813c52f +Ok: Payload: 0x4449444c00017d02 +Ok: Payload: 0x4449444c016e7b01000101 From b81ba4bfb08ba25e3aeb04694805b9ed355a99e9 Mon Sep 17 00:00:00 2001 From: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> Date: Fri, 14 Feb 2020 14:45:25 +0100 Subject: [PATCH 1030/1176] Automatically import on completion (#1198) * parses and slices up the import section * adds the ability to put files back together after import slicing * extends the completion item format with additional properties * adds concat_map to our lib * implements import path shortening for packages * implements searching the full index for a prefix * fixes warnings for parser production printing * implements adding imports as LSP text edits * adds the ability to auto-import identifiers on completion * implements path shortening for relative imports * removes dead import slicing code We're just using TextEdits now * fixes integration tests * adds tests for the import path shortening * adds a test for auto-imports on completion * don't crash the server on parser errors Just insert new imports at the top of the file if this happens * moves Imports exception into parser_lib.ml * Update src/mo_frontend/parser.mly Co-Authored-By: Claudio Russo Co-authored-by: Claudio Russo --- src/languageServer/completion.ml | 46 ++++++++---- src/languageServer/declaration_index.ml | 53 +++++++++++++ src/languageServer/declaration_index.mli | 18 +++++ src/languageServer/declaration_index_test.ml | 25 +++++++ src/languageServer/imports.ml | 79 ++++++++++++++++++++ src/lib/lib.ml | 20 +++++ src/lib/lib.mli | 15 ++++ src/lsp/lsp.atd | 14 +++- src/mo_def/syntax.ml | 1 - src/mo_frontend/parser.mly | 10 ++- src/mo_frontend/parser_lib.ml | 1 + src/mo_frontend/parser_lib.mli | 1 + src/mo_frontend/printers.ml | 2 + test/lsp-int/Main.hs | 45 +++++++---- 14 files changed, 297 insertions(+), 33 deletions(-) create mode 100644 src/languageServer/declaration_index_test.ml create mode 100644 src/languageServer/imports.ml create mode 100644 src/mo_frontend/parser_lib.ml create mode 100644 src/mo_frontend/parser_lib.mli diff --git a/src/languageServer/completion.ml b/src/languageServer/completion.ml index 3602e9f43b6..85332a689b6 100644 --- a/src/languageServer/completion.ml +++ b/src/languageServer/completion.ml @@ -41,9 +41,11 @@ let item_of_ide_decl (d : DI.ide_decl) : Lsp_t.completion_item = Lsp_t.{ completion_item_label = value.DI.name; completion_item_kind = 3; - completion_item_insertText = tmpl; - completion_item_insertTextFormat = 2; - completion_item_detail = Some(Type.string_of_typ value.DI.typ); + completion_item_insertText = Some tmpl; + completion_item_insertTextFormat = Some 2; + completion_item_additionalTextEdits = None; + completion_item_documentation = Some(Type.string_of_typ value.DI.typ); + completion_item_detail = None; } | DI.TypeDecl ty -> let con = ty.DI.typ in @@ -51,14 +53,16 @@ let item_of_ide_decl (d : DI.ide_decl) : Lsp_t.completion_item = Lsp_t.{ completion_item_label = ty.DI.name; completion_item_kind = 7; - completion_item_insertText = tmpl; - completion_item_insertTextFormat = 2; - completion_item_detail = + completion_item_insertText = Some tmpl; + completion_item_insertTextFormat = Some 2; + completion_item_additionalTextEdits = None; + completion_item_documentation = Some (Printf.sprintf "type %s%s" ty.DI.name params); + completion_item_detail = None; } let import_relative_to_project_root root module_path dependency = @@ -132,18 +136,20 @@ let completions index logger project_root file_path file_contents line column = let imported = Source_file.parse_module_header project_root file_path file_contents in let current_uri_opt = Lib.FilePath.relative_to project_root file_path in let toplevel_decls = - let current_module_decls = - current_uri_opt - |> opt_bind (fun uri -> DI.lookup_module (Filename.remove_extension uri) index) - |> Option.fold ~none:[] ~some:snd in - current_module_decls + let current_module_decls = + current_uri_opt + |> opt_bind (fun uri -> DI.lookup_module (Filename.remove_extension uri) index) + |> Option.fold ~none:[] ~some:snd in + current_module_decls in let module_alias_completion_item alias = Lsp_t.{ completion_item_label = alias; completion_item_kind = 9; - completion_item_insertText = alias; - completion_item_insertTextFormat = 1; + completion_item_insertText = Some alias; + completion_item_insertTextFormat = Some 1; + completion_item_additionalTextEdits = None; + completion_item_documentation = None; completion_item_detail = None; } in match find_completion_prefix logger file_contents line column with @@ -174,8 +180,18 @@ let completions index logger project_root file_path file_contents line column = (* The matching import references a module we haven't loaded *) []) | None -> - (* No module with the given prefix was found *) - [] + (* No import with the given alias was found *) + let import_edit = Imports.add_import file_contents alias in + let possible_imports = DI.find_with_prefix prefix (Lib.FilePath.make_absolute project_root file_path) index in + let completions = + Lib.List.concat_map (fun (p, ds) -> + List.map (fun d -> + Lsp_t.{ + (item_of_ide_decl d) with + completion_item_additionalTextEdits = Some [import_edit p]; + completion_item_detail = Some p + }) ds) possible_imports in + completions let completion_handler index logger project_root file_path file_contents position = let line = position.Lsp_t.position_line in diff --git a/src/languageServer/declaration_index.ml b/src/languageServer/declaration_index.ml index e9c508b5102..d275fabfc8f 100644 --- a/src/languageServer/declaration_index.ml +++ b/src/languageServer/declaration_index.ml @@ -50,6 +50,9 @@ let name_of_ide_decl (d : ide_decl) : string = | ValueDecl value -> value.name | TypeDecl ty -> ty.name +let decl_has_prefix prefix d = + Option.is_some (Lib.String.chop_prefix prefix (name_of_ide_decl d)) + module Index = Map.Make(String) type declaration_index = { @@ -92,6 +95,56 @@ let lookup_module | Ok (Ic _ | IcAlias _) -> (* TODO *) None | Error _ -> None +let rec drop_common_prefix eq l1 l2 = + match l1, l2 with + | h1 :: t1, h2 :: t2 when eq h1 h2 -> + drop_common_prefix eq t1 t2 + | _ -> (l1, l2) + +let shorten_import_path + : Pipeline.ResolveImport.package_map + -> string + -> string + -> string = + fun pkg_map base path -> + let pkg_path = + Flags.M.bindings pkg_map + |> Lib.List.first_opt (fun (name, pkg_path) -> + if Lib.FilePath.is_subpath pkg_path path + then + let rel_path = Option.get (Lib.FilePath.relative_to pkg_path path) in + Some (Printf.sprintf "mo:%s/%s" name (Filename.remove_extension rel_path)) + else + None + ) + in match pkg_path with + | Some p -> p + | None -> + let (base', path') = + drop_common_prefix + String.equal + (Lib.String.split (Filename.dirname base) '/') + (Lib.String.split path '/') in + List.map (fun _ -> "..") base' @ path' + |> String.concat "/" + |> Filename.remove_extension + +let find_with_prefix + : string + -> string + -> t + -> (string * ide_decl list) list = + fun prefix base {modules; package_map; _} -> + Index.bindings modules + |> List.map (fun (p, ds) -> + let import_path = + if p = "@prim" then + "mo:prim" + else + shorten_import_path package_map base p in + (import_path, List.filter (decl_has_prefix prefix) ds)) + |> List.filter (fun (_, ds) -> not (ds = [])) + let empty : unit -> t = fun _ -> let open Pipeline.ResolveImport in let resolved_flags = diff --git a/src/languageServer/declaration_index.mli b/src/languageServer/declaration_index.mli index 3da4650704f..00965277192 100644 --- a/src/languageServer/declaration_index.mli +++ b/src/languageServer/declaration_index.mli @@ -24,6 +24,24 @@ type ide_decl = val string_of_ide_decl : ide_decl -> string val name_of_ide_decl : ide_decl -> string +val shorten_import_path + : Pipeline.ResolveImport.package_map + (** The package map for searching package paths *) + -> string + (** The file that ends up containing the import *) + -> string + (** The path to be shortened *) + -> string + val lookup_module : string -> t -> (string * ide_decl list) option +val find_with_prefix + : string + (** The prefix *) + -> string + (** The file in which the results would be imported *) + -> t + (** The declaration index *) + -> (string * ide_decl list) list + val make_index : (string -> string -> unit) -> Vfs.t -> string list -> t Diag.result diff --git a/src/languageServer/declaration_index_test.ml b/src/languageServer/declaration_index_test.ml new file mode 100644 index 00000000000..b46c3d35b54 --- /dev/null +++ b/src/languageServer/declaration_index_test.ml @@ -0,0 +1,25 @@ +let shorten_test pkg_map base path expected = + let actual = + Declaration_index.shorten_import_path + (Mo_config.Flags.M.of_seq (List.to_seq pkg_map)) + base + path in + if not (actual = expected) then + (Printf.printf "Expected:\n%s\nBut got:\n%s\n" expected actual; + false) + else + true + +let%test "it shortens to a relative path" = + shorten_test + [("std", "/pkgs/std")] + "/project/src/file.mo" + "/project/src/lib/hello.mo" + "lib/hello" + +let%test "it shortens to a package path" = + shorten_test + [("std", "/pkgs/std")] + "/project/src/file.mo" + "/pkgs/std/list.mo" + "mo:std/list" diff --git a/src/languageServer/imports.ml b/src/languageServer/imports.ml new file mode 100644 index 00000000000..7abfc35baf5 --- /dev/null +++ b/src/languageServer/imports.ml @@ -0,0 +1,79 @@ +(** Import management for Motoko's language server *) +open Mo_frontend +open Mo_def +open Source +module Lsp = Lsp.Lsp_t + +type import = string * string + +let parse_with mode lexer parser = + Ok (Parsing.parse 0 (parser lexer.Lexing.lex_curr_p) (Lexer.token mode) lexer) + +let parse_string s = + try + (let lexer = Lexing.from_string s in + let parse = Parser.Incremental.parse_module_header in + ignore (parse_with Lexer.Normal lexer parse); []) + with + | Parser_lib.Imports is -> is + | ex -> [] + +let match_import : Syntax.dec -> string * string = + fun dec -> + let open Syntax in + match dec.it with + | LetD ({it=VarP {it=name;_};_}, {it=ImportE(s, _);_}) -> (name, s) + | _ -> ("Can't", "deal with this import format") + +let print_import : import -> string = + fun (alias, path) -> + Printf.sprintf "import %s \"%s\";" alias path + +(** Formats an import section. Eg. sorting imports alphabetically *) +let format_imports : import list -> string = + fun imports -> + if imports = [] + then "" + else + String.concat "\n" + (List.map + print_import + (List.sort (fun (a1, _) (a2, _) -> compare a1 a2) imports)) + ^ "\n" + +let mk_range : int * int -> int * int -> Lsp.range = + fun (sl, sc) (el, ec) -> + Lsp.{ + range_start = + { position_line = sl; + position_character = sc + }; + range_end_ = + { position_line = el; + position_character = ec + } + } + +let add_import : string -> string -> string -> Lsp.text_edit = + fun input -> + (* We do the parsing as soon as we get the input so the curried + usage of this function doesn't duplicate work *) + match parse_string input with + | [] -> + fun alias import_path -> + Lsp.{ + text_edit_range = mk_range (0, 0) (0, 0); + text_edit_newText = format_imports [(alias, import_path)] + } + | decls -> + let open Source in + let start_line = (List.hd decls).at.left.line - 1 in + let end_line = (Lib.List.last decls).at.right.line - 1 in + let imports = List.map match_import decls in + let import_range = mk_range (start_line, 0) (end_line + 1, 0) in + fun alias import_path -> + let new_imports = (alias, import_path) :: imports in + Lsp.{ + text_edit_range = import_range; + text_edit_newText = format_imports new_imports + } diff --git a/src/lib/lib.ml b/src/lib/lib.ml index 31974f4fd76..a8113aeb20b 100644 --- a/src/lib/lib.ml +++ b/src/lib/lib.ml @@ -187,6 +187,9 @@ struct and make' n x xs = if n = 0 then xs else make' (n - 1) x (x::xs) + let concat_map f xs = + List.concat (List.map f xs) + let rec table n f = table' n f [] and table' n f xs = if n = 0 then xs else table' (n - 1) f (f (n - 1) :: xs) @@ -275,6 +278,14 @@ struct let rec iter_pairs f = function | [] -> () | x::ys -> List.iter (fun y -> f x y) ys; iter_pairs f ys + + let rec is_prefix equal prefix list = + match prefix with + | [] -> true + | hd :: tl -> + (match list with + | [] -> false + | hd' :: tl' -> equal hd hd' && is_prefix equal tl tl') end module List32 = @@ -427,6 +438,15 @@ struct if not (Filename.is_relative path) then path else normalise (Filename.concat base path) + + let segments p = String.split p '/' + + let is_subpath base path = + if Filename.is_relative base || Filename.is_relative path + then assert false + (* We can't just check for prefixing on the string because + /path/tosomething is not a subpath of /path/to*) + else List.is_prefix (=) (segments base) (segments path) end diff --git a/src/lib/lib.mli b/src/lib/lib.mli index 77343e6e81b..981ddb6950f 100644 --- a/src/lib/lib.mli +++ b/src/lib/lib.mli @@ -11,6 +11,7 @@ end module List : sig val equal : ('a -> 'a -> bool) -> 'a list -> 'a list -> bool + val concat_map : ('a -> 'b list) -> 'a list -> 'b list val make : int -> 'a -> 'a list val table : int -> (int -> 'a) -> 'a list val group : ('a -> 'a -> bool) -> 'a list -> 'a list list @@ -29,6 +30,7 @@ sig val compare : ('a -> 'a -> int) -> 'a list -> 'a list -> int val is_ordered : ('a -> 'a -> int) -> 'a list -> bool val is_strictly_ordered : ('a -> 'a -> int) -> 'a list -> bool + val is_prefix : ('a -> 'a -> bool) -> 'a list -> 'a list -> bool val iter_pairs : ('a -> 'a -> unit) -> 'a list -> unit end @@ -168,4 +170,17 @@ sig val relative_to : string -> string -> string option val make_absolute : string -> string -> string + + (** + * Checks whether one path is nested below another. + * Must only be called on two absolute paths! + * + * Examples: + * + * is_subpath "/home" "/home/path" = true + * is_subpath "/home" "/path" = false + * is_subpath "/home/path" "/home" = false + * is_subpath "/home" "/homepath" = false + *) + val is_subpath : string -> string -> bool end diff --git a/src/lsp/lsp.atd b/src/lsp/lsp.atd index 0db4a6202c8..ba7bca90f0f 100644 --- a/src/lsp/lsp.atd +++ b/src/lsp/lsp.atd @@ -54,6 +54,14 @@ type incoming_message_params = [ | Exit of unit nullable ] +(* Common LSP data structures *) + +type text_edit = { + range: range; + newText: string; +} + + (* Outgoing messages @@ -100,9 +108,11 @@ type markup_content = { type completion_item = { label : string; kind : int; - insertText : string; - insertTextFormat : int; + ?insertText : string nullable; + ?insertTextFormat : int nullable; + ?additionalTextEdits : text_edit list nullable; ?detail: string nullable; + ?documentation: string nullable; } diff --git a/src/mo_def/syntax.ml b/src/mo_def/syntax.ml index 9eff044ceea..b497900da58 100644 --- a/src/mo_def/syntax.ml +++ b/src/mo_def/syntax.ml @@ -327,4 +327,3 @@ let funcE (f, s, tbs, p, t_opt, sugar, e) = FuncE(f, s, ensure_scope_bind "" tbs, p, t_opt, sugar, e) | _ -> FuncE(f, s, tbs, p, t_opt, sugar, e) - diff --git a/src/mo_frontend/parser.mly b/src/mo_frontend/parser.mly index dffbf0834ea..4b77721a739 100644 --- a/src/mo_frontend/parser.mly +++ b/src/mo_frontend/parser.mly @@ -6,6 +6,7 @@ open Mo_values open Syntax open Source open Operator +open Parser_lib (* Position handling *) @@ -173,10 +174,12 @@ let share_expfield (ef : exp_field) = %type class_body %type catch case %type Mo_def.Syntax.exp'> bl ob +%type import_list %type start %start Mo_def.Syntax.prog> parse_prog %start Mo_def.Syntax.prog> parse_prog_interactive +%start parse_module_header (* Result passed via the Parser_lib.Imports exception *) %on_error_reduce exp_bin(ob) exp_bin(bl) exp_nondec(bl) exp_nondec(ob) %% @@ -720,7 +723,6 @@ class_body : (* Programs *) - imp : | IMPORT xf=id_opt EQ? f=TEXT { let _, x = xf "import" $sloc in @@ -737,4 +739,10 @@ parse_prog_interactive : | start is=seplist(imp, SEMICOLON) ds=seplist(dec, SEMICOLON) SEMICOLON_EOL { fun filename -> { it = is @ ds; at = at $sloc ; note = filename} } +import_list : + | is=seplist(imp, semicolon) { raise (Imports is) } + +parse_module_header : + | start import_list EOF {} + %% diff --git a/src/mo_frontend/parser_lib.ml b/src/mo_frontend/parser_lib.ml new file mode 100644 index 00000000000..7d982ec279d --- /dev/null +++ b/src/mo_frontend/parser_lib.ml @@ -0,0 +1 @@ +exception Imports of Mo_def.Syntax.dec list diff --git a/src/mo_frontend/parser_lib.mli b/src/mo_frontend/parser_lib.mli new file mode 100644 index 00000000000..7d982ec279d --- /dev/null +++ b/src/mo_frontend/parser_lib.mli @@ -0,0 +1 @@ +exception Imports of Mo_def.Syntax.dec list diff --git a/src/mo_frontend/printers.ml b/src/mo_frontend/printers.ml index 88f05aac816..be9f319f26d 100644 --- a/src/mo_frontend/printers.ml +++ b/src/mo_frontend/printers.ml @@ -149,6 +149,7 @@ let string_of_symbol symbol : string = | X (N N_exp_un_ob_) -> "" | X (N N_func_body) -> "" | X (N N_imp) -> "" + | X (N N_import_list) -> "" | X (N N_lit) -> "" | X (N N_ob) -> "" | X (N N_obj_body) -> "" @@ -157,6 +158,7 @@ let string_of_symbol symbol : string = | X (N N_option_return_typ_) -> "?" | X (N N_option_return_typ_nullary_) -> "?" | X (N N_option_typ_args_) -> "?" + | X (N N_parse_module_header) -> "" | X (N N_parse_prog) -> "" | X (N N_parse_prog_interactive) -> "" | X (N N_pat) -> "" diff --git a/test/lsp-int/Main.hs b/test/lsp-int/Main.hs index c62ebb12552..36411ca62cc 100644 --- a/test/lsp-int/Main.hs +++ b/test/lsp-int/Main.hs @@ -1,8 +1,6 @@ -{-# language OverloadedStrings #-} -{-# language DuplicateRecordFields #-} -{-# language ExplicitForAll #-} -{-# language ScopedTypeVariables #-} -{-# language BlockArguments #-} +{-# language OverloadedStrings, DuplicateRecordFields, + ExplicitForAll, ScopedTypeVariables, BlockArguments, + LambdaCase #-} module Main where @@ -17,8 +15,9 @@ import Data.Maybe (mapMaybe) import Data.Text (Text) import qualified Data.Text as Text import Language.Haskell.LSP.Test hiding (message) -import Language.Haskell.LSP.Types (TextDocumentIdentifier(..), Position(..), HoverContents(..), MarkupContent(..), MarkupKind(..), TextEdit(..), Range(..), DidSaveTextDocumentParams(..), ClientMethod(..), Diagnostic(..), Location(..), Uri(..), filePathToUri) -import Language.Haskell.LSP.Types.Lens (contents, label, detail, message) +import Language.Haskell.LSP.Types (TextDocumentIdentifier(..), Position(..), HoverContents(..), MarkupContent(..), MarkupKind(..), TextEdit(..), Range(..), DidSaveTextDocumentParams(..), ClientMethod(..), Diagnostic(..), Location(..), Uri(..), filePathToUri, CompletionDoc(..)) +import qualified Language.Haskell.LSP.Types as LSP +import Language.Haskell.LSP.Types.Lens (contents, label, documentation, message, additionalTextEdits, newText) import System.Directory (setCurrentDirectory, makeAbsolute, removeFile) import System.Environment (getArgs) import System.Exit (exitFailure) @@ -27,6 +26,11 @@ import System.IO (hPutStr, stderr) import Test.HUnit.Lang (HUnitFailure(..), formatFailureReason) import Test.Hspec (shouldBe, shouldMatchList, shouldContain) +completionDocAsText :: Maybe CompletionDoc -> Maybe Text +completionDocAsText = fmap \case + CompletionDocString t -> t + _ -> error "Non-text documentation field" + completionTestCase :: TextDocumentIdentifier -> Position @@ -34,7 +38,7 @@ completionTestCase -> Session () completionTestCase doc pos pred = do actual <- getCompletions doc pos - liftIO (pred (map (\c -> (c^.label, c^.detail)) actual)) + liftIO (pred (map (\c -> (c^.label, completionDocAsText (c^.documentation))) actual)) hoverTestCase :: TextDocumentIdentifier @@ -111,8 +115,10 @@ main = do putStrLn "Starting the session" runSession (mo_ide - <> " --canister-main app.mo --debug --error-detail 0" - <> " --package mydep " <> project <> "/mydependency/") + <> " --canister-main app.mo" + <> " --debug" + <> " --error-detail 0" + <> " --package mydep " <> (project "mydependency")) fullCaps "." $ do log "Initializing" @@ -155,13 +161,13 @@ main = do [("mydependency/lib.mo", Range (Position 5 17) (Position 5 24))] log "Completion tests" - -- Completing top level definitions: + log "Completing top level definitions" withDoc "ListClient.mo" \doc -> do actual <- getCompletions doc (Position 7 0) liftIO (shouldBe (mapMaybe (\c -> guard (c^.label == "empty") - *> pure (c^.label, c^.detail)) actual) + *> pure (c^.label, completionDocAsText (c^.documentation))) actual) ([("empty", Just "() -> Stack")])) -- 15 | List.push(x, s); -- ==> 15 | List.pus @@ -173,7 +179,7 @@ main = do (Position 14 14) (`shouldMatchList` [("push",Just "(T, List) -> List")]) - -- Completing primitives: + log "Completing primitives" withDoc "ListClient.mo" \doc -> do let edit = TextEdit (Range (Position 15 0) (Position 15 0)) "Prim." _ <- applyEdit doc edit @@ -181,9 +187,20 @@ main = do liftIO (shouldBe (mapMaybe (\c -> guard (c^.label == "word32ToNat") - *> pure (c^.label, c^.detail)) actual) + *> pure (c^.label, completionDocAsText (c^.documentation))) actual) ([("word32ToNat", Just "Word32 -> Nat")])) + log "Completing not-yet-imported modules" + withDoc "ListClient.mo" \doc -> do + let edit = TextEdit (Range (Position 15 0) (Position 15 0)) "MyDep.print_" + _ <- applyEdit doc edit + [actual] <- getCompletions doc (Position 15 12) + liftIO do + shouldBe (actual^.label) "print_hello" + shouldBe (completionDocAsText (actual^.documentation)) (Just "() -> Text") + let Just (LSP.List [importEdit]) = actual^.additionalTextEdits + shouldContain (Text.lines (importEdit^.newText)) ["import MyDep \"mo:mydep/lib\";"] + withDoc "ListClient.mo" \doc -> do -- 1 | import List -- ==> 1 | ort List From 74dfa8cd9221409e7aaea0a8802f738f47c3913d Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Sun, 16 Feb 2020 07:21:31 -0800 Subject: [PATCH 1031/1176] Stdlib: add Nat/Int.min/max (#1205) I felt I needed them for my demo, and they seem to make sense, so adding them. --- stdlib/src/int.mo | 8 ++++++++ stdlib/src/nat.mo | 7 +++++++ 2 files changed, 15 insertions(+) diff --git a/stdlib/src/int.mo b/stdlib/src/int.mo index a994dedf638..519cbc13ee6 100644 --- a/stdlib/src/int.mo +++ b/stdlib/src/int.mo @@ -63,4 +63,12 @@ module { public let toInt16 : Int -> Int16 = Prim.intToInt16; public let toInt32 : Int -> Int32 = Prim.intToInt32; public let toInt64 : Int -> Int64 = Prim.intToInt64; + + public let min : (Int, Int) -> Int = func(x,y) { + if (x < y) x else y; + }; + + public let max : (Int, Int) -> Int = func(x,y) { + if (x < y) y else x; + }; } diff --git a/stdlib/src/nat.mo b/stdlib/src/nat.mo index 150ffb0197b..bc4dbbad1e3 100644 --- a/stdlib/src/nat.mo +++ b/stdlib/src/nat.mo @@ -42,4 +42,11 @@ module { x + y; }; + public let min : (Nat, Nat) -> Nat = func(x,y) { + if (x < y) x else y; + }; + + public let max : (Nat, Nat) -> Nat = func(x,y) { + if (x < y) y else x; + }; } From 11ad557623ab8b8a2029405ededaaed63e2ffcc8 Mon Sep 17 00:00:00 2001 From: Enzo Haussecker Date: Mon, 17 Feb 2020 08:36:43 -0800 Subject: [PATCH 1032/1176] Bug fix in tabulateVar (#1207) --- stdlib/src/array.mo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/src/array.mo b/stdlib/src/array.mo index 622b718b00b..1e6e3c97273 100644 --- a/stdlib/src/array.mo +++ b/stdlib/src/array.mo @@ -156,7 +156,7 @@ module { public func tabulateVar(len : Nat, gen : Nat -> A) : [var A] { if (len == 0) { return [var] }; let xs = Prim.Array_init(len, gen 0); - for (i in range(1,len)) { + for (i in range(1,len-1)) { xs[i] := gen i; }; return xs; From c03786a9ea7effe62ca0e00ce7579d361d0fc4eb Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Mon, 17 Feb 2020 22:22:29 +0000 Subject: [PATCH 1033/1176] utf8 bug repro for issue #1208 (#1212) * utf8 bug * minimize repro --- test/run-drun/ok/utf8.drun-run.ok | 6 ++++++ test/run-drun/ok/utf8.ic-stub-run.ok | 11 +++++++++++ test/run-drun/ok/utf8.run-ir.ok | 6 ++++++ test/run-drun/ok/utf8.run-low.ok | 6 ++++++ test/run-drun/ok/utf8.run.ok | 6 ++++++ test/run-drun/utf8.mo | 26 ++++++++++++++++++++++++++ 6 files changed, 61 insertions(+) create mode 100644 test/run-drun/ok/utf8.drun-run.ok create mode 100644 test/run-drun/ok/utf8.ic-stub-run.ok create mode 100644 test/run-drun/ok/utf8.run-ir.ok create mode 100644 test/run-drun/ok/utf8.run-low.ok create mode 100644 test/run-drun/ok/utf8.run.ok create mode 100644 test/run-drun/utf8.mo diff --git a/test/run-drun/ok/utf8.drun-run.ok b/test/run-drun/ok/utf8.drun-run.ok new file mode 100644 index 00000000000..fd8cd9921f3 --- /dev/null +++ b/test/run-drun/ok/utf8.drun-run.ok @@ -0,0 +1,6 @@ +ingress System +debug.print: ██ + ██ + +debug.print: IDL error: UTF-8 validation failure +ingress Err: IC0502: Canister ic:2A012B trapped: unreachable diff --git a/test/run-drun/ok/utf8.ic-stub-run.ok b/test/run-drun/ok/utf8.ic-stub-run.ok new file mode 100644 index 00000000000..b7050515055 --- /dev/null +++ b/test/run-drun/ok/utf8.ic-stub-run.ok @@ -0,0 +1,11 @@ +→ create +← completed: canister-id = 0x2a01 +→ install +← completed +→ update callshow(0x4449444c0000) +debug.print: ██ + ██ + +debug.print: IDL error: UTF-8 validation failure +Trap: EvalTrapError :0.1 "unreachable executed" +← rejected (RC_CANISTER_ERROR): canister trapped: EvalTrapError :0.1 "unreachable executed" diff --git a/test/run-drun/ok/utf8.run-ir.ok b/test/run-drun/ok/utf8.run-ir.ok new file mode 100644 index 00000000000..faf09a24400 --- /dev/null +++ b/test/run-drun/ok/utf8.run-ir.ok @@ -0,0 +1,6 @@ +██ + ██ + +██ + ██ + diff --git a/test/run-drun/ok/utf8.run-low.ok b/test/run-drun/ok/utf8.run-low.ok new file mode 100644 index 00000000000..faf09a24400 --- /dev/null +++ b/test/run-drun/ok/utf8.run-low.ok @@ -0,0 +1,6 @@ +██ + ██ + +██ + ██ + diff --git a/test/run-drun/ok/utf8.run.ok b/test/run-drun/ok/utf8.run.ok new file mode 100644 index 00000000000..faf09a24400 --- /dev/null +++ b/test/run-drun/ok/utf8.run.ok @@ -0,0 +1,6 @@ +██ + ██ + +██ + ██ + diff --git a/test/run-drun/utf8.mo b/test/run-drun/utf8.mo new file mode 100644 index 00000000000..cec83da429b --- /dev/null +++ b/test/run-drun/utf8.mo @@ -0,0 +1,26 @@ +import Prim "mo:prim"; +actor a { + + + +public func callshow(): async Text { + let t = await show(); + Prim.debugPrint t; + t + }; + +public func show() : async Text { + var accum = ""; + accum #= "██"; + accum #= " "; + accum #= "\n"; + accum #= " "; + accum #= "██"; + accum #= "\n"; + Prim.debugPrint accum; + accum + }; +}; + + +ignore a.callshow(); //OR-CALL ingress callshow "DIDL\x00\x00" From be2667f6bb872e3b8598688bb0b27a4dab528692 Mon Sep 17 00:00:00 2001 From: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> Date: Tue, 18 Feb 2020 12:22:31 +0100 Subject: [PATCH 1034/1176] filters out completions that would lead to self-imports (#1214) --- src/languageServer/completion.ml | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/languageServer/completion.ml b/src/languageServer/completion.ml index 85332a689b6..bc97f0b4e11 100644 --- a/src/languageServer/completion.ml +++ b/src/languageServer/completion.ml @@ -185,12 +185,16 @@ let completions index logger project_root file_path file_contents line column = let possible_imports = DI.find_with_prefix prefix (Lib.FilePath.make_absolute project_root file_path) index in let completions = Lib.List.concat_map (fun (p, ds) -> - List.map (fun d -> - Lsp_t.{ - (item_of_ide_decl d) with - completion_item_additionalTextEdits = Some [import_edit p]; - completion_item_detail = Some p - }) ds) possible_imports in + if p = Filename.basename file_path then + (* Self-imports are not allowed *) + [] + else + List.map (fun d -> + Lsp_t.{ + (item_of_ide_decl d) with + completion_item_additionalTextEdits = Some [import_edit p]; + completion_item_detail = Some p + }) ds) possible_imports in completions let completion_handler index logger project_root file_path file_contents position = From 05f41e1c84b8379c9dd6c26a701a51260ecb2cc8 Mon Sep 17 00:00:00 2001 From: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> Date: Tue, 18 Feb 2020 14:50:56 +0100 Subject: [PATCH 1035/1176] Reports diagnostics at startup (#1215) * reports diagnostics at startup This means no initial save is required to receive diagnostics * fixes formatting Co-authored-by: Claudio Russo --- src/languageServer/languageServer.ml | 46 +++++++++++++++------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/src/languageServer/languageServer.ml b/src/languageServer/languageServer.ml index 3d3ff4b4d2f..218183543bf 100644 --- a/src/languageServer/languageServer.ml +++ b/src/languageServer/languageServer.ml @@ -108,16 +108,31 @@ let start entry_point debug = let client_capabilities = ref None in let project_root = Sys.getcwd () in let _ = log_to_file "project_root" project_root in + let startup_diags = ref [] in let files_with_diags = ref [] in let vfs = ref Vfs.empty in let decl_index = let ix = match Declaration_index.make_index log_to_file !vfs [entry_point] with - | Error(err) -> - List.iter (fun e -> log_to_file "Error" (Diag.string_of_message e)) err; - Declaration_index.empty () + | Error errs -> + List.iter (fun e -> log_to_file "Error" (Diag.string_of_message e)) errs; + startup_diags := errs; + Declaration_index.empty () | Ok((ix, _)) -> ix in ref ix in + + let sync_diagnostics msgs = + let diags_by_file = + msgs + |> List.map diagnostics_of_message + |> Lib.List.group (fun (_, f1) (_, f2) -> f1 = f2) + |> List.map (fun diags -> + let (_, file) = List.hd diags in + (List.map fst diags, Vfs.uri_from_file file)) in + List.iter clear_diagnostics !files_with_diags; + files_with_diags := List.map snd diags_by_file; + List.iter (fun (diags, uri) -> publish_diagnostics uri diags) diags_by_file in + let rec loop () = let clength = read_line () in let cl = "Content-Length: " in @@ -224,27 +239,16 @@ let start entry_point debug = vfs := Vfs.close_file params !vfs | (_, `TextDocumentDidSave _) -> let msgs = match Declaration_index.make_index log_to_file !vfs [entry_point] with - | Error msgs' -> List.iter (fun msg -> log_to_file "rebuild_error" (Diag.string_of_message msg)) msgs'; msgs' - | Ok((ix, msgs')) -> - decl_index := ix; - msgs' in - let diags_by_file = - msgs - |> List.map diagnostics_of_message - |> Lib.List.group (fun (_, f1) (_, f2) -> f1 = f2) - |> List.map (fun diags -> - let (_, file) = List.hd diags in - (List.map fst diags, Vfs.uri_from_file file)) in - - List.iter clear_diagnostics !files_with_diags; - files_with_diags := List.map snd diags_by_file; - List.iter (fun (diags, uri) -> - let _ = log_to_file "diag_uri" uri in - publish_diagnostics uri diags) diags_by_file; - + | Error msgs' -> List.iter (fun msg -> log_to_file "rebuild_error" (Diag.string_of_message msg)) msgs'; msgs' + | Ok((ix, msgs')) -> + decl_index := ix; + msgs' in + sync_diagnostics msgs (* Notification messages *) | (None, `Initialized _) -> + sync_diagnostics !startup_diags; + startup_diags := []; show_message Lsp.MessageType.Info "Motoko LS initialized"; | (Some id, `Shutdown _) -> From ea32767909dfa962440312571ad0b38bb0043133 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 18 Feb 2020 09:31:11 -0800 Subject: [PATCH 1036/1176] RTS: Fix utf8 validation bug (#1213) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit C is great, isn’t it… also see https://github.com/chansen/c-utf8-valid/issues/1 --- rts/test_rts.c | 10 +++++++--- rts/utf8_valid.c | 4 +++- test/run-drun/ok/utf8.drun-run.ok | 8 ++++---- test/run-drun/ok/utf8.ic-stub-run.ok | 9 ++++----- test/run-drun/ok/utf8.run-ir.ok | 6 ++---- test/run-drun/ok/utf8.run-low.ok | 6 ++---- test/run-drun/ok/utf8.run.ok | 6 ++---- test/run-drun/utf8.mo | 8 +------- 8 files changed, 25 insertions(+), 32 deletions(-) diff --git a/rts/test_rts.c b/rts/test_rts.c index 1d446bc3245..6047bcf4944 100644 --- a/rts/test_rts.c +++ b/rts/test_rts.c @@ -132,10 +132,12 @@ int main () { printf("Testing UTF8...\n"); extern bool utf8_valid(const char*, size_t); - const int cases = 33; - const char* utf8_inputs[cases] = { + const char* utf8_inputs[] = { "abcd", + // issue 1208 + " \xe2\x96\x88 ", + // from https://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt // // 3.5 Impossible bytes @@ -181,10 +183,12 @@ int main () { "\xed\xae\x80\xed\xbf\xbf", "\xed\xaf\xbf\xed\xb0\x80", "\xed\xaf\xbf\xed\xbf\xbf" + }; + const int cases = sizeof utf8_inputs / sizeof *utf8_inputs; for (int i = 0; i < cases; ++i) { - bool invalid = i > 0; + bool invalid = i >= 2; // the first two tests should pass assert( invalid != utf8_valid(utf8_inputs[i], strlen(utf8_inputs[i])), "%svalid UTF-8 test #%d failed\n", invalid ? "in" : "", i + 1); } diff --git a/rts/utf8_valid.c b/rts/utf8_valid.c index b2b484ee7a6..40ee982da1d 100644 --- a/rts/utf8_valid.c +++ b/rts/utf8_valid.c @@ -71,13 +71,15 @@ utf8_check(const char *src, size_t len, size_t *cursor) { unsigned char buf[4]; uint32_t v; - for (p = cur;;) { + while (true) { if (cur >= end - 3) { if (cur == end) break; buf[0] = buf[1] = buf[2] = buf[3] = 0; as_memcpy((char *)buf, (const char *)cur, end - cur); p = (const unsigned char *)buf; + } else { + p = cur; } v = p[0]; diff --git a/test/run-drun/ok/utf8.drun-run.ok b/test/run-drun/ok/utf8.drun-run.ok index fd8cd9921f3..61ceeecd35e 100644 --- a/test/run-drun/ok/utf8.drun-run.ok +++ b/test/run-drun/ok/utf8.drun-run.ok @@ -1,6 +1,6 @@ ingress System -debug.print: ██ - ██ +debug.print: ██ ██ -debug.print: IDL error: UTF-8 validation failure -ingress Err: IC0502: Canister ic:2A012B trapped: unreachable +debug.print: ██ ██ + +ingress Completed: Canister: Payload: 0x4449444c00017111e29688e2968820202020e29688e296880a diff --git a/test/run-drun/ok/utf8.ic-stub-run.ok b/test/run-drun/ok/utf8.ic-stub-run.ok index b7050515055..912d4cd9a5d 100644 --- a/test/run-drun/ok/utf8.ic-stub-run.ok +++ b/test/run-drun/ok/utf8.ic-stub-run.ok @@ -3,9 +3,8 @@ → install ← completed → update callshow(0x4449444c0000) -debug.print: ██ - ██ +debug.print: ██ ██ -debug.print: IDL error: UTF-8 validation failure -Trap: EvalTrapError :0.1 "unreachable executed" -← rejected (RC_CANISTER_ERROR): canister trapped: EvalTrapError :0.1 "unreachable executed" +debug.print: ██ ██ + +← completed: 0x4449444c00017111e29688e2968820202020e29688e296880a diff --git a/test/run-drun/ok/utf8.run-ir.ok b/test/run-drun/ok/utf8.run-ir.ok index faf09a24400..793693fe708 100644 --- a/test/run-drun/ok/utf8.run-ir.ok +++ b/test/run-drun/ok/utf8.run-ir.ok @@ -1,6 +1,4 @@ -██ - ██ +██ ██ -██ - ██ +██ ██ diff --git a/test/run-drun/ok/utf8.run-low.ok b/test/run-drun/ok/utf8.run-low.ok index faf09a24400..793693fe708 100644 --- a/test/run-drun/ok/utf8.run-low.ok +++ b/test/run-drun/ok/utf8.run-low.ok @@ -1,6 +1,4 @@ -██ - ██ +██ ██ -██ - ██ +██ ██ diff --git a/test/run-drun/ok/utf8.run.ok b/test/run-drun/ok/utf8.run.ok index faf09a24400..793693fe708 100644 --- a/test/run-drun/ok/utf8.run.ok +++ b/test/run-drun/ok/utf8.run.ok @@ -1,6 +1,4 @@ -██ - ██ +██ ██ -██ - ██ +██ ██ diff --git a/test/run-drun/utf8.mo b/test/run-drun/utf8.mo index cec83da429b..9c8766ba14b 100644 --- a/test/run-drun/utf8.mo +++ b/test/run-drun/utf8.mo @@ -10,13 +10,7 @@ public func callshow(): async Text { }; public func show() : async Text { - var accum = ""; - accum #= "██"; - accum #= " "; - accum #= "\n"; - accum #= " "; - accum #= "██"; - accum #= "\n"; + let accum = "██ ██\n"; Prim.debugPrint accum; accum }; From 7ce3acc0a0ab9c46a12f1306fec93d2d142ad782 Mon Sep 17 00:00:00 2001 From: Jude Taylor Date: Tue, 18 Feb 2020 11:19:08 -0800 Subject: [PATCH 1037/1176] update common (#1217) --- nix/sources.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/sources.json b/nix/sources.json index 68a25931c28..9f917ef7ea5 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -2,7 +2,7 @@ "common": { "ref": "master", "repo": "ssh://git@github.com/dfinity-lab/common", - "rev": "7cf0a0864bf0670a7cad441067af0178fe51d506", + "rev": "7278afe2b6ddcd0c78c82fae38160bc4583fc1a6", "type": "git" }, "dfinity": { From 3f9bb991dc8034bcde5b54925b767aa182946f44 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 18 Feb 2020 14:45:54 -0800 Subject: [PATCH 1038/1176] Backend: Implement eq on `Principal` (#1206) fixing an omission from https://github.com/dfinity-lab/motoko/pull/1128 this was reported by @stanleygjones in https://dfinity.slack.com/archives/CGA566TPV/p1581702931005500 --- src/codegen/compile.ml | 18 +++++++------- test/run/ok/numeric-ops.comp.ok | 40 +++++++++++++++--------------- test/run/ok/relational-ops.comp.ok | 24 +++++++++--------- test/run/principal.mo | 3 +++ 4 files changed, 44 insertions(+), 41 deletions(-) create mode 100644 test/run/principal.mo diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index cb6429e3bfb..95f96810be1 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -1120,7 +1120,7 @@ module Tagged = struct | Blob -> begin match normalize ty with | (Con _ | Any) -> true - | (Prim Text) -> true + | (Prim (Text|Blob|Principal)) -> true | (Prim _ | Obj _ | Array _ | Tup _ | Opt _ | Variant _ | Func _ | Non) -> false | (Pre | Async _ | Mut _ | Var _ | Typ _) -> assert false end @@ -3397,7 +3397,7 @@ module Serialization = struct let rec add_typ t = match t with | Non -> assert false - | Prim Blob | Prim Principal -> + | Prim (Blob|Principal) -> add_typ Type.(Array (Prim Word8)) | Prim _ -> assert false | Tup ts -> @@ -3519,7 +3519,7 @@ module Serialization = struct get_x ^^ get_i ^^ Arr.idx env ^^ load_ptr ^^ size env t ) - | Prim Blob | Prim Principal -> + | Prim (Blob|Principal) -> let (set_len, get_len) = new_local env "len" in get_x ^^ Heap.load_field Blob.len_field ^^ set_len ^^ size_word env get_len ^^ @@ -3676,7 +3676,7 @@ module Serialization = struct ) ( List.mapi (fun i (_h, f) -> (i,f)) (sort_by_hash vs) ) ( E.trap_with env "serialize_go: unexpected variant" ) - | Prim (Blob | Principal) -> + | Prim (Blob|Principal) -> let (set_len, get_len) = new_local env "len" in get_x ^^ Heap.load_field Blob.len_field ^^ set_len ^^ write_word get_len ^^ @@ -3873,7 +3873,7 @@ module Serialization = struct (* Any vanilla value works here *) Opt.null - | Prim Blob -> + | Prim (Blob|Principal) -> assert_blob_typ env ^^ read_blob () | Prim Text -> @@ -4359,8 +4359,8 @@ module StackRep = struct | Prim (Nat64 | Int64 | Word64) -> UnboxedWord64 | Prim (Nat32 | Int32 | Word32) -> UnboxedWord32 | Prim (Nat8 | Nat16 | Int8 | Int16 | Word8 | Word16 | Char) -> Vanilla - | Prim (Text | Blob) -> Vanilla - | p -> todo "of_type" (Arrange_ir.typ p) Vanilla + | Prim (Text | Blob | Principal) -> Vanilla + | p -> todo "StackRep.of_type" (Arrange_ir.typ p) Vanilla let to_block_type env = function | Vanilla -> [I32Type] @@ -5801,7 +5801,7 @@ let compile_binop env t op = let compile_eq env = function | Type.(Prim Text) -> Text.compare env Operator.EqOp - | Type.(Prim Blob) -> Blob.compare env Operator.EqOp + | Type.(Prim (Blob|Principal)) -> Blob.compare env Operator.EqOp | Type.(Prim Bool) -> G.i (Compare (Wasm.Values.I32 I32Op.Eq)) | Type.(Prim (Nat | Int)) -> BigNum.compile_eq env | Type.(Prim (Int64 | Nat64 | Word64)) -> G.i (Compare (Wasm.Values.I64 I64Op.Eq)) @@ -5834,7 +5834,7 @@ let compile_relop env t op = let open Operator in match t, op with | Type.(Prim Text), _ -> Text.compare env op - | Type.(Prim Blob), _ -> Blob.compare env op + | Type.(Prim (Blob|Principal)), _ -> Blob.compare env op | _, EqOp -> compile_eq env t | _, NeqOp -> compile_eq env t ^^ G.i (Test (Wasm.Values.I32 I32Op.Eqz)) diff --git a/test/run/ok/numeric-ops.comp.ok b/test/run/ok/numeric-ops.comp.ok index 542e3add28a..f67e889e82d 100644 --- a/test/run/ok/numeric-ops.comp.ok +++ b/test/run/ok/numeric-ops.comp.ok @@ -1,32 +1,32 @@ compile_unop: NegOp compile_unop: NegOp compile_binop: AddOp -of_type: Float -of_type: Float +StackRep.of_type: Float +StackRep.of_type: Float compile_binop: AddOp -of_type: Float -of_type: Float +StackRep.of_type: Float +StackRep.of_type: Float compile_binop: SubOp -of_type: Float -of_type: Float +StackRep.of_type: Float +StackRep.of_type: Float compile_binop: SubOp -of_type: Float -of_type: Float +StackRep.of_type: Float +StackRep.of_type: Float compile_binop: MulOp -of_type: Float -of_type: Float +StackRep.of_type: Float +StackRep.of_type: Float compile_binop: MulOp -of_type: Float -of_type: Float +StackRep.of_type: Float +StackRep.of_type: Float compile_binop: DivOp -of_type: Float -of_type: Float +StackRep.of_type: Float +StackRep.of_type: Float compile_binop: DivOp -of_type: Float -of_type: Float +StackRep.of_type: Float +StackRep.of_type: Float compile_binop: PowOp -of_type: Float -of_type: Float +StackRep.of_type: Float +StackRep.of_type: Float compile_binop: PowOp -of_type: Float -of_type: Float +StackRep.of_type: Float +StackRep.of_type: Float diff --git a/test/run/ok/relational-ops.comp.ok b/test/run/ok/relational-ops.comp.ok index 5fd57559c6d..b39f05dc93b 100644 --- a/test/run/ok/relational-ops.comp.ok +++ b/test/run/ok/relational-ops.comp.ok @@ -1,24 +1,24 @@ compile_eq: EqOp -of_type: Float +StackRep.of_type: Float compile_eq: EqOp -of_type: Float +StackRep.of_type: Float compile_eq: EqOp -of_type: Float +StackRep.of_type: Float compile_eq: EqOp -of_type: Float +StackRep.of_type: Float compile_relop: LtOp -of_type: Float +StackRep.of_type: Float compile_relop: LtOp -of_type: Float +StackRep.of_type: Float compile_relop: LeOp -of_type: Float +StackRep.of_type: Float compile_relop: LeOp -of_type: Float +StackRep.of_type: Float compile_relop: GtOp -of_type: Float +StackRep.of_type: Float compile_relop: GtOp -of_type: Float +StackRep.of_type: Float compile_relop: GeOp -of_type: Float +StackRep.of_type: Float compile_relop: GeOp -of_type: Float +StackRep.of_type: Float diff --git a/test/run/principal.mo b/test/run/principal.mo new file mode 100644 index 00000000000..a8dfebe762a --- /dev/null +++ b/test/run/principal.mo @@ -0,0 +1,3 @@ +func isEq(x : Principal, y : Principal) : Bool { x == y }; + + From 9558500985ded5837972358b9c403250202a8494 Mon Sep 17 00:00:00 2001 From: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> Date: Wed, 19 Feb 2020 13:16:06 +0100 Subject: [PATCH 1039/1176] Scans the passed package paths for .mo files (#1210) * Scans the passed package paths for .mo files This way we can suggest imports for modules from packages even if they aren't a transitive dependency of an entry point yet. * log errors when trying to build the package env * merge fixes * Passes the project root as an argument in more places So we don't have to perform side effects in various places --- src/languageServer/completion.ml | 4 +- src/languageServer/debug.ml | 4 +- src/languageServer/declaration_index.ml | 87 +++++++++++++++++------- src/languageServer/declaration_index.mli | 18 ++++- src/languageServer/definition.ml | 4 +- src/languageServer/hover.ml | 4 +- src/languageServer/languageServer.ml | 13 ++-- src/pipeline/pipeline.ml | 4 +- 8 files changed, 93 insertions(+), 45 deletions(-) diff --git a/src/languageServer/completion.ml b/src/languageServer/completion.ml index bc97f0b4e11..d5acaefed17 100644 --- a/src/languageServer/completion.ml +++ b/src/languageServer/completion.ml @@ -138,7 +138,7 @@ let completions index logger project_root file_path file_contents line column = let toplevel_decls = let current_module_decls = current_uri_opt - |> opt_bind (fun uri -> DI.lookup_module (Filename.remove_extension uri) index) + |> opt_bind (fun uri -> DI.lookup_module project_root (Filename.remove_extension uri) index) |> Option.fold ~none:[] ~some:snd in current_module_decls in @@ -171,7 +171,7 @@ let completions index logger project_root file_path file_contents line column = |> List.find_opt (fun (mn, _) -> String.equal mn alias) in match module_path with | Some mp -> - (match DI.lookup_module (snd mp) index with + (match DI.lookup_module project_root (snd mp) index with | Some (_, decls) -> decls |> List.filter (has_prefix prefix) diff --git a/src/languageServer/debug.ml b/src/languageServer/debug.ml index d3f9979252e..ea4344ccd51 100644 --- a/src/languageServer/debug.ml +++ b/src/languageServer/debug.ml @@ -1,2 +1,2 @@ -let logger : (string -> unit) ref = ref ignore -let log : string -> unit = fun msg -> !logger msg +let logger : (string -> string -> unit) ref = ref (fun _ _ -> ()) +let log : string -> string -> unit = fun msg -> !logger msg diff --git a/src/languageServer/declaration_index.ml b/src/languageServer/declaration_index.ml index d275fabfc8f..8fd13707622 100644 --- a/src/languageServer/declaration_index.ml +++ b/src/languageServer/declaration_index.ml @@ -66,11 +66,12 @@ let add_module : string -> ide_decl list -> declaration_index -> declaration_ind fun path decls ix -> { ix with modules = Index.add path decls ix.modules} let lookup_module + (project_root : string) (path : string) (index : t) : (string * ide_decl list) option = let open Pipeline.URL in - let make_absolute = Lib.FilePath.make_absolute (Sys.getcwd ()) in + let make_absolute = Lib.FilePath.make_absolute project_root in match parse path with | Ok (Relative path) -> let path = @@ -145,7 +146,7 @@ let find_with_prefix (import_path, List.filter (decl_has_prefix prefix) ds)) |> List.filter (fun (_, ds) -> not (ds = [])) -let empty : unit -> t = fun _ -> +let empty : string -> t = fun cwd -> let open Pipeline.ResolveImport in let resolved_flags = Diag.run @@ -156,7 +157,7 @@ let empty : unit -> t = fun _ -> }) in { modules = Index.empty; actors = Index.empty; - package_map = resolved_flags.packages + package_map = Flags.M.map (Lib.FilePath.make_absolute cwd) resolved_flags.packages } module PatternMap = Map.Make(String) @@ -214,6 +215,7 @@ let unwrap_module_ast (lib : Syntax.lib): Syntax.exp_field list option = let populate_definitions + (project_root : string) (libs : Syntax.lib list) (path : string) (decls : ide_decl list) @@ -254,37 +256,72 @@ let populate_definitions TypeDecl { typ with definition = type_definition } in let opt_lib = List.find_opt - (fun lib -> String.equal path (Lib.FilePath.make_absolute (Sys.getcwd ()) lib.note)) + (fun lib -> String.equal path (Lib.FilePath.make_absolute project_root lib.note)) libs in match opt_lib with | None -> decls | Some lib -> List.map (find_def lib) decls -let make_index_inner logger vfs entry_points : t Diag.result = +let list_files_recursively dir = + let rec loop result = function + | f::fs when Sys.is_directory f -> + Sys.readdir f + |> Array.to_list + |> List.map (Filename.concat f) + |> List.append fs + |> loop result + | f::fs -> loop (f::result) fs + | [] -> result in + loop [] [dir] + +let scan_packages : unit -> string list = + fun _ -> + let scan_package path = + list_files_recursively path + |> List.filter (fun f -> Filename.extension f = ".mo") in + Flags.M.fold (fun _ v acc -> scan_package v @ acc) !Flags.package_urls [] + +let index_from_scope : string -> t -> Syntax.lib list -> Scope.t -> t = + fun project_root initial_index libs scope -> + Type.Env.fold + (fun path ty acc -> + let path = + if path = "@prim" then + path + else + Lib.FilePath.make_absolute project_root path in + add_module + path + (ty + |> read_single_module_lib + |> Fun.flip Lib.Option.get [] + |> populate_definitions project_root libs path) + acc) + scope.Scope.lib_env + initial_index + +let make_index_inner logger project_root vfs entry_points : t Diag.result = + let package_paths = List.map (fun f -> LibPath f @@ Source.no_region) (scan_packages ()) in + let package_env = Pipeline.chase_imports (Vfs.parse_file vfs) Pipeline.initial_stat_env package_paths in + let lib_index = match package_env with + | Result.Error errs -> begin + List.iter (fun err -> + logger "lib_index_errors" (Diag.string_of_message err)) errs; + empty project_root + end + | Result.Ok ((libs, scope), _) -> + index_from_scope project_root (empty project_root) libs scope in + (* TODO(Christoph): We should be able to return at least the + lib_index even if compiling from the entry points fails *) Pipeline.load_progs (Vfs.parse_file vfs) entry_points Pipeline.initial_stat_env - |> Diag.map (fun (libs, _, scope) -> - Type.Env.fold - (fun path ty acc -> - let path = - if path = "@prim" then - path - else - Lib.FilePath.make_absolute (Sys.getcwd ()) path in - add_module - path - (ty - |> read_single_module_lib - |> Fun.flip Lib.Option.get [] - |> populate_definitions libs path) - acc) - scope.Scope.lib_env - (empty ())) + |> Diag.map (fun (libs, _, scope) -> index_from_scope project_root lib_index libs scope) + -let make_index logger vfs entry_points : t Diag.result = +let make_index logger project_root vfs entry_points : t Diag.result = (* TODO(Christoph): Actually handle errors here *) - try make_index_inner logger vfs entry_points - with _ -> Diag.return (empty ()) + try make_index_inner logger project_root vfs entry_points + with _ -> Diag.return (empty project_root) diff --git a/src/languageServer/declaration_index.mli b/src/languageServer/declaration_index.mli index 00965277192..038003eb05b 100644 --- a/src/languageServer/declaration_index.mli +++ b/src/languageServer/declaration_index.mli @@ -2,7 +2,7 @@ open Source open Mo_types type t -val empty : unit -> t +val empty : string -> t val string_of_index : t -> string type value_decl = { @@ -33,7 +33,11 @@ val shorten_import_path (** The path to be shortened *) -> string -val lookup_module : string -> t -> (string * ide_decl list) option +val lookup_module + : string + -> string + -> t + -> (string * ide_decl list) option val find_with_prefix : string @@ -44,4 +48,12 @@ val find_with_prefix (** The declaration index *) -> (string * ide_decl list) list -val make_index : (string -> string -> unit) -> Vfs.t -> string list -> t Diag.result +val make_index + : (string -> string -> unit) + (** A logger *) + -> string + (** The project root *) + -> Vfs.t + -> string list + (** The entry points *) + -> t Diag.result diff --git a/src/languageServer/definition.ml b/src/languageServer/definition.ml index 717d5f7b4c5..9961c9d1cfb 100644 --- a/src/languageServer/definition.ml +++ b/src/languageServer/definition.ml @@ -50,12 +50,12 @@ let definition_handler | Alias _ -> None | Unresolved _ -> None | Resolved resolved -> - DI.lookup_module resolved.path index + DI.lookup_module project_root resolved.path index |> opt_bind (find_named resolved.ident) | Ident ident -> Lib.FilePath.relative_to project_root file_path |> opt_bind (fun uri -> - DI.lookup_module uri index + DI.lookup_module project_root uri index |> opt_bind (find_named ident) )) in let location = diff --git a/src/languageServer/hover.ml b/src/languageServer/hover.ml index 8723fa034c7..811f90d061c 100644 --- a/src/languageServer/hover.ml +++ b/src/languageServer/hover.ml @@ -25,7 +25,7 @@ let hover_handler let toplevel_decls = let current_module_decls = current_uri_opt - |> Fun.flip Option.bind (fun uri -> lookup_module uri index) + |> Fun.flip Option.bind (fun uri -> lookup_module project_root uri index) |> Option.fold ~none:[] ~some:snd in current_module_decls in let mk_hover_result ide_decl = @@ -41,7 +41,7 @@ let hover_handler | Source_file.Alias (_, path) -> Some Lsp.{ hover_result_contents = markup_content path } | Source_file.Resolved resolved -> - lookup_module resolved.Source_file.path index + lookup_module project_root resolved.Source_file.path index |> Fun.flip Option.bind (fun (_, decls) -> List.find_opt (fun d -> name_of_ide_decl d = resolved.Source_file.ident) diff --git a/src/languageServer/languageServer.ml b/src/languageServer/languageServer.ml index 218183543bf..d2ee1318e65 100644 --- a/src/languageServer/languageServer.ml +++ b/src/languageServer/languageServer.ml @@ -99,7 +99,7 @@ let start entry_point debug = let _ = Flags.M.iter (fun k v -> log_to_file "package" (Printf.sprintf "%s => %s" k v)) !Flags.package_urls in - let _ = Debug.logger := log_to_file "debug" in + let _ = Debug.logger := log_to_file in let publish_diagnostics = Channel.publish_diagnostics oc in let clear_diagnostics = Channel.clear_diagnostics oc in let send_response = Channel.send_response oc in @@ -110,14 +110,13 @@ let start entry_point debug = let _ = log_to_file "project_root" project_root in let startup_diags = ref [] in let files_with_diags = ref [] in - let vfs = ref Vfs.empty in let decl_index = - let ix = match Declaration_index.make_index log_to_file !vfs [entry_point] with + let ix = match Declaration_index.make_index log_to_file project_root !vfs [entry_point] with | Error errs -> - List.iter (fun e -> log_to_file "Error" (Diag.string_of_message e)) errs; - startup_diags := errs; - Declaration_index.empty () + List.iter (fun err -> log_to_file "Error" (Diag.string_of_message err)) errs; + startup_diags := errs; + Declaration_index.empty project_root | Ok((ix, _)) -> ix in ref ix in @@ -238,7 +237,7 @@ let start entry_point debug = | (_, `TextDocumentDidClose params) -> vfs := Vfs.close_file params !vfs | (_, `TextDocumentDidSave _) -> - let msgs = match Declaration_index.make_index log_to_file !vfs [entry_point] with + let msgs = match Declaration_index.make_index log_to_file project_root !vfs [entry_point] with | Error msgs' -> List.iter (fun msg -> log_to_file "rebuild_error" (Diag.string_of_message msg)) msgs'; msgs' | Ok((ix, msgs')) -> decl_index := ix; diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index 0cc557cb49a..95eb52926c0 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -403,7 +403,7 @@ let interpret_files (senv0, denv0) files : (Scope.scope * Interpret.scope) optio | None -> None | Some denv2 -> Some (senv1, denv2) ) - + let run_prelude () : dyn_env = match interpret_prog Interpret.empty_scope prelude with @@ -428,7 +428,7 @@ let check_files files : check_result = let check_string s name : check_result = Diag.map ignore (load_decl (parse_string name s) initial_stat_env) - + (* Generate IDL *) let generate_idl files : Idllib.Syntax.prog Diag.result = From 0d827fe7f7e3b05364257d4ce10ec36fa6dd40f0 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 19 Feb 2020 18:05:47 +0000 Subject: [PATCH 1040/1176] Improve error messages for scoped awaits (#1221) * rename top_cap * basic scope reporting * add diag.Info and use to report scope information * update test * update test output * refactor to avoid nested side-effect and give scope info after error * abbreviate regions to basename if any --- src/js/mo_js.ml | 2 +- src/lang_utils/diag.ml | 7 +- src/lang_utils/diag.mli | 2 +- src/languageServer/languageServer.ml | 1 + src/mo_frontend/typing.ml | 98 +++++++++++++++++++++++----- src/mo_types/async_cap.ml | 2 +- test/fail/bad-async.mo | 9 +++ test/fail/ok/bad-async.tc.ok | 8 +++ test/fail/ok/bad-async.tc.ret.ok | 1 + test/fail/ok/illegal-await.tc.ok | 45 +++++++++++-- test/repl/ok/type-lub-repl.stdout.ok | 2 +- 11 files changed, 147 insertions(+), 30 deletions(-) create mode 100644 test/fail/bad-async.mo create mode 100644 test/fail/ok/bad-async.tc.ok create mode 100644 test/fail/ok/bad-async.tc.ret.ok diff --git a/src/js/mo_js.ml b/src/js/mo_js.ml index d6a300658b9..cc136ef0a4c 100644 --- a/src/js/mo_js.ml +++ b/src/js/mo_js.ml @@ -20,7 +20,7 @@ let range_of_region at = let diagnostics_of_msg (msg : Diag.message) = Diag.(object%js val source = Js.string "motoko" - val severity = match msg.sev with Diag.Error -> 1 | Diag.Warning -> 2 + val severity = match msg.sev with Diag.Error -> 1 | (Diag.Warning | Diag.Info) -> 2 val range = range_of_region msg.at val message = Js.string msg.text end) diff --git a/src/lang_utils/diag.ml b/src/lang_utils/diag.ml index a8f23a5e433..76673ef3a67 100644 --- a/src/lang_utils/diag.ml +++ b/src/lang_utils/diag.ml @@ -1,6 +1,6 @@ open Mo_config -type severity = Warning | Error +type severity = Warning | Error | Info type message = { sev : severity; at : Source.region; @@ -50,11 +50,12 @@ let fatal_error at text = { sev = Error; at; cat = "fatal"; text } let string_of_message msg = let label = match msg.sev with | Error -> Printf.sprintf "%s error" msg.cat - | Warning -> "warning" in + | Warning -> "warning" + | Info -> "info" in Printf.sprintf "%s: %s, %s\n" (Source.string_of_region msg.at) label msg.text let print_message msg = - if msg.sev = Warning && not !Flags.print_warnings + if msg.sev <> Error && not !Flags.print_warnings then () else Printf.eprintf "%s%!" (string_of_message msg) diff --git a/src/lang_utils/diag.mli b/src/lang_utils/diag.mli index 4018670a02f..fd8d6624708 100644 --- a/src/lang_utils/diag.mli +++ b/src/lang_utils/diag.mli @@ -1,6 +1,6 @@ (* A common data type for diagnostic messages *) -type severity = Warning | Error +type severity = Warning | Error | Info type message = { sev : severity; diff --git a/src/languageServer/languageServer.ml b/src/languageServer/languageServer.ml index d2ee1318e65..2a78b8b946f 100644 --- a/src/languageServer/languageServer.ml +++ b/src/languageServer/languageServer.ml @@ -78,6 +78,7 @@ let range_of_region (at : Source.region) : Lsp_t.range = Lsp_t. let severity_of_sev : Diag.severity -> Lsp.DiagnosticSeverity.t = function | Diag.Error -> Lsp.DiagnosticSeverity.Error | Diag.Warning -> Lsp.DiagnosticSeverity.Warning + | Diag.Info -> Lsp.DiagnosticSeverity.Information let diagnostics_of_message (msg : Diag.message) : (Lsp_t.diagnostic * string) = (Lsp_t. { diagnostic_range = range_of_region msg.Diag.at; diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 698a36a869c..e4639935c34 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -36,6 +36,7 @@ type env = context : exp' list; pre : bool; msgs : Diag.msg_store; + scopes : Source.region T.ConEnv.t; } let env_of_scope msgs scope = @@ -52,6 +53,7 @@ let env_of_scope msgs scope = context = []; pre = false; msgs; + scopes = T.ConEnv.empty; } @@ -65,9 +67,14 @@ let recover f y = recover_with () f y let type_error at text : Diag.message = Diag.{sev = Diag.Error; at; cat = "type"; text} + let type_warning at text : Diag.message = Diag.{sev = Diag.Warning; at; cat = "type"; text} +let type_info at text : Diag.message = + Diag.{sev = Diag.Info; at; cat = "type"; text} + + let error env at fmt = Printf.ksprintf (fun s -> Diag.add_msg env.msgs (type_error at s); raise Recover) fmt @@ -78,6 +85,9 @@ let local_error env at fmt = let warn env at fmt = Printf.ksprintf (fun s -> Diag.add_msg env.msgs (type_warning at s)) fmt +let info env at fmt = + Printf.ksprintf (fun s -> Diag.add_msg env.msgs (type_info at s)) fmt + let flag_of_compile_mode mode = match mode with | Flags.ICMode -> "" @@ -238,13 +248,45 @@ let check_shared_return env at sort c ts = | T.Shared T.Query, _, _ -> error env at "shared query function must have syntactic return type `async `" | _ -> () -let rec infer_async_cap env sort cs tbs = +let region_of_scope env typ = + match T.normalize typ with + | T.Con(c,_) -> + T.ConEnv.find_opt c env.scopes + | _ -> None + +let string_of_region r = + let open Source in + let { left; right } = r in + let basename = if left.file = "" then "" else Filename.basename left.file in + Source.string_of_region + { left = { left with file = basename }; + right = { right with file = basename } } + +let associated_region env typ at = + match region_of_scope env typ with + | Some r -> + Printf.sprintf "\n scope %s is %s" (T.string_of_typ_expand typ) (string_of_region r); + | None -> + if T.eq typ (T.Con(C.top_cap,[])) then + Printf.sprintf "\n scope %s is the global scope" (T.string_of_typ_expand typ) + else "" + +let scope_info env typ at = + match region_of_scope env typ with + | Some r -> + info env r "this is scope %s mentioned in error at %s" + (T.string_of_typ_expand typ) (string_of_region at) + | None -> () + +let rec infer_async_cap env sort cs tbs at = match sort, cs, tbs with | (T.Shared T.Write | T.Local) , c::_, { T.sort = T.Scope; _ }::_ -> { env with typs = T.Env.add T.default_scope_var c env.typs; + scopes = T.ConEnv.add c at env.scopes; async = C.AsyncCap c } | (T.Shared T.Query) , c::_, { T.sort = T.Scope; _ }::_ -> { env with typs = T.Env.add T.default_scope_var c env.typs; + scopes = T.ConEnv.add c at env.scopes; async = C.QueryCap c } | T.Shared _, _, _ -> assert false (* impossible given sugaring *) | _ -> { env with async = C.NullCap } @@ -302,7 +344,7 @@ and check_typ' env typ : T.typ = T.Tup (List.map (check_typ env) typs) | FuncT (sort, binds, typ1, typ2) -> let cs, tbs, te, ce = check_typ_binds env binds in - let env' = infer_async_cap (adjoin_typs env te ce) sort.it cs tbs in + let env' = infer_async_cap (adjoin_typs env te ce) sort.it cs tbs typ.at in let typs1 = as_domT typ1 in let c, typs2 = as_codomT sort.it typ2 in let ts1 = List.map (check_typ env') typs1 in @@ -771,9 +813,9 @@ and infer_exp'' env exp : T.typ = "expected array type, but expression produces type\n %s" (T.string_of_typ_expand t1) ) - | FuncE (_, sort_pat, typ_binds, pat, typ_opt, _sugar, exp) -> + | FuncE (_, sort_pat, typ_binds, pat, typ_opt, _sugar, exp1) -> if not env.pre && not in_actor && T.is_shared_sort sort_pat.it then - error_in [Flags.ICMode; Flags.StubMode] env exp.at "a shared function is only allowed as a public field of an actor"; + error_in [Flags.ICMode; Flags.StubMode] env exp1.at "a shared function is only allowed as a public field of an actor"; let typ = match typ_opt with | Some typ -> typ | None -> {it = TupT []; at = no_region; note = T.Pre} @@ -782,7 +824,7 @@ and infer_exp'' env exp : T.typ = let cs, tbs, te, ce = check_typ_binds env typ_binds in let c, ts2 = as_codomT sort typ in check_shared_return env typ.at sort c ts2; - let env' = infer_async_cap (adjoin_typs env te ce) sort cs tbs in + let env' = infer_async_cap (adjoin_typs env te ce) sort cs tbs exp.at in let t1, ve1 = infer_pat_exhaustive (if T.is_shared_sort sort then local_error else warn) env' pat in let ve2 = T.Env.adjoin ve ve1 in let ts2 = List.map (check_typ env') ts2 in @@ -794,7 +836,7 @@ and infer_exp'' env exp : T.typ = rets = Some codom; (* async = None; *) } in - check_exp (adjoin_vals env'' ve2) codom exp; + check_exp (adjoin_vals env'' ve2) codom exp1; if Type.is_shared_sort sort then begin if not (T.shared t1) then error_shared env t1 pat.at @@ -808,12 +850,12 @@ and infer_exp'' env exp : T.typ = ) ts2; match c, ts2 with | T.Returns, [] when sort = T.Shared T.Write -> - if not (is_IgnoreAsync exp) then - error env exp.at + if not (is_IgnoreAsync exp1) then + error env exp1.at "shared function with () result type has unexpected body:\n the body must either be of sugared form '{ ... }' \n or explicit form '= ignore ((async ...) : async ())'" | T.Promises, _ -> - if not (is_Async exp) then - error env exp.at + if not (is_Async exp1) then + error env exp1.at "shared function with async result type has non-async body" | _ -> error env typ.at "shared function has non-async result type\n %s" @@ -985,7 +1027,11 @@ and infer_exp'' env exp : T.typ = let c, tb, ce, cs = check_typ_bind env typ_bind in let ce_scope = T.Env.add T.default_scope_var c ce in (* pun scope var with c *) let env' = - {(adjoin_typs env ce_scope cs) with labs = T.Env.empty; rets = Some T.Pre; async = next_cap c} in + {(adjoin_typs env ce_scope cs) with + labs = T.Env.empty; + rets = Some T.Pre; + async = next_cap c; + scopes = T.ConEnv.add c exp.at env.scopes } in let t = infer_exp env' exp1 in let t' = T.open_ [t1] (T.close [c] t) in if not (T.shared t') then @@ -997,9 +1043,15 @@ and infer_exp'' env exp : T.typ = let t1 = infer_exp_promote env exp1 in (try let (t2, t3) = T.as_async_sub t0 t1 in - if not (T.eq t0 t2) then - error env exp.at "ill-scoped await: expected async type from current scope %s, found async type from other scope %s" - (T.string_of_typ_expand t0) (T.string_of_typ_expand t2); + if not (T.eq t0 t2) then begin + local_error env exp1.at "ill-scoped await: expected async type from current scope %s, found async type from other scope %s%s%s" + (T.string_of_typ_expand t0) + (T.string_of_typ_expand t2) + (associated_region env t0 exp.at) + (associated_region env t2 exp.at); + scope_info env t0 exp.at; + scope_info env t2 exp.at; + end; t3 with Invalid_argument _ -> error env exp1.at "expected async type, but expression has type\n %s" @@ -1062,14 +1114,24 @@ and check_exp' env0 t exp : T.typ = t | AsyncE (tb, exp1), T.Async (t1', t') -> let t1, next_cap = check_AsyncCap env "async expression" exp.at in - if not (T.eq t1 t1') then - error env exp.at "async at scope\n %s\ncannot produce expected scope\n %s" + if not (T.eq t1 t1') then begin + local_error env exp.at "async at scope\n %s\ncannot produce expected scope\n %s%s%s" (T.string_of_typ_expand t1) - (T.string_of_typ_expand t1'); + (T.string_of_typ_expand t1') + (associated_region env t1 exp.at) + (associated_region env t1' exp.at); + scope_info env t1 exp.at; + scope_info env t1' exp.at + end; let c, tb, ce, cs = check_typ_bind env tb in let ce_scope = T.Env.add T.default_scope_var c ce in (* pun scope var with c *) let env' = - {(adjoin_typs env ce_scope cs) with labs = T.Env.empty; rets = Some t'; async = next_cap c} in + {(adjoin_typs env ce_scope cs) with + labs = T.Env.empty; + rets = Some t'; + async = next_cap c; + scopes = T.ConEnv.add c exp.at env.scopes; + } in check_exp env' t' exp1; t | BlockE decs, _ -> diff --git a/src/mo_types/async_cap.ml b/src/mo_types/async_cap.ml index 0c10b48193b..bc009c84bb7 100644 --- a/src/mo_types/async_cap.ml +++ b/src/mo_types/async_cap.ml @@ -10,6 +10,6 @@ type async_cap = | AwaitCap of T.con (* can async, send, try, catch, await (i.e. in an async expression *) | NullCap (* none of the above *) -let top_cap = Con.fresh "@" (T.Def([],T.Any)) +let top_cap = Con.fresh "$top-level" (T.Def([],T.Any)) let initial_cap () = if !Flags.compiled then NullCap else AsyncCap top_cap diff --git a/test/fail/bad-async.mo b/test/fail/bad-async.mo new file mode 100644 index 00000000000..e7118695c25 --- /dev/null +++ b/test/fail/bad-async.mo @@ -0,0 +1,9 @@ +actor a { + public func getNat() : async Nat { 0 }; + var x : [async Nat] = []; + public func foo1() { x := [a.getNat()] }; + public func foo2() : async Nat { + 10 + + (await x[0]) + }; +}; \ No newline at end of file diff --git a/test/fail/ok/bad-async.tc.ok b/test/fail/ok/bad-async.tc.ok new file mode 100644 index 00000000000..1d931a4f6b9 --- /dev/null +++ b/test/fail/ok/bad-async.tc.ok @@ -0,0 +1,8 @@ +bad-async.mo:4.32-4.42: type error, expression of type + async<$foo1> Nat +cannot produce expected type + async<$top-level> Nat +bad-async.mo:7.17-7.21: type error, ill-scoped await: expected async type from current scope $foo2, found async type from other scope $top-level + scope $foo2 is bad-async.mo:5.36-8.10 + scope $top-level is the global scope +bad-async.mo:5.36-8.10: info, this is scope $foo2 mentioned in error at bad-async.mo:7.11-7.21 diff --git a/test/fail/ok/bad-async.tc.ret.ok b/test/fail/ok/bad-async.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/bad-async.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/ok/illegal-await.tc.ok b/test/fail/ok/illegal-await.tc.ok index 1d990be4a8f..7f768094297 100644 --- a/test/fail/ok/illegal-await.tc.ok +++ b/test/fail/ok/illegal-await.tc.ok @@ -1,5 +1,40 @@ -illegal-await.mo:3.30-3.37: type error, ill-scoped await: expected async type from current scope $anon-async-3.22, found async type from other scope @ -illegal-await.mo:12.32-12.40: type error, ill-scoped await: expected async type from current scope $anon-async-12.25, found async type from other scope $anon-async-11.10 -illegal-await.mo:13.32-13.40: type error, ill-scoped await: expected async type from current scope $anon-async-13.25, found async type from other scope $anon-async-11.10 -illegal-await.mo:24.7-24.14: type error, ill-scoped await: expected async type from current scope $anon-async-23.11, found async type from other scope $anon-async-21.10 -illegal-await.mo:33.5-33.12: type error, ill-scoped await: expected async type from current scope $Rec, found async type from other scope $ +illegal-await.mo:3.36-3.37: type error, ill-scoped await: expected async type from current scope $anon-async-3.22, found async type from other scope $top-level + scope $anon-async-3.22 is illegal-await.mo:3.22-3.38 + scope $top-level is the global scope +illegal-await.mo:3.22-3.38: info, this is scope $anon-async-3.22 mentioned in error at illegal-await.mo:3.30-3.37 +illegal-await.mo:12.38-12.40: type error, ill-scoped await: expected async type from current scope $anon-async-12.25, found async type from other scope $anon-async-11.10 + scope $anon-async-12.25 is illegal-await.mo:12.25-12.43 + scope $anon-async-11.10 is illegal-await.mo:11.10-14.4 +illegal-await.mo:12.25-12.43: info, this is scope $anon-async-12.25 mentioned in error at illegal-await.mo:12.32-12.40 +illegal-await.mo:11.10-14.4: info, this is scope $anon-async-11.10 mentioned in error at illegal-await.mo:12.32-12.40 +illegal-await.mo:13.38-13.40: type error, ill-scoped await: expected async type from current scope $anon-async-13.25, found async type from other scope $anon-async-11.10 + scope $anon-async-13.25 is illegal-await.mo:13.25-13.43 + scope $anon-async-11.10 is illegal-await.mo:11.10-14.4 +illegal-await.mo:13.25-13.43: info, this is scope $anon-async-13.25 mentioned in error at illegal-await.mo:13.32-13.40 +illegal-await.mo:11.10-14.4: info, this is scope $anon-async-11.10 mentioned in error at illegal-await.mo:13.32-13.40 +illegal-await.mo:11.16-14.4: type error, async type has non-shared content type + async<$top-level> () +type + async<$top-level> () +is or contains non-shared type + async<$top-level> () +illegal-await.mo:24.13-24.14: type error, ill-scoped await: expected async type from current scope $anon-async-23.11, found async type from other scope $anon-async-21.10 + scope $anon-async-23.11 is illegal-await.mo:23.11-25.6 + scope $anon-async-21.10 is illegal-await.mo:21.10-26.4 +illegal-await.mo:23.11-25.6: info, this is scope $anon-async-23.11 mentioned in error at illegal-await.mo:24.7-24.14 +illegal-await.mo:21.10-26.4: info, this is scope $anon-async-21.10 mentioned in error at illegal-await.mo:24.7-24.14 +illegal-await.mo:33.11-33.12: type error, ill-scoped await: expected async type from current scope $Rec, found async type from other scope $ + scope $Rec is illegal-await.mo:31.51-38.2 + scope $ is illegal-await.mo:31.1-38.2 +illegal-await.mo:31.51-38.2: info, this is scope $Rec mentioned in error at illegal-await.mo:33.5-33.12 +illegal-await.mo:31.1-38.2: info, this is scope $ mentioned in error at illegal-await.mo:33.5-33.12 +illegal-await.mo:36.20-36.21: type error, expression of type + async<$> () +cannot produce expected type + async<$Rec> () +illegal-await.mo:31.16-31.39: type error, shared function has non-shared parameter type + (Int, async<$> ()) +type + (Int, async<$> ()) +is or contains non-shared type + async<$> () diff --git a/test/repl/ok/type-lub-repl.stdout.ok b/test/repl/ok/type-lub-repl.stdout.ok index d7fa1c338e4..d43988727e7 100644 --- a/test/repl/ok/type-lub-repl.stdout.ok +++ b/test/repl/ok/type-lub-repl.stdout.ok @@ -28,5 +28,5 @@ Motoko 0.1 interpreter > 25 : Int > 42 : Int > func : (C, D) -> [C] -> [async (?4), async (?(-42))] : [(async<@> (?Int))] +> [async (?4), async (?(-42))] : [(async<$top-level> (?Int))] > From b90fbc518837eb98fc3cc2a6fe59804ed429a9f6 Mon Sep 17 00:00:00 2001 From: Bas van Dijk Date: Wed, 19 Feb 2020 21:15:01 +0100 Subject: [PATCH 1041/1176] nix/haskell-packages: replace IFD with importing generated files (#1220) * nix/haskell-packages: replace IFD with importing generated files Replace IFD calls to callCabal2nix with importing generated `default.nix` files. The generated `default.nix` files are stored in the repository and contain instructions on how to regenerate them. The generation of the `default.nix` files is done using the `haskellSrc2nixWithDoc` function which generates a directory containing a `default.nix` which is the result of running `cabal2nix` with the `extraCabal2nixOptions` on the provided `src`. A header is then added to the `default.nix` which contains instructions on how to regenerate that file. Finally the new jobs are added which check that the stored `default.nix` matches the expected `default.nix`. So whenever the `.cabal` files are updated and don't match the stored `default.nix` anymore CI will complain. --- Building.md | 20 ++++++++++++++++++++ default.nix | 19 +++++++++++++++++++ ic-stub/default.nix | 24 +++++++++++++++++++++++ ic-stub/generate.nix | 1 + nix/default.nix | 40 +++++++++++++++++++++++++++++++++++++++ nix/haskell-packages.nix | 8 ++++---- test/lsp-int/default.nix | 21 ++++++++++++++++++++ test/lsp-int/generate.nix | 1 + test/random/default.nix | 22 +++++++++++++++++++++ test/random/generate.nix | 1 + winter/default.nix | 38 +++++++++++++++++++++++++++++++++++++ winter/generate.nix | 15 +++++++++++++++ 12 files changed, 206 insertions(+), 4 deletions(-) create mode 100644 ic-stub/default.nix create mode 100644 ic-stub/generate.nix create mode 100644 test/lsp-int/default.nix create mode 100644 test/lsp-int/generate.nix create mode 100644 test/random/default.nix create mode 100644 test/random/generate.nix create mode 100644 winter/default.nix create mode 100644 winter/generate.nix diff --git a/Building.md b/Building.md index 64557955397..9a25949e897 100644 --- a/Building.md +++ b/Building.md @@ -78,3 +78,23 @@ https://github.com/ocaml/dune/issues/57 to see when a coverage report is viable _pass_ it the path to the binary.) +## Updating Haskell Packages + +When the `.cabal` file of a Haskell package is changed you need to make sure the +corresponding `default.nix` file (stored in the same directory as the `.cabal` +file) is kept in sync with it. + +As mentioned in the `default.nix` files, these files are automatically generated: + +``` +# THIS IS AN AUTOMATICALLY GENERATED FILE. DO NOT EDIT MANUALLY! +# To regenerate this file execute the following command in this directory: +# +# cp $(nix-build ./generate.nix --no-link)/default.nix ./default.nix +``` + +Note that they also contain the instructions on how to update them. + +Don't worry if you forget to update the `default.nix` file. There are CI jobs +(like [`haskellSrc2nix.lsp-int`](https://hydra.dfinity.systems/job/dfinity-ci-build/motoko/haskellSrc2nix.lsp-int) +that check if the files are in sync and fail with a diff if they aren't. diff --git a/default.nix b/default.nix index 9b1b5569ebf..b13fdd7ec45 100644 --- a/default.nix +++ b/default.nix @@ -411,6 +411,25 @@ rec { }; stdlib-adocs = stdlib-doc.adocs; + haskellSrc2nix = + let + check = dir: nixpkgs.runCommandNoCC "check-${builtins.baseNameOf dir}" { + preferLocalBuild = true; + allowSubstitutes = false; + nativeBuildInputs = [ nixpkgs.diffutils ]; + expected = import (dir + "/generate.nix") { pkgs = nixpkgs; }; + inherit dir; + } '' + diff -U 3 $expected/default.nix $dir/default.nix + touch $out + ''; + in { + lsp-int = check ./test/lsp-int; + qc-motoko = check ./test/random; + ic-stub = check ./ic-stub; + winter = check ./winter; + }; + all-systems-go = nixpkgs.releaseTools.aggregate { name = "all-systems-go"; constituents = [ diff --git a/ic-stub/default.nix b/ic-stub/default.nix new file mode 100644 index 00000000000..f9ab4998473 --- /dev/null +++ b/ic-stub/default.nix @@ -0,0 +1,24 @@ +# THIS IS AN AUTOMATICALLY GENERATED FILE. DO NOT EDIT MANUALLY! +# To regenerate this file execute the following command in this directory: +# +# cp $(nix-build ./generate.nix --no-link)/default.nix ./default.nix +{ mkDerivation, base, binary, bytestring, containers +, data-default-class, filepath, hex-text, mtl, optparse-applicative +, primitive, stdenv, text, transformers, utf8-string, vector +, winter +}: +mkDerivation { + pname = "ic-stub"; + version = "0.1.0.0"; + src = ./.; + isLibrary = false; + isExecutable = true; + executableHaskellDepends = [ + base binary bytestring containers data-default-class filepath + hex-text mtl optparse-applicative primitive text transformers + utf8-string vector winter + ]; + doCheck = false; + license = "unknown"; + hydraPlatforms = stdenv.lib.platforms.none; +} diff --git a/ic-stub/generate.nix b/ic-stub/generate.nix new file mode 100644 index 00000000000..cd9857ac4b4 --- /dev/null +++ b/ic-stub/generate.nix @@ -0,0 +1 @@ +{ pkgs ? import ../nix {} }: pkgs.localHaskellSrc2nixWithDoc "ic-stub" ./. "--no-check" diff --git a/nix/default.nix b/nix/default.nix index 41ee345fa4d..155eb3e5e95 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -25,6 +25,46 @@ let }; } ) + (self: super: { + # A variant of `haskellSrc2nixWithDoc` for local Haskell packages. + localHaskellSrc2nixWithDoc = name: path: extraCabal2nixOptions: + self.haskellSrc2nixWithDoc { + inherit name extraCabal2nixOptions; + src = import ./gitSource.nix path; + src_subst = "./."; + }; + + # `haskellSrc2nixWithDoc` is used to generate `default.nix` files for + # Haskell packages which are intended to be stored in the repository. + # + # The function generates a directory containing a `default.nix` which + # is the result of running `cabal2nix` with the `extraCabal2nixOptions` + # on the provided `src`. + # + # A header is added to `default.nix` which contains instructions on + # how to regenerate that file. + # + # Finally the `src` attribute in the `default.nix` will be defined as + # `src_subst` such that it can be pointed to local or niv-managed + # sources. + haskellSrc2nixWithDoc = {name, src, src_subst, extraCabal2nixOptions}: + let + drv = pkgs.haskellPackages.haskellSrc2nix { + inherit name extraCabal2nixOptions src; + }; + in drv.overrideAttrs (oldAttrs: { + message = '' + # THIS IS AN AUTOMATICALLY GENERATED FILE. DO NOT EDIT MANUALLY!\ + # To regenerate this file execute the following command in this directory:\ + #\ + # cp $(nix-build ./generate.nix --no-link)/default.nix ./default.nix + ''; + inherit src_subst; + installPhase = oldAttrs.installPhase + '' + sed -i "1i$message;s|src = .*|src = $src_subst;|" $out/default.nix + ''; + }); + }) ]; }; in diff --git a/nix/haskell-packages.nix b/nix/haskell-packages.nix index a578ba03910..caf1e4e8c70 100644 --- a/nix/haskell-packages.nix +++ b/nix/haskell-packages.nix @@ -9,11 +9,11 @@ nix: subpath: lsp-test = nix.haskell.lib.dontCheck self.lsp-test_0_10_1_0; - lsp-int = self.callCabal2nix "lsp-int" (subpath "test/lsp-int") { }; + lsp-int = super.callPackage ../test/lsp-int {}; - qc-motoko = self.callCabal2nix "qc-motoko" (subpath "test/random") { }; + qc-motoko = super.callPackage ../test/random {}; - winter = self.callCabal2nixWithOptions "winter" nix.sources.winter "--no-check" {}; + winter = super.callPackage ../winter {}; - ic-stub = self.callCabal2nixWithOptions "ic-stub" (subpath "ic-stub") "-frelease" { }; + ic-stub = super.callPackage ../ic-stub {}; } diff --git a/test/lsp-int/default.nix b/test/lsp-int/default.nix new file mode 100644 index 00000000000..91dadd8bcee --- /dev/null +++ b/test/lsp-int/default.nix @@ -0,0 +1,21 @@ +# THIS IS AN AUTOMATICALLY GENERATED FILE. DO NOT EDIT MANUALLY! +# To regenerate this file execute the following command in this directory: +# +# cp $(nix-build ./generate.nix --no-link)/default.nix ./default.nix +{ mkDerivation, base, data-default, directory, filepath +, haskell-lsp-types, hspec, HUnit, lens, lsp-test, stdenv, text +}: +mkDerivation { + pname = "lsp-int"; + version = "0"; + src = ./.; + isLibrary = false; + isExecutable = true; + executableHaskellDepends = [ + base data-default directory filepath haskell-lsp-types hspec HUnit + lens lsp-test text + ]; + description = "Integration tests for the language server"; + license = "unknown"; + hydraPlatforms = stdenv.lib.platforms.none; +} diff --git a/test/lsp-int/generate.nix b/test/lsp-int/generate.nix new file mode 100644 index 00000000000..00c504f0724 --- /dev/null +++ b/test/lsp-int/generate.nix @@ -0,0 +1 @@ +{ pkgs ? import ../../nix {} }: pkgs.localHaskellSrc2nixWithDoc "lsp-int" ./. "" diff --git a/test/random/default.nix b/test/random/default.nix new file mode 100644 index 00000000000..94cf7906662 --- /dev/null +++ b/test/random/default.nix @@ -0,0 +1,22 @@ +# THIS IS AN AUTOMATICALLY GENERATED FILE. DO NOT EDIT MANUALLY! +# To regenerate this file execute the following command in this directory: +# +# cp $(nix-build ./generate.nix --no-link)/default.nix ./default.nix +{ mkDerivation, base, exceptions, managed, process, QuickCheck +, quickcheck-text, quickcheck-unicode, stdenv, tasty +, tasty-quickcheck, text, turtle +}: +mkDerivation { + pname = "qc-motoko"; + version = "1"; + src = ./.; + isLibrary = false; + isExecutable = true; + executableHaskellDepends = [ + base exceptions managed process QuickCheck quickcheck-text + quickcheck-unicode tasty tasty-quickcheck text turtle + ]; + description = "generate randomised tests for Motoko"; + license = "unknown"; + hydraPlatforms = stdenv.lib.platforms.none; +} diff --git a/test/random/generate.nix b/test/random/generate.nix new file mode 100644 index 00000000000..cd9b234c170 --- /dev/null +++ b/test/random/generate.nix @@ -0,0 +1 @@ +{ pkgs ? import ../../nix {} }: pkgs.localHaskellSrc2nixWithDoc "qc-motoko" ./. "" diff --git a/winter/default.nix b/winter/default.nix new file mode 100644 index 00000000000..bbee9d168ac --- /dev/null +++ b/winter/default.nix @@ -0,0 +1,38 @@ +# THIS IS AN AUTOMATICALLY GENERATED FILE. DO NOT EDIT MANUALLY! +# To regenerate this file execute the following command in this directory: +# +# cp $(nix-build ./generate.nix --no-link)/default.nix ./default.nix +{ mkDerivation, pkgs, array, base, binary, byte-order, bytestring +, cmdargs, containers, data-default-class, data-fix, deepseq +, directory, filepath, FloatingHex, lifted-base, microlens-platform +, monad-control, mtl, nats, parsec, primitive, primitive-unaligned +, process, stdenv, tasty, tasty-hunit, tasty-quickcheck, temporary +, text, transformers, vector +}: +mkDerivation { + pname = "winter"; + version = "1.0.0"; + src = pkgs.sources.winter; + isLibrary = true; + isExecutable = true; + libraryHaskellDepends = [ + array base binary byte-order bytestring containers + data-default-class data-fix deepseq FloatingHex lifted-base + microlens-platform monad-control mtl nats parsec primitive + primitive-unaligned text transformers vector + ]; + executableHaskellDepends = [ + base binary bytestring cmdargs containers data-default-class mtl + parsec text + ]; + testHaskellDepends = [ + array base binary bytestring containers data-default-class data-fix + deepseq directory filepath FloatingHex lifted-base + microlens-platform monad-control mtl parsec primitive process tasty + tasty-hunit tasty-quickcheck temporary text transformers vector + ]; + doCheck = false; + homepage = "https://github.com/dfinity/winter"; + description = "Haskell port of the WebAssembly OCaml reference interpreter"; + license = stdenv.lib.licenses.mit; +} diff --git a/winter/generate.nix b/winter/generate.nix new file mode 100644 index 00000000000..7c26f492245 --- /dev/null +++ b/winter/generate.nix @@ -0,0 +1,15 @@ +{ pkgs ? import ../nix {} }: +let + drv = pkgs.haskellSrc2nixWithDoc { + name = "winter"; + src = pkgs.sources.winter; + src_subst = "pkgs.sources.winter"; + extraCabal2nixOptions = "--no-check"; + }; +in +drv.overrideAttrs (oldAttrs: { + installPhase = oldAttrs.installPhase + '' + # Accept `pkgs` as an argument because the `src` depends on it. + sed -i "s|{ mkDerivation|{ mkDerivation, pkgs|" $out/default.nix + ''; +}) From 6245825a13e5d802f10c7ae500b22ef18b4d7aa2 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 19 Feb 2020 17:19:43 -0800 Subject: [PATCH 1042/1176] Test case: Bad error message with variant short-hand form (#1219) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ``` func (#variant : { #variant : Nat }) = () ``` produces ``` type error, tuple pattern cannot consume expected type ``` even though there is no tuple pattern around. (Typical problem when desugaring in the parser, before the type checker runs…) Co-authored-by: Claudio Russo --- test/fail/ok/variant-pat-missing.tc.ok | 2 ++ test/fail/ok/variant-pat-missing.tc.ret.ok | 1 + test/fail/variant-pat-missing.mo | 1 + 3 files changed, 4 insertions(+) create mode 100644 test/fail/ok/variant-pat-missing.tc.ok create mode 100644 test/fail/ok/variant-pat-missing.tc.ret.ok create mode 100644 test/fail/variant-pat-missing.mo diff --git a/test/fail/ok/variant-pat-missing.tc.ok b/test/fail/ok/variant-pat-missing.tc.ok new file mode 100644 index 00000000000..49cde8755cf --- /dev/null +++ b/test/fail/ok/variant-pat-missing.tc.ok @@ -0,0 +1,2 @@ +variant-pat-missing.mo:1.7-1.15: type error, tuple pattern cannot consume expected type + Nat diff --git a/test/fail/ok/variant-pat-missing.tc.ret.ok b/test/fail/ok/variant-pat-missing.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/variant-pat-missing.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/variant-pat-missing.mo b/test/fail/variant-pat-missing.mo new file mode 100644 index 00000000000..384ce32abd2 --- /dev/null +++ b/test/fail/variant-pat-missing.mo @@ -0,0 +1 @@ +func (#variant : { #variant : Nat }) = () From d4abbae1f2d036a71acff52126262028a25e3274 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 19 Feb 2020 23:13:58 -0800 Subject: [PATCH 1043/1176] Test runner: Check if `drun` and `ic-stub-run` are installed (#1216) if they are not, warn, but do not try to run the tests, and do not allow accepting tests. This means that people who do not have access to `dfinity` can run some tests (including a public CI like Github Actions). It also means that `make accept` will not commit `could not find ic-stub-run` as the expected output, as has happened to us a few times before. --- test/run.sh | 65 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 55 insertions(+), 10 deletions(-) diff --git a/test/run.sh b/test/run.sh index 61444d05c12..f35c7f234e4 100755 --- a/test/run.sh +++ b/test/run.sh @@ -21,7 +21,7 @@ function realpath() { ACCEPT=no -DRUN=no +DTESTS=no IDL=no PERF=no MOC=${MOC:-$(realpath $(dirname $0)/../src/moc)} @@ -30,6 +30,7 @@ DIDC=${DIDC:-$(realpath $(dirname $0)/../src/didc)} export MO_LD WASMTIME=${WASMTIME:-wasmtime} WASMTIME_OPTIONS="--disable-cache --cranelift" +DRUN=${DRUN:-drun} DRUN_WRAPPER=$(realpath $(dirname $0)/drun-wrapper.sh) IC_STUB_RUN_WRAPPER=$(realpath $(dirname $0)/ic-stub-run-wrapper.sh) IC_STUB_RUN=${IC_STUB_RUN:-ic-stub-run} @@ -43,7 +44,7 @@ while getopts "adpstir" o; do ACCEPT=yes ;; d) - DRUN=yes + DTESTS=yes ;; p) PERF=yes @@ -147,6 +148,44 @@ then fi fi +HAVE_DRUN=no +HAVE_IC_STUB_RUN=no + +if [ $DTESTS = yes -o $PERF = yes ] +then + if $DRUN --version >& /dev/null + then + HAVE_DRUN=yes + else + if [ $ACCEPT = yes ] + then + echo "ERROR: Could not run $DRUN, cannot update expected test output" + exit 1 + else + echo "WARNING: Could not run $DRUN, will skip some tests" + HAVE_DRUN=no + fi + fi +fi + +if [ $DTESTS = yes -o $PERF = yes ] +then + if $IC_STUB_RUN --help >& /dev/null + then + HAVE_IC_STUB_RUN=yes + else + if [ $ACCEPT = yes ] + then + echo "ERROR: Could not run $IC_STUB_RUN, cannot update expected test output" + exit 1 + else + echo "WARNING: Could not run $IC_STUB_RUN, will skip some tests" + HAVE_IC_STUB_RUN=no + fi + fi +fi + + for file in "$@"; do if ! [ -r $file ] @@ -257,7 +296,7 @@ do # Compile - if [ $DRUN = yes ] + if [ $DTESTS = yes ] then run comp $MOC $moc_extra_flags --hide-warnings --map -c $mangled -o $out/$base.wasm run comp-stub $MOC $moc_extra_flags -stub-system-api --hide-warnings --map -c $mangled -o $out/$base.stub.wasm @@ -289,16 +328,22 @@ do # Run compiled program if [ "$SKIP_RUNNING" != yes ] then - if [ $DRUN = yes ] + if [ $DTESTS = yes ] then - run_if wasm drun-run $DRUN_WRAPPER $out/$base.wasm $mangled - run_if stub.wasm ic-stub-run $IC_STUB_RUN_WRAPPER $out/$base.stub.wasm $mangled + if [ $HAVE_DRUN = yes ]; then + run_if wasm drun-run $DRUN_WRAPPER $out/$base.wasm $mangled + fi + if [ $HAVE_IC_STUB_RUN = yes ]; then + run_if stub.wasm ic-stub-run $IC_STUB_RUN_WRAPPER $out/$base.stub.wasm $mangled + fi elif [ $PERF = yes ] then - run_if wasm drun-run $DRUN_WRAPPER $out/$base.wasm $mangled 222> $out/$base.metrics - if [ -e $out/$base.metrics -a -n "$PERF_OUT" ] - then - LANG=C perl -ne "print \"gas/$base;\$1\n\" if /^gas_consumed_per_round_sum (\\d+)\$/" $out/$base.metrics >> $PERF_OUT; + if [ $HAVE_DRUN = yes ]; then + run_if wasm drun-run $DRUN_WRAPPER $out/$base.wasm $mangled 222> $out/$base.metrics + if [ -e $out/$base.metrics -a -n "$PERF_OUT" ] + then + LANG=C perl -ne "print \"gas/$base;\$1\n\" if /^gas_consumed_per_round_sum (\\d+)\$/" $out/$base.metrics >> $PERF_OUT; + fi fi else run_if wasm wasm-run $WASMTIME $WASMTIME_OPTIONS $out/$base.wasm From b1e6065ad0376a820f2732e7395456868e912a4b Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 19 Feb 2020 23:19:13 -0800 Subject: [PATCH 1044/1176] Drive-by improvements to README (#1225) Co-authored-by: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> --- README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 867517b1105..fe3ae57422a 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,7 @@ A simple language for writing Dfinity actors. * [Building, installing, developing on Motoko](Building.md). * [Overview slides](https://hydra.dfinity.systems/job/dfinity-ci-build/motoko/users-guide/latest/download/1/as-slides.html) ([sources](guide/as-slides.md)). * [Draft (incomplete) manual](guide/guide.md). -* [Prelude](src/prelude/prelude.ml). -* Beginnings of [standard library](stdlib). +* [Standard library](stdlib). * [Small samples](samples). * [Produce Exchange](stdlib/examples/produce-exchange). @@ -259,7 +258,7 @@ charlie.go(); ## Syntax -See [here](design/Syntax.html). +See [here](design/Syntax.md). ## Semantics @@ -269,4 +268,4 @@ TODO ... ## Implementation -See [here](design/Implementation.html) +See [here](design/Implementation.md) From 97e4f2bd2d2de3dc90dc7faeb36da4d4599bead1 Mon Sep 17 00:00:00 2001 From: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> Date: Thu, 20 Feb 2020 14:06:24 +0100 Subject: [PATCH 1045/1176] Completions and auto-imports for canisters (#1222) * Turns url parsing examples into unit tests * Allows completions for imported actors * scans the actor_idl_path for .did files * adds test for canister imports --- src/languageServer/declaration_index.ml | 91 +++++++++++++++++--- src/languageServer/declaration_index.mli | 2 + src/languageServer/declaration_index_test.ml | 5 +- src/languageServer/hover.ml | 8 +- src/pipeline/url.ml | 27 ++---- src/pipeline/url.mli | 1 + src/pipeline/url_test.ml | 43 +++++++++ test/lsp-int-test-project/idlpath/00.did | 3 + test/lsp-int/Main.hs | 28 ++++-- 9 files changed, 163 insertions(+), 45 deletions(-) create mode 100644 src/pipeline/url_test.ml create mode 100644 test/lsp-int-test-project/idlpath/00.did diff --git a/src/languageServer/declaration_index.ml b/src/languageServer/declaration_index.ml index 8fd13707622..18c76d70893 100644 --- a/src/languageServer/declaration_index.ml +++ b/src/languageServer/declaration_index.ml @@ -20,6 +20,15 @@ type ide_decl = | ValueDecl of value_decl | TypeDecl of type_decl +let string_of_option f = function + | None -> "None" + | Some x -> "Some " ^ f x + +let string_of_list f xs = + List.map f xs + |> String.concat "; " + |> fun x -> "[ " ^ x ^ " ]" + (** For debugging purposes *) let string_of_ide_decl = function | ValueDecl value -> @@ -59,12 +68,22 @@ type declaration_index = { modules: ide_decl list Index.t; actors: ide_decl list Index.t; package_map: Pipeline.ResolveImport.package_map; - (* TODO: Add the mapping for IC urls here *) + ic_aliases: Pipeline.ResolveImport.aliases; + actor_idl_path : Pipeline.ResolveImport.actor_idl_path; } + type t = declaration_index + let add_module : string -> ide_decl list -> declaration_index -> declaration_index = fun path decls ix -> { ix with modules = Index.add path decls ix.modules} +let ic_id_to_lookup : string option -> string -> string -> string = + fun actor_idl_path project_root id -> + let crc = Lib.CRC.crc8 id |> Lib.Hex.hex_of_byte in + let hex = Lib.Hex.hex_of_bytes id ^ crc in + let idl_path = actor_idl_path |> Option.value ~default:project_root in + Lib.FilePath.make_absolute project_root (Filename.concat idl_path (hex ^ ".did")) + let lookup_module (project_root : string) (path : string) @@ -93,7 +112,17 @@ let lookup_module | Ok Prim -> Index.find_opt "@prim" index.modules |> Option.map (fun decls -> ("@prim", decls)) - | Ok (Ic _ | IcAlias _) -> (* TODO *) None + | Ok (Ic id) -> + let lookup_path = ic_id_to_lookup index.actor_idl_path project_root id in + Index.find_opt lookup_path index.modules + |> Option.map (fun decls -> (path, decls)) + | Ok (IcAlias alias) -> + let mic_id = Flags.M.find_opt alias index.ic_aliases in + let _ = Debug.log "lookup_module.ic_alias.ic_id" (string_of_option (fun x -> x) mic_id) in + Option.bind mic_id (fun id -> + let lookup_path = ic_id_to_lookup index.actor_idl_path project_root id in + Index.find_opt lookup_path index.modules) + |> Option.map (fun decls -> (alias, decls)) | Error _ -> None let rec drop_common_prefix eq l1 l2 = @@ -104,10 +133,24 @@ let rec drop_common_prefix eq l1 l2 = let shorten_import_path : Pipeline.ResolveImport.package_map + -> Pipeline.ResolveImport.aliases -> string -> string -> string = - fun pkg_map base path -> + fun pkg_map ic_aliases base path -> + let _ = Debug.log "shorten_import" path in + if Filename.extension path = ".did" + then + let idl_basename = Filename.basename path in + Flags.M.bindings ic_aliases + |> Lib.List.first_opt (fun (alias, id) -> + Debug.log "basename" (Pipeline.URL.idl_basename_of_blob id); + if Pipeline.URL.idl_basename_of_blob id = idl_basename then Some alias else None + ) + |> (function + | None -> Printf.sprintf "ic:%s" (Filename.remove_extension idl_basename) + | Some alias -> Printf.sprintf "canister:%s" alias) + else let pkg_path = Flags.M.bindings pkg_map |> Lib.List.first_opt (fun (name, pkg_path) -> @@ -135,14 +178,14 @@ let find_with_prefix -> string -> t -> (string * ide_decl list) list = - fun prefix base {modules; package_map; _} -> + fun prefix base {modules; package_map; ic_aliases; _} -> Index.bindings modules |> List.map (fun (p, ds) -> let import_path = if p = "@prim" then "mo:prim" else - shorten_import_path package_map base p in + shorten_import_path package_map ic_aliases base p in (import_path, List.filter (decl_has_prefix prefix) ds)) |> List.filter (fun (_, ds) -> not (ds = [])) @@ -157,7 +200,9 @@ let empty : string -> t = fun cwd -> }) in { modules = Index.empty; actors = Index.empty; - package_map = Flags.M.map (Lib.FilePath.make_absolute cwd) resolved_flags.packages + package_map = Flags.M.map (Lib.FilePath.make_absolute cwd) resolved_flags.packages; + ic_aliases = resolved_flags.aliases; + actor_idl_path = resolved_flags.actor_idl_path } module PatternMap = Map.Make(String) @@ -175,11 +220,6 @@ let rec gather_pat ve pat : pattern_map = and gather_pat_field ve pf = gather_pat ve pf.it.pat -let string_of_list f xs = - List.map f xs - |> String.concat "; " - |> fun x -> "[ " ^ x ^ " ]" - let string_of_index : declaration_index -> string = fun index -> Index.bindings index.modules @@ -192,7 +232,7 @@ let string_of_index : declaration_index -> string = let read_single_module_lib (ty: Type.typ): ide_decl list option = match ty with - | Type.Obj (Type.Module, fields) -> + | Type.Obj ((Type.Module | Type.Actor), fields) -> fields |> List.map (fun Type.{ lab = name; typ } -> @@ -282,6 +322,14 @@ let scan_packages : unit -> string list = |> List.filter (fun f -> Filename.extension f = ".mo") in Flags.M.fold (fun _ v acc -> scan_package v @ acc) !Flags.package_urls [] +let scan_actors : unit -> string list = + fun _ -> + match !Flags.actor_idl_path with + | None -> [] + | Some idl_path -> + list_files_recursively idl_path + |> List.filter (fun f -> Filename.extension f = ".did") + let index_from_scope : string -> t -> Syntax.lib list -> Scope.t -> t = fun project_root initial_index libs scope -> Type.Env.fold @@ -312,13 +360,28 @@ let make_index_inner logger project_root vfs entry_points : t Diag.result = end | Result.Ok ((libs, scope), _) -> index_from_scope project_root (empty project_root) libs scope in + let actor_paths = scan_actors () in + let _ = Debug.log "Actor paths" (string_of_list (fun x -> x) actor_paths) in + let actor_env = + List.fold_left (fun acc f -> + Idllib.Pipeline.check_file f + |> function + | Result.Error errs -> + List.iter (fun err -> + logger "actor_index_errors" (Diag.string_of_message err)) errs; + acc + | Result.Ok ((prog, idl_scope, actor_opt), _) -> + let actor = Mo_idl.Idl_to_mo.check_prog idl_scope actor_opt in + Scope.adjoin acc (Scope.lib f actor); + ) Pipeline.initial_stat_env actor_paths in + let actor_index = index_from_scope project_root lib_index [] actor_env in (* TODO(Christoph): We should be able to return at least the - lib_index even if compiling from the entry points fails *) + actor_index even if compiling from the entry points fails *) Pipeline.load_progs (Vfs.parse_file vfs) entry_points Pipeline.initial_stat_env - |> Diag.map (fun (libs, _, scope) -> index_from_scope project_root lib_index libs scope) + |> Diag.map (fun (libs, _, scope) -> index_from_scope project_root actor_index libs scope) let make_index logger project_root vfs entry_points : t Diag.result = diff --git a/src/languageServer/declaration_index.mli b/src/languageServer/declaration_index.mli index 038003eb05b..6daa08d5783 100644 --- a/src/languageServer/declaration_index.mli +++ b/src/languageServer/declaration_index.mli @@ -27,6 +27,8 @@ val name_of_ide_decl : ide_decl -> string val shorten_import_path : Pipeline.ResolveImport.package_map (** The package map for searching package paths *) + -> Pipeline.ResolveImport.aliases + (** The aliases for looking up canister ids *) -> string (** The file that ends up containing the import *) -> string diff --git a/src/languageServer/declaration_index_test.ml b/src/languageServer/declaration_index_test.ml index b46c3d35b54..f9613e966a2 100644 --- a/src/languageServer/declaration_index_test.ml +++ b/src/languageServer/declaration_index_test.ml @@ -1,7 +1,8 @@ -let shorten_test pkg_map base path expected = +let shorten_test pkg_map aliases base path expected = let actual = Declaration_index.shorten_import_path (Mo_config.Flags.M.of_seq (List.to_seq pkg_map)) + (Mo_config.Flags.M.of_seq (List.to_seq aliases)) base path in if not (actual = expected) then @@ -13,6 +14,7 @@ let shorten_test pkg_map base path expected = let%test "it shortens to a relative path" = shorten_test [("std", "/pkgs/std")] + [] "/project/src/file.mo" "/project/src/lib/hello.mo" "lib/hello" @@ -20,6 +22,7 @@ let%test "it shortens to a relative path" = let%test "it shortens to a package path" = shorten_test [("std", "/pkgs/std")] + [] "/project/src/file.mo" "/pkgs/std/list.mo" "mo:std/list" diff --git a/src/languageServer/hover.ml b/src/languageServer/hover.ml index 811f90d061c..530a296830a 100644 --- a/src/languageServer/hover.ml +++ b/src/languageServer/hover.ml @@ -23,11 +23,9 @@ let hover_handler (file_path : string) = let current_uri_opt = Lib.FilePath.relative_to project_root file_path in let toplevel_decls = - let current_module_decls = - current_uri_opt - |> Fun.flip Option.bind (fun uri -> lookup_module project_root uri index) - |> Option.fold ~none:[] ~some:snd in - current_module_decls in + current_uri_opt + |> Fun.flip Option.bind (fun uri -> lookup_module project_root uri index) + |> Option.fold ~none:[] ~some:snd in let mk_hover_result ide_decl = Lsp.{ hover_result_contents = markup_content (hover_detail ide_decl) } in let hover_result = diff --git a/src/pipeline/url.ml b/src/pipeline/url.ml index bbbec42244c..f72bfcaeee8 100644 --- a/src/pipeline/url.ml +++ b/src/pipeline/url.ml @@ -1,24 +1,7 @@ (* Parsing known URLs from mo: and ic: URLs *) (* - parse "mo:std/list" = Ok (Package ("std", "list")) - parse "mo:std/foo/bar" = Ok (Package ("std", "foo/bar")) - parse "mo:foo/bar" = Ok (Package ("foo", "bar")) - parse "mo:foo" = Ok (Package ("foo", "")) - - parse "mo:prim" = Ok (Prim) - parse "mo:prim/bar" = Error… - - parse "ic:DEADBEEF" = Ok (Ic "\DE\AD\BE\EF") - - parse "ic-alias:foo" = Ok (IcAlias "foo") - - parse "std/foo" = Ok (Relative "std/foo") - parse "foo" = Ok (Relative "foo") - parse "./foo" = Ok (Relative "foo") - - - parse "something:else" = Error … + For usage examples take a look at url_test.ml TODO: This could be the place to reject things like ic: mo: http:std/foo @@ -38,7 +21,7 @@ let decode_actor_url url : (string, string) result = let blob, crc = sub hex 0 (length hex - 2), sub hex (length hex - 2) 2 in let bs = Lib.Hex.bytes_of_hex blob in let checksum = Lib.CRC.crc8 bs in - if checksum <> Lib.Hex.int_of_hex_byte crc then Error "invald checksum in principal ID, please check for typos" else + if checksum <> Lib.Hex.int_of_hex_byte crc then Error "invalid checksum in principal ID, please check for typos" else Ok bs type parsed = @@ -48,6 +31,12 @@ type parsed = | IcAlias of string | Prim +let string_of_parsed = function + | Package (x, y) -> Printf.sprintf "Package (%s, %s)" x y + | Relative x -> Printf.sprintf "Relative %s" x + | Ic x -> Printf.sprintf "Ic %s" x + | IcAlias x -> Printf.sprintf "IcAlias %s" x + | Prim -> "Prim" let parse (f: string) : (parsed, string) result = match Lib.String.chop_prefix "mo:" f with diff --git a/src/pipeline/url.mli b/src/pipeline/url.mli index 94e9be4f2cf..0142d4a337a 100644 --- a/src/pipeline/url.mli +++ b/src/pipeline/url.mli @@ -5,5 +5,6 @@ type parsed = | IcAlias of string | Prim +val string_of_parsed : parsed -> string val parse : string -> (parsed, string) result val idl_basename_of_blob : string -> string diff --git a/src/pipeline/url_test.ml b/src/pipeline/url_test.ml new file mode 100644 index 00000000000..6616d8705d0 --- /dev/null +++ b/src/pipeline/url_test.ml @@ -0,0 +1,43 @@ +open Url + +let parse_test input expected = + let actual = parse input in + let show x = match x with + | Result.Ok parsed -> "Ok " ^ string_of_parsed parsed + | Result.Error err -> "Err " ^ err in + if actual = expected then + true + else + (Printf.printf "\nExpected:\n %s\nbut got:\n %s\n" (show expected) (show actual); false) + +let%test "it should parse a package import" = + parse_test "mo:std/list" (Ok (Package ("std", "list"))) +let%test "it should parse a package import (2)" = + parse_test "mo:std/foo/bar" (Ok (Package ("std", "foo/bar"))) +let%test "it should parse a package import (3)" = + parse_test "mo:foo/bar" (Ok (Package ("foo", "bar"))) +let%test "it should parse a package import (4)" = + parse_test "mo:foo" (Ok (Package ("foo", ""))) + +let%test "it should parse a prim import" = + parse_test "mo:prim" (Ok (Prim)) +let%test "it should fail to parse a malformed prim import" = + (* TODO This should be erroring *) + (* parse_test "mo:prim/bar" (Error "") *) + parse_test "mo:prim/bar" (Ok (Package ("prim", "bar"))) + +let%test "it should parse an ic import" = + (* TODO We need a non-trivial ID with a correct CRC *) + parse_test "ic:DEADBEEF" (Error "invalid checksum in principal ID, please check for typos") + +let%test "it should parse a canister alias import" = + parse_test "canister:foo" (Ok (IcAlias "foo")) + +let%test "it should parse a relative import" = + parse_test "std/foo" (Ok (Relative "std/foo")) +let%test "it should parse a relative import (2)" = + parse_test "foo" (Ok (Relative "foo")) +let%test "it should parse a relative import (3)" = + parse_test "./foo" (Ok (Relative "foo")) +let%test "it should fail to parse an unknown URL scheme" = + parse_test "something:else" (Error "Unrecognized URL") diff --git a/test/lsp-int-test-project/idlpath/00.did b/test/lsp-int-test-project/idlpath/00.did new file mode 100644 index 00000000000..587a17d4da4 --- /dev/null +++ b/test/lsp-int-test-project/idlpath/00.did @@ -0,0 +1,3 @@ +service : { + "add_counter": (nat) -> () oneway; +} diff --git a/test/lsp-int/Main.hs b/test/lsp-int/Main.hs index 36411ca62cc..26ece4eb19f 100644 --- a/test/lsp-int/Main.hs +++ b/test/lsp-int/Main.hs @@ -111,14 +111,19 @@ main = do project <- makeAbsolute project removeFile (project "ls.log") `Exception.catch` \(_ :: Exception.SomeException) -> pure () setCurrentDirectory project - handleHUnitFailure project $ do + let serverCommand = mo_ide + <> " --canister-main app.mo" + <> " --debug" + <> " --error-detail 0" + <> " --package mydep " <> (project "mydependency") + <> " --actor-idl " <> (project "idlpath") + <> " --actor-alias counter ic:00" + putStrLn "Starting server with: " + putStrLn serverCommand + handleHUnitFailure project do putStrLn "Starting the session" runSession - (mo_ide - <> " --canister-main app.mo" - <> " --debug" - <> " --error-detail 0" - <> " --package mydep " <> (project "mydependency")) + serverCommand fullCaps "." $ do log "Initializing" @@ -201,6 +206,17 @@ main = do let Just (LSP.List [importEdit]) = actual^.additionalTextEdits shouldContain (Text.lines (importEdit^.newText)) ["import MyDep \"mo:mydep/lib\";"] + log "Completing on not-yet-imported actors" + withDoc "ListClient.mo" \doc -> do + let edit = TextEdit (Range (Position 15 0) (Position 15 0)) "Counter.add_" + _ <- applyEdit doc edit + [actual] <- getCompletions doc (Position 15 12) + liftIO do + shouldBe (actual^.label) "add_counter" + shouldBe (completionDocAsText (actual^.documentation)) (Just "shared Nat -> ()") + let Just (LSP.List [importEdit]) = actual^.additionalTextEdits + shouldContain (Text.lines (importEdit^.newText)) ["import Counter \"canister:counter\";"] + withDoc "ListClient.mo" \doc -> do -- 1 | import List -- ==> 1 | ort List From 2fd8bbb7b0ce18492f751af24f446eb01b15b1d4 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Thu, 20 Feb 2020 21:06:48 +0000 Subject: [PATCH 1046/1176] Separate diagnostics for beginning and end of scope (#1229) * indicate start and end if scope separately * update tests --- src/mo_frontend/typing.ml | 9 ++++- test/fail/bad-async.mo | 4 +- test/fail/illegal-await.mo | 12 +++--- test/fail/ok/bad-async.tc.ok | 5 ++- test/fail/ok/illegal-await.tc.ok | 67 +++++++++++++++----------------- 5 files changed, 51 insertions(+), 46 deletions(-) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index e4639935c34..541fc20b47c 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -274,8 +274,13 @@ let associated_region env typ at = let scope_info env typ at = match region_of_scope env typ with | Some r -> - info env r "this is scope %s mentioned in error at %s" - (T.string_of_typ_expand typ) (string_of_region at) + let s = {left = r.left; right = r.left} in + let l = { r.right with column = r.right.column - 1 } in + let e = {left = l; right = l} in + info env s "start of scope %s mentioned in error at %s" + (T.string_of_typ_expand typ) (string_of_region at); + info env e "end of scope %s mentioned in error at %s" + (T.string_of_typ_expand typ) (string_of_region at); | None -> () let rec infer_async_cap env sort cs tbs at = diff --git a/test/fail/bad-async.mo b/test/fail/bad-async.mo index e7118695c25..4ea7496617c 100644 --- a/test/fail/bad-async.mo +++ b/test/fail/bad-async.mo @@ -3,7 +3,7 @@ actor a { var x : [async Nat] = []; public func foo1() { x := [a.getNat()] }; public func foo2() : async Nat { - 10 + + 10 + (await x[0]) - }; + }; }; \ No newline at end of file diff --git a/test/fail/illegal-await.mo b/test/fail/illegal-await.mo index 75da42e2c9c..ab48fabd7fe 100644 --- a/test/fail/illegal-await.mo +++ b/test/fail/illegal-await.mo @@ -1,6 +1,6 @@ // immediate deadlock -{ - let t : async () = async { await t}; +{ + let t : async () = async { await t; }; }; @@ -9,8 +9,9 @@ { ignore async { - let a1 : async () = async{ await a2; }; // illegal await since a1 : Async() () - let a2 : async () = async{ await a1; }; // illegal await since a2 : Async() () + let a1 : async () = async { await a2; }; // illegal await since a1 : Async() () + let a2 : async () = async { await a1; }; // illegal await since a2 : Async() () + (); }; }; @@ -28,7 +29,8 @@ // Recursive deadlock -shared func Rec(n : Int, a : async ()) : async () { + +func Rec(n : Int, a : async ()) : async () { if (n == 0) { await a // <- illegal await since async<@>() () } diff --git a/test/fail/ok/bad-async.tc.ok b/test/fail/ok/bad-async.tc.ok index 1d931a4f6b9..04076ef16f2 100644 --- a/test/fail/ok/bad-async.tc.ok +++ b/test/fail/ok/bad-async.tc.ok @@ -3,6 +3,7 @@ bad-async.mo:4.32-4.42: type error, expression of type cannot produce expected type async<$top-level> Nat bad-async.mo:7.17-7.21: type error, ill-scoped await: expected async type from current scope $foo2, found async type from other scope $top-level - scope $foo2 is bad-async.mo:5.36-8.10 + scope $foo2 is bad-async.mo:5.36-8.6 scope $top-level is the global scope -bad-async.mo:5.36-8.10: info, this is scope $foo2 mentioned in error at bad-async.mo:7.11-7.21 +bad-async.mo:5.36: info, start of scope $foo2 mentioned in error at bad-async.mo:7.11-7.21 +bad-async.mo:8.5: info, end of scope $foo2 mentioned in error at bad-async.mo:7.11-7.21 diff --git a/test/fail/ok/illegal-await.tc.ok b/test/fail/ok/illegal-await.tc.ok index 7f768094297..329f7300cac 100644 --- a/test/fail/ok/illegal-await.tc.ok +++ b/test/fail/ok/illegal-await.tc.ok @@ -1,40 +1,37 @@ illegal-await.mo:3.36-3.37: type error, ill-scoped await: expected async type from current scope $anon-async-3.22, found async type from other scope $top-level - scope $anon-async-3.22 is illegal-await.mo:3.22-3.38 + scope $anon-async-3.22 is illegal-await.mo:3.22-3.40 scope $top-level is the global scope -illegal-await.mo:3.22-3.38: info, this is scope $anon-async-3.22 mentioned in error at illegal-await.mo:3.30-3.37 -illegal-await.mo:12.38-12.40: type error, ill-scoped await: expected async type from current scope $anon-async-12.25, found async type from other scope $anon-async-11.10 - scope $anon-async-12.25 is illegal-await.mo:12.25-12.43 - scope $anon-async-11.10 is illegal-await.mo:11.10-14.4 -illegal-await.mo:12.25-12.43: info, this is scope $anon-async-12.25 mentioned in error at illegal-await.mo:12.32-12.40 -illegal-await.mo:11.10-14.4: info, this is scope $anon-async-11.10 mentioned in error at illegal-await.mo:12.32-12.40 -illegal-await.mo:13.38-13.40: type error, ill-scoped await: expected async type from current scope $anon-async-13.25, found async type from other scope $anon-async-11.10 - scope $anon-async-13.25 is illegal-await.mo:13.25-13.43 - scope $anon-async-11.10 is illegal-await.mo:11.10-14.4 -illegal-await.mo:13.25-13.43: info, this is scope $anon-async-13.25 mentioned in error at illegal-await.mo:13.32-13.40 -illegal-await.mo:11.10-14.4: info, this is scope $anon-async-11.10 mentioned in error at illegal-await.mo:13.32-13.40 -illegal-await.mo:11.16-14.4: type error, async type has non-shared content type - async<$top-level> () -type - async<$top-level> () -is or contains non-shared type - async<$top-level> () -illegal-await.mo:24.13-24.14: type error, ill-scoped await: expected async type from current scope $anon-async-23.11, found async type from other scope $anon-async-21.10 - scope $anon-async-23.11 is illegal-await.mo:23.11-25.6 - scope $anon-async-21.10 is illegal-await.mo:21.10-26.4 -illegal-await.mo:23.11-25.6: info, this is scope $anon-async-23.11 mentioned in error at illegal-await.mo:24.7-24.14 -illegal-await.mo:21.10-26.4: info, this is scope $anon-async-21.10 mentioned in error at illegal-await.mo:24.7-24.14 -illegal-await.mo:33.11-33.12: type error, ill-scoped await: expected async type from current scope $Rec, found async type from other scope $ - scope $Rec is illegal-await.mo:31.51-38.2 - scope $ is illegal-await.mo:31.1-38.2 -illegal-await.mo:31.51-38.2: info, this is scope $Rec mentioned in error at illegal-await.mo:33.5-33.12 -illegal-await.mo:31.1-38.2: info, this is scope $ mentioned in error at illegal-await.mo:33.5-33.12 -illegal-await.mo:36.20-36.21: type error, expression of type +illegal-await.mo:3.22: info, start of scope $anon-async-3.22 mentioned in error at illegal-await.mo:3.30-3.37 +illegal-await.mo:3.39: info, end of scope $anon-async-3.22 mentioned in error at illegal-await.mo:3.30-3.37 +illegal-await.mo:12.39-12.41: type error, ill-scoped await: expected async type from current scope $anon-async-12.25, found async type from other scope $anon-async-11.10 + scope $anon-async-12.25 is illegal-await.mo:12.25-12.44 + scope $anon-async-11.10 is illegal-await.mo:11.10-15.4 +illegal-await.mo:12.25: info, start of scope $anon-async-12.25 mentioned in error at illegal-await.mo:12.33-12.41 +illegal-await.mo:12.43: info, end of scope $anon-async-12.25 mentioned in error at illegal-await.mo:12.33-12.41 +illegal-await.mo:11.10: info, start of scope $anon-async-11.10 mentioned in error at illegal-await.mo:12.33-12.41 +illegal-await.mo:15.3: info, end of scope $anon-async-11.10 mentioned in error at illegal-await.mo:12.33-12.41 +illegal-await.mo:13.39-13.41: type error, ill-scoped await: expected async type from current scope $anon-async-13.25, found async type from other scope $anon-async-11.10 + scope $anon-async-13.25 is illegal-await.mo:13.25-13.44 + scope $anon-async-11.10 is illegal-await.mo:11.10-15.4 +illegal-await.mo:13.25: info, start of scope $anon-async-13.25 mentioned in error at illegal-await.mo:13.33-13.41 +illegal-await.mo:13.43: info, end of scope $anon-async-13.25 mentioned in error at illegal-await.mo:13.33-13.41 +illegal-await.mo:11.10: info, start of scope $anon-async-11.10 mentioned in error at illegal-await.mo:13.33-13.41 +illegal-await.mo:15.3: info, end of scope $anon-async-11.10 mentioned in error at illegal-await.mo:13.33-13.41 +illegal-await.mo:25.13-25.14: type error, ill-scoped await: expected async type from current scope $anon-async-24.11, found async type from other scope $anon-async-22.10 + scope $anon-async-24.11 is illegal-await.mo:24.11-26.6 + scope $anon-async-22.10 is illegal-await.mo:22.10-27.4 +illegal-await.mo:24.11: info, start of scope $anon-async-24.11 mentioned in error at illegal-await.mo:25.7-25.14 +illegal-await.mo:26.5: info, end of scope $anon-async-24.11 mentioned in error at illegal-await.mo:25.7-25.14 +illegal-await.mo:22.10: info, start of scope $anon-async-22.10 mentioned in error at illegal-await.mo:25.7-25.14 +illegal-await.mo:27.3: info, end of scope $anon-async-22.10 mentioned in error at illegal-await.mo:25.7-25.14 +illegal-await.mo:35.11-35.12: type error, ill-scoped await: expected async type from current scope $Rec, found async type from other scope $ + scope $Rec is illegal-await.mo:33.44-40.2 + scope $ is illegal-await.mo:33.1-40.2 +illegal-await.mo:33.44: info, start of scope $Rec mentioned in error at illegal-await.mo:35.5-35.12 +illegal-await.mo:40.1: info, end of scope $Rec mentioned in error at illegal-await.mo:35.5-35.12 +illegal-await.mo:33.1: info, start of scope $ mentioned in error at illegal-await.mo:35.5-35.12 +illegal-await.mo:40.1: info, end of scope $ mentioned in error at illegal-await.mo:35.5-35.12 +illegal-await.mo:38.20-38.21: type error, expression of type async<$> () cannot produce expected type async<$Rec> () -illegal-await.mo:31.16-31.39: type error, shared function has non-shared parameter type - (Int, async<$> ()) -type - (Int, async<$> ()) -is or contains non-shared type - async<$> () From c09f7e1e86ce9a0f2aced11433caf2665b1824eb Mon Sep 17 00:00:00 2001 From: Yan Chen <48968912+chenyan-dfinity@users.noreply.github.com> Date: Thu, 20 Feb 2020 13:22:42 -0800 Subject: [PATCH 1047/1176] Add principal type to IDL spec (#1211) * Add principal type to IDL spec * update * fix --- design/IDL.md | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/design/IDL.md b/design/IDL.md index 07b7e4e43f0..feffc151aff 100644 --- a/design/IDL.md +++ b/design/IDL.md @@ -89,6 +89,7 @@ This is a summary of the grammar proposed: ::= | func | service + | principal ::= | ::= (A..Z|a..z|_)(A..Z|a..z|_|0..9)* @@ -266,7 +267,6 @@ Text strings are represented by the type `text` and consist of a sequence of Uni ``` **Note:** The `text` type is distinguished from `vec nat8` (a UTF-8 string) or `vec nat32` (a sequence of code points) in order to allow bindings to map it to a suitable string type, and enable the binary format to select an efficient internal representation independently. - #### Null The type `null` has exactly one value (the *null* value) and therefor carries no information. It can e.g. be used as a placeholder for optional fields that ought to be added to a record in future upgrades, or for *variant cases* that do not need any value, see below. @@ -424,7 +424,7 @@ type tree = variant { ### References -A third form of value are *references*. They represent first-class handles to (possibly remote) *functions* or *services*. +A third form of value are *references*. They represent first-class handles to (possibly remote) *functions*, *services*, or *principals*. #### Actor References @@ -459,6 +459,14 @@ type engine = service { } ``` +#### Principal References + +A *principal reference* points to an identity, such as an actor or a user. Through this, we can authenticate or authorize other services or users. + +``` + ::= ... | principal | ... +``` + ### Type Definitions Types can be named via *type definitions*. @@ -821,7 +829,7 @@ This section describes how abstract *IDL values* of the types described by the I Serialisation is defined by three functions `T`, `M`, and `R` given below. -Most IDL values are self-explanatory, except for references. There are two forms of IDL values for actor references: +Most IDL values are self-explanatory, except for references. There are two forms of IDL values for actor references and principal references: * `ref(r)` indicates an opaque reference, understood only by the underlying system. * `id(b)`, indicates a transparent reference to a service addressed by the blob `b`. @@ -886,6 +894,7 @@ T(func (*) -> (*) *) = sleb128(-22) T*(*) T*(*) T*(*) // 0x6a T(service {*}) = sleb128(-23) T*(*) // 0x69 +T(principal)= sleb128(-24) // 0x68 T : -> i8* T(:) = leb128(|utf8()|) i8*(utf8()) I() @@ -950,10 +959,13 @@ M((k,v) : k:) = M(v : ) M : -> -> i8* M(ref(r) : service ) = i8(0) -M(id(v*) : service ) = i8(1) M(v* : vec i8) +M(id(v*) : service ) = i8(1) M(v* : vec nat8) M(ref(r) : func ) = i8(0) M(pub(s,n) : func ) = i8(1) M(s : service {}) M(n : text) + +M(ref(r) : principal) = i8(0) +M(id(v*) : principal) = i8(1) M(v* : vec nat8) ``` @@ -981,6 +993,8 @@ R(ref(r) : service ) = r R(id(b*) : service ) = . R(ref(r) : func ) = r R(pub(s,n) : func ) = . +R(ref(r) : principal) = r +R(id(b*) : principal) = . ``` Note: @@ -992,7 +1006,7 @@ Note: Deserialisation is the parallel application of the inverse functions of `T`, `M`, and `R` defined above, with the following mechanism for robustness towards future extensions: -* A serialised type may be headed by an opcode other than the ones defined above (i.e., less than -23). Any such opcode is followed by an LEB128-encoded count, and then a number of bytes corresponding to this count. A type represented that way is called a *future type*. +* A serialised type may be headed by an opcode other than the ones defined above (i.e., less than -24). Any such opcode is followed by an LEB128-encoded count, and then a number of bytes corresponding to this count. A type represented that way is called a *future type*. * A value corresponding to a future type is called a *future value*. It is represented by two LEB128-encoded counts, *m* and *n*, followed by a *m* bytes in the memory representation M and accompanied by *n* corresponding references in R. @@ -1053,6 +1067,7 @@ The types of these values are assumed to be known from context, so the syntax do ::= | service (canister URI) | func . (canister URI and message name) + | principal (principal URI) ::= ( ,* ) From 004dfc5cfc26493012062c018a9785d56cf1ed41 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Thu, 20 Feb 2020 22:47:25 +0100 Subject: [PATCH 1048/1176] Decide which tests to run by the availability of the embedders (#1227) * fix `drun` options usage * probe the availability of embedders and run only corresponding tests * regroup tests by embedder * add `Text` encoding test --- test/random/Embedder.hs | 14 ++++++++++++-- test/random/Main.hs | 38 +++++++++++++++++++++++++++++++------- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/test/random/Embedder.hs b/test/random/Embedder.hs index 0107f4fa41e..474a86a4ff4 100644 --- a/test/random/Embedder.hs +++ b/test/random/Embedder.hs @@ -1,6 +1,6 @@ {-# language OverloadedStrings, {-PartialTypeSignatures,-} ScopedTypeVariables, TupleSections #-} -module Embedder (Embedder(..), WasmAPI(..), embedder, embedderCommand, addCompilerArgs, addEmbedderArgs, invokeEmbedder) where +module Embedder (Embedder(..), WasmAPI(..), embedder, isHealthy, embedderCommand, addCompilerArgs, addEmbedderArgs, invokeEmbedder) where import Test.QuickCheck @@ -9,7 +9,9 @@ import Turtle.Pipe import Control.Monad.Catch import GHC.IO.Exception (IOException) +import Data.Text (unwords) import Data.IORef +-- import Debug.Trace (traceShowId, traceShow) data WasmAPI = DontPrint | WASI @@ -22,6 +24,11 @@ embedderCommand Reference = "wasm" embedderCommand (WasmTime _) = "wasmtime" embedderCommand Drun = "drun" +isHealthy :: Embedder -> IO Bool +isHealthy e = do + (res, _) <- shellStrict (embedderCommand e <> " --help") empty + pure $ res == ExitSuccess + addCompilerArgs Reference = ("-no-system-api" :) addCompilerArgs (WasmTime DontPrint) = ("-no-system-api" :) addCompilerArgs (WasmTime WASI) = ("-wasi-system-api" :) @@ -31,6 +38,9 @@ addEmbedderArgs Reference = id addEmbedderArgs (WasmTime _) = ("--disable-cache" :) . ("--cranelift" :) addEmbedderArgs Drun = ("--extra-batches" :) . ("10" :) +embedderInvocation :: Embedder -> [Text] -> [Text] +embedderInvocation e args = embedderCommand e : addEmbedderArgs e args + invokeEmbedder :: Embedder -> Turtle.FilePath -> IO (ExitCode, Text, Text) invokeEmbedder embedder wasm = go embedder where fileArg = fromString . encodeString @@ -46,7 +56,7 @@ invokeEmbedder embedder wasm = go embedder rm (fileArg control) `catch` \(_ :: GHC.IO.Exception.IOException) -> pure () -- rm -f let Right c = toText control procs "mkfifo" [c] empty - consumer <- forkShell $ inshell ("drun --extra-batches 100 " <> c) empty + consumer <- forkShell $ inshell (Data.Text.unwords $ embedderInvocation embedder [c]) empty let install = unsafeTextToLine $ format ("install ic:2A012B "%s%" 0x") w pipe (fileArg control) (pure install diff --git a/test/random/Main.hs b/test/random/Main.hs index b3937528b1f..c723e7b8620 100644 --- a/test/random/Main.hs +++ b/test/random/Main.hs @@ -13,7 +13,7 @@ import Test.Tasty import Test.Tasty.QuickCheck as QC hiding ((.&.)) import Test.QuickCheck.Unicode import System.Environment -import qualified Data.Text (null, unpack) +import qualified Data.Text (null, pack, unpack) import Data.Maybe import Data.Bool (bool) import Data.Proxy @@ -23,15 +23,27 @@ import GHC.TypeLits hiding (Text) import qualified Data.Word import Data.Bits (Bits(..), FiniteBits(..)) import Numeric +import Data.List (intercalate) import Turtle import Embedder -- import Debug.Trace (traceShowId, traceShow) -main = setEnv "TASTY_NUM_THREADS" "1" >> defaultMain tests - where tests :: TestTree - tests = testGroup "Motoko tests" [arithProps, conversionProps, utf8Props, matchingProps] +main = do + putStrLn "Probing embedders..." + good <- isHealthy embedder + goodDrun <- isHealthy Drun + putStrLn . ("Found " <>) . (<> ".") . intercalate " and " . map embedderCommand + $ [ embedder | good ] <> [ Drun | goodDrun ] + let tests :: TestTree + tests = testGroup "Motoko tests" . concat + $ [ [arithProps, conversionProps, utf8Props, matchingProps] | good ] + <> [ [encodingProps] | goodDrun ] + + if not (good || goodDrun) + then putStrLn "No embedder available for testing. Done..." + else setEnv "TASTY_NUM_THREADS" "1" >> defaultMain tests arithProps = testGroup "Arithmetic/logic" [ QC.testProperty "expected failures" $ prop_rejects @@ -58,11 +70,17 @@ utf8Props = testGroup "UTF-8 coding" , QC.testProperty "chunky iterator (ropes)" $ prop_ropeIterator ] -matchingProps = testGroup "Pattern matching" - [ QC.testProperty "intra-actor" $ prop_matchStructured - , QC.testProperty "inter-actor" $ withMaxSuccess 20 prop_matchInActor +matchingProps = testGroup "Pattern matching" $ + [ QC.testProperty "intra-actor" $ prop_matchStructured ] + + +-- these require messaging +-- +encodingProps = testGroup "Encoding" $ + [ QC.testProperty "inter-actor" $ withMaxSuccess 20 prop_matchInActor , QC.testProperty "encoded-Nat" $ withMaxSuccess 10 prop_matchActorNat , QC.testProperty "encoded-Int" $ withMaxSuccess 10 prop_matchActorInt + , QC.testProperty "encoded-Text" $ withMaxSuccess 10 prop_matchActorText ] @@ -315,6 +333,12 @@ prop_matchActorInt int = monadicIO $ do eval'd = evalN int drunScriptNoFuzz "matchActorInt" (Data.Text.unpack testCase) +prop_matchActorText :: UTF8 String -> Property +prop_matchActorText (UTF8 text) = monadicIO $ do + let testCase = format ("actor { public func match (i : Text) : async () { assert (switch i { case (\""%s%"\") true; case _ false }) }; public func do () : async () { let res = await match (\""%s%"\" : Text); return res } };") eval'd eval'd + eval'd = Data.Text.pack $ text >>= escape + drunScriptNoFuzz "matchActorText" (Data.Text.unpack testCase) + -- instances of MOValue describe "ground values" in -- Motoko. These can appear in patterns and have -- well-defined Motoko type. From 290534b598883a6dae33e10bdf4618129ab5bb0c Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 20 Feb 2020 15:33:34 -0800 Subject: [PATCH 1049/1176] Refactor setup for generated nix files (#1223) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit the reiterates on #1220. The motivation for the refactoring was that the generated files were not using `gitSource`, so I would get cache misses and dirty files in the repo. Fixing this was easier if all generated nix files are in one place, so I did the following changes: * All generated nix files are in `nix/generated`. This de-pollutes the normal working area with generated files, and keeps them out from sources (more precise derivations). * The local generated files now use `gitSource`. * The generator is now `nix/generate.nix`. * I moved complex logic from `nix/default.nix` to `nix/generate.nix`, this means everything is in one place, instead of spread over several nix files. * There is now only a single check to check if the generated files are upto date, and a single command to update the files. * This check is no longer marked `allowSubstitutes = false`. The check isn’t cheap (it requires `cabal2nix`) and we want the check to happen on builders, not hydra itself, so that the cache has `cabal2nix`. * The check is now included in `all-systems-go`. --- Building.md | 22 ++---- default.nix | 27 +++---- ic-stub/generate.nix | 1 - nix/default.nix | 40 ---------- nix/generate.nix | 75 +++++++++++++++++++ .../default.nix => nix/generated/ic-stub.nix | 9 +-- nix/generated/lsp-int.nix | 20 +++++ .../default.nix => nix/generated/random.nix | 9 +-- .../default.nix => nix/generated/winter.nix | 5 +- nix/haskell-packages.nix | 8 +- test/random/generate.nix | 1 - winter/generate.nix | 15 ---- 12 files changed, 125 insertions(+), 107 deletions(-) delete mode 100644 ic-stub/generate.nix create mode 100644 nix/generate.nix rename ic-stub/default.nix => nix/generated/ic-stub.nix (73%) create mode 100644 nix/generated/lsp-int.nix rename test/random/default.nix => nix/generated/random.nix (70%) rename winter/default.nix => nix/generated/winter.nix (90%) delete mode 100644 test/random/generate.nix delete mode 100644 winter/generate.nix diff --git a/Building.md b/Building.md index 9a25949e897..a38524b2d54 100644 --- a/Building.md +++ b/Building.md @@ -81,20 +81,12 @@ https://github.com/ocaml/dune/issues/57 to see when a coverage report is viable ## Updating Haskell Packages When the `.cabal` file of a Haskell package is changed you need to make sure the -corresponding `default.nix` file (stored in the same directory as the `.cabal` -file) is kept in sync with it. +corresponding `default.nix` file (stored in `nix/generated/`) is kept in sync +with it. -As mentioned in the `default.nix` files, these files are automatically generated: +As mentioned in the `nix/generate.nix` files, these files are automatically +generated. See `nix/generate.nix` for the command to update them. -``` -# THIS IS AN AUTOMATICALLY GENERATED FILE. DO NOT EDIT MANUALLY! -# To regenerate this file execute the following command in this directory: -# -# cp $(nix-build ./generate.nix --no-link)/default.nix ./default.nix -``` - -Note that they also contain the instructions on how to update them. - -Don't worry if you forget to update the `default.nix` file. There are CI jobs -(like [`haskellSrc2nix.lsp-int`](https://hydra.dfinity.systems/job/dfinity-ci-build/motoko/haskellSrc2nix.lsp-int) -that check if the files are in sync and fail with a diff if they aren't. +Don't worry if you forget to update the `default.nix` file, the CI job +`check-generated` checks if these files are in sync and fail with a diff if +they aren't. diff --git a/default.nix b/default.nix index b13fdd7ec45..cdd7fc143ad 100644 --- a/default.nix +++ b/default.nix @@ -411,24 +411,14 @@ rec { }; stdlib-adocs = stdlib-doc.adocs; - haskellSrc2nix = - let - check = dir: nixpkgs.runCommandNoCC "check-${builtins.baseNameOf dir}" { - preferLocalBuild = true; - allowSubstitutes = false; - nativeBuildInputs = [ nixpkgs.diffutils ]; - expected = import (dir + "/generate.nix") { pkgs = nixpkgs; }; - inherit dir; - } '' - diff -U 3 $expected/default.nix $dir/default.nix - touch $out - ''; - in { - lsp-int = check ./test/lsp-int; - qc-motoko = check ./test/random; - ic-stub = check ./ic-stub; - winter = check ./winter; - }; + check-generated = nixpkgs.runCommandNoCC "check-generated" { + nativeBuildInputs = [ nixpkgs.diffutils ]; + expected = import ./nix/generate.nix { pkgs = nixpkgs; }; + dir = ./nix/generated; + } '' + diff -r -U 3 $expected $dir + touch $out + ''; all-systems-go = nixpkgs.releaseTools.aggregate { name = "all-systems-go"; @@ -447,6 +437,7 @@ rec { users-guide ic-stub shell + check-generated ] ++ builtins.attrValues tests ++ builtins.attrValues examples; }; diff --git a/ic-stub/generate.nix b/ic-stub/generate.nix deleted file mode 100644 index cd9857ac4b4..00000000000 --- a/ic-stub/generate.nix +++ /dev/null @@ -1 +0,0 @@ -{ pkgs ? import ../nix {} }: pkgs.localHaskellSrc2nixWithDoc "ic-stub" ./. "--no-check" diff --git a/nix/default.nix b/nix/default.nix index 155eb3e5e95..41ee345fa4d 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -25,46 +25,6 @@ let }; } ) - (self: super: { - # A variant of `haskellSrc2nixWithDoc` for local Haskell packages. - localHaskellSrc2nixWithDoc = name: path: extraCabal2nixOptions: - self.haskellSrc2nixWithDoc { - inherit name extraCabal2nixOptions; - src = import ./gitSource.nix path; - src_subst = "./."; - }; - - # `haskellSrc2nixWithDoc` is used to generate `default.nix` files for - # Haskell packages which are intended to be stored in the repository. - # - # The function generates a directory containing a `default.nix` which - # is the result of running `cabal2nix` with the `extraCabal2nixOptions` - # on the provided `src`. - # - # A header is added to `default.nix` which contains instructions on - # how to regenerate that file. - # - # Finally the `src` attribute in the `default.nix` will be defined as - # `src_subst` such that it can be pointed to local or niv-managed - # sources. - haskellSrc2nixWithDoc = {name, src, src_subst, extraCabal2nixOptions}: - let - drv = pkgs.haskellPackages.haskellSrc2nix { - inherit name extraCabal2nixOptions src; - }; - in drv.overrideAttrs (oldAttrs: { - message = '' - # THIS IS AN AUTOMATICALLY GENERATED FILE. DO NOT EDIT MANUALLY!\ - # To regenerate this file execute the following command in this directory:\ - #\ - # cp $(nix-build ./generate.nix --no-link)/default.nix ./default.nix - ''; - inherit src_subst; - installPhase = oldAttrs.installPhase + '' - sed -i "1i$message;s|src = .*|src = $src_subst;|" $out/default.nix - ''; - }); - }) ]; }; in diff --git a/nix/generate.nix b/nix/generate.nix new file mode 100644 index 00000000000..13b622e9a78 --- /dev/null +++ b/nix/generate.nix @@ -0,0 +1,75 @@ +# This file generates the contents of nix/generated/. Use +# +# cp -fv $(nix-build generate.nix --no-link)/ generated/ +# +# to update + +{ pkgs ? import ../nix {} }: + +let + + # `haskellSrc2nixWithDoc` is used to generate `default.nix` files for + # Haskell packages which are intended to be stored in the repository. + # + # The function generates a directory containing a `default.nix` which + # is the result of running `cabal2nix` with the `extraCabal2nixOptions` + # on the provided `src`. + # + # A header is added to `default.nix` which contains instructions on + # how to regenerate that file. + # + # Finally the `src` attribute in the `default.nix` will be defined as + # `src_subst` such that it can be pointed to local or niv-managed + # sources. + haskellSrc2nixWithDoc = {name, src, src_subst, extraCabal2nixOptions}: + let + drv = pkgs.haskellPackages.haskellSrc2nix { + inherit name extraCabal2nixOptions src; + }; + in drv.overrideAttrs (oldAttrs: { + message = '' + # THIS IS AN AUTOMATICALLY GENERATED FILE. DO NOT EDIT MANUALLY!\ + # See ./nix/generate.nix for instructions.\ + + ''; + inherit src_subst; + installPhase = oldAttrs.installPhase + '' + sed -i "1i$message;s|src = .*|src = $src_subst;|" $out/default.nix + # Accept `pkgs` as an argument in case the `src_subst` depends on it. + sed -i "s|{ mkDerivation|{ mkDerivation, pkgs|" $out/default.nix + ''; + }); + + # A variant of `haskellSrc2nixWithDoc` for local Haskell packages. + localHaskellSrc2nixWithDoc = name: path: extraCabal2nixOptions: + haskellSrc2nixWithDoc { + inherit name extraCabal2nixOptions; + src = import ./gitSource.nix path; + src_subst = "import ../gitSource.nix \"${path}\""; + }; + + + winter = (haskellSrc2nixWithDoc { + name = "winter"; + src = pkgs.sources.winter; + src_subst = "pkgs.sources.winter"; + extraCabal2nixOptions = "--no-check"; + }); + + ic-stub = localHaskellSrc2nixWithDoc "ic-stub" "ic-stub" "--no-check"; + random = localHaskellSrc2nixWithDoc "qc-motoko" "test/random" ""; + lsp-int = localHaskellSrc2nixWithDoc "lsp-int" "test/lsp-int" ""; + + allGenerated = pkgs.runCommandNoCC "generated" {} '' + mkdir -p $out + cp ${winter}/default.nix $out/winter.nix + cp ${ic-stub}/default.nix $out/ic-stub.nix + cp ${random}/default.nix $out/random.nix + cp ${lsp-int}/default.nix $out/lsp-int.nix + ''; +in +allGenerated + + + + diff --git a/ic-stub/default.nix b/nix/generated/ic-stub.nix similarity index 73% rename from ic-stub/default.nix rename to nix/generated/ic-stub.nix index f9ab4998473..c1cedd8a590 100644 --- a/ic-stub/default.nix +++ b/nix/generated/ic-stub.nix @@ -1,8 +1,7 @@ # THIS IS AN AUTOMATICALLY GENERATED FILE. DO NOT EDIT MANUALLY! -# To regenerate this file execute the following command in this directory: -# -# cp $(nix-build ./generate.nix --no-link)/default.nix ./default.nix -{ mkDerivation, base, binary, bytestring, containers +# See ./nix/generate.nix for instructions. + +{ mkDerivation, pkgs, base, binary, bytestring, containers , data-default-class, filepath, hex-text, mtl, optparse-applicative , primitive, stdenv, text, transformers, utf8-string, vector , winter @@ -10,7 +9,7 @@ mkDerivation { pname = "ic-stub"; version = "0.1.0.0"; - src = ./.; + src = import ../gitSource.nix "ic-stub"; isLibrary = false; isExecutable = true; executableHaskellDepends = [ diff --git a/nix/generated/lsp-int.nix b/nix/generated/lsp-int.nix new file mode 100644 index 00000000000..666263372a7 --- /dev/null +++ b/nix/generated/lsp-int.nix @@ -0,0 +1,20 @@ +# THIS IS AN AUTOMATICALLY GENERATED FILE. DO NOT EDIT MANUALLY! +# See ./nix/generate.nix for instructions. + +{ mkDerivation, pkgs, base, data-default, directory, filepath +, haskell-lsp-types, hspec, HUnit, lens, lsp-test, stdenv, text +}: +mkDerivation { + pname = "lsp-int"; + version = "0"; + src = import ../gitSource.nix "test/lsp-int"; + isLibrary = false; + isExecutable = true; + executableHaskellDepends = [ + base data-default directory filepath haskell-lsp-types hspec HUnit + lens lsp-test text + ]; + description = "Integration tests for the language server"; + license = "unknown"; + hydraPlatforms = stdenv.lib.platforms.none; +} diff --git a/test/random/default.nix b/nix/generated/random.nix similarity index 70% rename from test/random/default.nix rename to nix/generated/random.nix index 94cf7906662..c754e3b3f88 100644 --- a/test/random/default.nix +++ b/nix/generated/random.nix @@ -1,15 +1,14 @@ # THIS IS AN AUTOMATICALLY GENERATED FILE. DO NOT EDIT MANUALLY! -# To regenerate this file execute the following command in this directory: -# -# cp $(nix-build ./generate.nix --no-link)/default.nix ./default.nix -{ mkDerivation, base, exceptions, managed, process, QuickCheck +# See ./nix/generate.nix for instructions. + +{ mkDerivation, pkgs, base, exceptions, managed, process, QuickCheck , quickcheck-text, quickcheck-unicode, stdenv, tasty , tasty-quickcheck, text, turtle }: mkDerivation { pname = "qc-motoko"; version = "1"; - src = ./.; + src = import ../gitSource.nix "test/random"; isLibrary = false; isExecutable = true; executableHaskellDepends = [ diff --git a/winter/default.nix b/nix/generated/winter.nix similarity index 90% rename from winter/default.nix rename to nix/generated/winter.nix index bbee9d168ac..43f3da15b09 100644 --- a/winter/default.nix +++ b/nix/generated/winter.nix @@ -1,7 +1,6 @@ # THIS IS AN AUTOMATICALLY GENERATED FILE. DO NOT EDIT MANUALLY! -# To regenerate this file execute the following command in this directory: -# -# cp $(nix-build ./generate.nix --no-link)/default.nix ./default.nix +# See ./nix/generate.nix for instructions. + { mkDerivation, pkgs, array, base, binary, byte-order, bytestring , cmdargs, containers, data-default-class, data-fix, deepseq , directory, filepath, FloatingHex, lifted-base, microlens-platform diff --git a/nix/haskell-packages.nix b/nix/haskell-packages.nix index caf1e4e8c70..1937e7515b4 100644 --- a/nix/haskell-packages.nix +++ b/nix/haskell-packages.nix @@ -9,11 +9,11 @@ nix: subpath: lsp-test = nix.haskell.lib.dontCheck self.lsp-test_0_10_1_0; - lsp-int = super.callPackage ../test/lsp-int {}; + lsp-int = super.callPackage generated/lsp-int.nix {}; - qc-motoko = super.callPackage ../test/random {}; + qc-motoko = super.callPackage generated/random.nix {}; - winter = super.callPackage ../winter {}; + winter = super.callPackage generated/winter.nix {}; - ic-stub = super.callPackage ../ic-stub {}; + ic-stub = super.callPackage generated/ic-stub.nix {}; } diff --git a/test/random/generate.nix b/test/random/generate.nix deleted file mode 100644 index cd9b234c170..00000000000 --- a/test/random/generate.nix +++ /dev/null @@ -1 +0,0 @@ -{ pkgs ? import ../../nix {} }: pkgs.localHaskellSrc2nixWithDoc "qc-motoko" ./. "" diff --git a/winter/generate.nix b/winter/generate.nix deleted file mode 100644 index 7c26f492245..00000000000 --- a/winter/generate.nix +++ /dev/null @@ -1,15 +0,0 @@ -{ pkgs ? import ../nix {} }: -let - drv = pkgs.haskellSrc2nixWithDoc { - name = "winter"; - src = pkgs.sources.winter; - src_subst = "pkgs.sources.winter"; - extraCabal2nixOptions = "--no-check"; - }; -in -drv.overrideAttrs (oldAttrs: { - installPhase = oldAttrs.installPhase + '' - # Accept `pkgs` as an argument because the `src` depends on it. - sed -i "s|{ mkDerivation|{ mkDerivation, pkgs|" $out/default.nix - ''; -}) From 63a85d63027a728368e93eee85b2e9fce641461a Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 21 Feb 2020 00:10:13 -0800 Subject: [PATCH 1050/1176] Bump nixpkgs, track upstream (#1226) in #1189 we switched to a fork of nixpkgs to get two patches not in nixpkgs `master` at that time. Looks like they have made it to `nixpkgs/master`, so we can track that again (and make the Motoko repo more self-contained). --- nix/sources.json | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/nix/sources.json b/nix/sources.json index 9f917ef7ea5..fc85a4c6513 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -32,15 +32,14 @@ "version": "v1.2.0" }, "nixpkgs": { - "branch": "dfinity-motoko", - "description": "A read-only mirror of NixOS/nixpkgs tracking the released channels. Send issues and PRs to", + "branch": "master", "homepage": "https://github.com/NixOS/nixpkgs", - "owner": "dfinity-lab", + "owner": "NixOS", "repo": "nixpkgs", - "rev": "a4e23f32f8d7006e217125a9123b53597b9c0c24", - "sha256": "1afpk1w6akfpvyj3n0wmlydpmxzb6khcgl4vhi7qkgg9bp6rngg4", + "rev": "82a6834e3b1ae343fed1d9495943fba71d6759fa", + "sha256": "0q6vdl3m80mv9vlgix6116vghgnnr1hixa60b3wv7krxx3gaz626", "type": "tarball", - "url": "https://github.com/dfinity-lab/nixpkgs/archive/a4e23f32f8d7006e217125a9123b53597b9c0c24.tar.gz", + "url": "https://github.com/NixOS/nixpkgs/archive/82a6834e3b1ae343fed1d9495943fba71d6759fa.tar.gz", "url_template": "https://github.com///archive/.tar.gz" }, "ocaml-vlq": { From 150e2068072a7445860db47321f09e43ce441424 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 21 Feb 2020 01:15:12 -0800 Subject: [PATCH 1051/1176] Nix: make decision about static linking only once (#1230) this removes some redundant logic; cherry-picked from #1224 --- default.nix | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/default.nix b/default.nix index cdd7fc143ad..d3bae20a244 100644 --- a/default.nix +++ b/default.nix @@ -39,11 +39,9 @@ let in # When building for linux (but not in nix-shell) we build statically -let staticpkgs = - if nixpkgs.stdenv.isDarwin - then nixpkgs - else nixpkgs.pkgsMusl; in +let is_static = !nixpkgs.stdenv.isDarwin; in +let staticpkgs = if is_static then nixpkgs.pkgsMusl else nixpkgs; in # This branches on the pkgs, which is either # normal nixpkgs (nix-shell, darwin) @@ -76,14 +74,14 @@ let darwin_standalone = let ocaml_exe = name: bin: let profile = - if nixpkgs.stdenv.isDarwin - then "release" - else "release-static"; + if is_static + then "release-static" + else "release"; drv = staticpkgs.stdenv.mkDerivation { inherit name; - ${if nixpkgs.stdenv.isDarwin then null else "allowedRequisites"} = []; + ${if is_static then "allowedRequisites" else null} = []; src = subpath ./src; From 25bb2238f56043716b982f1d079efaf7f06d7062 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Fri, 21 Feb 2020 18:16:32 +0000 Subject: [PATCH 1052/1176] type argument infernce, first stab --- src/mo_frontend/typing.ml | 17 ++++- src/mo_types/type.ml | 145 ++++++++++++++++++++++++++++++++++++++ src/mo_types/type.mli | 3 + 3 files changed, 163 insertions(+), 2 deletions(-) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 541fc20b47c..6c67805ddcc 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -879,12 +879,25 @@ and infer_exp'' env exp : T.typ = "expected function type, but expression produces type\n %s" (T.string_of_typ_expand t1) in - let ts = check_inst_bounds env tbs typs exp.at in + let ts, check_arg = + if tbs <> [] && inst.it = [] then + let t2 = infer_exp env exp2 in + let cts = T.open_binds tbs in + let cs = List.map (fun t -> match t with T.Con(c,_) -> c | _ -> assert false) cts in + match T.match_typ cs t2 (T.open_ cts t_arg) with + | Some ts -> + check_typ_bounds env tbs ts (List.map (fun _ -> Source.no_region) ts) exp.at; + ts, + fun env t_arg exp -> + if not (T.sub t2 t_arg) then + error env exp.at "cannot infer type arguments due to subtyping" + | None -> error env exp.at "cannot infer type arguments" + else check_inst_bounds env tbs typs exp.at, check_exp in inst.note <- ts; let t_arg = T.open_ ts t_arg in let t_ret = T.open_ ts t_ret in if not env.pre then begin - check_exp env t_arg exp2; + check_arg env t_arg exp2; if Type.is_shared_sort sort then begin if not (T.concrete t_arg) then error env exp1.at diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index b713dcf479b..f252e7e5df9 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -1345,3 +1345,148 @@ let rec string_of_typ_expand t = ) | _ -> s + + +(* Matching *) + +let match_typ cs t1 t2 = + +let flexible c = List.exists (Con.eq c) cs +in + +(* let rigid c = not (flexible c) +in + *) + +let rec match_list p inst xs1 xs2 = + (match (xs1, xs2) with + | (x1::xs1, x2::xs2) -> + (match p inst x1 x2 with + | Some inst -> match_list p inst xs1 xs2 + | None -> None) + | [], [] -> Some inst + | _, _ -> None) +in + +let rec match_typ inst t1 t2 = + match t1, t2 with + | Pre, _ | _, Pre -> + assert false + | Any, Any -> + Some inst + | Non, Non -> + Some inst + | Con (con1, ts1), Con (con2, ts2) -> + (match Con.kind con1, Con.kind con2 with + | Def (tbs, t), _ -> (* TBR this may fail to terminate *) + match_typ inst (open_ ts1 t) t2 + | _, Def (tbs, t) -> (* TBR this may fail to terminate *) + match_typ inst t1 (open_ ts2 t) + | _ when Con.eq con1 con2 -> + match_list match_typ inst ts1 ts2 + | _ -> + None + ) + | Con (con1, ts1), t2 -> + (match Con.kind con1, t2 with + | Def (tbs, t), _ -> (* TBR this may fail to terminate *) + match_typ inst (open_ ts1 t) t2 + | _ -> None + ) + | t1, Con (con2, ts2) -> + (match Con.kind con2 with + | Def (tbs, t) -> (* TBR this may fail to terminate *) + match_typ inst t1 (open_ ts2 t) + | Abs(tbs,_) -> + if flexible con2 then + match ConEnv.find_opt con2 inst with + | Some t1' -> match_typ inst t1 t1' (* just check equality instead ? *) + | None -> Some (ConEnv.add con2 t1 inst) + else None + ) + | Prim p1, Prim p2 when p1 = p2 -> + Some inst + | Obj (s1, tfs1), Obj (s2, tfs2) -> + if s1 = s2 then + match_fields inst tfs1 tfs2 + else None + | Array t1', Array t2' -> + match_typ inst t1' t2' + | Opt t1', Opt t2' -> + match_typ inst t1' t2' + | Variant fs1, Variant fs2 -> + match_tags inst fs1 fs2 + | Tup ts1, Tup ts2 -> + match_list match_typ inst ts1 ts2 + | Func (s1, c1, tbs1, t11, t12), Func (s2, c2, tbs2, t21, t22) -> + if s1 = s2 && c1 = c2 then + (match match_binds inst tbs1 tbs2 with + | Some (inst, ts) -> + (match match_list match_typ inst (List.map (open_ ts) t21) (List.map (open_ ts) t11) with + | Some inst -> + match_list match_typ inst (List.map (open_ ts) t12) (List.map (open_ ts) t22) + | None -> None) + | None -> None + ) + else None + | Async (t11, t12), Async (t21, t22) -> + (match match_typ inst t11 t21 with + | Some inst -> match_typ inst t12 t22 + | None -> None) + | Mut t1', Mut t2' -> + match_typ inst t1' t2' + | Typ c1, Typ c2 -> + if eq t1 t2 then Some inst else None + | _, _ -> None + +and match_fields inst tfs1 tfs2 = + (* Assume that tfs1 and tfs2 are sorted. *) + match tfs1, tfs2 with + | [], [] -> + Some inst + | tf1::tfs1', tf2::tfs2' -> + (match compare_field tf1 tf2 with + | 0 -> + (match match_typ inst tf1.typ tf2.typ with + | Some inst -> + match_fields inst tfs1' tfs2' + | None -> None) + | _ -> None + ) + | _, _ -> None +and match_tags inst tfs1 tfs2 = + (* Assume that tfs1 and tfs2 are sorted. *) + match tfs1, tfs2 with + | [], [] -> + Some inst + | tf1::tfs1', tf2::tfs2' -> + (match compare_field tf1 tf2 with + | 0 -> + (match match_typ inst tf1.typ tf2.typ with + | Some inst -> + match_fields inst tfs1' tfs2' + | None -> None) + | _ -> None + ) + | _, _ -> None + +and match_binds inst tbs1 tbs2 = + let ts = open_binds tbs2 in + match match_list (match_bind ts) inst tbs2 tbs1 with + | Some inst -> Some (inst, ts) + | None -> None + +and match_bind ts inst tb1 tb2 = + match_typ inst (open_ ts tb1.bound) (open_ ts tb2.bound) + +in + match match_typ ConEnv.empty t1 t2 with + | Some inst -> + (* default undetermined to Non *) + Some (List.map + (fun c -> + match ConEnv.find_opt c inst with + | None -> Non + | Some t -> t) cs) + | None -> None + diff --git a/src/mo_types/type.mli b/src/mo_types/type.mli index acbcb3ccc99..0c8effa06be 100644 --- a/src/mo_types/type.mli +++ b/src/mo_types/type.mli @@ -226,3 +226,6 @@ val string_of_kind : kind -> string val strings_of_kind : kind -> string * string * string val string_of_typ_expand : typ -> string +(* Matching *) + +val match_typ : con list -> typ -> typ -> typ list option From aa567d1765ff44f5588cc26d2911ef192b595739 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Fri, 21 Feb 2020 18:48:46 +0000 Subject: [PATCH 1053/1176] inference test --- test/fail/inference.mo | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 test/fail/inference.mo diff --git a/test/fail/inference.mo b/test/fail/inference.mo new file mode 100644 index 00000000000..59865a00580 --- /dev/null +++ b/test/fail/inference.mo @@ -0,0 +1,24 @@ +func id(x:T):T { x }; +ignore id(1); +ignore id(1); + +func swap(x:T,y:U):(U,T){(y,x)}; +ignore swap(1,true); +ignore swap(true,1); + +type N = (T->T,T)->T; + +func zero(f:T->T,z:T):T{z}; + +func succ(n:N):N { + func (f:T->T,z:T) : T { f(n(f,z))} +}; + +ignore zero; +ignore succ(zero); +ignore succ(succ(zero)); + +func app(f: T-> U, x:T) : U { f(x); }; +func compose(f: T -> U, g : U-> V) : T->V { func x { g (f(x))} }; + +ignore compose(succ,succ); \ No newline at end of file From b86d8796b47433b9b98d91eb10fa0338a604f28c Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Sat, 22 Feb 2020 00:08:10 +0000 Subject: [PATCH 1054/1176] avoid looping; more examples --- src/mo_types/type.ml | 30 +++++++++++++++--------------- test/fail/inference.mo | 35 ++++++++++++++++++++++++++++++++--- 2 files changed, 47 insertions(+), 18 deletions(-) diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index f252e7e5df9..b2e0be33db5 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -1354,9 +1354,8 @@ let match_typ cs t1 t2 = let flexible c = List.exists (Con.eq c) cs in -(* let rigid c = not (flexible c) +let rigid c = not (flexible c) in - *) let rec match_list p inst xs1 xs2 = (match (xs1, xs2) with @@ -1369,6 +1368,7 @@ let rec match_list p inst xs1 xs2 = in let rec match_typ inst t1 t2 = + (* Printf.printf "%s , %s\n" (string_of_typ t1) (string_of_typ t2); *) match t1, t2 with | Pre, _ | _, Pre -> assert false @@ -1376,23 +1376,17 @@ let rec match_typ inst t1 t2 = Some inst | Non, Non -> Some inst - | Con (con1, ts1), Con (con2, ts2) -> + | Con (con1, ts1), Con (con2, ts2) when rigid con2-> (match Con.kind con1, Con.kind con2 with + | k1, k2 when eq_kind k1 k2 -> + match_list match_typ inst ts1 ts2 | Def (tbs, t), _ -> (* TBR this may fail to terminate *) - match_typ inst (open_ ts1 t) t2 + None (* match_typ inst (open_ ts1 t) t2 *) | _, Def (tbs, t) -> (* TBR this may fail to terminate *) - match_typ inst t1 (open_ ts2 t) - | _ when Con.eq con1 con2 -> - match_list match_typ inst ts1 ts2 + None (* match_typ inst t1 (open_ ts2 t) *) | _ -> None ) - | Con (con1, ts1), t2 -> - (match Con.kind con1, t2 with - | Def (tbs, t), _ -> (* TBR this may fail to terminate *) - match_typ inst (open_ ts1 t) t2 - | _ -> None - ) | t1, Con (con2, ts2) -> (match Con.kind con2 with | Def (tbs, t) -> (* TBR this may fail to terminate *) @@ -1400,10 +1394,16 @@ let rec match_typ inst t1 t2 = | Abs(tbs,_) -> if flexible con2 then match ConEnv.find_opt con2 inst with - | Some t1' -> match_typ inst t1 t1' (* just check equality instead ? *) + | Some t1' -> if eq t1 t1' then Some inst else None (* just check equality instead ? *) | None -> Some (ConEnv.add con2 t1 inst) else None ) + | Con (con1, ts1), t2 -> + (match Con.kind con1, t2 with + | Def (tbs, t), _ -> (* TBR this may fail to terminate *) + match_typ inst (open_ ts1 t) t2 + | _ -> None + ) | Prim p1, Prim p2 when p1 = p2 -> Some inst | Obj (s1, tfs1), Obj (s2, tfs2) -> @@ -1422,7 +1422,7 @@ let rec match_typ inst t1 t2 = if s1 = s2 && c1 = c2 then (match match_binds inst tbs1 tbs2 with | Some (inst, ts) -> - (match match_list match_typ inst (List.map (open_ ts) t21) (List.map (open_ ts) t11) with + (match match_list match_typ inst (List.map (open_ ts) t11) (List.map (open_ ts) t21) with | Some inst -> match_list match_typ inst (List.map (open_ ts) t12) (List.map (open_ ts) t22) | None -> None) diff --git a/test/fail/inference.mo b/test/fail/inference.mo index 59865a00580..2ad02a4f326 100644 --- a/test/fail/inference.mo +++ b/test/fail/inference.mo @@ -11,14 +11,43 @@ type N = (T->T,T)->T; func zero(f:T->T,z:T):T{z}; func succ(n:N):N { - func (f:T->T,z:T) : T { f(n(f,z))} + func (f:T->T,z:T) : T { f(n/**/(f,z))} }; ignore zero; ignore succ(zero); -ignore succ(succ(zero)); +ignore succ(succ zero); func app(f: T-> U, x:T) : U { f(x); }; + +ignore app/**/(succ,zero); + func compose(f: T -> U, g : U-> V) : T->V { func x { g (f(x))} }; -ignore compose(succ,succ); \ No newline at end of file +ignore compose((func(x:Int):Int=x),(func(x:Int):Int=x)); +ignore compose/**/(succ,succ); + + + +type List = ?(T,List); +type List2 = ?(T,List2); + +func cons(h:T,t:List):List {?(h,t)}; +func nil():List{ null }; + +ignore nil(); +ignore cons(1,nil()); +ignore cons(1,cons(2,nil())); +ignore cons(1,cons(2,null:List)); +ignore cons(1,cons(2,null:List2:List)); +ignore cons(1,cons(2,null:List2)); //fails + +func curry(f : (A,B)->C) : A->B->C { + func(a:A): B->C { func(b:B):C { f(a,b) } } +}; + +func add(m:N,n:N):N { m/**/(succ,n) }; + +func mult1(m:N,n:N):N { m/**/(func (a:N) : N { add(a,n)},zero) }; + +func mult2(m:N,n:N):N { m/**/(curry/**/ add n, zero) }; From 476d7bc01c19998d9c40e888e80ed8227688d3b7 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Sat, 22 Feb 2020 09:00:16 +0100 Subject: [PATCH 1055/1176] RTS: Track canister lifecycle state machien This module models the life cycle of a canister as a very simple state machine, keeps track of the current state of the canister, and traps noisily if an unexpected transition happens. Such a transition would either be a bug in the underlying system, or in our RTS. --- src/codegen/compile.ml | 110 +++++++++++++++++++++++++++++++---- test/run-drun/empty-actor.mo | 8 ++- 2 files changed, 104 insertions(+), 14 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 95f96810be1..126f472fcc0 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -548,7 +548,7 @@ let from_0_to_n env mk_body = let load_unskewed_ptr : G.t = G.i (Load {ty = I32Type; align = 2; offset = 0l; sz = None}) -let _store_unskewed_ptr : G.t = +let store_unskewed_ptr : G.t = G.i (Store {ty = I32Type; align = 2; offset = 0l; sz = None}) let load_ptr : G.t = @@ -893,11 +893,11 @@ module Stack = struct We sometimes use the stack space if we need small amounts of scratch space. *) - let end_of_stack = page_size (* 64k of stack *) + let end_ = page_size (* 64k of stack *) let register_globals env = (* stack pointer *) - E.add_global32 env "__stack_pointer" Mutable end_of_stack; + E.add_global32 env "__stack_pointer" Mutable end_; E.export_global env "__stack_pointer" let get_stack_ptr env = @@ -2797,6 +2797,78 @@ module Tuple = struct end (* Tuple *) +module Lifecycle = struct + (* + This module models the life cycle of a canister as a very simple state machine, + keeps track of the current state of the canister, and traps noisily if an + unexpected transition happens. Such a transition would either be a bug in the + underlying system, or in our RTS. + *) + + type state = + | PreInit + (* We do not use the (start) function when compiling canisters, so skip + these two: + | InStart + | Started (* (start) has run *) + *) + | InInit (* canister_init *) + | Running (* basic steady state *) + | InUpdate + | InQuery + | PostQuery (* an invalid state *) + (* To be added later: InPreUpgrade PostPreUpgrade InPostUpgrade *) + + let int_of_state = function + | PreInit -> 0l (* Automatically null *) + (* + | InStart -> 1l + | Started -> 2l + *) + | InInit -> 3l + | Running -> 4l + | InUpdate -> 5l + | InQuery -> 6l + | PostQuery -> 7l + + let ptr = Stack.end_ + let end_ = Int32.add Stack.end_ Heap.word_size + + (* Which states may come before this *) + let pre_states = function + | PreInit -> [] + (* + | InStart -> [PreInit] + | Started -> [InStart] + *) + | InInit -> [PreInit] + | Running -> [InInit; InUpdate] + | InUpdate -> [Running] + | InQuery -> [Running] + | PostQuery -> [InQuery] + + let trans env new_state = + let name = "trans_state" ^ Int32.to_string (int_of_state new_state) in + Func.share_code0 env name [] (fun env -> + G.block_ [] ( + let rec go = function + | [] -> E.trap_with env "internal error: unexpected state" + | (s::ss) -> + compile_unboxed_const (int_of_state s) ^^ + compile_unboxed_const ptr ^^ load_unskewed_ptr ^^ + G.i (Compare (Wasm.Values.I32 I32Op.Eq)) ^^ + G.if_ [] (G.i (Br (nr 1l))) G.nop ^^ + go ss + in go (pre_states new_state) + ) ^^ + compile_unboxed_const ptr ^^ + compile_unboxed_const (int_of_state new_state) ^^ + store_unskewed_ptr + ) + +end (* Lifecycle *) + + module Dfinity = struct (* Dfinity-specific stuff: System imports, databufs etc. *) @@ -2921,15 +2993,16 @@ module Dfinity = struct edesc = nr (TableExport (nr 0l)) }) - let export_start env start_fi = + let export_init env start_fi = assert (E.mode env = Flags.ICMode || E.mode env = Flags.StubMode); - (* Create an empty message *) let empty_f = Func.of_body env [] [] (fun env1 -> G.i (Call (nr start_fi)) ^^ + Lifecycle.trans env Lifecycle.InInit ^^ (* Collect garbage *) - G.i (Call (nr (E.built_in env1 "collect"))) + G.i (Call (nr (E.built_in env1 "collect"))) ^^ + Lifecycle.trans env Lifecycle.Running ) in - let fi = E.add_fun env "start_stub" empty_f in + let fi = E.add_fun env "canister_init" empty_f in E.add_export env (nr { name = Wasm.Utf8.decode "canister_init"; edesc = nr (FuncExport (nr fi)) @@ -4664,14 +4737,25 @@ module FuncDec = struct mk_body env ae2 )) + let message_start env sort = match sort with + | Type.Shared Type.Write -> + Lifecycle.trans env Lifecycle.InUpdate + | Type.Shared Type.Query -> + Lifecycle.trans env Lifecycle.InQuery + | _ -> assert false + let message_cleanup env sort = match sort with - | Type.Shared Type.Write -> G.i (Call (nr (E.built_in env "collect"))) - | Type.Shared Type.Query -> G.i Nop + | Type.Shared Type.Write -> + G.i (Call (nr (E.built_in env "collect"))) ^^ + Lifecycle.trans env Lifecycle.Running + | Type.Shared Type.Query -> + Lifecycle.trans env Lifecycle.PostQuery | _ -> assert false let compile_const_message outer_env outer_ae sort control args mk_body ret_tys at : E.func_with_names = let ae0 = VarEnv.mk_fun_ae outer_ae in Func.of_body outer_env [] [] (fun env -> G.with_region at ( + message_start env sort ^^ (* reply early for a oneway *) (if control = Type.Returns then @@ -4805,6 +4889,7 @@ module FuncDec = struct let closures_to_reply_reject_callbacks env ts = let reply_name = "@callback<" ^ Serialization.typ_id (Type.Tup ts) ^ ">" in Func.define_built_in env reply_name ["env", I32Type] [] (fun env -> + message_start env (Type.Shared Type.Write) ^^ (* Look up closure *) let (set_closure, get_closure) = new_local env "closure" in G.i (LocalGet (nr 0l)) ^^ @@ -4824,6 +4909,7 @@ module FuncDec = struct let reject_name = "@reject_callback" in Func.define_built_in env reject_name ["env", I32Type] [] (fun env -> + message_start env (Type.Shared Type.Write) ^^ (* Look up closure *) let (set_closure, get_closure) = new_local env "closure" in G.i (LocalGet (nr 0l)) ^^ @@ -4911,6 +4997,8 @@ module FuncDec = struct Func.define_built_in env name [] [] (fun env -> let (set_closure, get_closure) = new_local env "closure" in + message_start env (Type.Shared Type.Write) ^^ + (* Check that we are calling this *) Dfinity.assert_caller_self env ^^ @@ -6960,7 +7048,7 @@ and conclude_module env start_fi_o = | Some rts -> Linking.LinkModule.link emodule "rts" rts let compile mode module_name rts (progs : Ir.prog list) : Wasm_exts.CustomModule.extended_module = - let env = E.mk_global mode rts Dfinity.trap_with Stack.end_of_stack in + let env = E.mk_global mode rts Dfinity.trap_with Lifecycle.end_ in Heap.register_globals env; Stack.register_globals env; @@ -6972,7 +7060,7 @@ let compile mode module_name rts (progs : Ir.prog list) : Wasm_exts.CustomModule let start_fun = compile_start_func env progs in let start_fi = E.add_fun env "start" start_fun in let start_fi_o = match E.mode env with - | Flags.ICMode | Flags.StubMode -> Dfinity.export_start env start_fi; None + | Flags.ICMode | Flags.StubMode -> Dfinity.export_init env start_fi; None | Flags.WasmMode | Flags.WASIMode-> Some (nr start_fi) in conclude_module env start_fi_o diff --git a/test/run-drun/empty-actor.mo b/test/run-drun/empty-actor.mo index b0a0b4da549..2de5c614a75 100644 --- a/test/run-drun/empty-actor.mo +++ b/test/run-drun/empty-actor.mo @@ -3,10 +3,12 @@ actor {}; // The prelude should not require any code (besides maybe a call to collect) at runtime // CHECK: (func $start (type 4)) -// CHECK: (func $start_stub (type 4) +// CHECK: (func $canister_init (type 4) // CHECK-NEXT: call $start -// CHECK-NEXT: call $collect) +// CHECK-NEXT: call $trans_state +// CHECK-NEXT: call $collect +// CHECK-NEXT: call $trans_state -// CHECK: (export "canister_init" (func $start_stub)) +// CHECK: (export "canister_init" (func $canister_init)) From d285705e678989cc8322bf630a2c0012ac643033 Mon Sep 17 00:00:00 2001 From: Bas van Dijk Date: Mon, 24 Feb 2020 11:54:12 +0100 Subject: [PATCH 1056/1176] nix: specify a sha256 for fetching sources.nix (#1234) Without the hash Nix will check the URL each time you evaluate. This makes it impossible to work offline unless you know about `--option tarball-ttl 1000000`. See: https://dfinity.slack.com/archives/CL7Q2RXUM/p1582367096114000 --- nix/default.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/nix/default.nix b/nix/default.nix index 41ee345fa4d..40344472c4e 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -1,6 +1,9 @@ { system ? builtins.currentSystem }: let - sourcesnix = builtins.fetchurl https://raw.githubusercontent.com/nmattia/niv/506b896788d9705899592a303de95d8819504c55/nix/sources.nix; + sourcesnix = builtins.fetchurl { + url = https://raw.githubusercontent.com/nmattia/niv/506b896788d9705899592a303de95d8819504c55/nix/sources.nix; + sha256 = "007bgq4zy1mjnnkbmaaxvvn4kgpla9wkm0d3lfrz3y1pa3wp9ha1"; + }; nixpkgs_src = (import sourcesnix { sourcesFile = ./sources.json; inherit pkgs; }).nixpkgs; pkgs = From 5dc2ad3c27112335531f571cf378d0c4fd8e2925 Mon Sep 17 00:00:00 2001 From: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> Date: Tue, 25 Feb 2020 13:38:24 +0100 Subject: [PATCH 1057/1176] Some IDE robustness fixes (#1235) * Handles decoding failures for messages more graceful * Handles named module definitions for go-to-definition * nit: reduces number of qualifiers --- src/languageServer/declaration_index.ml | 6 +++- src/languageServer/languageServer.ml | 46 ++++++++++++------------- 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/src/languageServer/declaration_index.ml b/src/languageServer/declaration_index.ml index 18c76d70893..84e38015f56 100644 --- a/src/languageServer/declaration_index.ml +++ b/src/languageServer/declaration_index.ml @@ -250,7 +250,11 @@ let unwrap_module_ast (lib : Syntax.lib): Syntax.exp_field list option = | Syntax.BlockE decs -> (match Lib.List.last decs with | {it=Syntax.ExpD {it= Syntax.ObjE(_,fields) ;_} ;_} -> Some fields - | _ -> None) + | {it=Syntax.LetD(_, {it= Syntax.ObjE(_,fields) ;_}) ;_} -> Some fields + | d -> + Debug.log "unwrap_module_ast" + (Wasm.Sexpr.to_string 80 (Arrange.dec d)); + None) | _ -> None diff --git a/src/languageServer/languageServer.ml b/src/languageServer/languageServer.ml index 2a78b8b946f..6170028f24a 100644 --- a/src/languageServer/languageServer.ml +++ b/src/languageServer/languageServer.ml @@ -133,27 +133,7 @@ let start entry_point debug = files_with_diags := List.map snd diags_by_file; List.iter (fun (diags, uri) -> publish_diagnostics uri diags) diags_by_file in - let rec loop () = - let clength = read_line () in - let cl = "Content-Length: " in - let cll = String.length cl in - let num = - (int_of_string - (String.trim - (String.sub - clength - cll - (String.length(clength) - cll - 1)))) + 2 in - let buffer = Buffer.create num in - Buffer.add_channel buffer stdin num; - let raw = String.trim (Buffer.contents buffer) in - let message = Lsp_j.incoming_message_of_string raw in - let message_id = message.Lsp_t.incoming_message_id in - - (match (message_id, message.Lsp_t.incoming_message_params) with - - (* Request messages *) - + let handle_message raw = function | (Some id, `Initialize params) -> client_capabilities := Some params.Lsp_t.initialize_params_capabilities; let completion_options = @@ -244,7 +224,6 @@ let start entry_point debug = decl_index := ix; msgs' in sync_diagnostics msgs - (* Notification messages *) | (None, `Initialized _) -> sync_diagnostics !startup_diags; @@ -256,8 +235,10 @@ let start entry_point debug = response_result_message id (`ShutdownResponse None) |> Lsp_j.string_of_response_message |> send_response + | (_, `Exit _) -> if !shutdown then exit 0 else exit 1 + | (Some id, `CompletionRequest params) -> let uri = params @@ -285,8 +266,25 @@ let start entry_point debug = |> send_response (* Unhandled messages *) | _ -> - log_to_file "unhandled message" raw; - ); + log_to_file "unhandled message" raw in + let rec loop () = + let clength = read_line () in + let cl = "Content-Length: " in + let cll = String.length cl in + let num = + int_of_string + String.(trim (sub clength cll (length(clength) - cll - 1))) + 2 in + let buffer = Buffer.create num in + Buffer.add_channel buffer stdin num; + let raw = String.trim (Buffer.contents buffer) in + let message = + try Some (Lsp_j.incoming_message_of_string raw) + with _ -> None in + (match message with + | None -> Debug.log "decoding error" raw + | Some message -> + let message_id = message.Lsp_t.incoming_message_id in + handle_message raw (message_id, message.Lsp_t.incoming_message_params)); loop () in loop () From 7a262e5b54b5989676c346618450167cf60ad6d8 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 25 Feb 2020 13:50:54 +0100 Subject: [PATCH 1058/1176] RTS: Put hash list of objects into static memory (#1233) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit the things I do when I can’t sleep on a plane. (And unfortunately, this was quicker than I hoped…) Anywasys, the resulting code is simpler, allocates less etc. Feels good. --- src/codegen/compile.ml | 127 ++++++++++++++++++++++------------------- 1 file changed, 67 insertions(+), 60 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 95f96810be1..0d0c283e611 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -2292,9 +2292,17 @@ end (* Prim *) module Object = struct (* An object has the following heap layout: - ┌─────┬──────────┬─────────────┬─────────────┬───┐ - │ tag │ n_fields │ field_hash1 │ field_data1 │ … │ - └─────┴──────────┴─────────────┴─────────────┴───┘ + ┌─────┬──────────┬──────────┬─────────────┬───┐ + │ tag │ n_fields │ hash_ptr │ field_data1 │ … │ + └─────┴──────────┴──────────┴─────────────┴───┘ + ┌────────────╯ + ↓ + ┌─────────────┬──────────────┬───┐ + │ field_hash1 │ field_hash21 │ … │ + └─────────────┴──────────────┴───┘ + + The field hash array lives in static memory (so no size header needed). + The hash_ptr is skewed. The field_data for immutable fields simply point to the value. @@ -2307,10 +2315,11 @@ module Object = struct await-translation of objects, and get rid of this indirection. *) - let header_size = Int32.add Tagged.header_size 1l + let header_size = Int32.add Tagged.header_size 2l (* Number of object fields *) let size_field = Int32.add Tagged.header_size 0l + let hash_ptr_field = Int32.add Tagged.header_size 1l module FieldEnv = Env.Make(String) @@ -2328,74 +2337,75 @@ module Object = struct List.mapi (fun i (_h,n) -> (n,Int32.of_int i)) |> List.fold_left (fun m (n,i) -> FieldEnv.add n i m) FieldEnv.empty in - let sz = Int32.of_int (FieldEnv.cardinal name_pos_map) in - - (* Allocate memory *) - let (set_ri, get_ri, ri) = new_local_ env I32Type "obj" in - Heap.alloc env (Int32.add header_size (Int32.mul 2l sz)) ^^ - set_ri ^^ - - (* Set tag *) - get_ri ^^ - Tagged.store Tagged.Object ^^ - - (* Set size *) - get_ri ^^ - compile_unboxed_const sz ^^ - Heap.store_field size_field ^^ - - let hash_position env n = - let i = FieldEnv.find n name_pos_map in - Int32.add header_size (Int32.mul 2l i) in - let field_position env n = - let i = FieldEnv.find n name_pos_map in - Int32.add header_size (Int32.add (Int32.mul 2l i) 1l) in - - (* Write all the fields *) - let init_field (name, mk_is) : G.t = - (* Write the hash *) - get_ri ^^ - compile_unboxed_const (Mo_types.Hash.hash name) ^^ - Heap.store_field (hash_position env name) ^^ - (* Write the pointer to the indirection *) - get_ri ^^ - mk_is () ^^ - Heap.store_field (field_position env name) - in - G.concat_map init_field fs ^^ - - (* Return the pointer to the object *) - get_ri + let sz = Int32.of_int (FieldEnv.cardinal name_pos_map) in + + (* Create hash array *) + let hashes = fs |> + List.map (fun (n,_) -> Mo_types.Hash.hash n) |> + List.sort compare in + let data = String.concat "" (List.map bytes_of_int32 hashes) in + let hash_ptr = E.add_static_bytes env data in + + (* Allocate memory *) + let (set_ri, get_ri, ri) = new_local_ env I32Type "obj" in + Heap.alloc env (Int32.add header_size sz) ^^ + set_ri ^^ + + (* Set tag *) + get_ri ^^ + Tagged.store Tagged.Object ^^ + + (* Set size *) + get_ri ^^ + compile_unboxed_const sz ^^ + Heap.store_field size_field ^^ + + (* Set hash_ptr *) + get_ri ^^ + compile_unboxed_const hash_ptr ^^ + Heap.store_field hash_ptr_field ^^ + + (* Write all the fields *) + let init_field (name, mk_is) : G.t = + (* Write the pointer to the indirection *) + get_ri ^^ + mk_is () ^^ + let i = FieldEnv.find name name_pos_map in + let offset = Int32.add header_size i in + Heap.store_field offset + in + G.concat_map init_field fs ^^ + + (* Return the pointer to the object *) + get_ri (* Returns a pointer to the object field (without following the indirection) *) let idx_hash_raw env = Func.share_code2 env "obj_idx" (("x", I32Type), ("hash", I32Type)) [I32Type] (fun env get_x get_hash -> - let (set_f, get_f) = new_local env "f" in - let (set_r, get_r) = new_local env "r" in + let (set_h_ptr, get_h_ptr) = new_local env "h_ptr" in - get_x ^^ - Heap.load_field size_field ^^ + get_x ^^ Heap.load_field hash_ptr_field ^^ set_h_ptr ^^ + + get_x ^^ Heap.load_field size_field ^^ (* Linearly scan through the fields (binary search can come later) *) from_0_to_n env (fun get_i -> get_i ^^ - compile_mul_const 2l ^^ - compile_add_const header_size ^^ compile_mul_const Heap.word_size ^^ - get_x ^^ + get_h_ptr ^^ G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ - set_f ^^ - - get_f ^^ - Heap.load_field 0l ^^ (* the hash field *) + Heap.load_field 0l ^^ get_hash ^^ G.i (Compare (Wasm.Values.I32 I32Op.Eq)) ^^ G.if_ [] - ( get_f ^^ - compile_add_const Heap.word_size ^^ - set_r + ( get_i ^^ + compile_add_const header_size ^^ + compile_mul_const Heap.word_size ^^ + get_x ^^ + G.i (Binary (Wasm.Values.I32 I32Op.Add)) ^^ + G.i Return ) G.nop ) ^^ - get_r + E.trap_with env "internal error: object field not found" ) (* Returns a pointer to the object field (possibly following the indirection) *) @@ -3130,7 +3140,6 @@ module HeapTraversal = struct ; Tagged.Object, get_x ^^ Heap.load_field Object.size_field ^^ - compile_mul_const 2l ^^ compile_add_const Object.header_size ; Tagged.Closure, get_x ^^ @@ -3215,8 +3224,6 @@ module HeapTraversal = struct from_0_to_n env (fun get_i -> get_i ^^ - compile_mul_const 2l ^^ - compile_add_const 1l ^^ compile_add_const Object.header_size ^^ compile_mul_const Heap.word_size ^^ get_x ^^ From fe5f3f310e04273b12b25eb9330761b8342c67c9 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 25 Feb 2020 13:41:57 +0000 Subject: [PATCH 1059/1176] more examples --- test/fail/inference.mo | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/fail/inference.mo b/test/fail/inference.mo index 2ad02a4f326..2dde11692cd 100644 --- a/test/fail/inference.mo +++ b/test/fail/inference.mo @@ -51,3 +51,17 @@ func add(m:N,n:N):N { m/**/(succ,n) }; func mult1(m:N,n:N):N { m/**/(func (a:N) : N { add(a,n)},zero) }; func mult2(m:N,n:N):N { m/**/(curry/**/ add n, zero) }; + + +func tricky(f : T -> T) { }; + +tricky(func f(x:Any):None { f(x);}); +tricky(func f(x:Any):None { f(x);}); +ignore func () { tricky(func f(x:Any):None{f(x)}) }; + +//ignore tricky(func f(x:Any):None { f(x);}); //requires Dolan style bi-matching + +func amb(f : T -> T): T->T { f }; +ignore amb(func f(x:Any):None { f(x);}) : None -> None; +ignore amb(func f(x:Any):None { f(x);}) : Any -> Any; + From 540bdeb041fde1e0fe83457dff1162c50d38ef14 Mon Sep 17 00:00:00 2001 From: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> Date: Wed, 26 Feb 2020 10:07:02 +0100 Subject: [PATCH 1060/1176] Some more IDE fixes for the demo (#1236) * Normalises file paths we get from the editor VSCode likes to send us URI's like: "file:///home/creek/code/qr/app/../src/alphanumeric.mo" * turns off templated completions until it can be configured --- src/languageServer/completion.ml | 3 ++- src/languageServer/declaration_index.ml | 2 +- src/languageServer/vfs.ml | 11 ++++++----- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/languageServer/completion.ml b/src/languageServer/completion.ml index d5acaefed17..432562d5e67 100644 --- a/src/languageServer/completion.ml +++ b/src/languageServer/completion.ml @@ -35,7 +35,8 @@ let string_of_item (item : Lsp_t.completion_item) : string = item.Lsp_t.completion_item_label let item_of_ide_decl (d : DI.ide_decl) : Lsp_t.completion_item = - let tmpl = template_of_ide_decl d in + (* let tmpl = template_of_ide_decl d in *) + let tmpl = DI.name_of_ide_decl d in match d with | DI.ValueDecl value -> Lsp_t.{ diff --git a/src/languageServer/declaration_index.ml b/src/languageServer/declaration_index.ml index 84e38015f56..ddcc88b765b 100644 --- a/src/languageServer/declaration_index.ml +++ b/src/languageServer/declaration_index.ml @@ -138,7 +138,7 @@ let shorten_import_path -> string -> string = fun pkg_map ic_aliases base path -> - let _ = Debug.log "shorten_import" path in + let _ = Debug.log "shorten_import" (Printf.sprintf "base: %s, path: %s" base path) in if Filename.extension path = ".did" then let idl_basename = Filename.basename path in diff --git a/src/languageServer/vfs.ml b/src/languageServer/vfs.ml index 4905e764fd9..5f38eb2d50c 100644 --- a/src/languageServer/vfs.ml +++ b/src/languageServer/vfs.ml @@ -20,11 +20,12 @@ let file_from_uri logger uri = let _ = logger "error" ("Failed to strip filename from: " ^ uri) in uri let abs_file_from_uri logger uri = - match Lib.String.chop_prefix "file://" uri with - | Some file -> file - | None -> - let _ = logger "error" ("Failed to strip filename from: " ^ uri) in - uri + Lib.FilePath.normalise + (match Lib.String.chop_prefix "file://" uri with + | Some file -> file + | None -> + let _ = logger "error" ("Failed to strip filename from: " ^ uri) in + uri) let empty = VfsStore.empty From 31aa7aeddff7a30c0e1bd046ace3a74b30ce4d3d Mon Sep 17 00:00:00 2001 From: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> Date: Wed, 26 Feb 2020 13:03:51 +0100 Subject: [PATCH 1061/1176] Normalises file paths before sending them to the editors (#1237) --- src/languageServer/vfs.ml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/languageServer/vfs.ml b/src/languageServer/vfs.ml index 5f38eb2d50c..34dbef00f99 100644 --- a/src/languageServer/vfs.ml +++ b/src/languageServer/vfs.ml @@ -12,7 +12,8 @@ type uri = string let file_uri_prefix = "file://" ^ Sys.getcwd () ^ "/" let uri_from_file path = - if Filename.is_relative path then file_uri_prefix ^ path else "file://" ^ path + "file://" ^ Lib.FilePath.make_absolute (Sys.getcwd ()) path + let file_from_uri logger uri = match Lib.String.chop_prefix file_uri_prefix uri with | Some file -> file From 414317ce9ddf1d571ee9d710eea40393d64abbeb Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 26 Feb 2020 15:59:55 +0000 Subject: [PATCH 1062/1176] prelimary implementation of bimatching - todo mut arrays, constructor argument bounds, hypothethical bounds, open bounds? --- src/mo_frontend/typing.ml | 4 +- src/mo_types/type.ml | 197 ++++++++++++++++++++++++++++++++++++++ src/mo_types/type.mli | 1 + test/fail/inference.mo | 31 +++++- 4 files changed, 229 insertions(+), 4 deletions(-) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 6c67805ddcc..91dab902fbb 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -884,13 +884,13 @@ and infer_exp'' env exp : T.typ = let t2 = infer_exp env exp2 in let cts = T.open_binds tbs in let cs = List.map (fun t -> match t with T.Con(c,_) -> c | _ -> assert false) cts in - match T.match_typ cs t2 (T.open_ cts t_arg) with + match T.bimatch_typ cs t2 (T.open_ cts t_arg) with | Some ts -> check_typ_bounds env tbs ts (List.map (fun _ -> Source.no_region) ts) exp.at; ts, fun env t_arg exp -> if not (T.sub t2 t_arg) then - error env exp.at "cannot infer type arguments due to subtyping" + error env exp.at "cannot infer type arguments due to subtyping\n %s is not a subtype of %s" (T.string_of_typ_expand t2) (T.string_of_typ_expand t_arg) | None -> error env exp.at "cannot infer type arguments" else check_inst_bounds env tbs typs exp.at, check_exp in inst.note <- ts; diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index b2e0be33db5..ab605c64035 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -1490,3 +1490,200 @@ in | Some t -> t) cs) | None -> None + + +(* Bi-Matching *) + +let bimatch_typ cs t1 t2 = + +let rel = ref SS.empty +in + +let flexible c = List.exists (Con.eq c) cs +in + +let rigid c = not (flexible c) +in + +let rec bimatch_list p inst any xs1 xs2 = + (match (xs1, xs2) with + | (x1::xs1, x2::xs2) -> + (match p inst any x1 x2 with + | Some inst -> bimatch_list p inst any xs1 xs2 + | None -> None) + | [], [] -> Some inst + | _, _ -> None) +in + +let rec bimatch_typ ((l,u) as inst) (any:ConSet.t) (t1:typ) (t2:typ) = + if t1 == t2 || SS.mem (t1, t2) !rel + then Some inst + else begin + rel := SS.add (t1, t2) !rel; + (* Printf.printf "%s %s\n" (!str t1) (!str t2); *) + match t1, t2 with + | Pre, _ | _, Pre -> + Some inst + | Any, Any -> + Some inst + | _, Any -> + Some inst + | Non, Non -> + Some inst + | Non, _ -> + Some inst + | _, Con (con2, ts2) when flexible con2 -> + assert (ts2 = []); + if ConSet.is_empty (ConSet.inter (cons t1 ConSet.empty) any) then + (match ConEnv.find_opt con2 l with + | Some t1' -> + let lub = lub t1 t1' in + Some (ConEnv.add con2 lub l, u) + | None -> Some (ConEnv.add con2 t1 l, u)) + else None + | Con (con1, ts1), _ when flexible con1 -> + assert (ts1 = []); + if ConSet.is_empty (ConSet.inter (cons t2 ConSet.empty) any) then + (match ConEnv.find_opt con1 u with + | Some t2' -> + let glb = glb t2 t2' in + Some (l, ConEnv.add con1 glb u) + | None -> Some (l, ConEnv.add con1 t2 u)) + else None + | Con (con1, ts1), Con (con2, ts2) -> + (match Con.kind con1, Con.kind con2 with + | Def (tbs, t), _ -> (* TBR this may fail to terminate *) + bimatch_typ inst any (open_ ts1 t) t2 + | _, Def (tbs, t) -> (* TBR this may fail to terminate *) + bimatch_typ inst any t1 (open_ ts2 t) + | _ when Con.eq con1 con2 -> + assert (ts1 = []); + assert (ts2 = []); + Some inst + | Abs (tbs, t), _ -> + bimatch_typ inst any (open_ ts1 t) t2 + ) + | Con (con1, ts1), t2 -> + (match Con.kind con1, t2 with + | Def (tbs, t), _ -> (* TBR this may fail to terminate *) + bimatch_typ inst any (open_ ts1 t) t2 + | Abs (tbs, t), _ -> + bimatch_typ inst any (open_ ts1 t) t2 + ) + | t1, Con (con2, ts2) -> + (match Con.kind con2 with + | Def (tbs, t) -> (* TBR this may fail to terminate *) + bimatch_typ inst any t1 (open_ ts2 t) + | _ -> None + ) + | Prim p1, Prim p2 when p1 = p2 -> + Some inst + | Prim p1, Prim p2 -> + if p1 = Nat && p2 = Int then Some inst else None + | Obj (s1, tfs1), Obj (s2, tfs2) -> + if s1 = s2 then + bimatch_fields inst any tfs1 tfs2 + else None + | Array t1', Array t2' -> + bimatch_typ inst any t1' t2' + | Opt t1', Opt t2' -> + bimatch_typ inst any t1' t2' + | Prim Null, Opt t2' -> + Some inst + | Variant fs1, Variant fs2 -> + bimatch_tags inst any fs1 fs2 + | Tup ts1, Tup ts2 -> + bimatch_list bimatch_typ inst any ts1 ts2 + | Func (s1, c1, tbs1, t11, t12), Func (s2, c2, tbs2, t21, t22) -> + if s1 = s2 && c1 = c2 then + (match bimatch_binds inst any tbs1 tbs2 with + | Some (inst, ts) -> + let any' = List.fold_right + (function Con(c,[]) -> ConSet.add c + | _ -> assert false) ts any in + (match + bimatch_list bimatch_typ inst any' (List.map (open_ ts) t21) (List.map (open_ ts) t11) + with + | Some inst -> + bimatch_list bimatch_typ inst any' (List.map (open_ ts) t12) (List.map (open_ ts) t22) + | None -> None) + | None -> None + ) + else None + | Async (t11, t12), Async (t21, t22) -> + if eq t11 t21 then (* TBR *) + bimatch_typ inst any t12 t22 + else None + | Mut t1', Mut t2' -> + (* TBR *) + bimatch_list bimatch_typ inst any [t1';t2'] [t2';t1'] + | Typ c1, Typ c2 -> + (* TBR *) + if eq t1 t2 then Some inst else None + | _, _ -> None + end + +and bimatch_fields inst any tfs1 tfs2 = + (* Assume that tfs1 and tfs2 are sorted. *) + match tfs1, tfs2 with + | [], [] -> + Some inst + | _, [] -> + Some inst + | tf1::tfs1', tf2::tfs2' -> + (match compare_field tf1 tf2 with + | 0 -> + (match bimatch_typ inst any tf1.typ tf2.typ with + | Some inst -> bimatch_fields inst any tfs1' tfs2' + | None -> None) + | -1 -> + bimatch_fields inst any tfs1' tfs2 + | _ -> None + ) + | _, _ -> None + +and bimatch_tags inst any tfs1 tfs2 = + (* Assume that tfs1 and tfs2 are sorted. *) + match tfs1, tfs2 with + | [], [] -> + Some inst + | [], _ -> + Some inst + | tf1::tfs1', tf2::tfs2' -> + (match compare_field tf1 tf2 with + | 0 -> + (match bimatch_typ inst any tf1.typ tf2.typ with + | Some inst -> bimatch_tags inst any tfs1' tfs2' + | None -> None) + | +1 -> + bimatch_tags inst any tfs1 tfs2' + | _ -> None + ) + | _, _ -> None + +and bimatch_binds inst any tbs1 tbs2 = + let ts = open_binds tbs2 in + match bimatch_list (bimatch_bind ts) inst any tbs2 tbs1 with + | Some inst -> Some (inst,ts) + | None -> None + +and bimatch_bind ts inst any tb1 tb2 = + bimatch_typ inst any (open_ ts tb1.bound) (open_ ts tb2.bound) + +in + match bimatch_typ (ConEnv.empty, ConEnv.empty) ConSet.empty t1 t2 with + | Some (l,u) -> + (* default undetermined to Non *) + (try + Some (List.map + (fun c -> + match ConEnv.find_opt c l, ConEnv.find_opt c u with + | None, None -> Non + | None, Some ub -> ub + | Some lb, None -> lb + | Some lb, Some ub -> + Printf.printf "ambiguous inst"; + if eq lb ub then ub else failwith "none") cs) + with _ -> None) + | None -> None + diff --git a/src/mo_types/type.mli b/src/mo_types/type.mli index 0c8effa06be..301bc4108c6 100644 --- a/src/mo_types/type.mli +++ b/src/mo_types/type.mli @@ -229,3 +229,4 @@ val string_of_typ_expand : typ -> string (* Matching *) val match_typ : con list -> typ -> typ -> typ list option +val bimatch_typ : con list -> typ -> typ -> typ list option diff --git a/test/fail/inference.mo b/test/fail/inference.mo index 2dde11692cd..cd6a12504cb 100644 --- a/test/fail/inference.mo +++ b/test/fail/inference.mo @@ -40,7 +40,7 @@ ignore cons(1,nil()); ignore cons(1,cons(2,nil())); ignore cons(1,cons(2,null:List)); ignore cons(1,cons(2,null:List2:List)); -ignore cons(1,cons(2,null:List2)); //fails +ignore cons(1,cons(2,null:List2)); func curry(f : (A,B)->C) : A->B->C { func(a:A): B->C { func(b:B):C { f(a,b) } } @@ -59,9 +59,36 @@ tricky(func f(x:Any):None { f(x);}); tricky(func f(x:Any):None { f(x);}); ignore func () { tricky(func f(x:Any):None{f(x)}) }; -//ignore tricky(func f(x:Any):None { f(x);}); //requires Dolan style bi-matching +ignore tricky(func f(x:Any):None { f(x);}); +ignore tricky(func f(x:None):Any { f(x);}); //requires Dolan style bi-matching +ignore tricky(func f(x:None):None { f(x);}); //requires Dolan style bi-matching func amb(f : T -> T): T->T { f }; ignore amb(func f(x:Any):None { f(x);}) : None -> None; ignore amb(func f(x:Any):None { f(x);}) : Any -> Any; + +func co(x : T,y : T):(){}; +ignore co(1,2); +ignore co(1,2:Int); +ignore co(1,true); +ignore co(1,2); +ignore co(1,2:Int); +ignore co(1,true); + + +func contra(f:(T,T) -> ()):(){}; +ignore contra(func (x:Nat,y:Nat) {}); +ignore contra(func (x:Nat,y:Int) {}); +ignore contra(func (x:Nat,y:Bool) {}); +ignore contra(func (x:Nat,y:Nat) {}); +ignore contra(func (x:Nat,y:Int) {}); +ignore contra(func (x:Nat,y:Bool) {}); + + +func coswap(x : T,y : T):(U,U){(y,x)}; +ignore coswap(1,2); // works (coz Int <: Nat) +ignore coswap(1,2:Int); // works (coz Int <: Nat) +ignore coswap(1,true); // doesn't work unless we lub with with bound + + From 5de6fc82c23df0f58767bd6755713d8aa86da5f4 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 26 Feb 2020 18:29:28 +0000 Subject: [PATCH 1063/1176] more changes --- src/mo_frontend/typing.ml | 2 +- src/mo_types/type.ml | 25 ++++++++++--------------- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 91dab902fbb..a2adadd4449 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -886,7 +886,7 @@ and infer_exp'' env exp : T.typ = let cs = List.map (fun t -> match t with T.Con(c,_) -> c | _ -> assert false) cts in match T.bimatch_typ cs t2 (T.open_ cts t_arg) with | Some ts -> - check_typ_bounds env tbs ts (List.map (fun _ -> Source.no_region) ts) exp.at; + check_typ_bounds env tbs ts (List.map (fun _ -> exp1.at) ts) exp.at; ts, fun env t_arg exp -> if not (T.sub t2 t_arg) then diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index ab605c64035..338eebd2bc4 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -1502,9 +1502,6 @@ in let flexible c = List.exists (Con.eq c) cs in -let rigid c = not (flexible c) -in - let rec bimatch_list p inst any xs1 xs2 = (match (xs1, xs2) with | (x1::xs1, x2::xs2) -> @@ -1524,12 +1521,8 @@ let rec bimatch_typ ((l,u) as inst) (any:ConSet.t) (t1:typ) (t2:typ) = match t1, t2 with | Pre, _ | _, Pre -> Some inst - | Any, Any -> - Some inst | _, Any -> Some inst - | Non, Non -> - Some inst | Non, _ -> Some inst | _, Con (con2, ts2) when flexible con2 -> @@ -1599,8 +1592,8 @@ let rec bimatch_typ ((l,u) as inst) (any:ConSet.t) (t1:typ) (t2:typ) = (match bimatch_binds inst any tbs1 tbs2 with | Some (inst, ts) -> let any' = List.fold_right - (function Con(c,[]) -> ConSet.add c - | _ -> assert false) ts any in + (function Con(c,[]) -> ConSet.add c | _ -> assert false) ts any + in (match bimatch_list bimatch_typ inst any' (List.map (open_ ts) t21) (List.map (open_ ts) t11) with @@ -1611,9 +1604,8 @@ let rec bimatch_typ ((l,u) as inst) (any:ConSet.t) (t1:typ) (t2:typ) = ) else None | Async (t11, t12), Async (t21, t22) -> - if eq t11 t21 then (* TBR *) - bimatch_typ inst any t12 t22 - else None + (* TBR *) + bimatch_list bimatch_typ inst any [t11;t21;t12] [t21;t11;t22] | Mut t1', Mut t2' -> (* TBR *) bimatch_list bimatch_typ inst any [t1';t2'] [t2';t1'] @@ -1673,7 +1665,6 @@ and bimatch_bind ts inst any tb1 tb2 = in match bimatch_typ (ConEnv.empty, ConEnv.empty) ConSet.empty t1 t2 with | Some (l,u) -> - (* default undetermined to Non *) (try Some (List.map (fun c -> @@ -1682,8 +1673,12 @@ in | None, Some ub -> ub | Some lb, None -> lb | Some lb, Some ub -> - Printf.printf "ambiguous inst"; - if eq lb ub then ub else failwith "none") cs) + if eq lb ub + then ub + else + (Printf.printf "\n ambiguous instantiation %s <: %s <: %s" + (string_of_typ lb) (Con.name c) (string_of_typ ub); + failwith "none")) cs) with _ -> None) | None -> None From ee8388ef935a226e786e4f58d4271f03562e47ea Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 26 Feb 2020 22:53:19 +0000 Subject: [PATCH 1064/1176] special case inference for scoped monomorphic function to continue to support domain driven overload resolution --- src/mo_frontend/typing.ml | 22 ++++++++++++---- src/mo_types/type.ml | 55 +++++++++++++++++++++++++-------------- src/mo_types/type.mli | 2 +- test/fail/inference.mo | 4 +-- 4 files changed, 56 insertions(+), 27 deletions(-) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index a2adadd4449..05b8c69387b 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -322,6 +322,14 @@ and check_ErrorCap env s at = error env at "misplaced %s; try enclosing in an async expression or query function" s | C.NullCap -> error env at "misplaced %s" s +and scope_of_env env = + match env.async with + | C.AsyncCap c + | C.QueryCap c + | C.AwaitCap c -> Some (T.Con(c,[])) + | C.ErrorCap -> None + | C.NullCap -> None + and check_typ env (typ:typ) : T.typ = let t = check_typ' env typ in typ.note <- t; @@ -880,11 +888,15 @@ and infer_exp'' env exp : T.typ = (T.string_of_typ_expand t1) in let ts, check_arg = - if tbs <> [] && inst.it = [] then + match tbs, inst.it with + | [], [] -> (* no inference required *) + [], check_exp + | [{T.sort = T.Scope;_}], _ (* special case to allow t_arg driven overload resolution *) + | _, _::_ -> (* explicit instantiation, check *) + check_inst_bounds env tbs typs exp.at, check_exp + | _::_, [] -> (* implicit or empty instantiation, infer *) (* TODO: distinguish <> from missing *) let t2 = infer_exp env exp2 in - let cts = T.open_binds tbs in - let cs = List.map (fun t -> match t with T.Con(c,_) -> c | _ -> assert false) cts in - match T.bimatch_typ cs t2 (T.open_ cts t_arg) with + match T.bimatch_typ (scope_of_env env) tbs t2 t_arg with | Some ts -> check_typ_bounds env tbs ts (List.map (fun _ -> exp1.at) ts) exp.at; ts, @@ -892,7 +904,7 @@ and infer_exp'' env exp : T.typ = if not (T.sub t2 t_arg) then error env exp.at "cannot infer type arguments due to subtyping\n %s is not a subtype of %s" (T.string_of_typ_expand t2) (T.string_of_typ_expand t_arg) | None -> error env exp.at "cannot infer type arguments" - else check_inst_bounds env tbs typs exp.at, check_exp in + in inst.note <- ts; let t_arg = T.open_ ts t_arg in let t_ret = T.open_ ts t_ret in diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index 338eebd2bc4..ba3039e9be3 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -1494,7 +1494,11 @@ in (* Bi-Matching *) -let bimatch_typ cs t1 t2 = +let bimatch_typ scope_opt tbs t1 t2 = + +let ts = open_binds tbs in +let t2 = open_ ts t2 in +let cs = List.map (fun t -> match t with Con(c,_) -> c | _ -> assert false) ts in let rel = ref SS.empty in @@ -1663,22 +1667,35 @@ and bimatch_bind ts inst any tb1 tb2 = bimatch_typ inst any (open_ ts tb1.bound) (open_ ts tb2.bound) in - match bimatch_typ (ConEnv.empty, ConEnv.empty) ConSet.empty t1 t2 with - | Some (l,u) -> - (try - Some (List.map - (fun c -> - match ConEnv.find_opt c l, ConEnv.find_opt c u with - | None, None -> Non - | None, Some ub -> ub - | Some lb, None -> lb - | Some lb, Some ub -> - if eq lb ub - then ub - else - (Printf.printf "\n ambiguous instantiation %s <: %s <: %s" - (string_of_typ lb) (Con.name c) (string_of_typ ub); - failwith "none")) cs) - with _ -> None) - | None -> None + try + let bds = List.map (fun tb -> open_ ts tb.bound) tbs in + (* TODO, if bounds open return None *) + let add c b u = if eq b Any then u else ConEnv.add c b u in + let u = List.fold_right2 add cs bds ConEnv.empty in + let l,u = match scope_opt, tbs with + | Some c, {sort=Scope;_}::tbs -> + ConEnv.singleton (List.hd cs) c, + add (List.hd cs) (lub c (List.hd bds)) u + | None, {sort=Scope;_}::tbs -> failwith "" + | _, _ -> + ConEnv.empty, + u + in + match bimatch_typ (l, u) ConSet.empty t1 t2 with + | Some (l,u) -> + Some (List.map + (fun c -> + match ConEnv.find_opt c l, ConEnv.find_opt c u with + | None, None -> Non + | None, Some ub -> ub + | Some lb, None -> lb + | Some lb, Some ub -> + if eq lb ub + then ub + else + (Printf.eprintf "\n ambiguous instantiation %s <: %s <: %s" + (string_of_typ lb) (Con.name c) (string_of_typ ub); + failwith "none")) cs) + | None -> None + with _ -> None diff --git a/src/mo_types/type.mli b/src/mo_types/type.mli index 301bc4108c6..61fc1caa410 100644 --- a/src/mo_types/type.mli +++ b/src/mo_types/type.mli @@ -229,4 +229,4 @@ val string_of_typ_expand : typ -> string (* Matching *) val match_typ : con list -> typ -> typ -> typ list option -val bimatch_typ : con list -> typ -> typ -> typ list option +val bimatch_typ : typ option -> bind list -> typ -> typ -> typ list option diff --git a/test/fail/inference.mo b/test/fail/inference.mo index cd6a12504cb..b78f8ed81c6 100644 --- a/test/fail/inference.mo +++ b/test/fail/inference.mo @@ -85,10 +85,10 @@ ignore contra(func (x:Nat,y:Nat) {}); ignore contra(func (x:Nat,y:Int) {}); ignore contra(func (x:Nat,y:Bool) {}); - +/* func coswap(x : T,y : T):(U,U){(y,x)}; ignore coswap(1,2); // works (coz Int <: Nat) ignore coswap(1,2:Int); // works (coz Int <: Nat) ignore coswap(1,true); // doesn't work unless we lub with with bound - +*/ From 634202e70293ff68372d3da061f9d18f05afbaea Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 26 Feb 2020 23:18:47 +0000 Subject: [PATCH 1065/1176] bound tests --- test/fail/inference.mo | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/fail/inference.mo b/test/fail/inference.mo index b78f8ed81c6..809e4293704 100644 --- a/test/fail/inference.mo +++ b/test/fail/inference.mo @@ -92,3 +92,17 @@ ignore coswap(1,2:Int); // works (coz Int <: Nat) ignore coswap(1,true); // doesn't work unless we lub with with bound */ +// support domain driven overloading for scoped monomorphic functions (as before) +func f(g:shared Nat8 -> ()) : async () { + g(1); +}; + +func bnd(x:T):T{x}; +ignore bnd(1:Int) : Int; +ignore bnd(1) : Nat; +ignore (if false (bnd(loop {}):Nat) else 1); +ignore (if false (bnd(loop {}):Int) else 1); +ignore (if false (bnd(loop {}):None) else 1); +bnd(true); + + From 1b023617f1fe9e0929a3878e18d423dc4718e254 Mon Sep 17 00:00:00 2001 From: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> Date: Thu, 27 Feb 2020 14:33:17 +0100 Subject: [PATCH 1066/1176] Functorizes type pretty printing and hides stamps from IDE types (#1240) * Functorizes type pretty printing and hides stamps from IDE types * instantiate MakePretty for IDE purposes * Apply suggestions from code review Co-Authored-By: Andreas Rossberg Co-authored-by: Andreas Rossberg --- src/languageServer/completion.ml | 2 +- src/languageServer/hover.ml | 2 +- src/languageServer/pretty.ml | 1 + src/languageServer/pretty.mli | 1 + src/mo_types/con.ml | 6 ++++-- src/mo_types/con.mli | 1 + src/mo_types/type.ml | 21 +++++++++++++++++---- src/mo_types/type.mli | 18 ++++++++++++------ 8 files changed, 38 insertions(+), 14 deletions(-) create mode 100644 src/languageServer/pretty.ml create mode 100644 src/languageServer/pretty.mli diff --git a/src/languageServer/completion.ml b/src/languageServer/completion.ml index 432562d5e67..791afe20a8f 100644 --- a/src/languageServer/completion.ml +++ b/src/languageServer/completion.ml @@ -45,7 +45,7 @@ let item_of_ide_decl (d : DI.ide_decl) : Lsp_t.completion_item = completion_item_insertText = Some tmpl; completion_item_insertTextFormat = Some 2; completion_item_additionalTextEdits = None; - completion_item_documentation = Some(Type.string_of_typ value.DI.typ); + completion_item_documentation = Some (Pretty.string_of_typ value.DI.typ); completion_item_detail = None; } | DI.TypeDecl ty -> diff --git a/src/languageServer/hover.ml b/src/languageServer/hover.ml index 530a296830a..94fb7b854d7 100644 --- a/src/languageServer/hover.ml +++ b/src/languageServer/hover.ml @@ -5,7 +5,7 @@ module DI = Declaration_index let hover_detail = function | ValueDecl value -> - value.name ^ " : " ^ Type.string_of_typ value.typ + value.name ^ " : " ^ Pretty.string_of_typ value.typ | TypeDecl ty -> let _, params, _ = Type.strings_of_kind (Con.kind ty.typ) in Printf.sprintf "public type %s%s" ty.name params diff --git a/src/languageServer/pretty.ml b/src/languageServer/pretty.ml new file mode 100644 index 00000000000..a6af05160e6 --- /dev/null +++ b/src/languageServer/pretty.ml @@ -0,0 +1 @@ +include Mo_types.Type.MakePretty(struct let show_stamps = false end) diff --git a/src/languageServer/pretty.mli b/src/languageServer/pretty.mli new file mode 100644 index 00000000000..edc51128cc1 --- /dev/null +++ b/src/languageServer/pretty.mli @@ -0,0 +1 @@ +val string_of_typ : Mo_types.Type.typ -> string diff --git a/src/mo_types/con.ml b/src/mo_types/con.ml index 376cb46a92a..a3f4a1d6554 100644 --- a/src/mo_types/con.ml +++ b/src/mo_types/con.ml @@ -29,8 +29,10 @@ let kind c = !(c.kind) let unsafe_set_kind c k = c.kind := k let name c = c.name -let to_string c = - if c.stamp = 0 then c.name else Printf.sprintf "%s/%i" c.name c.stamp +let to_string' show_stamps c = + if not show_stamps || c.stamp = 0 then c.name else Printf.sprintf "%s/%i" c.name c.stamp + +let to_string c = to_string' true c let eq c1 c2 = (c1.name, c1.stamp) = (c2.name, c2.stamp) let compare c1 c2 = compare (c1.name, c1.stamp) (c2.name, c2.stamp) diff --git a/src/mo_types/con.mli b/src/mo_types/con.mli index 2b53b339527..79c196b80c4 100644 --- a/src/mo_types/con.mli +++ b/src/mo_types/con.mli @@ -7,6 +7,7 @@ val clone: 'a t -> 'a -> 'a t val name : 'a t -> string val to_string : 'a t -> string +val to_string' : bool -> 'a t -> string val kind : 'a t -> 'a val unsafe_set_kind : 'a t -> 'a -> unit (* cf. Type.set_kind *) diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index b713dcf479b..48e612523d9 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -1148,10 +1148,6 @@ let string_of_prim = function let string_of_var (x, i) = if i = 0 then sprintf "%s" x else sprintf "%s.%d" x i -let string_of_con' vs c = - let s = Con.to_string c in - if List.mem (s, 0) vs then s ^ "/0" else s (* TBR *) - let string_of_obj_sort = function | Object -> "" | Module -> "module " @@ -1162,6 +1158,13 @@ let string_of_func_sort = function | Shared Write -> "shared " | Shared Query -> "shared query " +module MakePretty(Cfg : sig val show_stamps : bool end) = + struct + +let string_of_con' vs c = + let s = Con.to_string' Cfg.show_stamps c in + if List.mem (s, 0) vs then s ^ "/0" else s (* TBR *) + let rec string_of_typ_nullary vs = function | Pre -> "???" | Any -> "Any" @@ -1344,4 +1347,14 @@ let rec string_of_typ_expand t = | t' -> s ^ " = " ^ string_of_typ_expand t' ) | _ -> s +end + +module type Pretty = sig + val string_of_con : con -> string + val string_of_typ : typ -> string + val string_of_kind : kind -> string + val strings_of_kind : kind -> string * string * string + val string_of_typ_expand : typ -> string +end +include MakePretty(struct let show_stamps = true end) diff --git a/src/mo_types/type.mli b/src/mo_types/type.mli index acbcb3ccc99..f61caf596dc 100644 --- a/src/mo_types/type.mli +++ b/src/mo_types/type.mli @@ -217,12 +217,18 @@ val scope_bind : bind (* Pretty printing *) +val string_of_prim : prim -> string val string_of_obj_sort : obj_sort -> string val string_of_func_sort : func_sort -> string -val string_of_con : con -> string -val string_of_prim : prim -> string -val string_of_typ : typ -> string -val string_of_kind : kind -> string -val strings_of_kind : kind -> string * string * string -val string_of_typ_expand : typ -> string +module type Pretty = sig + val string_of_con : con -> string + val string_of_typ : typ -> string + val string_of_kind : kind -> string + val strings_of_kind : kind -> string * string * string + val string_of_typ_expand : typ -> string +end + +module MakePretty(Cfg : sig val show_stamps : bool end) : Pretty + +include Pretty From 25fe971eb198aa162694eedc8f1e11efd7745bbf Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 27 Feb 2020 14:46:49 +0100 Subject: [PATCH 1067/1176] s/Running/Idle/g --- src/codegen/compile.ml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 126f472fcc0..026e39f8a40 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -2813,7 +2813,7 @@ module Lifecycle = struct | Started (* (start) has run *) *) | InInit (* canister_init *) - | Running (* basic steady state *) + | Idle (* basic steady state *) | InUpdate | InQuery | PostQuery (* an invalid state *) @@ -2826,7 +2826,7 @@ module Lifecycle = struct | Started -> 2l *) | InInit -> 3l - | Running -> 4l + | Idle -> 4l | InUpdate -> 5l | InQuery -> 6l | PostQuery -> 7l @@ -2842,9 +2842,9 @@ module Lifecycle = struct | Started -> [InStart] *) | InInit -> [PreInit] - | Running -> [InInit; InUpdate] - | InUpdate -> [Running] - | InQuery -> [Running] + | Idle -> [InInit; InUpdate] + | InUpdate -> [Idle] + | InQuery -> [Idle] | PostQuery -> [InQuery] let trans env new_state = @@ -3000,7 +3000,7 @@ module Dfinity = struct Lifecycle.trans env Lifecycle.InInit ^^ (* Collect garbage *) G.i (Call (nr (E.built_in env1 "collect"))) ^^ - Lifecycle.trans env Lifecycle.Running + Lifecycle.trans env Lifecycle.Idle ) in let fi = E.add_fun env "canister_init" empty_f in E.add_export env (nr { @@ -4747,7 +4747,7 @@ module FuncDec = struct let message_cleanup env sort = match sort with | Type.Shared Type.Write -> G.i (Call (nr (E.built_in env "collect"))) ^^ - Lifecycle.trans env Lifecycle.Running + Lifecycle.trans env Lifecycle.Idle | Type.Shared Type.Query -> Lifecycle.trans env Lifecycle.PostQuery | _ -> assert false From 895efb91ffca385db68d1cebe79f6b0cadf9c735 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Thu, 27 Feb 2020 15:43:06 +0000 Subject: [PATCH 1068/1176] refactor, add test output --- test/fail/inference.mo | 27 +++++++++++++++-------- test/fail/ok/inference.tc.ok | 38 ++++++++++++++++++++++++++++++++ test/fail/ok/inference.tc.ret.ok | 1 + 3 files changed, 57 insertions(+), 9 deletions(-) create mode 100644 test/fail/ok/inference.tc.ok create mode 100644 test/fail/ok/inference.tc.ret.ok diff --git a/test/fail/inference.mo b/test/fail/inference.mo index 809e4293704..c3a25d56133 100644 --- a/test/fail/inference.mo +++ b/test/fail/inference.mo @@ -55,13 +55,17 @@ func mult2(m:N,n:N):N { m/**/(curry/**/ add n, zero) }; func tricky(f : T -> T) { }; +//explicit instantiation tricky(func f(x:Any):None { f(x);}); tricky(func f(x:Any):None { f(x);}); +tricky(func f(x:None):Any { f(x);}); // correctly rejected +tricky(func f(x:None):Any { f(x);}); // correctly rejected ignore func () { tricky(func f(x:Any):None{f(x)}) }; +// implicit instantiation ignore tricky(func f(x:Any):None { f(x);}); -ignore tricky(func f(x:None):Any { f(x);}); //requires Dolan style bi-matching -ignore tricky(func f(x:None):None { f(x);}); //requires Dolan style bi-matching +ignore tricky(func f(x:None):Any { f(x);}); // fails, inconsitent instantiation required. +ignore tricky(func f(x:None):None { f(x);}); func amb(f : T -> T): T->T { f }; ignore amb(func f(x:Any):None { f(x);}) : None -> None; @@ -85,24 +89,29 @@ ignore contra(func (x:Nat,y:Nat) {}); ignore contra(func (x:Nat,y:Int) {}); ignore contra(func (x:Nat,y:Bool) {}); -/* + func coswap(x : T,y : T):(U,U){(y,x)}; ignore coswap(1,2); // works (coz Int <: Nat) ignore coswap(1,2:Int); // works (coz Int <: Nat) -ignore coswap(1,true); // doesn't work unless we lub with with bound -*/ +ignore coswap(1,true); // doesn't work unless we lub with bound + -// support domain driven overloading for scoped monomorphic functions (as before) +// support domain driven overloading for implicitly scoped, +// otherwise monomorphic functions (as before) func f(g:shared Nat8 -> ()) : async () { g(1); }; func bnd(x:T):T{x}; ignore bnd(1:Int) : Int; -ignore bnd(1) : Nat; -ignore (if false (bnd(loop {}):Nat) else 1); +ignore bnd(1) : Nat; // fails, under-constrained +ignore (if false (bnd(loop {}):Nat) else 1); // fails, underspecialized, requires expected ret typ info ignore (if false (bnd(loop {}):Int) else 1); -ignore (if false (bnd(loop {}):None) else 1); +ignore (if false (bnd(loop {}):None) else 1); // fails, underspecialized, requires expected ret typ info bnd(true); + + +//TODO: invariant mutables, constructor constraints, bail on open bounds + diff --git a/test/fail/ok/inference.tc.ok b/test/fail/ok/inference.tc.ok new file mode 100644 index 00000000000..e1f20aeda84 --- /dev/null +++ b/test/fail/ok/inference.tc.ok @@ -0,0 +1,38 @@ +inference.mo:87.27-87.32: warning, this pattern is never matched +inference.mo:61.14-61.41: type error, expression of type + None -> Any +cannot produce expected type + None -> None +inference.mo:62.13-62.40: type error, expression of type + None -> Any +cannot produce expected type + Any -> Any +inference.mo:66.8-66.43: type error, cannot instantiate function of type (T -> T) -> () to argument of type Any -> None: + under-constrained implicit instantiation None <: T <: Any, + with None =/= Any; explicit type instantiation required +inference.mo:67.8-67.43: type error, cannot instantiate function of type (T -> T) -> () to argument of type None -> Any: + over-constrained implicit instantiation requires Any <: T <: None, + but Any (T, T) -> (U, U) to argument of type (Nat, Nat): + type parameter T has an open bound U/9 mentioning another type parameter +; explicit type instantiation required +inference.mo:95.8-95.23: type error, cannot instantiate function of type (T, T) -> (U, U) to argument of type (Nat, Int): + type parameter T has an open bound U/10 mentioning another type parameter +; explicit type instantiation required +inference.mo:96.8-96.22: type error, cannot instantiate function of type (T, T) -> (U, U) to argument of type (Nat, Bool): + type parameter T has an open bound U/11 mentioning another type parameter +; explicit type instantiation required +inference.mo:107.8-107.14: type error, cannot instantiate function of type T -> T to argument of type Nat: + under-constrained implicit instantiation Nat <: T <: Int, + with Nat =/= Int; explicit type instantiation required +inference.mo:108.19-108.31: type error, expression of type + Int +cannot produce expected type + Nat +inference.mo:110.19-110.31: type error, expression of type + Int +cannot produce expected type + None +inference.mo:111.1-111.10: type error, cannot instantiate function of type T -> T to argument of type Bool: + over-constrained implicit instantiation requires Bool <: T <: Int, + but Bool Date: Thu, 27 Feb 2020 15:46:23 +0000 Subject: [PATCH 1069/1176] mo stuff --- src/mo_frontend/typing.ml | 11 +- src/mo_types/type.ml | 377 ++++++++++++++++++++------------------ 2 files changed, 210 insertions(+), 178 deletions(-) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 05b8c69387b..53df228c9be 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -894,7 +894,7 @@ and infer_exp'' env exp : T.typ = | [{T.sort = T.Scope;_}], _ (* special case to allow t_arg driven overload resolution *) | _, _::_ -> (* explicit instantiation, check *) check_inst_bounds env tbs typs exp.at, check_exp - | _::_, [] -> (* implicit or empty instantiation, infer *) (* TODO: distinguish <> from missing *) + | _::_, [] -> (* implicit or empty instantiation, infer *) (* TODO: distinguish explicit empty instantation <> from omitted instantiation *) let t2 = infer_exp env exp2 in match T.bimatch_typ (scope_of_env env) tbs t2 t_arg with | Some ts -> @@ -903,7 +903,14 @@ and infer_exp'' env exp : T.typ = fun env t_arg exp -> if not (T.sub t2 t_arg) then error env exp.at "cannot infer type arguments due to subtyping\n %s is not a subtype of %s" (T.string_of_typ_expand t2) (T.string_of_typ_expand t_arg) - | None -> error env exp.at "cannot infer type arguments" + | None -> + error env exp.at "function of type %s cannot be instantiated to consume argument of type %s" (T.string_of_typ t1) + (T.string_of_typ t2) + | exception (Failure msg) -> + error env exp.at "cannot instantiate function of type %s to argument of type %s:\n %s" + (T.string_of_typ t1) + (T.string_of_typ t2) + msg in inst.note <- ts; let t_arg = T.open_ ts t_arg in diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index ba3039e9be3..70ec6c0b50c 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -1496,187 +1496,212 @@ in let bimatch_typ scope_opt tbs t1 t2 = -let ts = open_binds tbs in -let t2 = open_ ts t2 in -let cs = List.map (fun t -> match t with Con(c,_) -> c | _ -> assert false) ts in + let ts = open_binds tbs in + let t2 = open_ ts t2 in + let cs = List.map (fun t -> match t with Con(c,_) -> c | _ -> assert false) ts in -let rel = ref SS.empty -in + let rel = ref SS.empty + in -let flexible c = List.exists (Con.eq c) cs -in + let flexible c = List.exists (Con.eq c) cs + in -let rec bimatch_list p inst any xs1 xs2 = - (match (xs1, xs2) with - | (x1::xs1, x2::xs2) -> - (match p inst any x1 x2 with - | Some inst -> bimatch_list p inst any xs1 xs2 - | None -> None) - | [], [] -> Some inst - | _, _ -> None) -in + let mentions typ ce = not (ConSet.is_empty (ConSet.inter (cons typ ConSet.empty) ce)) in -let rec bimatch_typ ((l,u) as inst) (any:ConSet.t) (t1:typ) (t2:typ) = - if t1 == t2 || SS.mem (t1, t2) !rel - then Some inst - else begin - rel := SS.add (t1, t2) !rel; - (* Printf.printf "%s %s\n" (!str t1) (!str t2); *) - match t1, t2 with - | Pre, _ | _, Pre -> - Some inst - | _, Any -> - Some inst - | Non, _ -> - Some inst - | _, Con (con2, ts2) when flexible con2 -> - assert (ts2 = []); - if ConSet.is_empty (ConSet.inter (cons t1 ConSet.empty) any) then - (match ConEnv.find_opt con2 l with - | Some t1' -> - let lub = lub t1 t1' in - Some (ConEnv.add con2 lub l, u) - | None -> Some (ConEnv.add con2 t1 l, u)) - else None - | Con (con1, ts1), _ when flexible con1 -> - assert (ts1 = []); - if ConSet.is_empty (ConSet.inter (cons t2 ConSet.empty) any) then - (match ConEnv.find_opt con1 u with - | Some t2' -> - let glb = glb t2 t2' in - Some (l, ConEnv.add con1 glb u) - | None -> Some (l, ConEnv.add con1 t2 u)) - else None - | Con (con1, ts1), Con (con2, ts2) -> - (match Con.kind con1, Con.kind con2 with - | Def (tbs, t), _ -> (* TBR this may fail to terminate *) - bimatch_typ inst any (open_ ts1 t) t2 - | _, Def (tbs, t) -> (* TBR this may fail to terminate *) - bimatch_typ inst any t1 (open_ ts2 t) - | _ when Con.eq con1 con2 -> - assert (ts1 = []); + let rec bimatch_list p inst any xs1 xs2 = + (match (xs1, xs2) with + | (x1::xs1, x2::xs2) -> + (match p inst any x1 x2 with + | Some inst -> bimatch_list p inst any xs1 xs2 + | None -> None) + | [], [] -> Some inst + | _, _ -> None) + in + + let rec bimatch_typ ((l,u) as inst) (any:ConSet.t) (t1:typ) (t2:typ) = + if t1 == t2 || SS.mem (t1, t2) !rel + then Some inst + else begin + rel := SS.add (t1, t2) !rel; + (* Printf.printf "%s %s\n" (!str t1) (!str t2); *) + match t1, t2 with + | Pre, _ | _, Pre -> + Some inst + | _, Any -> + Some inst + | Non, _ -> + Some inst + | _, Con (con2, ts2) when flexible con2 -> assert (ts2 = []); + if mentions t1 any then + None + else + (match ConEnv.find_opt con2 l with + | Some t1' -> + let lub = lub t1 t1' in + Some (ConEnv.add con2 lub l, u) + | None -> Some (ConEnv.add con2 t1 l, u)) + | Con (con1, ts1), _ when flexible con1 -> + assert (ts1 = []); + if mentions t2 any then + None + else + (match ConEnv.find_opt con1 u with + | Some t2' -> + let glb = glb t2 t2' in + Some (l, ConEnv.add con1 glb u) + | None -> Some (l, ConEnv.add con1 t2 u)) + | Con (con1, ts1), Con (con2, ts2) -> + (match Con.kind con1, Con.kind con2 with + | Def (tbs, t), _ -> (* TBR this may fail to terminate *) + bimatch_typ inst any (open_ ts1 t) t2 + | _, Def (tbs, t) -> (* TBR this may fail to terminate *) + bimatch_typ inst any t1 (open_ ts2 t) + | _ when Con.eq con1 con2 -> + assert (ts1 = []); + assert (ts2 = []); + Some inst + | Abs (tbs, t), _ -> + bimatch_typ inst any (open_ ts1 t) t2 + ) + | Con (con1, ts1), t2 -> + (match Con.kind con1, t2 with + | Def (tbs, t), _ -> (* TBR this may fail to terminate *) + bimatch_typ inst any (open_ ts1 t) t2 + | Abs (tbs, t), _ -> + bimatch_typ inst any (open_ ts1 t) t2 + ) + | t1, Con (con2, ts2) -> + (match Con.kind con2 with + | Def (tbs, t) -> (* TBR this may fail to terminate *) + bimatch_typ inst any t1 (open_ ts2 t) + | _ -> None + ) + | Prim p1, Prim p2 when p1 = p2 -> Some inst - | Abs (tbs, t), _ -> - bimatch_typ inst any (open_ ts1 t) t2 - ) - | Con (con1, ts1), t2 -> - (match Con.kind con1, t2 with - | Def (tbs, t), _ -> (* TBR this may fail to terminate *) - bimatch_typ inst any (open_ ts1 t) t2 - | Abs (tbs, t), _ -> - bimatch_typ inst any (open_ ts1 t) t2 - ) - | t1, Con (con2, ts2) -> - (match Con.kind con2 with - | Def (tbs, t) -> (* TBR this may fail to terminate *) - bimatch_typ inst any t1 (open_ ts2 t) - | _ -> None - ) - | Prim p1, Prim p2 when p1 = p2 -> - Some inst - | Prim p1, Prim p2 -> - if p1 = Nat && p2 = Int then Some inst else None - | Obj (s1, tfs1), Obj (s2, tfs2) -> - if s1 = s2 then - bimatch_fields inst any tfs1 tfs2 - else None - | Array t1', Array t2' -> - bimatch_typ inst any t1' t2' - | Opt t1', Opt t2' -> - bimatch_typ inst any t1' t2' - | Prim Null, Opt t2' -> - Some inst - | Variant fs1, Variant fs2 -> - bimatch_tags inst any fs1 fs2 - | Tup ts1, Tup ts2 -> - bimatch_list bimatch_typ inst any ts1 ts2 - | Func (s1, c1, tbs1, t11, t12), Func (s2, c2, tbs2, t21, t22) -> - if s1 = s2 && c1 = c2 then - (match bimatch_binds inst any tbs1 tbs2 with - | Some (inst, ts) -> - let any' = List.fold_right - (function Con(c,[]) -> ConSet.add c | _ -> assert false) ts any - in - (match - bimatch_list bimatch_typ inst any' (List.map (open_ ts) t21) (List.map (open_ ts) t11) - with - | Some inst -> - bimatch_list bimatch_typ inst any' (List.map (open_ ts) t12) (List.map (open_ ts) t22) - | None -> None) - | None -> None - ) - else None - | Async (t11, t12), Async (t21, t22) -> - (* TBR *) - bimatch_list bimatch_typ inst any [t11;t21;t12] [t21;t11;t22] - | Mut t1', Mut t2' -> - (* TBR *) - bimatch_list bimatch_typ inst any [t1';t2'] [t2';t1'] - | Typ c1, Typ c2 -> - (* TBR *) - if eq t1 t2 then Some inst else None - | _, _ -> None - end + | Prim p1, Prim p2 -> + if p1 = Nat && p2 = Int then Some inst else None + | Obj (s1, tfs1), Obj (s2, tfs2) -> + if s1 = s2 then + bimatch_fields inst any tfs1 tfs2 + else None + | Array t1', Array t2' -> + bimatch_typ inst any t1' t2' + | Opt t1', Opt t2' -> + bimatch_typ inst any t1' t2' + | Prim Null, Opt t2' -> + Some inst + | Variant fs1, Variant fs2 -> + bimatch_tags inst any fs1 fs2 + | Tup ts1, Tup ts2 -> + bimatch_list bimatch_typ inst any ts1 ts2 + | Func (s1, c1, tbs1, t11, t12), Func (s2, c2, tbs2, t21, t22) -> + if s1 = s2 && c1 = c2 then + (match bimatch_binds inst any tbs1 tbs2 with + | Some (inst, ts) -> + let any' = List.fold_right + (function Con(c,[]) -> ConSet.add c | _ -> assert false) ts any + in + (match + bimatch_list bimatch_typ inst any' (List.map (open_ ts) t21) (List.map (open_ ts) t11) + with + | Some inst -> + bimatch_list bimatch_typ inst any' (List.map (open_ ts) t12) (List.map (open_ ts) t22) + | None -> None) + | None -> None + ) + else None + | Async (t11, t12), Async (t21, t22) -> + (* TBR *) + bimatch_list bimatch_typ inst any [t11;t21;t12] [t21;t11;t22] + | Mut t1', Mut t2' -> + (* TBR *) + bimatch_list bimatch_typ inst any [t1';t2'] [t2';t1'] + | Typ c1, Typ c2 -> + (* TBR *) + if eq t1 t2 then Some inst else None + | _, _ -> None + end -and bimatch_fields inst any tfs1 tfs2 = - (* Assume that tfs1 and tfs2 are sorted. *) - match tfs1, tfs2 with - | [], [] -> - Some inst - | _, [] -> - Some inst - | tf1::tfs1', tf2::tfs2' -> - (match compare_field tf1 tf2 with - | 0 -> - (match bimatch_typ inst any tf1.typ tf2.typ with - | Some inst -> bimatch_fields inst any tfs1' tfs2' - | None -> None) - | -1 -> - bimatch_fields inst any tfs1' tfs2 - | _ -> None - ) - | _, _ -> None + and bimatch_fields inst any tfs1 tfs2 = + (* Assume that tfs1 and tfs2 are sorted. *) + match tfs1, tfs2 with + | [], [] -> + Some inst + | _, [] -> + Some inst + | tf1::tfs1', tf2::tfs2' -> + (match compare_field tf1 tf2 with + | 0 -> + (match bimatch_typ inst any tf1.typ tf2.typ with + | Some inst -> bimatch_fields inst any tfs1' tfs2' + | None -> None) + | -1 -> + bimatch_fields inst any tfs1' tfs2 + | _ -> None + ) + | _, _ -> None -and bimatch_tags inst any tfs1 tfs2 = - (* Assume that tfs1 and tfs2 are sorted. *) - match tfs1, tfs2 with - | [], [] -> - Some inst - | [], _ -> - Some inst - | tf1::tfs1', tf2::tfs2' -> - (match compare_field tf1 tf2 with - | 0 -> - (match bimatch_typ inst any tf1.typ tf2.typ with - | Some inst -> bimatch_tags inst any tfs1' tfs2' - | None -> None) - | +1 -> - bimatch_tags inst any tfs1 tfs2' - | _ -> None - ) - | _, _ -> None + and bimatch_tags inst any tfs1 tfs2 = + (* Assume that tfs1 and tfs2 are sorted. *) + match tfs1, tfs2 with + | [], [] -> + Some inst + | [], _ -> + Some inst + | tf1::tfs1', tf2::tfs2' -> + (match compare_field tf1 tf2 with + | 0 -> + (match bimatch_typ inst any tf1.typ tf2.typ with + | Some inst -> bimatch_tags inst any tfs1' tfs2' + | None -> None) + | +1 -> + bimatch_tags inst any tfs1 tfs2' + | _ -> None + ) + | _, _ -> None -and bimatch_binds inst any tbs1 tbs2 = - let ts = open_binds tbs2 in - match bimatch_list (bimatch_bind ts) inst any tbs2 tbs1 with - | Some inst -> Some (inst,ts) - | None -> None + and bimatch_binds inst any tbs1 tbs2 = + let ts = open_binds tbs2 in + match bimatch_list (bimatch_bind ts) inst any tbs2 tbs1 with + | Some inst -> Some (inst,ts) + | None -> None -and bimatch_bind ts inst any tb1 tb2 = - bimatch_typ inst any (open_ ts tb1.bound) (open_ ts tb2.bound) + and bimatch_bind ts inst any tb1 tb2 = + bimatch_typ inst any (open_ ts tb1.bound) (open_ ts tb2.bound) + + and fail_under_constrained lb c ub = + let lb = string_of_typ lb in + let c = Con.name c in + let ub = string_of_typ ub in + failwith (Printf.sprintf + "under-constrained implicit instantiation %s <: %s <: %s,\n with %s =/= %s; explicit type instantiation required" + lb c ub lb ub) + + and fail_over_constrained lb c ub = + let lb = string_of_typ lb in + let c = Con.name c in + let ub = string_of_typ ub in + failwith (Printf.sprintf + "over-constrained implicit instantiation requires %s <: %s <: %s,\n but %s open_ ts tb.bound) tbs in - (* TODO, if bounds open return None *) + let ce = ConSet.of_list cs in + List.iter2 (fun c bd -> if mentions bd ce then fail_open_bound c bd) cs bds; let add c b u = if eq b Any then u else ConEnv.add c b u in let u = List.fold_right2 add cs bds ConEnv.empty in let l,u = match scope_opt, tbs with | Some c, {sort=Scope;_}::tbs -> ConEnv.singleton (List.hd cs) c, add (List.hd cs) (lub c (List.hd bds)) u - | None, {sort=Scope;_}::tbs -> failwith "" + | None, {sort=Scope;_}::tbs -> failwith "scope instantiation required but no scope available" | _, _ -> ConEnv.empty, u @@ -1684,18 +1709,18 @@ in match bimatch_typ (l, u) ConSet.empty t1 t2 with | Some (l,u) -> Some (List.map - (fun c -> - match ConEnv.find_opt c l, ConEnv.find_opt c u with - | None, None -> Non - | None, Some ub -> ub - | Some lb, None -> lb - | Some lb, Some ub -> - if eq lb ub - then ub - else - (Printf.eprintf "\n ambiguous instantiation %s <: %s <: %s" - (string_of_typ lb) (Con.name c) (string_of_typ ub); - failwith "none")) cs) + (fun c -> + match ConEnv.find_opt c l, ConEnv.find_opt c u with + | None, None -> Non + | None, Some ub -> ub + | Some lb, None -> lb + | Some lb, Some ub -> + if eq lb ub then + ub + else if sub lb ub then + fail_under_constrained lb c ub + else + fail_over_constrained lb c ub) + cs) | None -> None - with _ -> None From 1ba1252149e440a397cd9724213d9e9cc2d6fe11 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 27 Feb 2020 16:57:59 +0100 Subject: [PATCH 1070/1176] Basic upgrade infrastructure (#1199) * ic-stub: Implement stable memory * ic stub: implement upgrade request * Add it to drun syntax * Add a very simple upgrade test * Export canister_post_upgrade (same semantics as init) * Scaffold upgrades by simply copying the whole heap to/from stable memory. This means we can test canister upgrades on the system, but only upgrading to the _same_ module. * Only export these on stub mode of course * And only import them on stub * Add upgrade hooks to lifetime tracking --- ic-stub/ic-stub.cabal | 1 + ic-stub/src/IC/Canister.hs | 6 ++ ic-stub/src/IC/Canister/Imp.hs | 136 +++++++++++++++++++----- ic-stub/src/IC/Canister/Interface.hs | 3 +- ic-stub/src/IC/Canister/Persisted.hs | 30 ++++-- ic-stub/src/IC/DRun/Parse.hs | 2 + ic-stub/src/IC/Stub.hs | 23 +++- ic-stub/src/IC/Types.hs | 2 + ic-stub/src/IC/Wasm/Winter/Persist.hs | 8 ++ ic-stub/src/IC/Wasm/WinterMemory.hs | 58 ++++++++++ ic-stub/src/ic-stub-run.hs | 5 + src/codegen/compile.ml | 114 ++++++++++++++++++-- test/drun-wrapper.sh | 2 +- test/ic-stub-run-wrapper.sh | 6 +- test/run-drun/ok/upgrade.ic-stub-run.ok | 23 ++++ test/run-drun/upgrade.mo | 27 +++++ 16 files changed, 396 insertions(+), 50 deletions(-) create mode 100644 ic-stub/src/IC/Wasm/WinterMemory.hs create mode 100644 test/run-drun/ok/upgrade.ic-stub-run.ok create mode 100644 test/run-drun/upgrade.mo diff --git a/ic-stub/ic-stub.cabal b/ic-stub/ic-stub.cabal index fc19d9e9c2b..6febcde490d 100644 --- a/ic-stub/ic-stub.cabal +++ b/ic-stub/ic-stub.cabal @@ -22,6 +22,7 @@ executable ic-stub-run other-modules: IC.Canister.Pure other-modules: IC.Canister.Persisted other-modules: IC.Wasm.Winter + other-modules: IC.Wasm.WinterMemory other-modules: IC.Wasm.Winter.Persist other-modules: IC.Wasm.Imports other-modules: IC.DRun.Parse diff --git a/ic-stub/src/IC/Canister.hs b/ic-stub/src/IC/Canister.hs index c5a01ca516c..e3f8f940b5b 100644 --- a/ic-stub/src/IC/Canister.hs +++ b/ic-stub/src/IC/Canister.hs @@ -34,6 +34,8 @@ data CanisterModule = CanisterModule , update_methods :: MethodName ↦ (EntityId -> Responded -> Blob -> UpdateFunc) , query_methods :: MethodName ↦ (EntityId -> Blob -> QueryFunc) , callbacks :: Callback -> Responded -> Response -> UpdateFunc + , pre_upgrade_method :: WasmState -> EntityId -> TrapOr Blob + , post_upgrade_method :: CanisterId -> EntityId -> Blob -> Blob -> TrapOr WasmState } parseCanister :: Blob -> Either String CanisterModule @@ -60,4 +62,8 @@ concreteToAbstractModule wasm_mod = CanisterModule ] , callbacks = \cb responded res wasm_state -> invoke wasm_state (CI.Callback cb responded res) + , pre_upgrade_method = \wasm_state caller -> + snd <$> invoke wasm_state (CI.PreUpgrade wasm_mod caller) + , post_upgrade_method = \cid caller mem dat -> + initializeUpgrade wasm_mod cid caller mem dat } diff --git a/ic-stub/src/IC/Canister/Imp.hs b/ic-stub/src/IC/Canister/Imp.hs index 5c853bb0a7a..71ba014a42c 100644 --- a/ic-stub/src/IC/Canister/Imp.hs +++ b/ic-stub/src/IC/Canister/Imp.hs @@ -10,7 +10,7 @@ The canister interface, presented imperatively (or impurely), i.e. without rollb -} module IC.Canister.Imp ( ESRef - , ImpState + , ImpState(..) , runESST , rawInitialize , rawInvoke @@ -26,10 +26,11 @@ import Control.Monad.ST import Control.Monad.Except import Data.STRef import Data.Maybe -import Data.Int +import Data.Int -- TODO: Should be Word32 in most cases import IC.Types import IC.Wasm.Winter +import IC.Wasm.WinterMemory as Mem import IC.Wasm.Imports import qualified IC.Canister.Interface as CI @@ -47,6 +48,7 @@ data Params = Params data ExecutionState s = ExecutionState { inst :: Instance s + , stableMem :: Memory s , self_id :: CanisterId , params :: Params -- now the mutable parts @@ -57,9 +59,10 @@ data ExecutionState s = ExecutionState } -initalExecutionState :: CanisterId -> Instance s -> Responded -> ExecutionState s -initalExecutionState self_id inst responded = ExecutionState +initalExecutionState :: CanisterId -> Instance s -> Memory s -> Responded -> ExecutionState s +initalExecutionState self_id inst stableMem responded = ExecutionState { inst + , stableMem , self_id , params = Params Nothing Nothing 0 "" , responded @@ -149,6 +152,10 @@ systemAPI esref = , toImport "ic0" "canister_self_copy" canister_self_copy , toImport "ic0" "canister_self_size" canister_self_size , toImport "ic0" "call_simple" call_simple + , toImport "ic0" "stable_size" stable_size + , toImport "ic0" "stable_grow" stable_grow + , toImport "ic0" "stable_write" stable_write + , toImport "ic0" "stable_read" stable_read , toImport "ic0" "debug_print" debug_print , toImport "ic0" "trap" explicit_trap ] @@ -227,7 +234,7 @@ systemAPI esref = msg_reply_data_append :: (Int32, Int32) -> HostM s () msg_reply_data_append (src, size) = do assert_not_responded - bytes <- copy_from_canister "debug_print" src size + bytes <- copy_from_canister "msg_reply_data_append" src size appendReplyData esref bytes msg_reply :: () -> HostM s () @@ -239,7 +246,7 @@ systemAPI esref = msg_reject :: (Int32, Int32) -> HostM s () msg_reject (src, size) = do assert_not_responded - bytes <- copy_from_canister "debug_print" src size + bytes <- copy_from_canister "msg_reject" src size let msg = BSU.toString bytes setResponse esref $ Reject (RC_CANISTER_REJECT, msg) @@ -278,6 +285,31 @@ systemAPI esref = } return 0 + stable_size :: () -> HostM s Int32 + stable_size () = do + m <- gets stableMem + Mem.size m + + stable_grow :: Int32 -> HostM s Int32 + stable_grow delta = do + m <- gets stableMem + Mem.grow m delta + + stable_write :: (Int32, Int32, Int32) -> HostM s () + stable_write (dst, src, size) = do + m <- gets stableMem + i <- getsES esref inst + blob <- getBytes i (fromIntegral src) size + Mem.write m (fromIntegral dst) blob + + stable_read :: (Int32, Int32, Int32) -> HostM s () + stable_read (dst, src, size) = do + m <- gets stableMem + i <- getsES esref inst + blob <- Mem.read m (fromIntegral src) size + setBytes i (fromIntegral dst) blob + + debug_print :: (Int32, Int32) -> HostM s () debug_print (src, size) = do -- TODO: This should be a non-trapping copy @@ -295,24 +327,35 @@ systemAPI esref = -- additional remembered information like the CanisterId -- and the 'ESRef' that the system api functions are accessing -type ImpState s = (ESRef s, CanisterId, Instance s) +data ImpState s = ImpState + { isESRef :: ESRef s + , isCanisterId :: CanisterId + , isInstance :: Instance s + , isStableMem :: Memory s + } rawInitialize :: ESRef s -> CanisterId -> Module -> ST s (TrapOr (ImpState s)) rawInitialize esref cid wasm_mod = do - result <- runExceptT $ initialize wasm_mod (systemAPI esref) + result <- runExceptT $ (,) + <$> initialize wasm_mod (systemAPI esref) + <*> Mem.new case result of Left err -> return $ Trap err - Right inst -> return $ Return (esref, cid, inst) + Right (inst, sm) -> return $ Return $ ImpState esref cid inst sm rawInvoke :: ImpState s -> CI.CanisterMethod r -> ST s (TrapOr r) -rawInvoke esref (CI.Initialize wasm_mod caller dat) = - rawInitializeMethod esref wasm_mod caller dat -rawInvoke esref (CI.Query name caller dat) = - rawQueryMethod esref name caller dat -rawInvoke esref (CI.Update name caller responded dat) = - rawUpdateMethod esref name caller responded dat -rawInvoke esref (CI.Callback cb responded res) = - rawCallbackMethod esref cb responded res +rawInvoke is (CI.Initialize wasm_mod caller dat) = + rawInitializeMethod is wasm_mod caller dat +rawInvoke is (CI.Query name caller dat) = + rawQueryMethod is name caller dat +rawInvoke is (CI.Update name caller responded dat) = + rawUpdateMethod is name caller responded dat +rawInvoke is (CI.Callback cb responded res) = + rawCallbackMethod is cb responded res +rawInvoke is (CI.PreUpgrade wasm_mod caller) = + rawPreUpgrade is wasm_mod caller +rawInvoke is (CI.PostUpgrade wasm_mod caller mem dat) = + rawPostUpgrade is wasm_mod caller mem dat cantRespond :: Responded cantRespond = Responded True @@ -321,9 +364,9 @@ canRespond :: Responded canRespond = Responded False rawInitializeMethod :: ImpState s -> Module -> EntityId -> Blob -> ST s (TrapOr InitResult) -rawInitializeMethod (esref, cid, inst) wasm_mod caller dat = do +rawInitializeMethod (ImpState esref cid inst sm) wasm_mod caller dat = do result <- runExceptT $ do - let es = (initalExecutionState cid inst cantRespond) + let es = (initalExecutionState cid inst sm cantRespond) { params = Params { param_dat = Just dat , param_caller = Just caller @@ -344,9 +387,52 @@ rawInitializeMethod (esref, cid, inst) wasm_mod caller dat = do -- TODO: extract canisters and calls here Return (calls es') +rawPreUpgrade :: ImpState s -> Module -> EntityId -> ST s (TrapOr Blob) +rawPreUpgrade (ImpState esref cid inst sm) wasm_mod caller = do + result <- runExceptT $ do + let es = (initalExecutionState cid inst sm cantRespond) + { params = Params + { param_dat = Nothing + , param_caller = Just caller + , reject_code = 0 + , reject_message = "" + } + } + + if "canister_pre_upgrade" `elem` exportedFunctions wasm_mod + then withES esref es $ void $ invokeExport inst "canister_pre_upgrade" [] + else return ((), es) + -- TODO: Check no calls are made + + case result of + Left err -> return $ Trap err + Right (_, es') -> Return <$> Mem.export (stableMem es') + +rawPostUpgrade :: ImpState s -> Module -> EntityId -> Blob -> Blob -> ST s (TrapOr ()) +rawPostUpgrade (ImpState esref cid inst sm) wasm_mod caller mem dat = do + result <- runExceptT $ do + let es = (initalExecutionState cid inst sm cantRespond) + { params = Params + { param_dat = Just dat + , param_caller = Just caller + , reject_code = 0 + , reject_message = "" + } + } + lift $ Mem.imp (stableMem es) mem + + if "canister_post_upgrade" `elem` exportedFunctions wasm_mod + then withES esref es $ void $ invokeExport inst "canister_post_upgrade" [] + else return ((), es) + -- TODO: Check no calls are made + + case result of + Left err -> return $ Trap err + Right ((), _es') -> return $ Return () + rawQueryMethod :: ImpState s -> MethodName -> EntityId -> Blob -> ST s (TrapOr Response) -rawQueryMethod (esref, cid, inst) method caller dat = do - let es = (initalExecutionState cid inst canRespond) +rawQueryMethod (ImpState esref cid inst sm) method caller dat = do + let es = (initalExecutionState cid inst sm canRespond) { params = Params { param_dat = Just dat , param_caller = Just caller @@ -365,8 +451,8 @@ rawQueryMethod (esref, cid, inst) method caller dat = do | otherwise -> return $ Trap "No response" rawUpdateMethod :: ImpState s -> MethodName -> EntityId -> Responded -> Blob -> ST s (TrapOr UpdateResult) -rawUpdateMethod (esref, cid, inst) method caller responded dat = do - let es = (initalExecutionState cid inst responded) +rawUpdateMethod (ImpState esref cid inst sm) method caller responded dat = do + let es = (initalExecutionState cid inst sm responded) { params = Params { param_dat = Just dat , param_caller = Just caller @@ -382,13 +468,13 @@ rawUpdateMethod (esref, cid, inst) method caller responded dat = do Right (_, es') -> return $ Return (calls es', response es') rawCallbackMethod :: ImpState s -> Callback -> Responded -> Response -> ST s (TrapOr UpdateResult) -rawCallbackMethod (esref, cid, inst) callback responded res = do +rawCallbackMethod (ImpState esref cid inst sm) callback responded res = do let params = case res of Reply dat -> Params { param_dat = Just dat, param_caller = Nothing, reject_code = 0, reject_message = "" } Reject (rc, reject_message) -> Params { param_dat = Nothing, param_caller = Nothing, reject_code = rejectCode rc, reject_message } - let es = (initalExecutionState cid inst responded) { params } + let es = (initalExecutionState cid inst sm responded) { params } let WasmClosure fun_idx env = case res of Reply {} -> reply_callback callback diff --git a/ic-stub/src/IC/Canister/Interface.hs b/ic-stub/src/IC/Canister/Interface.hs index 8b2a7d64446..2eacef6f38d 100644 --- a/ic-stub/src/IC/Canister/Interface.hs +++ b/ic-stub/src/IC/Canister/Interface.hs @@ -7,7 +7,6 @@ The point of this abstraction is to to allow adding new entry points, or changin Certain features here are beyond the specified abilities, in order to support the Motoko test suite. In particular: - * Creating canisters * Issuing calls from canister_init -} @@ -21,3 +20,5 @@ data CanisterMethod r where Query :: MethodName -> EntityId -> Blob -> CanisterMethod Response Update :: MethodName -> EntityId -> Responded -> Blob -> CanisterMethod UpdateResult Callback :: Callback -> Responded -> Response -> CanisterMethod UpdateResult + PreUpgrade :: Module -> EntityId -> CanisterMethod Blob + PostUpgrade :: Module -> EntityId -> Blob -> Blob -> CanisterMethod () diff --git a/ic-stub/src/IC/Canister/Persisted.hs b/ic-stub/src/IC/Canister/Persisted.hs index 2a0b4a7075e..b21b3125588 100644 --- a/ic-stub/src/IC/Canister/Persisted.hs +++ b/ic-stub/src/IC/Canister/Persisted.hs @@ -9,11 +9,13 @@ An implementation of canisters based on persistence, using "IC.Canister.Imp". It module IC.Canister.Persisted ( WasmState , initialize + , initializeUpgrade , invoke ) where import Control.Monad.ST +import Data.ByteString.Lazy (ByteString) import IC.Types import IC.Wasm.Winter (Module) @@ -21,7 +23,7 @@ import IC.Wasm.Winter.Persist import qualified IC.Canister.Interface as CI import IC.Canister.Imp -data WasmState = WasmState Module CanisterId PInstance +data WasmState = WasmState Module CanisterId PInstance ByteString initialize :: Module -> CanisterId -> EntityId -> Blob -> TrapOr (InitResult, WasmState) initialize wasm_mod cid caller dat = runESST $ \esref -> @@ -32,6 +34,15 @@ initialize wasm_mod cid caller dat = runESST $ \esref -> Trap err -> return $ Trap err Return ir -> Return . (ir,) <$> newWasmState wasm_mod rs +initializeUpgrade :: Module -> CanisterId -> EntityId -> Blob -> Blob -> TrapOr WasmState +initializeUpgrade wasm_mod cid caller mem dat = runESST $ \esref -> + rawInitialize esref cid wasm_mod >>= \case + Trap err -> return $ Trap err + Return rs -> + rawInvoke rs (CI.PostUpgrade wasm_mod caller mem dat) >>= \case + Trap err -> return $ Trap err + Return () -> Return <$> newWasmState wasm_mod rs + invoke :: WasmState -> CI.CanisterMethod r -> TrapOr (WasmState, r) invoke s m = runESST $ \esref -> do rs <- replay esref s @@ -43,22 +54,23 @@ invoke s m = runESST $ \esref -> do return $ Return (state', r) replay :: ESRef s -> WasmState -> ST s (ImpState s) -replay esref (WasmState wasm_mod cid pinst) = do +replay esref (WasmState wasm_mod cid pinst pmem) = do rs <- rawInitialize esref cid wasm_mod >>= trapToFail - resume rs pinst + resume rs pinst pmem return rs where trapToFail (Trap _err) = fail "replay failed" trapToFail (Return x) = return x newWasmState :: Module -> ImpState s -> ST s WasmState -newWasmState wasm_mod (_esref, cid, inst) = - WasmState wasm_mod cid <$> persistInstance inst +newWasmState wasm_mod (ImpState _ cid inst sm) = + WasmState wasm_mod cid <$> persistInstance inst <*> persistMemory sm -resume :: ImpState s -> PInstance -> ST s () -resume (_, _, inst) pinst = +resume :: ImpState s -> PInstance -> ByteString -> ST s () +resume (ImpState _ _ inst sm) pinst pmem = do resumeInstance inst pinst + resumeMemory sm pmem persist :: WasmState -> ImpState s -> ST s WasmState -persist (WasmState wasm_mod cid _) (_, _, inst) = - WasmState wasm_mod cid <$> persistInstance inst +persist (WasmState wasm_mod cid _ _) (ImpState _ _ inst sm) = + WasmState wasm_mod cid <$> persistInstance inst <*> persistMemory sm diff --git a/ic-stub/src/IC/DRun/Parse.hs b/ic-stub/src/IC/DRun/Parse.hs index d9d268b6b94..e360581c39e 100644 --- a/ic-stub/src/IC/DRun/Parse.hs +++ b/ic-stub/src/IC/DRun/Parse.hs @@ -14,6 +14,7 @@ type Id = B.ByteString data Ingress = Install Id FilePath Payload + | Upgrade Id FilePath Payload | Update Id MethodName Payload | Query Id MethodName Payload deriving Show @@ -30,6 +31,7 @@ parse = map parseLine . lines parseLine :: String -> Ingress parseLine l = case words l of ["install", i, f, a] -> Install (parseId i) f (parseArg a) + ["upgrade", i, f, a] -> Upgrade (parseId i) f (parseArg a) ["ingress", i, m, a] -> Update (parseId i) m (parseArg a) ["query", i, m, a] -> Query (parseId i) m (parseArg a) _ -> error $ "Cannot parse: " ++ show l diff --git a/ic-stub/src/IC/Stub.hs b/ic-stub/src/IC/Stub.hs index dbcba177289..ce6648a4a95 100644 --- a/ic-stub/src/IC/Stub.hs +++ b/ic-stub/src/IC/Stub.hs @@ -42,6 +42,7 @@ import IC.Logger data AsyncRequest = CreateRequest UserId (Maybe CanisterId) | InstallRequest CanisterId UserId Blob Blob + | UpgradeRequest CanisterId UserId Blob Blob | UpdateRequest CanisterId UserId MethodName Blob deriving (Eq, Ord, Show) @@ -187,7 +188,7 @@ createEmptyCanister cid = installCanister :: ICT m => CanisterId -> CanisterModule -> WasmState -> m () installCanister cid can_mod wasm_state = - -- Check that canister exists but is empty before? + -- Check that canister exists but is empty before? No, also used for upgrade. modify (\ic -> ic { canisters = M.insert cid (Just (CanState {can_mod, wasm_state})) (canisters ic) }) @@ -238,6 +239,25 @@ processRequest r@(InstallRequest canister_id user_id can_mod dat) = mapM_ (newCall ctxt_id) new_calls setReqStatus r $ Completed CompleteUnit +processRequest r@(UpgradeRequest canister_id user_id new_can_mod dat) = do + let res = setReqStatus r + case parseCanister new_can_mod of + Left err -> + setReqStatus r $ Rejected (RC_SYS_FATAL, "Parsing failed: " ++ err) + Right new_can_mod -> + gets (M.lookup canister_id . canisters) >>= \case + Nothing -> res $ Rejected (RC_DESTINATION_INVALID, "canister does not exist: " ++ show canister_id) + Just Nothing -> res $ Rejected (RC_DESTINATION_INVALID, "canister is empty") + Just (Just (CanState old_wasm_state old_can_mod)) -> + case pre_upgrade_method old_can_mod old_wasm_state user_id of + Trap msg -> res $ Rejected (RC_CANISTER_ERROR, "Pre-upgrade trapped: " ++ msg) + Return mem -> + case post_upgrade_method new_can_mod user_id user_id mem dat of + Trap msg -> res $ Rejected (RC_CANISTER_ERROR, "post-upgrade trapped: " ++ msg) + Return new_wasm_state -> do + installCanister canister_id new_can_mod new_wasm_state + res $ Completed CompleteUnit + processRequest r@(UpdateRequest canister_id _user_id method arg) = do ctxt_id <- newCallContext $ CallContext { canister = canister_id @@ -283,6 +303,7 @@ rememberTrap ctxt_id msg = callerOfRequest :: AsyncRequest -> EntityId callerOfRequest (CreateRequest user_id _) = user_id callerOfRequest (InstallRequest _ user_id _ _) = user_id +callerOfRequest (UpgradeRequest _ user_id _ _) = user_id callerOfRequest (UpdateRequest _ user_id _ _) = user_id callerOfCallID :: ICT m => CallId -> m EntityId diff --git a/ic-stub/src/IC/Types.hs b/ic-stub/src/IC/Types.hs index b4d254d4b85..76e1c25843c 100644 --- a/ic-stub/src/IC/Types.hs +++ b/ic-stub/src/IC/Types.hs @@ -75,3 +75,5 @@ type ExistingCanisters = [CanisterId] type InitResult = [MethodCall] type UpdateResult = ([MethodCall], Maybe Response) + +type StableMemory = Blob diff --git a/ic-stub/src/IC/Wasm/Winter/Persist.hs b/ic-stub/src/IC/Wasm/Winter/Persist.hs index b7ff5753085..039fcab0d53 100644 --- a/ic-stub/src/IC/Wasm/Winter/Persist.hs +++ b/ic-stub/src/IC/Wasm/Winter/Persist.hs @@ -14,6 +14,8 @@ module IC.Wasm.Winter.Persist ( PInstance , persistInstance , resumeInstance + , persistMemory + , resumeMemory ) where @@ -46,6 +48,12 @@ persistInstance i = PInstance <$> persist i resumeInstance :: Instance s -> PInstance -> ST s () resumeInstance i (PInstance p) = resume i p +persistMemory :: W.MemoryInst (ST s) -> ST s ByteString +persistMemory i = persist i + +resumeMemory :: W.MemoryInst (ST s) -> ByteString -> ST s () +resumeMemory i p = resume i p + class Monad (M a) => Persistable a where type Persisted a :: * type M a :: * -> * diff --git a/ic-stub/src/IC/Wasm/WinterMemory.hs b/ic-stub/src/IC/Wasm/WinterMemory.hs new file mode 100644 index 00000000000..95053242a95 --- /dev/null +++ b/ic-stub/src/IC/Wasm/WinterMemory.hs @@ -0,0 +1,58 @@ +{-# LANGUAGE ScopedTypeVariables #-} +{-| + +This module provides a thin wrapper around the winter Wasm engine, exposing just +the bits needed for accessing the stable memory. This will hopefully go away once +multiple memories are supported. +-} +module IC.Wasm.WinterMemory + ( Memory + , new + , size + , grow + , read + , write + , export + , imp + ) +where + +import Prelude hiding (read) + +import Data.ByteString.Lazy (ByteString) +import Control.Monad.Except +import Control.Monad.ST + +import qualified Wasm.Runtime.Memory as W +import qualified Wasm.Syntax.Types as W +import qualified Wasm.Syntax.Memory as W + +type HostM s = ExceptT String (ST s) +type Memory s = W.MemoryInst (ST s) + +new :: HostM s (Memory s) +new = withExceptT show $ W.alloc (W.Limits 0 Nothing) + +size :: Memory s -> HostM s W.Size +size mem = lift $ W.size mem + +grow :: Memory s -> W.Size -> HostM s W.Size +grow mem delta = lift $ do + -- See memory.grow impl in src/Wasm/Exec/Eval.hs + oldSize <- W.size mem + eres <- runExceptT $ W.grow mem delta + return $ case eres of + Left _ -> -1 + Right () -> oldSize + +read :: Memory s -> W.Address -> W.Size -> HostM s ByteString +read mem ptr len = withExceptT show $ W.loadBytes mem ptr len + +write :: Memory s -> W.Address -> ByteString -> HostM s () +write mem ptr blob = withExceptT show $ W.storeBytes mem (fromIntegral ptr) blob + +export :: Memory s -> ST s ByteString +export = W.exportMemory + +imp :: Memory s -> ByteString -> ST s () +imp = W.importMemory diff --git a/ic-stub/src/ic-stub-run.hs b/ic-stub/src/ic-stub-run.hs index e137058d05a..dac048f1d13 100644 --- a/ic-stub/src/ic-stub-run.hs +++ b/ic-stub/src/ic-stub-run.hs @@ -27,6 +27,8 @@ printAsyncRequest CreateRequest{} = printf "→ create\n" printAsyncRequest InstallRequest{} = printf "→ install\n" +printAsyncRequest UpgradeRequest{} = + printf "→ upgrade\n" printAsyncRequest (UpdateRequest _ _ method arg) = printf "→ update %s(%s)\n" method (prettyBlob arg) @@ -80,6 +82,9 @@ work msg_file = do wasm <- liftIO $ B.readFile filename _ <- submitAndRun (CreateRequest user_id (Just (EntityId cid))) submitAndRun (InstallRequest (EntityId cid) user_id wasm arg) + Upgrade cid filename arg -> do + wasm <- liftIO $ B.readFile filename + submitAndRun (UpgradeRequest (EntityId cid) user_id wasm arg) Query cid method arg -> submitRead (QueryRequest (EntityId cid) user_id method arg) Update cid method arg -> submitAndRun (UpdateRequest (EntityId cid) user_id method arg) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index faa6e3bd156..fcec58601df 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -2827,7 +2827,9 @@ module Lifecycle = struct | InUpdate | InQuery | PostQuery (* an invalid state *) - (* To be added later: InPreUpgrade PostPreUpgrade InPostUpgrade *) + | InPreUpgrade + | PostPreUpgrade (* an invalid state *) + | InPostUpgrade let int_of_state = function | PreInit -> 0l (* Automatically null *) @@ -2840,6 +2842,9 @@ module Lifecycle = struct | InUpdate -> 5l | InQuery -> 6l | PostQuery -> 7l + | InPreUpgrade -> 8l + | PostPreUpgrade -> 9l + | InPostUpgrade -> 10l let ptr = Stack.end_ let end_ = Int32.add Stack.end_ Heap.word_size @@ -2856,6 +2861,18 @@ module Lifecycle = struct | InUpdate -> [Idle] | InQuery -> [Idle] | PostQuery -> [InQuery] + | InPreUpgrade -> [Idle] + | PostPreUpgrade -> [InPreUpgrade] + | InPostUpgrade -> [PreInit] + + let get env = + compile_unboxed_const ptr ^^ + load_unskewed_ptr + + let set env new_state = + compile_unboxed_const ptr ^^ + compile_unboxed_const (int_of_state new_state) ^^ + store_unskewed_ptr let trans env new_state = let name = "trans_state" ^ Int32.to_string (int_of_state new_state) in @@ -2864,16 +2881,12 @@ module Lifecycle = struct let rec go = function | [] -> E.trap_with env "internal error: unexpected state" | (s::ss) -> - compile_unboxed_const (int_of_state s) ^^ - compile_unboxed_const ptr ^^ load_unskewed_ptr ^^ - G.i (Compare (Wasm.Values.I32 I32Op.Eq)) ^^ + get env ^^ compile_eq_const (int_of_state s) ^^ G.if_ [] (G.i (Br (nr 1l))) G.nop ^^ go ss in go (pre_states new_state) ) ^^ - compile_unboxed_const ptr ^^ - compile_unboxed_const (int_of_state new_state) ^^ - store_unskewed_ptr + set env new_state ) end (* Lifecycle *) @@ -2904,8 +2917,14 @@ module Dfinity = struct let system_imports env = match E.mode env with - | Flags.ICMode | Flags.StubMode -> + | Flags.ICMode -> import_ic0 env + | Flags.StubMode -> + import_ic0 env; + E.add_func_import env "ic0" "stable_write" (i32s 3) []; + E.add_func_import env "ic0" "stable_read" (i32s 3) []; + E.add_func_import env "ic0" "stable_size" [] [I32Type]; + E.add_func_import env "ic0" "stable_grow" [I32Type] [I32Type] | Flags.WASIMode -> E.add_func_import env "wasi_unstable" "fd_write" [I32Type; I32Type; I32Type; I32Type] [I32Type]; | Flags.WasmMode -> () @@ -3141,6 +3160,82 @@ module Dfinity = struct compile_unboxed_const 0l ^^ G.i (Compare (Wasm.Values.I32 I32Op.Eq)) ^^ E.else_trap_with env "not a self-call" +let export_upgrade_scaffold env = if E.mode env = Flags.StubMode then + let pre_upgrade_fi = E.add_fun env "pre_upgrade" (Func.of_body env [] [] (fun env -> + Lifecycle.trans env Lifecycle.InPreUpgrade ^^ + + (* grow stable memory if needed *) + let (set_pages_needed, get_pages_needed) = new_local env "pages_needed" in + G.i MemorySize ^^ + E.call_import env "ic0" "stable_size" ^^ + G.i (Binary (Wasm.Values.I32 I32Op.Sub)) ^^ + set_pages_needed ^^ + + get_pages_needed ^^ + compile_unboxed_zero ^^ + G.i (Compare (Wasm.Values.I32 I32Op.GtS)) ^^ + G.if_ [] + ( get_pages_needed ^^ + E.call_import env "ic0" "stable_grow" ^^ + (* Check result *) + compile_unboxed_zero ^^ + G.i (Compare (Wasm.Values.I32 I32Op.LtS)) ^^ + E.then_trap_with env "Cannot grow stable memory." + ) G.nop + ^^ + + (* copy to stable memory *) + compile_unboxed_const 0l ^^ + compile_unboxed_const 0l ^^ + G.i MemorySize ^^ compile_mul_const page_size ^^ + E.call_import env "ic0" "stable_write" ^^ + + Lifecycle.trans env Lifecycle.PostPreUpgrade + )) in + + let post_upgrade_fi = E.add_fun env "post_upgrade" (Func.of_body env [] [] (fun env -> + Lifecycle.trans env Lifecycle.InPostUpgrade ^^ + + (* grow memory if needed *) + let (set_pages_needed, get_pages_needed) = new_local env "pages_needed" in + E.call_import env "ic0" "stable_size" ^^ + G.i MemorySize ^^ + G.i (Binary (Wasm.Values.I32 I32Op.Sub)) ^^ + set_pages_needed ^^ + + get_pages_needed ^^ + compile_unboxed_zero ^^ + G.i (Compare (Wasm.Values.I32 I32Op.GtS)) ^^ + G.if_ [] + ( get_pages_needed ^^ + G.i MemoryGrow ^^ + (* Check result *) + compile_unboxed_zero ^^ + G.i (Compare (Wasm.Values.I32 I32Op.LtS)) ^^ + E.then_trap_with env "Cannot grow memory." + ) G.nop + ^^ + + (* copy from stable memory *) + compile_unboxed_const 0l ^^ + compile_unboxed_const 0l ^^ + E.call_import env "ic0" "stable_size" ^^ compile_mul_const page_size ^^ + E.call_import env "ic0" "stable_read" ^^ + + (* set, not trans, as we just copied the memory over *) + Lifecycle.set env Lifecycle.Idle + )) in + + E.add_export env (nr { + name = Wasm.Utf8.decode "canister_pre_upgrade"; + edesc = nr (FuncExport (nr pre_upgrade_fi)) + }); + + E.add_export env (nr { + name = Wasm.Utf8.decode "canister_post_upgrade"; + edesc = nr (FuncExport (nr post_upgrade_fi)) + }) + end (* Dfinity *) @@ -6983,6 +7078,8 @@ and conclude_module env start_fi_o = let static_roots = GC.store_static_roots env in + Dfinity.export_upgrade_scaffold env; + (* add beginning-of-heap pointer, may be changed by linker *) (* needs to happen here now that we know the size of static memory *) E.add_global32 env "__heap_base" Immutable (E.get_end_of_static_memory env); @@ -6998,6 +7095,7 @@ and conclude_module env start_fi_o = Dfinity.default_exports env; + GC.register env static_roots (E.get_end_of_static_memory env); let func_imports = E.get_func_imports env in diff --git a/test/drun-wrapper.sh b/test/drun-wrapper.sh index b76ebf7b711..164e11f7d8c 100755 --- a/test/drun-wrapper.sh +++ b/test/drun-wrapper.sh @@ -28,5 +28,5 @@ export LANG=C.UTF-8 EXTRA_BATCHES=100 (echo "install ic:2A012B $1 0x"; - if [ -n "$2" ]; then LANG=C perl -ne 'print "$1 ic:2A012B $2\n" if m,^//CALL (ingress|query) (.*),' $2; fi; + if [ -n "$2" ]; then LANG=C perl -ne 'print "$1 ic:2A012B $2\n" if m,^//CALL (ingress|query) (.*),;print "upgrade ic:2A012B '"$1"' 0x" if m,^//CALL upgrade,; ' $2; fi; ) | $DRUN -c "$CONFIG" --extra-batches $EXTRA_BATCHES /dev/stdin diff --git a/test/ic-stub-run-wrapper.sh b/test/ic-stub-run-wrapper.sh index cc86f26c25b..52135b00f0e 100755 --- a/test/ic-stub-run-wrapper.sh +++ b/test/ic-stub-run-wrapper.sh @@ -13,10 +13,6 @@ fi export LANG=C.UTF-8 -# canister id "ic:000000000000040054", in little-endian decimal, is: -# 1125899906842624 -# (drun currently expects a decimal number for the canister id) - (echo "install ic:2A012B $1 0x"; - if [ -n "$2" ]; then LANG=C perl -ne 'print "$1 ic:2A012B $2\n" if m,^//CALL (ingress|query) (.*),' $2; fi; + if [ -n "$2" ]; then LANG=C perl -ne 'print "$1 ic:2A012B $2\n" if m,^//CALL (ingress|query) (.*),;print "upgrade ic:2A012B '"$1"' 0x\n" if m,^//CALL upgrade,; ' $2; fi; ) | $IC_STUB_RUN -c "$CONFIG" /dev/stdin diff --git a/test/run-drun/ok/upgrade.ic-stub-run.ok b/test/run-drun/ok/upgrade.ic-stub-run.ok new file mode 100644 index 00000000000..03f65da92f6 --- /dev/null +++ b/test/run-drun/ok/upgrade.ic-stub-run.ok @@ -0,0 +1,23 @@ +→ create +← completed: canister-id = 0x2a01 +→ install +debug.print: init'ed +← completed +→ query check(0x4449444c00017d01) +← completed: 0x4449444c0000 +→ update inc(0x4449444c0000) +← completed: 0x4449444c0000 +→ query check(0x4449444c00017d02) +← completed: 0x4449444c0000 +→ update inc(0x4449444c0000) +← completed: 0x4449444c0000 +→ query check(0x4449444c00017d03) +← completed: 0x4449444c0000 +→ upgrade +← completed +→ query check(0x4449444c00017d03) +← completed: 0x4449444c0000 +→ update inc(0x4449444c0000) +← completed: 0x4449444c0000 +→ query check(0x4449444c00017d04) +← completed: 0x4449444c0000 diff --git a/test/run-drun/upgrade.mo b/test/run-drun/upgrade.mo new file mode 100644 index 00000000000..dbfc0465aab --- /dev/null +++ b/test/run-drun/upgrade.mo @@ -0,0 +1,27 @@ +import Prim "mo:prim"; +actor { + Prim.debugPrint ("init'ed"); + + var always10 = 10; + var c = 1; + public func inc() { c += 1; }; + public query func check(n : Int) : async () { + assert (c == n); + assert (always10 == 10); + }; +} + +//CALL query check "DIDL\x00\x01\x7d\x01" +//CALL ingress inc "DIDL\x00\x00" +//CALL query check "DIDL\x00\x01\x7d\x02" +//CALL ingress inc "DIDL\x00\x00" +//CALL query check "DIDL\x00\x01\x7d\x03" +//CALL upgrade +//CALL query check "DIDL\x00\x01\x7d\x03" +//CALL ingress inc "DIDL\x00\x00" +//CALL query check "DIDL\x00\x01\x7d\x04" + +//SKIP run +//SKIP run-ir +//SKIP run-low +//SKIP comp From 12a027e235180b0a72e949a6214b3184ac010081 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Thu, 27 Feb 2020 16:03:11 +0000 Subject: [PATCH 1071/1176] add scope violation test --- test/fail/inference.mo | 10 +++++++--- test/fail/ok/inference.tc.ok | 8 +++++--- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/test/fail/inference.mo b/test/fail/inference.mo index c3a25d56133..75a5f49c1e1 100644 --- a/test/fail/inference.mo +++ b/test/fail/inference.mo @@ -91,9 +91,9 @@ ignore contra(func (x:Nat,y:Bool) {}); func coswap(x : T,y : T):(U,U){(y,x)}; -ignore coswap(1,2); // works (coz Int <: Nat) -ignore coswap(1,2:Int); // works (coz Int <: Nat) -ignore coswap(1,true); // doesn't work unless we lub with bound +ignore coswap(1,2); // rejected due to open bounds +ignore coswap(1,2:Int); // rejected due to open bounds +ignore coswap(1,true); // rejected due to open bounds // support domain driven overloading for implicitly scoped, @@ -111,6 +111,10 @@ ignore (if false (bnd(loop {}):None) else 1); // fails, underspecialized, requir bnd(true); +func scopeco(f:T->U){}; +scopeco(func(x:V):V{x}); +func scopecontra(f:U->T){}; +scopecontra(func(x:V):V{x}); //TODO: invariant mutables, constructor constraints, bail on open bounds diff --git a/test/fail/ok/inference.tc.ok b/test/fail/ok/inference.tc.ok index e1f20aeda84..39b61227555 100644 --- a/test/fail/ok/inference.tc.ok +++ b/test/fail/ok/inference.tc.ok @@ -14,13 +14,13 @@ inference.mo:67.8-67.43: type error, cannot instantiate function of type (T - over-constrained implicit instantiation requires Any <: T <: None, but Any (T, T) -> (U, U) to argument of type (Nat, Nat): - type parameter T has an open bound U/9 mentioning another type parameter + type parameter T has an open bound U/11 mentioning another type parameter ; explicit type instantiation required inference.mo:95.8-95.23: type error, cannot instantiate function of type (T, T) -> (U, U) to argument of type (Nat, Int): - type parameter T has an open bound U/10 mentioning another type parameter + type parameter T has an open bound U/12 mentioning another type parameter ; explicit type instantiation required inference.mo:96.8-96.22: type error, cannot instantiate function of type (T, T) -> (U, U) to argument of type (Nat, Bool): - type parameter T has an open bound U/11 mentioning another type parameter + type parameter T has an open bound U/13 mentioning another type parameter ; explicit type instantiation required inference.mo:107.8-107.14: type error, cannot instantiate function of type T -> T to argument of type Nat: under-constrained implicit instantiation Nat <: T <: Int, @@ -36,3 +36,5 @@ cannot produce expected type inference.mo:111.1-111.10: type error, cannot instantiate function of type T -> T to argument of type Bool: over-constrained implicit instantiation requires Bool <: T <: Int, but Bool (T -> U) -> () cannot be instantiated to consume argument of type V -> V +inference.mo:117.1-117.31: type error, function of type (U -> T) -> () cannot be instantiated to consume argument of type V -> V From a658af368750a6452bc86ca49498e9ab62f50b5e Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Thu, 27 Feb 2020 16:03:51 +0000 Subject: [PATCH 1072/1176] add scope violation test --- test/fail/inference.mo | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/fail/inference.mo b/test/fail/inference.mo index 75a5f49c1e1..b57c2a295f7 100644 --- a/test/fail/inference.mo +++ b/test/fail/inference.mo @@ -112,9 +112,9 @@ bnd(true); func scopeco(f:T->U){}; -scopeco(func(x:V):V{x}); +scopeco(func(x:V):V{x}); // reject due to scope violation func scopecontra(f:U->T){}; -scopecontra(func(x:V):V{x}); +scopecontra(func(x:V):V{x}); // reject due to scope violation //TODO: invariant mutables, constructor constraints, bail on open bounds From 4f0b457d7b63207468d90e708dc4ae35bc82276d Mon Sep 17 00:00:00 2001 From: Nikola Knezevic Date: Thu, 20 Feb 2020 18:00:17 +0100 Subject: [PATCH 1073/1176] INF-996 .github: Add action for updating niv-dependencies Bye, bye, manual PR creation everytime common changes. --- .github/workflows/niv-updater.yml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 .github/workflows/niv-updater.yml diff --git a/.github/workflows/niv-updater.yml b/.github/workflows/niv-updater.yml new file mode 100644 index 00000000000..5801e1ac243 --- /dev/null +++ b/.github/workflows/niv-updater.yml @@ -0,0 +1,27 @@ +name: Automatically update niv-managed dependencies +on: + # Manual override, one can start the workflow by running: + # curl -H "Accept: application/vnd.github.everest-preview+json" \ + # -H "Authorization: token " \ + # --request POST \ + # --data '{"event_type": "niv-updater-nudge", "client_payload": {}}' \ + # https://api.github.com/repos/dfinity-lab/motoko/dispatches + # https://help.github.com/en/actions/reference/events-that-trigger-workflows#external-events-repository_dispatch + repository_dispatch: + types: niv-updater-nudge + schedule: + # * is a special character in YAML so you have to quote this string + # Run every 20min, as we like it that way (but it should be hourly) + - cron: '*/20 * * * *' +jobs: + niv-updater: + name: 'Check for updates' + runs-on: ubuntu-latest + steps: + - name: niv-updater-action + uses: knl/niv-updater-action@v3 + with: + # might be too noisy + blacklist: 'nixpkgs,dfinity' + env: + GITHUB_TOKEN: ${{ secrets.NIV_UPDATER_TOKEN }} From e93a3ddb72e6fcb3d73662d436798cfc64934131 Mon Sep 17 00:00:00 2001 From: DFINITY bot <58022693+dfinity-bot@users.noreply.github.com> Date: Fri, 28 Feb 2020 15:24:15 +0100 Subject: [PATCH 1074/1176] ## Changelog for common: (#1250) Commits: [dfinity-lab/common@7278afe2...6f8f0311](https://github.com/dfinity-lab/common/compare/7278afe2b6ddcd0c78c82fae38160bc4583fc1a6...6f8f03113b16177e35c9ac7ea3448e3a4aa2d055) * [422f8ec5](https://github.com/dfinity-lab/common/commit/422f8ec5d23e0ceae4db28ede0f1be578a87ea65) unpacker: stop trampling (#138) * [3f4d3077](https://github.com/dfinity-lab/common/commit/3f4d307796b48c535f7cd2c2eb6c9298c5387928) nix: specify a sha256 for fetching sources.nix * [4d317b75](https://github.com/dfinity-lab/common/commit/4d317b75180773cdd70a5189e7ffab295c96edd8) Merge pull request #139 from dfinity-lab/basvandijk/specify-sha256-for-sources.nix * [6f8f0311](https://github.com/dfinity-lab/common/commit/6f8f03113b16177e35c9ac7ea3448e3a4aa2d055) INF-1023: Run benchmarks on CI --- nix/sources.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/sources.json b/nix/sources.json index fc85a4c6513..7a4907fb51e 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -2,7 +2,7 @@ "common": { "ref": "master", "repo": "ssh://git@github.com/dfinity-lab/common", - "rev": "7278afe2b6ddcd0c78c82fae38160bc4583fc1a6", + "rev": "6f8f03113b16177e35c9ac7ea3448e3a4aa2d055", "type": "git" }, "dfinity": { From 52b0e7b9344feb23ceb2dab84fa0362786468417 Mon Sep 17 00:00:00 2001 From: Bas van Dijk Date: Sat, 29 Feb 2020 22:13:04 +0100 Subject: [PATCH 1075/1176] nix/sources.json: update common for the nixpkgs upgrade (#1251) For the changelog see: https://github.com/dfinity-lab/common/pull/144 --- nix/sources.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/sources.json b/nix/sources.json index 7a4907fb51e..a6483263e25 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -2,7 +2,7 @@ "common": { "ref": "master", "repo": "ssh://git@github.com/dfinity-lab/common", - "rev": "6f8f03113b16177e35c9ac7ea3448e3a4aa2d055", + "rev": "53663c4957c0db10ce9bf8401ed768ad0cb8faa9", "type": "git" }, "dfinity": { From 3ca2ddf6516f4659335024d7b0343a295d3402f3 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Sat, 29 Feb 2020 22:05:22 +0000 Subject: [PATCH 1076/1176] reject instantiation at mut types --- src/mo_types/type.ml | 4 ++-- test/fail/inference.mo | 9 +++++++++ test/fail/ok/inference.tc.ok | 10 ++++++++-- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index c2799839019..e28eac9ce95 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -1544,7 +1544,7 @@ let bimatch_typ scope_opt tbs t1 t2 = Some inst | _, Con (con2, ts2) when flexible con2 -> assert (ts2 = []); - if mentions t1 any then + if mentions t1 any || is_mut (normalize t1) then None else (match ConEnv.find_opt con2 l with @@ -1554,7 +1554,7 @@ let bimatch_typ scope_opt tbs t1 t2 = | None -> Some (ConEnv.add con2 t1 l, u)) | Con (con1, ts1), _ when flexible con1 -> assert (ts1 = []); - if mentions t2 any then + if mentions t2 any || is_mut (normalize t2) then None else (match ConEnv.find_opt con1 u with diff --git a/test/fail/inference.mo b/test/fail/inference.mo index b57c2a295f7..069b5ae2637 100644 --- a/test/fail/inference.mo +++ b/test/fail/inference.mo @@ -111,6 +111,7 @@ ignore (if false (bnd(loop {}):None) else 1); // fails, underspecialized, requir bnd(true); +// reject scope violations func scopeco(f:T->U){}; scopeco(func(x:V):V{x}); // reject due to scope violation func scopecontra(f:U->T){}; @@ -119,3 +120,11 @@ scopecontra(func(x:V):V{x}); // reject due to scope violation //TODO: invariant mutables, constructor constraints, bail on open bounds +// reject instantiations at `var _` +func sub(x:[T]):T{x[0]}; +sub([1]); +sub([var 1]); // reject + +func sub_mut(x:[var T]):T{x[0]}; +sub_mut([1]); // reject +sub_mut([var 1]); \ No newline at end of file diff --git a/test/fail/ok/inference.tc.ok b/test/fail/ok/inference.tc.ok index 39b61227555..d8dee29417b 100644 --- a/test/fail/ok/inference.tc.ok +++ b/test/fail/ok/inference.tc.ok @@ -36,5 +36,11 @@ cannot produce expected type inference.mo:111.1-111.10: type error, cannot instantiate function of type T -> T to argument of type Bool: over-constrained implicit instantiation requires Bool <: T <: Int, but Bool (T -> U) -> () cannot be instantiated to consume argument of type V -> V -inference.mo:117.1-117.31: type error, function of type (U -> T) -> () cannot be instantiated to consume argument of type V -> V +inference.mo:116.1-116.27: type error, function of type (T -> U) -> () cannot be instantiated to consume argument of type V -> V +inference.mo:118.1-118.31: type error, function of type (U -> T) -> () cannot be instantiated to consume argument of type V -> V +inference.mo:125.1-125.9: type error, expression of type + Nat +cannot produce expected type + () +inference.mo:126.1-126.13: type error, function of type [T] -> T cannot be instantiated to consume argument of type [var Nat] +inference.mo:129.1-129.13: type error, function of type [var T] -> T cannot be instantiated to consume argument of type [Nat] From f47f868ac6189b8504daa26b600742cc8af77daa Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Sat, 29 Feb 2020 23:03:44 +0000 Subject: [PATCH 1077/1176] tests involving open types with bounded pars --- test/fail/inference.mo | 23 ++++++++++++++++++++++- test/fail/ok/inference.tc.ok | 14 ++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/test/fail/inference.mo b/test/fail/inference.mo index 069b5ae2637..fad54367be3 100644 --- a/test/fail/inference.mo +++ b/test/fail/inference.mo @@ -127,4 +127,25 @@ sub([var 1]); // reject func sub_mut(x:[var T]):T{x[0]}; sub_mut([1]); // reject -sub_mut([var 1]); \ No newline at end of file +sub_mut([var 1]); + +// tricky examples involving open typing with bounded parameters +func g(x:T) { + func f(y:U) {}; + f(x); // reject, overconstrained U +}; + +func h(x:T) { + func f(y:U) {}; + f(x); // reject, underconstrained U +}; + +func i(x:T) { + func f(y:U):U{y}; + ignore f(x); // accept +}; + +func j(x:T) { + func f(y:U):U{y}; + ignore f(x) : None; // fail (requires inference w.r.t expected type +}; diff --git a/test/fail/ok/inference.tc.ok b/test/fail/ok/inference.tc.ok index d8dee29417b..9332297266a 100644 --- a/test/fail/ok/inference.tc.ok +++ b/test/fail/ok/inference.tc.ok @@ -44,3 +44,17 @@ cannot produce expected type () inference.mo:126.1-126.13: type error, function of type [T] -> T cannot be instantiated to consume argument of type [var Nat] inference.mo:129.1-129.13: type error, function of type [var T] -> T cannot be instantiated to consume argument of type [Nat] +inference.mo:130.1-130.17: type error, expression of type + Nat +cannot produce expected type + () +inference.mo:135.4-135.8: type error, cannot instantiate function of type U -> () to argument of type T/34: + over-constrained implicit instantiation requires T/34 <: U <: {}, + but T/34 U -> () to argument of type T/35: + under-constrained implicit instantiation T/35 <: U <: {}, + with T/35 =/= {}; explicit type instantiation required +inference.mo:150.11-150.15: type error, expression of type + T/37 +cannot produce expected type + None From 58e948bb9e81f6c571d8c59c94e6c61f71d68d17 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Sun, 1 Mar 2020 13:58:21 +0100 Subject: [PATCH 1078/1176] nix: Track nixpkgs-unstable, not master (#1241) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit nixpkgs-unstable is like master, but supposedly only when certain “important” packages have built on linux and darwin, and are available from the official nix cache. Seems like a better choice. See Bas’ comment in https://dfinity.slack.com/archives/CGXFE1VMW/p1582808508019200?thread_ts=1582666474.010400&cid=CGXFE1VMW and the docs at https://nixos.wiki/wiki/Nix_channels and https://howoldis.herokuapp.com/ --- nix/sources.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/nix/sources.json b/nix/sources.json index a6483263e25..41e294237e7 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -32,14 +32,14 @@ "version": "v1.2.0" }, "nixpkgs": { - "branch": "master", + "branch": "nixpkgs-unstable", "homepage": "https://github.com/NixOS/nixpkgs", "owner": "NixOS", - "repo": "nixpkgs", - "rev": "82a6834e3b1ae343fed1d9495943fba71d6759fa", - "sha256": "0q6vdl3m80mv9vlgix6116vghgnnr1hixa60b3wv7krxx3gaz626", + "repo": "nixpkgs-channels", + "rev": "ca3531850844e185d483fb878fcd00c6b44069e5", + "sha256": "1s1zhzdbmdd7l936g7ydzsjqdi5k5ch6vpjilil0jiwjhrpkw3m4", "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/82a6834e3b1ae343fed1d9495943fba71d6759fa.tar.gz", + "url": "https://github.com/NixOS/nixpkgs/archive/ca3531850844e185d483fb878fcd00c6b44069e5.tar.gz", "url_template": "https://github.com///archive/.tar.gz" }, "ocaml-vlq": { From 4a9cc84456ed27f9e7dab32c6f6a8b5c0d8c4458 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 2 Mar 2020 11:23:46 +0100 Subject: [PATCH 1079/1176] Nix: Fetch ic-stub from ic-ref repo (#1243) * Nix: Fetch ic-stub from ic-ref repo and stopping calling it IC Stub, but rather IC Ref. * Empty commit * Bump ic-ref * Rename ok files * More test updates * Less stub, more ref --- Building.md | 2 +- default.nix | 13 +- ic-stub/.gitignore | 23 - ic-stub/.hlint.yaml | 6 - ic-stub/README.md | 68 --- ic-stub/cabal.project | 1 - ic-stub/ic-stub.cabal | 49 -- ic-stub/shell.nix | 15 - ic-stub/src/IC/Canister.hs | 69 --- ic-stub/src/IC/Canister/Imp.hs | 488 ------------------ ic-stub/src/IC/Canister/Interface.hs | 24 - ic-stub/src/IC/Canister/Persisted.hs | 76 --- ic-stub/src/IC/Canister/Pure.hs | 69 --- ic-stub/src/IC/DRun/Parse.hs | 63 --- ic-stub/src/IC/Id.hs | 14 - ic-stub/src/IC/Logger.hs | 12 - ic-stub/src/IC/Stub.hs | 399 -------------- ic-stub/src/IC/Types.hs | 79 --- ic-stub/src/IC/Wasm/Imports.hs | 244 --------- ic-stub/src/IC/Wasm/Winter.hs | 133 ----- ic-stub/src/IC/Wasm/Winter/Persist.hs | 139 ----- ic-stub/src/IC/Wasm/WinterMemory.hs | 58 --- ic-stub/src/ic-stub-run.hs | 111 ---- nix/generate.nix | 11 - nix/generated/ic-stub.nix | 23 - nix/generated/winter.nix | 37 -- nix/haskell-packages.nix | 4 - nix/sources.json | 6 + samples/app/Makefile | 2 +- src/codegen/compile.ml | 38 +- src/exes/moc.ml | 6 +- src/mo_config/flags.ml | 2 +- src/mo_frontend/typing.ml | 16 +- test/compare-wat.sh | 4 +- ...b-run-wrapper.sh => ic-ref-run-wrapper.sh} | 4 +- test/run-drun/AST-64.mo | 2 +- test/run-drun/actor-creation.mo | 2 +- test/run-drun/actor-import.mo | 2 +- test/run-drun/chat.mo | 2 +- test/run-drun/control.mo | 2 +- test/run-drun/create-then-trap.mo | 4 +- test/run-drun/general-type-components.mo | 2 +- test/run-drun/large-array.mo | 2 +- test/run-drun/log-slow.mo | 2 +- ...66.ic-stub-run.ok => AST-66.ic-ref-run.ok} | 0 ...3.ic-stub-run.ok => GIT-843.ic-ref-run.ok} | 0 ...stub-run.ok => actor-import.ic-ref-run.ok} | 0 ...k => actor-reference-return.ic-ref-run.ok} | 0 ...b-run.ok => actor-reference.ic-ref-run.ok} | 0 ...ybug.comp-stub.ok => aritybug.comp-ref.ok} | 2 +- ...p-stub.ret.ok => aritybug.comp-ref.ret.ok} | 0 ...n.ok => array-out-of-bounds.ic-ref-run.ok} | 0 ...ic-stub-run.ok => async-any.ic-ref-run.ok} | 0 ...stub-run.ok => async-calls1.ic-ref-run.ok} | 0 ...stub-run.ok => async-calls2.ic-ref-run.ok} | 0 ...stub-run.ok => async-calls3.ic-ref-run.ok} | 0 ...ub-run.ok => async-free-var.ic-ref-run.ok} | 0 ...-run.ok => async-loop-while.ic-ref-run.ok} | 0 ...c-stub-run.ok => async-loop.ic-ref-run.ok} | 0 ...tub-run.ok => async-new-obj.ic-ref-run.ok} | 0 ...tub-run.ok => async-obj-mut.ic-ref-run.ok} | 0 ...-stub-run.ok => async-while.ic-ref-run.ok} | 0 ...-stub-run.ok => await-sugar.ic-ref-run.ok} | 0 ...ait.ic-stub-run.ok => await.ic-ref-run.ok} | 0 ...ock.ic-stub-run.ok => block.ic-ref-run.ok} | 0 ...run.ok => call-async-method.ic-ref-run.ok} | 0 ...er.ic-stub-run.ok => caller.ic-ref-run.ok} | 0 ...ub-run.ok => closure-params.ic-ref-run.ok} | 0 ...b-run.ok => count-callbacks.ic-ref-run.ok} | 0 ...r.ic-stub-run.ok => counter.ic-ref-run.ok} | 0 ....ic-stub-run.ok => counter2.ic-ref-run.ok} | 0 ...-stub-run.ok => data-params.ic-ref-run.ok} | 0 ...ub-run.ok => divide-by-zero.ic-ref-run.ok} | 0 ...-stub-run.ok => empty-actor.ic-ref-run.ok} | 0 ...c-stub-run.ok => empty-call.ic-ref-run.ok} | 0 ...un.ok => flatten-awaitables.ic-ref-run.ok} | 0 ...ic-stub-run.ok => for-await.ic-ref-run.ok} | 0 ...ub-run.ok => free-callbacks.ic-ref-run.ok} | 0 ...tub-run.ok => general_await.ic-ref-run.ok} | 0 ...k => general_await_implicit.ic-ref-run.ok} | 0 ...-run.ok => generic-tail-rec.ic-ref-run.ok} | 0 ...run.ok => hello-world-async.ic-ref-run.ok} | 0 ...run.ok => hello-world-await.ic-ref-run.ok} | 0 ...n.ok => hello-world-message.ic-ref-run.ok} | 0 ...un.ok => hello-world-return.ic-ref-run.ok} | 0 ...-stub-run.ok => hello-world.ic-ref-run.ok} | 0 ....ic-stub-run.ok => ic-calls.ic-ref-run.ok} | 0 ...y.ic-stub-run.ok => idl-any.ic-ref-run.ok} | 0 ...d.ic-stub-run.ok => idl-bad.ic-ref-run.ok} | 0 ...-run.ok => idl-buf-size-bug.ic-ref-run.ok} | 0 ...-run.ok => idl-field-escape.ic-ref-run.ok} | 0 ....ic-stub-run.ok => idl-func.ic-ref-run.ok} | 0 ...mo.ic-stub-run.ok => idl-mo.ic-ref-run.ok} | 0 ....ic-stub-run.ok => idl-nary.ic-ref-run.ok} | 0 ...-stub-run.ok => idl-nat-int.ic-ref-run.ok} | 0 ...c-stub-run.ok => idl-option.ic-ref-run.ok} | 0 ....ic-stub-run.ok => idl-pair.ic-ref-run.ok} | 0 ...c-stub-run.ok => idl-record.ic-ref-run.ok} | 0 ...tub-run.ok => idl-shorthand.ic-ref-run.ok} | 0 ...ic-stub-run.ok => idl-tuple.ic-ref-run.ok} | 0 ....ic-stub-run.ok => idl-unit.ic-ref-run.ok} | 0 ...-stub-run.ok => idl-variant.ic-ref-run.ok} | 0 ...c-stub-run.ok => idl-vector.ic-ref-run.ok} | 0 ...c-stub-run.ok => interleave.ic-ref-run.ok} | 0 ...ic-stub-run.ok => issue-894.ic-ref-run.ok} | 0 ...-stub-run.ok => local-throw.ic-ref-run.ok} | 0 ...c-stub-run.ok => mod-rebind.ic-ref-run.ok} | 0 ...c-stub-run.ok => nary-async.ic-ref-run.ok} | 0 ...stub-run.ok => oneway-throw.ic-ref-run.ok} | 0 ...ay.ic-stub-run.ok => oneway.ic-ref-run.ok} | 0 .../{oom.ic-stub-run.ok => oom.ic-ref-run.ok} | 0 ....ic-stub-run.ok => overflow.ic-ref-run.ok} | 0 ...mp-stub.ok => pass-references.comp-ref.ok} | 2 +- ...ret.ok => pass-references.comp-ref.ret.ok} | 0 ...b-run.ok => print-from-init.ic-ref-run.ok} | 0 ...ery.ic-stub-run.ok => query.ic-ref-run.ok} | 0 ...y2.ic-stub-run.ok => query2.ic-ref-run.ok} | 0 ...ct.ic-stub-run.ok => reject.ic-ref-run.ok} | 0 ...ic-stub-run.ok => rts-stats.ic-ref-run.ok} | 0 ...w.comp-stub.ok => self-shadow.comp-ref.ok} | 2 +- ...tub.ret.ok => self-shadow.comp-ref.ret.ok} | 0 ....ic-stub-run.ok => selftail.ic-ref-run.ok} | 0 ...tub-run.ok => shared-object.ic-ref-run.ok} | 0 ...c-stub-run.ok => sharingbug.ic-ref-run.ok} | 0 ...show.ic-stub-run.ok => show.ic-ref-run.ok} | 0 ...ic-stub-run.ok => static-gc.ic-ref-run.ok} | 0 ...stub-run.ok => switch-await.ic-ref-run.ok} | 0 ...ic-stub-run.ok => text-iter.ic-ref-run.ok} | 0 ...row.ic-stub-run.ok => throw.ic-ref-run.ok} | 0 ...ic-stub-run.ok => transpose.ic-ref-run.ok} | 0 ....ic-stub-run.ok => type-lub.ic-ref-run.ok} | 0 ...p-stub.ok => unsupported-more.comp-ref.ok} | 2 +- ...et.ok => unsupported-more.comp-ref.ret.ok} | 0 ...d.comp-stub.ok => unsupported.comp-ref.ok} | 16 +- ...tub.ret.ok => unsupported.comp-ref.ret.ok} | 0 ...e.ic-stub-run.ok => upgrade.ic-ref-run.ok} | 0 ...utf8.ic-stub-run.ok => utf8.ic-ref-run.ok} | 0 test/run-drun/reference-params.mo | 2 +- test/run-drun/show-in-actor.mo | 2 +- test/run-drun/tailpositions.mo | 2 +- test/run.sh | 26 +- 141 files changed, 89 insertions(+), 2295 deletions(-) delete mode 100644 ic-stub/.gitignore delete mode 100644 ic-stub/.hlint.yaml delete mode 100644 ic-stub/README.md delete mode 100644 ic-stub/cabal.project delete mode 100644 ic-stub/ic-stub.cabal delete mode 100644 ic-stub/shell.nix delete mode 100644 ic-stub/src/IC/Canister.hs delete mode 100644 ic-stub/src/IC/Canister/Imp.hs delete mode 100644 ic-stub/src/IC/Canister/Interface.hs delete mode 100644 ic-stub/src/IC/Canister/Persisted.hs delete mode 100644 ic-stub/src/IC/Canister/Pure.hs delete mode 100644 ic-stub/src/IC/DRun/Parse.hs delete mode 100644 ic-stub/src/IC/Id.hs delete mode 100644 ic-stub/src/IC/Logger.hs delete mode 100644 ic-stub/src/IC/Stub.hs delete mode 100644 ic-stub/src/IC/Types.hs delete mode 100644 ic-stub/src/IC/Wasm/Imports.hs delete mode 100644 ic-stub/src/IC/Wasm/Winter.hs delete mode 100644 ic-stub/src/IC/Wasm/Winter/Persist.hs delete mode 100644 ic-stub/src/IC/Wasm/WinterMemory.hs delete mode 100644 ic-stub/src/ic-stub-run.hs delete mode 100644 nix/generated/ic-stub.nix delete mode 100644 nix/generated/winter.nix rename test/{ic-stub-run-wrapper.sh => ic-ref-run-wrapper.sh} (82%) rename test/run-drun/ok/{AST-66.ic-stub-run.ok => AST-66.ic-ref-run.ok} (100%) rename test/run-drun/ok/{GIT-843.ic-stub-run.ok => GIT-843.ic-ref-run.ok} (100%) rename test/run-drun/ok/{actor-import.ic-stub-run.ok => actor-import.ic-ref-run.ok} (100%) rename test/run-drun/ok/{actor-reference-return.ic-stub-run.ok => actor-reference-return.ic-ref-run.ok} (100%) rename test/run-drun/ok/{actor-reference.ic-stub-run.ok => actor-reference.ic-ref-run.ok} (100%) rename test/run-drun/ok/{aritybug.comp-stub.ok => aritybug.comp-ref.ok} (72%) rename test/run-drun/ok/{aritybug.comp-stub.ret.ok => aritybug.comp-ref.ret.ok} (100%) rename test/run-drun/ok/{array-out-of-bounds.ic-stub-run.ok => array-out-of-bounds.ic-ref-run.ok} (100%) rename test/run-drun/ok/{async-any.ic-stub-run.ok => async-any.ic-ref-run.ok} (100%) rename test/run-drun/ok/{async-calls1.ic-stub-run.ok => async-calls1.ic-ref-run.ok} (100%) rename test/run-drun/ok/{async-calls2.ic-stub-run.ok => async-calls2.ic-ref-run.ok} (100%) rename test/run-drun/ok/{async-calls3.ic-stub-run.ok => async-calls3.ic-ref-run.ok} (100%) rename test/run-drun/ok/{async-free-var.ic-stub-run.ok => async-free-var.ic-ref-run.ok} (100%) rename test/run-drun/ok/{async-loop-while.ic-stub-run.ok => async-loop-while.ic-ref-run.ok} (100%) rename test/run-drun/ok/{async-loop.ic-stub-run.ok => async-loop.ic-ref-run.ok} (100%) rename test/run-drun/ok/{async-new-obj.ic-stub-run.ok => async-new-obj.ic-ref-run.ok} (100%) rename test/run-drun/ok/{async-obj-mut.ic-stub-run.ok => async-obj-mut.ic-ref-run.ok} (100%) rename test/run-drun/ok/{async-while.ic-stub-run.ok => async-while.ic-ref-run.ok} (100%) rename test/run-drun/ok/{await-sugar.ic-stub-run.ok => await-sugar.ic-ref-run.ok} (100%) rename test/run-drun/ok/{await.ic-stub-run.ok => await.ic-ref-run.ok} (100%) rename test/run-drun/ok/{block.ic-stub-run.ok => block.ic-ref-run.ok} (100%) rename test/run-drun/ok/{call-async-method.ic-stub-run.ok => call-async-method.ic-ref-run.ok} (100%) rename test/run-drun/ok/{caller.ic-stub-run.ok => caller.ic-ref-run.ok} (100%) rename test/run-drun/ok/{closure-params.ic-stub-run.ok => closure-params.ic-ref-run.ok} (100%) rename test/run-drun/ok/{count-callbacks.ic-stub-run.ok => count-callbacks.ic-ref-run.ok} (100%) rename test/run-drun/ok/{counter.ic-stub-run.ok => counter.ic-ref-run.ok} (100%) rename test/run-drun/ok/{counter2.ic-stub-run.ok => counter2.ic-ref-run.ok} (100%) rename test/run-drun/ok/{data-params.ic-stub-run.ok => data-params.ic-ref-run.ok} (100%) rename test/run-drun/ok/{divide-by-zero.ic-stub-run.ok => divide-by-zero.ic-ref-run.ok} (100%) rename test/run-drun/ok/{empty-actor.ic-stub-run.ok => empty-actor.ic-ref-run.ok} (100%) rename test/run-drun/ok/{empty-call.ic-stub-run.ok => empty-call.ic-ref-run.ok} (100%) rename test/run-drun/ok/{flatten-awaitables.ic-stub-run.ok => flatten-awaitables.ic-ref-run.ok} (100%) rename test/run-drun/ok/{for-await.ic-stub-run.ok => for-await.ic-ref-run.ok} (100%) rename test/run-drun/ok/{free-callbacks.ic-stub-run.ok => free-callbacks.ic-ref-run.ok} (100%) rename test/run-drun/ok/{general_await.ic-stub-run.ok => general_await.ic-ref-run.ok} (100%) rename test/run-drun/ok/{general_await_implicit.ic-stub-run.ok => general_await_implicit.ic-ref-run.ok} (100%) rename test/run-drun/ok/{generic-tail-rec.ic-stub-run.ok => generic-tail-rec.ic-ref-run.ok} (100%) rename test/run-drun/ok/{hello-world-async.ic-stub-run.ok => hello-world-async.ic-ref-run.ok} (100%) rename test/run-drun/ok/{hello-world-await.ic-stub-run.ok => hello-world-await.ic-ref-run.ok} (100%) rename test/run-drun/ok/{hello-world-message.ic-stub-run.ok => hello-world-message.ic-ref-run.ok} (100%) rename test/run-drun/ok/{hello-world-return.ic-stub-run.ok => hello-world-return.ic-ref-run.ok} (100%) rename test/run-drun/ok/{hello-world.ic-stub-run.ok => hello-world.ic-ref-run.ok} (100%) rename test/run-drun/ok/{ic-calls.ic-stub-run.ok => ic-calls.ic-ref-run.ok} (100%) rename test/run-drun/ok/{idl-any.ic-stub-run.ok => idl-any.ic-ref-run.ok} (100%) rename test/run-drun/ok/{idl-bad.ic-stub-run.ok => idl-bad.ic-ref-run.ok} (100%) rename test/run-drun/ok/{idl-buf-size-bug.ic-stub-run.ok => idl-buf-size-bug.ic-ref-run.ok} (100%) rename test/run-drun/ok/{idl-field-escape.ic-stub-run.ok => idl-field-escape.ic-ref-run.ok} (100%) rename test/run-drun/ok/{idl-func.ic-stub-run.ok => idl-func.ic-ref-run.ok} (100%) rename test/run-drun/ok/{idl-mo.ic-stub-run.ok => idl-mo.ic-ref-run.ok} (100%) rename test/run-drun/ok/{idl-nary.ic-stub-run.ok => idl-nary.ic-ref-run.ok} (100%) rename test/run-drun/ok/{idl-nat-int.ic-stub-run.ok => idl-nat-int.ic-ref-run.ok} (100%) rename test/run-drun/ok/{idl-option.ic-stub-run.ok => idl-option.ic-ref-run.ok} (100%) rename test/run-drun/ok/{idl-pair.ic-stub-run.ok => idl-pair.ic-ref-run.ok} (100%) rename test/run-drun/ok/{idl-record.ic-stub-run.ok => idl-record.ic-ref-run.ok} (100%) rename test/run-drun/ok/{idl-shorthand.ic-stub-run.ok => idl-shorthand.ic-ref-run.ok} (100%) rename test/run-drun/ok/{idl-tuple.ic-stub-run.ok => idl-tuple.ic-ref-run.ok} (100%) rename test/run-drun/ok/{idl-unit.ic-stub-run.ok => idl-unit.ic-ref-run.ok} (100%) rename test/run-drun/ok/{idl-variant.ic-stub-run.ok => idl-variant.ic-ref-run.ok} (100%) rename test/run-drun/ok/{idl-vector.ic-stub-run.ok => idl-vector.ic-ref-run.ok} (100%) rename test/run-drun/ok/{interleave.ic-stub-run.ok => interleave.ic-ref-run.ok} (100%) rename test/run-drun/ok/{issue-894.ic-stub-run.ok => issue-894.ic-ref-run.ok} (100%) rename test/run-drun/ok/{local-throw.ic-stub-run.ok => local-throw.ic-ref-run.ok} (100%) rename test/run-drun/ok/{mod-rebind.ic-stub-run.ok => mod-rebind.ic-ref-run.ok} (100%) rename test/run-drun/ok/{nary-async.ic-stub-run.ok => nary-async.ic-ref-run.ok} (100%) rename test/run-drun/ok/{oneway-throw.ic-stub-run.ok => oneway-throw.ic-ref-run.ok} (100%) rename test/run-drun/ok/{oneway.ic-stub-run.ok => oneway.ic-ref-run.ok} (100%) rename test/run-drun/ok/{oom.ic-stub-run.ok => oom.ic-ref-run.ok} (100%) rename test/run-drun/ok/{overflow.ic-stub-run.ok => overflow.ic-ref-run.ok} (100%) rename test/run-drun/ok/{pass-references.comp-stub.ok => pass-references.comp-ref.ok} (61%) rename test/run-drun/ok/{pass-references.comp-stub.ret.ok => pass-references.comp-ref.ret.ok} (100%) rename test/run-drun/ok/{print-from-init.ic-stub-run.ok => print-from-init.ic-ref-run.ok} (100%) rename test/run-drun/ok/{query.ic-stub-run.ok => query.ic-ref-run.ok} (100%) rename test/run-drun/ok/{query2.ic-stub-run.ok => query2.ic-ref-run.ok} (100%) rename test/run-drun/ok/{reject.ic-stub-run.ok => reject.ic-ref-run.ok} (100%) rename test/run-drun/ok/{rts-stats.ic-stub-run.ok => rts-stats.ic-ref-run.ok} (100%) rename test/run-drun/ok/{self-shadow.comp-stub.ok => self-shadow.comp-ref.ok} (60%) rename test/run-drun/ok/{self-shadow.comp-stub.ret.ok => self-shadow.comp-ref.ret.ok} (100%) rename test/run-drun/ok/{selftail.ic-stub-run.ok => selftail.ic-ref-run.ok} (100%) rename test/run-drun/ok/{shared-object.ic-stub-run.ok => shared-object.ic-ref-run.ok} (100%) rename test/run-drun/ok/{sharingbug.ic-stub-run.ok => sharingbug.ic-ref-run.ok} (100%) rename test/run-drun/ok/{show.ic-stub-run.ok => show.ic-ref-run.ok} (100%) rename test/run-drun/ok/{static-gc.ic-stub-run.ok => static-gc.ic-ref-run.ok} (100%) rename test/run-drun/ok/{switch-await.ic-stub-run.ok => switch-await.ic-ref-run.ok} (100%) rename test/run-drun/ok/{text-iter.ic-stub-run.ok => text-iter.ic-ref-run.ok} (100%) rename test/run-drun/ok/{throw.ic-stub-run.ok => throw.ic-ref-run.ok} (100%) rename test/run-drun/ok/{transpose.ic-stub-run.ok => transpose.ic-ref-run.ok} (100%) rename test/run-drun/ok/{type-lub.ic-stub-run.ok => type-lub.ic-ref-run.ok} (100%) rename test/run-drun/ok/{unsupported-more.comp-stub.ok => unsupported-more.comp-ref.ok} (55%) rename test/run-drun/ok/{unsupported-more.comp-stub.ret.ok => unsupported-more.comp-ref.ret.ok} (100%) rename test/run-drun/ok/{unsupported.comp-stub.ok => unsupported.comp-ref.ok} (58%) rename test/run-drun/ok/{unsupported.comp-stub.ret.ok => unsupported.comp-ref.ret.ok} (100%) rename test/run-drun/ok/{upgrade.ic-stub-run.ok => upgrade.ic-ref-run.ok} (100%) rename test/run-drun/ok/{utf8.ic-stub-run.ok => utf8.ic-ref-run.ok} (100%) diff --git a/Building.md b/Building.md index a38524b2d54..62e0de850d2 100644 --- a/Building.md +++ b/Building.md @@ -44,7 +44,7 @@ installing all required tools without nix is out of scope). nix-env -i -f . -A filecheck nix-env -i -f . -A wabt nix-env -i -f . -A drun - nix-env -i -f . -A ic-stub + nix-env -i -f . -A ic-run ``` * Building the Motoko runtime without nix is tricky. But you can run ``` diff --git a/default.nix b/default.nix index d3bae20a244..b60613d3b17 100644 --- a/default.nix +++ b/default.nix @@ -12,11 +12,12 @@ let subpath = p: import ./nix/gitSource.nix p; in let dfinity-src = let env = builtins.getEnv "DFINITY_SRC"; in if env != "" then env else nixpkgs.sources.dfinity; in - let dfinity-pkgs = import dfinity-src { inherit (nixpkgs) system; }; in - let drun = dfinity-pkgs.drun or dfinity-pkgs.dfinity.drun; in +let ic-ref-pkgs = import nixpkgs.sources.ic-ref { inherit (nixpkgs) system; }; in +let ic-ref = ic-ref-pkgs.ic-ref; in + let haskellPackages = nixpkgs.haskellPackages.override { overrides = import nix/haskell-packages.nix nixpkgs subpath; }; in @@ -146,7 +147,9 @@ rec { }; # “our” Haskell packages - inherit (haskellPackages) lsp-int qc-motoko ic-stub; + inherit (haskellPackages) lsp-int qc-motoko; + + inherit ic-ref; tests = let testDerivationArgs = { @@ -250,7 +253,7 @@ rec { }; in { run = test_subdir "run" [ moc ] ; - run-drun = test_subdir "run-drun" [ moc drun ic-stub ]; + run-drun = test_subdir "run-drun" [ moc drun ic-ref ]; perf = perf_subdir "perf" [ moc drun ]; fail = test_subdir "fail" [ moc ]; repl = test_subdir "repl" [ moc ]; @@ -433,7 +436,7 @@ rec { stdlib-doc stdlib-adocs users-guide - ic-stub + ic-ref shell check-generated ] ++ builtins.attrValues tests diff --git a/ic-stub/.gitignore b/ic-stub/.gitignore deleted file mode 100644 index fdf15c75487..00000000000 --- a/ic-stub/.gitignore +++ /dev/null @@ -1,23 +0,0 @@ -dist -dist-* -cabal-dev -*.o -*.hi -*.hie -*.chi -*.chs.h -*.dyn_o -*.dyn_hi -.hpc -.hsenv -.cabal-sandbox/ -cabal.sandbox.config -*.prof -*.aux -*.hp -*.eventlog -.stack-work/ -cabal.project.local -*~ -.HTF/ -.ghc.environment.* diff --git a/ic-stub/.hlint.yaml b/ic-stub/.hlint.yaml deleted file mode 100644 index 7486ac8efa3..00000000000 --- a/ic-stub/.hlint.yaml +++ /dev/null @@ -1,6 +0,0 @@ -# Warnings currently triggered by your code -- ignore: {name: "Use uncurry"} -- ignore: {name: "Avoid lambda"} -- ignore: {name: "Use camelCase"} -- ignore: {name: "Eta reduce"} -- ignore: {name: "Use >=>"} diff --git a/ic-stub/README.md b/ic-stub/README.md deleted file mode 100644 index 6b7c12eaacd..00000000000 --- a/ic-stub/README.md +++ /dev/null @@ -1,68 +0,0 @@ -The IC Stub -=========== - -The IC stub is a partial implementation of the public interface of the DFINITY -Internet Computer, as specified in -https://docs.dfinity.systems/spec/public/ -with the primary goal of providing a mock environment to test the output of the -Motoko compiler. - -It currently provides one binary, `ic-stub-run`, that allows you to script the -execution of a single canister. - -Status ------- - -This is neither complete nor authoritative. Since this is primarily meant for -testing the output of Motoko, code paths not exercised by Motoko may not be -present; in particular, error handling and input validation is incomplete. - -Extra features --------------- - -In order to support patterns useful for and used in the Motoko test suite, the -IC stub has some extra features that are not spec’ed or implemented in the -official client. These are: - - * The ability to create calls from `canister_init`. - - * The ability to create additional canisters, in a way where the creating - canisters learns the id of the created canister synchronously, and can send - messages to it right away. - - The interface for that is - - ic.create_canister : (mod_src : i32, mod_size : i32, arg_src : i32, arg_size : i32) -> (idx : i32) - ic.created_canister_id_size : (idx : i32) -> (size : i32) - ic.created_canister_id_copy : (idx : i32, dst : i32, offset : i32, size : i32) -> () - - where the `idx` is only valid within the same function invokation. - -Installation of `ic-stub-run` ------------------------------ - -If you use the top-level `nix-shell`, you should already have `ic-stub-run` in -your `PATH`. - -To install it into your normal environment, run from the top-level repository -directory. - - - nix-env -i -f . -A ic-stub - - -Developing on ic-stub ---------------------- - -Running `nix-shell` in the `ic-stub/` directory should give you an environment -that allows you to build the project using `cabal new-build`. - -The interpreter is too slow ---------------------------- - -The obvious performance issue with `winter`, according to profiling, is -evaluation under lambdas, the cost centres `step_Label7_k`, `step_Label7`, -`step_Label2` and `step_Framed4` are responsible for most allocation. Switching -to an interpreter form with a control stack would likely help a lot, but would -move `winter` away from being a straight-forward port of the Ocaml reference -interpreter `wasm`. diff --git a/ic-stub/cabal.project b/ic-stub/cabal.project deleted file mode 100644 index e6fdbadb439..00000000000 --- a/ic-stub/cabal.project +++ /dev/null @@ -1 +0,0 @@ -packages: . diff --git a/ic-stub/ic-stub.cabal b/ic-stub/ic-stub.cabal deleted file mode 100644 index 6febcde490d..00000000000 --- a/ic-stub/ic-stub.cabal +++ /dev/null @@ -1,49 +0,0 @@ -cabal-version: >=1.10 -name: ic-stub -version: 0.1.0.0 -author: Joachim Breitner -maintainer: mail@joachim-breitner.de -build-type: Simple - -flag release - default: False - description: Release build, warnings are errors - -executable ic-stub-run - main-is: ic-stub-run.hs - hs-source-dirs: src - other-modules: IC.Stub - other-modules: IC.Types - other-modules: IC.Canister - other-modules: IC.Id - other-modules: IC.Logger - other-modules: IC.Canister.Imp - other-modules: IC.Canister.Interface - other-modules: IC.Canister.Pure - other-modules: IC.Canister.Persisted - other-modules: IC.Wasm.Winter - other-modules: IC.Wasm.WinterMemory - other-modules: IC.Wasm.Winter.Persist - other-modules: IC.Wasm.Imports - other-modules: IC.DRun.Parse - build-depends: base >=4.11 && <5 - build-depends: optparse-applicative - build-depends: filepath - build-depends: hex-text - build-depends: text - build-depends: bytestring - build-depends: containers - build-depends: winter - build-depends: mtl - build-depends: transformers - build-depends: binary - build-depends: data-default-class - build-depends: vector - build-depends: primitive - build-depends: utf8-string - build-depends: hex-text - default-language: Haskell2010 - ghc-options: -rtsopts - ghc-options: -Wall -Wno-name-shadowing - if flag(release) - ghc-options: -Werror diff --git a/ic-stub/shell.nix b/ic-stub/shell.nix deleted file mode 100644 index 18baf159054..00000000000 --- a/ic-stub/shell.nix +++ /dev/null @@ -1,15 +0,0 @@ -{ system ? builtins.currentSystem, -}: -let - ic-stub = (import ../default.nix {inherit system;}).ic-stub; - - nixpkgs = import ../nix { inherit system; }; - - extra-pkgs = [ - nixpkgs.haskellPackages.cabal-install - nixpkgs.haskellPackages.ghcid - ]; -in - ic-stub.env.overrideAttrs (old: { - nativeBuildInputs = (old.nativeBuildInputs or []) ++ extra-pkgs ; - }) diff --git a/ic-stub/src/IC/Canister.hs b/ic-stub/src/IC/Canister.hs deleted file mode 100644 index e3f8f940b5b..00000000000 --- a/ic-stub/src/IC/Canister.hs +++ /dev/null @@ -1,69 +0,0 @@ -{-# LANGUAGE TypeOperators #-} - -{-| -A “pure” implementation of canisters, using "IC.Canister.Imp", but just replaying when needed. -Note that this is quadratic in the number of update calls, so do not run such canisters for long. - -We could do some hacking caching of state using stable names, so that, as long as no trap occurs, 'replay' is fast. --} - -module IC.Canister - ( WasmState - , parseCanister - , CanisterModule(..) - , InitFunc, UpdateFunc, QueryFunc - ) - where - -import qualified Data.Map as M -import Data.List - -import IC.Types -import IC.Wasm.Winter (parseModule, exportedFunctions, Module) - -import qualified IC.Canister.Interface as CI --- Here we can swap out the persistence implementation -import IC.Canister.Persisted - -type InitFunc = CanisterId -> EntityId -> Blob -> TrapOr (InitResult, WasmState) -type UpdateFunc = WasmState -> TrapOr (WasmState, UpdateResult) -type QueryFunc = WasmState -> TrapOr Response - -data CanisterModule = CanisterModule - { init_method :: InitFunc - , update_methods :: MethodName ↦ (EntityId -> Responded -> Blob -> UpdateFunc) - , query_methods :: MethodName ↦ (EntityId -> Blob -> QueryFunc) - , callbacks :: Callback -> Responded -> Response -> UpdateFunc - , pre_upgrade_method :: WasmState -> EntityId -> TrapOr Blob - , post_upgrade_method :: CanisterId -> EntityId -> Blob -> Blob -> TrapOr WasmState - } - -parseCanister :: Blob -> Either String CanisterModule -parseCanister bytes = - case parseModule bytes of - Left err -> Left err - Right wasm_mod -> Right $ concreteToAbstractModule wasm_mod - -concreteToAbstractModule :: Module -> CanisterModule -concreteToAbstractModule wasm_mod = CanisterModule - { init_method = \cid caller dat -> initialize wasm_mod cid caller dat - , update_methods = M.fromList - [ (m, - \caller responded dat wasm_state -> - invoke wasm_state (CI.Update m caller responded dat)) - | n <- exportedFunctions wasm_mod - , Just m <- return $ stripPrefix "canister_update " n - ] - , query_methods = M.fromList - [ (m, \caller arg wasm_state -> - snd <$> invoke wasm_state (CI.Query m caller arg)) - | n <- exportedFunctions wasm_mod - , Just m <- return $ stripPrefix "canister_query " n - ] - , callbacks = \cb responded res wasm_state -> - invoke wasm_state (CI.Callback cb responded res) - , pre_upgrade_method = \wasm_state caller -> - snd <$> invoke wasm_state (CI.PreUpgrade wasm_mod caller) - , post_upgrade_method = \cid caller mem dat -> - initializeUpgrade wasm_mod cid caller mem dat - } diff --git a/ic-stub/src/IC/Canister/Imp.hs b/ic-stub/src/IC/Canister/Imp.hs deleted file mode 100644 index 71ba014a42c..00000000000 --- a/ic-stub/src/IC/Canister/Imp.hs +++ /dev/null @@ -1,488 +0,0 @@ -{-# LANGUAGE RankNTypes #-} -{-# LANGUAGE LambdaCase #-} -{-# LANGUAGE NamedFieldPuns #-} -{-# LANGUAGE ScopedTypeVariables #-} -{-# LANGUAGE GADTs #-} -{-# LANGUAGE FlexibleContexts #-} - -{-| -The canister interface, presented imperatively (or impurely), i.e. without rollback --} -module IC.Canister.Imp - ( ESRef - , ImpState(..) - , runESST - , rawInitialize - , rawInvoke - , silently - ) -where - -import qualified Data.ByteString.Lazy as BS -import qualified Data.ByteString.Lazy.Char8 as BSC -import qualified Data.ByteString.Lazy.UTF8 as BSU -import Control.Monad.Primitive -import Control.Monad.ST -import Control.Monad.Except -import Data.STRef -import Data.Maybe -import Data.Int -- TODO: Should be Word32 in most cases - -import IC.Types -import IC.Wasm.Winter -import IC.Wasm.WinterMemory as Mem -import IC.Wasm.Imports -import qualified IC.Canister.Interface as CI - --- Parameters are the data that come from the caller - -data Params = Params - { param_dat :: Maybe Blob - , param_caller :: Maybe EntityId - , reject_code :: Int - , reject_message :: String - } - --- The execution state is all information available to the --- canister. Some of it is immutable (could be separated here) - -data ExecutionState s = ExecutionState - { inst :: Instance s - , stableMem :: Memory s - , self_id :: CanisterId - , params :: Params - -- now the mutable parts - , responded :: Responded - , response :: Maybe Response - , reply_data :: Blob - , calls :: [MethodCall] - } - - -initalExecutionState :: CanisterId -> Instance s -> Memory s -> Responded -> ExecutionState s -initalExecutionState self_id inst stableMem responded = ExecutionState - { inst - , stableMem - , self_id - , params = Params Nothing Nothing 0 "" - , responded - , response = Nothing - , reply_data = mempty - , calls = mempty - } - --- Some bookkeeping to access the ExecutionState --- --- We “always” have the 'STRef', but only within 'withES' is it actually --- present. --- --- Also: A flag to check whether we are running in silent mode or not --- (a bit of a hack) - -type ESRef s = (STRef s Bool, STRef s (Maybe (ExecutionState s))) - -newESRef :: ST s (ESRef s) -newESRef = (,) <$> newSTRef True <*> newSTRef Nothing - -runESST :: (forall s. ESRef s -> ST s a) -> a -runESST f = runST $ newESRef >>= f - --- | runs a computation with the given initial execution state --- and returns the final execution state with it. -withES :: PrimMonad m => - ESRef (PrimState m) -> - ExecutionState (PrimState m) -> - m a -> m (a, ExecutionState (PrimState m)) -withES (_pref, esref) es f = do - before <- stToPrim $ readSTRef esref - unless (isNothing before) $ fail "withES with non-empty es" - stToPrim $ writeSTRef esref $ Just es - x <- f - es' <- stToPrim $ readSTRef esref - case es' of - Nothing -> fail "withES: ExecutionState lost" - Just es' -> do - stToPrim $ writeSTRef esref Nothing - return (x, es') - -silently :: PrimMonad m => ESRef (PrimState m) -> m x -> m x -silently (pref, _esref) f = do - before <- stToPrim $ readSTRef pref - stToPrim $ writeSTRef pref False - x <- f - stToPrim $ writeSTRef pref before - return x - -getsES :: ESRef s -> (ExecutionState s -> b) -> HostM s b -getsES (_, esref) f = lift (readSTRef esref) >>= \case - Nothing -> throwError "System API not available yet" - Just es -> return (f es) - -modES :: ESRef s -> (ExecutionState s -> ExecutionState s) -> HostM s () -modES (_, esref) f = lift $ modifySTRef esref (fmap f) - -appendReplyData :: ESRef s -> Blob -> HostM s () -appendReplyData esref dat = modES esref $ \es -> - es { reply_data = reply_data es <> dat } - -setResponse :: ESRef s -> Response -> HostM s () -setResponse esref r = modES esref $ \es -> - es { response = Just r } - -appendCall :: ESRef s -> MethodCall -> HostM s () -appendCall esref c = modES esref $ \es -> - es { calls = calls es ++ [c] } - --- The System API, with all imports - --- The code is defined in the where clause to scope over the 'ESRef' - -systemAPI :: forall s. ESRef s -> Imports s -systemAPI esref = - [ toImport "ic0" "msg_arg_data_size" msg_arg_data_size - , toImport "ic0" "msg_arg_data_copy" msg_arg_data_copy - , toImport "ic0" "msg_caller_size" msg_caller_size - , toImport "ic0" "msg_caller_copy" msg_caller_copy - , toImport "ic0" "msg_reject_code" msg_reject_code - , toImport "ic0" "msg_reject_msg_size" msg_reject_msg_size - , toImport "ic0" "msg_reject_msg_copy" msg_reject_msg_copy - , toImport "ic0" "msg_reply_data_append" msg_reply_data_append - , toImport "ic0" "msg_reply" msg_reply - , toImport "ic0" "msg_reject" msg_reject - , toImport "ic0" "canister_self_copy" canister_self_copy - , toImport "ic0" "canister_self_size" canister_self_size - , toImport "ic0" "call_simple" call_simple - , toImport "ic0" "stable_size" stable_size - , toImport "ic0" "stable_grow" stable_grow - , toImport "ic0" "stable_write" stable_write - , toImport "ic0" "stable_read" stable_read - , toImport "ic0" "debug_print" debug_print - , toImport "ic0" "trap" explicit_trap - ] - where - -- Utilities - gets :: (ExecutionState s -> b) -> HostM s b - gets = getsES esref - - copy_to_canister :: Int32 -> Int32 -> Int32 -> Blob -> HostM s () - copy_to_canister dst offset size blob = do - unless (offset == 0) $ - throwError "offset /= 0 not supported" - unless (size == fromIntegral (BS.length blob)) $ - throwError "copying less than the full blob is not supported" - i <- getsES esref inst - -- TODO Bounds checking - setBytes i (fromIntegral dst) blob - - copy_from_canister :: String -> Int32 -> Int32 -> HostM s Blob - copy_from_canister _name src size = do - i <- gets inst - getBytes i (fromIntegral src) size - - size_and_copy :: HostM s Blob -> - ( () -> HostM s Int32 - , (Int32, Int32, Int32) -> HostM s () - ) - size_and_copy get_blob = - ( \() -> - get_blob >>= \blob -> return $ fromIntegral (BS.length blob) - , \(dst, offset, size) -> - get_blob >>= \blob -> copy_to_canister dst offset size blob - ) - - -- Unsafely print (if not in silent mode) - putBytes :: BS.ByteString -> HostM s () - putBytes bytes = - stToPrim (readSTRef (fst esref)) >>= \case - True -> unsafeIOToPrim $ BSC.putStrLn $ BSC.pack "debug.print: " <> bytes - False -> return () - - -- The system calls (in the order of the public spec) - -- https://docs.dfinity.systems/spec/public/#_system_imports - - msg_arg_data_size :: () -> HostM s Int32 - msg_arg_data_copy :: (Int32, Int32, Int32) -> HostM s () - (msg_arg_data_size, msg_arg_data_copy) = size_and_copy $ - gets (param_dat . params) >>= maybe (throwError "No argument") return - - msg_caller_size :: () -> HostM s Int32 - msg_caller_copy :: (Int32, Int32, Int32) -> HostM s () - (msg_caller_size, msg_caller_copy) = size_and_copy $ - fmap rawEntityId $ gets (param_caller . params) >>= maybe (throwError "No argument") return - - msg_reject_code :: () -> HostM s Int32 - msg_reject_code () = - fromIntegral <$> gets (reject_code . params) - - msg_reject_msg_size :: () -> HostM s Int32 - msg_reject_msg_copy :: (Int32, Int32, Int32) -> HostM s () - (msg_reject_msg_size, msg_reject_msg_copy) = size_and_copy $ do - c <- gets (reject_code . params) - when (c == 0) $ throwError "No reject message" - msg <- gets (reject_message . params) - return $ BSU.fromString msg - - assert_not_responded :: HostM s () - assert_not_responded = do - gets responded >>= \case - Responded False -> return () - Responded True -> throwError "This call has already been responded to earlier" - gets response >>= \case - Nothing -> return () - Just _ -> throwError "This call has already been responded to in this function" - - msg_reply_data_append :: (Int32, Int32) -> HostM s () - msg_reply_data_append (src, size) = do - assert_not_responded - bytes <- copy_from_canister "msg_reply_data_append" src size - appendReplyData esref bytes - - msg_reply :: () -> HostM s () - msg_reply () = do - assert_not_responded - bytes <- gets reply_data - setResponse esref (Reply bytes) - - msg_reject :: (Int32, Int32) -> HostM s () - msg_reject (src, size) = do - assert_not_responded - bytes <- copy_from_canister "msg_reject" src size - let msg = BSU.toString bytes - setResponse esref $ Reject (RC_CANISTER_REJECT, msg) - - canister_self_size :: () -> HostM s Int32 - canister_self_copy :: (Int32, Int32, Int32) -> HostM s () - (canister_self_size, canister_self_copy) = size_and_copy $ - rawEntityId <$> gets self_id - - call_simple :: - ( Int32, Int32, Int32, Int32, Int32 - , Int32, Int32, Int32, Int32, Int32) -> HostM s Int32 - call_simple - ( callee_src - , callee_size - , name_src - , name_size - , reply_fun - , reply_env - , reject_fun - , reject_env - , data_src - , data_size - ) = do - callee <- copy_from_canister "call_simple" callee_src callee_size - method_name <- copy_from_canister "call_simple" name_src name_size - arg <- copy_from_canister "call_simple" data_src data_size - - appendCall esref $ MethodCall - { call_callee = EntityId callee - , call_method_name = BSU.toString method_name -- TODO: check for valid UTF8 - , call_arg = arg - , call_callback = Callback - { reply_callback = WasmClosure reply_fun reply_env - , reject_callback = WasmClosure reject_fun reject_env - } - } - return 0 - - stable_size :: () -> HostM s Int32 - stable_size () = do - m <- gets stableMem - Mem.size m - - stable_grow :: Int32 -> HostM s Int32 - stable_grow delta = do - m <- gets stableMem - Mem.grow m delta - - stable_write :: (Int32, Int32, Int32) -> HostM s () - stable_write (dst, src, size) = do - m <- gets stableMem - i <- getsES esref inst - blob <- getBytes i (fromIntegral src) size - Mem.write m (fromIntegral dst) blob - - stable_read :: (Int32, Int32, Int32) -> HostM s () - stable_read (dst, src, size) = do - m <- gets stableMem - i <- getsES esref inst - blob <- Mem.read m (fromIntegral src) size - setBytes i (fromIntegral dst) blob - - - debug_print :: (Int32, Int32) -> HostM s () - debug_print (src, size) = do - -- TODO: This should be a non-trapping copy - bytes <- copy_from_canister "debug_print" src size - putBytes bytes - - explicit_trap :: (Int32, Int32) -> HostM s () - explicit_trap (src, size) = do - -- TODO: This should be a non-trapping copy - bytes <- copy_from_canister "trap" src size - let msg = BSU.toString bytes - throwError $ "canister trapped explicitly: " ++ msg - --- The state of an instance, consistig of the underlying Wasm state, --- additional remembered information like the CanisterId --- and the 'ESRef' that the system api functions are accessing - -data ImpState s = ImpState - { isESRef :: ESRef s - , isCanisterId :: CanisterId - , isInstance :: Instance s - , isStableMem :: Memory s - } - -rawInitialize :: ESRef s -> CanisterId -> Module -> ST s (TrapOr (ImpState s)) -rawInitialize esref cid wasm_mod = do - result <- runExceptT $ (,) - <$> initialize wasm_mod (systemAPI esref) - <*> Mem.new - case result of - Left err -> return $ Trap err - Right (inst, sm) -> return $ Return $ ImpState esref cid inst sm - -rawInvoke :: ImpState s -> CI.CanisterMethod r -> ST s (TrapOr r) -rawInvoke is (CI.Initialize wasm_mod caller dat) = - rawInitializeMethod is wasm_mod caller dat -rawInvoke is (CI.Query name caller dat) = - rawQueryMethod is name caller dat -rawInvoke is (CI.Update name caller responded dat) = - rawUpdateMethod is name caller responded dat -rawInvoke is (CI.Callback cb responded res) = - rawCallbackMethod is cb responded res -rawInvoke is (CI.PreUpgrade wasm_mod caller) = - rawPreUpgrade is wasm_mod caller -rawInvoke is (CI.PostUpgrade wasm_mod caller mem dat) = - rawPostUpgrade is wasm_mod caller mem dat - -cantRespond :: Responded -cantRespond = Responded True - -canRespond :: Responded -canRespond = Responded False - -rawInitializeMethod :: ImpState s -> Module -> EntityId -> Blob -> ST s (TrapOr InitResult) -rawInitializeMethod (ImpState esref cid inst sm) wasm_mod caller dat = do - result <- runExceptT $ do - let es = (initalExecutionState cid inst sm cantRespond) - { params = Params - { param_dat = Just dat - , param_caller = Just caller - , reject_code = 0 - , reject_message = "" - } - } - - -- invoke canister_init - if "canister_init" `elem` exportedFunctions wasm_mod - then withES esref es $ void $ invokeExport inst "canister_init" [] - else return ((), es) - -- TODO: Check no calls are made - - case result of - Left err -> return $ Trap err - Right (_, es') -> return $ - -- TODO: extract canisters and calls here - Return (calls es') - -rawPreUpgrade :: ImpState s -> Module -> EntityId -> ST s (TrapOr Blob) -rawPreUpgrade (ImpState esref cid inst sm) wasm_mod caller = do - result <- runExceptT $ do - let es = (initalExecutionState cid inst sm cantRespond) - { params = Params - { param_dat = Nothing - , param_caller = Just caller - , reject_code = 0 - , reject_message = "" - } - } - - if "canister_pre_upgrade" `elem` exportedFunctions wasm_mod - then withES esref es $ void $ invokeExport inst "canister_pre_upgrade" [] - else return ((), es) - -- TODO: Check no calls are made - - case result of - Left err -> return $ Trap err - Right (_, es') -> Return <$> Mem.export (stableMem es') - -rawPostUpgrade :: ImpState s -> Module -> EntityId -> Blob -> Blob -> ST s (TrapOr ()) -rawPostUpgrade (ImpState esref cid inst sm) wasm_mod caller mem dat = do - result <- runExceptT $ do - let es = (initalExecutionState cid inst sm cantRespond) - { params = Params - { param_dat = Just dat - , param_caller = Just caller - , reject_code = 0 - , reject_message = "" - } - } - lift $ Mem.imp (stableMem es) mem - - if "canister_post_upgrade" `elem` exportedFunctions wasm_mod - then withES esref es $ void $ invokeExport inst "canister_post_upgrade" [] - else return ((), es) - -- TODO: Check no calls are made - - case result of - Left err -> return $ Trap err - Right ((), _es') -> return $ Return () - -rawQueryMethod :: ImpState s -> MethodName -> EntityId -> Blob -> ST s (TrapOr Response) -rawQueryMethod (ImpState esref cid inst sm) method caller dat = do - let es = (initalExecutionState cid inst sm canRespond) - { params = Params - { param_dat = Just dat - , param_caller = Just caller - , reject_code = 0 - , reject_message = "" - } - } - result <- runExceptT $ withES esref es $ - invokeExport inst ("canister_query " ++ method) [] - -- TODO: Check no calls are made - - case result of - Left err -> return $ Trap err - Right (_, es') - | Just r <- response es' -> return $ Return r - | otherwise -> return $ Trap "No response" - -rawUpdateMethod :: ImpState s -> MethodName -> EntityId -> Responded -> Blob -> ST s (TrapOr UpdateResult) -rawUpdateMethod (ImpState esref cid inst sm) method caller responded dat = do - let es = (initalExecutionState cid inst sm responded) - { params = Params - { param_dat = Just dat - , param_caller = Just caller - , reject_code = 0 - , reject_message = "" - } - } - - result <- runExceptT $ withES esref es $ - invokeExport inst ("canister_update " ++ method) [] - case result of - Left err -> return $ Trap err - Right (_, es') -> return $ Return (calls es', response es') - -rawCallbackMethod :: ImpState s -> Callback -> Responded -> Response -> ST s (TrapOr UpdateResult) -rawCallbackMethod (ImpState esref cid inst sm) callback responded res = do - let params = case res of - Reply dat -> - Params { param_dat = Just dat, param_caller = Nothing, reject_code = 0, reject_message = "" } - Reject (rc, reject_message) -> - Params { param_dat = Nothing, param_caller = Nothing, reject_code = rejectCode rc, reject_message } - let es = (initalExecutionState cid inst sm responded) { params } - - let WasmClosure fun_idx env = case res of - Reply {} -> reply_callback callback - Reject {} -> reject_callback callback - - result <- runExceptT $ withES esref es $ - invokeTable inst fun_idx [I32 env] - case result of - Left err -> return $ Trap err - Right (_, es') -> return $ Return (calls es', response es') - diff --git a/ic-stub/src/IC/Canister/Interface.hs b/ic-stub/src/IC/Canister/Interface.hs deleted file mode 100644 index 2eacef6f38d..00000000000 --- a/ic-stub/src/IC/Canister/Interface.hs +++ /dev/null @@ -1,24 +0,0 @@ -{-# LANGUAGE GADTs #-} - -{-| -This module defines the various entry points provided by "IC.Canister.Imp" as a data type describing the arguments and results. - -The point of this abstraction is to to allow adding new entry points, or changing the arguments or result values, without changing the modules "IC.Canister.Pure" or "IC.Canister.Persisted", that sit between "IC.Canister.Imp" and "IC.Canister". - -Certain features here are beyond the specified abilities, in order to support the Motoko test suite. In particular: - - * Issuing calls from canister_init - --} -module IC.Canister.Interface where - -import IC.Types -import IC.Wasm.Winter (Module) - -data CanisterMethod r where - Initialize :: Module -> EntityId -> Blob -> CanisterMethod InitResult - Query :: MethodName -> EntityId -> Blob -> CanisterMethod Response - Update :: MethodName -> EntityId -> Responded -> Blob -> CanisterMethod UpdateResult - Callback :: Callback -> Responded -> Response -> CanisterMethod UpdateResult - PreUpgrade :: Module -> EntityId -> CanisterMethod Blob - PostUpgrade :: Module -> EntityId -> Blob -> Blob -> CanisterMethod () diff --git a/ic-stub/src/IC/Canister/Persisted.hs b/ic-stub/src/IC/Canister/Persisted.hs deleted file mode 100644 index b21b3125588..00000000000 --- a/ic-stub/src/IC/Canister/Persisted.hs +++ /dev/null @@ -1,76 +0,0 @@ -{-# LANGUAGE LambdaCase #-} -{-# LANGUAGE TupleSections #-} - -{-# OPTIONS_GHC -Wmissing-signatures #-} -{-| -An implementation of canisters based on persistence, using "IC.Canister.Imp". It has the same interface as "IC.Canister.Pure". --} - -module IC.Canister.Persisted - ( WasmState - , initialize - , initializeUpgrade - , invoke - ) - where - -import Control.Monad.ST -import Data.ByteString.Lazy (ByteString) - -import IC.Types -import IC.Wasm.Winter (Module) -import IC.Wasm.Winter.Persist -import qualified IC.Canister.Interface as CI -import IC.Canister.Imp - -data WasmState = WasmState Module CanisterId PInstance ByteString - -initialize :: Module -> CanisterId -> EntityId -> Blob -> TrapOr (InitResult, WasmState) -initialize wasm_mod cid caller dat = runESST $ \esref -> - rawInitialize esref cid wasm_mod >>= \case - Trap err -> return $ Trap err - Return rs -> - rawInvoke rs (CI.Initialize wasm_mod caller dat) >>= \case - Trap err -> return $ Trap err - Return ir -> Return . (ir,) <$> newWasmState wasm_mod rs - -initializeUpgrade :: Module -> CanisterId -> EntityId -> Blob -> Blob -> TrapOr WasmState -initializeUpgrade wasm_mod cid caller mem dat = runESST $ \esref -> - rawInitialize esref cid wasm_mod >>= \case - Trap err -> return $ Trap err - Return rs -> - rawInvoke rs (CI.PostUpgrade wasm_mod caller mem dat) >>= \case - Trap err -> return $ Trap err - Return () -> Return <$> newWasmState wasm_mod rs - -invoke :: WasmState -> CI.CanisterMethod r -> TrapOr (WasmState, r) -invoke s m = runESST $ \esref -> do - rs <- replay esref s - tor <- rawInvoke rs m - case tor of - Trap msg -> return $ Trap msg - Return r -> do - state' <- persist s rs - return $ Return (state', r) - -replay :: ESRef s -> WasmState -> ST s (ImpState s) -replay esref (WasmState wasm_mod cid pinst pmem) = do - rs <- rawInitialize esref cid wasm_mod >>= trapToFail - resume rs pinst pmem - return rs - where - trapToFail (Trap _err) = fail "replay failed" - trapToFail (Return x) = return x - -newWasmState :: Module -> ImpState s -> ST s WasmState -newWasmState wasm_mod (ImpState _ cid inst sm) = - WasmState wasm_mod cid <$> persistInstance inst <*> persistMemory sm - -resume :: ImpState s -> PInstance -> ByteString -> ST s () -resume (ImpState _ _ inst sm) pinst pmem = do - resumeInstance inst pinst - resumeMemory sm pmem - -persist :: WasmState -> ImpState s -> ST s WasmState -persist (WasmState wasm_mod cid _ _) (ImpState _ _ inst sm) = - WasmState wasm_mod cid <$> persistInstance inst <*> persistMemory sm diff --git a/ic-stub/src/IC/Canister/Pure.hs b/ic-stub/src/IC/Canister/Pure.hs deleted file mode 100644 index 84573c722f8..00000000000 --- a/ic-stub/src/IC/Canister/Pure.hs +++ /dev/null @@ -1,69 +0,0 @@ -{-# LANGUAGE ScopedTypeVariables #-} -{-# LANGUAGE RankNTypes #-} -{-# LANGUAGE LambdaCase #-} -{-# LANGUAGE GADTs #-} -{-# LANGUAGE NamedFieldPuns #-} - -{-# OPTIONS_GHC -Wmissing-signatures #-} -{-| -A “pure” implementation of canisters, using "IC.Canister.Imp", but just replaying when needed. -Note that this is quadratic in the number of update calls, so do not run such canisters for long. - -We could do some hacking caching of state using stable names, so that as long as no trap occurs, 'replay' is fast. --} - -module IC.Canister.Pure - ( WasmState - , initialize - , invoke - ) - where - -import Control.Monad.ST - -import IC.Types -import IC.Wasm.Winter (Module) -import qualified IC.Canister.Interface as CI -import IC.Canister.Imp - -data ACall = forall r. ACall (CI.CanisterMethod r) - -data WasmState = WasmState - { ws_mod :: Module - , ws_self_id :: CanisterId - , ws_calls :: [ACall] -- in reverse order - } - -initialize :: Module -> CanisterId -> EntityId -> Blob -> TrapOr WasmState -initialize wasm_mod cid caller dat = runESST $ \esref -> - rawInitialize esref cid wasm_mod >>= \case - Trap err -> return $ Trap err - Return rs -> do - let m = CI.Initialize wasm_mod caller dat - result <- rawInvoke rs m - let state' = WasmState wasm_mod cid [ACall m] - case result of - Trap err -> return $ Trap err - Return _raw_state -> return $ Return state' - -invoke :: WasmState -> CI.CanisterMethod r -> TrapOr (WasmState, r) -invoke s m = runESST $ \esref -> do - rs <- replay esref s - tor <- rawInvoke rs m - let state' = s { ws_calls = ACall m : ws_calls s } - case tor of - Trap msg -> return $ Trap msg - Return r -> return $ Return (state', r) - -replay :: forall s. ESRef s -> WasmState -> ST s (ImpState s) -replay esref WasmState{ ws_mod, ws_self_id, ws_calls } = silently esref $ go ws_calls - where - trapToFail (Trap _err) = fail "replay failed" - trapToFail (Return x) = return x - - go :: [ACall] -> ST s (ImpState s) - go [] = rawInitialize esref ws_self_id ws_mod >>= trapToFail - go (ACall m:ms) = do - is <- go ms - _ <- rawInvoke is m >>= trapToFail - return is diff --git a/ic-stub/src/IC/DRun/Parse.hs b/ic-stub/src/IC/DRun/Parse.hs deleted file mode 100644 index e360581c39e..00000000000 --- a/ic-stub/src/IC/DRun/Parse.hs +++ /dev/null @@ -1,63 +0,0 @@ -{-# LANGUAGE ScopedTypeVariables #-} -module IC.DRun.Parse where - -import qualified Data.ByteString.Lazy as B -import qualified Text.Hex as H -import qualified Data.Text as T -import Data.Char -import Data.List -import Control.Exception - -type MethodName = String -type Payload = B.ByteString -type Id = B.ByteString - -data Ingress - = Install Id FilePath Payload - | Upgrade Id FilePath Payload - | Update Id MethodName Payload - | Query Id MethodName Payload - deriving Show - -parseFile :: FilePath -> IO [Ingress] -parseFile input = do - x <- parse <$> readFile input - _ <- evaluate (show x) -- hack to evaluate until we have a proper parser - return x - -parse :: String -> [Ingress] -parse = map parseLine . lines - -parseLine :: String -> Ingress -parseLine l = case words l of - ["install", i, f, a] -> Install (parseId i) f (parseArg a) - ["upgrade", i, f, a] -> Upgrade (parseId i) f (parseArg a) - ["ingress", i, m, a] -> Update (parseId i) m (parseArg a) - ["query", i, m, a] -> Query (parseId i) m (parseArg a) - _ -> error $ "Cannot parse: " ++ show l - --- TODO: Implement proper and extract in own module -parseId :: String -> Id -parseId s - | "ic:" `isPrefixOf` s - , Just bs <- B.fromStrict <$> H.decodeHex (T.pack (drop 3 s)) - , B.length bs > 1 - = B.init bs - | otherwise - = error "Invalid canister id" - -parseArg :: String -> Payload -parseArg ('0':'x':xs) - | Just x <- B.fromStrict <$> H.decodeHex (T.pack xs) = x -parseArg ('"':xs) - = B.pack $ go xs - where - go "" = error "Missing terminating \"" - go "\"" = [] - go ('\\':'x':a:b:ys) - | Just h <- H.decodeHex (T.pack [a,b]) - = B.unpack (B.fromStrict h) ++ go ys - go (c:ys) = fromIntegral (ord c) : go ys -parseArg x = error $ "Invalid argument " ++ x - - diff --git a/ic-stub/src/IC/Id.hs b/ic-stub/src/IC/Id.hs deleted file mode 100644 index b3e2323198e..00000000000 --- a/ic-stub/src/IC/Id.hs +++ /dev/null @@ -1,14 +0,0 @@ -module IC.Id where - -import IC.Types - -import Data.Binary (encode) -import Data.Word - --- Not particulary efficent, but this is a reference implementation, right? -freshId :: [EntityId] -> EntityId -freshId ids = - head $ - filter (`notElem` ids) $ - map (EntityId . encode) - [1024::Word64 ..] diff --git a/ic-stub/src/IC/Logger.hs b/ic-stub/src/IC/Logger.hs deleted file mode 100644 index 10a4a24e4e8..00000000000 --- a/ic-stub/src/IC/Logger.hs +++ /dev/null @@ -1,12 +0,0 @@ -module IC.Logger where - -import Control.Monad.State - -class Logger m where - logTrap :: String -> m () - -instance (Monad m, Logger m) => Logger (StateT s m) where - logTrap x = lift $ logTrap x - -instance Logger IO where - logTrap msg = putStrLn $ "Trap: " ++ msg diff --git a/ic-stub/src/IC/Stub.hs b/ic-stub/src/IC/Stub.hs deleted file mode 100644 index ce6648a4a95..00000000000 --- a/ic-stub/src/IC/Stub.hs +++ /dev/null @@ -1,399 +0,0 @@ -{-# LANGUAGE TypeOperators #-} -{-# LANGUAGE ConstraintKinds #-} -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE LambdaCase #-} -{-# LANGUAGE NamedFieldPuns #-} -{-# LANGUAGE TypeFamilies #-} -{-# LANGUAGE ScopedTypeVariables #-} -{-# LANGUAGE RankNTypes #-} - -{-# OPTIONS_GHC -Wmissing-signatures #-} -module IC.Stub - ( IC - , AsyncRequest(..) - , SyncRequest(..) - , RequestStatus(..) - , CompletionValue(..) - , ReqResponse - , initialIC - , submitRequest, readRequest - , runToCompletion - , requestId - ) -where - -import qualified Data.ByteString.Lazy.Char8 as BSC -import qualified Data.Map as M -import Data.List -import Data.Maybe -import Control.Monad.State.Class -import Data.Sequence (Seq(..)) -import Data.Foldable (toList) - --- import Debug.Trace - -import IC.Types -import IC.Canister -import IC.Id -import IC.Logger - --- Abstract HTTP Interface - -data AsyncRequest - = CreateRequest UserId (Maybe CanisterId) - | InstallRequest CanisterId UserId Blob Blob - | UpgradeRequest CanisterId UserId Blob Blob - | UpdateRequest CanisterId UserId MethodName Blob - deriving (Eq, Ord, Show) - -data SyncRequest - = QueryRequest CanisterId UserId MethodName Blob - | StatusRequest Blob - -data RequestStatus - = Unknown -- never inside IC, only as ReqResponse - | Received - | Processing - | Rejected (RejectCode, String) - | Completed CompletionValue - deriving Show - -type ReqResponse = RequestStatus - - -data CompletionValue -- we need to be more typed than the public spec here - = CompleteUnit - | CompleteCanisterId CanisterId - | CompleteArg Blob - deriving Show - --- Abstract canisters - --- IC state - -data CanState = CanState - { wasm_state :: WasmState - , can_mod :: CanisterModule - } - -type ICT m = (MonadState IC m, Logger m) - -data EntryPoint - = Public MethodName Blob - | Closure Callback Response - deriving Show - -type CallId = Int - -data CallContext = CallContext - { canister :: CanisterId - , origin :: CallOrigin - , responded :: Responded - , last_trap :: Maybe String - } - deriving Show - -data CallOrigin - = FromUser AsyncRequest - | FromCanister CallId Callback - | FromInit EntityId - deriving Show - -data Message = - CallMessage - { call_context :: CallId - , entry :: EntryPoint - } - | ResponseMessage - { call_context :: CallId - , response :: Response - } - deriving Show - -data IC = IC - { canisters :: CanisterId ↦ Maybe CanState - , requests :: AsyncRequest ↦ RequestStatus - , messages :: Seq Message - , call_contexts :: CallId ↦ CallContext - } - -initialIC :: IC -initialIC = IC mempty mempty mempty mempty - -submitRequest :: ICT m => AsyncRequest -> m () -submitRequest r = - -- lensify? - modify (\ic -> ic { requests = M.insert r Received (requests ic) }) - -requestId :: AsyncRequest -> Blob -requestId r = BSC.pack (show r) -- TODO: Implement request hashing - -findRequest :: RequestID -> IC -> Maybe (AsyncRequest, RequestStatus) -findRequest rid ic = find (\(r,_s) -> requestId r == rid) (M.toList (requests ic)) - -readRequest :: ICT m => SyncRequest -> m ReqResponse - -readRequest (StatusRequest rid) = - gets (findRequest rid) >>= \case - Just (_r,status) -> return status - Nothing -> return Unknown - -readRequest (QueryRequest canister_id user_id method arg) = - gets (M.lookup canister_id . canisters) >>= \case - Nothing -> return $ Rejected (RC_DESTINATION_INVALID, "canister does not exist") - Just Nothing -> return $ Rejected (RC_DESTINATION_INVALID, "canister is empty") - Just (Just (CanState wasm_state can_mod)) -> - case M.lookup method (query_methods can_mod) of - Nothing -> return $ Rejected (RC_DESTINATION_INVALID, "query method does not exist") - Just f -> - case f user_id arg wasm_state of - Trap msg -> return $ Rejected (RC_CANISTER_ERROR, "canister trapped: " ++ msg) - Return (Reply res) -> return $ Completed (CompleteArg res) - Return (Reject (rc,rm)) -> return $ Rejected (rc, rm) - -nextReceived :: ICT m => m (Maybe AsyncRequest) -nextReceived = gets $ \ic -> listToMaybe - [ r | (r, Received) <- M.toList (requests ic) ] - -nextStarved :: ICT m => m (Maybe CallId) -nextStarved = gets $ \ic -> listToMaybe - [ c - | (c, ctxt) <- M.toList (call_contexts ic) - , Responded False <- return $ responded ctxt - , null [ () | ResponseMessage { call_context = c' } <- toList (messages ic), c' == c ] - , null - [ () - | CallContext { responded = Responded False, origin = FromCanister c' _} - <- M.elems (call_contexts ic) - , c' == c - ] - ] - -nextMessage :: ICT m => m (Maybe Message) -nextMessage = state $ \ic -> - case messages ic of - Empty -> (Nothing, ic) - m :<| ms -> (Just m, ic { messages = ms }) - -setReqStatus :: ICT m => AsyncRequest -> RequestStatus -> m () -setReqStatus r s = - modify (\ic -> ic { requests = M.insert r s (requests ic) }) - -createEmptyCanister :: ICT m => CanisterId -> m () -createEmptyCanister cid = - modify (\ic -> ic { canisters = - M.insert cid Nothing (canisters ic) - }) - - -installCanister :: ICT m => CanisterId -> CanisterModule -> WasmState -> m () -installCanister cid can_mod wasm_state = - -- Check that canister exists but is empty before? No, also used for upgrade. - modify (\ic -> ic { canisters = - M.insert cid (Just (CanState {can_mod, wasm_state})) (canisters ic) - }) - -setCanisterState :: ICT m => CanisterId -> WasmState -> m () -setCanisterState cid wasm_state = - modify (\ic -> ic { canisters = - M.adjust (fmap (\cs -> cs { wasm_state })) cid (canisters ic) - }) - -processRequest :: ICT m => AsyncRequest -> m () - -processRequest r@(CreateRequest _user_id (Just desired)) = do - exists <- gets (M.member desired . canisters) - if exists - then - setReqStatus r $ Rejected (RC_DESTINATION_INVALID, "Desired canister id already exists") - else do - createEmptyCanister desired - setReqStatus r $ Completed $ CompleteCanisterId desired - -processRequest r@(CreateRequest _user_id Nothing) = do - existing_canisters <- gets (M.keys . canisters) - let new_id = freshId existing_canisters - createEmptyCanister new_id - setReqStatus r $ Completed $ CompleteCanisterId new_id - -processRequest r@(InstallRequest canister_id user_id can_mod dat) = - case parseCanister can_mod of - Left err -> - setReqStatus r $ Rejected (RC_SYS_FATAL, "Parsing failed: " ++ err) - Right can_mod -> do - -- We only need a call context to be able to do inter-canister calls - -- from init, which is useful for Motoko testing, but not currently - -- allowed by the spec. - ctxt_id <- newCallContext $ CallContext - { canister = canister_id - , origin = FromInit user_id - , responded = Responded True - , last_trap = Nothing - } - - case init_method can_mod canister_id user_id dat of - Trap msg -> - setReqStatus r $ Rejected (RC_CANISTER_ERROR, "Initialization trapped: " ++ msg) - Return (new_calls, wasm_state) -> do - installCanister canister_id can_mod wasm_state - mapM_ (newCall ctxt_id) new_calls - setReqStatus r $ Completed CompleteUnit - -processRequest r@(UpgradeRequest canister_id user_id new_can_mod dat) = do - let res = setReqStatus r - case parseCanister new_can_mod of - Left err -> - setReqStatus r $ Rejected (RC_SYS_FATAL, "Parsing failed: " ++ err) - Right new_can_mod -> - gets (M.lookup canister_id . canisters) >>= \case - Nothing -> res $ Rejected (RC_DESTINATION_INVALID, "canister does not exist: " ++ show canister_id) - Just Nothing -> res $ Rejected (RC_DESTINATION_INVALID, "canister is empty") - Just (Just (CanState old_wasm_state old_can_mod)) -> - case pre_upgrade_method old_can_mod old_wasm_state user_id of - Trap msg -> res $ Rejected (RC_CANISTER_ERROR, "Pre-upgrade trapped: " ++ msg) - Return mem -> - case post_upgrade_method new_can_mod user_id user_id mem dat of - Trap msg -> res $ Rejected (RC_CANISTER_ERROR, "post-upgrade trapped: " ++ msg) - Return new_wasm_state -> do - installCanister canister_id new_can_mod new_wasm_state - res $ Completed CompleteUnit - -processRequest r@(UpdateRequest canister_id _user_id method arg) = do - ctxt_id <- newCallContext $ CallContext - { canister = canister_id - , origin = FromUser r - , responded = Responded False - , last_trap = Nothing - } - enqueueMessage $ CallMessage - { call_context = ctxt_id - , entry = Public method arg - } - setReqStatus r Processing - -enqueueMessage :: ICT m => Message -> m () -enqueueMessage m = modify $ \ic -> ic { messages = messages ic :|> m } - -newCallContext :: ICT m => CallContext -> m CallId -newCallContext cc = state go - where - go ic = (i, ic { call_contexts = M.insert i cc (call_contexts ic)}) - where - i | M.null (call_contexts ic) = 0 - | otherwise = fst (M.findMax (call_contexts ic)) + 1 - -getCallContext :: ICT m => CallId -> m CallContext -getCallContext ctxt_id = - gets ((M.! ctxt_id) . call_contexts) - -modifyCallContext :: ICT m => CallId -> (CallContext -> CallContext) -> m () -modifyCallContext ctxt_id f = - modify $ \ic -> ic { call_contexts = M.adjust f ctxt_id (call_contexts ic) } - -respondCallContext :: ICT m => CallId -> Response -> m () -respondCallContext ctxt_id response = do - -- TODO: check no prior response - modifyCallContext ctxt_id $ \ctxt -> ctxt { responded = Responded True } - enqueueMessage $ ResponseMessage { call_context = ctxt_id, response } - -rememberTrap :: ICT m => CallId -> String -> m () -rememberTrap ctxt_id msg = - modifyCallContext ctxt_id $ \ctxt -> ctxt { last_trap = Just msg } - -callerOfRequest :: AsyncRequest -> EntityId -callerOfRequest (CreateRequest user_id _) = user_id -callerOfRequest (InstallRequest _ user_id _ _) = user_id -callerOfRequest (UpgradeRequest _ user_id _ _) = user_id -callerOfRequest (UpdateRequest _ user_id _ _) = user_id - -callerOfCallID :: ICT m => CallId -> m EntityId -callerOfCallID ctxt_id = do - ctxt <- getCallContext ctxt_id - case origin ctxt of - FromUser request -> return $ callerOfRequest request - FromCanister other_ctxt_id _callback -> calleeOfCallID other_ctxt_id - FromInit entity_id -> return entity_id - -calleeOfCallID :: ICT m => CallId -> m EntityId -calleeOfCallID ctxt_id = canister <$> getCallContext ctxt_id - -respondedCallID :: ICT m => CallId -> m Responded -respondedCallID ctxt_id = responded <$> getCallContext ctxt_id - -invokeEntry :: ICT m => - CallId -> CanState -> EntryPoint -> - m (TrapOr (WasmState, UpdateResult)) -invokeEntry ctxt_id (CanState wasm_state can_mod) entry = do - responded <- respondedCallID ctxt_id - case entry of - Public method dat -> do - caller <- callerOfCallID ctxt_id - case M.lookup method (update_methods can_mod) of - Just f -> - return $ f caller responded dat wasm_state - Nothing -> do - let reject = Reject (RC_DESTINATION_INVALID, "update method does not exist: " ++ method) - return $ Return (wasm_state, ([], Just reject)) - Closure cb r -> - return $ callbacks can_mod cb responded r wasm_state - -newCall :: ICT m => CallId -> MethodCall -> m () -newCall from_ctxt_id call = do - new_ctxt_id <- newCallContext $ CallContext - { canister = call_callee call - , origin = FromCanister from_ctxt_id (call_callback call) - , responded = Responded False - , last_trap = Nothing - } - enqueueMessage $ CallMessage - { call_context = new_ctxt_id - , entry = Public (call_method_name call) (call_arg call) - } - -processMessage :: ICT m => Message -> m () -processMessage (CallMessage ctxt_id entry) = do - callee <- calleeOfCallID ctxt_id - let res r = respondCallContext ctxt_id r - gets (M.lookup callee . canisters) >>= \case - Nothing -> res $ Reject (RC_DESTINATION_INVALID, "canister does not exist: " ++ show callee) - Just Nothing -> res $ Reject (RC_DESTINATION_INVALID, "canister is empty") - Just (Just cs) -> - invokeEntry ctxt_id cs entry >>= \case - Trap msg -> do - logTrap msg - rememberTrap ctxt_id msg - Return (new_state, (new_calls, mb_response)) -> do - setCanisterState callee new_state - mapM_ (newCall ctxt_id) new_calls - mapM_ res mb_response - -processMessage (ResponseMessage ctxt_id response) = do - ctxt <- getCallContext ctxt_id - case origin ctxt of - FromUser request -> setReqStatus request $ - case response of - Reject (rc, msg) -> Rejected (rc, msg) - Reply blob -> Completed (CompleteArg blob) - FromCanister other_ctxt_id callback -> - enqueueMessage $ CallMessage - { call_context = other_ctxt_id - , entry = Closure callback response - } - FromInit _ -> fail "unexpected Response in Init" - -starveCallContext :: ICT m => CallId -> m () -starveCallContext ctxt_id = do - ctxt <- getCallContext ctxt_id - let msg | Just t <- last_trap ctxt = "canister trapped: " ++ t - | otherwise = "canister did not respond" - respondCallContext ctxt_id $ Reject (RC_CANISTER_ERROR, msg) - -runToCompletion :: ICT m => m () -runToCompletion = - nextReceived >>= \case - Just r -> processRequest r >> runToCompletion - Nothing -> nextMessage >>= \case - Just m -> processMessage m >> runToCompletion - Nothing -> nextStarved >>= \case - Just c -> starveCallContext c >> runToCompletion - Nothing -> return () diff --git a/ic-stub/src/IC/Types.hs b/ic-stub/src/IC/Types.hs deleted file mode 100644 index 76e1c25843c..00000000000 --- a/ic-stub/src/IC/Types.hs +++ /dev/null @@ -1,79 +0,0 @@ -{-# LANGUAGE TypeOperators #-} -{-# LANGUAGE DeriveFunctor #-} -module IC.Types where - -import qualified Data.ByteString.Lazy as BS -import qualified Data.Map as M -import qualified Data.Text as T -import qualified Text.Hex as T -import Data.Int - -type (↦) = M.Map - --- Basic types - -type Blob = BS.ByteString -newtype EntityId = EntityId { rawEntityId :: Blob } deriving (Show, Eq, Ord) -type CanisterId = EntityId -type UserId = EntityId -type MethodName = String -type RequestID = Blob - -prettyBlob :: Blob -> String -prettyBlob b = "0x" ++ T.unpack (T.encodeHex (BS.toStrict b)) - -prettyID :: EntityId -> String -prettyID = prettyBlob . rawEntityId -- implement the "ic:…" stuff - -newtype Responded = Responded Bool - deriving Show - -data RejectCode - = RC_SYS_FATAL - | RC_SYS_TRANSIENT - | RC_DESTINATION_INVALID - | RC_CANISTER_REJECT - | RC_CANISTER_ERROR - deriving Show - -rejectCode :: RejectCode -> Int -rejectCode RC_SYS_FATAL = 1 -rejectCode RC_SYS_TRANSIENT = 2 -rejectCode RC_DESTINATION_INVALID = 3 -rejectCode RC_CANISTER_REJECT = 4 -rejectCode RC_CANISTER_ERROR = 5 - - -data Response = Reply Blob | Reject (RejectCode, String) - deriving Show - --- Abstract canisters - -data TrapOr a = Trap String | Return a deriving Functor - -data WasmClosure = WasmClosure - { closure_idx :: Int32 - , closure_env :: Int32 - } - deriving Show - -data Callback = Callback - { reply_callback :: WasmClosure - , reject_callback :: WasmClosure - } - deriving Show - -data MethodCall = MethodCall - { call_callee :: CanisterId - , call_method_name :: MethodName - , call_arg :: Blob - , call_callback :: Callback - } - deriving Show - -type ExistingCanisters = [CanisterId] - -type InitResult = [MethodCall] -type UpdateResult = ([MethodCall], Maybe Response) - -type StableMemory = Blob diff --git a/ic-stub/src/IC/Wasm/Imports.hs b/ic-stub/src/IC/Wasm/Imports.hs deleted file mode 100644 index b947d353a4a..00000000000 --- a/ic-stub/src/IC/Wasm/Imports.hs +++ /dev/null @@ -1,244 +0,0 @@ -{-# LANGUAGE ScopedTypeVariables #-} -{-# LANGUAGE TypeApplications #-} -{-# LANGUAGE AllowAmbiguousTypes #-} -{-# LANGUAGE DefaultSignatures #-} - -module IC.Wasm.Imports where - -import Data.Int -import IC.Wasm.Winter -import Text.Printf -import Control.Monad.Except - - -class WasmArg a where - valueType :: ValueType - fromValue :: Value -> Either String a - toValue :: a -> Value - -class WasmArgs a where - stackType :: StackType - fromValues :: [Value] -> Either String a - toValues :: a -> [Value] - - default stackType :: WasmArg a => StackType - stackType = [valueType @a] - default fromValues :: WasmArg a => [Value] -> Either String a - fromValues [x] = fromValue x - fromValues xs = argError 1 xs - default toValues :: WasmArg a => a -> [Value] - toValues x = [toValue x] - -argError :: Int -> [a] -> Either String b -argError n xs = Left $ - printf "expected %d arguments, got %d arguments" n (length xs) - -instance WasmArg Int32 where - valueType = I32Type - fromValue (I32 i) = Right i - fromValue v = Left $ "expected i32, got " ++ show v - toValue = I32 -instance WasmArgs Int32 where - -instance WasmArgs () where - stackType = [] - fromValues [] = Right () - fromValues xs = argError 0 xs - toValues () = [] - --- The formatting is a bit odd, but it allows to create new instances easily by copy and paste and adding lines -instance - ( WasmArg a1 - , WasmArg a2 - ) => WasmArgs - ( a1 - , a2 - ) where - stackType = - [ valueType @a1 - , valueType @a2 - ] - fromValues - [ x1 - , x2 - ] = (,) - <$> fromValue x1 - <*> fromValue x2 - fromValues xs = argError 2 xs - toValues - ( x1 - , x2 - ) = - [ toValue x1 - , toValue x2 - ] - -instance - ( WasmArg a1 - , WasmArg a2 - , WasmArg a3 - , WasmArg a4 - ) => WasmArgs - ( a1 - , a2 - , a3 - , a4 - ) where - stackType = - [ valueType @a1 - , valueType @a2 - , valueType @a3 - , valueType @a4 - ] - fromValues - [ x1 - , x2 - , x3 - , x4 - ] = (,,,) - <$> fromValue x1 - <*> fromValue x2 - <*> fromValue x3 - <*> fromValue x4 - fromValues xs = argError 3 xs - toValues - ( x1 - , x2 - , x3 - , x4 - ) = - [ toValue x1 - , toValue x2 - , toValue x3 - , toValue x4 - ] - -instance - ( WasmArg a1 - , WasmArg a2 - , WasmArg a3 - ) => WasmArgs - ( a1 - , a2 - , a3 - ) where - stackType = - [ valueType @a1 - , valueType @a2 - , valueType @a3 - ] - fromValues - [ x1 - , x2 - , x3 - ] = (,,) - <$> fromValue x1 - <*> fromValue x2 - <*> fromValue x3 - fromValues xs = argError 3 xs - toValues - ( x1 - , x2 - , x3 - ) = - [ toValue x1 - , toValue x2 - , toValue x3 - ] - -instance - ( WasmArg a1 - , WasmArg a2 - , WasmArg a3 - , WasmArg a4 - , WasmArg a5 - , WasmArg a6 - , WasmArg a7 - , WasmArg a8 - , WasmArg a9 - , WasmArg a10 - ) => WasmArgs - ( a1 - , a2 - , a3 - , a4 - , a5 - , a6 - , a7 - , a8 - , a9 - , a10 - ) where - stackType = - [ valueType @a1 - , valueType @a2 - , valueType @a3 - , valueType @a4 - , valueType @a5 - , valueType @a6 - , valueType @a7 - , valueType @a8 - , valueType @a9 - , valueType @a10 - ] - fromValues - [ x1 - , x2 - , x3 - , x4 - , x5 - , x6 - , x7 - , x8 - , x9 - , x10 - ] = (,,,,,,,,,) - <$> fromValue x1 - <*> fromValue x2 - <*> fromValue x3 - <*> fromValue x4 - <*> fromValue x5 - <*> fromValue x6 - <*> fromValue x7 - <*> fromValue x8 - <*> fromValue x9 - <*> fromValue x10 - fromValues xs = argError 10 xs - toValues - ( x1 - , x2 - , x3 - , x4 - , x5 - , x6 - , x7 - , x8 - , x9 - , x10 - ) = - [ toValue x1 - , toValue x2 - , toValue x3 - , toValue x4 - , toValue x5 - , toValue x6 - , toValue x7 - , toValue x8 - , toValue x9 - , toValue x10 - ] - - -toImport :: - forall a b s. - (WasmArgs a, WasmArgs b) => - String -> String -> (a -> HostM s b) -> Import s -toImport mod_name fun_name f = (mod_name, fun_name, stackType @a, stackType @b, f') - where - f' :: [Value] -> HostFunc s - f' xs = do - a <- withExceptT ((mod_name ++ "." ++ fun_name ++ ": ") ++) $ - ExceptT $ return (fromValues xs) - b <- f a - return $ toValues b - diff --git a/ic-stub/src/IC/Wasm/Winter.hs b/ic-stub/src/IC/Wasm/Winter.hs deleted file mode 100644 index 0eee955b525..00000000000 --- a/ic-stub/src/IC/Wasm/Winter.hs +++ /dev/null @@ -1,133 +0,0 @@ -{-# LANGUAGE ScopedTypeVariables #-} -{-| - -This module provides a thin wrapper around the winter Wasm engine, exposing just -the bits needed by the IC stub. - -This is the interface at which one might plug in a different Wasm engine. --} -module IC.Wasm.Winter - ( Module - , parseModule - , exportedFunctions - , Import - , Imports - , HostM - , HostFunc - , W.Value(..) - , W.StackType - , W.ValueType(..) - , W.Address - , W.Size - , getBytes - , setBytes - , initialize - , Instance - , invokeExport - , invokeTable - ) -where - -import qualified Data.ByteString.Lazy as BS -import Control.Monad.Identity -import Control.Monad.Except -import qualified Data.Map as M -import qualified Data.IntMap as IM -import qualified Data.Text.Lazy as T -import Control.Monad.ST -import Data.Binary.Get (runGetOrFail) -import Data.Default.Class (Default (..)) -import Data.Int - -import qualified Wasm.Binary.Decode as W -import qualified Wasm.Exec.Eval as W -import qualified Wasm.Runtime.Func as W -import qualified Wasm.Runtime.Instance as W -import qualified Wasm.Runtime.Memory as W -import qualified Wasm.Syntax.AST as W -import qualified Wasm.Syntax.Types as W -import qualified Wasm.Syntax.Values as W -import qualified Wasm.Syntax.Memory as W - -type Instance s = (IM.IntMap (W.ModuleInst Identity (ST s)), Int) - -type HostM s = ExceptT String (ST s) - -type HostFunc s = HostM s [W.Value] - -type ModName = String -type FuncName = String -type Import s = (ModName, FuncName, W.StackType, W.StackType, [W.Value] -> HostFunc s) -type Imports s = [Import s] - -type Module = W.Module Identity - -parseModule :: BS.ByteString -> Either String Module -parseModule bytes = case runGetOrFail W.getModule bytes of - Left (_,_,err) -> Left err - Right (_,_,wasm_mod) -> Right wasm_mod - - -initialize :: forall s. Module -> Imports s -> HostM s (Instance s) -initialize mod imps = withExceptT show $ do - let by_mod :: [(T.Text, [(T.Text, W.StackType, W.StackType, [W.Value] -> HostFunc s)])] - by_mod = M.toList $ M.fromListWith (<>) - [ (T.pack m, [(T.pack n,t1,t2,f)]) | (m,n,t1,t2,f) <- imps ] - - names :: M.Map T.Text Int - names = M.fromList (zip (map fst by_mod) [1..]) - - mods :: IM.IntMap (W.ModuleInst Identity (ST s)) - mods = IM.fromList $ zip [1..] - [ (W.emptyModuleInst def) - { W._miGlobals = [ ] - , W._miTables = [ ] - , W._miMemories = [ ] - , W._miFuncs = [ ] - , W._miExports = M.fromList - [ (,) fname $ W.ExternFunc $ - W.allocHostEff (W.FuncType arg_ty ret_ty) - (\ args -> runExceptT $ f args) - | (fname, arg_ty, ret_ty, f) <- funcs - ] - } - | (_name, funcs) <- by_mod - ] - (ref, inst) <- W.initialize (Identity mod) names mods - let mods' = IM.insert ref inst mods - return (mods', ref) - - -exportedFunctions :: Module -> [FuncName] -exportedFunctions wasm_mod = - [ T.unpack (W._exportName e) - | Identity e <- W._moduleExports wasm_mod - , W.FuncExport {} <- return $ W._exportDesc e - ] - - -invokeExport :: Instance s -> FuncName -> [W.Value] -> HostM s [W.Value] -invokeExport (mods', ref) method args = do - let inst = mods' IM.! ref - withExceptT show $ - W.invokeByName mods' inst (T.pack method) args - -invokeTable :: Instance s -> Int32 -> [W.Value] -> HostM s [W.Value] -invokeTable (mods', ref) idx args = do - let inst = mods' IM.! ref - withExceptT show $ do - func <- W.elem inst 0 idx def - W.invoke mods' inst func args - -getBytes :: Instance s -> W.Address -> W.Size -> HostM s BS.ByteString -getBytes (mods', ref) ptr len = do - let inst = mods' IM.! ref - let mem = head (W._miMemories inst) - withExceptT show $ W.loadBytes mem ptr len - -setBytes :: Instance s -> W.Address -> BS.ByteString -> HostM s () -setBytes (mods', ref) ptr blob = do - let inst = mods' IM.! ref - let mem = head (W._miMemories inst) - withExceptT show $ W.storeBytes mem (fromIntegral ptr) blob - diff --git a/ic-stub/src/IC/Wasm/Winter/Persist.hs b/ic-stub/src/IC/Wasm/Winter/Persist.hs deleted file mode 100644 index 039fcab0d53..00000000000 --- a/ic-stub/src/IC/Wasm/Winter/Persist.hs +++ /dev/null @@ -1,139 +0,0 @@ -{-# LANGUAGE ExplicitForAll #-} -{-# LANGUAGE TypeFamilies #-} -{-# LANGUAGE MultiParamTypeClasses #-} -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE FlexibleContexts #-} -{- | -This module provides a way to persist the state of a Winter Wasm instance, and -to recover it. - -It is tailored to the use by ic-stub. For example it assumes that the -table of a wasm instance is immutable. --} -module IC.Wasm.Winter.Persist - ( PInstance - , persistInstance - , resumeInstance - , persistMemory - , resumeMemory - ) - where - -import Control.Monad.Identity -import Control.Monad.ST -import Data.Primitive.MutVar -import qualified Data.IntMap as IM -import qualified Data.Map.Lazy as M -import qualified Data.Text.Lazy as T -import Data.ByteString.Lazy (ByteString) - -import qualified Wasm.Runtime.Global as W -import qualified Wasm.Runtime.Instance as W -import qualified Wasm.Runtime.Memory as W -import qualified Wasm.Syntax.Values as W - -import IC.Wasm.Winter (Instance) - --- | --- This stores data read from an instance. --- --- Note that an 'Instance' has aliasing, the same global may appear in various --- spots. We don’t worry about that for now and just de-alias on reading, at the --- expense of writing the corresponding mutable values more than once. -newtype PInstance = PInstance (Persisted (Instance ())) - -persistInstance :: Instance s -> ST s PInstance -persistInstance i = PInstance <$> persist i - -resumeInstance :: Instance s -> PInstance -> ST s () -resumeInstance i (PInstance p) = resume i p - -persistMemory :: W.MemoryInst (ST s) -> ST s ByteString -persistMemory i = persist i - -resumeMemory :: W.MemoryInst (ST s) -> ByteString -> ST s () -resumeMemory i p = resume i p - -class Monad (M a) => Persistable a where - type Persisted a :: * - type M a :: * -> * - persist :: a -> M a (Persisted a) - resume :: a -> Persisted a -> M a () - -instance Persistable (W.MemoryInst (ST s)) where - type Persisted (W.MemoryInst (ST s)) = ByteString - type M (W.MemoryInst (ST s)) = ST s - persist = W.exportMemory - resume = W.importMemory - -instance Persistable (W.GlobalInst (ST s)) where - type Persisted (W.GlobalInst (ST s)) = W.Value - type M (W.GlobalInst (ST s)) = ST s - persist m = readMutVar (W._giContent m) - resume m = writeMutVar (W._giContent m) - -data PExtern - = PExternMemory (Persisted (W.MemoryInst (ST ()))) - | PExternGlobal (Persisted (W.GlobalInst (ST ()))) - | PExternOther - -instance Persistable (W.Extern f (ST s)) where - type Persisted (W.Extern f (ST s)) = PExtern - type M (W.Extern f (ST s)) = ST s - - persist (W.ExternGlobal g) = PExternGlobal <$> persist g - persist (W.ExternMemory m) = PExternMemory <$> persist m - persist _ = return PExternOther - - resume (W.ExternGlobal g) (PExternGlobal pg) = resume g pg - resume (W.ExternMemory m) (PExternMemory pm) = resume m pm - resume _ _ = return () - -data PModuleInst = PModuleInst - { memories :: [Persisted (W.MemoryInst (ST ()))] - , globals :: [Persisted (W.GlobalInst (ST ()))] - , exports :: M.Map T.Text (Persisted (W.Extern Identity (ST ()))) - } - -instance Persistable (W.ModuleInst Identity (ST s)) where - type Persisted (W.ModuleInst Identity (ST s)) = PModuleInst - type M (W.ModuleInst Identity (ST s)) = ST s - persist inst = PModuleInst - <$> persist (W._miMemories inst) - <*> persist (W._miGlobals inst) - <*> persist (W._miExports inst) - resume inst pinst = do - resume (W._miMemories inst) (memories pinst) - resume (W._miGlobals inst) (globals pinst) - resume (W._miExports inst) (exports pinst) - - -instance Persistable a => Persistable [a] where - type Persisted [a] = [Persisted a] - type M [a] = M a - persist = mapM persist - resume xs ys = do - unless (length xs == length ys) $ fail "Lengths don’t match" - zipWithM_ resume xs ys - -instance (Eq k, Persistable a) => Persistable (M.Map k a) where - type Persisted (M.Map k a) = M.Map k (Persisted a) - type M (M.Map k a) = M a - persist = mapM persist - resume xs ys = do - unless (M.keys xs == M.keys ys) $ fail "Map keys don’t match" - zipWithM_ resume (M.elems xs) (M.elems ys) - -instance Persistable a => Persistable (IM.IntMap a) where - type Persisted (IM.IntMap a) = IM.IntMap (Persisted a) - type M (IM.IntMap a) = M a - persist = mapM persist - resume xs ys = do - unless (IM.keys xs == IM.keys ys) $ fail "Map keys don’t match" - zipWithM_ resume (IM.elems xs) (IM.elems ys) - -instance Persistable a => Persistable (a, Int) where - type Persisted (a, Int) = Persisted a - type M (a, Int) = M a - persist (a, _i) = persist a - resume (a, _i) p = resume a p diff --git a/ic-stub/src/IC/Wasm/WinterMemory.hs b/ic-stub/src/IC/Wasm/WinterMemory.hs deleted file mode 100644 index 95053242a95..00000000000 --- a/ic-stub/src/IC/Wasm/WinterMemory.hs +++ /dev/null @@ -1,58 +0,0 @@ -{-# LANGUAGE ScopedTypeVariables #-} -{-| - -This module provides a thin wrapper around the winter Wasm engine, exposing just -the bits needed for accessing the stable memory. This will hopefully go away once -multiple memories are supported. --} -module IC.Wasm.WinterMemory - ( Memory - , new - , size - , grow - , read - , write - , export - , imp - ) -where - -import Prelude hiding (read) - -import Data.ByteString.Lazy (ByteString) -import Control.Monad.Except -import Control.Monad.ST - -import qualified Wasm.Runtime.Memory as W -import qualified Wasm.Syntax.Types as W -import qualified Wasm.Syntax.Memory as W - -type HostM s = ExceptT String (ST s) -type Memory s = W.MemoryInst (ST s) - -new :: HostM s (Memory s) -new = withExceptT show $ W.alloc (W.Limits 0 Nothing) - -size :: Memory s -> HostM s W.Size -size mem = lift $ W.size mem - -grow :: Memory s -> W.Size -> HostM s W.Size -grow mem delta = lift $ do - -- See memory.grow impl in src/Wasm/Exec/Eval.hs - oldSize <- W.size mem - eres <- runExceptT $ W.grow mem delta - return $ case eres of - Left _ -> -1 - Right () -> oldSize - -read :: Memory s -> W.Address -> W.Size -> HostM s ByteString -read mem ptr len = withExceptT show $ W.loadBytes mem ptr len - -write :: Memory s -> W.Address -> ByteString -> HostM s () -write mem ptr blob = withExceptT show $ W.storeBytes mem (fromIntegral ptr) blob - -export :: Memory s -> ST s ByteString -export = W.exportMemory - -imp :: Memory s -> ByteString -> ST s () -imp = W.importMemory diff --git a/ic-stub/src/ic-stub-run.hs b/ic-stub/src/ic-stub-run.hs deleted file mode 100644 index dac048f1d13..00000000000 --- a/ic-stub/src/ic-stub-run.hs +++ /dev/null @@ -1,111 +0,0 @@ -{-# LANGUAGE ConstraintKinds #-} -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE LambdaCase #-} -module Main where - -import Options.Applicative -import Control.Monad (join, forM_) -import Data.Monoid ((<>)) -import qualified Data.ByteString.Lazy as B -import Control.Monad.Trans -import Control.Monad.Trans.State -import Text.Printf - -import IC.Types -import IC.Stub -import IC.DRun.Parse (Ingress(..), parseFile) - -type DRun = StateT IC IO - --- Pretty printing - -dummyUserId :: CanisterId -dummyUserId = EntityId $ B.pack [0xCA, 0xFF, 0xEE] - -printAsyncRequest :: AsyncRequest -> IO () -printAsyncRequest CreateRequest{} = - printf "→ create\n" -printAsyncRequest InstallRequest{} = - printf "→ install\n" -printAsyncRequest UpgradeRequest{} = - printf "→ upgrade\n" -printAsyncRequest (UpdateRequest _ _ method arg) = - printf "→ update %s(%s)\n" method (prettyBlob arg) - -printSyncRequest :: SyncRequest -> IO () -printSyncRequest (StatusRequest rid) = - printf "→ status? %s\n" (prettyBlob rid) -printSyncRequest (QueryRequest _ _ method arg) = - printf "→ query %s(%s)\n" method (prettyBlob arg) - -printReqStatus :: RequestStatus -> IO () -printReqStatus Unknown = - printf "← unknown\n" -printReqStatus Received = - printf "← received\n" -printReqStatus Processing = - printf "← processing\n" -printReqStatus (Rejected (c, s)) = - printf "← rejected (%s): %s\n" (show c) s -printReqStatus (Completed CompleteUnit) = - printf "← completed\n" -printReqStatus (Completed (CompleteCanisterId id)) = - printf "← completed: canister-id = %s\n" (prettyID id) -printReqStatus (Completed (CompleteArg blob)) = - printf "← completed: %s\n" (prettyBlob blob) - -submitAndRun :: AsyncRequest -> DRun ReqResponse -submitAndRun r = do - lift $ printAsyncRequest r - submitRequest r - runToCompletion - r <- readRequest (StatusRequest (requestId r)) - lift $ printReqStatus r - return r - -submitRead :: SyncRequest -> DRun ReqResponse -submitRead r = do - lift $ printSyncRequest r - r <- readRequest r - lift $ printReqStatus r - return r - -work :: FilePath -> IO () -work msg_file = do - msgs <- parseFile msg_file - - let user_id = dummyUserId - - flip evalStateT initialIC $ - forM_ msgs $ \case - Install cid filename arg -> do - wasm <- liftIO $ B.readFile filename - _ <- submitAndRun (CreateRequest user_id (Just (EntityId cid))) - submitAndRun (InstallRequest (EntityId cid) user_id wasm arg) - Upgrade cid filename arg -> do - wasm <- liftIO $ B.readFile filename - submitAndRun (UpgradeRequest (EntityId cid) user_id wasm arg) - Query cid method arg -> submitRead (QueryRequest (EntityId cid) user_id method arg) - Update cid method arg -> submitAndRun (UpdateRequest (EntityId cid) user_id method arg) - -main :: IO () -main = join . customExecParser (prefs showHelpOnError) $ - info (helper <*> parser) - ( fullDesc - <> header "Internet Computer Canister runner" - <> progDesc "This runs an IC canister against a list of messages." - ) - where - parser :: Parser (IO ()) - parser = - work - <$ strOption - ( long "config" - <> short 'c' - <> metavar "CONFIG" - <> value "" - ) - <*> strArgument - ( metavar "script" - <> help "messages to execute" - ) diff --git a/nix/generate.nix b/nix/generate.nix index 13b622e9a78..4389ae9db63 100644 --- a/nix/generate.nix +++ b/nix/generate.nix @@ -48,22 +48,11 @@ let src_subst = "import ../gitSource.nix \"${path}\""; }; - - winter = (haskellSrc2nixWithDoc { - name = "winter"; - src = pkgs.sources.winter; - src_subst = "pkgs.sources.winter"; - extraCabal2nixOptions = "--no-check"; - }); - - ic-stub = localHaskellSrc2nixWithDoc "ic-stub" "ic-stub" "--no-check"; random = localHaskellSrc2nixWithDoc "qc-motoko" "test/random" ""; lsp-int = localHaskellSrc2nixWithDoc "lsp-int" "test/lsp-int" ""; allGenerated = pkgs.runCommandNoCC "generated" {} '' mkdir -p $out - cp ${winter}/default.nix $out/winter.nix - cp ${ic-stub}/default.nix $out/ic-stub.nix cp ${random}/default.nix $out/random.nix cp ${lsp-int}/default.nix $out/lsp-int.nix ''; diff --git a/nix/generated/ic-stub.nix b/nix/generated/ic-stub.nix deleted file mode 100644 index c1cedd8a590..00000000000 --- a/nix/generated/ic-stub.nix +++ /dev/null @@ -1,23 +0,0 @@ -# THIS IS AN AUTOMATICALLY GENERATED FILE. DO NOT EDIT MANUALLY! -# See ./nix/generate.nix for instructions. - -{ mkDerivation, pkgs, base, binary, bytestring, containers -, data-default-class, filepath, hex-text, mtl, optparse-applicative -, primitive, stdenv, text, transformers, utf8-string, vector -, winter -}: -mkDerivation { - pname = "ic-stub"; - version = "0.1.0.0"; - src = import ../gitSource.nix "ic-stub"; - isLibrary = false; - isExecutable = true; - executableHaskellDepends = [ - base binary bytestring containers data-default-class filepath - hex-text mtl optparse-applicative primitive text transformers - utf8-string vector winter - ]; - doCheck = false; - license = "unknown"; - hydraPlatforms = stdenv.lib.platforms.none; -} diff --git a/nix/generated/winter.nix b/nix/generated/winter.nix deleted file mode 100644 index 43f3da15b09..00000000000 --- a/nix/generated/winter.nix +++ /dev/null @@ -1,37 +0,0 @@ -# THIS IS AN AUTOMATICALLY GENERATED FILE. DO NOT EDIT MANUALLY! -# See ./nix/generate.nix for instructions. - -{ mkDerivation, pkgs, array, base, binary, byte-order, bytestring -, cmdargs, containers, data-default-class, data-fix, deepseq -, directory, filepath, FloatingHex, lifted-base, microlens-platform -, monad-control, mtl, nats, parsec, primitive, primitive-unaligned -, process, stdenv, tasty, tasty-hunit, tasty-quickcheck, temporary -, text, transformers, vector -}: -mkDerivation { - pname = "winter"; - version = "1.0.0"; - src = pkgs.sources.winter; - isLibrary = true; - isExecutable = true; - libraryHaskellDepends = [ - array base binary byte-order bytestring containers - data-default-class data-fix deepseq FloatingHex lifted-base - microlens-platform monad-control mtl nats parsec primitive - primitive-unaligned text transformers vector - ]; - executableHaskellDepends = [ - base binary bytestring cmdargs containers data-default-class mtl - parsec text - ]; - testHaskellDepends = [ - array base binary bytestring containers data-default-class data-fix - deepseq directory filepath FloatingHex lifted-base - microlens-platform monad-control mtl parsec primitive process tasty - tasty-hunit tasty-quickcheck temporary text transformers vector - ]; - doCheck = false; - homepage = "https://github.com/dfinity/winter"; - description = "Haskell port of the WebAssembly OCaml reference interpreter"; - license = stdenv.lib.licenses.mit; -} diff --git a/nix/haskell-packages.nix b/nix/haskell-packages.nix index 1937e7515b4..8015573b8b8 100644 --- a/nix/haskell-packages.nix +++ b/nix/haskell-packages.nix @@ -12,8 +12,4 @@ nix: subpath: lsp-int = super.callPackage generated/lsp-int.nix {}; qc-motoko = super.callPackage generated/random.nix {}; - - winter = super.callPackage generated/winter.nix {}; - - ic-stub = super.callPackage generated/ic-stub.nix {}; } diff --git a/nix/sources.json b/nix/sources.json index 41e294237e7..034c93abdaa 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -19,6 +19,12 @@ "url_template": "https://registry.npmjs.org/esm/-/esm-.tgz", "version": "3.2.25" }, + "ic-ref": { + "ref": "master", + "repo": "ssh://git@github.com/dfinity-lab/ic-ref", + "rev": "611af28895c2962040b06e506f822e0878612967", + "type": "git" + }, "libtommath": { "builtin": false, "description": "LibTomMath is a free open source portable number theoretic multiple-precision integer library written entirely in C.", diff --git a/samples/app/Makefile b/samples/app/Makefile index 9bdb3d25bc6..117dbee0a75 100644 --- a/samples/app/Makefile +++ b/samples/app/Makefile @@ -11,7 +11,7 @@ SAMPLES:= test all: rm -f main.txt - $(MOC) -stub-system-api -r -t -v main.mo >main.txt 2>&1 + $(MOC) -ref-system-api -r -t -v main.mo >main.txt 2>&1 cat main.txt clean: diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index fcec58601df..442520c7e82 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -2919,7 +2919,7 @@ module Dfinity = struct match E.mode env with | Flags.ICMode -> import_ic0 env - | Flags.StubMode -> + | Flags.RefMode -> import_ic0 env; E.add_func_import env "ic0" "stable_write" (i32s 3) []; E.add_func_import env "ic0" "stable_read" (i32s 3) []; @@ -2934,7 +2934,7 @@ module Dfinity = struct let print_ptr_len env = match E.mode env with | Flags.WasmMode -> G.i Drop ^^ G.i Drop - | Flags.ICMode | Flags.StubMode -> system_call env "ic0" "debug_print" + | Flags.ICMode | Flags.RefMode -> system_call env "ic0" "debug_print" | Flags.WASIMode -> Func.share_code2 env "print_ptr" (("ptr", I32Type), ("len", I32Type)) [] (fun env get_ptr get_len -> Stack.with_words env "io_vec" 6l (fun get_iovec_ptr -> @@ -3005,7 +3005,7 @@ module Dfinity = struct match E.mode env with | Flags.WasmMode -> G.i Unreachable | Flags.WASIMode -> compile_static_print env (s ^ "\n") ^^ G.i Unreachable - | Flags.ICMode | Flags.StubMode -> Blob.lit env s ^^ ic_trap_str env ^^ G.i Unreachable + | Flags.ICMode | Flags.RefMode -> Blob.lit env s ^^ ic_trap_str env ^^ G.i Unreachable let default_exports env = (* these exports seem to be wanted by the hypervisor/v8 *) @@ -3023,7 +3023,7 @@ module Dfinity = struct }) let export_init env start_fi = - assert (E.mode env = Flags.ICMode || E.mode env = Flags.StubMode); + assert (E.mode env = Flags.ICMode || E.mode env = Flags.RefMode); let empty_f = Func.of_body env [] [] (fun env1 -> G.i (Call (nr start_fi)) ^^ Lifecycle.trans env Lifecycle.InInit ^^ @@ -3039,7 +3039,7 @@ module Dfinity = struct let get_self_reference env = match E.mode env with - | Flags.ICMode | Flags.StubMode -> + | Flags.ICMode | Flags.RefMode -> Func.share_code0 env "canister_self" [I32Type] (fun env -> let (set_len, get_len) = new_local env "len" in let (set_blob, get_blob) = new_local env "blob" in @@ -3060,7 +3060,7 @@ module Dfinity = struct let caller env = SR.Vanilla, match E.mode env with - | Flags.ICMode | Flags.StubMode -> + | Flags.ICMode | Flags.RefMode -> let (set_len, get_len) = new_local env "len" in let (set_blob, get_blob) = new_local env "blob" in system_call env "ic0" "msg_caller_size" ^^ @@ -3077,7 +3077,7 @@ module Dfinity = struct let reject env arg_instrs = match E.mode env with - | Flags.ICMode | Flags.StubMode -> + | Flags.ICMode | Flags.RefMode -> arg_instrs ^^ Blob.as_ptr_len env ^^ system_call env "ic0" "msg_reject" @@ -3126,7 +3126,7 @@ module Dfinity = struct (* Actor reference on the stack *) let actor_public_field env name = match E.mode env with - | Flags.ICMode | Flags.StubMode -> + | Flags.ICMode | Flags.RefMode -> (* simply tuple canister name and function name *) Blob.lit env name ^^ Tuple.from_stack env 2 @@ -3160,7 +3160,7 @@ module Dfinity = struct compile_unboxed_const 0l ^^ G.i (Compare (Wasm.Values.I32 I32Op.Eq)) ^^ E.else_trap_with env "not a self-call" -let export_upgrade_scaffold env = if E.mode env = Flags.StubMode then +let export_upgrade_scaffold env = if E.mode env = Flags.RefMode then let pre_upgrade_fi = E.add_fun env "pre_upgrade" (Func.of_body env [] [] (fun env -> Lifecycle.trans env Lifecycle.InPreUpgrade ^^ @@ -4179,13 +4179,13 @@ module Serialization = struct let argument_data_size env = match E.mode env with - | Flags.ICMode | Flags.StubMode -> + | Flags.ICMode | Flags.RefMode -> Dfinity.system_call env "ic0" "msg_arg_data_size" | _ -> assert false let argument_data_copy env get_dest get_length = match E.mode env with - | Flags.ICMode | Flags.StubMode -> + | Flags.ICMode | Flags.RefMode -> get_dest ^^ (compile_unboxed_const 0l) ^^ get_length ^^ @@ -4239,7 +4239,7 @@ module Serialization = struct E.else_trap_with env "data buffer not filled " ^^ match E.mode env with - | Flags.ICMode | Flags.StubMode -> + | Flags.ICMode | Flags.RefMode -> get_refs_size ^^ compile_unboxed_const 0l ^^ G.i (Compare (Wasm.Values.I32 I32Op.Eq)) ^^ @@ -5053,7 +5053,7 @@ module FuncDec = struct let ic_call env ts1 ts2 get_meth_pair get_arg get_k get_r = match E.mode env with - | Flags.ICMode | Flags.StubMode -> + | Flags.ICMode | Flags.RefMode -> (* The callee *) get_meth_pair ^^ Arr.load_field 0l ^^ Blob.as_ptr_len env ^^ @@ -5072,7 +5072,7 @@ module FuncDec = struct let ic_call_one_shot env ts get_meth_pair get_arg = match E.mode env with - | Flags.ICMode | Flags.StubMode -> + | Flags.ICMode | Flags.RefMode -> (* The callee *) get_meth_pair ^^ Arr.load_field 0l ^^ Blob.as_ptr_len env ^^ @@ -5095,7 +5095,7 @@ module FuncDec = struct let export_async_method env = let name = Dfinity.async_method_name in begin match E.mode env with - | Flags.ICMode | Flags.StubMode -> + | Flags.ICMode | Flags.RefMode -> Func.define_built_in env name [] [] (fun env -> let (set_closure, get_closure) = new_local env "closure" in @@ -6452,7 +6452,7 @@ and compile_exp (env : E.t) ae exp = | ICReplyPrim ts, [e] -> SR.unit, begin match E.mode env with - | Flags.ICMode | Flags.StubMode -> + | Flags.ICMode | Flags.RefMode -> compile_exp_as env ae SR.Vanilla e ^^ (* TODO: We can try to avoid the boxing and pass the arguments to serialize individually *) @@ -6465,7 +6465,7 @@ and compile_exp (env : E.t) ae exp = SR.unit, Dfinity.reject env (compile_exp_vanilla env ae e) | ICCallerPrim, [] -> - assert (E.mode env = Flags.ICMode || E.mode env = Flags.StubMode); + assert (E.mode env = Flags.ICMode || E.mode env = Flags.RefMode); Dfinity.caller env | ICCallPrim, [f;e;k;r] -> @@ -7047,7 +7047,7 @@ and export_actor_field env ae (f : Ir.field) = E.add_export env (nr { name = Wasm.Utf8.decode (match E.mode env with - | Flags.ICMode | Flags.StubMode -> + | Flags.ICMode | Flags.RefMode -> Mo_types.Type.( match normalize f.note with | Func(Shared sort,_,_,_,_) -> @@ -7165,7 +7165,7 @@ let compile mode module_name rts (progs : Ir.prog list) : Wasm_exts.CustomModule let start_fun = compile_start_func env progs in let start_fi = E.add_fun env "start" start_fun in let start_fi_o = match E.mode env with - | Flags.ICMode | Flags.StubMode -> Dfinity.export_init env start_fi; None + | Flags.ICMode | Flags.RefMode -> Dfinity.export_init env start_fi; None | Flags.WasmMode | Flags.WASIMode-> Some (nr start_fi) in conclude_module env start_fi_o diff --git a/src/exes/moc.ml b/src/exes/moc.ml index 91e18661e64..1f49ee31167 100644 --- a/src/exes/moc.ml +++ b/src/exes/moc.ml @@ -71,9 +71,9 @@ let argspec = Arg.align [ "-wasi-system-api", Arg.Unit (fun () -> Flags.(compile_mode := WASIMode)), " use the WASI system API (wasmtime)"; - "-stub-system-api", - Arg.Unit (fun () -> Flags.(compile_mode := StubMode)), - " use the future DFINITY system API (ic-stub-run)"; + "-ref-system-api", + Arg.Unit (fun () -> Flags.(compile_mode := RefMode)), + " use the future DFINITY system API (ic-ref-run)"; (* TODO: bring this back (possibly with flipped default) as soon as the multi-value `wasm` library is out. "-multi-value", Arg.Set Flags.multi_value, " use multi-value extension"; diff --git a/src/mo_config/flags.ml b/src/mo_config/flags.ml index 23e05953f81..7ff2bea713f 100644 --- a/src/mo_config/flags.ml +++ b/src/mo_config/flags.ml @@ -2,7 +2,7 @@ module M = Map.Make(String) -type compile_mode = WasmMode | ICMode | StubMode | WASIMode +type compile_mode = WasmMode | ICMode | RefMode | WASIMode let trace = ref false let verbose = ref false diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 541fc20b47c..f4a80f0d3b6 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -93,7 +93,7 @@ let flag_of_compile_mode mode = | Flags.ICMode -> "" | Flags.WASIMode -> " and flag -wasi-system-api" | Flags.WasmMode -> " and flag -no-system-api" - | Flags.StubMode -> " and flag -stub-system-api" + | Flags.RefMode -> " and flag -ref-system-api" let compile_mode_error mode env at fmt = Printf.ksprintf @@ -766,7 +766,7 @@ and infer_exp'' env exp : T.typ = ) | ObjE (sort, fields) -> if not in_prog && sort.it = T.Actor then - error_in [Flags.ICMode; Flags.StubMode] env exp.at "non-toplevel actor; an actor can only be declared at the toplevel of a program"; + error_in [Flags.ICMode; Flags.RefMode] env exp.at "non-toplevel actor; an actor can only be declared at the toplevel of a program"; let env' = if sort.it = T.Actor then {env with async = C.NullCap; in_actor = true} else env in infer_obj env' sort.it fields exp.at | DotE (exp1, id) -> @@ -820,7 +820,7 @@ and infer_exp'' env exp : T.typ = ) | FuncE (_, sort_pat, typ_binds, pat, typ_opt, _sugar, exp1) -> if not env.pre && not in_actor && T.is_shared_sort sort_pat.it then - error_in [Flags.ICMode; Flags.StubMode] env exp1.at "a shared function is only allowed as a public field of an actor"; + error_in [Flags.ICMode; Flags.RefMode] env exp1.at "a shared function is only allowed as a public field of an actor"; let typ = match typ_opt with | Some typ -> typ | None -> {it = TupT []; at = no_region; note = T.Pre} @@ -1175,7 +1175,7 @@ and check_exp' env0 t exp : T.typ = | FuncE (_, sort_pat, [], pat, typ_opt, _sugar, exp), T.Func (s, c, [], ts1, ts2) -> let sort, ve = check_sort_pat env sort_pat in if not env.pre && not env0.in_actor && T.is_shared_sort sort then - error_in [Flags.ICMode; Flags.StubMode] env exp.at "a shared function is only allowed as a public field of an actor"; + error_in [Flags.ICMode; Flags.RefMode] env exp.at "a shared function is only allowed as a public field of an actor"; let ve1 = check_pat_exhaustive (if T.is_shared_sort sort then local_error else warn) env (T.seq ts1) pat in let ve2 = T.Env.adjoin ve ve1 in let codom = T.codom c (fun () -> assert false) ts2 in @@ -1624,7 +1624,7 @@ and infer_obj env s fields at : T.typ = ) fields; List.iter (fun ef -> if ef.it.vis.it = Syntax.Private && is_actor_method ef.it.dec then - error_in [Flags.ICMode; Flags.StubMode] env ef.it.dec.at + error_in [Flags.ICMode; Flags.RefMode] env ef.it.dec.at "a shared function cannot be private" ) fields; end; @@ -1956,14 +1956,14 @@ and infer_dec_valdecs env dec : Scope.t = } | ClassD (id, typ_binds, pat, _, sort, _, _) -> if sort.it = T.Actor then - error_in [Flags.ICMode; Flags.StubMode] env dec.at + error_in [Flags.ICMode; Flags.RefMode] env dec.at "actor classes are not supported; use an actor declaration instead"; let rec is_unit_pat p = match p.it with | ParP p -> is_unit_pat p | TupP [] -> true | _ -> false in if sort.it = T.Actor && not (is_unit_pat pat) then - error_in [Flags.StubMode] env dec.at + error_in [Flags.RefMode] env dec.at "actor classes with parameters are not supported; use an actor declaration instead"; let cs, tbs, te, ce = check_typ_binds env typ_binds in let env' = adjoin_typs env te ce in @@ -2018,7 +2018,7 @@ let check_actors scope progs : unit Diag.result = | [] -> () | [d] -> () | (d::ds) when is_actor_dec d -> - recover (error_in [Flags.ICMode; Flags.StubMode] env d.at) + recover (error_in [Flags.ICMode; Flags.RefMode] env d.at) "an actor must be the last declaration in a program" | (d::ds) -> go ds in go prog diff --git a/test/compare-wat.sh b/test/compare-wat.sh index 6c7692f989b..3ed2e6b71ba 100755 --- a/test/compare-wat.sh +++ b/test/compare-wat.sh @@ -71,14 +71,14 @@ do rm -rf compare-out/$base.old mkdir compare-out/$base.old - old-moc/bin/moc $file -stub-system-api -o compare-out/$base.old/$base.wasm 2> compare-out/$base.old/$base.stderr + old-moc/bin/moc $file -ref-system-api -o compare-out/$base.old/$base.wasm 2> compare-out/$base.old/$base.stderr test ! -e compare-out/$base.old/$base.wasm || $WASM2WAT compare-out/$base.old/$base.wasm >& compare-out/$base.old/$base.wat #wasm-objdump -s -h -d compare-out/$base.old/$base.wasm > compare-out/$base.old/$base.dump rm -rf compare-out/$base.new mkdir compare-out/$base.new - new-moc/bin/moc $file -stub-system-api -o compare-out/$base.new/$base.wasm 2> compare-out/$base.new/$base.stderr + new-moc/bin/moc $file -ref-system-api -o compare-out/$base.new/$base.wasm 2> compare-out/$base.new/$base.stderr test ! -e compare-out/$base.new/$base.wasm || $WASM2WAT compare-out/$base.new/$base.wasm >& compare-out/$base.new/$base.wat #wasm-objdump -s -h -d compare-out/$base.new/$base.wasm > compare-out/$base.new/$base.dump diff --git a/test/ic-stub-run-wrapper.sh b/test/ic-ref-run-wrapper.sh similarity index 82% rename from test/ic-stub-run-wrapper.sh rename to test/ic-ref-run-wrapper.sh index 52135b00f0e..4bd8b3768e2 100755 --- a/test/ic-stub-run-wrapper.sh +++ b/test/ic-ref-run-wrapper.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -IC_STUB_RUN=${IC_STUB_RUN:-ic-stub-run} +IC_REF_RUN=${IC_REF_RUN:-ic-ref-run} CONFIG=$(realpath $(dirname $0)/drun.toml) @@ -15,4 +15,4 @@ export LANG=C.UTF-8 (echo "install ic:2A012B $1 0x"; if [ -n "$2" ]; then LANG=C perl -ne 'print "$1 ic:2A012B $2\n" if m,^//CALL (ingress|query) (.*),;print "upgrade ic:2A012B '"$1"' 0x\n" if m,^//CALL upgrade,; ' $2; fi; -) | $IC_STUB_RUN -c "$CONFIG" /dev/stdin +) | $IC_REF_RUN -c "$CONFIG" /dev/stdin diff --git a/test/run-drun/AST-64.mo b/test/run-drun/AST-64.mo index 9373aae8f42..53b885c7741 100644 --- a/test/run-drun/AST-64.mo +++ b/test/run-drun/AST-64.mo @@ -14,4 +14,4 @@ let _ = (object this { public func x() { this.x() } }) : Any; let _ = (object { public func x() { x() } }) : Any; //SKIP comp -//SKIP comp-stub +//SKIP comp-ref diff --git a/test/run-drun/actor-creation.mo b/test/run-drun/actor-creation.mo index 7f9d59a6689..2e2a594f940 100644 --- a/test/run-drun/actor-creation.mo +++ b/test/run-drun/actor-creation.mo @@ -23,4 +23,4 @@ actor a { a.foo(); //OR-CALL ingress foo "DIDL\x00\x00" // certainly won’t work on drun //SKIP comp -//SKIP comp-stub +//SKIP comp-ref diff --git a/test/run-drun/actor-import.mo b/test/run-drun/actor-import.mo index 4085a78fbe2..f1b839358f1 100644 --- a/test/run-drun/actor-import.mo +++ b/test/run-drun/actor-import.mo @@ -3,7 +3,7 @@ // this imports our own IDL, stored in actor-import -// currently hard-codes the ic-stub self id +// currently hard-codes the ic-ref self id // once we have actor aliases we can let run.sh set an alias. import imported1 "ic:2A012B"; diff --git a/test/run-drun/chat.mo b/test/run-drun/chat.mo index 6a65e517d67..c8e2e082b04 100644 --- a/test/run-drun/chat.mo +++ b/test/run-drun/chat.mo @@ -70,4 +70,4 @@ actor Test { Test.go(); //OR-CALL ingress go "DIDL\x00\x00" //SKIP comp -//SKIP comp-stub +//SKIP comp-ref diff --git a/test/run-drun/control.mo b/test/run-drun/control.mo index 0872f79af80..534a3792fb5 100644 --- a/test/run-drun/control.mo +++ b/test/run-drun/control.mo @@ -1,7 +1,7 @@ // Nothing to run here (but do compile and validate) //SKIP drun-run -//SKIP ic-stub-run +//SKIP ic-ref-run actor control { diff --git a/test/run-drun/create-then-trap.mo b/test/run-drun/create-then-trap.mo index 50ff8f6c635..d5a1b93962d 100644 --- a/test/run-drun/create-then-trap.mo +++ b/test/run-drun/create-then-trap.mo @@ -14,6 +14,6 @@ a.go(); //OR-CALL ingress go "DIDL\x00\x00" // disabled, because hard to use Prim from inner actor -// a bit sad, because this test is mostly interesting on ic-stub +// a bit sad, because this test is mostly interesting on ic-ref-run -//SKIP comp-stub +//SKIP comp-ref diff --git a/test/run-drun/general-type-components.mo b/test/run-drun/general-type-components.mo index cad2c15b898..998e62876cb 100644 --- a/test/run-drun/general-type-components.mo +++ b/test/run-drun/general-type-components.mo @@ -27,4 +27,4 @@ actor A = { type AT = A.T; //SKIP comp -//SKIP comp-stub +//SKIP comp-ref diff --git a/test/run-drun/large-array.mo b/test/run-drun/large-array.mo index 778ea148c75..7cf4579ee78 100644 --- a/test/run-drun/large-array.mo +++ b/test/run-drun/large-array.mo @@ -8,4 +8,4 @@ Prim.debugPrint "done"; //SKIP run //SKIP run-ir //SKIP run-low -//SKIP comp-stub +//SKIP comp-ref diff --git a/test/run-drun/log-slow.mo b/test/run-drun/log-slow.mo index 49111076ed5..589ee7bf8da 100644 --- a/test/run-drun/log-slow.mo +++ b/test/run-drun/log-slow.mo @@ -1,5 +1,5 @@ // These are rather long-running tests, not advisable for wasm-run! -//SKIP comp-stub +//SKIP comp-ref import Prim "mo:prim"; diff --git a/test/run-drun/ok/AST-66.ic-stub-run.ok b/test/run-drun/ok/AST-66.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/AST-66.ic-stub-run.ok rename to test/run-drun/ok/AST-66.ic-ref-run.ok diff --git a/test/run-drun/ok/GIT-843.ic-stub-run.ok b/test/run-drun/ok/GIT-843.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/GIT-843.ic-stub-run.ok rename to test/run-drun/ok/GIT-843.ic-ref-run.ok diff --git a/test/run-drun/ok/actor-import.ic-stub-run.ok b/test/run-drun/ok/actor-import.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/actor-import.ic-stub-run.ok rename to test/run-drun/ok/actor-import.ic-ref-run.ok diff --git a/test/run-drun/ok/actor-reference-return.ic-stub-run.ok b/test/run-drun/ok/actor-reference-return.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/actor-reference-return.ic-stub-run.ok rename to test/run-drun/ok/actor-reference-return.ic-ref-run.ok diff --git a/test/run-drun/ok/actor-reference.ic-stub-run.ok b/test/run-drun/ok/actor-reference.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/actor-reference.ic-stub-run.ok rename to test/run-drun/ok/actor-reference.ic-ref-run.ok diff --git a/test/run-drun/ok/aritybug.comp-stub.ok b/test/run-drun/ok/aritybug.comp-ref.ok similarity index 72% rename from test/run-drun/ok/aritybug.comp-stub.ok rename to test/run-drun/ok/aritybug.comp-ref.ok index 17030177185..8a29e224d7f 100644 --- a/test/run-drun/ok/aritybug.comp-stub.ok +++ b/test/run-drun/ok/aritybug.comp-ref.ok @@ -1,3 +1,3 @@ aritybug.mo:13.41-15.2: type error, a shared function is only allowed as a public field of an actor - (This is a limitation of the current version and flag -stub-system-api.) + (This is a limitation of the current version and flag -ref-system-api.) aritybug.mo:17.25-22.2: type error, misplaced async expression; try enclosing in an async function diff --git a/test/run-drun/ok/aritybug.comp-stub.ret.ok b/test/run-drun/ok/aritybug.comp-ref.ret.ok similarity index 100% rename from test/run-drun/ok/aritybug.comp-stub.ret.ok rename to test/run-drun/ok/aritybug.comp-ref.ret.ok diff --git a/test/run-drun/ok/array-out-of-bounds.ic-stub-run.ok b/test/run-drun/ok/array-out-of-bounds.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/array-out-of-bounds.ic-stub-run.ok rename to test/run-drun/ok/array-out-of-bounds.ic-ref-run.ok diff --git a/test/run-drun/ok/async-any.ic-stub-run.ok b/test/run-drun/ok/async-any.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/async-any.ic-stub-run.ok rename to test/run-drun/ok/async-any.ic-ref-run.ok diff --git a/test/run-drun/ok/async-calls1.ic-stub-run.ok b/test/run-drun/ok/async-calls1.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/async-calls1.ic-stub-run.ok rename to test/run-drun/ok/async-calls1.ic-ref-run.ok diff --git a/test/run-drun/ok/async-calls2.ic-stub-run.ok b/test/run-drun/ok/async-calls2.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/async-calls2.ic-stub-run.ok rename to test/run-drun/ok/async-calls2.ic-ref-run.ok diff --git a/test/run-drun/ok/async-calls3.ic-stub-run.ok b/test/run-drun/ok/async-calls3.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/async-calls3.ic-stub-run.ok rename to test/run-drun/ok/async-calls3.ic-ref-run.ok diff --git a/test/run-drun/ok/async-free-var.ic-stub-run.ok b/test/run-drun/ok/async-free-var.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/async-free-var.ic-stub-run.ok rename to test/run-drun/ok/async-free-var.ic-ref-run.ok diff --git a/test/run-drun/ok/async-loop-while.ic-stub-run.ok b/test/run-drun/ok/async-loop-while.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/async-loop-while.ic-stub-run.ok rename to test/run-drun/ok/async-loop-while.ic-ref-run.ok diff --git a/test/run-drun/ok/async-loop.ic-stub-run.ok b/test/run-drun/ok/async-loop.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/async-loop.ic-stub-run.ok rename to test/run-drun/ok/async-loop.ic-ref-run.ok diff --git a/test/run-drun/ok/async-new-obj.ic-stub-run.ok b/test/run-drun/ok/async-new-obj.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/async-new-obj.ic-stub-run.ok rename to test/run-drun/ok/async-new-obj.ic-ref-run.ok diff --git a/test/run-drun/ok/async-obj-mut.ic-stub-run.ok b/test/run-drun/ok/async-obj-mut.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/async-obj-mut.ic-stub-run.ok rename to test/run-drun/ok/async-obj-mut.ic-ref-run.ok diff --git a/test/run-drun/ok/async-while.ic-stub-run.ok b/test/run-drun/ok/async-while.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/async-while.ic-stub-run.ok rename to test/run-drun/ok/async-while.ic-ref-run.ok diff --git a/test/run-drun/ok/await-sugar.ic-stub-run.ok b/test/run-drun/ok/await-sugar.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/await-sugar.ic-stub-run.ok rename to test/run-drun/ok/await-sugar.ic-ref-run.ok diff --git a/test/run-drun/ok/await.ic-stub-run.ok b/test/run-drun/ok/await.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/await.ic-stub-run.ok rename to test/run-drun/ok/await.ic-ref-run.ok diff --git a/test/run-drun/ok/block.ic-stub-run.ok b/test/run-drun/ok/block.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/block.ic-stub-run.ok rename to test/run-drun/ok/block.ic-ref-run.ok diff --git a/test/run-drun/ok/call-async-method.ic-stub-run.ok b/test/run-drun/ok/call-async-method.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/call-async-method.ic-stub-run.ok rename to test/run-drun/ok/call-async-method.ic-ref-run.ok diff --git a/test/run-drun/ok/caller.ic-stub-run.ok b/test/run-drun/ok/caller.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/caller.ic-stub-run.ok rename to test/run-drun/ok/caller.ic-ref-run.ok diff --git a/test/run-drun/ok/closure-params.ic-stub-run.ok b/test/run-drun/ok/closure-params.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/closure-params.ic-stub-run.ok rename to test/run-drun/ok/closure-params.ic-ref-run.ok diff --git a/test/run-drun/ok/count-callbacks.ic-stub-run.ok b/test/run-drun/ok/count-callbacks.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/count-callbacks.ic-stub-run.ok rename to test/run-drun/ok/count-callbacks.ic-ref-run.ok diff --git a/test/run-drun/ok/counter.ic-stub-run.ok b/test/run-drun/ok/counter.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/counter.ic-stub-run.ok rename to test/run-drun/ok/counter.ic-ref-run.ok diff --git a/test/run-drun/ok/counter2.ic-stub-run.ok b/test/run-drun/ok/counter2.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/counter2.ic-stub-run.ok rename to test/run-drun/ok/counter2.ic-ref-run.ok diff --git a/test/run-drun/ok/data-params.ic-stub-run.ok b/test/run-drun/ok/data-params.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/data-params.ic-stub-run.ok rename to test/run-drun/ok/data-params.ic-ref-run.ok diff --git a/test/run-drun/ok/divide-by-zero.ic-stub-run.ok b/test/run-drun/ok/divide-by-zero.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/divide-by-zero.ic-stub-run.ok rename to test/run-drun/ok/divide-by-zero.ic-ref-run.ok diff --git a/test/run-drun/ok/empty-actor.ic-stub-run.ok b/test/run-drun/ok/empty-actor.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/empty-actor.ic-stub-run.ok rename to test/run-drun/ok/empty-actor.ic-ref-run.ok diff --git a/test/run-drun/ok/empty-call.ic-stub-run.ok b/test/run-drun/ok/empty-call.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/empty-call.ic-stub-run.ok rename to test/run-drun/ok/empty-call.ic-ref-run.ok diff --git a/test/run-drun/ok/flatten-awaitables.ic-stub-run.ok b/test/run-drun/ok/flatten-awaitables.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/flatten-awaitables.ic-stub-run.ok rename to test/run-drun/ok/flatten-awaitables.ic-ref-run.ok diff --git a/test/run-drun/ok/for-await.ic-stub-run.ok b/test/run-drun/ok/for-await.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/for-await.ic-stub-run.ok rename to test/run-drun/ok/for-await.ic-ref-run.ok diff --git a/test/run-drun/ok/free-callbacks.ic-stub-run.ok b/test/run-drun/ok/free-callbacks.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/free-callbacks.ic-stub-run.ok rename to test/run-drun/ok/free-callbacks.ic-ref-run.ok diff --git a/test/run-drun/ok/general_await.ic-stub-run.ok b/test/run-drun/ok/general_await.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/general_await.ic-stub-run.ok rename to test/run-drun/ok/general_await.ic-ref-run.ok diff --git a/test/run-drun/ok/general_await_implicit.ic-stub-run.ok b/test/run-drun/ok/general_await_implicit.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/general_await_implicit.ic-stub-run.ok rename to test/run-drun/ok/general_await_implicit.ic-ref-run.ok diff --git a/test/run-drun/ok/generic-tail-rec.ic-stub-run.ok b/test/run-drun/ok/generic-tail-rec.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/generic-tail-rec.ic-stub-run.ok rename to test/run-drun/ok/generic-tail-rec.ic-ref-run.ok diff --git a/test/run-drun/ok/hello-world-async.ic-stub-run.ok b/test/run-drun/ok/hello-world-async.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/hello-world-async.ic-stub-run.ok rename to test/run-drun/ok/hello-world-async.ic-ref-run.ok diff --git a/test/run-drun/ok/hello-world-await.ic-stub-run.ok b/test/run-drun/ok/hello-world-await.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/hello-world-await.ic-stub-run.ok rename to test/run-drun/ok/hello-world-await.ic-ref-run.ok diff --git a/test/run-drun/ok/hello-world-message.ic-stub-run.ok b/test/run-drun/ok/hello-world-message.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/hello-world-message.ic-stub-run.ok rename to test/run-drun/ok/hello-world-message.ic-ref-run.ok diff --git a/test/run-drun/ok/hello-world-return.ic-stub-run.ok b/test/run-drun/ok/hello-world-return.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/hello-world-return.ic-stub-run.ok rename to test/run-drun/ok/hello-world-return.ic-ref-run.ok diff --git a/test/run-drun/ok/hello-world.ic-stub-run.ok b/test/run-drun/ok/hello-world.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/hello-world.ic-stub-run.ok rename to test/run-drun/ok/hello-world.ic-ref-run.ok diff --git a/test/run-drun/ok/ic-calls.ic-stub-run.ok b/test/run-drun/ok/ic-calls.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/ic-calls.ic-stub-run.ok rename to test/run-drun/ok/ic-calls.ic-ref-run.ok diff --git a/test/run-drun/ok/idl-any.ic-stub-run.ok b/test/run-drun/ok/idl-any.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/idl-any.ic-stub-run.ok rename to test/run-drun/ok/idl-any.ic-ref-run.ok diff --git a/test/run-drun/ok/idl-bad.ic-stub-run.ok b/test/run-drun/ok/idl-bad.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/idl-bad.ic-stub-run.ok rename to test/run-drun/ok/idl-bad.ic-ref-run.ok diff --git a/test/run-drun/ok/idl-buf-size-bug.ic-stub-run.ok b/test/run-drun/ok/idl-buf-size-bug.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/idl-buf-size-bug.ic-stub-run.ok rename to test/run-drun/ok/idl-buf-size-bug.ic-ref-run.ok diff --git a/test/run-drun/ok/idl-field-escape.ic-stub-run.ok b/test/run-drun/ok/idl-field-escape.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/idl-field-escape.ic-stub-run.ok rename to test/run-drun/ok/idl-field-escape.ic-ref-run.ok diff --git a/test/run-drun/ok/idl-func.ic-stub-run.ok b/test/run-drun/ok/idl-func.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/idl-func.ic-stub-run.ok rename to test/run-drun/ok/idl-func.ic-ref-run.ok diff --git a/test/run-drun/ok/idl-mo.ic-stub-run.ok b/test/run-drun/ok/idl-mo.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/idl-mo.ic-stub-run.ok rename to test/run-drun/ok/idl-mo.ic-ref-run.ok diff --git a/test/run-drun/ok/idl-nary.ic-stub-run.ok b/test/run-drun/ok/idl-nary.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/idl-nary.ic-stub-run.ok rename to test/run-drun/ok/idl-nary.ic-ref-run.ok diff --git a/test/run-drun/ok/idl-nat-int.ic-stub-run.ok b/test/run-drun/ok/idl-nat-int.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/idl-nat-int.ic-stub-run.ok rename to test/run-drun/ok/idl-nat-int.ic-ref-run.ok diff --git a/test/run-drun/ok/idl-option.ic-stub-run.ok b/test/run-drun/ok/idl-option.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/idl-option.ic-stub-run.ok rename to test/run-drun/ok/idl-option.ic-ref-run.ok diff --git a/test/run-drun/ok/idl-pair.ic-stub-run.ok b/test/run-drun/ok/idl-pair.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/idl-pair.ic-stub-run.ok rename to test/run-drun/ok/idl-pair.ic-ref-run.ok diff --git a/test/run-drun/ok/idl-record.ic-stub-run.ok b/test/run-drun/ok/idl-record.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/idl-record.ic-stub-run.ok rename to test/run-drun/ok/idl-record.ic-ref-run.ok diff --git a/test/run-drun/ok/idl-shorthand.ic-stub-run.ok b/test/run-drun/ok/idl-shorthand.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/idl-shorthand.ic-stub-run.ok rename to test/run-drun/ok/idl-shorthand.ic-ref-run.ok diff --git a/test/run-drun/ok/idl-tuple.ic-stub-run.ok b/test/run-drun/ok/idl-tuple.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/idl-tuple.ic-stub-run.ok rename to test/run-drun/ok/idl-tuple.ic-ref-run.ok diff --git a/test/run-drun/ok/idl-unit.ic-stub-run.ok b/test/run-drun/ok/idl-unit.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/idl-unit.ic-stub-run.ok rename to test/run-drun/ok/idl-unit.ic-ref-run.ok diff --git a/test/run-drun/ok/idl-variant.ic-stub-run.ok b/test/run-drun/ok/idl-variant.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/idl-variant.ic-stub-run.ok rename to test/run-drun/ok/idl-variant.ic-ref-run.ok diff --git a/test/run-drun/ok/idl-vector.ic-stub-run.ok b/test/run-drun/ok/idl-vector.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/idl-vector.ic-stub-run.ok rename to test/run-drun/ok/idl-vector.ic-ref-run.ok diff --git a/test/run-drun/ok/interleave.ic-stub-run.ok b/test/run-drun/ok/interleave.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/interleave.ic-stub-run.ok rename to test/run-drun/ok/interleave.ic-ref-run.ok diff --git a/test/run-drun/ok/issue-894.ic-stub-run.ok b/test/run-drun/ok/issue-894.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/issue-894.ic-stub-run.ok rename to test/run-drun/ok/issue-894.ic-ref-run.ok diff --git a/test/run-drun/ok/local-throw.ic-stub-run.ok b/test/run-drun/ok/local-throw.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/local-throw.ic-stub-run.ok rename to test/run-drun/ok/local-throw.ic-ref-run.ok diff --git a/test/run-drun/ok/mod-rebind.ic-stub-run.ok b/test/run-drun/ok/mod-rebind.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/mod-rebind.ic-stub-run.ok rename to test/run-drun/ok/mod-rebind.ic-ref-run.ok diff --git a/test/run-drun/ok/nary-async.ic-stub-run.ok b/test/run-drun/ok/nary-async.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/nary-async.ic-stub-run.ok rename to test/run-drun/ok/nary-async.ic-ref-run.ok diff --git a/test/run-drun/ok/oneway-throw.ic-stub-run.ok b/test/run-drun/ok/oneway-throw.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/oneway-throw.ic-stub-run.ok rename to test/run-drun/ok/oneway-throw.ic-ref-run.ok diff --git a/test/run-drun/ok/oneway.ic-stub-run.ok b/test/run-drun/ok/oneway.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/oneway.ic-stub-run.ok rename to test/run-drun/ok/oneway.ic-ref-run.ok diff --git a/test/run-drun/ok/oom.ic-stub-run.ok b/test/run-drun/ok/oom.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/oom.ic-stub-run.ok rename to test/run-drun/ok/oom.ic-ref-run.ok diff --git a/test/run-drun/ok/overflow.ic-stub-run.ok b/test/run-drun/ok/overflow.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/overflow.ic-stub-run.ok rename to test/run-drun/ok/overflow.ic-ref-run.ok diff --git a/test/run-drun/ok/pass-references.comp-stub.ok b/test/run-drun/ok/pass-references.comp-ref.ok similarity index 61% rename from test/run-drun/ok/pass-references.comp-stub.ok rename to test/run-drun/ok/pass-references.comp-ref.ok index 46f914d3ac0..1a74d1d90c9 100644 --- a/test/run-drun/ok/pass-references.comp-stub.ok +++ b/test/run-drun/ok/pass-references.comp-ref.ok @@ -1,2 +1,2 @@ pass-references.mo:14.5-16.6: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program - (This is a limitation of the current version and flag -stub-system-api.) + (This is a limitation of the current version and flag -ref-system-api.) diff --git a/test/run-drun/ok/pass-references.comp-stub.ret.ok b/test/run-drun/ok/pass-references.comp-ref.ret.ok similarity index 100% rename from test/run-drun/ok/pass-references.comp-stub.ret.ok rename to test/run-drun/ok/pass-references.comp-ref.ret.ok diff --git a/test/run-drun/ok/print-from-init.ic-stub-run.ok b/test/run-drun/ok/print-from-init.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/print-from-init.ic-stub-run.ok rename to test/run-drun/ok/print-from-init.ic-ref-run.ok diff --git a/test/run-drun/ok/query.ic-stub-run.ok b/test/run-drun/ok/query.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/query.ic-stub-run.ok rename to test/run-drun/ok/query.ic-ref-run.ok diff --git a/test/run-drun/ok/query2.ic-stub-run.ok b/test/run-drun/ok/query2.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/query2.ic-stub-run.ok rename to test/run-drun/ok/query2.ic-ref-run.ok diff --git a/test/run-drun/ok/reject.ic-stub-run.ok b/test/run-drun/ok/reject.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/reject.ic-stub-run.ok rename to test/run-drun/ok/reject.ic-ref-run.ok diff --git a/test/run-drun/ok/rts-stats.ic-stub-run.ok b/test/run-drun/ok/rts-stats.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/rts-stats.ic-stub-run.ok rename to test/run-drun/ok/rts-stats.ic-ref-run.ok diff --git a/test/run-drun/ok/self-shadow.comp-stub.ok b/test/run-drun/ok/self-shadow.comp-ref.ok similarity index 60% rename from test/run-drun/ok/self-shadow.comp-stub.ok rename to test/run-drun/ok/self-shadow.comp-ref.ok index 8765182a4d1..40f9b33fcf3 100644 --- a/test/run-drun/ok/self-shadow.comp-stub.ok +++ b/test/run-drun/ok/self-shadow.comp-ref.ok @@ -1,2 +1,2 @@ self-shadow.mo:5.15-5.49: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program - (This is a limitation of the current version and flag -stub-system-api.) + (This is a limitation of the current version and flag -ref-system-api.) diff --git a/test/run-drun/ok/self-shadow.comp-stub.ret.ok b/test/run-drun/ok/self-shadow.comp-ref.ret.ok similarity index 100% rename from test/run-drun/ok/self-shadow.comp-stub.ret.ok rename to test/run-drun/ok/self-shadow.comp-ref.ret.ok diff --git a/test/run-drun/ok/selftail.ic-stub-run.ok b/test/run-drun/ok/selftail.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/selftail.ic-stub-run.ok rename to test/run-drun/ok/selftail.ic-ref-run.ok diff --git a/test/run-drun/ok/shared-object.ic-stub-run.ok b/test/run-drun/ok/shared-object.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/shared-object.ic-stub-run.ok rename to test/run-drun/ok/shared-object.ic-ref-run.ok diff --git a/test/run-drun/ok/sharingbug.ic-stub-run.ok b/test/run-drun/ok/sharingbug.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/sharingbug.ic-stub-run.ok rename to test/run-drun/ok/sharingbug.ic-ref-run.ok diff --git a/test/run-drun/ok/show.ic-stub-run.ok b/test/run-drun/ok/show.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/show.ic-stub-run.ok rename to test/run-drun/ok/show.ic-ref-run.ok diff --git a/test/run-drun/ok/static-gc.ic-stub-run.ok b/test/run-drun/ok/static-gc.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/static-gc.ic-stub-run.ok rename to test/run-drun/ok/static-gc.ic-ref-run.ok diff --git a/test/run-drun/ok/switch-await.ic-stub-run.ok b/test/run-drun/ok/switch-await.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/switch-await.ic-stub-run.ok rename to test/run-drun/ok/switch-await.ic-ref-run.ok diff --git a/test/run-drun/ok/text-iter.ic-stub-run.ok b/test/run-drun/ok/text-iter.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/text-iter.ic-stub-run.ok rename to test/run-drun/ok/text-iter.ic-ref-run.ok diff --git a/test/run-drun/ok/throw.ic-stub-run.ok b/test/run-drun/ok/throw.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/throw.ic-stub-run.ok rename to test/run-drun/ok/throw.ic-ref-run.ok diff --git a/test/run-drun/ok/transpose.ic-stub-run.ok b/test/run-drun/ok/transpose.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/transpose.ic-stub-run.ok rename to test/run-drun/ok/transpose.ic-ref-run.ok diff --git a/test/run-drun/ok/type-lub.ic-stub-run.ok b/test/run-drun/ok/type-lub.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/type-lub.ic-stub-run.ok rename to test/run-drun/ok/type-lub.ic-ref-run.ok diff --git a/test/run-drun/ok/unsupported-more.comp-stub.ok b/test/run-drun/ok/unsupported-more.comp-ref.ok similarity index 55% rename from test/run-drun/ok/unsupported-more.comp-stub.ok rename to test/run-drun/ok/unsupported-more.comp-ref.ok index da64326058f..4228207b658 100644 --- a/test/run-drun/ok/unsupported-more.comp-stub.ok +++ b/test/run-drun/ok/unsupported-more.comp-ref.ok @@ -1,2 +1,2 @@ unsupported-more.mo:2.1-5.2: type error, an actor must be the last declaration in a program - (This is a limitation of the current version and flag -stub-system-api.) + (This is a limitation of the current version and flag -ref-system-api.) diff --git a/test/run-drun/ok/unsupported-more.comp-stub.ret.ok b/test/run-drun/ok/unsupported-more.comp-ref.ret.ok similarity index 100% rename from test/run-drun/ok/unsupported-more.comp-stub.ret.ok rename to test/run-drun/ok/unsupported-more.comp-ref.ret.ok diff --git a/test/run-drun/ok/unsupported.comp-stub.ok b/test/run-drun/ok/unsupported.comp-ref.ok similarity index 58% rename from test/run-drun/ok/unsupported.comp-stub.ok rename to test/run-drun/ok/unsupported.comp-ref.ok index 03b4745f859..82c9c8d95d0 100644 --- a/test/run-drun/ok/unsupported.comp-stub.ok +++ b/test/run-drun/ok/unsupported.comp-ref.ok @@ -1,16 +1,16 @@ unsupported.mo:4.5-4.41: type error, a shared function cannot be private - (This is a limitation of the current version and flag -stub-system-api.) + (This is a limitation of the current version and flag -ref-system-api.) unsupported.mo:36.26-36.29: type error, a shared function is only allowed as a public field of an actor - (This is a limitation of the current version and flag -stub-system-api.) + (This is a limitation of the current version and flag -ref-system-api.) unsupported.mo:50.3-50.35: type error, actor classes are not supported; use an actor declaration instead - (This is a limitation of the current version and flag -stub-system-api.) + (This is a limitation of the current version and flag -ref-system-api.) unsupported.mo:54.3-54.42: type error, actor classes are not supported; use an actor declaration instead - (This is a limitation of the current version and flag -stub-system-api.) + (This is a limitation of the current version and flag -ref-system-api.) unsupported.mo:58.45-58.53: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program - (This is a limitation of the current version and flag -stub-system-api.) + (This is a limitation of the current version and flag -ref-system-api.) unsupported.mo:62.37-62.45: type error, non-toplevel actor; an actor can only be declared at the toplevel of a program - (This is a limitation of the current version and flag -stub-system-api.) + (This is a limitation of the current version and flag -ref-system-api.) unsupported.mo:72.34-72.37: type error, a shared function is only allowed as a public field of an actor - (This is a limitation of the current version and flag -stub-system-api.) + (This is a limitation of the current version and flag -ref-system-api.) unsupported.mo:73.27-73.30: type error, a shared function is only allowed as a public field of an actor - (This is a limitation of the current version and flag -stub-system-api.) + (This is a limitation of the current version and flag -ref-system-api.) diff --git a/test/run-drun/ok/unsupported.comp-stub.ret.ok b/test/run-drun/ok/unsupported.comp-ref.ret.ok similarity index 100% rename from test/run-drun/ok/unsupported.comp-stub.ret.ok rename to test/run-drun/ok/unsupported.comp-ref.ret.ok diff --git a/test/run-drun/ok/upgrade.ic-stub-run.ok b/test/run-drun/ok/upgrade.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/upgrade.ic-stub-run.ok rename to test/run-drun/ok/upgrade.ic-ref-run.ok diff --git a/test/run-drun/ok/utf8.ic-stub-run.ok b/test/run-drun/ok/utf8.ic-ref-run.ok similarity index 100% rename from test/run-drun/ok/utf8.ic-stub-run.ok rename to test/run-drun/ok/utf8.ic-ref-run.ok diff --git a/test/run-drun/reference-params.mo b/test/run-drun/reference-params.mo index d5425c90ffc..234e2e8848d 100644 --- a/test/run-drun/reference-params.mo +++ b/test/run-drun/reference-params.mo @@ -54,4 +54,4 @@ actor Test { Test.go(); //OR-CALL ingress go "DIDL\x00\x00" //SKIP comp -//SKIP comp-stub +//SKIP comp-ref diff --git a/test/run-drun/show-in-actor.mo b/test/run-drun/show-in-actor.mo index feaca848341..eb92d777ec7 100644 --- a/test/run-drun/show-in-actor.mo +++ b/test/run-drun/show-in-actor.mo @@ -8,4 +8,4 @@ let _ = actor { // non-closed actors not allowed //SKIP comp -//SKIP comp-stub +//SKIP comp-ref diff --git a/test/run-drun/tailpositions.mo b/test/run-drun/tailpositions.mo index bc1f6275e99..5cec53ecfb3 100644 --- a/test/run-drun/tailpositions.mo +++ b/test/run-drun/tailpositions.mo @@ -1,7 +1,7 @@ import Prim "mo:prim"; /* test tail-position calculation; error would stack overflow in drun*/ -//SKIP comp-stub +//SKIP comp-ref let bound:Int = 100000; diff --git a/test/run.sh b/test/run.sh index f35c7f234e4..4de67101d2d 100755 --- a/test/run.sh +++ b/test/run.sh @@ -7,7 +7,7 @@ # Options: # # -a: Update the files in ok/ -# -d: Run on in drun (or, if not possible, in stub) +# -d: Run on in drun (or, if not possible, in ic-ref-run) # -t: Only typecheck # -s: Be silent in sunny-day execution # -i: Only check mo to idl generation @@ -32,8 +32,8 @@ WASMTIME=${WASMTIME:-wasmtime} WASMTIME_OPTIONS="--disable-cache --cranelift" DRUN=${DRUN:-drun} DRUN_WRAPPER=$(realpath $(dirname $0)/drun-wrapper.sh) -IC_STUB_RUN_WRAPPER=$(realpath $(dirname $0)/ic-stub-run-wrapper.sh) -IC_STUB_RUN=${IC_STUB_RUN:-ic-stub-run} +IC_REF_RUN_WRAPPER=$(realpath $(dirname $0)/ic-ref-run-wrapper.sh) +IC_REF_RUN=${IC_REF_RUN:-ic-ref-run} SKIP_RUNNING=${SKIP_RUNNING:-no} ONLY_TYPECHECK=no ECHO=echo @@ -149,7 +149,7 @@ then fi HAVE_DRUN=no -HAVE_IC_STUB_RUN=no +HAVE_IC_REF_RUN=no if [ $DTESTS = yes -o $PERF = yes ] then @@ -170,17 +170,17 @@ fi if [ $DTESTS = yes -o $PERF = yes ] then - if $IC_STUB_RUN --help >& /dev/null + if $IC_REF_RUN --help >& /dev/null then - HAVE_IC_STUB_RUN=yes + HAVE_IC_REF_RUN=yes else if [ $ACCEPT = yes ] then - echo "ERROR: Could not run $IC_STUB_RUN, cannot update expected test output" + echo "ERROR: Could not run $IC_REF_RUN, cannot update expected test output" exit 1 else - echo "WARNING: Could not run $IC_STUB_RUN, will skip some tests" - HAVE_IC_STUB_RUN=no + echo "WARNING: Could not run $IC_REF_RUN, will skip some tests" + HAVE_IC_REF_RUN=no fi fi fi @@ -299,7 +299,7 @@ do if [ $DTESTS = yes ] then run comp $MOC $moc_extra_flags --hide-warnings --map -c $mangled -o $out/$base.wasm - run comp-stub $MOC $moc_extra_flags -stub-system-api --hide-warnings --map -c $mangled -o $out/$base.stub.wasm + run comp-ref $MOC $moc_extra_flags -ref-system-api --hide-warnings --map -c $mangled -o $out/$base.ref.wasm elif [ $PERF = yes ] then run comp $MOC $moc_extra_flags --hide-warnings --map -c $mangled -o $out/$base.wasm @@ -308,7 +308,7 @@ do fi run_if wasm valid wasm-validate $out/$base.wasm - run_if stub.wasm valid-stub wasm-validate $out/$base.stub.wasm + run_if ref.wasm valid-ref wasm-validate $out/$base.ref.wasm if [ -e $out/$base.wasm ] then @@ -333,8 +333,8 @@ do if [ $HAVE_DRUN = yes ]; then run_if wasm drun-run $DRUN_WRAPPER $out/$base.wasm $mangled fi - if [ $HAVE_IC_STUB_RUN = yes ]; then - run_if stub.wasm ic-stub-run $IC_STUB_RUN_WRAPPER $out/$base.stub.wasm $mangled + if [ $HAVE_IC_REF_RUN = yes ]; then + run_if ref.wasm ic-ref-run $IC_REF_RUN_WRAPPER $out/$base.ref.wasm $mangled fi elif [ $PERF = yes ] then From b69a5006ff15d24e0a809141c99d2353b5920fba Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Mon, 2 Mar 2020 11:46:09 +0000 Subject: [PATCH 1080/1176] add test for invariance of mutable arrays --- test/fail/inference.mo | 16 +++++++++++++++- test/fail/ok/inference.tc.ok | 3 +++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/test/fail/inference.mo b/test/fail/inference.mo index fad54367be3..5c898c5c45e 100644 --- a/test/fail/inference.mo +++ b/test/fail/inference.mo @@ -147,5 +147,19 @@ func i(x:T) { func j(x:T) { func f(y:U):U{y}; - ignore f(x) : None; // fail (requires inference w.r.t expected type + ignore f(x) : None; // fail (requires inference w.r.t expected type) }; + +// immutable arrays + +func choose(b:Bool,x:[T],y:[T]):[T] {if b x else y}; +ignore choose(true,[1:Nat],[1:Nat]); +ignore choose(true,[1:Int],[1:Int]); +ignore choose(true,[1:Nat],[1:Int]); + + +// mutable arrays +func choose_var(b:Bool,x:[var T],y:[var T]):[var T] {if b x else y}; +ignore choose_var(true,[var (1:Nat)],[var (1:Nat)]); +ignore choose_var(true,[var (1:Int)],[var (1:Int)]); +ignore choose_var(true,[var (1:Nat)],[var (1:Int)]); // rejected as overconstrained (variance not applicable diff --git a/test/fail/ok/inference.tc.ok b/test/fail/ok/inference.tc.ok index 9332297266a..2fac57c1a37 100644 --- a/test/fail/ok/inference.tc.ok +++ b/test/fail/ok/inference.tc.ok @@ -58,3 +58,6 @@ inference.mo:150.11-150.15: type error, expression of type T/37 cannot produce expected type None +inference.mo:165.8-165.52: type error, cannot instantiate function of type (Bool, [var T], [var T]) -> [var T] to argument of type (Bool, [var Nat], [var Int]): + over-constrained implicit instantiation requires Int <: T <: Nat, + but Int Date: Mon, 2 Mar 2020 14:11:14 +0000 Subject: [PATCH 1081/1176] fix typo --- test/fail/inference.mo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/fail/inference.mo b/test/fail/inference.mo index 5c898c5c45e..d6184ff2f6c 100644 --- a/test/fail/inference.mo +++ b/test/fail/inference.mo @@ -162,4 +162,4 @@ ignore choose(true,[1:Nat],[1:Int]); func choose_var(b:Bool,x:[var T],y:[var T]):[var T] {if b x else y}; ignore choose_var(true,[var (1:Nat)],[var (1:Nat)]); ignore choose_var(true,[var (1:Int)],[var (1:Int)]); -ignore choose_var(true,[var (1:Nat)],[var (1:Int)]); // rejected as overconstrained (variance not applicable +ignore choose_var(true,[var (1:Nat)],[var (1:Int)]); // rejected as overconstrained (variance not applicable) From 4deb3edfdbec40cdbc1f4daaa53215ab70a9b8fb Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Mon, 2 Mar 2020 16:09:03 +0000 Subject: [PATCH 1082/1176] re-introduce rel eq args for efficient treatment of invariant constructor in a single pass --- src/mo_types/type.ml | 141 ++++++++++++++++++++++++++----------------- 1 file changed, 85 insertions(+), 56 deletions(-) diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index e28eac9ce95..918f4d055c3 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -1511,25 +1511,22 @@ let bimatch_typ scope_opt tbs t1 t2 = let t2 = open_ ts t2 in let cs = List.map (fun t -> match t with Con(c,_) -> c | _ -> assert false) ts in - let rel = ref SS.empty - in - let flexible c = List.exists (Con.eq c) cs in let mentions typ ce = not (ConSet.is_empty (ConSet.inter (cons typ ConSet.empty) ce)) in - let rec bimatch_list p inst any xs1 xs2 = + let rec bimatch_list p rel eq inst any xs1 xs2 = (match (xs1, xs2) with | (x1::xs1, x2::xs2) -> - (match p inst any x1 x2 with - | Some inst -> bimatch_list p inst any xs1 xs2 + (match p rel eq inst any x1 x2 with + | Some inst -> bimatch_list p rel eq inst any xs1 xs2 | None -> None) | [], [] -> Some inst | _, _ -> None) in - let rec bimatch_typ ((l,u) as inst) (any:ConSet.t) (t1:typ) (t2:typ) = + let rec bimatch_typ rel eq ((l,u) as inst) (any:ConSet.t) (t1:typ) (t2:typ) = if t1 == t2 || SS.mem (t1, t2) !rel then Some inst else begin @@ -1538,122 +1535,154 @@ let bimatch_typ scope_opt tbs t1 t2 = match t1, t2 with | Pre, _ | _, Pre -> Some inst - | _, Any -> + | Any, Any -> + Some inst + | _, Any when rel != eq -> Some inst - | Non, _ -> + | Non, Non -> + Some inst + | Non, _ when rel != eq -> Some inst | _, Con (con2, ts2) when flexible con2 -> assert (ts2 = []); if mentions t1 any || is_mut (normalize t1) then None else - (match ConEnv.find_opt con2 l with + let l = + match ConEnv.find_opt con2 l with + | Some t1' -> + let lub = lub t1 t1' in + ConEnv.add con2 lub l + | None -> ConEnv.add con2 t1 l + in + let u = if rel != eq then u else + match ConEnv.find_opt con2 u with | Some t1' -> - let lub = lub t1 t1' in - Some (ConEnv.add con2 lub l, u) - | None -> Some (ConEnv.add con2 t1 l, u)) + let glb = glb t1 t1' in + ConEnv.add con2 glb u + | None -> ConEnv.add con2 t1 u + in + Some (l,u) | Con (con1, ts1), _ when flexible con1 -> assert (ts1 = []); if mentions t2 any || is_mut (normalize t2) then None else - (match ConEnv.find_opt con1 u with - | Some t2' -> - let glb = glb t2 t2' in - Some (l, ConEnv.add con1 glb u) - | None -> Some (l, ConEnv.add con1 t2 u)) - | Con (con1, ts1), Con (con2, ts2) -> + let l = if rel != eq then l else + match ConEnv.find_opt con1 l with + | Some t2' -> + let lub = lub t2 t2' in + ConEnv.add con1 lub l + | None -> ConEnv.add con1 t2 l + in + let u = + match ConEnv.find_opt con1 u with + | Some t2' -> + let glb = glb t2 t2' in + ConEnv.add con1 glb u + | None -> ConEnv.add con1 t2 u + in + Some (l,u) + | Con (con1, ts1), Con (con2, ts2) -> (match Con.kind con1, Con.kind con2 with | Def (tbs, t), _ -> (* TBR this may fail to terminate *) - bimatch_typ inst any (open_ ts1 t) t2 + bimatch_typ rel eq inst any (open_ ts1 t) t2 | _, Def (tbs, t) -> (* TBR this may fail to terminate *) - bimatch_typ inst any t1 (open_ ts2 t) + bimatch_typ rel eq inst any t1 (open_ ts2 t) | _ when Con.eq con1 con2 -> assert (ts1 = []); assert (ts2 = []); Some inst - | Abs (tbs, t), _ -> - bimatch_typ inst any (open_ ts1 t) t2 + | Abs (tbs, t), _ when rel != eq -> + bimatch_typ rel eq inst any (open_ ts1 t) t2 + | _ -> None ) | Con (con1, ts1), t2 -> (match Con.kind con1, t2 with | Def (tbs, t), _ -> (* TBR this may fail to terminate *) - bimatch_typ inst any (open_ ts1 t) t2 - | Abs (tbs, t), _ -> - bimatch_typ inst any (open_ ts1 t) t2 + bimatch_typ rel eq inst any (open_ ts1 t) t2 + | Abs (tbs, t), _ when rel != eq -> + bimatch_typ rel eq inst any (open_ ts1 t) t2 + | _ -> None ) | t1, Con (con2, ts2) -> (match Con.kind con2 with | Def (tbs, t) -> (* TBR this may fail to terminate *) - bimatch_typ inst any t1 (open_ ts2 t) + bimatch_typ rel eq inst any t1 (open_ ts2 t) | _ -> None ) | Prim p1, Prim p2 when p1 = p2 -> Some inst - | Prim p1, Prim p2 -> + | Prim p1, Prim p2 when rel != eq -> if p1 = Nat && p2 = Int then Some inst else None | Obj (s1, tfs1), Obj (s2, tfs2) -> if s1 = s2 then - bimatch_fields inst any tfs1 tfs2 + bimatch_fields rel eq inst any tfs1 tfs2 else None | Array t1', Array t2' -> - bimatch_typ inst any t1' t2' + bimatch_typ rel eq inst any t1' t2' | Opt t1', Opt t2' -> - bimatch_typ inst any t1' t2' - | Prim Null, Opt t2' -> + bimatch_typ rel eq inst any t1' t2' + | Prim Null, Opt t2' when rel != eq -> Some inst | Variant fs1, Variant fs2 -> - bimatch_tags inst any fs1 fs2 + bimatch_tags rel eq inst any fs1 fs2 | Tup ts1, Tup ts2 -> - bimatch_list bimatch_typ inst any ts1 ts2 + bimatch_list bimatch_typ rel eq inst any ts1 ts2 | Func (s1, c1, tbs1, t11, t12), Func (s2, c2, tbs2, t21, t22) -> if s1 = s2 && c1 = c2 then - (match bimatch_binds inst any tbs1 tbs2 with + (match bimatch_binds rel eq inst any tbs1 tbs2 with | Some (inst, ts) -> let any' = List.fold_right (function Con(c,[]) -> ConSet.add c | _ -> assert false) ts any in (match - bimatch_list bimatch_typ inst any' (List.map (open_ ts) t21) (List.map (open_ ts) t11) + bimatch_list bimatch_typ rel eq inst any' (List.map (open_ ts) t21) (List.map (open_ ts) t11) with | Some inst -> - bimatch_list bimatch_typ inst any' (List.map (open_ ts) t12) (List.map (open_ ts) t22) + bimatch_list bimatch_typ rel eq inst any' (List.map (open_ ts) t12) (List.map (open_ ts) t22) | None -> None) | None -> None ) else None | Async (t11, t12), Async (t21, t22) -> (* TBR *) - bimatch_list bimatch_typ inst any [t11;t21;t12] [t21;t11;t22] + (match biequate_typ rel eq inst any t11 t12 with + | Some inst -> + bimatch_typ rel eq inst any t12 t22 + | None -> None) | Mut t1', Mut t2' -> (* TBR *) - bimatch_list bimatch_typ inst any [t1';t2'] [t2';t1'] + biequate_typ rel eq inst any t1' t2' | Typ c1, Typ c2 -> (* TBR *) - if eq t1 t2 then Some inst else None + if eq_con eq c1 c2 then Some inst else None | _, _ -> None end - and bimatch_fields inst any tfs1 tfs2 = + and biequate_typ rel eq inst any t1 t2 = + bimatch_typ eq eq inst any t1 t2 + + and bimatch_fields rel eq inst any tfs1 tfs2 = (* Assume that tfs1 and tfs2 are sorted. *) match tfs1, tfs2 with | [], [] -> Some inst - | _, [] -> + | _, [] when rel != eq -> Some inst | tf1::tfs1', tf2::tfs2' -> (match compare_field tf1 tf2 with | 0 -> - (match bimatch_typ inst any tf1.typ tf2.typ with - | Some inst -> bimatch_fields inst any tfs1' tfs2' + (match bimatch_typ rel eq inst any tf1.typ tf2.typ with + | Some inst -> bimatch_fields rel eq inst any tfs1' tfs2' | None -> None) - | -1 -> - bimatch_fields inst any tfs1' tfs2 + | -1 when rel != eq -> + bimatch_fields rel eq inst any tfs1' tfs2 | _ -> None ) | _, _ -> None - and bimatch_tags inst any tfs1 tfs2 = + and bimatch_tags rel eq inst any tfs1 tfs2 = (* Assume that tfs1 and tfs2 are sorted. *) match tfs1, tfs2 with | [], [] -> @@ -1663,23 +1692,23 @@ let bimatch_typ scope_opt tbs t1 t2 = | tf1::tfs1', tf2::tfs2' -> (match compare_field tf1 tf2 with | 0 -> - (match bimatch_typ inst any tf1.typ tf2.typ with - | Some inst -> bimatch_tags inst any tfs1' tfs2' + (match bimatch_typ rel eq inst any tf1.typ tf2.typ with + | Some inst -> bimatch_tags rel eq inst any tfs1' tfs2' | None -> None) - | +1 -> - bimatch_tags inst any tfs1 tfs2' + | +1 when rel != eq-> + bimatch_tags rel eq inst any tfs1 tfs2' | _ -> None ) | _, _ -> None - and bimatch_binds inst any tbs1 tbs2 = + and bimatch_binds rel eq inst any tbs1 tbs2 = let ts = open_binds tbs2 in - match bimatch_list (bimatch_bind ts) inst any tbs2 tbs1 with + match bimatch_list (bimatch_bind ts) rel eq inst any tbs2 tbs1 with | Some inst -> Some (inst,ts) | None -> None - and bimatch_bind ts inst any tb1 tb2 = - bimatch_typ inst any (open_ ts tb1.bound) (open_ ts tb2.bound) + and bimatch_bind ts rel eq inst any tb1 tb2 = + bimatch_typ rel eq inst any (open_ ts tb1.bound) (open_ ts tb2.bound) and fail_under_constrained lb c ub = let lb = string_of_typ lb in @@ -1717,7 +1746,7 @@ let bimatch_typ scope_opt tbs t1 t2 = ConEnv.empty, u in - match bimatch_typ (l, u) ConSet.empty t1 t2 with + match bimatch_typ (ref SS.empty) (ref SS.empty) (l, u) ConSet.empty t1 t2 with | Some (l,u) -> Some (List.map (fun c -> From c03af44d68650420ff84ca1fda96c8ff308cf4fb Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Mon, 2 Mar 2020 16:10:28 +0000 Subject: [PATCH 1083/1176] remove straw man match implementation --- src/mo_types/type.ml | 143 ------------------------------------------ src/mo_types/type.mli | 1 - 2 files changed, 144 deletions(-) diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index 918f4d055c3..80db3faed9d 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -1357,149 +1357,6 @@ module type Pretty = sig val string_of_typ_expand : typ -> string end -(* Matching *) - -let match_typ cs t1 t2 = - -let flexible c = List.exists (Con.eq c) cs -in - -let rigid c = not (flexible c) -in - -let rec match_list p inst xs1 xs2 = - (match (xs1, xs2) with - | (x1::xs1, x2::xs2) -> - (match p inst x1 x2 with - | Some inst -> match_list p inst xs1 xs2 - | None -> None) - | [], [] -> Some inst - | _, _ -> None) -in - -let rec match_typ inst t1 t2 = - (* Printf.printf "%s , %s\n" (string_of_typ t1) (string_of_typ t2); *) - match t1, t2 with - | Pre, _ | _, Pre -> - assert false - | Any, Any -> - Some inst - | Non, Non -> - Some inst - | Con (con1, ts1), Con (con2, ts2) when rigid con2-> - (match Con.kind con1, Con.kind con2 with - | k1, k2 when eq_kind k1 k2 -> - match_list match_typ inst ts1 ts2 - | Def (tbs, t), _ -> (* TBR this may fail to terminate *) - None (* match_typ inst (open_ ts1 t) t2 *) - | _, Def (tbs, t) -> (* TBR this may fail to terminate *) - None (* match_typ inst t1 (open_ ts2 t) *) - | _ -> - None - ) - | t1, Con (con2, ts2) -> - (match Con.kind con2 with - | Def (tbs, t) -> (* TBR this may fail to terminate *) - match_typ inst t1 (open_ ts2 t) - | Abs(tbs,_) -> - if flexible con2 then - match ConEnv.find_opt con2 inst with - | Some t1' -> if eq t1 t1' then Some inst else None (* just check equality instead ? *) - | None -> Some (ConEnv.add con2 t1 inst) - else None - ) - | Con (con1, ts1), t2 -> - (match Con.kind con1, t2 with - | Def (tbs, t), _ -> (* TBR this may fail to terminate *) - match_typ inst (open_ ts1 t) t2 - | _ -> None - ) - | Prim p1, Prim p2 when p1 = p2 -> - Some inst - | Obj (s1, tfs1), Obj (s2, tfs2) -> - if s1 = s2 then - match_fields inst tfs1 tfs2 - else None - | Array t1', Array t2' -> - match_typ inst t1' t2' - | Opt t1', Opt t2' -> - match_typ inst t1' t2' - | Variant fs1, Variant fs2 -> - match_tags inst fs1 fs2 - | Tup ts1, Tup ts2 -> - match_list match_typ inst ts1 ts2 - | Func (s1, c1, tbs1, t11, t12), Func (s2, c2, tbs2, t21, t22) -> - if s1 = s2 && c1 = c2 then - (match match_binds inst tbs1 tbs2 with - | Some (inst, ts) -> - (match match_list match_typ inst (List.map (open_ ts) t11) (List.map (open_ ts) t21) with - | Some inst -> - match_list match_typ inst (List.map (open_ ts) t12) (List.map (open_ ts) t22) - | None -> None) - | None -> None - ) - else None - | Async (t11, t12), Async (t21, t22) -> - (match match_typ inst t11 t21 with - | Some inst -> match_typ inst t12 t22 - | None -> None) - | Mut t1', Mut t2' -> - match_typ inst t1' t2' - | Typ c1, Typ c2 -> - if eq t1 t2 then Some inst else None - | _, _ -> None - -and match_fields inst tfs1 tfs2 = - (* Assume that tfs1 and tfs2 are sorted. *) - match tfs1, tfs2 with - | [], [] -> - Some inst - | tf1::tfs1', tf2::tfs2' -> - (match compare_field tf1 tf2 with - | 0 -> - (match match_typ inst tf1.typ tf2.typ with - | Some inst -> - match_fields inst tfs1' tfs2' - | None -> None) - | _ -> None - ) - | _, _ -> None -and match_tags inst tfs1 tfs2 = - (* Assume that tfs1 and tfs2 are sorted. *) - match tfs1, tfs2 with - | [], [] -> - Some inst - | tf1::tfs1', tf2::tfs2' -> - (match compare_field tf1 tf2 with - | 0 -> - (match match_typ inst tf1.typ tf2.typ with - | Some inst -> - match_fields inst tfs1' tfs2' - | None -> None) - | _ -> None - ) - | _, _ -> None - -and match_binds inst tbs1 tbs2 = - let ts = open_binds tbs2 in - match match_list (match_bind ts) inst tbs2 tbs1 with - | Some inst -> Some (inst, ts) - | None -> None - -and match_bind ts inst tb1 tb2 = - match_typ inst (open_ ts tb1.bound) (open_ ts tb2.bound) - -in - match match_typ ConEnv.empty t1 t2 with - | Some inst -> - (* default undetermined to Non *) - Some (List.map - (fun c -> - match ConEnv.find_opt c inst with - | None -> Non - | Some t -> t) cs) - | None -> None - include MakePretty(struct let show_stamps = true end) diff --git a/src/mo_types/type.mli b/src/mo_types/type.mli index 7fff4e53b08..451c0f2e3fd 100644 --- a/src/mo_types/type.mli +++ b/src/mo_types/type.mli @@ -233,5 +233,4 @@ module MakePretty(Cfg : sig val show_stamps : bool end) : Pretty include Pretty -val match_typ : con list -> typ -> typ -> typ list option val bimatch_typ : typ option -> bind list -> typ -> typ -> typ list option From 76ad47d0a8a0f6cc3096ba55b6bfea47f040a594 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Mon, 2 Mar 2020 16:13:21 +0000 Subject: [PATCH 1084/1176] rename bimatch to bi_match etc --- src/mo_frontend/typing.ml | 2 +- src/mo_types/type.ml | 72 +++++++++++++++++++-------------------- src/mo_types/type.mli | 2 +- 3 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 53df228c9be..1ac94523b6f 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -896,7 +896,7 @@ and infer_exp'' env exp : T.typ = check_inst_bounds env tbs typs exp.at, check_exp | _::_, [] -> (* implicit or empty instantiation, infer *) (* TODO: distinguish explicit empty instantation <> from omitted instantiation *) let t2 = infer_exp env exp2 in - match T.bimatch_typ (scope_of_env env) tbs t2 t_arg with + match T.bi_match_typ (scope_of_env env) tbs t2 t_arg with | Some ts -> check_typ_bounds env tbs ts (List.map (fun _ -> exp1.at) ts) exp.at; ts, diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index 80db3faed9d..20d51ae7a0e 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -1362,7 +1362,7 @@ include MakePretty(struct let show_stamps = true end) (* Bi-Matching *) -let bimatch_typ scope_opt tbs t1 t2 = +let bi_match_typ scope_opt tbs t1 t2 = let ts = open_binds tbs in let t2 = open_ ts t2 in @@ -1373,17 +1373,17 @@ let bimatch_typ scope_opt tbs t1 t2 = let mentions typ ce = not (ConSet.is_empty (ConSet.inter (cons typ ConSet.empty) ce)) in - let rec bimatch_list p rel eq inst any xs1 xs2 = + let rec bi_match_list p rel eq inst any xs1 xs2 = (match (xs1, xs2) with | (x1::xs1, x2::xs2) -> (match p rel eq inst any x1 x2 with - | Some inst -> bimatch_list p rel eq inst any xs1 xs2 + | Some inst -> bi_match_list p rel eq inst any xs1 xs2 | None -> None) | [], [] -> Some inst | _, _ -> None) in - let rec bimatch_typ rel eq ((l,u) as inst) (any:ConSet.t) (t1:typ) (t2:typ) = + let rec bi_match_typ rel eq ((l,u) as inst) (any:ConSet.t) (t1:typ) (t2:typ) = if t1 == t2 || SS.mem (t1, t2) !rel then Some inst else begin @@ -1443,29 +1443,29 @@ let bimatch_typ scope_opt tbs t1 t2 = | Con (con1, ts1), Con (con2, ts2) -> (match Con.kind con1, Con.kind con2 with | Def (tbs, t), _ -> (* TBR this may fail to terminate *) - bimatch_typ rel eq inst any (open_ ts1 t) t2 + bi_match_typ rel eq inst any (open_ ts1 t) t2 | _, Def (tbs, t) -> (* TBR this may fail to terminate *) - bimatch_typ rel eq inst any t1 (open_ ts2 t) + bi_match_typ rel eq inst any t1 (open_ ts2 t) | _ when Con.eq con1 con2 -> assert (ts1 = []); assert (ts2 = []); Some inst | Abs (tbs, t), _ when rel != eq -> - bimatch_typ rel eq inst any (open_ ts1 t) t2 + bi_match_typ rel eq inst any (open_ ts1 t) t2 | _ -> None ) | Con (con1, ts1), t2 -> (match Con.kind con1, t2 with | Def (tbs, t), _ -> (* TBR this may fail to terminate *) - bimatch_typ rel eq inst any (open_ ts1 t) t2 + bi_match_typ rel eq inst any (open_ ts1 t) t2 | Abs (tbs, t), _ when rel != eq -> - bimatch_typ rel eq inst any (open_ ts1 t) t2 + bi_match_typ rel eq inst any (open_ ts1 t) t2 | _ -> None ) | t1, Con (con2, ts2) -> (match Con.kind con2 with | Def (tbs, t) -> (* TBR this may fail to terminate *) - bimatch_typ rel eq inst any t1 (open_ ts2 t) + bi_match_typ rel eq inst any t1 (open_ ts2 t) | _ -> None ) | Prim p1, Prim p2 when p1 = p2 -> @@ -1474,53 +1474,53 @@ let bimatch_typ scope_opt tbs t1 t2 = if p1 = Nat && p2 = Int then Some inst else None | Obj (s1, tfs1), Obj (s2, tfs2) -> if s1 = s2 then - bimatch_fields rel eq inst any tfs1 tfs2 + bi_match_fields rel eq inst any tfs1 tfs2 else None | Array t1', Array t2' -> - bimatch_typ rel eq inst any t1' t2' + bi_match_typ rel eq inst any t1' t2' | Opt t1', Opt t2' -> - bimatch_typ rel eq inst any t1' t2' + bi_match_typ rel eq inst any t1' t2' | Prim Null, Opt t2' when rel != eq -> Some inst | Variant fs1, Variant fs2 -> - bimatch_tags rel eq inst any fs1 fs2 + bi_match_tags rel eq inst any fs1 fs2 | Tup ts1, Tup ts2 -> - bimatch_list bimatch_typ rel eq inst any ts1 ts2 + bi_match_list bi_match_typ rel eq inst any ts1 ts2 | Func (s1, c1, tbs1, t11, t12), Func (s2, c2, tbs2, t21, t22) -> if s1 = s2 && c1 = c2 then - (match bimatch_binds rel eq inst any tbs1 tbs2 with + (match bi_match_binds rel eq inst any tbs1 tbs2 with | Some (inst, ts) -> let any' = List.fold_right (function Con(c,[]) -> ConSet.add c | _ -> assert false) ts any in (match - bimatch_list bimatch_typ rel eq inst any' (List.map (open_ ts) t21) (List.map (open_ ts) t11) + bi_match_list bi_match_typ rel eq inst any' (List.map (open_ ts) t21) (List.map (open_ ts) t11) with | Some inst -> - bimatch_list bimatch_typ rel eq inst any' (List.map (open_ ts) t12) (List.map (open_ ts) t22) + bi_match_list bi_match_typ rel eq inst any' (List.map (open_ ts) t12) (List.map (open_ ts) t22) | None -> None) | None -> None ) else None | Async (t11, t12), Async (t21, t22) -> (* TBR *) - (match biequate_typ rel eq inst any t11 t12 with + (match bi_equate_typ rel eq inst any t11 t12 with | Some inst -> - bimatch_typ rel eq inst any t12 t22 + bi_match_typ rel eq inst any t12 t22 | None -> None) | Mut t1', Mut t2' -> (* TBR *) - biequate_typ rel eq inst any t1' t2' + bi_equate_typ rel eq inst any t1' t2' | Typ c1, Typ c2 -> (* TBR *) if eq_con eq c1 c2 then Some inst else None | _, _ -> None end - and biequate_typ rel eq inst any t1 t2 = - bimatch_typ eq eq inst any t1 t2 + and bi_equate_typ rel eq inst any t1 t2 = + bi_match_typ eq eq inst any t1 t2 - and bimatch_fields rel eq inst any tfs1 tfs2 = + and bi_match_fields rel eq inst any tfs1 tfs2 = (* Assume that tfs1 and tfs2 are sorted. *) match tfs1, tfs2 with | [], [] -> @@ -1530,16 +1530,16 @@ let bimatch_typ scope_opt tbs t1 t2 = | tf1::tfs1', tf2::tfs2' -> (match compare_field tf1 tf2 with | 0 -> - (match bimatch_typ rel eq inst any tf1.typ tf2.typ with - | Some inst -> bimatch_fields rel eq inst any tfs1' tfs2' + (match bi_match_typ rel eq inst any tf1.typ tf2.typ with + | Some inst -> bi_match_fields rel eq inst any tfs1' tfs2' | None -> None) | -1 when rel != eq -> - bimatch_fields rel eq inst any tfs1' tfs2 + bi_match_fields rel eq inst any tfs1' tfs2 | _ -> None ) | _, _ -> None - and bimatch_tags rel eq inst any tfs1 tfs2 = + and bi_match_tags rel eq inst any tfs1 tfs2 = (* Assume that tfs1 and tfs2 are sorted. *) match tfs1, tfs2 with | [], [] -> @@ -1549,23 +1549,23 @@ let bimatch_typ scope_opt tbs t1 t2 = | tf1::tfs1', tf2::tfs2' -> (match compare_field tf1 tf2 with | 0 -> - (match bimatch_typ rel eq inst any tf1.typ tf2.typ with - | Some inst -> bimatch_tags rel eq inst any tfs1' tfs2' + (match bi_match_typ rel eq inst any tf1.typ tf2.typ with + | Some inst -> bi_match_tags rel eq inst any tfs1' tfs2' | None -> None) | +1 when rel != eq-> - bimatch_tags rel eq inst any tfs1 tfs2' + bi_match_tags rel eq inst any tfs1 tfs2' | _ -> None ) | _, _ -> None - and bimatch_binds rel eq inst any tbs1 tbs2 = + and bi_match_binds rel eq inst any tbs1 tbs2 = let ts = open_binds tbs2 in - match bimatch_list (bimatch_bind ts) rel eq inst any tbs2 tbs1 with + match bi_match_list (bi_match_bind ts) rel eq inst any tbs2 tbs1 with | Some inst -> Some (inst,ts) | None -> None - and bimatch_bind ts rel eq inst any tb1 tb2 = - bimatch_typ rel eq inst any (open_ ts tb1.bound) (open_ ts tb2.bound) + and bi_match_bind ts rel eq inst any tb1 tb2 = + bi_match_typ rel eq inst any (open_ ts tb1.bound) (open_ ts tb2.bound) and fail_under_constrained lb c ub = let lb = string_of_typ lb in @@ -1603,7 +1603,7 @@ let bimatch_typ scope_opt tbs t1 t2 = ConEnv.empty, u in - match bimatch_typ (ref SS.empty) (ref SS.empty) (l, u) ConSet.empty t1 t2 with + match bi_match_typ (ref SS.empty) (ref SS.empty) (l, u) ConSet.empty t1 t2 with | Some (l,u) -> Some (List.map (fun c -> diff --git a/src/mo_types/type.mli b/src/mo_types/type.mli index 451c0f2e3fd..63993ea63bd 100644 --- a/src/mo_types/type.mli +++ b/src/mo_types/type.mli @@ -233,4 +233,4 @@ module MakePretty(Cfg : sig val show_stamps : bool end) : Pretty include Pretty -val bimatch_typ : typ option -> bind list -> typ -> typ -> typ list option +val bi_match_typ : typ option -> bind list -> typ -> typ -> typ list option From 05decafc476e1057913424564d91275d1ee7cd91 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Mon, 2 Mar 2020 17:04:42 +0000 Subject: [PATCH 1085/1176] move Type.bi_match to mo_frontent/bi_match.ml --- src/mo_frontend/bi_match.ml | 269 ++++++++++++++++++++++++++++++++ src/mo_frontend/bi_match.mli | 4 + src/mo_frontend/typing.ml | 2 +- src/mo_types/type.ml | 286 ++--------------------------------- src/mo_types/type.mli | 9 +- 5 files changed, 291 insertions(+), 279 deletions(-) create mode 100644 src/mo_frontend/bi_match.ml create mode 100644 src/mo_frontend/bi_match.mli diff --git a/src/mo_frontend/bi_match.ml b/src/mo_frontend/bi_match.ml new file mode 100644 index 00000000000..d72cc3692b1 --- /dev/null +++ b/src/mo_frontend/bi_match.ml @@ -0,0 +1,269 @@ +open Mo_types +open Type + +(* Bi-Matching *) + +module SS = Set.Make (struct type t = typ * typ let compare = compare end) + +let bi_match_typ scope_opt tbs t1 t2 = + + let ts = open_binds tbs in + let t2 = open_ ts t2 in + let cs = List.map (fun t -> match t with Con(c,_) -> c | _ -> assert false) ts in + + let flexible c = List.exists (Con.eq c) cs + in + + let mentions typ ce = not (ConSet.is_empty (ConSet.inter (cons typ) ce)) in + + let rec bi_match_list p rel eq inst any xs1 xs2 = + (match (xs1, xs2) with + | (x1::xs1, x2::xs2) -> + (match p rel eq inst any x1 x2 with + | Some inst -> bi_match_list p rel eq inst any xs1 xs2 + | None -> None) + | [], [] -> Some inst + | _, _ -> None) + in + + let rec bi_match_typ rel eq ((l,u) as inst) (any:ConSet.t) (t1:typ) (t2:typ) = + if t1 == t2 || SS.mem (t1, t2) !rel + then Some inst + else begin + rel := SS.add (t1, t2) !rel; + (* Printf.printf "%s %s\n" (!str t1) (!str t2); *) + match t1, t2 with + | Pre, _ | _, Pre -> + Some inst + | Any, Any -> + Some inst + | _, Any when rel != eq -> + Some inst + | Non, Non -> + Some inst + | Non, _ when rel != eq -> + Some inst + | _, Con (con2, ts2) when flexible con2 -> + assert (ts2 = []); + if mentions t1 any || is_mut (normalize t1) then + None + else + let l = + match ConEnv.find_opt con2 l with + | Some t1' -> + let lub = lub t1 t1' in + ConEnv.add con2 lub l + | None -> ConEnv.add con2 t1 l + in + let u = if rel != eq then u else + match ConEnv.find_opt con2 u with + | Some t1' -> + let glb = glb t1 t1' in + ConEnv.add con2 glb u + | None -> ConEnv.add con2 t1 u + in + Some (l,u) + | Con (con1, ts1), _ when flexible con1 -> + assert (ts1 = []); + if mentions t2 any || is_mut (normalize t2) then + None + else + let l = if rel != eq then l else + match ConEnv.find_opt con1 l with + | Some t2' -> + let lub = lub t2 t2' in + ConEnv.add con1 lub l + | None -> ConEnv.add con1 t2 l + in + let u = + match ConEnv.find_opt con1 u with + | Some t2' -> + let glb = glb t2 t2' in + ConEnv.add con1 glb u + | None -> ConEnv.add con1 t2 u + in + Some (l,u) + | Con (con1, ts1), Con (con2, ts2) -> + (match Con.kind con1, Con.kind con2 with + | Def (tbs, t), _ -> (* TBR this may fail to terminate *) + bi_match_typ rel eq inst any (open_ ts1 t) t2 + | _, Def (tbs, t) -> (* TBR this may fail to terminate *) + bi_match_typ rel eq inst any t1 (open_ ts2 t) + | _ when Con.eq con1 con2 -> + assert (ts1 = []); + assert (ts2 = []); + Some inst + | Abs (tbs, t), _ when rel != eq -> + bi_match_typ rel eq inst any (open_ ts1 t) t2 + | _ -> None + ) + | Con (con1, ts1), t2 -> + (match Con.kind con1, t2 with + | Def (tbs, t), _ -> (* TBR this may fail to terminate *) + bi_match_typ rel eq inst any (open_ ts1 t) t2 + | Abs (tbs, t), _ when rel != eq -> + bi_match_typ rel eq inst any (open_ ts1 t) t2 + | _ -> None + ) + | t1, Con (con2, ts2) -> + (match Con.kind con2 with + | Def (tbs, t) -> (* TBR this may fail to terminate *) + bi_match_typ rel eq inst any t1 (open_ ts2 t) + | _ -> None + ) + | Prim p1, Prim p2 when p1 = p2 -> + Some inst + | Prim p1, Prim p2 when rel != eq -> + if p1 = Nat && p2 = Int then Some inst else None + | Obj (s1, tfs1), Obj (s2, tfs2) -> + if s1 = s2 then + bi_match_fields rel eq inst any tfs1 tfs2 + else None + | Array t1', Array t2' -> + bi_match_typ rel eq inst any t1' t2' + | Opt t1', Opt t2' -> + bi_match_typ rel eq inst any t1' t2' + | Prim Null, Opt t2' when rel != eq -> + Some inst + | Variant fs1, Variant fs2 -> + bi_match_tags rel eq inst any fs1 fs2 + | Tup ts1, Tup ts2 -> + bi_match_list bi_match_typ rel eq inst any ts1 ts2 + | Func (s1, c1, tbs1, t11, t12), Func (s2, c2, tbs2, t21, t22) -> + if s1 = s2 && c1 = c2 then + (match bi_match_binds rel eq inst any tbs1 tbs2 with + | Some (inst, ts) -> + let any' = List.fold_right + (function Con(c,[]) -> ConSet.add c | _ -> assert false) ts any + in + (match + bi_match_list bi_match_typ rel eq inst any' (List.map (open_ ts) t21) (List.map (open_ ts) t11) + with + | Some inst -> + bi_match_list bi_match_typ rel eq inst any' (List.map (open_ ts) t12) (List.map (open_ ts) t22) + | None -> None) + | None -> None + ) + else None + | Async (t11, t12), Async (t21, t22) -> + (* TBR *) + (match bi_equate_typ rel eq inst any t11 t12 with + | Some inst -> + bi_match_typ rel eq inst any t12 t22 + | None -> None) + | Mut t1', Mut t2' -> + (* TBR *) + bi_equate_typ rel eq inst any t1' t2' + | Typ c1, Typ c2 -> + (* TBR *) + if Type.eq t1 t2 then Some inst else None + | _, _ -> None + end + + and bi_equate_typ rel eq inst any t1 t2 = + bi_match_typ eq eq inst any t1 t2 + + and bi_match_fields rel eq inst any tfs1 tfs2 = + (* Assume that tfs1 and tfs2 are sorted. *) + match tfs1, tfs2 with + | [], [] -> + Some inst + | _, [] when rel != eq -> + Some inst + | tf1::tfs1', tf2::tfs2' -> + (match compare_field tf1 tf2 with + | 0 -> + (match bi_match_typ rel eq inst any tf1.typ tf2.typ with + | Some inst -> bi_match_fields rel eq inst any tfs1' tfs2' + | None -> None) + | -1 when rel != eq -> + bi_match_fields rel eq inst any tfs1' tfs2 + | _ -> None + ) + | _, _ -> None + + and bi_match_tags rel eq inst any tfs1 tfs2 = + (* Assume that tfs1 and tfs2 are sorted. *) + match tfs1, tfs2 with + | [], [] -> + Some inst + | [], _ -> + Some inst + | tf1::tfs1', tf2::tfs2' -> + (match compare_field tf1 tf2 with + | 0 -> + (match bi_match_typ rel eq inst any tf1.typ tf2.typ with + | Some inst -> bi_match_tags rel eq inst any tfs1' tfs2' + | None -> None) + | +1 when rel != eq-> + bi_match_tags rel eq inst any tfs1 tfs2' + | _ -> None + ) + | _, _ -> None + + and bi_match_binds rel eq inst any tbs1 tbs2 = + let ts = open_binds tbs2 in + match bi_match_list (bi_match_bind ts) rel eq inst any tbs2 tbs1 with + | Some inst -> Some (inst,ts) + | None -> None + + and bi_match_bind ts rel eq inst any tb1 tb2 = + bi_match_typ rel eq inst any (open_ ts tb1.bound) (open_ ts tb2.bound) + + and fail_under_constrained lb c ub = + let lb = string_of_typ lb in + let c = Con.name c in + let ub = string_of_typ ub in + failwith (Printf.sprintf + "under-constrained implicit instantiation %s <: %s <: %s,\n with %s =/= %s; explicit type instantiation required" + lb c ub lb ub) + + and fail_over_constrained lb c ub = + let lb = string_of_typ lb in + let c = Con.name c in + let ub = string_of_typ ub in + failwith (Printf.sprintf + "over-constrained implicit instantiation requires %s <: %s <: %s,\n but %s open_ ts tb.bound) tbs in + let ce = ConSet.of_list cs in + List.iter2 (fun c bd -> if mentions bd ce then fail_open_bound c bd) cs bds; + let add c b u = if eq b Any then u else ConEnv.add c b u in + let u = List.fold_right2 add cs bds ConEnv.empty in + let l,u = match scope_opt, tbs with + | Some c, {sort=Scope;_}::tbs -> + ConEnv.singleton (List.hd cs) c, + add (List.hd cs) (lub c (List.hd bds)) u + | None, {sort=Scope;_}::tbs -> failwith "scope instantiation required but no scope available" + | _, _ -> + ConEnv.empty, + u + in + match bi_match_typ (ref SS.empty) (ref SS.empty) (l, u) ConSet.empty t1 t2 with + | Some (l,u) -> + Some (List.map + (fun c -> + match ConEnv.find_opt c l, ConEnv.find_opt c u with + | None, None -> Non + | None, Some ub -> ub + | Some lb, None -> lb + | Some lb, Some ub -> + if eq lb ub then + ub + else if sub lb ub then + fail_under_constrained lb c ub + else + fail_over_constrained lb c ub) + cs) + | None -> None + + + + diff --git a/src/mo_frontend/bi_match.mli b/src/mo_frontend/bi_match.mli new file mode 100644 index 00000000000..f3dbd7d4cd9 --- /dev/null +++ b/src/mo_frontend/bi_match.mli @@ -0,0 +1,4 @@ +open Mo_types +open Type + +val bi_match_typ : scope option -> bind list -> typ -> typ -> typ list option diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 1ac94523b6f..7792f8f4085 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -896,7 +896,7 @@ and infer_exp'' env exp : T.typ = check_inst_bounds env tbs typs exp.at, check_exp | _::_, [] -> (* implicit or empty instantiation, infer *) (* TODO: distinguish explicit empty instantation <> from omitted instantiation *) let t2 = infer_exp env exp2 in - match T.bi_match_typ (scope_of_env env) tbs t2 t_arg with + match Bi_match.bi_match_typ (scope_of_env env) tbs t2 t_arg with | Some ts -> check_typ_bounds env tbs ts (List.map (fun _ -> exp1.at) ts) exp.at; ts, diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index 20d51ae7a0e..ba9929aa251 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -520,37 +520,38 @@ let avoid cons t = (* Collecting type constructors *) -let rec cons t cs = +let rec cons' t cs = match t with | Var _ -> cs | (Prim _ | Any | Non | Pre ) -> cs | Con (c, ts) -> - List.fold_right cons ts (ConSet.add c cs) + List.fold_right cons' ts (ConSet.add c cs) | (Opt t | Mut t | Array t) -> - cons t cs + cons' t cs | Async (t1, t2) -> - cons t2 (cons t1 cs) - | Tup ts -> List.fold_right cons ts cs + cons' t2 (cons' t1 cs) + | Tup ts -> List.fold_right cons' ts cs | Func (s, c, tbs, ts1, ts2) -> let cs = List.fold_right cons_bind tbs cs in - let cs = List.fold_right cons ts1 cs in - List.fold_right cons ts2 cs + let cs = List.fold_right cons' ts1 cs in + List.fold_right cons' ts2 cs | (Obj (_, fs) | Variant fs) -> List.fold_right cons_field fs cs | Typ c -> ConSet.add c cs and cons_bind tb cs = - cons tb.bound cs + cons' tb.bound cs and cons_field {lab; typ} cs = - cons typ cs + cons' typ cs let cons_kind k = match k with | Def (tbs, t) | Abs (tbs, t) -> - cons t (List.fold_right cons_bind tbs ConSet.empty) + cons' t (List.fold_right cons_bind tbs ConSet.empty) +let cons t = cons' t ConSet.empty (* Checking for concrete types *) @@ -1359,268 +1360,3 @@ end include MakePretty(struct let show_stamps = true end) - -(* Bi-Matching *) - -let bi_match_typ scope_opt tbs t1 t2 = - - let ts = open_binds tbs in - let t2 = open_ ts t2 in - let cs = List.map (fun t -> match t with Con(c,_) -> c | _ -> assert false) ts in - - let flexible c = List.exists (Con.eq c) cs - in - - let mentions typ ce = not (ConSet.is_empty (ConSet.inter (cons typ ConSet.empty) ce)) in - - let rec bi_match_list p rel eq inst any xs1 xs2 = - (match (xs1, xs2) with - | (x1::xs1, x2::xs2) -> - (match p rel eq inst any x1 x2 with - | Some inst -> bi_match_list p rel eq inst any xs1 xs2 - | None -> None) - | [], [] -> Some inst - | _, _ -> None) - in - - let rec bi_match_typ rel eq ((l,u) as inst) (any:ConSet.t) (t1:typ) (t2:typ) = - if t1 == t2 || SS.mem (t1, t2) !rel - then Some inst - else begin - rel := SS.add (t1, t2) !rel; - (* Printf.printf "%s %s\n" (!str t1) (!str t2); *) - match t1, t2 with - | Pre, _ | _, Pre -> - Some inst - | Any, Any -> - Some inst - | _, Any when rel != eq -> - Some inst - | Non, Non -> - Some inst - | Non, _ when rel != eq -> - Some inst - | _, Con (con2, ts2) when flexible con2 -> - assert (ts2 = []); - if mentions t1 any || is_mut (normalize t1) then - None - else - let l = - match ConEnv.find_opt con2 l with - | Some t1' -> - let lub = lub t1 t1' in - ConEnv.add con2 lub l - | None -> ConEnv.add con2 t1 l - in - let u = if rel != eq then u else - match ConEnv.find_opt con2 u with - | Some t1' -> - let glb = glb t1 t1' in - ConEnv.add con2 glb u - | None -> ConEnv.add con2 t1 u - in - Some (l,u) - | Con (con1, ts1), _ when flexible con1 -> - assert (ts1 = []); - if mentions t2 any || is_mut (normalize t2) then - None - else - let l = if rel != eq then l else - match ConEnv.find_opt con1 l with - | Some t2' -> - let lub = lub t2 t2' in - ConEnv.add con1 lub l - | None -> ConEnv.add con1 t2 l - in - let u = - match ConEnv.find_opt con1 u with - | Some t2' -> - let glb = glb t2 t2' in - ConEnv.add con1 glb u - | None -> ConEnv.add con1 t2 u - in - Some (l,u) - | Con (con1, ts1), Con (con2, ts2) -> - (match Con.kind con1, Con.kind con2 with - | Def (tbs, t), _ -> (* TBR this may fail to terminate *) - bi_match_typ rel eq inst any (open_ ts1 t) t2 - | _, Def (tbs, t) -> (* TBR this may fail to terminate *) - bi_match_typ rel eq inst any t1 (open_ ts2 t) - | _ when Con.eq con1 con2 -> - assert (ts1 = []); - assert (ts2 = []); - Some inst - | Abs (tbs, t), _ when rel != eq -> - bi_match_typ rel eq inst any (open_ ts1 t) t2 - | _ -> None - ) - | Con (con1, ts1), t2 -> - (match Con.kind con1, t2 with - | Def (tbs, t), _ -> (* TBR this may fail to terminate *) - bi_match_typ rel eq inst any (open_ ts1 t) t2 - | Abs (tbs, t), _ when rel != eq -> - bi_match_typ rel eq inst any (open_ ts1 t) t2 - | _ -> None - ) - | t1, Con (con2, ts2) -> - (match Con.kind con2 with - | Def (tbs, t) -> (* TBR this may fail to terminate *) - bi_match_typ rel eq inst any t1 (open_ ts2 t) - | _ -> None - ) - | Prim p1, Prim p2 when p1 = p2 -> - Some inst - | Prim p1, Prim p2 when rel != eq -> - if p1 = Nat && p2 = Int then Some inst else None - | Obj (s1, tfs1), Obj (s2, tfs2) -> - if s1 = s2 then - bi_match_fields rel eq inst any tfs1 tfs2 - else None - | Array t1', Array t2' -> - bi_match_typ rel eq inst any t1' t2' - | Opt t1', Opt t2' -> - bi_match_typ rel eq inst any t1' t2' - | Prim Null, Opt t2' when rel != eq -> - Some inst - | Variant fs1, Variant fs2 -> - bi_match_tags rel eq inst any fs1 fs2 - | Tup ts1, Tup ts2 -> - bi_match_list bi_match_typ rel eq inst any ts1 ts2 - | Func (s1, c1, tbs1, t11, t12), Func (s2, c2, tbs2, t21, t22) -> - if s1 = s2 && c1 = c2 then - (match bi_match_binds rel eq inst any tbs1 tbs2 with - | Some (inst, ts) -> - let any' = List.fold_right - (function Con(c,[]) -> ConSet.add c | _ -> assert false) ts any - in - (match - bi_match_list bi_match_typ rel eq inst any' (List.map (open_ ts) t21) (List.map (open_ ts) t11) - with - | Some inst -> - bi_match_list bi_match_typ rel eq inst any' (List.map (open_ ts) t12) (List.map (open_ ts) t22) - | None -> None) - | None -> None - ) - else None - | Async (t11, t12), Async (t21, t22) -> - (* TBR *) - (match bi_equate_typ rel eq inst any t11 t12 with - | Some inst -> - bi_match_typ rel eq inst any t12 t22 - | None -> None) - | Mut t1', Mut t2' -> - (* TBR *) - bi_equate_typ rel eq inst any t1' t2' - | Typ c1, Typ c2 -> - (* TBR *) - if eq_con eq c1 c2 then Some inst else None - | _, _ -> None - end - - and bi_equate_typ rel eq inst any t1 t2 = - bi_match_typ eq eq inst any t1 t2 - - and bi_match_fields rel eq inst any tfs1 tfs2 = - (* Assume that tfs1 and tfs2 are sorted. *) - match tfs1, tfs2 with - | [], [] -> - Some inst - | _, [] when rel != eq -> - Some inst - | tf1::tfs1', tf2::tfs2' -> - (match compare_field tf1 tf2 with - | 0 -> - (match bi_match_typ rel eq inst any tf1.typ tf2.typ with - | Some inst -> bi_match_fields rel eq inst any tfs1' tfs2' - | None -> None) - | -1 when rel != eq -> - bi_match_fields rel eq inst any tfs1' tfs2 - | _ -> None - ) - | _, _ -> None - - and bi_match_tags rel eq inst any tfs1 tfs2 = - (* Assume that tfs1 and tfs2 are sorted. *) - match tfs1, tfs2 with - | [], [] -> - Some inst - | [], _ -> - Some inst - | tf1::tfs1', tf2::tfs2' -> - (match compare_field tf1 tf2 with - | 0 -> - (match bi_match_typ rel eq inst any tf1.typ tf2.typ with - | Some inst -> bi_match_tags rel eq inst any tfs1' tfs2' - | None -> None) - | +1 when rel != eq-> - bi_match_tags rel eq inst any tfs1 tfs2' - | _ -> None - ) - | _, _ -> None - - and bi_match_binds rel eq inst any tbs1 tbs2 = - let ts = open_binds tbs2 in - match bi_match_list (bi_match_bind ts) rel eq inst any tbs2 tbs1 with - | Some inst -> Some (inst,ts) - | None -> None - - and bi_match_bind ts rel eq inst any tb1 tb2 = - bi_match_typ rel eq inst any (open_ ts tb1.bound) (open_ ts tb2.bound) - - and fail_under_constrained lb c ub = - let lb = string_of_typ lb in - let c = Con.name c in - let ub = string_of_typ ub in - failwith (Printf.sprintf - "under-constrained implicit instantiation %s <: %s <: %s,\n with %s =/= %s; explicit type instantiation required" - lb c ub lb ub) - - and fail_over_constrained lb c ub = - let lb = string_of_typ lb in - let c = Con.name c in - let ub = string_of_typ ub in - failwith (Printf.sprintf - "over-constrained implicit instantiation requires %s <: %s <: %s,\n but %s open_ ts tb.bound) tbs in - let ce = ConSet.of_list cs in - List.iter2 (fun c bd -> if mentions bd ce then fail_open_bound c bd) cs bds; - let add c b u = if eq b Any then u else ConEnv.add c b u in - let u = List.fold_right2 add cs bds ConEnv.empty in - let l,u = match scope_opt, tbs with - | Some c, {sort=Scope;_}::tbs -> - ConEnv.singleton (List.hd cs) c, - add (List.hd cs) (lub c (List.hd bds)) u - | None, {sort=Scope;_}::tbs -> failwith "scope instantiation required but no scope available" - | _, _ -> - ConEnv.empty, - u - in - match bi_match_typ (ref SS.empty) (ref SS.empty) (l, u) ConSet.empty t1 t2 with - | Some (l,u) -> - Some (List.map - (fun c -> - match ConEnv.find_opt c l, ConEnv.find_opt c u with - | None, None -> Non - | None, Some ub -> ub - | Some lb, None -> lb - | Some lb, Some ub -> - if eq lb ub then - ub - else if sub lb ub then - fail_under_constrained lb c ub - else - fail_over_constrained lb c ub) - cs) - | None -> None - - - - diff --git a/src/mo_types/type.mli b/src/mo_types/type.mli index 63993ea63bd..25e207310ba 100644 --- a/src/mo_types/type.mli +++ b/src/mo_types/type.mli @@ -35,6 +35,7 @@ type prim = | Principal type t = typ + and typ = | Var of var * int (* variable *) | Con of con * typ list (* constructor *) @@ -45,13 +46,14 @@ and typ = | Opt of typ (* option *) | Tup of typ list (* tuple *) | Func of func_sort * control * bind list * typ list * typ list (* function *) - | Async of typ * typ (* future *) + | Async of scope * typ (* future *) | Mut of typ (* mutable type *) | Any (* top *) | Non (* bottom *) | Typ of con (* type (field of module) *) | Pre (* pre-type *) +and scope = typ and bind_sort = Scope | Type and bind = {var : var; sort: bind_sort; bound : typ} @@ -176,11 +178,13 @@ val inhabited : typ -> bool val span : typ -> int option -(* Cons occuring in kind *) +(* Constructor occurrences *) +val cons: typ -> ConSet.t val cons_kind : kind -> ConSet.t + (* Equivalence and Subtyping *) val eq : typ -> typ -> bool @@ -233,4 +237,3 @@ module MakePretty(Cfg : sig val show_stamps : bool end) : Pretty include Pretty -val bi_match_typ : typ option -> bind list -> typ -> typ -> typ list option From 94ed2e7bc71e31d9bb7d908b062bf8341b395a60 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Mon, 2 Mar 2020 21:37:52 +0000 Subject: [PATCH 1086/1176] remove option from bi_match return type; all errors by exceptions --- src/mo_frontend/bi_match.ml | 16 +++++++++++----- src/mo_frontend/bi_match.mli | 4 +++- src/mo_frontend/typing.ml | 5 +---- test/fail/ok/inference.tc.ok | 32 ++++++++++++++++++-------------- 4 files changed, 33 insertions(+), 24 deletions(-) diff --git a/src/mo_frontend/bi_match.ml b/src/mo_frontend/bi_match.ml index d72cc3692b1..37274b41302 100644 --- a/src/mo_frontend/bi_match.ml +++ b/src/mo_frontend/bi_match.ml @@ -1,10 +1,12 @@ open Mo_types open Type +open MakePretty(struct let show_stamps = false end) + (* Bi-Matching *) module SS = Set.Make (struct type t = typ * typ let compare = compare end) - + let bi_match_typ scope_opt tbs t1 t2 = let ts = open_binds tbs in @@ -229,7 +231,7 @@ let bi_match_typ scope_opt tbs t1 t2 = and fail_open_bound c bd = let c = Con.name c in let bd = string_of_typ bd in - failwith (Printf.sprintf "type parameter %s has an open bound %s mentioning another type parameter\n; explicit type instantiation required" c bd) + failwith (Printf.sprintf "type parameter %s has an open bound %s mentioning another type parameter:\n explicit type instantiation required" c bd) in let bds = List.map (fun tb -> open_ ts tb.bound) tbs in @@ -248,7 +250,7 @@ let bi_match_typ scope_opt tbs t1 t2 = in match bi_match_typ (ref SS.empty) (ref SS.empty) (l, u) ConSet.empty t1 t2 with | Some (l,u) -> - Some (List.map + List.map (fun c -> match ConEnv.find_opt c l, ConEnv.find_opt c u with | None, None -> Non @@ -261,8 +263,12 @@ let bi_match_typ scope_opt tbs t1 t2 = fail_under_constrained lb c ub else fail_over_constrained lb c ub) - cs) - | None -> None + cs + | None -> failwith (Printf.sprintf + "no instantiation of %s makes %s a subtype of %s" + (String.concat "," (List.map string_of_con cs)) + (string_of_typ t1) (string_of_typ t2)) + diff --git a/src/mo_frontend/bi_match.mli b/src/mo_frontend/bi_match.mli index f3dbd7d4cd9..ae1349f5031 100644 --- a/src/mo_frontend/bi_match.mli +++ b/src/mo_frontend/bi_match.mli @@ -1,4 +1,6 @@ open Mo_types open Type -val bi_match_typ : scope option -> bind list -> typ -> typ -> typ list option +val bi_match_typ : + scope option -> bind list -> typ -> typ -> + typ list (* raises Failure *) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 7792f8f4085..4756f5d3026 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -897,15 +897,12 @@ and infer_exp'' env exp : T.typ = | _::_, [] -> (* implicit or empty instantiation, infer *) (* TODO: distinguish explicit empty instantation <> from omitted instantiation *) let t2 = infer_exp env exp2 in match Bi_match.bi_match_typ (scope_of_env env) tbs t2 t_arg with - | Some ts -> + | ts -> check_typ_bounds env tbs ts (List.map (fun _ -> exp1.at) ts) exp.at; ts, fun env t_arg exp -> if not (T.sub t2 t_arg) then error env exp.at "cannot infer type arguments due to subtyping\n %s is not a subtype of %s" (T.string_of_typ_expand t2) (T.string_of_typ_expand t_arg) - | None -> - error env exp.at "function of type %s cannot be instantiated to consume argument of type %s" (T.string_of_typ t1) - (T.string_of_typ t2) | exception (Failure msg) -> error env exp.at "cannot instantiate function of type %s to argument of type %s:\n %s" (T.string_of_typ t1) diff --git a/test/fail/ok/inference.tc.ok b/test/fail/ok/inference.tc.ok index 2fac57c1a37..90a80da2556 100644 --- a/test/fail/ok/inference.tc.ok +++ b/test/fail/ok/inference.tc.ok @@ -14,14 +14,14 @@ inference.mo:67.8-67.43: type error, cannot instantiate function of type (T - over-constrained implicit instantiation requires Any <: T <: None, but Any (T, T) -> (U, U) to argument of type (Nat, Nat): - type parameter T has an open bound U/11 mentioning another type parameter -; explicit type instantiation required + type parameter T has an open bound U mentioning another type parameter: + explicit type instantiation required inference.mo:95.8-95.23: type error, cannot instantiate function of type (T, T) -> (U, U) to argument of type (Nat, Int): - type parameter T has an open bound U/12 mentioning another type parameter -; explicit type instantiation required + type parameter T has an open bound U mentioning another type parameter: + explicit type instantiation required inference.mo:96.8-96.22: type error, cannot instantiate function of type (T, T) -> (U, U) to argument of type (Nat, Bool): - type parameter T has an open bound U/13 mentioning another type parameter -; explicit type instantiation required + type parameter T has an open bound U mentioning another type parameter: + explicit type instantiation required inference.mo:107.8-107.14: type error, cannot instantiate function of type T -> T to argument of type Nat: under-constrained implicit instantiation Nat <: T <: Int, with Nat =/= Int; explicit type instantiation required @@ -36,24 +36,28 @@ cannot produce expected type inference.mo:111.1-111.10: type error, cannot instantiate function of type T -> T to argument of type Bool: over-constrained implicit instantiation requires Bool <: T <: Int, but Bool (T -> U) -> () cannot be instantiated to consume argument of type V -> V -inference.mo:118.1-118.31: type error, function of type (U -> T) -> () cannot be instantiated to consume argument of type V -> V +inference.mo:116.1-116.27: type error, cannot instantiate function of type (T -> U) -> () to argument of type V -> V: + no instantiation of T makes V -> V a subtype of T -> U +inference.mo:118.1-118.31: type error, cannot instantiate function of type (U -> T) -> () to argument of type V -> V: + no instantiation of T makes V -> V a subtype of U -> T inference.mo:125.1-125.9: type error, expression of type Nat cannot produce expected type () -inference.mo:126.1-126.13: type error, function of type [T] -> T cannot be instantiated to consume argument of type [var Nat] -inference.mo:129.1-129.13: type error, function of type [var T] -> T cannot be instantiated to consume argument of type [Nat] +inference.mo:126.1-126.13: type error, cannot instantiate function of type [T] -> T to argument of type [var Nat]: + no instantiation of T makes [var Nat] a subtype of [T] +inference.mo:129.1-129.13: type error, cannot instantiate function of type [var T] -> T to argument of type [Nat]: + no instantiation of T makes [Nat] a subtype of [var T] inference.mo:130.1-130.17: type error, expression of type Nat cannot produce expected type () inference.mo:135.4-135.8: type error, cannot instantiate function of type U -> () to argument of type T/34: - over-constrained implicit instantiation requires T/34 <: U <: {}, - but T/34 U -> () to argument of type T/35: - under-constrained implicit instantiation T/35 <: U <: {}, - with T/35 =/= {}; explicit type instantiation required + under-constrained implicit instantiation T <: U <: {}, + with T =/= {}; explicit type instantiation required inference.mo:150.11-150.15: type error, expression of type T/37 cannot produce expected type From 6c21c138c9f4322976f1e16754b6ef108f4758a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikola=20Kne=C5=BEevi=C4=87?= Date: Tue, 3 Mar 2020 09:28:09 +0100 Subject: [PATCH 1087/1176] .github: niv-updater-action v3 -> v4 (#1255) As this version brings in support for labels, use it. --- .github/workflows/niv-updater.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/niv-updater.yml b/.github/workflows/niv-updater.yml index 5801e1ac243..60ea6da8fe6 100644 --- a/.github/workflows/niv-updater.yml +++ b/.github/workflows/niv-updater.yml @@ -19,9 +19,11 @@ jobs: runs-on: ubuntu-latest steps: - name: niv-updater-action - uses: knl/niv-updater-action@v3 + uses: knl/niv-updater-action@v4 with: # might be too noisy blacklist: 'nixpkgs,dfinity' + labels: | + automerge-squash env: GITHUB_TOKEN: ${{ secrets.NIV_UPDATER_TOKEN }} From e67ee9797b02b563bfd2306533f1d5bcbe8b9043 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 3 Mar 2020 11:09:07 +0000 Subject: [PATCH 1088/1176] exploit expectation in type argument inference --- src/mo_frontend/bi_match.ml | 18 ++++++++---- src/mo_frontend/bi_match.mli | 2 +- src/mo_frontend/typing.ml | 56 ++++++++++++++++++++++++++++++++++-- 3 files changed, 67 insertions(+), 9 deletions(-) diff --git a/src/mo_frontend/bi_match.ml b/src/mo_frontend/bi_match.ml index 37274b41302..29425c278a7 100644 --- a/src/mo_frontend/bi_match.ml +++ b/src/mo_frontend/bi_match.ml @@ -7,10 +7,12 @@ open MakePretty(struct let show_stamps = false end) module SS = Set.Make (struct type t = typ * typ let compare = compare end) -let bi_match_typ scope_opt tbs t1 t2 = +let bi_match_typ scope_opt tbs ts1 ts2 = let ts = open_binds tbs in - let t2 = open_ ts t2 in + let ts1 = List.map (open_ ts) ts1 in + let ts2 = List.map (open_ ts) ts2 in + let cs = List.map (fun t -> match t with Con(c,_) -> c | _ -> assert false) ts in let flexible c = List.exists (Con.eq c) cs @@ -248,7 +250,8 @@ let bi_match_typ scope_opt tbs t1 t2 = ConEnv.empty, u in - match bi_match_typ (ref SS.empty) (ref SS.empty) (l, u) ConSet.empty t1 t2 with + match bi_match_list + bi_match_typ (ref SS.empty) (ref SS.empty) (l, u) ConSet.empty ts1 ts2 with | Some (l,u) -> List.map (fun c -> @@ -265,9 +268,12 @@ let bi_match_typ scope_opt tbs t1 t2 = fail_over_constrained lb c ub) cs | None -> failwith (Printf.sprintf - "no instantiation of %s makes %s a subtype of %s" - (String.concat "," (List.map string_of_con cs)) - (string_of_typ t1) (string_of_typ t2)) + "no instantiation of %s makes %s" + (String.concat " , " (List.map string_of_con cs)) + (String.concat " and " + (List.map2 (fun t1 t2 -> + Printf.sprintf "%s <: %s" (string_of_typ t1) (string_of_typ t2)) + ts1 ts2))) diff --git a/src/mo_frontend/bi_match.mli b/src/mo_frontend/bi_match.mli index ae1349f5031..8c67d12ed28 100644 --- a/src/mo_frontend/bi_match.mli +++ b/src/mo_frontend/bi_match.mli @@ -2,5 +2,5 @@ open Mo_types open Type val bi_match_typ : - scope option -> bind list -> typ -> typ -> + scope option -> bind list -> typ list -> typ list -> typ list (* raises Failure *) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 4756f5d3026..38fa6ff94b2 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -894,9 +894,9 @@ and infer_exp'' env exp : T.typ = | [{T.sort = T.Scope;_}], _ (* special case to allow t_arg driven overload resolution *) | _, _::_ -> (* explicit instantiation, check *) check_inst_bounds env tbs typs exp.at, check_exp - | _::_, [] -> (* implicit or empty instantiation, infer *) (* TODO: distinguish explicit empty instantation <> from omitted instantiation *) + | _::_, [] -> (* implicit or empty instantiation, infer *) (* TODO: distinguish explicit empty instantiation `<>` from omitted instantiation `` *) let t2 = infer_exp env exp2 in - match Bi_match.bi_match_typ (scope_of_env env) tbs t2 t_arg with + match Bi_match.bi_match_typ (scope_of_env env) tbs [t2] [t_arg] with | ts -> check_typ_bounds env tbs ts (List.map (fun _ -> exp1.at) ts) exp.at; ts, @@ -1229,6 +1229,58 @@ and check_exp' env0 t exp : T.typ = in check_exp (adjoin_vals env' ve2) t2 exp; t + | CallE (exp1, inst, exp2), _ -> + let typs = inst.it in + let t1 = infer_exp_promote env exp1 in + let sort, tbs, t_arg, t_ret = + try T.as_func_sub T.Local (List.length typs) t1 + with Invalid_argument _ -> + error env exp1.at + "expected function type, but expression produces type\n %s" + (T.string_of_typ_expand t1) + in + let ts, check_arg = + match tbs, inst.it with + | [], [] -> (* no inference required *) + [], check_exp + | [{T.sort = T.Scope;_}], _ (* special case to allow t_arg driven overload resolution *) + | _, _::_ -> (* explicit instantiation, check *) + check_inst_bounds env tbs typs exp.at, check_exp + | _::_, [] -> (* implicit or empty instantiation, infer *) (* TODO: distinguish explicit empty instantiation `<>` from omitted instantiation `` *) + let t2 = infer_exp env exp2 in + match Bi_match.bi_match_typ (scope_of_env env) tbs + [t2; t_ret] + [t_arg; t] + with + | ts -> + check_typ_bounds env tbs ts (List.map (fun _ -> exp1.at) ts) exp.at; + ts, + fun env t_arg exp -> + if not (T.sub t2 t_arg) then + error env exp.at "cannot infer type arguments due to subtyping\n %s is not a subtype of %s" (T.string_of_typ_expand t2) (T.string_of_typ_expand t_arg) + | exception (Failure msg) -> + error env exp.at "cannot instantiate function of type %s to argument of type %s:\n %s" + (T.string_of_typ t1) + (T.string_of_typ t2) + msg + in + inst.note <- ts; + let t_arg = T.open_ ts t_arg in + let t_ret = T.open_ ts t_ret in + if not env.pre then begin + check_arg env t_arg exp2; + if Type.is_shared_sort sort then begin + if not (T.concrete t_arg) then + error env exp1.at + "shared function argument contains abstract type\n %s" + (T.string_of_typ_expand t_arg); + if not (T.concrete t_ret) then + error env exp2.at + "shared function call result contains abstract type\n %s" + (T.string_of_typ_expand t_ret); + end + end; + t | _ -> let t' = infer_exp env0 exp in if not (T.sub t' t) then From 4d9e2c19fd2fb864a33210d4cacfd0d6b3a0ed6d Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 3 Mar 2020 15:27:20 +0000 Subject: [PATCH 1089/1176] reject T.Typ instantiations --- src/mo_frontend/bi_match.ml | 8 ++++++-- test/fail/inference.mo | 5 +++++ test/fail/ok/inference.tc.ok | 2 ++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/mo_frontend/bi_match.ml b/src/mo_frontend/bi_match.ml index 37274b41302..b067092384e 100644 --- a/src/mo_frontend/bi_match.ml +++ b/src/mo_frontend/bi_match.ml @@ -7,6 +7,10 @@ open MakePretty(struct let show_stamps = false end) module SS = Set.Make (struct type t = typ * typ let compare = compare end) +let denotable t = + let t' = normalize t in + not (is_mut t' || is_typ t') + let bi_match_typ scope_opt tbs t1 t2 = let ts = open_binds tbs in @@ -47,7 +51,7 @@ let bi_match_typ scope_opt tbs t1 t2 = Some inst | _, Con (con2, ts2) when flexible con2 -> assert (ts2 = []); - if mentions t1 any || is_mut (normalize t1) then + if mentions t1 any || not (denotable t1) then None else let l = @@ -67,7 +71,7 @@ let bi_match_typ scope_opt tbs t1 t2 = Some (l,u) | Con (con1, ts1), _ when flexible con1 -> assert (ts1 = []); - if mentions t2 any || is_mut (normalize t2) then + if mentions t2 any || not (denotable t2) then None else let l = if rel != eq then l else diff --git a/test/fail/inference.mo b/test/fail/inference.mo index d6184ff2f6c..27458b06e0d 100644 --- a/test/fail/inference.mo +++ b/test/fail/inference.mo @@ -163,3 +163,8 @@ func choose_var(b:Bool,x:[var T],y:[var T]):[var T] {if b x else y}; ignore choose_var(true,[var (1:Nat)],[var (1:Nat)]); ignore choose_var(true,[var (1:Int)],[var (1:Int)]); ignore choose_var(true,[var (1:Nat)],[var (1:Int)]); // rejected as overconstrained (variance not applicable) + +// reject type components as (non denotable) instantiations +func select(o:object {x:T}):T{ o.x }; +ignore select(object {public let x=1}); +ignore select(object {public type x = Nat}); // reject diff --git a/test/fail/ok/inference.tc.ok b/test/fail/ok/inference.tc.ok index 90a80da2556..94ee380545d 100644 --- a/test/fail/ok/inference.tc.ok +++ b/test/fail/ok/inference.tc.ok @@ -65,3 +65,5 @@ cannot produce expected type inference.mo:165.8-165.52: type error, cannot instantiate function of type (Bool, [var T], [var T]) -> [var T] to argument of type (Bool, [var Nat], [var Int]): over-constrained implicit instantiation requires Int <: T <: Nat, but Int {x : T} -> T to argument of type {type x = Nat}: + no instantiation of T makes {type x = Nat} a subtype of {x : T} From 1e5e55116cfbc9296003785af49c3893112e76cc Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 3 Mar 2020 23:01:46 +0000 Subject: [PATCH 1090/1176] improved error messages & formatting, update test inference.mo and visually inspect errors --- src/mo_frontend/bi_match.ml | 10 +- src/mo_frontend/typing.ml | 16 ++- test/fail/inference.mo | 31 +++--- test/fail/ok/inference.tc.ok | 183 ++++++++++++++++++++++++----------- 4 files changed, 163 insertions(+), 77 deletions(-) diff --git a/src/mo_frontend/bi_match.ml b/src/mo_frontend/bi_match.ml index b1fa1b76d7e..e2da0156378 100644 --- a/src/mo_frontend/bi_match.ml +++ b/src/mo_frontend/bi_match.ml @@ -91,7 +91,7 @@ let bi_match_typ scope_opt tbs ts1 ts2 = | None -> ConEnv.add con1 t2 u in Some (l,u) - | Con (con1, ts1), Con (con2, ts2) -> + | Con (con1, ts1), Con (con2, ts2) -> (match Con.kind con1, Con.kind con2 with | Def (tbs, t), _ -> (* TBR this may fail to terminate *) bi_match_typ rel eq inst any (open_ ts1 t) t2 @@ -223,7 +223,7 @@ let bi_match_typ scope_opt tbs ts1 ts2 = let c = Con.name c in let ub = string_of_typ ub in failwith (Printf.sprintf - "under-constrained implicit instantiation %s <: %s <: %s,\n with %s =/= %s; explicit type instantiation required" + "under-constrained implicit instantiation %s <: %s <: %s, with %s =/= %s;\nexplicit type instantiation required" lb c ub lb ub) and fail_over_constrained lb c ub = @@ -231,13 +231,13 @@ let bi_match_typ scope_opt tbs ts1 ts2 = let c = Con.name c in let ub = string_of_typ ub in failwith (Printf.sprintf - "over-constrained implicit instantiation requires %s <: %s <: %s,\n but %s open_ ts tb.bound) tbs in @@ -273,7 +273,7 @@ let bi_match_typ scope_opt tbs ts1 ts2 = cs | None -> failwith (Printf.sprintf "no instantiation of %s makes %s" - (String.concat " , " (List.map string_of_con cs)) + (String.concat ", " (List.map string_of_con cs)) (String.concat " and " (List.map2 (fun t1 t2 -> Printf.sprintf "%s <: %s" (string_of_typ t1) (string_of_typ t2)) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 38fa6ff94b2..ba8b92aa51d 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -903,8 +903,9 @@ and infer_exp'' env exp : T.typ = fun env t_arg exp -> if not (T.sub t2 t_arg) then error env exp.at "cannot infer type arguments due to subtyping\n %s is not a subtype of %s" (T.string_of_typ_expand t2) (T.string_of_typ_expand t_arg) - | exception (Failure msg) -> - error env exp.at "cannot instantiate function of type %s to argument of type %s:\n %s" + | exception Failure msg -> + error env exp.at + "cannot implicitly instantiate function of type\n %s\nto argument of type\n %s\n" (T.string_of_typ t1) (T.string_of_typ t2) msg @@ -1258,10 +1259,12 @@ and check_exp' env0 t exp : T.typ = fun env t_arg exp -> if not (T.sub t2 t_arg) then error env exp.at "cannot infer type arguments due to subtyping\n %s is not a subtype of %s" (T.string_of_typ_expand t2) (T.string_of_typ_expand t_arg) - | exception (Failure msg) -> - error env exp.at "cannot instantiate function of type %s to argument of type %s:\n %s" + | exception Failure msg -> + error env exp.at + "cannot implicitly instantiate function of type\n %s\nto argument of type\n %s\nto produce result of type\n %s\n%s" (T.string_of_typ t1) (T.string_of_typ t2) + (T.string_of_typ t) msg in inst.note <- ts; @@ -1280,6 +1283,11 @@ and check_exp' env0 t exp : T.typ = (T.string_of_typ_expand t_ret); end end; + if not (T.sub t_ret t) then + local_error env0 exp.at + "expression of type\n %s\ncannot produce expected type\n %s" + (T.string_of_typ_expand t_ret) + (T.string_of_typ_expand t); t | _ -> let t' = infer_exp env0 exp in diff --git a/test/fail/inference.mo b/test/fail/inference.mo index 27458b06e0d..27ee39b857e 100644 --- a/test/fail/inference.mo +++ b/test/fail/inference.mo @@ -63,8 +63,8 @@ tricky(func f(x:None):Any { f(x);}); // correctly rejected ignore func () { tricky(func f(x:Any):None{f(x)}) }; // implicit instantiation -ignore tricky(func f(x:Any):None { f(x);}); -ignore tricky(func f(x:None):Any { f(x);}); // fails, inconsitent instantiation required. +ignore tricky(func f(x:Any):None { f(x);}); // fails, under-constrained +ignore tricky(func f(x:None):Any { f(x);}); // fails, inconsistent instantiation required. ignore tricky(func f(x:None):None { f(x);}); func amb(f : T -> T): T->T { f }; @@ -104,12 +104,12 @@ func f(g:shared Nat8 -> ()) : async () { func bnd(x:T):T{x}; ignore bnd(1:Int) : Int; -ignore bnd(1) : Nat; // fails, under-constrained -ignore (if false (bnd(loop {}):Nat) else 1); // fails, underspecialized, requires expected ret typ info +ignore bnd(1) : Nat; // ok, uses expected type +ignore (if false (bnd(loop {}):Nat) else 1); // ok, given expected type ignore (if false (bnd(loop {}):Int) else 1); -ignore (if false (bnd(loop {}):None) else 1); // fails, underspecialized, requires expected ret typ info -bnd(true); - +ignore (if false (bnd(loop {}):None) else 1); // ok, given expected type +ignore bnd(true); // reject, overconstrained +bnd(true); // reject, overconstrained // reject scope violations func scopeco(f:T->U){}; @@ -120,14 +120,16 @@ scopecontra(func(x:V):V{x}); // reject due to scope violation //TODO: invariant mutables, constructor constraints, bail on open bounds -// reject instantiations at `var _` +// reject instantiations at `var _` (not denotable) func sub(x:[T]):T{x[0]}; -sub([1]); -sub([var 1]); // reject +ignore sub([1]); +sub([]); +ignore sub([var 1]); // reject func sub_mut(x:[var T]):T{x[0]}; sub_mut([1]); // reject -sub_mut([var 1]); +ignore sub_mut([var 1]); // ok +sub_mut([var 1]); // reject // tricky examples involving open typing with bounded parameters func g(x:T) { @@ -147,7 +149,12 @@ func i(x:T) { func j(x:T) { func f(y:U):U{y}; - ignore f(x) : None; // fail (requires inference w.r.t expected type) + ignore f(x) : None; // fail (overconstrained) +}; + +func k(x:T) { + func f(y:U):U{y}; + ignore f(x) : T; }; // immutable arrays diff --git a/test/fail/ok/inference.tc.ok b/test/fail/ok/inference.tc.ok index 94ee380545d..69e83483273 100644 --- a/test/fail/ok/inference.tc.ok +++ b/test/fail/ok/inference.tc.ok @@ -7,63 +7,134 @@ inference.mo:62.13-62.40: type error, expression of type None -> Any cannot produce expected type Any -> Any -inference.mo:66.8-66.43: type error, cannot instantiate function of type (T -> T) -> () to argument of type Any -> None: - under-constrained implicit instantiation None <: T <: Any, - with None =/= Any; explicit type instantiation required -inference.mo:67.8-67.43: type error, cannot instantiate function of type (T -> T) -> () to argument of type None -> Any: - over-constrained implicit instantiation requires Any <: T <: None, - but Any (T, T) -> (U, U) to argument of type (Nat, Nat): - type parameter T has an open bound U mentioning another type parameter: - explicit type instantiation required -inference.mo:95.8-95.23: type error, cannot instantiate function of type (T, T) -> (U, U) to argument of type (Nat, Int): - type parameter T has an open bound U mentioning another type parameter: - explicit type instantiation required -inference.mo:96.8-96.22: type error, cannot instantiate function of type (T, T) -> (U, U) to argument of type (Nat, Bool): - type parameter T has an open bound U mentioning another type parameter: - explicit type instantiation required -inference.mo:107.8-107.14: type error, cannot instantiate function of type T -> T to argument of type Nat: - under-constrained implicit instantiation Nat <: T <: Int, - with Nat =/= Int; explicit type instantiation required -inference.mo:108.19-108.31: type error, expression of type - Int -cannot produce expected type - Nat -inference.mo:110.19-110.31: type error, expression of type - Int -cannot produce expected type - None -inference.mo:111.1-111.10: type error, cannot instantiate function of type T -> T to argument of type Bool: - over-constrained implicit instantiation requires Bool <: T <: Int, - but Bool (T -> U) -> () to argument of type V -> V: - no instantiation of T makes V -> V a subtype of T -> U -inference.mo:118.1-118.31: type error, cannot instantiate function of type (U -> T) -> () to argument of type V -> V: - no instantiation of T makes V -> V a subtype of U -> T -inference.mo:125.1-125.9: type error, expression of type - Nat -cannot produce expected type +inference.mo:66.8-66.43: type error, cannot implicitly instantiate function of type + (T -> T) -> () +to argument of type + Any -> None +to produce result of type + Any +under-constrained implicit instantiation None <: T <: Any, with None =/= Any; +explicit type instantiation required +inference.mo:67.8-67.43: type error, cannot implicitly instantiate function of type + (T -> T) -> () +to argument of type + None -> Any +to produce result of type + Any +over-constrained implicit instantiation requires Any <: T <: None, but Any (T, T) -> (U, U) +to argument of type + (Nat, Nat) +to produce result of type + Any +type parameter T has an open bound U mentioning another type parameter; +explicit type instantiation required due to limitation of inference +inference.mo:95.8-95.23: type error, cannot implicitly instantiate function of type + (T, T) -> (U, U) +to argument of type + (Nat, Int) +to produce result of type + Any +type parameter T has an open bound U mentioning another type parameter; +explicit type instantiation required due to limitation of inference +inference.mo:96.8-96.22: type error, cannot implicitly instantiate function of type + (T, T) -> (U, U) +to argument of type + (Nat, Bool) +to produce result of type + Any +type parameter T has an open bound U mentioning another type parameter; +explicit type instantiation required due to limitation of inference +inference.mo:111.8-111.17: type error, cannot implicitly instantiate function of type + T -> T +to argument of type + Bool +to produce result of type + Any +over-constrained implicit instantiation requires Bool <: T <: Int, but Bool T -> T +to argument of type + Bool +to produce result of type () -inference.mo:126.1-126.13: type error, cannot instantiate function of type [T] -> T to argument of type [var Nat]: - no instantiation of T makes [var Nat] a subtype of [T] -inference.mo:129.1-129.13: type error, cannot instantiate function of type [var T] -> T to argument of type [Nat]: - no instantiation of T makes [Nat] a subtype of [var T] -inference.mo:130.1-130.17: type error, expression of type - Nat -cannot produce expected type +over-constrained implicit instantiation requires Bool <: T <: None, but Bool (T -> U) -> () +to argument of type + V -> V +to produce result of type () -inference.mo:135.4-135.8: type error, cannot instantiate function of type U -> () to argument of type T/34: - over-constrained implicit instantiation requires T <: U <: {}, - but T U -> () to argument of type T/35: - under-constrained implicit instantiation T <: U <: {}, - with T =/= {}; explicit type instantiation required -inference.mo:150.11-150.15: type error, expression of type +no instantiation of T makes V -> V <: T -> U and () <: () +inference.mo:118.1-118.31: type error, cannot implicitly instantiate function of type + (U -> T) -> () +to argument of type + V -> V +to produce result of type + () +no instantiation of T makes V -> V <: U -> T and () <: () +inference.mo:127.8-127.20: type error, cannot implicitly instantiate function of type + [T] -> T +to argument of type + [var Nat] +to produce result of type + Any +no instantiation of T makes [var Nat] <: [T] and T <: Any +inference.mo:130.1-130.13: type error, cannot implicitly instantiate function of type + [var T] -> T +to argument of type + [Nat] +to produce result of type + () +no instantiation of T makes [Nat] <: [var T] and T <: () +inference.mo:132.1-132.17: type error, cannot implicitly instantiate function of type + [var T] -> T +to argument of type + [var Nat] +to produce result of type + () +over-constrained implicit instantiation requires Nat <: T <: None, but Nat U -> () +to argument of type + T/34 +to produce result of type + () +over-constrained implicit instantiation requires T <: U <: {}, but T U -> () +to argument of type + T/35 +to produce result of type + () +under-constrained implicit instantiation T <: U <: {}, with T =/= {}; +explicit type instantiation required +inference.mo:152.11-152.15: type error, cannot implicitly instantiate function of type + U -> U +to argument of type T/37 -cannot produce expected type +to produce result of type None -inference.mo:165.8-165.52: type error, cannot instantiate function of type (Bool, [var T], [var T]) -> [var T] to argument of type (Bool, [var Nat], [var Int]): - over-constrained implicit instantiation requires Int <: T <: Nat, - but Int {x : T} -> T to argument of type {type x = Nat}: - no instantiation of T makes {type x = Nat} a subtype of {x : T} +over-constrained implicit instantiation requires T <: U <: None, but T (Bool, [var T], [var T]) -> [var T] +to argument of type + (Bool, [var Nat], [var Int]) +to produce result of type + Any +over-constrained implicit instantiation requires Int <: T <: Nat, but Int {x : T} -> T +to argument of type + {type x = Nat} +to produce result of type + Any +no instantiation of T makes {type x = Nat} <: {x : T} and T <: Any From 94ec9a3cf11cdb267f9cb39edb656bc7942e5588 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 4 Mar 2020 00:05:16 +0000 Subject: [PATCH 1091/1176] update comment --- src/mo_frontend/typing.ml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index ba8b92aa51d..85975b95e3d 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -1249,9 +1249,9 @@ and check_exp' env0 t exp : T.typ = check_inst_bounds env tbs typs exp.at, check_exp | _::_, [] -> (* implicit or empty instantiation, infer *) (* TODO: distinguish explicit empty instantiation `<>` from omitted instantiation `` *) let t2 = infer_exp env exp2 in - match Bi_match.bi_match_typ (scope_of_env env) tbs - [t2; t_ret] - [t_arg; t] + match + (* i.e. exists_unique ts . t2 <: open_ ts t_arg /\ open ts_ t_arg <: t1] *) + Bi_match.bi_match_typ (scope_of_env env) tbs [t2; t_ret] [t_arg; t] with | ts -> check_typ_bounds env tbs ts (List.map (fun _ -> exp1.at) ts) exp.at; From 2b4e9fe852a70a73f8f40810ebc846c75d0050ec Mon Sep 17 00:00:00 2001 From: Bas van Dijk Date: Wed, 4 Mar 2020 09:00:07 +0100 Subject: [PATCH 1092/1176] ci-pr.nix: use the src.mergeBase input instead of base (#1261) The `base` input will track the HEAD of the base branch while `src.mergeBase` will track the merge-base of your PR with its base branch. --- ci-pr.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ci-pr.nix b/ci-pr.nix index e5686e133d0..746ec60c025 100644 --- a/ci-pr.nix +++ b/ci-pr.nix @@ -1,4 +1,4 @@ -{ src ? { rev = null; }, base ? null }: +{ src ? { rev = null; } }: let nixpkgs = import ./nix { }; @@ -15,10 +15,10 @@ let }; in -import ./ci.nix { inherit src; } // nixpkgs.lib.optionalAttrs (base != null) { +import ./ci.nix { inherit src; } // nixpkgs.lib.optionalAttrs (src ? mergeBase) { perf-delta = let - baseJobs = import "${base}/default.nix" { system = "x86_64-linux"; }; + baseJobs = import (src.mergeBase + "/default.nix") { system = "x86_64-linux"; }; prJobs = import ./default.nix { system = "x86_64-linux"; }; in nixpkgs.runCommandNoCC "perf-delta" { From d7cc6f221efc38f0640c092295225fc42a95ee2f Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 4 Mar 2020 11:14:41 +0000 Subject: [PATCH 1093/1176] factor CallE inference into separate function, called twice --- src/mo_frontend/typing.ml | 164 ++++++++++++++------------------------ 1 file changed, 61 insertions(+), 103 deletions(-) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 85975b95e3d..747b7aa023d 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -878,55 +878,7 @@ and infer_exp'' env exp : T.typ = let ts1 = match pat.it with TupP _ -> T.seq_of_tup t1 | _ -> [t1] in T.Func (sort, c, T.close_binds cs tbs, List.map (T.close cs) ts1, List.map (T.close cs) ts2) | CallE (exp1, inst, exp2) -> - let typs = inst.it in - let t1 = infer_exp_promote env exp1 in - let sort, tbs, t_arg, t_ret = - try T.as_func_sub T.Local (List.length typs) t1 - with Invalid_argument _ -> - error env exp1.at - "expected function type, but expression produces type\n %s" - (T.string_of_typ_expand t1) - in - let ts, check_arg = - match tbs, inst.it with - | [], [] -> (* no inference required *) - [], check_exp - | [{T.sort = T.Scope;_}], _ (* special case to allow t_arg driven overload resolution *) - | _, _::_ -> (* explicit instantiation, check *) - check_inst_bounds env tbs typs exp.at, check_exp - | _::_, [] -> (* implicit or empty instantiation, infer *) (* TODO: distinguish explicit empty instantiation `<>` from omitted instantiation `` *) - let t2 = infer_exp env exp2 in - match Bi_match.bi_match_typ (scope_of_env env) tbs [t2] [t_arg] with - | ts -> - check_typ_bounds env tbs ts (List.map (fun _ -> exp1.at) ts) exp.at; - ts, - fun env t_arg exp -> - if not (T.sub t2 t_arg) then - error env exp.at "cannot infer type arguments due to subtyping\n %s is not a subtype of %s" (T.string_of_typ_expand t2) (T.string_of_typ_expand t_arg) - | exception Failure msg -> - error env exp.at - "cannot implicitly instantiate function of type\n %s\nto argument of type\n %s\n" - (T.string_of_typ t1) - (T.string_of_typ t2) - msg - in - inst.note <- ts; - let t_arg = T.open_ ts t_arg in - let t_ret = T.open_ ts t_ret in - if not env.pre then begin - check_arg env t_arg exp2; - if Type.is_shared_sort sort then begin - if not (T.concrete t_arg) then - error env exp1.at - "shared function argument contains abstract type\n %s" - (T.string_of_typ_expand t_arg); - if not (T.concrete t_ret) then - error env exp2.at - "shared function call result contains abstract type\n %s" - (T.string_of_typ_expand t_ret); - end - end; - t_ret + infer_call env exp1 inst exp2 exp.at None | BlockE decs -> let t, scope = infer_block env decs exp.at in (try T.avoid scope.Scope.con_env t with T.Unavoidable c -> @@ -1231,62 +1183,11 @@ and check_exp' env0 t exp : T.typ = check_exp (adjoin_vals env' ve2) t2 exp; t | CallE (exp1, inst, exp2), _ -> - let typs = inst.it in - let t1 = infer_exp_promote env exp1 in - let sort, tbs, t_arg, t_ret = - try T.as_func_sub T.Local (List.length typs) t1 - with Invalid_argument _ -> - error env exp1.at - "expected function type, but expression produces type\n %s" - (T.string_of_typ_expand t1) - in - let ts, check_arg = - match tbs, inst.it with - | [], [] -> (* no inference required *) - [], check_exp - | [{T.sort = T.Scope;_}], _ (* special case to allow t_arg driven overload resolution *) - | _, _::_ -> (* explicit instantiation, check *) - check_inst_bounds env tbs typs exp.at, check_exp - | _::_, [] -> (* implicit or empty instantiation, infer *) (* TODO: distinguish explicit empty instantiation `<>` from omitted instantiation `` *) - let t2 = infer_exp env exp2 in - match - (* i.e. exists_unique ts . t2 <: open_ ts t_arg /\ open ts_ t_arg <: t1] *) - Bi_match.bi_match_typ (scope_of_env env) tbs [t2; t_ret] [t_arg; t] - with - | ts -> - check_typ_bounds env tbs ts (List.map (fun _ -> exp1.at) ts) exp.at; - ts, - fun env t_arg exp -> - if not (T.sub t2 t_arg) then - error env exp.at "cannot infer type arguments due to subtyping\n %s is not a subtype of %s" (T.string_of_typ_expand t2) (T.string_of_typ_expand t_arg) - | exception Failure msg -> - error env exp.at - "cannot implicitly instantiate function of type\n %s\nto argument of type\n %s\nto produce result of type\n %s\n%s" - (T.string_of_typ t1) - (T.string_of_typ t2) - (T.string_of_typ t) - msg - in - inst.note <- ts; - let t_arg = T.open_ ts t_arg in - let t_ret = T.open_ ts t_ret in - if not env.pre then begin - check_arg env t_arg exp2; - if Type.is_shared_sort sort then begin - if not (T.concrete t_arg) then - error env exp1.at - "shared function argument contains abstract type\n %s" - (T.string_of_typ_expand t_arg); - if not (T.concrete t_ret) then - error env exp2.at - "shared function call result contains abstract type\n %s" - (T.string_of_typ_expand t_ret); - end - end; - if not (T.sub t_ret t) then + let t' = infer_call env exp1 inst exp2 exp.at (Some t) in + if not (T.sub t' t) then local_error env0 exp.at "expression of type\n %s\ncannot produce expected type\n %s" - (T.string_of_typ_expand t_ret) + (T.string_of_typ_expand t') (T.string_of_typ_expand t); t | _ -> @@ -1298,6 +1199,63 @@ and check_exp' env0 t exp : T.typ = (T.string_of_typ_expand t); t' +and infer_call env exp1 inst exp2 at t_opt = + let t = Lib.Option.get t_opt T.Any in + let typs = inst.it in + let t1 = infer_exp_promote env exp1 in + let sort, tbs, t_arg, t_ret = + try T.as_func_sub T.Local (List.length typs) t1 + with Invalid_argument _ -> + error env exp1.at + "expected function type, but expression produces type\n %s" + (T.string_of_typ_expand t1) + in + let ts, check_arg = + match tbs, inst.it with + | [], [] -> (* no inference required *) + [], check_exp + | [{T.sort = T.Scope;_}], _ (* special case to allow t_arg driven overload resolution *) + | _, _::_ -> (* explicit instantiation, check argument against it*) + check_inst_bounds env tbs typs at, check_exp + | _::_, [] -> (* implicit or empty instantiation, infer *) (* TODO: distinguish explicit empty instantiation `<>` from omitted instantiation `` *) + let t2 = infer_exp env exp2 in + match + (* i.e. exists_unique ts . t2 <: open_ ts t_arg /\ open ts_ t_arg <: t] *) + Bi_match.bi_match_typ (scope_of_env env) tbs + [t2; t_ret] [t_arg; t] + with + | ts -> + check_typ_bounds env tbs ts (List.map (fun _ -> exp1.at) ts) at; + ts, + fun env t_arg' exp -> + if not (T.sub t2 t_arg') then + error env exp.at "cannot infer type arguments due to subtyping\n %s is not a subtype of %s" (T.string_of_typ_expand t2) (T.string_of_typ_expand t_arg) + | exception Failure msg -> + error env at + "cannot implicitly instantiate function of type\n %s\nto argument of type\n %s%s%s" + (T.string_of_typ t1) + (T.string_of_typ t2) + (if Option.is_none t_opt then "" + else Printf.sprintf "\nto produce result of type\n %s\n" (T.string_of_typ t)) + msg + in + inst.note <- ts; + let t_arg' = T.open_ ts t_arg in + let t_ret' = T.open_ ts t_ret in + if not env.pre then begin + check_arg env t_arg' exp2; + if Type.is_shared_sort sort then begin + if not (T.concrete t_arg') then + error env exp1.at + "shared function argument contains abstract type\n %s" + (T.string_of_typ_expand t_arg'); + if not (T.concrete t_ret') then + error env exp2.at + "shared function call result contains abstract type\n %s" + (T.string_of_typ_expand t_ret'); + end + end; + t_ret' (* Cases *) From 0adb42b72b0251e14b0d5c350c687952e09007e3 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 4 Mar 2020 13:04:33 +0100 Subject: [PATCH 1094/1176] Bump ic-ref (#1264) Main points: * prints canister ids using ic:/ syntax * speed improvements in `winter` --- nix/sources.json | 2 +- test/run-drun/ok/AST-66.ic-ref-run.ok | 2 +- test/run-drun/ok/GIT-843.ic-ref-run.ok | 2 +- test/run-drun/ok/actor-import.ic-ref-run.ok | 2 +- test/run-drun/ok/actor-reference-return.ic-ref-run.ok | 2 +- test/run-drun/ok/actor-reference.ic-ref-run.ok | 2 +- test/run-drun/ok/array-out-of-bounds.ic-ref-run.ok | 2 +- test/run-drun/ok/async-any.ic-ref-run.ok | 2 +- test/run-drun/ok/async-calls1.ic-ref-run.ok | 2 +- test/run-drun/ok/async-calls2.ic-ref-run.ok | 2 +- test/run-drun/ok/async-calls3.ic-ref-run.ok | 2 +- test/run-drun/ok/async-free-var.ic-ref-run.ok | 2 +- test/run-drun/ok/async-loop-while.ic-ref-run.ok | 2 +- test/run-drun/ok/async-loop.ic-ref-run.ok | 2 +- test/run-drun/ok/async-new-obj.ic-ref-run.ok | 2 +- test/run-drun/ok/async-obj-mut.ic-ref-run.ok | 2 +- test/run-drun/ok/async-while.ic-ref-run.ok | 2 +- test/run-drun/ok/await-sugar.ic-ref-run.ok | 2 +- test/run-drun/ok/await.ic-ref-run.ok | 2 +- test/run-drun/ok/block.ic-ref-run.ok | 2 +- test/run-drun/ok/call-async-method.ic-ref-run.ok | 2 +- test/run-drun/ok/caller.ic-ref-run.ok | 2 +- test/run-drun/ok/closure-params.ic-ref-run.ok | 2 +- test/run-drun/ok/count-callbacks.ic-ref-run.ok | 2 +- test/run-drun/ok/counter.ic-ref-run.ok | 2 +- test/run-drun/ok/counter2.ic-ref-run.ok | 2 +- test/run-drun/ok/data-params.ic-ref-run.ok | 2 +- test/run-drun/ok/divide-by-zero.ic-ref-run.ok | 2 +- test/run-drun/ok/empty-actor.ic-ref-run.ok | 2 +- test/run-drun/ok/empty-call.ic-ref-run.ok | 2 +- test/run-drun/ok/flatten-awaitables.ic-ref-run.ok | 2 +- test/run-drun/ok/for-await.ic-ref-run.ok | 2 +- test/run-drun/ok/free-callbacks.ic-ref-run.ok | 2 +- test/run-drun/ok/general_await.ic-ref-run.ok | 2 +- test/run-drun/ok/general_await_implicit.ic-ref-run.ok | 2 +- test/run-drun/ok/generic-tail-rec.ic-ref-run.ok | 2 +- test/run-drun/ok/hello-world-async.ic-ref-run.ok | 2 +- test/run-drun/ok/hello-world-await.ic-ref-run.ok | 2 +- test/run-drun/ok/hello-world-message.ic-ref-run.ok | 2 +- test/run-drun/ok/hello-world-return.ic-ref-run.ok | 2 +- test/run-drun/ok/hello-world.ic-ref-run.ok | 2 +- test/run-drun/ok/ic-calls.ic-ref-run.ok | 2 +- test/run-drun/ok/idl-any.ic-ref-run.ok | 2 +- test/run-drun/ok/idl-bad.ic-ref-run.ok | 2 +- test/run-drun/ok/idl-buf-size-bug.ic-ref-run.ok | 2 +- test/run-drun/ok/idl-field-escape.ic-ref-run.ok | 2 +- test/run-drun/ok/idl-func.ic-ref-run.ok | 2 +- test/run-drun/ok/idl-mo.ic-ref-run.ok | 2 +- test/run-drun/ok/idl-nary.ic-ref-run.ok | 2 +- test/run-drun/ok/idl-nat-int.ic-ref-run.ok | 2 +- test/run-drun/ok/idl-option.ic-ref-run.ok | 2 +- test/run-drun/ok/idl-pair.ic-ref-run.ok | 2 +- test/run-drun/ok/idl-record.ic-ref-run.ok | 2 +- test/run-drun/ok/idl-shorthand.ic-ref-run.ok | 2 +- test/run-drun/ok/idl-tuple.ic-ref-run.ok | 2 +- test/run-drun/ok/idl-unit.ic-ref-run.ok | 2 +- test/run-drun/ok/idl-variant.ic-ref-run.ok | 2 +- test/run-drun/ok/idl-vector.ic-ref-run.ok | 2 +- test/run-drun/ok/interleave.ic-ref-run.ok | 2 +- test/run-drun/ok/issue-894.ic-ref-run.ok | 2 +- test/run-drun/ok/local-throw.ic-ref-run.ok | 2 +- test/run-drun/ok/mod-rebind.ic-ref-run.ok | 2 +- test/run-drun/ok/nary-async.ic-ref-run.ok | 2 +- test/run-drun/ok/oneway-throw.ic-ref-run.ok | 2 +- test/run-drun/ok/oneway.ic-ref-run.ok | 2 +- test/run-drun/ok/oom.ic-ref-run.ok | 2 +- test/run-drun/ok/overflow.ic-ref-run.ok | 2 +- test/run-drun/ok/print-from-init.ic-ref-run.ok | 2 +- test/run-drun/ok/query.ic-ref-run.ok | 2 +- test/run-drun/ok/query2.ic-ref-run.ok | 2 +- test/run-drun/ok/reject.ic-ref-run.ok | 2 +- test/run-drun/ok/rts-stats.ic-ref-run.ok | 2 +- test/run-drun/ok/selftail.ic-ref-run.ok | 2 +- test/run-drun/ok/shared-object.ic-ref-run.ok | 2 +- test/run-drun/ok/sharingbug.ic-ref-run.ok | 2 +- test/run-drun/ok/show.ic-ref-run.ok | 2 +- test/run-drun/ok/static-gc.ic-ref-run.ok | 2 +- test/run-drun/ok/switch-await.ic-ref-run.ok | 2 +- test/run-drun/ok/text-iter.ic-ref-run.ok | 2 +- test/run-drun/ok/throw.ic-ref-run.ok | 2 +- test/run-drun/ok/transpose.ic-ref-run.ok | 2 +- test/run-drun/ok/type-lub.ic-ref-run.ok | 2 +- test/run-drun/ok/upgrade.ic-ref-run.ok | 2 +- test/run-drun/ok/utf8.ic-ref-run.ok | 2 +- 84 files changed, 84 insertions(+), 84 deletions(-) diff --git a/nix/sources.json b/nix/sources.json index 034c93abdaa..658db44ac85 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -22,7 +22,7 @@ "ic-ref": { "ref": "master", "repo": "ssh://git@github.com/dfinity-lab/ic-ref", - "rev": "611af28895c2962040b06e506f822e0878612967", + "rev": "822a201c5e4e993567ac1066237c02dd9a6fcccb", "type": "git" }, "libtommath": { diff --git a/test/run-drun/ok/AST-66.ic-ref-run.ok b/test/run-drun/ok/AST-66.ic-ref-run.ok index afee61e2f46..034fb6499b4 100644 --- a/test/run-drun/ok/AST-66.ic-ref-run.ok +++ b/test/run-drun/ok/AST-66.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/GIT-843.ic-ref-run.ok b/test/run-drun/ok/GIT-843.ic-ref-run.ok index fdc5fc797d6..e55cbdd9580 100644 --- a/test/run-drun/ok/GIT-843.ic-ref-run.ok +++ b/test/run-drun/ok/GIT-843.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update Bad(0x4449444c0000) diff --git a/test/run-drun/ok/actor-import.ic-ref-run.ok b/test/run-drun/ok/actor-import.ic-ref-run.ok index db1865fee01..08a8db07ce5 100644 --- a/test/run-drun/ok/actor-import.ic-ref-run.ok +++ b/test/run-drun/ok/actor-import.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/actor-reference-return.ic-ref-run.ok b/test/run-drun/ok/actor-reference-return.ic-ref-run.ok index fa29433bf93..07d2f151835 100644 --- a/test/run-drun/ok/actor-reference-return.ic-ref-run.ok +++ b/test/run-drun/ok/actor-reference-return.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → query foo(0x4449444c0000) diff --git a/test/run-drun/ok/actor-reference.ic-ref-run.ok b/test/run-drun/ok/actor-reference.ic-ref-run.ok index c2b23162b29..0eb57fac0d6 100644 --- a/test/run-drun/ok/actor-reference.ic-ref-run.ok +++ b/test/run-drun/ok/actor-reference.ic-ref-run.ok @@ -1,4 +1,4 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed diff --git a/test/run-drun/ok/array-out-of-bounds.ic-ref-run.ok b/test/run-drun/ok/array-out-of-bounds.ic-ref-run.ok index e6fbfce33cd..d5a83262dd0 100644 --- a/test/run-drun/ok/array-out-of-bounds.ic-ref-run.ok +++ b/test/run-drun/ok/array-out-of-bounds.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update foo1(0x4449444c0000) diff --git a/test/run-drun/ok/async-any.ic-ref-run.ok b/test/run-drun/ok/async-any.ic-ref-run.ok index afee61e2f46..034fb6499b4 100644 --- a/test/run-drun/ok/async-any.ic-ref-run.ok +++ b/test/run-drun/ok/async-any.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/async-calls1.ic-ref-run.ok b/test/run-drun/ok/async-calls1.ic-ref-run.ok index afee61e2f46..034fb6499b4 100644 --- a/test/run-drun/ok/async-calls1.ic-ref-run.ok +++ b/test/run-drun/ok/async-calls1.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/async-calls2.ic-ref-run.ok b/test/run-drun/ok/async-calls2.ic-ref-run.ok index afee61e2f46..034fb6499b4 100644 --- a/test/run-drun/ok/async-calls2.ic-ref-run.ok +++ b/test/run-drun/ok/async-calls2.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/async-calls3.ic-ref-run.ok b/test/run-drun/ok/async-calls3.ic-ref-run.ok index afee61e2f46..034fb6499b4 100644 --- a/test/run-drun/ok/async-calls3.ic-ref-run.ok +++ b/test/run-drun/ok/async-calls3.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/async-free-var.ic-ref-run.ok b/test/run-drun/ok/async-free-var.ic-ref-run.ok index 8f7bba2765d..5dd50bddd80 100644 --- a/test/run-drun/ok/async-free-var.ic-ref-run.ok +++ b/test/run-drun/ok/async-free-var.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/async-loop-while.ic-ref-run.ok b/test/run-drun/ok/async-loop-while.ic-ref-run.ok index 5590a21c0cc..931bc9fe6eb 100644 --- a/test/run-drun/ok/async-loop-while.ic-ref-run.ok +++ b/test/run-drun/ok/async-loop-while.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/async-loop.ic-ref-run.ok b/test/run-drun/ok/async-loop.ic-ref-run.ok index c2b23162b29..0eb57fac0d6 100644 --- a/test/run-drun/ok/async-loop.ic-ref-run.ok +++ b/test/run-drun/ok/async-loop.ic-ref-run.ok @@ -1,4 +1,4 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed diff --git a/test/run-drun/ok/async-new-obj.ic-ref-run.ok b/test/run-drun/ok/async-new-obj.ic-ref-run.ok index 9c1c1024157..3adb758296e 100644 --- a/test/run-drun/ok/async-new-obj.ic-ref-run.ok +++ b/test/run-drun/ok/async-new-obj.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/async-obj-mut.ic-ref-run.ok b/test/run-drun/ok/async-obj-mut.ic-ref-run.ok index 6737780e9e8..c7846a7deb2 100644 --- a/test/run-drun/ok/async-obj-mut.ic-ref-run.ok +++ b/test/run-drun/ok/async-obj-mut.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/async-while.ic-ref-run.ok b/test/run-drun/ok/async-while.ic-ref-run.ok index 5590a21c0cc..931bc9fe6eb 100644 --- a/test/run-drun/ok/async-while.ic-ref-run.ok +++ b/test/run-drun/ok/async-while.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/await-sugar.ic-ref-run.ok b/test/run-drun/ok/await-sugar.ic-ref-run.ok index 1a26642aeb8..799673be81b 100644 --- a/test/run-drun/ok/await-sugar.ic-ref-run.ok +++ b/test/run-drun/ok/await-sugar.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update test(0x4449444c0000) diff --git a/test/run-drun/ok/await.ic-ref-run.ok b/test/run-drun/ok/await.ic-ref-run.ok index f9b45ab0b37..48e83a59765 100644 --- a/test/run-drun/ok/await.ic-ref-run.ok +++ b/test/run-drun/ok/await.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/block.ic-ref-run.ok b/test/run-drun/ok/block.ic-ref-run.ok index bc7fdc731f7..219f0e0982b 100644 --- a/test/run-drun/ok/block.ic-ref-run.ok +++ b/test/run-drun/ok/block.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/call-async-method.ic-ref-run.ok b/test/run-drun/ok/call-async-method.ic-ref-run.ok index 5db2c220aa9..a92bb347f7c 100644 --- a/test/run-drun/ok/call-async-method.ic-ref-run.ok +++ b/test/run-drun/ok/call-async-method.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update __motoko_async_helper(0x4449444c0000) diff --git a/test/run-drun/ok/caller.ic-ref-run.ok b/test/run-drun/ok/caller.ic-ref-run.ok index 822fe5814e7..09e6433fbae 100644 --- a/test/run-drun/ok/caller.ic-ref-run.ok +++ b/test/run-drun/ok/caller.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update c1(0x4449444c0000) diff --git a/test/run-drun/ok/closure-params.ic-ref-run.ok b/test/run-drun/ok/closure-params.ic-ref-run.ok index 78e8d45a493..8a77f764517 100644 --- a/test/run-drun/ok/closure-params.ic-ref-run.ok +++ b/test/run-drun/ok/closure-params.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/count-callbacks.ic-ref-run.ok b/test/run-drun/ok/count-callbacks.ic-ref-run.ok index cc9ae480184..8479c80c8ea 100644 --- a/test/run-drun/ok/count-callbacks.ic-ref-run.ok +++ b/test/run-drun/ok/count-callbacks.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/counter.ic-ref-run.ok b/test/run-drun/ok/counter.ic-ref-run.ok index e58b7435a4d..5fcd16c88c4 100644 --- a/test/run-drun/ok/counter.ic-ref-run.ok +++ b/test/run-drun/ok/counter.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update inc(0x4449444c0000) diff --git a/test/run-drun/ok/counter2.ic-ref-run.ok b/test/run-drun/ok/counter2.ic-ref-run.ok index 78ca22bb41e..ff15ed069cf 100644 --- a/test/run-drun/ok/counter2.ic-ref-run.ok +++ b/test/run-drun/ok/counter2.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/data-params.ic-ref-run.ok b/test/run-drun/ok/data-params.ic-ref-run.ok index bd4e6feb3b8..caa3ab4372b 100644 --- a/test/run-drun/ok/data-params.ic-ref-run.ok +++ b/test/run-drun/ok/data-params.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/divide-by-zero.ic-ref-run.ok b/test/run-drun/ok/divide-by-zero.ic-ref-run.ok index 49f70070b4b..234ac52c18b 100644 --- a/test/run-drun/ok/divide-by-zero.ic-ref-run.ok +++ b/test/run-drun/ok/divide-by-zero.ic-ref-run.ok @@ -1,4 +1,4 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← rejected (RC_CANISTER_ERROR): Initialization trapped: EvalTrapError :0.1 "NumericIntegerDivideByZero" diff --git a/test/run-drun/ok/empty-actor.ic-ref-run.ok b/test/run-drun/ok/empty-actor.ic-ref-run.ok index c2b23162b29..0eb57fac0d6 100644 --- a/test/run-drun/ok/empty-actor.ic-ref-run.ok +++ b/test/run-drun/ok/empty-actor.ic-ref-run.ok @@ -1,4 +1,4 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed diff --git a/test/run-drun/ok/empty-call.ic-ref-run.ok b/test/run-drun/ok/empty-call.ic-ref-run.ok index afee61e2f46..034fb6499b4 100644 --- a/test/run-drun/ok/empty-call.ic-ref-run.ok +++ b/test/run-drun/ok/empty-call.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/flatten-awaitables.ic-ref-run.ok b/test/run-drun/ok/flatten-awaitables.ic-ref-run.ok index d921798208b..71d6a8944ae 100644 --- a/test/run-drun/ok/flatten-awaitables.ic-ref-run.ok +++ b/test/run-drun/ok/flatten-awaitables.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/for-await.ic-ref-run.ok b/test/run-drun/ok/for-await.ic-ref-run.ok index fcacff2dc33..6822c5602ac 100644 --- a/test/run-drun/ok/for-await.ic-ref-run.ok +++ b/test/run-drun/ok/for-await.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/free-callbacks.ic-ref-run.ok b/test/run-drun/ok/free-callbacks.ic-ref-run.ok index 43c43a8a35c..b27a7071004 100644 --- a/test/run-drun/ok/free-callbacks.ic-ref-run.ok +++ b/test/run-drun/ok/free-callbacks.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/general_await.ic-ref-run.ok b/test/run-drun/ok/general_await.ic-ref-run.ok index 1b4ca9da8d8..f56e66a9605 100644 --- a/test/run-drun/ok/general_await.ic-ref-run.ok +++ b/test/run-drun/ok/general_await.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update Test(0x4449444c0000) diff --git a/test/run-drun/ok/general_await_implicit.ic-ref-run.ok b/test/run-drun/ok/general_await_implicit.ic-ref-run.ok index 1b4ca9da8d8..f56e66a9605 100644 --- a/test/run-drun/ok/general_await_implicit.ic-ref-run.ok +++ b/test/run-drun/ok/general_await_implicit.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update Test(0x4449444c0000) diff --git a/test/run-drun/ok/generic-tail-rec.ic-ref-run.ok b/test/run-drun/ok/generic-tail-rec.ic-ref-run.ok index b93725a4983..e004423eb65 100644 --- a/test/run-drun/ok/generic-tail-rec.ic-ref-run.ok +++ b/test/run-drun/ok/generic-tail-rec.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install debug.print: done 1 debug.print: done 2 diff --git a/test/run-drun/ok/hello-world-async.ic-ref-run.ok b/test/run-drun/ok/hello-world-async.ic-ref-run.ok index f8e57918ebf..e73d174b854 100644 --- a/test/run-drun/ok/hello-world-async.ic-ref-run.ok +++ b/test/run-drun/ok/hello-world-async.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/hello-world-await.ic-ref-run.ok b/test/run-drun/ok/hello-world-await.ic-ref-run.ok index 5ebf1fd6f35..0caa692a3c3 100644 --- a/test/run-drun/ok/hello-world-await.ic-ref-run.ok +++ b/test/run-drun/ok/hello-world-await.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/hello-world-message.ic-ref-run.ok b/test/run-drun/ok/hello-world-message.ic-ref-run.ok index c2b23162b29..0eb57fac0d6 100644 --- a/test/run-drun/ok/hello-world-message.ic-ref-run.ok +++ b/test/run-drun/ok/hello-world-message.ic-ref-run.ok @@ -1,4 +1,4 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed diff --git a/test/run-drun/ok/hello-world-return.ic-ref-run.ok b/test/run-drun/ok/hello-world-return.ic-ref-run.ok index c8d43bb2112..cb17be1132d 100644 --- a/test/run-drun/ok/hello-world-return.ic-ref-run.ok +++ b/test/run-drun/ok/hello-world-return.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → query hello(0x4449444c00017105576f726c64) diff --git a/test/run-drun/ok/hello-world.ic-ref-run.ok b/test/run-drun/ok/hello-world.ic-ref-run.ok index 787fda15c08..8d0b245b142 100644 --- a/test/run-drun/ok/hello-world.ic-ref-run.ok +++ b/test/run-drun/ok/hello-world.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install debug.print: Hello World! ← completed diff --git a/test/run-drun/ok/ic-calls.ic-ref-run.ok b/test/run-drun/ok/ic-calls.ic-ref-run.ok index afee61e2f46..034fb6499b4 100644 --- a/test/run-drun/ok/ic-calls.ic-ref-run.ok +++ b/test/run-drun/ok/ic-calls.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/idl-any.ic-ref-run.ok b/test/run-drun/ok/idl-any.ic-ref-run.ok index 9c450eca4cf..46052bedb22 100644 --- a/test/run-drun/ok/idl-any.ic-ref-run.ok +++ b/test/run-drun/ok/idl-any.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → query any(0x4449444c00027f7103466f6f) diff --git a/test/run-drun/ok/idl-bad.ic-ref-run.ok b/test/run-drun/ok/idl-bad.ic-ref-run.ok index 503aa6b80be..2a29f596d00 100644 --- a/test/run-drun/ok/idl-bad.ic-ref-run.ok +++ b/test/run-drun/ok/idl-bad.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → query foo(0x4e4f544449444c) diff --git a/test/run-drun/ok/idl-buf-size-bug.ic-ref-run.ok b/test/run-drun/ok/idl-buf-size-bug.ic-ref-run.ok index 36f2cf59629..9d0b57eac59 100644 --- a/test/run-drun/ok/idl-buf-size-bug.ic-ref-run.ok +++ b/test/run-drun/ok/idl-buf-size-bug.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update do(0x4449444c0000) diff --git a/test/run-drun/ok/idl-field-escape.ic-ref-run.ok b/test/run-drun/ok/idl-field-escape.ic-ref-run.ok index 4acc93354d6..2366a49f415 100644 --- a/test/run-drun/ok/idl-field-escape.ic-ref-run.ok +++ b/test/run-drun/ok/idl-field-escape.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → query foo1(0x4449444c0000) diff --git a/test/run-drun/ok/idl-func.ic-ref-run.ok b/test/run-drun/ok/idl-func.ic-ref-run.ok index 2187aa51f34..f3f4dd5b383 100644 --- a/test/run-drun/ok/idl-func.ic-ref-run.ok +++ b/test/run-drun/ok/idl-func.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → query fun(0x4449444c0000) diff --git a/test/run-drun/ok/idl-mo.ic-ref-run.ok b/test/run-drun/ok/idl-mo.ic-ref-run.ok index c2b23162b29..0eb57fac0d6 100644 --- a/test/run-drun/ok/idl-mo.ic-ref-run.ok +++ b/test/run-drun/ok/idl-mo.ic-ref-run.ok @@ -1,4 +1,4 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed diff --git a/test/run-drun/ok/idl-nary.ic-ref-run.ok b/test/run-drun/ok/idl-nary.ic-ref-run.ok index cbaf1fc6484..ced76119336 100644 --- a/test/run-drun/ok/idl-nary.ic-ref-run.ok +++ b/test/run-drun/ok/idl-nary.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → query two(0x4449444c00027171034f6e650354776f) diff --git a/test/run-drun/ok/idl-nat-int.ic-ref-run.ok b/test/run-drun/ok/idl-nat-int.ic-ref-run.ok index 0534f71c702..781fbe8b6ab 100644 --- a/test/run-drun/ok/idl-nat-int.ic-ref-run.ok +++ b/test/run-drun/ok/idl-nat-int.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → query absolute(0x4449444c00017d2a) diff --git a/test/run-drun/ok/idl-option.ic-ref-run.ok b/test/run-drun/ok/idl-option.ic-ref-run.ok index 9dca8a15c39..06f27ebfcfb 100644 --- a/test/run-drun/ok/idl-option.ic-ref-run.ok +++ b/test/run-drun/ok/idl-option.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → query any(0x4449444c00017f) diff --git a/test/run-drun/ok/idl-pair.ic-ref-run.ok b/test/run-drun/ok/idl-pair.ic-ref-run.ok index f8ab424d535..60087650730 100644 --- a/test/run-drun/ok/idl-pair.ic-ref-run.ok +++ b/test/run-drun/ok/idl-pair.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → query len2(0x4449444c0002717102486905576f726c64) diff --git a/test/run-drun/ok/idl-record.ic-ref-run.ok b/test/run-drun/ok/idl-record.ic-ref-run.ok index abdf225c1cb..692e52fa84f 100644 --- a/test/run-drun/ok/idl-record.ic-ref-run.ok +++ b/test/run-drun/ok/idl-record.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → query pair(0x4449444c016c020071017c010004486579212a) diff --git a/test/run-drun/ok/idl-shorthand.ic-ref-run.ok b/test/run-drun/ok/idl-shorthand.ic-ref-run.ok index a03dae7bc92..8101a1238f0 100644 --- a/test/run-drun/ok/idl-shorthand.ic-ref-run.ok +++ b/test/run-drun/ok/idl-shorthand.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → query foo(0x4449444c016b01d1a7cf027f010000) diff --git a/test/run-drun/ok/idl-tuple.ic-ref-run.ok b/test/run-drun/ok/idl-tuple.ic-ref-run.ok index b2cf5de241c..526eb6aa159 100644 --- a/test/run-drun/ok/idl-tuple.ic-ref-run.ok +++ b/test/run-drun/ok/idl-tuple.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → query len2(0x4449444c0002717102486905576f726c64) diff --git a/test/run-drun/ok/idl-unit.ic-ref-run.ok b/test/run-drun/ok/idl-unit.ic-ref-run.ok index 68199a00422..c5f6e6aa31f 100644 --- a/test/run-drun/ok/idl-unit.ic-ref-run.ok +++ b/test/run-drun/ok/idl-unit.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → query unit_id(0x4449444c0000) diff --git a/test/run-drun/ok/idl-variant.ic-ref-run.ok b/test/run-drun/ok/idl-variant.ic-ref-run.ok index f7e488349e5..62185194277 100644 --- a/test/run-drun/ok/idl-variant.ic-ref-run.ok +++ b/test/run-drun/ok/idl-variant.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → query numify(0x4449444c016b03d583b702008790c0bd0479dc9790cb0e790100000220000000) diff --git a/test/run-drun/ok/idl-vector.ic-ref-run.ok b/test/run-drun/ok/idl-vector.ic-ref-run.ok index 241d22977ff..6c6df821f1b 100644 --- a/test/run-drun/ok/idl-vector.ic-ref-run.ok +++ b/test/run-drun/ok/idl-vector.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → query rose(0x4449444c016d00010003000400020000000000) diff --git a/test/run-drun/ok/interleave.ic-ref-run.ok b/test/run-drun/ok/interleave.ic-ref-run.ok index a723c66cd44..66977dd78f2 100644 --- a/test/run-drun/ok/interleave.ic-ref-run.ok +++ b/test/run-drun/ok/interleave.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/issue-894.ic-ref-run.ok b/test/run-drun/ok/issue-894.ic-ref-run.ok index e634922b493..c95e740a750 100644 --- a/test/run-drun/ok/issue-894.ic-ref-run.ok +++ b/test/run-drun/ok/issue-894.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/local-throw.ic-ref-run.ok b/test/run-drun/ok/local-throw.ic-ref-run.ok index 62e5e112d7b..4a6cc821e0c 100644 --- a/test/run-drun/ok/local-throw.ic-ref-run.ok +++ b/test/run-drun/ok/local-throw.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/mod-rebind.ic-ref-run.ok b/test/run-drun/ok/mod-rebind.ic-ref-run.ok index c2b23162b29..0eb57fac0d6 100644 --- a/test/run-drun/ok/mod-rebind.ic-ref-run.ok +++ b/test/run-drun/ok/mod-rebind.ic-ref-run.ok @@ -1,4 +1,4 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed diff --git a/test/run-drun/ok/nary-async.ic-ref-run.ok b/test/run-drun/ok/nary-async.ic-ref-run.ok index 5d6aaab1806..19f83593563 100644 --- a/test/run-drun/ok/nary-async.ic-ref-run.ok +++ b/test/run-drun/ok/nary-async.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update go1(0x4449444c0000) diff --git a/test/run-drun/ok/oneway-throw.ic-ref-run.ok b/test/run-drun/ok/oneway-throw.ic-ref-run.ok index 4f8ced56d84..0c0b72d4fdc 100644 --- a/test/run-drun/ok/oneway-throw.ic-ref-run.ok +++ b/test/run-drun/ok/oneway-throw.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/oneway.ic-ref-run.ok b/test/run-drun/ok/oneway.ic-ref-run.ok index 85db204bcb2..e7159c8dbf0 100644 --- a/test/run-drun/ok/oneway.ic-ref-run.ok +++ b/test/run-drun/ok/oneway.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/oom.ic-ref-run.ok b/test/run-drun/ok/oom.ic-ref-run.ok index 301b73a2e17..c24960ac1af 100644 --- a/test/run-drun/ok/oom.ic-ref-run.ok +++ b/test/run-drun/ok/oom.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/overflow.ic-ref-run.ok b/test/run-drun/ok/overflow.ic-ref-run.ok index a57ceadf329..bdf1174fc4d 100644 --- a/test/run-drun/ok/overflow.ic-ref-run.ok +++ b/test/run-drun/ok/overflow.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/print-from-init.ic-ref-run.ok b/test/run-drun/ok/print-from-init.ic-ref-run.ok index 2aa6c66be32..13ed2cbc091 100644 --- a/test/run-drun/ok/print-from-init.ic-ref-run.ok +++ b/test/run-drun/ok/print-from-init.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install debug.print: Debug out ← completed diff --git a/test/run-drun/ok/query.ic-ref-run.ok b/test/run-drun/ok/query.ic-ref-run.ok index 6cee50090f9..d13ccb9cb71 100644 --- a/test/run-drun/ok/query.ic-ref-run.ok +++ b/test/run-drun/ok/query.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update inc(0x4449444c0000) diff --git a/test/run-drun/ok/query2.ic-ref-run.ok b/test/run-drun/ok/query2.ic-ref-run.ok index 760b54d7faa..be5266aaf32 100644 --- a/test/run-drun/ok/query2.ic-ref-run.ok +++ b/test/run-drun/ok/query2.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/reject.ic-ref-run.ok b/test/run-drun/ok/reject.ic-ref-run.ok index 1cb96c6b834..a546f58b669 100644 --- a/test/run-drun/ok/reject.ic-ref-run.ok +++ b/test/run-drun/ok/reject.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update reject1(0x4449444c0000) diff --git a/test/run-drun/ok/rts-stats.ic-ref-run.ok b/test/run-drun/ok/rts-stats.ic-ref-run.ok index a5f2c60f539..673f2ca5d68 100644 --- a/test/run-drun/ok/rts-stats.ic-ref-run.ok +++ b/test/run-drun/ok/rts-stats.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install debug.print: Size and allocation delta: (10_008, 10_008) ← completed diff --git a/test/run-drun/ok/selftail.ic-ref-run.ok b/test/run-drun/ok/selftail.ic-ref-run.ok index 7ce890fa05a..326651f1e00 100644 --- a/test/run-drun/ok/selftail.ic-ref-run.ok +++ b/test/run-drun/ok/selftail.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install debug.print: ok1 debug.print: ok2 diff --git a/test/run-drun/ok/shared-object.ic-ref-run.ok b/test/run-drun/ok/shared-object.ic-ref-run.ok index afee61e2f46..034fb6499b4 100644 --- a/test/run-drun/ok/shared-object.ic-ref-run.ok +++ b/test/run-drun/ok/shared-object.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/sharingbug.ic-ref-run.ok b/test/run-drun/ok/sharingbug.ic-ref-run.ok index c2b23162b29..0eb57fac0d6 100644 --- a/test/run-drun/ok/sharingbug.ic-ref-run.ok +++ b/test/run-drun/ok/sharingbug.ic-ref-run.ok @@ -1,4 +1,4 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed diff --git a/test/run-drun/ok/show.ic-ref-run.ok b/test/run-drun/ok/show.ic-ref-run.ok index cf0706b6256..80196c87f68 100644 --- a/test/run-drun/ok/show.ic-ref-run.ok +++ b/test/run-drun/ok/show.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install debug.print: true debug.print: false diff --git a/test/run-drun/ok/static-gc.ic-ref-run.ok b/test/run-drun/ok/static-gc.ic-ref-run.ok index 53f26d861ca..e7855dbfbe8 100644 --- a/test/run-drun/ok/static-gc.ic-ref-run.ok +++ b/test/run-drun/ok/static-gc.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update foo1(0x4449444c0000) diff --git a/test/run-drun/ok/switch-await.ic-ref-run.ok b/test/run-drun/ok/switch-await.ic-ref-run.ok index e0d0b5c0113..2a6f455992f 100644 --- a/test/run-drun/ok/switch-await.ic-ref-run.ok +++ b/test/run-drun/ok/switch-await.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update go_tt(0x4449444c0000) diff --git a/test/run-drun/ok/text-iter.ic-ref-run.ok b/test/run-drun/ok/text-iter.ic-ref-run.ok index 3ef6493bd15..44cb82c36db 100644 --- a/test/run-drun/ok/text-iter.ic-ref-run.ok +++ b/test/run-drun/ok/text-iter.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install debug.print: via `debugPrint`: debug.print: hello world! diff --git a/test/run-drun/ok/throw.ic-ref-run.ok b/test/run-drun/ok/throw.ic-ref-run.ok index 62e5e112d7b..4a6cc821e0c 100644 --- a/test/run-drun/ok/throw.ic-ref-run.ok +++ b/test/run-drun/ok/throw.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/transpose.ic-ref-run.ok b/test/run-drun/ok/transpose.ic-ref-run.ok index 252f077943a..d7b9e5a1d8d 100644 --- a/test/run-drun/ok/transpose.ic-ref-run.ok +++ b/test/run-drun/ok/transpose.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/type-lub.ic-ref-run.ok b/test/run-drun/ok/type-lub.ic-ref-run.ok index afee61e2f46..034fb6499b4 100644 --- a/test/run-drun/ok/type-lub.ic-ref-run.ok +++ b/test/run-drun/ok/type-lub.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update go(0x4449444c0000) diff --git a/test/run-drun/ok/upgrade.ic-ref-run.ok b/test/run-drun/ok/upgrade.ic-ref-run.ok index 03f65da92f6..15cf5b55781 100644 --- a/test/run-drun/ok/upgrade.ic-ref-run.ok +++ b/test/run-drun/ok/upgrade.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install debug.print: init'ed ← completed diff --git a/test/run-drun/ok/utf8.ic-ref-run.ok b/test/run-drun/ok/utf8.ic-ref-run.ok index 912d4cd9a5d..fe836a527ed 100644 --- a/test/run-drun/ok/utf8.ic-ref-run.ok +++ b/test/run-drun/ok/utf8.ic-ref-run.ok @@ -1,5 +1,5 @@ → create -← completed: canister-id = 0x2a01 +← completed: canister-id = ic:2a012b → install ← completed → update callshow(0x4449444c0000) From 3e643b557e26593fafdf15ad15739cb2ae3bae3c Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 4 Mar 2020 13:11:00 +0100 Subject: [PATCH 1095/1176] Remove winter from sources.json (#1263) it is now only an indirect dependency via `ic-ref`. --- nix/sources.json | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/nix/sources.json b/nix/sources.json index 658db44ac85..822e646de3a 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -61,18 +61,5 @@ "url": "https://github.com/flowtype/ocaml-vlq/archive/115bf0fef38018f31ac6386fef17a00bd8307218.tar.gz", "url_template": "https://github.com///archive/.tar.gz", "version": "v0.2.0" - }, - "winter": { - "branch": "master", - "builtin": false, - "description": "Haskell port of the WebAssembly OCaml reference interpreter", - "homepage": "https://github.com/WebAssembly/spec/tree/master/interpreter", - "owner": "dfinity-side-projects", - "repo": "winter", - "rev": "1e16b471644be26160cc20c4e2144c643c547ed8", - "sha256": "191fk1dv8vp28rwpl75nz9y3pbypc8jv9w669mvl9d2k5f74jirm", - "type": "tarball", - "url": "https://github.com/dfinity-side-projects/winter/archive/1e16b471644be26160cc20c4e2144c643c547ed8.tar.gz", - "url_template": "https://github.com///archive/.tar.gz" } } From e0d70d82c2af78f3ecd48ace0e49bad3f74d3bf6 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 4 Mar 2020 14:30:30 +0000 Subject: [PATCH 1096/1176] take list of subtyping problems, not two lists; push defensive verification of solution into bi_match --- src/mo_frontend/bi_match.ml | 20 ++++++++++++++++---- src/mo_frontend/bi_match.mli | 2 +- src/mo_frontend/typing.ml | 28 ++++++++++++++-------------- 3 files changed, 31 insertions(+), 19 deletions(-) diff --git a/src/mo_frontend/bi_match.ml b/src/mo_frontend/bi_match.ml index e2da0156378..541aee91290 100644 --- a/src/mo_frontend/bi_match.ml +++ b/src/mo_frontend/bi_match.ml @@ -11,11 +11,16 @@ let denotable t = let t' = normalize t in not (is_mut t' || is_typ t') -let bi_match_typ scope_opt tbs ts1 ts2 = +let verify tbs subs ts = + List.length tbs = List.length ts && + List.for_all2 (fun t tb -> sub t (open_ ts tb.bound)) ts tbs && + List.for_all (fun (t1,t2) -> sub (open_ ts t1) (open_ ts t2)) subs + +let bi_match_typ scope_opt tbs subs = let ts = open_binds tbs in - let ts1 = List.map (open_ ts) ts1 in - let ts2 = List.map (open_ ts) ts2 in + let ts1 = List.map (fun (t1, _) -> open_ ts t1) subs in + let ts2 = List.map (fun (_, t2) -> open_ ts t2) subs in let cs = List.map (fun t -> match t with Con(c,_) -> c | _ -> assert false) ts in @@ -257,7 +262,7 @@ let bi_match_typ scope_opt tbs ts1 ts2 = match bi_match_list bi_match_typ (ref SS.empty) (ref SS.empty) (l, u) ConSet.empty ts1 ts2 with | Some (l,u) -> - List.map + let us = List.map (fun c -> match ConEnv.find_opt c l, ConEnv.find_opt c u with | None, None -> Non @@ -271,6 +276,13 @@ let bi_match_typ scope_opt tbs ts1 ts2 = else fail_over_constrained lb c ub) cs + in + if verify tbs subs us then + us + else + (failwith + (Printf.sprintf "bug: inferred bad instantiation\n <%s>;\nplease report this error message as a bug and, for now, supply an explicit instantiation instead" + (String.concat ", " (List.map string_of_typ us)))) | None -> failwith (Printf.sprintf "no instantiation of %s makes %s" (String.concat ", " (List.map string_of_con cs)) diff --git a/src/mo_frontend/bi_match.mli b/src/mo_frontend/bi_match.mli index 8c67d12ed28..6b75c4f7b48 100644 --- a/src/mo_frontend/bi_match.mli +++ b/src/mo_frontend/bi_match.mli @@ -2,5 +2,5 @@ open Mo_types open Type val bi_match_typ : - scope option -> bind list -> typ list -> typ list -> + scope option -> bind list -> (typ * typ) list -> typ list (* raises Failure *) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 747b7aa023d..f29501294be 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -1210,40 +1210,40 @@ and infer_call env exp1 inst exp2 at t_opt = "expected function type, but expression produces type\n %s" (T.string_of_typ_expand t1) in - let ts, check_arg = + let ts, t_arg', t_ret' = match tbs, inst.it with | [], [] -> (* no inference required *) - [], check_exp + if not env.pre then check_exp env t_arg exp2; + [], t_arg, t_ret | [{T.sort = T.Scope;_}], _ (* special case to allow t_arg driven overload resolution *) | _, _::_ -> (* explicit instantiation, check argument against it*) - check_inst_bounds env tbs typs at, check_exp + let ts = check_inst_bounds env tbs typs at in + let t_arg' = T.open_ ts t_arg in + let t_ret' = T.open_ ts t_ret in + if not env.pre then check_exp env t_arg' exp2; + ts, t_arg', t_ret' | _::_, [] -> (* implicit or empty instantiation, infer *) (* TODO: distinguish explicit empty instantiation `<>` from omitted instantiation `` *) let t2 = infer_exp env exp2 in match (* i.e. exists_unique ts . t2 <: open_ ts t_arg /\ open ts_ t_arg <: t] *) Bi_match.bi_match_typ (scope_of_env env) tbs - [t2; t_ret] [t_arg; t] + [(t2, t_arg); (t_ret, t)] with | ts -> - check_typ_bounds env tbs ts (List.map (fun _ -> exp1.at) ts) at; - ts, - fun env t_arg' exp -> - if not (T.sub t2 t_arg') then - error env exp.at "cannot infer type arguments due to subtyping\n %s is not a subtype of %s" (T.string_of_typ_expand t2) (T.string_of_typ_expand t_arg) + let t_arg' = T.open_ ts t_arg in + let t_ret' = T.open_ ts t_ret in + ts, t_arg', t_ret' | exception Failure msg -> error env at - "cannot implicitly instantiate function of type\n %s\nto argument of type\n %s%s%s" + "cannot implicitly instantiate function of type\n %s\nto argument of type\n %s%s\n%s" (T.string_of_typ t1) (T.string_of_typ t2) (if Option.is_none t_opt then "" - else Printf.sprintf "\nto produce result of type\n %s\n" (T.string_of_typ t)) + else Printf.sprintf "\nto produce result of type\n %s" (T.string_of_typ t)) msg in inst.note <- ts; - let t_arg' = T.open_ ts t_arg in - let t_ret' = T.open_ ts t_ret in if not env.pre then begin - check_arg env t_arg' exp2; if Type.is_shared_sort sort then begin if not (T.concrete t_arg') then error env exp1.at From 025b78b8c084727dd5dcea0fe3b3eaea06075d06 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 4 Mar 2020 17:21:00 +0100 Subject: [PATCH 1097/1176] Auto-update: Do not update ic-ref (#1258) we want to make deliberate choices when we upgrade `ic-ref`, and eventually track versioned releases. --- .github/workflows/niv-updater.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/niv-updater.yml b/.github/workflows/niv-updater.yml index 60ea6da8fe6..ff0d3ca6f3b 100644 --- a/.github/workflows/niv-updater.yml +++ b/.github/workflows/niv-updater.yml @@ -22,7 +22,7 @@ jobs: uses: knl/niv-updater-action@v4 with: # might be too noisy - blacklist: 'nixpkgs,dfinity' + blacklist: 'nixpkgs,dfinity,ic-ref' labels: | automerge-squash env: From caa4490fef2700e1c49de81640bec436154463da Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 4 Mar 2020 17:35:25 +0000 Subject: [PATCH 1098/1176] Update src/mo_frontend/bi_match.ml Co-Authored-By: Joachim Breitner --- src/mo_frontend/bi_match.ml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/mo_frontend/bi_match.ml b/src/mo_frontend/bi_match.ml index 541aee91290..e120a1626f9 100644 --- a/src/mo_frontend/bi_match.ml +++ b/src/mo_frontend/bi_match.ml @@ -24,8 +24,7 @@ let bi_match_typ scope_opt tbs subs = let cs = List.map (fun t -> match t with Con(c,_) -> c | _ -> assert false) ts in - let flexible c = List.exists (Con.eq c) cs - in + let flexible c = List.exists (Con.eq c) cs in let mentions typ ce = not (ConSet.is_empty (ConSet.inter (cons typ) ce)) in @@ -294,4 +293,3 @@ let bi_match_typ scope_opt tbs subs = - From 7b39e117d8c33ca9ebf02f2f838a10d4e8674b57 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 4 Mar 2020 17:35:37 +0000 Subject: [PATCH 1099/1176] Update src/mo_frontend/bi_match.ml Co-Authored-By: Joachim Breitner --- src/mo_frontend/bi_match.ml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/mo_frontend/bi_match.ml b/src/mo_frontend/bi_match.ml index e120a1626f9..69be6082065 100644 --- a/src/mo_frontend/bi_match.ml +++ b/src/mo_frontend/bi_match.ml @@ -29,13 +29,13 @@ let bi_match_typ scope_opt tbs subs = let mentions typ ce = not (ConSet.is_empty (ConSet.inter (cons typ) ce)) in let rec bi_match_list p rel eq inst any xs1 xs2 = - (match (xs1, xs2) with - | (x1::xs1, x2::xs2) -> + match (xs1, xs2) with + | x1::xs1, x2::xs2 -> (match p rel eq inst any x1 x2 with | Some inst -> bi_match_list p rel eq inst any xs1 xs2 | None -> None) | [], [] -> Some inst - | _, _ -> None) + | _, _ -> None in let rec bi_match_typ rel eq ((l,u) as inst) (any:ConSet.t) (t1:typ) (t2:typ) = @@ -292,4 +292,3 @@ let bi_match_typ scope_opt tbs subs = - From 029f35c34684583bd96ff72ee4e0618987af5615 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 4 Mar 2020 17:37:49 +0000 Subject: [PATCH 1100/1176] Update src/mo_frontend/bi_match.ml Co-Authored-By: Joachim Breitner --- src/mo_frontend/bi_match.ml | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/mo_frontend/bi_match.ml b/src/mo_frontend/bi_match.ml index 69be6082065..85b8f1b3439 100644 --- a/src/mo_frontend/bi_match.ml +++ b/src/mo_frontend/bi_match.ml @@ -17,7 +17,6 @@ let verify tbs subs ts = List.for_all (fun (t1,t2) -> sub (open_ ts t1) (open_ ts t2)) subs let bi_match_typ scope_opt tbs subs = - let ts = open_binds tbs in let ts1 = List.map (fun (t1, _) -> open_ ts t1) subs in let ts2 = List.map (fun (_, t2) -> open_ ts t2) subs in @@ -291,4 +290,3 @@ let bi_match_typ scope_opt tbs subs = ts1 ts2))) - From 61efbbf122c984dce2e464b905fe94a5f9bd4295 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 4 Mar 2020 21:51:00 +0000 Subject: [PATCH 1101/1176] added (rough) mathematical spec of alg --- src/mo_frontend/bi_match.ml | 22 ++++++++++++++-------- src/mo_frontend/bi_match.mli | 25 +++++++++++++++++++++++++ src/mo_frontend/typing.ml | 4 +++- 3 files changed, 42 insertions(+), 9 deletions(-) diff --git a/src/mo_frontend/bi_match.ml b/src/mo_frontend/bi_match.ml index 85b8f1b3439..ad9147534d9 100644 --- a/src/mo_frontend/bi_match.ml +++ b/src/mo_frontend/bi_match.ml @@ -7,17 +7,21 @@ open MakePretty(struct let show_stamps = false end) module SS = Set.Make (struct type t = typ * typ let compare = compare end) +(* Types that are denotable (ranged over) by type variables *) let denotable t = let t' = normalize t in not (is_mut t' || is_typ t') -let verify tbs subs ts = +(* Check instantiation `ts` satisfies bounds `tbs` and all the pairwise sub-typing relations in `subs`; + used to sanity check inferred instantiations *) +let verify_inst tbs subs ts = List.length tbs = List.length ts && List.for_all2 (fun t tb -> sub t (open_ ts tb.bound)) ts tbs && List.for_all (fun (t1,t2) -> sub (open_ ts t1) (open_ ts t2)) subs let bi_match_typ scope_opt tbs subs = let ts = open_binds tbs in + let ts1 = List.map (fun (t1, _) -> open_ ts t1) subs in let ts2 = List.map (fun (_, t2) -> open_ ts t2) subs in @@ -42,7 +46,6 @@ let bi_match_typ scope_opt tbs subs = then Some inst else begin rel := SS.add (t1, t2) !rel; - (* Printf.printf "%s %s\n" (!str t1) (!str t2); *) match t1, t2 with | Pre, _ | _, Pre -> Some inst @@ -240,7 +243,8 @@ let bi_match_typ scope_opt tbs subs = and fail_open_bound c bd = let c = Con.name c in let bd = string_of_typ bd in - failwith (Printf.sprintf "type parameter %s has an open bound %s mentioning another type parameter;\nexplicit type instantiation required due to limitation of inference" c bd) + failwith (Printf.sprintf + "type parameter %s has an open bound %s mentioning another type parameter;\nexplicit type instantiation required due to limitation of inference" c bd) in let bds = List.map (fun tb -> open_ ts tb.bound) tbs in @@ -252,7 +256,8 @@ let bi_match_typ scope_opt tbs subs = | Some c, {sort=Scope;_}::tbs -> ConEnv.singleton (List.hd cs) c, add (List.hd cs) (lub c (List.hd bds)) u - | None, {sort=Scope;_}::tbs -> failwith "scope instantiation required but no scope available" + | None, {sort=Scope;_}::tbs -> + failwith "scope instantiation required but no scope available" | _, _ -> ConEnv.empty, u @@ -275,12 +280,13 @@ let bi_match_typ scope_opt tbs subs = fail_over_constrained lb c ub) cs in - if verify tbs subs us then + if verify_inst tbs subs us then us else - (failwith - (Printf.sprintf "bug: inferred bad instantiation\n <%s>;\nplease report this error message as a bug and, for now, supply an explicit instantiation instead" - (String.concat ", " (List.map string_of_typ us)))) + failwith + (Printf.sprintf + "bug: inferred bad instantiation\n <%s>;\nplease report this error message as a bug and, for now, supply an explicit instantiation instead" + (String.concat ", " (List.map string_of_typ us))) | None -> failwith (Printf.sprintf "no instantiation of %s makes %s" (String.concat ", " (List.map string_of_con cs)) diff --git a/src/mo_frontend/bi_match.mli b/src/mo_frontend/bi_match.mli index 6b75c4f7b48..eb3add8bd08 100644 --- a/src/mo_frontend/bi_match.mli +++ b/src/mo_frontend/bi_match.mli @@ -1,6 +1,31 @@ open Mo_types open Type +(* `bi_match scope_opt tbs subs` returns + a minimal instantiation `ts` such that + * |`ts`| = |`tbs`| + * `ts` satisfies the bounds in `tbs` + * every `(t1,t2)` in `subs` satisfies `open_ ts t1 <: open_ ts t2` + * any `Scope` parameter in `tbs` is instantiated with scope_opt, iff scope_opt <> None. + or fails with exception `Failure msg` if + * tbs contains open bounds mentioning parameters in tbs (a limitiation); or + * no such instantiation exists due to + * a subtype violation; or + * some parameter in `tbs` being under constrained (`ts` is ambiguous); or + * some parameter in `tbs` being over constrained (no `ts` exists); or + For every pair (t1, t2) in `subs`, at least one of `t1` or `t2` must be closed and the other + may be "open" mentioning parameters in `tbs` by index (Var i, i < |`tbs`|). + + The ordering on instantiations `ts` is determined pointwise depending on the + occurrence of that variable in `subs` and is: + * subtyping ( _ <: _) on variables that occur strictly positively in subs + * super-typing ( _ :> _) on variables that occur strictly negatively in subs + * equivalence ( _ = _ ) on variables that occur both positively and negatively in subs + * {(Non,Non)} on variables that don't occur in subs + + (modulo mixing my left foot with my right) +*) + val bi_match_typ : scope option -> bind list -> (typ * typ) list -> typ list (* raises Failure *) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 76d7428001d..33e41c26481 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -1216,7 +1216,8 @@ and infer_call env exp1 inst exp2 at t_opt = if not env.pre then check_exp env t_arg exp2; [], t_arg, t_ret | [{T.sort = T.Scope;_}], _ (* special case to allow t_arg driven overload resolution *) - | _, _::_ -> (* explicit instantiation, check argument against it*) + | _, _::_ -> + (* explicit instantiation, check argument against instantiated domain *) let ts = check_inst_bounds env tbs typs at in let t_arg' = T.open_ ts t_arg in let t_ret' = T.open_ ts t_ret in @@ -1255,6 +1256,7 @@ and infer_call env exp1 inst exp2 at t_opt = (T.string_of_typ_expand t_ret'); end end; + (* note t_ret' <: t checked by caller if necessary *) t_ret' (* Cases *) From b27ca3b731c4dc1bf6ad98305ee555657259bb45 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 4 Mar 2020 21:53:59 +0000 Subject: [PATCH 1102/1176] formatting --- src/mo_frontend/bi_match.mli | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mo_frontend/bi_match.mli b/src/mo_frontend/bi_match.mli index eb3add8bd08..9af23c562aa 100644 --- a/src/mo_frontend/bi_match.mli +++ b/src/mo_frontend/bi_match.mli @@ -21,7 +21,7 @@ open Type * subtyping ( _ <: _) on variables that occur strictly positively in subs * super-typing ( _ :> _) on variables that occur strictly negatively in subs * equivalence ( _ = _ ) on variables that occur both positively and negatively in subs - * {(Non,Non)} on variables that don't occur in subs + * trivial {(Non,Non)} on variables that don't occur in subs (modulo mixing my left foot with my right) *) From a5c0170449eae4b691cd46315bcea194bf24f69d Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 4 Mar 2020 21:55:54 +0000 Subject: [PATCH 1103/1176] typos --- src/mo_frontend/bi_match.mli | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mo_frontend/bi_match.mli b/src/mo_frontend/bi_match.mli index 9af23c562aa..fb6a1b83ce1 100644 --- a/src/mo_frontend/bi_match.mli +++ b/src/mo_frontend/bi_match.mli @@ -8,7 +8,7 @@ open Type * every `(t1,t2)` in `subs` satisfies `open_ ts t1 <: open_ ts t2` * any `Scope` parameter in `tbs` is instantiated with scope_opt, iff scope_opt <> None. or fails with exception `Failure msg` if - * tbs contains open bounds mentioning parameters in tbs (a limitiation); or + * `tbs` contains open bounds mentioning parameters in `tbs` (a limitation); or * no such instantiation exists due to * a subtype violation; or * some parameter in `tbs` being under constrained (`ts` is ambiguous); or @@ -18,7 +18,7 @@ open Type The ordering on instantiations `ts` is determined pointwise depending on the occurrence of that variable in `subs` and is: - * subtyping ( _ <: _) on variables that occur strictly positively in subs + * sub-typing ( _ <: _) on variables that occur strictly positively in subs * super-typing ( _ :> _) on variables that occur strictly negatively in subs * equivalence ( _ = _ ) on variables that occur both positively and negatively in subs * trivial {(Non,Non)} on variables that don't occur in subs From 7b580ac932bcb4bdbc3813fbea97f6965c06b5a2 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Thu, 5 Mar 2020 10:57:45 +0000 Subject: [PATCH 1104/1176] address review --- src/mo_frontend/bi_match.ml | 6 ++++-- src/mo_frontend/bi_match.mli | 2 +- src/mo_frontend/typing.ml | 8 ++++---- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/mo_frontend/bi_match.ml b/src/mo_frontend/bi_match.ml index ad9147534d9..2926f867f03 100644 --- a/src/mo_frontend/bi_match.ml +++ b/src/mo_frontend/bi_match.ml @@ -19,7 +19,7 @@ let verify_inst tbs subs ts = List.for_all2 (fun t tb -> sub t (open_ ts tb.bound)) ts tbs && List.for_all (fun (t1,t2) -> sub (open_ ts t1) (open_ ts t2)) subs -let bi_match_typ scope_opt tbs subs = +let bi_match_subs scope_opt tbs subs = let ts = open_binds tbs in let ts1 = List.map (fun (t1, _) -> open_ ts t1) subs in @@ -27,7 +27,9 @@ let bi_match_typ scope_opt tbs subs = let cs = List.map (fun t -> match t with Con(c,_) -> c | _ -> assert false) ts in - let flexible c = List.exists (Con.eq c) cs in + let flexible = + let cons = ConSet.of_list cs in + fun c -> ConSet.mem c cons in let mentions typ ce = not (ConSet.is_empty (ConSet.inter (cons typ) ce)) in diff --git a/src/mo_frontend/bi_match.mli b/src/mo_frontend/bi_match.mli index fb6a1b83ce1..a68f2511dee 100644 --- a/src/mo_frontend/bi_match.mli +++ b/src/mo_frontend/bi_match.mli @@ -26,6 +26,6 @@ open Type (modulo mixing my left foot with my right) *) -val bi_match_typ : +val bi_match_subs : scope option -> bind list -> (typ * typ) list -> typ list (* raises Failure *) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 33e41c26481..a0165f5dc74 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -1199,8 +1199,8 @@ and check_exp' env0 t exp : T.typ = (T.string_of_typ_expand t); t' -and infer_call env exp1 inst exp2 at t_opt = - let t = Lib.Option.get t_opt T.Any in +and infer_call env exp1 inst exp2 at t_expect_opt = + let t = Lib.Option.get t_expect_opt T.Any in let typs = inst.it in let t1 = infer_exp_promote env exp1 in let sort, tbs, t_arg, t_ret = @@ -1227,7 +1227,7 @@ and infer_call env exp1 inst exp2 at t_opt = let t2 = infer_exp env exp2 in match (* i.e. exists_unique ts . t2 <: open_ ts t_arg /\ open ts_ t_arg <: t] *) - Bi_match.bi_match_typ (scope_of_env env) tbs + Bi_match.bi_match_subs (scope_of_env env) tbs [(t2, t_arg); (t_ret, t)] with | ts -> @@ -1239,7 +1239,7 @@ and infer_call env exp1 inst exp2 at t_opt = "cannot implicitly instantiate function of type\n %s\nto argument of type\n %s%s\n%s" (T.string_of_typ t1) (T.string_of_typ t2) - (if Option.is_none t_opt then "" + (if Option.is_none t_expect_opt then "" else Printf.sprintf "\nto produce result of type\n %s" (T.string_of_typ t)) msg in From 169a69c43b04b1b3868ea670611cce5bdc92ec97 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Thu, 5 Mar 2020 13:44:36 +0000 Subject: [PATCH 1105/1176] Update test/fail/inference.mo --- test/fail/inference.mo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/fail/inference.mo b/test/fail/inference.mo index 27ee39b857e..56df2755473 100644 --- a/test/fail/inference.mo +++ b/test/fail/inference.mo @@ -172,6 +172,6 @@ ignore choose_var(true,[var (1:Int)],[var (1:Int)]); ignore choose_var(true,[var (1:Nat)],[var (1:Int)]); // rejected as overconstrained (variance not applicable) // reject type components as (non denotable) instantiations -func select(o:object {x:T}):T{ o.x }; +func select(o:object {x : T }):T{ o.x }; ignore select(object {public let x=1}); ignore select(object {public type x = Nat}); // reject From a862a6f59e6786bf83ca048aaf1cea07773ee7ec Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 5 Mar 2020 16:15:36 +0100 Subject: [PATCH 1106/1176] ## Changelog for common: (#1256) Commits: [dfinity-lab/common@53663c49...f6428739](https://github.com/dfinity-lab/common/compare/53663c4957c0db10ce9bf8401ed768ad0cb8faa9...f6428739d40d1aea027d9679cc2c0439f34e5aed) * [`c45b5a11`](https://github.com/dfinity-lab/common/commit/c45b5a11390e2281273ce51bd5b78c270798412f) rust: 1.40 -> 1.41 * [`5917427e`](https://github.com/dfinity-lab/common/commit/5917427ed5233ef768f1d9991c28db6210510514) Backport LLVM 9 * [`9dce180b`](https://github.com/dfinity-lab/common/commit/9dce180bd4dad38ffb977915fe30c74ed5b61b70) nix/overlays/build-dfinity-rust-package.nix: set RUST_SRC_PATH * [`731b3a71`](https://github.com/dfinity-lab/common/commit/731b3a7118b299c60975982838039d1bb7802151) nix/overlays/build-dfinity-rust-package.nix: add rls to the shell * [`b862d595`](https://github.com/dfinity-lab/common/commit/b862d59500d7d02443dfc07deb5f45482b32960a) Revert "Backport LLVM 9" * [`be765138`](https://github.com/dfinity-lab/common/commit/be7651387f3fcb6490fcec1b3947e8ccb7e48dbe) Revert "rust: 1.40 -> 1.41" * [`bece15d3`](https://github.com/dfinity-lab/common/commit/bece15d3339b1414bad61f9b5431d2cf1ed747d1) .github: Add niv-updater workflow Co-authored-by: Joachim Breitner --- nix/sources.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/sources.json b/nix/sources.json index 822e646de3a..d4794a95d14 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -2,7 +2,7 @@ "common": { "ref": "master", "repo": "ssh://git@github.com/dfinity-lab/common", - "rev": "53663c4957c0db10ce9bf8401ed768ad0cb8faa9", + "rev": "f6428739d40d1aea027d9679cc2c0439f34e5aed", "type": "git" }, "dfinity": { From be8497e70bb75d9948abbff9868781ec48591add Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Thu, 5 Mar 2020 16:49:00 +0000 Subject: [PATCH 1107/1176] ## Changelog for common: (#1267) Commits: [dfinity-lab/common@f6428739...b7a8085f](https://github.com/dfinity-lab/common/compare/f6428739d40d1aea027d9679cc2c0439f34e5aed...b7a8085fd17a5a970be267245634099339186f7a) * [`46b5063f`](https://github.com/dfinity-lab/common/commit/46b5063f501a5ea9216edb43e7d49000c96ee189) Revert "Revert "Backport LLVM 9"" * [`69cc56e9`](https://github.com/dfinity-lab/common/commit/69cc56e9d5f6c53857e49039497f25b06abbfab9) Revert "Revert "rust: 1.40 -> 1.41"" * [`ba00b589`](https://github.com/dfinity-lab/common/commit/ba00b589d1ab4a454f68e12464f699813fd2a8a3) Use llvmPackages_9 in build-dfinity-rust-package --- nix/sources.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/sources.json b/nix/sources.json index d4794a95d14..31ed1144b7e 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -2,7 +2,7 @@ "common": { "ref": "master", "repo": "ssh://git@github.com/dfinity-lab/common", - "rev": "f6428739d40d1aea027d9679cc2c0439f34e5aed", + "rev": "b7a8085fd17a5a970be267245634099339186f7a", "type": "git" }, "dfinity": { From 71b3f980f118727a0ee924a2103c679d8f8ac560 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Thu, 5 Mar 2020 18:44:30 +0000 Subject: [PATCH 1108/1176] Suppress inference for explicitly empty instantiations (#1265) * modify ast & frontend to distinguish between empty instantiations that suppress inference and omitted ones that enable inference * fix test --- src/mo_def/arrange.ml | 4 +- src/mo_def/syntax.ml | 2 +- src/mo_frontend/parser.mly | 12 ++- src/mo_frontend/printers.ml | 1 + src/mo_frontend/typing.ml | 11 +-- test/fail/inference.mo | 159 +++++++++++++++++++---------------- test/fail/ok/inference.tc.ok | 20 +++-- test/fail/ok/syntax2.tc.ok | 2 +- test/fail/ok/syntax3.tc.ok | 2 +- test/fail/ok/syntax5.tc.ok | 2 +- test/fail/ok/syntax6.tc.ok | 2 +- 11 files changed, 122 insertions(+), 95 deletions(-) diff --git a/src/mo_def/arrange.ml b/src/mo_def/arrange.ml index bf1ee30e629..608e4bb5606 100644 --- a/src/mo_def/arrange.ml +++ b/src/mo_def/arrange.ml @@ -62,7 +62,9 @@ let rec exp e = match e.it with | ThrowE e -> "ThrowE" $$ [exp e] | TryE (e, cs) -> "TryE" $$ [exp e] @ List.map catch cs -and inst ts = List.map typ ts.it +and inst inst = match inst.it with + | None -> [] + | Some ts -> List.map typ ts and pat p = match p.it with | WildP -> Atom "WildP" diff --git a/src/mo_def/syntax.ml b/src/mo_def/syntax.ml index b497900da58..26acff60f97 100644 --- a/src/mo_def/syntax.ml +++ b/src/mo_def/syntax.ml @@ -118,7 +118,7 @@ and vis' = Public | Private type op_typ = Type.typ ref (* For overloaded resolution; initially Type.Pre. *) -type inst = (typ list, Type.typ list) Source.annotated_phrase (* For implicit scope instantiation *) +type inst = (typ list option, Type.typ list) Source.annotated_phrase (* For implicit scope instantiation *) type sort_pat = (Type.shared_sort * pat) Type.shared Source.phrase diff --git a/src/mo_frontend/parser.mly b/src/mo_frontend/parser.mly index 4b77721a739..6fc7fc727ce 100644 --- a/src/mo_frontend/parser.mly +++ b/src/mo_frontend/parser.mly @@ -175,6 +175,7 @@ let share_expfield (ef : exp_field) = %type catch case %type Mo_def.Syntax.exp'> bl ob %type import_list +%type inst %type start %start Mo_def.Syntax.prog> parse_prog @@ -310,6 +311,13 @@ typ_item : typ_args : | LT ts=seplist(typ, COMMA) GT { ts } +inst : + | (* empty *) + { { it = None; at = no_region; note = [] } } + | LT ts=seplist(typ, COMMA) GT + { { it = Some ts; at = at $sloc; note = [] } } + + %inline typ_params_opt : | (* empty *) { [] } | LT ts=seplist(typ_bind, COMMA) GT { ts } @@ -435,8 +443,8 @@ exp_post(B) : { ProjE (e, int_of_string s) @? at $sloc } | e=exp_post(ob) DOT x=id { DotE(e, x) @? at $sloc } - | e1=exp_post(ob) tso=typ_args? e2=exp_nullary(ob) - { CallE(e1, {it = Lib.Option.get tso []; at = no_region; note = []}, e2) @? at $sloc } + | e1=exp_post(ob) inst=inst e2=exp_nullary(ob) + { CallE(e1, inst, e2) @? at $sloc } exp_un(B) : | e=exp_post(B) diff --git a/src/mo_frontend/printers.ml b/src/mo_frontend/printers.ml index be9f319f26d..f317a021cbd 100644 --- a/src/mo_frontend/printers.ml +++ b/src/mo_frontend/printers.ml @@ -150,6 +150,7 @@ let string_of_symbol symbol : string = | X (N N_func_body) -> "" | X (N N_imp) -> "" | X (N N_import_list) -> "" + | X (N N_inst) -> "" | X (N N_lit) -> "" | X (N N_ob) -> "" | X (N N_obj_body) -> "" diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index a0165f5dc74..3cc49259f85 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -1201,10 +1201,10 @@ and check_exp' env0 t exp : T.typ = and infer_call env exp1 inst exp2 at t_expect_opt = let t = Lib.Option.get t_expect_opt T.Any in - let typs = inst.it in + let n = match inst.it with None -> 0 | Some typs -> List.length typs in let t1 = infer_exp_promote env exp1 in let sort, tbs, t_arg, t_ret = - try T.as_func_sub T.Local (List.length typs) t1 + try T.as_func_sub T.Local n t1 with Invalid_argument _ -> error env exp1.at "expected function type, but expression produces type\n %s" @@ -1212,18 +1212,19 @@ and infer_call env exp1 inst exp2 at t_expect_opt = in let ts, t_arg', t_ret' = match tbs, inst.it with - | [], [] -> (* no inference required *) + | [], (None | Some []) -> (* no inference required *) if not env.pre then check_exp env t_arg exp2; [], t_arg, t_ret | [{T.sort = T.Scope;_}], _ (* special case to allow t_arg driven overload resolution *) - | _, _::_ -> + | _, Some _ -> (* explicit instantiation, check argument against instantiated domain *) + let typs = match inst.it with None -> [] | Some typs -> typs in let ts = check_inst_bounds env tbs typs at in let t_arg' = T.open_ ts t_arg in let t_ret' = T.open_ ts t_ret in if not env.pre then check_exp env t_arg' exp2; ts, t_arg', t_ret' - | _::_, [] -> (* implicit or empty instantiation, infer *) (* TODO: distinguish explicit empty instantiation `<>` from omitted instantiation `` *) + | _::_, None -> (* implicit, infer *) let t2 = infer_exp env exp2 in match (* i.e. exists_unique ts . t2 <: open_ ts t_arg /\ open ts_ t_arg <: t] *) diff --git a/test/fail/inference.mo b/test/fail/inference.mo index 56df2755473..adde0dd542c 100644 --- a/test/fail/inference.mo +++ b/test/fail/inference.mo @@ -1,99 +1,99 @@ -func id(x:T):T { x }; +func id(x : T) : T { x }; ignore id(1); ignore id(1); -func swap(x:T,y:U):(U,T){(y,x)}; -ignore swap(1,true); -ignore swap(true,1); +func swap(x : T, y : U) : (U,T){(y,x)}; +ignore swap(1, true); +ignore swap(true, 1); -type N = (T->T,T)->T; +type N = (T->T, T)->T; -func zero(f:T->T,z:T):T{z}; +func zero(f : T->T, z : T) : T {z}; -func succ(n:N):N { - func (f:T->T,z:T) : T { f(n/**/(f,z))} +func succ(n : N) : N { + func (f : T->T, z:T) : T { f(n/**/(f,z))} }; ignore zero; ignore succ(zero); ignore succ(succ zero); -func app(f: T-> U, x:T) : U { f(x); }; +func app(f : T-> U, x : T) : U { f(x); }; -ignore app/**/(succ,zero); +ignore app/**/(succ,zero); -func compose(f: T -> U, g : U-> V) : T->V { func x { g (f(x))} }; +func compose(f: T -> U, g : U-> V) : T->V { func x { g (f(x))} }; -ignore compose((func(x:Int):Int=x),(func(x:Int):Int=x)); -ignore compose/**/(succ,succ); +ignore compose((func( x : Int) : Int = x),(func (x : Int) : Int = x)); +ignore compose/**/(succ, succ); -type List = ?(T,List); -type List2 = ?(T,List2); +type List = ?(T, List); +type List2 = ?(T, List2); func cons(h:T,t:List):List {?(h,t)}; func nil():List{ null }; ignore nil(); -ignore cons(1,nil()); -ignore cons(1,cons(2,nil())); -ignore cons(1,cons(2,null:List)); -ignore cons(1,cons(2,null:List2:List)); -ignore cons(1,cons(2,null:List2)); +ignore cons(1, nil()); +ignore cons(1, cons(2, nil())); +ignore cons(1, cons(2, null : List)); +ignore cons(1, cons(2, null : List2:List)); +ignore cons(1, cons(2, null : List2)); func curry(f : (A,B)->C) : A->B->C { func(a:A): B->C { func(b:B):C { f(a,b) } } }; -func add(m:N,n:N):N { m/**/(succ,n) }; +func add(m:N, n:N) : N { m/**/(succ,n) }; -func mult1(m:N,n:N):N { m/**/(func (a:N) : N { add(a,n)},zero) }; +func mult1(m:N, n:N): N { m/**/(func (a:N) : N { add(a,n)},zero) }; -func mult2(m:N,n:N):N { m/**/(curry/**/ add n, zero) }; +func mult2(m:N, n:N) : N { m/**/(curry/**/ add n, zero) }; func tricky(f : T -> T) { }; //explicit instantiation -tricky(func f(x:Any):None { f(x);}); -tricky(func f(x:Any):None { f(x);}); -tricky(func f(x:None):Any { f(x);}); // correctly rejected -tricky(func f(x:None):Any { f(x);}); // correctly rejected +tricky(func f(x : Any) : None { f(x);}); +tricky(func f(x : Any) : None { f(x);}); +tricky(func f(x : None) : Any { f(x);}); // correctly rejected +tricky(func f(x : None) : Any { f(x);}); // correctly rejected ignore func () { tricky(func f(x:Any):None{f(x)}) }; // implicit instantiation -ignore tricky(func f(x:Any):None { f(x);}); // fails, under-constrained -ignore tricky(func f(x:None):Any { f(x);}); // fails, inconsistent instantiation required. -ignore tricky(func f(x:None):None { f(x);}); +ignore tricky(func f(x : Any) : None { f(x);}); // fails, under-constrained +ignore tricky(func f(x : None) : Any { f(x);}); // fails, inconsistent instantiation required. +ignore tricky(func f(x : None) : None { f(x);}); func amb(f : T -> T): T->T { f }; -ignore amb(func f(x:Any):None { f(x);}) : None -> None; -ignore amb(func f(x:Any):None { f(x);}) : Any -> Any; +ignore amb(func f(x : Any) : None { f(x);}) : None -> None; +ignore amb(func f(x : Any) : None { f(x);}) : Any -> Any; -func co(x : T,y : T):(){}; -ignore co(1,2); -ignore co(1,2:Int); -ignore co(1,true); -ignore co(1,2); -ignore co(1,2:Int); -ignore co(1,true); +func co(x : T, y : T) : () {}; +ignore co(1, 2); +ignore co(1, 2 : Int); +ignore co(1, true); +ignore co(1, 2); +ignore co(1, 2:Int); +ignore co(1, true); -func contra(f:(T,T) -> ()):(){}; -ignore contra(func (x:Nat,y:Nat) {}); -ignore contra(func (x:Nat,y:Int) {}); -ignore contra(func (x:Nat,y:Bool) {}); -ignore contra(func (x:Nat,y:Nat) {}); -ignore contra(func (x:Nat,y:Int) {}); -ignore contra(func (x:Nat,y:Bool) {}); +func contra(f : (T,T) -> ()) : () {}; +ignore contra(func (x : Nat, y : Nat) {}); +ignore contra(func (x : Nat, y : Int) {}); +ignore contra(func (x : Nat, y : Bool) {}); +ignore contra(func (x : Nat, y : Nat) {}); +ignore contra(func (x : Nat, y : Int) {}); +ignore contra(func (x : Nat, y : Bool) {}); -func coswap(x : T,y : T):(U,U){(y,x)}; -ignore coswap(1,2); // rejected due to open bounds -ignore coswap(1,2:Int); // rejected due to open bounds -ignore coswap(1,true); // rejected due to open bounds +func coswap(x : T,y : T): (U, U) { (y, x)}; +ignore coswap(1, 2); // rejected due to open bounds +ignore coswap(1, 2 : Int); // rejected due to open bounds +ignore coswap(1, true); // rejected due to open bounds // support domain driven overloading for implicitly scoped, @@ -102,8 +102,8 @@ func f(g:shared Nat8 -> ()) : async () { g(1); }; -func bnd(x:T):T{x}; -ignore bnd(1:Int) : Int; +func bnd(x : T) : T { x }; +ignore bnd(1 : Int) : Int; ignore bnd(1) : Nat; // ok, uses expected type ignore (if false (bnd(loop {}):Nat) else 1); // ok, given expected type ignore (if false (bnd(loop {}):Int) else 1); @@ -121,57 +121,70 @@ scopecontra(func(x:V):V{x}); // reject due to scope violation //TODO: invariant mutables, constructor constraints, bail on open bounds // reject instantiations at `var _` (not denotable) -func sub(x:[T]):T{x[0]}; +func sub(x : [T]) : T { x[0] }; ignore sub([1]); sub([]); ignore sub([var 1]); // reject -func sub_mut(x:[var T]):T{x[0]}; +func sub_mut( x : [var T]) :T { x[0] }; sub_mut([1]); // reject ignore sub_mut([var 1]); // ok sub_mut([var 1]); // reject // tricky examples involving open typing with bounded parameters -func g(x:T) { - func f(y:U) {}; +func g(x : T) { + func f(y : U) {}; f(x); // reject, overconstrained U }; -func h(x:T) { - func f(y:U) {}; +func h(x : T) { + func f(y : U) {}; f(x); // reject, underconstrained U }; -func i(x:T) { - func f(y:U):U{y}; +func i(x : T) { + func f(y : U) : U {y}; ignore f(x); // accept }; -func j(x:T) { - func f(y:U):U{y}; +func j(x : T) { + func f( y : U) : U { y }; ignore f(x) : None; // fail (overconstrained) }; func k(x:T) { - func f(y:U):U{y}; + func f(y : U) : U { y }; ignore f(x) : T; }; // immutable arrays -func choose(b:Bool,x:[T],y:[T]):[T] {if b x else y}; -ignore choose(true,[1:Nat],[1:Nat]); -ignore choose(true,[1:Int],[1:Int]); -ignore choose(true,[1:Nat],[1:Int]); +func choose(b : Bool, x : [T], y : [T]) : [T] { if b x else y }; +ignore choose(true, [1 : Nat], [1 : Nat]); +ignore choose(true, [1 : Int], [1 : Int]); +ignore choose(true, [1 : Nat], [1 : Int]); // mutable arrays -func choose_var(b:Bool,x:[var T],y:[var T]):[var T] {if b x else y}; -ignore choose_var(true,[var (1:Nat)],[var (1:Nat)]); -ignore choose_var(true,[var (1:Int)],[var (1:Int)]); -ignore choose_var(true,[var (1:Nat)],[var (1:Int)]); // rejected as overconstrained (variance not applicable) +func choose_var(b : Bool, x : [var T], y : [var T]) : [var T] { if b x else y }; +ignore choose_var(true, [var (1:Nat)], [var (1:Nat)]); +ignore choose_var(true, [var (1:Int)], [var (1:Int)]); +ignore choose_var(true, [var (1:Nat)], [var (1:Int)]); // rejected as overconstrained (variance not applicable) // reject type components as (non denotable) instantiations -func select(o:object {x : T }):T{ o.x }; -ignore select(object {public let x=1}); +func select(o : object {x : T}) : T { o.x }; +ignore select(object {public let x = 1}); ignore select(object {public type x = Nat}); // reject + +// distinguish empty <> from omitted instantiation, no inference when empty +func fst((t, u) : (T, U)) : T{t}; +ignore fst((1, 2)); +ignore fst((1, 2)); +ignore fst<>((1, 2)); // reject + +// more return type driven inference (no need to instantiate nil()) +ignore nil<>() : List; // reject +ignore nil() : List; +ignore cons(1, nil()) : List; +ignore cons(1, cons(2, nil())) : List; + diff --git a/test/fail/ok/inference.tc.ok b/test/fail/ok/inference.tc.ok index 69e83483273..e75055be17a 100644 --- a/test/fail/ok/inference.tc.ok +++ b/test/fail/ok/inference.tc.ok @@ -1,13 +1,13 @@ -inference.mo:87.27-87.32: warning, this pattern is never matched -inference.mo:61.14-61.41: type error, expression of type +inference.mo:87.27-87.34: warning, this pattern is never matched +inference.mo:61.14-61.45: type error, expression of type None -> Any cannot produce expected type None -> None -inference.mo:62.13-62.40: type error, expression of type +inference.mo:62.13-62.44: type error, expression of type None -> Any cannot produce expected type Any -> Any -inference.mo:66.8-66.43: type error, cannot implicitly instantiate function of type +inference.mo:66.8-66.47: type error, cannot implicitly instantiate function of type (T -> T) -> () to argument of type Any -> None @@ -15,7 +15,7 @@ to produce result of type Any under-constrained implicit instantiation None <: T <: Any, with None =/= Any; explicit type instantiation required -inference.mo:67.8-67.43: type error, cannot implicitly instantiate function of type +inference.mo:67.8-67.47: type error, cannot implicitly instantiate function of type (T -> T) -> () to argument of type None -> Any @@ -23,7 +23,7 @@ to produce result of type Any over-constrained implicit instantiation requires Any <: T <: None, but Any (T, T) -> (U, U) to argument of type (Nat, Nat) @@ -31,7 +31,7 @@ to produce result of type Any type parameter T has an open bound U mentioning another type parameter; explicit type instantiation required due to limitation of inference -inference.mo:95.8-95.23: type error, cannot implicitly instantiate function of type +inference.mo:95.8-95.26: type error, cannot implicitly instantiate function of type (T, T) -> (U, U) to argument of type (Nat, Int) @@ -39,7 +39,7 @@ to produce result of type Any type parameter T has an open bound U mentioning another type parameter; explicit type instantiation required due to limitation of inference -inference.mo:96.8-96.22: type error, cannot implicitly instantiate function of type +inference.mo:96.8-96.23: type error, cannot implicitly instantiate function of type (T, T) -> (U, U) to argument of type (Nat, Bool) @@ -123,7 +123,7 @@ to produce result of type None over-constrained implicit instantiation requires T <: U <: None, but T (Bool, [var T], [var T]) -> [var T] to argument of type (Bool, [var Nat], [var Int]) @@ -138,3 +138,5 @@ to argument of type to produce result of type Any no instantiation of T makes {type x = Nat} <: {x : T} and T <: Any +inference.mo:183.8-183.21: type error, too few type arguments +inference.mo:186.8-186.15: type error, too few type arguments diff --git a/test/fail/ok/syntax2.tc.ok b/test/fail/ok/syntax2.tc.ok index ba89d9d6bb9..b28bc7454ce 100644 --- a/test/fail/ok/syntax2.tc.ok +++ b/test/fail/ok/syntax2.tc.ok @@ -14,5 +14,5 @@ expected one of token or sequence: and - ? + [ ] diff --git a/test/fail/ok/syntax3.tc.ok b/test/fail/ok/syntax3.tc.ok index b0ad3b7859a..2c10bd52a62 100644 --- a/test/fail/ok/syntax3.tc.ok +++ b/test/fail/ok/syntax3.tc.ok @@ -14,5 +14,5 @@ expected one of token or sequence: and - ? + [ ] diff --git a/test/fail/ok/syntax5.tc.ok b/test/fail/ok/syntax5.tc.ok index 97d94d0ea1f..7bf4f6b208d 100644 --- a/test/fail/ok/syntax5.tc.ok +++ b/test/fail/ok/syntax5.tc.ok @@ -14,5 +14,5 @@ expected one of token or sequence: and - ? + [ ] diff --git a/test/fail/ok/syntax6.tc.ok b/test/fail/ok/syntax6.tc.ok index 1a893de3e5a..ca95a6bc7d7 100644 --- a/test/fail/ok/syntax6.tc.ok +++ b/test/fail/ok/syntax6.tc.ok @@ -14,5 +14,5 @@ expected one of token or sequence: and - ? + [ ] From 2967ef5601f3d910f8d0523110c690bcc4617d1f Mon Sep 17 00:00:00 2001 From: DFINITY bot <58022693+dfinity-bot@users.noreply.github.com> Date: Fri, 6 Mar 2020 17:14:41 +0100 Subject: [PATCH 1109/1176] ## Changelog for common: (#1269) Commits: [dfinity-lab/common@b7a8085f...79a7acd2](https://github.com/dfinity-lab/common/compare/b7a8085fd17a5a970be267245634099339186f7a...79a7acd25142e621854d787d5bcfe375af4712f8) * [`220cf074`](https://github.com/dfinity-lab/common/commit/220cf0742b2bfab81f2a68946cee147ebd1544b4) upgrade naersk to set RUST_TEST_THREADS=$NIX_BUILD_CORES --- nix/sources.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/sources.json b/nix/sources.json index 31ed1144b7e..aaf7b33271e 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -2,7 +2,7 @@ "common": { "ref": "master", "repo": "ssh://git@github.com/dfinity-lab/common", - "rev": "b7a8085fd17a5a970be267245634099339186f7a", + "rev": "79a7acd25142e621854d787d5bcfe375af4712f8", "type": "git" }, "dfinity": { From 4aacf9d13ad78f7a1ff14c84d3c2f2de7f69c1ab Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 6 Mar 2020 17:44:17 +0100 Subject: [PATCH 1110/1176] Mergify: Auto-approve PRs by dfinity-bot (#1271) --- .mergify.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.mergify.yml b/.mergify.yml index ea04825f814..5b92265c286 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -20,3 +20,11 @@ pull_request_rules: - automerge - automerge-squash - automerge-rebase + - name: Auto-approve auto-PRs + conditions: + - author=dfinity-bot + actions: + review: + type: APPROVE + message: This bot trusts that bot + From 49866f781313e688572398d92d25b350cd9e2b20 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 6 Mar 2020 18:12:55 +0100 Subject: [PATCH 1111/1176] Bump drun (#1248) * Bump drun mostly to see how well we work with their upgrade support. Also included: ``` 17507c070 Merge pull request #2717 from dfinity-lab/paulliu/registry-config 86f652e66 Merge pull request #2733 from dfinity-lab/drun-upgrade b9d312500 State Manager: improve docs for the interface (#2719) 82618cf9b Move canister_init from hypervisor into ExecutionEnvironment (#2721) 297bf56bc Remove unnecessary inputs 9db1edb76 Move cargo executables to overlay 54764e227 INF-1013: Add tarpaulin to shell 0c8cc2356 Make CompiledBinary optional in CanisterState (#2713) 9a2b9af38 drun logging: require a command line argument (#2714) 271067cd2 DFN-1392 Rename OutputStream to Stream (as per the spec) (#2707) 9301cf7e2 Merge pull request #2718 from dfinity-lab/wasmtime_signal_stack d63647ae5 Merge pull request #2716 from dfinity-lab/paulliu/tmux-resume-test d88f80238 Merge pull request #2702 from dfinity-lab/useAsRefInsteadOfCustomTrait aae50392b Merge pull request #2546 from dfinity-lab/david-new-persistence 263bd51d8 Merge pull request #2700 from dfinity-lab/skaestle/fix-perf-tests 9dcfc4100 Use byte literal for rust 1.41 6fc1050bb Merge pull request #2641 from dfinity-lab/rsub/xport-config-check 33f656002 Adding keys for multi-sigs to registry's CryptoKey (#2692) 70144dfff DFN-1366: Introduce RwLock and Locking Layer for Keygen (#2675) 0a3c981b6 Merge pull request #2604 from dfinity-lab/messageMakerSkeleton c20870ada Merge pull request #2659 from dfinity-lab/dkgStateReader 17ed1b65d [P2P-184] Restructuring Ingress Pool (#2625) d60dd78c4 DFN-1318 Don't panic on full input queue (#2686) de423fdef Adding logging capability to drun (#2679) 56c43abf5 Merge pull request #2682 from dfinity-lab/kw/sort-deps 9b3f3566c Make ic_crypto path configurable (#2655) c40d741fc Merge pull request #2654 from dfinity-lab/paulliu/temp-fix-of-state-purging 240baab79 DFN-1244: Use RawIngress as the content of SignedIngress (#2438) a4c481668 Merge pull request #2683 from dfinity-lab/mw/better-test-panic-message 318798a8e Merge pull request #2621 from dfinity-lab/CON-288 e4610188b [DFN-1388] Use prometheus metrics in StateManager 4ba0243a2 DFN-1358: Call upgrade hooks in canister upgrades. (#2676) 733a51143 Merge pull request #2668 from dfinity-lab/dsd/remove_unused_metric b35786c79 DFN-1358 Add support for canister upgrade system methods in hypervisor (#2651) 5f22c697d Add local testnet scripts (#2657) 86ea90d5d Merge pull request #2658 from dfinity-lab/rsub/fake-transport 1c060d5c1 Merge pull request #2656 from dfinity-lab/paulliu/fix-test-randomness 7e078dfbc StateManager: a tool for inspecting states (#2664) 2d3eeed9b StateManager: add certification API (#2650) adecfe2c0 Merge pull request #2660 from dfinity-lab/cryptoSigningAndHashingOfDKGTypes 2055a6014 Merge pull request #2529 from dfinity-lab/addGetRange e4f188c7a DFN-1365: Remove `mut` modifiers in DKG API (#2596) 51604d499 Merge pull request #2559 from dfinity-lab/johnw/fork 2201d561b Deterministic NaNs in the replica (#2549) c77ea1ed3 CON-230: proptests for pool purger (#2525) 7c2ad9cfe DFN-1376: Use references in DKG API rather than taking ownership (#2640) 267e1611f DFN-769: Remove message-type-to-params from Crypto Config (#2597) b7d9b4869 Fixed warnings in library code (#2649) df31d3cdf Made it so macro errors never cause a panic in the nightly compiler (#2648) 52ec588eb Crypto/DFN-1152: Factor out bls core (#2619) 3ba184507 Merge pull request #2613 from dfinity-lab/manu/delete-consensus-config-trait db0f952f1 DFN-1318 Return message when enqueuing fails (#2647) 250bef54e DFN-1354 & DFN-1357 Fixes to canister creation. 65ea63214 DFN-1147: Remove Signature in Types Crate (#2591) afd9a0459 Scheduler should execute messages if remaining gas is exactly exec_gas (#2633) d6711e271 Merge pull request #2629 from dfinity-lab/kw/wasmtime-integration 151ae697e DFN-1343: Construct hash tree from replicated state (#2583) 78d7569eb Rename allocation to compute_allocation (#2634) 16425864c DFN-1374 Improved cross-crate test-only methods (#2612) a9f42c202 DFN-1374 Test CanisterState method preconditions. (#2628) 64ad9fa48 Add more bits of state to canonical state traversal (#2589) e643e0b2f Merge pull request #2617 from dfinity-lab/manu/remove-function-from-xnet-selector-trait 2b16a69f0 Merge pull request #2626 from dfinity-lab/mw/remove-mutable-globals-validation 6a9a41ff7 DFN-1374 Simplify queue reservations. Add doc comments. (#2611) 0aad82b23 CON-238 RandomGraph delivery strategy for consensus test framework (#2558) a639f3b80 Merge pull request #2501 from dfinity-lab/david-split-in-memory-pool 488f8488a DFN-1367: Make DkgAlgorithm trait object-safe (#2603) f6a23fa57 Merge pull request #2572 from dfinity-lab/fs/taketransportimpl 83fffa587 Merge pull request #2602 from dfinity-lab/rsub/tokio-upgrade 00018a47e Crypto/DFN-1333: basic sig cli (#2550) b85ba8db7 Linking wasm files was failing on some Linux systems (#2599) e2dbf9c8a Add --benches in dcheck (#2587) 445b9ed2b DFN-1374 Use CanisterQueues instead of {Ingress|Input|Output}Queue directly (#2562) 34996c264 Merge pull request #2570 from dfinity-lab/fs/metricgauge 8d0c109a5 Merge pull request #2360 from dfinity-lab/dedup-by-attribute 6846d748d Fixed a few typos (#2600) b34e591ea SigsegvMemoryTracker: Perf improvement (#2590) 9821a1aa4 Overhaul SystemApiImpl (#2571) 3b153fd03 Squashed crypto/DFN-1152-clib-threshold-commitments from 1ed9097bca94d024ff1f75d8cf189cc482d87ef9 (#2444) 7ad8d66d2 Bump mockall from 0.5.0 to 0.6.0. This gets rid of all the clippy warnings when compiling with Rust 1.41.0. (See https://github.com/rust-lang/rust/issues/66145 and https://github.com/asomers/mockall/pull/62 for context.) (#2573) 9d2990f55 Provide conversion from Request or Response to RequestOrResponse. (#2575) 732337679 Implement ++ and -- (equivalents) for AmountOf. (#2574) 058fe36f2 Merge pull request #2560 from dfinity-lab/rsub/xport-handshake b85f967ed Merge pull request #2567 from dfinity-lab/dsd/comment_fix 534971043 DFN-1147: Remove obsolete Signer trait (#2561) 1bfae2097 Crypto/DFN-1338: move existing toplevel code (#2541) d38ff772e Crypto DFN:1331 cli hash tweaks (#2553) 6539d8e42 Merge pull request #2548 from dfinity-lab/skaestle/bench-execution-update 6170f2fd4 Remove scheduler flaky test (#2563) a674e871b crypto/DFN-962: adding a signature verification test with an invalid public key (#2552) dc8fd4474 [DFN-1325] Support upgrading canisters (#2555) eab3250b7 DFN-1374 Address review comments for #2531 (#2556) cee79cb33 config 23516fa17 Revert "Update config sample" 9e6be014c Update config sample 9c1e53f7d Copy helper function bf732aae8 Sort 8c1c1c072 Rename Config to EmbedderConfig, flatten namespace 814896c2e Move Lucet embedder 00063c079 Cleanup bcd569db8 Merge pull request #2349 from dfinity-lab/cleanerDefinitionForCommitteeThreshold b521d3e05 Removed a very noisey debug statement (#2554) 86cf72361 instrumentation: table/memory export for wasmtime; DFN-1296, DFN-1297 (#2518) 06665ee1e DFN-1242: Add proptest for verifying the scheduling algorithm (#2535) 023626da1 Better FakeIngressSelector (#2483) 864c39a7f MessageId: use LEB128 for numbers to compute message ids (#2462) e9b00daab Merge pull request #2489 from dfinity-lab/kb/resumability cabbe8f28 Tidying up of `struct ExecutionEnvironment` (#2499) 53d2495ee Merge pull request #2543 from dfinity-lab/dsd/user_query_send_sync 1ae25197b Merge pull request #2530 from dfinity-lab/CON-273 4b2fd5d19 Update wabt to 0.9.2 (#2540) 111dceebf [DFN-1325] Add 'mode' to CanisterInstallMessage (#2522) be49ce40b crypto/DFN-962: adding tests with invalid signatures (#2527) 52ef1e349 Make recover_checkpoint public (#2542) 1a085fa00 Crypto/dfn 1331 hashing cli (#2482) ec87b969c Merge pull request #2511 from dfinity-lab/skaestle/bench-user-calls f812d7073 crypto/DFN-1152: clib-threshold-polynomial-tweaks (#2526) 8c535a7d4 Merge pull request #2510 from dfinity-lab/manu/rephrase-aggregate-function 9c94226aa DFN-1374 Introduce CanisterQueues type, a wrapper around ingress queue, input queues and output queues. (#2531) 9042b870c Merge pull request #2533 from dfinity-lab/wasmtime-embedder e360b013e Merge pull request #2450 from dfinity-lab/dkgTypes 1496261d3 DFN-1281: Allow CSPRNG creation based on randomness purpose (#2440) 172925c8b Merge pull request #2515 from dfinity-lab/CON-269 31b38b340 Merge pull request #2492 from dfinity-lab/paulliu/test-execution-height-unavailable e65501c72 DFN-1374 Rename `Canister{Input|Output}Queue` to `{Input|Output}Queue` (#2524) 91f3ce958 Group tests in message_id/src/lib.rs (#2523) 6ad5597fc Merge pull request #2512 from dfinity-lab/chmllr/minor-improvements ca151a444 Crypto/DFN:1327 restructure clib (#2484) 724b3c27a Alphabetize members in top level Cargo.toml (#2497) e6f836a85 Merge pull request #2473 from dfinity-lab/rsub/xport-ports-1 c36e4cc88 Merge pull request #2493 from dfinity-lab/generalizePoolReaderFunctions ``` * Update test output * More bumping ``` 4baa063b5 Merge pull request #2729 from dfinity-lab/rsub/conn-event 585832cc7 Merge pull request #2737 from dfinity-lab/basvandijk/do-not-use-tmp-persistent-pool 24407308a Renaming some SigSegv and the MemoryTracker fields (#2726) d8534a766 Merge pull request #2728 from dfinity-lab/proptest_fixes ``` * Bump drun some more ``` 0da721854 Merge pull request #2786 from dfinity-lab/ops-15 811fb9098 DFN-1366: Adapt Crypto Initialization for Multi-Threading (#2723) 53b33f512 Verify alternative options in the sample config (#2632) c018ee387 Merge pull request #2774 from dfinity-lab/bump_crossbeam aed2a1aab P2P-201: Fix bug in exists() in ingress_pool (#2762) 25738a992 Merge pull request #2761 from dfinity-lab/CON-304 10019d068 Memory tracker bench performance regression (#2755) cf38daa45 Merge pull request #2335 from dfinity-lab/johnw/simulator 41810e84d Add the random tape and random tape share types (#2745) c5e03bf4d Merge pull request #2642 from dfinity-lab/david-persistence-integration 1edb79452 Rename available_compute_allocation to compute_capacity (#2767) 49e0fab77 Merge pull request #2645 from dfinity-lab/dkgPayloadBuilder 1614d6063 DFN-1392 Use BTreeMap for ReplicatedState::canister_states (#2760) 8ff08dd95 Merge pull request #2764 from dfinity-lab/sort-deps d4f93a91b Merge pull request #2743 from dfinity-lab/manu/proptest c42df7c33 Add more context to assertions in canister state (#2747) 538c312c5 DFN-1366: Create Locking Layer for 'sign' Module (#2704) 4ee54534e Fix for a bench regression introduced in 24407308a (#2750) 259b3d7ed CON-284: adds initial certification plumbing (#2636) ``` * Bump drun more ``` 9f947598f Deprecate mod.rs in ic-execution-environment (#2815) cca358af8 Fix doc test in crypto (#2814) da5873fce Get rid of circular dependencies involving ic-test-utilities (#2789) fc752ed9c Cleanup benchmark (#2806) d02cd2744 +=libsecp256k1 crate (#2797) 3317f2d45 CON-299: certification: implement certification pool and artifact validation (#2771) fc6689046 CON-284: implements certification aggregation (#2725) 9f200004c Update tests (#2689) 83b945b5f Merge pull request #2775 from dfinity-lab/mw/wasmtime-new-system-api 2daf8a232 Merge pull request #2777 from dfinity-lab/paulliu/catchup-types ede968e55 Merge pull request #2805 from dfinity-lab/johnw/logsimpl 2fb5f2cda Merge pull request #2802 from dfinity-lab/dsd/make_http_config_more_readable 28556dd6b DFN-1414 Fix failures in executor (#2778) d8a20bbac - remove obsolete CspSigner methods (#2794) 7e8796197 Crypto/DFN-1220: Use RegistryView instead of PublicKeyRegistry in crypto component. (#2720) b6e046fd7 Merge pull request #2791 from dfinity-lab/mw/trap-to-error-signature-mismatch b145ad66a Merge pull request #2792 from dfinity-lab/paulliu/fix-localnet-conf 28c02a566 Crypto (DFN-1152): clib-threshold-crypto (#2661) 19582dba5 Merge pull request #2790 from dfinity-lab/remove_size_log 8a68ed5fd Merge pull request #2739 from dfinity-lab/paulliu/test-with-persistence-feature ``` --- nix/sources.json | 4 ++-- test/run-drun/ok/caller.drun-run.ok | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/nix/sources.json b/nix/sources.json index aaf7b33271e..2e43381f78f 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -6,9 +6,9 @@ "type": "git" }, "dfinity": { - "ref": "v0.5.0", + "ref": "master", "repo": "ssh://git@github.com/dfinity-lab/dfinity", - "rev": "fc1706faada19c3bcf0eee941b0468bf0c312d00", + "rev": "9f947598f82d7782a3da4e6c0cf8a7b3ac6d5947", "type": "git" }, "esm": { diff --git a/test/run-drun/ok/caller.drun-run.ok b/test/run-drun/ok/caller.drun-run.ok index b2226da639a..f9fad751194 100644 --- a/test/run-drun/ok/caller.drun-run.ok +++ b/test/run-drun/ok/caller.drun-run.ok @@ -4,7 +4,7 @@ ingress Completed: Canister: Payload: 0x4449444c0000 ingress Completed: Canister: Payload: 0x4449444c0000 ingress Completed: Canister: Payload: 0x4449444c0000 Ok: Payload: 0x4449444c0000 -ingress Completed: Canister: Payload: 0x4449444c016d7b0100020101 +ingress Completed: Canister: Payload: 0x4449444c016d7b010021af5570f5a1810b7af78caf4bc70a660f0df51e42baf91d4de5b2328de0e83dfc02 Ok: Payload: 0x4449444c0001792813c52f Ok: Payload: 0x4449444c00017d02 Ok: Payload: 0x4449444c016e7b01000101 From a856438d94465a5f9d0f97ad9e7281601ae88318 Mon Sep 17 00:00:00 2001 From: Yan Chen <48968912+chenyan-dfinity@users.noreply.github.com> Date: Fri, 6 Mar 2020 12:13:57 -0800 Subject: [PATCH 1112/1176] Add Principal to IDL (#1268) * refactor mo_to_idl to use open_ * refactor * add principal type * update doc * update js function * codegen * fix * Apply suggestions from code review Co-Authored-By: Joachim Breitner * skip typ for fields * fix Co-authored-by: Joachim Breitner --- design/IDL-Motoko.md | 2 + src/codegen/compile.ml | 19 ++-- src/idllib/arrange_idl.ml | 2 + src/idllib/compile_js.ml | 8 +- src/idllib/lexer.mll | 1 + src/idllib/parser.mly | 3 +- src/idllib/syntax.ml | 1 + src/idllib/typing.ml | 1 + src/mo_idl/idl_to_mo.ml | 1 + src/mo_idl/mo_to_idl.ml | 136 +++++++++++--------------- test/idl/ok/fields.js.ok | 8 +- test/idl/ok/import3.js.ok | 4 +- test/idl/ok/principal.js.ok | 4 + test/idl/ok/recursion.js.ok | 4 +- test/idl/ok/test.js.ok | 4 +- test/idl/ok/unicode.js.ok | 4 +- test/idl/principal.did | 3 + test/mo-idl/ok/fun_self_arg.did.ok | 2 +- test/mo-idl/ok/prelude.did.ok | 6 +- test/mo-idl/ok/principal.did.ok | 3 + test/mo-idl/principal.mo | 6 ++ test/run-drun/ok/caller.drun-run.ok | 2 +- test/run-drun/ok/caller.ic-ref-run.ok | 2 +- 23 files changed, 118 insertions(+), 108 deletions(-) create mode 100644 test/idl/ok/principal.js.ok create mode 100644 test/idl/principal.did create mode 100644 test/mo-idl/ok/principal.did.ok create mode 100644 test/mo-idl/principal.mo diff --git a/design/IDL-Motoko.md b/design/IDL-Motoko.md index cbadb4cf662..a515eccf6b1 100644 --- a/design/IDL-Motoko.md +++ b/design/IDL-Motoko.md @@ -85,6 +85,7 @@ e(Word) = nat for n = 8, 16, 32, 64 e(Float) = float64 e(Char) = nat32 e(Text) = text +e(Principal) = principal e({ ;* }) = record { ef();* } e(variant { ;* }) = variant { ef();* } e([]) = vec (e()) @@ -139,6 +140,7 @@ i(record { ;* }) = { if();* } i(variant { ;* }) = variant { ivf();* } i(func ) = ifn() i(service { ;* }) = actor { im();* } +i(principal) = Principal if : -> if( : ) = escape() : i() diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 442520c7e82..dfb1975a5a3 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -3496,6 +3496,7 @@ module Serialization = struct (* NB: Prim Blob does not map to a primitive IDL type *) | Any -> Some 16 | Non -> Some 17 + | Prim Principal -> Some 24 | _ -> None let type_desc env ts : string = @@ -3572,7 +3573,7 @@ module Serialization = struct let rec add_typ t = match t with | Non -> assert false - | Prim (Blob|Principal) -> + | Prim Blob -> add_typ Type.(Array (Prim Word8)) | Prim _ -> assert false | Tup ts -> @@ -3694,7 +3695,7 @@ module Serialization = struct get_x ^^ get_i ^^ Arr.idx env ^^ load_ptr ^^ size env t ) - | Prim (Blob|Principal) -> + | Prim Blob -> let (set_len, get_len) = new_local env "len" in get_x ^^ Heap.load_field Blob.len_field ^^ set_len ^^ size_word env get_len ^^ @@ -3723,7 +3724,7 @@ module Serialization = struct inc_data_size (compile_unboxed_const 1l) ^^ (* one byte tag *) get_x ^^ Arr.load_field 0l ^^ size env (Obj (Actor, [])) ^^ get_x ^^ Arr.load_field 1l ^^ size env (Prim Text) - | Obj (Actor, _) -> + | Obj (Actor, _) | Prim Principal -> inc_data_size (compile_unboxed_const 1l) ^^ (* one byte tag *) get_x ^^ size env (Prim Blob) | Non -> @@ -3851,7 +3852,7 @@ module Serialization = struct ) ( List.mapi (fun i (_h, f) -> (i,f)) (sort_by_hash vs) ) ( E.trap_with env "serialize_go: unexpected variant" ) - | Prim (Blob|Principal) -> + | Prim Blob -> let (set_len, get_len) = new_local env "len" in get_x ^^ Heap.load_field Blob.len_field ^^ set_len ^^ write_word get_len ^^ @@ -3870,7 +3871,7 @@ module Serialization = struct write_byte (compile_unboxed_const 1l) ^^ get_x ^^ Arr.load_field 0l ^^ write env (Obj (Actor, [])) ^^ get_x ^^ Arr.load_field 1l ^^ write env (Prim Text) - | Obj (Actor, _) -> + | Obj (Actor, _) | Prim Principal -> write_byte (compile_unboxed_const 1l) ^^ get_x ^^ write env (Prim Blob) | Non -> @@ -4048,9 +4049,15 @@ module Serialization = struct (* Any vanilla value works here *) Opt.null - | Prim (Blob|Principal) -> + | Prim Blob -> assert_blob_typ env ^^ read_blob () + | Prim Principal -> + assert_prim_typ t ^^ + read_byte_tagged + [ E.trap_with env "IDL error: unexpected principal reference" + ; read_blob () + ] | Prim Text -> assert_prim_typ t ^^ read_text () diff --git a/src/idllib/arrange_idl.ml b/src/idllib/arrange_idl.ml index 64079be0000..cae44844dab 100644 --- a/src/idllib/arrange_idl.ml +++ b/src/idllib/arrange_idl.ml @@ -55,6 +55,7 @@ and typ t = match t.it with | VariantT cts -> "VariantT" $$ List.map typ_field cts | FuncT (ms, s, t) -> "FuncT" $$ List.map typ s @ List.map typ t @ List.map mode ms | ServT ts -> "ServT" $$ List.map typ_meth ts + | PrincipalT -> Atom "PrincipalT" | PreT -> Atom "PreT" and dec d = match d.it with @@ -100,6 +101,7 @@ let rec pp_typ ppf t = pp_print_break ppf 0 (-2); str ppf "}"; pp_close_box ppf () + | PrincipalT -> str ppf "principal" | PreT -> assert false); pp_close_box ppf () and pp_fields ppf name fs = diff --git a/src/idllib/compile_js.ml b/src/idllib/compile_js.ml index d1558110dfc..e41699c10df 100644 --- a/src/idllib/compile_js.ml +++ b/src/idllib/compile_js.ml @@ -19,6 +19,7 @@ let chase_env env actor = let rec chase t = match t.it with | PrimT _ -> () + | PrincipalT -> () | VarT id -> if not (TS.mem id.it !seen) then begin seen := TS.add id.it !seen; @@ -46,6 +47,7 @@ let infer_rec env_list = let rec go t = match t.it with | PrimT _ -> () + | PrincipalT -> () | VarT id -> if not (TS.mem id.it !seen) then begin seen := TS.add id.it !seen; @@ -86,7 +88,7 @@ let pp_prim p = | Float64 -> "Float64" | Bool -> "Bool" | Text -> "Text" - | Null -> "Unit" + | Null -> "Null" | Reserved -> "None" | Empty -> "None" @@ -106,6 +108,7 @@ let rec pp_typ ppf t = (match t.it with | VarT s -> id ppf s | PrimT p -> str ppf ("IDL."^(pp_prim p)) + | PrincipalT -> str ppf "IDL.Principal" | RecordT ts -> pp_fields ppf ts | VecT t -> str ppf "IDL.Vec("; pp_typ ppf t; str ppf ")"; | OptT t -> str ppf "IDL.Opt("; pp_typ ppf t; str ppf ")"; @@ -120,8 +123,7 @@ let rec pp_typ ppf t = str ppf ")"; | ServT ts -> pp_open_hovbox ppf 1; - kwd ppf "new"; - str ppf "IDL.ActorInterface({"; + str ppf "IDL.Service({"; concat ppf pp_meth "," ts; str ppf "})"; pp_close_box ppf (); diff --git a/src/idllib/lexer.mll b/src/idllib/lexer.mll index 6cc856a2955..7c3210b1416 100644 --- a/src/idllib/lexer.mll +++ b/src/idllib/lexer.mll @@ -130,6 +130,7 @@ rule token = parse | "record" { RECORD } | "variant" { VARIANT } | "blob" { BLOB } + | "principal" { PRINCIPAL } | id as s { ID s } diff --git a/src/idllib/parser.mly b/src/idllib/parser.mly index 09562ac19fe..b6d610fddaa 100644 --- a/src/idllib/parser.mly +++ b/src/idllib/parser.mly @@ -54,7 +54,7 @@ let record_fields fs = %token LPAR RPAR LCURLY RCURLY %token ARROW -%token FUNC TYPE SERVICE IMPORT +%token FUNC TYPE SERVICE IMPORT PRINCIPAL %token SEMICOLON COMMA COLON EQ %token OPT VEC RECORD VARIANT BLOB %token NAT @@ -92,6 +92,7 @@ prim_typ : ref_typ : | FUNC t=func_typ { t } | SERVICE ts=actor_typ { ServT ts @@ at $sloc } + | PRINCIPAL { PrincipalT @@ at $sloc } field_typ : | n=NAT COLON t=data_typ diff --git a/src/idllib/syntax.ml b/src/idllib/syntax.ml index 41f3912c421..8807122902c 100644 --- a/src/idllib/syntax.ml +++ b/src/idllib/syntax.ml @@ -40,6 +40,7 @@ and typ' = | RecordT of typ_field list (* record *) | VariantT of typ_field list (* variant *) | ServT of typ_meth list (* service reference *) + | PrincipalT | PreT (* pre-type *) and typ_field = typ_field' Source.phrase diff --git a/src/idllib/typing.ml b/src/idllib/typing.ml index 0803dda4c9d..2f2b3cf6bb5 100644 --- a/src/idllib/typing.ml +++ b/src/idllib/typing.ml @@ -111,6 +111,7 @@ let check_cycle env = let rec check_typ env t = match t.it with | PrimT prim -> t + | PrincipalT -> t | VarT id -> ignore (find_type env id); t | FuncT (ms, t1, t2) -> let t1' = List.map (fun t -> check_typ env t) t1 in diff --git a/src/mo_idl/idl_to_mo.ml b/src/mo_idl/idl_to_mo.ml index b2b06b91800..d260ed68d4a 100644 --- a/src/mo_idl/idl_to_mo.ml +++ b/src/mo_idl/idl_to_mo.ml @@ -49,6 +49,7 @@ let is_tuple fs = let rec check_typ env t = match t.it with | PrimT p -> check_prim p + | PrincipalT -> M.Prim M.Principal | VarT {it=id; _} -> (match M.Env.find_opt id !m_env with | None -> diff --git a/src/mo_idl/mo_to_idl.ml b/src/mo_idl/mo_to_idl.ml index 1c2a4d2d4dd..2e99cbf11a1 100644 --- a/src/mo_idl/mo_to_idl.ml +++ b/src/mo_idl/mo_to_idl.ml @@ -1,40 +1,39 @@ open Mo_types open Mo_types.Type open Source -open Printf module E = Mo_def.Syntax module I = Idllib.Syntax let env = ref Env.empty + (* For monomorphization *) -let stamp = ref Env.empty -(* can you replace this by a map with domain (Con.name) = string, ordered by Con.compare and implicit codomain int (or even int ref) *) +module Stamp = Map.Make(String) +let stamp = ref Stamp.empty + +module TypeMap = Map.Make (struct type t = con * typ list let compare = compare end) +let type_map = ref TypeMap.empty -let type_map = ref Env.empty -(* can you replace this by a map with domain (con * typ list), ordered by -compare and implicit codomain int *) - let normalize str = let illegal_chars = ['-'; '/';] in String.map (fun c -> if List.mem c illegal_chars then '_' else c) str -let string_of_con vs c = - let name = string_of_con c in (* maybe use Con.name instead, excluding the stamp *) +let monomorphize_con vs c = + let name = Con.name c in match Con.kind c with | Def ([], _) -> normalize name - | Def (tbs, _) -> - let id = sprintf "%s<%s>" name (String.concat "," (List.map string_of_typ vs)) in + | Def _ -> + let id = (c, vs) in let n = - match Env.find_opt id !type_map with + match TypeMap.find_opt id !type_map with | None -> - (match Env.find_opt name !stamp with + (match Stamp.find_opt name !stamp with | None -> - stamp := Env.add name 1 !stamp; - type_map := Env.add id 1 !type_map; + stamp := Stamp.add name 1 !stamp; + type_map := TypeMap.add id 1 !type_map; 1 | Some n -> - stamp := Env.add name (n+1) !stamp; - type_map := Env.add id (n+1) !type_map; + stamp := Stamp.add name (n+1) !stamp; + type_map := TypeMap.add id (n+1) !type_map; n+1) | Some n -> n in Printf.sprintf "%s_%d" (normalize name) n @@ -62,65 +61,52 @@ let prim p = | Char -> I.PrimT I.Nat32 | Text -> I.PrimT I.Text | Blob -> I.VecT (I.PrimT I.Nat8 @@ no_region) - | Principal -> I.VecT (I.PrimT I.Nat8 @@ no_region) (* could also be an empty service? *) + | Principal -> I.PrincipalT | Error -> assert false -let rec typ vs t = +let rec typ t = (match t with | Any -> I.PrimT I.Reserved | Non -> I.PrimT I.Empty | Prim p -> prim p - | Var (s, i) -> - (* matching on Var is dubious - - ideally we should use [Type.open_ ts typ] to go under binders - [Type.close cs typ] to introduce binders *) - (typ vs (List.nth vs i)).it - | Con (c, []) -> - (match Con.kind c with - | Def ([], Prim p) -> prim p - | Def ([], Any) -> I.PrimT I.Reserved - | Def ([], Non) -> I.PrimT I.Empty - | _ -> - chase_con vs c; - I.VarT (string_of_con vs c @@ no_region) - ) + | Var (s, i) -> assert false | Con (c, ts) -> - let ts = - (* this looks like a broken attempt at subsitution, but only when the arguments are variables - why? *) - List.map (fun t -> - match t with - | Var (s, i) -> List.nth vs i (* see above *) - | _ -> t - ) ts - in - (match Con.kind c with - | Def (tbs, t) -> - (* use this for inlining defs, doesn't work with recursion - (typ ts t).it - *) - chase_con ts c; - I.VarT (string_of_con ts c @@ no_region) - | _ -> assert false) + (match Con.kind c with + | Def (_, t) -> + (match (open_ ts t) with + | Prim p -> prim p + | Any -> I.PrimT I.Reserved + | Non -> I.PrimT I.Empty + | t -> + let id = monomorphize_con ts c in + if not (Env.mem id !env) then + begin + env := Env.add id (I.PreT @@ no_region) !env; + let t = typ t in + env := Env.add id t !env + end; + I.VarT (id @@ no_region)) + | _ -> assert false) | Typ c -> assert false | Tup ts -> if ts = [] then I.PrimT I.Null else - I.RecordT (tuple vs ts) - | Array t -> I.VecT (typ vs t) - | Opt t -> I.OptT (typ vs t) + I.RecordT (tuple ts) + | Array t -> I.VecT (typ t) + | Opt t -> I.OptT (typ t) | Obj (Object, fs) -> - I.RecordT (List.map (field vs) fs) - | Obj (Actor, fs) -> I.ServT (meths vs fs) + I.RecordT (fields fs) + | Obj (Actor, fs) -> I.ServT (meths fs) | Obj (Module, _) -> assert false | Variant fs -> - I.VariantT (List.map (field vs) fs) + I.VariantT (fields fs) | Func (Shared s, c, tbs, ts1, ts2) -> let nons = List.map (fun _ -> Non) tbs in let ts1, ts2 = (List.map (open_ nons) ts1, List.map (open_ nons) ts2) in - let t1 = args vs ts1 in + let t1 = args ts1 in (match ts2, c with | [], Returns -> I.FuncT ([I.Oneway @@ no_region], t1, []) | ts, Promises -> @@ -128,28 +114,31 @@ let rec typ vs t = (match s with | Query -> [I.Query @@ no_region] | Write -> []), - t1, args vs ts) + t1, args ts) | _ -> assert false) | Func _ -> assert false | Async _ -> assert false | Mut t -> assert false | Pre -> assert false ) @@ no_region -and field vs {lab; typ=t} = +and field {lab; typ=t} = let open Idllib.Escape in match unescape lab with | Nat nat -> - I.{label = I.Id nat @@ no_region; typ = typ vs t} @@ no_region + I.{label = I.Id nat @@ no_region; typ = typ t} @@ no_region | Id id -> - I.{label = I.Named id @@ no_region; typ = typ vs t} @@ no_region -and tuple vs ts = + I.{label = I.Named id @@ no_region; typ = typ t} @@ no_region +and fields fs = + List.map field + (List.filter (fun f -> not (is_typ f.typ)) fs) +and tuple ts = List.mapi (fun i x -> let id = Lib.Uint32.of_int i in - I.{label = I.Unnamed id @@ no_region; typ = typ vs x} @@ no_region + I.{label = I.Unnamed id @@ no_region; typ = typ x} @@ no_region ) ts -and args vs ts = - List.map (typ vs) ts -and meths vs fs = +and args ts = + List.map typ ts +and meths fs = List.fold_right (fun f list -> match f.typ with | Typ c -> @@ -160,21 +149,12 @@ and meths vs fs = match unescape f.lab with | Nat nat -> I.{var = Lib.Uint32.to_string nat @@ no_region; - meth = typ vs f.typ} @@ no_region + meth = typ f.typ} @@ no_region | Id id -> I.{var = id @@ no_region; - meth = typ vs f.typ} @@ no_region in + meth = typ f.typ} @@ no_region in meth :: list ) fs [] -and chase_con vs c = - let id = string_of_con vs c in - if not (Env.mem id !env) then - (match Con.kind c with - | Def (_, t) -> - env := Env.add id (I.PreT @@ no_region) !env; - let t = typ vs t in - env := Env.add id t !env - | _ -> assert false) let is_actor_con c = match Con.kind c with @@ -183,7 +163,7 @@ let is_actor_con c = let chase_decs env = ConSet.iter (fun c -> - if is_actor_con c then chase_con [] c + if is_actor_con c then ignore (typ (Con (c,[]))) ) env.Scope.con_env let gather_decs () = @@ -222,7 +202,7 @@ let actor progs = let prog = Lib.List.last progs in match find_last_actor prog with | None -> None - | Some t -> Some (typ [] t) + | Some t -> Some (typ t) let prog (progs, senv) : I.prog = env := Env.empty; diff --git a/test/idl/ok/fields.js.ok b/test/idl/ok/fields.js.ok index e51fdd02067..25a6387698f 100644 --- a/test/idl/ok/fields.js.ok +++ b/test/idl/ok/fields.js.ok @@ -5,10 +5,10 @@ export default ({ IDL }) => { '_36_': IDL.Nat, '_37_': IDL.Nat, 'named_files': IDL.None, '_3629958706_': IDL.Nat, '_3629958707_': IDL.Nat}) const C = - IDL.Variant({'_1_': IDL.Unit, '_2_': IDL.Unit, '_3_': IDL.Unit, - '_4_': IDL.Unit, '_10_': IDL.Unit, 'A': IDL.Unit, 'B': IDL.Unit, - 'C': IDL.Unit, 'red': IDL.Unit, 'blue': IDL.Unit, 'reserved': IDL.Unit, - 'green': IDL.Unit}) + IDL.Variant({'_1_': IDL.Null, '_2_': IDL.Null, '_3_': IDL.Null, + '_4_': IDL.Null, '_10_': IDL.Null, 'A': IDL.Null, 'B': IDL.Null, + 'C': IDL.Null, 'red': IDL.Null, 'blue': IDL.Null, 'reserved': IDL.Null, + 'green': IDL.Null}) const nest_record = IDL.Record({'_0_': IDL.Nat, '_1_': IDL.Nat, '_2_': IDL.Nat, '_3_': IDL.Record({'_0_': IDL.Nat, '_1_': IDL.Nat, '_2_': IDL.Nat}), diff --git a/test/idl/ok/import3.js.ok b/test/idl/ok/import3.js.ok index a79d5adb6c0..d3cc1c2d509 100644 --- a/test/idl/ok/import3.js.ok +++ b/test/idl/ok/import3.js.ok @@ -16,8 +16,6 @@ export default ({ IDL }) => { stream.fill( IDL.Opt( IDL.Record({'head': IDL.Nat, 'next': IDL.Func([], [stream], ['query'])}))) - s.fill( - new IDL.ActorInterface({'f': t, - 'g': IDL.Func([list], [B, tree, stream], [])})) + s.fill(IDL.Service({'f': t, 'g': IDL.Func([list], [B, tree, stream], [])})) return s.getType(); }; diff --git a/test/idl/ok/principal.js.ok b/test/idl/ok/principal.js.ok new file mode 100644 index 00000000000..336828d80e0 --- /dev/null +++ b/test/idl/ok/principal.js.ok @@ -0,0 +1,4 @@ +export default ({ IDL }) => { + return new IDL.ActorInterface({ + 'getCaller': IDL.Func([], [IDL.Principal, IDL.Nat32], [])}); +}; diff --git a/test/idl/ok/recursion.js.ok b/test/idl/ok/recursion.js.ok index a79d5adb6c0..d3cc1c2d509 100644 --- a/test/idl/ok/recursion.js.ok +++ b/test/idl/ok/recursion.js.ok @@ -16,8 +16,6 @@ export default ({ IDL }) => { stream.fill( IDL.Opt( IDL.Record({'head': IDL.Nat, 'next': IDL.Func([], [stream], ['query'])}))) - s.fill( - new IDL.ActorInterface({'f': t, - 'g': IDL.Func([list], [B, tree, stream], [])})) + s.fill(IDL.Service({'f': t, 'g': IDL.Func([list], [B, tree, stream], [])})) return s.getType(); }; diff --git a/test/idl/ok/test.js.ok b/test/idl/ok/test.js.ok index 098087e2e45..47faf6ba921 100644 --- a/test/idl/ok/test.js.ok +++ b/test/idl/ok/test.js.ok @@ -3,11 +3,11 @@ export default ({ IDL }) => { const B = my_type const message = IDL.Record({'_25_': B, '_26_': IDL.None, 'name': IDL.Text}) const broker = - new IDL.ActorInterface({ + IDL.Service({ 'find': IDL.Func([IDL.Text], [ - new IDL.ActorInterface({'up': IDL.Func([], [], []), + IDL.Service({'up': IDL.Func([], [], []), 'current': IDL.Func([], [IDL.Nat], [])}) ], [])}) diff --git a/test/idl/ok/unicode.js.ok b/test/idl/ok/unicode.js.ok index 8ca39e34301..3123178bc2b 100644 --- a/test/idl/ok/unicode.js.ok +++ b/test/idl/ok/unicode.js.ok @@ -3,8 +3,8 @@ export default ({ IDL }) => { IDL.Record({'': IDL.Nat, '📦🍦': IDL.Nat, '字段名': IDL.Nat, '字 段 名2': IDL.Nat}) const B = - IDL.Variant({'': IDL.Unit, '空的': IDL.Unit, ' 空的 ': IDL.Unit, - '1⃣️2⃣️3⃣️': IDL.Unit}) + IDL.Variant({'': IDL.Null, '空的': IDL.Null, ' 空的 ': IDL.Null, + '1⃣️2⃣️3⃣️': IDL.Null}) return new IDL.ActorInterface({'函数名': IDL.Func([A], [B], []), '': IDL.Func([IDL.Nat], [IDL.Nat], []), '👀': IDL.Func([IDL.Nat], [IDL.Nat], ['query']), diff --git a/test/idl/principal.did b/test/idl/principal.did new file mode 100644 index 00000000000..8b47535d90d --- /dev/null +++ b/test/idl/principal.did @@ -0,0 +1,3 @@ +service : { + "getCaller": () -> (principal, nat32); +} diff --git a/test/mo-idl/ok/fun_self_arg.did.ok b/test/mo-idl/ok/fun_self_arg.did.ok index 05996242017..9832a6eb66e 100644 --- a/test/mo-idl/ok/fun_self_arg.did.ok +++ b/test/mo-idl/ok/fun_self_arg.did.ok @@ -1,5 +1,5 @@ type F = func () -> (F); -type A_9 = +type A = service { "foo": F; }; diff --git a/test/mo-idl/ok/prelude.did.ok b/test/mo-idl/ok/prelude.did.ok index 112b7598cdd..41b65dba890 100644 --- a/test/mo-idl/ok/prelude.did.ok +++ b/test/mo-idl/ok/prelude.did.ok @@ -1,6 +1,6 @@ -type Text_1 = Nat_1; -type Nat_1 = null; +type Text = Nat; +type Nat = null; type Id = int; service : { - "f": (Nat_1, Text_1) -> (Id); + "f": (Nat, Text) -> (Id); } diff --git a/test/mo-idl/ok/principal.did.ok b/test/mo-idl/ok/principal.did.ok new file mode 100644 index 00000000000..8b47535d90d --- /dev/null +++ b/test/mo-idl/ok/principal.did.ok @@ -0,0 +1,3 @@ +service : { + "getCaller": () -> (principal, nat32); +} diff --git a/test/mo-idl/principal.mo b/test/mo-idl/principal.mo new file mode 100644 index 00000000000..5db63b4b229 --- /dev/null +++ b/test/mo-idl/principal.mo @@ -0,0 +1,6 @@ +import Prim "mo:prim"; +actor { + public shared { caller = c } func getCaller() : async (Principal, Word32) { + return (c, Prim.hashBlob (Prim.blobOfPrincipal c)); + }; +} diff --git a/test/run-drun/ok/caller.drun-run.ok b/test/run-drun/ok/caller.drun-run.ok index f9fad751194..fb6ae65d226 100644 --- a/test/run-drun/ok/caller.drun-run.ok +++ b/test/run-drun/ok/caller.drun-run.ok @@ -4,7 +4,7 @@ ingress Completed: Canister: Payload: 0x4449444c0000 ingress Completed: Canister: Payload: 0x4449444c0000 ingress Completed: Canister: Payload: 0x4449444c0000 Ok: Payload: 0x4449444c0000 -ingress Completed: Canister: Payload: 0x4449444c016d7b010021af5570f5a1810b7af78caf4bc70a660f0df51e42baf91d4de5b2328de0e83dfc02 +ingress Completed: Canister: Payload: 0x4449444c0001680121af5570f5a1810b7af78caf4bc70a660f0df51e42baf91d4de5b2328de0e83dfc02 Ok: Payload: 0x4449444c0001792813c52f Ok: Payload: 0x4449444c00017d02 Ok: Payload: 0x4449444c016e7b01000101 diff --git a/test/run-drun/ok/caller.ic-ref-run.ok b/test/run-drun/ok/caller.ic-ref-run.ok index 09e6433fbae..6f5a4b2415a 100644 --- a/test/run-drun/ok/caller.ic-ref-run.ok +++ b/test/run-drun/ok/caller.ic-ref-run.ok @@ -13,7 +13,7 @@ → query c6(0x4449444c0000) ← completed: 0x4449444c0000 → update c7(0x4449444c0000) -← completed: 0x4449444c016d7b010003caffee +← completed: 0x4449444c0001680103caffee → query c8(0x4449444c0000) ← completed: 0x4449444c00017989f8efb7 → query c9(0x4449444c0000) From 7fcfb5570bc38c8b50aa5d6c1de5516c94047655 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Sat, 7 Mar 2020 20:55:20 +0100 Subject: [PATCH 1113/1176] niv autoupdater: Only run once per day (#1270) slightly less noisy. Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- .github/workflows/niv-updater.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/niv-updater.yml b/.github/workflows/niv-updater.yml index ff0d3ca6f3b..0fd3788003c 100644 --- a/.github/workflows/niv-updater.yml +++ b/.github/workflows/niv-updater.yml @@ -11,8 +11,8 @@ on: types: niv-updater-nudge schedule: # * is a special character in YAML so you have to quote this string - # Run every 20min, as we like it that way (but it should be hourly) - - cron: '*/20 * * * *' + # Run every day + - cron: '0 0 * * *' jobs: niv-updater: name: 'Check for updates' From 370d3337cc42806ee8b577af7586b4ff8fdcd19e Mon Sep 17 00:00:00 2001 From: DFINITY bot <58022693+dfinity-bot@users.noreply.github.com> Date: Sat, 7 Mar 2020 20:58:18 +0100 Subject: [PATCH 1114/1176] ## Changelog for common: (#1272) Commits: [dfinity-lab/common@79a7acd2...7fbbf97c](https://github.com/dfinity-lab/common/compare/79a7acd25142e621854d787d5bcfe375af4712f8...7fbbf97c57eaa2c13eee6d958f494d800edb2b20) * [`fee34af0`](https://github.com/dfinity-lab/common/commit/fee34af0457e582e0cd2dbea7d69bb8623def448) nix/overlays/rust: 1.41.0 -> 1.41.1 Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- nix/sources.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/sources.json b/nix/sources.json index 2e43381f78f..9298f604726 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -2,7 +2,7 @@ "common": { "ref": "master", "repo": "ssh://git@github.com/dfinity-lab/common", - "rev": "79a7acd25142e621854d787d5bcfe375af4712f8", + "rev": "7fbbf97c57eaa2c13eee6d958f494d800edb2b20", "type": "git" }, "dfinity": { From ce76e60631d772b0084aefa294b795666fcdd33d Mon Sep 17 00:00:00 2001 From: DFINITY bot <58022693+dfinity-bot@users.noreply.github.com> Date: Mon, 9 Mar 2020 10:15:47 +0100 Subject: [PATCH 1115/1176] ## Changelog for common: (#1274) Commits: [dfinity-lab/common@7fbbf97c...8ab61d87](https://github.com/dfinity-lab/common/compare/7fbbf97c57eaa2c13eee6d958f494d800edb2b20...8ab61d8774c6976c61e52040135bf5dc609fabe4) * [`82791751`](https://github.com/dfinity-lab/common/commit/82791751ec41f33567327d60ac63ffcb316f8438) ## Changelog for nixpkgs: --- nix/sources.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/sources.json b/nix/sources.json index 9298f604726..2de9e76e3b4 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -2,7 +2,7 @@ "common": { "ref": "master", "repo": "ssh://git@github.com/dfinity-lab/common", - "rev": "7fbbf97c57eaa2c13eee6d958f494d800edb2b20", + "rev": "8ab61d8774c6976c61e52040135bf5dc609fabe4", "type": "git" }, "dfinity": { From 8cccfe28c1a80f89fb67eb7f95822b5dddb0593b Mon Sep 17 00:00:00 2001 From: Yan Chen <48968912+chenyan-dfinity@users.noreply.github.com> Date: Mon, 9 Mar 2020 11:02:28 -0700 Subject: [PATCH 1116/1176] fix bug in mo_to_idl (#1275) * fix bug in mo_to_idl * fix Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- src/exes/moc.ml | 1 - src/mo_idl/mo_to_idl.ml | 9 +++------ test/mo-idl/ok/dup_fields.did.ok | 18 +++++++++++++++++ test/mo-idl/ok/dup_fields.didc.ok | 1 + ...elds.idl.ret.ok => dup_fields.didc.ret.ok} | 0 test/mo-idl/ok/dup_fields.idl.ok | 1 - test/mo-idl/ok/issue-827.did.ok | 6 +++--- test/mo-idl/ok/recursion.did.ok | 6 +++--- test/mo-idl/ok/result.did.ok | 20 +++++++++---------- 9 files changed, 38 insertions(+), 24 deletions(-) create mode 100644 test/mo-idl/ok/dup_fields.did.ok create mode 100644 test/mo-idl/ok/dup_fields.didc.ok rename test/mo-idl/ok/{dup_fields.idl.ret.ok => dup_fields.didc.ret.ok} (100%) delete mode 100644 test/mo-idl/ok/dup_fields.idl.ok diff --git a/src/exes/moc.ml b/src/exes/moc.ml index 1f49ee31167..d8388c3b764 100644 --- a/src/exes/moc.ml +++ b/src/exes/moc.ml @@ -124,7 +124,6 @@ let process_files files : unit = | Idl -> set_out_file files ".did"; let prog = Diag.run (Pipeline.generate_idl files) in - ignore (Diag.run (Idllib.Pipeline.check_prog prog)); let oc = open_out !out_file in let idl_code = Idllib.Arrange_idl.string_of_prog prog in output_string oc idl_code; close_out oc diff --git a/src/mo_idl/mo_to_idl.ml b/src/mo_idl/mo_to_idl.ml index 2e99cbf11a1..4a388718964 100644 --- a/src/mo_idl/mo_to_idl.ml +++ b/src/mo_idl/mo_to_idl.ml @@ -13,14 +13,9 @@ let stamp = ref Stamp.empty module TypeMap = Map.Make (struct type t = con * typ list let compare = compare end) let type_map = ref TypeMap.empty -let normalize str = - let illegal_chars = ['-'; '/';] in - String.map (fun c -> if List.mem c illegal_chars then '_' else c) str - let monomorphize_con vs c = let name = Con.name c in match Con.kind c with - | Def ([], _) -> normalize name | Def _ -> let id = (c, vs) in let n = @@ -36,7 +31,9 @@ let monomorphize_con vs c = type_map := TypeMap.add id (n+1) !type_map; n+1) | Some n -> n - in Printf.sprintf "%s_%d" (normalize name) n + in + if n == 1 then name + else Printf.sprintf "%s_%d" name n | _ -> assert false let prim p = diff --git a/test/mo-idl/ok/dup_fields.did.ok b/test/mo-idl/ok/dup_fields.did.ok new file mode 100644 index 00000000000..65bb6bb4a6d --- /dev/null +++ b/test/mo-idl/ok/dup_fields.did.ok @@ -0,0 +1,18 @@ +type Tup = + record { + text; + Info; + text; + nat; + }; +type Info = + record { + 1: Info; + 345: text; + "name": text; + "name": int; + }; +service : { + "f": (Tup) -> () query; + "f_": (opt Tup) -> () oneway; +} diff --git a/test/mo-idl/ok/dup_fields.didc.ok b/test/mo-idl/ok/dup_fields.didc.ok new file mode 100644 index 00000000000..2de6819a41f --- /dev/null +++ b/test/mo-idl/ok/dup_fields.didc.ok @@ -0,0 +1 @@ +dup_fields.did:13.4-13.10: type error, field name name hash collision with field name diff --git a/test/mo-idl/ok/dup_fields.idl.ret.ok b/test/mo-idl/ok/dup_fields.didc.ret.ok similarity index 100% rename from test/mo-idl/ok/dup_fields.idl.ret.ok rename to test/mo-idl/ok/dup_fields.didc.ret.ok diff --git a/test/mo-idl/ok/dup_fields.idl.ok b/test/mo-idl/ok/dup_fields.idl.ok deleted file mode 100644 index 63274d81be3..00000000000 --- a/test/mo-idl/ok/dup_fields.idl.ok +++ /dev/null @@ -1 +0,0 @@ -(unknown location): type error, field name name hash collision with field name diff --git a/test/mo-idl/ok/issue-827.did.ok b/test/mo-idl/ok/issue-827.did.ok index 5aab225b14c..ae82a9bd1d5 100644 --- a/test/mo-idl/ok/issue-827.did.ok +++ b/test/mo-idl/ok/issue-827.did.ok @@ -1,8 +1,8 @@ -type List_1 = +type List = opt record { int; - List_1; + List; }; service : { - "f": (List_1) -> (List_1); + "f": (List) -> (List); } diff --git a/test/mo-idl/ok/recursion.did.ok b/test/mo-idl/ok/recursion.did.ok index 861930f3954..83987e16a3a 100644 --- a/test/mo-idl/ok/recursion.did.ok +++ b/test/mo-idl/ok/recursion.did.ok @@ -3,12 +3,12 @@ type List_2 = "head": nat; "tail": opt List_2; }; -type List_1 = +type List = record { "head": int; - "tail": opt List_1; + "tail": opt List; }; service : { "f": (nat) -> (List_2); - "g": (int) -> (List_1); + "g": (int) -> (List); } diff --git a/test/mo-idl/ok/result.did.ok b/test/mo-idl/ok/result.did.ok index 505e85c3ce7..2b0299c3f84 100644 --- a/test/mo-idl/ok/result.did.ok +++ b/test/mo-idl/ok/result.did.ok @@ -3,14 +3,9 @@ type Result_2 = "err": text; "ok": nat; }; -type Result_1 = +type Result3 = variant { - "err": text; - "ok": null; - }; -type Result3_1 = - variant { - "err": Result2_1; + "err": Result2; "ok": null; }; type Result2_2 = @@ -18,12 +13,17 @@ type Result2_2 = "err": Result_2; "ok": nat; }; -type Result2_1 = +type Result2 = variant { - "err": Result_1; + "err": Result; + "ok": null; + }; +type Result = + variant { + "err": text; "ok": null; }; service : { "f": (opt nat) -> (Result_2); - "g": (Result3_1) -> (Result2_2); + "g": (Result3) -> (Result2_2); } From 560830754038bf64942335861dfd2aaa2c94c86f Mon Sep 17 00:00:00 2001 From: DFINITY bot <58022693+dfinity-bot@users.noreply.github.com> Date: Tue, 10 Mar 2020 01:10:16 +0100 Subject: [PATCH 1117/1176] ## Changelog for common: (#1277) Commits: [dfinity-lab/common@8ab61d87...18b21123](https://github.com/dfinity-lab/common/compare/8ab61d8774c6976c61e52040135bf5dc609fabe4...18b21123f4bf7208be86e2f8865cc6f2328f09c2) * [`abb8b151`](https://github.com/dfinity-lab/common/commit/abb8b15117751477f500a5f31e80051515112663) ## Changelog for naersk: --- nix/sources.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/sources.json b/nix/sources.json index 2de9e76e3b4..d8b69a93c80 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -2,7 +2,7 @@ "common": { "ref": "master", "repo": "ssh://git@github.com/dfinity-lab/common", - "rev": "8ab61d8774c6976c61e52040135bf5dc609fabe4", + "rev": "18b21123f4bf7208be86e2f8865cc6f2328f09c2", "type": "git" }, "dfinity": { From 44362755cfc6f644a5cb3a6f5498815ce62efef6 Mon Sep 17 00:00:00 2001 From: Yan Chen <48968912+chenyan-dfinity@users.noreply.github.com> Date: Tue, 10 Mar 2020 00:58:06 -0700 Subject: [PATCH 1118/1176] update rts to decode principal (#1273) * update rts to decode principal * refactor * Apply suggestions from code review Co-Authored-By: Gabor Greif * Update rts/idl.c Co-Authored-By: Joachim Breitner * fix skip Co-authored-by: Gabor Greif Co-authored-by: Joachim Breitner Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- rts/idl.c | 43 +++++++++++++++----- src/codegen/compile.ml | 1 - test/run-drun/idl-any.mo | 2 + test/run-drun/idl-principal.mo | 12 ++++++ test/run-drun/ok/idl-any.drun-run.ok | 4 ++ test/run-drun/ok/idl-any.ic-ref-run.ok | 6 +++ test/run-drun/ok/idl-principal.drun-run.ok | 3 ++ test/run-drun/ok/idl-principal.ic-ref-run.ok | 8 ++++ 8 files changed, 67 insertions(+), 12 deletions(-) create mode 100644 test/run-drun/idl-principal.mo create mode 100644 test/run-drun/ok/idl-principal.drun-run.ok create mode 100644 test/run-drun/ok/idl-principal.ic-ref-run.ok diff --git a/rts/idl.c b/rts/idl.c index 4a95126c157..86833260610 100644 --- a/rts/idl.c +++ b/rts/idl.c @@ -72,8 +72,6 @@ export int32_t read_i32_of_sleb128(buf *buf) { #define IDL_PRIM_reserved (-16) #define IDL_PRIM_empty (-17) -#define IDL_PRIM_lowest (-17) - #define IDL_CON_opt (-18) #define IDL_CON_vec (-19) #define IDL_CON_record (-20) @@ -81,6 +79,19 @@ export int32_t read_i32_of_sleb128(buf *buf) { #define IDL_CON_func (-22) #define IDL_CON_service (-23) +#define IDL_REF_principal (-24) + +static bool is_primitive_type(int32_t ty) { + static const int32_t IDL_PRIM_lowest = -17; + return ty < 0 && (ty >= IDL_PRIM_lowest || ty == IDL_REF_principal); +} + +static void check_typearg(int32_t ty, uint32_t n_types) { + // arguments to type constructors can be: + if (is_primitive_type(ty)) return; // primitive types + if (ty >=0 && ty < n_types) return; // type indices. + idl_trap_with("invalid type argument"); +} /* * This function parses the IDL magic header and type description. It @@ -115,36 +126,38 @@ export void parse_idl_header(buf *buf, uint8_t ***typtbl_out, uint8_t **main_typ for (int i = 0; i < n_types; i++) { typtbl[i] = buf->p; int32_t ty = read_i32_of_sleb128(buf); - if (ty >= IDL_PRIM_lowest) { + if (ty >= 0) { + idl_trap_with("illeagal type table"); // illegal + } else if (is_primitive_type(ty)) { idl_trap_with("primitive type in type table"); // illegal } else if (ty == IDL_CON_opt) { int32_t t = read_i32_of_sleb128(buf); - if (t < IDL_PRIM_lowest || t >= n_types) idl_trap_with("type index out of range"); + check_typearg(t, n_types); } else if (ty == IDL_CON_vec) { int32_t t = read_i32_of_sleb128(buf); - if (t < IDL_PRIM_lowest || t >= n_types) idl_trap_with("type index out of range"); + check_typearg(t, n_types); } else if (ty == IDL_CON_record) { for (uint32_t n = read_u32_of_leb128(buf); n > 0; n--) { read_u32_of_leb128(buf); int32_t t = read_i32_of_sleb128(buf); - if (t < IDL_PRIM_lowest || t >= n_types) idl_trap_with("type index out of range"); + check_typearg(t, n_types); } } else if (ty == IDL_CON_variant) { for (uint32_t n = read_u32_of_leb128(buf); n > 0; n--) { read_u32_of_leb128(buf); int32_t t = read_i32_of_sleb128(buf); - if (t < IDL_PRIM_lowest || t >= n_types) idl_trap_with("type index out of range"); + check_typearg(t, n_types); } } else if (ty == IDL_CON_func) { // arg types for (uint32_t n = read_u32_of_leb128(buf); n > 0; n--) { int32_t t = read_i32_of_sleb128(buf); - if (t < IDL_PRIM_lowest || t >= n_types) idl_trap_with("type index out of range"); + check_typearg(t, n_types); } // ret types for (uint32_t n = read_u32_of_leb128(buf); n > 0; n--) { int32_t t = read_i32_of_sleb128(buf); - if (t < IDL_PRIM_lowest || t >= n_types) idl_trap_with("type index out of range"); + check_typearg(t, n_types); } // annotations for (uint32_t n = read_u32_of_leb128(buf); n > 0; n--) { @@ -157,7 +170,7 @@ export void parse_idl_header(buf *buf, uint8_t ***typtbl_out, uint8_t **main_typ (buf->p) += size; // type int32_t t = read_i32_of_sleb128(buf); - if (t < IDL_PRIM_lowest || t >= n_types) idl_trap_with("type index out of range"); + check_typearg(t, n_types); } } else { // future type uint32_t n = read_u32_of_leb128(buf); @@ -168,7 +181,7 @@ export void parse_idl_header(buf *buf, uint8_t ***typtbl_out, uint8_t **main_typ *main_types_out = buf->p; for (uint32_t n = read_u32_of_leb128(buf); n > 0; n--) { int32_t t = read_i32_of_sleb128(buf); - if (t < IDL_PRIM_lowest || t >= n_types) idl_trap_with("type index out of range"); + check_typearg(t, n_types); } *typtbl_out = typtbl; @@ -227,6 +240,14 @@ export void skip_any(buf *b, uint8_t **typtbl, int32_t t, int32_t depth) { return; case IDL_PRIM_empty: idl_trap_with("skip_any: encountered empty"); + case IDL_REF_principal: + { + if (read_byte(b)) { + uint32_t len = read_u32_of_leb128(b); + advance(b, len); + } + return; + } default: idl_trap_with("skip_any: unknown prim"); } diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index dfb1975a5a3..9c66b044829 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -3523,7 +3523,6 @@ module Serialization = struct | Func (s, c, tbs, ts1, ts2) -> List.iter go ts1; List.iter go ts2 | Prim Blob -> () - | Prim Principal -> () | _ -> Printf.eprintf "type_desc: unexpected type %s\n" (string_of_typ t); assert false diff --git a/test/run-drun/idl-any.mo b/test/run-drun/idl-any.mo index d20c79850da..316f62dcd14 100644 --- a/test/run-drun/idl-any.mo +++ b/test/run-drun/idl-any.mo @@ -24,6 +24,8 @@ actor { //CALL query any 0x4449444C00027271DEADBEEFCAFFEE6603466F6F //CALL query any 0x4449444C0002717103466F6F03466F6F //CALL query any 0x4449444C0002707103466F6F +//CALL query any 0x4449444C000268710003466F6F +//CALL query any 0x4449444C000268710104DEADBEEF03466F6F // Composite values: //CALL query any 0x4449444C016e710200710003466F6F diff --git a/test/run-drun/idl-principal.mo b/test/run-drun/idl-principal.mo new file mode 100644 index 00000000000..35a7471a1c3 --- /dev/null +++ b/test/run-drun/idl-principal.mo @@ -0,0 +1,12 @@ +actor { + public query func fun(id: Principal) : async Principal { return id; }; + public query func fun2(id: ?Principal) : async ?Principal { return id; }; +} + + +//CALL query fun 0x4449444C0001680103CAFFEE +//CALL query fun2 0x4449444C016E680100010103CAFFEE + +//SKIP run +//SKIP run-ir +//SKIP run-low diff --git a/test/run-drun/ok/idl-any.drun-run.ok b/test/run-drun/ok/idl-any.drun-run.ok index 94fb99baad1..b0e0985a933 100644 --- a/test/run-drun/ok/idl-any.drun-run.ok +++ b/test/run-drun/ok/idl-any.drun-run.ok @@ -55,3 +55,7 @@ debug.print: ok: Foo Ok: Payload: 0x4449444c0000 debug.print: ok: Foo Ok: Payload: 0x4449444c0000 +debug.print: ok: Foo +Ok: Payload: 0x4449444c0000 +debug.print: ok: Foo +Ok: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-any.ic-ref-run.ok b/test/run-drun/ok/idl-any.ic-ref-run.ok index 46052bedb22..20b8afd455f 100644 --- a/test/run-drun/ok/idl-any.ic-ref-run.ok +++ b/test/run-drun/ok/idl-any.ic-ref-run.ok @@ -50,6 +50,12 @@ debug.print: ok: Foo → query any(0x4449444c0002707103466f6f) debug.print: ok: Foo ← completed: 0x4449444c0000 +→ query any(0x4449444c000268710003466f6f) +debug.print: ok: Foo +← completed: 0x4449444c0000 +→ query any(0x4449444c000268710104deadbeef03466f6f) +debug.print: ok: Foo +← completed: 0x4449444c0000 → query any(0x4449444c016e710200710003466f6f) debug.print: ok: Foo ← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-principal.drun-run.ok b/test/run-drun/ok/idl-principal.drun-run.ok new file mode 100644 index 00000000000..1be6b08e9da --- /dev/null +++ b/test/run-drun/ok/idl-principal.drun-run.ok @@ -0,0 +1,3 @@ +ingress System +Ok: Payload: 0x4449444c0001680103caffee +Ok: Payload: 0x4449444c016e680100010103caffee diff --git a/test/run-drun/ok/idl-principal.ic-ref-run.ok b/test/run-drun/ok/idl-principal.ic-ref-run.ok new file mode 100644 index 00000000000..488dc335c0b --- /dev/null +++ b/test/run-drun/ok/idl-principal.ic-ref-run.ok @@ -0,0 +1,8 @@ +→ create +← completed: canister-id = ic:2a012b +→ install +← completed +→ query fun(0x4449444c0001680103caffee) +← completed: 0x4449444c0001680103caffee +→ query fun2(0x4449444c016e680100010103caffee) +← completed: 0x4449444c016e680100010103caffee From 849cfba0b8dead6c6e5de0905491f9e33631eb32 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 10 Mar 2020 11:55:34 +0000 Subject: [PATCH 1119/1176] Fix for unsorted recorded fields after pattern inference (#1278) * unsorted fields after typing repro * sort record fields in infer_pat * formatting --- src/mo_frontend/typing.ml | 2 +- test/run/sort-record-fields.mo | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 test/run/sort-record-fields.mo diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 3cc49259f85..2fb01fc9536 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -1367,7 +1367,7 @@ and infer_pats at env pats ts ve : T.typ list * Scope.val_env = and infer_pat_fields at env pfs ts ve : (T.obj_sort * T.field list) * Scope.val_env = match pfs with - | [] -> (T.Object, List.rev ts), ve + | [] -> (T.Object, List.sort T.compare_field ts), ve | pf::pfs' -> let typ, ve1 = infer_pat env pf.it.pat in let ve' = disjoint_union env at "duplicate binding for %s in pattern" ve ve1 in diff --git a/test/run/sort-record-fields.mo b/test/run/sort-record-fields.mo new file mode 100644 index 00000000000..e92d54e9989 --- /dev/null +++ b/test/run/sort-record-fields.mo @@ -0,0 +1,5 @@ +// tests that object fields are properly sorted after inference/checking +func bad({ name : Text; age : Nat }) : Text = "text"; +func ok({ age : Nat; name : Text }) : Text = "text"; +{ let {name; age} = {name = "fred"; age = 40};}; +{ let {age; name} = {name = "fred"; age = 40};}; From 6c14f08792203843b1d35b1de5f29da8064efc33 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 11 Mar 2020 07:17:41 +0000 Subject: [PATCH 1120/1176] Fix pretty printing of function types with scope parameters (#1281) * pretty printing of scope functions was broken * fix pretty printing of scoped functions --- src/mo_types/type.ml | 14 +++++++----- test/fail/ok/pretty_scoped.tc.ok | 33 ++++++++++++++++++++++++++++ test/fail/ok/pretty_scoped.tc.ret.ok | 1 + test/fail/pretty_scoped.mo | 12 ++++++++++ 4 files changed, 54 insertions(+), 6 deletions(-) create mode 100644 test/fail/ok/pretty_scoped.tc.ok create mode 100644 test/fail/ok/pretty_scoped.tc.ret.ok create mode 100644 test/fail/pretty_scoped.mo diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index ba9929aa251..d208a5f43fe 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -1253,16 +1253,17 @@ and string_of_typ' vs t = | Func (s, c, tbs, ts1, ts2) when can_sugar t -> let vs' = vars_of_binds vs tbs in let vs'', tbs' = List.tl vs', List.tl tbs in + let vs'vs = vs' @ vs in begin match tbs with | [tb] -> sprintf "%s%s -> %s" (string_of_func_sort s) - (string_of_dom vs ts1) - (string_of_control_cod true c vs ts2) + (string_of_dom (vs'vs) ts1) + (string_of_control_cod true c (vs'vs) ts2) | _ -> sprintf "%s%s%s -> %s" - (string_of_func_sort s) (string_of_binds (vs' @ vs) vs'' tbs') - (string_of_dom (vs' @ vs) ts1) (string_of_control_cod true c (vs' @ vs) ts2) + (string_of_func_sort s) (string_of_binds (vs'vs) vs'' tbs') + (string_of_dom (vs'vs) ts1) (string_of_control_cod true c (vs'vs) ts2) end | Func (s, c, [], ts1, ts2) -> sprintf "%s%s -> %s" (string_of_func_sort s) @@ -1270,9 +1271,10 @@ and string_of_typ' vs t = (string_of_control_cod false c vs ts2) | Func (s, c, tbs, ts1, ts2) -> let vs' = vars_of_binds vs tbs in + let vs'vs = vs' @ vs in sprintf "%s%s%s -> %s" - (string_of_func_sort s) (string_of_binds (vs' @ vs) vs' tbs) - (string_of_dom (vs' @ vs) ts1) (string_of_control_cod false c (vs' @ vs) ts2) + (string_of_func_sort s) (string_of_binds (vs'vs) vs' tbs) + (string_of_dom (vs'vs) ts1) (string_of_control_cod false c (vs'vs) ts2) | Opt t -> sprintf "?%s" (string_of_typ_nullary vs t) | Async (t1, t2) -> diff --git a/test/fail/ok/pretty_scoped.tc.ok b/test/fail/ok/pretty_scoped.tc.ok new file mode 100644 index 00000000000..2830b85a634 --- /dev/null +++ b/test/fail/ok/pretty_scoped.tc.ok @@ -0,0 +1,33 @@ +pretty_scoped.mo:2.1-2.38: type error, cannot implicitly instantiate function of type + (A -> async ()) -> () +to argument of type + () +to produce result of type + () +no instantiation of A makes () <: A -> async () and () <: () +pretty_scoped.mo:4.1-4.45: type error, cannot implicitly instantiate function of type + ((A, B) -> async ()) -> () +to argument of type + () +to produce result of type + () +no instantiation of A, B makes () <: (A, B) -> async () and () <: () +pretty_scoped.mo:6.1-6.50: type error, cannot implicitly instantiate function of type + ((A, B, C) -> async ()) -> () +to argument of type + () +to produce result of type + () +no instantiation of A, B, C makes () <: (A, B, C) -> async () and () <: () +pretty_scoped.mo:8.1-8.55: type error, cannot implicitly instantiate function of type + ((A, B, C, D) -> async ()) -> () +to argument of type + () +to produce result of type + () +no instantiation of A, B, C makes () <: (A, B, C, D) -> async () and () <: () +pretty_scoped.mo:10.1-10.69: type error, cannot implicitly instantiate function of type + ((A, B, C, D, E) -> async ()) -> () +to argument of type + () +no instantiation of A, B, C makes () <: (A, B, C, D, E) -> async () and () <: Any diff --git a/test/fail/ok/pretty_scoped.tc.ret.ok b/test/fail/ok/pretty_scoped.tc.ret.ok new file mode 100644 index 00000000000..69becfa16f9 --- /dev/null +++ b/test/fail/ok/pretty_scoped.tc.ret.ok @@ -0,0 +1 @@ +Return code 1 diff --git a/test/fail/pretty_scoped.mo b/test/fail/pretty_scoped.mo new file mode 100644 index 00000000000..236643a087f --- /dev/null +++ b/test/fail/pretty_scoped.mo @@ -0,0 +1,12 @@ +// test pretty printing of scoped functions (indirectly via error messages) +(func f1(g:A -> async ()):(){}) (); + +(func f2(g:(A,B) -> async ()):(){}) (); + +(func f3(g:(A,B,C) -> async ()):(){}) (); + +(func f4(g:(A,B,C,D) -> async ()):(){}) (); + +(func f5(g:(A,B,C,D,E) -> async ()):(){}) (); + + From bac0148cf6f6c007598c41d4bed78ef0883d0b7e Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 11 Mar 2020 07:36:24 +0000 Subject: [PATCH 1121/1176] Bug fix: typo in async case of bi_match.ml (bad scope matching) (#1282) * repro for async bi_match bug * fix repro * improve repro * fix bug in bi_match.ml; update test output --- src/mo_frontend/bi_match.ml | 6 ++---- test/fail/inference.mo | 4 ++++ test/fail/ok/inference.tc.ok | 4 ++++ 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/mo_frontend/bi_match.ml b/src/mo_frontend/bi_match.ml index 2926f867f03..f28272682da 100644 --- a/src/mo_frontend/bi_match.ml +++ b/src/mo_frontend/bi_match.ml @@ -162,16 +162,14 @@ let bi_match_subs scope_opt tbs subs = ) else None | Async (t11, t12), Async (t21, t22) -> - (* TBR *) - (match bi_equate_typ rel eq inst any t11 t12 with + (match bi_equate_typ rel eq inst any t11 t21 with | Some inst -> bi_match_typ rel eq inst any t12 t22 | None -> None) | Mut t1', Mut t2' -> - (* TBR *) bi_equate_typ rel eq inst any t1' t2' | Typ c1, Typ c2 -> - (* TBR *) + (* NB: we assume c1, c2 closed *) if Type.eq t1 t2 then Some inst else None | _, _ -> None end diff --git a/test/fail/inference.mo b/test/fail/inference.mo index adde0dd542c..4fdee542c74 100644 --- a/test/fail/inference.mo +++ b/test/fail/inference.mo @@ -188,3 +188,7 @@ ignore nil() : List; ignore cons(1, nil()) : List; ignore cons(1, cons(2, nil())) : List; +func req(x : Nat) : async Int { return x }; +func send( f: Nat -> async Int, x : T) : async Int { f(x); }; +async { ignore send(req,0);}; + diff --git a/test/fail/ok/inference.tc.ok b/test/fail/ok/inference.tc.ok index e75055be17a..d191704dd9a 100644 --- a/test/fail/ok/inference.tc.ok +++ b/test/fail/ok/inference.tc.ok @@ -140,3 +140,7 @@ to produce result of type no instantiation of T makes {type x = Nat} <: {x : T} and T <: Any inference.mo:183.8-183.21: type error, too few type arguments inference.mo:186.8-186.15: type error, too few type arguments +inference.mo:192.64-192.68: type error, expression of type + async<$send> Int +cannot produce expected type + Int From 524f39d2bbf173ed0abb7f82cfa873cb701ef88b Mon Sep 17 00:00:00 2001 From: DFINITY bot <58022693+dfinity-bot@users.noreply.github.com> Date: Thu, 12 Mar 2020 10:57:42 +0100 Subject: [PATCH 1122/1176] ## Changelog for common: (#1286) Commits: [dfinity-lab/common@18b21123...c022ff9f](https://github.com/dfinity-lab/common/compare/18b21123f4bf7208be86e2f8865cc6f2328f09c2...c022ff9f16ed0b9e3eb4ed97f26b493de3858df7) * [`6e2fa744`](https://github.com/dfinity-lab/common/commit/6e2fa744e19488fa76e17e73291b8aac33f737ff) build-dfinity-rust-package.nix: allow overriding cargoBuildCommands --- nix/sources.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/sources.json b/nix/sources.json index d8b69a93c80..6971f6ce832 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -2,7 +2,7 @@ "common": { "ref": "master", "repo": "ssh://git@github.com/dfinity-lab/common", - "rev": "18b21123f4bf7208be86e2f8865cc6f2328f09c2", + "rev": "c022ff9f16ed0b9e3eb4ed97f26b493de3858df7", "type": "git" }, "dfinity": { From 95ab2e9c3d61bc63a30f1af94bd1081e1e7d7ebd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikola=20Kne=C5=BEevi=C4=87?= Date: Thu, 12 Mar 2020 11:01:01 +0100 Subject: [PATCH 1123/1176] Update niv-updater-action to v5 (#1285) This brings back nice changelogs, as update commits now have a proper subject. Thanks @nomeata Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- .github/workflows/niv-updater.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/niv-updater.yml b/.github/workflows/niv-updater.yml index 0fd3788003c..84b4735ebc1 100644 --- a/.github/workflows/niv-updater.yml +++ b/.github/workflows/niv-updater.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest steps: - name: niv-updater-action - uses: knl/niv-updater-action@v4 + uses: knl/niv-updater-action@v5 with: # might be too noisy blacklist: 'nixpkgs,dfinity,ic-ref' From b68e97fce80ee9031a4fda031beb3cbc7624b34c Mon Sep 17 00:00:00 2001 From: Yan Chen <48968912+chenyan-dfinity@users.noreply.github.com> Date: Thu, 12 Mar 2020 10:36:38 -0700 Subject: [PATCH 1124/1176] cosmetic change in compile_js (#1284) * cosmetic change in compile_js * update test Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- src/idllib/compile_js.ml | 3 +-- test/idl/ok/actor.js.ok | 4 ++-- test/idl/ok/cyclic.js.ok | 2 +- test/idl/ok/diamond.js.ok | 2 +- test/idl/ok/escape.js.ok | 3 +-- test/idl/ok/fieldnat.js.ok | 3 +-- test/idl/ok/fields.js.ok | 3 +-- test/idl/ok/import.js.ok | 3 +-- test/idl/ok/import1.js.ok | 2 +- test/idl/ok/integer.js.ok | 2 +- test/idl/ok/keywords.js.ok | 3 +-- test/idl/ok/principal.js.ok | 2 +- test/idl/ok/px.js.ok | 2 +- test/idl/ok/test.js.ok | 2 +- test/idl/ok/unicode.js.ok | 2 +- 15 files changed, 16 insertions(+), 22 deletions(-) diff --git a/src/idllib/compile_js.ml b/src/idllib/compile_js.ml index e41699c10df..b1236f0ff78 100644 --- a/src/idllib/compile_js.ml +++ b/src/idllib/compile_js.ml @@ -199,8 +199,7 @@ let pp_actor ppf t recs = kwd ppf "return"; (match t.it with | ServT tp -> - kwd ppf "new"; - str ppf "IDL.ActorInterface({"; + str ppf "IDL.Service({"; concat ppf pp_meth "," tp; str ppf "});" | VarT var -> diff --git a/test/idl/ok/actor.js.ok b/test/idl/ok/actor.js.ok index adb582b68c2..7a3ceaad2a1 100644 --- a/test/idl/ok/actor.js.ok +++ b/test/idl/ok/actor.js.ok @@ -4,6 +4,6 @@ export default ({ IDL }) => { const h = IDL.Func([f], [f], []) const g = f o.fill(IDL.Opt(o)) - return new IDL.ActorInterface({'f': IDL.Func([IDL.Nat], [h], []), 'g': f, - 'h': g, 'o': IDL.Func([o], [o], [])}); + return IDL.Service({'f': IDL.Func([IDL.Nat], [h], []), 'g': f, 'h': g, + 'o': IDL.Func([o], [o], [])}); }; diff --git a/test/idl/ok/cyclic.js.ok b/test/idl/ok/cyclic.js.ok index 8e346b1a28d..a6cf3c07ee2 100644 --- a/test/idl/ok/cyclic.js.ok +++ b/test/idl/ok/cyclic.js.ok @@ -6,5 +6,5 @@ export default ({ IDL }) => { const Z = A const Y = Z const X = Y - return new IDL.ActorInterface({'f': IDL.Func([A, B, C, X, Y, Z], [], [])}); + return IDL.Service({'f': IDL.Func([A, B, C, X, Y, Z], [], [])}); }; diff --git a/test/idl/ok/diamond.js.ok b/test/idl/ok/diamond.js.ok index dc3bf76a756..a63075d91dc 100644 --- a/test/idl/ok/diamond.js.ok +++ b/test/idl/ok/diamond.js.ok @@ -3,5 +3,5 @@ export default ({ IDL }) => { const t2 = IDL.Vec(t) const t3 = IDL.Opt(t) const t1 = IDL.Record({'_0_': t2, '_1_': t3, '_2_': t}) - return new IDL.ActorInterface({'f': IDL.Func([t, t2, t3], [t1], [])}); + return IDL.Service({'f': IDL.Func([t, t2, t3], [t1], [])}); }; diff --git a/test/idl/ok/escape.js.ok b/test/idl/ok/escape.js.ok index cbfb408e594..7b67ac834d4 100644 --- a/test/idl/ok/escape.js.ok +++ b/test/idl/ok/escape.js.ok @@ -2,6 +2,5 @@ export default ({ IDL }) => { const t = IDL.Record({'\"': IDL.Nat, '\'': IDL.Nat, '\"\'': IDL.Nat, '\\\n\'\"': IDL.Nat}) - return new IDL.ActorInterface({'\n\'\"\'\'\"\"\r\t': IDL.Func([t], [], []) - }); + return IDL.Service({'\n\'\"\'\'\"\"\r\t': IDL.Func([t], [], [])}); }; diff --git a/test/idl/ok/fieldnat.js.ok b/test/idl/ok/fieldnat.js.ok index 01a9170e0a4..1438827ef46 100644 --- a/test/idl/ok/fieldnat.js.ok +++ b/test/idl/ok/fieldnat.js.ok @@ -1,6 +1,5 @@ export default ({ IDL }) => { - return new IDL.ActorInterface({ - 'foo': IDL.Func([IDL.Record({'_2_': IDL.Int})], [], []), + return IDL.Service({'foo': IDL.Func([IDL.Record({'_2_': IDL.Int})], [], []), 'bar': IDL.Func([IDL.Record({'2': IDL.Int})], [], []), 'baz': IDL.Func([IDL.Record({'_2_': IDL.Int, '2': IDL.Nat})], [], []), 'bab': IDL.Func([IDL.Int, IDL.Nat], [], [])}); diff --git a/test/idl/ok/fields.js.ok b/test/idl/ok/fields.js.ok index 25a6387698f..220f7478acd 100644 --- a/test/idl/ok/fields.js.ok +++ b/test/idl/ok/fields.js.ok @@ -14,6 +14,5 @@ export default ({ IDL }) => { '_3_': IDL.Record({'_0_': IDL.Nat, '_1_': IDL.Nat, '_2_': IDL.Nat}), '_4_': IDL.Nat, '_5_': IDL.Nat, '_6_': IDL.Nat, '_7_': A, '_8_': B, '_9_': C, '_10_': IDL.Nat}) - return new IDL.ActorInterface({'f': IDL.Func([A, B, C, nest_record], [], []) - }); + return IDL.Service({'f': IDL.Func([A, B, C, nest_record], [], [])}); }; diff --git a/test/idl/ok/import.js.ok b/test/idl/ok/import.js.ok index 0200ab84be4..4de20aacf47 100644 --- a/test/idl/ok/import.js.ok +++ b/test/idl/ok/import.js.ok @@ -11,7 +11,6 @@ export default ({ IDL }) => { const OpEntId = IDL.Opt(EntId) const IdErr = IDL.Record({'idErr': OpEntId}) const Inventory = IDL.Record({'produce_id': IDL.Nat, 'quantity': IDL.Nat}) - return new IDL.ActorInterface({ - 'f': IDL.Func([t, t1, t2], [list, IdErr], []), + return IDL.Service({'f': IDL.Func([t, t1, t2], [list, IdErr], []), 'getInventory': IDL.Func([IDL.Nat], [Inventory], ['query'])}); }; diff --git a/test/idl/ok/import1.js.ok b/test/idl/ok/import1.js.ok index f25f6306af4..5acd247ba70 100644 --- a/test/idl/ok/import1.js.ok +++ b/test/idl/ok/import1.js.ok @@ -3,5 +3,5 @@ export default ({ IDL }) => { const t1 = t const UserId = IDL.Nat const t2 = UserId - return new IDL.ActorInterface({'f': IDL.Func([t, t1, t2], [], [])}); + return IDL.Service({'f': IDL.Func([t, t1, t2], [], [])}); }; diff --git a/test/idl/ok/integer.js.ok b/test/idl/ok/integer.js.ok index ac73a9c7d56..206af7597d4 100644 --- a/test/idl/ok/integer.js.ok +++ b/test/idl/ok/integer.js.ok @@ -1,5 +1,5 @@ export default ({ IDL }) => { - return new IDL.ActorInterface({'f': IDL.Func([IDL.Nat8], [IDL.Int16], []), + return IDL.Service({'f': IDL.Func([IDL.Nat8], [IDL.Int16], []), 'g': IDL.Func([IDL.Nat64], [IDL.Int64], []), 'h': IDL.Func([IDL.Int8], [IDL.Nat], [])}); }; diff --git a/test/idl/ok/keywords.js.ok b/test/idl/ok/keywords.js.ok index c3047104cb7..418cc8ae566 100644 --- a/test/idl/ok/keywords.js.ok +++ b/test/idl/ok/keywords.js.ok @@ -1,8 +1,7 @@ export default ({ IDL }) => { const const_ = IDL.Record({'type_': IDL.Nat, 'vec_': IDL.Nat, 'service_': IDL.Nat}) - return new IDL.ActorInterface({ - 'blob': IDL.Func([const_], [IDL.Vec(IDL.Nat8)], []), + return IDL.Service({'blob': IDL.Func([const_], [IDL.Vec(IDL.Nat8)], []), 'record': IDL.Func([IDL.Nat, IDL.Nat, IDL.Variant({})], [IDL.Nat, IDL.Record({})], [])}); diff --git a/test/idl/ok/principal.js.ok b/test/idl/ok/principal.js.ok index 336828d80e0..69437d4e4be 100644 --- a/test/idl/ok/principal.js.ok +++ b/test/idl/ok/principal.js.ok @@ -1,4 +1,4 @@ export default ({ IDL }) => { - return new IDL.ActorInterface({ + return IDL.Service({ 'getCaller': IDL.Func([], [IDL.Principal, IDL.Nat32], [])}); }; diff --git a/test/idl/ok/px.js.ok b/test/idl/ok/px.js.ok index 05f72377b6b..f1258f3a583 100644 --- a/test/idl/ok/px.js.ok +++ b/test/idl/ok/px.js.ok @@ -12,7 +12,7 @@ export default ({ IDL }) => { IDL.Record({'region': RegionId, 'user': UserId, 'truckType': TruckTypeId}) const OpEntId = IDL.Opt(EntId) const IdErr = IDL.Record({'idErr': OpEntId}) - return new IDL.ActorInterface({ + return IDL.Service({ 'getInventory': IDL.Func([IDL.Nat, UserInfo], [Inventory, IdErr], ['query'])}); }; diff --git a/test/idl/ok/test.js.ok b/test/idl/ok/test.js.ok index 47faf6ba921..a59732b9d19 100644 --- a/test/idl/ok/test.js.ok +++ b/test/idl/ok/test.js.ok @@ -11,7 +11,7 @@ export default ({ IDL }) => { 'current': IDL.Func([], [IDL.Nat], [])}) ], [])}) - return new IDL.ActorInterface({ + return IDL.Service({ 'addUser': IDL.Func([IDL.Text, IDL.Nat8], [IDL.Nat64], []), 'userName': IDL.Func([IDL.Nat64], [IDL.Text], ['query']), 'userAge': IDL.Func([IDL.Nat64], [IDL.Nat8], ['query']), diff --git a/test/idl/ok/unicode.js.ok b/test/idl/ok/unicode.js.ok index 3123178bc2b..b8802ecb54f 100644 --- a/test/idl/ok/unicode.js.ok +++ b/test/idl/ok/unicode.js.ok @@ -5,7 +5,7 @@ export default ({ IDL }) => { const B = IDL.Variant({'': IDL.Null, '空的': IDL.Null, ' 空的 ': IDL.Null, '1⃣️2⃣️3⃣️': IDL.Null}) - return new IDL.ActorInterface({'函数名': IDL.Func([A], [B], []), + return IDL.Service({'函数名': IDL.Func([A], [B], []), '': IDL.Func([IDL.Nat], [IDL.Nat], []), '👀': IDL.Func([IDL.Nat], [IDL.Nat], ['query']), '✈️ 🚗 ⛱️ ': IDL.Func([], [], ['oneway'])}); From d6b8d0f71094e802a8a52eb886b7a094e340d324 Mon Sep 17 00:00:00 2001 From: DFINITY bot <58022693+dfinity-bot@users.noreply.github.com> Date: Fri, 13 Mar 2020 01:08:02 +0100 Subject: [PATCH 1125/1176] niv common: update c022ff9f -> c83d9681 (#1292) ## Changelog for common: Commits: [dfinity-lab/common@c022ff9f...c83d9681](https://github.com/dfinity-lab/common/compare/c022ff9f16ed0b9e3eb4ed97f26b493de3858df7...c83d968179e9c927b8bcf1cc9e34b21ba56faff1) * [`e412ad21`](https://github.com/dfinity-lab/common/commit/e412ad21e54a693ff9f4386eb94a936a80d8a478) Update niv-updater-action to v5 --- nix/sources.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/sources.json b/nix/sources.json index 6971f6ce832..359cfce9e53 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -2,7 +2,7 @@ "common": { "ref": "master", "repo": "ssh://git@github.com/dfinity-lab/common", - "rev": "c022ff9f16ed0b9e3eb4ed97f26b493de3858df7", + "rev": "c83d968179e9c927b8bcf1cc9e34b21ba56faff1", "type": "git" }, "dfinity": { From d9f081ed55e56db502722788dbb758b6b654ed41 Mon Sep 17 00:00:00 2001 From: DFINITY bot <58022693+dfinity-bot@users.noreply.github.com> Date: Tue, 17 Mar 2020 01:08:16 +0100 Subject: [PATCH 1126/1176] niv common: update c83d9681 -> 305dbe73 (#1297) ## Changelog for common: Commits: [dfinity-lab/common@c83d9681...305dbe73](https://github.com/dfinity-lab/common/compare/c83d968179e9c927b8bcf1cc9e34b21ba56faff1...305dbe73ae22af77769b377d2b5eb3d519918659) * [`2ba9d496`](https://github.com/dfinity-lab/common/commit/2ba9d49663307f5272866cb4d2899b32ff1bc4fe) nix/sources.json: upgrade naersk --- nix/sources.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/sources.json b/nix/sources.json index 359cfce9e53..73409e82c83 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -2,7 +2,7 @@ "common": { "ref": "master", "repo": "ssh://git@github.com/dfinity-lab/common", - "rev": "c83d968179e9c927b8bcf1cc9e34b21ba56faff1", + "rev": "305dbe73ae22af77769b377d2b5eb3d519918659", "type": "git" }, "dfinity": { From 3c2e3962e00b2196930feabced4b8c68f117efea Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Wed, 18 Mar 2020 12:09:54 +0000 Subject: [PATCH 1127/1176] inference revisions for rossberg (#1296) * implement is_con/as_con * address nits * don't add bounds of tbs to u, instead take glb at end so that dom(u) accurately reflects polar occurrences * don't add bounds of tbs to u, instead take glb at end so that dom(u) accurately reflects polar occurrences * Update src/mo_frontend/typing.ml * Update src/mo_frontend/bi_match.ml Co-Authored-By: Andreas Rossberg * Update src/mo_types/type.ml Co-Authored-By: Andreas Rossberg * Update src/mo_frontend/typing.ml Co-authored-by: Andreas Rossberg --- src/mo_frontend/bi_match.ml | 82 ++++++++++++++++++++---------------- src/mo_frontend/bi_match.mli | 8 ++-- src/mo_frontend/typing.ml | 39 ++++++++--------- src/mo_types/type.ml | 2 + src/mo_types/type.mli | 2 + test/fail/inference.mo | 4 +- test/fail/ok/inference.tc.ok | 8 ---- 7 files changed, 74 insertions(+), 71 deletions(-) diff --git a/src/mo_frontend/bi_match.ml b/src/mo_frontend/bi_match.ml index f28272682da..c70de695437 100644 --- a/src/mo_frontend/bi_match.ml +++ b/src/mo_frontend/bi_match.ml @@ -12,12 +12,16 @@ let denotable t = let t' = normalize t in not (is_mut t' || is_typ t') +let bound c = match Con.kind c with + | Abs ([], t) -> t + | _ -> assert false + (* Check instantiation `ts` satisfies bounds `tbs` and all the pairwise sub-typing relations in `subs`; used to sanity check inferred instantiations *) let verify_inst tbs subs ts = List.length tbs = List.length ts && List.for_all2 (fun t tb -> sub t (open_ ts tb.bound)) ts tbs && - List.for_all (fun (t1,t2) -> sub (open_ ts t1) (open_ ts t2)) subs + List.for_all (fun (t1, t2) -> sub (open_ ts t1) (open_ ts t2)) subs let bi_match_subs scope_opt tbs subs = let ts = open_binds tbs in @@ -25,7 +29,7 @@ let bi_match_subs scope_opt tbs subs = let ts1 = List.map (fun (t1, _) -> open_ ts t1) subs in let ts2 = List.map (fun (_, t2) -> open_ ts t2) subs in - let cs = List.map (fun t -> match t with Con(c,_) -> c | _ -> assert false) ts in + let cs = List.map (fun t -> fst (as_con t)) ts in let flexible = let cons = ConSet.of_list cs in @@ -43,7 +47,7 @@ let bi_match_subs scope_opt tbs subs = | _, _ -> None in - let rec bi_match_typ rel eq ((l,u) as inst) (any:ConSet.t) (t1:typ) (t2:typ) = + let rec bi_match_typ rel eq ((l, u) as inst) any t1 t2 = if t1 == t2 || SS.mem (t1, t2) !rel then Some inst else begin @@ -72,13 +76,13 @@ let bi_match_subs scope_opt tbs subs = | None -> ConEnv.add con2 t1 l in let u = if rel != eq then u else - match ConEnv.find_opt con2 u with - | Some t1' -> - let glb = glb t1 t1' in - ConEnv.add con2 glb u - | None -> ConEnv.add con2 t1 u + match ConEnv.find_opt con2 u with + | Some t1' -> + let glb = glb t1 t1' in + ConEnv.add con2 glb u + | None -> ConEnv.add con2 t1 u in - Some (l,u) + Some (l, u) | Con (con1, ts1), _ when flexible con1 -> assert (ts1 = []); if mentions t2 any || not (denotable t2) then @@ -98,7 +102,7 @@ let bi_match_subs scope_opt tbs subs = ConEnv.add con1 glb u | None -> ConEnv.add con1 t2 u in - Some (l,u) + Some (l, u) | Con (con1, ts1), Con (con2, ts2) -> (match Con.kind con1, Con.kind con2 with | Def (tbs, t), _ -> (* TBR this may fail to terminate *) @@ -150,7 +154,7 @@ let bi_match_subs scope_opt tbs subs = (match bi_match_binds rel eq inst any tbs1 tbs2 with | Some (inst, ts) -> let any' = List.fold_right - (function Con(c,[]) -> ConSet.add c | _ -> assert false) ts any + (fun t -> ConSet.add (fst (as_con t))) ts any in (match bi_match_list bi_match_typ rel eq inst any' (List.map (open_ ts) t21) (List.map (open_ ts) t11) @@ -187,9 +191,9 @@ let bi_match_subs scope_opt tbs subs = | tf1::tfs1', tf2::tfs2' -> (match compare_field tf1 tf2 with | 0 -> - (match bi_match_typ rel eq inst any tf1.typ tf2.typ with - | Some inst -> bi_match_fields rel eq inst any tfs1' tfs2' - | None -> None) + (match bi_match_typ rel eq inst any tf1.typ tf2.typ with + | Some inst -> bi_match_fields rel eq inst any tfs1' tfs2' + | None -> None) | -1 when rel != eq -> bi_match_fields rel eq inst any tfs1' tfs2 | _ -> None @@ -250,28 +254,33 @@ let bi_match_subs scope_opt tbs subs = let bds = List.map (fun tb -> open_ ts tb.bound) tbs in let ce = ConSet.of_list cs in List.iter2 (fun c bd -> if mentions bd ce then fail_open_bound c bd) cs bds; - let add c b u = if eq b Any then u else ConEnv.add c b u in - let u = List.fold_right2 add cs bds ConEnv.empty in - let l,u = match scope_opt, tbs with - | Some c, {sort=Scope;_}::tbs -> - ConEnv.singleton (List.hd cs) c, - add (List.hd cs) (lub c (List.hd bds)) u - | None, {sort=Scope;_}::tbs -> - failwith "scope instantiation required but no scope available" + let l, u = match scope_opt, tbs with + | Some c, {sort = Scope; _}::tbs -> + let c0 = List.hd cs in + ConEnv.singleton c0 c, + ConEnv.singleton c0 c + | None, {sort = Scope; _}::tbs -> + failwith "scope instantiation required but no scope available" | _, _ -> ConEnv.empty, - u + ConEnv.empty in - match bi_match_list - bi_match_typ (ref SS.empty) (ref SS.empty) (l, u) ConSet.empty ts1 ts2 with - | Some (l,u) -> + match + bi_match_list bi_match_typ + (ref SS.empty) (ref SS.empty) (l, u) ConSet.empty ts1 ts2 + with + | Some (l, u) -> let us = List.map (fun c -> match ConEnv.find_opt c l, ConEnv.find_opt c u with | None, None -> Non - | None, Some ub -> ub - | Some lb, None -> lb + | None, Some ub -> glb ub (bound c) + | Some lb, None -> + if sub lb (bound c) then + lb + else fail_over_constrained lb c (bound c) | Some lb, Some ub -> + let ub = glb ub (bound c) in if eq lb ub then ub else if sub lb ub then @@ -287,12 +296,11 @@ let bi_match_subs scope_opt tbs subs = (Printf.sprintf "bug: inferred bad instantiation\n <%s>;\nplease report this error message as a bug and, for now, supply an explicit instantiation instead" (String.concat ", " (List.map string_of_typ us))) - | None -> failwith (Printf.sprintf - "no instantiation of %s makes %s" - (String.concat ", " (List.map string_of_con cs)) - (String.concat " and " - (List.map2 (fun t1 t2 -> - Printf.sprintf "%s <: %s" (string_of_typ t1) (string_of_typ t2)) - ts1 ts2))) - - + | None -> + failwith (Printf.sprintf + "no instantiation of %s makes %s" + (String.concat ", " (List.map string_of_con cs)) + (String.concat " and " + (List.map2 (fun t1 t2 -> + Printf.sprintf "%s <: %s" (string_of_typ t1) (string_of_typ t2)) + ts1 ts2))) diff --git a/src/mo_frontend/bi_match.mli b/src/mo_frontend/bi_match.mli index a68f2511dee..1a2af9d1e07 100644 --- a/src/mo_frontend/bi_match.mli +++ b/src/mo_frontend/bi_match.mli @@ -13,15 +13,17 @@ open Type * a subtype violation; or * some parameter in `tbs` being under constrained (`ts` is ambiguous); or * some parameter in `tbs` being over constrained (no `ts` exists); or - For every pair (t1, t2) in `subs`, at least one of `t1` or `t2` must be closed and the other - may be "open" mentioning parameters in `tbs` by index (Var i, i < |`tbs`|). + For every pair (t1, t2) in `subs`, one of `t1` or `t2` must be closed + w.r.t `tbs` and the other may be "open" mentioning parameters in `tbs` + by index (Var i, i < |`tbs`|). + (This a pre-condition that avoid the need for full unitication.) The ordering on instantiations `ts` is determined pointwise depending on the occurrence of that variable in `subs` and is: * sub-typing ( _ <: _) on variables that occur strictly positively in subs * super-typing ( _ :> _) on variables that occur strictly negatively in subs * equivalence ( _ = _ ) on variables that occur both positively and negatively in subs - * trivial {(Non,Non)} on variables that don't occur in subs + * trivial relation {(Non,Non)} on variables that don't occur at all in subs (modulo mixing my left foot with my right) *) diff --git a/src/mo_frontend/typing.ml b/src/mo_frontend/typing.ml index 2fb01fc9536..4d0ba5699ad 100644 --- a/src/mo_frontend/typing.ml +++ b/src/mo_frontend/typing.ml @@ -1212,9 +1212,7 @@ and infer_call env exp1 inst exp2 at t_expect_opt = in let ts, t_arg', t_ret' = match tbs, inst.it with - | [], (None | Some []) -> (* no inference required *) - if not env.pre then check_exp env t_arg exp2; - [], t_arg, t_ret + | [], (None | Some []) (* no inference required *) | [{T.sort = T.Scope;_}], _ (* special case to allow t_arg driven overload resolution *) | _, Some _ -> (* explicit instantiation, check argument against instantiated domain *) @@ -1226,23 +1224,22 @@ and infer_call env exp1 inst exp2 at t_expect_opt = ts, t_arg', t_ret' | _::_, None -> (* implicit, infer *) let t2 = infer_exp env exp2 in - match - (* i.e. exists_unique ts . t2 <: open_ ts t_arg /\ open ts_ t_arg <: t] *) + try + (* i.e. exists_unique ts . t2 <: open_ ts t_arg /\ open ts_ t_ret <: t] *) + let ts = Bi_match.bi_match_subs (scope_of_env env) tbs - [(t2, t_arg); (t_ret, t)] - with - | ts -> - let t_arg' = T.open_ ts t_arg in - let t_ret' = T.open_ ts t_ret in - ts, t_arg', t_ret' - | exception Failure msg -> - error env at - "cannot implicitly instantiate function of type\n %s\nto argument of type\n %s%s\n%s" - (T.string_of_typ t1) - (T.string_of_typ t2) - (if Option.is_none t_expect_opt then "" - else Printf.sprintf "\nto produce result of type\n %s" (T.string_of_typ t)) - msg + [(t2, t_arg); (t_ret, t)] in + let t_arg' = T.open_ ts t_arg in + let t_ret' = T.open_ ts t_ret in + ts, t_arg', t_ret' + with Failure msg -> + error env at + "cannot implicitly instantiate function of type\n %s\nto argument of type\n %s%s\n%s" + (T.string_of_typ t1) + (T.string_of_typ t2) + (if Option.is_none t_expect_opt then "" + else Printf.sprintf "\nto produce result of type\n %s" (T.string_of_typ t)) + msg in inst.note <- ts; if not env.pre then begin @@ -1255,8 +1252,8 @@ and infer_call env exp1 inst exp2 at t_expect_opt = error env exp2.at "shared function call result contains abstract type\n %s" (T.string_of_typ_expand t_ret'); - end - end; + end + end; (* note t_ret' <: t checked by caller if necessary *) t_ret' diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index d208a5f43fe..463b2747b54 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -349,6 +349,7 @@ let is_func = function Func _ -> true | _ -> false let is_async = function Async _ -> true | _ -> false let is_mut = function Mut _ -> true | _ -> false let is_typ = function Typ _ -> true | _ -> false +let is_con = function Con _ -> true | _ -> false let invalid s = raise (Invalid_argument ("Type." ^ s)) @@ -365,6 +366,7 @@ let as_async = function Async (t1, t2) -> (t1, t2) | _ -> invalid "as_async" let as_mut = function Mut t -> t | _ -> invalid "as_mut" let as_immut = function Mut t -> t | t -> t let as_typ = function Typ c -> c | _ -> invalid "as_typ" +let as_con = function Con (c, ts) -> c,ts | _ -> invalid "as_con" let as_seq t = match normalize t with diff --git a/src/mo_types/type.mli b/src/mo_types/type.mli index 25e207310ba..0ac066f461f 100644 --- a/src/mo_types/type.mli +++ b/src/mo_types/type.mli @@ -108,6 +108,7 @@ val is_func : typ -> bool val is_async : typ -> bool val is_mut : typ -> bool val is_typ : typ -> bool +val is_con : typ -> bool val as_prim : prim -> typ -> unit val as_obj : typ -> obj_sort * field list @@ -122,6 +123,7 @@ val as_async : typ -> typ * typ val as_mut : typ -> typ val as_immut : typ -> typ val as_typ : typ -> con +val as_con : typ -> con * typ list val as_prim_sub : prim -> typ -> unit val as_obj_sub : string list -> typ -> obj_sort * field list diff --git a/test/fail/inference.mo b/test/fail/inference.mo index 4fdee542c74..c33372ecc5a 100644 --- a/test/fail/inference.mo +++ b/test/fail/inference.mo @@ -46,7 +46,7 @@ func curry(f : (A,B)->C) : A->B->C { func(a:A): B->C { func(b:B):C { f(a,b) } } }; -func add(m:N, n:N) : N { m/**/(succ,n) }; +func add(m:N, n:N) : N { m/**/(succ,n) }; func mult1(m:N, n:N): N { m/**/(func (a:N) : N { add(a,n)},zero) }; @@ -139,7 +139,7 @@ func g(x : T) { func h(x : T) { func f(y : U) {}; - f(x); // reject, underconstrained U + f(x); // accept }; func i(x : T) { diff --git a/test/fail/ok/inference.tc.ok b/test/fail/ok/inference.tc.ok index d191704dd9a..017abee4c51 100644 --- a/test/fail/ok/inference.tc.ok +++ b/test/fail/ok/inference.tc.ok @@ -107,14 +107,6 @@ to produce result of type () over-constrained implicit instantiation requires T <: U <: {}, but T U -> () -to argument of type - T/35 -to produce result of type - () -under-constrained implicit instantiation T <: U <: {}, with T =/= {}; -explicit type instantiation required inference.mo:152.11-152.15: type error, cannot implicitly instantiate function of type U -> U to argument of type From f0e729d5a0a02eab60702e8a00d158cf485ec654 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 18 Mar 2020 23:59:39 +0100 Subject: [PATCH 1128/1176] RTS: Create upgrade hooks also on drun (#1249) * Bump drun mostly to see how well we work with their upgrade support. Also included: ``` 17507c070 Merge pull request #2717 from dfinity-lab/paulliu/registry-config 86f652e66 Merge pull request #2733 from dfinity-lab/drun-upgrade b9d312500 State Manager: improve docs for the interface (#2719) 82618cf9b Move canister_init from hypervisor into ExecutionEnvironment (#2721) 297bf56bc Remove unnecessary inputs 9db1edb76 Move cargo executables to overlay 54764e227 INF-1013: Add tarpaulin to shell 0c8cc2356 Make CompiledBinary optional in CanisterState (#2713) 9a2b9af38 drun logging: require a command line argument (#2714) 271067cd2 DFN-1392 Rename OutputStream to Stream (as per the spec) (#2707) 9301cf7e2 Merge pull request #2718 from dfinity-lab/wasmtime_signal_stack d63647ae5 Merge pull request #2716 from dfinity-lab/paulliu/tmux-resume-test d88f80238 Merge pull request #2702 from dfinity-lab/useAsRefInsteadOfCustomTrait aae50392b Merge pull request #2546 from dfinity-lab/david-new-persistence 263bd51d8 Merge pull request #2700 from dfinity-lab/skaestle/fix-perf-tests 9dcfc4100 Use byte literal for rust 1.41 6fc1050bb Merge pull request #2641 from dfinity-lab/rsub/xport-config-check 33f656002 Adding keys for multi-sigs to registry's CryptoKey (#2692) 70144dfff DFN-1366: Introduce RwLock and Locking Layer for Keygen (#2675) 0a3c981b6 Merge pull request #2604 from dfinity-lab/messageMakerSkeleton c20870ada Merge pull request #2659 from dfinity-lab/dkgStateReader 17ed1b65d [P2P-184] Restructuring Ingress Pool (#2625) d60dd78c4 DFN-1318 Don't panic on full input queue (#2686) de423fdef Adding logging capability to drun (#2679) 56c43abf5 Merge pull request #2682 from dfinity-lab/kw/sort-deps 9b3f3566c Make ic_crypto path configurable (#2655) c40d741fc Merge pull request #2654 from dfinity-lab/paulliu/temp-fix-of-state-purging 240baab79 DFN-1244: Use RawIngress as the content of SignedIngress (#2438) a4c481668 Merge pull request #2683 from dfinity-lab/mw/better-test-panic-message 318798a8e Merge pull request #2621 from dfinity-lab/CON-288 e4610188b [DFN-1388] Use prometheus metrics in StateManager 4ba0243a2 DFN-1358: Call upgrade hooks in canister upgrades. (#2676) 733a51143 Merge pull request #2668 from dfinity-lab/dsd/remove_unused_metric b35786c79 DFN-1358 Add support for canister upgrade system methods in hypervisor (#2651) 5f22c697d Add local testnet scripts (#2657) 86ea90d5d Merge pull request #2658 from dfinity-lab/rsub/fake-transport 1c060d5c1 Merge pull request #2656 from dfinity-lab/paulliu/fix-test-randomness 7e078dfbc StateManager: a tool for inspecting states (#2664) 2d3eeed9b StateManager: add certification API (#2650) adecfe2c0 Merge pull request #2660 from dfinity-lab/cryptoSigningAndHashingOfDKGTypes 2055a6014 Merge pull request #2529 from dfinity-lab/addGetRange e4f188c7a DFN-1365: Remove `mut` modifiers in DKG API (#2596) 51604d499 Merge pull request #2559 from dfinity-lab/johnw/fork 2201d561b Deterministic NaNs in the replica (#2549) c77ea1ed3 CON-230: proptests for pool purger (#2525) 7c2ad9cfe DFN-1376: Use references in DKG API rather than taking ownership (#2640) 267e1611f DFN-769: Remove message-type-to-params from Crypto Config (#2597) b7d9b4869 Fixed warnings in library code (#2649) df31d3cdf Made it so macro errors never cause a panic in the nightly compiler (#2648) 52ec588eb Crypto/DFN-1152: Factor out bls core (#2619) 3ba184507 Merge pull request #2613 from dfinity-lab/manu/delete-consensus-config-trait db0f952f1 DFN-1318 Return message when enqueuing fails (#2647) 250bef54e DFN-1354 & DFN-1357 Fixes to canister creation. 65ea63214 DFN-1147: Remove Signature in Types Crate (#2591) afd9a0459 Scheduler should execute messages if remaining gas is exactly exec_gas (#2633) d6711e271 Merge pull request #2629 from dfinity-lab/kw/wasmtime-integration 151ae697e DFN-1343: Construct hash tree from replicated state (#2583) 78d7569eb Rename allocation to compute_allocation (#2634) 16425864c DFN-1374 Improved cross-crate test-only methods (#2612) a9f42c202 DFN-1374 Test CanisterState method preconditions. (#2628) 64ad9fa48 Add more bits of state to canonical state traversal (#2589) e643e0b2f Merge pull request #2617 from dfinity-lab/manu/remove-function-from-xnet-selector-trait 2b16a69f0 Merge pull request #2626 from dfinity-lab/mw/remove-mutable-globals-validation 6a9a41ff7 DFN-1374 Simplify queue reservations. Add doc comments. (#2611) 0aad82b23 CON-238 RandomGraph delivery strategy for consensus test framework (#2558) a639f3b80 Merge pull request #2501 from dfinity-lab/david-split-in-memory-pool 488f8488a DFN-1367: Make DkgAlgorithm trait object-safe (#2603) f6a23fa57 Merge pull request #2572 from dfinity-lab/fs/taketransportimpl 83fffa587 Merge pull request #2602 from dfinity-lab/rsub/tokio-upgrade 00018a47e Crypto/DFN-1333: basic sig cli (#2550) b85ba8db7 Linking wasm files was failing on some Linux systems (#2599) e2dbf9c8a Add --benches in dcheck (#2587) 445b9ed2b DFN-1374 Use CanisterQueues instead of {Ingress|Input|Output}Queue directly (#2562) 34996c264 Merge pull request #2570 from dfinity-lab/fs/metricgauge 8d0c109a5 Merge pull request #2360 from dfinity-lab/dedup-by-attribute 6846d748d Fixed a few typos (#2600) b34e591ea SigsegvMemoryTracker: Perf improvement (#2590) 9821a1aa4 Overhaul SystemApiImpl (#2571) 3b153fd03 Squashed crypto/DFN-1152-clib-threshold-commitments from 1ed9097bca94d024ff1f75d8cf189cc482d87ef9 (#2444) 7ad8d66d2 Bump mockall from 0.5.0 to 0.6.0. This gets rid of all the clippy warnings when compiling with Rust 1.41.0. (See https://github.com/rust-lang/rust/issues/66145 and https://github.com/asomers/mockall/pull/62 for context.) (#2573) 9d2990f55 Provide conversion from Request or Response to RequestOrResponse. (#2575) 732337679 Implement ++ and -- (equivalents) for AmountOf. (#2574) 058fe36f2 Merge pull request #2560 from dfinity-lab/rsub/xport-handshake b85f967ed Merge pull request #2567 from dfinity-lab/dsd/comment_fix 534971043 DFN-1147: Remove obsolete Signer trait (#2561) 1bfae2097 Crypto/DFN-1338: move existing toplevel code (#2541) d38ff772e Crypto DFN:1331 cli hash tweaks (#2553) 6539d8e42 Merge pull request #2548 from dfinity-lab/skaestle/bench-execution-update 6170f2fd4 Remove scheduler flaky test (#2563) a674e871b crypto/DFN-962: adding a signature verification test with an invalid public key (#2552) dc8fd4474 [DFN-1325] Support upgrading canisters (#2555) eab3250b7 DFN-1374 Address review comments for #2531 (#2556) cee79cb33 config 23516fa17 Revert "Update config sample" 9e6be014c Update config sample 9c1e53f7d Copy helper function bf732aae8 Sort 8c1c1c072 Rename Config to EmbedderConfig, flatten namespace 814896c2e Move Lucet embedder 00063c079 Cleanup bcd569db8 Merge pull request #2349 from dfinity-lab/cleanerDefinitionForCommitteeThreshold b521d3e05 Removed a very noisey debug statement (#2554) 86cf72361 instrumentation: table/memory export for wasmtime; DFN-1296, DFN-1297 (#2518) 06665ee1e DFN-1242: Add proptest for verifying the scheduling algorithm (#2535) 023626da1 Better FakeIngressSelector (#2483) 864c39a7f MessageId: use LEB128 for numbers to compute message ids (#2462) e9b00daab Merge pull request #2489 from dfinity-lab/kb/resumability cabbe8f28 Tidying up of `struct ExecutionEnvironment` (#2499) 53d2495ee Merge pull request #2543 from dfinity-lab/dsd/user_query_send_sync 1ae25197b Merge pull request #2530 from dfinity-lab/CON-273 4b2fd5d19 Update wabt to 0.9.2 (#2540) 111dceebf [DFN-1325] Add 'mode' to CanisterInstallMessage (#2522) be49ce40b crypto/DFN-962: adding tests with invalid signatures (#2527) 52ef1e349 Make recover_checkpoint public (#2542) 1a085fa00 Crypto/dfn 1331 hashing cli (#2482) ec87b969c Merge pull request #2511 from dfinity-lab/skaestle/bench-user-calls f812d7073 crypto/DFN-1152: clib-threshold-polynomial-tweaks (#2526) 8c535a7d4 Merge pull request #2510 from dfinity-lab/manu/rephrase-aggregate-function 9c94226aa DFN-1374 Introduce CanisterQueues type, a wrapper around ingress queue, input queues and output queues. (#2531) 9042b870c Merge pull request #2533 from dfinity-lab/wasmtime-embedder e360b013e Merge pull request #2450 from dfinity-lab/dkgTypes 1496261d3 DFN-1281: Allow CSPRNG creation based on randomness purpose (#2440) 172925c8b Merge pull request #2515 from dfinity-lab/CON-269 31b38b340 Merge pull request #2492 from dfinity-lab/paulliu/test-execution-height-unavailable e65501c72 DFN-1374 Rename `Canister{Input|Output}Queue` to `{Input|Output}Queue` (#2524) 91f3ce958 Group tests in message_id/src/lib.rs (#2523) 6ad5597fc Merge pull request #2512 from dfinity-lab/chmllr/minor-improvements ca151a444 Crypto/DFN:1327 restructure clib (#2484) 724b3c27a Alphabetize members in top level Cargo.toml (#2497) e6f836a85 Merge pull request #2473 from dfinity-lab/rsub/xport-ports-1 c36e4cc88 Merge pull request #2493 from dfinity-lab/generalizePoolReaderFunctions ``` * RTS: Create upgrade hooks also on drun using the scaffold implementation of just copying all heap. Includes the drun bump in #1248. * Update test output * More bumping ``` 4baa063b5 Merge pull request #2729 from dfinity-lab/rsub/conn-event 585832cc7 Merge pull request #2737 from dfinity-lab/basvandijk/do-not-use-tmp-persistent-pool 24407308a Renaming some SigSegv and the MemoryTracker fields (#2726) d8534a766 Merge pull request #2728 from dfinity-lab/proptest_fixes ``` * Bump drun some more ``` 0da721854 Merge pull request #2786 from dfinity-lab/ops-15 811fb9098 DFN-1366: Adapt Crypto Initialization for Multi-Threading (#2723) 53b33f512 Verify alternative options in the sample config (#2632) c018ee387 Merge pull request #2774 from dfinity-lab/bump_crossbeam aed2a1aab P2P-201: Fix bug in exists() in ingress_pool (#2762) 25738a992 Merge pull request #2761 from dfinity-lab/CON-304 10019d068 Memory tracker bench performance regression (#2755) cf38daa45 Merge pull request #2335 from dfinity-lab/johnw/simulator 41810e84d Add the random tape and random tape share types (#2745) c5e03bf4d Merge pull request #2642 from dfinity-lab/david-persistence-integration 1edb79452 Rename available_compute_allocation to compute_capacity (#2767) 49e0fab77 Merge pull request #2645 from dfinity-lab/dkgPayloadBuilder 1614d6063 DFN-1392 Use BTreeMap for ReplicatedState::canister_states (#2760) 8ff08dd95 Merge pull request #2764 from dfinity-lab/sort-deps d4f93a91b Merge pull request #2743 from dfinity-lab/manu/proptest c42df7c33 Add more context to assertions in canister state (#2747) 538c312c5 DFN-1366: Create Locking Layer for 'sign' Module (#2704) 4ee54534e Fix for a bench regression introduced in 24407308a (#2750) 259b3d7ed CON-284: adds initial certification plumbing (#2636) ``` * Bump drun more ``` 9f947598f Deprecate mod.rs in ic-execution-environment (#2815) cca358af8 Fix doc test in crypto (#2814) da5873fce Get rid of circular dependencies involving ic-test-utilities (#2789) fc752ed9c Cleanup benchmark (#2806) d02cd2744 +=libsecp256k1 crate (#2797) 3317f2d45 CON-299: certification: implement certification pool and artifact validation (#2771) fc6689046 CON-284: implements certification aggregation (#2725) 9f200004c Update tests (#2689) 83b945b5f Merge pull request #2775 from dfinity-lab/mw/wasmtime-new-system-api 2daf8a232 Merge pull request #2777 from dfinity-lab/paulliu/catchup-types ede968e55 Merge pull request #2805 from dfinity-lab/johnw/logsimpl 2fb5f2cda Merge pull request #2802 from dfinity-lab/dsd/make_http_config_more_readable 28556dd6b DFN-1414 Fix failures in executor (#2778) d8a20bbac - remove obsolete CspSigner methods (#2794) 7e8796197 Crypto/DFN-1220: Use RegistryView instead of PublicKeyRegistry in crypto component. (#2720) b6e046fd7 Merge pull request #2791 from dfinity-lab/mw/trap-to-error-signature-mismatch b145ad66a Merge pull request #2792 from dfinity-lab/paulliu/fix-localnet-conf 28c02a566 Crypto (DFN-1152): clib-threshold-crypto (#2661) 19582dba5 Merge pull request #2790 from dfinity-lab/remove_size_log 8a68ed5fd Merge pull request #2739 from dfinity-lab/paulliu/test-with-persistence-feature ``` * Only create upgrade scaffolding on ic or ref mode not in plain or wasi mode --- src/codegen/compile.ml | 13 +++++++------ test/drun-wrapper.sh | 2 +- test/run-drun/ok/upgrade.drun-run.ok | 11 +++++++++++ test/run-drun/upgrade.mo | 1 - 4 files changed, 19 insertions(+), 8 deletions(-) create mode 100644 test/run-drun/ok/upgrade.drun-run.ok diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 9c66b044829..301b1bc3db1 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -2913,6 +2913,10 @@ module Dfinity = struct E.add_func_import env "ic0" "msg_reply_data_append" (i32s 2) []; E.add_func_import env "ic0" "msg_reply" [] []; E.add_func_import env "ic0" "trap" (i32s 2) []; + E.add_func_import env "ic0" "stable_write" (i32s 3) []; + E.add_func_import env "ic0" "stable_read" (i32s 3) []; + E.add_func_import env "ic0" "stable_size" [] [I32Type]; + E.add_func_import env "ic0" "stable_grow" [I32Type] [I32Type]; () let system_imports env = @@ -2920,11 +2924,7 @@ module Dfinity = struct | Flags.ICMode -> import_ic0 env | Flags.RefMode -> - import_ic0 env; - E.add_func_import env "ic0" "stable_write" (i32s 3) []; - E.add_func_import env "ic0" "stable_read" (i32s 3) []; - E.add_func_import env "ic0" "stable_size" [] [I32Type]; - E.add_func_import env "ic0" "stable_grow" [I32Type] [I32Type] + import_ic0 env | Flags.WASIMode -> E.add_func_import env "wasi_unstable" "fd_write" [I32Type; I32Type; I32Type; I32Type] [I32Type]; | Flags.WasmMode -> () @@ -3160,7 +3160,8 @@ module Dfinity = struct compile_unboxed_const 0l ^^ G.i (Compare (Wasm.Values.I32 I32Op.Eq)) ^^ E.else_trap_with env "not a self-call" -let export_upgrade_scaffold env = if E.mode env = Flags.RefMode then +let export_upgrade_scaffold env = + if E.mode env = Flags.ICMode || E.mode env = Flags.RefMode then let pre_upgrade_fi = E.add_fun env "pre_upgrade" (Func.of_body env [] [] (fun env -> Lifecycle.trans env Lifecycle.InPreUpgrade ^^ diff --git a/test/drun-wrapper.sh b/test/drun-wrapper.sh index 164e11f7d8c..bd451301165 100755 --- a/test/drun-wrapper.sh +++ b/test/drun-wrapper.sh @@ -28,5 +28,5 @@ export LANG=C.UTF-8 EXTRA_BATCHES=100 (echo "install ic:2A012B $1 0x"; - if [ -n "$2" ]; then LANG=C perl -ne 'print "$1 ic:2A012B $2\n" if m,^//CALL (ingress|query) (.*),;print "upgrade ic:2A012B '"$1"' 0x" if m,^//CALL upgrade,; ' $2; fi; + if [ -n "$2" ]; then LANG=C perl -ne 'print "$1 ic:2A012B $2\n" if m,^//CALL (ingress|query) (.*),;print "upgrade ic:2A012B '"$1"' 0x\n" if m,^//CALL upgrade,; ' $2; fi; ) | $DRUN -c "$CONFIG" --extra-batches $EXTRA_BATCHES /dev/stdin diff --git a/test/run-drun/ok/upgrade.drun-run.ok b/test/run-drun/ok/upgrade.drun-run.ok new file mode 100644 index 00000000000..67e048e2cd0 --- /dev/null +++ b/test/run-drun/ok/upgrade.drun-run.ok @@ -0,0 +1,11 @@ +debug.print: init'ed +ingress System +Ok: Payload: 0x4449444c0000 +ingress Completed: Canister: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0000 +ingress Completed: Canister: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0000 +ingress System +Ok: Payload: 0x4449444c0000 +ingress Completed: Canister: Payload: 0x4449444c0000 +Ok: Payload: 0x4449444c0000 diff --git a/test/run-drun/upgrade.mo b/test/run-drun/upgrade.mo index dbfc0465aab..ed4f9df91a7 100644 --- a/test/run-drun/upgrade.mo +++ b/test/run-drun/upgrade.mo @@ -24,4 +24,3 @@ actor { //SKIP run //SKIP run-ir //SKIP run-low -//SKIP comp From 995d15b1c9420140ad9069de7699f0ac8f08c1f4 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 19 Mar 2020 14:02:49 +0100 Subject: [PATCH 1129/1176] Stdlib: Call the module principal, not principalId (#1298) as per https://github.com/dfinity-lab/ic-ref/pull/10 Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- stdlib/doc/index.adoc | 2 +- stdlib/src/{principalId.mo => principal.mo} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename stdlib/src/{principalId.mo => principal.mo} (100%) diff --git a/stdlib/doc/index.adoc b/stdlib/doc/index.adoc index 4bc9d248ecb..5d28fc9b22b 100644 --- a/stdlib/doc/index.adoc +++ b/stdlib/doc/index.adoc @@ -27,7 +27,7 @@ include::option.adoc[leveloffset=+1] include::function.adoc[leveloffset=+1] include::array.adoc[leveloffset=+1] include::blob.adoc[leveloffset=+1] -include::principalId.adoc[leveloffset=+1] +include::principal.adoc[leveloffset=+1] // Complex data structures diff --git a/stdlib/src/principalId.mo b/stdlib/src/principal.mo similarity index 100% rename from stdlib/src/principalId.mo rename to stdlib/src/principal.mo From 3aef8bf9c2f5029bae71c395ce3589992cb5eacb Mon Sep 17 00:00:00 2001 From: DFINITY bot <58022693+dfinity-bot@users.noreply.github.com> Date: Fri, 20 Mar 2020 01:22:49 +0100 Subject: [PATCH 1130/1176] niv common: update 305dbe73 -> 32956d48 (#1300) ## Changelog for common: Commits: [dfinity-lab/common@305dbe73...32956d48](https://github.com/dfinity-lab/common/compare/305dbe73ae22af77769b377d2b5eb3d519918659...32956d48089a239e8bf66ed17b38cd71ca5bf42a) * [`32956d48`](https://github.com/dfinity-lab/common/commit/32956d48089a239e8bf66ed17b38cd71ca5bf42a) nixpkgs => release-20.03 (dfinity-lab/common#160) --- nix/sources.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/sources.json b/nix/sources.json index 73409e82c83..eec2644cd1c 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -2,7 +2,7 @@ "common": { "ref": "master", "repo": "ssh://git@github.com/dfinity-lab/common", - "rev": "305dbe73ae22af77769b377d2b5eb3d519918659", + "rev": "32956d48089a239e8bf66ed17b38cd71ca5bf42a", "type": "git" }, "dfinity": { From 8cf3b88bc8630ae1268190bfabebd9b921024b0d Mon Sep 17 00:00:00 2001 From: DFINITY bot <58022693+dfinity-bot@users.noreply.github.com> Date: Sat, 21 Mar 2020 01:06:54 +0100 Subject: [PATCH 1131/1176] niv common: update 32956d48 -> aaaa0f66 (#1302) ## Changelog for common: Commits: [dfinity-lab/common@32956d48...aaaa0f66](https://github.com/dfinity-lab/common/compare/32956d48089a239e8bf66ed17b38cd71ca5bf42a...aaaa0f667e8bf01beb7a1c4bcb151175cf40d7a0) * [`aaaa0f66`](https://github.com/dfinity-lab/common/commit/aaaa0f667e8bf01beb7a1c4bcb151175cf40d7a0) INF-1115: Don't depend on crate sources in rust shell --- nix/sources.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/sources.json b/nix/sources.json index eec2644cd1c..65491078c3f 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -2,7 +2,7 @@ "common": { "ref": "master", "repo": "ssh://git@github.com/dfinity-lab/common", - "rev": "32956d48089a239e8bf66ed17b38cd71ca5bf42a", + "rev": "aaaa0f667e8bf01beb7a1c4bcb151175cf40d7a0", "type": "git" }, "dfinity": { From 9e0e17e9b27d66e5176b65a9b03a634bec637685 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Mon, 23 Mar 2020 13:03:00 -0600 Subject: [PATCH 1132/1176] fix: stdlib Array tabulateVar --- stdlib/src/array.mo | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/stdlib/src/array.mo b/stdlib/src/array.mo index 1e6e3c97273..30d7b949a72 100644 --- a/stdlib/src/array.mo +++ b/stdlib/src/array.mo @@ -156,9 +156,11 @@ module { public func tabulateVar(len : Nat, gen : Nat -> A) : [var A] { if (len == 0) { return [var] }; let xs = Prim.Array_init(len, gen 0); - for (i in range(1,len-1)) { - xs[i] := gen i; - }; + if (len > 1) { + for (i in range(1,len-1)) { + xs[i] := gen i; + }; + } return xs; }; } From 210f5e90c21fd826b8c924fc2c3a80ff47d9fa5c Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Mon, 23 Mar 2020 13:09:42 -0600 Subject: [PATCH 1133/1176] regression test for fix --- stdlib/test/arrayTest.mo | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/stdlib/test/arrayTest.mo b/stdlib/test/arrayTest.mo index 74527678001..56ad0515373 100644 --- a/stdlib/test/arrayTest.mo +++ b/stdlib/test/arrayTest.mo @@ -247,3 +247,15 @@ Prelude.printLn("Array"); assert(actual[i] == expected[i]); }; }; + +{ + Prelude.printLn(" tabulateVar"); + + // regression test for (fixed) issues in base cases, where func was called too often: + + let test0 = Array.tabulateVar(0, func (i:Nat) { assert(false); 0 }); + let test1 = Array.tabulateVar(1, func (i:Nat) { assert(i < 1); 0 }); + let test2 = Array.tabulateVar(2, func (i:Nat) { assert(i < 2); 0 }); + let test3 = Array.tabulateVar(3, func (i:Nat) { assert(i < 3); 0 }); + +}; From d8b1469f93550464744a03f8d66dfc27fd444e50 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 24 Mar 2020 10:43:37 +0100 Subject: [PATCH 1134/1176] run.sh: Do not warn about missing ic-ref when doing perf tests (#1305) --- test/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/run.sh b/test/run.sh index 4de67101d2d..dc4700c2c88 100755 --- a/test/run.sh +++ b/test/run.sh @@ -168,7 +168,7 @@ then fi fi -if [ $DTESTS = yes -o $PERF = yes ] +if [ $DTESTS = yes ] then if $IC_REF_RUN --help >& /dev/null then From 5be8d80be39e46918472392aea087bac88c5de11 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 24 Mar 2020 11:22:47 +0100 Subject: [PATCH 1135/1176] IR.FreeVars: Fix stupid typo (#1306) it is a bit worrying that this did not show up in our test suite. This fixes #1304 and includes the test case from there. Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- src/ir_def/freevars.ml | 2 +- test/run/issue1304.mo | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 test/run/issue1304.mo diff --git a/src/ir_def/freevars.ml b/src/ir_def/freevars.ml index dae0285ed63..def8366a5e7 100644 --- a/src/ir_def/freevars.ml +++ b/src/ir_def/freevars.ml @@ -13,7 +13,7 @@ type usage_info = { captured : bool; eager : bool } let join u1 u2 = { captured = u1.captured || u2.captured; - eager = u1.captured || u2.captured + eager = u1.eager || u2.eager } module M = Env.Make(String) diff --git a/test/run/issue1304.mo b/test/run/issue1304.mo new file mode 100644 index 00000000000..eea6c93303a --- /dev/null +++ b/test/run/issue1304.mo @@ -0,0 +1,6 @@ +class Pos() { + public var x: Int = 100; +}; + +let pos = Pos(); +let c = { a=pos.x; b=pos.x }; From 0b459e2b51846a38a2800a15be7da27e92e85911 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 24 Mar 2020 15:12:30 +0100 Subject: [PATCH 1136/1176] stdlib: Capitalize module names (#1307) this fixes #1176 where we decided that module file names should be capitalized, to match the idiomatic name for the module after imports. This also makes sure that we run `htmlproofer` over the generated docs to catch dead links (found some already). Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- default.nix | 13 ++++- stdlib/doc/README.md | 10 ++-- stdlib/doc/index.adoc | 50 +++++++++---------- stdlib/examples/actorspec/src/ActorSpec.mo | 8 +-- .../examples/produce-exchange/src/docTable.mo | 4 +- .../produce-exchange/src/serverActor.mo | 12 ++--- .../produce-exchange/src/serverLang.mo | 2 +- .../produce-exchange/src/serverModel.mo | 18 +++---- .../produce-exchange/src/serverModelTypes.mo | 2 +- .../produce-exchange/test/evalBulk.mo | 6 +-- .../test/loadWorkloadAndQueryBig.mo | 4 +- .../test/producerRemInventory.mo | 6 +-- .../test/profileFastCounts.mo | 2 +- .../test/retailerReserveMany.mo | 6 +-- .../test/simpleSetupAndQuery.mo | 6 +-- stdlib/examples/rx/test/RxTest.mo | 2 +- stdlib/src/{array.mo => Array.mo} | 4 +- stdlib/src/{assocList.mo => AssocList.mo} | 6 +-- stdlib/src/{blob.mo => Blob.mo} | 4 +- stdlib/src/{buf.mo => Buf.mo} | 10 ++-- stdlib/src/{char.mo => Char.mo} | 4 +- stdlib/src/{debug.mo => Debug.mo} | 4 +- stdlib/src/{function.mo => Function.mo} | 4 +- stdlib/src/{hash.mo => Hash.mo} | 6 +-- stdlib/src/{hashMap.mo => HashMap.mo} | 14 +++--- stdlib/src/{int.mo => Int.mo} | 6 +-- stdlib/src/{iter.mo => Iter.mo} | 8 +-- stdlib/src/{list.mo => List.mo} | 8 +-- stdlib/src/{nat.mo => Nat.mo} | 8 +-- stdlib/src/{none.mo => None.mo} | 4 +- stdlib/src/{option.mo => Option.mo} | 8 +-- stdlib/src/{prelude.mo => Prelude.mo} | 4 +- stdlib/src/{principal.mo => Principal.mo} | 7 ++- stdlib/src/{result.mo => Result.mo} | 8 +-- stdlib/src/{text.mo => Text.mo} | 8 +-- stdlib/src/{trie.mo => Trie.mo} | 16 +++--- stdlib/src/{trieMap.mo => TrieMap.mo} | 14 +++--- stdlib/src/{trieSet.mo => TrieSet.mo} | 8 +-- stdlib/test/arrayTest.mo | 6 +-- stdlib/test/bufTest.mo | 4 +- stdlib/test/functionTest.mo | 6 +-- stdlib/test/hashMapTest.mo | 4 +- stdlib/test/intTest.mo | 4 +- stdlib/test/iterTest.mo | 6 +-- stdlib/test/listTest.mo | 4 +- stdlib/test/natTest.mo | 4 +- stdlib/test/noneTest.mo | 6 +-- stdlib/test/optionTest.mo | 4 +- stdlib/test/textTest.mo | 4 +- stdlib/test/trieMapTest.mo | 4 +- 50 files changed, 193 insertions(+), 177 deletions(-) rename stdlib/src/{array.mo => Array.mo} (99%) rename stdlib/src/{assocList.mo => AssocList.mo} (98%) rename stdlib/src/{blob.mo => Blob.mo} (67%) rename stdlib/src/{buf.mo => Buf.mo} (96%) rename stdlib/src/{char.mo => Char.mo} (82%) rename stdlib/src/{debug.mo => Debug.mo} (87%) rename stdlib/src/{function.mo => Function.mo} (91%) rename stdlib/src/{hash.mo => Hash.mo} (97%) rename stdlib/src/{hashMap.mo => HashMap.mo} (96%) rename stdlib/src/{int.mo => Int.mo} (96%) rename stdlib/src/{iter.mo => Iter.mo} (96%) rename stdlib/src/{list.mo => List.mo} (99%) rename stdlib/src/{nat.mo => Nat.mo} (94%) rename stdlib/src/{none.mo => None.mo} (87%) rename stdlib/src/{option.mo => Option.mo} (95%) rename stdlib/src/{prelude.mo => Prelude.mo} (95%) rename stdlib/src/{principal.mo => Principal.mo} (53%) rename stdlib/src/{result.mo => Result.mo} (97%) rename stdlib/src/{text.mo => Text.mo} (71%) rename stdlib/src/{trie.mo => Trie.mo} (99%) rename stdlib/src/{trieMap.mo => TrieMap.mo} (96%) rename stdlib/src/{trieSet.mo => TrieSet.mo} (95%) diff --git a/default.nix b/default.nix index b60613d3b17..0d69cfa1189 100644 --- a/default.nix +++ b/default.nix @@ -395,11 +395,22 @@ rec { src = subpath ./stdlib/doc; outputs = [ "out" "adocs" ]; buildInputs = with nixpkgs; - [ bash perl asciidoctor ]; + [ bash perl asciidoctor html-proofer ]; buildPhase = '' patchShebangs . make STDLIB=${stdlib} ''; + + doCheck = true; + # These ones are needed for htmlproofer + LOCALE_ARCHIVE = nixpkgs.lib.optionalString nixpkgs.stdenv.isLinux "${nixpkgs.glibcLocales}/lib/locale/locale-archive"; + LANG = "en_US.UTF-8"; + LC_TYPE = "en_US.UTF-8"; + LANGUAGE = "en_US.UTF-8"; + checkPhase = '' + htmlproofer --disable-external _out/ + ''; + installPhase = '' mkdir -p $out mv _out/* $out/ diff --git a/stdlib/doc/README.md b/stdlib/doc/README.md index fb7950a0d9a..3bd640af74c 100644 --- a/stdlib/doc/README.md +++ b/stdlib/doc/README.md @@ -11,18 +11,18 @@ Run `make`. The output is in `_out`. The tool creates HTML anchors of these forms: - * `#mod-foo` for the module `foo` + * `#mod-Foo` for the module `Foo` (These are actually not generated, but are put in manually) - * `#foo_bar` for value `bar` in module `foo` - * `#foo_Bar` for type `Bar` in module `foo` + * `#Foo_bar` for value `bar` in module `Foo` + * `#Foo_Bar` for type `Bar` in module `Foo` To refer to them, use asciidoc syntax, as in - Also see <>. + Also see <>. ## Conventions and assumptions -See `stdlib/src/list.mo` for inspiration. +See `stdlib/src/List.mo` for inspiration. The doc generation tools requires the standard library code to be in a certain shape: diff --git a/stdlib/doc/index.adoc b/stdlib/doc/index.adoc index 5d28fc9b22b..87891ab6b03 100644 --- a/stdlib/doc/index.adoc +++ b/stdlib/doc/index.adoc @@ -5,46 +5,46 @@ This is the reference manual for the Motoko standard library. The following chapters each describe one module provided by the standard library. You can import the module under a name of your choice, e.g. .... -import List "stdlib:list" +import List "mo:stdlib/List" .... or .... -import L "stdlib:list" +import L "mo:stdlib/List" .... -For most basic types (<>, <>) there is one module with common operations on them. Additionally, there are more advanced data structures (<>) and utility modules (<>, <>). +For most basic types (<>, <>) there is one module with common operations on them. Additionally, there are more advanced data structures (<>) and utility modules (<>, <>). // Primitive data types -include::nat.adoc[leveloffset=+1] -include::int.adoc[leveloffset=+1] -include::char.adoc[leveloffset=+1] -include::text.adoc[leveloffset=+1] -include::none.adoc[leveloffset=+1] -include::option.adoc[leveloffset=+1] -include::function.adoc[leveloffset=+1] -include::array.adoc[leveloffset=+1] -include::blob.adoc[leveloffset=+1] -include::principal.adoc[leveloffset=+1] +include::Nat.adoc[leveloffset=+1] +include::Int.adoc[leveloffset=+1] +include::Char.adoc[leveloffset=+1] +include::Text.adoc[leveloffset=+1] +include::None.adoc[leveloffset=+1] +include::Option.adoc[leveloffset=+1] +include::Function.adoc[leveloffset=+1] +include::Array.adoc[leveloffset=+1] +include::Blob.adoc[leveloffset=+1] +include::Principal.adoc[leveloffset=+1] // Complex data structures -include::result.adoc[leveloffset=+1] -include::iter.adoc[leveloffset=+1] -include::buf.adoc[leveloffset=+1] -include::list.adoc[leveloffset=+1] -include::assocList.adoc[leveloffset=+1] -include::hash.adoc[leveloffset=+1] -include::hashMap.adoc[leveloffset=+1] -include::trie.adoc[leveloffset=+1] -include::trieMap.adoc[leveloffset=+1] -include::trieSet.adoc[leveloffset=+1] +include::Result.adoc[leveloffset=+1] +include::Iter.adoc[leveloffset=+1] +include::Buf.adoc[leveloffset=+1] +include::List.adoc[leveloffset=+1] +include::AssocList.adoc[leveloffset=+1] +include::Hash.adoc[leveloffset=+1] +include::HashMap.adoc[leveloffset=+1] +include::Trie.adoc[leveloffset=+1] +include::TrieMap.adoc[leveloffset=+1] +include::TrieSet.adoc[leveloffset=+1] // Utilities -include::prelude.adoc[leveloffset=+1] -include::debug.adoc[leveloffset=+1] +include::Prelude.adoc[leveloffset=+1] +include::Debug.adoc[leveloffset=+1] // At this point I’d like to include a proper index, diff --git a/stdlib/examples/actorspec/src/ActorSpec.mo b/stdlib/examples/actorspec/src/ActorSpec.mo index ec8d286ad2f..8e4b5615299 100644 --- a/stdlib/examples/actorspec/src/ActorSpec.mo +++ b/stdlib/examples/actorspec/src/ActorSpec.mo @@ -1,7 +1,7 @@ -import Debug "mo:stdlib/debug"; -import Array "mo:stdlib/array"; -import Int "mo:stdlib/int"; -import Text "mo:stdlib/text"; +import Debug "mo:stdlib/Debug"; +import Array "mo:stdlib/Array"; +import Int "mo:stdlib/Int"; +import Text "mo:stdlib/Text"; module { public type Group = { diff --git a/stdlib/examples/produce-exchange/src/docTable.mo b/stdlib/examples/produce-exchange/src/docTable.mo index c87e81be666..606887f6395 100644 --- a/stdlib/examples/produce-exchange/src/docTable.mo +++ b/stdlib/examples/produce-exchange/src/docTable.mo @@ -1,6 +1,6 @@ -import Hash "mo:stdlib/hash"; +import Hash "mo:stdlib/Hash"; -import Trie "mo:stdlib/trie"; +import Trie "mo:stdlib/Trie"; module { /** diff --git a/stdlib/examples/produce-exchange/src/serverActor.mo b/stdlib/examples/produce-exchange/src/serverActor.mo index b44ded42f38..f3b37651afa 100644 --- a/stdlib/examples/produce-exchange/src/serverActor.mo +++ b/stdlib/examples/produce-exchange/src/serverActor.mo @@ -4,16 +4,16 @@ -------------------- */ -import Debug "mo:stdlib/debug"; -import P = "mo:stdlib/prelude"; -import Option = "mo:stdlib/option"; +import Debug "mo:stdlib/Debug"; +import P = "mo:stdlib/Prelude"; +import Option = "mo:stdlib/Option"; import T = "serverTypes"; import L = "serverLang"; import Model = "serverModel"; -import Result = "mo:stdlib/result"; +import Result = "mo:stdlib/Result"; -import Trie = "mo:stdlib/trie"; -import List = "mo:stdlib/list"; +import Trie = "mo:stdlib/Trie"; +import List = "mo:stdlib/List"; type List = List.List; diff --git a/stdlib/examples/produce-exchange/src/serverLang.mo b/stdlib/examples/produce-exchange/src/serverLang.mo index 0810d135ffe..d6a50fedab6 100644 --- a/stdlib/examples/produce-exchange/src/serverLang.mo +++ b/stdlib/examples/produce-exchange/src/serverLang.mo @@ -1,4 +1,4 @@ -import Result = "mo:stdlib/result"; +import Result = "mo:stdlib/Result"; import T = "serverTypes"; diff --git a/stdlib/examples/produce-exchange/src/serverModel.mo b/stdlib/examples/produce-exchange/src/serverModel.mo index 3029697fe59..39802580384 100644 --- a/stdlib/examples/produce-exchange/src/serverModel.mo +++ b/stdlib/examples/produce-exchange/src/serverModel.mo @@ -1,18 +1,18 @@ -import Debug "mo:stdlib/debug"; -import P "mo:stdlib/prelude"; +import Debug "mo:stdlib/Debug"; +import P "mo:stdlib/Prelude"; import T "serverTypes"; import L "serverLang"; import M "serverModelTypes"; -import List "mo:stdlib/list"; -import Hash "mo:stdlib/hash"; -import Option "mo:stdlib/option"; -import Trie "mo:stdlib/trie"; -import Iter "mo:stdlib/iter"; -import Array "mo:stdlib/array"; +import List "mo:stdlib/List"; +import Hash "mo:stdlib/Hash"; +import Option "mo:stdlib/Option"; +import Trie "mo:stdlib/Trie"; +import Iter "mo:stdlib/Iter"; +import Array "mo:stdlib/Array"; -import Result "mo:stdlib/result"; +import Result "mo:stdlib/Result"; import DT = "docTable"; module { diff --git a/stdlib/examples/produce-exchange/src/serverModelTypes.mo b/stdlib/examples/produce-exchange/src/serverModelTypes.mo index 803082bbdab..21c0a9cbb55 100644 --- a/stdlib/examples/produce-exchange/src/serverModelTypes.mo +++ b/stdlib/examples/produce-exchange/src/serverModelTypes.mo @@ -1,5 +1,5 @@ import T = "serverTypes"; -import Trie = "mo:stdlib/trie"; +import Trie = "mo:stdlib/Trie"; import DocTable = "docTable"; diff --git a/stdlib/examples/produce-exchange/test/evalBulk.mo b/stdlib/examples/produce-exchange/test/evalBulk.mo index 5d8a24ccbce..0dad8f170be 100644 --- a/stdlib/examples/produce-exchange/test/evalBulk.mo +++ b/stdlib/examples/produce-exchange/test/evalBulk.mo @@ -1,8 +1,8 @@ -import Debug = "mo:stdlib/debug"; +import Debug = "mo:stdlib/Debug"; import T = "../src/serverTypes"; import A = "../src/serverActor"; -import Result = "mo:stdlib/result"; -import Option = "mo:stdlib/option"; +import Result = "mo:stdlib/Result"; +import Option = "mo:stdlib/Option"; func printEntityCount(entname:Text, count:Nat) { Debug.print ("- " # entname # " count: " # debug_show count # "\n"); diff --git a/stdlib/examples/produce-exchange/test/loadWorkloadAndQueryBig.mo b/stdlib/examples/produce-exchange/test/loadWorkloadAndQueryBig.mo index f20d86dc0e0..331963d51fe 100644 --- a/stdlib/examples/produce-exchange/test/loadWorkloadAndQueryBig.mo +++ b/stdlib/examples/produce-exchange/test/loadWorkloadAndQueryBig.mo @@ -1,7 +1,7 @@ //let T = (import "../src/serverTypes"); //let A = (import "../src/serverActor"); -//let Result = (import "mo:stdlib/result"); -//let Option = (import "mo:stdlib/option"); +//let Result = (import "mo:stdlib/Result"); +//let Option = (import "mo:stdlib/Option"); func scaledParams(region_count_:Nat, factor:Nat) : T.WorkloadParams = shared { region_count = region_count_:Nat; diff --git a/stdlib/examples/produce-exchange/test/producerRemInventory.mo b/stdlib/examples/produce-exchange/test/producerRemInventory.mo index 4c4937859ca..b0c407ba1c4 100644 --- a/stdlib/examples/produce-exchange/test/producerRemInventory.mo +++ b/stdlib/examples/produce-exchange/test/producerRemInventory.mo @@ -1,8 +1,8 @@ -import Debug "mo:stdlib/debug"; +import Debug "mo:stdlib/Debug"; import T = "../src/serverTypes"; import A = "../src/serverActor"; -import Result = "mo:stdlib/result"; -import Option = "mo:stdlib/option"; +import Result = "mo:stdlib/Result"; +import Option = "mo:stdlib/Option"; func printEntityCount(entname:Text, count:Nat) { Debug.print ("- " # entname # " count: " # debug_show count # "\n"); diff --git a/stdlib/examples/produce-exchange/test/profileFastCounts.mo b/stdlib/examples/produce-exchange/test/profileFastCounts.mo index e10bfc39dd5..00618555c06 100644 --- a/stdlib/examples/produce-exchange/test/profileFastCounts.mo +++ b/stdlib/examples/produce-exchange/test/profileFastCounts.mo @@ -2,7 +2,7 @@ // we correlate these numbers with times that we // measure elsewhere, where these numbers are not available. -import Debug "mo:stdlib/debug"; +import Debug "mo:stdlib/Debug"; import T "../src/serverTypes"; import Model "../src/serverModel"; diff --git a/stdlib/examples/produce-exchange/test/retailerReserveMany.mo b/stdlib/examples/produce-exchange/test/retailerReserveMany.mo index a68bdd85499..73a43a79c98 100644 --- a/stdlib/examples/produce-exchange/test/retailerReserveMany.mo +++ b/stdlib/examples/produce-exchange/test/retailerReserveMany.mo @@ -1,8 +1,8 @@ -import Debug "mo:stdlib/debug"; +import Debug "mo:stdlib/Debug"; import T = "../src/serverTypes"; import A = "../src/serverActor"; -import Result = "mo:stdlib/result"; -import Option = "mo:stdlib/option"; +import Result = "mo:stdlib/Result"; +import Option = "mo:stdlib/Option"; func printEntityCount(entname:Text, count:Nat) { Debug.print ("- " # entname # " count: " # debug_show count # "\n"); diff --git a/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.mo b/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.mo index 524c0a4857a..58859f4b133 100644 --- a/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.mo +++ b/stdlib/examples/produce-exchange/test/simpleSetupAndQuery.mo @@ -1,8 +1,8 @@ -import Debug "mo:stdlib/debug"; +import Debug "mo:stdlib/Debug"; import T = "../src/serverTypes"; import A = "../src/serverActor"; -import Result = "mo:stdlib/result"; -import Option = "mo:stdlib/option"; +import Result = "mo:stdlib/Result"; +import Option = "mo:stdlib/Option"; func printEntityCount(entname:Text, count:Nat) { Debug.print ("- " # entname # " count: " # debug_show count # "\n"); diff --git a/stdlib/examples/rx/test/RxTest.mo b/stdlib/examples/rx/test/RxTest.mo index e0e96ed7cb3..7f25a5c32c6 100644 --- a/stdlib/examples/rx/test/RxTest.mo +++ b/stdlib/examples/rx/test/RxTest.mo @@ -1,4 +1,4 @@ -import Array "mo:stdlib/array"; +import Array "mo:stdlib/Array"; import Rx "../src/Rx"; type Error = { diff --git a/stdlib/src/array.mo b/stdlib/src/Array.mo similarity index 99% rename from stdlib/src/array.mo rename to stdlib/src/Array.mo index 1e6e3c97273..e8443b834b9 100644 --- a/stdlib/src/array.mo +++ b/stdlib/src/Array.mo @@ -1,6 +1,6 @@ /** -[#mod-array] -= `array` -- Arrays +[#mod-Array] += `Array` -- Arrays */ import Prim "mo:prim"; diff --git a/stdlib/src/assocList.mo b/stdlib/src/AssocList.mo similarity index 98% rename from stdlib/src/assocList.mo rename to stdlib/src/AssocList.mo index 8d637e684a8..de7eac1aa4f 100644 --- a/stdlib/src/assocList.mo +++ b/stdlib/src/AssocList.mo @@ -1,9 +1,9 @@ /** -[#mod-assocList] -= `assocList` -- Association lists +[#mod-AssocList] += `AssocList` -- Association lists */ -import List "list"; +import List "List"; module { /* diff --git a/stdlib/src/blob.mo b/stdlib/src/Blob.mo similarity index 67% rename from stdlib/src/blob.mo rename to stdlib/src/Blob.mo index 10ac3a232b0..7cd9d88e029 100644 --- a/stdlib/src/blob.mo +++ b/stdlib/src/Blob.mo @@ -1,6 +1,6 @@ /* -[#mod-blob] -= `blob` -- Binary blobs +[#mod-Blob] += `Blob` -- Binary blobs */ import Prim "mo:prim"; diff --git a/stdlib/src/buf.mo b/stdlib/src/Buf.mo similarity index 96% rename from stdlib/src/buf.mo rename to stdlib/src/Buf.mo index 729e3ec1170..d648e9705e1 100644 --- a/stdlib/src/buf.mo +++ b/stdlib/src/Buf.mo @@ -1,11 +1,11 @@ /** -[#mod-buf] -= `buf` -- Growing buffers +[#mod-Buf] += `Buf` -- Growing buffers */ -import P "prelude"; -import I "iter"; -import A "array"; +import P "Prelude"; +import I "Iter"; +import A "Array"; module { diff --git a/stdlib/src/char.mo b/stdlib/src/Char.mo similarity index 82% rename from stdlib/src/char.mo rename to stdlib/src/Char.mo index 888fe5a3516..cd63816f8d3 100644 --- a/stdlib/src/char.mo +++ b/stdlib/src/Char.mo @@ -1,6 +1,6 @@ /** -[#mod-char] -= `char` -- Characters +[#mod-Char] += `Char` -- Characters */ import Prim "mo:prim"; diff --git a/stdlib/src/debug.mo b/stdlib/src/Debug.mo similarity index 87% rename from stdlib/src/debug.mo rename to stdlib/src/Debug.mo index a9ea42e0088..d930669c8d7 100644 --- a/stdlib/src/debug.mo +++ b/stdlib/src/Debug.mo @@ -1,6 +1,6 @@ /** -[#mod-debug] -= `debug` -- Debugging aids +[#mod-Debug] += `Debug` -- Debugging aids */ import Prim "mo:prim"; diff --git a/stdlib/src/function.mo b/stdlib/src/Function.mo similarity index 91% rename from stdlib/src/function.mo rename to stdlib/src/Function.mo index c56018f66a8..a4c6767540a 100644 --- a/stdlib/src/function.mo +++ b/stdlib/src/Function.mo @@ -1,6 +1,6 @@ /** -[#mod-function] -= `function` -- Functions on functions +[#mod-Function] += `Function` -- Functions on functions */ module { diff --git a/stdlib/src/hash.mo b/stdlib/src/Hash.mo similarity index 97% rename from stdlib/src/hash.mo rename to stdlib/src/Hash.mo index d4e13770bef..f4f7388349c 100644 --- a/stdlib/src/hash.mo +++ b/stdlib/src/Hash.mo @@ -1,10 +1,10 @@ /** -[#mod-hash] -= `hash` -- Hash values +[#mod-Hash] += `Hash` -- Hash values */ import Prim "mo:prim"; -import Iter "iter"; +import Iter "Iter"; module { /** diff --git a/stdlib/src/hashMap.mo b/stdlib/src/HashMap.mo similarity index 96% rename from stdlib/src/hashMap.mo rename to stdlib/src/HashMap.mo index a19c6c5859f..0c14bdee386 100644 --- a/stdlib/src/hashMap.mo +++ b/stdlib/src/HashMap.mo @@ -1,14 +1,14 @@ /** -[#mod-hashMap] -= `hashMap` -- Mutable hash map +[#mod-HashMap] += `HashMap` -- Mutable hash map */ import Prim "mo:prim"; -import P "prelude"; -import A "array"; -import Hash "hash"; -import Iter "iter"; -import AssocList "assocList"; +import P "Prelude"; +import A "Array"; +import Hash "Hash"; +import Iter "Iter"; +import AssocList "AssocList"; module { diff --git a/stdlib/src/int.mo b/stdlib/src/Int.mo similarity index 96% rename from stdlib/src/int.mo rename to stdlib/src/Int.mo index 519cbc13ee6..cb00333cf5b 100644 --- a/stdlib/src/int.mo +++ b/stdlib/src/Int.mo @@ -1,6 +1,6 @@ /** -[#mod-int] -= `int` -- Integer numbers +[#mod-Int] += `Int` -- Integer numbers Most operations on natural numbers (e.g. addition) are available as built-in operators (`1 + 1`). This module provides conversion functions. @@ -9,7 +9,7 @@ The conversions `toInt*` will trap if the number is out of bounds. */ import Prim "mo:prim"; -import Prelude "prelude"; +import Prelude "Prelude"; module { /** diff --git a/stdlib/src/iter.mo b/stdlib/src/Iter.mo similarity index 96% rename from stdlib/src/iter.mo rename to stdlib/src/Iter.mo index 127e51e7cc1..080d0f18e41 100644 --- a/stdlib/src/iter.mo +++ b/stdlib/src/Iter.mo @@ -1,10 +1,10 @@ /** -[#mod-iter] -= `iter` -- Iterators +[#mod-Iter] += `Iter` -- Iterators */ -import Array "array"; -import List "list"; +import Array "Array"; +import List "List"; module { public type Iter = {next : () -> ?T}; diff --git a/stdlib/src/list.mo b/stdlib/src/List.mo similarity index 99% rename from stdlib/src/list.mo rename to stdlib/src/List.mo index 5177f19a5c4..0579aa96491 100644 --- a/stdlib/src/list.mo +++ b/stdlib/src/List.mo @@ -1,14 +1,14 @@ /** -[#mod-list] -= `list` -- Lists +[#mod-List] += `List` -- Lists This module provides purely-functional, singly-linked lists. */ -import Array "array"; -import Option "option"; +import Array "Array"; +import Option "Option"; module { diff --git a/stdlib/src/nat.mo b/stdlib/src/Nat.mo similarity index 94% rename from stdlib/src/nat.mo rename to stdlib/src/Nat.mo index bc4dbbad1e3..9a32ea64b46 100644 --- a/stdlib/src/nat.mo +++ b/stdlib/src/Nat.mo @@ -1,6 +1,6 @@ /** -[#mod-nat] -= `nat` -- Natural numbers +[#mod-Nat] += `Nat` -- Natural numbers Most operations on natural numbers (e.g. addition) are available as built-in operators (`1 + 1`). This module provides conversion functions. @@ -10,8 +10,8 @@ The conversions `toNat*` will trap if the number is out of bounds; the conversio */ import Prim "mo:prim"; -import Int "int"; -import Prelude "prelude"; +import Int "Int"; +import Prelude "Prelude"; module { diff --git a/stdlib/src/none.mo b/stdlib/src/None.mo similarity index 87% rename from stdlib/src/none.mo rename to stdlib/src/None.mo index e61aa95afb2..c22b99a84ec 100644 --- a/stdlib/src/none.mo +++ b/stdlib/src/None.mo @@ -1,6 +1,6 @@ /** -[#mod-none] -= `none` -- The absent value +[#mod-None] += `None` -- The absent value The `None` type represents a type with _no_ value, often used to mark dead code. diff --git a/stdlib/src/option.mo b/stdlib/src/Option.mo similarity index 95% rename from stdlib/src/option.mo rename to stdlib/src/Option.mo index 8470042e01e..225cfcb6257 100644 --- a/stdlib/src/option.mo +++ b/stdlib/src/Option.mo @@ -1,9 +1,9 @@ /** -[#mod-option] -= `option` -- Optional values +[#mod-Option] += `Option` -- Optional values */ -import P "prelude"; +import P "Prelude"; module { @@ -73,7 +73,7 @@ public let apply : (?(A -> B), ?A) -> ?B = /** Applies an function to an optional value. Returns `null` if the argument is `null`, or the function returns `null`. -NOTE: Together with <>, this forms a “monad”. +NOTE: Together with <>, this forms a “monad”. */ public let bind : (?A, A -> ?B) -> ?B = func(x : ?A, f : A -> ?B) : ?B { diff --git a/stdlib/src/prelude.mo b/stdlib/src/Prelude.mo similarity index 95% rename from stdlib/src/prelude.mo rename to stdlib/src/Prelude.mo index 998014e578e..ef5592d0f49 100644 --- a/stdlib/src/prelude.mo +++ b/stdlib/src/Prelude.mo @@ -1,6 +1,6 @@ /** -[#mod-prelude] -= `prelude` -- General utilities +[#mod-Prelude] += `Prelude` -- General utilities */ import Prim "mo:prim"; diff --git a/stdlib/src/principal.mo b/stdlib/src/Principal.mo similarity index 53% rename from stdlib/src/principal.mo rename to stdlib/src/Principal.mo index e54d2dfdc80..e712a8b37c0 100644 --- a/stdlib/src/principal.mo +++ b/stdlib/src/Principal.mo @@ -1,5 +1,10 @@ +/** +[#mod-Principal] += `Principal` -- IC principals (User and canister IDs) +*/ + import Prim "mo:prim"; -import Blob "blob"; +import Blob "Blob"; module { public func hash(x : Principal) : Word32 = Blob.hash (Prim.blobOfPrincipal x); } diff --git a/stdlib/src/result.mo b/stdlib/src/Result.mo similarity index 97% rename from stdlib/src/result.mo rename to stdlib/src/Result.mo index 43f8d318168..bd26a48ce37 100644 --- a/stdlib/src/result.mo +++ b/stdlib/src/Result.mo @@ -1,10 +1,10 @@ /** -[#mod-result] -= `result` -- Error-annotated values +[#mod-Result] += `Result` -- Error-annotated values */ -import P "prelude"; -import Array "array"; +import P "Prelude"; +import Array "Array"; module { /* diff --git a/stdlib/src/text.mo b/stdlib/src/Text.mo similarity index 71% rename from stdlib/src/text.mo rename to stdlib/src/Text.mo index 494b0b9e65f..a89b7974fcd 100644 --- a/stdlib/src/text.mo +++ b/stdlib/src/Text.mo @@ -1,12 +1,12 @@ /** -[#mod-text] -= `text` -- Text values +[#mod-Text] += `Text` -- Text values This type describes a valid, human-readable text. It does not contain arbitrary binary data. */ -import Iter "iter"; +import Iter "Iter"; module { @@ -16,7 +16,7 @@ module { }; /** - Creates an <> that traverses the characters of the text. + Creates an <> that traverses the characters of the text. */ public let toIter : Text -> Iter.Iter = func(text) = text.chars() diff --git a/stdlib/src/trie.mo b/stdlib/src/Trie.mo similarity index 99% rename from stdlib/src/trie.mo rename to stdlib/src/Trie.mo index fec3341bd33..5e13488a241 100644 --- a/stdlib/src/trie.mo +++ b/stdlib/src/Trie.mo @@ -1,16 +1,16 @@ /** -[#mod-trie] -= `trie` -- Functional map +[#mod-Trie] += `Trie` -- Functional map */ import Prim "mo:prim"; -import P "prelude"; -import Option "option"; -import Hash "hash"; -import A "array"; +import P "Prelude"; +import Option "Option"; +import Hash "Hash"; +import A "Array"; -import List "list"; -import AssocList "assocList"; +import List "List"; +import AssocList "AssocList"; module { /* diff --git a/stdlib/src/trieMap.mo b/stdlib/src/TrieMap.mo similarity index 96% rename from stdlib/src/trieMap.mo rename to stdlib/src/TrieMap.mo index 884281b314f..a578204d733 100644 --- a/stdlib/src/trieMap.mo +++ b/stdlib/src/TrieMap.mo @@ -1,13 +1,13 @@ /** -[#mod-trieMap] -= `trieMap` -- Functional map +[#mod-TrieMap] += `TrieMap` -- Functional map */ -import T "trie"; -import P "prelude"; -import I "iter"; -import Hash "hash"; -import List "list"; +import T "Trie"; +import P "Prelude"; +import I "Iter"; +import Hash "Hash"; +import List "List"; /* diff --git a/stdlib/src/trieSet.mo b/stdlib/src/TrieSet.mo similarity index 95% rename from stdlib/src/trieSet.mo rename to stdlib/src/TrieSet.mo index 7c0bb85a95b..cd3f47c2f20 100644 --- a/stdlib/src/trieSet.mo +++ b/stdlib/src/TrieSet.mo @@ -1,6 +1,6 @@ /** -[#mod-trieSet] -= `trieSet` -- Functional set +[#mod-TrieSet] += `TrieSet` -- Functional set */ /* @@ -22,8 +22,8 @@ in the future, we might avoid this via https://dfinity.atlassian.net/browse/AST-32 */ -import Trie "trie"; -import Hash "hash"; +import Trie "Trie"; +import Hash "Hash"; module { public type Hash = Hash.Hash; diff --git a/stdlib/test/arrayTest.mo b/stdlib/test/arrayTest.mo index 74527678001..2e31177f0dc 100644 --- a/stdlib/test/arrayTest.mo +++ b/stdlib/test/arrayTest.mo @@ -1,6 +1,6 @@ -import Array "mo:stdlib/array"; -import Prelude "mo:stdlib/prelude"; -import Text "mo:stdlib/text"; +import Array "mo:stdlib/Array"; +import Prelude "mo:stdlib/Prelude"; +import Text "mo:stdlib/Text"; Prelude.printLn("Array"); diff --git a/stdlib/test/bufTest.mo b/stdlib/test/bufTest.mo index b9c9f8f98be..63c002a3985 100644 --- a/stdlib/test/bufTest.mo +++ b/stdlib/test/bufTest.mo @@ -1,6 +1,6 @@ import Prim "mo:prim"; -import B "mo:stdlib/buf"; -import I "mo:stdlib/iter"; +import B "mo:stdlib/Buf"; +import I "mo:stdlib/Iter"; // test repeated growing let a = B.Buf(3); diff --git a/stdlib/test/functionTest.mo b/stdlib/test/functionTest.mo index 8020c5ceca8..57a33625633 100644 --- a/stdlib/test/functionTest.mo +++ b/stdlib/test/functionTest.mo @@ -1,6 +1,6 @@ -import Function "mo:stdlib/function"; -import Prelude "mo:stdlib/prelude"; -import Text "mo:stdlib/text"; +import Function "mo:stdlib/Function"; +import Prelude "mo:stdlib/Prelude"; +import Text "mo:stdlib/Text"; Prelude.printLn("Function"); diff --git a/stdlib/test/hashMapTest.mo b/stdlib/test/hashMapTest.mo index cdb1199f0cf..2bd8dfce9fd 100644 --- a/stdlib/test/hashMapTest.mo +++ b/stdlib/test/hashMapTest.mo @@ -1,6 +1,6 @@ import Prim "mo:prim"; -import H "mo:stdlib/hashMap"; -import Hash "mo:stdlib/hash"; +import H "mo:stdlib/HashMap"; +import Hash "mo:stdlib/Hash"; func textIsEq(x:Text,y:Text):Bool { x == y }; diff --git a/stdlib/test/intTest.mo b/stdlib/test/intTest.mo index ba1991ad3a2..049225f686f 100644 --- a/stdlib/test/intTest.mo +++ b/stdlib/test/intTest.mo @@ -1,5 +1,5 @@ -import Prelude "mo:stdlib/prelude"; -import Int "mo:stdlib/int"; +import Prelude "mo:stdlib/Prelude"; +import Int "mo:stdlib/Int"; Prelude.printLn("Int"); diff --git a/stdlib/test/iterTest.mo b/stdlib/test/iterTest.mo index 0c421b9def9..fa640ac0c2b 100644 --- a/stdlib/test/iterTest.mo +++ b/stdlib/test/iterTest.mo @@ -1,6 +1,6 @@ -import Iter "mo:stdlib/iter"; -import List "mo:stdlib/list"; -import Prelude "mo:stdlib/prelude"; +import Iter "mo:stdlib/Iter"; +import List "mo:stdlib/List"; +import Prelude "mo:stdlib/Prelude"; Prelude.printLn("Iter"); diff --git a/stdlib/test/listTest.mo b/stdlib/test/listTest.mo index 2ead871523a..7bb830792d9 100644 --- a/stdlib/test/listTest.mo +++ b/stdlib/test/listTest.mo @@ -1,5 +1,5 @@ -import List "mo:stdlib/list"; -import Prelude "mo:stdlib/prelude"; +import List "mo:stdlib/List"; +import Prelude "mo:stdlib/Prelude"; type X = Nat; diff --git a/stdlib/test/natTest.mo b/stdlib/test/natTest.mo index 7f344b4131c..b2f49b30fb0 100644 --- a/stdlib/test/natTest.mo +++ b/stdlib/test/natTest.mo @@ -1,5 +1,5 @@ -import Prelude "mo:stdlib/prelude"; -import Nat "mo:stdlib/nat"; +import Prelude "mo:stdlib/Prelude"; +import Nat "mo:stdlib/Nat"; Prelude.printLn("Nat"); diff --git a/stdlib/test/noneTest.mo b/stdlib/test/noneTest.mo index be57a716e9a..d1e69edfcac 100644 --- a/stdlib/test/noneTest.mo +++ b/stdlib/test/noneTest.mo @@ -1,6 +1,6 @@ -import Array "mo:stdlib/array"; -import None "mo:stdlib/none"; -import Prelude "mo:stdlib/prelude"; +import Array "mo:stdlib/Array"; +import None "mo:stdlib/None"; +import Prelude "mo:stdlib/Prelude"; Prelude.printLn("None"); diff --git a/stdlib/test/optionTest.mo b/stdlib/test/optionTest.mo index f4978daacd8..1819ce8a47b 100644 --- a/stdlib/test/optionTest.mo +++ b/stdlib/test/optionTest.mo @@ -1,5 +1,5 @@ -import Option "mo:stdlib/option"; -import Prelude "mo:stdlib/prelude"; +import Option "mo:stdlib/Option"; +import Prelude "mo:stdlib/Prelude"; Prelude.printLn("Option"); diff --git a/stdlib/test/textTest.mo b/stdlib/test/textTest.mo index 8a7ab06fddc..c464eeefaa4 100644 --- a/stdlib/test/textTest.mo +++ b/stdlib/test/textTest.mo @@ -1,5 +1,5 @@ -import Prelude "mo:stdlib/prelude"; -import Text "mo:stdlib/text"; +import Prelude "mo:stdlib/Prelude"; +import Text "mo:stdlib/Text"; Prelude.printLn("Text"); diff --git a/stdlib/test/trieMapTest.mo b/stdlib/test/trieMapTest.mo index de41e6d900e..469681f9414 100644 --- a/stdlib/test/trieMapTest.mo +++ b/stdlib/test/trieMapTest.mo @@ -1,6 +1,6 @@ import Prim "mo:prim"; -import H "mo:stdlib/trieMap"; -import Hash "mo:stdlib/hash"; +import H "mo:stdlib/TrieMap"; +import Hash "mo:stdlib/Hash"; func textIsEq(x:Text,y:Text):Bool { x == y }; From 7ded9d72b9cd623747655f48e241452f4698f6c8 Mon Sep 17 00:00:00 2001 From: DFINITY bot <58022693+dfinity-bot@users.noreply.github.com> Date: Wed, 25 Mar 2020 01:09:07 +0100 Subject: [PATCH 1137/1176] niv common: update aaaa0f66 -> d696e4eb (#1310) ## Changelog for common: Commits: [dfinity-lab/common@aaaa0f66...d696e4eb](https://github.com/dfinity-lab/common/compare/aaaa0f667e8bf01beb7a1c4bcb151175cf40d7a0...d696e4ebcee16f374c0cd8377364f5c5beb23c9f) * [`db368e7b`](https://github.com/dfinity-lab/common/commit/db368e7b0c5802d5fa37dde726d9f28491f04e78) INF-1108 Remove --all-targets from cargoTestOptions --- nix/sources.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/sources.json b/nix/sources.json index 65491078c3f..6a0aa20bb52 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -2,7 +2,7 @@ "common": { "ref": "master", "repo": "ssh://git@github.com/dfinity-lab/common", - "rev": "aaaa0f667e8bf01beb7a1c4bcb151175cf40d7a0", + "rev": "d696e4ebcee16f374c0cd8377364f5c5beb23c9f", "type": "git" }, "dfinity": { From a67695fbfe16600fe58cd9f98aae1b69e9ec581a Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Wed, 25 Mar 2020 07:07:15 +0100 Subject: [PATCH 1138/1176] Design overview for stable variables and upgrade hooks (#1238) --- design/Stable.md | 192 +++++++++++++++++++++++++++++++++++++++++++++++ design/Syntax.md | 4 +- 2 files changed, 194 insertions(+), 2 deletions(-) create mode 100644 design/Stable.md diff --git a/design/Stable.md b/design/Stable.md new file mode 100644 index 00000000000..6fd40a09174 --- /dev/null +++ b/design/Stable.md @@ -0,0 +1,192 @@ +# Stable Variables and Upgrade + +To enable persistent state to survive upgrades, a special form of state is needed that we call _stable_. + +The compiler needs to take special care to never change the representation of such state. +To make this requirement feasible, certain type restrictions apply to stable state: essentially it can only contain data. + +Stable state is introduced in the form of _stable variable definitions_ that are only allowed (as well as required) in actors. + + +## Language Extension + +### Syntax + +We require all `let` and `var` declarations in an actor to be declared either stable or flexible. +This is to indicate explicitly that special type restrictions apply. + +Concretely, the syntax of `` is extended as follows: +``` + ::= + (public|private)? (stable|flexible)? dec +``` + +Additional restrictions apply: +* Either a `stable` or `flexible` modifier _must_ appear on `let` and `var` declarations that are actor fields. +* A `stable` or `flexible` modifier _must not_ appear anywhere else. + +Both restrictions may be relaxed in the future. + +(Note: One possible future use case might be to mark private methods as stable, which would be a requisite that they can be handed out as capabilities, because such methods must also remain backwards compatible.) + + +### Typing + +A stable declaration must have a _stable type_. Stable types are a superset of _shared_ types: specifically, they additionally allow objects or arrays with mutable components. + +Concretely, the `stable` predicate has the same definition as the `shared` predicate (cf. `type.ml`), except that the case for `Mut t` is +``` + | Mut t -> go t +``` + +That is, shared entails stable. +Note that this implies that stable types may contain actors or shared functions, but mutability of course does not extend into those. + +Note: This implies that stable state can only contain records, not objects (which contain non-shared functions). +This clearly is a severe restriction. +But we leave the possibility of "stable classes" for later, since it is not at all obvious how to design or implement them. + + +### Semantics + +Installing a new actor runs the initialiser expressions of all flexible and stable variables in sequence, like for ordinary variable definitions in an object. +(In terms of the System API, this happens in the init hook.) + +When upgrading an actor, all stable variables that existed in the previous version are pre-initialised with their old values. +Their initialiser expressions are ignored. +After that, the initialiser expressions of flexible and newly added stable variables are executed in sequence, like for ordinary variable definitions. +(In terms of the System API, this happens in the post_upgrade hook.) + +This implies that any expression declaration (or any of the form `let _ = `, for which expressions are a short-hand) will always be run after an upgrade. +They can hence be (ab)used as post-upgrade hooks. + +Open Question: What about let declarations with multiple variables, some of which existed before while others didn't? Or should we generally not persist `let`-bound values and always re-initialise them? Would that be a pitfall? Should we forbid it (how?)? + +Note: With respect to variable initialisation, installing a new actor behaves like upgrading the actor from an empty actor with no pre-existing stable variables. + + +## Stable Signatures + +The Candid IDL defines the public interface of an actor, listing the methods that an actor provides and their types. +When upgrading an actor, this interface may only be modified in backwards-compatible ways: +* new methods may be added, +* existing methods may be refined to a subtype. +This prevents breaking existing clients assuming the current or an earlier interface. + +With stable state, a second dimension is added: the _stable signature_ of an actor lists its stable fields and their types. +When upgrading an actor, this interface may also only be modified in backwards-compatible ways: +* new variables may be added, +* existing variables may be refined to a _supertype_. +This ensures that existing persistent state is still readable with the new version of the program. + +The stable signature is not public; its only relevance is to the owner of an actor, as an additional constraint imposed when upgrading the actor. + +Stable signatures could also be used to auto-generate interfaces or UI for inspecting or even administering the state of an actor. + + +### Syntax + +The stable signature can't be described in terms of IDL types, because it is specific to Motoko and stable types contain more than what the IDL can express. + +The textual representation for stable signatures looks like a Motoko actor type: +``` +actor { + stable x : Nat; + stable var y : Int; + stable z : [var Nat]; +}; +``` +Like in Candid, the actor specification may be preceded by a sequence of auxiliary (Motoko) type definitions. + +Grammar: +``` + ::= ... (Motoko types) + + ::= + stable : + stable var : + + ::= + type ? = + + ::= ;* actor { ;* }; + +``` + +Note: We could also allow imports if useful. + +Question: Should the stable signature become a superset of Candid signatures, i.e., also include methods, but expressed with (richer) Motoko types? + + +### Compiler and System Support + +Like the Candid IDL, the Motoko compiler can produce stable signatures for the actors it compiles. + +We will also need a tool (the compiler, or a separate one?) that can compare stable signature and verify that an extension is valid according to the Motoko subtyping rules. + +To make that test reliable, the stable signature of an actor should be contained in the Wasm module of a deployed Motoko actor. +That way, it is ensured that accurate signature information is always available for each installed actor. +One way to store it would be in a Motoko-specific custom section; +another alternative is as a separate internal asset. +In either case, it is probably sufficient to use a textual representation. + +Like for the IDL, the System would need to provide a way to extract this information from an on-chain canister. + + +## Upgrade Hooks + +The System API provides a number of hooks that a canister can implement. +In particular, this includes the pre & post upgrade hooks. + +Motoko does not currently provide a way to define these hooks. +While the post upgrade hook can be exploited by using expression declarations (see above), there is no immediate way to define the pre upgrade hook. + +Note: This feature could potentially be deferred until later. + + +### Syntax + +To this end, we further extend the syntax of `` with _system methods_ of the following form: +``` + ::= ... + (public|private|system)? (flexible|stable)? dec +``` +Again, additional restrictions apply: +* A `system` modifier _may only_ appear on `func` declarations that are actor fields. +* A `system` modifier _must not_ appear anywhere else. + +Two system methods are recognised by their name: +* `preupgrade` +* `postupgrade` + +The set of system functions may be extended in the future. + + +### Typing + +The required type of system methods depends on their name: +* `preupgrade : () -> ()` +* `postupgrade : () -> ()` + + +### Semantics + +Pre-upgrade and post-upgrade methods are executed before or after an upgrade, respectively. (In terms of the System API, they correspond to the respective hooks.) + +Moreover, a post-upgrade method is executed after the actor body and its variable initialisers have run (see above). + +Note: The post-upgrade method differs from expression declarations in the body of an actor in that they are _only_ run after an upgrade, not when first installing the actor. + + +## Implementation + +Until Wasm provides multiple memories, the values of stable variables need to be written to the _stable memory_ provided by the System API. +There are multiple possible implementation strategies for this: + +1. Lazy de/serialisation: the compiler generates a pre_upgrade hook that serialises a map of all stable variables to the stable memory, and a post_upgrade hook that deserialises. + +2. Eager de/serialisation: reading/writing a stable variable de/serialises their value directly into a key/value store living in the stable memory. +Dealing with in-place update on mutable components requires indirections in the store via some extensible table. +It also necessitates some form of garbage collection of the stable heap. + +3. Possibly other, like more smarter incremental approaches... diff --git a/design/Syntax.md b/design/Syntax.md index 7c69939a80b..2157a4528dc 100644 --- a/design/Syntax.md +++ b/design/Syntax.md @@ -115,14 +115,14 @@ Productions marked * probably deferred to later versions. expression let = immutable var (: )? = mutable - (actor|module|object) ? =? { ;* } object + (actor|module|object) ? =? { ;* } object shared? func ? ? (: )? =? function actor? class ? (: )? =? class type ? = type import ? =? import ::= object declaration fields - (public|private)? dec field + (public|private|system)? (flexible|stable)? dec field ``` ## Programs From 74220d8c0d54439639e949c31022fae7b0d450a2 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 25 Mar 2020 17:22:51 +0100 Subject: [PATCH 1139/1176] Bump ic-ref (#1309) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit somehow `ic-ref-run` now runs more of query2. I guess that’s a good thing. Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- nix/sources.json | 4 ++-- test/run-drun/ok/query2.ic-ref-run.ok | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/nix/sources.json b/nix/sources.json index 6a0aa20bb52..8c63b20abaf 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -20,9 +20,9 @@ "version": "3.2.25" }, "ic-ref": { - "ref": "master", + "ref": "release-0.2", "repo": "ssh://git@github.com/dfinity-lab/ic-ref", - "rev": "822a201c5e4e993567ac1066237c02dd9a6fcccb", + "rev": "f298af99efd9b93cd49707d443ad835c0260dee3", "type": "git" }, "libtommath": { diff --git a/test/run-drun/ok/query2.ic-ref-run.ok b/test/run-drun/ok/query2.ic-ref-run.ok index be5266aaf32..aeb05f6b919 100644 --- a/test/run-drun/ok/query2.ic-ref-run.ok +++ b/test/run-drun/ok/query2.ic-ref-run.ok @@ -7,4 +7,11 @@ debug.print: 2 debug.print: 3 debug.print: 4 debug.print: 4 +debug.print: In read: +debug.print: 5 +debug.print: 4 +debug.print: In read: +debug.print: 5 +debug.print: The following fails in the interpreter, for lack of query semantics +debug.print: 4 ← completed: 0x4449444c0000 From 9e51529311c16f87202cc71a1e2b86b59d4bd1e4 Mon Sep 17 00:00:00 2001 From: DFINITY bot <58022693+dfinity-bot@users.noreply.github.com> Date: Thu, 26 Mar 2020 01:08:34 +0100 Subject: [PATCH 1140/1176] niv common: update d696e4eb -> 24be014b (#1312) ## Changelog for common: Commits: [dfinity-lab/common@d696e4eb...24be014b](https://github.com/dfinity-lab/common/compare/d696e4ebcee16f374c0cd8377364f5c5beb23c9f...24be014bd63a35ef70a595048605afc0d3640c59) * [`f904ff1b`](https://github.com/dfinity-lab/common/commit/f904ff1bda21fc9c4e5dd7473473c564d69c05ca) cargo-security-audit: Make @firstresponder responsible --- nix/sources.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/sources.json b/nix/sources.json index 8c63b20abaf..6af5819952a 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -2,7 +2,7 @@ "common": { "ref": "master", "repo": "ssh://git@github.com/dfinity-lab/common", - "rev": "d696e4ebcee16f374c0cd8377364f5c5beb23c9f", + "rev": "24be014bd63a35ef70a595048605afc0d3640c59", "type": "git" }, "dfinity": { From 86c8fcaa88afa0bced65ef300647ff89775a4eb3 Mon Sep 17 00:00:00 2001 From: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> Date: Thu, 26 Mar 2020 20:19:17 +0100 Subject: [PATCH 1141/1176] Applies ocamlformat to languageServer sources (#1308) * Applies ocamlformat to languageServer sources * always align infix operators when breaking chains * moves doc comments before their declarations * adds a derivation to check formatting --- default.nix | 15 +- src/languageServer/.ocamlformat | 3 + src/languageServer/completion.ml | 291 ++++++----- src/languageServer/completion_test.ml | 84 ++-- src/languageServer/debug.ml | 1 + src/languageServer/declaration_index.ml | 494 +++++++++---------- src/languageServer/declaration_index.mli | 76 ++- src/languageServer/declaration_index_test.ml | 29 +- src/languageServer/definition.ml | 97 ++-- src/languageServer/hover.ml | 65 ++- src/languageServer/hover_tests.ml | 44 +- src/languageServer/imports.ml | 79 ++- src/languageServer/languageServer.ml | 460 +++++++++-------- src/languageServer/pretty.ml | 4 +- src/languageServer/source_file.ml | 138 +++--- src/languageServer/source_file_tests.ml | 93 ++-- src/languageServer/vfs.ml | 143 +++--- src/languageServer/vfs.mli | 17 +- src/languageServer/vfs_tests.ml | 70 ++- 19 files changed, 1086 insertions(+), 1117 deletions(-) create mode 100644 src/languageServer/.ocamlformat diff --git a/default.nix b/default.nix index 0d69cfa1189..7a4e4c7590c 100644 --- a/default.nix +++ b/default.nix @@ -352,6 +352,18 @@ rec { ''; }; + check-formatting = stdenv.mkDerivation { + name = "check-formatting"; + buildInputs = with nixpkgs; [ ocamlformat ]; + src = subpath "./src"; + doCheck = true; + phases = "unpackPhase checkPhase installPhase"; + installPhase = "touch $out"; + checkPhase = '' + ocamlformat --check languageServer/*.{ml,mli} + ''; + }; + stdlib-tests = stdenv.mkDerivation { name = "stdlib-tests"; src = subpath ./stdlib/test; @@ -449,6 +461,7 @@ rec { users-guide ic-ref shell + check-formatting check-generated ] ++ builtins.attrValues tests ++ builtins.attrValues examples; @@ -469,7 +482,7 @@ rec { rts.buildInputs ++ js.buildInputs ++ users-guide.buildInputs ++ - [ nixpkgs.ncurses nixpkgs.ocamlPackages.merlin nixpkgs.ocamlPackages.utop ] ++ + [ nixpkgs.ncurses nixpkgs.ocamlPackages.merlin nixpkgs.ocamlformat nixpkgs.ocamlPackages.utop ] ++ builtins.concatMap (d: d.buildInputs) (builtins.attrValues tests) )); diff --git a/src/languageServer/.ocamlformat b/src/languageServer/.ocamlformat new file mode 100644 index 00000000000..b05208f9dee --- /dev/null +++ b/src/languageServer/.ocamlformat @@ -0,0 +1,3 @@ +version=0.13.0 +break-infix=fit-or-vertical +doc-comments=before diff --git a/src/languageServer/completion.ml b/src/languageServer/completion.ml index 791afe20a8f..6bce63e783e 100644 --- a/src/languageServer/completion.ml +++ b/src/languageServer/completion.ml @@ -4,32 +4,34 @@ module Lsp_t = Lsp.Lsp_t module DI = Declaration_index let string_of_list f xs = - List.map f xs - |> String.concat "; " - |> fun x -> "[ " ^ x ^ " ]" + List.map f xs |> String.concat "; " |> fun x -> "[ " ^ x ^ " ]" let template_of_ide_decl decl = let supply = ref 0 in - let fresh () = supply := !supply + 1; string_of_int !supply in + let fresh () = + supply := !supply + 1; + string_of_int !supply + in match decl with - | DI.ValueDecl value -> - (match value.DI.typ with - | Type.Func(_, _, binds, ty_list1, ty_list2) -> - let ty_args = - binds - |> List.filter Type.(fun { sort; _ } -> sort = Type) - |> List.map (fun Type.{ var = var; bound = bound; _} -> - Printf.sprintf "${%s:%s}" (fresh ()) var) - |> String.concat ", " in - let args = - ty_list1 - |> List.map (fun _ -> Printf.sprintf "$%s" (fresh ())) - |> String.concat ", " in - let ty_args = if ty_args = "" then "" else "<" ^ ty_args ^ ">" in - Printf.sprintf "%s%s(%s)" value.DI.name ty_args args - | _ -> value.DI.name) - | DI.TypeDecl ty -> - ty.DI.name + | DI.ValueDecl value -> ( + match value.DI.typ with + | Type.Func (_, _, binds, ty_list1, ty_list2) -> + let ty_args = + binds + |> List.filter Type.(fun { sort; _ } -> sort = Type) + |> List.map (fun Type.{ var; bound; _ } -> + Printf.sprintf "${%s:%s}" (fresh ()) var) + |> String.concat ", " + in + let args = + ty_list1 + |> List.map (fun _ -> Printf.sprintf "$%s" (fresh ())) + |> String.concat ", " + in + let ty_args = if ty_args = "" then "" else "<" ^ ty_args ^ ">" in + Printf.sprintf "%s%s(%s)" value.DI.name ty_args args + | _ -> value.DI.name ) + | DI.TypeDecl ty -> ty.DI.name let string_of_item (item : Lsp_t.completion_item) : string = item.Lsp_t.completion_item_label @@ -39,112 +41,115 @@ let item_of_ide_decl (d : DI.ide_decl) : Lsp_t.completion_item = let tmpl = DI.name_of_ide_decl d in match d with | DI.ValueDecl value -> - Lsp_t.{ - completion_item_label = value.DI.name; - completion_item_kind = 3; - completion_item_insertText = Some tmpl; - completion_item_insertTextFormat = Some 2; - completion_item_additionalTextEdits = None; - completion_item_documentation = Some (Pretty.string_of_typ value.DI.typ); - completion_item_detail = None; - } + Lsp_t. + { + completion_item_label = value.DI.name; + completion_item_kind = 3; + completion_item_insertText = Some tmpl; + completion_item_insertTextFormat = Some 2; + completion_item_additionalTextEdits = None; + completion_item_documentation = + Some (Pretty.string_of_typ value.DI.typ); + completion_item_detail = None; + } | DI.TypeDecl ty -> - let con = ty.DI.typ in - let eq, params, typ = Type.strings_of_kind (Con.kind con) in - Lsp_t.{ - completion_item_label = ty.DI.name; - completion_item_kind = 7; - completion_item_insertText = Some tmpl; - completion_item_insertTextFormat = Some 2; - completion_item_additionalTextEdits = None; - completion_item_documentation = - Some - (Printf.sprintf - "type %s%s" - ty.DI.name - params); - completion_item_detail = None; - } + let con = ty.DI.typ in + let eq, params, typ = Type.strings_of_kind (Con.kind con) in + Lsp_t. + { + completion_item_label = ty.DI.name; + completion_item_kind = 7; + completion_item_insertText = Some tmpl; + completion_item_insertTextFormat = Some 2; + completion_item_additionalTextEdits = None; + completion_item_documentation = + Some (Printf.sprintf "type %s%s" ty.DI.name params); + completion_item_detail = None; + } let import_relative_to_project_root root module_path dependency = match Lib.FilePath.relative_to root module_path with | None -> None | Some root_to_module -> - root_to_module - |> Filename.dirname - |> Fun.flip Filename.concat dependency - |> Lib.FilePath.normalise - |> Option.some + root_to_module + |> Filename.dirname + |> Fun.flip Filename.concat dependency + |> Lib.FilePath.normalise + |> Option.some (* Given a source file and a cursor position in that file, figure out the prefix relevant to searching completions. For example, given: List.fi| (where | is the cursor) return `Some ("List", "fi")` *) -let find_completion_prefix logger file line column: (string * string) option = +let find_completion_prefix logger file line column : (string * string) option = let open Source in (* The LSP sends 0 based line numbers *) let line = line + 1 in let lexbuf = Lexing.from_string file in let next () = Lexer.token Lexer.Normal lexbuf in - let pos_eq_cursor pos = - pos.line = line && pos.column = column in + let pos_eq_cursor pos = pos.line = line && pos.column = column in let pos_past_cursor pos = - pos.line > line - || (pos.line = line && pos.column > column) in + pos.line > line || (pos.line = line && pos.column > column) + in let rec loop = function - | _ when (pos_past_cursor (Lexer.region lexbuf).right) -> None - | Parser.ID ident -> - let next_token_end = (Lexer.region lexbuf).right in - if pos_eq_cursor next_token_end - then Some("", ident) - else - (match next () with - | Parser.DOT -> - let next_token = next () in - let next_token_start = (Lexer.region lexbuf).left in - if pos_eq_cursor next_token_start - || pos_past_cursor next_token_start - then Some (ident, "") - else - (match next_token with - | Parser.EOF -> Some (ident, "") - | Parser.ID prefix -> - let next_token_start = (Lexer.region lexbuf).left in - let next_token_end = (Lexer.region lexbuf).right in - if pos_eq_cursor next_token_start - || pos_past_cursor next_token_start - then Some (ident, "") - else if pos_eq_cursor next_token_end - then Some (ident, prefix) - else loop (Parser.ID prefix) - | tkn -> loop tkn) - | tkn -> loop tkn) + | _ when pos_past_cursor (Lexer.region lexbuf).right -> None + | Parser.ID ident -> ( + let next_token_end = (Lexer.region lexbuf).right in + if pos_eq_cursor next_token_end then Some ("", ident) + else + match next () with + | Parser.DOT -> ( + let next_token = next () in + let next_token_start = (Lexer.region lexbuf).left in + if + pos_eq_cursor next_token_start + || pos_past_cursor next_token_start + then Some (ident, "") + else + match next_token with + | Parser.EOF -> Some (ident, "") + | Parser.ID prefix -> + let next_token_start = (Lexer.region lexbuf).left in + let next_token_end = (Lexer.region lexbuf).right in + if + pos_eq_cursor next_token_start + || pos_past_cursor next_token_start + then Some (ident, "") + else if pos_eq_cursor next_token_end then + Some (ident, prefix) + else loop (Parser.ID prefix) + | tkn -> loop tkn ) + | tkn -> loop tkn ) | Parser.EOF -> None - | _ -> loop (next ()) in + | _ -> loop (next ()) + in try loop (next ()) with _ -> None -let has_prefix (prefix : string) (ide_decl : DI.ide_decl): bool = +let has_prefix (prefix : string) (ide_decl : DI.ide_decl) : bool = ide_decl |> DI.name_of_ide_decl |> Lib.String.chop_prefix prefix |> Option.is_some -let opt_bind f = function - | None -> None - | Some x -> f x +let opt_bind f = function None -> None | Some x -> f x let completions index logger project_root file_path file_contents line column = - let imported = Source_file.parse_module_header project_root file_path file_contents in + let imported = + Source_file.parse_module_header project_root file_path file_contents + in let current_uri_opt = Lib.FilePath.relative_to project_root file_path in let toplevel_decls = let current_module_decls = current_uri_opt - |> opt_bind (fun uri -> DI.lookup_module project_root (Filename.remove_extension uri) index) - |> Option.fold ~none:[] ~some:snd in + |> opt_bind (fun uri -> + DI.lookup_module project_root (Filename.remove_extension uri) index) + |> Option.fold ~none:[] ~some:snd + in current_module_decls in let module_alias_completion_item alias = - Lsp_t.{ + Lsp_t. + { completion_item_label = alias; completion_item_kind = 9; completion_item_insertText = Some alias; @@ -152,53 +157,67 @@ let completions index logger project_root file_path file_contents line column = completion_item_additionalTextEdits = None; completion_item_documentation = None; completion_item_detail = None; - } in + } + in match find_completion_prefix logger file_contents line column with | None -> - (* If we don't have any prefix to work with, just suggest the - imported module aliases, as well as top-level definitions in - the current file *) - let decls = List.map item_of_ide_decl toplevel_decls in - decls @ List.map (fun (alias, _) -> module_alias_completion_item alias) imported + (* If we don't have any prefix to work with, just suggest the + imported module aliases, as well as top-level definitions in + the current file *) + let decls = List.map item_of_ide_decl toplevel_decls in + decls + @ List.map (fun (alias, _) -> module_alias_completion_item alias) imported | Some ("", prefix) -> - (* Without an alias but with a prefix we filter the toplevel - identifiers of the current module *) - toplevel_decls - |> List.filter (has_prefix prefix) - |> List.map item_of_ide_decl - | Some (alias, prefix) -> - let module_path = - imported - |> List.find_opt (fun (mn, _) -> String.equal mn alias) in - match module_path with - | Some mp -> - (match DI.lookup_module project_root (snd mp) index with - | Some (_, decls) -> - decls - |> List.filter (has_prefix prefix) - |> List.map item_of_ide_decl - | None -> - (* The matching import references a module we haven't loaded *) - []) - | None -> - (* No import with the given alias was found *) - let import_edit = Imports.add_import file_contents alias in - let possible_imports = DI.find_with_prefix prefix (Lib.FilePath.make_absolute project_root file_path) index in - let completions = - Lib.List.concat_map (fun (p, ds) -> - if p = Filename.basename file_path then - (* Self-imports are not allowed *) - [] - else - List.map (fun d -> - Lsp_t.{ - (item_of_ide_decl d) with - completion_item_additionalTextEdits = Some [import_edit p]; - completion_item_detail = Some p - }) ds) possible_imports in - completions + (* Without an alias but with a prefix we filter the toplevel + identifiers of the current module *) + toplevel_decls + |> List.filter (has_prefix prefix) + |> List.map item_of_ide_decl + | Some (alias, prefix) -> ( + let module_path = + imported |> List.find_opt (fun (mn, _) -> String.equal mn alias) + in + match module_path with + | Some mp -> ( + match DI.lookup_module project_root (snd mp) index with + | Some (_, decls) -> + decls + |> List.filter (has_prefix prefix) + |> List.map item_of_ide_decl + | None -> + (* The matching import references a module we haven't loaded *) + [] ) + | None -> + (* No import with the given alias was found *) + let import_edit = Imports.add_import file_contents alias in + let possible_imports = + DI.find_with_prefix prefix + (Lib.FilePath.make_absolute project_root file_path) + index + in + let completions = + Lib.List.concat_map + (fun (p, ds) -> + if p = Filename.basename file_path then + (* Self-imports are not allowed *) + [] + else + List.map + (fun d -> + Lsp_t. + { + (item_of_ide_decl d) with + completion_item_additionalTextEdits = + Some [ import_edit p ]; + completion_item_detail = Some p; + }) + ds) + possible_imports + in + completions ) -let completion_handler index logger project_root file_path file_contents position = +let completion_handler index logger project_root file_path file_contents + position = let line = position.Lsp_t.position_line in let column = position.Lsp_t.position_character in `CompletionResponse diff --git a/src/languageServer/completion_test.ml b/src/languageServer/completion_test.ml index 793063ca9ad..dc222f3269b 100644 --- a/src/languageServer/completion_test.ml +++ b/src/languageServer/completion_test.ml @@ -1,53 +1,45 @@ let extract_cursor input = let cursor_pos = ref (0, 0) in String.split_on_char '\n' input - |> List.mapi - (fun line_num line -> + |> List.mapi (fun line_num line -> match String.index_opt line '|' with | Some column_num -> - cursor_pos := (line_num, column_num); - line - |> String.split_on_char '|' - |> String.concat "" - | None -> line - ) + cursor_pos := (line_num, column_num); + line |> String.split_on_char '|' |> String.concat "" + | None -> line) |> String.concat "\n" |> fun f -> (f, !cursor_pos) let dummy_logger _ _ = () let prefix_test_case file expected = - let (file, (line, column)) = extract_cursor file in + let file, (line, column) = extract_cursor file in let show = function | None -> "None" - | Some (m, p) -> "Some (" ^ m ^ ", " ^ p ^ ")" in + | Some (m, p) -> "Some (" ^ m ^ ", " ^ p ^ ")" + in let actual = - Completion.find_completion_prefix dummy_logger file line column in - Option.equal (=) actual expected || - (Printf.printf - "\nExpected: %s\nActual: %s\n" - (show expected) - (show actual); - false) + Completion.find_completion_prefix dummy_logger file line column + in + Option.equal ( = ) actual expected + || + ( Printf.printf "\nExpected: %s\nActual: %s\n" (show expected) (show actual); + false ) let import_relative_test_case root module_path import expected = let actual = - Completion.import_relative_to_project_root root module_path import in - let show = function - | None -> "None" - | Some s -> "Some " ^ s in - Option.equal String.equal actual expected || - (Printf.printf - "\nExpected: %s\nActual: %s\n" - (show expected) - (show actual); - false) + Completion.import_relative_to_project_root root module_path import + in + let show = function None -> "None" | Some s -> "Some " ^ s in + Option.equal String.equal actual expected + || + ( Printf.printf "\nExpected: %s\nActual: %s\n" (show expected) (show actual); + false ) let%test "it finds unqualified prefixes" = prefix_test_case "filt|" (Some ("", "filt")) -let%test "it understands whitespace" = - prefix_test_case "filt |" None +let%test "it understands whitespace" = prefix_test_case "filt |" None let%test "it does find non-qualified idents after qualifiers" = prefix_test_case "List.filter we|" (Some ("", "we")) @@ -69,14 +61,13 @@ let%test "it handles qualifiers following the cursor" = && prefix_test_case "List.fil| Option" (Some ("List", "fil")) let%test "it handles multiline files" = - prefix_test_case -{|Stak. + prefix_test_case {|Stak. List.| |} (Some ("List", "")) let%test "it handles a full module" = prefix_test_case -{|module { + {|module { private import List = "./ListLib"; func singleton(x: T): List.List = @@ -84,11 +75,12 @@ let%test "it handles a full module" = func doubleton(x: T): List.List = List.cons(x, List.cons(x, List.nil())); - }|} (Some ("Test", "")) + }|} + (Some ("Test", "")) let%test "it doesn't fall through to the next valid prefix" = prefix_test_case -{|module { + {|module { private import List = "lib/ListLib"; // private, so we don't re-export List private import ListFns = "lib/ListFuncs"; // private, so we don't re-export List type Stack = List.List; @@ -97,25 +89,17 @@ func empty():Stack = List.nil(); func singleton(x : Int) : Stack = List.we| ListFns.singleton(x); -}|} (Some ("List", "we")) +}|} + (Some ("List", "we")) let%test "it makes an import relative to the project root" = - import_relative_test_case - "/home/project" - "/home/project/src/main.mo" - "lib/List.mo" - (Some "src/lib/List.mo") + import_relative_test_case "/home/project" "/home/project/src/main.mo" + "lib/List.mo" (Some "src/lib/List.mo") let%test "it preserves trailing slashes for directory imports" = - import_relative_test_case - "/home/project" - "/home/project/src/main.mo" - "lib/List/" - (Some "src/lib/List/") + import_relative_test_case "/home/project" "/home/project/src/main.mo" + "lib/List/" (Some "src/lib/List/") let%test "it can handle parent directory relationships" = - import_relative_test_case - "/home/project" - "/home/project/src/main.mo" - "../lib/List.mo" - (Some "lib/List.mo") + import_relative_test_case "/home/project" "/home/project/src/main.mo" + "../lib/List.mo" (Some "lib/List.mo") diff --git a/src/languageServer/debug.ml b/src/languageServer/debug.ml index ea4344ccd51..a804951dd76 100644 --- a/src/languageServer/debug.ml +++ b/src/languageServer/debug.ml @@ -1,2 +1,3 @@ let logger : (string -> string -> unit) ref = ref (fun _ _ -> ()) + let log : string -> string -> unit = fun msg -> !logger msg diff --git a/src/languageServer/declaration_index.ml b/src/languageServer/declaration_index.ml index ddcc88b765b..3fba343ea63 100644 --- a/src/languageServer/declaration_index.ml +++ b/src/languageServer/declaration_index.ml @@ -4,208 +4,195 @@ open Mo_def open Source open Syntax -type value_decl = { - name : string; - typ: Type.typ; - definition: region option; - } +type value_decl = { name : string; typ : Type.typ; definition : region option } -type type_decl = { - name : string; - typ: Type.con; - definition: region option; - } +type type_decl = { name : string; typ : Type.con; definition : region option } -type ide_decl = - | ValueDecl of value_decl - | TypeDecl of type_decl +type ide_decl = ValueDecl of value_decl | TypeDecl of type_decl -let string_of_option f = function - | None -> "None" - | Some x -> "Some " ^ f x +let string_of_option f = function None -> "None" | Some x -> "Some " ^ f x let string_of_list f xs = - List.map f xs - |> String.concat "; " - |> fun x -> "[ " ^ x ^ " ]" + List.map f xs |> String.concat "; " |> fun x -> "[ " ^ x ^ " ]" (** For debugging purposes *) let string_of_ide_decl = function | ValueDecl value -> - "ValueDecl{ name = " - ^ String.escaped value.name - ^ ", typ = " - ^ Type.string_of_typ value.typ - ^ Lib.Option.get - (Option.map - (fun pos -> ", definition = " ^ string_of_region pos) - value.definition) - "" - ^ " }" + "ValueDecl{ name = " + ^ String.escaped value.name + ^ ", typ = " + ^ Type.string_of_typ value.typ + ^ Lib.Option.get + (Option.map + (fun pos -> ", definition = " ^ string_of_region pos) + value.definition) + "" + ^ " }" | TypeDecl ty -> - "TypeDecl{ name = " - ^ String.escaped ty.name - ^ ", typ = " - ^ Type.string_of_con ty.typ - ^ Lib.Option.get - (Option.map - (fun pos -> ", definition = " ^ string_of_region pos) - ty.definition) - "" - ^ " }" + "TypeDecl{ name = " + ^ String.escaped ty.name + ^ ", typ = " + ^ Type.string_of_con ty.typ + ^ Lib.Option.get + (Option.map + (fun pos -> ", definition = " ^ string_of_region pos) + ty.definition) + "" + ^ " }" let name_of_ide_decl (d : ide_decl) : string = - match d with - | ValueDecl value -> value.name - | TypeDecl ty -> ty.name + match d with ValueDecl value -> value.name | TypeDecl ty -> ty.name let decl_has_prefix prefix d = Option.is_some (Lib.String.chop_prefix prefix (name_of_ide_decl d)) -module Index = Map.Make(String) +module Index = Map.Make (String) type declaration_index = { - modules: ide_decl list Index.t; - actors: ide_decl list Index.t; - package_map: Pipeline.ResolveImport.package_map; - ic_aliases: Pipeline.ResolveImport.aliases; - actor_idl_path : Pipeline.ResolveImport.actor_idl_path; - } + modules : ide_decl list Index.t; + actors : ide_decl list Index.t; + package_map : Pipeline.ResolveImport.package_map; + ic_aliases : Pipeline.ResolveImport.aliases; + actor_idl_path : Pipeline.ResolveImport.actor_idl_path; +} type t = declaration_index -let add_module : string -> ide_decl list -> declaration_index -> declaration_index = - fun path decls ix -> { ix with modules = Index.add path decls ix.modules} +let add_module : + string -> ide_decl list -> declaration_index -> declaration_index = + fun path decls ix -> { ix with modules = Index.add path decls ix.modules } let ic_id_to_lookup : string option -> string -> string -> string = - fun actor_idl_path project_root id -> + fun actor_idl_path project_root id -> let crc = Lib.CRC.crc8 id |> Lib.Hex.hex_of_byte in let hex = Lib.Hex.hex_of_bytes id ^ crc in let idl_path = actor_idl_path |> Option.value ~default:project_root in - Lib.FilePath.make_absolute project_root (Filename.concat idl_path (hex ^ ".did")) + Lib.FilePath.make_absolute project_root + (Filename.concat idl_path (hex ^ ".did")) -let lookup_module - (project_root : string) - (path : string) - (index : t) - : (string * ide_decl list) option = +let lookup_module (project_root : string) (path : string) (index : t) : + (string * ide_decl list) option = let open Pipeline.URL in let make_absolute = Lib.FilePath.make_absolute project_root in match parse path with | Ok (Relative path) -> - let path = - Pipeline.ResolveImport.append_extension Sys.file_exists path in - Index.find_opt (make_absolute path) index.modules - |> Option.map (fun decls -> (path, decls)) + let path = Pipeline.ResolveImport.append_extension Sys.file_exists path in + Index.find_opt (make_absolute path) index.modules + |> Option.map (fun decls -> (path, decls)) | Ok (Package (pkg, path)) -> - Option.bind - (Flags.M.find_opt pkg index.package_map) - (fun pkg_path -> - let path = - Pipeline.ResolveImport.append_extension - Sys.file_exists (Filename.concat pkg_path path) in - Index.find_opt - (make_absolute path) - index.modules - |> Option.map (fun decls -> (path, decls)) - ) + Option.bind (Flags.M.find_opt pkg index.package_map) (fun pkg_path -> + let path = + Pipeline.ResolveImport.append_extension Sys.file_exists + (Filename.concat pkg_path path) + in + Index.find_opt (make_absolute path) index.modules + |> Option.map (fun decls -> (path, decls))) | Ok Prim -> - Index.find_opt "@prim" index.modules - |> Option.map (fun decls -> ("@prim", decls)) + Index.find_opt "@prim" index.modules + |> Option.map (fun decls -> ("@prim", decls)) | Ok (Ic id) -> - let lookup_path = ic_id_to_lookup index.actor_idl_path project_root id in - Index.find_opt lookup_path index.modules - |> Option.map (fun decls -> (path, decls)) + let lookup_path = ic_id_to_lookup index.actor_idl_path project_root id in + Index.find_opt lookup_path index.modules + |> Option.map (fun decls -> (path, decls)) | Ok (IcAlias alias) -> - let mic_id = Flags.M.find_opt alias index.ic_aliases in - let _ = Debug.log "lookup_module.ic_alias.ic_id" (string_of_option (fun x -> x) mic_id) in - Option.bind mic_id (fun id -> - let lookup_path = ic_id_to_lookup index.actor_idl_path project_root id in - Index.find_opt lookup_path index.modules) - |> Option.map (fun decls -> (alias, decls)) + let mic_id = Flags.M.find_opt alias index.ic_aliases in + let _ = + Debug.log "lookup_module.ic_alias.ic_id" + (string_of_option (fun x -> x) mic_id) + in + Option.bind mic_id (fun id -> + let lookup_path = + ic_id_to_lookup index.actor_idl_path project_root id + in + Index.find_opt lookup_path index.modules) + |> Option.map (fun decls -> (alias, decls)) | Error _ -> None let rec drop_common_prefix eq l1 l2 = - match l1, l2 with - | h1 :: t1, h2 :: t2 when eq h1 h2 -> - drop_common_prefix eq t1 t2 + match (l1, l2) with + | h1 :: t1, h2 :: t2 when eq h1 h2 -> drop_common_prefix eq t1 t2 | _ -> (l1, l2) -let shorten_import_path - : Pipeline.ResolveImport.package_map - -> Pipeline.ResolveImport.aliases - -> string - -> string - -> string = - fun pkg_map ic_aliases base path -> - let _ = Debug.log "shorten_import" (Printf.sprintf "base: %s, path: %s" base path) in - if Filename.extension path = ".did" - then +let shorten_import_path : + Pipeline.ResolveImport.package_map -> + Pipeline.ResolveImport.aliases -> + string -> + string -> + string = + fun pkg_map ic_aliases base path -> + let _ = + Debug.log "shorten_import" (Printf.sprintf "base: %s, path: %s" base path) + in + if Filename.extension path = ".did" then let idl_basename = Filename.basename path in Flags.M.bindings ic_aliases |> Lib.List.first_opt (fun (alias, id) -> Debug.log "basename" (Pipeline.URL.idl_basename_of_blob id); - if Pipeline.URL.idl_basename_of_blob id = idl_basename then Some alias else None - ) - |> (function - | None -> Printf.sprintf "ic:%s" (Filename.remove_extension idl_basename) - | Some alias -> Printf.sprintf "canister:%s" alias) + if Pipeline.URL.idl_basename_of_blob id = idl_basename then + Some alias + else None) + |> function + | None -> Printf.sprintf "ic:%s" (Filename.remove_extension idl_basename) + | Some alias -> Printf.sprintf "canister:%s" alias else - let pkg_path = - Flags.M.bindings pkg_map - |> Lib.List.first_opt (fun (name, pkg_path) -> - if Lib.FilePath.is_subpath pkg_path path - then - let rel_path = Option.get (Lib.FilePath.relative_to pkg_path path) in - Some (Printf.sprintf "mo:%s/%s" name (Filename.remove_extension rel_path)) - else - None - ) - in match pkg_path with - | Some p -> p - | None -> - let (base', path') = - drop_common_prefix - String.equal + let pkg_path = + Flags.M.bindings pkg_map + |> Lib.List.first_opt (fun (name, pkg_path) -> + if Lib.FilePath.is_subpath pkg_path path then + let rel_path = + Option.get (Lib.FilePath.relative_to pkg_path path) + in + Some + (Printf.sprintf "mo:%s/%s" name + (Filename.remove_extension rel_path)) + else None) + in + match pkg_path with + | Some p -> p + | None -> + let base', path' = + drop_common_prefix String.equal (Lib.String.split (Filename.dirname base) '/') - (Lib.String.split path '/') in + (Lib.String.split path '/') + in List.map (fun _ -> "..") base' @ path' |> String.concat "/" |> Filename.remove_extension -let find_with_prefix - : string - -> string - -> t - -> (string * ide_decl list) list = - fun prefix base {modules; package_map; ic_aliases; _} -> +let find_with_prefix : string -> string -> t -> (string * ide_decl list) list = + fun prefix base { modules; package_map; ic_aliases; _ } -> Index.bindings modules |> List.map (fun (p, ds) -> let import_path = - if p = "@prim" then - "mo:prim" - else - shorten_import_path package_map ic_aliases base p in + if p = "@prim" then "mo:prim" + else shorten_import_path package_map ic_aliases base p + in (import_path, List.filter (decl_has_prefix prefix) ds)) |> List.filter (fun (_, ds) -> not (ds = [])) -let empty : string -> t = fun cwd -> +let empty : string -> t = + fun cwd -> let open Pipeline.ResolveImport in let resolved_flags = Diag.run (resolve_flags - { package_urls = !Flags.package_urls; + { + package_urls = !Flags.package_urls; actor_aliases = !Flags.actor_aliases; actor_idl_path = !Flags.actor_idl_path; - }) in - { modules = Index.empty; + }) + in + { + modules = Index.empty; actors = Index.empty; - package_map = Flags.M.map (Lib.FilePath.make_absolute cwd) resolved_flags.packages; + package_map = + Flags.M.map (Lib.FilePath.make_absolute cwd) resolved_flags.packages; ic_aliases = resolved_flags.aliases; - actor_idl_path = resolved_flags.actor_idl_path + actor_idl_path = resolved_flags.actor_idl_path; } -module PatternMap = Map.Make(String) +module PatternMap = Map.Make (String) + type pattern_map = Source.region PatternMap.t let rec gather_pat ve pat : pattern_map = @@ -214,179 +201,174 @@ let rec gather_pat ve pat : pattern_map = | VarP id -> PatternMap.add id.it id.at ve | TupP pats -> List.fold_left gather_pat ve pats | ObjP pfs -> List.fold_left gather_pat_field ve pfs - | TagP (_, pat1) | AltP (pat1, _) | OptP pat1 - | AnnotP (pat1, _) | ParP pat1 -> gather_pat ve pat1 + | TagP (_, pat1) | AltP (pat1, _) | OptP pat1 | AnnotP (pat1, _) | ParP pat1 + -> + gather_pat ve pat1 -and gather_pat_field ve pf = - gather_pat ve pf.it.pat +and gather_pat_field ve pf = gather_pat ve pf.it.pat let string_of_index : declaration_index -> string = - fun index -> + fun index -> Index.bindings index.modules - |> string_of_list - (fun (path, decls) -> - path - ^ " =>\n " - ^ string_of_list string_of_ide_decl decls - ^ "\n") - -let read_single_module_lib (ty: Type.typ): ide_decl list option = + |> string_of_list (fun (path, decls) -> + path ^ " =>\n " ^ string_of_list string_of_ide_decl decls ^ "\n") + +let read_single_module_lib (ty : Type.typ) : ide_decl list option = match ty with | Type.Obj ((Type.Module | Type.Actor), fields) -> - fields - |> List.map - (fun Type.{ lab = name; typ } -> - (match typ with + fields + |> List.map (fun Type.{ lab = name; typ } -> + match typ with | Type.Typ con -> TypeDecl { name; typ = con; definition = None } - | typ -> ValueDecl { name; typ; definition = None } - ) - ) - |> Option.some + | typ -> ValueDecl { name; typ; definition = None }) + |> Option.some | _ -> None -let unwrap_module_ast (lib : Syntax.lib): Syntax.exp_field list option = +let unwrap_module_ast (lib : Syntax.lib) : Syntax.exp_field list option = match lib.it.it with | Syntax.BlockE [] -> None - | Syntax.BlockE decs -> - (match Lib.List.last decs with - | {it=Syntax.ExpD {it= Syntax.ObjE(_,fields) ;_} ;_} -> Some fields - | {it=Syntax.LetD(_, {it= Syntax.ObjE(_,fields) ;_}) ;_} -> Some fields - | d -> - Debug.log "unwrap_module_ast" - (Wasm.Sexpr.to_string 80 (Arrange.dec d)); - None) + | Syntax.BlockE decs -> ( + match Lib.List.last decs with + | { it = Syntax.ExpD { it = Syntax.ObjE (_, fields); _ }; _ } -> + Some fields + | { it = Syntax.LetD (_, { it = Syntax.ObjE (_, fields); _ }); _ } -> + Some fields + | d -> + Debug.log "unwrap_module_ast" + (Wasm.Sexpr.to_string 80 (Arrange.dec d)); + None ) | _ -> None - -let populate_definitions - (project_root : string) - (libs : Syntax.lib list) - (path : string) - (decls : ide_decl list) - : ide_decl list = +let populate_definitions (project_root : string) (libs : Syntax.lib list) + (path : string) (decls : ide_decl list) : ide_decl list = let is_let_bound exp_field = match exp_field.it.Syntax.dec.it with - | Syntax.LetD(pat, _) -> Some pat - | _ -> None in + | Syntax.LetD (pat, _) -> Some pat + | _ -> None + in let is_type_def exp_field = match exp_field.it.Syntax.dec.it with - | Syntax.TypD (typ_id, _, _) -> - Some typ_id - | Syntax.ClassD (typ_id, _, _, _, _, _, _) -> - Some typ_id - | _ -> None in + | Syntax.TypD (typ_id, _, _) -> Some typ_id + | Syntax.ClassD (typ_id, _, _, _, _, _, _) -> Some typ_id + | _ -> None + in let extract_binders env (pat : Syntax.pat) = gather_pat env pat in let find_def (lib : Syntax.lib) def = match def with | ValueDecl value -> - let fields = Lib.Option.get (unwrap_module_ast lib) [] in - let positioned_binder = - fields - |> List.filter_map is_let_bound - |> List.fold_left extract_binders PatternMap.empty - |> PatternMap.find_opt value.name - in - ValueDecl { value with definition = positioned_binder } + let fields = Lib.Option.get (unwrap_module_ast lib) [] in + let positioned_binder = + fields + |> List.filter_map is_let_bound + |> List.fold_left extract_binders PatternMap.empty + |> PatternMap.find_opt value.name + in + ValueDecl { value with definition = positioned_binder } | TypeDecl typ -> - let fields = Lib.Option.get (unwrap_module_ast lib) [] in - let type_definition = - fields - |> List.filter_map is_type_def - |> Lib.List.first_opt (fun ty_id -> - if ty_id.it = typ.name - then Some ty_id.at - else None) - in - TypeDecl { typ with definition = type_definition } in + let fields = Lib.Option.get (unwrap_module_ast lib) [] in + let type_definition = + fields + |> List.filter_map is_type_def + |> Lib.List.first_opt (fun ty_id -> + if ty_id.it = typ.name then Some ty_id.at else None) + in + TypeDecl { typ with definition = type_definition } + in let opt_lib = List.find_opt - (fun lib -> String.equal path (Lib.FilePath.make_absolute project_root lib.note)) - libs in - match opt_lib with - | None -> decls - | Some lib -> - List.map (find_def lib) decls + (fun lib -> + String.equal path (Lib.FilePath.make_absolute project_root lib.note)) + libs + in + match opt_lib with None -> decls | Some lib -> List.map (find_def lib) decls let list_files_recursively dir = let rec loop result = function - | f::fs when Sys.is_directory f -> - Sys.readdir f - |> Array.to_list - |> List.map (Filename.concat f) - |> List.append fs - |> loop result - | f::fs -> loop (f::result) fs - | [] -> result in - loop [] [dir] + | f :: fs when Sys.is_directory f -> + Sys.readdir f + |> Array.to_list + |> List.map (Filename.concat f) + |> List.append fs + |> loop result + | f :: fs -> loop (f :: result) fs + | [] -> result + in + loop [] [ dir ] let scan_packages : unit -> string list = - fun _ -> + fun _ -> let scan_package path = list_files_recursively path - |> List.filter (fun f -> Filename.extension f = ".mo") in + |> List.filter (fun f -> Filename.extension f = ".mo") + in Flags.M.fold (fun _ v acc -> scan_package v @ acc) !Flags.package_urls [] let scan_actors : unit -> string list = - fun _ -> + fun _ -> match !Flags.actor_idl_path with | None -> [] | Some idl_path -> - list_files_recursively idl_path - |> List.filter (fun f -> Filename.extension f = ".did") + list_files_recursively idl_path + |> List.filter (fun f -> Filename.extension f = ".did") let index_from_scope : string -> t -> Syntax.lib list -> Scope.t -> t = - fun project_root initial_index libs scope -> + fun project_root initial_index libs scope -> Type.Env.fold (fun path ty acc -> let path = - if path = "@prim" then - path - else - Lib.FilePath.make_absolute project_root path in - add_module - path - (ty - |> read_single_module_lib - |> Fun.flip Lib.Option.get [] - |> populate_definitions project_root libs path) + if path = "@prim" then path + else Lib.FilePath.make_absolute project_root path + in + add_module path + ( ty + |> read_single_module_lib + |> Fun.flip Lib.Option.get [] + |> populate_definitions project_root libs path ) acc) - scope.Scope.lib_env - initial_index + scope.Scope.lib_env initial_index let make_index_inner logger project_root vfs entry_points : t Diag.result = - let package_paths = List.map (fun f -> LibPath f @@ Source.no_region) (scan_packages ()) in - let package_env = Pipeline.chase_imports (Vfs.parse_file vfs) Pipeline.initial_stat_env package_paths in - let lib_index = match package_env with - | Result.Error errs -> begin - List.iter (fun err -> - logger "lib_index_errors" (Diag.string_of_message err)) errs; - empty project_root - end + let package_paths = + List.map (fun f -> LibPath f @@ Source.no_region) (scan_packages ()) + in + let package_env = + Pipeline.chase_imports (Vfs.parse_file vfs) Pipeline.initial_stat_env + package_paths + in + let lib_index = + match package_env with + | Result.Error errs -> + List.iter + (fun err -> logger "lib_index_errors" (Diag.string_of_message err)) + errs; + empty project_root | Result.Ok ((libs, scope), _) -> - index_from_scope project_root (empty project_root) libs scope in + index_from_scope project_root (empty project_root) libs scope + in let actor_paths = scan_actors () in let _ = Debug.log "Actor paths" (string_of_list (fun x -> x) actor_paths) in let actor_env = - List.fold_left (fun acc f -> - Idllib.Pipeline.check_file f - |> function - | Result.Error errs -> - List.iter (fun err -> - logger "actor_index_errors" (Diag.string_of_message err)) errs; - acc - | Result.Ok ((prog, idl_scope, actor_opt), _) -> - let actor = Mo_idl.Idl_to_mo.check_prog idl_scope actor_opt in - Scope.adjoin acc (Scope.lib f actor); - ) Pipeline.initial_stat_env actor_paths in + List.fold_left + (fun acc f -> + Idllib.Pipeline.check_file f |> function + | Result.Error errs -> + List.iter + (fun err -> + logger "actor_index_errors" (Diag.string_of_message err)) + errs; + acc + | Result.Ok ((prog, idl_scope, actor_opt), _) -> + let actor = Mo_idl.Idl_to_mo.check_prog idl_scope actor_opt in + Scope.adjoin acc (Scope.lib f actor)) + Pipeline.initial_stat_env actor_paths + in let actor_index = index_from_scope project_root lib_index [] actor_env in (* TODO(Christoph): We should be able to return at least the actor_index even if compiling from the entry points fails *) - Pipeline.load_progs - (Vfs.parse_file vfs) - entry_points + Pipeline.load_progs (Vfs.parse_file vfs) entry_points Pipeline.initial_stat_env - |> Diag.map (fun (libs, _, scope) -> index_from_scope project_root actor_index libs scope) - + |> Diag.map (fun (libs, _, scope) -> + index_from_scope project_root actor_index libs scope) let make_index logger project_root vfs entry_points : t Diag.result = (* TODO(Christoph): Actually handle errors here *) diff --git a/src/languageServer/declaration_index.mli b/src/languageServer/declaration_index.mli index 6daa08d5783..85b49967798 100644 --- a/src/languageServer/declaration_index.mli +++ b/src/languageServer/declaration_index.mli @@ -2,60 +2,40 @@ open Source open Mo_types type t + val empty : string -> t + val string_of_index : t -> string -type value_decl = { - name : string; - typ: Type.typ; - definition: region option; - } +type value_decl = { name : string; typ : Type.typ; definition : region option } -type type_decl = { - name : string; - typ: Type.con; - definition: region option; - } +type type_decl = { name : string; typ : Type.con; definition : region option } -type ide_decl = - | ValueDecl of value_decl - | TypeDecl of type_decl +type ide_decl = ValueDecl of value_decl | TypeDecl of type_decl val string_of_ide_decl : ide_decl -> string + val name_of_ide_decl : ide_decl -> string -val shorten_import_path - : Pipeline.ResolveImport.package_map - (** The package map for searching package paths *) - -> Pipeline.ResolveImport.aliases - (** The aliases for looking up canister ids *) - -> string - (** The file that ends up containing the import *) - -> string - (** The path to be shortened *) - -> string - -val lookup_module - : string - -> string - -> t - -> (string * ide_decl list) option - -val find_with_prefix - : string - (** The prefix *) - -> string - (** The file in which the results would be imported *) - -> t - (** The declaration index *) - -> (string * ide_decl list) list - -val make_index - : (string -> string -> unit) - (** A logger *) - -> string - (** The project root *) - -> Vfs.t - -> string list - (** The entry points *) - -> t Diag.result +val shorten_import_path : + Pipeline.ResolveImport.package_map + (** The package map for searching package paths *) -> + Pipeline.ResolveImport.aliases (** The aliases for looking up canister ids *) -> + string (** The file that ends up containing the import *) -> + string (** The path to be shortened *) -> + string + +val lookup_module : string -> string -> t -> (string * ide_decl list) option + +val find_with_prefix : + string (** The prefix *) -> + string (** The file in which the results would be imported *) -> + t (** The declaration index *) -> + (string * ide_decl list) list + +val make_index : + (string -> string -> unit) (** A logger *) -> + string (** The project root *) -> + Vfs.t -> + string list (** The entry points *) -> + t Diag.result diff --git a/src/languageServer/declaration_index_test.ml b/src/languageServer/declaration_index_test.ml index f9613e966a2..ea05bb9844c 100644 --- a/src/languageServer/declaration_index_test.ml +++ b/src/languageServer/declaration_index_test.ml @@ -3,26 +3,17 @@ let shorten_test pkg_map aliases base path expected = Declaration_index.shorten_import_path (Mo_config.Flags.M.of_seq (List.to_seq pkg_map)) (Mo_config.Flags.M.of_seq (List.to_seq aliases)) - base - path in - if not (actual = expected) then - (Printf.printf "Expected:\n%s\nBut got:\n%s\n" expected actual; - false) - else - true + base path + in + if not (actual = expected) then ( + Printf.printf "Expected:\n%s\nBut got:\n%s\n" expected actual; + false ) + else true let%test "it shortens to a relative path" = - shorten_test - [("std", "/pkgs/std")] - [] - "/project/src/file.mo" - "/project/src/lib/hello.mo" - "lib/hello" + shorten_test [ ("std", "/pkgs/std") ] [] "/project/src/file.mo" + "/project/src/lib/hello.mo" "lib/hello" let%test "it shortens to a package path" = - shorten_test - [("std", "/pkgs/std")] - [] - "/project/src/file.mo" - "/pkgs/std/list.mo" - "mo:std/list" + shorten_test [ ("std", "/pkgs/std") ] [] "/project/src/file.mo" + "/pkgs/std/list.mo" "mo:std/list" diff --git a/src/languageServer/definition.ml b/src/languageServer/definition.ml index 9961c9d1cfb..56da1a1562a 100644 --- a/src/languageServer/definition.ml +++ b/src/languageServer/definition.ml @@ -1,70 +1,63 @@ module Lsp = Lsp.Lsp_t module DI = Declaration_index -let position_of_pos (pos : Source.pos) : Lsp.position = Lsp. - (* The LSP spec requires zero-based positions *) - { position_line = if pos.Source.line > 0 then pos.Source.line - 1 else 0; - position_character = pos.Source.column; - } +let position_of_pos (pos : Source.pos) : Lsp.position = + Lsp. + { + (* The LSP spec requires zero-based positions *) + position_line = (if pos.Source.line > 0 then pos.Source.line - 1 else 0); + position_character = pos.Source.column; + } -let range_of_region (at : Source.region) : Lsp.range = Lsp. - { range_start = position_of_pos at.Source.left; - range_end_ = position_of_pos at.Source.right; - } +let range_of_region (at : Source.region) : Lsp.range = + Lsp. + { + range_start = position_of_pos at.Source.left; + range_end_ = position_of_pos at.Source.right; + } -let find_named - : string -> - (string * DI.ide_decl list) -> - (string * Source.region) option = - fun name (path, decls) -> - Lib.List.first_opt (function - | DI.ValueDecl value -> - if String.equal value.DI.name name - then value.DI.definition - else None - | DI.TypeDecl typ -> - if String.equal typ.DI.name name - then typ.DI.definition - else None) decls +let find_named : + string -> string * DI.ide_decl list -> (string * Source.region) option = + fun name (path, decls) -> + Lib.List.first_opt + (function + | DI.ValueDecl value -> + if String.equal value.DI.name name then value.DI.definition else None + | DI.TypeDecl typ -> + if String.equal typ.DI.name name then typ.DI.definition else None) + decls |> Option.map (fun x -> (path, x)) -let opt_bind f = function - | Some x -> f x - | None -> None +let opt_bind f = function Some x -> f x | None -> None -let definition_handler - index - position - file_contents - project_root - file_path = +let definition_handler index position file_contents project_root file_path = let result = let open Source_file in Option.bind - (Source_file.identifier_at_pos - project_root - file_path - file_contents - position) - (function - | Alias _ -> None - | Unresolved _ -> None - | Resolved resolved -> + (Source_file.identifier_at_pos project_root file_path file_contents + position) (function + | Alias _ -> None + | Unresolved _ -> None + | Resolved resolved -> DI.lookup_module project_root resolved.path index |> opt_bind (find_named resolved.ident) - | Ident ident -> + | Ident ident -> Lib.FilePath.relative_to project_root file_path |> opt_bind (fun uri -> - DI.lookup_module project_root uri index - |> opt_bind (find_named ident) - )) in + DI.lookup_module project_root uri index + |> opt_bind (find_named ident))) + in let location = - Option.map (fun (path, region) -> + Option.map + (fun (path, region) -> Lsp. - { location_uri = - if Source_file.is_package_path path - then Option.get (Source_file.uri_for_package path) - else Vfs.uri_from_file path; - location_range = range_of_region region - }) result in + { + location_uri = + ( if Source_file.is_package_path path then + Option.get (Source_file.uri_for_package path) + else Vfs.uri_from_file path ); + location_range = range_of_region region; + }) + result + in `TextDocumentDefinitionResponse (Option.to_list location) diff --git a/src/languageServer/hover.ml b/src/languageServer/hover.ml index 94fb7b854d7..88f8176dd9d 100644 --- a/src/languageServer/hover.ml +++ b/src/languageServer/hover.ml @@ -4,53 +4,44 @@ module Lsp = Lsp.Lsp_t module DI = Declaration_index let hover_detail = function - | ValueDecl value -> - value.name ^ " : " ^ Pretty.string_of_typ value.typ + | ValueDecl value -> value.name ^ " : " ^ Pretty.string_of_typ value.typ | TypeDecl ty -> - let _, params, _ = Type.strings_of_kind (Con.kind ty.typ) in - Printf.sprintf "public type %s%s" ty.name params + let _, params, _ = Type.strings_of_kind (Con.kind ty.typ) in + Printf.sprintf "public type %s%s" ty.name params let markup_content (msg : string) : Lsp.markup_content = - Lsp.{ markup_content_kind = "plaintext"; - markup_content_value = msg } + Lsp.{ markup_content_kind = "plaintext"; markup_content_value = msg } -let hover_handler - (logger : string -> string -> unit) - (index : DI.t) - (position : Lsp.position) - (file_contents : string) - (project_root : string) - (file_path : string) = +let hover_handler (logger : string -> string -> unit) (index : DI.t) + (position : Lsp.position) (file_contents : string) (project_root : string) + (file_path : string) = let current_uri_opt = Lib.FilePath.relative_to project_root file_path in let toplevel_decls = current_uri_opt |> Fun.flip Option.bind (fun uri -> lookup_module project_root uri index) - |> Option.fold ~none:[] ~some:snd in + |> Option.fold ~none:[] ~some:snd + in let mk_hover_result ide_decl = - Lsp.{ hover_result_contents = markup_content (hover_detail ide_decl) } in + Lsp.{ hover_result_contents = markup_content (hover_detail ide_decl) } + in let hover_result = Option.bind - (Source_file.identifier_at_pos - project_root - file_path - file_contents - position) - (function - | Source_file.Alias (_, path) -> - Some Lsp.{ hover_result_contents = markup_content path } - | Source_file.Resolved resolved -> - lookup_module project_root resolved.Source_file.path index - |> Fun.flip Option.bind (fun (_, decls) -> - List.find_opt - (fun d -> name_of_ide_decl d = resolved.Source_file.ident) - decls) - |> Option.map mk_hover_result - | Source_file.Ident ident -> - toplevel_decls - |> List.find_opt (fun d -> name_of_ide_decl d = ident) - |> Option.map mk_hover_result - | Source_file.Unresolved _ -> - None) - in + (Source_file.identifier_at_pos project_root file_path file_contents + position) (function + | Source_file.Alias (_, path) -> + Some Lsp.{ hover_result_contents = markup_content path } + | Source_file.Resolved resolved -> + lookup_module project_root resolved.Source_file.path index + |> Fun.flip Option.bind (fun (_, decls) -> + List.find_opt + (fun d -> name_of_ide_decl d = resolved.Source_file.ident) + decls) + |> Option.map mk_hover_result + | Source_file.Ident ident -> + toplevel_decls + |> List.find_opt (fun d -> name_of_ide_decl d = ident) + |> Option.map mk_hover_result + | Source_file.Unresolved _ -> None) + in let result = `TextDocumentHoverResponse hover_result in result diff --git a/src/languageServer/hover_tests.ml b/src/languageServer/hover_tests.ml index 6ab38d1bcfa..7829d63f700 100644 --- a/src/languageServer/hover_tests.ml +++ b/src/languageServer/hover_tests.ml @@ -1,45 +1,41 @@ module Lsp = Lsp.Lsp_t + let extract_cursor input = let cursor_pos = ref (0, 0) in String.split_on_char '\n' input - |> List.mapi - (fun line_num line -> + |> List.mapi (fun line_num line -> match String.index_opt line '|' with | Some column_num -> - cursor_pos := (line_num, column_num); - line - |> String.split_on_char '|' - |> String.concat "" - | None -> line - ) + cursor_pos := (line_num, column_num); + line |> String.split_on_char '|' |> String.concat "" + | None -> line) |> String.concat "\n" |> fun f -> (f, !cursor_pos) let hovered_identifier_test_case file expected = - let (file, (line, column)) = extract_cursor file in + let file, (line, column) = extract_cursor file in let show = function - | Some(Source_file.CIdent i) -> i - | Some(Source_file.CQualified (qualifier, ident)) -> qualifier ^ "." ^ ident - | None -> "None" in + | Some (Source_file.CIdent i) -> i + | Some (Source_file.CQualified (qualifier, ident)) -> + qualifier ^ "." ^ ident + | None -> "None" + in let actual = Source_file.cursor_target_at_pos - Lsp.{ position_line = line; position_character = column } file in - Option.equal (=) actual expected || - (Printf.printf - "\nExpected: %s\nActual: %s\n" - (show expected) - (show actual); - false) + Lsp.{ position_line = line; position_character = column } + file + in + Option.equal ( = ) actual expected + || + ( Printf.printf "\nExpected: %s\nActual: %s\n" (show expected) (show actual); + false ) let%test "it finds an identifier" = - hovered_identifier_test_case - "f|ilter" - (Some (Source_file.CIdent "filter")) + hovered_identifier_test_case "f|ilter" (Some (Source_file.CIdent "filter")) let%test "it ignores hovering over whitespace" = hovered_identifier_test_case "filter |" None let%test "it finds a qualified identifier" = - hovered_identifier_test_case - "List.f|ilter" + hovered_identifier_test_case "List.f|ilter" (Some (Source_file.CQualified ("List", "filter"))) diff --git a/src/languageServer/imports.ml b/src/languageServer/imports.ml index 7abfc35baf5..19db2d86987 100644 --- a/src/languageServer/imports.ml +++ b/src/languageServer/imports.ml @@ -1,5 +1,6 @@ (** Import management for Motoko's language server *) open Mo_frontend + open Mo_def open Source module Lsp = Lsp.Lsp_t @@ -7,73 +8,69 @@ module Lsp = Lsp.Lsp_t type import = string * string let parse_with mode lexer parser = - Ok (Parsing.parse 0 (parser lexer.Lexing.lex_curr_p) (Lexer.token mode) lexer) + Ok (Parsing.parse 0 (parser lexer.Lexing.lex_curr_p) (Lexer.token mode) lexer) let parse_string s = try - (let lexer = Lexing.from_string s in + let lexer = Lexing.from_string s in let parse = Parser.Incremental.parse_module_header in - ignore (parse_with Lexer.Normal lexer parse); []) + ignore (parse_with Lexer.Normal lexer parse); + [] with | Parser_lib.Imports is -> is | ex -> [] let match_import : Syntax.dec -> string * string = - fun dec -> + fun dec -> let open Syntax in match dec.it with - | LetD ({it=VarP {it=name;_};_}, {it=ImportE(s, _);_}) -> (name, s) + | LetD ({ it = VarP { it = name; _ }; _ }, { it = ImportE (s, _); _ }) -> + (name, s) | _ -> ("Can't", "deal with this import format") let print_import : import -> string = - fun (alias, path) -> - Printf.sprintf "import %s \"%s\";" alias path + fun (alias, path) -> Printf.sprintf "import %s \"%s\";" alias path (** Formats an import section. Eg. sorting imports alphabetically *) let format_imports : import list -> string = - fun imports -> - if imports = [] - then "" + fun imports -> + if imports = [] then "" else String.concat "\n" - (List.map - print_import + (List.map print_import (List.sort (fun (a1, _) (a2, _) -> compare a1 a2) imports)) ^ "\n" let mk_range : int * int -> int * int -> Lsp.range = - fun (sl, sc) (el, ec) -> - Lsp.{ - range_start = - { position_line = sl; - position_character = sc - }; - range_end_ = - { position_line = el; - position_character = ec - } - } + fun (sl, sc) (el, ec) -> + Lsp. + { + range_start = { position_line = sl; position_character = sc }; + range_end_ = { position_line = el; position_character = ec }; + } let add_import : string -> string -> string -> Lsp.text_edit = - fun input -> + fun input -> (* We do the parsing as soon as we get the input so the curried usage of this function doesn't duplicate work *) match parse_string input with | [] -> - fun alias import_path -> - Lsp.{ - text_edit_range = mk_range (0, 0) (0, 0); - text_edit_newText = format_imports [(alias, import_path)] - } - | decls -> - let open Source in - let start_line = (List.hd decls).at.left.line - 1 in - let end_line = (Lib.List.last decls).at.right.line - 1 in - let imports = List.map match_import decls in - let import_range = mk_range (start_line, 0) (end_line + 1, 0) in - fun alias import_path -> - let new_imports = (alias, import_path) :: imports in - Lsp.{ - text_edit_range = import_range; - text_edit_newText = format_imports new_imports - } + fun alias import_path -> + Lsp. + { + text_edit_range = mk_range (0, 0) (0, 0); + text_edit_newText = format_imports [ (alias, import_path) ]; + } + | decls -> + let open Source in + let start_line = (List.hd decls).at.left.line - 1 in + let end_line = (Lib.List.last decls).at.right.line - 1 in + let imports = List.map match_import decls in + let import_range = mk_range (start_line, 0) (end_line + 1, 0) in + fun alias import_path -> + let new_imports = (alias, import_path) :: imports in + Lsp. + { + text_edit_range = import_range; + text_edit_newText = format_imports new_imports; + } diff --git a/src/languageServer/languageServer.ml b/src/languageServer/languageServer.ml index 6170028f24a..52ca883b7f7 100644 --- a/src/languageServer/languageServer.ml +++ b/src/languageServer/languageServer.ml @@ -8,24 +8,33 @@ module Lsp_t = Lsp.Lsp_t let jsonrpc_version : string = "2.0" -let notification (params : Lsp_t.notification_message_params) : Lsp_t.notification_message = Lsp_t. - { notification_message_jsonrpc = jsonrpc_version; - notification_message_params = params; - } +let notification (params : Lsp_t.notification_message_params) : + Lsp_t.notification_message = + Lsp_t. + { + notification_message_jsonrpc = jsonrpc_version; + notification_message_params = params; + } -let response_result_message (id : int) (result : Lsp_t.response_result) : Lsp_t.response_message = Lsp_t. - { response_message_jsonrpc = jsonrpc_version; - response_message_id = id; - response_message_result = Some result; - response_message_error = None; - } +let response_result_message (id : int) (result : Lsp_t.response_result) : + Lsp_t.response_message = + Lsp_t. + { + response_message_jsonrpc = jsonrpc_version; + response_message_id = id; + response_message_result = Some result; + response_message_error = None; + } -let response_error_message (id : int) (error : Lsp_t.response_error) : Lsp_t.response_message = Lsp_t. - { response_message_jsonrpc = jsonrpc_version; - response_message_id = id; - response_message_result = None; - response_message_error = Some error; - } +let response_error_message (id : int) (error : Lsp_t.response_error) : + Lsp_t.response_message = + Lsp_t. + { + response_message_jsonrpc = jsonrpc_version; + response_message_id = id; + response_message_result = None; + response_message_error = Some error; + } module Channel = struct let log_to_file (oc : out_channel) (lbl : string) (txt : string) : unit = @@ -40,66 +49,84 @@ module Channel = struct flush stdout let send_response (oc : out_channel) : string -> unit = send oc "response" - let send_notification (oc : out_channel) : string -> unit = send oc "notification" - let show_message (oc : out_channel) (typ : Lsp.MessageType.t) (msg: string): unit = + let send_notification (oc : out_channel) : string -> unit = + send oc "notification" + + let show_message (oc : out_channel) (typ : Lsp.MessageType.t) (msg : string) : + unit = let params = `WindowShowMessage - (Lsp_t. - { window_show_message_params_type_ = typ; + Lsp_t. + { + window_show_message_params_type_ = typ; window_show_message_params_message = msg; - }) in + } + in let notification = notification params in send_notification oc (Lsp_j.string_of_notification_message notification) - let publish_diagnostics (oc : out_channel) (uri : Lsp_t.document_uri) (diags : Lsp_t.diagnostic list): unit = - let params = `PublishDiagnostics (Lsp_t. - { publish_diagnostics_params_uri = uri; - publish_diagnostics_params_diagnostics = diags; - }) in + let publish_diagnostics (oc : out_channel) (uri : Lsp_t.document_uri) + (diags : Lsp_t.diagnostic list) : unit = + let params = + `PublishDiagnostics + Lsp_t. + { + publish_diagnostics_params_uri = uri; + publish_diagnostics_params_diagnostics = diags; + } + in let notification = notification params in send_notification oc (Lsp_j.string_of_notification_message notification) - let clear_diagnostics (oc : out_channel) (uri : Lsp_t.document_uri): unit = + let clear_diagnostics (oc : out_channel) (uri : Lsp_t.document_uri) : unit = publish_diagnostics oc uri [] end -let position_of_pos (pos : Source.pos) : Lsp_t.position = Lsp_t. - (* The LSP spec requires zero-based positions *) - { position_line = if pos.Source.line > 0 then pos.Source.line - 1 else 0; - position_character = pos.Source.column; - } +let position_of_pos (pos : Source.pos) : Lsp_t.position = + Lsp_t. + { + (* The LSP spec requires zero-based positions *) + position_line = (if pos.Source.line > 0 then pos.Source.line - 1 else 0); + position_character = pos.Source.column; + } -let range_of_region (at : Source.region) : Lsp_t.range = Lsp_t. - { range_start = position_of_pos at.Source.left; - range_end_ = position_of_pos at.Source.right; - } +let range_of_region (at : Source.region) : Lsp_t.range = + Lsp_t. + { + range_start = position_of_pos at.Source.left; + range_end_ = position_of_pos at.Source.right; + } let severity_of_sev : Diag.severity -> Lsp.DiagnosticSeverity.t = function | Diag.Error -> Lsp.DiagnosticSeverity.Error | Diag.Warning -> Lsp.DiagnosticSeverity.Warning | Diag.Info -> Lsp.DiagnosticSeverity.Information -let diagnostics_of_message (msg : Diag.message) : (Lsp_t.diagnostic * string) = (Lsp_t. - { diagnostic_range = range_of_region msg.Diag.at; - diagnostic_severity = Some (severity_of_sev msg.Diag.sev); - diagnostic_code = None; - diagnostic_source = Some "Motoko"; - diagnostic_message = msg.Diag.text; - diagnostic_relatedInformation = None; - }, msg.Diag.at.Source.left.Source.file) +let diagnostics_of_message (msg : Diag.message) : Lsp_t.diagnostic * string = + ( Lsp_t. + { + diagnostic_range = range_of_region msg.Diag.at; + diagnostic_severity = Some (severity_of_sev msg.Diag.sev); + diagnostic_code = None; + diagnostic_source = Some "Motoko"; + diagnostic_message = msg.Diag.text; + diagnostic_relatedInformation = None; + }, + msg.Diag.at.Source.left.Source.file ) let start entry_point debug = - let oc: out_channel = - if debug then - open_out_gen [Open_append; Open_creat] 0o666 "ls.log" - else - open_out "/dev/null" in + let oc : out_channel = + if debug then open_out_gen [ Open_append; Open_creat ] 0o666 "ls.log" + else open_out "/dev/null" + in let log_to_file = Channel.log_to_file oc in let _ = log_to_file "entry_point" entry_point in - let _ = Flags.M.iter - (fun k v -> log_to_file "package" (Printf.sprintf "%s => %s" k v)) - !Flags.package_urls in + let _ = + Flags.M.iter + (fun k v -> log_to_file "package" (Printf.sprintf "%s => %s" k v)) + !Flags.package_urls + in let _ = Debug.logger := log_to_file in let publish_diagnostics = Channel.publish_diagnostics oc in let clear_diagnostics = Channel.clear_diagnostics oc in @@ -113,178 +140,203 @@ let start entry_point debug = let files_with_diags = ref [] in let vfs = ref Vfs.empty in let decl_index = - let ix = match Declaration_index.make_index log_to_file project_root !vfs [entry_point] with + let ix = + match + Declaration_index.make_index log_to_file project_root !vfs + [ entry_point ] + with | Error errs -> - List.iter (fun err -> log_to_file "Error" (Diag.string_of_message err)) errs; - startup_diags := errs; - Declaration_index.empty project_root - | Ok((ix, _)) -> ix in - ref ix in - + List.iter + (fun err -> log_to_file "Error" (Diag.string_of_message err)) + errs; + startup_diags := errs; + Declaration_index.empty project_root + | Ok (ix, _) -> ix + in + ref ix + in let sync_diagnostics msgs = let diags_by_file = msgs |> List.map diagnostics_of_message |> Lib.List.group (fun (_, f1) (_, f2) -> f1 = f2) |> List.map (fun diags -> - let (_, file) = List.hd diags in - (List.map fst diags, Vfs.uri_from_file file)) in + let _, file = List.hd diags in + (List.map fst diags, Vfs.uri_from_file file)) + in List.iter clear_diagnostics !files_with_diags; files_with_diags := List.map snd diags_by_file; - List.iter (fun (diags, uri) -> publish_diagnostics uri diags) diags_by_file in - + List.iter (fun (diags, uri) -> publish_diagnostics uri diags) diags_by_file + in let handle_message raw = function - | (Some id, `Initialize params) -> - client_capabilities := Some params.Lsp_t.initialize_params_capabilities; - let completion_options = - Lsp_t.{ - completion_options_resolveProvider = Some false; - completion_options_triggerCharacters = Some ["."] } in - let text_document_sync_options = - Lsp_t.{ - text_document_sync_options_openClose = Some true; - (* Full *) - (* text_document_sync_options_change = Some 1; *) - (* Incremental *) - text_document_sync_options_change = Some 2; - text_document_sync_options_willSave = Some false; - text_document_sync_options_willSaveWaitUntil = Some false; - text_document_sync_options_save = Some { - save_options_includeText = Some true - } - } in - let result = `Initialize (Lsp_t.{ - initialize_result_capabilities = { - server_capabilities_textDocumentSync = text_document_sync_options; - server_capabilities_hoverProvider = Some true; - server_capabilities_completionProvider = Some completion_options; - server_capabilities_definitionProvider = Some true; - } - }) in + | Some id, `Initialize params -> + client_capabilities := Some params.Lsp_t.initialize_params_capabilities; + let completion_options = + Lsp_t. + { + completion_options_resolveProvider = Some false; + completion_options_triggerCharacters = Some [ "." ]; + } + in + let text_document_sync_options = + Lsp_t. + { + text_document_sync_options_openClose = Some true; + (* Full *) + (* text_document_sync_options_change = Some 1; *) + (* Incremental *) + text_document_sync_options_change = Some 2; + text_document_sync_options_willSave = Some false; + text_document_sync_options_willSaveWaitUntil = Some false; + text_document_sync_options_save = + Some { save_options_includeText = Some true }; + } + in + let result = + `Initialize + Lsp_t. + { + initialize_result_capabilities = + { + server_capabilities_textDocumentSync = + text_document_sync_options; + server_capabilities_hoverProvider = Some true; + server_capabilities_completionProvider = + Some completion_options; + server_capabilities_definitionProvider = Some true; + }; + } + in let response = response_result_message id result in - send_response (Lsp_j.string_of_response_message response); - - | (Some id, `TextDocumentHover params) -> - let uri = - params - .Lsp_t.text_document_position_params_textDocument - .Lsp_t.text_document_identifier_uri in - let position = - params.Lsp_t.text_document_position_params_position in - let response = match Vfs.read_file uri !vfs with - | None -> - response_error_message - id - Lsp_t.{ code = 1 - ; message = "Tried to find hover a file that hadn't been opened yet"} - | Some file_content -> - let result = - Hover.hover_handler - log_to_file - !decl_index - position - file_content - project_root - (Vfs.abs_file_from_uri log_to_file uri) in - response_result_message id result in - send_response (Lsp_j.string_of_response_message response); - | (Some id, `TextDocumentDefinition params) -> - let uri = - params - .Lsp_t.text_document_position_params_textDocument - .Lsp_t.text_document_identifier_uri in - let position = - params.Lsp_t.text_document_position_params_position in - let response = match Vfs.read_file uri !vfs with - | None -> - response_error_message - id - Lsp_t.{ code = 1 - ; message = "Tried to find a definition in a file that hadn't been opened yet"} - | Some file_content -> - let result = - Definition.definition_handler - !decl_index - position - file_content - project_root - (Vfs.abs_file_from_uri log_to_file uri) in - response_result_message id result in - send_response (Lsp_j.string_of_response_message response); - | (_, `TextDocumentDidOpen params) -> - vfs := Vfs.open_file params !vfs - | (_, `TextDocumentDidChange params) -> - vfs := Vfs.update_file params !vfs - | (_, `TextDocumentDidClose params) -> - vfs := Vfs.close_file params !vfs - | (_, `TextDocumentDidSave _) -> - let msgs = match Declaration_index.make_index log_to_file project_root !vfs [entry_point] with - | Error msgs' -> List.iter (fun msg -> log_to_file "rebuild_error" (Diag.string_of_message msg)) msgs'; msgs' - | Ok((ix, msgs')) -> - decl_index := ix; - msgs' in - sync_diagnostics msgs - - | (None, `Initialized _) -> - sync_diagnostics !startup_diags; - startup_diags := []; - show_message Lsp.MessageType.Info "Motoko LS initialized"; - - | (Some id, `Shutdown _) -> - shutdown := true; - response_result_message id (`ShutdownResponse None) - |> Lsp_j.string_of_response_message - |> send_response - - | (_, `Exit _) -> - if !shutdown then exit 0 else exit 1 - - | (Some id, `CompletionRequest params) -> - let uri = - params - .Lsp_t.text_document_position_params_textDocument - .Lsp_t.text_document_identifier_uri in - let position = - params.Lsp_t.text_document_position_params_position in - let response = match Vfs.read_file uri !vfs with - | None -> - response_error_message - id - Lsp_t.{ code = 1 - ; message = "Tried to find completions for a file that hadn't been opened yet"} - | Some file_content -> - Completion.completion_handler - !decl_index - log_to_file - project_root - (Vfs.abs_file_from_uri log_to_file uri) - file_content - position - |> response_result_message id in - response - |> Lsp_j.string_of_response_message - |> send_response + send_response (Lsp_j.string_of_response_message response) + | Some id, `TextDocumentHover params -> + let uri = + params.Lsp_t.text_document_position_params_textDocument + .Lsp_t.text_document_identifier_uri + in + let position = params.Lsp_t.text_document_position_params_position in + let response = + match Vfs.read_file uri !vfs with + | None -> + response_error_message id + Lsp_t. + { + code = 1; + message = + "Tried to find hover a file that hadn't been opened yet"; + } + | Some file_content -> + let result = + Hover.hover_handler log_to_file !decl_index position + file_content project_root + (Vfs.abs_file_from_uri log_to_file uri) + in + response_result_message id result + in + send_response (Lsp_j.string_of_response_message response) + | Some id, `TextDocumentDefinition params -> + let uri = + params.Lsp_t.text_document_position_params_textDocument + .Lsp_t.text_document_identifier_uri + in + let position = params.Lsp_t.text_document_position_params_position in + let response = + match Vfs.read_file uri !vfs with + | None -> + response_error_message id + Lsp_t. + { + code = 1; + message = + "Tried to find a definition in a file that hadn't been \ + opened yet"; + } + | Some file_content -> + let result = + Definition.definition_handler !decl_index position file_content + project_root + (Vfs.abs_file_from_uri log_to_file uri) + in + response_result_message id result + in + send_response (Lsp_j.string_of_response_message response) + | _, `TextDocumentDidOpen params -> vfs := Vfs.open_file params !vfs + | _, `TextDocumentDidChange params -> vfs := Vfs.update_file params !vfs + | _, `TextDocumentDidClose params -> vfs := Vfs.close_file params !vfs + | _, `TextDocumentDidSave _ -> + let msgs = + match + Declaration_index.make_index log_to_file project_root !vfs + [ entry_point ] + with + | Error msgs' -> + List.iter + (fun msg -> + log_to_file "rebuild_error" (Diag.string_of_message msg)) + msgs'; + msgs' + | Ok (ix, msgs') -> + decl_index := ix; + msgs' + in + sync_diagnostics msgs + | None, `Initialized _ -> + sync_diagnostics !startup_diags; + startup_diags := []; + show_message Lsp.MessageType.Info "Motoko LS initialized" + | Some id, `Shutdown _ -> + shutdown := true; + response_result_message id (`ShutdownResponse None) + |> Lsp_j.string_of_response_message + |> send_response + | _, `Exit _ -> if !shutdown then exit 0 else exit 1 + | Some id, `CompletionRequest params -> + let uri = + params.Lsp_t.text_document_position_params_textDocument + .Lsp_t.text_document_identifier_uri + in + let position = params.Lsp_t.text_document_position_params_position in + let response = + match Vfs.read_file uri !vfs with + | None -> + response_error_message id + Lsp_t. + { + code = 1; + message = + "Tried to find completions for a file that hadn't been \ + opened yet"; + } + | Some file_content -> + Completion.completion_handler !decl_index log_to_file project_root + (Vfs.abs_file_from_uri log_to_file uri) + file_content position + |> response_result_message id + in + response |> Lsp_j.string_of_response_message |> send_response (* Unhandled messages *) - | _ -> - log_to_file "unhandled message" raw in - + | _ -> log_to_file "unhandled message" raw + in let rec loop () = let clength = read_line () in let cl = "Content-Length: " in let cll = String.length cl in let num = - int_of_string - String.(trim (sub clength cll (length(clength) - cll - 1))) + 2 in + int_of_string String.(trim (sub clength cll (length clength - cll - 1))) + + 2 + in let buffer = Buffer.create num in Buffer.add_channel buffer stdin num; let raw = String.trim (Buffer.contents buffer) in let message = - try Some (Lsp_j.incoming_message_of_string raw) - with _ -> None in - (match message with - | None -> Debug.log "decoding error" raw - | Some message -> + try Some (Lsp_j.incoming_message_of_string raw) with _ -> None + in + ( match message with + | None -> Debug.log "decoding error" raw + | Some message -> let message_id = message.Lsp_t.incoming_message_id in - handle_message raw (message_id, message.Lsp_t.incoming_message_params)); + handle_message raw (message_id, message.Lsp_t.incoming_message_params) + ); loop () - in loop () + in + loop () diff --git a/src/languageServer/pretty.ml b/src/languageServer/pretty.ml index a6af05160e6..10a9c88b558 100644 --- a/src/languageServer/pretty.ml +++ b/src/languageServer/pretty.ml @@ -1 +1,3 @@ -include Mo_types.Type.MakePretty(struct let show_stamps = false end) +include Mo_types.Type.MakePretty (struct + let show_stamps = false +end) diff --git a/src/languageServer/source_file.ml b/src/languageServer/source_file.ml index 4f11ea379d4..487cbb19332 100644 --- a/src/languageServer/source_file.ml +++ b/src/languageServer/source_file.ml @@ -2,80 +2,72 @@ open Mo_frontend open Mo_config module Lsp = Lsp.Lsp_t -type cursor_target = - | CIdent of string - | CQualified of string * string +type cursor_target = CIdent of string | CQualified of string * string let string_of_cursor_target = function | CIdent i -> "(CIdent " ^ i ^ ")" | CQualified (q, i) -> "CQUalified (" ^ q ^ ", " ^ i ^ ")" -let cursor_target_at_pos - (position : Lsp.position) - (file_contents : string) - : cursor_target option = +let cursor_target_at_pos (position : Lsp.position) (file_contents : string) : + cursor_target option = let line = position.Lsp.position_line + 1 in let column = position.Lsp.position_character + 1 in let lexbuf = Lexing.from_string file_contents in let next () = Lexer.token Lexer.Normal lexbuf in let pos_past_cursor pos = pos.Source.line > line - || (pos.Source.line = line && pos.Source.column >= column) in + || (pos.Source.line = line && pos.Source.column >= column) + in let rec loop = function - | _ when (pos_past_cursor (Lexer.region lexbuf).Source.left) -> None - | Parser.ID ident -> - (match next () with - | Parser.DOT -> - (match next () with + | _ when pos_past_cursor (Lexer.region lexbuf).Source.left -> None + | Parser.ID ident -> ( + match next () with + | Parser.DOT -> ( + match next () with | Parser.ID prefix -> - let next_token_end = (Lexer.region lexbuf).Source.right in - if pos_past_cursor next_token_end - then Some (CQualified (ident, prefix)) - else loop (Parser.ID prefix) + let next_token_end = (Lexer.region lexbuf).Source.right in + if pos_past_cursor next_token_end then + Some (CQualified (ident, prefix)) + else loop (Parser.ID prefix) | tkn -> - let next_token_start = (Lexer.region lexbuf).Source.left in - if pos_past_cursor next_token_start - then Some (CIdent ident) - else loop tkn) + let next_token_start = (Lexer.region lexbuf).Source.left in + if pos_past_cursor next_token_start then Some (CIdent ident) + else loop tkn ) | _ when pos_past_cursor (Lexer.region lexbuf).Source.left -> - Some (CIdent ident) - | tkn -> loop tkn) + Some (CIdent ident) + | tkn -> loop tkn ) | Parser.EOF -> None - | _ -> loop (next ()) in + | _ -> loop (next ()) + in try loop (next ()) with _ -> None let is_package_path (path : string) = let open Pipeline.URL in - match parse path with - | Ok (Package _) -> true - | Ok Prim -> true - | _ -> false + match parse path with Ok (Package _) -> true | Ok Prim -> true | _ -> false let uri_for_package (path : string) = let open Pipeline.URL in match parse path with - | Ok (Package (pkg, path)) -> - begin match Flags.M.find_opt pkg !Flags.package_urls with - | None -> None - | Some pkg_path -> - (* Resolved package paths are always absolute *) - (* TBR: But Flags.package_urls does not contain the resolved paths! *) - Some ("file://" ^ Filename.concat pkg_path path) - end + | Ok (Package (pkg, path)) -> ( + match Flags.M.find_opt pkg !Flags.package_urls with + | None -> None + | Some pkg_path -> + (* Resolved package paths are always absolute *) + (* TBR: But Flags.package_urls does not contain the resolved paths! *) + Some ("file://" ^ Filename.concat pkg_path path) ) | _ -> None let import_relative_to_project_root root module_path dependency = - if is_package_path dependency - then Some dependency + if is_package_path dependency then Some dependency else match Lib.FilePath.relative_to root module_path with | None -> None | Some root_to_module -> - root_to_module - |> Filename.dirname - |> Fun.flip Filename.concat dependency - |> Lib.FilePath.normalise - |> Option.some + root_to_module + |> Filename.dirname + |> Fun.flip Filename.concat dependency + |> Lib.FilePath.normalise + |> Option.some (* Given the source of a module, figure out under what names what modules have been imported. Normalizes the imported modules @@ -85,30 +77,30 @@ let parse_module_header project_root current_file_path file = let next () = Lexer.token Lexer.Normal lexbuf in let res = ref [] in let rec loop = function - | Parser.IMPORT -> - (match next () with - | Parser.ID alias -> - (match next () with + | Parser.IMPORT -> ( + match next () with + | Parser.ID alias -> ( + match next () with | Parser.TEXT path -> - let path = - import_relative_to_project_root - project_root - current_file_path - path in - (match path with + let path = + import_relative_to_project_root project_root current_file_path + path + in + ( match path with | Some path -> res := (alias, path) :: !res - | None -> ()); - loop (next ()) - | tkn -> loop tkn) - | tkn -> loop tkn) + | None -> () ); + loop (next ()) + | tkn -> loop tkn ) + | tkn -> loop tkn ) | Parser.EOF -> List.rev !res - | tkn -> loop (next ()) in + | tkn -> loop (next ()) + in try loop (next ()) with _ -> List.rev !res -type unresolved_target = - { qualifier : string; ident : string } -type resolved_target = - { qualifier : string; ident : string; path : string } +type unresolved_target = { qualifier : string; ident : string } + +type resolved_target = { qualifier : string; ident : string; path : string } + type identifier_target = | Ident of string | Alias of string * string @@ -116,18 +108,14 @@ type identifier_target = | Resolved of resolved_target let identifier_at_pos project_root file_path file_contents position = - let imported = - parse_module_header - project_root - file_path - file_contents in + let imported = parse_module_header project_root file_path file_contents in cursor_target_at_pos position file_contents |> Option.map (function - | CIdent s -> - (match List.find_opt (fun (alias, _) -> alias = s) imported with - | None -> Ident s - | Some (alias, path) -> Alias (alias, path)) - | CQualified (qual, ident) -> - (match List.find_opt (fun (alias, _) -> alias = qual) imported with - | None -> Unresolved { qualifier = qual; ident } - | Some (alias, path) -> Resolved { qualifier = qual; ident; path })) + | CIdent s -> ( + match List.find_opt (fun (alias, _) -> alias = s) imported with + | None -> Ident s + | Some (alias, path) -> Alias (alias, path) ) + | CQualified (qual, ident) -> ( + match List.find_opt (fun (alias, _) -> alias = qual) imported with + | None -> Unresolved { qualifier = qual; ident } + | Some (alias, path) -> Resolved { qualifier = qual; ident; path } )) diff --git a/src/languageServer/source_file_tests.ml b/src/languageServer/source_file_tests.ml index f304440d8b6..b07690d835e 100644 --- a/src/languageServer/source_file_tests.ml +++ b/src/languageServer/source_file_tests.ml @@ -1,93 +1,76 @@ module Lsp = Lsp.Lsp_t + let extract_cursor input = let cursor_pos = ref (0, 0) in String.split_on_char '\n' input - |> List.mapi - (fun line_num line -> + |> List.mapi (fun line_num line -> match String.index_opt line '|' with | Some column_num -> - cursor_pos := (line_num, column_num); - line - |> String.split_on_char '|' - |> String.concat "" - | None -> line - ) + cursor_pos := (line_num, column_num); + line |> String.split_on_char '|' |> String.concat "" + | None -> line) |> String.concat "\n" |> fun f -> (f, !cursor_pos) let hovered_identifier_test_case file expected = - let (file, (line, column)) = extract_cursor file in + let file, (line, column) = extract_cursor file in let show = function - | Some(Source_file.CIdent i) -> i - | Some(Source_file.CQualified (qualifier, ident)) -> qualifier ^ "." ^ ident - | None -> "None" in + | Some (Source_file.CIdent i) -> i + | Some (Source_file.CQualified (qualifier, ident)) -> + qualifier ^ "." ^ ident + | None -> "None" + in let actual = Source_file.cursor_target_at_pos - Lsp.{ position_line = line; position_character = column } file in - Option.equal (=) actual expected || - (Printf.printf - "\nExpected: %s\nActual: %s\n" - (show expected) - (show actual); - false) + Lsp.{ position_line = line; position_character = column } + file + in + Option.equal ( = ) actual expected + || + ( Printf.printf "\nExpected: %s\nActual: %s\n" (show expected) (show actual); + false ) let parse_module_header_test_case project_root current_file file expected = - let actual = - Source_file.parse_module_header - project_root - current_file file in + let actual = Source_file.parse_module_header project_root current_file file in let display_result (alias, path) = Printf.sprintf "%s => \"%s\"" alias path in - let result = Lib.List.equal - (fun (x, y) (x', y') -> - String.equal x x' && String.equal y y') - actual - expected in + let result = + Lib.List.equal + (fun (x, y) (x', y') -> String.equal x x' && String.equal y y') + actual expected + in if not result then - Printf.printf - "\nExpected: %s\nActual: %s" + Printf.printf "\nExpected: %s\nActual: %s" (Completion.string_of_list display_result expected) - (Completion.string_of_list display_result actual) else (); + (Completion.string_of_list display_result actual) + else (); result let%test "it finds an identifier" = - hovered_identifier_test_case - "f|ilter" - (Some (Source_file.CIdent "filter")) + hovered_identifier_test_case "f|ilter" (Some (Source_file.CIdent "filter")) let%test "it ignores hovering over whitespace" = hovered_identifier_test_case "filter |" None let%test "it finds a qualified identifier" = - hovered_identifier_test_case - "List.f|ilter" + hovered_identifier_test_case "List.f|ilter" (Some (Source_file.CQualified ("List", "filter"))) - let%test "it parses a simple module header" = - parse_module_header_test_case - "/project" - "/project/src/Main.mo" + parse_module_header_test_case "/project" "/project/src/Main.mo" "import P \"lib/prelude\"" - ["P", "src/lib/prelude"] + [ ("P", "src/lib/prelude") ] let%test "it parses a simple module header that contains a prim import" = - parse_module_header_test_case - "/project" - "/project/src/Main.mo" - "import Prim \"mo:prim\"" - ["Prim", "mo:prim"] + parse_module_header_test_case "/project" "/project/src/Main.mo" + "import Prim \"mo:prim\"" [ ("Prim", "mo:prim") ] let%test "it parses a simple module header with package paths" = - parse_module_header_test_case - "/project" - "/project/src/Main.mo" + parse_module_header_test_case "/project" "/project/src/Main.mo" "import P \"mo:stdlib/prelude\"" - ["P", "mo:stdlib/prelude"] + [ ("P", "mo:stdlib/prelude") ] let%test "it parses a simple module header" = - parse_module_header_test_case - "/project" - "/project/Main.mo" + parse_module_header_test_case "/project" "/project/Main.mo" {| module { @@ -106,6 +89,4 @@ func singleton(x: Int): Stack = ListFuncs.doubleton(x, x); } |} - [ ("List", "lib/ListLib") - ; ("ListFuncs", "lib/ListFuncs") - ] + [ ("List", "lib/ListLib"); ("ListFuncs", "lib/ListFuncs") ] diff --git a/src/languageServer/vfs.ml b/src/languageServer/vfs.ml index 34dbef00f99..b93b04643f2 100644 --- a/src/languageServer/vfs.ml +++ b/src/languageServer/vfs.ml @@ -1,6 +1,5 @@ module Lsp_t = Lsp.Lsp_t - -module VfsStore = Map.Make(String) +module VfsStore = Map.Make (String) (* TODO(Christoph): Terrible format, ideally we want some RRB or HAMT backed vector type with a zipper *) @@ -11,114 +10,114 @@ type t = virtual_file VfsStore.t type uri = string let file_uri_prefix = "file://" ^ Sys.getcwd () ^ "/" + let uri_from_file path = "file://" ^ Lib.FilePath.make_absolute (Sys.getcwd ()) path let file_from_uri logger uri = match Lib.String.chop_prefix file_uri_prefix uri with - | Some file -> file - | None -> + | Some file -> file + | None -> let _ = logger "error" ("Failed to strip filename from: " ^ uri) in uri + let abs_file_from_uri logger uri = Lib.FilePath.normalise - (match Lib.String.chop_prefix "file://" uri with - | Some file -> file - | None -> + ( match Lib.String.chop_prefix "file://" uri with + | Some file -> file + | None -> let _ = logger "error" ("Failed to strip filename from: " ^ uri) in - uri) + uri ) let empty = VfsStore.empty let open_file did_open_params vfs = let text_document_item = - did_open_params - .Lsp_t - .text_document_did_open_params_textDocument in - let uri = - text_document_item.Lsp_t.text_document_item_uri in - let _ = - text_document_item.Lsp_t.text_document_item_version in - let text = - text_document_item.Lsp_t.text_document_item_text in + did_open_params.Lsp_t.text_document_did_open_params_textDocument + in + let uri = text_document_item.Lsp_t.text_document_item_uri in + let _ = text_document_item.Lsp_t.text_document_item_version in + let text = text_document_item.Lsp_t.text_document_item_text in let lines = (* TODO(Christoph): Windows compatibility issues *) - Lib.String.split text '\n' in + Lib.String.split text '\n' + in VfsStore.add uri lines vfs let read_file uri vfs = - VfsStore.find_opt uri vfs - |> Option.map (String.concat "\n") + VfsStore.find_opt uri vfs |> Option.map (String.concat "\n") let close_file did_close_params = let uri = - did_close_params - .Lsp_t.text_document_did_close_params_textDocument - .Lsp_t.text_document_identifier_uri in + did_close_params.Lsp_t.text_document_did_close_params_textDocument + .Lsp_t.text_document_identifier_uri + in VfsStore.remove uri (* This isn't recursive, but I prefer apply_change to be defined after update_file, to keep the public API of the module in one place *) let rec update_file did_change_params (vfs : t) : t = let uri = - did_change_params - .Lsp_t.text_document_did_change_params_textDocument - .Lsp_t.versioned_text_document_identifier_uri in + did_change_params.Lsp_t.text_document_did_change_params_textDocument + .Lsp_t.versioned_text_document_identifier_uri + in let change_events = - did_change_params.Lsp_t.text_document_did_change_params_contentChanges in + did_change_params.Lsp_t.text_document_did_change_params_contentChanges + in let previous_content = (* TODO Let's not crash here *) - VfsStore.find uri vfs in + VfsStore.find uri vfs + in let new_content = - List.fold_left apply_change previous_content change_events in + List.fold_left apply_change previous_content change_events + in VfsStore.add uri new_content vfs -and apply_change lines Lsp_t.{ - text_document_content_change_event_range = range; - text_document_content_change_event_rangeLength = rangeLength; - text_document_content_change_event_text = text - } = +and apply_change lines + Lsp_t. + { + text_document_content_change_event_range = range; + text_document_content_change_event_rangeLength = rangeLength; + text_document_content_change_event_text = text; + } = match range with | None -> - (* If the range is None, the editor expects us to fully replace - the file content *) - (* TODO(Christoph): We should be normalising file endings here *) - Lib.String.split text '\n' - | Some Lsp_t.{ - range_start = - { position_line = sl; - position_character = sc - }; - range_end_ = - { position_line = el; - position_character = ec - } - } -> - let (prev_lines, rest) = Lib.List.split_at sl lines in - let (affected, past_lines) = Lib.List.split_at (el - sl + 1) rest in - (* let print_lines lbl ls = - * Printf.printf "%s: %s\n" lbl ("[" ^ join_with "; " ls ^ "]") in - * let _ = print_lines "prev" prev_lines; - * print_lines "aff" affected; - * print_lines "past" past_lines in *) - (* TODO(Christoph): All the String.sub calls following should - operate on UTF16 code unit boundaries instead, as that's what - LSP talks. *) - let new_ = match affected with - | [] -> text - | [aff] -> - String.sub aff 0 sc - ^ text - ^ String.sub aff ec (String.length aff - ec) - | affected -> - let (init, last) = Lib.List.split_last affected in - String.sub (String.concat "\n" init) 0 sc - ^ text - ^ String.sub last ec (String.length last - ec) - in - prev_lines @ Lib.String.split new_ '\n' @ past_lines + (* If the range is None, the editor expects us to fully replace + the file content *) + (* TODO(Christoph): We should be normalising file endings here *) + Lib.String.split text '\n' + | Some + Lsp_t. + { + range_start = { position_line = sl; position_character = sc }; + range_end_ = { position_line = el; position_character = ec }; + } -> + let prev_lines, rest = Lib.List.split_at sl lines in + let affected, past_lines = Lib.List.split_at (el - sl + 1) rest in + (* let print_lines lbl ls = + * Printf.printf "%s: %s\n" lbl ("[" ^ join_with "; " ls ^ "]") in + * let _ = print_lines "prev" prev_lines; + * print_lines "aff" affected; + * print_lines "past" past_lines in *) + (* TODO(Christoph): All the String.sub calls following should + operate on UTF16 code unit boundaries instead, as that's what + LSP talks. *) + let new_ = + match affected with + | [] -> text + | [ aff ] -> + String.sub aff 0 sc + ^ text + ^ String.sub aff ec (String.length aff - ec) + | affected -> + let init, last = Lib.List.split_last affected in + String.sub (String.concat "\n" init) 0 sc + ^ text + ^ String.sub last ec (String.length last - ec) + in + prev_lines @ Lib.String.split new_ '\n' @ past_lines let parse_file vfs path = match read_file (uri_from_file path) vfs with | None -> Pipeline.parse_file path - | Some(file) -> Pipeline.parse_string path file + | Some file -> Pipeline.parse_string path file diff --git a/src/languageServer/vfs.mli b/src/languageServer/vfs.mli index 23b37541533..3bb0017b927 100644 --- a/src/languageServer/vfs.mli +++ b/src/languageServer/vfs.mli @@ -3,27 +3,32 @@ module Lsp_t = Lsp.Lsp_t type t type uri = string + (* NOTE(Christoph): Track file version *) val uri_from_file : string -> uri + val file_from_uri : (string -> string -> 'a) -> uri -> string + val abs_file_from_uri : (string -> string -> 'a) -> uri -> string + val parse_file : t -> Pipeline.parse_fn (** Creates a new virtual file system *) -val empty: t +val empty : t (** Reads a file from the OS's file system and adds it to the vfs *) -val open_file: Lsp_t.text_document_did_open_params -> t -> t +val open_file : Lsp_t.text_document_did_open_params -> t -> t (** Reads a file from the vfs *) -val read_file: uri -> t -> string option +val read_file : uri -> t -> string option (** Updates the contents of a file in the vfs *) -val update_file: Lsp_t.text_document_did_change_params -> t -> t +val update_file : Lsp_t.text_document_did_change_params -> t -> t (** Removes a file from the vfs *) -val close_file: Lsp_t.text_document_did_close_params -> t -> t +val close_file : Lsp_t.text_document_did_close_params -> t -> t (** For tests *) -val apply_change: string list -> Lsp_t.text_document_content_change_event -> string list +val apply_change : + string list -> Lsp_t.text_document_content_change_event -> string list diff --git a/src/languageServer/vfs_tests.ml b/src/languageServer/vfs_tests.ml index 1cb2af954f1..7affa5965f7 100644 --- a/src/languageServer/vfs_tests.ml +++ b/src/languageServer/vfs_tests.ml @@ -5,56 +5,50 @@ let extract_cursors input = let start_found = ref false in let cursor_end = ref (0, 0) in String.split_on_char '\n' input - |> List.mapi - (fun line_num line -> + |> List.mapi (fun line_num line -> match String.index_opt line '|' with | Some column_num -> - if not !start_found - then begin - start_found := true; - cursor_start := (line_num, column_num); - (* See if we can find a second pipe in the same line *) - (match String.index_from_opt line (column_num + 1) '|' with - | Some column_num -> - (* Need to account for the previously found pipe, - so we subtract 1 from the column_num *) - cursor_end := (line_num, column_num - 1); - | None -> ()) - end - else - cursor_end := (line_num, column_num); - line - |> String.split_on_char '|' - |> String.concat "" - | None -> line - ) + if not !start_found then ( + start_found := true; + cursor_start := (line_num, column_num); + (* See if we can find a second pipe in the same line *) + match String.index_from_opt line (column_num + 1) '|' with + | Some column_num -> + (* Need to account for the previously found pipe, + so we subtract 1 from the column_num *) + cursor_end := (line_num, column_num - 1) + | None -> () ) + else cursor_end := (line_num, column_num); + line |> String.split_on_char '|' |> String.concat "" + | None -> line) |> String.concat "\n" |> fun f -> (f, !cursor_start, !cursor_end) let apply_change_test_case file replacement expected = - let (input, (sl, sc), (el, ec)) = extract_cursors file in + let input, (sl, sc), (el, ec) = extract_cursors file in (* let _ = Printf.printf "start: %d:%d, end: %d:%d" sl sc el ec in *) let range = - Lsp.{ + Lsp. + { range_start = { position_line = sl; position_character = sc }; range_end_ = { position_line = el; position_character = ec }; - } + } in let actual = String.concat "\n" (Vfs.apply_change (Lib.String.split input '\n') - Lsp.{ - text_document_content_change_event_range = Some range; - text_document_content_change_event_rangeLength = Some 0; - text_document_content_change_event_text = replacement; - }) in - String.equal actual expected || - (Printf.printf - "\nExpected: %s\nActual: %s\n" - expected - actual; - false) + Lsp. + { + text_document_content_change_event_range = Some range; + text_document_content_change_event_rangeLength = Some 0; + text_document_content_change_event_text = replacement; + }) + in + String.equal actual expected + || + ( Printf.printf "\nExpected: %s\nActual: %s\n" expected actual; + false ) let%test "it applies the empty change" = apply_change_test_case "hi ||dude" "" "hi dude" @@ -65,8 +59,6 @@ let%test "it applies a change" = let%test "it applies a two-line change" = apply_change_test_case "1\n|2|\n3" "4\n5" "1\n4\n5\n3" -let%test "it removes a line" = - apply_change_test_case "a\n|b\n|c" "" "a\nc" +let%test "it removes a line" = apply_change_test_case "a\n|b\n|c" "" "a\nc" -let%test "it inserts a newline" = - apply_change_test_case "a\n||b" "\n" "a\n\nb" +let%test "it inserts a newline" = apply_change_test_case "a\n||b" "\n" "a\n\nb" From 8ece6318acc6decdee1b3021cf43afa651f2a3bb Mon Sep 17 00:00:00 2001 From: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> Date: Fri, 27 Mar 2020 15:59:12 +0100 Subject: [PATCH 1142/1176] Only add imports for capital module names (#1314) Until we have better scoping information --- src/languageServer/completion.ml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/languageServer/completion.ml b/src/languageServer/completion.ml index 6bce63e783e..fb98fbe8453 100644 --- a/src/languageServer/completion.ml +++ b/src/languageServer/completion.ml @@ -133,6 +133,8 @@ let has_prefix (prefix : string) (ide_decl : DI.ide_decl) : bool = let opt_bind f = function None -> None | Some x -> f x +let is_capital : string -> bool = fun s -> String.capitalize_ascii s = s + let completions index logger project_root file_path file_contents line column = let imported = Source_file.parse_module_header project_root file_path file_contents @@ -187,7 +189,9 @@ let completions index logger project_root file_path file_contents line column = | None -> (* The matching import references a module we haven't loaded *) [] ) - | None -> + (* We only try to add imports for capital aliases. Once we've got + * proper scoping information this can be improved *) + | None when is_capital alias -> (* No import with the given alias was found *) let import_edit = Imports.add_import file_contents alias in let possible_imports = @@ -214,7 +218,8 @@ let completions index logger project_root file_path file_contents line column = ds) possible_imports in - completions ) + completions + | None -> [] ) let completion_handler index logger project_root file_path file_contents position = From c9dbf4cbdebf9c7daec7b2956858283e3bf216f7 Mon Sep 17 00:00:00 2001 From: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> Date: Fri, 27 Mar 2020 16:24:54 +0100 Subject: [PATCH 1143/1176] Removes the completion template logic (#1313) Now that we have inference for type parameters it's no longer clear whether the user wants to type those parameters out or not, so we can't automatically insert a template for them. Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- src/languageServer/completion.ml | 34 +++----------------------------- 1 file changed, 3 insertions(+), 31 deletions(-) diff --git a/src/languageServer/completion.ml b/src/languageServer/completion.ml index fb98fbe8453..11e7ed362a4 100644 --- a/src/languageServer/completion.ml +++ b/src/languageServer/completion.ml @@ -6,46 +6,18 @@ module DI = Declaration_index let string_of_list f xs = List.map f xs |> String.concat "; " |> fun x -> "[ " ^ x ^ " ]" -let template_of_ide_decl decl = - let supply = ref 0 in - let fresh () = - supply := !supply + 1; - string_of_int !supply - in - match decl with - | DI.ValueDecl value -> ( - match value.DI.typ with - | Type.Func (_, _, binds, ty_list1, ty_list2) -> - let ty_args = - binds - |> List.filter Type.(fun { sort; _ } -> sort = Type) - |> List.map (fun Type.{ var; bound; _ } -> - Printf.sprintf "${%s:%s}" (fresh ()) var) - |> String.concat ", " - in - let args = - ty_list1 - |> List.map (fun _ -> Printf.sprintf "$%s" (fresh ())) - |> String.concat ", " - in - let ty_args = if ty_args = "" then "" else "<" ^ ty_args ^ ">" in - Printf.sprintf "%s%s(%s)" value.DI.name ty_args args - | _ -> value.DI.name ) - | DI.TypeDecl ty -> ty.DI.name - let string_of_item (item : Lsp_t.completion_item) : string = item.Lsp_t.completion_item_label let item_of_ide_decl (d : DI.ide_decl) : Lsp_t.completion_item = - (* let tmpl = template_of_ide_decl d in *) - let tmpl = DI.name_of_ide_decl d in + let comp = DI.name_of_ide_decl d in match d with | DI.ValueDecl value -> Lsp_t. { completion_item_label = value.DI.name; completion_item_kind = 3; - completion_item_insertText = Some tmpl; + completion_item_insertText = Some comp; completion_item_insertTextFormat = Some 2; completion_item_additionalTextEdits = None; completion_item_documentation = @@ -59,7 +31,7 @@ let item_of_ide_decl (d : DI.ide_decl) : Lsp_t.completion_item = { completion_item_label = ty.DI.name; completion_item_kind = 7; - completion_item_insertText = Some tmpl; + completion_item_insertText = Some comp; completion_item_insertTextFormat = Some 2; completion_item_additionalTextEdits = None; completion_item_documentation = From d5719a6e24029b8ca16772317da149dcb3b1598c Mon Sep 17 00:00:00 2001 From: DFINITY bot <58022693+dfinity-bot@users.noreply.github.com> Date: Sat, 28 Mar 2020 01:06:23 +0100 Subject: [PATCH 1144/1176] niv common: update 24be014b -> d0c1d2d5 (#1315) ## Changelog for common: Commits: [dfinity-lab/common@24be014b...d0c1d2d5](https://github.com/dfinity-lab/common/compare/24be014bd63a35ef70a595048605afc0d3640c59...d0c1d2d5e3aead1872c91663baf6d635ea020107) * [`0f09988e`](https://github.com/dfinity-lab/common/commit/0f09988efef495ab3b2de022a7e616d0d2fb4472) sh-fmt and sh-fmt-check fix find file for extension-less files * [`1c8d203e`](https://github.com/dfinity-lab/common/commit/1c8d203e096266b5e44ff2583dff0b745a4168e9) sh-fmt, sh-check make bash scripts filter explicit for extensionless files --- nix/sources.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/sources.json b/nix/sources.json index 6af5819952a..0eddab80874 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -2,7 +2,7 @@ "common": { "ref": "master", "repo": "ssh://git@github.com/dfinity-lab/common", - "rev": "24be014bd63a35ef70a595048605afc0d3640c59", + "rev": "d0c1d2d5e3aead1872c91663baf6d635ea020107", "type": "git" }, "dfinity": { From 78660e13a15a9f6a765ec7c00e39fa8a6b499e0b Mon Sep 17 00:00:00 2001 From: DFINITY bot <58022693+dfinity-bot@users.noreply.github.com> Date: Tue, 31 Mar 2020 02:07:39 +0200 Subject: [PATCH 1145/1176] niv common: update d0c1d2d5 -> 21396311 (#1318) ## Changelog for common: Commits: [dfinity-lab/common@d0c1d2d5...21396311](https://github.com/dfinity-lab/common/compare/d0c1d2d5e3aead1872c91663baf6d635ea020107...2139631132d8206ff3a514794a5a5fd36af9c895) * [`96cf45ec`](https://github.com/dfinity-lab/common/commit/96cf45ec8d4aa03c43778321f88c258df006ae53) fmt tools only affect tracked files * [`c158cb03`](https://github.com/dfinity-lab/common/commit/c158cb03041b9d165f49b2e35b7504f32b79c0ff) nix-fmt sh-fmt only modify tracked files. Replace abspath script with coreutils/realpath --- nix/sources.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/sources.json b/nix/sources.json index 0eddab80874..624e83db033 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -2,7 +2,7 @@ "common": { "ref": "master", "repo": "ssh://git@github.com/dfinity-lab/common", - "rev": "d0c1d2d5e3aead1872c91663baf6d635ea020107", + "rev": "2139631132d8206ff3a514794a5a5fd36af9c895", "type": "git" }, "dfinity": { From 958ebc72e2fbd431ee1371017c35b57b27bf153b Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Tue, 31 Mar 2020 10:26:54 -0600 Subject: [PATCH 1146/1176] fix syntax --- stdlib/src/array.mo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/src/array.mo b/stdlib/src/array.mo index 30d7b949a72..41f98374769 100644 --- a/stdlib/src/array.mo +++ b/stdlib/src/array.mo @@ -160,7 +160,7 @@ module { for (i in range(1,len-1)) { xs[i] := gen i; }; - } + }; return xs; }; } From 546a04f232610bf7b0a86e02bbb6fe9ba9c36c44 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Tue, 31 Mar 2020 10:39:28 -0600 Subject: [PATCH 1147/1176] simplify code --- stdlib/src/array.mo | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/stdlib/src/array.mo b/stdlib/src/array.mo index 41f98374769..1e6e3c97273 100644 --- a/stdlib/src/array.mo +++ b/stdlib/src/array.mo @@ -156,10 +156,8 @@ module { public func tabulateVar(len : Nat, gen : Nat -> A) : [var A] { if (len == 0) { return [var] }; let xs = Prim.Array_init(len, gen 0); - if (len > 1) { - for (i in range(1,len-1)) { - xs[i] := gen i; - }; + for (i in range(1,len-1)) { + xs[i] := gen i; }; return xs; }; From 1f9453ce6e0a41e89482f31e1fd6547142e44fe7 Mon Sep 17 00:00:00 2001 From: DFINITY bot <58022693+dfinity-bot@users.noreply.github.com> Date: Thu, 2 Apr 2020 02:08:33 +0200 Subject: [PATCH 1148/1176] niv common: update 21396311 -> 22f5d566 (#1321) ## Changelog for common: Commits: [dfinity-lab/common@21396311...22f5d566](https://github.com/dfinity-lab/common/compare/2139631132d8206ff3a514794a5a5fd36af9c895...22f5d56616a5e75c6b7dec2d7f7f130737f72644) * [`0529e68e`](https://github.com/dfinity-lab/common/commit/0529e68e8150fdfb2f934e56a75239bb2438f6ee) mkCheckedScript: bundle arguments and patch shebangs * [`ba03ff49`](https://github.com/dfinity-lab/common/commit/ba03ff4997844fb29d7e646ee3818fef87b8bb86) mkCheckedScript: pass arguments as environment variables * [`59566344`](https://github.com/dfinity-lab/common/commit/595663448e90fce0093783b316ceba7a017595c8) Update nix/overlays/lib/default.nix * [`8e91e089`](https://github.com/dfinity-lab/common/commit/8e91e089cf657483a1b158f8ef96e122c7962b6e) mkCheckedScript: run script in test * [`036aaba7`](https://github.com/dfinity-lab/common/commit/036aaba70b65894f2dde676b4afe3d3952cb9bd3) mkCheckedScript: actually SC the wrapped script * [`c70ea78e`](https://github.com/dfinity-lab/common/commit/c70ea78e0b3725032675c5c14fef124d54e77b6d) Document how to upgrade nixpkgs --- nix/sources.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/sources.json b/nix/sources.json index 624e83db033..f321ce4b6cb 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -2,7 +2,7 @@ "common": { "ref": "master", "repo": "ssh://git@github.com/dfinity-lab/common", - "rev": "2139631132d8206ff3a514794a5a5fd36af9c895", + "rev": "22f5d56616a5e75c6b7dec2d7f7f130737f72644", "type": "git" }, "dfinity": { From d36dadc762449aba97a843c26843d935cdbaed00 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 2 Apr 2020 15:33:54 +0200 Subject: [PATCH 1149/1176] Bump drun (#1328) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit no reason besides checking that nothing broke. Changes: ``` 1bb028c22 DFN-1441 Generate reject responses for requests that cannot be routed (#3113) 61ac4eb49 State Manager adoc: some minor reformatting and restructuring (#3112) 1ff1d97f9 Set LANG=C.UTF8 before running ic-ref-test (#3121) 8315d1bc4 Remove dfinity from integration test scripts (#3120) 01b6d6623 DFN-1459: Remove Dummy Values in CspPublicCoefficients (#3047) 63c1528e5 Change common_data to public_coefficients (#3084) 2db2f5d90 Merge pull request #3115 from dfinity-lab/mockAllDkgCrypto f219f38a6 Merge pull request #3094 from dfinity-lab/dkgAdvert adb2db4bd Merge pull request #3114 from dfinity-lab/CON-348 f0b2f8118 P2P-217 Select and validate Ingress messages for block proposal with upper bound on total size (#3069) 2942a3c64 Merge pull request #3111 from dfinity-lab/update/advisory-db-ffac5aa5f277cc58331bc879f14e498dca32e0a8 2e7db738a State Manager adocs: align interface with discussion last week (#3100) a25fd7a27 Merge pull request #3109 from dfinity-lab/mw/codeowners-embedders 9261cd13d Merge pull request #3106 from dfinity-lab/update/common-036aaba70b65894f2dde676b4afe3d3952cb9bd3 20fe1fb78 Merge pull request #3038 from dfinity-lab/nm-upload-benchmarks 97104f9f5 Merge pull request #3077 from dfinity-lab/dsd/fix_metrics_inline_comment 27e82e761 Update common 9ba2ece8e EE: run hypervisor tests using both Lucet and Wasmtime (#3102) 8f5aabcd3 [ExecEnv Cleanup] Move install code into ExecutionEnvironment. fde64bdc8 DFN-1441 Introduce CertifiedStreamSlice type (#3090) 9f50cc7fa Merge pull request #3089 from dfinity-lab/update/advisory-db-81193d1dbab92e8f7816c3b504ad8627fdc3d430 33ba68522 Bump ic-ref (#3097) a5dbcaa81 Implement GossipPool for certification (#3034) 12b3f2cec Merge pull request #3095 from dfinity-lab/wasmtime_sys_api_fix e2e759d4b Merge pull request #3091 from dfinity-lab/CON-345 bfc24c426 Phantom Newtype: implement std::iter::Sum trait for AmountOf. (#3067) 25f0bda44 Bug fix for consensus resumability (#2964) ab9cac0cc Move ic-ref-test one level up (#3085) 653a2195c EE: turn all inline tests into integration tests (#3087) bc07ba7bd DFN-1441 Drop StreamStore and XNetSender/XNetReceiver. (#3071) 3d2595d55 Merge pull request #3014 from dfinity-lab/dsd/http_server 27beb50d6 INF-1160: disable a flaky test that stops PRs from being merged (#3083) f14e94660 Merge pull request #3082 from dfinity-lab/fix-contributing 3eb1fab1d Merge pull request #3072 from dfinity-lab/update/advisory-db-f37a7bf90a4ddc60db4d8105c4598d8d92afb090 81b22d806 Interfaces: drop dependency on ic-replicated-state. (#3065) a437bfe90 Merge pull request #3070 from dfinity-lab/update/advisory-db-de905c8bfed22b6bfeadd3d6ed7b411016395aed e85f81f5c Clean up test-utilities exports: don't export both the modules and the types they define. (#3068) 593d089a7 DFN-1437: Split IDKM Sign Tests (#3041) 379c7a551 DFN-1437: Add IDKM sign_threshold and Tests (#3049) bf1f261d2 MessageRouting adocs: Introduce `CertifiedStreamSlice` type (#3060) 1e0d8c282 Types: rename Batch.requires_full_{certification,state_hash} (#3062) 156b7db82 Merge pull request #3066 from dfinity-lab/update/common-d0c1d2d5e3aead1872c91663baf6d635ea020107 ea248d584 extend the Arc::clone advice, drop second part (#3018) 2abf30f52 DFN-1437: Add Mock Builder for Mockall CSP (#3043) 667d5bd0c Message Routing: Incorporate Feedback from Y-A (#3055) b6854b7ed DFN-1458: Turn CspThresholdSignatureScheme into ThresholdSignatureCspClient (#3036) 561b79fdd Change UserAuthenicationService from struct to a trait (#3051) 89e5596bb Merge pull request #3016 from dfinity-lab/dkgIntervalLengthInRegistry 1d47c7427 Merge pull request #3007 from dfinity-lab/manu/registry-versions-in-membership 43e04ab51 Merge pull request #3050 from dfinity-lab/update_component_arch 1abe1a066 [Hypervisor Cleanup] Refactor `execute_update` 6fccd63f8 Merge pull request #3045 from dfinity-lab/update/common-24be014bd63a35ef70a595048605afc0d3640c59 c1508d244 DFN-1437: Map DkgId to KeyId (#3020) 9e4b1f0f4 Replica: handle SIGINT to complete debugging actions gracefully (#3011) 059914d8e Squashed crypto/DFN-1152-clib-dkg-api from f04d6da6c118c77a9fb869b9b377926472e4d2e3 (#2998) bde3a41b2 [Hypervisor Cleanup] Refactor `execute_query` 3f8eeb614 Merge pull request #3035 from dfinity-lab/kw/log-cleanup e210e9de1 DFN-1417: Replace seed with random beacon in CSPRNG constructor (#3037) 4c51c2cae Merge pull request #2870 from dfinity-lab/johnw/wait_on_status 5a4d5939d INF-1136: Run benchmarks on Darwin 4d60a2e32 DFN-1407: Adapt crypto lib hashers to return byte arrays instead of C… (#2753) 1302e5b1a Validate that canister_(pre|post)_upgrade have proper signatures. (#3029) 39347dbce Merge pull request #3032 from dfinity-lab/nm-nix-faq 14a561c33 Always require systemFeatures=benchmark for benchmarks b5a5b0029 Merge pull request #2966 from dfinity-lab/kw/use-select 69b3f0a8b Merge pull request #3027 from dfinity-lab/update/common-d696e4ebcee16f374c0cd8377364f5c5beb23c9f 8749cdbbb Merge pull request #2915 from dfinity-lab/skaestle/add-rench-workload-generator 7761f871e CON-327: minor replica refactorings (#3024) e3e861935 Merge pull request #3025 from dfinity-lab/useDkgStartBlockToGenerateCatchUpPackage 82f7d9866 DFN-1457: Add Mockall mock crypto service provider (#3023) 26d3fccc8 Refactoring FuncRef (#3019) ff984a344 derives default where no explicit implementation seem to be necessary (#2992) ed42acd49 DFN-1437: Add ThresholdSigantureScheme to CryptoServiceProvider Trait (#3021) 482e50b0f CON-327: use real crypto in certification (#2981) a5e1afac8 use CUP height for certification artifacts purging (#3004) aa774e01c Merge pull request #3022 from dfinity-lab/update/advisory-db-a6d2cc87a2f441213f76b040140de30c6dd16a2d d7dedc304 Merge pull request #3015 from dfinity-lab/update/advisory-db-ae3627d1a9a10e926f52469a6f3a65cfef64175d 97712ae73 Merge pull request #3005 from dfinity-lab/INF-1108-reenable-doc-tests 463d84ab0 Merge pull request #2997 from dfinity-lab/dkgPoolPurger 24ca60a4c Merge pull request #2984 from dfinity-lab/integrateDkgPayloadBuilder 0b7b0b984 Merge pull request #2950 from dfinity-lab/dkgSkeleton d0d91f513 Merge pull request #2999 from dfinity-lab/hassen/fullgossip 63a1ea7ff Minor fix in checkpoint benchmark (#3009) 9bdeecaa5 DFN-1452: Add crypto error variant for missing threshold signature data (#2996) fe93045b6 Adding a dummy implementation of DKG and threshold signatures for the crypto component. (#2995) d55778467 Crypto(DFN-1152): Csp Threshold Crypto (#2941) 3b34d6d20 Merge pull request #3008 from dfinity-lab/update/advisory-db-e00d8ad965d2131d4c25bcf83248d7f804c992f0 6772fce0e Merge pull request #3006 from dfinity-lab/INF-622-enable-pr-checks-on-darwin 09ea2f164 Update ReplicateState method API (#2982) fc234cf05 Merge pull request #2889 from dfinity-lab/yap/p2p-125 a59681d1f Instrumentation: Fix some typos in comments (#3000) 87dd30a5f Implements a simple prio function for certifier (#2977) de85c41ee Merge pull request #3002 from dfinity-lab/revert-wrong-enablement-of-master-builds-on-darwin fed58b70d Merge pull request #3001 from dfinity-lab/OPS-33-make-sure-benchmark-is-run-on-linux-only b470dc260 MessageRouting: propagate Catch-Up Package height from Consensus (#2989) c5d740b26 [Hypervisor Cleanup] Add execute_system to Hypervisor's API (#2990) 08bc82be3 Create temporary file in the same directory (#2961) 416ce2bd7 Merge pull request #2927 from dfinity-lab/dkgPool 8855ce6fc Remove Default for configs with path, and make sure such paths are created properly. (#2980) 8cdc14589 Merge pull request #2994 from dfinity-lab/update/advisory-db-9d4cdd5ebda1feff43717f3fabd5837f4bd67469 32f3320f2 Merge pull request #2993 from dfinity-lab/update/advisory-db-40077b6e77b78d76df98ecfe402fd82ec8e332f5 5ed092e7c Bump ic-ref to 0.2.4 (#2991) 35e8ec7ef Squashed crypto/csp_type_conversions from da620481e582d7a2c459454bfd92f87a47ca3089 (#2975) ab5806881 Merge pull request #2988 from dfinity-lab/basvandijk/fix-eval-error-due-to-nettools 507861797 Clean up Hypervisor's interface - Part I (#2921) 8e566abf5 implements Default for AmountOf (#2986) c992029c4 Certification spec update (#2955) 65f67b543 StateManager: implement filter by certification status (#2962) cfbcbad05 Merge pull request #2985 from dfinity-lab/update/advisory-db-b7d6d4ae35bf0131aaf70006d822a86e5fdefc6e 7058e9027 DFN-1366: Add Remaining Multi-Threading Unit Tests for Crypto (#2960) a0b5ead8d Squashed crypto/public-coefficients-conversions from da6249c5fd4913ff00c19b4594f23acb7cf5f464 (#2974) 0a6b7c3e6 Remove DKG components from consensus component diagram (#2978) 35671a28a DFN-1437: Conversion for CspPublicCoefficients to AlgorithmId (#2976) f8e1c0c20 MessageRouting: update interface docs (#2979) 8f0b6c191 rs: add a job to generate a JSON file and HTML report for every benchmark 1f50d47d7 DFN-1379: Update compute allocation during canister upgrades (#2969) 9da7d6ff0 DFN-1450: Extend CryptoComponentState with DKG Cache (#2970) ecf95f838 Added Threshold Signature Data Store to the DKG specs (#2888) 67af14f99 Message routing adocs: Add some notes and missing details (#2968) 7a8affbf6 Merge pull request #2971 from dfinity-lab/update/common-32956d48089a239e8bf66ed17b38cd71ca5bf42a e39125420 Certification bugfix (#2957) a3b01fb00 DFN-1436: Add basic implementation of threshold sig data store (#2949) 8c11d4df9 First steps in implementing controllers (#2929) 2a10dcf96 CON-312: adds certifier tests (#2918) cc99d63ca Merge pull request #2965 from dfinity-lab/mw/update-wasmtime-latest abb778476 Merge pull request #2930 from dfinity-lab/kb/artifact_manager 4ae880833 Merge pull request #2958 from dfinity-lab/update/common-305dbe73ae22af77769b377d2b5eb3d519918659 655ca9aaa Merge pull request #2851 from dfinity-lab/robin-kunzler/DFN-1366/add-csp-mock-and-first-multi-threading-test 7b95dc880 CON-321 Use CatchUpPackage to trigger purge (#2917) 01f04c2ec Crypto/DFN-1444: CSP-conversions-test-coverage (#2945) bfff6ac4f Squashed crypto/DFN-1152-clib-threshold-crypto from 0749d2b6ab0e3df273720465ea6f37c11f34f931 (#2800) 17c3494df DFN-1441 Always accept XNet messages (#2943) 665e18a8a StateManager: refactor tests (#2953) fafbfacf9 Merge pull request #2939 from dfinity-lab/ielashi/canister_stopping 7343c3442 CON-327: instantiates the real crypto component in replica (#2940) ce135d582 Bump ic-ref-test to a tagged version (#2952) 3b318c90b State Manager adocs: move State Manager macros from Message Routing to State Manager (#2951) 909c6ef1b Merge pull request #2948 from dfinity-lab/mw/export-all-mutable-globals 6a18a84ca StateManager spec: kick off adoc rework (#2935) 187b8b9d2 DFN-1435: Specify trait for threshold signature data store (aka cache) (#2925) 8b9e10e2f Removing dependency of sign/tests on PublicKeyRegistryRecord. (#2836) 1ecd249f1 CON-326 Read ArtifactPoolConfig from replica config file (#2931) 2fc7e975d Merge pull request #2946 from dfinity-lab/update/advisory-db-f9beae30a94ad39458f6aecf3c434c14b877f6d9 f6ae679a7 http_handler: Implement the status endpoint (#2942) 9e063a9f4 Squashed crypto/DFN-1433-csp-threshold-keygen-api-options from ec6000124ba01f2fe6b2fbf3eba590de6e1faf40 (#2920) 0979a1d57 Run ic-ref-test against replica (#2936) 1dbfdf586 Fixed QR Code generation on a query (#2924) ef1e6f6f7 Set message routing adocs to canonical (#2932) e4ef87d91 moves common type up in the hierarchy (#2933) b8b1afa98 CON-312: tests (#2916) 0491e71a7 Handle floating point globals in Wasm embedders (#2913) 23d2eaa0f Replica: invoke default panic hook before abort (#2928) f1fc2d1bf DFN-1392 Replace StreamIndex with FlatStreamIndex (#2908) 67fe4fffb Deleted + regenerated cargo.lock (#2914) 45ba206d3 Fix broken link (#2922) cd766d542 Don't derive Eq for CanisterState (#2919) 6ee80c44f Clean up entry document (#2893) 03a58e932 DFN-1366: Verify Signatures in Multi-Threading Int-Test (#2887) bf76a7144 CON-313: artifact_pool improvements (#2869) e3867dfe0 Do not offer proposal, finalization, notarization at genesis (#2891) 0f6f6ae4e CON-315 Consensus processing of CatchUpPackage artifacts (#2874) d7b92be25 Merge pull request #2890 from dfinity-lab/CON-317 8757a8eaa rs: build rocksdb, zstd and dependencies as separate derivations c3f9839eb CON-311: verifier (#2866) 1ebf3db5d Public Spec: Moved to ic-ref (#2865) 5288fc00f Merge pull request #2912 from dfinity-lab/update/advisory-db-88461fc18fc19e794e9b2adcbca7f51bc9ab7fb4 77826cb2a Merge pull request #2904 from dfinity-lab/update/advisory-db-19196c293666c83b7322f4bd990cd3b69e93b8d2 0df85ba10 Collapse imports in system_api/lib.rs (#2910) 3a99b63ea Message routing spec: incorporate feedback from in-depth review (#2907) d5820701d Prefix CSP DKG methods and clean create_transcript (#2897) 373b38f2c DFN-463: hardlink Wasm files on snapshotting (#2906) 073af6810 CON-301: certification integration (#2858) 55a5a2335 DFN-1392 Define StreamIndexedQueue for stream messages and signals (#2842) 9ca97288f Canister web server demo + libraries (#2901) 8ec29c7e8 Remove myself from docs notifications (#2902) f0cf628fe Adapt DKG API types to latest DKG specification (#2853) 41acc50ea ## Commit Message (#2903) 63ac87e72 Remove ic-orthogonal-persistence crate (#2899) 796a9db48 Drop 7 dependencies (2 duplicate versions), add 1, bumping some versions in the process. (#2898) 37e4f6b0d DFN-1366: Add Separate Modules for Sign Trait Implementations (#2834) 6c8c1fff1 [canister_install_handler]: Collapse imports from the same crate (#2900) c5b86f322 Remove mod.rs in embedders crate (#2895) e0cca3d21 After e5fc05b60a610ab94ba06642a8fa61f73732d685 we can have up to 10 84eb3487f Dont recompile tests (#2868) 45509e653 CON-153: Simplify HeightIndex implementation (#2886) 715934078 Message routing spec: intuitive description of inner workings of XNetTransfer (#2877) b2f1fe194 Replica: abort the process if one thread panics (#2885) 1931ec182 CON-300: purger (#2845) 9501e744f Merge pull request #2878 from dfinity-lab/dsd/remove_hypervisor_adoc 68c611a3c Update code owner for consensus type subdir (#2875) 7ffeacd7c Merge pull request #2882 from dfinity-lab/dsd/log_analyzer_doc_update 70c202db5 Move tests for inter canister messages in execution environment (#2880) 68e8cfca5 Demonstrate how prost-build is used to convert .proto to .rs (#2844) b8f256693 Remove obsolete `mut` in RegistryWriter and RegistryExtender API (#2864) f58620455 Remove more slog-scope usages (#2862) 3daecd8e2 Merge pull request #2879 from dfinity-lab/dsd/remove_unnecessary_dead_code 138fbd88f OPS-22: Copy SVG and JPEG images to the output directory (#2883) e74042b59 Merge pull request #2881 from dfinity-lab/dsd/rename_env_rs 84e2d87f7 Merge pull request #2873 from dfinity-lab/update-niv-updater-action 7e2ce704c CON-300: aggregate refactoring (#2818) 5c19a6b7d CON-300: consolidates registry version retrieval (#2817) e3255acde Update dependencies, re-run benchmarks (#2785) 0962246f6 Replace deprecated crate tempdir (#2830) 440c44c43 Merge pull request #2849 from dfinity-lab/johnw/analyzer ce1684a9c Drop unnecessary tokio-net alpha dependency. This gets rid of ~15 crates. (#2831) d4f0633cf Align spec with state manager interface in code (#2867) af7f5e4f8 Merge pull request #2741 from dfinity-lab/david/emulator 3daf13029 Remove fake functions from consensus types (#2860) f32768b88 Set maxfiles ulimit to 8192 (#2856) 2eac9f3f7 Crypto/DFN-1273: CSP threshold api (#2813) eb6e71e05 Merge pull request #2824 from dfinity-lab/update/common-7fbbf97c57eaa2c13eee6d958f494d800edb2b20 8a80dba0d Add the RandomTapeMaker to consensus (#2746) 3731f1135 Merge pull request #2861 from dfinity-lab/paulliu/get-state-hash-at 4cdcf075e Drop or demote udeps-detected unused dependencies (#2832) bb7ac9f28 Merge pull request #2788 from dfinity-lab/hassen/hotgossip 317c5a3de Message routing spec: section on canister migration (#2852) 08edbd225 Fix typo in principal_id.rs (#2863) 7d6cab9eb Squashed crypto/DFN-1380-256-bit-key-id from efdd6032e846791824e2f8c81a83e111331ce2c3 (#2848) 5a82c455a Merge pull request #2841 from dfinity-lab/skaestle/fix-bench f4178d391 Public Spec: Upgrades and `mode` field are implemented now (#2837) 55c40607c Remove any mod.rs files from test_utilities (#2855) 15c92262c adocs: Cleanup documentation tree and archive unmaintained documents (#2799) 963c91814 P2P-159: Initial implementation of Retransmission request (#2773) 430860376 Merge pull request #2859 from dfinity-lab/fs/slowstartfix afc3ffb23 Merge pull request #2826 from dfinity-lab/fs/processtests 4edaa283d Dependency cleanup (#2829) ba42ba985 Add a section to README.adoc: "If a PR needs quick approval" (#2516) c64229321 Public Spec: Some editorial changes (#2835) efb431b7a Remove any mod.rs files from message routing (#2854) bbb0a021e Make ExecutionState optional in CanisterState (#2759) d7776dc64 Message routing spec: editorial changes (#2846) 79b939ecc DFN-1366: Add Module for KeygenInternal (#2819) 3fa889a74 Split DKG in IDKM and CSP (#2607) f49b7e858 CON-309: Remove an ingress message from Validated IngressPool if it has been executed (#2807) 6c063f231 Merge pull request #2843 from dfinity-lab/dsd/hypervisor/clear_postconditions de8fae8f3 Merge pull request #2809 from dfinity-lab/robin-kunzler/DFN-1366/introduce-csp-trait 7acd4416e Implement a benchmark for msgpack (#2780) 4e86a85e4 Merge pull request #2839 from dfinity-lab/dsd/read_node_id_from_logger_config 6df41a205 Merge pull request #2833 from dfinity-lab/basvandijk/remove-base-input 5a2949921 Message routing spec: note on reservations (#2812) 8d78259fc Drop cranelift dependency in ic_embedders (#2828) 9de3d4493 Update example to work with new version of Rust compiler. 820ace601 Merge pull request #2823 from dfinity-lab/update/common-79a7acd25142e621854d787d5bcfe375af4712f8 930a65462 HTTP Handler: QueryResponse::Empty should map to empty CBOR map (#2820) 805d392b3 ## Changelog for common: (#2816) ``` --- nix/sources.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/sources.json b/nix/sources.json index f321ce4b6cb..e58b39ddde7 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -8,7 +8,7 @@ "dfinity": { "ref": "master", "repo": "ssh://git@github.com/dfinity-lab/dfinity", - "rev": "9f947598f82d7782a3da4e6c0cf8a7b3ac6d5947", + "rev": "1bb028c22ce4efb669555cba46bec91f9e6cca0e", "type": "git" }, "esm": { From f882198eff4de837c51fe751d61ed20b162bb5c5 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 2 Apr 2020 15:55:03 +0200 Subject: [PATCH 1150/1176] tests/perf: Include the QR in tests/perf (#1326) This is a snapshot of https://github.com/enzoh/qr at revision 3d4537cba3418f28a0b3ed53fe4485bbce3d10f8 with the following changes: * copied all files to qr/ * copied relevant files from stdlib to qr/ * updates imports accordingly * added a go() method to the canister with some test data Fixes #1323 Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- test/perf/ok/qr.drun-run.ok | 78 ++ test/perf/qr.mo | 96 +++ test/perf/qr/alphanumeric.mo | 121 +++ test/perf/qr/array.mo | 164 ++++ test/perf/qr/assocList.mo | 235 ++++++ test/perf/qr/block.mo | 151 ++++ test/perf/qr/char.mo | 12 + test/perf/qr/common.mo | 291 +++++++ test/perf/qr/eight-bit.mo | 23 + test/perf/qr/format.mo | 27 + test/perf/qr/galois.mo | 295 +++++++ test/perf/qr/generic.mo | 36 + test/perf/qr/hash.mo | 111 +++ test/perf/qr/iter.mo | 105 +++ test/perf/qr/kanji.mo | 23 + test/perf/qr/list.mo | 539 +++++++++++++ test/perf/qr/mask.mo | 80 ++ test/perf/qr/nat.mo | 100 +++ test/perf/qr/numeric.mo | 91 +++ test/perf/qr/option.mo | 139 ++++ test/perf/qr/prelude.mo | 62 ++ test/perf/qr/symbol.mo | 423 ++++++++++ test/perf/qr/text.mo | 24 + test/perf/qr/trie.mo | 1472 ++++++++++++++++++++++++++++++++++ test/perf/qr/util.mo | 33 + test/perf/qr/version.mo | 37 + 26 files changed, 4768 insertions(+) create mode 100644 test/perf/ok/qr.drun-run.ok create mode 100644 test/perf/qr.mo create mode 100644 test/perf/qr/alphanumeric.mo create mode 100644 test/perf/qr/array.mo create mode 100644 test/perf/qr/assocList.mo create mode 100644 test/perf/qr/block.mo create mode 100644 test/perf/qr/char.mo create mode 100644 test/perf/qr/common.mo create mode 100644 test/perf/qr/eight-bit.mo create mode 100644 test/perf/qr/format.mo create mode 100644 test/perf/qr/galois.mo create mode 100644 test/perf/qr/generic.mo create mode 100644 test/perf/qr/hash.mo create mode 100644 test/perf/qr/iter.mo create mode 100644 test/perf/qr/kanji.mo create mode 100644 test/perf/qr/list.mo create mode 100644 test/perf/qr/mask.mo create mode 100644 test/perf/qr/nat.mo create mode 100644 test/perf/qr/numeric.mo create mode 100644 test/perf/qr/option.mo create mode 100644 test/perf/qr/prelude.mo create mode 100644 test/perf/qr/symbol.mo create mode 100644 test/perf/qr/text.mo create mode 100644 test/perf/qr/trie.mo create mode 100644 test/perf/qr/util.mo create mode 100644 test/perf/qr/version.mo diff --git a/test/perf/ok/qr.drun-run.ok b/test/perf/ok/qr.drun-run.ok new file mode 100644 index 00000000000..79c42ce3c18 --- /dev/null +++ b/test/perf/ok/qr.drun-run.ok @@ -0,0 +1,78 @@ +ingress System +debug.print: +############## #### #### ############## +## ## ## ## ## ## +## ###### ## #### ## ## ###### ## +## ###### ## #### ## ###### ## +## ###### ## #### ## ###### ## +## ## #### ## ## +############## ## ## ## ############## + #### +## #### ###### ## ## ## #### + ## ## #### ## ## ## #### +## ## ######## ########## ## +#### ## ## ## #### ## ## + ############ ## ## ## + ###### ## ## ## +############## ## #### ## #### +## ## ## ########## ## ## +## ###### ## ## ## ## ## +## ###### ## ## ## ## ## #### +## ###### ## ## #### ## ## ## +## ## ## #### ## #### #### +############## ## #### ## ## + + +debug.print: +############## ## ############## +## ## #### ## ## ## +## ###### ## ## ## ## ###### ## +## ###### ## #### ## ###### ## +## ###### ## #### ## ###### ## +## ## ## ## ## ## +############## ## ## ## ############## + ## + ###### #### #### +## ## ######## #### ########## +## ###### #### ## #### ## ## + ###### ## ## ## ## #### +## #### ## ## #### ## + ## ## ## ## #### +############## ## ######## ## #### +## ## #### ###### #### +## ###### ## #### #### #### +## ###### ## ## ## ## #### ## +## ###### ## ######## ## #### +## ## ########## #### ## +############## #### ## #### + + +debug.print: +############## ######## ## ## ############## +## ## ## ## #### ## ## +## ###### ## #### ## ## ###### ## +## ###### ## ######## #### ## ###### ## +## ###### ## ## ## ## ## ###### ## +## ## ######## ## ## ## +############## ## ## ## ## ## ############## + ## #### +## #### ###### ## ## ## #### +######## ########## ######## ## + ## ######## ########## ## ## ###### + ## #### ###### ## ######## ## + #### #### ###### ###### ## + ## ## ## ## #### ## ###### ## #### + ## ## ###### ## ## ## +## ## ## ## #### #### ## #### + ## ## ## ## #################### + ###### ## ## #### #### +############## ## ######## ## ## +## ## ## #### ######## ###### ## +## ###### ## #### #### ############## ## +## ###### ## ## ## ## #### ## +## ###### ## ## ## ###### ###### ## +## ## ## ########## ## ## ## +############## ######## ## ## ## ## + + +ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/perf/qr.mo b/test/perf/qr.mo new file mode 100644 index 00000000000..0337892c71d --- /dev/null +++ b/test/perf/qr.mo @@ -0,0 +1,96 @@ +/* +This is a snapshot of https://github.com/enzoh/qr +at revision 3d4537cba3418f28a0b3ed53fe4485bbce3d10f8 +with the following changes: + * copied all files to qr/ + * copied relevant files from stdlib to qr/ + * updates imports accordingly + * added a go() method to the canister with some test data + +*/ + + +/** + * Module : qr.mo + * Copyright : 2020 DFINITY Stiftung + * License : Apache 2.0 with LLVM Exception + * Maintainer : Enzo Haussecker + * Stability : Stable + */ + +import Array "./qr/array"; +import Block "./qr/block"; +import Common "./qr/common"; +import Generic "./qr/generic"; +import List "./qr/list"; +import Mask "./qr/mask"; +import Option "./qr/option"; +import Symbol "./qr/symbol"; +import Version "./qr/version"; +import Prelude "./qr/prelude"; + +actor QR { + + type List = List.List; + + public type ErrorCorrection = Common.ErrorCorrection; + public type Matrix = Common.Matrix; + public type Mode = Common.Mode; + public type Version = Version.Version; + + public func encode( + version : Version, + level : ErrorCorrection, + mode : Mode, + text : Text + ) : async ?Matrix { + Option.bind( + Version.new(Version.unbox(version)), + func _ { + Option.bind, Matrix>( + Generic.encode(version, mode, text), + func (data) { + Option.bind, Matrix>( + Block.interleave(version, level, data), + func (code) { + let (arrays, maskRef) = Mask.generate(version, level, code); + ?#Matrix ( + Symbol.freeze( + Symbol.applyVersions(version, + Symbol.applyFormats(version, level, maskRef, arrays))) + ) + } + ) + } + ) + } + ) + }; + + public func show(matrix : Matrix) : async Text { + let #Matrix arrays = matrix; + Array.foldl<[Bool], Text>(func (accum1, array) { + Array.foldl(func (accum2, bit) { + let text = if bit "##" else " "; + text # accum2 + }, "\n", array) # accum1 + }, "", arrays) + }; + + public func go() { + let tests = [ + (#Version 1, #M, #Numeric, "01234567"), + (#Version 1, #Q, #Alphanumeric, "HELLO WORLD"), + (#Version 2, #M, #Alphanumeric, "HTTPS://SDK.DFINITY.ORG"), + ]; + for ((version, level, mode, text) in tests.vals()) { + let result = await QR.encode(version, level, mode, text); + Prelude.printLn(switch result { + case (?matrix) "\n" # (await QR.show(matrix)); + case _ "Error: Invalid input!"; + }) + }; + }; +} + +//CALL ingress go 0x4449444C0000 diff --git a/test/perf/qr/alphanumeric.mo b/test/perf/qr/alphanumeric.mo new file mode 100644 index 00000000000..9bc8da22098 --- /dev/null +++ b/test/perf/qr/alphanumeric.mo @@ -0,0 +1,121 @@ +/** + * Module : alphanumeric.mo + * Copyright : 2020 DFINITY Stiftung + * License : Apache 2.0 with LLVM Exception + * Maintainer : Enzo Haussecker + * Stability : Stable + */ + +import Array "array"; +import Common "common"; +import Iter "iter"; +import List "list"; +import Nat "nat"; +import Option "option"; +import Prelude "prelude"; +import Prim "mo:prim"; +import Text "text"; +import Trie "trie"; +import Util "util"; +import Version "version"; + +module { + + type List = List.List; + type Trie = Trie.Trie; + type Version = Version.Version; + + public func encode(version : Version, text : Text) : ?List { + + let mi = List.fromArray([false, false, true, false]); + let cci = Util.padLeftTo( + Common.cciLen(version, #Alphanumeric), + Nat.natToBits(text.len()) + ); + + func format(body : List) : List { + let header = List.append(mi, cci); + let footer = List.replicate(4, false); + List.append(header, List.append(body, footer)) + }; + + let table = genTable(); + let transliteration = List.foldRight>( + Iter.toList(Text.toIter(text)), + ?List.nil(), + func (char, accum) { + Option.bind, List>( + accum, + func (values) { + Option.map>( + func (value) { + List.push(value, values) + }, + Trie.find(table, keyChar(char), eqChar) + ) + } + ) + } + ); + + Option.map, List>( + format, + Option.map, List>( + func (values) { + List.foldRight, List>( + List.chunksOf(2, values), + List.nil(), + func (chunk, accum) { + List.append(encodeChunkOrTrap(chunk), accum) + } + ) + }, + transliteration + ) + ) + }; + + func genTable() : Trie { + let chars = [ + '0', '1', '2', '3', '4', '5', '6', '7', '8', + '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', + 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + ' ', '$', '%', '*', '+', '-', '.', '/', ':' + ]; + Array.foldl, Nat)>( + func (accum, char) { + let table = Trie.insert( + accum.0, + keyChar(char), + eqChar, + accum.1 + ).0; + let i = accum.1 + 1; + (table, i) + }, + (Trie.empty(), 0), + chars + ).0 + }; + + func keyChar(char : Char) : Trie.Key { + { key = char; hash = Prim.charToWord32(char) }; + }; + + func eqChar(a : Char, b : Char) : Bool { + a == b + }; + + func encodeChunkOrTrap(chunk : List) : List { + switch chunk { + case (?(x, null)) Util.padLeftTo(6, Nat.natToBits(x)); + case (?(x, ?(y, null))) Util.padLeftTo(11, Nat.natToBits(x * 45 + y)); + case _ { + Prelude.printLn("Error: Invalid chunk size!"); + Prelude.unreachable(); + } + } + }; + +} diff --git a/test/perf/qr/array.mo b/test/perf/qr/array.mo new file mode 100644 index 00000000000..e8443b834b9 --- /dev/null +++ b/test/perf/qr/array.mo @@ -0,0 +1,164 @@ +/** +[#mod-Array] += `Array` -- Arrays +*/ + +import Prim "mo:prim"; +module { + public func equals(a : [A], b : [A], eq : (A,A) -> Bool) : Bool { + if (a.len() != b.len()) { + return false; + }; + var i = 0; + while (i < a.len()) { + if (not eq(a[i],b[i])) { + return false; + }; + i += 1; + }; + return true; + }; + + public func append(xs : [A], ys : [A]) : [A] { + switch(xs.len(), ys.len()) { + case (0, 0) { []; }; + case (0, _) { ys; }; + case (_, 0) { xs; }; + case (xsLen, ysLen) { + Prim.Array_tabulate(xsLen + ysLen, func (i : Nat) : A { + if (i < xsLen) { + xs[i]; + } else { + ys[i - xsLen]; + }; + }); + }; + }; + }; + + public func apply(fs : [A -> B], xs : [A]) : [B] { + var ys : [B] = []; + for (f in fs.vals()) { + ys := append(ys, map(f, xs)); + }; + ys; + }; + + public func bind(xs : [A], f : A -> [B]) : [B] { + var ys : [B] = []; + for (i in xs.keys()) { + ys := append(ys, f(xs[i])); + }; + ys; + }; + + public func enumerate(xs : [A]) : [(A, Nat)] { + Prim.Array_tabulate<(A, Nat)>(xs.len(), func (i : Nat) : (A, Nat) { + (xs[i], i); + }); + }; + + public func filter(f : A -> Bool, xs : [A]) : [A] { + var ys : [A] = []; + for (x in xs.vals()) { + if (f(x)) { + ys := append(ys, [x]); + }; + }; + ys; + }; + + public func foldl(f : (B, A) -> B, initial : B, xs : [A]) : B { + var acc = initial; + let len = xs.len(); + var i = 0; + while (i < len) { + acc := f(acc, xs[i]); + i += 1; + }; + acc; + }; + + public func foldr(f : (A, B) -> B, initial : B, xs : [A]) : B { + var acc = initial; + let len = xs.len(); + var i = len; + while (i > 0) { + i -= 1; + acc := f(xs[i], acc); + }; + acc; + }; + + public func find(f : A -> Bool, xs : [A]) : ?A { + for (x in xs.vals()) { + if (f(x)) { + return ?x; + } + }; + return null; + }; + + public func freeze(xs : [var A]) : [A] { + Prim.Array_tabulate(xs.len(), func (i : Nat) : A { + xs[i]; + }); + }; + + public func join(xs : [[A]]) : [A] { + bind<[A], A>(xs, func (x : [A]) : [A] { + x; + }); + }; + + public func map(f : A -> B, xs : [A]) : [B] { + Prim.Array_tabulate(xs.len(), func (i : Nat) : B { + f(xs[i]); + }); + }; + + public func mapWithIndex(f : (A, Nat) -> B, xs : [A]) : [B] { + Prim.Array_tabulate(xs.len(), func (i : Nat) : B { + f(xs[i], i); + }); + }; + + public func pure(x: A) : [A] { + [x]; + }; + + public func thaw(xs : [A]) : [var A] { + let xsLen = xs.len(); + if (xsLen == 0) { + return [var]; + }; + let ys = Prim.Array_init(xsLen, xs[0]); + for (i in ys.keys()) { + ys[i] := xs[i]; + }; + ys; + }; + + public func init(len : Nat, x : A) : [var A] { + Prim.Array_init(len, x); + }; + + public func tabulate(len : Nat, gen : Nat -> A) : [A] { + Prim.Array_tabulate(len, gen); + }; + + // copy from iter.mo, but iter depends on array + class range(x : Nat, y : Nat) { + var i = x; + public func next() : ?Nat { if (i > y) null else {let j = i; i += 1; ?j} }; + }; + + public func tabulateVar(len : Nat, gen : Nat -> A) : [var A] { + if (len == 0) { return [var] }; + let xs = Prim.Array_init(len, gen 0); + for (i in range(1,len-1)) { + xs[i] := gen i; + }; + return xs; + }; +} diff --git a/test/perf/qr/assocList.mo b/test/perf/qr/assocList.mo new file mode 100644 index 00000000000..86efc33a436 --- /dev/null +++ b/test/perf/qr/assocList.mo @@ -0,0 +1,235 @@ +/** +[#mod-AssocList] += `AssocList` -- Association lists +*/ + +import List "list"; + +module { +/* + +Association Lists +================== + +Association Lists, a la functional programming, in Motoko. + +Implements the same interface as `Trie`, but as a linked-list of key-value pairs. + +*/ + +// polymorphic association linked lists between keys and values +public type AssocList = List.List<(K,V)>; + + /* + `find` + -------- + find the value associated with a given key, or null if absent. + */ + public func find(al : AssocList, + k:K, + k_eq:(K,K)->Bool) + : ?V + { + func rec(al:AssocList) : ?V { + label profile_assocList_find_rec : (?V) + switch (al) { + case (null) { label profile_assocList_find_end_fail : (?V) null }; + case (?((hd_k, hd_v), tl)) { + if (k_eq(k, hd_k)) { + label profile_assocList_find_end_success : (?V) + ?hd_v + } else { + rec(tl) + } + }; + }}; + label profile_assocList_find_begin : (?V) + rec(al) + }; + + /* + `replace` + --------- + replace the value associated with a given key, or add it, if missing. + returns old value, or null, if no prior value existed. + */ + public func replace(al : AssocList, + k:K, + k_eq:(K,K)->Bool, + ov: ?V) + : (AssocList, ?V) + { + func rec(al:AssocList) : (AssocList, ?V) { + switch (al) { + case (null) { + switch ov { + case (null) (null, null); + case (?v) (?((k, v), null), null); + } + }; + case (?((hd_k, hd_v), tl)) { + if (k_eq(k, hd_k)) { + // if value is null, remove the key; otherwise, replace key's old value + // return old value + switch ov { + case (null) (tl, ?hd_v); + case (?v) (?((hd_k, v), tl), ?hd_v); + } + } else { + let (tl2, old_v) = rec(tl); + (?((hd_k, hd_v), tl2), old_v) + } + }; + }}; + rec(al) + }; + + /* + `diff` + --------- + The key-value pairs of the final list consist of those pairs of + the left list whose keys are not present in the right list; the + values of the right list are irrelevant. + */ + public func diff(al1: AssocList, + al2: AssocList, + keq: (K,K)->Bool) + : AssocList + { + func rec(al1:AssocList) : AssocList = { + switch al1 { + case (null) null; + case (?((k, v1), tl)) { + switch (find(al2, k, keq)) { + case (null) { rec(tl)}; + case (?v2) { ?((k, v1), rec(tl)) }; + } + }; + } + }; + rec(al1) + }; + + /* + `mapAppend` + -------- + */ + public func mapAppend(al1:AssocList, + al2:AssocList, + vbin:(?V,?W)->X) + : AssocList = label profile_assocList_mapAppend : AssocList + { + func rec(al1:AssocList, + al2:AssocList) : AssocList = label profile_assocList_mapAppend_rec : AssocList { + switch (al1, al2) { + case (null, null) null; + case (?((k,v),al1_), _ ) ?((k, vbin(?v, null)), rec(al1_, al2 )); + case (null, ?((k,v),al2_)) ?((k, vbin(null, ?v)), rec(null, al2_)); + } + }; + rec(al1, al2) + }; + + public func disjDisjoint(al1:AssocList, + al2:AssocList, + vbin:(?V,?W)->X) + : AssocList = label profile_assocList_disjDisjoint : AssocList + { + mapAppend(al1, al2, vbin) + }; + + /* + `disj` + -------- + This operation generalizes the notion of "set union" to finite maps. + Produces a "disjunctive image" of the two lists, where the values of + matching keys are combined with the given binary operator. + + For unmatched key-value pairs, the operator is still applied to + create the value in the image. To accomodate these various + situations, the operator accepts optional values, but is never + applied to (null, null). + + */ + public func disj(al1:AssocList, + al2:AssocList, + keq:(K,K)->Bool, + vbin:(?V,?W)->X) + : AssocList + { + func rec1(al1:AssocList) : AssocList = { + switch al1 { + case (null) { + func rec2(al2:AssocList) : AssocList = { + switch al2 { + case (null) null; + case (?((k, v2), tl)) { + switch (find(al1, k, keq)) { + case (null) { ?((k, vbin(null, ?v2)), rec2(tl)) }; + case (?v1) { ?((k, vbin(?v1, ?v2)), rec2(tl)) }; + } + }; + } + }; + rec2(al2) + }; + case (?((k, v1), tl)) { + switch (find(al2, k, keq)) { + case (null) { ?((k, vbin(?v1, null)), rec1(tl)) }; + case (?v2) { /* handled above */ rec1(tl) }; + } + }; + } + }; + rec1(al1) + }; + + /* + `join` + --------- + This operation generalizes the notion of "set intersection" to + finite maps. Produces a "conjuctive image" of the two lists, where + the values of matching keys are combined with the given binary + operator, and unmatched key-value pairs are not present in the output. + + */ + public func join(al1 : AssocList, + al2:AssocList, + keq:(K,K)->Bool, + vbin:(V,W)->X) + : AssocList + { + func rec(al1:AssocList) : AssocList = { + switch al1 { + case (null) { null }; + case (?((k, v1), tl)) { + switch (find(al2, k, keq)) { + case (null) { rec(tl) }; + case (?v2) { ?((k, vbin(v1, v2)), rec(tl)) }; + } + }; + } + }; + rec(al1) + }; + + + /* + `fold` + --------- + */ + public func fold(al:AssocList, + nil:X, + cons:(K,V,X)->X) + : X + { + func rec(al:AssocList) : X = { + switch al { + case null nil; + case (?((k,v),t)) { cons(k, v, rec(t)) }; + } + }; + rec(al) + }; + +} diff --git a/test/perf/qr/block.mo b/test/perf/qr/block.mo new file mode 100644 index 00000000000..636ea324ba2 --- /dev/null +++ b/test/perf/qr/block.mo @@ -0,0 +1,151 @@ +/** + * Module : block.mo + * Copyright : 2020 DFINITY Stiftung + * License : Apache 2.0 with LLVM Exception + * Maintainer : Enzo Haussecker + * Stability : Stable + */ + +import Common "common"; +import Galois "galois"; +import List "list"; +import Nat "nat"; +import Option "option"; +import Version "version"; + +module { + + type Block = List; + type Blocks = List; + type Codewords = List>; + type Elem = Galois.Elem; + type ErrorCorrection = Common.ErrorCorrection; + type List = List.List; + type Version = Version.Version; + + public func interleave( + version : Version, + level : ErrorCorrection, + data : List + ) : ?List { + Option.map>(func (blocks) { + + // Calculate the codewords for each data block, as well as the + // corresponding error correction codewords. + let (blockCodewords, errorCodewords) = + List.foldRight, List)>( + blocks, + (List.nil(), List.nil()), + func (block, accum) { + let a = List.chunksOf(8, block); + let b = List.chunksOf(8, correction(version, level, block)); + ( List.push(a, accum.0), + List.push(b, accum.1) + ) + } + ); + + List.concat(List.fromArray>([ + flatten(blockCodewords), + flatten(errorCodewords), + List.replicate(Common.remainder(version), false) + ])) + + }, toBlocks(version, level, data)) + }; + + func toBlocks( + version : Version, + level : ErrorCorrection, + data : List + ) : ?Blocks { + Option.map, Blocks>(func (target) { + + func go( + accum : Blocks, + chunks : List>, + sizes : List + ) : Blocks { + switch sizes { + case (null) List.rev(accum); + case (?(h, t)) { + let (a, b) = List.splitAt>(h, chunks); + go(List.push(List.concat(a), accum), b, t) + } + } + }; + + go( + List.nil(), + List.chunksOf(8, target), + List.fromArray(Common.blockSizes(version, level)) + ) + + }, toTarget(version, level, data)) + }; + + func toTarget( + version : Version, + level : ErrorCorrection, + data : List + ) : ?List { + + let dataSize = List.len(data); + let targetSize = Common.targetSize(version, level); + if (dataSize > targetSize) null else { + + let zeroPadSize = + if (dataSize + 7 > targetSize) { + targetSize - dataSize + } else { + 8 - dataSize % 8 + }; + let zeroPad = List.replicate(zeroPadSize, false); + + var fillPadSize = targetSize - dataSize - zeroPadSize; + var fillPad = List.nil(); + while (fillPadSize > 0) { + let chunk = List.take(Nat.natToBits(60433), fillPadSize); + fillPadSize -= List.len(chunk); + fillPad := List.append(fillPad, chunk); + }; + + ?List.append(data, List.append(zeroPad, fillPad)) + } + }; + + func correction( + version : Version, + level : ErrorCorrection, + data : List + ) : List { + let chunksIn = List.chunksOf(8, data); + let elemsIn = List.map, Elem>(chunksIn, Galois.elemFromBits); + let errorSize = Common.errorSize(version, level); + let errorPoly = Common.errorPoly(version, level); + let dataPoly = Galois.polyPadRight(errorSize, { unbox = elemsIn }); + let resultPoly = Galois.polyDivMod(dataPoly, errorPoly).1; + let elemsOut = Galois.polyTrim(resultPoly).unbox; + let chunksOut = List.map>(elemsOut, Galois.elemToBits); + List.concat(chunksOut) + }; + + func flatten(data : List) : List { + func go(xss : List>, accum : List) : List { + switch (List.pop>(xss)) { + case (null, _) List.rev(accum); + case (?h1, t1) { + switch (List.pop(h1)) { + case (null, _) go(t1, accum); + case (?h2, t2) go( + List.append>(t1, List.singleton>(t2)), + List.push(h2, accum) + ) + } + } + } + }; + List.concat(go>(data, List.nil>())) + }; + +} diff --git a/test/perf/qr/char.mo b/test/perf/qr/char.mo new file mode 100644 index 00000000000..cd63816f8d3 --- /dev/null +++ b/test/perf/qr/char.mo @@ -0,0 +1,12 @@ +/** +[#mod-Char] += `Char` -- Characters +*/ + +import Prim "mo:prim"; +module { + public let isDigit : Char -> Bool = func(char) { + Prim.charToWord32(char) - Prim.charToWord32('0') <= (9 : Word32) + }; + +} diff --git a/test/perf/qr/common.mo b/test/perf/qr/common.mo new file mode 100644 index 00000000000..85110026716 --- /dev/null +++ b/test/perf/qr/common.mo @@ -0,0 +1,291 @@ +/** + * Module : common.mo + * Copyright : 2020 DFINITY Stiftung + * License : Apache 2.0 with LLVM Exception + * Maintainer : Enzo Haussecker + * Stability : stable + */ + +import Array "array"; +import Galois "galois"; +import List "list"; +import Prelude "prelude"; +import Version "version"; + +module { + + type List = List.List; + type Poly = Galois.Poly; + type Version = Version.Version; + + public type ErrorCorrection = { #L; #M; #Q; #H }; + public type Matrix = { #Matrix : [[Bool]] }; + public type Mode = { #Alphanumeric; #EightBit; #Kanji; #Numeric }; + + public func alignments(version : Version) : [Nat] { + [ + [], + [6,18], + [6,22], + [6,26], + [6,30], + [6,34], + [6,22,38], + [6,24,42], + [6,26,46], + [6,28,50], + [6,30,54], + [6,32,58], + [6,34,62], + [6,26,46,66], + [6,26,48,70], + [6,26,50,74], + [6,30,54,78], + [6,30,56,82], + [6,30,58,86], + [6,34,62,90], + [6,28,50,72,94], + [6,26,50,74,98], + [6,30,54,78,102], + [6,28,54,80,106], + [6,32,58,84,110], + [6,30,58,86,114], + [6,34,62,90,118], + [6,26,50,74,98,122], + [6,30,54,78,102,126], + [6,26,52,78,104,130], + [6,30,56,82,108,134], + [6,34,60,86,112,138], + [6,30,58,86,114,142], + [6,34,62,90,118,146], + [6,30,54,78,102,126,150], + [6,24,50,76,102,128,154], + [6,28,54,80,106,132,158], + [6,32,58,84,110,136,162], + [6,26,54,82,110,138,166] + ][Version.unbox(version) - 1] + }; + + public func remainder(version : Version) : Nat { + [ + 0, 7, 7, 7, 7, 7, 0, 0, 0, 0, + 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, + 3, 3, 3, 3, 0, 0, 0, 0, 0, 0 + ][Version.unbox(version) - 1] + }; + + public func width(version : Version) : Nat { + [ + 021, 025, 029, 033, 037, 041, 045, 049, 053, 057, + 061, 065, 069, 073, 077, 081, 085, 089, 093, 097, + 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, + 141, 145, 149, 153, 157, 161, 165, 169, 173, 177 + ][Version.unbox(version) - 1] + }; + + func match( + version : Version, + level : ErrorCorrection, + table : [X] + ) : X { + let i = Version.unbox(version) - 1; + let j = switch level { + case (#L) 0; + case (#M) 1; + case (#Q) 2; + case (#H) 3 + }; + table[4 * i + j] + }; + + public func targetSize(version : Version, level : ErrorCorrection) : Nat { + let table = [ + 00152, 00128, 00104, 00072, + 00272, 00224, 00176, 00128, + 00440, 00352, 00272, 00208, + 00640, 00512, 00384, 00288, + 00864, 00688, 00496, 00368, + 01088, 00864, 00608, 00480, + 01248, 00992, 00704, 00528, + 01552, 01232, 00880, 00688, + 01856, 01456, 01056, 00800, + 02192, 01728, 01232, 00976, + 02592, 02032, 01440, 01120, + 02960, 02320, 01648, 01264, + 03424, 02672, 01952, 01440, + 03688, 02920, 02088, 01576, + 04184, 03320, 02360, 01784, + 04712, 03624, 02600, 02024, + 05176, 04056, 02936, 02264, + 05768, 04504, 03176, 02504, + 06360, 05016, 03560, 02728, + 06888, 05352, 03880, 03080, + 07456, 05712, 04096, 03248, + 08048, 06256, 04544, 03536, + 08752, 06880, 04912, 03712, + 09392, 07312, 05312, 04112, + 10208, 08000, 05744, 04304, + 10960, 08496, 06032, 04768, + 11744, 09024, 06464, 05024, + 12248, 09544, 06968, 05288, + 13048, 10136, 07288, 05608, + 13880, 10984, 07880, 05960, + 14744, 11640, 08264, 06344, + 15640, 12328, 08920, 06760, + 16568, 13048, 09368, 07208, + 17528, 13800, 09848, 07688, + 18448, 14496, 10288, 07888, + 19472, 15312, 10832, 08432, + 20528, 15936, 11408, 08768, + 21616, 16816, 12016, 09136, + 22496, 17728, 12656, 09776, + 23648, 18672, 13328, 10208 + ]; + match(version, level, table) + }; + + public func blockSizes(version : Version, level : ErrorCorrection) : [Nat] { + let table = [ + [19], [16], [13], [9], + [34], [28], [22], [16], + [55], [44], [17,17], [13,13], + [80], [32,32], [24,24], [9,9,9,9], + [108], [43,43], [15,15,16,16], [11,11,12,12], + [68,68], [27,27,27,27], [19,19,19,19], [15,15,15,15], + [78,78], [31,31,31,31], [14,14,15,15,15,15], [13,13,13,13,14], + [97,97], [38,38,39,39], [18,18,18,18,19,19], [14,14,14,14,15,15], + [116,116], [36,36,36,37,37], [16,16,16,16,17,17,17,17], [12,12,12,12,13,13,13,13], + [68,68,69,69], [43,43,43,43,44], [19,19,19,19,19,19,20,20], [15,15,15,15,15,15,16,16], + [81,81,81,81], [50,51,51,51,51], [22,22,22,22,23,23,23,23], [12,12,12,13,13,13,13,13,13,13,13], + [92,92,93,93], [36,36,36,36,36,36,37,37], [20,20,20,20,21,21,21,21,21,21], [14,14,14,14,14,14,14,15,15,15,15], + [107,107,107,107], [37,37,37,37,37,37,37,37,38], [20,20,20,20,20,20,20,20,21,21,21,21], [11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12], + [115,115,115,116], [40,40,40,40,41,41,41,41,41], [16,16,16,16,16,16,16,16,16,16,16,17,17,17,17,17], [12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13], + [87,87,87,87,87,88], [41,41,41,41,41,42,42,42,42,42], [24,24,24,24,24,25,25,25,25,25,25,25], [12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13], + [98,98,98,98,98,99], [45,45,45,45,45,45,45,46,46,46], [19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,20,20], [15,15,15,16,16,16,16,16,16,16,16,16,16,16,16,16], + [107,108,108,108,108,108], [46,46,46,46,46,46,46,46,46,46,47], [22,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23], [14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15], + [120,120,120,120,120,121], [43,43,43,43,43,43,43,43,43,44,44,44,44], [22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,23], [14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15], + [113,113,113,114,114,114,114], [44,44,44,45,45,45,45,45,45,45,45,45,45,45], [21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,22,22,22,22], [13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14], + [107,107,107,108,108,108,108,108], [41,41,41,42,42,42,42,42,42,42,42,42,42,42,42,42], [24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,25,25,25,25,25], [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,16,16,16,16,16,16,16,16,16,16], + [116,116,116,116,117,117,117,117], [42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42], [22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,23,23,23,23,23,23], [16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,17,17,17,17,17,17], + [111,111,112,112,112,112,112,112,112], [46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46], [24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25], [13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13], + [121,121,121,121,122,122,122,122,122], [47,47,47,47,48,48,48,48,48,48,48,48,48,48,48,48,48,48], [24,24,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,25,25,25], [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,16,16,16,16,16,16,16,16,16,16,16,16,16,16], + [117,117,117,117,117,117,118,118,118,118], [45,45,45,45,45,45,46,46,46,46,46,46,46,46,46,46,46,46,46,46], [24,24,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25], [16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,17,17], + [106,106,106,106,106,106,106,106,107,107,107,107], [47,47,47,47,47,47,47,47,48,48,48,48,48,48,48,48,48,48,48,48,48], [24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25], [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,16,16,16,16,16,16,16,16,16,16,16,16,16], + [114,114,114,114,114,114,114,114,114,114,115,115], [46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,47,47,47,47], [22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,23,23,23,23,23,23], [16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,17,17,17,17], + [122,122,122,122,122,122,122,122,123,123,123,123], [45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,46,46,46], [23,23,23,23,23,23,23,23,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24], [15,15,15,15,15,15,15,15,15,15,15,15,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16], + [117,117,117,118,118,118,118,118,118,118,118,118,118], [45,45,45,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46], [24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25], [15,15,15,15,15,15,15,15,15,15,15,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16], + [116,116,116,116,116,116,116,117,117,117,117,117,117,117], [45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,46,46,46,46,46,46,46], [23,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24], [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16], + [115,115,115,115,115,116,116,116,116,116,116,116,116,116,116], [47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,48,48,48,48,48,48,48,48,48,48], [24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25], [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16], + [115,115,115,115,115,115,115,115,115,115,115,115,115,116,116,116], [46,46,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47], [24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,25], [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16], + [115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115], [46,46,46,46,46,46,46,46,46,46,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47], [24,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25], [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16], + [115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,116], [46,46,46,46,46,46,46,46,46,46,46,46,46,46,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47], [24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25], [15,15,15,15,15,15,15,15,15,15,15,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16], + [115,115,115,115,115,115,115,115,115,115,115,115,115,116,116,116,116,116,116], [46,46,46,46,46,46,46,46,46,46,46,46,46,46,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47], [24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25], [16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,17], + [121,121,121,121,121,121,121,121,121,121,121,121,122,122,122,122,122,122,122], [47,47,47,47,47,47,47,47,47,47,47,47,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48], [24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,25,25,25], [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16], + [121,121,121,121,121,121,122,122,122,122,122,122,122,122,122,122,122,122,122,122], [47,47,47,47,47,47,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48], [24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25], [15,15,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16], + [122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,123,123,123,123], [46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,47,47,47,47,47,47,47,47,47,47,47,47,47,47], [24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25], [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16], + [122,122,122,122,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123], [46,46,46,46,46,46,46,46,46,46,46,46,46,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47], [24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,25,25,25], [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16], + [117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,118,118,118,118], [47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,48,48,48,48,48,48,48], [24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25], [15,15,15,15,15,15,15,15,15,15,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16], + [118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,119,119,119,119,119,119], [47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48], [24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25], [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16] + ]; + match<[Nat]>(version, level, table) + }; + + public func errorSize(version : Version, level : ErrorCorrection) : Nat { + let table = [ + 07, 10, 13, 17, + 10, 16, 22, 28, + 15, 26, 18, 22, + 20, 18, 26, 16, + 26, 24, 18, 22, + 18, 16, 24, 28, + 20, 18, 18, 26, + 24, 22, 22, 26, + 30, 22, 20, 24, + 18, 26, 24, 28, + 20, 30, 28, 24, + 24, 22, 26, 28, + 26, 22, 24, 22, + 30, 24, 20, 24, + 22, 24, 30, 24, + 24, 28, 24, 30, + 28, 28, 28, 28, + 30, 26, 28, 28, + 28, 26, 26, 26, + 28, 26, 30, 28, + 28, 26, 28, 30, + 28, 28, 30, 24, + 30, 28, 30, 30, + 30, 28, 30, 30, + 26, 28, 30, 30, + 28, 28, 28, 30, + 30, 28, 30, 30, + 30, 28, 30, 30, + 30, 28, 30, 30, + 30, 28, 30, 30, + 30, 28, 30, 30, + 30, 28, 30, 30, + 30, 28, 30, 30, + 30, 28, 30, 30, + 30, 28, 30, 30, + 30, 28, 30, 30, + 30, 28, 30, 30, + 30, 28, 30, 30, + 30, 28, 30, 30, + 30, 28, 30, 30 + ]; + match(version, level, table) + }; + + public func errorPoly(version : Version, level : ErrorCorrection) : Poly { + let size = errorSize(version, level); + let logs = switch size { + case 07 [0,87,229,146,149,238,102,21]; + case 10 [0,251,67,46,61,118,70,64,94,32,45]; + case 13 [0,74,152,176,100,86,100,106,104,130,218,206,140,78]; + case 15 [0,8,183,61,91,202,37,51,58,58,237,140,124,5,99,105]; + case 16 [0,120,104,107,109,102,161,76,3,91,191,147,169,182,194,225,120]; + case 17 [0,43,139,206,78,43,239,123,206,214,147,24,99,150,39,243,163,136]; + case 18 [0,215,234,158,94,184,97,118,170,79,187,152,148,252,179,5,98,96,153]; + case 20 [0,17,60,79,50,61,163,26,187,202,180,221,225,83,239,156,164,212,212,188,190]; + case 22 [0,210,171,247,242,93,230,14,109,221,53,200,74,8,172,98,80,219,134,160,105,165,231]; + case 24 [0,229,121,135,48,211,117,251,126,159,180,169,152,192,226,228,218,111,0,117,232,87,96,227,21]; + case 26 [0,173,125,158,2,103,182,118,17,145,201,111,28,165,53,161,21,245,142,13,102,48,227,153,145,218,70]; + case 28 [0,168,223,200,104,224,234,108,180,110,190,195,147,205,27,232,201,21,43,245,87,42,195,212,119,242,37,9,123]; + case 30 [0,41,173,145,152,216,31,179,182,50,48,110,86,239,96,222,125,42,173,226,193,224,130,156,37,251,216,238,40,192,180]; + case _ { + Prelude.printLn("Error: Invalid error size!"); + Prelude.unreachable() + } + }; + Galois.polyNew(Array.map(Galois.alog, logs)) + }; + + public func cciLen(version : Version, mode : Mode) : Nat { + let n = Version.unbox(version); + let i = + if (09 >= n and n >= 01) 0 else + if (26 >= n and n >= 10) 1 else + if (40 >= n and n >= 27) 2 else { + Prelude.printLn("Error: Invalid version!"); + Prelude.unreachable() + }; + switch mode { + case (#Numeric) [10,12,14][i]; + case (#Alphanumeric) [9,11,13][i]; + case (#EightBit) [8,16,16][i]; + case (#Kanji) [8,10,12][i] + } + }; + + public func eciBits(level : ErrorCorrection) : List { + let bits = switch (level) { + case (#L) { [false, true] }; + case (#M) { [false, false] }; + case (#Q) { [true, true] }; + case (#H) { [true, false] } + }; + List.fromArray(bits) + }; + +} diff --git a/test/perf/qr/eight-bit.mo b/test/perf/qr/eight-bit.mo new file mode 100644 index 00000000000..f505fb1676a --- /dev/null +++ b/test/perf/qr/eight-bit.mo @@ -0,0 +1,23 @@ +/** + * Module : eight-bit.mo + * Copyright : 2020 DFINITY Stiftung + * License : Apache 2.0 with LLVM Exception + * Maintainer : Enzo Haussecker + * Stability : Experimental + */ + +import List "list"; +import Prelude "prelude"; +import Version "version"; + +module { + + type List = List.List; + type Version = Version.Version; + + public func encode(version : Version, text : Text) : ?List { + Prelude.printLn("Error: Eight-bit mode is not yet implemented!"); + Prelude.unreachable() + }; + +} diff --git a/test/perf/qr/format.mo b/test/perf/qr/format.mo new file mode 100644 index 00000000000..460fa7b9caf --- /dev/null +++ b/test/perf/qr/format.mo @@ -0,0 +1,27 @@ +/** + * Module : format.mo + * Copyright : 2020 DFINITY Stiftung + * License : Apache 2.0 with LLVM Exception + * Maintainer : Enzo Haussecker + * Stability : Stable + */ + +import Common "common"; +import Galois "galois"; +import List "list"; +import Nat "nat"; +import Util "util"; + +module { + + type ErrorCorrection = Common.ErrorCorrection; + type List = List.List; + + public func encode(level : ErrorCorrection, maskRef : List) : List { + let input = List.append(Common.eciBits(level), maskRef); + let poly1 = Galois.polyFromBits(Util.padRight(10, input)); + let poly2 = Galois.polyFromBits(Nat.natToBits(1335)); + Util.padLeftTo(15, Nat.natToBits(Nat.natXor(Nat.natFromBits(Galois.polyToBits(Galois.polyAdd(poly1, Galois.polyDivMod(poly1, poly2).1))), 21522))) + }; + +} diff --git a/test/perf/qr/galois.mo b/test/perf/qr/galois.mo new file mode 100644 index 00000000000..93fd5030c81 --- /dev/null +++ b/test/perf/qr/galois.mo @@ -0,0 +1,295 @@ +/** + * Module : galois.mo + * Copyright : 2020 DFINITY Stiftung + * License : Apache 2.0 with LLVM Exception + * Maintainer : Enzo Haussecker + * Stability : Stable + */ + +import Array "array"; +import List "list"; +import Nat "nat"; +import Prelude "prelude"; +import Prim "mo:prim"; +import Util "util" + +module { + + type List = List.List; + + public let logs = [ + 000, 001, 025, 002, 050, 026, 198, 003, 223, 051, + 238, 027, 104, 199, 075, 004, 100, 224, 014, 052, + 141, 239, 129, 028, 193, 105, 248, 200, 008, 076, + 113, 005, 138, 101, 047, 225, 036, 015, 033, 053, + 147, 142, 218, 240, 018, 130, 069, 029, 181, 194, + 125, 106, 039, 249, 185, 201, 154, 009, 120, 077, + 228, 114, 166, 006, 191, 139, 098, 102, 221, 048, + 253, 226, 152, 037, 179, 016, 145, 034, 136, 054, + 208, 148, 206, 143, 150, 219, 189, 241, 210, 019, + 092, 131, 056, 070, 064, 030, 066, 182, 163, 195, + 072, 126, 110, 107, 058, 040, 084, 250, 133, 186, + 061, 202, 094, 155, 159, 010, 021, 121, 043, 078, + 212, 229, 172, 115, 243, 167, 087, 007, 112, 192, + 247, 140, 128, 099, 013, 103, 074, 222, 237, 049, + 197, 254, 024, 227, 165, 153, 119, 038, 184, 180, + 124, 017, 068, 146, 217, 035, 032, 137, 046, 055, + 063, 209, 091, 149, 188, 207, 205, 144, 135, 151, + 178, 220, 252, 190, 097, 242, 086, 211, 171, 020, + 042, 093, 158, 132, 060, 057, 083, 071, 109, 065, + 162, 031, 045, 067, 216, 183, 123, 164, 118, 196, + 023, 073, 236, 127, 012, 111, 246, 108, 161, 059, + 082, 041, 157, 085, 170, 251, 096, 134, 177, 187, + 204, 062, 090, 203, 089, 095, 176, 156, 169, 160, + 081, 011, 245, 022, 235, 122, 117, 044, 215, 079, + 174, 213, 233, 230, 231, 173, 232, 116, 214, 244, + 234, 168, 080, 088, 175 + ]; + + public func log(n : Nat) : Nat { + let m = n % 256; + if (m == 0) { + Prelude.printLn("Error: Logarithm of zero is undefined in GF(256)!"); + Prelude.unreachable() + }; + logs[m - 1] + }; + + public let alogs = [ + 001, 002, 004, 008, 016, 032, 064, 128, 029, 058, + 116, 232, 205, 135, 019, 038, 076, 152, 045, 090, + 180, 117, 234, 201, 143, 003, 006, 012, 024, 048, + 096, 192, 157, 039, 078, 156, 037, 074, 148, 053, + 106, 212, 181, 119, 238, 193, 159, 035, 070, 140, + 005, 010, 020, 040, 080, 160, 093, 186, 105, 210, + 185, 111, 222, 161, 095, 190, 097, 194, 153, 047, + 094, 188, 101, 202, 137, 015, 030, 060, 120, 240, + 253, 231, 211, 187, 107, 214, 177, 127, 254, 225, + 223, 163, 091, 182, 113, 226, 217, 175, 067, 134, + 017, 034, 068, 136, 013, 026, 052, 104, 208, 189, + 103, 206, 129, 031, 062, 124, 248, 237, 199, 147, + 059, 118, 236, 197, 151, 051, 102, 204, 133, 023, + 046, 092, 184, 109, 218, 169, 079, 158, 033, 066, + 132, 021, 042, 084, 168, 077, 154, 041, 082, 164, + 085, 170, 073, 146, 057, 114, 228, 213, 183, 115, + 230, 209, 191, 099, 198, 145, 063, 126, 252, 229, + 215, 179, 123, 246, 241, 255, 227, 219, 171, 075, + 150, 049, 098, 196, 149, 055, 110, 220, 165, 087, + 174, 065, 130, 025, 050, 100, 200, 141, 007, 014, + 028, 056, 112, 224, 221, 167, 083, 166, 081, 162, + 089, 178, 121, 242, 249, 239, 195, 155, 043, 086, + 172, 069, 138, 009, 018, 036, 072, 144, 061, 122, + 244, 245, 247, 243, 251, 235, 203, 139, 011, 022, + 044, 088, 176, 125, 250, 233, 207, 131, 027, 054, + 108, 216, 173, 071, 142 + ]; + + public func alog(n : Nat) : Nat { + let m = n % 256; + if (m == 255) { + Prelude.printLn("Error: Antilogarithm of 255 is undefined in GF(256)!"); + Prelude.unreachable() + }; + alogs[m] + }; + + public type Elem = { unbox : Nat }; + + public func elemNew(n : Nat) : Elem { + { unbox = n % 256 } + }; + + public func elemShow(elem : Elem) : Text { + debug_show(elem.unbox) + }; + + public func elemToBit(elem : Elem) : Bool { + elem.unbox > 0 + }; + + public func elemFromBit(bit : Bool) : Elem { + if bit { unbox = 1 } else { unbox = 0 } + }; + + public func elemToBits(elem : Elem) : List { + Util.padLeftTo(8, Nat.natToBits(elem.unbox)) + }; + + public func elemFromBits(bits : List) : Elem { + elemNew(Nat.natFromBits(bits)) + }; + + public func elemEq(elem1 : Elem, elem2 : Elem) : Bool { + elem1.unbox == elem2.unbox + }; + + public func elemAdd(elem1 : Elem, elem2 : Elem) : Elem { + { unbox = Nat.natXor(elem1.unbox, elem2.unbox) } + }; + + public func elemSub(elem1 : Elem, elem2 : Elem) : Elem { + elemAdd(elem1, elem2) + }; + + public func elemMul(elem1 : Elem, elem2 : Elem) : Elem { + switch (elem1.unbox, elem2.unbox) { + case (0, _) { elem1 }; + case (_, 0) { elem2 }; + case (a, b) { unbox = alog((log(a) + log(b)) % 255) } + } + }; + + public func elemDiv(elem1 : Elem, elem2 : Elem) : Elem { + switch (elem1.unbox, elem2.unbox) { + case (_, 0) { + Prelude.printLn("Error: Division by zero is undefined in GF(256)!"); + Prelude.unreachable() + }; + case (0, _) { unbox = 0 }; + case (a, b) { unbox = alog((255 + log(a) - log(b)) % 255) } + } + }; + + public func elemDivMod(elem1 : Elem, elem2 : Elem) : (Elem, Elem) { + let elem3 = elemDiv(elem1, elem2); + (elem3, elemSub(elem1, elem3)) + }; + + public type Poly = { unbox : List }; + + public func polyNew(coeffs : [Nat]) : Poly { + func step(n : Nat, accum : List) : List { + List.push(elemNew(n), accum) + }; + let base = List.nil(); + { unbox = Array.foldr>(step, base, coeffs) } + }; + + public func polyShow(poly : Poly) : Text { + switch (List.pop(poly.unbox)) { + case (null, _) { "[]" }; + case (?head, tail) { + let base = elemShow(head); + func step(elem : Elem, accum : Text) : Text { + accum # "," # elemShow(elem) + }; + "[" # List.foldLeft(tail, base, step) # "]" + } + } + }; + + public func polyToBits(poly : Poly) : List { + List.map(poly.unbox, elemToBit) + }; + + public func polyFromBits(bits : List) : Poly { + { unbox = List.map(bits, elemFromBit) } + }; + + public func polyLen(poly : Poly) : Nat { + List.len(poly.unbox) + }; + + public func polyTrim(poly : Poly) : Poly { + func go(elems : List) : List { + switch (List.pop(elems)) { + case (?{ unbox = 0 }, tail) { go(tail) }; + case _ { elems } + } + }; + { unbox = go(poly.unbox) } + }; + + public func polyOrder(poly : Poly) : Int { + Prim.abs(polyLen(polyTrim(poly))) - 1 + }; + + public func polyLeadCoeff(poly : Poly) : Elem { + switch (List.pop(polyTrim(poly).unbox).0) { + case (?elem) { elem }; + case (null) { unbox = 0 } + } + }; + + public func polyPadLeft(n : Nat, poly : Poly) : Poly { + let zeros = List.replicate(n, { unbox = 0 }); + { unbox = List.append(zeros, poly.unbox) } + }; + + public func polyPadRight(n : Nat, poly : Poly) : Poly { + let zeros = List.replicate(n, { unbox = 0 }); + { unbox = List.append(poly.unbox, zeros) } + }; + + public func polyGrow(to : Nat, poly : Poly) : Poly { + let from = polyLen(poly); + if (to > from) { + polyPadLeft(to - from, poly) + } else poly + }; + + public func polyZipWith( + poly1 : Poly, + poly2 : Poly, + f : (Elem, Elem) -> Elem + ) : Poly { + let n1 = polyLen(poly1); + let n2 = polyLen(poly2); + let to = if (n1 > n2) n1 else n2; + { unbox = List.zipWith( + polyGrow(to, poly1).unbox, + polyGrow(to, poly2).unbox, + f + ) } + }; + + public func polyEq(poly1 : Poly, poly2 : Poly) : Bool { + List.isEq(polyTrim(poly1).unbox, polyTrim(poly2).unbox, elemEq) + }; + + public func polyAdd(poly1 : Poly, poly2 : Poly) : Poly { + polyZipWith(poly1, poly2, elemAdd) + }; + + public func polySub(poly1 : Poly, poly2 : Poly) : Poly { + polyAdd(poly1, poly2) + }; + + public func polyScale(alpha : Elem, poly : Poly) : Poly { + func scale(elem : Elem) : Elem = elemMul(alpha, elem); + { unbox = List.map(poly.unbox, scale) } + }; + + public type Term = { coeff : Elem; order : Int }; + + public func polyAddTerm(poly : Poly, term : Term) : Poly { + let n = if (term.order <= 0) 0 else Prim.abs(term.order); + polyAdd(poly, polyPadRight(n, polyNew([term.coeff.unbox]))) + }; + + public func polyMulTerm(poly : Poly, term : Term) : Poly { + let n = if (term.order <= 0) 0 else Prim.abs(term.order); + polyScale(term.coeff, polyPadRight(n, poly)) + }; + + public func polyDivMod(poly1 : Poly, poly2 : Poly) : (Poly, Poly) { + let divisorLeadCoeff = polyLeadCoeff(poly2); + let divisorOrder = polyOrder(poly2); + func go(currentDividend : Poly, currentDivisor : Poly) : (Poly, Poly) { + let currentOrder = polyOrder(currentDividend) - divisorOrder; + if (currentOrder < 0) { + (currentDivisor, currentDividend) + } else { + let currentDividendLeadCoeff = polyLeadCoeff(currentDividend); + let currentCoeff = elemDiv(currentDividendLeadCoeff, divisorLeadCoeff); + let currentTerm = { coeff = currentCoeff; order = currentOrder }; + let currentQuotient = polyMulTerm(poly2, currentTerm); + let nextDividend = polySub(currentQuotient, currentDividend); + let nextDivisor = polyAddTerm(currentDivisor, currentTerm); + go(nextDividend, nextDivisor) + } + }; + go(poly1, polyNew([])) + }; + +} diff --git a/test/perf/qr/generic.mo b/test/perf/qr/generic.mo new file mode 100644 index 00000000000..7718372035f --- /dev/null +++ b/test/perf/qr/generic.mo @@ -0,0 +1,36 @@ +/** + * Module : generic.mo + * Copyright : 2020 DFINITY Stiftung + * License : Apache 2.0 with LLVM Exception + * Maintainer : Enzo Haussecker + * Stability : Stable + */ + +import Alphanumeric "alphanumeric"; +import Common "common"; +import EightBit "eight-bit"; +import Kanji "kanji"; +import List "list"; +import Numeric "numeric"; +import Version "version"; + +module { + + type List = List.List; + type Mode = Common.Mode; + type Version = Version.Version; + + public func encode( + version : Version, + mode : Mode, + text : Text + ) : ?List { + switch mode { + case (#Alphanumeric) Alphanumeric.encode(version, text); + case (#EightBit) EightBit.encode(version, text); + case (#Kanji) Kanji.encode(version, text); + case (#Numeric) Numeric.encode(version, text) + } + }; + +} diff --git a/test/perf/qr/hash.mo b/test/perf/qr/hash.mo new file mode 100644 index 00000000000..47d88be63c1 --- /dev/null +++ b/test/perf/qr/hash.mo @@ -0,0 +1,111 @@ +/** +[#mod-Hash] += `Hash` -- Hash values +*/ + +import Prim "mo:prim"; +import Iter "iter"; + +module { + /** + Hash values represent a string of _hash bits_, packed into a `Word32`. + */ + public type Hash = Word32; + + /** + The hash length, always 31. + */ + public let length : Nat = 31; // Why not 32? + + public let hashOfInt : Int -> Hash = func(i) { + let j = Prim.intToWord32(i); + hashWord8s( + [j & (255 << 0), + j & (255 << 8), + j & (255 << 16), + j & (255 << 24) + ]); + }; + + /** + WARNING: This only hashes the lowest 32 bits of the `Int` + */ + public let hashOfIntAcc : (Hash, Int) -> Hash = func(h1, i) { + let j = Prim.intToWord32(i); + hashWord8s( + [h1, + j & (255 << 0), + j & (255 << 8), + j & (255 << 16), + j & (255 << 24) + ]); + }; + + /** + WARNING: This only hashes the lowest 32 bits of the `Int` + */ + public let hashOfText : Text -> Hash = func(t) { + var x = 0 : Word32; + for (c in t.chars()) { + x := x ^ Prim.charToWord32(c); + }; + return x + }; + + /** + Project a given bit from the bit vector. + */ + public let getHashBit : (Hash, Nat) -> Bool = func(h, pos) { + assert (pos <= length); + (h & (Prim.natToWord32(1) << Prim.natToWord32(pos))) != Prim.natToWord32(0) + }; + + /** + Test if two hashes are equal + */ + public let hashEq : (Hash, Hash) -> Bool = func(ha, hb) { + ha == hb + }; + + public let bitsPrintRev : Hash -> () = func(bits) { + for (j in Iter.range(0, length - 1)) { + if (getHashBit(bits, j)) { + Prim.debugPrint "1" + } else { + Prim.debugPrint "0" + } + } + }; + + public let hashPrintRev : Hash -> () = func(bits) { + for (j in Iter.range(length - 1, 0)) { + if (getHashBit(bits, j)) { + Prim.debugPrint "1" + } else { + Prim.debugPrint "0" + } + } + }; + + /** + Jenkin's one at a time: + https://en.wikipedia.org/wiki/Jenkins_hash_function#one_at_a_time + + The input type should actually be `[Word8]`. + Note: Be sure to explode each `Word8` of a `Word32` into its own `Word32`, and to shift into lower 8 bits. + // should this really be public? + */ + public let hashWord8s : [Hash] -> Hash = func(key) { + var hash = Prim.natToWord32(0); + for (wordOfKey in key.vals()) { + hash := hash + wordOfKey; + hash := hash + hash << 10; + hash := hash ^ (hash >> 6); + }; + hash := hash + hash << 3; + hash := hash ^ (hash >> 11); + hash := hash + hash << 15; + return hash; + }; + +} diff --git a/test/perf/qr/iter.mo b/test/perf/qr/iter.mo new file mode 100644 index 00000000000..a8195000c68 --- /dev/null +++ b/test/perf/qr/iter.mo @@ -0,0 +1,105 @@ +/** +[#mod-Iter] += `Iter` -- Iterators +*/ + +import Array "array"; +import List "list"; + +module { + public type Iter = {next : () -> ?T}; + + public class range(x : Nat, y : Nat) { + var i = x; + public func next() : ?Nat { if (i > y) null else {let j = i; i += 1; ?j} }; + }; + + public func forIn( + f : (A, Nat) -> (), + xs : Iter + ) { + var i = 0; + label l loop { + switch (xs.next()) { + case (?next) { + f(next, i); + }; + case (null) { + break l; + }; + }; + i += 1; + continue l; + }; + }; + + func length(xs : Iter) : Nat { + var len = 0; + forIn(func (x, i) { len += 1; }, xs); + len; + }; + + public func map(f : A -> B, xs : Iter) : Iter = object { + var i = 0; + public func next() : ?B { + label l loop { + switch (xs.next()) { + case (?next) { + return ?f(next); + }; + case (null) { + break l; + }; + }; + i += 1; + continue l; + }; + null; + }; + }; + + public func pure(x : A) : Iter = object { + public func next() : ?A { + ?x; + }; + }; + + public func fromArray(xs : [A]) : Iter { + fromList(List.fromArray(xs)); + }; + + public func fromArrayMut(xs : [var A]) : Iter { + fromArray(Array.freeze(xs)); + }; + + public func fromList(xs : List.List) : Iter { + List.toArray(xs).vals(); + }; + + public func toArray(xs : Iter) : [A] { + List.toArray(toList(xs)); + }; + + public func toArrayMut(xs : Iter) : [var A] { + Array.thaw(toArray(xs)); + }; + + public func toList(xs : Iter) : List.List { + toListWithLength(xs).list; + }; + + public func toListWithLength( + xs : Iter, + ) : ({ + length : Nat; + list : List.List; + }) { + var _length = 0; + var _list = List.nil(); + forIn(func (x, i) { + _length += 1; + _list := List.push(x, _list); + }, xs); + { length = _length; list = List.rev(_list); }; + }; +} diff --git a/test/perf/qr/kanji.mo b/test/perf/qr/kanji.mo new file mode 100644 index 00000000000..b99e77dd675 --- /dev/null +++ b/test/perf/qr/kanji.mo @@ -0,0 +1,23 @@ +/** + * Module : kanji.mo + * Copyright : 2020 DFINITY Stiftung + * License : Apache 2.0 with LLVM Exception + * Maintainer : Enzo Haussecker + * Stability : Experimental + */ + +import List "list"; +import Prelude "prelude"; +import Version "version"; + +module { + + type List = List.List; + type Version = Version.Version; + + public func encode(version : Version, text : Text) : ?List { + Prelude.printLn("Error: Kanji mode is not yet implemented!"); + Prelude.unreachable() + }; + +} diff --git a/test/perf/qr/list.mo b/test/perf/qr/list.mo new file mode 100644 index 00000000000..8eee28d09f9 --- /dev/null +++ b/test/perf/qr/list.mo @@ -0,0 +1,539 @@ +/** +[#mod-List] += `List` -- Lists + +This module provides purely-functional, singly-linked lists. + + +*/ + +import Array "array"; +import Option "option"; + +module { + + /** + A singly-linked list consists of zero or more _cons cells_, wherein + each cell contains a single list element (the cell's _head_), and a pointer to the + remainder of the list (the cell's _tail_). + */ + public type List = ?(T, List); + + /** + The empty list + */ + public let nil : () -> List = + func() : List = null; + + + /** + Returns true if the list is empty. + */ + public let isNil : List -> Bool = + func(l : List) : Bool { + switch l { + case null { true }; + case _ { false }; + } + }; + + /** + also known as "list cons" + */ + public let push : (T, List) -> List = + func(x : T, l : List) : List = ?(x, l); + + /** + The last element of the list, if present. + */ + public let last : List -> ?T = + func(l : List) : ?T { + switch l { + case null { null }; + case (?(x,null)) { ?x }; + case (?(_,t)) { last(t) }; + } + }; + + /** + Treating the list as a stack; this combines the usual operations `head` and (non-failing) `tail` into one operation. + */ + public let pop : List -> (?T, List) = + func(l : List) : (?T, List) { + switch l { + case null { (null, null) }; + case (?(h, t)) { (?h, t) }; + } + }; + + /** + The length of the list + */ + public let len : List -> Nat = + func(l : List) : Nat { + func rec(l : List, n : Nat) : Nat { + switch l { + case null { n }; + case (?(_,t)) { rec(t,n+1) }; + } + }; + rec(l,0) + }; + + /** + Tests the length against a maximum value + */ + public let lenIsEqLessThan : (List, Nat) -> Bool = + func(l : List , i : Nat) : Bool { + switch l { + case null true; + case (?(_, t)) { + if (i == 0) { false } + else { lenIsEqLessThan(t, i - 1) } + }; + }; + }; + + /** + Get the length, unless greater than a maximum value, in which return `null`. + */ + public let lenClamp : (List, max : Nat) -> ?Nat = + func(l : List, max : Nat) : ?Nat { + func rec(l : List, max : Nat, i : Nat) : ?Nat { + switch l { + case null { ?i }; + case (?(_, t)) { + if ( i > max ) { null } + else { rec(t, max, i + 1) } + }; + } + }; + rec(l, max, 0) + }; + + /** + Random list access, zero-based. + + NOTE: Indexing into a list is a linear operation, and usually an indication + that a list might not be the best data structure to use. + */ + public let nth : (List, Nat) -> ?T = + func(l : List, n : Nat) : ?T { + switch (n, l) { + case (_, null) { null }; + case (0, (?(h,t))) { ?h }; + case (_, (?(_,t))) { nth(t, n - 1) }; + } + }; + + /** + reverse the list; tail recursive + */ + public let rev : List -> List = + func(l : List) : List = { + func rec(l : List, r : List) : List { + switch l { + case null { r }; + case (?(h,t)) { rec(t,?(h,r)) }; + } + }; + rec(l, null) + }; + + /** + Calls the given function with each list element in turn. + + This is called `app` in SML Basis, and `iter` in OCaml. + */ + public let iter : (List, f : T -> ()) -> () = + func iter(l : List, f : T -> ()) { + switch l { + case null { () }; + case (?(h,t)) { f(h) ; iter(t, f) }; + } + }; + + /** + Calls the given function on each list element, collecing the results in a new + list. + */ + public let map : (List, f : T -> S) -> List = + func(l : List, f:T -> S) : List = { + switch l { + case null { null }; + case (?(h,t)) { ?(f(h),map(t,f)) }; + } + }; + + /** + Creates a new list with only those elements of the original list for which + the given function (often called the _predicate_) is returns true. + */ + public let filter : (List, p : T -> Bool) -> List = + func(l : List, f:T -> Bool) : List = { + switch l { + case null { null }; + case (?(h,t)) { + if (f(h)) { + ?(h,filter(t, f)) + } else { + filter(t, f) + } + }; + }; + }; + + /** + Creates two new lists. The first has those elements for which the given + function `f` returns true, the second those for which it returns false. + + Also known as `partition`. + */ + public let split : (List, f : T -> Bool) -> (List, List) = + func(l : List, f:T -> Bool) : (List, List) = { + switch l { + case null { (null, null) }; + case (?(h,t)) { + if (f(h)) { // call f in-order + let (l,r) = split(t, f); + (?(h,l), r) + } else { + let (l,r) = split(t, f); + (l, ?(h,r)) + } + }; + }; + }; + + /** + Calls the given function on each list element, collecing the non-null results + in a new list. + */ + public let mapFilter : (List, f : T -> ?S) -> List = + func(l : List, f:T -> ?S) : List = { + switch l { + case null { null }; + case (?(h,t)) { + switch (f(h)) { + case null { mapFilter(t, f) }; + case (?h_){ ?(h_,mapFilter(t, f)) }; + } + }; + }; + }; + + /** + Appends two lists. + */ + public let append : (List, List) -> List = + func (l : List, m : List) : List = { + func rec(l : List) : List { + switch l { + case null { m }; + case (?(h,t)) {?(h,rec(t))}; + } + }; + rec(l) + }; + + /** + concatenations a list of lists (Also known as "list join") + */ + public let concat : (List>) -> List = + // tail recursive, but requires "two passes" + func(l : List>) : List = { + // 1/2: fold from left to right, reverse-appending the sublists... + let r = foldLeft, List>(l, null, func(a,b) { revAppend(a,b) }); + // 2/2: ...re-reverse the elements, to their original order: + rev(r) + }; + + // Internal utility-function + func revAppend(l1 : List, l2 : List) : List { + switch l1 { + case null { l2 }; + case (?(h,t)) { revAppend(t, ?(h,l2)) }; + } + }; + + /** + "takes" `n` elements from the prefix of the given list. + If the given list has fewer than `n` elements, this returns (a copy of) the + full input list. + */ + public let take : (List, n:Nat) -> List = + func(l : List, n:Nat) : List = { + switch (l, n) { + case (_, 0) { null }; + case (null,_) { null }; + case (?(h, t), m) {?(h, take(t, m - 1))}; + } + }; + + /** + "drops" an `n` element prefix from the given list. + */ + public let drop : (List, n:Nat) -> List = + func(l : List, n:Nat) : List = { + switch (l, n) { + case (l_, 0) { l_ }; + case (null, _) { null }; + case ((?(h,t)), m) { drop(t, m - 1) }; + } + }; + + /** + fold list left-to-right using function `f`. + */ + public let foldLeft : (List, S, f : (T,S) -> S) -> S = + func(l : List, a:S, f:(T,S) -> S) : S = { + switch l { + case null { a }; + case (?(h,t)) { foldLeft(t, f(h,a), f) }; + }; + }; + + /** + fold the list right-to-left using function `f`. + */ + public let foldRight : (List, S, f : (T,S) -> S) -> S = + func(l : List, a:S, f:(T,S) -> S) : S = { + switch l { + case null { a }; + case (?(h,t)) { f(h, foldRight(t, a, f)) }; + }; + }; + + /** + Returns the first element for which given predicate `f` is true, if such an element exists. + */ + public let find : (l: List, f : T -> Bool) -> ?T = + func(l: List, f:T -> Bool) : ?T = { + switch l { + case null { null }; + case (?(h,t)) { if (f(h)) { ?h } else { find(t, f) } }; + }; + }; + + /** + Returns true if there exists list element for which given predicate `f` is true + */ + public let exists : (List, f : T -> Bool) -> Bool = + func(l: List, f:T -> Bool) : Bool = { + switch l { + case null { false }; + case (?(h,t)) { f(h) or exists(t, f)}; + }; + }; + + /** + Returns true if for all list element the given predicate `f` is true + */ + public let all : (List, f : T -> Bool) -> Bool = + func(l: List, f:T -> Bool) : Bool = { + switch l { + case null { true }; + case (?(h,t)) { f(h) and all(t, f) }; + } + }; + + /** + Given two lists that are orderd (with regard to the given relation `lte`), + merge them into a single ordered list + */ + public let merge : (List, List, lte : (T,T) -> Bool) -> List = + func(l1: List, l2: List, lte:(T,T) -> Bool) : List { + switch (l1, l2) { + case (null, _) { l2 }; + case (_, null) { l1 }; + case (?(h1,t1), ?(h2,t2)) { + if (lte(h1,h2)) { + ?(h1, merge(t1, l2, lte)) + } else { + ?(h2, merge(l1, t2, lte)) + } + }; + } + }; + + /** + Compares two lists using lexicographic ordering (with regard to the given relation `lte`). + + // To do: Eventually, follow `collate` design from SML Basis, with real sum + // types, use 3-valued `order` type here. + */ + public let lessThanEq : (List, List, lte: (T,T) -> Bool) -> Bool = + func(l1: List, l2: List, lte:(T,T) -> Bool) : Bool { + switch (l1, l2) { + case (null, _) { true }; + case (_, null) { false }; + case (?(h1,t1), ?(h2,t2)) { lte(h1,h2) and lessThanEq(t1, t2, lte) }; + }; + }; + + /** + Compares two lists for equality (with regard to the given relation `eq` on elements). + + // `isEq(l1, l2)` is equivalent to `lessThanEq(l1,l2) && lessThanEq(l2,l1)`, but the former is more efficient. + */ + public let isEq : (List, List, eq : (T,T) -> Bool) -> Bool = + func(l1: List, l2: List, eq:(T,T) -> Bool) : Bool { + switch (l1, l2) { + case (null, null) { true }; + case (null, _) { false }; + case (_, null) { false }; + case (?(h1,t1), ?(h2,t2)) { eq(h1,h2) and isEq(t1, t2, eq) }; + } + }; + + /** + generates a list based on a length, and a function from list index to list element. + */ + public let tabulate : (Nat, f : Nat -> T) -> List = + func(n:Nat, f:Nat -> T) : List { + func rec(i:Nat, n: Nat, f : Nat -> T) : List { + if (i == n) { null } else { ?(f(i), rec(i+1, n, f)) } + }; + rec(0, n, f) + }; + + /** + creates a list with exactly one element. + */ + public let singleton : X -> List = + func(x : X) : List { + ?(x, null) + }; + + /** + creates a list of the given length with the same value in each position. + */ + public let replicate : (Nat, X) -> List = + func(n : Nat, x : X) : List { + tabulate(n, func _ { x }) + }; + + /** + creates a list of pairs from a pair of lists. + + If the given lists have different lengths, then the created list will have a + length equal to the lenght of the smaller list. + */ + public let zip : (List, List) -> List<(X, Y)> = + func(xs : List, ys : List) : List<(X, Y)> { + zipWith(xs, ys, func (x, y) { (x, y) }) + }; + + /** + Creates a list whose elements are calculated from the function `f` and + elements occuring at the same position in the given lists. + + If the given lists have different lengths, then the created list will have a + length equal to the length of the smaller list. + */ + public let zipWith : (List, List, f : (X, Y) -> Z) -> List = + func(xs : List, ys : List, f : (X, Y) -> Z) : List { + switch (pop(xs)) { + case (null, _) null; + case (?x, xt) { + switch (pop(ys)) { + case (null, _) null; + case (?y, yt) { + push(f(x, y), zipWith(xt, yt, f)) + } + } + } + } + }; + + /** + splits the given list at the given zero-based index. + */ + public let splitAt : (Nat, List) -> (List, List) = + func(n : Nat, xs : List) : (List, List) { + if (n == 0) { + (null, xs) + } else { + func rec(n : Nat, xs : List) : (List, List) { + switch (pop(xs)) { + case (null, _) { + (null, null) + }; + case (?h, t) { + if (n == 1) { + (singleton(h), t) + } else { + let (l, r) = rec(n - 1, t); + (push(h, l), r) + } + } + } + }; + rec(n, xs) + } + }; + + /** + split the given list into length-n chunks. The last chunk will be shorter if + n does not evenly divide the length of the given list. + */ + public let chunksOf : (Nat, List) -> List> = + func(n : Nat, xs : List) : List> { + let (l, r) = splitAt(n, xs); + if (isNil(l)) { + null + } else { + push>(l, chunksOf(n, r)) + } + }; + + /** + converts an array into a list. + */ + public let fromArray : [A] -> List = + func(xs : [A]) : List { + Array.foldr>(func (x : A, ys : List) : List { + push(x, ys); + }, nil(), xs); + }; + + /** + converts a mutable array into a list. + */ + public let fromArrayMut : [var A] -> List = + func(xs : [var A]) : List { + fromArray(Array.freeze(xs)); + }; + + /** + creates an array from the list + */ + public let toArray : List -> [A] = + func(xs : List) : [A] { + let length = len(xs); + var list = xs; + Array.tabulate(length, func (i) { + let popped = pop(list); + list := popped.1; + Option.unwrap(popped.0); + }); + }; + + /** + creates a mutable array from the list + */ + public let toArrayMut : List -> [var A] = + func(xs : List) : [var A] { + Array.thaw(toArray(xs)); + }; + +/* + +To do: +-------- +- iterator objects, for use in `for ... in ...` patterns +- operations for lists of pairs and pairs of lists: split, etc +- more regression tests for everything that is below + +*/ +} diff --git a/test/perf/qr/mask.mo b/test/perf/qr/mask.mo new file mode 100644 index 00000000000..348b288b796 --- /dev/null +++ b/test/perf/qr/mask.mo @@ -0,0 +1,80 @@ +/** + * Module : mask.mo + * Copyright : 2020 DFINITY Stiftung + * License : Apache 2.0 with LLVM Exception + * Maintainer : Enzo Haussecker + * Stability : Experimental + */ + +import Common "common"; +import List "list"; +import Option "option"; +import Symbol "symbol"; +import Version "version"; + +module { + + type Candidate = ([var [var Bool]], List); + type ErrorCorrection = Common.ErrorCorrection; + type List = List.List; + type Version = Version.Version; + + public func generate( + version : Version, + level : ErrorCorrection, + data : List + ) : ([var [var Bool]], List) { + + let tests = List.fromArray<(Nat, Nat) -> Bool>([ + maskTest000, maskTest001, maskTest010, maskTest011, + maskTest100, maskTest101, maskTest110, maskTest111 + ]); + + let masks = List.map<(Nat, Nat) -> Bool, List>(tests, func (test) { + let w = Common.width(version); + func mirror(n : Nat) : Nat { w - n - 1 }; + List.map<(Nat, Nat), Bool>(Symbol.pathCoords(version), func (i, j) { + test(mirror(i), mirror(j)) + }) + }); + + let matrices = List.map, [var [var Bool]]>(masks, func (mask) { + Symbol.symbolize( + version, + List.zipWith(mask, data, func (x, y) { x != y }) + ) + }); + + let maskRefs = List.fromArray>([ + maskRef000, maskRef001, maskRef010, maskRef011, + maskRef100, maskRef101, maskRef110, maskRef111 + ]); + + let candidates = List.zip<[var [var Bool]], List>( + matrices, + maskRefs + ); + + // TODO: Score candidates. + Option.unwrap(List.nth(candidates, 3)) + }; + + let maskRef000 = ?(false, ?(false, ?(false, null))); + let maskRef001 = ?(false, ?(false, ?(true, null))); + let maskRef010 = ?(false, ?(true, ?(false, null))); + let maskRef011 = ?(false, ?(true, ?(true, null))); + let maskRef100 = ?(true, ?(false, ?(false, null))); + let maskRef101 = ?(true, ?(false, ?(true, null))); + let maskRef110 = ?(true, ?(true, ?(false, null))); + let maskRef111 = ?(true, ?(true, ?(true, null))); + + func maskTest000(i : Nat, j : Nat) : Bool { (i + j) % 2 == 0 }; + func maskTest001(i : Nat, j : Nat) : Bool { i % 2 == 0 }; + func maskTest010(i : Nat, j : Nat) : Bool { j % 3 == 0 }; + func maskTest011(i : Nat, j : Nat) : Bool { (i + j) % 3 == 0 }; + func maskTest100(i : Nat, j : Nat) : Bool { ((i / 2) + (j / 3)) % 2 == 0 }; + func maskTest101(i : Nat, j : Nat) : Bool { (i * j) % 2 + (i * j) % 3 == 0 }; + func maskTest110(i : Nat, j : Nat) : Bool { ((i * j) % 2 + (i * j) % 3) % 2 == 0 }; + func maskTest111(i : Nat, j : Nat) : Bool { ((i * j) % 3 + (i + j) % 2) % 2 == 0 }; + +} diff --git a/test/perf/qr/nat.mo b/test/perf/qr/nat.mo new file mode 100644 index 00000000000..f934823cf83 --- /dev/null +++ b/test/perf/qr/nat.mo @@ -0,0 +1,100 @@ +/** + * Module : nat.mo + * Copyright : 2020 DFINITY Stiftung + * License : Apache 2.0 with LLVM Exception + * Maintainer : Enzo Haussecker + * Stability : Stable + */ + +import List "list"; +import Prim "mo:prim"; + +module { + + type List = List.List; + + public func natNot(a : Nat) : Nat { + natMap(a, func (x) { ^ x }) + }; + + public func natAnd(a : Nat, b : Nat) : Nat { + natZipWith(a, b, func (x, y) { x & y }) + }; + + public func natOr(a : Nat, b : Nat) : Nat { + natZipWith(a, b, func (x, y) { x | y }) + }; + + public func natXor(a : Nat, b : Nat) : Nat { + natZipWith(a, b, func (x, y) { x ^ y }) + }; + + public func natMap(a : Nat, f : Word8 -> Word8) : Nat { + natFromBytes(List.map(natToBytes(a), f)) + }; + + public func natZipWith(a : Nat, b : Nat, f : (Word8, Word8) -> Word8) : Nat { + var xs = natToBytes(a); + var ys = natToBytes(b); + let xsLen = List.len(xs); + let ysLen = List.len(ys); + if (xsLen < ysLen) { + xs := List.append(List.replicate(ysLen - xsLen, 0), xs); + }; + if (xsLen > ysLen) { + ys := List.append(List.replicate(xsLen - ysLen, 0), xs); + }; + let zs = List.zipWith(xs, ys, f); + let c = natFromBytes(zs); + c + }; + + public func natToBytes(n : Nat) : List { + var a = 0; + var b = n; + var bytes = List.nil(); + var test = true; + while test { + a := b % 256; + b := b / 256; + bytes := List.push(Prim.natToWord8(a), bytes); + test := b > 0; + }; + bytes + }; + + public func natFromBytes(bytes : List) : Nat { + var n = 0; + var i = 0; + List.foldRight(bytes, (), func (byte, _) { + n += Prim.word8ToNat(byte) * 256 ** i; + i += 1; + }); + n + }; + + public func natToBits(n : Nat) : List { + var a = 0; + var b = n; + var bits = List.nil(); + var test = true; + while test { + a := b % 2; + b := b / 2; + bits := List.push(a == 1, bits); + test := b > 0; + }; + bits + }; + + public func natFromBits(bits : List) : Nat { + var n = 0; + var i = 0; + List.foldRight(bits, (), func (test, _) { + if test { n += 2 ** i }; + i += 1; + }); + n + }; + +} diff --git a/test/perf/qr/numeric.mo b/test/perf/qr/numeric.mo new file mode 100644 index 00000000000..281bb79c463 --- /dev/null +++ b/test/perf/qr/numeric.mo @@ -0,0 +1,91 @@ +/** + * Module : numeric.mo + * Copyright : 2020 DFINITY Stiftung + * License : Apache 2.0 with LLVM Exception + * Maintainer : Enzo Haussecker + * Stability : Experimental + */ + +import Char "char"; +import Common "common"; +import Iter "iter"; +import List "list"; +import Nat "nat"; +import Option "option"; +import Prim "mo:prim"; +import Text "text"; +import Util "util"; +import Version "version"; + +module { + + type List = List.List; + type Version = Version.Version; + + // Encode the given input text using the numeric encoding routine. + public func encode(version : Version, text : Text) : ?List { + + let mi = List.fromArray([false, false, false, true]); + let cci = Util.padLeftTo( + Common.cciLen(version, #Numeric), + Nat.natToBits(text.len()) + ); + + let header = List.append(mi, cci); + let footer = List.replicate(4, false); + func render(body : List) : List { + List.append(header, List.append(body, footer)) + }; + + // + let chunks = List.chunksOf(3, Iter.toList(Text.toIter(text))); + + // + func step(chunk : List, accum : ?List) : ?List { + switch (parse(chunk), accum) { + case (?a, ?b) { ?List.append(a, b) }; + case _ null + } + }; + + // + Option.map, List>( + render, + List.foldRight, ?List>(chunks, ?null, step) + ) + + }; + + func parse(chunk : List) : ?List { + + // + let p = switch (List.len(chunk)) { + case 3 ?10; + case 2 ?07; + case 1 ?04; + case _ null + }; + + // + let n = List.foldLeft(chunk, ?0, func (char, accum) { + if (Char.isDigit(char)) { + Option.map(func (a) { + let b = Prim.word32ToNat( + Prim.charToWord32(char) - Prim.charToWord32('0') + ); + 10 * a + b + }, accum) + } else { + null + } + }); + + // + switch (p, n) { + case (?a, ?b) { ?Util.padLeftTo(a, Nat.natToBits(b)) }; + case _ null + } + + }; + +} diff --git a/test/perf/qr/option.mo b/test/perf/qr/option.mo new file mode 100644 index 00000000000..c5e04c8b606 --- /dev/null +++ b/test/perf/qr/option.mo @@ -0,0 +1,139 @@ +/** +[#mod-Option] += `Option` -- Optional values +*/ + +import P "prelude"; + +module { + +/** +Returns true if the argument is not `null`. +*/ +public let isSome : ?Any -> Bool = func(x) = + switch x { + case null false; + case _ true; + }; + +/** +Returns true if the argument is `null`. +*/ +public let isNull : ?Any -> Bool = func(x) = + switch x { + case null true; + case _ false; + }; + +/** +Unwraps an optional value, with a default value, i.e. `unwrap(?x, d) = x` and `unwrap(null, d) = d`. +*/ +public let unwrapOr : (?T, default : T) -> T = + func (x: ?T, d: T): T = + switch x { + case null { d }; + case (?x_) x_; + }; + +/** +Unwraps an optional value using a function, or returns the default, i.e. `option(?x, f, d) = f x` and `option(null, f, d) = d`. +*/ +public let option : (?A, f : A -> B, default : B) -> B = + func(x: ?A, f: A->B, d: B): B = + switch x { + case null { d }; + case (?x_) f(x_); + }; + +/** +Applies a function to the wrapped value. +*/ +public let map : (f: A->B, x: ?A) -> ?B = + func map(f: A->B, x: ?A): ?B = + switch x { + case null null; + case (?x_) ?f(x_); + }; + +/** +Applies an optional function to an optional value. Returns `null` if at least one of the arguments is `null`. +*/ +public let apply : (?(A -> B), ?A) -> ?B = + func (f : ?(A -> B), x : ?A) : ?B { + switch (f, x) { + case (?f_, ?x_) { + ?f_(x_); + }; + case (_, _) { + null; + }; + }; + }; + +/** +Applies an function to an optional value. Returns `null` if the argument is `null`, or the function returns `null`. + +NOTE: Together with <>, this forms a “monad”. +*/ +public let bind : (?A, A -> ?B) -> ?B = + func(x : ?A, f : A -> ?B) : ?B { + switch(x) { + case (?x_) { + f(x_); + }; + case (null) { + null; + }; + }; + }; + +/** +Given an optional optional value, removes one layer of optionality. +*/ +public let join : ??A -> ?A = + func(x : ??A) : ?A { + bind(x, func (x_ : ?A) : ?A { + x_; + }); + }; + +/** +Creates an optional value from a definite value. +*/ +public let pure : A -> ?A = + func (x: A) : ?A = ?x; + +/** +Asserts that the value is not `null`; fails otherwise. +*/ +public let assertSome : ?Any -> () = + func(x) = + switch x { + case null { P.unreachable() }; + case _ {}; + }; + +/** +Asserts that the value _is_ `null`; fails otherwise. +*/ +public let assertNull : ?Any -> () = + func(x) = + switch x { + case null { }; + case _ { P.unreachable() }; + }; + +/** +Unwraps an optional value, i.e. `unwrap(?x) = x`. + +WARNING: `unwrap(x)` will fail if the argument is `null`, and is generally considered bad style. Use `switch x` instead. +*/ +public let unwrap : ?T -> T = + func(x: ?T): T = + switch x { + case null { P.unreachable() }; + case (?x_) x_; + }; + + +} diff --git a/test/perf/qr/prelude.mo b/test/perf/qr/prelude.mo new file mode 100644 index 00000000000..ef5592d0f49 --- /dev/null +++ b/test/perf/qr/prelude.mo @@ -0,0 +1,62 @@ +/** +[#mod-Prelude] += `Prelude` -- General utilities +*/ + +import Prim "mo:prim"; + +module { +/* + +Stdlib prelude +=============== + + This prelude file proposes standard library features that _may_ +belong in the _language_ (compiler-internal) prelude sometime, after +some further experience and discussion. Until then, they live here. + +*/ + +/* + + `printLn` + --------- + + Print text followed by a newline. + +*/ +public func printLn(x : Text) { + Prim.debugPrint(x # "\n"); +}; + +/* + + `nyi`: Not yet implemented + ----------------------------- + + Mark incomplete code with the `nyi` and `xxx` functions. + + Each have calls are well-typed in all typing contexts, which +trap in all execution contexts. + +*/ + +public func nyi() : None = + { assert false ; loop { } }; + +public func xxx() : None = + { assert false ; loop { } }; + +/* + + `unreachable` + -------------------- + + Mark unreachable code with the `unreachable` function. + + Calls are well-typed in all typing contexts, and they + trap in all execution contexts. + +*/ +public func unreachable() : None = { assert false ; loop { } }; +} diff --git a/test/perf/qr/symbol.mo b/test/perf/qr/symbol.mo new file mode 100644 index 00000000000..f91adf18a11 --- /dev/null +++ b/test/perf/qr/symbol.mo @@ -0,0 +1,423 @@ +/** + * Module : symbol.mo + * Copyright : 2020 DFINITY Stiftung + * License : Apache 2.0 with LLVM Exception + * Maintainer : Enzo Haussecker + * Stability : stable + */ + +import Array "array"; +import Common "common"; +import Format "format"; +import Iter "iter"; +import List "list"; +import Nat "nat"; +import Util "util"; +import Version "version"; + +module { + + type Coordinate = (Nat, Nat); + type ErrorCorrection = Common.ErrorCorrection; + type List = List.List; + type Version = Version.Version; + + public func symbolize( + version : Version, + data : List + ) : [var [var Bool]] { + applyAlignments(version, + applyHardcode(version, + applyTimings(version, + applyFinders(version, + applyData(version, data,init(version)))))) + }; + + func init(version : Version) : [var [var Bool]] { + let w = Common.width(version); + let matrix = Array.init<[var Bool]>(w, [var]); + for (i in Iter.range(0, w - 1)) { + matrix[i] := Array.init(w, false) + }; + matrix + }; + + func apply( + setters : List<(Coordinate, Bool)>, + matrix : [var [var Bool]] + ) : [var [var Bool]] { + List.iter<(Coordinate, Bool)>(setters, func (setter) { + let i = setter.0.0; + let j = setter.0.1; + matrix[i][j] := setter.1 + }); + matrix + }; + + public func freeze(matrix : [var [var Bool]]) : [[Bool]] { + Array.map<[var Bool], [Bool]>( + func (row) { Array.freeze(row) }, + Array.freeze<[var Bool]>(matrix) + ) + }; + + func applyFinders( + version : Version, + matrix : [var [var Bool]] + ) : [var [var Bool]] { + apply(finders(version), matrix) + }; + + func finders(version : Version) : List<(Coordinate, Bool)> { + List.concat<(Coordinate, Bool)>(List.fromArray>([ + finderTL(version), + finderTR(version), + finderBL(version) + ])) + }; + + func finderCoords(version : Version) : List { + List.concat(List.fromArray>([ + finderTLCoords(version), + finderTRCoords(version), + finderBLCoords(version) + ])) + }; + + func finderTL(version : Version) : List<(Coordinate, Bool)> { + let coords = finderTLCoords(version); + let pattern = Util.padLeftTo(64, Nat.natToBits(18339425943761911296)); + List.zip(coords, pattern) + }; + + func finderTLCoords(version : Version) : List { + let w = Common.width(version); + let v = w - 8; + var coords = List.nil(); + for (i in Iter.range(v, w - 1)) { + for (j in Iter.range(v, w - 1)) { + coords := List.push((i, j), coords) + } + }; + coords + }; + + func finderTR(version : Version) : List<(Coordinate, Bool)> { + let coords = finderTRCoords(version); + let pattern = Util.padLeftTo(64, Nat.natToBits(9169712971880955648)); + List.zip(coords, pattern) + }; + + func finderTRCoords(version : Version) : List { + let w = Common.width(version); + let r = w - 8; + var coords = List.nil(); + for (i in Iter.range(r, w - 1)) { + for (j in Iter.range(0, 7)) { + coords := List.push((i, j), coords) + } + }; + coords + }; + + func finderBL(version : Version) : List<(Coordinate, Bool)> { + let coords = finderBLCoords(version); + let pattern = Util.padLeftTo(64, Nat.natToBits(71638382592819966)); + List.zip(coords, pattern) + }; + + func finderBLCoords(version : Version) : List { + let w = Common.width(version); + let c = w - 8; + var coords = List.nil(); + for (i in Iter.range(0, 7)) { + for (j in Iter.range(c, w - 1)) { + coords := List.push((i, j), coords) + } + }; + coords + }; + + func applyTimings( + version : Version, + matrix : [var [var Bool]] + ) : [var [var Bool]] { + apply(timings(version), matrix) + }; + + func timings(version : Version) : List<(Coordinate, Bool)> { + List.append<(Coordinate, Bool)>(timingH(version), timingV(version)) + }; + + func timingCoords(version : Version) : List { + List.append(timingHCoords(version), timingVCoords(version)) + }; + + func timingH(version : Version) : List<(Coordinate, Bool)> { + let w = Common.width(version); + let coords = timingHCoords(version); + let pattern = List.tabulate(w - 16, func (n) { n % 2 == 0 }); + List.zip(coords, pattern) + }; + + func timingHCoords(version : Version) : List { + let w = Common.width(version); + let r = w - 7; + var coords = List.nil(); + for (j in Iter.range(8, w - 9)) { + coords := List.push((r, j), coords) + }; + coords + }; + + func timingV(version : Version) : List<(Coordinate, Bool)> { + let w = Common.width(version); + let coords = timingVCoords(version); + let pattern = List.tabulate(w - 16, func (n) { n % 2 == 0 }); + List.zip(coords, pattern) + }; + + func timingVCoords(version : Version) : List { + let coords = timingHCoords(version); + List.map(coords, func (a, b) { (b, a) }) + }; + + func applyHardcode( + version : Version, + matrix : [var [var Bool]] + ) : [var [var Bool]] { + apply(hardcode(version), matrix) + }; + + func hardcode(version : Version) : List<(Coordinate, Bool)> { + let coords = hardcodeCoords(version); + let pattern = List.singleton(true); + List.zip(coords, pattern) + }; + + func hardcodeCoords(version : Version) : List { + let w = Common.width(version); + let c = w - 9; + List.singleton((7, c)) + }; + + public func applyFormats( + version : Version, + level : ErrorCorrection, + mask : List, + matrix : [var [var Bool]] + ) : [var [var Bool]] { + apply(formats(version, level, mask), matrix) + }; + + func formats( + version : Version, + level : ErrorCorrection, + mask : List + ) : List<(Coordinate, Bool)> { + let coords = formatCoords(version); + let pattern = Format.encode(level, mask); + let cycles = List.append(pattern, pattern); + List.zip(coords, cycles) + }; + + func formatCoords(version : Version) : List { + List.append(formatHCoords(version), formatVCoords(version)) + }; + + func formatHCoords(version : Version) : List { + let w = Common.width(version); + let r = w - 9; + let c = w - 8; + var coords = List.nil(); + for (j in Iter.range(0, 7)) { + coords := List.push((r, j), coords) + }; + for (j in Iter.range(c, c)) { + coords := List.push((r, j), coords) + }; + for (j in Iter.range(c + 2, w - 1)) { + coords := List.push((r, j), coords) + }; + coords + }; + + func formatVCoords(version : Version) : List { + let w = Common.width(version); + let c = w - 9; + var coords = List.nil(); + for (i in Iter.range(0, 6)) { + coords := List.push((i, c), coords) + }; + for (i in Iter.range(w - 9, w - 8)) { + coords := List.push((i, c), coords) + }; + for (i in Iter.range(w - 6, w - 1)) { + coords := List.push((i, c), coords) + }; + List.rev(coords) + }; + + public func applyVersions( + version : Version, + matrix : [var [var Bool]] + ) : [var [var Bool]] { + apply(versions(version), matrix) + }; + + func versions(version : Version) : List<(Coordinate, Bool)> { + let coords = versionCoords(version); + let pattern = Version.encode(version); + let cycles = List.append(pattern, pattern); + List.zip(coords, cycles) + }; + + func versionCoords(version : Version) : List { + List.append(versionTRCoords(version), versionBLCoords(version)) + }; + + func versionTRCoords(version : Version) : List { + if (Version.unbox(version) < 7) { + List.nil() + } else { + func go(n : Nat, a : Nat, b : Nat) : List { + let idxs = Iter.toList(Iter.range(a, b)); + List.concat(List.replicate>(n, idxs)) + }; + let w = Common.width(version); + List.zip(go(3, w - 6, w - 1), go(5, 8, 10)) + } + }; + + func versionBLCoords(version : Version) : List { + let coords = versionTRCoords(version); + List.map(coords, func (a, b) { (b, a) }) + }; + + func applyAlignments( + version : Version, + matrix : [var [var Bool]] + ) : [var [var Bool]] { + apply(alignment(version), matrix) + }; + + func alignment(version : Version) : List<(Coordinate, Bool)> { + let n = Common.alignments(version).len() ** 2; + let m = if (n < 4) 0 else n - 3; + let coords = alignmentCoords(version); + let pattern = Nat.natToBits(33084991); + let cycles = List.concat(List.replicate>(m, pattern)); + List.zip(coords, cycles) + }; + + func alignmentCoords(version : Version) : List { + + let alignments = Common.alignments(version); + if (alignments.len() == 0) { + List.nil() + } else { + + let a = alignments[0]; + let b = alignments[alignments.len() - 1]; + let reserved = List.fromArray([(a, b), (b, a), (b, b)]); + func isReserved(r : Nat, c : Nat) : Bool { + List.exists(reserved, func (x, y) { + (x == r) and (y == c) + }) + }; + + var coords = List.nil(); + for (r in Iter.fromArray(alignments)) { + for (c in Iter.fromArray(alignments)) { + if (not isReserved(r, c)) { + for (i in Iter.range(r - 2, r + 2)) { + for (j in Iter.range(c - 2, c + 2)) { + coords := List.push((i, j), coords) + } + } + } + } + }; + coords + } + }; + + func applyData( + version : Version, + data : List, + matrix : [var [var Bool]] + ) : [var [var Bool]] { + apply(path(version, data), matrix) + }; + + func path(version : Version, data : List) : List<(Coordinate, Bool)> { + let coords = pathCoords(version); + List.zip(coords, data) + }; + + public func pathCoords(version : Version) : List { + List.foldLeft>( + patternCoords(version), + traceCoords(version), + func ((r, c), coords) { + List.filter(coords, func (x, y) { + not ((x == r) and (y == c)) + }) + } + ) + }; + + func patternCoords(version : Version) : List { + List.concat(List.fromArray>([ + finderCoords(version), + timingCoords(version), + hardcodeCoords(version), + formatCoords(version), + versionCoords(version), + alignmentCoords(version) + ])) + }; + + func traceCoords(version : Version) : List { + + let w = Common.width(version); + let t = w - 7; + + let up = List.concat(List.map>( + Iter.toList(Iter.range(0, w - 1)), + func (i) { List.replicate(2, i) } + )); + let down = List.rev(up); + + func rowwise(n : Nat, idxs : List) : List { + List.concat(List.replicate>(n * w, idxs)) + }; + + func columnwise(idxs : List) : List { + List.concat( + List.concat>( + List.map, List>>( + List.chunksOf(2, idxs), + func (chunk) { + List.replicate>(w, chunk) + } + ) + ) + ) + }; + + let rows1 = rowwise(w - t, List.append(up, down)); + let rows2 = rowwise(6, List.append(down, up)); + + let cols1 = columnwise(Iter.toList(Iter.range(0, t - 1))); + let cols2 = columnwise(Iter.toList(Iter.range(t + 1, w - 1))); + + let coords = List.append( + List.zip(rows1, cols1), + List.zip(rows2, cols2) + ); + + List.filter(coords, func (x, _) { x != t }) + }; + +} diff --git a/test/perf/qr/text.mo b/test/perf/qr/text.mo new file mode 100644 index 00000000000..011c9c6e250 --- /dev/null +++ b/test/perf/qr/text.mo @@ -0,0 +1,24 @@ +/** +[#mod-Text] += `Text` -- Text values + +This type describes a valid, human-readable text. It does not contain arbitrary +binary data. +*/ + +import Iter "iter"; + +module { + + // remove? + public func append(x : Text, y : Text) : Text { + x # y; + }; + + /** + Creates an <> that traverses the characters of the text. + */ + public let toIter : Text -> Iter.Iter = + func(text) = text.chars() + +} diff --git a/test/perf/qr/trie.mo b/test/perf/qr/trie.mo new file mode 100644 index 00000000000..0b2a20c7d76 --- /dev/null +++ b/test/perf/qr/trie.mo @@ -0,0 +1,1472 @@ +/** +[#mod-Trie] += `Trie` -- Functional map +*/ + +import Prim "mo:prim"; +import P "prelude"; +import Option "option"; +import Hash "hash"; +import A "array"; + +import List "list"; +import AssocList "assocList"; + +module { +/* + +Hash tries +====================== + +Functional maps (and sets) whose representation is "canonical", and +history independent. + +Background +------------------ + +See this POPL 1989 paper (Section 6): + + - ["Incremental computation via function caching", Pugh & Teitelbaum](https://dl.acm.org/citation.cfm?id=75305). + - [Public copy here](http://matthewhammer.org/courses/csci7000-s17/readings/Pugh89.pdf). + +By contrast, other usual functional representations of maps (AVL +Trees, Red-Black Trees) do not enjoy history independence, and are +each more complex to implement (e.g., each requires "rebalancing"; +these trees never do). + +*/ + +/* +Representation +===================== + +A hash trie is a binary trie, where each (internal) branch node +represents having distinguished its key-value pairs on a single bit of +the keys. + +By following paths in the trie, we determine an increasingly smaller +and smaller subset of the keys. + +Each leaf node consists of an association list of key-value pairs. + +We say that a leaf is valid if it contains no more than MAX_LEAF_COUNT +key-value pairs. + +Each non-empty trie node stores a count; we discuss that more below. + +### Adaptive depth + +For small mappings, this "trie" structure just consists of a single +leaf, which contains up to MAX_LEAF_COUNT key-value pairs. + +By construction, the algorithms below enforce the invariant that no +leaf ever contains more than MAX_LEAF_COUNT key-value pairs: the +function `leaf` accepts a list, but subdivides it with branches until +it can actually construct valid leaves. Ongce distinguished, subsets +of keys tend to remain distinguished by the presence of these branches. + +### Cached counts + +At each branch and leaf, we use a stored count to support a +memory-efficient `toArray` function, which itself relies on +per-element projection via `nth`; in turn, `nth` directly uses the +O(1)-time function `count` for achieving an acceptable level of +algorithmic efficiently. Notably, leaves are generally lists of +key-value pairs, and we do not store a count for each Cons cell in the +list. + + +### Details + +Below, we define the types used in the representation: + +*/ + +//let MAX_LEAF_COUNT = 4; // worse than 8, slightly +public let MAX_LEAF_COUNT = 8; // <-- beats both 4 and 16 for me, now +//let MAX_LEAF_COUNT = 16; +//let MAX_LEAF_COUNT = 32; + +public type List = List.List; +public type AssocList = AssocList.AssocList; + +/* A `Key` for the trie has an associated hash value */ +public type Key = { + /* `hash` permits fast inequality checks, and permits collisions */ + hash: Hash.Hash; + /* `key` permits percise equality checks, but only used after equal hashes. */ + key: K; +}; + +/* Equality function for two `Key`s, in terms of equality of `K`'s. */ +public func keyEq(keq:(K,K) -> Bool) : ((Key,Key) -> Bool) = { + func (key1:Key, key2:Key) : Bool = + label profile_trie_keyEq : Bool + (Hash.hashEq(key1.hash, key2.hash) and keq(key1.key, key2.key)) +}; + +/* leaf nodes of trie consist of key-value pairs as a list. */ +public type Leaf = { + count : Nat ; + keyvals : AssocList,V> ; +}; + +/* branch nodes of the trie discriminate on a bit position of the keys' hashes. + we never store this bitpos; rather, + we enforce a style where this position is always known from context. +*/ +public type Branch = { + count : Nat ; + left : Trie ; + right : Trie ; +}; + +/* binary hash tries: either empty, a leaf node, or a branch node */ +public type Trie = { + #empty ; + #leaf : Leaf ; + #branch : Branch ; +}; + +public func isValid (t:Trie, enforceNormal:Bool) : Bool { + func rec(t:Trie, bitpos:?Hash.Hash, bits:Hash.Hash, mask:Hash.Hash) : Bool { + switch t { + case (#empty) { + switch bitpos { + case null true; + case (?_) not enforceNormal; + } + }; + case (#leaf l) { + let len = List.len<(Key,V)>(l.keyvals); + ((len <= MAX_LEAF_COUNT) or (not enforceNormal)) + and + len == l.count + and + ( List.all<(Key,V)>( + l.keyvals, + func ((k:Key,v:V)):Bool{ + //{ Prim.debugPrint "testing hash..."; true } + //and + ((k.hash & mask) == bits) + or + { Prim.debugPrint "\nmalformed hash!:\n"; + Prim.debugPrintInt (Prim.word32ToNat(k.hash)); + Prim.debugPrint "\n (key hash) != (path bits): \n"; + Prim.debugPrintInt (Prim.word32ToNat(bits)); + Prim.debugPrint "\nmask : "; Prim.debugPrintInt (Prim.word32ToNat(mask)); + Prim.debugPrint "\n"; + false } + } + ) or + { Prim.debugPrint "one or more hashes are malformed"; false } + ) + }; + case (#branch b) { + let bitpos1 = switch bitpos { + case null (Prim.natToWord32(0)); + case (?bp) (Prim.natToWord32(Prim.word32ToNat(bp) + 1)) + }; + let mask1 = mask | (Prim.natToWord32(1) << bitpos1); + let bits1 = bits | (Prim.natToWord32(1) << bitpos1); + let sum = count(b.left) + count(b.right); + (b.count == sum or { Prim.debugPrint "malformed count"; false }) + and + rec(b.left, ?bitpos1, bits, mask1) + and + rec(b.right, ?bitpos1, bits1, mask1) + }; + } + }; + rec(t, null, 0, 0) +}; + + +/* + Two-dimensional trie + --------------------- + A 2D trie is just a trie that maps dimension-1 keys to another + layer of tries, each keyed on the dimension-2 keys. +*/ +public type Trie2D = Trie >; + +/* + Three-dimensional trie + --------------------- + A 3D trie is just a trie that maps dimension-1 keys to another + layer of 2D tries, each keyed on the dimension-2 and dimension-3 keys. +*/ +public type Trie3D = Trie >; + +/* + Module interface + =================== + */ + + /* + `empty` + -------- + An empty trie. + */ +public func empty() : Trie = + #empty; + + /* + `count` + -------- + Get the number of key-value pairs in the trie, in constant time. + + ### Implementation notes + + `nth` directly uses this function `count` for achieving an + acceptable level of algorithmic efficiently. + + */ +public func count(t: Trie) : Nat = label profile_trie_count : Nat { + switch t { + case (#empty) 0; + case (#leaf l) l.count; + case (#branch b) b.count; + } + }; + + /* + `branch` + -------- + Construct a branch node, computing the count stored there. + */ +public func branch(l:Trie, r:Trie) : Trie = label profile_trie_branch : Trie { + let sum = count(l) + count(r); + #branch( + { + count=sum; + left=l; + right=r + } + ); + }; + + /* + `leaf` + -------- + Construct a leaf node, computing the count stored there. + + This helper function automatically enforces the MAX_LEAF_COUNT + by constructing branches as necessary; to do so, it also needs the bitpos + of the leaf. + + */ +public func leaf(kvs:AssocList,V>, bitpos:Nat) : Trie = label trie_leaf : Trie { + fromSizedList(null, kvs, bitpos) + }; + +public func fromList(kvs:AssocList,V>, bitpos:Nat) : Trie = + label profile_trie_fromList_begin : (Trie) { + func rec(kvs:AssocList,V>, bitpos:Nat) : Trie { + if ( List.isNil<(Key,V)>(kvs) ) + label profile_trie_fromList_end_empty : (Trie) { + #empty + } + else if ( List.lenIsEqLessThan<(Key,V)>(kvs, MAX_LEAF_COUNT - 1) ) + label profile_trie_fromList_end_validleaf : (Trie) { + let len = List.len<(Key,V)>(kvs); + #leaf{count=len;keyvals=kvs} + } + else if ( bitpos >= 31 ) + label profile_trie_fromList_end_bitposIs31 : (Trie) { + let len = List.len<(Key,V)>(kvs); + #leaf{count=len;keyvals=kvs} + } + else /* too many keys for a leaf, so introduce a branch */ + label profile_trie_fromList_branch : (Trie) { + let (l, r) = splitAssocList(kvs, bitpos); + branch(rec(l, bitpos + 1), rec(r, bitpos + 1)) + } + }; + rec(kvs, bitpos) + }; + + +public func fromSizedList(kvc:?Nat, kvs:AssocList,V>, bitpos:Nat) : Trie = + label profile_trie_fromList_begin : (Trie) { + func rec(kvc:?Nat, kvs:AssocList,V>, bitpos:Nat) : Trie { + switch kvc { + case null { + switch (List.lenClamp<(Key,V)>(kvs, MAX_LEAF_COUNT)) { + case null () /* fall through to branch case. */; + case (?len) { + return #leaf{count=len; keyvals=kvs} + }; + } + }; + case (?c) { + if ( c == 0 ) { + return #empty + } else if ( c <= MAX_LEAF_COUNT ) { + return #leaf{count=c; keyvals=kvs} + } else { + /* fall through to branch case */ + } + }; + }; + let (ls, l, rs, r) = splitSizedList(kvs, bitpos); + if ( ls == 0 and rs == 0 ) { + #empty + } else if (rs == 0 and ls <= MAX_LEAF_COUNT) { + #leaf{count=ls; keyvals=l} + } else if (ls == 0 and rs <= MAX_LEAF_COUNT) { + #leaf{count=rs; keyvals=r} + } else { + branch(rec(?ls, l, bitpos + 1), rec(?rs, r, bitpos + 1)) + } + }; + rec(kvc, kvs, bitpos) + }; + + /* + `copy` + --------- + Purely-functional representation permits _O(1)_-time copy, via persistent sharing. + */ +public func copy(t : Trie) : Trie = t; + + /* + `replace` + --------- + replace the given key's value option with the given one, returning the previous one + */ +public func replace(t : Trie, k:Key, k_eq:(K,K)->Bool, v:?V) : (Trie, ?V) = + label profile_trie_replace : (Trie, ?V) { + let key_eq = keyEq(k_eq); + + func rec(t : Trie, bitpos:Nat) : (Trie, ?V) = + label profile_trie_replace_rec : (Trie, ?V) { + switch t { + case (#empty) label profile_trie_replace_rec_empty : (Trie, ?V) { + let (kvs, _) = AssocList.replace,V>(null, k, key_eq, v); + (leaf(kvs, bitpos), null) + }; + case (#branch b) label profile_trie_replace_rec_branch : (Trie, ?V) { + let bit = Hash.getHashBit(k.hash, bitpos); + // rebuild either the left or right path with the inserted (k,v) pair + if (not bit) { + let (l, v_) = rec(b.left, bitpos+1); + (branch(l, b.right), v_) + } + else { + let (r, v_) = rec(b.right, bitpos+1); + (branch(b.left, r), v_) + } + }; + case (#leaf l) label profile_trie_replace_rec_leaf : (Trie, ?V) { + let (kvs2, old_val) = + AssocList.replace,V>(l.keyvals, k, key_eq, v); + (leaf(kvs2, bitpos), old_val) + }; + } + }; + let (to, vo) = rec(t, 0); + //assert(isValid(to, false)); + (to, vo) + }; + + /* + `insert` + ------------ + insert the given key's value in the trie; return the new trie, and the previous value associated with the key, if any + */ +public func insert(t : Trie, k:Key, k_eq:(K,K)->Bool, v:V) : (Trie, ?V) = + label profile_trie_insert : (Trie, ?V) { + replace(t, k, k_eq, ?v) + }; + +/* + `find` + --------- + find the given key's value in the trie, or return null if nonexistent + */ +public func find(t : Trie, k:Key, k_eq:(K,K) -> Bool) : ?V = label profile_trie_find : (?V) { + let key_eq = keyEq(k_eq); + func rec(t : Trie, bitpos:Nat) : ?V = label profile_trie_find_rec : (?V) { + switch t { + case (#empty) { + label profile_trie_find_end_null : (?V) + null + }; + case (#leaf l) { + label profile_trie_find_end_assocList_find : (?V) + AssocList.find,V>(l.keyvals, k, key_eq) + }; + case (#branch b) { + let bit = Hash.getHashBit(k.hash, bitpos); + if (not bit) { + label profile_trie_find_branch_left : (?V) + rec(b.left, bitpos+1) + } + else { + label profile_trie_find_branch_right : (?V) + rec(b.right, bitpos+1) + } + }; + } + }; + rec(t, 0) + }; + + + + +public func splitAssocList(al:AssocList,V>, bitpos:Nat) + : (AssocList,V>, AssocList,V>) = + label profile_trie_splitAssocList : (AssocList,V>, AssocList,V>) + { + List.split<(Key,V)>( + al, + func ((k : Key, v : V)) : Bool { + not Hash.getHashBit(k.hash, bitpos) + } + ) + }; + +public func splitSizedList(l:AssocList,V>, bitpos:Nat) + : (Nat, AssocList,V>, Nat, AssocList,V>) = + label profile_trie_splitSizedList : (Nat, AssocList,V>, Nat, AssocList,V>) + { + func rec(l : AssocList,V>) : (Nat, AssocList,V>, Nat, AssocList,V>) = + label profile_trie_sized_split_rec : (Nat, AssocList,V>, Nat, AssocList,V>) { + switch l { + case null { (0, null, 0, null) }; + case (?((k,v),t)) { + let (cl, l, cr, r) = rec(t) ; + if (not Hash.getHashBit(k.hash, bitpos)){ + (cl + 1, ?((k,v),l), cr, r) + } else { + (cl, l, cr + 1, ?((k,v),r)) + } + }; + } + }; + rec(l) + }; + + /* + `merge` + --------- + merge tries, preferring the right trie where there are collisions + in common keys. note: the `disj` operation generalizes this `merge` + operation in various ways, and does not (in general) lose + information; this operation is a simpler, special case. + + See also: + + - [`disj`](#disj) + - [`join`](#join) + - [`prod`](#prod) + + */ +public func merge(tl:Trie, tr:Trie, k_eq:(K,K)->Bool) : Trie = label profile_trie_merge : Trie { + let key_eq = keyEq(k_eq); + func br(l:Trie, r:Trie) : Trie = branch(l,r); + func rec(bitpos:Nat, tl:Trie, tr:Trie) : Trie { + func lf(kvs:AssocList,V>) : Trie = leaf(kvs, bitpos); + switch (tl, tr) { + case (#empty, _) { return tr }; + case (_, #empty) { return tl }; + case (#leaf l1, #leaf l2) { + lf( + AssocList.disj,V,V,V>( + l1.keyvals, l2.keyvals, + key_eq, + func (x:?V, y:?V):V = { + switch (x, y) { + case (null, null) { P.unreachable() }; + case (null, ?v) v; + case (?v, _) v; + }} + ) + ) + }; + case (#leaf l, _) { + let (ll, lr) = splitAssocList(l.keyvals, bitpos); + rec(bitpos, br(lf ll, lf lr), tr) + }; + case (_, #leaf l) { + let (ll, lr) = splitAssocList(l.keyvals, bitpos); + rec(bitpos, tl, br(lf ll, lf lr)) + }; + case (#branch b1, #branch b2) { + br(rec(bitpos + 1, b1.left, b2.left), + rec(bitpos + 1, b1.right, b2.right)) + }; + } + }; + rec(0, tl, tr) + }; + + /* + `mergeDisjoint` + ---------------- + like `merge`, it merges tries, but unlike `merge`, it signals a + dynamic error if there are collisions in common keys between the + left and right inputs. + */ +public func mergeDisjoint(tl:Trie, tr:Trie, k_eq:(K,K)->Bool): Trie = + label profile_trie_mergeDisjoint : Trie { + let key_eq = keyEq(k_eq); + func br(l:Trie, r:Trie) : Trie = branch(l,r); + func rec(bitpos:Nat, tl:Trie, tr:Trie) : Trie = label profile_trie_mergeDisjoint_rec : Trie { + func lf(kvs:AssocList,V>) : Trie = leaf(kvs, bitpos); + switch (tl, tr) { + case (#empty, _) label profile_trie_mergeDisjoint_rec_emptyL : Trie { return tr }; + case (_, #empty) label profile_trie_mergeDisjoint_rec_emptyR : Trie { return tl }; + case (#leaf l1, #leaf l2) label profile_trie_mergeDisjoint_rec_leafPair : Trie { + lf( + AssocList.disjDisjoint,V,V,V>( + l1.keyvals, l2.keyvals, + func (x:?V, y:?V):V = { + switch (x, y) { + case (null, ?v) v; + case (?v, null) v; + case (_, _) P.unreachable(); + } + } + ) + ) + }; + case (#leaf l, _) label profile_trie_mergeDisjoint_rec_splitLeafL : Trie { + let (ll, lr) = splitAssocList(l.keyvals, bitpos); + rec(bitpos, br(lf ll, lf lr), tr) + }; + case (_, #leaf l) label profile_trie_mergeDisjoint_rec_splitLeafR : Trie { + let (ll, lr) = splitAssocList(l.keyvals, bitpos); + rec(bitpos, tl, br(lf ll, lf lr)) + }; + case (#branch b1, #branch b2) label profile_trie_mergeDisjoint_rec_branchPair : Trie { + branch( + rec(bitpos + 1, b1.left, b2.left), + rec(bitpos + 1, b1.right, b2.right) + ) + }; + + } + }; + rec(0, tl, tr) + }; + + /* + `diff` + ------ + The key-value pairs of the final trie consists of those pairs of + the left trie whose keys are not present in the right trie; the + values of the right trie are irrelevant. + */ +public func diff(tl:Trie, tr:Trie, k_eq:(K,K)->Bool): Trie { + let key_eq = keyEq(k_eq); + + func br1(l:Trie, r:Trie) : Trie = branch(l,r); + func br2(l:Trie, r:Trie) : Trie = branch(l,r); + + func rec(bitpos:Nat, tl:Trie, tr:Trie) : Trie { + func lf1(kvs:AssocList,V>) : Trie = leaf(kvs, bitpos); + func lf2(kvs:AssocList,W>) : Trie = leaf(kvs, bitpos); + + switch (tl, tr) { + case (#empty, _) { return #empty }; + case (_, #empty) { return tl }; + case (#leaf l1, #leaf l2) { + lf1( + AssocList.diff,V,W>( + l1.keyvals, l2.keyvals, + key_eq, + ) + ) + }; + case (#leaf l, _) { + let (ll, lr) = splitAssocList(l.keyvals, bitpos); + rec(bitpos, br1(lf1 ll, lf1 lr), tr) + }; + case (_, #leaf l) { + let (ll, lr) = splitAssocList(l.keyvals, bitpos); + rec(bitpos, tl, br2(lf2 ll, lf2 lr)) + }; + case (#branch b1, #branch b2) { + br1(rec(bitpos + 1, b1.left, b2.left), + rec(bitpos + 1, b1.right, b2.right)) + }; + } + }; + rec(0, tl, tr) + }; + + /* + `disj` + -------- + + This operation generalizes the notion of "set union" to finite maps. + + Produces a "disjunctive image" of the two tries, where the values of + matching keys are combined with the given binary operator. + + For unmatched key-value pairs, the operator is still applied to + create the value in the image. To accomodate these various + situations, the operator accepts optional values, but is never + applied to (null, null). + + Implements the database idea of an ["outer join"](https://stackoverflow.com/questions/38549/what-is-the-difference-between-inner-join-and-outer-join). + + See also: + + - [`join`](#join) + - [`merge`](#merge) + - [`prod`](#prod) + + */ +public func disj( + tl : Trie, + tr : Trie, + k_eq : (K,K)->Bool, + vbin : (?V,?W)->X + ) + : Trie + { + let key_eq = keyEq(k_eq); + + func br1(l:Trie, r:Trie) : Trie = branch(l,r); + func br2(l:Trie, r:Trie) : Trie = branch(l,r); + + func br3(l:Trie, r:Trie) : Trie = branch(l,r); + func lf3(kvs:AssocList,X>, bitpos:Nat) : Trie = leaf(kvs, bitpos); + + /* empty right case; build from left only: */ + func recL(t:Trie, bitpos:Nat) : Trie { + switch t { + case (#empty) #empty; + case (#leaf l) { + lf3(AssocList.disj,V,W,X>(l.keyvals, null, key_eq, vbin), bitpos) + }; + case (#branch(b)) { br3(recL(b.left,bitpos+1),recL(b.right,bitpos+1)) }; + } + }; + /* empty left case; build from right only: */ + func recR(t:Trie, bitpos:Nat) : Trie { + switch t { + case (#empty) #empty; + case (#leaf l) { + lf3(AssocList.disj,V,W,X>(null, l.keyvals, key_eq, vbin), bitpos) + }; + case (#branch(b)) { br3(recR(b.left,bitpos+1),recR(b.right,bitpos+1)) }; + } + }; + + /* main recursion */ + func rec(bitpos:Nat, tl:Trie, tr:Trie) : Trie { + func lf1(kvs:AssocList,V>) : Trie = leaf(kvs, bitpos); + func lf2(kvs:AssocList,W>) : Trie = leaf(kvs, bitpos); + switch (tl, tr) { + case (#empty, #empty) { #empty }; + case (#empty, _ ) { recR(tr, bitpos) }; + case (_, #empty) { recL(tl, bitpos) }; + case (#leaf l1, #leaf l2) { + lf3(AssocList.disj,V,W,X>(l1.keyvals, l2.keyvals, key_eq, vbin), bitpos) + }; + case (#leaf l, _) { + let (ll, lr) = splitAssocList(l.keyvals, bitpos); + rec(bitpos, br1(lf1 ll, lf1 lr), tr) + }; + case (_, #leaf l) { + let (ll, lr) = splitAssocList(l.keyvals, bitpos); + rec(bitpos, tl, br2(lf2 ll, lf2 lr)) + }; + case (#branch b1, #branch b2) { + br3(rec(bitpos + 1, b1.left, b2.left), + rec(bitpos + 1, b1.right, b2.right)) + }; + + } + }; + + rec(0, tl, tr) + }; + + /* + `join` + --------- + This operation generalizes the notion of "set intersection" to + finite maps. Produces a "conjuctive image" of the two tries, where + the values of matching keys are combined with the given binary + operator, and unmatched key-value pairs are not present in the output. + + Implements the database idea of an ["inner join"](https://stackoverflow.com/questions/38549/what-is-the-difference-between-inner-join-and-outer-join). + + See also: + + - [`disj`](#disj) + - [`merge`](#merge) + - [`prod`](#prod) + + */ + public func join(tl:Trie, tr:Trie, + k_eq:(K,K)->Bool, vbin:(V,W)->X) + : Trie = label profile_trie_join : Trie + { + let key_eq = keyEq(k_eq); + + func br1(l:Trie, r:Trie) : Trie = branch(l,r); + func br2(l:Trie, r:Trie) : Trie = branch(l,r); + func br3(l:Trie, r:Trie) : Trie = branch(l,r); + + func rec(bitpos:Nat, tl:Trie, tr:Trie) : Trie = label profile_trie_join_rec : Trie { + func lf1(kvs:AssocList,V>) : Trie = leaf(kvs, bitpos); + func lf2(kvs:AssocList,W>) : Trie = leaf(kvs, bitpos); + func lf3(kvs:AssocList,X>) : Trie = leaf(kvs, bitpos); + + switch (tl, tr) { + case (#empty, _) { #empty }; + case (_, #empty) { #empty }; + case (#leaf l1, #leaf l2) { + lf3(AssocList.join,V,W,X>(l1.keyvals, l2.keyvals, key_eq, vbin)) + }; + case (#leaf l, _) { + let (ll, lr) = splitAssocList(l.keyvals, bitpos); + rec(bitpos, br1(lf1 ll, lf1 lr), tr) + }; + case (_, #leaf l) { + let (ll, lr) = splitAssocList(l.keyvals, bitpos); + rec(bitpos, tl, br2(lf2 ll, lf2 lr)) + }; + case (#branch b1, #branch b2) { + br3(rec(bitpos + 1, b1.left, b2.left), + rec(bitpos + 1, b1.right, b2.right)) + }; + + } + }; + rec(0, tl, tr) + }; + + /* + `foldUp` + ------------ + This operation gives a recursor for the internal structure of + tries. Many common operations are instantiations of this function, + either as clients, or as hand-specialized versions (e.g., see map, + mapFilter, exists and forAll below). + */ + public func foldUp(t:Trie, bin:(X,X)->X, leaf:(K,V)->X, empty:X) : X { + func rec(t:Trie) : X { + switch t { + case (#empty) { empty }; + case (#leaf l) { + AssocList.fold,V,X>( + l.keyvals, empty, + func (k:Key, v:V, x:X):X = + bin(leaf(k.key,v),x) + ) + }; + case (#branch(b)) { bin(rec(b.left), rec(b.right)) }; + } + }; + rec(t) + }; + + + /* + `prod` + --------- + + Conditional _catesian product_, where the given + operation `op` _conditionally_ creates output elements in the + resulting trie. + + The keyed structure of the input tries are not relevant for this + operation: all pairs are considered, regardless of keys matching or + not. Moreover, the resulting trie may use keys that are unrelated to + these input keys. + + See also: + + - [`disj`](#disj) + - [`join`](#join) + - [`merge`](#merge) + + */ + public func prod( + tl :Trie, + tr :Trie, + op :(K1,V1,K2,V2) -> ?(Key,V3), + k3_eq :(K3,K3) -> Bool + ) + : Trie + { + /*- binary case: merge disjoint results: */ + func merge (a:Trie, b:Trie) : Trie = + mergeDisjoint(a, b, k3_eq); + + /*- "`foldUp` squared" (imagine two nested loops): */ + foldUp>( + tl, merge, + func (k1:K1, v1:V1) : Trie { + foldUp>( + tr, merge, + func (k2:K2, v2:V2) : Trie { + switch (op(k1, v1, k2, v2)) { + case null #empty; + case (?(k3, v3)) { (insert(#empty, k3, k3_eq, v3)).0 }; + } + }, + #empty + ) + }, + #empty + ) + }; + + + /* + Build: An ADT for "Trie Builds" + ======================================== + + This module provides optimized variants of normal tries, for + (much!) more efficient PX retailer queries. + + The central insight is that for (unmaterialized) query results, we + do not need to actually build any resulting trie of the resulting + data, but rather, just need a collection of what would be in that + trie. Since query results can be large (quadratic in the DB size!), + avoiding the construction of this trie provides a considerable savings. + + To get this savings, we use an ADT for the operations that _would_ build this trie, + if evaluated. This structure specializes a rope: a balanced tree representing a + sequence. It is only as balanced as the tries from which we generate + these build ASTs. They have no intrinsic balance properties of their + own. + + */ + public module Build { + + /* Commands for building tries. + + For PL academics: Imagine commands for the IMP imperative language, + but where global memory consists of a single (anonymous) global trie */ + public type TrieBuild = { + #skip ; + #insert : (K, ?Hash.Hash, V) ; + #seq : { + count : Nat ; + left : TrieBuild ; + right : TrieBuild ; + } ; + }; + + public func buildCount(tb:TrieBuild) : Nat = + label profile_trie_buildCount : Nat { + switch tb { + case (#skip) 0; + case (#insert(_, _, _)) 1; + case (#seq(seq)) seq.count; + } + }; + + public func buildSeq(l:TrieBuild, r:TrieBuild) : TrieBuild = + label profile_trie_buildSeq : TrieBuild { + let sum = buildCount(l) + buildCount(r); + #seq { count = sum; left = l; right = r } + }; + + /* + `prodBuild` + --------------- + + Like `prod`, except do not actually do the insert calls, just + record them, as a (binary tree) data structure, isomorphic to the + recursion of this function (which is balanced, in expectation). + + See also: + + - [`prod`](#prod) + + */ + public func prodBuild( + tl :Trie, + tr :Trie, + op :(K1,V1,K2,V2) -> ?(K3,V3), + k3_eq :(K3,K3) -> Bool + ) + : TrieBuild + { + func outer_bin (a:TrieBuild, + b:TrieBuild) + : TrieBuild = + label profile_trie_prodBuild_outer_seqOfBranch : TrieBuild { + buildSeq(a, b) + }; + + func inner_bin (a:TrieBuild, + b:TrieBuild) + : TrieBuild = + label profile_trie_prodBuild_inner_seqOfBranch : TrieBuild { + buildSeq(a, b) + }; + + /*- "`foldUp` squared" (imagine two nested loops): */ + foldUp>( + tl, outer_bin, + func (k1:K1, v1:V1) : TrieBuild { + foldUp>( + tr, inner_bin, + func (k2:K2, v2:V2) : TrieBuild { + switch (op(k1, v1, k2, v2)) { + case null #skip; + case (?(k3, v3)) { #insert(k3, null, v3) }; + } + }, + #skip + ) + }, + #skip + ) + }; + + /* + `buildNth` + -------- + Project the nth key-value pair from the trie build. + + This position is meaningful only when the build contains multiple uses of one or more keys, otherwise it is not. + */ + public func buildNth(tb:TrieBuild, i:Nat) : ?(K, ?Hash.Hash, V) = label profile_triebuild_nth : (?(K, ?Hash.Hash, V)) { + func rec(tb:TrieBuild, i:Nat) : ?(K, ?Hash.Hash, V) = label profile_triebuild_nth_rec : (?(K, ?Hash.Hash, V)) { + switch tb { + case (#skip) P.unreachable(); + case (#insert (k,h,v)) label profile_trie_buildNth_rec_end : (?(K, ?Hash.Hash, V)) { + assert(i == 0); + ?(k,h,v) + }; + case (#seq s) label profile_trie_buildNth_rec_seq : (?(K, ?Hash.Hash, V)) { + let count_left = buildCount(s.left); + if (i < count_left) { rec(s.left, i) } + else { rec(s.right, i - count_left) } + }; + } + }; + if (i >= buildCount(tb)) { + return null + }; + rec(tb, i) + }; + + /* + `projectInnerBuild` + -------------- + + Like [`mergeDisjoint`](#mergedisjoint), except that it avoids the + work of actually merging any tries; rather, just record the work for + latter (if ever). + */ + public func projectInnerBuild(t : Trie>) + : TrieBuild + { + foldUp, TrieBuild> + ( t, + func (t1:TrieBuild, t2:TrieBuild):TrieBuild { buildSeq(t1, t2) }, + func (_:K1, t:TrieBuild): TrieBuild { t }, + #skip ) + }; + + /* + `buildToArray` + -------- + Gather the collection of key-value pairs into an array of a (possibly-distinct) type. + */ + public func buildToArray(tb:TrieBuild,f:(K,V)->W):[W] = + label profile_triebuild_toArray_begin : [W] { + let a = A.tabulate ( + buildCount(tb), + func (i:Nat) : W = label profile_triebuild_toArray_nth : W { + let (k,_,v) = Option.unwrap<(K,?Hash.Hash,V)>(buildNth(tb, i)); + f(k, v) + } + ); + label profile_triebuild_toArray_end : [W] + a + }; + + /* + `buildToArray2` + -------- + Gather the collection of key-value pairs into an array of a (possibly-distinct) type. + + (Same semantics as `buildToArray`, but faster in practice.) + */ + public func buildToArray2(tb:TrieBuild,f:(K,V)->W):[W] { + let c = buildCount(tb); + let a = A.init(c, null); + var i = 0; + func rec(tb:TrieBuild) = label profile_triebuild_toArray2_rec { + switch tb { + case (#skip) (); + case (#insert(k,_,v)) { a[i] := ?f(k,v); i := i + 1 }; + case (#seq(s)) { rec(s.left); rec(s.right) }; + } + }; + rec(tb); + A.tabulate(c, func(i:Nat) : W = Option.unwrap(a[i])) + }; + + }; + + /* + `fold` + --------- + Fold over the key-value pairs of the trie, using an accumulator. + The key-value pairs have no reliable or meaningful ordering. + */ + public func fold(t:Trie, f:(K,V,X)->X, x:X) : X { + func rec(t:Trie, x:X) : X { + switch t { + case (#empty) x; + case (#leaf l) { + AssocList.fold,V,X>( + l.keyvals, x, + func (k:Key, v:V, x:X):X = f(k.key,v,x) + ) + }; + case (#branch(b)) { rec(b.left,rec(b.right,x)) }; + }; + }; + rec(t, x) + }; + + + /* + `exists` + -------- + Test whether a given key-value pair is present, or not. + */ + public func exists(t:Trie, f:(K,V)->Bool) : Bool { + func rec(t:Trie) : Bool { + switch t { + case (#empty) { false }; + case (#leaf l) { + List.exists<(Key,V)>( + l.keyvals, func ((k:Key,v:V)):Bool=f(k.key,v) + ) + }; + case (#branch(b)) { rec(b.left) or rec(b.right) }; + }; + }; + rec(t) + }; + + /* + `forAll` + --------- + Test whether all key-value pairs have a given property. + */ + public func forAll(t:Trie, f:(K,V)->Bool) : Bool { + func rec(t:Trie) : Bool { + switch t { + case (#empty) { true }; + case (#leaf l) { + List.all<(Key,V)>( + l.keyvals, func ((k:Key,v:V)):Bool=f(k.key,v) + ) + }; + case (#branch(b)) { rec(b.left) and rec(b.right) }; + }; + }; + rec(t) + }; + + /* + `nth` + -------- + Project the nth key-value pair from the trie. + + Note: This position is not meaningful; it's only here so that we + can inject tries into arrays given the A.tabulate interface for + doing so. + */ + public func nth(t:Trie, i:Nat) : ?(Key, V) = label profile_trie_nth : (?(Key, V)) { + func rec(t:Trie, i:Nat) : ?(Key, V) = label profile_trie_nth_rec : (?(Key, V)) { + switch t { + case (#empty) P.unreachable(); + case (#leaf l) List.nth<(Key,V)>(l.keyvals, i); + case (#branch b) { + let count_left = count(b.left); + if (i < count_left) { rec(b.left, i) } + else { rec(b.right, i - count_left) } + } + } + }; + if (i >= count(t)) { + return null + }; + rec(t, i) + }; + + + /* + `toArray` + -------- + Gather the collection of key-value pairs into an array of a (possibly-distinct) type. + + ### Implementation notes: + + we use this function repeatedly in the Produce Exchange example + application, often on very large tries. + + Performance Profiling shows that it is important that this be + memory efficient, and reasonably time efficient, at large scales. + + To do so, we use a single array allocation (for the returned array) and we + sacrifice some efficiency in reading the input trie, and instead use function `nth` to + project each element with an independent trie traversal. + + This approach is somewhat forced on us by the type signature of + A.tabulate, and the desire to only allocate one array; that requirement rules + out iterative mutation of an optionally-null array, since an imperative + approach which would give us the wrong return type. + + Since we want to statically rule out null output elements, and since the AS type system + cannot do that for an imperative approach unless we assume more about + the type W (e.g., the existence of "default values"), we settle for using `nth`. + + */ + public func toArray(t:Trie,f:(K,V)->W):[W] = + label profile_trie_toArray_begin : [W] { + let a = A.tabulate ( + count(t), + func (i:Nat) : W = label profile_trie_toArray_nth : W { + let (k,v) = Option.unwrap<(Key,V)>(nth(t, i)); + f(k.key, v) + } + ); + label profile_trie_toArray_end : [W] + a + }; + + /* + `isEmpty` + ----------- + specialized foldUp operation. + Test for "deep emptiness": subtrees that have branching structure, + but no leaves. These can result from naive filtering operations; + filter uses this function to avoid creating such subtrees. + */ + public func isEmpty(t:Trie) : Bool = + count(t) == 0; + + /* + `filter` + ----------- + filter the key-value pairs by a given predicate. + */ + public func filter(t:Trie, f:(K,V)->Bool) : Trie { + func rec(t:Trie, bitpos:Nat) : Trie { + switch t { + case (#empty) { #empty }; + case (#leaf l) { + leaf( + List.filter<(Key,V)>( + l.keyvals, + func ((k:Key,v:V)):Bool = f(k.key,v) + ), + bitpos + ) + }; + case (#branch(b)) { + let fl = rec(b.left, bitpos+1); + let fr = rec(b.right, bitpos+1); + switch (isEmpty(fl), + isEmpty(fr)) { + case (true, true) #empty; + case (false, true) fr; + case (true, false) fl; + case (false, false) branch(fl, fr); + }; + } + } + }; + rec(t, 0) + }; + + /* + `mapFilter` + ----------- + map and filter the key-value pairs by a given predicate. + */ + public func mapFilter(t:Trie, f:(K,V)->?W) : Trie { + func rec(t:Trie, bitpos:Nat) : Trie { + switch t { + case (#empty) { #empty }; + case (#leaf l) { + leaf( + List.mapFilter<(Key,V),(Key,W)>( + l.keyvals, + // retain key and hash, but update key's value using f: + func ((k:Key,v:V)):?(Key,W) = { + switch (f(k.key,v)) { + case (null) null; + case (?w) (?({key=k.key; hash=k.hash}, w)); + }} + ), + bitpos + ) + }; + case (#branch(b)) { + let fl = rec(b.left, bitpos + 1); + let fr = rec(b.right, bitpos + 1); + switch (isEmpty(fl), + isEmpty(fr)) { + case (true, true) #empty; + case (false, true) fr; + case (true, false) fl; + case (false, false) branch(fl, fr); + }; + } + } + }; + rec(t, 0) + }; + + /* + `equalStructure` + ------------------ + + Test for equality, but naively, based on structure. + Does not attempt to remove "junk" in the tree; + For instance, a "smarter" approach would equate + `#bin{left=#empty;right=#empty}` + with + `#empty`. + We do not observe that equality here. + */ + public func equalStructure( + tl:Trie, + tr:Trie, + keq:(K,K)->Bool, + veq:(V,V)->Bool + ) : Bool { + func rec(tl:Trie, tr:Trie) : Bool { + switch (tl, tr) { + case (#empty, #empty) { true }; + case (#leaf l1, #leaf l2) { + List.isEq<(Key,V)> + (l1.keyvals, l2.keyvals, + func ((k1:Key, v1:V), (k2:Key, v2:V)) : Bool = + keq(k1.key, k2.key) and veq(v1,v2) + ) + }; + case (#branch(b1),#branch(b2)) { + rec(b1.left, b2.left) and rec(b2.right, b2.right) + }; + case _ { false }; + } + }; + rec(tl,tr) + }; + + /* + `replaceThen` + ------------ + replace the given key's value in the trie, + and only if successful, do the success continuation, + otherwise, return the failure value + */ + public func replaceThen(t : Trie, k:Key, k_eq:(K,K)->Bool, v2:V, + success: (Trie, V) -> X, + fail: () -> X) + : X + { + let (t2, ov) = replace(t, k, k_eq, ?v2); + switch ov { + case (null) { /* no prior value; failure to remove */ fail() }; + case (?v1) { success(t2, v1) }; + } + }; + + /* + `insertFresh` + ---------------- + insert the given key's value in the trie; return the new trie; assert that no prior value is associated with the key + */ + public func insertFresh(t : Trie, k:Key, k_eq:(K,K)->Bool, v:V) : Trie { + let (t2, none) = replace(t, k, k_eq, ?v); + switch none { + case (null) (); + case (?_) assert false; + }; + t2 + }; + + /* + `insert2D` + --------------- + insert the given key's value in the 2D trie; return the new 2D trie. + */ + public func insert2D(t : Trie2D, + k1:Key, k1_eq:(K1,K1)->Bool, + k2:Key, k2_eq:(K2,K2)->Bool, + v:V) + : Trie2D + { + let inner = find>(t, k1, k1_eq); + let (updated_inner, _) = switch inner { + case (null) { insert(#empty, k2, k2_eq, v) }; + case (?inner) { insert(inner, k2, k2_eq, v) }; + }; + let (updated_outer, _) = { insert>(t, k1, k1_eq, updated_inner) }; + updated_outer; + }; + + /* + `insert3D` + --------------- + insert the given key's value in the trie; return the new trie; + */ + public func insert3D + (t : Trie3D, + k1:Key, k1_eq:(K1,K1)->Bool, + k2:Key, k2_eq:(K2,K2)->Bool, + k3:Key, k3_eq:(K3,K3)->Bool, + v:V + ) + : Trie3D + { + let inner1 = find>(t, k1, k1_eq); + let (updated_inner1, _) = switch inner1 { + case (null) { + insert>( + #empty, k2, k2_eq, + (insert(#empty, k3, k3_eq, v)).0 + ) + }; + case (?inner1) { + let inner2 = find>(inner1, k2, k2_eq); + let (updated_inner2, _) = switch inner2 { + case (null) { insert(#empty, k3, k3_eq, v) }; + case (?inner2) { insert(inner2, k3, k3_eq, v) }; + }; + insert>( inner1, k2, k2_eq, updated_inner2 ) + }; + }; + let (updated_outer, _) = { insert>(t, k1, k1_eq, updated_inner1) }; + updated_outer; + }; + + /* + `remove` + ------------- + remove the given key's value in the trie; return the new trie + */ + public func remove(t : Trie, k:Key, k_eq:(K,K)->Bool) : (Trie, ?V) { + replace(t, k, k_eq, null) + }; + + /* + `removeThen` + ------------ + remove the given key's value in the trie, + and only if successful, do the success continuation, + otherwise, return the failure value + */ + public func removeThen(t : Trie, k:Key, k_eq:(K,K)->Bool, + success: (Trie, V) -> X, + fail: () -> X) + : X + { + let (t2, ov) = replace(t, k, k_eq, null); + switch ov { + case (null) { /* no prior value; failure to remove */ fail() }; + case (?v) { success(t2, v) }; + } + }; + + + /* + `remove2D` + -------------- + remove the given key-key pair's value in the 2D trie; return the + new trie, and the prior value, if any. + */ + public func remove2D(t : Trie2D, + k1:Key, k1_eq:(K1,K1)->Bool, + k2:Key, k2_eq:(K2,K2)->Bool) + : (Trie2D, ?V) + { + switch (find>(t, k1, k1_eq)) { + case (null) { + (t, null) + }; + case (?inner) { + let (updated_inner, ov) = remove(inner, k2, k2_eq); + let (updated_outer, _) = { + insert>(t, k1, k1_eq, updated_inner) + }; + (updated_outer, ov) + }; + } + }; + + /* + `remove3D` + --------------- + remove the given key-key pair's value in the 3D trie; return the + new trie, and the prior value, if any. + */ + public func remove3D + (t : Trie3D, + k1:Key, k1_eq:(K1,K1)->Bool, + k2:Key, k2_eq:(K2,K2)->Bool, + k3:Key, k3_eq:(K3,K3)->Bool, + ) + : (Trie3D, ?V) + { + switch (find>(t, k1, k1_eq)) { + case (null) { + (t, null) + }; + case (?inner) { + let (updated_inner, ov) = remove2D(inner, k2, k2_eq, k3, k3_eq); + let (updated_outer, _) = { + insert>(t, k1, k1_eq, updated_inner) + }; + (updated_outer, ov) + }; + } + }; + + + + /* + `mergeDisjoint2D` + -------------- + + Like [`mergeDisjoint`](#mergedisjoint), except instead of merging a + pair, it merges the collection of dimension-2 sub-trees of a 2D + trie. + + */ + public func mergeDisjoint2D(t : Trie2D, k1_eq:(K1,K1)->Bool, k2_eq:(K2,K2)->Bool) + : Trie + { + foldUp, Trie> + ( t, + func (t1:Trie, t2:Trie):Trie { mergeDisjoint(t1, t2, k2_eq) }, + func (_:K1, t:Trie): Trie { t }, + #empty ) + }; + + +/* + +Future work +============= + +Iterator objects +------------------- +for use in 'for ... in ...' patterns + +*/ +} diff --git a/test/perf/qr/util.mo b/test/perf/qr/util.mo new file mode 100644 index 00000000000..eb26384cff2 --- /dev/null +++ b/test/perf/qr/util.mo @@ -0,0 +1,33 @@ +/** + * Module : util.mo + * Copyright : 2020 DFINITY Stiftung + * License : Apache 2.0 with LLVM Exception + * Maintainer : Enzo Haussecker + * Stability : Stable + */ + +import List "list"; + +module Util { + + type List = List.List; + + public func padLeft(n : Nat, bits : List) : List { + List.append(List.replicate(n, false), bits) + }; + + public func padRight(n : Nat, bits : List) : List { + List.append(bits, List.replicate(n, false)) + }; + + public func padLeftTo(n : Nat, bits : List) : List { + let m = List.len(bits); + if (m > n) bits else padLeft(n - m, bits) + }; + + public func padRightTo(n : Nat, bits : List) : List { + let m = List.len(bits); + if (m > n) bits else padRight(n - m, bits) + }; + +} diff --git a/test/perf/qr/version.mo b/test/perf/qr/version.mo new file mode 100644 index 00000000000..5c5022f39b8 --- /dev/null +++ b/test/perf/qr/version.mo @@ -0,0 +1,37 @@ +/** + * Module : version.mo + * Copyright : 2020 DFINITY Stiftung + * License : Apache 2.0 with LLVM Exception + * Maintainer : Enzo Haussecker + * Stability : Stable + */ + +import Galois "galois"; +import List "list"; +import Nat "nat"; +import Prelude "prelude"; +import Util "util"; + +module { + + type List = List.List; + + public type Version = { #Version : Nat }; + + public func unbox(version : Version) : Nat { + let #Version n = version; + n + }; + + public func new(n : Nat) : ?Version { + if (n > 40 or n == 0) null else ?#Version n + }; + + public func encode(version : Version) : List { + let input = Nat.natToBits(unbox(version)); + let poly1 = Galois.polyFromBits(Util.padRight(12, input)); + let poly2 = Galois.polyFromBits(Nat.natToBits(7973)); + Util.padLeftTo(18, Galois.polyToBits(Galois.polyAdd(poly1, Galois.polyDivMod(poly1, poly2).1))) + }; + +} From 7d1d615c14ceba038aa35d1b6f8a1017b705811d Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 2 Apr 2020 16:13:10 +0200 Subject: [PATCH 1151/1176] tests.perf: Record gas numbers again (#1327) at some point in the past, `drun` changed its output format for performance counters, and we stopped tracking gas usage. This fixes this, and also makes sure that CI complains if that happens again. Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- default.nix | 13 +++++++------ test/README.md | 4 ++-- test/run.sh | 2 +- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/default.nix b/default.nix index 7a4e4c7590c..b9b43bd28a0 100644 --- a/default.nix +++ b/default.nix @@ -206,11 +206,6 @@ rec { # run this once to work around self-unpacking-race-condition type -p drun && drun --version make -C ${dir} - - if test -e ${dir}/_out/stats.csv - then - cp ${dir}/_out/stats.csv $out - fi ''; }; in @@ -218,7 +213,13 @@ rec { (test_subdir dir deps).overrideAttrs (args: { checkPhase = '' export PERF_OUT=$out - '' + args.checkPhase; + '' + args.checkPhase + '' + if ! grep -q ^gas/ $out + then + echo "perf stats do not include gas. change in drun output format?" >&2 + exit 1 + fi + ''; }); in let qc = testDerivation { diff --git a/test/README.md b/test/README.md index b0a6518e0e6..53cd29ad5a7 100644 --- a/test/README.md +++ b/test/README.md @@ -72,8 +72,8 @@ For these tests the test suite records the following numbers: * Size of the produced Wasm binary. * Gas consumed by a single run in drun [not yet implemented] -The numbers are written to `_out/stats.csv`, and are also the output of the nix -derivation `tests.perf`. +The numbers are written to the file specified by `$PERF_OUT` (and end up being +the output of the nix derivation `tests.perf`. The format is a simple CSV format, as consumed by [gipeda](https://github.com/nomeata/gipeda). diff --git a/test/run.sh b/test/run.sh index dc4700c2c88..66548468f31 100755 --- a/test/run.sh +++ b/test/run.sh @@ -342,7 +342,7 @@ do run_if wasm drun-run $DRUN_WRAPPER $out/$base.wasm $mangled 222> $out/$base.metrics if [ -e $out/$base.metrics -a -n "$PERF_OUT" ] then - LANG=C perl -ne "print \"gas/$base;\$1\n\" if /^gas_consumed_per_round_sum (\\d+)\$/" $out/$base.metrics >> $PERF_OUT; + LANG=C perl -ne "print \"gas/$base;\$1\n\" if /^scheduler_gas_consumed_per_round_sum (\\d+)\$/" $out/$base.metrics >> $PERF_OUT; fi fi else From b23c1d3221c734b3853a4db7f437ab9177222a78 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Thu, 2 Apr 2020 16:54:36 +0200 Subject: [PATCH 1152/1176] IR: Make notes record more abstract (#1325) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * IR: Make notes record more abstract I want to make the IR notes abstract and expose a default note that only gets extended. This way, we can add more field to the record without changing existing code (I hope). It looks like Ocaml doesn’t allow you to prevent other modules from _creating_ the record type, while still allowing other modules from _updating_ records. So I guess the type will be abstract by convention, but not enforced by the module system. By disabling warning `23`, Ocaml will _not_ complain about `{ def where … }` when `…` actually sets _all_ fields. This fixes #1322 * Fix dune flag settings * Update src/ir_def/ir.ml * Do not use old typ_note type * More uses of `def with…` Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- src/codegen/compile.ml | 20 ++-- src/dune | 6 +- src/ir_def/construct.ml | 147 +++++++++++++---------------- src/ir_def/ir.ml | 3 +- src/ir_def/ir_effect.ml | 8 +- src/ir_def/ir_effect.mli | 7 +- src/ir_def/note.ml | 12 +++ src/ir_def/note.mli | 9 ++ src/ir_interpreter/interpret_ir.ml | 6 +- src/ir_passes/async.ml | 9 +- src/ir_passes/await.ml | 14 +-- src/ir_passes/show.ml | 2 +- src/lowering/desugar.ml | 24 ++--- 13 files changed, 136 insertions(+), 131 deletions(-) create mode 100644 src/ir_def/note.ml create mode 100644 src/ir_def/note.mli diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 301b1bc3db1..a45bc3a79f3 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -6059,13 +6059,13 @@ let rec compile_lexp (env : E.t) ae lexp = | DotLE (e, n) -> compile_exp_vanilla env ae e ^^ (* Only real objects have mutable fields, no need to branch on the tag *) - Object.idx env e.note.note_typ n, + Object.idx env e.note.Note.typ n, store_ptr and compile_exp (env : E.t) ae exp = (fun (sr,code) -> (sr, G.with_region exp.at code)) @@ match exp.it with - | PrimE (p, es) when List.exists (fun e -> Type.is_non e.note.note_typ) es -> + | PrimE (p, es) when List.exists (fun e -> Type.is_non e.note.Note.typ) es -> (* Handle dead code separately, so that we can rely on useful type annotations below *) SR.Unreachable, @@ -6079,7 +6079,7 @@ and compile_exp (env : E.t) ae exp = begin match p, es with (* Calls *) | CallPrim _, [e1; e2] -> - let sort, control, _, arg_tys, ret_tys = Type.as_func e1.note.note_typ in + let sort, control, _, arg_tys, ret_tys = Type.as_func e1.note.Note.typ in let n_args = List.length arg_tys in let return_arity = match control with | Type.Returns -> List.length ret_tys @@ -6109,7 +6109,7 @@ and compile_exp (env : E.t) ae exp = let (set_meth_pair, get_meth_pair) = new_local env "meth_pair" in let (set_arg, get_arg) = new_local env "arg" in - let _, _, _, ts, _ = Type.as_func e1.note.note_typ in + let _, _, _, ts, _ = Type.as_func e1.note.Note.typ in code1 ^^ StackRep.adjust env fun_sr SR.Vanilla ^^ set_meth_pair ^^ compile_exp_as env ae SR.Vanilla e2 ^^ set_arg ^^ @@ -6163,7 +6163,7 @@ and compile_exp (env : E.t) ae exp = | _ -> SR.Vanilla, code1 ^^ StackRep.adjust env sr SR.Vanilla ^^ - Object.load_idx env e.note.note_typ name + Object.load_idx env e.note.Note.typ name end | ActorDotPrim name, [e] -> SR.Vanilla, @@ -6246,7 +6246,7 @@ and compile_exp (env : E.t) ae exp = BigNum.truncate_to_word64 env) | Int, (Int8|Int16|Int32) -> - let ty = exp.note.note_typ in + let ty = exp.note.Note.typ in StackRep.of_type ty, let pty = prim_of_typ ty in compile_exp_vanilla env ae e ^^ @@ -6269,7 +6269,7 @@ and compile_exp (env : E.t) ae exp = BigNum.truncate_to_word64 env) | Nat, (Nat8|Nat16|Nat32) -> - let ty = exp.note.note_typ in + let ty = exp.note.Note.typ in StackRep.of_type ty, let pty = prim_of_typ ty in compile_exp_vanilla env ae e ^^ @@ -6478,8 +6478,8 @@ and compile_exp (env : E.t) ae exp = | ICCallPrim, [f;e;k;r] -> SR.unit, begin (* TBR: Can we do better than using the notes? *) - let _, _, _, ts1, _ = Type.as_func f.note.note_typ in - let _, _, _, ts2, _ = Type.as_func k.note.note_typ in + let _, _, _, ts1, _ = Type.as_func f.note.Note.typ in + let _, _, _, ts2, _ = Type.as_func k.note.Note.typ in let (set_meth_pair, get_meth_pair) = new_local env "meth_pair" in let (set_arg, get_arg) = new_local env "arg" in let (set_k, get_k) = new_local env "k" in @@ -6604,7 +6604,7 @@ and compile_exp (env : E.t) ae exp = SR.Vanilla, let fs' = fs |> List.map (fun (f : Ir.field) -> (f.it.name, fun () -> - if Object.is_mut_field env exp.note.note_typ f.it.name + if Object.is_mut_field env exp.note.Note.typ f.it.name then Var.get_val_ptr env ae f.it.var else Var.get_val_vanilla env ae f.it.var)) in Object.lit_raw env fs' diff --git a/src/dune b/src/dune index 7888d3a34aa..a062daeeb16 100644 --- a/src/dune +++ b/src/dune @@ -1,6 +1,6 @@ (env - (dev (flags "-w" "+a-4-27-30-42-44-45-58")) - (release (flags "-w" "+a-4-27-30-42-44-45-58" "-warn-error" "+a")) - (release-static (flags "-w" "+a-4-27-30-42-44-45-58" "-warn-error" "+a" "-cclib" "-static")) + (dev (flags "-w" "+a-4-23-27-30-42-44-45-58")) + (release (flags "-w" "+a-4-23-27-30-42-44-45-58" "-warn-error" "+a")) + (release-static (flags "-w" "+a-4-23-27-30-42-44-45-58" "-warn-error" "+a" "-cclib" "-static")) ) diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index 98554165d64..30a37541447 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -18,7 +18,7 @@ let nextN = "next" let idE id typ = { it = VarE id; at = no_region; - note = { note_typ = typ; note_eff = T.Triv } + note = Note.{ def with typ = typ } } let id_of_exp x = @@ -28,7 +28,7 @@ let id_of_exp x = let arg_of_exp x = match x.it with - | VarE i -> { it = i; at = x.at; note = x.note.note_typ } + | VarE i -> { it = i; at = x.at; note = x.note.Note.typ } | _ -> failwith "Impossible: arg_of_exp" let exp_of_arg a = @@ -60,7 +60,7 @@ let fresh_vars name_base ts = let varP x = { it = VarP (id_of_exp x); at = x.at; - note = x.note.note_typ + note = x.note.Note.typ } let tupP pats = @@ -76,7 +76,7 @@ let seqP ps = (* Primitives *) let primE prim es = - let ty = match prim with + let typ = match prim with | ShowPrim _ -> T.text | ICReplyPrim _ -> T.Non | ICRejectPrim -> T.Non @@ -85,49 +85,49 @@ let primE prim es = | _ -> assert false (* implement more as needed *) in let effs = List.map eff es in - let e = List.fold_left max_eff T.Triv effs in + let eff = List.fold_left max_eff T.Triv effs in { it = PrimE (prim, es); at = no_region; - note = { note_typ = ty; note_eff = e } + note = Note.{ def with typ; eff } } let selfRefE typ = { it = PrimE (SelfRef typ, []); at = no_region; - note = { note_typ = typ; note_eff = T.Triv } + note = Note.{ def with typ } } let asyncE typ1 typ2 e = { it = PrimE (CPSAsync typ1, [e]); at = no_region; - note = { note_typ = T.Async (typ1, typ2); note_eff = eff e } + note = Note.{ def with typ = T.Async (typ1, typ2); eff = eff e } } let assertE e = { it = PrimE (AssertPrim, [e]); at = no_region; - note = { note_typ = T.unit; note_eff = eff e} + note = Note.{ def with typ = T.unit; eff = eff e} } let awaitE typ e1 e2 = { it = PrimE (CPSAwait, [e1; e2]); at = no_region; - note = { note_typ = T.unit; note_eff = max_eff (eff e1) (eff e2) } + note = Note.{ def with typ = T.unit; eff = max_eff (eff e1) (eff e2) } } let ic_replyE ts e = (match ts with - | [t] -> assert (T.sub (e.note.note_typ) t) - | _ -> assert (T.sub (T.Tup ts) (e.note.note_typ))); + | [t] -> assert (T.sub (e.note.Note.typ) t) + | _ -> assert (T.sub (T.Tup ts) (e.note.Note.typ))); { it = PrimE (ICReplyPrim ts, [e]); at = no_region; - note = { note_typ = T.unit; note_eff = eff e } + note = Note.{ def with typ = T.unit; eff = eff e } } let ic_rejectE e = { it = PrimE (ICRejectPrim, [e]); at = no_region; - note = { note_typ = T.unit; note_eff = eff e } + note = Note.{ def with typ = T.unit; eff = eff e } } let ic_callE f e k r = @@ -136,7 +136,7 @@ let ic_callE f e k r = let eff = List.fold_left max_eff T.Triv effs in { it = PrimE (ICCallPrim, es); at = no_region; - note = { note_typ = T.unit; note_eff = eff } + note = Note.{ def with typ = T.unit; eff = eff } } @@ -146,20 +146,20 @@ let projE e n = match typ e with | T.Tup ts -> { it = PrimE (ProjPrim n, [e]); - note = { note_typ = List.nth ts n; note_eff = eff e }; + note = Note.{ def with typ = List.nth ts n; eff = eff e }; at = no_region; } | _ -> failwith "projE" let optE e = { it = PrimE (OptPrim, [e]); - note = { note_typ = T.Opt (typ e); note_eff = eff e }; + note = Note.{ def with typ = T.Opt (typ e); eff = eff e }; at = no_region; } let tagE i e = { it = PrimE (TagPrim i, [e]); - note = { note_typ = T.Variant [{T.lab = i; typ = typ e}]; note_eff = eff e }; + note = Note.{ def with typ = T.Variant [{T.lab = i; typ = typ e}]; eff = eff e }; at = no_region; } @@ -182,28 +182,28 @@ let blockE decs exp = | _ -> let es = List.map dec_eff decs' in let typ = typ exp in - let e = List.fold_left max_eff (eff exp) es in + let eff = List.fold_left max_eff (eff exp) es in { it = BlockE (decs', exp); at = no_region; - note = {note_typ = typ; note_eff = e } + note = Note.{ def with typ; eff } } let textE s = { it = LitE (TextLit s); at = no_region; - note = { note_typ = T.text; note_eff = T.Triv } + note = Note.{ def with typ = T.text } } let blobE s = { it = LitE (BlobLit s); at = no_region; - note = { note_typ = T.blob; note_eff = T.Triv } + note = Note.{ def with typ = T.blob } } let boolE b = { it = LitE (BoolLit b); at = no_region; - note = { note_typ = T.bool; note_eff = T.Triv} + note = Note.{ def with typ = T.bool } } let callE exp1 ts exp2 = @@ -211,9 +211,9 @@ let callE exp1 ts exp2 = | T.Func (_sort, _control, _, _, ret_tys) -> { it = PrimE (CallPrim ts, [exp1; exp2]); at = no_region; - note = { - note_typ = T.open_ ts (T.seq ret_tys); - note_eff = max_eff (eff exp1) (eff exp2) + note = Note.{ def with + typ = T.open_ ts (T.seq ret_tys); + eff = max_eff (eff exp1) (eff exp2) } } | T.Non -> exp1 @@ -222,18 +222,18 @@ let callE exp1 ts exp2 = let ifE exp1 exp2 exp3 typ = { it = IfE (exp1, exp2, exp3); at = no_region; - note = { - note_typ = typ; - note_eff = max_eff (eff exp1) (max_eff (eff exp2) (eff exp3)) + note = Note.{ def with + typ = typ; + eff = max_eff (eff exp1) (max_eff (eff exp2) (eff exp3)) } } let dotE exp name typ = { it = PrimE (DotPrim name, [exp]); at = no_region; - note = { - note_typ = typ; - note_eff = eff exp + note = Note.{ def with + typ = typ; + eff = eff exp } } @@ -255,9 +255,9 @@ let switch_optE exp1 exp2 pat exp3 typ1 = note = () }] ); at = no_region; - note = { - note_typ = typ1; - note_eff = max_eff (eff exp1) (max_eff (eff exp2) (eff exp3)) + note = Note.{ def with + typ = typ1; + eff = max_eff (eff exp1) (max_eff (eff exp2) (eff exp3)) } } @@ -275,9 +275,9 @@ let switch_variantE exp1 cases typ1 = cases ); at = no_region; - note = { - note_typ = typ1; - note_eff = List.fold_left max_eff (eff exp1) (List.map (fun (l,p,e) -> eff e) cases) + note = Note.{ def with + typ = typ1; + eff = List.fold_left max_eff (eff exp1) (List.map (fun (l,p,e) -> eff e) cases) } } @@ -286,10 +286,7 @@ let tupE exps = let eff = List.fold_left max_eff T.Triv effs in { it = PrimE (TupPrim, exps); at = no_region; - note = { - note_typ = T.Tup (List.map typ exps); - note_eff = eff - } + note = Note.{ def with typ = T.Tup (List.map typ exps); eff }; } let unitE = tupE [] @@ -297,23 +294,18 @@ let unitE = tupE [] let breakE l exp = { it = PrimE (BreakPrim l, [exp]); at = no_region; - note = { - note_eff = eff exp; - note_typ = T.Non - } + note = Note.{ def with typ = T.Non; eff = eff exp }; } let retE exp = { it = PrimE (RetPrim, [exp]); at = no_region; - note = { note_eff = eff exp; - note_typ = T.Non } + note = Note.{ def with typ = T.Non; eff = eff exp }; } let immuteE e = { e with - note = { note_eff = eff e; - note_typ = T.as_immut (typ e) } + note = Note.{ def with typ = T.as_immut (typ e); eff = eff e }; } @@ -331,23 +323,20 @@ let assignE exp1 exp2 = assert (T.is_mut (typ exp1)); { it = AssignE (lexp_of_exp exp1, exp2); at = no_region; - note = { note_eff = eff exp2; - note_typ = T.unit } + note = Note.{ def with typ = T.unit; eff = eff exp2 }; } let labelE l typ exp = { it = LabelE (l, typ, exp); at = no_region; - note = { note_eff = eff exp; - note_typ = typ } + note = Note.{ def with typ; eff = eff exp } } (* Used to desugar for loops, while loops and loop-while loops. *) let loopE exp = { it = LoopE exp; at = no_region; - note = { note_eff = eff exp ; - note_typ = T.Non } + note = Note.{ def with typ = T.Non; eff = eff exp } } let declare_idE x typ exp1 = @@ -359,15 +348,13 @@ let declare_idE x typ exp1 = let define_idE x mut exp1 = { it = DefineE (x, mut, exp1); at = no_region; - note = { note_typ = T.unit; - note_eff = T.Triv} + note = Note.{ def with typ = T.unit } } let newObjE sort ids typ = { it = NewObjE (sort, ids, typ); at = no_region; - note = { note_typ = typ; - note_eff = T.Triv } + note = Note.{ def with typ } } @@ -381,7 +368,7 @@ let varD x t exp = VarD (x, t, exp) @@ no_region let expD exp = - let pat = { it = WildP; at = exp.at; note = exp.note.note_typ } in + let pat = { it = WildP; at = exp.at; note = exp.note.Note.typ } in LetD (pat, exp) @@ exp.at let let_no_shadow x exp decs = @@ -405,8 +392,8 @@ let ignoreE exp = (* Mono-morphic function expression *) -let funcE name t x exp = - let sort, control, arg_tys, ret_tys = match t with +let funcE name typ x exp = + let sort, control, arg_tys, ret_tys = match typ with | T.Func(s, c, _, ts1, ts2) -> s, c, ts1, ts2 | _ -> assert false in let args, exp' = @@ -429,11 +416,11 @@ let funcE name t x exp = exp' ); at = no_region; - note = { note_eff = T.Triv; note_typ = t } + note = Note.{ def with typ } }) -let nary_funcE name t xs exp = - let sort, control, arg_tys, ret_tys = match t with +let nary_funcE name typ xs exp = + let sort, control, arg_tys, ret_tys = match typ with | T.Func(s, c, _, ts1, ts2) -> s, c, ts1, ts2 | _ -> assert false in assert (List.length arg_tys = List.length xs); @@ -447,7 +434,7 @@ let nary_funcE name t xs exp = exp ); at = no_region; - note = { note_eff = T.Triv; note_typ = t } + note = Note.{ def with typ } }) (* Mono-morphic function declaration, sharing inferred from f's type *) @@ -506,16 +493,17 @@ let close_typ_binds cs tbs = (* polymorphic, n-ary local lambda *) let forall tbs e = let cs = List.map (fun tb -> tb.it.con) tbs in - match e.it, e.note.note_typ with + match e.it, e.note.Note.typ with | FuncE (n, s, c1, [], xs, ts, exp), T.Func ( _, c2, [], ts1, ts2) -> { e with it = FuncE(n, s, c1, tbs, xs, ts, exp); - note = { e.note with - note_typ = T.Func(s, c2, close_typ_binds cs tbs, - List.map (T.close cs) ts1, - List.map (T.close cs) ts2) - }} + note = Note.{ e.note with + typ = T.Func(s, c2, close_typ_binds cs tbs, + List.map (T.close cs) ts1, + List.map (T.close cs) ts2) + } + } | _ -> assert false (* Lambda application (monomorphic) *) @@ -525,14 +513,13 @@ let ( -*- ) exp1 exp2 = | T.Func (_, _, [], _, ret_tys) -> { it = PrimE (CallPrim [], [exp1; exp2]); at = no_region; - note = {note_typ = T.seq ret_tys; - note_eff = max_eff (eff exp1) (eff exp2)} + note = Note.{def with typ = T.seq ret_tys; eff = max_eff (eff exp1) (eff exp2)} } | typ1 -> failwith - (Printf.sprintf "Impossible: \n func: %s \n : %s arg: \n %s" - (Wasm.Sexpr.to_string 80 (Arrange_ir.exp exp1)) - (T.string_of_typ typ1) - (Wasm.Sexpr.to_string 80 (Arrange_ir.exp exp2))) + (Printf.sprintf "Impossible: \n func: %s \n : %s arg: \n %s" + (Wasm.Sexpr.to_string 80 (Arrange_ir.exp exp1)) + (T.string_of_typ typ1) + (Wasm.Sexpr.to_string 80 (Arrange_ir.exp exp2))) (* derived loop forms; each can be expressed as an unconditional loop *) @@ -583,7 +570,7 @@ let forE pat exp1 exp2 = } } *) let lab = fresh_id "done" () in - let ty1 = exp1.note.note_typ in + let ty1 = exp1.note.Note.typ in let _, tfs = T.as_obj_sub ["next"] ty1 in let tnxt = T.lookup_val_field "next" tfs in let nxt = fresh_var "nxt" tnxt in diff --git a/src/ir_def/ir.ml b/src/ir_def/ir.ml index 378a0ca7af4..1eb67393386 100644 --- a/src/ir_def/ir.ml +++ b/src/ir_def/ir.ml @@ -28,9 +28,8 @@ type lit = | BlobLit of string (* Patterns *) -type typ_note = {note_typ : Type.typ; note_eff : Type.eff} -type 'a phrase = ('a, typ_note) Source.annotated_phrase +type 'a phrase = ('a, Note.t) Source.annotated_phrase type typ_bind' = {con : Type.con; sort: Type.bind_sort; bound : Type.typ} type typ_bind = typ_bind' Source.phrase diff --git a/src/ir_def/ir_effect.ml b/src/ir_def/ir_effect.ml index 6ad91076e80..53668b1ff99 100644 --- a/src/ir_def/ir_effect.ml +++ b/src/ir_def/ir_effect.ml @@ -13,12 +13,10 @@ let max_eff e1 e2 = | _ , T.Await -> T.Await | T.Await,_ -> T.Await -let typ phrase = phrase.note.note_typ +let typ phrase = phrase.note.Note.typ +let eff phrase = phrase.note.Note.eff -let eff phrase = phrase.note.note_eff - -let is_triv phrase = - eff phrase = T.Triv +let is_triv phrase = eff phrase = T.Triv let effect_exp (exp: exp) : T.eff = eff exp diff --git a/src/ir_def/ir_effect.mli b/src/ir_def/ir_effect.mli index 9fddc14f0b4..c8aae61827c 100644 --- a/src/ir_def/ir_effect.mli +++ b/src/ir_def/ir_effect.mli @@ -1,15 +1,14 @@ open Source -open Ir open Mo_types.Type val max_eff : eff -> eff -> eff (* (incremental) effect inference on IR *) -val typ : ('a, typ_note) annotated_phrase -> typ -val eff : ('a, typ_note) annotated_phrase -> eff +val typ : ('a, Note.t) annotated_phrase -> typ +val eff : ('a, Note.t) annotated_phrase -> eff -val is_triv : ('a, typ_note) annotated_phrase -> bool +val is_triv : ('a, Note.t) annotated_phrase -> bool val effect_exp: Ir.exp -> eff val infer_effect_exp : Ir.exp -> eff diff --git a/src/ir_def/note.ml b/src/ir_def/note.ml new file mode 100644 index 00000000000..0d99c82152c --- /dev/null +++ b/src/ir_def/note.ml @@ -0,0 +1,12 @@ +open Mo_types + +type t = { + typ : Type.typ; + eff : Type.eff; +} + +let def : t = { + typ = Type.Pre; + eff = Type.Triv; +} + diff --git a/src/ir_def/note.mli b/src/ir_def/note.mli new file mode 100644 index 00000000000..0de332d8763 --- /dev/null +++ b/src/ir_def/note.mli @@ -0,0 +1,9 @@ +open Mo_types + +type t = { + typ : Type.typ; + eff : Type.eff; +} + +val def : t + diff --git a/src/ir_interpreter/interpret_ir.ml b/src/ir_interpreter/interpret_ir.ml index a46cfe43635..28b57c98699 100644 --- a/src/ir_interpreter/interpret_ir.ml +++ b/src/ir_interpreter/interpret_ir.ml @@ -280,11 +280,11 @@ let interpret_lit env lit : V.value = let check_call_conv exp call_conv = let open Call_conv in - let exp_call_conv = call_conv_of_typ exp.note.note_typ in + let exp_call_conv = call_conv_of_typ exp.note.Note.typ in if not (exp_call_conv = call_conv) then failwith (Printf.sprintf "call_conv mismatch: function %s of type %s expecting %s, found %s" (Wasm.Sexpr.to_string 80 (Arrange_ir.exp exp)) - (T.string_of_typ exp.note.note_typ) + (T.string_of_typ exp.note.Note.typ) (string_of_call_conv exp_call_conv) (string_of_call_conv call_conv)) @@ -384,7 +384,7 @@ and interpret_exp_mut env exp (k : V.value V.cont) = | CPSAsync _, [v1] -> assert (not env.flavor.has_await && env.flavor.has_async_typ); let (_, f) = V.as_func v1 in - let typ = exp.note.note_typ in + let typ = exp.note.Note.typ in begin match typ with | T.Func(_, _, _, [T.Func(_, _, _, [f_dom], _);T.Func(_, _, _, [r_dom], _)], _) -> let call_conv_f = CC.call_conv_of_typ f_dom in diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index 512ff726661..da88fd9344e 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -27,8 +27,7 @@ module ConRenaming = E.Make(struct type t = T.con let compare = Con.compare end) let selfcallE ts e1 e2 e3 = { it = SelfCallE (ts, e1, e2, e3); at = no_region; - note = { note_typ = T.unit; - note_eff = T.Triv } + note = Note.{ def with typ = T.unit } } let error_ty = @@ -221,8 +220,10 @@ let transform mode env prog = let rec t_exp (exp: exp) = { it = t_exp' exp; - note = { note_typ = t_typ exp.note.note_typ; - note_eff = exp.note.note_eff}; + note = Note.{ def with + typ = t_typ exp.note.typ; + eff = exp.note.eff + }; at = exp.at; } and t_exp' (exp:exp) = diff --git a/src/ir_passes/await.ml b/src/ir_passes/await.ml index 136feea822d..7794dee9889 100644 --- a/src/ir_passes/await.ml +++ b/src/ir_passes/await.ml @@ -264,14 +264,14 @@ and c_exp' context exp k = | T.Triv -> { it = SwitchE(t_exp context exp1, cases'); at = exp.at; - note = { exp.note with note_typ = answerT } } + note = Note.{ exp.note with typ = answerT } } | T.Await -> c_exp context exp1 (meta (typ exp1) (fun v1 -> { it = SwitchE(v1, cases'); at = exp.at; - note = { exp.note with note_typ = answerT } })) + note = Note.{ exp.note with typ = answerT } })) end) | TryE (exp1, cases) -> (* TODO: do we need to reify f? *) @@ -301,11 +301,11 @@ and c_exp' context exp k = k -*- (t_exp context exp1) | T.Await -> blockE - [funcD throw e - { it = SwitchE (e, cases'); - at = exp.at; - note = { note_eff = T.Await; (* shouldn't matter *) - note_typ = T.unit } }] + [funcD throw e { + it = SwitchE (e, cases'); + at = exp.at; + note = Note.{ def with typ = T.unit; eff = T.Await; (* shouldn't matter *) } + }] (c_exp context' exp1 (ContVar k)) end)) | LoopE exp1 -> diff --git a/src/ir_passes/show.ml b/src/ir_passes/show.ml index 9d81146f389..b5a977f903e 100644 --- a/src/ir_passes/show.ml +++ b/src/ir_passes/show.ml @@ -107,7 +107,7 @@ let list_build : 'a -> 'a -> 'a -> 'a list -> 'a list = fun pre sep post xs -> let catE : Ir.exp -> Ir.exp -> Ir.exp = fun e1 e2 -> { it = PrimE (BinPrim (T.text, Operator.CatOp), [e1; e2]) ; at = no_region - ; note = { note_typ = T.text; note_eff = T.Triv } + ; note = { Note.def with Note.typ = T.text } } let cat_list : Ir.exp list -> Ir.exp = fun es -> diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 91a9df7bef7..65872c9270d 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -37,8 +37,8 @@ let apply_sign op l = Syntax.(match op, l with let phrase f x = { x with it = f x.it } -let typ_note : S.typ_note -> I.typ_note = - fun {S.note_typ;S.note_eff} -> {I.note_typ;I.note_eff} +let typ_note : S.typ_note -> Note.t = + fun {S.note_typ;S.note_eff} -> Note.{def with typ = note_typ; eff = note_eff} let phrase' f x = { x with it = f x.at x.note x.it } @@ -58,7 +58,7 @@ and exp e = and exp' at note = function | S.VarE i -> I.VarE i.it | S.ActorUrlE e -> - I.(PrimE (ActorOfIdBlob note.note_typ, [url e])) + I.(PrimE (ActorOfIdBlob note.Note.typ, [url e])) | S.LitE l -> I.LitE (lit !l) | S.UnE (ot, o, e) -> I.PrimE (I.UnPrim (!ot, o), [exp e]) @@ -72,7 +72,7 @@ and exp' at note = function | S.ProjE (e, i) -> (projE (exp e) i).it | S.OptE e -> (optE (exp e)).it | S.ObjE (s, es) -> - obj at s None es note.I.note_typ + obj at s None es note.Note.typ | S.TagE (c, e) -> (tagE c.it (exp e)).it | S.DotE (e, x) when T.is_array e.note.S.note_typ -> (array_dotE e.note.S.note_typ x.it (exp e)).it @@ -87,7 +87,7 @@ and exp' at note = function end | S.AssignE (e1, e2) -> I.AssignE (lexp e1, exp e2) | S.ArrayE (m, es) -> - let t = T.as_array note.I.note_typ in + let t = T.as_array note.Note.typ in I.PrimE (I.ArrayPrim (mut m, T.as_immut t), exps es) | S.IdxE (e1, e2) -> I.PrimE (I.IdxPrim, [exp e1; exp e2]) | S.FuncE (name, sp, tbs, p, _t_opt, _, e) -> @@ -96,7 +96,7 @@ and exp' at note = function | T.Shared (ss, {it = S.WildP; _} ) -> (* don't bother with ctxt pat *) (T.Shared ss, None) | T.Shared (ss, sp) -> (T.Shared ss, Some sp) in - let args, wrap, control, res_tys = to_args note.I.note_typ po p in + let args, wrap, control, res_tys = to_args note.Note.typ po p in let tbs' = typ_binds tbs in let vars = List.map (fun (tb : I.typ_bind) -> T.Con (tb.it.I.con, [])) tbs' in let tys = List.map (T.open_ vars) res_tys in @@ -125,7 +125,7 @@ and exp' at note = function I.PrimE (I.CallPrim inst.note, [exp e1; exp e2]) | S.BlockE [] -> unitE.it | S.BlockE [{it = S.ExpD e; _}] -> (exp e).it - | S.BlockE ds -> I.BlockE (block (T.is_unit note.I.note_typ) ds) + | S.BlockE ds -> I.BlockE (block (T.is_unit note.Note.typ) ds) | S.NotE e -> I.IfE (exp e, falseE, trueE) | S.AndE (e1, e2) -> I.IfE (exp e1, exp e2, falseE) | S.OrE (e1, e2) -> I.IfE (exp e1, trueE, exp e2) @@ -143,7 +143,7 @@ and exp' at note = function | S.ThrowE e -> I.PrimE (I.ThrowPrim, [exp e]) | S.AsyncE (tb, e) -> I.AsyncE (typ_bind tb, exp e, - match note.I.note_typ with + match note.Note.typ with | T.Async (t, _) -> t | _ -> assert false) | S.AwaitE e -> I.PrimE (I.AwaitPrim, [exp e]) @@ -154,7 +154,7 @@ and exp' at note = function | S.Unresolved -> raise (Invalid_argument ("Unresolved import " ^ f)) | S.LibPath fp -> I.VarE (id_of_full_path fp).it | S.PrimPath -> I.VarE (id_of_full_path "@prim").it - | S.IDLPath (fp, blob_id) -> I.(PrimE (ActorOfIdBlob note.note_typ, [blobE blob_id])) + | S.IDLPath (fp, blob_id) -> I.(PrimE (ActorOfIdBlob note.Note.typ, [blobE blob_id])) end | S.PrimE s -> raise (Invalid_argument ("Unapplied prim " ^ s)) @@ -164,7 +164,7 @@ and url e = | S.AnnotE (e,_) -> url e | _ -> let transformed = typed_phrase' (url' e) e in - I.{ transformed with note = { transformed.note with note_typ = T.blob } } + { transformed with note = Note.{ transformed.note with typ = T.blob } } and url' e at _ _ = I.(PrimE (BlobOfIcUrl, [exp e])) @@ -338,9 +338,9 @@ and dec' at n d = match d with it = I.FuncE (id.it, sort, control, typ_binds tbs, args, [obj_typ], wrap { it = obj at s (Some self_id) es obj_typ; at = at; - note = { I.note_typ = obj_typ; I.note_eff = T.Triv } }); + note = Note.{ def with typ = obj_typ } }); at = at; - note = { I.note_typ = fun_typ; I.note_eff = T.Triv } + note = Note.{ def with typ = fun_typ } } in I.LetD (varPat, fn) From b68a5b36ada9976afd544e317c03c97c28d4cfa7 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 3 Apr 2020 15:43:05 +0200 Subject: [PATCH 1153/1176] construct.ml: Make var a spearate type from exp (#1330) this is more principled, and it might really help with #1329 --- src/ir_def/construct.ml | 87 ++++++++++++----------------- src/ir_def/construct.mli | 18 +++--- src/ir_passes/async.ml | 64 ++++++++++++---------- src/ir_passes/await.ml | 112 +++++++++++++++++++------------------- src/ir_passes/show.ml | 45 +++++++-------- src/ir_passes/tailcall.ml | 8 +-- src/lowering/desugar.ml | 34 ++++++------ 7 files changed, 181 insertions(+), 187 deletions(-) diff --git a/src/ir_def/construct.ml b/src/ir_def/construct.ml index 30a37541447..b0969470ff9 100644 --- a/src/ir_def/construct.ml +++ b/src/ir_def/construct.ml @@ -5,8 +5,6 @@ open Ir_effect module Con = Mo_types.Con module T = Mo_types.Type -type var = exp - (* Field names *) let nameN s = s @@ -15,24 +13,12 @@ let nextN = "next" (* Identifiers *) -let idE id typ = - { it = VarE id; - at = no_region; - note = Note.{ def with typ = typ } - } +type var = (string * T.typ) -let id_of_exp x = - match x.it with - | VarE x -> x - | _ -> failwith "Impossible: id_of_exp" +let var id typ = (id, typ) -let arg_of_exp x = - match x.it with - | VarE i -> { it = i; at = x.at; note = x.note.Note.typ } - | _ -> failwith "Impossible: arg_of_exp" - -let exp_of_arg a = - idE a.it a.note +let id_of_var (id, _) = id +let typ_of_var (_, typ) = typ (* Fresh id generation *) @@ -47,9 +33,9 @@ let fresh name_base () : string = let fresh_id name_base () : id = fresh name_base () -let fresh_var name_base typ : exp = +let fresh_var name_base typ : var = let name = fresh name_base () in - idE name typ + var name typ let fresh_vars name_base ts = List.mapi (fun i t -> fresh_var (Printf.sprintf "%s%i" name_base i) t) ts @@ -57,10 +43,10 @@ let fresh_vars name_base ts = (* Patterns *) -let varP x = - { it = VarP (id_of_exp x); - at = x.at; - note = x.note.Note.typ +let varP (n, typ) = + { it = VarP n; + at = no_region; + note = typ } let tupP pats = @@ -75,6 +61,9 @@ let seqP ps = (* Primitives *) +let varE (id, typ) = + { it = VarE id; at = no_region; note = Note.{ def with typ } } + let primE prim es = let typ = match prim with | ShowPrim _ -> T.text @@ -319,9 +308,9 @@ let lexp_of_exp' = function let lexp_of_exp (e:exp) = { e with it = lexp_of_exp' e.it; note = typ e } -let assignE exp1 exp2 = - assert (T.is_mut (typ exp1)); - { it = AssignE (lexp_of_exp exp1, exp2); +let assignE v exp2 = + assert (T.is_mut (typ_of_var v)); + { it = AssignE (lexp_of_exp (varE v), exp2); at = no_region; note = Note.{ def with typ = T.unit; eff = eff exp2 }; } @@ -371,13 +360,12 @@ let expD exp = let pat = { it = WildP; at = exp.at; note = exp.note.Note.typ } in LetD (pat, exp) @@ exp.at -let let_no_shadow x exp decs = - let id = id_of_exp x in +let let_no_shadow (id, typ) exp decs = (* could be replaced by a more simple “defined by this decs” function *) let (_,f) = Freevars.decs decs in if Freevars.S.mem id f then decs - else [ letD x exp ] @ decs + else [ letD (id, typ) exp ] @ decs (* Derived expressions *) @@ -392,6 +380,10 @@ let ignoreE exp = (* Mono-morphic function expression *) +let arg_of_var (id, typ) = + { it = id; at = no_region; note = typ } +let var_of_arg { it = id; note = typ; _} = (id, typ) + let funcE name typ x exp = let sort, control, arg_tys, ret_tys = match typ with | T.Func(s, c, _, ts1, ts2) -> s, c, ts1, ts2 @@ -399,11 +391,11 @@ let funcE name typ x exp = let args, exp' = if List.length arg_tys = 1; then - [ arg_of_exp x ], exp + [ arg_of_var x ], exp else let vs = fresh_vars "param" arg_tys in - List.map arg_of_exp vs, - blockE [letD x (tupE vs)] exp + List.map arg_of_var vs, + blockE [letD x (tupE (List.map varE vs))] exp in ({it = FuncE ( name, @@ -429,7 +421,7 @@ let nary_funcE name typ xs exp = sort, control, [], - List.map arg_of_exp xs, + List.map arg_of_var xs, ret_tys, exp ); @@ -438,19 +430,12 @@ let nary_funcE name typ xs exp = }) (* Mono-morphic function declaration, sharing inferred from f's type *) -let funcD f x exp = - match f.it, x.it with - | VarE _, VarE _ -> - letD f (funcE (id_of_exp f) (typ f) x exp) - | _ -> failwith "Impossible: funcD" +let funcD ((id, typ) as f) x exp = + letD f (funcE id typ x exp) (* Mono-morphic, n-ary function declaration *) -let nary_funcD f xs exp = - match f.it with - | VarE _ -> - letD f (nary_funcE (id_of_exp f) (typ f) xs exp) - | _ -> failwith "Impossible: funcD" - +let nary_funcD ((id, typ) as f) xs exp = + letD f (nary_funcE id typ xs exp) (* Continuation types *) @@ -462,10 +447,6 @@ let err_contT = T.Func (T.Local, T.Returns, [], [T.catch], []) let cpsT typ = T.Func (T.Local, T.Returns, [], [contT typ; err_contT], []) -let fresh_cont typ = fresh_var "k" (contT typ) - -let fresh_err_cont () = fresh_var "r" (err_contT) - (* Sequence expressions *) let seqE es = @@ -479,12 +460,12 @@ let seqE es = (* local lambda *) let (-->) x exp = - let fun_ty = T.Func (T.Local, T.Returns, [], T.as_seq (typ x), T.as_seq (typ exp)) in + let fun_ty = T.Func (T.Local, T.Returns, [], T.as_seq (typ_of_var x), T.as_seq (typ exp)) in funcE "$lambda" fun_ty x exp (* n-ary local lambda *) let (-->*) xs exp = - let fun_ty = T.Func (T.Local, T.Returns, [], List.map typ xs, T.as_seq (typ exp)) in + let fun_ty = T.Func (T.Local, T.Returns, [], List.map typ_of_var xs, T.as_seq (typ exp)) in nary_funcE "$lambda" fun_ty xs exp let close_typ_binds cs tbs = @@ -577,7 +558,7 @@ let forE pat exp1 exp2 = letE nxt (dotE exp1 (nameN "next") tnxt) ( labelE lab T.unit ( loopE ( - switch_optE (callE nxt [] (tupE [])) + switch_optE (callE (varE nxt) [] (tupE [])) (breakE lab (tupE [])) pat exp2 T.unit ) @@ -585,6 +566,6 @@ let forE pat exp1 exp2 = ) let unreachableE = - (* Do we want UnreachableE in the AST *) + (* Do we want a dedicated UnreachableE in the AST? *) loopE unitE diff --git a/src/ir_def/construct.mli b/src/ir_def/construct.mli index 4148897f291..168681553a7 100644 --- a/src/ir_def/construct.mli +++ b/src/ir_def/construct.mli @@ -11,7 +11,6 @@ open Type at the loss of some precision in OCaml typing. *) -type var = exp (* Field names *) @@ -20,14 +19,18 @@ val nextN : Type.lab (* Identifiers *) +type var + +val var : string -> typ -> var +val id_of_var : var -> string +val typ_of_var : var -> typ +val arg_of_var : var -> arg +val var_of_arg : arg -> var + val fresh_id : string -> unit -> id val fresh_var : string -> typ -> var val fresh_vars : string -> typ list -> var list -val idE : id -> typ -> exp -val id_of_exp : var -> id -val arg_of_exp : var -> arg -val exp_of_arg : arg -> var (* Patterns *) @@ -38,6 +41,7 @@ val seqP : pat list -> pat (* Expressions *) +val varE : var -> exp val primE : Ir.prim -> exp list -> exp val selfRefE : typ -> exp val asyncE : typ -> typ -> exp -> exp @@ -68,7 +72,7 @@ val tupE : exp list -> exp val breakE: id -> exp -> exp val retE: exp -> exp val immuteE: exp -> exp -val assignE : exp -> exp -> exp +val assignE : var -> exp -> exp val labelE : id -> typ -> exp -> exp val loopE : exp -> exp val forE : pat -> exp -> exp -> exp @@ -98,8 +102,6 @@ val answerT : typ val contT : typ -> typ val err_contT : typ val cpsT : typ -> typ -val fresh_cont : typ -> var -val fresh_err_cont : unit -> var (* Sequence expressions *) diff --git a/src/ir_passes/async.ml b/src/ir_passes/async.ml index da88fd9344e..4a9c06c1605 100644 --- a/src/ir_passes/async.ml +++ b/src/ir_passes/async.ml @@ -58,11 +58,11 @@ let new_asyncT = new_async_ret unary (T.Var ("T", 0)) ) -let new_asyncE = - idE "@new_async" new_asyncT +let new_asyncE () = + varE (var "@new_async" new_asyncT) let new_async t1 = - let call_new_async = callE new_asyncE [t1] (tupE []) in + let call_new_async = callE (new_asyncE ()) [t1] (tupE []) in let async = fresh_var "async" (typ (projE call_new_async 0)) in let fulfill = fresh_var "fulfill" (typ (projE call_new_async 1)) in let fail = fresh_var "fail" (typ (projE call_new_async 2)) in @@ -77,12 +77,14 @@ let new_nary_async_reply mode ts1 = let nary_async = match ts1 with | [t] -> - unary_async + varE unary_async | ts -> let k' = fresh_var "k" (contT t1) in let r' = fresh_var "r" err_contT in - let seq_of_v' = tupE (List.mapi (fun i _ -> projE v' i) ts) in - [k';r'] -->* (unary_async -*- (tupE[([v'] -->* (k' -*- seq_of_v'));r'])) + let seq_of_v' = tupE (List.mapi (fun i _ -> projE (varE v') i) ts) in + [k';r'] -->* ( + varE unary_async -*- (tupE[([v'] -->* (varE k' -*- seq_of_v')); varE r']) + ) in (* construct the n-ary reply callback that sends a sequence of values to fulfill the async *) let nary_reply = @@ -90,27 +92,27 @@ let new_nary_async_reply mode ts1 = match ts1 with | [t] -> let v = fresh_var "rep" t in - [v],v + [v], varE v | ts -> let vs = fresh_vars "rep" ts in - vs, tupE vs + vs, tupE (List.map varE vs) in - vs -->* (unary_fulfill -*- seq_of_vs) + vs -->* (varE unary_fulfill -*- seq_of_vs) in let async,reply,reject = fresh_var "async" (typ nary_async), fresh_var "reply" (typ nary_reply), - fresh_var "reject" (typ fail) + fresh_var "reject" (typ_of_var fail) in (async, reply, reject), blockE [letP (tupP [varP unary_async; varP unary_fulfill; varP fail]) call_new_async] - (tupE [nary_async; nary_reply; fail]) + (tupE [nary_async; nary_reply; varE fail]) let letEta e scope = match e.it with | VarE _ -> scope e (* pure, so reduce *) | _ -> let f = fresh_var "x" (typ e) in - letD f e :: (scope f) (* maybe impure; sequence *) + letD f e :: (scope (varE f)) (* maybe impure; sequence *) let isAwaitableFunc exp = match typ exp with @@ -244,14 +246,16 @@ let transform mode env prog = let ((nary_async, nary_reply, reject), def) = new_nary_async_reply mode ts1 in (blockE [ letP (tupP [varP nary_async; varP nary_reply; varP reject]) def; - let v = fresh_var "v" (T.seq ts1) in (* flatten v, here and below? *) - let ic_reply = v --> (ic_replyE ts1 v) in - let e = fresh_var "e" T.catch in - let ic_reject = [e] -->* (ic_rejectE (errorMessageE e)) in + let ic_reply = (* flatten v, here and below? *) + let v = fresh_var "v" (T.seq ts1) in + v --> (ic_replyE ts1 (varE v)) in + let ic_reject = + let e = fresh_var "e" T.catch in + [e] -->* (ic_rejectE (errorMessageE (varE e))) in let exp' = callE (t_exp exp1) [t0] (tupE [ic_reply; ic_reject]) in - expD (selfcallE ts1 exp' nary_reply reject) + expD (selfcallE ts1 exp' (varE nary_reply) (varE reject)) ] - nary_async + (varE nary_async) ).it | PrimE (CallPrim typs, [exp1; exp2]) when isAwaitableFunc exp1 -> let ts1,ts2 = @@ -268,11 +272,11 @@ let transform mode env prog = (blockE ( letP (tupP [varP nary_async; varP nary_reply; varP reject]) def :: letEta exp1' (fun v1 -> letSeq ts1 exp2' (fun vs -> - [ expD (ic_callE v1 (seqE vs) nary_reply reject) ] + [ expD (ic_callE v1 (seqE (List.map varE vs)) (varE nary_reply) (varE reject)) ] ) ) ) - nary_async) + (varE nary_async)) .it | PrimE (p, exps) -> PrimE (prim p, List.map t_exp exps) @@ -319,10 +323,12 @@ let transform mode env prog = []) -> (t_typ (T.seq (List.map (T.open_ [t0]) ts1)),t_typ (T.open_ [t0] contT)) | t -> assert false in - let v = fresh_var "v" t1 in - let k = v --> (ic_replyE ret_tys v) in - let e = fresh_var "e" T.catch in - let r = [e] -->* (ic_rejectE (errorMessageE e)) in + let k = + let v = fresh_var "v" t1 in + v --> (ic_replyE ret_tys (varE v)) in + let r = + let e = fresh_var "e" T.catch in + [e] -->* (ic_rejectE (errorMessageE (varE e))) in let exp' = callE (t_exp cps) [t0] (tupE [k;r]) in FuncE (x, T.Shared s', Replies, typbinds', args', ret_tys, exp') (* oneway, always with `ignore(async _)` body *) @@ -346,10 +352,12 @@ let transform mode env prog = []) -> (t_typ (T.seq (List.map (T.open_ [t0]) ts1)),t_typ (T.open_ [t0] contT)) | t -> assert false in - let v = fresh_var "v" t1 in - let k = v --> tupE [] in (* discard return *) - let e = fresh_var "e" T.catch in - let r = [e] -->* tupE [] in (* discard error *) + let k = + let v = fresh_var "v" t1 in + v --> tupE [] in (* discard return *) + let r = + let e = fresh_var "e" T.catch in + [e] -->* tupE [] in (* discard error *) let exp' = callE (t_exp cps) [t0] (tupE [k;r]) in FuncE (x, T.Shared s', Returns, typbinds', args', ret_tys, exp') | Returns, _ -> diff --git a/src/ir_passes/await.ml b/src/ir_passes/await.ml index 7794dee9889..be74059cc0f 100644 --- a/src/ir_passes/await.ml +++ b/src/ir_passes/await.ml @@ -8,10 +8,14 @@ module R = Rename module T = Type open Construct +let fresh_cont typ = fresh_var "k" (contT typ) + +let fresh_err_cont () = fresh_var "r" (err_contT) + (* continuations, syntactic and meta-level *) -type kont = ContVar of exp - | MetaCont of T.typ * (exp -> exp) +type kont = ContVar of var + | MetaCont of T.typ * (var -> exp) let meta typ exp = let expanded = ref false in @@ -37,11 +41,11 @@ type label = Return | Throw | Named of string let ( -@- ) k exp2 = match k with - | ContVar exp1 -> - exp1 -*- exp2 - | MetaCont (typ,k) -> + | ContVar v -> + varE v -*- exp2 + | MetaCont (typ, k) -> match exp2.it with - | VarE _ -> k exp2 + | VarE v -> k (var v exp2.note.Note.typ) | _ -> let u = fresh_var "u" typ in letE u exp2 (k u) @@ -84,14 +88,14 @@ and t_exp' context exp' = | PrimE (BreakPrim id, [exp1]) -> begin match LabelEnv.find_opt (Named id) context with - | Some (Cont k) -> (retE (k -@- (t_exp context exp1))).it + | Some (Cont k) -> (retE (k -@- t_exp context exp1)).it | Some Label -> (breakE id (t_exp context exp1)).it | None -> assert false end | PrimE (RetPrim, [exp1]) -> begin match LabelEnv.find_opt Return context with - | Some (Cont k) -> (retE (k -@- (t_exp context exp1))).it + | Some (Cont k) -> (retE (k -@- t_exp context exp1)).it | Some Label -> (retE (t_exp context exp1)).it | None -> assert false end @@ -155,15 +159,15 @@ and binary context k binE e1 e2 = | T.Triv, T.Await -> let v1 = fresh_var "v" (typ e1) in (* TBR *) letE v1 (t_exp context e1) - (c_exp context e2 (meta (typ e2) (fun v2 -> k -@- binE v1 v2))) + (c_exp context e2 (meta (typ e2) (fun v2 -> k -@- binE (varE v1) (varE v2)))) | T.Await, T.Await -> c_exp context e1 (meta (typ e1) (fun v1 -> c_exp context e2 (meta (typ e2) (fun v2 -> - k -@- binE v1 v2)))) + k -@- binE (varE v1) (varE v2))))) | T.Await, T.Triv -> - c_exp context e1 (meta (typ e1) (fun v1 -> k -@- binE v1 (t_exp context e2))) + c_exp context e1 (meta (typ e1) (fun v1 -> k -@- binE (varE v1) (t_exp context e2))) | T.Triv, T.Triv -> assert false @@ -179,10 +183,10 @@ and nary context k naryE es = | T.Triv -> let v1 = fresh_var "v" (typ e1) in letE v1 (t_exp context e1) - (nary_aux (v1 :: vs) es) + (nary_aux (varE v1 :: vs) es) | T.Await -> c_exp context e1 - (meta (typ e1) (fun v1 -> nary_aux (v1 :: vs) es)) + (meta (typ e1) (fun v1 -> nary_aux (varE v1 :: vs) es)) in nary_aux [] es @@ -190,7 +194,7 @@ and nary context k naryE es = and c_if context k e1 e2 e3 = letcont k (fun k -> let trans_branch exp = match eff exp with - | T.Triv -> k -*- t_exp context exp + | T.Triv -> varE k -*- t_exp context exp | T.Await -> c_exp context exp (ContVar k) in let e2 = trans_branch e2 in @@ -199,24 +203,24 @@ and c_if context k e1 e2 e3 = | T.Triv -> ifE (t_exp context e1) e2 e3 answerT | T.Await -> - c_exp context e1 (meta (typ e1) (fun v1 -> ifE v1 e2 e3 answerT)) + c_exp context e1 (meta (typ e1) (fun v1 -> ifE (varE v1) e2 e3 answerT)) ) and c_loop context k e1 = - let loop = fresh_var "loop" (contT T.unit) in match eff e1 with | T.Triv -> assert false | T.Await -> + let loop = fresh_var "loop" (contT T.unit) in let v1 = fresh_var "v" T.unit in blockE [funcD loop v1 (c_exp context e1 (ContVar loop))] - (loop -*- unitE) + (varE loop -*- unitE) and c_assign context k e lexp1 exp2 = match lexp1.it with | VarLE _ -> - unary context k (fun v2 -> e (AssignE(lexp1, v2))) exp2 + unary context k (fun v2 -> e (AssignE(lexp1, varE v2))) exp2 | DotLE (exp11, id) -> binary context k (fun v11 v2 -> e (AssignE ({lexp1 with it = DotLE (v11, id)}, v2))) exp11 exp2 @@ -253,7 +257,7 @@ and c_exp' context exp k = let cases' = List.map (fun {it = {pat;exp}; at; note} -> let exp' = match eff exp with - | T.Triv -> k -*- (t_exp context exp) + | T.Triv -> varE k -*- (t_exp context exp) | T.Await -> c_exp context exp (ContVar k) in {it = { pat; exp = exp' }; at; note}) @@ -269,7 +273,7 @@ and c_exp' context exp k = c_exp context exp1 (meta (typ exp1) (fun v1 -> - { it = SwitchE(v1, cases'); + { it = SwitchE(varE v1, cases'); at = exp.at; note = Note.{ exp.note with typ = answerT } })) end) @@ -278,36 +282,36 @@ and c_exp' context exp k = let f = match LabelEnv.find Throw context with Cont f -> f | _ -> assert false in letcont f (fun f -> letcont k (fun k -> - let cases' = List.map - (fun {it = {pat;exp}; at; note} -> - let exp' = match eff exp with - | T.Triv -> k -*- (t_exp context exp) - | T.Await -> c_exp context exp (ContVar k) - in - { it = {pat;exp = exp' }; at; note }) - cases - in - let error = fresh_var "v" T.catch in - let cases' = cases' @ [ - { it = {pat = varP error; exp = f -*- error}; - at = no_region; - note = () }] in - let throw = fresh_err_cont () in - let e = fresh_var "e" T.catch in - let context' = LabelEnv.add Throw (Cont (ContVar throw)) context in - begin match eff exp1 with | T.Triv -> - k -*- (t_exp context exp1) + varE k -*- (t_exp context exp1) | T.Await -> + let error = fresh_var "v" T.catch in + let cases' = + List.map + (fun {it = {pat;exp}; at; note} -> + let exp' = match eff exp with + | T.Triv -> varE k -*- (t_exp context exp) + | T.Await -> c_exp context exp (ContVar k) + in + { it = {pat;exp = exp' }; at; note }) + cases + @ [{ it = {pat = varP error; exp = varE f -*- varE error}; + at = no_region; + note = () + }] in + let throw = fresh_err_cont () in + let context' = LabelEnv.add Throw (Cont (ContVar throw)) context in blockE - [funcD throw e { - it = SwitchE (e, cases'); - at = exp.at; - note = Note.{ def with typ = T.unit; eff = T.Await; (* shouldn't matter *) } - }] + [ let e = fresh_var "e" T.catch in + funcD throw e { + it = SwitchE (varE e, cases'); + at = exp.at; + note = Note.{ def with typ = T.unit; eff = T.Await; (* shouldn't matter *) } + } + ] (c_exp context' exp1 (ContVar k)) - end)) + )) | LoopE exp1 -> c_loop context k exp1 | LabelE (id, _typ, exp1) -> @@ -356,18 +360,18 @@ and c_exp' context exp k = in letcont r (fun r -> letcont k (fun k -> - let kr = tupE [k;r] in + let kr = tupE [varE k; varE r] in match eff exp1 with | T.Triv -> awaitE (typ exp) (t_exp context exp1) kr | T.Await -> c_exp context exp1 - (meta (typ exp1) (fun v1 -> (awaitE (typ exp) v1 kr))) + (meta (typ exp1) (fun v1 -> (awaitE (typ exp) (varE v1) kr))) )) | DeclareE (id, typ, exp1) -> - unary context k (fun v1 -> e (DeclareE (id, typ, v1))) exp1 + unary context k (fun v1 -> e (DeclareE (id, typ, varE v1))) exp1 | DefineE (id, mut, exp1) -> - unary context k (fun v1 -> e (DefineE (id, mut, v1))) exp1 + unary context k (fun v1 -> e (DefineE (id, mut, varE v1))) exp1 | NewObjE _ -> exp | SelfCallE _ -> assert false | PrimE (p, exps) -> @@ -390,8 +394,7 @@ and c_dec context dec (k:kont) = | T.Triv -> block (t_exp context exp) | T.Await -> - c_exp context exp (meta (typ exp) - (fun v -> block v)) + c_exp context exp (meta (typ exp) (fun v -> block (varE v))) end | VarD (id, _typ, exp) -> begin @@ -401,7 +404,7 @@ and c_dec context dec (k:kont) = | T.Await -> c_exp context exp (meta (typ exp) - (fun v -> k -@- define_idE id Var v)) + (fun v -> k -@- define_idE id Var (varE v))) end @@ -456,8 +459,7 @@ and rename_pat' pat = | LitP _ -> (PatEnv.empty, pat.it) | VarP id -> let v = fresh_var "v" pat.note in - (PatEnv.singleton id v, - VarP (id_of_exp v)) + (PatEnv.singleton id v, VarP (id_of_var v)) | TupP pats -> let (patenv,pats') = rename_pats pats in (patenv,TupP pats') @@ -490,7 +492,7 @@ and define_pat patenv pat : dec list = | LitP _ -> [] | VarP id -> - [ expD (define_idE id Const (PatEnv.find id patenv)) ] + [ expD (define_idE id Const (varE (PatEnv.find id patenv))) ] | TupP pats -> define_pats patenv pats | ObjP pfs -> define_pats patenv (pats_of_obj_pat pfs) | OptP pat1 diff --git a/src/ir_passes/show.ml b/src/ir_passes/show.ml index b5a977f903e..66c57027ac9 100644 --- a/src/ir_passes/show.ml +++ b/src/ir_passes/show.ml @@ -57,7 +57,7 @@ let show_fun_typ_for t = T.Func (T.Local, T.Returns, [], [t], [T.text]) let show_var_for t : Construct.var = - idE (show_name_for t) (show_fun_typ_for t) + var (show_name_for t) (show_fun_typ_for t) (* Construction helpers *) @@ -65,43 +65,44 @@ let show_var_for t : Construct.var = (* Many of these are simply the entry points for helper functions defined in the prelude. *) -let argE t = idE "x" t +let argVar t = var "x" t +let argE t = varE (argVar t) let define_show : T.typ -> Ir.exp -> Ir.dec = fun t e -> - Construct.funcD (show_var_for t) (argE t) e + Construct.funcD (show_var_for t) (argVar t) e let invoke_generated_show : T.typ -> Ir.exp -> Ir.exp = fun t e -> - show_var_for t -*- e + varE (show_var_for t) -*- e let invoke_prelude_show : string -> T.typ -> Ir.exp -> Ir.exp = fun n t e -> let fun_typ = T.Func (T.Local, T.Returns, [], [t], [T.text]) in - idE n fun_typ -*- argE t + varE (var n fun_typ) -*- argE t let invoke_text_of_option : T.typ -> Ir.exp -> Ir.exp -> Ir.exp = fun t f e -> let fun_typ = T.Func (T.Local, T.Returns, [{T.var="T";T.sort=T.Type;T.bound=T.Any}], [show_fun_typ_for (T.Var ("T",0)); T.Opt (T.Var ("T",0))], [T.text]) in - callE (idE "@text_of_option" fun_typ) [t] (tupE [f; e]) + callE (varE (var "@text_of_option" fun_typ)) [t] (tupE [f; e]) let invoke_text_of_variant : T.typ -> Ir.exp -> T.lab -> Ir.exp -> Ir.exp = fun t f l e -> let fun_typ = T.Func (T.Local, T.Returns, [{T.var="T";T.sort=T.Type;T.bound=T.Any}], [T.text; show_fun_typ_for (T.Var ("T",0)); T.Var ("T",0)], [T.text]) in - callE (idE "@text_of_variant" fun_typ) [t] (tupE [textE l; f; e]) + callE (varE (var "@text_of_variant" fun_typ)) [t] (tupE [textE l; f; e]) let invoke_text_of_array : T.typ -> Ir.exp -> Ir.exp -> Ir.exp = fun t f e -> let fun_typ = T.Func (T.Local, T.Returns, [{T.var="T";T.sort=T.Type;T.bound=T.Any}], [show_fun_typ_for (T.Var ("T",0)); T.Array (T.Var ("T",0))], [T.text]) in - callE (idE "@text_of_array" fun_typ) [t] (tupE [f; e]) + callE (varE (var "@text_of_array" fun_typ)) [t] (tupE [f; e]) let invoke_text_of_array_mut : T.typ -> Ir.exp -> Ir.exp -> Ir.exp = fun t f e -> let fun_typ = T.Func (T.Local, T.Returns, [{T.var="T";T.sort=T.Type;T.bound=T.Any}], [show_fun_typ_for (T.Var ("T",0)); T.Array (T.Mut (T.Var ("T",0)))], [T.text]) in - callE (idE "@text_of_array_mut" fun_typ) [t] (tupE [f; e]) + callE (varE (var "@text_of_array_mut" fun_typ)) [t] (tupE [f; e]) -let list_build : 'a -> 'a -> 'a -> 'a list -> 'a list = fun pre sep post xs -> +let list_build : 'a -> (unit -> 'a) -> 'a -> 'a list -> 'a list = fun pre sep post xs -> let rec go = function | [] -> [ post ] | [x] -> [ x; post ] - | x::xs -> [ x; sep ] @ go xs + | x::xs -> [ x; sep () ] @ go xs in [ pre ] @ go xs let catE : Ir.exp -> Ir.exp -> Ir.exp = fun e1 e2 -> @@ -172,45 +173,45 @@ let show_for : T.typ -> Ir.dec * T.typ list = fun t -> define_show t (invoke_prelude_show "@text_of_Char" t (argE t)), [] | T.(Prim Null) -> - define_show t (textE ("null")), + define_show t (textE "null"), [] | T.Func _ -> - define_show t (textE ("func")), + define_show t (textE "func"), [] | T.Con (c,_) -> (* t is normalized, so this is a type parameter *) define_show t (textE ("show_for: cannot handle type parameter " ^ T.string_of_typ t)), [] | T.Tup [] -> - define_show t (textE ("()")), + define_show t (textE "()"), [] | T.Tup ts' -> let ts' = List.map T.normalize ts' in define_show t ( cat_list (list_build - (textE "(") (textE ", ") (textE ")") + (textE "(") (fun () -> textE ", ") (textE ")") (List.mapi (fun i t' -> invoke_generated_show t' (projE (argE t) i)) ts') ) ), ts' | T.Opt t' -> let t' = T.normalize t' in - define_show t (invoke_text_of_option t' (show_var_for t') (argE t)), + define_show t (invoke_text_of_option t' (varE (show_var_for t')) (argE t)), [t'] | T.Array t' -> let t' = T.normalize t' in begin match t' with | T.Mut t' -> - define_show t (invoke_text_of_array_mut t' (show_var_for t') (argE t)), + define_show t (invoke_text_of_array_mut t' (varE (show_var_for t')) (argE t)), [t'] | _ -> - define_show t (invoke_text_of_array t' (show_var_for t') (argE t)), + define_show t (invoke_text_of_array t' (varE (show_var_for t')) (argE t)), [t'] end | T.Obj (T.Object, fs) -> define_show t ( cat_list (list_build - (textE "{") (textE "; ") (textE "}") + (textE "{") (fun () -> textE "; ") (textE "}") (List.map (fun f -> let t' = T.as_immut (T.normalize f.Type.typ) in catE @@ -228,8 +229,8 @@ let show_for : T.typ -> Ir.dec * T.typ list = fun t -> (List.map (fun {T.lab = l; typ = t'} -> let t' = T.normalize t' in l, - (varP (argE t')), (* Shadowing, but that's fine *) - (invoke_text_of_variant t' (show_var_for t') l (argE t')) + (varP (argVar t')), (* Shadowing, but that's fine *) + (invoke_text_of_variant t' (varE (show_var_for t')) l (argE t')) ) fs) (T.text) ), @@ -273,7 +274,7 @@ and t_exp' env = function | PrimE (ShowPrim ot, [exp1]) -> let t' = T.normalize ot in add_type env t'; - (idE (show_name_for t') (show_fun_typ_for t') -*- t_exp env exp1).it + (varE (show_var_for t') -*- t_exp env exp1).it | PrimE (p, es) -> PrimE (p, t_exps env es) | AssignE (lexp1, exp2) -> AssignE (t_lexp env lexp1, t_exp env exp2) diff --git a/src/ir_passes/tailcall.ml b/src/ir_passes/tailcall.ml index 4f1f603d1bd..011930d7d86 100644 --- a/src/ir_passes/tailcall.ml +++ b/src/ir_passes/tailcall.ml @@ -89,7 +89,7 @@ and assignEs vars exp : dec list = | _, _ -> let tup = fresh_var "tup" (typ exp) in letD tup exp :: - List.mapi (fun i v -> expD (assignE v (projE v i))) vars + List.mapi (fun i v -> expD (assignE v (projE (varE v) i))) vars and exp' env e : exp' = match e.it with | VarE _ | LitE _ -> e.it @@ -209,15 +209,15 @@ and dec' env d = in let l_typ = Type.unit in let body = - blockE (List.map2 (fun t i -> varD (id_of_exp t) (typ i) i) temps ids) ( + blockE (List.map2 (fun t i -> varD (id_of_var t) (typ_of_var i) (varE i)) temps ids) ( loopE ( labelE label l_typ (blockE - (List.map2 (fun a t -> letD (exp_of_arg a) (immuteE t)) as_ temps) + (List.map2 (fun a t -> letD (var_of_arg a) (immuteE (varE t))) as_ temps) (retE exp0')) ) ) in - LetD (id_pat, {funexp with it = FuncE (x, Local, c, tbs, List.map arg_of_exp ids, typT, body)}) + LetD (id_pat, {funexp with it = FuncE (x, Local, c, tbs, List.map arg_of_var ids, typT, body)}) else LetD (id_pat, {funexp with it = FuncE (x, Local, c, tbs, as_, typT, exp0')}) end, diff --git a/src/lowering/desugar.ml b/src/lowering/desugar.ml index 65872c9270d..af4d327c615 100644 --- a/src/lowering/desugar.ml +++ b/src/lowering/desugar.ml @@ -206,7 +206,7 @@ and build_fields obj_typ = | _ -> assert false and with_self i typ decs = - let_no_shadow (idE i typ) (selfRefE typ) decs + let_no_shadow (var i typ) (selfRefE typ) decs and build_actor at self_id es obj_typ = let fs = build_fields obj_typ in @@ -222,7 +222,7 @@ and build_obj at s self_id es obj_typ = let ret_ds, ret_o = match self_id with | None -> [], obj_e - | Some id -> let self = idE id.it obj_typ in [ letD self obj_e ], self + | Some id -> let self = var id.it obj_typ in [ letD self obj_e ], varE self in I.BlockE (decs (List.map (fun ef -> ef.it.S.dec) es) @ ret_ds, ret_o) and typ_binds tbs = List.map typ_bind tbs @@ -247,8 +247,8 @@ and array_dotE array_ty proj e = then T.Array (T.Mut varA) else T.Array varA in let ty_param = {T.var = "A"; sort = T.Type; T.bound = T.Any} in - let f = idE name (fun_ty [ty_param] [poly_array_ty] [fun_ty [] t1 t2]) in - callE f [element_ty] e in + let f = var name (fun_ty [ty_param] [poly_array_ty] [fun_ty [] t1 t2]) in + callE (varE f) [element_ty] e in match T.is_mut (T.as_array array_ty), proj with | true, "len" -> call "@mut_array_len" [] [T.nat] | false, "len" -> call "@immut_array_len" [] [T.nat] @@ -264,8 +264,8 @@ and array_dotE array_ty proj e = and blob_dotE proj e = let fun_ty t1 t2 = T.Func (T.Local, T.Returns, [], t1, t2) in let call name t1 t2 = - let f = idE name (fun_ty [T.blob] [fun_ty t1 t2]) in - callE f [] e in + let f = var name (fun_ty [T.blob] [fun_ty t1 t2]) in + callE (varE f) [] e in match proj with | "size" -> call "@blob_size" [] [T.nat] | "bytes" -> call "@blob_bytes" [] [T.iter_obj T.(Prim Word8)] @@ -274,8 +274,8 @@ and blob_dotE proj e = and text_dotE proj e = let fun_ty t1 t2 = T.Func (T.Local, T.Returns, [], t1, t2) in let call name t1 t2 = - let f = idE name (fun_ty [T.text] [fun_ty t1 t2]) in - callE f [] e in + let f = var name (fun_ty [T.text] [fun_ty t1 t2]) in + callE (varE f) [] e in match proj with | "len" -> call "@text_len" [] [T.nat] | "chars" -> call "@text_chars" [] [T.iter_obj T.char] @@ -287,10 +287,10 @@ and block force_unit ds = | _, S.ExpD e -> (decs prefix, exp e) | false, S.LetD ({it = S.VarP x; _}, e) -> - (decs ds, idE x.it e.note.S.note_typ) + (decs ds, varE (var x.it e.note.S.note_typ)) | false, S.LetD (p', e') -> let x = fresh_var "x" (e'.note.S.note_typ) in - (decs prefix @ [letD x (exp e'); letP (pat p') x], x) + (decs prefix @ [letD x (exp e'); letP (pat p') (varE x)], varE x) | _ , S.IgnoreD _ (* redundant, but explicit *) | _, _ -> (decs ds, tupE []) @@ -426,12 +426,12 @@ and to_args typ po p : Ir.arg list * (Ir.exp -> Ir.exp) * T.control * T.typ list (fun e -> e) | S.WildP -> let v = fresh_var "param" p.note in - arg_of_exp v, + arg_of_var v, (fun e -> e) | _ -> let v = fresh_var "param" p.note in - arg_of_exp v, - (fun e -> blockE [letP (pat p) v] e) + arg_of_var v, + (fun e -> blockE [letP (pat p) (varE v)] e) in let args, wrap = @@ -439,7 +439,7 @@ and to_args typ po p : Ir.arg list * (Ir.exp -> Ir.exp) * T.control * T.typ list | _, (S.AnnotP _ | S.ParP _) -> assert false | _, S.WildP -> let vs = fresh_vars "ignored" tys in - List.map arg_of_exp vs, + List.map arg_of_var vs, (fun e -> e) | 1, _ -> let a, wrap = to_arg p in @@ -454,8 +454,8 @@ and to_args typ po p : Ir.arg list * (Ir.exp -> Ir.exp) * T.control * T.typ list ) ps ([], fun e -> e) | _, _ -> let vs = fresh_vars "param" tys in - List.map arg_of_exp vs, - (fun e -> blockE [letP (pat p) (tupE vs)] e) + List.map arg_of_var vs, + (fun e -> blockE [letP (pat p) (tupE (List.map varE vs))] e) in let wrap_po e = @@ -467,7 +467,7 @@ and to_args typ po p : Ir.arg list * (Ir.exp -> Ir.exp) * T.control * T.typ list [letD v (primE I.ICCallerPrim []); letP (pat p) (newObjE T.Object - [{ it = {Ir.name = "caller"; var = id_of_exp v}; + [{ it = {Ir.name = "caller"; var = id_of_var v}; at = no_region; note = T.caller }] T.ctxt)] From ac3dbb2db81b5b5ada2e6631ec8dbe59e58b3b95 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Sun, 5 Apr 2020 21:41:12 +0200 Subject: [PATCH 1154/1176] Peephole optimise eqz before if (#1331) * peephole optimise negation followed by if fix test * typo * testcase: status quo with eqz --- rts/Makefile | 2 +- src/codegen/instrList.ml | 3 +++ test/run/if-swap.mo | 10 ++++++++++ 3 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 test/run/if-swap.mo diff --git a/rts/Makefile b/rts/Makefile index c577959c088..9b52156ec23 100644 --- a/rts/Makefile +++ b/rts/Makefile @@ -19,7 +19,7 @@ TOMMATHFILES=\ TOMMATHSRC ?= $(PWD)/../../libtommath # -# Various libtommath flags, in particuliar telling it to use our own memory +# Various libtommath flags, in particular telling it to use our own memory # manager # diff --git a/src/codegen/instrList.ml b/src/codegen/instrList.ml index f9157172cb8..5dd60c3064e 100644 --- a/src/codegen/instrList.ml +++ b/src/codegen/instrList.ml @@ -43,6 +43,9 @@ let optimize : instr list -> instr list = fun is -> go l' ({i with it = Block (res, else_)} :: r') | { it = Const {it = I32 _; _}; _} :: l', ({it = If (res,then_,_); _} as i) :: r' -> go l' ({i with it = Block (res, then_)} :: r') + (* `If` blocks after negation can swap legs *) + | { it = Test (I32 I32Op.Eqz); _} :: l', ({it = If (res,then_,else_); _} as i) :: r' -> + go l' ({i with it = If (res,else_,then_)} :: r') (* Empty block is redundant *) | l', ({ it = Block (_, []); _ }) :: r' -> go l' r' (* Constant shifts can be combined *) diff --git a/test/run/if-swap.mo b/test/run/if-swap.mo new file mode 100644 index 00000000000..7b96731d2cd --- /dev/null +++ b/test/run/if-swap.mo @@ -0,0 +1,10 @@ +func wantSeeSwap() : Nat = + if (true != true) 42 else 25 + +// CHECK-LABEL: wantSeeSwap +// CHECK: i32.eq +// CHECK-NEXT: if (result i32) +// CHECK-NEXT: i32.const 100 +// CHECK-NEXT: else +// CHECK-NEXT: i32.const 168 + From f07b5f98f4eccdee7ae417de839da3f4e17067bc Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Sun, 5 Apr 2020 21:47:31 +0200 Subject: [PATCH 1155/1176] Test suite: add prim.mo (#1332) a test that does nothing but importing Prim. also rename `prelude.mo` to `ignore.mo` (which it is) and remove commented out code. Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- test/run/ignore.mo | 1 + test/run/prelude.mo | 59 --------------------------------------------- test/run/prim.mo | 1 + 3 files changed, 2 insertions(+), 59 deletions(-) create mode 100644 test/run/ignore.mo delete mode 100644 test/run/prelude.mo create mode 100644 test/run/prim.mo diff --git a/test/run/ignore.mo b/test/run/ignore.mo new file mode 100644 index 00000000000..4518b3b2313 --- /dev/null +++ b/test/run/ignore.mo @@ -0,0 +1 @@ +ignore({}); diff --git a/test/run/prelude.mo b/test/run/prelude.mo deleted file mode 100644 index 0031a6e72d6..00000000000 --- a/test/run/prelude.mo +++ /dev/null @@ -1,59 +0,0 @@ -//ignore(3); -ignore({}); -/* -assert(abs(-3) == 3); - -var i = 0; - -i := 0; -for (j in range(0, 100)) { - assert(j == i); - i += 1; -}; -assert(i == 101); - -i := 3; -for (j in range(3, 10)) { - assert(j == i); - i += 1; -}; -assert(i == 11); - -for (j in range(3, 3)) { - assert(j == 3); -}; - -for (j in range(0, 0)) { - assert(j == 0); -}; - -for (j in range(3, 2)) { - assert(false); -}; - -i := 30; -for (j in revrange(30, 2)) { - assert(j == i); - i -= 1; -}; -assert(i == 1); - -i := 11; -for (j in revrange(10, 0)) { - assert(j == i - 1); - i -= 1; -}; -assert(i == 0); - -for (j in revrange(3, 3)) { - assert(j == 3); -}; - -for (j in revrange(0, 0)) { - assert(j == 0); -}; - -for (j in revrange(1, 2)) { - assert(false); -}; -*/ diff --git a/test/run/prim.mo b/test/run/prim.mo new file mode 100644 index 00000000000..bddaa775f5b --- /dev/null +++ b/test/run/prim.mo @@ -0,0 +1 @@ +import Prim "mo:prim" From 9e50a5eda0142ae70d540eeebf9dfc0c1f7267f1 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 6 Apr 2020 16:01:12 +0200 Subject: [PATCH 1156/1176] Testsuite: static-call-redex (#1337) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I _thought_ that this would fail without the ongoing work about static subexpressions (#1336). Turns out it already works, likely because functions are declarations, so I can’t even produce direct redexe in the IR (e.g. `CallE (FuncE …) …`). But still a nice test. Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- test/run/dec-bug.mo | 2 -- test/run/static-call-redex.mo | 13 +++++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 test/run/static-call-redex.mo diff --git a/test/run/dec-bug.mo b/test/run/dec-bug.mo index e08a859c64c..d3456d723f2 100644 --- a/test/run/dec-bug.mo +++ b/test/run/dec-bug.mo @@ -1,5 +1,3 @@ -import Prim "mo:prim"; - class range(x : Nat, y : Nat) { var i = x; public func next() : ?Nat { if (i > y) null else {let j = i; i += 1; ?j} }; diff --git a/test/run/static-call-redex.mo b/test/run/static-call-redex.mo new file mode 100644 index 00000000000..b5d52a3e296 --- /dev/null +++ b/test/run/static-call-redex.mo @@ -0,0 +1,13 @@ +func go () { + (func foobar1() = ())(); +}; + +(func foobar2() = ())(); + +// CHECK: func $go +// CHECK-NOT: call_indirect +// CHECK: call $foobar1 + +// CHECK: func $start +// CHECK-NOT: call_indirect +// CHECK: call $foobar2 From 661cec070e631138362a4181884fae5aa40ebb55 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 6 Apr 2020 18:35:39 +0200 Subject: [PATCH 1157/1176] Check_ir: Check the const annotation (#1333) this is in preparation for the const-analysis-pass (#1334) It adds the `const` to the notes, and checks that they are correct in `Check_ir`. --- src/ir_def/check_ir.ml | 83 +++++++++++++++++++++++++++++++----------- src/ir_def/note.ml | 2 + src/ir_def/note.mli | 1 + src/mo_types/type.ml | 4 ++ src/mo_types/type.mli | 1 + 5 files changed, 70 insertions(+), 21 deletions(-) diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 30222c21cdc..88acf6de3b9 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -28,7 +28,8 @@ let immute_typ p = (* Scope *) -type val_env = T.typ T.Env.t +type val_info = { typ : T.typ; const : bool } +type val_env = val_info T.Env.t type scope = { val_env : val_env; @@ -48,8 +49,11 @@ type ret_env = T.typ option *) type con_env = T.ConSet.t +type lvl = TopLvl | NotTopLvl + type env = { flavor : Ir.flavor; + lvl : lvl; vals : val_env; cons : con_env; labs : lab_env; @@ -60,7 +64,8 @@ type env = let env_of_scope scope flavor : env = { flavor; - vals = scope.Scope.val_env; + lvl = TopLvl; + vals = T.Env.map (fun typ -> { typ; const = true }) scope.Scope.val_env; cons = T.ConSet.empty; labs = T.Env.empty; rets = None; @@ -332,12 +337,13 @@ let rec check_exp env (exp:Ir.exp) : unit = check (E.infer_effect_exp exp <= E.eff exp) "inferred effect not a subtype of expected effect"; (* check typing *) - match exp.it with + begin match exp.it with | VarE id -> - let t0 = try T.Env.find id env.vals with - | Not_found -> error env exp.at "unbound variable %s" id + let { typ; const } = + try T.Env.find id env.vals + with Not_found -> error env exp.at "unbound variable %s" id in - t0 <~ t + typ <~ t | LitE lit -> T.Prim (type_lit env lit exp.at) <: t | PrimE (p, es) -> @@ -558,7 +564,7 @@ let rec check_exp env (exp:Ir.exp) : unit = typ exp1 <: t; check_cases env T.catch t cases; | LoopE exp1 -> - check_exp env exp1; + check_exp { env with lvl = NotTopLvl } exp1; typ exp1 <: T.unit; T.Non <: t (* vacuously true *) | LabelE (id, t0, exp1) -> @@ -574,14 +580,14 @@ let rec check_exp env (exp:Ir.exp) : unit = let t1 = typ exp1 in let env' = {(adjoin_cons env ce) - with labs = T.Env.empty; rets = Some t1; async = Some c} in + with labs = T.Env.empty; rets = Some t1; async = Some c; lvl = NotTopLvl} in check_exp env' exp1; let t1' = T.open_ [t0] (T.close [c] t1) in t1' <: T.Any; (* vacuous *) T.Async (t0, t1') <: t | DeclareE (id, t0, exp1) -> check_typ env t0; - let env' = adjoin_vals env (T.Env.singleton id t0) in + let env' = adjoin_vals env (T.Env.singleton id { typ = t0; const = false }) in check_exp env' exp1; (typ exp1) <: t | DefineE (id, mut, exp1) -> @@ -589,7 +595,8 @@ let rec check_exp env (exp:Ir.exp) : unit = begin match T.Env.find_opt id env.vals with | None -> error env exp.at "unbound variable %s" id - | Some t0 -> + | Some { typ = t0; const } -> + check (not const) "cannot use DefineE on const variable"; match mut with | Const -> typ exp1 <: t0 @@ -612,7 +619,7 @@ let rec check_exp env (exp:Ir.exp) : unit = if T.is_shared_sort sort then List.iter (check_concrete env exp.at) ret_tys; let codom = T.codom control (fun () -> List.hd ts) ret_tys in let env'' = - {env' with labs = T.Env.empty; rets = Some codom; async = None} in + {env' with labs = T.Env.empty; rets = Some codom; async = None; lvl = NotTopLvl} in check_exp (adjoin_vals env'' ve) exp; check_sub env' exp.at (typ exp) codom; (* Now construct the function type and compare with the annotation *) @@ -626,7 +633,7 @@ let rec check_exp env (exp:Ir.exp) : unit = | SelfCallE (ts, exp_f, exp_k, exp_r) -> check (not env.flavor.Ir.has_async_typ) "SelfCallE in async flavor"; List.iter (check_typ env) ts; - check_exp env exp_f; + check_exp { env with lvl = NotTopLvl } exp_f; check_exp env exp_k; check_exp env exp_r; typ exp_f <: T.unit; @@ -654,6 +661,32 @@ let rec check_exp env (exp:Ir.exp) : unit = t1 <: T.Obj (s0, val_tfs0); t0 <: t + end; + (* check const annotation *) + let check_var ctxt v = + check (T.Env.find v env.vals).const "const %s with non-const variable %s" ctxt v in + if exp.note.Note.const + then begin + match exp.it with + | VarE id -> check_var "VarE" id + | FuncE (x, s, c, tp, as_ , ts, body) -> + if env.lvl = NotTopLvl then + Freevars.M.iter (fun v _ -> check_var "FuncE" v) (Freevars.exp exp) + | NewObjE (Type.(Object | Module), fs, t) when T.is_immutable_obj t -> + List.iter (fun f -> check_var "NewObjE" f.it.var) fs + | PrimE (DotPrim n, [e1]) -> + check e1.note.Note.const "constant DotPrim on non-constant subexpression" + | BlockE (ds, e) -> + List.iter (fun d -> match d.it with + | VarD _ -> check false "VarD in constant BlockE" + | LetD ({it = VarP _; _}, exp) -> + check exp.note.Note.const "non-constant RHS in constant BlockE" + | _ -> + check false "complex pattern in constant BlockE" + ) ds; + check e.note.Note.const "non-constant body in constant BlockE" + | _ -> check false "unexpected constant expression" + end; and check_lexp env (lexp:Ir.lexp) : unit = @@ -666,10 +699,12 @@ and check_lexp env (lexp:Ir.lexp) : unit = (* check typing *) match lexp.it with | VarLE id -> - let t0 = try T.Env.find id env.vals with - | Not_found -> error env lexp.at "unbound variable %s" id + let { typ = t0; const } = + try T.Env.find id env.vals + with Not_found -> error env lexp.at "unbound variable %s" id in - t0 <: t + check (not const) "cannot assign to constant variable"; + t0 <: t | DotLE (exp1, n) -> begin let t1 = typ exp1 in @@ -715,7 +750,7 @@ and check_args env args = check env a.at (not (T.Env.mem a.it ve)) "duplicate binding for %s in argument list" a.it; check_typ env a.note; - go (T.Env.add a.it a.note ve) as_ + go (T.Env.add a.it {typ = a.note; const = false} ve) as_ in go T.Env.empty args (* Patterns *) @@ -729,7 +764,7 @@ and gather_pat env ve0 pat : val_env = | VarP id -> check env pat.at (not (T.Env.mem id ve0)) "duplicate binding for %s in block" id; - T.Env.add id pat.note ve (*TBR*) + T.Env.add id {typ = pat.note; const = false} ve (*TBR*) | TupP pats -> List.fold_left go ve pats | ObjP pfs -> @@ -752,7 +787,7 @@ and check_pat env pat : val_env = let t = pat.note in match pat.it with | WildP -> T.Env.empty - | VarP id -> T.Env.singleton id pat.note + | VarP id -> T.Env.singleton id { typ = pat.note; const = false } | LitP NullLit -> t <: T.Opt T.Any; T.Env.empty @@ -821,8 +856,9 @@ and type_exp_fields env s fs : T.field list = and type_exp_field env s f : T.field = let {name; var} = f.it in - let t = try T.Env.find var env.vals with - | Not_found -> error env f.at "field typing for %s not found" name + let { typ = t; const } = + try T.Env.find var env.vals + with Not_found -> error env f.at "field typing for %s not found" name in assert (t <> T.Pre); check_sub env f.at t f.note; @@ -871,13 +907,18 @@ and gather_dec env scope dec : scope = match dec.it with | LetD (pat, exp) -> let ve = gather_pat env scope.val_env pat in + (* patch the ve for a const binding *) + let ve = match pat.it with + | VarP id when exp.note.Note.const -> + T.Env.add id { (T.Env.find id ve) with const = true } ve + | _ -> ve in { val_env = ve } | VarD (id, t, exp) -> check_typ env t; check env dec.at (not (T.Env.mem id scope.val_env)) "duplicate variable definition in block"; - let ve = T.Env.add id (T.Mut t) scope.val_env in + let ve = T.Env.add id {typ = T.Mut t; const = false} scope.val_env in { val_env = ve} (* Programs *) diff --git a/src/ir_def/note.ml b/src/ir_def/note.ml index 0d99c82152c..eacb37c7b78 100644 --- a/src/ir_def/note.ml +++ b/src/ir_def/note.ml @@ -3,10 +3,12 @@ open Mo_types type t = { typ : Type.typ; eff : Type.eff; + const : bool; } let def : t = { typ = Type.Pre; eff = Type.Triv; + const = false; } diff --git a/src/ir_def/note.mli b/src/ir_def/note.mli index 0de332d8763..c4028ffcb64 100644 --- a/src/ir_def/note.mli +++ b/src/ir_def/note.mli @@ -3,6 +3,7 @@ open Mo_types type t = { typ : Type.typ; eff : Type.eff; + const : bool; } val def : t diff --git a/src/mo_types/type.ml b/src/mo_types/type.ml index 463b2747b54..5cb32bffbe5 100644 --- a/src/mo_types/type.ml +++ b/src/mo_types/type.ml @@ -429,6 +429,10 @@ let as_async_sub default_scope t = match promote t with | Non -> default_scope, Non (* TBR *) | _ -> invalid "as_async_sub" +let is_immutable_obj obj_type = + let _, fields = as_obj_sub [] obj_type in + List.for_all (fun f -> not (is_mut f.typ)) fields + let lookup_val_field l tfs = let is_lab = function {typ = Typ _; _} -> false | {lab; _} -> lab = l in diff --git a/src/mo_types/type.mli b/src/mo_types/type.mli index 0ac066f461f..767f8e9535d 100644 --- a/src/mo_types/type.mli +++ b/src/mo_types/type.mli @@ -98,6 +98,7 @@ val prim : string -> prim val is_non : typ -> bool val is_prim : prim -> typ -> bool val is_obj : typ -> bool +val is_immutable_obj : typ -> bool val is_variant : typ -> bool val is_array : typ -> bool val is_opt : typ -> bool From 72d92c90242ea6052eb89272ca0538a88ac0d5f6 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 6 Apr 2020 18:53:40 +0200 Subject: [PATCH 1158/1176] An analysis pass for constness (#1334) and as always, things are tricky due to recursion. But I think I found a neat solution here. --- src/ir_passes/const.ml | 212 +++++++++++++++++++++++++++++++++++++++ src/ir_passes/const.mli | 3 + src/pipeline/pipeline.ml | 8 ++ 3 files changed, 223 insertions(+) create mode 100644 src/ir_passes/const.ml create mode 100644 src/ir_passes/const.mli diff --git a/src/ir_passes/const.ml b/src/ir_passes/const.ml new file mode 100644 index 00000000000..18d543b8852 --- /dev/null +++ b/src/ir_passes/const.ml @@ -0,0 +1,212 @@ +open Mo_types +open Ir_def +open Source +open Ir + +(* + This module identifies subexpressions that can be compiled statically. This + means each subexpression must be a constant, immutable value for which the backend can create + the memory representation statically. + + This module should stay in sync with the `compile_const_exp` function in + `codegen/compile.ml`. + + If we didn't have recursion, this would be simple: We'd pass down an environment + mapping all free variables to whether they are constant or not (bool E.t), use this + in the VarE case, and otherwise const-able expressions are constant when their + subexpressions are. + + As always, recursion makes things hard. But not too much: We pass down a custom type + called `lazy_bool`. It denotes a boolean value, just we do not know which one yet. + But we can still do operations like implications and conjunction on these values. + + Internally, these lazy_bool values keep track of their dependencies, and + propagate more knowledge automatically. When one of them knows it is going to + be surely false, then it updates the corresponding `note.const` field. + + This works even in the presence of recursion, because it is monotonic: We start + with true (possibly constant) and only use implications to connect these values, so + all propagations of “false” eventually terminate. + + This analysis relies on the fact that AST notes are mutable. So sharing AST + nodes would be bad. Check_ir checks for the absence of sharing. +*) + +(* The lazy bool value type *) + +type lazy_bool' = + | SurelyTrue + | SurelyFalse + | MaybeFalse of (unit -> unit) (* who to notify when turning false *) +type lazy_bool = lazy_bool' ref + +let set_false (l : lazy_bool) = + match !l with + | SurelyTrue -> assert false + | SurelyFalse -> () + | MaybeFalse when_false -> + l := SurelyFalse; (* do this first, this breaks cycles *) + when_false () + +let when_false (l : lazy_bool) (act : unit -> unit) = + match !l with + | SurelyTrue -> () + | SurelyFalse -> act () + | MaybeFalse when_false -> + l := MaybeFalse (fun () -> act (); when_false ()) + +let surely_true = ref SurelyTrue (* sharing is ok *) +let surely_false = ref SurelyFalse (* sharing is ok *) +let maybe_false () = ref (MaybeFalse (fun () -> ())) + +let required_for (a : lazy_bool) (b : lazy_bool) = + when_false a (fun () -> set_false b) + +let all (xs : lazy_bool list) : lazy_bool = + if xs = [] then surely_true else + let b = maybe_false () in + List.iter (fun a -> required_for a b) xs; + b + +(* The environment *) + +type lvl = TopLvl | NotTopLvl + +module S = Freevars.S + +module M = Env.Make(String) + +type env = lazy_bool M.t + +let arg env a = M.add a.it surely_false env +let args env as_ = List.fold_left arg env as_ + +let rec pat env p = match p.it with + | WildP + | LitP _ -> env + | VarP id -> M.add id surely_false env + | TupP pats -> List.fold_left pat env pats + | ObjP pfs -> List.fold_left pat env (pats_of_obj_pat pfs) + | AltP (pat1, _) | OptP pat1 | TagP (_, pat1) -> pat env pat1 + +let find v env = match M.find_opt v env with + | None -> raise (Invalid_argument (Printf.sprintf "Unbound var: %s\n" v)) + | Some lb -> lb + + +(* Setting the notes *) + +let set_const e b = + if e.note.Note.const != b + then e.note <- Note.{ e.note with const = b } + +let set_lazy_const e lb = + set_const e true; + when_false lb (fun () -> set_const e false) + +(* Traversals *) + +let rec exp lvl env e : lazy_bool = + let lb = + match e.it with + | VarE v -> find v env + | FuncE (x, s, c, tp, as_ , ts, body) -> + exp_ NotTopLvl (args env as_) body; + begin match lvl with + | TopLvl -> surely_true (* top-level functions can always be static *) + | NotTopLvl -> + let lb = maybe_false () in + Freevars.M.iter (fun v _ -> required_for (find v env) lb) (Freevars.exp e); + lb + end + | NewObjE (Type.(Object | Module), fs, t) when Type.is_immutable_obj t -> + let lb = maybe_false () in + List.iter (fun f -> required_for (find f.it.var env) lb) fs; + lb + | BlockE (ds, body) -> + block lvl env (ds, body) + | PrimE (DotPrim n, [e1]) -> + exp lvl env e1 + + (* All the following expressions cannot be const, but we still need to descend *) + | PrimE (_, es) -> + List.iter (exp_ lvl env) es; + surely_false + | LitE _ -> + surely_false + | DeclareE (id, _, e1) -> + exp_ lvl (M.add id surely_false env) e1; + surely_false + | LoopE e1 | AsyncE (_, e1, _) -> + exp_ NotTopLvl env e1; + surely_false + | AssignE (_, e1) | LabelE (_, _, e1) | DefineE (_, _, e1) -> + exp_ lvl env e1; + surely_false + | IfE (e1, e2, e3) -> + exp_ lvl env e1; + exp_ lvl env e2; + exp_ lvl env e3; + surely_false + | SelfCallE (_, e1, e2, e3) -> + exp_ NotTopLvl env e1; + exp_ lvl env e2; + exp_ lvl env e3; + surely_false + | SwitchE (e1, cs) | TryE (e1, cs) -> + exp_ lvl env e1; + List.iter (case_ lvl env) cs; + surely_false + | NewObjE _ -> (* mutable objects *) + surely_false + | ActorE _ -> + (* no point in traversing until the backend supports dynamic actors *) + surely_false + in + set_lazy_const e lb; + lb + +and exp_ lvl env e : unit = ignore (exp lvl env e) +and case_ lvl env c : unit = + exp_ lvl (pat env c.it.pat) c.it.exp + +and gather_dec scope dec : env = match dec.it with + | LetD ({it = VarP v; _}, e) -> M.add v (maybe_false ()) scope + | _ -> + let vs = snd (Freevars.dec dec) in (* TODO: implement gather_dec more directly *) + S.fold (fun v scope -> M.add v surely_false scope) vs scope + +and gather_decs ds : env = + List.fold_left gather_dec M.empty ds + +and check_dec lvl env dec : lazy_bool = match dec.it with + | LetD ({it = VarP v; _}, e) -> + let lb = exp lvl env e in + required_for lb (M.find v env); + lb + | LetD (_, e) | VarD (_, _, e) -> + exp_ lvl env e; + surely_false + +and check_decs lvl env ds : lazy_bool = + let lbs = List.map (check_dec lvl env) ds in + all lbs + +and decs lvl env ds : (env * lazy_bool) = + let scope = gather_decs ds in + let env' = M.adjoin env scope in + let could_be = check_decs lvl env' ds in + (env', could_be) + +and block lvl env (ds, body) = + let (env', decs_const) = decs lvl env ds in + let exp_const = exp lvl env' body in + all [decs_const; exp_const] + +let analyze scope ((b, _flavor) : prog) = + (* + We assume everything in scope is static. Right now, this is only the prelude, + which is static. It will blow up in compile if we break this. + *) + let env = M.of_seq (Seq.map (fun (v, _typ) -> (v, surely_true)) (Type.Env.to_seq scope.Scope.val_env)) in + ignore (block TopLvl env b) diff --git a/src/ir_passes/const.mli b/src/ir_passes/const.mli new file mode 100644 index 00000000000..88320c48391 --- /dev/null +++ b/src/ir_passes/const.mli @@ -0,0 +1,3 @@ +open Mo_types +open Ir_def +val analyze : Scope.scope -> Ir.prog -> unit diff --git a/src/pipeline/pipeline.ml b/src/pipeline/pipeline.ml index 95eb52926c0..6e0504c3d69 100644 --- a/src/pipeline/pipeline.ml +++ b/src/pipeline/pipeline.ml @@ -544,6 +544,12 @@ let tailcall_optimization = let show_translation = transform_if "Translate show" Show.transform +let analyze analysis_name analysis env prog name = + phase analysis_name name; + analysis env prog; + if !Flags.check_ir + then Check_ir.check_prog !Flags.verbose env analysis_name prog + (* Compilation *) @@ -581,10 +587,12 @@ let lower_prog mode senv libs progs name = let prog_ir = async_lowering mode !Flags.async_lowering initial_stat_env prog_ir name in let prog_ir = tailcall_optimization true initial_stat_env prog_ir name in let prog_ir = show_translation true initial_stat_env prog_ir name in + analyze "constness analysis" Const.analyze initial_stat_env prog_ir name; prog_ir let compile_prog mode do_link libs progs : Wasm_exts.CustomModule.extended_module = let prelude_ir = Lowering.Desugar.transform prelude in + analyze "constness analysis" Const.analyze initial_stat_env prelude_ir "prelude"; let name = name_progs progs in let prog_ir = lower_prog mode initial_stat_env libs progs name in phase "Compiling" name; From 31e1d114d07e9ce7acdc71e94e91c1c69618e554 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Mon, 6 Apr 2020 19:15:16 +0200 Subject: [PATCH 1159/1176] Compile: More disciplined detection of the TopLevel (#1335) the compiler behaves differently on the top level, e.g. variables can be put in _static_ rather than _dynamic_ positions, which makes more functions be static (all top-level `FuncE` are constant values). This refines the tracking of whether we are at the top level: The top level is, well, the top-level, excluding all funcion bodies (AsyncE and SelfCallE are function-like) and also loops. This actually simplifies some of the code, while simulatenously producing better output (more constant values). --- src/codegen/compile.ml | 73 ++++++++++++++++++------------------------ 1 file changed, 32 insertions(+), 41 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index a45bc3a79f3..725e6c1648d 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -108,23 +108,17 @@ The fields fall into the following categories: 1. Static global fields. Never change. Example: whether we are compiling with -no-system-api - 2. Immutable global fields. Change in a well-scoped manner. - Example: Mapping from Motoko names to their location. - - 3. Mutable global fields. Change only monotonously. + 2. Mutable global fields. Change only monotonically. These are used to register things like functions. This should be monotone in the sense that entries are only added, and that the order should not matter in a significant way. In some instances, the list contains futures so that we can reserve and know the _position_ of the thing before we have to actually fill it in. - 4. Static local fields. Never change within a function. + 3. Static local fields. Never change within a function. Example: number of parameters and return values - 5. Immutable local fields. Change in a well-scoped manner. - Example: Jump label depth - - 6. Mutable local fields. See above + 4. Mutable local fields. See above Example: Name and type of locals. **) @@ -190,8 +184,6 @@ module E = struct n_param : int32; (* Number of parameters (to calculate indices of locals) *) return_arity : int; (* Number of return values (for type of Return) *) - (* Immutable *) - (* Mutable *) locals : value_type list ref; (* Types of locals *) local_names : (int32 * string) list ref; (* Names of locals *) @@ -4660,18 +4652,25 @@ module VarEnv = struct | HeapStatic _ -> true | Const _ -> true + type lvl = TopLvl | NotTopLvl + (* The source variable environment: - In scope variables and in-scope jump labels + - Whether we are on the top level + - In-scope variables + - scope jump labels *) + module NameEnv = Env.Make(String) type t = { + lvl : lvl; vars : varloc NameEnv.t; (* variables ↦ their location *) labels : G.depth NameEnv.t; (* jump label ↦ their depth *) } let empty_ae = { + lvl = TopLvl; vars = NameEnv.empty; labels = NameEnv.empty; } @@ -4681,6 +4680,7 @@ module VarEnv = struct *) let mk_fun_ae ae = { ae with + lvl = NotTopLvl; vars = NameEnv.filter (fun v l -> let non_local = is_non_local l in (* For debugging, enable this: @@ -4966,9 +4966,10 @@ module FuncDec = struct else assert false (* no first class shared functions *) let lit env ae name sort control free_vars args mk_body ret_tys at = - let captured = List.filter (VarEnv.needs_capture ae) free_vars in + if ae.VarEnv.lvl = VarEnv.TopLvl then assert (captured = []); + if captured = [] then let (ct, fill) = closed env sort control name args mk_body ret_tys at in @@ -5247,8 +5248,6 @@ module AllocHow = struct )) let joins = List.fold_left join M.empty - type lvl = TopLvl | NotTopLvl - let map_of_set = Freevars.map_of_set let set_of_map = Freevars.set_of_map let disjoint s1 s2 = S.is_empty (S.inter s1 s2) @@ -5281,12 +5280,12 @@ module AllocHow = struct - everything that is non-static (i.e. still in locals) *) match lvl with - | NotTopLvl -> + | VarEnv.NotTopLvl -> map_of_set StoreHeap (S.union (S.inter (set_of_map (M.filter is_local_mut how)) captured) (S.inter (set_of_map (M.filter is_local how)) (S.diff captured seen)) ) - | TopLvl -> + | VarEnv.TopLvl -> map_of_set StoreStatic (S.inter (set_of_map (M.filter is_local how)) captured) @@ -5327,7 +5326,7 @@ module AllocHow = struct | LetD ({it = VarP _; _}, e) when is_const_exp e && disjoint (Freevars.eager_vars f) (set_of_map (M.filter is_not_const how_all)) && - (lvl = TopLvl || disjoint (Freevars.captured_vars f) (set_of_map (M.filter require_closure how_all))) + (lvl = VarEnv.TopLvl || disjoint (Freevars.captured_vars f) (set_of_map (M.filter require_closure how_all))) -> map_of_set (Const : how) d @@ -5352,7 +5351,8 @@ module AllocHow = struct | VarEnv.HeapInd _ -> StoreHeap ) ae.VarEnv.vars - let decs (ae : VarEnv.t) lvl decs captured_in_body : allocHow = + let decs (ae : VarEnv.t) decs captured_in_body : allocHow = + let lvl = ae.VarEnv.lvl in let how_outer = how_of_ae ae in let defined_here = snd (Freevars.decs decs) in (* TODO: implement gather_decs more directly *) let how_outer = Freevars.diff how_outer defined_here in (* shadowing *) @@ -6516,7 +6516,7 @@ and compile_exp (env : E.t) ae exp = (code2 ^^ StackRep.adjust env sr2 sr) | BlockE (decs, exp) -> let captured = Freevars.captured_vars (Freevars.exp exp) in - let (ae', code1) = compile_decs env ae AllocHow.NotTopLvl decs captured in + let (ae', code1) = compile_decs env ae decs captured in let (sr, code2) = compile_exp env ae' exp in (sr, code1 ^^ code2) | LabelE (name, _ty, e) -> @@ -6533,7 +6533,8 @@ and compile_exp (env : E.t) ae exp = ) | LoopE e -> SR.Unreachable, - G.loop_ [] (compile_exp_unit env ae e ^^ G.i (Br (nr 0l)) + let ae' = VarEnv.{ ae with lvl = NotTopLvl } in + G.loop_ [] (compile_exp_unit env ae' e ^^ G.i (Br (nr 0l)) ) ^^ G.i Unreachable @@ -6616,7 +6617,7 @@ and compile_exp_as env ae sr_out e = (* Some optimizations for certain sr_out and expressions *) | _ , BlockE (decs, exp) -> let captured = Freevars.captured_vars (Freevars.exp exp) in - let (ae', code1) = compile_decs env ae AllocHow.NotTopLvl decs captured in + let (ae', code1) = compile_decs env ae decs captured in let code2 = compile_exp_as env ae' sr_out exp in code1 ^^ code2 (* Fallback to whatever stackrep compile_exp chooses *) @@ -6896,8 +6897,8 @@ and compile_dec env pre_ae how v2en dec : VarEnv.t * G.t * (VarEnv.t -> G.t) = Var.set_val env ae name ) -and compile_decs_public env pre_ae lvl decs v2en captured_in_body : VarEnv.t * G.t = - let how = AllocHow.decs pre_ae lvl decs captured_in_body in +and compile_decs_public env pre_ae decs v2en captured_in_body : VarEnv.t * G.t = + let how = AllocHow.decs pre_ae decs captured_in_body in let rec go pre_ae decs = match decs with | [] -> (pre_ae, G.nop, fun _ -> G.nop) | [dec] -> compile_dec env pre_ae how v2en dec @@ -6914,24 +6915,14 @@ and compile_decs_public env pre_ae lvl decs v2en captured_in_body : VarEnv.t * G let code = mk_code ae1 in (ae1, alloc_code ^^ code) -and compile_decs env ae lvl decs captured_in_body : VarEnv.t * G.t = - compile_decs_public env ae lvl decs E.NameEnv.empty captured_in_body - -and compile_top_lvl_expr env ae e = match e.it with - | BlockE (decs, exp) -> - let captured = Freevars.captured_vars (Freevars.exp e) in - let (ae', code1) = compile_decs env ae AllocHow.TopLvl decs captured in - let code2 = compile_top_lvl_expr env ae' exp in - code1 ^^ code2 - | _ -> - let (sr, code) = compile_exp env ae e in - code ^^ StackRep.drop env sr +and compile_decs env ae decs captured_in_body : VarEnv.t * G.t = + compile_decs_public env ae decs E.NameEnv.empty captured_in_body and compile_prog env ae (ds, e) = - let captured = Freevars.captured_vars (Freevars.exp e) in - let (ae', code1) = compile_decs env ae AllocHow.TopLvl ds captured in - let code2 = compile_top_lvl_expr env ae' e in - (ae', code1 ^^ code2) + let captured = Freevars.captured_vars (Freevars.exp e) in + let (ae', code1) = compile_decs env ae ds captured in + let (sr, code2) = compile_exp env ae' e in + (ae', code1 ^^ code2 ^^ StackRep.drop env sr) and compile_const_exp env pre_ae exp : Const.t * (E.t -> VarEnv.t -> unit) = match exp.it with @@ -7072,7 +7063,7 @@ and main_actor env ae1 ds fs = let v2en = E.NameEnv.from_list (List.map (fun f -> (f.it.var, f.it.name)) fs) in (* Compile the declarations *) - let (ae2, decls_code) = compile_decs_public env ae1 AllocHow.TopLvl ds v2en Freevars.S.empty in + let (ae2, decls_code) = compile_decs_public env ae1 ds v2en Freevars.S.empty in (* Export the public functions *) List.iter (export_actor_field env ae2) fs; From 4125f4111491858c209a3af5a3a881d4961a4167 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Tue, 7 Apr 2020 12:01:50 +0200 Subject: [PATCH 1160/1176] Test case: capturing top-level variables in local function (#1342) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit on `master`, this correctly leads to a statically allocated `rec`, but with #1336 this breaks. It seems we need to be able to distinguish “location statically known” (true for all top-level bindings, and required for free variables of a `FuncE` for it to be constant) and “value constant” (required to put a value pre-compiled into static memory). The test case is a minized version of `fromList` in `Trie.mo` which uses a global constant. --- test/run/static-call-rec.mo | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 test/run/static-call-rec.mo diff --git a/test/run/static-call-rec.mo b/test/run/static-call-rec.mo new file mode 100644 index 00000000000..b2c683ec574 --- /dev/null +++ b/test/run/static-call-rec.mo @@ -0,0 +1,13 @@ +var FOO = 1; +func go (x:Nat) { + func rec(x:Nat) { + ignore(FOO); + }; + rec(x); +}; +go(1000); + +// CHECK: func $go +// CHECK-NOT: call_indirect +// CHECK: call $rec + From 5b5b57f8701bec15f8626910e101fd99257908d7 Mon Sep 17 00:00:00 2001 From: Christoph Hegemann <6189397+kritzcreek@users.noreply.github.com> Date: Tue, 7 Apr 2020 14:01:23 +0200 Subject: [PATCH 1161/1176] Cleaning up Language Server interfaces (#1340) * Various cleanups for the languageServer module - Unifies function definition format - Groups all IO functionality into a module and parameterizes it over its input and output channels * small refactor * simple clamp * Collects the LS state in a single record This makes it easier to document and easier to tell which operations are stateful * Explains and simplifies the message reading * moves client capabilities into the server state * Pervasively uses the global logger inside the LS If we ever decide we need structured logging this will need to be revisited, but for now I'm convinced the convenience is worth it. * Gives the languageServer entrypoint an .mli file * extracts IO functions to a Communication module * give a better name to the Channels structure --- src/languageServer/communication.ml | 105 ++++++++++ src/languageServer/communication.mli | 23 +++ src/languageServer/completion.ml | 11 +- src/languageServer/completion_test.ml | 6 +- src/languageServer/declaration_index.ml | 10 +- src/languageServer/declaration_index.mli | 1 - src/languageServer/hover.ml | 5 +- src/languageServer/languageServer.ml | 238 ++++++++++------------- src/languageServer/languageServer.mli | 3 + src/languageServer/vfs.ml | 8 +- src/languageServer/vfs.mli | 4 +- 11 files changed, 253 insertions(+), 161 deletions(-) create mode 100644 src/languageServer/communication.ml create mode 100644 src/languageServer/communication.mli create mode 100644 src/languageServer/languageServer.mli diff --git a/src/languageServer/communication.ml b/src/languageServer/communication.ml new file mode 100644 index 00000000000..4f23bfdc377 --- /dev/null +++ b/src/languageServer/communication.ml @@ -0,0 +1,105 @@ +module Lsp_j = Lsp.Lsp_j +module Lsp_t = Lsp.Lsp_t + +let jsonrpc_version : string = "2.0" + +let notification : + Lsp_t.notification_message_params -> Lsp_t.notification_message = + fun params -> + Lsp_t. + { + notification_message_jsonrpc = jsonrpc_version; + notification_message_params = params; + } + +module MakeIO (Channels : sig + val debug_channel : out_channel option + + val in_channel : in_channel + + val out_channel : out_channel +end) = +struct + let log_to_file : string -> string -> unit = + fun lbl txt -> + Option.iter + (fun oc -> + Printf.fprintf oc "[%s] %s\n" lbl txt; + flush oc) + Channels.debug_channel + + let send : string -> unit = + fun msg -> + let length = String.length msg in + Printf.fprintf Channels.out_channel "Content-Length: %d\r\n\r\n%s" length + msg; + flush Channels.out_channel + + let read_message : unit -> string * Lsp_t.incoming_message option = + fun () -> + let num = + (* Every LSP message begins with a content length header *) + input_line Channels.in_channel + |> Lib.String.chop_prefix "Content-Length: " + (* If this fails the protocol was broken and we abort. Should we recover from this? *) + |> Option.get + (* `input_line` does not consume the trailing \r, so we need to trim it off here *) + |> String.trim + |> int_of_string + (* The protocol terminates the content length header with two \r\n s. Our `input_line` + call consumed the first, but we still need to eat the second one, so we add 2 to + the length of the message *) + |> ( + ) 2 + in + + let buffer = Buffer.create num in + Buffer.add_channel buffer stdin num; + let raw = String.trim (Buffer.contents buffer) in + let msg = + try Some (Lsp_j.incoming_message_of_string raw) with _ -> None + in + (raw, msg) + + let show_message : Lsp.MessageType.t -> string -> unit = + fun typ msg -> + let params = + `WindowShowMessage + Lsp_t. + { + window_show_message_params_type_ = typ; + window_show_message_params_message = msg; + } + in + let notification = notification params in + send (Lsp_j.string_of_notification_message notification) + + let publish_diags : Lsp_t.document_uri -> Lsp_t.diagnostic list -> unit = + fun uri diags -> + let params = + `PublishDiagnostics + Lsp_t. + { + publish_diagnostics_params_uri = uri; + publish_diagnostics_params_diagnostics = diags; + } + in + let notification = notification params in + send (Lsp_j.string_of_notification_message notification) + + let clear_diagnostics : Lsp_t.document_uri -> unit = + fun uri -> publish_diags uri [] +end + +module type IO = sig + val log_to_file : string -> string -> unit + + val send : string -> unit + + val read_message : unit -> string * Lsp_t.incoming_message option + + val show_message : Lsp.MessageType.t -> string -> unit + + val publish_diags : Lsp_t.document_uri -> Lsp_t.diagnostic list -> unit + + val clear_diagnostics : Lsp_t.document_uri -> unit +end diff --git a/src/languageServer/communication.mli b/src/languageServer/communication.mli new file mode 100644 index 00000000000..d3fec2f540b --- /dev/null +++ b/src/languageServer/communication.mli @@ -0,0 +1,23 @@ +module Lsp_t = Lsp.Lsp_t + +module type IO = sig + val log_to_file : string -> string -> unit + + val send : string -> unit + + val read_message : unit -> string * Lsp_t.incoming_message option + + val show_message : Lsp.MessageType.t -> string -> unit + + val publish_diags : Lsp_t.document_uri -> Lsp_t.diagnostic list -> unit + + val clear_diagnostics : Lsp_t.document_uri -> unit +end + +module MakeIO (Channels : sig + val debug_channel : out_channel option + + val in_channel : in_channel + + val out_channel : out_channel +end) : IO diff --git a/src/languageServer/completion.ml b/src/languageServer/completion.ml index 11e7ed362a4..eb35b1b2390 100644 --- a/src/languageServer/completion.ml +++ b/src/languageServer/completion.ml @@ -53,7 +53,7 @@ let import_relative_to_project_root root module_path dependency = the prefix relevant to searching completions. For example, given: List.fi| (where | is the cursor) return `Some ("List", "fi")` *) -let find_completion_prefix logger file line column : (string * string) option = +let find_completion_prefix file line column : (string * string) option = let open Source in (* The LSP sends 0 based line numbers *) let line = line + 1 in @@ -107,7 +107,7 @@ let opt_bind f = function None -> None | Some x -> f x let is_capital : string -> bool = fun s -> String.capitalize_ascii s = s -let completions index logger project_root file_path file_contents line column = +let completions index project_root file_path file_contents line column = let imported = Source_file.parse_module_header project_root file_path file_contents in @@ -133,7 +133,7 @@ let completions index logger project_root file_path file_contents line column = completion_item_detail = None; } in - match find_completion_prefix logger file_contents line column with + match find_completion_prefix file_contents line column with | None -> (* If we don't have any prefix to work with, just suggest the imported module aliases, as well as top-level definitions in @@ -193,9 +193,8 @@ let completions index logger project_root file_path file_contents line column = completions | None -> [] ) -let completion_handler index logger project_root file_path file_contents - position = +let completion_handler index project_root file_path file_contents position = let line = position.Lsp_t.position_line in let column = position.Lsp_t.position_character in `CompletionResponse - (completions index logger project_root file_path file_contents line column) + (completions index project_root file_path file_contents line column) diff --git a/src/languageServer/completion_test.ml b/src/languageServer/completion_test.ml index dc222f3269b..e83fc1c5a4f 100644 --- a/src/languageServer/completion_test.ml +++ b/src/languageServer/completion_test.ml @@ -10,17 +10,13 @@ let extract_cursor input = |> String.concat "\n" |> fun f -> (f, !cursor_pos) -let dummy_logger _ _ = () - let prefix_test_case file expected = let file, (line, column) = extract_cursor file in let show = function | None -> "None" | Some (m, p) -> "Some (" ^ m ^ ", " ^ p ^ ")" in - let actual = - Completion.find_completion_prefix dummy_logger file line column - in + let actual = Completion.find_completion_prefix file line column in Option.equal ( = ) actual expected || ( Printf.printf "\nExpected: %s\nActual: %s\n" (show expected) (show actual); diff --git a/src/languageServer/declaration_index.ml b/src/languageServer/declaration_index.ml index 3fba343ea63..dd06d59a2e6 100644 --- a/src/languageServer/declaration_index.ml +++ b/src/languageServer/declaration_index.ml @@ -327,7 +327,7 @@ let index_from_scope : string -> t -> Syntax.lib list -> Scope.t -> t = acc) scope.Scope.lib_env initial_index -let make_index_inner logger project_root vfs entry_points : t Diag.result = +let make_index_inner project_root vfs entry_points : t Diag.result = let package_paths = List.map (fun f -> LibPath f @@ Source.no_region) (scan_packages ()) in @@ -339,7 +339,7 @@ let make_index_inner logger project_root vfs entry_points : t Diag.result = match package_env with | Result.Error errs -> List.iter - (fun err -> logger "lib_index_errors" (Diag.string_of_message err)) + (fun err -> Debug.log "lib_index_errors" (Diag.string_of_message err)) errs; empty project_root | Result.Ok ((libs, scope), _) -> @@ -354,7 +354,7 @@ let make_index_inner logger project_root vfs entry_points : t Diag.result = | Result.Error errs -> List.iter (fun err -> - logger "actor_index_errors" (Diag.string_of_message err)) + Debug.log "actor_index_errors" (Diag.string_of_message err)) errs; acc | Result.Ok ((prog, idl_scope, actor_opt), _) -> @@ -370,7 +370,7 @@ let make_index_inner logger project_root vfs entry_points : t Diag.result = |> Diag.map (fun (libs, _, scope) -> index_from_scope project_root actor_index libs scope) -let make_index logger project_root vfs entry_points : t Diag.result = +let make_index project_root vfs entry_points : t Diag.result = (* TODO(Christoph): Actually handle errors here *) - try make_index_inner logger project_root vfs entry_points + try make_index_inner project_root vfs entry_points with _ -> Diag.return (empty project_root) diff --git a/src/languageServer/declaration_index.mli b/src/languageServer/declaration_index.mli index 85b49967798..e14e397b2cf 100644 --- a/src/languageServer/declaration_index.mli +++ b/src/languageServer/declaration_index.mli @@ -34,7 +34,6 @@ val find_with_prefix : (string * ide_decl list) list val make_index : - (string -> string -> unit) (** A logger *) -> string (** The project root *) -> Vfs.t -> string list (** The entry points *) -> diff --git a/src/languageServer/hover.ml b/src/languageServer/hover.ml index 88f8176dd9d..97950d1c5e2 100644 --- a/src/languageServer/hover.ml +++ b/src/languageServer/hover.ml @@ -12,9 +12,8 @@ let hover_detail = function let markup_content (msg : string) : Lsp.markup_content = Lsp.{ markup_content_kind = "plaintext"; markup_content_value = msg } -let hover_handler (logger : string -> string -> unit) (index : DI.t) - (position : Lsp.position) (file_contents : string) (project_root : string) - (file_path : string) = +let hover_handler (index : DI.t) (position : Lsp.position) + (file_contents : string) (project_root : string) (file_path : string) = let current_uri_opt = Lib.FilePath.relative_to project_root file_path in let toplevel_decls = current_uri_opt diff --git a/src/languageServer/languageServer.ml b/src/languageServer/languageServer.ml index 52ca883b7f7..2780a97926e 100644 --- a/src/languageServer/languageServer.ml +++ b/src/languageServer/languageServer.ml @@ -8,16 +8,9 @@ module Lsp_t = Lsp.Lsp_t let jsonrpc_version : string = "2.0" -let notification (params : Lsp_t.notification_message_params) : - Lsp_t.notification_message = - Lsp_t. - { - notification_message_jsonrpc = jsonrpc_version; - notification_message_params = params; - } - -let response_result_message (id : int) (result : Lsp_t.response_result) : - Lsp_t.response_message = +let response_result_message : + int -> Lsp_t.response_result -> Lsp_t.response_message = + fun id result -> Lsp_t. { response_message_jsonrpc = jsonrpc_version; @@ -26,8 +19,9 @@ let response_result_message (id : int) (result : Lsp_t.response_result) : response_message_error = None; } -let response_error_message (id : int) (error : Lsp_t.response_error) : - Lsp_t.response_message = +let response_error_message : + int -> Lsp_t.response_error -> Lsp_t.response_message = + fun id error -> Lsp_t. { response_message_jsonrpc = jsonrpc_version; @@ -36,62 +30,17 @@ let response_error_message (id : int) (error : Lsp_t.response_error) : response_message_error = Some error; } -module Channel = struct - let log_to_file (oc : out_channel) (lbl : string) (txt : string) : unit = - Printf.fprintf oc "[%s] %s\n" lbl txt; - flush oc - - let send (oc : out_channel) (label : string) (out : string) : unit = - let cl = "Content-Length: " ^ string_of_int (String.length out) in - print_string cl; - print_string "\r\n\r\n"; - print_string out; - flush stdout - - let send_response (oc : out_channel) : string -> unit = send oc "response" - - let send_notification (oc : out_channel) : string -> unit = - send oc "notification" - - let show_message (oc : out_channel) (typ : Lsp.MessageType.t) (msg : string) : - unit = - let params = - `WindowShowMessage - Lsp_t. - { - window_show_message_params_type_ = typ; - window_show_message_params_message = msg; - } - in - let notification = notification params in - send_notification oc (Lsp_j.string_of_notification_message notification) - - let publish_diagnostics (oc : out_channel) (uri : Lsp_t.document_uri) - (diags : Lsp_t.diagnostic list) : unit = - let params = - `PublishDiagnostics - Lsp_t. - { - publish_diagnostics_params_uri = uri; - publish_diagnostics_params_diagnostics = diags; - } - in - let notification = notification params in - send_notification oc (Lsp_j.string_of_notification_message notification) - - let clear_diagnostics (oc : out_channel) (uri : Lsp_t.document_uri) : unit = - publish_diagnostics oc uri [] -end - -let position_of_pos (pos : Source.pos) : Lsp_t.position = +let position_of_pos : Source.pos -> Lsp_t.position = + fun pos -> Lsp_t. { (* The LSP spec requires zero-based positions *) - position_line = (if pos.Source.line > 0 then pos.Source.line - 1 else 0); + position_line = max 0 (pos.Source.line - 1); position_character = pos.Source.column; } -let range_of_region (at : Source.region) : Lsp_t.range = +let range_of_region : Source.region -> Lsp_t.range = + fun at -> Lsp_t. { range_start = position_of_pos at.Source.left; @@ -103,7 +52,8 @@ let severity_of_sev : Diag.severity -> Lsp.DiagnosticSeverity.t = function | Diag.Warning -> Lsp.DiagnosticSeverity.Warning | Diag.Info -> Lsp.DiagnosticSeverity.Information -let diagnostics_of_message (msg : Diag.message) : Lsp_t.diagnostic * string = +let diagnostics_of_message : Diag.message -> Lsp_t.diagnostic * string = + fun msg -> ( Lsp_t. { diagnostic_range = range_of_region msg.Diag.at; @@ -115,45 +65,71 @@ let diagnostics_of_message (msg : Diag.message) : Lsp_t.diagnostic * string = }, msg.Diag.at.Source.left.Source.file ) -let start entry_point debug = - let oc : out_channel = - if debug then open_out_gen [ Open_append; Open_creat ] 0o666 "ls.log" - else open_out "/dev/null" +(** A record with all the mutable state and caches the Language Server needs *) +type ls_state = { + decl_index : Declaration_index.t ref; (** Our index of known definitions *) + vfs : Vfs.t ref; + (** The virtual file system. Our knowledge of opened files and their contents *) + startup_diagnostics : Diag.messages ref; + (** Diagnostics we encountered when building the index on startup. These need to + ** be cached here because we can't report them until initialization is completed *) + files_with_diagnostics : Vfs.uri list ref; + (** All files with known diagnostics. We need to store them so that we can clear + ** their diagnostics once compilation succeeds *) + shutdown : bool ref; + (** Have we received the shutdown message?, A quirk of the LSP *) + client_capabilities : Lsp_t.client_capabilities option ref; + (** What are the capabilities the client reported? *) +} + +let start : string -> bool -> 'a = + fun entry_point debug -> + let debug_channel : out_channel option = + if debug then Some (open_out_gen [ Open_append; Open_creat ] 0o666 "ls.log") + else None in - let log_to_file = Channel.log_to_file oc in - let _ = log_to_file "entry_point" entry_point in + let module IO = Communication.MakeIO (struct + let debug_channel = debug_channel + + let in_channel = stdin + + let out_channel = stdout + end) in + let _ = Debug.logger := IO.log_to_file in + let _ = Debug.log "entry_point" entry_point in let _ = Flags.M.iter - (fun k v -> log_to_file "package" (Printf.sprintf "%s => %s" k v)) + (fun k v -> Debug.log "package" (Printf.sprintf "%s => %s" k v)) !Flags.package_urls in - let _ = Debug.logger := log_to_file in - let publish_diagnostics = Channel.publish_diagnostics oc in - let clear_diagnostics = Channel.clear_diagnostics oc in - let send_response = Channel.send_response oc in - let show_message = Channel.show_message oc in - let shutdown = ref false in - let client_capabilities = ref None in - let project_root = Sys.getcwd () in - let _ = log_to_file "project_root" project_root in - let startup_diags = ref [] in - let files_with_diags = ref [] in - let vfs = ref Vfs.empty in - let decl_index = - let ix = + let project_root = + let root = Sys.getcwd () in + Debug.log "project_root" root; + root + in + let ls_state = + { + vfs = ref Vfs.empty; + decl_index = ref (Declaration_index.empty project_root); + startup_diagnostics = ref []; + files_with_diagnostics = ref []; + shutdown = ref false; + client_capabilities = ref None; + } + in + let _ = + ls_state.decl_index := match - Declaration_index.make_index log_to_file project_root !vfs + Declaration_index.make_index project_root !(ls_state.vfs) [ entry_point ] with | Error errs -> List.iter - (fun err -> log_to_file "Error" (Diag.string_of_message err)) + (fun err -> Debug.log "startup_error" (Diag.string_of_message err)) errs; - startup_diags := errs; + ls_state.startup_diagnostics := errs; Declaration_index.empty project_root | Ok (ix, _) -> ix - in - ref ix in let sync_diagnostics msgs = let diags_by_file = @@ -162,15 +138,16 @@ let start entry_point debug = |> Lib.List.group (fun (_, f1) (_, f2) -> f1 = f2) |> List.map (fun diags -> let _, file = List.hd diags in - (List.map fst diags, Vfs.uri_from_file file)) + (Vfs.uri_from_file file, List.map fst diags)) in - List.iter clear_diagnostics !files_with_diags; - files_with_diags := List.map snd diags_by_file; - List.iter (fun (diags, uri) -> publish_diagnostics uri diags) diags_by_file + List.iter IO.clear_diagnostics !(ls_state.files_with_diagnostics); + ls_state.files_with_diagnostics := List.map fst diags_by_file; + List.iter (Lib.Fun.uncurry IO.publish_diags) diags_by_file in let handle_message raw = function | Some id, `Initialize params -> - client_capabilities := Some params.Lsp_t.initialize_params_capabilities; + ls_state.client_capabilities := + Some params.Lsp_t.initialize_params_capabilities; let completion_options = Lsp_t. { @@ -208,7 +185,7 @@ let start entry_point debug = } in let response = response_result_message id result in - send_response (Lsp_j.string_of_response_message response) + IO.send (Lsp_j.string_of_response_message response) | Some id, `TextDocumentHover params -> let uri = params.Lsp_t.text_document_position_params_textDocument @@ -216,7 +193,7 @@ let start entry_point debug = in let position = params.Lsp_t.text_document_position_params_position in let response = - match Vfs.read_file uri !vfs with + match Vfs.read_file uri !(ls_state.vfs) with | None -> response_error_message id Lsp_t. @@ -227,13 +204,13 @@ let start entry_point debug = } | Some file_content -> let result = - Hover.hover_handler log_to_file !decl_index position - file_content project_root - (Vfs.abs_file_from_uri log_to_file uri) + Hover.hover_handler !(ls_state.decl_index) position file_content + project_root + (Vfs.abs_file_from_uri uri) in response_result_message id result in - send_response (Lsp_j.string_of_response_message response) + IO.send (Lsp_j.string_of_response_message response) | Some id, `TextDocumentDefinition params -> let uri = params.Lsp_t.text_document_position_params_textDocument @@ -241,7 +218,7 @@ let start entry_point debug = in let position = params.Lsp_t.text_document_position_params_position in let response = - match Vfs.read_file uri !vfs with + match Vfs.read_file uri !(ls_state.vfs) with | None -> response_error_message id Lsp_t. @@ -253,43 +230,46 @@ let start entry_point debug = } | Some file_content -> let result = - Definition.definition_handler !decl_index position file_content - project_root - (Vfs.abs_file_from_uri log_to_file uri) + Definition.definition_handler !(ls_state.decl_index) position + file_content project_root + (Vfs.abs_file_from_uri uri) in response_result_message id result in - send_response (Lsp_j.string_of_response_message response) - | _, `TextDocumentDidOpen params -> vfs := Vfs.open_file params !vfs - | _, `TextDocumentDidChange params -> vfs := Vfs.update_file params !vfs - | _, `TextDocumentDidClose params -> vfs := Vfs.close_file params !vfs + IO.send (Lsp_j.string_of_response_message response) + | _, `TextDocumentDidOpen params -> + ls_state.vfs := Vfs.open_file params !(ls_state.vfs) + | _, `TextDocumentDidChange params -> + ls_state.vfs := Vfs.update_file params !(ls_state.vfs) + | _, `TextDocumentDidClose params -> + ls_state.vfs := Vfs.close_file params !(ls_state.vfs) | _, `TextDocumentDidSave _ -> let msgs = match - Declaration_index.make_index log_to_file project_root !vfs + Declaration_index.make_index project_root !(ls_state.vfs) [ entry_point ] with | Error msgs' -> List.iter (fun msg -> - log_to_file "rebuild_error" (Diag.string_of_message msg)) + Debug.log "rebuild_error" (Diag.string_of_message msg)) msgs'; msgs' | Ok (ix, msgs') -> - decl_index := ix; + ls_state.decl_index := ix; msgs' in sync_diagnostics msgs | None, `Initialized _ -> - sync_diagnostics !startup_diags; - startup_diags := []; - show_message Lsp.MessageType.Info "Motoko LS initialized" + sync_diagnostics !(ls_state.startup_diagnostics); + ls_state.startup_diagnostics := []; + IO.show_message Lsp.MessageType.Info "Motoko LS initialized" | Some id, `Shutdown _ -> - shutdown := true; + ls_state.shutdown := true; response_result_message id (`ShutdownResponse None) |> Lsp_j.string_of_response_message - |> send_response - | _, `Exit _ -> if !shutdown then exit 0 else exit 1 + |> IO.send + | _, `Exit _ -> if !(ls_state.shutdown) then exit 0 else exit 1 | Some id, `CompletionRequest params -> let uri = params.Lsp_t.text_document_position_params_textDocument @@ -297,7 +277,7 @@ let start entry_point debug = in let position = params.Lsp_t.text_document_position_params_position in let response = - match Vfs.read_file uri !vfs with + match Vfs.read_file uri !(ls_state.vfs) with | None -> response_error_message id Lsp_t. @@ -308,29 +288,17 @@ let start entry_point debug = opened yet"; } | Some file_content -> - Completion.completion_handler !decl_index log_to_file project_root - (Vfs.abs_file_from_uri log_to_file uri) + Completion.completion_handler !(ls_state.decl_index) project_root + (Vfs.abs_file_from_uri uri) file_content position |> response_result_message id in - response |> Lsp_j.string_of_response_message |> send_response + IO.send (Lsp_j.string_of_response_message response) (* Unhandled messages *) - | _ -> log_to_file "unhandled message" raw + | _ -> Debug.log "unhandled message" raw in let rec loop () = - let clength = read_line () in - let cl = "Content-Length: " in - let cll = String.length cl in - let num = - int_of_string String.(trim (sub clength cll (length clength - cll - 1))) - + 2 - in - let buffer = Buffer.create num in - Buffer.add_channel buffer stdin num; - let raw = String.trim (Buffer.contents buffer) in - let message = - try Some (Lsp_j.incoming_message_of_string raw) with _ -> None - in + let raw, message = IO.read_message () in ( match message with | None -> Debug.log "decoding error" raw | Some message -> diff --git a/src/languageServer/languageServer.mli b/src/languageServer/languageServer.mli new file mode 100644 index 00000000000..5acc4bf349b --- /dev/null +++ b/src/languageServer/languageServer.mli @@ -0,0 +1,3 @@ +(** Starts the language server against the given entry point. + ** The flag enables debug messages *) +val start : string -> bool -> 'a diff --git a/src/languageServer/vfs.ml b/src/languageServer/vfs.ml index b93b04643f2..46f389b185a 100644 --- a/src/languageServer/vfs.ml +++ b/src/languageServer/vfs.ml @@ -14,19 +14,19 @@ let file_uri_prefix = "file://" ^ Sys.getcwd () ^ "/" let uri_from_file path = "file://" ^ Lib.FilePath.make_absolute (Sys.getcwd ()) path -let file_from_uri logger uri = +let file_from_uri uri = match Lib.String.chop_prefix file_uri_prefix uri with | Some file -> file | None -> - let _ = logger "error" ("Failed to strip filename from: " ^ uri) in + let _ = Debug.log "error" ("Failed to strip filename from: " ^ uri) in uri -let abs_file_from_uri logger uri = +let abs_file_from_uri uri = Lib.FilePath.normalise ( match Lib.String.chop_prefix "file://" uri with | Some file -> file | None -> - let _ = logger "error" ("Failed to strip filename from: " ^ uri) in + let _ = Debug.log "error" ("Failed to strip filename from: " ^ uri) in uri ) let empty = VfsStore.empty diff --git a/src/languageServer/vfs.mli b/src/languageServer/vfs.mli index 3bb0017b927..23c0fb6e71e 100644 --- a/src/languageServer/vfs.mli +++ b/src/languageServer/vfs.mli @@ -8,9 +8,9 @@ type uri = string val uri_from_file : string -> uri -val file_from_uri : (string -> string -> 'a) -> uri -> string +val file_from_uri : uri -> string -val abs_file_from_uri : (string -> string -> 'a) -> uri -> string +val abs_file_from_uri : uri -> string val parse_file : t -> Pipeline.parse_fn From 36498aa982f437619f959d1915f20247545b74d6 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Tue, 7 Apr 2020 16:32:48 +0200 Subject: [PATCH 1162/1176] use ine Wasm instruction for integral not-equal (#1344) add routine for bigints resort to negation hack only for Bool, Text etc. Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- rts/bigint.c | 3 +++ src/codegen/compile.ml | 10 +++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/rts/bigint.c b/rts/bigint.c index 55879b8f0b8..c4d25e224c6 100644 --- a/rts/bigint.c +++ b/rts/bigint.c @@ -178,6 +178,9 @@ export as_ptr bigint_of_word64_signed(int64_t b) { export bool bigint_eq(as_ptr a, as_ptr b) { return mp_cmp(BIGINT_PAYLOAD(a), BIGINT_PAYLOAD(b)) == 0; } +export bool bigint_ne(as_ptr a, as_ptr b) { + return mp_cmp(BIGINT_PAYLOAD(a), BIGINT_PAYLOAD(b)) != 0; +} export bool bigint_lt(as_ptr a, as_ptr b) { return mp_cmp(BIGINT_PAYLOAD(a), BIGINT_PAYLOAD(b)) < 0; } diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 725e6c1648d..24bdd66fd92 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -659,6 +659,7 @@ module RTS = struct E.add_func_import env "rts" "bigint_to_word64_trap" [I32Type] [I64Type]; E.add_func_import env "rts" "bigint_to_word64_signed_trap" [I32Type] [I64Type]; E.add_func_import env "rts" "bigint_eq" [I32Type; I32Type] [I32Type]; + E.add_func_import env "rts" "bigint_ne" [I32Type; I32Type] [I32Type]; E.add_func_import env "rts" "bigint_isneg" [I32Type] [I32Type]; E.add_func_import env "rts" "bigint_count_bits" [I32Type] [I32Type]; E.add_func_import env "rts" "bigint_2complement_bits" [I32Type] [I32Type]; @@ -1589,7 +1590,7 @@ module ReadBuf = struct end (* Buf *) -type comparator = Lt | Le | Ge | Gt +type comparator = Lt | Le | Ge | Gt | Ne module type BigNumType = sig @@ -1671,12 +1672,14 @@ let i64op_from_relop = function | Le -> I64Op.LeS | Ge -> I64Op.GeS | Gt -> I64Op.GtS + | Ne -> I64Op.Ne let name_from_relop = function | Lt -> "B_lt" | Le -> "B_le" | Ge -> "B_ge" | Gt -> "B_gt" + | Ne -> "B_ne" (* helper, measures the dynamics of the unsigned i32, returns (32 - effective bits) *) let unsigned_dynamics get_x = @@ -2241,6 +2244,7 @@ module BigNumLibtommath : BigNumType = struct | Le -> E.call_import env "rts" "bigint_le" | Ge -> E.call_import env "rts" "bigint_ge" | Gt -> E.call_import env "rts" "bigint_gt" + | Ne -> E.call_import env "rts" "bigint_ne" let fits_signed_bits env bits = E.call_import env "rts" "bigint_2complement_bits" ^^ @@ -6012,6 +6016,7 @@ let get_relops = Operator.(function | GtOp -> Gt, I64Op.GtU, I64Op.GtS, I32Op.GtU, I32Op.GtS | LeOp -> Le, I64Op.LeU, I64Op.LeS, I32Op.LeU, I32Op.LeS | LtOp -> Lt, I64Op.LtU, I64Op.LtS, I32Op.LtU, I32Op.LtS + | NeqOp -> Ne, I64Op.Ne, I64Op.Ne, I32Op.Ne, I32Op.Ne | _ -> failwith "uncovered relop") let compile_comparison env t op = @@ -6033,10 +6038,9 @@ let compile_relop env t op = | Type.(Prim Text), _ -> Text.compare env op | Type.(Prim (Blob|Principal)), _ -> Blob.compare env op | _, EqOp -> compile_eq env t - | _, NeqOp -> compile_eq env t ^^ - G.i (Test (Wasm.Values.I32 I32Op.Eqz)) | Type.(Prim (Nat | Nat8 | Nat16 | Nat32 | Nat64 | Int | Int8 | Int16 | Int32 | Int64 | Word8 | Word16 | Word32 | Word64 | Char as t1)), op1 -> compile_comparison env t1 op1 + | _, NeqOp -> compile_eq env t ^^ G.i (Test (Wasm.Values.I32 I32Op.Eqz)) | _ -> todo_trap env "compile_relop" (Arrange_ops.relop op) let compile_load_field env typ name = From 1ec09bf31ef407b5449c2fc48228471033747d99 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Tue, 7 Apr 2020 16:55:51 +0200 Subject: [PATCH 1163/1176] refactor: rename Int (tag) -> Bits64 (#1343) * rename Int (tag) -> Bits64 * rename SmallWord -> Bits32 too review suggestion Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- src/codegen/compile.ml | 26 +++++++++++++------------- src/ir_def/ir.ml | 2 +- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 24bdd66fd92..614ca2e70c0 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -1020,14 +1020,14 @@ module Tagged = struct | Object | ObjInd (* The indirection used for object fields *) | Array (* Also a tuple *) - | Int (* Contains a 64 bit number *) + | Bits64 (* Contains a 64 bit number *) | MutBox (* used for mutable heap-allocated variables *) | Closure | Some (* For opt *) | Variant | Blob | Indirection - | SmallWord (* Contains a 32 bit unsigned number *) + | Bits32 (* Contains a 32 bit unsigned number *) | BigInt | Concat (* String concatenation, used by rts/text.c *) @@ -1036,14 +1036,14 @@ module Tagged = struct | Object -> 1l | ObjInd -> 2l | Array -> 3l - | Int -> 5l + | Bits64 -> 5l | MutBox -> 6l | Closure -> 7l | Some -> 8l | Variant -> 9l | Blob -> 10l | Indirection -> 11l - | SmallWord -> 12l + | Bits32 -> 12l | BigInt -> 13l | Concat -> 14l @@ -1267,7 +1267,7 @@ module BoxedWord64 = struct let (set_i, get_i) = new_local env "boxed_i64" in Heap.alloc env 3l ^^ set_i ^^ - get_i ^^ Tagged.store Tagged.Int ^^ + get_i ^^ Tagged.(store Bits64) ^^ get_i ^^ compile_elem ^^ Heap.store_field64 payload_field ^^ get_i @@ -1352,7 +1352,7 @@ module BoxedSmallWord = struct let (set_i, get_i) = new_local env "boxed_i32" in Heap.alloc env 2l ^^ set_i ^^ - get_i ^^ Tagged.store Tagged.SmallWord ^^ + get_i ^^ Tagged.(store Bits32) ^^ get_i ^^ compile_elem ^^ Heap.store_field payload_field ^^ get_i @@ -2349,7 +2349,7 @@ module Object = struct (* Set tag *) get_ri ^^ - Tagged.store Tagged.Object ^^ + Tagged.(store Object) ^^ (* Set size *) get_ri ^^ @@ -2465,7 +2465,7 @@ module Blob = struct Heap.dyn_alloc_bytes env ^^ set_x ^^ - get_x ^^ Tagged.store Tagged.Blob ^^ + get_x ^^ Tagged.(store Blob) ^^ get_x ^^ get_len ^^ Heap.store_field len_field ^^ get_x ) @@ -2699,7 +2699,7 @@ module Arr = struct (* Write header *) get_r ^^ - Tagged.store Tagged.Array ^^ + Tagged.(store Array) ^^ get_r ^^ get_len ^^ Heap.store_field len_field ^^ @@ -3278,9 +3278,9 @@ module HeapTraversal = struct Func.share_code1 env "object_size" ("x", I32Type) [I32Type] (fun env get_x -> get_x ^^ Tagged.branch env [I32Type] - [ Tagged.Int, + [ Tagged.Bits64, compile_unboxed_const 3l - ; Tagged.SmallWord, + ; Tagged.Bits32, compile_unboxed_const 2l ; Tagged.BigInt, compile_unboxed_const 5l (* HeapTag + sizeof(mp_int) *) @@ -4385,7 +4385,7 @@ module GC = struct (* Set indirection *) get_obj ^^ - Tagged.store Tagged.Indirection ^^ + Tagged.(store Indirection) ^^ get_obj ^^ get_new_ptr ^^ Heap.store_field 1l ^^ @@ -4946,7 +4946,7 @@ module FuncDec = struct (* Store the tag *) get_clos ^^ - Tagged.store Tagged.Closure ^^ + Tagged.(store Closure) ^^ (* Store the function pointer number: *) get_clos ^^ diff --git a/src/ir_def/ir.ml b/src/ir_def/ir.ml index 1eb67393386..f8e47accb1a 100644 --- a/src/ir_def/ir.ml +++ b/src/ir_def/ir.ml @@ -94,7 +94,7 @@ and lexp' = (* In the IR, a prim is any AST node that has expr subexpressions, but they are -all call-by-value. Many passes can treat them uniformly, so they are unified using the +all call-by-value. Many passes can treat them uniformly, so they are unified using the PrimE node. *) and prim = | CallPrim of Type.typ list (* function call *) From 41dacc729fc390063839dc7ff803b4344a055514 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Tue, 7 Apr 2020 21:17:41 +0200 Subject: [PATCH 1164/1176] Basic support for the Float type (#1316) * implement a few float operators in interpreter and backend machinery * (de)serialise support * unary/binary float prims to interpreter and backend * tests * debug_show for Float - no decimal point in interpreter - missing implementation of `@text_of_Float` * port specific files from `wasi-libc` (originally `musl`) * frobbing pow, sin, cos * funnel musl sources into rts build via nix too * lossy conversions Float <-> Int64 * add a float test that receives a 3.0 and returns a 6.0 --- default.nix | 14 ++ nix/sources.json | 13 ++ rts/Makefile | 89 ++++++++-- rts/float.c | 28 ++++ rts/stubs.c | 8 + src/codegen/compile.ml | 181 +++++++++++++++++++-- src/ir_passes/show.ml | 3 + src/mo_values/prim.ml | 28 +++- src/mo_values/show.ml | 2 + src/prelude/prelude.ml | 20 +++ test/run-drun/data-params.mo | 13 ++ test/run-drun/float.mo | 9 + test/run-drun/ok/data-params.drun-run.ok | 4 + test/run-drun/ok/data-params.ic-ref-run.ok | 4 + test/run-drun/ok/data-params.run-ir.ok | 4 + test/run-drun/ok/data-params.run-low.ok | 4 + test/run-drun/ok/data-params.run.ok | 4 + test/run-drun/ok/float.drun-run.ok | 2 + test/run-drun/ok/float.ic-ref-run.ok | 6 + test/run/float-ops.mo | 54 ++++++ test/run/numeric-ops.mo | 3 +- test/run/ok/issue36.comp.ok | 5 - test/run/ok/issue36.wasm-run.ok | 7 - test/run/ok/issue36.wasm-run.ret.ok | 1 - test/run/ok/numeric-ops.comp.ok | 32 ---- test/run/ok/relational-ops.comp.ok | 24 --- test/run/ok/type-inference.comp.ok | 1 - 27 files changed, 465 insertions(+), 98 deletions(-) create mode 100644 rts/float.c create mode 100644 rts/stubs.c create mode 100644 test/run-drun/float.mo create mode 100644 test/run-drun/ok/float.drun-run.ok create mode 100644 test/run-drun/ok/float.ic-ref-run.ok create mode 100644 test/run/float-ops.mo delete mode 100644 test/run/ok/issue36.comp.ok delete mode 100644 test/run/ok/issue36.wasm-run.ok delete mode 100644 test/run/ok/issue36.wasm-run.ret.ok delete mode 100644 test/run/ok/numeric-ops.comp.ok delete mode 100644 test/run/ok/relational-ops.comp.ok delete mode 100644 test/run/ok/type-inference.comp.ok diff --git a/default.nix b/default.nix index b9b43bd28a0..a3e9cacbd55 100644 --- a/default.nix +++ b/default.nix @@ -105,6 +105,16 @@ let ocaml_exe = name: bin: in rec { + musl-wasi-sysroot = stdenv.mkDerivation { + name = "musl-wasi-sysroot"; + buildInputs = [ nixpkgs.sources.musl-wasi ]; + phases = [ "installPhase" ]; + installPhase = '' + cp --no-preserve=mode ${nixpkgs.sources.musl-wasi}/Makefile ./mk + substituteInPlace ./mk --replace "cp -r" "cp --no-preserve=mode -r" + make --makefile=$(pwd)/mk -C ${nixpkgs.sources.musl-wasi} SYSROOT="$out" include_dirs + ''; + }; rts = stdenv.mkDerivation { name = "moc-rts"; @@ -116,6 +126,8 @@ rec { preBuild = '' ${llvmEnv} export TOMMATHSRC=${nixpkgs.sources.libtommath} + export MUSLSRC=${nixpkgs.sources.musl-wasi}/libc-top-half/musl + export MUSL_WASI_SYSROOT=${musl-wasi-sysroot} ''; doCheck = true; @@ -490,6 +502,8 @@ rec { shellHook = llvmEnv; ESM=nixpkgs.sources.esm; TOMMATHSRC = nixpkgs.sources.libtommath; + MUSLSRC = "${nixpkgs.sources.musl-wasi}/libc-top-half/musl"; + MUSL_WASI_SYSROOT = musl-wasi-sysroot; NIX_FONTCONFIG_FILE = users-guide.NIX_FONTCONFIG_FILE; LOCALE_ARCHIVE = stdenv.lib.optionalString stdenv.isLinux "${nixpkgs.glibcLocales}/lib/locale/locale-archive"; diff --git a/nix/sources.json b/nix/sources.json index e58b39ddde7..dca731eefc4 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -37,6 +37,19 @@ "url_template": "https://github.com///archive/.tar.gz", "version": "v1.2.0" }, + "musl-wasi": { + "branch": "master", + "builtin": false, + "description": "WASI libc implementation for WebAssembly", + "homepage": "https://wasi.dev", + "owner": "WebAssembly", + "repo": "wasi-libc", + "rev": "4b41c5d5ec64f1219e57e474c027d8552c1503ff", + "sha256": "17wlkpl495zs4cl3djdqaf089a4bhbrj87z2i2gm21cvmfqmva7p", + "type": "tarball", + "url": "https://github.com/WebAssembly/wasi-libc/archive/4b41c5d5ec64f1219e57e474c027d8552c1503ff.tar.gz", + "url_template": "https://github.com///archive/.tar.gz" + }, "nixpkgs": { "branch": "nixpkgs-unstable", "homepage": "https://github.com/NixOS/nixpkgs", diff --git a/rts/Makefile b/rts/Makefile index 9b52156ec23..1d53b8a5f5d 100644 --- a/rts/Makefile +++ b/rts/Makefile @@ -7,7 +7,7 @@ WASM_LD ?= wasm-ld-9 # (Usually the Wasm linker embedded in moc will complain if something is missing.) # -TOMMATHFILES=\ +TOMMATHFILES = \ mp_init mp_add mp_sub mp_mul mp_zero mp_cmp \ mp_set_u32 mp_set_i32 mp_get_i32 mp_get_mag_u32 \ mp_set_u64 mp_set_i64 mp_get_i64 mp_get_mag_u64 \ @@ -16,7 +16,16 @@ TOMMATHFILES=\ mp_init_size mp_exch mp_clear mp_copy mp_count_bits mp_mul_2d mp_rshd mp_mul_d mp_div_2d mp_mod_2d \ s_mp_balance_mul s_mp_toom_mul s_mp_toom_sqr s_mp_karatsuba_sqr s_mp_sqr_fast s_mp_sqr s_mp_karatsuba_mul s_mp_mul_digs_fast s_mp_mul_digs mp_init_multi mp_clear_multi mp_mul_2 mp_div_2 mp_div_3 mp_lshd mp_incr mp_decr mp_add_d mp_sub_d -TOMMATHSRC ?= $(PWD)/../../libtommath +MUSLFILES = \ + exp_data pow_data pow fabs sin cos __math_invalid \ + floor scalbn frexp strnlen memchr memset memcpy snprintf vsnprintf vfprintf \ + __math_oflow __math_uflow __math_xflow \ + __rem_pio2 __rem_pio2_large __sin __cos \ + stubs + +TOMMATHSRC ?= $(CURDIR)/../../libtommath +MUSLSRC ?= $(CURDIR)/../../wasi-libc/libc-top-half/musl +MUSL_WASI_SYSROOT ?= $(MUSLSRC)/../../sysroot # # Various libtommath flags, in particular telling it to use our own memory @@ -33,21 +42,59 @@ TOMMATH_FLAGS = \ -DMP_FIXED_CUTOFFS \ -DMP_NO_FILE \ +# +# Various musl flags, in particular telling it to not have long doubles +# and exclude , which pulls in too many dependencies +# +# Note: we use a bit of magic to get rid of invocations to __fwritex (and similar) +# - the headers contain a declaration, we rename it to (__fwritex ## __COUNTER__) +# - similarly the invocation becomes __fwritex_2(...) which we inline immediately +# Be aware that upon bumps of the musl sources the number of occurrences may jump a bit +# and will need tweaks/additions below. +# Similarly we define include guards (to suppress certain headers), but those should be +# pretty stable. +# TODO: run `wasm2wat mo-rts.wasm | grep -F '(import' | grep __fwritex_` expecting empty. +# +# See also https://stackoverflow.com/questions/1597007/creating-c-macro-with-and-line-token-concatenation-with-positioning-macr + +MUSL_FLAGS = \ + -isystem $(MUSLSRC)/arch/wasm32 \ + -isystem $(MUSLSRC)/src/include \ + -isystem $(MUSLSRC)/src/internal \ + -isystem $(MUSL_WASI_SYSROOT)/include \ + -I $(MUSLSRC)/../headers/private \ + -D_ERRNO_H -DEOVERFLOW=75 -DEINVAL=22 \ + -Derrno='(*({ static int bla = 0; &bla; }))' \ + -DNL_ARGMAX=9 \ + -D'TOKENPASTE0(x, y)=x \#\# y' \ + -D'TOKENPASTE(x, y)=TOKENPASTE0(x, y)' \ + -D'__fwritex=TOKENPASTE(__fwritex_,__COUNTER__)' \ + -D'__fwritex_2(s, l, f)=(f->write((f), (s), (l)))' \ + -D'__towrite=TOKENPASTE(__towrite_,__COUNTER__)' \ + -D'__towrite_3(f)=(0)' \ + -D__wasilibc_printscan_no_long_double \ + -D__wasilibc_printscan_full_support_option='""' \ + -D__wasi__ \ + -D__NEED_va_list \ + -D__NEED_off_t + # # clang flags used both for Wasm compilation and native (i.e. test suite) compilation # CLANG_FLAGS = \ - --compile \ + --compile \ -fpic \ -fvisibility=hidden \ + --std=c11 # # clang flags only used during Wasm compilation # WASM_FLAGS = \ - --target=wasm32-unknown-emscripten-wasm -fvisibility=hidden \ + --target=wasm32-emscripten \ + -fvisibility=hidden \ -fno-builtin -ffreestanding \ --optimize=3 \ @@ -66,28 +113,42 @@ _build/wasm _build/native: # Building the libtommath files, Wasm and native # +_build/wasm/tommath_%.o: bn_%.c | _build/wasm + $(WASM_CLANG) $(CLANG_FLAGS) $(WASM_FLAGS) $(TOMMATH_FLAGS) $< --output $@ -_build/wasm/tommath_%.o: $(TOMMATHSRC)/bn_%.c | _build/wasm - $(WASM_CLANG) -c $(CLANG_FLAGS) $(WASM_FLAGS) $(TOMMATH_FLAGS) $< --output $@ - - -_build/native/tommath_%.o: $(TOMMATHSRC)/bn_%.c | _build/native - $(CLANG) -c $(CLANG_FLAGS) $(TOMMATH_FLAGS) $< --output $@ +_build/native/tommath_%.o: bn_%.c | _build/native + $(CLANG) $(CLANG_FLAGS) $(TOMMATH_FLAGS) $< --output $@ TOMMATH_WASM_O=$(TOMMATHFILES:%=_build/wasm/tommath_%.o) TOMMATH_NATIVE_O=$(TOMMATHFILES:%=_build/native/tommath_%.o) +MUSL_WASM_O=$(MUSLFILES:%=_build/wasm/musl_%.o) + +# +# Look into following directories for source dependencies +# + +vpath %.c $(MUSLSRC)/src/math $(MUSLSRC)/src/stdio $(MUSLSRC)/src/string $(TOMMATHSRC) # # Our part of the RTS, Wasm and native # -RTSFILES=rts idl bigint buf utf8_valid closure-table text blob url +RTSFILES=rts idl bigint float buf utf8_valid closure-table text blob url _build/wasm/%.o: %.c rts.h buf.h | _build/wasm - $(WASM_CLANG) -c $(CLANG_FLAGS) $(WASM_FLAGS) $(TOMMATH_FLAGS) -I$(TOMMATHSRC) --std=c11 $< --output $@ + $(WASM_CLANG) $(CLANG_FLAGS) $(WASM_FLAGS) $(TOMMATH_FLAGS) -I$(TOMMATHSRC) $< --output $@ _build/native/%.o: %.c rts.h buf.h | _build/native - $(CLANG) -c $(CLANG_FLAGS) $(TOMMATH_FLAGS) -I$(TOMMATHSRC) --std=c11 $< --output $@ + $(CLANG) $(CLANG_FLAGS) $(TOMMATH_FLAGS) -I$(TOMMATHSRC) $< --output $@ + +_build/wasm/tommath_%.o: %.c rts.h buf.h | _build/wasm + $(WASM_CLANG) $(CLANG_FLAGS) $(WASM_FLAGS) $(TOMMATH_FLAGS) $< --output $@ + +_build/native/tommath_%.o: %.c rts.h buf.h | _build/native + $(CLANG) $(CLANG_FLAGS) $(TOMMATH_FLAGS) $< --output $@ + +_build/wasm/musl_%.o: %.c | _build/wasm + $(WASM_CLANG) $(CLANG_FLAGS) $(WASM_FLAGS) $(MUSL_FLAGS) $< --output $@ RTS_WASM_O=$(RTSFILES:%=_build/wasm/%.o) RTS_NATIVE_O=$(RTSFILES:%=_build/native/%.o) @@ -96,7 +157,7 @@ RTS_NATIVE_O=$(RTSFILES:%=_build/native/%.o) # The actual RTS, as we ship it with the compiler # -mo-rts.wasm: $(RTS_WASM_O) $(TOMMATH_WASM_O) +mo-rts.wasm: $(RTS_WASM_O) $(TOMMATH_WASM_O) $(MUSL_WASM_O) $(WASM_LD) -o $@ \ --import-memory --shared --no-entry --gc-sections \ --export=__wasm_call_ctors \ diff --git a/rts/float.c b/rts/float.c new file mode 100644 index 00000000000..bf717e42e58 --- /dev/null +++ b/rts/float.c @@ -0,0 +1,28 @@ +#include "rts.h" + +// this is not intended for native compilation/testing (yet) +#ifdef __wasm__ + +export as_ptr float_fmt(double a) { + extern int snprintf(char *__restrict, size_t, const char *__restrict, ...); + char buf[50]; // corresponds to 150 bits of pure floatness, room for 64 bits needed + const int chars = snprintf(buf, sizeof buf, "%f", a); + return text_of_ptr_size(buf, chars); +} + +export double float_pow(double a, double b) { + extern double pow(double, double); + return pow(a, b); +} + +export double float_sin(double a) { + extern double sin(double); + return sin(a); +} + +export double float_cos(double a) { + extern double cos(double); + return cos(a); +} + +#endif diff --git a/rts/stubs.c b/rts/stubs.c new file mode 100644 index 00000000000..7c1be81b0bb --- /dev/null +++ b/rts/stubs.c @@ -0,0 +1,8 @@ +#include "rts.h" + +/* Stubbery for musl */ + +int wctomb(char *s, wchar_t wc) { *s = '\0'; } +int fputs(const char *s, void *f) { return 0; } +void abort(void) __attribute__((__noreturn__)) { rts_trap("abort", 5); } +char *strerror(int e) { return ""; } diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 614ca2e70c0..b4651cdabc2 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -85,6 +85,7 @@ module SR = struct | UnboxedTuple of int | UnboxedWord64 | UnboxedWord32 + | UnboxedFloat64 | Unreachable | Const of Const.t @@ -486,7 +487,7 @@ let bytes_of_int32 (i : int32) : string = (* A common variant of todo *) let todo_trap env fn se = todo fn se (E.trap_with env ("TODO: " ^ fn)) -let todo_trap_SR env fn se = todo fn se (SR.Unreachable, E.trap_with env ("TODO: " ^ fn)) +let _todo_trap_SR env fn se = todo fn se (SR.Unreachable, E.trap_with env ("TODO: " ^ fn)) (* Locals *) @@ -506,6 +507,10 @@ let new_local64 env name = let (set_i, get_i, _) = new_local_ env I64Type name in (set_i, get_i) +let new_float_local env name = + let (set_i, get_i, _) = new_local_ env F64Type name + in (set_i, get_i) + (* Some common code macros *) (* Iterates while cond is true. *) @@ -710,6 +715,10 @@ module RTS = struct E.add_func_import env "rts" "blob_iter_done" [I32Type] [I32Type]; E.add_func_import env "rts" "blob_iter" [I32Type] [I32Type]; E.add_func_import env "rts" "blob_iter_next" [I32Type] [I32Type]; + E.add_func_import env "rts" "float_pow" [F64Type; F64Type] [F64Type]; + E.add_func_import env "rts" "float_sin" [F64Type] [F64Type]; + E.add_func_import env "rts" "float_cos" [F64Type] [F64Type]; + E.add_func_import env "rts" "float_fmt" [F64Type] [I32Type]; () end (* RTS *) @@ -835,6 +844,16 @@ module Heap = struct let offset = Int32.(add (mul word_size i) ptr_unskew) in G.i (Store {ty = I64Type; align = 2; offset; sz = None}) + (* Or even as a single 64 bit float *) + + let load_field_float64 (i : int32) : G.t = + let offset = Int32.(add (mul word_size i) ptr_unskew) in + G.i (Load {ty = F64Type; align = 2; offset; sz = None}) + + let store_field_float64 (i : int32) : G.t = + let offset = Int32.(add (mul word_size i) ptr_unskew) in + G.i (Store {ty = F64Type; align = 2; offset; sz = None}) + (* Create a heap object with instructions that fill in each word *) let obj env element_instructions : G.t = let (set_heap_obj, get_heap_obj) = new_local env "heap_object" in @@ -1502,6 +1521,42 @@ module UnboxedSmallWord = struct end (* UnboxedSmallWord *) + +module Float = struct + (* We store floats (C doubles) in immutable boxed 64bit heap objects. + + The heap layout of a Float is: + + ┌─────┬─────┬─────┐ + │ tag │ f64 │ + └─────┴─────┴─────┘ + + For now the tag stored is that of a Bits64, because the payload is + treated opaquely by the RTS. We'll introduce a separate tag when the need of + debug inspection (or GC representation change) arises. + + *) + + let payload_field = Tagged.header_size + + let compile_unboxed_const f = G.i Wasm.(Ast.Const (nr (Values.F64 f))) + let lit f = compile_unboxed_const (Wasm.F64.of_float f) + let compile_unboxed_zero = lit 0.0 + + let box env = Func.share_code1 env "box_f64" ("f", F64Type) [I32Type] (fun env get_f -> + let (set_i, get_i) = new_local env "boxed_f64" in + Heap.alloc env 3l ^^ + set_i ^^ + get_i ^^ Tagged.(store Bits64) ^^ + get_i ^^ get_f ^^ Heap.store_field_float64 payload_field ^^ + get_i + ) + + let unbox env = Heap.load_field_float64 payload_field + +end (* Float *) + + module ReadBuf = struct (* Combinators to safely read from a dynamic buffer. @@ -1579,6 +1634,12 @@ module ReadBuf = struct G.i (Load {ty = I64Type; align = 0; offset = 0l; sz = None}) ^^ advance get_buf (compile_unboxed_const 8l) + let read_float64 env get_buf = + check_space env get_buf (compile_unboxed_const 8l) ^^ + get_ptr get_buf ^^ + G.i (Load {ty = F64Type; align = 0; offset = 0l; sz = None}) ^^ + advance get_buf (compile_unboxed_const 8l) + let read_blob env get_buf get_len = check_space env get_buf get_len ^^ (* Already has destination address on the stack *) @@ -3669,7 +3730,7 @@ module Serialization = struct | Prim (Int8|Nat8|Word8) -> inc_data_size (compile_unboxed_const 1l) | Prim (Int16|Nat16|Word16) -> inc_data_size (compile_unboxed_const 2l) | Prim (Int32|Nat32|Word32|Char) -> inc_data_size (compile_unboxed_const 4l) - | Prim (Int64|Nat64|Word64) -> inc_data_size (compile_unboxed_const 8l) + | Prim (Int64|Nat64|Word64|Float) -> inc_data_size (compile_unboxed_const 8l) | Prim Bool -> inc_data_size (compile_unboxed_const 1l) | Prim Null -> G.nop | Any -> G.nop @@ -3780,6 +3841,11 @@ module Serialization = struct get_x ^^ BigNum.compile_store_to_data_buf_signed env ^^ advance_data_buf + | Prim Float -> + get_data_buf ^^ + get_x ^^ Float.unbox env ^^ + G.i (Store {ty = F64Type; align = 0; offset = 0l; sz = None}) ^^ + compile_unboxed_const 8l ^^ advance_data_buf | Prim (Int64|Nat64|Word64) -> get_data_buf ^^ get_x ^^ BoxedWord64.unbox env ^^ @@ -4011,6 +4077,10 @@ module Serialization = struct get_data_buf ^^ BigNum.compile_load_from_data_buf env true end + | Prim Float -> + assert_prim_typ t ^^ + ReadBuf.read_float64 env get_data_buf ^^ + Float.box env | Prim (Int64|Nat64|Word64) -> assert_prim_typ t ^^ ReadBuf.read_word64 env get_data_buf ^^ @@ -4538,12 +4608,14 @@ module StackRep = struct | Prim (Nat32 | Int32 | Word32) -> UnboxedWord32 | Prim (Nat8 | Nat16 | Int8 | Int16 | Word8 | Word16 | Char) -> Vanilla | Prim (Text | Blob | Principal) -> Vanilla + | Prim Float -> UnboxedFloat64 | p -> todo "StackRep.of_type" (Arrange_ir.typ p) Vanilla let to_block_type env = function | Vanilla -> [I32Type] | UnboxedWord64 -> [I64Type] | UnboxedWord32 -> [I32Type] + | UnboxedFloat64 -> [F64Type] | UnboxedTuple 0 -> [] | UnboxedTuple 1 -> [I32Type] | UnboxedTuple n -> @@ -4555,6 +4627,7 @@ module StackRep = struct | Vanilla -> "Vanilla" | UnboxedWord64 -> "UnboxedWord64" | UnboxedWord32 -> "UnboxedWord32" + | UnboxedFloat64 -> "UnboxedFloat64" | UnboxedTuple n -> Printf.sprintf "UnboxedTuple %d" n | Unreachable -> "Unreachable" | Const _ -> "StaticThing" @@ -4583,12 +4656,9 @@ module StackRep = struct let drop env (sr_in : t) = match sr_in with - | Vanilla -> G.i Drop - | UnboxedWord64 -> G.i Drop - | UnboxedWord32 -> G.i Drop + | Vanilla | UnboxedWord64 | UnboxedWord32 | UnboxedFloat64 -> G.i Drop | UnboxedTuple n -> G.table n (fun _ -> G.i Drop) - | Const _ -> G.nop - | Unreachable -> G.nop + | Const _ | Unreachable -> G.nop let rec materialize env (p, cv) = if Lib.Promise.is_fulfilled p @@ -4622,6 +4692,9 @@ module StackRep = struct | UnboxedWord32, Vanilla -> BoxedSmallWord.box env | Vanilla, UnboxedWord32 -> BoxedSmallWord.unbox env + | UnboxedFloat64, Vanilla -> Float.box env + | Vanilla, UnboxedFloat64 -> Float.unbox env + | Const c, Vanilla -> materialize env c | Const c, UnboxedTuple 0 -> G.nop @@ -5425,7 +5498,7 @@ let compile_lit env lit = | NullLit -> SR.Vanilla, Opt.null | TextLit t | BlobLit t -> SR.Vanilla, Blob.lit env t - | FloatLit _ -> todo_trap_SR env "compile_lit" (Arrange_ir.lit lit) + | FloatLit f -> SR.UnboxedFloat64, Float.compile_unboxed_const f with Failure _ -> Printf.eprintf "compile_lit: Overflow in literal %s\n" (string_of_lit lit); SR.Unreachable, E.trap_with env "static literal overflow" @@ -5485,11 +5558,15 @@ let compile_unop env t op = get_n ^^ G.i (Binary (Wasm.Values.I32 I32Op.Sub)) ) + | NegOp, Type.(Prim Float) -> + SR.UnboxedFloat64, SR.UnboxedFloat64, + let (set_f, get_f) = new_float_local env "f" in + set_f ^^ Float.compile_unboxed_zero ^^ get_f ^^ G.i (Binary (Wasm.Values.F64 F64Op.Sub)) | NotOp, Type.(Prim Word64) -> SR.UnboxedWord64, SR.UnboxedWord64, compile_const_64 (-1L) ^^ G.i (Binary (Wasm.Values.I64 I64Op.Xor)) - | NotOp, Type.Prim Type.(Word8 | Word16 | Word32 as ty) -> + | NotOp, Type.(Prim (Word8 | Word16 | Word32 as ty)) -> StackRep.of_type t, StackRep.of_type t, compile_unboxed_const (UnboxedSmallWord.mask_of_type ty) ^^ G.i (Binary (Wasm.Values.I32 I32Op.Xor)) @@ -5775,11 +5852,13 @@ let compile_binop env t op = | Type.Prim Type.(Int8 | Int16 as ty), AddOp -> compile_smallInt_kernel env ty "add" I32Op.Add | Type.(Prim Nat32), AddOp -> compile_Nat32_kernel env "add" I64Op.Add | Type.Prim Type.(Nat8 | Nat16 as ty), AddOp -> compile_smallNat_kernel env ty "add" I32Op.Add + | Type.(Prim Float), AddOp -> G.i (Binary (Wasm.Values.F64 F64Op.Add)) | Type.Prim Type.(Word8 | Word16 | Word32), SubOp -> G.i (Binary (Wasm.Values.I32 I32Op.Sub)) | Type.(Prim Int32), SubOp -> compile_Int32_kernel env "sub" I64Op.Sub | Type.(Prim (Int8|Int16 as ty)), SubOp -> compile_smallInt_kernel env ty "sub" I32Op.Sub | Type.(Prim Nat32), SubOp -> compile_Nat32_kernel env "sub" I64Op.Sub | Type.(Prim (Nat8|Nat16 as ty)), SubOp -> compile_smallNat_kernel env ty "sub" I32Op.Sub + | Type.(Prim Float), SubOp -> G.i (Binary (Wasm.Values.F64 F64Op.Sub)) | Type.(Prim (Word8|Word16|Word32 as ty)), MulOp -> UnboxedSmallWord.compile_word_mul env ty | Type.(Prim Int32), MulOp -> compile_Int32_kernel env "mul" I64Op.Mul | Type.(Prim Int16), MulOp -> compile_smallInt_kernel env Type.Int16 "mul" I32Op.Mul @@ -5789,6 +5868,7 @@ let compile_binop env t op = | Type.(Prim Nat16), MulOp -> compile_smallNat_kernel env Type.Nat16 "mul" I32Op.Mul | Type.(Prim Nat8), MulOp -> compile_smallNat_kernel' env Type.Nat8 "mul" (compile_shrU_const 8l ^^ G.i (Binary (Wasm.Values.I32 I32Op.Mul))) + | Type.(Prim Float), MulOp -> G.i (Binary (Wasm.Values.F64 F64Op.Mul)) | Type.(Prim (Nat8|Nat16|Nat32|Word8|Word16|Word32 as ty)), DivOp -> G.i (Binary (Wasm.Values.I32 I32Op.DivU)) ^^ UnboxedSmallWord.msb_adjust ty @@ -5810,6 +5890,7 @@ let compile_binop env t op = get_res end get_res) + | Type.(Prim Float), DivOp -> G.i (Binary (Wasm.Values.F64 F64Op.Div)) | Type.(Prim (Int8|Int16|Int32)), ModOp -> G.i (Binary (Wasm.Values.I32 I32Op.RemS)) | Type.(Prim (Word8|Word16|Word32 as ty)), PowOp -> UnboxedSmallWord.compile_word_power env ty | Type.(Prim ((Nat8|Nat16) as ty)), PowOp -> @@ -5957,6 +6038,7 @@ let compile_binop env t op = BigNum.compile_unsigned_pow (powNat64_shortcut (BoxedWord64.compile_unsigned_pow env)) | Type.(Prim Nat), PowOp -> BigNum.compile_unsigned_pow env + | Type.(Prim Float), PowOp -> E.call_import env "rts" "float_pow" | Type.(Prim Word64), AndOp -> G.i (Binary (Wasm.Values.I64 I64Op.And)) | Type.Prim Type.(Word8 | Word16 | Word32), AndOp -> G.i (Binary (Wasm.Values.I32 I32Op.And)) | Type.(Prim Word64), OrOp -> G.i (Binary (Wasm.Values.I64 I64Op.Or)) @@ -6009,6 +6091,7 @@ let compile_eq env = function | Type.(Prim (Int8 | Nat8 | Word8 | Int16 | Nat16 | Word16 | Int32 | Nat32 | Word32 | Char)) -> G.i (Compare (Wasm.Values.I32 I32Op.Eq)) | Type.Non -> G.i Unreachable + | Type.(Prim Float) -> G.i (Compare (Wasm.Values.F64 F64Op.Eq)) | _ -> todo_trap env "compile_eq" (Arrange_ops.relop Operator.EqOp) let get_relops = Operator.(function @@ -6038,9 +6121,14 @@ let compile_relop env t op = | Type.(Prim Text), _ -> Text.compare env op | Type.(Prim (Blob|Principal)), _ -> Blob.compare env op | _, EqOp -> compile_eq env t + | Type.(Prim Float), NeqOp -> G.i (Compare (Wasm.Values.F64 F64Op.Ne)) | Type.(Prim (Nat | Nat8 | Nat16 | Nat32 | Nat64 | Int | Int8 | Int16 | Int32 | Int64 | Word8 | Word16 | Word32 | Word64 | Char as t1)), op1 -> compile_comparison env t1 op1 | _, NeqOp -> compile_eq env t ^^ G.i (Test (Wasm.Values.I32 I32Op.Eqz)) + | Type.(Prim Float), GtOp -> G.i (Compare (Wasm.Values.F64 F64Op.Gt)) + | Type.(Prim Float), GeOp -> G.i (Compare (Wasm.Values.F64 F64Op.Ge)) + | Type.(Prim Float), LeOp -> G.i (Compare (Wasm.Values.F64 F64Op.Le)) + | Type.(Prim Float), LtOp -> G.i (Compare (Wasm.Values.F64 F64Op.Lt)) | _ -> todo_trap env "compile_relop" (Arrange_ops.relop op) let compile_load_field env typ name = @@ -6324,7 +6412,17 @@ and compile_exp (env : E.t) ae exp = SR.Vanilla, compile_exp_as env ae SR.UnboxedWord32 e ^^ Func.share_code1 env "Word32->Char" ("n", I32Type) [I32Type] - UnboxedSmallWord.check_and_box_codepoint + UnboxedSmallWord.check_and_box_codepoint + + | Float, Int64 -> + SR.UnboxedWord64, + compile_exp_as env ae SR.UnboxedFloat64 e ^^ + G.i (Convert (Wasm.Values.I64 I64Op.TruncSF64)) + + | Int64, Float -> + SR.UnboxedFloat64, + compile_exp_as env ae SR.UnboxedWord64 e ^^ + G.i (Convert (Wasm.Values.F64 F64Op.ConvertSI64)) | _ -> SR.Unreachable, todo_trap env "compile_exp" (Arrange_ir.exp exp) end @@ -6360,6 +6458,69 @@ and compile_exp (env : E.t) ae exp = compile_exp_vanilla env ae e ^^ BigNum.compile_abs env + | OtherPrim "fabs", [e] -> + SR.UnboxedFloat64, + compile_exp_as env ae SR.UnboxedFloat64 e ^^ + G.i (Unary (Wasm.Values.F64 F64Op.Abs)) + + | OtherPrim "fsqrt", [e] -> + SR.UnboxedFloat64, + compile_exp_as env ae SR.UnboxedFloat64 e ^^ + G.i (Unary (Wasm.Values.F64 F64Op.Sqrt)) + + | OtherPrim "fceil", [e] -> + SR.UnboxedFloat64, + compile_exp_as env ae SR.UnboxedFloat64 e ^^ + G.i (Unary (Wasm.Values.F64 F64Op.Ceil)) + + | OtherPrim "ffloor", [e] -> + SR.UnboxedFloat64, + compile_exp_as env ae SR.UnboxedFloat64 e ^^ + G.i (Unary (Wasm.Values.F64 F64Op.Floor)) + + | OtherPrim "ftrunc", [e] -> + SR.UnboxedFloat64, + compile_exp_as env ae SR.UnboxedFloat64 e ^^ + G.i (Unary (Wasm.Values.F64 F64Op.Trunc)) + + | OtherPrim "fnearest", [e] -> + SR.UnboxedFloat64, + compile_exp_as env ae SR.UnboxedFloat64 e ^^ + G.i (Unary (Wasm.Values.F64 F64Op.Nearest)) + + | OtherPrim "fmin", [e; f] -> + SR.UnboxedFloat64, + compile_exp_as env ae SR.UnboxedFloat64 e ^^ + compile_exp_as env ae SR.UnboxedFloat64 f ^^ + G.i (Binary (Wasm.Values.F64 F64Op.Min)) + + | OtherPrim "fmax", [e; f] -> + SR.UnboxedFloat64, + compile_exp_as env ae SR.UnboxedFloat64 e ^^ + compile_exp_as env ae SR.UnboxedFloat64 f ^^ + G.i (Binary (Wasm.Values.F64 F64Op.Max)) + + | OtherPrim "fcopysign", [e; f] -> + SR.UnboxedFloat64, + compile_exp_as env ae SR.UnboxedFloat64 e ^^ + compile_exp_as env ae SR.UnboxedFloat64 f ^^ + G.i (Binary (Wasm.Values.F64 F64Op.CopySign)) + + | OtherPrim "Float->Text", [e] -> + SR.Vanilla, + compile_exp_as env ae SR.UnboxedFloat64 e ^^ + E.call_import env "rts" "float_fmt" + + | OtherPrim "fsin", [e] -> + SR.UnboxedFloat64, + compile_exp_as env ae SR.UnboxedFloat64 e ^^ + E.call_import env "rts" "float_sin" + + | OtherPrim "fcos", [e] -> + SR.UnboxedFloat64, + compile_exp_as env ae SR.UnboxedFloat64 e ^^ + E.call_import env "rts" "float_cos" + | OtherPrim "rts_version", [] -> SR.Vanilla, E.call_import env "rts" "version" diff --git a/src/ir_passes/show.ml b/src/ir_passes/show.ml index 66c57027ac9..174070ba20d 100644 --- a/src/ir_passes/show.ml +++ b/src/ir_passes/show.ml @@ -166,6 +166,9 @@ let show_for : T.typ -> Ir.dec * T.typ list = fun t -> | T.(Prim Word64) -> define_show t (invoke_prelude_show "@text_of_Word64" t (argE t)), [] + | T.(Prim Float) -> + define_show t (invoke_prelude_show "@text_of_Float" t (argE t)), + [] | T.(Prim Text) -> define_show t (invoke_prelude_show "@text_of_Text" t (argE t)), [] diff --git a/src/mo_values/prim.ml b/src/mo_values/prim.ml index 6c8bb3a2304..395edeb4bb1 100644 --- a/src/mo_values/prim.ml +++ b/src/mo_values/prim.ml @@ -193,11 +193,35 @@ let num_conv_prim t1 t2 = | T.Word32, T.Char -> fun _ v k -> let i = Conv.int_of_word32_u (as_word32 v) in if i < 0xD800 || i >= 0xE000 && i < 0x110000 then k (Char i) else raise (Invalid_argument "character value out of bounds") + | T.Float, T.Int64 -> fun _ v k -> k (Int64 (Int_64.of_big_int (Big_int.big_int_of_int64 (Wasm.I64_convert.trunc_f64_s (as_float v))))) + | T.Int64, T.Float -> fun _ v k -> k (Float (Wasm.F64_convert.convert_i64_s (Big_int.int64_of_big_int (Int_64.to_big_int (as_int64 v))))) | t1, t2 -> raise (Invalid_argument ("Value.num_conv_prim: " ^ T.string_of_typ (T.Prim t1) ^ T.string_of_typ (T.Prim t2) )) -let prim = function +let prim = + let via_float f v = Float.(Float (of_float (f (to_float (as_float v))))) in + function | "abs" -> fun _ v k -> k (Int (Nat.abs (as_int v))) - + | "fabs" -> fun _ v k -> k (Float (Float.abs (as_float v))) + | "fsqrt" -> fun _ v k -> k (Float (Float.sqrt (as_float v))) + | "fceil" -> fun _ v k -> k (Float (Float.ceil (as_float v))) + | "ffloor" -> fun _ v k -> k (Float (Float.floor (as_float v))) + | "ftrunc" -> fun _ v k -> k (Float (Float.trunc (as_float v))) + | "fnearest" -> fun _ v k -> k (Float (Float.nearest (as_float v))) + | "fmin" -> fun _ v k -> + (match Value.as_tup v with + | [a; b] -> k (Float (Float.min (as_float a) (as_float b))) + | _ -> assert false) + | "fmax" -> fun _ v k -> + (match Value.as_tup v with + | [a; b] -> k (Float (Float.max (as_float a) (as_float b))) + | _ -> assert false) + | "fcopysign" -> fun _ v k -> + (match Value.as_tup v with + | [a; b] -> k (Float (Float.copysign (as_float a) (as_float b))) + | _ -> assert false) + | "Float->Text" -> fun _ v k -> k (Text (Float.to_string (as_float v))) + | "fsin" -> fun _ v k -> k (via_float Stdlib.sin v) + | "fcos" -> fun _ v k -> k (via_float Stdlib.cos v) | "popcnt8" | "popcnt16" | "popcnt32" | "popcnt64" -> fun _ v k -> diff --git a/src/mo_values/show.ml b/src/mo_values/show.ml index 6f5cd147c92..6b1a20d83ff 100644 --- a/src/mo_values/show.ml +++ b/src/mo_values/show.ml @@ -10,6 +10,7 @@ let rec can_show t = | Prim (Nat16|Int16|Word16) | Prim (Nat32|Int32|Word32) | Prim (Nat64|Int64|Word64) -> true + | Prim Float -> true | Tup ts' -> List.for_all can_show ts' | Opt t' -> can_show t' | Array t' -> can_show (as_immut t') @@ -44,6 +45,7 @@ let rec show_val t v = | T.(Prim Word16), Value.Word16 i -> "0x" ^ Value.Word16.to_string i | T.(Prim Word32), Value.Word32 i -> "0x" ^ Value.Word32.to_string i | T.(Prim Word64), Value.Word64 i -> "0x" ^ Value.Word64.to_string i + | T.(Prim Float), Value.Float i -> Value.Float.to_string i | T.(Prim Text), Value.Text s -> "\"" ^ s ^ "\"" | T.(Prim Char), Value.Char c -> "\'" ^ Wasm.Utf8.encode [c] ^ "\'" | T.(Prim Null), Value.Null -> "null" diff --git a/src/prelude/prelude.ml b/src/prelude/prelude.ml index 4479d257c41..6afb8c3858e 100644 --- a/src/prelude/prelude.ml +++ b/src/prelude/prelude.ml @@ -180,6 +180,7 @@ func @text_of_Word8(x : Word8) : Text = @text_of_Word (@word8ToNat x); func @text_of_Word16(x : Word16) : Text = @text_of_Word (@word16ToNat x); func @text_of_Word32(x : Word32) : Text = @text_of_Word (@word32ToNat x); func @text_of_Word64(x : Word64) : Text = @text_of_Word (@word64ToNat x); +func @text_of_Float(x : Float) : Text = (prim "Float->Text" : Float -> Text) x; func @text_of_Bool(b : Bool) : Text { @@ -434,6 +435,25 @@ func clzWord64(w : Word64) : Word64 = (prim "clz64" : Word64 -> Word64) w; func ctzWord64(w : Word64) : Word64 = (prim "ctz64" : Word64 -> Word64) w; func btstWord64(w : Word64, amount : Word64) : Bool = (prim "btst64" : (Word64, Word64) -> Word64) (w, amount) != (0 : Word64); +// Float operations + +func floatAbs(f : Float) : Float = (prim "fabs" : Float -> Float) f; +func floatSqrt(f : Float) : Float = (prim "fsqrt" : Float -> Float) f; +func floatCeil(f : Float) : Float = (prim "fceil" : Float -> Float) f; +func floatFloor(f : Float) : Float = (prim "ffloor" : Float -> Float) f; +func floatTrunc(f : Float) : Float = (prim "ftrunc" : Float -> Float) f; +func floatNearest(f : Float) : Float = (prim "fnearest" : Float -> Float) f; +func floatMin(f : Float, g : Float) : Float = (prim "fmin" : (Float, Float) -> Float) (f, g); +func floatMax(f : Float, g : Float) : Float = (prim "fmax" : (Float, Float) -> Float) (f, g); +func floatCopySign(f : Float, g : Float) : Float = (prim "fcopysign" : (Float, Float) -> Float) (f, g); +func floatToInt64(f : Float) : Int64 = (prim "num_conv_Float_Int64" : Float -> Int64) (f); +func int64ToFloat(n : Int64) : Float = (prim "num_conv_Int64_Float" : Int64 -> Float) (n); + +// Trigonometric functions + +func sin(f : Float) : Float = (prim "fsin" : Float -> Float) f; +func cos(f : Float) : Float = (prim "fcos" : Float -> Float) f; + // Array utilities func Array_init(len : Nat, x : T) : [var T] { diff --git a/test/run-drun/data-params.mo b/test/run-drun/data-params.mo index d8601f83627..f4323df4bf3 100644 --- a/test/run-drun/data-params.mo +++ b/test/run-drun/data-params.mo @@ -73,6 +73,18 @@ actor a { c += Prim.int64ToInt(i64); Prim.debugPrintInt(c); }; + var f : Float = 0.0; + public func incfloat(f64 : Float) : () { + f += f64; + assert(f == 42.0); + Prim.debugPrint(debug_show(f)); + c += Prim.int64ToInt(Prim.floatToInt64(f)); + Prim.debugPrintInt(c); + f += Prim.int64ToFloat(Prim.intToInt64(c)); + Prim.debugPrint(debug_show(f)); + f += Prim.int64ToFloat(Prim.intToInt64(-c)); + Prim.debugPrint(debug_show(f)); + }; public func go() : () { a.incn(0); @@ -113,6 +125,7 @@ actor a { a.inci(42); a.inci(-42); a.incn(2**31 - 1); // highest compact + a.incfloat(42.0); }; }; a.go(); //OR-CALL ingress go "DIDL\x00\x00" diff --git a/test/run-drun/float.mo b/test/run-drun/float.mo new file mode 100644 index 00000000000..20b1daeb975 --- /dev/null +++ b/test/run-drun/float.mo @@ -0,0 +1,9 @@ +actor { + public query func foon(f : Float) : async Float { return f + 3.0; }; +} + +//CALL query foon 0x4449444c0001720000000000000840 + +//SKIP run +//SKIP run-ir +//SKIP run-low diff --git a/test/run-drun/ok/data-params.drun-run.ok b/test/run-drun/ok/data-params.drun-run.ok index 2c75785c8b9..fde2fbf7e30 100644 --- a/test/run-drun/ok/data-params.drun-run.ok +++ b/test/run-drun/ok/data-params.drun-run.ok @@ -40,4 +40,8 @@ debug.print: +2_148_489_869 debug.print: +2_148_489_911 debug.print: +2_148_489_869 debug.print: +4_295_973_516 +debug.print: 42.000000 +debug.print: +4_295_973_558 +debug.print: 4295973600.000000 +debug.print: 42.000000 ingress Completed: Canister: Payload: 0x4449444c0000 diff --git a/test/run-drun/ok/data-params.ic-ref-run.ok b/test/run-drun/ok/data-params.ic-ref-run.ok index caa3ab4372b..50c185c1245 100644 --- a/test/run-drun/ok/data-params.ic-ref-run.ok +++ b/test/run-drun/ok/data-params.ic-ref-run.ok @@ -44,4 +44,8 @@ debug.print: +2_148_489_869 debug.print: +2_148_489_911 debug.print: +2_148_489_869 debug.print: +4_295_973_516 +debug.print: 42.000000 +debug.print: +4_295_973_558 +debug.print: 4295973600.000000 +debug.print: 42.000000 ← completed: 0x4449444c0000 diff --git a/test/run-drun/ok/data-params.run-ir.ok b/test/run-drun/ok/data-params.run-ir.ok index 2fd43916bee..9be727d4d43 100644 --- a/test/run-drun/ok/data-params.run-ir.ok +++ b/test/run-drun/ok/data-params.run-ir.ok @@ -39,3 +39,7 @@ Foo2: +2_148_489_911 +2_148_489_869 +4_295_973_516 +42 ++4_295_973_558 +4_295_973_600 +42 diff --git a/test/run-drun/ok/data-params.run-low.ok b/test/run-drun/ok/data-params.run-low.ok index 2fd43916bee..9be727d4d43 100644 --- a/test/run-drun/ok/data-params.run-low.ok +++ b/test/run-drun/ok/data-params.run-low.ok @@ -39,3 +39,7 @@ Foo2: +2_148_489_911 +2_148_489_869 +4_295_973_516 +42 ++4_295_973_558 +4_295_973_600 +42 diff --git a/test/run-drun/ok/data-params.run.ok b/test/run-drun/ok/data-params.run.ok index 2fd43916bee..9be727d4d43 100644 --- a/test/run-drun/ok/data-params.run.ok +++ b/test/run-drun/ok/data-params.run.ok @@ -39,3 +39,7 @@ Foo2: +2_148_489_911 +2_148_489_869 +4_295_973_516 +42 ++4_295_973_558 +4_295_973_600 +42 diff --git a/test/run-drun/ok/float.drun-run.ok b/test/run-drun/ok/float.drun-run.ok new file mode 100644 index 00000000000..8349e123ec8 --- /dev/null +++ b/test/run-drun/ok/float.drun-run.ok @@ -0,0 +1,2 @@ +ingress System +Ok: Payload: 0x4449444c0001720000000000001840 diff --git a/test/run-drun/ok/float.ic-ref-run.ok b/test/run-drun/ok/float.ic-ref-run.ok new file mode 100644 index 00000000000..125abbc8227 --- /dev/null +++ b/test/run-drun/ok/float.ic-ref-run.ok @@ -0,0 +1,6 @@ +→ create +← completed: canister-id = ic:2a012b +→ install +← completed +→ query foon(0x4449444c0001720000000000000840) +← completed: 0x4449444c0001720000000000001840 diff --git a/test/run/float-ops.mo b/test/run/float-ops.mo new file mode 100644 index 00000000000..9f071ca28ce --- /dev/null +++ b/test/run/float-ops.mo @@ -0,0 +1,54 @@ +import Prim "mo:prim"; + +assert (Prim.floatAbs(9.7) == 9.7); +assert (Prim.floatAbs(-9.7) == 9.7); + +assert (Prim.floatSqrt(0.0) == 0.0); +assert (Prim.floatSqrt(25.0) == 5.0); + +assert (Prim.floatCeil(9.7) == 10.0); +assert (Prim.floatCeil(-9.7) == -9.0); + +assert (Prim.floatFloor(9.7) == 9.0); +assert (Prim.floatFloor(-9.7) == -10.0); + +assert (Prim.floatTrunc(9.7) == 9.0); +assert (Prim.floatTrunc(-9.7) == -9.0); + +assert (Prim.floatNearest(9.7) == 10.0); +assert (Prim.floatNearest(-9.7) == -10.0); +assert (Prim.floatNearest(9.4) == 9.0); +assert (Prim.floatNearest(-9.4) == -9.0); + +assert (Prim.floatMin(9.7, 4.2) == 4.2); +assert (Prim.floatMin(-9.7, 4.2) == -9.7); + +assert (Prim.floatMax(9.7, 4.2) == 9.7); +assert (Prim.floatMax(-9.7, 4.2) == 4.2); + +assert (Prim.floatCopySign(-9.7, 4.2) == 9.7); +assert (Prim.floatCopySign(9.7, -4.2) == -9.7); + +assert (-9.7 < 4.2); +assert (-9.7 <= -9.7); +assert (-9.7 <= 4.2); + +assert (-9.7 >= -9.7); +assert (9.7 >= -4.2); +assert (9.7 > -4.2); + +assert (-9.7 != 4.2); + +// Trigonometric +let pi = 3.141592653589793238; +assert (Prim.sin(0.0) == 0.0); +assert (Prim.sin(pi / 2.0) == 1.0); +assert (Prim.cos(0.0) == 1.0); +assert (Prim.cos(pi) == -1.0); + +// Conversions +assert (Prim.floatToInt64(pi) == (3 : Int64)); +assert (Prim.floatToInt64(-pi) == (-3 : Int64)); + +assert (Prim.int64ToFloat(42) == 42.0); +assert (Prim.int64ToFloat(-42) == -42.0); diff --git a/test/run/numeric-ops.mo b/test/run/numeric-ops.mo index f27728f856f..cc1babaf85e 100644 --- a/test/run/numeric-ops.mo +++ b/test/run/numeric-ops.mo @@ -143,8 +143,7 @@ func testFloat(a : Float, b : Float) : [Float] { [pos1, pos2, neg1, neg2, sum1, sum2, diff1, diff2, prod1, prod2, rat1, rat2, pow1, pow2] }; -// no Floats yet -// verify([3, -3, 8, -2, 15, 0, 3, 243], testFloat(3.0, 5.0), func (a : Float, b : Float) : Bool = a == b); +verify([3, -3, 8, -2, 15, 0.6, 243.0], testFloat(3.0, 5.0), func (a : Float, b : Float) : Bool = a == b); func testWord8(a : Word8, b : Word8) : [Word8] { let pos1 = + a; diff --git a/test/run/ok/issue36.comp.ok b/test/run/ok/issue36.comp.ok deleted file mode 100644 index de1fadfdc43..00000000000 --- a/test/run/ok/issue36.comp.ok +++ /dev/null @@ -1,5 +0,0 @@ -compile_lit: (FloatLit 1) -compile_lit: (FloatLit 1.7) -compile_lit: (FloatLit 0.000_180_000_000_000_000_01) -compile_lit: (FloatLit 1_604) -compile_lit: (FloatLit 802.156_25) diff --git a/test/run/ok/issue36.wasm-run.ok b/test/run/ok/issue36.wasm-run.ok deleted file mode 100644 index eb44a3c30de..00000000000 --- a/test/run/ok/issue36.wasm-run.ok +++ /dev/null @@ -1,7 +0,0 @@ -TODO: compile_lit - -Error: failed to process main module `_out/issue36.wasm` - -Caused by: - 0: Instantiation failed during setup - 1: Trap occurred while invoking start function: wasm trap: unreachable, source location: @___: diff --git a/test/run/ok/issue36.wasm-run.ret.ok b/test/run/ok/issue36.wasm-run.ret.ok deleted file mode 100644 index 69becfa16f9..00000000000 --- a/test/run/ok/issue36.wasm-run.ret.ok +++ /dev/null @@ -1 +0,0 @@ -Return code 1 diff --git a/test/run/ok/numeric-ops.comp.ok b/test/run/ok/numeric-ops.comp.ok deleted file mode 100644 index f67e889e82d..00000000000 --- a/test/run/ok/numeric-ops.comp.ok +++ /dev/null @@ -1,32 +0,0 @@ -compile_unop: NegOp -compile_unop: NegOp -compile_binop: AddOp -StackRep.of_type: Float -StackRep.of_type: Float -compile_binop: AddOp -StackRep.of_type: Float -StackRep.of_type: Float -compile_binop: SubOp -StackRep.of_type: Float -StackRep.of_type: Float -compile_binop: SubOp -StackRep.of_type: Float -StackRep.of_type: Float -compile_binop: MulOp -StackRep.of_type: Float -StackRep.of_type: Float -compile_binop: MulOp -StackRep.of_type: Float -StackRep.of_type: Float -compile_binop: DivOp -StackRep.of_type: Float -StackRep.of_type: Float -compile_binop: DivOp -StackRep.of_type: Float -StackRep.of_type: Float -compile_binop: PowOp -StackRep.of_type: Float -StackRep.of_type: Float -compile_binop: PowOp -StackRep.of_type: Float -StackRep.of_type: Float diff --git a/test/run/ok/relational-ops.comp.ok b/test/run/ok/relational-ops.comp.ok deleted file mode 100644 index b39f05dc93b..00000000000 --- a/test/run/ok/relational-ops.comp.ok +++ /dev/null @@ -1,24 +0,0 @@ -compile_eq: EqOp -StackRep.of_type: Float -compile_eq: EqOp -StackRep.of_type: Float -compile_eq: EqOp -StackRep.of_type: Float -compile_eq: EqOp -StackRep.of_type: Float -compile_relop: LtOp -StackRep.of_type: Float -compile_relop: LtOp -StackRep.of_type: Float -compile_relop: LeOp -StackRep.of_type: Float -compile_relop: LeOp -StackRep.of_type: Float -compile_relop: GtOp -StackRep.of_type: Float -compile_relop: GtOp -StackRep.of_type: Float -compile_relop: GeOp -StackRep.of_type: Float -compile_relop: GeOp -StackRep.of_type: Float diff --git a/test/run/ok/type-inference.comp.ok b/test/run/ok/type-inference.comp.ok deleted file mode 100644 index a955962091b..00000000000 --- a/test/run/ok/type-inference.comp.ok +++ /dev/null @@ -1 +0,0 @@ -compile_lit: (FloatLit 5.099_999_999_999_999_6) From b4ae803f92c8ec791015dbd53b15c2a3c0463e3c Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Tue, 7 Apr 2020 23:22:49 +0200 Subject: [PATCH 1165/1176] refactor: share prelude definitions (#1349) * share definitions of all conversions which start with @ this saves us 12 functions in the prelude * don't use destructuring it pessimizes --- src/prelude/prelude.ml | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/prelude/prelude.ml b/src/prelude/prelude.ml index 6afb8c3858e..dedf9c36d68 100644 --- a/src/prelude/prelude.ml +++ b/src/prelude/prelude.ml @@ -354,58 +354,58 @@ func hashBlob(b : Blob) : Word32 { (prim "crc32Hash" : Blob -> Word32) b }; // Conversions -func int64ToInt(n : Int64) : Int = (prim "num_conv_Int64_Int" : Int64 -> Int) n; +let int64ToInt = @int64ToInt; +let int32ToInt = @int32ToInt; +let int16ToInt = @int16ToInt; +let int8ToInt = @int8ToInt; +let nat64ToNat = @nat64ToNat; +let nat32ToNat = @nat32ToNat; +let nat16ToNat = @nat16ToNat; +let nat8ToNat = @nat8ToNat; +let word64ToNat = @word64ToNat; +let word32ToNat = @word32ToNat; +let word16ToNat = @word16ToNat; +let word8ToNat = @word8ToNat; + func intToInt64(n : Int) : Int64 = (prim "num_conv_Int_Int64" : Int -> Int64) n; func int64ToWord64(n : Int64) : Word64 = (prim "num_conv_Int64_Word64" : Int64 -> Word64) n; func word64ToInt64(n : Word64) : Int64 = (prim "num_conv_Word64_Int64" : Word64 -> Int64) n; -func int32ToInt(n : Int32) : Int = (prim "num_conv_Int32_Int" : Int32 -> Int) n; func intToInt32(n : Int) : Int32 = (prim "num_conv_Int_Int32" : Int -> Int32) n; func int32ToWord32(n : Int32) : Word32 = (prim "num_conv_Int32_Word32" : Int32 -> Word32) n; func word32ToInt32(n : Word32) : Int32 = (prim "num_conv_Word32_Int32" : Word32 -> Int32) n; -func int16ToInt(n : Int16) : Int = (prim "num_conv_Int16_Int" : Int16 -> Int) n; func intToInt16(n : Int) : Int16 = (prim "num_conv_Int_Int16" : Int -> Int16) n; func int16ToWord16(n : Int16) : Word16 = (prim "num_conv_Int16_Word16" : Int16 -> Word16) n; func word16ToInt16(n : Word16) : Int16 = (prim "num_conv_Word16_Int16" : Word16 -> Int16) n; -func int8ToInt(n : Int8) : Int = (prim "num_conv_Int8_Int" : Int8 -> Int) n; func intToInt8(n : Int) : Int8 = (prim "num_conv_Int_Int8" : Int -> Int8) n; func int8ToWord8(n : Int8) : Word8 = (prim "num_conv_Int8_Word8" : Int8 -> Word8) n; func word8ToInt8(n : Word8) : Int8 = (prim "num_conv_Word8_Int8" : Word8 -> Int8) n; -func nat64ToNat(n : Nat64) : Nat = (prim "num_conv_Nat64_Nat" : Nat64 -> Nat) n; func natToNat64(n : Nat) : Nat64 = (prim "num_conv_Nat_Nat64" : Nat -> Nat64) n; func nat64ToWord64(n : Nat64) : Word64 = (prim "num_conv_Nat64_Word64" : Nat64 -> Word64) n; func word64ToNat64(n : Word64) : Nat64 = (prim "num_conv_Word64_Nat64" : Word64 -> Nat64) n; -func nat32ToNat(n : Nat32) : Nat = (prim "num_conv_Nat32_Nat" : Nat32 -> Nat) n; func natToNat32(n : Nat) : Nat32 = (prim "num_conv_Nat_Nat32" : Nat -> Nat32) n; func nat32ToWord32(n : Nat32) : Word32 = (prim "num_conv_Nat32_Word32" : Nat32 -> Word32) n; func word32ToNat32(n : Word32) : Nat32 = (prim "num_conv_Word32_Nat32" : Word32 -> Nat32) n; -func nat16ToNat(n : Nat16) : Nat = (prim "num_conv_Nat16_Nat" : Nat16 -> Nat) n; func natToNat16(n : Nat) : Nat16 = (prim "num_conv_Nat_Nat16" : Nat -> Nat16) n; func nat16ToWord16(n : Nat16) : Word16 = (prim "num_conv_Nat16_Word16" : Nat16 -> Word16) n; func word16ToNat16(n : Word16) : Nat16 = (prim "num_conv_Word16_Nat16" : Word16 -> Nat16) n; -func nat8ToNat(n : Nat8) : Nat = (prim "num_conv_Nat8_Nat" : Nat8 -> Nat) n; func natToNat8(n : Nat) : Nat8 = (prim "num_conv_Nat_Nat8" : Nat -> Nat8) n; func nat8ToWord8(n : Nat8) : Word8 = (prim "num_conv_Nat8_Word8" : Nat8 -> Word8) n; func word8ToNat8(n : Word8) : Nat8 = (prim "num_conv_Word8_Nat8" : Word8 -> Nat8) n; - func natToWord8(n : Nat) : Word8 = (prim "num_conv_Nat_Word8" : Nat -> Word8) n; -func word8ToNat(n : Word8) : Nat = (prim "num_conv_Word8_Nat" : Word8 -> Nat) n; func intToWord8(n : Int) : Word8 = (prim "num_conv_Int_Word8" : Int -> Word8) n; func word8ToInt(n : Word8) : Int = (prim "num_conv_Word8_Int" : Word8 -> Int) n; func natToWord16(n : Nat) : Word16 = (prim "num_conv_Nat_Word16" : Nat -> Word16) n; -func word16ToNat(n : Word16) : Nat = (prim "num_conv_Word16_Nat" : Word16 -> Nat) n; func intToWord16(n : Int) : Word16 = (prim "num_conv_Int_Word16" : Int -> Word16) n; func word16ToInt(n : Word16) : Int = (prim "num_conv_Word16_Int" : Word16 -> Int) n; func natToWord32(n : Nat) : Word32 = (prim "num_conv_Nat_Word32" : Nat -> Word32) n; -func word32ToNat(n : Word32) : Nat = (prim "num_conv_Word32_Nat" : Word32 -> Nat) n; func intToWord32(n : Int) : Word32 = (prim "num_conv_Int_Word32" : Int -> Word32) n; func word32ToInt(n : Word32) : Int = (prim "num_conv_Word32_Int" : Word32 -> Int) n; func natToWord64(n : Nat) : Word64 = (prim "num_conv_Nat_Word64" : Nat -> Word64) n; -func word64ToNat(n : Word64) : Nat = (prim "num_conv_Word64_Nat" : Word64 -> Nat) n; func intToWord64(n : Int) : Word64 = (prim "num_conv_Int_Word64" : Int -> Word64) n; func word64ToInt(n : Word64) : Int = (prim "num_conv_Word64_Int" : Word64 -> Int) n; From c219df4a22d87c163399d5887d828fb3010eaa54 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 8 Apr 2020 00:08:41 +0200 Subject: [PATCH 1166/1176] default.nix: Slightly more idiomatic `musl-wasi-sysroot` (#1350) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit and don’t make it its won CI job (follow-up to #1316) --- default.nix | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/default.nix b/default.nix index a3e9cacbd55..57155323648 100644 --- a/default.nix +++ b/default.nix @@ -102,19 +102,18 @@ let ocaml_exe = name: bin: if nixpkgs.stdenv.isDarwin then darwin_standalone { inherit drv; usePackager = false; exename = bin; } else drv; -in -rec { musl-wasi-sysroot = stdenv.mkDerivation { name = "musl-wasi-sysroot"; - buildInputs = [ nixpkgs.sources.musl-wasi ]; - phases = [ "installPhase" ]; + src = nixpkgs.sources.musl-wasi; + phases = [ "unpackPhase" "installPhase" ]; installPhase = '' - cp --no-preserve=mode ${nixpkgs.sources.musl-wasi}/Makefile ./mk - substituteInPlace ./mk --replace "cp -r" "cp --no-preserve=mode -r" - make --makefile=$(pwd)/mk -C ${nixpkgs.sources.musl-wasi} SYSROOT="$out" include_dirs + make SYSROOT="$out" include_dirs ''; }; +in + +rec { rts = stdenv.mkDerivation { name = "moc-rts"; From 396ff25d3ad483eb82638769d1e81f79bc20f506 Mon Sep 17 00:00:00 2001 From: Matthew Hammer Date: Tue, 7 Apr 2020 16:17:55 -0600 Subject: [PATCH 1167/1176] Float module, initial draft (#1351) * Float module, initial draft * fix build and tests --- stdlib/doc/index.adoc | 1 + stdlib/src/Float.mo | 28 +++++++++++++++ stdlib/test/floatTest.mo | 74 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 103 insertions(+) create mode 100644 stdlib/src/Float.mo create mode 100644 stdlib/test/floatTest.mo diff --git a/stdlib/doc/index.adoc b/stdlib/doc/index.adoc index 87891ab6b03..7fc4765e065 100644 --- a/stdlib/doc/index.adoc +++ b/stdlib/doc/index.adoc @@ -22,6 +22,7 @@ include::Nat.adoc[leveloffset=+1] include::Int.adoc[leveloffset=+1] include::Char.adoc[leveloffset=+1] include::Text.adoc[leveloffset=+1] +include::Float.adoc[leveloffset=+1] include::None.adoc[leveloffset=+1] include::Option.adoc[leveloffset=+1] include::Function.adoc[leveloffset=+1] diff --git a/stdlib/src/Float.mo b/stdlib/src/Float.mo new file mode 100644 index 00000000000..7cc91e65fdf --- /dev/null +++ b/stdlib/src/Float.mo @@ -0,0 +1,28 @@ +/** +[#mod-Float] += `Float` -- Floating-point numbers +*/ + +import Prim "mo:prim"; +import Prelude "Prelude"; + +module { + + public let abs : Float -> Float = Prim.floatAbs; + public let sqrt : Float -> Float = Prim.floatSqrt; + + public let ceil : Float -> Float = Prim.floatCeil; + public let floor : Float -> Float = Prim.floatFloor; + public let trunc : Float -> Float = Prim.floatTrunc; + public let nearest : Float -> Float = Prim.floatNearest; + + public let min : (Float, Float) -> Float = Prim.floatMin; + public let max : (Float, Float) -> Float = Prim.floatMax; + + public let sin : Float -> Float = Prim.sin; + public let cos : Float -> Float = Prim.cos; + + public let toInt64 : Float -> Int64 = Prim.floatToInt64; + public let ofInt64 : Int64 -> Float = Prim.int64ToFloat; + +}; diff --git a/stdlib/test/floatTest.mo b/stdlib/test/floatTest.mo new file mode 100644 index 00000000000..04ad55f0499 --- /dev/null +++ b/stdlib/test/floatTest.mo @@ -0,0 +1,74 @@ +import Prelude "mo:stdlib/Prelude"; +import Float "mo:stdlib/Float"; + +Prelude.printLn("Float"); + +{ + Prelude.printLn(" abs"); + + assert(Float.abs(1.1) == 1.1); + assert(Float.abs(-1.1) == 1.1); +}; + +{ + Prelude.printLn(" ceil"); + + assert(Float.ceil(1.1) == 2.0); +}; + +{ + Prelude.printLn(" floor"); + + assert(Float.floor(1.1) == 1.0); +}; + +{ + Prelude.printLn(" trunc"); + + assert(Float.trunc(1.0012345789) == 1.0); +}; + +{ + Prelude.printLn(" nearest"); + + assert(Float.nearest(1.00001) == 1.0); + assert(Float.nearest(1.99999) == 2.0); +}; + +{ + Prelude.printLn(" min"); + + assert(Float.min(1.1, 2.2) == 1.1); +}; + +{ + Prelude.printLn(" max"); + + assert(Float.max(1.1, 2.2) == 2.2); +}; + +{ + Prelude.printLn(" sin"); + + assert(Float.sin(0.0) == 0.0); +}; + +{ + Prelude.printLn(" cos"); + + assert(Float.cos(0.0) == 1.0); +}; + +{ + Prelude.printLn(" toFloat64"); + + assert(Float.toInt64(1e10) == (10000000000 : Int64)); + assert(Float.toInt64(-1e10) == (-10000000000 : Int64)); +}; + +{ + Prelude.printLn(" ofFloat64"); + + assert(Float.ofInt64(10000000000) == 1e10); + assert(Float.ofInt64(-10000000000) == -1e10); +}; From 652409eb5aae64aeabb00c0edfef880ac42ce502 Mon Sep 17 00:00:00 2001 From: DFINITY bot <58022693+dfinity-bot@users.noreply.github.com> Date: Wed, 8 Apr 2020 09:51:41 +0200 Subject: [PATCH 1168/1176] niv musl-wasi: update 4b41c5d5 -> 86550c37 (#1352) ## Changelog for musl-wasi: Commits: [WebAssembly/wasi-libc@4b41c5d5...86550c37](https://github.com/WebAssembly/wasi-libc/compare/4b41c5d5ec64f1219e57e474c027d8552c1503ff...86550c37ab14962233f73413ea0e0c0e57d056d7) * [`fcbf8f40`](https://github.com/WebAssembly/wasi-libc/commit/fcbf8f40ea02a0565b805f2fe40d488e471776b2) wasi submodule: point to latest (witx 0.8.5 release) * [`e2bdce89`](https://github.com/WebAssembly/wasi-libc/commit/e2bdce89eaba2835320dd1e30551f70c7f05ebb4) gen-headers: make handle output consistient with prior * [`156fdc47`](https://github.com/WebAssembly/wasi-libc/commit/156fdc476aa4c15ce335026dbde081491561d2e4) regenerate api.h * [`7b92f334`](https://github.com/WebAssembly/wasi-libc/commit/7b92f334e69c60a1d1c5d3e289790d790b9a185b) Added utime.h (WebAssembly/wasi-libc#188) * [`ee272670`](https://github.com/WebAssembly/wasi-libc/commit/ee2726700cbdfd29c0c3642f07130ab43e1128b5) github ci: download llvm over https, add -L flag to curl * [`1792d02a`](https://github.com/WebAssembly/wasi-libc/commit/1792d02ac94c6c18f28ef38704c8d957f37fb879) debug * [`86550c37`](https://github.com/WebAssembly/wasi-libc/commit/86550c37ab14962233f73413ea0e0c0e57d056d7) CI: use llvm 10.0.0 release (WebAssembly/wasi-libc#194) --- nix/sources.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nix/sources.json b/nix/sources.json index dca731eefc4..5daee40bc49 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -44,10 +44,10 @@ "homepage": "https://wasi.dev", "owner": "WebAssembly", "repo": "wasi-libc", - "rev": "4b41c5d5ec64f1219e57e474c027d8552c1503ff", - "sha256": "17wlkpl495zs4cl3djdqaf089a4bhbrj87z2i2gm21cvmfqmva7p", + "rev": "86550c37ab14962233f73413ea0e0c0e57d056d7", + "sha256": "16qbfkvsz8ks73r1jmwy0q8dshzmbj6cc72zvb7krin0dhmb5krf", "type": "tarball", - "url": "https://github.com/WebAssembly/wasi-libc/archive/4b41c5d5ec64f1219e57e474c027d8552c1503ff.tar.gz", + "url": "https://github.com/WebAssembly/wasi-libc/archive/86550c37ab14962233f73413ea0e0c0e57d056d7.tar.gz", "url_template": "https://github.com///archive/.tar.gz" }, "nixpkgs": { From 485804cdc924623ed6bc8e320983597e2bd52f80 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Wed, 8 Apr 2020 09:55:31 +0200 Subject: [PATCH 1169/1176] niv-updater: blacklist musl-wasi for now (#1354) Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- .github/workflows/niv-updater.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/niv-updater.yml b/.github/workflows/niv-updater.yml index 84b4735ebc1..7b958f6b3cb 100644 --- a/.github/workflows/niv-updater.yml +++ b/.github/workflows/niv-updater.yml @@ -22,7 +22,7 @@ jobs: uses: knl/niv-updater-action@v5 with: # might be too noisy - blacklist: 'nixpkgs,dfinity,ic-ref' + blacklist: 'nixpkgs,dfinity,ic-ref,musl-wasi' labels: | automerge-squash env: From 56f626e04267238b26efa9a72511d0c23a3e20f5 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Wed, 8 Apr 2020 11:23:20 +0200 Subject: [PATCH 1170/1176] publish floatToText as a primitive (#1355) --- src/prelude/prelude.ml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/prelude/prelude.ml b/src/prelude/prelude.ml index dedf9c36d68..604a73c2890 100644 --- a/src/prelude/prelude.ml +++ b/src/prelude/prelude.ml @@ -449,6 +449,8 @@ func floatCopySign(f : Float, g : Float) : Float = (prim "fcopysign" : (Float, F func floatToInt64(f : Float) : Int64 = (prim "num_conv_Float_Int64" : Float -> Int64) (f); func int64ToFloat(n : Int64) : Float = (prim "num_conv_Int64_Float" : Int64 -> Float) (n); +let floatToText = @text_of_Float; + // Trigonometric functions func sin(f : Float) : Float = (prim "fsin" : Float -> Float) f; From fcfce39b8b807fc2c1678556d7285bf1337340f0 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 8 Apr 2020 14:38:48 +0200 Subject: [PATCH 1171/1176] Test case: static-call-from-pub (#1346) Another test case that highlights a regression in #1336 --- .../run-drun/ok/static-call-from-pub.drun-run.ok | 1 + .../ok/static-call-from-pub.ic-ref-run.ok | 4 ++++ test/run-drun/static-call-from-pub.mo | 16 ++++++++++++++++ 3 files changed, 21 insertions(+) create mode 100644 test/run-drun/ok/static-call-from-pub.drun-run.ok create mode 100644 test/run-drun/ok/static-call-from-pub.ic-ref-run.ok create mode 100644 test/run-drun/static-call-from-pub.mo diff --git a/test/run-drun/ok/static-call-from-pub.drun-run.ok b/test/run-drun/ok/static-call-from-pub.drun-run.ok new file mode 100644 index 00000000000..5d7495cc8a5 --- /dev/null +++ b/test/run-drun/ok/static-call-from-pub.drun-run.ok @@ -0,0 +1 @@ +ingress System diff --git a/test/run-drun/ok/static-call-from-pub.ic-ref-run.ok b/test/run-drun/ok/static-call-from-pub.ic-ref-run.ok new file mode 100644 index 00000000000..0eb57fac0d6 --- /dev/null +++ b/test/run-drun/ok/static-call-from-pub.ic-ref-run.ok @@ -0,0 +1,4 @@ +→ create +← completed: canister-id = ic:2a012b +→ install +← completed diff --git a/test/run-drun/static-call-from-pub.mo b/test/run-drun/static-call-from-pub.mo new file mode 100644 index 00000000000..ba5b38b6095 --- /dev/null +++ b/test/run-drun/static-call-from-pub.mo @@ -0,0 +1,16 @@ +actor { + func init() {}; + public func reset() { + init() + }; +}; + +// annoying administrative regexes introduced by our passes + +// CHECK-LABEL: (func $reset (type +// CHECK-NOT: call_indirect +// CHECK: call $$lambda + +// CHECK-LABEL: (func $$lambda +// CHECK-NOT: call_indirect +// CHECK: call $init From e40f4e92900f950590a61da9fc7a8004c2921170 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 8 Apr 2020 15:01:05 +0200 Subject: [PATCH 1172/1176] Const: Ignore top-level-bound free variables for FuncE (#1348) the analysis was not precise enough: a `FuncE` is constant if every free variable is either * constant (duh) * or top-level bound Rationale: To compile a function statically (without a closure) we just need to know the _location_ of its free variables, but not their values. And for all top-level things we will know where they end up. With this change, actually _using_ the information (#1336) will produce identical code as before, so hopefully this means that have not regressed in any way. --- src/ir_def/check_ir.ml | 38 +++++++++++++++++++---------- src/ir_passes/const.ml | 55 +++++++++++++++++++++++++++--------------- 2 files changed, 60 insertions(+), 33 deletions(-) diff --git a/src/ir_def/check_ir.ml b/src/ir_def/check_ir.ml index 88acf6de3b9..faec260a0b4 100644 --- a/src/ir_def/check_ir.ml +++ b/src/ir_def/check_ir.ml @@ -28,7 +28,11 @@ let immute_typ p = (* Scope *) -type val_info = { typ : T.typ; const : bool } +type val_info = { + typ : T.typ; + loc_known : bool; + const : bool; +} type val_env = val_info T.Env.t type scope = @@ -65,7 +69,7 @@ type env = let env_of_scope scope flavor : env = { flavor; lvl = TopLvl; - vals = T.Env.map (fun typ -> { typ; const = true }) scope.Scope.val_env; + vals = T.Env.map (fun typ -> { typ; loc_known = true; const = true }) scope.Scope.val_env; cons = T.ConSet.empty; labs = T.Env.empty; rets = None; @@ -339,7 +343,7 @@ let rec check_exp env (exp:Ir.exp) : unit = (* check typing *) begin match exp.it with | VarE id -> - let { typ; const } = + let { typ; loc_known; const } = try T.Env.find id env.vals with Not_found -> error env exp.at "unbound variable %s" id in @@ -587,7 +591,8 @@ let rec check_exp env (exp:Ir.exp) : unit = T.Async (t0, t1') <: t | DeclareE (id, t0, exp1) -> check_typ env t0; - let env' = adjoin_vals env (T.Env.singleton id { typ = t0; const = false }) in + let val_info = { typ = t0; loc_known = false; const = false } in + let env' = adjoin_vals env (T.Env.singleton id val_info) in check_exp env' exp1; (typ exp1) <: t | DefineE (id, mut, exp1) -> @@ -595,7 +600,7 @@ let rec check_exp env (exp:Ir.exp) : unit = begin match T.Env.find_opt id env.vals with | None -> error env exp.at "unbound variable %s" id - | Some { typ = t0; const } -> + | Some { typ = t0; const; loc_known } -> check (not const) "cannot use DefineE on const variable"; match mut with | Const -> @@ -671,7 +676,10 @@ let rec check_exp env (exp:Ir.exp) : unit = | VarE id -> check_var "VarE" id | FuncE (x, s, c, tp, as_ , ts, body) -> if env.lvl = NotTopLvl then - Freevars.M.iter (fun v _ -> check_var "FuncE" v) (Freevars.exp exp) + Freevars.M.iter (fun v _ -> + if (T.Env.find v env.vals).loc_known then () else + check_var "FuncE" v + ) (Freevars.exp exp) | NewObjE (Type.(Object | Module), fs, t) when T.is_immutable_obj t -> List.iter (fun f -> check_var "NewObjE" f.it.var) fs | PrimE (DotPrim n, [e1]) -> @@ -699,7 +707,7 @@ and check_lexp env (lexp:Ir.lexp) : unit = (* check typing *) match lexp.it with | VarLE id -> - let { typ = t0; const } = + let { typ = t0; const; loc_known } = try T.Env.find id env.vals with Not_found -> error env lexp.at "unbound variable %s" id in @@ -750,7 +758,9 @@ and check_args env args = check env a.at (not (T.Env.mem a.it ve)) "duplicate binding for %s in argument list" a.it; check_typ env a.note; - go (T.Env.add a.it {typ = a.note; const = false} ve) as_ + let val_info = {typ = a.note; const = false; loc_known = false} in + let env' = T.Env.add a.it val_info ve in + go env' as_ in go T.Env.empty args (* Patterns *) @@ -764,7 +774,8 @@ and gather_pat env ve0 pat : val_env = | VarP id -> check env pat.at (not (T.Env.mem id ve0)) "duplicate binding for %s in block" id; - T.Env.add id {typ = pat.note; const = false} ve (*TBR*) + let val_info = {typ = pat.note; const = false; loc_known = env.lvl = TopLvl} in + T.Env.add id val_info ve (*TBR*) | TupP pats -> List.fold_left go ve pats | ObjP pfs -> @@ -787,7 +798,7 @@ and check_pat env pat : val_env = let t = pat.note in match pat.it with | WildP -> T.Env.empty - | VarP id -> T.Env.singleton id { typ = pat.note; const = false } + | VarP id -> T.Env.singleton id { typ = pat.note; const = false; loc_known = env.lvl = TopLvl } | LitP NullLit -> t <: T.Opt T.Any; T.Env.empty @@ -856,7 +867,7 @@ and type_exp_fields env s fs : T.field list = and type_exp_field env s f : T.field = let {name; var} = f.it in - let { typ = t; const } = + let { typ = t; const; loc_known } = try T.Env.find var env.vals with Not_found -> error env f.at "field typing for %s not found" name in @@ -918,8 +929,9 @@ and gather_dec env scope dec : scope = check env dec.at (not (T.Env.mem id scope.val_env)) "duplicate variable definition in block"; - let ve = T.Env.add id {typ = T.Mut t; const = false} scope.val_env in - { val_env = ve} + let val_info = {typ = T.Mut t; const = false; loc_known = env.lvl = TopLvl} in + let ve = T.Env.add id val_info scope.val_env in + { val_env = ve } (* Programs *) diff --git a/src/ir_passes/const.ml b/src/ir_passes/const.ml index 18d543b8852..91cb3561cf8 100644 --- a/src/ir_passes/const.ml +++ b/src/ir_passes/const.ml @@ -76,15 +76,21 @@ module S = Freevars.S module M = Env.Make(String) -type env = lazy_bool M.t +type info = { + loc_known : bool; + const : lazy_bool; +} +type env = info M.t -let arg env a = M.add a.it surely_false env + +let no_info = { loc_known = false; const = surely_false } +let arg env a = M.add a.it no_info env let args env as_ = List.fold_left arg env as_ let rec pat env p = match p.it with | WildP | LitP _ -> env - | VarP id -> M.add id surely_false env + | VarP id -> M.add id no_info env | TupP pats -> List.fold_left pat env pats | ObjP pfs -> List.fold_left pat env (pats_of_obj_pat pfs) | AltP (pat1, _) | OptP pat1 | TagP (_, pat1) -> pat env pat1 @@ -106,22 +112,26 @@ let set_lazy_const e lb = (* Traversals *) -let rec exp lvl env e : lazy_bool = +let rec exp lvl (env : env) e : lazy_bool = let lb = match e.it with - | VarE v -> find v env + | VarE v -> (find v env).const | FuncE (x, s, c, tp, as_ , ts, body) -> exp_ NotTopLvl (args env as_) body; begin match lvl with - | TopLvl -> surely_true (* top-level functions can always be static *) + | TopLvl -> surely_true (* top-level functions can always be const *) | NotTopLvl -> let lb = maybe_false () in - Freevars.M.iter (fun v _ -> required_for (find v env) lb) (Freevars.exp e); + Freevars.M.iter (fun v _ -> + let info = find v env in + if info.loc_known then () else (* static definitions are ok *) + required_for info.const lb + ) (Freevars.exp e); lb end | NewObjE (Type.(Object | Module), fs, t) when Type.is_immutable_obj t -> let lb = maybe_false () in - List.iter (fun f -> required_for (find f.it.var env) lb) fs; + List.iter (fun f -> required_for (find f.it.var env).const lb) fs; lb | BlockE (ds, body) -> block lvl env (ds, body) @@ -135,7 +145,7 @@ let rec exp lvl env e : lazy_bool = | LitE _ -> surely_false | DeclareE (id, _, e1) -> - exp_ lvl (M.add id surely_false env) e1; + exp_ lvl (M.add id no_info env) e1; surely_false | LoopE e1 | AsyncE (_, e1, _) -> exp_ NotTopLvl env e1; @@ -159,8 +169,9 @@ let rec exp lvl env e : lazy_bool = surely_false | NewObjE _ -> (* mutable objects *) surely_false - | ActorE _ -> - (* no point in traversing until the backend supports dynamic actors *) + | ActorE (ds, fs, _typ) -> + (* this may well be “the” top-level actor, so don’t update lvl here *) + ignore (decs lvl env ds); surely_false in set_lazy_const e lb; @@ -170,19 +181,22 @@ and exp_ lvl env e : unit = ignore (exp lvl env e) and case_ lvl env c : unit = exp_ lvl (pat env c.it.pat) c.it.exp -and gather_dec scope dec : env = match dec.it with - | LetD ({it = VarP v; _}, e) -> M.add v (maybe_false ()) scope +and gather_dec lvl scope dec : env = + let mk_info const = { loc_known = lvl = TopLvl; const } in + match dec.it with + | LetD ({it = VarP v; _}, e) -> + M.add v (mk_info (maybe_false ())) scope | _ -> let vs = snd (Freevars.dec dec) in (* TODO: implement gather_dec more directly *) - S.fold (fun v scope -> M.add v surely_false scope) vs scope + S.fold (fun v scope -> M.add v (mk_info surely_false) scope) vs scope -and gather_decs ds : env = - List.fold_left gather_dec M.empty ds +and gather_decs lvl ds : env = + List.fold_left (gather_dec lvl) M.empty ds and check_dec lvl env dec : lazy_bool = match dec.it with | LetD ({it = VarP v; _}, e) -> let lb = exp lvl env e in - required_for lb (M.find v env); + required_for lb (M.find v env).const; lb | LetD (_, e) | VarD (_, _, e) -> exp_ lvl env e; @@ -193,7 +207,7 @@ and check_decs lvl env ds : lazy_bool = all lbs and decs lvl env ds : (env * lazy_bool) = - let scope = gather_decs ds in + let scope = gather_decs lvl ds in let env' = M.adjoin env scope in let could_be = check_decs lvl env' ds in (env', could_be) @@ -206,7 +220,8 @@ and block lvl env (ds, body) = let analyze scope ((b, _flavor) : prog) = (* We assume everything in scope is static. Right now, this is only the prelude, - which is static. It will blow up in compile if we break this. + which is static. It will blow up in compile if we get this wrong. *) - let env = M.of_seq (Seq.map (fun (v, _typ) -> (v, surely_true)) (Type.Env.to_seq scope.Scope.val_env)) in + let static_info = { loc_known = true; const = surely_true } in + let env = M.of_seq (Seq.map (fun (v, _typ) -> (v, static_info)) (Type.Env.to_seq scope.Scope.val_env)) in ignore (block TopLvl env b) From cf02ea7ef78dc9666e1221dc904e6c31be64e32f Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 8 Apr 2020 15:53:36 +0200 Subject: [PATCH 1173/1176] Compile: Make use of the const flag (#1336) and get rid of the internal analysis for constness. --- src/codegen/compile.ml | 51 +++++++----------------------------------- 1 file changed, 8 insertions(+), 43 deletions(-) diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index b4651cdabc2..57098a716c3 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -2480,10 +2480,6 @@ module Object = struct let _, fields = Type.as_obj_sub [s] obj_type in Type.is_mut (Type.lookup_val_field s fields) - let is_immutable obj_type = - let _, fields = Type.as_obj_sub [] obj_type in - List.for_all (fun f -> not (Type.is_mut f.Type.typ)) fields - let idx env obj_type name = compile_unboxed_const (Mo_types.Hash.hash name) ^^ idx_hash env (is_mut_field env obj_type name) @@ -4630,7 +4626,7 @@ module StackRep = struct | UnboxedFloat64 -> "UnboxedFloat64" | UnboxedTuple n -> Printf.sprintf "UnboxedTuple %d" n | Unreachable -> "Unreachable" - | Const _ -> "StaticThing" + | Const _ -> "Const" let join (sr1 : t) (sr2 : t) = match sr1, sr2 with | _, _ when sr1 = sr2 -> sr1 @@ -4641,6 +4637,8 @@ module StackRep = struct | _, Vanilla -> Vanilla | Vanilla, _ -> Vanilla | Const _, Const _ -> Vanilla + | Const _, UnboxedTuple 0 -> UnboxedTuple 0 + | UnboxedTuple 0, Const _-> UnboxedTuple 0 | _, _ -> Printf.eprintf "Invalid stack rep join (%s, %s)\n" (to_string sr1) (to_string sr2); sr1 @@ -5327,7 +5325,6 @@ module AllocHow = struct let map_of_set = Freevars.map_of_set let set_of_map = Freevars.set_of_map - let disjoint s1 s2 = S.is_empty (S.inter s1 s2) (* Various filters used in the set operations below *) let is_local_mut _ = function @@ -5339,15 +5336,6 @@ module AllocHow = struct | LocalMut -> true | _ -> false - let is_not_const _ : how -> bool = function - | Const -> false - | _ -> true - - let require_closure _ : how -> bool = function - | Const -> false - | StoreStatic -> false - | _ -> true - let how_captured lvl how seen captured = (* What to do so that we can capture something? * For local blocks, put on the dynamic heap: @@ -5366,22 +5354,6 @@ module AllocHow = struct map_of_set StoreStatic (S.inter (set_of_map (M.filter is_local how)) captured) - let rec is_const_exp exp = match exp.it with - | FuncE _ -> true - | VarE _ -> true - | BlockE (ds, e) -> - List.for_all is_const_dec ds && is_const_exp e - | NewObjE (Type.(Object | Module), _, t) -> - Object.is_immutable t - | PrimE (DotPrim n, [e]) -> - is_const_exp e - | _ -> false - - and is_const_dec dec = match dec.it with - | VarD _ -> false - | LetD ({it = VarP v; _}, e) -> is_const_exp e - | LetD _ -> false - let dec lvl how_outer (seen, how0) dec = let how_all = disjoint_union how_outer how0 in @@ -5394,19 +5366,10 @@ module AllocHow = struct | VarD _ -> map_of_set LocalMut d - (* Constant expressions on the top-level: - - need to be constant forms - - all non-captured free variables must be constant - - all captured variables must be constant or static-heap, if not on top level - (stuff captured on the top level will always be static-heap, via how2 below) - *) - | LetD ({it = VarP _; _}, e) when - is_const_exp e && - disjoint (Freevars.eager_vars f) (set_of_map (M.filter is_not_const how_all)) && - (lvl = VarEnv.TopLvl || disjoint (Freevars.captured_vars f) (set_of_map (M.filter require_closure how_all))) + (* Constant expressions (trusting static_vals.ml) *) + | LetD ({it = VarP _; _}, e) when e.note.Note.const -> map_of_set (Const : how) d - (* Everything else needs at least a local *) | _ -> map_of_set LocalImmut d in @@ -6156,7 +6119,9 @@ let rec compile_lexp (env : E.t) ae lexp = and compile_exp (env : E.t) ae exp = (fun (sr,code) -> (sr, G.with_region exp.at code)) @@ - match exp.it with + if exp.note.Note.const + then let (c, fill) = compile_const_exp env ae exp in fill env ae; (SR.Const c, G.nop) + else match exp.it with | PrimE (p, es) when List.exists (fun e -> Type.is_non e.note.Note.typ) es -> (* Handle dead code separately, so that we can rely on useful type annotations below *) From 229976898aa839dcc012e38136a803515c5ef242 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Wed, 8 Apr 2020 17:21:02 +0200 Subject: [PATCH 1174/1176] test compile_lit for Word8/16 and Nat/Int (#1356) * testcase * record status quo for Nats * add example derivations of the constants * check for comparison code review feedback --- test/run/issue1356.mo | 58 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 test/run/issue1356.mo diff --git a/test/run/issue1356.mo b/test/run/issue1356.mo new file mode 100644 index 00000000000..55119b6a7dd --- /dev/null +++ b/test/run/issue1356.mo @@ -0,0 +1,58 @@ +func matchNat(n : Nat) : Bool = + switch n { case 1073741823 true + ; case _ false }; +// CHECK-LABEL: (func $matchNat +// CHECK: local.get $switch_in +// CHECK-NEXT: i32.const -4 +// CHECK-NEXT: $B_eq + +/* + +Example derivations: + +-1073741824 as binary: 0b11000000000000000000000000000000 +(arithmetic) shift left by 1: 0b10000000000000000000000000000000 +rotate left by 1: 0b00000000000000000000000000000001 +this is 1. + +1073741823 as binary: 0b00111111111111111111111111111111 +(arithmetic) shift left by 1: 0b01111111111111111111111111111110 +rotate left by 1: 0b11111111111111111111111111111100 +this is -4. + +Note: the topmost 2 bits must be equal for the compact form at all times. +In the encoding result lsb is the sign, the bit left to it must be 0. + +*/ + +func matchInt(n : Int) : Bool = + switch n { case (-1073741824) true + ; case 1073741823 true + ; case _ false }; +// CHECK-LABEL: (func $matchInt +// CHECK: local.get $switch_in +// CHECK-NEXT: i32.const 1 +// CHECK-NEXT: $B_eq +// CHECK: local.get $switch_in +// CHECK-NEXT: i32.const -4 +// CHECK-NEXT: $B_eq + +func match8(n : Word8) : Bool = switch n { case 42 true; case _ false }; +// CHECK-LABEL: (func $match8 +// CHECK: i32.const 704643072 +// CHECK-NEXT: i32.eq +// N.B.: 704643072 == 0x2a000000 == 42 << 24 + +func match16(n : Word16) : Bool = switch n { case 42 true; case _ false }; +// CHECK-LABEL: (func $match16 +// CHECK: i32.const 2752512 +// CHECK-NEXT: i32.eq +// N.B.: 2752512 == 0x002a0000 == 42 << 16 + +assert (matchNat(1073741823)); +assert (matchInt(-1073741824)); +assert (matchInt(1073741823)); +assert (match8(42)); +assert (match16(42)); + +// CHECK-LABEL: (func $start From a169a742ede218df2ffe2374720305285e291c73 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Wed, 8 Apr 2020 18:30:47 +0200 Subject: [PATCH 1175/1176] Nixpkgs: Try 20.03 (#1266) * Nixpkgs: Try 20.03 still only beta, but to check problems early. * Bump nixpkgs * Pick same nixpkgs version as `common` see https://github.com/dfinity-lab/common/commit/859285a7214df86a4f8524232f6ac1efe84c6b66 * No need to use nixpkgs-channels TIL that that repo is obsolete, and all its branchs are also in `nixpkgs` * Bump nixpkgs * Update nixpkgs (in sync with common) * bump to get llvm-10 too * bump dune * ocaml 4.08 is default in nixpkgs 20.03, so no need to overlay * Updating to latest commit Co-authored-by: Gabor Greif Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- default.nix | 2 +- nix/default.nix | 2 +- nix/sources.json | 14 ++++++++------ 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/default.nix b/default.nix index 57155323648..5845bc5168a 100644 --- a/default.nix +++ b/default.nix @@ -49,7 +49,7 @@ let staticpkgs = if is_static then nixpkgs.pkgsMusl else nixpkgs; in # nixpkgs.pkgsMusl for static building (release builds) let commonBuildInputs = pkgs: [ - pkgs.dune + pkgs.dune_2 pkgs.ocamlPackages.ocaml pkgs.ocamlPackages.atdgen pkgs.ocamlPackages.checkseum diff --git a/nix/default.nix b/nix/default.nix index 40344472c4e..ca291915bef 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -12,7 +12,7 @@ let overlays = [ (self: super: { sources = import sourcesnix { sourcesFile = ./sources.json; pkgs = super; }; }) # Selecting the ocaml version - (self: super: { ocamlPackages = self.ocaml-ng.ocamlPackages_4_08; }) + # (self: super: { ocamlPackages = super.ocamlPackages; }) # Additional ocaml package ( self: super: { diff --git a/nix/sources.json b/nix/sources.json index 5daee40bc49..5483025768e 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -51,14 +51,16 @@ "url_template": "https://github.com///archive/.tar.gz" }, "nixpkgs": { - "branch": "nixpkgs-unstable", - "homepage": "https://github.com/NixOS/nixpkgs", + "branch": "release-20.03", + "builtin": true, + "description": "Nixpkgs/NixOS branches that track the Nixpkgs/NixOS channels", + "homepage": null, "owner": "NixOS", - "repo": "nixpkgs-channels", - "rev": "ca3531850844e185d483fb878fcd00c6b44069e5", - "sha256": "1s1zhzdbmdd7l936g7ydzsjqdi5k5ch6vpjilil0jiwjhrpkw3m4", + "repo": "nixpkgs", + "rev": "d63f95896ca8c5480629ef59fd46d6c50e3f98d0", + "sha256": "1nq65cczxjcvfy0m4hxyl4hbcxdqsqhdnr58n9h30zbsdv6vl6b4", "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/ca3531850844e185d483fb878fcd00c6b44069e5.tar.gz", + "url": "https://github.com/NixOS/nixpkgs/archive/d63f95896ca8c5480629ef59fd46d6c50e3f98d0.tar.gz", "url_template": "https://github.com///archive/.tar.gz" }, "ocaml-vlq": { From a6cb9c3e9841d582a6950e9dc697af678268c1f0 Mon Sep 17 00:00:00 2001 From: DFINITY bot <58022693+dfinity-bot@users.noreply.github.com> Date: Thu, 9 Apr 2020 02:05:51 +0200 Subject: [PATCH 1176/1176] niv common: update 22f5d566 -> 96395685 (#1362) ## Changelog for common: Commits: [dfinity-lab/common@22f5d566...96395685](https://github.com/dfinity-lab/common/compare/22f5d56616a5e75c6b7dec2d7f7f130737f72644...96395685d062093ba0848bc94f8ba2cb3202cda3) * [`eaa68abf`](https://github.com/dfinity-lab/common/commit/eaa68abf1bdd8970624abd54a50baeffe2e78805) build-dfinity-rust-package.nix: set RUST_SRC_PATH on the shell drv --- nix/sources.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/sources.json b/nix/sources.json index 5483025768e..e8d38659c22 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -2,7 +2,7 @@ "common": { "ref": "master", "repo": "ssh://git@github.com/dfinity-lab/common", - "rev": "22f5d56616a5e75c6b7dec2d7f7f130737f72644", + "rev": "96395685d062093ba0848bc94f8ba2cb3202cda3", "type": "git" }, "dfinity": {